From 2207a38326f515e398c3b615f535da53b7498e7d Mon Sep 17 00:00:00 2001 From: Anirudh Warrier <12178754+anirudhwarrier@users.noreply.github.com> Date: Fri, 19 Jul 2024 21:16:05 +0530 Subject: [PATCH 001/115] [AUTO-11176] fix automation chaos test (#13904) * fix automation chaos test * fix ondemand workflow for chaos tests * use standard automation test functions * update automation testconfig * lint * lint --- .../workflows/automation-ondemand-tests.yml | 2 +- .../chaos/automation_chaos_test.go | 144 ++++++++++-------- .../testconfig/automation/automation.toml | 51 +++++++ 3 files changed, 132 insertions(+), 65 deletions(-) diff --git a/.github/workflows/automation-ondemand-tests.yml b/.github/workflows/automation-ondemand-tests.yml index 324d5b04b9..7514743fa8 100644 --- a/.github/workflows/automation-ondemand-tests.yml +++ b/.github/workflows/automation-ondemand-tests.yml @@ -146,7 +146,7 @@ jobs: - name: chaos id: chaos suite: chaos - nodes: 15 + nodes: 20 os: ubuntu-latest enabled: ${{ inputs.enableChaos }} pyroscope_env: ci-automation-on-demand-chaos diff --git a/integration-tests/chaos/automation_chaos_test.go b/integration-tests/chaos/automation_chaos_test.go index 79513b2e8f..467f371ad1 100644 --- a/integration-tests/chaos/automation_chaos_test.go +++ b/integration-tests/chaos/automation_chaos_test.go @@ -6,6 +6,11 @@ import ( "testing" "time" + ocr3 "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3confighelper" + + ocr2keepers30config "github.com/smartcontractkit/chainlink-automation/pkg/v3/config" + "github.com/smartcontractkit/chainlink/integration-tests/actions/automationv2" + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" "github.com/onsi/gomega" @@ -77,22 +82,6 @@ ListenAddresses = ["0.0.0.0:6690"]` }, }, } - - defaultOCRRegistryConfig = contracts.KeeperRegistrySettings{ - PaymentPremiumPPB: uint32(200000000), - FlatFeeMicroLINK: uint32(0), - BlockCountPerTurn: big.NewInt(10), - CheckGasLimit: uint32(2500000), - StalenessSeconds: big.NewInt(90000), - GasCeilingMultiplier: uint16(1), - MinUpkeepSpend: big.NewInt(0), - MaxPerformGas: uint32(5000000), - FallbackGasPrice: big.NewInt(2e11), - FallbackLinkPrice: big.NewInt(2e18), - MaxCheckDataSize: uint32(5000), - MaxPerformDataSize: uint32(5000), - MaxRevertDataSize: uint32(5000), - } ) func getDefaultAutomationSettings(config *tc.TestConfig) map[string]interface{} { @@ -127,6 +116,7 @@ func TestAutomationChaos(t *testing.T) { "registry_2_0": eth_contracts.RegistryVersion_2_0, "registry_2_1": eth_contracts.RegistryVersion_2_1, "registry_2_2": eth_contracts.RegistryVersion_2_2, + "registry_2_3": eth_contracts.RegistryVersion_2_3, } for name, registryVersion := range registryVersions { @@ -253,57 +243,76 @@ func TestAutomationChaos(t *testing.T) { require.NoError(t, err, "Error tearing down environment") }) - txCost, err := actions.EstimateCostForChainlinkOperations(l, chainClient, network, 1000) - require.NoError(t, err, "Error estimating cost for Chainlink Operations") - err = actions.FundChainlinkNodesFromRootAddress(l, chainClient, contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(chainlinkNodes), txCost) - require.NoError(t, err, "Error funding Chainlink nodes") - - linkToken, err := contracts.DeployLinkTokenContract(l, chainClient) - require.NoError(t, err, "Error deploying LINK token") - - wethToken, err := contracts.DeployWETHTokenContract(l, chainClient) - require.NoError(t, err, "Error deploying weth token contract") - - // This feed is used for both eth/usd and link/usd - ethUSDFeed, err := contracts.DeployMockETHUSDFeed(chainClient, defaultOCRRegistryConfig.FallbackLinkPrice) - require.NoError(t, err, "Error deploying eth usd feed contract") - - registry, registrar := actions.DeployAutoOCRRegistryAndRegistrar( - t, - chainClient, - rv, - defaultOCRRegistryConfig, - linkToken, - wethToken, - ethUSDFeed, - ) - - // Fund the registry with LINK - err = linkToken.Transfer(registry.Address(), big.NewInt(0).Mul(big.NewInt(1e18), big.NewInt(int64(numberOfUpkeeps)))) - require.NoError(t, err, "Funding keeper registry contract shouldn't fail") - - actions.CreateOCRKeeperJobs(t, chainlinkNodes, registry.Address(), network.ChainID, 0, rv) - nodesWithoutBootstrap := chainlinkNodes[1:] - defaultOCRRegistryConfig.RegistryVersion = rv - ocrConfig, err := actions.BuildAutoOCR2ConfigVars(t, nodesWithoutBootstrap, defaultOCRRegistryConfig, registrar.Address(), 30*time.Second, registry.ChainModuleAddress(), registry.ReorgProtectionEnabled(), linkToken, wethToken, ethUSDFeed) - require.NoError(t, err, "Error building OCR config vars") - - if rv == eth_contracts.RegistryVersion_2_0 { - err = registry.SetConfig(defaultOCRRegistryConfig, ocrConfig) - } else { - err = registry.SetConfigTypeSafe(ocrConfig) + a := automationv2.NewAutomationTestK8s(l, chainClient, chainlinkNodes) + a.SetMercuryCredentialName("cred1") + conf := config.Automation.AutomationConfig + a.RegistrySettings = contracts.KeeperRegistrySettings{ + PaymentPremiumPPB: *conf.RegistrySettings.PaymentPremiumPPB, + FlatFeeMicroLINK: *conf.RegistrySettings.FlatFeeMicroLINK, + CheckGasLimit: *conf.RegistrySettings.CheckGasLimit, + StalenessSeconds: conf.RegistrySettings.StalenessSeconds, + GasCeilingMultiplier: *conf.RegistrySettings.GasCeilingMultiplier, + MaxPerformGas: *conf.RegistrySettings.MaxPerformGas, + MinUpkeepSpend: conf.RegistrySettings.MinUpkeepSpend, + FallbackGasPrice: conf.RegistrySettings.FallbackGasPrice, + FallbackLinkPrice: conf.RegistrySettings.FallbackLinkPrice, + MaxCheckDataSize: *conf.RegistrySettings.MaxCheckDataSize, + MaxPerformDataSize: *conf.RegistrySettings.MaxPerformDataSize, + MaxRevertDataSize: *conf.RegistrySettings.MaxRevertDataSize, + RegistryVersion: rv, + } + a.RegistrarSettings = contracts.KeeperRegistrarSettings{ + AutoApproveConfigType: uint8(2), + AutoApproveMaxAllowed: 1000, + MinLinkJuels: big.NewInt(0), + } + plCfg := config.GetAutomationConfig().AutomationConfig.PluginConfig + a.PluginConfig = ocr2keepers30config.OffchainConfig{ + TargetProbability: *plCfg.TargetProbability, + TargetInRounds: *plCfg.TargetInRounds, + PerformLockoutWindow: *plCfg.PerformLockoutWindow, + GasLimitPerReport: *plCfg.GasLimitPerReport, + GasOverheadPerUpkeep: *plCfg.GasOverheadPerUpkeep, + MinConfirmations: *plCfg.MinConfirmations, + MaxUpkeepBatchSize: *plCfg.MaxUpkeepBatchSize, + } + pubCfg := config.GetAutomationConfig().AutomationConfig.PublicConfig + a.PublicConfig = ocr3.PublicConfig{ + DeltaProgress: *pubCfg.DeltaProgress, + DeltaResend: *pubCfg.DeltaResend, + DeltaInitial: *pubCfg.DeltaInitial, + DeltaRound: *pubCfg.DeltaRound, + DeltaGrace: *pubCfg.DeltaGrace, + DeltaCertifiedCommitRequest: *pubCfg.DeltaCertifiedCommitRequest, + DeltaStage: *pubCfg.DeltaStage, + RMax: *pubCfg.RMax, + MaxDurationQuery: *pubCfg.MaxDurationQuery, + MaxDurationObservation: *pubCfg.MaxDurationObservation, + MaxDurationShouldAcceptAttestedReport: *pubCfg.MaxDurationShouldAcceptAttestedReport, + MaxDurationShouldTransmitAcceptedReport: *pubCfg.MaxDurationShouldTransmitAcceptedReport, + F: *pubCfg.F, } - require.NoError(t, err, "Error setting OCR config") - consumersConditional, upkeepidsConditional := actions.DeployConsumers(t, chainClient, registry, registrar, linkToken, numberOfUpkeeps, big.NewInt(defaultLinkFunds), defaultUpkeepGasLimit, false, false, false, nil) - consumersLogtrigger, upkeepidsLogtrigger := actions.DeployConsumers(t, chainClient, registry, registrar, linkToken, numberOfUpkeeps, big.NewInt(defaultLinkFunds), defaultUpkeepGasLimit, true, false, false, nil) + a.SetupAutomationDeployment(t) - consumers := append(consumersConditional, consumersLogtrigger...) - upkeepIDs := append(upkeepidsConditional, upkeepidsLogtrigger...) + err = actions.FundChainlinkNodesFromRootAddress(l, a.ChainClient, contracts.ChainlinkK8sClientToChainlinkNodeWithKeysAndAddress(chainlinkNodes[1:]), big.NewFloat(*config.Common.ChainlinkNodeFunding)) + require.NoError(t, err, "Error funding Chainlink nodes") + + var consumersLogTrigger, consumersConditional []contracts.KeeperConsumer + var upkeepidsConditional, upkeepidsLogTrigger []*big.Int + consumersConditional, upkeepidsConditional = actions.DeployConsumers(t, a.ChainClient, a.Registry, a.Registrar, a.LinkToken, numberOfUpkeeps, big.NewInt(defaultLinkFunds), defaultUpkeepGasLimit, false, false, false, nil) + consumers := consumersConditional + upkeepIDs := upkeepidsConditional + if rv >= eth_contracts.RegistryVersion_2_1 { + consumersLogTrigger, upkeepidsLogTrigger = actions.DeployConsumers(t, a.ChainClient, a.Registry, a.Registrar, a.LinkToken, numberOfUpkeeps, big.NewInt(defaultLinkFunds), defaultUpkeepGasLimit, true, false, false, nil) - for _, c := range consumersLogtrigger { - err = c.Start() - require.NoError(t, err, "Error starting consumer") + consumers = append(consumersConditional, consumersLogTrigger...) + upkeepIDs = append(upkeepidsConditional, upkeepidsLogTrigger...) + + for _, c := range consumersLogTrigger { + err = c.Start() + require.NoError(t, err, "Error starting consumer") + } } l.Info().Msg("Waiting for all upkeeps to be performed") @@ -324,6 +333,13 @@ func TestAutomationChaos(t *testing.T) { _, err = testEnvironment.Chaos.Run(testCase.chaosFunc(testEnvironment.Cfg.Namespace, testCase.chaosProps)) require.NoError(t, err) + if rv >= eth_contracts.RegistryVersion_2_1 { + for _, c := range consumersLogTrigger { + err = c.Start() + require.NoError(t, err, "Error starting consumer") + } + } + gom.Eventually(func(g gomega.Gomega) { // Check if the upkeeps are performing multiple times by analyzing their counters and checking they are greater than 10 for i := 0; i < len(upkeepIDs); i++ { @@ -334,7 +350,7 @@ func TestAutomationChaos(t *testing.T) { g.Expect(counter.Int64()).Should(gomega.BeNumerically(">=", int64(expect)), "Expected consumer counter to be greater than %d, but got %d", expect, counter.Int64()) } - }, "3m", "1s").Should(gomega.Succeed()) // ~1m for cluster setup, ~2m for performing each upkeep 5 times, ~2m buffer + }, "5m", "1s").Should(gomega.Succeed()) // ~1m for cluster setup, ~2m for performing each upkeep 5 times, ~2m buffer }) } diff --git a/integration-tests/testconfig/automation/automation.toml b/integration-tests/testconfig/automation/automation.toml index 7e10af62cf..26b9f05597 100644 --- a/integration-tests/testconfig/automation/automation.toml +++ b/integration-tests/testconfig/automation/automation.toml @@ -152,6 +152,57 @@ max_check_data_size=5_000 max_perform_data_size=5_000 max_revert_data_size=5_000 +# chaos test specific overrides +[Chaos.Common] +chainlink_node_funding = 2.0 + +[Chaos.Automation] + +[Chaos.Automation.AutomationConfig] +use_log_buffer_v1=false + +[Chaos.Automation.AutomationConfig.PublicConfig] +delta_progress=10_000_000_000 +delta_resend=15_000_000_000 +delta_initial=500_000_000 +delta_round=1_000_000_000 +delta_grace=200_000_000 +delta_certified_commit_request=300_000_000 +delta_stage=30_000_000_000 +r_max=24 +f=1 +max_duration_query=20_000_000 +max_duration_observation=20_000_000 +max_duration_should_accept_attested_report=1_200_000_000 +max_duration_should_transmit_accepted_report=20_000_000 + +[Chaos.Automation.AutomationConfig.PluginConfig] +perform_lockout_window=3_600_000 +target_probability="0.999" +target_in_rounds=1 +min_confirmations=0 +gas_limit_per_report=10_300_000 +gas_overhead_per_upkeep=300_000 +max_upkeep_batch_size=10 + +[Chaos.Automation.AutomationConfig.PluginConfig.LogProviderConfig] +block_rate=1 +log_limit=2 + +[Chaos.Automation.AutomationConfig.RegistrySettings] +payment_premium_ppb=200_000_000 +flat_fee_micro_link=0 +check_gas_limit=2_500_000 +staleness_seconds=90000 +gas_ceiling_multiplier=1 +max_perform_gas=5_000_000 +min_upkeep_spend=0 +fallback_gas_price=200_000_000_000 +fallback_link_price=2_000_000_000_000_000_000 +max_check_data_size=5_000 +max_perform_data_size=5_000 +max_revert_data_size=5_000 + # load test specific overrides [Load.Seth] ephemeral_addresses_number = 100 From 5b668c186ac8ba294a97b20484352221f258bae2 Mon Sep 17 00:00:00 2001 From: ferglor Date: Fri, 19 Jul 2024 17:34:39 +0100 Subject: [PATCH 002/115] Remove the old log buffer (#13821) * Remove the old log buffer * Add a changeset * Update integration test * Lint * Clean up from config * Update tests * Integration test lint * Clean up sync filters --- .changeset/unlucky-lemons-learn.md | 5 + core/services/job/helpers_test.go | 3 +- core/services/ocr2/delegate.go | 9 - .../ocr2/plugins/ocr2keeper/config.go | 3 - .../evmregistry/v21/logprovider/buffer.go | 388 -------- .../v21/logprovider/buffer_test.go | 892 ------------------ .../evmregistry/v21/logprovider/factory.go | 11 - .../v21/logprovider/integration_test.go | 288 +++--- .../evmregistry/v21/logprovider/provider.go | 72 +- .../v21/logprovider/provider_test.go | 45 +- .../plugins/ocr2keeper/integration_21_test.go | 550 +++++------ .../actions/automationv2/actions.go | 12 +- .../automationv2_1/automationv2_1_test.go | 4 - .../testconfig/automation/config.go | 9 +- 14 files changed, 395 insertions(+), 1896 deletions(-) create mode 100644 .changeset/unlucky-lemons-learn.md delete mode 100644 core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/buffer.go delete mode 100644 core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/buffer_test.go diff --git a/.changeset/unlucky-lemons-learn.md b/.changeset/unlucky-lemons-learn.md new file mode 100644 index 0000000000..3e33963995 --- /dev/null +++ b/.changeset/unlucky-lemons-learn.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +Use the new log buffer in automation #changed diff --git a/core/services/job/helpers_test.go b/core/services/job/helpers_test.go index d69056ae81..6f9bee66a0 100644 --- a/core/services/job/helpers_test.go +++ b/core/services/job/helpers_test.go @@ -71,7 +71,6 @@ maxServiceWorkers = 100 cacheEvictionInterval = "1s" mercuryCredentialName = "%s" contractVersion = "v2.1" -useBufferV1 = %v ` voterTurnoutDataSourceTemplate = ` // data source 1 @@ -277,7 +276,7 @@ func makeOCR2Keeper21JobSpec(t testing.TB, ks keystore.Master, transmitter commo _, registry := cltest.MustInsertRandomKey(t, ks.Eth()) ocr2Keeper21Job := fmt.Sprintf(ocr2Keeper21JobSpecTemplate, registry.String(), kb.ID(), transmitter, - fmt.Sprintf("%s127.0.0.1:%d", bootstrapPeerID, bootstrapNodePort), chainID, "mercury cred", false) + fmt.Sprintf("%s127.0.0.1:%d", bootstrapPeerID, bootstrapNodePort), chainID, "mercury cred") jobSpec := makeOCR2JobSpecFromToml(t, ocr2Keeper21Job) diff --git a/core/services/ocr2/delegate.go b/core/services/ocr2/delegate.go index a6843401aa..db0f4e9725 100644 --- a/core/services/ocr2/delegate.go +++ b/core/services/ocr2/delegate.go @@ -55,7 +55,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/autotelemetry21" ocr2keeper21core "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/core" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/validate" "github.com/smartcontractkit/chainlink/v2/core/services/ocrcommon" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" @@ -1123,14 +1122,6 @@ func (d *Delegate) newServicesOCR2Keepers21( return nil, errors.New("could not coerce PluginProvider to AutomationProvider") } - // TODO: (AUTO-9355) remove once we remove v0 - if useBufferV1 := cfg.UseBufferV1 != nil && *cfg.UseBufferV1; useBufferV1 { - logProviderFeatures, ok := keeperProvider.LogEventProvider().(logprovider.LogEventProviderFeatures) - if ok { - logProviderFeatures.WithBufferVersion("v1") - } - } - services, err := ocr2keeper.EVMDependencies21(kb) if err != nil { return nil, errors.Wrap(err, "could not build dependencies for ocr2 keepers") diff --git a/core/services/ocr2/plugins/ocr2keeper/config.go b/core/services/ocr2/plugins/ocr2keeper/config.go index 4b41e5a028..ec56f9c699 100644 --- a/core/services/ocr2/plugins/ocr2keeper/config.go +++ b/core/services/ocr2/plugins/ocr2keeper/config.go @@ -60,9 +60,6 @@ type PluginConfig struct { ContractVersion string `json:"contractVersion"` // CaptureAutomationCustomTelemetry is a bool flag to toggle Custom Telemetry Service CaptureAutomationCustomTelemetry *bool `json:"captureAutomationCustomTelemetry,omitempty"` - // UseBufferV1 is a bool flag to toggle the new log buffer implementation - // TODO: (AUTO-9355) remove once we have a single version - UseBufferV1 *bool `json:"useBufferV1,omitempty"` } func ValidatePluginConfig(cfg PluginConfig) error { diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/buffer.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/buffer.go deleted file mode 100644 index af934a0801..0000000000 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/buffer.go +++ /dev/null @@ -1,388 +0,0 @@ -package logprovider - -import ( - "encoding/hex" - "math/big" - "sort" - "sync" - "sync/atomic" - - "github.com/smartcontractkit/chainlink-automation/pkg/v3/random" - ocr2keepers "github.com/smartcontractkit/chainlink-common/pkg/types/automation" - - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" - "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/prommetrics" -) - -var ( - // defaultFastExecLogsHigh is the default upper bound / maximum number of logs that Automation is committed to process for each upkeep, - // based on available capacity, i.e. if there are no logs from other upkeeps. - // Used by Log buffer to limit the number of logs we are saving in memory for each upkeep in a block - defaultFastExecLogsHigh = 32 - // defaultNumOfLogUpkeeps is the default number of log upkeeps supported by the registry. - defaultNumOfLogUpkeeps = 50 -) - -// fetchedLog holds the log and the ID of the upkeep -type fetchedLog struct { - upkeepID *big.Int - log logpoller.Log - // cachedLogID is the cached log identifier, used for sorting. - // It is calculated lazily, and cached for performance. - cachedLogID string -} - -func (l *fetchedLog) getLogID() string { - if len(l.cachedLogID) == 0 { - ext := ocr2keepers.LogTriggerExtension{ - Index: uint32(l.log.LogIndex), - } - copy(ext.TxHash[:], l.log.TxHash[:]) - copy(ext.BlockHash[:], l.log.BlockHash[:]) - l.cachedLogID = hex.EncodeToString(ext.LogIdentifier()) - } - return l.cachedLogID -} - -// fetchedBlock holds the logs fetched for a block -type fetchedBlock struct { - blockNumber int64 - // logs is the logs fetched for the block and haven't been visited yet - logs []fetchedLog - // visited is the logs fetched for the block and have been visited. - // We keep them in order to avoid fetching them again. - visited []fetchedLog -} - -func (b *fetchedBlock) Append(lggr logger.Logger, fl fetchedLog, maxBlockLogs, maxUpkeepLogs int) (fetchedLog, bool) { - has, upkeepLogs := b.has(fl.upkeepID, fl.log) - if has { - // Skipping known logs - return fetchedLog{}, false - } - // lggr.Debugw("Adding log", "i", i, "blockBlock", currentBlock.blockNumber, "logBlock", log.BlockNumber, "id", id) - b.logs = append(b.logs, fl) - - // drop logs if we reached limits. - if upkeepLogs+1 > maxUpkeepLogs { - // in case we have logs overflow for a particular upkeep, we drop a log of that upkeep, - // based on shared, random (per block) order of the logs in the block. - b.Sort() - var dropped fetchedLog - currentLogs := make([]fetchedLog, 0, len(b.logs)-1) - for _, l := range b.logs { - if dropped.upkeepID == nil && l.upkeepID.Cmp(fl.upkeepID) == 0 { - dropped = l - continue - } - currentLogs = append(currentLogs, l) - } - b.logs = currentLogs - return dropped, true - } else if len(b.logs)+len(b.visited) > maxBlockLogs { - // in case we have logs overflow in the buffer level, we drop a log based on - // shared, random (per block) order of the logs in the block. - b.Sort() - dropped := b.logs[0] - b.logs = b.logs[1:] - return dropped, true - } - - return fetchedLog{}, true -} - -// Has returns true if the block has the log, -// and the number of logs for that upkeep in the block. -func (b fetchedBlock) has(id *big.Int, log logpoller.Log) (bool, int) { - allLogs := append(b.logs, b.visited...) - upkeepLogs := 0 - for _, l := range allLogs { - if l.upkeepID.Cmp(id) != 0 { - continue - } - upkeepLogs++ - if l.log.BlockHash == log.BlockHash && l.log.TxHash == log.TxHash && l.log.LogIndex == log.LogIndex { - return true, upkeepLogs - } - } - return false, upkeepLogs -} - -func (b fetchedBlock) Clone() fetchedBlock { - logs := make([]fetchedLog, len(b.logs)) - copy(logs, b.logs) - visited := make([]fetchedLog, len(b.visited)) - copy(visited, b.visited) - return fetchedBlock{ - blockNumber: b.blockNumber, - logs: logs, - visited: visited, - } -} - -// Sort by log identifiers, shuffled using a pseduorandom souce that is shared across all nodes -// for a given block. -func (b *fetchedBlock) Sort() { - randSeed := random.GetRandomKeySource(nil, uint64(b.blockNumber)) - - shuffledLogIDs := make(map[string]string, len(b.logs)) - for _, log := range b.logs { - logID := log.getLogID() - shuffledLogIDs[logID] = random.ShuffleString(logID, randSeed) - } - - sort.SliceStable(b.logs, func(i, j int) bool { - return shuffledLogIDs[b.logs[i].getLogID()] < shuffledLogIDs[b.logs[j].getLogID()] - }) -} - -// logEventBuffer is a circular/ring buffer of fetched logs. -// Each entry in the buffer represents a block, -// and holds the logs fetched for that block. -type logEventBuffer struct { - lggr logger.Logger - lock sync.RWMutex - // size is the number of blocks supported by the buffer - size int32 - - numOfLogUpkeeps, fastExecLogsHigh uint32 - // blocks is the circular buffer of fetched blocks - blocks []fetchedBlock - // latestBlock is the latest block number seen - latestBlock int64 -} - -func newLogEventBuffer(lggr logger.Logger, size, numOfLogUpkeeps, fastExecLogsHigh int) *logEventBuffer { - return &logEventBuffer{ - lggr: lggr.Named("KeepersRegistry.LogEventBuffer"), - size: int32(size), - blocks: make([]fetchedBlock, size), - numOfLogUpkeeps: uint32(numOfLogUpkeeps), - fastExecLogsHigh: uint32(fastExecLogsHigh), - } -} - -func (b *logEventBuffer) latestBlockSeen() int64 { - return atomic.LoadInt64(&b.latestBlock) -} - -func (b *logEventBuffer) bufferSize() int { - return int(atomic.LoadInt32(&b.size)) -} - -func (b *logEventBuffer) SetLimits(numOfLogUpkeeps, fastExecLogsHigh int) { - atomic.StoreUint32(&b.numOfLogUpkeeps, uint32(numOfLogUpkeeps)) - atomic.StoreUint32(&b.fastExecLogsHigh, uint32(fastExecLogsHigh)) -} - -// enqueue adds logs (if not exist) to the buffer, returning the number of logs added -// minus the number of logs dropped. -func (b *logEventBuffer) enqueue(id *big.Int, logs ...logpoller.Log) int { - b.lock.Lock() - defer b.lock.Unlock() - - lggr := b.lggr.With("id", id.String()) - - maxBlockLogs := int(atomic.LoadUint32(&b.fastExecLogsHigh) * atomic.LoadUint32(&b.numOfLogUpkeeps)) - maxUpkeepLogs := int(atomic.LoadUint32(&b.fastExecLogsHigh)) - - latestBlock := b.latestBlockSeen() - added, dropped := 0, 0 - - for _, log := range logs { - if log.BlockNumber == 0 { - // invalid log - continue - } - i := b.blockNumberIndex(log.BlockNumber) - currentBlock := b.blocks[i] - if currentBlock.blockNumber < log.BlockNumber { - lggr.Debugw("Got log on a new block", "prevBlock", currentBlock.blockNumber, "newBlock", log.BlockNumber) - currentBlock.blockNumber = log.BlockNumber - currentBlock.logs = nil - currentBlock.visited = nil - } else if currentBlock.blockNumber > log.BlockNumber { - // not expected to happen - lggr.Debugw("Skipping log from old block", "currentBlock", currentBlock.blockNumber, "newBlock", log.BlockNumber) - continue - } - droppedLog, ok := currentBlock.Append(lggr, fetchedLog{upkeepID: id, log: log}, maxBlockLogs, maxUpkeepLogs) - if !ok { - // Skipping known logs - continue - } - if droppedLog.upkeepID != nil { - dropped++ - lggr.Debugw("Reached log buffer limits, dropping log", "blockNumber", droppedLog.log.BlockNumber, - "blockHash", droppedLog.log.BlockHash, "txHash", droppedLog.log.TxHash, "logIndex", droppedLog.log.LogIndex, - "upkeepID", droppedLog.upkeepID.String()) - } - added++ - b.blocks[i] = currentBlock - - if log.BlockNumber > latestBlock { - latestBlock = log.BlockNumber - } - } - - if latestBlock > b.latestBlockSeen() { - atomic.StoreInt64(&b.latestBlock, latestBlock) - } - if added > 0 { - lggr.Debugw("Added logs to buffer", "addedLogs", added, "dropped", dropped, "latestBlock", latestBlock) - prommetrics.AutomationLogBufferFlow.WithLabelValues(prommetrics.LogBufferFlowDirectionIngress).Add(float64(added)) - prommetrics.AutomationLogBufferFlow.WithLabelValues(prommetrics.LogBufferFlowDirectionDropped).Add(float64(dropped)) - } - - return added - dropped -} - -// peek returns the logs in range [latestBlock-blocks, latestBlock] -func (b *logEventBuffer) peek(blocks int) []fetchedLog { - latestBlock := b.latestBlockSeen() - if latestBlock == 0 { - return nil - } - if blocks > int(latestBlock) { - blocks = int(latestBlock) - 1 - } - - return b.peekRange(latestBlock-int64(blocks), latestBlock) -} - -// peekRange returns the logs between start and end inclusive. -func (b *logEventBuffer) peekRange(start, end int64) []fetchedLog { - b.lock.RLock() - defer b.lock.RUnlock() - - blocksInRange := b.getBlocksInRange(int(start), int(end)) - - var results []fetchedLog - for _, block := range blocksInRange { - // double checking that we don't have any gaps in the range - if block.blockNumber < start || block.blockNumber > end { - continue - } - results = append(results, block.logs...) - } - - sort.SliceStable(results, func(i, j int) bool { - return results[i].log.BlockNumber < results[j].log.BlockNumber - }) - - b.lggr.Debugw("Peeked logs", "results", len(results), "start", start, "end", end) - - return results -} - -// dequeueRange returns the logs between start and end inclusive. -func (b *logEventBuffer) dequeueRange(start, end int64, upkeepLimit, totalLimit int) []fetchedLog { - b.lock.Lock() - defer b.lock.Unlock() - - blocksInRange := b.getBlocksInRange(int(start), int(end)) - fetchedBlocks := make([]fetchedBlock, 0, len(blocksInRange)) - for _, block := range blocksInRange { - // Create clone of the blocks as they get processed and update underlying b.blocks - fetchedBlocks = append(fetchedBlocks, block.Clone()) - } - - // Sort the blocks in reverse order of block number so that latest logs - // are preferred while dequeueing. - sort.SliceStable(fetchedBlocks, func(i, j int) bool { - return fetchedBlocks[i].blockNumber > fetchedBlocks[j].blockNumber - }) - - logsCount := map[string]int{} - totalCount := 0 - var results []fetchedLog - for _, block := range fetchedBlocks { - if block.blockNumber < start || block.blockNumber > end { - // double checking that we don't have any gaps in the range - continue - } - if totalCount >= totalLimit { - // reached total limit, no need to process more blocks - break - } - // Sort the logs in random order that is shared across all nodes. - // This ensures that nodes across the network will process the same logs. - block.Sort() - var remainingLogs, blockResults []fetchedLog - for _, log := range block.logs { - if totalCount >= totalLimit { - remainingLogs = append(remainingLogs, log) - continue - } - if logsCount[log.upkeepID.String()] >= upkeepLimit { - remainingLogs = append(remainingLogs, log) - continue - } - blockResults = append(blockResults, log) - logsCount[log.upkeepID.String()]++ - totalCount++ - } - if len(blockResults) == 0 { - continue - } - results = append(results, blockResults...) - block.visited = append(block.visited, blockResults...) - block.logs = remainingLogs - b.blocks[b.blockNumberIndex(block.blockNumber)] = block - } - - if len(results) > 0 { - b.lggr.Debugw("Dequeued logs", "results", len(results), "start", start, "end", end) - prommetrics.AutomationLogBufferFlow.WithLabelValues(prommetrics.LogBufferFlowDirectionEgress).Add(float64(len(results))) - } - - return results -} - -// getBlocksInRange returns the blocks between start and end. -// NOTE: this function should be called with the lock held -func (b *logEventBuffer) getBlocksInRange(start, end int) []fetchedBlock { - var blocksInRange []fetchedBlock - start, end = b.blockRangeToIndices(start, end) - if start == -1 || end == -1 { - // invalid range - return blocksInRange - } - if start <= end { - // Normal range, need to return indices from start to end(inclusive) - return b.blocks[start : end+1] - } - // in case we get circular range such as [0, 1, end, ... , start, ..., size-1] - // we need to return the blocks in two ranges: [0, end](inclusive) and [start, size-1] - blocksInRange = append(blocksInRange, b.blocks[start:]...) - blocksInRange = append(blocksInRange, b.blocks[:end+1]...) - - return blocksInRange -} - -// blockRangeToIndices returns the normalized range of start to end block range, -// to indices aligned with buffer size. Note ranges inclusive of start, end indices. -func (b *logEventBuffer) blockRangeToIndices(start, end int) (int, int) { - latest := b.latestBlockSeen() - if end > int(latest) { - // Limit end of range to latest block seen - end = int(latest) - } - if end < start || start == 0 || end == 0 { - // invalid range - return -1, -1 - } - size := b.bufferSize() - if end-start >= size { - // If range requires more than buffer size blocks, only to return - // last size blocks as that's the max the buffer stores. - start = (end - size) + 1 - } - return b.blockNumberIndex(int64(start)), b.blockNumberIndex(int64(end)) -} - -// blockNumberIndex returns the index of the block in the buffer -func (b *logEventBuffer) blockNumberIndex(bn int64) int { - return int(bn-1) % b.bufferSize() -} diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/buffer_test.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/buffer_test.go deleted file mode 100644 index dca43ca14a..0000000000 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/buffer_test.go +++ /dev/null @@ -1,892 +0,0 @@ -package logprovider - -import ( - "encoding/hex" - "fmt" - "math/big" - "testing" - - "github.com/smartcontractkit/chainlink-automation/pkg/v3/types" - - "github.com/ethereum/go-ethereum/common" - "github.com/stretchr/testify/require" - - ocr2keepers "github.com/smartcontractkit/chainlink-common/pkg/types/automation" - - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" - "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/core" -) - -func TestLogEventBuffer_GetBlocksInRange(t *testing.T) { - size := 3 - maxSeenBlock := int64(4) - buf := newLogEventBuffer(logger.TestLogger(t), size, 10, 10) - - buf.enqueue(big.NewInt(1), - logpoller.Log{BlockNumber: 2, TxHash: common.HexToHash("0x2"), LogIndex: 0}, - logpoller.Log{BlockNumber: 3, TxHash: common.HexToHash("0x3"), LogIndex: 0}, - ) - - buf.enqueue(big.NewInt(2), - logpoller.Log{BlockNumber: 2, TxHash: common.HexToHash("0x2"), LogIndex: 2}, - logpoller.Log{BlockNumber: 3, TxHash: common.HexToHash("0x3"), LogIndex: 2}, - logpoller.Log{BlockNumber: 4, TxHash: common.HexToHash("0x1"), LogIndex: 0}, - logpoller.Log{BlockNumber: 4, TxHash: common.HexToHash("0x1"), LogIndex: 1}, - ) - - tests := []struct { - name string - from int64 - to int64 - want int - }{ - { - name: "all", - from: 2, - to: 4, - want: 3, - }, - { - name: "partial", - from: 2, - to: 3, - want: 2, - }, - { - name: "circular", - from: 3, - to: 4, - want: 2, - }, - { - name: "zero start", - from: 0, - to: 2, - }, - { - name: "invalid zero end", - from: 0, - to: 0, - }, - { - name: "invalid from larger than to", - from: 4, - to: 2, - }, - { - name: "outside max last seen", - from: 5, - to: 10, - }, - { - name: "limited by max last seen", - from: 2, - to: 5, - want: 3, - }, - } - - for _, tc := range tests { - t.Run(tc.name, func(t *testing.T) { - blocks := buf.getBlocksInRange(int(tc.from), int(tc.to)) - require.Equal(t, tc.want, len(blocks)) - if tc.want > 0 { - from := tc.from - require.Equal(t, from, blocks[0].blockNumber) - to := tc.to - if to >= maxSeenBlock { - to = maxSeenBlock - } - require.Equal(t, to, blocks[len(blocks)-1].blockNumber) - } - }) - } -} - -func TestLogEventBuffer_GetBlocksInRange_Circular(t *testing.T) { - size := 4 - buf := newLogEventBuffer(logger.TestLogger(t), size, 10, 10) - - require.Equal(t, buf.enqueue(big.NewInt(1), - logpoller.Log{BlockNumber: 1, TxHash: common.HexToHash("0x1"), LogIndex: 0}, - logpoller.Log{BlockNumber: 2, TxHash: common.HexToHash("0x2"), LogIndex: 0}, - logpoller.Log{BlockNumber: 3, TxHash: common.HexToHash("0x3"), LogIndex: 0}, - ), 3) - - require.Equal(t, buf.enqueue(big.NewInt(2), - logpoller.Log{BlockNumber: 2, TxHash: common.HexToHash("0x2"), LogIndex: 2}, - logpoller.Log{BlockNumber: 3, TxHash: common.HexToHash("0x3"), LogIndex: 2}, - logpoller.Log{BlockNumber: 4, TxHash: common.HexToHash("0x1"), LogIndex: 1}, - ), 3) - - require.Equal(t, buf.enqueue(big.NewInt(3), - logpoller.Log{BlockNumber: 4, TxHash: common.HexToHash("0x1"), LogIndex: 4}, - logpoller.Log{BlockNumber: 5, TxHash: common.HexToHash("0x3"), LogIndex: 2}, - logpoller.Log{BlockNumber: 5, TxHash: common.HexToHash("0x3"), LogIndex: 5}, - ), 3) - - tests := []struct { - name string - from int64 - to int64 - expectedBlocks []int64 - }{ - { - name: "happy flow", - from: 2, - to: 5, - expectedBlocks: []int64{2, 3, 4, 5}, - }, - { - name: "range overflow circular", - from: 1, - to: 6, - expectedBlocks: []int64{2, 3, 4, 5}, - }, - } - - for _, tc := range tests { - t.Run(tc.name, func(t *testing.T) { - blocks := buf.getBlocksInRange(int(tc.from), int(tc.to)) - require.Equal(t, len(tc.expectedBlocks), len(blocks)) - expectedBlockNumbers := map[int64]bool{} - for _, b := range tc.expectedBlocks { - expectedBlockNumbers[b] = false - } - for _, b := range blocks { - expectedBlockNumbers[b.blockNumber] = true - } - for k, v := range expectedBlockNumbers { - require.True(t, v, "missing block %d", k) - } - }) - } -} - -func TestLogEventBuffer_EnqueueDequeue(t *testing.T) { - t.Run("dequeue empty", func(t *testing.T) { - buf := newLogEventBuffer(logger.TestLogger(t), 3, 10, 10) - - results := buf.peekRange(int64(1), int64(2)) - require.Equal(t, 0, len(results)) - results = buf.peek(2) - require.Equal(t, 0, len(results)) - }) - - t.Run("enqueue", func(t *testing.T) { - buf := newLogEventBuffer(logger.TestLogger(t), 3, 10, 10) - - buf.enqueue(big.NewInt(1), - logpoller.Log{BlockNumber: 1, TxHash: common.HexToHash("0x1"), LogIndex: 0}, - logpoller.Log{BlockNumber: 1, TxHash: common.HexToHash("0x1"), LogIndex: 1}, - ) - buf.lock.Lock() - require.Equal(t, 2, len(buf.blocks[0].logs)) - buf.lock.Unlock() - }) - - t.Run("enqueue logs overflow", func(t *testing.T) { - buf := newLogEventBuffer(logger.TestLogger(t), 2, 2, 2) - - require.Equal(t, 2, buf.enqueue(big.NewInt(1), - logpoller.Log{BlockNumber: 1, TxHash: common.HexToHash("0x1"), LogIndex: 0}, - logpoller.Log{BlockNumber: 1, TxHash: common.HexToHash("0x1"), LogIndex: 1}, - logpoller.Log{BlockNumber: 1, TxHash: common.HexToHash("0x1"), LogIndex: 2}, - )) - buf.lock.Lock() - require.Equal(t, 2, len(buf.blocks[0].logs)) - buf.lock.Unlock() - }) - - t.Run("enqueue logs overflow with dynamic limits", func(t *testing.T) { - buf := newLogEventBuffer(logger.TestLogger(t), 2, 10, 2) - - require.Equal(t, 2, buf.enqueue(big.NewInt(1), - logpoller.Log{BlockNumber: 1, TxHash: common.HexToHash("0x1"), LogIndex: 0}, - logpoller.Log{BlockNumber: 1, TxHash: common.HexToHash("0x1"), LogIndex: 1}, - logpoller.Log{BlockNumber: 1, TxHash: common.HexToHash("0x1"), LogIndex: 2}, - )) - buf.SetLimits(10, 3) - require.Equal(t, 3, buf.enqueue(big.NewInt(1), - logpoller.Log{BlockNumber: 2, TxHash: common.HexToHash("0x21"), LogIndex: 0}, - logpoller.Log{BlockNumber: 2, TxHash: common.HexToHash("0x21"), LogIndex: 1}, - logpoller.Log{BlockNumber: 2, TxHash: common.HexToHash("0x21"), LogIndex: 2}, - logpoller.Log{BlockNumber: 2, TxHash: common.HexToHash("0x21"), LogIndex: 3}, - )) - - buf.lock.Lock() - defer buf.lock.Unlock() - require.Equal(t, 2, len(buf.blocks[0].logs)) - require.Equal(t, 3, len(buf.blocks[1].logs)) - }) - - t.Run("enqueue logs overflow with dynamic limits", func(t *testing.T) { - buf := newLogEventBuffer(logger.TestLogger(t), 2, 10, 2) - - require.Equal(t, 2, buf.enqueue(big.NewInt(1), - logpoller.Log{BlockNumber: 1, TxHash: common.HexToHash("0x1"), LogIndex: 0}, - logpoller.Log{BlockNumber: 1, TxHash: common.HexToHash("0x1"), LogIndex: 1}, - logpoller.Log{BlockNumber: 1, TxHash: common.HexToHash("0x1"), LogIndex: 2}, - logpoller.Log{BlockNumber: 1, TxHash: common.HexToHash("0x1"), LogIndex: 3}, - )) - buf.SetLimits(10, 3) - require.Equal(t, 3, buf.enqueue(big.NewInt(1), - logpoller.Log{BlockNumber: 2, TxHash: common.HexToHash("0x21"), LogIndex: 0}, - logpoller.Log{BlockNumber: 2, TxHash: common.HexToHash("0x21"), LogIndex: 1}, - logpoller.Log{BlockNumber: 2, TxHash: common.HexToHash("0x21"), LogIndex: 2}, - logpoller.Log{BlockNumber: 2, TxHash: common.HexToHash("0x21"), LogIndex: 3}, - )) - - buf.lock.Lock() - defer buf.lock.Unlock() - require.Equal(t, 2, len(buf.blocks[0].logs)) - }) - - t.Run("enqueue block overflow", func(t *testing.T) { - buf := newLogEventBuffer(logger.TestLogger(t), 3, 2, 10) - - require.Equal(t, 5, buf.enqueue(big.NewInt(1), - logpoller.Log{BlockNumber: 1, TxHash: common.HexToHash("0x1"), LogIndex: 0}, - logpoller.Log{BlockNumber: 2, TxHash: common.HexToHash("0x2"), LogIndex: 0}, - logpoller.Log{BlockNumber: 3, TxHash: common.HexToHash("0x3"), LogIndex: 0}, - logpoller.Log{BlockNumber: 4, TxHash: common.HexToHash("0x4"), LogIndex: 0}, - logpoller.Log{BlockNumber: 4, TxHash: common.HexToHash("0x4"), LogIndex: 1}, - )) - buf.lock.Lock() - require.Equal(t, 2, len(buf.blocks[0].logs)) - buf.lock.Unlock() - }) - - t.Run("enqueue upkeep block overflow", func(t *testing.T) { - buf := newLogEventBuffer(logger.TestLogger(t), 10, 10, 2) - - require.Equal(t, 2, buf.enqueue(big.NewInt(1), - logpoller.Log{BlockNumber: 1, TxHash: common.HexToHash("0x1"), LogIndex: 0}, - logpoller.Log{BlockNumber: 1, TxHash: common.HexToHash("0x1"), LogIndex: 1}, - logpoller.Log{BlockNumber: 1, TxHash: common.HexToHash("0x1"), LogIndex: 2}, - logpoller.Log{BlockNumber: 1, TxHash: common.HexToHash("0x1"), LogIndex: 3}, - )) - buf.lock.Lock() - require.Equal(t, 2, len(buf.blocks[0].logs)) - buf.lock.Unlock() - }) - - t.Run("peek range after dequeue", func(t *testing.T) { - buf := newLogEventBuffer(logger.TestLogger(t), 3, 10, 10) - - require.Equal(t, buf.enqueue(big.NewInt(10), - logpoller.Log{BlockNumber: 1, TxHash: common.HexToHash("0x1"), LogIndex: 10}, - logpoller.Log{BlockNumber: 3, TxHash: common.HexToHash("0x1"), LogIndex: 11}, - ), 2) - require.Equal(t, buf.enqueue(big.NewInt(1), - logpoller.Log{BlockNumber: 2, TxHash: common.HexToHash("0x1"), LogIndex: 0}, - logpoller.Log{BlockNumber: 3, TxHash: common.HexToHash("0x1"), LogIndex: 1}, - ), 2) - results := buf.peekRange(int64(1), int64(2)) - require.Equal(t, 2, len(results)) - verifyBlockNumbers(t, results, 1, 2) - removed := buf.dequeueRange(int64(1), int64(2), 2, 10) - require.Equal(t, 2, len(removed)) - results = buf.peekRange(int64(1), int64(2)) - require.Equal(t, 0, len(results)) - }) - - t.Run("enqueue peek and dequeue", func(t *testing.T) { - buf := newLogEventBuffer(logger.TestLogger(t), 4, 10, 10) - - require.Equal(t, buf.enqueue(big.NewInt(10), - logpoller.Log{BlockNumber: 1, TxHash: common.HexToHash("0x1"), LogIndex: 10}, - logpoller.Log{BlockNumber: 3, TxHash: common.HexToHash("0x1"), LogIndex: 11}, - ), 2) - require.Equal(t, buf.enqueue(big.NewInt(1), - logpoller.Log{BlockNumber: 2, TxHash: common.HexToHash("0x1"), LogIndex: 0}, - logpoller.Log{BlockNumber: 3, TxHash: common.HexToHash("0x1"), LogIndex: 1}, - ), 2) - results := buf.peek(8) - require.Equal(t, 4, len(results)) - verifyBlockNumbers(t, results, 1, 2, 3, 3) - removed := buf.dequeueRange(1, 3, 5, 5) - require.Equal(t, 4, len(removed)) - buf.lock.Lock() - require.Equal(t, 0, len(buf.blocks[0].logs)) - require.Equal(t, int64(2), buf.blocks[1].blockNumber) - require.Equal(t, 1, len(buf.blocks[1].visited)) - buf.lock.Unlock() - }) - - t.Run("enqueue and peek range circular", func(t *testing.T) { - buf := newLogEventBuffer(logger.TestLogger(t), 3, 10, 10) - - require.Equal(t, buf.enqueue(big.NewInt(1), - logpoller.Log{BlockNumber: 1, TxHash: common.HexToHash("0x1"), LogIndex: 0}, - logpoller.Log{BlockNumber: 2, TxHash: common.HexToHash("0x2"), LogIndex: 0}, - logpoller.Log{BlockNumber: 3, TxHash: common.HexToHash("0x3"), LogIndex: 0}, - ), 3) - require.Equal(t, buf.enqueue(big.NewInt(10), - logpoller.Log{BlockNumber: 4, TxHash: common.HexToHash("0x1"), LogIndex: 10}, - logpoller.Log{BlockNumber: 4, TxHash: common.HexToHash("0x1"), LogIndex: 11}, - ), 2) - - results := buf.peekRange(int64(1), int64(1)) - require.Equal(t, 0, len(results)) - - results = buf.peekRange(int64(3), int64(5)) - require.Equal(t, 3, len(results)) - verifyBlockNumbers(t, results, 3, 4, 4) - }) - - t.Run("doesnt enqueue old blocks", func(t *testing.T) { - buf := newLogEventBuffer(logger.TestLogger(t), 3, 5, 10) - - require.Equal(t, buf.enqueue(big.NewInt(10), - logpoller.Log{BlockNumber: 4, TxHash: common.HexToHash("0x1"), LogIndex: 10}, - logpoller.Log{BlockNumber: 4, TxHash: common.HexToHash("0x1"), LogIndex: 11}, - ), 2) - require.Equal(t, buf.enqueue(big.NewInt(1), - logpoller.Log{BlockNumber: 1, TxHash: common.HexToHash("0x1"), LogIndex: 0}, - logpoller.Log{BlockNumber: 2, TxHash: common.HexToHash("0x2"), LogIndex: 0}, - logpoller.Log{BlockNumber: 3, TxHash: common.HexToHash("0x3"), LogIndex: 0}, - ), 2) - results := buf.peekRange(int64(1), int64(5)) - fmt.Println(results) - verifyBlockNumbers(t, results, 2, 3, 4, 4) - }) - - t.Run("dequeue with limits returns latest block logs", func(t *testing.T) { - buf := newLogEventBuffer(logger.TestLogger(t), 3, 5, 10) - require.Equal(t, buf.enqueue(big.NewInt(1), - logpoller.Log{BlockNumber: 1, TxHash: common.HexToHash("0x1"), LogIndex: 0}, - logpoller.Log{BlockNumber: 2, TxHash: common.HexToHash("0x2"), LogIndex: 0}, - logpoller.Log{BlockNumber: 3, TxHash: common.HexToHash("0x3"), LogIndex: 0}, - logpoller.Log{BlockNumber: 4, TxHash: common.HexToHash("0x4"), LogIndex: 0}, - logpoller.Log{BlockNumber: 5, TxHash: common.HexToHash("0x5"), LogIndex: 0}, - ), 5) - - logs := buf.dequeueRange(1, 5, 2, 10) - require.Equal(t, 2, len(logs)) - require.Equal(t, int64(5), logs[0].log.BlockNumber) - require.Equal(t, int64(4), logs[1].log.BlockNumber) - - require.Equal(t, buf.enqueue(big.NewInt(1), - logpoller.Log{BlockNumber: 4, TxHash: common.HexToHash("0x4"), LogIndex: 1}, - logpoller.Log{BlockNumber: 5, TxHash: common.HexToHash("0x5"), LogIndex: 1}, - ), 2) - - logs = buf.dequeueRange(1, 5, 3, 2) - require.Equal(t, 2, len(logs)) - }) - - t.Run("dequeue doesn't return same logs again", func(t *testing.T) { - buf := newLogEventBuffer(logger.TestLogger(t), 3, 5, 10) - require.Equal(t, buf.enqueue(big.NewInt(1), - logpoller.Log{BlockNumber: 1, TxHash: common.HexToHash("0x1"), LogIndex: 0}, - logpoller.Log{BlockNumber: 2, TxHash: common.HexToHash("0x2"), LogIndex: 0}, - logpoller.Log{BlockNumber: 3, TxHash: common.HexToHash("0x3"), LogIndex: 0}, - ), 3) - - logs := buf.dequeueRange(3, 3, 2, 10) - fmt.Println(logs) - require.Equal(t, 1, len(logs)) - - logs = buf.dequeueRange(3, 3, 2, 10) - fmt.Println(logs) - require.Equal(t, 0, len(logs)) - }) -} - -func TestLogEventBuffer_FetchedBlock_Append(t *testing.T) { - type appendArgs struct { - fl fetchedLog - maxBlockLogs, maxUpkeepLogs int - added, dropped bool - } - - tests := []struct { - name string - blockNumber int64 - logs []fetchedLog - visited []fetchedLog - toAdd []appendArgs - expected []fetchedLog - added bool - }{ - { - name: "empty block", - blockNumber: 1, - logs: []fetchedLog{}, - visited: []fetchedLog{}, - toAdd: []appendArgs{ - { - fl: fetchedLog{ - log: logpoller.Log{ - BlockNumber: 1, - TxHash: common.HexToHash("0x1"), - LogIndex: 0, - }, - upkeepID: core.GenUpkeepID(types.LogTrigger, "111").BigInt(), - }, - maxBlockLogs: 10, - maxUpkeepLogs: 2, - added: true, - }, - }, - expected: []fetchedLog{ - { - log: logpoller.Log{ - BlockNumber: 1, - TxHash: common.HexToHash("0x1"), - LogIndex: 0, - }, - upkeepID: core.GenUpkeepID(types.LogTrigger, "111").BigInt(), - }, - }, - }, - { - name: "existing log", - blockNumber: 1, - logs: []fetchedLog{ - { - log: logpoller.Log{ - BlockNumber: 1, - TxHash: common.HexToHash("0x1"), - LogIndex: 0, - }, - upkeepID: core.GenUpkeepID(types.LogTrigger, "111").BigInt(), - }, - }, - visited: []fetchedLog{}, - toAdd: []appendArgs{ - { - fl: fetchedLog{ - log: logpoller.Log{ - BlockNumber: 1, - TxHash: common.HexToHash("0x1"), - LogIndex: 0, - }, - upkeepID: core.GenUpkeepID(types.LogTrigger, "111").BigInt(), - }, - maxBlockLogs: 10, - maxUpkeepLogs: 2, - added: false, - }, - }, - expected: []fetchedLog{ - { - log: logpoller.Log{ - BlockNumber: 1, - TxHash: common.HexToHash("0x1"), - LogIndex: 0, - }, - upkeepID: core.GenUpkeepID(types.LogTrigger, "111").BigInt(), - }, - }, - }, - { - name: "visited log", - blockNumber: 1, - logs: []fetchedLog{}, - visited: []fetchedLog{ - { - log: logpoller.Log{ - BlockNumber: 1, - TxHash: common.HexToHash("0x1"), - LogIndex: 0, - }, - upkeepID: core.GenUpkeepID(types.LogTrigger, "111").BigInt(), - }, - }, - toAdd: []appendArgs{ - { - fl: fetchedLog{ - log: logpoller.Log{ - BlockNumber: 1, - TxHash: common.HexToHash("0x1"), - LogIndex: 0, - }, - upkeepID: core.GenUpkeepID(types.LogTrigger, "111").BigInt(), - }, - maxBlockLogs: 10, - maxUpkeepLogs: 2, - added: false, - }, - }, - expected: []fetchedLog{}, - }, - { - name: "upkeep log limits", - blockNumber: 1, - logs: []fetchedLog{}, - visited: []fetchedLog{}, - toAdd: []appendArgs{ - { - fl: fetchedLog{ - log: logpoller.Log{ - BlockNumber: 1, - TxHash: common.HexToHash("0x1"), - LogIndex: 0, - }, - upkeepID: core.GenUpkeepID(types.LogTrigger, "111").BigInt(), - }, - maxBlockLogs: 10, - maxUpkeepLogs: 2, - added: true, - }, - { - fl: fetchedLog{ - log: logpoller.Log{ - BlockNumber: 1, - TxHash: common.HexToHash("0x1"), - LogIndex: 1, - }, - upkeepID: core.GenUpkeepID(types.LogTrigger, "111").BigInt(), - }, - maxBlockLogs: 10, - maxUpkeepLogs: 2, - added: true, - }, - { - fl: fetchedLog{ - log: logpoller.Log{ - BlockNumber: 1, - TxHash: common.HexToHash("0x1"), - LogIndex: 2, - }, - upkeepID: core.GenUpkeepID(types.LogTrigger, "111").BigInt(), - }, - maxBlockLogs: 10, - maxUpkeepLogs: 2, - added: true, - dropped: true, - }, - }, - expected: []fetchedLog{ - { - log: logpoller.Log{ - BlockNumber: 1, - TxHash: common.HexToHash("0x1"), - LogIndex: 1, - }, - upkeepID: core.GenUpkeepID(types.LogTrigger, "111").BigInt(), - }, - { - log: logpoller.Log{ - BlockNumber: 1, - TxHash: common.HexToHash("0x1"), - LogIndex: 2, - }, - upkeepID: core.GenUpkeepID(types.LogTrigger, "111").BigInt(), - }, - }, - }, - { - name: "block log limits", - blockNumber: 1, - logs: []fetchedLog{}, - visited: []fetchedLog{}, - toAdd: []appendArgs{ - { - fl: fetchedLog{ - log: logpoller.Log{ - BlockNumber: 1, - TxHash: common.HexToHash("0x1"), - LogIndex: 0, - }, - upkeepID: core.GenUpkeepID(types.LogTrigger, "111").BigInt(), - }, - maxBlockLogs: 2, - maxUpkeepLogs: 4, - added: true, - }, - { - fl: fetchedLog{ - log: logpoller.Log{ - BlockNumber: 1, - TxHash: common.HexToHash("0x1"), - LogIndex: 1, - }, - upkeepID: core.GenUpkeepID(types.LogTrigger, "111").BigInt(), - }, - maxBlockLogs: 2, - maxUpkeepLogs: 4, - added: true, - }, - { - fl: fetchedLog{ - log: logpoller.Log{ - BlockNumber: 1, - TxHash: common.HexToHash("0x1"), - LogIndex: 2, - }, - upkeepID: core.GenUpkeepID(types.LogTrigger, "111").BigInt(), - }, - maxBlockLogs: 2, - maxUpkeepLogs: 4, - added: true, - dropped: true, - }, - }, - expected: []fetchedLog{ - { - log: logpoller.Log{ - BlockNumber: 1, - TxHash: common.HexToHash("0x1"), - LogIndex: 1, - }, - upkeepID: core.GenUpkeepID(types.LogTrigger, "111").BigInt(), - }, - { - log: logpoller.Log{ - BlockNumber: 1, - TxHash: common.HexToHash("0x1"), - LogIndex: 2, - }, - upkeepID: core.GenUpkeepID(types.LogTrigger, "111").BigInt(), - }, - }, - }, - } - - for _, tc := range tests { - t.Run(tc.name, func(t *testing.T) { - lggr := logger.TestLogger(t) - b := fetchedBlock{ - blockNumber: tc.blockNumber, - logs: make([]fetchedLog, len(tc.logs)), - visited: make([]fetchedLog, len(tc.visited)), - } - copy(b.logs, tc.logs) - copy(b.visited, tc.visited) - - for _, args := range tc.toAdd { - dropped, added := b.Append(lggr, args.fl, args.maxBlockLogs, args.maxUpkeepLogs) - require.Equal(t, args.added, added) - if args.dropped { - require.NotNil(t, dropped.upkeepID) - } else { - require.Nil(t, dropped.upkeepID) - } - } - // clear cached logIDs - for i := range b.logs { - b.logs[i].cachedLogID = "" - } - require.Equal(t, tc.expected, b.logs) - }) - } -} -func TestLogEventBuffer_FetchedBlock_Sort(t *testing.T) { - tests := []struct { - name string - blockNumber int64 - logs []fetchedLog - beforeSort []string - afterSort []string - iterations int - }{ - { - name: "no logs", - blockNumber: 10, - logs: []fetchedLog{}, - beforeSort: []string{}, - afterSort: []string{}, - }, - { - name: "single log", - blockNumber: 1, - logs: []fetchedLog{ - { - log: logpoller.Log{ - BlockHash: common.HexToHash("0x111"), - BlockNumber: 1, - TxHash: common.HexToHash("0x1"), - LogIndex: 0, - }, - }, - }, - beforeSort: []string{ - "0000000000000000000000000000000000000000000000000000000000000111000000000000000000000000000000000000000000000000000000000000000100000000", - }, - afterSort: []string{ - "0000000000000000000000000000000000000000000000000000000000000111000000000000000000000000000000000000000000000000000000000000000100000000", - }, - }, - { - name: "multiple logs with 10 iterations", - blockNumber: 1, - logs: []fetchedLog{ - { - log: logpoller.Log{ - BlockNumber: 1, - BlockHash: common.HexToHash("0xa25ebae1099f3fbae2525ebae279f3ae25e"), - TxHash: common.HexToHash("0xb711bd1103927611ee41152aa8ae27f3330"), - LogIndex: 0, - }, - upkeepID: core.GenUpkeepID(types.LogTrigger, "111").BigInt(), - }, - { - log: logpoller.Log{ - BlockNumber: 1, - BlockHash: common.HexToHash("0xa25ebae1099f3fbae2525ebae279f3ae25e"), - TxHash: common.HexToHash("0xa651bd1109922111ee411525ebae27f3fb6"), - LogIndex: 0, - }, - upkeepID: core.GenUpkeepID(types.LogTrigger, "222").BigInt(), - }, - { - log: logpoller.Log{ - BlockNumber: 1, - BlockHash: common.HexToHash("0xa25ebae1099f3fbae2525ebae279f3ae25e"), - TxHash: common.HexToHash("0xa651bd1109922111ee411525ebae27f3fb6"), - LogIndex: 4, - }, - upkeepID: core.GenUpkeepID(types.LogTrigger, "111").BigInt(), - }, - { - log: logpoller.Log{ - BlockNumber: 1, - BlockHash: common.HexToHash("0xa25ebae1099f3fbae2525ebae279f3ae25e"), - TxHash: common.HexToHash("0xa651bd1109922111ee411525ebae27f3fb6"), - LogIndex: 3, - }, - upkeepID: core.GenUpkeepID(types.LogTrigger, "222").BigInt(), - }, - { - log: logpoller.Log{ - BlockNumber: 1, - BlockHash: common.HexToHash("0xa25ebae1099f3fbae2525ebae279f3ae25e"), - TxHash: common.HexToHash("0xa651bd1109922111ee411525ebae27f3fb6"), - LogIndex: 2, - }, - upkeepID: core.GenUpkeepID(types.LogTrigger, "111").BigInt(), - }, - { - log: logpoller.Log{ - BlockNumber: 1, - BlockHash: common.HexToHash("0xa25ebae1099f3fbae2525ebae279f3ae25e"), - TxHash: common.HexToHash("0xa651bd1109922111ee411525ebae27f3fb6"), - LogIndex: 5, - }, - upkeepID: core.GenUpkeepID(types.LogTrigger, "111").BigInt(), - }, - { - log: logpoller.Log{ - BlockNumber: 1, - BlockHash: common.HexToHash("0xa25ebae1099f3fbae2525ebae279f3ae25e"), - TxHash: common.HexToHash("0xa651bd1109922111ee411525ebae27f3fb6"), - LogIndex: 3, - }, - upkeepID: core.GenUpkeepID(types.LogTrigger, "111").BigInt(), - }, - { - log: logpoller.Log{ - BlockNumber: 1, - BlockHash: common.HexToHash("0xa25ebae1099f3fbae2525ebae279f3ae25e"), - TxHash: common.HexToHash("0xa651bd1109922111ee411525ebae27f3fb6"), - LogIndex: 1, - }, - upkeepID: core.GenUpkeepID(types.LogTrigger, "111").BigInt(), - }, - }, - beforeSort: []string{ - "00000000000000000000000000000a25ebae1099f3fbae2525ebae279f3ae25e00000000000000000000000000000b711bd1103927611ee41152aa8ae27f333000000000", - "00000000000000000000000000000a25ebae1099f3fbae2525ebae279f3ae25e00000000000000000000000000000a651bd1109922111ee411525ebae27f3fb600000000", - "00000000000000000000000000000a25ebae1099f3fbae2525ebae279f3ae25e00000000000000000000000000000a651bd1109922111ee411525ebae27f3fb600000004", - "00000000000000000000000000000a25ebae1099f3fbae2525ebae279f3ae25e00000000000000000000000000000a651bd1109922111ee411525ebae27f3fb600000003", - "00000000000000000000000000000a25ebae1099f3fbae2525ebae279f3ae25e00000000000000000000000000000a651bd1109922111ee411525ebae27f3fb600000002", - "00000000000000000000000000000a25ebae1099f3fbae2525ebae279f3ae25e00000000000000000000000000000a651bd1109922111ee411525ebae27f3fb600000005", - "00000000000000000000000000000a25ebae1099f3fbae2525ebae279f3ae25e00000000000000000000000000000a651bd1109922111ee411525ebae27f3fb600000003", - "00000000000000000000000000000a25ebae1099f3fbae2525ebae279f3ae25e00000000000000000000000000000a651bd1109922111ee411525ebae27f3fb600000001", - }, - afterSort: []string{ - "00000000000000000000000000000a25ebae1099f3fbae2525ebae279f3ae25e00000000000000000000000000000b711bd1103927611ee41152aa8ae27f333000000000", - "00000000000000000000000000000a25ebae1099f3fbae2525ebae279f3ae25e00000000000000000000000000000a651bd1109922111ee411525ebae27f3fb600000000", - "00000000000000000000000000000a25ebae1099f3fbae2525ebae279f3ae25e00000000000000000000000000000a651bd1109922111ee411525ebae27f3fb600000001", - "00000000000000000000000000000a25ebae1099f3fbae2525ebae279f3ae25e00000000000000000000000000000a651bd1109922111ee411525ebae27f3fb600000002", - "00000000000000000000000000000a25ebae1099f3fbae2525ebae279f3ae25e00000000000000000000000000000a651bd1109922111ee411525ebae27f3fb600000003", - "00000000000000000000000000000a25ebae1099f3fbae2525ebae279f3ae25e00000000000000000000000000000a651bd1109922111ee411525ebae27f3fb600000003", - "00000000000000000000000000000a25ebae1099f3fbae2525ebae279f3ae25e00000000000000000000000000000a651bd1109922111ee411525ebae27f3fb600000004", - "00000000000000000000000000000a25ebae1099f3fbae2525ebae279f3ae25e00000000000000000000000000000a651bd1109922111ee411525ebae27f3fb600000005", - }, - iterations: 10, - }, - } - - for _, tc := range tests { - t.Run(tc.name, func(t *testing.T) { - b := fetchedBlock{ - blockNumber: tc.blockNumber, - logs: make([]fetchedLog, len(tc.logs)), - } - if tc.iterations == 0 { - tc.iterations = 1 - } - // performing the same multiple times should yield the same result - // default is one iteration - for i := 0; i < tc.iterations; i++ { - copy(b.logs, tc.logs) - logIDs := getLogIds(b) - require.Equal(t, len(tc.beforeSort), len(logIDs)) - require.Equal(t, tc.beforeSort, logIDs) - b.Sort() - logIDsAfterSort := getLogIds(b) - require.Equal(t, len(tc.afterSort), len(logIDsAfterSort)) - require.Equal(t, tc.afterSort, logIDsAfterSort) - } - }) - } -} - -func TestLogEventBuffer_FetchedBlock_Clone(t *testing.T) { - b1 := fetchedBlock{ - blockNumber: 1, - logs: []fetchedLog{ - { - log: logpoller.Log{ - BlockNumber: 1, - TxHash: common.HexToHash("0x1"), - LogIndex: 0, - }, - upkeepID: core.GenUpkeepID(types.LogTrigger, "111").BigInt(), - }, - { - log: logpoller.Log{ - BlockNumber: 1, - TxHash: common.HexToHash("0x1"), - LogIndex: 2, - }, - upkeepID: core.GenUpkeepID(types.LogTrigger, "111").BigInt(), - }, - }, - } - - b2 := b1.Clone() - require.Equal(t, b1.blockNumber, b2.blockNumber) - require.Equal(t, len(b1.logs), len(b2.logs)) - require.Equal(t, b1.logs[0].log.BlockNumber, b2.logs[0].log.BlockNumber) - - b1.blockNumber = 2 - b1.logs[0].log.BlockNumber = 2 - require.NotEqual(t, b1.blockNumber, b2.blockNumber) - require.NotEqual(t, b1.logs[0].log.BlockNumber, b2.logs[0].log.BlockNumber) -} - -func verifyBlockNumbers(t *testing.T, logs []fetchedLog, bns ...int64) { - require.Equal(t, len(bns), len(logs), "expected length mismatch") - for i, log := range logs { - require.Equal(t, bns[i], log.log.BlockNumber, "wrong block number") - } -} - -func getLogIds(b fetchedBlock) []string { - logIDs := make([]string, len(b.logs)) - for i, l := range b.logs { - ext := ocr2keepers.LogTriggerExtension{ - TxHash: l.log.TxHash, - Index: uint32(l.log.LogIndex), - BlockHash: l.log.BlockHash, - } - logIDs[i] = hex.EncodeToString(ext.LogIdentifier()) - } - return logIDs -} diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/factory.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/factory.go index 19302624b4..7ec65ff474 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/factory.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/factory.go @@ -35,23 +35,12 @@ type LogTriggersOptions struct { // Finality depth is the number of blocks to wait before considering a block final. FinalityDepth int64 - // TODO: (AUTO-9355) remove once we have a single version - BufferVersion BufferVersion // LogLimit is the minimum number of logs to process in a single block window. LogLimit uint32 // BlockRate determines the block window for log processing. BlockRate uint32 } -// BufferVersion is the version of the log buffer. -// TODO: (AUTO-9355) remove once we have a single version -type BufferVersion string - -const ( - BufferVersionDefault BufferVersion = "" - BufferVersionV1 BufferVersion = "v1" -) - func NewOptions(finalityDepth int64, chainID *big.Int) LogTriggersOptions { opts := new(LogTriggersOptions) opts.chainID = chainID diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/integration_test.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/integration_test.go index cdd800071d..9942609395 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/integration_test.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/integration_test.go @@ -34,115 +34,92 @@ import ( ) func TestIntegration_LogEventProvider(t *testing.T) { - tests := []struct { - name string - bufferVersion logprovider.BufferVersion - logLimit uint32 - }{ - { - name: "default buffer", - bufferVersion: logprovider.BufferVersionDefault, - logLimit: 10, - }, - { - name: "buffer v1", - bufferVersion: logprovider.BufferVersionV1, - logLimit: 10, - }, - } + ctx, cancel := context.WithCancel(testutils.Context(t)) + defer cancel() + + backend, stopMining, accounts := setupBackend(t) + defer stopMining() + carrol := accounts[2] + + db := setupDB(t) + defer db.Close() + + opts := logprovider.NewOptions(200, big.NewInt(1)) + opts.ReadInterval = time.Second / 2 + opts.LogLimit = 10 + + lp, ethClient := setupDependencies(t, db, backend) + filterStore := logprovider.NewUpkeepFilterStore() + provider, _ := setup(logger.TestLogger(t), lp, nil, nil, filterStore, &opts) + logProvider := provider.(logprovider.LogEventProviderTest) + + n := 10 + + backend.Commit() + lp.PollAndSaveLogs(ctx, 1) // Ensure log poller has a latest block - for _, tc := range tests { - bufferVersion, logLimit := tc.bufferVersion, tc.logLimit - t.Run(tc.name, func(t *testing.T) { - ctx, cancel := context.WithCancel(testutils.Context(t)) - defer cancel() - - backend, stopMining, accounts := setupBackend(t) - defer stopMining() - carrol := accounts[2] - - db := setupDB(t) - defer db.Close() - - opts := logprovider.NewOptions(200, big.NewInt(1)) - opts.ReadInterval = time.Second / 2 - opts.BufferVersion = bufferVersion - opts.LogLimit = logLimit - - lp, ethClient := setupDependencies(t, db, backend) - filterStore := logprovider.NewUpkeepFilterStore() - provider, _ := setup(logger.TestLogger(t), lp, nil, nil, filterStore, &opts) - logProvider := provider.(logprovider.LogEventProviderTest) - - n := 10 - - backend.Commit() - lp.PollAndSaveLogs(ctx, 1) // Ensure log poller has a latest block - - ids, addrs, contracts := deployUpkeepCounter(ctx, t, n, ethClient, backend, carrol, logProvider) - lp.PollAndSaveLogs(ctx, int64(n)) - - go func() { - if err := logProvider.Start(ctx); err != nil { - t.Logf("error starting log provider: %s", err) - t.Fail() - } - }() - defer logProvider.Close() - - logsRounds := 10 - - poll := pollFn(ctx, t, lp, ethClient) - - triggerEvents(ctx, t, backend, carrol, logsRounds, poll, contracts...) - - poll(backend.Commit()) - - waitLogPoller(ctx, t, backend, lp, ethClient) - - waitLogProvider(ctx, t, logProvider, 3) - - allPayloads := collectPayloads(ctx, t, logProvider, n, logsRounds/2) - require.GreaterOrEqual(t, len(allPayloads), n, - "failed to get logs after restart") - - t.Run("Restart", func(t *testing.T) { - t.Log("restarting log provider") - // assuming that our service was closed and restarted, - // we should be able to backfill old logs and fetch new ones - filterStore := logprovider.NewUpkeepFilterStore() - logProvider2 := logprovider.NewLogProvider(logger.TestLogger(t), lp, big.NewInt(1), logprovider.NewLogEventsPacker(), filterStore, opts) - - poll(backend.Commit()) - go func() { - if err2 := logProvider2.Start(ctx); err2 != nil { - t.Logf("error starting log provider: %s", err2) - t.Fail() - } - }() - defer logProvider2.Close() - - // re-register filters - for i, id := range ids { - err := logProvider2.RegisterFilter(ctx, logprovider.FilterOptions{ - UpkeepID: id, - TriggerConfig: newPlainLogTriggerConfig(addrs[i]), - // using block number at which the upkeep was registered, - // before we emitted any logs - UpdateBlock: uint64(n), - }) - require.NoError(t, err) - } - - waitLogProvider(ctx, t, logProvider2, 2) - - t.Log("getting logs after restart") - logsAfterRestart := collectPayloads(ctx, t, logProvider2, n, 5) - require.GreaterOrEqual(t, len(logsAfterRestart), n, - "failed to get logs after restart") + ids, addrs, contracts := deployUpkeepCounter(ctx, t, n, ethClient, backend, carrol, logProvider) + lp.PollAndSaveLogs(ctx, int64(n)) + + go func() { + if err := logProvider.Start(ctx); err != nil { + t.Logf("error starting log provider: %s", err) + t.Fail() + } + }() + defer logProvider.Close() + + logsRounds := 10 + + poll := pollFn(ctx, t, lp, ethClient) + + triggerEvents(ctx, t, backend, carrol, logsRounds, poll, contracts...) + + poll(backend.Commit()) + + waitLogPoller(ctx, t, backend, lp, ethClient) + + waitLogProvider(ctx, t, logProvider, 3) + + allPayloads := collectPayloads(ctx, t, logProvider, n, logsRounds/2) + require.GreaterOrEqual(t, len(allPayloads), n, + "failed to get logs after restart") + + t.Run("Restart", func(t *testing.T) { + t.Log("restarting log provider") + // assuming that our service was closed and restarted, + // we should be able to backfill old logs and fetch new ones + filterStore := logprovider.NewUpkeepFilterStore() + logProvider2 := logprovider.NewLogProvider(logger.TestLogger(t), lp, big.NewInt(1), logprovider.NewLogEventsPacker(), filterStore, opts) + + poll(backend.Commit()) + go func() { + if err2 := logProvider2.Start(ctx); err2 != nil { + t.Logf("error starting log provider: %s", err2) + t.Fail() + } + }() + defer logProvider2.Close() + + // re-register filters + for i, id := range ids { + err := logProvider2.RegisterFilter(ctx, logprovider.FilterOptions{ + UpkeepID: id, + TriggerConfig: newPlainLogTriggerConfig(addrs[i]), + // using block number at which the upkeep was registered, + // before we emitted any logs + UpdateBlock: uint64(n), }) - }) - } + require.NoError(t, err) + } + + waitLogProvider(ctx, t, logProvider2, 2) + + t.Log("getting logs after restart") + logsAfterRestart := collectPayloads(ctx, t, logProvider2, n, 5) + require.GreaterOrEqual(t, len(logsAfterRestart), n, + "failed to get logs after restart") + }) } func TestIntegration_LogEventProvider_UpdateConfig(t *testing.T) { @@ -219,78 +196,55 @@ func TestIntegration_LogEventProvider_UpdateConfig(t *testing.T) { } func TestIntegration_LogEventProvider_Backfill(t *testing.T) { - tests := []struct { - name string - bufferVersion logprovider.BufferVersion - logLimit uint32 - }{ - { - name: "default buffer", - bufferVersion: logprovider.BufferVersionDefault, - logLimit: 10, - }, - { - name: "buffer v1", - bufferVersion: logprovider.BufferVersionV1, - logLimit: 10, - }, - } - - for _, tc := range tests { - bufferVersion, limitLow := tc.bufferVersion, tc.logLimit - t.Run(tc.name, func(t *testing.T) { - ctx, cancel := context.WithTimeout(testutils.Context(t), time.Second*60) - defer cancel() + ctx, cancel := context.WithTimeout(testutils.Context(t), time.Second*60) + defer cancel() - backend, stopMining, accounts := setupBackend(t) - defer stopMining() - carrol := accounts[2] + backend, stopMining, accounts := setupBackend(t) + defer stopMining() + carrol := accounts[2] - db := setupDB(t) - defer db.Close() + db := setupDB(t) + defer db.Close() - opts := logprovider.NewOptions(200, big.NewInt(1)) - opts.ReadInterval = time.Second / 4 - opts.BufferVersion = bufferVersion - opts.LogLimit = limitLow + opts := logprovider.NewOptions(200, big.NewInt(1)) + opts.ReadInterval = time.Second / 4 + opts.LogLimit = 10 - lp, ethClient := setupDependencies(t, db, backend) - filterStore := logprovider.NewUpkeepFilterStore() - provider, _ := setup(logger.TestLogger(t), lp, nil, nil, filterStore, &opts) - logProvider := provider.(logprovider.LogEventProviderTest) + lp, ethClient := setupDependencies(t, db, backend) + filterStore := logprovider.NewUpkeepFilterStore() + provider, _ := setup(logger.TestLogger(t), lp, nil, nil, filterStore, &opts) + logProvider := provider.(logprovider.LogEventProviderTest) - n := 10 + n := 10 - backend.Commit() - lp.PollAndSaveLogs(ctx, 1) // Ensure log poller has a latest block - _, _, contracts := deployUpkeepCounter(ctx, t, n, ethClient, backend, carrol, logProvider) + backend.Commit() + lp.PollAndSaveLogs(ctx, 1) // Ensure log poller has a latest block + _, _, contracts := deployUpkeepCounter(ctx, t, n, ethClient, backend, carrol, logProvider) - poll := pollFn(ctx, t, lp, ethClient) + poll := pollFn(ctx, t, lp, ethClient) - rounds := 8 - for i := 0; i < rounds; i++ { - poll(backend.Commit()) - triggerEvents(ctx, t, backend, carrol, n, poll, contracts...) - poll(backend.Commit()) - } + rounds := 8 + for i := 0; i < rounds; i++ { + poll(backend.Commit()) + triggerEvents(ctx, t, backend, carrol, n, poll, contracts...) + poll(backend.Commit()) + } - waitLogPoller(ctx, t, backend, lp, ethClient) + waitLogPoller(ctx, t, backend, lp, ethClient) - // starting the log provider should backfill logs - go func() { - if startErr := logProvider.Start(ctx); startErr != nil { - t.Logf("error starting log provider: %s", startErr) - t.Fail() - } - }() - defer logProvider.Close() + // starting the log provider should backfill logs + go func() { + if startErr := logProvider.Start(ctx); startErr != nil { + t.Logf("error starting log provider: %s", startErr) + t.Fail() + } + }() + defer logProvider.Close() - waitLogProvider(ctx, t, logProvider, 3) + waitLogProvider(ctx, t, logProvider, 3) - allPayloads := collectPayloads(ctx, t, logProvider, n*rounds, 5) - require.GreaterOrEqual(t, len(allPayloads), len(contracts), "failed to backfill logs") - }) - } + allPayloads := collectPayloads(ctx, t, logProvider, n*rounds, 5) + require.GreaterOrEqual(t, len(allPayloads), len(contracts), "failed to backfill logs") } func TestIntegration_LogRecoverer_Backfill(t *testing.T) { diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/provider.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/provider.go index 3609d0a465..f1de1ef512 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/provider.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/provider.go @@ -81,13 +81,8 @@ type LogEventProviderTest interface { CurrentPartitionIdx() uint64 } -type LogEventProviderFeatures interface { - WithBufferVersion(v BufferVersion) -} - var _ LogEventProvider = &logEventProvider{} var _ LogEventProviderTest = &logEventProvider{} -var _ LogEventProviderFeatures = &logEventProvider{} // logEventProvider manages log filters for upkeeps and enables to read the log events. type logEventProvider struct { @@ -104,8 +99,7 @@ type logEventProvider struct { registerLock sync.Mutex filterStore UpkeepFilterStore - buffer *logEventBuffer - bufferV1 LogBuffer + buffer LogBuffer opts LogTriggersOptions @@ -119,8 +113,7 @@ func NewLogProvider(lggr logger.Logger, poller logpoller.LogPoller, chainID *big threadCtrl: utils.NewThreadControl(), lggr: lggr.Named("KeepersRegistry.LogEventProvider"), packer: packer, - buffer: newLogEventBuffer(lggr, int(opts.LookbackBlocks), defaultNumOfLogUpkeeps, defaultFastExecLogsHigh), - bufferV1: NewLogBuffer(lggr, uint32(opts.LookbackBlocks), opts.BlockRate, opts.LogLimit), + buffer: NewLogBuffer(lggr, uint32(opts.LookbackBlocks), opts.BlockRate, opts.LogLimit), poller: poller, opts: opts, filterStore: filterStore, @@ -147,20 +140,7 @@ func (p *logEventProvider) SetConfig(cfg ocr2keepers.LogEventProviderConfig) { atomic.StoreUint32(&p.opts.BlockRate, blockRate) atomic.StoreUint32(&p.opts.LogLimit, logLimit) - switch p.opts.BufferVersion { - case BufferVersionV1: - p.bufferV1.SetConfig(uint32(p.opts.LookbackBlocks), blockRate, logLimit) - default: - } -} - -func (p *logEventProvider) WithBufferVersion(v BufferVersion) { - p.lock.Lock() - defer p.lock.Unlock() - - p.lggr.Debugw("with buffer version", "version", v) - - p.opts.BufferVersion = v + p.buffer.SetConfig(uint32(p.opts.LookbackBlocks), blockRate, logLimit) } func (p *logEventProvider) Start(context.Context) error { @@ -197,7 +177,7 @@ func (p *logEventProvider) Start(context.Context) error { for { select { case <-ticker.C: - if err := p.syncBufferFilters(); err != nil { + if err := p.buffer.SyncFilters(p.filterStore); err != nil { p.lggr.Warnw("failed to sync buffer filters", "err", err) } case <-ctx.Done(): @@ -259,22 +239,11 @@ func (p *logEventProvider) getLogsFromBuffer(latestBlock int64) []ocr2keepers.Up start = 1 } - switch p.opts.BufferVersion { - case BufferVersionV1: - payloads = p.minimumCommitmentDequeue(latestBlock, start) + payloads = p.minimumCommitmentDequeue(latestBlock, start) - // if we have remaining capacity following minimum commitment dequeue, perform a best effort dequeue - if len(payloads) < MaxPayloads { - payloads = p.bestEffortDequeue(latestBlock, start, payloads) - } - default: - logs := p.buffer.dequeueRange(start, latestBlock, AllowedLogsPerUpkeep, MaxPayloads) - for _, l := range logs { - payload, err := p.createPayload(l.upkeepID, l.log) - if err == nil { - payloads = append(payloads, payload) - } - } + // if we have remaining capacity following minimum commitment dequeue, perform a best effort dequeue + if len(payloads) < MaxPayloads { + payloads = p.bestEffortDequeue(latestBlock, start, payloads) } return payloads @@ -290,7 +259,7 @@ func (p *logEventProvider) minimumCommitmentDequeue(latestBlock, start int64) [] startWindow, _ := getBlockWindow(start, blockRate) // dequeue the minimum number logs (log limit, varies by chain) per upkeep for this block window - logs, remaining := p.bufferV1.Dequeue(startWindow, MaxPayloads-len(payloads), true) + logs, remaining := p.buffer.Dequeue(startWindow, MaxPayloads-len(payloads), true) if len(logs) > 0 { p.lggr.Debugw("minimum commitment dequeue", "start", start, "latestBlock", latestBlock, "logs", len(logs), "remaining", remaining) } @@ -316,7 +285,7 @@ func (p *logEventProvider) bestEffortDequeue(latestBlock, start int64, payloads startWindow, _ := getBlockWindow(start, blockRate) // dequeue as many logs as we can, based on remaining capacity, for this block window - logs, remaining := p.bufferV1.Dequeue(startWindow, MaxPayloads-len(payloads), false) + logs, remaining := p.buffer.Dequeue(startWindow, MaxPayloads-len(payloads), false) if len(logs) > 0 { p.lggr.Debugw("best effort dequeue", "start", start, "latestBlock", latestBlock, "logs", len(logs), "remaining", remaining) } @@ -522,12 +491,8 @@ func (p *logEventProvider) readLogs(ctx context.Context, latest int64, filters [ } filteredLogs := filter.Select(logs...) - switch p.opts.BufferVersion { - case BufferVersionV1: - p.bufferV1.Enqueue(filter.upkeepID, filteredLogs...) - default: - p.buffer.enqueue(filter.upkeepID, filteredLogs...) - } + p.buffer.Enqueue(filter.upkeepID, filteredLogs...) + // Update the lastPollBlock for filter in slice this is then // updated into filter store in updateFiltersLastPoll filters[i].lastPollBlock = latest @@ -535,16 +500,3 @@ func (p *logEventProvider) readLogs(ctx context.Context, latest int64, filters [ return merr } - -func (p *logEventProvider) syncBufferFilters() error { - p.lock.RLock() - buffVersion := p.opts.BufferVersion - p.lock.RUnlock() - - switch buffVersion { - case BufferVersionV1: - return p.bufferV1.SyncFilters(p.filterStore) - default: - return nil - } -} diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/provider_test.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/provider_test.go index 282f89d370..9536a24ce0 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/provider_test.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider/provider_test.go @@ -258,37 +258,14 @@ func TestLogEventProvider_ReadLogs(t *testing.T) { filterStore := NewUpkeepFilterStore() p := NewLogProvider(logger.TestLogger(t), mp, big.NewInt(1), &mockedPacker{}, filterStore, NewOptions(200, big.NewInt(1))) - var ids []*big.Int for i := 0; i < 10; i++ { cfg, f := newEntry(p, i+1) - ids = append(ids, f.upkeepID) require.NoError(t, p.RegisterFilter(ctx, FilterOptions{ UpkeepID: f.upkeepID, TriggerConfig: cfg, })) } - t.Run("no entries", func(t *testing.T) { - require.NoError(t, p.ReadLogs(ctx, big.NewInt(999999))) - logs := p.buffer.peek(10) - require.Len(t, logs, 0) - }) - - t.Run("has entries", func(t *testing.T) { - require.NoError(t, p.ReadLogs(ctx, ids[:2]...)) - logs := p.buffer.peek(10) - require.Len(t, logs, 2) - - var updatedFilters []upkeepFilter - filterStore.RangeFiltersByIDs(func(i int, f upkeepFilter) { - updatedFilters = append(updatedFilters, f.Clone()) - }, ids[:2]...) - for _, f := range updatedFilters { - // Last poll block should be updated - require.Equal(t, int64(1), f.lastPollBlock) - } - }) - // TODO: test rate limiting } @@ -342,7 +319,6 @@ func remainingBlockWindowCounts(queues map[string]*upkeepLogQueue, blockRate int func TestLogEventProvider_GetLatestPayloads(t *testing.T) { t.Run("dequeuing from an empty buffer returns 0 logs", func(t *testing.T) { opts := NewOptions(200, big.NewInt(42161)) - opts.BufferVersion = "v1" logPoller := &mockLogPoller{ LatestBlockFn: func(ctx context.Context) (int64, error) { @@ -361,7 +337,6 @@ func TestLogEventProvider_GetLatestPayloads(t *testing.T) { t.Run("a single log for a single upkeep gets dequeued", func(t *testing.T) { opts := NewOptions(200, big.NewInt(42161)) - opts.BufferVersion = "v1" logPoller := &mockLogPoller{ LatestBlockFn: func(ctx context.Context) (int64, error) { @@ -373,7 +348,7 @@ func TestLogEventProvider_GetLatestPayloads(t *testing.T) { ctx := context.Background() - buffer := provider.bufferV1 + buffer := provider.buffer buffer.Enqueue(big.NewInt(1), logpoller.Log{BlockNumber: 1, TxHash: common.HexToHash("0x1"), LogIndex: 0}) @@ -384,7 +359,6 @@ func TestLogEventProvider_GetLatestPayloads(t *testing.T) { t.Run("a log per upkeep for 4 upkeeps across 4 blocks (2 separate block windows) is dequeued, for a total of 4 payloads", func(t *testing.T) { opts := NewOptions(200, big.NewInt(42161)) - opts.BufferVersion = "v1" logPoller := &mockLogPoller{ LatestBlockFn: func(ctx context.Context) (int64, error) { @@ -396,7 +370,7 @@ func TestLogEventProvider_GetLatestPayloads(t *testing.T) { ctx := context.Background() - buffer := provider.bufferV1 + buffer := provider.buffer buffer.Enqueue(big.NewInt(1), logpoller.Log{BlockNumber: 1, TxHash: common.HexToHash("0x1"), LogIndex: 0}) buffer.Enqueue(big.NewInt(2), logpoller.Log{BlockNumber: 2, TxHash: common.HexToHash("0x2"), LogIndex: 0}) @@ -410,7 +384,6 @@ func TestLogEventProvider_GetLatestPayloads(t *testing.T) { t.Run("100 logs are dequeued for a single upkeep, 1 log for every block window across 100 blocks followed by best effort", func(t *testing.T) { opts := NewOptions(200, big.NewInt(42161)) - opts.BufferVersion = "v1" logPoller := &mockLogPoller{ LatestBlockFn: func(ctx context.Context) (int64, error) { @@ -422,7 +395,7 @@ func TestLogEventProvider_GetLatestPayloads(t *testing.T) { ctx := context.Background() - buffer := provider.bufferV1.(*logBuffer) + buffer := provider.buffer.(*logBuffer) for i := 0; i < 100; i++ { buffer.Enqueue(big.NewInt(1), logpoller.Log{BlockNumber: int64(i + 1), TxHash: common.HexToHash(fmt.Sprintf("0x%d", i+1)), LogIndex: 0}) @@ -439,7 +412,6 @@ func TestLogEventProvider_GetLatestPayloads(t *testing.T) { t.Run("100 logs are dequeued for two upkeeps, 25 logs each as min commitment (50 logs total best effort), followed by best effort", func(t *testing.T) { opts := NewOptions(200, big.NewInt(42161)) - opts.BufferVersion = "v1" logPoller := &mockLogPoller{ LatestBlockFn: func(ctx context.Context) (int64, error) { @@ -451,7 +423,7 @@ func TestLogEventProvider_GetLatestPayloads(t *testing.T) { ctx := context.Background() - buffer := provider.bufferV1.(*logBuffer) + buffer := provider.buffer.(*logBuffer) for i := 0; i < 100; i++ { buffer.Enqueue(big.NewInt(1), logpoller.Log{BlockNumber: int64(i + 1), TxHash: common.HexToHash(fmt.Sprintf("0x1%d", i+1)), LogIndex: 0}) @@ -491,7 +463,6 @@ func TestLogEventProvider_GetLatestPayloads(t *testing.T) { t.Run("minimum guaranteed for all windows including an incomplete window followed by best effort", func(t *testing.T) { opts := NewOptions(200, big.NewInt(42161)) - opts.BufferVersion = "v1" logPoller := &mockLogPoller{ LatestBlockFn: func(ctx context.Context) (int64, error) { @@ -503,7 +474,7 @@ func TestLogEventProvider_GetLatestPayloads(t *testing.T) { ctx := context.Background() - buffer := provider.bufferV1.(*logBuffer) + buffer := provider.buffer.(*logBuffer) for i := 0; i < 102; i++ { buffer.Enqueue(big.NewInt(1), logpoller.Log{BlockNumber: int64(i + 1), TxHash: common.HexToHash(fmt.Sprintf("0x1%d", i+1)), LogIndex: 0}) @@ -551,7 +522,6 @@ func TestLogEventProvider_GetLatestPayloads(t *testing.T) { t.Run("min dequeue followed by best effort followed by reorg followed by best effort", func(t *testing.T) { opts := NewOptions(200, big.NewInt(42161)) - opts.BufferVersion = "v1" logPoller := &mockLogPoller{ LatestBlockFn: func(ctx context.Context) (int64, error) { @@ -563,7 +533,7 @@ func TestLogEventProvider_GetLatestPayloads(t *testing.T) { ctx := context.Background() - buffer := provider.bufferV1.(*logBuffer) + buffer := provider.buffer.(*logBuffer) for i := 0; i < 100; i++ { buffer.Enqueue(big.NewInt(1), logpoller.Log{BlockNumber: int64(i + 1), TxHash: common.HexToHash(fmt.Sprintf("0x1%d", i+1)), LogIndex: 0}) @@ -606,7 +576,6 @@ func TestLogEventProvider_GetLatestPayloads(t *testing.T) { t.Run("sparsely populated blocks", func(t *testing.T) { opts := NewOptions(200, big.NewInt(42161)) - opts.BufferVersion = "v1" logPoller := &mockLogPoller{ LatestBlockFn: func(ctx context.Context) (int64, error) { @@ -618,7 +587,7 @@ func TestLogEventProvider_GetLatestPayloads(t *testing.T) { ctx := context.Background() - buffer := provider.bufferV1.(*logBuffer) + buffer := provider.buffer.(*logBuffer) upkeepOmittedOnBlocks := map[int64][]int{ 1: {5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100}, // upkeep 1 won't have logs on 20 blocks diff --git a/core/services/ocr2/plugins/ocr2keeper/integration_21_test.go b/core/services/ocr2/plugins/ocr2keeper/integration_21_test.go index a79237cf04..7f74f9a38a 100644 --- a/core/services/ocr2/plugins/ocr2keeper/integration_21_test.go +++ b/core/services/ocr2/plugins/ocr2keeper/integration_21_test.go @@ -54,7 +54,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/job" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/streams" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" @@ -119,7 +118,7 @@ func TestIntegration_KeeperPluginConditionalUpkeep(t *testing.T) { require.NoError(t, err) registry := deployKeeper21Registry(t, steve, backend, linkAddr, linkFeedAddr, gasFeedAddr) - setupNodes(t, nodeKeys, registry, backend, steve, false) + setupNodes(t, nodeKeys, registry, backend, steve) <-time.After(time.Second * 5) @@ -173,368 +172,314 @@ func TestIntegration_KeeperPluginConditionalUpkeep(t *testing.T) { } func TestIntegration_KeeperPluginLogUpkeep(t *testing.T) { - tests := []struct { - name string - logBufferVersion logprovider.BufferVersion - }{ - { - name: "default buffer", - logBufferVersion: logprovider.BufferVersionDefault, - }, - { - name: "buffer v1", - logBufferVersion: logprovider.BufferVersionV1, - }, - } + g := gomega.NewWithT(t) - for _, tc := range tests { - t.Run(tc.name, func(t *testing.T) { - g := gomega.NewWithT(t) - - // setup blockchain - sergey := testutils.MustNewSimTransactor(t) // owns all the link - steve := testutils.MustNewSimTransactor(t) // registry owner - carrol := testutils.MustNewSimTransactor(t) // upkeep owner - genesisData := core.GenesisAlloc{ - sergey.From: {Balance: assets.Ether(10000).ToInt()}, - steve.From: {Balance: assets.Ether(10000).ToInt()}, - carrol.From: {Balance: assets.Ether(10000).ToInt()}, - } - // Generate 5 keys for nodes (1 bootstrap + 4 ocr nodes) and fund them with ether - var nodeKeys [5]ethkey.KeyV2 - for i := int64(0); i < 5; i++ { - nodeKeys[i] = cltest.MustGenerateRandomKey(t) - genesisData[nodeKeys[i].Address] = core.GenesisAccount{Balance: assets.Ether(1000).ToInt()} - } + // setup blockchain + sergey := testutils.MustNewSimTransactor(t) // owns all the link + steve := testutils.MustNewSimTransactor(t) // registry owner + carrol := testutils.MustNewSimTransactor(t) // upkeep owner + genesisData := core.GenesisAlloc{ + sergey.From: {Balance: assets.Ether(10000).ToInt()}, + steve.From: {Balance: assets.Ether(10000).ToInt()}, + carrol.From: {Balance: assets.Ether(10000).ToInt()}, + } + // Generate 5 keys for nodes (1 bootstrap + 4 ocr nodes) and fund them with ether + var nodeKeys [5]ethkey.KeyV2 + for i := int64(0); i < 5; i++ { + nodeKeys[i] = cltest.MustGenerateRandomKey(t) + genesisData[nodeKeys[i].Address] = core.GenesisAccount{Balance: assets.Ether(1000).ToInt()} + } - backend := cltest.NewSimulatedBackend(t, genesisData, uint32(ethconfig.Defaults.Miner.GasCeil)) - stopMining := cltest.Mine(backend, 3*time.Second) // Should be greater than deltaRound since we cannot access old blocks on simulated blockchain - defer stopMining() + backend := cltest.NewSimulatedBackend(t, genesisData, uint32(ethconfig.Defaults.Miner.GasCeil)) + stopMining := cltest.Mine(backend, 3*time.Second) // Should be greater than deltaRound since we cannot access old blocks on simulated blockchain + defer stopMining() - // Deploy registry - linkAddr, _, linkToken, err := link_token_interface.DeployLinkToken(sergey, backend) - require.NoError(t, err) - gasFeedAddr, _, _, err := mock_v3_aggregator_contract.DeployMockV3AggregatorContract(steve, backend, 18, big.NewInt(60000000000)) - require.NoError(t, err) - linkFeedAddr, _, _, err := mock_v3_aggregator_contract.DeployMockV3AggregatorContract(steve, backend, 18, big.NewInt(2000000000000000000)) - require.NoError(t, err) + // Deploy registry + linkAddr, _, linkToken, err := link_token_interface.DeployLinkToken(sergey, backend) + require.NoError(t, err) + gasFeedAddr, _, _, err := mock_v3_aggregator_contract.DeployMockV3AggregatorContract(steve, backend, 18, big.NewInt(60000000000)) + require.NoError(t, err) + linkFeedAddr, _, _, err := mock_v3_aggregator_contract.DeployMockV3AggregatorContract(steve, backend, 18, big.NewInt(2000000000000000000)) + require.NoError(t, err) - registry := deployKeeper21Registry(t, steve, backend, linkAddr, linkFeedAddr, gasFeedAddr) - setupNodes(t, nodeKeys, registry, backend, steve, tc.logBufferVersion == logprovider.BufferVersionV1) - upkeeps := 1 + registry := deployKeeper21Registry(t, steve, backend, linkAddr, linkFeedAddr, gasFeedAddr) + setupNodes(t, nodeKeys, registry, backend, steve) + upkeeps := 1 - _, err = linkToken.Transfer(sergey, carrol.From, big.NewInt(0).Mul(oneHunEth, big.NewInt(int64(upkeeps+1)))) - require.NoError(t, err) + _, err = linkToken.Transfer(sergey, carrol.From, big.NewInt(0).Mul(oneHunEth, big.NewInt(int64(upkeeps+1)))) + require.NoError(t, err) - backend.Commit() + backend.Commit() - ids, addrs, contracts := deployUpkeeps(t, backend, carrol, steve, linkToken, registry, upkeeps) - require.Equal(t, upkeeps, len(ids)) - require.Equal(t, len(ids), len(contracts)) - require.Equal(t, len(ids), len(addrs)) + ids, addrs, contracts := deployUpkeeps(t, backend, carrol, steve, linkToken, registry, upkeeps) + require.Equal(t, upkeeps, len(ids)) + require.Equal(t, len(ids), len(contracts)) + require.Equal(t, len(ids), len(addrs)) - backend.Commit() + backend.Commit() - emits := 1 - go emitEvents(testutils.Context(t), t, emits, contracts, carrol, func() { - backend.Commit() - }) + emits := 1 + go emitEvents(testutils.Context(t), t, emits, contracts, carrol, func() { + backend.Commit() + }) - listener, done := listenPerformed(t, backend, registry, ids, int64(1)) - g.Eventually(listener, testutils.WaitTimeout(t), cltest.DBPollingInterval).Should(gomega.BeTrue()) - done() + listener, done := listenPerformed(t, backend, registry, ids, int64(1)) + g.Eventually(listener, testutils.WaitTimeout(t), cltest.DBPollingInterval).Should(gomega.BeTrue()) + done() - t.Run("recover logs", func(t *testing.T) { - addr, contract := addrs[0], contracts[0] - upkeepID := registerUpkeep(t, registry, addr, carrol, steve, backend) + t.Run("recover logs", func(t *testing.T) { + addr, contract := addrs[0], contracts[0] + upkeepID := registerUpkeep(t, registry, addr, carrol, steve, backend) + backend.Commit() + t.Logf("Registered new upkeep %s for address %s", upkeepID.String(), addr.String()) + // Emit 100 logs in a burst + recoverEmits := 100 + i := 0 + emitEvents(testutils.Context(t), t, 100, []*log_upkeep_counter_wrapper.LogUpkeepCounter{contract}, carrol, func() { + i++ + if i%(recoverEmits/4) == 0 { backend.Commit() - t.Logf("Registered new upkeep %s for address %s", upkeepID.String(), addr.String()) - // Emit 100 logs in a burst - recoverEmits := 100 - i := 0 - emitEvents(testutils.Context(t), t, 100, []*log_upkeep_counter_wrapper.LogUpkeepCounter{contract}, carrol, func() { - i++ - if i%(recoverEmits/4) == 0 { - backend.Commit() - time.Sleep(time.Millisecond * 250) // otherwise we get "invalid transaction nonce" errors - } - }) + time.Sleep(time.Millisecond * 250) // otherwise we get "invalid transaction nonce" errors + } + }) - beforeDummyBlocks := backend.Blockchain().CurrentBlock().Number.Uint64() + beforeDummyBlocks := backend.Blockchain().CurrentBlock().Number.Uint64() - // Mine enough blocks to ensure these logs don't fall into log provider range - dummyBlocks := 500 - for i := 0; i < dummyBlocks; i++ { - backend.Commit() - time.Sleep(time.Millisecond * 10) - } + // Mine enough blocks to ensure these logs don't fall into log provider range + dummyBlocks := 500 + for i := 0; i < dummyBlocks; i++ { + backend.Commit() + time.Sleep(time.Millisecond * 10) + } - t.Logf("Mined %d blocks, waiting for logs to be recovered", dummyBlocks) + t.Logf("Mined %d blocks, waiting for logs to be recovered", dummyBlocks) - listener, done := listenPerformedN(t, backend, registry, ids, int64(beforeDummyBlocks), recoverEmits) - defer done() - g.Eventually(listener, testutils.WaitTimeout(t), cltest.DBPollingInterval).Should(gomega.BeTrue()) - }) - }) - } + listener, done := listenPerformedN(t, backend, registry, ids, int64(beforeDummyBlocks), recoverEmits) + defer done() + g.Eventually(listener, testutils.WaitTimeout(t), cltest.DBPollingInterval).Should(gomega.BeTrue()) + }) } func TestIntegration_KeeperPluginLogUpkeep_Retry(t *testing.T) { - tests := []struct { - name string - logBufferVersion logprovider.BufferVersion - }{ - { - name: "default buffer", - logBufferVersion: logprovider.BufferVersionDefault, - }, - { - name: "buffer v1", - logBufferVersion: logprovider.BufferVersionV1, - }, + g := gomega.NewWithT(t) + + // setup blockchain + linkOwner := testutils.MustNewSimTransactor(t) // owns all the link + registryOwner := testutils.MustNewSimTransactor(t) // registry owner + upkeepOwner := testutils.MustNewSimTransactor(t) // upkeep owner + genesisData := core.GenesisAlloc{ + linkOwner.From: {Balance: assets.Ether(10000).ToInt()}, + registryOwner.From: {Balance: assets.Ether(10000).ToInt()}, + upkeepOwner.From: {Balance: assets.Ether(10000).ToInt()}, } - for _, tc := range tests { - t.Run(tc.name, func(t *testing.T) { - g := gomega.NewWithT(t) - - // setup blockchain - linkOwner := testutils.MustNewSimTransactor(t) // owns all the link - registryOwner := testutils.MustNewSimTransactor(t) // registry owner - upkeepOwner := testutils.MustNewSimTransactor(t) // upkeep owner - genesisData := core.GenesisAlloc{ - linkOwner.From: {Balance: assets.Ether(10000).ToInt()}, - registryOwner.From: {Balance: assets.Ether(10000).ToInt()}, - upkeepOwner.From: {Balance: assets.Ether(10000).ToInt()}, - } + // Generate 5 keys for nodes (1 bootstrap + 4 ocr nodes) and fund them with ether + var nodeKeys [5]ethkey.KeyV2 + for i := int64(0); i < 5; i++ { + nodeKeys[i] = cltest.MustGenerateRandomKey(t) + genesisData[nodeKeys[i].Address] = core.GenesisAccount{Balance: assets.Ether(1000).ToInt()} + } - // Generate 5 keys for nodes (1 bootstrap + 4 ocr nodes) and fund them with ether - var nodeKeys [5]ethkey.KeyV2 - for i := int64(0); i < 5; i++ { - nodeKeys[i] = cltest.MustGenerateRandomKey(t) - genesisData[nodeKeys[i].Address] = core.GenesisAccount{Balance: assets.Ether(1000).ToInt()} - } + backend := cltest.NewSimulatedBackend(t, genesisData, uint32(ethconfig.Defaults.Miner.GasCeil)) + stopMining := cltest.Mine(backend, 3*time.Second) // Should be greater than deltaRound since we cannot access old blocks on simulated blockchain + defer stopMining() - backend := cltest.NewSimulatedBackend(t, genesisData, uint32(ethconfig.Defaults.Miner.GasCeil)) - stopMining := cltest.Mine(backend, 3*time.Second) // Should be greater than deltaRound since we cannot access old blocks on simulated blockchain - defer stopMining() + // Deploy registry + linkAddr, _, linkToken, err := link_token_interface.DeployLinkToken(linkOwner, backend) + require.NoError(t, err) - // Deploy registry - linkAddr, _, linkToken, err := link_token_interface.DeployLinkToken(linkOwner, backend) - require.NoError(t, err) + gasFeedAddr, _, _, err := mock_v3_aggregator_contract.DeployMockV3AggregatorContract(registryOwner, backend, 18, big.NewInt(60000000000)) + require.NoError(t, err) - gasFeedAddr, _, _, err := mock_v3_aggregator_contract.DeployMockV3AggregatorContract(registryOwner, backend, 18, big.NewInt(60000000000)) - require.NoError(t, err) + linkFeedAddr, _, _, err := mock_v3_aggregator_contract.DeployMockV3AggregatorContract(registryOwner, backend, 18, big.NewInt(2000000000000000000)) + require.NoError(t, err) - linkFeedAddr, _, _, err := mock_v3_aggregator_contract.DeployMockV3AggregatorContract(registryOwner, backend, 18, big.NewInt(2000000000000000000)) - require.NoError(t, err) + registry := deployKeeper21Registry(t, registryOwner, backend, linkAddr, linkFeedAddr, gasFeedAddr) - registry := deployKeeper21Registry(t, registryOwner, backend, linkAddr, linkFeedAddr, gasFeedAddr) + _, mercuryServer := setupNodes(t, nodeKeys, registry, backend, registryOwner) - _, mercuryServer := setupNodes(t, nodeKeys, registry, backend, registryOwner, tc.logBufferVersion == logprovider.BufferVersionV1) + const upkeepCount = 10 + const mercuryFailCount = upkeepCount * 3 * 2 - const upkeepCount = 10 - const mercuryFailCount = upkeepCount * 3 * 2 + // testing with the mercury server involves mocking responses. currently, + // there is not a way to connect a mercury call to an upkeep id (though we + // could add custom headers) so the test must be fairly basic and just + // count calls before switching to successes + var ( + mu sync.Mutex + count int + ) - // testing with the mercury server involves mocking responses. currently, - // there is not a way to connect a mercury call to an upkeep id (though we - // could add custom headers) so the test must be fairly basic and just - // count calls before switching to successes - var ( - mu sync.Mutex - count int - ) + mercuryServer.RegisterHandler(func(w http.ResponseWriter, r *http.Request) { + mu.Lock() + defer mu.Unlock() - mercuryServer.RegisterHandler(func(w http.ResponseWriter, r *http.Request) { - mu.Lock() - defer mu.Unlock() + count++ - count++ + _ = r.ParseForm() - _ = r.ParseForm() + t.Logf("MercuryHTTPServe:RequestURI: %s", r.RequestURI) - t.Logf("MercuryHTTPServe:RequestURI: %s", r.RequestURI) + for key, value := range r.Form { + t.Logf("MercuryHTTPServe:FormValue: key: %s; value: %s;", key, value) + } - for key, value := range r.Form { - t.Logf("MercuryHTTPServe:FormValue: key: %s; value: %s;", key, value) - } + // the streams lookup retries against the remote server 3 times before + // returning a result as retryable. + // the simulation here should force the streams lookup process to return + // retryable 2 times. + // the total count of failures should be (upkeepCount * 3 * tryCount) + if count <= mercuryFailCount { + w.WriteHeader(http.StatusNotFound) - // the streams lookup retries against the remote server 3 times before - // returning a result as retryable. - // the simulation here should force the streams lookup process to return - // retryable 2 times. - // the total count of failures should be (upkeepCount * 3 * tryCount) - if count <= mercuryFailCount { - w.WriteHeader(http.StatusNotFound) + return + } - return - } + // start sending success messages + output := `{"chainlinkBlob":"0x0001c38d71fed6c320b90e84b6f559459814d068e2a1700adc931ca9717d4fe70000000000000000000000000000000000000000000000000000000001a80b52b4bf1233f9cb71144a253a1791b202113c4ab4a92fa1b176d684b4959666ff8200000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001004254432d5553442d415242495452554d2d544553544e4554000000000000000000000000000000000000000000000000000000000000000000000000645570be000000000000000000000000000000000000000000000000000002af2b818dc5000000000000000000000000000000000000000000000000000002af2426faf3000000000000000000000000000000000000000000000000000002af32dc209700000000000000000000000000000000000000000000000000000000012130f8df0a9745bb6ad5e2df605e158ba8ad8a33ef8a0acf9851f0f01668a3a3f2b68600000000000000000000000000000000000000000000000000000000012130f60000000000000000000000000000000000000000000000000000000000000002c4a7958dce105089cf5edb68dad7dcfe8618d7784eb397f97d5a5fade78c11a58275aebda478968e545f7e3657aba9dcbe8d44605e4c6fde3e24edd5e22c94270000000000000000000000000000000000000000000000000000000000000002459c12d33986018a8959566d145225f0c4a4e61a9a3f50361ccff397899314f0018162cf10cd89897635a0bb62a822355bd199d09f4abe76e4d05261bb44733d"}` - // start sending success messages - output := `{"chainlinkBlob":"0x0001c38d71fed6c320b90e84b6f559459814d068e2a1700adc931ca9717d4fe70000000000000000000000000000000000000000000000000000000001a80b52b4bf1233f9cb71144a253a1791b202113c4ab4a92fa1b176d684b4959666ff8200000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000260000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001004254432d5553442d415242495452554d2d544553544e4554000000000000000000000000000000000000000000000000000000000000000000000000645570be000000000000000000000000000000000000000000000000000002af2b818dc5000000000000000000000000000000000000000000000000000002af2426faf3000000000000000000000000000000000000000000000000000002af32dc209700000000000000000000000000000000000000000000000000000000012130f8df0a9745bb6ad5e2df605e158ba8ad8a33ef8a0acf9851f0f01668a3a3f2b68600000000000000000000000000000000000000000000000000000000012130f60000000000000000000000000000000000000000000000000000000000000002c4a7958dce105089cf5edb68dad7dcfe8618d7784eb397f97d5a5fade78c11a58275aebda478968e545f7e3657aba9dcbe8d44605e4c6fde3e24edd5e22c94270000000000000000000000000000000000000000000000000000000000000002459c12d33986018a8959566d145225f0c4a4e61a9a3f50361ccff397899314f0018162cf10cd89897635a0bb62a822355bd199d09f4abe76e4d05261bb44733d"}` + w.WriteHeader(http.StatusOK) + _, _ = w.Write([]byte(output)) + }) - w.WriteHeader(http.StatusOK) - _, _ = w.Write([]byte(output)) - }) + defer mercuryServer.Stop() - defer mercuryServer.Stop() + _, err = linkToken.Transfer(linkOwner, upkeepOwner.From, big.NewInt(0).Mul(oneHunEth, big.NewInt(int64(upkeepCount+1)))) + require.NoError(t, err) - _, err = linkToken.Transfer(linkOwner, upkeepOwner.From, big.NewInt(0).Mul(oneHunEth, big.NewInt(int64(upkeepCount+1)))) - require.NoError(t, err) + backend.Commit() - backend.Commit() + feeds, err := newFeedLookupUpkeepController(backend, registryOwner) + require.NoError(t, err, "no error expected from creating a feed lookup controller") + + // deploy multiple upkeeps that listen to a log emitter and need to be + // performed for each log event + _ = feeds.DeployUpkeeps(t, backend, upkeepOwner, upkeepCount, func(int) bool { + return false + }) + _ = feeds.RegisterAndFund(t, registry, registryOwner, backend, linkToken) + _ = feeds.EnableMercury(t, backend, registry, registryOwner) + _ = feeds.VerifyEnv(t, backend, registry, registryOwner) - feeds, err := newFeedLookupUpkeepController(backend, registryOwner) - require.NoError(t, err, "no error expected from creating a feed lookup controller") - - // deploy multiple upkeeps that listen to a log emitter and need to be - // performed for each log event - _ = feeds.DeployUpkeeps(t, backend, upkeepOwner, upkeepCount, func(int) bool { - return false - }) - _ = feeds.RegisterAndFund(t, registry, registryOwner, backend, linkToken) - _ = feeds.EnableMercury(t, backend, registry, registryOwner) - _ = feeds.VerifyEnv(t, backend, registry, registryOwner) - - // start emitting events in a separate go-routine - // feed lookup relies on a single contract event log to perform multiple - // listener contracts - go func() { - // only 1 event is necessary to make all 10 upkeeps eligible - _ = feeds.EmitEvents(t, backend, 1, func() { - // pause per emit for expected block production time - time.Sleep(3 * time.Second) - }) - }() - - listener, done := listenPerformed(t, backend, registry, feeds.UpkeepsIds(), int64(1)) - defer done() - g.Eventually(listener, testutils.WaitTimeout(t)-(5*time.Second), cltest.DBPollingInterval).Should(gomega.BeTrue()) + // start emitting events in a separate go-routine + // feed lookup relies on a single contract event log to perform multiple + // listener contracts + go func() { + // only 1 event is necessary to make all 10 upkeeps eligible + _ = feeds.EmitEvents(t, backend, 1, func() { + // pause per emit for expected block production time + time.Sleep(3 * time.Second) }) - } + }() + + listener, done := listenPerformed(t, backend, registry, feeds.UpkeepsIds(), int64(1)) + defer done() + g.Eventually(listener, testutils.WaitTimeout(t)-(5*time.Second), cltest.DBPollingInterval).Should(gomega.BeTrue()) } func TestIntegration_KeeperPluginLogUpkeep_ErrHandler(t *testing.T) { - tests := []struct { - name string - logBufferVersion logprovider.BufferVersion - }{ - { - name: "default buffer", - logBufferVersion: logprovider.BufferVersionDefault, - }, - { - name: "buffer v1", - logBufferVersion: logprovider.BufferVersionV1, - }, + g := gomega.NewWithT(t) + + // setup blockchain + linkOwner := testutils.MustNewSimTransactor(t) // owns all the link + registryOwner := testutils.MustNewSimTransactor(t) // registry owner + upkeepOwner := testutils.MustNewSimTransactor(t) // upkeep owner + genesisData := core.GenesisAlloc{ + linkOwner.From: {Balance: assets.Ether(10000).ToInt()}, + registryOwner.From: {Balance: assets.Ether(10000).ToInt()}, + upkeepOwner.From: {Balance: assets.Ether(10000).ToInt()}, } - for _, tc := range tests { - t.Run(tc.name, func(t *testing.T) { - g := gomega.NewWithT(t) - - // setup blockchain - linkOwner := testutils.MustNewSimTransactor(t) // owns all the link - registryOwner := testutils.MustNewSimTransactor(t) // registry owner - upkeepOwner := testutils.MustNewSimTransactor(t) // upkeep owner - genesisData := core.GenesisAlloc{ - linkOwner.From: {Balance: assets.Ether(10000).ToInt()}, - registryOwner.From: {Balance: assets.Ether(10000).ToInt()}, - upkeepOwner.From: {Balance: assets.Ether(10000).ToInt()}, - } + // Generate 5 keys for nodes (1 bootstrap + 4 ocr nodes) and fund them with ether + var nodeKeys [5]ethkey.KeyV2 + for i := int64(0); i < 5; i++ { + nodeKeys[i] = cltest.MustGenerateRandomKey(t) + genesisData[nodeKeys[i].Address] = core.GenesisAccount{Balance: assets.Ether(1000).ToInt()} + } - // Generate 5 keys for nodes (1 bootstrap + 4 ocr nodes) and fund them with ether - var nodeKeys [5]ethkey.KeyV2 - for i := int64(0); i < 5; i++ { - nodeKeys[i] = cltest.MustGenerateRandomKey(t) - genesisData[nodeKeys[i].Address] = core.GenesisAccount{Balance: assets.Ether(1000).ToInt()} - } + backend := cltest.NewSimulatedBackend(t, genesisData, uint32(ethconfig.Defaults.Miner.GasCeil)) + stopMining := cltest.Mine(backend, 3*time.Second) // Should be greater than deltaRound since we cannot access old blocks on simulated blockchain + defer stopMining() - backend := cltest.NewSimulatedBackend(t, genesisData, uint32(ethconfig.Defaults.Miner.GasCeil)) - stopMining := cltest.Mine(backend, 3*time.Second) // Should be greater than deltaRound since we cannot access old blocks on simulated blockchain - defer stopMining() + // Deploy registry + linkAddr, _, linkToken, err := link_token_interface.DeployLinkToken(linkOwner, backend) + require.NoError(t, err) - // Deploy registry - linkAddr, _, linkToken, err := link_token_interface.DeployLinkToken(linkOwner, backend) - require.NoError(t, err) + gasFeedAddr, _, _, err := mock_v3_aggregator_contract.DeployMockV3AggregatorContract(registryOwner, backend, 18, big.NewInt(60000000000)) + require.NoError(t, err) - gasFeedAddr, _, _, err := mock_v3_aggregator_contract.DeployMockV3AggregatorContract(registryOwner, backend, 18, big.NewInt(60000000000)) - require.NoError(t, err) + linkFeedAddr, _, _, err := mock_v3_aggregator_contract.DeployMockV3AggregatorContract(registryOwner, backend, 18, big.NewInt(2000000000000000000)) + require.NoError(t, err) - linkFeedAddr, _, _, err := mock_v3_aggregator_contract.DeployMockV3AggregatorContract(registryOwner, backend, 18, big.NewInt(2000000000000000000)) - require.NoError(t, err) + registry := deployKeeper21Registry(t, registryOwner, backend, linkAddr, linkFeedAddr, gasFeedAddr) - registry := deployKeeper21Registry(t, registryOwner, backend, linkAddr, linkFeedAddr, gasFeedAddr) + _, mercuryServer := setupNodes(t, nodeKeys, registry, backend, registryOwner) - _, mercuryServer := setupNodes(t, nodeKeys, registry, backend, registryOwner, tc.logBufferVersion == logprovider.BufferVersionV1) + upkeepCount := 10 - upkeepCount := 10 + errResponses := []int{ + http.StatusUnauthorized, + http.StatusBadRequest, + http.StatusInternalServerError, + http.StatusNotFound, + http.StatusNotFound, + http.StatusNotFound, + http.StatusUnauthorized, + } + startMercuryServer(t, mercuryServer, func(i int) (int, []byte) { + var resp int + if i < len(errResponses) { + resp = errResponses[i] + } + if resp == 0 { + resp = http.StatusNotFound + } + return resp, nil + }) + defer mercuryServer.Stop() - errResponses := []int{ - http.StatusUnauthorized, - http.StatusBadRequest, - http.StatusInternalServerError, - http.StatusNotFound, - http.StatusNotFound, - http.StatusNotFound, - http.StatusUnauthorized, - } - startMercuryServer(t, mercuryServer, func(i int) (int, []byte) { - var resp int - if i < len(errResponses) { - resp = errResponses[i] - } - if resp == 0 { - resp = http.StatusNotFound - } - return resp, nil - }) - defer mercuryServer.Stop() + _, err = linkToken.Transfer(linkOwner, upkeepOwner.From, big.NewInt(0).Mul(oneHunEth, big.NewInt(int64(upkeepCount+1)))) + require.NoError(t, err) - _, err = linkToken.Transfer(linkOwner, upkeepOwner.From, big.NewInt(0).Mul(oneHunEth, big.NewInt(int64(upkeepCount+1)))) - require.NoError(t, err) + backend.Commit() - backend.Commit() + feeds, err := newFeedLookupUpkeepController(backend, registryOwner) + require.NoError(t, err, "no error expected from creating a feed lookup controller") - feeds, err := newFeedLookupUpkeepController(backend, registryOwner) - require.NoError(t, err, "no error expected from creating a feed lookup controller") + // deploy multiple upkeeps that listen to a log emitter and need to be + // performed for each log event + checkResultsProvider := func(i int) bool { + return i%2 == 1 + } + require.NoError(t, feeds.DeployUpkeeps(t, backend, upkeepOwner, upkeepCount, checkResultsProvider)) + require.NoError(t, feeds.RegisterAndFund(t, registry, registryOwner, backend, linkToken)) + require.NoError(t, feeds.EnableMercury(t, backend, registry, registryOwner)) + require.NoError(t, feeds.VerifyEnv(t, backend, registry, registryOwner)) + + startBlock := backend.Blockchain().CurrentBlock().Number.Int64() + // start emitting events in a separate go-routine + // feed lookup relies on a single contract event log to perform multiple + // listener contracts + go func() { + // only 1 event is necessary to make all 10 upkeeps eligible + _ = feeds.EmitEvents(t, backend, 1, func() { + // pause per emit for expected block production time + time.Sleep(3 * time.Second) + }) + }() - // deploy multiple upkeeps that listen to a log emitter and need to be - // performed for each log event - checkResultsProvider := func(i int) bool { - return i%2 == 1 - } - require.NoError(t, feeds.DeployUpkeeps(t, backend, upkeepOwner, upkeepCount, checkResultsProvider)) - require.NoError(t, feeds.RegisterAndFund(t, registry, registryOwner, backend, linkToken)) - require.NoError(t, feeds.EnableMercury(t, backend, registry, registryOwner)) - require.NoError(t, feeds.VerifyEnv(t, backend, registry, registryOwner)) - - startBlock := backend.Blockchain().CurrentBlock().Number.Int64() - // start emitting events in a separate go-routine - // feed lookup relies on a single contract event log to perform multiple - // listener contracts - go func() { - // only 1 event is necessary to make all 10 upkeeps eligible - _ = feeds.EmitEvents(t, backend, 1, func() { - // pause per emit for expected block production time - time.Sleep(3 * time.Second) - }) - }() - - go makeDummyBlocks(t, backend, 3*time.Second, 1000) - - idsToCheck := make([]*big.Int, 0) - for i, uid := range feeds.UpkeepsIds() { - if checkResultsProvider(i) { - idsToCheck = append(idsToCheck, uid) - } - } + go makeDummyBlocks(t, backend, 3*time.Second, 1000) - listener, done := listenPerformed(t, backend, registry, idsToCheck, startBlock) - defer done() - g.Eventually(listener, testutils.WaitTimeout(t)-(5*time.Second), cltest.DBPollingInterval).Should(gomega.BeTrue()) - }) + idsToCheck := make([]*big.Int, 0) + for i, uid := range feeds.UpkeepsIds() { + if checkResultsProvider(i) { + idsToCheck = append(idsToCheck, uid) + } } + + listener, done := listenPerformed(t, backend, registry, idsToCheck, startBlock) + defer done() + g.Eventually(listener, testutils.WaitTimeout(t)-(5*time.Second), cltest.DBPollingInterval).Should(gomega.BeTrue()) } func startMercuryServer(t *testing.T, mercuryServer *mercury.SimulatedMercuryServer, responder func(i int) (int, []byte)) { @@ -644,7 +589,7 @@ func listenPerformed(t *testing.T, backend *backends.SimulatedBackend, registry return listenPerformedN(t, backend, registry, ids, startBlock, 0) } -func setupNodes(t *testing.T, nodeKeys [5]ethkey.KeyV2, registry *iregistry21.IKeeperRegistryMaster, backend *backends.SimulatedBackend, usr *bind.TransactOpts, useBufferV1 bool) ([]Node, *mercury.SimulatedMercuryServer) { +func setupNodes(t *testing.T, nodeKeys [5]ethkey.KeyV2, registry *iregistry21.IKeeperRegistryMaster, backend *backends.SimulatedBackend, usr *bind.TransactOpts) ([]Node, *mercury.SimulatedMercuryServer) { lggr := logger.TestLogger(t) mServer := mercury.NewSimulatedMercuryServer() mServer.Start() @@ -727,8 +672,7 @@ func setupNodes(t *testing.T, nodeKeys [5]ethkey.KeyV2, registry *iregistry21.IK cacheEvictionInterval = "1s" mercuryCredentialName = "%s" contractVersion = "v2.1" - useBufferV1 = %v - `, i, registry.Address(), node.KeyBundle.ID(), node.Transmitter, fmt.Sprintf("%s@127.0.0.1:%d", bootstrapPeerID, bootstrapNodePort), MercuryCredName, useBufferV1)) + `, i, registry.Address(), node.KeyBundle.ID(), node.Transmitter, fmt.Sprintf("%s@127.0.0.1:%d", bootstrapPeerID, bootstrapNodePort), MercuryCredName)) } // Setup config on contract diff --git a/integration-tests/actions/automationv2/actions.go b/integration-tests/actions/automationv2/actions.go index f7d495bda5..40caf15917 100644 --- a/integration-tests/actions/automationv2/actions.go +++ b/integration-tests/actions/automationv2/actions.go @@ -88,8 +88,7 @@ type AutomationTest struct { mercuryCredentialName string TransmitterKeyIndex int - Logger zerolog.Logger - useLogBufferV1 bool + Logger zerolog.Logger } type UpkeepConfig struct { @@ -117,7 +116,6 @@ func NewAutomationTestK8s( TransmitterKeyIndex: 0, UpkeepPrivilegeManager: chainClient.MustGetRootKeyAddress(), mercuryCredentialName: "", - useLogBufferV1: false, Logger: l, } } @@ -134,7 +132,6 @@ func NewAutomationTestDocker( TransmitterKeyIndex: 0, UpkeepPrivilegeManager: chainClient.MustGetRootKeyAddress(), mercuryCredentialName: "", - useLogBufferV1: false, Logger: l, } } @@ -147,10 +144,6 @@ func (a *AutomationTest) SetMercuryCredentialName(name string) { a.mercuryCredentialName = name } -func (a *AutomationTest) SetUseLogBufferV1(flag bool) { - a.useLogBufferV1 = flag -} - func (a *AutomationTest) SetTransmitterKeyIndex(index int) { a.TransmitterKeyIndex = index } @@ -422,9 +415,6 @@ func (a *AutomationTest) AddAutomationJobs() error { if a.mercuryCredentialName != "" { pluginCfg["mercuryCredentialName"] = "\"" + a.mercuryCredentialName + "\"" } - if a.useLogBufferV1 { - pluginCfg["useBufferV1"] = "true" - } } for i := 1; i < len(a.ChainlinkNodes); i++ { autoOCR2JobSpec := client.OCR2TaskJobSpec{ diff --git a/integration-tests/load/automationv2_1/automationv2_1_test.go b/integration-tests/load/automationv2_1/automationv2_1_test.go index b0555cdd3f..0fe13d4bc7 100644 --- a/integration-tests/load/automationv2_1/automationv2_1_test.go +++ b/integration-tests/load/automationv2_1/automationv2_1_test.go @@ -368,10 +368,6 @@ Load Config: a.SetMercuryCredentialName("cred1") } - if *conf.UseLogBufferV1 { - a.SetUseLogBufferV1(true) - } - startTimeTestSetup := time.Now() l.Info().Str("START_TIME", startTimeTestSetup.String()).Msg("Test setup started") diff --git a/integration-tests/testconfig/automation/config.go b/integration-tests/testconfig/automation/config.go index bde989f544..e6df7714af 100644 --- a/integration-tests/testconfig/automation/config.go +++ b/integration-tests/testconfig/automation/config.go @@ -160,7 +160,6 @@ type AutomationConfig struct { PluginConfig *PluginConfig `toml:"PluginConfig"` PublicConfig *PublicConfig `toml:"PublicConfig"` RegistrySettings *RegistrySettings `toml:"RegistrySettings"` - UseLogBufferV1 *bool `toml:"use_log_buffer_v1"` } func (c *AutomationConfig) Validate() error { @@ -170,13 +169,7 @@ func (c *AutomationConfig) Validate() error { if err := c.PublicConfig.Validate(); err != nil { return err } - if err := c.RegistrySettings.Validate(); err != nil { - return err - } - if c.UseLogBufferV1 == nil { - return errors.New("use_log_buffer_v1 must be set") - } - return nil + return c.RegistrySettings.Validate() } type PluginConfig struct { From 4565feffef574fee7080458e361858283a4cf272 Mon Sep 17 00:00:00 2001 From: Bartek Tofel Date: Fri, 19 Jul 2024 19:25:43 +0200 Subject: [PATCH 003/115] run tests also if CL image build was skipped (tag), fix notification (#13905) --- .../workflows/client-compatibility-tests.yml | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/.github/workflows/client-compatibility-tests.yml b/.github/workflows/client-compatibility-tests.yml index 311614033b..b204c79d2d 100644 --- a/.github/workflows/client-compatibility-tests.yml +++ b/.github/workflows/client-compatibility-tests.yml @@ -120,6 +120,7 @@ jobs: evm_implementations: ${{ steps.select-implementations.outputs.evm_implementations }} chainlink_version: ${{ steps.select-chainlink-version.outputs.chainlink_version }} latest_image_count: ${{ steps.get-image-count.outputs.image_count }} + chainlink_ref_path: ${{ steps.select-chainlink-version.outputs.cl_ref_path }} steps: # ghlatestreleasechecker is a tool to check if new release is available for a given repo - name: Set Up ghlatestreleasechecker @@ -186,28 +187,39 @@ jobs: # we use 100 days since we really want the latest one, and it's highly improbable there won't be a release in last 100 days chainlink_version=$(ghlatestreleasechecker "smartcontractkit/chainlink" 100) echo "chainlink_version=$chainlink_version" >> $GITHUB_OUTPUT + cl_ref_path="release" elif [ "$GITHUB_EVENT_NAME" = "workflow_dispatch" ]; then echo "Fetching Chainlink version from input" if [ -n "${{ github.event.inputs.chainlinkVersion }}" ]; then echo "Chainlink version provided in input" chainlink_version="${{ github.event.inputs.chainlinkVersion }}" + if [[ "$chainlink_version" =~ ^[0-9a-f]{40}$ ]]; then + cl_ref_path="commit" + else + cl_ref_path="release" + fi else echo "Chainlink version not provided in input. Using latest commit SHA." chainlink_version=${{ github.sha }} + cl_ref_path="commit" fi echo "chainlink_version=$chainlink_version" >> $GITHUB_OUTPUT + echo "cl_ref_path=$cl_ref_path" >> $GITHUB_OUTPUT elif [ "$GITHUB_EVENT_NAME" = "pull_request" ]; then echo "Fetching Chainlink version from PR's head commit" chainlink_version="${{ github.event.pull_request.head.sha }}" echo "chainlink_version=$chainlink_version" >> $GITHUB_OUTPUT + echo "cl_ref_path=commit" >> $GITHUB_OUTPUT elif [ "$GITHUB_EVENT_NAME" = "merge_queue" ]; then echo "Fetching Chainlink version from merge queue's head commit" chainlink_version="${{ github.event.merge_group.head_sha }}" echo "chainlink_version=$chainlink_version" >> $GITHUB_OUTPUT + echo "cl_ref_path=commit" >> $GITHUB_OUTPUT elif [ "$GITHUB_REF_TYPE" = "tag" ]; then echo "Fetching Chainlink version from tag" chainlink_version="${{ github.ref_name }}" echo "chainlink_version=$chainlink_version" >> $GITHUB_OUTPUT + echo "cl_ref_path=release" >> $GITHUB_OUTPUT else echo "Unsupported trigger event. It's probably an issue with the pipeline definition. Please reach out to the Test Tooling team." exit 1 @@ -223,7 +235,7 @@ jobs: else image_count="${{ github.event.inputs.latestVersionsNumber }}" echo "image_count=$image_count" >> $GITHUB_OUTPUT - fi + fi else echo "Fetching default latest image count" image_count=3 @@ -512,7 +524,7 @@ jobs: run-client-compatibility-matrix: name: ${{ matrix.evm_node.product }} compatibility with ${{ matrix.evm_node.docker_image }} - if: always() && needs.should-run.outputs.should_run == 'true' && needs.build-chainlink.result == 'success' && needs.prepare-compatibility-matrix.outputs.matrix != '' + if: always() && needs.should-run.outputs.should_run == 'true' && (needs.build-chainlink.result == 'success' || needs.build-chainlink.result == 'skipped') && needs.prepare-compatibility-matrix.outputs.matrix != '' environment: integration permissions: checks: write @@ -672,7 +684,7 @@ jobs: "type": "section", "text": { "type": "mrkdwn", - "text": "<${{ github.server_url }}/${{ github.repository }}/releases/tag/${{ github.ref_name }}|${{ github.ref_name }}> | <${{ github.server_url }}/${{ github.repository }}/commit/${{ needs.select-versions.outputs.chainlink_version }}|${{ needs.select-versions.outputs.chainlink_version }}> | <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|Run>" + "text": "<${{ github.server_url }}/${{ github.repository }}/${{ needs.select-versions.outputs.chainlink_ref_path }}/${{ needs.select-versions.outputs.chainlink_version }}|${{ needs.select-versions.outputs.chainlink_version }}> | <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|Run>" } } ] From 518350d24bca734c3e41e327c5a8e33661b3ff6d Mon Sep 17 00:00:00 2001 From: Bolek <1416262+bolekk@users.noreply.github.com> Date: Tue, 23 Jul 2024 05:25:30 -0700 Subject: [PATCH 004/115] Ukflake TestFunctionsConnectorHandler (#13916) Wait for the handler to be called before proceeding. --- core/services/functions/connector_handler_test.go | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/core/services/functions/connector_handler_test.go b/core/services/functions/connector_handler_test.go index 7e1f3ced34..a24139da58 100644 --- a/core/services/functions/connector_handler_test.go +++ b/core/services/functions/connector_handler_test.go @@ -269,7 +269,10 @@ func TestFunctionsConnectorHandler(t *testing.T) { // first call to trigger the request var response functions.HeartbeatResponse allowlist.On("Allow", addr).Return(true).Once() - listener.On("HandleOffchainRequest", mock.Anything, mock.Anything).Return(nil).Once() + handlerCalled := make(chan struct{}) + listener.On("HandleOffchainRequest", mock.Anything, mock.Anything).Run(func(args mock.Arguments) { + handlerCalled <- struct{}{} + }).Return(nil).Once() connector.On("SendToGateway", mock.Anything, "gw1", mock.Anything).Run(func(args mock.Arguments) { respMsg, ok := args[2].(*api.Message) require.True(t, ok) @@ -277,6 +280,7 @@ func TestFunctionsConnectorHandler(t *testing.T) { require.Equal(t, functions.RequestStatePending, response.Status) }).Return(nil).Once() handler.HandleGatewayMessage(ctx, "gw1", msg) + <-handlerCalled // async response computation reportCh <- &functions.OffchainResponse{ @@ -304,9 +308,13 @@ func TestFunctionsConnectorHandler(t *testing.T) { // first call to trigger the request var response functions.HeartbeatResponse allowlist.On("Allow", addr).Return(true).Once() - listener.On("HandleOffchainRequest", mock.Anything, mock.Anything).Return(errors.New("boom")).Once() + handlerCalled := make(chan struct{}) + listener.On("HandleOffchainRequest", mock.Anything, mock.Anything).Run(func(args mock.Arguments) { + handlerCalled <- struct{}{} + }).Return(errors.New("boom")).Once() connector.On("SendToGateway", mock.Anything, "gw1", mock.Anything).Return(nil).Once() handler.HandleGatewayMessage(ctx, "gw1", msg) + <-handlerCalled // collect the response - should eventually result in an internal error gomega.NewGomegaWithT(t).Eventually(func() bool { From 2b099563f00070fece1aa8fc23a95b23e091f567 Mon Sep 17 00:00:00 2001 From: Bartek Tofel Date: Tue, 23 Jul 2024 15:34:03 +0200 Subject: [PATCH 005/115] fail explicitly if base_ref is empty in PR/MQ (#13910) --- .github/workflows/client-compatibility-tests.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/client-compatibility-tests.yml b/.github/workflows/client-compatibility-tests.yml index b204c79d2d..956da46e77 100644 --- a/.github/workflows/client-compatibility-tests.yml +++ b/.github/workflows/client-compatibility-tests.yml @@ -54,6 +54,12 @@ jobs: - name: Check for go.mod changes id: changes run: | + if [ -z "${{ github.base_ref }}" ]; then + echo "No base branch found, this should not happen in a PR or MQ. Please reach out to the Test Tooling team." + echo "Github even that triggered the workflow: $GITHUB_EVENT_NAME" + echo "Github ref that triggered the workflow: $GITHUB_REF" + exit 1 + fi git fetch origin ${{ github.base_ref }} # if no match is found then grep exits with code 1, but if there is a match it exits with code 0 # this will return a match if there are any changes on that corresponding line, for example if spacing was changed From 780d304f6bcc041f86c39303f8ebb82f87d70066 Mon Sep 17 00:00:00 2001 From: chainchad <96362174+chainchad@users.noreply.github.com> Date: Tue, 23 Jul 2024 09:56:28 -0400 Subject: [PATCH 006/115] Notify slack on new (pre)release tags (#13914) * Notify slack on new release tags and release branches * Add changelog url * Use released version of action * Only notify slack on tags --- .../build-sign-publish-chainlink/action.yml | 10 ++++ .github/workflows/build-publish.yml | 51 +++++++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/.github/actions/build-sign-publish-chainlink/action.yml b/.github/actions/build-sign-publish-chainlink/action.yml index b5bb725098..b992edfbf7 100644 --- a/.github/actions/build-sign-publish-chainlink/action.yml +++ b/.github/actions/build-sign-publish-chainlink/action.yml @@ -68,6 +68,13 @@ inputs: description: When set to the string boolean value of "true", the resulting build image signature will be verified default: "false" required: false +outputs: + docker-image-tag: + description: The docker image tag that was built and pushed + value: ${{ steps.save-non-root-image-name-env.outputs.image-tag }} + docker-image-digest: + description: The docker image digest that was built and pushed + value: ${{ steps.save-non-root-image-name-env.outputs.image-digest }} runs: using: composite @@ -208,10 +215,13 @@ runs: IMAGES_NAME_RAW=${{ fromJSON(steps.buildpush-nonroot.outputs.metadata)['image.name'] }} IMAGE_DIGEST=${{ fromJSON(steps.buildpush-nonroot.outputs.metadata)['containerimage.digest'] }} IMAGE_NAME=$(echo "$IMAGES_NAME_RAW" | cut -d"," -f1) + IMAGE_TAG=$(echo "$IMAGES_NAME_RAW" | cut -d":" -f2) echo "nonroot_image_name=${IMAGE_NAME}" >> $GITHUB_ENV echo '### Docker Image' >> $GITHUB_STEP_SUMMARY echo "Image Name: ${IMAGE_NAME}" >> $GITHUB_STEP_SUMMARY echo "Image Digest: ${IMAGE_DIGEST}" >> $GITHUB_STEP_SUMMARY + echo "image-tag=${IMAGE_TAG}" >> $GITHUB_OUTPUT + echo "image-digest=${IMAGE_DIGEST}" >> $GITHUB_OUTPUT - name: Check if non-root image runs as root id: check-nonroot-runs-root diff --git a/.github/workflows/build-publish.yml b/.github/workflows/build-publish.yml index ef0f641db1..d692285f68 100644 --- a/.github/workflows/build-publish.yml +++ b/.github/workflows/build-publish.yml @@ -8,6 +8,10 @@ on: branches: - "release/**" +env: + ECR_HOSTNAME: public.ecr.aws + ECR_IMAGE_NAME: chainlink/chainlink + jobs: checks: name: "Checks" @@ -30,17 +34,23 @@ jobs: permissions: id-token: write contents: read + outputs: + docker-image-tag: ${{ steps.build-sign-publish.outputs.docker-image-tag }} + docker-image-digest: ${{ steps.build-sign-publish.outputs.docker-image-digest }} steps: - name: Checkout repository uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - name: Build, sign and publish chainlink image + id: build-sign-publish uses: ./.github/actions/build-sign-publish-chainlink with: publish: true aws-role-to-assume: ${{ secrets.AWS_OIDC_IAM_ROLE_ARN }} aws-role-duration-seconds: ${{ secrets.AWS_ROLE_DURATION_SECONDS }} aws-region: ${{ secrets.AWS_REGION }} + ecr-hostname: ${{ env.ECR_HOSTNAME }} + ecr-image-name: ${{ env.ECR_IMAGE_NAME }} sign-images: true sign-method: "keypair" cosign-private-key: ${{ secrets.COSIGN_PRIVATE_KEY }} @@ -60,3 +70,44 @@ jobs: hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} this-job-name: build-sign-publish-chainlink continue-on-error: true + + # Notify Slack channel for new git tags. + slack-notify: + if: github.ref_type == 'tag' + needs: [build-sign-publish-chainlink] + runs-on: ubuntu-24.04 + environment: build-publish + steps: + - name: Checkout repository + uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + - name: Notify Slack + uses: smartcontractkit/.github/actions/slack-notify-git-ref@7fa90bbeff35aa6ce3a9054f542bcf10b7d47cec # slack-notify-git-ref@0.1.0 + with: + slack-channel-id: ${{ secrets.SLACK_CHANNEL_RELEASE_NOTIFICATIONS }} + slack-bot-token: ${{ secrets.SLACK_BOT_TOKEN_RELENG }} # Releng Bot + git-ref: ${{ github.ref_name }} + git-ref-type: ${{ github.ref_type }} + changelog-url: >- + ${{ + github.ref_type == 'tag' && + format( + 'https://github.com/{0}/blob/{1}/CHANGELOG.md', + github.repository, + github.ref_name, + ) || '' + }} + docker-image-name: >- + ${{ + github.ref_type == 'tag' && + format( + '{0}/{1}:{2}', + env.ECR_HOSTNAME, + env.ECR_IMAGE_NAME, + needs.build-sign-publish-chainlink.outputs.docker-image-tag + ) || '' + }} + docker-image-digest: >- + ${{ + github.ref_type == 'tag' && + needs.build-sign-publish-chainlink.outputs.docker-image-digest || '' + }} From c5224df52f9daf8ff219628b9d73f8e49166d703 Mon Sep 17 00:00:00 2001 From: Matthew Pendrey Date: Wed, 24 Jul 2024 11:24:11 +0100 Subject: [PATCH 007/115] add startonce protection to syncer (#13917) --- .changeset/friendly-needles-ring.md | 5 +++++ core/services/registrysyncer/syncer.go | 23 ++++++++++++++--------- 2 files changed, 19 insertions(+), 9 deletions(-) create mode 100644 .changeset/friendly-needles-ring.md diff --git a/.changeset/friendly-needles-ring.md b/.changeset/friendly-needles-ring.md new file mode 100644 index 0000000000..8f98047e0f --- /dev/null +++ b/.changeset/friendly-needles-ring.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#internal syncer start onc3 diff --git a/core/services/registrysyncer/syncer.go b/core/services/registrysyncer/syncer.go index f3c254af6d..d4f5b0e02d 100644 --- a/core/services/registrysyncer/syncer.go +++ b/core/services/registrysyncer/syncer.go @@ -36,6 +36,7 @@ type Syncer interface { } type registrySyncer struct { + services.StateMachine stopCh services.StopChan launchers []Launcher reader types.ContractReader @@ -118,12 +119,14 @@ func newReader(ctx context.Context, lggr logger.Logger, relayer contractReaderFa } func (s *registrySyncer) Start(ctx context.Context) error { - s.wg.Add(1) - go func() { - defer s.wg.Done() - s.syncLoop() - }() - return nil + return s.StartOnce("testAsyncMessageBroker", func() error { + s.wg.Add(1) + go func() { + defer s.wg.Done() + s.syncLoop() + }() + return nil + }) } func (s *registrySyncer) syncLoop() { @@ -232,9 +235,11 @@ func (s *registrySyncer) AddLauncher(launchers ...Launcher) { } func (s *registrySyncer) Close() error { - close(s.stopCh) - s.wg.Wait() - return nil + return s.StopOnce("testAsyncMessageBroker", func() error { + close(s.stopCh) + s.wg.Wait() + return nil + }) } func (s *registrySyncer) Ready() error { From d777fd8e7fda447c7a60703564d6a703215382e6 Mon Sep 17 00:00:00 2001 From: Cedric Date: Wed, 24 Jul 2024 13:17:52 +0100 Subject: [PATCH 008/115] [KS-370] Pass config from onchain registry to execute calls (#13750) * [KS-370] Add ConfigForCapability to registry - This allows us to set some config inside the registry without needing to specify it on the capability registry * Update common * Update PR * Linting * Rename ExecuteConfig -> DefaultConfig * Add IsLocal to CapabilityInfo * Minor review feedback; rename GetLocalNode -> LocalNode * More comments * Remote CapabilityID type * Stop coercing capability.ID since it's already a string * Update common * Linting / Go generate * Update common * Update common --- core/capabilities/launcher.go | 207 +++------ core/capabilities/launcher_test.go | 408 +++++++----------- core/capabilities/registry.go | 36 +- core/capabilities/remote/dispatcher_test.go | 3 +- core/capabilities/remote/trigger_publisher.go | 10 +- .../remote/trigger_publisher_test.go | 10 +- .../capabilities/remote/trigger_subscriber.go | 14 +- .../remote/trigger_subscriber_test.go | 10 +- core/capabilities/remote/types/config.go | 21 - core/capabilities/remote/types/messages.pb.go | 139 +----- core/capabilities/remote/types/messages.proto | 7 - core/capabilities/streams/trigger_test.go | 2 +- core/scripts/go.mod | 50 +-- core/scripts/go.sum | 100 ++--- ...deploy_initialize_capabilities_registry.go | 21 +- core/services/chainlink/application.go | 8 +- .../services/registrysyncer/local_registry.go | 85 ++++ core/services/registrysyncer/syncer.go | 133 ++++-- core/services/registrysyncer/syncer_test.go | 187 ++++++-- .../relay/evm/mercury/wsrpc/pb/mercury.pb.go | 16 +- core/services/workflows/delegate.go | 12 +- core/services/workflows/engine.go | 61 ++- core/services/workflows/engine_test.go | 132 +++++- core/services/workflows/models.go | 1 + go.mod | 50 +-- go.sum | 100 ++--- integration-tests/go.mod | 32 +- integration-tests/go.sum | 69 +-- integration-tests/load/go.mod | 32 +- integration-tests/load/go.sum | 69 +-- 30 files changed, 1084 insertions(+), 941 deletions(-) delete mode 100644 core/capabilities/remote/types/config.go create mode 100644 core/services/registrysyncer/local_registry.go diff --git a/core/capabilities/launcher.go b/core/capabilities/launcher.go index 267e32055e..b4ade04127 100644 --- a/core/capabilities/launcher.go +++ b/core/capabilities/launcher.go @@ -7,12 +7,9 @@ import ( "strings" "time" - "google.golang.org/protobuf/proto" - "github.com/smartcontractkit/chainlink-common/pkg/capabilities" "github.com/smartcontractkit/chainlink-common/pkg/capabilities/triggers" "github.com/smartcontractkit/chainlink-common/pkg/services" - "github.com/smartcontractkit/chainlink-common/pkg/types/core" "github.com/smartcontractkit/libocr/ragep2p" ragetypes "github.com/smartcontractkit/libocr/ragep2p/types" @@ -21,7 +18,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/target" remotetypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/types" "github.com/smartcontractkit/chainlink/v2/core/capabilities/streams" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" "github.com/smartcontractkit/chainlink/v2/core/logger" p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" "github.com/smartcontractkit/chainlink/v2/core/services/registrysyncer" @@ -46,8 +42,7 @@ type launcher struct { lggr logger.Logger peerWrapper p2ptypes.PeerWrapper dispatcher remotetypes.Dispatcher - registry core.CapabilitiesRegistry - localNode capabilities.Node + registry *Registry subServices []services.Service } @@ -55,7 +50,7 @@ func NewLauncher( lggr logger.Logger, peerWrapper p2ptypes.PeerWrapper, dispatcher remotetypes.Dispatcher, - registry core.CapabilitiesRegistry, + registry *Registry, ) *launcher { return &launcher{ lggr: lggr.Named("CapabilitiesLauncher"), @@ -92,50 +87,8 @@ func (w *launcher) Name() string { return "CapabilitiesLauncher" } -func (w *launcher) LocalNode(ctx context.Context) (capabilities.Node, error) { - if w.peerWrapper.GetPeer() == nil { - return w.localNode, errors.New("unable to get local node: peerWrapper hasn't started yet") - } - - if w.localNode.WorkflowDON.ID == 0 { - return w.localNode, errors.New("unable to get local node: waiting for initial call from syncer") - } - - return w.localNode, nil -} - -func (w *launcher) updateLocalNode(state registrysyncer.State) { - pid := w.peerWrapper.GetPeer().ID() - - var workflowDON capabilities.DON - capabilityDONs := []capabilities.DON{} - for _, d := range state.IDsToDONs { - for _, p := range d.NodeP2PIds { - if p == pid { - if d.AcceptsWorkflows { - if workflowDON.ID == 0 { - workflowDON = *toDONInfo(d) - w.lggr.Debug("Workflow DON identified: %+v", workflowDON) - } else { - w.lggr.Errorf("Configuration error: node %s belongs to more than one workflowDON", pid) - } - } - - capabilityDONs = append(capabilityDONs, *toDONInfo(d)) - } - } - } - - w.localNode = capabilities.Node{ - PeerID: &pid, - WorkflowDON: workflowDON, - CapabilityDONs: capabilityDONs, - } -} - -func (w *launcher) Launch(ctx context.Context, state registrysyncer.State) error { - w.lggr.Debugw("running capabilities launcher", "state", state) - w.updateLocalNode(state) +func (w *launcher) Launch(ctx context.Context, state *registrysyncer.LocalRegistry) error { + w.registry.SetLocalRegistry(state) // Let's start by updating the list of Peers // We do this by creating a new entry for each node belonging @@ -143,15 +96,15 @@ func (w *launcher) Launch(ctx context.Context, state registrysyncer.State) error // We also add the hardcoded peers determined by the NetworkSetup. allPeers := make(map[ragetypes.PeerID]p2ptypes.StreamConfig) - publicDONs := []kcr.CapabilitiesRegistryDONInfo{} + publicDONs := []registrysyncer.DON{} for _, d := range state.IDsToDONs { - if !d.IsPublic { + if !d.DON.IsPublic { continue } publicDONs = append(publicDONs, d) - for _, nid := range d.NodeP2PIds { + for _, nid := range d.DON.Members { allPeers[nid] = defaultStreamConfig } } @@ -171,18 +124,18 @@ func (w *launcher) Launch(ctx context.Context, state registrysyncer.State) error // We'll also construct a set to record what DONs the current node is a part of, // regardless of any modifiers (public/acceptsWorkflows etc). myID := w.peerWrapper.GetPeer().ID() - myWorkflowDONs := []kcr.CapabilitiesRegistryDONInfo{} - remoteWorkflowDONs := []kcr.CapabilitiesRegistryDONInfo{} + myWorkflowDONs := []registrysyncer.DON{} + remoteWorkflowDONs := []registrysyncer.DON{} myDONs := map[uint32]bool{} for _, d := range state.IDsToDONs { - for _, peerID := range d.NodeP2PIds { + for _, peerID := range d.Members { if peerID == myID { - myDONs[d.Id] = true + myDONs[d.ID] = true } } if d.AcceptsWorkflows { - if myDONs[d.Id] { + if myDONs[d.ID] { myWorkflowDONs = append(myWorkflowDONs, d) } else { remoteWorkflowDONs = append(remoteWorkflowDONs, d) @@ -192,11 +145,11 @@ func (w *launcher) Launch(ctx context.Context, state registrysyncer.State) error // - remote capability DONs (with IsPublic = true) the current node is a part of. // These need server-side shims. - myCapabilityDONs := []kcr.CapabilitiesRegistryDONInfo{} - remoteCapabilityDONs := []kcr.CapabilitiesRegistryDONInfo{} + myCapabilityDONs := []registrysyncer.DON{} + remoteCapabilityDONs := []registrysyncer.DON{} for _, d := range publicDONs { if len(d.CapabilityConfigurations) > 0 { - if myDONs[d.Id] { + if myDONs[d.ID] { myCapabilityDONs = append(myCapabilityDONs, d) } else { remoteCapabilityDONs = append(remoteCapabilityDONs, d) @@ -236,14 +189,14 @@ func (w *launcher) Launch(ctx context.Context, state registrysyncer.State) error return nil } -func (w *launcher) addRemoteCapabilities(ctx context.Context, myDON kcr.CapabilitiesRegistryDONInfo, remoteDON kcr.CapabilitiesRegistryDONInfo, state registrysyncer.State) error { - for _, c := range remoteDON.CapabilityConfigurations { - capability, ok := state.IDsToCapabilities[c.CapabilityId] +func (w *launcher) addRemoteCapabilities(ctx context.Context, myDON registrysyncer.DON, remoteDON registrysyncer.DON, state *registrysyncer.LocalRegistry) error { + for cid, c := range remoteDON.CapabilityConfigurations { + capability, ok := state.IDsToCapabilities[cid] if !ok { - return fmt.Errorf("could not find capability matching id %s", c.CapabilityId) + return fmt.Errorf("could not find capability matching id %s", cid) } - switch toCapabilityType(capability.CapabilityType) { + switch capability.CapabilityType { case capabilities.CapabilityTypeTrigger: newTriggerFn := func(info capabilities.CapabilityInfo) (capabilityService, error) { if !strings.HasPrefix(info.ID, "streams-trigger") { @@ -263,12 +216,6 @@ func (w *launcher) addRemoteCapabilities(ctx context.Context, myDON kcr.Capabili int(remoteDON.F+1), w.lggr, ) - cfg := &remotetypes.RemoteTriggerConfig{} - cfg.ApplyDefaults() - err = proto.Unmarshal(c.Config, cfg) - if err != nil { - return nil, err - } // TODO: We need to implement a custom, Mercury-specific // aggregator here, because there is no guarantee that // all trigger events in the workflow will have the same @@ -276,10 +223,10 @@ func (w *launcher) addRemoteCapabilities(ctx context.Context, myDON kcr.Capabili // When this is solved, we can move to a generic aggregator // and remove this. triggerCap := remote.NewTriggerSubscriber( - cfg, + c.RemoteTriggerConfig, info, - *toDONInfo(remoteDON), - *toDONInfo(myDON), + remoteDON.DON, + myDON.DON, w.dispatcher, aggregator, w.lggr, @@ -298,7 +245,7 @@ func (w *launcher) addRemoteCapabilities(ctx context.Context, myDON kcr.Capabili newTargetFn := func(info capabilities.CapabilityInfo) (capabilityService, error) { client := target.NewClient( info, - *toDONInfo(myDON), + myDON.DON, w.dispatcher, defaultTargetRequestTimeout, w.lggr, @@ -323,24 +270,24 @@ type capabilityService interface { services.Service } -func (w *launcher) addToRegistryAndSetDispatcher(ctx context.Context, capabilityInfo kcr.CapabilitiesRegistryCapabilityInfo, don kcr.CapabilitiesRegistryDONInfo, newCapFn func(info capabilities.CapabilityInfo) (capabilityService, error)) error { - fullCapID := fmt.Sprintf("%s@%s", capabilityInfo.LabelledName, capabilityInfo.Version) +func (w *launcher) addToRegistryAndSetDispatcher(ctx context.Context, capability registrysyncer.Capability, don registrysyncer.DON, newCapFn func(info capabilities.CapabilityInfo) (capabilityService, error)) error { + capabilityID := capability.ID info, err := capabilities.NewRemoteCapabilityInfo( - fullCapID, - toCapabilityType(capabilityInfo.CapabilityType), - fmt.Sprintf("Remote Capability for %s", fullCapID), - toDONInfo(don), + capabilityID, + capability.CapabilityType, + fmt.Sprintf("Remote Capability for %s", capabilityID), + &don.DON, ) if err != nil { return fmt.Errorf("failed to create remote capability info: %w", err) } w.lggr.Debugw("Adding remote capability to registry", "id", info.ID, "don", info.DON) - capability, err := newCapFn(info) + cp, err := newCapFn(info) if err != nil { return fmt.Errorf("failed to instantiate capability: %w", err) } - err = w.registry.Add(ctx, capability) + err = w.registry.Add(ctx, cp) if err != nil { // If the capability already exists, then it's either local // or we've handled this in a previous syncer iteration, @@ -353,19 +300,19 @@ func (w *launcher) addToRegistryAndSetDispatcher(ctx context.Context, capability } err = w.dispatcher.SetReceiver( - fullCapID, - don.Id, - capability, + capabilityID, + don.ID, + cp, ) if err != nil { return err } - w.lggr.Debugw("Setting receiver for capability", "id", fullCapID, "donID", don.Id) - err = capability.Start(ctx) + w.lggr.Debugw("Setting receiver for capability", "id", capabilityID, "donID", don.ID) + err = cp.Start(ctx) if err != nil { return fmt.Errorf("failed to start capability: %w", err) } - w.subServices = append(w.subServices, capability) + w.subServices = append(w.subServices, cp) return nil } @@ -373,32 +320,26 @@ var ( defaultTargetRequestTimeout = time.Minute ) -func (w *launcher) exposeCapabilities(ctx context.Context, myPeerID p2ptypes.PeerID, don kcr.CapabilitiesRegistryDONInfo, state registrysyncer.State, remoteWorkflowDONs []kcr.CapabilitiesRegistryDONInfo) error { +func (w *launcher) exposeCapabilities(ctx context.Context, myPeerID p2ptypes.PeerID, don registrysyncer.DON, state *registrysyncer.LocalRegistry, remoteWorkflowDONs []registrysyncer.DON) error { idsToDONs := map[uint32]capabilities.DON{} for _, d := range remoteWorkflowDONs { - idsToDONs[d.Id] = *toDONInfo(d) + idsToDONs[d.ID] = d.DON } - for _, c := range don.CapabilityConfigurations { - capability, ok := state.IDsToCapabilities[c.CapabilityId] + for cid, c := range don.CapabilityConfigurations { + capability, ok := state.IDsToCapabilities[cid] if !ok { - return fmt.Errorf("could not find capability matching id %s", c.CapabilityId) + return fmt.Errorf("could not find capability matching id %s", cid) } - switch toCapabilityType(capability.CapabilityType) { + switch capability.CapabilityType { case capabilities.CapabilityTypeTrigger: newTriggerPublisher := func(capability capabilities.BaseCapability, info capabilities.CapabilityInfo) (receiverService, error) { - cfg := &remotetypes.RemoteTriggerConfig{} - cfg.ApplyDefaults() - err := proto.Unmarshal(c.Config, cfg) - if err != nil { - return nil, err - } publisher := remote.NewTriggerPublisher( - cfg, + c.RemoteTriggerConfig, capability.(capabilities.TriggerCapability), info, - *toDONInfo(don), + don.DON, idsToDONs, w.dispatcher, w.lggr, @@ -420,7 +361,7 @@ func (w *launcher) exposeCapabilities(ctx context.Context, myPeerID p2ptypes.Pee myPeerID, capability.(capabilities.TargetCapability), info, - *toDONInfo(don), + don.DON, idsToDONs, w.dispatcher, defaultTargetRequestTimeout, @@ -444,18 +385,18 @@ type receiverService interface { remotetypes.Receiver } -func (w *launcher) addReceiver(ctx context.Context, capability kcr.CapabilitiesRegistryCapabilityInfo, don kcr.CapabilitiesRegistryDONInfo, newReceiverFn func(capability capabilities.BaseCapability, info capabilities.CapabilityInfo) (receiverService, error)) error { - fullCapID := fmt.Sprintf("%s@%s", capability.LabelledName, capability.Version) +func (w *launcher) addReceiver(ctx context.Context, capability registrysyncer.Capability, don registrysyncer.DON, newReceiverFn func(capability capabilities.BaseCapability, info capabilities.CapabilityInfo) (receiverService, error)) error { + capID := capability.ID info, err := capabilities.NewRemoteCapabilityInfo( - fullCapID, - toCapabilityType(capability.CapabilityType), - fmt.Sprintf("Remote Capability for %s", fullCapID), - toDONInfo(don), + capID, + capability.CapabilityType, + fmt.Sprintf("Remote Capability for %s", capability.ID), + &don.DON, ) if err != nil { return fmt.Errorf("failed to instantiate remote capability for receiver: %w", err) } - underlying, err := w.registry.Get(ctx, fullCapID) + underlying, err := w.registry.Get(ctx, capability.ID) if err != nil { return fmt.Errorf("failed to get capability from registry: %w", err) } @@ -465,12 +406,12 @@ func (w *launcher) addReceiver(ctx context.Context, capability kcr.CapabilitiesR return fmt.Errorf("failed to instantiate receiver: %w", err) } - w.lggr.Debugw("Enabling external access for capability", "id", fullCapID, "donID", don.Id) - err = w.dispatcher.SetReceiver(fullCapID, don.Id, receiver) + w.lggr.Debugw("Enabling external access for capability", "id", capID, "donID", don.ID) + err = w.dispatcher.SetReceiver(capID, don.ID, receiver) if errors.Is(err, remote.ErrReceiverExists) { // If a receiver already exists, let's log the error for debug purposes, but // otherwise short-circuit here. We've handled this capability in a previous iteration. - w.lggr.Debugf("receiver already exists for cap ID %s and don ID %d: %s", fullCapID, don.Id, err) + w.lggr.Debugf("receiver already exists for cap ID %s and don ID %d: %s", capID, don.ID, err) return nil } else if err != nil { return fmt.Errorf("failed to set receiver: %w", err) @@ -485,9 +426,9 @@ func (w *launcher) addReceiver(ctx context.Context, capability kcr.CapabilitiesR return nil } -func signersFor(don kcr.CapabilitiesRegistryDONInfo, state registrysyncer.State) ([][]byte, error) { +func signersFor(don registrysyncer.DON, state *registrysyncer.LocalRegistry) ([][]byte, error) { s := [][]byte{} - for _, nodeID := range don.NodeP2PIds { + for _, nodeID := range don.Members { node, ok := state.IDsToNodes[nodeID] if !ok { return nil, fmt.Errorf("could not find node for id %s", nodeID) @@ -500,33 +441,3 @@ func signersFor(don kcr.CapabilitiesRegistryDONInfo, state registrysyncer.State) return s, nil } - -func toDONInfo(don kcr.CapabilitiesRegistryDONInfo) *capabilities.DON { - peerIDs := []p2ptypes.PeerID{} - for _, p := range don.NodeP2PIds { - peerIDs = append(peerIDs, p) - } - - return &capabilities.DON{ - ID: don.Id, - ConfigVersion: don.ConfigCount, - Members: peerIDs, - F: don.F, - } -} - -func toCapabilityType(capabilityType uint8) capabilities.CapabilityType { - switch capabilityType { - case 0: - return capabilities.CapabilityTypeTrigger - case 1: - return capabilities.CapabilityTypeAction - case 2: - return capabilities.CapabilityTypeConsensus - case 3: - return capabilities.CapabilityTypeTarget - default: - // Not found - return capabilities.CapabilityType(-1) - } -} diff --git a/core/capabilities/launcher_test.go b/core/capabilities/launcher_test.go index d314be6069..fb3e6837d0 100644 --- a/core/capabilities/launcher_test.go +++ b/core/capabilities/launcher_test.go @@ -78,7 +78,7 @@ func TestLauncher_WiresUpExternalCapabilities(t *testing.T) { wrapper := mocks.NewPeerWrapper(t) wrapper.On("GetPeer").Return(peer) - nodes := [][32]byte{ + nodes := []ragetypes.PeerID{ pid, randomWord(), randomWord(), @@ -110,37 +110,31 @@ func TestLauncher_WiresUpExternalCapabilities(t *testing.T) { // which exposes the streams-trigger and write_chain capabilities. // We expect a publisher to be wired up with this configuration, and // no entries should be added to the registry. - state := registrysyncer.State{ - IDsToDONs: map[registrysyncer.DonID]kcr.CapabilitiesRegistryDONInfo{ + state := ®istrysyncer.LocalRegistry{ + IDsToDONs: map[registrysyncer.DonID]registrysyncer.DON{ registrysyncer.DonID(dID): { - Id: dID, - ConfigCount: uint32(0), - F: uint8(1), - IsPublic: true, - AcceptsWorkflows: true, - NodeP2PIds: nodes, - CapabilityConfigurations: []kcr.CapabilitiesRegistryCapabilityConfiguration{ - { - CapabilityId: triggerCapID, - Config: []byte(""), - }, - { - CapabilityId: targetCapID, - Config: []byte(""), - }, + DON: capabilities.DON{ + ID: dID, + ConfigVersion: uint32(0), + F: uint8(1), + IsPublic: true, + AcceptsWorkflows: true, + Members: nodes, + }, + CapabilityConfigurations: map[string]capabilities.CapabilityConfiguration{ + fullTriggerCapID: {}, + fullTargetID: {}, }, }, }, - IDsToCapabilities: map[registrysyncer.HashedCapabilityID]kcr.CapabilitiesRegistryCapabilityInfo{ - triggerCapID: { - LabelledName: "streams-trigger", - Version: "1.0.0", - CapabilityType: 0, + IDsToCapabilities: map[string]registrysyncer.Capability{ + fullTriggerCapID: { + ID: "streams-trigger@1.0.0", + CapabilityType: capabilities.CapabilityTypeTrigger, }, - targetCapID: { - LabelledName: "write-chain_evm_1", - Version: "1.0.0", - CapabilityType: 3, + fullTargetID: { + ID: "write-chain_evm_1@1.0.0", + CapabilityType: capabilities.CapabilityTypeTarget, }, }, IDsToNodes: map[p2ptypes.PeerID]kcr.CapabilitiesRegistryNodeInfo{ @@ -201,51 +195,48 @@ func TestSyncer_IgnoresCapabilitiesForPrivateDON(t *testing.T) { wrapper := mocks.NewPeerWrapper(t) wrapper.On("GetPeer").Return(peer) - nodes := [][32]byte{ + nodes := []ragetypes.PeerID{ pid, randomWord(), randomWord(), randomWord(), } - triggerCapID := randomWord() - targetCapID := randomWord() dID := uint32(1) + triggerID := "streams-trigger@1.0.0" + hashedTriggerID := randomWord() + targetID := "write-chain_evm_1@1.0.0" + hashedTargetID := randomWord() + // The below state describes a Workflow DON (AcceptsWorkflows = true), // which isn't public (IsPublic = false), but hosts the // the streams-trigger and write_chain capabilities. // We expect no action to be taken by the syncer. - state := registrysyncer.State{ - IDsToDONs: map[registrysyncer.DonID]kcr.CapabilitiesRegistryDONInfo{ + state := ®istrysyncer.LocalRegistry{ + IDsToDONs: map[registrysyncer.DonID]registrysyncer.DON{ registrysyncer.DonID(dID): { - Id: dID, - ConfigCount: uint32(0), - F: uint8(1), - IsPublic: false, - AcceptsWorkflows: true, - NodeP2PIds: nodes, - CapabilityConfigurations: []kcr.CapabilitiesRegistryCapabilityConfiguration{ - { - CapabilityId: triggerCapID, - Config: []byte(""), - }, - { - CapabilityId: targetCapID, - Config: []byte(""), - }, + DON: capabilities.DON{ + ID: dID, + ConfigVersion: uint32(0), + F: uint8(1), + IsPublic: false, + AcceptsWorkflows: true, + Members: nodes, + }, + CapabilityConfigurations: map[string]capabilities.CapabilityConfiguration{ + triggerID: {}, + targetID: {}, }, }, }, - IDsToCapabilities: map[registrysyncer.HashedCapabilityID]kcr.CapabilitiesRegistryCapabilityInfo{ - triggerCapID: { - LabelledName: "streams-trigger", - Version: "1.0.0", - CapabilityType: 0, + IDsToCapabilities: map[string]registrysyncer.Capability{ + triggerID: { + ID: triggerID, + CapabilityType: capabilities.CapabilityTypeTrigger, }, - targetCapID: { - LabelledName: "write-chain_evm_1", - Version: "1.0.0", - CapabilityType: 3, + targetID: { + ID: targetID, + CapabilityType: capabilities.CapabilityTypeTarget, }, }, IDsToNodes: map[p2ptypes.PeerID]kcr.CapabilitiesRegistryNodeInfo{ @@ -253,25 +244,25 @@ func TestSyncer_IgnoresCapabilitiesForPrivateDON(t *testing.T) { NodeOperatorId: 1, Signer: randomWord(), P2pId: nodes[0], - HashedCapabilityIds: [][32]byte{triggerCapID, targetCapID}, + HashedCapabilityIds: [][32]byte{hashedTriggerID, hashedTargetID}, }, nodes[1]: { NodeOperatorId: 1, Signer: randomWord(), P2pId: nodes[1], - HashedCapabilityIds: [][32]byte{triggerCapID, targetCapID}, + HashedCapabilityIds: [][32]byte{hashedTriggerID, hashedTargetID}, }, nodes[2]: { NodeOperatorId: 1, Signer: randomWord(), P2pId: nodes[2], - HashedCapabilityIds: [][32]byte{triggerCapID, targetCapID}, + HashedCapabilityIds: [][32]byte{hashedTriggerID, hashedTargetID}, }, nodes[3]: { NodeOperatorId: 1, Signer: randomWord(), P2pId: nodes[3], - HashedCapabilityIds: [][32]byte{triggerCapID, targetCapID}, + HashedCapabilityIds: [][32]byte{hashedTriggerID, hashedTargetID}, }, }, } @@ -309,14 +300,14 @@ func TestLauncher_WiresUpClientsForPublicWorkflowDON(t *testing.T) { wrapper := mocks.NewPeerWrapper(t) wrapper.On("GetPeer").Return(peer) - workflowDonNodes := [][32]byte{ + workflowDonNodes := []ragetypes.PeerID{ pid, randomWord(), randomWord(), randomWord(), } - capabilityDonNodes := [][32]byte{ + capabilityDonNodes := []ragetypes.PeerID{ randomWord(), randomWord(), randomWord(), @@ -332,45 +323,48 @@ func TestLauncher_WiresUpClientsForPublicWorkflowDON(t *testing.T) { // The below state describes a Workflow DON (AcceptsWorkflows = true), // which exposes the streams-trigger and write_chain capabilities. // We expect receivers to be wired up and both capabilities to be added to the registry. - state := registrysyncer.State{ - IDsToDONs: map[registrysyncer.DonID]kcr.CapabilitiesRegistryDONInfo{ + var rtc capabilities.RemoteTriggerConfig + rtc.ApplyDefaults() + + state := ®istrysyncer.LocalRegistry{ + IDsToDONs: map[registrysyncer.DonID]registrysyncer.DON{ registrysyncer.DonID(dID): { - Id: dID, - ConfigCount: uint32(0), - F: uint8(1), - IsPublic: true, - AcceptsWorkflows: true, - NodeP2PIds: workflowDonNodes, + DON: capabilities.DON{ + ID: dID, + ConfigVersion: uint32(0), + F: uint8(1), + IsPublic: true, + AcceptsWorkflows: true, + Members: workflowDonNodes, + }, }, registrysyncer.DonID(capDonID): { - Id: capDonID, - ConfigCount: uint32(0), - F: uint8(1), - IsPublic: true, - AcceptsWorkflows: false, - NodeP2PIds: capabilityDonNodes, - CapabilityConfigurations: []kcr.CapabilitiesRegistryCapabilityConfiguration{ - { - CapabilityId: triggerCapID, - Config: []byte(""), + DON: capabilities.DON{ + ID: capDonID, + ConfigVersion: uint32(0), + F: uint8(1), + IsPublic: true, + AcceptsWorkflows: false, + Members: capabilityDonNodes, + }, + CapabilityConfigurations: map[string]capabilities.CapabilityConfiguration{ + fullTriggerCapID: { + RemoteTriggerConfig: rtc, }, - { - CapabilityId: targetCapID, - Config: []byte(""), + fullTargetID: { + RemoteTriggerConfig: rtc, }, }, }, }, - IDsToCapabilities: map[registrysyncer.HashedCapabilityID]kcr.CapabilitiesRegistryCapabilityInfo{ - triggerCapID: { - LabelledName: "streams-trigger", - Version: "1.0.0", - CapabilityType: 0, + IDsToCapabilities: map[string]registrysyncer.Capability{ + fullTriggerCapID: { + ID: fullTriggerCapID, + CapabilityType: capabilities.CapabilityTypeTrigger, }, - targetCapID: { - LabelledName: "write-chain_evm_1", - Version: "1.0.0", - CapabilityType: 3, + fullTargetID: { + ID: fullTargetID, + CapabilityType: capabilities.CapabilityTypeTarget, }, }, IDsToNodes: map[p2ptypes.PeerID]kcr.CapabilitiesRegistryNodeInfo{ @@ -457,14 +451,14 @@ func TestLauncher_WiresUpClientsForPublicWorkflowDONButIgnoresPrivateCapabilitie wrapper := mocks.NewPeerWrapper(t) wrapper.On("GetPeer").Return(peer) - workflowDonNodes := [][32]byte{ + workflowDonNodes := []ragetypes.PeerID{ pid, randomWord(), randomWord(), randomWord(), } - capabilityDonNodes := [][32]byte{ + capabilityDonNodes := []ragetypes.PeerID{ randomWord(), randomWord(), randomWord(), @@ -472,6 +466,7 @@ func TestLauncher_WiresUpClientsForPublicWorkflowDONButIgnoresPrivateCapabilitie } fullTriggerCapID := "streams-trigger@1.0.0" + fullTargetID := "write-chain_evm_1@1.0.0" triggerCapID := randomWord() targetCapID := randomWord() dID := uint32(1) @@ -480,55 +475,53 @@ func TestLauncher_WiresUpClientsForPublicWorkflowDONButIgnoresPrivateCapabilitie // The below state describes a Workflow DON (AcceptsWorkflows = true), // which exposes the streams-trigger and write_chain capabilities. // We expect receivers to be wired up and both capabilities to be added to the registry. - state := registrysyncer.State{ - IDsToDONs: map[registrysyncer.DonID]kcr.CapabilitiesRegistryDONInfo{ + state := ®istrysyncer.LocalRegistry{ + IDsToDONs: map[registrysyncer.DonID]registrysyncer.DON{ registrysyncer.DonID(dID): { - Id: dID, - ConfigCount: uint32(0), - F: uint8(1), - IsPublic: true, - AcceptsWorkflows: true, - NodeP2PIds: workflowDonNodes, + DON: capabilities.DON{ + ID: dID, + ConfigVersion: uint32(0), + F: uint8(1), + IsPublic: true, + AcceptsWorkflows: true, + Members: workflowDonNodes, + }, }, registrysyncer.DonID(triggerCapDonID): { - Id: triggerCapDonID, - ConfigCount: uint32(0), - F: uint8(1), - IsPublic: true, - AcceptsWorkflows: false, - NodeP2PIds: capabilityDonNodes, - CapabilityConfigurations: []kcr.CapabilitiesRegistryCapabilityConfiguration{ - { - CapabilityId: triggerCapID, - Config: []byte(""), - }, + DON: capabilities.DON{ + ID: triggerCapDonID, + ConfigVersion: uint32(0), + F: uint8(1), + IsPublic: true, + AcceptsWorkflows: false, + Members: capabilityDonNodes, + }, + CapabilityConfigurations: map[string]capabilities.CapabilityConfiguration{ + fullTriggerCapID: {}, }, }, registrysyncer.DonID(targetCapDonID): { - Id: targetCapDonID, - ConfigCount: uint32(0), - F: uint8(1), - IsPublic: false, - AcceptsWorkflows: false, - NodeP2PIds: capabilityDonNodes, - CapabilityConfigurations: []kcr.CapabilitiesRegistryCapabilityConfiguration{ - { - CapabilityId: targetCapID, - Config: []byte(""), - }, + DON: capabilities.DON{ + ID: targetCapDonID, + ConfigVersion: uint32(0), + F: uint8(1), + IsPublic: false, + AcceptsWorkflows: false, + Members: capabilityDonNodes, + }, + CapabilityConfigurations: map[string]capabilities.CapabilityConfiguration{ + fullTargetID: {}, }, }, }, - IDsToCapabilities: map[registrysyncer.HashedCapabilityID]kcr.CapabilitiesRegistryCapabilityInfo{ - triggerCapID: { - LabelledName: "streams-trigger", - Version: "1.0.0", - CapabilityType: 0, + IDsToCapabilities: map[string]registrysyncer.Capability{ + fullTriggerCapID: { + ID: fullTriggerCapID, + CapabilityType: capabilities.CapabilityTypeTrigger, }, - targetCapID: { - LabelledName: "write-chain_evm_1", - Version: "1.0.0", - CapabilityType: 3, + fullTargetID: { + ID: fullTargetID, + CapabilityType: capabilities.CapabilityTypeTarget, }, }, IDsToNodes: map[p2ptypes.PeerID]kcr.CapabilitiesRegistryNodeInfo{ @@ -596,103 +589,6 @@ func TestLauncher_WiresUpClientsForPublicWorkflowDONButIgnoresPrivateCapabilitie require.NoError(t, err) } -func toPeerIDs(is [][32]byte) (out []p2ptypes.PeerID) { - for _, i := range is { - out = append(out, i) - } - - return out -} - -func TestLauncher_LocalNode(t *testing.T) { - ctx := tests.Context(t) - lggr := logger.TestLogger(t) - registry := NewRegistry(lggr) - dispatcher := remoteMocks.NewDispatcher(t) - - var pid ragetypes.PeerID - err := pid.UnmarshalText([]byte("12D3KooWBCF1XT5Wi8FzfgNCqRL76Swv8TRU3TiD4QiJm8NMNX7N")) - require.NoError(t, err) - peer := mocks.NewPeer(t) - peer.On("UpdateConnections", mock.Anything).Return(nil) - peer.On("ID").Return(pid) - wrapper := mocks.NewPeerWrapper(t) - wrapper.On("GetPeer").Return(peer) - - workflowDonNodes := [][32]byte{ - pid, - randomWord(), - randomWord(), - randomWord(), - } - - dID := uint32(1) - // The below state describes a Workflow DON (AcceptsWorkflows = true), - // which exposes the streams-trigger and write_chain capabilities. - // We expect receivers to be wired up and both capabilities to be added to the registry. - state := registrysyncer.State{ - IDsToDONs: map[registrysyncer.DonID]kcr.CapabilitiesRegistryDONInfo{ - registrysyncer.DonID(dID): { - Id: dID, - ConfigCount: uint32(2), - F: uint8(1), - IsPublic: true, - AcceptsWorkflows: true, - NodeP2PIds: workflowDonNodes, - }, - }, - IDsToNodes: map[p2ptypes.PeerID]kcr.CapabilitiesRegistryNodeInfo{ - workflowDonNodes[0]: { - NodeOperatorId: 1, - Signer: randomWord(), - P2pId: workflowDonNodes[0], - }, - workflowDonNodes[1]: { - NodeOperatorId: 1, - Signer: randomWord(), - P2pId: workflowDonNodes[1], - }, - workflowDonNodes[2]: { - NodeOperatorId: 1, - Signer: randomWord(), - P2pId: workflowDonNodes[2], - }, - workflowDonNodes[3]: { - NodeOperatorId: 1, - Signer: randomWord(), - P2pId: workflowDonNodes[3], - }, - }, - } - - launcher := NewLauncher( - lggr, - wrapper, - dispatcher, - registry, - ) - - err = launcher.Launch(ctx, state) - require.NoError(t, err) - defer launcher.Close() - - node, err := launcher.LocalNode(ctx) - require.NoError(t, err) - - don := capabilities.DON{ - ID: dID, - ConfigVersion: 2, - Members: toPeerIDs(workflowDonNodes), - F: 1, - } - expectedNode := capabilities.Node{ - PeerID: &pid, - WorkflowDON: don, - CapabilityDONs: []capabilities.DON{don}, - } - assert.Equal(t, expectedNode, node) -} - func TestLauncher_SucceedsEvenIfDispatcherAlreadyHasReceiver(t *testing.T) { ctx := tests.Context(t) lggr := logger.TestLogger(t) @@ -716,14 +612,14 @@ func TestLauncher_SucceedsEvenIfDispatcherAlreadyHasReceiver(t *testing.T) { )) require.NoError(t, registry.Add(ctx, mt)) - workflowDonNodes := [][32]byte{ + workflowDonNodes := []p2ptypes.PeerID{ randomWord(), randomWord(), randomWord(), randomWord(), } - capabilityDonNodes := [][32]byte{ + capabilityDonNodes := []p2ptypes.PeerID{ pid, randomWord(), randomWord(), @@ -736,36 +632,36 @@ func TestLauncher_SucceedsEvenIfDispatcherAlreadyHasReceiver(t *testing.T) { // The below state describes a Capability DON (AcceptsWorkflows = true), // which exposes the streams-trigger and write_chain capabilities. // We expect receivers to be wired up. - state := registrysyncer.State{ - IDsToDONs: map[registrysyncer.DonID]kcr.CapabilitiesRegistryDONInfo{ + state := ®istrysyncer.LocalRegistry{ + IDsToDONs: map[registrysyncer.DonID]registrysyncer.DON{ registrysyncer.DonID(dID): { - Id: dID, - ConfigCount: uint32(0), - F: uint8(1), - IsPublic: true, - AcceptsWorkflows: true, - NodeP2PIds: workflowDonNodes, + DON: capabilities.DON{ + ID: dID, + ConfigVersion: uint32(0), + F: uint8(1), + IsPublic: true, + AcceptsWorkflows: true, + Members: workflowDonNodes, + }, }, registrysyncer.DonID(capDonID): { - Id: capDonID, - ConfigCount: uint32(0), - F: uint8(1), - IsPublic: true, - AcceptsWorkflows: false, - NodeP2PIds: capabilityDonNodes, - CapabilityConfigurations: []kcr.CapabilitiesRegistryCapabilityConfiguration{ - { - CapabilityId: triggerCapID, - Config: []byte(""), - }, + DON: capabilities.DON{ + ID: capDonID, + ConfigVersion: uint32(0), + F: uint8(1), + IsPublic: true, + AcceptsWorkflows: false, + Members: capabilityDonNodes, + }, + CapabilityConfigurations: map[string]capabilities.CapabilityConfiguration{ + fullTriggerCapID: {}, }, }, }, - IDsToCapabilities: map[registrysyncer.HashedCapabilityID]kcr.CapabilitiesRegistryCapabilityInfo{ - triggerCapID: { - LabelledName: "streams-trigger", - Version: "1.0.0", - CapabilityType: 0, + IDsToCapabilities: map[string]registrysyncer.Capability{ + fullTriggerCapID: { + ID: fullTriggerCapID, + CapabilityType: capabilities.CapabilityTypeTrigger, }, }, IDsToNodes: map[p2ptypes.PeerID]kcr.CapabilitiesRegistryNodeInfo{ diff --git a/core/capabilities/registry.go b/core/capabilities/registry.go index 4cca25d03c..8a99450c09 100644 --- a/core/capabilities/registry.go +++ b/core/capabilities/registry.go @@ -14,16 +14,42 @@ var ( ErrCapabilityAlreadyExists = errors.New("capability already exists") ) +type metadataRegistry interface { + LocalNode(ctx context.Context) (capabilities.Node, error) + ConfigForCapability(ctx context.Context, capabilityID string, donID uint32) (capabilities.CapabilityConfiguration, error) +} + // Registry is a struct for the registry of capabilities. // Registry is safe for concurrent use. type Registry struct { - lggr logger.Logger - m map[string]capabilities.BaseCapability - mu sync.RWMutex + metadataRegistry metadataRegistry + lggr logger.Logger + m map[string]capabilities.BaseCapability + mu sync.RWMutex +} + +func (r *Registry) LocalNode(ctx context.Context) (capabilities.Node, error) { + if r.metadataRegistry == nil { + return capabilities.Node{}, errors.New("metadataRegistry information not available") + } + + return r.metadataRegistry.LocalNode(ctx) } -func (r *Registry) GetLocalNode(_ context.Context) (capabilities.Node, error) { - return capabilities.Node{}, nil +func (r *Registry) ConfigForCapability(ctx context.Context, capabilityID string, donID uint32) (capabilities.CapabilityConfiguration, error) { + if r.metadataRegistry == nil { + return capabilities.CapabilityConfiguration{}, errors.New("metadataRegistry information not available") + } + + return r.metadataRegistry.ConfigForCapability(ctx, capabilityID, donID) +} + +// SetLocalRegistry sets a local copy of the offchain registry for the registry to use. +// This is only public for testing purposes; the only production use should be from the CapabilitiesLauncher. +func (r *Registry) SetLocalRegistry(lr metadataRegistry) { + r.mu.Lock() + defer r.mu.Unlock() + r.metadataRegistry = lr } // Get gets a capability from the registry. diff --git a/core/capabilities/remote/dispatcher_test.go b/core/capabilities/remote/dispatcher_test.go index 173972375a..7ea4c2e262 100644 --- a/core/capabilities/remote/dispatcher_test.go +++ b/core/capabilities/remote/dispatcher_test.go @@ -8,13 +8,14 @@ import ( "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" - commonMocks "github.com/smartcontractkit/chainlink-common/pkg/types/core/mocks" "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote" remotetypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/types" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/logger" p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types/mocks" + + commonMocks "github.com/smartcontractkit/chainlink-common/pkg/types/core/mocks" ) type testReceiver struct { diff --git a/core/capabilities/remote/trigger_publisher.go b/core/capabilities/remote/trigger_publisher.go index 7744cfb55e..35ce41118f 100644 --- a/core/capabilities/remote/trigger_publisher.go +++ b/core/capabilities/remote/trigger_publisher.go @@ -21,7 +21,7 @@ import ( // // TriggerPublisher communicates with corresponding TriggerSubscribers on remote nodes. type triggerPublisher struct { - config *types.RemoteTriggerConfig + config capabilities.RemoteTriggerConfig underlying commoncap.TriggerCapability capInfo commoncap.CapabilityInfo capDonInfo commoncap.DON @@ -48,7 +48,7 @@ type pubRegState struct { var _ types.Receiver = &triggerPublisher{} var _ services.Service = &triggerPublisher{} -func NewTriggerPublisher(config *types.RemoteTriggerConfig, underlying commoncap.TriggerCapability, capInfo commoncap.CapabilityInfo, capDonInfo commoncap.DON, workflowDONs map[uint32]commoncap.DON, dispatcher types.Dispatcher, lggr logger.Logger) *triggerPublisher { +func NewTriggerPublisher(config capabilities.RemoteTriggerConfig, underlying commoncap.TriggerCapability, capInfo commoncap.CapabilityInfo, capDonInfo commoncap.DON, workflowDONs map[uint32]commoncap.DON, dispatcher types.Dispatcher, lggr logger.Logger) *triggerPublisher { config.ApplyDefaults() return &triggerPublisher{ config: config, @@ -97,7 +97,7 @@ func (p *triggerPublisher) Receive(_ context.Context, msg *types.MessageBody) { } // NOTE: require 2F+1 by default, introduce different strategies later (KS-76) minRequired := uint32(2*callerDon.F + 1) - ready, payloads := p.messageCache.Ready(key, minRequired, nowMs-int64(p.config.RegistrationExpiryMs), false) + ready, payloads := p.messageCache.Ready(key, minRequired, nowMs-p.config.RegistrationExpiry.Milliseconds(), false) if !ready { p.lggr.Debugw("not ready to aggregate yet", "capabilityId", p.capInfo.ID, "workflowId", req.Metadata.WorkflowID, "minRequired", minRequired) return @@ -133,7 +133,7 @@ func (p *triggerPublisher) Receive(_ context.Context, msg *types.MessageBody) { func (p *triggerPublisher) registrationCleanupLoop() { defer p.wg.Done() - ticker := time.NewTicker(time.Duration(p.config.RegistrationExpiryMs) * time.Millisecond) + ticker := time.NewTicker(p.config.RegistrationExpiry) defer ticker.Stop() for { select { @@ -144,7 +144,7 @@ func (p *triggerPublisher) registrationCleanupLoop() { p.mu.RLock() for key, req := range p.registrations { callerDon := p.workflowDONs[key.callerDonId] - ready, _ := p.messageCache.Ready(key, uint32(2*callerDon.F+1), now-int64(p.config.RegistrationExpiryMs), false) + ready, _ := p.messageCache.Ready(key, uint32(2*callerDon.F+1), now-p.config.RegistrationExpiry.Milliseconds(), false) if !ready { p.lggr.Infow("trigger registration expired", "capabilityId", p.capInfo.ID, "callerDonID", key.callerDonId, "workflowId", key.workflowId) ctx, cancel := p.stopCh.NewCtx() diff --git a/core/capabilities/remote/trigger_publisher_test.go b/core/capabilities/remote/trigger_publisher_test.go index ec38b962ce..1e3000d20c 100644 --- a/core/capabilities/remote/trigger_publisher_test.go +++ b/core/capabilities/remote/trigger_publisher_test.go @@ -3,9 +3,11 @@ package remote_test import ( "context" "testing" + "time" "github.com/stretchr/testify/require" + "github.com/smartcontractkit/chainlink-common/pkg/capabilities" commoncap "github.com/smartcontractkit/chainlink-common/pkg/capabilities" "github.com/smartcontractkit/chainlink-common/pkg/capabilities/pb" "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote" @@ -40,11 +42,11 @@ func TestTriggerPublisher_Register(t *testing.T) { } dispatcher := remoteMocks.NewDispatcher(t) - config := &remotetypes.RemoteTriggerConfig{ - RegistrationRefreshMs: 100, - RegistrationExpiryMs: 100_000, + config := capabilities.RemoteTriggerConfig{ + RegistrationRefresh: 100 * time.Millisecond, + RegistrationExpiry: 100 * time.Second, MinResponsesToAggregate: 1, - MessageExpiryMs: 100_000, + MessageExpiry: 100 * time.Second, } workflowDONs := map[uint32]commoncap.DON{ workflowDonInfo.ID: workflowDonInfo, diff --git a/core/capabilities/remote/trigger_subscriber.go b/core/capabilities/remote/trigger_subscriber.go index 28bdff9c51..0ccbf37c61 100644 --- a/core/capabilities/remote/trigger_subscriber.go +++ b/core/capabilities/remote/trigger_subscriber.go @@ -23,7 +23,7 @@ import ( // // TriggerSubscriber communicates with corresponding TriggerReceivers on remote nodes. type triggerSubscriber struct { - config *types.RemoteTriggerConfig + config capabilities.RemoteTriggerConfig capInfo commoncap.CapabilityInfo capDonInfo capabilities.DON capDonMembers map[p2ptypes.PeerID]struct{} @@ -55,7 +55,7 @@ var _ services.Service = &triggerSubscriber{} // TODO makes this configurable with a default const defaultSendChannelBufferSize = 1000 -func NewTriggerSubscriber(config *types.RemoteTriggerConfig, capInfo commoncap.CapabilityInfo, capDonInfo capabilities.DON, localDonInfo capabilities.DON, dispatcher types.Dispatcher, aggregator types.Aggregator, lggr logger.Logger) *triggerSubscriber { +func NewTriggerSubscriber(config capabilities.RemoteTriggerConfig, capInfo commoncap.CapabilityInfo, capDonInfo capabilities.DON, localDonInfo capabilities.DON, dispatcher types.Dispatcher, aggregator types.Aggregator, lggr logger.Logger) *triggerSubscriber { if aggregator == nil { lggr.Warnw("no aggregator provided, using default MODE aggregator", "capabilityId", capInfo.ID) aggregator = NewDefaultModeAggregator(uint32(capDonInfo.F + 1)) @@ -121,7 +121,7 @@ func (s *triggerSubscriber) RegisterTrigger(ctx context.Context, request commonc func (s *triggerSubscriber) registrationLoop() { defer s.wg.Done() - ticker := time.NewTicker(time.Duration(s.config.RegistrationRefreshMs) * time.Millisecond) + ticker := time.NewTicker(s.config.RegistrationRefresh) defer ticker.Stop() for { select { @@ -195,9 +195,9 @@ func (s *triggerSubscriber) Receive(_ context.Context, msg *types.MessageBody) { nowMs := time.Now().UnixMilli() s.mu.RLock() creationTs := s.messageCache.Insert(key, sender, nowMs, msg.Payload) - ready, payloads := s.messageCache.Ready(key, s.config.MinResponsesToAggregate, nowMs-int64(s.config.MessageExpiryMs), true) + ready, payloads := s.messageCache.Ready(key, s.config.MinResponsesToAggregate, nowMs-s.config.MessageExpiry.Milliseconds(), true) s.mu.RUnlock() - if nowMs-creationTs > int64(s.config.RegistrationExpiryMs) { + if nowMs-creationTs > s.config.RegistrationExpiry.Milliseconds() { s.lggr.Warnw("received trigger event for an expired ID", "triggerEventID", meta.TriggerEventId, "capabilityId", s.capInfo.ID, "workflowId", workflowId, "sender", sender) continue } @@ -219,7 +219,7 @@ func (s *triggerSubscriber) Receive(_ context.Context, msg *types.MessageBody) { func (s *triggerSubscriber) eventCleanupLoop() { defer s.wg.Done() - ticker := time.NewTicker(time.Duration(s.config.MessageExpiryMs) * time.Millisecond) + ticker := time.NewTicker(s.config.MessageExpiry) defer ticker.Stop() for { select { @@ -227,7 +227,7 @@ func (s *triggerSubscriber) eventCleanupLoop() { return case <-ticker.C: s.mu.Lock() - s.messageCache.DeleteOlderThan(time.Now().UnixMilli() - int64(s.config.MessageExpiryMs)) + s.messageCache.DeleteOlderThan(time.Now().UnixMilli() - s.config.MessageExpiry.Milliseconds()) s.mu.Unlock() } } diff --git a/core/capabilities/remote/trigger_subscriber_test.go b/core/capabilities/remote/trigger_subscriber_test.go index 782b29d41f..93e962215a 100644 --- a/core/capabilities/remote/trigger_subscriber_test.go +++ b/core/capabilities/remote/trigger_subscriber_test.go @@ -2,10 +2,12 @@ package remote_test import ( "testing" + "time" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" + "github.com/smartcontractkit/chainlink-common/pkg/capabilities" commoncap "github.com/smartcontractkit/chainlink-common/pkg/capabilities" "github.com/smartcontractkit/chainlink-common/pkg/capabilities/pb" "github.com/smartcontractkit/chainlink-common/pkg/values" @@ -61,11 +63,11 @@ func TestTriggerSubscriber_RegisterAndReceive(t *testing.T) { }) // register trigger - config := &remotetypes.RemoteTriggerConfig{ - RegistrationRefreshMs: 100, - RegistrationExpiryMs: 100, + config := capabilities.RemoteTriggerConfig{ + RegistrationRefresh: 100 * time.Millisecond, + RegistrationExpiry: 100 * time.Second, MinResponsesToAggregate: 1, - MessageExpiryMs: 100_000, + MessageExpiry: 100 * time.Second, } subscriber := remote.NewTriggerSubscriber(config, capInfo, capDonInfo, workflowDonInfo, dispatcher, nil, lggr) require.NoError(t, subscriber.Start(ctx)) diff --git a/core/capabilities/remote/types/config.go b/core/capabilities/remote/types/config.go deleted file mode 100644 index bb9e0fa434..0000000000 --- a/core/capabilities/remote/types/config.go +++ /dev/null @@ -1,21 +0,0 @@ -package types - -const ( - DefaultRegistrationRefreshMs = 30_000 - DefaultRegistrationExpiryMs = 120_000 - DefaultMessageExpiryMs = 120_000 -) - -// NOTE: consider splitting this config into values stored in Registry (KS-118) -// and values defined locally by Capability owners. -func (c *RemoteTriggerConfig) ApplyDefaults() { - if c.RegistrationRefreshMs == 0 { - c.RegistrationRefreshMs = DefaultRegistrationRefreshMs - } - if c.RegistrationExpiryMs == 0 { - c.RegistrationExpiryMs = DefaultRegistrationExpiryMs - } - if c.MessageExpiryMs == 0 { - c.MessageExpiryMs = DefaultMessageExpiryMs - } -} diff --git a/core/capabilities/remote/types/messages.pb.go b/core/capabilities/remote/types/messages.pb.go index 68d8f4a262..f5b77b5c15 100644 --- a/core/capabilities/remote/types/messages.pb.go +++ b/core/capabilities/remote/types/messages.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.34.1 +// protoc-gen-go v1.34.2 // protoc v4.25.1 // source: core/capabilities/remote/types/messages.proto @@ -413,77 +413,6 @@ func (x *TriggerEventMetadata) GetWorkflowIds() []string { return nil } -type RemoteTriggerConfig struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - RegistrationRefreshMs uint32 `protobuf:"varint,1,opt,name=registrationRefreshMs,proto3" json:"registrationRefreshMs,omitempty"` - RegistrationExpiryMs uint32 `protobuf:"varint,2,opt,name=registrationExpiryMs,proto3" json:"registrationExpiryMs,omitempty"` - MinResponsesToAggregate uint32 `protobuf:"varint,3,opt,name=minResponsesToAggregate,proto3" json:"minResponsesToAggregate,omitempty"` - MessageExpiryMs uint32 `protobuf:"varint,4,opt,name=messageExpiryMs,proto3" json:"messageExpiryMs,omitempty"` -} - -func (x *RemoteTriggerConfig) Reset() { - *x = RemoteTriggerConfig{} - if protoimpl.UnsafeEnabled { - mi := &file_core_capabilities_remote_types_messages_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *RemoteTriggerConfig) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RemoteTriggerConfig) ProtoMessage() {} - -func (x *RemoteTriggerConfig) ProtoReflect() protoreflect.Message { - mi := &file_core_capabilities_remote_types_messages_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use RemoteTriggerConfig.ProtoReflect.Descriptor instead. -func (*RemoteTriggerConfig) Descriptor() ([]byte, []int) { - return file_core_capabilities_remote_types_messages_proto_rawDescGZIP(), []int{4} -} - -func (x *RemoteTriggerConfig) GetRegistrationRefreshMs() uint32 { - if x != nil { - return x.RegistrationRefreshMs - } - return 0 -} - -func (x *RemoteTriggerConfig) GetRegistrationExpiryMs() uint32 { - if x != nil { - return x.RegistrationExpiryMs - } - return 0 -} - -func (x *RemoteTriggerConfig) GetMinResponsesToAggregate() uint32 { - if x != nil { - return x.MinResponsesToAggregate - } - return 0 -} - -func (x *RemoteTriggerConfig) GetMessageExpiryMs() uint32 { - if x != nil { - return x.MessageExpiryMs - } - return 0 -} - var File_core_capabilities_remote_types_messages_proto protoreflect.FileDescriptor var file_core_capabilities_remote_types_messages_proto_rawDesc = []byte{ @@ -543,32 +472,17 @@ var file_core_capabilities_remote_types_messages_proto_rawDesc = []byte{ 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x77, 0x6f, - 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x49, 0x64, 0x73, 0x22, 0xe3, 0x01, 0x0a, 0x13, 0x52, 0x65, - 0x6d, 0x6f, 0x74, 0x65, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x12, 0x34, 0x0a, 0x15, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x4d, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, - 0x52, 0x15, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, - 0x66, 0x72, 0x65, 0x73, 0x68, 0x4d, 0x73, 0x12, 0x32, 0x0a, 0x14, 0x72, 0x65, 0x67, 0x69, 0x73, - 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x78, 0x70, 0x69, 0x72, 0x79, 0x4d, 0x73, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x14, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x45, 0x78, 0x70, 0x69, 0x72, 0x79, 0x4d, 0x73, 0x12, 0x38, 0x0a, 0x17, 0x6d, - 0x69, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x54, 0x6f, 0x41, 0x67, 0x67, - 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x17, 0x6d, 0x69, - 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x54, 0x6f, 0x41, 0x67, 0x67, 0x72, - 0x65, 0x67, 0x61, 0x74, 0x65, 0x12, 0x28, 0x0a, 0x0f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x45, 0x78, 0x70, 0x69, 0x72, 0x79, 0x4d, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0f, - 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x45, 0x78, 0x70, 0x69, 0x72, 0x79, 0x4d, 0x73, 0x2a, - 0x76, 0x0a, 0x05, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x06, 0x0a, 0x02, 0x4f, 0x4b, 0x10, 0x00, - 0x12, 0x15, 0x0a, 0x11, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x46, - 0x41, 0x49, 0x4c, 0x45, 0x44, 0x10, 0x01, 0x12, 0x18, 0x0a, 0x14, 0x43, 0x41, 0x50, 0x41, 0x42, - 0x49, 0x4c, 0x49, 0x54, 0x59, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x46, 0x4f, 0x55, 0x4e, 0x44, 0x10, - 0x02, 0x12, 0x13, 0x0a, 0x0f, 0x49, 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x5f, 0x52, 0x45, 0x51, - 0x55, 0x45, 0x53, 0x54, 0x10, 0x03, 0x12, 0x0b, 0x0a, 0x07, 0x54, 0x49, 0x4d, 0x45, 0x4f, 0x55, - 0x54, 0x10, 0x04, 0x12, 0x12, 0x0a, 0x0e, 0x49, 0x4e, 0x54, 0x45, 0x52, 0x4e, 0x41, 0x4c, 0x5f, - 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x05, 0x42, 0x20, 0x5a, 0x1e, 0x63, 0x6f, 0x72, 0x65, 0x2f, - 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x2f, 0x72, 0x65, 0x6d, - 0x6f, 0x74, 0x65, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x33, + 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x49, 0x64, 0x73, 0x2a, 0x76, 0x0a, 0x05, 0x45, 0x72, 0x72, + 0x6f, 0x72, 0x12, 0x06, 0x0a, 0x02, 0x4f, 0x4b, 0x10, 0x00, 0x12, 0x15, 0x0a, 0x11, 0x56, 0x41, + 0x4c, 0x49, 0x44, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44, 0x10, + 0x01, 0x12, 0x18, 0x0a, 0x14, 0x43, 0x41, 0x50, 0x41, 0x42, 0x49, 0x4c, 0x49, 0x54, 0x59, 0x5f, + 0x4e, 0x4f, 0x54, 0x5f, 0x46, 0x4f, 0x55, 0x4e, 0x44, 0x10, 0x02, 0x12, 0x13, 0x0a, 0x0f, 0x49, + 0x4e, 0x56, 0x41, 0x4c, 0x49, 0x44, 0x5f, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x10, 0x03, + 0x12, 0x0b, 0x0a, 0x07, 0x54, 0x49, 0x4d, 0x45, 0x4f, 0x55, 0x54, 0x10, 0x04, 0x12, 0x12, 0x0a, + 0x0e, 0x49, 0x4e, 0x54, 0x45, 0x52, 0x4e, 0x41, 0x4c, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, + 0x05, 0x42, 0x20, 0x5a, 0x1e, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, + 0x6c, 0x69, 0x74, 0x69, 0x65, 0x73, 0x2f, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x2f, 0x74, 0x79, + 0x70, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -584,14 +498,13 @@ func file_core_capabilities_remote_types_messages_proto_rawDescGZIP() []byte { } var file_core_capabilities_remote_types_messages_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_core_capabilities_remote_types_messages_proto_msgTypes = make([]protoimpl.MessageInfo, 5) -var file_core_capabilities_remote_types_messages_proto_goTypes = []interface{}{ +var file_core_capabilities_remote_types_messages_proto_msgTypes = make([]protoimpl.MessageInfo, 4) +var file_core_capabilities_remote_types_messages_proto_goTypes = []any{ (Error)(0), // 0: remote.Error (*Message)(nil), // 1: remote.Message (*MessageBody)(nil), // 2: remote.MessageBody (*TriggerRegistrationMetadata)(nil), // 3: remote.TriggerRegistrationMetadata (*TriggerEventMetadata)(nil), // 4: remote.TriggerEventMetadata - (*RemoteTriggerConfig)(nil), // 5: remote.RemoteTriggerConfig } var file_core_capabilities_remote_types_messages_proto_depIdxs = []int32{ 0, // 0: remote.MessageBody.error:type_name -> remote.Error @@ -610,7 +523,7 @@ func file_core_capabilities_remote_types_messages_proto_init() { return } if !protoimpl.UnsafeEnabled { - file_core_capabilities_remote_types_messages_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + file_core_capabilities_remote_types_messages_proto_msgTypes[0].Exporter = func(v any, i int) any { switch v := v.(*Message); i { case 0: return &v.state @@ -622,7 +535,7 @@ func file_core_capabilities_remote_types_messages_proto_init() { return nil } } - file_core_capabilities_remote_types_messages_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + file_core_capabilities_remote_types_messages_proto_msgTypes[1].Exporter = func(v any, i int) any { switch v := v.(*MessageBody); i { case 0: return &v.state @@ -634,7 +547,7 @@ func file_core_capabilities_remote_types_messages_proto_init() { return nil } } - file_core_capabilities_remote_types_messages_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + file_core_capabilities_remote_types_messages_proto_msgTypes[2].Exporter = func(v any, i int) any { switch v := v.(*TriggerRegistrationMetadata); i { case 0: return &v.state @@ -646,7 +559,7 @@ func file_core_capabilities_remote_types_messages_proto_init() { return nil } } - file_core_capabilities_remote_types_messages_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + file_core_capabilities_remote_types_messages_proto_msgTypes[3].Exporter = func(v any, i int) any { switch v := v.(*TriggerEventMetadata); i { case 0: return &v.state @@ -658,20 +571,8 @@ func file_core_capabilities_remote_types_messages_proto_init() { return nil } } - file_core_capabilities_remote_types_messages_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RemoteTriggerConfig); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } } - file_core_capabilities_remote_types_messages_proto_msgTypes[1].OneofWrappers = []interface{}{ + file_core_capabilities_remote_types_messages_proto_msgTypes[1].OneofWrappers = []any{ (*MessageBody_TriggerRegistrationMetadata)(nil), (*MessageBody_TriggerEventMetadata)(nil), } @@ -681,7 +582,7 @@ func file_core_capabilities_remote_types_messages_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_core_capabilities_remote_types_messages_proto_rawDesc, NumEnums: 1, - NumMessages: 5, + NumMessages: 4, NumExtensions: 0, NumServices: 0, }, diff --git a/core/capabilities/remote/types/messages.proto b/core/capabilities/remote/types/messages.proto index 4855892f9f..7726538e8d 100644 --- a/core/capabilities/remote/types/messages.proto +++ b/core/capabilities/remote/types/messages.proto @@ -49,10 +49,3 @@ message TriggerEventMetadata { string trigger_event_id = 1; repeated string workflow_ids = 2; } - -message RemoteTriggerConfig { - uint32 registrationRefreshMs = 1; - uint32 registrationExpiryMs = 2; - uint32 minResponsesToAggregate = 3; - uint32 messageExpiryMs = 4; -} diff --git a/core/capabilities/streams/trigger_test.go b/core/capabilities/streams/trigger_test.go index 6d8c9a27c1..cb4cfaa36b 100644 --- a/core/capabilities/streams/trigger_test.go +++ b/core/capabilities/streams/trigger_test.go @@ -87,7 +87,7 @@ func TestStreamsTrigger(t *testing.T) { Members: capMembers, F: uint8(F), } - config := &remotetypes.RemoteTriggerConfig{ + config := capabilities.RemoteTriggerConfig{ MinResponsesToAggregate: uint32(F + 1), } subscriber := remote.NewTriggerSubscriber(config, capInfo, capDonInfo, capabilities.DON{}, nil, agg, lggr) diff --git a/core/scripts/go.mod b/core/scripts/go.mod index c2af4c13f4..77b9d9d74d 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -20,9 +20,9 @@ require ( github.com/olekukonko/tablewriter v0.0.5 github.com/pelletier/go-toml/v2 v2.2.0 github.com/prometheus/client_golang v1.17.0 - github.com/shopspring/decimal v1.3.1 + github.com/shopspring/decimal v1.4.0 github.com/smartcontractkit/chainlink-automation v1.0.4 - github.com/smartcontractkit/chainlink-common v0.2.1 + github.com/smartcontractkit/chainlink-common v0.2.2-0.20240723123524-e407ecd120b1 github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000 github.com/smartcontractkit/libocr v0.0.0-20240702141926-063ceef8c42e github.com/spf13/cobra v1.8.0 @@ -31,7 +31,7 @@ require ( github.com/umbracle/ethgo v0.1.3 github.com/umbracle/fastrlp v0.0.0-20220527094140-59d5dd30e722 github.com/urfave/cli v1.22.14 - google.golang.org/protobuf v1.34.1 + google.golang.org/protobuf v1.34.2 k8s.io/api v0.30.0 k8s.io/apimachinery v0.30.0 k8s.io/client-go v0.30.0 @@ -74,7 +74,7 @@ require ( github.com/cenkalti/backoff v2.2.1+incompatible // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/cespare/xxhash v1.1.0 // indirect - github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect github.com/chenzhuoyu/iasm v0.9.0 // indirect github.com/cockroachdb/errors v1.9.1 // indirect @@ -141,7 +141,7 @@ require ( github.com/go-kit/log v0.2.1 // indirect github.com/go-ldap/ldap/v3 v3.4.6 // indirect github.com/go-logfmt/logfmt v0.6.0 // indirect - github.com/go-logr/logr v1.4.1 // indirect + github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.2.6 // indirect github.com/go-openapi/jsonpointer v0.20.0 // indirect @@ -157,7 +157,7 @@ require ( github.com/gofrs/flock v0.8.1 // indirect github.com/gogo/protobuf v1.3.3 // indirect github.com/golang-jwt/jwt/v5 v5.2.0 // indirect - github.com/golang/glog v1.2.0 // indirect + github.com/golang/glog v1.2.1 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect @@ -318,33 +318,33 @@ require ( go.opencensus.io v0.24.0 // indirect go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin v0.49.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.52.0 // indirect - go.opentelemetry.io/otel v1.27.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.27.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0 // indirect - go.opentelemetry.io/otel/metric v1.27.0 // indirect - go.opentelemetry.io/otel/sdk v1.27.0 // indirect - go.opentelemetry.io/otel/trace v1.27.0 // indirect - go.opentelemetry.io/proto/otlp v1.2.0 // indirect + go.opentelemetry.io/otel v1.28.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0 // indirect + go.opentelemetry.io/otel/metric v1.28.0 // indirect + go.opentelemetry.io/otel/sdk v1.28.0 // indirect + go.opentelemetry.io/otel/trace v1.28.0 // indirect + go.opentelemetry.io/proto/otlp v1.3.1 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/ratelimit v0.3.0 // indirect - go.uber.org/zap v1.26.0 // indirect + go.uber.org/zap v1.27.0 // indirect golang.org/x/arch v0.7.0 // indirect - golang.org/x/crypto v0.24.0 // indirect - golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8 // indirect - golang.org/x/mod v0.17.0 // indirect - golang.org/x/net v0.25.0 // indirect + golang.org/x/crypto v0.25.0 // indirect + golang.org/x/exp v0.0.0-20240716175740-e3f259677ff7 // indirect + golang.org/x/mod v0.19.0 // indirect + golang.org/x/net v0.27.0 // indirect golang.org/x/oauth2 v0.20.0 // indirect golang.org/x/sync v0.7.0 // indirect - golang.org/x/sys v0.21.0 // indirect - golang.org/x/term v0.21.0 // indirect + golang.org/x/sys v0.22.0 // indirect + golang.org/x/term v0.22.0 // indirect golang.org/x/text v0.16.0 // indirect golang.org/x/time v0.5.0 // indirect - golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect - gonum.org/v1/gonum v0.14.0 // indirect + golang.org/x/tools v0.23.0 // indirect + gonum.org/v1/gonum v0.15.0 // indirect google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240520151616-dc85e6b867a5 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240520151616-dc85e6b867a5 // indirect - google.golang.org/grpc v1.64.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240711142825-46eb208f015d // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240711142825-46eb208f015d // indirect + google.golang.org/grpc v1.65.0 // indirect gopkg.in/guregu/null.v4 v4.0.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect diff --git a/core/scripts/go.sum b/core/scripts/go.sum index 3bc29ea81d..1704916a3c 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -26,7 +26,7 @@ cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvf cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/compute v1.25.1 h1:ZRpHJedLtTpKgr3RV1Fx23NuaAEN1Zfx9hw1u4aJdjU= +cloud.google.com/go/compute v1.24.0 h1:phWcR2eWzRJaL/kOiJwfFsPs4BaKq1j6vnpZrc1YlVg= cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc= cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= @@ -212,8 +212,9 @@ github.com/cespare/cp v1.1.1/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY= github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk= github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d h1:77cEq6EriyTZ0g/qfRdp61a3Uu/AWrgIq2s0ClJV1g0= @@ -478,8 +479,8 @@ github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4= github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= -github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8= @@ -539,8 +540,8 @@ github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w github.com/golang-jwt/jwt/v5 v5.2.0 h1:d/ix8ftRUorsN+5eMIlF4T6J8CAt9rch3My2winC1Jw= github.com/golang-jwt/jwt/v5 v5.2.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.2.0 h1:uCdmnmatrKCgMBlM4rMuJZWOkPDqdbZPnrMXDY4gI68= -github.com/golang/glog v1.2.0/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= +github.com/golang/glog v1.2.1 h1:OptwRhECazUx5ix5TTWC3EZhsZEHWcYWY4FQHTIubm4= +github.com/golang/glog v1.2.1/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -1166,8 +1167,9 @@ github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= -github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= +github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k= +github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= @@ -1178,8 +1180,8 @@ github.com/smartcontractkit/chain-selectors v1.0.10 h1:t9kJeE6B6G+hKD0GYR4kGJSCq github.com/smartcontractkit/chain-selectors v1.0.10/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/smartcontractkit/chainlink-automation v1.0.4 h1:iyW181JjKHLNMnDleI8umfIfVVlwC7+n5izbLSFgjw8= github.com/smartcontractkit/chainlink-automation v1.0.4/go.mod h1:u4NbPZKJ5XiayfKHD/v3z3iflQWqvtdhj13jVZXj/cM= -github.com/smartcontractkit/chainlink-common v0.2.1 h1:IqaJBQf6lkSiV58jnCx/TtxHzrXPavDjBmt4LgEHy4U= -github.com/smartcontractkit/chainlink-common v0.2.1/go.mod h1:fh9eBbrReCmv31bfz52ENCAMa7nTKQbdhb2B3+S2VGo= +github.com/smartcontractkit/chainlink-common v0.2.2-0.20240723123524-e407ecd120b1 h1:pdEpjgbZ5w/Sd5lzg/XiuC5gVyrmSovOo+3nUD46SP8= +github.com/smartcontractkit/chainlink-common v0.2.2-0.20240723123524-e407ecd120b1/go.mod h1:Jg1sCTsbxg76YByI8ifpFby3FvVqISStHT8ypy9ocmY= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240710121324-3ed288aa9b45 h1:NBQLtqk8zsyY4qTJs+NElI3aDFTcAo83JHvqD04EvB0= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240710121324-3ed288aa9b45/go.mod h1:LV0h7QBQUpoC2UUi6TcUvcIFm1xjP/DtEcqV8+qeLUs= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240718160222-2dc0c8136bfa h1:g75H8oh2ws52s8BekwvGQ9XvBVu3E7WM1rfiA0PN0zk= @@ -1391,22 +1393,22 @@ go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw= go.opentelemetry.io/contrib/propagators/b3 v1.24.0 h1:n4xwCdTx3pZqZs2CjS/CUZAs03y3dZcGhC/FepKtEUY= go.opentelemetry.io/contrib/propagators/b3 v1.24.0/go.mod h1:k5wRxKRU2uXx2F8uNJ4TaonuEO/V7/5xoz7kdsDACT8= -go.opentelemetry.io/otel v1.27.0 h1:9BZoF3yMK/O1AafMiQTVu0YDj5Ea4hPhxCs7sGva+cg= -go.opentelemetry.io/otel v1.27.0/go.mod h1:DMpAK8fzYRzs+bi3rS5REupisuqTheUlSZJ1WnZaPAQ= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.27.0 h1:R9DE4kQ4k+YtfLI2ULwX82VtNQ2J8yZmA7ZIF/D+7Mc= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.27.0/go.mod h1:OQFyQVrDlbe+R7xrEyDr/2Wr67Ol0hRUgsfA+V5A95s= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0 h1:qFffATk0X+HD+f1Z8lswGiOQYKHRlzfmdJm0wEaVrFA= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0/go.mod h1:MOiCmryaYtc+V0Ei+Tx9o5S1ZjA7kzLucuVuyzBZloQ= -go.opentelemetry.io/otel/metric v1.27.0 h1:hvj3vdEKyeCi4YaYfNjv2NUje8FqKqUY8IlF0FxV/ik= -go.opentelemetry.io/otel/metric v1.27.0/go.mod h1:mVFgmRlhljgBiuk/MP/oKylr4hs85GZAylncepAX/ak= -go.opentelemetry.io/otel/sdk v1.27.0 h1:mlk+/Y1gLPLn84U4tI8d3GNJmGT/eXe3ZuOXN9kTWmI= -go.opentelemetry.io/otel/sdk v1.27.0/go.mod h1:Ha9vbLwJE6W86YstIywK2xFfPjbWlCuwPtMkKdz/Y4A= +go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo= +go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 h1:3Q/xZUyC1BBkualc9ROb4G8qkH90LXEIICcs5zv1OYY= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0/go.mod h1:s75jGIWA9OfCMzF0xr+ZgfrB5FEbbV7UuYo32ahUiFI= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0 h1:R3X6ZXmNPRR8ul6i3WgFURCHzaXjHdm0karRG/+dj3s= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0/go.mod h1:QWFXnDavXWwMx2EEcZsf3yxgEKAqsxQ+Syjp+seyInw= +go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q= +go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s= +go.opentelemetry.io/otel/sdk v1.28.0 h1:b9d7hIry8yZsgtbmM0DKyPWMMUMlK9NEKuIG4aBqWyE= +go.opentelemetry.io/otel/sdk v1.28.0/go.mod h1:oYj7ClPUA7Iw3m+r7GeEjz0qckQRJK2B8zjcZEfu7Pg= go.opentelemetry.io/otel/sdk/metric v1.21.0 h1:smhI5oD714d6jHE6Tie36fPx4WDFIg+Y6RfAY4ICcR0= go.opentelemetry.io/otel/sdk/metric v1.21.0/go.mod h1:FJ8RAsoPGv/wYMgBdUJXOm+6pzFY3YdljnXtv1SBE8Q= -go.opentelemetry.io/otel/trace v1.27.0 h1:IqYb813p7cmbHk0a5y6pD5JPakbVfftRXABGt5/Rscw= -go.opentelemetry.io/otel/trace v1.27.0/go.mod h1:6RiD1hkAprV4/q+yd2ln1HG9GoPx39SuvvstaLBl+l4= -go.opentelemetry.io/proto/otlp v1.2.0 h1:pVeZGk7nXDC9O2hncA6nHldxEjm6LByfA2aN8IOkz94= -go.opentelemetry.io/proto/otlp v1.2.0/go.mod h1:gGpR8txAl5M03pDhMC79G6SdqNV26naRm/KDsgaHD8A= +go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g= +go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI= +go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= +go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= @@ -1434,8 +1436,8 @@ go.uber.org/zap v1.14.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= -go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= -go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/arch v0.7.0 h1:pskyeJh/3AmoQ8CPE95vxHLqp1G1GfGNXTmcl9NEKTc= golang.org/x/arch v0.7.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= @@ -1466,8 +1468,8 @@ golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0 golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= -golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= +golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1478,8 +1480,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8 h1:aAcj0Da7eBAtrTp03QXWvm88pSyOt+UgdZw2BFZ+lEw= -golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8/go.mod h1:CQ1k9gNrJ50XIzaKCRR2hssIjF07kZFEiieALBM/ARQ= +golang.org/x/exp v0.0.0-20240716175740-e3f259677ff7 h1:wDLEX9a7YQoKdKNQt88rtydkqDxeGaBUTnIYc3iG/mA= +golang.org/x/exp v0.0.0-20240716175740-e3f259677ff7/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -1507,8 +1509,8 @@ golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= -golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8= +golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1565,8 +1567,8 @@ golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= -golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= +golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= +golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1678,8 +1680,8 @@ golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= +golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -1687,8 +1689,8 @@ golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuX golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= -golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= -golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= +golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk= +golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1774,8 +1776,8 @@ golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= +golang.org/x/tools v0.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg= +golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI= golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1783,8 +1785,8 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -gonum.org/v1/gonum v0.14.0 h1:2NiG67LD1tEH0D7kM+ps2V+fXmsAnpUeec7n8tcr4S0= -gonum.org/v1/gonum v0.14.0/go.mod h1:AoWeoz0becf9QMWtE8iWXNXc27fK4fNeHNf/oMejGfU= +gonum.org/v1/gonum v0.15.0 h1:2lYxjRbTYyxkJxlhC+LvJIx3SsANPdRybu1tGj9/OrQ= +gonum.org/v1/gonum v0.15.0/go.mod h1:xzZVBJBtS+Mz4q0Yl2LJTk+OxOg4jiXZ7qBoM0uISGo= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= @@ -1861,10 +1863,10 @@ google.golang.org/genproto v0.0.0-20210401141331-865547bb08e2/go.mod h1:9lPAdzaE google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 h1:9+tzLLstTlPTRyJTh+ah5wIMsBW5c4tQwGTN3thOW9Y= google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9/go.mod h1:mqHbVIp48Muh7Ywss/AD6I5kNVKZMmAa/QEW58Gxp2s= -google.golang.org/genproto/googleapis/api v0.0.0-20240520151616-dc85e6b867a5 h1:P8OJ/WCl/Xo4E4zoe4/bifHpSmmKwARqyqE4nW6J2GQ= -google.golang.org/genproto/googleapis/api v0.0.0-20240520151616-dc85e6b867a5/go.mod h1:RGnPtTG7r4i8sPlNyDeikXF99hMM+hN6QMm4ooG9g2g= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240520151616-dc85e6b867a5 h1:Q2RxlXqh1cgzzUgV261vBO2jI5R/3DD1J2pM0nI4NhU= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240520151616-dc85e6b867a5/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= +google.golang.org/genproto/googleapis/api v0.0.0-20240711142825-46eb208f015d h1:kHjw/5UfflP/L5EbledDrcG4C2597RtymmGRZvHiCuY= +google.golang.org/genproto/googleapis/api v0.0.0-20240711142825-46eb208f015d/go.mod h1:mw8MG/Qz5wfgYr6VqVCiZcHe/GJEfI+oGGDCohaVgB0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240711142825-46eb208f015d h1:JU0iKnSg02Gmb5ZdV8nYsKEKsP6o/FGVWTrw4i1DA9A= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240711142825-46eb208f015d/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= google.golang.org/grpc v1.12.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= @@ -1887,8 +1889,8 @@ google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA5 google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.64.0 h1:KH3VH9y/MgNQg1dE7b3XfVK0GsPSIzJwdF617gUSbvY= -google.golang.org/grpc v1.64.0/go.mod h1:oxjF8E3FBnjp+/gVFYdWacaLDx9na1aqy9oovLpxQYg= +google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc= +google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -1902,8 +1904,8 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= -google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/core/scripts/keystone/src/05_deploy_initialize_capabilities_registry.go b/core/scripts/keystone/src/05_deploy_initialize_capabilities_registry.go index 338a582a76..387ebf46b9 100644 --- a/core/scripts/keystone/src/05_deploy_initialize_capabilities_registry.go +++ b/core/scripts/keystone/src/05_deploy_initialize_capabilities_registry.go @@ -8,15 +8,19 @@ import ( "log" "os" "strings" + "time" "github.com/ethereum/go-ethereum/common" ragetypes "github.com/smartcontractkit/libocr/ragep2p/types" "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/types/known/durationpb" + + capabilitiespb "github.com/smartcontractkit/chainlink-common/pkg/capabilities/pb" + "github.com/smartcontractkit/chainlink-common/pkg/values" "github.com/ethereum/go-ethereum/accounts/abi/bind" helpers "github.com/smartcontractkit/chainlink/core/scripts/common" - remotetypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/types" kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" ) @@ -324,11 +328,16 @@ func (c *deployAndInitializeCapabilitiesRegistryCommand) Run(args []string) { panic(err) } - config := &remotetypes.RemoteTriggerConfig{ - RegistrationRefreshMs: 20000, - RegistrationExpiryMs: 60000, - // F + 1 - MinResponsesToAggregate: uint32(1) + 1, + config := &capabilitiespb.CapabilityConfig{ + DefaultConfig: values.Proto(values.EmptyMap()).GetMapValue(), + RemoteConfig: &capabilitiespb.CapabilityConfig_RemoteTriggerConfig{ + RemoteTriggerConfig: &capabilitiespb.RemoteTriggerConfig{ + RegistrationRefresh: durationpb.New(20 * time.Second), + RegistrationExpiry: durationpb.New(60 * time.Second), + // F + 1 + MinResponsesToAggregate: uint32(1) + 1, + }, + }, } configb, err := proto.Marshal(config) if err != nil { diff --git a/core/services/chainlink/application.go b/core/services/chainlink/application.go index fd263470a8..2b76baf7b5 100644 --- a/core/services/chainlink/application.go +++ b/core/services/chainlink/application.go @@ -17,11 +17,9 @@ import ( "go.uber.org/multierr" "go.uber.org/zap/zapcore" - pkgcapabilities "github.com/smartcontractkit/chainlink-common/pkg/capabilities" "github.com/smartcontractkit/chainlink-common/pkg/loop" commonservices "github.com/smartcontractkit/chainlink-common/pkg/services" "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" - coretypes "github.com/smartcontractkit/chainlink-common/pkg/types/core" "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink-common/pkg/utils/jsonserializable" "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" @@ -180,7 +178,7 @@ type ApplicationOpts struct { LoopRegistry *plugins.LoopRegistry GRPCOpts loop.GRPCOpts MercuryPool wsrpc.Pool - CapabilitiesRegistry coretypes.CapabilitiesRegistry + CapabilitiesRegistry *capabilities.Registry } // NewApplication initializes a new store if one is not already @@ -205,7 +203,6 @@ func NewApplication(opts ApplicationOpts) (Application, error) { } var externalPeerWrapper p2ptypes.PeerWrapper - var getLocalNode func(ctx context.Context) (pkgcapabilities.Node, error) if cfg.Capabilities().Peering().Enabled() { externalPeer := externalp2p.NewExternalPeerWrapper(keyStore.P2P(), cfg.Capabilities().Peering(), opts.DS, globalLogger) signer := externalPeer @@ -224,6 +221,7 @@ func NewApplication(opts ApplicationOpts) (Application, error) { registrySyncer, err := registrysyncer.New( globalLogger, + externalPeerWrapper, relayer, registryAddress, ) @@ -239,7 +237,6 @@ func NewApplication(opts ApplicationOpts) (Application, error) { ) registrySyncer.AddLauncher(wfLauncher) - getLocalNode = wfLauncher.LocalNode srvcs = append(srvcs, dispatcher, wfLauncher, registrySyncer) } @@ -431,7 +428,6 @@ func NewApplication(opts ApplicationOpts) (Application, error) { globalLogger, opts.CapabilitiesRegistry, workflowORM, - getLocalNode, ) // Flux monitor requires ethereum just to boot, silence errors with a null delegate diff --git a/core/services/registrysyncer/local_registry.go b/core/services/registrysyncer/local_registry.go new file mode 100644 index 0000000000..4e4a632bf8 --- /dev/null +++ b/core/services/registrysyncer/local_registry.go @@ -0,0 +1,85 @@ +package registrysyncer + +import ( + "context" + "errors" + "fmt" + + "github.com/smartcontractkit/chainlink-common/pkg/capabilities" + + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" + "github.com/smartcontractkit/chainlink/v2/core/logger" + p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" +) + +type DonID uint32 + +type DON struct { + capabilities.DON + CapabilityConfigurations map[string]capabilities.CapabilityConfiguration +} + +type Capability struct { + ID string + CapabilityType capabilities.CapabilityType +} + +type LocalRegistry struct { + lggr logger.Logger + peerWrapper p2ptypes.PeerWrapper + IDsToDONs map[DonID]DON + IDsToNodes map[p2ptypes.PeerID]kcr.CapabilitiesRegistryNodeInfo + IDsToCapabilities map[string]Capability +} + +func (l *LocalRegistry) LocalNode(ctx context.Context) (capabilities.Node, error) { + // Load the current nodes PeerWrapper, this gets us the current node's + // PeerID, allowing us to contextualize registry information in terms of DON ownership + // (eg. get my current DON configuration, etc). + if l.peerWrapper.GetPeer() == nil { + return capabilities.Node{}, errors.New("unable to get local node: peerWrapper hasn't started yet") + } + + pid := l.peerWrapper.GetPeer().ID() + + var workflowDON capabilities.DON + capabilityDONs := []capabilities.DON{} + for _, d := range l.IDsToDONs { + for _, p := range d.Members { + if p == pid { + if d.AcceptsWorkflows { + // The CapabilitiesRegistry enforces that the DON ID is strictly + // greater than 0, so if the ID is 0, it means we've not set `workflowDON` initialized above yet. + if workflowDON.ID == 0 { + workflowDON = d.DON + l.lggr.Debug("Workflow DON identified: %+v", workflowDON) + } else { + l.lggr.Errorf("Configuration error: node %s belongs to more than one workflowDON", pid) + } + } + + capabilityDONs = append(capabilityDONs, d.DON) + } + } + } + + return capabilities.Node{ + PeerID: &pid, + WorkflowDON: workflowDON, + CapabilityDONs: capabilityDONs, + }, nil +} + +func (l *LocalRegistry) ConfigForCapability(ctx context.Context, capabilityID string, donID uint32) (capabilities.CapabilityConfiguration, error) { + d, ok := l.IDsToDONs[DonID(donID)] + if !ok { + return capabilities.CapabilityConfiguration{}, fmt.Errorf("could not find don %d", donID) + } + + cc, ok := d.CapabilityConfigurations[capabilityID] + if !ok { + return capabilities.CapabilityConfiguration{}, fmt.Errorf("could not find capability configuration for capability %s and donID %d", capabilityID, donID) + } + + return cc, nil +} diff --git a/core/services/registrysyncer/syncer.go b/core/services/registrysyncer/syncer.go index d4f5b0e02d..4fb4b70dce 100644 --- a/core/services/registrysyncer/syncer.go +++ b/core/services/registrysyncer/syncer.go @@ -7,9 +7,14 @@ import ( "sync" "time" + "google.golang.org/protobuf/proto" + + "github.com/smartcontractkit/chainlink-common/pkg/capabilities" + capabilitiespb "github.com/smartcontractkit/chainlink-common/pkg/capabilities/pb" "github.com/smartcontractkit/chainlink-common/pkg/services" "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink-common/pkg/types/query/primitives" + "github.com/smartcontractkit/chainlink-common/pkg/values" kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" "github.com/smartcontractkit/chainlink/v2/core/logger" @@ -17,17 +22,8 @@ import ( evmrelaytypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" ) -type HashedCapabilityID [32]byte -type DonID uint32 - -type State struct { - IDsToDONs map[DonID]kcr.CapabilitiesRegistryDONInfo - IDsToNodes map[p2ptypes.PeerID]kcr.CapabilitiesRegistryNodeInfo - IDsToCapabilities map[HashedCapabilityID]kcr.CapabilitiesRegistryCapabilityInfo -} - type Launcher interface { - Launch(ctx context.Context, state State) error + Launch(ctx context.Context, registry *LocalRegistry) error } type Syncer interface { @@ -43,6 +39,7 @@ type registrySyncer struct { initReader func(ctx context.Context, lggr logger.Logger, relayer contractReaderFactory, registryAddress string) (types.ContractReader, error) relayer contractReaderFactory registryAddress string + peerWrapper p2ptypes.PeerWrapper wg sync.WaitGroup lggr logger.Logger @@ -58,6 +55,7 @@ var ( // New instantiates a new RegistrySyncer func New( lggr logger.Logger, + peerWrapper p2ptypes.PeerWrapper, relayer contractReaderFactory, registryAddress string, ) (*registrySyncer, error) { @@ -68,6 +66,7 @@ func New( relayer: relayer, registryAddress: registryAddress, initReader: newReader, + peerWrapper: peerWrapper, }, nil } @@ -159,33 +158,81 @@ func (s *registrySyncer) syncLoop() { } } -func (s *registrySyncer) state(ctx context.Context) (State, error) { - dons := []kcr.CapabilitiesRegistryDONInfo{} - err := s.reader.GetLatestValue(ctx, "CapabilitiesRegistry", "getDONs", primitives.Unconfirmed, nil, &dons) +func unmarshalCapabilityConfig(data []byte) (capabilities.CapabilityConfiguration, error) { + cconf := &capabilitiespb.CapabilityConfig{} + err := proto.Unmarshal(data, cconf) if err != nil { - return State{}, err + return capabilities.CapabilityConfiguration{}, err } - idsToDONs := map[DonID]kcr.CapabilitiesRegistryDONInfo{} - for _, d := range dons { - idsToDONs[DonID(d.Id)] = d + var rtc capabilities.RemoteTriggerConfig + if prtc := cconf.GetRemoteTriggerConfig(); prtc != nil { + rtc.RegistrationRefresh = prtc.RegistrationRefresh.AsDuration() + rtc.RegistrationExpiry = prtc.RegistrationExpiry.AsDuration() + rtc.MinResponsesToAggregate = prtc.MinResponsesToAggregate + rtc.MessageExpiry = prtc.MessageExpiry.AsDuration() } + return capabilities.CapabilityConfiguration{ + DefaultConfig: values.FromMapValueProto(cconf.DefaultConfig), + RemoteTriggerConfig: rtc, + }, nil +} + +func (s *registrySyncer) localRegistry(ctx context.Context) (*LocalRegistry, error) { caps := []kcr.CapabilitiesRegistryCapabilityInfo{} - err = s.reader.GetLatestValue(ctx, "CapabilitiesRegistry", "getCapabilities", primitives.Unconfirmed, nil, &caps) + err := s.reader.GetLatestValue(ctx, "CapabilitiesRegistry", "getCapabilities", primitives.Unconfirmed, nil, &caps) if err != nil { - return State{}, err + return nil, err } - idsToCapabilities := map[HashedCapabilityID]kcr.CapabilitiesRegistryCapabilityInfo{} + idsToCapabilities := map[string]Capability{} + hashedIDsToCapabilityIDs := map[[32]byte]string{} for _, c := range caps { - idsToCapabilities[c.HashedId] = c + cid := fmt.Sprintf("%s@%s", c.LabelledName, c.Version) + idsToCapabilities[cid] = Capability{ + ID: cid, + CapabilityType: toCapabilityType(c.CapabilityType), + } + + hashedIDsToCapabilityIDs[c.HashedId] = cid + } + + dons := []kcr.CapabilitiesRegistryDONInfo{} + err = s.reader.GetLatestValue(ctx, "CapabilitiesRegistry", "getDONs", primitives.Unconfirmed, nil, &dons) + if err != nil { + return nil, err + } + + idsToDONs := map[DonID]DON{} + for _, d := range dons { + cc := map[string]capabilities.CapabilityConfiguration{} + for _, dc := range d.CapabilityConfigurations { + cid, ok := hashedIDsToCapabilityIDs[dc.CapabilityId] + if !ok { + return nil, fmt.Errorf("invariant violation: could not find full ID for hashed ID %s", dc.CapabilityId) + } + + cconf, innerErr := unmarshalCapabilityConfig(dc.Config) + if innerErr != nil { + return nil, innerErr + } + + cconf.RemoteTriggerConfig.ApplyDefaults() + + cc[cid] = cconf + } + + idsToDONs[DonID(d.Id)] = DON{ + DON: *toDONInfo(d), + CapabilityConfigurations: cc, + } } nodes := []kcr.CapabilitiesRegistryNodeInfo{} err = s.reader.GetLatestValue(ctx, "CapabilitiesRegistry", "getNodes", primitives.Unconfirmed, nil, &nodes) if err != nil { - return State{}, err + return nil, err } idsToNodes := map[p2ptypes.PeerID]kcr.CapabilitiesRegistryNodeInfo{} @@ -193,7 +240,13 @@ func (s *registrySyncer) state(ctx context.Context) (State, error) { idsToNodes[node.P2pId] = node } - return State{IDsToDONs: idsToDONs, IDsToCapabilities: idsToCapabilities, IDsToNodes: idsToNodes}, nil + return &LocalRegistry{ + lggr: s.lggr, + peerWrapper: s.peerWrapper, + IDsToDONs: idsToDONs, + IDsToCapabilities: idsToCapabilities, + IDsToNodes: idsToNodes, + }, nil } func (s *registrySyncer) sync(ctx context.Context) error { @@ -214,13 +267,13 @@ func (s *registrySyncer) sync(ctx context.Context) error { s.reader = reader } - state, err := s.state(ctx) + lr, err := s.localRegistry(ctx) if err != nil { return fmt.Errorf("failed to sync with remote registry: %w", err) } for _, h := range s.launchers { - if err := h.Launch(ctx, state); err != nil { + if err := h.Launch(ctx, lr); err != nil { s.lggr.Errorf("error calling launcher: %s", err) } } @@ -228,6 +281,36 @@ func (s *registrySyncer) sync(ctx context.Context) error { return nil } +func toCapabilityType(capabilityType uint8) capabilities.CapabilityType { + switch capabilityType { + case 0: + return capabilities.CapabilityTypeTrigger + case 1: + return capabilities.CapabilityTypeAction + case 2: + return capabilities.CapabilityTypeConsensus + case 3: + return capabilities.CapabilityTypeTarget + default: + // Not found + return capabilities.CapabilityType(-1) + } +} + +func toDONInfo(don kcr.CapabilitiesRegistryDONInfo) *capabilities.DON { + peerIDs := []p2ptypes.PeerID{} + for _, p := range don.NodeP2PIds { + peerIDs = append(peerIDs, p) + } + + return &capabilities.DON{ + ID: don.Id, + ConfigVersion: don.ConfigCount, + Members: peerIDs, + F: don.F, + } +} + func (s *registrySyncer) AddLauncher(launchers ...Launcher) { s.mu.Lock() defer s.mu.Unlock() diff --git a/core/services/registrysyncer/syncer_test.go b/core/services/registrysyncer/syncer_test.go index c239cead43..0e2a57ee6b 100644 --- a/core/services/registrysyncer/syncer_test.go +++ b/core/services/registrysyncer/syncer_test.go @@ -16,9 +16,15 @@ import ( "github.com/ethereum/go-ethereum/eth/ethconfig" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/types/known/durationpb" + "github.com/smartcontractkit/chainlink-common/pkg/capabilities" "github.com/smartcontractkit/chainlink-common/pkg/types" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + "github.com/smartcontractkit/chainlink-common/pkg/values" + capabilitiespb "github.com/smartcontractkit/chainlink-common/pkg/capabilities/pb" evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" @@ -27,14 +33,15 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" + "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types/mocks" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" evmrelaytypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" ) var writeChainCapability = kcr.CapabilitiesRegistryCapability{ - LabelledName: "write-chain", - Version: "1.0.1", - ResponseType: uint8(1), + LabelledName: "write-chain", + Version: "1.0.1", + CapabilityType: uint8(3), } func startNewChainWithRegistry(t *testing.T) (*kcr.CapabilitiesRegistry, common.Address, *bind.TransactOpts, *backends.SimulatedBackend) { @@ -120,14 +127,22 @@ func randomWord() [32]byte { } type launcher struct { - localRegistry State + localRegistry *LocalRegistry } -func (l *launcher) Launch(ctx context.Context, localRegistry State) error { +func (l *launcher) Launch(ctx context.Context, localRegistry *LocalRegistry) error { l.localRegistry = localRegistry return nil } +func toPeerIDs(ids [][32]byte) []p2ptypes.PeerID { + pids := []p2ptypes.PeerID{} + for _, id := range ids { + pids = append(pids, id) + } + return pids +} + func TestReader_Integration(t *testing.T) { ctx := testutils.Context(t) reg, regAddress, owner, sim := startNewChainWithRegistry(t) @@ -136,7 +151,9 @@ func TestReader_Integration(t *testing.T) { require.NoError(t, err, "AddCapability failed for %s", writeChainCapability.LabelledName) sim.Commit() - cid, err := reg.GetHashedCapabilityId(&bind.CallOpts{}, writeChainCapability.LabelledName, writeChainCapability.Version) + cid := fmt.Sprintf("%s@%s", writeChainCapability.LabelledName, writeChainCapability.Version) + + hid, err := reg.GetHashedCapabilityId(&bind.CallOpts{}, writeChainCapability.LabelledName, writeChainCapability.Version) require.NoError(t, err) _, err = reg.AddNodeOperators(owner, []kcr.CapabilitiesRegistryNodeOperator{ @@ -165,30 +182,46 @@ func TestReader_Integration(t *testing.T) { NodeOperatorId: uint32(1), Signer: signersSet[0], P2pId: nodeSet[0], - HashedCapabilityIds: [][32]byte{cid}, + HashedCapabilityIds: [][32]byte{hid}, }, { // The first NodeOperatorId has id 1 since the id is auto-incrementing. NodeOperatorId: uint32(1), Signer: signersSet[1], P2pId: nodeSet[1], - HashedCapabilityIds: [][32]byte{cid}, + HashedCapabilityIds: [][32]byte{hid}, }, { // The first NodeOperatorId has id 1 since the id is auto-incrementing. NodeOperatorId: uint32(1), Signer: signersSet[2], P2pId: nodeSet[2], - HashedCapabilityIds: [][32]byte{cid}, + HashedCapabilityIds: [][32]byte{hid}, }, } _, err = reg.AddNodes(owner, nodes) require.NoError(t, err) + config := &capabilitiespb.CapabilityConfig{ + DefaultConfig: values.Proto(values.EmptyMap()).GetMapValue(), + RemoteConfig: &capabilitiespb.CapabilityConfig_RemoteTriggerConfig{ + RemoteTriggerConfig: &capabilitiespb.RemoteTriggerConfig{ + RegistrationRefresh: durationpb.New(20 * time.Second), + RegistrationExpiry: durationpb.New(60 * time.Second), + // F + 1 + MinResponsesToAggregate: uint32(1) + 1, + }, + }, + } + configb, err := proto.Marshal(config) + if err != nil { + panic(err) + } + cfgs := []kcr.CapabilitiesRegistryCapabilityConfiguration{ { - CapabilityId: cid, - Config: []byte(`{"hello": "world"}`), + CapabilityId: hid, + Config: configb, }, } _, err = reg.AddDON( @@ -203,8 +236,9 @@ func TestReader_Integration(t *testing.T) { require.NoError(t, err) + wrapper := mocks.NewPeerWrapper(t) factory := newContractReaderFactory(t, sim) - syncer, err := New(logger.TestLogger(t), factory, regAddress.Hex()) + syncer, err := New(logger.TestLogger(t), wrapper, factory, regAddress.Hex()) require.NoError(t, err) l := &launcher{} @@ -216,25 +250,35 @@ func TestReader_Integration(t *testing.T) { assert.Len(t, s.IDsToCapabilities, 1) gotCap := s.IDsToCapabilities[cid] - assert.Equal(t, kcr.CapabilitiesRegistryCapabilityInfo{ - HashedId: cid, - LabelledName: "write-chain", - Version: "1.0.1", - ResponseType: uint8(1), - CapabilityType: uint8(0), - IsDeprecated: false, + assert.Equal(t, Capability{ + CapabilityType: capabilities.CapabilityTypeTarget, + ID: "write-chain@1.0.1", }, gotCap) assert.Len(t, s.IDsToDONs, 1) - assert.Equal(t, kcr.CapabilitiesRegistryDONInfo{ - Id: 1, // initial Id - ConfigCount: 1, // initial Count - IsPublic: true, - AcceptsWorkflows: true, - F: 1, - NodeP2PIds: nodeSet, - CapabilityConfigurations: cfgs, - }, s.IDsToDONs[1]) + rtc := capabilities.RemoteTriggerConfig{ + RegistrationRefresh: 20 * time.Second, + MinResponsesToAggregate: 2, + RegistrationExpiry: 60 * time.Second, + MessageExpiry: 120 * time.Second, + } + expectedDON := DON{ + DON: capabilities.DON{ + ID: 1, + ConfigVersion: 1, + IsPublic: false, + AcceptsWorkflows: false, + F: 1, + Members: toPeerIDs(nodeSet), + }, + CapabilityConfigurations: map[string]capabilities.CapabilityConfiguration{ + cid: { + DefaultConfig: values.EmptyMap(), + RemoteTriggerConfig: rtc, + }, + }, + } + assert.Equal(t, expectedDON, s.IDsToDONs[1]) nodesInfo := []kcr.CapabilitiesRegistryNodeInfo{ { @@ -244,7 +288,7 @@ func TestReader_Integration(t *testing.T) { WorkflowDONId: 1, Signer: signersSet[0], P2pId: nodeSet[0], - HashedCapabilityIds: [][32]byte{cid}, + HashedCapabilityIds: [][32]byte{hid}, CapabilitiesDONIds: []*big.Int{}, }, { @@ -254,7 +298,7 @@ func TestReader_Integration(t *testing.T) { WorkflowDONId: 1, Signer: signersSet[1], P2pId: nodeSet[1], - HashedCapabilityIds: [][32]byte{cid}, + HashedCapabilityIds: [][32]byte{hid}, CapabilitiesDONIds: []*big.Int{}, }, { @@ -264,7 +308,7 @@ func TestReader_Integration(t *testing.T) { WorkflowDONId: 1, Signer: signersSet[2], P2pId: nodeSet[2], - HashedCapabilityIds: [][32]byte{cid}, + HashedCapabilityIds: [][32]byte{hid}, CapabilitiesDONIds: []*big.Int{}, }, } @@ -276,3 +320,84 @@ func TestReader_Integration(t *testing.T) { nodeSet[2]: nodesInfo[2], }, s.IDsToNodes) } + +func TestSyncer_LocalNode(t *testing.T) { + ctx := tests.Context(t) + lggr := logger.TestLogger(t) + + var pid p2ptypes.PeerID + err := pid.UnmarshalText([]byte("12D3KooWBCF1XT5Wi8FzfgNCqRL76Swv8TRU3TiD4QiJm8NMNX7N")) + require.NoError(t, err) + peer := mocks.NewPeer(t) + peer.On("ID").Return(pid) + wrapper := mocks.NewPeerWrapper(t) + wrapper.On("GetPeer").Return(peer) + + workflowDonNodes := []p2ptypes.PeerID{ + pid, + randomWord(), + randomWord(), + randomWord(), + } + + dID := uint32(1) + // The below state describes a Workflow DON (AcceptsWorkflows = true), + // which exposes the streams-trigger and write_chain capabilities. + // We expect receivers to be wired up and both capabilities to be added to the registry. + localRegistry := LocalRegistry{ + lggr: lggr, + peerWrapper: wrapper, + IDsToDONs: map[DonID]DON{ + DonID(dID): { + DON: capabilities.DON{ + ID: dID, + ConfigVersion: uint32(2), + F: uint8(1), + IsPublic: true, + AcceptsWorkflows: true, + Members: workflowDonNodes, + }, + }, + }, + IDsToNodes: map[p2ptypes.PeerID]kcr.CapabilitiesRegistryNodeInfo{ + workflowDonNodes[0]: { + NodeOperatorId: 1, + Signer: randomWord(), + P2pId: workflowDonNodes[0], + }, + workflowDonNodes[1]: { + NodeOperatorId: 1, + Signer: randomWord(), + P2pId: workflowDonNodes[1], + }, + workflowDonNodes[2]: { + NodeOperatorId: 1, + Signer: randomWord(), + P2pId: workflowDonNodes[2], + }, + workflowDonNodes[3]: { + NodeOperatorId: 1, + Signer: randomWord(), + P2pId: workflowDonNodes[3], + }, + }, + } + + node, err := localRegistry.LocalNode(ctx) + require.NoError(t, err) + + don := capabilities.DON{ + ID: dID, + ConfigVersion: 2, + Members: workflowDonNodes, + F: 1, + IsPublic: true, + AcceptsWorkflows: true, + } + expectedNode := capabilities.Node{ + PeerID: &pid, + WorkflowDON: don, + CapabilityDONs: []capabilities.DON{don}, + } + assert.Equal(t, expectedNode, node) +} diff --git a/core/services/relay/evm/mercury/wsrpc/pb/mercury.pb.go b/core/services/relay/evm/mercury/wsrpc/pb/mercury.pb.go index a1f0fef069..ab74d426bb 100644 --- a/core/services/relay/evm/mercury/wsrpc/pb/mercury.pb.go +++ b/core/services/relay/evm/mercury/wsrpc/pb/mercury.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.34.1 +// protoc-gen-go v1.34.2 // protoc v4.25.1 // source: mercury.proto @@ -535,7 +535,7 @@ func file_mercury_proto_rawDescGZIP() []byte { } var file_mercury_proto_msgTypes = make([]protoimpl.MessageInfo, 6) -var file_mercury_proto_goTypes = []interface{}{ +var file_mercury_proto_goTypes = []any{ (*TransmitRequest)(nil), // 0: pb.TransmitRequest (*TransmitResponse)(nil), // 1: pb.TransmitResponse (*LatestReportRequest)(nil), // 2: pb.LatestReportRequest @@ -563,7 +563,7 @@ func file_mercury_proto_init() { return } if !protoimpl.UnsafeEnabled { - file_mercury_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + file_mercury_proto_msgTypes[0].Exporter = func(v any, i int) any { switch v := v.(*TransmitRequest); i { case 0: return &v.state @@ -575,7 +575,7 @@ func file_mercury_proto_init() { return nil } } - file_mercury_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + file_mercury_proto_msgTypes[1].Exporter = func(v any, i int) any { switch v := v.(*TransmitResponse); i { case 0: return &v.state @@ -587,7 +587,7 @@ func file_mercury_proto_init() { return nil } } - file_mercury_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + file_mercury_proto_msgTypes[2].Exporter = func(v any, i int) any { switch v := v.(*LatestReportRequest); i { case 0: return &v.state @@ -599,7 +599,7 @@ func file_mercury_proto_init() { return nil } } - file_mercury_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + file_mercury_proto_msgTypes[3].Exporter = func(v any, i int) any { switch v := v.(*LatestReportResponse); i { case 0: return &v.state @@ -611,7 +611,7 @@ func file_mercury_proto_init() { return nil } } - file_mercury_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + file_mercury_proto_msgTypes[4].Exporter = func(v any, i int) any { switch v := v.(*Report); i { case 0: return &v.state @@ -623,7 +623,7 @@ func file_mercury_proto_init() { return nil } } - file_mercury_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + file_mercury_proto_msgTypes[5].Exporter = func(v any, i int) any { switch v := v.(*Timestamp); i { case 0: return &v.state diff --git a/core/services/workflows/delegate.go b/core/services/workflows/delegate.go index b937e0b580..acd006940f 100644 --- a/core/services/workflows/delegate.go +++ b/core/services/workflows/delegate.go @@ -7,7 +7,6 @@ import ( "github.com/google/uuid" "github.com/pelletier/go-toml" - "github.com/smartcontractkit/chainlink-common/pkg/capabilities" "github.com/smartcontractkit/chainlink-common/pkg/types/core" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/job" @@ -15,10 +14,9 @@ import ( ) type Delegate struct { - registry core.CapabilitiesRegistry - logger logger.Logger - getLocalNode func(ctx context.Context) (capabilities.Node, error) - store store.Store + registry core.CapabilitiesRegistry + logger logger.Logger + store store.Store } var _ job.Delegate = (*Delegate)(nil) @@ -44,7 +42,6 @@ func (d *Delegate) ServicesForSpec(_ context.Context, spec job.Job) ([]job.Servi WorkflowOwner: spec.WorkflowSpec.WorkflowOwner, WorkflowName: spec.WorkflowSpec.WorkflowName, Registry: d.registry, - GetLocalNode: d.getLocalNode, Store: d.store, } engine, err := NewEngine(cfg) @@ -58,9 +55,8 @@ func NewDelegate( logger logger.Logger, registry core.CapabilitiesRegistry, store store.Store, - getLocalNode func(ctx context.Context) (capabilities.Node, error), ) *Delegate { - return &Delegate{logger: logger, registry: registry, store: store, getLocalNode: getLocalNode} + return &Delegate{logger: logger, registry: registry, store: store} } func ValidatedWorkflowJobSpec(tomlString string) (job.Job, error) { diff --git a/core/services/workflows/engine.go b/core/services/workflows/engine.go index f83d40b176..ed5daaf210 100644 --- a/core/services/workflows/engine.go +++ b/core/services/workflows/engine.go @@ -33,7 +33,6 @@ type Engine struct { logger logger.Logger registry core.CapabilitiesRegistry workflow *workflow - getLocalNode func(ctx context.Context) (capabilities.Node, error) localNode capabilities.Node executionStates store.Store pendingStepRequests chan stepRequest @@ -164,9 +163,11 @@ func (e *Engine) initializeCapability(ctx context.Context, step *step) error { return newCPErr("failed to get capability info", err) } + step.info = info + // Special treatment for local targets - wrap into a transmission capability // If the DON is nil, this is a local target. - if info.CapabilityType == capabilities.CapabilityTypeTarget && info.DON == nil { + if info.CapabilityType == capabilities.CapabilityTypeTarget && info.IsLocal { l := e.logger.With("capabilityID", step.ID) l.Debug("wrapping capability in local transmission protocol") cp = transmission.NewLocalTargetCapability( @@ -222,7 +223,7 @@ func (e *Engine) init(ctx context.Context) { retryErr := retryable(ctx, e.logger, e.retryMs, e.maxRetries, func() error { // first wait for localDON to return a non-error response; this depends // on the underlying peerWrapper returning the PeerID. - node, err := e.getLocalNode(ctx) + node, err := e.registry.LocalNode(ctx) if err != nil { return fmt.Errorf("failed to get donInfo: %w", err) } @@ -680,6 +681,45 @@ func (e *Engine) workerForStepRequest(ctx context.Context, msg stepRequest) { } } +func merge(baseConfig *values.Map, overrideConfig *values.Map) *values.Map { + m := values.EmptyMap() + + for k, v := range baseConfig.Underlying { + m.Underlying[k] = v + } + + for k, v := range overrideConfig.Underlying { + m.Underlying[k] = v + } + + return m +} + +func (e *Engine) configForStep(ctx context.Context, executionID string, step *step) (*values.Map, error) { + ID := step.info.ID + + // If the capability info is missing a DON, then + // the capability is local, and we should use the localNode's DON ID. + var donID uint32 + if !step.info.IsLocal { + donID = step.info.DON.ID + } else { + donID = e.localNode.WorkflowDON.ID + } + + capConfig, err := e.registry.ConfigForCapability(ctx, ID, donID) + if err != nil { + e.logger.Warnw(fmt.Sprintf("could not retrieve config from remote registry: %s", err), "executionID", executionID, "capabilityID", ID) + return step.config, nil + } + + // Merge the configs for now; note that this means that a workflow can override + // all of the config set by the capability. This is probably not desirable in + // the long-term, but we don't know much about those use cases so stick to a simpler + // implementation for now. + return merge(capConfig.DefaultConfig, step.config), nil +} + // executeStep executes the referenced capability within a step and returns the result. func (e *Engine) executeStep(ctx context.Context, msg stepRequest) (*values.Map, values.Value, error) { step, err := e.workflow.Vertex(msg.stepRef) @@ -704,9 +744,14 @@ func (e *Engine) executeStep(ctx context.Context, msg stepRequest) (*values.Map, return nil, nil, err } + config, err := e.configForStep(ctx, msg.state.ExecutionID, step) + if err != nil { + return nil, nil, err + } + tr := capabilities.CapabilityRequest{ Inputs: inputsMap, - Config: step.config, + Config: config, Metadata: capabilities.RequestMetadata{ WorkflowID: msg.state.WorkflowID, WorkflowExecutionID: msg.state.ExecutionID, @@ -825,7 +870,6 @@ type Config struct { QueueSize int NewWorkerTimeout time.Duration MaxExecutionDuration time.Duration - GetLocalNode func(ctx context.Context) (capabilities.Node, error) Store store.Store // For testing purposes only @@ -868,12 +912,6 @@ func NewEngine(cfg Config) (engine *Engine, err error) { cfg.MaxExecutionDuration = defaultMaxExecutionDuration } - if cfg.GetLocalNode == nil { - cfg.GetLocalNode = func(ctx context.Context) (capabilities.Node, error) { - return capabilities.Node{}, nil - } - } - if cfg.retryMs == 0 { cfg.retryMs = 5000 } @@ -911,7 +949,6 @@ func NewEngine(cfg Config) (engine *Engine, err error) { logger: cfg.Lggr.Named("WorkflowEngine").With("workflowID", cfg.WorkflowID), registry: cfg.Registry, workflow: workflow, - getLocalNode: cfg.GetLocalNode, executionStates: cfg.Store, pendingStepRequests: make(chan stepRequest, cfg.QueueSize), stepUpdateCh: make(chan store.WorkflowExecutionStep), diff --git a/core/services/workflows/engine_test.go b/core/services/workflows/engine_test.go index 2c4129dbaf..b8d5a9591e 100644 --- a/core/services/workflows/engine_test.go +++ b/core/services/workflows/engine_test.go @@ -99,26 +99,46 @@ func newTestDBStore(t *testing.T, clock clockwork.Clock) store.Store { return store.NewDBStore(db, logger.TestLogger(t), clock) } +type testConfigProvider struct { + localNode func(ctx context.Context) (capabilities.Node, error) + configForCapability func(ctx context.Context, capabilityID string, donID uint32) (capabilities.CapabilityConfiguration, error) +} + +func (t testConfigProvider) LocalNode(ctx context.Context) (capabilities.Node, error) { + if t.localNode != nil { + return t.localNode(ctx) + } + + peerID := p2ptypes.PeerID{} + return capabilities.Node{ + WorkflowDON: capabilities.DON{ + ID: 1, + }, + PeerID: &peerID, + }, nil +} + +func (t testConfigProvider) ConfigForCapability(ctx context.Context, capabilityID string, donID uint32) (capabilities.CapabilityConfiguration, error) { + if t.configForCapability != nil { + return t.configForCapability(ctx, capabilityID, donID) + } + + return capabilities.CapabilityConfiguration{DefaultConfig: values.EmptyMap()}, nil +} + // newTestEngine creates a new engine with some test defaults. func newTestEngine(t *testing.T, reg *coreCap.Registry, spec string, opts ...func(c *Config)) (*Engine, *testHooks) { - peerID := p2ptypes.PeerID{} initFailed := make(chan struct{}) initSuccessful := make(chan struct{}) executionFinished := make(chan string, 100) clock := clockwork.NewFakeClock() + + reg.SetLocalRegistry(&testConfigProvider{}) cfg := Config{ WorkflowID: testWorkflowId, Lggr: logger.TestLogger(t), Registry: reg, Spec: spec, - GetLocalNode: func(ctx context.Context) (capabilities.Node, error) { - return capabilities.Node{ - WorkflowDON: capabilities.DON{ - ID: 1, - }, - PeerID: &peerID, - }, nil - }, maxRetries: 1, retryMs: 100, afterInit: func(success bool) { @@ -787,6 +807,19 @@ func TestEngine_GetsNodeInfoDuringInitialization(t *testing.T) { }, } retryCount := 0 + + reg.SetLocalRegistry(testConfigProvider{ + localNode: func(ctx context.Context) (capabilities.Node, error) { + n := capabilities.Node{} + err := errors.New("peer not initialized") + if retryCount > 0 { + n = node + err = nil + } + retryCount++ + return n, err + }, + }) eng, hooks := newTestEngine( t, reg, @@ -796,16 +829,6 @@ func TestEngine_GetsNodeInfoDuringInitialization(t *testing.T) { c.clock = clock c.maxRetries = 2 c.retryMs = 0 - c.GetLocalNode = func(ctx context.Context) (capabilities.Node, error) { - n := capabilities.Node{} - err := errors.New("peer not initialized") - if retryCount > 0 { - n = node - err = nil - } - retryCount++ - return n, err - } }, ) servicetest.Run(t, eng) @@ -969,3 +992,74 @@ func TestEngine_Error(t *testing.T) { }) } } + +func TestEngine_MergesWorkflowConfigAndCRConfig(t *testing.T) { + ctx := testutils.Context(t) + reg := coreCap.NewRegistry(logger.TestLogger(t)) + + trigger, _ := mockTrigger(t) + + require.NoError(t, reg.Add(ctx, trigger)) + require.NoError(t, reg.Add(ctx, mockConsensus())) + writeID := "write_polygon-testnet-mumbai@1.0.0" + + gotConfig := values.EmptyMap() + target := newMockCapability( + // Create a remote capability so we don't use the local transmission protocol. + capabilities.MustNewRemoteCapabilityInfo( + writeID, + capabilities.CapabilityTypeTarget, + "a write capability targeting polygon testnet", + &capabilities.DON{ID: 1}, + ), + func(req capabilities.CapabilityRequest) (capabilities.CapabilityResponse, error) { + gotConfig = req.Config + + return capabilities.CapabilityResponse{ + Value: req.Inputs, + }, nil + }, + ) + require.NoError(t, reg.Add(ctx, target)) + + eng, testHooks := newTestEngine( + t, + reg, + simpleWorkflow, + ) + reg.SetLocalRegistry(testConfigProvider{ + configForCapability: func(ctx context.Context, capabilityID string, donID uint32) (capabilities.CapabilityConfiguration, error) { + if capabilityID != writeID { + return capabilities.CapabilityConfiguration{ + DefaultConfig: values.EmptyMap(), + }, nil + } + + cm, err := values.WrapMap(map[string]any{ + "deltaStage": "1s", + "schedule": "allAtOnce", + }) + if err != nil { + return capabilities.CapabilityConfiguration{}, err + } + + return capabilities.CapabilityConfiguration{ + DefaultConfig: cm, + }, nil + }, + }) + + servicetest.Run(t, eng) + + eid := getExecutionId(t, eng, testHooks) + + state, err := eng.executionStates.Get(ctx, eid) + require.NoError(t, err) + + assert.Equal(t, state.Status, store.StatusCompleted) + + m, err := values.Unwrap(gotConfig) + require.NoError(t, err) + assert.Equal(t, m.(map[string]any)["deltaStage"], "1s") + assert.Equal(t, m.(map[string]any)["schedule"], "allAtOnce") +} diff --git a/core/services/workflows/models.go b/core/services/workflows/models.go index d55212a30c..8d970dfa94 100644 --- a/core/services/workflows/models.go +++ b/core/services/workflows/models.go @@ -79,6 +79,7 @@ func (w *workflow) dependents(start string) ([]*step, error) { type step struct { workflows.Vertex capability capabilities.CallbackCapability + info capabilities.CapabilityInfo config *values.Map } diff --git a/go.mod b/go.mod index 3a56816498..2f531d03a8 100644 --- a/go.mod +++ b/go.mod @@ -69,10 +69,10 @@ require ( github.com/rogpeppe/go-internal v1.12.0 github.com/scylladb/go-reflectx v1.0.1 github.com/shirou/gopsutil/v3 v3.24.3 - github.com/shopspring/decimal v1.3.1 + github.com/shopspring/decimal v1.4.0 github.com/smartcontractkit/chain-selectors v1.0.10 github.com/smartcontractkit/chainlink-automation v1.0.4 - github.com/smartcontractkit/chainlink-common v0.2.1 + github.com/smartcontractkit/chainlink-common v0.2.2-0.20240723123524-e407ecd120b1 github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240710121324-3ed288aa9b45 github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240718160222-2dc0c8136bfa github.com/smartcontractkit/chainlink-feeds v0.0.0-20240710170203-5b41615da827 @@ -95,21 +95,21 @@ require ( go.dedis.ch/fixbuf v1.0.3 go.dedis.ch/kyber/v3 v3.1.0 go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin v0.49.0 - go.opentelemetry.io/otel v1.27.0 + go.opentelemetry.io/otel v1.28.0 go.uber.org/multierr v1.11.0 - go.uber.org/zap v1.26.0 - golang.org/x/crypto v0.24.0 - golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8 - golang.org/x/mod v0.17.0 - golang.org/x/net v0.25.0 + go.uber.org/zap v1.27.0 + golang.org/x/crypto v0.25.0 + golang.org/x/exp v0.0.0-20240716175740-e3f259677ff7 + golang.org/x/mod v0.19.0 + golang.org/x/net v0.27.0 golang.org/x/sync v0.7.0 - golang.org/x/term v0.21.0 + golang.org/x/term v0.22.0 golang.org/x/text v0.16.0 golang.org/x/time v0.5.0 - golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d - gonum.org/v1/gonum v0.14.0 - google.golang.org/grpc v1.64.0 - google.golang.org/protobuf v1.34.1 + golang.org/x/tools v0.23.0 + gonum.org/v1/gonum v0.15.0 + google.golang.org/grpc v1.65.0 + google.golang.org/protobuf v1.34.2 gopkg.in/guregu/null.v4 v4.0.0 gopkg.in/natefinch/lumberjack.v2 v2.2.1 ) @@ -144,7 +144,7 @@ require ( github.com/cenkalti/backoff v2.2.1+incompatible // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/cespare/xxhash v1.1.0 // indirect - github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect github.com/chenzhuoyu/iasm v0.9.0 // indirect github.com/cockroachdb/errors v1.9.1 // indirect @@ -193,7 +193,7 @@ require ( github.com/go-kit/kit v0.12.0 // indirect github.com/go-kit/log v0.2.1 // indirect github.com/go-logfmt/logfmt v0.6.0 // indirect - github.com/go-logr/logr v1.4.1 // indirect + github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.2.6 // indirect github.com/go-playground/locales v0.14.1 // indirect @@ -205,7 +205,7 @@ require ( github.com/gofrs/flock v0.8.1 // indirect github.com/gogo/protobuf v1.3.3 // indirect github.com/golang-jwt/jwt/v5 v5.2.0 // indirect - github.com/golang/glog v1.2.0 // indirect + github.com/golang/glog v1.2.1 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect @@ -319,18 +319,18 @@ require ( go.mongodb.org/mongo-driver v1.15.0 // indirect go.opencensus.io v0.24.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.52.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.27.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0 // indirect - go.opentelemetry.io/otel/metric v1.27.0 // indirect - go.opentelemetry.io/otel/sdk v1.27.0 // indirect - go.opentelemetry.io/otel/trace v1.27.0 // indirect - go.opentelemetry.io/proto/otlp v1.2.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0 // indirect + go.opentelemetry.io/otel/metric v1.28.0 // indirect + go.opentelemetry.io/otel/sdk v1.28.0 // indirect + go.opentelemetry.io/otel/trace v1.28.0 // indirect + go.opentelemetry.io/proto/otlp v1.3.1 // indirect go.uber.org/ratelimit v0.3.0 // indirect golang.org/x/arch v0.7.0 // indirect - golang.org/x/sys v0.21.0 // indirect + golang.org/x/sys v0.22.0 // indirect google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240520151616-dc85e6b867a5 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240520151616-dc85e6b867a5 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240711142825-46eb208f015d // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240711142825-46eb208f015d // indirect gopkg.in/guregu/null.v2 v2.1.2 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect diff --git a/go.sum b/go.sum index ab268b6556..4851cd9e75 100644 --- a/go.sum +++ b/go.sum @@ -26,7 +26,7 @@ cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvf cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/compute v1.25.1 h1:ZRpHJedLtTpKgr3RV1Fx23NuaAEN1Zfx9hw1u4aJdjU= +cloud.google.com/go/compute v1.24.0 h1:phWcR2eWzRJaL/kOiJwfFsPs4BaKq1j6vnpZrc1YlVg= cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc= cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= @@ -198,8 +198,9 @@ github.com/cespare/cp v1.1.1/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY= github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk= github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d h1:77cEq6EriyTZ0g/qfRdp61a3Uu/AWrgIq2s0ClJV1g0= @@ -450,8 +451,8 @@ github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4= github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= -github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8= @@ -503,8 +504,8 @@ github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w github.com/golang-jwt/jwt/v5 v5.2.0 h1:d/ix8ftRUorsN+5eMIlF4T6J8CAt9rch3My2winC1Jw= github.com/golang-jwt/jwt/v5 v5.2.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.2.0 h1:uCdmnmatrKCgMBlM4rMuJZWOkPDqdbZPnrMXDY4gI68= -github.com/golang/glog v1.2.0/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= +github.com/golang/glog v1.2.1 h1:OptwRhECazUx5ix5TTWC3EZhsZEHWcYWY4FQHTIubm4= +github.com/golang/glog v1.2.1/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -1119,8 +1120,9 @@ github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= -github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= +github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k= +github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= @@ -1131,8 +1133,8 @@ github.com/smartcontractkit/chain-selectors v1.0.10 h1:t9kJeE6B6G+hKD0GYR4kGJSCq github.com/smartcontractkit/chain-selectors v1.0.10/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/smartcontractkit/chainlink-automation v1.0.4 h1:iyW181JjKHLNMnDleI8umfIfVVlwC7+n5izbLSFgjw8= github.com/smartcontractkit/chainlink-automation v1.0.4/go.mod h1:u4NbPZKJ5XiayfKHD/v3z3iflQWqvtdhj13jVZXj/cM= -github.com/smartcontractkit/chainlink-common v0.2.1 h1:IqaJBQf6lkSiV58jnCx/TtxHzrXPavDjBmt4LgEHy4U= -github.com/smartcontractkit/chainlink-common v0.2.1/go.mod h1:fh9eBbrReCmv31bfz52ENCAMa7nTKQbdhb2B3+S2VGo= +github.com/smartcontractkit/chainlink-common v0.2.2-0.20240723123524-e407ecd120b1 h1:pdEpjgbZ5w/Sd5lzg/XiuC5gVyrmSovOo+3nUD46SP8= +github.com/smartcontractkit/chainlink-common v0.2.2-0.20240723123524-e407ecd120b1/go.mod h1:Jg1sCTsbxg76YByI8ifpFby3FvVqISStHT8ypy9ocmY= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240710121324-3ed288aa9b45 h1:NBQLtqk8zsyY4qTJs+NElI3aDFTcAo83JHvqD04EvB0= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240710121324-3ed288aa9b45/go.mod h1:LV0h7QBQUpoC2UUi6TcUvcIFm1xjP/DtEcqV8+qeLUs= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240718160222-2dc0c8136bfa h1:g75H8oh2ws52s8BekwvGQ9XvBVu3E7WM1rfiA0PN0zk= @@ -1341,22 +1343,22 @@ go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw= go.opentelemetry.io/contrib/propagators/b3 v1.24.0 h1:n4xwCdTx3pZqZs2CjS/CUZAs03y3dZcGhC/FepKtEUY= go.opentelemetry.io/contrib/propagators/b3 v1.24.0/go.mod h1:k5wRxKRU2uXx2F8uNJ4TaonuEO/V7/5xoz7kdsDACT8= -go.opentelemetry.io/otel v1.27.0 h1:9BZoF3yMK/O1AafMiQTVu0YDj5Ea4hPhxCs7sGva+cg= -go.opentelemetry.io/otel v1.27.0/go.mod h1:DMpAK8fzYRzs+bi3rS5REupisuqTheUlSZJ1WnZaPAQ= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.27.0 h1:R9DE4kQ4k+YtfLI2ULwX82VtNQ2J8yZmA7ZIF/D+7Mc= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.27.0/go.mod h1:OQFyQVrDlbe+R7xrEyDr/2Wr67Ol0hRUgsfA+V5A95s= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0 h1:qFffATk0X+HD+f1Z8lswGiOQYKHRlzfmdJm0wEaVrFA= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0/go.mod h1:MOiCmryaYtc+V0Ei+Tx9o5S1ZjA7kzLucuVuyzBZloQ= -go.opentelemetry.io/otel/metric v1.27.0 h1:hvj3vdEKyeCi4YaYfNjv2NUje8FqKqUY8IlF0FxV/ik= -go.opentelemetry.io/otel/metric v1.27.0/go.mod h1:mVFgmRlhljgBiuk/MP/oKylr4hs85GZAylncepAX/ak= -go.opentelemetry.io/otel/sdk v1.27.0 h1:mlk+/Y1gLPLn84U4tI8d3GNJmGT/eXe3ZuOXN9kTWmI= -go.opentelemetry.io/otel/sdk v1.27.0/go.mod h1:Ha9vbLwJE6W86YstIywK2xFfPjbWlCuwPtMkKdz/Y4A= +go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo= +go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 h1:3Q/xZUyC1BBkualc9ROb4G8qkH90LXEIICcs5zv1OYY= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0/go.mod h1:s75jGIWA9OfCMzF0xr+ZgfrB5FEbbV7UuYo32ahUiFI= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0 h1:R3X6ZXmNPRR8ul6i3WgFURCHzaXjHdm0karRG/+dj3s= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0/go.mod h1:QWFXnDavXWwMx2EEcZsf3yxgEKAqsxQ+Syjp+seyInw= +go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q= +go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s= +go.opentelemetry.io/otel/sdk v1.28.0 h1:b9d7hIry8yZsgtbmM0DKyPWMMUMlK9NEKuIG4aBqWyE= +go.opentelemetry.io/otel/sdk v1.28.0/go.mod h1:oYj7ClPUA7Iw3m+r7GeEjz0qckQRJK2B8zjcZEfu7Pg= go.opentelemetry.io/otel/sdk/metric v1.21.0 h1:smhI5oD714d6jHE6Tie36fPx4WDFIg+Y6RfAY4ICcR0= go.opentelemetry.io/otel/sdk/metric v1.21.0/go.mod h1:FJ8RAsoPGv/wYMgBdUJXOm+6pzFY3YdljnXtv1SBE8Q= -go.opentelemetry.io/otel/trace v1.27.0 h1:IqYb813p7cmbHk0a5y6pD5JPakbVfftRXABGt5/Rscw= -go.opentelemetry.io/otel/trace v1.27.0/go.mod h1:6RiD1hkAprV4/q+yd2ln1HG9GoPx39SuvvstaLBl+l4= -go.opentelemetry.io/proto/otlp v1.2.0 h1:pVeZGk7nXDC9O2hncA6nHldxEjm6LByfA2aN8IOkz94= -go.opentelemetry.io/proto/otlp v1.2.0/go.mod h1:gGpR8txAl5M03pDhMC79G6SdqNV26naRm/KDsgaHD8A= +go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g= +go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI= +go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= +go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= @@ -1384,8 +1386,8 @@ go.uber.org/zap v1.14.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= -go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= -go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/arch v0.7.0 h1:pskyeJh/3AmoQ8CPE95vxHLqp1G1GfGNXTmcl9NEKTc= golang.org/x/arch v0.7.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= @@ -1416,8 +1418,8 @@ golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0 golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= -golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= +golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1428,8 +1430,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8 h1:aAcj0Da7eBAtrTp03QXWvm88pSyOt+UgdZw2BFZ+lEw= -golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8/go.mod h1:CQ1k9gNrJ50XIzaKCRR2hssIjF07kZFEiieALBM/ARQ= +golang.org/x/exp v0.0.0-20240716175740-e3f259677ff7 h1:wDLEX9a7YQoKdKNQt88rtydkqDxeGaBUTnIYc3iG/mA= +golang.org/x/exp v0.0.0-20240716175740-e3f259677ff7/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -1457,8 +1459,8 @@ golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= -golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8= +golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1514,8 +1516,8 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= -golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= +golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= +golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1626,8 +1628,8 @@ golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= +golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -1636,8 +1638,8 @@ golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= -golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= -golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= +golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk= +golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1724,8 +1726,8 @@ golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= +golang.org/x/tools v0.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg= +golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI= golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1733,8 +1735,8 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -gonum.org/v1/gonum v0.14.0 h1:2NiG67LD1tEH0D7kM+ps2V+fXmsAnpUeec7n8tcr4S0= -gonum.org/v1/gonum v0.14.0/go.mod h1:AoWeoz0becf9QMWtE8iWXNXc27fK4fNeHNf/oMejGfU= +gonum.org/v1/gonum v0.15.0 h1:2lYxjRbTYyxkJxlhC+LvJIx3SsANPdRybu1tGj9/OrQ= +gonum.org/v1/gonum v0.15.0/go.mod h1:xzZVBJBtS+Mz4q0Yl2LJTk+OxOg4jiXZ7qBoM0uISGo= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= @@ -1811,10 +1813,10 @@ google.golang.org/genproto v0.0.0-20210401141331-865547bb08e2/go.mod h1:9lPAdzaE google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 h1:9+tzLLstTlPTRyJTh+ah5wIMsBW5c4tQwGTN3thOW9Y= google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9/go.mod h1:mqHbVIp48Muh7Ywss/AD6I5kNVKZMmAa/QEW58Gxp2s= -google.golang.org/genproto/googleapis/api v0.0.0-20240520151616-dc85e6b867a5 h1:P8OJ/WCl/Xo4E4zoe4/bifHpSmmKwARqyqE4nW6J2GQ= -google.golang.org/genproto/googleapis/api v0.0.0-20240520151616-dc85e6b867a5/go.mod h1:RGnPtTG7r4i8sPlNyDeikXF99hMM+hN6QMm4ooG9g2g= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240520151616-dc85e6b867a5 h1:Q2RxlXqh1cgzzUgV261vBO2jI5R/3DD1J2pM0nI4NhU= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240520151616-dc85e6b867a5/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= +google.golang.org/genproto/googleapis/api v0.0.0-20240711142825-46eb208f015d h1:kHjw/5UfflP/L5EbledDrcG4C2597RtymmGRZvHiCuY= +google.golang.org/genproto/googleapis/api v0.0.0-20240711142825-46eb208f015d/go.mod h1:mw8MG/Qz5wfgYr6VqVCiZcHe/GJEfI+oGGDCohaVgB0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240711142825-46eb208f015d h1:JU0iKnSg02Gmb5ZdV8nYsKEKsP6o/FGVWTrw4i1DA9A= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240711142825-46eb208f015d/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= google.golang.org/grpc v1.12.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= @@ -1837,8 +1839,8 @@ google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA5 google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.64.0 h1:KH3VH9y/MgNQg1dE7b3XfVK0GsPSIzJwdF617gUSbvY= -google.golang.org/grpc v1.64.0/go.mod h1:oxjF8E3FBnjp+/gVFYdWacaLDx9na1aqy9oovLpxQYg= +google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc= +google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -1852,8 +1854,8 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= -google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/integration-tests/go.mod b/integration-tests/go.mod index 9d40115908..6d816df2a4 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -25,10 +25,10 @@ require ( github.com/rs/zerolog v1.31.0 github.com/scylladb/go-reflectx v1.0.1 github.com/segmentio/ksuid v1.0.4 - github.com/shopspring/decimal v1.3.1 + github.com/shopspring/decimal v1.4.0 github.com/slack-go/slack v0.12.2 github.com/smartcontractkit/chainlink-automation v1.0.4 - github.com/smartcontractkit/chainlink-common v0.2.1 + github.com/smartcontractkit/chainlink-common v0.2.2-0.20240723123524-e407ecd120b1 github.com/smartcontractkit/chainlink-testing-framework v1.32.7 github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240405215812-5a72bc9af239 github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000 @@ -41,7 +41,7 @@ require ( github.com/test-go/testify v1.1.4 github.com/testcontainers/testcontainers-go v0.28.0 github.com/umbracle/ethgo v0.1.3 - go.uber.org/zap v1.26.0 + go.uber.org/zap v1.27.0 golang.org/x/sync v0.7.0 golang.org/x/text v0.16.0 gopkg.in/guregu/null.v4 v4.0.0 @@ -213,7 +213,7 @@ require ( github.com/gogo/protobuf v1.3.3 // indirect github.com/gogo/status v1.1.1 // indirect github.com/golang-jwt/jwt/v5 v5.2.0 // indirect - github.com/golang/glog v1.2.0 // indirect + github.com/golang/glog v1.2.1 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect @@ -432,13 +432,13 @@ require ( go.opentelemetry.io/collector/semconv v0.87.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.52.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect - go.opentelemetry.io/otel v1.27.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.27.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0 // indirect - go.opentelemetry.io/otel/metric v1.27.0 // indirect - go.opentelemetry.io/otel/sdk v1.27.0 // indirect - go.opentelemetry.io/otel/trace v1.27.0 // indirect - go.opentelemetry.io/proto/otlp v1.2.0 // indirect + go.opentelemetry.io/otel v1.28.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0 // indirect + go.opentelemetry.io/otel/metric v1.28.0 // indirect + go.opentelemetry.io/otel/sdk v1.28.0 // indirect + go.opentelemetry.io/otel/trace v1.28.0 // indirect + go.opentelemetry.io/proto/otlp v1.3.1 // indirect go.starlark.net v0.0.0-20230525235612-a134d8f9ddca // indirect go.uber.org/atomic v1.11.0 // indirect go.uber.org/goleak v1.3.0 // indirect @@ -447,7 +447,7 @@ require ( go4.org/netipx v0.0.0-20230125063823-8449b0a6169f // indirect golang.org/x/arch v0.7.0 // indirect golang.org/x/crypto v0.25.0 // indirect - golang.org/x/exp v0.0.0-20240707233637-46b078467d37 // indirect + golang.org/x/exp v0.0.0-20240716175740-e3f259677ff7 // indirect golang.org/x/mod v0.19.0 // indirect golang.org/x/net v0.27.0 // indirect golang.org/x/oauth2 v0.21.0 // indirect @@ -456,11 +456,11 @@ require ( golang.org/x/time v0.5.0 // indirect golang.org/x/tools v0.23.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect - gonum.org/v1/gonum v0.14.0 // indirect + gonum.org/v1/gonum v0.15.0 // indirect google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240520151616-dc85e6b867a5 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240520151616-dc85e6b867a5 // indirect - google.golang.org/grpc v1.64.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240711142825-46eb208f015d // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240711142825-46eb208f015d // indirect + google.golang.org/grpc v1.65.0 // indirect google.golang.org/protobuf v1.34.2 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect diff --git a/integration-tests/go.sum b/integration-tests/go.sum index d00a67d042..24120b51ba 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -26,7 +26,7 @@ cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvf cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/compute v1.25.1 h1:ZRpHJedLtTpKgr3RV1Fx23NuaAEN1Zfx9hw1u4aJdjU= +cloud.google.com/go/compute v1.24.0 h1:phWcR2eWzRJaL/kOiJwfFsPs4BaKq1j6vnpZrc1YlVg= cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc= cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= @@ -302,8 +302,8 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/xds/go v0.0.0-20240318125728-8a4994d93e50 h1:DBmgJDC9dTfkVyGgipamEh2BpGYxScCH1TOF1LL1cXc= -github.com/cncf/xds/go v0.0.0-20240318125728-8a4994d93e50/go.mod h1:5e1+Vvlzido69INQaVO6d87Qn543Xr6nooe9Kz7oBFM= +github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b h1:ga8SEFjZ60pxLcmhnThWgvH2wg8376yUJmPhEH4H3kw= +github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I= github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= github.com/cockroachdb/apd/v2 v2.0.2 h1:weh8u7Cneje73dDh+2tEVLUvyBc89iwepWCD8b8034E= @@ -708,8 +708,8 @@ github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w github.com/golang-jwt/jwt/v5 v5.2.0 h1:d/ix8ftRUorsN+5eMIlF4T6J8CAt9rch3My2winC1Jw= github.com/golang-jwt/jwt/v5 v5.2.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.2.0 h1:uCdmnmatrKCgMBlM4rMuJZWOkPDqdbZPnrMXDY4gI68= -github.com/golang/glog v1.2.0/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= +github.com/golang/glog v1.2.1 h1:OptwRhECazUx5ix5TTWC3EZhsZEHWcYWY4FQHTIubm4= +github.com/golang/glog v1.2.1/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -1467,8 +1467,9 @@ github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= -github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= +github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k= +github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= @@ -1481,8 +1482,8 @@ github.com/smartcontractkit/chain-selectors v1.0.10 h1:t9kJeE6B6G+hKD0GYR4kGJSCq github.com/smartcontractkit/chain-selectors v1.0.10/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/smartcontractkit/chainlink-automation v1.0.4 h1:iyW181JjKHLNMnDleI8umfIfVVlwC7+n5izbLSFgjw8= github.com/smartcontractkit/chainlink-automation v1.0.4/go.mod h1:u4NbPZKJ5XiayfKHD/v3z3iflQWqvtdhj13jVZXj/cM= -github.com/smartcontractkit/chainlink-common v0.2.1 h1:IqaJBQf6lkSiV58jnCx/TtxHzrXPavDjBmt4LgEHy4U= -github.com/smartcontractkit/chainlink-common v0.2.1/go.mod h1:fh9eBbrReCmv31bfz52ENCAMa7nTKQbdhb2B3+S2VGo= +github.com/smartcontractkit/chainlink-common v0.2.2-0.20240723123524-e407ecd120b1 h1:pdEpjgbZ5w/Sd5lzg/XiuC5gVyrmSovOo+3nUD46SP8= +github.com/smartcontractkit/chainlink-common v0.2.2-0.20240723123524-e407ecd120b1/go.mod h1:Jg1sCTsbxg76YByI8ifpFby3FvVqISStHT8ypy9ocmY= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240710121324-3ed288aa9b45 h1:NBQLtqk8zsyY4qTJs+NElI3aDFTcAo83JHvqD04EvB0= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240710121324-3ed288aa9b45/go.mod h1:LV0h7QBQUpoC2UUi6TcUvcIFm1xjP/DtEcqV8+qeLUs= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240718160222-2dc0c8136bfa h1:g75H8oh2ws52s8BekwvGQ9XvBVu3E7WM1rfiA0PN0zk= @@ -1731,24 +1732,24 @@ go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.5 go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.52.0/go.mod h1:BMsdeOxN04K0L5FNUBfjFdvwWGNe/rkmSwH4Aelu/X0= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw= -go.opentelemetry.io/otel v1.27.0 h1:9BZoF3yMK/O1AafMiQTVu0YDj5Ea4hPhxCs7sGva+cg= -go.opentelemetry.io/otel v1.27.0/go.mod h1:DMpAK8fzYRzs+bi3rS5REupisuqTheUlSZJ1WnZaPAQ= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.27.0 h1:R9DE4kQ4k+YtfLI2ULwX82VtNQ2J8yZmA7ZIF/D+7Mc= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.27.0/go.mod h1:OQFyQVrDlbe+R7xrEyDr/2Wr67Ol0hRUgsfA+V5A95s= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0 h1:qFffATk0X+HD+f1Z8lswGiOQYKHRlzfmdJm0wEaVrFA= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0/go.mod h1:MOiCmryaYtc+V0Ei+Tx9o5S1ZjA7kzLucuVuyzBZloQ= +go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo= +go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 h1:3Q/xZUyC1BBkualc9ROb4G8qkH90LXEIICcs5zv1OYY= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0/go.mod h1:s75jGIWA9OfCMzF0xr+ZgfrB5FEbbV7UuYo32ahUiFI= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0 h1:R3X6ZXmNPRR8ul6i3WgFURCHzaXjHdm0karRG/+dj3s= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0/go.mod h1:QWFXnDavXWwMx2EEcZsf3yxgEKAqsxQ+Syjp+seyInw= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 h1:IeMeyr1aBvBiPVYihXIaeIZba6b8E1bYp7lbdxK8CQg= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0/go.mod h1:oVdCUtjq9MK9BlS7TtucsQwUcXcymNiEDjgDD2jMtZU= -go.opentelemetry.io/otel/metric v1.27.0 h1:hvj3vdEKyeCi4YaYfNjv2NUje8FqKqUY8IlF0FxV/ik= -go.opentelemetry.io/otel/metric v1.27.0/go.mod h1:mVFgmRlhljgBiuk/MP/oKylr4hs85GZAylncepAX/ak= -go.opentelemetry.io/otel/sdk v1.27.0 h1:mlk+/Y1gLPLn84U4tI8d3GNJmGT/eXe3ZuOXN9kTWmI= -go.opentelemetry.io/otel/sdk v1.27.0/go.mod h1:Ha9vbLwJE6W86YstIywK2xFfPjbWlCuwPtMkKdz/Y4A= +go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q= +go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s= +go.opentelemetry.io/otel/sdk v1.28.0 h1:b9d7hIry8yZsgtbmM0DKyPWMMUMlK9NEKuIG4aBqWyE= +go.opentelemetry.io/otel/sdk v1.28.0/go.mod h1:oYj7ClPUA7Iw3m+r7GeEjz0qckQRJK2B8zjcZEfu7Pg= go.opentelemetry.io/otel/sdk/metric v1.21.0 h1:smhI5oD714d6jHE6Tie36fPx4WDFIg+Y6RfAY4ICcR0= go.opentelemetry.io/otel/sdk/metric v1.21.0/go.mod h1:FJ8RAsoPGv/wYMgBdUJXOm+6pzFY3YdljnXtv1SBE8Q= -go.opentelemetry.io/otel/trace v1.27.0 h1:IqYb813p7cmbHk0a5y6pD5JPakbVfftRXABGt5/Rscw= -go.opentelemetry.io/otel/trace v1.27.0/go.mod h1:6RiD1hkAprV4/q+yd2ln1HG9GoPx39SuvvstaLBl+l4= -go.opentelemetry.io/proto/otlp v1.2.0 h1:pVeZGk7nXDC9O2hncA6nHldxEjm6LByfA2aN8IOkz94= -go.opentelemetry.io/proto/otlp v1.2.0/go.mod h1:gGpR8txAl5M03pDhMC79G6SdqNV26naRm/KDsgaHD8A= +go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g= +go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI= +go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= +go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= go.starlark.net v0.0.0-20230525235612-a134d8f9ddca h1:VdD38733bfYv5tUZwEIskMM93VanwNIi5bIKnDrJdEY= go.starlark.net v0.0.0-20230525235612-a134d8f9ddca/go.mod h1:jxU+3+j+71eXOW14274+SmmuW82qJzl6iZSeqEtTGds= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= @@ -1778,8 +1779,8 @@ go.uber.org/zap v1.14.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= -go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= -go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= go4.org/netipx v0.0.0-20230125063823-8449b0a6169f h1:ketMxHg+vWm3yccyYiq+uK8D3fRmna2Fcj+awpQp84s= go4.org/netipx v0.0.0-20230125063823-8449b0a6169f/go.mod h1:tgPU4N2u9RByaTN3NC2p9xOzyFpte4jYwsIIRF7XlSc= golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= @@ -1829,8 +1830,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20240707233637-46b078467d37 h1:uLDX+AfeFCct3a2C7uIWBKMJIR3CJMhcgfrUAqjRK6w= -golang.org/x/exp v0.0.0-20240707233637-46b078467d37/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= +golang.org/x/exp v0.0.0-20240716175740-e3f259677ff7 h1:wDLEX9a7YQoKdKNQt88rtydkqDxeGaBUTnIYc3iG/mA= +golang.org/x/exp v0.0.0-20240716175740-e3f259677ff7/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -2167,8 +2168,8 @@ golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw= gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= -gonum.org/v1/gonum v0.14.0 h1:2NiG67LD1tEH0D7kM+ps2V+fXmsAnpUeec7n8tcr4S0= -gonum.org/v1/gonum v0.14.0/go.mod h1:AoWeoz0becf9QMWtE8iWXNXc27fK4fNeHNf/oMejGfU= +gonum.org/v1/gonum v0.15.0 h1:2lYxjRbTYyxkJxlhC+LvJIx3SsANPdRybu1tGj9/OrQ= +gonum.org/v1/gonum v0.15.0/go.mod h1:xzZVBJBtS+Mz4q0Yl2LJTk+OxOg4jiXZ7qBoM0uISGo= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= @@ -2245,10 +2246,10 @@ google.golang.org/genproto v0.0.0-20210401141331-865547bb08e2/go.mod h1:9lPAdzaE google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 h1:9+tzLLstTlPTRyJTh+ah5wIMsBW5c4tQwGTN3thOW9Y= google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9/go.mod h1:mqHbVIp48Muh7Ywss/AD6I5kNVKZMmAa/QEW58Gxp2s= -google.golang.org/genproto/googleapis/api v0.0.0-20240520151616-dc85e6b867a5 h1:P8OJ/WCl/Xo4E4zoe4/bifHpSmmKwARqyqE4nW6J2GQ= -google.golang.org/genproto/googleapis/api v0.0.0-20240520151616-dc85e6b867a5/go.mod h1:RGnPtTG7r4i8sPlNyDeikXF99hMM+hN6QMm4ooG9g2g= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240520151616-dc85e6b867a5 h1:Q2RxlXqh1cgzzUgV261vBO2jI5R/3DD1J2pM0nI4NhU= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240520151616-dc85e6b867a5/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= +google.golang.org/genproto/googleapis/api v0.0.0-20240711142825-46eb208f015d h1:kHjw/5UfflP/L5EbledDrcG4C2597RtymmGRZvHiCuY= +google.golang.org/genproto/googleapis/api v0.0.0-20240711142825-46eb208f015d/go.mod h1:mw8MG/Qz5wfgYr6VqVCiZcHe/GJEfI+oGGDCohaVgB0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240711142825-46eb208f015d h1:JU0iKnSg02Gmb5ZdV8nYsKEKsP6o/FGVWTrw4i1DA9A= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240711142825-46eb208f015d/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= google.golang.org/grpc v1.12.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= @@ -2271,8 +2272,8 @@ google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA5 google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.64.0 h1:KH3VH9y/MgNQg1dE7b3XfVK0GsPSIzJwdF617gUSbvY= -google.golang.org/grpc v1.64.0/go.mod h1:oxjF8E3FBnjp+/gVFYdWacaLDx9na1aqy9oovLpxQYg= +google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc= +google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index b0b2e42654..5e6d5af25b 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -16,7 +16,7 @@ require ( github.com/rs/zerolog v1.31.0 github.com/slack-go/slack v0.12.2 github.com/smartcontractkit/chainlink-automation v1.0.4 - github.com/smartcontractkit/chainlink-common v0.2.1 + github.com/smartcontractkit/chainlink-common v0.2.2-0.20240723123524-e407ecd120b1 github.com/smartcontractkit/chainlink-testing-framework v1.32.7 github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20240214231432-4ad5eb95178c github.com/smartcontractkit/chainlink/v2 v2.9.0-beta0.0.20240216210048-da02459ddad8 @@ -202,7 +202,7 @@ require ( github.com/gogo/protobuf v1.3.3 // indirect github.com/gogo/status v1.1.1 // indirect github.com/golang-jwt/jwt/v5 v5.2.0 // indirect - github.com/golang/glog v1.2.0 // indirect + github.com/golang/glog v1.2.1 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect @@ -366,7 +366,7 @@ require ( github.com/shirou/gopsutil v3.21.11+incompatible // indirect github.com/shirou/gopsutil/v3 v3.24.3 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect - github.com/shopspring/decimal v1.3.1 // indirect + github.com/shopspring/decimal v1.4.0 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/chain-selectors v1.0.10 // indirect github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240718160222-2dc0c8136bfa // indirect @@ -429,22 +429,22 @@ require ( go.opentelemetry.io/collector/semconv v0.87.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.52.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect - go.opentelemetry.io/otel v1.27.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.27.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0 // indirect - go.opentelemetry.io/otel/metric v1.27.0 // indirect - go.opentelemetry.io/otel/sdk v1.27.0 // indirect - go.opentelemetry.io/otel/trace v1.27.0 // indirect - go.opentelemetry.io/proto/otlp v1.2.0 // indirect + go.opentelemetry.io/otel v1.28.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0 // indirect + go.opentelemetry.io/otel/metric v1.28.0 // indirect + go.opentelemetry.io/otel/sdk v1.28.0 // indirect + go.opentelemetry.io/otel/trace v1.28.0 // indirect + go.opentelemetry.io/proto/otlp v1.3.1 // indirect go.starlark.net v0.0.0-20230525235612-a134d8f9ddca // indirect go.uber.org/atomic v1.11.0 // indirect go.uber.org/goleak v1.3.0 // indirect go.uber.org/multierr v1.11.0 // indirect - go.uber.org/zap v1.26.0 // indirect + go.uber.org/zap v1.27.0 // indirect go4.org/netipx v0.0.0-20230125063823-8449b0a6169f // indirect golang.org/x/arch v0.7.0 // indirect golang.org/x/crypto v0.25.0 // indirect - golang.org/x/exp v0.0.0-20240707233637-46b078467d37 // indirect + golang.org/x/exp v0.0.0-20240716175740-e3f259677ff7 // indirect golang.org/x/mod v0.19.0 // indirect golang.org/x/net v0.27.0 // indirect golang.org/x/oauth2 v0.21.0 // indirect @@ -455,11 +455,11 @@ require ( golang.org/x/time v0.5.0 // indirect golang.org/x/tools v0.23.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect - gonum.org/v1/gonum v0.14.0 // indirect + gonum.org/v1/gonum v0.15.0 // indirect google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240520151616-dc85e6b867a5 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240520151616-dc85e6b867a5 // indirect - google.golang.org/grpc v1.64.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240711142825-46eb208f015d // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240711142825-46eb208f015d // indirect + google.golang.org/grpc v1.65.0 // indirect google.golang.org/protobuf v1.34.2 // indirect gopkg.in/guregu/null.v4 v4.0.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index 31d07103c5..a1797f1459 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -26,7 +26,7 @@ cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvf cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/compute v1.25.1 h1:ZRpHJedLtTpKgr3RV1Fx23NuaAEN1Zfx9hw1u4aJdjU= +cloud.google.com/go/compute v1.24.0 h1:phWcR2eWzRJaL/kOiJwfFsPs4BaKq1j6vnpZrc1YlVg= cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc= cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= @@ -292,8 +292,8 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/xds/go v0.0.0-20240318125728-8a4994d93e50 h1:DBmgJDC9dTfkVyGgipamEh2BpGYxScCH1TOF1LL1cXc= -github.com/cncf/xds/go v0.0.0-20240318125728-8a4994d93e50/go.mod h1:5e1+Vvlzido69INQaVO6d87Qn543Xr6nooe9Kz7oBFM= +github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b h1:ga8SEFjZ60pxLcmhnThWgvH2wg8376yUJmPhEH4H3kw= +github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I= github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= github.com/cockroachdb/apd/v2 v2.0.2 h1:weh8u7Cneje73dDh+2tEVLUvyBc89iwepWCD8b8034E= @@ -698,8 +698,8 @@ github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w github.com/golang-jwt/jwt/v5 v5.2.0 h1:d/ix8ftRUorsN+5eMIlF4T6J8CAt9rch3My2winC1Jw= github.com/golang-jwt/jwt/v5 v5.2.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.2.0 h1:uCdmnmatrKCgMBlM4rMuJZWOkPDqdbZPnrMXDY4gI68= -github.com/golang/glog v1.2.0/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= +github.com/golang/glog v1.2.1 h1:OptwRhECazUx5ix5TTWC3EZhsZEHWcYWY4FQHTIubm4= +github.com/golang/glog v1.2.1/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -1449,8 +1449,9 @@ github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= -github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= +github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k= +github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= @@ -1463,8 +1464,8 @@ github.com/smartcontractkit/chain-selectors v1.0.10 h1:t9kJeE6B6G+hKD0GYR4kGJSCq github.com/smartcontractkit/chain-selectors v1.0.10/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/smartcontractkit/chainlink-automation v1.0.4 h1:iyW181JjKHLNMnDleI8umfIfVVlwC7+n5izbLSFgjw8= github.com/smartcontractkit/chainlink-automation v1.0.4/go.mod h1:u4NbPZKJ5XiayfKHD/v3z3iflQWqvtdhj13jVZXj/cM= -github.com/smartcontractkit/chainlink-common v0.2.1 h1:IqaJBQf6lkSiV58jnCx/TtxHzrXPavDjBmt4LgEHy4U= -github.com/smartcontractkit/chainlink-common v0.2.1/go.mod h1:fh9eBbrReCmv31bfz52ENCAMa7nTKQbdhb2B3+S2VGo= +github.com/smartcontractkit/chainlink-common v0.2.2-0.20240723123524-e407ecd120b1 h1:pdEpjgbZ5w/Sd5lzg/XiuC5gVyrmSovOo+3nUD46SP8= +github.com/smartcontractkit/chainlink-common v0.2.2-0.20240723123524-e407ecd120b1/go.mod h1:Jg1sCTsbxg76YByI8ifpFby3FvVqISStHT8ypy9ocmY= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240710121324-3ed288aa9b45 h1:NBQLtqk8zsyY4qTJs+NElI3aDFTcAo83JHvqD04EvB0= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240710121324-3ed288aa9b45/go.mod h1:LV0h7QBQUpoC2UUi6TcUvcIFm1xjP/DtEcqV8+qeLUs= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240718160222-2dc0c8136bfa h1:g75H8oh2ws52s8BekwvGQ9XvBVu3E7WM1rfiA0PN0zk= @@ -1713,24 +1714,24 @@ go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.5 go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.52.0/go.mod h1:BMsdeOxN04K0L5FNUBfjFdvwWGNe/rkmSwH4Aelu/X0= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw= -go.opentelemetry.io/otel v1.27.0 h1:9BZoF3yMK/O1AafMiQTVu0YDj5Ea4hPhxCs7sGva+cg= -go.opentelemetry.io/otel v1.27.0/go.mod h1:DMpAK8fzYRzs+bi3rS5REupisuqTheUlSZJ1WnZaPAQ= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.27.0 h1:R9DE4kQ4k+YtfLI2ULwX82VtNQ2J8yZmA7ZIF/D+7Mc= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.27.0/go.mod h1:OQFyQVrDlbe+R7xrEyDr/2Wr67Ol0hRUgsfA+V5A95s= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0 h1:qFffATk0X+HD+f1Z8lswGiOQYKHRlzfmdJm0wEaVrFA= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0/go.mod h1:MOiCmryaYtc+V0Ei+Tx9o5S1ZjA7kzLucuVuyzBZloQ= +go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo= +go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 h1:3Q/xZUyC1BBkualc9ROb4G8qkH90LXEIICcs5zv1OYY= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0/go.mod h1:s75jGIWA9OfCMzF0xr+ZgfrB5FEbbV7UuYo32ahUiFI= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0 h1:R3X6ZXmNPRR8ul6i3WgFURCHzaXjHdm0karRG/+dj3s= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0/go.mod h1:QWFXnDavXWwMx2EEcZsf3yxgEKAqsxQ+Syjp+seyInw= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 h1:IeMeyr1aBvBiPVYihXIaeIZba6b8E1bYp7lbdxK8CQg= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0/go.mod h1:oVdCUtjq9MK9BlS7TtucsQwUcXcymNiEDjgDD2jMtZU= -go.opentelemetry.io/otel/metric v1.27.0 h1:hvj3vdEKyeCi4YaYfNjv2NUje8FqKqUY8IlF0FxV/ik= -go.opentelemetry.io/otel/metric v1.27.0/go.mod h1:mVFgmRlhljgBiuk/MP/oKylr4hs85GZAylncepAX/ak= -go.opentelemetry.io/otel/sdk v1.27.0 h1:mlk+/Y1gLPLn84U4tI8d3GNJmGT/eXe3ZuOXN9kTWmI= -go.opentelemetry.io/otel/sdk v1.27.0/go.mod h1:Ha9vbLwJE6W86YstIywK2xFfPjbWlCuwPtMkKdz/Y4A= +go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q= +go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s= +go.opentelemetry.io/otel/sdk v1.28.0 h1:b9d7hIry8yZsgtbmM0DKyPWMMUMlK9NEKuIG4aBqWyE= +go.opentelemetry.io/otel/sdk v1.28.0/go.mod h1:oYj7ClPUA7Iw3m+r7GeEjz0qckQRJK2B8zjcZEfu7Pg= go.opentelemetry.io/otel/sdk/metric v1.21.0 h1:smhI5oD714d6jHE6Tie36fPx4WDFIg+Y6RfAY4ICcR0= go.opentelemetry.io/otel/sdk/metric v1.21.0/go.mod h1:FJ8RAsoPGv/wYMgBdUJXOm+6pzFY3YdljnXtv1SBE8Q= -go.opentelemetry.io/otel/trace v1.27.0 h1:IqYb813p7cmbHk0a5y6pD5JPakbVfftRXABGt5/Rscw= -go.opentelemetry.io/otel/trace v1.27.0/go.mod h1:6RiD1hkAprV4/q+yd2ln1HG9GoPx39SuvvstaLBl+l4= -go.opentelemetry.io/proto/otlp v1.2.0 h1:pVeZGk7nXDC9O2hncA6nHldxEjm6LByfA2aN8IOkz94= -go.opentelemetry.io/proto/otlp v1.2.0/go.mod h1:gGpR8txAl5M03pDhMC79G6SdqNV26naRm/KDsgaHD8A= +go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g= +go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI= +go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= +go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= go.starlark.net v0.0.0-20230525235612-a134d8f9ddca h1:VdD38733bfYv5tUZwEIskMM93VanwNIi5bIKnDrJdEY= go.starlark.net v0.0.0-20230525235612-a134d8f9ddca/go.mod h1:jxU+3+j+71eXOW14274+SmmuW82qJzl6iZSeqEtTGds= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= @@ -1760,8 +1761,8 @@ go.uber.org/zap v1.14.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= -go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= -go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= go4.org/netipx v0.0.0-20230125063823-8449b0a6169f h1:ketMxHg+vWm3yccyYiq+uK8D3fRmna2Fcj+awpQp84s= go4.org/netipx v0.0.0-20230125063823-8449b0a6169f/go.mod h1:tgPU4N2u9RByaTN3NC2p9xOzyFpte4jYwsIIRF7XlSc= golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= @@ -1811,8 +1812,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20240707233637-46b078467d37 h1:uLDX+AfeFCct3a2C7uIWBKMJIR3CJMhcgfrUAqjRK6w= -golang.org/x/exp v0.0.0-20240707233637-46b078467d37/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= +golang.org/x/exp v0.0.0-20240716175740-e3f259677ff7 h1:wDLEX9a7YQoKdKNQt88rtydkqDxeGaBUTnIYc3iG/mA= +golang.org/x/exp v0.0.0-20240716175740-e3f259677ff7/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -2147,8 +2148,8 @@ golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw= gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= -gonum.org/v1/gonum v0.14.0 h1:2NiG67LD1tEH0D7kM+ps2V+fXmsAnpUeec7n8tcr4S0= -gonum.org/v1/gonum v0.14.0/go.mod h1:AoWeoz0becf9QMWtE8iWXNXc27fK4fNeHNf/oMejGfU= +gonum.org/v1/gonum v0.15.0 h1:2lYxjRbTYyxkJxlhC+LvJIx3SsANPdRybu1tGj9/OrQ= +gonum.org/v1/gonum v0.15.0/go.mod h1:xzZVBJBtS+Mz4q0Yl2LJTk+OxOg4jiXZ7qBoM0uISGo= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= @@ -2225,10 +2226,10 @@ google.golang.org/genproto v0.0.0-20210401141331-865547bb08e2/go.mod h1:9lPAdzaE google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 h1:9+tzLLstTlPTRyJTh+ah5wIMsBW5c4tQwGTN3thOW9Y= google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9/go.mod h1:mqHbVIp48Muh7Ywss/AD6I5kNVKZMmAa/QEW58Gxp2s= -google.golang.org/genproto/googleapis/api v0.0.0-20240520151616-dc85e6b867a5 h1:P8OJ/WCl/Xo4E4zoe4/bifHpSmmKwARqyqE4nW6J2GQ= -google.golang.org/genproto/googleapis/api v0.0.0-20240520151616-dc85e6b867a5/go.mod h1:RGnPtTG7r4i8sPlNyDeikXF99hMM+hN6QMm4ooG9g2g= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240520151616-dc85e6b867a5 h1:Q2RxlXqh1cgzzUgV261vBO2jI5R/3DD1J2pM0nI4NhU= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240520151616-dc85e6b867a5/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= +google.golang.org/genproto/googleapis/api v0.0.0-20240711142825-46eb208f015d h1:kHjw/5UfflP/L5EbledDrcG4C2597RtymmGRZvHiCuY= +google.golang.org/genproto/googleapis/api v0.0.0-20240711142825-46eb208f015d/go.mod h1:mw8MG/Qz5wfgYr6VqVCiZcHe/GJEfI+oGGDCohaVgB0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240711142825-46eb208f015d h1:JU0iKnSg02Gmb5ZdV8nYsKEKsP6o/FGVWTrw4i1DA9A= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240711142825-46eb208f015d/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= google.golang.org/grpc v1.12.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= @@ -2251,8 +2252,8 @@ google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA5 google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.64.0 h1:KH3VH9y/MgNQg1dE7b3XfVK0GsPSIzJwdF617gUSbvY= -google.golang.org/grpc v1.64.0/go.mod h1:oxjF8E3FBnjp+/gVFYdWacaLDx9na1aqy9oovLpxQYg= +google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc= +google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= From 3ecb9544b297de939da2b5157b2cb5a4a9b6f44b Mon Sep 17 00:00:00 2001 From: chainchad <96362174+chainchad@users.noreply.github.com> Date: Wed, 24 Jul 2024 13:45:02 -0400 Subject: [PATCH 009/115] @chainlink.contracts release v1.2.0 (#13895) * Update CHANGELOG and package version for contracts release * Add today's date to CHANGELOG 1.2.0 --- contracts/.changeset/blue-onions-sleep.md | 5 - contracts/.changeset/brave-seahorses-shave.md | 5 - contracts/.changeset/calm-bikes-grin.md | 5 - contracts/.changeset/chilly-rivers-study.md | 5 - contracts/.changeset/cyan-apes-perform.md | 5 - contracts/.changeset/dull-phones-retire.md | 5 - contracts/.changeset/green-pigs-reflect.md | 5 - contracts/.changeset/happy-plants-dance.md | 5 - .../.changeset/healthy-impalas-hammer.md | 5 - contracts/.changeset/hip-comics-rhyme.md | 5 - contracts/.changeset/large-news-nail.md | 5 - contracts/.changeset/long-beans-turn.md | 5 - contracts/.changeset/long-cups-perform.md | 5 - contracts/.changeset/long-jars-protect.md | 5 - contracts/.changeset/moody-days-share.md | 5 - contracts/.changeset/nasty-tables-guess.md | 5 - contracts/.changeset/neat-brooms-repeat.md | 5 - contracts/.changeset/new-bugs-draw.md | 5 - contracts/.changeset/ninety-cobras-drive.md | 5 - contracts/.changeset/ninety-wolves-sleep.md | 5 - contracts/.changeset/odd-gorillas-develop.md | 5 - contracts/.changeset/orange-tips-attend.md | 5 - contracts/.changeset/proud-seals-draw.md | 5 - contracts/.changeset/proud-turkeys-fold.md | 5 - contracts/.changeset/quiet-crews-impress.md | 5 - contracts/.changeset/quiet-guests-march.md | 5 - contracts/.changeset/red-wasps-behave.md | 5 - contracts/.changeset/rich-crabs-smoke.md | 5 - contracts/.changeset/selfish-files-learn.md | 5 - contracts/.changeset/serious-cats-fold.md | 5 - contracts/.changeset/seven-apes-drop.md | 5 - contracts/.changeset/silent-ravens-lay.md | 5 - contracts/.changeset/six-ears-sin.md | 5 - contracts/.changeset/smart-rules-love.md | 5 - contracts/.changeset/smart-trainers-begin.md | 5 - contracts/.changeset/smooth-years-reply.md | 5 - contracts/.changeset/sour-parents-explode.md | 5 - contracts/.changeset/spicy-mirrors-care.md | 5 - contracts/.changeset/stupid-lamps-sell.md | 5 - contracts/.changeset/sweet-geese-rescue.md | 5 - contracts/.changeset/swift-ads-stare.md | 5 - contracts/.changeset/tender-roses-know.md | 5 - contracts/.changeset/tricky-comics-scream.md | 5 - contracts/.changeset/tricky-meals-decide.md | 6 -- contracts/.changeset/two-doors-dance.md | 5 - contracts/.changeset/witty-onions-relate.md | 5 - contracts/.changeset/yellow-snails-wash.md | 5 - contracts/CHANGELOG.md | 102 +++++++++++++++++- contracts/package.json | 2 +- 49 files changed, 102 insertions(+), 238 deletions(-) delete mode 100644 contracts/.changeset/blue-onions-sleep.md delete mode 100644 contracts/.changeset/brave-seahorses-shave.md delete mode 100644 contracts/.changeset/calm-bikes-grin.md delete mode 100644 contracts/.changeset/chilly-rivers-study.md delete mode 100644 contracts/.changeset/cyan-apes-perform.md delete mode 100644 contracts/.changeset/dull-phones-retire.md delete mode 100644 contracts/.changeset/green-pigs-reflect.md delete mode 100644 contracts/.changeset/happy-plants-dance.md delete mode 100644 contracts/.changeset/healthy-impalas-hammer.md delete mode 100644 contracts/.changeset/hip-comics-rhyme.md delete mode 100644 contracts/.changeset/large-news-nail.md delete mode 100644 contracts/.changeset/long-beans-turn.md delete mode 100644 contracts/.changeset/long-cups-perform.md delete mode 100644 contracts/.changeset/long-jars-protect.md delete mode 100644 contracts/.changeset/moody-days-share.md delete mode 100644 contracts/.changeset/nasty-tables-guess.md delete mode 100644 contracts/.changeset/neat-brooms-repeat.md delete mode 100644 contracts/.changeset/new-bugs-draw.md delete mode 100644 contracts/.changeset/ninety-cobras-drive.md delete mode 100644 contracts/.changeset/ninety-wolves-sleep.md delete mode 100644 contracts/.changeset/odd-gorillas-develop.md delete mode 100644 contracts/.changeset/orange-tips-attend.md delete mode 100644 contracts/.changeset/proud-seals-draw.md delete mode 100644 contracts/.changeset/proud-turkeys-fold.md delete mode 100644 contracts/.changeset/quiet-crews-impress.md delete mode 100644 contracts/.changeset/quiet-guests-march.md delete mode 100644 contracts/.changeset/red-wasps-behave.md delete mode 100644 contracts/.changeset/rich-crabs-smoke.md delete mode 100644 contracts/.changeset/selfish-files-learn.md delete mode 100644 contracts/.changeset/serious-cats-fold.md delete mode 100644 contracts/.changeset/seven-apes-drop.md delete mode 100644 contracts/.changeset/silent-ravens-lay.md delete mode 100644 contracts/.changeset/six-ears-sin.md delete mode 100644 contracts/.changeset/smart-rules-love.md delete mode 100644 contracts/.changeset/smart-trainers-begin.md delete mode 100644 contracts/.changeset/smooth-years-reply.md delete mode 100644 contracts/.changeset/sour-parents-explode.md delete mode 100644 contracts/.changeset/spicy-mirrors-care.md delete mode 100644 contracts/.changeset/stupid-lamps-sell.md delete mode 100644 contracts/.changeset/sweet-geese-rescue.md delete mode 100644 contracts/.changeset/swift-ads-stare.md delete mode 100644 contracts/.changeset/tender-roses-know.md delete mode 100644 contracts/.changeset/tricky-comics-scream.md delete mode 100644 contracts/.changeset/tricky-meals-decide.md delete mode 100644 contracts/.changeset/two-doors-dance.md delete mode 100644 contracts/.changeset/witty-onions-relate.md delete mode 100644 contracts/.changeset/yellow-snails-wash.md diff --git a/contracts/.changeset/blue-onions-sleep.md b/contracts/.changeset/blue-onions-sleep.md deleted file mode 100644 index 35944a0960..0000000000 --- a/contracts/.changeset/blue-onions-sleep.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@chainlink/contracts': patch ---- - -capability registry internal review diff --git a/contracts/.changeset/brave-seahorses-shave.md b/contracts/.changeset/brave-seahorses-shave.md deleted file mode 100644 index 3f29e6aa4a..0000000000 --- a/contracts/.changeset/brave-seahorses-shave.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@chainlink/contracts': patch ---- - -upgrade keystone contracts to 0.8.24 diff --git a/contracts/.changeset/calm-bikes-grin.md b/contracts/.changeset/calm-bikes-grin.md deleted file mode 100644 index 675d42ce4f..0000000000 --- a/contracts/.changeset/calm-bikes-grin.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@chainlink/contracts": patch ---- - -add events, add getter and add comments #bugfix diff --git a/contracts/.changeset/chilly-rivers-study.md b/contracts/.changeset/chilly-rivers-study.md deleted file mode 100644 index 0bd5d713a1..0000000000 --- a/contracts/.changeset/chilly-rivers-study.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@chainlink/contracts': patch ---- - -add capability registry comment explaining why we do not validate node operator name diff --git a/contracts/.changeset/cyan-apes-perform.md b/contracts/.changeset/cyan-apes-perform.md deleted file mode 100644 index b35f80a981..0000000000 --- a/contracts/.changeset/cyan-apes-perform.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@chainlink/contracts': minor ---- - -#added EnumerableMapAddresses shared lib for AddressToAddress and AddressToBytes32 maps diff --git a/contracts/.changeset/dull-phones-retire.md b/contracts/.changeset/dull-phones-retire.md deleted file mode 100644 index be65a31fac..0000000000 --- a/contracts/.changeset/dull-phones-retire.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@chainlink/contracts': patch ---- - -capability registry informational findings diff --git a/contracts/.changeset/green-pigs-reflect.md b/contracts/.changeset/green-pigs-reflect.md deleted file mode 100644 index cb197a32bc..0000000000 --- a/contracts/.changeset/green-pigs-reflect.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@chainlink/contracts": patch ---- - -add test for v23 #added diff --git a/contracts/.changeset/happy-plants-dance.md b/contracts/.changeset/happy-plants-dance.md deleted file mode 100644 index 1b8c7fcb66..0000000000 --- a/contracts/.changeset/happy-plants-dance.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@chainlink/contracts': patch ---- - -allow updating capabilities and to add/remove multiple capabilities at once from the capability registry diff --git a/contracts/.changeset/healthy-impalas-hammer.md b/contracts/.changeset/healthy-impalas-hammer.md deleted file mode 100644 index dbbef2fca2..0000000000 --- a/contracts/.changeset/healthy-impalas-hammer.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@chainlink/contracts': patch ---- - -remove tracking deprecated arrays diff --git a/contracts/.changeset/hip-comics-rhyme.md b/contracts/.changeset/hip-comics-rhyme.md deleted file mode 100644 index f114282148..0000000000 --- a/contracts/.changeset/hip-comics-rhyme.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@chainlink/contracts": patch ---- - -track config count in DON struct diff --git a/contracts/.changeset/large-news-nail.md b/contracts/.changeset/large-news-nail.md deleted file mode 100644 index 016216426a..0000000000 --- a/contracts/.changeset/large-news-nail.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@chainlink/contracts": patch ---- - -Add Additional tests to the callWithExactGasLibrary to ensure proper gas usage diff --git a/contracts/.changeset/long-beans-turn.md b/contracts/.changeset/long-beans-turn.md deleted file mode 100644 index 3af5e4a217..0000000000 --- a/contracts/.changeset/long-beans-turn.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@chainlink/contracts": patch ---- - -implement remove DONs in capability registry diff --git a/contracts/.changeset/long-cups-perform.md b/contracts/.changeset/long-cups-perform.md deleted file mode 100644 index 93fba83b55..0000000000 --- a/contracts/.changeset/long-cups-perform.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@chainlink/contracts': patch ---- - -#internal diff --git a/contracts/.changeset/long-jars-protect.md b/contracts/.changeset/long-jars-protect.md deleted file mode 100644 index 2e5a11e3c8..0000000000 --- a/contracts/.changeset/long-jars-protect.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@chainlink/contracts': patch ---- - -update error message when node does not exist diff --git a/contracts/.changeset/moody-days-share.md b/contracts/.changeset/moody-days-share.md deleted file mode 100644 index 6c0eb4780b..0000000000 --- a/contracts/.changeset/moody-days-share.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@chainlink/contracts': patch ---- - -#internal stub of keystone feed consumer contract diff --git a/contracts/.changeset/nasty-tables-guess.md b/contracts/.changeset/nasty-tables-guess.md deleted file mode 100644 index c3c1df76cd..0000000000 --- a/contracts/.changeset/nasty-tables-guess.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@chainlink/contracts": patch ---- - -roundup #bugfix diff --git a/contracts/.changeset/neat-brooms-repeat.md b/contracts/.changeset/neat-brooms-repeat.md deleted file mode 100644 index 48188702bc..0000000000 --- a/contracts/.changeset/neat-brooms-repeat.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@chainlink/contracts': minor ---- - -We have multiple validation use-cases on-chain which requires the inputs to be a set, sorted-set or we need to do subset checks.Adding a library for these validations diff --git a/contracts/.changeset/new-bugs-draw.md b/contracts/.changeset/new-bugs-draw.md deleted file mode 100644 index 93fba83b55..0000000000 --- a/contracts/.changeset/new-bugs-draw.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@chainlink/contracts': patch ---- - -#internal diff --git a/contracts/.changeset/ninety-cobras-drive.md b/contracts/.changeset/ninety-cobras-drive.md deleted file mode 100644 index cd57662462..0000000000 --- a/contracts/.changeset/ninety-cobras-drive.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@chainlink/contracts": patch ---- - -relax pragma solidity version in VRF SubscriptionAPI.sol diff --git a/contracts/.changeset/ninety-wolves-sleep.md b/contracts/.changeset/ninety-wolves-sleep.md deleted file mode 100644 index 7b66938838..0000000000 --- a/contracts/.changeset/ninety-wolves-sleep.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@chainlink/contracts': patch ---- - -#internal internal-review-for-capability-registry diff --git a/contracts/.changeset/odd-gorillas-develop.md b/contracts/.changeset/odd-gorillas-develop.md deleted file mode 100644 index 93fba83b55..0000000000 --- a/contracts/.changeset/odd-gorillas-develop.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@chainlink/contracts': patch ---- - -#internal diff --git a/contracts/.changeset/orange-tips-attend.md b/contracts/.changeset/orange-tips-attend.md deleted file mode 100644 index 2b5fa8e88e..0000000000 --- a/contracts/.changeset/orange-tips-attend.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@chainlink/contracts': patch ---- - -validate that a node is not part of a DON when removing diff --git a/contracts/.changeset/proud-seals-draw.md b/contracts/.changeset/proud-seals-draw.md deleted file mode 100644 index 6bda7ed255..0000000000 --- a/contracts/.changeset/proud-seals-draw.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@chainlink/contracts": patch ---- - -move v23 contracts #bugfix diff --git a/contracts/.changeset/proud-turkeys-fold.md b/contracts/.changeset/proud-turkeys-fold.md deleted file mode 100644 index eab0c19249..0000000000 --- a/contracts/.changeset/proud-turkeys-fold.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@chainlink/contracts': patch ---- - -VRFV2Plus coordinator and wrapper split contracts between L1 and L2 chains #updated diff --git a/contracts/.changeset/quiet-crews-impress.md b/contracts/.changeset/quiet-crews-impress.md deleted file mode 100644 index 5310806f1c..0000000000 --- a/contracts/.changeset/quiet-crews-impress.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@chainlink/contracts': patch ---- - -#internal Use audited version of OCR2Base.sol in OCR3Capability.sol diff --git a/contracts/.changeset/quiet-guests-march.md b/contracts/.changeset/quiet-guests-march.md deleted file mode 100644 index 40285829c1..0000000000 --- a/contracts/.changeset/quiet-guests-march.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@chainlink/contracts": patch ---- - -Add update DON function to capability registry diff --git a/contracts/.changeset/red-wasps-behave.md b/contracts/.changeset/red-wasps-behave.md deleted file mode 100644 index 93fba83b55..0000000000 --- a/contracts/.changeset/red-wasps-behave.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@chainlink/contracts': patch ---- - -#internal diff --git a/contracts/.changeset/rich-crabs-smoke.md b/contracts/.changeset/rich-crabs-smoke.md deleted file mode 100644 index fc33cf7d4e..0000000000 --- a/contracts/.changeset/rich-crabs-smoke.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@chainlink/contracts': patch ---- - -#internal Keystone Forwarder and Feeds Consumer diff --git a/contracts/.changeset/selfish-files-learn.md b/contracts/.changeset/selfish-files-learn.md deleted file mode 100644 index 3d348d1d8d..0000000000 --- a/contracts/.changeset/selfish-files-learn.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@chainlink/contracts": patch ---- - -add getters in capability registry diff --git a/contracts/.changeset/serious-cats-fold.md b/contracts/.changeset/serious-cats-fold.md deleted file mode 100644 index ccf89c9b04..0000000000 --- a/contracts/.changeset/serious-cats-fold.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@chainlink/contracts": patch ---- - -Implemented improved L1 fee calculation for L2 chains in Functions contracts diff --git a/contracts/.changeset/seven-apes-drop.md b/contracts/.changeset/seven-apes-drop.md deleted file mode 100644 index 2882975f66..0000000000 --- a/contracts/.changeset/seven-apes-drop.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@chainlink/contracts": patch ---- - -increase solhint max-warnings to 2 (from 0) to allow workflow to pass diff --git a/contracts/.changeset/silent-ravens-lay.md b/contracts/.changeset/silent-ravens-lay.md deleted file mode 100644 index e987e9e082..0000000000 --- a/contracts/.changeset/silent-ravens-lay.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@chainlink/contracts': patch ---- - -remove update capabilities from capability registry diff --git a/contracts/.changeset/six-ears-sin.md b/contracts/.changeset/six-ears-sin.md deleted file mode 100644 index 186481a36e..0000000000 --- a/contracts/.changeset/six-ears-sin.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@chainlink/contracts": patch ---- - -update ICapabilityConfiguration interface diff --git a/contracts/.changeset/smart-rules-love.md b/contracts/.changeset/smart-rules-love.md deleted file mode 100644 index eb2542a685..0000000000 --- a/contracts/.changeset/smart-rules-love.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@chainlink/contracts": patch ---- - -Added Base Sepolia to ChainUtils #changed diff --git a/contracts/.changeset/smart-trainers-begin.md b/contracts/.changeset/smart-trainers-begin.md deleted file mode 100644 index 5e76abd21e..0000000000 --- a/contracts/.changeset/smart-trainers-begin.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@chainlink/contracts": patch ---- - -check data size #bugfix diff --git a/contracts/.changeset/smooth-years-reply.md b/contracts/.changeset/smooth-years-reply.md deleted file mode 100644 index 330310cb8d..0000000000 --- a/contracts/.changeset/smooth-years-reply.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@chainlink/contracts": patch ---- - -link transfer status check #bugfix diff --git a/contracts/.changeset/sour-parents-explode.md b/contracts/.changeset/sour-parents-explode.md deleted file mode 100644 index ff5b52b98f..0000000000 --- a/contracts/.changeset/sour-parents-explode.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@chainlink/contracts": patch ---- - -update node signer type diff --git a/contracts/.changeset/spicy-mirrors-care.md b/contracts/.changeset/spicy-mirrors-care.md deleted file mode 100644 index 93fba83b55..0000000000 --- a/contracts/.changeset/spicy-mirrors-care.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@chainlink/contracts': patch ---- - -#internal diff --git a/contracts/.changeset/stupid-lamps-sell.md b/contracts/.changeset/stupid-lamps-sell.md deleted file mode 100644 index ad5d70a04a..0000000000 --- a/contracts/.changeset/stupid-lamps-sell.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@chainlink/contracts': patch ---- - -verify valid node operator when adding nodes to capability registry diff --git a/contracts/.changeset/sweet-geese-rescue.md b/contracts/.changeset/sweet-geese-rescue.md deleted file mode 100644 index ba0f2c916c..0000000000 --- a/contracts/.changeset/sweet-geese-rescue.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@chainlink/contracts': patch ---- - -update uint256 to uint32 for donId declaration in capability config interface diff --git a/contracts/.changeset/swift-ads-stare.md b/contracts/.changeset/swift-ads-stare.md deleted file mode 100644 index 33a5d0cf16..0000000000 --- a/contracts/.changeset/swift-ads-stare.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@chainlink/contracts': patch ---- - -return hashed capability ids diff --git a/contracts/.changeset/tender-roses-know.md b/contracts/.changeset/tender-roses-know.md deleted file mode 100644 index 383837fce0..0000000000 --- a/contracts/.changeset/tender-roses-know.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@chainlink/contracts': minor ---- - -#internal Modify ChainReader tester contract. diff --git a/contracts/.changeset/tricky-comics-scream.md b/contracts/.changeset/tricky-comics-scream.md deleted file mode 100644 index f7cd1ceeab..0000000000 --- a/contracts/.changeset/tricky-comics-scream.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@chainlink/contracts": patch ---- - -remove stale automation HH tests diff --git a/contracts/.changeset/tricky-meals-decide.md b/contracts/.changeset/tricky-meals-decide.md deleted file mode 100644 index afbb24ad9f..0000000000 --- a/contracts/.changeset/tricky-meals-decide.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@chainlink/contracts": patch ---- - -#bugfix -fix a funding bug in LinkAvailableBalanceMonitor diff --git a/contracts/.changeset/two-doors-dance.md b/contracts/.changeset/two-doors-dance.md deleted file mode 100644 index 93fba83b55..0000000000 --- a/contracts/.changeset/two-doors-dance.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@chainlink/contracts': patch ---- - -#internal diff --git a/contracts/.changeset/witty-onions-relate.md b/contracts/.changeset/witty-onions-relate.md deleted file mode 100644 index 30d3da6df9..0000000000 --- a/contracts/.changeset/witty-onions-relate.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@chainlink/contracts': patch ---- - -#internal KeystoneFeedsConsumer bytes10 decoding bugfix diff --git a/contracts/.changeset/yellow-snails-wash.md b/contracts/.changeset/yellow-snails-wash.md deleted file mode 100644 index 479fedcbe4..0000000000 --- a/contracts/.changeset/yellow-snails-wash.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@chainlink/contracts': patch ---- - -return don capability config contract config from capability registry diff --git a/contracts/CHANGELOG.md b/contracts/CHANGELOG.md index ba6dabfeb0..01a9dd4b6c 100644 --- a/contracts/CHANGELOG.md +++ b/contracts/CHANGELOG.md @@ -1,5 +1,106 @@ # @chainlink/contracts +## 1.2.0 - 2024-07-18 + +### Minor Changes + +- [#13428](https://github.com/smartcontractkit/chainlink/pull/13428) [`a02bb0a`](https://github.com/smartcontractkit/chainlink/commit/a02bb0a48cb78c815ec3a2f3bd351f2efc3869d7) Thanks [@elatoskinas](https://github.com/elatoskinas)! - #added EnumerableMapAddresses shared lib for AddressToAddress and AddressToBytes32 maps + +- [#13774](https://github.com/smartcontractkit/chainlink/pull/13774) [`b5c0ea9`](https://github.com/smartcontractkit/chainlink/commit/b5c0ea9f106ced6daf8e1f35e88bc39d7b82de28) Thanks [@0xsuryansh](https://github.com/0xsuryansh)! - We have multiple validation use-cases on-chain which requires the inputs to be a set, sorted-set or we need to do subset checks.Adding a library for these validations + +- [#13514](https://github.com/smartcontractkit/chainlink/pull/13514) [`f84a3f2`](https://github.com/smartcontractkit/chainlink/commit/f84a3f2f276847d26c94bf67215e2a3600951c9c) Thanks [@ilija42](https://github.com/ilija42)! - #internal Modify ChainReader tester contract. + +### Patch Changes + +- [#13368](https://github.com/smartcontractkit/chainlink/pull/13368) [`000f2cb`](https://github.com/smartcontractkit/chainlink/commit/000f2cb36b7d9b6d046d383c85996ae1ae7a606e) Thanks [@cds95](https://github.com/cds95)! - capability registry internal review + +- [#13546](https://github.com/smartcontractkit/chainlink/pull/13546) [`10ddafa`](https://github.com/smartcontractkit/chainlink/commit/10ddafaebedb94ad5a59968d19256b8c4592857f) Thanks [@cds95](https://github.com/cds95)! - upgrade keystone contracts to 0.8.24 + +- [#13376](https://github.com/smartcontractkit/chainlink/pull/13376) [`bb40d51`](https://github.com/smartcontractkit/chainlink/commit/bb40d51502487b010a1d6621db42458356dbbdc0) Thanks [@shileiwill](https://github.com/shileiwill)! - add events, add getter and add comments #bugfix + +- [#13368](https://github.com/smartcontractkit/chainlink/pull/13368) [`000f2cb`](https://github.com/smartcontractkit/chainlink/commit/000f2cb36b7d9b6d046d383c85996ae1ae7a606e) Thanks [@cds95](https://github.com/cds95)! - add capability registry comment explaining why we do not validate node operator name + +- [#13368](https://github.com/smartcontractkit/chainlink/pull/13368) [`000f2cb`](https://github.com/smartcontractkit/chainlink/commit/000f2cb36b7d9b6d046d383c85996ae1ae7a606e) Thanks [@cds95](https://github.com/cds95)! - capability registry informational findings + +- [#13644](https://github.com/smartcontractkit/chainlink/pull/13644) [`2ed4478`](https://github.com/smartcontractkit/chainlink/commit/2ed4478ecc7fa6bada1138d204c12236fe56a810) Thanks [@shileiwill](https://github.com/shileiwill)! - add test for v23 #added + +- [#13368](https://github.com/smartcontractkit/chainlink/pull/13368) [`000f2cb`](https://github.com/smartcontractkit/chainlink/commit/000f2cb36b7d9b6d046d383c85996ae1ae7a606e) Thanks [@cds95](https://github.com/cds95)! - allow updating capabilities and to add/remove multiple capabilities at once from the capability registry + +- [#13368](https://github.com/smartcontractkit/chainlink/pull/13368) [`000f2cb`](https://github.com/smartcontractkit/chainlink/commit/000f2cb36b7d9b6d046d383c85996ae1ae7a606e) Thanks [@cds95](https://github.com/cds95)! - remove tracking deprecated arrays + +- [#13183](https://github.com/smartcontractkit/chainlink/pull/13183) [`9630475`](https://github.com/smartcontractkit/chainlink/commit/96304756a77cdb2acf251d21d59b6aa8b55bf61a) Thanks [@cds95](https://github.com/cds95)! - track config count in DON struct + +- [#13326](https://github.com/smartcontractkit/chainlink/pull/13326) [`732eea0`](https://github.com/smartcontractkit/chainlink/commit/732eea0f834e1f84c3a7520e131698d38762c78b) Thanks [@jhweintraub](https://github.com/jhweintraub)! - Add Additional tests to the callWithExactGasLibrary to ensure proper gas usage + +- [#13183](https://github.com/smartcontractkit/chainlink/pull/13183) [`9630475`](https://github.com/smartcontractkit/chainlink/commit/96304756a77cdb2acf251d21d59b6aa8b55bf61a) Thanks [@cds95](https://github.com/cds95)! - implement remove DONs in capability registry + +- [#13425](https://github.com/smartcontractkit/chainlink/pull/13425) [`eeb363f`](https://github.com/smartcontractkit/chainlink/commit/eeb363f1230415dde573607a095b177c612d3bef) Thanks [@DeividasK](https://github.com/DeividasK)! - #internal + +- [#13453](https://github.com/smartcontractkit/chainlink/pull/13453) [`8c98c80`](https://github.com/smartcontractkit/chainlink/commit/8c98c80376c3b6d72bffeab62ee45a74449b6ef5) Thanks [@cds95](https://github.com/cds95)! - update error message when node does not exist + +- [#13366](https://github.com/smartcontractkit/chainlink/pull/13366) [`d53d6d0`](https://github.com/smartcontractkit/chainlink/commit/d53d6d08dac5d3ee27ae89012669c6c2455295c8) Thanks [@bolekk](https://github.com/bolekk)! - #internal stub of keystone feed consumer contract + +- [#13287](https://github.com/smartcontractkit/chainlink/pull/13287) [`8491b24`](https://github.com/smartcontractkit/chainlink/commit/8491b247cd5ff240d281ecfbabc0fe0fa19134f1) Thanks [@shileiwill](https://github.com/shileiwill)! - roundup #bugfix + +- [#13426](https://github.com/smartcontractkit/chainlink/pull/13426) [`592b2bb`](https://github.com/smartcontractkit/chainlink/commit/592b2bb5a84a0e8858f77c5faa99e881f911878c) Thanks [@archseer](https://github.com/archseer)! - #internal + +- [#13600](https://github.com/smartcontractkit/chainlink/pull/13600) [`4406364`](https://github.com/smartcontractkit/chainlink/commit/4406364702dd5af0b34c0397c00f8489510ecb11) Thanks [@jinhoonbang](https://github.com/jinhoonbang)! - relax pragma solidity version in VRF SubscriptionAPI.sol + +- [#13368](https://github.com/smartcontractkit/chainlink/pull/13368) [`000f2cb`](https://github.com/smartcontractkit/chainlink/commit/000f2cb36b7d9b6d046d383c85996ae1ae7a606e) Thanks [@cds95](https://github.com/cds95)! - #internal internal-review-for-capability-registry + +- [#13528](https://github.com/smartcontractkit/chainlink/pull/13528) [`95502ad`](https://github.com/smartcontractkit/chainlink/commit/95502ad2699d63891662594f70e82e76682f2ed8) Thanks [@DeividasK](https://github.com/DeividasK)! - #internal + +- [#13368](https://github.com/smartcontractkit/chainlink/pull/13368) [`000f2cb`](https://github.com/smartcontractkit/chainlink/commit/000f2cb36b7d9b6d046d383c85996ae1ae7a606e) Thanks [@cds95](https://github.com/cds95)! - validate that a node is not part of a DON when removing + +- [#13504](https://github.com/smartcontractkit/chainlink/pull/13504) [`815c5ea`](https://github.com/smartcontractkit/chainlink/commit/815c5ea8715462e00f6ea10cdc0b93ec3e1ba505) Thanks [@shileiwill](https://github.com/shileiwill)! - move v23 contracts #bugfix + +- [#13335](https://github.com/smartcontractkit/chainlink/pull/13335) [`697e469`](https://github.com/smartcontractkit/chainlink/commit/697e469e41e640c8c71214461426174340527b4b) Thanks [@ibrajer](https://github.com/ibrajer)! - VRFV2Plus coordinator and wrapper split contracts between L1 and L2 chains #updated + +- [#13487](https://github.com/smartcontractkit/chainlink/pull/13487) [`5e27da9`](https://github.com/smartcontractkit/chainlink/commit/5e27da95f09f21272e93f086bc2de5a9bc2ae399) Thanks [@bolekk](https://github.com/bolekk)! - #internal Use audited version of OCR2Base.sol in OCR3Capability.sol + +- [#13183](https://github.com/smartcontractkit/chainlink/pull/13183) [`9630475`](https://github.com/smartcontractkit/chainlink/commit/96304756a77cdb2acf251d21d59b6aa8b55bf61a) Thanks [@cds95](https://github.com/cds95)! - Add update DON function to capability registry + +- [#13566](https://github.com/smartcontractkit/chainlink/pull/13566) [`f1d478d`](https://github.com/smartcontractkit/chainlink/commit/f1d478d8bbba92f9753f7a1d6733ba4efd1f616a) Thanks [@DeividasK](https://github.com/DeividasK)! - #internal + +- [#13389](https://github.com/smartcontractkit/chainlink/pull/13389) [`3959091`](https://github.com/smartcontractkit/chainlink/commit/3959091d4f3925b64cb6b0b55b7f7c72a4f924b9) Thanks [@bolekk](https://github.com/bolekk)! - #internal Keystone Forwarder and Feeds Consumer + +- [#13183](https://github.com/smartcontractkit/chainlink/pull/13183) [`9630475`](https://github.com/smartcontractkit/chainlink/commit/96304756a77cdb2acf251d21d59b6aa8b55bf61a) Thanks [@cds95](https://github.com/cds95)! - add getters in capability registry + +- [#13815](https://github.com/smartcontractkit/chainlink/pull/13815) [`fb177f4`](https://github.com/smartcontractkit/chainlink/commit/fb177f4ee77898dd12e20499e421a4d591fb92ef) Thanks [@KuphJr](https://github.com/KuphJr)! - Implemented improved L1 fee calculation for L2 chains in Functions contracts + +- [#13237](https://github.com/smartcontractkit/chainlink/pull/13237) [`53312f0`](https://github.com/smartcontractkit/chainlink/commit/53312f01f3459408402ed97a9e3935ec63ccee7a) Thanks [@erikburt](https://github.com/erikburt)! - increase solhint max-warnings to 2 (from 0) to allow workflow to pass + +- [#13368](https://github.com/smartcontractkit/chainlink/pull/13368) [`000f2cb`](https://github.com/smartcontractkit/chainlink/commit/000f2cb36b7d9b6d046d383c85996ae1ae7a606e) Thanks [@cds95](https://github.com/cds95)! - remove update capabilities from capability registry + +- [#13183](https://github.com/smartcontractkit/chainlink/pull/13183) [`9630475`](https://github.com/smartcontractkit/chainlink/commit/96304756a77cdb2acf251d21d59b6aa8b55bf61a) Thanks [@cds95](https://github.com/cds95)! - update ICapabilityConfiguration interface + +- [#13216](https://github.com/smartcontractkit/chainlink/pull/13216) [`6099abb`](https://github.com/smartcontractkit/chainlink/commit/6099abbdbfb3ad396ca1ed5138ecd7a13159de19) Thanks [@ibrajer](https://github.com/ibrajer)! - Added Base Sepolia to ChainUtils #changed + +- [#13352](https://github.com/smartcontractkit/chainlink/pull/13352) [`33a9cdf`](https://github.com/smartcontractkit/chainlink/commit/33a9cdf8d7c42cab4682121b50d5fa12d9b5ff27) Thanks [@shileiwill](https://github.com/shileiwill)! - check data size #bugfix + +- [#13177](https://github.com/smartcontractkit/chainlink/pull/13177) [`0d58a8d`](https://github.com/smartcontractkit/chainlink/commit/0d58a8d5db24f42720226e73328e501637ba59c5) Thanks [@shileiwill](https://github.com/shileiwill)! - link transfer status check #bugfix + +- [#13183](https://github.com/smartcontractkit/chainlink/pull/13183) [`9630475`](https://github.com/smartcontractkit/chainlink/commit/96304756a77cdb2acf251d21d59b6aa8b55bf61a) Thanks [@cds95](https://github.com/cds95)! - update node signer type + +- [#13580](https://github.com/smartcontractkit/chainlink/pull/13580) [`0d4a3b2`](https://github.com/smartcontractkit/chainlink/commit/0d4a3b2cd8ff938ba018d982ef514c754a7df345) Thanks [@DeividasK](https://github.com/DeividasK)! - #internal + +- [#13368](https://github.com/smartcontractkit/chainlink/pull/13368) [`000f2cb`](https://github.com/smartcontractkit/chainlink/commit/000f2cb36b7d9b6d046d383c85996ae1ae7a606e) Thanks [@cds95](https://github.com/cds95)! - verify valid node operator when adding nodes to capability registry + +- [#13368](https://github.com/smartcontractkit/chainlink/pull/13368) [`000f2cb`](https://github.com/smartcontractkit/chainlink/commit/000f2cb36b7d9b6d046d383c85996ae1ae7a606e) Thanks [@cds95](https://github.com/cds95)! - update uint256 to uint32 for donId declaration in capability config interface + +- [#13453](https://github.com/smartcontractkit/chainlink/pull/13453) [`8c98c80`](https://github.com/smartcontractkit/chainlink/commit/8c98c80376c3b6d72bffeab62ee45a74449b6ef5) Thanks [@cds95](https://github.com/cds95)! - return hashed capability ids + +- [#13676](https://github.com/smartcontractkit/chainlink/pull/13676) [`ed6b9ad`](https://github.com/smartcontractkit/chainlink/commit/ed6b9ad7909e09d0ff9850b7a1e34a0137762642) Thanks [@RyanRHall](https://github.com/RyanRHall)! - remove stale automation HH tests + +- [#13364](https://github.com/smartcontractkit/chainlink/pull/13364) [`fc007a9`](https://github.com/smartcontractkit/chainlink/commit/fc007a94846c178bc9d5203dbff6b6b8c7546a71) Thanks [@FelixFan1992](https://github.com/FelixFan1992)! - #bugfix + fix a funding bug in LinkAvailableBalanceMonitor + +- [#13569](https://github.com/smartcontractkit/chainlink/pull/13569) [`f5a70eb`](https://github.com/smartcontractkit/chainlink/commit/f5a70eb09abc9a4d859442c9bd062a74a7ec9c54) Thanks [@DeividasK](https://github.com/DeividasK)! - #internal + +- [#13436](https://github.com/smartcontractkit/chainlink/pull/13436) [`f37afb9`](https://github.com/smartcontractkit/chainlink/commit/f37afb9ebaeda10f8b3873b069b8a824e60a81c3) Thanks [@bolekk](https://github.com/bolekk)! - #internal KeystoneFeedsConsumer bytes10 decoding bugfix + +- [#13368](https://github.com/smartcontractkit/chainlink/pull/13368) [`000f2cb`](https://github.com/smartcontractkit/chainlink/commit/000f2cb36b7d9b6d046d383c85996ae1ae7a606e) Thanks [@cds95](https://github.com/cds95)! - return don capability config contract config from capability registry + ## 1.1.1 - 2024-05-23 ### Patch Changes @@ -32,7 +133,6 @@ - [#13022](https://github.com/smartcontractkit/chainlink/pull/13022) [`2805fa6c9b`](https://github.com/smartcontractkit/chainlink/commit/2805fa6c9b469d535edcd3d66c08e1d22bbaa2d0) Thanks [@cds95](https://github.com/cds95)! - #internal - - [#12812](https://github.com/smartcontractkit/chainlink/pull/12812) [`5b33a3296f`](https://github.com/smartcontractkit/chainlink/commit/5b33a3296f895cec8a23ba2e235989868f398ddb) Thanks [@shileiwill](https://github.com/shileiwill)! - Support decimals #added - [#12979](https://github.com/smartcontractkit/chainlink/pull/12979) [`0c4c24ad8c`](https://github.com/smartcontractkit/chainlink/commit/0c4c24ad8c95e505cd2a29be711cc40e612658b0) Thanks [@cds95](https://github.com/cds95)! - Add function to remove node operators from capability registry diff --git a/contracts/package.json b/contracts/package.json index 247bb92303..5a13d561f0 100644 --- a/contracts/package.json +++ b/contracts/package.json @@ -1,6 +1,6 @@ { "name": "@chainlink/contracts", - "version": "1.1.1", + "version": "1.2.0", "description": "Chainlink smart contracts", "author": "Chainlink devs", "license": "MIT", From e7552f8a6b49f322df9be2fc70d97bcdebdef005 Mon Sep 17 00:00:00 2001 From: Cedric Date: Thu, 25 Jul 2024 11:30:11 +0100 Subject: [PATCH 010/115] Small fixes (#13926) --- ...deploy_initialize_capabilities_registry.go | 20 +++++++++++++++++++ core/services/registrysyncer/syncer.go | 14 +++++++------ core/services/registrysyncer/syncer_test.go | 4 ++-- 3 files changed, 30 insertions(+), 8 deletions(-) diff --git a/core/scripts/keystone/src/05_deploy_initialize_capabilities_registry.go b/core/scripts/keystone/src/05_deploy_initialize_capabilities_registry.go index 387ebf46b9..8762241543 100644 --- a/core/scripts/keystone/src/05_deploy_initialize_capabilities_registry.go +++ b/core/scripts/keystone/src/05_deploy_initialize_capabilities_registry.go @@ -166,6 +166,12 @@ func peerToNode(nopID uint32, p peer) (kcr.CapabilitiesRegistryNodeParams, error }, nil } +func newCapabilityConfig() *capabilitiespb.CapabilityConfig { + return &capabilitiespb.CapabilityConfig{ + DefaultConfig: values.Proto(values.EmptyMap()).GetMapValue(), + } +} + // Run expects the following environment variables to be set: // // 1. Deploys the CapabilitiesRegistry contract @@ -312,9 +318,16 @@ func (c *deployAndInitializeCapabilitiesRegistryCommand) Run(args []string) { panic(err) } + cc := newCapabilityConfig() + ccb, err := proto.Marshal(cc) + if err != nil { + panic(err) + } + cfgs := []kcr.CapabilitiesRegistryCapabilityConfiguration{ { CapabilityId: ocrid, + Config: ccb, }, } _, err = reg.AddDON(env.Owner, ps, cfgs, true, true, 2) @@ -360,9 +373,16 @@ func (c *deployAndInitializeCapabilitiesRegistryCommand) Run(args []string) { panic(err) } + cc = newCapabilityConfig() + ccb, err = proto.Marshal(cc) + if err != nil { + panic(err) + } + cfgs = []kcr.CapabilitiesRegistryCapabilityConfiguration{ { CapabilityId: wid, + Config: ccb, }, } _, err = reg.AddDON(env.Owner, ps, cfgs, true, false, 1) diff --git a/core/services/registrysyncer/syncer.go b/core/services/registrysyncer/syncer.go index 4fb4b70dce..6a44ff561d 100644 --- a/core/services/registrysyncer/syncer.go +++ b/core/services/registrysyncer/syncer.go @@ -118,7 +118,7 @@ func newReader(ctx context.Context, lggr logger.Logger, relayer contractReaderFa } func (s *registrySyncer) Start(ctx context.Context) error { - return s.StartOnce("testAsyncMessageBroker", func() error { + return s.StartOnce("RegistrySyncer", func() error { s.wg.Add(1) go func() { defer s.wg.Done() @@ -304,10 +304,12 @@ func toDONInfo(don kcr.CapabilitiesRegistryDONInfo) *capabilities.DON { } return &capabilities.DON{ - ID: don.Id, - ConfigVersion: don.ConfigCount, - Members: peerIDs, - F: don.F, + ID: don.Id, + ConfigVersion: don.ConfigCount, + Members: peerIDs, + F: don.F, + IsPublic: don.IsPublic, + AcceptsWorkflows: don.AcceptsWorkflows, } } @@ -318,7 +320,7 @@ func (s *registrySyncer) AddLauncher(launchers ...Launcher) { } func (s *registrySyncer) Close() error { - return s.StopOnce("testAsyncMessageBroker", func() error { + return s.StopOnce("RegistrySyncer", func() error { close(s.stopCh) s.wg.Wait() return nil diff --git a/core/services/registrysyncer/syncer_test.go b/core/services/registrysyncer/syncer_test.go index 0e2a57ee6b..b926183394 100644 --- a/core/services/registrysyncer/syncer_test.go +++ b/core/services/registrysyncer/syncer_test.go @@ -266,8 +266,8 @@ func TestReader_Integration(t *testing.T) { DON: capabilities.DON{ ID: 1, ConfigVersion: 1, - IsPublic: false, - AcceptsWorkflows: false, + IsPublic: true, + AcceptsWorkflows: true, F: 1, Members: toPeerIDs(nodeSet), }, From d6ebada1b6572820a98255b8762cf60810db3210 Mon Sep 17 00:00:00 2001 From: Matthew Pendrey Date: Sun, 28 Jul 2024 12:37:45 +0200 Subject: [PATCH 011/115] keystone end to end integration tests (#13838) --- .changeset/lucky-cameras-punch.md | 5 + .swp | Bin 0 -> 61440 bytes .../scripts/native_solc_compile_all_keystone | 1 + .../keystone_contracts_setup.go | 345 +++++++++ .../integration_tests/mock_dispatcher.go | 195 +++++ .../integration_tests/mock_libocr.go | 198 +++++ .../integration_tests/mock_trigger.go | 147 ++++ core/capabilities/integration_tests/setup.go | 438 +++++++++++ .../integration_tests/streams_test.go | 99 +++ .../integration_tests/workflow.go | 75 ++ .../remote/target/endtoend_test.go | 20 + .../target/request/client_request_test.go | 20 + .../target/request/server_request_test.go | 20 + .../remote/types/mocks/dispatcher.go | 233 +++++- core/capabilities/remote/types/types.go | 2 + core/capabilities/targets/write_target.go | 3 +- core/cmd/shell_local_test.go | 6 +- .../feeds_consumer/feeds_consumer.go | 732 ++++++++++++++++++ ...rapper-dependency-versions-do-not-edit.txt | 1 + core/gethwrappers/keystone/go_generate.go | 1 + core/internal/cltest/cltest.go | 43 +- core/services/chainlink/application.go | 24 +- .../relayer_chain_interoperators_test.go | 8 +- core/services/chainlink/relayer_factory.go | 5 +- 24 files changed, 2601 insertions(+), 20 deletions(-) create mode 100644 .changeset/lucky-cameras-punch.md create mode 100644 .swp create mode 100644 core/capabilities/integration_tests/keystone_contracts_setup.go create mode 100644 core/capabilities/integration_tests/mock_dispatcher.go create mode 100644 core/capabilities/integration_tests/mock_libocr.go create mode 100644 core/capabilities/integration_tests/mock_trigger.go create mode 100644 core/capabilities/integration_tests/setup.go create mode 100644 core/capabilities/integration_tests/streams_test.go create mode 100644 core/capabilities/integration_tests/workflow.go create mode 100644 core/gethwrappers/keystone/generated/feeds_consumer/feeds_consumer.go diff --git a/.changeset/lucky-cameras-punch.md b/.changeset/lucky-cameras-punch.md new file mode 100644 index 0000000000..73dbc1e7c7 --- /dev/null +++ b/.changeset/lucky-cameras-punch.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#internal end to end test for streams capabilities diff --git a/.swp b/.swp new file mode 100644 index 0000000000000000000000000000000000000000..e2293baeb2c82c5dda684b915378632a283c71fb GIT binary patch literal 61440 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 HJo5hlrWzqI literal 0 HcmV?d00001 diff --git a/contracts/scripts/native_solc_compile_all_keystone b/contracts/scripts/native_solc_compile_all_keystone index 0516b2aedb..a42b06b8f6 100755 --- a/contracts/scripts/native_solc_compile_all_keystone +++ b/contracts/scripts/native_solc_compile_all_keystone @@ -32,3 +32,4 @@ compileContract () { compileContract keystone/CapabilitiesRegistry.sol compileContract keystone/KeystoneForwarder.sol compileContract keystone/OCR3Capability.sol +compileContract keystone/KeystoneFeedsConsumer.sol diff --git a/core/capabilities/integration_tests/keystone_contracts_setup.go b/core/capabilities/integration_tests/keystone_contracts_setup.go new file mode 100644 index 0000000000..42269d1bd4 --- /dev/null +++ b/core/capabilities/integration_tests/keystone_contracts_setup.go @@ -0,0 +1,345 @@ +package integration_tests + +import ( + "context" + "encoding/hex" + "fmt" + "log" + "os" + "strings" + "sync" + "testing" + "time" + + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/eth/ethconfig" + gethlog "github.com/ethereum/go-ethereum/log" + "github.com/stretchr/testify/require" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/types/known/durationpb" + + ragetypes "github.com/smartcontractkit/libocr/ragep2p/types" + + "github.com/smartcontractkit/chainlink-common/pkg/capabilities/pb" + "github.com/smartcontractkit/chainlink-common/pkg/values" + + "github.com/smartcontractkit/chainlink-common/pkg/capabilities" + "github.com/smartcontractkit/chainlink-common/pkg/services" + + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/feeds_consumer" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/forwarder" + "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + + kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" +) + +type peer struct { + PeerID string + Signer string +} + +func peerIDToBytes(peerID string) ([32]byte, error) { + var peerIDB ragetypes.PeerID + err := peerIDB.UnmarshalText([]byte(peerID)) + if err != nil { + return [32]byte{}, err + } + + return peerIDB, nil +} + +func peers(ps []peer) ([][32]byte, error) { + out := [][32]byte{} + for _, p := range ps { + b, err := peerIDToBytes(p.PeerID) + if err != nil { + return nil, err + } + + out = append(out, b) + } + + return out, nil +} + +func peerToNode(nopID uint32, p peer) (kcr.CapabilitiesRegistryNodeParams, error) { + peerIDB, err := peerIDToBytes(p.PeerID) + if err != nil { + return kcr.CapabilitiesRegistryNodeParams{}, fmt.Errorf("failed to convert peerID: %w", err) + } + + sig := strings.TrimPrefix(p.Signer, "0x") + signerB, err := hex.DecodeString(sig) + if err != nil { + return kcr.CapabilitiesRegistryNodeParams{}, fmt.Errorf("failed to convert signer: %w", err) + } + + var sigb [32]byte + copy(sigb[:], signerB) + + return kcr.CapabilitiesRegistryNodeParams{ + NodeOperatorId: nopID, + P2pId: peerIDB, + Signer: sigb, + }, nil +} + +func setupCapabilitiesRegistryContract(ctx context.Context, t *testing.T, workflowDonPeers []peer, triggerDonPeers []peer, + targetDonPeerIDs []peer, + transactOpts *bind.TransactOpts, backend *ethBackend) common.Address { + addr, _, reg, err := kcr.DeployCapabilitiesRegistry(transactOpts, backend) + require.NoError(t, err) + + backend.Commit() + + streamsTrigger := kcr.CapabilitiesRegistryCapability{ + LabelledName: "streams-trigger", + Version: "1.0.0", + CapabilityType: uint8(capabilities.CapabilityTypeTrigger), + } + sid, err := reg.GetHashedCapabilityId(&bind.CallOpts{}, streamsTrigger.LabelledName, streamsTrigger.Version) + require.NoError(t, err) + + writeChain := kcr.CapabilitiesRegistryCapability{ + LabelledName: "write_geth-testnet", + Version: "1.0.0", + CapabilityType: uint8(capabilities.CapabilityTypeTarget), + } + wid, err := reg.GetHashedCapabilityId(&bind.CallOpts{}, writeChain.LabelledName, writeChain.Version) + if err != nil { + log.Printf("failed to call GetHashedCapabilityId: %s", err) + } + + ocr := kcr.CapabilitiesRegistryCapability{ + LabelledName: "offchain_reporting", + Version: "1.0.0", + CapabilityType: uint8(capabilities.CapabilityTypeConsensus), + } + ocrid, err := reg.GetHashedCapabilityId(&bind.CallOpts{}, ocr.LabelledName, ocr.Version) + require.NoError(t, err) + + _, err = reg.AddCapabilities(transactOpts, []kcr.CapabilitiesRegistryCapability{ + streamsTrigger, + writeChain, + ocr, + }) + require.NoError(t, err) + backend.Commit() + + _, err = reg.AddNodeOperators(transactOpts, []kcr.CapabilitiesRegistryNodeOperator{ + { + Admin: transactOpts.From, + Name: "TEST_NODE_OPERATOR", + }, + }) + require.NoError(t, err) + blockHash := backend.Commit() + + logs, err := backend.FilterLogs(ctx, ethereum.FilterQuery{ + BlockHash: &blockHash, + FromBlock: nil, + ToBlock: nil, + Addresses: nil, + Topics: nil, + }) + + require.NoError(t, err) + + recLog, err := reg.ParseNodeOperatorAdded(logs[0]) + require.NoError(t, err) + + nopID := recLog.NodeOperatorId + nodes := []kcr.CapabilitiesRegistryNodeParams{} + for _, wfPeer := range workflowDonPeers { + n, innerErr := peerToNode(nopID, wfPeer) + require.NoError(t, innerErr) + + n.HashedCapabilityIds = [][32]byte{ocrid} + nodes = append(nodes, n) + } + + for _, triggerPeer := range triggerDonPeers { + n, innerErr := peerToNode(nopID, triggerPeer) + require.NoError(t, innerErr) + + n.HashedCapabilityIds = [][32]byte{sid} + nodes = append(nodes, n) + } + + for _, targetPeer := range targetDonPeerIDs { + n, innerErr := peerToNode(nopID, targetPeer) + require.NoError(t, innerErr) + + n.HashedCapabilityIds = [][32]byte{wid} + nodes = append(nodes, n) + } + + _, err = reg.AddNodes(transactOpts, nodes) + require.NoError(t, err) + + // workflow DON + ps, err := peers(workflowDonPeers) + require.NoError(t, err) + + cc := newCapabilityConfig() + ccb, err := proto.Marshal(cc) + require.NoError(t, err) + + cfgs := []kcr.CapabilitiesRegistryCapabilityConfiguration{ + { + CapabilityId: ocrid, + Config: ccb, + }, + } + + workflowDonF := uint8(2) + _, err = reg.AddDON(transactOpts, ps, cfgs, false, true, workflowDonF) + require.NoError(t, err) + + // trigger DON + ps, err = peers(triggerDonPeers) + require.NoError(t, err) + + triggerDonF := 1 + config := &pb.RemoteTriggerConfig{ + RegistrationRefresh: durationpb.New(20000 * time.Millisecond), + RegistrationExpiry: durationpb.New(60000 * time.Millisecond), + // F + 1 + MinResponsesToAggregate: uint32(triggerDonF) + 1, + } + configb, err := proto.Marshal(config) + require.NoError(t, err) + + cfgs = []kcr.CapabilitiesRegistryCapabilityConfiguration{ + { + CapabilityId: sid, + Config: configb, + }, + } + + _, err = reg.AddDON(transactOpts, ps, cfgs, true, false, uint8(triggerDonF)) + require.NoError(t, err) + + // target DON + ps, err = peers(targetDonPeerIDs) + require.NoError(t, err) + + cfgs = []kcr.CapabilitiesRegistryCapabilityConfiguration{ + { + CapabilityId: wid, + Config: ccb, + }, + } + + targetDonF := uint8(1) + _, err = reg.AddDON(transactOpts, ps, cfgs, true, false, targetDonF) + require.NoError(t, err) + + backend.Commit() + + return addr +} + +func newCapabilityConfig() *pb.CapabilityConfig { + return &pb.CapabilityConfig{ + DefaultConfig: values.Proto(values.EmptyMap()).GetMapValue(), + } +} + +func setupForwarderContract(t *testing.T, workflowDonPeers []peer, workflowDonId uint32, + configVersion uint32, f uint8, + transactOpts *bind.TransactOpts, backend *ethBackend) (common.Address, *forwarder.KeystoneForwarder) { + addr, _, fwd, err := forwarder.DeployKeystoneForwarder(transactOpts, backend) + require.NoError(t, err) + backend.Commit() + + var signers []common.Address + for _, p := range workflowDonPeers { + signers = append(signers, common.HexToAddress(p.Signer)) + } + + _, err = fwd.SetConfig(transactOpts, workflowDonId, configVersion, f, signers) + require.NoError(t, err) + backend.Commit() + + return addr, fwd +} + +func setupConsumerContract(t *testing.T, transactOpts *bind.TransactOpts, backend *ethBackend, + forwarderAddress common.Address, workflowOwner string, workflowName string) (common.Address, *feeds_consumer.KeystoneFeedsConsumer) { + addr, _, consumer, err := feeds_consumer.DeployKeystoneFeedsConsumer(transactOpts, backend) + require.NoError(t, err) + backend.Commit() + + var nameBytes [10]byte + copy(nameBytes[:], workflowName) + + ownerAddr := common.HexToAddress(workflowOwner) + + _, err = consumer.SetConfig(transactOpts, []common.Address{forwarderAddress}, []common.Address{ownerAddr}, [][10]byte{nameBytes}) + require.NoError(t, err) + + backend.Commit() + + return addr, consumer +} + +type ethBackend struct { + services.StateMachine + *backends.SimulatedBackend + + blockTimeProcessingTime time.Duration + + stopCh services.StopChan + wg sync.WaitGroup +} + +func setupBlockchain(t *testing.T, initialEth int, blockTimeProcessingTime time.Duration) (*ethBackend, *bind.TransactOpts) { + transactOpts := testutils.MustNewSimTransactor(t) // config contract deployer and owner + genesisData := core.GenesisAlloc{transactOpts.From: {Balance: assets.Ether(initialEth).ToInt()}} + backend := cltest.NewSimulatedBackend(t, genesisData, uint32(ethconfig.Defaults.Miner.GasCeil)) + gethlog.SetDefault(gethlog.NewLogger(gethlog.NewTerminalHandlerWithLevel(os.Stderr, gethlog.LevelWarn, true))) + backend.Commit() + + return ðBackend{SimulatedBackend: backend, stopCh: make(services.StopChan), + blockTimeProcessingTime: blockTimeProcessingTime}, transactOpts +} + +func (b *ethBackend) Start(ctx context.Context) error { + return b.StartOnce("ethBackend", func() error { + b.wg.Add(1) + go func() { + defer b.wg.Done() + ticker := time.NewTicker(b.blockTimeProcessingTime) + defer ticker.Stop() + + for { + select { + case <-b.stopCh: + return + case <-ctx.Done(): + return + case <-ticker.C: + b.SimulatedBackend.Commit() + } + } + }() + + return nil + }) +} + +func (b *ethBackend) Close() error { + return b.StopOnce("ethBackend", func() error { + close(b.stopCh) + b.wg.Wait() + return nil + }) +} diff --git a/core/capabilities/integration_tests/mock_dispatcher.go b/core/capabilities/integration_tests/mock_dispatcher.go new file mode 100644 index 0000000000..f685f0ad2e --- /dev/null +++ b/core/capabilities/integration_tests/mock_dispatcher.go @@ -0,0 +1,195 @@ +package integration_tests + +import ( + "context" + "fmt" + "sync" + "testing" + "time" + + "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + remotetypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/types" + p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" + + "google.golang.org/protobuf/proto" +) + +// testAsyncMessageBroker backs the dispatchers created for each node in the test and effectively +// acts as the rageP2P network layer. +type testAsyncMessageBroker struct { + services.StateMachine + t *testing.T + + chanBufferSize int + stopCh services.StopChan + wg sync.WaitGroup + + peerIDToBrokerNode map[p2ptypes.PeerID]*brokerNode + + mux sync.Mutex +} + +func newTestAsyncMessageBroker(t *testing.T, chanBufferSize int) *testAsyncMessageBroker { + return &testAsyncMessageBroker{ + t: t, + stopCh: make(services.StopChan), + chanBufferSize: chanBufferSize, + peerIDToBrokerNode: make(map[p2ptypes.PeerID]*brokerNode), + } +} + +func (a *testAsyncMessageBroker) Start(ctx context.Context) error { + return a.StartOnce("testAsyncMessageBroker", func() error { + return nil + }) +} + +func (a *testAsyncMessageBroker) Close() error { + return a.StopOnce("testAsyncMessageBroker", func() error { + close(a.stopCh) + a.wg.Wait() + return nil + }) +} + +// NewDispatcherForNode creates a new dispatcher for a node with the given peer ID. +func (a *testAsyncMessageBroker) NewDispatcherForNode(nodePeerID p2ptypes.PeerID) remotetypes.Dispatcher { + return &brokerDispatcher{ + callerPeerID: nodePeerID, + broker: a, + } +} + +func (a *testAsyncMessageBroker) HealthReport() map[string]error { + return nil +} + +func (a *testAsyncMessageBroker) Name() string { + return "testAsyncMessageBroker" +} + +func (a *testAsyncMessageBroker) registerReceiverNode(nodePeerID p2ptypes.PeerID, capabilityId string, capabilityDonID uint32, receiver remotetypes.Receiver) { + a.mux.Lock() + defer a.mux.Unlock() + + node, ok := a.peerIDToBrokerNode[nodePeerID] + if !ok { + node = a.newNode() + a.peerIDToBrokerNode[nodePeerID] = node + } + + node.registerReceiverCh <- ®isterReceiverRequest{ + receiverKey: receiverKey{ + capabilityId: capabilityId, + donId: capabilityDonID, + }, + receiver: receiver, + } +} + +func (a *testAsyncMessageBroker) Send(msg *remotetypes.MessageBody) { + peerID := toPeerID(msg.Receiver) + node, ok := a.peerIDToBrokerNode[peerID] + if !ok { + panic(fmt.Sprintf("node not found for peer ID %v", peerID)) + } + + node.receiveCh <- msg +} + +type brokerNode struct { + registerReceiverCh chan *registerReceiverRequest + receiveCh chan *remotetypes.MessageBody +} + +type receiverKey struct { + capabilityId string + donId uint32 +} + +type registerReceiverRequest struct { + receiverKey + receiver remotetypes.Receiver +} + +func (a *testAsyncMessageBroker) newNode() *brokerNode { + n := &brokerNode{ + receiveCh: make(chan *remotetypes.MessageBody, a.chanBufferSize), + registerReceiverCh: make(chan *registerReceiverRequest, a.chanBufferSize), + } + + a.wg.Add(1) + go func() { + defer a.wg.Done() + receivers := make(map[receiverKey]remotetypes.Receiver) + for { + select { + case <-a.stopCh: + return + case msg := <-n.receiveCh: + k := receiverKey{ + capabilityId: msg.CapabilityId, + donId: msg.CapabilityDonId, + } + + r, ok := receivers[k] + if !ok { + panic(fmt.Sprintf("receiver not found for key %+v", k)) + } + + r.Receive(tests.Context(a.t), msg) + case reg := <-n.registerReceiverCh: + receivers[reg.receiverKey] = reg.receiver + } + } + }() + return n +} + +func toPeerID(id []byte) p2ptypes.PeerID { + return [32]byte(id) +} + +type broker interface { + Send(msg *remotetypes.MessageBody) +} + +type brokerDispatcher struct { + callerPeerID p2ptypes.PeerID + broker broker +} + +func (t *brokerDispatcher) Send(peerID p2ptypes.PeerID, msgBody *remotetypes.MessageBody) error { + clonedMsg := proto.Clone(msgBody).(*remotetypes.MessageBody) + clonedMsg.Version = 1 + clonedMsg.Sender = t.callerPeerID[:] + clonedMsg.Receiver = peerID[:] + clonedMsg.Timestamp = time.Now().UnixMilli() + t.broker.Send(clonedMsg) + return nil +} + +func (t *brokerDispatcher) SetReceiver(capabilityId string, donId uint32, receiver remotetypes.Receiver) error { + t.broker.(*testAsyncMessageBroker).registerReceiverNode(t.callerPeerID, capabilityId, donId, receiver) + return nil +} +func (t *brokerDispatcher) RemoveReceiver(capabilityId string, donId uint32) {} + +func (t *brokerDispatcher) Start(context.Context) error { return nil } + +func (t *brokerDispatcher) Close() error { + return nil +} + +func (t *brokerDispatcher) Ready() error { + return nil +} + +func (t *brokerDispatcher) HealthReport() map[string]error { + return nil +} + +func (t *brokerDispatcher) Name() string { + return "mockDispatcher" +} diff --git a/core/capabilities/integration_tests/mock_libocr.go b/core/capabilities/integration_tests/mock_libocr.go new file mode 100644 index 0000000000..39c53d48af --- /dev/null +++ b/core/capabilities/integration_tests/mock_libocr.go @@ -0,0 +1,198 @@ +package integration_tests + +import ( + "bytes" + "context" + "fmt" + "math/rand" + "sync" + "testing" + "time" + + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/libocr/commontypes" + "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" + "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + + "github.com/smartcontractkit/chainlink-common/pkg/capabilities/consensus/ocr3" + "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ocr2key" +) + +type libocrNode struct { + ocr3types.ReportingPlugin[[]byte] + *ocr3.ContractTransmitter + key ocr2key.KeyBundle +} + +// mockLibOCR is a mock libocr implementation for testing purposes that simulates libocr protocol rounds without having +// to setup the libocr network +type mockLibOCR struct { + services.StateMachine + t *testing.T + + nodes []*libocrNode + f uint8 + protocolRoundInterval time.Duration + + seqNr uint64 + outcomeCtx ocr3types.OutcomeContext + + stopCh services.StopChan + wg sync.WaitGroup +} + +func newMockLibOCR(t *testing.T, f uint8, protocolRoundInterval time.Duration) *mockLibOCR { + return &mockLibOCR{ + t: t, + f: f, outcomeCtx: ocr3types.OutcomeContext{ + SeqNr: 0, + PreviousOutcome: nil, + Epoch: 0, + Round: 0, + }, + protocolRoundInterval: protocolRoundInterval, + stopCh: make(services.StopChan), + } +} + +func (m *mockLibOCR) Start(ctx context.Context) error { + return m.StartOnce("mockLibOCR", func() error { + m.wg.Add(1) + go func() { + defer m.wg.Done() + + ticker := time.NewTicker(m.protocolRoundInterval) + defer ticker.Stop() + + for { + select { + case <-m.stopCh: + return + case <-ctx.Done(): + return + case <-ticker.C: + err := m.simulateProtocolRound(ctx) + if err != nil { + require.FailNow(m.t, err.Error()) + } + } + } + }() + return nil + }) +} + +func (m *mockLibOCR) Close() error { + return m.StopOnce("mockLibOCR", func() error { + close(m.stopCh) + m.wg.Wait() + return nil + }) +} + +func (m *mockLibOCR) AddNode(plugin ocr3types.ReportingPlugin[[]byte], transmitter *ocr3.ContractTransmitter, key ocr2key.KeyBundle) { + m.nodes = append(m.nodes, &libocrNode{plugin, transmitter, key}) +} + +func (m *mockLibOCR) simulateProtocolRound(ctx context.Context) error { + // randomly select a leader + leader := m.nodes[rand.Intn(len(m.nodes))] + + // get the query + query, err := leader.Query(ctx, m.outcomeCtx) + if err != nil { + return fmt.Errorf("failed to get query: %w", err) + } + + var observations []types.AttributedObservation + for oracleID, node := range m.nodes { + obs, err2 := node.Observation(ctx, m.outcomeCtx, query) + if err2 != nil { + return fmt.Errorf("failed to get observation: %w", err) + } + + observations = append(observations, types.AttributedObservation{ + Observation: obs, + Observer: commontypes.OracleID(oracleID), + }) + } + + var outcomes []ocr3types.Outcome + for _, node := range m.nodes { + outcome, err2 := node.Outcome(m.outcomeCtx, query, observations) + if err2 != nil { + return fmt.Errorf("failed to get outcome: %w", err) + } + + if len(outcome) == 0 { + return nil // wait until all nodes have an outcome for testing purposes + } + + outcomes = append(outcomes, outcome) + } + + // if all outcomes are equal proceed to reports + for _, outcome := range outcomes { + if !bytes.Equal(outcome, outcomes[0]) { + return nil + } + } + + reports, err := leader.Reports(0, outcomes[0]) + if err != nil { + return fmt.Errorf("failed to get reports: %w", err) + } + for _, report := range reports { + // create signatures + var signatures []types.AttributedOnchainSignature + for i, node := range m.nodes { + sig, err := node.key.Sign(types.ReportContext{}, report.Report) + if err != nil { + return fmt.Errorf("failed to sign report: %w", err) + } + + signatures = append(signatures, types.AttributedOnchainSignature{ + Signer: commontypes.OracleID(i), + Signature: sig, + }) + + if uint8(len(signatures)) == m.f+1 { + break + } + } + + for _, node := range m.nodes { + accept, err := node.ShouldAcceptAttestedReport(ctx, m.seqNr, report) + if err != nil { + return fmt.Errorf("failed to check if report should be accepted: %w", err) + } + if !accept { + continue + } + + transmit, err := node.ShouldTransmitAcceptedReport(ctx, m.seqNr, report) + if err != nil { + return fmt.Errorf("failed to check if report should be transmitted: %w", err) + } + + if !transmit { + continue + } + + err = node.Transmit(ctx, types.ConfigDigest{}, 0, report, signatures) + if err != nil { + return fmt.Errorf("failed to transmit report: %w", err) + } + } + + m.seqNr++ + m.outcomeCtx = ocr3types.OutcomeContext{ + SeqNr: 0, + PreviousOutcome: outcomes[0], + } + } + + return nil +} diff --git a/core/capabilities/integration_tests/mock_trigger.go b/core/capabilities/integration_tests/mock_trigger.go new file mode 100644 index 0000000000..cb673f54ff --- /dev/null +++ b/core/capabilities/integration_tests/mock_trigger.go @@ -0,0 +1,147 @@ +package integration_tests + +import ( + "context" + "fmt" + "strconv" + "sync" + "testing" + + "github.com/smartcontractkit/chainlink-common/pkg/capabilities" + "github.com/smartcontractkit/chainlink-common/pkg/capabilities/datastreams" + "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink-common/pkg/values" +) + +const triggerID = "streams-trigger@1.0.0" + +type reportsSink struct { + services.StateMachine + triggers []streamsTrigger + + stopCh services.StopChan + wg sync.WaitGroup +} + +func newReportsSink() *reportsSink { + return &reportsSink{ + stopCh: make(services.StopChan), + } +} + +func (r *reportsSink) Start(ctx context.Context) error { + return r.StartOnce("reportsSink", func() error { + return nil + }) +} + +func (r *reportsSink) Close() error { + return r.StopOnce("reportsSink", func() error { + close(r.stopCh) + r.wg.Wait() + return nil + }) +} + +func (r *reportsSink) sendReports(reportList []*datastreams.FeedReport) { + for _, trigger := range r.triggers { + resp, err := wrapReports(reportList, "1", 12, datastreams.SignersMetadata{}) + if err != nil { + panic(err) + } + trigger.sendResponse(resp) + } +} + +func (r *reportsSink) getNewTrigger(t *testing.T) *streamsTrigger { + trigger := streamsTrigger{t: t, toSend: make(chan capabilities.CapabilityResponse, 1000), + wg: &r.wg, stopCh: r.stopCh} + r.triggers = append(r.triggers, trigger) + return &trigger +} + +type streamsTrigger struct { + t *testing.T + cancel context.CancelFunc + toSend chan capabilities.CapabilityResponse + + wg *sync.WaitGroup + stopCh services.StopChan +} + +func (s *streamsTrigger) sendResponse(resp capabilities.CapabilityResponse) { + s.toSend <- resp +} + +func (s *streamsTrigger) Info(ctx context.Context) (capabilities.CapabilityInfo, error) { + return capabilities.MustNewCapabilityInfo( + triggerID, + capabilities.CapabilityTypeTrigger, + "issues a trigger when a report is received.", + ), nil +} + +func (s *streamsTrigger) RegisterTrigger(ctx context.Context, request capabilities.CapabilityRequest) (<-chan capabilities.CapabilityResponse, error) { + if s.cancel != nil { + s.t.Fatal("trigger already registered") + } + + responseCh := make(chan capabilities.CapabilityResponse) + + ctxWithCancel, cancel := context.WithCancel(ctx) + s.cancel = cancel + s.wg.Add(1) + go func() { + defer s.wg.Done() + select { + case <-s.stopCh: + return + case <-ctxWithCancel.Done(): + return + case resp := <-s.toSend: + responseCh <- resp + } + }() + + return responseCh, nil +} + +func (s *streamsTrigger) UnregisterTrigger(ctx context.Context, request capabilities.CapabilityRequest) error { + if s.cancel == nil { + s.t.Fatal("trigger not registered") + } + + s.cancel() + s.cancel = nil + return nil +} + +func wrapReports(reportList []*datastreams.FeedReport, eventID string, timestamp int64, meta datastreams.SignersMetadata) (capabilities.CapabilityResponse, error) { + val, err := values.Wrap(reportList) + if err != nil { + return capabilities.CapabilityResponse{}, err + } + + metaVal, err := values.Wrap(meta) + if err != nil { + return capabilities.CapabilityResponse{}, err + } + + triggerEvent := capabilities.TriggerEvent{ + TriggerType: triggerID, + ID: eventID, + Timestamp: strconv.FormatInt(timestamp, 10), + Metadata: metaVal, + Payload: val, + } + + triggerEventMapValue, err := values.WrapMap(triggerEvent) + if err != nil { + return capabilities.CapabilityResponse{}, fmt.Errorf("failed to wrap trigger event: %w", err) + } + + // Create a new CapabilityResponse with the MercuryTriggerEvent + return capabilities.CapabilityResponse{ + Value: triggerEventMapValue, + }, nil +} diff --git a/core/capabilities/integration_tests/setup.go b/core/capabilities/integration_tests/setup.go new file mode 100644 index 0000000000..0095d2fd9d --- /dev/null +++ b/core/capabilities/integration_tests/setup.go @@ -0,0 +1,438 @@ +package integration_tests + +import ( + "context" + "crypto/rand" + "encoding/hex" + "fmt" + "math/big" + "strconv" + "testing" + "time" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/mr-tron/base58" + "github.com/stretchr/testify/require" + "go.uber.org/zap/zapcore" + + "github.com/smartcontractkit/libocr/offchainreporting2plus/chains/evmutil" + "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" + ocrTypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/feeds_consumer" + + commoncap "github.com/smartcontractkit/chainlink-common/pkg/capabilities" + "github.com/smartcontractkit/chainlink-common/pkg/capabilities/consensus/ocr3" + "github.com/smartcontractkit/chainlink-common/pkg/capabilities/datastreams" + "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" + coretypes "github.com/smartcontractkit/chainlink-common/pkg/types/core" + v3 "github.com/smartcontractkit/chainlink-common/pkg/types/mercury/v3" + "github.com/smartcontractkit/chainlink/v2/core/capabilities" + remotetypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/types" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" + "github.com/smartcontractkit/chainlink/v2/core/internal/cltest/heavyweight" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/chaintype" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ocr2key" + p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" + "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" + "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/v3/reportcodec" +) + +const ( + // As a default set the logging to info otherwise 10s/100s of MB of logs are created on each test run + TestLogLevel = zapcore.InfoLevel +) + +var ( + workflowName = "abcdef0123" + workflowOwnerID = "0100000000000000000000000000000000000001" +) + +type donInfo struct { + commoncap.DON + keys []ethkey.KeyV2 + keyBundles []ocr2key.KeyBundle + peerIDs []peer +} + +func setupStreamDonsWithTransmissionSchedule(ctx context.Context, t *testing.T, workflowDonInfo donInfo, triggerDonInfo donInfo, targetDonInfo donInfo, + feedCount int, deltaStage string, schedule string) (*feeds_consumer.KeystoneFeedsConsumer, []string, *reportsSink) { + lggr := logger.TestLogger(t) + lggr.SetLogLevel(TestLogLevel) + + ethBlockchain, transactor := setupBlockchain(t, 1000, 1*time.Second) + capabilitiesRegistryAddr := setupCapabilitiesRegistryContract(ctx, t, workflowDonInfo.peerIDs, triggerDonInfo.peerIDs, targetDonInfo.peerIDs, transactor, ethBlockchain) + forwarderAddr, _ := setupForwarderContract(t, workflowDonInfo.peerIDs, workflowDonInfo.ID, 1, workflowDonInfo.F, transactor, ethBlockchain) + consumerAddr, consumer := setupConsumerContract(t, transactor, ethBlockchain, forwarderAddr, workflowOwnerID, workflowName) + + var feedIDs []string + for i := 0; i < feedCount; i++ { + feedIDs = append(feedIDs, newFeedID(t)) + } + + sink := newReportsSink() + + libocr := newMockLibOCR(t, workflowDonInfo.F, 1*time.Second) + workflowDonNodes, _, _ := createDons(ctx, t, lggr, sink, + workflowDonInfo, triggerDonInfo, targetDonInfo, + ethBlockchain, capabilitiesRegistryAddr, forwarderAddr, + workflowDonInfo.keyBundles, transactor, libocr) + for _, node := range workflowDonNodes { + addWorkflowJob(t, node, workflowName, workflowOwnerID, feedIDs, consumerAddr, deltaStage, schedule) + } + + servicetest.Run(t, ethBlockchain) + servicetest.Run(t, libocr) + servicetest.Run(t, sink) + return consumer, feedIDs, sink +} + +func createDons(ctx context.Context, t *testing.T, lggr logger.Logger, reportsSink *reportsSink, + workflowDon donInfo, + triggerDon donInfo, + targetDon donInfo, + simulatedEthBlockchain *ethBackend, + capRegistryAddr common.Address, + forwarderAddr common.Address, + workflowNodeKeyBundles []ocr2key.KeyBundle, + transactor *bind.TransactOpts, + libocr *mockLibOCR, +) ([]*cltest.TestApplication, []*cltest.TestApplication, []*cltest.TestApplication) { + broker := newTestAsyncMessageBroker(t, 1000) + + var triggerNodes []*cltest.TestApplication + for i, triggerPeer := range triggerDon.Members { + triggerPeerDispatcher := broker.NewDispatcherForNode(triggerPeer) + nodeInfo := commoncap.Node{ + PeerID: &triggerPeer, + } + + capabilityRegistry := capabilities.NewRegistry(lggr) + trigger := reportsSink.getNewTrigger(t) + err := capabilityRegistry.Add(ctx, trigger) + require.NoError(t, err) + + triggerNode := startNewNode(ctx, t, lggr.Named("Trigger-"+strconv.Itoa(i)), nodeInfo, simulatedEthBlockchain, capRegistryAddr, triggerPeerDispatcher, + testPeerWrapper{peer: testPeer{triggerPeer}}, capabilityRegistry, nil, transactor, + triggerDon.keys[i]) + + require.NoError(t, triggerNode.Start(testutils.Context(t))) + triggerNodes = append(triggerNodes, triggerNode) + } + + var targetNodes []*cltest.TestApplication + for i, targetPeer := range targetDon.Members { + targetPeerDispatcher := broker.NewDispatcherForNode(targetPeer) + nodeInfo := commoncap.Node{ + PeerID: &targetPeer, + } + + capabilityRegistry := capabilities.NewRegistry(lggr) + + targetNode := startNewNode(ctx, t, lggr.Named("Target-"+strconv.Itoa(i)), nodeInfo, simulatedEthBlockchain, capRegistryAddr, targetPeerDispatcher, + testPeerWrapper{peer: testPeer{targetPeer}}, capabilityRegistry, &forwarderAddr, transactor, + targetDon.keys[i]) + + require.NoError(t, targetNode.Start(testutils.Context(t))) + targetNodes = append(triggerNodes, targetNode) + } + + var workflowNodes []*cltest.TestApplication + for i, workflowPeer := range workflowDon.Members { + workflowPeerDispatcher := broker.NewDispatcherForNode(workflowPeer) + capabilityRegistry := capabilities.NewRegistry(lggr) + + requestTimeout := 10 * time.Minute + cfg := ocr3.Config{ + Logger: lggr, + EncoderFactory: evm.NewEVMEncoder, + AggregatorFactory: capabilities.NewAggregator, + RequestTimeout: &requestTimeout, + } + + ocr3Capability := ocr3.NewOCR3(cfg) + servicetest.Run(t, ocr3Capability) + + pluginCfg := coretypes.ReportingPluginServiceConfig{} + pluginFactory, err := ocr3Capability.NewReportingPluginFactory(ctx, pluginCfg, nil, + nil, nil, nil, capabilityRegistry, nil, nil) + require.NoError(t, err) + + repConfig := ocr3types.ReportingPluginConfig{ + F: int(workflowDon.F), + } + plugin, _, err := pluginFactory.NewReportingPlugin(repConfig) + require.NoError(t, err) + + transmitter := ocr3.NewContractTransmitter(lggr, capabilityRegistry, "") + + libocr.AddNode(plugin, transmitter, workflowNodeKeyBundles[i]) + + nodeInfo := commoncap.Node{ + PeerID: &workflowPeer, + WorkflowDON: workflowDon.DON, + CapabilityDONs: []commoncap.DON{triggerDon.DON, targetDon.DON}, + } + + workflowNode := startNewNode(ctx, t, lggr.Named("Workflow-"+strconv.Itoa(i)), nodeInfo, simulatedEthBlockchain, capRegistryAddr, workflowPeerDispatcher, + testPeerWrapper{peer: testPeer{workflowPeer}}, capabilityRegistry, nil, transactor, + workflowDon.keys[i]) + + require.NoError(t, workflowNode.Start(testutils.Context(t))) + workflowNodes = append(workflowNodes, workflowNode) + } + + servicetest.Run(t, broker) + + return workflowNodes, triggerNodes, targetNodes +} + +func startNewNode(ctx context.Context, + t *testing.T, lggr logger.Logger, nodeInfo commoncap.Node, + backend *ethBackend, capRegistryAddr common.Address, + dispatcher remotetypes.Dispatcher, + peerWrapper p2ptypes.PeerWrapper, + localCapabilities *capabilities.Registry, + forwarderAddress *common.Address, + transactor *bind.TransactOpts, + keyV2 ethkey.KeyV2, +) *cltest.TestApplication { + config, _ := heavyweight.FullTestDBV2(t, func(c *chainlink.Config, s *chainlink.Secrets) { + c.Capabilities.ExternalRegistry.ChainID = ptr(fmt.Sprintf("%d", testutils.SimulatedChainID)) + c.Capabilities.ExternalRegistry.Address = ptr(capRegistryAddr.String()) + c.Capabilities.Peering.V2.Enabled = ptr(true) + + if forwarderAddress != nil { + eip55Address := types.EIP55AddressFromAddress(*forwarderAddress) + c.EVM[0].Chain.Workflow.ForwarderAddress = &eip55Address + c.EVM[0].Chain.Workflow.FromAddress = &keyV2.EIP55Address + } + + c.Feature.FeedsManager = ptr(false) + }) + + n, err := backend.NonceAt(ctx, transactor.From, nil) + require.NoError(t, err) + + tx := cltest.NewLegacyTransaction( + n, keyV2.Address, + assets.Ether(1).ToInt(), + 21000, + assets.GWei(1).ToInt(), + nil) + signedTx, err := transactor.Signer(transactor.From, tx) + require.NoError(t, err) + err = backend.SendTransaction(ctx, signedTx) + require.NoError(t, err) + backend.Commit() + + return cltest.NewApplicationWithConfigV2AndKeyOnSimulatedBlockchain(t, config, backend.SimulatedBackend, nodeInfo, + dispatcher, peerWrapper, localCapabilities, keyV2, lggr) +} + +type don struct { + id uint32 + numNodes int + f uint8 +} + +func createDonInfo(t *testing.T, don don) donInfo { + keyBundles, peerIDs := getKeyBundlesAndPeerIDs(t, don.numNodes) + + donPeers := make([]p2ptypes.PeerID, len(peerIDs)) + var donKeys []ethkey.KeyV2 + for i := 0; i < len(peerIDs); i++ { + peerID := p2ptypes.PeerID{} + require.NoError(t, peerID.UnmarshalText([]byte(peerIDs[i].PeerID))) + donPeers[i] = peerID + newKey, err := ethkey.NewV2() + require.NoError(t, err) + donKeys = append(donKeys, newKey) + } + + triggerDonInfo := donInfo{ + DON: commoncap.DON{ + ID: don.id, + Members: donPeers, + F: don.f, + }, + peerIDs: peerIDs, + keys: donKeys, + keyBundles: keyBundles, + } + return triggerDonInfo +} + +func createFeedReport(t *testing.T, price *big.Int, observationTimestamp int64, + feedIDString string, + keyBundles []ocr2key.KeyBundle) *datastreams.FeedReport { + reportCtx := ocrTypes.ReportContext{} + rawCtx := RawReportContext(reportCtx) + + bytes, err := hex.DecodeString(feedIDString[2:]) + require.NoError(t, err) + var feedIDBytes [32]byte + copy(feedIDBytes[:], bytes) + + report := &datastreams.FeedReport{ + FeedID: feedIDString, + FullReport: newReport(t, feedIDBytes, price, observationTimestamp), + BenchmarkPrice: price.Bytes(), + ObservationTimestamp: observationTimestamp, + Signatures: [][]byte{}, + ReportContext: rawCtx, + } + + for _, key := range keyBundles { + sig, err := key.Sign(reportCtx, report.FullReport) + require.NoError(t, err) + report.Signatures = append(report.Signatures, sig) + } + + return report +} + +func getKeyBundlesAndPeerIDs(t *testing.T, numNodes int) ([]ocr2key.KeyBundle, []peer) { + var keyBundles []ocr2key.KeyBundle + var donPeerIDs []peer + for i := 0; i < numNodes; i++ { + peerID := NewPeerID() + + keyBundle, err := ocr2key.New(chaintype.EVM) + require.NoError(t, err) + keyBundles = append(keyBundles, keyBundle) + + pk := keyBundle.PublicKey() + + p := peer{ + PeerID: peerID, + Signer: fmt.Sprintf("0x%x", pk), + } + + donPeerIDs = append(donPeerIDs, p) + } + return keyBundles, donPeerIDs +} + +func newFeedID(t *testing.T) string { + buf := [32]byte{} + _, err := rand.Read(buf[:]) + require.NoError(t, err) + return "0x" + hex.EncodeToString(buf[:]) +} + +func newReport(t *testing.T, feedID [32]byte, price *big.Int, timestamp int64) []byte { + v3Codec := reportcodec.NewReportCodec(feedID, logger.TestLogger(t)) + raw, err := v3Codec.BuildReport(v3.ReportFields{ + BenchmarkPrice: price, + Timestamp: uint32(timestamp), + Bid: big.NewInt(0), + Ask: big.NewInt(0), + LinkFee: big.NewInt(0), + NativeFee: big.NewInt(0), + }) + require.NoError(t, err) + return raw +} + +type testPeerWrapper struct { + peer testPeer +} + +func (t testPeerWrapper) Start(ctx context.Context) error { + return nil +} + +func (t testPeerWrapper) Close() error { + return nil +} + +func (t testPeerWrapper) Ready() error { + return nil +} + +func (t testPeerWrapper) HealthReport() map[string]error { + return nil +} + +func (t testPeerWrapper) Name() string { + return "testPeerWrapper" +} + +func (t testPeerWrapper) GetPeer() p2ptypes.Peer { + return t.peer +} + +type testPeer struct { + id p2ptypes.PeerID +} + +func (t testPeer) Start(ctx context.Context) error { + return nil +} + +func (t testPeer) Close() error { + return nil +} + +func (t testPeer) Ready() error { + return nil +} + +func (t testPeer) HealthReport() map[string]error { + return nil +} + +func (t testPeer) Name() string { + return "testPeer" +} + +func (t testPeer) ID() p2ptypes.PeerID { + return t.id +} + +func (t testPeer) UpdateConnections(peers map[p2ptypes.PeerID]p2ptypes.StreamConfig) error { + return nil +} + +func (t testPeer) Send(peerID p2ptypes.PeerID, msg []byte) error { + return nil +} + +func (t testPeer) Receive() <-chan p2ptypes.Message { + return nil +} + +func NewPeerID() string { + var privKey [32]byte + _, err := rand.Read(privKey[:]) + if err != nil { + panic(err) + } + + peerID := append(libp2pMagic(), privKey[:]...) + + return base58.Encode(peerID[:]) +} + +func libp2pMagic() []byte { + return []byte{0x00, 0x24, 0x08, 0x01, 0x12, 0x20} +} + +func ptr[T any](t T) *T { return &t } + +func RawReportContext(reportCtx ocrTypes.ReportContext) []byte { + rc := evmutil.RawReportContext(reportCtx) + flat := []byte{} + for _, r := range rc { + flat = append(flat, r[:]...) + } + return flat +} diff --git a/core/capabilities/integration_tests/streams_test.go b/core/capabilities/integration_tests/streams_test.go new file mode 100644 index 0000000000..6216e36c85 --- /dev/null +++ b/core/capabilities/integration_tests/streams_test.go @@ -0,0 +1,99 @@ +package integration_tests + +import ( + "context" + "encoding/hex" + "math/big" + "testing" + "time" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink-common/pkg/capabilities/datastreams" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/feeds_consumer" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + reporttypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/mercury/v3/types" +) + +func Test_AllAtOnceTransmissionSchedule(t *testing.T) { + ctx := testutils.Context(t) + + // The don IDs set in the below calls are inferred from the order in which the dons are added to the capabilities registry + // in the setupCapabilitiesRegistryContract function, should this order change the don IDs will need updating. + workflowDonInfo := createDonInfo(t, don{id: 1, numNodes: 5, f: 1}) + triggerDonInfo := createDonInfo(t, don{id: 2, numNodes: 7, f: 1}) + targetDonInfo := createDonInfo(t, don{id: 3, numNodes: 4, f: 1}) + + consumer, feedIDs, triggerSink := setupStreamDonsWithTransmissionSchedule(ctx, t, workflowDonInfo, triggerDonInfo, targetDonInfo, 3, + "2s", "allAtOnce") + + reports := []*datastreams.FeedReport{ + createFeedReport(t, big.NewInt(1), 5, feedIDs[0], triggerDonInfo.keyBundles), + createFeedReport(t, big.NewInt(3), 7, feedIDs[1], triggerDonInfo.keyBundles), + createFeedReport(t, big.NewInt(2), 6, feedIDs[2], triggerDonInfo.keyBundles), + } + + triggerSink.sendReports(reports) + + waitForConsumerReports(ctx, t, consumer, reports) +} + +func Test_OneAtATimeTransmissionSchedule(t *testing.T) { + ctx := testutils.Context(t) + + // The don IDs set in the below calls are inferred from the order in which the dons are added to the capabilities registry + // in the setupCapabilitiesRegistryContract function, should this order change the don IDs will need updating. + workflowDonInfo := createDonInfo(t, don{id: 1, numNodes: 5, f: 1}) + triggerDonInfo := createDonInfo(t, don{id: 2, numNodes: 7, f: 1}) + targetDonInfo := createDonInfo(t, don{id: 3, numNodes: 4, f: 1}) + + consumer, feedIDs, triggerSink := setupStreamDonsWithTransmissionSchedule(ctx, t, workflowDonInfo, triggerDonInfo, targetDonInfo, 3, + "2s", "oneAtATime") + + reports := []*datastreams.FeedReport{ + createFeedReport(t, big.NewInt(1), 5, feedIDs[0], triggerDonInfo.keyBundles), + createFeedReport(t, big.NewInt(3), 7, feedIDs[1], triggerDonInfo.keyBundles), + createFeedReport(t, big.NewInt(2), 6, feedIDs[2], triggerDonInfo.keyBundles), + } + + triggerSink.sendReports(reports) + + waitForConsumerReports(ctx, t, consumer, reports) +} + +func waitForConsumerReports(ctx context.Context, t *testing.T, consumer *feeds_consumer.KeystoneFeedsConsumer, triggerFeedReports []*datastreams.FeedReport) { + feedsReceived := make(chan *feeds_consumer.KeystoneFeedsConsumerFeedReceived, 1000) + feedsSub, err := consumer.WatchFeedReceived(&bind.WatchOpts{}, feedsReceived, nil) + require.NoError(t, err) + + feedToReport := map[string]*datastreams.FeedReport{} + for _, report := range triggerFeedReports { + feedToReport[report.FeedID] = report + } + + ctxWithTimeout, cancel := context.WithTimeout(ctx, 5*time.Minute) + defer cancel() + feedCount := 0 + for { + select { + case <-ctxWithTimeout.Done(): + t.Fatalf("timed out waiting for feed reports, expected %d, received %d", len(triggerFeedReports), feedCount) + case err := <-feedsSub.Err(): + require.NoError(t, err) + case feed := <-feedsReceived: + feedID := "0x" + hex.EncodeToString(feed.FeedId[:]) + report := feedToReport[feedID] + decodedReport, err := reporttypes.Decode(report.FullReport) + require.NoError(t, err) + assert.Equal(t, decodedReport.BenchmarkPrice, feed.Price) + assert.Equal(t, decodedReport.ObservationsTimestamp, feed.Timestamp) + + feedCount++ + if feedCount == len(triggerFeedReports) { + return + } + } + } +} diff --git a/core/capabilities/integration_tests/workflow.go b/core/capabilities/integration_tests/workflow.go new file mode 100644 index 0000000000..d116a1ec63 --- /dev/null +++ b/core/capabilities/integration_tests/workflow.go @@ -0,0 +1,75 @@ +package integration_tests + +import ( + "fmt" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + "github.com/smartcontractkit/chainlink/v2/core/testdata/testspecs" +) + +const hardcodedWorkflow = ` +name: "%s" +owner: "0x%s" +triggers: + - id: "streams-trigger@1.0.0" + config: + feedIds: +%s + +consensus: + - id: "offchain_reporting@1.0.0" + ref: "evm_median" + inputs: + observations: + - "$(trigger.outputs)" + config: + report_id: "0001" + aggregation_method: "data_feeds" + aggregation_config: + feeds: +%s + encoder: "EVM" + encoder_config: + abi: "(bytes32 FeedID, uint224 Price, uint32 Timestamp)[] Reports" + +targets: + - id: "write_geth-testnet@1.0.0" + inputs: + signed_report: "$(evm_median.outputs)" + config: + address: "%s" + params: ["$(report)"] + abi: "receive(report bytes)" + deltaStage: %s + schedule: %s +` + +func addWorkflowJob(t *testing.T, app *cltest.TestApplication, + workflowName string, + workflowOwner string, + feedIDs []string, + consumerAddr common.Address, + deltaStage string, + schedule string) { + triggerFeedIDs := "" + for _, feedID := range feedIDs { + triggerFeedIDs += fmt.Sprintf(" - \"%s\"\n", feedID) + } + + aggregationFeeds := "" + for _, feedID := range feedIDs { + aggregationFeeds += fmt.Sprintf(" \"%s\":\n deviation: \"0.001\"\n heartbeat: 3600\n", feedID) + } + + workflowJobSpec := testspecs.GenerateWorkflowJobSpec(t, fmt.Sprintf(hardcodedWorkflow, workflowName, workflowOwner, triggerFeedIDs, aggregationFeeds, + consumerAddr.String(), deltaStage, schedule)) + job := workflowJobSpec.Job() + + err := app.AddJobV2(testutils.Context(t), &job) + require.NoError(t, err) +} diff --git a/core/capabilities/remote/target/endtoend_test.go b/core/capabilities/remote/target/endtoend_test.go index c01b8d99a4..9bbb53d4f6 100644 --- a/core/capabilities/remote/target/endtoend_test.go +++ b/core/capabilities/remote/target/endtoend_test.go @@ -371,6 +371,26 @@ type nodeDispatcher struct { broker broker } +func (t *nodeDispatcher) Name() string { + return "nodeDispatcher" +} + +func (t *nodeDispatcher) Start(ctx context.Context) error { + return nil +} + +func (t *nodeDispatcher) Close() error { + return nil +} + +func (t *nodeDispatcher) Ready() error { + return nil +} + +func (t *nodeDispatcher) HealthReport() map[string]error { + return nil +} + func (t *nodeDispatcher) Send(peerID p2ptypes.PeerID, msgBody *remotetypes.MessageBody) error { msgBody.Version = 1 msgBody.Sender = t.callerPeerID[:] diff --git a/core/capabilities/remote/target/request/client_request_test.go b/core/capabilities/remote/target/request/client_request_test.go index c20c24a550..07f43dbc71 100644 --- a/core/capabilities/remote/target/request/client_request_test.go +++ b/core/capabilities/remote/target/request/client_request_test.go @@ -311,6 +311,26 @@ type clientRequestTestDispatcher struct { msgs chan *types.MessageBody } +func (t *clientRequestTestDispatcher) Name() string { + return "clientRequestTestDispatcher" +} + +func (t *clientRequestTestDispatcher) Start(ctx context.Context) error { + return nil +} + +func (t *clientRequestTestDispatcher) Close() error { + return nil +} + +func (t *clientRequestTestDispatcher) Ready() error { + return nil +} + +func (t *clientRequestTestDispatcher) HealthReport() map[string]error { + return nil +} + func (t *clientRequestTestDispatcher) SetReceiver(capabilityId string, donId uint32, receiver types.Receiver) error { return nil } diff --git a/core/capabilities/remote/target/request/server_request_test.go b/core/capabilities/remote/target/request/server_request_test.go index 053cba7064..a35725d6b1 100644 --- a/core/capabilities/remote/target/request/server_request_test.go +++ b/core/capabilities/remote/target/request/server_request_test.go @@ -190,6 +190,26 @@ type testDispatcher struct { msgs []*types.MessageBody } +func (t *testDispatcher) Name() string { + return "testDispatcher" +} + +func (t *testDispatcher) Start(ctx context.Context) error { + return nil +} + +func (t *testDispatcher) Close() error { + return nil +} + +func (t *testDispatcher) Ready() error { + return nil +} + +func (t *testDispatcher) HealthReport() map[string]error { + return nil +} + func (t *testDispatcher) SetReceiver(capabilityId string, donId uint32, receiver types.Receiver) error { return nil } diff --git a/core/capabilities/remote/types/mocks/dispatcher.go b/core/capabilities/remote/types/mocks/dispatcher.go index a73fa7e362..422198ffc1 100644 --- a/core/capabilities/remote/types/mocks/dispatcher.go +++ b/core/capabilities/remote/types/mocks/dispatcher.go @@ -3,9 +3,12 @@ package mocks import ( - types "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/types" + context "context" + ragep2ptypes "github.com/smartcontractkit/libocr/ragep2p/types" mock "github.com/stretchr/testify/mock" + + types "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/types" ) // Dispatcher is an autogenerated mock type for the Dispatcher type @@ -21,6 +24,188 @@ func (_m *Dispatcher) EXPECT() *Dispatcher_Expecter { return &Dispatcher_Expecter{mock: &_m.Mock} } +// Close provides a mock function with given fields: +func (_m *Dispatcher) Close() error { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for Close") + } + + var r0 error + if rf, ok := ret.Get(0).(func() error); ok { + r0 = rf() + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// Dispatcher_Close_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Close' +type Dispatcher_Close_Call struct { + *mock.Call +} + +// Close is a helper method to define mock.On call +func (_e *Dispatcher_Expecter) Close() *Dispatcher_Close_Call { + return &Dispatcher_Close_Call{Call: _e.mock.On("Close")} +} + +func (_c *Dispatcher_Close_Call) Run(run func()) *Dispatcher_Close_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *Dispatcher_Close_Call) Return(_a0 error) *Dispatcher_Close_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Dispatcher_Close_Call) RunAndReturn(run func() error) *Dispatcher_Close_Call { + _c.Call.Return(run) + return _c +} + +// HealthReport provides a mock function with given fields: +func (_m *Dispatcher) HealthReport() map[string]error { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for HealthReport") + } + + var r0 map[string]error + if rf, ok := ret.Get(0).(func() map[string]error); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(map[string]error) + } + } + + return r0 +} + +// Dispatcher_HealthReport_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'HealthReport' +type Dispatcher_HealthReport_Call struct { + *mock.Call +} + +// HealthReport is a helper method to define mock.On call +func (_e *Dispatcher_Expecter) HealthReport() *Dispatcher_HealthReport_Call { + return &Dispatcher_HealthReport_Call{Call: _e.mock.On("HealthReport")} +} + +func (_c *Dispatcher_HealthReport_Call) Run(run func()) *Dispatcher_HealthReport_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *Dispatcher_HealthReport_Call) Return(_a0 map[string]error) *Dispatcher_HealthReport_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Dispatcher_HealthReport_Call) RunAndReturn(run func() map[string]error) *Dispatcher_HealthReport_Call { + _c.Call.Return(run) + return _c +} + +// Name provides a mock function with given fields: +func (_m *Dispatcher) Name() string { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for Name") + } + + var r0 string + if rf, ok := ret.Get(0).(func() string); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(string) + } + + return r0 +} + +// Dispatcher_Name_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Name' +type Dispatcher_Name_Call struct { + *mock.Call +} + +// Name is a helper method to define mock.On call +func (_e *Dispatcher_Expecter) Name() *Dispatcher_Name_Call { + return &Dispatcher_Name_Call{Call: _e.mock.On("Name")} +} + +func (_c *Dispatcher_Name_Call) Run(run func()) *Dispatcher_Name_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *Dispatcher_Name_Call) Return(_a0 string) *Dispatcher_Name_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Dispatcher_Name_Call) RunAndReturn(run func() string) *Dispatcher_Name_Call { + _c.Call.Return(run) + return _c +} + +// Ready provides a mock function with given fields: +func (_m *Dispatcher) Ready() error { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for Ready") + } + + var r0 error + if rf, ok := ret.Get(0).(func() error); ok { + r0 = rf() + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// Dispatcher_Ready_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Ready' +type Dispatcher_Ready_Call struct { + *mock.Call +} + +// Ready is a helper method to define mock.On call +func (_e *Dispatcher_Expecter) Ready() *Dispatcher_Ready_Call { + return &Dispatcher_Ready_Call{Call: _e.mock.On("Ready")} +} + +func (_c *Dispatcher_Ready_Call) Run(run func()) *Dispatcher_Ready_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *Dispatcher_Ready_Call) Return(_a0 error) *Dispatcher_Ready_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Dispatcher_Ready_Call) RunAndReturn(run func() error) *Dispatcher_Ready_Call { + _c.Call.Return(run) + return _c +} + // RemoveReceiver provides a mock function with given fields: capabilityId, donId func (_m *Dispatcher) RemoveReceiver(capabilityId string, donId uint32) { _m.Called(capabilityId, donId) @@ -150,6 +335,52 @@ func (_c *Dispatcher_SetReceiver_Call) RunAndReturn(run func(string, uint32, typ return _c } +// Start provides a mock function with given fields: _a0 +func (_m *Dispatcher) Start(_a0 context.Context) error { + ret := _m.Called(_a0) + + if len(ret) == 0 { + panic("no return value specified for Start") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context) error); ok { + r0 = rf(_a0) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// Dispatcher_Start_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Start' +type Dispatcher_Start_Call struct { + *mock.Call +} + +// Start is a helper method to define mock.On call +// - _a0 context.Context +func (_e *Dispatcher_Expecter) Start(_a0 interface{}) *Dispatcher_Start_Call { + return &Dispatcher_Start_Call{Call: _e.mock.On("Start", _a0)} +} + +func (_c *Dispatcher_Start_Call) Run(run func(_a0 context.Context)) *Dispatcher_Start_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context)) + }) + return _c +} + +func (_c *Dispatcher_Start_Call) Return(_a0 error) *Dispatcher_Start_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *Dispatcher_Start_Call) RunAndReturn(run func(context.Context) error) *Dispatcher_Start_Call { + _c.Call.Return(run) + return _c +} + // NewDispatcher creates a new instance of Dispatcher. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. // The first argument is typically a *testing.T value. func NewDispatcher(t interface { diff --git a/core/capabilities/remote/types/types.go b/core/capabilities/remote/types/types.go index d15e2a2824..3629fc06fe 100644 --- a/core/capabilities/remote/types/types.go +++ b/core/capabilities/remote/types/types.go @@ -8,6 +8,7 @@ import ( "context" commoncap "github.com/smartcontractkit/chainlink-common/pkg/capabilities" + "github.com/smartcontractkit/chainlink-common/pkg/services" p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" ) @@ -19,6 +20,7 @@ const ( ) type Dispatcher interface { + services.Service SetReceiver(capabilityId string, donId uint32, receiver Receiver) error RemoveReceiver(capabilityId string, donId uint32) Send(peerID p2ptypes.PeerID, msgBody *MessageBody) error diff --git a/core/capabilities/targets/write_target.go b/core/capabilities/targets/write_target.go index da2de59a8a..330f15872d 100644 --- a/core/capabilities/targets/write_target.go +++ b/core/capabilities/targets/write_target.go @@ -29,6 +29,7 @@ type WriteTarget struct { cw commontypes.ChainWriter forwarderAddress string capabilities.CapabilityInfo + lggr logger.Logger bound bool @@ -132,7 +133,7 @@ func (cap *WriteTarget) Execute(ctx context.Context, request capabilities.Capabi } var transmitter common.Address if err = cap.cr.GetLatestValue(ctx, "forwarder", "getTransmitter", primitives.Unconfirmed, queryInputs, &transmitter); err != nil { - return nil, err + return nil, fmt.Errorf("failed to getTransmitter latest value: %w", err) } if transmitter != common.HexToAddress("0x0") { cap.lggr.Infow("WriteTarget report already onchain - returning without a tranmission attempt", "executionID", request.Metadata.WorkflowExecutionID) diff --git a/core/cmd/shell_local_test.go b/core/cmd/shell_local_test.go index 5fbbff4260..60545269e2 100644 --- a/core/cmd/shell_local_test.go +++ b/core/cmd/shell_local_test.go @@ -11,6 +11,7 @@ import ( commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" + "github.com/smartcontractkit/chainlink/v2/core/capabilities" "github.com/smartcontractkit/chainlink/v2/common/client" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" @@ -44,8 +45,9 @@ import ( func genTestEVMRelayers(t *testing.T, opts legacyevm.ChainRelayExtenderConfig, ks evmrelayer.CSAETHKeystore) *chainlink.CoreRelayerChainInteroperators { f := chainlink.RelayerFactory{ - Logger: opts.Logger, - LoopRegistry: plugins.NewLoopRegistry(opts.Logger, opts.AppConfig.Tracing()), + Logger: opts.Logger, + LoopRegistry: plugins.NewLoopRegistry(opts.Logger, opts.AppConfig.Tracing()), + CapabilitiesRegistry: capabilities.NewRegistry(opts.Logger), } relayers, err := chainlink.NewCoreRelayerChainInteroperators(chainlink.InitEVM(testutils.Context(t), f, chainlink.EVMFactoryConfig{ diff --git a/core/gethwrappers/keystone/generated/feeds_consumer/feeds_consumer.go b/core/gethwrappers/keystone/generated/feeds_consumer/feeds_consumer.go new file mode 100644 index 0000000000..f4d52eedb9 --- /dev/null +++ b/core/gethwrappers/keystone/generated/feeds_consumer/feeds_consumer.go @@ -0,0 +1,732 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package feeds_consumer + +import ( + "errors" + "fmt" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated" +) + +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +var KeystoneFeedsConsumerMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"UnauthorizedSender\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes10\",\"name\":\"workflowName\",\"type\":\"bytes10\"}],\"name\":\"UnauthorizedWorkflowName\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"}],\"name\":\"UnauthorizedWorkflowOwner\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"feedId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint224\",\"name\":\"price\",\"type\":\"uint224\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"name\":\"FeedReceived\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"feedId\",\"type\":\"bytes32\"}],\"name\":\"getPrice\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"rawReport\",\"type\":\"bytes\"}],\"name\":\"onReport\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_allowedSendersList\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"_allowedWorkflowOwnersList\",\"type\":\"address[]\"},{\"internalType\":\"bytes10[]\",\"name\":\"_allowedWorkflowNamesList\",\"type\":\"bytes10[]\"}],\"name\":\"setConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x608060405234801561001057600080fd5b5033806000816100675760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615610097576100978161009f565b505050610148565b336001600160a01b038216036100f75760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161005e565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6111cf806101576000396000f3fe608060405234801561001057600080fd5b50600436106100725760003560e01c80638da5cb5b116100505780638da5cb5b1461014e578063e340171114610176578063f2fde38b1461018957600080fd5b806331d98b3f1461007757806379ba509714610131578063805f21321461013b575b600080fd5b6100f3610085366004610d64565b6000908152600260209081526040918290208251808401909352547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff81168084527c010000000000000000000000000000000000000000000000000000000090910463ffffffff169290910182905291565b604080517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff909316835263ffffffff9091166020830152015b60405180910390f35b61013961019c565b005b610139610149366004610dc6565b61029e565b60005460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610128565b610139610184366004610e77565b61061d565b610139610197366004610f11565b610a5d565b60015473ffffffffffffffffffffffffffffffffffffffff163314610222576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b3360009081526004602052604090205460ff166102e9576040517f3fcc3f17000000000000000000000000000000000000000000000000000000008152336004820152602401610219565b60008061032b86868080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610a7192505050565b7fffffffffffffffffffff000000000000000000000000000000000000000000008216600090815260086020526040902054919350915060ff166103bf576040517f4b942f800000000000000000000000000000000000000000000000000000000081527fffffffffffffffffffff0000000000000000000000000000000000000000000083166004820152602401610219565b73ffffffffffffffffffffffffffffffffffffffff811660009081526006602052604090205460ff16610436576040517fbf24162300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152602401610219565b600061044484860186610ff5565b905060005b815181101561061357604051806040016040528083838151811061046f5761046f611107565b6020026020010151602001517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1681526020018383815181106104b0576104b0611107565b60200260200101516040015163ffffffff16815250600260008484815181106104db576104db611107565b602090810291909101810151518252818101929092526040016000208251929091015163ffffffff167c0100000000000000000000000000000000000000000000000000000000027bffffffffffffffffffffffffffffffffffffffffffffffffffffffff909216919091179055815182908290811061055d5761055d611107565b6020026020010151600001517f2c30f5cb3caf4239d0f994ce539d7ef24817fa550169c388e3a110f02e40197d83838151811061059c5761059c611107565b6020026020010151602001518484815181106105ba576105ba611107565b6020026020010151604001516040516106039291907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff92909216825263ffffffff16602082015260400190565b60405180910390a2600101610449565b5050505050505050565b610625610a87565b60005b60035463ffffffff821610156106c65760006004600060038463ffffffff168154811061065757610657611107565b60009182526020808320919091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169115159190911790556106bf81611136565b9050610628565b5060005b63ffffffff811686111561076e5760016004600089898563ffffffff168181106106f6576106f6611107565b905060200201602081019061070b9190610f11565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001691151591909117905561076781611136565b90506106ca565b5061077b60038787610bff565b5060005b60055463ffffffff8216101561081d5760006006600060058463ffffffff16815481106107ae576107ae611107565b60009182526020808320919091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001691151591909117905561081681611136565b905061077f565b5060005b63ffffffff81168411156108c55760016006600087878563ffffffff1681811061084d5761084d611107565b90506020020160208101906108629190610f11565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169115159190911790556108be81611136565b9050610821565b506108d260058585610bff565b5060005b60075463ffffffff821610156109935760006008600060078463ffffffff168154811061090557610905611107565b600091825260208083206003808404909101549206600a026101000a90910460b01b7fffffffffffffffffffff00000000000000000000000000000000000000000000168352820192909252604001902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001691151591909117905561098c81611136565b90506108d6565b5060005b63ffffffff8116821115610a475760016008600085858563ffffffff168181106109c3576109c3611107565b90506020020160208101906109d89190611180565b7fffffffffffffffffffff00000000000000000000000000000000000000000000168152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055610a4081611136565b9050610997565b50610a5460078383610c87565b50505050505050565b610a65610a87565b610a6e81610b0a565b50565b6040810151604a90910151909160609190911c90565b60005473ffffffffffffffffffffffffffffffffffffffff163314610b08576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610219565b565b3373ffffffffffffffffffffffffffffffffffffffff821603610b89576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610219565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b828054828255906000526020600020908101928215610c77579160200282015b82811115610c775781547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff843516178255602090920191600190910190610c1f565b50610c83929150610d4f565b5090565b82805482825590600052602060002090600201600390048101928215610c775791602002820160005b83821115610d1057833575ffffffffffffffffffffffffffffffffffffffffffff191683826101000a81548169ffffffffffffffffffff021916908360b01c02179055509260200192600a01602081600901049283019260010302610cb0565b8015610d465782816101000a81549069ffffffffffffffffffff0219169055600a01602081600901049283019260010302610d10565b5050610c839291505b5b80821115610c835760008155600101610d50565b600060208284031215610d7657600080fd5b5035919050565b60008083601f840112610d8f57600080fd5b50813567ffffffffffffffff811115610da757600080fd5b602083019150836020828501011115610dbf57600080fd5b9250929050565b60008060008060408587031215610ddc57600080fd5b843567ffffffffffffffff80821115610df457600080fd5b610e0088838901610d7d565b90965094506020870135915080821115610e1957600080fd5b50610e2687828801610d7d565b95989497509550505050565b60008083601f840112610e4457600080fd5b50813567ffffffffffffffff811115610e5c57600080fd5b6020830191508360208260051b8501011115610dbf57600080fd5b60008060008060008060608789031215610e9057600080fd5b863567ffffffffffffffff80821115610ea857600080fd5b610eb48a838b01610e32565b90985096506020890135915080821115610ecd57600080fd5b610ed98a838b01610e32565b90965094506040890135915080821115610ef257600080fd5b50610eff89828a01610e32565b979a9699509497509295939492505050565b600060208284031215610f2357600080fd5b813573ffffffffffffffffffffffffffffffffffffffff81168114610f4757600080fd5b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040516060810167ffffffffffffffff81118282101715610fa057610fa0610f4e565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715610fed57610fed610f4e565b604052919050565b6000602080838503121561100857600080fd5b823567ffffffffffffffff8082111561102057600080fd5b818501915085601f83011261103457600080fd5b81358181111561104657611046610f4e565b611054848260051b01610fa6565b8181528481019250606091820284018501918883111561107357600080fd5b938501935b828510156110fb5780858a0312156110905760008081fd5b611098610f7d565b85358152868601357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811681146110cb5760008081fd5b8188015260408681013563ffffffff811681146110e85760008081fd5b9082015284529384019392850192611078565b50979650505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600063ffffffff808316818103611176577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6001019392505050565b60006020828403121561119257600080fd5b81357fffffffffffffffffffff0000000000000000000000000000000000000000000081168114610f4757600080fdfea164736f6c6343000818000a", +} + +var KeystoneFeedsConsumerABI = KeystoneFeedsConsumerMetaData.ABI + +var KeystoneFeedsConsumerBin = KeystoneFeedsConsumerMetaData.Bin + +func DeployKeystoneFeedsConsumer(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *KeystoneFeedsConsumer, error) { + parsed, err := KeystoneFeedsConsumerMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(KeystoneFeedsConsumerBin), backend) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &KeystoneFeedsConsumer{address: address, abi: *parsed, KeystoneFeedsConsumerCaller: KeystoneFeedsConsumerCaller{contract: contract}, KeystoneFeedsConsumerTransactor: KeystoneFeedsConsumerTransactor{contract: contract}, KeystoneFeedsConsumerFilterer: KeystoneFeedsConsumerFilterer{contract: contract}}, nil +} + +type KeystoneFeedsConsumer struct { + address common.Address + abi abi.ABI + KeystoneFeedsConsumerCaller + KeystoneFeedsConsumerTransactor + KeystoneFeedsConsumerFilterer +} + +type KeystoneFeedsConsumerCaller struct { + contract *bind.BoundContract +} + +type KeystoneFeedsConsumerTransactor struct { + contract *bind.BoundContract +} + +type KeystoneFeedsConsumerFilterer struct { + contract *bind.BoundContract +} + +type KeystoneFeedsConsumerSession struct { + Contract *KeystoneFeedsConsumer + CallOpts bind.CallOpts + TransactOpts bind.TransactOpts +} + +type KeystoneFeedsConsumerCallerSession struct { + Contract *KeystoneFeedsConsumerCaller + CallOpts bind.CallOpts +} + +type KeystoneFeedsConsumerTransactorSession struct { + Contract *KeystoneFeedsConsumerTransactor + TransactOpts bind.TransactOpts +} + +type KeystoneFeedsConsumerRaw struct { + Contract *KeystoneFeedsConsumer +} + +type KeystoneFeedsConsumerCallerRaw struct { + Contract *KeystoneFeedsConsumerCaller +} + +type KeystoneFeedsConsumerTransactorRaw struct { + Contract *KeystoneFeedsConsumerTransactor +} + +func NewKeystoneFeedsConsumer(address common.Address, backend bind.ContractBackend) (*KeystoneFeedsConsumer, error) { + abi, err := abi.JSON(strings.NewReader(KeystoneFeedsConsumerABI)) + if err != nil { + return nil, err + } + contract, err := bindKeystoneFeedsConsumer(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &KeystoneFeedsConsumer{address: address, abi: abi, KeystoneFeedsConsumerCaller: KeystoneFeedsConsumerCaller{contract: contract}, KeystoneFeedsConsumerTransactor: KeystoneFeedsConsumerTransactor{contract: contract}, KeystoneFeedsConsumerFilterer: KeystoneFeedsConsumerFilterer{contract: contract}}, nil +} + +func NewKeystoneFeedsConsumerCaller(address common.Address, caller bind.ContractCaller) (*KeystoneFeedsConsumerCaller, error) { + contract, err := bindKeystoneFeedsConsumer(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &KeystoneFeedsConsumerCaller{contract: contract}, nil +} + +func NewKeystoneFeedsConsumerTransactor(address common.Address, transactor bind.ContractTransactor) (*KeystoneFeedsConsumerTransactor, error) { + contract, err := bindKeystoneFeedsConsumer(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &KeystoneFeedsConsumerTransactor{contract: contract}, nil +} + +func NewKeystoneFeedsConsumerFilterer(address common.Address, filterer bind.ContractFilterer) (*KeystoneFeedsConsumerFilterer, error) { + contract, err := bindKeystoneFeedsConsumer(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &KeystoneFeedsConsumerFilterer{contract: contract}, nil +} + +func bindKeystoneFeedsConsumer(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := KeystoneFeedsConsumerMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _KeystoneFeedsConsumer.Contract.KeystoneFeedsConsumerCaller.contract.Call(opts, result, method, params...) +} + +func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _KeystoneFeedsConsumer.Contract.KeystoneFeedsConsumerTransactor.contract.Transfer(opts) +} + +func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _KeystoneFeedsConsumer.Contract.KeystoneFeedsConsumerTransactor.contract.Transact(opts, method, params...) +} + +func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _KeystoneFeedsConsumer.Contract.contract.Call(opts, result, method, params...) +} + +func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _KeystoneFeedsConsumer.Contract.contract.Transfer(opts) +} + +func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _KeystoneFeedsConsumer.Contract.contract.Transact(opts, method, params...) +} + +func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerCaller) GetPrice(opts *bind.CallOpts, feedId [32]byte) (*big.Int, uint32, error) { + var out []interface{} + err := _KeystoneFeedsConsumer.contract.Call(opts, &out, "getPrice", feedId) + + if err != nil { + return *new(*big.Int), *new(uint32), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + out1 := *abi.ConvertType(out[1], new(uint32)).(*uint32) + + return out0, out1, err + +} + +func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerSession) GetPrice(feedId [32]byte) (*big.Int, uint32, error) { + return _KeystoneFeedsConsumer.Contract.GetPrice(&_KeystoneFeedsConsumer.CallOpts, feedId) +} + +func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerCallerSession) GetPrice(feedId [32]byte) (*big.Int, uint32, error) { + return _KeystoneFeedsConsumer.Contract.GetPrice(&_KeystoneFeedsConsumer.CallOpts, feedId) +} + +func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerCaller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _KeystoneFeedsConsumer.contract.Call(opts, &out, "owner") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerSession) Owner() (common.Address, error) { + return _KeystoneFeedsConsumer.Contract.Owner(&_KeystoneFeedsConsumer.CallOpts) +} + +func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerCallerSession) Owner() (common.Address, error) { + return _KeystoneFeedsConsumer.Contract.Owner(&_KeystoneFeedsConsumer.CallOpts) +} + +func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _KeystoneFeedsConsumer.contract.Transact(opts, "acceptOwnership") +} + +func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerSession) AcceptOwnership() (*types.Transaction, error) { + return _KeystoneFeedsConsumer.Contract.AcceptOwnership(&_KeystoneFeedsConsumer.TransactOpts) +} + +func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerTransactorSession) AcceptOwnership() (*types.Transaction, error) { + return _KeystoneFeedsConsumer.Contract.AcceptOwnership(&_KeystoneFeedsConsumer.TransactOpts) +} + +func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerTransactor) OnReport(opts *bind.TransactOpts, metadata []byte, rawReport []byte) (*types.Transaction, error) { + return _KeystoneFeedsConsumer.contract.Transact(opts, "onReport", metadata, rawReport) +} + +func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerSession) OnReport(metadata []byte, rawReport []byte) (*types.Transaction, error) { + return _KeystoneFeedsConsumer.Contract.OnReport(&_KeystoneFeedsConsumer.TransactOpts, metadata, rawReport) +} + +func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerTransactorSession) OnReport(metadata []byte, rawReport []byte) (*types.Transaction, error) { + return _KeystoneFeedsConsumer.Contract.OnReport(&_KeystoneFeedsConsumer.TransactOpts, metadata, rawReport) +} + +func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerTransactor) SetConfig(opts *bind.TransactOpts, _allowedSendersList []common.Address, _allowedWorkflowOwnersList []common.Address, _allowedWorkflowNamesList [][10]byte) (*types.Transaction, error) { + return _KeystoneFeedsConsumer.contract.Transact(opts, "setConfig", _allowedSendersList, _allowedWorkflowOwnersList, _allowedWorkflowNamesList) +} + +func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerSession) SetConfig(_allowedSendersList []common.Address, _allowedWorkflowOwnersList []common.Address, _allowedWorkflowNamesList [][10]byte) (*types.Transaction, error) { + return _KeystoneFeedsConsumer.Contract.SetConfig(&_KeystoneFeedsConsumer.TransactOpts, _allowedSendersList, _allowedWorkflowOwnersList, _allowedWorkflowNamesList) +} + +func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerTransactorSession) SetConfig(_allowedSendersList []common.Address, _allowedWorkflowOwnersList []common.Address, _allowedWorkflowNamesList [][10]byte) (*types.Transaction, error) { + return _KeystoneFeedsConsumer.Contract.SetConfig(&_KeystoneFeedsConsumer.TransactOpts, _allowedSendersList, _allowedWorkflowOwnersList, _allowedWorkflowNamesList) +} + +func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { + return _KeystoneFeedsConsumer.contract.Transact(opts, "transferOwnership", to) +} + +func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _KeystoneFeedsConsumer.Contract.TransferOwnership(&_KeystoneFeedsConsumer.TransactOpts, to) +} + +func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _KeystoneFeedsConsumer.Contract.TransferOwnership(&_KeystoneFeedsConsumer.TransactOpts, to) +} + +type KeystoneFeedsConsumerFeedReceivedIterator struct { + Event *KeystoneFeedsConsumerFeedReceived + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *KeystoneFeedsConsumerFeedReceivedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(KeystoneFeedsConsumerFeedReceived) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(KeystoneFeedsConsumerFeedReceived) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *KeystoneFeedsConsumerFeedReceivedIterator) Error() error { + return it.fail +} + +func (it *KeystoneFeedsConsumerFeedReceivedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type KeystoneFeedsConsumerFeedReceived struct { + FeedId [32]byte + Price *big.Int + Timestamp uint32 + Raw types.Log +} + +func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerFilterer) FilterFeedReceived(opts *bind.FilterOpts, feedId [][32]byte) (*KeystoneFeedsConsumerFeedReceivedIterator, error) { + + var feedIdRule []interface{} + for _, feedIdItem := range feedId { + feedIdRule = append(feedIdRule, feedIdItem) + } + + logs, sub, err := _KeystoneFeedsConsumer.contract.FilterLogs(opts, "FeedReceived", feedIdRule) + if err != nil { + return nil, err + } + return &KeystoneFeedsConsumerFeedReceivedIterator{contract: _KeystoneFeedsConsumer.contract, event: "FeedReceived", logs: logs, sub: sub}, nil +} + +func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerFilterer) WatchFeedReceived(opts *bind.WatchOpts, sink chan<- *KeystoneFeedsConsumerFeedReceived, feedId [][32]byte) (event.Subscription, error) { + + var feedIdRule []interface{} + for _, feedIdItem := range feedId { + feedIdRule = append(feedIdRule, feedIdItem) + } + + logs, sub, err := _KeystoneFeedsConsumer.contract.WatchLogs(opts, "FeedReceived", feedIdRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(KeystoneFeedsConsumerFeedReceived) + if err := _KeystoneFeedsConsumer.contract.UnpackLog(event, "FeedReceived", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerFilterer) ParseFeedReceived(log types.Log) (*KeystoneFeedsConsumerFeedReceived, error) { + event := new(KeystoneFeedsConsumerFeedReceived) + if err := _KeystoneFeedsConsumer.contract.UnpackLog(event, "FeedReceived", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type KeystoneFeedsConsumerOwnershipTransferRequestedIterator struct { + Event *KeystoneFeedsConsumerOwnershipTransferRequested + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *KeystoneFeedsConsumerOwnershipTransferRequestedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(KeystoneFeedsConsumerOwnershipTransferRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(KeystoneFeedsConsumerOwnershipTransferRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *KeystoneFeedsConsumerOwnershipTransferRequestedIterator) Error() error { + return it.fail +} + +func (it *KeystoneFeedsConsumerOwnershipTransferRequestedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type KeystoneFeedsConsumerOwnershipTransferRequested struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*KeystoneFeedsConsumerOwnershipTransferRequestedIterator, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _KeystoneFeedsConsumer.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + if err != nil { + return nil, err + } + return &KeystoneFeedsConsumerOwnershipTransferRequestedIterator{contract: _KeystoneFeedsConsumer.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil +} + +func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *KeystoneFeedsConsumerOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _KeystoneFeedsConsumer.contract.WatchLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(KeystoneFeedsConsumerOwnershipTransferRequested) + if err := _KeystoneFeedsConsumer.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerFilterer) ParseOwnershipTransferRequested(log types.Log) (*KeystoneFeedsConsumerOwnershipTransferRequested, error) { + event := new(KeystoneFeedsConsumerOwnershipTransferRequested) + if err := _KeystoneFeedsConsumer.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type KeystoneFeedsConsumerOwnershipTransferredIterator struct { + Event *KeystoneFeedsConsumerOwnershipTransferred + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *KeystoneFeedsConsumerOwnershipTransferredIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(KeystoneFeedsConsumerOwnershipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(KeystoneFeedsConsumerOwnershipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *KeystoneFeedsConsumerOwnershipTransferredIterator) Error() error { + return it.fail +} + +func (it *KeystoneFeedsConsumerOwnershipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type KeystoneFeedsConsumerOwnershipTransferred struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*KeystoneFeedsConsumerOwnershipTransferredIterator, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _KeystoneFeedsConsumer.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) + if err != nil { + return nil, err + } + return &KeystoneFeedsConsumerOwnershipTransferredIterator{contract: _KeystoneFeedsConsumer.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil +} + +func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *KeystoneFeedsConsumerOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _KeystoneFeedsConsumer.contract.WatchLogs(opts, "OwnershipTransferred", fromRule, toRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(KeystoneFeedsConsumerOwnershipTransferred) + if err := _KeystoneFeedsConsumer.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerFilterer) ParseOwnershipTransferred(log types.Log) (*KeystoneFeedsConsumerOwnershipTransferred, error) { + event := new(KeystoneFeedsConsumerOwnershipTransferred) + if err := _KeystoneFeedsConsumer.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +func (_KeystoneFeedsConsumer *KeystoneFeedsConsumer) ParseLog(log types.Log) (generated.AbigenLog, error) { + switch log.Topics[0] { + case _KeystoneFeedsConsumer.abi.Events["FeedReceived"].ID: + return _KeystoneFeedsConsumer.ParseFeedReceived(log) + case _KeystoneFeedsConsumer.abi.Events["OwnershipTransferRequested"].ID: + return _KeystoneFeedsConsumer.ParseOwnershipTransferRequested(log) + case _KeystoneFeedsConsumer.abi.Events["OwnershipTransferred"].ID: + return _KeystoneFeedsConsumer.ParseOwnershipTransferred(log) + + default: + return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) + } +} + +func (KeystoneFeedsConsumerFeedReceived) Topic() common.Hash { + return common.HexToHash("0x2c30f5cb3caf4239d0f994ce539d7ef24817fa550169c388e3a110f02e40197d") +} + +func (KeystoneFeedsConsumerOwnershipTransferRequested) Topic() common.Hash { + return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") +} + +func (KeystoneFeedsConsumerOwnershipTransferred) Topic() common.Hash { + return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") +} + +func (_KeystoneFeedsConsumer *KeystoneFeedsConsumer) Address() common.Address { + return _KeystoneFeedsConsumer.address +} + +type KeystoneFeedsConsumerInterface interface { + GetPrice(opts *bind.CallOpts, feedId [32]byte) (*big.Int, uint32, error) + + Owner(opts *bind.CallOpts) (common.Address, error) + + AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) + + OnReport(opts *bind.TransactOpts, metadata []byte, rawReport []byte) (*types.Transaction, error) + + SetConfig(opts *bind.TransactOpts, _allowedSendersList []common.Address, _allowedWorkflowOwnersList []common.Address, _allowedWorkflowNamesList [][10]byte) (*types.Transaction, error) + + TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) + + FilterFeedReceived(opts *bind.FilterOpts, feedId [][32]byte) (*KeystoneFeedsConsumerFeedReceivedIterator, error) + + WatchFeedReceived(opts *bind.WatchOpts, sink chan<- *KeystoneFeedsConsumerFeedReceived, feedId [][32]byte) (event.Subscription, error) + + ParseFeedReceived(log types.Log) (*KeystoneFeedsConsumerFeedReceived, error) + + FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*KeystoneFeedsConsumerOwnershipTransferRequestedIterator, error) + + WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *KeystoneFeedsConsumerOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferRequested(log types.Log) (*KeystoneFeedsConsumerOwnershipTransferRequested, error) + + FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*KeystoneFeedsConsumerOwnershipTransferredIterator, error) + + WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *KeystoneFeedsConsumerOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferred(log types.Log) (*KeystoneFeedsConsumerOwnershipTransferred, error) + + ParseLog(log types.Log) (generated.AbigenLog, error) + + Address() common.Address +} diff --git a/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt index 4051f95020..53b8a64daf 100644 --- a/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -1,4 +1,5 @@ GETH_VERSION: 1.13.8 capabilities_registry: ../../../contracts/solc/v0.8.24/CapabilitiesRegistry/CapabilitiesRegistry.abi ../../../contracts/solc/v0.8.24/CapabilitiesRegistry/CapabilitiesRegistry.bin 3a082f0307411f41c30db26e61d59adcd5b003141a5aa8fe79d7779619028e26 +feeds_consumer: ../../../contracts/solc/v0.8.24/KeystoneFeedsConsumer/KeystoneFeedsConsumer.abi ../../../contracts/solc/v0.8.24/KeystoneFeedsConsumer/KeystoneFeedsConsumer.bin f098e25df6afc100425fcad7f5107aec0844cc98315117e49da139a179d0eead forwarder: ../../../contracts/solc/v0.8.24/KeystoneForwarder/KeystoneForwarder.abi ../../../contracts/solc/v0.8.24/KeystoneForwarder/KeystoneForwarder.bin dc98a86a3775ead987b79d5b6079ee0e26f31c0626032bdd6508f986e2423227 ocr3_capability: ../../../contracts/solc/v0.8.24/OCR3Capability/OCR3Capability.abi ../../../contracts/solc/v0.8.24/OCR3Capability/OCR3Capability.bin 8bf0f53f222efce7143dea6134552eb26ea1eef845407b4475a0d79b7d7ba9f8 diff --git a/core/gethwrappers/keystone/go_generate.go b/core/gethwrappers/keystone/go_generate.go index 36b27852ad..79f49264b3 100644 --- a/core/gethwrappers/keystone/go_generate.go +++ b/core/gethwrappers/keystone/go_generate.go @@ -7,3 +7,4 @@ package gethwrappers //go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/KeystoneForwarder/KeystoneForwarder.abi ../../../contracts/solc/v0.8.24/KeystoneForwarder/KeystoneForwarder.bin KeystoneForwarder forwarder //go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/OCR3Capability/OCR3Capability.abi ../../../contracts/solc/v0.8.24/OCR3Capability/OCR3Capability.bin OCR3Capability ocr3_capability //go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/CapabilitiesRegistry/CapabilitiesRegistry.abi ../../../contracts/solc/v0.8.24/CapabilitiesRegistry/CapabilitiesRegistry.bin CapabilitiesRegistry capabilities_registry +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/KeystoneFeedsConsumer/KeystoneFeedsConsumer.abi ../../../contracts/solc/v0.8.24/KeystoneFeedsConsumer/KeystoneFeedsConsumer.bin KeystoneFeedsConsumer feeds_consumer diff --git a/core/internal/cltest/cltest.go b/core/internal/cltest/cltest.go index 508dde86a0..12491300bf 100644 --- a/core/internal/cltest/cltest.go +++ b/core/internal/cltest/cltest.go @@ -37,6 +37,10 @@ import ( ocrtypes "github.com/smartcontractkit/libocr/offchainreporting/types" + "github.com/smartcontractkit/chainlink/v2/core/capabilities" + remotetypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/types" + p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" + "github.com/smartcontractkit/chainlink-common/pkg/loop" "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" @@ -316,6 +320,31 @@ func NewApplicationWithConfig(t testing.TB, cfg chainlink.GeneralConfig, flagsAn auditLogger = audit.NoopLogger } + var capabilitiesRegistry *capabilities.Registry + capabilitiesRegistry = capabilities.NewRegistry(lggr) + for _, dep := range flagsAndDeps { + registry, _ := dep.(*capabilities.Registry) + if registry != nil { + capabilitiesRegistry = registry + } + } + + var dispatcher remotetypes.Dispatcher + for _, dep := range flagsAndDeps { + dispatcher, _ = dep.(remotetypes.Dispatcher) + if dispatcher != nil { + break + } + } + + var peerWrapper p2ptypes.PeerWrapper + for _, dep := range flagsAndDeps { + peerWrapper, _ = dep.(p2ptypes.PeerWrapper) + if peerWrapper != nil { + break + } + } + url := cfg.Database().URL() db, err := pg.NewConnection(url.String(), cfg.Database().Dialect(), cfg.Database()) require.NoError(t, err) @@ -354,10 +383,11 @@ func NewApplicationWithConfig(t testing.TB, cfg chainlink.GeneralConfig, flagsAn }) relayerFactory := chainlink.RelayerFactory{ - Logger: lggr, - LoopRegistry: loopRegistry, - GRPCOpts: loop.GRPCOpts{}, - MercuryPool: mercuryPool, + Logger: lggr, + LoopRegistry: loopRegistry, + GRPCOpts: loop.GRPCOpts{}, + MercuryPool: mercuryPool, + CapabilitiesRegistry: capabilitiesRegistry, } evmOpts := chainlink.EVMFactoryConfig{ @@ -409,6 +439,7 @@ func NewApplicationWithConfig(t testing.TB, cfg chainlink.GeneralConfig, flagsAn } initOps = append(initOps, chainlink.InitStarknet(testCtx, relayerFactory, starkCfg)) } + relayChainInterops, err := chainlink.NewCoreRelayerChainInteroperators(initOps...) if err != nil { t.Fatal(err) @@ -429,7 +460,11 @@ func NewApplicationWithConfig(t testing.TB, cfg chainlink.GeneralConfig, flagsAn SecretGenerator: MockSecretGenerator{}, LoopRegistry: plugins.NewLoopRegistry(lggr, nil), MercuryPool: mercuryPool, + CapabilitiesRegistry: capabilitiesRegistry, + CapabilitiesDispatcher: dispatcher, + CapabilitiesPeerWrapper: peerWrapper, }) + require.NoError(t, err) app := appInstance.(*chainlink.ChainlinkApplication) ta := &TestApplication{ diff --git a/core/services/chainlink/application.go b/core/services/chainlink/application.go index 2b76baf7b5..cabaacbb27 100644 --- a/core/services/chainlink/application.go +++ b/core/services/chainlink/application.go @@ -31,6 +31,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/bridges" "github.com/smartcontractkit/chainlink/v2/core/build" "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote" + remotetypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" evmutils "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" @@ -179,6 +180,8 @@ type ApplicationOpts struct { GRPCOpts loop.GRPCOpts MercuryPool wsrpc.Pool CapabilitiesRegistry *capabilities.Registry + CapabilitiesDispatcher remotetypes.Dispatcher + CapabilitiesPeerWrapper p2ptypes.PeerWrapper } // NewApplication initializes a new store if one is not already @@ -198,20 +201,29 @@ func NewApplication(opts ApplicationOpts) (Application, error) { restrictedHTTPClient := opts.RestrictedHTTPClient unrestrictedHTTPClient := opts.UnrestrictedHTTPClient - if opts.CapabilitiesRegistry == nil { // for tests only, in prod Registry is always set at this point + if opts.CapabilitiesRegistry == nil { + // for tests only, in prod Registry should always be set at this point opts.CapabilitiesRegistry = capabilities.NewRegistry(globalLogger) } var externalPeerWrapper p2ptypes.PeerWrapper if cfg.Capabilities().Peering().Enabled() { - externalPeer := externalp2p.NewExternalPeerWrapper(keyStore.P2P(), cfg.Capabilities().Peering(), opts.DS, globalLogger) - signer := externalPeer - externalPeerWrapper = externalPeer + var dispatcher remotetypes.Dispatcher + if opts.CapabilitiesDispatcher == nil { + externalPeer := externalp2p.NewExternalPeerWrapper(keyStore.P2P(), cfg.Capabilities().Peering(), opts.DS, globalLogger) + signer := externalPeer + externalPeerWrapper = externalPeer + remoteDispatcher := remote.NewDispatcher(externalPeerWrapper, signer, opts.CapabilitiesRegistry, globalLogger) + srvcs = append(srvcs, remoteDispatcher) + + dispatcher = remoteDispatcher + } else { + dispatcher = opts.CapabilitiesDispatcher + externalPeerWrapper = opts.CapabilitiesPeerWrapper + } srvcs = append(srvcs, externalPeerWrapper) - dispatcher := remote.NewDispatcher(externalPeerWrapper, signer, opts.CapabilitiesRegistry, globalLogger) - rid := cfg.Capabilities().ExternalRegistry().RelayID() registryAddress := cfg.Capabilities().ExternalRegistry().Address() relayer, err := relayerChainInterops.Get(rid) diff --git a/core/services/chainlink/relayer_chain_interoperators_test.go b/core/services/chainlink/relayer_chain_interoperators_test.go index aaf458c76c..5aaf6e16dd 100644 --- a/core/services/chainlink/relayer_chain_interoperators_test.go +++ b/core/services/chainlink/relayer_chain_interoperators_test.go @@ -13,6 +13,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/loop" "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" + "github.com/smartcontractkit/chainlink/v2/core/capabilities" coscfg "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/config" solcfg "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" @@ -174,9 +175,10 @@ func TestCoreRelayerChainInteroperators(t *testing.T) { lggr := logger.TestLogger(t) factory := chainlink.RelayerFactory{ - Logger: lggr, - LoopRegistry: plugins.NewLoopRegistry(lggr, nil), - GRPCOpts: loop.GRPCOpts{}, + Logger: lggr, + LoopRegistry: plugins.NewLoopRegistry(lggr, nil), + GRPCOpts: loop.GRPCOpts{}, + CapabilitiesRegistry: capabilities.NewRegistry(lggr), } testctx := testutils.Context(t) diff --git a/core/services/chainlink/relayer_factory.go b/core/services/chainlink/relayer_factory.go index ae222f56c6..849964f9be 100644 --- a/core/services/chainlink/relayer_factory.go +++ b/core/services/chainlink/relayer_factory.go @@ -11,6 +11,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/loop/adapters/relay" "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink-common/pkg/types" + coretypes "github.com/smartcontractkit/chainlink-common/pkg/types/core" "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos" coscfg "github.com/smartcontractkit/chainlink-cosmos/pkg/cosmos/config" "github.com/smartcontractkit/chainlink-solana/pkg/solana" @@ -18,8 +19,6 @@ import ( pkgstarknet "github.com/smartcontractkit/chainlink-starknet/relayer/pkg/chainlink" starkchain "github.com/smartcontractkit/chainlink-starknet/relayer/pkg/chainlink/chain" "github.com/smartcontractkit/chainlink-starknet/relayer/pkg/chainlink/config" - - "github.com/smartcontractkit/chainlink/v2/core/capabilities" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" coreconfig "github.com/smartcontractkit/chainlink/v2/core/config" "github.com/smartcontractkit/chainlink/v2/core/config/env" @@ -37,7 +36,7 @@ type RelayerFactory struct { *plugins.LoopRegistry loop.GRPCOpts MercuryPool wsrpc.Pool - CapabilitiesRegistry *capabilities.Registry + CapabilitiesRegistry coretypes.CapabilitiesRegistry } type DummyFactoryConfig struct { From 683a12e85e91628f240fe24f32b982b53ac30bd9 Mon Sep 17 00:00:00 2001 From: Morgan Kuphal <87319522+KuphJr@users.noreply.github.com> Date: Sun, 28 Jul 2024 09:01:29 -0500 Subject: [PATCH 012/115] FUN-1527 Add updateFromPrevious method to Functions ToS (#13795) * Add updateFromPrevious method to Functions ToS contract * Update test * Update gethwrappers * Added test * prettier * Address feedback * Added tag to changeset * Addressed feedback on tests * Updated gas snapshot * Add missing deployment arg to ToS in core tests * New approach which enables batching * Add require * prettier, gas snapshot & wrappers * update snapshot * addressed feedback * prettier --------- Co-authored-by: app-token-issuer-infra-releng[bot] <120227048+app-token-issuer-infra-releng[bot]@users.noreply.github.com> --- .changeset/kind-garlics-smash.md | 5 + contracts/.changeset/empty-ants-suffer.md | 5 + .../gas-snapshots/functions.gas-snapshot | 234 +++++++++--------- .../accessControl/TermsOfServiceAllowList.sol | 24 +- .../interfaces/ITermsOfServiceAllowList.sol | 4 + .../FunctionsTermsOfServiceAllowList.t.sol | 46 +++- .../src/v0.8/functions/tests/v1_X/Setup.t.sol | 4 +- .../functions_allow_list.go | 22 +- ...rapper-dependency-versions-do-not-edit.txt | 2 +- .../v1/internal/testutils.go | 4 +- 10 files changed, 224 insertions(+), 126 deletions(-) create mode 100644 .changeset/kind-garlics-smash.md create mode 100644 contracts/.changeset/empty-ants-suffer.md diff --git a/.changeset/kind-garlics-smash.md b/.changeset/kind-garlics-smash.md new file mode 100644 index 0000000000..3d9ededa23 --- /dev/null +++ b/.changeset/kind-garlics-smash.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +Updated Functions ToS contract wrappers #internal diff --git a/contracts/.changeset/empty-ants-suffer.md b/contracts/.changeset/empty-ants-suffer.md new file mode 100644 index 0000000000..8270da10f1 --- /dev/null +++ b/contracts/.changeset/empty-ants-suffer.md @@ -0,0 +1,5 @@ +--- +'@chainlink/contracts': patch +--- + +Added updateFromPrevious method to Functions ToS contract diff --git a/contracts/gas-snapshots/functions.gas-snapshot b/contracts/gas-snapshots/functions.gas-snapshot index d7945f225e..44d557ebcf 100644 --- a/contracts/gas-snapshots/functions.gas-snapshot +++ b/contracts/gas-snapshots/functions.gas-snapshot @@ -1,21 +1,21 @@ -ChainSpecificUtil__getL1FeeUpperLimit_Arbitrum:test__getL1FeeUpperLimit_SuccessWhenArbitrumGoerli() (gas: 15903239) -ChainSpecificUtil__getL1FeeUpperLimit_Arbitrum:test__getL1FeeUpperLimit_SuccessWhenArbitrumMainnet() (gas: 15903196) -ChainSpecificUtil__getL1FeeUpperLimit_Arbitrum:test__getL1FeeUpperLimit_SuccessWhenArbitrumSepolia() (gas: 15903265) -ChainSpecificUtil__getL1FeeUpperLimit_Base:test__getL1FeeUpperLimit_SuccessWhenBaseGoerli() (gas: 15903033) -ChainSpecificUtil__getL1FeeUpperLimit_Base:test__getL1FeeUpperLimit_SuccessWhenBaseMainnet() (gas: 15903011) -ChainSpecificUtil__getL1FeeUpperLimit_Base:test__getL1FeeUpperLimit_SuccessWhenBaseSepolia() (gas: 15903060) -ChainSpecificUtil__getL1FeeUpperLimit_Optimism:test__getL1FeeUpperLimit_SuccessWhenOptimismGoerli() (gas: 15902946) -ChainSpecificUtil__getL1FeeUpperLimit_Optimism:test__getL1FeeUpperLimit_SuccessWhenOptimismMainnet() (gas: 15902968) -ChainSpecificUtil__getL1FeeUpperLimit_Optimism:test__getL1FeeUpperLimit_SuccessWhenOptimismSepolia() (gas: 15903011) +ChainSpecificUtil__getL1FeeUpperLimit_Arbitrum:test__getL1FeeUpperLimit_SuccessWhenArbitrumGoerli() (gas: 16076840) +ChainSpecificUtil__getL1FeeUpperLimit_Arbitrum:test__getL1FeeUpperLimit_SuccessWhenArbitrumMainnet() (gas: 16076819) +ChainSpecificUtil__getL1FeeUpperLimit_Arbitrum:test__getL1FeeUpperLimit_SuccessWhenArbitrumSepolia() (gas: 16076888) +ChainSpecificUtil__getL1FeeUpperLimit_Base:test__getL1FeeUpperLimit_SuccessWhenBaseGoerli() (gas: 16076608) +ChainSpecificUtil__getL1FeeUpperLimit_Base:test__getL1FeeUpperLimit_SuccessWhenBaseMainnet() (gas: 16076564) +ChainSpecificUtil__getL1FeeUpperLimit_Base:test__getL1FeeUpperLimit_SuccessWhenBaseSepolia() (gas: 16076635) +ChainSpecificUtil__getL1FeeUpperLimit_Optimism:test__getL1FeeUpperLimit_SuccessWhenOptimismGoerli() (gas: 16076521) +ChainSpecificUtil__getL1FeeUpperLimit_Optimism:test__getL1FeeUpperLimit_SuccessWhenOptimismMainnet() (gas: 16076543) +ChainSpecificUtil__getL1FeeUpperLimit_Optimism:test__getL1FeeUpperLimit_SuccessWhenOptimismSepolia() (gas: 16076586) FunctionsBilling_Constructor:test_Constructor_Success() (gas: 17982) -FunctionsBilling_DeleteCommitment:test_DeleteCommitment_RevertIfNotRouter() (gas: 13260) -FunctionsBilling_DeleteCommitment:test_DeleteCommitment_Success() (gas: 15875) +FunctionsBilling_DeleteCommitment:test_DeleteCommitment_RevertIfNotRouter() (gas: 13283) +FunctionsBilling_DeleteCommitment:test_DeleteCommitment_Success() (gas: 15853) FunctionsBilling_EstimateCost:test_EstimateCost_RevertsIfGasPriceAboveCeiling() (gas: 32450) -FunctionsBilling_EstimateCost:test_EstimateCost_Success() (gas: 90999) +FunctionsBilling_EstimateCost:test_EstimateCost_Success() (gas: 90977) FunctionsBilling_EstimateCost:test_EstimateCost_SuccessLowGasPrice() (gas: 91102) FunctionsBilling_GetAdminFeeJuels:test_GetAdminFeeJuels_Success() (gas: 18671) -FunctionsBilling_GetConfig:test_GetConfig_Success() (gas: 30727) -FunctionsBilling_GetDONFeeJuels:test_GetDONFeeJuels_Success() (gas: 41128) +FunctionsBilling_GetConfig:test_GetConfig_Success() (gas: 30750) +FunctionsBilling_GetDONFeeJuels:test_GetDONFeeJuels_Success() (gas: 41151) FunctionsBilling_GetOperationFee:test_GetOperationFeeJuels_Success() (gas: 40548) FunctionsBilling_GetWeiPerUnitLink:test_GetWeiPerUnitLink_Success() (gas: 29751) FunctionsBilling_OracleWithdraw:test_OracleWithdraw_RevertIfInsufficientBalance() (gas: 70136) @@ -23,41 +23,41 @@ FunctionsBilling_OracleWithdraw:test_OracleWithdraw_RevertWithNoBalance() (gas: FunctionsBilling_OracleWithdraw:test_OracleWithdraw_SuccessCoordinatorOwner() (gas: 129908) FunctionsBilling_OracleWithdraw:test_OracleWithdraw_SuccessTransmitterWithBalanceNoAmountGiven() (gas: 171930) FunctionsBilling_OracleWithdraw:test_OracleWithdraw_SuccessTransmitterWithBalanceValidAmountGiven() (gas: 145165) -FunctionsBilling_OracleWithdrawAll:test_OracleWithdrawAll_RevertIfNotOwner() (gas: 13297) +FunctionsBilling_OracleWithdrawAll:test_OracleWithdrawAll_RevertIfNotOwner() (gas: 13320) FunctionsBilling_OracleWithdrawAll:test_OracleWithdrawAll_SuccessPaysTransmittersWithBalance() (gas: 222357) -FunctionsBilling_UpdateConfig:test_UpdateConfig_RevertIfNotOwner() (gas: 21654) -FunctionsBilling_UpdateConfig:test_UpdateConfig_Success() (gas: 54121) +FunctionsBilling_UpdateConfig:test_UpdateConfig_RevertIfNotOwner() (gas: 21632) +FunctionsBilling_UpdateConfig:test_UpdateConfig_Success() (gas: 54099) FunctionsBilling__DisperseFeePool:test__DisperseFeePool_RevertIfNotSet() (gas: 8810) -FunctionsBilling__FulfillAndBill:test__FulfillAndBill_RevertIfInvalidCommitment() (gas: 13375) -FunctionsBilling__FulfillAndBill:test__FulfillAndBill_Success() (gas: 185953) +FunctionsBilling__FulfillAndBill:test__FulfillAndBill_RevertIfInvalidCommitment() (gas: 13353) +FunctionsBilling__FulfillAndBill:test__FulfillAndBill_Success() (gas: 185976) FunctionsBilling__StartBilling:test__FulfillAndBill_HasUniqueGlobalRequestId() (gas: 524582) FunctionsClient_Constructor:test_Constructor_Success() (gas: 10407) -FunctionsClient_HandleOracleFulfillment:test_HandleOracleFulfillment_RevertIfNotRouter() (gas: 14617) -FunctionsClient_HandleOracleFulfillment:test_HandleOracleFulfillment_Success() (gas: 22917) +FunctionsClient_HandleOracleFulfillment:test_HandleOracleFulfillment_RevertIfNotRouter() (gas: 14595) +FunctionsClient_HandleOracleFulfillment:test_HandleOracleFulfillment_Success() (gas: 22983) FunctionsClient__SendRequest:test__SendRequest_RevertIfInvalidCallbackGasLimit() (gas: 55069) FunctionsCoordinator_Constructor:test_Constructor_Success() (gas: 15085) -FunctionsCoordinator_GetDONPublicKey:test_GetDONPublicKey_RevertIfEmpty() (gas: 15378) +FunctionsCoordinator_GetDONPublicKey:test_GetDONPublicKey_RevertIfEmpty() (gas: 15356) FunctionsCoordinator_GetDONPublicKey:test_GetDONPublicKey_Success() (gas: 91691) -FunctionsCoordinator_GetThresholdPublicKey:test_GetThresholdPublicKey_RevertIfEmpty() (gas: 15356) -FunctionsCoordinator_GetThresholdPublicKey:test_GetThresholdPublicKey_Success() (gas: 515973) -FunctionsCoordinator_SetDONPublicKey:test_SetDONPublicKey_RevertNotOwner() (gas: 20365) +FunctionsCoordinator_GetThresholdPublicKey:test_GetThresholdPublicKey_RevertIfEmpty() (gas: 15334) +FunctionsCoordinator_GetThresholdPublicKey:test_GetThresholdPublicKey_Success() (gas: 515951) +FunctionsCoordinator_SetDONPublicKey:test_SetDONPublicKey_RevertNotOwner() (gas: 20409) FunctionsCoordinator_SetDONPublicKey:test_SetDONPublicKey_Success() (gas: 88970) -FunctionsCoordinator_SetThresholdPublicKey:test_SetThresholdPublicKey_RevertNotOwner() (gas: 13892) +FunctionsCoordinator_SetThresholdPublicKey:test_SetThresholdPublicKey_RevertNotOwner() (gas: 13915) FunctionsCoordinator_SetThresholdPublicKey:test_SetThresholdPublicKey_Success() (gas: 513165) -FunctionsCoordinator_StartRequest:test_StartRequest_RevertIfNotRouter() (gas: 22736) -FunctionsCoordinator_StartRequest:test_StartRequest_Success() (gas: 150172) +FunctionsCoordinator_StartRequest:test_StartRequest_RevertIfNotRouter() (gas: 22802) +FunctionsCoordinator_StartRequest:test_StartRequest_Success() (gas: 150150) FunctionsCoordinator__IsTransmitter:test__IsTransmitter_SuccessFound() (gas: 15106) -FunctionsCoordinator__IsTransmitter:test__IsTransmitter_SuccessNotFound() (gas: 22938) +FunctionsCoordinator__IsTransmitter:test__IsTransmitter_SuccessNotFound() (gas: 22916) FunctionsRequest_DEFAULT_BUFFER_SIZE:test_DEFAULT_BUFFER_SIZE() (gas: 3089) FunctionsRequest_EncodeCBOR:test_EncodeCBOR_Success() (gas: 3066) FunctionsRequest_REQUEST_DATA_VERSION:test_REQUEST_DATA_VERSION() (gas: 3068) FunctionsRouter_Constructor:test_Constructor_Success() (gas: 15107) -FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedCostExceedsCommitment() (gas: 172497) +FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedCostExceedsCommitment() (gas: 172475) FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedInsufficientGas() (gas: 163010) FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedInvalidCommitment() (gas: 38777) FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedInvalidRequestId() (gas: 35900) FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedSubscriptionBalanceInvariant() (gas: 180976) -FunctionsRouter_Fulfill:test_Fulfill_RevertIfNotCommittedCoordinator() (gas: 28086) +FunctionsRouter_Fulfill:test_Fulfill_RevertIfNotCommittedCoordinator() (gas: 28152) FunctionsRouter_Fulfill:test_Fulfill_RevertIfPaused() (gas: 156535) FunctionsRouter_Fulfill:test_Fulfill_SuccessClientNoLongerExists() (gas: 335070) FunctionsRouter_Fulfill:test_Fulfill_SuccessFulfilled() (gas: 348695) @@ -65,19 +65,19 @@ FunctionsRouter_Fulfill:test_Fulfill_SuccessUserCallbackReverts() (gas: 2627478) FunctionsRouter_Fulfill:test_Fulfill_SuccessUserCallbackRunsOutOfGas() (gas: 658423) FunctionsRouter_GetAdminFee:test_GetAdminFee_Success() (gas: 18323) FunctionsRouter_GetAllowListId:test_GetAllowListId_Success() (gas: 13241) -FunctionsRouter_GetConfig:test_GetConfig_Success() (gas: 40170) -FunctionsRouter_GetContractById:test_GetContractById_RevertIfRouteDoesNotExist() (gas: 13839) +FunctionsRouter_GetConfig:test_GetConfig_Success() (gas: 40193) +FunctionsRouter_GetContractById:test_GetContractById_RevertIfRouteDoesNotExist() (gas: 13862) FunctionsRouter_GetContractById:test_GetContractById_SuccessIfRouteExists() (gas: 17704) -FunctionsRouter_GetProposedContractById:test_GetProposedContractById_RevertIfRouteDoesNotExist() (gas: 16373) -FunctionsRouter_GetProposedContractById:test_GetProposedContractById_SuccessIfRouteExists() (gas: 24266) +FunctionsRouter_GetProposedContractById:test_GetProposedContractById_RevertIfRouteDoesNotExist() (gas: 16417) +FunctionsRouter_GetProposedContractById:test_GetProposedContractById_SuccessIfRouteExists() (gas: 24289) FunctionsRouter_GetProposedContractSet:test_GetProposedContractSet_Success() (gas: 27289) FunctionsRouter_IsValidCallbackGasLimit:test_IsValidCallbackGasLimit_RevertGasLimitTooBig() (gas: 28087) FunctionsRouter_IsValidCallbackGasLimit:test_IsValidCallbackGasLimit_RevertInvalidConfig() (gas: 41095) FunctionsRouter_IsValidCallbackGasLimit:test_IsValidCallbackGasLimit_Success() (gas: 24632) -FunctionsRouter_Pause:test_Pause_RevertIfNotOwner() (gas: 13338) -FunctionsRouter_Pause:test_Pause_Success() (gas: 20669) -FunctionsRouter_ProposeContractsUpdate:test_ProposeContractsUpdate_RevertIfEmptyAddress() (gas: 14791) -FunctionsRouter_ProposeContractsUpdate:test_ProposeContractsUpdate_RevertIfExceedsMaxProposal() (gas: 21693) +FunctionsRouter_Pause:test_Pause_RevertIfNotOwner() (gas: 13361) +FunctionsRouter_Pause:test_Pause_Success() (gas: 20647) +FunctionsRouter_ProposeContractsUpdate:test_ProposeContractsUpdate_RevertIfEmptyAddress() (gas: 14769) +FunctionsRouter_ProposeContractsUpdate:test_ProposeContractsUpdate_RevertIfExceedsMaxProposal() (gas: 21716) FunctionsRouter_ProposeContractsUpdate:test_ProposeContractsUpdate_RevertIfLengthMismatch() (gas: 14670) FunctionsRouter_ProposeContractsUpdate:test_ProposeContractsUpdate_RevertIfNotNewContract() (gas: 19048) FunctionsRouter_ProposeContractsUpdate:test_ProposeContractsUpdate_RevertIfNotOwner() (gas: 23392) @@ -85,149 +85,151 @@ FunctionsRouter_ProposeContractsUpdate:test_ProposeContractsUpdate_Success() (ga FunctionsRouter_SendRequest:test_SendRequest_RevertIfConsumerNotAllowed() (gas: 59400) FunctionsRouter_SendRequest:test_SendRequest_RevertIfDuplicateRequestId() (gas: 217996) FunctionsRouter_SendRequest:test_SendRequest_RevertIfEmptyData() (gas: 29426) -FunctionsRouter_SendRequest:test_SendRequest_RevertIfIncorrectDonId() (gas: 57904) +FunctionsRouter_SendRequest:test_SendRequest_RevertIfIncorrectDonId() (gas: 57882) FunctionsRouter_SendRequest:test_SendRequest_RevertIfInsufficientSubscriptionBalance() (gas: 208451) FunctionsRouter_SendRequest:test_SendRequest_RevertIfInvalidCallbackGasLimit() (gas: 50953) FunctionsRouter_SendRequest:test_SendRequest_RevertIfInvalidDonId() (gas: 25082) -FunctionsRouter_SendRequest:test_SendRequest_RevertIfNoSubscription() (gas: 29132) +FunctionsRouter_SendRequest:test_SendRequest_RevertIfNoSubscription() (gas: 29177) FunctionsRouter_SendRequest:test_SendRequest_RevertIfPaused() (gas: 34291) -FunctionsRouter_SendRequest:test_SendRequest_Success() (gas: 226346) -FunctionsRouter_SendRequestToProposed:test_SendRequestToProposed_RevertIfConsumerNotAllowed() (gas: 65896) +FunctionsRouter_SendRequest:test_SendRequest_Success() (gas: 226324) +FunctionsRouter_SendRequestToProposed:test_SendRequestToProposed_RevertIfConsumerNotAllowed() (gas: 65918) FunctionsRouter_SendRequestToProposed:test_SendRequestToProposed_RevertIfEmptyData() (gas: 36012) FunctionsRouter_SendRequestToProposed:test_SendRequestToProposed_RevertIfIncorrectDonId() (gas: 29896) FunctionsRouter_SendRequestToProposed:test_SendRequestToProposed_RevertIfInvalidCallbackGasLimit() (gas: 57539) FunctionsRouter_SendRequestToProposed:test_SendRequestToProposed_RevertIfInvalidDonId() (gas: 27503) -FunctionsRouter_SendRequestToProposed:test_SendRequestToProposed_RevertIfNoSubscription() (gas: 35717) +FunctionsRouter_SendRequestToProposed:test_SendRequestToProposed_RevertIfNoSubscription() (gas: 35672) FunctionsRouter_SendRequestToProposed:test_SendRequestToProposed_RevertIfPaused() (gas: 40810) FunctionsRouter_SendRequestToProposed:test_SendRequestToProposed_Success() (gas: 232783) FunctionsRouter_SendRequestToProposed:test_SendRequest_RevertIfInsufficientSubscriptionBalance() (gas: 214899) FunctionsRouter_SetAllowListId:test_SetAllowListId_Success() (gas: 33531) -FunctionsRouter_SetAllowListId:test_UpdateConfig_RevertIfNotOwner() (gas: 13403) -FunctionsRouter_Unpause:test_Unpause_RevertIfNotOwner() (gas: 13293) -FunctionsRouter_Unpause:test_Unpause_Success() (gas: 77725) -FunctionsRouter_UpdateConfig:test_UpdateConfig_RevertIfNotOwner() (gas: 24437) -FunctionsRouter_UpdateConfig:test_UpdateConfig_Success() (gas: 63353) -FunctionsRouter_UpdateContracts:test_UpdateContracts_RevertIfNotOwner() (gas: 13336) +FunctionsRouter_SetAllowListId:test_UpdateConfig_RevertIfNotOwner() (gas: 13381) +FunctionsRouter_Unpause:test_Unpause_RevertIfNotOwner() (gas: 13337) +FunctionsRouter_Unpause:test_Unpause_Success() (gas: 77748) +FunctionsRouter_UpdateConfig:test_UpdateConfig_RevertIfNotOwner() (gas: 24415) +FunctionsRouter_UpdateConfig:test_UpdateConfig_Success() (gas: 63331) +FunctionsRouter_UpdateContracts:test_UpdateContracts_RevertIfNotOwner() (gas: 13314) FunctionsRouter_UpdateContracts:test_UpdateContracts_Success() (gas: 39269) FunctionsSubscriptions_AcceptSubscriptionOwnerTransfer:test_AcceptSubscriptionOwnerTransfer_RevertIfNotAllowedSender() (gas: 60413) FunctionsSubscriptions_AcceptSubscriptionOwnerTransfer:test_AcceptSubscriptionOwnerTransfer_RevertIfPaused() (gas: 61040) FunctionsSubscriptions_AcceptSubscriptionOwnerTransfer:test_AcceptSubscriptionOwnerTransfer_RevertIfSenderBecomesBlocked() (gas: 139706) FunctionsSubscriptions_AcceptSubscriptionOwnerTransfer:test_AcceptSubscriptionOwnerTransfer_RevertIfSenderIsNotNewOwner() (gas: 62780) -FunctionsSubscriptions_AcceptSubscriptionOwnerTransfer:test_AcceptSubscriptionOwnerTransfer_Success() (gas: 239911) +FunctionsSubscriptions_AcceptSubscriptionOwnerTransfer:test_AcceptSubscriptionOwnerTransfer_Success() (gas: 239919) FunctionsSubscriptions_AddConsumer:test_AddConsumer_RevertIfMaximumConsumers() (gas: 138033) FunctionsSubscriptions_AddConsumer:test_AddConsumer_RevertIfMaximumConsumersAfterConfigUpdate() (gas: 164977) -FunctionsSubscriptions_AddConsumer:test_AddConsumer_RevertIfNoSubscription() (gas: 12955) -FunctionsSubscriptions_AddConsumer:test_AddConsumer_RevertIfNotAllowedSender() (gas: 102450) -FunctionsSubscriptions_AddConsumer:test_AddConsumer_RevertIfNotSubscriptionOwner() (gas: 87205) +FunctionsSubscriptions_AddConsumer:test_AddConsumer_RevertIfNoSubscription() (gas: 12933) +FunctionsSubscriptions_AddConsumer:test_AddConsumer_RevertIfNotAllowedSender() (gas: 102428) +FunctionsSubscriptions_AddConsumer:test_AddConsumer_RevertIfNotSubscriptionOwner() (gas: 87272) FunctionsSubscriptions_AddConsumer:test_AddConsumer_RevertIfPaused() (gas: 18100) FunctionsSubscriptions_AddConsumer:test_AddConsumer_Success() (gas: 96221) FunctionsSubscriptions_CancelSubscription:test_CancelSubscription_RevertIfNoSubscription() (gas: 15053) -FunctionsSubscriptions_CancelSubscription:test_CancelSubscription_RevertIfNotAllowedSender() (gas: 102529) -FunctionsSubscriptions_CancelSubscription:test_CancelSubscription_RevertIfNotSubscriptionOwner() (gas: 89318) +FunctionsSubscriptions_CancelSubscription:test_CancelSubscription_RevertIfNotAllowedSender() (gas: 102507) +FunctionsSubscriptions_CancelSubscription:test_CancelSubscription_RevertIfNotSubscriptionOwner() (gas: 89341) FunctionsSubscriptions_CancelSubscription:test_CancelSubscription_RevertIfPaused() (gas: 20157) -FunctionsSubscriptions_CancelSubscription:test_CancelSubscription_RevertIfPendingRequests() (gas: 218330) +FunctionsSubscriptions_CancelSubscription:test_CancelSubscription_RevertIfPendingRequests() (gas: 218308) FunctionsSubscriptions_CancelSubscription:test_CancelSubscription_SuccessForfeitAllBalanceAsDeposit() (gas: 115656) FunctionsSubscriptions_CancelSubscription:test_CancelSubscription_SuccessForfeitSomeBalanceAsDeposit() (gas: 126964) FunctionsSubscriptions_CancelSubscription_ReceiveDeposit:test_CancelSubscription_SuccessRecieveDeposit() (gas: 75369) FunctionsSubscriptions_Constructor:test_Constructor_Success() (gas: 10488) FunctionsSubscriptions_CreateSubscriptionWithConsumer:test_CreateSubscriptionWithConsumer_RevertIfNotAllowedSender() (gas: 28688) -FunctionsSubscriptions_CreateSubscriptionWithConsumer:test_CreateSubscriptionWithConsumer_RevertIfPaused() (gas: 17994) +FunctionsSubscriptions_CreateSubscriptionWithConsumer:test_CreateSubscriptionWithConsumer_RevertIfPaused() (gas: 18038) FunctionsSubscriptions_CreateSubscriptionWithConsumer:test_CreateSubscriptionWithConsumer_Success() (gas: 353899) -FunctionsSubscriptions_GetConsumer:test_GetConsumer_Success() (gas: 17256) -FunctionsSubscriptions_GetFlags:test_GetFlags_SuccessInvalidSubscription() (gas: 13438) -FunctionsSubscriptions_GetFlags:test_GetFlags_SuccessValidSubscription() (gas: 41243) +FunctionsSubscriptions_GetConsumer:test_GetConsumer_Success() (gas: 17279) +FunctionsSubscriptions_GetFlags:test_GetFlags_SuccessInvalidSubscription() (gas: 13504) +FunctionsSubscriptions_GetFlags:test_GetFlags_SuccessValidSubscription() (gas: 41221) FunctionsSubscriptions_GetSubscription:test_GetSubscription_Success() (gas: 32968) FunctionsSubscriptions_GetSubscriptionCount:test_GetSubscriptionCount_Success() (gas: 13305) -FunctionsSubscriptions_GetSubscriptionsInRange:test_GetSubscriptionsInRange_RevertIfEndIsAfterLastSubscription() (gas: 16547) +FunctionsSubscriptions_GetSubscriptionsInRange:test_GetSubscriptionsInRange_RevertIfEndIsAfterLastSubscription() (gas: 16570) FunctionsSubscriptions_GetSubscriptionsInRange:test_GetSubscriptionsInRange_RevertIfStartIsAfterEnd() (gas: 13465) -FunctionsSubscriptions_GetSubscriptionsInRange:test_GetSubscriptionsInRange_Success() (gas: 65990) -FunctionsSubscriptions_GetTotalBalance:test_GetTotalBalance_Success() (gas: 15347) +FunctionsSubscriptions_GetSubscriptionsInRange:test_GetSubscriptionsInRange_Success() (gas: 65968) +FunctionsSubscriptions_GetTotalBalance:test_GetTotalBalance_Success() (gas: 15370) FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_RevertIfCallerIsNoCalldata() (gas: 39908) FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_RevertIfCallerIsNoSubscription() (gas: 42382) FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_RevertIfCallerIsNotLink() (gas: 13419) FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_RevertIfPaused() (gas: 47325) FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_Success() (gas: 84314) -FunctionsSubscriptions_OracleWithdraw:test_OracleWithdraw_RevertIfAmountMoreThanBalance() (gas: 20766) +FunctionsSubscriptions_OracleWithdraw:test_OracleWithdraw_RevertIfAmountMoreThanBalance() (gas: 20744) FunctionsSubscriptions_OracleWithdraw:test_OracleWithdraw_RevertIfBalanceInvariant() (gas: 189) -FunctionsSubscriptions_OracleWithdraw:test_OracleWithdraw_RevertIfNoAmount() (gas: 15641) +FunctionsSubscriptions_OracleWithdraw:test_OracleWithdraw_RevertIfNoAmount() (gas: 15686) FunctionsSubscriptions_OracleWithdraw:test_OracleWithdraw_RevertIfPaused() (gas: 20859) -FunctionsSubscriptions_OracleWithdraw:test_OracleWithdraw_SuccessPaysRecipient() (gas: 60075) +FunctionsSubscriptions_OracleWithdraw:test_OracleWithdraw_SuccessPaysRecipient() (gas: 60119) FunctionsSubscriptions_OracleWithdraw:test_OracleWithdraw_SuccessSetsBalanceToZero() (gas: 57716) -FunctionsSubscriptions_OwnerCancelSubscription:test_OwnerCancelSubscription_RevertIfNoSubscription() (gas: 12818) -FunctionsSubscriptions_OwnerCancelSubscription:test_OwnerCancelSubscription_RevertIfNotOwner() (gas: 15549) -FunctionsSubscriptions_OwnerCancelSubscription:test_OwnerCancelSubscription_Success() (gas: 55141) +FunctionsSubscriptions_OwnerCancelSubscription:test_OwnerCancelSubscription_RevertIfNoSubscription() (gas: 12796) +FunctionsSubscriptions_OwnerCancelSubscription:test_OwnerCancelSubscription_RevertIfNotOwner() (gas: 15594) +FunctionsSubscriptions_OwnerCancelSubscription:test_OwnerCancelSubscription_Success() (gas: 55177) FunctionsSubscriptions_OwnerCancelSubscription:test_OwnerCancelSubscription_SuccessDeletesSubscription() (gas: 49607) FunctionsSubscriptions_OwnerCancelSubscription:test_OwnerCancelSubscription_SuccessSubOwnerRefunded() (gas: 53166) -FunctionsSubscriptions_OwnerCancelSubscription:test_OwnerCancelSubscription_SuccessWhenRequestInFlight() (gas: 186533) -FunctionsSubscriptions_OwnerWithdraw:test_OwnerWithdraw_RevertIfAmountMoreThanBalance() (gas: 17945) +FunctionsSubscriptions_OwnerCancelSubscription:test_OwnerCancelSubscription_SuccessWhenRequestInFlight() (gas: 186511) +FunctionsSubscriptions_OwnerWithdraw:test_OwnerWithdraw_RevertIfAmountMoreThanBalance() (gas: 17923) FunctionsSubscriptions_OwnerWithdraw:test_OwnerWithdraw_RevertIfBalanceInvariant() (gas: 210) -FunctionsSubscriptions_OwnerWithdraw:test_OwnerWithdraw_RevertIfNotOwner() (gas: 15555) +FunctionsSubscriptions_OwnerWithdraw:test_OwnerWithdraw_RevertIfNotOwner() (gas: 15600) FunctionsSubscriptions_OwnerWithdraw:test_OwnerWithdraw_SuccessIfNoAmount() (gas: 33839) -FunctionsSubscriptions_OwnerWithdraw:test_OwnerWithdraw_SuccessIfRecipientAddressZero() (gas: 31649) +FunctionsSubscriptions_OwnerWithdraw:test_OwnerWithdraw_SuccessIfRecipientAddressZero() (gas: 31627) FunctionsSubscriptions_OwnerWithdraw:test_OwnerWithdraw_SuccessPaysRecipient() (gas: 33935) FunctionsSubscriptions_OwnerWithdraw:test_OwnerWithdraw_SuccessSetsBalanceToZero() (gas: 31584) -FunctionsSubscriptions_PendingRequestExists:test_PendingRequestExists_SuccessFalseIfNoPendingRequests() (gas: 17818) -FunctionsSubscriptions_PendingRequestExists:test_PendingRequestExists_SuccessTrueIfPendingRequests() (gas: 203333) -FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_RevertIfEmptyNewOwner() (gas: 27664) -FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_RevertIfInvalidNewOwner() (gas: 57815) +FunctionsSubscriptions_PendingRequestExists:test_PendingRequestExists_SuccessFalseIfNoPendingRequests() (gas: 17796) +FunctionsSubscriptions_PendingRequestExists:test_PendingRequestExists_SuccessTrueIfPendingRequests() (gas: 203311) +FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_RevertIfEmptyNewOwner() (gas: 27642) +FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_RevertIfInvalidNewOwner() (gas: 57793) FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_RevertIfNoSubscription() (gas: 15013) -FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_RevertIfNotAllowedSender() (gas: 119775) -FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_RevertIfNotSubscriptionOwner() (gas: 17969) -FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_RevertIfPaused() (gas: 20137) -FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_Success() (gas: 68596) -FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_SuccessChangeProposedOwner() (gas: 83539) -FunctionsSubscriptions_RecoverFunds:test_OwnerCancelSubscription_RevertIfNotOwner() (gas: 15554) -FunctionsSubscriptions_RecoverFunds:test_RecoverFunds_Success() (gas: 41376) +FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_RevertIfNotAllowedSender() (gas: 119820) +FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_RevertIfNotSubscriptionOwner() (gas: 17947) +FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_RevertIfPaused() (gas: 20181) +FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_Success() (gas: 68574) +FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_SuccessChangeProposedOwner() (gas: 83582) +FunctionsSubscriptions_RecoverFunds:test_OwnerCancelSubscription_RevertIfNotOwner() (gas: 15577) +FunctionsSubscriptions_RecoverFunds:test_RecoverFunds_Success() (gas: 41358) FunctionsSubscriptions_RemoveConsumer:test_RemoveConsumer_RevertIfInvalidConsumer() (gas: 30310) FunctionsSubscriptions_RemoveConsumer:test_RemoveConsumer_RevertIfNoSubscription() (gas: 15031) FunctionsSubscriptions_RemoveConsumer:test_RemoveConsumer_RevertIfNotAllowedSender() (gas: 102444) -FunctionsSubscriptions_RemoveConsumer:test_RemoveConsumer_RevertIfNotSubscriptionOwner() (gas: 87254) -FunctionsSubscriptions_RemoveConsumer:test_RemoveConsumer_RevertIfPaused() (gas: 18058) +FunctionsSubscriptions_RemoveConsumer:test_RemoveConsumer_RevertIfNotSubscriptionOwner() (gas: 87277) +FunctionsSubscriptions_RemoveConsumer:test_RemoveConsumer_RevertIfPaused() (gas: 18103) FunctionsSubscriptions_RemoveConsumer:test_RemoveConsumer_RevertIfPendingRequests() (gas: 215863) -FunctionsSubscriptions_RemoveConsumer:test_RemoveConsumer_Success() (gas: 42088) +FunctionsSubscriptions_RemoveConsumer:test_RemoveConsumer_Success() (gas: 42066) FunctionsSubscriptions_SetFlags:test_SetFlags_RevertIfNoSubscription() (gas: 12888) FunctionsSubscriptions_SetFlags:test_SetFlags_RevertIfNotOwner() (gas: 15684) FunctionsSubscriptions_SetFlags:test_SetFlags_Success() (gas: 38434) FunctionsSubscriptions_TimeoutRequests:test_TimeoutRequests_RevertIfPaused() (gas: 25955) FunctionsSubscriptions_TimeoutRequests:test_TimeoutRequests_RevertIfTimeoutNotExceeded() (gas: 25261) -FunctionsSubscriptions_TimeoutRequests:test_TimeoutRequests_RevertInvalidRequest() (gas: 28242) -FunctionsSubscriptions_TimeoutRequests:test_TimeoutRequests_Success() (gas: 58416) -FunctionsSubscriptions_createSubscription:test_CreateSubscription_RevertIfNotAllowedSender() (gas: 26418) +FunctionsSubscriptions_TimeoutRequests:test_TimeoutRequests_RevertInvalidRequest() (gas: 28220) +FunctionsSubscriptions_TimeoutRequests:test_TimeoutRequests_Success() (gas: 58394) +FunctionsSubscriptions_createSubscription:test_CreateSubscription_RevertIfNotAllowedSender() (gas: 26462) FunctionsSubscriptions_createSubscription:test_CreateSubscription_RevertIfPaused() (gas: 15759) FunctionsSubscriptions_createSubscription:test_CreateSubscription_Success() (gas: 153701) -FunctionsTermsOfServiceAllowList_AcceptTermsOfService:testAcceptTermsOfService_InvalidSigner_vuln() (gas: 94913) -FunctionsTermsOfServiceAllowList_AcceptTermsOfService:test_AcceptTermsOfService_RevertIfAcceptorIsNotSender() (gas: 25859) -FunctionsTermsOfServiceAllowList_AcceptTermsOfService:test_AcceptTermsOfService_RevertIfBlockedSender() (gas: 88990) -FunctionsTermsOfServiceAllowList_AcceptTermsOfService:test_AcceptTermsOfService_RevertIfInvalidSigner() (gas: 23619) -FunctionsTermsOfServiceAllowList_AcceptTermsOfService:test_AcceptTermsOfService_RevertIfRecipientContractIsNotSender() (gas: 1866552) -FunctionsTermsOfServiceAllowList_AcceptTermsOfService:test_AcceptTermsOfService_RevertIfRecipientIsNotSender() (gas: 26025) -FunctionsTermsOfServiceAllowList_AcceptTermsOfService:test_AcceptTermsOfService_SuccessIfAcceptingForContract() (gas: 1946965) -FunctionsTermsOfServiceAllowList_AcceptTermsOfService:test_AcceptTermsOfService_SuccessIfAcceptingForSelf() (gas: 104509) -FunctionsTermsOfServiceAllowList_BlockSender:test_BlockSender_RevertIfNotOwner() (gas: 15491) -FunctionsTermsOfServiceAllowList_BlockSender:test_BlockSender_Success() (gas: 97541) +FunctionsTermsOfServiceAllowList_AcceptTermsOfService:testAcceptTermsOfService_InvalidSigner_vuln() (gas: 94943) +FunctionsTermsOfServiceAllowList_AcceptTermsOfService:test_AcceptTermsOfService_RevertIfAcceptorIsNotSender() (gas: 25925) +FunctionsTermsOfServiceAllowList_AcceptTermsOfService:test_AcceptTermsOfService_RevertIfBlockedSender() (gas: 89013) +FunctionsTermsOfServiceAllowList_AcceptTermsOfService:test_AcceptTermsOfService_RevertIfInvalidSigner() (gas: 23620) +FunctionsTermsOfServiceAllowList_AcceptTermsOfService:test_AcceptTermsOfService_RevertIfRecipientContractIsNotSender() (gas: 1866619) +FunctionsTermsOfServiceAllowList_AcceptTermsOfService:test_AcceptTermsOfService_RevertIfRecipientIsNotSender() (gas: 26026) +FunctionsTermsOfServiceAllowList_AcceptTermsOfService:test_AcceptTermsOfService_SuccessIfAcceptingForContract() (gas: 1946966) +FunctionsTermsOfServiceAllowList_AcceptTermsOfService:test_AcceptTermsOfService_SuccessIfAcceptingForSelf() (gas: 104555) +FunctionsTermsOfServiceAllowList_BlockSender:test_BlockSender_RevertIfNotOwner() (gas: 15535) +FunctionsTermsOfServiceAllowList_BlockSender:test_BlockSender_Success() (gas: 97587) FunctionsTermsOfServiceAllowList_Constructor:test_Constructor_Success() (gas: 15345) FunctionsTermsOfServiceAllowList_GetAllAllowedSenders:test_GetAllAllowedSenders_Success() (gas: 19243) FunctionsTermsOfServiceAllowList_GetAllowedSendersCount:test_GetAllowedSendersCount_Success() (gas: 13332) -FunctionsTermsOfServiceAllowList_GetAllowedSendersInRange:test_GetAllowedSendersInRange_RevertIfAllowedSendersIsEmpty() (gas: 13153024) -FunctionsTermsOfServiceAllowList_GetAllowedSendersInRange:test_GetAllowedSendersInRange_RevertIfEndIsAfterLastAllowedSender() (gas: 16554) -FunctionsTermsOfServiceAllowList_GetAllowedSendersInRange:test_GetAllowedSendersInRange_RevertIfStartIsAfterEnd() (gas: 13284) -FunctionsTermsOfServiceAllowList_GetAllowedSendersInRange:test_GetAllowedSendersInRange_Success() (gas: 20312) +FunctionsTermsOfServiceAllowList_GetAllowedSendersInRange:test_GetAllowedSendersInRange_RevertIfAllowedSendersIsEmpty() (gas: 13326576) +FunctionsTermsOfServiceAllowList_GetAllowedSendersInRange:test_GetAllowedSendersInRange_RevertIfEndIsAfterLastAllowedSender() (gas: 16532) +FunctionsTermsOfServiceAllowList_GetAllowedSendersInRange:test_GetAllowedSendersInRange_RevertIfStartIsAfterEnd() (gas: 13307) +FunctionsTermsOfServiceAllowList_GetAllowedSendersInRange:test_GetAllowedSendersInRange_Success() (gas: 20335) FunctionsTermsOfServiceAllowList_GetBlockedSendersCount:test_GetBlockedSendersCount_Success() (gas: 13268) -FunctionsTermsOfServiceAllowList_GetBlockedSendersInRange:test_GetBlockedSendersInRange_RevertIfAllowedSendersIsEmpty() (gas: 13153034) +FunctionsTermsOfServiceAllowList_GetBlockedSendersInRange:test_GetBlockedSendersInRange_RevertIfAllowedSendersIsEmpty() (gas: 13326564) FunctionsTermsOfServiceAllowList_GetBlockedSendersInRange:test_GetBlockedSendersInRange_RevertIfEndIsAfterLastAllowedSender() (gas: 16549) -FunctionsTermsOfServiceAllowList_GetBlockedSendersInRange:test_GetBlockedSendersInRange_RevertIfStartIsAfterEnd() (gas: 13367) -FunctionsTermsOfServiceAllowList_GetBlockedSendersInRange:test_GetBlockedSendersInRange_Success() (gas: 18537) -FunctionsTermsOfServiceAllowList_GetConfig:test_GetConfig_Success() (gas: 16388) +FunctionsTermsOfServiceAllowList_GetBlockedSendersInRange:test_GetBlockedSendersInRange_RevertIfStartIsAfterEnd() (gas: 13345) +FunctionsTermsOfServiceAllowList_GetBlockedSendersInRange:test_GetBlockedSendersInRange_Success() (gas: 18580) +FunctionsTermsOfServiceAllowList_GetConfig:test_GetConfig_Success() (gas: 16411) FunctionsTermsOfServiceAllowList_GetMessage:test_GetMessage_Success() (gas: 11918) -FunctionsTermsOfServiceAllowList_HasAccess:test_HasAccess_FalseWhenEnabled() (gas: 16257) -FunctionsTermsOfServiceAllowList_HasAccess:test_HasAccess_TrueWhenDisabled() (gas: 23848) +FunctionsTermsOfServiceAllowList_HasAccess:test_HasAccess_FalseWhenEnabled() (gas: 16235) +FunctionsTermsOfServiceAllowList_HasAccess:test_HasAccess_TrueWhenDisabled() (gas: 23877) FunctionsTermsOfServiceAllowList_IsBlockedSender:test_IsBlockedSender_SuccessFalse() (gas: 15776) FunctionsTermsOfServiceAllowList_IsBlockedSender:test_IsBlockedSender_SuccessTrue() (gas: 86974) -FunctionsTermsOfServiceAllowList_UnblockSender:test_UnblockSender_RevertIfNotOwner() (gas: 13502) -FunctionsTermsOfServiceAllowList_UnblockSender:test_UnblockSender_Success() (gas: 96216) -FunctionsTermsOfServiceAllowList_UpdateConfig:test_UpdateConfig_RevertIfNotOwner() (gas: 13812) -FunctionsTermsOfServiceAllowList_UpdateConfig:test_UpdateConfig_Success() (gas: 22817) -Gas_AcceptTermsOfService:test_AcceptTermsOfService_Gas() (gas: 84702) +FunctionsTermsOfServiceAllowList_MigratePreviouslyAllowedSenders:test_MigratePreviouslyAllowedSenders_RevertIfNotOwner() (gas: 13987) +FunctionsTermsOfServiceAllowList_MigratePreviouslyAllowedSenders:test_MigratePreviouslyAllowedSenders_Success() (gas: 210636) +FunctionsTermsOfServiceAllowList_UnblockSender:test_UnblockSender_RevertIfNotOwner() (gas: 13548) +FunctionsTermsOfServiceAllowList_UnblockSender:test_UnblockSender_Success() (gas: 96240) +FunctionsTermsOfServiceAllowList_UpdateConfig:test_UpdateConfig_RevertIfNotOwner() (gas: 13819) +FunctionsTermsOfServiceAllowList_UpdateConfig:test_UpdateConfig_Success() (gas: 22824) +Gas_AcceptTermsOfService:test_AcceptTermsOfService_Gas() (gas: 84725) Gas_AddConsumer:test_AddConsumer_Gas() (gas: 79140) Gas_CreateSubscription:test_CreateSubscription_Gas() (gas: 73419) Gas_FulfillRequest_DuplicateRequestID:test_FulfillRequest_DuplicateRequestID_MaximumGas() (gas: 20717) diff --git a/contracts/src/v0.8/functions/dev/v1_X/accessControl/TermsOfServiceAllowList.sol b/contracts/src/v0.8/functions/dev/v1_X/accessControl/TermsOfServiceAllowList.sol index 04604e6797..0ba8e5d6ca 100644 --- a/contracts/src/v0.8/functions/dev/v1_X/accessControl/TermsOfServiceAllowList.sol +++ b/contracts/src/v0.8/functions/dev/v1_X/accessControl/TermsOfServiceAllowList.sol @@ -16,7 +16,8 @@ contract TermsOfServiceAllowList is ITermsOfServiceAllowList, IAccessController, using EnumerableSet for EnumerableSet.AddressSet; /// @inheritdoc ITypeAndVersion - string public constant override typeAndVersion = "Functions Terms of Service Allow List v1.1.0"; + string public constant override typeAndVersion = "Functions Terms of Service Allow List v1.1.1"; + address private s_previousToSContract; EnumerableSet.AddressSet private s_allowedSenders; EnumerableSet.AddressSet private s_blockedSenders; @@ -29,6 +30,7 @@ contract TermsOfServiceAllowList is ITermsOfServiceAllowList, IAccessController, error InvalidUsage(); error RecipientIsBlocked(); error InvalidCalldata(); + error NoPreviousToSContract(); TermsOfServiceAllowListConfig private s_config; @@ -41,7 +43,8 @@ contract TermsOfServiceAllowList is ITermsOfServiceAllowList, IAccessController, constructor( TermsOfServiceAllowListConfig memory config, address[] memory initialAllowedSenders, - address[] memory initialBlockedSenders + address[] memory initialBlockedSenders, + address previousToSContract ) ConfirmedOwner(msg.sender) { updateConfig(config); @@ -56,6 +59,8 @@ contract TermsOfServiceAllowList is ITermsOfServiceAllowList, IAccessController, } s_blockedSenders.add(initialBlockedSenders[j]); } + + s_previousToSContract = previousToSContract; } // ================================================================ @@ -197,4 +202,19 @@ contract TermsOfServiceAllowList is ITermsOfServiceAllowList, IAccessController, return blockedSenders; } + + /// @inheritdoc ITermsOfServiceAllowList + function migratePreviouslyAllowedSenders(address[] memory previousSendersToAdd) external override onlyOwner { + if (s_previousToSContract == address(0)) { + revert NoPreviousToSContract(); + } + IAccessController previousToSContract = IAccessController(s_previousToSContract); + for (uint256 i = 0; i < previousSendersToAdd.length; ++i) { + if (previousToSContract.hasAccess(previousSendersToAdd[i], "")) { + if (!s_blockedSenders.contains(previousSendersToAdd[i])) { + s_allowedSenders.add(previousSendersToAdd[i]); + } + } + } + } } diff --git a/contracts/src/v0.8/functions/dev/v1_X/accessControl/interfaces/ITermsOfServiceAllowList.sol b/contracts/src/v0.8/functions/dev/v1_X/accessControl/interfaces/ITermsOfServiceAllowList.sol index 65db9c42b6..32a0ecef79 100644 --- a/contracts/src/v0.8/functions/dev/v1_X/accessControl/interfaces/ITermsOfServiceAllowList.sol +++ b/contracts/src/v0.8/functions/dev/v1_X/accessControl/interfaces/ITermsOfServiceAllowList.sol @@ -69,6 +69,10 @@ interface ITermsOfServiceAllowList { uint64 blockedSenderIdxStart, uint64 blockedSenderIdxEnd ) external view returns (address[] memory blockedSenders); + + /// @notice Enables migrating any previously allowed senders to the new contract + /// @param previousSendersToAdd - List of addresses to migrate. These address must be allowed on the previous ToS contract and not blocked + function migratePreviouslyAllowedSenders(address[] memory previousSendersToAdd) external; } // ================================================================ diff --git a/contracts/src/v0.8/functions/tests/v1_X/FunctionsTermsOfServiceAllowList.t.sol b/contracts/src/v0.8/functions/tests/v1_X/FunctionsTermsOfServiceAllowList.t.sol index e121f7b881..9bf09748b8 100644 --- a/contracts/src/v0.8/functions/tests/v1_X/FunctionsTermsOfServiceAllowList.t.sol +++ b/contracts/src/v0.8/functions/tests/v1_X/FunctionsTermsOfServiceAllowList.t.sol @@ -11,7 +11,7 @@ import "forge-std/Vm.sol"; /// @notice #constructor contract FunctionsTermsOfServiceAllowList_Constructor is FunctionsRoutesSetup { function test_Constructor_Success() public { - assertEq(s_termsOfServiceAllowList.typeAndVersion(), "Functions Terms of Service Allow List v1.1.0"); + assertEq(s_termsOfServiceAllowList.typeAndVersion(), "Functions Terms of Service Allow List v1.1.1"); assertEq(s_termsOfServiceAllowList.owner(), OWNER_ADDRESS); } } @@ -511,3 +511,47 @@ contract FunctionsTermsOfServiceAllowList_GetBlockedSendersInRange is FunctionsR s_termsOfServiceAllowList.getBlockedSendersInRange(1, BlockedSendersCount + 1); } } + +/// @notice #migratePreviouslyAllowedSenders +contract FunctionsTermsOfServiceAllowList_MigratePreviouslyAllowedSenders is FunctionsRoutesSetup { + function setUp() public virtual override { + FunctionsRoutesSetup.setUp(); + } + + function test_MigratePreviouslyAllowedSenders_RevertIfNotOwner() public { + // Send as stranger + vm.stopPrank(); + vm.startPrank(STRANGER_ADDRESS); + + vm.expectRevert("Only callable by owner"); + address[] memory empty = new address[](0); + s_termsOfServiceAllowList.migratePreviouslyAllowedSenders(empty); + } + + function test_MigratePreviouslyAllowedSenders_Success() public { + address previouslyAllowedSender1 = 0x1000000000000000000000000000000000000000; + address previouslyAllowedSender2 = 0x2000000000000000000000000000000000000000; + address currentlyBlockedSender = 0xB000000000000000000000000000000000000000; + + address[] memory mockPreviousAllowlist = new address[](3); + mockPreviousAllowlist[0] = previouslyAllowedSender1; + mockPreviousAllowlist[1] = currentlyBlockedSender; + mockPreviousAllowlist[2] = previouslyAllowedSender2; + + s_termsOfServiceAllowList.blockSender(currentlyBlockedSender); + + vm.mockCall( + MOCK_PREVIOUS_TOS_ADDRESS, + abi.encodeWithSelector(TermsOfServiceAllowList.hasAccess.selector), + abi.encode(true) + ); + s_termsOfServiceAllowList.migratePreviouslyAllowedSenders(mockPreviousAllowlist); + + address[] memory currentlyAllowedSenders = s_termsOfServiceAllowList.getAllAllowedSenders(); + + address[] memory expectedAllowedSenders = new address[](2); + expectedAllowedSenders[0] = previouslyAllowedSender1; + expectedAllowedSenders[1] = previouslyAllowedSender2; + assertEq(currentlyAllowedSenders, expectedAllowedSenders); + } +} diff --git a/contracts/src/v0.8/functions/tests/v1_X/Setup.t.sol b/contracts/src/v0.8/functions/tests/v1_X/Setup.t.sol index 815366e62a..444fc18fe8 100644 --- a/contracts/src/v0.8/functions/tests/v1_X/Setup.t.sol +++ b/contracts/src/v0.8/functions/tests/v1_X/Setup.t.sol @@ -37,6 +37,7 @@ contract FunctionsRouterSetup is BaseTest { int256 internal LINK_USD_RATE = 1_500_000_000; uint8 internal LINK_USD_DECIMALS = 8; + address public MOCK_PREVIOUS_TOS_ADDRESS = 0x746f730000000000000000000000000000000000; uint256 internal TOS_SIGNER_PRIVATE_KEY = 0x3; address internal TOS_SIGNER = vm.addr(TOS_SIGNER_PRIVATE_KEY); @@ -57,7 +58,8 @@ contract FunctionsRouterSetup is BaseTest { s_termsOfServiceAllowList = new TermsOfServiceAllowList( getTermsOfServiceConfig(), initialAllowedSenders, - initialBlockedSenders + initialBlockedSenders, + MOCK_PREVIOUS_TOS_ADDRESS ); } diff --git a/core/gethwrappers/functions/generated/functions_allow_list/functions_allow_list.go b/core/gethwrappers/functions/generated/functions_allow_list/functions_allow_list.go index 2f98ae1623..aa8cf0bd86 100644 --- a/core/gethwrappers/functions/generated/functions_allow_list/functions_allow_list.go +++ b/core/gethwrappers/functions/generated/functions_allow_list/functions_allow_list.go @@ -36,15 +36,15 @@ type TermsOfServiceAllowListConfig struct { } var TermsOfServiceAllowListMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"enabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"signerPublicKey\",\"type\":\"address\"}],\"internalType\":\"structTermsOfServiceAllowListConfig\",\"name\":\"config\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"initialAllowedSenders\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"initialBlockedSenders\",\"type\":\"address[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"InvalidCalldata\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSignature\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidUsage\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RecipientIsBlocked\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"}],\"name\":\"AddedAccess\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"}],\"name\":\"BlockedAccess\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"enabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"signerPublicKey\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structTermsOfServiceAllowListConfig\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"}],\"name\":\"UnblockedAccess\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"acceptor\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"}],\"name\":\"acceptTermsOfService\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"blockSender\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllAllowedSenders\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowedSendersCount\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"allowedSenderIdxStart\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"allowedSenderIdxEnd\",\"type\":\"uint64\"}],\"name\":\"getAllowedSendersInRange\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"allowedSenders\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBlockedSendersCount\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"blockedSenderIdxStart\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"blockedSenderIdxEnd\",\"type\":\"uint64\"}],\"name\":\"getBlockedSendersInRange\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"blockedSenders\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"enabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"signerPublicKey\",\"type\":\"address\"}],\"internalType\":\"structTermsOfServiceAllowListConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"acceptor\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"}],\"name\":\"getMessage\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"hasAccess\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"isBlockedSender\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"unblockSender\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"enabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"signerPublicKey\",\"type\":\"address\"}],\"internalType\":\"structTermsOfServiceAllowListConfig\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"updateConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x60806040523480156200001157600080fd5b5060405162001a1e38038062001a1e8339810160408190526200003491620004d9565b33806000816200008b5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000be57620000be81620001d4565b505050620000d2836200027f60201b60201c565b60005b8251811015620001255762000111838281518110620000f857620000f8620005a8565b602002602001015160026200030660201b90919060201c565b506200011d81620005be565b9050620000d5565b5060005b8151811015620001ca57620001658282815181106200014c576200014c620005a8565b602002602001015160026200032660201b90919060201c565b156200018457604051638129bbcd60e01b815260040160405180910390fd5b620001b68282815181106200019d576200019d620005a8565b602002602001015160046200030660201b90919060201c565b50620001c281620005be565b905062000129565b50505050620005e6565b336001600160a01b038216036200022e5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000082565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6200028962000349565b805160068054602080850180516001600160a81b0319909316941515610100600160a81b03198116959095176101006001600160a01b039485160217909355604080519485529251909116908301527f0d22b8a99f411b3dd338c961284f608489ca0dab9cdad17366a343c361bcf80a910160405180910390a150565b60006200031d836001600160a01b038416620003a7565b90505b92915050565b6001600160a01b038116600090815260018301602052604081205415156200031d565b6000546001600160a01b03163314620003a55760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640162000082565b565b6000818152600183016020526040812054620003f05750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000320565b50600062000320565b634e487b7160e01b600052604160045260246000fd5b80516001600160a01b03811681146200042757600080fd5b919050565b600082601f8301126200043e57600080fd5b815160206001600160401b03808311156200045d576200045d620003f9565b8260051b604051601f19603f83011681018181108482111715620004855762000485620003f9565b604052938452858101830193838101925087851115620004a457600080fd5b83870191505b84821015620004ce57620004be826200040f565b83529183019190830190620004aa565b979650505050505050565b60008060008385036080811215620004f057600080fd5b6040811215620004ff57600080fd5b50604080519081016001600160401b038082118383101715620005265762000526620003f9565b816040528651915081151582146200053d57600080fd5b8183526200054e602088016200040f565b60208401526040870151929550808311156200056957600080fd5b62000577888489016200042c565b945060608701519250808311156200058e57600080fd5b50506200059e868287016200042c565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b600060018201620005df57634e487b7160e01b600052601160045260246000fd5b5060010190565b61142880620005f66000396000f3fe608060405234801561001057600080fd5b506004361061011b5760003560e01c8063817ef62e116100b2578063a39b06e311610081578063c3f909d411610066578063c3f909d4146102c3578063cc7ebf4914610322578063f2fde38b1461032a57600080fd5b8063a39b06e314610237578063a5e1d61d146102b057600080fd5b8063817ef62e146101e157806382184c7b146101e957806389f9a2c4146101fc5780638da5cb5b1461020f57600080fd5b80633908c4d4116100ee5780633908c4d41461018e57806347663acb146101a35780636b14daf8146101b657806379ba5097146101d957600080fd5b806301a05958146101205780630a8c9c2414610146578063181f5a771461016657806320229a861461017b575b600080fd5b61012861033d565b60405167ffffffffffffffff90911681526020015b60405180910390f35b610159610154366004610fc4565b61034e565b60405161013d9190610ff7565b61016e6104aa565b60405161013d9190611051565b610159610189366004610fc4565b6104c6565b6101a161019c3660046110e1565b61062c565b005b6101a16101b1366004611142565b6108d7565b6101c96101c436600461115d565b610938565b604051901515815260200161013d565b6101a1610962565b610159610a64565b6101a16101f7366004611142565b610a70565b6101a161020a36600461120f565b610ad6565b60005460405173ffffffffffffffffffffffffffffffffffffffff909116815260200161013d565b6102a2610245366004611298565b6040517fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606084811b8216602084015283901b16603482015260009060480160405160208183030381529060405280519060200120905092915050565b60405190815260200161013d565b6101c96102be366004611142565b610b91565b60408051808201825260008082526020918201528151808301835260065460ff8116151580835273ffffffffffffffffffffffffffffffffffffffff61010090920482169284019283528451908152915116918101919091520161013d565b610128610bb1565b6101a1610338366004611142565b610bbd565b60006103496004610bd1565b905090565b60608167ffffffffffffffff168367ffffffffffffffff16118061038557506103776002610bd1565b8267ffffffffffffffff1610155b156103bc576040517f8129bbcd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103c683836112f1565b6103d1906001611312565b67ffffffffffffffff1667ffffffffffffffff8111156103f3576103f36111e0565b60405190808252806020026020018201604052801561041c578160200160208202803683370190505b50905060005b61042c84846112f1565b67ffffffffffffffff1681116104a25761045b6104538267ffffffffffffffff8716611333565b600290610bdb565b82828151811061046d5761046d611346565b73ffffffffffffffffffffffffffffffffffffffff9092166020928302919091019091015261049b81611375565b9050610422565b505b92915050565b6040518060600160405280602c81526020016113f0602c913981565b60608167ffffffffffffffff168367ffffffffffffffff1611806104fd57506104ef6004610bd1565b8267ffffffffffffffff1610155b8061050f575061050d6004610bd1565b155b15610546576040517f8129bbcd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61055083836112f1565b61055b906001611312565b67ffffffffffffffff1667ffffffffffffffff81111561057d5761057d6111e0565b6040519080825280602002602001820160405280156105a6578160200160208202803683370190505b50905060005b6105b684846112f1565b67ffffffffffffffff1681116104a2576105e56105dd8267ffffffffffffffff8716611333565b600490610bdb565b8282815181106105f7576105f7611346565b73ffffffffffffffffffffffffffffffffffffffff9092166020928302919091019091015261062581611375565b90506105ac565b610637600485610be7565b1561066e576040517f62b7a34d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408051606087811b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000009081166020808501919091529188901b16603483015282516028818403018152604890920190925280519101206000906040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c810191909152605c01604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815282825280516020918201206006546000855291840180845281905260ff8616928401929092526060830187905260808301869052909250610100900473ffffffffffffffffffffffffffffffffffffffff169060019060a0016020604051602081039080840390855afa1580156107a2573d6000803e3d6000fd5b5050506020604051035173ffffffffffffffffffffffffffffffffffffffff16146107f9576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff861614158061083e57503373ffffffffffffffffffffffffffffffffffffffff87161480159061083e5750333b155b15610875576040517f381cfcbd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610880600286610c16565b156108cf5760405173ffffffffffffffffffffffffffffffffffffffff861681527f87286ad1f399c8e82bf0c4ef4fcdc570ea2e1e92176e5c848b6413545b885db49060200160405180910390a15b505050505050565b6108df610c38565b6108ea600482610cbb565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527f28bbd0761309a99e8fb5e5d02ada0b7b2db2e5357531ff5dbfc205c3f5b6592b906020015b60405180910390a150565b60065460009060ff1661094d5750600161095b565b610958600285610be7565b90505b9392505050565b60015473ffffffffffffffffffffffffffffffffffffffff1633146109e8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b60606103496002610cdd565b610a78610c38565b610a83600282610cbb565b50610a8f600482610c16565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527f337cd0f3f594112b6d830afb510072d3b08556b446514f73b8109162fd1151e19060200161092d565b610ade610c38565b805160068054602080850180517fffffffffffffffffffffff0000000000000000000000000000000000000000009093169415157fffffffffffffffffffffff0000000000000000000000000000000000000000ff81169590951761010073ffffffffffffffffffffffffffffffffffffffff9485160217909355604080519485529251909116908301527f0d22b8a99f411b3dd338c961284f608489ca0dab9cdad17366a343c361bcf80a910161092d565b60065460009060ff16610ba657506000919050565b6104a4600483610be7565b60006103496002610bd1565b610bc5610c38565b610bce81610cea565b50565b60006104a4825490565b600061095b8383610ddf565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600183016020526040812054151561095b565b600061095b8373ffffffffffffffffffffffffffffffffffffffff8416610e09565b60005473ffffffffffffffffffffffffffffffffffffffff163314610cb9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016109df565b565b600061095b8373ffffffffffffffffffffffffffffffffffffffff8416610e58565b6060600061095b83610f4b565b3373ffffffffffffffffffffffffffffffffffffffff821603610d69576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016109df565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000826000018281548110610df657610df6611346565b9060005260206000200154905092915050565b6000818152600183016020526040812054610e50575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556104a4565b5060006104a4565b60008181526001830160205260408120548015610f41576000610e7c6001836113ad565b8554909150600090610e90906001906113ad565b9050818114610ef5576000866000018281548110610eb057610eb0611346565b9060005260206000200154905080876000018481548110610ed357610ed3611346565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080610f0657610f066113c0565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506104a4565b60009150506104a4565b606081600001805480602002602001604051908101604052809291908181526020018280548015610f9b57602002820191906000526020600020905b815481526020019060010190808311610f87575b50505050509050919050565b803567ffffffffffffffff81168114610fbf57600080fd5b919050565b60008060408385031215610fd757600080fd5b610fe083610fa7565b9150610fee60208401610fa7565b90509250929050565b6020808252825182820181905260009190848201906040850190845b8181101561104557835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101611013565b50909695505050505050565b600060208083528351808285015260005b8181101561107e57858101830151858201604001528201611062565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610fbf57600080fd5b600080600080600060a086880312156110f957600080fd5b611102866110bd565b9450611110602087016110bd565b93506040860135925060608601359150608086013560ff8116811461113457600080fd5b809150509295509295909350565b60006020828403121561115457600080fd5b61095b826110bd565b60008060006040848603121561117257600080fd5b61117b846110bd565b9250602084013567ffffffffffffffff8082111561119857600080fd5b818601915086601f8301126111ac57600080fd5b8135818111156111bb57600080fd5b8760208285010111156111cd57600080fd5b6020830194508093505050509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006040828403121561122157600080fd5b6040516040810181811067ffffffffffffffff8211171561126b577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040528235801515811461127e57600080fd5b815261128c602084016110bd565b60208201529392505050565b600080604083850312156112ab57600080fd5b6112b4836110bd565b9150610fee602084016110bd565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b67ffffffffffffffff8281168282160390808211156104a2576104a26112c2565b67ffffffffffffffff8181168382160190808211156104a2576104a26112c2565b808201808211156104a4576104a46112c2565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036113a6576113a66112c2565b5060010190565b818103818111156104a4576104a46112c2565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfe46756e6374696f6e73205465726d73206f66205365727669636520416c6c6f77204c6973742076312e312e30a164736f6c6343000813000a", + ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"enabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"signerPublicKey\",\"type\":\"address\"}],\"internalType\":\"structTermsOfServiceAllowListConfig\",\"name\":\"config\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"initialAllowedSenders\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"initialBlockedSenders\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"previousToSContract\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"InvalidCalldata\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSignature\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidUsage\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoPreviousToSContract\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RecipientIsBlocked\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"}],\"name\":\"AddedAccess\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"}],\"name\":\"BlockedAccess\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"enabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"signerPublicKey\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structTermsOfServiceAllowListConfig\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"}],\"name\":\"UnblockedAccess\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"acceptor\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"}],\"name\":\"acceptTermsOfService\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"blockSender\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllAllowedSenders\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowedSendersCount\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"allowedSenderIdxStart\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"allowedSenderIdxEnd\",\"type\":\"uint64\"}],\"name\":\"getAllowedSendersInRange\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"allowedSenders\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBlockedSendersCount\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"blockedSenderIdxStart\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"blockedSenderIdxEnd\",\"type\":\"uint64\"}],\"name\":\"getBlockedSendersInRange\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"blockedSenders\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"enabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"signerPublicKey\",\"type\":\"address\"}],\"internalType\":\"structTermsOfServiceAllowListConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"acceptor\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"}],\"name\":\"getMessage\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"name\":\"hasAccess\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"isBlockedSender\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"previousSendersToAdd\",\"type\":\"address[]\"}],\"name\":\"migratePreviouslyAllowedSenders\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"unblockSender\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"enabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"signerPublicKey\",\"type\":\"address\"}],\"internalType\":\"structTermsOfServiceAllowListConfig\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"updateConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x60806040523480156200001157600080fd5b5060405162001d5338038062001d53833981016040819052620000349162000525565b33806000816200008b5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000be57620000be81620001f5565b505050620000d284620002a060201b60201c565b60005b8351811015620001255762000111848281518110620000f857620000f8620005eb565b602002602001015160036200032760201b90919060201c565b506200011d8162000601565b9050620000d5565b5060005b8251811015620001ca57620001658382815181106200014c576200014c620005eb565b602002602001015160036200034760201b90919060201c565b156200018457604051638129bbcd60e01b815260040160405180910390fd5b620001b68382815181106200019d576200019d620005eb565b602002602001015160056200032760201b90919060201c565b50620001c28162000601565b905062000129565b50600280546001600160a01b0319166001600160a01b03929092169190911790555062000629915050565b336001600160a01b038216036200024f5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000082565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b620002aa6200036a565b805160078054602080850180516001600160a81b0319909316941515610100600160a81b03198116959095176101006001600160a01b039485160217909355604080519485529251909116908301527f0d22b8a99f411b3dd338c961284f608489ca0dab9cdad17366a343c361bcf80a910160405180910390a150565b60006200033e836001600160a01b038416620003c8565b90505b92915050565b6001600160a01b038116600090815260018301602052604081205415156200033e565b6000546001600160a01b03163314620003c65760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640162000082565b565b6000818152600183016020526040812054620004115750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000341565b50600062000341565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b03811182821017156200045557620004556200041a565b60405290565b80516001600160a01b03811681146200047357600080fd5b919050565b600082601f8301126200048a57600080fd5b815160206001600160401b0380831115620004a957620004a96200041a565b8260051b604051601f19603f83011681018181108482111715620004d157620004d16200041a565b604052938452858101830193838101925087851115620004f057600080fd5b83870191505b848210156200051a576200050a826200045b565b83529183019190830190620004f6565b979650505050505050565b60008060008084860360a08112156200053d57600080fd5b60408112156200054c57600080fd5b506200055762000430565b855180151581146200056857600080fd5b815262000578602087016200045b565b602082015260408601519094506001600160401b03808211156200059b57600080fd5b620005a98883890162000478565b94506060870151915080821115620005c057600080fd5b50620005cf8782880162000478565b925050620005e0608086016200045b565b905092959194509250565b634e487b7160e01b600052603260045260246000fd5b6000600182016200062257634e487b7160e01b600052601160045260246000fd5b5060010190565b61171a80620006396000396000f3fe608060405234801561001057600080fd5b50600436106101365760003560e01c8063817ef62e116100b2578063a39b06e311610081578063c3f909d411610066578063c3f909d4146102f1578063cc7ebf4914610350578063f2fde38b1461035857600080fd5b8063a39b06e314610265578063a5e1d61d146102de57600080fd5b8063817ef62e1461020f57806382184c7b1461021757806389f9a2c41461022a5780638da5cb5b1461023d57600080fd5b80633908c4d4116101095780634e10a5b3116100ee5780634e10a5b3146101d15780636b14daf8146101e457806379ba50971461020757600080fd5b80633908c4d4146101a957806347663acb146101be57600080fd5b806301a059581461013b5780630a8c9c2414610161578063181f5a771461018157806320229a8614610196575b600080fd5b61014361036b565b60405167ffffffffffffffff90911681526020015b60405180910390f35b61017461016f3660046111bb565b61037c565b60405161015891906111ee565b6101896104d8565b6040516101589190611248565b6101746101a43660046111bb565b6104f4565b6101bc6101b73660046112d8565b61065a565b005b6101bc6101cc366004611339565b610905565b6101bc6101df3660046113d2565b610966565b6101f76101f236600461147f565b610b2f565b6040519015158152602001610158565b6101bc610b59565b610174610c5b565b6101bc610225366004611339565b610c67565b6101bc610238366004611510565b610ccd565b60005460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610158565b6102d061027336600461156d565b6040517fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606084811b8216602084015283901b16603482015260009060480160405160208183030381529060405280519060200120905092915050565b604051908152602001610158565b6101f76102ec366004611339565b610d88565b60408051808201825260008082526020918201528151808301835260075460ff8116151580835273ffffffffffffffffffffffffffffffffffffffff610100909204821692840192835284519081529151169181019190915201610158565b610143610da8565b6101bc610366366004611339565b610db4565b60006103776005610dc8565b905090565b60608167ffffffffffffffff168367ffffffffffffffff1611806103b357506103a56003610dc8565b8267ffffffffffffffff1610155b156103ea576040517f8129bbcd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6103f483836115c6565b6103ff9060016115e7565b67ffffffffffffffff1667ffffffffffffffff81111561042157610421611354565b60405190808252806020026020018201604052801561044a578160200160208202803683370190505b50905060005b61045a84846115c6565b67ffffffffffffffff1681116104d0576104896104818267ffffffffffffffff8716611608565b600390610dd2565b82828151811061049b5761049b61161b565b73ffffffffffffffffffffffffffffffffffffffff909216602092830291909101909101526104c98161164a565b9050610450565b505b92915050565b6040518060600160405280602c81526020016116e2602c913981565b60608167ffffffffffffffff168367ffffffffffffffff16118061052b575061051d6005610dc8565b8267ffffffffffffffff1610155b8061053d575061053b6005610dc8565b155b15610574576040517f8129bbcd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61057e83836115c6565b6105899060016115e7565b67ffffffffffffffff1667ffffffffffffffff8111156105ab576105ab611354565b6040519080825280602002602001820160405280156105d4578160200160208202803683370190505b50905060005b6105e484846115c6565b67ffffffffffffffff1681116104d05761061361060b8267ffffffffffffffff8716611608565b600590610dd2565b8282815181106106255761062561161b565b73ffffffffffffffffffffffffffffffffffffffff909216602092830291909101909101526106538161164a565b90506105da565b610665600585610dde565b1561069c576040517f62b7a34d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408051606087811b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000009081166020808501919091529188901b16603483015282516028818403018152604890920190925280519101206000906040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c810191909152605c01604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815282825280516020918201206007546000855291840180845281905260ff8616928401929092526060830187905260808301869052909250610100900473ffffffffffffffffffffffffffffffffffffffff169060019060a0016020604051602081039080840390855afa1580156107d0573d6000803e3d6000fd5b5050506020604051035173ffffffffffffffffffffffffffffffffffffffff1614610827576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff861614158061086c57503373ffffffffffffffffffffffffffffffffffffffff87161480159061086c5750333b155b156108a3576040517f381cfcbd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6108ae600386610e0d565b156108fd5760405173ffffffffffffffffffffffffffffffffffffffff861681527f87286ad1f399c8e82bf0c4ef4fcdc570ea2e1e92176e5c848b6413545b885db49060200160405180910390a15b505050505050565b61090d610e2f565b610918600582610eb2565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527f28bbd0761309a99e8fb5e5d02ada0b7b2db2e5357531ff5dbfc205c3f5b6592b906020015b60405180910390a150565b61096e610e2f565b60025473ffffffffffffffffffffffffffffffffffffffff166109bd576040517fb25f406700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60025473ffffffffffffffffffffffffffffffffffffffff1660005b8251811015610b2a578173ffffffffffffffffffffffffffffffffffffffff16636b14daf8848381518110610a1057610a1061161b565b6020908102919091010151604080517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815273ffffffffffffffffffffffffffffffffffffffff9092166004830152602482015260006044820152606401602060405180830381865afa158015610a91573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ab59190611682565b15610b1a57610ae7838281518110610acf57610acf61161b565b60200260200101516005610dde90919063ffffffff16565b610b1a57610b18838281518110610b0057610b0061161b565b60200260200101516003610e0d90919063ffffffff16565b505b610b238161164a565b90506109d9565b505050565b60075460009060ff16610b4457506001610b52565b610b4f600385610dde565b90505b9392505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610bdf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b60606103776003610ed4565b610c6f610e2f565b610c7a600382610eb2565b50610c86600582610e0d565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527f337cd0f3f594112b6d830afb510072d3b08556b446514f73b8109162fd1151e19060200161095b565b610cd5610e2f565b805160078054602080850180517fffffffffffffffffffffff0000000000000000000000000000000000000000009093169415157fffffffffffffffffffffff0000000000000000000000000000000000000000ff81169590951761010073ffffffffffffffffffffffffffffffffffffffff9485160217909355604080519485529251909116908301527f0d22b8a99f411b3dd338c961284f608489ca0dab9cdad17366a343c361bcf80a910161095b565b60075460009060ff16610d9d57506000919050565b6104d2600583610dde565b60006103776003610dc8565b610dbc610e2f565b610dc581610ee1565b50565b60006104d2825490565b6000610b528383610fd6565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515610b52565b6000610b528373ffffffffffffffffffffffffffffffffffffffff8416611000565b60005473ffffffffffffffffffffffffffffffffffffffff163314610eb0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610bd6565b565b6000610b528373ffffffffffffffffffffffffffffffffffffffff841661104f565b60606000610b5283611142565b3373ffffffffffffffffffffffffffffffffffffffff821603610f60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610bd6565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000826000018281548110610fed57610fed61161b565b9060005260206000200154905092915050565b6000818152600183016020526040812054611047575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556104d2565b5060006104d2565b6000818152600183016020526040812054801561113857600061107360018361169f565b85549091506000906110879060019061169f565b90508181146110ec5760008660000182815481106110a7576110a761161b565b90600052602060002001549050808760000184815481106110ca576110ca61161b565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806110fd576110fd6116b2565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506104d2565b60009150506104d2565b60608160000180548060200260200160405190810160405280929190818152602001828054801561119257602002820191906000526020600020905b81548152602001906001019080831161117e575b50505050509050919050565b803567ffffffffffffffff811681146111b657600080fd5b919050565b600080604083850312156111ce57600080fd5b6111d78361119e565b91506111e56020840161119e565b90509250929050565b6020808252825182820181905260009190848201906040850190845b8181101561123c57835173ffffffffffffffffffffffffffffffffffffffff168352928401929184019160010161120a565b50909695505050505050565b600060208083528351808285015260005b8181101561127557858101830151858201604001528201611259565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b803573ffffffffffffffffffffffffffffffffffffffff811681146111b657600080fd5b600080600080600060a086880312156112f057600080fd5b6112f9866112b4565b9450611307602087016112b4565b93506040860135925060608601359150608086013560ff8116811461132b57600080fd5b809150509295509295909350565b60006020828403121561134b57600080fd5b610b52826112b4565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156113ca576113ca611354565b604052919050565b600060208083850312156113e557600080fd5b823567ffffffffffffffff808211156113fd57600080fd5b818501915085601f83011261141157600080fd5b81358181111561142357611423611354565b8060051b9150611434848301611383565b818152918301840191848101908884111561144e57600080fd5b938501935b8385101561147357611464856112b4565b82529385019390850190611453565b98975050505050505050565b60008060006040848603121561149457600080fd5b61149d846112b4565b9250602084013567ffffffffffffffff808211156114ba57600080fd5b818601915086601f8301126114ce57600080fd5b8135818111156114dd57600080fd5b8760208285010111156114ef57600080fd5b6020830194508093505050509250925092565b8015158114610dc557600080fd5b60006040828403121561152257600080fd5b6040516040810181811067ffffffffffffffff8211171561154557611545611354565b604052823561155381611502565b8152611561602084016112b4565b60208201529392505050565b6000806040838503121561158057600080fd5b611589836112b4565b91506111e5602084016112b4565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b67ffffffffffffffff8281168282160390808211156104d0576104d0611597565b67ffffffffffffffff8181168382160190808211156104d0576104d0611597565b808201808211156104d2576104d2611597565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361167b5761167b611597565b5060010190565b60006020828403121561169457600080fd5b8151610b5281611502565b818103818111156104d2576104d2611597565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfe46756e6374696f6e73205465726d73206f66205365727669636520416c6c6f77204c6973742076312e312e31a164736f6c6343000813000a", } var TermsOfServiceAllowListABI = TermsOfServiceAllowListMetaData.ABI var TermsOfServiceAllowListBin = TermsOfServiceAllowListMetaData.Bin -func DeployTermsOfServiceAllowList(auth *bind.TransactOpts, backend bind.ContractBackend, config TermsOfServiceAllowListConfig, initialAllowedSenders []common.Address, initialBlockedSenders []common.Address) (common.Address, *types.Transaction, *TermsOfServiceAllowList, error) { +func DeployTermsOfServiceAllowList(auth *bind.TransactOpts, backend bind.ContractBackend, config TermsOfServiceAllowListConfig, initialAllowedSenders []common.Address, initialBlockedSenders []common.Address, previousToSContract common.Address) (common.Address, *types.Transaction, *TermsOfServiceAllowList, error) { parsed, err := TermsOfServiceAllowListMetaData.GetAbi() if err != nil { return common.Address{}, nil, nil, err @@ -53,7 +53,7 @@ func DeployTermsOfServiceAllowList(auth *bind.TransactOpts, backend bind.Contrac return common.Address{}, nil, nil, errors.New("GetABI returned nil") } - address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(TermsOfServiceAllowListBin), backend, config, initialAllowedSenders, initialBlockedSenders) + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(TermsOfServiceAllowListBin), backend, config, initialAllowedSenders, initialBlockedSenders, previousToSContract) if err != nil { return common.Address{}, nil, nil, err } @@ -454,6 +454,18 @@ func (_TermsOfServiceAllowList *TermsOfServiceAllowListTransactorSession) BlockS return _TermsOfServiceAllowList.Contract.BlockSender(&_TermsOfServiceAllowList.TransactOpts, sender) } +func (_TermsOfServiceAllowList *TermsOfServiceAllowListTransactor) MigratePreviouslyAllowedSenders(opts *bind.TransactOpts, previousSendersToAdd []common.Address) (*types.Transaction, error) { + return _TermsOfServiceAllowList.contract.Transact(opts, "migratePreviouslyAllowedSenders", previousSendersToAdd) +} + +func (_TermsOfServiceAllowList *TermsOfServiceAllowListSession) MigratePreviouslyAllowedSenders(previousSendersToAdd []common.Address) (*types.Transaction, error) { + return _TermsOfServiceAllowList.Contract.MigratePreviouslyAllowedSenders(&_TermsOfServiceAllowList.TransactOpts, previousSendersToAdd) +} + +func (_TermsOfServiceAllowList *TermsOfServiceAllowListTransactorSession) MigratePreviouslyAllowedSenders(previousSendersToAdd []common.Address) (*types.Transaction, error) { + return _TermsOfServiceAllowList.Contract.MigratePreviouslyAllowedSenders(&_TermsOfServiceAllowList.TransactOpts, previousSendersToAdd) +} + func (_TermsOfServiceAllowList *TermsOfServiceAllowListTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { return _TermsOfServiceAllowList.contract.Transact(opts, "transferOwnership", to) } @@ -1307,6 +1319,8 @@ type TermsOfServiceAllowListInterface interface { BlockSender(opts *bind.TransactOpts, sender common.Address) (*types.Transaction, error) + MigratePreviouslyAllowedSenders(opts *bind.TransactOpts, previousSendersToAdd []common.Address) (*types.Transaction, error) + TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) UnblockSender(opts *bind.TransactOpts, sender common.Address) (*types.Transaction, error) diff --git a/core/gethwrappers/functions/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/functions/generation/generated-wrapper-dependency-versions-do-not-edit.txt index 83ea4d13b6..5153e4055f 100644 --- a/core/gethwrappers/functions/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/functions/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -1,6 +1,6 @@ GETH_VERSION: 1.13.8 functions: ../../../contracts/solc/v0.8.19/functions/v1_X/FunctionsRequest.abi ../../../contracts/solc/v0.8.19/functions/v1_X/FunctionsRequest.bin 3c972870b0afeb6d73a29ebb182f24956a2cebb127b21c4f867d1ecf19a762db -functions_allow_list: ../../../contracts/solc/v0.8.19/functions/v1_X/TermsOfServiceAllowList.abi ../../../contracts/solc/v0.8.19/functions/v1_X/TermsOfServiceAllowList.bin 268de8b3c061b53a1a2a1ccc0149eff68545959e29cd41b5f2e9f5dab19075cf +functions_allow_list: ../../../contracts/solc/v0.8.19/functions/v1_X/TermsOfServiceAllowList.abi ../../../contracts/solc/v0.8.19/functions/v1_X/TermsOfServiceAllowList.bin 6581a3e82c8a6b5532addb8278ff520d18f38c2be4ac07ed0ad9ccc2e6825e48 functions_billing_registry_events_mock: ../../../contracts/solc/v0.8.6/functions/v0_0_0/FunctionsBillingRegistryEventsMock.abi ../../../contracts/solc/v0.8.6/functions/v0_0_0/FunctionsBillingRegistryEventsMock.bin 50deeb883bd9c3729702be335c0388f9d8553bab4be5e26ecacac496a89e2b77 functions_client: ../../../contracts/solc/v0.8.19/functions/v1_X/FunctionsClient.abi ../../../contracts/solc/v0.8.19/functions/v1_X/FunctionsClient.bin 2368f537a04489c720a46733f8596c4fc88a31062ecfa966d05f25dd98608aca functions_client_example: ../../../contracts/solc/v0.8.19/functions/v1_X/FunctionsClientExample.abi ../../../contracts/solc/v0.8.19/functions/v1_X/FunctionsClientExample.bin abf32e69f268f40e8530eb8d8e96bf310b798a4c0049a58022d9d2fb527b601b diff --git a/core/services/ocr2/plugins/functions/integration_tests/v1/internal/testutils.go b/core/services/ocr2/plugins/functions/integration_tests/v1/internal/testutils.go index 6d704b50f9..ef81028f20 100644 --- a/core/services/ocr2/plugins/functions/integration_tests/v1/internal/testutils.go +++ b/core/services/ocr2/plugins/functions/integration_tests/v1/internal/testutils.go @@ -217,7 +217,9 @@ func StartNewChainWithContracts(t *testing.T, nClients int) (*bind.TransactOpts, } var initialAllowedSenders []common.Address var initialBlockedSenders []common.Address - allowListAddress, _, allowListContract, err := functions_allow_list.DeployTermsOfServiceAllowList(owner, b, allowListConfig, initialAllowedSenders, initialBlockedSenders) + // The allowlist requires a pointer to the previous allowlist. If none exists, use the null address. + var nullPreviousAllowlist common.Address + allowListAddress, _, allowListContract, err := functions_allow_list.DeployTermsOfServiceAllowList(owner, b, allowListConfig, initialAllowedSenders, initialBlockedSenders, nullPreviousAllowlist) require.NoError(t, err) // Deploy Coordinator contract (matches updateConfig() in FunctionsBilling.sol) From 27d9c71b196961666de87bc3128d31f3c22fb3fa Mon Sep 17 00:00:00 2001 From: Christopher Dimitri Sastropranoto Date: Mon, 29 Jul 2024 16:57:36 +0700 Subject: [PATCH 013/115] KS-391: Capabilities Registry Fixes (#13937) * prevent malicious a node operator from taking over another node belonging to another node operator * prevent malicious node operator from becoming the admin for another node operator --- .changeset/bright-readers-dress.md | 5 +++++ contracts/.changeset/chatty-feet-clean.md | 5 +++++ .../src/v0.8/keystone/CapabilitiesRegistry.sol | 9 +++++---- ...itiesRegistry_UpdateNodeOperatorsTest.t.sol | 5 +---- .../CapabilitiesRegistry_UpdateNodesTest.t.sol | 18 ++++++++++++++++++ .../capabilities_registry.go | 2 +- ...wrapper-dependency-versions-do-not-edit.txt | 2 +- 7 files changed, 36 insertions(+), 10 deletions(-) create mode 100644 .changeset/bright-readers-dress.md create mode 100644 contracts/.changeset/chatty-feet-clean.md diff --git a/.changeset/bright-readers-dress.md b/.changeset/bright-readers-dress.md new file mode 100644 index 0000000000..ac26fbeb4e --- /dev/null +++ b/.changeset/bright-readers-dress.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#internal address security vulnerabilities around updating nodes and node operators on capabilities registry diff --git a/contracts/.changeset/chatty-feet-clean.md b/contracts/.changeset/chatty-feet-clean.md new file mode 100644 index 0000000000..161bfee8ac --- /dev/null +++ b/contracts/.changeset/chatty-feet-clean.md @@ -0,0 +1,5 @@ +--- +'@chainlink/contracts': patch +--- + +#internal address security vulnerabilities around updating nodes and node operators on capabilities registry diff --git a/contracts/src/v0.8/keystone/CapabilitiesRegistry.sol b/contracts/src/v0.8/keystone/CapabilitiesRegistry.sol index 6b150dc5d7..ba61584d0a 100644 --- a/contracts/src/v0.8/keystone/CapabilitiesRegistry.sol +++ b/contracts/src/v0.8/keystone/CapabilitiesRegistry.sol @@ -502,7 +502,7 @@ contract CapabilitiesRegistry is OwnerIsCreator, TypeAndVersionInterface { NodeOperator memory nodeOperator = nodeOperators[i]; if (nodeOperator.admin == address(0)) revert InvalidNodeOperatorAdmin(); - if (msg.sender != nodeOperator.admin && msg.sender != owner) revert AccessForbidden(msg.sender); + if (msg.sender != currentNodeOperator.admin && msg.sender != owner) revert AccessForbidden(msg.sender); if ( currentNodeOperator.admin != nodeOperator.admin || @@ -611,11 +611,12 @@ contract CapabilitiesRegistry is OwnerIsCreator, TypeAndVersionInterface { bool isOwner = msg.sender == owner(); for (uint256 i; i < nodes.length; ++i) { NodeParams memory node = nodes[i]; - NodeOperator memory nodeOperator = s_nodeOperators[node.nodeOperatorId]; - if (!isOwner && msg.sender != nodeOperator.admin) revert AccessForbidden(msg.sender); - Node storage storedNode = s_nodes[node.p2pId]; + NodeOperator memory nodeOperator = s_nodeOperators[storedNode.nodeOperatorId]; + if (storedNode.signer == bytes32("")) revert NodeDoesNotExist(node.p2pId); + if (!isOwner && msg.sender != nodeOperator.admin) revert AccessForbidden(msg.sender); + if (node.signer == bytes32("")) revert InvalidNodeSigner(); bytes32 previousSigner = storedNode.signer; diff --git a/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_UpdateNodeOperatorsTest.t.sol b/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_UpdateNodeOperatorsTest.t.sol index e0d1742c98..721fd35eae 100644 --- a/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_UpdateNodeOperatorsTest.t.sol +++ b/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_UpdateNodeOperatorsTest.t.sol @@ -19,10 +19,7 @@ contract CapabilitiesRegistry_UpdateNodeOperatorTest is BaseTest { changePrank(STRANGER); CapabilitiesRegistry.NodeOperator[] memory nodeOperators = new CapabilitiesRegistry.NodeOperator[](1); - nodeOperators[0] = CapabilitiesRegistry.NodeOperator({ - admin: NEW_NODE_OPERATOR_ADMIN, - name: NEW_NODE_OPERATOR_NAME - }); + nodeOperators[0] = CapabilitiesRegistry.NodeOperator({admin: ADMIN, name: NEW_NODE_OPERATOR_NAME}); uint32[] memory nodeOperatorIds = new uint32[](1); nodeOperatorIds[0] = TEST_NODE_OPERATOR_ID; diff --git a/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_UpdateNodesTest.t.sol b/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_UpdateNodesTest.t.sol index 43c6adc35b..9b516767f2 100644 --- a/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_UpdateNodesTest.t.sol +++ b/contracts/src/v0.8/keystone/test/CapabilitiesRegistry_UpdateNodesTest.t.sol @@ -59,6 +59,24 @@ contract CapabilitiesRegistry_UpdateNodesTest is BaseTest { s_CapabilitiesRegistry.updateNodes(nodes); } + function test_RevertWhen_CalledByAnotherNodeOperatorAdmin() public { + changePrank(NODE_OPERATOR_TWO_ADMIN); + CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); + + bytes32[] memory hashedCapabilityIds = new bytes32[](1); + hashedCapabilityIds[0] = s_basicHashedCapabilityId; + + nodes[0] = CapabilitiesRegistry.NodeParams({ + nodeOperatorId: TEST_NODE_OPERATOR_TWO_ID, + p2pId: P2P_ID, + signer: NEW_NODE_SIGNER, + hashedCapabilityIds: hashedCapabilityIds + }); + + vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.AccessForbidden.selector, NODE_OPERATOR_TWO_ADMIN)); + s_CapabilitiesRegistry.updateNodes(nodes); + } + function test_RevertWhen_NodeDoesNotExist() public { changePrank(NODE_OPERATOR_ONE_ADMIN); CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); diff --git a/core/gethwrappers/keystone/generated/capabilities_registry/capabilities_registry.go b/core/gethwrappers/keystone/generated/capabilities_registry/capabilities_registry.go index bb92001085..c345a86569 100644 --- a/core/gethwrappers/keystone/generated/capabilities_registry/capabilities_registry.go +++ b/core/gethwrappers/keystone/generated/capabilities_registry/capabilities_registry.go @@ -87,7 +87,7 @@ type CapabilitiesRegistryNodeParams struct { var CapabilitiesRegistryMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"AccessForbidden\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityIsDeprecated\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"}],\"name\":\"CapabilityRequiredByDON\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"}],\"name\":\"DONDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"}],\"name\":\"DuplicateDONCapability\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"nodeP2PId\",\"type\":\"bytes32\"}],\"name\":\"DuplicateDONNode\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"proposedConfigurationContract\",\"type\":\"address\"}],\"name\":\"InvalidCapabilityConfigurationContractInterface\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"nodeCount\",\"type\":\"uint256\"}],\"name\":\"InvalidFaultTolerance\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"hashedCapabilityIds\",\"type\":\"bytes32[]\"}],\"name\":\"InvalidNodeCapabilities\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidNodeOperatorAdmin\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"}],\"name\":\"InvalidNodeP2PId\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidNodeSigner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"lengthOne\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"lengthTwo\",\"type\":\"uint256\"}],\"name\":\"LengthMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"nodeP2PId\",\"type\":\"bytes32\"}],\"name\":\"NodeAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"nodeP2PId\",\"type\":\"bytes32\"}],\"name\":\"NodeDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"nodeP2PId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"}],\"name\":\"NodeDoesNotSupportCapability\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"}],\"name\":\"NodeOperatorDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"nodeP2PId\",\"type\":\"bytes32\"}],\"name\":\"NodePartOfCapabilitiesDON\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"nodeP2PId\",\"type\":\"bytes32\"}],\"name\":\"NodePartOfWorkflowDON\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityConfigured\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityDeprecated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"signer\",\"type\":\"bytes32\"}],\"name\":\"NodeAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"NodeOperatorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"}],\"name\":\"NodeOperatorRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"name\":\"NodeOperatorUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"}],\"name\":\"NodeRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"signer\",\"type\":\"bytes32\"}],\"name\":\"NodeUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"labelledName\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"version\",\"type\":\"string\"},{\"internalType\":\"enumCapabilitiesRegistry.CapabilityType\",\"name\":\"capabilityType\",\"type\":\"uint8\"},{\"internalType\":\"enumCapabilitiesRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"}],\"internalType\":\"structCapabilitiesRegistry.Capability[]\",\"name\":\"capabilities\",\"type\":\"tuple[]\"}],\"name\":\"addCapabilities\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"nodes\",\"type\":\"bytes32[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"internalType\":\"structCapabilitiesRegistry.CapabilityConfiguration[]\",\"name\":\"capabilityConfigurations\",\"type\":\"tuple[]\"},{\"internalType\":\"bool\",\"name\":\"isPublic\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"acceptsWorkflows\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"}],\"name\":\"addDON\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilitiesRegistry.NodeOperator[]\",\"name\":\"nodeOperators\",\"type\":\"tuple[]\"}],\"name\":\"addNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"signer\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32[]\",\"name\":\"hashedCapabilityIds\",\"type\":\"bytes32[]\"}],\"internalType\":\"structCapabilitiesRegistry.NodeParams[]\",\"name\":\"nodes\",\"type\":\"tuple[]\"}],\"name\":\"addNodes\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"hashedCapabilityIds\",\"type\":\"bytes32[]\"}],\"name\":\"deprecateCapabilities\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCapabilities\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"hashedId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"labelledName\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"version\",\"type\":\"string\"},{\"internalType\":\"enumCapabilitiesRegistry.CapabilityType\",\"name\":\"capabilityType\",\"type\":\"uint8\"},{\"internalType\":\"enumCapabilitiesRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isDeprecated\",\"type\":\"bool\"}],\"internalType\":\"structCapabilitiesRegistry.CapabilityInfo[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedId\",\"type\":\"bytes32\"}],\"name\":\"getCapability\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"hashedId\",\"type\":\"bytes32\"},{\"internalType\":\"string\",\"name\":\"labelledName\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"version\",\"type\":\"string\"},{\"internalType\":\"enumCapabilitiesRegistry.CapabilityType\",\"name\":\"capabilityType\",\"type\":\"uint8\"},{\"internalType\":\"enumCapabilitiesRegistry.CapabilityResponseType\",\"name\":\"responseType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"configurationContract\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isDeprecated\",\"type\":\"bool\"}],\"internalType\":\"structCapabilitiesRegistry.CapabilityInfo\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"}],\"name\":\"getCapabilityConfigs\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"}],\"name\":\"getDON\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"id\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isPublic\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"acceptsWorkflows\",\"type\":\"bool\"},{\"internalType\":\"bytes32[]\",\"name\":\"nodeP2PIds\",\"type\":\"bytes32[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"internalType\":\"structCapabilitiesRegistry.CapabilityConfiguration[]\",\"name\":\"capabilityConfigurations\",\"type\":\"tuple[]\"}],\"internalType\":\"structCapabilitiesRegistry.DONInfo\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDONs\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"id\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isPublic\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"acceptsWorkflows\",\"type\":\"bool\"},{\"internalType\":\"bytes32[]\",\"name\":\"nodeP2PIds\",\"type\":\"bytes32[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"internalType\":\"structCapabilitiesRegistry.CapabilityConfiguration[]\",\"name\":\"capabilityConfigurations\",\"type\":\"tuple[]\"}],\"internalType\":\"structCapabilitiesRegistry.DONInfo[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"labelledName\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"version\",\"type\":\"string\"}],\"name\":\"getHashedCapabilityId\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"}],\"name\":\"getNode\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"workflowDONId\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"signer\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32[]\",\"name\":\"hashedCapabilityIds\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256[]\",\"name\":\"capabilitiesDONIds\",\"type\":\"uint256[]\"}],\"internalType\":\"structCapabilitiesRegistry.NodeInfo\",\"name\":\"nodeInfo\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"}],\"name\":\"getNodeOperator\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilitiesRegistry.NodeOperator\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNodeOperators\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilitiesRegistry.NodeOperator[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNodes\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"workflowDONId\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"signer\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32[]\",\"name\":\"hashedCapabilityIds\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256[]\",\"name\":\"capabilitiesDONIds\",\"type\":\"uint256[]\"}],\"internalType\":\"structCapabilitiesRegistry.NodeInfo[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hashedCapabilityId\",\"type\":\"bytes32\"}],\"name\":\"isCapabilityDeprecated\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32[]\",\"name\":\"donIds\",\"type\":\"uint32[]\"}],\"name\":\"removeDONs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32[]\",\"name\":\"nodeOperatorIds\",\"type\":\"uint32[]\"}],\"name\":\"removeNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"removedNodeP2PIds\",\"type\":\"bytes32[]\"}],\"name\":\"removeNodes\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"bytes32[]\",\"name\":\"nodes\",\"type\":\"bytes32[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"internalType\":\"structCapabilitiesRegistry.CapabilityConfiguration[]\",\"name\":\"capabilityConfigurations\",\"type\":\"tuple[]\"},{\"internalType\":\"bool\",\"name\":\"isPublic\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"acceptsWorkflows\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"}],\"name\":\"updateDON\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32[]\",\"name\":\"nodeOperatorIds\",\"type\":\"uint32[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"}],\"internalType\":\"structCapabilitiesRegistry.NodeOperator[]\",\"name\":\"nodeOperators\",\"type\":\"tuple[]\"}],\"name\":\"updateNodeOperators\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"nodeOperatorId\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"signer\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32[]\",\"name\":\"hashedCapabilityIds\",\"type\":\"bytes32[]\"}],\"internalType\":\"structCapabilitiesRegistry.NodeParams[]\",\"name\":\"nodes\",\"type\":\"tuple[]\"}],\"name\":\"updateNodes\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x6080604052600e80546001600160401b0319166401000000011790553480156200002857600080fd5b503380600081620000805760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000b357620000b381620000bc565b50505062000167565b336001600160a01b03821603620001165760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000077565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6150f680620001776000396000f3fe608060405234801561001057600080fd5b50600436106101ae5760003560e01c80635e65e309116100ee5780638da5cb5b11610097578063d8bc7b6811610071578063d8bc7b68146103f6578063ddbe4f8214610409578063e29581aa1461041e578063f2fde38b1461043357600080fd5b80638da5cb5b1461039b5780639cb7c5f4146103c3578063d59a79f6146103e357600080fd5b806373ac22b4116100c857806373ac22b41461036d57806379ba50971461038057806386fa42461461038857600080fd5b80635e65e3091461033257806366acaa3314610345578063715f52951461035a57600080fd5b8063235374051161015b578063398f377311610135578063398f3773146102cb5780633f2a13c9146102de57806350c946fe146102ff5780635d83d9671461031f57600080fd5b80632353740514610285578063275459f2146102a55780632c01a1e8146102b857600080fd5b80631d05394c1161018c5780631d05394c1461023b578063214502431461025057806322bdbcbc1461026557600080fd5b80630fe5800a146101b357806312570011146101d9578063181f5a77146101fc575b600080fd5b6101c66101c1366004613e8b565b610446565b6040519081526020015b60405180910390f35b6101ec6101e7366004613eef565b61047a565b60405190151581526020016101d0565b604080518082018252601a81527f4361706162696c6974696573526567697374727920312e302e30000000000000602082015290516101d09190613f76565b61024e610249366004613fce565b610487565b005b61025861069c565b6040516101d09190614150565b6102786102733660046141eb565b6107f9565b6040516101d09190614243565b6102986102933660046141eb565b6108e6565b6040516101d09190614256565b61024e6102b3366004613fce565b61092a565b61024e6102c6366004613fce565b610a01565b61024e6102d9366004613fce565b610c9d565b6102f16102ec366004614269565b610e5c565b6040516101d0929190614293565b61031261030d366004613eef565b611048565b6040516101d09190614358565b61024e61032d366004613fce565b611122565b61024e610340366004613fce565b611217565b61034d61193f565b6040516101d0919061436b565b61024e610368366004613fce565b611b22565b61024e61037b366004613fce565b611bd4565b61024e6120a2565b61024e6103963660046143e0565b61219f565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101d0565b6103d66103d1366004613eef565b6124df565b6040516101d0919061452f565b61024e6103f1366004614561565b61271a565b61024e610404366004614616565b6127e3565b6104116128ad565b6040516101d091906146bb565b6104266129a1565b6040516101d09190614730565b61024e6104413660046147c9565b612aaa565b6000828260405160200161045b929190614293565b6040516020818303038152906040528051906020012090505b92915050565b6000610474600583612abe565b61048f612ad9565b60005b818110156106975760008383838181106104ae576104ae6147e4565b90506020020160208101906104c391906141eb565b63ffffffff8181166000908152600d60209081526040808320805464010000000081049095168085526001820190935290832094955093909290916a010000000000000000000090910460ff16905b61051b83612b5c565b8110156105bb57811561057157600c60006105368584612b66565b8152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff1690556105b3565b6105b18663ffffffff16600c60006105928588612b6690919063ffffffff16565b8152602001908152602001600020600401612b7290919063ffffffff16565b505b600101610512565b508354640100000000900463ffffffff16600003610612576040517f2b62be9b00000000000000000000000000000000000000000000000000000000815263ffffffff861660048201526024015b60405180910390fd5b63ffffffff85166000818152600d6020908152604080832080547fffffffffffffffffffffffffffffffffffffffffff00000000000000000000001690558051938452908301919091527ff264aae70bf6a9d90e68e0f9b393f4e7fbea67b063b0f336e0b36c1581703651910160405180910390a15050505050806001019050610492565b505050565b600e54606090640100000000900463ffffffff1660006106bd600183614842565b63ffffffff1667ffffffffffffffff8111156106db576106db613d25565b60405190808252806020026020018201604052801561076257816020015b6040805160e081018252600080825260208083018290529282018190526060808301829052608083019190915260a0820181905260c082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816106f95790505b509050600060015b8363ffffffff168163ffffffff1610156107d65763ffffffff8082166000908152600d602052604090205416156107ce576107a481612b7e565b8383815181106107b6576107b66147e4565b6020026020010181905250816107cb9061485f565b91505b60010161076a565b506107e2600184614842565b63ffffffff1681146107f2578082525b5092915050565b60408051808201909152600081526060602082015263ffffffff82166000908152600b60209081526040918290208251808401909352805473ffffffffffffffffffffffffffffffffffffffff168352600181018054919284019161085d90614897565b80601f016020809104026020016040519081016040528092919081815260200182805461088990614897565b80156108d65780601f106108ab576101008083540402835291602001916108d6565b820191906000526020600020905b8154815290600101906020018083116108b957829003601f168201915b5050505050815250509050919050565b6040805160e0810182526000808252602082018190529181018290526060808201839052608082019290925260a0810182905260c081019190915261047482612b7e565b610932612ad9565b60005b63ffffffff811682111561069757600083838363ffffffff1681811061095d5761095d6147e4565b905060200201602081019061097291906141eb565b63ffffffff81166000908152600b6020526040812080547fffffffffffffffffffffffff00000000000000000000000000000000000000001681559192506109bd6001830182613cb8565b505060405163ffffffff8216907fa59268ca81d40429e65ccea5385b59cf2d3fc6519371dee92f8eb1dae5107a7a90600090a2506109fa816148ea565b9050610935565b6000805473ffffffffffffffffffffffffffffffffffffffff163314905b82811015610c97576000848483818110610a3b57610a3b6147e4565b602090810292909201356000818152600c90935260409092206001810154929350919050610a98576040517fd82f6adb00000000000000000000000000000000000000000000000000000000815260048101839052602401610609565b6000610aa682600401612b5c565b1115610afb57610ab96004820184612b66565b6040517f60a6d89800000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015260248101839052604401610609565b805468010000000000000000900463ffffffff1615610b635780546040517f60b9df730000000000000000000000000000000000000000000000000000000081526801000000000000000090910463ffffffff16600482015260248101839052604401610609565b83158015610b9d5750805463ffffffff166000908152600b602052604090205473ffffffffffffffffffffffffffffffffffffffff163314155b15610bd6576040517f9473075d000000000000000000000000000000000000000000000000000000008152336004820152602401610609565b6001810154610be790600790612b72565b506002810154610bf990600990612b72565b506000828152600c6020526040812080547fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016815560018101829055600281018290559060048201818181610c4e8282613cf2565b5050505050507f5254e609a97bab37b7cc79fe128f85c097bd6015c6e1624ae0ba392eb975320582604051610c8591815260200190565b60405180910390a15050600101610a1f565b50505050565b610ca5612ad9565b60005b81811015610697576000838383818110610cc457610cc46147e4565b9050602002810190610cd6919061490d565b610cdf9061494b565b805190915073ffffffffffffffffffffffffffffffffffffffff16610d30576040517feeacd93900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600e54604080518082018252835173ffffffffffffffffffffffffffffffffffffffff908116825260208086015181840190815263ffffffff9095166000818152600b909252939020825181547fffffffffffffffffffffffff00000000000000000000000000000000000000001692169190911781559251919290916001820190610dbc9082614a05565b5050600e8054909150600090610dd79063ffffffff166148ea565b91906101000a81548163ffffffff021916908363ffffffff160217905550816000015173ffffffffffffffffffffffffffffffffffffffff168163ffffffff167f78e94ca80be2c30abc061b99e7eb8583b1254781734b1e3ce339abb57da2fe8e8460200151604051610e4a9190613f76565b60405180910390a35050600101610ca8565b63ffffffff8083166000908152600d60209081526040808320805464010000000090049094168084526001909401825280832085845260030190915281208054606093849390929091610eae90614897565b80601f0160208091040260200160405190810160405280929190818152602001828054610eda90614897565b8015610f275780601f10610efc57610100808354040283529160200191610f27565b820191906000526020600020905b815481529060010190602001808311610f0a57829003601f168201915b5050506000888152600260208190526040909120015492935060609262010000900473ffffffffffffffffffffffffffffffffffffffff1615915061103a905057600086815260026020819052604091829020015490517f8318ed5d00000000000000000000000000000000000000000000000000000000815263ffffffff891660048201526201000090910473ffffffffffffffffffffffffffffffffffffffff1690638318ed5d90602401600060405180830381865afa158015610ff1573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526110379190810190614b1f565b90505b9093509150505b9250929050565b6040805160e0810182526000808252602082018190529181018290526060808201839052608082019290925260a0810182905260c08101919091526040805160e0810182526000848152600c6020908152838220805463ffffffff8082168652640100000000820481168487018190526801000000000000000090920416858701526001820154606086015260028201546080860152835260030190529190912060a08201906110f790612e49565b815260200161111a600c6000868152602001908152602001600020600401612e49565b905292915050565b61112a612ad9565b60005b81811015610697576000838383818110611149576111496147e4565b905060200201359050611166816003612abe90919063ffffffff16565b61119f576040517fe181733f00000000000000000000000000000000000000000000000000000000815260048101829052602401610609565b6111aa600582612e56565b6111e3576040517ff7d7a29400000000000000000000000000000000000000000000000000000000815260048101829052602401610609565b60405181907fdcea1b78b6ddc31592a94607d537543fcaafda6cc52d6d5cc7bbfca1422baf2190600090a25060010161112d565b6000805473ffffffffffffffffffffffffffffffffffffffff163314905b82811015610c97576000848483818110611251576112516147e4565b90506020028101906112639190614b8d565b61126c90614bc1565b805163ffffffff166000908152600b602090815260408083208151808301909252805473ffffffffffffffffffffffffffffffffffffffff1682526001810180549596509394919390928401916112c290614897565b80601f01602080910402602001604051908101604052809291908181526020018280546112ee90614897565b801561133b5780601f106113105761010080835404028352916020019161133b565b820191906000526020600020905b81548152906001019060200180831161131e57829003601f168201915b50505050508152505090508315801561136b5750805173ffffffffffffffffffffffffffffffffffffffff163314155b156113a4576040517f9473075d000000000000000000000000000000000000000000000000000000008152336004820152602401610609565b6040808301516000908152600c6020522060018101546113f85782604001516040517fd82f6adb00000000000000000000000000000000000000000000000000000000815260040161060991815260200190565b6020830151611433576040517f8377314600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001810154602084015181146114b457602084015161145490600790612abe565b1561148b576040517f8377314600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602084015160018301556114a0600782612b72565b5060208401516114b290600790612e56565b505b606084015180516000036114f657806040517f3748d4c60000000000000000000000000000000000000000000000000000000081526004016106099190614c94565b8254600090849060049061151790640100000000900463ffffffff166148ea565b91906101000a81548163ffffffff021916908363ffffffff1602179055905060005b82518110156115fc5761156f838281518110611557576115576147e4565b60200260200101516003612abe90919063ffffffff16565b6115a757826040517f3748d4c60000000000000000000000000000000000000000000000000000000081526004016106099190614c94565b6115f38382815181106115bc576115bc6147e4565b60200260200101518660030160008563ffffffff1663ffffffff168152602001908152602001600020612e5690919063ffffffff16565b50600101611539565b50835468010000000000000000900463ffffffff16801561175d5763ffffffff8082166000908152600d60209081526040808320805464010000000090049094168352600190930181528282206002018054845181840281018401909552808552929392909183018282801561169157602002820191906000526020600020905b81548152602001906001019080831161167d575b5050505050905060005b815181101561175a576116f08282815181106116b9576116b96147e4565b60200260200101518860030160008763ffffffff1663ffffffff168152602001908152602001600020612abe90919063ffffffff16565b61175257818181518110611706576117066147e4565b6020026020010151836040517f03dcd86200000000000000000000000000000000000000000000000000000000815260040161060992919091825263ffffffff16602082015260400190565b60010161169b565b50505b600061176b86600401612e49565b905060005b81518163ffffffff1610156118b1576000828263ffffffff1681518110611799576117996147e4565b60209081029190910181015163ffffffff8082166000908152600d8452604080822080546401000000009004909316825260019092018452818120600201805483518187028101870190945280845293955090939192909183018282801561182057602002820191906000526020600020905b81548152602001906001019080831161180c575b5050505050905060005b815181101561189d5761187f828281518110611848576118486147e4565b60200260200101518b60030160008a63ffffffff1663ffffffff168152602001908152602001600020612abe90919063ffffffff16565b61189557818181518110611706576117066147e4565b60010161182a565b505050806118aa906148ea565b9050611770565b50875186547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff90911690811787556040808a0151600289018190556020808c01518351928352908201527f4b5b465e22eea0c3d40c30e936643245b80d19b2dcf75788c0699fe8d8db645b910160405180910390a25050505050505050806001019050611235565b600e5460609063ffffffff166000611958600183614842565b63ffffffff1667ffffffffffffffff81111561197657611976613d25565b6040519080825280602002602001820160405280156119bc57816020015b6040805180820190915260008152606060208201528152602001906001900390816119945790505b509050600060015b8363ffffffff168163ffffffff161015611b0c5763ffffffff81166000908152600b602052604090205473ffffffffffffffffffffffffffffffffffffffff1615611b045763ffffffff81166000908152600b60209081526040918290208251808401909352805473ffffffffffffffffffffffffffffffffffffffff1683526001810180549192840191611a5890614897565b80601f0160208091040260200160405190810160405280929190818152602001828054611a8490614897565b8015611ad15780601f10611aa657610100808354040283529160200191611ad1565b820191906000526020600020905b815481529060010190602001808311611ab457829003601f168201915b505050505081525050838381518110611aec57611aec6147e4565b602002602001018190525081611b019061485f565b91505b6001016119c4565b50600e546107e29060019063ffffffff16614842565b611b2a612ad9565b60005b81811015610697576000838383818110611b4957611b496147e4565b9050602002810190611b5b9190614cd8565b611b6490614d1b565b90506000611b7a82600001518360200151610446565b9050611b87600382612e56565b611bc0576040517febf5255100000000000000000000000000000000000000000000000000000000815260048101829052602401610609565b611bca8183612e62565b5050600101611b2d565b6000805473ffffffffffffffffffffffffffffffffffffffff163314905b82811015610c97576000848483818110611c0e57611c0e6147e4565b9050602002810190611c209190614b8d565b611c2990614bc1565b805163ffffffff166000908152600b602090815260408083208151808301909252805473ffffffffffffffffffffffffffffffffffffffff168252600181018054959650939491939092840191611c7f90614897565b80601f0160208091040260200160405190810160405280929190818152602001828054611cab90614897565b8015611cf85780601f10611ccd57610100808354040283529160200191611cf8565b820191906000526020600020905b815481529060010190602001808311611cdb57829003601f168201915b50505091909252505081519192505073ffffffffffffffffffffffffffffffffffffffff16611d5e5781516040517fadd9ae1e00000000000000000000000000000000000000000000000000000000815263ffffffff9091166004820152602401610609565b83158015611d835750805173ffffffffffffffffffffffffffffffffffffffff163314155b15611dbc576040517f9473075d000000000000000000000000000000000000000000000000000000008152336004820152602401610609565b6040808301516000908152600c60205220600181015415611e115782604001516040517f5461848300000000000000000000000000000000000000000000000000000000815260040161060991815260200190565b6040830151611e545782604001516040517f64e2ee9200000000000000000000000000000000000000000000000000000000815260040161060991815260200190565b60208301511580611e7157506020830151611e7190600790612abe565b15611ea8576040517f8377314600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60608301518051600003611eea57806040517f3748d4c60000000000000000000000000000000000000000000000000000000081526004016106099190614c94565b81548290600490611f0890640100000000900463ffffffff166148ea565b82546101009290920a63ffffffff818102199093169183160217909155825464010000000090041660005b8251811015611fde57611f51838281518110611557576115576147e4565b611f8957826040517f3748d4c60000000000000000000000000000000000000000000000000000000081526004016106099190614c94565b611fd5838281518110611f9e57611f9e6147e4565b60200260200101518560030160008563ffffffff1663ffffffff168152602001908152602001600020612e5690919063ffffffff16565b50600101611f33565b50845183547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff918216178455604086015160028501556020860151600185018190556120349160079190612e5616565b50604085015161204690600990612e56565b50845160408087015160208089015183519283529082015263ffffffff909216917f74becb12a5e8fd0e98077d02dfba8f647c9670c9df177e42c2418cf17a636f05910160405180910390a25050505050806001019050611bf2565b60015473ffffffffffffffffffffffffffffffffffffffff163314612123576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610609565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b8281146121e2576040517fab8b67c60000000000000000000000000000000000000000000000000000000081526004810184905260248101829052604401610609565b6000805473ffffffffffffffffffffffffffffffffffffffff16905b848110156124d757600086868381811061221a5761221a6147e4565b905060200201602081019061222f91906141eb565b63ffffffff81166000908152600b6020526040902080549192509073ffffffffffffffffffffffffffffffffffffffff1661229e576040517fadd9ae1e00000000000000000000000000000000000000000000000000000000815263ffffffff83166004820152602401610609565b60008686858181106122b2576122b26147e4565b90506020028101906122c4919061490d565b6122cd9061494b565b805190915073ffffffffffffffffffffffffffffffffffffffff1661231e576040517feeacd93900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805173ffffffffffffffffffffffffffffffffffffffff16331480159061235b57503373ffffffffffffffffffffffffffffffffffffffff861614155b15612394576040517f9473075d000000000000000000000000000000000000000000000000000000008152336004820152602401610609565b8051825473ffffffffffffffffffffffffffffffffffffffff908116911614158061241057506020808201516040516123cd9201613f76565b60405160208183030381529060405280519060200120826001016040516020016123f79190614dc1565b6040516020818303038152906040528051906020012014155b156124c957805182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9091161782556020810151600183019061246a9082614a05565b50806000015173ffffffffffffffffffffffffffffffffffffffff168363ffffffff167f86f41145bde5dd7f523305452e4aad3685508c181432ec733d5f345009358a2883602001516040516124c09190613f76565b60405180910390a35b5050508060010190506121fe565b505050505050565b6125206040805160e0810182526000808252606060208301819052928201839052909182019081526020016000815260006020820181905260409091015290565b6040805160e0810182528381526000848152600260209081529290208054919283019161254c90614897565b80601f016020809104026020016040519081016040528092919081815260200182805461257890614897565b80156125c55780601f1061259a576101008083540402835291602001916125c5565b820191906000526020600020905b8154815290600101906020018083116125a857829003601f168201915b505050505081526020016002600085815260200190815260200160002060010180546125f090614897565b80601f016020809104026020016040519081016040528092919081815260200182805461261c90614897565b80156126695780601f1061263e57610100808354040283529160200191612669565b820191906000526020600020905b81548152906001019060200180831161264c57829003601f168201915b50505091835250506000848152600260208181526040909220015491019060ff16600381111561269b5761269b61444c565b815260008481526002602081815260409092200154910190610100900460ff1660018111156126cc576126cc61444c565b81526000848152600260208181526040928390209091015462010000900473ffffffffffffffffffffffffffffffffffffffff169083015201612710600585612abe565b1515905292915050565b612722612ad9565b63ffffffff8089166000908152600d6020526040812054640100000000900490911690819003612786576040517f2b62be9b00000000000000000000000000000000000000000000000000000000815263ffffffff8a166004820152602401610609565b6127d8888888886040518060a001604052808f63ffffffff168152602001876127ae906148ea565b97508763ffffffff1681526020018a1515815260200189151581526020018860ff168152506130f6565b505050505050505050565b6127eb612ad9565b600e805460009164010000000090910463ffffffff1690600461280d836148ea565b82546101009290920a63ffffffff81810219909316918316021790915581166000818152600d602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001684179055815160a08101835292835260019083015286151590820152841515606082015260ff841660808201529091506128a39089908990899089906130f6565b5050505050505050565b606060006128bb6003612e49565b90506000815167ffffffffffffffff8111156128d9576128d9613d25565b60405190808252806020026020018201604052801561294b57816020015b6129386040805160e0810182526000808252606060208301819052928201839052909182019081526020016000815260006020820181905260409091015290565b8152602001906001900390816128f75790505b50905060005b82518110156107f25761297c83828151811061296f5761296f6147e4565b60200260200101516124df565b82828151811061298e5761298e6147e4565b6020908102919091010152600101612951565b606060006129af6009612e49565b90506000815167ffffffffffffffff8111156129cd576129cd613d25565b604051908082528060200260200182016040528015612a5457816020015b6040805160e081018252600080825260208083018290529282018190526060808301829052608083019190915260a0820181905260c082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816129eb5790505b50905060005b82518110156107f257612a85838281518110612a7857612a786147e4565b6020026020010151611048565b828281518110612a9757612a976147e4565b6020908102919091010152600101612a5a565b612ab2612ad9565b612abb8161391a565b50565b600081815260018301602052604081205415155b9392505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314612b5a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610609565b565b6000610474825490565b6000612ad28383613a0f565b6000612ad28383613a39565b6040805160e0810182526000808252602080830182905282840182905260608084018390526080840183905260a0840181905260c084015263ffffffff8581168352600d8252848320805464010000000090049091168084526001909101825284832060028101805487518186028101860190985280885295969295919493909190830182828015612c2f57602002820191906000526020600020905b815481526020019060010190808311612c1b575b505050505090506000815167ffffffffffffffff811115612c5257612c52613d25565b604051908082528060200260200182016040528015612c9857816020015b604080518082019091526000815260606020820152815260200190600190039081612c705790505b50905060005b8151811015612db0576040518060400160405280848381518110612cc457612cc46147e4565b60200260200101518152602001856003016000868581518110612ce957612ce96147e4565b602002602001015181526020019081526020016000208054612d0a90614897565b80601f0160208091040260200160405190810160405280929190818152602001828054612d3690614897565b8015612d835780601f10612d5857610100808354040283529160200191612d83565b820191906000526020600020905b815481529060010190602001808311612d6657829003601f168201915b5050505050815250828281518110612d9d57612d9d6147e4565b6020908102919091010152600101612c9e565b506040805160e08101825263ffffffff8089166000818152600d6020818152868320548086168752948b168187015260ff680100000000000000008604811697870197909752690100000000000000000085048716151560608701529290915290526a010000000000000000000090049091161515608082015260a08101612e3785612e49565b81526020019190915295945050505050565b60606000612ad283613b2c565b6000612ad28383613b88565b608081015173ffffffffffffffffffffffffffffffffffffffff1615612fb057608081015173ffffffffffffffffffffffffffffffffffffffff163b1580612f5b575060808101516040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527f78bea72100000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff909116906301ffc9a790602401602060405180830381865afa158015612f35573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f599190614e6f565b155b15612fb05760808101516040517fabb5e3fd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610609565b600082815260026020526040902081518291908190612fcf9082614a05565b5060208201516001820190612fe49082614a05565b5060408201516002820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660018360038111156130265761302661444c565b021790555060608201516002820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1661010083600181111561306d5761306d61444c565b0217905550608091909101516002909101805473ffffffffffffffffffffffffffffffffffffffff90921662010000027fffffffffffffffffffff0000000000000000000000000000000000000000ffff90921691909117905560405182907f04f0a9bcf3f3a3b42a4d7ca081119755f82ebe43e0d30c8f7292c4fe0dc4a2ae90600090a25050565b805163ffffffff9081166000908152600d602090815260408083208286015190941683526001909301905220608082015160ff161580613148575060808201518590613143906001614e8c565b60ff16115b156131915760808201516040517f25b4d61800000000000000000000000000000000000000000000000000000000815260ff909116600482015260248101869052604401610609565b6001826020015163ffffffff16111561327957815163ffffffff166000908152600d6020908152604082209084015160019182019183916131d29190614842565b63ffffffff1663ffffffff168152602001908152602001600020905060005b6131fa82612b5c565b81101561327657613229846000015163ffffffff16600c60006105928587600001612b6690919063ffffffff16565b50600c60006132388484612b66565b8152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff1690556001016131f1565b50505b60005b858110156134b3576132a9878783818110613299576132996147e4565b8592602090910201359050612e56565b61330a5782518787838181106132c1576132c16147e4565b6040517f636e405700000000000000000000000000000000000000000000000000000000815263ffffffff90941660048501526020029190910135602483015250604401610609565b82606001511561346157825163ffffffff16600c6000898985818110613332576133326147e4565b602090810292909201358352508101919091526040016000205468010000000000000000900463ffffffff16148015906133ac5750600c600088888481811061337d5761337d6147e4565b602090810292909201358352508101919091526040016000205468010000000000000000900463ffffffff1615155b1561340e5782518787838181106133c5576133c56147e4565b6040517f60b9df7300000000000000000000000000000000000000000000000000000000815263ffffffff90941660048501526020029190910135602483015250604401610609565b8251600c6000898985818110613426576134266147e4565b90506020020135815260200190815260200160002060000160086101000a81548163ffffffff021916908363ffffffff1602179055506134ab565b82516134a99063ffffffff16600c60008a8a86818110613483576134836147e4565b905060200201358152602001908152602001600020600401612e5690919063ffffffff16565b505b60010161327c565b5060005b8381101561378f57368585838181106134d2576134d26147e4565b90506020028101906134e4919061490d565b90506134f260038235612abe565b61352b576040517fe181733f00000000000000000000000000000000000000000000000000000000815281356004820152602401610609565b61353760058235612abe565b15613571576040517ff7d7a29400000000000000000000000000000000000000000000000000000000815281356004820152602401610609565b803560009081526003840160205260408120805461358e90614897565b905011156135da5783516040517f3927d08000000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015281356024820152604401610609565b60005b878110156136e4576136818235600c60008c8c86818110613600576136006147e4565b9050602002013581526020019081526020016000206003016000600c60008e8e88818110613630576136306147e4565b90506020020135815260200190815260200160002060000160049054906101000a900463ffffffff1663ffffffff1663ffffffff168152602001908152602001600020612abe90919063ffffffff16565b6136dc57888882818110613697576136976147e4565b6040517fa7e792500000000000000000000000000000000000000000000000000000000081526020909102929092013560048301525082356024820152604401610609565b6001016135dd565b506002830180546001810182556000918252602091829020833591015561370d90820182614ea5565b8235600090815260038601602052604090209161372b919083614f0a565b50835160208086015161378692918435908c908c9061374c90880188614ea5565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250613bd792505050565b506001016134b7565b50604080830151835163ffffffff9081166000908152600d602090815284822080549415156901000000000000000000027fffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffff90951694909417909355606086015186518316825284822080549115156a0100000000000000000000027fffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffff9092169190911790556080860151865183168252848220805460ff9290921668010000000000000000027fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff909216919091179055918501805186518316845292849020805493909216640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff00000000ffffffff9093169290921790558351905191517ff264aae70bf6a9d90e68e0f9b393f4e7fbea67b063b0f336e0b36c15817036519261390a929163ffffffff92831681529116602082015260400190565b60405180910390a1505050505050565b3373ffffffffffffffffffffffffffffffffffffffff821603613999576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610609565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000826000018281548110613a2657613a266147e4565b9060005260206000200154905092915050565b60008181526001830160205260408120548015613b22576000613a5d600183615025565b8554909150600090613a7190600190615025565b9050818114613ad6576000866000018281548110613a9157613a916147e4565b9060005260206000200154905080876000018481548110613ab457613ab46147e4565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080613ae757613ae7615038565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610474565b6000915050610474565b606081600001805480602002602001604051908101604052809291908181526020018280548015613b7c57602002820191906000526020600020905b815481526020019060010190808311613b68575b50505050509050919050565b6000818152600183016020526040812054613bcf57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610474565b506000610474565b6000848152600260208190526040909120015462010000900473ffffffffffffffffffffffffffffffffffffffff16156124d757600084815260026020819052604091829020015490517ffba64a7c0000000000000000000000000000000000000000000000000000000081526201000090910473ffffffffffffffffffffffffffffffffffffffff169063fba64a7c90613c7e908690869086908b908d90600401615067565b600060405180830381600087803b158015613c9857600080fd5b505af1158015613cac573d6000803e3d6000fd5b50505050505050505050565b508054613cc490614897565b6000825580601f10613cd4575050565b601f016020900490600052602060002090810190612abb9190613d0c565b5080546000825590600052602060002090810190612abb91905b5b80821115613d215760008155600101613d0d565b5090565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040516080810167ffffffffffffffff81118282101715613d7757613d77613d25565b60405290565b60405160a0810167ffffffffffffffff81118282101715613d7757613d77613d25565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613de757613de7613d25565b604052919050565b600067ffffffffffffffff821115613e0957613e09613d25565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f830112613e4657600080fd5b8135613e59613e5482613def565b613da0565b818152846020838601011115613e6e57600080fd5b816020850160208301376000918101602001919091529392505050565b60008060408385031215613e9e57600080fd5b823567ffffffffffffffff80821115613eb657600080fd5b613ec286838701613e35565b93506020850135915080821115613ed857600080fd5b50613ee585828601613e35565b9150509250929050565b600060208284031215613f0157600080fd5b5035919050565b60005b83811015613f23578181015183820152602001613f0b565b50506000910152565b60008151808452613f44816020860160208601613f08565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000612ad26020830184613f2c565b60008083601f840112613f9b57600080fd5b50813567ffffffffffffffff811115613fb357600080fd5b6020830191508360208260051b850101111561104157600080fd5b60008060208385031215613fe157600080fd5b823567ffffffffffffffff811115613ff857600080fd5b61400485828601613f89565b90969095509350505050565b60008151808452602080850194506020840160005b8381101561404157815187529582019590820190600101614025565b509495945050505050565b600082825180855260208086019550808260051b84010181860160005b848110156140c9578583037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001895281518051845284015160408585018190526140b581860183613f2c565b9a86019a9450505090830190600101614069565b5090979650505050505050565b600063ffffffff8083511684528060208401511660208501525060ff604083015116604084015260608201511515606084015260808201511515608084015260a082015160e060a085015261412e60e0850182614010565b905060c083015184820360c0860152614147828261404c565b95945050505050565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b828110156141c5577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526141b38583516140d6565b94509285019290850190600101614179565b5092979650505050505050565b803563ffffffff811681146141e657600080fd5b919050565b6000602082840312156141fd57600080fd5b612ad2826141d2565b73ffffffffffffffffffffffffffffffffffffffff8151168252600060208201516040602085015261423b6040850182613f2c565b949350505050565b602081526000612ad26020830184614206565b602081526000612ad260208301846140d6565b6000806040838503121561427c57600080fd5b614285836141d2565b946020939093013593505050565b6040815260006142a66040830185613f2c565b82810360208401526141478185613f2c565b600063ffffffff808351168452602081818501511681860152816040850151166040860152606084015160608601526080840151608086015260a0840151915060e060a086015261430c60e0860183614010565b60c08581015187830391880191909152805180835290830193506000918301905b8083101561434d578451825293830193600192909201919083019061432d565b509695505050505050565b602081526000612ad260208301846142b8565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b828110156141c5577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526143ce858351614206565b94509285019290850190600101614394565b600080600080604085870312156143f657600080fd5b843567ffffffffffffffff8082111561440e57600080fd5b61441a88838901613f89565b9096509450602087013591508082111561443357600080fd5b5061444087828801613f89565b95989497509550505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b805182526000602082015160e0602085015261449a60e0850182613f2c565b9050604083015184820360408601526144b38282613f2c565b9150506060830151600481106144cb576144cb61444c565b60608501526080830151600281106144e5576144e561444c565b8060808601525060a083015161451360a086018273ffffffffffffffffffffffffffffffffffffffff169052565b5060c083015161452760c086018215159052565b509392505050565b602081526000612ad2602083018461447b565b8015158114612abb57600080fd5b803560ff811681146141e657600080fd5b60008060008060008060008060c0898b03121561457d57600080fd5b614586896141d2565b9750602089013567ffffffffffffffff808211156145a357600080fd5b6145af8c838d01613f89565b909950975060408b01359150808211156145c857600080fd5b506145d58b828c01613f89565b90965094505060608901356145e981614542565b925060808901356145f981614542565b915061460760a08a01614550565b90509295985092959890939650565b600080600080600080600060a0888a03121561463157600080fd5b873567ffffffffffffffff8082111561464957600080fd5b6146558b838c01613f89565b909950975060208a013591508082111561466e57600080fd5b5061467b8a828b01613f89565b909650945050604088013561468f81614542565b9250606088013561469f81614542565b91506146ad60808901614550565b905092959891949750929550565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b828110156141c5577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc088860301845261471e85835161447b565b945092850192908501906001016146e4565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b828110156141c5577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526147938583516142b8565b94509285019290850190600101614759565b803573ffffffffffffffffffffffffffffffffffffffff811681146141e657600080fd5b6000602082840312156147db57600080fd5b612ad2826147a5565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b63ffffffff8281168282160390808211156107f2576107f2614813565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361489057614890614813565b5060010190565b600181811c908216806148ab57607f821691505b6020821081036148e4577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b600063ffffffff80831681810361490357614903614813565b6001019392505050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc183360301811261494157600080fd5b9190910192915050565b60006040823603121561495d57600080fd5b6040516040810167ffffffffffffffff828210818311171561498157614981613d25565b8160405261498e856147a5565b835260208501359150808211156149a457600080fd5b506149b136828601613e35565b60208301525092915050565b601f821115610697576000816000526020600020601f850160051c810160208610156149e65750805b601f850160051c820191505b818110156124d7578281556001016149f2565b815167ffffffffffffffff811115614a1f57614a1f613d25565b614a3381614a2d8454614897565b846149bd565b602080601f831160018114614a865760008415614a505750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556124d7565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015614ad357888601518255948401946001909101908401614ab4565b5085821015614b0f57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b600060208284031215614b3157600080fd5b815167ffffffffffffffff811115614b4857600080fd5b8201601f81018413614b5957600080fd5b8051614b67613e5482613def565b818152856020838501011115614b7c57600080fd5b614147826020830160208601613f08565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8183360301811261494157600080fd5b600060808236031215614bd357600080fd5b614bdb613d54565b614be4836141d2565b81526020808401358183015260408401356040830152606084013567ffffffffffffffff80821115614c1557600080fd5b9085019036601f830112614c2857600080fd5b813581811115614c3a57614c3a613d25565b8060051b9150614c4b848301613da0565b8181529183018401918481019036841115614c6557600080fd5b938501935b83851015614c8357843582529385019390850190614c6a565b606087015250939695505050505050565b6020808252825182820181905260009190848201906040850190845b81811015614ccc57835183529284019291840191600101614cb0565b50909695505050505050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6183360301811261494157600080fd5b8035600281106141e657600080fd5b600060a08236031215614d2d57600080fd5b614d35613d7d565b823567ffffffffffffffff80821115614d4d57600080fd5b614d5936838701613e35565b83526020850135915080821115614d6f57600080fd5b50614d7c36828601613e35565b602083015250604083013560048110614d9457600080fd5b6040820152614da560608401614d0c565b6060820152614db6608084016147a5565b608082015292915050565b6000602080835260008454614dd581614897565b8060208701526040600180841660008114614df75760018114614e3157614e61565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00851660408a0152604084151560051b8a01019550614e61565b89600052602060002060005b85811015614e585781548b8201860152908301908801614e3d565b8a016040019650505b509398975050505050505050565b600060208284031215614e8157600080fd5b8151612ad281614542565b60ff818116838216019081111561047457610474614813565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112614eda57600080fd5b83018035915067ffffffffffffffff821115614ef557600080fd5b60200191503681900382131561104157600080fd5b67ffffffffffffffff831115614f2257614f22613d25565b614f3683614f308354614897565b836149bd565b6000601f841160018114614f885760008515614f525750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b17835561501e565b6000838152602090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0861690835b82811015614fd75786850135825560209485019460019092019101614fb7565b5086821015615012577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b8181038181111561047457610474614813565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b6080815284608082015260007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8611156150a057600080fd5b8560051b808860a0850137820182810360a090810160208501526150c690820187613f2c565b91505063ffffffff8085166040840152808416606084015250969550505050505056fea164736f6c6343000818000a", + Bin: "0x6080604052600e80546001600160401b0319166401000000011790553480156200002857600080fd5b503380600081620000805760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000b357620000b381620000bc565b50505062000167565b336001600160a01b03821603620001165760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000077565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6150f680620001776000396000f3fe608060405234801561001057600080fd5b50600436106101ae5760003560e01c80635e65e309116100ee5780638da5cb5b11610097578063d8bc7b6811610071578063d8bc7b68146103f6578063ddbe4f8214610409578063e29581aa1461041e578063f2fde38b1461043357600080fd5b80638da5cb5b1461039b5780639cb7c5f4146103c3578063d59a79f6146103e357600080fd5b806373ac22b4116100c857806373ac22b41461036d57806379ba50971461038057806386fa42461461038857600080fd5b80635e65e3091461033257806366acaa3314610345578063715f52951461035a57600080fd5b8063235374051161015b578063398f377311610135578063398f3773146102cb5780633f2a13c9146102de57806350c946fe146102ff5780635d83d9671461031f57600080fd5b80632353740514610285578063275459f2146102a55780632c01a1e8146102b857600080fd5b80631d05394c1161018c5780631d05394c1461023b578063214502431461025057806322bdbcbc1461026557600080fd5b80630fe5800a146101b357806312570011146101d9578063181f5a77146101fc575b600080fd5b6101c66101c1366004613e8b565b610446565b6040519081526020015b60405180910390f35b6101ec6101e7366004613eef565b61047a565b60405190151581526020016101d0565b604080518082018252601a81527f4361706162696c6974696573526567697374727920312e302e30000000000000602082015290516101d09190613f76565b61024e610249366004613fce565b610487565b005b61025861069c565b6040516101d09190614150565b6102786102733660046141eb565b6107f9565b6040516101d09190614243565b6102986102933660046141eb565b6108e6565b6040516101d09190614256565b61024e6102b3366004613fce565b61092a565b61024e6102c6366004613fce565b610a01565b61024e6102d9366004613fce565b610c9d565b6102f16102ec366004614269565b610e5c565b6040516101d0929190614293565b61031261030d366004613eef565b611048565b6040516101d09190614358565b61024e61032d366004613fce565b611122565b61024e610340366004613fce565b611217565b61034d61193f565b6040516101d0919061436b565b61024e610368366004613fce565b611b22565b61024e61037b366004613fce565b611bd4565b61024e6120a2565b61024e6103963660046143e0565b61219f565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101d0565b6103d66103d1366004613eef565b6124df565b6040516101d0919061452f565b61024e6103f1366004614561565b61271a565b61024e610404366004614616565b6127e3565b6104116128ad565b6040516101d091906146bb565b6104266129a1565b6040516101d09190614730565b61024e6104413660046147c9565b612aaa565b6000828260405160200161045b929190614293565b6040516020818303038152906040528051906020012090505b92915050565b6000610474600583612abe565b61048f612ad9565b60005b818110156106975760008383838181106104ae576104ae6147e4565b90506020020160208101906104c391906141eb565b63ffffffff8181166000908152600d60209081526040808320805464010000000081049095168085526001820190935290832094955093909290916a010000000000000000000090910460ff16905b61051b83612b5c565b8110156105bb57811561057157600c60006105368584612b66565b8152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff1690556105b3565b6105b18663ffffffff16600c60006105928588612b6690919063ffffffff16565b8152602001908152602001600020600401612b7290919063ffffffff16565b505b600101610512565b508354640100000000900463ffffffff16600003610612576040517f2b62be9b00000000000000000000000000000000000000000000000000000000815263ffffffff861660048201526024015b60405180910390fd5b63ffffffff85166000818152600d6020908152604080832080547fffffffffffffffffffffffffffffffffffffffffff00000000000000000000001690558051938452908301919091527ff264aae70bf6a9d90e68e0f9b393f4e7fbea67b063b0f336e0b36c1581703651910160405180910390a15050505050806001019050610492565b505050565b600e54606090640100000000900463ffffffff1660006106bd600183614842565b63ffffffff1667ffffffffffffffff8111156106db576106db613d25565b60405190808252806020026020018201604052801561076257816020015b6040805160e081018252600080825260208083018290529282018190526060808301829052608083019190915260a0820181905260c082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816106f95790505b509050600060015b8363ffffffff168163ffffffff1610156107d65763ffffffff8082166000908152600d602052604090205416156107ce576107a481612b7e565b8383815181106107b6576107b66147e4565b6020026020010181905250816107cb9061485f565b91505b60010161076a565b506107e2600184614842565b63ffffffff1681146107f2578082525b5092915050565b60408051808201909152600081526060602082015263ffffffff82166000908152600b60209081526040918290208251808401909352805473ffffffffffffffffffffffffffffffffffffffff168352600181018054919284019161085d90614897565b80601f016020809104026020016040519081016040528092919081815260200182805461088990614897565b80156108d65780601f106108ab576101008083540402835291602001916108d6565b820191906000526020600020905b8154815290600101906020018083116108b957829003601f168201915b5050505050815250509050919050565b6040805160e0810182526000808252602082018190529181018290526060808201839052608082019290925260a0810182905260c081019190915261047482612b7e565b610932612ad9565b60005b63ffffffff811682111561069757600083838363ffffffff1681811061095d5761095d6147e4565b905060200201602081019061097291906141eb565b63ffffffff81166000908152600b6020526040812080547fffffffffffffffffffffffff00000000000000000000000000000000000000001681559192506109bd6001830182613cb8565b505060405163ffffffff8216907fa59268ca81d40429e65ccea5385b59cf2d3fc6519371dee92f8eb1dae5107a7a90600090a2506109fa816148ea565b9050610935565b6000805473ffffffffffffffffffffffffffffffffffffffff163314905b82811015610c97576000848483818110610a3b57610a3b6147e4565b602090810292909201356000818152600c90935260409092206001810154929350919050610a98576040517fd82f6adb00000000000000000000000000000000000000000000000000000000815260048101839052602401610609565b6000610aa682600401612b5c565b1115610afb57610ab96004820184612b66565b6040517f60a6d89800000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015260248101839052604401610609565b805468010000000000000000900463ffffffff1615610b635780546040517f60b9df730000000000000000000000000000000000000000000000000000000081526801000000000000000090910463ffffffff16600482015260248101839052604401610609565b83158015610b9d5750805463ffffffff166000908152600b602052604090205473ffffffffffffffffffffffffffffffffffffffff163314155b15610bd6576040517f9473075d000000000000000000000000000000000000000000000000000000008152336004820152602401610609565b6001810154610be790600790612b72565b506002810154610bf990600990612b72565b506000828152600c6020526040812080547fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016815560018101829055600281018290559060048201818181610c4e8282613cf2565b5050505050507f5254e609a97bab37b7cc79fe128f85c097bd6015c6e1624ae0ba392eb975320582604051610c8591815260200190565b60405180910390a15050600101610a1f565b50505050565b610ca5612ad9565b60005b81811015610697576000838383818110610cc457610cc46147e4565b9050602002810190610cd6919061490d565b610cdf9061494b565b805190915073ffffffffffffffffffffffffffffffffffffffff16610d30576040517feeacd93900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600e54604080518082018252835173ffffffffffffffffffffffffffffffffffffffff908116825260208086015181840190815263ffffffff9095166000818152600b909252939020825181547fffffffffffffffffffffffff00000000000000000000000000000000000000001692169190911781559251919290916001820190610dbc9082614a05565b5050600e8054909150600090610dd79063ffffffff166148ea565b91906101000a81548163ffffffff021916908363ffffffff160217905550816000015173ffffffffffffffffffffffffffffffffffffffff168163ffffffff167f78e94ca80be2c30abc061b99e7eb8583b1254781734b1e3ce339abb57da2fe8e8460200151604051610e4a9190613f76565b60405180910390a35050600101610ca8565b63ffffffff8083166000908152600d60209081526040808320805464010000000090049094168084526001909401825280832085845260030190915281208054606093849390929091610eae90614897565b80601f0160208091040260200160405190810160405280929190818152602001828054610eda90614897565b8015610f275780601f10610efc57610100808354040283529160200191610f27565b820191906000526020600020905b815481529060010190602001808311610f0a57829003601f168201915b5050506000888152600260208190526040909120015492935060609262010000900473ffffffffffffffffffffffffffffffffffffffff1615915061103a905057600086815260026020819052604091829020015490517f8318ed5d00000000000000000000000000000000000000000000000000000000815263ffffffff891660048201526201000090910473ffffffffffffffffffffffffffffffffffffffff1690638318ed5d90602401600060405180830381865afa158015610ff1573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526110379190810190614b1f565b90505b9093509150505b9250929050565b6040805160e0810182526000808252602082018190529181018290526060808201839052608082019290925260a0810182905260c08101919091526040805160e0810182526000848152600c6020908152838220805463ffffffff8082168652640100000000820481168487018190526801000000000000000090920416858701526001820154606086015260028201546080860152835260030190529190912060a08201906110f790612e49565b815260200161111a600c6000868152602001908152602001600020600401612e49565b905292915050565b61112a612ad9565b60005b81811015610697576000838383818110611149576111496147e4565b905060200201359050611166816003612abe90919063ffffffff16565b61119f576040517fe181733f00000000000000000000000000000000000000000000000000000000815260048101829052602401610609565b6111aa600582612e56565b6111e3576040517ff7d7a29400000000000000000000000000000000000000000000000000000000815260048101829052602401610609565b60405181907fdcea1b78b6ddc31592a94607d537543fcaafda6cc52d6d5cc7bbfca1422baf2190600090a25060010161112d565b6000805473ffffffffffffffffffffffffffffffffffffffff163314905b82811015610c97576000848483818110611251576112516147e4565b90506020028101906112639190614b8d565b61126c90614bc1565b6040808201516000908152600c6020908152828220805463ffffffff168352600b82528383208451808601909552805473ffffffffffffffffffffffffffffffffffffffff16855260018101805496975091959394939092840191906112d190614897565b80601f01602080910402602001604051908101604052809291908181526020018280546112fd90614897565b801561134a5780601f1061131f5761010080835404028352916020019161134a565b820191906000526020600020905b81548152906001019060200180831161132d57829003601f168201915b50505091909252505050600183015490915061139a5782604001516040517fd82f6adb00000000000000000000000000000000000000000000000000000000815260040161060991815260200190565b841580156113bf5750805173ffffffffffffffffffffffffffffffffffffffff163314155b156113f8576040517f9473075d000000000000000000000000000000000000000000000000000000008152336004820152602401610609565b6020830151611433576040517f8377314600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001820154602084015181146114b457602084015161145490600790612abe565b1561148b576040517f8377314600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602084015160018401556114a0600782612b72565b5060208401516114b290600790612e56565b505b606084015180516000036114f657806040517f3748d4c60000000000000000000000000000000000000000000000000000000081526004016106099190614c94565b8354600090859060049061151790640100000000900463ffffffff166148ea565b91906101000a81548163ffffffff021916908363ffffffff1602179055905060005b82518110156115fc5761156f838281518110611557576115576147e4565b60200260200101516003612abe90919063ffffffff16565b6115a757826040517f3748d4c60000000000000000000000000000000000000000000000000000000081526004016106099190614c94565b6115f38382815181106115bc576115bc6147e4565b60200260200101518760030160008563ffffffff1663ffffffff168152602001908152602001600020612e5690919063ffffffff16565b50600101611539565b50845468010000000000000000900463ffffffff16801561175d5763ffffffff8082166000908152600d60209081526040808320805464010000000090049094168352600190930181528282206002018054845181840281018401909552808552929392909183018282801561169157602002820191906000526020600020905b81548152602001906001019080831161167d575b5050505050905060005b815181101561175a576116f08282815181106116b9576116b96147e4565b60200260200101518960030160008763ffffffff1663ffffffff168152602001908152602001600020612abe90919063ffffffff16565b61175257818181518110611706576117066147e4565b6020026020010151836040517f03dcd86200000000000000000000000000000000000000000000000000000000815260040161060992919091825263ffffffff16602082015260400190565b60010161169b565b50505b600061176b87600401612e49565b905060005b81518163ffffffff1610156118b1576000828263ffffffff1681518110611799576117996147e4565b60209081029190910181015163ffffffff8082166000908152600d8452604080822080546401000000009004909316825260019092018452818120600201805483518187028101870190945280845293955090939192909183018282801561182057602002820191906000526020600020905b81548152602001906001019080831161180c575b5050505050905060005b815181101561189d5761187f828281518110611848576118486147e4565b60200260200101518c60030160008a63ffffffff1663ffffffff168152602001908152602001600020612abe90919063ffffffff16565b61189557818181518110611706576117066147e4565b60010161182a565b505050806118aa906148ea565b9050611770565b50875187547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff90911690811788556040808a015160028a018190556020808c01518351928352908201527f4b5b465e22eea0c3d40c30e936643245b80d19b2dcf75788c0699fe8d8db645b910160405180910390a25050505050505050806001019050611235565b600e5460609063ffffffff166000611958600183614842565b63ffffffff1667ffffffffffffffff81111561197657611976613d25565b6040519080825280602002602001820160405280156119bc57816020015b6040805180820190915260008152606060208201528152602001906001900390816119945790505b509050600060015b8363ffffffff168163ffffffff161015611b0c5763ffffffff81166000908152600b602052604090205473ffffffffffffffffffffffffffffffffffffffff1615611b045763ffffffff81166000908152600b60209081526040918290208251808401909352805473ffffffffffffffffffffffffffffffffffffffff1683526001810180549192840191611a5890614897565b80601f0160208091040260200160405190810160405280929190818152602001828054611a8490614897565b8015611ad15780601f10611aa657610100808354040283529160200191611ad1565b820191906000526020600020905b815481529060010190602001808311611ab457829003601f168201915b505050505081525050838381518110611aec57611aec6147e4565b602002602001018190525081611b019061485f565b91505b6001016119c4565b50600e546107e29060019063ffffffff16614842565b611b2a612ad9565b60005b81811015610697576000838383818110611b4957611b496147e4565b9050602002810190611b5b9190614cd8565b611b6490614d1b565b90506000611b7a82600001518360200151610446565b9050611b87600382612e56565b611bc0576040517febf5255100000000000000000000000000000000000000000000000000000000815260048101829052602401610609565b611bca8183612e62565b5050600101611b2d565b6000805473ffffffffffffffffffffffffffffffffffffffff163314905b82811015610c97576000848483818110611c0e57611c0e6147e4565b9050602002810190611c209190614b8d565b611c2990614bc1565b805163ffffffff166000908152600b602090815260408083208151808301909252805473ffffffffffffffffffffffffffffffffffffffff168252600181018054959650939491939092840191611c7f90614897565b80601f0160208091040260200160405190810160405280929190818152602001828054611cab90614897565b8015611cf85780601f10611ccd57610100808354040283529160200191611cf8565b820191906000526020600020905b815481529060010190602001808311611cdb57829003601f168201915b50505091909252505081519192505073ffffffffffffffffffffffffffffffffffffffff16611d5e5781516040517fadd9ae1e00000000000000000000000000000000000000000000000000000000815263ffffffff9091166004820152602401610609565b83158015611d835750805173ffffffffffffffffffffffffffffffffffffffff163314155b15611dbc576040517f9473075d000000000000000000000000000000000000000000000000000000008152336004820152602401610609565b6040808301516000908152600c60205220600181015415611e115782604001516040517f5461848300000000000000000000000000000000000000000000000000000000815260040161060991815260200190565b6040830151611e545782604001516040517f64e2ee9200000000000000000000000000000000000000000000000000000000815260040161060991815260200190565b60208301511580611e7157506020830151611e7190600790612abe565b15611ea8576040517f8377314600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60608301518051600003611eea57806040517f3748d4c60000000000000000000000000000000000000000000000000000000081526004016106099190614c94565b81548290600490611f0890640100000000900463ffffffff166148ea565b82546101009290920a63ffffffff818102199093169183160217909155825464010000000090041660005b8251811015611fde57611f51838281518110611557576115576147e4565b611f8957826040517f3748d4c60000000000000000000000000000000000000000000000000000000081526004016106099190614c94565b611fd5838281518110611f9e57611f9e6147e4565b60200260200101518560030160008563ffffffff1663ffffffff168152602001908152602001600020612e5690919063ffffffff16565b50600101611f33565b50845183547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001663ffffffff918216178455604086015160028501556020860151600185018190556120349160079190612e5616565b50604085015161204690600990612e56565b50845160408087015160208089015183519283529082015263ffffffff909216917f74becb12a5e8fd0e98077d02dfba8f647c9670c9df177e42c2418cf17a636f05910160405180910390a25050505050806001019050611bf2565b60015473ffffffffffffffffffffffffffffffffffffffff163314612123576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610609565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b8281146121e2576040517fab8b67c60000000000000000000000000000000000000000000000000000000081526004810184905260248101829052604401610609565b6000805473ffffffffffffffffffffffffffffffffffffffff16905b848110156124d757600086868381811061221a5761221a6147e4565b905060200201602081019061222f91906141eb565b63ffffffff81166000908152600b6020526040902080549192509073ffffffffffffffffffffffffffffffffffffffff1661229e576040517fadd9ae1e00000000000000000000000000000000000000000000000000000000815263ffffffff83166004820152602401610609565b60008686858181106122b2576122b26147e4565b90506020028101906122c4919061490d565b6122cd9061494b565b805190915073ffffffffffffffffffffffffffffffffffffffff1661231e576040517feeacd93900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815473ffffffffffffffffffffffffffffffffffffffff16331480159061235b57503373ffffffffffffffffffffffffffffffffffffffff861614155b15612394576040517f9473075d000000000000000000000000000000000000000000000000000000008152336004820152602401610609565b8051825473ffffffffffffffffffffffffffffffffffffffff908116911614158061241057506020808201516040516123cd9201613f76565b60405160208183030381529060405280519060200120826001016040516020016123f79190614dc1565b6040516020818303038152906040528051906020012014155b156124c957805182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9091161782556020810151600183019061246a9082614a05565b50806000015173ffffffffffffffffffffffffffffffffffffffff168363ffffffff167f86f41145bde5dd7f523305452e4aad3685508c181432ec733d5f345009358a2883602001516040516124c09190613f76565b60405180910390a35b5050508060010190506121fe565b505050505050565b6125206040805160e0810182526000808252606060208301819052928201839052909182019081526020016000815260006020820181905260409091015290565b6040805160e0810182528381526000848152600260209081529290208054919283019161254c90614897565b80601f016020809104026020016040519081016040528092919081815260200182805461257890614897565b80156125c55780601f1061259a576101008083540402835291602001916125c5565b820191906000526020600020905b8154815290600101906020018083116125a857829003601f168201915b505050505081526020016002600085815260200190815260200160002060010180546125f090614897565b80601f016020809104026020016040519081016040528092919081815260200182805461261c90614897565b80156126695780601f1061263e57610100808354040283529160200191612669565b820191906000526020600020905b81548152906001019060200180831161264c57829003601f168201915b50505091835250506000848152600260208181526040909220015491019060ff16600381111561269b5761269b61444c565b815260008481526002602081815260409092200154910190610100900460ff1660018111156126cc576126cc61444c565b81526000848152600260208181526040928390209091015462010000900473ffffffffffffffffffffffffffffffffffffffff169083015201612710600585612abe565b1515905292915050565b612722612ad9565b63ffffffff8089166000908152600d6020526040812054640100000000900490911690819003612786576040517f2b62be9b00000000000000000000000000000000000000000000000000000000815263ffffffff8a166004820152602401610609565b6127d8888888886040518060a001604052808f63ffffffff168152602001876127ae906148ea565b97508763ffffffff1681526020018a1515815260200189151581526020018860ff168152506130f6565b505050505050505050565b6127eb612ad9565b600e805460009164010000000090910463ffffffff1690600461280d836148ea565b82546101009290920a63ffffffff81810219909316918316021790915581166000818152600d602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000001684179055815160a08101835292835260019083015286151590820152841515606082015260ff841660808201529091506128a39089908990899089906130f6565b5050505050505050565b606060006128bb6003612e49565b90506000815167ffffffffffffffff8111156128d9576128d9613d25565b60405190808252806020026020018201604052801561294b57816020015b6129386040805160e0810182526000808252606060208301819052928201839052909182019081526020016000815260006020820181905260409091015290565b8152602001906001900390816128f75790505b50905060005b82518110156107f25761297c83828151811061296f5761296f6147e4565b60200260200101516124df565b82828151811061298e5761298e6147e4565b6020908102919091010152600101612951565b606060006129af6009612e49565b90506000815167ffffffffffffffff8111156129cd576129cd613d25565b604051908082528060200260200182016040528015612a5457816020015b6040805160e081018252600080825260208083018290529282018190526060808301829052608083019190915260a0820181905260c082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816129eb5790505b50905060005b82518110156107f257612a85838281518110612a7857612a786147e4565b6020026020010151611048565b828281518110612a9757612a976147e4565b6020908102919091010152600101612a5a565b612ab2612ad9565b612abb8161391a565b50565b600081815260018301602052604081205415155b9392505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314612b5a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610609565b565b6000610474825490565b6000612ad28383613a0f565b6000612ad28383613a39565b6040805160e0810182526000808252602080830182905282840182905260608084018390526080840183905260a0840181905260c084015263ffffffff8581168352600d8252848320805464010000000090049091168084526001909101825284832060028101805487518186028101860190985280885295969295919493909190830182828015612c2f57602002820191906000526020600020905b815481526020019060010190808311612c1b575b505050505090506000815167ffffffffffffffff811115612c5257612c52613d25565b604051908082528060200260200182016040528015612c9857816020015b604080518082019091526000815260606020820152815260200190600190039081612c705790505b50905060005b8151811015612db0576040518060400160405280848381518110612cc457612cc46147e4565b60200260200101518152602001856003016000868581518110612ce957612ce96147e4565b602002602001015181526020019081526020016000208054612d0a90614897565b80601f0160208091040260200160405190810160405280929190818152602001828054612d3690614897565b8015612d835780601f10612d5857610100808354040283529160200191612d83565b820191906000526020600020905b815481529060010190602001808311612d6657829003601f168201915b5050505050815250828281518110612d9d57612d9d6147e4565b6020908102919091010152600101612c9e565b506040805160e08101825263ffffffff8089166000818152600d6020818152868320548086168752948b168187015260ff680100000000000000008604811697870197909752690100000000000000000085048716151560608701529290915290526a010000000000000000000090049091161515608082015260a08101612e3785612e49565b81526020019190915295945050505050565b60606000612ad283613b2c565b6000612ad28383613b88565b608081015173ffffffffffffffffffffffffffffffffffffffff1615612fb057608081015173ffffffffffffffffffffffffffffffffffffffff163b1580612f5b575060808101516040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527f78bea72100000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff909116906301ffc9a790602401602060405180830381865afa158015612f35573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f599190614e6f565b155b15612fb05760808101516040517fabb5e3fd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610609565b600082815260026020526040902081518291908190612fcf9082614a05565b5060208201516001820190612fe49082614a05565b5060408201516002820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660018360038111156130265761302661444c565b021790555060608201516002820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1661010083600181111561306d5761306d61444c565b0217905550608091909101516002909101805473ffffffffffffffffffffffffffffffffffffffff90921662010000027fffffffffffffffffffff0000000000000000000000000000000000000000ffff90921691909117905560405182907f04f0a9bcf3f3a3b42a4d7ca081119755f82ebe43e0d30c8f7292c4fe0dc4a2ae90600090a25050565b805163ffffffff9081166000908152600d602090815260408083208286015190941683526001909301905220608082015160ff161580613148575060808201518590613143906001614e8c565b60ff16115b156131915760808201516040517f25b4d61800000000000000000000000000000000000000000000000000000000815260ff909116600482015260248101869052604401610609565b6001826020015163ffffffff16111561327957815163ffffffff166000908152600d6020908152604082209084015160019182019183916131d29190614842565b63ffffffff1663ffffffff168152602001908152602001600020905060005b6131fa82612b5c565b81101561327657613229846000015163ffffffff16600c60006105928587600001612b6690919063ffffffff16565b50600c60006132388484612b66565b8152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff1690556001016131f1565b50505b60005b858110156134b3576132a9878783818110613299576132996147e4565b8592602090910201359050612e56565b61330a5782518787838181106132c1576132c16147e4565b6040517f636e405700000000000000000000000000000000000000000000000000000000815263ffffffff90941660048501526020029190910135602483015250604401610609565b82606001511561346157825163ffffffff16600c6000898985818110613332576133326147e4565b602090810292909201358352508101919091526040016000205468010000000000000000900463ffffffff16148015906133ac5750600c600088888481811061337d5761337d6147e4565b602090810292909201358352508101919091526040016000205468010000000000000000900463ffffffff1615155b1561340e5782518787838181106133c5576133c56147e4565b6040517f60b9df7300000000000000000000000000000000000000000000000000000000815263ffffffff90941660048501526020029190910135602483015250604401610609565b8251600c6000898985818110613426576134266147e4565b90506020020135815260200190815260200160002060000160086101000a81548163ffffffff021916908363ffffffff1602179055506134ab565b82516134a99063ffffffff16600c60008a8a86818110613483576134836147e4565b905060200201358152602001908152602001600020600401612e5690919063ffffffff16565b505b60010161327c565b5060005b8381101561378f57368585838181106134d2576134d26147e4565b90506020028101906134e4919061490d565b90506134f260038235612abe565b61352b576040517fe181733f00000000000000000000000000000000000000000000000000000000815281356004820152602401610609565b61353760058235612abe565b15613571576040517ff7d7a29400000000000000000000000000000000000000000000000000000000815281356004820152602401610609565b803560009081526003840160205260408120805461358e90614897565b905011156135da5783516040517f3927d08000000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015281356024820152604401610609565b60005b878110156136e4576136818235600c60008c8c86818110613600576136006147e4565b9050602002013581526020019081526020016000206003016000600c60008e8e88818110613630576136306147e4565b90506020020135815260200190815260200160002060000160049054906101000a900463ffffffff1663ffffffff1663ffffffff168152602001908152602001600020612abe90919063ffffffff16565b6136dc57888882818110613697576136976147e4565b6040517fa7e792500000000000000000000000000000000000000000000000000000000081526020909102929092013560048301525082356024820152604401610609565b6001016135dd565b506002830180546001810182556000918252602091829020833591015561370d90820182614ea5565b8235600090815260038601602052604090209161372b919083614f0a565b50835160208086015161378692918435908c908c9061374c90880188614ea5565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250613bd792505050565b506001016134b7565b50604080830151835163ffffffff9081166000908152600d602090815284822080549415156901000000000000000000027fffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffff90951694909417909355606086015186518316825284822080549115156a0100000000000000000000027fffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffff9092169190911790556080860151865183168252848220805460ff9290921668010000000000000000027fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff909216919091179055918501805186518316845292849020805493909216640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff00000000ffffffff9093169290921790558351905191517ff264aae70bf6a9d90e68e0f9b393f4e7fbea67b063b0f336e0b36c15817036519261390a929163ffffffff92831681529116602082015260400190565b60405180910390a1505050505050565b3373ffffffffffffffffffffffffffffffffffffffff821603613999576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610609565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000826000018281548110613a2657613a266147e4565b9060005260206000200154905092915050565b60008181526001830160205260408120548015613b22576000613a5d600183615025565b8554909150600090613a7190600190615025565b9050818114613ad6576000866000018281548110613a9157613a916147e4565b9060005260206000200154905080876000018481548110613ab457613ab46147e4565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080613ae757613ae7615038565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610474565b6000915050610474565b606081600001805480602002602001604051908101604052809291908181526020018280548015613b7c57602002820191906000526020600020905b815481526020019060010190808311613b68575b50505050509050919050565b6000818152600183016020526040812054613bcf57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610474565b506000610474565b6000848152600260208190526040909120015462010000900473ffffffffffffffffffffffffffffffffffffffff16156124d757600084815260026020819052604091829020015490517ffba64a7c0000000000000000000000000000000000000000000000000000000081526201000090910473ffffffffffffffffffffffffffffffffffffffff169063fba64a7c90613c7e908690869086908b908d90600401615067565b600060405180830381600087803b158015613c9857600080fd5b505af1158015613cac573d6000803e3d6000fd5b50505050505050505050565b508054613cc490614897565b6000825580601f10613cd4575050565b601f016020900490600052602060002090810190612abb9190613d0c565b5080546000825590600052602060002090810190612abb91905b5b80821115613d215760008155600101613d0d565b5090565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040516080810167ffffffffffffffff81118282101715613d7757613d77613d25565b60405290565b60405160a0810167ffffffffffffffff81118282101715613d7757613d77613d25565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613de757613de7613d25565b604052919050565b600067ffffffffffffffff821115613e0957613e09613d25565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f830112613e4657600080fd5b8135613e59613e5482613def565b613da0565b818152846020838601011115613e6e57600080fd5b816020850160208301376000918101602001919091529392505050565b60008060408385031215613e9e57600080fd5b823567ffffffffffffffff80821115613eb657600080fd5b613ec286838701613e35565b93506020850135915080821115613ed857600080fd5b50613ee585828601613e35565b9150509250929050565b600060208284031215613f0157600080fd5b5035919050565b60005b83811015613f23578181015183820152602001613f0b565b50506000910152565b60008151808452613f44816020860160208601613f08565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000612ad26020830184613f2c565b60008083601f840112613f9b57600080fd5b50813567ffffffffffffffff811115613fb357600080fd5b6020830191508360208260051b850101111561104157600080fd5b60008060208385031215613fe157600080fd5b823567ffffffffffffffff811115613ff857600080fd5b61400485828601613f89565b90969095509350505050565b60008151808452602080850194506020840160005b8381101561404157815187529582019590820190600101614025565b509495945050505050565b600082825180855260208086019550808260051b84010181860160005b848110156140c9578583037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001895281518051845284015160408585018190526140b581860183613f2c565b9a86019a9450505090830190600101614069565b5090979650505050505050565b600063ffffffff8083511684528060208401511660208501525060ff604083015116604084015260608201511515606084015260808201511515608084015260a082015160e060a085015261412e60e0850182614010565b905060c083015184820360c0860152614147828261404c565b95945050505050565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b828110156141c5577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526141b38583516140d6565b94509285019290850190600101614179565b5092979650505050505050565b803563ffffffff811681146141e657600080fd5b919050565b6000602082840312156141fd57600080fd5b612ad2826141d2565b73ffffffffffffffffffffffffffffffffffffffff8151168252600060208201516040602085015261423b6040850182613f2c565b949350505050565b602081526000612ad26020830184614206565b602081526000612ad260208301846140d6565b6000806040838503121561427c57600080fd5b614285836141d2565b946020939093013593505050565b6040815260006142a66040830185613f2c565b82810360208401526141478185613f2c565b600063ffffffff808351168452602081818501511681860152816040850151166040860152606084015160608601526080840151608086015260a0840151915060e060a086015261430c60e0860183614010565b60c08581015187830391880191909152805180835290830193506000918301905b8083101561434d578451825293830193600192909201919083019061432d565b509695505050505050565b602081526000612ad260208301846142b8565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b828110156141c5577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526143ce858351614206565b94509285019290850190600101614394565b600080600080604085870312156143f657600080fd5b843567ffffffffffffffff8082111561440e57600080fd5b61441a88838901613f89565b9096509450602087013591508082111561443357600080fd5b5061444087828801613f89565b95989497509550505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b805182526000602082015160e0602085015261449a60e0850182613f2c565b9050604083015184820360408601526144b38282613f2c565b9150506060830151600481106144cb576144cb61444c565b60608501526080830151600281106144e5576144e561444c565b8060808601525060a083015161451360a086018273ffffffffffffffffffffffffffffffffffffffff169052565b5060c083015161452760c086018215159052565b509392505050565b602081526000612ad2602083018461447b565b8015158114612abb57600080fd5b803560ff811681146141e657600080fd5b60008060008060008060008060c0898b03121561457d57600080fd5b614586896141d2565b9750602089013567ffffffffffffffff808211156145a357600080fd5b6145af8c838d01613f89565b909950975060408b01359150808211156145c857600080fd5b506145d58b828c01613f89565b90965094505060608901356145e981614542565b925060808901356145f981614542565b915061460760a08a01614550565b90509295985092959890939650565b600080600080600080600060a0888a03121561463157600080fd5b873567ffffffffffffffff8082111561464957600080fd5b6146558b838c01613f89565b909950975060208a013591508082111561466e57600080fd5b5061467b8a828b01613f89565b909650945050604088013561468f81614542565b9250606088013561469f81614542565b91506146ad60808901614550565b905092959891949750929550565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b828110156141c5577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc088860301845261471e85835161447b565b945092850192908501906001016146e4565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b828110156141c5577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526147938583516142b8565b94509285019290850190600101614759565b803573ffffffffffffffffffffffffffffffffffffffff811681146141e657600080fd5b6000602082840312156147db57600080fd5b612ad2826147a5565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b63ffffffff8281168282160390808211156107f2576107f2614813565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361489057614890614813565b5060010190565b600181811c908216806148ab57607f821691505b6020821081036148e4577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b600063ffffffff80831681810361490357614903614813565b6001019392505050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc183360301811261494157600080fd5b9190910192915050565b60006040823603121561495d57600080fd5b6040516040810167ffffffffffffffff828210818311171561498157614981613d25565b8160405261498e856147a5565b835260208501359150808211156149a457600080fd5b506149b136828601613e35565b60208301525092915050565b601f821115610697576000816000526020600020601f850160051c810160208610156149e65750805b601f850160051c820191505b818110156124d7578281556001016149f2565b815167ffffffffffffffff811115614a1f57614a1f613d25565b614a3381614a2d8454614897565b846149bd565b602080601f831160018114614a865760008415614a505750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556124d7565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015614ad357888601518255948401946001909101908401614ab4565b5085821015614b0f57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b600060208284031215614b3157600080fd5b815167ffffffffffffffff811115614b4857600080fd5b8201601f81018413614b5957600080fd5b8051614b67613e5482613def565b818152856020838501011115614b7c57600080fd5b614147826020830160208601613f08565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8183360301811261494157600080fd5b600060808236031215614bd357600080fd5b614bdb613d54565b614be4836141d2565b81526020808401358183015260408401356040830152606084013567ffffffffffffffff80821115614c1557600080fd5b9085019036601f830112614c2857600080fd5b813581811115614c3a57614c3a613d25565b8060051b9150614c4b848301613da0565b8181529183018401918481019036841115614c6557600080fd5b938501935b83851015614c8357843582529385019390850190614c6a565b606087015250939695505050505050565b6020808252825182820181905260009190848201906040850190845b81811015614ccc57835183529284019291840191600101614cb0565b50909695505050505050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6183360301811261494157600080fd5b8035600281106141e657600080fd5b600060a08236031215614d2d57600080fd5b614d35613d7d565b823567ffffffffffffffff80821115614d4d57600080fd5b614d5936838701613e35565b83526020850135915080821115614d6f57600080fd5b50614d7c36828601613e35565b602083015250604083013560048110614d9457600080fd5b6040820152614da560608401614d0c565b6060820152614db6608084016147a5565b608082015292915050565b6000602080835260008454614dd581614897565b8060208701526040600180841660008114614df75760018114614e3157614e61565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00851660408a0152604084151560051b8a01019550614e61565b89600052602060002060005b85811015614e585781548b8201860152908301908801614e3d565b8a016040019650505b509398975050505050505050565b600060208284031215614e8157600080fd5b8151612ad281614542565b60ff818116838216019081111561047457610474614813565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112614eda57600080fd5b83018035915067ffffffffffffffff821115614ef557600080fd5b60200191503681900382131561104157600080fd5b67ffffffffffffffff831115614f2257614f22613d25565b614f3683614f308354614897565b836149bd565b6000601f841160018114614f885760008515614f525750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b17835561501e565b6000838152602090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0861690835b82811015614fd75786850135825560209485019460019092019101614fb7565b5086821015615012577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b8181038181111561047457610474614813565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b6080815284608082015260007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8611156150a057600080fd5b8560051b808860a0850137820182810360a090810160208501526150c690820187613f2c565b91505063ffffffff8085166040840152808416606084015250969550505050505056fea164736f6c6343000818000a", } var CapabilitiesRegistryABI = CapabilitiesRegistryMetaData.ABI diff --git a/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt index 53b8a64daf..7d25f651dd 100644 --- a/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -1,5 +1,5 @@ GETH_VERSION: 1.13.8 -capabilities_registry: ../../../contracts/solc/v0.8.24/CapabilitiesRegistry/CapabilitiesRegistry.abi ../../../contracts/solc/v0.8.24/CapabilitiesRegistry/CapabilitiesRegistry.bin 3a082f0307411f41c30db26e61d59adcd5b003141a5aa8fe79d7779619028e26 +capabilities_registry: ../../../contracts/solc/v0.8.24/CapabilitiesRegistry/CapabilitiesRegistry.abi ../../../contracts/solc/v0.8.24/CapabilitiesRegistry/CapabilitiesRegistry.bin 6d2e3aa3a6f3aed2cf24b613743bb9ae4b9558f48a6864dc03b8b0ebb37235e3 feeds_consumer: ../../../contracts/solc/v0.8.24/KeystoneFeedsConsumer/KeystoneFeedsConsumer.abi ../../../contracts/solc/v0.8.24/KeystoneFeedsConsumer/KeystoneFeedsConsumer.bin f098e25df6afc100425fcad7f5107aec0844cc98315117e49da139a179d0eead forwarder: ../../../contracts/solc/v0.8.24/KeystoneForwarder/KeystoneForwarder.abi ../../../contracts/solc/v0.8.24/KeystoneForwarder/KeystoneForwarder.bin dc98a86a3775ead987b79d5b6079ee0e26f31c0626032bdd6508f986e2423227 ocr3_capability: ../../../contracts/solc/v0.8.24/OCR3Capability/OCR3Capability.abi ../../../contracts/solc/v0.8.24/OCR3Capability/OCR3Capability.bin 8bf0f53f222efce7143dea6134552eb26ea1eef845407b4475a0d79b7d7ba9f8 From ca6e1c26a331af67a1d57bf69d8160c23fc1e297 Mon Sep 17 00:00:00 2001 From: Bartek Tofel Date: Mon, 29 Jul 2024 13:33:37 +0200 Subject: [PATCH 014/115] check for nils in log processor call (#13940) --- integration-tests/docker/test_env/test_env_builder.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/integration-tests/docker/test_env/test_env_builder.go b/integration-tests/docker/test_env/test_env_builder.go index 19ab64671e..0b7c9de5ff 100644 --- a/integration-tests/docker/test_env/test_env_builder.go +++ b/integration-tests/docker/test_env/test_env_builder.go @@ -280,6 +280,9 @@ func (b *CLTestEnvBuilder) Build() (*CLClusterTestEnv, error) { // new logs can be added to the log stream, so parallel processing would get stuck on waiting for it to be unlocked LogScanningLoop: for i := 0; i < b.clNodesCount; i++ { + if b == nil || b.te == nil || b.te.ClCluster == nil || b.te.ClCluster.Nodes == nil || b.te.ClCluster.Nodes[i] == nil || len(b.te.ClCluster.Nodes)-1 < i { + continue + } // ignore count return, because we are only interested in the error _, err := logProcessor.ProcessContainerLogs(b.te.ClCluster.Nodes[i].ContainerName, processFn) if err != nil && !strings.Contains(err.Error(), testreporters.MultipleLogsAtLogLevelErr) && !strings.Contains(err.Error(), testreporters.OneLogAtLogLevelErr) { From d150bc6e11a85513a0b3443e139483a6813a8f09 Mon Sep 17 00:00:00 2001 From: Jordan Krage Date: Mon, 29 Jul 2024 19:13:26 +0200 Subject: [PATCH 015/115] bump deps (#13901) --- core/scripts/go.mod | 8 ++--- core/scripts/go.sum | 58 +++++++++++++++++++---------------- go.mod | 17 +++++++--- go.sum | 53 +++++++++++++++++--------------- integration-tests/go.mod | 8 ++--- integration-tests/go.sum | 54 +++++++++++++++++--------------- integration-tests/load/go.mod | 8 ++--- integration-tests/load/go.sum | 54 +++++++++++++++++--------------- 8 files changed, 141 insertions(+), 119 deletions(-) diff --git a/core/scripts/go.mod b/core/scripts/go.mod index 77b9d9d74d..61dd4c4b9f 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -317,7 +317,7 @@ require ( go.mongodb.org/mongo-driver v1.15.0 // indirect go.opencensus.io v0.24.0 // indirect go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin v0.49.0 // indirect - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.52.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0 // indirect go.opentelemetry.io/otel v1.28.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0 // indirect @@ -328,12 +328,12 @@ require ( go.uber.org/multierr v1.11.0 // indirect go.uber.org/ratelimit v0.3.0 // indirect go.uber.org/zap v1.27.0 // indirect - golang.org/x/arch v0.7.0 // indirect + golang.org/x/arch v0.8.0 // indirect golang.org/x/crypto v0.25.0 // indirect golang.org/x/exp v0.0.0-20240716175740-e3f259677ff7 // indirect golang.org/x/mod v0.19.0 // indirect golang.org/x/net v0.27.0 // indirect - golang.org/x/oauth2 v0.20.0 // indirect + golang.org/x/oauth2 v0.21.0 // indirect golang.org/x/sync v0.7.0 // indirect golang.org/x/sys v0.22.0 // indirect golang.org/x/term v0.22.0 // indirect @@ -341,7 +341,7 @@ require ( golang.org/x/time v0.5.0 // indirect golang.org/x/tools v0.23.0 // indirect gonum.org/v1/gonum v0.15.0 // indirect - google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 // indirect + google.golang.org/genproto v0.0.0-20240711142825-46eb208f015d // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240711142825-46eb208f015d // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240711142825-46eb208f015d // indirect google.golang.org/grpc v1.65.0 // indirect diff --git a/core/scripts/go.sum b/core/scripts/go.sum index 1704916a3c..30db21987e 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -18,22 +18,26 @@ cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHOb cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= -cloud.google.com/go v0.112.1 h1:uJSeirPke5UNZHIb4SxfZklVSiWWVqW4oXlETwZziwM= -cloud.google.com/go v0.112.1/go.mod h1:+Vbu+Y1UU+I1rjmzeMOb/8RfkKJK2Gyxi1X6jJCZLo4= +cloud.google.com/go v0.115.0 h1:CnFSK6Xo3lDYRoBKEcAtia6VSC837/ZkJuRduSFnr14= +cloud.google.com/go v0.115.0/go.mod h1:8jIM5vVgoAEoiVxQ/O4BFTfHqulPZgs/ufEzMcFMdWU= +cloud.google.com/go/auth v0.7.1 h1:Iv1bbpzJ2OIg16m94XI9/tlzZZl3cdeR3nGVGj78N7s= +cloud.google.com/go/auth v0.7.1/go.mod h1:VEc4p5NNxycWQTMQEDQF0bd6aTMb6VgYDXEwiJJQAbs= +cloud.google.com/go/auth/oauth2adapt v0.2.3 h1:MlxF+Pd3OmSudg/b1yZ5lJwoXCEaeedAguodky1PcKI= +cloud.google.com/go/auth/oauth2adapt v0.2.3/go.mod h1:tMQXOfZzFuNuUxOypHlQEXgdfX5cuhwU+ffUuXRJE8I= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/compute v1.24.0 h1:phWcR2eWzRJaL/kOiJwfFsPs4BaKq1j6vnpZrc1YlVg= -cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc= -cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= +cloud.google.com/go/compute v1.27.2 h1:5cE5hdrwJV/92ravlwIFRGnyH9CpLGhh4N0ZDVTU+BA= +cloud.google.com/go/compute/metadata v0.5.0 h1:Zr0eK8JbFv6+Wi4ilXAR8FJ3wyNdpxHKJNPos6LTZOY= +cloud.google.com/go/compute/metadata v0.5.0/go.mod h1:aHnloV2TPI38yx4s9+wAZhHykWvVCfu7hQbF+9CWoiY= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= -cloud.google.com/go/iam v1.1.6 h1:bEa06k05IO4f4uJonbB5iAgKTPpABy1ayxaIZV/GHVc= -cloud.google.com/go/iam v1.1.6/go.mod h1:O0zxdPeGBoFdWW3HWmBxJsk0pfvNM/p/qa82rWOGTwI= +cloud.google.com/go/iam v1.1.11 h1:0mQ8UKSfdHLut6pH9FM3bI55KWR46ketn0PuXleDyxw= +cloud.google.com/go/iam v1.1.11/go.mod h1:biXoiLWYIKntto2joP+62sd9uW5EpkZmKIvfNcTWlnQ= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= @@ -44,8 +48,8 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= -cloud.google.com/go/storage v1.38.0 h1:Az68ZRGlnNTpIBbLjSMIV2BDcwwXYlRlQzis0llkpJg= -cloud.google.com/go/storage v1.38.0/go.mod h1:tlUADB0mAb9BgYls9lq+8MGkfzOXuLrnHXlpHmvFJoY= +cloud.google.com/go/storage v1.43.0 h1:CcxnSohZwizt4LCzQHWvBf1/kvtHUn7gk9QERXPyXFs= +cloud.google.com/go/storage v1.43.0/go.mod h1:ajvxEa7WmZS1PxvKRq4bq0tFT3vMd502JwstCcYv0Q0= contrib.go.opencensus.io/exporter/stackdriver v0.12.6/go.mod h1:8x999/OcIPy5ivx/wDiV7Gx4D+VUPODf0mWRGRc5kSk= contrib.go.opencensus.io/exporter/stackdriver v0.13.4/go.mod h1:aXENhDJ1Y4lIg4EUaVTwzvYETVNZk10Pu26tevFKLUc= contrib.go.opencensus.io/exporter/stackdriver v0.13.5 h1:TNaexHK16gPUoc7uzELKOU7JULqccn1NDuqUxmxSqfo= @@ -638,12 +642,12 @@ github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+ github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs= -github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= +github.com/googleapis/enterprise-certificate-proxy v0.3.1 h1:SBWmZhjUDRorQxrN0nwzf+AHBxnbFjViHQS4P0yVpmQ= +github.com/googleapis/enterprise-certificate-proxy v0.3.1/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/gax-go/v2 v2.12.2 h1:mhN09QQW1jEWeMF74zGR81R30z4VJzjZsfkUhuHF+DA= -github.com/googleapis/gax-go/v2 v2.12.2/go.mod h1:61M8vcyyXR2kqKFxKrfA22jaA8JGF7Dc8App1U3H6jc= +github.com/googleapis/gax-go/v2 v2.12.0 h1:A+gCJKdRfqXkr+BIRGtZLibNXf0m1f9E4HG56etFpas= +github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8= @@ -1387,10 +1391,10 @@ go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin v0.49.0 h1:1f31+6grJmV3X4lxcEvUy13i5/kfDw1nJZwhd8mA4tg= go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin v0.49.0/go.mod h1:1P/02zM3OwkX9uki+Wmxw3a5GVb6KUXRsa7m7bOC9Fg= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.52.0 h1:vS1Ao/R55RNV4O7TA2Qopok8yN+X0LIP6RVWLFkprck= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.52.0/go.mod h1:BMsdeOxN04K0L5FNUBfjFdvwWGNe/rkmSwH4Aelu/X0= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0 h1:9G6E0TXzGFVfTnawRzrPl83iHOAV7L8NJiR8RSGYV1g= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0/go.mod h1:azvtTADFQJA8mX80jIH/akaE7h+dbm/sVuaHqN13w74= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 h1:4K4tsIXefpVJtvA/8srF4V4y0akAoPHkIslgAkjixJA= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0/go.mod h1:jjdQuTGVsXV4vSs+CJ2qYDeDPf9yIJV23qlIzBm73Vg= go.opentelemetry.io/contrib/propagators/b3 v1.24.0 h1:n4xwCdTx3pZqZs2CjS/CUZAs03y3dZcGhC/FepKtEUY= go.opentelemetry.io/contrib/propagators/b3 v1.24.0/go.mod h1:k5wRxKRU2uXx2F8uNJ4TaonuEO/V7/5xoz7kdsDACT8= go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo= @@ -1403,8 +1407,8 @@ go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6b go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s= go.opentelemetry.io/otel/sdk v1.28.0 h1:b9d7hIry8yZsgtbmM0DKyPWMMUMlK9NEKuIG4aBqWyE= go.opentelemetry.io/otel/sdk v1.28.0/go.mod h1:oYj7ClPUA7Iw3m+r7GeEjz0qckQRJK2B8zjcZEfu7Pg= -go.opentelemetry.io/otel/sdk/metric v1.21.0 h1:smhI5oD714d6jHE6Tie36fPx4WDFIg+Y6RfAY4ICcR0= -go.opentelemetry.io/otel/sdk/metric v1.21.0/go.mod h1:FJ8RAsoPGv/wYMgBdUJXOm+6pzFY3YdljnXtv1SBE8Q= +go.opentelemetry.io/otel/sdk/metric v1.28.0 h1:OkuaKgKrgAbYrrY0t92c+cC+2F6hsFNnCQArXCKlg08= +go.opentelemetry.io/otel/sdk/metric v1.28.0/go.mod h1:cWPjykihLAPvXKi4iZc1dpER3Jdq2Z0YLse3moQUCpg= go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g= go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI= go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= @@ -1439,8 +1443,8 @@ go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= -golang.org/x/arch v0.7.0 h1:pskyeJh/3AmoQ8CPE95vxHLqp1G1GfGNXTmcl9NEKTc= -golang.org/x/arch v0.7.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= +golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc= +golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -1578,8 +1582,8 @@ golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.20.0 h1:4mQdhULixXKP1rwYBW0vAijoXnkTG0BLCDRzfe1idMo= -golang.org/x/oauth2 v0.20.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= +golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1807,8 +1811,8 @@ google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz513 google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= -google.golang.org/api v0.169.0 h1:QwWPy71FgMWqJN/l6jVlFHUa29a7dcUy02I8o799nPY= -google.golang.org/api v0.169.0/go.mod h1:gpNOiMA2tZ4mf5R9Iwf4rK/Dcz0fbdIgWYWVoxmsyLg= +google.golang.org/api v0.188.0 h1:51y8fJ/b1AaaBRJr4yWm96fPcuxSo0JcegXE3DaHQHw= +google.golang.org/api v0.188.0/go.mod h1:VR0d+2SIiWOYG3r/jdm7adPW9hI2aRv9ETOSCQ9Beag= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -1861,8 +1865,8 @@ google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210401141331-865547bb08e2/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= -google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 h1:9+tzLLstTlPTRyJTh+ah5wIMsBW5c4tQwGTN3thOW9Y= -google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9/go.mod h1:mqHbVIp48Muh7Ywss/AD6I5kNVKZMmAa/QEW58Gxp2s= +google.golang.org/genproto v0.0.0-20240711142825-46eb208f015d h1:/hmn0Ku5kWij/kjGsrcJeC1T/MrJi2iNWwgAqrihFwc= +google.golang.org/genproto v0.0.0-20240711142825-46eb208f015d/go.mod h1:FfBgJBJg9GcpPvKIuHSZ/aE1g2ecGL74upMzGZjiGEY= google.golang.org/genproto/googleapis/api v0.0.0-20240711142825-46eb208f015d h1:kHjw/5UfflP/L5EbledDrcG4C2597RtymmGRZvHiCuY= google.golang.org/genproto/googleapis/api v0.0.0-20240711142825-46eb208f015d/go.mod h1:mw8MG/Qz5wfgYr6VqVCiZcHe/GJEfI+oGGDCohaVgB0= google.golang.org/genproto/googleapis/rpc v0.0.0-20240711142825-46eb208f015d h1:JU0iKnSg02Gmb5ZdV8nYsKEKsP6o/FGVWTrw4i1DA9A= diff --git a/go.mod b/go.mod index 2f531d03a8..ed4766196a 100644 --- a/go.mod +++ b/go.mod @@ -115,6 +115,11 @@ require ( ) require ( + cloud.google.com/go/auth v0.7.1 // indirect + cloud.google.com/go/auth/oauth2adapt v0.2.3 // indirect + cloud.google.com/go/compute/metadata v0.5.0 // indirect + cloud.google.com/go/iam v1.1.11 // indirect + cloud.google.com/go/storage v1.43.0 // indirect contrib.go.opencensus.io/exporter/stackdriver v0.13.5 // indirect cosmossdk.io/api v0.3.1 // indirect cosmossdk.io/core v0.5.1 // indirect @@ -213,8 +218,6 @@ require ( github.com/google/go-cmp v0.6.0 // indirect github.com/google/go-tpm v0.9.0 // indirect github.com/google/gofuzz v1.2.0 // indirect - github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect - github.com/googleapis/gax-go/v2 v2.12.2 // indirect github.com/gorilla/context v1.1.1 // indirect github.com/grafana/pyroscope-go/godeltaprof v0.1.6 // indirect github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect @@ -318,17 +321,21 @@ require ( go.etcd.io/bbolt v1.3.7 // indirect go.mongodb.org/mongo-driver v1.15.0 // indirect go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.52.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0 // indirect go.opentelemetry.io/otel/metric v1.28.0 // indirect go.opentelemetry.io/otel/sdk v1.28.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.28.0 // indirect go.opentelemetry.io/otel/trace v1.28.0 // indirect go.opentelemetry.io/proto/otlp v1.3.1 // indirect go.uber.org/ratelimit v0.3.0 // indirect - golang.org/x/arch v0.7.0 // indirect + golang.org/x/arch v0.8.0 // indirect + golang.org/x/oauth2 v0.21.0 // indirect golang.org/x/sys v0.22.0 // indirect - google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 // indirect + google.golang.org/api v0.188.0 // indirect + google.golang.org/genproto v0.0.0-20240711142825-46eb208f015d // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240711142825-46eb208f015d // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240711142825-46eb208f015d // indirect gopkg.in/guregu/null.v2 v2.1.2 // indirect diff --git a/go.sum b/go.sum index 4851cd9e75..c86afe1128 100644 --- a/go.sum +++ b/go.sum @@ -18,22 +18,25 @@ cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHOb cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= -cloud.google.com/go v0.112.1 h1:uJSeirPke5UNZHIb4SxfZklVSiWWVqW4oXlETwZziwM= -cloud.google.com/go v0.112.1/go.mod h1:+Vbu+Y1UU+I1rjmzeMOb/8RfkKJK2Gyxi1X6jJCZLo4= +cloud.google.com/go v0.115.0 h1:CnFSK6Xo3lDYRoBKEcAtia6VSC837/ZkJuRduSFnr14= +cloud.google.com/go v0.115.0/go.mod h1:8jIM5vVgoAEoiVxQ/O4BFTfHqulPZgs/ufEzMcFMdWU= +cloud.google.com/go/auth v0.7.1 h1:Iv1bbpzJ2OIg16m94XI9/tlzZZl3cdeR3nGVGj78N7s= +cloud.google.com/go/auth v0.7.1/go.mod h1:VEc4p5NNxycWQTMQEDQF0bd6aTMb6VgYDXEwiJJQAbs= +cloud.google.com/go/auth/oauth2adapt v0.2.3 h1:MlxF+Pd3OmSudg/b1yZ5lJwoXCEaeedAguodky1PcKI= +cloud.google.com/go/auth/oauth2adapt v0.2.3/go.mod h1:tMQXOfZzFuNuUxOypHlQEXgdfX5cuhwU+ffUuXRJE8I= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/compute v1.24.0 h1:phWcR2eWzRJaL/kOiJwfFsPs4BaKq1j6vnpZrc1YlVg= -cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc= -cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= +cloud.google.com/go/compute/metadata v0.5.0 h1:Zr0eK8JbFv6+Wi4ilXAR8FJ3wyNdpxHKJNPos6LTZOY= +cloud.google.com/go/compute/metadata v0.5.0/go.mod h1:aHnloV2TPI38yx4s9+wAZhHykWvVCfu7hQbF+9CWoiY= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= -cloud.google.com/go/iam v1.1.6 h1:bEa06k05IO4f4uJonbB5iAgKTPpABy1ayxaIZV/GHVc= -cloud.google.com/go/iam v1.1.6/go.mod h1:O0zxdPeGBoFdWW3HWmBxJsk0pfvNM/p/qa82rWOGTwI= +cloud.google.com/go/iam v1.1.11 h1:0mQ8UKSfdHLut6pH9FM3bI55KWR46ketn0PuXleDyxw= +cloud.google.com/go/iam v1.1.11/go.mod h1:biXoiLWYIKntto2joP+62sd9uW5EpkZmKIvfNcTWlnQ= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= @@ -44,8 +47,8 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= -cloud.google.com/go/storage v1.38.0 h1:Az68ZRGlnNTpIBbLjSMIV2BDcwwXYlRlQzis0llkpJg= -cloud.google.com/go/storage v1.38.0/go.mod h1:tlUADB0mAb9BgYls9lq+8MGkfzOXuLrnHXlpHmvFJoY= +cloud.google.com/go/storage v1.43.0 h1:CcxnSohZwizt4LCzQHWvBf1/kvtHUn7gk9QERXPyXFs= +cloud.google.com/go/storage v1.43.0/go.mod h1:ajvxEa7WmZS1PxvKRq4bq0tFT3vMd502JwstCcYv0Q0= contrib.go.opencensus.io/exporter/stackdriver v0.12.6/go.mod h1:8x999/OcIPy5ivx/wDiV7Gx4D+VUPODf0mWRGRc5kSk= contrib.go.opencensus.io/exporter/stackdriver v0.13.4/go.mod h1:aXENhDJ1Y4lIg4EUaVTwzvYETVNZk10Pu26tevFKLUc= contrib.go.opencensus.io/exporter/stackdriver v0.13.5 h1:TNaexHK16gPUoc7uzELKOU7JULqccn1NDuqUxmxSqfo= @@ -605,8 +608,8 @@ github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfF github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/gax-go/v2 v2.12.2 h1:mhN09QQW1jEWeMF74zGR81R30z4VJzjZsfkUhuHF+DA= -github.com/googleapis/gax-go/v2 v2.12.2/go.mod h1:61M8vcyyXR2kqKFxKrfA22jaA8JGF7Dc8App1U3H6jc= +github.com/googleapis/gax-go/v2 v2.12.5 h1:8gw9KZK8TiVKB6q3zHY3SBzLnrGp6HQjyfYBYGmXdxA= +github.com/googleapis/gax-go/v2 v2.12.5/go.mod h1:BUDKcWo+RaKq5SC9vVYL0wLADa3VcfswbOMMRmB9H3E= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8= @@ -1337,10 +1340,10 @@ go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin v0.49.0 h1:1f31+6grJmV3X4lxcEvUy13i5/kfDw1nJZwhd8mA4tg= go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin v0.49.0/go.mod h1:1P/02zM3OwkX9uki+Wmxw3a5GVb6KUXRsa7m7bOC9Fg= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.52.0 h1:vS1Ao/R55RNV4O7TA2Qopok8yN+X0LIP6RVWLFkprck= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.52.0/go.mod h1:BMsdeOxN04K0L5FNUBfjFdvwWGNe/rkmSwH4Aelu/X0= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0 h1:9G6E0TXzGFVfTnawRzrPl83iHOAV7L8NJiR8RSGYV1g= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0/go.mod h1:azvtTADFQJA8mX80jIH/akaE7h+dbm/sVuaHqN13w74= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 h1:4K4tsIXefpVJtvA/8srF4V4y0akAoPHkIslgAkjixJA= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0/go.mod h1:jjdQuTGVsXV4vSs+CJ2qYDeDPf9yIJV23qlIzBm73Vg= go.opentelemetry.io/contrib/propagators/b3 v1.24.0 h1:n4xwCdTx3pZqZs2CjS/CUZAs03y3dZcGhC/FepKtEUY= go.opentelemetry.io/contrib/propagators/b3 v1.24.0/go.mod h1:k5wRxKRU2uXx2F8uNJ4TaonuEO/V7/5xoz7kdsDACT8= go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo= @@ -1353,8 +1356,8 @@ go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6b go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s= go.opentelemetry.io/otel/sdk v1.28.0 h1:b9d7hIry8yZsgtbmM0DKyPWMMUMlK9NEKuIG4aBqWyE= go.opentelemetry.io/otel/sdk v1.28.0/go.mod h1:oYj7ClPUA7Iw3m+r7GeEjz0qckQRJK2B8zjcZEfu7Pg= -go.opentelemetry.io/otel/sdk/metric v1.21.0 h1:smhI5oD714d6jHE6Tie36fPx4WDFIg+Y6RfAY4ICcR0= -go.opentelemetry.io/otel/sdk/metric v1.21.0/go.mod h1:FJ8RAsoPGv/wYMgBdUJXOm+6pzFY3YdljnXtv1SBE8Q= +go.opentelemetry.io/otel/sdk/metric v1.28.0 h1:OkuaKgKrgAbYrrY0t92c+cC+2F6hsFNnCQArXCKlg08= +go.opentelemetry.io/otel/sdk/metric v1.28.0/go.mod h1:cWPjykihLAPvXKi4iZc1dpER3Jdq2Z0YLse3moQUCpg= go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g= go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI= go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= @@ -1389,8 +1392,8 @@ go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= -golang.org/x/arch v0.7.0 h1:pskyeJh/3AmoQ8CPE95vxHLqp1G1GfGNXTmcl9NEKTc= -golang.org/x/arch v0.7.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= +golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc= +golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -1527,8 +1530,8 @@ golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.20.0 h1:4mQdhULixXKP1rwYBW0vAijoXnkTG0BLCDRzfe1idMo= -golang.org/x/oauth2 v0.20.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= +golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1757,8 +1760,8 @@ google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz513 google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= -google.golang.org/api v0.169.0 h1:QwWPy71FgMWqJN/l6jVlFHUa29a7dcUy02I8o799nPY= -google.golang.org/api v0.169.0/go.mod h1:gpNOiMA2tZ4mf5R9Iwf4rK/Dcz0fbdIgWYWVoxmsyLg= +google.golang.org/api v0.188.0 h1:51y8fJ/b1AaaBRJr4yWm96fPcuxSo0JcegXE3DaHQHw= +google.golang.org/api v0.188.0/go.mod h1:VR0d+2SIiWOYG3r/jdm7adPW9hI2aRv9ETOSCQ9Beag= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -1811,8 +1814,8 @@ google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210401141331-865547bb08e2/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= -google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 h1:9+tzLLstTlPTRyJTh+ah5wIMsBW5c4tQwGTN3thOW9Y= -google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9/go.mod h1:mqHbVIp48Muh7Ywss/AD6I5kNVKZMmAa/QEW58Gxp2s= +google.golang.org/genproto v0.0.0-20240711142825-46eb208f015d h1:/hmn0Ku5kWij/kjGsrcJeC1T/MrJi2iNWwgAqrihFwc= +google.golang.org/genproto v0.0.0-20240711142825-46eb208f015d/go.mod h1:FfBgJBJg9GcpPvKIuHSZ/aE1g2ecGL74upMzGZjiGEY= google.golang.org/genproto/googleapis/api v0.0.0-20240711142825-46eb208f015d h1:kHjw/5UfflP/L5EbledDrcG4C2597RtymmGRZvHiCuY= google.golang.org/genproto/googleapis/api v0.0.0-20240711142825-46eb208f015d/go.mod h1:mw8MG/Qz5wfgYr6VqVCiZcHe/GJEfI+oGGDCohaVgB0= google.golang.org/genproto/googleapis/rpc v0.0.0-20240711142825-46eb208f015d h1:JU0iKnSg02Gmb5ZdV8nYsKEKsP6o/FGVWTrw4i1DA9A= diff --git a/integration-tests/go.mod b/integration-tests/go.mod index 6d816df2a4..267332eba7 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -430,8 +430,8 @@ require ( go.opencensus.io v0.24.0 // indirect go.opentelemetry.io/collector/pdata v1.0.0-rcv0016 // indirect go.opentelemetry.io/collector/semconv v0.87.0 // indirect - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.52.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 // indirect go.opentelemetry.io/otel v1.28.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0 // indirect @@ -445,7 +445,7 @@ require ( go.uber.org/multierr v1.11.0 // indirect go.uber.org/ratelimit v0.3.0 // indirect go4.org/netipx v0.0.0-20230125063823-8449b0a6169f // indirect - golang.org/x/arch v0.7.0 // indirect + golang.org/x/arch v0.8.0 // indirect golang.org/x/crypto v0.25.0 // indirect golang.org/x/exp v0.0.0-20240716175740-e3f259677ff7 // indirect golang.org/x/mod v0.19.0 // indirect @@ -457,7 +457,7 @@ require ( golang.org/x/tools v0.23.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect gonum.org/v1/gonum v0.15.0 // indirect - google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 // indirect + google.golang.org/genproto v0.0.0-20240711142825-46eb208f015d // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240711142825-46eb208f015d // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240711142825-46eb208f015d // indirect google.golang.org/grpc v1.65.0 // indirect diff --git a/integration-tests/go.sum b/integration-tests/go.sum index 24120b51ba..df4008a1e1 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -18,23 +18,27 @@ cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHOb cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= -cloud.google.com/go v0.112.1 h1:uJSeirPke5UNZHIb4SxfZklVSiWWVqW4oXlETwZziwM= -cloud.google.com/go v0.112.1/go.mod h1:+Vbu+Y1UU+I1rjmzeMOb/8RfkKJK2Gyxi1X6jJCZLo4= +cloud.google.com/go v0.115.0 h1:CnFSK6Xo3lDYRoBKEcAtia6VSC837/ZkJuRduSFnr14= +cloud.google.com/go v0.115.0/go.mod h1:8jIM5vVgoAEoiVxQ/O4BFTfHqulPZgs/ufEzMcFMdWU= +cloud.google.com/go/auth v0.7.1 h1:Iv1bbpzJ2OIg16m94XI9/tlzZZl3cdeR3nGVGj78N7s= +cloud.google.com/go/auth v0.7.1/go.mod h1:VEc4p5NNxycWQTMQEDQF0bd6aTMb6VgYDXEwiJJQAbs= +cloud.google.com/go/auth/oauth2adapt v0.2.3 h1:MlxF+Pd3OmSudg/b1yZ5lJwoXCEaeedAguodky1PcKI= +cloud.google.com/go/auth/oauth2adapt v0.2.3/go.mod h1:tMQXOfZzFuNuUxOypHlQEXgdfX5cuhwU+ffUuXRJE8I= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/compute v1.24.0 h1:phWcR2eWzRJaL/kOiJwfFsPs4BaKq1j6vnpZrc1YlVg= +cloud.google.com/go/compute v1.27.2 h1:5cE5hdrwJV/92ravlwIFRGnyH9CpLGhh4N0ZDVTU+BA= cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= -cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc= -cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= +cloud.google.com/go/compute/metadata v0.5.0 h1:Zr0eK8JbFv6+Wi4ilXAR8FJ3wyNdpxHKJNPos6LTZOY= +cloud.google.com/go/compute/metadata v0.5.0/go.mod h1:aHnloV2TPI38yx4s9+wAZhHykWvVCfu7hQbF+9CWoiY= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= -cloud.google.com/go/iam v1.1.6 h1:bEa06k05IO4f4uJonbB5iAgKTPpABy1ayxaIZV/GHVc= -cloud.google.com/go/iam v1.1.6/go.mod h1:O0zxdPeGBoFdWW3HWmBxJsk0pfvNM/p/qa82rWOGTwI= +cloud.google.com/go/iam v1.1.11 h1:0mQ8UKSfdHLut6pH9FM3bI55KWR46ketn0PuXleDyxw= +cloud.google.com/go/iam v1.1.11/go.mod h1:biXoiLWYIKntto2joP+62sd9uW5EpkZmKIvfNcTWlnQ= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= @@ -45,8 +49,8 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= -cloud.google.com/go/storage v1.38.0 h1:Az68ZRGlnNTpIBbLjSMIV2BDcwwXYlRlQzis0llkpJg= -cloud.google.com/go/storage v1.38.0/go.mod h1:tlUADB0mAb9BgYls9lq+8MGkfzOXuLrnHXlpHmvFJoY= +cloud.google.com/go/storage v1.43.0 h1:CcxnSohZwizt4LCzQHWvBf1/kvtHUn7gk9QERXPyXFs= +cloud.google.com/go/storage v1.43.0/go.mod h1:ajvxEa7WmZS1PxvKRq4bq0tFT3vMd502JwstCcYv0Q0= contrib.go.opencensus.io/exporter/stackdriver v0.12.6/go.mod h1:8x999/OcIPy5ivx/wDiV7Gx4D+VUPODf0mWRGRc5kSk= contrib.go.opencensus.io/exporter/stackdriver v0.13.4/go.mod h1:aXENhDJ1Y4lIg4EUaVTwzvYETVNZk10Pu26tevFKLUc= contrib.go.opencensus.io/exporter/stackdriver v0.13.5 h1:TNaexHK16gPUoc7uzELKOU7JULqccn1NDuqUxmxSqfo= @@ -815,12 +819,12 @@ github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+ github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs= -github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= +github.com/googleapis/enterprise-certificate-proxy v0.2.5 h1:UR4rDjcgpgEnqpIEvkiqTYKBCKLNmlge2eVjoZfySzM= +github.com/googleapis/enterprise-certificate-proxy v0.2.5/go.mod h1:RxW0N9901Cko1VOCW3SXCpWP+mlIEkk2tP7jnHy9a3w= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/gax-go/v2 v2.12.2 h1:mhN09QQW1jEWeMF74zGR81R30z4VJzjZsfkUhuHF+DA= -github.com/googleapis/gax-go/v2 v2.12.2/go.mod h1:61M8vcyyXR2kqKFxKrfA22jaA8JGF7Dc8App1U3H6jc= +github.com/googleapis/gax-go/v2 v2.12.0 h1:A+gCJKdRfqXkr+BIRGtZLibNXf0m1f9E4HG56etFpas= +github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/gophercloud/gophercloud v1.5.0 h1:cDN6XFCLKiiqvYpjQLq9AiM7RDRbIC9450WpPH+yvXo= github.com/gophercloud/gophercloud v1.5.0/go.mod h1:aAVqcocTSXh2vYFZ1JTvx4EQmfgzxRcNupUfxZbBNDM= @@ -1728,10 +1732,10 @@ go.opentelemetry.io/collector/semconv v0.87.0 h1:BsG1jdLLRCBRlvUujk4QA86af7r/ZXn go.opentelemetry.io/collector/semconv v0.87.0/go.mod h1:j/8THcqVxFna1FpvA2zYIsUperEtOaRaqoLYIN4doWw= go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin v0.49.0 h1:1f31+6grJmV3X4lxcEvUy13i5/kfDw1nJZwhd8mA4tg= go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin v0.49.0/go.mod h1:1P/02zM3OwkX9uki+Wmxw3a5GVb6KUXRsa7m7bOC9Fg= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.52.0 h1:vS1Ao/R55RNV4O7TA2Qopok8yN+X0LIP6RVWLFkprck= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.52.0/go.mod h1:BMsdeOxN04K0L5FNUBfjFdvwWGNe/rkmSwH4Aelu/X0= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0 h1:9G6E0TXzGFVfTnawRzrPl83iHOAV7L8NJiR8RSGYV1g= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0/go.mod h1:azvtTADFQJA8mX80jIH/akaE7h+dbm/sVuaHqN13w74= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 h1:4K4tsIXefpVJtvA/8srF4V4y0akAoPHkIslgAkjixJA= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0/go.mod h1:jjdQuTGVsXV4vSs+CJ2qYDeDPf9yIJV23qlIzBm73Vg= go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo= go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 h1:3Q/xZUyC1BBkualc9ROb4G8qkH90LXEIICcs5zv1OYY= @@ -1744,8 +1748,8 @@ go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6b go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s= go.opentelemetry.io/otel/sdk v1.28.0 h1:b9d7hIry8yZsgtbmM0DKyPWMMUMlK9NEKuIG4aBqWyE= go.opentelemetry.io/otel/sdk v1.28.0/go.mod h1:oYj7ClPUA7Iw3m+r7GeEjz0qckQRJK2B8zjcZEfu7Pg= -go.opentelemetry.io/otel/sdk/metric v1.21.0 h1:smhI5oD714d6jHE6Tie36fPx4WDFIg+Y6RfAY4ICcR0= -go.opentelemetry.io/otel/sdk/metric v1.21.0/go.mod h1:FJ8RAsoPGv/wYMgBdUJXOm+6pzFY3YdljnXtv1SBE8Q= +go.opentelemetry.io/otel/sdk/metric v1.28.0 h1:OkuaKgKrgAbYrrY0t92c+cC+2F6hsFNnCQArXCKlg08= +go.opentelemetry.io/otel/sdk/metric v1.28.0/go.mod h1:cWPjykihLAPvXKi4iZc1dpER3Jdq2Z0YLse3moQUCpg= go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g= go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI= go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= @@ -1784,8 +1788,8 @@ go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= go4.org/netipx v0.0.0-20230125063823-8449b0a6169f h1:ketMxHg+vWm3yccyYiq+uK8D3fRmna2Fcj+awpQp84s= go4.org/netipx v0.0.0-20230125063823-8449b0a6169f/go.mod h1:tgPU4N2u9RByaTN3NC2p9xOzyFpte4jYwsIIRF7XlSc= golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= -golang.org/x/arch v0.7.0 h1:pskyeJh/3AmoQ8CPE95vxHLqp1G1GfGNXTmcl9NEKTc= -golang.org/x/arch v0.7.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= +golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc= +golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -2190,8 +2194,8 @@ google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz513 google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= -google.golang.org/api v0.169.0 h1:QwWPy71FgMWqJN/l6jVlFHUa29a7dcUy02I8o799nPY= -google.golang.org/api v0.169.0/go.mod h1:gpNOiMA2tZ4mf5R9Iwf4rK/Dcz0fbdIgWYWVoxmsyLg= +google.golang.org/api v0.188.0 h1:51y8fJ/b1AaaBRJr4yWm96fPcuxSo0JcegXE3DaHQHw= +google.golang.org/api v0.188.0/go.mod h1:VR0d+2SIiWOYG3r/jdm7adPW9hI2aRv9ETOSCQ9Beag= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -2244,8 +2248,8 @@ google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210401141331-865547bb08e2/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= -google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 h1:9+tzLLstTlPTRyJTh+ah5wIMsBW5c4tQwGTN3thOW9Y= -google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9/go.mod h1:mqHbVIp48Muh7Ywss/AD6I5kNVKZMmAa/QEW58Gxp2s= +google.golang.org/genproto v0.0.0-20240711142825-46eb208f015d h1:/hmn0Ku5kWij/kjGsrcJeC1T/MrJi2iNWwgAqrihFwc= +google.golang.org/genproto v0.0.0-20240711142825-46eb208f015d/go.mod h1:FfBgJBJg9GcpPvKIuHSZ/aE1g2ecGL74upMzGZjiGEY= google.golang.org/genproto/googleapis/api v0.0.0-20240711142825-46eb208f015d h1:kHjw/5UfflP/L5EbledDrcG4C2597RtymmGRZvHiCuY= google.golang.org/genproto/googleapis/api v0.0.0-20240711142825-46eb208f015d/go.mod h1:mw8MG/Qz5wfgYr6VqVCiZcHe/GJEfI+oGGDCohaVgB0= google.golang.org/genproto/googleapis/rpc v0.0.0-20240711142825-46eb208f015d h1:JU0iKnSg02Gmb5ZdV8nYsKEKsP6o/FGVWTrw4i1DA9A= diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index 5e6d5af25b..eb66376a07 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -427,8 +427,8 @@ require ( go.opencensus.io v0.24.0 // indirect go.opentelemetry.io/collector/pdata v1.0.0-rcv0016 // indirect go.opentelemetry.io/collector/semconv v0.87.0 // indirect - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.52.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 // indirect go.opentelemetry.io/otel v1.28.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0 // indirect @@ -442,7 +442,7 @@ require ( go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect go4.org/netipx v0.0.0-20230125063823-8449b0a6169f // indirect - golang.org/x/arch v0.7.0 // indirect + golang.org/x/arch v0.8.0 // indirect golang.org/x/crypto v0.25.0 // indirect golang.org/x/exp v0.0.0-20240716175740-e3f259677ff7 // indirect golang.org/x/mod v0.19.0 // indirect @@ -456,7 +456,7 @@ require ( golang.org/x/tools v0.23.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect gonum.org/v1/gonum v0.15.0 // indirect - google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 // indirect + google.golang.org/genproto v0.0.0-20240711142825-46eb208f015d // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240711142825-46eb208f015d // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240711142825-46eb208f015d // indirect google.golang.org/grpc v1.65.0 // indirect diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index a1797f1459..9b6dcc768f 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -18,23 +18,27 @@ cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHOb cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= -cloud.google.com/go v0.112.1 h1:uJSeirPke5UNZHIb4SxfZklVSiWWVqW4oXlETwZziwM= -cloud.google.com/go v0.112.1/go.mod h1:+Vbu+Y1UU+I1rjmzeMOb/8RfkKJK2Gyxi1X6jJCZLo4= +cloud.google.com/go v0.115.0 h1:CnFSK6Xo3lDYRoBKEcAtia6VSC837/ZkJuRduSFnr14= +cloud.google.com/go v0.115.0/go.mod h1:8jIM5vVgoAEoiVxQ/O4BFTfHqulPZgs/ufEzMcFMdWU= +cloud.google.com/go/auth v0.7.1 h1:Iv1bbpzJ2OIg16m94XI9/tlzZZl3cdeR3nGVGj78N7s= +cloud.google.com/go/auth v0.7.1/go.mod h1:VEc4p5NNxycWQTMQEDQF0bd6aTMb6VgYDXEwiJJQAbs= +cloud.google.com/go/auth/oauth2adapt v0.2.3 h1:MlxF+Pd3OmSudg/b1yZ5lJwoXCEaeedAguodky1PcKI= +cloud.google.com/go/auth/oauth2adapt v0.2.3/go.mod h1:tMQXOfZzFuNuUxOypHlQEXgdfX5cuhwU+ffUuXRJE8I= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/compute v1.24.0 h1:phWcR2eWzRJaL/kOiJwfFsPs4BaKq1j6vnpZrc1YlVg= +cloud.google.com/go/compute v1.27.2 h1:5cE5hdrwJV/92ravlwIFRGnyH9CpLGhh4N0ZDVTU+BA= cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= -cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc= -cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= +cloud.google.com/go/compute/metadata v0.5.0 h1:Zr0eK8JbFv6+Wi4ilXAR8FJ3wyNdpxHKJNPos6LTZOY= +cloud.google.com/go/compute/metadata v0.5.0/go.mod h1:aHnloV2TPI38yx4s9+wAZhHykWvVCfu7hQbF+9CWoiY= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= -cloud.google.com/go/iam v1.1.6 h1:bEa06k05IO4f4uJonbB5iAgKTPpABy1ayxaIZV/GHVc= -cloud.google.com/go/iam v1.1.6/go.mod h1:O0zxdPeGBoFdWW3HWmBxJsk0pfvNM/p/qa82rWOGTwI= +cloud.google.com/go/iam v1.1.11 h1:0mQ8UKSfdHLut6pH9FM3bI55KWR46ketn0PuXleDyxw= +cloud.google.com/go/iam v1.1.11/go.mod h1:biXoiLWYIKntto2joP+62sd9uW5EpkZmKIvfNcTWlnQ= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= @@ -45,8 +49,8 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= -cloud.google.com/go/storage v1.38.0 h1:Az68ZRGlnNTpIBbLjSMIV2BDcwwXYlRlQzis0llkpJg= -cloud.google.com/go/storage v1.38.0/go.mod h1:tlUADB0mAb9BgYls9lq+8MGkfzOXuLrnHXlpHmvFJoY= +cloud.google.com/go/storage v1.43.0 h1:CcxnSohZwizt4LCzQHWvBf1/kvtHUn7gk9QERXPyXFs= +cloud.google.com/go/storage v1.43.0/go.mod h1:ajvxEa7WmZS1PxvKRq4bq0tFT3vMd502JwstCcYv0Q0= contrib.go.opencensus.io/exporter/stackdriver v0.12.6/go.mod h1:8x999/OcIPy5ivx/wDiV7Gx4D+VUPODf0mWRGRc5kSk= contrib.go.opencensus.io/exporter/stackdriver v0.13.4/go.mod h1:aXENhDJ1Y4lIg4EUaVTwzvYETVNZk10Pu26tevFKLUc= contrib.go.opencensus.io/exporter/stackdriver v0.13.5 h1:TNaexHK16gPUoc7uzELKOU7JULqccn1NDuqUxmxSqfo= @@ -805,12 +809,12 @@ github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+ github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs= -github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= +github.com/googleapis/enterprise-certificate-proxy v0.2.5 h1:UR4rDjcgpgEnqpIEvkiqTYKBCKLNmlge2eVjoZfySzM= +github.com/googleapis/enterprise-certificate-proxy v0.2.5/go.mod h1:RxW0N9901Cko1VOCW3SXCpWP+mlIEkk2tP7jnHy9a3w= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/gax-go/v2 v2.12.2 h1:mhN09QQW1jEWeMF74zGR81R30z4VJzjZsfkUhuHF+DA= -github.com/googleapis/gax-go/v2 v2.12.2/go.mod h1:61M8vcyyXR2kqKFxKrfA22jaA8JGF7Dc8App1U3H6jc= +github.com/googleapis/gax-go/v2 v2.12.0 h1:A+gCJKdRfqXkr+BIRGtZLibNXf0m1f9E4HG56etFpas= +github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/gophercloud/gophercloud v1.5.0 h1:cDN6XFCLKiiqvYpjQLq9AiM7RDRbIC9450WpPH+yvXo= github.com/gophercloud/gophercloud v1.5.0/go.mod h1:aAVqcocTSXh2vYFZ1JTvx4EQmfgzxRcNupUfxZbBNDM= @@ -1710,10 +1714,10 @@ go.opentelemetry.io/collector/semconv v0.87.0 h1:BsG1jdLLRCBRlvUujk4QA86af7r/ZXn go.opentelemetry.io/collector/semconv v0.87.0/go.mod h1:j/8THcqVxFna1FpvA2zYIsUperEtOaRaqoLYIN4doWw= go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin v0.49.0 h1:1f31+6grJmV3X4lxcEvUy13i5/kfDw1nJZwhd8mA4tg= go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin v0.49.0/go.mod h1:1P/02zM3OwkX9uki+Wmxw3a5GVb6KUXRsa7m7bOC9Fg= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.52.0 h1:vS1Ao/R55RNV4O7TA2Qopok8yN+X0LIP6RVWLFkprck= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.52.0/go.mod h1:BMsdeOxN04K0L5FNUBfjFdvwWGNe/rkmSwH4Aelu/X0= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0 h1:9G6E0TXzGFVfTnawRzrPl83iHOAV7L8NJiR8RSGYV1g= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.53.0/go.mod h1:azvtTADFQJA8mX80jIH/akaE7h+dbm/sVuaHqN13w74= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 h1:4K4tsIXefpVJtvA/8srF4V4y0akAoPHkIslgAkjixJA= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0/go.mod h1:jjdQuTGVsXV4vSs+CJ2qYDeDPf9yIJV23qlIzBm73Vg= go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo= go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 h1:3Q/xZUyC1BBkualc9ROb4G8qkH90LXEIICcs5zv1OYY= @@ -1726,8 +1730,8 @@ go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6b go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s= go.opentelemetry.io/otel/sdk v1.28.0 h1:b9d7hIry8yZsgtbmM0DKyPWMMUMlK9NEKuIG4aBqWyE= go.opentelemetry.io/otel/sdk v1.28.0/go.mod h1:oYj7ClPUA7Iw3m+r7GeEjz0qckQRJK2B8zjcZEfu7Pg= -go.opentelemetry.io/otel/sdk/metric v1.21.0 h1:smhI5oD714d6jHE6Tie36fPx4WDFIg+Y6RfAY4ICcR0= -go.opentelemetry.io/otel/sdk/metric v1.21.0/go.mod h1:FJ8RAsoPGv/wYMgBdUJXOm+6pzFY3YdljnXtv1SBE8Q= +go.opentelemetry.io/otel/sdk/metric v1.28.0 h1:OkuaKgKrgAbYrrY0t92c+cC+2F6hsFNnCQArXCKlg08= +go.opentelemetry.io/otel/sdk/metric v1.28.0/go.mod h1:cWPjykihLAPvXKi4iZc1dpER3Jdq2Z0YLse3moQUCpg= go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g= go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI= go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= @@ -1766,8 +1770,8 @@ go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= go4.org/netipx v0.0.0-20230125063823-8449b0a6169f h1:ketMxHg+vWm3yccyYiq+uK8D3fRmna2Fcj+awpQp84s= go4.org/netipx v0.0.0-20230125063823-8449b0a6169f/go.mod h1:tgPU4N2u9RByaTN3NC2p9xOzyFpte4jYwsIIRF7XlSc= golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= -golang.org/x/arch v0.7.0 h1:pskyeJh/3AmoQ8CPE95vxHLqp1G1GfGNXTmcl9NEKTc= -golang.org/x/arch v0.7.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= +golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc= +golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -2170,8 +2174,8 @@ google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz513 google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= -google.golang.org/api v0.169.0 h1:QwWPy71FgMWqJN/l6jVlFHUa29a7dcUy02I8o799nPY= -google.golang.org/api v0.169.0/go.mod h1:gpNOiMA2tZ4mf5R9Iwf4rK/Dcz0fbdIgWYWVoxmsyLg= +google.golang.org/api v0.188.0 h1:51y8fJ/b1AaaBRJr4yWm96fPcuxSo0JcegXE3DaHQHw= +google.golang.org/api v0.188.0/go.mod h1:VR0d+2SIiWOYG3r/jdm7adPW9hI2aRv9ETOSCQ9Beag= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -2224,8 +2228,8 @@ google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210401141331-865547bb08e2/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= -google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 h1:9+tzLLstTlPTRyJTh+ah5wIMsBW5c4tQwGTN3thOW9Y= -google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9/go.mod h1:mqHbVIp48Muh7Ywss/AD6I5kNVKZMmAa/QEW58Gxp2s= +google.golang.org/genproto v0.0.0-20240711142825-46eb208f015d h1:/hmn0Ku5kWij/kjGsrcJeC1T/MrJi2iNWwgAqrihFwc= +google.golang.org/genproto v0.0.0-20240711142825-46eb208f015d/go.mod h1:FfBgJBJg9GcpPvKIuHSZ/aE1g2ecGL74upMzGZjiGEY= google.golang.org/genproto/googleapis/api v0.0.0-20240711142825-46eb208f015d h1:kHjw/5UfflP/L5EbledDrcG4C2597RtymmGRZvHiCuY= google.golang.org/genproto/googleapis/api v0.0.0-20240711142825-46eb208f015d/go.mod h1:mw8MG/Qz5wfgYr6VqVCiZcHe/GJEfI+oGGDCohaVgB0= google.golang.org/genproto/googleapis/rpc v0.0.0-20240711142825-46eb208f015d h1:JU0iKnSg02Gmb5ZdV8nYsKEKsP6o/FGVWTrw4i1DA9A= From 9f850e3fb951ce1eec08aeb606ace08670faa7c2 Mon Sep 17 00:00:00 2001 From: Sneha Agnihotri <180277+snehaagni@users.noreply.github.com> Date: Tue, 30 Jul 2024 00:15:29 +0530 Subject: [PATCH 016/115] Bump version and update CHANGELOG for core v2.14.0 (#13752) * Bump version and update CHANGELOG fore core v2.14.0 Signed-off-by: Sneha Agnihotri * Bump libocr to fix nil msg error (#13919) * Finalize date on changelog for 2.14.0 (#13943) --------- Signed-off-by: Sneha Agnihotri Co-authored-by: chainchad <96362174+chainchad@users.noreply.github.com> --- .changeset/friendly-needles-ring.md | 5 ----- .changeset/many-kids-shave.md | 5 ----- CHANGELOG.md | 2 +- core/scripts/go.mod | 2 +- core/scripts/go.sum | 4 ++-- go.mod | 2 +- go.sum | 4 ++-- integration-tests/go.mod | 2 +- integration-tests/go.sum | 4 ++-- integration-tests/load/go.mod | 2 +- integration-tests/load/go.sum | 4 ++-- 11 files changed, 13 insertions(+), 23 deletions(-) delete mode 100644 .changeset/friendly-needles-ring.md delete mode 100644 .changeset/many-kids-shave.md diff --git a/.changeset/friendly-needles-ring.md b/.changeset/friendly-needles-ring.md deleted file mode 100644 index 8f98047e0f..0000000000 --- a/.changeset/friendly-needles-ring.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#internal syncer start onc3 diff --git a/.changeset/many-kids-shave.md b/.changeset/many-kids-shave.md deleted file mode 100644 index 5c3c83bad9..0000000000 --- a/.changeset/many-kids-shave.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -Go: 1.21.7 => 1.22.5 diff --git a/CHANGELOG.md b/CHANGELOG.md index f212445503..d25c84b322 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog Chainlink Core -## 2.14.0 - UNRELEASED +## 2.14.0 - 2024-07-29 ### Minor Changes diff --git a/core/scripts/go.mod b/core/scripts/go.mod index 61dd4c4b9f..3753cf92bc 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -24,7 +24,7 @@ require ( github.com/smartcontractkit/chainlink-automation v1.0.4 github.com/smartcontractkit/chainlink-common v0.2.2-0.20240723123524-e407ecd120b1 github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000 - github.com/smartcontractkit/libocr v0.0.0-20240702141926-063ceef8c42e + github.com/smartcontractkit/libocr v0.0.0-20240717100443-f6226e09bee7 github.com/spf13/cobra v1.8.0 github.com/spf13/viper v1.15.0 github.com/stretchr/testify v1.9.0 diff --git a/core/scripts/go.sum b/core/scripts/go.sum index 30db21987e..f3276d5a62 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -1200,8 +1200,8 @@ github.com/smartcontractkit/go-plugin v0.0.0-20240208201424-b3b91517de16 h1:TFe+ github.com/smartcontractkit/go-plugin v0.0.0-20240208201424-b3b91517de16/go.mod h1:lBS5MtSSBZk0SHc66KACcjjlU6WzEVP/8pwz68aMkCI= github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f h1:hgJif132UCdjo8u43i7iPN1/MFnu49hv7lFGFftCHKU= github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f/go.mod h1:MvMXoufZAtqExNexqi4cjrNYE9MefKddKylxjS+//n0= -github.com/smartcontractkit/libocr v0.0.0-20240702141926-063ceef8c42e h1:9ypZ/8aW8Vm497i1gXHcT96oNLiu88jbg9QdX+IUE3E= -github.com/smartcontractkit/libocr v0.0.0-20240702141926-063ceef8c42e/go.mod h1:fb1ZDVXACvu4frX3APHZaEBp0xi1DIm34DcA0CwTsZM= +github.com/smartcontractkit/libocr v0.0.0-20240717100443-f6226e09bee7 h1:e38V5FYE7DA1JfKXeD5Buo/7lczALuVXlJ8YNTAUxcw= +github.com/smartcontractkit/libocr v0.0.0-20240717100443-f6226e09bee7/go.mod h1:fb1ZDVXACvu4frX3APHZaEBp0xi1DIm34DcA0CwTsZM= github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 h1:yiKnypAqP8l0OX0P3klzZ7SCcBUxy5KqTAKZmQOvSQE= github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1/go.mod h1:q6f4fe39oZPdsh1i57WznEZgxd8siidMaSFq3wdPmVg= github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1 h1:Dai1bn+Q5cpeGMQwRdjOdVjG8mmFFROVkSKuUgBErRQ= diff --git a/go.mod b/go.mod index ed4766196a..5dd79d3632 100644 --- a/go.mod +++ b/go.mod @@ -78,7 +78,7 @@ require ( github.com/smartcontractkit/chainlink-feeds v0.0.0-20240710170203-5b41615da827 github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240712132946-267a37c5ac6e github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240709043547-03612098f799 - github.com/smartcontractkit/libocr v0.0.0-20240702141926-063ceef8c42e + github.com/smartcontractkit/libocr v0.0.0-20240717100443-f6226e09bee7 github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1 github.com/smartcontractkit/wsrpc v0.7.3 diff --git a/go.sum b/go.sum index c86afe1128..4f0edd8701 100644 --- a/go.sum +++ b/go.sum @@ -1152,8 +1152,8 @@ github.com/smartcontractkit/go-plugin v0.0.0-20240208201424-b3b91517de16 h1:TFe+ github.com/smartcontractkit/go-plugin v0.0.0-20240208201424-b3b91517de16/go.mod h1:lBS5MtSSBZk0SHc66KACcjjlU6WzEVP/8pwz68aMkCI= github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f h1:hgJif132UCdjo8u43i7iPN1/MFnu49hv7lFGFftCHKU= github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f/go.mod h1:MvMXoufZAtqExNexqi4cjrNYE9MefKddKylxjS+//n0= -github.com/smartcontractkit/libocr v0.0.0-20240702141926-063ceef8c42e h1:9ypZ/8aW8Vm497i1gXHcT96oNLiu88jbg9QdX+IUE3E= -github.com/smartcontractkit/libocr v0.0.0-20240702141926-063ceef8c42e/go.mod h1:fb1ZDVXACvu4frX3APHZaEBp0xi1DIm34DcA0CwTsZM= +github.com/smartcontractkit/libocr v0.0.0-20240717100443-f6226e09bee7 h1:e38V5FYE7DA1JfKXeD5Buo/7lczALuVXlJ8YNTAUxcw= +github.com/smartcontractkit/libocr v0.0.0-20240717100443-f6226e09bee7/go.mod h1:fb1ZDVXACvu4frX3APHZaEBp0xi1DIm34DcA0CwTsZM= github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 h1:yiKnypAqP8l0OX0P3klzZ7SCcBUxy5KqTAKZmQOvSQE= github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1/go.mod h1:q6f4fe39oZPdsh1i57WznEZgxd8siidMaSFq3wdPmVg= github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1 h1:Dai1bn+Q5cpeGMQwRdjOdVjG8mmFFROVkSKuUgBErRQ= diff --git a/integration-tests/go.mod b/integration-tests/go.mod index 267332eba7..19a7218a3d 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -33,7 +33,7 @@ require ( github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240405215812-5a72bc9af239 github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000 github.com/smartcontractkit/havoc/k8schaos v0.0.0-20240409145249-e78d20847e37 - github.com/smartcontractkit/libocr v0.0.0-20240702141926-063ceef8c42e + github.com/smartcontractkit/libocr v0.0.0-20240717100443-f6226e09bee7 github.com/smartcontractkit/seth v1.0.12 github.com/smartcontractkit/wasp v0.4.5 github.com/spf13/cobra v1.8.0 diff --git a/integration-tests/go.sum b/integration-tests/go.sum index df4008a1e1..23f1d900d1 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1508,8 +1508,8 @@ github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f h1:hgJ github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f/go.mod h1:MvMXoufZAtqExNexqi4cjrNYE9MefKddKylxjS+//n0= github.com/smartcontractkit/havoc/k8schaos v0.0.0-20240409145249-e78d20847e37 h1:ZEhn2Yo1jY4hqy8nasDL4k4pNtopT3rS3Ap1GDb7ODc= github.com/smartcontractkit/havoc/k8schaos v0.0.0-20240409145249-e78d20847e37/go.mod h1:/kFr0D7SI/vueXl1N03uzOun4nViGPFRyA5X6eL3jXw= -github.com/smartcontractkit/libocr v0.0.0-20240702141926-063ceef8c42e h1:9ypZ/8aW8Vm497i1gXHcT96oNLiu88jbg9QdX+IUE3E= -github.com/smartcontractkit/libocr v0.0.0-20240702141926-063ceef8c42e/go.mod h1:fb1ZDVXACvu4frX3APHZaEBp0xi1DIm34DcA0CwTsZM= +github.com/smartcontractkit/libocr v0.0.0-20240717100443-f6226e09bee7 h1:e38V5FYE7DA1JfKXeD5Buo/7lczALuVXlJ8YNTAUxcw= +github.com/smartcontractkit/libocr v0.0.0-20240717100443-f6226e09bee7/go.mod h1:fb1ZDVXACvu4frX3APHZaEBp0xi1DIm34DcA0CwTsZM= github.com/smartcontractkit/seth v1.0.12 h1:iVdgMx42XWanPPnBaM5StR4c1XsTr/0/B/kKRZL5BsY= github.com/smartcontractkit/seth v1.0.12/go.mod h1:thWtbLyW4nRHJGzC5heknQDORoJPErE15sF34LHkorg= github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 h1:yiKnypAqP8l0OX0P3klzZ7SCcBUxy5KqTAKZmQOvSQE= diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index eb66376a07..75575382c7 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -20,7 +20,7 @@ require ( github.com/smartcontractkit/chainlink-testing-framework v1.32.7 github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20240214231432-4ad5eb95178c github.com/smartcontractkit/chainlink/v2 v2.9.0-beta0.0.20240216210048-da02459ddad8 - github.com/smartcontractkit/libocr v0.0.0-20240702141926-063ceef8c42e + github.com/smartcontractkit/libocr v0.0.0-20240717100443-f6226e09bee7 github.com/smartcontractkit/seth v1.0.12 github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1 github.com/smartcontractkit/wasp v0.4.7 diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index 9b6dcc768f..05af3d1b0a 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -1490,8 +1490,8 @@ github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f h1:hgJ github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f/go.mod h1:MvMXoufZAtqExNexqi4cjrNYE9MefKddKylxjS+//n0= github.com/smartcontractkit/havoc/k8schaos v0.0.0-20240409145249-e78d20847e37 h1:ZEhn2Yo1jY4hqy8nasDL4k4pNtopT3rS3Ap1GDb7ODc= github.com/smartcontractkit/havoc/k8schaos v0.0.0-20240409145249-e78d20847e37/go.mod h1:/kFr0D7SI/vueXl1N03uzOun4nViGPFRyA5X6eL3jXw= -github.com/smartcontractkit/libocr v0.0.0-20240702141926-063ceef8c42e h1:9ypZ/8aW8Vm497i1gXHcT96oNLiu88jbg9QdX+IUE3E= -github.com/smartcontractkit/libocr v0.0.0-20240702141926-063ceef8c42e/go.mod h1:fb1ZDVXACvu4frX3APHZaEBp0xi1DIm34DcA0CwTsZM= +github.com/smartcontractkit/libocr v0.0.0-20240717100443-f6226e09bee7 h1:e38V5FYE7DA1JfKXeD5Buo/7lczALuVXlJ8YNTAUxcw= +github.com/smartcontractkit/libocr v0.0.0-20240717100443-f6226e09bee7/go.mod h1:fb1ZDVXACvu4frX3APHZaEBp0xi1DIm34DcA0CwTsZM= github.com/smartcontractkit/seth v1.0.12 h1:iVdgMx42XWanPPnBaM5StR4c1XsTr/0/B/kKRZL5BsY= github.com/smartcontractkit/seth v1.0.12/go.mod h1:thWtbLyW4nRHJGzC5heknQDORoJPErE15sF34LHkorg= github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 h1:yiKnypAqP8l0OX0P3klzZ7SCcBUxy5KqTAKZmQOvSQE= From 9bd5793c6c868149e3ac6d4eacfc8387fe858b75 Mon Sep 17 00:00:00 2001 From: chainchad <96362174+chainchad@users.noreply.github.com> Date: Mon, 29 Jul 2024 15:22:59 -0400 Subject: [PATCH 017/115] Bump version and update CHANGELOG fore core v2.15.0 Signed-off-by: chainchad <96362174+chainchad@users.noreply.github.com> --- .changeset/angry-wolves-fix.md | 5 - .changeset/bright-crabs-live.md | 7 -- .changeset/bright-readers-dress.md | 5 - .changeset/config.json | 7 +- .changeset/cuddly-toys-warn.md | 14 --- .changeset/curly-zebras-agree.md | 5 - .changeset/dull-seals-jog.md | 5 - .changeset/eighty-points-bathe.md | 5 - .changeset/fluffy-ghosts-sneeze.md | 5 - .changeset/fresh-badgers-pull.md | 5 - .changeset/gold-candles-flow.md | 5 - .changeset/good-paws-switch.md | 5 - .changeset/healthy-lamps-argue.md | 5 - .changeset/hungry-pandas-suffer.md | 5 - .changeset/kind-garlics-smash.md | 5 - .changeset/lucky-cameras-punch.md | 5 - .changeset/mighty-nails-argue.md | 5 - .changeset/neat-peas-reflect.md | 5 - .changeset/neat-rockets-love.md | 5 - .changeset/pink-papayas-swim.md | 5 - .changeset/proud-zoos-sort.md | 5 - .changeset/red-meals-mix.md | 5 - .changeset/serious-apples-dance.md | 5 - .changeset/shiny-ligers-compete.md | 5 - .changeset/silent-cups-flow.md | 5 - .changeset/silver-peas-happen.md | 5 - .changeset/slow-trees-pay.md | 5 - .changeset/soft-maps-ring.md | 5 - .changeset/sour-guests-exercise.md | 5 - .changeset/tall-emus-fail.md | 5 - .changeset/tricky-seas-invite.md | 5 - .changeset/twenty-rings-kneel.md | 5 - .changeset/unlucky-lemons-learn.md | 5 - .changeset/wet-wasps-hide.md | 5 - CHANGELOG.md | 60 ++++++++++ crib/values-profiles/values-dev.yaml | 171 +++++++++++++++++++++++++++ package.json | 2 +- 37 files changed, 233 insertions(+), 183 deletions(-) delete mode 100644 .changeset/angry-wolves-fix.md delete mode 100644 .changeset/bright-crabs-live.md delete mode 100644 .changeset/bright-readers-dress.md delete mode 100644 .changeset/cuddly-toys-warn.md delete mode 100644 .changeset/curly-zebras-agree.md delete mode 100644 .changeset/dull-seals-jog.md delete mode 100644 .changeset/eighty-points-bathe.md delete mode 100644 .changeset/fluffy-ghosts-sneeze.md delete mode 100644 .changeset/fresh-badgers-pull.md delete mode 100644 .changeset/gold-candles-flow.md delete mode 100644 .changeset/good-paws-switch.md delete mode 100644 .changeset/healthy-lamps-argue.md delete mode 100644 .changeset/hungry-pandas-suffer.md delete mode 100644 .changeset/kind-garlics-smash.md delete mode 100644 .changeset/lucky-cameras-punch.md delete mode 100644 .changeset/mighty-nails-argue.md delete mode 100644 .changeset/neat-peas-reflect.md delete mode 100644 .changeset/neat-rockets-love.md delete mode 100644 .changeset/pink-papayas-swim.md delete mode 100644 .changeset/proud-zoos-sort.md delete mode 100644 .changeset/red-meals-mix.md delete mode 100644 .changeset/serious-apples-dance.md delete mode 100644 .changeset/shiny-ligers-compete.md delete mode 100644 .changeset/silent-cups-flow.md delete mode 100644 .changeset/silver-peas-happen.md delete mode 100644 .changeset/slow-trees-pay.md delete mode 100644 .changeset/soft-maps-ring.md delete mode 100644 .changeset/sour-guests-exercise.md delete mode 100644 .changeset/tall-emus-fail.md delete mode 100644 .changeset/tricky-seas-invite.md delete mode 100644 .changeset/twenty-rings-kneel.md delete mode 100644 .changeset/unlucky-lemons-learn.md delete mode 100644 .changeset/wet-wasps-hide.md create mode 100644 crib/values-profiles/values-dev.yaml diff --git a/.changeset/angry-wolves-fix.md b/.changeset/angry-wolves-fix.md deleted file mode 100644 index 51fe7d7be8..0000000000 --- a/.changeset/angry-wolves-fix.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -add chaos and reorg tests #added diff --git a/.changeset/bright-crabs-live.md b/.changeset/bright-crabs-live.md deleted file mode 100644 index 7e21431ee2..0000000000 --- a/.changeset/bright-crabs-live.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -"chainlink": minor ---- - -Remove ocr2vrf - -#removed all ocr2vrf and dkg OCR2 plugin materials. \ No newline at end of file diff --git a/.changeset/bright-readers-dress.md b/.changeset/bright-readers-dress.md deleted file mode 100644 index ac26fbeb4e..0000000000 --- a/.changeset/bright-readers-dress.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#internal address security vulnerabilities around updating nodes and node operators on capabilities registry diff --git a/.changeset/config.json b/.changeset/config.json index 4bdbe5141f..7f98b10d9f 100644 --- a/.changeset/config.json +++ b/.changeset/config.json @@ -1,11 +1,6 @@ { "$schema": "https://unpkg.com/@changesets/config@2.3.1/schema.json", - "changelog": [ - "@changesets/changelog-github", - { - "repo": "smartcontractkit/chainlink" - } - ], + "changelog": "@changesets/cli/changelog", "commit": false, "fixed": [], "linked": [], diff --git a/.changeset/cuddly-toys-warn.md b/.changeset/cuddly-toys-warn.md deleted file mode 100644 index 8e15ba6501..0000000000 --- a/.changeset/cuddly-toys-warn.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -"chainlink": patch ---- - -Add "VerboseLogging" option to mercury - -Off by default, can be enabled like so: - -```toml -[Mercury] -VerboseLogging = true -``` - -#updated diff --git a/.changeset/curly-zebras-agree.md b/.changeset/curly-zebras-agree.md deleted file mode 100644 index a57b379d2a..0000000000 --- a/.changeset/curly-zebras-agree.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#added support for EIP-1559 transactions for Scroll diff --git a/.changeset/dull-seals-jog.md b/.changeset/dull-seals-jog.md deleted file mode 100644 index 12dbb06d86..0000000000 --- a/.changeset/dull-seals-jog.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -remove tautological err check within evm txm. #internal diff --git a/.changeset/eighty-points-bathe.md b/.changeset/eighty-points-bathe.md deleted file mode 100644 index 914975c961..0000000000 --- a/.changeset/eighty-points-bathe.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#db_update add an empty BAL spec in migrations diff --git a/.changeset/fluffy-ghosts-sneeze.md b/.changeset/fluffy-ghosts-sneeze.md deleted file mode 100644 index 48503995c2..0000000000 --- a/.changeset/fluffy-ghosts-sneeze.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -Dequeue minimum guaranteed upkeeps as a priority #changed diff --git a/.changeset/fresh-badgers-pull.md b/.changeset/fresh-badgers-pull.md deleted file mode 100644 index 17255e767d..0000000000 --- a/.changeset/fresh-badgers-pull.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#internal change chain reader to use nil blocknumber when reading latest value diff --git a/.changeset/gold-candles-flow.md b/.changeset/gold-candles-flow.md deleted file mode 100644 index 277a96469e..0000000000 --- a/.changeset/gold-candles-flow.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#internal Bumped dependencies for `chainlink-common`, `chainlink-solana`, and `chainlink-starknet`. diff --git a/.changeset/good-paws-switch.md b/.changeset/good-paws-switch.md deleted file mode 100644 index 76758a2c86..0000000000 --- a/.changeset/good-paws-switch.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#internal add `NewChainWriter` method onto the dummy relayer. diff --git a/.changeset/healthy-lamps-argue.md b/.changeset/healthy-lamps-argue.md deleted file mode 100644 index 33357ddd6c..0000000000 --- a/.changeset/healthy-lamps-argue.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -Initialize registry syncer' contract reader lazily #keystone #internal diff --git a/.changeset/hungry-pandas-suffer.md b/.changeset/hungry-pandas-suffer.md deleted file mode 100644 index f8f151a7ce..0000000000 --- a/.changeset/hungry-pandas-suffer.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -Make send signatures configurable when Transmit in Contract Transmitter #internal diff --git a/.changeset/kind-garlics-smash.md b/.changeset/kind-garlics-smash.md deleted file mode 100644 index 3d9ededa23..0000000000 --- a/.changeset/kind-garlics-smash.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -Updated Functions ToS contract wrappers #internal diff --git a/.changeset/lucky-cameras-punch.md b/.changeset/lucky-cameras-punch.md deleted file mode 100644 index 73dbc1e7c7..0000000000 --- a/.changeset/lucky-cameras-punch.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#internal end to end test for streams capabilities diff --git a/.changeset/mighty-nails-argue.md b/.changeset/mighty-nails-argue.md deleted file mode 100644 index 9456f44956..0000000000 --- a/.changeset/mighty-nails-argue.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -#internal Change CR GetLatestValue to accept confidenceLevels that map to finality for contract read and event querying. Also remove Pending from BoundContract which used to map to finality for log events. diff --git a/.changeset/neat-peas-reflect.md b/.changeset/neat-peas-reflect.md deleted file mode 100644 index 2728e74668..0000000000 --- a/.changeset/neat-peas-reflect.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#internal Updated wrappers for improved L1 -> L2 fee calculation for Functions diff --git a/.changeset/neat-rockets-love.md b/.changeset/neat-rockets-love.md deleted file mode 100644 index 29fdcebe6e..0000000000 --- a/.changeset/neat-rockets-love.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -#internal Added small check to allow for nil TxMeta in CW SubmitTransaction diff --git a/.changeset/pink-papayas-swim.md b/.changeset/pink-papayas-swim.md deleted file mode 100644 index 1e6a2cacd0..0000000000 --- a/.changeset/pink-papayas-swim.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -#internal Add BatchGetLatestValues to ChainReader diff --git a/.changeset/proud-zoos-sort.md b/.changeset/proud-zoos-sort.md deleted file mode 100644 index 571beae821..0000000000 --- a/.changeset/proud-zoos-sort.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -VRFV2Plus coordinator and wrapper split contracts between L1 and L2 chains #updated diff --git a/.changeset/red-meals-mix.md b/.changeset/red-meals-mix.md deleted file mode 100644 index a3667ed20e..0000000000 --- a/.changeset/red-meals-mix.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -Bump to start the next version diff --git a/.changeset/serious-apples-dance.md b/.changeset/serious-apples-dance.md deleted file mode 100644 index 37f8be7e6e..0000000000 --- a/.changeset/serious-apples-dance.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#internal Mercury v3: Include telemetry if bid/ask violation is detected diff --git a/.changeset/shiny-ligers-compete.md b/.changeset/shiny-ligers-compete.md deleted file mode 100644 index d621b94183..0000000000 --- a/.changeset/shiny-ligers-compete.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#internal logging of non determinism in target server diff --git a/.changeset/silent-cups-flow.md b/.changeset/silent-cups-flow.md deleted file mode 100644 index 564e02223f..0000000000 --- a/.changeset/silent-cups-flow.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -#internal refactor goose migrations to use provider diff --git a/.changeset/silver-peas-happen.md b/.changeset/silver-peas-happen.md deleted file mode 100644 index 2e7d062e26..0000000000 --- a/.changeset/silver-peas-happen.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -#internal cleanup heavyweight test databases automatically diff --git a/.changeset/slow-trees-pay.md b/.changeset/slow-trees-pay.md deleted file mode 100644 index 73dca08308..0000000000 --- a/.changeset/slow-trees-pay.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -Protocol-level support for preventing bid/ask variant violations in mercury #added diff --git a/.changeset/soft-maps-ring.md b/.changeset/soft-maps-ring.md deleted file mode 100644 index 1beed3685b..0000000000 --- a/.changeset/soft-maps-ring.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#changed Rename the `InBackupHealthReport` to `StartUpHealthReport` and enable it for DB migrations as well. This will enable health report to be available during long start-up tasks (db backups and migrations). \ No newline at end of file diff --git a/.changeset/sour-guests-exercise.md b/.changeset/sour-guests-exercise.md deleted file mode 100644 index 6138a786d9..0000000000 --- a/.changeset/sour-guests-exercise.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#internal additional logging to remote target capability diff --git a/.changeset/tall-emus-fail.md b/.changeset/tall-emus-fail.md deleted file mode 100644 index 98d5775cb1..0000000000 --- a/.changeset/tall-emus-fail.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -#internal Use txid as the idempotency key in the evm chainwriter diff --git a/.changeset/tricky-seas-invite.md b/.changeset/tricky-seas-invite.md deleted file mode 100644 index f109a2d8f9..0000000000 --- a/.changeset/tricky-seas-invite.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -Fix TestHeadTracker_CallsHeadTrackableCallbacks flaky test #internal diff --git a/.changeset/twenty-rings-kneel.md b/.changeset/twenty-rings-kneel.md deleted file mode 100644 index 160881c7fa..0000000000 --- a/.changeset/twenty-rings-kneel.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -#bugfix Set LatestFinalizedBlock for finalized blocks saved by logpoller diff --git a/.changeset/unlucky-lemons-learn.md b/.changeset/unlucky-lemons-learn.md deleted file mode 100644 index 3e33963995..0000000000 --- a/.changeset/unlucky-lemons-learn.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": minor ---- - -Use the new log buffer in automation #changed diff --git a/.changeset/wet-wasps-hide.md b/.changeset/wet-wasps-hide.md deleted file mode 100644 index 2d6d6fd764..0000000000 --- a/.changeset/wet-wasps-hide.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"chainlink": patch ---- - -Fix TestIntegration_KeeperPluginLogUpkeep_ErrHandler flaky test #internal diff --git a/CHANGELOG.md b/CHANGELOG.md index d25c84b322..dd44eb4307 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,65 @@ # Changelog Chainlink Core +## 2.15.1 + +### Patch Changes + +- Bump to start v2.15.0 + +## 2.15.0 + +### Minor Changes + +- 685681e1b3: Remove ocr2vrf + + #removed all ocr2vrf and dkg OCR2 plugin materials. + +- e065b82d2b: Initialize registry syncer' contract reader lazily #keystone #internal +- f84a3f2f27: #internal Change CR GetLatestValue to accept confidenceLevels that map to finality for contract read and event querying. Also remove Pending from BoundContract which used to map to finality for log events. +- 5daee38379: #internal Added small check to allow for nil TxMeta in CW SubmitTransaction +- 055a9d24f8: #internal Add BatchGetLatestValues to ChainReader +- 8beda6093f: Bump to start the next version +- 4e3f5e8d4f: #internal refactor goose migrations to use provider +- 31557117b2: #internal cleanup heavyweight test databases automatically +- b3c93a7f25: #bugfix Set LatestFinalizedBlock for finalized blocks saved by logpoller +- 5b668c186a: Use the new log buffer in automation #changed + +### Patch Changes + +- e28f8a4386: add chaos and reorg tests #added +- 27d9c71b19: #internal address security vulnerabilities around updating nodes and node operators on capabilities registry +- 5f3d58ba67: Add "VerboseLogging" option to mercury + + Off by default, can be enabled like so: + + ```toml + [Mercury] + VerboseLogging = true + ``` + + #updated + +- df0b06ee1c: #added support for EIP-1559 transactions for Scroll +- 6bf25fc01c: remove tautological err check within evm txm. #internal +- 48b11ddff4: #db_update add an empty BAL spec in migrations +- b1c9315776: Dequeue minimum guaranteed upkeeps as a priority #changed +- 6adb82788a: #internal change chain reader to use nil blocknumber when reading latest value +- 741351107b: #internal Bumped dependencies for `chainlink-common`, `chainlink-solana`, and `chainlink-starknet`. +- e140a2bc1c: #internal add `NewChainWriter` method onto the dummy relayer. +- 89196f1fb8: Make send signatures configurable when Transmit in Contract Transmitter #internal +- 683a12e85e: Updated Functions ToS contract wrappers #internal +- d6ebada1b6: #internal end to end test for streams capabilities +- fb177f4ee7: #internal Updated wrappers for improved L1 -> L2 fee calculation for Functions +- 697e469e41: VRFV2Plus coordinator and wrapper split contracts between L1 and L2 chains #updated +- 873abacbc6: #internal Mercury v3: Include telemetry if bid/ask violation is detected +- 81a21bb56c: #internal logging of non determinism in target server +- 00ef51a7c1: Protocol-level support for preventing bid/ask variant violations in mercury #added +- 68a6a66919: #changed Rename the `InBackupHealthReport` to `StartUpHealthReport` and enable it for DB migrations as well. This will enable health report to be available during long start-up tasks (db backups and migrations). +- ced300beeb: #internal additional logging to remote target capability +- 51225f83f3: #internal Use txid as the idempotency key in the evm chainwriter +- 535d2795c6: Fix TestHeadTracker_CallsHeadTrackableCallbacks flaky test #internal +- 6d2b5faf10: Fix TestIntegration_KeeperPluginLogUpkeep_ErrHandler flaky test #internal + ## 2.14.0 - 2024-07-29 ### Minor Changes diff --git a/crib/values-profiles/values-dev.yaml b/crib/values-profiles/values-dev.yaml new file mode 100644 index 0000000000..5ce3598ab8 --- /dev/null +++ b/crib/values-profiles/values-dev.yaml @@ -0,0 +1,171 @@ +tags: + # Enable BlockScout Stack. + blockscout: true +blockscout-stack1: &default_blockscout_stack_config + blockscout: + image: + repository: "389435844244.dkr.ecr.us-west-2.amazonaws.com/blockscout-internal" + pullPolicy: IfNotPresent + tag: "pr-14" + env: + DATABASE_URL: "postgres://postgres:verylongdatabasepassword@app-blockscout-stack1-db:5432/blockscout" + DATABASE_HOST: "app-blockscout-stack1-db" + ETHEREUM_JSONRPC_HTTP_URL: "http://geth-1337:8544" + ETHEREUM_JSONRPC_WS_URL: "ws://geth-1337:8546" + ETHEREUM_JSONRPC_HTTP_INSECURE: "true" + BLOCKSCOUT_PROTOCOL: "HTTPS" + SECRET_KEY_BASE: "knilniahc" + init: + enabled: true + command: + - /bin/sh + args: + - -c + - | + until nc -z $DATABASE_HOST 5432; do + echo "Waiting for PostgreSQL to be ready..." + sleep 2 + done; + echo "PostgreSQL is ready, starting BlockScout migrations..."; + bin/blockscout eval "Elixir.Explorer.ReleaseTasks.create_and_migrate()" + frontend: + env: + NEXT_PUBLIC_API_HOST: "app-blockscout-stack1-blockscout-svc:80" +blockscout-stack2: + <<: *default_blockscout_stack_config + blockscout: + env: + DATABASE_URL: "postgres://postgres:verylongdatabasepassword@app-blockscout-stack2-db:5432/blockscout" + DATABASE_HOST: "app-blockscout-stack2-db" + ETHEREUM_JSONRPC_HTTP_URL: "http://geth-2337:8544" + ETHEREUM_JSONRPC_WS_URL: "ws://geth-2337:8546" + frontend: + env: + NEXT_PUBLIC_API_HOST: "app-blockscout-stack2-blockscout-svc:80" +blockscout-stack1-db: &default_blockscout_db_config + auth: + # For the `postgres` user. + postgresPassword: verylongdatabasepassword + database: blockscout + primary: + resources: + requests: + cpu: 2 + memory: 512Mi + limits: + cpu: 3 + memory: 1024Mi + extendedConfiguration: | + max_connections = 500 + +blockscout-stack2-db: + <<: *default_blockscout_db_config +chainlink: + global: + overridesToml: |- + [Feature] + LogPoller = true + [Log] + Level = 'debug' + JSONConsole = true + [Log.File] + MaxSize = '0b' + [WebServer] + AllowOrigins = '*' + HTTPPort = 6688 + SecureCookies = false + HTTPWriteTimeout = '1m' + [WebServer.RateLimit] + Authenticated = 2000 + Unauthenticated = 1000 + [WebServer.TLS] + HTTPSPort = 0 + [Database] + MaxIdleConns = 50 + MaxOpenConns = 50 + MigrateOnStartup = true + [OCR2] + Enabled = true + DefaultTransactionQueueDepth = 0 + [OCR] + Enabled = false + DefaultTransactionQueueDepth = 0 + [P2P] + [P2P.V2] + Enabled = true + ListenAddresses = ['0.0.0.0:6690'] + AnnounceAddresses = ['0.0.0.0:6690'] + DeltaDial = '500ms' + DeltaReconcile = '5s' + securityContext: + capabilities: + drop: + - ALL + readOnlyRootFilesystem: false + runAsNonRoot: true + runAsUser: 14933 + runAsGroup: 999 + web_port: 6688 + p2p_port: 6690 + # extraEnvVars: + # "CL_MEDIAN_CMD": "chainlink-feeds" + nodes: + - name: node-1 + image: ${runtime.images.app} + # default resources are 300m/1Gi + # first node need more resources to build faster inside container + # at least 2Gi of memory is required otherwise build will fail (OOM) + resources: + requests: + cpu: 2000m + memory: 2048Mi + limits: + cpu: 2000m + memory: 2048Mi + # override default config per node + # for example, use OCRv2 P2P setup, the whole config + # toml: | + # RootDir = './clroot' + # [Log] + # JSONConsole = true + # Level = 'debug' + # [WebServer] + # AllowOrigins = '*' + # SecureCookies = false + # SessionTimeout = '999h0m0s' + # [OCR2] + # Enabled = true + # [P2P] + # [P2P.V2] + # Enabled = false + # AnnounceAddresses = [] + # DefaultBootstrappers = [] + # DeltaDial = '15s' + # DeltaReconcile = '1m0s' + # ListenAddresses = [] + # [[EVM]] + # ChainID = '1337' + # MinContractPayment = '0' + # [[EVM.Nodes]] + # Name = 'node-0' + # WSURL = 'ws://geth:8546' + # HTTPURL = 'http://geth:8544' + # [WebServer.TLS] + # HTTPSPort = 0 + # or use overridesToml to override some part of configuration + # overridesToml: | + # Enable Tracing + # [Tracing] + # Enabled = true + # SamplingRatio = 1.0 + # CollectorTarget = 'app-opentelemetry-collector:4317' + # TLSCertPath = '' + # Mode = 'unencrypted' + - name: node-2 + image: ${runtime.images.app} + - name: node-3 + image: ${runtime.images.app} + - name: node-4 + image: ${runtime.images.app} + - name: node-5 + image: ${runtime.images.app} diff --git a/package.json b/package.json index b60a4573d5..979d37d464 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "chainlink", - "version": "2.14.0", + "version": "2.15.1", "description": "node of the decentralized oracle network, bridging on and off-chain computation", "main": "index.js", "scripts": { From e9d23b949f71a11b0b4e15071201e34fa0729376 Mon Sep 17 00:00:00 2001 From: chainchad <96362174+chainchad@users.noreply.github.com> Date: Mon, 29 Jul 2024 16:56:43 -0400 Subject: [PATCH 018/115] Fix syntax error in workflow (#13952) (cherry picked from commit 7147653630cd24389e0a3ddab7c56f74a2f0c5b1) --- .github/workflows/build-publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-publish.yml b/.github/workflows/build-publish.yml index d692285f68..1a3c6546a6 100644 --- a/.github/workflows/build-publish.yml +++ b/.github/workflows/build-publish.yml @@ -93,7 +93,7 @@ jobs: format( 'https://github.com/{0}/blob/{1}/CHANGELOG.md', github.repository, - github.ref_name, + github.ref_name ) || '' }} docker-image-name: >- From b028bf5c655b1380d116f0ebc49f35f4171fc615 Mon Sep 17 00:00:00 2001 From: chainchad <96362174+chainchad@users.noreply.github.com> Date: Tue, 30 Jul 2024 10:54:11 -0400 Subject: [PATCH 019/115] Bump slack-notify-git-ref action for fixes --- .github/workflows/build-publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-publish.yml b/.github/workflows/build-publish.yml index 1a3c6546a6..be87de580d 100644 --- a/.github/workflows/build-publish.yml +++ b/.github/workflows/build-publish.yml @@ -81,7 +81,7 @@ jobs: - name: Checkout repository uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - name: Notify Slack - uses: smartcontractkit/.github/actions/slack-notify-git-ref@7fa90bbeff35aa6ce3a9054f542bcf10b7d47cec # slack-notify-git-ref@0.1.0 + uses: smartcontractkit/.github/actions/slack-notify-git-ref@31e00facdd8f57a2bc7868b5e4c8591bf2aa3727 # slack-notify-git-ref@0.1.2 with: slack-channel-id: ${{ secrets.SLACK_CHANNEL_RELEASE_NOTIFICATIONS }} slack-bot-token: ${{ secrets.SLACK_BOT_TOKEN_RELENG }} # Releng Bot From 136e0746189c6ffa11b1822524b9685ec36f3756 Mon Sep 17 00:00:00 2001 From: chainchad <96362174+chainchad@users.noreply.github.com> Date: Wed, 31 Jul 2024 10:05:08 -0400 Subject: [PATCH 020/115] Cleanup old CRIB file --- crib/values-profiles/values-dev.yaml | 171 --------------------------- 1 file changed, 171 deletions(-) delete mode 100644 crib/values-profiles/values-dev.yaml diff --git a/crib/values-profiles/values-dev.yaml b/crib/values-profiles/values-dev.yaml deleted file mode 100644 index 5ce3598ab8..0000000000 --- a/crib/values-profiles/values-dev.yaml +++ /dev/null @@ -1,171 +0,0 @@ -tags: - # Enable BlockScout Stack. - blockscout: true -blockscout-stack1: &default_blockscout_stack_config - blockscout: - image: - repository: "389435844244.dkr.ecr.us-west-2.amazonaws.com/blockscout-internal" - pullPolicy: IfNotPresent - tag: "pr-14" - env: - DATABASE_URL: "postgres://postgres:verylongdatabasepassword@app-blockscout-stack1-db:5432/blockscout" - DATABASE_HOST: "app-blockscout-stack1-db" - ETHEREUM_JSONRPC_HTTP_URL: "http://geth-1337:8544" - ETHEREUM_JSONRPC_WS_URL: "ws://geth-1337:8546" - ETHEREUM_JSONRPC_HTTP_INSECURE: "true" - BLOCKSCOUT_PROTOCOL: "HTTPS" - SECRET_KEY_BASE: "knilniahc" - init: - enabled: true - command: - - /bin/sh - args: - - -c - - | - until nc -z $DATABASE_HOST 5432; do - echo "Waiting for PostgreSQL to be ready..." - sleep 2 - done; - echo "PostgreSQL is ready, starting BlockScout migrations..."; - bin/blockscout eval "Elixir.Explorer.ReleaseTasks.create_and_migrate()" - frontend: - env: - NEXT_PUBLIC_API_HOST: "app-blockscout-stack1-blockscout-svc:80" -blockscout-stack2: - <<: *default_blockscout_stack_config - blockscout: - env: - DATABASE_URL: "postgres://postgres:verylongdatabasepassword@app-blockscout-stack2-db:5432/blockscout" - DATABASE_HOST: "app-blockscout-stack2-db" - ETHEREUM_JSONRPC_HTTP_URL: "http://geth-2337:8544" - ETHEREUM_JSONRPC_WS_URL: "ws://geth-2337:8546" - frontend: - env: - NEXT_PUBLIC_API_HOST: "app-blockscout-stack2-blockscout-svc:80" -blockscout-stack1-db: &default_blockscout_db_config - auth: - # For the `postgres` user. - postgresPassword: verylongdatabasepassword - database: blockscout - primary: - resources: - requests: - cpu: 2 - memory: 512Mi - limits: - cpu: 3 - memory: 1024Mi - extendedConfiguration: | - max_connections = 500 - -blockscout-stack2-db: - <<: *default_blockscout_db_config -chainlink: - global: - overridesToml: |- - [Feature] - LogPoller = true - [Log] - Level = 'debug' - JSONConsole = true - [Log.File] - MaxSize = '0b' - [WebServer] - AllowOrigins = '*' - HTTPPort = 6688 - SecureCookies = false - HTTPWriteTimeout = '1m' - [WebServer.RateLimit] - Authenticated = 2000 - Unauthenticated = 1000 - [WebServer.TLS] - HTTPSPort = 0 - [Database] - MaxIdleConns = 50 - MaxOpenConns = 50 - MigrateOnStartup = true - [OCR2] - Enabled = true - DefaultTransactionQueueDepth = 0 - [OCR] - Enabled = false - DefaultTransactionQueueDepth = 0 - [P2P] - [P2P.V2] - Enabled = true - ListenAddresses = ['0.0.0.0:6690'] - AnnounceAddresses = ['0.0.0.0:6690'] - DeltaDial = '500ms' - DeltaReconcile = '5s' - securityContext: - capabilities: - drop: - - ALL - readOnlyRootFilesystem: false - runAsNonRoot: true - runAsUser: 14933 - runAsGroup: 999 - web_port: 6688 - p2p_port: 6690 - # extraEnvVars: - # "CL_MEDIAN_CMD": "chainlink-feeds" - nodes: - - name: node-1 - image: ${runtime.images.app} - # default resources are 300m/1Gi - # first node need more resources to build faster inside container - # at least 2Gi of memory is required otherwise build will fail (OOM) - resources: - requests: - cpu: 2000m - memory: 2048Mi - limits: - cpu: 2000m - memory: 2048Mi - # override default config per node - # for example, use OCRv2 P2P setup, the whole config - # toml: | - # RootDir = './clroot' - # [Log] - # JSONConsole = true - # Level = 'debug' - # [WebServer] - # AllowOrigins = '*' - # SecureCookies = false - # SessionTimeout = '999h0m0s' - # [OCR2] - # Enabled = true - # [P2P] - # [P2P.V2] - # Enabled = false - # AnnounceAddresses = [] - # DefaultBootstrappers = [] - # DeltaDial = '15s' - # DeltaReconcile = '1m0s' - # ListenAddresses = [] - # [[EVM]] - # ChainID = '1337' - # MinContractPayment = '0' - # [[EVM.Nodes]] - # Name = 'node-0' - # WSURL = 'ws://geth:8546' - # HTTPURL = 'http://geth:8544' - # [WebServer.TLS] - # HTTPSPort = 0 - # or use overridesToml to override some part of configuration - # overridesToml: | - # Enable Tracing - # [Tracing] - # Enabled = true - # SamplingRatio = 1.0 - # CollectorTarget = 'app-opentelemetry-collector:4317' - # TLSCertPath = '' - # Mode = 'unencrypted' - - name: node-2 - image: ${runtime.images.app} - - name: node-3 - image: ${runtime.images.app} - - name: node-4 - image: ${runtime.images.app} - - name: node-5 - image: ${runtime.images.app} From 69cccdf2af8b322a45f66374aabcf03649ddc9d8 Mon Sep 17 00:00:00 2001 From: chainchad <96362174+chainchad@users.noreply.github.com> Date: Thu, 1 Aug 2024 10:22:48 -0400 Subject: [PATCH 021/115] Use changeset github changelog generator --- CHANGELOG.md | 101 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 62 insertions(+), 39 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dd44eb4307..a521df865b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,34 +1,38 @@ # Changelog Chainlink Core -## 2.15.1 - -### Patch Changes - -- Bump to start v2.15.0 - ## 2.15.0 ### Minor Changes -- 685681e1b3: Remove ocr2vrf +- [#13472](https://github.com/smartcontractkit/chainlink/pull/13472) [`685681e1b3`](https://github.com/smartcontractkit/chainlink/commit/685681e1b3b44ec9dadd4756ec6f0407ffda8afe) Thanks [@vreff](https://github.com/vreff)! - Remove ocr2vrf #removed all ocr2vrf and dkg OCR2 plugin materials. -- e065b82d2b: Initialize registry syncer' contract reader lazily #keystone #internal -- f84a3f2f27: #internal Change CR GetLatestValue to accept confidenceLevels that map to finality for contract read and event querying. Also remove Pending from BoundContract which used to map to finality for log events. -- 5daee38379: #internal Added small check to allow for nil TxMeta in CW SubmitTransaction -- 055a9d24f8: #internal Add BatchGetLatestValues to ChainReader -- 8beda6093f: Bump to start the next version -- 4e3f5e8d4f: #internal refactor goose migrations to use provider -- 31557117b2: #internal cleanup heavyweight test databases automatically -- b3c93a7f25: #bugfix Set LatestFinalizedBlock for finalized blocks saved by logpoller -- 5b668c186a: Use the new log buffer in automation #changed +- [#13787](https://github.com/smartcontractkit/chainlink/pull/13787) [`e065b82d2b`](https://github.com/smartcontractkit/chainlink/commit/e065b82d2b8d565c046c2d96065ad1f593d9b488) Thanks [@cedric-cordenier](https://github.com/cedric-cordenier)! - Initialize registry syncer' contract reader lazily #keystone #internal + +- [#13514](https://github.com/smartcontractkit/chainlink/pull/13514) [`f84a3f2f27`](https://github.com/smartcontractkit/chainlink/commit/f84a3f2f276847d26c94bf67215e2a3600951c9c) Thanks [@ilija42](https://github.com/ilija42)! - #internal Change CR GetLatestValue to accept confidenceLevels that map to finality for contract read and event querying. Also remove Pending from BoundContract which used to map to finality for log events. + +- [#13805](https://github.com/smartcontractkit/chainlink/pull/13805) [`5daee38379`](https://github.com/smartcontractkit/chainlink/commit/5daee38379495cd858d8022339b5e9202e2ef0aa) Thanks [@silaslenihan](https://github.com/silaslenihan)! - #internal Added small check to allow for nil TxMeta in CW SubmitTransaction + +- [#13635](https://github.com/smartcontractkit/chainlink/pull/13635) [`055a9d24f8`](https://github.com/smartcontractkit/chainlink/commit/055a9d24f80a0a6cba8a44cab1a2832eef883761) Thanks [@ilija42](https://github.com/ilija42)! - #internal Add BatchGetLatestValues to ChainReader + +- [#13753](https://github.com/smartcontractkit/chainlink/pull/13753) [`8beda6093f`](https://github.com/smartcontractkit/chainlink/commit/8beda6093fe464a98b34ceb77bac6ba51add26b2) Thanks [@snehaagni](https://github.com/snehaagni)! - Bump to start the next version + +- [#13678](https://github.com/smartcontractkit/chainlink/pull/13678) [`4e3f5e8d4f`](https://github.com/smartcontractkit/chainlink/commit/4e3f5e8d4f022dcabce177ac52477820b85f04b1) Thanks [@krehermann](https://github.com/krehermann)! - #internal refactor goose migrations to use provider + +- [#13843](https://github.com/smartcontractkit/chainlink/pull/13843) [`31557117b2`](https://github.com/smartcontractkit/chainlink/commit/31557117b25f456b0dda38453098fa92dba55200) Thanks [@krehermann](https://github.com/krehermann)! - #internal cleanup heavyweight test databases automatically + +- [#13861](https://github.com/smartcontractkit/chainlink/pull/13861) [`b3c93a7f25`](https://github.com/smartcontractkit/chainlink/commit/b3c93a7f259a279060f555098efb4d683ab7e838) Thanks [@reductionista](https://github.com/reductionista)! - #bugfix Set LatestFinalizedBlock for finalized blocks saved by logpoller + +- [#13821](https://github.com/smartcontractkit/chainlink/pull/13821) [`5b668c186a`](https://github.com/smartcontractkit/chainlink/commit/5b668c186ac8ba294a97b20484352221f258bae2) Thanks [@ferglor](https://github.com/ferglor)! - Use the new log buffer in automation #changed ### Patch Changes -- e28f8a4386: add chaos and reorg tests #added -- 27d9c71b19: #internal address security vulnerabilities around updating nodes and node operators on capabilities registry -- 5f3d58ba67: Add "VerboseLogging" option to mercury +- [#13749](https://github.com/smartcontractkit/chainlink/pull/13749) [`e28f8a4386`](https://github.com/smartcontractkit/chainlink/commit/e28f8a4386fcd0baa09cf95e5f59e3312b592506) Thanks [@shileiwill](https://github.com/shileiwill)! - add chaos and reorg tests #added + +- [#13937](https://github.com/smartcontractkit/chainlink/pull/13937) [`27d9c71b19`](https://github.com/smartcontractkit/chainlink/commit/27d9c71b196961666de87bc3128d31f3c22fb3fa) Thanks [@cds95](https://github.com/cds95)! - #internal address security vulnerabilities around updating nodes and node operators on capabilities registry + +- [#13692](https://github.com/smartcontractkit/chainlink/pull/13692) [`5f3d58ba67`](https://github.com/smartcontractkit/chainlink/commit/5f3d58ba67a4e92832d2fa9fc2af487b697ee8ab) Thanks [@samsondav](https://github.com/samsondav)! - Add "VerboseLogging" option to mercury Off by default, can be enabled like so: @@ -39,26 +43,45 @@ #updated -- df0b06ee1c: #added support for EIP-1559 transactions for Scroll -- 6bf25fc01c: remove tautological err check within evm txm. #internal -- 48b11ddff4: #db_update add an empty BAL spec in migrations -- b1c9315776: Dequeue minimum guaranteed upkeeps as a priority #changed -- 6adb82788a: #internal change chain reader to use nil blocknumber when reading latest value -- 741351107b: #internal Bumped dependencies for `chainlink-common`, `chainlink-solana`, and `chainlink-starknet`. -- e140a2bc1c: #internal add `NewChainWriter` method onto the dummy relayer. -- 89196f1fb8: Make send signatures configurable when Transmit in Contract Transmitter #internal -- 683a12e85e: Updated Functions ToS contract wrappers #internal -- d6ebada1b6: #internal end to end test for streams capabilities -- fb177f4ee7: #internal Updated wrappers for improved L1 -> L2 fee calculation for Functions -- 697e469e41: VRFV2Plus coordinator and wrapper split contracts between L1 and L2 chains #updated -- 873abacbc6: #internal Mercury v3: Include telemetry if bid/ask violation is detected -- 81a21bb56c: #internal logging of non determinism in target server -- 00ef51a7c1: Protocol-level support for preventing bid/ask variant violations in mercury #added -- 68a6a66919: #changed Rename the `InBackupHealthReport` to `StartUpHealthReport` and enable it for DB migrations as well. This will enable health report to be available during long start-up tasks (db backups and migrations). -- ced300beeb: #internal additional logging to remote target capability -- 51225f83f3: #internal Use txid as the idempotency key in the evm chainwriter -- 535d2795c6: Fix TestHeadTracker_CallsHeadTrackableCallbacks flaky test #internal -- 6d2b5faf10: Fix TestIntegration_KeeperPluginLogUpkeep_ErrHandler flaky test #internal +- [#13687](https://github.com/smartcontractkit/chainlink/pull/13687) [`df0b06ee1c`](https://github.com/smartcontractkit/chainlink/commit/df0b06ee1ce28a8a7977bd3c9bdd8c9c307bef79) Thanks [@KodeyThomas](https://github.com/KodeyThomas)! - #added support for EIP-1559 transactions for Scroll + +- [#13857](https://github.com/smartcontractkit/chainlink/pull/13857) [`6bf25fc01c`](https://github.com/smartcontractkit/chainlink/commit/6bf25fc01c2e0c7de2ef9d79d511688c276368c1) Thanks [@Farber98](https://github.com/Farber98)! - remove tautological err check within evm txm. #internal + +- [#13839](https://github.com/smartcontractkit/chainlink/pull/13839) [`48b11ddff4`](https://github.com/smartcontractkit/chainlink/commit/48b11ddff47675c4c645764b0a25fd8a23b247ed) Thanks [@jinhoonbang](https://github.com/jinhoonbang)! - #db_update add an empty BAL spec in migrations + +- [#13653](https://github.com/smartcontractkit/chainlink/pull/13653) [`b1c9315776`](https://github.com/smartcontractkit/chainlink/commit/b1c9315776c906bd671c5be404b5cd0c5c34fdba) Thanks [@ferglor](https://github.com/ferglor)! - Dequeue minimum guaranteed upkeeps as a priority #changed + +- [#13906](https://github.com/smartcontractkit/chainlink/pull/13906) [`6adb82788a`](https://github.com/smartcontractkit/chainlink/commit/6adb82788a3b53514dd8b2c0742565e5bd175f9b) Thanks [@ettec](https://github.com/ettec)! - #internal change chain reader to use nil blocknumber when reading latest value + +- [#13793](https://github.com/smartcontractkit/chainlink/pull/13793) [`741351107b`](https://github.com/smartcontractkit/chainlink/commit/741351107b11966f0af8246a76ac7b5bd6a20556) Thanks [@nickcorin](https://github.com/nickcorin)! - #internal Bumped dependencies for `chainlink-common`, `chainlink-solana`, and `chainlink-starknet`. + +- [#13789](https://github.com/smartcontractkit/chainlink/pull/13789) [`e140a2bc1c`](https://github.com/smartcontractkit/chainlink/commit/e140a2bc1c90fa2522109c9da021c3085ed9268d) Thanks [@nickcorin](https://github.com/nickcorin)! - #internal add `NewChainWriter` method onto the dummy relayer. + +- [#13761](https://github.com/smartcontractkit/chainlink/pull/13761) [`89196f1fb8`](https://github.com/smartcontractkit/chainlink/commit/89196f1fb8306c90d4e45281130c894bb12328f7) Thanks [@agusaldasoro](https://github.com/agusaldasoro)! - Make send signatures configurable when Transmit in Contract Transmitter #internal + +- [#13795](https://github.com/smartcontractkit/chainlink/pull/13795) [`683a12e85e`](https://github.com/smartcontractkit/chainlink/commit/683a12e85e91628f240fe24f32b982b53ac30bd9) Thanks [@KuphJr](https://github.com/KuphJr)! - Updated Functions ToS contract wrappers #internal + +- [#13838](https://github.com/smartcontractkit/chainlink/pull/13838) [`d6ebada1b6`](https://github.com/smartcontractkit/chainlink/commit/d6ebada1b6572820a98255b8762cf60810db3210) Thanks [@ettec](https://github.com/ettec)! - #internal end to end test for streams capabilities + +- [#13815](https://github.com/smartcontractkit/chainlink/pull/13815) [`fb177f4ee7`](https://github.com/smartcontractkit/chainlink/commit/fb177f4ee77898dd12e20499e421a4d591fb92ef) Thanks [@KuphJr](https://github.com/KuphJr)! - #internal Updated wrappers for improved L1 -> L2 fee calculation for Functions + +- [#13335](https://github.com/smartcontractkit/chainlink/pull/13335) [`697e469e41`](https://github.com/smartcontractkit/chainlink/commit/697e469e41e640c8c71214461426174340527b4b) Thanks [@ibrajer](https://github.com/ibrajer)! - VRFV2Plus coordinator and wrapper split contracts between L1 and L2 chains #updated + +- [#13785](https://github.com/smartcontractkit/chainlink/pull/13785) [`873abacbc6`](https://github.com/smartcontractkit/chainlink/commit/873abacbc6ce1391fec245045c9436b92d3749f4) Thanks [@martin-cll](https://github.com/martin-cll)! - #internal Mercury v3: Include telemetry if bid/ask violation is detected + +- [#13877](https://github.com/smartcontractkit/chainlink/pull/13877) [`81a21bb56c`](https://github.com/smartcontractkit/chainlink/commit/81a21bb56cd597858221f775c796994be0f2e0da) Thanks [@ettec](https://github.com/ettec)! - #internal logging of non determinism in target server + +- [#13868](https://github.com/smartcontractkit/chainlink/pull/13868) [`00ef51a7c1`](https://github.com/smartcontractkit/chainlink/commit/00ef51a7c11fd227b73e3533f59950aa78b82162) Thanks [@samsondav](https://github.com/samsondav)! - Protocol-level support for preventing bid/ask variant violations in mercury #added + +- [#13120](https://github.com/smartcontractkit/chainlink/pull/13120) [`68a6a66919`](https://github.com/smartcontractkit/chainlink/commit/68a6a6691906aec5807f6c8dae12f9da621304ee) Thanks [@george-dorin](https://github.com/george-dorin)! - #changed Rename the `InBackupHealthReport` to `StartUpHealthReport` and enable it for DB migrations as well. This will enable health report to be available during long start-up tasks (db backups and migrations). + +- [#13852](https://github.com/smartcontractkit/chainlink/pull/13852) [`ced300beeb`](https://github.com/smartcontractkit/chainlink/commit/ced300beebbd1971e11e83a558bb9b1efe0290d9) Thanks [@ettec](https://github.com/ettec)! - #internal additional logging to remote target capability + +- [#13829](https://github.com/smartcontractkit/chainlink/pull/13829) [`51225f83f3`](https://github.com/smartcontractkit/chainlink/commit/51225f83f30a87606c3c7af56618cd16393c345e) Thanks [@nickcorin](https://github.com/nickcorin)! - #internal Use txid as the idempotency key in the evm chainwriter + +- [#13712](https://github.com/smartcontractkit/chainlink/pull/13712) [`535d2795c6`](https://github.com/smartcontractkit/chainlink/commit/535d2795c6e9b66315fe066c7dbaf91977d3e913) Thanks [@dhaidashenko](https://github.com/dhaidashenko)! - Fix TestHeadTracker_CallsHeadTrackableCallbacks flaky test #internal + +- [#13713](https://github.com/smartcontractkit/chainlink/pull/13713) [`6d2b5faf10`](https://github.com/smartcontractkit/chainlink/commit/6d2b5faf10efb81a235ff3470bc205c929a6d35d) Thanks [@dhaidashenko](https://github.com/dhaidashenko)! - Fix TestIntegration_KeeperPluginLogUpkeep_ErrHandler flaky test #internal ## 2.14.0 - 2024-07-29 From c919da6f3b584d7077e98c3ba1fb65661afc99e9 Mon Sep 17 00:00:00 2001 From: chainchad <96362174+chainchad@users.noreply.github.com> Date: Tue, 6 Aug 2024 16:31:37 -0400 Subject: [PATCH 022/115] Fix version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 979d37d464..18171178bc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "chainlink", - "version": "2.15.1", + "version": "2.15.0", "description": "node of the decentralized oracle network, bridging on and off-chain computation", "main": "index.js", "scripts": { From 883c9f9059c259ca17454703b57521ea9ac166cb Mon Sep 17 00:00:00 2001 From: chainchad <96362174+chainchad@users.noreply.github.com> Date: Mon, 19 Aug 2024 10:33:43 -0400 Subject: [PATCH 023/115] Finalize date on changelog for 2.15.0 (#14144) Signed-off-by: chainchad <96362174+chainchad@users.noreply.github.com> --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a521df865b..a78e070b43 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog Chainlink Core -## 2.15.0 +## 2.15.0 - 2024-08-19 ### Minor Changes From d56db81857855295d89537fa3523abf77764ba2f Mon Sep 17 00:00:00 2001 From: Rafael Felix Correa Date: Mon, 26 Aug 2024 10:56:17 +0200 Subject: [PATCH 024/115] CRIB-317 - update ctf version (#1352) ## Motivation Take advantage of the kyverno cleanup logic from https://github.com/smartcontractkit/chainlink-testing-framework/releases/tag/v1.34.5 ## Solution --- integration-tests/go.mod | 2 +- integration-tests/go.sum | 4 ++-- integration-tests/load/go.mod | 2 +- integration-tests/load/go.sum | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/integration-tests/go.mod b/integration-tests/go.mod index 7abf19dc82..bce00021fc 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -38,7 +38,7 @@ require ( github.com/smartcontractkit/chainlink-automation v1.0.4 github.com/smartcontractkit/chainlink-ccip v0.0.0-20240816163757-48726fd8165f github.com/smartcontractkit/chainlink-common v0.2.1-0.20240717132349-ee5af9b79834 - github.com/smartcontractkit/chainlink-testing-framework v1.33.0 + github.com/smartcontractkit/chainlink-testing-framework v1.34.5 github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240405215812-5a72bc9af239 github.com/smartcontractkit/chainlink/integration-tests v0.0.0-00010101000000-000000000000 github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000 diff --git a/integration-tests/go.sum b/integration-tests/go.sum index babc3fc8c6..a83b35591f 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1408,8 +1408,8 @@ github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240712132946-267a37c5ac6 github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240712132946-267a37c5ac6e/go.mod h1:hsFhop+SlQHKD+DEFjZrMJmbauT1A/wvtZIeeo4PxFU= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240709043547-03612098f799 h1:HyLTySm7BR+oNfZqDTkVJ25wnmcTtxBBD31UkFL+kEM= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240709043547-03612098f799/go.mod h1:UVFRacRkP7O7TQAzFmR52v5mUlxf+G1ovMlCQAB/cHU= -github.com/smartcontractkit/chainlink-testing-framework v1.33.0 h1:vHQODEdsq5AIbRiyZZ30de6uwJUNFXLYvCr+Odr8TIs= -github.com/smartcontractkit/chainlink-testing-framework v1.33.0/go.mod h1:GrhHthZ5AmceF82+Ypw6Fov1EvB05JJbb1T0EKyO1x0= +github.com/smartcontractkit/chainlink-testing-framework v1.34.5 h1:6itLSDW4NHDDNR+Y+Z8YDzxxCN9SjdKb6SmLCl0vTFM= +github.com/smartcontractkit/chainlink-testing-framework v1.34.5/go.mod h1:hRZEDh2+afO8MSZb9qYNscmWb+3mHZf01J5ACZuIdTQ= github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240405215812-5a72bc9af239 h1:Kk5OVlx/5g9q3Z3lhxytZS4/f8ds1MiNM8yaHgK3Oe8= github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240405215812-5a72bc9af239/go.mod h1:DC8sQMyTlI/44UCTL8QWFwb0bYNoXCfjwCv2hMivYZU= github.com/smartcontractkit/go-plugin v0.0.0-20240208201424-b3b91517de16 h1:TFe+FvzxClblt6qRfqEhUfa4kFQx5UobuoFGO2W4mMo= diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index a90826f599..0c2d9546b3 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -17,7 +17,7 @@ require ( github.com/slack-go/slack v0.12.2 github.com/smartcontractkit/chainlink-automation v1.0.4 github.com/smartcontractkit/chainlink-common v0.2.1-0.20240717132349-ee5af9b79834 - github.com/smartcontractkit/chainlink-testing-framework v1.33.0 + github.com/smartcontractkit/chainlink-testing-framework v1.34.5 github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20240214231432-4ad5eb95178c github.com/smartcontractkit/chainlink/v2 v2.9.0-beta0.0.20240216210048-da02459ddad8 github.com/smartcontractkit/libocr v0.0.0-20240717100443-f6226e09bee7 diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index 536b96f8b6..06b617f178 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -1372,8 +1372,8 @@ github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240712132946-267a37c5ac6 github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240712132946-267a37c5ac6e/go.mod h1:hsFhop+SlQHKD+DEFjZrMJmbauT1A/wvtZIeeo4PxFU= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240709043547-03612098f799 h1:HyLTySm7BR+oNfZqDTkVJ25wnmcTtxBBD31UkFL+kEM= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240709043547-03612098f799/go.mod h1:UVFRacRkP7O7TQAzFmR52v5mUlxf+G1ovMlCQAB/cHU= -github.com/smartcontractkit/chainlink-testing-framework v1.33.0 h1:vHQODEdsq5AIbRiyZZ30de6uwJUNFXLYvCr+Odr8TIs= -github.com/smartcontractkit/chainlink-testing-framework v1.33.0/go.mod h1:GrhHthZ5AmceF82+Ypw6Fov1EvB05JJbb1T0EKyO1x0= +github.com/smartcontractkit/chainlink-testing-framework v1.34.5 h1:6itLSDW4NHDDNR+Y+Z8YDzxxCN9SjdKb6SmLCl0vTFM= +github.com/smartcontractkit/chainlink-testing-framework v1.34.5/go.mod h1:hRZEDh2+afO8MSZb9qYNscmWb+3mHZf01J5ACZuIdTQ= github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240405215812-5a72bc9af239 h1:Kk5OVlx/5g9q3Z3lhxytZS4/f8ds1MiNM8yaHgK3Oe8= github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240405215812-5a72bc9af239/go.mod h1:DC8sQMyTlI/44UCTL8QWFwb0bYNoXCfjwCv2hMivYZU= github.com/smartcontractkit/go-plugin v0.0.0-20240208201424-b3b91517de16 h1:TFe+FvzxClblt6qRfqEhUfa4kFQx5UobuoFGO2W4mMo= From 74a6b008d0d9d668abad5e616c95ed2216014e88 Mon Sep 17 00:00:00 2001 From: Aleksandr Bukata <96521086+bukata-sa@users.noreply.github.com> Date: Mon, 26 Aug 2024 10:10:14 +0100 Subject: [PATCH 025/115] cherry pick: non-zero default period (#14206) + head report chain_id (#14212) (#1355) cherry pick https://github.com/smartcontractkit/chainlink/commit/621e87538c931d5d3996974589dc27a0ab43f758 https://github.com/smartcontractkit/chainlink/commit/25d29611543c3d43484c168e7efc23a7bf83f035 --- .changeset/eight-bees-speak.md | 5 ++ .changeset/swift-pumas-taste.md | 5 ++ core/services/headreporter/head_reporter.go | 11 +++-- .../headreporter/head_reporter_test.go | 6 +++ .../headreporter/telemetry_reporter.go | 1 + .../headreporter/telemetry_reporter_test.go | 2 + .../telem/telem_head_report.pb.go | 47 ++++++++++--------- 7 files changed, 49 insertions(+), 28 deletions(-) create mode 100644 .changeset/eight-bees-speak.md create mode 100644 .changeset/swift-pumas-taste.md diff --git a/.changeset/eight-bees-speak.md b/.changeset/eight-bees-speak.md new file mode 100644 index 0000000000..9c8ebe428d --- /dev/null +++ b/.changeset/eight-bees-speak.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#bugfix head reporter non-zero reporting period diff --git a/.changeset/swift-pumas-taste.md b/.changeset/swift-pumas-taste.md new file mode 100644 index 0000000000..eb08662e20 --- /dev/null +++ b/.changeset/swift-pumas-taste.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#internal add head report chain_id diff --git a/core/services/headreporter/head_reporter.go b/core/services/headreporter/head_reporter.go index f81a6acf91..94de8ae2be 100644 --- a/core/services/headreporter/head_reporter.go +++ b/core/services/headreporter/head_reporter.go @@ -35,11 +35,12 @@ type ( func NewHeadReporterService(ds sqlutil.DataSource, lggr logger.Logger, reporters ...HeadReporter) *HeadReporterService { return &HeadReporterService{ - ds: ds, - lggr: lggr.Named("HeadReporter"), - newHeads: mailbox.NewSingle[*evmtypes.Head](), - chStop: make(chan struct{}), - reporters: reporters, + ds: ds, + lggr: lggr.Named("HeadReporter"), + newHeads: mailbox.NewSingle[*evmtypes.Head](), + chStop: make(chan struct{}), + reporters: reporters, + reportPeriod: 15 * time.Second, } } diff --git a/core/services/headreporter/head_reporter_test.go b/core/services/headreporter/head_reporter_test.go index ded7e1fb61..304dd59a47 100644 --- a/core/services/headreporter/head_reporter_test.go +++ b/core/services/headreporter/head_reporter_test.go @@ -5,6 +5,7 @@ import ( "testing" "time" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" @@ -42,4 +43,9 @@ func Test_HeadReporterService(t *testing.T) { require.Eventually(t, func() bool { return reportCalls.Load() == 2 }, 5*time.Second, 100*time.Millisecond) }) + + t.Run("has default report period", func(t *testing.T) { + service := NewHeadReporterService(pgtest.NewSqlxDB(t), logger.TestLogger(t), NewMockHeadReporter(t)) + assert.Equal(t, service.reportPeriod, 15*time.Second) + }) } diff --git a/core/services/headreporter/telemetry_reporter.go b/core/services/headreporter/telemetry_reporter.go index 93852f44c0..0d93ca59a4 100644 --- a/core/services/headreporter/telemetry_reporter.go +++ b/core/services/headreporter/telemetry_reporter.go @@ -44,6 +44,7 @@ func (t *telemetryReporter) ReportNewHead(ctx context.Context, head *evmtypes.He } } request := &telem.HeadReportRequest{ + ChainID: head.EVMChainID.String(), Latest: &telem.Block{ Timestamp: uint64(head.Timestamp.UTC().Unix()), Number: uint64(head.Number), diff --git a/core/services/headreporter/telemetry_reporter_test.go b/core/services/headreporter/telemetry_reporter_test.go index 58c0935490..85bfea5866 100644 --- a/core/services/headreporter/telemetry_reporter_test.go +++ b/core/services/headreporter/telemetry_reporter_test.go @@ -35,6 +35,7 @@ func Test_TelemetryReporter_NewHead(t *testing.T) { }, } requestBytes, err := proto.Marshal(&telem.HeadReportRequest{ + ChainID: "100", Latest: &telem.Block{ Timestamp: uint64(head.Timestamp.UTC().Unix()), Number: 42, @@ -70,6 +71,7 @@ func Test_TelemetryReporter_NewHeadMissingFinalized(t *testing.T) { IsFinalized: false, } requestBytes, err := proto.Marshal(&telem.HeadReportRequest{ + ChainID: "100", Latest: &telem.Block{ Timestamp: uint64(head.Timestamp.UTC().Unix()), Number: 42, diff --git a/core/services/synchronization/telem/telem_head_report.pb.go b/core/services/synchronization/telem/telem_head_report.pb.go index 18e4532472..12801314a7 100644 --- a/core/services/synchronization/telem/telem_head_report.pb.go +++ b/core/services/synchronization/telem/telem_head_report.pb.go @@ -25,7 +25,7 @@ type HeadReportRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Chain string `protobuf:"bytes,1,opt,name=chain,proto3" json:"chain,omitempty"` + ChainID string `protobuf:"bytes,1,opt,name=chainID,proto3" json:"chainID,omitempty"` Latest *Block `protobuf:"bytes,2,opt,name=latest,proto3" json:"latest,omitempty"` Finalized *Block `protobuf:"bytes,3,opt,name=finalized,proto3,oneof" json:"finalized,omitempty"` } @@ -62,9 +62,9 @@ func (*HeadReportRequest) Descriptor() ([]byte, []int) { return file_core_services_synchronization_telem_telem_head_report_proto_rawDescGZIP(), []int{0} } -func (x *HeadReportRequest) GetChain() string { +func (x *HeadReportRequest) GetChainID() string { if x != nil { - return x.Chain + return x.ChainID } return "" } @@ -153,26 +153,27 @@ var file_core_services_synchronization_telem_telem_head_report_proto_rawDesc = [ 0x73, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x5f, 0x68, 0x65, 0x61, 0x64, 0x5f, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x05, 0x74, - 0x65, 0x6c, 0x65, 0x6d, 0x22, 0x8e, 0x01, 0x0a, 0x11, 0x48, 0x65, 0x61, 0x64, 0x52, 0x65, 0x70, - 0x6f, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x68, - 0x61, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x63, 0x68, 0x61, 0x69, 0x6e, - 0x12, 0x24, 0x0a, 0x06, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x0c, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x06, - 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x12, 0x2f, 0x0a, 0x09, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, - 0x7a, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x74, 0x65, 0x6c, 0x65, - 0x6d, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x00, 0x52, 0x09, 0x66, 0x69, 0x6e, 0x61, 0x6c, - 0x69, 0x7a, 0x65, 0x64, 0x88, 0x01, 0x01, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x66, 0x69, 0x6e, 0x61, - 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x22, 0x51, 0x0a, 0x05, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x1c, - 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x04, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x16, 0x0a, 0x06, - 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x6e, 0x75, - 0x6d, 0x62, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x42, 0x4e, 0x5a, 0x4c, 0x67, 0x69, 0x74, 0x68, - 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x73, 0x6d, 0x61, 0x72, 0x74, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x61, 0x63, 0x74, 0x6b, 0x69, 0x74, 0x2f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x6c, 0x69, 0x6e, - 0x6b, 0x2f, 0x76, 0x32, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x73, 0x2f, 0x73, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x65, 0x6c, 0x65, 0x6d, 0x22, 0x92, 0x01, 0x0a, 0x11, 0x48, 0x65, 0x61, 0x64, 0x52, 0x65, 0x70, + 0x6f, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x68, + 0x61, 0x69, 0x6e, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x68, 0x61, + 0x69, 0x6e, 0x49, 0x44, 0x12, 0x24, 0x0a, 0x06, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x2e, 0x42, 0x6c, 0x6f, + 0x63, 0x6b, 0x52, 0x06, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x12, 0x2f, 0x0a, 0x09, 0x66, 0x69, + 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, + 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x00, 0x52, 0x09, 0x66, + 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x88, 0x01, 0x01, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, + 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x22, 0x51, 0x0a, 0x05, 0x42, 0x6c, 0x6f, + 0x63, 0x6b, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, + 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, + 0x52, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x42, 0x4e, 0x5a, 0x4c, + 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x73, 0x6d, 0x61, 0x72, 0x74, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x6b, 0x69, 0x74, 0x2f, 0x63, 0x68, 0x61, 0x69, + 0x6e, 0x6c, 0x69, 0x6e, 0x6b, 0x2f, 0x76, 0x32, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x73, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x73, 0x79, 0x6e, 0x63, 0x68, 0x72, 0x6f, 0x6e, 0x69, + 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x62, 0x06, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x33, } var ( From c5f2a99cc3df97b488f0dffd59e5c38d428e9cdc Mon Sep 17 00:00:00 2001 From: Rens Rooimans Date: Mon, 26 Aug 2024 13:19:12 +0200 Subject: [PATCH 026/115] fix ping pong version (#1363) ## Motivation The version should have been bumped to 1.5.0 with the previous release as changes had been made since 1.2.0 ## Solution Bump the version --- contracts/src/v0.8/ccip/applications/PingPongDemo.sol | 2 +- contracts/src/v0.8/ccip/applications/SelfFundedPingPong.sol | 2 +- .../ccip/generated/ping_pong_demo/ping_pong_demo.go | 2 +- .../generated/self_funded_ping_pong/self_funded_ping_pong.go | 2 +- .../generated-wrapper-dependency-versions-do-not-edit.txt | 4 ++-- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/contracts/src/v0.8/ccip/applications/PingPongDemo.sol b/contracts/src/v0.8/ccip/applications/PingPongDemo.sol index 5144b3ed4c..3697c7ff5a 100644 --- a/contracts/src/v0.8/ccip/applications/PingPongDemo.sol +++ b/contracts/src/v0.8/ccip/applications/PingPongDemo.sol @@ -37,7 +37,7 @@ contract PingPongDemo is CCIPReceiver, OwnerIsCreator, ITypeAndVersion { } function typeAndVersion() external pure virtual returns (string memory) { - return "PingPongDemo 1.2.0"; + return "PingPongDemo 1.5.0"; } function setCounterpart(uint64 counterpartChainSelector, address counterpartAddress) external onlyOwner { diff --git a/contracts/src/v0.8/ccip/applications/SelfFundedPingPong.sol b/contracts/src/v0.8/ccip/applications/SelfFundedPingPong.sol index 80bc7bb24a..f9e4fd0aa6 100644 --- a/contracts/src/v0.8/ccip/applications/SelfFundedPingPong.sol +++ b/contracts/src/v0.8/ccip/applications/SelfFundedPingPong.sol @@ -9,7 +9,7 @@ import {PingPongDemo} from "./PingPongDemo.sol"; import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; contract SelfFundedPingPong is PingPongDemo { - string public constant override typeAndVersion = "SelfFundedPingPong 1.2.0"; + string public constant override typeAndVersion = "SelfFundedPingPong 1.5.0"; event Funded(); event CountIncrBeforeFundingSet(uint8 countIncrBeforeFunding); diff --git a/core/gethwrappers/ccip/generated/ping_pong_demo/ping_pong_demo.go b/core/gethwrappers/ccip/generated/ping_pong_demo/ping_pong_demo.go index 349d83182c..08ae9cc0cc 100644 --- a/core/gethwrappers/ccip/generated/ping_pong_demo/ping_pong_demo.go +++ b/core/gethwrappers/ccip/generated/ping_pong_demo/ping_pong_demo.go @@ -45,7 +45,7 @@ type ClientEVMTokenAmount struct { var PingPongDemoMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"contractIERC20\",\"name\":\"feeToken\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"name\":\"InvalidRouter\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"isOutOfOrder\",\"type\":\"bool\"}],\"name\":\"OutOfOrderExecutionChange\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"pingPongCount\",\"type\":\"uint256\"}],\"name\":\"Ping\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"pingPongCount\",\"type\":\"uint256\"}],\"name\":\"Pong\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"destTokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structClient.Any2EVMMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"ccipReceive\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCounterpartAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCounterpartChainSelector\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getFeeToken\",\"outputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getOutOfOrderExecution\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"counterpartChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"counterpartAddress\",\"type\":\"address\"}],\"name\":\"setCounterpart\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"setCounterpartAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"setCounterpartChainSelector\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"outOfOrderExecution\",\"type\":\"bool\"}],\"name\":\"setOutOfOrderExecution\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"pause\",\"type\":\"bool\"}],\"name\":\"setPaused\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"startPingPong\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]", - Bin: "0x60a06040523480156200001157600080fd5b506040516200159d3803806200159d833981016040819052620000349162000263565b33806000846001600160a01b03811662000069576040516335fdcccd60e21b8152600060048201526024015b60405180910390fd5b6001600160a01b039081166080528216620000c75760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f0000000000000000604482015260640162000060565b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000fa57620000fa816200019f565b50506002805460ff60a01b1916905550600380546001600160a01b0319166001600160a01b0383811691821790925560405163095ea7b360e01b8152918416600483015260001960248301529063095ea7b3906044016020604051808303816000875af115801562000170573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001969190620002a2565b505050620002cd565b336001600160a01b03821603620001f95760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000060565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6001600160a01b03811681146200026057600080fd5b50565b600080604083850312156200027757600080fd5b825162000284816200024a565b602084015190925062000297816200024a565b809150509250929050565b600060208284031215620002b557600080fd5b81518015158114620002c657600080fd5b9392505050565b6080516112a6620002f760003960008181610295015281816106860152610ab901526112a66000f3fe608060405234801561001057600080fd5b50600436106101365760003560e01c80638da5cb5b116100b2578063b187bd2611610081578063bee518a411610066578063bee518a4146102ef578063ca709a251461032d578063f2fde38b1461034b57600080fd5b8063b187bd26146102b9578063b5a11011146102dc57600080fd5b80638da5cb5b1461023f5780639d2aede51461025d578063ae90de5514610270578063b0f479a11461029357600080fd5b80632874d8bf11610109578063665ed537116100ee578063665ed5371461021157806379ba50971461022457806385572ffb1461022c57600080fd5b80632874d8bf146101ca5780632b6e5d63146101d257600080fd5b806301ffc9a71461013b57806316c38b3c14610163578063181f5a77146101785780631892b906146101b7575b600080fd5b61014e610149366004610cba565b61035e565b60405190151581526020015b60405180910390f35b610176610171366004610d03565b6103f7565b005b604080518082018252601281527f50696e67506f6e6744656d6f20312e322e3000000000000000000000000000006020820152905161015a9190610d89565b6101766101c5366004610db9565b610449565b6101766104a4565b60025473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161015a565b61017661021f366004610d03565b6104e0565b61017661056c565b61017661023a366004610dd4565b61066e565b60005473ffffffffffffffffffffffffffffffffffffffff166101ec565b61017661026b366004610e33565b6106f3565b60035474010000000000000000000000000000000000000000900460ff1661014e565b7f00000000000000000000000000000000000000000000000000000000000000006101ec565b60025474010000000000000000000000000000000000000000900460ff1661014e565b6101766102ea366004610e4e565b610742565b60015474010000000000000000000000000000000000000000900467ffffffffffffffff1660405167ffffffffffffffff909116815260200161015a565b60035473ffffffffffffffffffffffffffffffffffffffff166101ec565b610176610359366004610e33565b6107e4565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f85572ffb0000000000000000000000000000000000000000000000000000000014806103f157507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b6103ff6107f5565b6002805491151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff909216919091179055565b6104516107f5565b6001805467ffffffffffffffff90921674010000000000000000000000000000000000000000027fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff909216919091179055565b6104ac6107f5565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1690556104de6001610876565b565b6104e86107f5565b6003805482151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff9091161790556040517f05a3fef9935c9013a24c6193df2240d34fcf6b0ebf8786b85efe8401d696cdd99061056190831515815260200190565b60405180910390a150565b60015473ffffffffffffffffffffffffffffffffffffffff1633146105f2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146106df576040517fd7f733340000000000000000000000000000000000000000000000000000000081523360048201526024016105e9565b6106f06106eb82611084565b610b6f565b50565b6106fb6107f5565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b61074a6107f5565b6001805467ffffffffffffffff90931674010000000000000000000000000000000000000000027fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff909316929092179091556002805473ffffffffffffffffffffffffffffffffffffffff9092167fffffffffffffffffffffffff0000000000000000000000000000000000000000909216919091179055565b6107ec6107f5565b6106f081610bc5565b60005473ffffffffffffffffffffffffffffffffffffffff1633146104de576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016105e9565b806001166001036108b9576040518181527f48257dc961b6f792c2b78a080dacfed693b660960a702de21cee364e20270e2f9060200160405180910390a16108ed565b6040518181527f58b69f57828e6962d216502094c54f6562f3bf082ba758966c3454f9e37b15259060200160405180910390a15b6040805160a0810190915260025473ffffffffffffffffffffffffffffffffffffffff1660c08201526000908060e0810160405160208183030381529060405281526020018360405160200161094591815260200190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052815260200160006040519080825280602002602001820160405280156109bf57816020015b60408051808201909152600080825260208201528152602001906001900390816109985790505b50815260035473ffffffffffffffffffffffffffffffffffffffff811660208084019190915260408051808201825262030d408082527401000000000000000000000000000000000000000090940460ff16151590830190815281516024810194909452511515604480850191909152815180850390910181526064909301815290820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f181dcf1000000000000000000000000000000000000000000000000000000000179052909101526001546040517f96f4e9f90000000000000000000000000000000000000000000000000000000081529192507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16916396f4e9f991610b27917401000000000000000000000000000000000000000090910467ffffffffffffffff16908590600401611131565b6020604051808303816000875af1158015610b46573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b6a9190611246565b505050565b60008160600151806020019051810190610b899190611246565b60025490915074010000000000000000000000000000000000000000900460ff16610bc157610bc1610bbc82600161125f565b610876565b5050565b3373ffffffffffffffffffffffffffffffffffffffff821603610c44576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016105e9565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600060208284031215610ccc57600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610cfc57600080fd5b9392505050565b600060208284031215610d1557600080fd5b81358015158114610cfc57600080fd5b6000815180845260005b81811015610d4b57602081850181015186830182015201610d2f565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000610cfc6020830184610d25565b803567ffffffffffffffff81168114610db457600080fd5b919050565b600060208284031215610dcb57600080fd5b610cfc82610d9c565b600060208284031215610de657600080fd5b813567ffffffffffffffff811115610dfd57600080fd5b820160a08185031215610cfc57600080fd5b803573ffffffffffffffffffffffffffffffffffffffff81168114610db457600080fd5b600060208284031215610e4557600080fd5b610cfc82610e0f565b60008060408385031215610e6157600080fd5b610e6a83610d9c565b9150610e7860208401610e0f565b90509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715610ed357610ed3610e81565b60405290565b60405160a0810167ffffffffffffffff81118282101715610ed357610ed3610e81565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715610f4357610f43610e81565b604052919050565b600082601f830112610f5c57600080fd5b813567ffffffffffffffff811115610f7657610f76610e81565b610fa760207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601610efc565b818152846020838601011115610fbc57600080fd5b816020850160208301376000918101602001919091529392505050565b600082601f830112610fea57600080fd5b8135602067ffffffffffffffff82111561100657611006610e81565b611014818360051b01610efc565b82815260069290921b8401810191818101908684111561103357600080fd5b8286015b8481101561107957604081890312156110505760008081fd5b611058610eb0565b61106182610e0f565b81528185013585820152835291830191604001611037565b509695505050505050565b600060a0823603121561109657600080fd5b61109e610ed9565b823581526110ae60208401610d9c565b6020820152604083013567ffffffffffffffff808211156110ce57600080fd5b6110da36838701610f4b565b604084015260608501359150808211156110f357600080fd5b6110ff36838701610f4b565b6060840152608085013591508082111561111857600080fd5b5061112536828601610fd9565b60808301525092915050565b6000604067ffffffffffffffff851683526020604081850152845160a0604086015261116060e0860182610d25565b9050818601517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08087840301606088015261119b8383610d25565b6040890151888203830160808a01528051808352908601945060009350908501905b808410156111fc578451805173ffffffffffffffffffffffffffffffffffffffff168352860151868301529385019360019390930192908601906111bd565b50606089015173ffffffffffffffffffffffffffffffffffffffff1660a08901526080890151888203830160c08a015295506112388187610d25565b9a9950505050505050505050565b60006020828403121561125857600080fd5b5051919050565b808201808211156103f1577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fdfea164736f6c6343000818000a", + Bin: "0x60a06040523480156200001157600080fd5b506040516200159d3803806200159d833981016040819052620000349162000263565b33806000846001600160a01b03811662000069576040516335fdcccd60e21b8152600060048201526024015b60405180910390fd5b6001600160a01b039081166080528216620000c75760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f0000000000000000604482015260640162000060565b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000fa57620000fa816200019f565b50506002805460ff60a01b1916905550600380546001600160a01b0319166001600160a01b0383811691821790925560405163095ea7b360e01b8152918416600483015260001960248301529063095ea7b3906044016020604051808303816000875af115801562000170573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001969190620002a2565b505050620002cd565b336001600160a01b03821603620001f95760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000060565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6001600160a01b03811681146200026057600080fd5b50565b600080604083850312156200027757600080fd5b825162000284816200024a565b602084015190925062000297816200024a565b809150509250929050565b600060208284031215620002b557600080fd5b81518015158114620002c657600080fd5b9392505050565b6080516112a6620002f760003960008181610295015281816106860152610ab901526112a66000f3fe608060405234801561001057600080fd5b50600436106101365760003560e01c80638da5cb5b116100b2578063b187bd2611610081578063bee518a411610066578063bee518a4146102ef578063ca709a251461032d578063f2fde38b1461034b57600080fd5b8063b187bd26146102b9578063b5a11011146102dc57600080fd5b80638da5cb5b1461023f5780639d2aede51461025d578063ae90de5514610270578063b0f479a11461029357600080fd5b80632874d8bf11610109578063665ed537116100ee578063665ed5371461021157806379ba50971461022457806385572ffb1461022c57600080fd5b80632874d8bf146101ca5780632b6e5d63146101d257600080fd5b806301ffc9a71461013b57806316c38b3c14610163578063181f5a77146101785780631892b906146101b7575b600080fd5b61014e610149366004610cba565b61035e565b60405190151581526020015b60405180910390f35b610176610171366004610d03565b6103f7565b005b604080518082018252601281527f50696e67506f6e6744656d6f20312e352e3000000000000000000000000000006020820152905161015a9190610d89565b6101766101c5366004610db9565b610449565b6101766104a4565b60025473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161015a565b61017661021f366004610d03565b6104e0565b61017661056c565b61017661023a366004610dd4565b61066e565b60005473ffffffffffffffffffffffffffffffffffffffff166101ec565b61017661026b366004610e33565b6106f3565b60035474010000000000000000000000000000000000000000900460ff1661014e565b7f00000000000000000000000000000000000000000000000000000000000000006101ec565b60025474010000000000000000000000000000000000000000900460ff1661014e565b6101766102ea366004610e4e565b610742565b60015474010000000000000000000000000000000000000000900467ffffffffffffffff1660405167ffffffffffffffff909116815260200161015a565b60035473ffffffffffffffffffffffffffffffffffffffff166101ec565b610176610359366004610e33565b6107e4565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f85572ffb0000000000000000000000000000000000000000000000000000000014806103f157507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b6103ff6107f5565b6002805491151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff909216919091179055565b6104516107f5565b6001805467ffffffffffffffff90921674010000000000000000000000000000000000000000027fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff909216919091179055565b6104ac6107f5565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1690556104de6001610876565b565b6104e86107f5565b6003805482151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff9091161790556040517f05a3fef9935c9013a24c6193df2240d34fcf6b0ebf8786b85efe8401d696cdd99061056190831515815260200190565b60405180910390a150565b60015473ffffffffffffffffffffffffffffffffffffffff1633146105f2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146106df576040517fd7f733340000000000000000000000000000000000000000000000000000000081523360048201526024016105e9565b6106f06106eb82611084565b610b6f565b50565b6106fb6107f5565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b61074a6107f5565b6001805467ffffffffffffffff90931674010000000000000000000000000000000000000000027fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff909316929092179091556002805473ffffffffffffffffffffffffffffffffffffffff9092167fffffffffffffffffffffffff0000000000000000000000000000000000000000909216919091179055565b6107ec6107f5565b6106f081610bc5565b60005473ffffffffffffffffffffffffffffffffffffffff1633146104de576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016105e9565b806001166001036108b9576040518181527f48257dc961b6f792c2b78a080dacfed693b660960a702de21cee364e20270e2f9060200160405180910390a16108ed565b6040518181527f58b69f57828e6962d216502094c54f6562f3bf082ba758966c3454f9e37b15259060200160405180910390a15b6040805160a0810190915260025473ffffffffffffffffffffffffffffffffffffffff1660c08201526000908060e0810160405160208183030381529060405281526020018360405160200161094591815260200190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052815260200160006040519080825280602002602001820160405280156109bf57816020015b60408051808201909152600080825260208201528152602001906001900390816109985790505b50815260035473ffffffffffffffffffffffffffffffffffffffff811660208084019190915260408051808201825262030d408082527401000000000000000000000000000000000000000090940460ff16151590830190815281516024810194909452511515604480850191909152815180850390910181526064909301815290820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f181dcf1000000000000000000000000000000000000000000000000000000000179052909101526001546040517f96f4e9f90000000000000000000000000000000000000000000000000000000081529192507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16916396f4e9f991610b27917401000000000000000000000000000000000000000090910467ffffffffffffffff16908590600401611131565b6020604051808303816000875af1158015610b46573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b6a9190611246565b505050565b60008160600151806020019051810190610b899190611246565b60025490915074010000000000000000000000000000000000000000900460ff16610bc157610bc1610bbc82600161125f565b610876565b5050565b3373ffffffffffffffffffffffffffffffffffffffff821603610c44576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016105e9565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600060208284031215610ccc57600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610cfc57600080fd5b9392505050565b600060208284031215610d1557600080fd5b81358015158114610cfc57600080fd5b6000815180845260005b81811015610d4b57602081850181015186830182015201610d2f565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000610cfc6020830184610d25565b803567ffffffffffffffff81168114610db457600080fd5b919050565b600060208284031215610dcb57600080fd5b610cfc82610d9c565b600060208284031215610de657600080fd5b813567ffffffffffffffff811115610dfd57600080fd5b820160a08185031215610cfc57600080fd5b803573ffffffffffffffffffffffffffffffffffffffff81168114610db457600080fd5b600060208284031215610e4557600080fd5b610cfc82610e0f565b60008060408385031215610e6157600080fd5b610e6a83610d9c565b9150610e7860208401610e0f565b90509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715610ed357610ed3610e81565b60405290565b60405160a0810167ffffffffffffffff81118282101715610ed357610ed3610e81565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715610f4357610f43610e81565b604052919050565b600082601f830112610f5c57600080fd5b813567ffffffffffffffff811115610f7657610f76610e81565b610fa760207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601610efc565b818152846020838601011115610fbc57600080fd5b816020850160208301376000918101602001919091529392505050565b600082601f830112610fea57600080fd5b8135602067ffffffffffffffff82111561100657611006610e81565b611014818360051b01610efc565b82815260069290921b8401810191818101908684111561103357600080fd5b8286015b8481101561107957604081890312156110505760008081fd5b611058610eb0565b61106182610e0f565b81528185013585820152835291830191604001611037565b509695505050505050565b600060a0823603121561109657600080fd5b61109e610ed9565b823581526110ae60208401610d9c565b6020820152604083013567ffffffffffffffff808211156110ce57600080fd5b6110da36838701610f4b565b604084015260608501359150808211156110f357600080fd5b6110ff36838701610f4b565b6060840152608085013591508082111561111857600080fd5b5061112536828601610fd9565b60808301525092915050565b6000604067ffffffffffffffff851683526020604081850152845160a0604086015261116060e0860182610d25565b9050818601517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08087840301606088015261119b8383610d25565b6040890151888203830160808a01528051808352908601945060009350908501905b808410156111fc578451805173ffffffffffffffffffffffffffffffffffffffff168352860151868301529385019360019390930192908601906111bd565b50606089015173ffffffffffffffffffffffffffffffffffffffff1660a08901526080890151888203830160c08a015295506112388187610d25565b9a9950505050505050505050565b60006020828403121561125857600080fd5b5051919050565b808201808211156103f1577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fdfea164736f6c6343000818000a", } var PingPongDemoABI = PingPongDemoMetaData.ABI diff --git a/core/gethwrappers/ccip/generated/self_funded_ping_pong/self_funded_ping_pong.go b/core/gethwrappers/ccip/generated/self_funded_ping_pong/self_funded_ping_pong.go index 755b4183fe..274f72bae3 100644 --- a/core/gethwrappers/ccip/generated/self_funded_ping_pong/self_funded_ping_pong.go +++ b/core/gethwrappers/ccip/generated/self_funded_ping_pong/self_funded_ping_pong.go @@ -45,7 +45,7 @@ type ClientEVMTokenAmount struct { var SelfFundedPingPongMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"contractIERC20\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"roundTripsBeforeFunding\",\"type\":\"uint8\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"name\":\"InvalidRouter\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"countIncrBeforeFunding\",\"type\":\"uint8\"}],\"name\":\"CountIncrBeforeFundingSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"Funded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"isOutOfOrder\",\"type\":\"bool\"}],\"name\":\"OutOfOrderExecutionChange\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"pingPongCount\",\"type\":\"uint256\"}],\"name\":\"Ping\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"pingPongCount\",\"type\":\"uint256\"}],\"name\":\"Pong\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"destTokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structClient.Any2EVMMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"ccipReceive\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"pingPongCount\",\"type\":\"uint256\"}],\"name\":\"fundPingPong\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCountIncrBeforeFunding\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCounterpartAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCounterpartChainSelector\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getFeeToken\",\"outputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getOutOfOrderExecution\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"countIncrBeforeFunding\",\"type\":\"uint8\"}],\"name\":\"setCountIncrBeforeFunding\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"counterpartChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"counterpartAddress\",\"type\":\"address\"}],\"name\":\"setCounterpart\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"addr\",\"type\":\"address\"}],\"name\":\"setCounterpartAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"setCounterpartChainSelector\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"outOfOrderExecution\",\"type\":\"bool\"}],\"name\":\"setOutOfOrderExecution\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"pause\",\"type\":\"bool\"}],\"name\":\"setPaused\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"startPingPong\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x60a06040523480156200001157600080fd5b506040516200190938038062001909833981016040819052620000349162000291565b828233806000846001600160a01b0381166200006b576040516335fdcccd60e21b8152600060048201526024015b60405180910390fd5b6001600160a01b039081166080528216620000c95760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f0000000000000000604482015260640162000062565b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000fc57620000fc81620001cd565b50506002805460ff60a01b1916905550600380546001600160a01b0319166001600160a01b0383811691821790925560405163095ea7b360e01b8152918416600483015260001960248301529063095ea7b3906044016020604051808303816000875af115801562000172573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001989190620002ea565b505050806002620001aa919062000315565b600360156101000a81548160ff021916908360ff16021790555050505062000347565b336001600160a01b03821603620002275760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000062565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6001600160a01b03811681146200028e57600080fd5b50565b600080600060608486031215620002a757600080fd5b8351620002b48162000278565b6020850151909350620002c78162000278565b604085015190925060ff81168114620002df57600080fd5b809150509250925092565b600060208284031215620002fd57600080fd5b815180151581146200030e57600080fd5b9392505050565b60ff81811683821602908116908181146200034057634e487b7160e01b600052601160045260246000fd5b5092915050565b60805161159162000378600039600081816102f301528181610728015281816108180152610d0901526115916000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c80638f491cba116100d8578063b5a110111161008c578063e6c725f511610066578063e6c725f5146103a9578063ef686d8e146103da578063f2fde38b146103ed57600080fd5b8063b5a110111461033a578063bee518a41461034d578063ca709a251461038b57600080fd5b8063ae90de55116100bd578063ae90de55146102ce578063b0f479a1146102f1578063b187bd261461031757600080fd5b80638f491cba146102a85780639d2aede5146102bb57600080fd5b80632b6e5d631161012f57806379ba50971161011457806379ba50971461026f57806385572ffb146102775780638da5cb5b1461028a57600080fd5b80632b6e5d631461021d578063665ed5371461025c57600080fd5b8063181f5a7711610160578063181f5a77146101b95780631892b906146102025780632874d8bf1461021557600080fd5b806301ffc9a71461017c57806316c38b3c146101a4575b600080fd5b61018f61018a366004610f0b565b610400565b60405190151581526020015b60405180910390f35b6101b76101b2366004610f54565b610499565b005b6101f56040518060400160405280601881526020017f53656c6646756e64656450696e67506f6e6720312e322e30000000000000000081525081565b60405161019b9190610fda565b6101b761021036600461100a565b6104eb565b6101b7610546565b60025473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019b565b6101b761026a366004610f54565b610582565b6101b761060e565b6101b7610285366004611025565b610710565b60005473ffffffffffffffffffffffffffffffffffffffff16610237565b6101b76102b6366004611060565b610795565b6101b76102c936600461109b565b610977565b60035474010000000000000000000000000000000000000000900460ff1661018f565b7f0000000000000000000000000000000000000000000000000000000000000000610237565b60025474010000000000000000000000000000000000000000900460ff1661018f565b6101b76103483660046110b8565b6109c6565b60015474010000000000000000000000000000000000000000900467ffffffffffffffff1660405167ffffffffffffffff909116815260200161019b565b60035473ffffffffffffffffffffffffffffffffffffffff16610237565b6003547501000000000000000000000000000000000000000000900460ff1660405160ff909116815260200161019b565b6101b76103e83660046110ef565b610a68565b6101b76103fb36600461109b565b610aeb565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f85572ffb00000000000000000000000000000000000000000000000000000000148061049357507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b6104a1610afc565b6002805491151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff909216919091179055565b6104f3610afc565b6001805467ffffffffffffffff90921674010000000000000000000000000000000000000000027fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff909216919091179055565b61054e610afc565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1690556105806001610b7d565b565b61058a610afc565b6003805482151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff9091161790556040517f05a3fef9935c9013a24c6193df2240d34fcf6b0ebf8786b85efe8401d696cdd99061060390831515815260200190565b60405180910390a150565b60015473ffffffffffffffffffffffffffffffffffffffff163314610694576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610781576040517fd7f7333400000000000000000000000000000000000000000000000000000000815233600482015260240161068b565b61079261078d82611317565b610dc0565b50565b6003547501000000000000000000000000000000000000000000900460ff1615806107dd57506003547501000000000000000000000000000000000000000000900460ff1681105b156107e55750565b600354600190610811907501000000000000000000000000000000000000000000900460ff16836113c4565b11610792577f00000000000000000000000000000000000000000000000000000000000000006001546040517fa8d87a3b0000000000000000000000000000000000000000000000000000000081527401000000000000000000000000000000000000000090910467ffffffffffffffff16600482015273ffffffffffffffffffffffffffffffffffffffff919091169063a8d87a3b90602401602060405180830381865afa1580156108c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108ec91906113ff565b73ffffffffffffffffffffffffffffffffffffffff1663eff7cc486040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561093357600080fd5b505af1158015610947573d6000803e3d6000fd5b50506040517f302777af5d26fab9dd5120c5f1307c65193ebc51daf33244ada4365fab10602c925060009150a150565b61097f610afc565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6109ce610afc565b6001805467ffffffffffffffff90931674010000000000000000000000000000000000000000027fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff909316929092179091556002805473ffffffffffffffffffffffffffffffffffffffff9092167fffffffffffffffffffffffff0000000000000000000000000000000000000000909216919091179055565b610a70610afc565b600380547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff16750100000000000000000000000000000000000000000060ff8416908102919091179091556040519081527f4768dbf8645b24c54f2887651545d24f748c0d0d1d4c689eb810fb19f0befcf390602001610603565b610af3610afc565b61079281610e16565b60005473ffffffffffffffffffffffffffffffffffffffff163314610580576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640161068b565b80600116600103610bc0576040518181527f48257dc961b6f792c2b78a080dacfed693b660960a702de21cee364e20270e2f9060200160405180910390a1610bf4565b6040518181527f58b69f57828e6962d216502094c54f6562f3bf082ba758966c3454f9e37b15259060200160405180910390a15b610bfd81610795565b6040805160a0810190915260025473ffffffffffffffffffffffffffffffffffffffff1660c08201526000908060e08101604051602081830303815290604052815260200183604051602001610c5591815260200190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905281526020016000604051908082528060200260200182016040528015610ccf57816020015b6040805180820190915260008082526020820152815260200190600190039081610ca85790505b50815260035473ffffffffffffffffffffffffffffffffffffffff16602080830191909152604080519182018152600082529091015290507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166396f4e9f9600160149054906101000a900467ffffffffffffffff16836040518363ffffffff1660e01b8152600401610d7892919061141c565b6020604051808303816000875af1158015610d97573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dbb9190611531565b505050565b60008160600151806020019051810190610dda9190611531565b60025490915074010000000000000000000000000000000000000000900460ff16610e1257610e12610e0d82600161154a565b610b7d565b5050565b3373ffffffffffffffffffffffffffffffffffffffff821603610e95576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161068b565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600060208284031215610f1d57600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610f4d57600080fd5b9392505050565b600060208284031215610f6657600080fd5b81358015158114610f4d57600080fd5b6000815180845260005b81811015610f9c57602081850181015186830182015201610f80565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000610f4d6020830184610f76565b803567ffffffffffffffff8116811461100557600080fd5b919050565b60006020828403121561101c57600080fd5b610f4d82610fed565b60006020828403121561103757600080fd5b813567ffffffffffffffff81111561104e57600080fd5b820160a08185031215610f4d57600080fd5b60006020828403121561107257600080fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff8116811461079257600080fd5b6000602082840312156110ad57600080fd5b8135610f4d81611079565b600080604083850312156110cb57600080fd5b6110d483610fed565b915060208301356110e481611079565b809150509250929050565b60006020828403121561110157600080fd5b813560ff81168114610f4d57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561116457611164611112565b60405290565b60405160a0810167ffffffffffffffff8111828210171561116457611164611112565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156111d4576111d4611112565b604052919050565b600082601f8301126111ed57600080fd5b813567ffffffffffffffff81111561120757611207611112565b61123860207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160161118d565b81815284602083860101111561124d57600080fd5b816020850160208301376000918101602001919091529392505050565b600082601f83011261127b57600080fd5b8135602067ffffffffffffffff82111561129757611297611112565b6112a5818360051b0161118d565b82815260069290921b840181019181810190868411156112c457600080fd5b8286015b8481101561130c57604081890312156112e15760008081fd5b6112e9611141565b81356112f481611079565b815281850135858201528352918301916040016112c8565b509695505050505050565b600060a0823603121561132957600080fd5b61133161116a565b8235815261134160208401610fed565b6020820152604083013567ffffffffffffffff8082111561136157600080fd5b61136d368387016111dc565b6040840152606085013591508082111561138657600080fd5b611392368387016111dc565b606084015260808501359150808211156113ab57600080fd5b506113b83682860161126a565b60808301525092915050565b6000826113fa577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500690565b60006020828403121561141157600080fd5b8151610f4d81611079565b6000604067ffffffffffffffff851683526020604081850152845160a0604086015261144b60e0860182610f76565b9050818601517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0808784030160608801526114868383610f76565b6040890151888203830160808a01528051808352908601945060009350908501905b808410156114e7578451805173ffffffffffffffffffffffffffffffffffffffff168352860151868301529385019360019390930192908601906114a8565b50606089015173ffffffffffffffffffffffffffffffffffffffff1660a08901526080890151888203830160c08a015295506115238187610f76565b9a9950505050505050505050565b60006020828403121561154357600080fd5b5051919050565b80820180821115610493577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fdfea164736f6c6343000818000a", + Bin: "0x60a06040523480156200001157600080fd5b506040516200190938038062001909833981016040819052620000349162000291565b828233806000846001600160a01b0381166200006b576040516335fdcccd60e21b8152600060048201526024015b60405180910390fd5b6001600160a01b039081166080528216620000c95760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f0000000000000000604482015260640162000062565b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000fc57620000fc81620001cd565b50506002805460ff60a01b1916905550600380546001600160a01b0319166001600160a01b0383811691821790925560405163095ea7b360e01b8152918416600483015260001960248301529063095ea7b3906044016020604051808303816000875af115801562000172573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001989190620002ea565b505050806002620001aa919062000315565b600360156101000a81548160ff021916908360ff16021790555050505062000347565b336001600160a01b03821603620002275760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000062565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6001600160a01b03811681146200028e57600080fd5b50565b600080600060608486031215620002a757600080fd5b8351620002b48162000278565b6020850151909350620002c78162000278565b604085015190925060ff81168114620002df57600080fd5b809150509250925092565b600060208284031215620002fd57600080fd5b815180151581146200030e57600080fd5b9392505050565b60ff81811683821602908116908181146200034057634e487b7160e01b600052601160045260246000fd5b5092915050565b60805161159162000378600039600081816102f301528181610728015281816108180152610d0901526115916000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c80638f491cba116100d8578063b5a110111161008c578063e6c725f511610066578063e6c725f5146103a9578063ef686d8e146103da578063f2fde38b146103ed57600080fd5b8063b5a110111461033a578063bee518a41461034d578063ca709a251461038b57600080fd5b8063ae90de55116100bd578063ae90de55146102ce578063b0f479a1146102f1578063b187bd261461031757600080fd5b80638f491cba146102a85780639d2aede5146102bb57600080fd5b80632b6e5d631161012f57806379ba50971161011457806379ba50971461026f57806385572ffb146102775780638da5cb5b1461028a57600080fd5b80632b6e5d631461021d578063665ed5371461025c57600080fd5b8063181f5a7711610160578063181f5a77146101b95780631892b906146102025780632874d8bf1461021557600080fd5b806301ffc9a71461017c57806316c38b3c146101a4575b600080fd5b61018f61018a366004610f0b565b610400565b60405190151581526020015b60405180910390f35b6101b76101b2366004610f54565b610499565b005b6101f56040518060400160405280601881526020017f53656c6646756e64656450696e67506f6e6720312e352e30000000000000000081525081565b60405161019b9190610fda565b6101b761021036600461100a565b6104eb565b6101b7610546565b60025473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161019b565b6101b761026a366004610f54565b610582565b6101b761060e565b6101b7610285366004611025565b610710565b60005473ffffffffffffffffffffffffffffffffffffffff16610237565b6101b76102b6366004611060565b610795565b6101b76102c936600461109b565b610977565b60035474010000000000000000000000000000000000000000900460ff1661018f565b7f0000000000000000000000000000000000000000000000000000000000000000610237565b60025474010000000000000000000000000000000000000000900460ff1661018f565b6101b76103483660046110b8565b6109c6565b60015474010000000000000000000000000000000000000000900467ffffffffffffffff1660405167ffffffffffffffff909116815260200161019b565b60035473ffffffffffffffffffffffffffffffffffffffff16610237565b6003547501000000000000000000000000000000000000000000900460ff1660405160ff909116815260200161019b565b6101b76103e83660046110ef565b610a68565b6101b76103fb36600461109b565b610aeb565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f85572ffb00000000000000000000000000000000000000000000000000000000148061049357507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b6104a1610afc565b6002805491151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff909216919091179055565b6104f3610afc565b6001805467ffffffffffffffff90921674010000000000000000000000000000000000000000027fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff909216919091179055565b61054e610afc565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1690556105806001610b7d565b565b61058a610afc565b6003805482151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff9091161790556040517f05a3fef9935c9013a24c6193df2240d34fcf6b0ebf8786b85efe8401d696cdd99061060390831515815260200190565b60405180910390a150565b60015473ffffffffffffffffffffffffffffffffffffffff163314610694576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610781576040517fd7f7333400000000000000000000000000000000000000000000000000000000815233600482015260240161068b565b61079261078d82611317565b610dc0565b50565b6003547501000000000000000000000000000000000000000000900460ff1615806107dd57506003547501000000000000000000000000000000000000000000900460ff1681105b156107e55750565b600354600190610811907501000000000000000000000000000000000000000000900460ff16836113c4565b11610792577f00000000000000000000000000000000000000000000000000000000000000006001546040517fa8d87a3b0000000000000000000000000000000000000000000000000000000081527401000000000000000000000000000000000000000090910467ffffffffffffffff16600482015273ffffffffffffffffffffffffffffffffffffffff919091169063a8d87a3b90602401602060405180830381865afa1580156108c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108ec91906113ff565b73ffffffffffffffffffffffffffffffffffffffff1663eff7cc486040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561093357600080fd5b505af1158015610947573d6000803e3d6000fd5b50506040517f302777af5d26fab9dd5120c5f1307c65193ebc51daf33244ada4365fab10602c925060009150a150565b61097f610afc565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6109ce610afc565b6001805467ffffffffffffffff90931674010000000000000000000000000000000000000000027fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff909316929092179091556002805473ffffffffffffffffffffffffffffffffffffffff9092167fffffffffffffffffffffffff0000000000000000000000000000000000000000909216919091179055565b610a70610afc565b600380547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff16750100000000000000000000000000000000000000000060ff8416908102919091179091556040519081527f4768dbf8645b24c54f2887651545d24f748c0d0d1d4c689eb810fb19f0befcf390602001610603565b610af3610afc565b61079281610e16565b60005473ffffffffffffffffffffffffffffffffffffffff163314610580576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640161068b565b80600116600103610bc0576040518181527f48257dc961b6f792c2b78a080dacfed693b660960a702de21cee364e20270e2f9060200160405180910390a1610bf4565b6040518181527f58b69f57828e6962d216502094c54f6562f3bf082ba758966c3454f9e37b15259060200160405180910390a15b610bfd81610795565b6040805160a0810190915260025473ffffffffffffffffffffffffffffffffffffffff1660c08201526000908060e08101604051602081830303815290604052815260200183604051602001610c5591815260200190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905281526020016000604051908082528060200260200182016040528015610ccf57816020015b6040805180820190915260008082526020820152815260200190600190039081610ca85790505b50815260035473ffffffffffffffffffffffffffffffffffffffff16602080830191909152604080519182018152600082529091015290507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166396f4e9f9600160149054906101000a900467ffffffffffffffff16836040518363ffffffff1660e01b8152600401610d7892919061141c565b6020604051808303816000875af1158015610d97573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dbb9190611531565b505050565b60008160600151806020019051810190610dda9190611531565b60025490915074010000000000000000000000000000000000000000900460ff16610e1257610e12610e0d82600161154a565b610b7d565b5050565b3373ffffffffffffffffffffffffffffffffffffffff821603610e95576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161068b565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600060208284031215610f1d57600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610f4d57600080fd5b9392505050565b600060208284031215610f6657600080fd5b81358015158114610f4d57600080fd5b6000815180845260005b81811015610f9c57602081850181015186830182015201610f80565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000610f4d6020830184610f76565b803567ffffffffffffffff8116811461100557600080fd5b919050565b60006020828403121561101c57600080fd5b610f4d82610fed565b60006020828403121561103757600080fd5b813567ffffffffffffffff81111561104e57600080fd5b820160a08185031215610f4d57600080fd5b60006020828403121561107257600080fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff8116811461079257600080fd5b6000602082840312156110ad57600080fd5b8135610f4d81611079565b600080604083850312156110cb57600080fd5b6110d483610fed565b915060208301356110e481611079565b809150509250929050565b60006020828403121561110157600080fd5b813560ff81168114610f4d57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561116457611164611112565b60405290565b60405160a0810167ffffffffffffffff8111828210171561116457611164611112565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156111d4576111d4611112565b604052919050565b600082601f8301126111ed57600080fd5b813567ffffffffffffffff81111561120757611207611112565b61123860207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160161118d565b81815284602083860101111561124d57600080fd5b816020850160208301376000918101602001919091529392505050565b600082601f83011261127b57600080fd5b8135602067ffffffffffffffff82111561129757611297611112565b6112a5818360051b0161118d565b82815260069290921b840181019181810190868411156112c457600080fd5b8286015b8481101561130c57604081890312156112e15760008081fd5b6112e9611141565b81356112f481611079565b815281850135858201528352918301916040016112c8565b509695505050505050565b600060a0823603121561132957600080fd5b61133161116a565b8235815261134160208401610fed565b6020820152604083013567ffffffffffffffff8082111561136157600080fd5b61136d368387016111dc565b6040840152606085013591508082111561138657600080fd5b611392368387016111dc565b606084015260808501359150808211156113ab57600080fd5b506113b83682860161126a565b60808301525092915050565b6000826113fa577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500690565b60006020828403121561141157600080fd5b8151610f4d81611079565b6000604067ffffffffffffffff851683526020604081850152845160a0604086015261144b60e0860182610f76565b9050818601517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0808784030160608801526114868383610f76565b6040890151888203830160808a01528051808352908601945060009350908501905b808410156114e7578451805173ffffffffffffffffffffffffffffffffffffffff168352860151868301529385019360019390930192908601906114a8565b50606089015173ffffffffffffffffffffffffffffffffffffffff1660a08901526080890151888203830160c08a015295506115238187610f76565b9a9950505050505050505050565b60006020828403121561154357600080fd5b5051919050565b80820180821115610493577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fdfea164736f6c6343000818000a", } var SelfFundedPingPongABI = SelfFundedPingPongMetaData.ABI diff --git a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt index 5c3a85cb32..16dc444b43 100644 --- a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -24,14 +24,14 @@ nonce_manager: ../../../contracts/solc/v0.8.24/NonceManager/NonceManager.abi ../ ocr3_config_encoder: ../../../contracts/solc/v0.8.24/IOCR3ConfigEncoder/IOCR3ConfigEncoder.abi ../../../contracts/solc/v0.8.24/IOCR3ConfigEncoder/IOCR3ConfigEncoder.bin e21180898e1ad54a045ee20add85a2793c681425ea06f66d1a9e5cab128b6487 offramp: ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.abi ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.bin 76ec9676116368ab7c7c7ed45191698a12e4d975633caea32d821a1125633589 onramp: ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.abi ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.bin 123e949bc9607289382534c4432ecebe5b1da5ca92c1c6c8cc6b9be56c3352c6 -ping_pong_demo: ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.abi ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.bin 4e51d70bdb6d951041518a3d7fd3b33ba8d3954bcc3d078318055b833b880324 +ping_pong_demo: ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.abi ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.bin c1c2f8a65c7ffd971899cae7fe62f2da57d09e936151e2b92163c4bebe699d6b price_registry: ../../../contracts/solc/v0.8.24/PriceRegistry/PriceRegistry.abi ../../../contracts/solc/v0.8.24/PriceRegistry/PriceRegistry.bin 8931609776700a2a8121c9fdd757dbf9207d8b97583e70c84ec2d88c839d4a30 registry_module_owner_custom: ../../../contracts/solc/v0.8.24/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.abi ../../../contracts/solc/v0.8.24/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.bin 75be86323c227917a9bbc3f799d7ed02f92db546653a36db30ed0ebe64461353 report_codec: ../../../contracts/solc/v0.8.24/ReportCodec/ReportCodec.abi ../../../contracts/solc/v0.8.24/ReportCodec/ReportCodec.bin 20292ddaba15096fe8060567cf56cda673b947df27241d0c49d2debc838feb24 rmn_contract: ../../../contracts/solc/v0.8.24/RMN/RMN.abi ../../../contracts/solc/v0.8.24/RMN/RMN.bin 8b45b0fb08631c6b582fd3c0b4052a79cc2b4e091e6286af1ab131bef63661f9 rmn_proxy_contract: ../../../contracts/solc/v0.8.24/ARMProxy/ARMProxy.abi ../../../contracts/solc/v0.8.24/ARMProxy/ARMProxy.bin b048d8e752e3c41113ebb305c1efa06737ad36b4907b93e627fb0a3113023454 router: ../../../contracts/solc/v0.8.24/Router/Router.abi ../../../contracts/solc/v0.8.24/Router/Router.bin 2e4f0a7826c8abb49d882bb49fc5ff20a186dbd3137624b9097ffed903ae4888 -self_funded_ping_pong: ../../../contracts/solc/v0.8.24/SelfFundedPingPong/SelfFundedPingPong.abi ../../../contracts/solc/v0.8.24/SelfFundedPingPong/SelfFundedPingPong.bin 4f339db2b670b88214b738efb7a714be9d50fa32c8008710b607d58670b22074 +self_funded_ping_pong: ../../../contracts/solc/v0.8.24/SelfFundedPingPong/SelfFundedPingPong.abi ../../../contracts/solc/v0.8.24/SelfFundedPingPong/SelfFundedPingPong.bin 8ea5d75dbc3f8afd90d22c4a665a94e02892259cd16520c1c6b4cf0dc80c9148 token_admin_registry: ../../../contracts/solc/v0.8.24/TokenAdminRegistry/TokenAdminRegistry.abi ../../../contracts/solc/v0.8.24/TokenAdminRegistry/TokenAdminRegistry.bin 942be7d1681ac102e0615bee13f76838ebb0b261697cf1270d2bf82c12e57aeb token_pool: ../../../contracts/solc/v0.8.24/TokenPool/TokenPool.abi ../../../contracts/solc/v0.8.24/TokenPool/TokenPool.bin 7c01fd89f5153baa4d7409d14beabb3f861abfbf8880d3c6d06802cc398570f9 usdc_token_pool: ../../../contracts/solc/v0.8.24/USDCTokenPool/USDCTokenPool.abi ../../../contracts/solc/v0.8.24/USDCTokenPool/USDCTokenPool.bin 8e7eae4c7277ce4a0092cca815c046cc49094028c23d2d113de9335fa4358030 From 757cbf333ee8bf4281fa60269e4f090ddad083f5 Mon Sep 17 00:00:00 2001 From: Rens Rooimans Date: Mon, 26 Aug 2024 14:31:10 +0200 Subject: [PATCH 027/115] go mod tidy (#1364) --- integration-tests/actions/private_network.go | 5 +-- .../ccip-tests/actions/ccip_helpers.go | 6 +--- .../ccip-tests/testsetups/ccip.go | 5 +-- .../ccip-tests/testsetups/test_env.go | 5 +-- integration-tests/chaos/ocr_chaos_test.go | 3 +- .../citool/cmd/create_test_config_cmd.go | 35 ++++++++++--------- .../citool/cmd/test_config_cmd_test.go | 5 +-- integration-tests/go.mod | 3 +- integration-tests/go.sum | 6 ++-- integration-tests/load/go.mod | 3 +- integration-tests/load/go.sum | 6 ++-- integration-tests/testsetups/ocr.go | 10 ++---- 12 files changed, 47 insertions(+), 45 deletions(-) diff --git a/integration-tests/actions/private_network.go b/integration-tests/actions/private_network.go index 70239a6006..f10371d41a 100644 --- a/integration-tests/actions/private_network.go +++ b/integration-tests/actions/private_network.go @@ -4,6 +4,7 @@ import ( "github.com/rs/zerolog" ctf_config "github.com/smartcontractkit/chainlink-testing-framework/config" + ctf_config_types "github.com/smartcontractkit/chainlink-testing-framework/config/types" ctf_test_env "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env" ) @@ -12,8 +13,8 @@ func EthereumNetworkConfigFromConfig(l zerolog.Logger, config ctf_config.GlobalT l.Warn().Msg("No TOML private ethereum network config found, will use old geth") ethBuilder := ctf_test_env.NewEthereumNetworkBuilder() network, err = ethBuilder. - WithEthereumVersion(ctf_config.EthereumVersion_Eth1). - WithExecutionLayer(ctf_config.ExecutionLayer_Geth). + WithEthereumVersion(ctf_config_types.EthereumVersion_Eth1). + WithExecutionLayer(ctf_config_types.ExecutionLayer_Geth). Build() return diff --git a/integration-tests/ccip-tests/actions/ccip_helpers.go b/integration-tests/ccip-tests/actions/ccip_helpers.go index e89f75baad..60d1800ab3 100644 --- a/integration-tests/ccip-tests/actions/ccip_helpers.go +++ b/integration-tests/ccip-tests/actions/ccip_helpers.go @@ -4056,11 +4056,7 @@ func (c *CCIPTestEnv) ConnectToDeployedNodes() error { } c.CLNodes = chainlinkK8sNodes if _, exists := c.K8Env.URLs[mockserver.InternalURLsKey]; exists { - mockServer, err := ctfClient.ConnectMockServer(c.K8Env) - if err != nil { - return fmt.Errorf("failed to connect to mock server: %w", err) - } - c.MockServer = mockServer + c.MockServer = ctfClient.ConnectMockServer(c.K8Env) } } return nil diff --git a/integration-tests/ccip-tests/testsetups/ccip.go b/integration-tests/ccip-tests/testsetups/ccip.go index 3fb25bc675..6e3ee5b7e8 100644 --- a/integration-tests/ccip-tests/testsetups/ccip.go +++ b/integration-tests/ccip-tests/testsetups/ccip.go @@ -30,6 +30,7 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/blockchain" ctfClient "github.com/smartcontractkit/chainlink-testing-framework/client" ctfconfig "github.com/smartcontractkit/chainlink-testing-framework/config" + ctfconfigtypes "github.com/smartcontractkit/chainlink-testing-framework/config/types" ctftestenv "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env" "github.com/smartcontractkit/chainlink-testing-framework/k8s/config" "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment" @@ -276,8 +277,8 @@ func (c *CCIPTestConfig) SetNetworkPairs(lggr zerolog.Logger) error { allError = multierr.Append(allError, fmt.Errorf("failed to get default chain config: %w", err)) } else { chainConfig.ChainID = int(chainID) - eth1 := ctfconfig.EthereumVersion_Eth1 - geth := ctfconfig.ExecutionLayer_Geth + eth1 := ctfconfigtypes.EthereumVersion_Eth1 + geth := ctfconfigtypes.ExecutionLayer_Geth c.EnvInput.PrivateEthereumNetworks[fmt.Sprint(chainID)] = &ctfconfig.EthereumNetworkConfig{ EthereumVersion: ð1, diff --git a/integration-tests/ccip-tests/testsetups/test_env.go b/integration-tests/ccip-tests/testsetups/test_env.go index e0a9c84482..85a5a10511 100644 --- a/integration-tests/ccip-tests/testsetups/test_env.go +++ b/integration-tests/ccip-tests/testsetups/test_env.go @@ -14,6 +14,7 @@ import ( "github.com/stretchr/testify/require" ctfconfig "github.com/smartcontractkit/chainlink-testing-framework/config" + ctfconfigtypes "github.com/smartcontractkit/chainlink-testing-framework/config/types" "github.com/smartcontractkit/chainlink-testing-framework/networks" "github.com/smartcontractkit/chainlink-testing-framework/utils/conversions" @@ -292,8 +293,8 @@ func DeployLocalCluster( require.NoError(t, err, "failed to get default chain config: %w", err) } else { chainConfig.ChainID = int(network.ChainID) - eth1 := ctfconfig.EthereumVersion_Eth1 - geth := ctfconfig.ExecutionLayer_Geth + eth1 := ctfconfigtypes.EthereumVersion_Eth1 + geth := ctfconfigtypes.ExecutionLayer_Geth privateEthereumNetworks = append(privateEthereumNetworks, &ctfconfig.EthereumNetworkConfig{ EthereumVersion: ð1, diff --git a/integration-tests/chaos/ocr_chaos_test.go b/integration-tests/chaos/ocr_chaos_test.go index 54a02cf64f..052726afda 100644 --- a/integration-tests/chaos/ocr_chaos_test.go +++ b/integration-tests/chaos/ocr_chaos_test.go @@ -178,8 +178,7 @@ func TestOCRChaos(t *testing.T) { require.NoError(t, err, "Error tearing down environment") }) - ms, err := ctfClient.ConnectMockServer(testEnvironment) - require.NoError(t, err, "Creating mockserver clients shouldn't fail") + ms := ctfClient.ConnectMockServer(testEnvironment) linkContract, err := contracts.DeployLinkTokenContract(l, seth) require.NoError(t, err, "Error deploying link token contract") diff --git a/integration-tests/citool/cmd/create_test_config_cmd.go b/integration-tests/citool/cmd/create_test_config_cmd.go index bc1b65bcdc..518a041318 100644 --- a/integration-tests/citool/cmd/create_test_config_cmd.go +++ b/integration-tests/citool/cmd/create_test_config_cmd.go @@ -7,14 +7,15 @@ import ( "github.com/pelletier/go-toml/v2" "github.com/spf13/cobra" - ctf_config "github.com/smartcontractkit/chainlink-testing-framework/config" + ctfconfig "github.com/smartcontractkit/chainlink-testing-framework/config" + ctfconfigtypes "github.com/smartcontractkit/chainlink-testing-framework/config/types" ) var createTestConfigCmd = &cobra.Command{ Use: "create", Short: "Create a test config from the provided flags", Run: func(cmd *cobra.Command, _ []string) { - var tc ctf_config.TestConfig + var tc ctfconfig.TestConfig var version, postgresVersion *string if cmd.Flags().Changed(ChainlinkVersionFlag) { @@ -24,7 +25,7 @@ var createTestConfigCmd = &cobra.Command{ version = &oc.ChainlinkPostgresVersion } if version != nil || postgresVersion != nil { - tc.ChainlinkImage = &ctf_config.ChainlinkImageConfig{ + tc.ChainlinkImage = &ctfconfig.ChainlinkImageConfig{ Version: version, PostgresVersion: postgresVersion, } @@ -35,7 +36,7 @@ var createTestConfigCmd = &cobra.Command{ upgradeVersion = &oc.ChainlinkUpgradeVersion } if upgradeVersion != nil { - tc.ChainlinkUpgradeImage = &ctf_config.ChainlinkImageConfig{ + tc.ChainlinkUpgradeImage = &ctfconfig.ChainlinkImageConfig{ Version: upgradeVersion, } } @@ -45,7 +46,7 @@ var createTestConfigCmd = &cobra.Command{ selectedNetworks = &oc.SelectedNetworks } if selectedNetworks != nil { - tc.Network = &ctf_config.NetworkConfig{ + tc.Network = &ctfconfig.NetworkConfig{ SelectedNetworks: oc.SelectedNetworks, } } @@ -65,7 +66,7 @@ var createTestConfigCmd = &cobra.Command{ pyroscopeEnvironment = &oc.PyroscopeEnvironment } if peryscopeEnabled != nil { - tc.Pyroscope = &ctf_config.PyroscopeConfig{ + tc.Pyroscope = &ctfconfig.PyroscopeConfig{ Enabled: peryscopeEnabled, ServerUrl: pyroscopeServerURL, Environment: pyroscopeEnvironment, @@ -111,23 +112,23 @@ var createTestConfigCmd = &cobra.Command{ } if testLogCollect != nil || loggingRunID != nil || loggingLogTargets != nil || loggingLokiEndpoint != nil || loggingLokiTenantID != nil || loggingLokiBasicAuth != nil || loggingGrafanaBaseURL != nil || loggingGrafanaDashboardURL != nil || loggingGrafanaBearerToken != nil { - tc.Logging = &ctf_config.LoggingConfig{} + tc.Logging = &ctfconfig.LoggingConfig{} tc.Logging.TestLogCollect = testLogCollect tc.Logging.RunId = loggingRunID if loggingLogTargets != nil { - tc.Logging.LogStream = &ctf_config.LogStreamConfig{ + tc.Logging.LogStream = &ctfconfig.LogStreamConfig{ LogTargets: loggingLogTargets, } } if loggingLokiTenantID != nil || loggingLokiBasicAuth != nil || loggingLokiEndpoint != nil { - tc.Logging.Loki = &ctf_config.LokiConfig{ + tc.Logging.Loki = &ctfconfig.LokiConfig{ TenantId: loggingLokiTenantID, BasicAuth: loggingLokiBasicAuth, Endpoint: loggingLokiEndpoint, } } if loggingGrafanaBaseURL != nil || loggingGrafanaDashboardURL != nil || loggingGrafanaBearerToken != nil { - tc.Logging.Grafana = &ctf_config.GrafanaConfig{ + tc.Logging.Grafana = &ctfconfig.GrafanaConfig{ BaseUrl: loggingGrafanaBaseURL, DashboardUrl: loggingGrafanaDashboardURL, BearerToken: loggingGrafanaBearerToken, @@ -148,19 +149,19 @@ var createTestConfigCmd = &cobra.Command{ privateEthereumNetworkCustomDockerImage = &oc.PrivateEthereumNetworkCustomDockerImages } if privateEthereumNetworkExecutionLayer != nil || privateEthereumNetworkEthereumVersion != nil || privateEthereumNetworkCustomDockerImage != nil { - var el ctf_config.ExecutionLayer + var el ctfconfigtypes.ExecutionLayer if privateEthereumNetworkExecutionLayer != nil { - el = ctf_config.ExecutionLayer(*privateEthereumNetworkExecutionLayer) + el = ctfconfigtypes.ExecutionLayer(*privateEthereumNetworkExecutionLayer) } - var ev ctf_config.EthereumVersion + var ev ctfconfigtypes.EthereumVersion if privateEthereumNetworkEthereumVersion != nil { - ev = ctf_config.EthereumVersion(*privateEthereumNetworkEthereumVersion) + ev = ctfconfigtypes.EthereumVersion(*privateEthereumNetworkEthereumVersion) } - var customImages map[ctf_config.ContainerType]string + var customImages map[ctfconfig.ContainerType]string if privateEthereumNetworkCustomDockerImage != nil { - customImages = map[ctf_config.ContainerType]string{"execution_layer": *privateEthereumNetworkCustomDockerImage} + customImages = map[ctfconfig.ContainerType]string{"execution_layer": *privateEthereumNetworkCustomDockerImage} } - tc.PrivateEthereumNetwork = &ctf_config.EthereumNetworkConfig{ + tc.PrivateEthereumNetwork = &ctfconfig.EthereumNetworkConfig{ ExecutionLayer: &el, EthereumVersion: &ev, CustomDockerImages: customImages, diff --git a/integration-tests/citool/cmd/test_config_cmd_test.go b/integration-tests/citool/cmd/test_config_cmd_test.go index fb1ef5332b..3fcc25fd17 100644 --- a/integration-tests/citool/cmd/test_config_cmd_test.go +++ b/integration-tests/citool/cmd/test_config_cmd_test.go @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" ctf_config "github.com/smartcontractkit/chainlink-testing-framework/config" + ctfconfigtypes "github.com/smartcontractkit/chainlink-testing-framework/config/types" ) func TestCreateTestConfigCmd(t *testing.T) { @@ -34,8 +35,8 @@ func TestCreateTestConfigCmd(t *testing.T) { check: func(t *testing.T, tc *ctf_config.TestConfig) { assert.NotNil(t, tc.PrivateEthereumNetwork) assert.NotNil(t, tc.PrivateEthereumNetwork.ExecutionLayer) - assert.Equal(t, ctf_config.ExecutionLayer("geth"), *tc.PrivateEthereumNetwork.ExecutionLayer) - assert.Equal(t, ctf_config.EthereumVersion("1.10.0"), *tc.PrivateEthereumNetwork.EthereumVersion) + assert.Equal(t, ctfconfigtypes.ExecutionLayer("geth"), *tc.PrivateEthereumNetwork.ExecutionLayer) + assert.Equal(t, ctfconfigtypes.EthereumVersion("1.10.0"), *tc.PrivateEthereumNetwork.EthereumVersion) }, }, { diff --git a/integration-tests/go.mod b/integration-tests/go.mod index bce00021fc..3c1386cb30 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -44,7 +44,7 @@ require ( github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000 github.com/smartcontractkit/havoc/k8schaos v0.0.0-20240409145249-e78d20847e37 github.com/smartcontractkit/libocr v0.0.0-20240717100443-f6226e09bee7 - github.com/smartcontractkit/seth v1.0.12 + github.com/smartcontractkit/seth v1.1.1 github.com/smartcontractkit/wasp v0.4.5 github.com/spf13/cobra v1.8.1 github.com/stretchr/testify v1.9.0 @@ -108,6 +108,7 @@ require ( github.com/armon/go-metrics v0.4.1 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/avast/retry-go v3.0.0+incompatible // indirect + github.com/awalterschulze/gographviz v2.0.3+incompatible // indirect github.com/aws/aws-sdk-go v1.45.25 // indirect github.com/aws/constructs-go/constructs/v10 v10.1.255 // indirect github.com/aws/jsii-runtime-go v1.75.0 // indirect diff --git a/integration-tests/go.sum b/integration-tests/go.sum index a83b35591f..4d324d1033 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -204,6 +204,8 @@ github.com/avast/retry-go v3.0.0+incompatible h1:4SOWQ7Qs+oroOTQOYnAHqelpCO0biHS github.com/avast/retry-go v3.0.0+incompatible/go.mod h1:XtSnn+n/sHqQIpZ10K1qAevBhOOCWBLXXy3hyiqqBrY= github.com/avast/retry-go/v4 v4.6.0 h1:K9xNA+KeB8HHc2aWFuLb25Offp+0iVRXEvFx8IinRJA= github.com/avast/retry-go/v4 v4.6.0/go.mod h1:gvWlPhBVsvBbLkVGDg/KwvBv0bEkCOLRRSHKIr2PyOE= +github.com/awalterschulze/gographviz v2.0.3+incompatible h1:9sVEXJBJLwGX7EQVhLm2elIKCm7P2YHFC8v6096G09E= +github.com/awalterschulze/gographviz v2.0.3+incompatible/go.mod h1:GEV5wmg4YquNw7v1kkyoX9etIk8yVmXj+AkDHuuETHs= github.com/aws/aws-sdk-go v1.22.1/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.23.20/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.38.35/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= @@ -1420,8 +1422,8 @@ github.com/smartcontractkit/havoc/k8schaos v0.0.0-20240409145249-e78d20847e37 h1 github.com/smartcontractkit/havoc/k8schaos v0.0.0-20240409145249-e78d20847e37/go.mod h1:/kFr0D7SI/vueXl1N03uzOun4nViGPFRyA5X6eL3jXw= github.com/smartcontractkit/libocr v0.0.0-20240717100443-f6226e09bee7 h1:e38V5FYE7DA1JfKXeD5Buo/7lczALuVXlJ8YNTAUxcw= github.com/smartcontractkit/libocr v0.0.0-20240717100443-f6226e09bee7/go.mod h1:fb1ZDVXACvu4frX3APHZaEBp0xi1DIm34DcA0CwTsZM= -github.com/smartcontractkit/seth v1.0.12 h1:iVdgMx42XWanPPnBaM5StR4c1XsTr/0/B/kKRZL5BsY= -github.com/smartcontractkit/seth v1.0.12/go.mod h1:thWtbLyW4nRHJGzC5heknQDORoJPErE15sF34LHkorg= +github.com/smartcontractkit/seth v1.1.1 h1:6hvexjJD7ek8ht/CLlEwQcH21K2E/WEYwbSRdKInZmM= +github.com/smartcontractkit/seth v1.1.1/go.mod h1:cDfKHi/hJLpO9sRpVbrflrHCOV+MJPAMJHloExJnIXk= github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 h1:yiKnypAqP8l0OX0P3klzZ7SCcBUxy5KqTAKZmQOvSQE= github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1/go.mod h1:q6f4fe39oZPdsh1i57WznEZgxd8siidMaSFq3wdPmVg= github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1 h1:Dai1bn+Q5cpeGMQwRdjOdVjG8mmFFROVkSKuUgBErRQ= diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index 0c2d9546b3..fc44d83aa5 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -21,7 +21,7 @@ require ( github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20240214231432-4ad5eb95178c github.com/smartcontractkit/chainlink/v2 v2.9.0-beta0.0.20240216210048-da02459ddad8 github.com/smartcontractkit/libocr v0.0.0-20240717100443-f6226e09bee7 - github.com/smartcontractkit/seth v1.0.12 + github.com/smartcontractkit/seth v1.1.1 github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1 github.com/smartcontractkit/wasp v0.4.7 github.com/stretchr/testify v1.9.0 @@ -35,6 +35,7 @@ require ( cosmossdk.io/depinject v1.0.0-alpha.4 // indirect cosmossdk.io/errors v1.0.1 // indirect cosmossdk.io/math v1.3.0 // indirect + github.com/awalterschulze/gographviz v2.0.3+incompatible // indirect github.com/containerd/errdefs v0.1.0 // indirect github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index 06b617f178..2c340a73d1 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -192,6 +192,8 @@ github.com/avast/retry-go v3.0.0+incompatible h1:4SOWQ7Qs+oroOTQOYnAHqelpCO0biHS github.com/avast/retry-go v3.0.0+incompatible/go.mod h1:XtSnn+n/sHqQIpZ10K1qAevBhOOCWBLXXy3hyiqqBrY= github.com/avast/retry-go/v4 v4.6.0 h1:K9xNA+KeB8HHc2aWFuLb25Offp+0iVRXEvFx8IinRJA= github.com/avast/retry-go/v4 v4.6.0/go.mod h1:gvWlPhBVsvBbLkVGDg/KwvBv0bEkCOLRRSHKIr2PyOE= +github.com/awalterschulze/gographviz v2.0.3+incompatible h1:9sVEXJBJLwGX7EQVhLm2elIKCm7P2YHFC8v6096G09E= +github.com/awalterschulze/gographviz v2.0.3+incompatible/go.mod h1:GEV5wmg4YquNw7v1kkyoX9etIk8yVmXj+AkDHuuETHs= github.com/aws/aws-sdk-go v1.22.1/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.23.20/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.38.35/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= @@ -1384,8 +1386,8 @@ github.com/smartcontractkit/havoc/k8schaos v0.0.0-20240409145249-e78d20847e37 h1 github.com/smartcontractkit/havoc/k8schaos v0.0.0-20240409145249-e78d20847e37/go.mod h1:/kFr0D7SI/vueXl1N03uzOun4nViGPFRyA5X6eL3jXw= github.com/smartcontractkit/libocr v0.0.0-20240717100443-f6226e09bee7 h1:e38V5FYE7DA1JfKXeD5Buo/7lczALuVXlJ8YNTAUxcw= github.com/smartcontractkit/libocr v0.0.0-20240717100443-f6226e09bee7/go.mod h1:fb1ZDVXACvu4frX3APHZaEBp0xi1DIm34DcA0CwTsZM= -github.com/smartcontractkit/seth v1.0.12 h1:iVdgMx42XWanPPnBaM5StR4c1XsTr/0/B/kKRZL5BsY= -github.com/smartcontractkit/seth v1.0.12/go.mod h1:thWtbLyW4nRHJGzC5heknQDORoJPErE15sF34LHkorg= +github.com/smartcontractkit/seth v1.1.1 h1:6hvexjJD7ek8ht/CLlEwQcH21K2E/WEYwbSRdKInZmM= +github.com/smartcontractkit/seth v1.1.1/go.mod h1:cDfKHi/hJLpO9sRpVbrflrHCOV+MJPAMJHloExJnIXk= github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 h1:yiKnypAqP8l0OX0P3klzZ7SCcBUxy5KqTAKZmQOvSQE= github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1/go.mod h1:q6f4fe39oZPdsh1i57WznEZgxd8siidMaSFq3wdPmVg= github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1 h1:Dai1bn+Q5cpeGMQwRdjOdVjG8mmFFROVkSKuUgBErRQ= diff --git a/integration-tests/testsetups/ocr.go b/integration-tests/testsetups/ocr.go index 45c334bf69..30b0a6fcb1 100644 --- a/integration-tests/testsetups/ocr.go +++ b/integration-tests/testsetups/ocr.go @@ -277,8 +277,7 @@ func (o *OCRSoakTest) Setup(ocrTestConfig tt.OcrTestConfig) { nodes, err := client.ConnectChainlinkNodes(o.testEnvironment) require.NoError(o.t, err, "Connecting to chainlink nodes shouldn't fail") o.bootstrapNode, o.workerNodes = nodes[0], nodes[1:] - o.mockServer, err = ctf_client.ConnectMockServer(o.testEnvironment) - require.NoError(o.t, err, "Creating mockserver clients shouldn't fail") + o.mockServer = ctf_client.ConnectMockServer(o.testEnvironment) linkContract, err := contracts.DeployLinkTokenContract(o.log, sethClient) require.NoError(o.t, err, "Error deploying LINK contract") @@ -546,12 +545,9 @@ func (o *OCRSoakTest) LoadState() error { } } - o.mockServer, err = ctf_client.ConnectMockServerURL(testState.MockServerURL) - if err != nil { - return err - } + o.mockServer = ctf_client.ConnectMockServerURL(testState.MockServerURL) - return err + return nil } func (o *OCRSoakTest) Resume() { From c6387675e8959898e73a3d90dedc2bdae9e46337 Mon Sep 17 00:00:00 2001 From: Suryansh <39276431+0xsuryansh@users.noreply.github.com> Date: Mon, 26 Aug 2024 18:25:01 +0530 Subject: [PATCH 028/115] Port v1.5 fixes to v1.6 (#1286) ## Motivation Porting the fixes done in https://github.com/smartcontractkit/ccip/pull/1212 1. Add ~~uint32~~ `bytes destExecData` to the `struct RampTokenAmount` to allow us to send the amount we billed on source to dest 2. removed `defaultTokenDestBytesOverhead` and used `CCIP_LOCK_OR_BURN_V1_RET_BYTES` as default value --------- Signed-off-by: 0xsuryansh Co-authored-by: app-token-issuer-infra-releng[bot] <120227048+app-token-issuer-infra-releng[bot]@users.noreply.github.com> --- contracts/gas-snapshots/ccip.gas-snapshot | 686 +++++++++--------- contracts/src/v0.8/ccip/PriceRegistry.sol | 23 +- .../v0.8/ccip/interfaces/IPriceRegistry.sol | 7 +- .../src/v0.8/ccip/libraries/Internal.sol | 12 +- contracts/src/v0.8/ccip/onRamp/OnRamp.sol | 9 +- .../src/v0.8/ccip/test/offRamp/OffRamp.t.sol | 40 +- .../v0.8/ccip/test/offRamp/OffRampSetup.t.sol | 6 +- .../test/priceRegistry/PriceRegistry.t.sol | 67 +- .../priceRegistry/PriceRegistrySetup.t.sol | 39 +- .../ccip/ccip_integration_tests/helpers.go | 1 - .../ccip/configs/evm/contract_reader.go | 4 +- .../ccip_reader_tester/ccip_reader_tester.go | 7 +- .../message_hasher/message_hasher.go | 5 +- .../ccip/generated/offramp/offramp.go | 5 +- .../ccip/generated/onramp/onramp.go | 7 +- .../price_registry/price_registry.go | 48 +- .../generated/report_codec/report_codec.go | 7 +- ...rapper-dependency-versions-do-not-edit.txt | 12 +- .../ccip/mocks/price_registry_interface.go | 110 +-- integration-tests/deployment/ccip/add_lane.go | 1 - 20 files changed, 583 insertions(+), 513 deletions(-) diff --git a/contracts/gas-snapshots/ccip.gas-snapshot b/contracts/gas-snapshots/ccip.gas-snapshot index 9680750a88..a573668aa9 100644 --- a/contracts/gas-snapshots/ccip.gas-snapshot +++ b/contracts/gas-snapshots/ccip.gas-snapshot @@ -10,8 +10,8 @@ AggregateTokenLimiter_getTokenBucket:test_GetTokenBucket_Success() (gas: 19691) AggregateTokenLimiter_getTokenBucket:test_Refill_Success() (gas: 40911) AggregateTokenLimiter_getTokenBucket:test_TimeUnderflow_Revert() (gas: 15368) AggregateTokenLimiter_getTokenLimitAdmin:test_GetTokenLimitAdmin_Success() (gas: 10531) -AggregateTokenLimiter_getTokenValue:test_GetTokenValue_Success() (gas: 19652) -AggregateTokenLimiter_getTokenValue:test_NoTokenPrice_Reverts() (gas: 21237) +AggregateTokenLimiter_getTokenValue:test_GetTokenValue_Success() (gas: 19668) +AggregateTokenLimiter_getTokenValue:test_NoTokenPrice_Reverts() (gas: 21253) AggregateTokenLimiter_rateLimitValue:test_AggregateValueMaxCapacityExceeded_Revert() (gas: 16418) AggregateTokenLimiter_rateLimitValue:test_RateLimitValueSuccess_gas() (gas: 18306) AggregateTokenLimiter_setAdmin:test_OnlyOwnerOrAdmin_Revert() (gas: 13047) @@ -34,7 +34,7 @@ BurnWithFromMintTokenPool_lockOrBurn:test_ChainNotAllowed_Revert() (gas: 28761) BurnWithFromMintTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 55115) BurnWithFromMintTokenPool_lockOrBurn:test_PoolBurn_Success() (gas: 243517) BurnWithFromMintTokenPool_lockOrBurn:test_Setup_Success() (gas: 23951) -CCIPClientExample_sanity:test_ImmutableExamples_Success() (gas: 2132726) +CCIPClientExample_sanity:test_ImmutableExamples_Success() (gas: 2132684) CCIPConfigSetup:test_getCapabilityConfiguration_Success() (gas: 9517) CCIPConfig_ConfigStateMachine:test__computeConfigDigest_Success() (gas: 70831) CCIPConfig_ConfigStateMachine:test__computeNewConfigWithMeta_InitToRunning_Success() (gas: 363664) @@ -98,16 +98,16 @@ CommitStore_isUnpausedAndRMNHealthy:test_RMN_Success() (gas: 73420) CommitStore_report:test_InvalidIntervalMinLargerThanMax_Revert() (gas: 28670) CommitStore_report:test_InvalidInterval_Revert() (gas: 28610) CommitStore_report:test_InvalidRootRevert() (gas: 27843) -CommitStore_report:test_OnlyGasPriceUpdates_Success() (gas: 53253) -CommitStore_report:test_OnlyPriceUpdateStaleReport_Revert() (gas: 59049) -CommitStore_report:test_OnlyTokenPriceUpdates_Success() (gas: 53251) +CommitStore_report:test_OnlyGasPriceUpdates_Success() (gas: 53275) +CommitStore_report:test_OnlyPriceUpdateStaleReport_Revert() (gas: 59071) +CommitStore_report:test_OnlyTokenPriceUpdates_Success() (gas: 53273) CommitStore_report:test_Paused_Revert() (gas: 21259) -CommitStore_report:test_ReportAndPriceUpdate_Success() (gas: 84242) +CommitStore_report:test_ReportAndPriceUpdate_Success() (gas: 84264) CommitStore_report:test_ReportOnlyRootSuccess_gas() (gas: 56313) CommitStore_report:test_RootAlreadyCommitted_Revert() (gas: 63969) -CommitStore_report:test_StaleReportWithRoot_Success() (gas: 119332) +CommitStore_report:test_StaleReportWithRoot_Success() (gas: 119364) CommitStore_report:test_Unhealthy_Revert() (gas: 44751) -CommitStore_report:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 100714) +CommitStore_report:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 100752) CommitStore_report:test_ZeroEpochAndRound_Revert() (gas: 27626) CommitStore_resetUnblessedRoots:test_OnlyOwner_Revert() (gas: 11325) CommitStore_resetUnblessedRoots:test_ResetUnblessedRoots_Success() (gas: 143718) @@ -123,7 +123,7 @@ CommitStore_verify:test_Paused_Revert() (gas: 18496) CommitStore_verify:test_TooManyLeaves_Revert() (gas: 36785) DefensiveExampleTest:test_HappyPath_Success() (gas: 200018) DefensiveExampleTest:test_Recovery() (gas: 424256) -E2E:test_E2E_3MessagesSuccess_gas() (gas: 1103907) +E2E:test_E2E_3MessagesSuccess_gas() (gas: 1104033) EVM2EVMOffRamp__releaseOrMintToken:test__releaseOrMintToken_NotACompatiblePool_Revert() (gas: 37797) EVM2EVMOffRamp__releaseOrMintToken:test__releaseOrMintToken_Success() (gas: 103733) EVM2EVMOffRamp__releaseOrMintToken:test__releaseOrMintToken_TokenHandlingError_transfer_Revert() (gas: 85258) @@ -131,20 +131,20 @@ EVM2EVMOffRamp__releaseOrMintToken:test_releaseOrMintToken_InvalidDataLength_Rev EVM2EVMOffRamp__releaseOrMintToken:test_releaseOrMintToken_ReleaseOrMintBalanceMismatch_Revert() (gas: 94302) EVM2EVMOffRamp__releaseOrMintToken:test_releaseOrMintToken_TokenHandlingError_BalanceOf_Revert() (gas: 39768) EVM2EVMOffRamp__releaseOrMintToken:test_releaseOrMintToken_skip_ReleaseOrMintBalanceMismatch_if_pool_Revert() (gas: 86559) -EVM2EVMOffRamp__releaseOrMintTokens:test_OverValueWithARLOff_Success() (gas: 385176) -EVM2EVMOffRamp__releaseOrMintTokens:test_PriceNotFoundForToken_Reverts() (gas: 141858) -EVM2EVMOffRamp__releaseOrMintTokens:test_RateLimitErrors_Reverts() (gas: 802991) -EVM2EVMOffRamp__releaseOrMintTokens:test_TokenHandlingError_Reverts() (gas: 179228) +EVM2EVMOffRamp__releaseOrMintTokens:test_OverValueWithARLOff_Success() (gas: 385246) +EVM2EVMOffRamp__releaseOrMintTokens:test_PriceNotFoundForToken_Reverts() (gas: 141896) +EVM2EVMOffRamp__releaseOrMintTokens:test_RateLimitErrors_Reverts() (gas: 803071) +EVM2EVMOffRamp__releaseOrMintTokens:test_TokenHandlingError_Reverts() (gas: 179244) EVM2EVMOffRamp__releaseOrMintTokens:test__releaseOrMintTokens_NotACompatiblePool_Reverts() (gas: 29240) EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_InvalidDataLengthReturnData_Revert() (gas: 66444) EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_InvalidEVMAddress_Revert() (gas: 43320) -EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_Success() (gas: 210936) -EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals_Success() (gas: 222200) +EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_Success() (gas: 210968) +EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals_Success() (gas: 222232) EVM2EVMOffRamp__report:test_Report_Success() (gas: 126637) -EVM2EVMOffRamp__trialExecute:test_RateLimitError_Success() (gas: 237775) -EVM2EVMOffRamp__trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 246375) -EVM2EVMOffRamp__trialExecute:test_TokenPoolIsNotAContract_Success() (gas: 329796) -EVM2EVMOffRamp__trialExecute:test_trialExecute_Success() (gas: 312233) +EVM2EVMOffRamp__trialExecute:test_RateLimitError_Success() (gas: 237791) +EVM2EVMOffRamp__trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 246391) +EVM2EVMOffRamp__trialExecute:test_TokenPoolIsNotAContract_Success() (gas: 329828) +EVM2EVMOffRamp__trialExecute:test_trialExecute_Success() (gas: 312265) EVM2EVMOffRamp_ccipReceive:test_Reverts() (gas: 17030) EVM2EVMOffRamp_constructor:test_CommitStoreAlreadyInUse_Revert() (gas: 153727) EVM2EVMOffRamp_constructor:test_Constructor_Success() (gas: 5665947) @@ -152,7 +152,7 @@ EVM2EVMOffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 144461) EVM2EVMOffRamp_execute:test_EmptyReport_Revert() (gas: 21318) EVM2EVMOffRamp_execute:test_InvalidMessageId_Revert() (gas: 36432) EVM2EVMOffRamp_execute:test_InvalidSourceChain_Revert() (gas: 51598) -EVM2EVMOffRamp_execute:test_InvalidSourcePoolAddress_Success() (gas: 473297) +EVM2EVMOffRamp_execute:test_InvalidSourcePoolAddress_Success() (gas: 473329) EVM2EVMOffRamp_execute:test_ManualExecutionNotYetEnabled_Revert() (gas: 47668) EVM2EVMOffRamp_execute:test_MessageTooLarge_Revert() (gas: 152359) EVM2EVMOffRamp_execute:test_Paused_Revert() (gas: 102842) @@ -163,25 +163,25 @@ EVM2EVMOffRamp_execute:test_SingleMessageNoTokensUnordered_Success() (gas: 15734 EVM2EVMOffRamp_execute:test_SingleMessageNoTokens_Success() (gas: 172692) EVM2EVMOffRamp_execute:test_SingleMessageToNonCCIPReceiver_Success() (gas: 247069) EVM2EVMOffRamp_execute:test_SingleMessagesNoTokensSuccess_gas() (gas: 114153) -EVM2EVMOffRamp_execute:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 407419) +EVM2EVMOffRamp_execute:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 407451) EVM2EVMOffRamp_execute:test_SkippedIncorrectNonce_Success() (gas: 54096) EVM2EVMOffRamp_execute:test_StrictUntouchedToSuccess_Success() (gas: 131047) EVM2EVMOffRamp_execute:test_TokenDataMismatch_Revert() (gas: 52090) -EVM2EVMOffRamp_execute:test_TwoMessagesWithTokensAndGE_Success() (gas: 563321) -EVM2EVMOffRamp_execute:test_TwoMessagesWithTokensSuccess_gas() (gas: 495444) +EVM2EVMOffRamp_execute:test_TwoMessagesWithTokensAndGE_Success() (gas: 563385) +EVM2EVMOffRamp_execute:test_TwoMessagesWithTokensSuccess_gas() (gas: 495508) EVM2EVMOffRamp_execute:test_UnexpectedTokenData_Revert() (gas: 35383) -EVM2EVMOffRamp_execute:test_Unhealthy_Revert() (gas: 544577) +EVM2EVMOffRamp_execute:test_Unhealthy_Revert() (gas: 544641) EVM2EVMOffRamp_execute:test_UnsupportedNumberOfTokens_Revert() (gas: 64326) EVM2EVMOffRamp_execute:test__execute_SkippedAlreadyExecutedMessageUnordered_Success() (gas: 122322) EVM2EVMOffRamp_execute:test__execute_SkippedAlreadyExecutedMessage_Success() (gas: 142532) EVM2EVMOffRamp_execute:test_execute_RouterYULCall_Success() (gas: 427337) EVM2EVMOffRamp_executeSingleMessage:test_MessageSender_Revert() (gas: 18502) -EVM2EVMOffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 278065) +EVM2EVMOffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 278097) EVM2EVMOffRamp_executeSingleMessage:test_NonContract_Success() (gas: 18659) -EVM2EVMOffRamp_executeSingleMessage:test_TokenHandlingError_Revert() (gas: 221405) +EVM2EVMOffRamp_executeSingleMessage:test_TokenHandlingError_Revert() (gas: 221421) EVM2EVMOffRamp_executeSingleMessage:test_ZeroGasDONExecution_Revert() (gas: 47881) EVM2EVMOffRamp_executeSingleMessage:test_executeSingleMessage_NoTokens_Success() (gas: 47352) -EVM2EVMOffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens_Success() (gas: 313885) +EVM2EVMOffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens_Success() (gas: 313917) EVM2EVMOffRamp_executeSingleMessage:test_executeSingleMessage_ZeroGasZeroData_Success() (gas: 70008) EVM2EVMOffRamp_execute_upgrade:test_V2NonceNewSenderStartsAtZero_Success() (gas: 229319) EVM2EVMOffRamp_execute_upgrade:test_V2NonceStartsAtV1Nonce_Success() (gas: 276790) @@ -195,13 +195,13 @@ EVM2EVMOffRamp_manuallyExecute:test_ManualExecFailedTx_Revert() (gas: 185829) EVM2EVMOffRamp_manuallyExecute:test_ManualExecForkedChain_Revert() (gas: 27049) EVM2EVMOffRamp_manuallyExecute:test_ManualExecGasLimitMismatch_Revert() (gas: 45155) EVM2EVMOffRamp_manuallyExecute:test_ManualExecInvalidGasLimit_Revert() (gas: 27468) -EVM2EVMOffRamp_manuallyExecute:test_ManualExecWithMultipleMessagesAndSourceTokens_Success() (gas: 530087) -EVM2EVMOffRamp_manuallyExecute:test_ManualExecWithSourceTokens_Success() (gas: 345726) +EVM2EVMOffRamp_manuallyExecute:test_ManualExecWithMultipleMessagesAndSourceTokens_Success() (gas: 530151) +EVM2EVMOffRamp_manuallyExecute:test_ManualExecWithSourceTokens_Success() (gas: 345758) EVM2EVMOffRamp_manuallyExecute:test_ManualExec_Success() (gas: 187324) -EVM2EVMOffRamp_manuallyExecute:test_ReentrancyManualExecuteFails_Success() (gas: 2321890) -EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_DestinationGasAmountCountMismatch_Revert() (gas: 362933) +EVM2EVMOffRamp_manuallyExecute:test_ReentrancyManualExecuteFails_Success() (gas: 2321906) +EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_DestinationGasAmountCountMismatch_Revert() (gas: 362965) EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_DoesNotRevertIfUntouched_Success() (gas: 143900) -EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_InvalidTokenGasOverride_Revert() (gas: 366072) +EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_InvalidTokenGasOverride_Revert() (gas: 366104) EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_LowGasLimitManualExec_Success() (gas: 482691) EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_WithGasOverride_Success() (gas: 189727) EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_WithInvalidReceiverExecutionGasOverride_Revert() (gas: 153641) @@ -225,47 +225,47 @@ EVM2EVMOnRamp_forwardFromRouter:test_InvalidAddressEncodePacked_Revert() (gas: 3 EVM2EVMOnRamp_forwardFromRouter:test_InvalidAddress_Revert() (gas: 38440) EVM2EVMOnRamp_forwardFromRouter:test_InvalidChainSelector_Revert() (gas: 25489) EVM2EVMOnRamp_forwardFromRouter:test_InvalidExtraArgsTag_Revert() (gas: 25275) -EVM2EVMOnRamp_forwardFromRouter:test_MaxCapacityExceeded_Revert() (gas: 85997) +EVM2EVMOnRamp_forwardFromRouter:test_MaxCapacityExceeded_Revert() (gas: 86013) EVM2EVMOnRamp_forwardFromRouter:test_MaxFeeBalanceReached_Revert() (gas: 36457) EVM2EVMOnRamp_forwardFromRouter:test_MessageGasLimitTooHigh_Revert() (gas: 29015) EVM2EVMOnRamp_forwardFromRouter:test_MessageTooLarge_Revert() (gas: 107571) EVM2EVMOnRamp_forwardFromRouter:test_OriginalSender_Revert() (gas: 22679) -EVM2EVMOnRamp_forwardFromRouter:test_OverValueWithARLOff_Success() (gas: 224581) +EVM2EVMOnRamp_forwardFromRouter:test_OverValueWithARLOff_Success() (gas: 224619) EVM2EVMOnRamp_forwardFromRouter:test_Paused_Revert() (gas: 53072) EVM2EVMOnRamp_forwardFromRouter:test_Permissions_Revert() (gas: 25481) -EVM2EVMOnRamp_forwardFromRouter:test_PriceNotFoundForToken_Revert() (gas: 59303) +EVM2EVMOnRamp_forwardFromRouter:test_PriceNotFoundForToken_Revert() (gas: 59341) EVM2EVMOnRamp_forwardFromRouter:test_ShouldIncrementNonceOnlyOnOrdered_Success() (gas: 179148) EVM2EVMOnRamp_forwardFromRouter:test_ShouldIncrementSeqNumAndNonce_Success() (gas: 177430) -EVM2EVMOnRamp_forwardFromRouter:test_ShouldStoreNonLinkFees() (gas: 137234) +EVM2EVMOnRamp_forwardFromRouter:test_ShouldStoreNonLinkFees() (gas: 137254) EVM2EVMOnRamp_forwardFromRouter:test_SourceTokenDataTooLarge_Revert() (gas: 3822827) EVM2EVMOnRamp_forwardFromRouter:test_TooManyTokens_Revert() (gas: 30187) EVM2EVMOnRamp_forwardFromRouter:test_Unhealthy_Revert() (gas: 43300) -EVM2EVMOnRamp_forwardFromRouter:test_UnsupportedToken_Revert() (gas: 109283) +EVM2EVMOnRamp_forwardFromRouter:test_UnsupportedToken_Revert() (gas: 109305) EVM2EVMOnRamp_forwardFromRouter:test_ZeroAddressReceiver_Revert() (gas: 312579) EVM2EVMOnRamp_forwardFromRouter:test_forwardFromRouter_ShouldStoreLinkFees_Success() (gas: 112322) EVM2EVMOnRamp_forwardFromRouter:test_forwardFromRouter_UnsupportedToken_Revert() (gas: 72206) -EVM2EVMOnRamp_forwardFromRouter:test_forwardFromRouter_correctSourceTokenData_Success() (gas: 710443) +EVM2EVMOnRamp_forwardFromRouter:test_forwardFromRouter_correctSourceTokenData_Success() (gas: 710475) EVM2EVMOnRamp_forwardFromRouter_upgrade:test_V2NonceNewSenderStartsAtZero_Success() (gas: 147664) EVM2EVMOnRamp_forwardFromRouter_upgrade:test_V2NonceStartsAtV1Nonce_Success() (gas: 190529) EVM2EVMOnRamp_forwardFromRouter_upgrade:test_V2SenderNoncesReadsPreviousRamp_Success() (gas: 121320) EVM2EVMOnRamp_forwardFromRouter_upgrade:test_V2_Success() (gas: 95349) EVM2EVMOnRamp_getDataAvailabilityCost:test_EmptyMessageCalculatesDataAvailabilityCost_Success() (gas: 20544) EVM2EVMOnRamp_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCost_Success() (gas: 20912) -EVM2EVMOnRamp_getFee:test_EmptyMessage_Success() (gas: 78242) -EVM2EVMOnRamp_getFee:test_HighGasMessage_Success() (gas: 234090) +EVM2EVMOnRamp_getFee:test_EmptyMessage_Success() (gas: 78230) +EVM2EVMOnRamp_getFee:test_HighGasMessage_Success() (gas: 234078) EVM2EVMOnRamp_getFee:test_MessageGasLimitTooHigh_Revert() (gas: 16715) EVM2EVMOnRamp_getFee:test_MessageTooLarge_Revert() (gas: 95271) -EVM2EVMOnRamp_getFee:test_MessageWithDataAndTokenTransfer_Success() (gas: 159352) +EVM2EVMOnRamp_getFee:test_MessageWithDataAndTokenTransfer_Success() (gas: 159436) EVM2EVMOnRamp_getFee:test_NotAFeeToken_Revert() (gas: 24089) -EVM2EVMOnRamp_getFee:test_SingleTokenMessage_Success() (gas: 117902) +EVM2EVMOnRamp_getFee:test_SingleTokenMessage_Success() (gas: 117922) EVM2EVMOnRamp_getFee:test_TooManyTokens_Revert() (gas: 19902) -EVM2EVMOnRamp_getFee:test_ZeroDataAvailabilityMultiplier_Success() (gas: 64654) +EVM2EVMOnRamp_getFee:test_ZeroDataAvailabilityMultiplier_Success() (gas: 64648) EVM2EVMOnRamp_getSupportedTokens:test_GetSupportedTokens_Revert() (gas: 10460) EVM2EVMOnRamp_getTokenPool:test_GetTokenPool_Success() (gas: 35195) -EVM2EVMOnRamp_getTokenTransferCost:test_CustomTokenBpsFee_Success() (gas: 45104) +EVM2EVMOnRamp_getTokenTransferCost:test_CustomTokenBpsFee_Success() (gas: 45120) EVM2EVMOnRamp_getTokenTransferCost:test_FeeTokenBpsFee_Success() (gas: 33019) EVM2EVMOnRamp_getTokenTransferCost:test_LargeTokenTransferChargesMaxFeeAndGas_Success() (gas: 28296) -EVM2EVMOnRamp_getTokenTransferCost:test_MixedTokenTransferFee_Success() (gas: 126357) +EVM2EVMOnRamp_getTokenTransferCost:test_MixedTokenTransferFee_Success() (gas: 126453) EVM2EVMOnRamp_getTokenTransferCost:test_NoTokenTransferChargesZeroFee_Success() (gas: 15238) EVM2EVMOnRamp_getTokenTransferCost:test_SmallTokenTransferChargesMinFeeAndGas_Success() (gas: 28104) EVM2EVMOnRamp_getTokenTransferCost:test_UnsupportedToken_Revert() (gas: 21248) @@ -377,27 +377,27 @@ MultiAggregateRateLimiter_constructor:test_Constructor_Success() (gas: 2265894) MultiAggregateRateLimiter_getTokenBucket:test_GetTokenBucket_Success() (gas: 30248) MultiAggregateRateLimiter_getTokenBucket:test_Refill_Success() (gas: 47358) MultiAggregateRateLimiter_getTokenBucket:test_TimeUnderflow_Revert() (gas: 15821) -MultiAggregateRateLimiter_getTokenValue:test_GetTokenValue_Success() (gas: 19668) -MultiAggregateRateLimiter_getTokenValue:test_NoTokenPrice_Reverts() (gas: 21253) +MultiAggregateRateLimiter_getTokenValue:test_GetTokenValue_Success() (gas: 19684) +MultiAggregateRateLimiter_getTokenValue:test_NoTokenPrice_Reverts() (gas: 21269) MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageFromUnauthorizedCaller_Revert() (gas: 14527) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithDifferentTokensOnDifferentChains_Success() (gas: 213612) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithDisabledRateLimitToken_Success() (gas: 60443) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithDifferentTokensOnDifferentChains_Success() (gas: 213660) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithDisabledRateLimitToken_Success() (gas: 60459) MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithNoTokens_Success() (gas: 17593) MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitDisabled_Success() (gas: 44895) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitExceeded_Revert() (gas: 50510) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitReset_Success() (gas: 78604) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithTokensOnDifferentChains_Success() (gas: 311885) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithTokens_Success() (gas: 54696) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitExceeded_Revert() (gas: 50542) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitReset_Success() (gas: 78668) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithTokensOnDifferentChains_Success() (gas: 311949) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithTokens_Success() (gas: 54728) MultiAggregateRateLimiter_onOutboundMessage:test_RateLimitValueDifferentLanes_Success() (gas: 9223372036854754743) MultiAggregateRateLimiter_onOutboundMessage:test_ValidateMessageWithNoTokens_Success() (gas: 19104) MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageFromUnauthorizedCaller_Revert() (gas: 15778) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithDifferentTokensOnDifferentChains_Success() (gas: 213600) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithDisabledRateLimitToken_Success() (gas: 62178) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithDifferentTokensOnDifferentChains_Success() (gas: 213648) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithDisabledRateLimitToken_Success() (gas: 62194) MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitDisabled_Success() (gas: 46683) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitExceeded_Revert() (gas: 52283) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitReset_Success() (gas: 79669) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithTokensOnDifferentChains_Success() (gas: 312099) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithTokens_Success() (gas: 56453) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitExceeded_Revert() (gas: 52315) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitReset_Success() (gas: 79733) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithTokensOnDifferentChains_Success() (gas: 312163) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithTokens_Success() (gas: 56485) MultiAggregateRateLimiter_setPriceRegistry:test_OnlyOwner_Revert() (gas: 11292) MultiAggregateRateLimiter_setPriceRegistry:test_Owner_Success() (gas: 19080) MultiAggregateRateLimiter_setPriceRegistry:test_ZeroAddress_Revert() (gas: 10564) @@ -438,23 +438,23 @@ MultiOCR3Base_transmit:test_UnAuthorizedTransmitter_Revert() (gas: 24191) MultiOCR3Base_transmit:test_UnauthorizedSigner_Revert() (gas: 61409) MultiOCR3Base_transmit:test_UnconfiguredPlugin_Revert() (gas: 39890) MultiOCR3Base_transmit:test_ZeroSignatures_Revert() (gas: 32973) -MultiOnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 393648) -MultiRampsE2E:test_E2E_3MessagesMMultiOffRampSuccess_gas() (gas: 1448351) +MultiOnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 410740) +MultiRampsE2E:test_E2E_3MessagesMMultiOffRampSuccess_gas() (gas: 1486877) NonceManager_NonceIncrementation:test_getIncrementedOutboundNonce_Success() (gas: 37907) NonceManager_NonceIncrementation:test_incrementInboundNonce_Skip() (gas: 23694) NonceManager_NonceIncrementation:test_incrementInboundNonce_Success() (gas: 38763) NonceManager_NonceIncrementation:test_incrementNoncesInboundAndOutbound_Success() (gas: 71847) -NonceManager_OffRampUpgrade:test_NoPrevOffRampForChain_Success() (gas: 257252) -NonceManager_OffRampUpgrade:test_UpgradedNonceNewSenderStartsAtZero_Success() (gas: 259369) -NonceManager_OffRampUpgrade:test_UpgradedNonceStartsAtV1Nonce_Success() (gas: 319959) -NonceManager_OffRampUpgrade:test_UpgradedOffRampNonceSkipsIfMsgInFlight_Success() (gas: 295278) +NonceManager_OffRampUpgrade:test_NoPrevOffRampForChain_Success() (gas: 257298) +NonceManager_OffRampUpgrade:test_UpgradedNonceNewSenderStartsAtZero_Success() (gas: 259415) +NonceManager_OffRampUpgrade:test_UpgradedNonceStartsAtV1Nonce_Success() (gas: 320051) +NonceManager_OffRampUpgrade:test_UpgradedOffRampNonceSkipsIfMsgInFlight_Success() (gas: 295325) NonceManager_OffRampUpgrade:test_UpgradedSenderNoncesReadsPreviousRampTransitive_Success() (gas: 244940) NonceManager_OffRampUpgrade:test_UpgradedSenderNoncesReadsPreviousRamp_Success() (gas: 233260) -NonceManager_OffRampUpgrade:test_Upgraded_Success() (gas: 150148) -NonceManager_OnRampUpgrade:test_UpgradeNonceNewSenderStartsAtZero_Success() (gas: 167714) -NonceManager_OnRampUpgrade:test_UpgradeNonceStartsAtV1Nonce_Success() (gas: 218902) +NonceManager_OffRampUpgrade:test_Upgraded_Success() (gas: 150194) +NonceManager_OnRampUpgrade:test_UpgradeNonceNewSenderStartsAtZero_Success() (gas: 168502) +NonceManager_OnRampUpgrade:test_UpgradeNonceStartsAtV1Nonce_Success() (gas: 220478) NonceManager_OnRampUpgrade:test_UpgradeSenderNoncesReadsPreviousRamp_Success() (gas: 125070) -NonceManager_OnRampUpgrade:test_Upgrade_Success() (gas: 106943) +NonceManager_OnRampUpgrade:test_Upgrade_Success() (gas: 107731) NonceManager_applyPreviousRampsUpdates:test_MultipleRampsUpdates() (gas: 122943) NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySetOffRamp_Revert() (gas: 42959) NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySetOnRampAndOffRamp_Revert() (gas: 64282) @@ -487,172 +487,172 @@ OCR2Base_transmit:test_Transmit2SignersSuccess_gas() (gas: 51686) OCR2Base_transmit:test_UnAuthorizedTransmitter_Revert() (gas: 23484) OCR2Base_transmit:test_UnauthorizedSigner_Revert() (gas: 39665) OCR2Base_transmit:test_WrongNumberOfSignatures_Revert() (gas: 20557) -OffRamp__releaseOrMintSingleToken:test__releaseOrMintSingleToken_NotACompatiblePool_Revert() (gas: 38408) -OffRamp__releaseOrMintSingleToken:test__releaseOrMintSingleToken_Success() (gas: 106250) -OffRamp__releaseOrMintSingleToken:test__releaseOrMintSingleToken_TokenHandlingError_transfer_Revert() (gas: 87409) -OffRamp__releaseOrMintSingleToken:test_releaseOrMintToken_InvalidDataLength_Revert() (gas: 38954) -OffRamp__releaseOrMintSingleToken:test_releaseOrMintToken_ReleaseOrMintBalanceMismatch_Revert() (gas: 96511) -OffRamp__releaseOrMintSingleToken:test_releaseOrMintToken_TokenHandlingError_BalanceOf_Revert() (gas: 41956) -OffRamp__releaseOrMintSingleToken:test_releaseOrMintToken_skip_ReleaseOrMintBalanceMismatch_if_pool_Revert() (gas: 88684) -OffRamp_applySourceChainConfigUpdates:test_AddMultipleChains_Success() (gas: 468115) -OffRamp_applySourceChainConfigUpdates:test_AddNewChain_Success() (gas: 99227) +OffRamp__releaseOrMintSingleToken:test__releaseOrMintSingleToken_NotACompatiblePool_Revert() (gas: 40127) +OffRamp__releaseOrMintSingleToken:test__releaseOrMintSingleToken_Success() (gas: 107130) +OffRamp__releaseOrMintSingleToken:test__releaseOrMintSingleToken_TokenHandlingError_transfer_Revert() (gas: 88331) +OffRamp__releaseOrMintSingleToken:test_releaseOrMintToken_InvalidDataLength_Revert() (gas: 39848) +OffRamp__releaseOrMintSingleToken:test_releaseOrMintToken_ReleaseOrMintBalanceMismatch_Revert() (gas: 97399) +OffRamp__releaseOrMintSingleToken:test_releaseOrMintToken_TokenHandlingError_BalanceOf_Revert() (gas: 42843) +OffRamp__releaseOrMintSingleToken:test_releaseOrMintToken_skip_ReleaseOrMintBalanceMismatch_if_pool_Revert() (gas: 89579) +OffRamp_applySourceChainConfigUpdates:test_AddMultipleChains_Success() (gas: 467917) +OffRamp_applySourceChainConfigUpdates:test_AddNewChain_Success() (gas: 99161) OffRamp_applySourceChainConfigUpdates:test_ApplyZeroUpdates_Success() (gas: 12395) OffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChainOnRamp_Revert() (gas: 93181) -OffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChain_Success() (gas: 109890) +OffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChain_Success() (gas: 109824) OffRamp_applySourceChainConfigUpdates:test_RouterAddress_Revert() (gas: 13263) OffRamp_applySourceChainConfigUpdates:test_ZeroOnRampAddress_Revert() (gas: 17988) OffRamp_applySourceChainConfigUpdates:test_ZeroSourceChainSelector_Revert() (gas: 15343) -OffRamp_batchExecute:test_MultipleReportsDifferentChains_Success() (gas: 313594) -OffRamp_batchExecute:test_MultipleReportsSameChain_Success() (gas: 254984) -OffRamp_batchExecute:test_MultipleReportsSkipDuplicate_Success() (gas: 166123) -OffRamp_batchExecute:test_OutOfBoundsGasLimitsAccess_Revert() (gas: 187729) -OffRamp_batchExecute:test_SingleReport_Success() (gas: 153140) -OffRamp_batchExecute:test_Unhealthy_Revert() (gas: 518887) +OffRamp_batchExecute:test_MultipleReportsDifferentChains_Success() (gas: 313729) +OffRamp_batchExecute:test_MultipleReportsSameChain_Success() (gas: 255119) +OffRamp_batchExecute:test_MultipleReportsSkipDuplicate_Success() (gas: 166168) +OffRamp_batchExecute:test_OutOfBoundsGasLimitsAccess_Revert() (gas: 187819) +OffRamp_batchExecute:test_SingleReport_Success() (gas: 153185) +OffRamp_batchExecute:test_Unhealthy_Revert() (gas: 532970) OffRamp_batchExecute:test_ZeroReports_Revert() (gas: 10439) -OffRamp_ccipReceive:test_Reverts() (gas: 15684) -OffRamp_commit:test_InvalidIntervalMinLargerThanMax_Revert() (gas: 67458) -OffRamp_commit:test_InvalidInterval_Revert() (gas: 59734) -OffRamp_commit:test_InvalidRootRevert() (gas: 58814) -OffRamp_commit:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6538106) -OffRamp_commit:test_NoConfig_Revert() (gas: 6121178) -OffRamp_commit:test_OnlyGasPriceUpdates_Success() (gas: 106251) -OffRamp_commit:test_OnlyPriceUpdateStaleReport_Revert() (gas: 116259) -OffRamp_commit:test_OnlyTokenPriceUpdates_Success() (gas: 106272) -OffRamp_commit:test_PriceSequenceNumberCleared_Success() (gas: 351586) -OffRamp_commit:test_ReportAndPriceUpdate_Success() (gas: 159364) -OffRamp_commit:test_ReportOnlyRootSuccess_gas() (gas: 136569) -OffRamp_commit:test_RootAlreadyCommitted_Revert() (gas: 136859) -OffRamp_commit:test_SourceChainNotEnabled_Revert() (gas: 59082) -OffRamp_commit:test_StaleReportWithRoot_Success() (gas: 225684) -OffRamp_commit:test_UnauthorizedTransmitter_Revert() (gas: 117566) -OffRamp_commit:test_Unhealthy_Revert() (gas: 77608) -OffRamp_commit:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 205073) -OffRamp_commit:test_WrongConfigWithoutSigners_Revert() (gas: 6532429) -OffRamp_commit:test_ZeroEpochAndRound_Revert() (gas: 47788) -OffRamp_constructor:test_Constructor_Success() (gas: 6125436) -OffRamp_constructor:test_SourceChainSelector_Revert() (gas: 137067) -OffRamp_constructor:test_ZeroChainSelector_Revert() (gas: 103784) -OffRamp_constructor:test_ZeroNonceManager_Revert() (gas: 101677) -OffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 139641) -OffRamp_constructor:test_ZeroRMNProxy_Revert() (gas: 101554) -OffRamp_constructor:test_ZeroTokenAdminRegistry_Revert() (gas: 101599) -OffRamp_execute:test_IncorrectArrayType_Revert() (gas: 17261) -OffRamp_execute:test_LargeBatch_Success() (gas: 1726826) -OffRamp_execute:test_MultipleReportsWithPartialValidationFailures_Success() (gas: 349476) -OffRamp_execute:test_MultipleReports_Success() (gas: 276933) -OffRamp_execute:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6588804) -OffRamp_execute:test_NoConfig_Revert() (gas: 6171638) -OffRamp_execute:test_NonArray_Revert() (gas: 27733) -OffRamp_execute:test_SingleReport_Success() (gas: 172458) -OffRamp_execute:test_UnauthorizedTransmitter_Revert() (gas: 147390) -OffRamp_execute:test_WrongConfigWithSigners_Revert() (gas: 6950878) -OffRamp_execute:test_ZeroReports_Revert() (gas: 17159) -OffRamp_executeSingleMessage:test_MessageSender_Revert() (gas: 18190) -OffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 246556) -OffRamp_executeSingleMessage:test_NonContract_Success() (gas: 20472) -OffRamp_executeSingleMessage:test_TokenHandlingError_Revert() (gas: 205195) -OffRamp_executeSingleMessage:test_ZeroGasDONExecution_Revert() (gas: 48734) -OffRamp_executeSingleMessage:test_executeSingleMessage_NoTokens_Success() (gas: 48257) -OffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidationNoRouterCall_Revert() (gas: 229631) -OffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidation_Revert() (gas: 86202) -OffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens_Success() (gas: 277436) -OffRamp_executeSingleMessage:test_executeSingleMessage_WithValidation_Success() (gas: 92436) -OffRamp_executeSingleReport:test_DisabledSourceChain_Revert() (gas: 35126) -OffRamp_executeSingleReport:test_EmptyReport_Revert() (gas: 23922) -OffRamp_executeSingleReport:test_InvalidSourcePoolAddress_Success() (gas: 475599) -OffRamp_executeSingleReport:test_ManualExecutionNotYetEnabled_Revert() (gas: 54456) -OffRamp_executeSingleReport:test_MismatchingDestChainSelector_Revert() (gas: 35904) -OffRamp_executeSingleReport:test_MismatchingOnRampRoot_Revert() (gas: 154426) -OffRamp_executeSingleReport:test_NonExistingSourceChain_Revert() (gas: 35337) -OffRamp_executeSingleReport:test_ReceiverError_Success() (gas: 184865) -OffRamp_executeSingleReport:test_RetryFailedMessageWithoutManualExecution_Revert() (gas: 196122) -OffRamp_executeSingleReport:test_RootNotCommitted_Revert() (gas: 48073) -OffRamp_executeSingleReport:test_RouterYULCall_Revert() (gas: 444686) -OffRamp_executeSingleReport:test_SingleMessageNoTokensOtherChain_Success() (gas: 250335) -OffRamp_executeSingleReport:test_SingleMessageNoTokensUnordered_Success() (gas: 187191) -OffRamp_executeSingleReport:test_SingleMessageNoTokens_Success() (gas: 206771) -OffRamp_executeSingleReport:test_SingleMessageToNonCCIPReceiver_Success() (gas: 263519) -OffRamp_executeSingleReport:test_SingleMessagesNoTokensSuccess_gas() (gas: 138408) -OffRamp_executeSingleReport:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 409328) -OffRamp_executeSingleReport:test_SkippedIncorrectNonce_Success() (gas: 65876) -OffRamp_executeSingleReport:test_TokenDataMismatch_Revert() (gas: 80909) -OffRamp_executeSingleReport:test_TwoMessagesWithTokensAndGE_Success() (gas: 566299) -OffRamp_executeSingleReport:test_TwoMessagesWithTokensSuccess_gas() (gas: 517689) -OffRamp_executeSingleReport:test_UnexpectedTokenData_Revert() (gas: 35742) -OffRamp_executeSingleReport:test_UnhealthySingleChainCurse_Revert() (gas: 517721) -OffRamp_executeSingleReport:test_Unhealthy_Revert() (gas: 515089) -OffRamp_executeSingleReport:test_WithCurseOnAnotherSourceChain_Success() (gas: 485207) -OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessageUnordered_Success() (gas: 133513) -OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessage_Success() (gas: 162713) -OffRamp_getExecutionState:test_FillExecutionState_Success() (gas: 3674540) -OffRamp_getExecutionState:test_GetDifferentChainExecutionState_Success() (gas: 118375) -OffRamp_getExecutionState:test_GetExecutionState_Success() (gas: 87586) -OffRamp_manuallyExecute:test_ManualExecGasLimitMismatchSingleReport_Revert() (gas: 75635) -OffRamp_manuallyExecute:test_ManualExecInvalidGasLimit_Revert() (gas: 26471) -OffRamp_manuallyExecute:test_manuallyExecute_DoesNotRevertIfUntouched_Success() (gas: 168604) -OffRamp_manuallyExecute:test_manuallyExecute_FailedTx_Revert() (gas: 205435) -OffRamp_manuallyExecute:test_manuallyExecute_ForkedChain_Revert() (gas: 26014) -OffRamp_manuallyExecute:test_manuallyExecute_GasLimitMismatchMultipleReports_Revert() (gas: 152948) -OffRamp_manuallyExecute:test_manuallyExecute_LowGasLimit_Success() (gas: 518487) -OffRamp_manuallyExecute:test_manuallyExecute_ReentrancyFails_Success() (gas: 2295740) -OffRamp_manuallyExecute:test_manuallyExecute_Success() (gas: 205788) -OffRamp_manuallyExecute:test_manuallyExecute_WithGasOverride_Success() (gas: 206365) -OffRamp_manuallyExecute:test_manuallyExecute_WithMultiReportGasOverride_Success() (gas: 649321) -OffRamp_manuallyExecute:test_manuallyExecute_WithPartialMessages_Success() (gas: 318903) -OffRamp_releaseOrMintTokens:test_TokenHandlingError_Reverts() (gas: 164042) -OffRamp_releaseOrMintTokens:test__releaseOrMintTokens_PoolIsNotAPool_Reverts() (gas: 23736) -OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_InvalidDataLengthReturnData_Revert() (gas: 64484) -OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_InvalidEVMAddress_Revert() (gas: 39516) -OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_PoolDoesNotSupportDest_Reverts() (gas: 81512) -OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_Success() (gas: 176140) -OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals_Success() (gas: 189342) -OffRamp_resetUnblessedRoots:test_OnlyOwner_Revert() (gas: 11379) -OffRamp_resetUnblessedRoots:test_ResetUnblessedRoots_Success() (gas: 215398) -OffRamp_setDynamicConfig:test_NonOwner_Revert() (gas: 14140) -OffRamp_setDynamicConfig:test_PriceRegistryZeroAddress_Revert() (gas: 11660) -OffRamp_setDynamicConfig:test_SetDynamicConfigWithValidator_Success() (gas: 49203) -OffRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 27147) -OffRamp_trialExecute:test_RateLimitError_Success() (gas: 221780) -OffRamp_trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 230403) -OffRamp_trialExecute:test_TokenPoolIsNotAContract_Success() (gas: 297574) -OffRamp_trialExecute:test_trialExecute_Success() (gas: 279978) -OffRamp_verify:test_Blessed_Success() (gas: 176620) -OffRamp_verify:test_NotBlessedWrongChainSelector_Success() (gas: 178688) -OffRamp_verify:test_NotBlessed_Success() (gas: 141549) +OffRamp_ccipReceive:test_Reverts() (gas: 15773) +OffRamp_commit:test_InvalidIntervalMinLargerThanMax_Revert() (gas: 67436) +OffRamp_commit:test_InvalidInterval_Revert() (gas: 59778) +OffRamp_commit:test_InvalidRootRevert() (gas: 58858) +OffRamp_commit:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6551011) +OffRamp_commit:test_NoConfig_Revert() (gas: 6134083) +OffRamp_commit:test_OnlyGasPriceUpdates_Success() (gas: 106295) +OffRamp_commit:test_OnlyPriceUpdateStaleReport_Revert() (gas: 116369) +OffRamp_commit:test_OnlyTokenPriceUpdates_Success() (gas: 106316) +OffRamp_commit:test_PriceSequenceNumberCleared_Success() (gas: 351652) +OffRamp_commit:test_ReportAndPriceUpdate_Success() (gas: 159342) +OffRamp_commit:test_ReportOnlyRootSuccess_gas() (gas: 136480) +OffRamp_commit:test_RootAlreadyCommitted_Revert() (gas: 136947) +OffRamp_commit:test_SourceChainNotEnabled_Revert() (gas: 59126) +OffRamp_commit:test_StaleReportWithRoot_Success() (gas: 225582) +OffRamp_commit:test_UnauthorizedTransmitter_Revert() (gas: 117632) +OffRamp_commit:test_Unhealthy_Revert() (gas: 77652) +OffRamp_commit:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 205066) +OffRamp_commit:test_WrongConfigWithoutSigners_Revert() (gas: 6545334) +OffRamp_commit:test_ZeroEpochAndRound_Revert() (gas: 47832) +OffRamp_constructor:test_Constructor_Success() (gas: 6137987) +OffRamp_constructor:test_SourceChainSelector_Revert() (gas: 137086) +OffRamp_constructor:test_ZeroChainSelector_Revert() (gas: 103803) +OffRamp_constructor:test_ZeroNonceManager_Revert() (gas: 101696) +OffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 139661) +OffRamp_constructor:test_ZeroRMNProxy_Revert() (gas: 101573) +OffRamp_constructor:test_ZeroTokenAdminRegistry_Revert() (gas: 101618) +OffRamp_execute:test_IncorrectArrayType_Revert() (gas: 17305) +OffRamp_execute:test_LargeBatch_Success() (gas: 1728220) +OffRamp_execute:test_MultipleReportsWithPartialValidationFailures_Success() (gas: 349589) +OffRamp_execute:test_MultipleReports_Success() (gas: 277112) +OffRamp_execute:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6601732) +OffRamp_execute:test_NoConfig_Revert() (gas: 6184566) +OffRamp_execute:test_NonArray_Revert() (gas: 27777) +OffRamp_execute:test_SingleReport_Success() (gas: 172547) +OffRamp_execute:test_UnauthorizedTransmitter_Revert() (gas: 147479) +OffRamp_execute:test_WrongConfigWithSigners_Revert() (gas: 6963806) +OffRamp_execute:test_ZeroReports_Revert() (gas: 17203) +OffRamp_executeSingleMessage:test_MessageSender_Revert() (gas: 18235) +OffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 249015) +OffRamp_executeSingleMessage:test_NonContract_Success() (gas: 20517) +OffRamp_executeSingleMessage:test_TokenHandlingError_Revert() (gas: 207654) +OffRamp_executeSingleMessage:test_ZeroGasDONExecution_Revert() (gas: 48779) +OffRamp_executeSingleMessage:test_executeSingleMessage_NoTokens_Success() (gas: 48302) +OffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidationNoRouterCall_Revert() (gas: 229610) +OffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidation_Revert() (gas: 86181) +OffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens_Success() (gas: 280837) +OffRamp_executeSingleMessage:test_executeSingleMessage_WithValidation_Success() (gas: 92415) +OffRamp_executeSingleReport:test_DisabledSourceChain_Revert() (gas: 35127) +OffRamp_executeSingleReport:test_EmptyReport_Revert() (gas: 23923) +OffRamp_executeSingleReport:test_InvalidSourcePoolAddress_Success() (gas: 486078) +OffRamp_executeSingleReport:test_ManualExecutionNotYetEnabled_Revert() (gas: 54457) +OffRamp_executeSingleReport:test_MismatchingDestChainSelector_Revert() (gas: 35905) +OffRamp_executeSingleReport:test_MismatchingOnRampRoot_Revert() (gas: 154471) +OffRamp_executeSingleReport:test_NonExistingSourceChain_Revert() (gas: 35338) +OffRamp_executeSingleReport:test_ReceiverError_Success() (gas: 184911) +OffRamp_executeSingleReport:test_RetryFailedMessageWithoutManualExecution_Revert() (gas: 196169) +OffRamp_executeSingleReport:test_RootNotCommitted_Revert() (gas: 48074) +OffRamp_executeSingleReport:test_RouterYULCall_Revert() (gas: 444732) +OffRamp_executeSingleReport:test_SingleMessageNoTokensOtherChain_Success() (gas: 250427) +OffRamp_executeSingleReport:test_SingleMessageNoTokensUnordered_Success() (gas: 187283) +OffRamp_executeSingleReport:test_SingleMessageNoTokens_Success() (gas: 206863) +OffRamp_executeSingleReport:test_SingleMessageToNonCCIPReceiver_Success() (gas: 263565) +OffRamp_executeSingleReport:test_SingleMessagesNoTokensSuccess_gas() (gas: 138454) +OffRamp_executeSingleReport:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 417627) +OffRamp_executeSingleReport:test_SkippedIncorrectNonce_Success() (gas: 65877) +OffRamp_executeSingleReport:test_TokenDataMismatch_Revert() (gas: 80910) +OffRamp_executeSingleReport:test_TwoMessagesWithTokensAndGE_Success() (gas: 576137) +OffRamp_executeSingleReport:test_TwoMessagesWithTokensSuccess_gas() (gas: 525167) +OffRamp_executeSingleReport:test_UnexpectedTokenData_Revert() (gas: 35743) +OffRamp_executeSingleReport:test_UnhealthySingleChainCurse_Revert() (gas: 531800) +OffRamp_executeSingleReport:test_Unhealthy_Revert() (gas: 529168) +OffRamp_executeSingleReport:test_WithCurseOnAnotherSourceChain_Success() (gas: 494410) +OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessageUnordered_Success() (gas: 133560) +OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessage_Success() (gas: 162760) +OffRamp_getExecutionState:test_FillExecutionState_Success() (gas: 3742124) +OffRamp_getExecutionState:test_GetDifferentChainExecutionState_Success() (gas: 118859) +OffRamp_getExecutionState:test_GetExecutionState_Success() (gas: 88048) +OffRamp_manuallyExecute:test_ManualExecGasLimitMismatchSingleReport_Revert() (gas: 75551) +OffRamp_manuallyExecute:test_ManualExecInvalidGasLimit_Revert() (gas: 26439) +OffRamp_manuallyExecute:test_manuallyExecute_DoesNotRevertIfUntouched_Success() (gas: 168628) +OffRamp_manuallyExecute:test_manuallyExecute_FailedTx_Revert() (gas: 205504) +OffRamp_manuallyExecute:test_manuallyExecute_ForkedChain_Revert() (gas: 25993) +OffRamp_manuallyExecute:test_manuallyExecute_GasLimitMismatchMultipleReports_Revert() (gas: 152822) +OffRamp_manuallyExecute:test_manuallyExecute_LowGasLimit_Success() (gas: 518556) +OffRamp_manuallyExecute:test_manuallyExecute_ReentrancyFails_Success() (gas: 2384534) +OffRamp_manuallyExecute:test_manuallyExecute_Success() (gas: 205857) +OffRamp_manuallyExecute:test_manuallyExecute_WithGasOverride_Success() (gas: 215965) +OffRamp_manuallyExecute:test_manuallyExecute_WithMultiReportGasOverride_Success() (gas: 649750) +OffRamp_manuallyExecute:test_manuallyExecute_WithPartialMessages_Success() (gas: 319062) +OffRamp_releaseOrMintTokens:test_TokenHandlingError_Reverts() (gas: 165822) +OffRamp_releaseOrMintTokens:test__releaseOrMintTokens_PoolIsNotAPool_Reverts() (gas: 24603) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_InvalidDataLengthReturnData_Revert() (gas: 66263) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_InvalidEVMAddress_Revert() (gas: 41294) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_PoolDoesNotSupportDest_Reverts() (gas: 83291) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_Success() (gas: 177934) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals_Success() (gas: 191136) +OffRamp_resetUnblessedRoots:test_OnlyOwner_Revert() (gas: 11423) +OffRamp_resetUnblessedRoots:test_ResetUnblessedRoots_Success() (gas: 215351) +OffRamp_setDynamicConfig:test_NonOwner_Revert() (gas: 14097) +OffRamp_setDynamicConfig:test_PriceRegistryZeroAddress_Revert() (gas: 11617) +OffRamp_setDynamicConfig:test_SetDynamicConfigWithValidator_Success() (gas: 49137) +OffRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 27081) +OffRamp_trialExecute:test_RateLimitError_Success() (gas: 225773) +OffRamp_trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 234394) +OffRamp_trialExecute:test_TokenPoolIsNotAContract_Success() (gas: 309206) +OffRamp_trialExecute:test_trialExecute_Success() (gas: 283972) +OffRamp_verify:test_Blessed_Success() (gas: 176664) +OffRamp_verify:test_NotBlessedWrongChainSelector_Success() (gas: 178732) +OffRamp_verify:test_NotBlessed_Success() (gas: 141593) OffRamp_verify:test_TooManyLeaves_Revert() (gas: 51510) -OnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 390322) +OnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 390336) OnRamp_applyDestChainConfigUpdates:test_ApplyDestChainConfigUpdates_Success() (gas: 63649) OnRamp_applyDestChainConfigUpdates:test_ApplyDestChainConfigUpdates_WithInalidChainSelector_Revert() (gas: 13308) -OnRamp_constructor:test_Constructor_InvalidConfigChainSelectorEqZero_Revert() (gas: 94175) -OnRamp_constructor:test_Constructor_InvalidConfigNonceManagerEqAddressZero_Revert() (gas: 92092) -OnRamp_constructor:test_Constructor_InvalidConfigRMNProxyEqAddressZero_Revert() (gas: 97113) -OnRamp_constructor:test_Constructor_InvalidConfigTokenAdminRegistryEqAddressZero_Revert() (gas: 92150) -OnRamp_constructor:test_Constructor_Success() (gas: 2384439) -OnRamp_forwardFromRouter:test_CannotSendZeroTokens_Revert() (gas: 71940) -OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() (gas: 112003) -OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2_Success() (gas: 142773) -OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessCustomExtraArgs() (gas: 142349) -OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessEmptyExtraArgs() (gas: 140526) -OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessLegacyExtraArgs() (gas: 142579) -OnRamp_forwardFromRouter:test_ForwardFromRouter_Success() (gas: 141948) -OnRamp_forwardFromRouter:test_ForwardFromRouter_Success_ConfigurableSourceRouter() (gas: 134391) -OnRamp_forwardFromRouter:test_InvalidExtraArgsTag_Revert() (gas: 26316) +OnRamp_constructor:test_Constructor_InvalidConfigChainSelectorEqZero_Revert() (gas: 94260) +OnRamp_constructor:test_Constructor_InvalidConfigNonceManagerEqAddressZero_Revert() (gas: 92177) +OnRamp_constructor:test_Constructor_InvalidConfigRMNProxyEqAddressZero_Revert() (gas: 97198) +OnRamp_constructor:test_Constructor_InvalidConfigTokenAdminRegistryEqAddressZero_Revert() (gas: 92235) +OnRamp_constructor:test_Constructor_Success() (gas: 2455004) +OnRamp_forwardFromRouter:test_CannotSendZeroTokens_Revert() (gas: 72010) +OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() (gas: 112791) +OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2_Success() (gas: 143561) +OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessCustomExtraArgs() (gas: 143137) +OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessEmptyExtraArgs() (gas: 141314) +OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessLegacyExtraArgs() (gas: 143367) +OnRamp_forwardFromRouter:test_ForwardFromRouter_Success() (gas: 142736) +OnRamp_forwardFromRouter:test_ForwardFromRouter_Success_ConfigurableSourceRouter() (gas: 135246) +OnRamp_forwardFromRouter:test_InvalidExtraArgsTag_Revert() (gas: 26349) OnRamp_forwardFromRouter:test_MessageValidationError_Revert() (gas: 133253) -OnRamp_forwardFromRouter:test_MesssageFeeTooHigh_Revert() (gas: 24382) +OnRamp_forwardFromRouter:test_MesssageFeeTooHigh_Revert() (gas: 24426) OnRamp_forwardFromRouter:test_OriginalSender_Revert() (gas: 12872) OnRamp_forwardFromRouter:test_Paused_Revert() (gas: 32033) OnRamp_forwardFromRouter:test_Permissions_Revert() (gas: 15762) -OnRamp_forwardFromRouter:test_ShouldIncrementNonceOnlyOnOrdered_Success() (gas: 179668) -OnRamp_forwardFromRouter:test_ShouldIncrementSeqNumAndNonce_Success() (gas: 205937) -OnRamp_forwardFromRouter:test_ShouldStoreLinkFees() (gas: 121859) -OnRamp_forwardFromRouter:test_ShouldStoreNonLinkFees() (gas: 143149) -OnRamp_forwardFromRouter:test_SourceTokenDataTooLarge_Revert() (gas: 3872828) -OnRamp_forwardFromRouter:test_UnsupportedToken_Revert() (gas: 108568) -OnRamp_forwardFromRouter:test_forwardFromRouter_UnsupportedToken_Revert() (gas: 73997) -OnRamp_forwardFromRouter:test_forwardFromRouter_WithValidation_Success() (gas: 262774) -OnRamp_getFee:test_EmptyMessage_Success() (gas: 104647) -OnRamp_getFee:test_EnforceOutOfOrder_Revert() (gas: 74120) -OnRamp_getFee:test_SingleTokenMessage_Success() (gas: 119979) +OnRamp_forwardFromRouter:test_ShouldIncrementNonceOnlyOnOrdered_Success() (gas: 182032) +OnRamp_forwardFromRouter:test_ShouldIncrementSeqNumAndNonce_Success() (gas: 208301) +OnRamp_forwardFromRouter:test_ShouldStoreLinkFees() (gas: 122714) +OnRamp_forwardFromRouter:test_ShouldStoreNonLinkFees() (gas: 144094) +OnRamp_forwardFromRouter:test_SourceTokenDataTooLarge_Revert() (gas: 3887491) +OnRamp_forwardFromRouter:test_UnsupportedToken_Revert() (gas: 108659) +OnRamp_forwardFromRouter:test_forwardFromRouter_UnsupportedToken_Revert() (gas: 74066) +OnRamp_forwardFromRouter:test_forwardFromRouter_WithValidation_Success() (gas: 273429) +OnRamp_getFee:test_EmptyMessage_Success() (gas: 104351) +OnRamp_getFee:test_EnforceOutOfOrder_Revert() (gas: 73173) +OnRamp_getFee:test_SingleTokenMessage_Success() (gas: 119675) OnRamp_getFee:test_Unhealthy_Revert() (gas: 43679) OnRamp_getSupportedTokens:test_GetSupportedTokens_Revert() (gas: 10438) OnRamp_getTokenPool:test_GetTokenPool_Success() (gas: 35270) @@ -661,117 +661,115 @@ OnRamp_setDynamicConfig:test_SetConfigInvalidConfigPriceRegistryEqAddressZero_Re OnRamp_setDynamicConfig:test_SetConfigInvalidConfig_Revert() (gas: 11112) OnRamp_setDynamicConfig:test_SetConfigOnlyOwner_Revert() (gas: 15939) OnRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 51996) -OnRamp_withdrawFeeTokens:test_WithdrawFeeTokens_Success() (gas: 97236) -PingPong_ccipReceive:test_CcipReceive_Success() (gas: 150175) +OnRamp_withdrawFeeTokens:test_WithdrawFeeTokens_Success() (gas: 97192) +PingPong_ccipReceive:test_CcipReceive_Success() (gas: 150169) PingPong_plumbing:test_OutOfOrderExecution_Success() (gas: 20277) PingPong_plumbing:test_Pausing_Success() (gas: 17777) -PingPong_startPingPong:test_StartPingPong_With_OOO_Success() (gas: 163199) -PingPong_startPingPong:test_StartPingPong_With_Sequenced_Ordered_Success() (gas: 182611) -PriceRegistry_applyDestChainConfigUpdates:test_InvalidChainFamilySelector_Revert() (gas: 16725) -PriceRegistry_applyDestChainConfigUpdates:test_InvalidDestBytesOverhead_Revert() (gas: 16816) -PriceRegistry_applyDestChainConfigUpdates:test_InvalidDestChainConfigDestChainSelectorEqZero_Revert() (gas: 16617) -PriceRegistry_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesDefaultTxGasLimitEqZero_Revert() (gas: 16681) -PriceRegistry_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesDefaultTxGasLimitGtMaxPerMessageGasLimit_Revert() (gas: 40971) -PriceRegistry_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesZeroIntput_Success() (gas: 12341) -PriceRegistry_applyDestChainConfigUpdates:test_applyDestChainConfigUpdates_Success() (gas: 139678) -PriceRegistry_applyFeeTokensUpdates:test_ApplyFeeTokensUpdates_Success() (gas: 80108) +PingPong_startPingPong:test_StartPingPong_With_OOO_Success() (gas: 163187) +PingPong_startPingPong:test_StartPingPong_With_Sequenced_Ordered_Success() (gas: 182599) +PriceRegistry_applyDestChainConfigUpdates:test_InvalidChainFamilySelector_Revert() (gas: 16503) +PriceRegistry_applyDestChainConfigUpdates:test_InvalidDestChainConfigDestChainSelectorEqZero_Revert() (gas: 16417) +PriceRegistry_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesDefaultTxGasLimitEqZero_Revert() (gas: 16459) +PriceRegistry_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesDefaultTxGasLimitGtMaxPerMessageGasLimit_Revert() (gas: 39957) +PriceRegistry_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesZeroIntput_Success() (gas: 12342) +PriceRegistry_applyDestChainConfigUpdates:test_applyDestChainConfigUpdates_Success() (gas: 135870) +PriceRegistry_applyFeeTokensUpdates:test_ApplyFeeTokensUpdates_Success() (gas: 79896) PriceRegistry_applyFeeTokensUpdates:test_OnlyCallableByOwner_Revert() (gas: 12603) -PriceRegistry_applyPremiumMultiplierWeiPerEthUpdates:test_OnlyCallableByOwnerOrAdmin_Revert() (gas: 11465) -PriceRegistry_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesMultipleTokens_Success() (gas: 54149) -PriceRegistry_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesSingleToken_Success() (gas: 44835) -PriceRegistry_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesZeroInput() (gas: 12301) +PriceRegistry_applyPremiumMultiplierWeiPerEthUpdates:test_OnlyCallableByOwnerOrAdmin_Revert() (gas: 11421) +PriceRegistry_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesMultipleTokens_Success() (gas: 54105) +PriceRegistry_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesSingleToken_Success() (gas: 44791) +PriceRegistry_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesZeroInput() (gas: 12257) PriceRegistry_applyTokenTransferFeeConfigUpdates:test_ApplyTokenTransferFeeConfig_Success() (gas: 86926) PriceRegistry_applyTokenTransferFeeConfigUpdates:test_ApplyTokenTransferFeeZeroInput() (gas: 13089) PriceRegistry_applyTokenTransferFeeConfigUpdates:test_InvalidDestBytesOverhead_Revert() (gas: 17071) PriceRegistry_applyTokenTransferFeeConfigUpdates:test_OnlyCallableByOwnerOrAdmin_Revert() (gas: 12240) -PriceRegistry_constructor:test_InvalidLinkTokenEqZeroAddress_Revert() (gas: 101316) -PriceRegistry_constructor:test_InvalidMaxFeeJuelsPerMsg_Revert() (gas: 105666) -PriceRegistry_constructor:test_InvalidStalenessThreshold_Revert() (gas: 105719) -PriceRegistry_constructor:test_Setup_Success() (gas: 5194297) -PriceRegistry_convertTokenAmount:test_ConvertTokenAmount_Success() (gas: 72751) -PriceRegistry_convertTokenAmount:test_LinkTokenNotSupported_Revert() (gas: 30981) -PriceRegistry_getDataAvailabilityCost:test_EmptyMessageCalculatesDataAvailabilityCost_Success() (gas: 95677) -PriceRegistry_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCostUnsupportedDestChainSelector_Success() (gas: 14636) -PriceRegistry_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCost_Success() (gas: 20659) -PriceRegistry_getTokenAndGasPrices:test_GetFeeTokenAndGasPrices_Success() (gas: 70449) +PriceRegistry_constructor:test_InvalidLinkTokenEqZeroAddress_Revert() (gas: 107016) +PriceRegistry_constructor:test_InvalidMaxFeeJuelsPerMsg_Revert() (gas: 111366) +PriceRegistry_constructor:test_InvalidStalenessThreshold_Revert() (gas: 111419) +PriceRegistry_constructor:test_Setup_Success() (gas: 5336824) +PriceRegistry_convertTokenAmount:test_ConvertTokenAmount_Success() (gas: 72739) +PriceRegistry_convertTokenAmount:test_LinkTokenNotSupported_Revert() (gas: 30963) +PriceRegistry_getDataAvailabilityCost:test_EmptyMessageCalculatesDataAvailabilityCost_Success() (gas: 94303) +PriceRegistry_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCostUnsupportedDestChainSelector_Success() (gas: 14614) +PriceRegistry_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCost_Success() (gas: 20410) +PriceRegistry_getTokenAndGasPrices:test_GetFeeTokenAndGasPrices_Success() (gas: 70443) PriceRegistry_getTokenAndGasPrices:test_StaleGasPrice_Revert() (gas: 16838) PriceRegistry_getTokenAndGasPrices:test_UnsupportedChain_Revert() (gas: 16140) -PriceRegistry_getTokenAndGasPrices:test_ZeroGasPrice_Success() (gas: 45734) -PriceRegistry_getTokenPrice:test_GetTokenPriceFromFeed_Success() (gas: 62308) -PriceRegistry_getTokenPrices:test_GetTokenPrices_Success() (gas: 84796) -PriceRegistry_getTokenTransferCost:test_CustomTokenBpsFee_Success() (gas: 41277) -PriceRegistry_getTokenTransferCost:test_FeeTokenBpsFee_Success() (gas: 34727) -PriceRegistry_getTokenTransferCost:test_LargeTokenTransferChargesMaxFeeAndGas_Success() (gas: 27801) -PriceRegistry_getTokenTransferCost:test_MixedTokenTransferFee_Success() (gas: 101840) -PriceRegistry_getTokenTransferCost:test_NoTokenTransferChargesZeroFee_Success() (gas: 20398) -PriceRegistry_getTokenTransferCost:test_SmallTokenTransferChargesMinFeeAndGas_Success() (gas: 27676) -PriceRegistry_getTokenTransferCost:test_ZeroAmountTokenTransferChargesMinFeeAndGas_Success() (gas: 27632) -PriceRegistry_getTokenTransferCost:test_ZeroFeeConfigChargesMinFee_Success() (gas: 40058) -PriceRegistry_getTokenTransferCost:test_getTokenTransferCost_selfServeUsesDefaults_Success() (gas: 29359) -PriceRegistry_getValidatedFee:test_DestinationChainNotEnabled_Revert() (gas: 18248) -PriceRegistry_getValidatedFee:test_EmptyMessage_Success() (gas: 81644) -PriceRegistry_getValidatedFee:test_EnforceOutOfOrder_Revert() (gas: 55241) -PriceRegistry_getValidatedFee:test_HighGasMessage_Success() (gas: 238106) -PriceRegistry_getValidatedFee:test_InvalidEVMAddress_Revert() (gas: 20016) -PriceRegistry_getValidatedFee:test_MessageGasLimitTooHigh_Revert() (gas: 31820) -PriceRegistry_getValidatedFee:test_MessageTooLarge_Revert() (gas: 97759) -PriceRegistry_getValidatedFee:test_MessageWithDataAndTokenTransfer_Success() (gas: 143549) -PriceRegistry_getValidatedFee:test_NotAFeeToken_Revert() (gas: 29480) -PriceRegistry_getValidatedFee:test_SingleTokenMessage_Success() (gas: 112551) -PriceRegistry_getValidatedFee:test_TooManyTokens_Revert() (gas: 20152) -PriceRegistry_getValidatedFee:test_ZeroDataAvailabilityMultiplier_Success() (gas: 63052) -PriceRegistry_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Above18Decimals_Success() (gas: 2094595) -PriceRegistry_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Below18Decimals_Success() (gas: 2094553) -PriceRegistry_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt0Decimals_Success() (gas: 2074672) -PriceRegistry_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt18Decimals_Success() (gas: 2094327) -PriceRegistry_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFlippedDecimals_Success() (gas: 2094531) -PriceRegistry_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedMaxInt224Value_Success() (gas: 2094343) -PriceRegistry_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedOverStalenessPeriod_Success() (gas: 62060) -PriceRegistry_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeed_Success() (gas: 61940) -PriceRegistry_getValidatedTokenPrice:test_GetValidatedTokenPrice_Success() (gas: 61020) -PriceRegistry_getValidatedTokenPrice:test_OverflowFeedPrice_Revert() (gas: 2094030) -PriceRegistry_getValidatedTokenPrice:test_StaleFeeToken_Success() (gas: 61547) -PriceRegistry_getValidatedTokenPrice:test_TokenNotSupportedFeed_Revert() (gas: 109176) -PriceRegistry_getValidatedTokenPrice:test_TokenNotSupported_Revert() (gas: 13841) -PriceRegistry_getValidatedTokenPrice:test_UnderflowFeedPrice_Revert() (gas: 2092692) -PriceRegistry_onReport:test_OnReport_StaleUpdate_Revert() (gas: 43415) +PriceRegistry_getTokenAndGasPrices:test_ZeroGasPrice_Success() (gas: 45750) +PriceRegistry_getTokenPrice:test_GetTokenPriceFromFeed_Success() (gas: 62252) +PriceRegistry_getTokenPrices:test_GetTokenPrices_Success() (gas: 84800) +PriceRegistry_getTokenTransferCost:test_CustomTokenBpsFee_Success() (gas: 41227) +PriceRegistry_getTokenTransferCost:test_FeeTokenBpsFee_Success() (gas: 34682) +PriceRegistry_getTokenTransferCost:test_LargeTokenTransferChargesMaxFeeAndGas_Success() (gas: 27756) +PriceRegistry_getTokenTransferCost:test_MixedTokenTransferFee_Success() (gas: 101624) +PriceRegistry_getTokenTransferCost:test_NoTokenTransferChargesZeroFee_Success() (gas: 20354) +PriceRegistry_getTokenTransferCost:test_SmallTokenTransferChargesMinFeeAndGas_Success() (gas: 27631) +PriceRegistry_getTokenTransferCost:test_ZeroAmountTokenTransferChargesMinFeeAndGas_Success() (gas: 27587) +PriceRegistry_getTokenTransferCost:test_ZeroFeeConfigChargesMinFee_Success() (gas: 40013) +PriceRegistry_getTokenTransferCost:test_getTokenTransferCost_selfServeUsesDefaults_Success() (gas: 29299) +PriceRegistry_getValidatedFee:test_DestinationChainNotEnabled_Revert() (gas: 18180) +PriceRegistry_getValidatedFee:test_EmptyMessage_Success() (gas: 81054) +PriceRegistry_getValidatedFee:test_EnforceOutOfOrder_Revert() (gas: 54294) +PriceRegistry_getValidatedFee:test_HighGasMessage_Success() (gas: 237472) +PriceRegistry_getValidatedFee:test_InvalidEVMAddress_Revert() (gas: 19949) +PriceRegistry_getValidatedFee:test_MessageGasLimitTooHigh_Revert() (gas: 31746) +PriceRegistry_getValidatedFee:test_MessageTooLarge_Revert() (gas: 97692) +PriceRegistry_getValidatedFee:test_MessageWithDataAndTokenTransfer_Success() (gas: 142833) +PriceRegistry_getValidatedFee:test_NotAFeeToken_Revert() (gas: 29407) +PriceRegistry_getValidatedFee:test_SingleTokenMessage_Success() (gas: 111861) +PriceRegistry_getValidatedFee:test_TooManyTokens_Revert() (gas: 20085) +PriceRegistry_getValidatedFee:test_ZeroDataAvailabilityMultiplier_Success() (gas: 61933) +PriceRegistry_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Above18Decimals_Success() (gas: 2094539) +PriceRegistry_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Below18Decimals_Success() (gas: 2094497) +PriceRegistry_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt0Decimals_Success() (gas: 2074616) +PriceRegistry_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt18Decimals_Success() (gas: 2094271) +PriceRegistry_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFlippedDecimals_Success() (gas: 2094475) +PriceRegistry_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedMaxInt224Value_Success() (gas: 2094287) +PriceRegistry_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedOverStalenessPeriod_Success() (gas: 62004) +PriceRegistry_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeed_Success() (gas: 61884) +PriceRegistry_getValidatedTokenPrice:test_GetValidatedTokenPrice_Success() (gas: 61036) +PriceRegistry_getValidatedTokenPrice:test_OverflowFeedPrice_Revert() (gas: 2093974) +PriceRegistry_getValidatedTokenPrice:test_StaleFeeToken_Success() (gas: 61563) +PriceRegistry_getValidatedTokenPrice:test_TokenNotSupportedFeed_Revert() (gas: 109120) +PriceRegistry_getValidatedTokenPrice:test_TokenNotSupported_Revert() (gas: 13857) +PriceRegistry_getValidatedTokenPrice:test_UnderflowFeedPrice_Revert() (gas: 2092636) +PriceRegistry_onReport:test_OnReport_StaleUpdate_Revert() (gas: 43359) PriceRegistry_onReport:test_onReport_InvalidForwarder_Reverts() (gas: 23261) -PriceRegistry_onReport:test_onReport_Success() (gas: 80702) -PriceRegistry_onReport:test_onReport_UnsupportedToken_Reverts() (gas: 26681) -PriceRegistry_parseEVMExtraArgsFromBytes:test_EVMExtraArgsDefault_Success() (gas: 17316) -PriceRegistry_parseEVMExtraArgsFromBytes:test_EVMExtraArgsEnforceOutOfOrder_Revert() (gas: 21410) -PriceRegistry_parseEVMExtraArgsFromBytes:test_EVMExtraArgsGasLimitTooHigh_Revert() (gas: 18507) -PriceRegistry_parseEVMExtraArgsFromBytes:test_EVMExtraArgsInvalidExtraArgsTag_Revert() (gas: 18031) -PriceRegistry_parseEVMExtraArgsFromBytes:test_EVMExtraArgsV1_Success() (gas: 18408) -PriceRegistry_parseEVMExtraArgsFromBytes:test_EVMExtraArgsV2_Success() (gas: 18525) -PriceRegistry_processMessageArgs:test_InvalidExtraArgs_Revert() (gas: 18328) -PriceRegistry_processMessageArgs:test_MalformedEVMExtraArgs_Revert() (gas: 18874) -PriceRegistry_processMessageArgs:test_MessageFeeTooHigh_Revert() (gas: 16382) -PriceRegistry_processMessageArgs:test_WitEVMExtraArgsV2_Success() (gas: 26303) -PriceRegistry_processMessageArgs:test_WithConvertedTokenAmount_Success() (gas: 32432) -PriceRegistry_processMessageArgs:test_WithEVMExtraArgsV1_Success() (gas: 25915) -PriceRegistry_processMessageArgs:test_WithEmptyEVMExtraArgs_Success() (gas: 23730) -PriceRegistry_processMessageArgs:test_WithLinkTokenAmount_Success() (gas: 17342) -PriceRegistry_updatePrices:test_OnlyCallableByUpdater_Revert() (gas: 12080) -PriceRegistry_updatePrices:test_OnlyGasPrice_Success() (gas: 23621) -PriceRegistry_updatePrices:test_OnlyTokenPrice_Success() (gas: 30593) -PriceRegistry_updatePrices:test_UpdatableByAuthorizedCaller_Success() (gas: 75937) -PriceRegistry_updatePrices:test_UpdateMultiplePrices_Success() (gas: 151455) -PriceRegistry_updateTokenPriceFeeds:test_FeedNotUpdated() (gas: 50633) -PriceRegistry_updateTokenPriceFeeds:test_FeedUnset_Success() (gas: 63662) -PriceRegistry_updateTokenPriceFeeds:test_FeedUpdatedByNonOwner_Revert() (gas: 19998) -PriceRegistry_updateTokenPriceFeeds:test_MultipleFeedUpdate_Success() (gas: 88898) -PriceRegistry_updateTokenPriceFeeds:test_SingleFeedUpdate_Success() (gas: 50817) -PriceRegistry_updateTokenPriceFeeds:test_ZeroFeeds_Success() (gas: 12362) -PriceRegistry_validateDestFamilyAddress:test_InvalidEVMAddressEncodePacked_Revert() (gas: 10572) -PriceRegistry_validateDestFamilyAddress:test_InvalidEVMAddressPrecompiles_Revert() (gas: 3916546) -PriceRegistry_validateDestFamilyAddress:test_InvalidEVMAddress_Revert() (gas: 10756) -PriceRegistry_validateDestFamilyAddress:test_ValidEVMAddress_Success() (gas: 6660) -PriceRegistry_validateDestFamilyAddress:test_ValidNonEVMAddress_Success() (gas: 6440) -PriceRegistry_validatePoolReturnData:test_InvalidEVMAddressDestToken_Revert() (gas: 35479) -PriceRegistry_validatePoolReturnData:test_SourceTokenDataTooLarge_Revert() (gas: 90819) -PriceRegistry_validatePoolReturnData:test_TokenAmountArraysMismatching_Revert() (gas: 32771) -PriceRegistry_validatePoolReturnData:test_WithSingleToken_Success() (gas: 31315) +PriceRegistry_onReport:test_onReport_Success() (gas: 80666) +PriceRegistry_onReport:test_onReport_UnsupportedToken_Reverts() (gas: 26675) +PriceRegistry_parseEVMExtraArgsFromBytes:test_EVMExtraArgsDefault_Success() (gas: 17185) +PriceRegistry_parseEVMExtraArgsFromBytes:test_EVMExtraArgsEnforceOutOfOrder_Revert() (gas: 21290) +PriceRegistry_parseEVMExtraArgsFromBytes:test_EVMExtraArgsGasLimitTooHigh_Revert() (gas: 18387) +PriceRegistry_parseEVMExtraArgsFromBytes:test_EVMExtraArgsInvalidExtraArgsTag_Revert() (gas: 17911) +PriceRegistry_parseEVMExtraArgsFromBytes:test_EVMExtraArgsV1_Success() (gas: 18285) +PriceRegistry_parseEVMExtraArgsFromBytes:test_EVMExtraArgsV2_Success() (gas: 18401) +PriceRegistry_processMessageArgs:test_InvalidExtraArgs_Revert() (gas: 18361) +PriceRegistry_processMessageArgs:test_MalformedEVMExtraArgs_Revert() (gas: 18907) +PriceRegistry_processMessageArgs:test_MessageFeeTooHigh_Revert() (gas: 16426) +PriceRegistry_processMessageArgs:test_WitEVMExtraArgsV2_Success() (gas: 26269) +PriceRegistry_processMessageArgs:test_WithConvertedTokenAmount_Success() (gas: 32441) +PriceRegistry_processMessageArgs:test_WithEVMExtraArgsV1_Success() (gas: 25881) +PriceRegistry_processMessageArgs:test_WithEmptyEVMExtraArgs_Success() (gas: 23696) +PriceRegistry_processMessageArgs:test_WithLinkTokenAmount_Success() (gas: 17375) +PriceRegistry_processPoolReturnData:test_InvalidEVMAddressDestToken_Revert() (gas: 42784) +PriceRegistry_processPoolReturnData:test_SourceTokenDataTooLarge_Revert() (gas: 107735) +PriceRegistry_processPoolReturnData:test_TokenAmountArraysMismatching_Revert() (gas: 40104) +PriceRegistry_updatePrices:test_OnlyCallableByUpdater_Revert() (gas: 12102) +PriceRegistry_updatePrices:test_OnlyGasPrice_Success() (gas: 23599) +PriceRegistry_updatePrices:test_OnlyTokenPrice_Success() (gas: 30631) +PriceRegistry_updatePrices:test_UpdatableByAuthorizedCaller_Success() (gas: 76003) +PriceRegistry_updatePrices:test_UpdateMultiplePrices_Success() (gas: 151393) +PriceRegistry_updateTokenPriceFeeds:test_FeedNotUpdated() (gas: 50527) +PriceRegistry_updateTokenPriceFeeds:test_FeedUnset_Success() (gas: 63626) +PriceRegistry_updateTokenPriceFeeds:test_FeedUpdatedByNonOwner_Revert() (gas: 19932) +PriceRegistry_updateTokenPriceFeeds:test_MultipleFeedUpdate_Success() (gas: 88972) +PriceRegistry_updateTokenPriceFeeds:test_SingleFeedUpdate_Success() (gas: 50821) +PriceRegistry_updateTokenPriceFeeds:test_ZeroFeeds_Success() (gas: 12296) +PriceRegistry_validateDestFamilyAddress:test_InvalidEVMAddressEncodePacked_Revert() (gas: 10616) +PriceRegistry_validateDestFamilyAddress:test_InvalidEVMAddressPrecompiles_Revert() (gas: 3961646) +PriceRegistry_validateDestFamilyAddress:test_InvalidEVMAddress_Revert() (gas: 10800) +PriceRegistry_validateDestFamilyAddress:test_ValidEVMAddress_Success() (gas: 6704) +PriceRegistry_validateDestFamilyAddress:test_ValidNonEVMAddress_Success() (gas: 6484) RMNHome:test() (gas: 186) RMN_constructor:test_Constructor_Success() (gas: 48838) RMN_getRecordedCurseRelatedOps:test_OpsPostDeployment() (gas: 19666) @@ -852,24 +850,24 @@ Router_applyRampUpdates:test_OffRampMismatch_Revert() (gas: 89288) Router_applyRampUpdates:test_OffRampUpdatesWithRouting() (gas: 10642128) Router_applyRampUpdates:test_OnRampDisable() (gas: 55913) Router_applyRampUpdates:test_OnlyOwner_Revert() (gas: 12311) -Router_ccipSend:test_CCIPSendLinkFeeNoTokenSuccess_gas() (gas: 113886) -Router_ccipSend:test_CCIPSendLinkFeeOneTokenSuccess_gas() (gas: 201342) -Router_ccipSend:test_CCIPSendNativeFeeNoTokenSuccess_gas() (gas: 128533) -Router_ccipSend:test_CCIPSendNativeFeeOneTokenSuccess_gas() (gas: 215991) -Router_ccipSend:test_FeeTokenAmountTooLow_Revert() (gas: 66275) +Router_ccipSend:test_CCIPSendLinkFeeNoTokenSuccess_gas() (gas: 113880) +Router_ccipSend:test_CCIPSendLinkFeeOneTokenSuccess_gas() (gas: 201336) +Router_ccipSend:test_CCIPSendNativeFeeNoTokenSuccess_gas() (gas: 128515) +Router_ccipSend:test_CCIPSendNativeFeeOneTokenSuccess_gas() (gas: 215973) +Router_ccipSend:test_FeeTokenAmountTooLow_Revert() (gas: 66269) Router_ccipSend:test_InvalidMsgValue() (gas: 31963) -Router_ccipSend:test_NativeFeeTokenInsufficientValue() (gas: 68746) -Router_ccipSend:test_NativeFeeTokenOverpay_Success() (gas: 173630) -Router_ccipSend:test_NativeFeeTokenZeroValue() (gas: 56037) -Router_ccipSend:test_NativeFeeToken_Success() (gas: 172224) -Router_ccipSend:test_NonLinkFeeToken_Success() (gas: 242732) +Router_ccipSend:test_NativeFeeTokenInsufficientValue() (gas: 68740) +Router_ccipSend:test_NativeFeeTokenOverpay_Success() (gas: 173606) +Router_ccipSend:test_NativeFeeTokenZeroValue() (gas: 56031) +Router_ccipSend:test_NativeFeeToken_Success() (gas: 172200) +Router_ccipSend:test_NonLinkFeeToken_Success() (gas: 242714) Router_ccipSend:test_UnsupportedDestinationChain_Revert() (gas: 24749) Router_ccipSend:test_WhenNotHealthy_Revert() (gas: 44724) -Router_ccipSend:test_WrappedNativeFeeToken_Success() (gas: 174440) -Router_ccipSend:test_ZeroFeeAndGasPrice_Success() (gas: 244856) +Router_ccipSend:test_WrappedNativeFeeToken_Success() (gas: 174416) +Router_ccipSend:test_ZeroFeeAndGasPrice_Success() (gas: 244854) Router_constructor:test_Constructor_Success() (gas: 13074) Router_getArmProxy:test_getArmProxy() (gas: 10561) -Router_getFee:test_GetFeeSupportedChain_Success() (gas: 46464) +Router_getFee:test_GetFeeSupportedChain_Success() (gas: 46458) Router_getFee:test_UnsupportedDestinationChain_Revert() (gas: 17138) Router_getSupportedTokens:test_GetSupportedTokens_Revert() (gas: 10460) Router_recoverTokens:test_RecoverTokensInvalidRecipient_Revert() (gas: 11316) @@ -884,7 +882,7 @@ Router_routeMessage:test_OnlyOffRamp_Revert() (gas: 25116) Router_routeMessage:test_WhenNotHealthy_Revert() (gas: 44724) Router_setWrappedNative:test_OnlyOwner_Revert() (gas: 10985) SelfFundedPingPong_ccipReceive:test_FundingIfNotANop_Revert() (gas: 53531) -SelfFundedPingPong_ccipReceive:test_Funding_Success() (gas: 417002) +SelfFundedPingPong_ccipReceive:test_Funding_Success() (gas: 416966) SelfFundedPingPong_setCountIncrBeforeFunding:test_setCountIncrBeforeFunding() (gas: 20151) TokenAdminRegistry_acceptAdminRole:test_acceptAdminRole_OnlyPendingAdministrator_Revert() (gas: 51085) TokenAdminRegistry_acceptAdminRole:test_acceptAdminRole_Success() (gas: 43947) @@ -912,8 +910,8 @@ TokenPoolAndProxy:test_lockOrBurn_burnMint_Success() (gas: 6070353) TokenPoolAndProxy:test_lockOrBurn_burnWithFromMint_Success() (gas: 6101826) TokenPoolAndProxy:test_lockOrBurn_lockRelease_Success() (gas: 6319594) TokenPoolAndProxy:test_setPreviousPool_Success() (gas: 3387124) -TokenPoolAndProxyMigration:test_tokenPoolMigration_Success_1_2() (gas: 6913796) -TokenPoolAndProxyMigration:test_tokenPoolMigration_Success_1_4() (gas: 7097821) +TokenPoolAndProxyMigration:test_tokenPoolMigration_Success_1_2() (gas: 6913778) +TokenPoolAndProxyMigration:test_tokenPoolMigration_Success_1_4() (gas: 7097803) TokenPoolWithAllowList_applyAllowListUpdates:test_AllowListNotEnabled_Revert() (gas: 2209837) TokenPoolWithAllowList_applyAllowListUpdates:test_OnlyOwner_Revert() (gas: 12089) TokenPoolWithAllowList_applyAllowListUpdates:test_SetAllowListSkipsZero_Success() (gas: 23324) @@ -942,16 +940,16 @@ TokenPool_setRemotePool:test_setRemotePool_NonExistentChain_Reverts() (gas: 1562 TokenPool_setRemotePool:test_setRemotePool_OnlyOwner_Reverts() (gas: 13195) TokenPool_setRemotePool:test_setRemotePool_Success() (gas: 281912) TokenProxy_ccipSend:test_CcipSendGasShouldBeZero_Revert() (gas: 17109) -TokenProxy_ccipSend:test_CcipSendInsufficientAllowance_Revert() (gas: 136228) +TokenProxy_ccipSend:test_CcipSendInsufficientAllowance_Revert() (gas: 136222) TokenProxy_ccipSend:test_CcipSendInvalidToken_Revert() (gas: 15919) -TokenProxy_ccipSend:test_CcipSendNative_Success() (gas: 245191) +TokenProxy_ccipSend:test_CcipSendNative_Success() (gas: 245173) TokenProxy_ccipSend:test_CcipSendNoDataAllowed_Revert() (gas: 16303) -TokenProxy_ccipSend:test_CcipSend_Success() (gas: 261568) +TokenProxy_ccipSend:test_CcipSend_Success() (gas: 261558) TokenProxy_constructor:test_Constructor() (gas: 13812) TokenProxy_getFee:test_GetFeeGasShouldBeZero_Revert() (gas: 16827) TokenProxy_getFee:test_GetFeeInvalidToken_Revert() (gas: 12658) TokenProxy_getFee:test_GetFeeNoDataAllowed_Revert() (gas: 15849) -TokenProxy_getFee:test_GetFee_Success() (gas: 86702) +TokenProxy_getFee:test_GetFee_Success() (gas: 86690) USDCTokenPool__validateMessage:test_ValidateInvalidMessage_Revert() (gas: 25290) USDCTokenPool_lockOrBurn:test_CallerIsNotARampOnRouter_Revert() (gas: 35322) USDCTokenPool_lockOrBurn:test_LockOrBurnWithAllowList_Revert() (gas: 30073) diff --git a/contracts/src/v0.8/ccip/PriceRegistry.sol b/contracts/src/v0.8/ccip/PriceRegistry.sol index f9989f9363..8593568371 100644 --- a/contracts/src/v0.8/ccip/PriceRegistry.sol +++ b/contracts/src/v0.8/ccip/PriceRegistry.sol @@ -98,8 +98,7 @@ contract PriceRegistry is // The following three properties are defaults, they can be overridden by setting the TokenTransferFeeConfig for a token uint16 defaultTokenFeeUSDCents; // │ Default token fee charged per token transfer uint32 defaultTokenDestGasOverhead; // ──────╯ Default gas charged to execute the token transfer on the destination chain - uint32 defaultTokenDestBytesOverhead; // ────╮ Default extra data availability bytes charged per token transfer - uint32 defaultTxGasLimit; // │ Default gas limit for a tx + uint32 defaultTxGasLimit; //─────────────────╮ Default gas limit for a tx uint64 gasMultiplierWeiPerEth; // │ Multiplier for gas costs, 1e18 based so 11e17 = 10% extra cost. uint32 networkFeeUSDCents; // │ Flat network fee to charge for messages, multiples of 0.01 USD bool enforceOutOfOrder; // │ Whether to enforce the allowOutOfOrderExecution extraArg value to be true. @@ -601,7 +600,7 @@ contract PriceRegistry is if (!transferFeeConfig.isEnabled) { tokenTransferFeeUSDWei += uint256(destChainConfig.defaultTokenFeeUSDCents) * 1e16; tokenTransferGas += destChainConfig.defaultTokenDestGasOverhead; - tokenTransferBytesOverhead += destChainConfig.defaultTokenDestBytesOverhead; + tokenTransferBytesOverhead += Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES; continue; } @@ -867,13 +866,13 @@ contract PriceRegistry is /// @inheritdoc IPriceRegistry /// @dev precondition - rampTokenAmounts and sourceTokenAmounts lengths must be equal - function validatePoolReturnData( + function processPoolReturnData( uint64 destChainSelector, Internal.RampTokenAmount[] calldata rampTokenAmounts, Client.EVMTokenAmount[] calldata sourceTokenAmounts - ) external view { + ) external view returns (bytes[] memory destExecDataPerToken) { bytes4 chainFamilySelector = s_destChainConfigs[destChainSelector].chainFamilySelector; - + destExecDataPerToken = new bytes[](rampTokenAmounts.length); for (uint256 i = 0; i < rampTokenAmounts.length; ++i) { address sourceToken = sourceTokenAmounts[i].token; @@ -888,7 +887,18 @@ contract PriceRegistry is } _validateDestFamilyAddress(chainFamilySelector, rampTokenAmounts[i].destTokenAddress); + PriceRegistry.TokenTransferFeeConfig memory tokenTransferFeeConfig = + s_tokenTransferFeeConfig[destChainSelector][sourceToken]; + uint32 defaultGasOverhead = s_destChainConfigs[destChainSelector].defaultTokenDestGasOverhead; + // NOTE: Revisit this when adding new non-EVM chain family selector support + uint32 destGasAmount = + tokenTransferFeeConfig.isEnabled ? tokenTransferFeeConfig.destGasOverhead : defaultGasOverhead; + + // The user will be billed either the default or the override, so we send the exact amount that we billed for + // to the destination chain to be used for the token releaseOrMint and transfer. + destExecDataPerToken[i] = abi.encode(destGasAmount); } + return destExecDataPerToken; } // ================================================================ @@ -919,7 +929,6 @@ contract PriceRegistry is if ( destChainSelector == 0 || destChainConfig.defaultTxGasLimit == 0 || destChainConfig.chainFamilySelector != Internal.CHAIN_FAMILY_SELECTOR_EVM - || destChainConfig.defaultTokenDestBytesOverhead < Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES || destChainConfig.defaultTxGasLimit > destChainConfig.maxPerMsgGasLimit ) { revert InvalidDestChainConfig(destChainSelector); diff --git a/contracts/src/v0.8/ccip/interfaces/IPriceRegistry.sol b/contracts/src/v0.8/ccip/interfaces/IPriceRegistry.sol index a29db78e04..05d68b3183 100644 --- a/contracts/src/v0.8/ccip/interfaces/IPriceRegistry.sol +++ b/contracts/src/v0.8/ccip/interfaces/IPriceRegistry.sol @@ -101,9 +101,10 @@ interface IPriceRegistry { /// @param destChainSelector Destination chain selector to which the token amounts are sent to /// @param rampTokenAmounts Token amounts with populated pool return data /// @param sourceTokenAmounts Token amounts originally sent in a Client.EVM2AnyMessage message - function validatePoolReturnData( + /// @return destExecData Destination chain execution data + function processPoolReturnData( uint64 destChainSelector, - Internal.RampTokenAmount[] calldata rampTokenAmounts, + Internal.RampTokenAmount[] memory rampTokenAmounts, Client.EVMTokenAmount[] calldata sourceTokenAmounts - ) external view; + ) external view returns (bytes[] memory); } diff --git a/contracts/src/v0.8/ccip/libraries/Internal.sol b/contracts/src/v0.8/ccip/libraries/Internal.sol index bd1ee48d9a..9b251eedcf 100644 --- a/contracts/src/v0.8/ccip/libraries/Internal.sol +++ b/contracts/src/v0.8/ccip/libraries/Internal.sol @@ -140,10 +140,11 @@ library Internal { uint256 public constant ANY_2_EVM_MESSAGE_FIXED_BYTES = 32 * 14; /// @dev Each token transfer adds 1 RampTokenAmount - /// RampTokenAmount has 4 fields, including 3 bytes. - /// Each bytes takes 1 more slot to store its length, and one slot to store the offset. - /// When abi encoded, each token transfer takes up 10 slots, excl bytes contents. - uint256 public constant ANY_2_EVM_MESSAGE_FIXED_BYTES_PER_TOKEN = 32 * 10; + /// RampTokenAmount has 5 fields, 3 of which are bytes type, 1 uint256 and 1 uint32. + /// Each bytes type takes 1 slot for length, 1 slot for data and 1 slot for the offset. + /// uint256 amount takes 1 slot. + /// uint32 destGasAmount takes 1 slot. + uint256 public constant ANY_2_EVM_MESSAGE_FIXED_BYTES_PER_TOKEN = 32 * ((3 * 3) + 2); bytes32 internal constant EVM_2_EVM_MESSAGE_HASH = keccak256("EVM2EVMMessageHashV2"); @@ -294,6 +295,9 @@ library Internal { // has to be set for the specific token. bytes extraData; uint256 amount; // Amount of tokens. + // Destination chain specific execution data encoded in bytes + //(for EVM destination it consists of the amount of gas available for the releaseOrMint and transfer calls on the offRamp + bytes destExecData; } /// @notice Family-agnostic header for OnRamp & OffRamp messages. diff --git a/contracts/src/v0.8/ccip/onRamp/OnRamp.sol b/contracts/src/v0.8/ccip/onRamp/OnRamp.sol index dc25354668..6de57bf548 100644 --- a/contracts/src/v0.8/ccip/onRamp/OnRamp.sol +++ b/contracts/src/v0.8/ccip/onRamp/OnRamp.sol @@ -191,10 +191,14 @@ contract OnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCreator { } // Validate pool return data after it is populated (view function - no state changes) - IPriceRegistry(s_dynamicConfig.priceRegistry).validatePoolReturnData( + bytes[] memory destExecDataPerToken = IPriceRegistry(s_dynamicConfig.priceRegistry).processPoolReturnData( destChainSelector, newMessage.tokenAmounts, message.tokenAmounts ); + for (uint256 i = 0; i < newMessage.tokenAmounts.length; ++i) { + newMessage.tokenAmounts[i].destExecData = destExecDataPerToken[i]; + } + // Override extraArgs with latest version newMessage.extraArgs = convertedExtraArgs; @@ -251,7 +255,8 @@ contract OnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCreator { sourcePoolAddress: abi.encode(sourcePool), destTokenAddress: poolReturnData.destTokenAddress, extraData: poolReturnData.destPoolData, - amount: tokenAndAmount.amount + amount: tokenAndAmount.amount, + destExecData: "" // This is set in the processPoolReturnData function }); } diff --git a/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol index 70e5689679..04c7b0b63b 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol @@ -1307,12 +1307,12 @@ contract OffRamp_manuallyExecute is OffRampSetup { s_offRamp.batchExecute(_generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[][](1)); s_reverting_receiver.setRevert(false); + uint256[][] memory gasLimitOverrides = new uint256[][](1); gasLimitOverrides[0] = _getGasLimitsFromMessages(messages); gasLimitOverrides[0][0] += 1; - + vm.recordLogs(); s_offRamp.manuallyExecute(_generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), gasLimitOverrides); - assertExecutionStateChangedEventLogs( SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber, @@ -1664,7 +1664,8 @@ contract OffRamp_manuallyExecute is OffRampSetup { sourcePoolAddress: abi.encode(s_sourcePoolByToken[s_sourceFeeToken]), destTokenAddress: abi.encode(s_destTokenBySourceToken[s_sourceFeeToken]), extraData: "", - amount: tokenAmount + amount: tokenAmount, + destExecData: abi.encode(DEFAULT_TOKEN_DEST_GAS_OVERHEAD) }); messages[0].receiver = address(receiver); @@ -2216,7 +2217,8 @@ contract OffRamp_trialExecute is OffRampSetup { sourcePoolAddress: abi.encode(address(0)), destTokenAddress: abi.encode(address(0)), extraData: "", - amount: message.tokenAmounts[0].amount + amount: message.tokenAmounts[0].amount, + destExecData: abi.encode(DEFAULT_TOKEN_DEST_GAS_OVERHEAD) }); message.header.messageId = Internal._hash(message, ON_RAMP_ADDRESS_1); @@ -2233,7 +2235,8 @@ contract OffRamp_trialExecute is OffRampSetup { sourcePoolAddress: abi.encode(address(0)), destTokenAddress: abi.encode(notAContract), extraData: "", - amount: message.tokenAmounts[0].amount + amount: message.tokenAmounts[0].amount, + destExecData: abi.encode(DEFAULT_TOKEN_DEST_GAS_OVERHEAD) }); message.header.messageId = Internal._hash(message, ON_RAMP_ADDRESS_1); @@ -2264,7 +2267,8 @@ contract OffRamp__releaseOrMintSingleToken is OffRampSetup { sourcePoolAddress: abi.encode(s_sourcePoolByToken[token]), destTokenAddress: abi.encode(s_destTokenBySourceToken[token]), extraData: "", - amount: amount + amount: amount, + destExecData: abi.encode(DEFAULT_TOKEN_DEST_GAS_OVERHEAD) }); vm.expectCall( @@ -2297,7 +2301,8 @@ contract OffRamp__releaseOrMintSingleToken is OffRampSetup { sourcePoolAddress: abi.encode(s_sourcePoolByToken[token]), destTokenAddress: abi.encode(s_destTokenBySourceToken[token]), extraData: "", - amount: amount + amount: amount, + destExecData: abi.encode(DEFAULT_TOKEN_DEST_GAS_OVERHEAD) }); // Mock the call so returns 2 slots of data @@ -2318,7 +2323,8 @@ contract OffRamp__releaseOrMintSingleToken is OffRampSetup { sourcePoolAddress: abi.encode(s_sourcePoolByToken[token]), destTokenAddress: abi.encode(s_destTokenBySourceToken[token]), extraData: "", - amount: amount + amount: amount, + destExecData: abi.encode(DEFAULT_TOKEN_DEST_GAS_OVERHEAD) }); bytes memory revertData = "failed to balanceOf"; @@ -2342,7 +2348,8 @@ contract OffRamp__releaseOrMintSingleToken is OffRampSetup { sourcePoolAddress: abi.encode(s_sourcePoolByToken[token]), destTokenAddress: abi.encode(s_destTokenBySourceToken[token]), extraData: "", - amount: amount + amount: amount, + destExecData: abi.encode(DEFAULT_TOKEN_DEST_GAS_OVERHEAD) }); vm.mockCall( @@ -2369,7 +2376,8 @@ contract OffRamp__releaseOrMintSingleToken is OffRampSetup { sourcePoolAddress: abi.encode(s_sourcePoolByToken[token]), destTokenAddress: abi.encode(s_destTokenBySourceToken[token]), extraData: "", - amount: amount + amount: amount, + destExecData: abi.encode(DEFAULT_TOKEN_DEST_GAS_OVERHEAD) }); // This should make the call fail if it does not skip the check @@ -2396,7 +2404,8 @@ contract OffRamp__releaseOrMintSingleToken is OffRampSetup { sourcePoolAddress: abi.encode(s_sourcePoolByToken[token]), destTokenAddress: abi.encode(destToken), extraData: "", - amount: amount + amount: amount, + destExecData: abi.encode(DEFAULT_TOKEN_DEST_GAS_OVERHEAD) }); // Address(0) should always revert @@ -2438,7 +2447,8 @@ contract OffRamp__releaseOrMintSingleToken is OffRampSetup { sourcePoolAddress: abi.encode(s_sourcePoolByToken[token]), destTokenAddress: abi.encode(destToken), extraData: "", - amount: amount + amount: amount, + destExecData: abi.encode(DEFAULT_TOKEN_DEST_GAS_OVERHEAD) }); bytes memory revertData = "call reverted :o"; @@ -2594,7 +2604,8 @@ contract OffRamp_releaseOrMintTokens is OffRampSetup { sourcePoolAddress: abi.encode(fakePoolAddress), destTokenAddress: abi.encode(s_offRamp), extraData: "", - amount: 1 + amount: 1, + destExecData: abi.encode(DEFAULT_TOKEN_DEST_GAS_OVERHEAD) }); vm.expectRevert(abi.encodeWithSelector(OffRamp.NotACompatiblePool.selector, address(0))); @@ -2646,7 +2657,8 @@ contract OffRamp_releaseOrMintTokens is OffRampSetup { sourcePoolAddress: unusedVar, destTokenAddress: abi.encode(destPool), extraData: unusedVar, - amount: 1 + amount: 1, + destExecData: abi.encode(DEFAULT_TOKEN_DEST_GAS_OVERHEAD) }); try s_offRamp.releaseOrMintTokens( diff --git a/contracts/src/v0.8/ccip/test/offRamp/OffRampSetup.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRampSetup.t.sol index 8156c8c14a..fb61fbfc7d 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/OffRampSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRampSetup.t.sol @@ -297,7 +297,8 @@ contract OffRampSetup is PriceRegistrySetup, MultiOCR3BaseSetup { sourcePoolAddress: abi.encode(s_sourcePoolByToken[tokenAmounts[i].token]), destTokenAddress: abi.encode(s_destTokenBySourceToken[tokenAmounts[i].token]), extraData: "", - amount: tokenAmounts[i].amount + amount: tokenAmounts[i].amount, + destExecData: abi.encode(DEFAULT_TOKEN_DEST_GAS_OVERHEAD) }); } @@ -414,7 +415,8 @@ contract OffRampSetup is PriceRegistrySetup, MultiOCR3BaseSetup { sourcePoolAddress: abi.encode(s_sourcePoolByToken[srcTokenAmounts[i].token]), destTokenAddress: abi.encode(s_destTokenBySourceToken[srcTokenAmounts[i].token]), extraData: "", - amount: srcTokenAmounts[i].amount + amount: srcTokenAmounts[i].amount, + destExecData: abi.encode(DEFAULT_TOKEN_DEST_GAS_OVERHEAD) }); } return sourceTokenData; diff --git a/contracts/src/v0.8/ccip/test/priceRegistry/PriceRegistry.t.sol b/contracts/src/v0.8/ccip/test/priceRegistry/PriceRegistry.t.sol index bc7b3159b6..dbbc4b32cd 100644 --- a/contracts/src/v0.8/ccip/test/priceRegistry/PriceRegistry.t.sol +++ b/contracts/src/v0.8/ccip/test/priceRegistry/PriceRegistry.t.sol @@ -748,13 +748,6 @@ contract PriceRegistry_applyDestChainConfigUpdates is PriceRegistrySetup { destChainConfigArgs.destChainConfig.defaultTxGasLimit, 1, destChainConfigArgs.destChainConfig.maxPerMsgGasLimit ) ); - destChainConfigArgs.destChainConfig.defaultTokenDestBytesOverhead = uint32( - bound( - destChainConfigArgs.destChainConfig.defaultTokenDestBytesOverhead, - Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES, - type(uint32).max - ) - ); destChainConfigArgs.destChainConfig.chainFamilySelector = Internal.CHAIN_FAMILY_SELECTOR_EVM; bool isNewChain = destChainConfigArgs.destChainSelector != DEST_CHAIN_SELECTOR; @@ -852,17 +845,6 @@ contract PriceRegistry_applyDestChainConfigUpdates is PriceRegistrySetup { s_priceRegistry.applyDestChainConfigUpdates(destChainConfigArgs); } - function test_InvalidDestBytesOverhead_Revert() public { - PriceRegistry.DestChainConfigArgs[] memory destChainConfigArgs = _generatePriceRegistryDestChainConfigArgs(); - PriceRegistry.DestChainConfigArgs memory destChainConfigArg = destChainConfigArgs[0]; - - destChainConfigArg.destChainConfig.defaultTokenDestBytesOverhead = uint32(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES - 1); - - vm.expectRevert(abi.encodeWithSelector(PriceRegistry.InvalidDestChainConfig.selector, DEST_CHAIN_SELECTOR)); - - s_priceRegistry.applyDestChainConfigUpdates(destChainConfigArgs); - } - function test_InvalidChainFamilySelector_Revert() public { PriceRegistry.DestChainConfigArgs[] memory destChainConfigArgs = _generatePriceRegistryDestChainConfigArgs(); PriceRegistry.DestChainConfigArgs memory destChainConfigArg = destChainConfigArgs[0]; @@ -969,8 +951,6 @@ contract PriceRegistry_getDataAvailabilityCost is PriceRegistrySetup { destChainConfigArgs[0].destChainConfig.defaultTxGasLimit = GAS_LIMIT; destChainConfigArgs[0].destChainConfig.maxPerMsgGasLimit = GAS_LIMIT; destChainConfigArgs[0].destChainConfig.chainFamilySelector = Internal.CHAIN_FAMILY_SELECTOR_EVM; - destChainConfigArgs[0].destChainConfig.defaultTokenDestBytesOverhead = DEFAULT_TOKEN_BYTES_OVERHEAD; - s_priceRegistry.applyDestChainConfigUpdates(destChainConfigArgs); uint256 dataAvailabilityCostUSD = s_priceRegistry.getDataAvailabilityCost( @@ -1889,31 +1869,44 @@ contract PriceRegistry_processMessageArgs is PriceRegistryFeeSetup { } } -contract PriceRegistry_validatePoolReturnData is PriceRegistryFeeSetup { - function test_WithSingleToken_Success() public view { - Client.EVMTokenAmount[] memory sourceTokenAmounts = new Client.EVMTokenAmount[](1); +contract PriceRegistry_processPoolReturnData is PriceRegistryFeeSetup { + function Test_ProcessPoolReturnData_Success() public view { + Client.EVMTokenAmount[] memory sourceTokenAmounts = new Client.EVMTokenAmount[](2); sourceTokenAmounts[0].amount = 1e18; sourceTokenAmounts[0].token = s_sourceTokens[0]; + sourceTokenAmounts[1].amount = 1e18; + sourceTokenAmounts[1].token = CUSTOM_TOKEN_2; - Internal.RampTokenAmount[] memory rampTokenAmounts = new Internal.RampTokenAmount[](1); - rampTokenAmounts[0] = _getSourceTokenData(sourceTokenAmounts[0], s_tokenAdminRegistry); + Internal.RampTokenAmount[] memory rampTokenAmounts = new Internal.RampTokenAmount[](2); + rampTokenAmounts[0] = _getSourceTokenData(sourceTokenAmounts[0], s_tokenAdminRegistry, DEST_CHAIN_SELECTOR); + rampTokenAmounts[1] = _getSourceTokenData(sourceTokenAmounts[1], s_tokenAdminRegistry, DEST_CHAIN_SELECTOR); + bytes[] memory expectedDestExecData = new bytes[](2); + expectedDestExecData[0] = abi.encode( + s_priceRegistryTokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig.destGasOverhead + ); + expectedDestExecData[1] = abi.encode(DEFAULT_TOKEN_DEST_GAS_OVERHEAD); //expected return data should be abi.encoded default as isEnabled is false // No revert - successful - s_priceRegistry.validatePoolReturnData(DEST_CHAIN_SELECTOR, rampTokenAmounts, sourceTokenAmounts); + bytes[] memory destExecData = + s_priceRegistry.processPoolReturnData(DEST_CHAIN_SELECTOR, rampTokenAmounts, sourceTokenAmounts); + + for (uint256 i = 0; i < destExecData.length; ++i) { + assertEq(destExecData[i], expectedDestExecData[i]); + } } function test_TokenAmountArraysMismatching_Revert() public { - Client.EVMTokenAmount[] memory sourceTokenAmounts = new Client.EVMTokenAmount[](1); + Client.EVMTokenAmount[] memory sourceTokenAmounts = new Client.EVMTokenAmount[](2); sourceTokenAmounts[0].amount = 1e18; sourceTokenAmounts[0].token = s_sourceTokens[0]; Internal.RampTokenAmount[] memory rampTokenAmounts = new Internal.RampTokenAmount[](1); - rampTokenAmounts[0] = _getSourceTokenData(sourceTokenAmounts[0], s_tokenAdminRegistry); + rampTokenAmounts[0] = _getSourceTokenData(sourceTokenAmounts[0], s_tokenAdminRegistry, DEST_CHAIN_SELECTOR); // Revert due to index out of bounds access vm.expectRevert(); - s_priceRegistry.validatePoolReturnData( + s_priceRegistry.processPoolReturnData( DEST_CHAIN_SELECTOR, new Internal.RampTokenAmount[](1), new Client.EVMTokenAmount[](0) ); } @@ -1926,19 +1919,19 @@ contract PriceRegistry_validatePoolReturnData is PriceRegistryFeeSetup { sourceTokenAmounts[0].token = sourceETH; Internal.RampTokenAmount[] memory rampTokenAmounts = new Internal.RampTokenAmount[](1); - rampTokenAmounts[0] = _getSourceTokenData(sourceTokenAmounts[0], s_tokenAdminRegistry); + rampTokenAmounts[0] = _getSourceTokenData(sourceTokenAmounts[0], s_tokenAdminRegistry, DEST_CHAIN_SELECTOR); // No data set, should succeed - s_priceRegistry.validatePoolReturnData(DEST_CHAIN_SELECTOR, rampTokenAmounts, sourceTokenAmounts); + s_priceRegistry.processPoolReturnData(DEST_CHAIN_SELECTOR, rampTokenAmounts, sourceTokenAmounts); // Set max data length, should succeed rampTokenAmounts[0].extraData = new bytes(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES); - s_priceRegistry.validatePoolReturnData(DEST_CHAIN_SELECTOR, rampTokenAmounts, sourceTokenAmounts); + s_priceRegistry.processPoolReturnData(DEST_CHAIN_SELECTOR, rampTokenAmounts, sourceTokenAmounts); // Set data to max length +1, should revert rampTokenAmounts[0].extraData = new bytes(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES + 1); vm.expectRevert(abi.encodeWithSelector(PriceRegistry.SourceTokenDataTooLarge.selector, sourceETH)); - s_priceRegistry.validatePoolReturnData(DEST_CHAIN_SELECTOR, rampTokenAmounts, sourceTokenAmounts); + s_priceRegistry.processPoolReturnData(DEST_CHAIN_SELECTOR, rampTokenAmounts, sourceTokenAmounts); // Set token config to allow larger data PriceRegistry.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs = @@ -1958,13 +1951,13 @@ contract PriceRegistry_validatePoolReturnData is PriceRegistryFeeSetup { tokenTransferFeeConfigArgs, new PriceRegistry.TokenTransferFeeConfigRemoveArgs[](0) ); - s_priceRegistry.validatePoolReturnData(DEST_CHAIN_SELECTOR, rampTokenAmounts, sourceTokenAmounts); + s_priceRegistry.processPoolReturnData(DEST_CHAIN_SELECTOR, rampTokenAmounts, sourceTokenAmounts); // Set the token data larger than the configured token data, should revert rampTokenAmounts[0].extraData = new bytes(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES + 32 + 1); vm.expectRevert(abi.encodeWithSelector(PriceRegistry.SourceTokenDataTooLarge.selector, sourceETH)); - s_priceRegistry.validatePoolReturnData(DEST_CHAIN_SELECTOR, rampTokenAmounts, sourceTokenAmounts); + s_priceRegistry.processPoolReturnData(DEST_CHAIN_SELECTOR, rampTokenAmounts, sourceTokenAmounts); } function test_InvalidEVMAddressDestToken_Revert() public { @@ -1975,11 +1968,11 @@ contract PriceRegistry_validatePoolReturnData is PriceRegistryFeeSetup { sourceTokenAmounts[0].token = s_sourceTokens[0]; Internal.RampTokenAmount[] memory rampTokenAmounts = new Internal.RampTokenAmount[](1); - rampTokenAmounts[0] = _getSourceTokenData(sourceTokenAmounts[0], s_tokenAdminRegistry); + rampTokenAmounts[0] = _getSourceTokenData(sourceTokenAmounts[0], s_tokenAdminRegistry, DEST_CHAIN_SELECTOR); rampTokenAmounts[0].destTokenAddress = nonEvmAddress; vm.expectRevert(abi.encodeWithSelector(Internal.InvalidEVMAddress.selector, nonEvmAddress)); - s_priceRegistry.validatePoolReturnData(DEST_CHAIN_SELECTOR, rampTokenAmounts, sourceTokenAmounts); + s_priceRegistry.processPoolReturnData(DEST_CHAIN_SELECTOR, rampTokenAmounts, sourceTokenAmounts); } } diff --git a/contracts/src/v0.8/ccip/test/priceRegistry/PriceRegistrySetup.t.sol b/contracts/src/v0.8/ccip/test/priceRegistry/PriceRegistrySetup.t.sol index 6a4a1e3205..ee76c51c53 100644 --- a/contracts/src/v0.8/ccip/test/priceRegistry/PriceRegistrySetup.t.sol +++ b/contracts/src/v0.8/ccip/test/priceRegistry/PriceRegistrySetup.t.sol @@ -16,7 +16,10 @@ contract PriceRegistrySetup is TokenSetup { uint112 internal constant USD_PER_DATA_AVAILABILITY_GAS = 1e9; // 1 gwei address internal constant CUSTOM_TOKEN = address(12345); + address internal constant CUSTOM_TOKEN_2 = address(bytes20(keccak256("CUSTOM_TOKEN_2"))); + uint224 internal constant CUSTOM_TOKEN_PRICE = 1e17; // $0.1 CUSTOM + uint224 internal constant CUSTOM_TOKEN_PRICE_2 = 1e18; // $1 CUSTOM // Encode L1 gas price and L2 gas price into a packed price. // L1 gas price is left-shifted to the higher-order bits. @@ -138,6 +141,22 @@ contract PriceRegistrySetup is TokenSetup { }) }) ); + s_priceRegistryTokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs.push( + PriceRegistry.TokenTransferFeeConfigSingleTokenArgs({ + token: CUSTOM_TOKEN_2, + tokenTransferFeeConfig: PriceRegistry.TokenTransferFeeConfig({ + minFeeUSDCents: 2_00, // 1 USD + maxFeeUSDCents: 2000_00, // 1,000 USD + deciBps: 10_0, // 10 bps, or 0.1% + destGasOverhead: 1, + destBytesOverhead: 200, + isEnabled: false + }) + }) + ); + + //setting up the destination token for CUSTOM_TOKEN_2 here as it is specific to these tests + s_destTokenBySourceToken[CUSTOM_TOKEN_2] = address(bytes20(keccak256("CUSTOM_TOKEN_2_DEST"))); s_priceRegistry = new PriceRegistryHelper( PriceRegistry.StaticConfig({ @@ -236,7 +255,6 @@ contract PriceRegistrySetup is TokenSetup { maxPerMsgGasLimit: MAX_GAS_LIMIT, defaultTokenFeeUSDCents: DEFAULT_TOKEN_FEE_USD_CENTS, defaultTokenDestGasOverhead: DEFAULT_TOKEN_DEST_GAS_OVERHEAD, - defaultTokenDestBytesOverhead: DEFAULT_TOKEN_BYTES_OVERHEAD, defaultTxGasLimit: GAS_LIMIT, gasMultiplierWeiPerEth: 5e17, networkFeeUSDCents: 1_00, @@ -300,7 +318,6 @@ contract PriceRegistrySetup is TokenSetup { assertEq(a.destDataAvailabilityMultiplierBps, b.destDataAvailabilityMultiplierBps); assertEq(a.defaultTokenFeeUSDCents, b.defaultTokenFeeUSDCents); assertEq(a.defaultTokenDestGasOverhead, b.defaultTokenDestGasOverhead); - assertEq(a.defaultTokenDestBytesOverhead, b.defaultTokenDestBytesOverhead); assertEq(a.defaultTxGasLimit, b.defaultTxGasLimit); } } @@ -383,7 +400,8 @@ contract PriceRegistryFeeSetup is PriceRegistrySetup { }); for (uint256 i = 0; i < message.tokenAmounts.length; ++i) { - messageEvent.tokenAmounts[i] = _getSourceTokenData(message.tokenAmounts[i], tokenAdminRegistry); + messageEvent.tokenAmounts[i] = + _getSourceTokenData(message.tokenAmounts[i], tokenAdminRegistry, DEST_CHAIN_SELECTOR); } messageEvent.header.messageId = Internal._hash(messageEvent, metadataHash); @@ -392,15 +410,26 @@ contract PriceRegistryFeeSetup is PriceRegistrySetup { function _getSourceTokenData( Client.EVMTokenAmount memory tokenAmount, - TokenAdminRegistry tokenAdminRegistry + TokenAdminRegistry tokenAdminRegistry, + uint64 destChainSelector ) internal view returns (Internal.RampTokenAmount memory) { address destToken = s_destTokenBySourceToken[tokenAmount.token]; + uint256 tokenTransferFeeConfigArgIndex; + uint256 tokenTransferFeeConfigsIndex; + + uint32 expectedDestGasAmount; + PriceRegistry.TokenTransferFeeConfig memory tokenTransferFeeConfig = + PriceRegistry(s_priceRegistry).getTokenTransferFeeConfig(destChainSelector, tokenAmount.token); + expectedDestGasAmount = + tokenTransferFeeConfig.isEnabled ? tokenTransferFeeConfig.destGasOverhead : DEFAULT_TOKEN_DEST_GAS_OVERHEAD; + return Internal.RampTokenAmount({ sourcePoolAddress: abi.encode(tokenAdminRegistry.getTokenConfig(tokenAmount.token).tokenPool), destTokenAddress: abi.encode(destToken), extraData: "", - amount: tokenAmount.amount + amount: tokenAmount.amount, + destExecData: abi.encode(expectedDestGasAmount) }); } diff --git a/core/capabilities/ccip/ccip_integration_tests/helpers.go b/core/capabilities/ccip/ccip_integration_tests/helpers.go index 11c8d96800..a98a8ce1cd 100644 --- a/core/capabilities/ccip/ccip_integration_tests/helpers.go +++ b/core/capabilities/ccip/ccip_integration_tests/helpers.go @@ -841,7 +841,6 @@ func defaultPriceRegistryDestChainConfig(t *testing.T) price_registry.PriceRegis DestGasPerDataAvailabilityByte: 100, DestDataAvailabilityMultiplierBps: 1, DefaultTokenDestGasOverhead: 125_000, - DefaultTokenDestBytesOverhead: 32, DefaultTxGasLimit: 200_000, GasMultiplierWeiPerEth: 1, NetworkFeeUSDCents: 1, diff --git a/core/capabilities/ccip/configs/evm/contract_reader.go b/core/capabilities/ccip/configs/evm/contract_reader.go index fd5cc49fa3..e395013cc9 100644 --- a/core/capabilities/ccip/configs/evm/contract_reader.go +++ b/core/capabilities/ccip/configs/evm/contract_reader.go @@ -162,8 +162,8 @@ var SourceReaderConfig = evmrelaytypes.ChainReaderConfig{ ChainSpecificName: mustGetMethodName("processMessageArgs", priceRegistryABI), ReadType: evmrelaytypes.Method, }, - "ValidatePoolReturnData": { - ChainSpecificName: mustGetMethodName("validatePoolReturnData", priceRegistryABI), + "ProcessPoolReturnData": { + ChainSpecificName: mustGetMethodName("processPoolReturnData", priceRegistryABI), ReadType: evmrelaytypes.Method, }, "GetValidatedTokenPrice": { diff --git a/core/gethwrappers/ccip/generated/ccip_reader_tester/ccip_reader_tester.go b/core/gethwrappers/ccip/generated/ccip_reader_tester/ccip_reader_tester.go index 164c066e23..915a045c10 100644 --- a/core/gethwrappers/ccip/generated/ccip_reader_tester/ccip_reader_tester.go +++ b/core/gethwrappers/ccip/generated/ccip_reader_tester/ccip_reader_tester.go @@ -64,6 +64,7 @@ type InternalRampTokenAmount struct { DestTokenAddress []byte ExtraData []byte Amount *big.Int + DestExecData []byte } type InternalTokenPriceUpdate struct { @@ -95,8 +96,8 @@ type OffRampSourceChainConfig struct { } var CCIPReaderTesterMetaData = &bind.MetaData{ - ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"CCIPSendRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"internalType\":\"structOffRamp.Interval\",\"name\":\"interval\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structOffRamp.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"report\",\"type\":\"tuple\"}],\"name\":\"CommitReportAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"name\":\"ExecutionStateChanged\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"emitCCIPSendRequested\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"internalType\":\"structOffRamp.Interval\",\"name\":\"interval\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structOffRamp.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"}],\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"report\",\"type\":\"tuple\"}],\"name\":\"emitCommitReportAccepted\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"name\":\"emitExecutionStateChanged\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"getSourceChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"sourceChainConfig\",\"type\":\"tuple\"}],\"name\":\"setSourceChainConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x608060405234801561001057600080fd5b50611149806100206000396000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c80634cf66e361461005c578063a65558f614610071578063e44302b714610084578063e83eabba14610097578063e9d68a8e146100aa575b600080fd5b61006f61006a3660046104a7565b6100d3565b005b61006f61007f366004610718565b610128565b61006f6100923660046109b6565b61016d565b61006f6100a5366004610b20565b6101a7565b6100bd6100b8366004610bdb565b610233565b6040516100ca9190610c43565b60405180910390f35b82846001600160401b0316866001600160401b03167f8c324ce1367b83031769f6a813e3bb4c117aba2185789d66b98b791405be6df28585604051610119929190610c9b565b60405180910390a45050505050565b816001600160401b03167f0f07cd31e53232da9125e517f09550fdde74bf43d6a0a76ebd41674dafe2ab29826040516101619190610d83565b60405180910390a25050565b7f3a3950e13dd607cc37980db0ef14266c40d2bba9c01b2e44bfe549808883095d8160405161019c9190610f3d565b60405180910390a150565b6001600160401b0380831660009081526020818152604091829020845181549286015193860151909416600160a81b02600160a81b600160e81b0319931515600160a01b026001600160a81b03199093166001600160a01b039095169490941791909117919091169190911781556060820151829190600182019061022c908261107d565b5050505050565b60408051608080820183526000808352602080840182905283850182905260608085018190526001600160401b038781168452838352928690208651948501875280546001600160a01b0381168652600160a01b810460ff16151593860193909352600160a81b9092049092169483019490945260018401805493949293918401916102be90610ff2565b80601f01602080910402602001604051908101604052809291908181526020018280546102ea90610ff2565b80156103375780601f1061030c57610100808354040283529160200191610337565b820191906000526020600020905b81548152906001019060200180831161031a57829003601f168201915b5050505050815250509050919050565b80356001600160401b038116811461035e57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b038111828210171561039b5761039b610363565b60405290565b60405161010081016001600160401b038111828210171561039b5761039b610363565b604080519081016001600160401b038111828210171561039b5761039b610363565b604051606081016001600160401b038111828210171561039b5761039b610363565b604051601f8201601f191681016001600160401b038111828210171561043057610430610363565b604052919050565b600082601f83011261044957600080fd5b81356001600160401b0381111561046257610462610363565b610475601f8201601f1916602001610408565b81815284602083860101111561048a57600080fd5b816020850160208301376000918101602001919091529392505050565b600080600080600060a086880312156104bf57600080fd5b6104c886610347565b94506104d660208701610347565b9350604086013592506060860135600481106104f157600080fd5b915060808601356001600160401b0381111561050c57600080fd5b61051888828901610438565b9150509295509295909350565b600060a0828403121561053757600080fd5b60405160a081016001600160401b038111828210171561055957610559610363565b6040528235815290508061056f60208401610347565b602082015261058060408401610347565b604082015261059160608401610347565b60608201526105a260808401610347565b60808201525092915050565b6001600160a01b03811681146105c357600080fd5b50565b803561035e816105ae565b60006001600160401b038211156105ea576105ea610363565b5060051b60200190565b600082601f83011261060557600080fd5b8135602061061a610615836105d1565b610408565b82815260059290921b8401810191818101908684111561063957600080fd5b8286015b8481101561070d5780356001600160401b038082111561065d5760008081fd5b908801906080828b03601f19018113156106775760008081fd5b61067f610379565b87840135838111156106915760008081fd5b61069f8d8a83880101610438565b825250604080850135848111156106b65760008081fd5b6106c48e8b83890101610438565b8a84015250606080860135858111156106dd5760008081fd5b6106eb8f8c838a0101610438565b928401929092529490920135938101939093525050835291830191830161063d565b509695505050505050565b6000806040838503121561072b57600080fd5b61073483610347565b915060208301356001600160401b038082111561075057600080fd5b90840190610180828703121561076557600080fd5b61076d6103a1565b6107778784610525565b815261078560a084016105c6565b602082015260c08301358281111561079c57600080fd5b6107a888828601610438565b60408301525060e0830135828111156107c057600080fd5b6107cc88828601610438565b606083015250610100830135828111156107e557600080fd5b6107f188828601610438565b60808301525061080461012084016105c6565b60a082015261014083013560c08201526101608301358281111561082757600080fd5b610833888286016105f4565b60e0830152508093505050509250929050565b80356001600160e01b038116811461035e57600080fd5b600082601f83011261086e57600080fd5b8135602061087e610615836105d1565b82815260069290921b8401810191818101908684111561089d57600080fd5b8286015b8481101561070d57604081890312156108ba5760008081fd5b6108c26103c4565b6108cb82610347565b81526108d8858301610846565b818601528352918301916040016108a1565b600082601f8301126108fb57600080fd5b8135602061090b610615836105d1565b82815260079290921b8401810191818101908684111561092a57600080fd5b8286015b8481101561070d5780880360808112156109485760008081fd5b6109506103e6565b61095983610347565b8152604080601f198401121561096f5760008081fd5b6109776103c4565b9250610984878501610347565b8352610991818501610347565b838801528187019290925260608301359181019190915283529183019160800161092e565b600060208083850312156109c957600080fd5b82356001600160401b03808211156109e057600080fd5b818501915060408083880312156109f657600080fd5b6109fe6103c4565b833583811115610a0d57600080fd5b84016040818a031215610a1f57600080fd5b610a276103c4565b813585811115610a3657600080fd5b8201601f81018b13610a4757600080fd5b8035610a55610615826105d1565b81815260069190911b8201890190898101908d831115610a7457600080fd5b928a01925b82841015610ac45787848f031215610a915760008081fd5b610a996103c4565b8435610aa4816105ae565b8152610ab1858d01610846565b818d0152825292870192908a0190610a79565b845250505081870135935084841115610adc57600080fd5b610ae88a85840161085d565b8188015282525083850135915082821115610b0257600080fd5b610b0e888386016108ea565b85820152809550505050505092915050565b60008060408385031215610b3357600080fd5b610b3c83610347565b915060208301356001600160401b0380821115610b5857600080fd5b9084019060808287031215610b6c57600080fd5b610b74610379565b8235610b7f816105ae565b815260208301358015158114610b9457600080fd5b6020820152610ba560408401610347565b6040820152606083013582811115610bbc57600080fd5b610bc888828601610438565b6060830152508093505050509250929050565b600060208284031215610bed57600080fd5b610bf682610347565b9392505050565b6000815180845260005b81811015610c2357602081850181015186830182015201610c07565b506000602082860101526020601f19601f83011685010191505092915050565b602080825282516001600160a01b03168282015282015115156040808301919091528201516001600160401b0316606080830191909152820151608080830152600090610c9360a0840182610bfd565b949350505050565b600060048410610cbb57634e487b7160e01b600052602160045260246000fd5b83825260406020830152610c936040830184610bfd565b6001600160a01b03169052565b600082825180855260208086019550808260051b84010181860160005b84811015610d7657601f19868403018952815160808151818652610d2282870182610bfd565b9150508582015185820387870152610d3a8282610bfd565b91505060408083015186830382880152610d548382610bfd565b6060948501519790940196909652505098840198925090830190600101610cfc565b5090979650505050505050565b60208152610dd0602082018351805182526020808201516001600160401b039081169184019190915260408083015182169084015260608083015182169084015260809182015116910152565b60006020830151610de460c0840182610cd2565b5060408301516101808060e0850152610e016101a0850183610bfd565b91506060850151601f198086850301610100870152610e208483610bfd565b9350608087015191508086850301610120870152610e3e8483610bfd565b935060a08701519150610e55610140870183610cd2565b60c087015161016087015260e0870151915080868503018387015250610e7b8382610cdf565b9695505050505050565b60008151808452602080850194506020840160005b83811015610ed357815180516001600160401b031688528301516001600160e01b03168388015260409096019590820190600101610e9a565b509495945050505050565b600081518084526020808501945080840160005b83811015610ed357815180516001600160401b0390811689528482015180518216868b0152850151166040898101919091520151606088015260809096019590820190600101610ef2565b6000602080835283516040808386015260a0850182516040606088015281815180845260c0890191508683019350600092505b80831015610fab57835180516001600160a01b031683528701516001600160e01b031687830152928601926001929092019190840190610f70565b5093850151878503605f1901608089015293610fc78186610e85565b945050505050818501519150601f19848203016040850152610fe98183610ede565b95945050505050565b600181811c9082168061100657607f821691505b60208210810361102657634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115611078576000816000526020600020601f850160051c810160208610156110555750805b601f850160051c820191505b8181101561107457828155600101611061565b5050505b505050565b81516001600160401b0381111561109657611096610363565b6110aa816110a48454610ff2565b8461102c565b602080601f8311600181146110df57600084156110c75750858301515b600019600386901b1c1916600185901b178555611074565b600085815260208120601f198616915b8281101561110e578886015182559484019460019091019084016110ef565b508582101561112c5787850151600019600388901b60f8161c191681555b5050505050600190811b0190555056fea164736f6c6343000818000a", + ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"CCIPSendRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"internalType\":\"structOffRamp.Interval\",\"name\":\"interval\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structOffRamp.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"report\",\"type\":\"tuple\"}],\"name\":\"CommitReportAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"name\":\"ExecutionStateChanged\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"emitCCIPSendRequested\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"internalType\":\"structOffRamp.Interval\",\"name\":\"interval\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structOffRamp.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"}],\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"report\",\"type\":\"tuple\"}],\"name\":\"emitCommitReportAccepted\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"name\":\"emitExecutionStateChanged\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"getSourceChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"sourceChainConfig\",\"type\":\"tuple\"}],\"name\":\"setSourceChainConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x608060405234801561001057600080fd5b5061118d806100206000396000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c80634cf66e361461005c57806385096da914610071578063e44302b714610084578063e83eabba14610097578063e9d68a8e146100aa575b600080fd5b61006f61006a3660046104c9565b6100d3565b005b61006f61007f366004610741565b610128565b61006f6100923660046109df565b61016d565b61006f6100a5366004610b49565b6101a7565b6100bd6100b8366004610c04565b610233565b6040516100ca9190610c6c565b60405180910390f35b82846001600160401b0316866001600160401b03167f8c324ce1367b83031769f6a813e3bb4c117aba2185789d66b98b791405be6df28585604051610119929190610cc4565b60405180910390a45050505050565b816001600160401b03167fcae3d9f68a9ed33d0a770e9bcc6fc25d4041dd6391e6cd8015546547a3c93140826040516101619190610dc7565b60405180910390a25050565b7f3a3950e13dd607cc37980db0ef14266c40d2bba9c01b2e44bfe549808883095d8160405161019c9190610f81565b60405180910390a150565b6001600160401b0380831660009081526020818152604091829020845181549286015193860151909416600160a81b02600160a81b600160e81b0319931515600160a01b026001600160a81b03199093166001600160a01b039095169490941791909117919091169190911781556060820151829190600182019061022c90826110c1565b5050505050565b60408051608080820183526000808352602080840182905283850182905260608085018190526001600160401b038781168452838352928690208651948501875280546001600160a01b0381168652600160a01b810460ff16151593860193909352600160a81b9092049092169483019490945260018401805493949293918401916102be90611036565b80601f01602080910402602001604051908101604052809291908181526020018280546102ea90611036565b80156103375780601f1061030c57610100808354040283529160200191610337565b820191906000526020600020905b81548152906001019060200180831161031a57829003601f168201915b5050505050815250509050919050565b80356001600160401b038116811461035e57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60405160a081016001600160401b038111828210171561039b5761039b610363565b60405290565b60405161010081016001600160401b038111828210171561039b5761039b610363565b604080519081016001600160401b038111828210171561039b5761039b610363565b604051606081016001600160401b038111828210171561039b5761039b610363565b604051608081016001600160401b038111828210171561039b5761039b610363565b604051601f8201601f191681016001600160401b038111828210171561045257610452610363565b604052919050565b600082601f83011261046b57600080fd5b81356001600160401b0381111561048457610484610363565b610497601f8201601f191660200161042a565b8181528460208386010111156104ac57600080fd5b816020850160208301376000918101602001919091529392505050565b600080600080600060a086880312156104e157600080fd5b6104ea86610347565b94506104f860208701610347565b93506040860135925060608601356004811061051357600080fd5b915060808601356001600160401b0381111561052e57600080fd5b61053a8882890161045a565b9150509295509295909350565b600060a0828403121561055957600080fd5b610561610379565b90508135815261057360208301610347565b602082015261058460408301610347565b604082015261059560608301610347565b60608201526105a660808301610347565b608082015292915050565b6001600160a01b03811681146105c657600080fd5b50565b803561035e816105b1565b60006001600160401b038211156105ed576105ed610363565b5060051b60200190565b600082601f83011261060857600080fd5b8135602061061d610618836105d4565b61042a565b82815260059290921b8401810191818101908684111561063c57600080fd5b8286015b848110156107365780356001600160401b03808211156106605760008081fd5b9088019060a0828b03601f190181131561067a5760008081fd5b610682610379565b87840135838111156106945760008081fd5b6106a28d8a8388010161045a565b825250604080850135848111156106b95760008081fd5b6106c78e8b8389010161045a565b8a84015250606080860135858111156106e05760008081fd5b6106ee8f8c838a010161045a565b838501525060809150818601358184015250828501359250838311156107145760008081fd5b6107228d8a8588010161045a565b908201528652505050918301918301610640565b509695505050505050565b6000806040838503121561075457600080fd5b61075d83610347565b915060208301356001600160401b038082111561077957600080fd5b90840190610180828703121561078e57600080fd5b6107966103a1565b6107a08784610547565b81526107ae60a084016105c9565b602082015260c0830135828111156107c557600080fd5b6107d18882860161045a565b60408301525060e0830135828111156107e957600080fd5b6107f58882860161045a565b6060830152506101008301358281111561080e57600080fd5b61081a8882860161045a565b60808301525061082d61012084016105c9565b60a082015261014083013560c08201526101608301358281111561085057600080fd5b61085c888286016105f7565b60e0830152508093505050509250929050565b80356001600160e01b038116811461035e57600080fd5b600082601f83011261089757600080fd5b813560206108a7610618836105d4565b82815260069290921b840181019181810190868411156108c657600080fd5b8286015b8481101561073657604081890312156108e35760008081fd5b6108eb6103c4565b6108f482610347565b815261090185830161086f565b818601528352918301916040016108ca565b600082601f83011261092457600080fd5b81356020610934610618836105d4565b82815260079290921b8401810191818101908684111561095357600080fd5b8286015b848110156107365780880360808112156109715760008081fd5b6109796103e6565b61098283610347565b8152604080601f19840112156109985760008081fd5b6109a06103c4565b92506109ad878501610347565b83526109ba818501610347565b8388015281870192909252606083013591810191909152835291830191608001610957565b600060208083850312156109f257600080fd5b82356001600160401b0380821115610a0957600080fd5b81850191506040808388031215610a1f57600080fd5b610a276103c4565b833583811115610a3657600080fd5b84016040818a031215610a4857600080fd5b610a506103c4565b813585811115610a5f57600080fd5b8201601f81018b13610a7057600080fd5b8035610a7e610618826105d4565b81815260069190911b8201890190898101908d831115610a9d57600080fd5b928a01925b82841015610aed5787848f031215610aba5760008081fd5b610ac26103c4565b8435610acd816105b1565b8152610ada858d0161086f565b818d0152825292870192908a0190610aa2565b845250505081870135935084841115610b0557600080fd5b610b118a858401610886565b8188015282525083850135915082821115610b2b57600080fd5b610b3788838601610913565b85820152809550505050505092915050565b60008060408385031215610b5c57600080fd5b610b6583610347565b915060208301356001600160401b0380821115610b8157600080fd5b9084019060808287031215610b9557600080fd5b610b9d610408565b8235610ba8816105b1565b815260208301358015158114610bbd57600080fd5b6020820152610bce60408401610347565b6040820152606083013582811115610be557600080fd5b610bf18882860161045a565b6060830152508093505050509250929050565b600060208284031215610c1657600080fd5b610c1f82610347565b9392505050565b6000815180845260005b81811015610c4c57602081850181015186830182015201610c30565b506000602082860101526020601f19601f83011685010191505092915050565b602080825282516001600160a01b03168282015282015115156040808301919091528201516001600160401b0316606080830191909152820151608080830152600090610cbc60a0840182610c26565b949350505050565b600060048410610ce457634e487b7160e01b600052602160045260246000fd5b83825260406020830152610cbc6040830184610c26565b6001600160a01b03169052565b600082825180855260208086019550808260051b84010181860160005b84811015610dba57601f19868403018952815160a08151818652610d4b82870182610c26565b9150508582015185820387870152610d638282610c26565b91505060408083015186830382880152610d7d8382610c26565b92505050606080830151818701525060808083015192508582038187015250610da68183610c26565b9a86019a9450505090830190600101610d25565b5090979650505050505050565b60208152610e14602082018351805182526020808201516001600160401b039081169184019190915260408083015182169084015260608083015182169084015260809182015116910152565b60006020830151610e2860c0840182610cfb565b5060408301516101808060e0850152610e456101a0850183610c26565b91506060850151601f198086850301610100870152610e648483610c26565b9350608087015191508086850301610120870152610e828483610c26565b935060a08701519150610e99610140870183610cfb565b60c087015161016087015260e0870151915080868503018387015250610ebf8382610d08565b9695505050505050565b60008151808452602080850194506020840160005b83811015610f1757815180516001600160401b031688528301516001600160e01b03168388015260409096019590820190600101610ede565b509495945050505050565b600081518084526020808501945080840160005b83811015610f1757815180516001600160401b0390811689528482015180518216868b0152850151166040898101919091520151606088015260809096019590820190600101610f36565b6000602080835283516040808386015260a0850182516040606088015281815180845260c0890191508683019350600092505b80831015610fef57835180516001600160a01b031683528701516001600160e01b031687830152928601926001929092019190840190610fb4565b5093850151878503605f190160808901529361100b8186610ec9565b945050505050818501519150601f1984820301604085015261102d8183610f22565b95945050505050565b600181811c9082168061104a57607f821691505b60208210810361106a57634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156110bc576000816000526020600020601f850160051c810160208610156110995750805b601f850160051c820191505b818110156110b8578281556001016110a5565b5050505b505050565b81516001600160401b038111156110da576110da610363565b6110ee816110e88454611036565b84611070565b602080601f831160018114611123576000841561110b5750858301515b600019600386901b1c1916600185901b1785556110b8565b600085815260208120601f198616915b8281101561115257888601518255948401946001909101908401611133565b50858210156111705787850151600019600388901b60f8161c191681555b5050505050600190811b0190555056fea164736f6c6343000818000a", } var CCIPReaderTesterABI = CCIPReaderTesterMetaData.ABI @@ -712,7 +713,7 @@ func (_CCIPReaderTester *CCIPReaderTester) ParseLog(log types.Log) (generated.Ab } func (CCIPReaderTesterCCIPSendRequested) Topic() common.Hash { - return common.HexToHash("0x0f07cd31e53232da9125e517f09550fdde74bf43d6a0a76ebd41674dafe2ab29") + return common.HexToHash("0xcae3d9f68a9ed33d0a770e9bcc6fc25d4041dd6391e6cd8015546547a3c93140") } func (CCIPReaderTesterCommitReportAccepted) Topic() common.Hash { diff --git a/core/gethwrappers/ccip/generated/message_hasher/message_hasher.go b/core/gethwrappers/ccip/generated/message_hasher/message_hasher.go index 52434b5049..1d95e75778 100644 --- a/core/gethwrappers/ccip/generated/message_hasher/message_hasher.go +++ b/core/gethwrappers/ccip/generated/message_hasher/message_hasher.go @@ -59,11 +59,12 @@ type InternalRampTokenAmount struct { DestTokenAddress []byte ExtraData []byte Amount *big.Int + DestExecData []byte } var MessageHasherMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"}],\"name\":\"decodeEVMExtraArgsV1\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMExtraArgsV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"allowOutOfOrderExecution\",\"type\":\"bool\"}],\"name\":\"decodeEVMExtraArgsV2\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"allowOutOfOrderExecution\",\"type\":\"bool\"}],\"internalType\":\"structClient.EVMExtraArgsV2\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMExtraArgsV1\",\"name\":\"extraArgs\",\"type\":\"tuple\"}],\"name\":\"encodeEVMExtraArgsV1\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"allowOutOfOrderExecution\",\"type\":\"bool\"}],\"internalType\":\"structClient.EVMExtraArgsV2\",\"name\":\"extraArgs\",\"type\":\"tuple\"}],\"name\":\"encodeEVMExtraArgsV2\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"leafDomainSeparator\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"implicitMetadataHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"fixedSizeFieldsHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"dataHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"tokenAmountsHash\",\"type\":\"bytes32\"}],\"name\":\"encodeFinalHashPreimage\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"name\":\"encodeFixedSizeFieldsHashPreimage\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"any2EVMMessageHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"name\":\"encodeMetadataHashPreimage\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"rampTokenAmounts\",\"type\":\"tuple[]\"}],\"name\":\"encodeTokenAmountsHashPreimage\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"name\":\"hash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]", - Bin: "0x608060405234801561001057600080fd5b50610de7806100206000396000f3fe608060405234801561001057600080fd5b50600436106100a35760003560e01c8063a91d3aeb11610076578063c63641bd1161005b578063c63641bd1461019e578063c7ca9a18146101f5578063e733d2091461020857600080fd5b8063a91d3aeb14610150578063b17df7141461016357600080fd5b8063902e94a0146100a85780639511afaa146100d157806399df8d05146100f2578063a1e747df1461013d575b600080fd5b6100bb6100b63660046107d9565b61021b565b6040516100c8919061087a565b60405180910390f35b6100e46100df366004610958565b610244565b6040519081526020016100c8565b6100bb610100366004610a62565b604080516020810196909652858101949094526060850192909252608084015260a0808401919091528151808403909101815260c0909201905290565b6100bb61014b366004610a9d565b610257565b6100bb61015e366004610b05565b610289565b61018f610171366004610b86565b60408051602080820183526000909152815190810190915290815290565b604051905181526020016100c8565b6101d86101ac366004610baf565b604080518082019091526000808252602082015250604080518082019091529182521515602082015290565b6040805182518152602092830151151592810192909252016100c8565b6100bb610203366004610bdb565b6102c1565b6100bb610216366004610c2f565b6102d2565b60608160405160200161022e9190610c71565b6040516020818303038152906040529050919050565b600061025083836102dd565b9392505050565b6060848484846040516020016102709493929190610d3d565b6040516020818303038152906040529050949350505050565b60608686868686866040516020016102a696959493929190610d7a565b60405160208183030381529060405290509695505050505050565b60606102cc8261043a565b92915050565b60606102cc826104fc565b815160208082015160409283015192516000938493610323937f2425b0b9f9054c76ff151b0a175b18f37a4a4e82013a72e9f15c9caa095ed21f93909291889101610d3d565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815290829052805160209182012086518051888401516060808b0151908401516080808d0151950151959761038a9794969395929491939101610d7a565b604051602081830303815290604052805190602001208560400151805190602001208660a001516040516020016103c19190610c71565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120908301969096528101939093526060830191909152608082015260a081019190915260c00160405160208183030381529060405280519060200120905092915050565b604051815160248201526020820151151560448201526060907f181dcf1000000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915292915050565b604051815160248201526060907f97a657c90000000000000000000000000000000000000000000000000000000090604401610479565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040516080810167ffffffffffffffff8111828210171561058557610585610533565b60405290565b60405160c0810167ffffffffffffffff8111828210171561058557610585610533565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156105f5576105f5610533565b604052919050565b600082601f83011261060e57600080fd5b813567ffffffffffffffff81111561062857610628610533565b61065960207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016105ae565b81815284602083860101111561066e57600080fd5b816020850160208301376000918101602001919091529392505050565b600082601f83011261069c57600080fd5b8135602067ffffffffffffffff808311156106b9576106b9610533565b8260051b6106c88382016105ae565b93845285810183019383810190888611156106e257600080fd5b84880192505b858310156107cd578235848111156107005760008081fd5b88016080818b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018113156107365760008081fd5b61073e610562565b87830135878111156107505760008081fd5b61075e8d8a838701016105fd565b825250604080840135888111156107755760008081fd5b6107838e8b838801016105fd565b8a840152506060808501358981111561079c5760008081fd5b6107aa8f8c838901016105fd565b9284019290925293909201359281019290925250825291840191908401906106e8565b98975050505050505050565b6000602082840312156107eb57600080fd5b813567ffffffffffffffff81111561080257600080fd5b61080e8482850161068b565b949350505050565b6000815180845260005b8181101561083c57602081850181015186830182015201610820565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b6020815260006102506020830184610816565b803567ffffffffffffffff811681146108a557600080fd5b919050565b600060a082840312156108bc57600080fd5b60405160a0810181811067ffffffffffffffff821117156108df576108df610533565b604052823581529050806108f56020840161088d565b60208201526109066040840161088d565b60408201526109176060840161088d565b60608201526109286080840161088d565b60808201525092915050565b803573ffffffffffffffffffffffffffffffffffffffff811681146108a557600080fd5b6000806040838503121561096b57600080fd5b823567ffffffffffffffff8082111561098357600080fd5b90840190610140828703121561099857600080fd5b6109a061058b565b6109aa87846108aa565b815260a0830135828111156109be57600080fd5b6109ca888286016105fd565b60208301525060c0830135828111156109e257600080fd5b6109ee888286016105fd565b604083015250610a0060e08401610934565b6060820152610100830135608082015261012083013582811115610a2357600080fd5b610a2f8882860161068b565b60a08301525093506020850135915080821115610a4b57600080fd5b50610a58858286016105fd565b9150509250929050565b600080600080600060a08688031215610a7a57600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b60008060008060808587031215610ab357600080fd5b84359350610ac36020860161088d565b9250610ad16040860161088d565b9150606085013567ffffffffffffffff811115610aed57600080fd5b610af9878288016105fd565b91505092959194509250565b60008060008060008060c08789031215610b1e57600080fd5b86359550602087013567ffffffffffffffff811115610b3c57600080fd5b610b4889828a016105fd565b955050610b5760408801610934565b9350610b656060880161088d565b925060808701359150610b7a60a0880161088d565b90509295509295509295565b600060208284031215610b9857600080fd5b5035919050565b803580151581146108a557600080fd5b60008060408385031215610bc257600080fd5b82359150610bd260208401610b9f565b90509250929050565b600060408284031215610bed57600080fd5b6040516040810181811067ffffffffffffffff82111715610c1057610c10610533565b60405282358152610c2360208401610b9f565b60208201529392505050565b600060208284031215610c4157600080fd5b6040516020810181811067ffffffffffffffff82111715610c6457610c64610533565b6040529135825250919050565b600060208083018184528085518083526040925060408601915060408160051b87010184880160005b83811015610d2f577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0898403018552815160808151818652610cde82870182610816565b915050888201518582038a870152610cf68282610816565b9150508782015185820389870152610d0e8282610816565b60609384015196909301959095525094870194925090860190600101610c9a565b509098975050505050505050565b848152600067ffffffffffffffff808616602084015280851660408401525060806060830152610d706080830184610816565b9695505050505050565b86815260c060208201526000610d9360c0830188610816565b73ffffffffffffffffffffffffffffffffffffffff9690961660408301525067ffffffffffffffff9384166060820152608081019290925290911660a0909101529291505056fea164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"}],\"name\":\"decodeEVMExtraArgsV1\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMExtraArgsV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"allowOutOfOrderExecution\",\"type\":\"bool\"}],\"name\":\"decodeEVMExtraArgsV2\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"allowOutOfOrderExecution\",\"type\":\"bool\"}],\"internalType\":\"structClient.EVMExtraArgsV2\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMExtraArgsV1\",\"name\":\"extraArgs\",\"type\":\"tuple\"}],\"name\":\"encodeEVMExtraArgsV1\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"allowOutOfOrderExecution\",\"type\":\"bool\"}],\"internalType\":\"structClient.EVMExtraArgsV2\",\"name\":\"extraArgs\",\"type\":\"tuple\"}],\"name\":\"encodeEVMExtraArgsV2\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"leafDomainSeparator\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"implicitMetadataHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"fixedSizeFieldsHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"dataHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"tokenAmountsHash\",\"type\":\"bytes32\"}],\"name\":\"encodeFinalHashPreimage\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"name\":\"encodeFixedSizeFieldsHashPreimage\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"any2EVMMessageHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"name\":\"encodeMetadataHashPreimage\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"rampTokenAmounts\",\"type\":\"tuple[]\"}],\"name\":\"encodeTokenAmountsHashPreimage\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"name\":\"hash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]", + Bin: "0x608060405234801561001057600080fd5b50610e08806100206000396000f3fe608060405234801561001057600080fd5b50600436106100a35760003560e01c8063a91d3aeb11610076578063c63641bd1161005b578063c63641bd1461019e578063c7ca9a18146101f5578063e733d2091461020857600080fd5b8063a91d3aeb14610150578063b17df7141461016357600080fd5b80632d6d4c5e146100a85780632efb5ac2146100d157806399df8d05146100f2578063a1e747df1461013d575b600080fd5b6100bb6100b63660046107ff565b61021b565b6040516100c891906108a0565b60405180910390f35b6100e46100df36600461095e565b610244565b6040519081526020016100c8565b6100bb610100366004610a68565b604080516020810196909652858101949094526060850192909252608084015260a0808401919091528151808403909101815260c0909201905290565b6100bb61014b366004610aa3565b610257565b6100bb61015e366004610b0b565b610289565b61018f610171366004610b8c565b60408051602080820183526000909152815190810190915290815290565b604051905181526020016100c8565b6101d86101ac366004610bb5565b604080518082019091526000808252602082015250604080518082019091529182521515602082015290565b6040805182518152602092830151151592810192909252016100c8565b6100bb610203366004610be1565b6102c1565b6100bb610216366004610c35565b6102d2565b60608160405160200161022e9190610c77565b6040516020818303038152906040529050919050565b600061025083836102dd565b9392505050565b6060848484846040516020016102709493929190610d5e565b6040516020818303038152906040529050949350505050565b60608686868686866040516020016102a696959493929190610d9b565b60405160208183030381529060405290509695505050505050565b60606102cc8261043a565b92915050565b60606102cc826104fc565b815160208082015160409283015192516000938493610323937f2425b0b9f9054c76ff151b0a175b18f37a4a4e82013a72e9f15c9caa095ed21f93909291889101610d5e565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815290829052805160209182012086518051888401516060808b0151908401516080808d0151950151959761038a9794969395929491939101610d9b565b604051602081830303815290604052805190602001208560400151805190602001208660a001516040516020016103c19190610c77565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120908301969096528101939093526060830191909152608082015260a081019190915260c00160405160208183030381529060405280519060200120905092915050565b604051815160248201526020820151151560448201526060907f181dcf1000000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915292915050565b604051815160248201526060907f97a657c90000000000000000000000000000000000000000000000000000000090604401610479565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff8111828210171561058557610585610533565b60405290565b60405160c0810167ffffffffffffffff8111828210171561058557610585610533565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156105f5576105f5610533565b604052919050565b600082601f83011261060e57600080fd5b813567ffffffffffffffff81111561062857610628610533565b61065960207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016105ae565b81815284602083860101111561066e57600080fd5b816020850160208301376000918101602001919091529392505050565b600082601f83011261069c57600080fd5b8135602067ffffffffffffffff808311156106b9576106b9610533565b8260051b6106c88382016105ae565b93845285810183019383810190888611156106e257600080fd5b84880192505b858310156107f3578235848111156107005760008081fd5b880160a0818b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018113156107365760008081fd5b61073e610562565b87830135878111156107505760008081fd5b61075e8d8a838701016105fd565b825250604080840135888111156107755760008081fd5b6107838e8b838801016105fd565b8a840152506060808501358981111561079c5760008081fd5b6107aa8f8c838901016105fd565b838501525060809150818501358184015250828401359250878311156107d05760008081fd5b6107de8d8a858701016105fd565b908201528452505091840191908401906106e8565b98975050505050505050565b60006020828403121561081157600080fd5b813567ffffffffffffffff81111561082857600080fd5b6108348482850161068b565b949350505050565b6000815180845260005b8181101561086257602081850181015186830182015201610846565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000610250602083018461083c565b803567ffffffffffffffff811681146108cb57600080fd5b919050565b600060a082840312156108e257600080fd5b6108ea610562565b9050813581526108fc602083016108b3565b602082015261090d604083016108b3565b604082015261091e606083016108b3565b606082015261092f608083016108b3565b608082015292915050565b803573ffffffffffffffffffffffffffffffffffffffff811681146108cb57600080fd5b6000806040838503121561097157600080fd5b823567ffffffffffffffff8082111561098957600080fd5b90840190610140828703121561099e57600080fd5b6109a661058b565b6109b087846108d0565b815260a0830135828111156109c457600080fd5b6109d0888286016105fd565b60208301525060c0830135828111156109e857600080fd5b6109f4888286016105fd565b604083015250610a0660e0840161093a565b6060820152610100830135608082015261012083013582811115610a2957600080fd5b610a358882860161068b565b60a08301525093506020850135915080821115610a5157600080fd5b50610a5e858286016105fd565b9150509250929050565b600080600080600060a08688031215610a8057600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b60008060008060808587031215610ab957600080fd5b84359350610ac9602086016108b3565b9250610ad7604086016108b3565b9150606085013567ffffffffffffffff811115610af357600080fd5b610aff878288016105fd565b91505092959194509250565b60008060008060008060c08789031215610b2457600080fd5b86359550602087013567ffffffffffffffff811115610b4257600080fd5b610b4e89828a016105fd565b955050610b5d6040880161093a565b9350610b6b606088016108b3565b925060808701359150610b8060a088016108b3565b90509295509295509295565b600060208284031215610b9e57600080fd5b5035919050565b803580151581146108cb57600080fd5b60008060408385031215610bc857600080fd5b82359150610bd860208401610ba5565b90509250929050565b600060408284031215610bf357600080fd5b6040516040810181811067ffffffffffffffff82111715610c1657610c16610533565b60405282358152610c2960208401610ba5565b60208201529392505050565b600060208284031215610c4757600080fd5b6040516020810181811067ffffffffffffffff82111715610c6a57610c6a610533565b6040529135825250919050565b600060208083018184528085518083526040925060408601915060408160051b87010184880160005b83811015610d50577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0898403018552815160a08151818652610ce48287018261083c565b915050888201518582038a870152610cfc828261083c565b9150508782015185820389870152610d14828261083c565b915050606080830151818701525060808083015192508582038187015250610d3c818361083c565b968901969450505090860190600101610ca0565b509098975050505050505050565b848152600067ffffffffffffffff808616602084015280851660408401525060806060830152610d91608083018461083c565b9695505050505050565b86815260c060208201526000610db460c083018861083c565b73ffffffffffffffffffffffffffffffffffffffff9690961660408301525067ffffffffffffffff9384166060820152608081019290925290911660a0909101529291505056fea164736f6c6343000818000a", } var MessageHasherABI = MessageHasherMetaData.ABI diff --git a/core/gethwrappers/ccip/generated/offramp/offramp.go b/core/gethwrappers/ccip/generated/offramp/offramp.go index 72917cf943..0dd7280074 100644 --- a/core/gethwrappers/ccip/generated/offramp/offramp.go +++ b/core/gethwrappers/ccip/generated/offramp/offramp.go @@ -83,6 +83,7 @@ type InternalRampTokenAmount struct { DestTokenAddress []byte ExtraData []byte Amount *big.Int + DestExecData []byte } type InternalTokenPriceUpdate struct { @@ -163,8 +164,8 @@ type OffRampUnblessedRoot struct { } var OffRampMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CanOnlySelfCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"actual\",\"type\":\"bytes32\"}],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ExecutionError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"ForkedChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enumMultiOCR3Base.InvalidConfigErrorType\",\"name\":\"errorType\",\"type\":\"uint8\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"got\",\"type\":\"uint256\"}],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidEVMAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"internalType\":\"structOffRamp.Interval\",\"name\":\"interval\",\"type\":\"tuple\"}],\"name\":\"InvalidInterval\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"newLimit\",\"type\":\"uint256\"}],\"name\":\"InvalidManualExecutionGasLimit\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"messageDestChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidMessageDestChainSelector\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"newState\",\"type\":\"uint8\"}],\"name\":\"InvalidNewState\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRoot\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidStaticConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LeavesCannotBeEmpty\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ManualExecutionGasLimitMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"ManualExecutionNotYetEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"errorReason\",\"type\":\"bytes\"}],\"name\":\"MessageValidationError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonUniqueSignatures\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"notPool\",\"type\":\"address\"}],\"name\":\"NotACompatiblePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OracleCannotBeZeroAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ReceiverError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountReleased\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePre\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePost\",\"type\":\"uint256\"}],\"name\":\"ReleaseOrMintBalanceMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"name\":\"RootAlreadyCommitted\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"RootNotCommitted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignaturesOutOfRegistration\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"StaleCommitReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"StaticConfigCannotBeChanged\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"TokenDataMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"TokenHandlingError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnexpectedTokenData\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"WrongMessageLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WrongNumberOfSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroChainSelectorNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"AlreadyAttempted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"internalType\":\"structOffRamp.Interval\",\"name\":\"interval\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structOffRamp.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"report\",\"type\":\"tuple\"}],\"name\":\"CommitReportAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"DynamicConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"name\":\"ExecutionStateChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"RootRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"SkippedAlreadyExecutedMessage\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"sourceConfig\",\"type\":\"tuple\"}],\"name\":\"SourceChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainSelectorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"}],\"name\":\"StaticConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigUpdates\",\"type\":\"tuple[]\"}],\"name\":\"applySourceChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"destTokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structClient.Any2EVMMessage\",\"name\":\"\",\"type\":\"tuple\"}],\"name\":\"ccipReceive\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"rawVs\",\"type\":\"bytes32\"}],\"name\":\"commit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"execute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"bytes[]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[]\"}],\"name\":\"executeSingleMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"getExecutionState\",\"outputs\":[{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLatestPriceSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"getMerkleRoot\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"getSourceChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"isBlessed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"latestConfigDetails\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"n\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"}],\"internalType\":\"structMultiOCR3Base.ConfigInfo\",\"name\":\"configInfo\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfig\",\"name\":\"ocrConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage[]\",\"name\":\"messages\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[][]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[][]\"},{\"internalType\":\"bytes32[]\",\"name\":\"proofs\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"proofFlagBits\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.ExecutionReportSingleChain[]\",\"name\":\"reports\",\"type\":\"tuple[]\"},{\"internalType\":\"uint256[][]\",\"name\":\"gasLimitOverrides\",\"type\":\"uint256[][]\"}],\"name\":\"manuallyExecute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structOffRamp.UnblessedRoot[]\",\"name\":\"rootToReset\",\"type\":\"tuple[]\"}],\"name\":\"resetUnblessedRoots\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"setDynamicConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfigArgs[]\",\"name\":\"ocrConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"setOCR3Configs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x6101206040523480156200001257600080fd5b5060405162006bdd38038062006bdd8339810160408190526200003591620008c7565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf81620001fa565b5050466080525060208301516001600160a01b03161580620000ec575060408301516001600160a01b0316155b8062000103575060608301516001600160a01b0316155b1562000122576040516342bcdf7f60e11b815260040160405180910390fd5b82516001600160401b03166000036200014e5760405163c656089560e01b815260040160405180910390fd5b82516001600160401b0390811660a052602080850180516001600160a01b0390811660c05260408088018051831660e0526060808a01805185166101005283518b519098168852945184169587019590955251821690850152905116908201527f683eb52ee924eb817377cfa8f41f238f4bb7a877da5267869dfffbad85f564d89060800160405180910390a1620001e682620002a5565b620001f181620003c1565b50505062000c67565b336001600160a01b03821603620002545760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b0316620002ce576040516342bcdf7f60e11b815260040160405180910390fd5b80516004805460208085018051604080880180516060808b0180516001600160a01b039b8c166001600160c01b0319909a168a17600160a01b63ffffffff98891602176001600160c01b0316600160c01b948816949094026001600160e01b031693909317600160e01b93871693909302929092179098556080808b018051600580546001600160a01b031916918d169190911790558451988952955185169688019690965290518316918601919091525116938301939093529151909216908201527fa55bd56595c45f517e5967a3067f3dca684445a3080e7c04a4e0d5a40cda627d9060a00160405180910390a150565b60005b815181101562000666576000828281518110620003e557620003e562000a1d565b60200260200101519050600081602001519050806001600160401b0316600003620004235760405163c656089560e01b815260040160405180910390fd5b81516001600160a01b03166200044c576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160401b0381166000908152600660205260408120600181018054919291620004789062000a33565b80601f0160208091040260200160405190810160405280929190818152602001828054620004a69062000a33565b8015620004f75780601f10620004cb57610100808354040283529160200191620004f7565b820191906000526020600020905b815481529060010190602001808311620004d957829003601f168201915b5050505050905060008460600151905081516000036200059e57805160000362000534576040516342bcdf7f60e11b815260040160405180910390fd5b6001830162000544828262000ac4565b508254600160a81b600160e81b031916600160a81b1783556040516001600160401b03851681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1620005d9565b8080519060200120828051906020012014620005d95760405163c39a620560e01b81526001600160401b038516600482015260240162000083565b604080860151845487516001600160a01b03166001600160a01b0319921515600160a01b02929092166001600160a81b031990911617178455516001600160401b038516907f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b906200064d90869062000b90565b60405180910390a25050505050806001019050620003c4565b5050565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b0381118282101715620006a557620006a56200066a565b60405290565b604051601f8201601f191681016001600160401b0381118282101715620006d657620006d66200066a565b604052919050565b80516001600160401b0381168114620006f657600080fd5b919050565b6001600160a01b03811681146200071157600080fd5b50565b805163ffffffff81168114620006f657600080fd5b6000601f83601f8401126200073d57600080fd5b825160206001600160401b03808311156200075c576200075c6200066a565b8260051b6200076d838201620006ab565b93845286810183019383810190898611156200078857600080fd5b84890192505b85831015620008ba57825184811115620007a85760008081fd5b89016080601f19828d038101821315620007c25760008081fd5b620007cc62000680565b88840151620007db81620006fb565b81526040620007ec858201620006de565b8a8301526060808601518015158114620008065760008081fd5b838301529385015193898511156200081e5760008081fd5b84860195508f603f8701126200083657600094508485fd5b8a8601519450898511156200084f576200084f6200066a565b620008608b858f88011601620006ab565b93508484528f82868801011115620008785760008081fd5b60005b8581101562000898578681018301518582018d01528b016200087b565b5060009484018b0194909452509182015283525091840191908401906200078e565b9998505050505050505050565b6000806000838503610140811215620008df57600080fd5b6080811215620008ee57600080fd5b620008f862000680565b6200090386620006de565b815260208601516200091581620006fb565b602082015260408601516200092a81620006fb565b604082015260608601516200093f81620006fb565b6060820152935060a0607f19820112156200095957600080fd5b5060405160a081016001600160401b0380821183831017156200098057620009806200066a565b81604052608087015191506200099682620006fb565b818352620009a760a0880162000714565b6020840152620009ba60c0880162000714565b6040840152620009cd60e0880162000714565b60608401526101008701519150620009e582620006fb565b608083018290526101208701519294508083111562000a0357600080fd5b505062000a138682870162000729565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b600181811c9082168062000a4857607f821691505b60208210810362000a6957634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111562000abf576000816000526020600020601f850160051c8101602086101562000a9a5750805b601f850160051c820191505b8181101562000abb5782815560010162000aa6565b5050505b505050565b81516001600160401b0381111562000ae05762000ae06200066a565b62000af88162000af1845462000a33565b8462000a6f565b602080601f83116001811462000b30576000841562000b175750858301515b600019600386901b1c1916600185901b17855562000abb565b600085815260208120601f198616915b8281101562000b615788860151825594840194600190910190840162000b40565b508582101562000b805787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b602080825282546001600160a01b0381168383015260a081901c60ff161515604084015260a81c6001600160401b0316606083015260808083015260018084018054600093929190849062000be58162000a33565b8060a089015260c0600183166000811462000c09576001811462000c265762000c58565b60ff19841660c08b015260c083151560051b8b0101945062000c58565b85600052602060002060005b8481101562000c4f5781548c820185015290880190890162000c32565b8b0160c0019550505b50929998505050505050505050565b60805160a05160c05160e05161010051615f0762000cd6600039600081816102530152612c120152600081816102240152612ef80152600081816101f50152818161142f01526118400152600081816101c50152612801015260008181611dce0152611e1a0152615f076000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806385572ffb116100d8578063d2a15d351161008c578063f2fde38b11610066578063f2fde38b14610583578063f716f99f14610596578063ff888fb1146105a957600080fd5b8063d2a15d351461053d578063e9d68a8e14610550578063ece670b61461057057600080fd5b8063991a5018116100bd578063991a5018146104c5578063c673e584146104d8578063ccd37ba3146104f857600080fd5b806385572ffb1461049c5780638da5cb5b146104aa57600080fd5b80633f4b04aa1161012f5780637437ff9f116101145780637437ff9f1461038557806379ba5097146104815780637d4eef601461048957600080fd5b80633f4b04aa146103495780635e36480c1461036557600080fd5b8063181f5a7711610160578063181f5a77146102da5780632d04ab7614610323578063311cd5131461033657600080fd5b806304666f9c1461017c57806306285c6914610191575b600080fd5b61018f61018a3660046140b3565b6105cc565b005b61028360408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316815250905090565b6040516102d19190815167ffffffffffffffff1681526020808301516001600160a01b0390811691830191909152604080840151821690830152606092830151169181019190915260800190565b60405180910390f35b6103166040518060400160405280601181526020017f4f666652616d7020312e362e302d64657600000000000000000000000000000081525081565b6040516102d19190614222565b61018f6103313660046142cd565b6105e0565b61018f610344366004614380565b6109c0565b60095460405167ffffffffffffffff90911681526020016102d1565b6103786103733660046143d4565b610a29565b6040516102d19190614431565b6104246040805160a081018252600080825260208201819052918101829052606081018290526080810191909152506040805160a0810182526004546001600160a01b03808216835263ffffffff600160a01b83048116602085015278010000000000000000000000000000000000000000000000008304811694840194909452600160e01b9091049092166060820152600554909116608082015290565b6040516102d19190600060a0820190506001600160a01b03808451168352602084015163ffffffff808216602086015280604087015116604086015280606087015116606086015250508060808501511660808401525092915050565b61018f610a7f565b61018f610497366004614986565b610b3d565b61018f610177366004614ab1565b6000546040516001600160a01b0390911681526020016102d1565b61018f6104d3366004614b00565b610cdd565b6104eb6104e6366004614b85565b610cee565b6040516102d19190614be5565b61052f610506366004614c5a565b67ffffffffffffffff919091166000908152600860209081526040808320938352929052205490565b6040519081526020016102d1565b61018f61054b366004614c84565b610e4c565b61056361055e366004614cf9565b610f06565b6040516102d19190614d14565b61018f61057e366004614d62565b611013565b61018f610591366004614dbe565b611386565b61018f6105a4366004614e43565b611397565b6105bc6105b7366004614f81565b6113d9565b60405190151581526020016102d1565b6105d461149a565b6105dd816114f6565b50565b60006105ee8789018961510a565b8051515190915015158061060757508051602001515115155b156107075760095460208a01359067ffffffffffffffff808316911610156106c6576009805467ffffffffffffffff191667ffffffffffffffff83161790556004805483516040517f3937306f0000000000000000000000000000000000000000000000000000000081526001600160a01b0390921692633937306f9261068f929101615348565b600060405180830381600087803b1580156106a957600080fd5b505af11580156106bd573d6000803e3d6000fd5b50505050610705565b816020015151600003610705576040517f2261116700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b60005b8160200151518110156109095760008260200151828151811061072f5761072f615275565b6020026020010151905060008160000151905061074b816117f4565b6000610756826118f6565b602084015151815491925067ffffffffffffffff908116600160a81b9092041614158061079a575060208084015190810151905167ffffffffffffffff9182169116115b156107e357825160208401516040517feefb0cac0000000000000000000000000000000000000000000000000000000081526107da92919060040161535b565b60405180910390fd5b60408301518061081f576040517f504570e300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b835167ffffffffffffffff166000908152600860209081526040808320848452909152902054156108925783516040517f32cf0cbf00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602481018290526044016107da565b60208085015101516108a59060016153a6565b82547fffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffff16600160a81b67ffffffffffffffff92831602179092559251166000908152600860209081526040808320948352939052919091204290555060010161070a565b507f3a3950e13dd607cc37980db0ef14266c40d2bba9c01b2e44bfe549808883095d8160405161093991906153ce565b60405180910390a16109b560008a8a8a8a8a8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808e0282810182019093528d82529093508d92508c9182918501908490808284376000920191909152508b925061195d915050565b505050505050505050565b610a006109cf8284018461546b565b60408051600080825260208201909252906109fa565b60608152602001906001900390816109e55790505b50611cd4565b604080516000808252602082019092529050610a2360018585858586600061195d565b50505050565b6000610a37600160046154a0565b6002610a446080856154c9565b67ffffffffffffffff16610a5891906154f0565b610a628585611d84565b901c166003811115610a7657610a76614407565b90505b92915050565b6001546001600160a01b03163314610ad95760405162461bcd60e51b815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064016107da565b600080543373ffffffffffffffffffffffffffffffffffffffff19808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610b45611dcb565b815181518114610b81576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015610ccd576000848281518110610ba057610ba0615275565b60200260200101519050600081602001515190506000858481518110610bc857610bc8615275565b6020026020010151905080518214610c0c576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b82811015610cbe576000828281518110610c2b57610c2b615275565b6020026020010151905080600014610cb55784602001518281518110610c5357610c53615275565b602002602001015160800151811015610cb55784516040517fc8e9605100000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260248101839052604481018290526064016107da565b50600101610c0f565b50505050806001019050610b84565b50610cd88383611cd4565b505050565b610ce561149a565b6105dd81611e4c565b610d316040805160e081019091526000606082018181526080830182905260a0830182905260c08301919091528190815260200160608152602001606081525090565b60ff808316600090815260026020818152604092839020835160e081018552815460608201908152600183015480881660808401526101008104881660a0840152620100009004909616151560c082015294855291820180548451818402810184019095528085529293858301939092830182828015610dda57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610dbc575b5050505050815260200160038201805480602002602001604051908101604052809291908181526020018280548015610e3c57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610e1e575b5050505050815250509050919050565b610e5461149a565b60005b81811015610cd8576000838383818110610e7357610e73615275565b905060400201803603810190610e899190615507565b9050610e9881602001516113d9565b610efd57805167ffffffffffffffff1660009081526008602090815260408083208285018051855290835281842093909355915191519182527f202f1139a3e334b6056064c0e9b19fd07e44a88d8f6e5ded571b24cf8c371f12910160405180910390a15b50600101610e57565b604080516080808201835260008083526020808401829052838501829052606080850181905267ffffffffffffffff878116845260068352928690208651948501875280546001600160a01b0381168652600160a01b810460ff16151593860193909352600160a81b909204909216948301949094526001840180549394929391840191610f9390615540565b80601f0160208091040260200160405190810160405280929190818152602001828054610fbf90615540565b8015610e3c5780601f10610fe157610100808354040283529160200191610e3c565b820191906000526020600020905b815481529060010190602001808311610fef57505050919092525091949350505050565b33301461104c576040517f371a732800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160008082526020820190925281611089565b60408051808201909152600080825260208201528152602001906001900390816110625790505b5060a085015151909150156110bd576110ba8460a00151856020015186606001518760000151602001518787611fb2565b90505b6040805160a0810182528551518152855160209081015167ffffffffffffffff16818301528087015183516000948401926110f9929101614222565b60408051601f19818403018152918152908252878101516020830152018390526005549091506001600160a01b03168015611206576040517f08d450a10000000000000000000000000000000000000000000000000000000081526001600160a01b038216906308d450a19061117390859060040161561c565b600060405180830381600087803b15801561118d57600080fd5b505af192505050801561119e575060015b611206573d8080156111cc576040519150601f19603f3d011682016040523d82523d6000602084013e6111d1565b606091505b50806040517f09c253250000000000000000000000000000000000000000000000000000000081526004016107da9190614222565b60408601515115801561121b57506080860151155b80611232575060608601516001600160a01b03163b155b8061127257506060860151611270906001600160a01b03167f85572ffb000000000000000000000000000000000000000000000000000000006120d1565b155b1561127f57505050505050565b855160209081015167ffffffffffffffff1660009081526006909152604080822054608089015160608a015192517f3cf9798300000000000000000000000000000000000000000000000000000000815284936001600160a01b0390931692633cf97983926112f7928992611388929160040161562f565b6000604051808303816000875af1158015611316573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261133e919081019061566b565b50915091508161137c57806040517f0a8d6e8c0000000000000000000000000000000000000000000000000000000081526004016107da9190614222565b5050505050505050565b61138e61149a565b6105dd816120ed565b61139f61149a565b60005b81518110156113d5576113cd8282815181106113c0576113c0615275565b60200260200101516121a3565b6001016113a2565b5050565b6040805180820182523081526020810183815291517f4d61677100000000000000000000000000000000000000000000000000000000815290516001600160a01b039081166004830152915160248201526000917f00000000000000000000000000000000000000000000000000000000000000001690634d61677190604401602060405180830381865afa158015611476573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a799190615701565b6000546001600160a01b031633146114f45760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016107da565b565b60005b81518110156113d557600082828151811061151657611516615275565b602002602001015190506000816020015190508067ffffffffffffffff1660000361156d576040517fc656089500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81516001600160a01b0316611595576040516342bcdf7f60e11b815260040160405180910390fd5b67ffffffffffffffff811660009081526006602052604081206001810180549192916115c090615540565b80601f01602080910402602001604051908101604052809291908181526020018280546115ec90615540565b80156116395780601f1061160e57610100808354040283529160200191611639565b820191906000526020600020905b81548152906001019060200180831161161c57829003601f168201915b5050505050905060008460600151905081516000036116f1578051600003611674576040516342bcdf7f60e11b815260040160405180910390fd5b600183016116828282615766565b5082547fffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffff16600160a81b17835560405167ffffffffffffffff851681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1611744565b8080519060200120828051906020012014611744576040517fc39a620500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff851660048201526024016107da565b604080860151845487516001600160a01b031673ffffffffffffffffffffffffffffffffffffffff19921515600160a01b02929092167fffffffffffffffffffffff000000000000000000000000000000000000000000909116171784555167ffffffffffffffff8516907f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b906117dc908690615826565b60405180910390a250505050508060010190506114f9565b6040517f2cbc26bb000000000000000000000000000000000000000000000000000000008152608082901b77ffffffffffffffff000000000000000000000000000000001660048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632cbc26bb90602401602060405180830381865afa15801561188f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118b39190615701565b156105dd576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff821660048201526024016107da565b67ffffffffffffffff811660009081526006602052604081208054600160a01b900460ff16610a79576040517fed053c5900000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024016107da565b60ff878116600090815260026020908152604080832081516080810183528154815260019091015480861693820193909352610100830485169181019190915262010000909104909216151560608301528735906119bc8760a46158f4565b9050826060015115611a045784516119d59060206154f0565b86516119e29060206154f0565b6119ed9060a06158f4565b6119f791906158f4565b611a0190826158f4565b90505b368114611a46576040517f8e1192e1000000000000000000000000000000000000000000000000000000008152600481018290523660248201526044016107da565b5081518114611a8e5781516040517f93df584c0000000000000000000000000000000000000000000000000000000081526004810191909152602481018290526044016107da565b611a96611dcb565b60ff808a1660009081526003602090815260408083203384528252808320815180830190925280548086168352939491939092840191610100909104166002811115611ae457611ae4614407565b6002811115611af557611af5614407565b9052509050600281602001516002811115611b1257611b12614407565b148015611b665750600260008b60ff1660ff168152602001908152602001600020600301816000015160ff1681548110611b4e57611b4e615275565b6000918252602090912001546001600160a01b031633145b611b9c576040517fda0f08e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50816060015115611c7e576020820151611bb7906001615907565b60ff16855114611bf3576040517f71253a2500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8351855114611c2e576040517fa75d88af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008787604051611c40929190615920565b604051908190038120611c57918b90602001615930565b604051602081830303815290604052805190602001209050611c7c8a828888886124e7565b505b6040805182815260208a81013567ffffffffffffffff169082015260ff8b16917f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef0910160405180910390a2505050505050505050565b8151600003611d0e576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160408051600080825260208201909252911591905b8451811015611d7d57611d75858281518110611d4357611d43615275565b602002602001015184611d6f57858381518110611d6257611d62615275565b60200260200101516126f4565b836126f4565b600101611d25565b5050505050565b67ffffffffffffffff8216600090815260076020526040812081611da9608085615944565b67ffffffffffffffff1681526020810191909152604001600020549392505050565b467f0000000000000000000000000000000000000000000000000000000000000000146114f4576040517f0f01ce850000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060048201524660248201526044016107da565b80516001600160a01b0316611e74576040516342bcdf7f60e11b815260040160405180910390fd5b80516004805460208085018051604080880180516060808b0180516001600160a01b039b8c167fffffffffffffffff000000000000000000000000000000000000000000000000909a168a17600160a01b63ffffffff988916021777ffffffffffffffffffffffffffffffffffffffffffffffff167801000000000000000000000000000000000000000000000000948816949094026001600160e01b031693909317600160e01b93871693909302929092179098556080808b0180516005805473ffffffffffffffffffffffffffffffffffffffff1916918d169190911790558451988952955185169688019690965290518316918601919091525116938301939093529151909216908201527fa55bd56595c45f517e5967a3067f3dca684445a3080e7c04a4e0d5a40cda627d9060a00160405180910390a150565b6060865167ffffffffffffffff811115611fce57611fce613eca565b60405190808252806020026020018201604052801561201357816020015b6040805180820190915260008082526020820152815260200190600190039081611fec5790505b50905060005b87518110156120c5576120a088828151811061203757612037615275565b602002602001015188888888888781811061205457612054615275565b9050602002810190612066919061596b565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612e9792505050565b8282815181106120b2576120b2615275565b6020908102919091010152600101612019565b505b9695505050505050565b60006120dc8361323c565b8015610a765750610a7683836132a0565b336001600160a01b038216036121455760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016107da565b6001805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b806040015160ff166000036121ce576000604051631b3fab5160e11b81526004016107da91906159d0565b60208082015160ff8082166000908152600290935260408320600181015492939092839216900361223b57606084015160018201805491151562010000027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff909216919091179055612290565b6060840151600182015460ff6201000090910416151590151514612290576040517f87f6037c00000000000000000000000000000000000000000000000000000000815260ff841660048201526024016107da565b60a08401518051601f60ff821611156122bf576001604051631b3fab5160e11b81526004016107da91906159d0565b612325858560030180548060200260200160405190810160405280929190818152602001828054801561231b57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116122fd575b505050505061335b565b85606001511561245457612393858560020180548060200260200160405190810160405280929190818152602001828054801561231b576020028201919060005260206000209081546001600160a01b031681526001909101906020018083116122fd57505050505061335b565b608086015180516123ad9060028701906020840190613e24565b5080516001850180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1661010060ff841690810291909117909155601f101561240d576002604051631b3fab5160e11b81526004016107da91906159d0565b604088015161241d9060036159ea565b60ff168160ff1611612445576003604051631b3fab5160e11b81526004016107da91906159d0565b612451878360016133c4565b50505b612460858360026133c4565b81516124759060038601906020850190613e24565b5060408681015160018501805460ff191660ff8316179055875180865560a089015192517fab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f547936124ce938a939260028b01929190615a06565b60405180910390a16124df85613544565b505050505050565b6124ef613e96565b835160005b8181101561137c57600060018886846020811061251357612513615275565b61252091901a601b615907565b89858151811061253257612532615275565b602002602001015189868151811061254c5761254c615275565b60200260200101516040516000815260200160405260405161258a949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa1580156125ac573d6000803e3d6000fd5b505060408051601f1981015160ff808e166000908152600360209081528582206001600160a01b0385168352815285822085870190965285548084168652939750909550929392840191610100900416600281111561260d5761260d614407565b600281111561261e5761261e614407565b905250905060018160200151600281111561263b5761263b614407565b14612672576040517fca31867a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051859060ff16601f811061268957612689615275565b6020020151156126c5576040517ff67bc7c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600185826000015160ff16601f81106126e0576126e0615275565b9115156020909202015250506001016124f4565b81516126ff816117f4565b600061270a826118f6565b602085015151909150600081900361274d576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b846040015151811461278b576040517f57e0e08300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008167ffffffffffffffff8111156127a6576127a6613eca565b6040519080825280602002602001820160405280156127cf578160200160208202803683370190505b50905060005b82811015612944576000876020015182815181106127f5576127f5615275565b602002602001015190507f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681600001516040015167ffffffffffffffff161461288857805160409081015190517f38432a2200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016107da565b61291e8186600101805461289b90615540565b80601f01602080910402602001604051908101604052809291908181526020018280546128c790615540565b80156129145780601f106128e957610100808354040283529160200191612914565b820191906000526020600020905b8154815290600101906020018083116128f757829003601f168201915b5050505050613560565b83838151811061293057612930615275565b6020908102919091010152506001016127d5565b50600061295b858389606001518a60800151613682565b9050806000036129a3576040517f7dd17a7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff861660048201526024016107da565b8551151560005b848110156109b55760005a905060008a6020015183815181106129cf576129cf615275565b6020026020010151905060006129ed8a836000015160600151610a29565b90506000816003811115612a0357612a03614407565b1480612a2057506003816003811115612a1e57612a1e614407565b145b612a78578151606001516040805167ffffffffffffffff808e16825290921660208301527f3b575419319662b2a6f5e2467d84521517a3382b908eb3d557bb3fdb0c50e23c91015b60405180910390a1505050612e8f565b8415612b4857600454600090600160a01b900463ffffffff16612a9b88426154a0565b1190508080612abb57506003826003811115612ab957612ab9614407565b145b612afd576040517fa9cfc86200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8c1660048201526024016107da565b8b8581518110612b0f57612b0f615275565b6020026020010151600014612b42578b8581518110612b3057612b30615275565b60200260200101518360800181815250505b50612ba9565b6000816003811115612b5c57612b5c614407565b14612ba9578151606001516040805167ffffffffffffffff808e16825290921660208301527f3ef2a99c550a751d4b0b261268f05a803dfb049ab43616a1ffb388f61fe651209101612a68565b81516080015167ffffffffffffffff1615612c98576000816003811115612bd257612bd2614407565b03612c985781516080015160208301516040517fe0e03cae0000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169263e0e03cae92612c49928f929190600401615ab2565b6020604051808303816000875af1158015612c68573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c8c9190615701565b612c9857505050612e8f565b60008c604001518581518110612cb057612cb0615275565b6020026020010151905080518360a001515114612d14578251606001516040517f1cfe6d8b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808e16600483015290911660248201526044016107da565b612d288b84600001516060015160016136d8565b600080612d358584613780565b91509150612d4c8d866000015160600151846136d8565b8715612dbc576003826003811115612d6657612d66614407565b03612dbc576000846003811115612d7f57612d7f614407565b14612dbc578451516040517f2b11b8d90000000000000000000000000000000000000000000000000000000081526107da91908390600401615adf565b6002826003811115612dd057612dd0614407565b14612e2a576003826003811115612de957612de9614407565b14612e2a578451606001516040517f926c5a3e0000000000000000000000000000000000000000000000000000000081526107da918f918590600401615af8565b8451805160609091015167ffffffffffffffff908116908f167fdc8ccbc35e0eebd81239bcd1971fcd53c7eb34034880142a0f43c809a458732f85855a612e71908d6154a0565b604051612e8093929190615b1e565b60405180910390a45050505050505b6001016129aa565b60408051808201909152600080825260208201526000612eba876020015161384a565b6040517fbbe4f6db0000000000000000000000000000000000000000000000000000000081526001600160a01b0380831660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063bbe4f6db90602401602060405180830381865afa158015612f3f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f639190615b4e565b90506001600160a01b0381161580612fab5750612fa96001600160a01b0382167faff2afbf000000000000000000000000000000000000000000000000000000006120d1565b155b15612fed576040517fae9b4ce90000000000000000000000000000000000000000000000000000000081526001600160a01b03821660048201526024016107da565b600454600090819061300f9089908690600160e01b900463ffffffff166138f0565b9150915060008060006130dc6040518061010001604052808e81526020018c67ffffffffffffffff1681526020018d6001600160a01b031681526020018f606001518152602001896001600160a01b031681526020018f6000015181526020018f6040015181526020018b81525060405160240161308d9190615b6b565b60408051601f198184030181529190526020810180516001600160e01b03167f390775370000000000000000000000000000000000000000000000000000000017905287866113886084613a1e565b9250925092508261311b57816040517fe1cd55090000000000000000000000000000000000000000000000000000000081526004016107da9190614222565b81516020146131635781516040517f78ef80240000000000000000000000000000000000000000000000000000000081526020600482015260248101919091526044016107da565b6000828060200190518101906131799190615c38565b9050866001600160a01b03168c6001600160a01b03161461320e5760006131aa8d8a6131a5868a6154a0565b6138f0565b509050868110806131c45750816131c188836154a0565b14155b1561320c576040517fa966e21f0000000000000000000000000000000000000000000000000000000081526004810183905260248101889052604481018290526064016107da565b505b604080518082019091526001600160a01b039098168852602088015250949550505050505095945050505050565b6000613268827f01ffc9a7000000000000000000000000000000000000000000000000000000006132a0565b8015610a795750613299827fffffffff000000000000000000000000000000000000000000000000000000006132a0565b1592915050565b6040517fffffffff0000000000000000000000000000000000000000000000000000000082166024820152600090819060440160408051601f19818403018152919052602080820180516001600160e01b03167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825192935060009283928392909183918a617530fa92503d91506000519050828015613344575060208210155b80156133505750600081115b979650505050505050565b60005b8151811015610cd85760ff83166000908152600360205260408120835190919084908490811061339057613390615275565b6020908102919091018101516001600160a01b03168252810191909152604001600020805461ffff1916905560010161335e565b60005b82518160ff161015610a23576000838260ff16815181106133ea576133ea615275565b602002602001015190506000600281111561340757613407614407565b60ff80871660009081526003602090815260408083206001600160a01b0387168452909152902054610100900416600281111561344657613446614407565b14613467576004604051631b3fab5160e11b81526004016107da91906159d0565b6001600160a01b0381166134a7576040517fd6c62c9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052808360ff1681526020018460028111156134cd576134cd614407565b905260ff80871660009081526003602090815260408083206001600160a01b0387168452825290912083518154931660ff198416811782559184015190929091839161ffff19161761010083600281111561352a5761352a614407565b0217905550905050508061353d90615c51565b90506133c7565b60ff81166105dd576009805467ffffffffffffffff1916905550565b8151602080820151604092830151925160009384936135a6937f2425b0b9f9054c76ff151b0a175b18f37a4a4e82013a72e9f15c9caa095ed21f93909291889101615c70565b60408051601f1981840301815290829052805160209182012086518051888401516060808b0151908401516080808d015195015195976135ef9794969395929491939101615ca3565b604051602081830303815290604052805190602001208560400151805190602001208660a001516040516020016136269190615d9a565b60408051601f198184030181528282528051602091820120908301969096528101939093526060830191909152608082015260a081019190915260c0015b60405160208183030381529060405280519060200120905092915050565b600080613690858585613b44565b905061369b816113d9565b6136a95760009150506136d0565b67ffffffffffffffff86166000908152600860209081526040808320938352929052205490505b949350505050565b600060026136e76080856154c9565b67ffffffffffffffff166136fb91906154f0565b905060006137098585611d84565b905081613718600160046154a0565b901b19168183600381111561372f5761372f614407565b67ffffffffffffffff871660009081526007602052604081209190921b9290921791829161375e608088615944565b67ffffffffffffffff1681526020810191909152604001600020555050505050565b6040517fece670b6000000000000000000000000000000000000000000000000000000008152600090606090309063ece670b6906137c49087908790600401615dfa565b600060405180830381600087803b1580156137de57600080fd5b505af19250505080156137ef575060015b61382e573d80801561381d576040519150601f19603f3d011682016040523d82523d6000602084013e613822565b606091505b50600392509050613843565b50506040805160208101909152600081526002905b9250929050565b6000815160201461388957816040517f8d666f600000000000000000000000000000000000000000000000000000000081526004016107da9190614222565b60008280602001905181019061389f9190615c38565b90506001600160a01b038111806138b7575061040081105b15610a7957826040517f8d666f600000000000000000000000000000000000000000000000000000000081526004016107da9190614222565b600080600080600061396a8860405160240161391b91906001600160a01b0391909116815260200190565b60408051601f198184030181529190526020810180516001600160e01b03167f70a082310000000000000000000000000000000000000000000000000000000017905288886113886084613a1e565b925092509250826139a957816040517fe1cd55090000000000000000000000000000000000000000000000000000000081526004016107da9190614222565b60208251146139f15781516040517f78ef80240000000000000000000000000000000000000000000000000000000081526020600482015260248101919091526044016107da565b81806020019051810190613a059190615c38565b613a0f82886154a0565b94509450505050935093915050565b6000606060008361ffff1667ffffffffffffffff811115613a4157613a41613eca565b6040519080825280601f01601f191660200182016040528015613a6b576020820181803683370190505b509150863b613a9e577f0c3b563c0000000000000000000000000000000000000000000000000000000060005260046000fd5b5a85811015613ad1577fafa32a2c0000000000000000000000000000000000000000000000000000000060005260046000fd5b8590036040810481038710613b0a577f37c3be290000000000000000000000000000000000000000000000000000000060005260046000fd5b505a6000808a5160208c0160008c8cf193505a900390503d84811115613b2d5750835b808352806000602085013e50955095509592505050565b8251825160009190818303613b85576040517f11a6b26400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6101018211801590613b9957506101018111155b613bb6576040516309bde33960e01b815260040160405180910390fd5b60001982820101610100811115613be0576040516309bde33960e01b815260040160405180910390fd5b80600003613c0d5786600081518110613bfb57613bfb615275565b60200260200101519350505050613ddc565b60008167ffffffffffffffff811115613c2857613c28613eca565b604051908082528060200260200182016040528015613c51578160200160208202803683370190505b50905060008080805b85811015613d7b5760006001821b8b811603613cb55788851015613c9e578c5160018601958e918110613c8f57613c8f615275565b60200260200101519050613cd7565b8551600185019487918110613c8f57613c8f615275565b8b5160018401938d918110613ccc57613ccc615275565b602002602001015190505b600089861015613d07578d5160018701968f918110613cf857613cf8615275565b60200260200101519050613d29565b8651600186019588918110613d1e57613d1e615275565b602002602001015190505b82851115613d4a576040516309bde33960e01b815260040160405180910390fd5b613d548282613de3565b878481518110613d6657613d66615275565b60209081029190910101525050600101613c5a565b506001850382148015613d8d57508683145b8015613d9857508581145b613db5576040516309bde33960e01b815260040160405180910390fd5b836001860381518110613dca57613dca615275565b60200260200101519750505050505050505b9392505050565b6000818310613dfb57613df68284613e01565b610a76565b610a7683835b604080516001602082015290810183905260608101829052600090608001613664565b828054828255906000526020600020908101928215613e86579160200282015b82811115613e86578251825473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03909116178255602090920191600190910190613e44565b50613e92929150613eb5565b5090565b604051806103e00160405280601f906020820280368337509192915050565b5b80821115613e925760008155600101613eb6565b634e487b7160e01b600052604160045260246000fd5b6040516080810167ffffffffffffffff81118282101715613f0357613f03613eca565b60405290565b60405160a0810167ffffffffffffffff81118282101715613f0357613f03613eca565b60405160c0810167ffffffffffffffff81118282101715613f0357613f03613eca565b6040805190810167ffffffffffffffff81118282101715613f0357613f03613eca565b6040516060810167ffffffffffffffff81118282101715613f0357613f03613eca565b604051601f8201601f1916810167ffffffffffffffff81118282101715613fbe57613fbe613eca565b604052919050565b600067ffffffffffffffff821115613fe057613fe0613eca565b5060051b60200190565b6001600160a01b03811681146105dd57600080fd5b803567ffffffffffffffff8116811461401757600080fd5b919050565b80151581146105dd57600080fd5b80356140178161401c565b600067ffffffffffffffff82111561404f5761404f613eca565b50601f01601f191660200190565b600082601f83011261406e57600080fd5b813561408161407c82614035565b613f95565b81815284602083860101111561409657600080fd5b816020850160208301376000918101602001919091529392505050565b600060208083850312156140c657600080fd5b823567ffffffffffffffff808211156140de57600080fd5b818501915085601f8301126140f257600080fd5b813561410061407c82613fc6565b81815260059190911b8301840190848101908883111561411f57600080fd5b8585015b838110156141c55780358581111561413b5760008081fd5b86016080818c03601f19018113156141535760008081fd5b61415b613ee0565b8983013561416881613fea565b81526040614177848201613fff565b8b83015260608085013561418a8161401c565b838301529284013592898411156141a357600091508182fd5b6141b18f8d8688010161405d565b908301525085525050918601918601614123565b5098975050505050505050565b60005b838110156141ed5781810151838201526020016141d5565b50506000910152565b6000815180845261420e8160208601602086016141d2565b601f01601f19169290920160200192915050565b602081526000610a7660208301846141f6565b8060608101831015610a7957600080fd5b60008083601f84011261425857600080fd5b50813567ffffffffffffffff81111561427057600080fd5b60208301915083602082850101111561384357600080fd5b60008083601f84011261429a57600080fd5b50813567ffffffffffffffff8111156142b257600080fd5b6020830191508360208260051b850101111561384357600080fd5b60008060008060008060008060e0898b0312156142e957600080fd5b6142f38a8a614235565b9750606089013567ffffffffffffffff8082111561431057600080fd5b61431c8c838d01614246565b909950975060808b013591508082111561433557600080fd5b6143418c838d01614288565b909750955060a08b013591508082111561435a57600080fd5b506143678b828c01614288565b999c989b50969995989497949560c00135949350505050565b60008060006080848603121561439557600080fd5b61439f8585614235565b9250606084013567ffffffffffffffff8111156143bb57600080fd5b6143c786828701614246565b9497909650939450505050565b600080604083850312156143e757600080fd5b6143f083613fff565b91506143fe60208401613fff565b90509250929050565b634e487b7160e01b600052602160045260246000fd5b6004811061442d5761442d614407565b9052565b60208101610a79828461441d565b600060a0828403121561445157600080fd5b614459613f09565b90508135815261446b60208301613fff565b602082015261447c60408301613fff565b604082015261448d60608301613fff565b606082015261449e60808301613fff565b608082015292915050565b803561401781613fea565b600082601f8301126144c557600080fd5b813560206144d561407c83613fc6565b82815260059290921b840181019181810190868411156144f457600080fd5b8286015b848110156120c557803567ffffffffffffffff808211156145195760008081fd5b8189019150608080601f19848d030112156145345760008081fd5b61453c613ee0565b878401358381111561454e5760008081fd5b61455c8d8a8388010161405d565b825250604080850135848111156145735760008081fd5b6145818e8b8389010161405d565b8a840152506060808601358581111561459a5760008081fd5b6145a88f8c838a010161405d565b92840192909252949092013593810193909352505083529183019183016144f8565b600061014082840312156145dd57600080fd5b6145e5613f2c565b90506145f1838361443f565b815260a082013567ffffffffffffffff8082111561460e57600080fd5b61461a8583860161405d565b602084015260c084013591508082111561463357600080fd5b61463f8583860161405d565b604084015261465060e085016144a9565b6060840152610100840135608084015261012084013591508082111561467557600080fd5b50614682848285016144b4565b60a08301525092915050565b600082601f83011261469f57600080fd5b813560206146af61407c83613fc6565b82815260059290921b840181019181810190868411156146ce57600080fd5b8286015b848110156120c557803567ffffffffffffffff8111156146f25760008081fd5b6147008986838b01016145ca565b8452509183019183016146d2565b600082601f83011261471f57600080fd5b8135602061472f61407c83613fc6565b82815260059290921b8401810191818101908684111561474e57600080fd5b8286015b848110156120c557803567ffffffffffffffff8082111561477257600080fd5b818901915089603f83011261478657600080fd5b8582013561479661407c82613fc6565b81815260059190911b830160400190878101908c8311156147b657600080fd5b604085015b838110156147ef578035858111156147d257600080fd5b6147e18f6040838a010161405d565b8452509189019189016147bb565b50875250505092840192508301614752565b600082601f83011261481257600080fd5b8135602061482261407c83613fc6565b8083825260208201915060208460051b87010193508684111561484457600080fd5b602086015b848110156120c55780358352918301918301614849565b600082601f83011261487157600080fd5b8135602061488161407c83613fc6565b82815260059290921b840181019181810190868411156148a057600080fd5b8286015b848110156120c557803567ffffffffffffffff808211156148c55760008081fd5b818901915060a080601f19848d030112156148e05760008081fd5b6148e8613f09565b6148f3888501613fff565b8152604080850135848111156149095760008081fd5b6149178e8b8389010161468e565b8a84015250606080860135858111156149305760008081fd5b61493e8f8c838a010161470e565b83850152506080915081860135858111156149595760008081fd5b6149678f8c838a0101614801565b91840191909152509190930135908301525083529183019183016148a4565b600080604080848603121561499a57600080fd5b833567ffffffffffffffff808211156149b257600080fd5b6149be87838801614860565b94506020915081860135818111156149d557600080fd5b8601601f810188136149e657600080fd5b80356149f461407c82613fc6565b81815260059190911b8201840190848101908a831115614a1357600080fd5b8584015b83811015614a9f57803586811115614a2f5760008081fd5b8501603f81018d13614a415760008081fd5b87810135614a5161407c82613fc6565b81815260059190911b82018a0190898101908f831115614a715760008081fd5b928b01925b82841015614a8f5783358252928a0192908a0190614a76565b8652505050918601918601614a17565b50809750505050505050509250929050565b600060208284031215614ac357600080fd5b813567ffffffffffffffff811115614ada57600080fd5b820160a08185031215613ddc57600080fd5b803563ffffffff8116811461401757600080fd5b600060a08284031215614b1257600080fd5b614b1a613f09565b8235614b2581613fea565b8152614b3360208401614aec565b6020820152614b4460408401614aec565b6040820152614b5560608401614aec565b60608201526080830135614b6881613fea565b60808201529392505050565b803560ff8116811461401757600080fd5b600060208284031215614b9757600080fd5b610a7682614b74565b60008151808452602080850194506020840160005b83811015614bda5781516001600160a01b031687529582019590820190600101614bb5565b509495945050505050565b60208152600082518051602084015260ff602082015116604084015260ff604082015116606084015260608101511515608084015250602083015160c060a0840152614c3460e0840182614ba0565b90506040840151601f198483030160c0850152614c518282614ba0565b95945050505050565b60008060408385031215614c6d57600080fd5b614c7683613fff565b946020939093013593505050565b60008060208385031215614c9757600080fd5b823567ffffffffffffffff80821115614caf57600080fd5b818501915085601f830112614cc357600080fd5b813581811115614cd257600080fd5b8660208260061b8501011115614ce757600080fd5b60209290920196919550909350505050565b600060208284031215614d0b57600080fd5b610a7682613fff565b602081526001600160a01b03825116602082015260208201511515604082015267ffffffffffffffff6040830151166060820152600060608301516080808401526136d060a08401826141f6565b600080600060408486031215614d7757600080fd5b833567ffffffffffffffff80821115614d8f57600080fd5b614d9b878388016145ca565b94506020860135915080821115614db157600080fd5b506143c786828701614288565b600060208284031215614dd057600080fd5b8135613ddc81613fea565b600082601f830112614dec57600080fd5b81356020614dfc61407c83613fc6565b8083825260208201915060208460051b870101935086841115614e1e57600080fd5b602086015b848110156120c5578035614e3681613fea565b8352918301918301614e23565b60006020808385031215614e5657600080fd5b823567ffffffffffffffff80821115614e6e57600080fd5b818501915085601f830112614e8257600080fd5b8135614e9061407c82613fc6565b81815260059190911b83018401908481019088831115614eaf57600080fd5b8585015b838110156141c557803585811115614eca57600080fd5b860160c0818c03601f19011215614ee15760008081fd5b614ee9613f2c565b8882013581526040614efc818401614b74565b8a8301526060614f0d818501614b74565b8284015260809150614f2082850161402a565b9083015260a08381013589811115614f385760008081fd5b614f468f8d83880101614ddb565b838501525060c0840135915088821115614f605760008081fd5b614f6e8e8c84870101614ddb565b9083015250845250918601918601614eb3565b600060208284031215614f9357600080fd5b5035919050565b80356001600160e01b038116811461401757600080fd5b600082601f830112614fc257600080fd5b81356020614fd261407c83613fc6565b82815260069290921b84018101918181019086841115614ff157600080fd5b8286015b848110156120c5576040818903121561500e5760008081fd5b615016613f4f565b61501f82613fff565b815261502c858301614f9a565b81860152835291830191604001614ff5565b600082601f83011261504f57600080fd5b8135602061505f61407c83613fc6565b82815260079290921b8401810191818101908684111561507e57600080fd5b8286015b848110156120c557808803608081121561509c5760008081fd5b6150a4613f72565b6150ad83613fff565b8152604080601f19840112156150c35760008081fd5b6150cb613f4f565b92506150d8878501613fff565b83526150e5818501613fff565b8388015281870192909252606083013591810191909152835291830191608001615082565b6000602080838503121561511d57600080fd5b823567ffffffffffffffff8082111561513557600080fd5b8185019150604080838803121561514b57600080fd5b615153613f4f565b83358381111561516257600080fd5b84016040818a03121561517457600080fd5b61517c613f4f565b81358581111561518b57600080fd5b8201601f81018b1361519c57600080fd5b80356151aa61407c82613fc6565b81815260069190911b8201890190898101908d8311156151c957600080fd5b928a01925b828410156152195787848f0312156151e65760008081fd5b6151ee613f4f565b84356151f981613fea565b8152615206858d01614f9a565b818d0152825292870192908a01906151ce565b84525050508187013593508484111561523157600080fd5b61523d8a858401614fb1565b818801528252508385013591508282111561525757600080fd5b6152638883860161503e565b85820152809550505050505092915050565b634e487b7160e01b600052603260045260246000fd5b805160408084528151848201819052600092602091908201906060870190855b818110156152e257835180516001600160a01b031684528501516001600160e01b03168584015292840192918501916001016152ab565b50508583015187820388850152805180835290840192506000918401905b8083101561533c578351805167ffffffffffffffff1683528501516001600160e01b031685830152928401926001929092019190850190615300565b50979650505050505050565b602081526000610a76602083018461528b565b67ffffffffffffffff8316815260608101613ddc6020830184805167ffffffffffffffff908116835260209182015116910152565b634e487b7160e01b600052601160045260246000fd5b67ffffffffffffffff8181168382160190808211156153c7576153c7615390565b5092915050565b6000602080835260608451604080848701526153ed606087018361528b565b87850151878203601f19016040890152805180835290860193506000918601905b808310156141c557845167ffffffffffffffff81511683528781015161544d89850182805167ffffffffffffffff908116835260209182015116910152565b5084015182870152938601936001929092019160809091019061540e565b60006020828403121561547d57600080fd5b813567ffffffffffffffff81111561549457600080fd5b6136d084828501614860565b81810381811115610a7957610a79615390565b634e487b7160e01b600052601260045260246000fd5b600067ffffffffffffffff808416806154e4576154e46154b3565b92169190910692915050565b8082028115828204841417610a7957610a79615390565b60006040828403121561551957600080fd5b615521613f4f565b61552a83613fff565b8152602083013560208201528091505092915050565b600181811c9082168061555457607f821691505b60208210810361557457634e487b7160e01b600052602260045260246000fd5b50919050565b805182526000602067ffffffffffffffff81840151168185015260408084015160a060408701526155ae60a08701826141f6565b9050606085015186820360608801526155c782826141f6565b608087810151898303918a01919091528051808352908601935060009250908501905b8083101561533c57835180516001600160a01b03168352860151868301529285019260019290920191908401906155ea565b602081526000610a76602083018461557a565b608081526000615642608083018761557a565b61ffff9590951660208301525060408101929092526001600160a01b0316606090910152919050565b60008060006060848603121561568057600080fd5b835161568b8161401c565b602085015190935067ffffffffffffffff8111156156a857600080fd5b8401601f810186136156b957600080fd5b80516156c761407c82614035565b8181528760208385010111156156dc57600080fd5b6156ed8260208301602086016141d2565b809450505050604084015190509250925092565b60006020828403121561571357600080fd5b8151613ddc8161401c565b601f821115610cd8576000816000526020600020601f850160051c810160208610156157475750805b601f850160051c820191505b818110156124df57828155600101615753565b815167ffffffffffffffff81111561578057615780613eca565b6157948161578e8454615540565b8461571e565b602080601f8311600181146157c957600084156157b15750858301515b600019600386901b1c1916600185901b1785556124df565b600085815260208120601f198616915b828110156157f8578886015182559484019460019091019084016157d9565b50858210156158165787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6000602080835283546001600160a01b038116602085015260ff8160a01c161515604085015267ffffffffffffffff8160a81c1660608501525060018085016080808601526000815461587881615540565b8060a089015260c0600183166000811461589957600181146158b5576158e5565b60ff19841660c08b015260c083151560051b8b010194506158e5565b85600052602060002060005b848110156158dc5781548c82018501529088019089016158c1565b8b0160c0019550505b50929998505050505050505050565b80820180821115610a7957610a79615390565b60ff8181168382160190811115610a7957610a79615390565b8183823760009101908152919050565b828152606082602083013760800192915050565b600067ffffffffffffffff8084168061595f5761595f6154b3565b92169190910492915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126159a057600080fd5b83018035915067ffffffffffffffff8211156159bb57600080fd5b60200191503681900382131561384357600080fd5b60208101600583106159e4576159e4614407565b91905290565b60ff81811683821602908116908181146153c7576153c7615390565b600060a0820160ff881683526020878185015260a0604085015281875480845260c0860191508860005282600020935060005b81811015615a5e5784546001600160a01b031683526001948501949284019201615a39565b50508481036060860152865180825290820192508187019060005b81811015615a9e5782516001600160a01b031685529383019391830191600101615a79565b50505060ff851660808501525090506120c7565b600067ffffffffffffffff808616835280851660208401525060606040830152614c5160608301846141f6565b8281526040602082015260006136d060408301846141f6565b67ffffffffffffffff848116825283166020820152606081016136d0604083018461441d565b615b28818561441d565b606060208201526000615b3e60608301856141f6565b9050826040830152949350505050565b600060208284031215615b6057600080fd5b8151613ddc81613fea565b6020815260008251610100806020850152615b8a6101208501836141f6565b91506020850151615ba7604086018267ffffffffffffffff169052565b5060408501516001600160a01b038116606086015250606085015160808501526080850151615be160a08601826001600160a01b03169052565b5060a0850151601f19808685030160c0870152615bfe84836141f6565b935060c08701519150808685030160e0870152615c1b84836141f6565b935060e08701519150808685030183870152506120c783826141f6565b600060208284031215615c4a57600080fd5b5051919050565b600060ff821660ff8103615c6757615c67615390565b60010192915050565b848152600067ffffffffffffffff8086166020840152808516604084015250608060608301526120c760808301846141f6565b86815260c060208201526000615cbc60c08301886141f6565b6001600160a01b039690961660408301525067ffffffffffffffff9384166060820152608081019290925290911660a09091015292915050565b600082825180855260208086019550808260051b84010181860160005b84811015615d8d57601f19868403018952815160808151818652615d39828701826141f6565b9150508582015185820387870152615d5182826141f6565b91505060408083015186830382880152615d6b83826141f6565b6060948501519790940196909652505098840198925090830190600101615d13565b5090979650505050505050565b602081526000610a766020830184615cf6565b60008282518085526020808601955060208260051b8401016020860160005b84811015615d8d57601f19868403018952615de88383516141f6565b98840198925090830190600101615dcc565b604081526000835180516040840152602081015167ffffffffffffffff80821660608601528060408401511660808601528060608401511660a08601528060808401511660c086015250505060208401516101408060e0850152615e626101808501836141f6565b915060408601517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08086850301610100870152615e9f84836141f6565b935060608801519150615ebe6101208701836001600160a01b03169052565b60808801518387015260a0880151925080868503016101608701525050615ee58282615cf6565b9150508281036020840152614c518185615dad56fea164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CanOnlySelfCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"actual\",\"type\":\"bytes32\"}],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ExecutionError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"ForkedChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enumMultiOCR3Base.InvalidConfigErrorType\",\"name\":\"errorType\",\"type\":\"uint8\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"got\",\"type\":\"uint256\"}],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidEVMAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"internalType\":\"structOffRamp.Interval\",\"name\":\"interval\",\"type\":\"tuple\"}],\"name\":\"InvalidInterval\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"newLimit\",\"type\":\"uint256\"}],\"name\":\"InvalidManualExecutionGasLimit\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"messageDestChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidMessageDestChainSelector\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"newState\",\"type\":\"uint8\"}],\"name\":\"InvalidNewState\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRoot\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidStaticConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LeavesCannotBeEmpty\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ManualExecutionGasLimitMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"ManualExecutionNotYetEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"errorReason\",\"type\":\"bytes\"}],\"name\":\"MessageValidationError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonUniqueSignatures\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"notPool\",\"type\":\"address\"}],\"name\":\"NotACompatiblePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OracleCannotBeZeroAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ReceiverError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountReleased\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePre\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePost\",\"type\":\"uint256\"}],\"name\":\"ReleaseOrMintBalanceMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"name\":\"RootAlreadyCommitted\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"RootNotCommitted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignaturesOutOfRegistration\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"StaleCommitReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"StaticConfigCannotBeChanged\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"TokenDataMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"TokenHandlingError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnexpectedTokenData\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"WrongMessageLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WrongNumberOfSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroChainSelectorNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"AlreadyAttempted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"internalType\":\"structOffRamp.Interval\",\"name\":\"interval\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structOffRamp.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"report\",\"type\":\"tuple\"}],\"name\":\"CommitReportAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"DynamicConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"name\":\"ExecutionStateChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"RootRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"SkippedAlreadyExecutedMessage\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"sourceConfig\",\"type\":\"tuple\"}],\"name\":\"SourceChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainSelectorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"}],\"name\":\"StaticConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigUpdates\",\"type\":\"tuple[]\"}],\"name\":\"applySourceChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"destTokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structClient.Any2EVMMessage\",\"name\":\"\",\"type\":\"tuple\"}],\"name\":\"ccipReceive\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"rawVs\",\"type\":\"bytes32\"}],\"name\":\"commit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"execute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"bytes[]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[]\"}],\"name\":\"executeSingleMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"getExecutionState\",\"outputs\":[{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLatestPriceSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"getMerkleRoot\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"getSourceChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"isBlessed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"latestConfigDetails\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"n\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"}],\"internalType\":\"structMultiOCR3Base.ConfigInfo\",\"name\":\"configInfo\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfig\",\"name\":\"ocrConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage[]\",\"name\":\"messages\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[][]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[][]\"},{\"internalType\":\"bytes32[]\",\"name\":\"proofs\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"proofFlagBits\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.ExecutionReportSingleChain[]\",\"name\":\"reports\",\"type\":\"tuple[]\"},{\"internalType\":\"uint256[][]\",\"name\":\"gasLimitOverrides\",\"type\":\"uint256[][]\"}],\"name\":\"manuallyExecute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structOffRamp.UnblessedRoot[]\",\"name\":\"rootToReset\",\"type\":\"tuple[]\"}],\"name\":\"resetUnblessedRoots\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"setDynamicConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfigArgs[]\",\"name\":\"ocrConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"setOCR3Configs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x6101206040523480156200001257600080fd5b5060405162006c1a38038062006c1a8339810160408190526200003591620008c7565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf81620001fa565b5050466080525060208301516001600160a01b03161580620000ec575060408301516001600160a01b0316155b8062000103575060608301516001600160a01b0316155b1562000122576040516342bcdf7f60e11b815260040160405180910390fd5b82516001600160401b03166000036200014e5760405163c656089560e01b815260040160405180910390fd5b82516001600160401b0390811660a052602080850180516001600160a01b0390811660c05260408088018051831660e0526060808a01805185166101005283518b519098168852945184169587019590955251821690850152905116908201527f683eb52ee924eb817377cfa8f41f238f4bb7a877da5267869dfffbad85f564d89060800160405180910390a1620001e682620002a5565b620001f181620003c1565b50505062000c67565b336001600160a01b03821603620002545760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b0316620002ce576040516342bcdf7f60e11b815260040160405180910390fd5b80516004805460208085018051604080880180516060808b0180516001600160a01b039b8c166001600160c01b0319909a168a17600160a01b63ffffffff98891602176001600160c01b0316600160c01b948816949094026001600160e01b031693909317600160e01b93871693909302929092179098556080808b018051600580546001600160a01b031916918d169190911790558451988952955185169688019690965290518316918601919091525116938301939093529151909216908201527fa55bd56595c45f517e5967a3067f3dca684445a3080e7c04a4e0d5a40cda627d9060a00160405180910390a150565b60005b815181101562000666576000828281518110620003e557620003e562000a1d565b60200260200101519050600081602001519050806001600160401b0316600003620004235760405163c656089560e01b815260040160405180910390fd5b81516001600160a01b03166200044c576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160401b0381166000908152600660205260408120600181018054919291620004789062000a33565b80601f0160208091040260200160405190810160405280929190818152602001828054620004a69062000a33565b8015620004f75780601f10620004cb57610100808354040283529160200191620004f7565b820191906000526020600020905b815481529060010190602001808311620004d957829003601f168201915b5050505050905060008460600151905081516000036200059e57805160000362000534576040516342bcdf7f60e11b815260040160405180910390fd5b6001830162000544828262000ac4565b508254600160a81b600160e81b031916600160a81b1783556040516001600160401b03851681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1620005d9565b8080519060200120828051906020012014620005d95760405163c39a620560e01b81526001600160401b038516600482015260240162000083565b604080860151845487516001600160a01b03166001600160a01b0319921515600160a01b02929092166001600160a81b031990911617178455516001600160401b038516907f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b906200064d90869062000b90565b60405180910390a25050505050806001019050620003c4565b5050565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b0381118282101715620006a557620006a56200066a565b60405290565b604051601f8201601f191681016001600160401b0381118282101715620006d657620006d66200066a565b604052919050565b80516001600160401b0381168114620006f657600080fd5b919050565b6001600160a01b03811681146200071157600080fd5b50565b805163ffffffff81168114620006f657600080fd5b6000601f83601f8401126200073d57600080fd5b825160206001600160401b03808311156200075c576200075c6200066a565b8260051b6200076d838201620006ab565b93845286810183019383810190898611156200078857600080fd5b84890192505b85831015620008ba57825184811115620007a85760008081fd5b89016080601f19828d038101821315620007c25760008081fd5b620007cc62000680565b88840151620007db81620006fb565b81526040620007ec858201620006de565b8a8301526060808601518015158114620008065760008081fd5b838301529385015193898511156200081e5760008081fd5b84860195508f603f8701126200083657600094508485fd5b8a8601519450898511156200084f576200084f6200066a565b620008608b858f88011601620006ab565b93508484528f82868801011115620008785760008081fd5b60005b8581101562000898578681018301518582018d01528b016200087b565b5060009484018b0194909452509182015283525091840191908401906200078e565b9998505050505050505050565b6000806000838503610140811215620008df57600080fd5b6080811215620008ee57600080fd5b620008f862000680565b6200090386620006de565b815260208601516200091581620006fb565b602082015260408601516200092a81620006fb565b604082015260608601516200093f81620006fb565b6060820152935060a0607f19820112156200095957600080fd5b5060405160a081016001600160401b0380821183831017156200098057620009806200066a565b81604052608087015191506200099682620006fb565b818352620009a760a0880162000714565b6020840152620009ba60c0880162000714565b6040840152620009cd60e0880162000714565b60608401526101008701519150620009e582620006fb565b608083018290526101208701519294508083111562000a0357600080fd5b505062000a138682870162000729565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b600181811c9082168062000a4857607f821691505b60208210810362000a6957634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111562000abf576000816000526020600020601f850160051c8101602086101562000a9a5750805b601f850160051c820191505b8181101562000abb5782815560010162000aa6565b5050505b505050565b81516001600160401b0381111562000ae05762000ae06200066a565b62000af88162000af1845462000a33565b8462000a6f565b602080601f83116001811462000b30576000841562000b175750858301515b600019600386901b1c1916600185901b17855562000abb565b600085815260208120601f198616915b8281101562000b615788860151825594840194600190910190840162000b40565b508582101562000b805787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b602080825282546001600160a01b0381168383015260a081901c60ff161515604084015260a81c6001600160401b0316606083015260808083015260018084018054600093929190849062000be58162000a33565b8060a089015260c0600183166000811462000c09576001811462000c265762000c58565b60ff19841660c08b015260c083151560051b8b0101945062000c58565b85600052602060002060005b8481101562000c4f5781548c820185015290880190890162000c32565b8b0160c0019550505b50929998505050505050505050565b60805160a05160c05160e05161010051615f4462000cd6600039600081816102660152612a010152600081816102370152612ef40152600081816102080152818161142b015261196d0152600081816101d801526125f00152600081816117f3015261183f0152615f446000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806385572ffb116100d8578063ccd37ba31161008c578063f2fde38b11610066578063f2fde38b14610583578063f716f99f14610596578063ff888fb1146105a957600080fd5b8063ccd37ba31461050b578063d2a15d3514610550578063e9d68a8e1461056357600080fd5b8063991a5018116100bd578063991a5018146104c5578063a80036b4146104d8578063c673e584146104eb57600080fd5b806385572ffb1461049c5780638da5cb5b146104aa57600080fd5b8063311cd5131161012f5780635e36480c116101145780635e36480c146103785780637437ff9f1461039857806379ba50971461049457600080fd5b8063311cd513146103495780633f4b04aa1461035c57600080fd5b806306285c691161016057806306285c69146101a4578063181f5a77146102ed5780632d04ab761461033657600080fd5b806304666f9c1461017c57806305d938b514610191575b600080fd5b61018f61018a3660046140af565b6105cc565b005b61018f61019f36600461473b565b6105e0565b61029660408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316815250905090565b6040516102e49190815167ffffffffffffffff1681526020808301516001600160a01b0390811691830191909152604080840151821690830152606092830151169181019190915260800190565b60405180910390f35b6103296040518060400160405280601181526020017f4f666652616d7020312e362e302d64657600000000000000000000000000000081525081565b6040516102e491906148b6565b61018f610344366004614961565b610785565b61018f610357366004614a14565b610b5c565b60095460405167ffffffffffffffff90911681526020016102e4565b61038b610386366004614a68565b610bc5565b6040516102e49190614ac5565b6104376040805160a081018252600080825260208201819052918101829052606081018290526080810191909152506040805160a0810182526004546001600160a01b03808216835263ffffffff600160a01b83048116602085015278010000000000000000000000000000000000000000000000008304811694840194909452600160e01b9091049092166060820152600554909116608082015290565b6040516102e49190600060a0820190506001600160a01b03808451168352602084015163ffffffff808216602086015280604087015116604086015280606087015116606086015250508060808501511660808401525092915050565b61018f610c1b565b61018f610177366004614ad3565b6000546040516001600160a01b0390911681526020016102e4565b61018f6104d3366004614b22565b610cd9565b61018f6104e6366004614b96565b610cea565b6104fe6104f9366004614c03565b61105d565b6040516102e49190614c63565b610542610519366004614cd8565b67ffffffffffffffff919091166000908152600860209081526040808320938352929052205490565b6040519081526020016102e4565b61018f61055e366004614d02565b6111bb565b610576610571366004614d77565b611275565b6040516102e49190614d92565b61018f610591366004614de0565b611382565b61018f6105a4366004614e65565b611393565b6105bc6105b7366004614fa3565b6113d5565b60405190151581526020016102e4565b6105d4611496565b6105dd816114f2565b50565b6105e86117f0565b815181518114610624576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8181101561077557600084828151811061064357610643614fbc565b6020026020010151905060008160200151519050600085848151811061066b5761066b614fbc565b60200260200101519050805182146106af576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b828110156107665760008282815181106106ce576106ce614fbc565b602002602001015190508060001461075d57846020015182815181106106f6576106f6614fbc565b60200260200101516080015181101561075d5784516040517fc8e9605100000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260248101839052604481018290526064015b60405180910390fd5b506001016106b2565b50505050806001019050610627565b506107808383611871565b505050565b600061079387890189615142565b805151519091501515806107ac57508051602001515115155b156108ac5760095460208a01359067ffffffffffffffff8083169116101561086b576009805467ffffffffffffffff191667ffffffffffffffff83161790556004805483516040517f3937306f0000000000000000000000000000000000000000000000000000000081526001600160a01b0390921692633937306f9261083492910161536a565b600060405180830381600087803b15801561084e57600080fd5b505af1158015610862573d6000803e3d6000fd5b505050506108aa565b8160200151516000036108aa576040517f2261116700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b60005b816020015151811015610aa5576000826020015182815181106108d4576108d4614fbc565b602002602001015190506000816000015190506108f081611921565b60006108fb82611a23565b602084015151815491925067ffffffffffffffff908116600160a81b9092041614158061093f575060208084015190810151905167ffffffffffffffff9182169116115b1561097f57825160208401516040517feefb0cac00000000000000000000000000000000000000000000000000000000815261075492919060040161537d565b6040830151806109bb576040517f504570e300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b835167ffffffffffffffff16600090815260086020908152604080832084845290915290205415610a2e5783516040517f32cf0cbf00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260248101829052604401610754565b6020808501510151610a419060016153c8565b82547fffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffff16600160a81b67ffffffffffffffff9283160217909255925116600090815260086020908152604080832094835293905291909120429055506001016108af565b507f3a3950e13dd607cc37980db0ef14266c40d2bba9c01b2e44bfe549808883095d81604051610ad591906153f0565b60405180910390a1610b5160008a8a8a8a8a8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808e0282810182019093528d82529093508d92508c9182918501908490808284376000920191909152508b9250611a8a915050565b505050505050505050565b610b9c610b6b8284018461548d565b6040805160008082526020820190925290610b96565b6060815260200190600190039081610b815790505b50611871565b604080516000808252602082019092529050610bbf600185858585866000611a8a565b50505050565b6000610bd3600160046154c2565b6002610be06080856154eb565b67ffffffffffffffff16610bf49190615512565b610bfe8585611e01565b901c166003811115610c1257610c12614a9b565b90505b92915050565b6001546001600160a01b03163314610c755760405162461bcd60e51b815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610754565b600080543373ffffffffffffffffffffffffffffffffffffffff19808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610ce1611496565b6105dd81611e48565b333014610d23576040517f371a732800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160008082526020820190925281610d60565b6040805180820190915260008082526020820152815260200190600190039081610d395790505b5060a08501515190915015610d9457610d918460a00151856020015186606001518760000151602001518787611fae565b90505b6040805160a0810182528551518152855160209081015167ffffffffffffffff1681830152808701518351600094840192610dd09291016148b6565b60408051601f19818403018152918152908252878101516020830152018390526005549091506001600160a01b03168015610edd576040517f08d450a10000000000000000000000000000000000000000000000000000000081526001600160a01b038216906308d450a190610e4a9085906004016155cb565b600060405180830381600087803b158015610e6457600080fd5b505af1925050508015610e75575060015b610edd573d808015610ea3576040519150601f19603f3d011682016040523d82523d6000602084013e610ea8565b606091505b50806040517f09c2532500000000000000000000000000000000000000000000000000000000815260040161075491906148b6565b604086015151158015610ef257506080860151155b80610f09575060608601516001600160a01b03163b155b80610f4957506060860151610f47906001600160a01b03167f85572ffb000000000000000000000000000000000000000000000000000000006120cd565b155b15610f5657505050505050565b855160209081015167ffffffffffffffff1660009081526006909152604080822054608089015160608a015192517f3cf9798300000000000000000000000000000000000000000000000000000000815284936001600160a01b0390931692633cf9798392610fce92899261138892916004016155de565b6000604051808303816000875af1158015610fed573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611015919081019061561a565b50915091508161105357806040517f0a8d6e8c00000000000000000000000000000000000000000000000000000000815260040161075491906148b6565b5050505050505050565b6110a06040805160e081019091526000606082018181526080830182905260a0830182905260c08301919091528190815260200160608152602001606081525090565b60ff808316600090815260026020818152604092839020835160e081018552815460608201908152600183015480881660808401526101008104881660a0840152620100009004909616151560c08201529485529182018054845181840281018401909552808552929385830193909283018282801561114957602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161112b575b50505050508152602001600382018054806020026020016040519081016040528092919081815260200182805480156111ab57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161118d575b5050505050815250509050919050565b6111c3611496565b60005b818110156107805760008383838181106111e2576111e2614fbc565b9050604002018036038101906111f891906156b0565b905061120781602001516113d5565b61126c57805167ffffffffffffffff1660009081526008602090815260408083208285018051855290835281842093909355915191519182527f202f1139a3e334b6056064c0e9b19fd07e44a88d8f6e5ded571b24cf8c371f12910160405180910390a15b506001016111c6565b604080516080808201835260008083526020808401829052838501829052606080850181905267ffffffffffffffff878116845260068352928690208651948501875280546001600160a01b0381168652600160a01b810460ff16151593860193909352600160a81b909204909216948301949094526001840180549394929391840191611302906156e9565b80601f016020809104026020016040519081016040528092919081815260200182805461132e906156e9565b80156111ab5780601f10611350576101008083540402835291602001916111ab565b820191906000526020600020905b81548152906001019060200180831161135e57505050919092525091949350505050565b61138a611496565b6105dd816120e9565b61139b611496565b60005b81518110156113d1576113c98282815181106113bc576113bc614fbc565b602002602001015161219f565b60010161139e565b5050565b6040805180820182523081526020810183815291517f4d61677100000000000000000000000000000000000000000000000000000000815290516001600160a01b039081166004830152915160248201526000917f00000000000000000000000000000000000000000000000000000000000000001690634d61677190604401602060405180830381865afa158015611472573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c159190615723565b6000546001600160a01b031633146114f05760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610754565b565b60005b81518110156113d157600082828151811061151257611512614fbc565b602002602001015190506000816020015190508067ffffffffffffffff16600003611569576040517fc656089500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81516001600160a01b0316611591576040516342bcdf7f60e11b815260040160405180910390fd5b67ffffffffffffffff811660009081526006602052604081206001810180549192916115bc906156e9565b80601f01602080910402602001604051908101604052809291908181526020018280546115e8906156e9565b80156116355780601f1061160a57610100808354040283529160200191611635565b820191906000526020600020905b81548152906001019060200180831161161857829003601f168201915b5050505050905060008460600151905081516000036116ed578051600003611670576040516342bcdf7f60e11b815260040160405180910390fd5b6001830161167e8282615788565b5082547fffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffff16600160a81b17835560405167ffffffffffffffff851681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1611740565b8080519060200120828051906020012014611740576040517fc39a620500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff85166004820152602401610754565b604080860151845487516001600160a01b031673ffffffffffffffffffffffffffffffffffffffff19921515600160a01b02929092167fffffffffffffffffffffff000000000000000000000000000000000000000000909116171784555167ffffffffffffffff8516907f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b906117d8908690615848565b60405180910390a250505050508060010190506114f5565b467f0000000000000000000000000000000000000000000000000000000000000000146114f0576040517f0f01ce850000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000006004820152466024820152604401610754565b81516000036118ab576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160408051600080825260208201909252911591905b845181101561191a576119128582815181106118e0576118e0614fbc565b60200260200101518461190c578583815181106118ff576118ff614fbc565b60200260200101516124e3565b836124e3565b6001016118c2565b5050505050565b6040517f2cbc26bb000000000000000000000000000000000000000000000000000000008152608082901b77ffffffffffffffff000000000000000000000000000000001660048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632cbc26bb90602401602060405180830381865afa1580156119bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119e09190615723565b156105dd576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610754565b67ffffffffffffffff811660009081526006602052604081208054600160a01b900460ff16610c15576040517fed053c5900000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610754565b60ff87811660009081526002602090815260408083208151608081018352815481526001909101548086169382019390935261010083048516918101919091526201000090910490921615156060830152873590611ae98760a4615916565b9050826060015115611b31578451611b02906020615512565b8651611b0f906020615512565b611b1a9060a0615916565b611b249190615916565b611b2e9082615916565b90505b368114611b73576040517f8e1192e100000000000000000000000000000000000000000000000000000000815260048101829052366024820152604401610754565b5081518114611bbb5781516040517f93df584c000000000000000000000000000000000000000000000000000000008152600481019190915260248101829052604401610754565b611bc36117f0565b60ff808a1660009081526003602090815260408083203384528252808320815180830190925280548086168352939491939092840191610100909104166002811115611c1157611c11614a9b565b6002811115611c2257611c22614a9b565b9052509050600281602001516002811115611c3f57611c3f614a9b565b148015611c935750600260008b60ff1660ff168152602001908152602001600020600301816000015160ff1681548110611c7b57611c7b614fbc565b6000918252602090912001546001600160a01b031633145b611cc9576040517fda0f08e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50816060015115611dab576020820151611ce4906001615929565b60ff16855114611d20576040517f71253a2500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8351855114611d5b576040517fa75d88af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008787604051611d6d929190615942565b604051908190038120611d84918b90602001615952565b604051602081830303815290604052805190602001209050611da98a82888888612c86565b505b6040805182815260208a81013567ffffffffffffffff169082015260ff8b16917f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef0910160405180910390a2505050505050505050565b67ffffffffffffffff8216600090815260076020526040812081611e26608085615966565b67ffffffffffffffff1681526020810191909152604001600020549392505050565b80516001600160a01b0316611e70576040516342bcdf7f60e11b815260040160405180910390fd5b80516004805460208085018051604080880180516060808b0180516001600160a01b039b8c167fffffffffffffffff000000000000000000000000000000000000000000000000909a168a17600160a01b63ffffffff988916021777ffffffffffffffffffffffffffffffffffffffffffffffff167801000000000000000000000000000000000000000000000000948816949094026001600160e01b031693909317600160e01b93871693909302929092179098556080808b0180516005805473ffffffffffffffffffffffffffffffffffffffff1916918d169190911790558451988952955185169688019690965290518316918601919091525116938301939093529151909216908201527fa55bd56595c45f517e5967a3067f3dca684445a3080e7c04a4e0d5a40cda627d9060a00160405180910390a150565b6060865167ffffffffffffffff811115611fca57611fca613ec6565b60405190808252806020026020018201604052801561200f57816020015b6040805180820190915260008082526020820152815260200190600190039081611fe85790505b50905060005b87518110156120c15761209c88828151811061203357612033614fbc565b602002602001015188888888888781811061205057612050614fbc565b9050602002810190612062919061598d565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612e9392505050565b8282815181106120ae576120ae614fbc565b6020908102919091010152600101612015565b505b9695505050505050565b60006120d883613238565b8015610c125750610c12838361329c565b336001600160a01b038216036121415760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610754565b6001805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b806040015160ff166000036121ca576000604051631b3fab5160e11b815260040161075491906159f2565b60208082015160ff8082166000908152600290935260408320600181015492939092839216900361223757606084015160018201805491151562010000027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff90921691909117905561228c565b6060840151600182015460ff620100009091041615159015151461228c576040517f87f6037c00000000000000000000000000000000000000000000000000000000815260ff84166004820152602401610754565b60a08401518051601f60ff821611156122bb576001604051631b3fab5160e11b815260040161075491906159f2565b612321858560030180548060200260200160405190810160405280929190818152602001828054801561231757602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116122f9575b5050505050613357565b8560600151156124505761238f8585600201805480602002602001604051908101604052809291908181526020018280548015612317576020028201919060005260206000209081546001600160a01b031681526001909101906020018083116122f9575050505050613357565b608086015180516123a99060028701906020840190613e20565b5080516001850180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1661010060ff841690810291909117909155601f1015612409576002604051631b3fab5160e11b815260040161075491906159f2565b6040880151612419906003615a0c565b60ff168160ff1611612441576003604051631b3fab5160e11b815260040161075491906159f2565b61244d878360016133c0565b50505b61245c858360026133c0565b81516124719060038601906020850190613e20565b5060408681015160018501805460ff191660ff8316179055875180865560a089015192517fab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f547936124ca938a939260028b01929190615a28565b60405180910390a16124db85613540565b505050505050565b81516124ee81611921565b60006124f982611a23565b602085015151909150600081900361253c576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b846040015151811461257a576040517f57e0e08300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008167ffffffffffffffff81111561259557612595613ec6565b6040519080825280602002602001820160405280156125be578160200160208202803683370190505b50905060005b82811015612733576000876020015182815181106125e4576125e4614fbc565b602002602001015190507f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681600001516040015167ffffffffffffffff161461267757805160409081015190517f38432a2200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610754565b61270d8186600101805461268a906156e9565b80601f01602080910402602001604051908101604052809291908181526020018280546126b6906156e9565b80156127035780601f106126d857610100808354040283529160200191612703565b820191906000526020600020905b8154815290600101906020018083116126e657829003601f168201915b505050505061355c565b83838151811061271f5761271f614fbc565b6020908102919091010152506001016125c4565b50600061274a858389606001518a6080015161367e565b905080600003612792576040517f7dd17a7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff86166004820152602401610754565b8551151560005b84811015610b515760005a905060008a6020015183815181106127be576127be614fbc565b6020026020010151905060006127dc8a836000015160600151610bc5565b905060008160038111156127f2576127f2614a9b565b148061280f5750600381600381111561280d5761280d614a9b565b145b612867578151606001516040805167ffffffffffffffff808e16825290921660208301527f3b575419319662b2a6f5e2467d84521517a3382b908eb3d557bb3fdb0c50e23c91015b60405180910390a1505050612c7e565b841561293757600454600090600160a01b900463ffffffff1661288a88426154c2565b11905080806128aa575060038260038111156128a8576128a8614a9b565b145b6128ec576040517fa9cfc86200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8c166004820152602401610754565b8b85815181106128fe576128fe614fbc565b6020026020010151600014612931578b858151811061291f5761291f614fbc565b60200260200101518360800181815250505b50612998565b600081600381111561294b5761294b614a9b565b14612998578151606001516040805167ffffffffffffffff808e16825290921660208301527f3ef2a99c550a751d4b0b261268f05a803dfb049ab43616a1ffb388f61fe651209101612857565b81516080015167ffffffffffffffff1615612a875760008160038111156129c1576129c1614a9b565b03612a875781516080015160208301516040517fe0e03cae0000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169263e0e03cae92612a38928f929190600401615ad4565b6020604051808303816000875af1158015612a57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a7b9190615723565b612a8757505050612c7e565b60008c604001518581518110612a9f57612a9f614fbc565b6020026020010151905080518360a001515114612b03578251606001516040517f1cfe6d8b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808e1660048301529091166024820152604401610754565b612b178b84600001516060015160016136d4565b600080612b24858461377c565b91509150612b3b8d866000015160600151846136d4565b8715612bab576003826003811115612b5557612b55614a9b565b03612bab576000846003811115612b6e57612b6e614a9b565b14612bab578451516040517f2b11b8d900000000000000000000000000000000000000000000000000000000815261075491908390600401615b01565b6002826003811115612bbf57612bbf614a9b565b14612c19576003826003811115612bd857612bd8614a9b565b14612c19578451606001516040517f926c5a3e000000000000000000000000000000000000000000000000000000008152610754918f918590600401615b1a565b8451805160609091015167ffffffffffffffff908116908f167fdc8ccbc35e0eebd81239bcd1971fcd53c7eb34034880142a0f43c809a458732f85855a612c60908d6154c2565b604051612c6f93929190615b40565b60405180910390a45050505050505b600101612799565b612c8e613e92565b835160005b81811015611053576000600188868460208110612cb257612cb2614fbc565b612cbf91901a601b615929565b898581518110612cd157612cd1614fbc565b6020026020010151898681518110612ceb57612ceb614fbc565b602002602001015160405160008152602001604052604051612d29949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015612d4b573d6000803e3d6000fd5b505060408051601f1981015160ff808e166000908152600360209081528582206001600160a01b03851683528152858220858701909652855480841686529397509095509293928401916101009004166002811115612dac57612dac614a9b565b6002811115612dbd57612dbd614a9b565b9052509050600181602001516002811115612dda57612dda614a9b565b14612e11576040517fca31867a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051859060ff16601f8110612e2857612e28614fbc565b602002015115612e64576040517ff67bc7c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600185826000015160ff16601f8110612e7f57612e7f614fbc565b911515602090920201525050600101612c93565b60408051808201909152600080825260208201526000612eb68760200151613846565b6040517fbbe4f6db0000000000000000000000000000000000000000000000000000000081526001600160a01b0380831660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063bbe4f6db90602401602060405180830381865afa158015612f3b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f5f9190615b70565b90506001600160a01b0381161580612fa75750612fa56001600160a01b0382167faff2afbf000000000000000000000000000000000000000000000000000000006120cd565b155b15612fe9576040517fae9b4ce90000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152602401610754565b600454600090819061300b9089908690600160e01b900463ffffffff166138ec565b9150915060008060006130d86040518061010001604052808e81526020018c67ffffffffffffffff1681526020018d6001600160a01b031681526020018f606001518152602001896001600160a01b031681526020018f6000015181526020018f6040015181526020018b8152506040516024016130899190615b8d565b60408051601f198184030181529190526020810180516001600160e01b03167f390775370000000000000000000000000000000000000000000000000000000017905287866113886084613a1a565b9250925092508261311757816040517fe1cd550900000000000000000000000000000000000000000000000000000000815260040161075491906148b6565b815160201461315f5781516040517f78ef8024000000000000000000000000000000000000000000000000000000008152602060048201526024810191909152604401610754565b6000828060200190518101906131759190615c5a565b9050866001600160a01b03168c6001600160a01b03161461320a5760006131a68d8a6131a1868a6154c2565b6138ec565b509050868110806131c05750816131bd88836154c2565b14155b15613208576040517fa966e21f000000000000000000000000000000000000000000000000000000008152600481018390526024810188905260448101829052606401610754565b505b604080518082019091526001600160a01b039098168852602088015250949550505050505095945050505050565b6000613264827f01ffc9a70000000000000000000000000000000000000000000000000000000061329c565b8015610c155750613295827fffffffff0000000000000000000000000000000000000000000000000000000061329c565b1592915050565b6040517fffffffff0000000000000000000000000000000000000000000000000000000082166024820152600090819060440160408051601f19818403018152919052602080820180516001600160e01b03167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825192935060009283928392909183918a617530fa92503d91506000519050828015613340575060208210155b801561334c5750600081115b979650505050505050565b60005b81518110156107805760ff83166000908152600360205260408120835190919084908490811061338c5761338c614fbc565b6020908102919091018101516001600160a01b03168252810191909152604001600020805461ffff1916905560010161335a565b60005b82518160ff161015610bbf576000838260ff16815181106133e6576133e6614fbc565b602002602001015190506000600281111561340357613403614a9b565b60ff80871660009081526003602090815260408083206001600160a01b0387168452909152902054610100900416600281111561344257613442614a9b565b14613463576004604051631b3fab5160e11b815260040161075491906159f2565b6001600160a01b0381166134a3576040517fd6c62c9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052808360ff1681526020018460028111156134c9576134c9614a9b565b905260ff80871660009081526003602090815260408083206001600160a01b0387168452825290912083518154931660ff198416811782559184015190929091839161ffff19161761010083600281111561352657613526614a9b565b0217905550905050508061353990615c73565b90506133c3565b60ff81166105dd576009805467ffffffffffffffff1916905550565b8151602080820151604092830151925160009384936135a2937f2425b0b9f9054c76ff151b0a175b18f37a4a4e82013a72e9f15c9caa095ed21f93909291889101615c92565b60408051601f1981840301815290829052805160209182012086518051888401516060808b0151908401516080808d015195015195976135eb9794969395929491939101615cc5565b604051602081830303815290604052805190602001208560400151805190602001208660a001516040516020016136229190615dd7565b60408051601f198184030181528282528051602091820120908301969096528101939093526060830191909152608082015260a081019190915260c0015b60405160208183030381529060405280519060200120905092915050565b60008061368c858585613b40565b9050613697816113d5565b6136a55760009150506136cc565b67ffffffffffffffff86166000908152600860209081526040808320938352929052205490505b949350505050565b600060026136e36080856154eb565b67ffffffffffffffff166136f79190615512565b905060006137058585611e01565b905081613714600160046154c2565b901b19168183600381111561372b5761372b614a9b565b67ffffffffffffffff871660009081526007602052604081209190921b9290921791829161375a608088615966565b67ffffffffffffffff1681526020810191909152604001600020555050505050565b6040517fa80036b4000000000000000000000000000000000000000000000000000000008152600090606090309063a80036b4906137c09087908790600401615e37565b600060405180830381600087803b1580156137da57600080fd5b505af19250505080156137eb575060015b61382a573d808015613819576040519150601f19603f3d011682016040523d82523d6000602084013e61381e565b606091505b5060039250905061383f565b50506040805160208101909152600081526002905b9250929050565b6000815160201461388557816040517f8d666f6000000000000000000000000000000000000000000000000000000000815260040161075491906148b6565b60008280602001905181019061389b9190615c5a565b90506001600160a01b038111806138b3575061040081105b15610c1557826040517f8d666f6000000000000000000000000000000000000000000000000000000000815260040161075491906148b6565b60008060008060006139668860405160240161391791906001600160a01b0391909116815260200190565b60408051601f198184030181529190526020810180516001600160e01b03167f70a082310000000000000000000000000000000000000000000000000000000017905288886113886084613a1a565b925092509250826139a557816040517fe1cd550900000000000000000000000000000000000000000000000000000000815260040161075491906148b6565b60208251146139ed5781516040517f78ef8024000000000000000000000000000000000000000000000000000000008152602060048201526024810191909152604401610754565b81806020019051810190613a019190615c5a565b613a0b82886154c2565b94509450505050935093915050565b6000606060008361ffff1667ffffffffffffffff811115613a3d57613a3d613ec6565b6040519080825280601f01601f191660200182016040528015613a67576020820181803683370190505b509150863b613a9a577f0c3b563c0000000000000000000000000000000000000000000000000000000060005260046000fd5b5a85811015613acd577fafa32a2c0000000000000000000000000000000000000000000000000000000060005260046000fd5b8590036040810481038710613b06577f37c3be290000000000000000000000000000000000000000000000000000000060005260046000fd5b505a6000808a5160208c0160008c8cf193505a900390503d84811115613b295750835b808352806000602085013e50955095509592505050565b8251825160009190818303613b81576040517f11a6b26400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6101018211801590613b9557506101018111155b613bb2576040516309bde33960e01b815260040160405180910390fd5b60001982820101610100811115613bdc576040516309bde33960e01b815260040160405180910390fd5b80600003613c095786600081518110613bf757613bf7614fbc565b60200260200101519350505050613dd8565b60008167ffffffffffffffff811115613c2457613c24613ec6565b604051908082528060200260200182016040528015613c4d578160200160208202803683370190505b50905060008080805b85811015613d775760006001821b8b811603613cb15788851015613c9a578c5160018601958e918110613c8b57613c8b614fbc565b60200260200101519050613cd3565b8551600185019487918110613c8b57613c8b614fbc565b8b5160018401938d918110613cc857613cc8614fbc565b602002602001015190505b600089861015613d03578d5160018701968f918110613cf457613cf4614fbc565b60200260200101519050613d25565b8651600186019588918110613d1a57613d1a614fbc565b602002602001015190505b82851115613d46576040516309bde33960e01b815260040160405180910390fd5b613d508282613ddf565b878481518110613d6257613d62614fbc565b60209081029190910101525050600101613c56565b506001850382148015613d8957508683145b8015613d9457508581145b613db1576040516309bde33960e01b815260040160405180910390fd5b836001860381518110613dc657613dc6614fbc565b60200260200101519750505050505050505b9392505050565b6000818310613df757613df28284613dfd565b610c12565b610c1283835b604080516001602082015290810183905260608101829052600090608001613660565b828054828255906000526020600020908101928215613e82579160200282015b82811115613e82578251825473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03909116178255602090920191600190910190613e40565b50613e8e929150613eb1565b5090565b604051806103e00160405280601f906020820280368337509192915050565b5b80821115613e8e5760008155600101613eb2565b634e487b7160e01b600052604160045260246000fd5b6040516080810167ffffffffffffffff81118282101715613eff57613eff613ec6565b60405290565b60405160a0810167ffffffffffffffff81118282101715613eff57613eff613ec6565b60405160c0810167ffffffffffffffff81118282101715613eff57613eff613ec6565b6040805190810167ffffffffffffffff81118282101715613eff57613eff613ec6565b6040516060810167ffffffffffffffff81118282101715613eff57613eff613ec6565b604051601f8201601f1916810167ffffffffffffffff81118282101715613fba57613fba613ec6565b604052919050565b600067ffffffffffffffff821115613fdc57613fdc613ec6565b5060051b60200190565b6001600160a01b03811681146105dd57600080fd5b803567ffffffffffffffff8116811461401357600080fd5b919050565b80151581146105dd57600080fd5b803561401381614018565b600067ffffffffffffffff82111561404b5761404b613ec6565b50601f01601f191660200190565b600082601f83011261406a57600080fd5b813561407d61407882614031565b613f91565b81815284602083860101111561409257600080fd5b816020850160208301376000918101602001919091529392505050565b600060208083850312156140c257600080fd5b823567ffffffffffffffff808211156140da57600080fd5b818501915085601f8301126140ee57600080fd5b81356140fc61407882613fc2565b81815260059190911b8301840190848101908883111561411b57600080fd5b8585015b838110156141c1578035858111156141375760008081fd5b86016080818c03601f190181131561414f5760008081fd5b614157613edc565b8983013561416481613fe6565b81526040614173848201613ffb565b8b83015260608085013561418681614018565b8383015292840135928984111561419f57600091508182fd5b6141ad8f8d86880101614059565b90830152508552505091860191860161411f565b5098975050505050505050565b600060a082840312156141e057600080fd5b6141e8613f05565b9050813581526141fa60208301613ffb565b602082015261420b60408301613ffb565b604082015261421c60608301613ffb565b606082015261422d60808301613ffb565b608082015292915050565b803561401381613fe6565b600082601f83011261425457600080fd5b8135602061426461407883613fc2565b82815260059290921b8401810191818101908684111561428357600080fd5b8286015b848110156120c157803567ffffffffffffffff808211156142a85760008081fd5b818901915060a080601f19848d030112156142c35760008081fd5b6142cb613f05565b87840135838111156142dd5760008081fd5b6142eb8d8a83880101614059565b825250604080850135848111156143025760008081fd5b6143108e8b83890101614059565b8a84015250606080860135858111156143295760008081fd5b6143378f8c838a0101614059565b8385015250608091508186013581840152508285013592508383111561435d5760008081fd5b61436b8d8a85880101614059565b908201528652505050918301918301614287565b6000610140828403121561439257600080fd5b61439a613f28565b90506143a683836141ce565b815260a082013567ffffffffffffffff808211156143c357600080fd5b6143cf85838601614059565b602084015260c08401359150808211156143e857600080fd5b6143f485838601614059565b604084015261440560e08501614238565b6060840152610100840135608084015261012084013591508082111561442a57600080fd5b5061443784828501614243565b60a08301525092915050565b600082601f83011261445457600080fd5b8135602061446461407883613fc2565b82815260059290921b8401810191818101908684111561448357600080fd5b8286015b848110156120c157803567ffffffffffffffff8111156144a75760008081fd5b6144b58986838b010161437f565b845250918301918301614487565b600082601f8301126144d457600080fd5b813560206144e461407883613fc2565b82815260059290921b8401810191818101908684111561450357600080fd5b8286015b848110156120c157803567ffffffffffffffff8082111561452757600080fd5b818901915089603f83011261453b57600080fd5b8582013561454b61407882613fc2565b81815260059190911b830160400190878101908c83111561456b57600080fd5b604085015b838110156145a45780358581111561458757600080fd5b6145968f6040838a0101614059565b845250918901918901614570565b50875250505092840192508301614507565b600082601f8301126145c757600080fd5b813560206145d761407883613fc2565b8083825260208201915060208460051b8701019350868411156145f957600080fd5b602086015b848110156120c157803583529183019183016145fe565b600082601f83011261462657600080fd5b8135602061463661407883613fc2565b82815260059290921b8401810191818101908684111561465557600080fd5b8286015b848110156120c157803567ffffffffffffffff8082111561467a5760008081fd5b818901915060a080601f19848d030112156146955760008081fd5b61469d613f05565b6146a8888501613ffb565b8152604080850135848111156146be5760008081fd5b6146cc8e8b83890101614443565b8a84015250606080860135858111156146e55760008081fd5b6146f38f8c838a01016144c3565b838501525060809150818601358581111561470e5760008081fd5b61471c8f8c838a01016145b6565b9184019190915250919093013590830152508352918301918301614659565b600080604080848603121561474f57600080fd5b833567ffffffffffffffff8082111561476757600080fd5b61477387838801614615565b945060209150818601358181111561478a57600080fd5b8601601f8101881361479b57600080fd5b80356147a961407882613fc2565b81815260059190911b8201840190848101908a8311156147c857600080fd5b8584015b83811015614854578035868111156147e45760008081fd5b8501603f81018d136147f65760008081fd5b8781013561480661407882613fc2565b81815260059190911b82018a0190898101908f8311156148265760008081fd5b928b01925b828410156148445783358252928a0192908a019061482b565b86525050509186019186016147cc565b50809750505050505050509250929050565b60005b83811015614881578181015183820152602001614869565b50506000910152565b600081518084526148a2816020860160208601614866565b601f01601f19169290920160200192915050565b602081526000610c12602083018461488a565b8060608101831015610c1557600080fd5b60008083601f8401126148ec57600080fd5b50813567ffffffffffffffff81111561490457600080fd5b60208301915083602082850101111561383f57600080fd5b60008083601f84011261492e57600080fd5b50813567ffffffffffffffff81111561494657600080fd5b6020830191508360208260051b850101111561383f57600080fd5b60008060008060008060008060e0898b03121561497d57600080fd5b6149878a8a6148c9565b9750606089013567ffffffffffffffff808211156149a457600080fd5b6149b08c838d016148da565b909950975060808b01359150808211156149c957600080fd5b6149d58c838d0161491c565b909750955060a08b01359150808211156149ee57600080fd5b506149fb8b828c0161491c565b999c989b50969995989497949560c00135949350505050565b600080600060808486031215614a2957600080fd5b614a3385856148c9565b9250606084013567ffffffffffffffff811115614a4f57600080fd5b614a5b868287016148da565b9497909650939450505050565b60008060408385031215614a7b57600080fd5b614a8483613ffb565b9150614a9260208401613ffb565b90509250929050565b634e487b7160e01b600052602160045260246000fd5b60048110614ac157614ac1614a9b565b9052565b60208101610c158284614ab1565b600060208284031215614ae557600080fd5b813567ffffffffffffffff811115614afc57600080fd5b820160a08185031215613dd857600080fd5b803563ffffffff8116811461401357600080fd5b600060a08284031215614b3457600080fd5b614b3c613f05565b8235614b4781613fe6565b8152614b5560208401614b0e565b6020820152614b6660408401614b0e565b6040820152614b7760608401614b0e565b60608201526080830135614b8a81613fe6565b60808201529392505050565b600080600060408486031215614bab57600080fd5b833567ffffffffffffffff80821115614bc357600080fd5b614bcf8783880161437f565b94506020860135915080821115614be557600080fd5b50614a5b8682870161491c565b803560ff8116811461401357600080fd5b600060208284031215614c1557600080fd5b610c1282614bf2565b60008151808452602080850194506020840160005b83811015614c585781516001600160a01b031687529582019590820190600101614c33565b509495945050505050565b60208152600082518051602084015260ff602082015116604084015260ff604082015116606084015260608101511515608084015250602083015160c060a0840152614cb260e0840182614c1e565b90506040840151601f198483030160c0850152614ccf8282614c1e565b95945050505050565b60008060408385031215614ceb57600080fd5b614cf483613ffb565b946020939093013593505050565b60008060208385031215614d1557600080fd5b823567ffffffffffffffff80821115614d2d57600080fd5b818501915085601f830112614d4157600080fd5b813581811115614d5057600080fd5b8660208260061b8501011115614d6557600080fd5b60209290920196919550909350505050565b600060208284031215614d8957600080fd5b610c1282613ffb565b602081526001600160a01b03825116602082015260208201511515604082015267ffffffffffffffff6040830151166060820152600060608301516080808401526136cc60a084018261488a565b600060208284031215614df257600080fd5b8135613dd881613fe6565b600082601f830112614e0e57600080fd5b81356020614e1e61407883613fc2565b8083825260208201915060208460051b870101935086841115614e4057600080fd5b602086015b848110156120c1578035614e5881613fe6565b8352918301918301614e45565b60006020808385031215614e7857600080fd5b823567ffffffffffffffff80821115614e9057600080fd5b818501915085601f830112614ea457600080fd5b8135614eb261407882613fc2565b81815260059190911b83018401908481019088831115614ed157600080fd5b8585015b838110156141c157803585811115614eec57600080fd5b860160c0818c03601f19011215614f035760008081fd5b614f0b613f28565b8882013581526040614f1e818401614bf2565b8a8301526060614f2f818501614bf2565b8284015260809150614f42828501614026565b9083015260a08381013589811115614f5a5760008081fd5b614f688f8d83880101614dfd565b838501525060c0840135915088821115614f825760008081fd5b614f908e8c84870101614dfd565b9083015250845250918601918601614ed5565b600060208284031215614fb557600080fd5b5035919050565b634e487b7160e01b600052603260045260246000fd5b80356001600160e01b038116811461401357600080fd5b600082601f830112614ffa57600080fd5b8135602061500a61407883613fc2565b82815260069290921b8401810191818101908684111561502957600080fd5b8286015b848110156120c157604081890312156150465760008081fd5b61504e613f4b565b61505782613ffb565b8152615064858301614fd2565b8186015283529183019160400161502d565b600082601f83011261508757600080fd5b8135602061509761407883613fc2565b82815260079290921b840181019181810190868411156150b657600080fd5b8286015b848110156120c15780880360808112156150d45760008081fd5b6150dc613f6e565b6150e583613ffb565b8152604080601f19840112156150fb5760008081fd5b615103613f4b565b9250615110878501613ffb565b835261511d818501613ffb565b83880152818701929092526060830135918101919091528352918301916080016150ba565b6000602080838503121561515557600080fd5b823567ffffffffffffffff8082111561516d57600080fd5b8185019150604080838803121561518357600080fd5b61518b613f4b565b83358381111561519a57600080fd5b84016040818a0312156151ac57600080fd5b6151b4613f4b565b8135858111156151c357600080fd5b8201601f81018b136151d457600080fd5b80356151e261407882613fc2565b81815260069190911b8201890190898101908d83111561520157600080fd5b928a01925b828410156152515787848f03121561521e5760008081fd5b615226613f4b565b843561523181613fe6565b815261523e858d01614fd2565b818d0152825292870192908a0190615206565b84525050508187013593508484111561526957600080fd5b6152758a858401614fe9565b818801528252508385013591508282111561528f57600080fd5b61529b88838601615076565b85820152809550505050505092915050565b805160408084528151848201819052600092602091908201906060870190855b8181101561530457835180516001600160a01b031684528501516001600160e01b03168584015292840192918501916001016152cd565b50508583015187820388850152805180835290840192506000918401905b8083101561535e578351805167ffffffffffffffff1683528501516001600160e01b031685830152928401926001929092019190850190615322565b50979650505050505050565b602081526000610c1260208301846152ad565b67ffffffffffffffff8316815260608101613dd86020830184805167ffffffffffffffff908116835260209182015116910152565b634e487b7160e01b600052601160045260246000fd5b67ffffffffffffffff8181168382160190808211156153e9576153e96153b2565b5092915050565b60006020808352606084516040808487015261540f60608701836152ad565b87850151878203601f19016040890152805180835290860193506000918601905b808310156141c157845167ffffffffffffffff81511683528781015161546f89850182805167ffffffffffffffff908116835260209182015116910152565b50840151828701529386019360019290920191608090910190615430565b60006020828403121561549f57600080fd5b813567ffffffffffffffff8111156154b657600080fd5b6136cc84828501614615565b81810381811115610c1557610c156153b2565b634e487b7160e01b600052601260045260246000fd5b600067ffffffffffffffff80841680615506576155066154d5565b92169190910692915050565b8082028115828204841417610c1557610c156153b2565b805182526000602067ffffffffffffffff81840151168185015260408084015160a0604087015261555d60a087018261488a565b905060608501518682036060880152615576828261488a565b608087810151898303918a01919091528051808352908601935060009250908501905b8083101561535e57835180516001600160a01b0316835286015186830152928501926001929092019190840190615599565b602081526000610c126020830184615529565b6080815260006155f16080830187615529565b61ffff9590951660208301525060408101929092526001600160a01b0316606090910152919050565b60008060006060848603121561562f57600080fd5b835161563a81614018565b602085015190935067ffffffffffffffff81111561565757600080fd5b8401601f8101861361566857600080fd5b805161567661407882614031565b81815287602083850101111561568b57600080fd5b61569c826020830160208601614866565b809450505050604084015190509250925092565b6000604082840312156156c257600080fd5b6156ca613f4b565b6156d383613ffb565b8152602083013560208201528091505092915050565b600181811c908216806156fd57607f821691505b60208210810361571d57634e487b7160e01b600052602260045260246000fd5b50919050565b60006020828403121561573557600080fd5b8151613dd881614018565b601f821115610780576000816000526020600020601f850160051c810160208610156157695750805b601f850160051c820191505b818110156124db57828155600101615775565b815167ffffffffffffffff8111156157a2576157a2613ec6565b6157b6816157b084546156e9565b84615740565b602080601f8311600181146157eb57600084156157d35750858301515b600019600386901b1c1916600185901b1785556124db565b600085815260208120601f198616915b8281101561581a578886015182559484019460019091019084016157fb565b50858210156158385787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6000602080835283546001600160a01b038116602085015260ff8160a01c161515604085015267ffffffffffffffff8160a81c1660608501525060018085016080808601526000815461589a816156e9565b8060a089015260c060018316600081146158bb57600181146158d757615907565b60ff19841660c08b015260c083151560051b8b01019450615907565b85600052602060002060005b848110156158fe5781548c82018501529088019089016158e3565b8b0160c0019550505b50929998505050505050505050565b80820180821115610c1557610c156153b2565b60ff8181168382160190811115610c1557610c156153b2565b8183823760009101908152919050565b828152606082602083013760800192915050565b600067ffffffffffffffff80841680615981576159816154d5565b92169190910492915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126159c257600080fd5b83018035915067ffffffffffffffff8211156159dd57600080fd5b60200191503681900382131561383f57600080fd5b6020810160058310615a0657615a06614a9b565b91905290565b60ff81811683821602908116908181146153e9576153e96153b2565b600060a0820160ff881683526020878185015260a0604085015281875480845260c0860191508860005282600020935060005b81811015615a805784546001600160a01b031683526001948501949284019201615a5b565b50508481036060860152865180825290820192508187019060005b81811015615ac05782516001600160a01b031685529383019391830191600101615a9b565b50505060ff851660808501525090506120c3565b600067ffffffffffffffff808616835280851660208401525060606040830152614ccf606083018461488a565b8281526040602082015260006136cc604083018461488a565b67ffffffffffffffff848116825283166020820152606081016136cc6040830184614ab1565b615b4a8185614ab1565b606060208201526000615b60606083018561488a565b9050826040830152949350505050565b600060208284031215615b8257600080fd5b8151613dd881613fe6565b6020815260008251610100806020850152615bac61012085018361488a565b91506020850151615bc9604086018267ffffffffffffffff169052565b5060408501516001600160a01b038116606086015250606085015160808501526080850151615c0360a08601826001600160a01b03169052565b5060a0850151601f19808685030160c0870152615c20848361488a565b935060c08701519150808685030160e0870152615c3d848361488a565b935060e08701519150808685030183870152506120c3838261488a565b600060208284031215615c6c57600080fd5b5051919050565b600060ff821660ff8103615c8957615c896153b2565b60010192915050565b848152600067ffffffffffffffff8086166020840152808516604084015250608060608301526120c3608083018461488a565b86815260c060208201526000615cde60c083018861488a565b6001600160a01b039690961660408301525067ffffffffffffffff9384166060820152608081019290925290911660a09091015292915050565b600082825180855260208086019550808260051b84010181860160005b84811015615dca57601f19868403018952815160a08151818652615d5b8287018261488a565b9150508582015185820387870152615d73828261488a565b91505060408083015186830382880152615d8d838261488a565b92505050606080830151818701525060808083015192508582038187015250615db6818361488a565b9a86019a9450505090830190600101615d35565b5090979650505050505050565b602081526000610c126020830184615d18565b60008282518085526020808601955060208260051b8401016020860160005b84811015615dca57601f19868403018952615e2583835161488a565b98840198925090830190600101615e09565b604081526000835180516040840152602081015167ffffffffffffffff80821660608601528060408401511660808601528060608401511660a08601528060808401511660c086015250505060208401516101408060e0850152615e9f61018085018361488a565b915060408601517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08086850301610100870152615edc848361488a565b935060608801519150615efb6101208701836001600160a01b03169052565b60808801518387015260a0880151925080868503016101608701525050615f228282615d18565b9150508281036020840152614ccf8185615dea56fea164736f6c6343000818000a", } var OffRampABI = OffRampMetaData.ABI diff --git a/core/gethwrappers/ccip/generated/onramp/onramp.go b/core/gethwrappers/ccip/generated/onramp/onramp.go index 5a77d6854f..46804a0e47 100644 --- a/core/gethwrappers/ccip/generated/onramp/onramp.go +++ b/core/gethwrappers/ccip/generated/onramp/onramp.go @@ -67,6 +67,7 @@ type InternalRampTokenAmount struct { DestTokenAddress []byte ExtraData []byte Amount *big.Int + DestExecData []byte } type OnRampDestChainConfig struct { @@ -93,8 +94,8 @@ type OnRampStaticConfig struct { } var OnRampMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CannotSendZeroTokens\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GetSupportedTokensFunctionalityRemovedCheckAdminRegistry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidDestChainConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeCalledByRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RouterMustSetOriginalSender\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"UnsupportedToken\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"CCIPSendRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOnRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOnRamp.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"name\":\"DestChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"feeValueJuels\",\"type\":\"uint256\"}],\"name\":\"FeePaid\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeeTokenWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyDestChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"}],\"name\":\"forwardFromRouter\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getExpectedNextSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"getFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"},{\"internalType\":\"contractIERC20\",\"name\":\"sourceToken\",\"type\":\"address\"}],\"name\":\"getPoolBySourceToken\",\"outputs\":[{\"internalType\":\"contractIPoolV1\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"contractIRouter\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"name\":\"getSupportedTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"setDynamicConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"withdrawFeeTokens\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x6101006040523480156200001257600080fd5b50604051620036af380380620036af83398101604081905262000035916200069c565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf8162000186565b505083516001600160401b031615905080620000e6575060208301516001600160a01b0316155b80620000fd575060408301516001600160a01b0316155b8062000114575060608301516001600160a01b0316155b1562000133576040516306b7c75960e31b815260040160405180910390fd5b82516001600160401b031660805260208301516001600160a01b0390811660a0526040840151811660c05260608401511660e052620001728262000231565b6200017d816200036d565b5050506200079c565b336001600160a01b03821603620001e05760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b0316158062000254575060408101516001600160a01b0316155b1562000273576040516306b7c75960e31b815260040160405180910390fd5b8051600280546001600160a01b03199081166001600160a01b03938416179091556020808401805160038054851691861691909117905560408086018051600480549096169087161790945580516080808201835280516001600160401b031680835260a08051891684880190815260c080518b1686880190815260e080518d166060988901908152895196875293518d169a86019a909a52518b169684019690965251891693820193909352885188169181019190915292518616908301529251909316918301919091527f2d8f19dc1cd01460c3367a09d2d424f2b1940ba7c886047edd078c7b77ea4558910160405180910390a150565b60005b8151811015620004aa57600082828151811062000391576200039162000786565b602002602001015190506000838381518110620003b257620003b262000786565b6020026020010151600001519050806001600160401b0316600003620003f75760405163c35aa79d60e01b81526001600160401b038216600482015260240162000083565b6040805180820182526001600160401b03838116600081815260056020818152868320805480871688528a8301516001600160a01b03908116848a019081529587905293835287518551851668010000000000000000026001600160e01b0319909216971696871717905586519485529151169083015291927f324d4a7950b57da00ce533ad6697039be6281726a73da959d0ab3ff795181ec6910160405180910390a250505080600101905062000370565b5050565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b0381118282101715620004e957620004e9620004ae565b60405290565b604051601f8201601f191681016001600160401b03811182821017156200051a576200051a620004ae565b604052919050565b80516001600160401b03811681146200053a57600080fd5b919050565b6001600160a01b03811681146200055557600080fd5b50565b6000606082840312156200056b57600080fd5b604051606081016001600160401b0381118282101715620005905762000590620004ae565b80604052508091508251620005a5816200053f565b81526020830151620005b7816200053f565b60208201526040830151620005cc816200053f565b6040919091015292915050565b600082601f830112620005eb57600080fd5b815160206001600160401b03821115620006095762000609620004ae565b62000619818360051b01620004ef565b82815260069290921b840181019181810190868411156200063957600080fd5b8286015b84811015620006915760408189031215620006585760008081fd5b62000662620004c4565b6200066d8262000522565b8152848201516200067e816200053f565b818601528352918301916040016200063d565b509695505050505050565b6000806000838503610100811215620006b457600080fd5b6080811215620006c357600080fd5b50604051608081016001600160401b038082118383101715620006ea57620006ea620004ae565b81604052620006f98762000522565b8352602087015191506200070d826200053f565b8160208401526040870151915062000725826200053f565b816040840152606087015191506200073d826200053f565b81606084015282955062000755886080890162000558565b945060e08701519250808311156200076c57600080fd5b50506200077c86828701620005d9565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b60805160a05160c05160e051612e9a62000815600039600081816101eb015281816108a201526115da0152600081816101af01528181610dc601526115b3015260008181610173015281816104c4015261158901526000818161014301528181610cec0152818161117c015261155c0152612e9a6000f3fe608060405234801561001057600080fd5b50600436106100f55760003560e01c80637437ff9f11610097578063d77d5ed011610066578063d77d5ed0146103ba578063df0aa9e914610406578063f2fde38b14610419578063fbca3b741461042c57600080fd5b80637437ff9f146102fb57806379ba5097146103685780638da5cb5b146103705780639041be3d1461038e57600080fd5b806320487ded116100d357806320487ded1461028757806334d560e4146102a85780633a019940146102bb57806348a98aa4146102c357600080fd5b80630242cf60146100fa57806306285c691461010f578063181f5a771461023e575b600080fd5b61010d610108366004611fe6565b61044c565b005b61022860408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16815250905090565b60405161023591906120a9565b60405180910390f35b61027a6040518060400160405280601081526020017f4f6e52616d7020312e362e302d6465760000000000000000000000000000000081525081565b604051610235919061216e565b61029a610295366004612199565b610460565b604051908152602001610235565b61010d6102b63660046121f9565b610619565b61010d61062a565b6102d66102d136600461226b565b61085a565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610235565b61035b6040805160608101825260008082526020820181905291810191909152506040805160608101825260025473ffffffffffffffffffffffffffffffffffffffff908116825260035481166020830152600454169181019190915290565b60405161023591906122a4565b61010d61090f565b60005473ffffffffffffffffffffffffffffffffffffffff166102d6565b6103a161039c3660046122e1565b610a0c565b60405167ffffffffffffffff9091168152602001610235565b6102d66103c83660046122e1565b67ffffffffffffffff1660009081526005602052604090205468010000000000000000900473ffffffffffffffffffffffffffffffffffffffff1690565b61029a6104143660046122fe565b610a35565b61010d61042736600461236a565b611230565b61043f61043a3660046122e1565b611241565b6040516102359190612387565b610454611275565b61045d816112f8565b50565b6040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815277ffffffffffffffff00000000000000000000000000000000608084901b16600482015260009073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690632cbc26bb90602401602060405180830381865afa15801561050b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061052f91906123f1565b15610577576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024015b60405180910390fd5b6002546040517fd8694ccd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063d8694ccd906105cf9086908690600401612520565b602060405180830381865afa1580156105ec573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106109190612669565b90505b92915050565b610621611275565b61045d81611470565b600254604080517fcdc73d51000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163cdc73d5191600480830192869291908290030181865afa158015610699573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526106df9190810190612682565b60045490915073ffffffffffffffffffffffffffffffffffffffff1660005b825181101561085557600083828151811061071b5761071b612711565b60209081029190910101516040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915060009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa158015610796573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107ba9190612669565b9050801561084b576107e373ffffffffffffffffffffffffffffffffffffffff8316858361163a565b8173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f508d7d183612c18fc339b42618912b9fa3239f631dd7ec0671f950200a0fa66e8360405161084291815260200190565b60405180910390a35b50506001016106fe565b505050565b6040517fbbe4f6db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063bbe4f6db90602401602060405180830381865afa1580156108eb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106109190612740565b60015473ffffffffffffffffffffffffffffffffffffffff163314610990576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e657200000000000000000000604482015260640161056e565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b67ffffffffffffffff80821660009081526005602052604081205490916106139116600161278c565b67ffffffffffffffff8416600090815260056020526040812073ffffffffffffffffffffffffffffffffffffffff8316610a9b576040517fa4ec747900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805468010000000000000000900473ffffffffffffffffffffffffffffffffffffffff163314610af7576040517f1c0a352900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60035473ffffffffffffffffffffffffffffffffffffffff168015610b9d576040517fe0a0e50600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82169063e0a0e50690610b6a908a908a90600401612520565b600060405180830381600087803b158015610b8457600080fd5b505af1158015610b98573d6000803e3d6000fd5b505050505b506002546000908190819073ffffffffffffffffffffffffffffffffffffffff1663c4276bfc8a610bd460808c0160608d0161236a565b8a610be260808e018e6127b4565b6040518663ffffffff1660e01b8152600401610c02959493929190612819565b600060405180830381865afa158015610c1f573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610c6591908101906128e1565b91945092509050610c7c6080890160608a0161236a565b73ffffffffffffffffffffffffffffffffffffffff167f075a2720282fdf622141dae0b048ef90a21a7e57c134c76912d19d006b3b3f6f84604051610cc391815260200190565b60405180910390a2604080516101a081019091526000610100820181815267ffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000081166101208501528c811661014085015287549293928392916101608401918a918791610d389116612938565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905567ffffffffffffffff16815260200186610e38576040517fea458c0c00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8f16600482015273ffffffffffffffffffffffffffffffffffffffff8c811660248301527f0000000000000000000000000000000000000000000000000000000000000000169063ea458c0c906044016020604051808303816000875af1158015610e0f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e33919061295f565b610e3b565b60005b67ffffffffffffffff1681525081526020018873ffffffffffffffffffffffffffffffffffffffff1681526020018a8060200190610e7991906127b4565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250505090825250602001610ebd8b806127b4565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250505090825250602001610f0460808c018c6127b4565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250505090825250602001610f4e60808c0160608d0161236a565b73ffffffffffffffffffffffffffffffffffffffff1681526020018981526020018a8060400190610f7f919061297c565b905067ffffffffffffffff811115610f9957610f99611ee3565b604051908082528060200260200182016040528015610ff557816020015b610fe26040518060800160405280606081526020016060815260200160608152602001600081525090565b815260200190600190039081610fb75790505b509052905060005b61100a60408b018b61297c565b90508110156110b95761109061102360408c018c61297c565b8381811061103357611033612711565b90506040020180360381019061104991906129e4565b8c6110548d806127b4565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508e92506116c7915050565b8260e0015182815181106110a6576110a6612711565b6020908102919091010152600101610ffd565b5060025460e082015173ffffffffffffffffffffffffffffffffffffffff9091169063cc88924c908c906110f060408e018e61297c565b6040518563ffffffff1660e01b815260040161110f9493929190612ae0565b60006040518083038186803b15801561112757600080fd5b505afa15801561113b573d6000803e3d6000fd5b505050506080808201839052604080517f130ac867e79e2789f923760a88743d292acdf7002139a588206e2260f73f7321602082015267ffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811692820192909252908c16606082015230918101919091526111d890829060a001604051602081830303815290604052805190602001206119d1565b81515260405167ffffffffffffffff8b16907f0f07cd31e53232da9125e517f09550fdde74bf43d6a0a76ebd41674dafe2ab2990611217908490612b16565b60405180910390a251519450505050505b949350505050565b611238611275565b61045d81611ad1565b60606040517f9e7177c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005473ffffffffffffffffffffffffffffffffffffffff1633146112f6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640161056e565b565b60005b815181101561146c57600082828151811061131857611318612711565b60200260200101519050600083838151811061133657611336612711565b60200260200101516000015190508067ffffffffffffffff16600003611394576040517fc35aa79d00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8216600482015260240161056e565b60408051808201825267ffffffffffffffff838116600081815260056020818152868320805480871688528a83015173ffffffffffffffffffffffffffffffffffffffff908116848a019081529587905293835287518551851668010000000000000000027fffffffff00000000000000000000000000000000000000000000000000000000909216971696871717905586519485529151169083015291927f324d4a7950b57da00ce533ad6697039be6281726a73da959d0ab3ff795181ec6910160405180910390a25050508060010190506112fb565b5050565b805173ffffffffffffffffffffffffffffffffffffffff1615806114ac5750604081015173ffffffffffffffffffffffffffffffffffffffff16155b156114e3576040517f35be3ac800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051600280547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff93841617909155602080840151600380548416918516919091179055604080850151600480549094169085161790925581516080810183527f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681527f00000000000000000000000000000000000000000000000000000000000000008416918101919091527f00000000000000000000000000000000000000000000000000000000000000008316818301527f00000000000000000000000000000000000000000000000000000000000000009092166060830152517f2d8f19dc1cd01460c3367a09d2d424f2b1940ba7c886047edd078c7b77ea45589161162f918490612c64565b60405180910390a150565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052610855908490611bc6565b6116f26040518060800160405280606081526020016060815260200160608152602001600081525090565b8460200151600003611730576040517f5cf0444900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061174085876000015161085a565b905073ffffffffffffffffffffffffffffffffffffffff8116158061181057506040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527faff2afbf00000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff8216906301ffc9a790602401602060405180830381865afa1580156117ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061180e91906123f1565b155b156118625785516040517fbf16aab600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116600482015260240161056e565b60008173ffffffffffffffffffffffffffffffffffffffff16639a4575b96040518060a001604052808881526020018967ffffffffffffffff1681526020018773ffffffffffffffffffffffffffffffffffffffff1681526020018a6020015181526020018a6000015173ffffffffffffffffffffffffffffffffffffffff168152506040518263ffffffff1660e01b81526004016119019190612cf6565b6000604051808303816000875af1158015611920573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526119669190810190612d6c565b604080516080810190915273ffffffffffffffffffffffffffffffffffffffff841660a08201529091508060c0810160405160208183030381529060405281526020018260000151815260200182602001518152602001886020015181525092505050949350505050565b60008060001b82846020015185606001518660000151606001518760000151608001518860a001518960c00151604051602001611a1396959493929190612dfd565b604051602081830303815290604052805190602001208560400151805190602001208660e00151604051602001611a4a9190612e5e565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201206080808c0151805190840120928501989098529183019590955260608201939093529384015260a083015260c082015260e00160405160208183030381529060405280519060200120905092915050565b3373ffffffffffffffffffffffffffffffffffffffff821603611b50576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161056e565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000611c28826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611cd29092919063ffffffff16565b8051909150156108555780806020019051810190611c4691906123f1565b610855576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f74207375636365656400000000000000000000000000000000000000000000606482015260840161056e565b6060611ce18484600085611ceb565b90505b9392505050565b606082471015611d7d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c0000000000000000000000000000000000000000000000000000606482015260840161056e565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051611da69190612e71565b60006040518083038185875af1925050503d8060008114611de3576040519150601f19603f3d011682016040523d82523d6000602084013e611de8565b606091505b5091509150611df987838387611e04565b979650505050505050565b60608315611e9a578251600003611e935773ffffffffffffffffffffffffffffffffffffffff85163b611e93576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161056e565b5081611228565b6112288383815115611eaf5781518083602001fd5b806040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161056e919061216e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715611f3557611f35611ee3565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611f8257611f82611ee3565b604052919050565b600067ffffffffffffffff821115611fa457611fa4611ee3565b5060051b60200190565b67ffffffffffffffff8116811461045d57600080fd5b73ffffffffffffffffffffffffffffffffffffffff8116811461045d57600080fd5b60006020808385031215611ff957600080fd5b823567ffffffffffffffff81111561201057600080fd5b8301601f8101851361202157600080fd5b803561203461202f82611f8a565b611f3b565b81815260069190911b8201830190838101908783111561205357600080fd5b928401925b82841015611df957604084890312156120715760008081fd5b612079611f12565b843561208481611fae565b81528486013561209381611fc4565b8187015282526040939093019290840190612058565b60808101610613828467ffffffffffffffff8151168252602081015173ffffffffffffffffffffffffffffffffffffffff808216602085015280604084015116604085015280606084015116606085015250505050565b60005b8381101561211b578181015183820152602001612103565b50506000910152565b6000815180845261213c816020860160208601612100565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006106106020830184612124565b600060a0828403121561219357600080fd5b50919050565b600080604083850312156121ac57600080fd5b82356121b781611fae565b9150602083013567ffffffffffffffff8111156121d357600080fd5b6121df85828601612181565b9150509250929050565b80356121f481611fc4565b919050565b60006060828403121561220b57600080fd5b6040516060810181811067ffffffffffffffff8211171561222e5761222e611ee3565b604052823561223c81611fc4565b8152602083013561224c81611fc4565b6020820152604083013561225f81611fc4565b60408201529392505050565b6000806040838503121561227e57600080fd5b823561228981611fae565b9150602083013561229981611fc4565b809150509250929050565b606081016106138284805173ffffffffffffffffffffffffffffffffffffffff908116835260208083015182169084015260409182015116910152565b6000602082840312156122f357600080fd5b8135611ce481611fae565b6000806000806080858703121561231457600080fd5b843561231f81611fae565b9350602085013567ffffffffffffffff81111561233b57600080fd5b61234787828801612181565b93505060408501359150606085013561235f81611fc4565b939692955090935050565b60006020828403121561237c57600080fd5b8135611ce481611fc4565b6020808252825182820181905260009190848201906040850190845b818110156123d557835173ffffffffffffffffffffffffffffffffffffffff16835292840192918401916001016123a3565b50909695505050505050565b805180151581146121f457600080fd5b60006020828403121561240357600080fd5b610610826123e1565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261244157600080fd5b830160208101925035905067ffffffffffffffff81111561246157600080fd5b80360382131561247057600080fd5b9250929050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b8183526000602080850194508260005b858110156125155781356124e381611fc4565b73ffffffffffffffffffffffffffffffffffffffff1687528183013583880152604096870196909101906001016124d0565b509495945050505050565b600067ffffffffffffffff808516835260406020840152612541848561240c565b60a0604086015261255660e086018284612477565b915050612566602086018661240c565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08087850301606088015261259c848385612477565b9350604088013592507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18836030183126125d557600080fd5b602092880192830192359150848211156125ee57600080fd5b8160061b360383131561260057600080fd5b808785030160808801526126158483856124c0565b9450612623606089016121e9565b73ffffffffffffffffffffffffffffffffffffffff811660a0890152935061264e608089018961240c565b94509250808786030160c08801525050611df9838383612477565b60006020828403121561267b57600080fd5b5051919050565b6000602080838503121561269557600080fd5b825167ffffffffffffffff8111156126ac57600080fd5b8301601f810185136126bd57600080fd5b80516126cb61202f82611f8a565b81815260059190911b820183019083810190878311156126ea57600080fd5b928401925b82841015611df957835161270281611fc4565b825292840192908401906126ef565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561275257600080fd5b8151611ce481611fc4565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b67ffffffffffffffff8181168382160190808211156127ad576127ad61275d565b5092915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126127e957600080fd5b83018035915067ffffffffffffffff82111561280457600080fd5b60200191503681900382131561247057600080fd5b67ffffffffffffffff8616815273ffffffffffffffffffffffffffffffffffffffff85166020820152836040820152608060608201526000611df9608083018486612477565b600082601f83011261287057600080fd5b815167ffffffffffffffff81111561288a5761288a611ee3565b6128bb60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611f3b565b8181528460208386010111156128d057600080fd5b611228826020830160208701612100565b6000806000606084860312156128f657600080fd5b83519250612906602085016123e1565b9150604084015167ffffffffffffffff81111561292257600080fd5b61292e8682870161285f565b9150509250925092565b600067ffffffffffffffff8083168181036129555761295561275d565b6001019392505050565b60006020828403121561297157600080fd5b8151611ce481611fae565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126129b157600080fd5b83018035915067ffffffffffffffff8211156129cc57600080fd5b6020019150600681901b360382131561247057600080fd5b6000604082840312156129f657600080fd5b6129fe611f12565b8235612a0981611fc4565b81526020928301359281019290925250919050565b600082825180855260208086019550808260051b84010181860160005b84811015612ad3577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018952815160808151818652612a7f82870182612124565b9150508582015185820387870152612a978282612124565b91505060408083015186830382880152612ab18382612124565b6060948501519790940196909652505098840198925090830190600101612a3b565b5090979650505050505050565b67ffffffffffffffff85168152606060208201526000612b036060830186612a1e565b8281036040840152611df98185876124c0565b60208152612b6760208201835180518252602081015167ffffffffffffffff808216602085015280604084015116604085015280606084015116606085015280608084015116608085015250505050565b60006020830151612b9060c084018273ffffffffffffffffffffffffffffffffffffffff169052565b5060408301516101808060e0850152612bad6101a0850183612124565b915060608501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08086850301610100870152612bea8483612124565b9350608087015191508086850301610120870152612c088483612124565b935060a08701519150612c3461014087018373ffffffffffffffffffffffffffffffffffffffff169052565b60c087015161016087015260e0870151915080868503018387015250612c5a8382612a1e565b9695505050505050565b60e08101612cbb828567ffffffffffffffff8151168252602081015173ffffffffffffffffffffffffffffffffffffffff808216602085015280604084015116604085015280606084015116606085015250505050565b825173ffffffffffffffffffffffffffffffffffffffff90811660808401526020840151811660a084015260408401511660c0830152611ce4565b602081526000825160a06020840152612d1260c0840182612124565b905067ffffffffffffffff6020850151166040840152604084015173ffffffffffffffffffffffffffffffffffffffff8082166060860152606086015160808601528060808701511660a086015250508091505092915050565b600060208284031215612d7e57600080fd5b815167ffffffffffffffff80821115612d9657600080fd5b9083019060408286031215612daa57600080fd5b612db2611f12565b825182811115612dc157600080fd5b612dcd8782860161285f565b825250602083015182811115612de257600080fd5b612dee8782860161285f565b60208301525095945050505050565b600073ffffffffffffffffffffffffffffffffffffffff808916835260c06020840152612e2d60c0840189612124565b67ffffffffffffffff97881660408501529590961660608301525091909316608082015260a0019190915292915050565b6020815260006106106020830184612a1e565b60008251612e83818460208701612100565b919091019291505056fea164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CannotSendZeroTokens\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GetSupportedTokensFunctionalityRemovedCheckAdminRegistry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidDestChainConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeCalledByRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RouterMustSetOriginalSender\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"UnsupportedToken\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"CCIPSendRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOnRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOnRamp.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"name\":\"DestChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"feeValueJuels\",\"type\":\"uint256\"}],\"name\":\"FeePaid\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeeTokenWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyDestChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"}],\"name\":\"forwardFromRouter\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getExpectedNextSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"getFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"},{\"internalType\":\"contractIERC20\",\"name\":\"sourceToken\",\"type\":\"address\"}],\"name\":\"getPoolBySourceToken\",\"outputs\":[{\"internalType\":\"contractIPoolV1\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"contractIRouter\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"name\":\"getSupportedTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"setDynamicConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"withdrawFeeTokens\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x6101006040523480156200001257600080fd5b506040516200382d3803806200382d83398101604081905262000035916200069c565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf8162000186565b505083516001600160401b031615905080620000e6575060208301516001600160a01b0316155b80620000fd575060408301516001600160a01b0316155b8062000114575060608301516001600160a01b0316155b1562000133576040516306b7c75960e31b815260040160405180910390fd5b82516001600160401b031660805260208301516001600160a01b0390811660a0526040840151811660c05260608401511660e052620001728262000231565b6200017d816200036d565b5050506200079c565b336001600160a01b03821603620001e05760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b0316158062000254575060408101516001600160a01b0316155b1562000273576040516306b7c75960e31b815260040160405180910390fd5b8051600280546001600160a01b03199081166001600160a01b03938416179091556020808401805160038054851691861691909117905560408086018051600480549096169087161790945580516080808201835280516001600160401b031680835260a08051891684880190815260c080518b1686880190815260e080518d166060988901908152895196875293518d169a86019a909a52518b169684019690965251891693820193909352885188169181019190915292518616908301529251909316918301919091527f2d8f19dc1cd01460c3367a09d2d424f2b1940ba7c886047edd078c7b77ea4558910160405180910390a150565b60005b8151811015620004aa57600082828151811062000391576200039162000786565b602002602001015190506000838381518110620003b257620003b262000786565b6020026020010151600001519050806001600160401b0316600003620003f75760405163c35aa79d60e01b81526001600160401b038216600482015260240162000083565b6040805180820182526001600160401b03838116600081815260056020818152868320805480871688528a8301516001600160a01b03908116848a019081529587905293835287518551851668010000000000000000026001600160e01b0319909216971696871717905586519485529151169083015291927f324d4a7950b57da00ce533ad6697039be6281726a73da959d0ab3ff795181ec6910160405180910390a250505080600101905062000370565b5050565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b0381118282101715620004e957620004e9620004ae565b60405290565b604051601f8201601f191681016001600160401b03811182821017156200051a576200051a620004ae565b604052919050565b80516001600160401b03811681146200053a57600080fd5b919050565b6001600160a01b03811681146200055557600080fd5b50565b6000606082840312156200056b57600080fd5b604051606081016001600160401b0381118282101715620005905762000590620004ae565b80604052508091508251620005a5816200053f565b81526020830151620005b7816200053f565b60208201526040830151620005cc816200053f565b6040919091015292915050565b600082601f830112620005eb57600080fd5b815160206001600160401b03821115620006095762000609620004ae565b62000619818360051b01620004ef565b82815260069290921b840181019181810190868411156200063957600080fd5b8286015b84811015620006915760408189031215620006585760008081fd5b62000662620004c4565b6200066d8262000522565b8152848201516200067e816200053f565b818601528352918301916040016200063d565b509695505050505050565b6000806000838503610100811215620006b457600080fd5b6080811215620006c357600080fd5b50604051608081016001600160401b038082118383101715620006ea57620006ea620004ae565b81604052620006f98762000522565b8352602087015191506200070d826200053f565b8160208401526040870151915062000725826200053f565b816040840152606087015191506200073d826200053f565b81606084015282955062000755886080890162000558565b945060e08701519250808311156200076c57600080fd5b50506200077c86828701620005d9565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b60805160a05160c05160e05161301862000815600039600081816101eb015281816108a201526116700152600081816101af01528181610dc60152611649015260008181610173015281816104c4015261161f01526000818161014301528181610cec0152818161121101526115f201526130186000f3fe608060405234801561001057600080fd5b50600436106100f55760003560e01c80637437ff9f11610097578063d77d5ed011610066578063d77d5ed0146103ba578063df0aa9e914610406578063f2fde38b14610419578063fbca3b741461042c57600080fd5b80637437ff9f146102fb57806379ba5097146103685780638da5cb5b146103705780639041be3d1461038e57600080fd5b806320487ded116100d357806320487ded1461028757806334d560e4146102a85780633a019940146102bb57806348a98aa4146102c357600080fd5b80630242cf60146100fa57806306285c691461010f578063181f5a771461023e575b600080fd5b61010d610108366004612098565b61044c565b005b61022860408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16815250905090565b604051610235919061215b565b60405180910390f35b61027a6040518060400160405280601081526020017f4f6e52616d7020312e362e302d6465760000000000000000000000000000000081525081565b6040516102359190612220565b61029a61029536600461224b565b610460565b604051908152602001610235565b61010d6102b63660046122ab565b610619565b61010d61062a565b6102d66102d136600461231d565b61085a565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610235565b61035b6040805160608101825260008082526020820181905291810191909152506040805160608101825260025473ffffffffffffffffffffffffffffffffffffffff908116825260035481166020830152600454169181019190915290565b6040516102359190612356565b61010d61090f565b60005473ffffffffffffffffffffffffffffffffffffffff166102d6565b6103a161039c366004612393565b610a0c565b60405167ffffffffffffffff9091168152602001610235565b6102d66103c8366004612393565b67ffffffffffffffff1660009081526005602052604090205468010000000000000000900473ffffffffffffffffffffffffffffffffffffffff1690565b61029a6104143660046123b0565b610a35565b61010d61042736600461241c565b6112c6565b61043f61043a366004612393565b6112d7565b6040516102359190612439565b61045461130b565b61045d8161138e565b50565b6040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815277ffffffffffffffff00000000000000000000000000000000608084901b16600482015260009073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690632cbc26bb90602401602060405180830381865afa15801561050b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061052f91906124a3565b15610577576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024015b60405180910390fd5b6002546040517fd8694ccd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063d8694ccd906105cf90869086906004016125d2565b602060405180830381865afa1580156105ec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610610919061271b565b90505b92915050565b61062161130b565b61045d81611506565b600254604080517fcdc73d51000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163cdc73d5191600480830192869291908290030181865afa158015610699573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526106df9190810190612734565b60045490915073ffffffffffffffffffffffffffffffffffffffff1660005b825181101561085557600083828151811061071b5761071b6127c3565b60209081029190910101516040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915060009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa158015610796573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107ba919061271b565b9050801561084b576107e373ffffffffffffffffffffffffffffffffffffffff831685836116d0565b8173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f508d7d183612c18fc339b42618912b9fa3239f631dd7ec0671f950200a0fa66e8360405161084291815260200190565b60405180910390a35b50506001016106fe565b505050565b6040517fbbe4f6db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063bbe4f6db90602401602060405180830381865afa1580156108eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061061091906127f2565b60015473ffffffffffffffffffffffffffffffffffffffff163314610990576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e657200000000000000000000604482015260640161056e565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b67ffffffffffffffff80821660009081526005602052604081205490916106139116600161283e565b67ffffffffffffffff8416600090815260056020526040812073ffffffffffffffffffffffffffffffffffffffff8316610a9b576040517fa4ec747900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805468010000000000000000900473ffffffffffffffffffffffffffffffffffffffff163314610af7576040517f1c0a352900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60035473ffffffffffffffffffffffffffffffffffffffff168015610b9d576040517fe0a0e50600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82169063e0a0e50690610b6a908a908a906004016125d2565b600060405180830381600087803b158015610b8457600080fd5b505af1158015610b98573d6000803e3d6000fd5b505050505b506002546000908190819073ffffffffffffffffffffffffffffffffffffffff1663c4276bfc8a610bd460808c0160608d0161241c565b8a610be260808e018e612866565b6040518663ffffffff1660e01b8152600401610c029594939291906128cb565b600060405180830381865afa158015610c1f573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610c659190810190612993565b91945092509050610c7c6080890160608a0161241c565b73ffffffffffffffffffffffffffffffffffffffff167f075a2720282fdf622141dae0b048ef90a21a7e57c134c76912d19d006b3b3f6f84604051610cc391815260200190565b60405180910390a2604080516101a081019091526000610100820181815267ffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000081166101208501528c811661014085015287549293928392916101608401918a918791610d3891166129ea565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905567ffffffffffffffff16815260200186610e38576040517fea458c0c00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8f16600482015273ffffffffffffffffffffffffffffffffffffffff8c811660248301527f0000000000000000000000000000000000000000000000000000000000000000169063ea458c0c906044016020604051808303816000875af1158015610e0f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e339190612a11565b610e3b565b60005b67ffffffffffffffff1681525081526020018873ffffffffffffffffffffffffffffffffffffffff1681526020018a8060200190610e799190612866565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250505090825250602001610ebd8b80612866565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250505090825250602001610f0460808c018c612866565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250505090825250602001610f4e60808c0160608d0161241c565b73ffffffffffffffffffffffffffffffffffffffff1681526020018981526020018a8060400190610f7f9190612a2e565b905067ffffffffffffffff811115610f9957610f99611f95565b604051908082528060200260200182016040528015610ffc57816020015b610fe96040518060a0016040528060608152602001606081526020016060815260200160008152602001606081525090565b815260200190600190039081610fb75790505b509052905060005b61101160408b018b612a2e565b90508110156110c05761109761102a60408c018c612a2e565b8381811061103a5761103a6127c3565b9050604002018036038101906110509190612a96565b8c61105b8d80612866565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508e925061175d915050565b8260e0015182815181106110ad576110ad6127c3565b6020908102919091010152600101611004565b5060025460e082015160009173ffffffffffffffffffffffffffffffffffffffff169063085318f8908d906110f860408f018f612a2e565b6040518563ffffffff1660e01b81526004016111179493929190612bad565b600060405180830381865afa158015611134573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261117a9190810190612be3565b905060005b8260e00151518110156111d35781818151811061119e5761119e6127c3565b60200260200101518360e0015182815181106111bc576111bc6127c3565b60209081029190910101516080015260010161117f565b506080808301849052604080517f130ac867e79e2789f923760a88743d292acdf7002139a588206e2260f73f7321602082015267ffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811692820192909252908d166060820152309181019190915261126d90839060a00160405160208183030381529060405280519060200120611a83565b82515260405167ffffffffffffffff8c16907fcae3d9f68a9ed33d0a770e9bcc6fc25d4041dd6391e6cd8015546547a3c93140906112ac908590612c94565b60405180910390a25051519450505050505b949350505050565b6112ce61130b565b61045d81611b83565b60606040517f9e7177c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005473ffffffffffffffffffffffffffffffffffffffff16331461138c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640161056e565b565b60005b81518110156115025760008282815181106113ae576113ae6127c3565b6020026020010151905060008383815181106113cc576113cc6127c3565b60200260200101516000015190508067ffffffffffffffff1660000361142a576040517fc35aa79d00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8216600482015260240161056e565b60408051808201825267ffffffffffffffff838116600081815260056020818152868320805480871688528a83015173ffffffffffffffffffffffffffffffffffffffff908116848a019081529587905293835287518551851668010000000000000000027fffffffff00000000000000000000000000000000000000000000000000000000909216971696871717905586519485529151169083015291927f324d4a7950b57da00ce533ad6697039be6281726a73da959d0ab3ff795181ec6910160405180910390a2505050806001019050611391565b5050565b805173ffffffffffffffffffffffffffffffffffffffff1615806115425750604081015173ffffffffffffffffffffffffffffffffffffffff16155b15611579576040517f35be3ac800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051600280547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff93841617909155602080840151600380548416918516919091179055604080850151600480549094169085161790925581516080810183527f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681527f00000000000000000000000000000000000000000000000000000000000000008416918101919091527f00000000000000000000000000000000000000000000000000000000000000008316818301527f00000000000000000000000000000000000000000000000000000000000000009092166060830152517f2d8f19dc1cd01460c3367a09d2d424f2b1940ba7c886047edd078c7b77ea4558916116c5918490612de2565b60405180910390a150565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052610855908490611c78565b61178f6040518060a0016040528060608152602001606081526020016060815260200160008152602001606081525090565b84602001516000036117cd576040517f5cf0444900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006117dd85876000015161085a565b905073ffffffffffffffffffffffffffffffffffffffff811615806118ad57506040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527faff2afbf00000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff8216906301ffc9a790602401602060405180830381865afa158015611887573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118ab91906124a3565b155b156118ff5785516040517fbf16aab600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116600482015260240161056e565b60008173ffffffffffffffffffffffffffffffffffffffff16639a4575b96040518060a001604052808881526020018967ffffffffffffffff1681526020018773ffffffffffffffffffffffffffffffffffffffff1681526020018a6020015181526020018a6000015173ffffffffffffffffffffffffffffffffffffffff168152506040518263ffffffff1660e01b815260040161199e9190612e74565b6000604051808303816000875af11580156119bd573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611a039190810190612eea565b6040805160a0810190915273ffffffffffffffffffffffffffffffffffffffff841660c08201529091508060e0810160405160208183030381529060405281526020018260000151815260200182602001518152602001886020015181526020016040518060200160405280600081525081525092505050949350505050565b60008060001b82846020015185606001518660000151606001518760000151608001518860a001518960c00151604051602001611ac596959493929190612f7b565b604051602081830303815290604052805190602001208560400151805190602001208660e00151604051602001611afc9190612fdc565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201206080808c0151805190840120928501989098529183019590955260608201939093529384015260a083015260c082015260e00160405160208183030381529060405280519060200120905092915050565b3373ffffffffffffffffffffffffffffffffffffffff821603611c02576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161056e565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000611cda826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611d849092919063ffffffff16565b8051909150156108555780806020019051810190611cf891906124a3565b610855576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f74207375636365656400000000000000000000000000000000000000000000606482015260840161056e565b6060611d938484600085611d9d565b90505b9392505050565b606082471015611e2f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c0000000000000000000000000000000000000000000000000000606482015260840161056e565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051611e589190612fef565b60006040518083038185875af1925050503d8060008114611e95576040519150601f19603f3d011682016040523d82523d6000602084013e611e9a565b606091505b5091509150611eab87838387611eb6565b979650505050505050565b60608315611f4c578251600003611f455773ffffffffffffffffffffffffffffffffffffffff85163b611f45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161056e565b50816112be565b6112be8383815115611f615781518083602001fd5b806040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161056e9190612220565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715611fe757611fe7611f95565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561203457612034611f95565b604052919050565b600067ffffffffffffffff82111561205657612056611f95565b5060051b60200190565b67ffffffffffffffff8116811461045d57600080fd5b73ffffffffffffffffffffffffffffffffffffffff8116811461045d57600080fd5b600060208083850312156120ab57600080fd5b823567ffffffffffffffff8111156120c257600080fd5b8301601f810185136120d357600080fd5b80356120e66120e18261203c565b611fed565b81815260069190911b8201830190838101908783111561210557600080fd5b928401925b82841015611eab57604084890312156121235760008081fd5b61212b611fc4565b843561213681612060565b81528486013561214581612076565b818701528252604093909301929084019061210a565b60808101610613828467ffffffffffffffff8151168252602081015173ffffffffffffffffffffffffffffffffffffffff808216602085015280604084015116604085015280606084015116606085015250505050565b60005b838110156121cd5781810151838201526020016121b5565b50506000910152565b600081518084526121ee8160208601602086016121b2565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061061060208301846121d6565b600060a0828403121561224557600080fd5b50919050565b6000806040838503121561225e57600080fd5b823561226981612060565b9150602083013567ffffffffffffffff81111561228557600080fd5b61229185828601612233565b9150509250929050565b80356122a681612076565b919050565b6000606082840312156122bd57600080fd5b6040516060810181811067ffffffffffffffff821117156122e0576122e0611f95565b60405282356122ee81612076565b815260208301356122fe81612076565b6020820152604083013561231181612076565b60408201529392505050565b6000806040838503121561233057600080fd5b823561233b81612060565b9150602083013561234b81612076565b809150509250929050565b606081016106138284805173ffffffffffffffffffffffffffffffffffffffff908116835260208083015182169084015260409182015116910152565b6000602082840312156123a557600080fd5b8135611d9681612060565b600080600080608085870312156123c657600080fd5b84356123d181612060565b9350602085013567ffffffffffffffff8111156123ed57600080fd5b6123f987828801612233565b93505060408501359150606085013561241181612076565b939692955090935050565b60006020828403121561242e57600080fd5b8135611d9681612076565b6020808252825182820181905260009190848201906040850190845b8181101561248757835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101612455565b50909695505050505050565b805180151581146122a657600080fd5b6000602082840312156124b557600080fd5b61061082612493565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126124f357600080fd5b830160208101925035905067ffffffffffffffff81111561251357600080fd5b80360382131561252257600080fd5b9250929050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b8183526000602080850194508260005b858110156125c757813561259581612076565b73ffffffffffffffffffffffffffffffffffffffff168752818301358388015260409687019690910190600101612582565b509495945050505050565b600067ffffffffffffffff8085168352604060208401526125f384856124be565b60a0604086015261260860e086018284612529565b91505061261860208601866124be565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08087850301606088015261264e848385612529565b9350604088013592507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe188360301831261268757600080fd5b602092880192830192359150848211156126a057600080fd5b8160061b36038313156126b257600080fd5b808785030160808801526126c7848385612572565b94506126d56060890161229b565b73ffffffffffffffffffffffffffffffffffffffff811660a0890152935061270060808901896124be565b94509250808786030160c08801525050611eab838383612529565b60006020828403121561272d57600080fd5b5051919050565b6000602080838503121561274757600080fd5b825167ffffffffffffffff81111561275e57600080fd5b8301601f8101851361276f57600080fd5b805161277d6120e18261203c565b81815260059190911b8201830190838101908783111561279c57600080fd5b928401925b82841015611eab5783516127b481612076565b825292840192908401906127a1565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561280457600080fd5b8151611d9681612076565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b67ffffffffffffffff81811683821601908082111561285f5761285f61280f565b5092915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261289b57600080fd5b83018035915067ffffffffffffffff8211156128b657600080fd5b60200191503681900382131561252257600080fd5b67ffffffffffffffff8616815273ffffffffffffffffffffffffffffffffffffffff85166020820152836040820152608060608201526000611eab608083018486612529565b600082601f83011261292257600080fd5b815167ffffffffffffffff81111561293c5761293c611f95565b61296d60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611fed565b81815284602083860101111561298257600080fd5b6112be8260208301602087016121b2565b6000806000606084860312156129a857600080fd5b835192506129b860208501612493565b9150604084015167ffffffffffffffff8111156129d457600080fd5b6129e086828701612911565b9150509250925092565b600067ffffffffffffffff808316818103612a0757612a0761280f565b6001019392505050565b600060208284031215612a2357600080fd5b8151611d9681612060565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112612a6357600080fd5b83018035915067ffffffffffffffff821115612a7e57600080fd5b6020019150600681901b360382131561252257600080fd5b600060408284031215612aa857600080fd5b612ab0611fc4565b8235612abb81612076565b81526020928301359281019290925250919050565b600082825180855260208086019550808260051b84010181860160005b84811015612ba0577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018952815160a08151818652612b31828701826121d6565b9150508582015185820387870152612b4982826121d6565b91505060408083015186830382880152612b6383826121d6565b92505050606080830151818701525060808083015192508582038187015250612b8c81836121d6565b9a86019a9450505090830190600101612aed565b5090979650505050505050565b67ffffffffffffffff85168152606060208201526000612bd06060830186612ad0565b8281036040840152611eab818587612572565b60006020808385031215612bf657600080fd5b825167ffffffffffffffff80821115612c0e57600080fd5b818501915085601f830112612c2257600080fd5b8151612c306120e18261203c565b81815260059190911b83018401908481019088831115612c4f57600080fd5b8585015b83811015612c8757805185811115612c6b5760008081fd5b612c798b89838a0101612911565b845250918601918601612c53565b5098975050505050505050565b60208152612ce560208201835180518252602081015167ffffffffffffffff808216602085015280604084015116604085015280606084015116606085015280608084015116608085015250505050565b60006020830151612d0e60c084018273ffffffffffffffffffffffffffffffffffffffff169052565b5060408301516101808060e0850152612d2b6101a08501836121d6565b915060608501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08086850301610100870152612d6884836121d6565b9350608087015191508086850301610120870152612d8684836121d6565b935060a08701519150612db261014087018373ffffffffffffffffffffffffffffffffffffffff169052565b60c087015161016087015260e0870151915080868503018387015250612dd88382612ad0565b9695505050505050565b60e08101612e39828567ffffffffffffffff8151168252602081015173ffffffffffffffffffffffffffffffffffffffff808216602085015280604084015116604085015280606084015116606085015250505050565b825173ffffffffffffffffffffffffffffffffffffffff90811660808401526020840151811660a084015260408401511660c0830152611d96565b602081526000825160a06020840152612e9060c08401826121d6565b905067ffffffffffffffff6020850151166040840152604084015173ffffffffffffffffffffffffffffffffffffffff8082166060860152606086015160808601528060808701511660a086015250508091505092915050565b600060208284031215612efc57600080fd5b815167ffffffffffffffff80821115612f1457600080fd5b9083019060408286031215612f2857600080fd5b612f30611fc4565b825182811115612f3f57600080fd5b612f4b87828601612911565b825250602083015182811115612f6057600080fd5b612f6c87828601612911565b60208301525095945050505050565b600073ffffffffffffffffffffffffffffffffffffffff808916835260c06020840152612fab60c08401896121d6565b67ffffffffffffffff97881660408501529590961660608301525091909316608082015260a0019190915292915050565b6020815260006106106020830184612ad0565b600082516130018184602087016121b2565b919091019291505056fea164736f6c6343000818000a", } var OnRampABI = OnRampMetaData.ABI @@ -1437,7 +1438,7 @@ func (_OnRamp *OnRamp) ParseLog(log types.Log) (generated.AbigenLog, error) { } func (OnRampCCIPSendRequested) Topic() common.Hash { - return common.HexToHash("0x0f07cd31e53232da9125e517f09550fdde74bf43d6a0a76ebd41674dafe2ab29") + return common.HexToHash("0xcae3d9f68a9ed33d0a770e9bcc6fc25d4041dd6391e6cd8015546547a3c93140") } func (OnRampConfigSet) Topic() common.Hash { diff --git a/core/gethwrappers/ccip/generated/price_registry/price_registry.go b/core/gethwrappers/ccip/generated/price_registry/price_registry.go index fd50287f53..a4839d7ac3 100644 --- a/core/gethwrappers/ccip/generated/price_registry/price_registry.go +++ b/core/gethwrappers/ccip/generated/price_registry/price_registry.go @@ -68,6 +68,7 @@ type InternalRampTokenAmount struct { DestTokenAddress []byte ExtraData []byte Amount *big.Int + DestExecData []byte } type InternalTimestampedPackedUint224 struct { @@ -100,7 +101,6 @@ type PriceRegistryDestChainConfig struct { DestDataAvailabilityMultiplierBps uint16 DefaultTokenFeeUSDCents uint16 DefaultTokenDestGasOverhead uint32 - DefaultTokenDestBytesOverhead uint32 DefaultTxGasLimit uint32 GasMultiplierWeiPerEth uint64 NetworkFeeUSDCents uint32 @@ -154,8 +154,8 @@ type PriceRegistryTokenTransferFeeConfigSingleTokenArgs struct { } var PriceRegistryMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint96\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"linkToken\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"stalenessThreshold\",\"type\":\"uint32\"}],\"internalType\":\"structPriceRegistry.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"priceUpdaters\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"feeTokens\",\"type\":\"address[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"}],\"internalType\":\"structIPriceRegistry.TokenPriceFeedConfig\",\"name\":\"feedConfig\",\"type\":\"tuple\"}],\"internalType\":\"structPriceRegistry.TokenPriceFeedUpdate[]\",\"name\":\"tokenPriceFeeds\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structPriceRegistry.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"internalType\":\"structPriceRegistry.TokenTransferFeeConfigSingleTokenArgs[]\",\"name\":\"tokenTransferFeeConfigs\",\"type\":\"tuple[]\"}],\"internalType\":\"structPriceRegistry.TokenTransferFeeConfigArgs[]\",\"name\":\"tokenTransferFeeConfigArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"internalType\":\"structPriceRegistry.PremiumMultiplierWeiPerEthArgs[]\",\"name\":\"premiumMultiplierWeiPerEthArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"internalType\":\"structPriceRegistry.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structPriceRegistry.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chain\",\"type\":\"uint64\"}],\"name\":\"ChainNotSupported\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DataFeedValueOutOfUint224Range\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"DestinationChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ExtraArgOutOfOrderExecutionMustBeTrue\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"}],\"name\":\"InvalidDestBytesOverhead\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidDestChainConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidEVMAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidExtraArgsTag\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidStaticConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"msgFeeJuels\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint256\"}],\"name\":\"MessageFeeTooHigh\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MessageGasLimitTooHigh\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"maxSize\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualSize\",\"type\":\"uint256\"}],\"name\":\"MessageTooLarge\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"internalType\":\"bytes10\",\"name\":\"workflowName\",\"type\":\"bytes10\"},{\"internalType\":\"bytes2\",\"name\":\"reportName\",\"type\":\"bytes2\"}],\"name\":\"ReportForwarderUnauthorized\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"SourceTokenDataTooLarge\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"threshold\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timePassed\",\"type\":\"uint256\"}],\"name\":\"StaleGasPrice\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feedTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"storedTimeStamp\",\"type\":\"uint256\"}],\"name\":\"StaleKeystoneUpdate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"TokenNotSupported\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"UnauthorizedCaller\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnsupportedNumberOfTokens\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"AuthorizedCallerAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"AuthorizedCallerRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"indexed\":false,\"internalType\":\"structPriceRegistry.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"name\":\"DestChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"indexed\":false,\"internalType\":\"structPriceRegistry.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"name\":\"DestChainConfigUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"}],\"name\":\"FeeTokenAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"}],\"name\":\"FeeTokenRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"name\":\"PremiumMultiplierWeiPerEthUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"}],\"indexed\":false,\"internalType\":\"structIPriceRegistry.TokenPriceFeedConfig\",\"name\":\"priceFeedConfig\",\"type\":\"tuple\"}],\"name\":\"PriceFeedPerTokenUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"reportId\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"},{\"internalType\":\"bytes10\",\"name\":\"workflowName\",\"type\":\"bytes10\"},{\"internalType\":\"bytes2\",\"name\":\"reportName\",\"type\":\"bytes2\"},{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isAllowed\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"structKeystoneFeedsPermissionHandler.Permission\",\"name\":\"permission\",\"type\":\"tuple\"}],\"name\":\"ReportPermissionSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"TokenTransferFeeConfigDeleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"structPriceRegistry.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"name\":\"TokenTransferFeeConfigUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"UsdPerTokenUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChain\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"UsdPerUnitGasUpdated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address[]\",\"name\":\"addedCallers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"removedCallers\",\"type\":\"address[]\"}],\"internalType\":\"structAuthorizedCallers.AuthorizedCallerArgs\",\"name\":\"authorizedCallerArgs\",\"type\":\"tuple\"}],\"name\":\"applyAuthorizedCallerUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"internalType\":\"structPriceRegistry.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structPriceRegistry.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyDestChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"feeTokensToAdd\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"feeTokensToRemove\",\"type\":\"address[]\"}],\"name\":\"applyFeeTokensUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"internalType\":\"structPriceRegistry.PremiumMultiplierWeiPerEthArgs[]\",\"name\":\"premiumMultiplierWeiPerEthArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyPremiumMultiplierWeiPerEthUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structPriceRegistry.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"internalType\":\"structPriceRegistry.TokenTransferFeeConfigSingleTokenArgs[]\",\"name\":\"tokenTransferFeeConfigs\",\"type\":\"tuple[]\"}],\"internalType\":\"structPriceRegistry.TokenTransferFeeConfigArgs[]\",\"name\":\"tokenTransferFeeConfigArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"internalType\":\"structPriceRegistry.TokenTransferFeeConfigRemoveArgs[]\",\"name\":\"tokensToUseDefaultFeeConfigs\",\"type\":\"tuple[]\"}],\"name\":\"applyTokenTransferFeeConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"fromToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fromTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"toToken\",\"type\":\"address\"}],\"name\":\"convertTokenAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllAuthorizedCallers\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getDestChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"internalType\":\"structPriceRegistry.DestChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getDestinationChainGasPrice\",\"outputs\":[{\"components\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"internalType\":\"structInternal.TimestampedPackedUint224\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getFeeTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getPremiumMultiplierWeiPerEth\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint96\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"linkToken\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"stalenessThreshold\",\"type\":\"uint32\"}],\"internalType\":\"structPriceRegistry.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getTokenAndGasPrices\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"tokenPrice\",\"type\":\"uint224\"},{\"internalType\":\"uint224\",\"name\":\"gasPriceValue\",\"type\":\"uint224\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenPrice\",\"outputs\":[{\"components\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"internalType\":\"structInternal.TimestampedPackedUint224\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenPriceFeedConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"}],\"internalType\":\"structIPriceRegistry.TokenPriceFeedConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"tokens\",\"type\":\"address[]\"}],\"name\":\"getTokenPrices\",\"outputs\":[{\"components\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"internalType\":\"structInternal.TimestampedPackedUint224[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenTransferFeeConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structPriceRegistry.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"getValidatedFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getValidatedTokenPrice\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"\",\"type\":\"uint224\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"onReport\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"name\":\"processMessageArgs\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"msgFeeJuels\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isOutOfOrderExecution\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"convertedExtraArgs\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"},{\"internalType\":\"bytes10\",\"name\":\"workflowName\",\"type\":\"bytes10\"},{\"internalType\":\"bytes2\",\"name\":\"reportName\",\"type\":\"bytes2\"},{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isAllowed\",\"type\":\"bool\"}],\"internalType\":\"structKeystoneFeedsPermissionHandler.Permission[]\",\"name\":\"permissions\",\"type\":\"tuple[]\"}],\"name\":\"setReportPermissions\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"}],\"name\":\"updatePrices\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"}],\"internalType\":\"structIPriceRegistry.TokenPriceFeedConfig\",\"name\":\"feedConfig\",\"type\":\"tuple\"}],\"internalType\":\"structPriceRegistry.TokenPriceFeedUpdate[]\",\"name\":\"tokenPriceFeedUpdates\",\"type\":\"tuple[]\"}],\"name\":\"updateTokenPriceFeeds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"rampTokenAmounts\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"sourceTokenAmounts\",\"type\":\"tuple[]\"}],\"name\":\"validatePoolReturnData\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x60e06040523480156200001157600080fd5b50604051620075cf380380620075cf83398101604081905262000034916200188e565b8533806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf8162000207565b5050604080518082018252838152815160008152602080820190935291810191909152620000ee9150620002b2565b5060208701516001600160a01b0316158062000112575086516001600160601b0316155b80620001265750604087015163ffffffff16155b15620001455760405163d794ef9560e01b815260040160405180910390fd5b6020878101516001600160a01b031660a05287516001600160601b031660805260408089015163ffffffff1660c05280516000815291820190526200018c90869062000401565b620001978462000549565b620001a2816200061a565b620001ad8262000a9f565b60408051600080825260208201909252620001fa91859190620001f3565b6040805180820190915260008082526020820152815260200190600190039081620001cb5790505b5062000b6b565b5050505050505062001b4c565b336001600160a01b03821603620002615760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b602081015160005b815181101562000342576000828281518110620002db57620002db620019ad565b60209081029190910101519050620002f560028262000ea4565b1562000338576040516001600160a01b03821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b50600101620002ba565b50815160005b8151811015620003fb576000828281518110620003695762000369620019ad565b6020026020010151905060006001600160a01b0316816001600160a01b031603620003a7576040516342bcdf7f60e11b815260040160405180910390fd5b620003b460028262000ec4565b506040516001600160a01b03821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a15060010162000348565b50505050565b60005b8251811015620004a25762000440838281518110620004275762000427620019ad565b6020026020010151600b62000ec460201b90919060201c565b1562000499578281815181106200045b576200045b620019ad565b60200260200101516001600160a01b03167fdf1b1bd32a69711488d71554706bb130b1fc63a5fa1a2cd85e8440f84065ba2360405160405180910390a25b60010162000404565b5060005b81518110156200054457620004e2828281518110620004c957620004c9620019ad565b6020026020010151600b62000edb60201b90919060201c565b156200053b57818181518110620004fd57620004fd620019ad565b60200260200101516001600160a01b03167f1795838dc8ab2ffc5f431a1729a6afa0b587f982f7b2be0b9d7187a1ef547f9160405160405180910390a25b600101620004a6565b505050565b60005b8151811015620006165760008282815181106200056d576200056d620019ad565b6020908102919091018101518051818301516001600160a01b0380831660008181526007875260409081902084518154868a018051929096166001600160a81b03199091168117600160a01b60ff9384160217909255825191825293519093169683019690965293955091939092917f08a5f7f5bb38a81d8e43aca13ecd76431dbf8816ae4699affff7b00b2fc1c464910160405180910390a25050508060010190506200054c565b5050565b60005b8151811015620006165760008282815181106200063e576200063e620019ad565b6020026020010151905060008383815181106200065f576200065f620019ad565b6020026020010151600001519050600082602001519050816001600160401b03166000148062000698575061018081015163ffffffff16155b80620006ba57506102008101516001600160e01b031916630a04b54b60e21b14155b80620006d75750602063ffffffff1681610160015163ffffffff16105b80620006f75750806060015163ffffffff1681610180015163ffffffff16115b15620007225760405163c35aa79d60e01b81526001600160401b038316600482015260240162000083565b6001600160401b038216600090815260096020526040812060010154600160a81b900460e01b6001600160e01b0319169003620007a257816001600160401b03167fa937382a486d993de71c220bc8b559242deb4e286a353fa732330b4aa7d1357782604051620007949190620019c3565b60405180910390a2620007e6565b816001600160401b03167fa7b607fc10d28a1caf39ab7d27f4c94945db708a576d572781a455c5894fad9382604051620007dd9190620019c3565b60405180910390a25b8060096000846001600160401b03166001600160401b0316815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548161ffff021916908361ffff16021790555060408201518160000160036101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160076101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600b6101000a81548163ffffffff021916908363ffffffff16021790555060a082015181600001600f6101000a81548161ffff021916908361ffff16021790555060c08201518160000160116101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160000160156101000a81548161ffff021916908361ffff1602179055506101008201518160000160176101000a81548161ffff021916908361ffff1602179055506101208201518160000160196101000a81548161ffff021916908361ffff16021790555061014082015181600001601b6101000a81548163ffffffff021916908363ffffffff1602179055506101608201518160010160006101000a81548163ffffffff021916908363ffffffff1602179055506101808201518160010160046101000a81548163ffffffff021916908363ffffffff1602179055506101a08201518160010160086101000a8154816001600160401b0302191690836001600160401b031602179055506101c08201518160010160106101000a81548163ffffffff021916908363ffffffff1602179055506101e08201518160010160146101000a81548160ff0219169083151502179055506102008201518160010160156101000a81548163ffffffff021916908360e01c02179055509050505050508060010190506200061d565b60005b81518110156200061657600082828151811062000ac35762000ac3620019ad565b6020026020010151600001519050600083838151811062000ae85762000ae8620019ad565b6020908102919091018101518101516001600160a01b03841660008181526008845260409081902080546001600160401b0319166001600160401b0385169081179091559051908152919350917fbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d910160405180910390a2505060010162000aa2565b60005b825181101562000dde57600083828151811062000b8f5762000b8f620019ad565b6020026020010151905060008160000151905060005b82602001515181101562000dcf5760008360200151828151811062000bce5762000bce620019ad565b602002602001015160200151905060008460200151838151811062000bf75762000bf7620019ad565b6020026020010151600001519050602063ffffffff16826080015163ffffffff16101562000c565760808201516040516312766e0160e11b81526001600160a01b038316600482015263ffffffff909116602482015260440162000083565b6001600160401b0384166000818152600a602090815260408083206001600160a01b0386168085529083529281902086518154938801518389015160608a015160808b015160a08c01511515600160901b0260ff60901b1963ffffffff928316600160701b021664ffffffffff60701b199383166a01000000000000000000000263ffffffff60501b1961ffff90961668010000000000000000029590951665ffffffffffff60401b19968416640100000000026001600160401b0319909b16939097169290921798909817939093169390931717919091161792909217909155519091907f94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b59062000dbc908690600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60405180910390a3505060010162000ba5565b50505080600101905062000b6e565b5060005b81518110156200054457600082828151811062000e035762000e03620019ad565b6020026020010151600001519050600083838151811062000e285762000e28620019ad565b6020908102919091018101518101516001600160401b0384166000818152600a845260408082206001600160a01b038516808452955280822080546001600160981b03191690555192945090917f4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b9190a3505060010162000de2565b600062000ebb836001600160a01b03841662000ef2565b90505b92915050565b600062000ebb836001600160a01b03841662000ff6565b600062000ebb836001600160a01b03841662001048565b6000818152600183016020526040812054801562000feb57600062000f1960018362001b14565b855490915060009062000f2f9060019062001b14565b905081811462000f9b57600086600001828154811062000f535762000f53620019ad565b906000526020600020015490508087600001848154811062000f795762000f79620019ad565b6000918252602080832090910192909255918252600188019052604090208390555b855486908062000faf5762000faf62001b36565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505062000ebe565b600091505062000ebe565b60008181526001830160205260408120546200103f5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000ebe565b50600062000ebe565b6000818152600183016020526040812054801562000feb5760006200106f60018362001b14565b8554909150600090620010859060019062001b14565b905080821462000f9b57600086600001828154811062000f535762000f53620019ad565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b0381118282101715620010e457620010e4620010a9565b60405290565b60405160c081016001600160401b0381118282101715620010e457620010e4620010a9565b60405161022081016001600160401b0381118282101715620010e457620010e4620010a9565b604051601f8201601f191681016001600160401b0381118282101715620011605762001160620010a9565b604052919050565b80516001600160a01b03811681146200118057600080fd5b919050565b805163ffffffff811681146200118057600080fd5b600060608284031215620011ad57600080fd5b604051606081016001600160401b0381118282101715620011d257620011d2620010a9565b604052825190915081906001600160601b0381168114620011f257600080fd5b8152620012026020840162001168565b6020820152620012156040840162001185565b60408201525092915050565b60006001600160401b038211156200123d576200123d620010a9565b5060051b60200190565b600082601f8301126200125957600080fd5b81516020620012726200126c8362001221565b62001135565b8083825260208201915060208460051b8701019350868411156200129557600080fd5b602086015b84811015620012bc57620012ae8162001168565b83529183019183016200129a565b509695505050505050565b600082601f830112620012d957600080fd5b81516020620012ec6200126c8362001221565b828152606092830285018201928282019190878511156200130c57600080fd5b8387015b858110156200139f57808903828112156200132b5760008081fd5b62001335620010bf565b620013408362001168565b8152604080601f1984011215620013575760008081fd5b62001361620010bf565b92506200137088850162001168565b835283015160ff81168114620013865760008081fd5b8288015280870191909152845292840192810162001310565b5090979650505050505050565b80516001600160401b03811681146200118057600080fd5b805161ffff811681146200118057600080fd5b805180151581146200118057600080fd5b600082601f830112620013fa57600080fd5b815160206200140d6200126c8362001221565b82815260059290921b840181019181810190868411156200142d57600080fd5b8286015b84811015620012bc5780516001600160401b03808211156200145257600080fd5b908801906040601f19838c0381018213156200146d57600080fd5b62001477620010bf565b62001484898601620013ac565b815282850151848111156200149857600080fd5b8086019550508c603f860112620014ae57600080fd5b888501519350620014c36200126c8562001221565b84815260e09094028501830193898101908e861115620014e257600080fd5b958401955b85871015620015bb57868f0360e08112156200150257600080fd5b6200150c620010bf565b620015178962001168565b815260c086830112156200152a57600080fd5b62001534620010ea565b9150620015438d8a0162001185565b825262001552878a0162001185565b8d8301526200156460608a01620013c4565b878301526200157660808a0162001185565b60608301526200158960a08a0162001185565b60808301526200159c60c08a01620013d7565b60a0830152808d0191909152825260e09690960195908a0190620014e7565b828b01525087525050509284019250830162001431565b600082601f830112620015e457600080fd5b81516020620015f76200126c8362001221565b82815260069290921b840181019181810190868411156200161757600080fd5b8286015b84811015620012bc5760408189031215620016365760008081fd5b62001640620010bf565b6200164b8262001168565b81526200165a858301620013ac565b818601528352918301916040016200161b565b80516001600160e01b0319811681146200118057600080fd5b600082601f8301126200169857600080fd5b81516020620016ab6200126c8362001221565b8281526102409283028501820192828201919087851115620016cc57600080fd5b8387015b858110156200139f5780890382811215620016eb5760008081fd5b620016f5620010bf565b6200170083620013ac565b815261022080601f1984011215620017185760008081fd5b620017226200110f565b925062001731888501620013d7565b8352604062001742818601620013c4565b8985015260606200175581870162001185565b82860152608091506200176a82870162001185565b9085015260a06200177d86820162001185565b8286015260c0915062001792828701620013c4565b9085015260e0620017a586820162001185565b828601526101009150620017bb828701620013c4565b90850152610120620017cf868201620013c4565b828601526101409150620017e5828701620013c4565b90850152610160620017f986820162001185565b8286015261018091506200180f82870162001185565b908501526101a06200182386820162001185565b828601526101c0915062001839828701620013ac565b908501526101e06200184d86820162001185565b82860152610200915062001863828701620013d7565b90850152620018748583016200166d565b9084015250808701919091528452928401928101620016d0565b6000806000806000806000610120888a031215620018ab57600080fd5b620018b789896200119a565b60608901519097506001600160401b0380821115620018d557600080fd5b620018e38b838c0162001247565b975060808a0151915080821115620018fa57600080fd5b620019088b838c0162001247565b965060a08a01519150808211156200191f57600080fd5b6200192d8b838c01620012c7565b955060c08a01519150808211156200194457600080fd5b620019528b838c01620013e8565b945060e08a01519150808211156200196957600080fd5b620019778b838c01620015d2565b93506101008a01519150808211156200198f57600080fd5b506200199e8a828b0162001686565b91505092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b81511515815261022081016020830151620019e4602084018261ffff169052565b506040830151620019fd604084018263ffffffff169052565b50606083015162001a16606084018263ffffffff169052565b50608083015162001a2f608084018263ffffffff169052565b5060a083015162001a4660a084018261ffff169052565b5060c083015162001a5f60c084018263ffffffff169052565b5060e083015162001a7660e084018261ffff169052565b506101008381015161ffff9081169184019190915261012080850151909116908301526101408084015163ffffffff9081169184019190915261016080850151821690840152610180808501518216908401526101a0808501516001600160401b0316908401526101c080850151909116908301526101e080840151151590830152610200928301516001600160e01b031916929091019190915290565b8181038181111562000ebe57634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b60805160a05160c051615a2962001ba6600039600081816102ef01528181612035015261209e0152600081816102b3015281816115b0015261161001526000818161027f0152818161163901526116a90152615a296000f3fe608060405234801561001057600080fd5b50600436106101ce5760003560e01c80637afac32211610104578063c4276bfc116100a2578063d8694ccd11610071578063d8694ccd14610a98578063f2fde38b14610aab578063f700042a14610abe578063ffdb4b3714610ad157600080fd5b8063c4276bfc14610a48578063cc88924c14610a6a578063cdc73d5114610a7d578063d02641a014610a8557600080fd5b80638da5cb5b116100de5780638da5cb5b1461094d57806391a2749a14610975578063a69c64c014610988578063bf78e03f1461099b57600080fd5b80637afac322146107b7578063805f2132146107ca57806382b49eb0146107dd57600080fd5b806341ed29e711610171578063514e8cff1161014b578063514e8cff146104615780636def4ce714610504578063770e2dc41461079c57806379ba5097146107af57600080fd5b806341ed29e7146103ee57806345ac924d146104015780634ab35b0b1461042157600080fd5b8063181f5a77116101ad578063181f5a77146103685780632451a627146103b15780633937306f146103c6578063407e1086146103db57600080fd5b806241e5be146101d3578063061877e3146101f957806306285c6914610252575b600080fd5b6101e66101e1366004614142565b610b19565b6040519081526020015b60405180910390f35b61023961020736600461417e565b73ffffffffffffffffffffffffffffffffffffffff1660009081526008602052604090205467ffffffffffffffff1690565b60405167ffffffffffffffff90911681526020016101f0565b61031c604080516060810182526000808252602082018190529181019190915260405180606001604052807f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000063ffffffff16815250905090565b6040805182516bffffffffffffffffffffffff16815260208084015173ffffffffffffffffffffffffffffffffffffffff16908201529181015163ffffffff16908201526060016101f0565b6103a46040518060400160405280601781526020017f5072696365526567697374727920312e362e302d64657600000000000000000081525081565b6040516101f091906141fd565b6103b9610b87565b6040516101f09190614210565b6103d96103d436600461426a565b610b98565b005b6103d96103e936600461440c565b610e4d565b6103d96103fc36600461453e565b610e61565b61041461040f3660046146be565b610ea3565b6040516101f09190614700565b61043461042f36600461417e565b610f6e565b6040517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff90911681526020016101f0565b6104f761046f366004614793565b60408051808201909152600080825260208201525067ffffffffffffffff166000908152600560209081526040918290208251808401909352547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811683527c0100000000000000000000000000000000000000000000000000000000900463ffffffff169082015290565b6040516101f091906147ae565b61078f610512366004614793565b6040805161022081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a081018290526101c081018290526101e081018290526102008101919091525067ffffffffffffffff908116600090815260096020908152604091829020825161022081018452815460ff8082161515835261ffff61010080840482169685019690965263ffffffff630100000084048116978501979097526701000000000000008304871660608501526b0100000000000000000000008304871660808501526f010000000000000000000000000000008304811660a0850152710100000000000000000000000000000000008304871660c08501527501000000000000000000000000000000000000000000808404821660e08087019190915277010000000000000000000000000000000000000000000000850483169786019790975279010000000000000000000000000000000000000000000000000084049091166101208501527b010000000000000000000000000000000000000000000000000000009092048616610140840152600190930154808616610160840152640100000000810486166101808401526801000000000000000081049096166101a083015270010000000000000000000000000000000086049094166101c082015274010000000000000000000000000000000000000000850490911615156101e08201527fffffffff0000000000000000000000000000000000000000000000000000000092909304901b1661020082015290565b6040516101f091906147e9565b6103d96107aa366004614a0d565b610f79565b6103d9610f8b565b6103d96107c5366004614d27565b61108d565b6103d96107d8366004614dcd565b61109f565b6108ed6107eb366004614e39565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101919091525067ffffffffffffffff919091166000908152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff94909416835292815290829020825160c081018452905463ffffffff8082168352640100000000820481169383019390935268010000000000000000810461ffff16938201939093526a01000000000000000000008304821660608201526e01000000000000000000000000000083049091166080820152720100000000000000000000000000000000000090910460ff16151560a082015290565b6040516101f09190600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101f0565b6103d9610983366004614e63565b611587565b6103d9610996366004614ef4565b611598565b610a146109a936600461417e565b6040805180820182526000808252602091820181905273ffffffffffffffffffffffffffffffffffffffff93841681526007825282902082518084019093525492831682527401000000000000000000000000000000000000000090920460ff169181019190915290565b60408051825173ffffffffffffffffffffffffffffffffffffffff16815260209283015160ff1692810192909252016101f0565b610a5b610a56366004614fb9565b6115a9565b6040516101f093929190615028565b6103d9610a78366004615049565b6117a7565b6103b961197d565b6104f7610a9336600461417e565b611989565b6101e6610aa63660046150f7565b611a85565b6103d9610ab936600461417e565b611f3f565b6103d9610acc36600461517c565b611f50565b610ae4610adf36600461539c565b611f61565b604080517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff9384168152929091166020830152016101f0565b6000610b24826120ec565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16610b4b856120ec565b610b73907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16856153f5565b610b7d919061540c565b90505b9392505050565b6060610b936002612186565b905090565b610ba0612193565b6000610bac8280615447565b9050905060005b81811015610cf6576000610bc78480615447565b83818110610bd757610bd76154af565b905060400201803603810190610bed919061550a565b604080518082018252602080840180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff908116845263ffffffff42818116858701908152885173ffffffffffffffffffffffffffffffffffffffff9081166000908152600690975295889020965190519092167c010000000000000000000000000000000000000000000000000000000002919092161790935584519051935194955016927f52f50aa6d1a95a4595361ecf953d095f125d442e4673716dede699e049de148a92610ce59290917bffffffffffffffffffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b60405180910390a250600101610bb3565b506000610d066020840184615447565b9050905060005b81811015610e47576000610d246020860186615447565b83818110610d3457610d346154af565b905060400201803603810190610d4a9190615547565b604080518082018252602080840180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff908116845263ffffffff42818116858701908152885167ffffffffffffffff9081166000908152600590975295889020965190519092167c010000000000000000000000000000000000000000000000000000000002919092161790935584519051935194955016927fdd84a3fa9ef9409f550d54d6affec7e9c480c878c6ab27b78912a03e1b371c6e92610e369290917bffffffffffffffffffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b60405180910390a250600101610d0d565b50505050565b610e556121d8565b610e5e81612259565b50565b610e696121d8565b60005b8151811015610e9f57610e97828281518110610e8a57610e8a6154af565b6020026020010151612357565b600101610e6c565b5050565b60608160008167ffffffffffffffff811115610ec157610ec16142a5565b604051908082528060200260200182016040528015610f0657816020015b6040805180820190915260008082526020820152815260200190600190039081610edf5790505b50905060005b82811015610f6357610f3e868683818110610f2957610f296154af565b9050602002016020810190610a93919061417e565b828281518110610f5057610f506154af565b6020908102919091010152600101610f0c565b509150505b92915050565b6000610f68826120ec565b610f816121d8565b610e9f8282612529565b60015473ffffffffffffffffffffffffffffffffffffffff163314611011576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6110956121d8565b610e9f828261293b565b60008060006110e387878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612a8292505050565b9250925092506110f533838584612a9d565b60006111038587018761556a565b905060005b815181101561157c57600060076000848481518110611129576111296154af565b6020908102919091018101515173ffffffffffffffffffffffffffffffffffffffff16825281019190915260400160009081205474010000000000000000000000000000000000000000900460ff1691508190036111ea57828281518110611193576111936154af565b6020908102919091010151516040517f06439c6b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401611008565b6000611233601283868681518110611204576112046154af565b6020026020010151602001517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16612bf5565b90506006600085858151811061124b5761124b6154af565b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001601c9054906101000a900463ffffffff1663ffffffff168484815181106112bd576112bd6154af565b60200260200101516040015163ffffffff1610156113c7578383815181106112e7576112e76154af565b602002602001015160000151848481518110611305576113056154af565b60200260200101516040015160066000878781518110611327576113276154af565b6020908102919091018101515173ffffffffffffffffffffffffffffffffffffffff90811683529082019290925260409081016000205490517f191ec70600000000000000000000000000000000000000000000000000000000815293909116600484015263ffffffff91821660248401527c01000000000000000000000000000000000000000000000000000000009004166044820152606401611008565b6040518060400160405280827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168152602001858581518110611408576114086154af565b60200260200101516040015163ffffffff1681525060066000868681518110611433576114336154af565b6020908102919091018101515173ffffffffffffffffffffffffffffffffffffffff168252818101929092526040016000208251929091015163ffffffff167c0100000000000000000000000000000000000000000000000000000000027bffffffffffffffffffffffffffffffffffffffffffffffffffffffff90921691909117905583518490849081106114cb576114cb6154af565b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff167f52f50aa6d1a95a4595361ecf953d095f125d442e4673716dede699e049de148a82868681518110611521576115216154af565b60200260200101516040015160405161156a9291907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff92909216825263ffffffff16602082015260400190565b60405180910390a25050600101611108565b505050505050505050565b61158f6121d8565b610e5e81612cbb565b6115a06121d8565b610e5e81612e47565b60008060607f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff160361160957859250611637565b61163487877f0000000000000000000000000000000000000000000000000000000000000000610b19565b92505b7f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff168311156116d6576040517f6a92a483000000000000000000000000000000000000000000000000000000008152600481018490526bffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166024820152604401611008565b67ffffffffffffffff8816600090815260096020526040812060010154640100000000900463ffffffff169061170d878784612f31565b9050806020015193508484611794836040805182516024820152602092830151151560448083019190915282518083039091018152606490910190915290810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f181dcf100000000000000000000000000000000000000000000000000000000017905290565b9450945094505050955095509592505050565b67ffffffffffffffff85166000908152600960205260408120600101547501000000000000000000000000000000000000000000900460e01b905b848110156119745760008484838181106117fe576117fe6154af565b611814926020604090920201908101915061417e565b9050600087878481811061182a5761182a6154af565b905060200281019061183c9190615631565b61184a90604081019061566f565b91505060208111156118fa5767ffffffffffffffff89166000908152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff861684529091529020546e010000000000000000000000000000900463ffffffff168111156118fa576040517f36f536ca00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83166004820152602401611008565b61196a84898986818110611910576119106154af565b90506020028101906119229190615631565b61193090602081019061566f565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506130da92505050565b50506001016117e2565b50505050505050565b6060610b93600b612186565b604080518082019091526000808252602082015273ffffffffffffffffffffffffffffffffffffffff8281166000908152600760209081526040918290208251808401909352549283168083527401000000000000000000000000000000000000000090930460ff169082015290611a7c57505073ffffffffffffffffffffffffffffffffffffffff166000908152600660209081526040918290208251808401909352547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811683527c0100000000000000000000000000000000000000000000000000000000900463ffffffff169082015290565b610b808161312c565b67ffffffffffffffff8083166000908152600960209081526040808320815161022081018352815460ff808216151580845261ffff61010080850482169886019890985263ffffffff630100000085048116978601979097526701000000000000008404871660608601526b0100000000000000000000008404871660808601526f010000000000000000000000000000008404811660a0860152710100000000000000000000000000000000008404871660c08601527501000000000000000000000000000000000000000000808504821660e08088019190915277010000000000000000000000000000000000000000000000860483169987019990995279010000000000000000000000000000000000000000000000000085049091166101208601527b010000000000000000000000000000000000000000000000000000009093048616610140850152600190940154808616610160850152640100000000810486166101808501526801000000000000000081049098166101a084015270010000000000000000000000000000000088049094166101c083015274010000000000000000000000000000000000000000870490931615156101e08201527fffffffff000000000000000000000000000000000000000000000000000000009290950490921b16610200840152909190611cbb576040517f99ac52f200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff85166004820152602401611008565b6000611cca6040850185615447565b9150611d26905082611cdf602087018761566f565b905083611cec888061566f565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506132bb92505050565b6000600881611d3b608088016060890161417e565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160009081205467ffffffffffffffff16915080611d8a611d846080890160608a0161417e565b89611f61565b9092509050600080808615611dd057611dc4888c611dae60808e0160608f0161417e565b888e8060400190611dbf9190615447565b613365565b91945092509050611df0565b6101c0880151611ded9063ffffffff16662386f26fc100006153f5565b92505b61010088015160009061ffff1615611e3457611e31896dffffffffffffffffffffffffffff607088901c16611e2860208f018f61566f565b90508b86613643565b90505b6101a089015160009067ffffffffffffffff16611e5d611e5760808f018f61566f565b8d6136f3565b600001518563ffffffff168c60a0015161ffff168f8060200190611e81919061566f565b611e8c9291506153f5565b8d6080015163ffffffff16611ea191906156d4565b611eab91906156d4565b611eb591906156d4565b611ecf906dffffffffffffffffffffffffffff89166153f5565b611ed991906153f5565b90507bffffffffffffffffffffffffffffffffffffffffffffffffffffffff87168282611f1067ffffffffffffffff8c16896153f5565b611f1a91906156d4565b611f2491906156d4565b611f2e919061540c565b9d9c50505050505050505050505050565b611f476121d8565b610e5e816137b4565b611f586121d8565b610e5e816138a9565b67ffffffffffffffff811660009081526005602090815260408083208151808301909252547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811682527c0100000000000000000000000000000000000000000000000000000000900463ffffffff1691810182905282918203612019576040517f2e59db3a00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff85166004820152602401611008565b6000816020015163ffffffff164261203191906156e7565b90507f000000000000000000000000000000000000000000000000000000000000000063ffffffff168111156120d2576040517ff08bcb3e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8616600482015263ffffffff7f000000000000000000000000000000000000000000000000000000000000000016602482015260448101829052606401611008565b6120db866120ec565b9151919350909150505b9250929050565b6000806120f883611989565b9050806020015163ffffffff1660001480612130575080517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16155b1561217f576040517f06439c6b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152602401611008565b5192915050565b60606000610b8083613d97565b61219e600233613df3565b6121d6576040517fd86ad9cf000000000000000000000000000000000000000000000000000000008152336004820152602401611008565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633146121d6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401611008565b60005b8151811015610e9f576000828281518110612279576122796154af565b60209081029190910181015180518183015173ffffffffffffffffffffffffffffffffffffffff80831660008181526007875260409081902084518154868a018051929096167fffffffffffffffffffffff00000000000000000000000000000000000000000090911681177401000000000000000000000000000000000000000060ff9384160217909255825191825293519093169683019690965293955091939092917f08a5f7f5bb38a81d8e43aca13ecd76431dbf8816ae4699affff7b00b2fc1c464910160405180910390a250505080600101905061225c565b600061241082600001518360600151846020015185604001516040805173ffffffffffffffffffffffffffffffffffffffff80871660208301528516918101919091527fffffffffffffffffffff00000000000000000000000000000000000000000000831660608201527fffff0000000000000000000000000000000000000000000000000000000000008216608082015260009060a001604051602081830303815290604052805190602001209050949350505050565b60808301516000828152600460205260409081902080549215157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00909316929092179091555190915081907f32a4ba3fa3351b11ad555d4c8ec70a744e8705607077a946807030d64b6ab1a39061251d908590600060a08201905073ffffffffffffffffffffffffffffffffffffffff8084511683527fffffffffffffffffffff0000000000000000000000000000000000000000000060208501511660208401527fffff00000000000000000000000000000000000000000000000000000000000060408501511660408401528060608501511660608401525060808301511515608083015292915050565b60405180910390a25050565b60005b8251811015612852576000838281518110612549576125496154af565b6020026020010151905060008160000151905060005b82602001515181101561284457600083602001518281518110612584576125846154af565b60200260200101516020015190506000846020015183815181106125aa576125aa6154af565b6020026020010151600001519050602063ffffffff16826080015163ffffffff16101561262d5760808201516040517f24ecdc0200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8316600482015263ffffffff9091166024820152604401611008565b67ffffffffffffffff84166000818152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff86168085529083529281902086518154938801518389015160608a015160808b015160a08c015115157201000000000000000000000000000000000000027fffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffff63ffffffff9283166e01000000000000000000000000000002167fffffffffffffffffffffffffff0000000000ffffffffffffffffffffffffffff9383166a0100000000000000000000027fffffffffffffffffffffffffffffffffffff00000000ffffffffffffffffffff61ffff9096166801000000000000000002959095167fffffffffffffffffffffffffffffffffffff000000000000ffffffffffffffff968416640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000909b16939097169290921798909817939093169390931717919091161792909217909155519091907f94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b590612832908690600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60405180910390a3505060010161255f565b50505080600101905061252c565b5060005b8151811015612936576000828281518110612873576128736154af565b60200260200101516000015190506000838381518110612895576128956154af565b60209081029190910181015181015167ffffffffffffffff84166000818152600a8452604080822073ffffffffffffffffffffffffffffffffffffffff8516808452955280822080547fffffffffffffffffffffffffff000000000000000000000000000000000000001690555192945090917f4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b9190a35050600101612856565b505050565b60005b82518110156129de5761297483828151811061295c5761295c6154af565b6020026020010151600b613e2290919063ffffffff16565b156129d65782818151811061298b5761298b6154af565b602002602001015173ffffffffffffffffffffffffffffffffffffffff167fdf1b1bd32a69711488d71554706bb130b1fc63a5fa1a2cd85e8440f84065ba2360405160405180910390a25b60010161293e565b5060005b815181101561293657612a18828281518110612a0057612a006154af565b6020026020010151600b613e4490919063ffffffff16565b15612a7a57818181518110612a2f57612a2f6154af565b602002602001015173ffffffffffffffffffffffffffffffffffffffff167f1795838dc8ab2ffc5f431a1729a6afa0b587f982f7b2be0b9d7187a1ef547f9160405160405180910390a25b6001016129e2565b6040810151604a820151605e90920151909260609290921c91565b6040805173ffffffffffffffffffffffffffffffffffffffff868116602080840191909152908616828401527fffffffffffffffffffff00000000000000000000000000000000000000000000851660608301527fffff00000000000000000000000000000000000000000000000000000000000084166080808401919091528351808403909101815260a09092018352815191810191909120600081815260049092529190205460ff16612bee576040517f097e17ff00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8087166004830152851660248201527fffffffffffffffffffff00000000000000000000000000000000000000000000841660448201527fffff00000000000000000000000000000000000000000000000000000000000083166064820152608401611008565b5050505050565b600080612c0284866156fa565b9050600060248260ff161115612c3957612c1d602483615713565b612c2890600a61584c565b612c32908561540c565b9050612c5c565b612c44826024615713565b612c4f90600a61584c565b612c5990856153f5565b90505b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811115612cb2576040517f10cb51d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b95945050505050565b602081015160005b8151811015612d56576000828281518110612ce057612ce06154af565b60200260200101519050612cfe816002613e6690919063ffffffff16565b15612d4d5760405173ffffffffffffffffffffffffffffffffffffffff821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b50600101612cc3565b50815160005b8151811015610e47576000828281518110612d7957612d796154af565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603612de9576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612df4600282613e22565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a150600101612d5c565b60005b8151811015610e9f576000828281518110612e6757612e676154af565b60200260200101516000015190506000838381518110612e8957612e896154af565b60209081029190910181015181015173ffffffffffffffffffffffffffffffffffffffff841660008181526008845260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff85169081179091559051908152919350917fbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d910160405180910390a25050600101612e4a565b60408051808201909152600080825260208201526000839003612f7257506040805180820190915267ffffffffffffffff8216815260006020820152610b80565b6000612f7e848661585b565b90506000612f8f85600481896158a1565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505050507fffffffff0000000000000000000000000000000000000000000000000000000082167fe7e230f0000000000000000000000000000000000000000000000000000000000161302c578080602001905181019061302391906158cb565b92505050610b80565b7f6859a837000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316016130a85760405180604001604052808280602001905181019061309491906158f7565b815260006020909101529250610b80915050565b6040517f5247fdce00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7fd7ed2ad4000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831601610e9f5761293681613e88565b604080518082019091526000808252602082015260008260000151905060008173ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015613196573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131ba919061592a565b50505091505060008112156131fb576040517f10cb51d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061327a8373ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561324b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061326f919061597a565b866020015184612bf5565b604080518082019091527bffffffffffffffffffffffffffffffffffffffffffffffffffffffff909116815263ffffffff4216602082015295945050505050565b836040015163ffffffff168311156133145760408085015190517f8693378900000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015260248101849052604401611008565b836020015161ffff16821115613356576040517f4c056b6a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610e47846102000151826130da565b6000808083815b81811015613635576000878783818110613388576133886154af565b90506040020180360381019061339e9190615997565b67ffffffffffffffff8c166000908152600a60209081526040808320845173ffffffffffffffffffffffffffffffffffffffff168452825291829020825160c081018452905463ffffffff8082168352640100000000820481169383019390935268010000000000000000810461ffff16938201939093526a01000000000000000000008304821660608201526e01000000000000000000000000000083049091166080820152720100000000000000000000000000000000000090910460ff16151560a08201819052919250906134c4576101208d015161348b9061ffff16662386f26fc100006153f5565b61349590886156d4565b96508c6101400151866134a891906159d0565b95508c6101600151856134bb91906159d0565b9450505061362d565b604081015160009061ffff161561357d5760008c73ffffffffffffffffffffffffffffffffffffffff16846000015173ffffffffffffffffffffffffffffffffffffffff1614613520578351613519906120ec565b9050613523565b508a5b620186a0836040015161ffff166135658660200151847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16613f3b90919063ffffffff16565b61356f91906153f5565b613579919061540c565b9150505b606082015161358c90886159d0565b965081608001518661359e91906159d0565b82519096506000906135bd9063ffffffff16662386f26fc100006153f5565b9050808210156135dc576135d1818a6156d4565b98505050505061362d565b6000836020015163ffffffff16662386f26fc100006135fb91906153f5565b90508083111561361b5761360f818b6156d4565b9950505050505061362d565b613625838b6156d4565b995050505050505b60010161336c565b505096509650969350505050565b60008063ffffffff8316613659610140866153f5565b613665876101c06156d4565b61366f91906156d4565b61367991906156d4565b905060008760c0015163ffffffff168860e0015161ffff168361369c91906153f5565b6136a691906156d4565b61010089015190915061ffff166136cd6dffffffffffffffffffffffffffff8916836153f5565b6136d791906153f5565b6136e790655af3107a40006153f5565b98975050505050505050565b6040805180820190915260008082526020820152600061371f858585610180015163ffffffff16612f31565b9050826060015163ffffffff1681600001511115613769576040517f4c4fc93a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b826101e00151801561377d57508060200151155b15610b7d576040517fee433e9900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff821603613833576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401611008565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60005b8151811015610e9f5760008282815181106138c9576138c96154af565b6020026020010151905060008383815181106138e7576138e76154af565b60200260200101516000015190506000826020015190508167ffffffffffffffff1660001480613920575061018081015163ffffffff16155b8061397257506102008101517fffffffff00000000000000000000000000000000000000000000000000000000167f2812d52c0000000000000000000000000000000000000000000000000000000014155b8061398e5750602063ffffffff1681610160015163ffffffff16105b806139ad5750806060015163ffffffff1681610180015163ffffffff16115b156139f0576040517fc35aa79d00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff83166004820152602401611008565b67ffffffffffffffff82166000908152600960205260408120600101547501000000000000000000000000000000000000000000900460e01b7fffffffff00000000000000000000000000000000000000000000000000000000169003613a98578167ffffffffffffffff167fa937382a486d993de71c220bc8b559242deb4e286a353fa732330b4aa7d1357782604051613a8b91906147e9565b60405180910390a2613adb565b8167ffffffffffffffff167fa7b607fc10d28a1caf39ab7d27f4c94945db708a576d572781a455c5894fad9382604051613ad291906147e9565b60405180910390a25b80600960008467ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548161ffff021916908361ffff16021790555060408201518160000160036101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160076101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600b6101000a81548163ffffffff021916908363ffffffff16021790555060a082015181600001600f6101000a81548161ffff021916908361ffff16021790555060c08201518160000160116101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160000160156101000a81548161ffff021916908361ffff1602179055506101008201518160000160176101000a81548161ffff021916908361ffff1602179055506101208201518160000160196101000a81548161ffff021916908361ffff16021790555061014082015181600001601b6101000a81548163ffffffff021916908363ffffffff1602179055506101608201518160010160006101000a81548163ffffffff021916908363ffffffff1602179055506101808201518160010160046101000a81548163ffffffff021916908363ffffffff1602179055506101a08201518160010160086101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506101c08201518160010160106101000a81548163ffffffff021916908363ffffffff1602179055506101e08201518160010160146101000a81548160ff0219169083151502179055506102008201518160010160156101000a81548163ffffffff021916908360e01c02179055509050505050508060010190506138ac565b606081600001805480602002602001604051908101604052809291908181526020018280548015613de757602002820191906000526020600020905b815481526020019060010190808311613dd3575b50505050509050919050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515610b80565b6000610b808373ffffffffffffffffffffffffffffffffffffffff8416613f78565b6000610b808373ffffffffffffffffffffffffffffffffffffffff8416613fc7565b6000610b808373ffffffffffffffffffffffffffffffffffffffff84166140c1565b60008151602014613ec757816040517f8d666f6000000000000000000000000000000000000000000000000000000000815260040161100891906141fd565b600082806020019051810190613edd91906158f7565b905073ffffffffffffffffffffffffffffffffffffffff811180613f02575061040081105b15610f6857826040517f8d666f6000000000000000000000000000000000000000000000000000000000815260040161100891906141fd565b6000670de0b6b3a7640000613f6e837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff86166153f5565b610b80919061540c565b6000818152600183016020526040812054613fbf57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610f68565b506000610f68565b600081815260018301602052604081205480156140b0576000613feb6001836156e7565b8554909150600090613fff906001906156e7565b905080821461406457600086600001828154811061401f5761401f6154af565b9060005260206000200154905080876000018481548110614042576140426154af565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080614075576140756159ed565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610f68565b6000915050610f68565b5092915050565b600081815260018301602052604081205480156140b05760006140e56001836156e7565b85549091506000906140f9906001906156e7565b905081811461406457600086600001828154811061401f5761401f6154af565b803573ffffffffffffffffffffffffffffffffffffffff8116811461413d57600080fd5b919050565b60008060006060848603121561415757600080fd5b61416084614119565b92506020840135915061417560408501614119565b90509250925092565b60006020828403121561419057600080fd5b610b8082614119565b6000815180845260005b818110156141bf576020818501810151868301820152016141a3565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000610b806020830184614199565b6020808252825182820181905260009190848201906040850190845b8181101561425e57835173ffffffffffffffffffffffffffffffffffffffff168352928401929184019160010161422c565b50909695505050505050565b60006020828403121561427c57600080fd5b813567ffffffffffffffff81111561429357600080fd5b820160408185031215610b8057600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff811182821017156142f7576142f76142a5565b60405290565b60405160a0810167ffffffffffffffff811182821017156142f7576142f76142a5565b60405160c0810167ffffffffffffffff811182821017156142f7576142f76142a5565b604051610220810167ffffffffffffffff811182821017156142f7576142f76142a5565b6040516060810167ffffffffffffffff811182821017156142f7576142f76142a5565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156143d1576143d16142a5565b604052919050565b600067ffffffffffffffff8211156143f3576143f36142a5565b5060051b60200190565b60ff81168114610e5e57600080fd5b6000602080838503121561441f57600080fd5b823567ffffffffffffffff81111561443657600080fd5b8301601f8101851361444757600080fd5b803561445a614455826143d9565b61438a565b8181526060918202830184019184820191908884111561447957600080fd5b938501935b8385101561451957848903818112156144975760008081fd5b61449f6142d4565b6144a887614119565b81526040807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0840112156144dc5760008081fd5b6144e46142d4565b92506144f1898901614119565b83528701356144ff816143fd565b82890152808801919091528352938401939185019161447e565b50979650505050505050565b8015158114610e5e57600080fd5b803561413d81614525565b6000602080838503121561455157600080fd5b823567ffffffffffffffff81111561456857600080fd5b8301601f8101851361457957600080fd5b8035614587614455826143d9565b81815260a091820283018401918482019190888411156145a657600080fd5b938501935b838510156145195780858a0312156145c35760008081fd5b6145cb6142fd565b6145d486614119565b8152868601357fffffffffffffffffffff00000000000000000000000000000000000000000000811681146146095760008081fd5b818801526040868101357fffff000000000000000000000000000000000000000000000000000000000000811681146146425760008081fd5b908201526060614653878201614119565b9082015260808681013561466681614525565b90820152835293840193918501916145ab565b60008083601f84011261468b57600080fd5b50813567ffffffffffffffff8111156146a357600080fd5b6020830191508360208260051b85010111156120e557600080fd5b600080602083850312156146d157600080fd5b823567ffffffffffffffff8111156146e857600080fd5b6146f485828601614679565b90969095509350505050565b602080825282518282018190526000919060409081850190868401855b8281101561476e5761475e84835180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16825260209081015163ffffffff16910152565b928401929085019060010161471d565b5091979650505050505050565b803567ffffffffffffffff8116811461413d57600080fd5b6000602082840312156147a557600080fd5b610b808261477b565b81517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16815260208083015163ffffffff169082015260408101610f68565b81511515815261022081016020830151614809602084018261ffff169052565b506040830151614821604084018263ffffffff169052565b506060830151614839606084018263ffffffff169052565b506080830151614851608084018263ffffffff169052565b5060a083015161486760a084018261ffff169052565b5060c083015161487f60c084018263ffffffff169052565b5060e083015161489560e084018261ffff169052565b506101008381015161ffff9081169184019190915261012080850151909116908301526101408084015163ffffffff9081169184019190915261016080850151821690840152610180808501518216908401526101a08085015167ffffffffffffffff16908401526101c080850151909116908301526101e080840151151590830152610200808401517fffffffff000000000000000000000000000000000000000000000000000000008116828501525b505092915050565b803563ffffffff8116811461413d57600080fd5b803561ffff8116811461413d57600080fd5b600082601f83011261498657600080fd5b81356020614996614455836143d9565b82815260069290921b840181019181810190868411156149b557600080fd5b8286015b84811015614a0257604081890312156149d25760008081fd5b6149da6142d4565b6149e38261477b565b81526149f0858301614119565b818601528352918301916040016149b9565b509695505050505050565b60008060408385031215614a2057600080fd5b67ffffffffffffffff83351115614a3657600080fd5b83601f843585010112614a4857600080fd5b614a5861445584358501356143d9565b8335840180358083526020808401939260059290921b90910101861015614a7e57600080fd5b602085358601015b85358601803560051b01602001811015614c8b5767ffffffffffffffff81351115614ab057600080fd5b8035863587010160407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0828a03011215614ae957600080fd5b614af16142d4565b614afd6020830161477b565b815267ffffffffffffffff60408301351115614b1857600080fd5b88603f604084013584010112614b2d57600080fd5b614b4361445560206040850135850101356143d9565b6020604084810135850182810135808552928401939260e00201018b1015614b6a57600080fd5b6040808501358501015b6040858101358601602081013560e0020101811015614c6c5760e0818d031215614b9d57600080fd5b614ba56142d4565b614bae82614119565b815260c07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0838f03011215614be257600080fd5b614bea614320565b614bf66020840161494f565b8152614c046040840161494f565b6020820152614c1560608401614963565b6040820152614c266080840161494f565b6060820152614c3760a0840161494f565b6080820152614c4960c0840135614525565b60c083013560a0820152602082810191909152908452929092019160e001614b74565b5080602084015250508085525050602083019250602081019050614a86565b5092505067ffffffffffffffff60208401351115614ca857600080fd5b614cb88460208501358501614975565b90509250929050565b600082601f830112614cd257600080fd5b81356020614ce2614455836143d9565b8083825260208201915060208460051b870101935086841115614d0457600080fd5b602086015b84811015614a0257614d1a81614119565b8352918301918301614d09565b60008060408385031215614d3a57600080fd5b823567ffffffffffffffff80821115614d5257600080fd5b614d5e86838701614cc1565b93506020850135915080821115614d7457600080fd5b50614d8185828601614cc1565b9150509250929050565b60008083601f840112614d9d57600080fd5b50813567ffffffffffffffff811115614db557600080fd5b6020830191508360208285010111156120e557600080fd5b60008060008060408587031215614de357600080fd5b843567ffffffffffffffff80821115614dfb57600080fd5b614e0788838901614d8b565b90965094506020870135915080821115614e2057600080fd5b50614e2d87828801614d8b565b95989497509550505050565b60008060408385031215614e4c57600080fd5b614e558361477b565b9150614cb860208401614119565b600060208284031215614e7557600080fd5b813567ffffffffffffffff80821115614e8d57600080fd5b9083019060408286031215614ea157600080fd5b614ea96142d4565b823582811115614eb857600080fd5b614ec487828601614cc1565b825250602083013582811115614ed957600080fd5b614ee587828601614cc1565b60208301525095945050505050565b60006020808385031215614f0757600080fd5b823567ffffffffffffffff811115614f1e57600080fd5b8301601f81018513614f2f57600080fd5b8035614f3d614455826143d9565b81815260069190911b82018301908381019087831115614f5c57600080fd5b928401925b82841015614fae5760408489031215614f7a5760008081fd5b614f826142d4565b614f8b85614119565b8152614f9886860161477b565b8187015282526040939093019290840190614f61565b979650505050505050565b600080600080600060808688031215614fd157600080fd5b614fda8661477b565b9450614fe860208701614119565b935060408601359250606086013567ffffffffffffffff81111561500b57600080fd5b61501788828901614d8b565b969995985093965092949392505050565b8381528215156020820152606060408201526000612cb26060830184614199565b60008060008060006060868803121561506157600080fd5b61506a8661477b565b9450602086013567ffffffffffffffff8082111561508757600080fd5b61509389838a01614679565b909650945060408801359150808211156150ac57600080fd5b818801915088601f8301126150c057600080fd5b8135818111156150cf57600080fd5b8960208260061b85010111156150e457600080fd5b9699959850939650602001949392505050565b6000806040838503121561510a57600080fd5b6151138361477b565b9150602083013567ffffffffffffffff81111561512f57600080fd5b830160a0818603121561514157600080fd5b809150509250929050565b80357fffffffff000000000000000000000000000000000000000000000000000000008116811461413d57600080fd5b6000602080838503121561518f57600080fd5b823567ffffffffffffffff8111156151a657600080fd5b8301601f810185136151b757600080fd5b80356151c5614455826143d9565b81815261024091820283018401918482019190888411156151e557600080fd5b938501935b8385101561451957848903818112156152035760008081fd5b61520b6142d4565b6152148761477b565b8152610220807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0840112156152495760008081fd5b615251614343565b925061525e898901614533565b8352604061526d818a01614963565b8a850152606061527e818b0161494f565b8286015260809150615291828b0161494f565b9085015260a06152a28a820161494f565b8286015260c091506152b5828b01614963565b9085015260e06152c68a820161494f565b8286015261010091506152da828b01614963565b908501526101206152ec8a8201614963565b828601526101409150615300828b01614963565b908501526101606153128a820161494f565b828601526101809150615326828b0161494f565b908501526101a06153388a820161494f565b828601526101c0915061534c828b0161477b565b908501526101e061535e8a820161494f565b828601526102009150615372828b01614533565b9085015261538189830161514c565b908401525080880191909152835293840193918501916151ea565b600080604083850312156153af57600080fd5b6153b883614119565b9150614cb86020840161477b565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082028115828204841417610f6857610f686153c6565b600082615442577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261547c57600080fd5b83018035915067ffffffffffffffff82111561549757600080fd5b6020019150600681901b36038213156120e557600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b80357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116811461413d57600080fd5b60006040828403121561551c57600080fd5b6155246142d4565b61552d83614119565b815261553b602084016154de565b60208201529392505050565b60006040828403121561555957600080fd5b6155616142d4565b61552d8361477b565b6000602080838503121561557d57600080fd5b823567ffffffffffffffff81111561559457600080fd5b8301601f810185136155a557600080fd5b80356155b3614455826143d9565b818152606091820283018401918482019190888411156155d257600080fd5b938501935b838510156145195780858a0312156155ef5760008081fd5b6155f7614367565b61560086614119565b815261560d8787016154de565b87820152604061561e81880161494f565b90820152835293840193918501916155d7565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8183360301811261566557600080fd5b9190910192915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126156a457600080fd5b83018035915067ffffffffffffffff8211156156bf57600080fd5b6020019150368190038213156120e557600080fd5b80820180821115610f6857610f686153c6565b81810381811115610f6857610f686153c6565b60ff8181168382160190811115610f6857610f686153c6565b60ff8281168282160390811115610f6857610f686153c6565b600181815b8085111561578557817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561576b5761576b6153c6565b8085161561577857918102915b93841c9390800290615731565b509250929050565b60008261579c57506001610f68565b816157a957506000610f68565b81600181146157bf57600281146157c9576157e5565b6001915050610f68565b60ff8411156157da576157da6153c6565b50506001821b610f68565b5060208310610133831016604e8410600b8410161715615808575081810a610f68565b615812838361572c565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115615844576158446153c6565b029392505050565b6000610b8060ff84168361578d565b7fffffffff0000000000000000000000000000000000000000000000000000000081358181169160048510156149475760049490940360031b84901b1690921692915050565b600080858511156158b157600080fd5b838611156158be57600080fd5b5050820193919092039150565b6000604082840312156158dd57600080fd5b6158e56142d4565b82518152602083015161553b81614525565b60006020828403121561590957600080fd5b5051919050565b805169ffffffffffffffffffff8116811461413d57600080fd5b600080600080600060a0868803121561594257600080fd5b61594b86615910565b945060208601519350604086015192506060860151915061596e60808701615910565b90509295509295909350565b60006020828403121561598c57600080fd5b8151610b80816143fd565b6000604082840312156159a957600080fd5b6159b16142d4565b6159ba83614119565b8152602083013560208201528091505092915050565b63ffffffff8181168382160190808211156140ba576140ba6153c6565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint96\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"linkToken\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"stalenessThreshold\",\"type\":\"uint32\"}],\"internalType\":\"structPriceRegistry.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"priceUpdaters\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"feeTokens\",\"type\":\"address[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"}],\"internalType\":\"structIPriceRegistry.TokenPriceFeedConfig\",\"name\":\"feedConfig\",\"type\":\"tuple\"}],\"internalType\":\"structPriceRegistry.TokenPriceFeedUpdate[]\",\"name\":\"tokenPriceFeeds\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structPriceRegistry.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"internalType\":\"structPriceRegistry.TokenTransferFeeConfigSingleTokenArgs[]\",\"name\":\"tokenTransferFeeConfigs\",\"type\":\"tuple[]\"}],\"internalType\":\"structPriceRegistry.TokenTransferFeeConfigArgs[]\",\"name\":\"tokenTransferFeeConfigArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"internalType\":\"structPriceRegistry.PremiumMultiplierWeiPerEthArgs[]\",\"name\":\"premiumMultiplierWeiPerEthArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"internalType\":\"structPriceRegistry.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structPriceRegistry.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chain\",\"type\":\"uint64\"}],\"name\":\"ChainNotSupported\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DataFeedValueOutOfUint224Range\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"DestinationChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ExtraArgOutOfOrderExecutionMustBeTrue\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"}],\"name\":\"InvalidDestBytesOverhead\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidDestChainConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidEVMAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidExtraArgsTag\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidStaticConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"msgFeeJuels\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint256\"}],\"name\":\"MessageFeeTooHigh\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MessageGasLimitTooHigh\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"maxSize\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualSize\",\"type\":\"uint256\"}],\"name\":\"MessageTooLarge\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"internalType\":\"bytes10\",\"name\":\"workflowName\",\"type\":\"bytes10\"},{\"internalType\":\"bytes2\",\"name\":\"reportName\",\"type\":\"bytes2\"}],\"name\":\"ReportForwarderUnauthorized\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"SourceTokenDataTooLarge\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"threshold\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timePassed\",\"type\":\"uint256\"}],\"name\":\"StaleGasPrice\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feedTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"storedTimeStamp\",\"type\":\"uint256\"}],\"name\":\"StaleKeystoneUpdate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"TokenNotSupported\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"UnauthorizedCaller\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnsupportedNumberOfTokens\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"AuthorizedCallerAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"AuthorizedCallerRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"indexed\":false,\"internalType\":\"structPriceRegistry.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"name\":\"DestChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"indexed\":false,\"internalType\":\"structPriceRegistry.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"name\":\"DestChainConfigUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"}],\"name\":\"FeeTokenAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"}],\"name\":\"FeeTokenRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"name\":\"PremiumMultiplierWeiPerEthUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"}],\"indexed\":false,\"internalType\":\"structIPriceRegistry.TokenPriceFeedConfig\",\"name\":\"priceFeedConfig\",\"type\":\"tuple\"}],\"name\":\"PriceFeedPerTokenUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"reportId\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"},{\"internalType\":\"bytes10\",\"name\":\"workflowName\",\"type\":\"bytes10\"},{\"internalType\":\"bytes2\",\"name\":\"reportName\",\"type\":\"bytes2\"},{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isAllowed\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"structKeystoneFeedsPermissionHandler.Permission\",\"name\":\"permission\",\"type\":\"tuple\"}],\"name\":\"ReportPermissionSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"TokenTransferFeeConfigDeleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"structPriceRegistry.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"name\":\"TokenTransferFeeConfigUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"UsdPerTokenUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChain\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"UsdPerUnitGasUpdated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address[]\",\"name\":\"addedCallers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"removedCallers\",\"type\":\"address[]\"}],\"internalType\":\"structAuthorizedCallers.AuthorizedCallerArgs\",\"name\":\"authorizedCallerArgs\",\"type\":\"tuple\"}],\"name\":\"applyAuthorizedCallerUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"internalType\":\"structPriceRegistry.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structPriceRegistry.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyDestChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"feeTokensToAdd\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"feeTokensToRemove\",\"type\":\"address[]\"}],\"name\":\"applyFeeTokensUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"internalType\":\"structPriceRegistry.PremiumMultiplierWeiPerEthArgs[]\",\"name\":\"premiumMultiplierWeiPerEthArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyPremiumMultiplierWeiPerEthUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structPriceRegistry.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"internalType\":\"structPriceRegistry.TokenTransferFeeConfigSingleTokenArgs[]\",\"name\":\"tokenTransferFeeConfigs\",\"type\":\"tuple[]\"}],\"internalType\":\"structPriceRegistry.TokenTransferFeeConfigArgs[]\",\"name\":\"tokenTransferFeeConfigArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"internalType\":\"structPriceRegistry.TokenTransferFeeConfigRemoveArgs[]\",\"name\":\"tokensToUseDefaultFeeConfigs\",\"type\":\"tuple[]\"}],\"name\":\"applyTokenTransferFeeConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"fromToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fromTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"toToken\",\"type\":\"address\"}],\"name\":\"convertTokenAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllAuthorizedCallers\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getDestChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"internalType\":\"structPriceRegistry.DestChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getDestinationChainGasPrice\",\"outputs\":[{\"components\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"internalType\":\"structInternal.TimestampedPackedUint224\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getFeeTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getPremiumMultiplierWeiPerEth\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint96\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"linkToken\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"stalenessThreshold\",\"type\":\"uint32\"}],\"internalType\":\"structPriceRegistry.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getTokenAndGasPrices\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"tokenPrice\",\"type\":\"uint224\"},{\"internalType\":\"uint224\",\"name\":\"gasPriceValue\",\"type\":\"uint224\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenPrice\",\"outputs\":[{\"components\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"internalType\":\"structInternal.TimestampedPackedUint224\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenPriceFeedConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"}],\"internalType\":\"structIPriceRegistry.TokenPriceFeedConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"tokens\",\"type\":\"address[]\"}],\"name\":\"getTokenPrices\",\"outputs\":[{\"components\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"internalType\":\"structInternal.TimestampedPackedUint224[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenTransferFeeConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structPriceRegistry.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"getValidatedFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getValidatedTokenPrice\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"\",\"type\":\"uint224\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"onReport\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"name\":\"processMessageArgs\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"msgFeeJuels\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isOutOfOrderExecution\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"convertedExtraArgs\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"rampTokenAmounts\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"sourceTokenAmounts\",\"type\":\"tuple[]\"}],\"name\":\"processPoolReturnData\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"destExecDataPerToken\",\"type\":\"bytes[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"},{\"internalType\":\"bytes10\",\"name\":\"workflowName\",\"type\":\"bytes10\"},{\"internalType\":\"bytes2\",\"name\":\"reportName\",\"type\":\"bytes2\"},{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isAllowed\",\"type\":\"bool\"}],\"internalType\":\"structKeystoneFeedsPermissionHandler.Permission[]\",\"name\":\"permissions\",\"type\":\"tuple[]\"}],\"name\":\"setReportPermissions\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"}],\"name\":\"updatePrices\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"}],\"internalType\":\"structIPriceRegistry.TokenPriceFeedConfig\",\"name\":\"feedConfig\",\"type\":\"tuple\"}],\"internalType\":\"structPriceRegistry.TokenPriceFeedUpdate[]\",\"name\":\"tokenPriceFeedUpdates\",\"type\":\"tuple[]\"}],\"name\":\"updateTokenPriceFeeds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x60e06040523480156200001157600080fd5b50604051620076d8380380620076d8833981016040819052620000349162001834565b8533806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf8162000207565b5050604080518082018252838152815160008152602080820190935291810191909152620000ee9150620002b2565b5060208701516001600160a01b0316158062000112575086516001600160601b0316155b80620001265750604087015163ffffffff16155b15620001455760405163d794ef9560e01b815260040160405180910390fd5b6020878101516001600160a01b031660a05287516001600160601b031660805260408089015163ffffffff1660c05280516000815291820190526200018c90869062000401565b620001978462000549565b620001a2816200061a565b620001ad8262000a5a565b60408051600080825260208201909252620001fa91859190620001f3565b6040805180820190915260008082526020820152815260200190600190039081620001cb5790505b5062000b26565b5050505050505062001ae5565b336001600160a01b03821603620002615760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b602081015160005b815181101562000342576000828281518110620002db57620002db62001953565b60209081029190910101519050620002f560028262000e5f565b1562000338576040516001600160a01b03821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b50600101620002ba565b50815160005b8151811015620003fb57600082828151811062000369576200036962001953565b6020026020010151905060006001600160a01b0316816001600160a01b031603620003a7576040516342bcdf7f60e11b815260040160405180910390fd5b620003b460028262000e7f565b506040516001600160a01b03821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a15060010162000348565b50505050565b60005b8251811015620004a2576200044083828151811062000427576200042762001953565b6020026020010151600b62000e7f60201b90919060201c565b1562000499578281815181106200045b576200045b62001953565b60200260200101516001600160a01b03167fdf1b1bd32a69711488d71554706bb130b1fc63a5fa1a2cd85e8440f84065ba2360405160405180910390a25b60010162000404565b5060005b81518110156200054457620004e2828281518110620004c957620004c962001953565b6020026020010151600b62000e9660201b90919060201c565b156200053b57818181518110620004fd57620004fd62001953565b60200260200101516001600160a01b03167f1795838dc8ab2ffc5f431a1729a6afa0b587f982f7b2be0b9d7187a1ef547f9160405160405180910390a25b600101620004a6565b505050565b60005b8151811015620006165760008282815181106200056d576200056d62001953565b6020908102919091018101518051818301516001600160a01b0380831660008181526007875260409081902084518154868a018051929096166001600160a81b03199091168117600160a01b60ff9384160217909255825191825293519093169683019690965293955091939092917f08a5f7f5bb38a81d8e43aca13ecd76431dbf8816ae4699affff7b00b2fc1c464910160405180910390a25050508060010190506200054c565b5050565b60005b8151811015620006165760008282815181106200063e576200063e62001953565b6020026020010151905060008383815181106200065f576200065f62001953565b6020026020010151600001519050600082602001519050816001600160401b03166000148062000698575061016081015163ffffffff16155b80620006ba57506101e08101516001600160e01b031916630a04b54b60e21b14155b80620006da5750806060015163ffffffff1681610160015163ffffffff16115b15620007055760405163c35aa79d60e01b81526001600160401b038316600482015260240162000083565b6001600160401b038216600090815260096020526040812060010154600160881b900460e01b6001600160e01b03191690036200078557816001600160401b03167fd31c671936387b2f84ed402b553bd50c0e9c20408ea4e91a836d77b8180fb7248260405162000777919062001969565b60405180910390a2620007c9565b816001600160401b03167f1edd6f3553cfa16f10b95b195abae3a1cfca4783de4843f95d674b1e1df5ab2082604051620007c0919062001969565b60405180910390a25b8060096000846001600160401b03166001600160401b0316815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548161ffff021916908361ffff16021790555060408201518160000160036101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160076101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600b6101000a81548163ffffffff021916908363ffffffff16021790555060a082015181600001600f6101000a81548161ffff021916908361ffff16021790555060c08201518160000160116101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160000160156101000a81548161ffff021916908361ffff1602179055506101008201518160000160176101000a81548161ffff021916908361ffff1602179055506101208201518160000160196101000a81548161ffff021916908361ffff16021790555061014082015181600001601b6101000a81548163ffffffff021916908363ffffffff1602179055506101608201518160010160006101000a81548163ffffffff021916908363ffffffff1602179055506101808201518160010160046101000a8154816001600160401b0302191690836001600160401b031602179055506101a082015181600101600c6101000a81548163ffffffff021916908363ffffffff1602179055506101c08201518160010160106101000a81548160ff0219169083151502179055506101e08201518160010160116101000a81548163ffffffff021916908360e01c02179055509050505050508060010190506200061d565b60005b81518110156200061657600082828151811062000a7e5762000a7e62001953565b6020026020010151600001519050600083838151811062000aa35762000aa362001953565b6020908102919091018101518101516001600160a01b03841660008181526008845260409081902080546001600160401b0319166001600160401b0385169081179091559051908152919350917fbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d910160405180910390a2505060010162000a5d565b60005b825181101562000d9957600083828151811062000b4a5762000b4a62001953565b6020026020010151905060008160000151905060005b82602001515181101562000d8a5760008360200151828151811062000b895762000b8962001953565b602002602001015160200151905060008460200151838151811062000bb25762000bb262001953565b6020026020010151600001519050602063ffffffff16826080015163ffffffff16101562000c115760808201516040516312766e0160e11b81526001600160a01b038316600482015263ffffffff909116602482015260440162000083565b6001600160401b0384166000818152600a602090815260408083206001600160a01b0386168085529083529281902086518154938801518389015160608a015160808b015160a08c01511515600160901b0260ff60901b1963ffffffff928316600160701b021664ffffffffff60701b199383166a01000000000000000000000263ffffffff60501b1961ffff90961668010000000000000000029590951665ffffffffffff60401b19968416640100000000026001600160401b0319909b16939097169290921798909817939093169390931717919091161792909217909155519091907f94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b59062000d77908690600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60405180910390a3505060010162000b60565b50505080600101905062000b29565b5060005b81518110156200054457600082828151811062000dbe5762000dbe62001953565b6020026020010151600001519050600083838151811062000de35762000de362001953565b6020908102919091018101518101516001600160401b0384166000818152600a845260408082206001600160a01b038516808452955280822080546001600160981b03191690555192945090917f4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b9190a3505060010162000d9d565b600062000e76836001600160a01b03841662000ead565b90505b92915050565b600062000e76836001600160a01b03841662000fb1565b600062000e76836001600160a01b03841662001003565b6000818152600183016020526040812054801562000fa657600062000ed460018362001aad565b855490915060009062000eea9060019062001aad565b905081811462000f5657600086600001828154811062000f0e5762000f0e62001953565b906000526020600020015490508087600001848154811062000f345762000f3462001953565b6000918252602080832090910192909255918252600188019052604090208390555b855486908062000f6a5762000f6a62001acf565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505062000e79565b600091505062000e79565b600081815260018301602052604081205462000ffa5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000e79565b50600062000e79565b6000818152600183016020526040812054801562000fa65760006200102a60018362001aad565b8554909150600090620010409060019062001aad565b905080821462000f5657600086600001828154811062000f0e5762000f0e62001953565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b03811182821017156200109f576200109f62001064565b60405290565b60405160c081016001600160401b03811182821017156200109f576200109f62001064565b60405161020081016001600160401b03811182821017156200109f576200109f62001064565b604051601f8201601f191681016001600160401b03811182821017156200111b576200111b62001064565b604052919050565b80516001600160a01b03811681146200113b57600080fd5b919050565b805163ffffffff811681146200113b57600080fd5b6000606082840312156200116857600080fd5b604051606081016001600160401b03811182821017156200118d576200118d62001064565b604052825190915081906001600160601b0381168114620011ad57600080fd5b8152620011bd6020840162001123565b6020820152620011d06040840162001140565b60408201525092915050565b60006001600160401b03821115620011f857620011f862001064565b5060051b60200190565b600082601f8301126200121457600080fd5b815160206200122d6200122783620011dc565b620010f0565b8083825260208201915060208460051b8701019350868411156200125057600080fd5b602086015b848110156200127757620012698162001123565b835291830191830162001255565b509695505050505050565b600082601f8301126200129457600080fd5b81516020620012a76200122783620011dc565b82815260609283028501820192828201919087851115620012c757600080fd5b8387015b858110156200135a5780890382811215620012e65760008081fd5b620012f06200107a565b620012fb8362001123565b8152604080601f1984011215620013125760008081fd5b6200131c6200107a565b92506200132b88850162001123565b835283015160ff81168114620013415760008081fd5b82880152808701919091528452928401928101620012cb565b5090979650505050505050565b80516001600160401b03811681146200113b57600080fd5b805161ffff811681146200113b57600080fd5b805180151581146200113b57600080fd5b600082601f830112620013b557600080fd5b81516020620013c86200122783620011dc565b82815260059290921b84018101918181019086841115620013e857600080fd5b8286015b84811015620012775780516001600160401b03808211156200140d57600080fd5b908801906040601f19838c0381018213156200142857600080fd5b620014326200107a565b6200143f89860162001367565b815282850151848111156200145357600080fd5b8086019550508c603f8601126200146957600080fd5b8885015193506200147e6200122785620011dc565b84815260e09094028501830193898101908e8611156200149d57600080fd5b958401955b858710156200157657868f0360e0811215620014bd57600080fd5b620014c76200107a565b620014d28962001123565b815260c08683011215620014e557600080fd5b620014ef620010a5565b9150620014fe8d8a0162001140565b82526200150d878a0162001140565b8d8301526200151f60608a016200137f565b878301526200153160808a0162001140565b60608301526200154460a08a0162001140565b60808301526200155760c08a0162001392565b60a0830152808d0191909152825260e09690960195908a0190620014a2565b828b015250875250505092840192508301620013ec565b600082601f8301126200159f57600080fd5b81516020620015b26200122783620011dc565b82815260069290921b84018101918181019086841115620015d257600080fd5b8286015b84811015620012775760408189031215620015f15760008081fd5b620015fb6200107a565b620016068262001123565b81526200161585830162001367565b81860152835291830191604001620015d6565b80516001600160e01b0319811681146200113b57600080fd5b600082601f8301126200165357600080fd5b81516020620016666200122783620011dc565b82815261022092830285018201928282019190878511156200168757600080fd5b8387015b858110156200135a5780890382811215620016a65760008081fd5b620016b06200107a565b620016bb8362001367565b815261020080601f1984011215620016d35760008081fd5b620016dd620010ca565b9250620016ec88850162001392565b83526040620016fd8186016200137f565b8985015260606200171081870162001140565b82860152608091506200172582870162001140565b9085015260a06200173886820162001140565b8286015260c091506200174d8287016200137f565b9085015260e06200176086820162001140565b828601526101009150620017768287016200137f565b908501526101206200178a8682016200137f565b828601526101409150620017a08287016200137f565b90850152610160620017b486820162001140565b828601526101809150620017ca82870162001140565b908501526101a0620017de86820162001367565b828601526101c09150620017f482870162001140565b908501526101e06200180886820162001392565b828601526200181983870162001628565b9085015250508087019190915284529284019281016200168b565b6000806000806000806000610120888a0312156200185157600080fd5b6200185d898962001155565b60608901519097506001600160401b03808211156200187b57600080fd5b620018898b838c0162001202565b975060808a0151915080821115620018a057600080fd5b620018ae8b838c0162001202565b965060a08a0151915080821115620018c557600080fd5b620018d38b838c0162001282565b955060c08a0151915080821115620018ea57600080fd5b620018f88b838c01620013a3565b945060e08a01519150808211156200190f57600080fd5b6200191d8b838c016200158d565b93506101008a01519150808211156200193557600080fd5b50620019448a828b0162001641565b91505092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b815115158152610200810160208301516200198a602084018261ffff169052565b506040830151620019a3604084018263ffffffff169052565b506060830151620019bc606084018263ffffffff169052565b506080830151620019d5608084018263ffffffff169052565b5060a0830151620019ec60a084018261ffff169052565b5060c083015162001a0560c084018263ffffffff169052565b5060e083015162001a1c60e084018261ffff169052565b506101008381015161ffff9081169184019190915261012080850151909116908301526101408084015163ffffffff9081169184019190915261016080850151821690840152610180808501516001600160401b0316908401526101a080850151909116908301526101c0808401511515908301526101e0928301516001600160e01b031916929091019190915290565b8181038181111562000e7957634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b60805160a05160c051615b9962001b3f600039600081816102ef0152818161219101526121fa0152600081816102b301528181611917015261197701526000818161027f015281816119a00152611a100152615b996000f3fe608060405234801561001057600080fd5b50600436106101ce5760003560e01c806379ba509711610104578063a69c64c0116100a2578063d02641a011610071578063d02641a014610a81578063d8694ccd14610a94578063f2fde38b14610aa7578063ffdb4b3714610aba57600080fd5b8063a69c64c014610997578063bf78e03f146109aa578063c4276bfc14610a57578063cdc73d5114610a7957600080fd5b806382b49eb0116100de57806382b49eb0146107d95780638da5cb5b1461094957806391a2749a146109715780639ea600261461098457600080fd5b806379ba5097146107ab5780637afac322146107b3578063805f2132146107c657600080fd5b8063407e1086116101715780634ab35b0b1161014b5780634ab35b0b14610441578063514e8cff146104815780636def4ce714610524578063770e2dc41461079857600080fd5b8063407e1086146103fb57806341ed29e71461040e57806345ac924d1461042157600080fd5b8063085318f8116101ad578063085318f814610368578063181f5a77146103885780632451a627146103d15780633937306f146103e657600080fd5b806241e5be146101d3578063061877e3146101f957806306285c6914610252575b600080fd5b6101e66101e1366004614250565b610b02565b6040519081526020015b60405180910390f35b61023961020736600461428c565b73ffffffffffffffffffffffffffffffffffffffff1660009081526008602052604090205467ffffffffffffffff1690565b60405167ffffffffffffffff90911681526020016101f0565b61031c604080516060810182526000808252602082018190529181019190915260405180606001604052807f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000063ffffffff16815250905090565b6040805182516bffffffffffffffffffffffff16815260208084015173ffffffffffffffffffffffffffffffffffffffff16908201529181015163ffffffff16908201526060016101f0565b61037b610376366004614304565b610b70565b6040516101f09190614416565b6103c46040518060400160405280601781526020017f5072696365526567697374727920312e362e302d64657600000000000000000081525081565b6040516101f09190614498565b6103d9610ee2565b6040516101f091906144ab565b6103f96103f4366004614505565b610ef3565b005b6103f96104093660046146a7565b6111a8565b6103f961041c3660046147d9565b6111bc565b61043461042f366004614914565b6111fe565b6040516101f09190614956565b61045461044f36600461428c565b6112c9565b6040517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff90911681526020016101f0565b61051761048f3660046149d1565b60408051808201909152600080825260208201525067ffffffffffffffff166000908152600560209081526040918290208251808401909352547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811683527c0100000000000000000000000000000000000000000000000000000000900463ffffffff169082015290565b6040516101f091906149ec565b61078b6105323660046149d1565b6040805161020081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a081018290526101c081018290526101e08101919091525067ffffffffffffffff908116600090815260096020908152604091829020825161020081018452815460ff8082161515835261ffff61010080840482169685019690965263ffffffff630100000084048116978501979097526701000000000000008304871660608501526b0100000000000000000000008304871660808501526f010000000000000000000000000000008304811660a085015271010000000000000000000000000000000000808404881660c086015275010000000000000000000000000000000000000000008404821660e08087019190915277010000000000000000000000000000000000000000000000850483169786019790975279010000000000000000000000000000000000000000000000000084049091166101208501527b01000000000000000000000000000000000000000000000000000000909204861661014084015260019093015480861661016084015264010000000081049096166101808301526c0100000000000000000000000086049094166101a0820152700100000000000000000000000000000000850490911615156101c08201527fffffffff0000000000000000000000000000000000000000000000000000000092909304901b166101e082015290565b6040516101f09190614a27565b6103f96107a6366004614c3e565b6112d4565b6103f96112e6565b6103f96107c1366004614f58565b6113e3565b6103f96107d4366004614ffe565b6113f5565b6108e96107e736600461506a565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101919091525067ffffffffffffffff919091166000908152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff94909416835292815290829020825160c081018452905463ffffffff8082168352640100000000820481169383019390935268010000000000000000810461ffff16938201939093526a01000000000000000000008304821660608201526e01000000000000000000000000000083049091166080820152720100000000000000000000000000000000000090910460ff16151560a082015290565b6040516101f09190600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101f0565b6103f961097f366004615094565b6118dd565b6103f9610992366004615155565b6118ee565b6103f96109a5366004615362565b6118ff565b610a236109b836600461428c565b6040805180820182526000808252602091820181905273ffffffffffffffffffffffffffffffffffffffff93841681526007825282902082518084019093525492831682527401000000000000000000000000000000000000000090920460ff169181019190915290565b60408051825173ffffffffffffffffffffffffffffffffffffffff16815260209283015160ff1692810192909252016101f0565b610a6a610a65366004615427565b611910565b6040516101f093929190615496565b6103d9611b06565b610517610a8f36600461428c565b611b12565b6101e6610aa23660046154b7565b611c0e565b6103f9610ab536600461428c565b6120ac565b610acd610ac836600461550c565b6120bd565b604080517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff9384168152929091166020830152016101f0565b6000610b0d82612248565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16610b3485612248565b610b5c907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1685615565565b610b66919061557c565b90505b9392505050565b67ffffffffffffffff8086166000908152600960205260409020600101546060917101000000000000000000000000000000000090910460e01b908590811115610bbc57610bbc614540565b604051908082528060200260200182016040528015610bef57816020015b6060815260200190600190039081610bda5790505b50915060005b85811015610ed7576000858583818110610c1157610c116155b7565b610c27926020604090920201908101915061428c565b90506000888884818110610c3d57610c3d6155b7565b9050602002810190610c4f91906155e6565b610c5d906040810190615624565b9150506020811115610d125767ffffffffffffffff8a166000908152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff861684529091529020546e010000000000000000000000000000900463ffffffff16811115610d12576040517f36f536ca00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526024015b60405180910390fd5b610d82848a8a86818110610d2857610d286155b7565b9050602002810190610d3a91906155e6565b610d48906020810190615624565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506122e292505050565b67ffffffffffffffff8a166000818152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684528252808320815160c081018352905463ffffffff8082168352640100000000820481168386015268010000000000000000820461ffff16838501526a01000000000000000000008204811660608401526e010000000000000000000000000000820481166080840152720100000000000000000000000000000000000090910460ff16151560a08301908152958552600990935290832054935190937b0100000000000000000000000000000000000000000000000000000090049091169190610e815781610e87565b82606001515b6040805163ffffffff8316602082015291925001604051602081830303815290604052888781518110610ebc57610ebc6155b7565b60200260200101819052505050505050806001019050610bf5565b505095945050505050565b6060610eee6002612339565b905090565b610efb612346565b6000610f078280615689565b9050905060005b81811015611051576000610f228480615689565b83818110610f3257610f326155b7565b905060400201803603810190610f48919061571d565b604080518082018252602080840180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff908116845263ffffffff42818116858701908152885173ffffffffffffffffffffffffffffffffffffffff9081166000908152600690975295889020965190519092167c010000000000000000000000000000000000000000000000000000000002919092161790935584519051935194955016927f52f50aa6d1a95a4595361ecf953d095f125d442e4673716dede699e049de148a926110409290917bffffffffffffffffffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b60405180910390a250600101610f0e565b5060006110616020840184615689565b9050905060005b818110156111a257600061107f6020860186615689565b8381811061108f5761108f6155b7565b9050604002018036038101906110a5919061575a565b604080518082018252602080840180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff908116845263ffffffff42818116858701908152885167ffffffffffffffff9081166000908152600590975295889020965190519092167c010000000000000000000000000000000000000000000000000000000002919092161790935584519051935194955016927fdd84a3fa9ef9409f550d54d6affec7e9c480c878c6ab27b78912a03e1b371c6e926111919290917bffffffffffffffffffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b60405180910390a250600101611068565b50505050565b6111b061238b565b6111b98161240c565b50565b6111c461238b565b60005b81518110156111fa576111f28282815181106111e5576111e56155b7565b602002602001015161250a565b6001016111c7565b5050565b60608160008167ffffffffffffffff81111561121c5761121c614540565b60405190808252806020026020018201604052801561126157816020015b604080518082019091526000808252602082015281526020019060019003908161123a5790505b50905060005b828110156112be57611299868683818110611284576112846155b7565b9050602002016020810190610a8f919061428c565b8282815181106112ab576112ab6155b7565b6020908102919091010152600101611267565b509150505b92915050565b60006112c382612248565b6112dc61238b565b6111fa82826126dc565b60015473ffffffffffffffffffffffffffffffffffffffff163314611367576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610d09565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6113eb61238b565b6111fa8282612ae9565b600080600061143987878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612c3092505050565b92509250925061144b33838584612c4b565b60006114598587018761577d565b905060005b81518110156118d25760006007600084848151811061147f5761147f6155b7565b6020908102919091018101515173ffffffffffffffffffffffffffffffffffffffff16825281019190915260400160009081205474010000000000000000000000000000000000000000900460ff169150819003611540578282815181106114e9576114e96155b7565b6020908102919091010151516040517f06439c6b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610d09565b600061158960128386868151811061155a5761155a6155b7565b6020026020010151602001517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16612da3565b9050600660008585815181106115a1576115a16155b7565b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001601c9054906101000a900463ffffffff1663ffffffff16848481518110611613576116136155b7565b60200260200101516040015163ffffffff16101561171d5783838151811061163d5761163d6155b7565b60200260200101516000015184848151811061165b5761165b6155b7565b6020026020010151604001516006600087878151811061167d5761167d6155b7565b6020908102919091018101515173ffffffffffffffffffffffffffffffffffffffff90811683529082019290925260409081016000205490517f191ec70600000000000000000000000000000000000000000000000000000000815293909116600484015263ffffffff91821660248401527c01000000000000000000000000000000000000000000000000000000009004166044820152606401610d09565b6040518060400160405280827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16815260200185858151811061175e5761175e6155b7565b60200260200101516040015163ffffffff1681525060066000868681518110611789576117896155b7565b6020908102919091018101515173ffffffffffffffffffffffffffffffffffffffff168252818101929092526040016000208251929091015163ffffffff167c0100000000000000000000000000000000000000000000000000000000027bffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092169190911790558351849084908110611821576118216155b7565b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff167f52f50aa6d1a95a4595361ecf953d095f125d442e4673716dede699e049de148a82868681518110611877576118776155b7565b6020026020010151604001516040516118c09291907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff92909216825263ffffffff16602082015260400190565b60405180910390a2505060010161145e565b505050505050505050565b6118e561238b565b6111b981612e69565b6118f661238b565b6111b981612ff5565b61190761238b565b6111b98161349b565b60008060607f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff16036119705785925061199e565b61199b87877f0000000000000000000000000000000000000000000000000000000000000000610b02565b92505b7f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff16831115611a3d576040517f6a92a483000000000000000000000000000000000000000000000000000000008152600481018490526bffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166024820152604401610d09565b67ffffffffffffffff881660009081526009602052604081206001015463ffffffff1690611a6c878784613585565b9050806020015193508484611af3836040805182516024820152602092830151151560448083019190915282518083039091018152606490910190915290810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f181dcf100000000000000000000000000000000000000000000000000000000017905290565b9450945094505050955095509592505050565b6060610eee600b612339565b604080518082019091526000808252602082015273ffffffffffffffffffffffffffffffffffffffff8281166000908152600760209081526040918290208251808401909352549283168083527401000000000000000000000000000000000000000090930460ff169082015290611c0557505073ffffffffffffffffffffffffffffffffffffffff166000908152600660209081526040918290208251808401909352547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811683527c0100000000000000000000000000000000000000000000000000000000900463ffffffff169082015290565b610b698161372e565b67ffffffffffffffff8083166000908152600960209081526040808320815161020081018352815460ff808216151580845261ffff61010080850482169886019890985263ffffffff630100000085048116978601979097526701000000000000008404871660608601526b0100000000000000000000008404871660808601526f010000000000000000000000000000008404811660a086015271010000000000000000000000000000000000808504881660c087015275010000000000000000000000000000000000000000008504821660e08088019190915277010000000000000000000000000000000000000000000000860483169987019990995279010000000000000000000000000000000000000000000000000085049091166101208601527b01000000000000000000000000000000000000000000000000000000909304861661014085015260019094015480861661016085015264010000000081049098166101808401526c0100000000000000000000000088049094166101a0830152700100000000000000000000000000000000870490931615156101c08201527fffffffff000000000000000000000000000000000000000000000000000000009290950490921b166101e0840152909190611e28576040517f99ac52f200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff85166004820152602401610d09565b6000611e376040850185615689565b9150611e93905082611e4c6020870187615624565b905083611e598880615624565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506138bd92505050565b6000600881611ea8608088016060890161428c565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160009081205467ffffffffffffffff16915080611ef7611ef16080890160608a0161428c565b896120bd565b9092509050600080808615611f3d57611f31888c611f1b60808e0160608f0161428c565b888e8060400190611f2c9190615689565b613967565b91945092509050611f5d565b6101a0880151611f5a9063ffffffff16662386f26fc10000615565565b92505b61010088015160009061ffff1615611fa157611f9e896dffffffffffffffffffffffffffff607088901c16611f9560208f018f615624565b90508b86613c3f565b90505b61018089015160009067ffffffffffffffff16611fca611fc460808f018f615624565b8d613cef565b600001518563ffffffff168c60a0015161ffff168f8060200190611fee9190615624565b611ff9929150615565565b8d6080015163ffffffff1661200e9190615844565b6120189190615844565b6120229190615844565b61203c906dffffffffffffffffffffffffffff8916615565565b6120469190615565565b90507bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8716828261207d67ffffffffffffffff8c1689615565565b6120879190615844565b6120919190615844565b61209b919061557c565b9d9c50505050505050505050505050565b6120b461238b565b6111b981613db0565b67ffffffffffffffff811660009081526005602090815260408083208151808301909252547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811682527c0100000000000000000000000000000000000000000000000000000000900463ffffffff1691810182905282918203612175576040517f2e59db3a00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff85166004820152602401610d09565b6000816020015163ffffffff164261218d9190615857565b90507f000000000000000000000000000000000000000000000000000000000000000063ffffffff1681111561222e576040517ff08bcb3e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8616600482015263ffffffff7f000000000000000000000000000000000000000000000000000000000000000016602482015260448101829052606401610d09565b61223786612248565b9151919350909150505b9250929050565b60008061225483611b12565b9050806020015163ffffffff166000148061228c575080517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16155b156122db576040517f06439c6b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152602401610d09565b5192915050565b7fd7ed2ad4000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316016111fa5761233481613ea5565b505050565b60606000610b6983613f58565b612351600233613fb4565b612389576040517fd86ad9cf000000000000000000000000000000000000000000000000000000008152336004820152602401610d09565b565b60005473ffffffffffffffffffffffffffffffffffffffff163314612389576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610d09565b60005b81518110156111fa57600082828151811061242c5761242c6155b7565b60209081029190910181015180518183015173ffffffffffffffffffffffffffffffffffffffff80831660008181526007875260409081902084518154868a018051929096167fffffffffffffffffffffff00000000000000000000000000000000000000000090911681177401000000000000000000000000000000000000000060ff9384160217909255825191825293519093169683019690965293955091939092917f08a5f7f5bb38a81d8e43aca13ecd76431dbf8816ae4699affff7b00b2fc1c464910160405180910390a250505080600101905061240f565b60006125c382600001518360600151846020015185604001516040805173ffffffffffffffffffffffffffffffffffffffff80871660208301528516918101919091527fffffffffffffffffffff00000000000000000000000000000000000000000000831660608201527fffff0000000000000000000000000000000000000000000000000000000000008216608082015260009060a001604051602081830303815290604052805190602001209050949350505050565b60808301516000828152600460205260409081902080549215157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00909316929092179091555190915081907f32a4ba3fa3351b11ad555d4c8ec70a744e8705607077a946807030d64b6ab1a3906126d0908590600060a08201905073ffffffffffffffffffffffffffffffffffffffff8084511683527fffffffffffffffffffff0000000000000000000000000000000000000000000060208501511660208401527fffff00000000000000000000000000000000000000000000000000000000000060408501511660408401528060608501511660608401525060808301511515608083015292915050565b60405180910390a25050565b60005b8251811015612a055760008382815181106126fc576126fc6155b7565b6020026020010151905060008160000151905060005b8260200151518110156129f757600083602001518281518110612737576127376155b7565b602002602001015160200151905060008460200151838151811061275d5761275d6155b7565b6020026020010151600001519050602063ffffffff16826080015163ffffffff1610156127e05760808201516040517f24ecdc0200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8316600482015263ffffffff9091166024820152604401610d09565b67ffffffffffffffff84166000818152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff86168085529083529281902086518154938801518389015160608a015160808b015160a08c015115157201000000000000000000000000000000000000027fffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffff63ffffffff9283166e01000000000000000000000000000002167fffffffffffffffffffffffffff0000000000ffffffffffffffffffffffffffff9383166a0100000000000000000000027fffffffffffffffffffffffffffffffffffff00000000ffffffffffffffffffff61ffff9096166801000000000000000002959095167fffffffffffffffffffffffffffffffffffff000000000000ffffffffffffffff968416640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000909b16939097169290921798909817939093169390931717919091161792909217909155519091907f94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b5906129e5908690600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60405180910390a35050600101612712565b5050508060010190506126df565b5060005b8151811015612334576000828281518110612a2657612a266155b7565b60200260200101516000015190506000838381518110612a4857612a486155b7565b60209081029190910181015181015167ffffffffffffffff84166000818152600a8452604080822073ffffffffffffffffffffffffffffffffffffffff8516808452955280822080547fffffffffffffffffffffffffff000000000000000000000000000000000000001690555192945090917f4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b9190a35050600101612a09565b60005b8251811015612b8c57612b22838281518110612b0a57612b0a6155b7565b6020026020010151600b613fe390919063ffffffff16565b15612b8457828181518110612b3957612b396155b7565b602002602001015173ffffffffffffffffffffffffffffffffffffffff167fdf1b1bd32a69711488d71554706bb130b1fc63a5fa1a2cd85e8440f84065ba2360405160405180910390a25b600101612aec565b5060005b815181101561233457612bc6828281518110612bae57612bae6155b7565b6020026020010151600b61400590919063ffffffff16565b15612c2857818181518110612bdd57612bdd6155b7565b602002602001015173ffffffffffffffffffffffffffffffffffffffff167f1795838dc8ab2ffc5f431a1729a6afa0b587f982f7b2be0b9d7187a1ef547f9160405160405180910390a25b600101612b90565b6040810151604a820151605e90920151909260609290921c91565b6040805173ffffffffffffffffffffffffffffffffffffffff868116602080840191909152908616828401527fffffffffffffffffffff00000000000000000000000000000000000000000000851660608301527fffff00000000000000000000000000000000000000000000000000000000000084166080808401919091528351808403909101815260a09092018352815191810191909120600081815260049092529190205460ff16612d9c576040517f097e17ff00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8087166004830152851660248201527fffffffffffffffffffff00000000000000000000000000000000000000000000841660448201527fffff00000000000000000000000000000000000000000000000000000000000083166064820152608401610d09565b5050505050565b600080612db0848661586a565b9050600060248260ff161115612de757612dcb602483615883565b612dd690600a6159bc565b612de0908561557c565b9050612e0a565b612df2826024615883565b612dfd90600a6159bc565b612e079085615565565b90505b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811115612e60576040517f10cb51d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b95945050505050565b602081015160005b8151811015612f04576000828281518110612e8e57612e8e6155b7565b60200260200101519050612eac81600261402790919063ffffffff16565b15612efb5760405173ffffffffffffffffffffffffffffffffffffffff821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b50600101612e71565b50815160005b81518110156111a2576000828281518110612f2757612f276155b7565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603612f97576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612fa2600282613fe3565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a150600101612f0a565b60005b81518110156111fa576000828281518110613015576130156155b7565b602002602001015190506000838381518110613033576130336155b7565b60200260200101516000015190506000826020015190508167ffffffffffffffff166000148061306c575061016081015163ffffffff16155b806130be57506101e08101517fffffffff00000000000000000000000000000000000000000000000000000000167f2812d52c0000000000000000000000000000000000000000000000000000000014155b806130dd5750806060015163ffffffff1681610160015163ffffffff16115b15613120576040517fc35aa79d00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff83166004820152602401610d09565b67ffffffffffffffff821660009081526009602052604081206001015471010000000000000000000000000000000000900460e01b7fffffffff000000000000000000000000000000000000000000000000000000001690036131c4578167ffffffffffffffff167fd31c671936387b2f84ed402b553bd50c0e9c20408ea4e91a836d77b8180fb724826040516131b79190614a27565b60405180910390a2613207565b8167ffffffffffffffff167f1edd6f3553cfa16f10b95b195abae3a1cfca4783de4843f95d674b1e1df5ab20826040516131fe9190614a27565b60405180910390a25b80600960008467ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548161ffff021916908361ffff16021790555060408201518160000160036101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160076101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600b6101000a81548163ffffffff021916908363ffffffff16021790555060a082015181600001600f6101000a81548161ffff021916908361ffff16021790555060c08201518160000160116101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160000160156101000a81548161ffff021916908361ffff1602179055506101008201518160000160176101000a81548161ffff021916908361ffff1602179055506101208201518160000160196101000a81548161ffff021916908361ffff16021790555061014082015181600001601b6101000a81548163ffffffff021916908363ffffffff1602179055506101608201518160010160006101000a81548163ffffffff021916908363ffffffff1602179055506101808201518160010160046101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506101a082015181600101600c6101000a81548163ffffffff021916908363ffffffff1602179055506101c08201518160010160106101000a81548160ff0219169083151502179055506101e08201518160010160116101000a81548163ffffffff021916908360e01c0217905550905050505050806001019050612ff8565b60005b81518110156111fa5760008282815181106134bb576134bb6155b7565b602002602001015160000151905060008383815181106134dd576134dd6155b7565b60209081029190910181015181015173ffffffffffffffffffffffffffffffffffffffff841660008181526008845260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff85169081179091559051908152919350917fbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d910160405180910390a2505060010161349e565b604080518082019091526000808252602082015260008390036135c657506040805180820190915267ffffffffffffffff8216815260006020820152610b69565b60006135d284866159cb565b905060006135e38560048189615a11565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505050507fffffffff0000000000000000000000000000000000000000000000000000000082167fe7e230f0000000000000000000000000000000000000000000000000000000000161368057808060200190518101906136779190615a3b565b92505050610b69565b7f6859a837000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316016136fc576040518060400160405280828060200190518101906136e89190615a67565b815260006020909101529250610b69915050565b6040517f5247fdce00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080518082019091526000808252602082015260008260000151905060008173ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015613798573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137bc9190615a9a565b50505091505060008112156137fd576040517f10cb51d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061387c8373ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561384d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138719190615aea565b866020015184612da3565b604080518082019091527bffffffffffffffffffffffffffffffffffffffffffffffffffffffff909116815263ffffffff4216602082015295945050505050565b836040015163ffffffff168311156139165760408085015190517f8693378900000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015260248101849052604401610d09565b836020015161ffff16821115613958576040517f4c056b6a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6111a2846101e00151826122e2565b6000808083815b81811015613c3157600087878381811061398a5761398a6155b7565b9050604002018036038101906139a09190615b07565b67ffffffffffffffff8c166000908152600a60209081526040808320845173ffffffffffffffffffffffffffffffffffffffff168452825291829020825160c081018452905463ffffffff8082168352640100000000820481169383019390935268010000000000000000810461ffff16938201939093526a01000000000000000000008304821660608201526e01000000000000000000000000000083049091166080820152720100000000000000000000000000000000000090910460ff16151560a0820181905291925090613ac0576101208d0151613a8d9061ffff16662386f26fc10000615565565b613a979088615844565b96508c610140015186613aaa9190615b40565b9550613ab7602086615b40565b94505050613c29565b604081015160009061ffff1615613b795760008c73ffffffffffffffffffffffffffffffffffffffff16846000015173ffffffffffffffffffffffffffffffffffffffff1614613b1c578351613b1590612248565b9050613b1f565b508a5b620186a0836040015161ffff16613b618660200151847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1661404990919063ffffffff16565b613b6b9190615565565b613b75919061557c565b9150505b6060820151613b889088615b40565b9650816080015186613b9a9190615b40565b8251909650600090613bb99063ffffffff16662386f26fc10000615565565b905080821015613bd857613bcd818a615844565b985050505050613c29565b6000836020015163ffffffff16662386f26fc10000613bf79190615565565b905080831115613c1757613c0b818b615844565b99505050505050613c29565b613c21838b615844565b995050505050505b60010161396e565b505096509650969350505050565b60008063ffffffff8316613c5561016086615565565b613c61876101c0615844565b613c6b9190615844565b613c759190615844565b905060008760c0015163ffffffff168860e0015161ffff1683613c989190615565565b613ca29190615844565b61010089015190915061ffff16613cc96dffffffffffffffffffffffffffff891683615565565b613cd39190615565565b613ce390655af3107a4000615565565b98975050505050505050565b60408051808201909152600080825260208201526000613d1b858585610160015163ffffffff16613585565b9050826060015163ffffffff1681600001511115613d65576040517f4c4fc93a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b826101c001518015613d7957508060200151155b15610b66576040517fee433e9900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff821603613e2f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610d09565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60008151602014613ee457816040517f8d666f60000000000000000000000000000000000000000000000000000000008152600401610d099190614498565b600082806020019051810190613efa9190615a67565b905073ffffffffffffffffffffffffffffffffffffffff811180613f1f575061040081105b156112c357826040517f8d666f60000000000000000000000000000000000000000000000000000000008152600401610d099190614498565b606081600001805480602002602001604051908101604052809291908181526020018280548015613fa857602002820191906000526020600020905b815481526020019060010190808311613f94575b50505050509050919050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515610b69565b6000610b698373ffffffffffffffffffffffffffffffffffffffff8416614086565b6000610b698373ffffffffffffffffffffffffffffffffffffffff84166140d5565b6000610b698373ffffffffffffffffffffffffffffffffffffffff84166141cf565b6000670de0b6b3a764000061407c837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8616615565565b610b69919061557c565b60008181526001830160205260408120546140cd575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556112c3565b5060006112c3565b600081815260018301602052604081205480156141be5760006140f9600183615857565b855490915060009061410d90600190615857565b905080821461417257600086600001828154811061412d5761412d6155b7565b9060005260206000200154905080876000018481548110614150576141506155b7565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061418357614183615b5d565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506112c3565b60009150506112c3565b5092915050565b600081815260018301602052604081205480156141be5760006141f3600183615857565b855490915060009061420790600190615857565b905081811461417257600086600001828154811061412d5761412d6155b7565b803573ffffffffffffffffffffffffffffffffffffffff8116811461424b57600080fd5b919050565b60008060006060848603121561426557600080fd5b61426e84614227565b92506020840135915061428360408501614227565b90509250925092565b60006020828403121561429e57600080fd5b610b6982614227565b803567ffffffffffffffff8116811461424b57600080fd5b60008083601f8401126142d157600080fd5b50813567ffffffffffffffff8111156142e957600080fd5b6020830191508360208260051b850101111561224157600080fd5b60008060008060006060868803121561431c57600080fd5b614325866142a7565b9450602086013567ffffffffffffffff8082111561434257600080fd5b61434e89838a016142bf565b9096509450604088013591508082111561436757600080fd5b818801915088601f83011261437b57600080fd5b81358181111561438a57600080fd5b8960208260061b850101111561439f57600080fd5b9699959850939650602001949392505050565b6000815180845260005b818110156143d8576020818501810151868301820152016143bc565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b8281101561448b577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526144798583516143b2565b9450928501929085019060010161443f565b5092979650505050505050565b602081526000610b6960208301846143b2565b6020808252825182820181905260009190848201906040850190845b818110156144f957835173ffffffffffffffffffffffffffffffffffffffff16835292840192918401916001016144c7565b50909695505050505050565b60006020828403121561451757600080fd5b813567ffffffffffffffff81111561452e57600080fd5b820160408185031215610b6957600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561459257614592614540565b60405290565b60405160a0810167ffffffffffffffff8111828210171561459257614592614540565b60405160c0810167ffffffffffffffff8111828210171561459257614592614540565b604051610200810167ffffffffffffffff8111828210171561459257614592614540565b6040516060810167ffffffffffffffff8111828210171561459257614592614540565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561466c5761466c614540565b604052919050565b600067ffffffffffffffff82111561468e5761468e614540565b5060051b60200190565b60ff811681146111b957600080fd5b600060208083850312156146ba57600080fd5b823567ffffffffffffffff8111156146d157600080fd5b8301601f810185136146e257600080fd5b80356146f56146f082614674565b614625565b8181526060918202830184019184820191908884111561471457600080fd5b938501935b838510156147b457848903818112156147325760008081fd5b61473a61456f565b61474387614227565b81526040807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0840112156147775760008081fd5b61477f61456f565b925061478c898901614227565b835287013561479a81614698565b828901528088019190915283529384019391850191614719565b50979650505050505050565b80151581146111b957600080fd5b803561424b816147c0565b600060208083850312156147ec57600080fd5b823567ffffffffffffffff81111561480357600080fd5b8301601f8101851361481457600080fd5b80356148226146f082614674565b81815260a0918202830184019184820191908884111561484157600080fd5b938501935b838510156147b45780858a03121561485e5760008081fd5b614866614598565b61486f86614227565b8152868601357fffffffffffffffffffff00000000000000000000000000000000000000000000811681146148a45760008081fd5b818801526040868101357fffff000000000000000000000000000000000000000000000000000000000000811681146148dd5760008081fd5b9082015260606148ee878201614227565b90820152608086810135614901816147c0565b9082015283529384019391850191614846565b6000806020838503121561492757600080fd5b823567ffffffffffffffff81111561493e57600080fd5b61494a858286016142bf565b90969095509350505050565b602080825282518282018190526000919060409081850190868401855b828110156149c4576149b484835180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16825260209081015163ffffffff16910152565b9284019290850190600101614973565b5091979650505050505050565b6000602082840312156149e357600080fd5b610b69826142a7565b81517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16815260208083015163ffffffff1690820152604081016112c3565b81511515815261020081016020830151614a47602084018261ffff169052565b506040830151614a5f604084018263ffffffff169052565b506060830151614a77606084018263ffffffff169052565b506080830151614a8f608084018263ffffffff169052565b5060a0830151614aa560a084018261ffff169052565b5060c0830151614abd60c084018263ffffffff169052565b5060e0830151614ad360e084018261ffff169052565b506101008381015161ffff9081169184019190915261012080850151909116908301526101408084015163ffffffff90811691840191909152610160808501518216908401526101808085015167ffffffffffffffff16908401526101a080850151909116908301526101c0808401511515908301526101e0808401517fffffffff000000000000000000000000000000000000000000000000000000008116828501525b505092915050565b803563ffffffff8116811461424b57600080fd5b803561ffff8116811461424b57600080fd5b600082601f830112614bb757600080fd5b81356020614bc76146f083614674565b82815260069290921b84018101918181019086841115614be657600080fd5b8286015b84811015614c335760408189031215614c035760008081fd5b614c0b61456f565b614c14826142a7565b8152614c21858301614227565b81860152835291830191604001614bea565b509695505050505050565b60008060408385031215614c5157600080fd5b67ffffffffffffffff83351115614c6757600080fd5b83601f843585010112614c7957600080fd5b614c896146f08435850135614674565b8335840180358083526020808401939260059290921b90910101861015614caf57600080fd5b602085358601015b85358601803560051b01602001811015614ebc5767ffffffffffffffff81351115614ce157600080fd5b8035863587010160407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0828a03011215614d1a57600080fd5b614d2261456f565b614d2e602083016142a7565b815267ffffffffffffffff60408301351115614d4957600080fd5b88603f604084013584010112614d5e57600080fd5b614d746146f06020604085013585010135614674565b6020604084810135850182810135808552928401939260e00201018b1015614d9b57600080fd5b6040808501358501015b6040858101358601602081013560e0020101811015614e9d5760e0818d031215614dce57600080fd5b614dd661456f565b614ddf82614227565b815260c07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0838f03011215614e1357600080fd5b614e1b6145bb565b614e2760208401614b80565b8152614e3560408401614b80565b6020820152614e4660608401614b94565b6040820152614e5760808401614b80565b6060820152614e6860a08401614b80565b6080820152614e7a60c08401356147c0565b60c083013560a0820152602082810191909152908452929092019160e001614da5565b5080602084015250508085525050602083019250602081019050614cb7565b5092505067ffffffffffffffff60208401351115614ed957600080fd5b614ee98460208501358501614ba6565b90509250929050565b600082601f830112614f0357600080fd5b81356020614f136146f083614674565b8083825260208201915060208460051b870101935086841115614f3557600080fd5b602086015b84811015614c3357614f4b81614227565b8352918301918301614f3a565b60008060408385031215614f6b57600080fd5b823567ffffffffffffffff80821115614f8357600080fd5b614f8f86838701614ef2565b93506020850135915080821115614fa557600080fd5b50614fb285828601614ef2565b9150509250929050565b60008083601f840112614fce57600080fd5b50813567ffffffffffffffff811115614fe657600080fd5b60208301915083602082850101111561224157600080fd5b6000806000806040858703121561501457600080fd5b843567ffffffffffffffff8082111561502c57600080fd5b61503888838901614fbc565b9096509450602087013591508082111561505157600080fd5b5061505e87828801614fbc565b95989497509550505050565b6000806040838503121561507d57600080fd5b615086836142a7565b9150614ee960208401614227565b6000602082840312156150a657600080fd5b813567ffffffffffffffff808211156150be57600080fd5b90830190604082860312156150d257600080fd5b6150da61456f565b8235828111156150e957600080fd5b6150f587828601614ef2565b82525060208301358281111561510a57600080fd5b61511687828601614ef2565b60208301525095945050505050565b80357fffffffff000000000000000000000000000000000000000000000000000000008116811461424b57600080fd5b6000602080838503121561516857600080fd5b823567ffffffffffffffff81111561517f57600080fd5b8301601f8101851361519057600080fd5b803561519e6146f082614674565b81815261022091820283018401918482019190888411156151be57600080fd5b938501935b838510156147b457848903818112156151dc5760008081fd5b6151e461456f565b6151ed876142a7565b8152610200807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0840112156152225760008081fd5b61522a6145de565b92506152378989016147ce565b83526040615246818a01614b94565b8a8501526060615257818b01614b80565b828601526080915061526a828b01614b80565b9085015260a061527b8a8201614b80565b8286015260c0915061528e828b01614b94565b9085015260e061529f8a8201614b80565b8286015261010091506152b3828b01614b94565b908501526101206152c58a8201614b94565b8286015261014091506152d9828b01614b94565b908501526101606152eb8a8201614b80565b8286015261018091506152ff828b01614b80565b908501526101a06153118a82016142a7565b828601526101c09150615325828b01614b80565b908501526101e06153378a82016147ce565b82860152615346838b01615125565b90850152505080880191909152835293840193918501916151c3565b6000602080838503121561537557600080fd5b823567ffffffffffffffff81111561538c57600080fd5b8301601f8101851361539d57600080fd5b80356153ab6146f082614674565b81815260069190911b820183019083810190878311156153ca57600080fd5b928401925b8284101561541c57604084890312156153e85760008081fd5b6153f061456f565b6153f985614227565b81526154068686016142a7565b81870152825260409390930192908401906153cf565b979650505050505050565b60008060008060006080868803121561543f57600080fd5b615448866142a7565b945061545660208701614227565b935060408601359250606086013567ffffffffffffffff81111561547957600080fd5b61548588828901614fbc565b969995985093965092949392505050565b8381528215156020820152606060408201526000612e6060608301846143b2565b600080604083850312156154ca57600080fd5b6154d3836142a7565b9150602083013567ffffffffffffffff8111156154ef57600080fd5b830160a0818603121561550157600080fd5b809150509250929050565b6000806040838503121561551f57600080fd5b61552883614227565b9150614ee9602084016142a7565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80820281158282048414176112c3576112c3615536565b6000826155b2577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6183360301811261561a57600080fd5b9190910192915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261565957600080fd5b83018035915067ffffffffffffffff82111561567457600080fd5b60200191503681900382131561224157600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126156be57600080fd5b83018035915067ffffffffffffffff8211156156d957600080fd5b6020019150600681901b360382131561224157600080fd5b80357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116811461424b57600080fd5b60006040828403121561572f57600080fd5b61573761456f565b61574083614227565b815261574e602084016156f1565b60208201529392505050565b60006040828403121561576c57600080fd5b61577461456f565b615740836142a7565b6000602080838503121561579057600080fd5b823567ffffffffffffffff8111156157a757600080fd5b8301601f810185136157b857600080fd5b80356157c66146f082614674565b818152606091820283018401918482019190888411156157e557600080fd5b938501935b838510156147b45780858a0312156158025760008081fd5b61580a614602565b61581386614227565b81526158208787016156f1565b878201526040615831818801614b80565b90820152835293840193918501916157ea565b808201808211156112c3576112c3615536565b818103818111156112c3576112c3615536565b60ff81811683821601908111156112c3576112c3615536565b60ff82811682821603908111156112c3576112c3615536565b600181815b808511156158f557817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156158db576158db615536565b808516156158e857918102915b93841c93908002906158a1565b509250929050565b60008261590c575060016112c3565b81615919575060006112c3565b816001811461592f576002811461593957615955565b60019150506112c3565b60ff84111561594a5761594a615536565b50506001821b6112c3565b5060208310610133831016604e8410600b8410161715615978575081810a6112c3565b615982838361589c565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156159b4576159b4615536565b029392505050565b6000610b6960ff8416836158fd565b7fffffffff000000000000000000000000000000000000000000000000000000008135818116916004851015614b785760049490940360031b84901b1690921692915050565b60008085851115615a2157600080fd5b83861115615a2e57600080fd5b5050820193919092039150565b600060408284031215615a4d57600080fd5b615a5561456f565b82518152602083015161574e816147c0565b600060208284031215615a7957600080fd5b5051919050565b805169ffffffffffffffffffff8116811461424b57600080fd5b600080600080600060a08688031215615ab257600080fd5b615abb86615a80565b9450602086015193506040860151925060608601519150615ade60808701615a80565b90509295509295909350565b600060208284031215615afc57600080fd5b8151610b6981614698565b600060408284031215615b1957600080fd5b615b2161456f565b615b2a83614227565b8152602083013560208201528091505092915050565b63ffffffff8181168382160190808211156141c8576141c8615536565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea164736f6c6343000818000a", } var PriceRegistryABI = PriceRegistryMetaData.ABI @@ -663,46 +663,48 @@ func (_PriceRegistry *PriceRegistryCallerSession) ProcessMessageArgs(destChainSe return _PriceRegistry.Contract.ProcessMessageArgs(&_PriceRegistry.CallOpts, destChainSelector, feeToken, feeTokenAmount, extraArgs) } -func (_PriceRegistry *PriceRegistryCaller) TypeAndVersion(opts *bind.CallOpts) (string, error) { +func (_PriceRegistry *PriceRegistryCaller) ProcessPoolReturnData(opts *bind.CallOpts, destChainSelector uint64, rampTokenAmounts []InternalRampTokenAmount, sourceTokenAmounts []ClientEVMTokenAmount) ([][]byte, error) { var out []interface{} - err := _PriceRegistry.contract.Call(opts, &out, "typeAndVersion") + err := _PriceRegistry.contract.Call(opts, &out, "processPoolReturnData", destChainSelector, rampTokenAmounts, sourceTokenAmounts) if err != nil { - return *new(string), err + return *new([][]byte), err } - out0 := *abi.ConvertType(out[0], new(string)).(*string) + out0 := *abi.ConvertType(out[0], new([][]byte)).(*[][]byte) return out0, err } -func (_PriceRegistry *PriceRegistrySession) TypeAndVersion() (string, error) { - return _PriceRegistry.Contract.TypeAndVersion(&_PriceRegistry.CallOpts) +func (_PriceRegistry *PriceRegistrySession) ProcessPoolReturnData(destChainSelector uint64, rampTokenAmounts []InternalRampTokenAmount, sourceTokenAmounts []ClientEVMTokenAmount) ([][]byte, error) { + return _PriceRegistry.Contract.ProcessPoolReturnData(&_PriceRegistry.CallOpts, destChainSelector, rampTokenAmounts, sourceTokenAmounts) } -func (_PriceRegistry *PriceRegistryCallerSession) TypeAndVersion() (string, error) { - return _PriceRegistry.Contract.TypeAndVersion(&_PriceRegistry.CallOpts) +func (_PriceRegistry *PriceRegistryCallerSession) ProcessPoolReturnData(destChainSelector uint64, rampTokenAmounts []InternalRampTokenAmount, sourceTokenAmounts []ClientEVMTokenAmount) ([][]byte, error) { + return _PriceRegistry.Contract.ProcessPoolReturnData(&_PriceRegistry.CallOpts, destChainSelector, rampTokenAmounts, sourceTokenAmounts) } -func (_PriceRegistry *PriceRegistryCaller) ValidatePoolReturnData(opts *bind.CallOpts, destChainSelector uint64, rampTokenAmounts []InternalRampTokenAmount, sourceTokenAmounts []ClientEVMTokenAmount) error { +func (_PriceRegistry *PriceRegistryCaller) TypeAndVersion(opts *bind.CallOpts) (string, error) { var out []interface{} - err := _PriceRegistry.contract.Call(opts, &out, "validatePoolReturnData", destChainSelector, rampTokenAmounts, sourceTokenAmounts) + err := _PriceRegistry.contract.Call(opts, &out, "typeAndVersion") if err != nil { - return err + return *new(string), err } - return err + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err } -func (_PriceRegistry *PriceRegistrySession) ValidatePoolReturnData(destChainSelector uint64, rampTokenAmounts []InternalRampTokenAmount, sourceTokenAmounts []ClientEVMTokenAmount) error { - return _PriceRegistry.Contract.ValidatePoolReturnData(&_PriceRegistry.CallOpts, destChainSelector, rampTokenAmounts, sourceTokenAmounts) +func (_PriceRegistry *PriceRegistrySession) TypeAndVersion() (string, error) { + return _PriceRegistry.Contract.TypeAndVersion(&_PriceRegistry.CallOpts) } -func (_PriceRegistry *PriceRegistryCallerSession) ValidatePoolReturnData(destChainSelector uint64, rampTokenAmounts []InternalRampTokenAmount, sourceTokenAmounts []ClientEVMTokenAmount) error { - return _PriceRegistry.Contract.ValidatePoolReturnData(&_PriceRegistry.CallOpts, destChainSelector, rampTokenAmounts, sourceTokenAmounts) +func (_PriceRegistry *PriceRegistryCallerSession) TypeAndVersion() (string, error) { + return _PriceRegistry.Contract.TypeAndVersion(&_PriceRegistry.CallOpts) } func (_PriceRegistry *PriceRegistryTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { @@ -2825,11 +2827,11 @@ func (PriceRegistryAuthorizedCallerRemoved) Topic() common.Hash { } func (PriceRegistryDestChainAdded) Topic() common.Hash { - return common.HexToHash("0xa937382a486d993de71c220bc8b559242deb4e286a353fa732330b4aa7d13577") + return common.HexToHash("0xd31c671936387b2f84ed402b553bd50c0e9c20408ea4e91a836d77b8180fb724") } func (PriceRegistryDestChainConfigUpdated) Topic() common.Hash { - return common.HexToHash("0xa7b607fc10d28a1caf39ab7d27f4c94945db708a576d572781a455c5894fad93") + return common.HexToHash("0x1edd6f3553cfa16f10b95b195abae3a1cfca4783de4843f95d674b1e1df5ab20") } func (PriceRegistryFeeTokenAdded) Topic() common.Hash { @@ -2917,9 +2919,9 @@ type PriceRegistryInterface interface { error) - TypeAndVersion(opts *bind.CallOpts) (string, error) + ProcessPoolReturnData(opts *bind.CallOpts, destChainSelector uint64, rampTokenAmounts []InternalRampTokenAmount, sourceTokenAmounts []ClientEVMTokenAmount) ([][]byte, error) - ValidatePoolReturnData(opts *bind.CallOpts, destChainSelector uint64, rampTokenAmounts []InternalRampTokenAmount, sourceTokenAmounts []ClientEVMTokenAmount) error + TypeAndVersion(opts *bind.CallOpts) (string, error) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) diff --git a/core/gethwrappers/ccip/generated/report_codec/report_codec.go b/core/gethwrappers/ccip/generated/report_codec/report_codec.go index 7afd3d9bba..0080cfc419 100644 --- a/core/gethwrappers/ccip/generated/report_codec/report_codec.go +++ b/core/gethwrappers/ccip/generated/report_codec/report_codec.go @@ -70,6 +70,7 @@ type InternalRampTokenAmount struct { DestTokenAddress []byte ExtraData []byte Amount *big.Int + DestExecData []byte } type InternalTokenPriceUpdate struct { @@ -94,8 +95,8 @@ type OffRampMerkleRoot struct { } var ReportCodecMetaData = &bind.MetaData{ - ABI: "[{\"anonymous\":false,\"inputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"internalType\":\"structOffRamp.Interval\",\"name\":\"interval\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structOffRamp.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"report\",\"type\":\"tuple\"}],\"name\":\"CommitReportDecoded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage[]\",\"name\":\"messages\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[][]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[][]\"},{\"internalType\":\"bytes32[]\",\"name\":\"proofs\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"proofFlagBits\",\"type\":\"uint256\"}],\"indexed\":false,\"internalType\":\"structInternal.ExecutionReportSingleChain[]\",\"name\":\"report\",\"type\":\"tuple[]\"}],\"name\":\"ExecuteReportDecoded\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"decodeCommitReport\",\"outputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"internalType\":\"structOffRamp.Interval\",\"name\":\"interval\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structOffRamp.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"}],\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"decodeExecuteReport\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage[]\",\"name\":\"messages\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[][]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[][]\"},{\"internalType\":\"bytes32[]\",\"name\":\"proofs\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"proofFlagBits\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.ExecutionReportSingleChain[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]", - Bin: "0x608060405234801561001057600080fd5b5061124f806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80636fb349561461003b578063f816ec6014610064575b600080fd5b61004e61004936600461024f565b610084565b60405161005b91906104f5565b60405180910390f35b61007761007236600461024f565b6100a0565b60405161005b91906107ae565b60608180602001905181019061009a9190610dc3565b92915050565b604080516080810182526060918101828152828201839052815260208101919091528180602001905181019061009a91906110d9565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff81118282101715610128576101286100d6565b60405290565b6040516080810167ffffffffffffffff81118282101715610128576101286100d6565b60405160c0810167ffffffffffffffff81118282101715610128576101286100d6565b6040805190810167ffffffffffffffff81118282101715610128576101286100d6565b6040516060810167ffffffffffffffff81118282101715610128576101286100d6565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715610201576102016100d6565b604052919050565b600067ffffffffffffffff821115610223576102236100d6565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b60006020828403121561026157600080fd5b813567ffffffffffffffff81111561027857600080fd5b8201601f8101841361028957600080fd5b803561029c61029782610209565b6101ba565b8181528560208385010111156102b157600080fd5b81602084016020830137600091810160200191909152949350505050565b60005b838110156102ea5781810151838201526020016102d2565b50506000910152565b6000815180845261030b8160208601602086016102cf565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b600082825180855260208086019550808260051b84010181860160005b848110156103f2577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe086840301895281516080815181865261039e828701826102f3565b91505085820151858203878701526103b682826102f3565b915050604080830151868303828801526103d083826102f3565b606094850151979094019690965250509884019892509083019060010161035a565b5090979650505050505050565b6000828251808552602080860195506005818360051b8501018287016000805b868110156104aa577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe088850381018c5283518051808752908801908887019080891b88018a01865b8281101561049357858a83030184526104818286516102f3565b948c0194938c01939150600101610467565b509e8a019e9750505093870193505060010161041f565b50919998505050505050505050565b60008151808452602080850194506020840160005b838110156104ea578151875295820195908201906001016104ce565b509495945050505050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b828110156106dd577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0888603018452815160a0860167ffffffffffffffff8083511688528883015160a08a8a015282815180855260c08b01915060c08160051b8c010194508b8301925060005b81811015610686577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff408c87030183528351805180518852868f820151168f890152866040820151166040890152866060820151166060890152866080820151166080890152508d81015161014060a08901526106096101408901826102f3565b9050604082015188820360c08a015261062282826102f3565b915050606082015161064c60e08a018273ffffffffffffffffffffffffffffffffffffffff169052565b50608082015161010089015260a08201519150878103610120890152610672818361033d565b97505050928c0192918c0191600101610589565b5050505050604082015187820360408901526106a282826103ff565b915050606082015187820360608901526106bc82826104b9565b6080938401519890930197909752509450928501929085019060010161051c565b5092979650505050505050565b60008151808452602080850194506020840160005b838110156104ea578151805167ffffffffffffffff1688528301517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1683880152604090960195908201906001016106ff565b600081518084526020808501945080840160005b838110156104ea578151805167ffffffffffffffff90811689528482015180518216868b0152850151166040808a01919091520151606088015260809096019590820190600101610762565b6000602080835283516040808386015260a0850182516040606088015281815180845260c0890191508683019350600092505b8083101561083e578351805173ffffffffffffffffffffffffffffffffffffffff1683528701517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16878301529286019260019290920191908401906107e1565b50938501518785037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa00160808901529361087881866106ea565b9450505050508185015191507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08482030160408501526108b8818361074e565b95945050505050565b600067ffffffffffffffff8211156108db576108db6100d6565b5060051b60200190565b805167ffffffffffffffff811681146108fd57600080fd5b919050565b600060a0828403121561091457600080fd5b61091c610105565b90508151815261092e602083016108e5565b602082015261093f604083016108e5565b6040820152610950606083016108e5565b6060820152610961608083016108e5565b608082015292915050565b600082601f83011261097d57600080fd5b815161098b61029782610209565b8181528460208386010111156109a057600080fd5b6109b18260208301602087016102cf565b949350505050565b805173ffffffffffffffffffffffffffffffffffffffff811681146108fd57600080fd5b600082601f8301126109ee57600080fd5b815160206109fe610297836108c1565b82815260059290921b84018101918181019086841115610a1d57600080fd5b8286015b84811015610b1157805167ffffffffffffffff80821115610a425760008081fd5b81890191506080807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848d03011215610a7b5760008081fd5b610a8361012e565b8784015183811115610a955760008081fd5b610aa38d8a8388010161096c565b82525060408085015184811115610aba5760008081fd5b610ac88e8b8389010161096c565b8a8401525060608086015185811115610ae15760008081fd5b610aef8f8c838a010161096c565b9284019290925294909201519381019390935250508352918301918301610a21565b509695505050505050565b600082601f830112610b2d57600080fd5b81516020610b3d610297836108c1565b82815260059290921b84018101918181019086841115610b5c57600080fd5b8286015b84811015610b1157805167ffffffffffffffff80821115610b815760008081fd5b8189019150610140807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848d03011215610bbb5760008081fd5b610bc3610151565b610bcf8c898601610902565b815260c084015183811115610be45760008081fd5b610bf28d8a8388010161096c565b898301525060e084015183811115610c0a5760008081fd5b610c188d8a8388010161096c565b604083015250610c2b61010085016109b9565b60608201526101208401516080820152908301519082821115610c4e5760008081fd5b610c5c8c89848701016109dd565b60a08201528652505050918301918301610b60565b600082601f830112610c8257600080fd5b81516020610c92610297836108c1565b82815260059290921b84018101918181019086841115610cb157600080fd5b8286015b84811015610b1157805167ffffffffffffffff80821115610cd557600080fd5b818901915089603f830112610ce957600080fd5b85820151610cf9610297826108c1565b81815260059190911b830160400190878101908c831115610d1957600080fd5b604085015b83811015610d5257805185811115610d3557600080fd5b610d448f6040838a010161096c565b845250918901918901610d1e565b50875250505092840192508301610cb5565b600082601f830112610d7557600080fd5b81516020610d85610297836108c1565b8083825260208201915060208460051b870101935086841115610da757600080fd5b602086015b84811015610b115780518352918301918301610dac565b60006020808385031215610dd657600080fd5b825167ffffffffffffffff80821115610dee57600080fd5b818501915085601f830112610e0257600080fd5b8151610e10610297826108c1565b81815260059190911b83018401908481019088831115610e2f57600080fd5b8585015b83811015610f2957805185811115610e4a57600080fd5b860160a0818c037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0011215610e7f5760008081fd5b610e87610105565b610e928983016108e5565b815260408083015188811115610ea85760008081fd5b610eb68e8c83870101610b1c565b8b8401525060608084015189811115610ecf5760008081fd5b610edd8f8d83880101610c71565b8385015250608091508184015189811115610ef85760008081fd5b610f068f8d83880101610d64565b918401919091525060a09290920151918101919091528352918601918601610e33565b5098975050505050505050565b80517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811681146108fd57600080fd5b600082601f830112610f7357600080fd5b81516020610f83610297836108c1565b82815260069290921b84018101918181019086841115610fa257600080fd5b8286015b84811015610b115760408189031215610fbf5760008081fd5b610fc7610174565b610fd0826108e5565b8152610fdd858301610f36565b81860152835291830191604001610fa6565b600082601f83011261100057600080fd5b81516020611010610297836108c1565b82815260079290921b8401810191818101908684111561102f57600080fd5b8286015b84811015610b1157808803608081121561104d5760008081fd5b611055610197565b61105e836108e5565b81526040807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0840112156110925760008081fd5b61109a610174565b92506110a78785016108e5565b83526110b48185016108e5565b8388015281870192909252606083015191810191909152835291830191608001611033565b600060208083850312156110ec57600080fd5b825167ffffffffffffffff8082111561110457600080fd5b8185019150604080838803121561111a57600080fd5b611122610174565b83518381111561113157600080fd5b84016040818a03121561114357600080fd5b61114b610174565b81518581111561115a57600080fd5b8201601f81018b1361116b57600080fd5b8051611179610297826108c1565b81815260069190911b8201890190898101908d83111561119857600080fd5b928a01925b828410156111e65787848f0312156111b55760008081fd5b6111bd610174565b6111c6856109b9565b81526111d38c8601610f36565b818d0152825292870192908a019061119d565b8452505050818701519350848411156111fe57600080fd5b61120a8a858401610f62565b818801528252508385015191508282111561122457600080fd5b61123088838601610fef565b8582015280955050505050509291505056fea164736f6c6343000818000a", + ABI: "[{\"anonymous\":false,\"inputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"internalType\":\"structOffRamp.Interval\",\"name\":\"interval\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structOffRamp.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"report\",\"type\":\"tuple\"}],\"name\":\"CommitReportDecoded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage[]\",\"name\":\"messages\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[][]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[][]\"},{\"internalType\":\"bytes32[]\",\"name\":\"proofs\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"proofFlagBits\",\"type\":\"uint256\"}],\"indexed\":false,\"internalType\":\"structInternal.ExecutionReportSingleChain[]\",\"name\":\"report\",\"type\":\"tuple[]\"}],\"name\":\"ExecuteReportDecoded\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"decodeCommitReport\",\"outputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"internalType\":\"structOffRamp.Interval\",\"name\":\"interval\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structOffRamp.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"}],\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"decodeExecuteReport\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage[]\",\"name\":\"messages\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[][]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[][]\"},{\"internalType\":\"bytes32[]\",\"name\":\"proofs\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"proofFlagBits\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.ExecutionReportSingleChain[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]", + Bin: "0x608060405234801561001057600080fd5b5061126d806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80636fb349561461003b578063f816ec6014610064575b600080fd5b61004e61004936600461022c565b610084565b60405161005b91906104ed565b60405180910390f35b61007761007236600461022c565b6100a0565b60405161005b91906107a6565b60608180602001905181019061009a9190610de1565b92915050565b604080516080810182526060918101828152828201839052815260208101919091528180602001905181019061009a91906110f7565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff81118282101715610128576101286100d6565b60405290565b60405160c0810167ffffffffffffffff81118282101715610128576101286100d6565b6040805190810167ffffffffffffffff81118282101715610128576101286100d6565b6040516060810167ffffffffffffffff81118282101715610128576101286100d6565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156101de576101de6100d6565b604052919050565b600067ffffffffffffffff821115610200576102006100d6565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b60006020828403121561023e57600080fd5b813567ffffffffffffffff81111561025557600080fd5b8201601f8101841361026657600080fd5b8035610279610274826101e6565b610197565b81815285602083850101111561028e57600080fd5b81602084016020830137600091810160200191909152949350505050565b60005b838110156102c75781810151838201526020016102af565b50506000910152565b600081518084526102e88160208601602086016102ac565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b600082825180855260208086019550808260051b84010181860160005b848110156103ea577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018952815160a0815181865261037b828701826102d0565b915050858201518582038787015261039382826102d0565b915050604080830151868303828801526103ad83826102d0565b925050506060808301518187015250608080830151925085820381870152506103d681836102d0565b9a86019a9450505090830190600101610337565b5090979650505050505050565b6000828251808552602080860195506005818360051b8501018287016000805b868110156104a2577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe088850381018c5283518051808752908801908887019080891b88018a01865b8281101561048b57858a83030184526104798286516102d0565b948c0194938c0193915060010161045f565b509e8a019e97505050938701935050600101610417565b50919998505050505050505050565b60008151808452602080850194506020840160005b838110156104e2578151875295820195908201906001016104c6565b509495945050505050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b828110156106d5577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0888603018452815160a0860167ffffffffffffffff8083511688528883015160a08a8a015282815180855260c08b01915060c08160051b8c010194508b8301925060005b8181101561067e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff408c87030183528351805180518852868f820151168f890152866040820151166040890152866060820151166060890152866080820151166080890152508d81015161014060a08901526106016101408901826102d0565b9050604082015188820360c08a015261061a82826102d0565b915050606082015161064460e08a018273ffffffffffffffffffffffffffffffffffffffff169052565b50608082015161010089015260a0820151915087810361012089015261066a818361031a565b97505050928c0192918c0191600101610581565b50505050506040820151878203604089015261069a82826103f7565b915050606082015187820360608901526106b482826104b1565b60809384015198909301979097525094509285019290850190600101610514565b5092979650505050505050565b60008151808452602080850194506020840160005b838110156104e2578151805167ffffffffffffffff1688528301517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1683880152604090960195908201906001016106f7565b600081518084526020808501945080840160005b838110156104e2578151805167ffffffffffffffff90811689528482015180518216868b0152850151166040808a0191909152015160608801526080909601959082019060010161075a565b6000602080835283516040808386015260a0850182516040606088015281815180845260c0890191508683019350600092505b80831015610836578351805173ffffffffffffffffffffffffffffffffffffffff1683528701517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16878301529286019260019290920191908401906107d9565b50938501518785037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa00160808901529361087081866106e2565b9450505050508185015191507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08482030160408501526108b08183610746565b95945050505050565b600067ffffffffffffffff8211156108d3576108d36100d6565b5060051b60200190565b805167ffffffffffffffff811681146108f557600080fd5b919050565b600060a0828403121561090c57600080fd5b610914610105565b905081518152610926602083016108dd565b6020820152610937604083016108dd565b6040820152610948606083016108dd565b6060820152610959608083016108dd565b608082015292915050565b600082601f83011261097557600080fd5b8151610983610274826101e6565b81815284602083860101111561099857600080fd5b6109a98260208301602087016102ac565b949350505050565b805173ffffffffffffffffffffffffffffffffffffffff811681146108f557600080fd5b600082601f8301126109e657600080fd5b815160206109f6610274836108b9565b82815260059290921b84018101918181019086841115610a1557600080fd5b8286015b84811015610b2f57805167ffffffffffffffff80821115610a3a5760008081fd5b818901915060a0807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848d03011215610a735760008081fd5b610a7b610105565b8784015183811115610a8d5760008081fd5b610a9b8d8a83880101610964565b82525060408085015184811115610ab25760008081fd5b610ac08e8b83890101610964565b8a8401525060608086015185811115610ad95760008081fd5b610ae78f8c838a0101610964565b83850152506080915081860151818401525082850151925083831115610b0d5760008081fd5b610b1b8d8a85880101610964565b908201528652505050918301918301610a19565b509695505050505050565b600082601f830112610b4b57600080fd5b81516020610b5b610274836108b9565b82815260059290921b84018101918181019086841115610b7a57600080fd5b8286015b84811015610b2f57805167ffffffffffffffff80821115610b9f5760008081fd5b8189019150610140807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848d03011215610bd95760008081fd5b610be161012e565b610bed8c8986016108fa565b815260c084015183811115610c025760008081fd5b610c108d8a83880101610964565b898301525060e084015183811115610c285760008081fd5b610c368d8a83880101610964565b604083015250610c4961010085016109b1565b60608201526101208401516080820152908301519082821115610c6c5760008081fd5b610c7a8c89848701016109d5565b60a08201528652505050918301918301610b7e565b600082601f830112610ca057600080fd5b81516020610cb0610274836108b9565b82815260059290921b84018101918181019086841115610ccf57600080fd5b8286015b84811015610b2f57805167ffffffffffffffff80821115610cf357600080fd5b818901915089603f830112610d0757600080fd5b85820151610d17610274826108b9565b81815260059190911b830160400190878101908c831115610d3757600080fd5b604085015b83811015610d7057805185811115610d5357600080fd5b610d628f6040838a0101610964565b845250918901918901610d3c565b50875250505092840192508301610cd3565b600082601f830112610d9357600080fd5b81516020610da3610274836108b9565b8083825260208201915060208460051b870101935086841115610dc557600080fd5b602086015b84811015610b2f5780518352918301918301610dca565b60006020808385031215610df457600080fd5b825167ffffffffffffffff80821115610e0c57600080fd5b818501915085601f830112610e2057600080fd5b8151610e2e610274826108b9565b81815260059190911b83018401908481019088831115610e4d57600080fd5b8585015b83811015610f4757805185811115610e6857600080fd5b860160a0818c037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0011215610e9d5760008081fd5b610ea5610105565b610eb08983016108dd565b815260408083015188811115610ec65760008081fd5b610ed48e8c83870101610b3a565b8b8401525060608084015189811115610eed5760008081fd5b610efb8f8d83880101610c8f565b8385015250608091508184015189811115610f165760008081fd5b610f248f8d83880101610d82565b918401919091525060a09290920151918101919091528352918601918601610e51565b5098975050505050505050565b80517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811681146108f557600080fd5b600082601f830112610f9157600080fd5b81516020610fa1610274836108b9565b82815260069290921b84018101918181019086841115610fc057600080fd5b8286015b84811015610b2f5760408189031215610fdd5760008081fd5b610fe5610151565b610fee826108dd565b8152610ffb858301610f54565b81860152835291830191604001610fc4565b600082601f83011261101e57600080fd5b8151602061102e610274836108b9565b82815260079290921b8401810191818101908684111561104d57600080fd5b8286015b84811015610b2f57808803608081121561106b5760008081fd5b611073610174565b61107c836108dd565b81526040807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0840112156110b05760008081fd5b6110b8610151565b92506110c58785016108dd565b83526110d28185016108dd565b8388015281870192909252606083015191810191909152835291830191608001611051565b6000602080838503121561110a57600080fd5b825167ffffffffffffffff8082111561112257600080fd5b8185019150604080838803121561113857600080fd5b611140610151565b83518381111561114f57600080fd5b84016040818a03121561116157600080fd5b611169610151565b81518581111561117857600080fd5b8201601f81018b1361118957600080fd5b8051611197610274826108b9565b81815260069190911b8201890190898101908d8311156111b657600080fd5b928a01925b828410156112045787848f0312156111d35760008081fd5b6111db610151565b6111e4856109b1565b81526111f18c8601610f54565b818d0152825292870192908a01906111bb565b84525050508187015193508484111561121c57600080fd5b6112288a858401610f80565b818801528252508385015191508282111561124257600080fd5b61124e8883860161100d565b8582015280955050505050509291505056fea164736f6c6343000818000a", } var ReportCodecABI = ReportCodecMetaData.ABI @@ -529,7 +530,7 @@ func (ReportCodecCommitReportDecoded) Topic() common.Hash { } func (ReportCodecExecuteReportDecoded) Topic() common.Hash { - return common.HexToHash("0x7f4f1032eaaa1f5c3fc02d56071d69a09a2595d9a5fa4704f0eb298792908abb") + return common.HexToHash("0x70d042e9d8463eeac7e835e7172c08846ad327fc4eb6fc89f3bb5226e17ad618") } func (_ReportCodec *ReportCodec) Address() common.Address { diff --git a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt index 16dc444b43..4ebdb09e02 100644 --- a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -5,7 +5,7 @@ burn_mint_token_pool_and_proxy: ../../../contracts/solc/v0.8.24/BurnMintTokenPoo burn_with_from_mint_token_pool: ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.abi ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.bin 6333d0314d0bd29e75ea5e05fe62a4516ade0c6db91c30b6f93645035db52ed8 burn_with_from_mint_token_pool_and_proxy: ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPoolAndProxy/BurnWithFromMintTokenPoolAndProxy.abi ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPoolAndProxy/BurnWithFromMintTokenPoolAndProxy.bin 08ed1235dda921ce8841b26aa18d0c0f36db4884779dd7670857159801b6d597 ccip_config: ../../../contracts/solc/v0.8.24/CCIPConfig/CCIPConfig.abi ../../../contracts/solc/v0.8.24/CCIPConfig/CCIPConfig.bin 213d4adc8634671aea16fb4207989375b1aac919b04d608f4767c29592affbf5 -ccip_reader_tester: ../../../contracts/solc/v0.8.24/CCIPReaderTester/CCIPReaderTester.abi ../../../contracts/solc/v0.8.24/CCIPReaderTester/CCIPReaderTester.bin a5b0275dcf502f73d72f6bc53bff774e25fcca01a74cc019536bdee6a42ac655 +ccip_reader_tester: ../../../contracts/solc/v0.8.24/CCIPReaderTester/CCIPReaderTester.abi ../../../contracts/solc/v0.8.24/CCIPReaderTester/CCIPReaderTester.bin 459ae9c785343bd032856baaacdfc8bf4f6b0d9f5d9082e1580b5846c2be80e5 commit_store: ../../../contracts/solc/v0.8.24/CommitStore/CommitStore.abi ../../../contracts/solc/v0.8.24/CommitStore/CommitStore.bin 274d87db70b643e00ab0a7e7845bb4b791f3b613bfc87708d33fc5a8369e2a41 commit_store_helper: ../../../contracts/solc/v0.8.24/CommitStoreHelper/CommitStoreHelper.abi ../../../contracts/solc/v0.8.24/CommitStoreHelper/CommitStoreHelper.bin f7128dcc2ee6dbcbc976288abcc16970ffb19b59412c5202ef6b259d2007f801 ether_sender_receiver: ../../../contracts/solc/v0.8.24/EtherSenderReceiver/EtherSenderReceiver.abi ../../../contracts/solc/v0.8.24/EtherSenderReceiver/EtherSenderReceiver.bin 09510a3f773f108a3c231e8d202835c845ded862d071ec54c4f89c12d868b8de @@ -14,7 +14,7 @@ evm_2_evm_onramp: ../../../contracts/solc/v0.8.24/EVM2EVMOnRamp/EVM2EVMOnRamp.ab lock_release_token_pool: ../../../contracts/solc/v0.8.24/LockReleaseTokenPool/LockReleaseTokenPool.abi ../../../contracts/solc/v0.8.24/LockReleaseTokenPool/LockReleaseTokenPool.bin e6a8ec9e8faccb1da7d90e0f702ed72975964f97dc3222b54cfcca0a0ba3fea2 lock_release_token_pool_and_proxy: ../../../contracts/solc/v0.8.24/LockReleaseTokenPoolAndProxy/LockReleaseTokenPoolAndProxy.abi ../../../contracts/solc/v0.8.24/LockReleaseTokenPoolAndProxy/LockReleaseTokenPoolAndProxy.bin e632b08be0fbd1d013e8b3a9d75293d0d532b83071c531ff2be1deec1fa48ec1 maybe_revert_message_receiver: ../../../contracts/solc/v0.8.24/MaybeRevertMessageReceiver/MaybeRevertMessageReceiver.abi ../../../contracts/solc/v0.8.24/MaybeRevertMessageReceiver/MaybeRevertMessageReceiver.bin d73956c26232ebcc4a5444429fa99cbefed960e323be9b5a24925885c2e477d5 -message_hasher: ../../../contracts/solc/v0.8.24/MessageHasher/MessageHasher.abi ../../../contracts/solc/v0.8.24/MessageHasher/MessageHasher.bin 1d5146d43e1b99cd2d6f9f06475be19087e4349f7cee0fdbbf134ba65e967c93 +message_hasher: ../../../contracts/solc/v0.8.24/MessageHasher/MessageHasher.abi ../../../contracts/solc/v0.8.24/MessageHasher/MessageHasher.bin 5712fbc30cf826c0cf38c68f54f744741b553d98c60e66696b7a845778cb2b3d mock_usdc_token_messenger: ../../../contracts/solc/v0.8.24/MockE2EUSDCTokenMessenger/MockE2EUSDCTokenMessenger.abi ../../../contracts/solc/v0.8.24/MockE2EUSDCTokenMessenger/MockE2EUSDCTokenMessenger.bin d976651d36b33ac2196b32b9d2f4fa6690c6a18d41b621365659fce1c1d1e737 mock_usdc_token_transmitter: ../../../contracts/solc/v0.8.24/MockE2EUSDCTransmitter/MockE2EUSDCTransmitter.abi ../../../contracts/solc/v0.8.24/MockE2EUSDCTransmitter/MockE2EUSDCTransmitter.bin be0dbc3e475741ea0b7a54ec2b935a321b428baa9f4ce18180a87fb38bb87de2 mock_v3_aggregator_contract: ../../../contracts/solc/v0.8.24/MockV3Aggregator/MockV3Aggregator.abi ../../../contracts/solc/v0.8.24/MockV3Aggregator/MockV3Aggregator.bin 518e19efa2ff52b0fefd8e597b05765317ee7638189bfe34ca43de2f6599faf4 @@ -22,12 +22,12 @@ multi_aggregate_rate_limiter: ../../../contracts/solc/v0.8.24/MultiAggregateRate multi_ocr3_helper: ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Helper.abi ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Helper.bin aa299e0c2659d53aad4eace4d66be0e734b1366008593669cf30361ff529da6a nonce_manager: ../../../contracts/solc/v0.8.24/NonceManager/NonceManager.abi ../../../contracts/solc/v0.8.24/NonceManager/NonceManager.bin 6f64e1083b356c06ee66b9138e398b9c97a4cd3e8c9ec38cf3010cebc79af536 ocr3_config_encoder: ../../../contracts/solc/v0.8.24/IOCR3ConfigEncoder/IOCR3ConfigEncoder.abi ../../../contracts/solc/v0.8.24/IOCR3ConfigEncoder/IOCR3ConfigEncoder.bin e21180898e1ad54a045ee20add85a2793c681425ea06f66d1a9e5cab128b6487 -offramp: ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.abi ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.bin 76ec9676116368ab7c7c7ed45191698a12e4d975633caea32d821a1125633589 -onramp: ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.abi ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.bin 123e949bc9607289382534c4432ecebe5b1da5ca92c1c6c8cc6b9be56c3352c6 +offramp: ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.abi ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.bin e47ad9f887ace1741af3147cbd82c89e10deb3c68d8ffcd7fcbca33dc017e35a +onramp: ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.abi ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.bin 5b00bebfbf22003a13a2bce78e35c90869ca1dc2ebd3febd9bdf8151d8fa11e0 ping_pong_demo: ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.abi ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.bin c1c2f8a65c7ffd971899cae7fe62f2da57d09e936151e2b92163c4bebe699d6b -price_registry: ../../../contracts/solc/v0.8.24/PriceRegistry/PriceRegistry.abi ../../../contracts/solc/v0.8.24/PriceRegistry/PriceRegistry.bin 8931609776700a2a8121c9fdd757dbf9207d8b97583e70c84ec2d88c839d4a30 +price_registry: ../../../contracts/solc/v0.8.24/PriceRegistry/PriceRegistry.abi ../../../contracts/solc/v0.8.24/PriceRegistry/PriceRegistry.bin e7781d600c1bb7aa4620106af7f6e146a109b97f4cb6a7d06c9e15773340ecb2 registry_module_owner_custom: ../../../contracts/solc/v0.8.24/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.abi ../../../contracts/solc/v0.8.24/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.bin 75be86323c227917a9bbc3f799d7ed02f92db546653a36db30ed0ebe64461353 -report_codec: ../../../contracts/solc/v0.8.24/ReportCodec/ReportCodec.abi ../../../contracts/solc/v0.8.24/ReportCodec/ReportCodec.bin 20292ddaba15096fe8060567cf56cda673b947df27241d0c49d2debc838feb24 +report_codec: ../../../contracts/solc/v0.8.24/ReportCodec/ReportCodec.abi ../../../contracts/solc/v0.8.24/ReportCodec/ReportCodec.bin 3d7ebd8d4563b63cec83b141fe9f9ef5d8ab12a7c23ccd5e7e3434aba3cab66a rmn_contract: ../../../contracts/solc/v0.8.24/RMN/RMN.abi ../../../contracts/solc/v0.8.24/RMN/RMN.bin 8b45b0fb08631c6b582fd3c0b4052a79cc2b4e091e6286af1ab131bef63661f9 rmn_proxy_contract: ../../../contracts/solc/v0.8.24/ARMProxy/ARMProxy.abi ../../../contracts/solc/v0.8.24/ARMProxy/ARMProxy.bin b048d8e752e3c41113ebb305c1efa06737ad36b4907b93e627fb0a3113023454 router: ../../../contracts/solc/v0.8.24/Router/Router.abi ../../../contracts/solc/v0.8.24/Router/Router.bin 2e4f0a7826c8abb49d882bb49fc5ff20a186dbd3137624b9097ffed903ae4888 diff --git a/core/gethwrappers/ccip/mocks/price_registry_interface.go b/core/gethwrappers/ccip/mocks/price_registry_interface.go index 01d435d05a..04104ce835 100644 --- a/core/gethwrappers/ccip/mocks/price_registry_interface.go +++ b/core/gethwrappers/ccip/mocks/price_registry_interface.go @@ -3239,6 +3239,67 @@ func (_c *PriceRegistryInterface_ProcessMessageArgs_Call) RunAndReturn(run func( return _c } +// ProcessPoolReturnData provides a mock function with given fields: opts, destChainSelector, rampTokenAmounts, sourceTokenAmounts +func (_m *PriceRegistryInterface) ProcessPoolReturnData(opts *bind.CallOpts, destChainSelector uint64, rampTokenAmounts []price_registry.InternalRampTokenAmount, sourceTokenAmounts []price_registry.ClientEVMTokenAmount) ([][]byte, error) { + ret := _m.Called(opts, destChainSelector, rampTokenAmounts, sourceTokenAmounts) + + if len(ret) == 0 { + panic("no return value specified for ProcessPoolReturnData") + } + + var r0 [][]byte + var r1 error + if rf, ok := ret.Get(0).(func(*bind.CallOpts, uint64, []price_registry.InternalRampTokenAmount, []price_registry.ClientEVMTokenAmount) ([][]byte, error)); ok { + return rf(opts, destChainSelector, rampTokenAmounts, sourceTokenAmounts) + } + if rf, ok := ret.Get(0).(func(*bind.CallOpts, uint64, []price_registry.InternalRampTokenAmount, []price_registry.ClientEVMTokenAmount) [][]byte); ok { + r0 = rf(opts, destChainSelector, rampTokenAmounts, sourceTokenAmounts) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([][]byte) + } + } + + if rf, ok := ret.Get(1).(func(*bind.CallOpts, uint64, []price_registry.InternalRampTokenAmount, []price_registry.ClientEVMTokenAmount) error); ok { + r1 = rf(opts, destChainSelector, rampTokenAmounts, sourceTokenAmounts) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// PriceRegistryInterface_ProcessPoolReturnData_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ProcessPoolReturnData' +type PriceRegistryInterface_ProcessPoolReturnData_Call struct { + *mock.Call +} + +// ProcessPoolReturnData is a helper method to define mock.On call +// - opts *bind.CallOpts +// - destChainSelector uint64 +// - rampTokenAmounts []price_registry.InternalRampTokenAmount +// - sourceTokenAmounts []price_registry.ClientEVMTokenAmount +func (_e *PriceRegistryInterface_Expecter) ProcessPoolReturnData(opts interface{}, destChainSelector interface{}, rampTokenAmounts interface{}, sourceTokenAmounts interface{}) *PriceRegistryInterface_ProcessPoolReturnData_Call { + return &PriceRegistryInterface_ProcessPoolReturnData_Call{Call: _e.mock.On("ProcessPoolReturnData", opts, destChainSelector, rampTokenAmounts, sourceTokenAmounts)} +} + +func (_c *PriceRegistryInterface_ProcessPoolReturnData_Call) Run(run func(opts *bind.CallOpts, destChainSelector uint64, rampTokenAmounts []price_registry.InternalRampTokenAmount, sourceTokenAmounts []price_registry.ClientEVMTokenAmount)) *PriceRegistryInterface_ProcessPoolReturnData_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.CallOpts), args[1].(uint64), args[2].([]price_registry.InternalRampTokenAmount), args[3].([]price_registry.ClientEVMTokenAmount)) + }) + return _c +} + +func (_c *PriceRegistryInterface_ProcessPoolReturnData_Call) Return(_a0 [][]byte, _a1 error) *PriceRegistryInterface_ProcessPoolReturnData_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *PriceRegistryInterface_ProcessPoolReturnData_Call) RunAndReturn(run func(*bind.CallOpts, uint64, []price_registry.InternalRampTokenAmount, []price_registry.ClientEVMTokenAmount) ([][]byte, error)) *PriceRegistryInterface_ProcessPoolReturnData_Call { + _c.Call.Return(run) + return _c +} + // SetReportPermissions provides a mock function with given fields: opts, permissions func (_m *PriceRegistryInterface) SetReportPermissions(opts *bind.TransactOpts, permissions []price_registry.KeystoneFeedsPermissionHandlerPermission) (*types.Transaction, error) { ret := _m.Called(opts, permissions) @@ -3531,55 +3592,6 @@ func (_c *PriceRegistryInterface_UpdateTokenPriceFeeds_Call) RunAndReturn(run fu return _c } -// ValidatePoolReturnData provides a mock function with given fields: opts, destChainSelector, rampTokenAmounts, sourceTokenAmounts -func (_m *PriceRegistryInterface) ValidatePoolReturnData(opts *bind.CallOpts, destChainSelector uint64, rampTokenAmounts []price_registry.InternalRampTokenAmount, sourceTokenAmounts []price_registry.ClientEVMTokenAmount) error { - ret := _m.Called(opts, destChainSelector, rampTokenAmounts, sourceTokenAmounts) - - if len(ret) == 0 { - panic("no return value specified for ValidatePoolReturnData") - } - - var r0 error - if rf, ok := ret.Get(0).(func(*bind.CallOpts, uint64, []price_registry.InternalRampTokenAmount, []price_registry.ClientEVMTokenAmount) error); ok { - r0 = rf(opts, destChainSelector, rampTokenAmounts, sourceTokenAmounts) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// PriceRegistryInterface_ValidatePoolReturnData_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ValidatePoolReturnData' -type PriceRegistryInterface_ValidatePoolReturnData_Call struct { - *mock.Call -} - -// ValidatePoolReturnData is a helper method to define mock.On call -// - opts *bind.CallOpts -// - destChainSelector uint64 -// - rampTokenAmounts []price_registry.InternalRampTokenAmount -// - sourceTokenAmounts []price_registry.ClientEVMTokenAmount -func (_e *PriceRegistryInterface_Expecter) ValidatePoolReturnData(opts interface{}, destChainSelector interface{}, rampTokenAmounts interface{}, sourceTokenAmounts interface{}) *PriceRegistryInterface_ValidatePoolReturnData_Call { - return &PriceRegistryInterface_ValidatePoolReturnData_Call{Call: _e.mock.On("ValidatePoolReturnData", opts, destChainSelector, rampTokenAmounts, sourceTokenAmounts)} -} - -func (_c *PriceRegistryInterface_ValidatePoolReturnData_Call) Run(run func(opts *bind.CallOpts, destChainSelector uint64, rampTokenAmounts []price_registry.InternalRampTokenAmount, sourceTokenAmounts []price_registry.ClientEVMTokenAmount)) *PriceRegistryInterface_ValidatePoolReturnData_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.CallOpts), args[1].(uint64), args[2].([]price_registry.InternalRampTokenAmount), args[3].([]price_registry.ClientEVMTokenAmount)) - }) - return _c -} - -func (_c *PriceRegistryInterface_ValidatePoolReturnData_Call) Return(_a0 error) *PriceRegistryInterface_ValidatePoolReturnData_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *PriceRegistryInterface_ValidatePoolReturnData_Call) RunAndReturn(run func(*bind.CallOpts, uint64, []price_registry.InternalRampTokenAmount, []price_registry.ClientEVMTokenAmount) error) *PriceRegistryInterface_ValidatePoolReturnData_Call { - _c.Call.Return(run) - return _c -} - // WatchAuthorizedCallerAdded provides a mock function with given fields: opts, sink func (_m *PriceRegistryInterface) WatchAuthorizedCallerAdded(opts *bind.WatchOpts, sink chan<- *price_registry.PriceRegistryAuthorizedCallerAdded) (event.Subscription, error) { ret := _m.Called(opts, sink) diff --git a/integration-tests/deployment/ccip/add_lane.go b/integration-tests/deployment/ccip/add_lane.go index c9d949cbe9..1f8dcd43f9 100644 --- a/integration-tests/deployment/ccip/add_lane.go +++ b/integration-tests/deployment/ccip/add_lane.go @@ -112,7 +112,6 @@ func defaultPriceRegistryDestChainConfig() price_registry.PriceRegistryDestChain DestGasPerDataAvailabilityByte: 100, DestDataAvailabilityMultiplierBps: 1, DefaultTokenDestGasOverhead: 125_000, - DefaultTokenDestBytesOverhead: 32, DefaultTxGasLimit: 200_000, GasMultiplierWeiPerEth: 1, NetworkFeeUSDCents: 1, From ca8fa56e87e662135f9233bc77da845520bdb813 Mon Sep 17 00:00:00 2001 From: Sishir Giri Date: Mon, 26 Aug 2024 09:51:45 -0700 Subject: [PATCH 029/115] Chore: Change metis config (#1345) ## Motivation ## Solution --- core/chains/evm/config/toml/defaults/Metis_Sepolia.toml | 2 +- docs/CONFIG.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/chains/evm/config/toml/defaults/Metis_Sepolia.toml b/core/chains/evm/config/toml/defaults/Metis_Sepolia.toml index 286b888e1a..4ff4056c75 100644 --- a/core/chains/evm/config/toml/defaults/Metis_Sepolia.toml +++ b/core/chains/evm/config/toml/defaults/Metis_Sepolia.toml @@ -1,5 +1,5 @@ ChainID = '59902' -ChainType = 'metis' +ChainType = 'optimismBedrock' FinalityDepth = 10 FinalityTagEnabled = true MinIncomingConfirmations = 1 diff --git a/docs/CONFIG.md b/docs/CONFIG.md index fdeb73484d..71ddf1c2c8 100644 --- a/docs/CONFIG.md +++ b/docs/CONFIG.md @@ -6666,7 +6666,7 @@ GasLimit = 5400000 AutoCreateKey = true BlockBackfillDepth = 10 BlockBackfillSkip = false -ChainType = 'metis' +ChainType = 'optimismBedrock' FinalityDepth = 10 FinalityTagEnabled = true LogBackfillBatchSize = 1000 From 629c2a4d8bf177bc46bf0a4324526a0f69a81a51 Mon Sep 17 00:00:00 2001 From: Peter Olds Date: Mon, 26 Aug 2024 16:40:22 -0700 Subject: [PATCH 030/115] feat: Add support for parsing deployed 1.0 contracts which have no TypeAndVersion (#1368) ## Motivation - 1.0.0 contracts have no TypeAndVersion however tooling validation expects a TypeAndVersion be set ## Solution - Return `Unknown 1.0.0` for contracts with an empty type and version string, implying that they are 1.0.0 deployed contracts --- .../plugins/ccip/config/type_and_version.go | 7 +++ .../ccip/config/type_and_version_test.go | 49 +++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 core/services/ocr2/plugins/ccip/config/type_and_version_test.go diff --git a/core/services/ocr2/plugins/ccip/config/type_and_version.go b/core/services/ocr2/plugins/ccip/config/type_and_version.go index fdfd892b08..00e3b26d4e 100644 --- a/core/services/ocr2/plugins/ccip/config/type_and_version.go +++ b/core/services/ocr2/plugins/ccip/config/type_and_version.go @@ -19,6 +19,7 @@ var ( EVM2EVMOffRamp ContractType = "EVM2EVMOffRamp" CommitStore ContractType = "CommitStore" PriceRegistry ContractType = "PriceRegistry" + Unknown ContractType = "Unknown" // 1.0.0 Contracts which have no TypeAndVersion ContractTypes = mapset.NewSet[ContractType]( EVM2EVMOffRamp, EVM2EVMOnRamp, @@ -63,7 +64,13 @@ func TypeAndVersion(addr common.Address, client bind.ContractBackend) (ContractT return ContractType(contractType), *v, nil } +// default version to use when TypeAndVersion is missing. +const defaultVersion = "1.0.0" + func ParseTypeAndVersion(tvStr string) (string, string, error) { + if tvStr == "" { + tvStr = string(Unknown) + " " + defaultVersion + } typeAndVersionValues := strings.Split(tvStr, " ") if len(typeAndVersionValues) < 2 { diff --git a/core/services/ocr2/plugins/ccip/config/type_and_version_test.go b/core/services/ocr2/plugins/ccip/config/type_and_version_test.go new file mode 100644 index 0000000000..f626389dcd --- /dev/null +++ b/core/services/ocr2/plugins/ccip/config/type_and_version_test.go @@ -0,0 +1,49 @@ +package config + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestParseTypeAndVersion(t *testing.T) { + tests := []struct { + name string + input string + expectedType string + expectedVersion string + expectedError string + }{ + { + name: "Valid input", + input: string(EVM2EVMOnRamp) + " 1.2.0", + expectedType: string(EVM2EVMOnRamp), + expectedVersion: "1.2.0", + }, + { + name: "Empty input", + input: "", + expectedType: string(Unknown), + expectedVersion: defaultVersion, + }, + { + name: "Invalid input", + input: "InvalidInput", + expectedError: "invalid type and version InvalidInput", + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + actualType, actualVersion, err := ParseTypeAndVersion(tc.input) + + if tc.expectedError != "" { + assert.EqualError(t, err, tc.expectedError) + } else { + assert.NoError(t, err) + assert.Equal(t, tc.expectedType, actualType) + assert.Equal(t, tc.expectedVersion, actualVersion) + } + }) + } +} From 0189bd0ec898f591781bfd6c0a903d07b4531527 Mon Sep 17 00:00:00 2001 From: dimitris Date: Tue, 27 Aug 2024 10:50:48 +0300 Subject: [PATCH 031/115] Bump chainlink-ccip to dev branch (#1365) Ref: https://github.com/smartcontractkit/chainlink-ccip/pull/78 --- core/capabilities/ccip/oraclecreator/inprocess.go | 2 +- core/scripts/go.mod | 2 +- core/scripts/go.sum | 4 ++-- go.mod | 2 +- go.sum | 4 ++-- integration-tests/go.mod | 2 +- integration-tests/go.sum | 4 ++-- integration-tests/load/go.mod | 2 +- integration-tests/load/go.sum | 4 ++-- 9 files changed, 13 insertions(+), 13 deletions(-) diff --git a/core/capabilities/ccip/oraclecreator/inprocess.go b/core/capabilities/ccip/oraclecreator/inprocess.go index d705367d57..21e9bcec6d 100644 --- a/core/capabilities/ccip/oraclecreator/inprocess.go +++ b/core/capabilities/ccip/oraclecreator/inprocess.go @@ -28,7 +28,7 @@ import ( cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3" - commitocr3 "github.com/smartcontractkit/chainlink-ccip/commitrmnocb" + commitocr3 "github.com/smartcontractkit/chainlink-ccip/commit" execocr3 "github.com/smartcontractkit/chainlink-ccip/execute" ccipreaderpkg "github.com/smartcontractkit/chainlink-ccip/pkg/reader" diff --git a/core/scripts/go.mod b/core/scripts/go.mod index 13ed1c4aa9..368cee79d9 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -274,7 +274,7 @@ require ( github.com/sethvargo/go-retry v0.2.4 // indirect github.com/shirou/gopsutil v3.21.11+incompatible // indirect github.com/shirou/gopsutil/v3 v3.24.3 // indirect - github.com/smartcontractkit/chainlink-ccip v0.0.0-20240816163757-48726fd8165f // indirect + github.com/smartcontractkit/chainlink-ccip v0.0.0-20240826120733-199eb5870f15 // indirect github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240710121324-3ed288aa9b45 // indirect github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240718160222-2dc0c8136bfa // indirect github.com/smartcontractkit/chainlink-feeds v0.0.0-20240710170203-5b41615da827 // indirect diff --git a/core/scripts/go.sum b/core/scripts/go.sum index 468c13a670..7e684e245d 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -1070,8 +1070,8 @@ github.com/smartcontractkit/chain-selectors v1.0.21 h1:KCR9SA7PhOexaBzFieHoLv1Wo github.com/smartcontractkit/chain-selectors v1.0.21/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/smartcontractkit/chainlink-automation v1.0.4 h1:iyW181JjKHLNMnDleI8umfIfVVlwC7+n5izbLSFgjw8= github.com/smartcontractkit/chainlink-automation v1.0.4/go.mod h1:u4NbPZKJ5XiayfKHD/v3z3iflQWqvtdhj13jVZXj/cM= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20240816163757-48726fd8165f h1:lQZBOjeYFpCdk0mGQUhbrJipd00tu49xK4zSijC/9Co= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20240816163757-48726fd8165f/go.mod h1:/ZWraCBaDDgaIN1prixYcbVvIk/6HeED9+8zbWQ+TMo= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20240826120733-199eb5870f15 h1:+Km1o8ApEv/DofxAa5MIPbkxXkKo4BG5u3GKLKB5FSI= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20240826120733-199eb5870f15/go.mod h1:Z9lQ5t20kRk28pzRLnqAJZUVOw8E6/siA3P3MLyKqoM= github.com/smartcontractkit/chainlink-common v0.2.1-0.20240717132349-ee5af9b79834 h1:pTf4xdcmiWBqWZ6rTy2RMTDBzhHk89VC1pM7jXKQztI= github.com/smartcontractkit/chainlink-common v0.2.1-0.20240717132349-ee5af9b79834/go.mod h1:fh9eBbrReCmv31bfz52ENCAMa7nTKQbdhb2B3+S2VGo= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240710121324-3ed288aa9b45 h1:NBQLtqk8zsyY4qTJs+NElI3aDFTcAo83JHvqD04EvB0= diff --git a/go.mod b/go.mod index 683793cb53..8a75274125 100644 --- a/go.mod +++ b/go.mod @@ -74,7 +74,7 @@ require ( github.com/shopspring/decimal v1.4.0 github.com/smartcontractkit/chain-selectors v1.0.21 github.com/smartcontractkit/chainlink-automation v1.0.4 - github.com/smartcontractkit/chainlink-ccip v0.0.0-20240816163757-48726fd8165f + github.com/smartcontractkit/chainlink-ccip v0.0.0-20240826120733-199eb5870f15 github.com/smartcontractkit/chainlink-common v0.2.1-0.20240717132349-ee5af9b79834 github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240710121324-3ed288aa9b45 github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240718160222-2dc0c8136bfa diff --git a/go.sum b/go.sum index 5ad6772ecd..d25f3d297a 100644 --- a/go.sum +++ b/go.sum @@ -1027,8 +1027,8 @@ github.com/smartcontractkit/chain-selectors v1.0.21 h1:KCR9SA7PhOexaBzFieHoLv1Wo github.com/smartcontractkit/chain-selectors v1.0.21/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/smartcontractkit/chainlink-automation v1.0.4 h1:iyW181JjKHLNMnDleI8umfIfVVlwC7+n5izbLSFgjw8= github.com/smartcontractkit/chainlink-automation v1.0.4/go.mod h1:u4NbPZKJ5XiayfKHD/v3z3iflQWqvtdhj13jVZXj/cM= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20240816163757-48726fd8165f h1:lQZBOjeYFpCdk0mGQUhbrJipd00tu49xK4zSijC/9Co= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20240816163757-48726fd8165f/go.mod h1:/ZWraCBaDDgaIN1prixYcbVvIk/6HeED9+8zbWQ+TMo= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20240826120733-199eb5870f15 h1:+Km1o8ApEv/DofxAa5MIPbkxXkKo4BG5u3GKLKB5FSI= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20240826120733-199eb5870f15/go.mod h1:Z9lQ5t20kRk28pzRLnqAJZUVOw8E6/siA3P3MLyKqoM= github.com/smartcontractkit/chainlink-common v0.2.1-0.20240717132349-ee5af9b79834 h1:pTf4xdcmiWBqWZ6rTy2RMTDBzhHk89VC1pM7jXKQztI= github.com/smartcontractkit/chainlink-common v0.2.1-0.20240717132349-ee5af9b79834/go.mod h1:fh9eBbrReCmv31bfz52ENCAMa7nTKQbdhb2B3+S2VGo= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240710121324-3ed288aa9b45 h1:NBQLtqk8zsyY4qTJs+NElI3aDFTcAo83JHvqD04EvB0= diff --git a/integration-tests/go.mod b/integration-tests/go.mod index 3c1386cb30..12773a0b93 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -36,7 +36,7 @@ require ( github.com/smartcontractkit/ccip-owner-contracts v0.0.0-20240808195812-ae0378684685 github.com/smartcontractkit/chain-selectors v1.0.21 github.com/smartcontractkit/chainlink-automation v1.0.4 - github.com/smartcontractkit/chainlink-ccip v0.0.0-20240816163757-48726fd8165f + github.com/smartcontractkit/chainlink-ccip v0.0.0-20240826120733-199eb5870f15 github.com/smartcontractkit/chainlink-common v0.2.1-0.20240717132349-ee5af9b79834 github.com/smartcontractkit/chainlink-testing-framework v1.34.5 github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240405215812-5a72bc9af239 diff --git a/integration-tests/go.sum b/integration-tests/go.sum index 4d324d1033..31fc2ff399 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1396,8 +1396,8 @@ github.com/smartcontractkit/chain-selectors v1.0.21 h1:KCR9SA7PhOexaBzFieHoLv1Wo github.com/smartcontractkit/chain-selectors v1.0.21/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/smartcontractkit/chainlink-automation v1.0.4 h1:iyW181JjKHLNMnDleI8umfIfVVlwC7+n5izbLSFgjw8= github.com/smartcontractkit/chainlink-automation v1.0.4/go.mod h1:u4NbPZKJ5XiayfKHD/v3z3iflQWqvtdhj13jVZXj/cM= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20240816163757-48726fd8165f h1:lQZBOjeYFpCdk0mGQUhbrJipd00tu49xK4zSijC/9Co= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20240816163757-48726fd8165f/go.mod h1:/ZWraCBaDDgaIN1prixYcbVvIk/6HeED9+8zbWQ+TMo= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20240826120733-199eb5870f15 h1:+Km1o8ApEv/DofxAa5MIPbkxXkKo4BG5u3GKLKB5FSI= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20240826120733-199eb5870f15/go.mod h1:Z9lQ5t20kRk28pzRLnqAJZUVOw8E6/siA3P3MLyKqoM= github.com/smartcontractkit/chainlink-common v0.2.1-0.20240717132349-ee5af9b79834 h1:pTf4xdcmiWBqWZ6rTy2RMTDBzhHk89VC1pM7jXKQztI= github.com/smartcontractkit/chainlink-common v0.2.1-0.20240717132349-ee5af9b79834/go.mod h1:fh9eBbrReCmv31bfz52ENCAMa7nTKQbdhb2B3+S2VGo= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240710121324-3ed288aa9b45 h1:NBQLtqk8zsyY4qTJs+NElI3aDFTcAo83JHvqD04EvB0= diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index fc44d83aa5..dca0d80503 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -42,7 +42,7 @@ require ( github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect - github.com/smartcontractkit/chainlink-ccip v0.0.0-20240816163757-48726fd8165f // indirect + github.com/smartcontractkit/chainlink-ccip v0.0.0-20240826120733-199eb5870f15 // indirect github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240710121324-3ed288aa9b45 // indirect github.com/testcontainers/testcontainers-go v0.28.0 // indirect k8s.io/apimachinery v0.30.2 // indirect diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index 2c340a73d1..487769fb46 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -1360,8 +1360,8 @@ github.com/smartcontractkit/chain-selectors v1.0.21 h1:KCR9SA7PhOexaBzFieHoLv1Wo github.com/smartcontractkit/chain-selectors v1.0.21/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/smartcontractkit/chainlink-automation v1.0.4 h1:iyW181JjKHLNMnDleI8umfIfVVlwC7+n5izbLSFgjw8= github.com/smartcontractkit/chainlink-automation v1.0.4/go.mod h1:u4NbPZKJ5XiayfKHD/v3z3iflQWqvtdhj13jVZXj/cM= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20240816163757-48726fd8165f h1:lQZBOjeYFpCdk0mGQUhbrJipd00tu49xK4zSijC/9Co= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20240816163757-48726fd8165f/go.mod h1:/ZWraCBaDDgaIN1prixYcbVvIk/6HeED9+8zbWQ+TMo= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20240826120733-199eb5870f15 h1:+Km1o8ApEv/DofxAa5MIPbkxXkKo4BG5u3GKLKB5FSI= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20240826120733-199eb5870f15/go.mod h1:Z9lQ5t20kRk28pzRLnqAJZUVOw8E6/siA3P3MLyKqoM= github.com/smartcontractkit/chainlink-common v0.2.1-0.20240717132349-ee5af9b79834 h1:pTf4xdcmiWBqWZ6rTy2RMTDBzhHk89VC1pM7jXKQztI= github.com/smartcontractkit/chainlink-common v0.2.1-0.20240717132349-ee5af9b79834/go.mod h1:fh9eBbrReCmv31bfz52ENCAMa7nTKQbdhb2B3+S2VGo= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240710121324-3ed288aa9b45 h1:NBQLtqk8zsyY4qTJs+NElI3aDFTcAo83JHvqD04EvB0= From ad43c21382f285fe6b205b1d14c617f16c6f9fb1 Mon Sep 17 00:00:00 2001 From: dimitris Date: Tue, 27 Aug 2024 11:26:25 +0300 Subject: [PATCH 032/115] Bump chainlink-ccip to ccip-develop latest (#1371) Bump chainlink-ccip to latest commit of ccip-develop branch. ref: https://github.com/smartcontractkit/chainlink-ccip/commit/11e3f1781d9e46a69bddfb037028f44167ec8cdd --- core/scripts/go.mod | 2 +- core/scripts/go.sum | 4 ++-- go.mod | 2 +- go.sum | 4 ++-- integration-tests/go.mod | 2 +- integration-tests/go.sum | 4 ++-- integration-tests/load/go.mod | 2 +- integration-tests/load/go.sum | 4 ++-- 8 files changed, 12 insertions(+), 12 deletions(-) diff --git a/core/scripts/go.mod b/core/scripts/go.mod index 368cee79d9..1167821d05 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -274,7 +274,7 @@ require ( github.com/sethvargo/go-retry v0.2.4 // indirect github.com/shirou/gopsutil v3.21.11+incompatible // indirect github.com/shirou/gopsutil/v3 v3.24.3 // indirect - github.com/smartcontractkit/chainlink-ccip v0.0.0-20240826120733-199eb5870f15 // indirect + github.com/smartcontractkit/chainlink-ccip v0.0.0-20240827080218-11e3f1781d9e // indirect github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240710121324-3ed288aa9b45 // indirect github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240718160222-2dc0c8136bfa // indirect github.com/smartcontractkit/chainlink-feeds v0.0.0-20240710170203-5b41615da827 // indirect diff --git a/core/scripts/go.sum b/core/scripts/go.sum index 7e684e245d..a155bfc334 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -1070,8 +1070,8 @@ github.com/smartcontractkit/chain-selectors v1.0.21 h1:KCR9SA7PhOexaBzFieHoLv1Wo github.com/smartcontractkit/chain-selectors v1.0.21/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/smartcontractkit/chainlink-automation v1.0.4 h1:iyW181JjKHLNMnDleI8umfIfVVlwC7+n5izbLSFgjw8= github.com/smartcontractkit/chainlink-automation v1.0.4/go.mod h1:u4NbPZKJ5XiayfKHD/v3z3iflQWqvtdhj13jVZXj/cM= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20240826120733-199eb5870f15 h1:+Km1o8ApEv/DofxAa5MIPbkxXkKo4BG5u3GKLKB5FSI= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20240826120733-199eb5870f15/go.mod h1:Z9lQ5t20kRk28pzRLnqAJZUVOw8E6/siA3P3MLyKqoM= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20240827080218-11e3f1781d9e h1:ecZaltgIB+mRi9sXYYpOJQXEkeyvQYrKUUzKWv7D+J0= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20240827080218-11e3f1781d9e/go.mod h1:Z9lQ5t20kRk28pzRLnqAJZUVOw8E6/siA3P3MLyKqoM= github.com/smartcontractkit/chainlink-common v0.2.1-0.20240717132349-ee5af9b79834 h1:pTf4xdcmiWBqWZ6rTy2RMTDBzhHk89VC1pM7jXKQztI= github.com/smartcontractkit/chainlink-common v0.2.1-0.20240717132349-ee5af9b79834/go.mod h1:fh9eBbrReCmv31bfz52ENCAMa7nTKQbdhb2B3+S2VGo= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240710121324-3ed288aa9b45 h1:NBQLtqk8zsyY4qTJs+NElI3aDFTcAo83JHvqD04EvB0= diff --git a/go.mod b/go.mod index 8a75274125..de8ef4d0fa 100644 --- a/go.mod +++ b/go.mod @@ -74,7 +74,7 @@ require ( github.com/shopspring/decimal v1.4.0 github.com/smartcontractkit/chain-selectors v1.0.21 github.com/smartcontractkit/chainlink-automation v1.0.4 - github.com/smartcontractkit/chainlink-ccip v0.0.0-20240826120733-199eb5870f15 + github.com/smartcontractkit/chainlink-ccip v0.0.0-20240827080218-11e3f1781d9e github.com/smartcontractkit/chainlink-common v0.2.1-0.20240717132349-ee5af9b79834 github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240710121324-3ed288aa9b45 github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240718160222-2dc0c8136bfa diff --git a/go.sum b/go.sum index d25f3d297a..5e5b72ed2c 100644 --- a/go.sum +++ b/go.sum @@ -1027,8 +1027,8 @@ github.com/smartcontractkit/chain-selectors v1.0.21 h1:KCR9SA7PhOexaBzFieHoLv1Wo github.com/smartcontractkit/chain-selectors v1.0.21/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/smartcontractkit/chainlink-automation v1.0.4 h1:iyW181JjKHLNMnDleI8umfIfVVlwC7+n5izbLSFgjw8= github.com/smartcontractkit/chainlink-automation v1.0.4/go.mod h1:u4NbPZKJ5XiayfKHD/v3z3iflQWqvtdhj13jVZXj/cM= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20240826120733-199eb5870f15 h1:+Km1o8ApEv/DofxAa5MIPbkxXkKo4BG5u3GKLKB5FSI= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20240826120733-199eb5870f15/go.mod h1:Z9lQ5t20kRk28pzRLnqAJZUVOw8E6/siA3P3MLyKqoM= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20240827080218-11e3f1781d9e h1:ecZaltgIB+mRi9sXYYpOJQXEkeyvQYrKUUzKWv7D+J0= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20240827080218-11e3f1781d9e/go.mod h1:Z9lQ5t20kRk28pzRLnqAJZUVOw8E6/siA3P3MLyKqoM= github.com/smartcontractkit/chainlink-common v0.2.1-0.20240717132349-ee5af9b79834 h1:pTf4xdcmiWBqWZ6rTy2RMTDBzhHk89VC1pM7jXKQztI= github.com/smartcontractkit/chainlink-common v0.2.1-0.20240717132349-ee5af9b79834/go.mod h1:fh9eBbrReCmv31bfz52ENCAMa7nTKQbdhb2B3+S2VGo= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240710121324-3ed288aa9b45 h1:NBQLtqk8zsyY4qTJs+NElI3aDFTcAo83JHvqD04EvB0= diff --git a/integration-tests/go.mod b/integration-tests/go.mod index 12773a0b93..3e8db90744 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -36,7 +36,7 @@ require ( github.com/smartcontractkit/ccip-owner-contracts v0.0.0-20240808195812-ae0378684685 github.com/smartcontractkit/chain-selectors v1.0.21 github.com/smartcontractkit/chainlink-automation v1.0.4 - github.com/smartcontractkit/chainlink-ccip v0.0.0-20240826120733-199eb5870f15 + github.com/smartcontractkit/chainlink-ccip v0.0.0-20240827080218-11e3f1781d9e github.com/smartcontractkit/chainlink-common v0.2.1-0.20240717132349-ee5af9b79834 github.com/smartcontractkit/chainlink-testing-framework v1.34.5 github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240405215812-5a72bc9af239 diff --git a/integration-tests/go.sum b/integration-tests/go.sum index 31fc2ff399..3a75793f13 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1396,8 +1396,8 @@ github.com/smartcontractkit/chain-selectors v1.0.21 h1:KCR9SA7PhOexaBzFieHoLv1Wo github.com/smartcontractkit/chain-selectors v1.0.21/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/smartcontractkit/chainlink-automation v1.0.4 h1:iyW181JjKHLNMnDleI8umfIfVVlwC7+n5izbLSFgjw8= github.com/smartcontractkit/chainlink-automation v1.0.4/go.mod h1:u4NbPZKJ5XiayfKHD/v3z3iflQWqvtdhj13jVZXj/cM= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20240826120733-199eb5870f15 h1:+Km1o8ApEv/DofxAa5MIPbkxXkKo4BG5u3GKLKB5FSI= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20240826120733-199eb5870f15/go.mod h1:Z9lQ5t20kRk28pzRLnqAJZUVOw8E6/siA3P3MLyKqoM= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20240827080218-11e3f1781d9e h1:ecZaltgIB+mRi9sXYYpOJQXEkeyvQYrKUUzKWv7D+J0= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20240827080218-11e3f1781d9e/go.mod h1:Z9lQ5t20kRk28pzRLnqAJZUVOw8E6/siA3P3MLyKqoM= github.com/smartcontractkit/chainlink-common v0.2.1-0.20240717132349-ee5af9b79834 h1:pTf4xdcmiWBqWZ6rTy2RMTDBzhHk89VC1pM7jXKQztI= github.com/smartcontractkit/chainlink-common v0.2.1-0.20240717132349-ee5af9b79834/go.mod h1:fh9eBbrReCmv31bfz52ENCAMa7nTKQbdhb2B3+S2VGo= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240710121324-3ed288aa9b45 h1:NBQLtqk8zsyY4qTJs+NElI3aDFTcAo83JHvqD04EvB0= diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index dca0d80503..970896b124 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -42,7 +42,7 @@ require ( github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect - github.com/smartcontractkit/chainlink-ccip v0.0.0-20240826120733-199eb5870f15 // indirect + github.com/smartcontractkit/chainlink-ccip v0.0.0-20240827080218-11e3f1781d9e // indirect github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240710121324-3ed288aa9b45 // indirect github.com/testcontainers/testcontainers-go v0.28.0 // indirect k8s.io/apimachinery v0.30.2 // indirect diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index 487769fb46..97ed754ba7 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -1360,8 +1360,8 @@ github.com/smartcontractkit/chain-selectors v1.0.21 h1:KCR9SA7PhOexaBzFieHoLv1Wo github.com/smartcontractkit/chain-selectors v1.0.21/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/smartcontractkit/chainlink-automation v1.0.4 h1:iyW181JjKHLNMnDleI8umfIfVVlwC7+n5izbLSFgjw8= github.com/smartcontractkit/chainlink-automation v1.0.4/go.mod h1:u4NbPZKJ5XiayfKHD/v3z3iflQWqvtdhj13jVZXj/cM= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20240826120733-199eb5870f15 h1:+Km1o8ApEv/DofxAa5MIPbkxXkKo4BG5u3GKLKB5FSI= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20240826120733-199eb5870f15/go.mod h1:Z9lQ5t20kRk28pzRLnqAJZUVOw8E6/siA3P3MLyKqoM= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20240827080218-11e3f1781d9e h1:ecZaltgIB+mRi9sXYYpOJQXEkeyvQYrKUUzKWv7D+J0= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20240827080218-11e3f1781d9e/go.mod h1:Z9lQ5t20kRk28pzRLnqAJZUVOw8E6/siA3P3MLyKqoM= github.com/smartcontractkit/chainlink-common v0.2.1-0.20240717132349-ee5af9b79834 h1:pTf4xdcmiWBqWZ6rTy2RMTDBzhHk89VC1pM7jXKQztI= github.com/smartcontractkit/chainlink-common v0.2.1-0.20240717132349-ee5af9b79834/go.mod h1:fh9eBbrReCmv31bfz52ENCAMa7nTKQbdhb2B3+S2VGo= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240710121324-3ed288aa9b45 h1:NBQLtqk8zsyY4qTJs+NElI3aDFTcAo83JHvqD04EvB0= From f1d53f2905b1368a64796ce85997cb539e624212 Mon Sep 17 00:00:00 2001 From: Anirudh Warrier <12178754+anirudhwarrier@users.noreply.github.com> Date: Tue, 27 Aug 2024 15:15:25 +0400 Subject: [PATCH 033/115] lowercase networkName (#1372) ## Motivation Load tests with different load config per chain is not working properly. ## Solution Debugged the issue and found that issue was with uppercase in network name. --- integration-tests/ccip-tests/load/helper.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration-tests/ccip-tests/load/helper.go b/integration-tests/ccip-tests/load/helper.go index 9522a6c346..54d9fb2c11 100644 --- a/integration-tests/ccip-tests/load/helper.go +++ b/integration-tests/ccip-tests/load/helper.go @@ -112,7 +112,7 @@ func (l *LoadArgs) scheduleForDest(destNetworkName string) []*wasp.Segment { // otherwise, use the default frequency if l.TestCfg.TestGroupInput.LoadProfile.FrequencyByDestination != nil { for networkName, freq := range l.TestCfg.TestGroupInput.LoadProfile.FrequencyByDestination { - if strings.Contains(destNetworkName, networkName) { + if strings.Contains(destNetworkName, strings.ToLower(networkName)) { return WaspSchedule( freq.RequestPerUnitTime, l.TestCfg.TestGroupInput.LoadProfile.TestDuration, From fd63fe3f10fc99d0665d53e0502c09b97da940a9 Mon Sep 17 00:00:00 2001 From: Rens Rooimans Date: Tue, 27 Aug 2024 13:24:22 +0200 Subject: [PATCH 034/115] Rename PriceRegistry -> FeeQuoter (#1350) Rename the PriceRegistry to FeeQuoter. This PR restores the 1.2 PriceRegistry interface which is still used for CCIP 1.5. The FeeQuoter is a superset of that interface, which is why all tests can use the feeQuoter, even in 1.5. This PR does NOT claim to rename all offchain instances. It only handles onchain and wrapper/mock based references --- .mockery.yaml | 6 +- contracts/gas-snapshots/ccip.gas-snapshot | 273 +- .../scripts/native_solc_compile_all_ccip | 2 +- .../ccip/{PriceRegistry.sol => FeeQuoter.sol} | 43 +- .../v0.8/ccip/MultiAggregateRateLimiter.sol | 46 +- .../src/v0.8/ccip/interfaces/IFeeQuoter.sol | 54 + .../v0.8/ccip/interfaces/IPriceRegistry.sol | 11 - contracts/src/v0.8/ccip/offRamp/OffRamp.sol | 11 +- contracts/src/v0.8/ccip/onRamp/OnRamp.sol | 19 +- .../src/v0.8/ccip/test/NonceManager.t.sol | 2 +- .../ccip/test/commitStore/CommitStore.t.sol | 41 +- .../v0.8/ccip/test/e2e/MultiRampsEnd2End.sol | 2 +- .../FeeQuoter.t.sol} | 982 ++-- .../FeeQuoterSetup.t.sol} | 129 +- ...RegistryHelper.sol => FeeQuoterHelper.sol} | 6 +- .../MultiAggregateRateLimiterHelper.sol | 4 +- .../ccip/test/offRamp/EVM2EVMOffRamp.t.sol | 10 +- .../test/offRamp/EVM2EVMOffRampSetup.t.sol | 11 +- .../src/v0.8/ccip/test/offRamp/OffRamp.t.sol | 49 +- .../v0.8/ccip/test/offRamp/OffRampSetup.t.sol | 27 +- .../v0.8/ccip/test/onRamp/EVM2EVMOnRamp.t.sol | 16 +- .../ccip/test/onRamp/EVM2EVMOnRampSetup.t.sol | 13 +- .../src/v0.8/ccip/test/onRamp/OnRamp.t.sol | 64 +- .../v0.8/ccip/test/onRamp/OnRampSetup.t.sol | 13 +- .../rateLimiter/AggregateRateLimiter.t.sol | 13 +- .../MultiAggregateRateLimiter.t.sol | 41 +- .../src/v0.8/ccip/test/router/Router.t.sol | 6 +- .../ccip/ccip_integration_tests/helpers.go | 44 +- .../ccip/configs/evm/contract_reader.go | 8 +- .../fee_quoter.go} | 1336 ++--- .../multi_aggregate_rate_limiter.go | 214 +- .../ccip/generated/offramp/offramp.go | 4 +- .../ccip/generated/onramp/onramp.go | 4 +- ...rapper-dependency-versions-do-not-edit.txt | 7 +- core/gethwrappers/ccip/go_generate.go | 2 +- .../ccip/mocks/fee_quoter_interface.go | 4509 +++++++++++++++++ .../ccip/mocks/price_registry_interface.go | 4509 ----------------- .../ccip/revert-reason/handler/reason.go | 4 +- .../internal/ccipdata/v1_2_0/test_helpers.go | 14 +- .../ccip-tests/actions/ccip_helpers.go | 6 +- .../ccip-tests/contracts/contract_models.go | 24 +- integration-tests/deployment/ccip/add_lane.go | 15 +- integration-tests/deployment/ccip/deploy.go | 31 +- integration-tests/deployment/ccip/state.go | 16 +- 44 files changed, 6307 insertions(+), 6334 deletions(-) rename contracts/src/v0.8/ccip/{PriceRegistry.sol => FeeQuoter.sol} (97%) create mode 100644 contracts/src/v0.8/ccip/interfaces/IFeeQuoter.sol rename contracts/src/v0.8/ccip/test/{priceRegistry/PriceRegistry.t.sol => feeQuoter/FeeQuoter.t.sol} (60%) rename contracts/src/v0.8/ccip/test/{priceRegistry/PriceRegistrySetup.t.sol => feeQuoter/FeeQuoterSetup.t.sol} (76%) rename contracts/src/v0.8/ccip/test/helpers/{PriceRegistryHelper.sol => FeeQuoterHelper.sol} (95%) rename core/gethwrappers/ccip/generated/{price_registry/price_registry.go => fee_quoter/fee_quoter.go} (54%) create mode 100644 core/gethwrappers/ccip/mocks/fee_quoter_interface.go delete mode 100644 core/gethwrappers/ccip/mocks/price_registry_interface.go diff --git a/.mockery.yaml b/.mockery.yaml index 64217a04be..18749da4f3 100644 --- a/.mockery.yaml +++ b/.mockery.yaml @@ -371,13 +371,13 @@ packages: outpkg: mock_contracts interfaces: CommitStoreInterface: - github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/price_registry: + github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/fee_quoter: config: dir: core/gethwrappers/ccip/mocks/ - filename: price_registry_interface.go + filename: fee_quoter_interface.go outpkg: mock_contracts interfaces: - PriceRegistryInterface: + FeeQuoterInterface: github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/link_token_interface: config: dir: core/gethwrappers/ccip/mocks/ diff --git a/contracts/gas-snapshots/ccip.gas-snapshot b/contracts/gas-snapshots/ccip.gas-snapshot index a573668aa9..af1f296236 100644 --- a/contracts/gas-snapshots/ccip.gas-snapshot +++ b/contracts/gas-snapshots/ccip.gas-snapshot @@ -327,6 +327,110 @@ EtherSenderReceiverTest_validatedMessage:test_validatedMessage_emptyDataOverwrit EtherSenderReceiverTest_validatedMessage:test_validatedMessage_invalidTokenAmounts() (gas: 17895) EtherSenderReceiverTest_validatedMessage:test_validatedMessage_tokenOverwrittenToWeth() (gas: 25287) EtherSenderReceiverTest_validatedMessage:test_validatedMessage_validMessage_extraArgs() (gas: 26292) +FeeQuoter_applyDestChainConfigUpdates:test_InvalidChainFamilySelector_Revert() (gas: 16503) +FeeQuoter_applyDestChainConfigUpdates:test_InvalidDestChainConfigDestChainSelectorEqZero_Revert() (gas: 16417) +FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesDefaultTxGasLimitEqZero_Revert() (gas: 16459) +FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesDefaultTxGasLimitGtMaxPerMessageGasLimit_Revert() (gas: 39957) +FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesZeroIntput_Success() (gas: 12342) +FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdates_Success() (gas: 135870) +FeeQuoter_applyFeeTokensUpdates:test_ApplyFeeTokensUpdates_Success() (gas: 79896) +FeeQuoter_applyFeeTokensUpdates:test_OnlyCallableByOwner_Revert() (gas: 12603) +FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_OnlyCallableByOwnerOrAdmin_Revert() (gas: 11421) +FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesMultipleTokens_Success() (gas: 54105) +FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesSingleToken_Success() (gas: 44791) +FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesZeroInput() (gas: 12257) +FeeQuoter_applyTokenTransferFeeConfigUpdates:test_ApplyTokenTransferFeeConfig_Success() (gas: 86926) +FeeQuoter_applyTokenTransferFeeConfigUpdates:test_ApplyTokenTransferFeeZeroInput() (gas: 13089) +FeeQuoter_applyTokenTransferFeeConfigUpdates:test_InvalidDestBytesOverhead_Revert() (gas: 17071) +FeeQuoter_applyTokenTransferFeeConfigUpdates:test_OnlyCallableByOwnerOrAdmin_Revert() (gas: 12240) +FeeQuoter_constructor:test_InvalidLinkTokenEqZeroAddress_Revert() (gas: 107016) +FeeQuoter_constructor:test_InvalidMaxFeeJuelsPerMsg_Revert() (gas: 111366) +FeeQuoter_constructor:test_InvalidStalenessThreshold_Revert() (gas: 111419) +FeeQuoter_constructor:test_Setup_Success() (gas: 5336824) +FeeQuoter_convertTokenAmount:test_ConvertTokenAmount_Success() (gas: 72739) +FeeQuoter_convertTokenAmount:test_LinkTokenNotSupported_Revert() (gas: 30963) +FeeQuoter_getDataAvailabilityCost:test_EmptyMessageCalculatesDataAvailabilityCost_Success() (gas: 94303) +FeeQuoter_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCostUnsupportedDestChainSelector_Success() (gas: 14614) +FeeQuoter_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCost_Success() (gas: 20410) +FeeQuoter_getTokenAndGasPrices:test_GetFeeTokenAndGasPrices_Success() (gas: 70443) +FeeQuoter_getTokenAndGasPrices:test_StaleGasPrice_Revert() (gas: 16838) +FeeQuoter_getTokenAndGasPrices:test_UnsupportedChain_Revert() (gas: 16140) +FeeQuoter_getTokenAndGasPrices:test_ZeroGasPrice_Success() (gas: 45750) +FeeQuoter_getTokenPrice:test_GetTokenPriceFromFeed_Success() (gas: 62252) +FeeQuoter_getTokenPrices:test_GetTokenPrices_Success() (gas: 84800) +FeeQuoter_getTokenTransferCost:test_CustomTokenBpsFee_Success() (gas: 41227) +FeeQuoter_getTokenTransferCost:test_FeeTokenBpsFee_Success() (gas: 34682) +FeeQuoter_getTokenTransferCost:test_LargeTokenTransferChargesMaxFeeAndGas_Success() (gas: 27756) +FeeQuoter_getTokenTransferCost:test_MixedTokenTransferFee_Success() (gas: 101624) +FeeQuoter_getTokenTransferCost:test_NoTokenTransferChargesZeroFee_Success() (gas: 20354) +FeeQuoter_getTokenTransferCost:test_SmallTokenTransferChargesMinFeeAndGas_Success() (gas: 27631) +FeeQuoter_getTokenTransferCost:test_ZeroAmountTokenTransferChargesMinFeeAndGas_Success() (gas: 27587) +FeeQuoter_getTokenTransferCost:test_ZeroFeeConfigChargesMinFee_Success() (gas: 40013) +FeeQuoter_getTokenTransferCost:test_getTokenTransferCost_selfServeUsesDefaults_Success() (gas: 29299) +FeeQuoter_getValidatedFee:test_DestinationChainNotEnabled_Revert() (gas: 18180) +FeeQuoter_getValidatedFee:test_EmptyMessage_Success() (gas: 81054) +FeeQuoter_getValidatedFee:test_EnforceOutOfOrder_Revert() (gas: 54294) +FeeQuoter_getValidatedFee:test_HighGasMessage_Success() (gas: 237472) +FeeQuoter_getValidatedFee:test_InvalidEVMAddress_Revert() (gas: 19949) +FeeQuoter_getValidatedFee:test_MessageGasLimitTooHigh_Revert() (gas: 31746) +FeeQuoter_getValidatedFee:test_MessageTooLarge_Revert() (gas: 97692) +FeeQuoter_getValidatedFee:test_MessageWithDataAndTokenTransfer_Success() (gas: 142833) +FeeQuoter_getValidatedFee:test_NotAFeeToken_Revert() (gas: 29407) +FeeQuoter_getValidatedFee:test_SingleTokenMessage_Success() (gas: 111861) +FeeQuoter_getValidatedFee:test_TooManyTokens_Revert() (gas: 20085) +FeeQuoter_getValidatedFee:test_ZeroDataAvailabilityMultiplier_Success() (gas: 61933) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Above18Decimals_Success() (gas: 2094539) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Below18Decimals_Success() (gas: 2094497) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt0Decimals_Success() (gas: 2074616) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt18Decimals_Success() (gas: 2094271) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFlippedDecimals_Success() (gas: 2094475) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedMaxInt224Value_Success() (gas: 2094287) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedOverStalenessPeriod_Success() (gas: 62004) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeed_Success() (gas: 61884) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPrice_Success() (gas: 61036) +FeeQuoter_getValidatedTokenPrice:test_OverflowFeedPrice_Revert() (gas: 2093974) +FeeQuoter_getValidatedTokenPrice:test_StaleFeeToken_Success() (gas: 61563) +FeeQuoter_getValidatedTokenPrice:test_TokenNotSupportedFeed_Revert() (gas: 109120) +FeeQuoter_getValidatedTokenPrice:test_TokenNotSupported_Revert() (gas: 13857) +FeeQuoter_getValidatedTokenPrice:test_UnderflowFeedPrice_Revert() (gas: 2092636) +FeeQuoter_onReport:test_OnReport_StaleUpdate_Revert() (gas: 43334) +FeeQuoter_onReport:test_onReport_InvalidForwarder_Reverts() (gas: 23294) +FeeQuoter_onReport:test_onReport_Success() (gas: 80639) +FeeQuoter_onReport:test_onReport_UnsupportedToken_Reverts() (gas: 26677) +FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsDefault_Success() (gas: 17185) +FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsEnforceOutOfOrder_Revert() (gas: 21290) +FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsGasLimitTooHigh_Revert() (gas: 18387) +FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsInvalidExtraArgsTag_Revert() (gas: 17911) +FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsV1_Success() (gas: 18285) +FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsV2_Success() (gas: 18401) +FeeQuoter_processMessageArgs:test_InvalidExtraArgs_Revert() (gas: 18361) +FeeQuoter_processMessageArgs:test_MalformedEVMExtraArgs_Revert() (gas: 18907) +FeeQuoter_processMessageArgs:test_MessageFeeTooHigh_Revert() (gas: 16426) +FeeQuoter_processMessageArgs:test_WitEVMExtraArgsV2_Success() (gas: 26269) +FeeQuoter_processMessageArgs:test_WithConvertedTokenAmount_Success() (gas: 32441) +FeeQuoter_processMessageArgs:test_WithEVMExtraArgsV1_Success() (gas: 25881) +FeeQuoter_processMessageArgs:test_WithEmptyEVMExtraArgs_Success() (gas: 23696) +FeeQuoter_processMessageArgs:test_WithLinkTokenAmount_Success() (gas: 17375) +FeeQuoter_updatePrices:test_OnlyCallableByUpdater_Revert() (gas: 12102) +FeeQuoter_updatePrices:test_OnlyGasPrice_Success() (gas: 23599) +FeeQuoter_updatePrices:test_OnlyTokenPrice_Success() (gas: 30631) +FeeQuoter_updatePrices:test_UpdatableByAuthorizedCaller_Success() (gas: 76003) +FeeQuoter_updatePrices:test_UpdateMultiplePrices_Success() (gas: 151393) +FeeQuoter_updateTokenPriceFeeds:test_FeedNotUpdated() (gas: 50527) +FeeQuoter_updateTokenPriceFeeds:test_FeedUnset_Success() (gas: 63626) +FeeQuoter_updateTokenPriceFeeds:test_FeedUpdatedByNonOwner_Revert() (gas: 19932) +FeeQuoter_updateTokenPriceFeeds:test_MultipleFeedUpdate_Success() (gas: 88972) +FeeQuoter_updateTokenPriceFeeds:test_SingleFeedUpdate_Success() (gas: 50821) +FeeQuoter_updateTokenPriceFeeds:test_ZeroFeeds_Success() (gas: 12296) +FeeQuoter_validateDestFamilyAddress:test_InvalidEVMAddressEncodePacked_Revert() (gas: 10616) +FeeQuoter_validateDestFamilyAddress:test_InvalidEVMAddressPrecompiles_Revert() (gas: 3961646) +FeeQuoter_validateDestFamilyAddress:test_InvalidEVMAddress_Revert() (gas: 10800) +FeeQuoter_validateDestFamilyAddress:test_ValidEVMAddress_Success() (gas: 6704) +FeeQuoter_validateDestFamilyAddress:test_ValidNonEVMAddress_Success() (gas: 6484) +FeeQuoter_validatePoolReturnData:test_InvalidEVMAddressDestToken_Revert() (gas: 42748) +FeeQuoter_validatePoolReturnData:test_ProcessPoolReturnData_Success() (gas: 73252) +FeeQuoter_validatePoolReturnData:test_SourceTokenDataTooLarge_Revert() (gas: 107744) +FeeQuoter_validatePoolReturnData:test_TokenAmountArraysMismatching_Revert() (gas: 40091) LockReleaseTokenPoolAndProxy_setRebalancer:test_SetRebalancer_Revert() (gas: 10970) LockReleaseTokenPoolAndProxy_setRebalancer:test_SetRebalancer_Success() (gas: 17992) LockReleaseTokenPoolPoolAndProxy_canAcceptLiquidity:test_CanAcceptLiquidity_Success() (gas: 3368110) @@ -372,42 +476,42 @@ MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_UpdateExistingConfi MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_UpdateExistingConfig_Success() (gas: 53092) MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_ZeroChainSelector_Revert() (gas: 17019) MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_ZeroConfigs_Success() (gas: 12295) -MultiAggregateRateLimiter_constructor:test_ConstructorNoAuthorizedCallers_Success() (gas: 2149637) -MultiAggregateRateLimiter_constructor:test_Constructor_Success() (gas: 2265894) +MultiAggregateRateLimiter_constructor:test_ConstructorNoAuthorizedCallers_Success() (gas: 2149547) +MultiAggregateRateLimiter_constructor:test_Constructor_Success() (gas: 2265849) MultiAggregateRateLimiter_getTokenBucket:test_GetTokenBucket_Success() (gas: 30248) MultiAggregateRateLimiter_getTokenBucket:test_Refill_Success() (gas: 47358) MultiAggregateRateLimiter_getTokenBucket:test_TimeUnderflow_Revert() (gas: 15821) -MultiAggregateRateLimiter_getTokenValue:test_GetTokenValue_Success() (gas: 19684) -MultiAggregateRateLimiter_getTokenValue:test_NoTokenPrice_Reverts() (gas: 21269) +MultiAggregateRateLimiter_getTokenValue:test_GetTokenValue_Success() (gas: 19662) +MultiAggregateRateLimiter_getTokenValue:test_NoTokenPrice_Reverts() (gas: 21247) MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageFromUnauthorizedCaller_Revert() (gas: 14527) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithDifferentTokensOnDifferentChains_Success() (gas: 213660) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithDisabledRateLimitToken_Success() (gas: 60459) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithDifferentTokensOnDifferentChains_Success() (gas: 213638) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithDisabledRateLimitToken_Success() (gas: 60437) MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithNoTokens_Success() (gas: 17593) MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitDisabled_Success() (gas: 44895) MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitExceeded_Revert() (gas: 50542) MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitReset_Success() (gas: 78668) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithTokensOnDifferentChains_Success() (gas: 311949) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithTokensOnDifferentChains_Success() (gas: 311927) MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithTokens_Success() (gas: 54728) MultiAggregateRateLimiter_onOutboundMessage:test_RateLimitValueDifferentLanes_Success() (gas: 9223372036854754743) -MultiAggregateRateLimiter_onOutboundMessage:test_ValidateMessageWithNoTokens_Success() (gas: 19104) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageFromUnauthorizedCaller_Revert() (gas: 15778) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithDifferentTokensOnDifferentChains_Success() (gas: 213648) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithDisabledRateLimitToken_Success() (gas: 62194) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitDisabled_Success() (gas: 46683) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitExceeded_Revert() (gas: 52315) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitReset_Success() (gas: 79733) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithTokensOnDifferentChains_Success() (gas: 312163) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithTokens_Success() (gas: 56485) -MultiAggregateRateLimiter_setPriceRegistry:test_OnlyOwner_Revert() (gas: 11292) -MultiAggregateRateLimiter_setPriceRegistry:test_Owner_Success() (gas: 19080) -MultiAggregateRateLimiter_setPriceRegistry:test_ZeroAddress_Revert() (gas: 10564) -MultiAggregateRateLimiter_updateRateLimitTokens:test_NonOwner_Revert() (gas: 18872) -MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokensMultipleChains_Success() (gas: 279906) -MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokensSingleChain_Success() (gas: 254501) +MultiAggregateRateLimiter_onOutboundMessage:test_ValidateMessageWithNoTokens_Success() (gas: 19149) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageFromUnauthorizedCaller_Revert() (gas: 15823) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithDifferentTokensOnDifferentChains_Success() (gas: 213716) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithDisabledRateLimitToken_Success() (gas: 62217) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitDisabled_Success() (gas: 46728) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitExceeded_Revert() (gas: 52360) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitReset_Success() (gas: 79913) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithTokensOnDifferentChains_Success() (gas: 312231) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithTokens_Success() (gas: 56530) +MultiAggregateRateLimiter_setFeeQuoter:test_OnlyOwner_Revert() (gas: 11313) +MultiAggregateRateLimiter_setFeeQuoter:test_Owner_Success() (gas: 19066) +MultiAggregateRateLimiter_setFeeQuoter:test_ZeroAddress_Revert() (gas: 10585) +MultiAggregateRateLimiter_updateRateLimitTokens:test_NonOwner_Revert() (gas: 18850) +MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokensMultipleChains_Success() (gas: 279972) +MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokensSingleChain_Success() (gas: 254523) MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokens_AddsAndRemoves_Success() (gas: 204488) -MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokens_RemoveNonExistentToken_Success() (gas: 28681) -MultiAggregateRateLimiter_updateRateLimitTokens:test_ZeroDestToken_Revert() (gas: 18309) -MultiAggregateRateLimiter_updateRateLimitTokens:test_ZeroSourceToken_Revert() (gas: 18238) +MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokens_RemoveNonExistentToken_Success() (gas: 28703) +MultiAggregateRateLimiter_updateRateLimitTokens:test_ZeroDestToken_Revert() (gas: 18287) +MultiAggregateRateLimiter_updateRateLimitTokens:test_ZeroSourceToken_Revert() (gas: 18216) MultiOCR3Base_setOCR3Configs:test_FMustBePositive_Revert() (gas: 59331) MultiOCR3Base_setOCR3Configs:test_FTooHigh_Revert() (gas: 44298) MultiOCR3Base_setOCR3Configs:test_RepeatSignerAddress_Revert() (gas: 283711) @@ -438,7 +542,7 @@ MultiOCR3Base_transmit:test_UnAuthorizedTransmitter_Revert() (gas: 24191) MultiOCR3Base_transmit:test_UnauthorizedSigner_Revert() (gas: 61409) MultiOCR3Base_transmit:test_UnconfiguredPlugin_Revert() (gas: 39890) MultiOCR3Base_transmit:test_ZeroSignatures_Revert() (gas: 32973) -MultiOnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 410740) +MultiOnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 410714) MultiRampsE2E:test_E2E_3MessagesMMultiOffRampSuccess_gas() (gas: 1486877) NonceManager_NonceIncrementation:test_getIncrementedOutboundNonce_Success() (gas: 37907) NonceManager_NonceIncrementation:test_incrementInboundNonce_Skip() (gas: 23694) @@ -608,10 +712,10 @@ OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_Success() (gas: 177934) OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals_Success() (gas: 191136) OffRamp_resetUnblessedRoots:test_OnlyOwner_Revert() (gas: 11423) OffRamp_resetUnblessedRoots:test_ResetUnblessedRoots_Success() (gas: 215351) -OffRamp_setDynamicConfig:test_NonOwner_Revert() (gas: 14097) -OffRamp_setDynamicConfig:test_PriceRegistryZeroAddress_Revert() (gas: 11617) -OffRamp_setDynamicConfig:test_SetDynamicConfigWithValidator_Success() (gas: 49137) -OffRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 27081) +OffRamp_setDynamicConfig:test_FeeQuoterZeroAddress_Revert() (gas: 11585) +OffRamp_setDynamicConfig:test_NonOwner_Revert() (gas: 14130) +OffRamp_setDynamicConfig:test_SetDynamicConfigWithValidator_Success() (gas: 49093) +OffRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 27103) OffRamp_trialExecute:test_RateLimitError_Success() (gas: 225773) OffRamp_trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 234394) OffRamp_trialExecute:test_TokenPoolIsNotAContract_Success() (gas: 309206) @@ -649,7 +753,7 @@ OnRamp_forwardFromRouter:test_ShouldStoreNonLinkFees() (gas: 144094) OnRamp_forwardFromRouter:test_SourceTokenDataTooLarge_Revert() (gas: 3887491) OnRamp_forwardFromRouter:test_UnsupportedToken_Revert() (gas: 108659) OnRamp_forwardFromRouter:test_forwardFromRouter_UnsupportedToken_Revert() (gas: 74066) -OnRamp_forwardFromRouter:test_forwardFromRouter_WithValidation_Success() (gas: 273429) +OnRamp_forwardFromRouter:test_forwardFromRouter_WithValidation_Success() (gas: 273416) OnRamp_getFee:test_EmptyMessage_Success() (gas: 104351) OnRamp_getFee:test_EnforceOutOfOrder_Revert() (gas: 73173) OnRamp_getFee:test_SingleTokenMessage_Success() (gas: 119675) @@ -657,119 +761,16 @@ OnRamp_getFee:test_Unhealthy_Revert() (gas: 43679) OnRamp_getSupportedTokens:test_GetSupportedTokens_Revert() (gas: 10438) OnRamp_getTokenPool:test_GetTokenPool_Success() (gas: 35270) OnRamp_setDynamicConfig:test_SetConfigInvalidConfigFeeAggregatorEqAddressZero_Revert() (gas: 11155) -OnRamp_setDynamicConfig:test_SetConfigInvalidConfigPriceRegistryEqAddressZero_Revert() (gas: 12740) +OnRamp_setDynamicConfig:test_SetConfigInvalidConfigFeeQuoterEqAddressZero_Revert() (gas: 12763) OnRamp_setDynamicConfig:test_SetConfigInvalidConfig_Revert() (gas: 11112) OnRamp_setDynamicConfig:test_SetConfigOnlyOwner_Revert() (gas: 15939) -OnRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 51996) +OnRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 52018) OnRamp_withdrawFeeTokens:test_WithdrawFeeTokens_Success() (gas: 97192) PingPong_ccipReceive:test_CcipReceive_Success() (gas: 150169) PingPong_plumbing:test_OutOfOrderExecution_Success() (gas: 20277) PingPong_plumbing:test_Pausing_Success() (gas: 17777) PingPong_startPingPong:test_StartPingPong_With_OOO_Success() (gas: 163187) PingPong_startPingPong:test_StartPingPong_With_Sequenced_Ordered_Success() (gas: 182599) -PriceRegistry_applyDestChainConfigUpdates:test_InvalidChainFamilySelector_Revert() (gas: 16503) -PriceRegistry_applyDestChainConfigUpdates:test_InvalidDestChainConfigDestChainSelectorEqZero_Revert() (gas: 16417) -PriceRegistry_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesDefaultTxGasLimitEqZero_Revert() (gas: 16459) -PriceRegistry_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesDefaultTxGasLimitGtMaxPerMessageGasLimit_Revert() (gas: 39957) -PriceRegistry_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesZeroIntput_Success() (gas: 12342) -PriceRegistry_applyDestChainConfigUpdates:test_applyDestChainConfigUpdates_Success() (gas: 135870) -PriceRegistry_applyFeeTokensUpdates:test_ApplyFeeTokensUpdates_Success() (gas: 79896) -PriceRegistry_applyFeeTokensUpdates:test_OnlyCallableByOwner_Revert() (gas: 12603) -PriceRegistry_applyPremiumMultiplierWeiPerEthUpdates:test_OnlyCallableByOwnerOrAdmin_Revert() (gas: 11421) -PriceRegistry_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesMultipleTokens_Success() (gas: 54105) -PriceRegistry_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesSingleToken_Success() (gas: 44791) -PriceRegistry_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesZeroInput() (gas: 12257) -PriceRegistry_applyTokenTransferFeeConfigUpdates:test_ApplyTokenTransferFeeConfig_Success() (gas: 86926) -PriceRegistry_applyTokenTransferFeeConfigUpdates:test_ApplyTokenTransferFeeZeroInput() (gas: 13089) -PriceRegistry_applyTokenTransferFeeConfigUpdates:test_InvalidDestBytesOverhead_Revert() (gas: 17071) -PriceRegistry_applyTokenTransferFeeConfigUpdates:test_OnlyCallableByOwnerOrAdmin_Revert() (gas: 12240) -PriceRegistry_constructor:test_InvalidLinkTokenEqZeroAddress_Revert() (gas: 107016) -PriceRegistry_constructor:test_InvalidMaxFeeJuelsPerMsg_Revert() (gas: 111366) -PriceRegistry_constructor:test_InvalidStalenessThreshold_Revert() (gas: 111419) -PriceRegistry_constructor:test_Setup_Success() (gas: 5336824) -PriceRegistry_convertTokenAmount:test_ConvertTokenAmount_Success() (gas: 72739) -PriceRegistry_convertTokenAmount:test_LinkTokenNotSupported_Revert() (gas: 30963) -PriceRegistry_getDataAvailabilityCost:test_EmptyMessageCalculatesDataAvailabilityCost_Success() (gas: 94303) -PriceRegistry_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCostUnsupportedDestChainSelector_Success() (gas: 14614) -PriceRegistry_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCost_Success() (gas: 20410) -PriceRegistry_getTokenAndGasPrices:test_GetFeeTokenAndGasPrices_Success() (gas: 70443) -PriceRegistry_getTokenAndGasPrices:test_StaleGasPrice_Revert() (gas: 16838) -PriceRegistry_getTokenAndGasPrices:test_UnsupportedChain_Revert() (gas: 16140) -PriceRegistry_getTokenAndGasPrices:test_ZeroGasPrice_Success() (gas: 45750) -PriceRegistry_getTokenPrice:test_GetTokenPriceFromFeed_Success() (gas: 62252) -PriceRegistry_getTokenPrices:test_GetTokenPrices_Success() (gas: 84800) -PriceRegistry_getTokenTransferCost:test_CustomTokenBpsFee_Success() (gas: 41227) -PriceRegistry_getTokenTransferCost:test_FeeTokenBpsFee_Success() (gas: 34682) -PriceRegistry_getTokenTransferCost:test_LargeTokenTransferChargesMaxFeeAndGas_Success() (gas: 27756) -PriceRegistry_getTokenTransferCost:test_MixedTokenTransferFee_Success() (gas: 101624) -PriceRegistry_getTokenTransferCost:test_NoTokenTransferChargesZeroFee_Success() (gas: 20354) -PriceRegistry_getTokenTransferCost:test_SmallTokenTransferChargesMinFeeAndGas_Success() (gas: 27631) -PriceRegistry_getTokenTransferCost:test_ZeroAmountTokenTransferChargesMinFeeAndGas_Success() (gas: 27587) -PriceRegistry_getTokenTransferCost:test_ZeroFeeConfigChargesMinFee_Success() (gas: 40013) -PriceRegistry_getTokenTransferCost:test_getTokenTransferCost_selfServeUsesDefaults_Success() (gas: 29299) -PriceRegistry_getValidatedFee:test_DestinationChainNotEnabled_Revert() (gas: 18180) -PriceRegistry_getValidatedFee:test_EmptyMessage_Success() (gas: 81054) -PriceRegistry_getValidatedFee:test_EnforceOutOfOrder_Revert() (gas: 54294) -PriceRegistry_getValidatedFee:test_HighGasMessage_Success() (gas: 237472) -PriceRegistry_getValidatedFee:test_InvalidEVMAddress_Revert() (gas: 19949) -PriceRegistry_getValidatedFee:test_MessageGasLimitTooHigh_Revert() (gas: 31746) -PriceRegistry_getValidatedFee:test_MessageTooLarge_Revert() (gas: 97692) -PriceRegistry_getValidatedFee:test_MessageWithDataAndTokenTransfer_Success() (gas: 142833) -PriceRegistry_getValidatedFee:test_NotAFeeToken_Revert() (gas: 29407) -PriceRegistry_getValidatedFee:test_SingleTokenMessage_Success() (gas: 111861) -PriceRegistry_getValidatedFee:test_TooManyTokens_Revert() (gas: 20085) -PriceRegistry_getValidatedFee:test_ZeroDataAvailabilityMultiplier_Success() (gas: 61933) -PriceRegistry_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Above18Decimals_Success() (gas: 2094539) -PriceRegistry_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Below18Decimals_Success() (gas: 2094497) -PriceRegistry_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt0Decimals_Success() (gas: 2074616) -PriceRegistry_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt18Decimals_Success() (gas: 2094271) -PriceRegistry_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFlippedDecimals_Success() (gas: 2094475) -PriceRegistry_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedMaxInt224Value_Success() (gas: 2094287) -PriceRegistry_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedOverStalenessPeriod_Success() (gas: 62004) -PriceRegistry_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeed_Success() (gas: 61884) -PriceRegistry_getValidatedTokenPrice:test_GetValidatedTokenPrice_Success() (gas: 61036) -PriceRegistry_getValidatedTokenPrice:test_OverflowFeedPrice_Revert() (gas: 2093974) -PriceRegistry_getValidatedTokenPrice:test_StaleFeeToken_Success() (gas: 61563) -PriceRegistry_getValidatedTokenPrice:test_TokenNotSupportedFeed_Revert() (gas: 109120) -PriceRegistry_getValidatedTokenPrice:test_TokenNotSupported_Revert() (gas: 13857) -PriceRegistry_getValidatedTokenPrice:test_UnderflowFeedPrice_Revert() (gas: 2092636) -PriceRegistry_onReport:test_OnReport_StaleUpdate_Revert() (gas: 43359) -PriceRegistry_onReport:test_onReport_InvalidForwarder_Reverts() (gas: 23261) -PriceRegistry_onReport:test_onReport_Success() (gas: 80666) -PriceRegistry_onReport:test_onReport_UnsupportedToken_Reverts() (gas: 26675) -PriceRegistry_parseEVMExtraArgsFromBytes:test_EVMExtraArgsDefault_Success() (gas: 17185) -PriceRegistry_parseEVMExtraArgsFromBytes:test_EVMExtraArgsEnforceOutOfOrder_Revert() (gas: 21290) -PriceRegistry_parseEVMExtraArgsFromBytes:test_EVMExtraArgsGasLimitTooHigh_Revert() (gas: 18387) -PriceRegistry_parseEVMExtraArgsFromBytes:test_EVMExtraArgsInvalidExtraArgsTag_Revert() (gas: 17911) -PriceRegistry_parseEVMExtraArgsFromBytes:test_EVMExtraArgsV1_Success() (gas: 18285) -PriceRegistry_parseEVMExtraArgsFromBytes:test_EVMExtraArgsV2_Success() (gas: 18401) -PriceRegistry_processMessageArgs:test_InvalidExtraArgs_Revert() (gas: 18361) -PriceRegistry_processMessageArgs:test_MalformedEVMExtraArgs_Revert() (gas: 18907) -PriceRegistry_processMessageArgs:test_MessageFeeTooHigh_Revert() (gas: 16426) -PriceRegistry_processMessageArgs:test_WitEVMExtraArgsV2_Success() (gas: 26269) -PriceRegistry_processMessageArgs:test_WithConvertedTokenAmount_Success() (gas: 32441) -PriceRegistry_processMessageArgs:test_WithEVMExtraArgsV1_Success() (gas: 25881) -PriceRegistry_processMessageArgs:test_WithEmptyEVMExtraArgs_Success() (gas: 23696) -PriceRegistry_processMessageArgs:test_WithLinkTokenAmount_Success() (gas: 17375) -PriceRegistry_processPoolReturnData:test_InvalidEVMAddressDestToken_Revert() (gas: 42784) -PriceRegistry_processPoolReturnData:test_SourceTokenDataTooLarge_Revert() (gas: 107735) -PriceRegistry_processPoolReturnData:test_TokenAmountArraysMismatching_Revert() (gas: 40104) -PriceRegistry_updatePrices:test_OnlyCallableByUpdater_Revert() (gas: 12102) -PriceRegistry_updatePrices:test_OnlyGasPrice_Success() (gas: 23599) -PriceRegistry_updatePrices:test_OnlyTokenPrice_Success() (gas: 30631) -PriceRegistry_updatePrices:test_UpdatableByAuthorizedCaller_Success() (gas: 76003) -PriceRegistry_updatePrices:test_UpdateMultiplePrices_Success() (gas: 151393) -PriceRegistry_updateTokenPriceFeeds:test_FeedNotUpdated() (gas: 50527) -PriceRegistry_updateTokenPriceFeeds:test_FeedUnset_Success() (gas: 63626) -PriceRegistry_updateTokenPriceFeeds:test_FeedUpdatedByNonOwner_Revert() (gas: 19932) -PriceRegistry_updateTokenPriceFeeds:test_MultipleFeedUpdate_Success() (gas: 88972) -PriceRegistry_updateTokenPriceFeeds:test_SingleFeedUpdate_Success() (gas: 50821) -PriceRegistry_updateTokenPriceFeeds:test_ZeroFeeds_Success() (gas: 12296) -PriceRegistry_validateDestFamilyAddress:test_InvalidEVMAddressEncodePacked_Revert() (gas: 10616) -PriceRegistry_validateDestFamilyAddress:test_InvalidEVMAddressPrecompiles_Revert() (gas: 3961646) -PriceRegistry_validateDestFamilyAddress:test_InvalidEVMAddress_Revert() (gas: 10800) -PriceRegistry_validateDestFamilyAddress:test_ValidEVMAddress_Success() (gas: 6704) -PriceRegistry_validateDestFamilyAddress:test_ValidNonEVMAddress_Success() (gas: 6484) RMNHome:test() (gas: 186) RMN_constructor:test_Constructor_Success() (gas: 48838) RMN_getRecordedCurseRelatedOps:test_OpsPostDeployment() (gas: 19666) diff --git a/contracts/scripts/native_solc_compile_all_ccip b/contracts/scripts/native_solc_compile_all_ccip index a384ea6786..7b2c580b3c 100755 --- a/contracts/scripts/native_solc_compile_all_ccip +++ b/contracts/scripts/native_solc_compile_all_ccip @@ -67,7 +67,7 @@ compileContract ccip/onRamp/EVM2EVMOnRamp.sol compileContract ccip/CommitStore.sol compileContract ccip/MultiAggregateRateLimiter.sol compileContract ccip/Router.sol -compileContract ccip/PriceRegistry.sol +compileContract ccip/FeeQuoter.sol compileContract ccip/RMN.sol compileContract ccip/ARMProxy.sol compileContract ccip/tokenAdminRegistry/TokenAdminRegistry.sol diff --git a/contracts/src/v0.8/ccip/PriceRegistry.sol b/contracts/src/v0.8/ccip/FeeQuoter.sol similarity index 97% rename from contracts/src/v0.8/ccip/PriceRegistry.sol rename to contracts/src/v0.8/ccip/FeeQuoter.sol index 8593568371..c2a7231d96 100644 --- a/contracts/src/v0.8/ccip/PriceRegistry.sol +++ b/contracts/src/v0.8/ccip/FeeQuoter.sol @@ -2,6 +2,7 @@ pragma solidity 0.8.24; import {ITypeAndVersion} from "../shared/interfaces/ITypeAndVersion.sol"; +import {IFeeQuoter} from "./interfaces/IFeeQuoter.sol"; import {IPriceRegistry} from "./interfaces/IPriceRegistry.sol"; import {AuthorizedCallers} from "../shared/access/AuthorizedCallers.sol"; @@ -16,18 +17,12 @@ import {IReceiver} from "../keystone/interfaces/IReceiver.sol"; import {KeystoneFeedDefaultMetadataLib} from "../keystone/lib/KeystoneFeedDefaultMetadataLib.sol"; import {EnumerableSet} from "../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/structs/EnumerableSet.sol"; -/// @notice The PriceRegistry contract responsibility is to: +/// @notice The FeeQuoter contract responsibility is to: /// - Store the current gas price in USD for a given destination chain, /// - Store the price of a token in USD allowing the owner or priceUpdater to update this value. /// - Manage chain specific fee calculations. /// The authorized callers in the contract represent the fee price updaters. -contract PriceRegistry is - AuthorizedCallers, - IPriceRegistry, - ITypeAndVersion, - IReceiver, - KeystoneFeedsPermissionHandler -{ +contract FeeQuoter is AuthorizedCallers, IFeeQuoter, ITypeAndVersion, IReceiver, KeystoneFeedsPermissionHandler { using EnumerableSet for EnumerableSet.AddressSet; using USDPriceWith18Decimals for uint224; using KeystoneFeedDefaultMetadataLib for bytes; @@ -53,7 +48,7 @@ contract PriceRegistry is event FeeTokenRemoved(address indexed feeToken); event UsdPerUnitGasUpdated(uint64 indexed destChain, uint256 value, uint256 timestamp); event UsdPerTokenUpdated(address indexed token, uint256 value, uint256 timestamp); - event PriceFeedPerTokenUpdated(address indexed token, IPriceRegistry.TokenPriceFeedConfig priceFeedConfig); + event PriceFeedPerTokenUpdated(address indexed token, IFeeQuoter.TokenPriceFeedConfig priceFeedConfig); event TokenTransferFeeConfigUpdated( uint64 indexed destChainSelector, address indexed token, TokenTransferFeeConfig tokenTransferFeeConfig ); @@ -65,7 +60,7 @@ contract PriceRegistry is /// @notice Token price data feed update struct TokenPriceFeedUpdate { address sourceToken; // Source token to update feed for - IPriceRegistry.TokenPriceFeedConfig feedConfig; // Feed config update data + IFeeQuoter.TokenPriceFeedConfig feedConfig; // Feed config update data } /// @dev Struct that contains the static configuration @@ -155,7 +150,7 @@ contract PriceRegistry is uint64 premiumMultiplierWeiPerEth; // ──╯ Multiplier for destination chain specific premiums. Should never be 0 so can be used as an isEnabled flag } - string public constant override typeAndVersion = "PriceRegistry 1.6.0-dev"; + string public constant override typeAndVersion = "FeeQuoter 1.6.0-dev"; /// @dev The gas price per unit of gas for a given destination chain, in USD with 18 decimals. /// Multiple gas prices can be encoded into the same value. Each price takes {Internal.GAS_PRICE_BITS} bits. @@ -176,7 +171,7 @@ contract PriceRegistry is mapping(address token => Internal.TimestampedPackedUint224 price) private s_usdPerToken; /// @dev Stores the price data feed configurations per token. - mapping(address token => IPriceRegistry.TokenPriceFeedConfig dataFeedAddress) private s_usdPriceFeedsPerToken; + mapping(address token => IFeeQuoter.TokenPriceFeedConfig dataFeedAddress) private s_usdPriceFeedsPerToken; /// @dev The multiplier for destination chain specific premiums that can be set by the owner or fee admin /// This should never be 0 once set, so it can be used as an isEnabled flag @@ -232,7 +227,7 @@ contract PriceRegistry is /// @inheritdoc IPriceRegistry function getTokenPrice(address token) public view override returns (Internal.TimestampedPackedUint224 memory) { - IPriceRegistry.TokenPriceFeedConfig memory priceFeedConfig = s_usdPriceFeedsPerToken[token]; + IFeeQuoter.TokenPriceFeedConfig memory priceFeedConfig = s_usdPriceFeedsPerToken[token]; if (priceFeedConfig.dataFeedAddress == address(0)) { return s_usdPerToken[token]; } @@ -260,12 +255,12 @@ contract PriceRegistry is return tokenPrices; } - /// @inheritdoc IPriceRegistry + /// @inheritdoc IFeeQuoter function getTokenPriceFeedConfig(address token) external view override - returns (IPriceRegistry.TokenPriceFeedConfig memory) + returns (IFeeQuoter.TokenPriceFeedConfig memory) { return s_usdPriceFeedsPerToken[token]; } @@ -324,7 +319,7 @@ contract PriceRegistry is /// @notice Gets the token price from a data feed address, rebased to the same units as s_usdPerToken /// @param priceFeedConfig token data feed configuration with valid data feed address (used to retrieve price & timestamp) /// @return tokenPrice data feed price answer rebased to s_usdPerToken units, with latest block timestamp - function _getTokenPriceFromDataFeed(IPriceRegistry.TokenPriceFeedConfig memory priceFeedConfig) + function _getTokenPriceFromDataFeed(IFeeQuoter.TokenPriceFeedConfig memory priceFeedConfig) internal view returns (Internal.TimestampedPackedUint224 memory tokenPrice) @@ -347,7 +342,7 @@ contract PriceRegistry is uint224 rebasedValue = _calculateRebasedValue(dataFeedContract.decimals(), priceFeedConfig.tokenDecimals, uint256(dataFeedAnswer)); - // Data feed staleness is unchecked to decouple the PriceRegistry from data feed delay issues + // Data feed staleness is unchecked to decouple the FeeQuoter from data feed delay issues return Internal.TimestampedPackedUint224({value: rebasedValue, timestamp: uint32(block.timestamp)}); } @@ -428,7 +423,7 @@ contract PriceRegistry is for (uint256 i; i < tokenPriceFeedUpdates.length; ++i) { TokenPriceFeedUpdate memory update = tokenPriceFeedUpdates[i]; address sourceToken = update.sourceToken; - IPriceRegistry.TokenPriceFeedConfig memory tokenPriceFeedConfig = update.feedConfig; + IFeeQuoter.TokenPriceFeedConfig memory tokenPriceFeedConfig = update.feedConfig; s_usdPriceFeedsPerToken[sourceToken] = tokenPriceFeedConfig; emit PriceFeedPerTokenUpdated(sourceToken, tokenPriceFeedConfig); @@ -470,7 +465,7 @@ contract PriceRegistry is // │ Fee quoting │ // ================================================================ - /// @inheritdoc IPriceRegistry + /// @inheritdoc IFeeQuoter /// @dev The function should always validate message.extraArgs, message.receiver and family-specific configs function getValidatedFee( uint64 destChainSelector, @@ -606,7 +601,7 @@ contract PriceRegistry is uint256 bpsFeeUSDWei = 0; // Only calculate bps fee if ratio is greater than 0. Ratio of 0 means no bps fee for a token. - // Useful for when the PriceRegistry cannot return a valid price for the token. + // Useful for when the FeeQuoter cannot return a valid price for the token. if (transferFeeConfig.deciBps > 0) { uint224 tokenPrice = 0; if (tokenAmount.token != feeToken) { @@ -839,7 +834,7 @@ contract PriceRegistry is _validateDestFamilyAddress(destChainConfig.chainFamilySelector, receiver); } - /// @inheritdoc IPriceRegistry + /// @inheritdoc IFeeQuoter function processMessageArgs( uint64 destChainSelector, address feeToken, @@ -864,7 +859,7 @@ contract PriceRegistry is return (msgFeeJuels, isOutOfOrderExecution, Client._argsToBytes(parsedExtraArgs)); } - /// @inheritdoc IPriceRegistry + /// @inheritdoc IFeeQuoter /// @dev precondition - rampTokenAmounts and sourceTokenAmounts lengths must be equal function processPoolReturnData( uint64 destChainSelector, @@ -887,7 +882,7 @@ contract PriceRegistry is } _validateDestFamilyAddress(chainFamilySelector, rampTokenAmounts[i].destTokenAddress); - PriceRegistry.TokenTransferFeeConfig memory tokenTransferFeeConfig = + FeeQuoter.TokenTransferFeeConfig memory tokenTransferFeeConfig = s_tokenTransferFeeConfig[destChainSelector][sourceToken]; uint32 defaultGasOverhead = s_destChainConfigs[destChainSelector].defaultTokenDestGasOverhead; // NOTE: Revisit this when adding new non-EVM chain family selector support @@ -945,7 +940,7 @@ contract PriceRegistry is } } - /// @notice Returns the static PriceRegistry config. + /// @notice Returns the static FeeQuoter config. /// @dev RMN depends on this function, if updated, please notify the RMN maintainers. /// @return staticConfig The static configuration. function getStaticConfig() external view returns (StaticConfig memory) { diff --git a/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol b/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol index 13ba582a2b..0f1e9b9702 100644 --- a/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol +++ b/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol @@ -2,8 +2,8 @@ pragma solidity 0.8.24; import {ITypeAndVersion} from "../shared/interfaces/ITypeAndVersion.sol"; +import {IFeeQuoter} from "./interfaces/IFeeQuoter.sol"; import {IMessageInterceptor} from "./interfaces/IMessageInterceptor.sol"; -import {IPriceRegistry} from "./interfaces/IPriceRegistry.sol"; import {AuthorizedCallers} from "../shared/access/AuthorizedCallers.sol"; import {EnumerableMapAddresses} from "./../shared/enumerable/EnumerableMapAddresses.sol"; @@ -13,7 +13,7 @@ import {USDPriceWith18Decimals} from "./libraries/USDPriceWith18Decimals.sol"; /// @notice The aggregate rate limiter is a wrapper of the token bucket rate limiter /// which permits rate limiting based on the aggregate value of a group of -/// token transfers, using a price registry to convert to a numeraire asset (e.g. USD). +/// token transfers, using a fee quoter to convert to a numeraire asset (e.g. USD). /// The contract is a standalone multi-lane message validator contract, which can be called by authorized /// ramp contracts to apply rate limit changes to lanes, and revert when the rate limits get breached. contract MultiAggregateRateLimiter is IMessageInterceptor, AuthorizedCallers, ITypeAndVersion { @@ -25,7 +25,7 @@ contract MultiAggregateRateLimiter is IMessageInterceptor, AuthorizedCallers, IT error ZeroChainSelectorNotAllowed(); event RateLimiterConfigUpdated(uint64 indexed remoteChainSelector, bool isOutboundLane, RateLimiter.Config config); - event PriceRegistrySet(address newPriceRegistry); + event FeeQuoterSet(address newFeeQuoter); event TokenAggregateRateLimitAdded(uint64 remoteChainSelector, bytes remoteToken, address localToken); event TokenAggregateRateLimitRemoved(uint64 remoteChainSelector, address localToken); @@ -62,16 +62,16 @@ contract MultiAggregateRateLimiter is IMessageInterceptor, AuthorizedCallers, IT mapping(uint64 remoteChainSelector => EnumerableMapAddresses.AddressToBytesMap tokensLocalToRemote) internal s_rateLimitedTokensLocalToRemote; - /// @notice The address of the PriceRegistry used to query token values for ratelimiting. - address internal s_priceRegistry; + /// @notice The address of the FeeQuoter used to query token values for ratelimiting. + address internal s_feeQuoter; /// @notice Rate limiter token bucket states per chain, with separate buckets for inbound and outbound lanes. mapping(uint64 remoteChainSelector => RateLimiterBuckets buckets) internal s_rateLimitersByChainSelector; - /// @param priceRegistry the price registry to set. + /// @param feeQuoter the fee quoter to set. /// @param authorizedCallers the authorized callers to set. - constructor(address priceRegistry, address[] memory authorizedCallers) AuthorizedCallers(authorizedCallers) { - _setPriceRegistry(priceRegistry); + constructor(address feeQuoter, address[] memory authorizedCallers) AuthorizedCallers(authorizedCallers) { + _setFeeQuoter(feeQuoter); } /// @inheritdoc IMessageInterceptor @@ -127,13 +127,13 @@ contract MultiAggregateRateLimiter is IMessageInterceptor, AuthorizedCallers, IT } } - /// @notice Retrieves the token value for a token using the PriceRegistry. + /// @notice Retrieves the token value for a token using the FeeQuoter. /// @param tokenAmount The token and amount to get the value for. /// @return tokenValue USD value in 18 decimals. function _getTokenValue(Client.EVMTokenAmount memory tokenAmount) internal view returns (uint256) { // not fetching validated price, as price staleness is not important for value-based rate limiting // we only need to verify the price is not 0 - uint224 pricePerToken = IPriceRegistry(s_priceRegistry).getTokenPrice(tokenAmount.token).value; + uint224 pricePerToken = IFeeQuoter(s_feeQuoter).getTokenPrice(tokenAmount.token).value; if (pricePerToken == 0) revert PriceNotFoundForToken(tokenAmount.token); return pricePerToken._calcUSDValueFromTokenAmount(tokenAmount.amount); } @@ -247,27 +247,27 @@ contract MultiAggregateRateLimiter is IMessageInterceptor, AuthorizedCallers, IT } } - /// @return priceRegistry The configured PriceRegistry address. - function getPriceRegistry() external view returns (address) { - return s_priceRegistry; + /// @return feeQuoter The configured FeeQuoter address. + function getFeeQuoter() external view returns (address feeQuoter) { + return s_feeQuoter; } - /// @notice Sets the Price Registry address. - /// @param newPriceRegistry the address of the new PriceRegistry. + /// @notice Sets the FeeQuoter address. + /// @param newFeeQuoter the address of the new FeeQuoter. /// @dev precondition The address must be a non-zero address. - function setPriceRegistry(address newPriceRegistry) external onlyOwner { - _setPriceRegistry(newPriceRegistry); + function setFeeQuoter(address newFeeQuoter) external onlyOwner { + _setFeeQuoter(newFeeQuoter); } - /// @notice Sets the Price Registry address. - /// @param newPriceRegistry the address of the new PriceRegistry. + /// @notice Sets the FeeQuoter address. + /// @param newFeeQuoter the address of the new FeeQuoter. /// @dev precondition The address must be a non-zero address. - function _setPriceRegistry(address newPriceRegistry) internal { - if (newPriceRegistry == address(0)) { + function _setFeeQuoter(address newFeeQuoter) internal { + if (newFeeQuoter == address(0)) { revert ZeroAddressNotAllowed(); } - s_priceRegistry = newPriceRegistry; - emit PriceRegistrySet(newPriceRegistry); + s_feeQuoter = newFeeQuoter; + emit FeeQuoterSet(newFeeQuoter); } } diff --git a/contracts/src/v0.8/ccip/interfaces/IFeeQuoter.sol b/contracts/src/v0.8/ccip/interfaces/IFeeQuoter.sol new file mode 100644 index 0000000000..fdea4538b6 --- /dev/null +++ b/contracts/src/v0.8/ccip/interfaces/IFeeQuoter.sol @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {Client} from "../libraries/Client.sol"; +import {Internal} from "../libraries/Internal.sol"; +import {IPriceRegistry} from "./IPriceRegistry.sol"; + +interface IFeeQuoter is IPriceRegistry { + /// @notice Token price data feed configuration + struct TokenPriceFeedConfig { + address dataFeedAddress; // ──╮ AggregatorV3Interface contract (0 - feed is unset) + uint8 tokenDecimals; // ──────╯ Decimals of the token that the feed represents + } + + /// @notice Returns the token price data feed configuration + /// @param token The token to retrieve the feed config for + /// @return tokenPriceFeedConfig The token price data feed config (if feed address is 0, the feed config is disabled) + function getTokenPriceFeedConfig(address token) external view returns (TokenPriceFeedConfig memory); + + /// @notice Validates the ccip message & returns the fee + /// @param destChainSelector The destination chain selector. + /// @param message The message to get quote for. + /// @return feeTokenAmount The amount of fee token needed for the fee, in smallest denomination of the fee token. + function getValidatedFee( + uint64 destChainSelector, + Client.EVM2AnyMessage calldata message + ) external view returns (uint256 feeTokenAmount); + + /// @notice Converts the extraArgs to the latest version and returns the converted message fee in juels + /// @param destChainSelector destination chain selector to process + /// @param feeToken Fee token address used to pay for message fees + /// @param feeTokenAmount Fee token amount + /// @param extraArgs Message extra args that were passed in by the client + /// @return msgFeeJuels message fee in juels + /// @return isOutOfOrderExecution true if the message should be executed out of order + /// @return convertedExtraArgs extra args converted to the latest family-specific args version + function processMessageArgs( + uint64 destChainSelector, + address feeToken, + uint256 feeTokenAmount, + bytes memory extraArgs + ) external view returns (uint256 msgFeeJuels, bool isOutOfOrderExecution, bytes memory convertedExtraArgs); + + /// @notice Validates pool return data + /// @param destChainSelector Destination chain selector to which the token amounts are sent to + /// @param rampTokenAmounts Token amounts with populated pool return data + /// @param sourceTokenAmounts Token amounts originally sent in a Client.EVM2AnyMessage message + /// @return destExecData Destination chain execution data + function processPoolReturnData( + uint64 destChainSelector, + Internal.RampTokenAmount[] memory rampTokenAmounts, + Client.EVMTokenAmount[] calldata sourceTokenAmounts + ) external view returns (bytes[] memory); +} diff --git a/contracts/src/v0.8/ccip/interfaces/IPriceRegistry.sol b/contracts/src/v0.8/ccip/interfaces/IPriceRegistry.sol index 05d68b3183..a2c7bc1880 100644 --- a/contracts/src/v0.8/ccip/interfaces/IPriceRegistry.sol +++ b/contracts/src/v0.8/ccip/interfaces/IPriceRegistry.sol @@ -5,12 +5,6 @@ import {Client} from "../libraries/Client.sol"; import {Internal} from "../libraries/Internal.sol"; interface IPriceRegistry { - /// @notice Token price data feed configuration - struct TokenPriceFeedConfig { - address dataFeedAddress; // ──╮ AggregatorV3Interface contract (0 - feed is unset) - uint8 tokenDecimals; // ──────╯ Decimals of the token that the feed represents - } - /// @notice Update the price for given tokens and gas prices for given chains. /// @param priceUpdates The price updates to apply. function updatePrices(Internal.PriceUpdates memory priceUpdates) external; @@ -30,11 +24,6 @@ interface IPriceRegistry { /// @return tokenPrices The tokenPrices for the given tokens. function getTokenPrices(address[] calldata tokens) external view returns (Internal.TimestampedPackedUint224[] memory); - /// @notice Returns the token price data feed configuration - /// @param token The token to retrieve the feed config for - /// @return tokenPriceFeedConfig The token price data feed config (if feed address is 0, the feed config is disabled) - function getTokenPriceFeedConfig(address token) external view returns (TokenPriceFeedConfig memory); - /// @notice Get an encoded `gasPrice` for a given destination chain ID. /// The 224-bit result encodes necessary gas price components. /// On L1 chains like Ethereum or Avax, the only component is the gas price. diff --git a/contracts/src/v0.8/ccip/offRamp/OffRamp.sol b/contracts/src/v0.8/ccip/offRamp/OffRamp.sol index 3f98d55e81..20ce6115dc 100644 --- a/contracts/src/v0.8/ccip/offRamp/OffRamp.sol +++ b/contracts/src/v0.8/ccip/offRamp/OffRamp.sol @@ -3,10 +3,11 @@ pragma solidity 0.8.24; import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; import {IAny2EVMMessageReceiver} from "../interfaces/IAny2EVMMessageReceiver.sol"; + +import {IFeeQuoter} from "../interfaces/IFeeQuoter.sol"; import {IMessageInterceptor} from "../interfaces/IMessageInterceptor.sol"; import {INonceManager} from "../interfaces/INonceManager.sol"; import {IPoolV1} from "../interfaces/IPool.sol"; -import {IPriceRegistry} from "../interfaces/IPriceRegistry.sol"; import {IRMN} from "../interfaces/IRMN.sol"; import {IRouter} from "../interfaces/IRouter.sol"; import {ITokenAdminRegistry} from "../interfaces/ITokenAdminRegistry.sol"; @@ -108,7 +109,7 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { /// @notice Dynamic offRamp config /// @dev Since DynamicConfig is part of DynamicConfigSet event, if changing it, we should update the ABI on Atlas struct DynamicConfig { - address priceRegistry; // ──────────────────────────╮ Price registry address on the local chain + address feeQuoter; // ──────────────────────────────╮ FeeQuoter address on the local chain uint32 permissionLessExecutionThresholdSeconds; // │ Waiting time before manual execution is enabled uint32 maxTokenTransferGas; // │ Maximum amount of gas passed on to token `transfer` call uint32 maxPoolReleaseOrMintGas; // ─────────────────╯ Maximum amount of gas passed on to token pool when calling releaseOrMint @@ -589,8 +590,8 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { if (s_latestPriceSequenceNumber < sequenceNumber) { // If prices are not stale, update the latest epoch and round s_latestPriceSequenceNumber = sequenceNumber; - // And update the prices in the price registry - IPriceRegistry(s_dynamicConfig.priceRegistry).updatePrices(commitReport.priceUpdates); + // And update the prices in the fee quoter + IFeeQuoter(s_dynamicConfig.feeQuoter).updatePrices(commitReport.priceUpdates); } else { // If prices are stale and the report doesn't contain a root, this report // does not have any valid information and we revert. @@ -780,7 +781,7 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { /// @notice Sets the dynamic config. /// @param dynamicConfig The dynamic config. function _setDynamicConfig(DynamicConfig memory dynamicConfig) internal { - if (dynamicConfig.priceRegistry == address(0)) { + if (dynamicConfig.feeQuoter == address(0)) { revert ZeroAddressNotAllowed(); } diff --git a/contracts/src/v0.8/ccip/onRamp/OnRamp.sol b/contracts/src/v0.8/ccip/onRamp/OnRamp.sol index 6de57bf548..aa4edba3ac 100644 --- a/contracts/src/v0.8/ccip/onRamp/OnRamp.sol +++ b/contracts/src/v0.8/ccip/onRamp/OnRamp.sol @@ -3,10 +3,10 @@ pragma solidity 0.8.24; import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; import {IEVM2AnyOnRampClient} from "../interfaces/IEVM2AnyOnRampClient.sol"; +import {IFeeQuoter} from "../interfaces/IFeeQuoter.sol"; import {IMessageInterceptor} from "../interfaces/IMessageInterceptor.sol"; import {INonceManager} from "../interfaces/INonceManager.sol"; import {IPoolV1} from "../interfaces/IPool.sol"; -import {IPriceRegistry} from "../interfaces/IPriceRegistry.sol"; import {IRMN} from "../interfaces/IRMN.sol"; import {IRouter} from "../interfaces/IRouter.sol"; import {ITokenAdminRegistry} from "../interfaces/ITokenAdminRegistry.sol"; @@ -56,7 +56,7 @@ contract OnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCreator { /// @dev Struct that contains the dynamic configuration // solhint-disable-next-line gas-struct-packing struct DynamicConfig { - address priceRegistry; // Price registry address + address feeQuoter; // FeeQuoter address address messageValidator; // Optional message validator to validate outbound messages (zero address = no validator) address feeAggregator; // Fee aggregator address } @@ -153,8 +153,8 @@ contract OnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCreator { } // Convert message fee to juels and retrieve converted args - (uint256 msgFeeJuels, bool isOutOfOrderExecution, bytes memory convertedExtraArgs) = IPriceRegistry( - s_dynamicConfig.priceRegistry + (uint256 msgFeeJuels, bool isOutOfOrderExecution, bytes memory convertedExtraArgs) = IFeeQuoter( + s_dynamicConfig.feeQuoter ).processMessageArgs(destChainSelector, message.feeToken, feeTokenAmount, message.extraArgs); emit FeePaid(message.feeToken, msgFeeJuels); @@ -191,7 +191,7 @@ contract OnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCreator { } // Validate pool return data after it is populated (view function - no state changes) - bytes[] memory destExecDataPerToken = IPriceRegistry(s_dynamicConfig.priceRegistry).processPoolReturnData( + bytes[] memory destExecDataPerToken = IFeeQuoter(s_dynamicConfig.feeQuoter).processPoolReturnData( destChainSelector, newMessage.tokenAmounts, message.tokenAmounts ); @@ -249,8 +249,7 @@ contract OnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCreator { }) ); - // NOTE: pool data validations are outsourced to the PriceRegistry to handle family-specific logic handling - + // NOTE: pool data validations are outsourced to the FeeQuoter to handle family-specific logic handling return Internal.RampTokenAmount({ sourcePoolAddress: abi.encode(sourcePool), destTokenAddress: poolReturnData.destTokenAddress, @@ -297,7 +296,7 @@ contract OnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCreator { /// @notice Internal version of setDynamicConfig to allow for reuse in the constructor. function _setDynamicConfig(DynamicConfig memory dynamicConfig) internal { - if (dynamicConfig.priceRegistry == address(0) || dynamicConfig.feeAggregator == address(0)) revert InvalidConfig(); + if (dynamicConfig.feeQuoter == address(0) || dynamicConfig.feeAggregator == address(0)) revert InvalidConfig(); s_dynamicConfig = dynamicConfig; @@ -367,13 +366,13 @@ contract OnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCreator { ) external view returns (uint256 feeTokenAmount) { if (IRMN(i_rmnProxy).isCursed(bytes16(uint128(destChainSelector)))) revert CursedByRMN(destChainSelector); - return IPriceRegistry(s_dynamicConfig.priceRegistry).getValidatedFee(destChainSelector, message); + return IFeeQuoter(s_dynamicConfig.feeQuoter).getValidatedFee(destChainSelector, message); } /// @notice Withdraws the outstanding fee token balances to the fee aggregator. /// @dev This function can be permissionless as it only transfers accepted fee tokens to the fee aggregator which is a trusted address. function withdrawFeeTokens() external { - address[] memory feeTokens = IPriceRegistry(s_dynamicConfig.priceRegistry).getFeeTokens(); + address[] memory feeTokens = IFeeQuoter(s_dynamicConfig.feeQuoter).getFeeTokens(); address feeAggregator = s_dynamicConfig.feeAggregator; for (uint256 i = 0; i < feeTokens.length; ++i) { diff --git a/contracts/src/v0.8/ccip/test/NonceManager.t.sol b/contracts/src/v0.8/ccip/test/NonceManager.t.sol index 3811f0d3c6..81da419253 100644 --- a/contracts/src/v0.8/ccip/test/NonceManager.t.sol +++ b/contracts/src/v0.8/ccip/test/NonceManager.t.sol @@ -236,7 +236,7 @@ contract NonceManager_OnRampUpgrade is OnRampSetup { destDataAvailabilityOverheadGas: DEST_DATA_AVAILABILITY_OVERHEAD_GAS, destGasPerDataAvailabilityByte: DEST_GAS_PER_DATA_AVAILABILITY_BYTE, destDataAvailabilityMultiplierBps: DEST_GAS_DATA_AVAILABILITY_MULTIPLIER_BPS, - priceRegistry: address(s_priceRegistry), + priceRegistry: address(s_feeQuoter), maxDataBytes: MAX_DATA_SIZE, maxPerMsgGasLimit: MAX_GAS_LIMIT, defaultTokenFeeUSDCents: DEFAULT_TOKEN_FEE_USD_CENTS, diff --git a/contracts/src/v0.8/ccip/test/commitStore/CommitStore.t.sol b/contracts/src/v0.8/ccip/test/commitStore/CommitStore.t.sol index 7ea64c9f89..0976ab96c5 100644 --- a/contracts/src/v0.8/ccip/test/commitStore/CommitStore.t.sol +++ b/contracts/src/v0.8/ccip/test/commitStore/CommitStore.t.sol @@ -6,19 +6,19 @@ import {IRMN} from "../../interfaces/IRMN.sol"; import {AuthorizedCallers} from "../../../shared/access/AuthorizedCallers.sol"; import {CommitStore} from "../../CommitStore.sol"; -import {PriceRegistry} from "../../PriceRegistry.sol"; +import {FeeQuoter} from "../../FeeQuoter.sol"; import {RMN} from "../../RMN.sol"; import {MerkleMultiProof} from "../../libraries/MerkleMultiProof.sol"; import {OCR2Abstract} from "../../ocr/OCR2Abstract.sol"; +import {FeeQuoterSetup} from "../feeQuoter/FeeQuoterSetup.t.sol"; import {CommitStoreHelper} from "../helpers/CommitStoreHelper.sol"; import {OCR2BaseSetup} from "../ocr/OCR2Base.t.sol"; -import {PriceRegistrySetup} from "../priceRegistry/PriceRegistrySetup.t.sol"; -contract CommitStoreSetup is PriceRegistrySetup, OCR2BaseSetup { +contract CommitStoreSetup is FeeQuoterSetup, OCR2BaseSetup { CommitStoreHelper internal s_commitStore; - function setUp() public virtual override(PriceRegistrySetup, OCR2BaseSetup) { - PriceRegistrySetup.setUp(); + function setUp() public virtual override(FeeQuoterSetup, OCR2BaseSetup) { + FeeQuoterSetup.setUp(); OCR2BaseSetup.setUp(); s_commitStore = new CommitStoreHelper( @@ -29,29 +29,28 @@ contract CommitStoreSetup is PriceRegistrySetup, OCR2BaseSetup { rmnProxy: address(s_mockRMN) }) ); - CommitStore.DynamicConfig memory dynamicConfig = - CommitStore.DynamicConfig({priceRegistry: address(s_priceRegistry)}); + CommitStore.DynamicConfig memory dynamicConfig = CommitStore.DynamicConfig({priceRegistry: address(s_feeQuoter)}); s_commitStore.setOCR2Config( s_valid_signers, s_valid_transmitters, s_f, abi.encode(dynamicConfig), s_offchainConfigVersion, abi.encode("") ); address[] memory priceUpdaters = new address[](1); priceUpdaters[0] = address(s_commitStore); - s_priceRegistry.applyAuthorizedCallerUpdates( + s_feeQuoter.applyAuthorizedCallerUpdates( AuthorizedCallers.AuthorizedCallerArgs({addedCallers: priceUpdaters, removedCallers: new address[](0)}) ); } } -contract CommitStoreRealRMNSetup is PriceRegistrySetup, OCR2BaseSetup { +contract CommitStoreRealRMNSetup is FeeQuoterSetup, OCR2BaseSetup { CommitStoreHelper internal s_commitStore; RMN internal s_rmn; address internal constant BLESS_VOTE_ADDR = address(8888); - function setUp() public virtual override(PriceRegistrySetup, OCR2BaseSetup) { - PriceRegistrySetup.setUp(); + function setUp() public virtual override(FeeQuoterSetup, OCR2BaseSetup) { + FeeQuoterSetup.setUp(); OCR2BaseSetup.setUp(); RMN.Voter[] memory voters = new RMN.Voter[](1); @@ -67,17 +66,16 @@ contract CommitStoreRealRMNSetup is PriceRegistrySetup, OCR2BaseSetup { rmnProxy: address(s_rmn) }) ); - CommitStore.DynamicConfig memory dynamicConfig = - CommitStore.DynamicConfig({priceRegistry: address(s_priceRegistry)}); + CommitStore.DynamicConfig memory dynamicConfig = CommitStore.DynamicConfig({priceRegistry: address(s_feeQuoter)}); s_commitStore.setOCR2Config( s_valid_signers, s_valid_transmitters, s_f, abi.encode(dynamicConfig), s_offchainConfigVersion, abi.encode("") ); } } -contract CommitStore_constructor is PriceRegistrySetup, OCR2BaseSetup { - function setUp() public virtual override(PriceRegistrySetup, OCR2BaseSetup) { - PriceRegistrySetup.setUp(); +contract CommitStore_constructor is FeeQuoterSetup, OCR2BaseSetup { + function setUp() public virtual override(FeeQuoterSetup, OCR2BaseSetup) { + FeeQuoterSetup.setUp(); OCR2BaseSetup.setUp(); } @@ -88,8 +86,7 @@ contract CommitStore_constructor is PriceRegistrySetup, OCR2BaseSetup { onRamp: 0x2C44CDDdB6a900Fa2B585dd299E03D12Fa4293Bc, rmnProxy: address(s_mockRMN) }); - CommitStore.DynamicConfig memory dynamicConfig = - CommitStore.DynamicConfig({priceRegistry: address(s_priceRegistry)}); + CommitStore.DynamicConfig memory dynamicConfig = CommitStore.DynamicConfig({priceRegistry: address(s_feeQuoter)}); vm.expectEmit(); emit CommitStore.ConfigSet(staticConfig, dynamicConfig); @@ -354,7 +351,7 @@ contract CommitStore_report is CommitStoreSetup { }); vm.expectEmit(); - emit PriceRegistry.UsdPerTokenUpdated(s_sourceFeeToken, 4e18, block.timestamp); + emit FeeQuoter.UsdPerTokenUpdated(s_sourceFeeToken, 4e18, block.timestamp); s_commitStore.report(abi.encode(report), ++s_latestEpochAndRound); assertEq(s_latestEpochAndRound, s_commitStore.getLatestPriceEpochAndRound()); @@ -368,7 +365,7 @@ contract CommitStore_report is CommitStoreSetup { }); vm.expectEmit(); - emit PriceRegistry.UsdPerTokenUpdated(s_sourceFeeToken, 4e18, block.timestamp); + emit FeeQuoter.UsdPerTokenUpdated(s_sourceFeeToken, 4e18, block.timestamp); s_commitStore.report(abi.encode(report), ++s_latestEpochAndRound); assertEq(s_latestEpochAndRound, s_commitStore.getLatestPriceEpochAndRound()); @@ -386,7 +383,7 @@ contract CommitStore_report is CommitStoreSetup { }); vm.expectEmit(); - emit PriceRegistry.UsdPerTokenUpdated(s_sourceFeeToken, tokenPrice1, block.timestamp); + emit FeeQuoter.UsdPerTokenUpdated(s_sourceFeeToken, tokenPrice1, block.timestamp); s_commitStore.report(abi.encode(report), ++s_latestEpochAndRound); assertEq(s_latestEpochAndRound, s_commitStore.getLatestPriceEpochAndRound()); @@ -476,7 +473,7 @@ contract CommitStore_report is CommitStoreSetup { }); vm.expectEmit(); - emit PriceRegistry.UsdPerTokenUpdated(s_sourceFeeToken, 4e18, block.timestamp); + emit FeeQuoter.UsdPerTokenUpdated(s_sourceFeeToken, 4e18, block.timestamp); s_commitStore.report(abi.encode(report), ++s_latestEpochAndRound); vm.expectRevert(CommitStore.StaleReport.selector); diff --git a/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.sol b/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.sol index 5ad0091734..4f9d0ac2c7 100644 --- a/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.sol +++ b/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.sol @@ -240,7 +240,7 @@ contract MultiRampsE2E is OnRampSetup, OffRampSetup { router.ccipSend(DEST_CHAIN_SELECTOR, message); vm.pauseGasMetering(); - uint256 gasLimit = s_priceRegistry.parseEVMExtraArgsFromBytes(msgEvent.extraArgs, DEST_CHAIN_SELECTOR).gasLimit; + uint256 gasLimit = s_feeQuoter.parseEVMExtraArgsFromBytes(msgEvent.extraArgs, DEST_CHAIN_SELECTOR).gasLimit; return Internal.Any2EVMRampMessage({ header: Internal.RampMessageHeader({ diff --git a/contracts/src/v0.8/ccip/test/priceRegistry/PriceRegistry.t.sol b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.t.sol similarity index 60% rename from contracts/src/v0.8/ccip/test/priceRegistry/PriceRegistry.t.sol rename to contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.t.sol index dbbc4b32cd..11836b3d7b 100644 --- a/contracts/src/v0.8/ccip/test/priceRegistry/PriceRegistry.t.sol +++ b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.t.sol @@ -1,21 +1,22 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.24; +import {IFeeQuoter} from "../../interfaces/IFeeQuoter.sol"; + import {KeystoneFeedsPermissionHandler} from "../../../keystone/KeystoneFeedsPermissionHandler.sol"; import {AuthorizedCallers} from "../../../shared/access/AuthorizedCallers.sol"; import {MockV3Aggregator} from "../../../tests/MockV3Aggregator.sol"; -import {PriceRegistry} from "../../PriceRegistry.sol"; -import {IPriceRegistry} from "../../interfaces/IPriceRegistry.sol"; +import {FeeQuoter} from "../../FeeQuoter.sol"; import {Client} from "../../libraries/Client.sol"; import {Internal} from "../../libraries/Internal.sol"; import {Pool} from "../../libraries/Pool.sol"; import {USDPriceWith18Decimals} from "../../libraries/USDPriceWith18Decimals.sol"; -import {PriceRegistryHelper} from "../helpers/PriceRegistryHelper.sol"; -import {PriceRegistryFeeSetup, PriceRegistrySetup} from "./PriceRegistrySetup.t.sol"; +import {FeeQuoterHelper} from "../helpers/FeeQuoterHelper.sol"; +import {FeeQuoterFeeSetup, FeeQuoterSetup} from "./FeeQuoterSetup.t.sol"; import {Vm} from "forge-std/Vm.sol"; -contract PriceRegistry_constructor is PriceRegistrySetup { +contract FeeQuoter_constructor is FeeQuoterSetup { function test_Setup_Success() public virtual { address[] memory priceUpdaters = new address[](2); priceUpdaters[0] = STRANGER; @@ -23,134 +24,133 @@ contract PriceRegistry_constructor is PriceRegistrySetup { address[] memory feeTokens = new address[](2); feeTokens[0] = s_sourceTokens[0]; feeTokens[1] = s_sourceTokens[1]; - PriceRegistry.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new PriceRegistry.TokenPriceFeedUpdate[](2); + FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](2); tokenPriceFeedUpdates[0] = _getSingleTokenPriceFeedUpdateStruct(s_sourceTokens[0], s_dataFeedByToken[s_sourceTokens[0]], 18); tokenPriceFeedUpdates[1] = _getSingleTokenPriceFeedUpdateStruct(s_sourceTokens[1], s_dataFeedByToken[s_sourceTokens[1]], 6); - PriceRegistry.DestChainConfigArgs[] memory destChainConfigArgs = _generatePriceRegistryDestChainConfigArgs(); + FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = _generateFeeQuoterDestChainConfigArgs(); - PriceRegistry.StaticConfig memory staticConfig = PriceRegistry.StaticConfig({ + FeeQuoter.StaticConfig memory staticConfig = FeeQuoter.StaticConfig({ linkToken: s_sourceTokens[0], maxFeeJuelsPerMsg: MAX_MSG_FEES_JUELS, stalenessThreshold: uint32(TWELVE_HOURS) }); - s_priceRegistry = new PriceRegistryHelper( + s_feeQuoter = new FeeQuoterHelper( staticConfig, priceUpdaters, feeTokens, tokenPriceFeedUpdates, - s_priceRegistryTokenTransferFeeConfigArgs, - s_priceRegistryPremiumMultiplierWeiPerEthArgs, + s_feeQuoterTokenTransferFeeConfigArgs, + s_feeQuoterPremiumMultiplierWeiPerEthArgs, destChainConfigArgs ); - _assertPriceRegistryStaticConfigsEqual(s_priceRegistry.getStaticConfig(), staticConfig); - assertEq(feeTokens, s_priceRegistry.getFeeTokens()); - assertEq(priceUpdaters, s_priceRegistry.getAllAuthorizedCallers()); - assertEq(s_priceRegistry.typeAndVersion(), "PriceRegistry 1.6.0-dev"); + _assertFeeQuoterStaticConfigsEqual(s_feeQuoter.getStaticConfig(), staticConfig); + assertEq(feeTokens, s_feeQuoter.getFeeTokens()); + assertEq(priceUpdaters, s_feeQuoter.getAllAuthorizedCallers()); + assertEq(s_feeQuoter.typeAndVersion(), "FeeQuoter 1.6.0-dev"); _assertTokenPriceFeedConfigEquality( - tokenPriceFeedUpdates[0].feedConfig, s_priceRegistry.getTokenPriceFeedConfig(s_sourceTokens[0]) + tokenPriceFeedUpdates[0].feedConfig, s_feeQuoter.getTokenPriceFeedConfig(s_sourceTokens[0]) ); _assertTokenPriceFeedConfigEquality( - tokenPriceFeedUpdates[1].feedConfig, s_priceRegistry.getTokenPriceFeedConfig(s_sourceTokens[1]) + tokenPriceFeedUpdates[1].feedConfig, s_feeQuoter.getTokenPriceFeedConfig(s_sourceTokens[1]) ); assertEq( - s_priceRegistryPremiumMultiplierWeiPerEthArgs[0].premiumMultiplierWeiPerEth, - s_priceRegistry.getPremiumMultiplierWeiPerEth(s_priceRegistryPremiumMultiplierWeiPerEthArgs[0].token) + s_feeQuoterPremiumMultiplierWeiPerEthArgs[0].premiumMultiplierWeiPerEth, + s_feeQuoter.getPremiumMultiplierWeiPerEth(s_feeQuoterPremiumMultiplierWeiPerEthArgs[0].token) ); assertEq( - s_priceRegistryPremiumMultiplierWeiPerEthArgs[1].premiumMultiplierWeiPerEth, - s_priceRegistry.getPremiumMultiplierWeiPerEth(s_priceRegistryPremiumMultiplierWeiPerEthArgs[1].token) + s_feeQuoterPremiumMultiplierWeiPerEthArgs[1].premiumMultiplierWeiPerEth, + s_feeQuoter.getPremiumMultiplierWeiPerEth(s_feeQuoterPremiumMultiplierWeiPerEthArgs[1].token) ); - PriceRegistry.TokenTransferFeeConfigArgs memory tokenTransferFeeConfigArg = - s_priceRegistryTokenTransferFeeConfigArgs[0]; + FeeQuoter.TokenTransferFeeConfigArgs memory tokenTransferFeeConfigArg = s_feeQuoterTokenTransferFeeConfigArgs[0]; for (uint256 i = 0; i < tokenTransferFeeConfigArg.tokenTransferFeeConfigs.length; ++i) { - PriceRegistry.TokenTransferFeeConfigSingleTokenArgs memory tokenFeeArgs = - s_priceRegistryTokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[i]; + FeeQuoter.TokenTransferFeeConfigSingleTokenArgs memory tokenFeeArgs = + s_feeQuoterTokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[i]; _assertTokenTransferFeeConfigEqual( tokenFeeArgs.tokenTransferFeeConfig, - s_priceRegistry.getTokenTransferFeeConfig(tokenTransferFeeConfigArg.destChainSelector, tokenFeeArgs.token) + s_feeQuoter.getTokenTransferFeeConfig(tokenTransferFeeConfigArg.destChainSelector, tokenFeeArgs.token) ); } for (uint256 i = 0; i < destChainConfigArgs.length; ++i) { - PriceRegistry.DestChainConfig memory expectedConfig = destChainConfigArgs[i].destChainConfig; + FeeQuoter.DestChainConfig memory expectedConfig = destChainConfigArgs[i].destChainConfig; uint64 destChainSelector = destChainConfigArgs[i].destChainSelector; - _assertPriceRegistryDestChainConfigsEqual(expectedConfig, s_priceRegistry.getDestChainConfig(destChainSelector)); + _assertFeeQuoterDestChainConfigsEqual(expectedConfig, s_feeQuoter.getDestChainConfig(destChainSelector)); } } function test_InvalidStalenessThreshold_Revert() public { - PriceRegistry.StaticConfig memory staticConfig = PriceRegistry.StaticConfig({ + FeeQuoter.StaticConfig memory staticConfig = FeeQuoter.StaticConfig({ linkToken: s_sourceTokens[0], maxFeeJuelsPerMsg: MAX_MSG_FEES_JUELS, stalenessThreshold: 0 }); - vm.expectRevert(PriceRegistry.InvalidStaticConfig.selector); + vm.expectRevert(FeeQuoter.InvalidStaticConfig.selector); - s_priceRegistry = new PriceRegistryHelper( + s_feeQuoter = new FeeQuoterHelper( staticConfig, new address[](0), new address[](0), - new PriceRegistry.TokenPriceFeedUpdate[](0), - s_priceRegistryTokenTransferFeeConfigArgs, - s_priceRegistryPremiumMultiplierWeiPerEthArgs, - new PriceRegistry.DestChainConfigArgs[](0) + new FeeQuoter.TokenPriceFeedUpdate[](0), + s_feeQuoterTokenTransferFeeConfigArgs, + s_feeQuoterPremiumMultiplierWeiPerEthArgs, + new FeeQuoter.DestChainConfigArgs[](0) ); } function test_InvalidLinkTokenEqZeroAddress_Revert() public { - PriceRegistry.StaticConfig memory staticConfig = PriceRegistry.StaticConfig({ + FeeQuoter.StaticConfig memory staticConfig = FeeQuoter.StaticConfig({ linkToken: address(0), maxFeeJuelsPerMsg: MAX_MSG_FEES_JUELS, stalenessThreshold: uint32(TWELVE_HOURS) }); - vm.expectRevert(PriceRegistry.InvalidStaticConfig.selector); + vm.expectRevert(FeeQuoter.InvalidStaticConfig.selector); - s_priceRegistry = new PriceRegistryHelper( + s_feeQuoter = new FeeQuoterHelper( staticConfig, new address[](0), new address[](0), - new PriceRegistry.TokenPriceFeedUpdate[](0), - s_priceRegistryTokenTransferFeeConfigArgs, - s_priceRegistryPremiumMultiplierWeiPerEthArgs, - new PriceRegistry.DestChainConfigArgs[](0) + new FeeQuoter.TokenPriceFeedUpdate[](0), + s_feeQuoterTokenTransferFeeConfigArgs, + s_feeQuoterPremiumMultiplierWeiPerEthArgs, + new FeeQuoter.DestChainConfigArgs[](0) ); } function test_InvalidMaxFeeJuelsPerMsg_Revert() public { - PriceRegistry.StaticConfig memory staticConfig = PriceRegistry.StaticConfig({ + FeeQuoter.StaticConfig memory staticConfig = FeeQuoter.StaticConfig({ linkToken: s_sourceTokens[0], maxFeeJuelsPerMsg: 0, stalenessThreshold: uint32(TWELVE_HOURS) }); - vm.expectRevert(PriceRegistry.InvalidStaticConfig.selector); + vm.expectRevert(FeeQuoter.InvalidStaticConfig.selector); - s_priceRegistry = new PriceRegistryHelper( + s_feeQuoter = new FeeQuoterHelper( staticConfig, new address[](0), new address[](0), - new PriceRegistry.TokenPriceFeedUpdate[](0), - s_priceRegistryTokenTransferFeeConfigArgs, - s_priceRegistryPremiumMultiplierWeiPerEthArgs, - new PriceRegistry.DestChainConfigArgs[](0) + new FeeQuoter.TokenPriceFeedUpdate[](0), + s_feeQuoterTokenTransferFeeConfigArgs, + s_feeQuoterPremiumMultiplierWeiPerEthArgs, + new FeeQuoter.DestChainConfigArgs[](0) ); } } -contract PriceRegistry_getTokenPrices is PriceRegistrySetup { +contract FeeQuoter_getTokenPrices is FeeQuoterSetup { function test_GetTokenPrices_Success() public view { Internal.PriceUpdates memory priceUpdates = abi.decode(s_encodedInitialPriceUpdates, (Internal.PriceUpdates)); @@ -159,7 +159,7 @@ contract PriceRegistry_getTokenPrices is PriceRegistrySetup { tokens[1] = s_sourceTokens[1]; tokens[2] = s_weth; - Internal.TimestampedPackedUint224[] memory tokenPrices = s_priceRegistry.getTokenPrices(tokens); + Internal.TimestampedPackedUint224[] memory tokenPrices = s_feeQuoter.getTokenPrices(tokens); assertEq(tokenPrices.length, 3); assertEq(tokenPrices[0].value, priceUpdates.tokenPriceUpdates[0].usdPerToken); @@ -168,7 +168,7 @@ contract PriceRegistry_getTokenPrices is PriceRegistrySetup { } } -contract PriceRegistry_getTokenPrice is PriceRegistrySetup { +contract FeeQuoter_getTokenPrice is FeeQuoterSetup { function test_GetTokenPriceFromFeed_Success() public { uint256 originalTimestampValue = block.timestamp; @@ -176,7 +176,7 @@ contract PriceRegistry_getTokenPrice is PriceRegistrySetup { vm.warp(originalTimestampValue + 1 hours); address sourceToken = _initialiseSingleTokenPriceFeed(); - Internal.TimestampedPackedUint224 memory tokenPriceAnswer = s_priceRegistry.getTokenPrice(sourceToken); + Internal.TimestampedPackedUint224 memory tokenPriceAnswer = s_feeQuoter.getTokenPrice(sourceToken); // Price answer is 1e8 (18 decimal token) - unit is (1e18 * 1e18 / 1e18) -> expected 1e18 assertEq(tokenPriceAnswer.value, uint224(1e18)); @@ -184,12 +184,12 @@ contract PriceRegistry_getTokenPrice is PriceRegistrySetup { } } -contract PriceRegistry_getValidatedTokenPrice is PriceRegistrySetup { +contract FeeQuoter_getValidatedTokenPrice is FeeQuoterSetup { function test_GetValidatedTokenPrice_Success() public view { Internal.PriceUpdates memory priceUpdates = abi.decode(s_encodedInitialPriceUpdates, (Internal.PriceUpdates)); address token = priceUpdates.tokenPriceUpdates[0].sourceToken; - uint224 tokenPrice = s_priceRegistry.getValidatedTokenPrice(token); + uint224 tokenPrice = s_feeQuoter.getValidatedTokenPrice(token); assertEq(priceUpdates.tokenPriceUpdates[0].usdPerToken, tokenPrice); } @@ -201,7 +201,7 @@ contract PriceRegistry_getValidatedTokenPrice is PriceRegistrySetup { vm.warp(originalTimestampValue + TWELVE_HOURS); address sourceToken = _initialiseSingleTokenPriceFeed(); - uint224 tokenPriceAnswer = s_priceRegistry.getValidatedTokenPrice(sourceToken); + uint224 tokenPriceAnswer = s_feeQuoter.getValidatedTokenPrice(sourceToken); // Price answer is 1e8 (18 decimal token) - unit is (1e18 * 1e18 / 1e18) -> expected 1e18 assertEq(tokenPriceAnswer, uint224(1e18)); @@ -214,7 +214,7 @@ contract PriceRegistry_getValidatedTokenPrice is PriceRegistrySetup { vm.warp(originalTimestampValue + TWELVE_HOURS + 1); address sourceToken = _initialiseSingleTokenPriceFeed(); - uint224 tokenPriceAnswer = s_priceRegistry.getValidatedTokenPrice(sourceToken); + uint224 tokenPriceAnswer = s_feeQuoter.getValidatedTokenPrice(sourceToken); // Price answer is 1e8 (18 decimal token) - unit is (1e18 * 1e18 / 1e18) -> expected 1e18 assertEq(tokenPriceAnswer, uint224(1e18)); @@ -224,11 +224,11 @@ contract PriceRegistry_getValidatedTokenPrice is PriceRegistrySetup { address tokenAddress = _deploySourceToken("testToken", 0, 18); address feedAddress = _deployTokenPriceDataFeed(tokenAddress, 18, int256(uint256(type(uint224).max))); - PriceRegistry.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new PriceRegistry.TokenPriceFeedUpdate[](1); + FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](1); tokenPriceFeedUpdates[0] = _getSingleTokenPriceFeedUpdateStruct(tokenAddress, feedAddress, 18); - s_priceRegistry.updateTokenPriceFeeds(tokenPriceFeedUpdates); + s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeedUpdates); - uint224 tokenPriceAnswer = s_priceRegistry.getValidatedTokenPrice(tokenAddress); + uint224 tokenPriceAnswer = s_feeQuoter.getValidatedTokenPrice(tokenAddress); // Price answer is: uint224.MAX_VALUE * (10 ** (36 - 18 - 18)) assertEq(tokenPriceAnswer, uint224(type(uint224).max)); @@ -238,11 +238,11 @@ contract PriceRegistry_getValidatedTokenPrice is PriceRegistrySetup { address tokenAddress = _deploySourceToken("testToken", 0, 6); address feedAddress = _deployTokenPriceDataFeed(tokenAddress, 8, 1e8); - PriceRegistry.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new PriceRegistry.TokenPriceFeedUpdate[](1); + FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](1); tokenPriceFeedUpdates[0] = _getSingleTokenPriceFeedUpdateStruct(tokenAddress, feedAddress, 6); - s_priceRegistry.updateTokenPriceFeeds(tokenPriceFeedUpdates); + s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeedUpdates); - uint224 tokenPriceAnswer = s_priceRegistry.getValidatedTokenPrice(tokenAddress); + uint224 tokenPriceAnswer = s_feeQuoter.getValidatedTokenPrice(tokenAddress); // Price answer is 1e8 (6 decimal token) - unit is (1e18 * 1e18 / 1e6) -> expected 1e30 assertEq(tokenPriceAnswer, uint224(1e30)); @@ -252,11 +252,11 @@ contract PriceRegistry_getValidatedTokenPrice is PriceRegistrySetup { address tokenAddress = _deploySourceToken("testToken", 0, 24); address feedAddress = _deployTokenPriceDataFeed(tokenAddress, 8, 1e8); - PriceRegistry.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new PriceRegistry.TokenPriceFeedUpdate[](1); + FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](1); tokenPriceFeedUpdates[0] = _getSingleTokenPriceFeedUpdateStruct(tokenAddress, feedAddress, 24); - s_priceRegistry.updateTokenPriceFeeds(tokenPriceFeedUpdates); + s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeedUpdates); - uint224 tokenPriceAnswer = s_priceRegistry.getValidatedTokenPrice(tokenAddress); + uint224 tokenPriceAnswer = s_feeQuoter.getValidatedTokenPrice(tokenAddress); // Price answer is 1e8 (6 decimal token) - unit is (1e18 * 1e18 / 1e24) -> expected 1e12 assertEq(tokenPriceAnswer, uint224(1e12)); @@ -266,11 +266,11 @@ contract PriceRegistry_getValidatedTokenPrice is PriceRegistrySetup { address tokenAddress = _deploySourceToken("testToken", 0, 18); address feedAddress = _deployTokenPriceDataFeed(tokenAddress, 18, 1e18); - PriceRegistry.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new PriceRegistry.TokenPriceFeedUpdate[](1); + FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](1); tokenPriceFeedUpdates[0] = _getSingleTokenPriceFeedUpdateStruct(tokenAddress, feedAddress, 18); - s_priceRegistry.updateTokenPriceFeeds(tokenPriceFeedUpdates); + s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeedUpdates); - uint224 tokenPriceAnswer = s_priceRegistry.getValidatedTokenPrice(tokenAddress); + uint224 tokenPriceAnswer = s_feeQuoter.getValidatedTokenPrice(tokenAddress); // Price answer is 1e8 (6 decimal token) - unit is (1e18 * 1e18 / 1e18) -> expected 1e18 assertEq(tokenPriceAnswer, uint224(1e18)); @@ -280,11 +280,11 @@ contract PriceRegistry_getValidatedTokenPrice is PriceRegistrySetup { address tokenAddress = _deploySourceToken("testToken", 0, 0); address feedAddress = _deployTokenPriceDataFeed(tokenAddress, 0, 1e31); - PriceRegistry.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new PriceRegistry.TokenPriceFeedUpdate[](1); + FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](1); tokenPriceFeedUpdates[0] = _getSingleTokenPriceFeedUpdateStruct(tokenAddress, feedAddress, 0); - s_priceRegistry.updateTokenPriceFeeds(tokenPriceFeedUpdates); + s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeedUpdates); - uint224 tokenPriceAnswer = s_priceRegistry.getValidatedTokenPrice(tokenAddress); + uint224 tokenPriceAnswer = s_feeQuoter.getValidatedTokenPrice(tokenAddress); // Price answer is 1e31 (0 decimal token) - unit is (1e18 * 1e18 / 1e0) -> expected 1e36 assertEq(tokenPriceAnswer, uint224(1e67)); @@ -294,11 +294,11 @@ contract PriceRegistry_getValidatedTokenPrice is PriceRegistrySetup { address tokenAddress = _deploySourceToken("testToken", 0, 20); address feedAddress = _deployTokenPriceDataFeed(tokenAddress, 20, 1e18); - PriceRegistry.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new PriceRegistry.TokenPriceFeedUpdate[](1); + FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](1); tokenPriceFeedUpdates[0] = _getSingleTokenPriceFeedUpdateStruct(tokenAddress, feedAddress, 20); - s_priceRegistry.updateTokenPriceFeeds(tokenPriceFeedUpdates); + s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeedUpdates); - uint224 tokenPriceAnswer = s_priceRegistry.getValidatedTokenPrice(tokenAddress); + uint224 tokenPriceAnswer = s_feeQuoter.getValidatedTokenPrice(tokenAddress); // Price answer is 1e8 (6 decimal token) - unit is (1e18 * 1e18 / 1e20) -> expected 1e14 assertEq(tokenPriceAnswer, uint224(1e14)); @@ -310,7 +310,7 @@ contract PriceRegistry_getValidatedTokenPrice is PriceRegistrySetup { Internal.PriceUpdates memory priceUpdates = abi.decode(s_encodedInitialPriceUpdates, (Internal.PriceUpdates)); address token = priceUpdates.tokenPriceUpdates[0].sourceToken; - uint224 tokenPrice = s_priceRegistry.getValidatedTokenPrice(token); + uint224 tokenPrice = s_feeQuoter.getValidatedTokenPrice(token); assertEq(priceUpdates.tokenPriceUpdates[0].usdPerToken, tokenPrice); } @@ -321,66 +321,66 @@ contract PriceRegistry_getValidatedTokenPrice is PriceRegistrySetup { address tokenAddress = _deploySourceToken("testToken", 0, 18); address feedAddress = _deployTokenPriceDataFeed(tokenAddress, 18, int256(uint256(type(uint224).max) + 1)); - PriceRegistry.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new PriceRegistry.TokenPriceFeedUpdate[](1); + FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](1); tokenPriceFeedUpdates[0] = _getSingleTokenPriceFeedUpdateStruct(tokenAddress, feedAddress, 18); - s_priceRegistry.updateTokenPriceFeeds(tokenPriceFeedUpdates); + s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeedUpdates); - vm.expectRevert(PriceRegistry.DataFeedValueOutOfUint224Range.selector); - s_priceRegistry.getValidatedTokenPrice(tokenAddress); + vm.expectRevert(FeeQuoter.DataFeedValueOutOfUint224Range.selector); + s_feeQuoter.getValidatedTokenPrice(tokenAddress); } function test_UnderflowFeedPrice_Revert() public { address tokenAddress = _deploySourceToken("testToken", 0, 18); address feedAddress = _deployTokenPriceDataFeed(tokenAddress, 18, -1); - PriceRegistry.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new PriceRegistry.TokenPriceFeedUpdate[](1); + FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](1); tokenPriceFeedUpdates[0] = _getSingleTokenPriceFeedUpdateStruct(tokenAddress, feedAddress, 18); - s_priceRegistry.updateTokenPriceFeeds(tokenPriceFeedUpdates); + s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeedUpdates); - vm.expectRevert(PriceRegistry.DataFeedValueOutOfUint224Range.selector); - s_priceRegistry.getValidatedTokenPrice(tokenAddress); + vm.expectRevert(FeeQuoter.DataFeedValueOutOfUint224Range.selector); + s_feeQuoter.getValidatedTokenPrice(tokenAddress); } function test_TokenNotSupported_Revert() public { - vm.expectRevert(abi.encodeWithSelector(PriceRegistry.TokenNotSupported.selector, DUMMY_CONTRACT_ADDRESS)); - s_priceRegistry.getValidatedTokenPrice(DUMMY_CONTRACT_ADDRESS); + vm.expectRevert(abi.encodeWithSelector(FeeQuoter.TokenNotSupported.selector, DUMMY_CONTRACT_ADDRESS)); + s_feeQuoter.getValidatedTokenPrice(DUMMY_CONTRACT_ADDRESS); } function test_TokenNotSupportedFeed_Revert() public { address sourceToken = _initialiseSingleTokenPriceFeed(); MockV3Aggregator(s_dataFeedByToken[sourceToken]).updateAnswer(0); - vm.expectRevert(abi.encodeWithSelector(PriceRegistry.TokenNotSupported.selector, sourceToken)); - s_priceRegistry.getValidatedTokenPrice(sourceToken); + vm.expectRevert(abi.encodeWithSelector(FeeQuoter.TokenNotSupported.selector, sourceToken)); + s_feeQuoter.getValidatedTokenPrice(sourceToken); } } -contract PriceRegistry_applyFeeTokensUpdates is PriceRegistrySetup { +contract FeeQuoter_applyFeeTokensUpdates is FeeQuoterSetup { function test_ApplyFeeTokensUpdates_Success() public { address[] memory feeTokens = new address[](1); feeTokens[0] = s_sourceTokens[1]; vm.expectEmit(); - emit PriceRegistry.FeeTokenAdded(feeTokens[0]); + emit FeeQuoter.FeeTokenAdded(feeTokens[0]); - s_priceRegistry.applyFeeTokensUpdates(feeTokens, new address[](0)); - assertEq(s_priceRegistry.getFeeTokens().length, 3); - assertEq(s_priceRegistry.getFeeTokens()[2], feeTokens[0]); + s_feeQuoter.applyFeeTokensUpdates(feeTokens, new address[](0)); + assertEq(s_feeQuoter.getFeeTokens().length, 3); + assertEq(s_feeQuoter.getFeeTokens()[2], feeTokens[0]); // add same feeToken is no-op - s_priceRegistry.applyFeeTokensUpdates(feeTokens, new address[](0)); - assertEq(s_priceRegistry.getFeeTokens().length, 3); - assertEq(s_priceRegistry.getFeeTokens()[2], feeTokens[0]); + s_feeQuoter.applyFeeTokensUpdates(feeTokens, new address[](0)); + assertEq(s_feeQuoter.getFeeTokens().length, 3); + assertEq(s_feeQuoter.getFeeTokens()[2], feeTokens[0]); vm.expectEmit(); - emit PriceRegistry.FeeTokenRemoved(feeTokens[0]); + emit FeeQuoter.FeeTokenRemoved(feeTokens[0]); - s_priceRegistry.applyFeeTokensUpdates(new address[](0), feeTokens); - assertEq(s_priceRegistry.getFeeTokens().length, 2); + s_feeQuoter.applyFeeTokensUpdates(new address[](0), feeTokens); + assertEq(s_feeQuoter.getFeeTokens().length, 2); // removing already removed feeToken is no-op - s_priceRegistry.applyFeeTokensUpdates(new address[](0), feeTokens); - assertEq(s_priceRegistry.getFeeTokens().length, 2); + s_feeQuoter.applyFeeTokensUpdates(new address[](0), feeTokens); + assertEq(s_feeQuoter.getFeeTokens().length, 2); } function test_OnlyCallableByOwner_Revert() public { @@ -388,11 +388,11 @@ contract PriceRegistry_applyFeeTokensUpdates is PriceRegistrySetup { feeTokens[0] = STRANGER; vm.startPrank(STRANGER); vm.expectRevert("Only callable by owner"); - s_priceRegistry.applyFeeTokensUpdates(feeTokens, new address[](0)); + s_feeQuoter.applyFeeTokensUpdates(feeTokens, new address[](0)); } } -contract PriceRegistry_updatePrices is PriceRegistrySetup { +contract FeeQuoter_updatePrices is FeeQuoterSetup { function test_OnlyTokenPrice_Success() public { Internal.PriceUpdates memory update = Internal.PriceUpdates({ tokenPriceUpdates: new Internal.TokenPriceUpdate[](1), @@ -401,13 +401,13 @@ contract PriceRegistry_updatePrices is PriceRegistrySetup { update.tokenPriceUpdates[0] = Internal.TokenPriceUpdate({sourceToken: s_sourceTokens[0], usdPerToken: 4e18}); vm.expectEmit(); - emit PriceRegistry.UsdPerTokenUpdated( + emit FeeQuoter.UsdPerTokenUpdated( update.tokenPriceUpdates[0].sourceToken, update.tokenPriceUpdates[0].usdPerToken, block.timestamp ); - s_priceRegistry.updatePrices(update); + s_feeQuoter.updatePrices(update); - assertEq(s_priceRegistry.getTokenPrice(s_sourceTokens[0]).value, update.tokenPriceUpdates[0].usdPerToken); + assertEq(s_feeQuoter.getTokenPrice(s_sourceTokens[0]).value, update.tokenPriceUpdates[0].usdPerToken); } function test_OnlyGasPrice_Success() public { @@ -419,14 +419,14 @@ contract PriceRegistry_updatePrices is PriceRegistrySetup { Internal.GasPriceUpdate({destChainSelector: DEST_CHAIN_SELECTOR, usdPerUnitGas: 2000e18}); vm.expectEmit(); - emit PriceRegistry.UsdPerUnitGasUpdated( + emit FeeQuoter.UsdPerUnitGasUpdated( update.gasPriceUpdates[0].destChainSelector, update.gasPriceUpdates[0].usdPerUnitGas, block.timestamp ); - s_priceRegistry.updatePrices(update); + s_feeQuoter.updatePrices(update); assertEq( - s_priceRegistry.getDestinationChainGasPrice(DEST_CHAIN_SELECTOR).value, update.gasPriceUpdates[0].usdPerUnitGas + s_feeQuoter.getDestinationChainGasPrice(DEST_CHAIN_SELECTOR).value, update.gasPriceUpdates[0].usdPerUnitGas ); } @@ -446,27 +446,27 @@ contract PriceRegistry_updatePrices is PriceRegistrySetup { for (uint256 i = 0; i < tokenPriceUpdates.length; ++i) { vm.expectEmit(); - emit PriceRegistry.UsdPerTokenUpdated( + emit FeeQuoter.UsdPerTokenUpdated( update.tokenPriceUpdates[i].sourceToken, update.tokenPriceUpdates[i].usdPerToken, block.timestamp ); } for (uint256 i = 0; i < gasPriceUpdates.length; ++i) { vm.expectEmit(); - emit PriceRegistry.UsdPerUnitGasUpdated( + emit FeeQuoter.UsdPerUnitGasUpdated( update.gasPriceUpdates[i].destChainSelector, update.gasPriceUpdates[i].usdPerUnitGas, block.timestamp ); } - s_priceRegistry.updatePrices(update); + s_feeQuoter.updatePrices(update); for (uint256 i = 0; i < tokenPriceUpdates.length; ++i) { assertEq( - s_priceRegistry.getTokenPrice(update.tokenPriceUpdates[i].sourceToken).value, tokenPriceUpdates[i].usdPerToken + s_feeQuoter.getTokenPrice(update.tokenPriceUpdates[i].sourceToken).value, tokenPriceUpdates[i].usdPerToken ); } for (uint256 i = 0; i < gasPriceUpdates.length; ++i) { assertEq( - s_priceRegistry.getDestinationChainGasPrice(update.gasPriceUpdates[i].destChainSelector).value, + s_feeQuoter.getDestinationChainGasPrice(update.gasPriceUpdates[i].destChainSelector).value, gasPriceUpdates[i].usdPerUnitGas ); } @@ -482,33 +482,33 @@ contract PriceRegistry_updatePrices is PriceRegistrySetup { // Revert when caller is not authorized vm.startPrank(STRANGER); vm.expectRevert(abi.encodeWithSelector(AuthorizedCallers.UnauthorizedCaller.selector, STRANGER)); - s_priceRegistry.updatePrices(priceUpdates); + s_feeQuoter.updatePrices(priceUpdates); address[] memory priceUpdaters = new address[](1); priceUpdaters[0] = STRANGER; vm.startPrank(OWNER); - s_priceRegistry.applyAuthorizedCallerUpdates( + s_feeQuoter.applyAuthorizedCallerUpdates( AuthorizedCallers.AuthorizedCallerArgs({addedCallers: priceUpdaters, removedCallers: new address[](0)}) ); // Stranger is now an authorized caller to update prices vm.expectEmit(); - emit PriceRegistry.UsdPerTokenUpdated( + emit FeeQuoter.UsdPerTokenUpdated( priceUpdates.tokenPriceUpdates[0].sourceToken, priceUpdates.tokenPriceUpdates[0].usdPerToken, block.timestamp ); - s_priceRegistry.updatePrices(priceUpdates); + s_feeQuoter.updatePrices(priceUpdates); - assertEq(s_priceRegistry.getTokenPrice(s_sourceTokens[0]).value, priceUpdates.tokenPriceUpdates[0].usdPerToken); + assertEq(s_feeQuoter.getTokenPrice(s_sourceTokens[0]).value, priceUpdates.tokenPriceUpdates[0].usdPerToken); vm.startPrank(OWNER); - s_priceRegistry.applyAuthorizedCallerUpdates( + s_feeQuoter.applyAuthorizedCallerUpdates( AuthorizedCallers.AuthorizedCallerArgs({addedCallers: new address[](0), removedCallers: priceUpdaters}) ); // Revert when authorized caller is removed vm.startPrank(STRANGER); vm.expectRevert(abi.encodeWithSelector(AuthorizedCallers.UnauthorizedCaller.selector, STRANGER)); - s_priceRegistry.updatePrices(priceUpdates); + s_feeQuoter.updatePrices(priceUpdates); } // Reverts @@ -521,18 +521,18 @@ contract PriceRegistry_updatePrices is PriceRegistrySetup { vm.startPrank(STRANGER); vm.expectRevert(abi.encodeWithSelector(AuthorizedCallers.UnauthorizedCaller.selector, STRANGER)); - s_priceRegistry.updatePrices(priceUpdates); + s_feeQuoter.updatePrices(priceUpdates); } } -contract PriceRegistry_convertTokenAmount is PriceRegistrySetup { +contract FeeQuoter_convertTokenAmount is FeeQuoterSetup { function test_ConvertTokenAmount_Success() public view { Internal.PriceUpdates memory initialPriceUpdates = abi.decode(s_encodedInitialPriceUpdates, (Internal.PriceUpdates)); uint256 amount = 3e16; uint256 conversionRate = (uint256(initialPriceUpdates.tokenPriceUpdates[2].usdPerToken) * 1e18) / uint256(initialPriceUpdates.tokenPriceUpdates[0].usdPerToken); uint256 expected = (amount * conversionRate) / 1e18; - assertEq(s_priceRegistry.convertTokenAmount(s_weth, amount, s_sourceTokens[0]), expected); + assertEq(s_feeQuoter.convertTokenAmount(s_weth, amount, s_sourceTokens[0]), expected); } function test_Fuzz_ConvertTokenAmount_Success( @@ -550,7 +550,7 @@ contract PriceRegistry_convertTokenAmount is PriceRegistrySetup { address linkToken = address(2); address[] memory feeTokens = new address[](1); feeTokens[0] = feeToken; - s_priceRegistry.applyFeeTokensUpdates(feeTokens, new address[](0)); + s_feeQuoter.applyFeeTokensUpdates(feeTokens, new address[](0)); Internal.TokenPriceUpdate[] memory tokenPriceUpdates = new Internal.TokenPriceUpdate[](2); tokenPriceUpdates[0] = Internal.TokenPriceUpdate({sourceToken: feeToken, usdPerToken: usdPerFeeToken}); @@ -562,27 +562,26 @@ contract PriceRegistry_convertTokenAmount is PriceRegistrySetup { Internal.PriceUpdates memory priceUpdates = Internal.PriceUpdates({tokenPriceUpdates: tokenPriceUpdates, gasPriceUpdates: gasPriceUpdates}); - s_priceRegistry.updatePrices(priceUpdates); + s_feeQuoter.updatePrices(priceUpdates); - uint256 linkFee = s_priceRegistry.convertTokenAmount(feeToken, feeTokenAmount, linkToken); + uint256 linkFee = s_feeQuoter.convertTokenAmount(feeToken, feeTokenAmount, linkToken); assertEq(linkFee, (feeTokenAmount * usdPerFeeToken) / usdPerLinkToken); } // Reverts function test_LinkTokenNotSupported_Revert() public { - vm.expectRevert(abi.encodeWithSelector(PriceRegistry.TokenNotSupported.selector, DUMMY_CONTRACT_ADDRESS)); - s_priceRegistry.convertTokenAmount(DUMMY_CONTRACT_ADDRESS, 3e16, s_sourceTokens[0]); + vm.expectRevert(abi.encodeWithSelector(FeeQuoter.TokenNotSupported.selector, DUMMY_CONTRACT_ADDRESS)); + s_feeQuoter.convertTokenAmount(DUMMY_CONTRACT_ADDRESS, 3e16, s_sourceTokens[0]); - vm.expectRevert(abi.encodeWithSelector(PriceRegistry.TokenNotSupported.selector, DUMMY_CONTRACT_ADDRESS)); - s_priceRegistry.convertTokenAmount(s_sourceTokens[0], 3e16, DUMMY_CONTRACT_ADDRESS); + vm.expectRevert(abi.encodeWithSelector(FeeQuoter.TokenNotSupported.selector, DUMMY_CONTRACT_ADDRESS)); + s_feeQuoter.convertTokenAmount(s_sourceTokens[0], 3e16, DUMMY_CONTRACT_ADDRESS); } } -contract PriceRegistry_getTokenAndGasPrices is PriceRegistrySetup { +contract FeeQuoter_getTokenAndGasPrices is FeeQuoterSetup { function test_GetFeeTokenAndGasPrices_Success() public view { - (uint224 feeTokenPrice, uint224 gasPrice) = - s_priceRegistry.getTokenAndGasPrices(s_sourceFeeToken, DEST_CHAIN_SELECTOR); + (uint224 feeTokenPrice, uint224 gasPrice) = s_feeQuoter.getTokenAndGasPrices(s_sourceFeeToken, DEST_CHAIN_SELECTOR); Internal.PriceUpdates memory priceUpdates = abi.decode(s_encodedInitialPriceUpdates, (Internal.PriceUpdates)); @@ -597,148 +596,136 @@ contract PriceRegistry_getTokenAndGasPrices is PriceRegistrySetup { Internal.PriceUpdates memory priceUpdates = Internal.PriceUpdates({tokenPriceUpdates: new Internal.TokenPriceUpdate[](0), gasPriceUpdates: gasPriceUpdates}); - s_priceRegistry.updatePrices(priceUpdates); + s_feeQuoter.updatePrices(priceUpdates); - (, uint224 gasPrice) = s_priceRegistry.getTokenAndGasPrices(s_sourceFeeToken, zeroGasDestChainSelector); + (, uint224 gasPrice) = s_feeQuoter.getTokenAndGasPrices(s_sourceFeeToken, zeroGasDestChainSelector); assertEq(gasPrice, priceUpdates.gasPriceUpdates[0].usdPerUnitGas); } function test_UnsupportedChain_Revert() public { - vm.expectRevert(abi.encodeWithSelector(PriceRegistry.ChainNotSupported.selector, DEST_CHAIN_SELECTOR + 1)); - s_priceRegistry.getTokenAndGasPrices(s_sourceTokens[0], DEST_CHAIN_SELECTOR + 1); + vm.expectRevert(abi.encodeWithSelector(FeeQuoter.ChainNotSupported.selector, DEST_CHAIN_SELECTOR + 1)); + s_feeQuoter.getTokenAndGasPrices(s_sourceTokens[0], DEST_CHAIN_SELECTOR + 1); } function test_StaleGasPrice_Revert() public { uint256 diff = TWELVE_HOURS + 1; vm.warp(block.timestamp + diff); - vm.expectRevert( - abi.encodeWithSelector(PriceRegistry.StaleGasPrice.selector, DEST_CHAIN_SELECTOR, TWELVE_HOURS, diff) - ); - s_priceRegistry.getTokenAndGasPrices(s_sourceTokens[0], DEST_CHAIN_SELECTOR); + vm.expectRevert(abi.encodeWithSelector(FeeQuoter.StaleGasPrice.selector, DEST_CHAIN_SELECTOR, TWELVE_HOURS, diff)); + s_feeQuoter.getTokenAndGasPrices(s_sourceTokens[0], DEST_CHAIN_SELECTOR); } } -contract PriceRegistry_updateTokenPriceFeeds is PriceRegistrySetup { +contract FeeQuoter_updateTokenPriceFeeds is FeeQuoterSetup { function test_ZeroFeeds_Success() public { Vm.Log[] memory logEntries = vm.getRecordedLogs(); - PriceRegistry.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new PriceRegistry.TokenPriceFeedUpdate[](0); + FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](0); vm.recordLogs(); - s_priceRegistry.updateTokenPriceFeeds(tokenPriceFeedUpdates); + s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeedUpdates); // Verify no log emissions assertEq(logEntries.length, 0); } function test_SingleFeedUpdate_Success() public { - PriceRegistry.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new PriceRegistry.TokenPriceFeedUpdate[](1); + FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](1); tokenPriceFeedUpdates[0] = _getSingleTokenPriceFeedUpdateStruct(s_sourceTokens[0], s_dataFeedByToken[s_sourceTokens[0]], 18); - _assertTokenPriceFeedConfigUnconfigured( - s_priceRegistry.getTokenPriceFeedConfig(tokenPriceFeedUpdates[0].sourceToken) - ); + _assertTokenPriceFeedConfigUnconfigured(s_feeQuoter.getTokenPriceFeedConfig(tokenPriceFeedUpdates[0].sourceToken)); vm.expectEmit(); - emit PriceRegistry.PriceFeedPerTokenUpdated( - tokenPriceFeedUpdates[0].sourceToken, tokenPriceFeedUpdates[0].feedConfig - ); + emit FeeQuoter.PriceFeedPerTokenUpdated(tokenPriceFeedUpdates[0].sourceToken, tokenPriceFeedUpdates[0].feedConfig); - s_priceRegistry.updateTokenPriceFeeds(tokenPriceFeedUpdates); + s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeedUpdates); _assertTokenPriceFeedConfigEquality( - s_priceRegistry.getTokenPriceFeedConfig(tokenPriceFeedUpdates[0].sourceToken), tokenPriceFeedUpdates[0].feedConfig + s_feeQuoter.getTokenPriceFeedConfig(tokenPriceFeedUpdates[0].sourceToken), tokenPriceFeedUpdates[0].feedConfig ); } function test_MultipleFeedUpdate_Success() public { - PriceRegistry.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new PriceRegistry.TokenPriceFeedUpdate[](2); + FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](2); for (uint256 i = 0; i < 2; ++i) { tokenPriceFeedUpdates[i] = _getSingleTokenPriceFeedUpdateStruct(s_sourceTokens[i], s_dataFeedByToken[s_sourceTokens[i]], 18); - _assertTokenPriceFeedConfigUnconfigured( - s_priceRegistry.getTokenPriceFeedConfig(tokenPriceFeedUpdates[i].sourceToken) - ); + _assertTokenPriceFeedConfigUnconfigured(s_feeQuoter.getTokenPriceFeedConfig(tokenPriceFeedUpdates[i].sourceToken)); vm.expectEmit(); - emit PriceRegistry.PriceFeedPerTokenUpdated( - tokenPriceFeedUpdates[i].sourceToken, tokenPriceFeedUpdates[i].feedConfig - ); + emit FeeQuoter.PriceFeedPerTokenUpdated(tokenPriceFeedUpdates[i].sourceToken, tokenPriceFeedUpdates[i].feedConfig); } - s_priceRegistry.updateTokenPriceFeeds(tokenPriceFeedUpdates); + s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeedUpdates); _assertTokenPriceFeedConfigEquality( - s_priceRegistry.getTokenPriceFeedConfig(tokenPriceFeedUpdates[0].sourceToken), tokenPriceFeedUpdates[0].feedConfig + s_feeQuoter.getTokenPriceFeedConfig(tokenPriceFeedUpdates[0].sourceToken), tokenPriceFeedUpdates[0].feedConfig ); _assertTokenPriceFeedConfigEquality( - s_priceRegistry.getTokenPriceFeedConfig(tokenPriceFeedUpdates[1].sourceToken), tokenPriceFeedUpdates[1].feedConfig + s_feeQuoter.getTokenPriceFeedConfig(tokenPriceFeedUpdates[1].sourceToken), tokenPriceFeedUpdates[1].feedConfig ); } function test_FeedUnset_Success() public { - Internal.TimestampedPackedUint224 memory priceQueryInitial = s_priceRegistry.getTokenPrice(s_sourceTokens[0]); + Internal.TimestampedPackedUint224 memory priceQueryInitial = s_feeQuoter.getTokenPrice(s_sourceTokens[0]); assertFalse(priceQueryInitial.value == 0); assertFalse(priceQueryInitial.timestamp == 0); - PriceRegistry.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new PriceRegistry.TokenPriceFeedUpdate[](1); + FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](1); tokenPriceFeedUpdates[0] = _getSingleTokenPriceFeedUpdateStruct(s_sourceTokens[0], s_dataFeedByToken[s_sourceTokens[0]], 18); - s_priceRegistry.updateTokenPriceFeeds(tokenPriceFeedUpdates); + s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeedUpdates); _assertTokenPriceFeedConfigEquality( - s_priceRegistry.getTokenPriceFeedConfig(tokenPriceFeedUpdates[0].sourceToken), tokenPriceFeedUpdates[0].feedConfig + s_feeQuoter.getTokenPriceFeedConfig(tokenPriceFeedUpdates[0].sourceToken), tokenPriceFeedUpdates[0].feedConfig ); tokenPriceFeedUpdates[0].feedConfig.dataFeedAddress = address(0); vm.expectEmit(); - emit PriceRegistry.PriceFeedPerTokenUpdated( - tokenPriceFeedUpdates[0].sourceToken, tokenPriceFeedUpdates[0].feedConfig - ); + emit FeeQuoter.PriceFeedPerTokenUpdated(tokenPriceFeedUpdates[0].sourceToken, tokenPriceFeedUpdates[0].feedConfig); - s_priceRegistry.updateTokenPriceFeeds(tokenPriceFeedUpdates); + s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeedUpdates); _assertTokenPriceFeedConfigEquality( - s_priceRegistry.getTokenPriceFeedConfig(tokenPriceFeedUpdates[0].sourceToken), tokenPriceFeedUpdates[0].feedConfig + s_feeQuoter.getTokenPriceFeedConfig(tokenPriceFeedUpdates[0].sourceToken), tokenPriceFeedUpdates[0].feedConfig ); // Price data should remain after a feed has been set->unset - Internal.TimestampedPackedUint224 memory priceQueryPostUnsetFeed = s_priceRegistry.getTokenPrice(s_sourceTokens[0]); + Internal.TimestampedPackedUint224 memory priceQueryPostUnsetFeed = s_feeQuoter.getTokenPrice(s_sourceTokens[0]); assertEq(priceQueryPostUnsetFeed.value, priceQueryInitial.value); assertEq(priceQueryPostUnsetFeed.timestamp, priceQueryInitial.timestamp); } function test_FeedNotUpdated() public { - PriceRegistry.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new PriceRegistry.TokenPriceFeedUpdate[](1); + FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](1); tokenPriceFeedUpdates[0] = _getSingleTokenPriceFeedUpdateStruct(s_sourceTokens[0], s_dataFeedByToken[s_sourceTokens[0]], 18); - s_priceRegistry.updateTokenPriceFeeds(tokenPriceFeedUpdates); - s_priceRegistry.updateTokenPriceFeeds(tokenPriceFeedUpdates); + s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeedUpdates); + s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeedUpdates); _assertTokenPriceFeedConfigEquality( - s_priceRegistry.getTokenPriceFeedConfig(tokenPriceFeedUpdates[0].sourceToken), tokenPriceFeedUpdates[0].feedConfig + s_feeQuoter.getTokenPriceFeedConfig(tokenPriceFeedUpdates[0].sourceToken), tokenPriceFeedUpdates[0].feedConfig ); } // Reverts function test_FeedUpdatedByNonOwner_Revert() public { - PriceRegistry.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new PriceRegistry.TokenPriceFeedUpdate[](1); + FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](1); tokenPriceFeedUpdates[0] = _getSingleTokenPriceFeedUpdateStruct(s_sourceTokens[0], s_dataFeedByToken[s_sourceTokens[0]], 18); vm.startPrank(STRANGER); vm.expectRevert("Only callable by owner"); - s_priceRegistry.updateTokenPriceFeeds(tokenPriceFeedUpdates); + s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeedUpdates); } } -contract PriceRegistry_applyDestChainConfigUpdates is PriceRegistrySetup { - function test_Fuzz_applyDestChainConfigUpdates_Success(PriceRegistry.DestChainConfigArgs memory destChainConfigArgs) +contract FeeQuoter_applyDestChainConfigUpdates is FeeQuoterSetup { + function test_Fuzz_applyDestChainConfigUpdates_Success(FeeQuoter.DestChainConfigArgs memory destChainConfigArgs) public { vm.assume(destChainConfigArgs.destChainSelector != 0); @@ -752,55 +739,52 @@ contract PriceRegistry_applyDestChainConfigUpdates is PriceRegistrySetup { bool isNewChain = destChainConfigArgs.destChainSelector != DEST_CHAIN_SELECTOR; - PriceRegistry.DestChainConfigArgs[] memory newDestChainConfigArgs = new PriceRegistry.DestChainConfigArgs[](1); + FeeQuoter.DestChainConfigArgs[] memory newDestChainConfigArgs = new FeeQuoter.DestChainConfigArgs[](1); newDestChainConfigArgs[0] = destChainConfigArgs; if (isNewChain) { vm.expectEmit(); - emit PriceRegistry.DestChainAdded(destChainConfigArgs.destChainSelector, destChainConfigArgs.destChainConfig); + emit FeeQuoter.DestChainAdded(destChainConfigArgs.destChainSelector, destChainConfigArgs.destChainConfig); } else { vm.expectEmit(); - emit PriceRegistry.DestChainConfigUpdated( - destChainConfigArgs.destChainSelector, destChainConfigArgs.destChainConfig - ); + emit FeeQuoter.DestChainConfigUpdated(destChainConfigArgs.destChainSelector, destChainConfigArgs.destChainConfig); } - s_priceRegistry.applyDestChainConfigUpdates(newDestChainConfigArgs); + s_feeQuoter.applyDestChainConfigUpdates(newDestChainConfigArgs); - _assertPriceRegistryDestChainConfigsEqual( - destChainConfigArgs.destChainConfig, s_priceRegistry.getDestChainConfig(destChainConfigArgs.destChainSelector) + _assertFeeQuoterDestChainConfigsEqual( + destChainConfigArgs.destChainConfig, s_feeQuoter.getDestChainConfig(destChainConfigArgs.destChainSelector) ); } function test_applyDestChainConfigUpdates_Success() public { - PriceRegistry.DestChainConfigArgs[] memory destChainConfigArgs = new PriceRegistry.DestChainConfigArgs[](2); - destChainConfigArgs[0] = _generatePriceRegistryDestChainConfigArgs()[0]; + FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = new FeeQuoter.DestChainConfigArgs[](2); + destChainConfigArgs[0] = _generateFeeQuoterDestChainConfigArgs()[0]; destChainConfigArgs[0].destChainConfig.isEnabled = false; - destChainConfigArgs[1] = _generatePriceRegistryDestChainConfigArgs()[0]; + destChainConfigArgs[1] = _generateFeeQuoterDestChainConfigArgs()[0]; destChainConfigArgs[1].destChainSelector = DEST_CHAIN_SELECTOR + 1; vm.expectEmit(); - emit PriceRegistry.DestChainConfigUpdated(DEST_CHAIN_SELECTOR, destChainConfigArgs[0].destChainConfig); + emit FeeQuoter.DestChainConfigUpdated(DEST_CHAIN_SELECTOR, destChainConfigArgs[0].destChainConfig); vm.expectEmit(); - emit PriceRegistry.DestChainAdded(DEST_CHAIN_SELECTOR + 1, destChainConfigArgs[1].destChainConfig); + emit FeeQuoter.DestChainAdded(DEST_CHAIN_SELECTOR + 1, destChainConfigArgs[1].destChainConfig); vm.recordLogs(); - s_priceRegistry.applyDestChainConfigUpdates(destChainConfigArgs); + s_feeQuoter.applyDestChainConfigUpdates(destChainConfigArgs); - PriceRegistry.DestChainConfig memory gotDestChainConfig0 = s_priceRegistry.getDestChainConfig(DEST_CHAIN_SELECTOR); - PriceRegistry.DestChainConfig memory gotDestChainConfig1 = - s_priceRegistry.getDestChainConfig(DEST_CHAIN_SELECTOR + 1); + FeeQuoter.DestChainConfig memory gotDestChainConfig0 = s_feeQuoter.getDestChainConfig(DEST_CHAIN_SELECTOR); + FeeQuoter.DestChainConfig memory gotDestChainConfig1 = s_feeQuoter.getDestChainConfig(DEST_CHAIN_SELECTOR + 1); assertEq(vm.getRecordedLogs().length, 2); - _assertPriceRegistryDestChainConfigsEqual(destChainConfigArgs[0].destChainConfig, gotDestChainConfig0); - _assertPriceRegistryDestChainConfigsEqual(destChainConfigArgs[1].destChainConfig, gotDestChainConfig1); + _assertFeeQuoterDestChainConfigsEqual(destChainConfigArgs[0].destChainConfig, gotDestChainConfig0); + _assertFeeQuoterDestChainConfigsEqual(destChainConfigArgs[1].destChainConfig, gotDestChainConfig1); } function test_applyDestChainConfigUpdatesZeroIntput_Success() public { - PriceRegistry.DestChainConfigArgs[] memory destChainConfigArgs = new PriceRegistry.DestChainConfigArgs[](0); + FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = new FeeQuoter.DestChainConfigArgs[](0); vm.recordLogs(); - s_priceRegistry.applyDestChainConfigUpdates(destChainConfigArgs); + s_feeQuoter.applyDestChainConfigUpdates(destChainConfigArgs); assertEq(vm.getRecordedLogs().length, 0); } @@ -808,62 +792,62 @@ contract PriceRegistry_applyDestChainConfigUpdates is PriceRegistrySetup { // Reverts function test_applyDestChainConfigUpdatesDefaultTxGasLimitEqZero_Revert() public { - PriceRegistry.DestChainConfigArgs[] memory destChainConfigArgs = _generatePriceRegistryDestChainConfigArgs(); - PriceRegistry.DestChainConfigArgs memory destChainConfigArg = destChainConfigArgs[0]; + FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = _generateFeeQuoterDestChainConfigArgs(); + FeeQuoter.DestChainConfigArgs memory destChainConfigArg = destChainConfigArgs[0]; destChainConfigArg.destChainConfig.defaultTxGasLimit = 0; vm.expectRevert( - abi.encodeWithSelector(PriceRegistry.InvalidDestChainConfig.selector, destChainConfigArg.destChainSelector) + abi.encodeWithSelector(FeeQuoter.InvalidDestChainConfig.selector, destChainConfigArg.destChainSelector) ); - s_priceRegistry.applyDestChainConfigUpdates(destChainConfigArgs); + s_feeQuoter.applyDestChainConfigUpdates(destChainConfigArgs); } function test_applyDestChainConfigUpdatesDefaultTxGasLimitGtMaxPerMessageGasLimit_Revert() public { - PriceRegistry.DestChainConfigArgs[] memory destChainConfigArgs = _generatePriceRegistryDestChainConfigArgs(); - PriceRegistry.DestChainConfigArgs memory destChainConfigArg = destChainConfigArgs[0]; + FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = _generateFeeQuoterDestChainConfigArgs(); + FeeQuoter.DestChainConfigArgs memory destChainConfigArg = destChainConfigArgs[0]; // Allow setting to the max value destChainConfigArg.destChainConfig.defaultTxGasLimit = destChainConfigArg.destChainConfig.maxPerMsgGasLimit; - s_priceRegistry.applyDestChainConfigUpdates(destChainConfigArgs); + s_feeQuoter.applyDestChainConfigUpdates(destChainConfigArgs); // Revert when exceeding max value destChainConfigArg.destChainConfig.defaultTxGasLimit = destChainConfigArg.destChainConfig.maxPerMsgGasLimit + 1; vm.expectRevert( - abi.encodeWithSelector(PriceRegistry.InvalidDestChainConfig.selector, destChainConfigArg.destChainSelector) + abi.encodeWithSelector(FeeQuoter.InvalidDestChainConfig.selector, destChainConfigArg.destChainSelector) ); - s_priceRegistry.applyDestChainConfigUpdates(destChainConfigArgs); + s_feeQuoter.applyDestChainConfigUpdates(destChainConfigArgs); } function test_InvalidDestChainConfigDestChainSelectorEqZero_Revert() public { - PriceRegistry.DestChainConfigArgs[] memory destChainConfigArgs = _generatePriceRegistryDestChainConfigArgs(); - PriceRegistry.DestChainConfigArgs memory destChainConfigArg = destChainConfigArgs[0]; + FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = _generateFeeQuoterDestChainConfigArgs(); + FeeQuoter.DestChainConfigArgs memory destChainConfigArg = destChainConfigArgs[0]; destChainConfigArg.destChainSelector = 0; vm.expectRevert( - abi.encodeWithSelector(PriceRegistry.InvalidDestChainConfig.selector, destChainConfigArg.destChainSelector) + abi.encodeWithSelector(FeeQuoter.InvalidDestChainConfig.selector, destChainConfigArg.destChainSelector) ); - s_priceRegistry.applyDestChainConfigUpdates(destChainConfigArgs); + s_feeQuoter.applyDestChainConfigUpdates(destChainConfigArgs); } function test_InvalidChainFamilySelector_Revert() public { - PriceRegistry.DestChainConfigArgs[] memory destChainConfigArgs = _generatePriceRegistryDestChainConfigArgs(); - PriceRegistry.DestChainConfigArgs memory destChainConfigArg = destChainConfigArgs[0]; + FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = _generateFeeQuoterDestChainConfigArgs(); + FeeQuoter.DestChainConfigArgs memory destChainConfigArg = destChainConfigArgs[0]; destChainConfigArg.destChainConfig.chainFamilySelector = bytes4(uint32(1)); vm.expectRevert( - abi.encodeWithSelector(PriceRegistry.InvalidDestChainConfig.selector, destChainConfigArg.destChainSelector) + abi.encodeWithSelector(FeeQuoter.InvalidDestChainConfig.selector, destChainConfigArg.destChainSelector) ); - s_priceRegistry.applyDestChainConfigUpdates(destChainConfigArgs); + s_feeQuoter.applyDestChainConfigUpdates(destChainConfigArgs); } } -contract PriceRegistry_getDataAvailabilityCost is PriceRegistrySetup { +contract FeeQuoter_getDataAvailabilityCost is FeeQuoterSetup { function test_EmptyMessageCalculatesDataAvailabilityCost_Success() public { uint256 dataAvailabilityCostUSD = - s_priceRegistry.getDataAvailabilityCost(DEST_CHAIN_SELECTOR, USD_PER_DATA_AVAILABILITY_GAS, 0, 0, 0); + s_feeQuoter.getDataAvailabilityCost(DEST_CHAIN_SELECTOR, USD_PER_DATA_AVAILABILITY_GAS, 0, 0, 0); - PriceRegistry.DestChainConfig memory destChainConfig = s_priceRegistry.getDestChainConfig(DEST_CHAIN_SELECTOR); + FeeQuoter.DestChainConfig memory destChainConfig = s_feeQuoter.getDestChainConfig(DEST_CHAIN_SELECTOR); uint256 dataAvailabilityGas = destChainConfig.destDataAvailabilityOverheadGas + destChainConfig.destGasPerDataAvailabilityByte * Internal.ANY_2_EVM_MESSAGE_FIXED_BYTES; @@ -873,7 +857,7 @@ contract PriceRegistry_getDataAvailabilityCost is PriceRegistrySetup { assertEq(expectedDataAvailabilityCostUSD, dataAvailabilityCostUSD); // Test that the cost is destnation chain specific - PriceRegistry.DestChainConfigArgs[] memory destChainConfigArgs = _generatePriceRegistryDestChainConfigArgs(); + FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = _generateFeeQuoterDestChainConfigArgs(); destChainConfigArgs[0].destChainSelector = DEST_CHAIN_SELECTOR + 1; destChainConfigArgs[0].destChainConfig.destDataAvailabilityOverheadGas = destChainConfig.destDataAvailabilityOverheadGas * 2; @@ -881,11 +865,11 @@ contract PriceRegistry_getDataAvailabilityCost is PriceRegistrySetup { destChainConfig.destGasPerDataAvailabilityByte * 2; destChainConfigArgs[0].destChainConfig.destDataAvailabilityMultiplierBps = destChainConfig.destDataAvailabilityMultiplierBps * 2; - s_priceRegistry.applyDestChainConfigUpdates(destChainConfigArgs); + s_feeQuoter.applyDestChainConfigUpdates(destChainConfigArgs); - destChainConfig = s_priceRegistry.getDestChainConfig(DEST_CHAIN_SELECTOR + 1); + destChainConfig = s_feeQuoter.getDestChainConfig(DEST_CHAIN_SELECTOR + 1); uint256 dataAvailabilityCostUSD2 = - s_priceRegistry.getDataAvailabilityCost(DEST_CHAIN_SELECTOR + 1, USD_PER_DATA_AVAILABILITY_GAS, 0, 0, 0); + s_feeQuoter.getDataAvailabilityCost(DEST_CHAIN_SELECTOR + 1, USD_PER_DATA_AVAILABILITY_GAS, 0, 0, 0); dataAvailabilityGas = destChainConfig.destDataAvailabilityOverheadGas + destChainConfig.destGasPerDataAvailabilityByte * Internal.ANY_2_EVM_MESSAGE_FIXED_BYTES; expectedDataAvailabilityCostUSD = @@ -897,9 +881,9 @@ contract PriceRegistry_getDataAvailabilityCost is PriceRegistrySetup { function test_SimpleMessageCalculatesDataAvailabilityCost_Success() public view { uint256 dataAvailabilityCostUSD = - s_priceRegistry.getDataAvailabilityCost(DEST_CHAIN_SELECTOR, USD_PER_DATA_AVAILABILITY_GAS, 100, 5, 50); + s_feeQuoter.getDataAvailabilityCost(DEST_CHAIN_SELECTOR, USD_PER_DATA_AVAILABILITY_GAS, 100, 5, 50); - PriceRegistry.DestChainConfig memory destChainConfig = s_priceRegistry.getDestChainConfig(DEST_CHAIN_SELECTOR); + FeeQuoter.DestChainConfig memory destChainConfig = s_feeQuoter.getDestChainConfig(DEST_CHAIN_SELECTOR); uint256 dataAvailabilityLengthBytes = Internal.ANY_2_EVM_MESSAGE_FIXED_BYTES + 100 + (5 * Internal.ANY_2_EVM_MESSAGE_FIXED_BYTES_PER_TOKEN) + 50; @@ -912,8 +896,7 @@ contract PriceRegistry_getDataAvailabilityCost is PriceRegistrySetup { } function test_SimpleMessageCalculatesDataAvailabilityCostUnsupportedDestChainSelector_Success() public view { - uint256 dataAvailabilityCostUSD = - s_priceRegistry.getDataAvailabilityCost(0, USD_PER_DATA_AVAILABILITY_GAS, 100, 5, 50); + uint256 dataAvailabilityCostUSD = s_feeQuoter.getDataAvailabilityCost(0, USD_PER_DATA_AVAILABILITY_GAS, 100, 5, 50); assertEq(dataAvailabilityCostUSD, 0); } @@ -923,7 +906,7 @@ contract PriceRegistry_getDataAvailabilityCost is PriceRegistrySetup { uint32 numberOfTokens, uint32 tokenTransferBytesOverhead ) public view { - uint256 dataAvailabilityCostUSD = s_priceRegistry.getDataAvailabilityCost( + uint256 dataAvailabilityCostUSD = s_feeQuoter.getDataAvailabilityCost( DEST_CHAIN_SELECTOR, 0, messageDataLength, numberOfTokens, tokenTransferBytesOverhead ); @@ -941,19 +924,20 @@ contract PriceRegistry_getDataAvailabilityCost is PriceRegistrySetup { uint32 tokenTransferBytesOverhead ) public { vm.assume(destChainSelector != 0); - PriceRegistry.DestChainConfigArgs[] memory destChainConfigArgs = new PriceRegistry.DestChainConfigArgs[](1); - PriceRegistry.DestChainConfig memory destChainConfig = s_priceRegistry.getDestChainConfig(destChainSelector); + FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = new FeeQuoter.DestChainConfigArgs[](1); + FeeQuoter.DestChainConfig memory destChainConfig = s_feeQuoter.getDestChainConfig(destChainSelector); destChainConfigArgs[0] = - PriceRegistry.DestChainConfigArgs({destChainSelector: destChainSelector, destChainConfig: destChainConfig}); + FeeQuoter.DestChainConfigArgs({destChainSelector: destChainSelector, destChainConfig: destChainConfig}); destChainConfigArgs[0].destChainConfig.destDataAvailabilityOverheadGas = destDataAvailabilityOverheadGas; destChainConfigArgs[0].destChainConfig.destGasPerDataAvailabilityByte = destGasPerDataAvailabilityByte; destChainConfigArgs[0].destChainConfig.destDataAvailabilityMultiplierBps = destDataAvailabilityMultiplierBps; destChainConfigArgs[0].destChainConfig.defaultTxGasLimit = GAS_LIMIT; destChainConfigArgs[0].destChainConfig.maxPerMsgGasLimit = GAS_LIMIT; destChainConfigArgs[0].destChainConfig.chainFamilySelector = Internal.CHAIN_FAMILY_SELECTOR_EVM; - s_priceRegistry.applyDestChainConfigUpdates(destChainConfigArgs); - uint256 dataAvailabilityCostUSD = s_priceRegistry.getDataAvailabilityCost( + s_feeQuoter.applyDestChainConfigUpdates(destChainConfigArgs); + + uint256 dataAvailabilityCostUSD = s_feeQuoter.getDataAvailabilityCost( destChainConfigArgs[0].destChainSelector, dataAvailabilityGasPrice, messageDataLength, @@ -973,77 +957,77 @@ contract PriceRegistry_getDataAvailabilityCost is PriceRegistrySetup { } } -contract PriceRegistry_applyPremiumMultiplierWeiPerEthUpdates is PriceRegistrySetup { +contract FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates is FeeQuoterSetup { function test_Fuzz_applyPremiumMultiplierWeiPerEthUpdates_Success( - PriceRegistry.PremiumMultiplierWeiPerEthArgs memory premiumMultiplierWeiPerEthArg + FeeQuoter.PremiumMultiplierWeiPerEthArgs memory premiumMultiplierWeiPerEthArg ) public { - PriceRegistry.PremiumMultiplierWeiPerEthArgs[] memory premiumMultiplierWeiPerEthArgs = - new PriceRegistry.PremiumMultiplierWeiPerEthArgs[](1); + FeeQuoter.PremiumMultiplierWeiPerEthArgs[] memory premiumMultiplierWeiPerEthArgs = + new FeeQuoter.PremiumMultiplierWeiPerEthArgs[](1); premiumMultiplierWeiPerEthArgs[0] = premiumMultiplierWeiPerEthArg; vm.expectEmit(); - emit PriceRegistry.PremiumMultiplierWeiPerEthUpdated( + emit FeeQuoter.PremiumMultiplierWeiPerEthUpdated( premiumMultiplierWeiPerEthArg.token, premiumMultiplierWeiPerEthArg.premiumMultiplierWeiPerEth ); - s_priceRegistry.applyPremiumMultiplierWeiPerEthUpdates(premiumMultiplierWeiPerEthArgs); + s_feeQuoter.applyPremiumMultiplierWeiPerEthUpdates(premiumMultiplierWeiPerEthArgs); assertEq( premiumMultiplierWeiPerEthArg.premiumMultiplierWeiPerEth, - s_priceRegistry.getPremiumMultiplierWeiPerEth(premiumMultiplierWeiPerEthArg.token) + s_feeQuoter.getPremiumMultiplierWeiPerEth(premiumMultiplierWeiPerEthArg.token) ); } function test_applyPremiumMultiplierWeiPerEthUpdatesSingleToken_Success() public { - PriceRegistry.PremiumMultiplierWeiPerEthArgs[] memory premiumMultiplierWeiPerEthArgs = - new PriceRegistry.PremiumMultiplierWeiPerEthArgs[](1); - premiumMultiplierWeiPerEthArgs[0] = s_priceRegistryPremiumMultiplierWeiPerEthArgs[0]; + FeeQuoter.PremiumMultiplierWeiPerEthArgs[] memory premiumMultiplierWeiPerEthArgs = + new FeeQuoter.PremiumMultiplierWeiPerEthArgs[](1); + premiumMultiplierWeiPerEthArgs[0] = s_feeQuoterPremiumMultiplierWeiPerEthArgs[0]; premiumMultiplierWeiPerEthArgs[0].token = vm.addr(1); vm.expectEmit(); - emit PriceRegistry.PremiumMultiplierWeiPerEthUpdated( + emit FeeQuoter.PremiumMultiplierWeiPerEthUpdated( vm.addr(1), premiumMultiplierWeiPerEthArgs[0].premiumMultiplierWeiPerEth ); - s_priceRegistry.applyPremiumMultiplierWeiPerEthUpdates(premiumMultiplierWeiPerEthArgs); + s_feeQuoter.applyPremiumMultiplierWeiPerEthUpdates(premiumMultiplierWeiPerEthArgs); assertEq( - s_priceRegistryPremiumMultiplierWeiPerEthArgs[0].premiumMultiplierWeiPerEth, - s_priceRegistry.getPremiumMultiplierWeiPerEth(vm.addr(1)) + s_feeQuoterPremiumMultiplierWeiPerEthArgs[0].premiumMultiplierWeiPerEth, + s_feeQuoter.getPremiumMultiplierWeiPerEth(vm.addr(1)) ); } function test_applyPremiumMultiplierWeiPerEthUpdatesMultipleTokens_Success() public { - PriceRegistry.PremiumMultiplierWeiPerEthArgs[] memory premiumMultiplierWeiPerEthArgs = - new PriceRegistry.PremiumMultiplierWeiPerEthArgs[](2); - premiumMultiplierWeiPerEthArgs[0] = s_priceRegistryPremiumMultiplierWeiPerEthArgs[0]; + FeeQuoter.PremiumMultiplierWeiPerEthArgs[] memory premiumMultiplierWeiPerEthArgs = + new FeeQuoter.PremiumMultiplierWeiPerEthArgs[](2); + premiumMultiplierWeiPerEthArgs[0] = s_feeQuoterPremiumMultiplierWeiPerEthArgs[0]; premiumMultiplierWeiPerEthArgs[0].token = vm.addr(1); premiumMultiplierWeiPerEthArgs[1].token = vm.addr(2); vm.expectEmit(); - emit PriceRegistry.PremiumMultiplierWeiPerEthUpdated( + emit FeeQuoter.PremiumMultiplierWeiPerEthUpdated( vm.addr(1), premiumMultiplierWeiPerEthArgs[0].premiumMultiplierWeiPerEth ); vm.expectEmit(); - emit PriceRegistry.PremiumMultiplierWeiPerEthUpdated( + emit FeeQuoter.PremiumMultiplierWeiPerEthUpdated( vm.addr(2), premiumMultiplierWeiPerEthArgs[1].premiumMultiplierWeiPerEth ); - s_priceRegistry.applyPremiumMultiplierWeiPerEthUpdates(premiumMultiplierWeiPerEthArgs); + s_feeQuoter.applyPremiumMultiplierWeiPerEthUpdates(premiumMultiplierWeiPerEthArgs); assertEq( premiumMultiplierWeiPerEthArgs[0].premiumMultiplierWeiPerEth, - s_priceRegistry.getPremiumMultiplierWeiPerEth(vm.addr(1)) + s_feeQuoter.getPremiumMultiplierWeiPerEth(vm.addr(1)) ); assertEq( premiumMultiplierWeiPerEthArgs[1].premiumMultiplierWeiPerEth, - s_priceRegistry.getPremiumMultiplierWeiPerEth(vm.addr(2)) + s_feeQuoter.getPremiumMultiplierWeiPerEth(vm.addr(2)) ); } function test_applyPremiumMultiplierWeiPerEthUpdatesZeroInput() public { vm.recordLogs(); - s_priceRegistry.applyPremiumMultiplierWeiPerEthUpdates(new PriceRegistry.PremiumMultiplierWeiPerEthArgs[](0)); + s_feeQuoter.applyPremiumMultiplierWeiPerEthUpdates(new FeeQuoter.PremiumMultiplierWeiPerEthArgs[](0)); assertEq(vm.getRecordedLogs().length, 0); } @@ -1051,21 +1035,20 @@ contract PriceRegistry_applyPremiumMultiplierWeiPerEthUpdates is PriceRegistrySe // Reverts function test_OnlyCallableByOwnerOrAdmin_Revert() public { - PriceRegistry.PremiumMultiplierWeiPerEthArgs[] memory premiumMultiplierWeiPerEthArgs; + FeeQuoter.PremiumMultiplierWeiPerEthArgs[] memory premiumMultiplierWeiPerEthArgs; vm.startPrank(STRANGER); vm.expectRevert("Only callable by owner"); - s_priceRegistry.applyPremiumMultiplierWeiPerEthUpdates(premiumMultiplierWeiPerEthArgs); + s_feeQuoter.applyPremiumMultiplierWeiPerEthUpdates(premiumMultiplierWeiPerEthArgs); } } -contract PriceRegistry_applyTokenTransferFeeConfigUpdates is PriceRegistrySetup { +contract FeeQuoter_applyTokenTransferFeeConfigUpdates is FeeQuoterSetup { function test_Fuzz_ApplyTokenTransferFeeConfig_Success( - PriceRegistry.TokenTransferFeeConfig[2] memory tokenTransferFeeConfigs + FeeQuoter.TokenTransferFeeConfig[2] memory tokenTransferFeeConfigs ) public { - PriceRegistry.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs = - _generateTokenTransferFeeConfigArgs(2, 2); + FeeQuoter.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs = _generateTokenTransferFeeConfigArgs(2, 2); tokenTransferFeeConfigArgs[0].destChainSelector = DEST_CHAIN_SELECTOR; tokenTransferFeeConfigArgs[1].destChainSelector = DEST_CHAIN_SELECTOR + 1; @@ -1079,20 +1062,20 @@ contract PriceRegistry_applyTokenTransferFeeConfigUpdates is PriceRegistrySetup tokenTransferFeeConfigArgs[i].tokenTransferFeeConfigs[j].tokenTransferFeeConfig = tokenTransferFeeConfigs[j]; vm.expectEmit(); - emit PriceRegistry.TokenTransferFeeConfigUpdated( + emit FeeQuoter.TokenTransferFeeConfigUpdated( tokenTransferFeeConfigArgs[i].destChainSelector, feeToken, tokenTransferFeeConfigs[j] ); } } - s_priceRegistry.applyTokenTransferFeeConfigUpdates( - tokenTransferFeeConfigArgs, new PriceRegistry.TokenTransferFeeConfigRemoveArgs[](0) + s_feeQuoter.applyTokenTransferFeeConfigUpdates( + tokenTransferFeeConfigArgs, new FeeQuoter.TokenTransferFeeConfigRemoveArgs[](0) ); for (uint256 i = 0; i < tokenTransferFeeConfigs.length; ++i) { _assertTokenTransferFeeConfigEqual( tokenTransferFeeConfigs[i], - s_priceRegistry.getTokenTransferFeeConfig( + s_feeQuoter.getTokenTransferFeeConfig( tokenTransferFeeConfigArgs[0].destChainSelector, tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[i].token ) @@ -1101,12 +1084,10 @@ contract PriceRegistry_applyTokenTransferFeeConfigUpdates is PriceRegistrySetup } function test_ApplyTokenTransferFeeConfig_Success() public { - PriceRegistry.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs = - _generateTokenTransferFeeConfigArgs(1, 2); + FeeQuoter.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs = _generateTokenTransferFeeConfigArgs(1, 2); tokenTransferFeeConfigArgs[0].destChainSelector = DEST_CHAIN_SELECTOR; tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token = address(5); - tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig = PriceRegistry - .TokenTransferFeeConfig({ + tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig = FeeQuoter.TokenTransferFeeConfig({ minFeeUSDCents: 6, maxFeeUSDCents: 7, deciBps: 8, @@ -1115,8 +1096,7 @@ contract PriceRegistry_applyTokenTransferFeeConfigUpdates is PriceRegistrySetup isEnabled: true }); tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[1].token = address(11); - tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[1].tokenTransferFeeConfig = PriceRegistry - .TokenTransferFeeConfig({ + tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[1].tokenTransferFeeConfig = FeeQuoter.TokenTransferFeeConfig({ minFeeUSDCents: 12, maxFeeUSDCents: 13, deciBps: 14, @@ -1126,26 +1106,26 @@ contract PriceRegistry_applyTokenTransferFeeConfigUpdates is PriceRegistrySetup }); vm.expectEmit(); - emit PriceRegistry.TokenTransferFeeConfigUpdated( + emit FeeQuoter.TokenTransferFeeConfigUpdated( tokenTransferFeeConfigArgs[0].destChainSelector, tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token, tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig ); vm.expectEmit(); - emit PriceRegistry.TokenTransferFeeConfigUpdated( + emit FeeQuoter.TokenTransferFeeConfigUpdated( tokenTransferFeeConfigArgs[0].destChainSelector, tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[1].token, tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[1].tokenTransferFeeConfig ); - PriceRegistry.TokenTransferFeeConfigRemoveArgs[] memory tokensToRemove = - new PriceRegistry.TokenTransferFeeConfigRemoveArgs[](0); - s_priceRegistry.applyTokenTransferFeeConfigUpdates(tokenTransferFeeConfigArgs, tokensToRemove); + FeeQuoter.TokenTransferFeeConfigRemoveArgs[] memory tokensToRemove = + new FeeQuoter.TokenTransferFeeConfigRemoveArgs[](0); + s_feeQuoter.applyTokenTransferFeeConfigUpdates(tokenTransferFeeConfigArgs, tokensToRemove); - PriceRegistry.TokenTransferFeeConfig memory config0 = s_priceRegistry.getTokenTransferFeeConfig( + FeeQuoter.TokenTransferFeeConfig memory config0 = s_feeQuoter.getTokenTransferFeeConfig( tokenTransferFeeConfigArgs[0].destChainSelector, tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token ); - PriceRegistry.TokenTransferFeeConfig memory config1 = s_priceRegistry.getTokenTransferFeeConfig( + FeeQuoter.TokenTransferFeeConfig memory config1 = s_feeQuoter.getTokenTransferFeeConfig( tokenTransferFeeConfigArgs[0].destChainSelector, tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[1].token ); @@ -1157,29 +1137,27 @@ contract PriceRegistry_applyTokenTransferFeeConfigUpdates is PriceRegistrySetup ); // Remove only the first token and validate only the first token is removed - tokensToRemove = new PriceRegistry.TokenTransferFeeConfigRemoveArgs[](1); - tokensToRemove[0] = PriceRegistry.TokenTransferFeeConfigRemoveArgs({ + tokensToRemove = new FeeQuoter.TokenTransferFeeConfigRemoveArgs[](1); + tokensToRemove[0] = FeeQuoter.TokenTransferFeeConfigRemoveArgs({ destChainSelector: tokenTransferFeeConfigArgs[0].destChainSelector, token: tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token }); vm.expectEmit(); - emit PriceRegistry.TokenTransferFeeConfigDeleted( + emit FeeQuoter.TokenTransferFeeConfigDeleted( tokenTransferFeeConfigArgs[0].destChainSelector, tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token ); - s_priceRegistry.applyTokenTransferFeeConfigUpdates( - new PriceRegistry.TokenTransferFeeConfigArgs[](0), tokensToRemove - ); + s_feeQuoter.applyTokenTransferFeeConfigUpdates(new FeeQuoter.TokenTransferFeeConfigArgs[](0), tokensToRemove); - config0 = s_priceRegistry.getTokenTransferFeeConfig( + config0 = s_feeQuoter.getTokenTransferFeeConfig( tokenTransferFeeConfigArgs[0].destChainSelector, tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token ); - config1 = s_priceRegistry.getTokenTransferFeeConfig( + config1 = s_feeQuoter.getTokenTransferFeeConfig( tokenTransferFeeConfigArgs[0].destChainSelector, tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[1].token ); - PriceRegistry.TokenTransferFeeConfig memory emptyConfig; + FeeQuoter.TokenTransferFeeConfig memory emptyConfig; _assertTokenTransferFeeConfigEqual(emptyConfig, config0); _assertTokenTransferFeeConfigEqual( @@ -1189,8 +1167,8 @@ contract PriceRegistry_applyTokenTransferFeeConfigUpdates is PriceRegistrySetup function test_ApplyTokenTransferFeeZeroInput() public { vm.recordLogs(); - s_priceRegistry.applyTokenTransferFeeConfigUpdates( - new PriceRegistry.TokenTransferFeeConfigArgs[](0), new PriceRegistry.TokenTransferFeeConfigRemoveArgs[](0) + s_feeQuoter.applyTokenTransferFeeConfigUpdates( + new FeeQuoter.TokenTransferFeeConfigArgs[](0), new FeeQuoter.TokenTransferFeeConfigRemoveArgs[](0) ); assertEq(vm.getRecordedLogs().length, 0); @@ -1200,22 +1178,20 @@ contract PriceRegistry_applyTokenTransferFeeConfigUpdates is PriceRegistrySetup function test_OnlyCallableByOwnerOrAdmin_Revert() public { vm.startPrank(STRANGER); - PriceRegistry.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs; + FeeQuoter.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs; vm.expectRevert("Only callable by owner"); - s_priceRegistry.applyTokenTransferFeeConfigUpdates( - tokenTransferFeeConfigArgs, new PriceRegistry.TokenTransferFeeConfigRemoveArgs[](0) + s_feeQuoter.applyTokenTransferFeeConfigUpdates( + tokenTransferFeeConfigArgs, new FeeQuoter.TokenTransferFeeConfigRemoveArgs[](0) ); } function test_InvalidDestBytesOverhead_Revert() public { - PriceRegistry.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs = - _generateTokenTransferFeeConfigArgs(1, 1); + FeeQuoter.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs = _generateTokenTransferFeeConfigArgs(1, 1); tokenTransferFeeConfigArgs[0].destChainSelector = DEST_CHAIN_SELECTOR; tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token = address(5); - tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig = PriceRegistry - .TokenTransferFeeConfig({ + tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig = FeeQuoter.TokenTransferFeeConfig({ minFeeUSDCents: 6, maxFeeUSDCents: 7, deciBps: 8, @@ -1226,25 +1202,25 @@ contract PriceRegistry_applyTokenTransferFeeConfigUpdates is PriceRegistrySetup vm.expectRevert( abi.encodeWithSelector( - PriceRegistry.InvalidDestBytesOverhead.selector, + FeeQuoter.InvalidDestBytesOverhead.selector, tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token, tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig.destBytesOverhead ) ); - s_priceRegistry.applyTokenTransferFeeConfigUpdates( - tokenTransferFeeConfigArgs, new PriceRegistry.TokenTransferFeeConfigRemoveArgs[](0) + s_feeQuoter.applyTokenTransferFeeConfigUpdates( + tokenTransferFeeConfigArgs, new FeeQuoter.TokenTransferFeeConfigRemoveArgs[](0) ); } } -contract PriceRegistry_getTokenTransferCost is PriceRegistryFeeSetup { +contract FeeQuoter_getTokenTransferCost is FeeQuoterFeeSetup { using USDPriceWith18Decimals for uint224; function test_NoTokenTransferChargesZeroFee_Success() public view { Client.EVM2AnyMessage memory message = _generateEmptyMessage(); (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = - s_priceRegistry.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_feeTokenPrice, message.tokenAmounts); + s_feeQuoter.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_feeTokenPrice, message.tokenAmounts); assertEq(0, feeUSDWei); assertEq(0, destGasOverhead); @@ -1255,13 +1231,13 @@ contract PriceRegistry_getTokenTransferCost is PriceRegistryFeeSetup { Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(s_selfServeTokenDefaultPricing, 1000); // Get config to assert it isn't set - PriceRegistry.TokenTransferFeeConfig memory transferFeeConfig = - s_priceRegistry.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token); + FeeQuoter.TokenTransferFeeConfig memory transferFeeConfig = + s_feeQuoter.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token); assertFalse(transferFeeConfig.isEnabled); (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = - s_priceRegistry.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_feeTokenPrice, message.tokenAmounts); + s_feeQuoter.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_feeTokenPrice, message.tokenAmounts); // Assert that the default values are used assertEq(uint256(DEFAULT_TOKEN_FEE_USD_CENTS) * 1e16, feeUSDWei); @@ -1271,11 +1247,11 @@ contract PriceRegistry_getTokenTransferCost is PriceRegistryFeeSetup { function test_SmallTokenTransferChargesMinFeeAndGas_Success() public view { Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(s_sourceFeeToken, 1000); - PriceRegistry.TokenTransferFeeConfig memory transferFeeConfig = - s_priceRegistry.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token); + FeeQuoter.TokenTransferFeeConfig memory transferFeeConfig = + s_feeQuoter.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token); (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = - s_priceRegistry.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_feeTokenPrice, message.tokenAmounts); + s_feeQuoter.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_feeTokenPrice, message.tokenAmounts); assertEq(_configUSDCentToWei(transferFeeConfig.minFeeUSDCents), feeUSDWei); assertEq(transferFeeConfig.destGasOverhead, destGasOverhead); @@ -1284,11 +1260,11 @@ contract PriceRegistry_getTokenTransferCost is PriceRegistryFeeSetup { function test_ZeroAmountTokenTransferChargesMinFeeAndGas_Success() public view { Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(s_sourceFeeToken, 0); - PriceRegistry.TokenTransferFeeConfig memory transferFeeConfig = - s_priceRegistry.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token); + FeeQuoter.TokenTransferFeeConfig memory transferFeeConfig = + s_feeQuoter.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token); (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = - s_priceRegistry.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_feeTokenPrice, message.tokenAmounts); + s_feeQuoter.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_feeTokenPrice, message.tokenAmounts); assertEq(_configUSDCentToWei(transferFeeConfig.minFeeUSDCents), feeUSDWei); assertEq(transferFeeConfig.destGasOverhead, destGasOverhead); @@ -1297,11 +1273,11 @@ contract PriceRegistry_getTokenTransferCost is PriceRegistryFeeSetup { function test_LargeTokenTransferChargesMaxFeeAndGas_Success() public view { Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(s_sourceFeeToken, 1e36); - PriceRegistry.TokenTransferFeeConfig memory transferFeeConfig = - s_priceRegistry.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token); + FeeQuoter.TokenTransferFeeConfig memory transferFeeConfig = + s_feeQuoter.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token); (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = - s_priceRegistry.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_feeTokenPrice, message.tokenAmounts); + s_feeQuoter.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_feeTokenPrice, message.tokenAmounts); assertEq(_configUSDCentToWei(transferFeeConfig.maxFeeUSDCents), feeUSDWei); assertEq(transferFeeConfig.destGasOverhead, destGasOverhead); @@ -1312,15 +1288,15 @@ contract PriceRegistry_getTokenTransferCost is PriceRegistryFeeSetup { uint256 tokenAmount = 10000e18; Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(s_sourceFeeToken, tokenAmount); - PriceRegistry.TokenTransferFeeConfig memory transferFeeConfig = - s_priceRegistry.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token); + FeeQuoter.TokenTransferFeeConfig memory transferFeeConfig = + s_feeQuoter.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token); (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = - s_priceRegistry.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_feeTokenPrice, message.tokenAmounts); + s_feeQuoter.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_feeTokenPrice, message.tokenAmounts); uint256 usdWei = _calcUSDValueFromTokenAmount(s_feeTokenPrice, tokenAmount); uint256 bpsUSDWei = _applyBpsRatio( - usdWei, s_priceRegistryTokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig.deciBps + usdWei, s_feeQuoterTokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig.deciBps ); assertEq(bpsUSDWei, feeUSDWei); @@ -1340,15 +1316,15 @@ contract PriceRegistry_getTokenTransferCost is PriceRegistryFeeSetup { }); message.tokenAmounts[0] = Client.EVMTokenAmount({token: CUSTOM_TOKEN, amount: tokenAmount}); - PriceRegistry.TokenTransferFeeConfig memory transferFeeConfig = - s_priceRegistry.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token); + FeeQuoter.TokenTransferFeeConfig memory transferFeeConfig = + s_feeQuoter.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token); (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = - s_priceRegistry.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_feeTokenPrice, message.tokenAmounts); + s_feeQuoter.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_feeTokenPrice, message.tokenAmounts); uint256 usdWei = _calcUSDValueFromTokenAmount(s_customTokenPrice, tokenAmount); uint256 bpsUSDWei = _applyBpsRatio( - usdWei, s_priceRegistryTokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[1].tokenTransferFeeConfig.deciBps + usdWei, s_feeQuoterTokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[1].tokenTransferFeeConfig.deciBps ); assertEq(bpsUSDWei, feeUSDWei); @@ -1357,12 +1333,10 @@ contract PriceRegistry_getTokenTransferCost is PriceRegistryFeeSetup { } function test_ZeroFeeConfigChargesMinFee_Success() public { - PriceRegistry.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs = - _generateTokenTransferFeeConfigArgs(1, 1); + FeeQuoter.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs = _generateTokenTransferFeeConfigArgs(1, 1); tokenTransferFeeConfigArgs[0].destChainSelector = DEST_CHAIN_SELECTOR; tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token = s_sourceFeeToken; - tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig = PriceRegistry - .TokenTransferFeeConfig({ + tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig = FeeQuoter.TokenTransferFeeConfig({ minFeeUSDCents: 1, maxFeeUSDCents: 0, deciBps: 0, @@ -1370,13 +1344,13 @@ contract PriceRegistry_getTokenTransferCost is PriceRegistryFeeSetup { destBytesOverhead: uint32(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES), isEnabled: true }); - s_priceRegistry.applyTokenTransferFeeConfigUpdates( - tokenTransferFeeConfigArgs, new PriceRegistry.TokenTransferFeeConfigRemoveArgs[](0) + s_feeQuoter.applyTokenTransferFeeConfigUpdates( + tokenTransferFeeConfigArgs, new FeeQuoter.TokenTransferFeeConfigRemoveArgs[](0) ); Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(s_sourceFeeToken, 1e36); (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = - s_priceRegistry.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_feeTokenPrice, message.tokenAmounts); + s_feeQuoter.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_feeTokenPrice, message.tokenAmounts); // if token charges 0 bps, it should cost minFee to transfer assertEq( @@ -1392,7 +1366,7 @@ contract PriceRegistry_getTokenTransferCost is PriceRegistryFeeSetup { function test_Fuzz_TokenTransferFeeDuplicateTokens_Success(uint256 transfers, uint256 amount) public view { // It shouldn't be possible to pay materially lower fees by splitting up the transfers. // Note it is possible to pay higher fees since the minimum fees are added. - PriceRegistry.DestChainConfig memory destChainConfig = s_priceRegistry.getDestChainConfig(DEST_CHAIN_SELECTOR); + FeeQuoter.DestChainConfig memory destChainConfig = s_feeQuoter.getDestChainConfig(DEST_CHAIN_SELECTOR); transfers = bound(transfers, 1, destChainConfig.maxNumberOfTokensPerMsg); // Cap amount to avoid overflow amount = bound(amount, 0, 1e36); @@ -1406,9 +1380,9 @@ contract PriceRegistry_getTokenTransferCost is PriceRegistryFeeSetup { address feeToken = s_sourceRouter.getWrappedNative(); (uint256 feeSingleUSDWei, uint32 gasOverheadSingle, uint32 bytesOverheadSingle) = - s_priceRegistry.getTokenTransferCost(DEST_CHAIN_SELECTOR, feeToken, s_wrappedTokenPrice, single); + s_feeQuoter.getTokenTransferCost(DEST_CHAIN_SELECTOR, feeToken, s_wrappedTokenPrice, single); (uint256 feeMultipleUSDWei, uint32 gasOverheadMultiple, uint32 bytesOverheadMultiple) = - s_priceRegistry.getTokenTransferCost(DEST_CHAIN_SELECTOR, feeToken, s_wrappedTokenPrice, multiple); + s_feeQuoter.getTokenTransferCost(DEST_CHAIN_SELECTOR, feeToken, s_wrappedTokenPrice, multiple); // Note that there can be a rounding error once per split. assertGe(feeMultipleUSDWei, (feeSingleUSDWei - destChainConfig.maxNumberOfTokensPerMsg)); @@ -1419,10 +1393,10 @@ contract PriceRegistry_getTokenTransferCost is PriceRegistryFeeSetup { function test_MixedTokenTransferFee_Success() public view { address[3] memory testTokens = [s_sourceFeeToken, s_sourceRouter.getWrappedNative(), CUSTOM_TOKEN]; uint224[3] memory tokenPrices = [s_feeTokenPrice, s_wrappedTokenPrice, s_customTokenPrice]; - PriceRegistry.TokenTransferFeeConfig[3] memory tokenTransferFeeConfigs = [ - s_priceRegistry.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, testTokens[0]), - s_priceRegistry.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, testTokens[1]), - s_priceRegistry.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, testTokens[2]) + FeeQuoter.TokenTransferFeeConfig[3] memory tokenTransferFeeConfigs = [ + s_feeQuoter.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, testTokens[0]), + s_feeQuoter.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, testTokens[1]), + s_feeQuoter.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, testTokens[2]) ]; Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({ @@ -1438,8 +1412,8 @@ contract PriceRegistry_getTokenTransferCost is PriceRegistryFeeSetup { // Start with small token transfers, total bps fee is lower than min token transfer fee for (uint256 i = 0; i < testTokens.length; ++i) { message.tokenAmounts[i] = Client.EVMTokenAmount({token: testTokens[i], amount: 1e14}); - PriceRegistry.TokenTransferFeeConfig memory tokenTransferFeeConfig = - s_priceRegistry.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, testTokens[i]); + FeeQuoter.TokenTransferFeeConfig memory tokenTransferFeeConfig = + s_feeQuoter.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, testTokens[i]); expectedTotalGas += tokenTransferFeeConfig.destGasOverhead == 0 ? DEFAULT_TOKEN_DEST_GAS_OVERHEAD @@ -1448,9 +1422,8 @@ contract PriceRegistry_getTokenTransferCost is PriceRegistryFeeSetup { ? DEFAULT_TOKEN_BYTES_OVERHEAD : tokenTransferFeeConfig.destBytesOverhead; } - (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = s_priceRegistry.getTokenTransferCost( - DEST_CHAIN_SELECTOR, message.feeToken, s_wrappedTokenPrice, message.tokenAmounts - ); + (uint256 feeUSDWei, uint32 destGasOverhead, uint32 destBytesOverhead) = + s_feeQuoter.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_wrappedTokenPrice, message.tokenAmounts); uint256 expectedFeeUSDWei = 0; for (uint256 i = 0; i < testTokens.length; ++i) { @@ -1473,9 +1446,8 @@ contract PriceRegistry_getTokenTransferCost is PriceRegistryFeeSetup { ); uint256 token1USDWei = _configUSDCentToWei(DEFAULT_TOKEN_FEE_USD_CENTS); - (feeUSDWei, destGasOverhead, destBytesOverhead) = s_priceRegistry.getTokenTransferCost( - DEST_CHAIN_SELECTOR, message.feeToken, s_wrappedTokenPrice, message.tokenAmounts - ); + (feeUSDWei, destGasOverhead, destBytesOverhead) = + s_feeQuoter.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_wrappedTokenPrice, message.tokenAmounts); expectedFeeUSDWei = token0USDWei + token1USDWei + _configUSDCentToWei(tokenTransferFeeConfigs[2].minFeeUSDCents); assertEq(expectedFeeUSDWei, feeUSDWei, "wrong feeUSDWei 2"); @@ -1485,9 +1457,8 @@ contract PriceRegistry_getTokenTransferCost is PriceRegistryFeeSetup { // Set 2nd token transfer to a large amount that is higher than maxFeeUSD message.tokenAmounts[2] = Client.EVMTokenAmount({token: testTokens[2], amount: 1e36}); - (feeUSDWei, destGasOverhead, destBytesOverhead) = s_priceRegistry.getTokenTransferCost( - DEST_CHAIN_SELECTOR, message.feeToken, s_wrappedTokenPrice, message.tokenAmounts - ); + (feeUSDWei, destGasOverhead, destBytesOverhead) = + s_feeQuoter.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, s_wrappedTokenPrice, message.tokenAmounts); expectedFeeUSDWei = token0USDWei + token1USDWei + _configUSDCentToWei(tokenTransferFeeConfigs[2].maxFeeUSDCents); assertEq(expectedFeeUSDWei, feeUSDWei, "wrong feeUSDWei 3"); @@ -1496,7 +1467,7 @@ contract PriceRegistry_getTokenTransferCost is PriceRegistryFeeSetup { } } -contract PriceRegistry_getValidatedFee is PriceRegistryFeeSetup { +contract FeeQuoter_getValidatedFee is FeeQuoterFeeSetup { using USDPriceWith18Decimals for uint224; function test_EmptyMessage_Success() public view { @@ -1506,15 +1477,15 @@ contract PriceRegistry_getValidatedFee is PriceRegistryFeeSetup { for (uint256 i = 0; i < feeTokenPrices.length; ++i) { Client.EVM2AnyMessage memory message = _generateEmptyMessage(); message.feeToken = testTokens[i]; - uint64 premiumMultiplierWeiPerEth = s_priceRegistry.getPremiumMultiplierWeiPerEth(message.feeToken); - PriceRegistry.DestChainConfig memory destChainConfig = s_priceRegistry.getDestChainConfig(DEST_CHAIN_SELECTOR); + uint64 premiumMultiplierWeiPerEth = s_feeQuoter.getPremiumMultiplierWeiPerEth(message.feeToken); + FeeQuoter.DestChainConfig memory destChainConfig = s_feeQuoter.getDestChainConfig(DEST_CHAIN_SELECTOR); - uint256 feeAmount = s_priceRegistry.getValidatedFee(DEST_CHAIN_SELECTOR, message); + uint256 feeAmount = s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR, message); uint256 gasUsed = GAS_LIMIT + DEST_GAS_OVERHEAD; uint256 gasFeeUSD = (gasUsed * destChainConfig.gasMultiplierWeiPerEth * USD_PER_GAS); uint256 messageFeeUSD = (_configUSDCentToWei(destChainConfig.networkFeeUSDCents) * premiumMultiplierWeiPerEth); - uint256 dataAvailabilityFeeUSD = s_priceRegistry.getDataAvailabilityCost( + uint256 dataAvailabilityFeeUSD = s_feeQuoter.getDataAvailabilityCost( DEST_CHAIN_SELECTOR, USD_PER_DATA_AVAILABILITY_GAS, message.data.length, message.tokenAmounts.length, 0 ); @@ -1524,17 +1495,17 @@ contract PriceRegistry_getValidatedFee is PriceRegistryFeeSetup { } function test_ZeroDataAvailabilityMultiplier_Success() public { - PriceRegistry.DestChainConfigArgs[] memory destChainConfigArgs = new PriceRegistry.DestChainConfigArgs[](1); - PriceRegistry.DestChainConfig memory destChainConfig = s_priceRegistry.getDestChainConfig(DEST_CHAIN_SELECTOR); + FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = new FeeQuoter.DestChainConfigArgs[](1); + FeeQuoter.DestChainConfig memory destChainConfig = s_feeQuoter.getDestChainConfig(DEST_CHAIN_SELECTOR); destChainConfigArgs[0] = - PriceRegistry.DestChainConfigArgs({destChainSelector: DEST_CHAIN_SELECTOR, destChainConfig: destChainConfig}); + FeeQuoter.DestChainConfigArgs({destChainSelector: DEST_CHAIN_SELECTOR, destChainConfig: destChainConfig}); destChainConfigArgs[0].destChainConfig.destDataAvailabilityMultiplierBps = 0; - s_priceRegistry.applyDestChainConfigUpdates(destChainConfigArgs); + s_feeQuoter.applyDestChainConfigUpdates(destChainConfigArgs); Client.EVM2AnyMessage memory message = _generateEmptyMessage(); - uint64 premiumMultiplierWeiPerEth = s_priceRegistry.getPremiumMultiplierWeiPerEth(message.feeToken); + uint64 premiumMultiplierWeiPerEth = s_feeQuoter.getPremiumMultiplierWeiPerEth(message.feeToken); - uint256 feeAmount = s_priceRegistry.getValidatedFee(DEST_CHAIN_SELECTOR, message); + uint256 feeAmount = s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR, message); uint256 gasUsed = GAS_LIMIT + DEST_GAS_OVERHEAD; uint256 gasFeeUSD = (gasUsed * destChainConfig.gasMultiplierWeiPerEth * USD_PER_GAS); @@ -1559,14 +1530,14 @@ contract PriceRegistry_getValidatedFee is PriceRegistryFeeSetup { extraArgs: Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: customGasLimit})) }); - uint64 premiumMultiplierWeiPerEth = s_priceRegistry.getPremiumMultiplierWeiPerEth(message.feeToken); - PriceRegistry.DestChainConfig memory destChainConfig = s_priceRegistry.getDestChainConfig(DEST_CHAIN_SELECTOR); + uint64 premiumMultiplierWeiPerEth = s_feeQuoter.getPremiumMultiplierWeiPerEth(message.feeToken); + FeeQuoter.DestChainConfig memory destChainConfig = s_feeQuoter.getDestChainConfig(DEST_CHAIN_SELECTOR); - uint256 feeAmount = s_priceRegistry.getValidatedFee(DEST_CHAIN_SELECTOR, message); + uint256 feeAmount = s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR, message); uint256 gasUsed = customGasLimit + DEST_GAS_OVERHEAD + customDataSize * DEST_GAS_PER_PAYLOAD_BYTE; uint256 gasFeeUSD = (gasUsed * destChainConfig.gasMultiplierWeiPerEth * USD_PER_GAS); uint256 messageFeeUSD = (_configUSDCentToWei(destChainConfig.networkFeeUSDCents) * premiumMultiplierWeiPerEth); - uint256 dataAvailabilityFeeUSD = s_priceRegistry.getDataAvailabilityCost( + uint256 dataAvailabilityFeeUSD = s_feeQuoter.getDataAvailabilityCost( DEST_CHAIN_SELECTOR, USD_PER_DATA_AVAILABILITY_GAS, message.data.length, message.tokenAmounts.length, 0 ); @@ -1583,22 +1554,21 @@ contract PriceRegistry_getValidatedFee is PriceRegistryFeeSetup { for (uint256 i = 0; i < feeTokenPrices.length; ++i) { Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(s_sourceFeeToken, tokenAmount); message.feeToken = testTokens[i]; - PriceRegistry.DestChainConfig memory destChainConfig = s_priceRegistry.getDestChainConfig(DEST_CHAIN_SELECTOR); + FeeQuoter.DestChainConfig memory destChainConfig = s_feeQuoter.getDestChainConfig(DEST_CHAIN_SELECTOR); uint32 destBytesOverhead = - s_priceRegistry.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token).destBytesOverhead; + s_feeQuoter.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token).destBytesOverhead; uint32 tokenBytesOverhead = destBytesOverhead == 0 ? uint32(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES) : destBytesOverhead; - uint256 feeAmount = s_priceRegistry.getValidatedFee(DEST_CHAIN_SELECTOR, message); + uint256 feeAmount = s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR, message); uint256 gasUsed = GAS_LIMIT + DEST_GAS_OVERHEAD - + s_priceRegistry.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token).destGasOverhead; + + s_feeQuoter.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[0].token).destGasOverhead; uint256 gasFeeUSD = (gasUsed * destChainConfig.gasMultiplierWeiPerEth * USD_PER_GAS); - (uint256 transferFeeUSD,,) = s_priceRegistry.getTokenTransferCost( - DEST_CHAIN_SELECTOR, message.feeToken, feeTokenPrices[i], message.tokenAmounts - ); - uint256 messageFeeUSD = (transferFeeUSD * s_priceRegistry.getPremiumMultiplierWeiPerEth(message.feeToken)); - uint256 dataAvailabilityFeeUSD = s_priceRegistry.getDataAvailabilityCost( + (uint256 transferFeeUSD,,) = + s_feeQuoter.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, feeTokenPrices[i], message.tokenAmounts); + uint256 messageFeeUSD = (transferFeeUSD * s_feeQuoter.getPremiumMultiplierWeiPerEth(message.feeToken)); + uint256 dataAvailabilityFeeUSD = s_feeQuoter.getDataAvailabilityCost( DEST_CHAIN_SELECTOR, USD_PER_DATA_AVAILABILITY_GAS, message.data.length, @@ -1624,8 +1594,8 @@ contract PriceRegistry_getValidatedFee is PriceRegistryFeeSetup { feeToken: testTokens[i], extraArgs: Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: customGasLimit})) }); - uint64 premiumMultiplierWeiPerEth = s_priceRegistry.getPremiumMultiplierWeiPerEth(message.feeToken); - PriceRegistry.DestChainConfig memory destChainConfig = s_priceRegistry.getDestChainConfig(DEST_CHAIN_SELECTOR); + uint64 premiumMultiplierWeiPerEth = s_feeQuoter.getPremiumMultiplierWeiPerEth(message.feeToken); + FeeQuoter.DestChainConfig memory destChainConfig = s_feeQuoter.getDestChainConfig(DEST_CHAIN_SELECTOR); message.tokenAmounts[0] = Client.EVMTokenAmount({token: s_sourceFeeToken, amount: 10000e18}); // feeTokenAmount message.tokenAmounts[1] = Client.EVMTokenAmount({token: CUSTOM_TOKEN, amount: 200000e18}); // customTokenAmount @@ -1635,21 +1605,19 @@ contract PriceRegistry_getValidatedFee is PriceRegistryFeeSetup { uint32 tokenBytesOverhead = 0; for (uint256 j = 0; j < message.tokenAmounts.length; ++j) { tokenGasOverhead += - s_priceRegistry.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[j].token).destGasOverhead; - uint32 destBytesOverhead = s_priceRegistry.getTokenTransferFeeConfig( - DEST_CHAIN_SELECTOR, message.tokenAmounts[j].token - ).destBytesOverhead; + s_feeQuoter.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[j].token).destGasOverhead; + uint32 destBytesOverhead = + s_feeQuoter.getTokenTransferFeeConfig(DEST_CHAIN_SELECTOR, message.tokenAmounts[j].token).destBytesOverhead; tokenBytesOverhead += destBytesOverhead == 0 ? uint32(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES) : destBytesOverhead; } uint256 gasUsed = customGasLimit + DEST_GAS_OVERHEAD + message.data.length * DEST_GAS_PER_PAYLOAD_BYTE + tokenGasOverhead; uint256 gasFeeUSD = (gasUsed * destChainConfig.gasMultiplierWeiPerEth * USD_PER_GAS); - (uint256 transferFeeUSD,,) = s_priceRegistry.getTokenTransferCost( - DEST_CHAIN_SELECTOR, message.feeToken, feeTokenPrices[i], message.tokenAmounts - ); + (uint256 transferFeeUSD,,) = + s_feeQuoter.getTokenTransferCost(DEST_CHAIN_SELECTOR, message.feeToken, feeTokenPrices[i], message.tokenAmounts); uint256 messageFeeUSD = (transferFeeUSD * premiumMultiplierWeiPerEth); - uint256 dataAvailabilityFeeUSD = s_priceRegistry.getDataAvailabilityCost( + uint256 dataAvailabilityFeeUSD = s_feeQuoter.getDataAvailabilityCost( DEST_CHAIN_SELECTOR, USD_PER_DATA_AVAILABILITY_GAS, message.data.length, @@ -1658,7 +1626,7 @@ contract PriceRegistry_getValidatedFee is PriceRegistryFeeSetup { ); uint256 totalPriceInFeeToken = (gasFeeUSD + messageFeeUSD + dataAvailabilityFeeUSD) / feeTokenPrices[i]; - assertEq(totalPriceInFeeToken, s_priceRegistry.getValidatedFee(DEST_CHAIN_SELECTOR, message)); + assertEq(totalPriceInFeeToken, s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR, message)); } } @@ -1667,9 +1635,9 @@ contract PriceRegistry_getValidatedFee is PriceRegistryFeeSetup { vm.stopPrank(); vm.startPrank(OWNER); - PriceRegistry.DestChainConfigArgs[] memory destChainConfigArgs = _generatePriceRegistryDestChainConfigArgs(); + FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = _generateFeeQuoterDestChainConfigArgs(); destChainConfigArgs[0].destChainConfig.enforceOutOfOrder = enforce; - s_priceRegistry.applyDestChainConfigUpdates(destChainConfigArgs); + s_feeQuoter.applyDestChainConfigUpdates(destChainConfigArgs); Client.EVM2AnyMessage memory message = _generateEmptyMessage(); message.extraArgs = abi.encodeWithSelector( @@ -1679,16 +1647,16 @@ contract PriceRegistry_getValidatedFee is PriceRegistryFeeSetup { // If enforcement is on, only true should be allowed. if (enforce && !allowOutOfOrderExecution) { - vm.expectRevert(PriceRegistry.ExtraArgOutOfOrderExecutionMustBeTrue.selector); + vm.expectRevert(FeeQuoter.ExtraArgOutOfOrderExecutionMustBeTrue.selector); } - s_priceRegistry.getValidatedFee(DEST_CHAIN_SELECTOR, message); + s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR, message); } // Reverts function test_DestinationChainNotEnabled_Revert() public { - vm.expectRevert(abi.encodeWithSelector(PriceRegistry.DestinationChainNotEnabled.selector, DEST_CHAIN_SELECTOR + 1)); - s_priceRegistry.getValidatedFee(DEST_CHAIN_SELECTOR + 1, _generateEmptyMessage()); + vm.expectRevert(abi.encodeWithSelector(FeeQuoter.DestinationChainNotEnabled.selector, DEST_CHAIN_SELECTOR + 1)); + s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR + 1, _generateEmptyMessage()); } function test_EnforceOutOfOrder_Revert() public { @@ -1696,41 +1664,41 @@ contract PriceRegistry_getValidatedFee is PriceRegistryFeeSetup { vm.stopPrank(); vm.startPrank(OWNER); - PriceRegistry.DestChainConfigArgs[] memory destChainConfigArgs = _generatePriceRegistryDestChainConfigArgs(); + FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = _generateFeeQuoterDestChainConfigArgs(); destChainConfigArgs[0].destChainConfig.enforceOutOfOrder = true; - s_priceRegistry.applyDestChainConfigUpdates(destChainConfigArgs); + s_feeQuoter.applyDestChainConfigUpdates(destChainConfigArgs); vm.stopPrank(); Client.EVM2AnyMessage memory message = _generateEmptyMessage(); // Empty extraArgs to should revert since it enforceOutOfOrder is true. message.extraArgs = ""; - vm.expectRevert(PriceRegistry.ExtraArgOutOfOrderExecutionMustBeTrue.selector); - s_priceRegistry.getValidatedFee(DEST_CHAIN_SELECTOR, message); + vm.expectRevert(FeeQuoter.ExtraArgOutOfOrderExecutionMustBeTrue.selector); + s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR, message); } function test_MessageTooLarge_Revert() public { Client.EVM2AnyMessage memory message = _generateEmptyMessage(); message.data = new bytes(MAX_DATA_SIZE + 1); - vm.expectRevert(abi.encodeWithSelector(PriceRegistry.MessageTooLarge.selector, MAX_DATA_SIZE, message.data.length)); + vm.expectRevert(abi.encodeWithSelector(FeeQuoter.MessageTooLarge.selector, MAX_DATA_SIZE, message.data.length)); - s_priceRegistry.getValidatedFee(DEST_CHAIN_SELECTOR, message); + s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR, message); } function test_TooManyTokens_Revert() public { Client.EVM2AnyMessage memory message = _generateEmptyMessage(); uint256 tooMany = MAX_TOKENS_LENGTH + 1; message.tokenAmounts = new Client.EVMTokenAmount[](tooMany); - vm.expectRevert(PriceRegistry.UnsupportedNumberOfTokens.selector); - s_priceRegistry.getValidatedFee(DEST_CHAIN_SELECTOR, message); + vm.expectRevert(FeeQuoter.UnsupportedNumberOfTokens.selector); + s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR, message); } // Asserts gasLimit must be <=maxGasLimit function test_MessageGasLimitTooHigh_Revert() public { Client.EVM2AnyMessage memory message = _generateEmptyMessage(); message.extraArgs = Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: MAX_GAS_LIMIT + 1})); - vm.expectRevert(abi.encodeWithSelector(PriceRegistry.MessageGasLimitTooHigh.selector)); - s_priceRegistry.getValidatedFee(DEST_CHAIN_SELECTOR, message); + vm.expectRevert(abi.encodeWithSelector(FeeQuoter.MessageGasLimitTooHigh.selector)); + s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR, message); } function test_NotAFeeToken_Revert() public { @@ -1738,9 +1706,9 @@ contract PriceRegistry_getValidatedFee is PriceRegistryFeeSetup { Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(notAFeeToken, 1); message.feeToken = notAFeeToken; - vm.expectRevert(abi.encodeWithSelector(PriceRegistry.TokenNotSupported.selector, notAFeeToken)); + vm.expectRevert(abi.encodeWithSelector(FeeQuoter.TokenNotSupported.selector, notAFeeToken)); - s_priceRegistry.getValidatedFee(DEST_CHAIN_SELECTOR, message); + s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR, message); } function test_InvalidEVMAddress_Revert() public { @@ -1749,11 +1717,11 @@ contract PriceRegistry_getValidatedFee is PriceRegistryFeeSetup { vm.expectRevert(abi.encodeWithSelector(Internal.InvalidEVMAddress.selector, message.receiver)); - s_priceRegistry.getValidatedFee(DEST_CHAIN_SELECTOR, message); + s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR, message); } } -contract PriceRegistry_processMessageArgs is PriceRegistryFeeSetup { +contract FeeQuoter_processMessageArgs is FeeQuoterFeeSetup { using USDPriceWith18Decimals for uint224; function setUp() public virtual override { @@ -1766,7 +1734,7 @@ contract PriceRegistry_processMessageArgs is PriceRegistryFeeSetup { /* bool isOutOfOrderExecution */ , /* bytes memory convertedExtraArgs */ - ) = s_priceRegistry.processMessageArgs( + ) = s_feeQuoter.processMessageArgs( DEST_CHAIN_SELECTOR, // LINK s_sourceTokens[0], @@ -1780,14 +1748,14 @@ contract PriceRegistry_processMessageArgs is PriceRegistryFeeSetup { function test_WithConvertedTokenAmount_Success() public view { address feeToken = s_sourceTokens[1]; uint256 feeTokenAmount = 10_000 gwei; - uint256 expectedConvertedAmount = s_priceRegistry.convertTokenAmount(feeToken, feeTokenAmount, s_sourceTokens[0]); + uint256 expectedConvertedAmount = s_feeQuoter.convertTokenAmount(feeToken, feeTokenAmount, s_sourceTokens[0]); ( uint256 msgFeeJuels, /* bool isOutOfOrderExecution */ , /* bytes memory convertedExtraArgs */ - ) = s_priceRegistry.processMessageArgs(DEST_CHAIN_SELECTOR, feeToken, feeTokenAmount, ""); + ) = s_feeQuoter.processMessageArgs(DEST_CHAIN_SELECTOR, feeToken, feeTokenAmount, ""); assertEq(msgFeeJuels, expectedConvertedAmount); } @@ -1798,12 +1766,10 @@ contract PriceRegistry_processMessageArgs is PriceRegistryFeeSetup { , bool isOutOfOrderExecution, bytes memory convertedExtraArgs - ) = s_priceRegistry.processMessageArgs(DEST_CHAIN_SELECTOR, s_sourceTokens[0], 0, ""); + ) = s_feeQuoter.processMessageArgs(DEST_CHAIN_SELECTOR, s_sourceTokens[0], 0, ""); assertEq(isOutOfOrderExecution, false); - assertEq( - convertedExtraArgs, Client._argsToBytes(s_priceRegistry.parseEVMExtraArgsFromBytes("", DEST_CHAIN_SELECTOR)) - ); + assertEq(convertedExtraArgs, Client._argsToBytes(s_feeQuoter.parseEVMExtraArgsFromBytes("", DEST_CHAIN_SELECTOR))); } function test_WithEVMExtraArgsV1_Success() public view { @@ -1814,12 +1780,11 @@ contract PriceRegistry_processMessageArgs is PriceRegistryFeeSetup { , bool isOutOfOrderExecution, bytes memory convertedExtraArgs - ) = s_priceRegistry.processMessageArgs(DEST_CHAIN_SELECTOR, s_sourceTokens[0], 0, extraArgs); + ) = s_feeQuoter.processMessageArgs(DEST_CHAIN_SELECTOR, s_sourceTokens[0], 0, extraArgs); assertEq(isOutOfOrderExecution, false); assertEq( - convertedExtraArgs, - Client._argsToBytes(s_priceRegistry.parseEVMExtraArgsFromBytes(extraArgs, DEST_CHAIN_SELECTOR)) + convertedExtraArgs, Client._argsToBytes(s_feeQuoter.parseEVMExtraArgsFromBytes(extraArgs, DEST_CHAIN_SELECTOR)) ); } @@ -1831,12 +1796,11 @@ contract PriceRegistry_processMessageArgs is PriceRegistryFeeSetup { , bool isOutOfOrderExecution, bytes memory convertedExtraArgs - ) = s_priceRegistry.processMessageArgs(DEST_CHAIN_SELECTOR, s_sourceTokens[0], 0, extraArgs); + ) = s_feeQuoter.processMessageArgs(DEST_CHAIN_SELECTOR, s_sourceTokens[0], 0, extraArgs); assertEq(isOutOfOrderExecution, true); assertEq( - convertedExtraArgs, - Client._argsToBytes(s_priceRegistry.parseEVMExtraArgsFromBytes(extraArgs, DEST_CHAIN_SELECTOR)) + convertedExtraArgs, Client._argsToBytes(s_feeQuoter.parseEVMExtraArgsFromBytes(extraArgs, DEST_CHAIN_SELECTOR)) ); } @@ -1844,23 +1808,23 @@ contract PriceRegistry_processMessageArgs is PriceRegistryFeeSetup { function test_MessageFeeTooHigh_Revert() public { vm.expectRevert( - abi.encodeWithSelector(PriceRegistry.MessageFeeTooHigh.selector, MAX_MSG_FEES_JUELS + 1, MAX_MSG_FEES_JUELS) + abi.encodeWithSelector(FeeQuoter.MessageFeeTooHigh.selector, MAX_MSG_FEES_JUELS + 1, MAX_MSG_FEES_JUELS) ); - s_priceRegistry.processMessageArgs(DEST_CHAIN_SELECTOR, s_sourceTokens[0], MAX_MSG_FEES_JUELS + 1, ""); + s_feeQuoter.processMessageArgs(DEST_CHAIN_SELECTOR, s_sourceTokens[0], MAX_MSG_FEES_JUELS + 1, ""); } function test_InvalidExtraArgs_Revert() public { - vm.expectRevert(PriceRegistry.InvalidExtraArgsTag.selector); + vm.expectRevert(FeeQuoter.InvalidExtraArgsTag.selector); - s_priceRegistry.processMessageArgs(DEST_CHAIN_SELECTOR, s_sourceTokens[0], 0, "abcde"); + s_feeQuoter.processMessageArgs(DEST_CHAIN_SELECTOR, s_sourceTokens[0], 0, "abcde"); } function test_MalformedEVMExtraArgs_Revert() public { // abi.decode error vm.expectRevert(); - s_priceRegistry.processMessageArgs( + s_feeQuoter.processMessageArgs( DEST_CHAIN_SELECTOR, s_sourceTokens[0], 0, @@ -1869,8 +1833,8 @@ contract PriceRegistry_processMessageArgs is PriceRegistryFeeSetup { } } -contract PriceRegistry_processPoolReturnData is PriceRegistryFeeSetup { - function Test_ProcessPoolReturnData_Success() public view { +contract FeeQuoter_validatePoolReturnData is FeeQuoterFeeSetup { + function test_ProcessPoolReturnData_Success() public view { Client.EVMTokenAmount[] memory sourceTokenAmounts = new Client.EVMTokenAmount[](2); sourceTokenAmounts[0].amount = 1e18; sourceTokenAmounts[0].token = s_sourceTokens[0]; @@ -1882,13 +1846,13 @@ contract PriceRegistry_processPoolReturnData is PriceRegistryFeeSetup { rampTokenAmounts[1] = _getSourceTokenData(sourceTokenAmounts[1], s_tokenAdminRegistry, DEST_CHAIN_SELECTOR); bytes[] memory expectedDestExecData = new bytes[](2); expectedDestExecData[0] = abi.encode( - s_priceRegistryTokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig.destGasOverhead + s_feeQuoterTokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig.destGasOverhead ); expectedDestExecData[1] = abi.encode(DEFAULT_TOKEN_DEST_GAS_OVERHEAD); //expected return data should be abi.encoded default as isEnabled is false // No revert - successful bytes[] memory destExecData = - s_priceRegistry.processPoolReturnData(DEST_CHAIN_SELECTOR, rampTokenAmounts, sourceTokenAmounts); + s_feeQuoter.processPoolReturnData(DEST_CHAIN_SELECTOR, rampTokenAmounts, sourceTokenAmounts); for (uint256 i = 0; i < destExecData.length; ++i) { assertEq(destExecData[i], expectedDestExecData[i]); @@ -1906,7 +1870,7 @@ contract PriceRegistry_processPoolReturnData is PriceRegistryFeeSetup { // Revert due to index out of bounds access vm.expectRevert(); - s_priceRegistry.processPoolReturnData( + s_feeQuoter.processPoolReturnData( DEST_CHAIN_SELECTOR, new Internal.RampTokenAmount[](1), new Client.EVMTokenAmount[](0) ); } @@ -1922,24 +1886,22 @@ contract PriceRegistry_processPoolReturnData is PriceRegistryFeeSetup { rampTokenAmounts[0] = _getSourceTokenData(sourceTokenAmounts[0], s_tokenAdminRegistry, DEST_CHAIN_SELECTOR); // No data set, should succeed - s_priceRegistry.processPoolReturnData(DEST_CHAIN_SELECTOR, rampTokenAmounts, sourceTokenAmounts); + s_feeQuoter.processPoolReturnData(DEST_CHAIN_SELECTOR, rampTokenAmounts, sourceTokenAmounts); // Set max data length, should succeed rampTokenAmounts[0].extraData = new bytes(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES); - s_priceRegistry.processPoolReturnData(DEST_CHAIN_SELECTOR, rampTokenAmounts, sourceTokenAmounts); + s_feeQuoter.processPoolReturnData(DEST_CHAIN_SELECTOR, rampTokenAmounts, sourceTokenAmounts); // Set data to max length +1, should revert rampTokenAmounts[0].extraData = new bytes(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES + 1); - vm.expectRevert(abi.encodeWithSelector(PriceRegistry.SourceTokenDataTooLarge.selector, sourceETH)); - s_priceRegistry.processPoolReturnData(DEST_CHAIN_SELECTOR, rampTokenAmounts, sourceTokenAmounts); + vm.expectRevert(abi.encodeWithSelector(FeeQuoter.SourceTokenDataTooLarge.selector, sourceETH)); + s_feeQuoter.processPoolReturnData(DEST_CHAIN_SELECTOR, rampTokenAmounts, sourceTokenAmounts); // Set token config to allow larger data - PriceRegistry.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs = - _generateTokenTransferFeeConfigArgs(1, 1); + FeeQuoter.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs = _generateTokenTransferFeeConfigArgs(1, 1); tokenTransferFeeConfigArgs[0].destChainSelector = DEST_CHAIN_SELECTOR; tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token = sourceETH; - tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig = PriceRegistry - .TokenTransferFeeConfig({ + tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig = FeeQuoter.TokenTransferFeeConfig({ minFeeUSDCents: 1, maxFeeUSDCents: 0, deciBps: 0, @@ -1947,17 +1909,17 @@ contract PriceRegistry_processPoolReturnData is PriceRegistryFeeSetup { destBytesOverhead: uint32(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES) + 32, isEnabled: true }); - s_priceRegistry.applyTokenTransferFeeConfigUpdates( - tokenTransferFeeConfigArgs, new PriceRegistry.TokenTransferFeeConfigRemoveArgs[](0) + s_feeQuoter.applyTokenTransferFeeConfigUpdates( + tokenTransferFeeConfigArgs, new FeeQuoter.TokenTransferFeeConfigRemoveArgs[](0) ); - s_priceRegistry.processPoolReturnData(DEST_CHAIN_SELECTOR, rampTokenAmounts, sourceTokenAmounts); + s_feeQuoter.processPoolReturnData(DEST_CHAIN_SELECTOR, rampTokenAmounts, sourceTokenAmounts); // Set the token data larger than the configured token data, should revert rampTokenAmounts[0].extraData = new bytes(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES + 32 + 1); - vm.expectRevert(abi.encodeWithSelector(PriceRegistry.SourceTokenDataTooLarge.selector, sourceETH)); - s_priceRegistry.processPoolReturnData(DEST_CHAIN_SELECTOR, rampTokenAmounts, sourceTokenAmounts); + vm.expectRevert(abi.encodeWithSelector(FeeQuoter.SourceTokenDataTooLarge.selector, sourceETH)); + s_feeQuoter.processPoolReturnData(DEST_CHAIN_SELECTOR, rampTokenAmounts, sourceTokenAmounts); } function test_InvalidEVMAddressDestToken_Revert() public { @@ -1972,18 +1934,18 @@ contract PriceRegistry_processPoolReturnData is PriceRegistryFeeSetup { rampTokenAmounts[0].destTokenAddress = nonEvmAddress; vm.expectRevert(abi.encodeWithSelector(Internal.InvalidEVMAddress.selector, nonEvmAddress)); - s_priceRegistry.processPoolReturnData(DEST_CHAIN_SELECTOR, rampTokenAmounts, sourceTokenAmounts); + s_feeQuoter.processPoolReturnData(DEST_CHAIN_SELECTOR, rampTokenAmounts, sourceTokenAmounts); } } -contract PriceRegistry_validateDestFamilyAddress is PriceRegistrySetup { +contract FeeQuoter_validateDestFamilyAddress is FeeQuoterSetup { function test_ValidEVMAddress_Success() public view { bytes memory encodedAddress = abi.encode(address(10000)); - s_priceRegistry.validateDestFamilyAddress(Internal.CHAIN_FAMILY_SELECTOR_EVM, encodedAddress); + s_feeQuoter.validateDestFamilyAddress(Internal.CHAIN_FAMILY_SELECTOR_EVM, encodedAddress); } function test_ValidNonEVMAddress_Success() public view { - s_priceRegistry.validateDestFamilyAddress(bytes4(uint32(1)), abi.encode(type(uint208).max)); + s_feeQuoter.validateDestFamilyAddress(bytes4(uint32(1)), abi.encode(type(uint208).max)); } // Reverts @@ -1991,34 +1953,34 @@ contract PriceRegistry_validateDestFamilyAddress is PriceRegistrySetup { function test_InvalidEVMAddress_Revert() public { bytes memory invalidAddress = abi.encode(type(uint208).max); vm.expectRevert(abi.encodeWithSelector(Internal.InvalidEVMAddress.selector, invalidAddress)); - s_priceRegistry.validateDestFamilyAddress(Internal.CHAIN_FAMILY_SELECTOR_EVM, invalidAddress); + s_feeQuoter.validateDestFamilyAddress(Internal.CHAIN_FAMILY_SELECTOR_EVM, invalidAddress); } function test_InvalidEVMAddressEncodePacked_Revert() public { bytes memory invalidAddress = abi.encodePacked(address(234)); vm.expectRevert(abi.encodeWithSelector(Internal.InvalidEVMAddress.selector, invalidAddress)); - s_priceRegistry.validateDestFamilyAddress(Internal.CHAIN_FAMILY_SELECTOR_EVM, invalidAddress); + s_feeQuoter.validateDestFamilyAddress(Internal.CHAIN_FAMILY_SELECTOR_EVM, invalidAddress); } function test_InvalidEVMAddressPrecompiles_Revert() public { for (uint160 i = 0; i < Internal.PRECOMPILE_SPACE; ++i) { bytes memory invalidAddress = abi.encode(address(i)); vm.expectRevert(abi.encodeWithSelector(Internal.InvalidEVMAddress.selector, invalidAddress)); - s_priceRegistry.validateDestFamilyAddress(Internal.CHAIN_FAMILY_SELECTOR_EVM, invalidAddress); + s_feeQuoter.validateDestFamilyAddress(Internal.CHAIN_FAMILY_SELECTOR_EVM, invalidAddress); } - s_priceRegistry.validateDestFamilyAddress( + s_feeQuoter.validateDestFamilyAddress( Internal.CHAIN_FAMILY_SELECTOR_EVM, abi.encode(address(uint160(Internal.PRECOMPILE_SPACE))) ); } } -contract PriceRegistry_parseEVMExtraArgsFromBytes is PriceRegistrySetup { - PriceRegistry.DestChainConfig private s_destChainConfig; +contract FeeQuoter_parseEVMExtraArgsFromBytes is FeeQuoterSetup { + FeeQuoter.DestChainConfig private s_destChainConfig; function setUp() public virtual override { super.setUp(); - s_destChainConfig = _generatePriceRegistryDestChainConfigArgs()[0].destChainConfig; + s_destChainConfig = _generateFeeQuoterDestChainConfigArgs()[0].destChainConfig; } function test_EVMExtraArgsV1_Success() public view { @@ -2028,7 +1990,7 @@ contract PriceRegistry_parseEVMExtraArgsFromBytes is PriceRegistrySetup { Client.EVMExtraArgsV2({gasLimit: GAS_LIMIT, allowOutOfOrderExecution: false}); vm.assertEq( - abi.encode(s_priceRegistry.parseEVMExtraArgsFromBytes(inputExtraArgs, s_destChainConfig)), + abi.encode(s_feeQuoter.parseEVMExtraArgsFromBytes(inputExtraArgs, s_destChainConfig)), abi.encode(expectedOutputArgs) ); } @@ -2039,7 +2001,7 @@ contract PriceRegistry_parseEVMExtraArgsFromBytes is PriceRegistrySetup { bytes memory inputExtraArgs = Client._argsToBytes(inputArgs); vm.assertEq( - abi.encode(s_priceRegistry.parseEVMExtraArgsFromBytes(inputExtraArgs, s_destChainConfig)), abi.encode(inputArgs) + abi.encode(s_feeQuoter.parseEVMExtraArgsFromBytes(inputExtraArgs, s_destChainConfig)), abi.encode(inputArgs) ); } @@ -2048,7 +2010,7 @@ contract PriceRegistry_parseEVMExtraArgsFromBytes is PriceRegistrySetup { Client.EVMExtraArgsV2({gasLimit: s_destChainConfig.defaultTxGasLimit, allowOutOfOrderExecution: false}); vm.assertEq( - abi.encode(s_priceRegistry.parseEVMExtraArgsFromBytes("", s_destChainConfig)), abi.encode(expectedOutputArgs) + abi.encode(s_feeQuoter.parseEVMExtraArgsFromBytes("", s_destChainConfig)), abi.encode(expectedOutputArgs) ); } @@ -2061,8 +2023,8 @@ contract PriceRegistry_parseEVMExtraArgsFromBytes is PriceRegistrySetup { // Invalidate selector inputExtraArgs[0] = bytes1(uint8(0)); - vm.expectRevert(PriceRegistry.InvalidExtraArgsTag.selector); - s_priceRegistry.parseEVMExtraArgsFromBytes(inputExtraArgs, s_destChainConfig); + vm.expectRevert(FeeQuoter.InvalidExtraArgsTag.selector); + s_feeQuoter.parseEVMExtraArgsFromBytes(inputExtraArgs, s_destChainConfig); } function test_EVMExtraArgsEnforceOutOfOrder_Revert() public { @@ -2071,8 +2033,8 @@ contract PriceRegistry_parseEVMExtraArgsFromBytes is PriceRegistrySetup { bytes memory inputExtraArgs = Client._argsToBytes(inputArgs); s_destChainConfig.enforceOutOfOrder = true; - vm.expectRevert(PriceRegistry.ExtraArgOutOfOrderExecutionMustBeTrue.selector); - s_priceRegistry.parseEVMExtraArgsFromBytes(inputExtraArgs, s_destChainConfig); + vm.expectRevert(FeeQuoter.ExtraArgOutOfOrderExecutionMustBeTrue.selector); + s_feeQuoter.parseEVMExtraArgsFromBytes(inputExtraArgs, s_destChainConfig); } function test_EVMExtraArgsGasLimitTooHigh_Revert() public { @@ -2080,18 +2042,18 @@ contract PriceRegistry_parseEVMExtraArgsFromBytes is PriceRegistrySetup { Client.EVMExtraArgsV2({gasLimit: s_destChainConfig.maxPerMsgGasLimit + 1, allowOutOfOrderExecution: true}); bytes memory inputExtraArgs = Client._argsToBytes(inputArgs); - vm.expectRevert(PriceRegistry.MessageGasLimitTooHigh.selector); - s_priceRegistry.parseEVMExtraArgsFromBytes(inputExtraArgs, s_destChainConfig); + vm.expectRevert(FeeQuoter.MessageGasLimitTooHigh.selector); + s_feeQuoter.parseEVMExtraArgsFromBytes(inputExtraArgs, s_destChainConfig); } } -contract PriceRegistry_KeystoneSetup is PriceRegistrySetup { - address constant FORWARDER_1 = address(0x1); - address constant WORKFLOW_OWNER_1 = address(0x3); - bytes10 constant WORKFLOW_NAME_1 = "workflow1"; - bytes2 constant REPORT_NAME_1 = "01"; - address onReportTestToken1; - address onReportTestToken2; +contract FeeQuoter_KeystoneSetup is FeeQuoterSetup { + address internal constant FORWARDER_1 = address(0x1); + address internal constant WORKFLOW_OWNER_1 = address(0x3); + bytes10 internal constant WORKFLOW_NAME_1 = "workflow1"; + bytes2 internal constant REPORT_NAME_1 = "01"; + address internal onReportTestToken1; + address internal onReportTestToken2; function setUp() public virtual override { super.setUp(); @@ -2106,57 +2068,54 @@ contract PriceRegistry_KeystoneSetup is PriceRegistrySetup { reportName: REPORT_NAME_1, isAllowed: true }); - PriceRegistry.TokenPriceFeedUpdate[] memory tokenPriceFeeds = new PriceRegistry.TokenPriceFeedUpdate[](2); - tokenPriceFeeds[0] = PriceRegistry.TokenPriceFeedUpdate({ + FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeeds = new FeeQuoter.TokenPriceFeedUpdate[](2); + tokenPriceFeeds[0] = FeeQuoter.TokenPriceFeedUpdate({ sourceToken: onReportTestToken1, - feedConfig: IPriceRegistry.TokenPriceFeedConfig({dataFeedAddress: address(0x0), tokenDecimals: 18}) + feedConfig: IFeeQuoter.TokenPriceFeedConfig({dataFeedAddress: address(0x0), tokenDecimals: 18}) }); - tokenPriceFeeds[1] = PriceRegistry.TokenPriceFeedUpdate({ + tokenPriceFeeds[1] = FeeQuoter.TokenPriceFeedUpdate({ sourceToken: onReportTestToken2, - feedConfig: IPriceRegistry.TokenPriceFeedConfig({dataFeedAddress: address(0x0), tokenDecimals: 20}) + feedConfig: IFeeQuoter.TokenPriceFeedConfig({dataFeedAddress: address(0x0), tokenDecimals: 20}) }); - s_priceRegistry.setReportPermissions(permissions); - s_priceRegistry.updateTokenPriceFeeds(tokenPriceFeeds); + s_feeQuoter.setReportPermissions(permissions); + s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeeds); } } -contract PriceRegistry_onReport is PriceRegistry_KeystoneSetup { +contract FeeQuoter_onReport is FeeQuoter_KeystoneSetup { function test_onReport_Success() public { bytes memory encodedPermissionsMetadata = abi.encodePacked(keccak256(abi.encode("workflowCID")), WORKFLOW_NAME_1, WORKFLOW_OWNER_1, REPORT_NAME_1); - PriceRegistry.ReceivedCCIPFeedReport[] memory report = new PriceRegistry.ReceivedCCIPFeedReport[](2); + FeeQuoter.ReceivedCCIPFeedReport[] memory report = new FeeQuoter.ReceivedCCIPFeedReport[](2); report[0] = - PriceRegistry.ReceivedCCIPFeedReport({token: onReportTestToken1, price: 4e18, timestamp: uint32(block.timestamp)}); + FeeQuoter.ReceivedCCIPFeedReport({token: onReportTestToken1, price: 4e18, timestamp: uint32(block.timestamp)}); report[1] = - PriceRegistry.ReceivedCCIPFeedReport({token: onReportTestToken2, price: 4e18, timestamp: uint32(block.timestamp)}); + FeeQuoter.ReceivedCCIPFeedReport({token: onReportTestToken2, price: 4e18, timestamp: uint32(block.timestamp)}); - bytes memory encodedReport = abi.encode(report); - uint224 expectedStoredToken1Price = s_priceRegistry.calculateRebasedValue(18, 18, report[0].price); - uint224 expectedStoredToken2Price = s_priceRegistry.calculateRebasedValue(18, 20, report[1].price); + uint224 expectedStoredToken1Price = s_feeQuoter.calculateRebasedValue(18, 18, report[0].price); + uint224 expectedStoredToken2Price = s_feeQuoter.calculateRebasedValue(18, 20, report[1].price); vm.expectEmit(); - emit PriceRegistry.UsdPerTokenUpdated(onReportTestToken1, expectedStoredToken1Price, block.timestamp); + emit FeeQuoter.UsdPerTokenUpdated(onReportTestToken1, expectedStoredToken1Price, block.timestamp); vm.expectEmit(); - emit PriceRegistry.UsdPerTokenUpdated(onReportTestToken2, expectedStoredToken2Price, block.timestamp); + emit FeeQuoter.UsdPerTokenUpdated(onReportTestToken2, expectedStoredToken2Price, block.timestamp); changePrank(FORWARDER_1); - s_priceRegistry.onReport(encodedPermissionsMetadata, encodedReport); + s_feeQuoter.onReport(encodedPermissionsMetadata, abi.encode(report)); - vm.assertEq(s_priceRegistry.getTokenPrice(report[0].token).value, expectedStoredToken1Price); - vm.assertEq(s_priceRegistry.getTokenPrice(report[0].token).timestamp, report[0].timestamp); + vm.assertEq(s_feeQuoter.getTokenPrice(report[0].token).value, expectedStoredToken1Price); + vm.assertEq(s_feeQuoter.getTokenPrice(report[0].token).timestamp, report[0].timestamp); - vm.assertEq(s_priceRegistry.getTokenPrice(report[1].token).value, expectedStoredToken2Price); - vm.assertEq(s_priceRegistry.getTokenPrice(report[1].token).timestamp, report[1].timestamp); + vm.assertEq(s_feeQuoter.getTokenPrice(report[1].token).value, expectedStoredToken2Price); + vm.assertEq(s_feeQuoter.getTokenPrice(report[1].token).timestamp, report[1].timestamp); } function test_onReport_InvalidForwarder_Reverts() public { bytes memory encodedPermissionsMetadata = abi.encodePacked(keccak256(abi.encode("workflowCID")), WORKFLOW_NAME_1, WORKFLOW_OWNER_1, REPORT_NAME_1); - PriceRegistry.ReceivedCCIPFeedReport[] memory report = new PriceRegistry.ReceivedCCIPFeedReport[](1); + FeeQuoter.ReceivedCCIPFeedReport[] memory report = new FeeQuoter.ReceivedCCIPFeedReport[](1); report[0] = - PriceRegistry.ReceivedCCIPFeedReport({token: s_sourceTokens[0], price: 4e18, timestamp: uint32(block.timestamp)}); - - bytes memory encodedReport = abi.encode(report); + FeeQuoter.ReceivedCCIPFeedReport({token: s_sourceTokens[0], price: 4e18, timestamp: uint32(block.timestamp)}); vm.expectRevert( abi.encodeWithSelector( @@ -2168,21 +2127,19 @@ contract PriceRegistry_onReport is PriceRegistry_KeystoneSetup { ) ); changePrank(STRANGER); - s_priceRegistry.onReport(encodedPermissionsMetadata, encodedReport); + s_feeQuoter.onReport(encodedPermissionsMetadata, abi.encode(report)); } function test_onReport_UnsupportedToken_Reverts() public { bytes memory encodedPermissionsMetadata = abi.encodePacked(keccak256(abi.encode("workflowCID")), WORKFLOW_NAME_1, WORKFLOW_OWNER_1, REPORT_NAME_1); - PriceRegistry.ReceivedCCIPFeedReport[] memory report = new PriceRegistry.ReceivedCCIPFeedReport[](1); + FeeQuoter.ReceivedCCIPFeedReport[] memory report = new FeeQuoter.ReceivedCCIPFeedReport[](1); report[0] = - PriceRegistry.ReceivedCCIPFeedReport({token: s_sourceTokens[1], price: 4e18, timestamp: uint32(block.timestamp)}); + FeeQuoter.ReceivedCCIPFeedReport({token: s_sourceTokens[1], price: 4e18, timestamp: uint32(block.timestamp)}); - bytes memory encodedReport = abi.encode(report); - - vm.expectRevert(abi.encodeWithSelector(PriceRegistry.TokenNotSupported.selector, s_sourceTokens[1])); + vm.expectRevert(abi.encodeWithSelector(FeeQuoter.TokenNotSupported.selector, s_sourceTokens[1])); changePrank(FORWARDER_1); - s_priceRegistry.onReport(encodedPermissionsMetadata, encodedReport); + s_feeQuoter.onReport(encodedPermissionsMetadata, abi.encode(report)); } function test_OnReport_StaleUpdate_Revert() public { @@ -2190,33 +2147,28 @@ contract PriceRegistry_onReport is PriceRegistry_KeystoneSetup { bytes memory encodedPermissionsMetadata = abi.encodePacked(keccak256(abi.encode("workflowCID")), WORKFLOW_NAME_1, WORKFLOW_OWNER_1, REPORT_NAME_1); - PriceRegistry.ReceivedCCIPFeedReport[] memory report = new PriceRegistry.ReceivedCCIPFeedReport[](1); + FeeQuoter.ReceivedCCIPFeedReport[] memory report = new FeeQuoter.ReceivedCCIPFeedReport[](1); report[0] = - PriceRegistry.ReceivedCCIPFeedReport({token: onReportTestToken1, price: 4e18, timestamp: uint32(block.timestamp)}); + FeeQuoter.ReceivedCCIPFeedReport({token: onReportTestToken1, price: 4e18, timestamp: uint32(block.timestamp)}); - bytes memory encodedReport = abi.encode(report); - uint224 expectedStoredTokenPrice = s_priceRegistry.calculateRebasedValue(18, 18, report[0].price); + uint224 expectedStoredTokenPrice = s_feeQuoter.calculateRebasedValue(18, 18, report[0].price); vm.expectEmit(); - emit PriceRegistry.UsdPerTokenUpdated(onReportTestToken1, expectedStoredTokenPrice, block.timestamp); + emit FeeQuoter.UsdPerTokenUpdated(onReportTestToken1, expectedStoredTokenPrice, block.timestamp); changePrank(FORWARDER_1); //setting the correct price and time with the correct report - s_priceRegistry.onReport(encodedPermissionsMetadata, encodedReport); + s_feeQuoter.onReport(encodedPermissionsMetadata, abi.encode(report)); //create a stale report - report[0] = PriceRegistry.ReceivedCCIPFeedReport({ - token: onReportTestToken1, - price: 4e18, - timestamp: uint32(block.timestamp - 1) - }); - encodedReport = abi.encode(report); + report[0] = + FeeQuoter.ReceivedCCIPFeedReport({token: onReportTestToken1, price: 4e18, timestamp: uint32(block.timestamp - 1)}); //expecting a revert vm.expectRevert( abi.encodeWithSelector( - PriceRegistry.StaleKeystoneUpdate.selector, onReportTestToken1, block.timestamp - 1, block.timestamp + FeeQuoter.StaleKeystoneUpdate.selector, onReportTestToken1, block.timestamp - 1, block.timestamp ) ); - s_priceRegistry.onReport(encodedPermissionsMetadata, encodedReport); + s_feeQuoter.onReport(encodedPermissionsMetadata, abi.encode(report)); } } diff --git a/contracts/src/v0.8/ccip/test/priceRegistry/PriceRegistrySetup.t.sol b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoterSetup.t.sol similarity index 76% rename from contracts/src/v0.8/ccip/test/priceRegistry/PriceRegistrySetup.t.sol rename to contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoterSetup.t.sol index ee76c51c53..124980bc81 100644 --- a/contracts/src/v0.8/ccip/test/priceRegistry/PriceRegistrySetup.t.sol +++ b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoterSetup.t.sol @@ -1,17 +1,17 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.24; -import {IPriceRegistry} from "../../interfaces/IPriceRegistry.sol"; +import {IFeeQuoter} from "../../interfaces/IFeeQuoter.sol"; import {MockV3Aggregator} from "../../../tests/MockV3Aggregator.sol"; -import {PriceRegistry} from "../../PriceRegistry.sol"; +import {FeeQuoter} from "../../FeeQuoter.sol"; import {Client} from "../../libraries/Client.sol"; import {Internal} from "../../libraries/Internal.sol"; import {TokenAdminRegistry} from "../../tokenAdminRegistry/TokenAdminRegistry.sol"; import {TokenSetup} from "../TokenSetup.t.sol"; -import {PriceRegistryHelper} from "../helpers/PriceRegistryHelper.sol"; +import {FeeQuoterHelper} from "../helpers/FeeQuoterHelper.sol"; -contract PriceRegistrySetup is TokenSetup { +contract FeeQuoterSetup is TokenSetup { uint112 internal constant USD_PER_GAS = 1e6; // 0.001 gwei uint112 internal constant USD_PER_DATA_AVAILABILITY_GAS = 1e9; // 1 gwei @@ -26,7 +26,7 @@ contract PriceRegistrySetup is TokenSetup { uint224 internal constant PACKED_USD_PER_GAS = (uint224(USD_PER_DATA_AVAILABILITY_GAS) << Internal.GAS_PRICE_BITS) + USD_PER_GAS; - PriceRegistryHelper internal s_priceRegistry; + FeeQuoterHelper internal s_feeQuoter; // Cheat to store the price updates in storage since struct arrays aren't supported. bytes internal s_encodedInitialPriceUpdates; address internal s_weth; @@ -36,8 +36,8 @@ contract PriceRegistrySetup is TokenSetup { address[] internal s_destFeeTokens; uint224[] internal s_destTokenPrices; - PriceRegistry.PremiumMultiplierWeiPerEthArgs[] internal s_priceRegistryPremiumMultiplierWeiPerEthArgs; - PriceRegistry.TokenTransferFeeConfigArgs[] internal s_priceRegistryTokenTransferFeeConfigArgs; + FeeQuoter.PremiumMultiplierWeiPerEthArgs[] internal s_feeQuoterPremiumMultiplierWeiPerEthArgs; + FeeQuoter.TokenTransferFeeConfigArgs[] internal s_feeQuoterTokenTransferFeeConfigArgs; mapping(address token => address dataFeedAddress) internal s_dataFeedByToken; @@ -98,27 +98,27 @@ contract PriceRegistrySetup is TokenSetup { address[] memory feeTokens = new address[](2); feeTokens[0] = s_sourceTokens[0]; feeTokens[1] = s_weth; - PriceRegistry.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new PriceRegistry.TokenPriceFeedUpdate[](0); + FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](0); - s_priceRegistryPremiumMultiplierWeiPerEthArgs.push( - PriceRegistry.PremiumMultiplierWeiPerEthArgs({ + s_feeQuoterPremiumMultiplierWeiPerEthArgs.push( + FeeQuoter.PremiumMultiplierWeiPerEthArgs({ token: s_sourceFeeToken, premiumMultiplierWeiPerEth: 5e17 // 0.5x }) ); - s_priceRegistryPremiumMultiplierWeiPerEthArgs.push( - PriceRegistry.PremiumMultiplierWeiPerEthArgs({ + s_feeQuoterPremiumMultiplierWeiPerEthArgs.push( + FeeQuoter.PremiumMultiplierWeiPerEthArgs({ token: s_sourceRouter.getWrappedNative(), premiumMultiplierWeiPerEth: 2e18 // 2x }) ); - s_priceRegistryTokenTransferFeeConfigArgs.push(); - s_priceRegistryTokenTransferFeeConfigArgs[0].destChainSelector = DEST_CHAIN_SELECTOR; - s_priceRegistryTokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs.push( - PriceRegistry.TokenTransferFeeConfigSingleTokenArgs({ + s_feeQuoterTokenTransferFeeConfigArgs.push(); + s_feeQuoterTokenTransferFeeConfigArgs[0].destChainSelector = DEST_CHAIN_SELECTOR; + s_feeQuoterTokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs.push( + FeeQuoter.TokenTransferFeeConfigSingleTokenArgs({ token: s_sourceFeeToken, - tokenTransferFeeConfig: PriceRegistry.TokenTransferFeeConfig({ + tokenTransferFeeConfig: FeeQuoter.TokenTransferFeeConfig({ minFeeUSDCents: 1_00, // 1 USD maxFeeUSDCents: 1000_00, // 1,000 USD deciBps: 2_5, // 2.5 bps, or 0.025% @@ -128,10 +128,10 @@ contract PriceRegistrySetup is TokenSetup { }) }) ); - s_priceRegistryTokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs.push( - PriceRegistry.TokenTransferFeeConfigSingleTokenArgs({ + s_feeQuoterTokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs.push( + FeeQuoter.TokenTransferFeeConfigSingleTokenArgs({ token: CUSTOM_TOKEN, - tokenTransferFeeConfig: PriceRegistry.TokenTransferFeeConfig({ + tokenTransferFeeConfig: FeeQuoter.TokenTransferFeeConfig({ minFeeUSDCents: 2_00, // 1 USD maxFeeUSDCents: 2000_00, // 1,000 USD deciBps: 10_0, // 10 bps, or 0.1% @@ -141,10 +141,10 @@ contract PriceRegistrySetup is TokenSetup { }) }) ); - s_priceRegistryTokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs.push( - PriceRegistry.TokenTransferFeeConfigSingleTokenArgs({ + s_feeQuoterTokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs.push( + FeeQuoter.TokenTransferFeeConfigSingleTokenArgs({ token: CUSTOM_TOKEN_2, - tokenTransferFeeConfig: PriceRegistry.TokenTransferFeeConfig({ + tokenTransferFeeConfig: FeeQuoter.TokenTransferFeeConfig({ minFeeUSDCents: 2_00, // 1 USD maxFeeUSDCents: 2000_00, // 1,000 USD deciBps: 10_0, // 10 bps, or 0.1% @@ -158,8 +158,8 @@ contract PriceRegistrySetup is TokenSetup { //setting up the destination token for CUSTOM_TOKEN_2 here as it is specific to these tests s_destTokenBySourceToken[CUSTOM_TOKEN_2] = address(bytes20(keccak256("CUSTOM_TOKEN_2_DEST"))); - s_priceRegistry = new PriceRegistryHelper( - PriceRegistry.StaticConfig({ + s_feeQuoter = new FeeQuoterHelper( + FeeQuoter.StaticConfig({ linkToken: s_sourceTokens[0], maxFeeJuelsPerMsg: MAX_MSG_FEES_JUELS, stalenessThreshold: uint32(TWELVE_HOURS) @@ -167,11 +167,11 @@ contract PriceRegistrySetup is TokenSetup { priceUpdaters, feeTokens, tokenPriceFeedUpdates, - s_priceRegistryTokenTransferFeeConfigArgs, - s_priceRegistryPremiumMultiplierWeiPerEthArgs, - _generatePriceRegistryDestChainConfigArgs() + s_feeQuoterTokenTransferFeeConfigArgs, + s_feeQuoterPremiumMultiplierWeiPerEthArgs, + _generateFeeQuoterDestChainConfigArgs() ); - s_priceRegistry.updatePrices(priceUpdates); + s_feeQuoter.updatePrices(priceUpdates); } function _deployTokenPriceDataFeed(address token, uint8 decimals, int256 initialAnswer) internal returns (address) { @@ -207,43 +207,39 @@ contract PriceRegistrySetup is TokenSetup { address sourceToken, address dataFeedAddress, uint8 tokenDecimals - ) internal pure returns (PriceRegistry.TokenPriceFeedUpdate memory) { - return PriceRegistry.TokenPriceFeedUpdate({ + ) internal pure returns (FeeQuoter.TokenPriceFeedUpdate memory) { + return FeeQuoter.TokenPriceFeedUpdate({ sourceToken: sourceToken, - feedConfig: IPriceRegistry.TokenPriceFeedConfig({dataFeedAddress: dataFeedAddress, tokenDecimals: tokenDecimals}) + feedConfig: IFeeQuoter.TokenPriceFeedConfig({dataFeedAddress: dataFeedAddress, tokenDecimals: tokenDecimals}) }); } function _initialiseSingleTokenPriceFeed() internal returns (address) { - PriceRegistry.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new PriceRegistry.TokenPriceFeedUpdate[](1); + FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeedUpdates = new FeeQuoter.TokenPriceFeedUpdate[](1); tokenPriceFeedUpdates[0] = _getSingleTokenPriceFeedUpdateStruct(s_sourceTokens[0], s_dataFeedByToken[s_sourceTokens[0]], 18); - s_priceRegistry.updateTokenPriceFeeds(tokenPriceFeedUpdates); + s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeedUpdates); return s_sourceTokens[0]; } function _generateTokenTransferFeeConfigArgs( uint256 destChainSelectorLength, uint256 tokenLength - ) internal pure returns (PriceRegistry.TokenTransferFeeConfigArgs[] memory) { - PriceRegistry.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs = - new PriceRegistry.TokenTransferFeeConfigArgs[](destChainSelectorLength); + ) internal pure returns (FeeQuoter.TokenTransferFeeConfigArgs[] memory) { + FeeQuoter.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs = + new FeeQuoter.TokenTransferFeeConfigArgs[](destChainSelectorLength); for (uint256 i = 0; i < destChainSelectorLength; ++i) { tokenTransferFeeConfigArgs[i].tokenTransferFeeConfigs = - new PriceRegistry.TokenTransferFeeConfigSingleTokenArgs[](tokenLength); + new FeeQuoter.TokenTransferFeeConfigSingleTokenArgs[](tokenLength); } return tokenTransferFeeConfigArgs; } - function _generatePriceRegistryDestChainConfigArgs() - internal - pure - returns (PriceRegistry.DestChainConfigArgs[] memory) - { - PriceRegistry.DestChainConfigArgs[] memory destChainConfigs = new PriceRegistry.DestChainConfigArgs[](1); - destChainConfigs[0] = PriceRegistry.DestChainConfigArgs({ + function _generateFeeQuoterDestChainConfigArgs() internal pure returns (FeeQuoter.DestChainConfigArgs[] memory) { + FeeQuoter.DestChainConfigArgs[] memory destChainConfigs = new FeeQuoter.DestChainConfigArgs[](1); + destChainConfigs[0] = FeeQuoter.DestChainConfigArgs({ destChainSelector: DEST_CHAIN_SELECTOR, - destChainConfig: PriceRegistry.DestChainConfig({ + destChainConfig: FeeQuoter.DestChainConfig({ isEnabled: true, maxNumberOfTokensPerMsg: MAX_TOKENS_LENGTH, destGasOverhead: DEST_GAS_OVERHEAD, @@ -266,26 +262,22 @@ contract PriceRegistrySetup is TokenSetup { } function _assertTokenPriceFeedConfigEquality( - IPriceRegistry.TokenPriceFeedConfig memory config1, - IPriceRegistry.TokenPriceFeedConfig memory config2 + IFeeQuoter.TokenPriceFeedConfig memory config1, + IFeeQuoter.TokenPriceFeedConfig memory config2 ) internal pure virtual { assertEq(config1.dataFeedAddress, config2.dataFeedAddress); assertEq(config1.tokenDecimals, config2.tokenDecimals); } - function _assertTokenPriceFeedConfigUnconfigured(IPriceRegistry.TokenPriceFeedConfig memory config) - internal - pure - virtual - { + function _assertTokenPriceFeedConfigUnconfigured(IFeeQuoter.TokenPriceFeedConfig memory config) internal pure virtual { _assertTokenPriceFeedConfigEquality( - config, IPriceRegistry.TokenPriceFeedConfig({dataFeedAddress: address(0), tokenDecimals: 0}) + config, IFeeQuoter.TokenPriceFeedConfig({dataFeedAddress: address(0), tokenDecimals: 0}) ); } function _assertTokenTransferFeeConfigEqual( - PriceRegistry.TokenTransferFeeConfig memory a, - PriceRegistry.TokenTransferFeeConfig memory b + FeeQuoter.TokenTransferFeeConfig memory a, + FeeQuoter.TokenTransferFeeConfig memory b ) internal pure { assertEq(a.minFeeUSDCents, b.minFeeUSDCents); assertEq(a.maxFeeUSDCents, b.maxFeeUSDCents); @@ -295,17 +287,17 @@ contract PriceRegistrySetup is TokenSetup { assertEq(a.isEnabled, b.isEnabled); } - function _assertPriceRegistryStaticConfigsEqual( - PriceRegistry.StaticConfig memory a, - PriceRegistry.StaticConfig memory b + function _assertFeeQuoterStaticConfigsEqual( + FeeQuoter.StaticConfig memory a, + FeeQuoter.StaticConfig memory b ) internal pure { assertEq(a.linkToken, b.linkToken); assertEq(a.maxFeeJuelsPerMsg, b.maxFeeJuelsPerMsg); } - function _assertPriceRegistryDestChainConfigsEqual( - PriceRegistry.DestChainConfig memory a, - PriceRegistry.DestChainConfig memory b + function _assertFeeQuoterDestChainConfigsEqual( + FeeQuoter.DestChainConfig memory a, + FeeQuoter.DestChainConfig memory b ) internal pure { assertEq(a.isEnabled, b.isEnabled); assertEq(a.maxNumberOfTokensPerMsg, b.maxNumberOfTokensPerMsg); @@ -322,7 +314,7 @@ contract PriceRegistrySetup is TokenSetup { } } -contract PriceRegistryFeeSetup is PriceRegistrySetup { +contract FeeQuoterFeeSetup is FeeQuoterSetup { uint224 internal s_feeTokenPrice; uint224 internal s_wrappedTokenPrice; uint224 internal s_customTokenPrice; @@ -339,7 +331,7 @@ contract PriceRegistryFeeSetup is PriceRegistrySetup { s_wrappedTokenPrice = s_sourceTokenPrices[2]; s_customTokenPrice = CUSTOM_TOKEN_PRICE; - s_priceRegistry.updatePrices(_getSingleTokenPriceUpdateStruct(CUSTOM_TOKEN, CUSTOM_TOKEN_PRICE)); + s_feeQuoter.updatePrices(_getSingleTokenPriceUpdateStruct(CUSTOM_TOKEN, CUSTOM_TOKEN_PRICE)); } function _generateEmptyMessage() public view returns (Client.EVM2AnyMessage memory) { @@ -380,7 +372,7 @@ contract PriceRegistryFeeSetup is PriceRegistrySetup { TokenAdminRegistry tokenAdminRegistry ) internal view returns (Internal.EVM2AnyRampMessage memory) { Client.EVMExtraArgsV2 memory extraArgs = - s_priceRegistry.parseEVMExtraArgsFromBytes(message.extraArgs, destChainSelector); + s_feeQuoter.parseEVMExtraArgsFromBytes(message.extraArgs, destChainSelector); Internal.EVM2AnyRampMessage memory messageEvent = Internal.EVM2AnyRampMessage({ header: Internal.RampMessageHeader({ @@ -415,12 +407,9 @@ contract PriceRegistryFeeSetup is PriceRegistrySetup { ) internal view returns (Internal.RampTokenAmount memory) { address destToken = s_destTokenBySourceToken[tokenAmount.token]; - uint256 tokenTransferFeeConfigArgIndex; - uint256 tokenTransferFeeConfigsIndex; - uint32 expectedDestGasAmount; - PriceRegistry.TokenTransferFeeConfig memory tokenTransferFeeConfig = - PriceRegistry(s_priceRegistry).getTokenTransferFeeConfig(destChainSelector, tokenAmount.token); + FeeQuoter.TokenTransferFeeConfig memory tokenTransferFeeConfig = + FeeQuoter(s_feeQuoter).getTokenTransferFeeConfig(destChainSelector, tokenAmount.token); expectedDestGasAmount = tokenTransferFeeConfig.isEnabled ? tokenTransferFeeConfig.destGasOverhead : DEFAULT_TOKEN_DEST_GAS_OVERHEAD; diff --git a/contracts/src/v0.8/ccip/test/helpers/PriceRegistryHelper.sol b/contracts/src/v0.8/ccip/test/helpers/FeeQuoterHelper.sol similarity index 95% rename from contracts/src/v0.8/ccip/test/helpers/PriceRegistryHelper.sol rename to contracts/src/v0.8/ccip/test/helpers/FeeQuoterHelper.sol index f939cd3c1f..e392ba0558 100644 --- a/contracts/src/v0.8/ccip/test/helpers/PriceRegistryHelper.sol +++ b/contracts/src/v0.8/ccip/test/helpers/FeeQuoterHelper.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.24; -import {PriceRegistry} from "../../PriceRegistry.sol"; +import {FeeQuoter} from "../../FeeQuoter.sol"; import {Client} from "../../libraries/Client.sol"; -contract PriceRegistryHelper is PriceRegistry { +contract FeeQuoterHelper is FeeQuoter { constructor( StaticConfig memory staticConfig, address[] memory priceUpdaters, @@ -14,7 +14,7 @@ contract PriceRegistryHelper is PriceRegistry { PremiumMultiplierWeiPerEthArgs[] memory premiumMultiplierWeiPerEthArgs, DestChainConfigArgs[] memory destChainConfigArgs ) - PriceRegistry( + FeeQuoter( staticConfig, priceUpdaters, feeTokens, diff --git a/contracts/src/v0.8/ccip/test/helpers/MultiAggregateRateLimiterHelper.sol b/contracts/src/v0.8/ccip/test/helpers/MultiAggregateRateLimiterHelper.sol index 2bcaabda33..d011ba0685 100644 --- a/contracts/src/v0.8/ccip/test/helpers/MultiAggregateRateLimiterHelper.sol +++ b/contracts/src/v0.8/ccip/test/helpers/MultiAggregateRateLimiterHelper.sol @@ -6,9 +6,9 @@ import {Client} from "../../libraries/Client.sol"; contract MultiAggregateRateLimiterHelper is MultiAggregateRateLimiter { constructor( - address priceRegistry, + address feeQuoter, address[] memory authorizedCallers - ) MultiAggregateRateLimiter(priceRegistry, authorizedCallers) {} + ) MultiAggregateRateLimiter(feeQuoter, authorizedCallers) {} function getTokenValue(Client.EVMTokenAmount memory tokenAmount) public view returns (uint256) { return _getTokenValue(tokenAmount); diff --git a/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMOffRamp.t.sol b/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMOffRamp.t.sol index 6162419367..493d02c7c2 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMOffRamp.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMOffRamp.t.sol @@ -41,7 +41,7 @@ contract EVM2EVMOffRamp_constructor is EVM2EVMOffRampSetup { tokenAdminRegistry: address(s_tokenAdminRegistry) }); EVM2EVMOffRamp.DynamicConfig memory dynamicConfig = - generateDynamicOffRampConfig(address(s_destRouter), address(s_priceRegistry)); + generateDynamicOffRampConfig(address(s_destRouter), address(s_feeQuoter)); s_offRamp = new EVM2EVMOffRampHelper(staticConfig, _getInboundRateLimiterConfig()); @@ -112,7 +112,7 @@ contract EVM2EVMOffRamp_constructor is EVM2EVMOffRampSetup { contract EVM2EVMOffRamp_setDynamicConfig is EVM2EVMOffRampSetup { function test_SetDynamicConfig_Success() public { EVM2EVMOffRamp.StaticConfig memory staticConfig = s_offRamp.getStaticConfig(); - EVM2EVMOffRamp.DynamicConfig memory dynamicConfig = generateDynamicOffRampConfig(USER_3, address(s_priceRegistry)); + EVM2EVMOffRamp.DynamicConfig memory dynamicConfig = generateDynamicOffRampConfig(USER_3, address(s_feeQuoter)); bytes memory onchainConfig = abi.encode(dynamicConfig); vm.expectEmit(); @@ -142,7 +142,7 @@ contract EVM2EVMOffRamp_setDynamicConfig is EVM2EVMOffRampSetup { function test_NonOwner_Revert() public { vm.startPrank(STRANGER); - EVM2EVMOffRamp.DynamicConfig memory dynamicConfig = generateDynamicOffRampConfig(USER_3, address(s_priceRegistry)); + EVM2EVMOffRamp.DynamicConfig memory dynamicConfig = generateDynamicOffRampConfig(USER_3, address(s_feeQuoter)); vm.expectRevert("Only callable by owner"); @@ -1856,7 +1856,7 @@ contract EVM2EVMOffRamp__releaseOrMintTokens is EVM2EVMOffRampSetup { // Set a high price to trip the ARL uint224 tokenPrice = 3 ** 128; Internal.PriceUpdates memory priceUpdates = _getSingleTokenPriceUpdateStruct(s_destFeeToken, tokenPrice); - s_priceRegistry.updatePrices(priceUpdates); + s_feeQuoter.updatePrices(priceUpdates); Client.EVMTokenAmount[] memory srcTokenAmounts = _getCastedSourceEVMTokenAmountsWithZeroAmounts(); uint256 amount1 = 100; @@ -2032,7 +2032,7 @@ contract EVM2EVMOffRamp__releaseOrMintTokens is EVM2EVMOffRampSetup { function test_PriceNotFoundForToken_Reverts() public { // Set token price to 0 - s_priceRegistry.updatePrices(_getSingleTokenPriceUpdateStruct(s_destFeeToken, 0)); + s_feeQuoter.updatePrices(_getSingleTokenPriceUpdateStruct(s_destFeeToken, 0)); Client.EVMTokenAmount[] memory srcTokenAmounts = _getCastedSourceEVMTokenAmountsWithZeroAmounts(); uint256 amount1 = 100; diff --git a/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMOffRampSetup.t.sol b/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMOffRampSetup.t.sol index a0fa6a4a8e..a5cb4f3d2b 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMOffRampSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMOffRampSetup.t.sol @@ -10,14 +10,15 @@ import {Internal} from "../../libraries/Internal.sol"; import {EVM2EVMOffRamp} from "../../offRamp/EVM2EVMOffRamp.sol"; import {TokenPool} from "../../pools/TokenPool.sol"; import {TokenSetup} from "../TokenSetup.t.sol"; + +import {FeeQuoterSetup} from "../feeQuoter/FeeQuoterSetup.t.sol"; import {EVM2EVMOffRampHelper} from "../helpers/EVM2EVMOffRampHelper.sol"; import {MaybeRevertingBurnMintTokenPool} from "../helpers/MaybeRevertingBurnMintTokenPool.sol"; import {MaybeRevertMessageReceiver} from "../helpers/receivers/MaybeRevertMessageReceiver.sol"; import {MockCommitStore} from "../mocks/MockCommitStore.sol"; import {OCR2BaseSetup} from "../ocr/OCR2Base.t.sol"; -import {PriceRegistrySetup} from "../priceRegistry/PriceRegistrySetup.t.sol"; -contract EVM2EVMOffRampSetup is TokenSetup, PriceRegistrySetup, OCR2BaseSetup { +contract EVM2EVMOffRampSetup is TokenSetup, FeeQuoterSetup, OCR2BaseSetup { MockCommitStore internal s_mockCommitStore; IAny2EVMMessageReceiver internal s_receiver; IAny2EVMMessageReceiver internal s_secondary_receiver; @@ -28,9 +29,9 @@ contract EVM2EVMOffRampSetup is TokenSetup, PriceRegistrySetup, OCR2BaseSetup { EVM2EVMOffRampHelper internal s_offRamp; address internal s_sourceTokenPool = makeAddr("sourceTokenPool"); - function setUp() public virtual override(TokenSetup, PriceRegistrySetup, OCR2BaseSetup) { + function setUp() public virtual override(TokenSetup, FeeQuoterSetup, OCR2BaseSetup) { TokenSetup.setUp(); - PriceRegistrySetup.setUp(); + FeeQuoterSetup.setUp(); OCR2BaseSetup.setUp(); s_mockCommitStore = new MockCommitStore(); @@ -60,7 +61,7 @@ contract EVM2EVMOffRampSetup is TokenSetup, PriceRegistrySetup, OCR2BaseSetup { s_valid_signers, s_valid_transmitters, s_f, - abi.encode(generateDynamicOffRampConfig(address(router), address(s_priceRegistry))), + abi.encode(generateDynamicOffRampConfig(address(router), address(s_feeQuoter))), s_offchainConfigVersion, abi.encode("") ); diff --git a/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol index 04c7b0b63b..b3fb5de5a2 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol @@ -1,15 +1,15 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.24; +import {IFeeQuoter} from "../../interfaces/IFeeQuoter.sol"; import {IMessageInterceptor} from "../../interfaces/IMessageInterceptor.sol"; -import {IPriceRegistry} from "../../interfaces/IPriceRegistry.sol"; import {IRMN} from "../../interfaces/IRMN.sol"; import {IRouter} from "../../interfaces/IRouter.sol"; import {ITokenAdminRegistry} from "../../interfaces/ITokenAdminRegistry.sol"; import {CallWithExactGas} from "../../../shared/call/CallWithExactGas.sol"; +import {FeeQuoter} from "../../FeeQuoter.sol"; import {NonceManager} from "../../NonceManager.sol"; -import {PriceRegistry} from "../../PriceRegistry.sol"; import {Client} from "../../libraries/Client.sol"; import {Internal} from "../../libraries/Internal.sol"; import {MerkleMultiProof} from "../../libraries/MerkleMultiProof.sol"; @@ -38,7 +38,7 @@ contract OffRamp_constructor is OffRampSetup { tokenAdminRegistry: address(s_tokenAdminRegistry), nonceManager: address(s_inboundNonceManager) }); - OffRamp.DynamicConfig memory dynamicConfig = _generateDynamicOffRampConfig(address(s_priceRegistry)); + OffRamp.DynamicConfig memory dynamicConfig = _generateDynamicOffRampConfig(address(s_feeQuoter)); OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](2); sourceChainConfigs[0] = OffRamp.SourceChainConfigArgs({ @@ -159,7 +159,7 @@ contract OffRamp_constructor is OffRampSetup { tokenAdminRegistry: address(s_tokenAdminRegistry), nonceManager: address(s_inboundNonceManager) }), - _generateDynamicOffRampConfig(address(s_priceRegistry)), + _generateDynamicOffRampConfig(address(s_feeQuoter)), sourceChainConfigs ); } @@ -185,7 +185,7 @@ contract OffRamp_constructor is OffRampSetup { tokenAdminRegistry: address(s_tokenAdminRegistry), nonceManager: address(s_inboundNonceManager) }), - _generateDynamicOffRampConfig(address(s_priceRegistry)), + _generateDynamicOffRampConfig(address(s_feeQuoter)), sourceChainConfigs ); } @@ -205,7 +205,7 @@ contract OffRamp_constructor is OffRampSetup { tokenAdminRegistry: address(s_tokenAdminRegistry), nonceManager: address(s_inboundNonceManager) }), - _generateDynamicOffRampConfig(address(s_priceRegistry)), + _generateDynamicOffRampConfig(address(s_feeQuoter)), sourceChainConfigs ); } @@ -225,7 +225,7 @@ contract OffRamp_constructor is OffRampSetup { tokenAdminRegistry: address(s_tokenAdminRegistry), nonceManager: address(s_inboundNonceManager) }), - _generateDynamicOffRampConfig(address(s_priceRegistry)), + _generateDynamicOffRampConfig(address(s_feeQuoter)), sourceChainConfigs ); } @@ -245,7 +245,7 @@ contract OffRamp_constructor is OffRampSetup { tokenAdminRegistry: ZERO_ADDRESS, nonceManager: address(s_inboundNonceManager) }), - _generateDynamicOffRampConfig(address(s_priceRegistry)), + _generateDynamicOffRampConfig(address(s_feeQuoter)), sourceChainConfigs ); } @@ -265,7 +265,7 @@ contract OffRamp_constructor is OffRampSetup { tokenAdminRegistry: address(s_tokenAdminRegistry), nonceManager: ZERO_ADDRESS }), - _generateDynamicOffRampConfig(address(s_priceRegistry)), + _generateDynamicOffRampConfig(address(s_feeQuoter)), sourceChainConfigs ); } @@ -273,7 +273,7 @@ contract OffRamp_constructor is OffRampSetup { contract OffRamp_setDynamicConfig is OffRampSetup { function test_SetDynamicConfig_Success() public { - OffRamp.DynamicConfig memory dynamicConfig = _generateDynamicOffRampConfig(address(s_priceRegistry)); + OffRamp.DynamicConfig memory dynamicConfig = _generateDynamicOffRampConfig(address(s_feeQuoter)); vm.expectEmit(); emit OffRamp.DynamicConfigSet(dynamicConfig); @@ -285,7 +285,7 @@ contract OffRamp_setDynamicConfig is OffRampSetup { } function test_SetDynamicConfigWithValidator_Success() public { - OffRamp.DynamicConfig memory dynamicConfig = _generateDynamicOffRampConfig(address(s_priceRegistry)); + OffRamp.DynamicConfig memory dynamicConfig = _generateDynamicOffRampConfig(address(s_feeQuoter)); dynamicConfig.messageValidator = address(s_inboundMessageValidator); vm.expectEmit(); @@ -301,14 +301,14 @@ contract OffRamp_setDynamicConfig is OffRampSetup { function test_NonOwner_Revert() public { vm.startPrank(STRANGER); - OffRamp.DynamicConfig memory dynamicConfig = _generateDynamicOffRampConfig(address(s_priceRegistry)); + OffRamp.DynamicConfig memory dynamicConfig = _generateDynamicOffRampConfig(address(s_feeQuoter)); vm.expectRevert("Only callable by owner"); s_offRamp.setDynamicConfig(dynamicConfig); } - function test_PriceRegistryZeroAddress_Revert() public { + function test_FeeQuoterZeroAddress_Revert() public { OffRamp.DynamicConfig memory dynamicConfig = _generateDynamicOffRampConfig(ZERO_ADDRESS); vm.expectRevert(OffRamp.ZeroAddressNotAllowed.selector); @@ -2953,8 +2953,7 @@ contract OffRamp_commit is OffRampSetup { function test_StaleReportWithRoot_Success() public { uint64 maxSeq = 12; - uint224 tokenStartPrice = - IPriceRegistry(s_offRamp.getDynamicConfig().priceRegistry).getTokenPrice(s_sourceFeeToken).value; + uint224 tokenStartPrice = IFeeQuoter(s_offRamp.getDynamicConfig().feeQuoter).getTokenPrice(s_sourceFeeToken).value; OffRamp.MerkleRoot[] memory roots = new OffRamp.MerkleRoot[](1); roots[0] = OffRamp.MerkleRoot({ @@ -2989,9 +2988,7 @@ contract OffRamp_commit is OffRampSetup { assertEq(maxSeq * 2 + 1, s_offRamp.getSourceChainConfig(SOURCE_CHAIN_SELECTOR).minSeqNr); assertEq(0, s_offRamp.getLatestPriceSequenceNumber()); - assertEq( - tokenStartPrice, IPriceRegistry(s_offRamp.getDynamicConfig().priceRegistry).getTokenPrice(s_sourceFeeToken).value - ); + assertEq(tokenStartPrice, IFeeQuoter(s_offRamp.getDynamicConfig().feeQuoter).getTokenPrice(s_sourceFeeToken).value); } function test_OnlyTokenPriceUpdates_Success() public { @@ -3000,7 +2997,7 @@ contract OffRamp_commit is OffRampSetup { OffRamp.CommitReport({priceUpdates: _getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), merkleRoots: roots}); vm.expectEmit(); - emit PriceRegistry.UsdPerTokenUpdated(s_sourceFeeToken, 4e18, block.timestamp); + emit FeeQuoter.UsdPerTokenUpdated(s_sourceFeeToken, 4e18, block.timestamp); vm.expectEmit(); emit MultiOCR3Base.Transmitted(uint8(Internal.OCRPluginType.Commit), s_configDigestCommit, s_latestSequenceNumber); @@ -3016,7 +3013,7 @@ contract OffRamp_commit is OffRampSetup { OffRamp.CommitReport({priceUpdates: _getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), merkleRoots: roots}); vm.expectEmit(); - emit PriceRegistry.UsdPerTokenUpdated(s_sourceFeeToken, 4e18, block.timestamp); + emit FeeQuoter.UsdPerTokenUpdated(s_sourceFeeToken, 4e18, block.timestamp); vm.expectEmit(); emit MultiOCR3Base.Transmitted(uint8(Internal.OCRPluginType.Commit), s_configDigestCommit, s_latestSequenceNumber); @@ -3031,7 +3028,7 @@ contract OffRamp_commit is OffRampSetup { OffRamp.CommitReport({priceUpdates: _getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), merkleRoots: roots}); vm.expectEmit(); - emit PriceRegistry.UsdPerTokenUpdated(s_sourceFeeToken, 4e18, block.timestamp); + emit FeeQuoter.UsdPerTokenUpdated(s_sourceFeeToken, 4e18, block.timestamp); _commit(commitReport, s_latestSequenceNumber); assertEq(s_latestSequenceNumber, s_offRamp.getLatestPriceSequenceNumber()); @@ -3066,7 +3063,7 @@ contract OffRamp_commit is OffRampSetup { // The same sequence number can be reported again vm.expectEmit(); - emit PriceRegistry.UsdPerTokenUpdated(s_sourceFeeToken, 4e18, block.timestamp); + emit FeeQuoter.UsdPerTokenUpdated(s_sourceFeeToken, 4e18, block.timestamp); _commit(commitReport, s_latestSequenceNumber); } @@ -3082,7 +3079,7 @@ contract OffRamp_commit is OffRampSetup { }); vm.expectEmit(); - emit PriceRegistry.UsdPerTokenUpdated(s_sourceFeeToken, tokenPrice1, block.timestamp); + emit FeeQuoter.UsdPerTokenUpdated(s_sourceFeeToken, tokenPrice1, block.timestamp); vm.expectEmit(); emit MultiOCR3Base.Transmitted(uint8(Internal.OCRPluginType.Commit), s_configDigestCommit, s_latestSequenceNumber); @@ -3108,9 +3105,7 @@ contract OffRamp_commit is OffRampSetup { _commit(commitReport, s_latestSequenceNumber); assertEq(maxSeq + 1, s_offRamp.getSourceChainConfig(SOURCE_CHAIN_SELECTOR).minSeqNr); - assertEq( - tokenPrice1, IPriceRegistry(s_offRamp.getDynamicConfig().priceRegistry).getTokenPrice(s_sourceFeeToken).value - ); + assertEq(tokenPrice1, IFeeQuoter(s_offRamp.getDynamicConfig().feeQuoter).getTokenPrice(s_sourceFeeToken).value); assertEq(s_latestSequenceNumber, s_offRamp.getLatestPriceSequenceNumber()); } @@ -3258,7 +3253,7 @@ contract OffRamp_commit is OffRampSetup { OffRamp.CommitReport({priceUpdates: _getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), merkleRoots: roots}); vm.expectEmit(); - emit PriceRegistry.UsdPerTokenUpdated(s_sourceFeeToken, 4e18, block.timestamp); + emit FeeQuoter.UsdPerTokenUpdated(s_sourceFeeToken, 4e18, block.timestamp); _commit(commitReport, s_latestSequenceNumber); vm.expectRevert(OffRamp.StaleCommitReport.selector); diff --git a/contracts/src/v0.8/ccip/test/offRamp/OffRampSetup.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRampSetup.t.sol index fb61fbfc7d..ff051cdd21 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/OffRampSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRampSetup.t.sol @@ -15,16 +15,17 @@ import {MultiOCR3Base} from "../../ocr/MultiOCR3Base.sol"; import {EVM2EVMOffRamp} from "../../offRamp/EVM2EVMOffRamp.sol"; import {OffRamp} from "../../offRamp/OffRamp.sol"; import {TokenPool} from "../../pools/TokenPool.sol"; + +import {FeeQuoterSetup} from "../feeQuoter/FeeQuoterSetup.t.sol"; import {EVM2EVMOffRampHelper} from "../helpers/EVM2EVMOffRampHelper.sol"; import {MaybeRevertingBurnMintTokenPool} from "../helpers/MaybeRevertingBurnMintTokenPool.sol"; import {MessageInterceptorHelper} from "../helpers/MessageInterceptorHelper.sol"; import {OffRampHelper} from "../helpers/OffRampHelper.sol"; import {MaybeRevertMessageReceiver} from "../helpers/receivers/MaybeRevertMessageReceiver.sol"; import {MultiOCR3BaseSetup} from "../ocr/MultiOCR3BaseSetup.t.sol"; -import {PriceRegistrySetup} from "../priceRegistry/PriceRegistrySetup.t.sol"; import {Vm} from "forge-std/Test.sol"; -contract OffRampSetup is PriceRegistrySetup, MultiOCR3BaseSetup { +contract OffRampSetup is FeeQuoterSetup, MultiOCR3BaseSetup { uint64 internal constant SOURCE_CHAIN_SELECTOR_1 = SOURCE_CHAIN_SELECTOR; uint64 internal constant SOURCE_CHAIN_SELECTOR_2 = 6433500567565415381; uint64 internal constant SOURCE_CHAIN_SELECTOR_3 = 4051577828743386545; @@ -56,8 +57,8 @@ contract OffRampSetup is PriceRegistrySetup, MultiOCR3BaseSetup { uint64 internal s_latestSequenceNumber; - function setUp() public virtual override(PriceRegistrySetup, MultiOCR3BaseSetup) { - PriceRegistrySetup.setUp(); + function setUp() public virtual override(FeeQuoterSetup, MultiOCR3BaseSetup) { + FeeQuoterSetup.setUp(); MultiOCR3BaseSetup.setUp(); s_inboundMessageValidator = new MessageInterceptorHelper(); @@ -81,7 +82,7 @@ contract OffRampSetup is PriceRegistrySetup, MultiOCR3BaseSetup { tokenAdminRegistry: address(s_tokenAdminRegistry), nonceManager: address(nonceManager) }), - _generateDynamicOffRampConfig(address(s_priceRegistry)), + _generateDynamicOffRampConfig(address(s_feeQuoter)), sourceChainConfigs ); @@ -106,7 +107,7 @@ contract OffRampSetup is PriceRegistrySetup, MultiOCR3BaseSetup { transmitters: s_validTransmitters }); - s_offRamp.setDynamicConfig(_generateDynamicOffRampConfig(address(s_priceRegistry))); + s_offRamp.setDynamicConfig(_generateDynamicOffRampConfig(address(s_feeQuoter))); s_offRamp.setOCR3Configs(ocrConfigs); address[] memory authorizedCallers = new address[](1); @@ -117,7 +118,7 @@ contract OffRampSetup is PriceRegistrySetup, MultiOCR3BaseSetup { address[] memory priceUpdaters = new address[](1); priceUpdaters[0] = address(s_offRamp); - s_priceRegistry.applyAuthorizedCallerUpdates( + s_feeQuoter.applyAuthorizedCallerUpdates( AuthorizedCallers.AuthorizedCallerArgs({addedCallers: priceUpdaters, removedCallers: new address[](0)}) ); } @@ -146,7 +147,7 @@ contract OffRampSetup is PriceRegistrySetup, MultiOCR3BaseSetup { s_validSigners, s_validTransmitters, s_F, - abi.encode(_generateDynamicOffRampConfig(address(router), address(s_priceRegistry))), + abi.encode(_generateDynamicOffRampConfig(address(router), address(s_feeQuoter))), s_offchainConfigVersion, abi.encode("") ); @@ -223,10 +224,10 @@ contract OffRampSetup is PriceRegistrySetup, MultiOCR3BaseSetup { uint32 internal constant MAX_TOKEN_POOL_RELEASE_OR_MINT_GAS = 200_000; uint32 internal constant MAX_TOKEN_POOL_TRANSFER_GAS = 50_000; - function _generateDynamicOffRampConfig(address priceRegistry) internal pure returns (OffRamp.DynamicConfig memory) { + function _generateDynamicOffRampConfig(address feeQuoter) internal pure returns (OffRamp.DynamicConfig memory) { return OffRamp.DynamicConfig({ permissionLessExecutionThresholdSeconds: PERMISSION_LESS_EXECUTION_THRESHOLD_SECONDS, - priceRegistry: priceRegistry, + feeQuoter: feeQuoter, messageValidator: address(0), maxPoolReleaseOrMintGas: MAX_TOKEN_POOL_RELEASE_OR_MINT_GAS, maxTokenTransferGas: MAX_TOKEN_POOL_TRANSFER_GAS @@ -391,7 +392,7 @@ contract OffRampSetup is PriceRegistrySetup, MultiOCR3BaseSetup { assertEq(a.maxPoolReleaseOrMintGas, b.maxPoolReleaseOrMintGas); assertEq(a.maxTokenTransferGas, b.maxTokenTransferGas); assertEq(a.messageValidator, b.messageValidator); - assertEq(a.priceRegistry, b.priceRegistry); + assertEq(a.feeQuoter, b.feeQuoter); } function _assertSourceChainConfigEquality( @@ -436,7 +437,7 @@ contract OffRampSetup is PriceRegistrySetup, MultiOCR3BaseSetup { tokenAdminRegistry: address(s_tokenAdminRegistry), nonceManager: address(s_inboundNonceManager) }), - _generateDynamicOffRampConfig(address(s_priceRegistry)), + _generateDynamicOffRampConfig(address(s_feeQuoter)), new OffRamp.SourceChainConfigArgs[](0) ); @@ -449,7 +450,7 @@ contract OffRampSetup is PriceRegistrySetup, MultiOCR3BaseSetup { address[] memory priceUpdaters = new address[](1); priceUpdaters[0] = address(s_offRamp); - s_priceRegistry.applyAuthorizedCallerUpdates( + s_feeQuoter.applyAuthorizedCallerUpdates( AuthorizedCallers.AuthorizedCallerArgs({addedCallers: priceUpdaters, removedCallers: new address[](0)}) ); } diff --git a/contracts/src/v0.8/ccip/test/onRamp/EVM2EVMOnRamp.t.sol b/contracts/src/v0.8/ccip/test/onRamp/EVM2EVMOnRamp.t.sol index 54054716e6..7b400c0df6 100644 --- a/contracts/src/v0.8/ccip/test/onRamp/EVM2EVMOnRamp.t.sol +++ b/contracts/src/v0.8/ccip/test/onRamp/EVM2EVMOnRamp.t.sol @@ -27,7 +27,7 @@ contract EVM2EVMOnRamp_constructor is EVM2EVMOnRampSetup { tokenAdminRegistry: address(s_tokenAdminRegistry) }); EVM2EVMOnRamp.DynamicConfig memory dynamicConfig = - generateDynamicOnRampConfig(address(s_sourceRouter), address(s_priceRegistry)); + generateDynamicOnRampConfig(address(s_sourceRouter), address(s_feeQuoter)); vm.expectEmit(); emit EVM2EVMOnRamp.ConfigSet(staticConfig, dynamicConfig); @@ -247,7 +247,7 @@ contract EVM2EVMOnRamp_forwardFromRouter is EVM2EVMOnRampSetup { address[] memory feeTokens = new address[](1); feeTokens[0] = s_sourceTokens[1]; - s_priceRegistry.applyFeeTokensUpdates(feeTokens, new address[](0)); + s_feeQuoter.applyFeeTokensUpdates(feeTokens, new address[](0)); // Since we'll mostly be testing for valid calls from the router we'll // mock all calls to be originating from the router and re-mock in @@ -437,8 +437,8 @@ contract EVM2EVMOnRamp_forwardFromRouter is EVM2EVMOnRampSetup { assertEq(IERC20(s_sourceTokens[1]).balanceOf(address(s_onRamp)), feeAmount); // Calculate conversion done by prices contract - uint256 feeTokenPrice = s_priceRegistry.getTokenPrice(s_sourceTokens[1]).value; - uint256 linkTokenPrice = s_priceRegistry.getTokenPrice(s_sourceFeeToken).value; + uint256 feeTokenPrice = s_feeQuoter.getTokenPrice(s_sourceTokens[1]).value; + uint256 linkTokenPrice = s_feeQuoter.getTokenPrice(s_sourceFeeToken).value; uint256 conversionRate = (feeTokenPrice * 1e18) / linkTokenPrice; uint256 expectedJuels = (feeAmount * conversionRate) / 1e18; @@ -487,7 +487,7 @@ contract EVM2EVMOnRamp_forwardFromRouter is EVM2EVMOnRampSetup { // Set a high price to trip the ARL uint224 tokenPrice = 3 ** 128; Internal.PriceUpdates memory priceUpdates = _getSingleTokenPriceUpdateStruct(s_sourceTokens[0], tokenPrice); - s_priceRegistry.updatePrices(priceUpdates); + s_feeQuoter.updatePrices(priceUpdates); vm.startPrank(address(s_sourceRouter)); vm.expectRevert( @@ -662,7 +662,7 @@ contract EVM2EVMOnRamp_forwardFromRouter is EVM2EVMOnRampSetup { vm.startPrank(OWNER); Internal.PriceUpdates memory priceUpdates = _getSingleTokenPriceUpdateStruct(wrongToken, 1); - s_priceRegistry.updatePrices(priceUpdates); + s_feeQuoter.updatePrices(priceUpdates); // Change back to the router vm.startPrank(address(s_sourceRouter)); @@ -694,7 +694,7 @@ contract EVM2EVMOnRamp_forwardFromRouter is EVM2EVMOnRampSetup { // Set token price to 0 vm.stopPrank(); vm.startPrank(OWNER); - s_priceRegistry.updatePrices(_getSingleTokenPriceUpdateStruct(CUSTOM_TOKEN, 0)); + s_feeQuoter.updatePrices(_getSingleTokenPriceUpdateStruct(CUSTOM_TOKEN, 0)); vm.startPrank(address(s_sourceRouter)); @@ -905,7 +905,7 @@ contract EVM2EVMOnRamp_forwardFromRouter_upgrade is EVM2EVMOnRampSetup { rmnProxy: address(s_mockRMN), tokenAdminRegistry: address(s_tokenAdminRegistry) }), - generateDynamicOnRampConfig(address(s_sourceRouter), address(s_priceRegistry)), + generateDynamicOnRampConfig(address(s_sourceRouter), address(s_feeQuoter)), _getOutboundRateLimiterConfig(), s_feeTokenConfigArgs, s_tokenTransferFeeConfigArgs, diff --git a/contracts/src/v0.8/ccip/test/onRamp/EVM2EVMOnRampSetup.t.sol b/contracts/src/v0.8/ccip/test/onRamp/EVM2EVMOnRampSetup.t.sol index f827bf983c..84350448a1 100644 --- a/contracts/src/v0.8/ccip/test/onRamp/EVM2EVMOnRampSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/onRamp/EVM2EVMOnRampSetup.t.sol @@ -7,12 +7,13 @@ import {Internal} from "../../libraries/Internal.sol"; import {Pool} from "../../libraries/Pool.sol"; import {EVM2EVMOnRamp} from "../../onRamp/EVM2EVMOnRamp.sol"; import {TokenSetup} from "../TokenSetup.t.sol"; + +import {FeeQuoterSetup} from "../feeQuoter/FeeQuoterSetup.t.sol"; import {EVM2EVMOnRampHelper} from "../helpers/EVM2EVMOnRampHelper.sol"; -import {PriceRegistrySetup} from "../priceRegistry/PriceRegistrySetup.t.sol"; import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; -contract EVM2EVMOnRampSetup is TokenSetup, PriceRegistrySetup { +contract EVM2EVMOnRampSetup is TokenSetup, FeeQuoterSetup { uint256 internal immutable i_tokenAmount0 = 9; uint256 internal immutable i_tokenAmount1 = 7; @@ -27,11 +28,11 @@ contract EVM2EVMOnRampSetup is TokenSetup, PriceRegistrySetup { EVM2EVMOnRamp.FeeTokenConfigArgs[] internal s_feeTokenConfigArgs; EVM2EVMOnRamp.TokenTransferFeeConfigArgs[] internal s_tokenTransferFeeConfigArgs; - function setUp() public virtual override(TokenSetup, PriceRegistrySetup) { + function setUp() public virtual override(TokenSetup, FeeQuoterSetup) { TokenSetup.setUp(); - PriceRegistrySetup.setUp(); + FeeQuoterSetup.setUp(); - s_priceRegistry.updatePrices(_getSingleTokenPriceUpdateStruct(CUSTOM_TOKEN, CUSTOM_TOKEN_PRICE)); + s_feeQuoter.updatePrices(_getSingleTokenPriceUpdateStruct(CUSTOM_TOKEN, CUSTOM_TOKEN_PRICE)); address WETH = s_sourceRouter.getWrappedNative(); @@ -88,7 +89,7 @@ contract EVM2EVMOnRampSetup is TokenSetup, PriceRegistrySetup { rmnProxy: address(s_mockRMN), tokenAdminRegistry: address(s_tokenAdminRegistry) }), - generateDynamicOnRampConfig(address(s_sourceRouter), address(s_priceRegistry)), + generateDynamicOnRampConfig(address(s_sourceRouter), address(s_feeQuoter)), _getOutboundRateLimiterConfig(), s_feeTokenConfigArgs, s_tokenTransferFeeConfigArgs, diff --git a/contracts/src/v0.8/ccip/test/onRamp/OnRamp.t.sol b/contracts/src/v0.8/ccip/test/onRamp/OnRamp.t.sol index 10c0a9f0db..43d57b4624 100644 --- a/contracts/src/v0.8/ccip/test/onRamp/OnRamp.t.sol +++ b/contracts/src/v0.8/ccip/test/onRamp/OnRamp.t.sol @@ -5,7 +5,7 @@ import {IMessageInterceptor} from "../../interfaces/IMessageInterceptor.sol"; import {IRouter} from "../../interfaces/IRouter.sol"; import {BurnMintERC677} from "../../../shared/token/ERC677/BurnMintERC677.sol"; -import {PriceRegistry} from "../../PriceRegistry.sol"; +import {FeeQuoter} from "../../FeeQuoter.sol"; import {Client} from "../../libraries/Client.sol"; import {Internal} from "../../libraries/Internal.sol"; import {Pool} from "../../libraries/Pool.sol"; @@ -25,7 +25,7 @@ contract OnRamp_constructor is OnRampSetup { nonceManager: address(s_outboundNonceManager), tokenAdminRegistry: address(s_tokenAdminRegistry) }); - OnRamp.DynamicConfig memory dynamicConfig = _generateDynamicOnRampConfig(address(s_priceRegistry)); + OnRamp.DynamicConfig memory dynamicConfig = _generateDynamicOnRampConfig(address(s_feeQuoter)); vm.expectEmit(); emit OnRamp.ConfigSet(staticConfig, dynamicConfig); @@ -56,7 +56,7 @@ contract OnRamp_constructor is OnRampSetup { nonceManager: address(s_outboundNonceManager), tokenAdminRegistry: address(s_tokenAdminRegistry) }), - _generateDynamicOnRampConfig(address(s_priceRegistry)), + _generateDynamicOnRampConfig(address(s_feeQuoter)), _generateDestChainConfigArgs(IRouter(address(0))) ); } @@ -70,7 +70,7 @@ contract OnRamp_constructor is OnRampSetup { nonceManager: address(s_outboundNonceManager), tokenAdminRegistry: address(s_tokenAdminRegistry) }), - _generateDynamicOnRampConfig(address(s_priceRegistry)), + _generateDynamicOnRampConfig(address(s_feeQuoter)), _generateDestChainConfigArgs(IRouter(address(0))) ); } @@ -84,7 +84,7 @@ contract OnRamp_constructor is OnRampSetup { nonceManager: address(0), tokenAdminRegistry: address(s_tokenAdminRegistry) }), - _generateDynamicOnRampConfig(address(s_priceRegistry)), + _generateDynamicOnRampConfig(address(s_feeQuoter)), _generateDestChainConfigArgs(IRouter(address(0))) ); } @@ -98,7 +98,7 @@ contract OnRamp_constructor is OnRampSetup { nonceManager: address(s_outboundNonceManager), tokenAdminRegistry: address(0) }), - _generateDynamicOnRampConfig(address(s_priceRegistry)), + _generateDynamicOnRampConfig(address(s_feeQuoter)), _generateDestChainConfigArgs(IRouter(address(0))) ); } @@ -115,7 +115,7 @@ contract OnRamp_forwardFromRouter is OnRampSetup { address[] memory feeTokens = new address[](1); feeTokens[0] = s_sourceTokens[1]; - s_priceRegistry.applyFeeTokensUpdates(feeTokens, new address[](0)); + s_feeQuoter.applyFeeTokensUpdates(feeTokens, new address[](0)); // Since we'll mostly be testing for valid calls from the router we'll // mock all calls to be originating from the router and re-mock in @@ -286,8 +286,8 @@ contract OnRamp_forwardFromRouter is OnRampSetup { IERC20(s_sourceTokens[1]).transferFrom(OWNER, address(s_onRamp), feeAmount); // Calculate conversion done by prices contract - uint256 feeTokenPrice = s_priceRegistry.getTokenPrice(s_sourceTokens[1]).value; - uint256 linkTokenPrice = s_priceRegistry.getTokenPrice(s_sourceFeeToken).value; + uint256 feeTokenPrice = s_feeQuoter.getTokenPrice(s_sourceTokens[1]).value; + uint256 linkTokenPrice = s_feeQuoter.getTokenPrice(s_sourceFeeToken).value; uint256 conversionRate = (feeTokenPrice * 1e18) / linkTokenPrice; uint256 expectedJuels = (feeAmount * conversionRate) / 1e18; @@ -362,7 +362,7 @@ contract OnRamp_forwardFromRouter is OnRampSetup { Client.EVM2AnyMessage memory message = _generateEmptyMessage(); message.extraArgs = bytes("bad args"); - vm.expectRevert(PriceRegistry.InvalidExtraArgsTag.selector); + vm.expectRevert(FeeQuoter.InvalidExtraArgsTag.selector); s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); } @@ -421,7 +421,7 @@ contract OnRamp_forwardFromRouter is OnRampSetup { vm.startPrank(OWNER); Internal.PriceUpdates memory priceUpdates = _getSingleTokenPriceUpdateStruct(wrongToken, 1); - s_priceRegistry.updatePrices(priceUpdates); + s_feeQuoter.updatePrices(priceUpdates); // Change back to the router vm.startPrank(address(s_sourceRouter)); @@ -445,7 +445,7 @@ contract OnRamp_forwardFromRouter is OnRampSetup { Client.EVM2AnyMessage memory message = _generateEmptyMessage(); vm.expectRevert( - abi.encodeWithSelector(PriceRegistry.MessageFeeTooHigh.selector, MAX_MSG_FEES_JUELS + 1, MAX_MSG_FEES_JUELS) + abi.encodeWithSelector(FeeQuoter.MessageFeeTooHigh.selector, MAX_MSG_FEES_JUELS + 1, MAX_MSG_FEES_JUELS) ); s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, MAX_MSG_FEES_JUELS + 1, OWNER); @@ -495,17 +495,15 @@ contract OnRamp_forwardFromRouter is OnRampSetup { newPool.setSourceTokenData(new bytes(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES + 1)); vm.startPrank(address(s_sourceRouter)); - vm.expectRevert(abi.encodeWithSelector(PriceRegistry.SourceTokenDataTooLarge.selector, sourceETH)); + vm.expectRevert(abi.encodeWithSelector(FeeQuoter.SourceTokenDataTooLarge.selector, sourceETH)); s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); // Set token config to allow larger data vm.startPrank(OWNER); - PriceRegistry.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs = - _generateTokenTransferFeeConfigArgs(1, 1); + FeeQuoter.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs = _generateTokenTransferFeeConfigArgs(1, 1); tokenTransferFeeConfigArgs[0].destChainSelector = DEST_CHAIN_SELECTOR; tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].token = sourceETH; - tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig = PriceRegistry - .TokenTransferFeeConfig({ + tokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig = FeeQuoter.TokenTransferFeeConfig({ minFeeUSDCents: 1, maxFeeUSDCents: 0, deciBps: 0, @@ -513,8 +511,8 @@ contract OnRamp_forwardFromRouter is OnRampSetup { destBytesOverhead: uint32(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES) + 32, isEnabled: true }); - s_priceRegistry.applyTokenTransferFeeConfigUpdates( - tokenTransferFeeConfigArgs, new PriceRegistry.TokenTransferFeeConfigRemoveArgs[](0) + s_feeQuoter.applyTokenTransferFeeConfigUpdates( + tokenTransferFeeConfigArgs, new FeeQuoter.TokenTransferFeeConfigRemoveArgs[](0) ); vm.startPrank(address(s_sourceRouter)); @@ -525,7 +523,7 @@ contract OnRamp_forwardFromRouter is OnRampSetup { newPool.setSourceTokenData(new bytes(uint32(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES) + 32 + 1)); vm.startPrank(address(s_sourceRouter)); - vm.expectRevert(abi.encodeWithSelector(PriceRegistry.SourceTokenDataTooLarge.selector, sourceETH)); + vm.expectRevert(abi.encodeWithSelector(FeeQuoter.SourceTokenDataTooLarge.selector, sourceETH)); s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); } } @@ -549,7 +547,7 @@ contract OnRamp_getFee is OnRampSetup { message.feeToken = testTokens[i]; uint256 feeAmount = s_onRamp.getFee(DEST_CHAIN_SELECTOR, message); - uint256 expectedFeeAmount = s_priceRegistry.getValidatedFee(DEST_CHAIN_SELECTOR, message); + uint256 expectedFeeAmount = s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR, message); assertEq(expectedFeeAmount, feeAmount); } @@ -565,7 +563,7 @@ contract OnRamp_getFee is OnRampSetup { message.feeToken = testTokens[i]; uint256 feeAmount = s_onRamp.getFee(DEST_CHAIN_SELECTOR, message); - uint256 expectedFeeAmount = s_priceRegistry.getValidatedFee(DEST_CHAIN_SELECTOR, message); + uint256 expectedFeeAmount = s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR, message); assertEq(expectedFeeAmount, feeAmount); } @@ -584,16 +582,16 @@ contract OnRamp_getFee is OnRampSetup { vm.stopPrank(); vm.startPrank(OWNER); - PriceRegistry.DestChainConfigArgs[] memory destChainConfigArgs = _generatePriceRegistryDestChainConfigArgs(); + FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = _generateFeeQuoterDestChainConfigArgs(); destChainConfigArgs[0].destChainConfig.enforceOutOfOrder = true; - s_priceRegistry.applyDestChainConfigUpdates(destChainConfigArgs); + s_feeQuoter.applyDestChainConfigUpdates(destChainConfigArgs); vm.stopPrank(); Client.EVM2AnyMessage memory message = _generateEmptyMessage(); // Empty extraArgs to should revert since it enforceOutOfOrder is true. message.extraArgs = ""; - vm.expectRevert(PriceRegistry.ExtraArgOutOfOrderExecutionMustBeTrue.selector); + vm.expectRevert(FeeQuoter.ExtraArgOutOfOrderExecutionMustBeTrue.selector); s_onRamp.getFee(DEST_CHAIN_SELECTOR, message); } } @@ -602,7 +600,7 @@ contract OnRamp_setDynamicConfig is OnRampSetup { function test_SetDynamicConfig_Success() public { OnRamp.StaticConfig memory staticConfig = s_onRamp.getStaticConfig(); OnRamp.DynamicConfig memory newConfig = OnRamp.DynamicConfig({ - priceRegistry: address(23423), + feeQuoter: address(23423), messageValidator: makeAddr("messageValidator"), feeAggregator: FEE_AGGREGATOR }); @@ -613,14 +611,14 @@ contract OnRamp_setDynamicConfig is OnRampSetup { s_onRamp.setDynamicConfig(newConfig); OnRamp.DynamicConfig memory gotDynamicConfig = s_onRamp.getDynamicConfig(); - assertEq(newConfig.priceRegistry, gotDynamicConfig.priceRegistry); + assertEq(newConfig.feeQuoter, gotDynamicConfig.feeQuoter); } // Reverts - function test_SetConfigInvalidConfigPriceRegistryEqAddressZero_Revert() public { + function test_SetConfigInvalidConfigFeeQuoterEqAddressZero_Revert() public { OnRamp.DynamicConfig memory newConfig = OnRamp.DynamicConfig({ - priceRegistry: address(0), + feeQuoter: address(0), feeAggregator: FEE_AGGREGATOR, messageValidator: makeAddr("messageValidator") }); @@ -631,17 +629,17 @@ contract OnRamp_setDynamicConfig is OnRampSetup { function test_SetConfigInvalidConfig_Revert() public { OnRamp.DynamicConfig memory newConfig = - OnRamp.DynamicConfig({priceRegistry: address(23423), messageValidator: address(0), feeAggregator: FEE_AGGREGATOR}); + OnRamp.DynamicConfig({feeQuoter: address(23423), messageValidator: address(0), feeAggregator: FEE_AGGREGATOR}); // Invalid price reg reverts. - newConfig.priceRegistry = address(0); + newConfig.feeQuoter = address(0); vm.expectRevert(OnRamp.InvalidConfig.selector); s_onRamp.setDynamicConfig(newConfig); } function test_SetConfigInvalidConfigFeeAggregatorEqAddressZero_Revert() public { OnRamp.DynamicConfig memory newConfig = - OnRamp.DynamicConfig({priceRegistry: address(23423), messageValidator: address(0), feeAggregator: address(0)}); + OnRamp.DynamicConfig({feeQuoter: address(23423), messageValidator: address(0), feeAggregator: address(0)}); vm.expectRevert(OnRamp.InvalidConfig.selector); s_onRamp.setDynamicConfig(newConfig); } @@ -689,7 +687,7 @@ contract OnRamp_withdrawFeeTokens is OnRampSetup { IERC20(feeTokens[i]).transfer(address(s_onRamp), amounts[i]); } - s_priceRegistry.applyFeeTokensUpdates(feeTokens, new address[](0)); + s_feeQuoter.applyFeeTokensUpdates(feeTokens, new address[](0)); for (uint256 i = 0; i < feeTokens.length; ++i) { vm.expectEmit(); diff --git a/contracts/src/v0.8/ccip/test/onRamp/OnRampSetup.t.sol b/contracts/src/v0.8/ccip/test/onRamp/OnRampSetup.t.sol index a8d1919948..635a75c843 100644 --- a/contracts/src/v0.8/ccip/test/onRamp/OnRampSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/onRamp/OnRampSetup.t.sol @@ -9,13 +9,13 @@ import {Router} from "../../Router.sol"; import {Client} from "../../libraries/Client.sol"; import {Internal} from "../../libraries/Internal.sol"; import {OnRamp} from "../../onRamp/OnRamp.sol"; +import {FeeQuoterFeeSetup} from "../feeQuoter/FeeQuoterSetup.t.sol"; import {MessageInterceptorHelper} from "../helpers/MessageInterceptorHelper.sol"; import {OnRampHelper} from "../helpers/OnRampHelper.sol"; -import {PriceRegistryFeeSetup} from "../priceRegistry/PriceRegistry.t.sol"; import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; -contract OnRampSetup is PriceRegistryFeeSetup { +contract OnRampSetup is FeeQuoterFeeSetup { uint256 internal immutable i_tokenAmount0 = 9; uint256 internal immutable i_tokenAmount1 = 7; @@ -84,9 +84,8 @@ contract OnRampSetup is PriceRegistryFeeSetup { ); } - function _generateDynamicOnRampConfig(address priceRegistry) internal pure returns (OnRamp.DynamicConfig memory) { - return - OnRamp.DynamicConfig({priceRegistry: priceRegistry, messageValidator: address(0), feeAggregator: FEE_AGGREGATOR}); + function _generateDynamicOnRampConfig(address feeQuoter) internal pure returns (OnRamp.DynamicConfig memory) { + return OnRamp.DynamicConfig({feeQuoter: feeQuoter, messageValidator: address(0), feeAggregator: FEE_AGGREGATOR}); } // Slicing is only available for calldata. So we have to build a new bytes array. @@ -117,7 +116,7 @@ contract OnRampSetup is PriceRegistryFeeSetup { nonceManager: nonceManager, tokenAdminRegistry: tokenAdminRegistry }), - _generateDynamicOnRampConfig(address(s_priceRegistry)), + _generateDynamicOnRampConfig(address(s_feeQuoter)), _generateDestChainConfigArgs(router) ); @@ -162,6 +161,6 @@ contract OnRampSetup is PriceRegistryFeeSetup { } function _assertDynamicConfigsEqual(OnRamp.DynamicConfig memory a, OnRamp.DynamicConfig memory b) internal pure { - assertEq(a.priceRegistry, b.priceRegistry); + assertEq(a.feeQuoter, b.feeQuoter); } } diff --git a/contracts/src/v0.8/ccip/test/rateLimiter/AggregateRateLimiter.t.sol b/contracts/src/v0.8/ccip/test/rateLimiter/AggregateRateLimiter.t.sol index af970b0f92..318821c441 100644 --- a/contracts/src/v0.8/ccip/test/rateLimiter/AggregateRateLimiter.t.sol +++ b/contracts/src/v0.8/ccip/test/rateLimiter/AggregateRateLimiter.t.sol @@ -5,12 +5,13 @@ import {AggregateRateLimiter} from "../../AggregateRateLimiter.sol"; import {Client} from "../../libraries/Client.sol"; import {Internal} from "../../libraries/Internal.sol"; import {RateLimiter} from "../../libraries/RateLimiter.sol"; + +import {FeeQuoterSetup} from "../feeQuoter/FeeQuoterSetup.t.sol"; import {AggregateRateLimiterHelper} from "../helpers/AggregateRateLimiterHelper.sol"; -import {PriceRegistrySetup} from "../priceRegistry/PriceRegistrySetup.t.sol"; import {stdError} from "forge-std/Test.sol"; -contract AggregateTokenLimiterSetup is PriceRegistrySetup { +contract AggregateTokenLimiterSetup is FeeQuoterSetup { AggregateRateLimiterHelper internal s_rateLimiter; RateLimiter.Config internal s_config; @@ -18,10 +19,10 @@ contract AggregateTokenLimiterSetup is PriceRegistrySetup { uint224 internal constant TOKEN_PRICE = 4e18; function setUp() public virtual override { - PriceRegistrySetup.setUp(); + FeeQuoterSetup.setUp(); Internal.PriceUpdates memory priceUpdates = _getSingleTokenPriceUpdateStruct(TOKEN, TOKEN_PRICE); - s_priceRegistry.updatePrices(priceUpdates); + s_feeQuoter.updatePrices(priceUpdates); s_config = RateLimiter.Config({isEnabled: true, rate: 5, capacity: 100}); s_rateLimiter = new AggregateRateLimiterHelper(s_config); @@ -219,7 +220,7 @@ contract AggregateTokenLimiter_getTokenValue is AggregateTokenLimiterSetup { function test_GetTokenValue_Success() public view { uint256 numberOfTokens = 10; Client.EVMTokenAmount memory tokenAmount = Client.EVMTokenAmount({token: TOKEN, amount: 10}); - uint256 value = s_rateLimiter.getTokenValue(tokenAmount, s_priceRegistry); + uint256 value = s_rateLimiter.getTokenValue(tokenAmount, s_feeQuoter); assertEq(value, (numberOfTokens * TOKEN_PRICE) / 1e18); } @@ -229,6 +230,6 @@ contract AggregateTokenLimiter_getTokenValue is AggregateTokenLimiterSetup { Client.EVMTokenAmount memory tokenAmount = Client.EVMTokenAmount({token: tokenWithNoPrice, amount: 10}); vm.expectRevert(abi.encodeWithSelector(AggregateRateLimiter.PriceNotFoundForToken.selector, tokenWithNoPrice)); - s_rateLimiter.getTokenValue(tokenAmount, s_priceRegistry); + s_rateLimiter.getTokenValue(tokenAmount, s_feeQuoter); } } diff --git a/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol b/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol index 292c4533e4..9fcf08f722 100644 --- a/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol +++ b/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol @@ -7,12 +7,13 @@ import {Client} from "../../libraries/Client.sol"; import {Internal} from "../../libraries/Internal.sol"; import {RateLimiter} from "../../libraries/RateLimiter.sol"; import {BaseTest} from "../BaseTest.t.sol"; + +import {FeeQuoterSetup} from "../feeQuoter/FeeQuoterSetup.t.sol"; import {MultiAggregateRateLimiterHelper} from "../helpers/MultiAggregateRateLimiterHelper.sol"; -import {PriceRegistrySetup} from "../priceRegistry/PriceRegistrySetup.t.sol"; import {stdError} from "forge-std/Test.sol"; import {Vm} from "forge-std/Vm.sol"; -contract MultiAggregateRateLimiterSetup is BaseTest, PriceRegistrySetup { +contract MultiAggregateRateLimiterSetup is BaseTest, FeeQuoterSetup { MultiAggregateRateLimiterHelper internal s_rateLimiter; address internal immutable TOKEN = 0x21118E64E1fB0c487F25Dd6d3601FF6af8D32E4e; @@ -29,12 +30,12 @@ contract MultiAggregateRateLimiterSetup is BaseTest, PriceRegistrySetup { address[] internal s_authorizedCallers; - function setUp() public virtual override(BaseTest, PriceRegistrySetup) { + function setUp() public virtual override(BaseTest, FeeQuoterSetup) { BaseTest.setUp(); - PriceRegistrySetup.setUp(); + FeeQuoterSetup.setUp(); Internal.PriceUpdates memory priceUpdates = _getSingleTokenPriceUpdateStruct(TOKEN, TOKEN_PRICE); - s_priceRegistry.updatePrices(priceUpdates); + s_feeQuoter.updatePrices(priceUpdates); MultiAggregateRateLimiter.RateLimiterConfigArgs[] memory configUpdates = new MultiAggregateRateLimiter.RateLimiterConfigArgs[](4); @@ -63,7 +64,7 @@ contract MultiAggregateRateLimiterSetup is BaseTest, PriceRegistrySetup { s_authorizedCallers[0] = MOCK_OFFRAMP; s_authorizedCallers[1] = MOCK_ONRAMP; - s_rateLimiter = new MultiAggregateRateLimiterHelper(address(s_priceRegistry), s_authorizedCallers); + s_rateLimiter = new MultiAggregateRateLimiterHelper(address(s_feeQuoter), s_authorizedCallers); s_rateLimiter.applyRateLimiterConfigUpdates(configUpdates); } @@ -114,14 +115,14 @@ contract MultiAggregateRateLimiter_constructor is MultiAggregateRateLimiterSetup address[] memory authorizedCallers = new address[](0); vm.recordLogs(); - s_rateLimiter = new MultiAggregateRateLimiterHelper(address(s_priceRegistry), authorizedCallers); + s_rateLimiter = new MultiAggregateRateLimiterHelper(address(s_feeQuoter), authorizedCallers); - // PriceRegistrySet + // FeeQuoterSet Vm.Log[] memory logEntries = vm.getRecordedLogs(); assertEq(logEntries.length, 1); assertEq(OWNER, s_rateLimiter.owner()); - assertEq(address(s_priceRegistry), s_rateLimiter.getPriceRegistry()); + assertEq(address(s_feeQuoter), s_rateLimiter.getFeeQuoter()); } function test_Constructor_Success() public { @@ -130,25 +131,25 @@ contract MultiAggregateRateLimiter_constructor is MultiAggregateRateLimiterSetup authorizedCallers[1] = MOCK_ONRAMP; vm.expectEmit(); - emit MultiAggregateRateLimiter.PriceRegistrySet(address(s_priceRegistry)); + emit MultiAggregateRateLimiter.FeeQuoterSet(address(s_feeQuoter)); - s_rateLimiter = new MultiAggregateRateLimiterHelper(address(s_priceRegistry), authorizedCallers); + s_rateLimiter = new MultiAggregateRateLimiterHelper(address(s_feeQuoter), authorizedCallers); assertEq(OWNER, s_rateLimiter.owner()); - assertEq(address(s_priceRegistry), s_rateLimiter.getPriceRegistry()); + assertEq(address(s_feeQuoter), s_rateLimiter.getFeeQuoter()); assertEq(s_rateLimiter.typeAndVersion(), "MultiAggregateRateLimiter 1.6.0-dev"); } } -contract MultiAggregateRateLimiter_setPriceRegistry is MultiAggregateRateLimiterSetup { +contract MultiAggregateRateLimiter_setFeeQuoter is MultiAggregateRateLimiterSetup { function test_Owner_Success() public { address newAddress = address(42); vm.expectEmit(); - emit MultiAggregateRateLimiter.PriceRegistrySet(newAddress); + emit MultiAggregateRateLimiter.FeeQuoterSet(newAddress); - s_rateLimiter.setPriceRegistry(newAddress); - assertEq(newAddress, s_rateLimiter.getPriceRegistry()); + s_rateLimiter.setFeeQuoter(newAddress); + assertEq(newAddress, s_rateLimiter.getFeeQuoter()); } // Reverts @@ -157,12 +158,12 @@ contract MultiAggregateRateLimiter_setPriceRegistry is MultiAggregateRateLimiter vm.startPrank(STRANGER); vm.expectRevert(bytes("Only callable by owner")); - s_rateLimiter.setPriceRegistry(STRANGER); + s_rateLimiter.setFeeQuoter(STRANGER); } function test_ZeroAddress_Revert() public { vm.expectRevert(AuthorizedCallers.ZeroAddressNotAllowed.selector); - s_rateLimiter.setPriceRegistry(address(0)); + s_rateLimiter.setFeeQuoter(address(0)); } } @@ -684,7 +685,7 @@ contract MultiAggregateRateLimiter_onInboundMessage is MultiAggregateRateLimiter Internal.PriceUpdates memory priceUpdates = _getSingleTokenPriceUpdateStruct(s_destTokens[i], TOKEN_PRICE * (i + 1)); - s_priceRegistry.updatePrices(priceUpdates); + s_feeQuoter.updatePrices(priceUpdates); } s_rateLimiter.updateRateLimitTokens(new MultiAggregateRateLimiter.LocalRateLimitToken[](0), tokensToAdd); } @@ -920,7 +921,7 @@ contract MultiAggregateRateLimiter_onOutboundMessage is MultiAggregateRateLimite Internal.PriceUpdates memory priceUpdates = _getSingleTokenPriceUpdateStruct(s_sourceTokens[i], TOKEN_PRICE * (i + 1)); - s_priceRegistry.updatePrices(priceUpdates); + s_feeQuoter.updatePrices(priceUpdates); } s_rateLimiter.updateRateLimitTokens(new MultiAggregateRateLimiter.LocalRateLimitToken[](0), tokensToAdd); } diff --git a/contracts/src/v0.8/ccip/test/router/Router.t.sol b/contracts/src/v0.8/ccip/test/router/Router.t.sol index 5f3a3a66ab..95d3c2f293 100644 --- a/contracts/src/v0.8/ccip/test/router/Router.t.sol +++ b/contracts/src/v0.8/ccip/test/router/Router.t.sol @@ -210,7 +210,7 @@ contract Router_ccipSend is EVM2EVMOnRampSetup { address[] memory feeTokens = new address[](1); feeTokens[0] = s_sourceTokens[1]; - s_priceRegistry.applyFeeTokensUpdates(feeTokens, new address[](0)); + s_feeQuoter.applyFeeTokensUpdates(feeTokens, new address[](0)); Client.EVM2AnyMessage memory message = _generateEmptyMessage(); message.feeToken = s_sourceTokens[1]; @@ -262,7 +262,7 @@ contract Router_ccipSend is EVM2EVMOnRampSetup { // Set the new token as feeToken address[] memory feeTokens = new address[](1); feeTokens[0] = feeTokenWithZeroFeeAndGas; - s_priceRegistry.applyFeeTokensUpdates(feeTokens, new address[](0)); + s_feeQuoter.applyFeeTokensUpdates(feeTokens, new address[](0)); // Update the price of the newly set feeToken Internal.PriceUpdates memory priceUpdates = _getSingleTokenPriceUpdateStruct(feeTokenWithZeroFeeAndGas, 2_000 ether); @@ -270,7 +270,7 @@ contract Router_ccipSend is EVM2EVMOnRampSetup { priceUpdates.gasPriceUpdates[0] = Internal.GasPriceUpdate({destChainSelector: DEST_CHAIN_SELECTOR, usdPerUnitGas: 0}); - s_priceRegistry.updatePrices(priceUpdates); + s_feeQuoter.updatePrices(priceUpdates); // Set the feeToken args on the onRamp EVM2EVMOnRamp.FeeTokenConfigArgs[] memory feeTokenConfigArgs = new EVM2EVMOnRamp.FeeTokenConfigArgs[](1); diff --git a/core/capabilities/ccip/ccip_integration_tests/helpers.go b/core/capabilities/ccip/ccip_integration_tests/helpers.go index a98a8ce1cd..0cc06bc30d 100644 --- a/core/capabilities/ccip/ccip_integration_tests/helpers.go +++ b/core/capabilities/ccip/ccip_integration_tests/helpers.go @@ -14,6 +14,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccip_integration_tests/integrationhelpers" cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/fee_quoter" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" @@ -31,7 +32,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/ocr3_config_encoder" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/offramp" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/onramp" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/price_registry" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_proxy_contract" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/token_admin_registry" @@ -106,7 +106,7 @@ type onchainUniverse struct { rmn *mock_rmn_contract.MockRMNContract onramp *onramp.OnRamp offramp *offramp.OffRamp - priceRegistry *price_registry.PriceRegistry + priceRegistry *fee_quoter.FeeQuoter tokenAdminRegistry *token_admin_registry.TokenAdminRegistry nonceManager *nonce_manager.NonceManager receiver *maybe_revert_message_receiver.MaybeRevertMessageReceiver @@ -200,7 +200,7 @@ func createUniverses( TokenAdminRegistry: tokenAdminRegistry.Address(), }, onramp.OnRampDynamicConfig{ - PriceRegistry: priceRegistry.Address(), + FeeQuoter: priceRegistry.Address(), // `withdrawFeeTokens` onRamp function is not part of the message flow // so we can set this to any address FeeAggregator: testutils.NewAddress(), @@ -226,7 +226,7 @@ func createUniverses( NonceManager: nonceManager.Address(), }, offramp.OffRampDynamicConfig{ - PriceRegistry: priceRegistry.Address(), + FeeQuoter: priceRegistry.Address(), }, // Source chain configs will be set up later once we have all chains []offramp.OffRampSourceChainConfigArgs{}, @@ -660,7 +660,7 @@ func setupUniverseBasics(t *testing.T, uni onchainUniverse) { // Price updates for tokens // These are the prices of the fee tokens of local chain in USD // ============================================================================= - tokenPriceUpdates := []price_registry.InternalTokenPriceUpdate{ + tokenPriceUpdates := []fee_quoter.InternalTokenPriceUpdate{ { SourceToken: uni.linkToken.Address(), UsdPerToken: e18Mult(20), @@ -670,13 +670,13 @@ func setupUniverseBasics(t *testing.T, uni onchainUniverse) { UsdPerToken: e18Mult(4000), }, } - _, err = uni.priceRegistry.UpdatePrices(owner, price_registry.InternalPriceUpdates{ + _, err = uni.priceRegistry.UpdatePrices(owner, fee_quoter.InternalPriceUpdates{ TokenPriceUpdates: tokenPriceUpdates, }) require.NoErrorf(t, err, "failed to update prices in price registry on chain id %d", uni.chainID) uni.backend.Commit() - _, err = uni.priceRegistry.ApplyAuthorizedCallerUpdates(owner, price_registry.AuthorizedCallersAuthorizedCallerArgs{ + _, err = uni.priceRegistry.ApplyAuthorizedCallerUpdates(owner, fee_quoter.AuthorizedCallersAuthorizedCallerArgs{ AddedCallers: []common.Address{ uni.offramp.Address(), }, @@ -729,12 +729,12 @@ func wireRouter(t *testing.T, uni onchainUniverse, universes map[uint64]onchainU // Setting OnRampDestChainConfigs func wirePriceRegistry(t *testing.T, uni onchainUniverse, universes map[uint64]onchainUniverse) { owner := uni.owner - var priceRegistryDestChainConfigArgs []price_registry.PriceRegistryDestChainConfigArgs + var priceRegistryDestChainConfigArgs []fee_quoter.FeeQuoterDestChainConfigArgs for remoteChainID := range universes { if remoteChainID == uni.chainID { continue } - priceRegistryDestChainConfigArgs = append(priceRegistryDestChainConfigArgs, price_registry.PriceRegistryDestChainConfigArgs{ + priceRegistryDestChainConfigArgs = append(priceRegistryDestChainConfigArgs, fee_quoter.FeeQuoterDestChainConfigArgs{ DestChainSelector: getSelector(remoteChainID), DestChainConfig: defaultPriceRegistryDestChainConfig(t), }) @@ -801,25 +801,25 @@ func getSelector(chainID uint64) uint64 { // initRemoteChainsGasPrices sets the gas prices for all chains except the local chain in the local price registry func initRemoteChainsGasPrices(t *testing.T, uni onchainUniverse, universes map[uint64]onchainUniverse) { - var gasPriceUpdates []price_registry.InternalGasPriceUpdate + var gasPriceUpdates []fee_quoter.InternalGasPriceUpdate for remoteChainID := range universes { if remoteChainID == uni.chainID { continue } gasPriceUpdates = append(gasPriceUpdates, - price_registry.InternalGasPriceUpdate{ + fee_quoter.InternalGasPriceUpdate{ DestChainSelector: getSelector(remoteChainID), UsdPerUnitGas: big.NewInt(2e12), }, ) } - _, err := uni.priceRegistry.UpdatePrices(uni.owner, price_registry.InternalPriceUpdates{ + _, err := uni.priceRegistry.UpdatePrices(uni.owner, fee_quoter.InternalPriceUpdates{ GasPriceUpdates: gasPriceUpdates, }) require.NoError(t, err) } -func defaultPriceRegistryDestChainConfig(t *testing.T) price_registry.PriceRegistryDestChainConfig { +func defaultPriceRegistryDestChainConfig(t *testing.T) fee_quoter.FeeQuoterDestChainConfig { // https://github.com/smartcontractkit/ccip/blob/c4856b64bd766f1ddbaf5d13b42d3c4b12efde3a/contracts/src/v0.8/ccip/libraries/Internal.sol#L337-L337 /* ```Solidity @@ -829,7 +829,7 @@ func defaultPriceRegistryDestChainConfig(t *testing.T) price_registry.PriceRegis */ evmFamilySelector, err := hex.DecodeString("2812d52c") require.NoError(t, err) - return price_registry.PriceRegistryDestChainConfig{ + return fee_quoter.FeeQuoterDestChainConfig{ IsEnabled: true, MaxNumberOfTokensPerMsg: 10, MaxDataBytes: 256, @@ -901,11 +901,11 @@ func deployPriceRegistry( wethAddr common.Address, maxFeeJuelsPerMsg *big.Int, chainID uint64, -) *price_registry.PriceRegistry { - priceRegistryAddr, _, _, err := price_registry.DeployPriceRegistry( +) *fee_quoter.FeeQuoter { + priceRegistryAddr, _, _, err := fee_quoter.DeployFeeQuoter( owner, backend, - price_registry.PriceRegistryStaticConfig{ + fee_quoter.FeeQuoterStaticConfig{ MaxFeeJuelsPerMsg: maxFeeJuelsPerMsg, LinkToken: linkAddr, StalenessThreshold: 24 * 60 * 60, // 24 hours @@ -915,10 +915,10 @@ func deployPriceRegistry( }, // price updaters, will be set to offramp later []common.Address{linkAddr, wethAddr}, // fee tokens // empty for now, need to fill in when testing token transfers - []price_registry.PriceRegistryTokenPriceFeedUpdate{}, + []fee_quoter.FeeQuoterTokenPriceFeedUpdate{}, // empty for now, need to fill in when testing token transfers - []price_registry.PriceRegistryTokenTransferFeeConfigArgs{}, - []price_registry.PriceRegistryPremiumMultiplierWeiPerEthArgs{ + []fee_quoter.FeeQuoterTokenTransferFeeConfigArgs{}, + []fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthArgs{ { PremiumMultiplierWeiPerEth: 9e17, // 0.9 ETH Token: linkAddr, @@ -929,11 +929,11 @@ func deployPriceRegistry( }, }, // Destination chain configs will be set up later once we have all chains - []price_registry.PriceRegistryDestChainConfigArgs{}, + []fee_quoter.FeeQuoterDestChainConfigArgs{}, ) require.NoErrorf(t, err, "failed to deploy price registry on chain id %d", chainID) backend.Commit() - priceRegistry, err := price_registry.NewPriceRegistry(priceRegistryAddr, backend) + priceRegistry, err := fee_quoter.NewFeeQuoter(priceRegistryAddr, backend) require.NoError(t, err) return priceRegistry } diff --git a/core/capabilities/ccip/configs/evm/contract_reader.go b/core/capabilities/ccip/configs/evm/contract_reader.go index e395013cc9..cd89e96337 100644 --- a/core/capabilities/ccip/configs/evm/contract_reader.go +++ b/core/capabilities/ccip/configs/evm/contract_reader.go @@ -7,12 +7,12 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi" "github.com/smartcontractkit/chainlink-ccip/pkg/consts" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/onramp" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/ccip_config" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/fee_quoter" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/offramp" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/onramp" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/price_registry" kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" evmrelaytypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" ) @@ -21,7 +21,7 @@ var ( onrampABI = evmtypes.MustGetABI(onramp.OnRampABI) capabilitiesRegsitryABI = evmtypes.MustGetABI(kcr.CapabilitiesRegistryABI) ccipConfigABI = evmtypes.MustGetABI(ccip_config.CCIPConfigABI) - priceRegistryABI = evmtypes.MustGetABI(price_registry.PriceRegistryABI) + priceRegistryABI = evmtypes.MustGetABI(fee_quoter.FeeQuoterABI) ) // MustSourceReaderConfig returns a ChainReaderConfig that can be used to read from the onramp. @@ -138,7 +138,7 @@ var SourceReaderConfig = evmrelaytypes.ChainReaderConfig{ }, }, consts.ContractNamePriceRegistry: { - ContractABI: price_registry.PriceRegistryABI, + ContractABI: fee_quoter.FeeQuoterABI, Configs: map[string]*evmrelaytypes.ChainReaderDefinition{ // TODO: update with the consts from https://github.com/smartcontractkit/chainlink-ccip/pull/39 // in a followup. diff --git a/core/gethwrappers/ccip/generated/price_registry/price_registry.go b/core/gethwrappers/ccip/generated/fee_quoter/fee_quoter.go similarity index 54% rename from core/gethwrappers/ccip/generated/price_registry/price_registry.go rename to core/gethwrappers/ccip/generated/fee_quoter/fee_quoter.go index a4839d7ac3..74ed33b73a 100644 --- a/core/gethwrappers/ccip/generated/price_registry/price_registry.go +++ b/core/gethwrappers/ccip/generated/fee_quoter/fee_quoter.go @@ -1,7 +1,7 @@ // Code generated - DO NOT EDIT. // This file is a generated binding and any manual changes will be lost. -package price_registry +package fee_quoter import ( "errors" @@ -48,48 +48,7 @@ type ClientEVMTokenAmount struct { Amount *big.Int } -type IPriceRegistryTokenPriceFeedConfig struct { - DataFeedAddress common.Address - TokenDecimals uint8 -} - -type InternalGasPriceUpdate struct { - DestChainSelector uint64 - UsdPerUnitGas *big.Int -} - -type InternalPriceUpdates struct { - TokenPriceUpdates []InternalTokenPriceUpdate - GasPriceUpdates []InternalGasPriceUpdate -} - -type InternalRampTokenAmount struct { - SourcePoolAddress []byte - DestTokenAddress []byte - ExtraData []byte - Amount *big.Int - DestExecData []byte -} - -type InternalTimestampedPackedUint224 struct { - Value *big.Int - Timestamp uint32 -} - -type InternalTokenPriceUpdate struct { - SourceToken common.Address - UsdPerToken *big.Int -} - -type KeystoneFeedsPermissionHandlerPermission struct { - Forwarder common.Address - WorkflowName [10]byte - ReportName [2]byte - WorkflowOwner common.Address - IsAllowed bool -} - -type PriceRegistryDestChainConfig struct { +type FeeQuoterDestChainConfig struct { IsEnabled bool MaxNumberOfTokensPerMsg uint16 MaxDataBytes uint32 @@ -108,28 +67,28 @@ type PriceRegistryDestChainConfig struct { ChainFamilySelector [4]byte } -type PriceRegistryDestChainConfigArgs struct { +type FeeQuoterDestChainConfigArgs struct { DestChainSelector uint64 - DestChainConfig PriceRegistryDestChainConfig + DestChainConfig FeeQuoterDestChainConfig } -type PriceRegistryPremiumMultiplierWeiPerEthArgs struct { +type FeeQuoterPremiumMultiplierWeiPerEthArgs struct { Token common.Address PremiumMultiplierWeiPerEth uint64 } -type PriceRegistryStaticConfig struct { +type FeeQuoterStaticConfig struct { MaxFeeJuelsPerMsg *big.Int LinkToken common.Address StalenessThreshold uint32 } -type PriceRegistryTokenPriceFeedUpdate struct { +type FeeQuoterTokenPriceFeedUpdate struct { SourceToken common.Address - FeedConfig IPriceRegistryTokenPriceFeedConfig + FeedConfig IFeeQuoterTokenPriceFeedConfig } -type PriceRegistryTokenTransferFeeConfig struct { +type FeeQuoterTokenTransferFeeConfig struct { MinFeeUSDCents uint32 MaxFeeUSDCents uint32 DeciBps uint16 @@ -138,32 +97,73 @@ type PriceRegistryTokenTransferFeeConfig struct { IsEnabled bool } -type PriceRegistryTokenTransferFeeConfigArgs struct { +type FeeQuoterTokenTransferFeeConfigArgs struct { DestChainSelector uint64 - TokenTransferFeeConfigs []PriceRegistryTokenTransferFeeConfigSingleTokenArgs + TokenTransferFeeConfigs []FeeQuoterTokenTransferFeeConfigSingleTokenArgs } -type PriceRegistryTokenTransferFeeConfigRemoveArgs struct { +type FeeQuoterTokenTransferFeeConfigRemoveArgs struct { DestChainSelector uint64 Token common.Address } -type PriceRegistryTokenTransferFeeConfigSingleTokenArgs struct { +type FeeQuoterTokenTransferFeeConfigSingleTokenArgs struct { Token common.Address - TokenTransferFeeConfig PriceRegistryTokenTransferFeeConfig + TokenTransferFeeConfig FeeQuoterTokenTransferFeeConfig +} + +type IFeeQuoterTokenPriceFeedConfig struct { + DataFeedAddress common.Address + TokenDecimals uint8 +} + +type InternalGasPriceUpdate struct { + DestChainSelector uint64 + UsdPerUnitGas *big.Int +} + +type InternalPriceUpdates struct { + TokenPriceUpdates []InternalTokenPriceUpdate + GasPriceUpdates []InternalGasPriceUpdate +} + +type InternalRampTokenAmount struct { + SourcePoolAddress []byte + DestTokenAddress []byte + ExtraData []byte + Amount *big.Int + DestExecData []byte +} + +type InternalTimestampedPackedUint224 struct { + Value *big.Int + Timestamp uint32 +} + +type InternalTokenPriceUpdate struct { + SourceToken common.Address + UsdPerToken *big.Int +} + +type KeystoneFeedsPermissionHandlerPermission struct { + Forwarder common.Address + WorkflowName [10]byte + ReportName [2]byte + WorkflowOwner common.Address + IsAllowed bool } -var PriceRegistryMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint96\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"linkToken\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"stalenessThreshold\",\"type\":\"uint32\"}],\"internalType\":\"structPriceRegistry.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"priceUpdaters\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"feeTokens\",\"type\":\"address[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"}],\"internalType\":\"structIPriceRegistry.TokenPriceFeedConfig\",\"name\":\"feedConfig\",\"type\":\"tuple\"}],\"internalType\":\"structPriceRegistry.TokenPriceFeedUpdate[]\",\"name\":\"tokenPriceFeeds\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structPriceRegistry.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"internalType\":\"structPriceRegistry.TokenTransferFeeConfigSingleTokenArgs[]\",\"name\":\"tokenTransferFeeConfigs\",\"type\":\"tuple[]\"}],\"internalType\":\"structPriceRegistry.TokenTransferFeeConfigArgs[]\",\"name\":\"tokenTransferFeeConfigArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"internalType\":\"structPriceRegistry.PremiumMultiplierWeiPerEthArgs[]\",\"name\":\"premiumMultiplierWeiPerEthArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"internalType\":\"structPriceRegistry.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structPriceRegistry.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chain\",\"type\":\"uint64\"}],\"name\":\"ChainNotSupported\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DataFeedValueOutOfUint224Range\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"DestinationChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ExtraArgOutOfOrderExecutionMustBeTrue\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"}],\"name\":\"InvalidDestBytesOverhead\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidDestChainConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidEVMAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidExtraArgsTag\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidStaticConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"msgFeeJuels\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint256\"}],\"name\":\"MessageFeeTooHigh\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MessageGasLimitTooHigh\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"maxSize\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualSize\",\"type\":\"uint256\"}],\"name\":\"MessageTooLarge\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"internalType\":\"bytes10\",\"name\":\"workflowName\",\"type\":\"bytes10\"},{\"internalType\":\"bytes2\",\"name\":\"reportName\",\"type\":\"bytes2\"}],\"name\":\"ReportForwarderUnauthorized\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"SourceTokenDataTooLarge\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"threshold\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timePassed\",\"type\":\"uint256\"}],\"name\":\"StaleGasPrice\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feedTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"storedTimeStamp\",\"type\":\"uint256\"}],\"name\":\"StaleKeystoneUpdate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"TokenNotSupported\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"UnauthorizedCaller\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnsupportedNumberOfTokens\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"AuthorizedCallerAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"AuthorizedCallerRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"indexed\":false,\"internalType\":\"structPriceRegistry.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"name\":\"DestChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"indexed\":false,\"internalType\":\"structPriceRegistry.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"name\":\"DestChainConfigUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"}],\"name\":\"FeeTokenAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"}],\"name\":\"FeeTokenRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"name\":\"PremiumMultiplierWeiPerEthUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"}],\"indexed\":false,\"internalType\":\"structIPriceRegistry.TokenPriceFeedConfig\",\"name\":\"priceFeedConfig\",\"type\":\"tuple\"}],\"name\":\"PriceFeedPerTokenUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"reportId\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"},{\"internalType\":\"bytes10\",\"name\":\"workflowName\",\"type\":\"bytes10\"},{\"internalType\":\"bytes2\",\"name\":\"reportName\",\"type\":\"bytes2\"},{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isAllowed\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"structKeystoneFeedsPermissionHandler.Permission\",\"name\":\"permission\",\"type\":\"tuple\"}],\"name\":\"ReportPermissionSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"TokenTransferFeeConfigDeleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"structPriceRegistry.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"name\":\"TokenTransferFeeConfigUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"UsdPerTokenUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChain\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"UsdPerUnitGasUpdated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address[]\",\"name\":\"addedCallers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"removedCallers\",\"type\":\"address[]\"}],\"internalType\":\"structAuthorizedCallers.AuthorizedCallerArgs\",\"name\":\"authorizedCallerArgs\",\"type\":\"tuple\"}],\"name\":\"applyAuthorizedCallerUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"internalType\":\"structPriceRegistry.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structPriceRegistry.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyDestChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"feeTokensToAdd\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"feeTokensToRemove\",\"type\":\"address[]\"}],\"name\":\"applyFeeTokensUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"internalType\":\"structPriceRegistry.PremiumMultiplierWeiPerEthArgs[]\",\"name\":\"premiumMultiplierWeiPerEthArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyPremiumMultiplierWeiPerEthUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structPriceRegistry.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"internalType\":\"structPriceRegistry.TokenTransferFeeConfigSingleTokenArgs[]\",\"name\":\"tokenTransferFeeConfigs\",\"type\":\"tuple[]\"}],\"internalType\":\"structPriceRegistry.TokenTransferFeeConfigArgs[]\",\"name\":\"tokenTransferFeeConfigArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"internalType\":\"structPriceRegistry.TokenTransferFeeConfigRemoveArgs[]\",\"name\":\"tokensToUseDefaultFeeConfigs\",\"type\":\"tuple[]\"}],\"name\":\"applyTokenTransferFeeConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"fromToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fromTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"toToken\",\"type\":\"address\"}],\"name\":\"convertTokenAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllAuthorizedCallers\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getDestChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"internalType\":\"structPriceRegistry.DestChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getDestinationChainGasPrice\",\"outputs\":[{\"components\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"internalType\":\"structInternal.TimestampedPackedUint224\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getFeeTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getPremiumMultiplierWeiPerEth\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint96\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"linkToken\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"stalenessThreshold\",\"type\":\"uint32\"}],\"internalType\":\"structPriceRegistry.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getTokenAndGasPrices\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"tokenPrice\",\"type\":\"uint224\"},{\"internalType\":\"uint224\",\"name\":\"gasPriceValue\",\"type\":\"uint224\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenPrice\",\"outputs\":[{\"components\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"internalType\":\"structInternal.TimestampedPackedUint224\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenPriceFeedConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"}],\"internalType\":\"structIPriceRegistry.TokenPriceFeedConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"tokens\",\"type\":\"address[]\"}],\"name\":\"getTokenPrices\",\"outputs\":[{\"components\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"internalType\":\"structInternal.TimestampedPackedUint224[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenTransferFeeConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structPriceRegistry.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"getValidatedFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getValidatedTokenPrice\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"\",\"type\":\"uint224\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"onReport\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"name\":\"processMessageArgs\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"msgFeeJuels\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isOutOfOrderExecution\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"convertedExtraArgs\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"rampTokenAmounts\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"sourceTokenAmounts\",\"type\":\"tuple[]\"}],\"name\":\"processPoolReturnData\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"destExecDataPerToken\",\"type\":\"bytes[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"},{\"internalType\":\"bytes10\",\"name\":\"workflowName\",\"type\":\"bytes10\"},{\"internalType\":\"bytes2\",\"name\":\"reportName\",\"type\":\"bytes2\"},{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isAllowed\",\"type\":\"bool\"}],\"internalType\":\"structKeystoneFeedsPermissionHandler.Permission[]\",\"name\":\"permissions\",\"type\":\"tuple[]\"}],\"name\":\"setReportPermissions\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"}],\"name\":\"updatePrices\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"}],\"internalType\":\"structIPriceRegistry.TokenPriceFeedConfig\",\"name\":\"feedConfig\",\"type\":\"tuple\"}],\"internalType\":\"structPriceRegistry.TokenPriceFeedUpdate[]\",\"name\":\"tokenPriceFeedUpdates\",\"type\":\"tuple[]\"}],\"name\":\"updateTokenPriceFeeds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x60e06040523480156200001157600080fd5b50604051620076d8380380620076d8833981016040819052620000349162001834565b8533806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf8162000207565b5050604080518082018252838152815160008152602080820190935291810191909152620000ee9150620002b2565b5060208701516001600160a01b0316158062000112575086516001600160601b0316155b80620001265750604087015163ffffffff16155b15620001455760405163d794ef9560e01b815260040160405180910390fd5b6020878101516001600160a01b031660a05287516001600160601b031660805260408089015163ffffffff1660c05280516000815291820190526200018c90869062000401565b620001978462000549565b620001a2816200061a565b620001ad8262000a5a565b60408051600080825260208201909252620001fa91859190620001f3565b6040805180820190915260008082526020820152815260200190600190039081620001cb5790505b5062000b26565b5050505050505062001ae5565b336001600160a01b03821603620002615760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b602081015160005b815181101562000342576000828281518110620002db57620002db62001953565b60209081029190910101519050620002f560028262000e5f565b1562000338576040516001600160a01b03821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b50600101620002ba565b50815160005b8151811015620003fb57600082828151811062000369576200036962001953565b6020026020010151905060006001600160a01b0316816001600160a01b031603620003a7576040516342bcdf7f60e11b815260040160405180910390fd5b620003b460028262000e7f565b506040516001600160a01b03821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a15060010162000348565b50505050565b60005b8251811015620004a2576200044083828151811062000427576200042762001953565b6020026020010151600b62000e7f60201b90919060201c565b1562000499578281815181106200045b576200045b62001953565b60200260200101516001600160a01b03167fdf1b1bd32a69711488d71554706bb130b1fc63a5fa1a2cd85e8440f84065ba2360405160405180910390a25b60010162000404565b5060005b81518110156200054457620004e2828281518110620004c957620004c962001953565b6020026020010151600b62000e9660201b90919060201c565b156200053b57818181518110620004fd57620004fd62001953565b60200260200101516001600160a01b03167f1795838dc8ab2ffc5f431a1729a6afa0b587f982f7b2be0b9d7187a1ef547f9160405160405180910390a25b600101620004a6565b505050565b60005b8151811015620006165760008282815181106200056d576200056d62001953565b6020908102919091018101518051818301516001600160a01b0380831660008181526007875260409081902084518154868a018051929096166001600160a81b03199091168117600160a01b60ff9384160217909255825191825293519093169683019690965293955091939092917f08a5f7f5bb38a81d8e43aca13ecd76431dbf8816ae4699affff7b00b2fc1c464910160405180910390a25050508060010190506200054c565b5050565b60005b8151811015620006165760008282815181106200063e576200063e62001953565b6020026020010151905060008383815181106200065f576200065f62001953565b6020026020010151600001519050600082602001519050816001600160401b03166000148062000698575061016081015163ffffffff16155b80620006ba57506101e08101516001600160e01b031916630a04b54b60e21b14155b80620006da5750806060015163ffffffff1681610160015163ffffffff16115b15620007055760405163c35aa79d60e01b81526001600160401b038316600482015260240162000083565b6001600160401b038216600090815260096020526040812060010154600160881b900460e01b6001600160e01b03191690036200078557816001600160401b03167fd31c671936387b2f84ed402b553bd50c0e9c20408ea4e91a836d77b8180fb7248260405162000777919062001969565b60405180910390a2620007c9565b816001600160401b03167f1edd6f3553cfa16f10b95b195abae3a1cfca4783de4843f95d674b1e1df5ab2082604051620007c0919062001969565b60405180910390a25b8060096000846001600160401b03166001600160401b0316815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548161ffff021916908361ffff16021790555060408201518160000160036101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160076101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600b6101000a81548163ffffffff021916908363ffffffff16021790555060a082015181600001600f6101000a81548161ffff021916908361ffff16021790555060c08201518160000160116101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160000160156101000a81548161ffff021916908361ffff1602179055506101008201518160000160176101000a81548161ffff021916908361ffff1602179055506101208201518160000160196101000a81548161ffff021916908361ffff16021790555061014082015181600001601b6101000a81548163ffffffff021916908363ffffffff1602179055506101608201518160010160006101000a81548163ffffffff021916908363ffffffff1602179055506101808201518160010160046101000a8154816001600160401b0302191690836001600160401b031602179055506101a082015181600101600c6101000a81548163ffffffff021916908363ffffffff1602179055506101c08201518160010160106101000a81548160ff0219169083151502179055506101e08201518160010160116101000a81548163ffffffff021916908360e01c02179055509050505050508060010190506200061d565b60005b81518110156200061657600082828151811062000a7e5762000a7e62001953565b6020026020010151600001519050600083838151811062000aa35762000aa362001953565b6020908102919091018101518101516001600160a01b03841660008181526008845260409081902080546001600160401b0319166001600160401b0385169081179091559051908152919350917fbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d910160405180910390a2505060010162000a5d565b60005b825181101562000d9957600083828151811062000b4a5762000b4a62001953565b6020026020010151905060008160000151905060005b82602001515181101562000d8a5760008360200151828151811062000b895762000b8962001953565b602002602001015160200151905060008460200151838151811062000bb25762000bb262001953565b6020026020010151600001519050602063ffffffff16826080015163ffffffff16101562000c115760808201516040516312766e0160e11b81526001600160a01b038316600482015263ffffffff909116602482015260440162000083565b6001600160401b0384166000818152600a602090815260408083206001600160a01b0386168085529083529281902086518154938801518389015160608a015160808b015160a08c01511515600160901b0260ff60901b1963ffffffff928316600160701b021664ffffffffff60701b199383166a01000000000000000000000263ffffffff60501b1961ffff90961668010000000000000000029590951665ffffffffffff60401b19968416640100000000026001600160401b0319909b16939097169290921798909817939093169390931717919091161792909217909155519091907f94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b59062000d77908690600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60405180910390a3505060010162000b60565b50505080600101905062000b29565b5060005b81518110156200054457600082828151811062000dbe5762000dbe62001953565b6020026020010151600001519050600083838151811062000de35762000de362001953565b6020908102919091018101518101516001600160401b0384166000818152600a845260408082206001600160a01b038516808452955280822080546001600160981b03191690555192945090917f4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b9190a3505060010162000d9d565b600062000e76836001600160a01b03841662000ead565b90505b92915050565b600062000e76836001600160a01b03841662000fb1565b600062000e76836001600160a01b03841662001003565b6000818152600183016020526040812054801562000fa657600062000ed460018362001aad565b855490915060009062000eea9060019062001aad565b905081811462000f5657600086600001828154811062000f0e5762000f0e62001953565b906000526020600020015490508087600001848154811062000f345762000f3462001953565b6000918252602080832090910192909255918252600188019052604090208390555b855486908062000f6a5762000f6a62001acf565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505062000e79565b600091505062000e79565b600081815260018301602052604081205462000ffa5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000e79565b50600062000e79565b6000818152600183016020526040812054801562000fa65760006200102a60018362001aad565b8554909150600090620010409060019062001aad565b905080821462000f5657600086600001828154811062000f0e5762000f0e62001953565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b03811182821017156200109f576200109f62001064565b60405290565b60405160c081016001600160401b03811182821017156200109f576200109f62001064565b60405161020081016001600160401b03811182821017156200109f576200109f62001064565b604051601f8201601f191681016001600160401b03811182821017156200111b576200111b62001064565b604052919050565b80516001600160a01b03811681146200113b57600080fd5b919050565b805163ffffffff811681146200113b57600080fd5b6000606082840312156200116857600080fd5b604051606081016001600160401b03811182821017156200118d576200118d62001064565b604052825190915081906001600160601b0381168114620011ad57600080fd5b8152620011bd6020840162001123565b6020820152620011d06040840162001140565b60408201525092915050565b60006001600160401b03821115620011f857620011f862001064565b5060051b60200190565b600082601f8301126200121457600080fd5b815160206200122d6200122783620011dc565b620010f0565b8083825260208201915060208460051b8701019350868411156200125057600080fd5b602086015b848110156200127757620012698162001123565b835291830191830162001255565b509695505050505050565b600082601f8301126200129457600080fd5b81516020620012a76200122783620011dc565b82815260609283028501820192828201919087851115620012c757600080fd5b8387015b858110156200135a5780890382811215620012e65760008081fd5b620012f06200107a565b620012fb8362001123565b8152604080601f1984011215620013125760008081fd5b6200131c6200107a565b92506200132b88850162001123565b835283015160ff81168114620013415760008081fd5b82880152808701919091528452928401928101620012cb565b5090979650505050505050565b80516001600160401b03811681146200113b57600080fd5b805161ffff811681146200113b57600080fd5b805180151581146200113b57600080fd5b600082601f830112620013b557600080fd5b81516020620013c86200122783620011dc565b82815260059290921b84018101918181019086841115620013e857600080fd5b8286015b84811015620012775780516001600160401b03808211156200140d57600080fd5b908801906040601f19838c0381018213156200142857600080fd5b620014326200107a565b6200143f89860162001367565b815282850151848111156200145357600080fd5b8086019550508c603f8601126200146957600080fd5b8885015193506200147e6200122785620011dc565b84815260e09094028501830193898101908e8611156200149d57600080fd5b958401955b858710156200157657868f0360e0811215620014bd57600080fd5b620014c76200107a565b620014d28962001123565b815260c08683011215620014e557600080fd5b620014ef620010a5565b9150620014fe8d8a0162001140565b82526200150d878a0162001140565b8d8301526200151f60608a016200137f565b878301526200153160808a0162001140565b60608301526200154460a08a0162001140565b60808301526200155760c08a0162001392565b60a0830152808d0191909152825260e09690960195908a0190620014a2565b828b015250875250505092840192508301620013ec565b600082601f8301126200159f57600080fd5b81516020620015b26200122783620011dc565b82815260069290921b84018101918181019086841115620015d257600080fd5b8286015b84811015620012775760408189031215620015f15760008081fd5b620015fb6200107a565b620016068262001123565b81526200161585830162001367565b81860152835291830191604001620015d6565b80516001600160e01b0319811681146200113b57600080fd5b600082601f8301126200165357600080fd5b81516020620016666200122783620011dc565b82815261022092830285018201928282019190878511156200168757600080fd5b8387015b858110156200135a5780890382811215620016a65760008081fd5b620016b06200107a565b620016bb8362001367565b815261020080601f1984011215620016d35760008081fd5b620016dd620010ca565b9250620016ec88850162001392565b83526040620016fd8186016200137f565b8985015260606200171081870162001140565b82860152608091506200172582870162001140565b9085015260a06200173886820162001140565b8286015260c091506200174d8287016200137f565b9085015260e06200176086820162001140565b828601526101009150620017768287016200137f565b908501526101206200178a8682016200137f565b828601526101409150620017a08287016200137f565b90850152610160620017b486820162001140565b828601526101809150620017ca82870162001140565b908501526101a0620017de86820162001367565b828601526101c09150620017f482870162001140565b908501526101e06200180886820162001392565b828601526200181983870162001628565b9085015250508087019190915284529284019281016200168b565b6000806000806000806000610120888a0312156200185157600080fd5b6200185d898962001155565b60608901519097506001600160401b03808211156200187b57600080fd5b620018898b838c0162001202565b975060808a0151915080821115620018a057600080fd5b620018ae8b838c0162001202565b965060a08a0151915080821115620018c557600080fd5b620018d38b838c0162001282565b955060c08a0151915080821115620018ea57600080fd5b620018f88b838c01620013a3565b945060e08a01519150808211156200190f57600080fd5b6200191d8b838c016200158d565b93506101008a01519150808211156200193557600080fd5b50620019448a828b0162001641565b91505092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b815115158152610200810160208301516200198a602084018261ffff169052565b506040830151620019a3604084018263ffffffff169052565b506060830151620019bc606084018263ffffffff169052565b506080830151620019d5608084018263ffffffff169052565b5060a0830151620019ec60a084018261ffff169052565b5060c083015162001a0560c084018263ffffffff169052565b5060e083015162001a1c60e084018261ffff169052565b506101008381015161ffff9081169184019190915261012080850151909116908301526101408084015163ffffffff9081169184019190915261016080850151821690840152610180808501516001600160401b0316908401526101a080850151909116908301526101c0808401511515908301526101e0928301516001600160e01b031916929091019190915290565b8181038181111562000e7957634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b60805160a05160c051615b9962001b3f600039600081816102ef0152818161219101526121fa0152600081816102b301528181611917015261197701526000818161027f015281816119a00152611a100152615b996000f3fe608060405234801561001057600080fd5b50600436106101ce5760003560e01c806379ba509711610104578063a69c64c0116100a2578063d02641a011610071578063d02641a014610a81578063d8694ccd14610a94578063f2fde38b14610aa7578063ffdb4b3714610aba57600080fd5b8063a69c64c014610997578063bf78e03f146109aa578063c4276bfc14610a57578063cdc73d5114610a7957600080fd5b806382b49eb0116100de57806382b49eb0146107d95780638da5cb5b1461094957806391a2749a146109715780639ea600261461098457600080fd5b806379ba5097146107ab5780637afac322146107b3578063805f2132146107c657600080fd5b8063407e1086116101715780634ab35b0b1161014b5780634ab35b0b14610441578063514e8cff146104815780636def4ce714610524578063770e2dc41461079857600080fd5b8063407e1086146103fb57806341ed29e71461040e57806345ac924d1461042157600080fd5b8063085318f8116101ad578063085318f814610368578063181f5a77146103885780632451a627146103d15780633937306f146103e657600080fd5b806241e5be146101d3578063061877e3146101f957806306285c6914610252575b600080fd5b6101e66101e1366004614250565b610b02565b6040519081526020015b60405180910390f35b61023961020736600461428c565b73ffffffffffffffffffffffffffffffffffffffff1660009081526008602052604090205467ffffffffffffffff1690565b60405167ffffffffffffffff90911681526020016101f0565b61031c604080516060810182526000808252602082018190529181019190915260405180606001604052807f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000063ffffffff16815250905090565b6040805182516bffffffffffffffffffffffff16815260208084015173ffffffffffffffffffffffffffffffffffffffff16908201529181015163ffffffff16908201526060016101f0565b61037b610376366004614304565b610b70565b6040516101f09190614416565b6103c46040518060400160405280601781526020017f5072696365526567697374727920312e362e302d64657600000000000000000081525081565b6040516101f09190614498565b6103d9610ee2565b6040516101f091906144ab565b6103f96103f4366004614505565b610ef3565b005b6103f96104093660046146a7565b6111a8565b6103f961041c3660046147d9565b6111bc565b61043461042f366004614914565b6111fe565b6040516101f09190614956565b61045461044f36600461428c565b6112c9565b6040517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff90911681526020016101f0565b61051761048f3660046149d1565b60408051808201909152600080825260208201525067ffffffffffffffff166000908152600560209081526040918290208251808401909352547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811683527c0100000000000000000000000000000000000000000000000000000000900463ffffffff169082015290565b6040516101f091906149ec565b61078b6105323660046149d1565b6040805161020081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a081018290526101c081018290526101e08101919091525067ffffffffffffffff908116600090815260096020908152604091829020825161020081018452815460ff8082161515835261ffff61010080840482169685019690965263ffffffff630100000084048116978501979097526701000000000000008304871660608501526b0100000000000000000000008304871660808501526f010000000000000000000000000000008304811660a085015271010000000000000000000000000000000000808404881660c086015275010000000000000000000000000000000000000000008404821660e08087019190915277010000000000000000000000000000000000000000000000850483169786019790975279010000000000000000000000000000000000000000000000000084049091166101208501527b01000000000000000000000000000000000000000000000000000000909204861661014084015260019093015480861661016084015264010000000081049096166101808301526c0100000000000000000000000086049094166101a0820152700100000000000000000000000000000000850490911615156101c08201527fffffffff0000000000000000000000000000000000000000000000000000000092909304901b166101e082015290565b6040516101f09190614a27565b6103f96107a6366004614c3e565b6112d4565b6103f96112e6565b6103f96107c1366004614f58565b6113e3565b6103f96107d4366004614ffe565b6113f5565b6108e96107e736600461506a565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101919091525067ffffffffffffffff919091166000908152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff94909416835292815290829020825160c081018452905463ffffffff8082168352640100000000820481169383019390935268010000000000000000810461ffff16938201939093526a01000000000000000000008304821660608201526e01000000000000000000000000000083049091166080820152720100000000000000000000000000000000000090910460ff16151560a082015290565b6040516101f09190600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101f0565b6103f961097f366004615094565b6118dd565b6103f9610992366004615155565b6118ee565b6103f96109a5366004615362565b6118ff565b610a236109b836600461428c565b6040805180820182526000808252602091820181905273ffffffffffffffffffffffffffffffffffffffff93841681526007825282902082518084019093525492831682527401000000000000000000000000000000000000000090920460ff169181019190915290565b60408051825173ffffffffffffffffffffffffffffffffffffffff16815260209283015160ff1692810192909252016101f0565b610a6a610a65366004615427565b611910565b6040516101f093929190615496565b6103d9611b06565b610517610a8f36600461428c565b611b12565b6101e6610aa23660046154b7565b611c0e565b6103f9610ab536600461428c565b6120ac565b610acd610ac836600461550c565b6120bd565b604080517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff9384168152929091166020830152016101f0565b6000610b0d82612248565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16610b3485612248565b610b5c907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1685615565565b610b66919061557c565b90505b9392505050565b67ffffffffffffffff8086166000908152600960205260409020600101546060917101000000000000000000000000000000000090910460e01b908590811115610bbc57610bbc614540565b604051908082528060200260200182016040528015610bef57816020015b6060815260200190600190039081610bda5790505b50915060005b85811015610ed7576000858583818110610c1157610c116155b7565b610c27926020604090920201908101915061428c565b90506000888884818110610c3d57610c3d6155b7565b9050602002810190610c4f91906155e6565b610c5d906040810190615624565b9150506020811115610d125767ffffffffffffffff8a166000908152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff861684529091529020546e010000000000000000000000000000900463ffffffff16811115610d12576040517f36f536ca00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526024015b60405180910390fd5b610d82848a8a86818110610d2857610d286155b7565b9050602002810190610d3a91906155e6565b610d48906020810190615624565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506122e292505050565b67ffffffffffffffff8a166000818152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684528252808320815160c081018352905463ffffffff8082168352640100000000820481168386015268010000000000000000820461ffff16838501526a01000000000000000000008204811660608401526e010000000000000000000000000000820481166080840152720100000000000000000000000000000000000090910460ff16151560a08301908152958552600990935290832054935190937b0100000000000000000000000000000000000000000000000000000090049091169190610e815781610e87565b82606001515b6040805163ffffffff8316602082015291925001604051602081830303815290604052888781518110610ebc57610ebc6155b7565b60200260200101819052505050505050806001019050610bf5565b505095945050505050565b6060610eee6002612339565b905090565b610efb612346565b6000610f078280615689565b9050905060005b81811015611051576000610f228480615689565b83818110610f3257610f326155b7565b905060400201803603810190610f48919061571d565b604080518082018252602080840180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff908116845263ffffffff42818116858701908152885173ffffffffffffffffffffffffffffffffffffffff9081166000908152600690975295889020965190519092167c010000000000000000000000000000000000000000000000000000000002919092161790935584519051935194955016927f52f50aa6d1a95a4595361ecf953d095f125d442e4673716dede699e049de148a926110409290917bffffffffffffffffffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b60405180910390a250600101610f0e565b5060006110616020840184615689565b9050905060005b818110156111a257600061107f6020860186615689565b8381811061108f5761108f6155b7565b9050604002018036038101906110a5919061575a565b604080518082018252602080840180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff908116845263ffffffff42818116858701908152885167ffffffffffffffff9081166000908152600590975295889020965190519092167c010000000000000000000000000000000000000000000000000000000002919092161790935584519051935194955016927fdd84a3fa9ef9409f550d54d6affec7e9c480c878c6ab27b78912a03e1b371c6e926111919290917bffffffffffffffffffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b60405180910390a250600101611068565b50505050565b6111b061238b565b6111b98161240c565b50565b6111c461238b565b60005b81518110156111fa576111f28282815181106111e5576111e56155b7565b602002602001015161250a565b6001016111c7565b5050565b60608160008167ffffffffffffffff81111561121c5761121c614540565b60405190808252806020026020018201604052801561126157816020015b604080518082019091526000808252602082015281526020019060019003908161123a5790505b50905060005b828110156112be57611299868683818110611284576112846155b7565b9050602002016020810190610a8f919061428c565b8282815181106112ab576112ab6155b7565b6020908102919091010152600101611267565b509150505b92915050565b60006112c382612248565b6112dc61238b565b6111fa82826126dc565b60015473ffffffffffffffffffffffffffffffffffffffff163314611367576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610d09565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6113eb61238b565b6111fa8282612ae9565b600080600061143987878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612c3092505050565b92509250925061144b33838584612c4b565b60006114598587018761577d565b905060005b81518110156118d25760006007600084848151811061147f5761147f6155b7565b6020908102919091018101515173ffffffffffffffffffffffffffffffffffffffff16825281019190915260400160009081205474010000000000000000000000000000000000000000900460ff169150819003611540578282815181106114e9576114e96155b7565b6020908102919091010151516040517f06439c6b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610d09565b600061158960128386868151811061155a5761155a6155b7565b6020026020010151602001517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16612da3565b9050600660008585815181106115a1576115a16155b7565b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001601c9054906101000a900463ffffffff1663ffffffff16848481518110611613576116136155b7565b60200260200101516040015163ffffffff16101561171d5783838151811061163d5761163d6155b7565b60200260200101516000015184848151811061165b5761165b6155b7565b6020026020010151604001516006600087878151811061167d5761167d6155b7565b6020908102919091018101515173ffffffffffffffffffffffffffffffffffffffff90811683529082019290925260409081016000205490517f191ec70600000000000000000000000000000000000000000000000000000000815293909116600484015263ffffffff91821660248401527c01000000000000000000000000000000000000000000000000000000009004166044820152606401610d09565b6040518060400160405280827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16815260200185858151811061175e5761175e6155b7565b60200260200101516040015163ffffffff1681525060066000868681518110611789576117896155b7565b6020908102919091018101515173ffffffffffffffffffffffffffffffffffffffff168252818101929092526040016000208251929091015163ffffffff167c0100000000000000000000000000000000000000000000000000000000027bffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092169190911790558351849084908110611821576118216155b7565b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff167f52f50aa6d1a95a4595361ecf953d095f125d442e4673716dede699e049de148a82868681518110611877576118776155b7565b6020026020010151604001516040516118c09291907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff92909216825263ffffffff16602082015260400190565b60405180910390a2505060010161145e565b505050505050505050565b6118e561238b565b6111b981612e69565b6118f661238b565b6111b981612ff5565b61190761238b565b6111b98161349b565b60008060607f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff16036119705785925061199e565b61199b87877f0000000000000000000000000000000000000000000000000000000000000000610b02565b92505b7f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff16831115611a3d576040517f6a92a483000000000000000000000000000000000000000000000000000000008152600481018490526bffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166024820152604401610d09565b67ffffffffffffffff881660009081526009602052604081206001015463ffffffff1690611a6c878784613585565b9050806020015193508484611af3836040805182516024820152602092830151151560448083019190915282518083039091018152606490910190915290810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f181dcf100000000000000000000000000000000000000000000000000000000017905290565b9450945094505050955095509592505050565b6060610eee600b612339565b604080518082019091526000808252602082015273ffffffffffffffffffffffffffffffffffffffff8281166000908152600760209081526040918290208251808401909352549283168083527401000000000000000000000000000000000000000090930460ff169082015290611c0557505073ffffffffffffffffffffffffffffffffffffffff166000908152600660209081526040918290208251808401909352547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811683527c0100000000000000000000000000000000000000000000000000000000900463ffffffff169082015290565b610b698161372e565b67ffffffffffffffff8083166000908152600960209081526040808320815161020081018352815460ff808216151580845261ffff61010080850482169886019890985263ffffffff630100000085048116978601979097526701000000000000008404871660608601526b0100000000000000000000008404871660808601526f010000000000000000000000000000008404811660a086015271010000000000000000000000000000000000808504881660c087015275010000000000000000000000000000000000000000008504821660e08088019190915277010000000000000000000000000000000000000000000000860483169987019990995279010000000000000000000000000000000000000000000000000085049091166101208601527b01000000000000000000000000000000000000000000000000000000909304861661014085015260019094015480861661016085015264010000000081049098166101808401526c0100000000000000000000000088049094166101a0830152700100000000000000000000000000000000870490931615156101c08201527fffffffff000000000000000000000000000000000000000000000000000000009290950490921b166101e0840152909190611e28576040517f99ac52f200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff85166004820152602401610d09565b6000611e376040850185615689565b9150611e93905082611e4c6020870187615624565b905083611e598880615624565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506138bd92505050565b6000600881611ea8608088016060890161428c565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160009081205467ffffffffffffffff16915080611ef7611ef16080890160608a0161428c565b896120bd565b9092509050600080808615611f3d57611f31888c611f1b60808e0160608f0161428c565b888e8060400190611f2c9190615689565b613967565b91945092509050611f5d565b6101a0880151611f5a9063ffffffff16662386f26fc10000615565565b92505b61010088015160009061ffff1615611fa157611f9e896dffffffffffffffffffffffffffff607088901c16611f9560208f018f615624565b90508b86613c3f565b90505b61018089015160009067ffffffffffffffff16611fca611fc460808f018f615624565b8d613cef565b600001518563ffffffff168c60a0015161ffff168f8060200190611fee9190615624565b611ff9929150615565565b8d6080015163ffffffff1661200e9190615844565b6120189190615844565b6120229190615844565b61203c906dffffffffffffffffffffffffffff8916615565565b6120469190615565565b90507bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8716828261207d67ffffffffffffffff8c1689615565565b6120879190615844565b6120919190615844565b61209b919061557c565b9d9c50505050505050505050505050565b6120b461238b565b6111b981613db0565b67ffffffffffffffff811660009081526005602090815260408083208151808301909252547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811682527c0100000000000000000000000000000000000000000000000000000000900463ffffffff1691810182905282918203612175576040517f2e59db3a00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff85166004820152602401610d09565b6000816020015163ffffffff164261218d9190615857565b90507f000000000000000000000000000000000000000000000000000000000000000063ffffffff1681111561222e576040517ff08bcb3e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8616600482015263ffffffff7f000000000000000000000000000000000000000000000000000000000000000016602482015260448101829052606401610d09565b61223786612248565b9151919350909150505b9250929050565b60008061225483611b12565b9050806020015163ffffffff166000148061228c575080517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16155b156122db576040517f06439c6b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152602401610d09565b5192915050565b7fd7ed2ad4000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316016111fa5761233481613ea5565b505050565b60606000610b6983613f58565b612351600233613fb4565b612389576040517fd86ad9cf000000000000000000000000000000000000000000000000000000008152336004820152602401610d09565b565b60005473ffffffffffffffffffffffffffffffffffffffff163314612389576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610d09565b60005b81518110156111fa57600082828151811061242c5761242c6155b7565b60209081029190910181015180518183015173ffffffffffffffffffffffffffffffffffffffff80831660008181526007875260409081902084518154868a018051929096167fffffffffffffffffffffff00000000000000000000000000000000000000000090911681177401000000000000000000000000000000000000000060ff9384160217909255825191825293519093169683019690965293955091939092917f08a5f7f5bb38a81d8e43aca13ecd76431dbf8816ae4699affff7b00b2fc1c464910160405180910390a250505080600101905061240f565b60006125c382600001518360600151846020015185604001516040805173ffffffffffffffffffffffffffffffffffffffff80871660208301528516918101919091527fffffffffffffffffffff00000000000000000000000000000000000000000000831660608201527fffff0000000000000000000000000000000000000000000000000000000000008216608082015260009060a001604051602081830303815290604052805190602001209050949350505050565b60808301516000828152600460205260409081902080549215157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00909316929092179091555190915081907f32a4ba3fa3351b11ad555d4c8ec70a744e8705607077a946807030d64b6ab1a3906126d0908590600060a08201905073ffffffffffffffffffffffffffffffffffffffff8084511683527fffffffffffffffffffff0000000000000000000000000000000000000000000060208501511660208401527fffff00000000000000000000000000000000000000000000000000000000000060408501511660408401528060608501511660608401525060808301511515608083015292915050565b60405180910390a25050565b60005b8251811015612a055760008382815181106126fc576126fc6155b7565b6020026020010151905060008160000151905060005b8260200151518110156129f757600083602001518281518110612737576127376155b7565b602002602001015160200151905060008460200151838151811061275d5761275d6155b7565b6020026020010151600001519050602063ffffffff16826080015163ffffffff1610156127e05760808201516040517f24ecdc0200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8316600482015263ffffffff9091166024820152604401610d09565b67ffffffffffffffff84166000818152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff86168085529083529281902086518154938801518389015160608a015160808b015160a08c015115157201000000000000000000000000000000000000027fffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffff63ffffffff9283166e01000000000000000000000000000002167fffffffffffffffffffffffffff0000000000ffffffffffffffffffffffffffff9383166a0100000000000000000000027fffffffffffffffffffffffffffffffffffff00000000ffffffffffffffffffff61ffff9096166801000000000000000002959095167fffffffffffffffffffffffffffffffffffff000000000000ffffffffffffffff968416640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000909b16939097169290921798909817939093169390931717919091161792909217909155519091907f94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b5906129e5908690600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60405180910390a35050600101612712565b5050508060010190506126df565b5060005b8151811015612334576000828281518110612a2657612a266155b7565b60200260200101516000015190506000838381518110612a4857612a486155b7565b60209081029190910181015181015167ffffffffffffffff84166000818152600a8452604080822073ffffffffffffffffffffffffffffffffffffffff8516808452955280822080547fffffffffffffffffffffffffff000000000000000000000000000000000000001690555192945090917f4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b9190a35050600101612a09565b60005b8251811015612b8c57612b22838281518110612b0a57612b0a6155b7565b6020026020010151600b613fe390919063ffffffff16565b15612b8457828181518110612b3957612b396155b7565b602002602001015173ffffffffffffffffffffffffffffffffffffffff167fdf1b1bd32a69711488d71554706bb130b1fc63a5fa1a2cd85e8440f84065ba2360405160405180910390a25b600101612aec565b5060005b815181101561233457612bc6828281518110612bae57612bae6155b7565b6020026020010151600b61400590919063ffffffff16565b15612c2857818181518110612bdd57612bdd6155b7565b602002602001015173ffffffffffffffffffffffffffffffffffffffff167f1795838dc8ab2ffc5f431a1729a6afa0b587f982f7b2be0b9d7187a1ef547f9160405160405180910390a25b600101612b90565b6040810151604a820151605e90920151909260609290921c91565b6040805173ffffffffffffffffffffffffffffffffffffffff868116602080840191909152908616828401527fffffffffffffffffffff00000000000000000000000000000000000000000000851660608301527fffff00000000000000000000000000000000000000000000000000000000000084166080808401919091528351808403909101815260a09092018352815191810191909120600081815260049092529190205460ff16612d9c576040517f097e17ff00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8087166004830152851660248201527fffffffffffffffffffff00000000000000000000000000000000000000000000841660448201527fffff00000000000000000000000000000000000000000000000000000000000083166064820152608401610d09565b5050505050565b600080612db0848661586a565b9050600060248260ff161115612de757612dcb602483615883565b612dd690600a6159bc565b612de0908561557c565b9050612e0a565b612df2826024615883565b612dfd90600a6159bc565b612e079085615565565b90505b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811115612e60576040517f10cb51d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b95945050505050565b602081015160005b8151811015612f04576000828281518110612e8e57612e8e6155b7565b60200260200101519050612eac81600261402790919063ffffffff16565b15612efb5760405173ffffffffffffffffffffffffffffffffffffffff821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b50600101612e71565b50815160005b81518110156111a2576000828281518110612f2757612f276155b7565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603612f97576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612fa2600282613fe3565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a150600101612f0a565b60005b81518110156111fa576000828281518110613015576130156155b7565b602002602001015190506000838381518110613033576130336155b7565b60200260200101516000015190506000826020015190508167ffffffffffffffff166000148061306c575061016081015163ffffffff16155b806130be57506101e08101517fffffffff00000000000000000000000000000000000000000000000000000000167f2812d52c0000000000000000000000000000000000000000000000000000000014155b806130dd5750806060015163ffffffff1681610160015163ffffffff16115b15613120576040517fc35aa79d00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff83166004820152602401610d09565b67ffffffffffffffff821660009081526009602052604081206001015471010000000000000000000000000000000000900460e01b7fffffffff000000000000000000000000000000000000000000000000000000001690036131c4578167ffffffffffffffff167fd31c671936387b2f84ed402b553bd50c0e9c20408ea4e91a836d77b8180fb724826040516131b79190614a27565b60405180910390a2613207565b8167ffffffffffffffff167f1edd6f3553cfa16f10b95b195abae3a1cfca4783de4843f95d674b1e1df5ab20826040516131fe9190614a27565b60405180910390a25b80600960008467ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548161ffff021916908361ffff16021790555060408201518160000160036101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160076101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600b6101000a81548163ffffffff021916908363ffffffff16021790555060a082015181600001600f6101000a81548161ffff021916908361ffff16021790555060c08201518160000160116101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160000160156101000a81548161ffff021916908361ffff1602179055506101008201518160000160176101000a81548161ffff021916908361ffff1602179055506101208201518160000160196101000a81548161ffff021916908361ffff16021790555061014082015181600001601b6101000a81548163ffffffff021916908363ffffffff1602179055506101608201518160010160006101000a81548163ffffffff021916908363ffffffff1602179055506101808201518160010160046101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506101a082015181600101600c6101000a81548163ffffffff021916908363ffffffff1602179055506101c08201518160010160106101000a81548160ff0219169083151502179055506101e08201518160010160116101000a81548163ffffffff021916908360e01c0217905550905050505050806001019050612ff8565b60005b81518110156111fa5760008282815181106134bb576134bb6155b7565b602002602001015160000151905060008383815181106134dd576134dd6155b7565b60209081029190910181015181015173ffffffffffffffffffffffffffffffffffffffff841660008181526008845260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff85169081179091559051908152919350917fbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d910160405180910390a2505060010161349e565b604080518082019091526000808252602082015260008390036135c657506040805180820190915267ffffffffffffffff8216815260006020820152610b69565b60006135d284866159cb565b905060006135e38560048189615a11565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505050507fffffffff0000000000000000000000000000000000000000000000000000000082167fe7e230f0000000000000000000000000000000000000000000000000000000000161368057808060200190518101906136779190615a3b565b92505050610b69565b7f6859a837000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316016136fc576040518060400160405280828060200190518101906136e89190615a67565b815260006020909101529250610b69915050565b6040517f5247fdce00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080518082019091526000808252602082015260008260000151905060008173ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015613798573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137bc9190615a9a565b50505091505060008112156137fd576040517f10cb51d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061387c8373ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561384d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138719190615aea565b866020015184612da3565b604080518082019091527bffffffffffffffffffffffffffffffffffffffffffffffffffffffff909116815263ffffffff4216602082015295945050505050565b836040015163ffffffff168311156139165760408085015190517f8693378900000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015260248101849052604401610d09565b836020015161ffff16821115613958576040517f4c056b6a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6111a2846101e00151826122e2565b6000808083815b81811015613c3157600087878381811061398a5761398a6155b7565b9050604002018036038101906139a09190615b07565b67ffffffffffffffff8c166000908152600a60209081526040808320845173ffffffffffffffffffffffffffffffffffffffff168452825291829020825160c081018452905463ffffffff8082168352640100000000820481169383019390935268010000000000000000810461ffff16938201939093526a01000000000000000000008304821660608201526e01000000000000000000000000000083049091166080820152720100000000000000000000000000000000000090910460ff16151560a0820181905291925090613ac0576101208d0151613a8d9061ffff16662386f26fc10000615565565b613a979088615844565b96508c610140015186613aaa9190615b40565b9550613ab7602086615b40565b94505050613c29565b604081015160009061ffff1615613b795760008c73ffffffffffffffffffffffffffffffffffffffff16846000015173ffffffffffffffffffffffffffffffffffffffff1614613b1c578351613b1590612248565b9050613b1f565b508a5b620186a0836040015161ffff16613b618660200151847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1661404990919063ffffffff16565b613b6b9190615565565b613b75919061557c565b9150505b6060820151613b889088615b40565b9650816080015186613b9a9190615b40565b8251909650600090613bb99063ffffffff16662386f26fc10000615565565b905080821015613bd857613bcd818a615844565b985050505050613c29565b6000836020015163ffffffff16662386f26fc10000613bf79190615565565b905080831115613c1757613c0b818b615844565b99505050505050613c29565b613c21838b615844565b995050505050505b60010161396e565b505096509650969350505050565b60008063ffffffff8316613c5561016086615565565b613c61876101c0615844565b613c6b9190615844565b613c759190615844565b905060008760c0015163ffffffff168860e0015161ffff1683613c989190615565565b613ca29190615844565b61010089015190915061ffff16613cc96dffffffffffffffffffffffffffff891683615565565b613cd39190615565565b613ce390655af3107a4000615565565b98975050505050505050565b60408051808201909152600080825260208201526000613d1b858585610160015163ffffffff16613585565b9050826060015163ffffffff1681600001511115613d65576040517f4c4fc93a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b826101c001518015613d7957508060200151155b15610b66576040517fee433e9900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff821603613e2f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610d09565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60008151602014613ee457816040517f8d666f60000000000000000000000000000000000000000000000000000000008152600401610d099190614498565b600082806020019051810190613efa9190615a67565b905073ffffffffffffffffffffffffffffffffffffffff811180613f1f575061040081105b156112c357826040517f8d666f60000000000000000000000000000000000000000000000000000000008152600401610d099190614498565b606081600001805480602002602001604051908101604052809291908181526020018280548015613fa857602002820191906000526020600020905b815481526020019060010190808311613f94575b50505050509050919050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515610b69565b6000610b698373ffffffffffffffffffffffffffffffffffffffff8416614086565b6000610b698373ffffffffffffffffffffffffffffffffffffffff84166140d5565b6000610b698373ffffffffffffffffffffffffffffffffffffffff84166141cf565b6000670de0b6b3a764000061407c837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8616615565565b610b69919061557c565b60008181526001830160205260408120546140cd575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556112c3565b5060006112c3565b600081815260018301602052604081205480156141be5760006140f9600183615857565b855490915060009061410d90600190615857565b905080821461417257600086600001828154811061412d5761412d6155b7565b9060005260206000200154905080876000018481548110614150576141506155b7565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061418357614183615b5d565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506112c3565b60009150506112c3565b5092915050565b600081815260018301602052604081205480156141be5760006141f3600183615857565b855490915060009061420790600190615857565b905081811461417257600086600001828154811061412d5761412d6155b7565b803573ffffffffffffffffffffffffffffffffffffffff8116811461424b57600080fd5b919050565b60008060006060848603121561426557600080fd5b61426e84614227565b92506020840135915061428360408501614227565b90509250925092565b60006020828403121561429e57600080fd5b610b6982614227565b803567ffffffffffffffff8116811461424b57600080fd5b60008083601f8401126142d157600080fd5b50813567ffffffffffffffff8111156142e957600080fd5b6020830191508360208260051b850101111561224157600080fd5b60008060008060006060868803121561431c57600080fd5b614325866142a7565b9450602086013567ffffffffffffffff8082111561434257600080fd5b61434e89838a016142bf565b9096509450604088013591508082111561436757600080fd5b818801915088601f83011261437b57600080fd5b81358181111561438a57600080fd5b8960208260061b850101111561439f57600080fd5b9699959850939650602001949392505050565b6000815180845260005b818110156143d8576020818501810151868301820152016143bc565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b8281101561448b577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526144798583516143b2565b9450928501929085019060010161443f565b5092979650505050505050565b602081526000610b6960208301846143b2565b6020808252825182820181905260009190848201906040850190845b818110156144f957835173ffffffffffffffffffffffffffffffffffffffff16835292840192918401916001016144c7565b50909695505050505050565b60006020828403121561451757600080fd5b813567ffffffffffffffff81111561452e57600080fd5b820160408185031215610b6957600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561459257614592614540565b60405290565b60405160a0810167ffffffffffffffff8111828210171561459257614592614540565b60405160c0810167ffffffffffffffff8111828210171561459257614592614540565b604051610200810167ffffffffffffffff8111828210171561459257614592614540565b6040516060810167ffffffffffffffff8111828210171561459257614592614540565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561466c5761466c614540565b604052919050565b600067ffffffffffffffff82111561468e5761468e614540565b5060051b60200190565b60ff811681146111b957600080fd5b600060208083850312156146ba57600080fd5b823567ffffffffffffffff8111156146d157600080fd5b8301601f810185136146e257600080fd5b80356146f56146f082614674565b614625565b8181526060918202830184019184820191908884111561471457600080fd5b938501935b838510156147b457848903818112156147325760008081fd5b61473a61456f565b61474387614227565b81526040807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0840112156147775760008081fd5b61477f61456f565b925061478c898901614227565b835287013561479a81614698565b828901528088019190915283529384019391850191614719565b50979650505050505050565b80151581146111b957600080fd5b803561424b816147c0565b600060208083850312156147ec57600080fd5b823567ffffffffffffffff81111561480357600080fd5b8301601f8101851361481457600080fd5b80356148226146f082614674565b81815260a0918202830184019184820191908884111561484157600080fd5b938501935b838510156147b45780858a03121561485e5760008081fd5b614866614598565b61486f86614227565b8152868601357fffffffffffffffffffff00000000000000000000000000000000000000000000811681146148a45760008081fd5b818801526040868101357fffff000000000000000000000000000000000000000000000000000000000000811681146148dd5760008081fd5b9082015260606148ee878201614227565b90820152608086810135614901816147c0565b9082015283529384019391850191614846565b6000806020838503121561492757600080fd5b823567ffffffffffffffff81111561493e57600080fd5b61494a858286016142bf565b90969095509350505050565b602080825282518282018190526000919060409081850190868401855b828110156149c4576149b484835180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16825260209081015163ffffffff16910152565b9284019290850190600101614973565b5091979650505050505050565b6000602082840312156149e357600080fd5b610b69826142a7565b81517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16815260208083015163ffffffff1690820152604081016112c3565b81511515815261020081016020830151614a47602084018261ffff169052565b506040830151614a5f604084018263ffffffff169052565b506060830151614a77606084018263ffffffff169052565b506080830151614a8f608084018263ffffffff169052565b5060a0830151614aa560a084018261ffff169052565b5060c0830151614abd60c084018263ffffffff169052565b5060e0830151614ad360e084018261ffff169052565b506101008381015161ffff9081169184019190915261012080850151909116908301526101408084015163ffffffff90811691840191909152610160808501518216908401526101808085015167ffffffffffffffff16908401526101a080850151909116908301526101c0808401511515908301526101e0808401517fffffffff000000000000000000000000000000000000000000000000000000008116828501525b505092915050565b803563ffffffff8116811461424b57600080fd5b803561ffff8116811461424b57600080fd5b600082601f830112614bb757600080fd5b81356020614bc76146f083614674565b82815260069290921b84018101918181019086841115614be657600080fd5b8286015b84811015614c335760408189031215614c035760008081fd5b614c0b61456f565b614c14826142a7565b8152614c21858301614227565b81860152835291830191604001614bea565b509695505050505050565b60008060408385031215614c5157600080fd5b67ffffffffffffffff83351115614c6757600080fd5b83601f843585010112614c7957600080fd5b614c896146f08435850135614674565b8335840180358083526020808401939260059290921b90910101861015614caf57600080fd5b602085358601015b85358601803560051b01602001811015614ebc5767ffffffffffffffff81351115614ce157600080fd5b8035863587010160407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0828a03011215614d1a57600080fd5b614d2261456f565b614d2e602083016142a7565b815267ffffffffffffffff60408301351115614d4957600080fd5b88603f604084013584010112614d5e57600080fd5b614d746146f06020604085013585010135614674565b6020604084810135850182810135808552928401939260e00201018b1015614d9b57600080fd5b6040808501358501015b6040858101358601602081013560e0020101811015614e9d5760e0818d031215614dce57600080fd5b614dd661456f565b614ddf82614227565b815260c07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0838f03011215614e1357600080fd5b614e1b6145bb565b614e2760208401614b80565b8152614e3560408401614b80565b6020820152614e4660608401614b94565b6040820152614e5760808401614b80565b6060820152614e6860a08401614b80565b6080820152614e7a60c08401356147c0565b60c083013560a0820152602082810191909152908452929092019160e001614da5565b5080602084015250508085525050602083019250602081019050614cb7565b5092505067ffffffffffffffff60208401351115614ed957600080fd5b614ee98460208501358501614ba6565b90509250929050565b600082601f830112614f0357600080fd5b81356020614f136146f083614674565b8083825260208201915060208460051b870101935086841115614f3557600080fd5b602086015b84811015614c3357614f4b81614227565b8352918301918301614f3a565b60008060408385031215614f6b57600080fd5b823567ffffffffffffffff80821115614f8357600080fd5b614f8f86838701614ef2565b93506020850135915080821115614fa557600080fd5b50614fb285828601614ef2565b9150509250929050565b60008083601f840112614fce57600080fd5b50813567ffffffffffffffff811115614fe657600080fd5b60208301915083602082850101111561224157600080fd5b6000806000806040858703121561501457600080fd5b843567ffffffffffffffff8082111561502c57600080fd5b61503888838901614fbc565b9096509450602087013591508082111561505157600080fd5b5061505e87828801614fbc565b95989497509550505050565b6000806040838503121561507d57600080fd5b615086836142a7565b9150614ee960208401614227565b6000602082840312156150a657600080fd5b813567ffffffffffffffff808211156150be57600080fd5b90830190604082860312156150d257600080fd5b6150da61456f565b8235828111156150e957600080fd5b6150f587828601614ef2565b82525060208301358281111561510a57600080fd5b61511687828601614ef2565b60208301525095945050505050565b80357fffffffff000000000000000000000000000000000000000000000000000000008116811461424b57600080fd5b6000602080838503121561516857600080fd5b823567ffffffffffffffff81111561517f57600080fd5b8301601f8101851361519057600080fd5b803561519e6146f082614674565b81815261022091820283018401918482019190888411156151be57600080fd5b938501935b838510156147b457848903818112156151dc5760008081fd5b6151e461456f565b6151ed876142a7565b8152610200807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0840112156152225760008081fd5b61522a6145de565b92506152378989016147ce565b83526040615246818a01614b94565b8a8501526060615257818b01614b80565b828601526080915061526a828b01614b80565b9085015260a061527b8a8201614b80565b8286015260c0915061528e828b01614b94565b9085015260e061529f8a8201614b80565b8286015261010091506152b3828b01614b94565b908501526101206152c58a8201614b94565b8286015261014091506152d9828b01614b94565b908501526101606152eb8a8201614b80565b8286015261018091506152ff828b01614b80565b908501526101a06153118a82016142a7565b828601526101c09150615325828b01614b80565b908501526101e06153378a82016147ce565b82860152615346838b01615125565b90850152505080880191909152835293840193918501916151c3565b6000602080838503121561537557600080fd5b823567ffffffffffffffff81111561538c57600080fd5b8301601f8101851361539d57600080fd5b80356153ab6146f082614674565b81815260069190911b820183019083810190878311156153ca57600080fd5b928401925b8284101561541c57604084890312156153e85760008081fd5b6153f061456f565b6153f985614227565b81526154068686016142a7565b81870152825260409390930192908401906153cf565b979650505050505050565b60008060008060006080868803121561543f57600080fd5b615448866142a7565b945061545660208701614227565b935060408601359250606086013567ffffffffffffffff81111561547957600080fd5b61548588828901614fbc565b969995985093965092949392505050565b8381528215156020820152606060408201526000612e6060608301846143b2565b600080604083850312156154ca57600080fd5b6154d3836142a7565b9150602083013567ffffffffffffffff8111156154ef57600080fd5b830160a0818603121561550157600080fd5b809150509250929050565b6000806040838503121561551f57600080fd5b61552883614227565b9150614ee9602084016142a7565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80820281158282048414176112c3576112c3615536565b6000826155b2577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6183360301811261561a57600080fd5b9190910192915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261565957600080fd5b83018035915067ffffffffffffffff82111561567457600080fd5b60200191503681900382131561224157600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126156be57600080fd5b83018035915067ffffffffffffffff8211156156d957600080fd5b6020019150600681901b360382131561224157600080fd5b80357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116811461424b57600080fd5b60006040828403121561572f57600080fd5b61573761456f565b61574083614227565b815261574e602084016156f1565b60208201529392505050565b60006040828403121561576c57600080fd5b61577461456f565b615740836142a7565b6000602080838503121561579057600080fd5b823567ffffffffffffffff8111156157a757600080fd5b8301601f810185136157b857600080fd5b80356157c66146f082614674565b818152606091820283018401918482019190888411156157e557600080fd5b938501935b838510156147b45780858a0312156158025760008081fd5b61580a614602565b61581386614227565b81526158208787016156f1565b878201526040615831818801614b80565b90820152835293840193918501916157ea565b808201808211156112c3576112c3615536565b818103818111156112c3576112c3615536565b60ff81811683821601908111156112c3576112c3615536565b60ff82811682821603908111156112c3576112c3615536565b600181815b808511156158f557817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156158db576158db615536565b808516156158e857918102915b93841c93908002906158a1565b509250929050565b60008261590c575060016112c3565b81615919575060006112c3565b816001811461592f576002811461593957615955565b60019150506112c3565b60ff84111561594a5761594a615536565b50506001821b6112c3565b5060208310610133831016604e8410600b8410161715615978575081810a6112c3565b615982838361589c565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156159b4576159b4615536565b029392505050565b6000610b6960ff8416836158fd565b7fffffffff000000000000000000000000000000000000000000000000000000008135818116916004851015614b785760049490940360031b84901b1690921692915050565b60008085851115615a2157600080fd5b83861115615a2e57600080fd5b5050820193919092039150565b600060408284031215615a4d57600080fd5b615a5561456f565b82518152602083015161574e816147c0565b600060208284031215615a7957600080fd5b5051919050565b805169ffffffffffffffffffff8116811461424b57600080fd5b600080600080600060a08688031215615ab257600080fd5b615abb86615a80565b9450602086015193506040860151925060608601519150615ade60808701615a80565b90509295509295909350565b600060208284031215615afc57600080fd5b8151610b6981614698565b600060408284031215615b1957600080fd5b615b2161456f565b615b2a83614227565b8152602083013560208201528091505092915050565b63ffffffff8181168382160190808211156141c8576141c8615536565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea164736f6c6343000818000a", +var FeeQuoterMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint96\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"linkToken\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"stalenessThreshold\",\"type\":\"uint32\"}],\"internalType\":\"structFeeQuoter.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"priceUpdaters\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"feeTokens\",\"type\":\"address[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"}],\"internalType\":\"structIFeeQuoter.TokenPriceFeedConfig\",\"name\":\"feedConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.TokenPriceFeedUpdate[]\",\"name\":\"tokenPriceFeeds\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigSingleTokenArgs[]\",\"name\":\"tokenTransferFeeConfigs\",\"type\":\"tuple[]\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigArgs[]\",\"name\":\"tokenTransferFeeConfigArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"internalType\":\"structFeeQuoter.PremiumMultiplierWeiPerEthArgs[]\",\"name\":\"premiumMultiplierWeiPerEthArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chain\",\"type\":\"uint64\"}],\"name\":\"ChainNotSupported\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DataFeedValueOutOfUint224Range\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"DestinationChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ExtraArgOutOfOrderExecutionMustBeTrue\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"}],\"name\":\"InvalidDestBytesOverhead\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidDestChainConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidEVMAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidExtraArgsTag\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidStaticConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"msgFeeJuels\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint256\"}],\"name\":\"MessageFeeTooHigh\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MessageGasLimitTooHigh\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"maxSize\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualSize\",\"type\":\"uint256\"}],\"name\":\"MessageTooLarge\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"internalType\":\"bytes10\",\"name\":\"workflowName\",\"type\":\"bytes10\"},{\"internalType\":\"bytes2\",\"name\":\"reportName\",\"type\":\"bytes2\"}],\"name\":\"ReportForwarderUnauthorized\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"SourceTokenDataTooLarge\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"threshold\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timePassed\",\"type\":\"uint256\"}],\"name\":\"StaleGasPrice\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feedTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"storedTimeStamp\",\"type\":\"uint256\"}],\"name\":\"StaleKeystoneUpdate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"TokenNotSupported\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"UnauthorizedCaller\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnsupportedNumberOfTokens\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"AuthorizedCallerAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"AuthorizedCallerRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"indexed\":false,\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"name\":\"DestChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"indexed\":false,\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"name\":\"DestChainConfigUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"}],\"name\":\"FeeTokenAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"}],\"name\":\"FeeTokenRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"name\":\"PremiumMultiplierWeiPerEthUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"}],\"indexed\":false,\"internalType\":\"structIFeeQuoter.TokenPriceFeedConfig\",\"name\":\"priceFeedConfig\",\"type\":\"tuple\"}],\"name\":\"PriceFeedPerTokenUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"reportId\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"},{\"internalType\":\"bytes10\",\"name\":\"workflowName\",\"type\":\"bytes10\"},{\"internalType\":\"bytes2\",\"name\":\"reportName\",\"type\":\"bytes2\"},{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isAllowed\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"structKeystoneFeedsPermissionHandler.Permission\",\"name\":\"permission\",\"type\":\"tuple\"}],\"name\":\"ReportPermissionSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"TokenTransferFeeConfigDeleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"name\":\"TokenTransferFeeConfigUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"UsdPerTokenUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChain\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"UsdPerUnitGasUpdated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address[]\",\"name\":\"addedCallers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"removedCallers\",\"type\":\"address[]\"}],\"internalType\":\"structAuthorizedCallers.AuthorizedCallerArgs\",\"name\":\"authorizedCallerArgs\",\"type\":\"tuple\"}],\"name\":\"applyAuthorizedCallerUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyDestChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"feeTokensToAdd\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"feeTokensToRemove\",\"type\":\"address[]\"}],\"name\":\"applyFeeTokensUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"internalType\":\"structFeeQuoter.PremiumMultiplierWeiPerEthArgs[]\",\"name\":\"premiumMultiplierWeiPerEthArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyPremiumMultiplierWeiPerEthUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigSingleTokenArgs[]\",\"name\":\"tokenTransferFeeConfigs\",\"type\":\"tuple[]\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigArgs[]\",\"name\":\"tokenTransferFeeConfigArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigRemoveArgs[]\",\"name\":\"tokensToUseDefaultFeeConfigs\",\"type\":\"tuple[]\"}],\"name\":\"applyTokenTransferFeeConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"fromToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fromTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"toToken\",\"type\":\"address\"}],\"name\":\"convertTokenAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllAuthorizedCallers\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getDestChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getDestinationChainGasPrice\",\"outputs\":[{\"components\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"internalType\":\"structInternal.TimestampedPackedUint224\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getFeeTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getPremiumMultiplierWeiPerEth\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint96\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"linkToken\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"stalenessThreshold\",\"type\":\"uint32\"}],\"internalType\":\"structFeeQuoter.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getTokenAndGasPrices\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"tokenPrice\",\"type\":\"uint224\"},{\"internalType\":\"uint224\",\"name\":\"gasPriceValue\",\"type\":\"uint224\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenPrice\",\"outputs\":[{\"components\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"internalType\":\"structInternal.TimestampedPackedUint224\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenPriceFeedConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"}],\"internalType\":\"structIFeeQuoter.TokenPriceFeedConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"tokens\",\"type\":\"address[]\"}],\"name\":\"getTokenPrices\",\"outputs\":[{\"components\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"internalType\":\"structInternal.TimestampedPackedUint224[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenTransferFeeConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"getValidatedFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getValidatedTokenPrice\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"\",\"type\":\"uint224\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"onReport\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"name\":\"processMessageArgs\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"msgFeeJuels\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isOutOfOrderExecution\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"convertedExtraArgs\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"rampTokenAmounts\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"sourceTokenAmounts\",\"type\":\"tuple[]\"}],\"name\":\"processPoolReturnData\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"destExecDataPerToken\",\"type\":\"bytes[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"},{\"internalType\":\"bytes10\",\"name\":\"workflowName\",\"type\":\"bytes10\"},{\"internalType\":\"bytes2\",\"name\":\"reportName\",\"type\":\"bytes2\"},{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isAllowed\",\"type\":\"bool\"}],\"internalType\":\"structKeystoneFeedsPermissionHandler.Permission[]\",\"name\":\"permissions\",\"type\":\"tuple[]\"}],\"name\":\"setReportPermissions\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"}],\"name\":\"updatePrices\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"}],\"internalType\":\"structIFeeQuoter.TokenPriceFeedConfig\",\"name\":\"feedConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.TokenPriceFeedUpdate[]\",\"name\":\"tokenPriceFeedUpdates\",\"type\":\"tuple[]\"}],\"name\":\"updateTokenPriceFeeds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x60e06040523480156200001157600080fd5b50604051620076d8380380620076d8833981016040819052620000349162001834565b8533806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf8162000207565b5050604080518082018252838152815160008152602080820190935291810191909152620000ee9150620002b2565b5060208701516001600160a01b0316158062000112575086516001600160601b0316155b80620001265750604087015163ffffffff16155b15620001455760405163d794ef9560e01b815260040160405180910390fd5b6020878101516001600160a01b031660a05287516001600160601b031660805260408089015163ffffffff1660c05280516000815291820190526200018c90869062000401565b620001978462000549565b620001a2816200061a565b620001ad8262000a5a565b60408051600080825260208201909252620001fa91859190620001f3565b6040805180820190915260008082526020820152815260200190600190039081620001cb5790505b5062000b26565b5050505050505062001ae5565b336001600160a01b03821603620002615760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b602081015160005b815181101562000342576000828281518110620002db57620002db62001953565b60209081029190910101519050620002f560028262000e5f565b1562000338576040516001600160a01b03821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b50600101620002ba565b50815160005b8151811015620003fb57600082828151811062000369576200036962001953565b6020026020010151905060006001600160a01b0316816001600160a01b031603620003a7576040516342bcdf7f60e11b815260040160405180910390fd5b620003b460028262000e7f565b506040516001600160a01b03821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a15060010162000348565b50505050565b60005b8251811015620004a2576200044083828151811062000427576200042762001953565b6020026020010151600b62000e7f60201b90919060201c565b1562000499578281815181106200045b576200045b62001953565b60200260200101516001600160a01b03167fdf1b1bd32a69711488d71554706bb130b1fc63a5fa1a2cd85e8440f84065ba2360405160405180910390a25b60010162000404565b5060005b81518110156200054457620004e2828281518110620004c957620004c962001953565b6020026020010151600b62000e9660201b90919060201c565b156200053b57818181518110620004fd57620004fd62001953565b60200260200101516001600160a01b03167f1795838dc8ab2ffc5f431a1729a6afa0b587f982f7b2be0b9d7187a1ef547f9160405160405180910390a25b600101620004a6565b505050565b60005b8151811015620006165760008282815181106200056d576200056d62001953565b6020908102919091018101518051818301516001600160a01b0380831660008181526007875260409081902084518154868a018051929096166001600160a81b03199091168117600160a01b60ff9384160217909255825191825293519093169683019690965293955091939092917f08a5f7f5bb38a81d8e43aca13ecd76431dbf8816ae4699affff7b00b2fc1c464910160405180910390a25050508060010190506200054c565b5050565b60005b8151811015620006165760008282815181106200063e576200063e62001953565b6020026020010151905060008383815181106200065f576200065f62001953565b6020026020010151600001519050600082602001519050816001600160401b03166000148062000698575061016081015163ffffffff16155b80620006ba57506101e08101516001600160e01b031916630a04b54b60e21b14155b80620006da5750806060015163ffffffff1681610160015163ffffffff16115b15620007055760405163c35aa79d60e01b81526001600160401b038316600482015260240162000083565b6001600160401b038216600090815260096020526040812060010154600160881b900460e01b6001600160e01b03191690036200078557816001600160401b03167fd31c671936387b2f84ed402b553bd50c0e9c20408ea4e91a836d77b8180fb7248260405162000777919062001969565b60405180910390a2620007c9565b816001600160401b03167f1edd6f3553cfa16f10b95b195abae3a1cfca4783de4843f95d674b1e1df5ab2082604051620007c0919062001969565b60405180910390a25b8060096000846001600160401b03166001600160401b0316815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548161ffff021916908361ffff16021790555060408201518160000160036101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160076101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600b6101000a81548163ffffffff021916908363ffffffff16021790555060a082015181600001600f6101000a81548161ffff021916908361ffff16021790555060c08201518160000160116101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160000160156101000a81548161ffff021916908361ffff1602179055506101008201518160000160176101000a81548161ffff021916908361ffff1602179055506101208201518160000160196101000a81548161ffff021916908361ffff16021790555061014082015181600001601b6101000a81548163ffffffff021916908363ffffffff1602179055506101608201518160010160006101000a81548163ffffffff021916908363ffffffff1602179055506101808201518160010160046101000a8154816001600160401b0302191690836001600160401b031602179055506101a082015181600101600c6101000a81548163ffffffff021916908363ffffffff1602179055506101c08201518160010160106101000a81548160ff0219169083151502179055506101e08201518160010160116101000a81548163ffffffff021916908360e01c02179055509050505050508060010190506200061d565b60005b81518110156200061657600082828151811062000a7e5762000a7e62001953565b6020026020010151600001519050600083838151811062000aa35762000aa362001953565b6020908102919091018101518101516001600160a01b03841660008181526008845260409081902080546001600160401b0319166001600160401b0385169081179091559051908152919350917fbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d910160405180910390a2505060010162000a5d565b60005b825181101562000d9957600083828151811062000b4a5762000b4a62001953565b6020026020010151905060008160000151905060005b82602001515181101562000d8a5760008360200151828151811062000b895762000b8962001953565b602002602001015160200151905060008460200151838151811062000bb25762000bb262001953565b6020026020010151600001519050602063ffffffff16826080015163ffffffff16101562000c115760808201516040516312766e0160e11b81526001600160a01b038316600482015263ffffffff909116602482015260440162000083565b6001600160401b0384166000818152600a602090815260408083206001600160a01b0386168085529083529281902086518154938801518389015160608a015160808b015160a08c01511515600160901b0260ff60901b1963ffffffff928316600160701b021664ffffffffff60701b199383166a01000000000000000000000263ffffffff60501b1961ffff90961668010000000000000000029590951665ffffffffffff60401b19968416640100000000026001600160401b0319909b16939097169290921798909817939093169390931717919091161792909217909155519091907f94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b59062000d77908690600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60405180910390a3505060010162000b60565b50505080600101905062000b29565b5060005b81518110156200054457600082828151811062000dbe5762000dbe62001953565b6020026020010151600001519050600083838151811062000de35762000de362001953565b6020908102919091018101518101516001600160401b0384166000818152600a845260408082206001600160a01b038516808452955280822080546001600160981b03191690555192945090917f4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b9190a3505060010162000d9d565b600062000e76836001600160a01b03841662000ead565b90505b92915050565b600062000e76836001600160a01b03841662000fb1565b600062000e76836001600160a01b03841662001003565b6000818152600183016020526040812054801562000fa657600062000ed460018362001aad565b855490915060009062000eea9060019062001aad565b905081811462000f5657600086600001828154811062000f0e5762000f0e62001953565b906000526020600020015490508087600001848154811062000f345762000f3462001953565b6000918252602080832090910192909255918252600188019052604090208390555b855486908062000f6a5762000f6a62001acf565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505062000e79565b600091505062000e79565b600081815260018301602052604081205462000ffa5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000e79565b50600062000e79565b6000818152600183016020526040812054801562000fa65760006200102a60018362001aad565b8554909150600090620010409060019062001aad565b905080821462000f5657600086600001828154811062000f0e5762000f0e62001953565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b03811182821017156200109f576200109f62001064565b60405290565b60405160c081016001600160401b03811182821017156200109f576200109f62001064565b60405161020081016001600160401b03811182821017156200109f576200109f62001064565b604051601f8201601f191681016001600160401b03811182821017156200111b576200111b62001064565b604052919050565b80516001600160a01b03811681146200113b57600080fd5b919050565b805163ffffffff811681146200113b57600080fd5b6000606082840312156200116857600080fd5b604051606081016001600160401b03811182821017156200118d576200118d62001064565b604052825190915081906001600160601b0381168114620011ad57600080fd5b8152620011bd6020840162001123565b6020820152620011d06040840162001140565b60408201525092915050565b60006001600160401b03821115620011f857620011f862001064565b5060051b60200190565b600082601f8301126200121457600080fd5b815160206200122d6200122783620011dc565b620010f0565b8083825260208201915060208460051b8701019350868411156200125057600080fd5b602086015b848110156200127757620012698162001123565b835291830191830162001255565b509695505050505050565b600082601f8301126200129457600080fd5b81516020620012a76200122783620011dc565b82815260609283028501820192828201919087851115620012c757600080fd5b8387015b858110156200135a5780890382811215620012e65760008081fd5b620012f06200107a565b620012fb8362001123565b8152604080601f1984011215620013125760008081fd5b6200131c6200107a565b92506200132b88850162001123565b835283015160ff81168114620013415760008081fd5b82880152808701919091528452928401928101620012cb565b5090979650505050505050565b80516001600160401b03811681146200113b57600080fd5b805161ffff811681146200113b57600080fd5b805180151581146200113b57600080fd5b600082601f830112620013b557600080fd5b81516020620013c86200122783620011dc565b82815260059290921b84018101918181019086841115620013e857600080fd5b8286015b84811015620012775780516001600160401b03808211156200140d57600080fd5b908801906040601f19838c0381018213156200142857600080fd5b620014326200107a565b6200143f89860162001367565b815282850151848111156200145357600080fd5b8086019550508c603f8601126200146957600080fd5b8885015193506200147e6200122785620011dc565b84815260e09094028501830193898101908e8611156200149d57600080fd5b958401955b858710156200157657868f0360e0811215620014bd57600080fd5b620014c76200107a565b620014d28962001123565b815260c08683011215620014e557600080fd5b620014ef620010a5565b9150620014fe8d8a0162001140565b82526200150d878a0162001140565b8d8301526200151f60608a016200137f565b878301526200153160808a0162001140565b60608301526200154460a08a0162001140565b60808301526200155760c08a0162001392565b60a0830152808d0191909152825260e09690960195908a0190620014a2565b828b015250875250505092840192508301620013ec565b600082601f8301126200159f57600080fd5b81516020620015b26200122783620011dc565b82815260069290921b84018101918181019086841115620015d257600080fd5b8286015b84811015620012775760408189031215620015f15760008081fd5b620015fb6200107a565b620016068262001123565b81526200161585830162001367565b81860152835291830191604001620015d6565b80516001600160e01b0319811681146200113b57600080fd5b600082601f8301126200165357600080fd5b81516020620016666200122783620011dc565b82815261022092830285018201928282019190878511156200168757600080fd5b8387015b858110156200135a5780890382811215620016a65760008081fd5b620016b06200107a565b620016bb8362001367565b815261020080601f1984011215620016d35760008081fd5b620016dd620010ca565b9250620016ec88850162001392565b83526040620016fd8186016200137f565b8985015260606200171081870162001140565b82860152608091506200172582870162001140565b9085015260a06200173886820162001140565b8286015260c091506200174d8287016200137f565b9085015260e06200176086820162001140565b828601526101009150620017768287016200137f565b908501526101206200178a8682016200137f565b828601526101409150620017a08287016200137f565b90850152610160620017b486820162001140565b828601526101809150620017ca82870162001140565b908501526101a0620017de86820162001367565b828601526101c09150620017f482870162001140565b908501526101e06200180886820162001392565b828601526200181983870162001628565b9085015250508087019190915284529284019281016200168b565b6000806000806000806000610120888a0312156200185157600080fd5b6200185d898962001155565b60608901519097506001600160401b03808211156200187b57600080fd5b620018898b838c0162001202565b975060808a0151915080821115620018a057600080fd5b620018ae8b838c0162001202565b965060a08a0151915080821115620018c557600080fd5b620018d38b838c0162001282565b955060c08a0151915080821115620018ea57600080fd5b620018f88b838c01620013a3565b945060e08a01519150808211156200190f57600080fd5b6200191d8b838c016200158d565b93506101008a01519150808211156200193557600080fd5b50620019448a828b0162001641565b91505092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b815115158152610200810160208301516200198a602084018261ffff169052565b506040830151620019a3604084018263ffffffff169052565b506060830151620019bc606084018263ffffffff169052565b506080830151620019d5608084018263ffffffff169052565b5060a0830151620019ec60a084018261ffff169052565b5060c083015162001a0560c084018263ffffffff169052565b5060e083015162001a1c60e084018261ffff169052565b506101008381015161ffff9081169184019190915261012080850151909116908301526101408084015163ffffffff9081169184019190915261016080850151821690840152610180808501516001600160401b0316908401526101a080850151909116908301526101c0808401511515908301526101e0928301516001600160e01b031916929091019190915290565b8181038181111562000e7957634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b60805160a05160c051615b9962001b3f600039600081816102ef0152818161219101526121fa0152600081816102b301528181611917015261197701526000818161027f015281816119a00152611a100152615b996000f3fe608060405234801561001057600080fd5b50600436106101ce5760003560e01c806379ba509711610104578063a69c64c0116100a2578063d02641a011610071578063d02641a014610a81578063d8694ccd14610a94578063f2fde38b14610aa7578063ffdb4b3714610aba57600080fd5b8063a69c64c014610997578063bf78e03f146109aa578063c4276bfc14610a57578063cdc73d5114610a7957600080fd5b806382b49eb0116100de57806382b49eb0146107d95780638da5cb5b1461094957806391a2749a146109715780639ea600261461098457600080fd5b806379ba5097146107ab5780637afac322146107b3578063805f2132146107c657600080fd5b8063407e1086116101715780634ab35b0b1161014b5780634ab35b0b14610441578063514e8cff146104815780636def4ce714610524578063770e2dc41461079857600080fd5b8063407e1086146103fb57806341ed29e71461040e57806345ac924d1461042157600080fd5b8063085318f8116101ad578063085318f814610368578063181f5a77146103885780632451a627146103d15780633937306f146103e657600080fd5b806241e5be146101d3578063061877e3146101f957806306285c6914610252575b600080fd5b6101e66101e1366004614250565b610b02565b6040519081526020015b60405180910390f35b61023961020736600461428c565b73ffffffffffffffffffffffffffffffffffffffff1660009081526008602052604090205467ffffffffffffffff1690565b60405167ffffffffffffffff90911681526020016101f0565b61031c604080516060810182526000808252602082018190529181019190915260405180606001604052807f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000063ffffffff16815250905090565b6040805182516bffffffffffffffffffffffff16815260208084015173ffffffffffffffffffffffffffffffffffffffff16908201529181015163ffffffff16908201526060016101f0565b61037b610376366004614304565b610b70565b6040516101f09190614416565b6103c46040518060400160405280601381526020017f46656551756f74657220312e362e302d6465760000000000000000000000000081525081565b6040516101f09190614498565b6103d9610ee2565b6040516101f091906144ab565b6103f96103f4366004614505565b610ef3565b005b6103f96104093660046146a7565b6111a8565b6103f961041c3660046147d9565b6111bc565b61043461042f366004614914565b6111fe565b6040516101f09190614956565b61045461044f36600461428c565b6112c9565b6040517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff90911681526020016101f0565b61051761048f3660046149d1565b60408051808201909152600080825260208201525067ffffffffffffffff166000908152600560209081526040918290208251808401909352547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811683527c0100000000000000000000000000000000000000000000000000000000900463ffffffff169082015290565b6040516101f091906149ec565b61078b6105323660046149d1565b6040805161020081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a081018290526101c081018290526101e08101919091525067ffffffffffffffff908116600090815260096020908152604091829020825161020081018452815460ff8082161515835261ffff61010080840482169685019690965263ffffffff630100000084048116978501979097526701000000000000008304871660608501526b0100000000000000000000008304871660808501526f010000000000000000000000000000008304811660a085015271010000000000000000000000000000000000808404881660c086015275010000000000000000000000000000000000000000008404821660e08087019190915277010000000000000000000000000000000000000000000000850483169786019790975279010000000000000000000000000000000000000000000000000084049091166101208501527b01000000000000000000000000000000000000000000000000000000909204861661014084015260019093015480861661016084015264010000000081049096166101808301526c0100000000000000000000000086049094166101a0820152700100000000000000000000000000000000850490911615156101c08201527fffffffff0000000000000000000000000000000000000000000000000000000092909304901b166101e082015290565b6040516101f09190614a27565b6103f96107a6366004614c3e565b6112d4565b6103f96112e6565b6103f96107c1366004614f58565b6113e3565b6103f96107d4366004614ffe565b6113f5565b6108e96107e736600461506a565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101919091525067ffffffffffffffff919091166000908152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff94909416835292815290829020825160c081018452905463ffffffff8082168352640100000000820481169383019390935268010000000000000000810461ffff16938201939093526a01000000000000000000008304821660608201526e01000000000000000000000000000083049091166080820152720100000000000000000000000000000000000090910460ff16151560a082015290565b6040516101f09190600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101f0565b6103f961097f366004615094565b6118dd565b6103f9610992366004615155565b6118ee565b6103f96109a5366004615362565b6118ff565b610a236109b836600461428c565b6040805180820182526000808252602091820181905273ffffffffffffffffffffffffffffffffffffffff93841681526007825282902082518084019093525492831682527401000000000000000000000000000000000000000090920460ff169181019190915290565b60408051825173ffffffffffffffffffffffffffffffffffffffff16815260209283015160ff1692810192909252016101f0565b610a6a610a65366004615427565b611910565b6040516101f093929190615496565b6103d9611b06565b610517610a8f36600461428c565b611b12565b6101e6610aa23660046154b7565b611c0e565b6103f9610ab536600461428c565b6120ac565b610acd610ac836600461550c565b6120bd565b604080517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff9384168152929091166020830152016101f0565b6000610b0d82612248565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16610b3485612248565b610b5c907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1685615565565b610b66919061557c565b90505b9392505050565b67ffffffffffffffff8086166000908152600960205260409020600101546060917101000000000000000000000000000000000090910460e01b908590811115610bbc57610bbc614540565b604051908082528060200260200182016040528015610bef57816020015b6060815260200190600190039081610bda5790505b50915060005b85811015610ed7576000858583818110610c1157610c116155b7565b610c27926020604090920201908101915061428c565b90506000888884818110610c3d57610c3d6155b7565b9050602002810190610c4f91906155e6565b610c5d906040810190615624565b9150506020811115610d125767ffffffffffffffff8a166000908152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff861684529091529020546e010000000000000000000000000000900463ffffffff16811115610d12576040517f36f536ca00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526024015b60405180910390fd5b610d82848a8a86818110610d2857610d286155b7565b9050602002810190610d3a91906155e6565b610d48906020810190615624565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506122e292505050565b67ffffffffffffffff8a166000818152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684528252808320815160c081018352905463ffffffff8082168352640100000000820481168386015268010000000000000000820461ffff16838501526a01000000000000000000008204811660608401526e010000000000000000000000000000820481166080840152720100000000000000000000000000000000000090910460ff16151560a08301908152958552600990935290832054935190937b0100000000000000000000000000000000000000000000000000000090049091169190610e815781610e87565b82606001515b6040805163ffffffff8316602082015291925001604051602081830303815290604052888781518110610ebc57610ebc6155b7565b60200260200101819052505050505050806001019050610bf5565b505095945050505050565b6060610eee6002612339565b905090565b610efb612346565b6000610f078280615689565b9050905060005b81811015611051576000610f228480615689565b83818110610f3257610f326155b7565b905060400201803603810190610f48919061571d565b604080518082018252602080840180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff908116845263ffffffff42818116858701908152885173ffffffffffffffffffffffffffffffffffffffff9081166000908152600690975295889020965190519092167c010000000000000000000000000000000000000000000000000000000002919092161790935584519051935194955016927f52f50aa6d1a95a4595361ecf953d095f125d442e4673716dede699e049de148a926110409290917bffffffffffffffffffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b60405180910390a250600101610f0e565b5060006110616020840184615689565b9050905060005b818110156111a257600061107f6020860186615689565b8381811061108f5761108f6155b7565b9050604002018036038101906110a5919061575a565b604080518082018252602080840180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff908116845263ffffffff42818116858701908152885167ffffffffffffffff9081166000908152600590975295889020965190519092167c010000000000000000000000000000000000000000000000000000000002919092161790935584519051935194955016927fdd84a3fa9ef9409f550d54d6affec7e9c480c878c6ab27b78912a03e1b371c6e926111919290917bffffffffffffffffffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b60405180910390a250600101611068565b50505050565b6111b061238b565b6111b98161240c565b50565b6111c461238b565b60005b81518110156111fa576111f28282815181106111e5576111e56155b7565b602002602001015161250a565b6001016111c7565b5050565b60608160008167ffffffffffffffff81111561121c5761121c614540565b60405190808252806020026020018201604052801561126157816020015b604080518082019091526000808252602082015281526020019060019003908161123a5790505b50905060005b828110156112be57611299868683818110611284576112846155b7565b9050602002016020810190610a8f919061428c565b8282815181106112ab576112ab6155b7565b6020908102919091010152600101611267565b509150505b92915050565b60006112c382612248565b6112dc61238b565b6111fa82826126dc565b60015473ffffffffffffffffffffffffffffffffffffffff163314611367576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610d09565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6113eb61238b565b6111fa8282612ae9565b600080600061143987878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612c3092505050565b92509250925061144b33838584612c4b565b60006114598587018761577d565b905060005b81518110156118d25760006007600084848151811061147f5761147f6155b7565b6020908102919091018101515173ffffffffffffffffffffffffffffffffffffffff16825281019190915260400160009081205474010000000000000000000000000000000000000000900460ff169150819003611540578282815181106114e9576114e96155b7565b6020908102919091010151516040517f06439c6b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610d09565b600061158960128386868151811061155a5761155a6155b7565b6020026020010151602001517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16612da3565b9050600660008585815181106115a1576115a16155b7565b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001601c9054906101000a900463ffffffff1663ffffffff16848481518110611613576116136155b7565b60200260200101516040015163ffffffff16101561171d5783838151811061163d5761163d6155b7565b60200260200101516000015184848151811061165b5761165b6155b7565b6020026020010151604001516006600087878151811061167d5761167d6155b7565b6020908102919091018101515173ffffffffffffffffffffffffffffffffffffffff90811683529082019290925260409081016000205490517f191ec70600000000000000000000000000000000000000000000000000000000815293909116600484015263ffffffff91821660248401527c01000000000000000000000000000000000000000000000000000000009004166044820152606401610d09565b6040518060400160405280827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16815260200185858151811061175e5761175e6155b7565b60200260200101516040015163ffffffff1681525060066000868681518110611789576117896155b7565b6020908102919091018101515173ffffffffffffffffffffffffffffffffffffffff168252818101929092526040016000208251929091015163ffffffff167c0100000000000000000000000000000000000000000000000000000000027bffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092169190911790558351849084908110611821576118216155b7565b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff167f52f50aa6d1a95a4595361ecf953d095f125d442e4673716dede699e049de148a82868681518110611877576118776155b7565b6020026020010151604001516040516118c09291907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff92909216825263ffffffff16602082015260400190565b60405180910390a2505060010161145e565b505050505050505050565b6118e561238b565b6111b981612e69565b6118f661238b565b6111b981612ff5565b61190761238b565b6111b98161349b565b60008060607f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff16036119705785925061199e565b61199b87877f0000000000000000000000000000000000000000000000000000000000000000610b02565b92505b7f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff16831115611a3d576040517f6a92a483000000000000000000000000000000000000000000000000000000008152600481018490526bffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166024820152604401610d09565b67ffffffffffffffff881660009081526009602052604081206001015463ffffffff1690611a6c878784613585565b9050806020015193508484611af3836040805182516024820152602092830151151560448083019190915282518083039091018152606490910190915290810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f181dcf100000000000000000000000000000000000000000000000000000000017905290565b9450945094505050955095509592505050565b6060610eee600b612339565b604080518082019091526000808252602082015273ffffffffffffffffffffffffffffffffffffffff8281166000908152600760209081526040918290208251808401909352549283168083527401000000000000000000000000000000000000000090930460ff169082015290611c0557505073ffffffffffffffffffffffffffffffffffffffff166000908152600660209081526040918290208251808401909352547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811683527c0100000000000000000000000000000000000000000000000000000000900463ffffffff169082015290565b610b698161372e565b67ffffffffffffffff8083166000908152600960209081526040808320815161020081018352815460ff808216151580845261ffff61010080850482169886019890985263ffffffff630100000085048116978601979097526701000000000000008404871660608601526b0100000000000000000000008404871660808601526f010000000000000000000000000000008404811660a086015271010000000000000000000000000000000000808504881660c087015275010000000000000000000000000000000000000000008504821660e08088019190915277010000000000000000000000000000000000000000000000860483169987019990995279010000000000000000000000000000000000000000000000000085049091166101208601527b01000000000000000000000000000000000000000000000000000000909304861661014085015260019094015480861661016085015264010000000081049098166101808401526c0100000000000000000000000088049094166101a0830152700100000000000000000000000000000000870490931615156101c08201527fffffffff000000000000000000000000000000000000000000000000000000009290950490921b166101e0840152909190611e28576040517f99ac52f200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff85166004820152602401610d09565b6000611e376040850185615689565b9150611e93905082611e4c6020870187615624565b905083611e598880615624565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506138bd92505050565b6000600881611ea8608088016060890161428c565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160009081205467ffffffffffffffff16915080611ef7611ef16080890160608a0161428c565b896120bd565b9092509050600080808615611f3d57611f31888c611f1b60808e0160608f0161428c565b888e8060400190611f2c9190615689565b613967565b91945092509050611f5d565b6101a0880151611f5a9063ffffffff16662386f26fc10000615565565b92505b61010088015160009061ffff1615611fa157611f9e896dffffffffffffffffffffffffffff607088901c16611f9560208f018f615624565b90508b86613c3f565b90505b61018089015160009067ffffffffffffffff16611fca611fc460808f018f615624565b8d613cef565b600001518563ffffffff168c60a0015161ffff168f8060200190611fee9190615624565b611ff9929150615565565b8d6080015163ffffffff1661200e9190615844565b6120189190615844565b6120229190615844565b61203c906dffffffffffffffffffffffffffff8916615565565b6120469190615565565b90507bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8716828261207d67ffffffffffffffff8c1689615565565b6120879190615844565b6120919190615844565b61209b919061557c565b9d9c50505050505050505050505050565b6120b461238b565b6111b981613db0565b67ffffffffffffffff811660009081526005602090815260408083208151808301909252547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811682527c0100000000000000000000000000000000000000000000000000000000900463ffffffff1691810182905282918203612175576040517f2e59db3a00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff85166004820152602401610d09565b6000816020015163ffffffff164261218d9190615857565b90507f000000000000000000000000000000000000000000000000000000000000000063ffffffff1681111561222e576040517ff08bcb3e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8616600482015263ffffffff7f000000000000000000000000000000000000000000000000000000000000000016602482015260448101829052606401610d09565b61223786612248565b9151919350909150505b9250929050565b60008061225483611b12565b9050806020015163ffffffff166000148061228c575080517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16155b156122db576040517f06439c6b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152602401610d09565b5192915050565b7fd7ed2ad4000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316016111fa5761233481613ea5565b505050565b60606000610b6983613f58565b612351600233613fb4565b612389576040517fd86ad9cf000000000000000000000000000000000000000000000000000000008152336004820152602401610d09565b565b60005473ffffffffffffffffffffffffffffffffffffffff163314612389576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610d09565b60005b81518110156111fa57600082828151811061242c5761242c6155b7565b60209081029190910181015180518183015173ffffffffffffffffffffffffffffffffffffffff80831660008181526007875260409081902084518154868a018051929096167fffffffffffffffffffffff00000000000000000000000000000000000000000090911681177401000000000000000000000000000000000000000060ff9384160217909255825191825293519093169683019690965293955091939092917f08a5f7f5bb38a81d8e43aca13ecd76431dbf8816ae4699affff7b00b2fc1c464910160405180910390a250505080600101905061240f565b60006125c382600001518360600151846020015185604001516040805173ffffffffffffffffffffffffffffffffffffffff80871660208301528516918101919091527fffffffffffffffffffff00000000000000000000000000000000000000000000831660608201527fffff0000000000000000000000000000000000000000000000000000000000008216608082015260009060a001604051602081830303815290604052805190602001209050949350505050565b60808301516000828152600460205260409081902080549215157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00909316929092179091555190915081907f32a4ba3fa3351b11ad555d4c8ec70a744e8705607077a946807030d64b6ab1a3906126d0908590600060a08201905073ffffffffffffffffffffffffffffffffffffffff8084511683527fffffffffffffffffffff0000000000000000000000000000000000000000000060208501511660208401527fffff00000000000000000000000000000000000000000000000000000000000060408501511660408401528060608501511660608401525060808301511515608083015292915050565b60405180910390a25050565b60005b8251811015612a055760008382815181106126fc576126fc6155b7565b6020026020010151905060008160000151905060005b8260200151518110156129f757600083602001518281518110612737576127376155b7565b602002602001015160200151905060008460200151838151811061275d5761275d6155b7565b6020026020010151600001519050602063ffffffff16826080015163ffffffff1610156127e05760808201516040517f24ecdc0200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8316600482015263ffffffff9091166024820152604401610d09565b67ffffffffffffffff84166000818152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff86168085529083529281902086518154938801518389015160608a015160808b015160a08c015115157201000000000000000000000000000000000000027fffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffff63ffffffff9283166e01000000000000000000000000000002167fffffffffffffffffffffffffff0000000000ffffffffffffffffffffffffffff9383166a0100000000000000000000027fffffffffffffffffffffffffffffffffffff00000000ffffffffffffffffffff61ffff9096166801000000000000000002959095167fffffffffffffffffffffffffffffffffffff000000000000ffffffffffffffff968416640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000909b16939097169290921798909817939093169390931717919091161792909217909155519091907f94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b5906129e5908690600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60405180910390a35050600101612712565b5050508060010190506126df565b5060005b8151811015612334576000828281518110612a2657612a266155b7565b60200260200101516000015190506000838381518110612a4857612a486155b7565b60209081029190910181015181015167ffffffffffffffff84166000818152600a8452604080822073ffffffffffffffffffffffffffffffffffffffff8516808452955280822080547fffffffffffffffffffffffffff000000000000000000000000000000000000001690555192945090917f4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b9190a35050600101612a09565b60005b8251811015612b8c57612b22838281518110612b0a57612b0a6155b7565b6020026020010151600b613fe390919063ffffffff16565b15612b8457828181518110612b3957612b396155b7565b602002602001015173ffffffffffffffffffffffffffffffffffffffff167fdf1b1bd32a69711488d71554706bb130b1fc63a5fa1a2cd85e8440f84065ba2360405160405180910390a25b600101612aec565b5060005b815181101561233457612bc6828281518110612bae57612bae6155b7565b6020026020010151600b61400590919063ffffffff16565b15612c2857818181518110612bdd57612bdd6155b7565b602002602001015173ffffffffffffffffffffffffffffffffffffffff167f1795838dc8ab2ffc5f431a1729a6afa0b587f982f7b2be0b9d7187a1ef547f9160405160405180910390a25b600101612b90565b6040810151604a820151605e90920151909260609290921c91565b6040805173ffffffffffffffffffffffffffffffffffffffff868116602080840191909152908616828401527fffffffffffffffffffff00000000000000000000000000000000000000000000851660608301527fffff00000000000000000000000000000000000000000000000000000000000084166080808401919091528351808403909101815260a09092018352815191810191909120600081815260049092529190205460ff16612d9c576040517f097e17ff00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8087166004830152851660248201527fffffffffffffffffffff00000000000000000000000000000000000000000000841660448201527fffff00000000000000000000000000000000000000000000000000000000000083166064820152608401610d09565b5050505050565b600080612db0848661586a565b9050600060248260ff161115612de757612dcb602483615883565b612dd690600a6159bc565b612de0908561557c565b9050612e0a565b612df2826024615883565b612dfd90600a6159bc565b612e079085615565565b90505b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811115612e60576040517f10cb51d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b95945050505050565b602081015160005b8151811015612f04576000828281518110612e8e57612e8e6155b7565b60200260200101519050612eac81600261402790919063ffffffff16565b15612efb5760405173ffffffffffffffffffffffffffffffffffffffff821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b50600101612e71565b50815160005b81518110156111a2576000828281518110612f2757612f276155b7565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603612f97576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612fa2600282613fe3565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a150600101612f0a565b60005b81518110156111fa576000828281518110613015576130156155b7565b602002602001015190506000838381518110613033576130336155b7565b60200260200101516000015190506000826020015190508167ffffffffffffffff166000148061306c575061016081015163ffffffff16155b806130be57506101e08101517fffffffff00000000000000000000000000000000000000000000000000000000167f2812d52c0000000000000000000000000000000000000000000000000000000014155b806130dd5750806060015163ffffffff1681610160015163ffffffff16115b15613120576040517fc35aa79d00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff83166004820152602401610d09565b67ffffffffffffffff821660009081526009602052604081206001015471010000000000000000000000000000000000900460e01b7fffffffff000000000000000000000000000000000000000000000000000000001690036131c4578167ffffffffffffffff167fd31c671936387b2f84ed402b553bd50c0e9c20408ea4e91a836d77b8180fb724826040516131b79190614a27565b60405180910390a2613207565b8167ffffffffffffffff167f1edd6f3553cfa16f10b95b195abae3a1cfca4783de4843f95d674b1e1df5ab20826040516131fe9190614a27565b60405180910390a25b80600960008467ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548161ffff021916908361ffff16021790555060408201518160000160036101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160076101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600b6101000a81548163ffffffff021916908363ffffffff16021790555060a082015181600001600f6101000a81548161ffff021916908361ffff16021790555060c08201518160000160116101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160000160156101000a81548161ffff021916908361ffff1602179055506101008201518160000160176101000a81548161ffff021916908361ffff1602179055506101208201518160000160196101000a81548161ffff021916908361ffff16021790555061014082015181600001601b6101000a81548163ffffffff021916908363ffffffff1602179055506101608201518160010160006101000a81548163ffffffff021916908363ffffffff1602179055506101808201518160010160046101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506101a082015181600101600c6101000a81548163ffffffff021916908363ffffffff1602179055506101c08201518160010160106101000a81548160ff0219169083151502179055506101e08201518160010160116101000a81548163ffffffff021916908360e01c0217905550905050505050806001019050612ff8565b60005b81518110156111fa5760008282815181106134bb576134bb6155b7565b602002602001015160000151905060008383815181106134dd576134dd6155b7565b60209081029190910181015181015173ffffffffffffffffffffffffffffffffffffffff841660008181526008845260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff85169081179091559051908152919350917fbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d910160405180910390a2505060010161349e565b604080518082019091526000808252602082015260008390036135c657506040805180820190915267ffffffffffffffff8216815260006020820152610b69565b60006135d284866159cb565b905060006135e38560048189615a11565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505050507fffffffff0000000000000000000000000000000000000000000000000000000082167fe7e230f0000000000000000000000000000000000000000000000000000000000161368057808060200190518101906136779190615a3b565b92505050610b69565b7f6859a837000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316016136fc576040518060400160405280828060200190518101906136e89190615a67565b815260006020909101529250610b69915050565b6040517f5247fdce00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080518082019091526000808252602082015260008260000151905060008173ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015613798573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137bc9190615a9a565b50505091505060008112156137fd576040517f10cb51d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061387c8373ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561384d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138719190615aea565b866020015184612da3565b604080518082019091527bffffffffffffffffffffffffffffffffffffffffffffffffffffffff909116815263ffffffff4216602082015295945050505050565b836040015163ffffffff168311156139165760408085015190517f8693378900000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015260248101849052604401610d09565b836020015161ffff16821115613958576040517f4c056b6a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6111a2846101e00151826122e2565b6000808083815b81811015613c3157600087878381811061398a5761398a6155b7565b9050604002018036038101906139a09190615b07565b67ffffffffffffffff8c166000908152600a60209081526040808320845173ffffffffffffffffffffffffffffffffffffffff168452825291829020825160c081018452905463ffffffff8082168352640100000000820481169383019390935268010000000000000000810461ffff16938201939093526a01000000000000000000008304821660608201526e01000000000000000000000000000083049091166080820152720100000000000000000000000000000000000090910460ff16151560a0820181905291925090613ac0576101208d0151613a8d9061ffff16662386f26fc10000615565565b613a979088615844565b96508c610140015186613aaa9190615b40565b9550613ab7602086615b40565b94505050613c29565b604081015160009061ffff1615613b795760008c73ffffffffffffffffffffffffffffffffffffffff16846000015173ffffffffffffffffffffffffffffffffffffffff1614613b1c578351613b1590612248565b9050613b1f565b508a5b620186a0836040015161ffff16613b618660200151847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1661404990919063ffffffff16565b613b6b9190615565565b613b75919061557c565b9150505b6060820151613b889088615b40565b9650816080015186613b9a9190615b40565b8251909650600090613bb99063ffffffff16662386f26fc10000615565565b905080821015613bd857613bcd818a615844565b985050505050613c29565b6000836020015163ffffffff16662386f26fc10000613bf79190615565565b905080831115613c1757613c0b818b615844565b99505050505050613c29565b613c21838b615844565b995050505050505b60010161396e565b505096509650969350505050565b60008063ffffffff8316613c5561016086615565565b613c61876101c0615844565b613c6b9190615844565b613c759190615844565b905060008760c0015163ffffffff168860e0015161ffff1683613c989190615565565b613ca29190615844565b61010089015190915061ffff16613cc96dffffffffffffffffffffffffffff891683615565565b613cd39190615565565b613ce390655af3107a4000615565565b98975050505050505050565b60408051808201909152600080825260208201526000613d1b858585610160015163ffffffff16613585565b9050826060015163ffffffff1681600001511115613d65576040517f4c4fc93a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b826101c001518015613d7957508060200151155b15610b66576040517fee433e9900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff821603613e2f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610d09565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60008151602014613ee457816040517f8d666f60000000000000000000000000000000000000000000000000000000008152600401610d099190614498565b600082806020019051810190613efa9190615a67565b905073ffffffffffffffffffffffffffffffffffffffff811180613f1f575061040081105b156112c357826040517f8d666f60000000000000000000000000000000000000000000000000000000008152600401610d099190614498565b606081600001805480602002602001604051908101604052809291908181526020018280548015613fa857602002820191906000526020600020905b815481526020019060010190808311613f94575b50505050509050919050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515610b69565b6000610b698373ffffffffffffffffffffffffffffffffffffffff8416614086565b6000610b698373ffffffffffffffffffffffffffffffffffffffff84166140d5565b6000610b698373ffffffffffffffffffffffffffffffffffffffff84166141cf565b6000670de0b6b3a764000061407c837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8616615565565b610b69919061557c565b60008181526001830160205260408120546140cd575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556112c3565b5060006112c3565b600081815260018301602052604081205480156141be5760006140f9600183615857565b855490915060009061410d90600190615857565b905080821461417257600086600001828154811061412d5761412d6155b7565b9060005260206000200154905080876000018481548110614150576141506155b7565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061418357614183615b5d565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506112c3565b60009150506112c3565b5092915050565b600081815260018301602052604081205480156141be5760006141f3600183615857565b855490915060009061420790600190615857565b905081811461417257600086600001828154811061412d5761412d6155b7565b803573ffffffffffffffffffffffffffffffffffffffff8116811461424b57600080fd5b919050565b60008060006060848603121561426557600080fd5b61426e84614227565b92506020840135915061428360408501614227565b90509250925092565b60006020828403121561429e57600080fd5b610b6982614227565b803567ffffffffffffffff8116811461424b57600080fd5b60008083601f8401126142d157600080fd5b50813567ffffffffffffffff8111156142e957600080fd5b6020830191508360208260051b850101111561224157600080fd5b60008060008060006060868803121561431c57600080fd5b614325866142a7565b9450602086013567ffffffffffffffff8082111561434257600080fd5b61434e89838a016142bf565b9096509450604088013591508082111561436757600080fd5b818801915088601f83011261437b57600080fd5b81358181111561438a57600080fd5b8960208260061b850101111561439f57600080fd5b9699959850939650602001949392505050565b6000815180845260005b818110156143d8576020818501810151868301820152016143bc565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b8281101561448b577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526144798583516143b2565b9450928501929085019060010161443f565b5092979650505050505050565b602081526000610b6960208301846143b2565b6020808252825182820181905260009190848201906040850190845b818110156144f957835173ffffffffffffffffffffffffffffffffffffffff16835292840192918401916001016144c7565b50909695505050505050565b60006020828403121561451757600080fd5b813567ffffffffffffffff81111561452e57600080fd5b820160408185031215610b6957600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561459257614592614540565b60405290565b60405160a0810167ffffffffffffffff8111828210171561459257614592614540565b60405160c0810167ffffffffffffffff8111828210171561459257614592614540565b604051610200810167ffffffffffffffff8111828210171561459257614592614540565b6040516060810167ffffffffffffffff8111828210171561459257614592614540565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561466c5761466c614540565b604052919050565b600067ffffffffffffffff82111561468e5761468e614540565b5060051b60200190565b60ff811681146111b957600080fd5b600060208083850312156146ba57600080fd5b823567ffffffffffffffff8111156146d157600080fd5b8301601f810185136146e257600080fd5b80356146f56146f082614674565b614625565b8181526060918202830184019184820191908884111561471457600080fd5b938501935b838510156147b457848903818112156147325760008081fd5b61473a61456f565b61474387614227565b81526040807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0840112156147775760008081fd5b61477f61456f565b925061478c898901614227565b835287013561479a81614698565b828901528088019190915283529384019391850191614719565b50979650505050505050565b80151581146111b957600080fd5b803561424b816147c0565b600060208083850312156147ec57600080fd5b823567ffffffffffffffff81111561480357600080fd5b8301601f8101851361481457600080fd5b80356148226146f082614674565b81815260a0918202830184019184820191908884111561484157600080fd5b938501935b838510156147b45780858a03121561485e5760008081fd5b614866614598565b61486f86614227565b8152868601357fffffffffffffffffffff00000000000000000000000000000000000000000000811681146148a45760008081fd5b818801526040868101357fffff000000000000000000000000000000000000000000000000000000000000811681146148dd5760008081fd5b9082015260606148ee878201614227565b90820152608086810135614901816147c0565b9082015283529384019391850191614846565b6000806020838503121561492757600080fd5b823567ffffffffffffffff81111561493e57600080fd5b61494a858286016142bf565b90969095509350505050565b602080825282518282018190526000919060409081850190868401855b828110156149c4576149b484835180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16825260209081015163ffffffff16910152565b9284019290850190600101614973565b5091979650505050505050565b6000602082840312156149e357600080fd5b610b69826142a7565b81517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16815260208083015163ffffffff1690820152604081016112c3565b81511515815261020081016020830151614a47602084018261ffff169052565b506040830151614a5f604084018263ffffffff169052565b506060830151614a77606084018263ffffffff169052565b506080830151614a8f608084018263ffffffff169052565b5060a0830151614aa560a084018261ffff169052565b5060c0830151614abd60c084018263ffffffff169052565b5060e0830151614ad360e084018261ffff169052565b506101008381015161ffff9081169184019190915261012080850151909116908301526101408084015163ffffffff90811691840191909152610160808501518216908401526101808085015167ffffffffffffffff16908401526101a080850151909116908301526101c0808401511515908301526101e0808401517fffffffff000000000000000000000000000000000000000000000000000000008116828501525b505092915050565b803563ffffffff8116811461424b57600080fd5b803561ffff8116811461424b57600080fd5b600082601f830112614bb757600080fd5b81356020614bc76146f083614674565b82815260069290921b84018101918181019086841115614be657600080fd5b8286015b84811015614c335760408189031215614c035760008081fd5b614c0b61456f565b614c14826142a7565b8152614c21858301614227565b81860152835291830191604001614bea565b509695505050505050565b60008060408385031215614c5157600080fd5b67ffffffffffffffff83351115614c6757600080fd5b83601f843585010112614c7957600080fd5b614c896146f08435850135614674565b8335840180358083526020808401939260059290921b90910101861015614caf57600080fd5b602085358601015b85358601803560051b01602001811015614ebc5767ffffffffffffffff81351115614ce157600080fd5b8035863587010160407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0828a03011215614d1a57600080fd5b614d2261456f565b614d2e602083016142a7565b815267ffffffffffffffff60408301351115614d4957600080fd5b88603f604084013584010112614d5e57600080fd5b614d746146f06020604085013585010135614674565b6020604084810135850182810135808552928401939260e00201018b1015614d9b57600080fd5b6040808501358501015b6040858101358601602081013560e0020101811015614e9d5760e0818d031215614dce57600080fd5b614dd661456f565b614ddf82614227565b815260c07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0838f03011215614e1357600080fd5b614e1b6145bb565b614e2760208401614b80565b8152614e3560408401614b80565b6020820152614e4660608401614b94565b6040820152614e5760808401614b80565b6060820152614e6860a08401614b80565b6080820152614e7a60c08401356147c0565b60c083013560a0820152602082810191909152908452929092019160e001614da5565b5080602084015250508085525050602083019250602081019050614cb7565b5092505067ffffffffffffffff60208401351115614ed957600080fd5b614ee98460208501358501614ba6565b90509250929050565b600082601f830112614f0357600080fd5b81356020614f136146f083614674565b8083825260208201915060208460051b870101935086841115614f3557600080fd5b602086015b84811015614c3357614f4b81614227565b8352918301918301614f3a565b60008060408385031215614f6b57600080fd5b823567ffffffffffffffff80821115614f8357600080fd5b614f8f86838701614ef2565b93506020850135915080821115614fa557600080fd5b50614fb285828601614ef2565b9150509250929050565b60008083601f840112614fce57600080fd5b50813567ffffffffffffffff811115614fe657600080fd5b60208301915083602082850101111561224157600080fd5b6000806000806040858703121561501457600080fd5b843567ffffffffffffffff8082111561502c57600080fd5b61503888838901614fbc565b9096509450602087013591508082111561505157600080fd5b5061505e87828801614fbc565b95989497509550505050565b6000806040838503121561507d57600080fd5b615086836142a7565b9150614ee960208401614227565b6000602082840312156150a657600080fd5b813567ffffffffffffffff808211156150be57600080fd5b90830190604082860312156150d257600080fd5b6150da61456f565b8235828111156150e957600080fd5b6150f587828601614ef2565b82525060208301358281111561510a57600080fd5b61511687828601614ef2565b60208301525095945050505050565b80357fffffffff000000000000000000000000000000000000000000000000000000008116811461424b57600080fd5b6000602080838503121561516857600080fd5b823567ffffffffffffffff81111561517f57600080fd5b8301601f8101851361519057600080fd5b803561519e6146f082614674565b81815261022091820283018401918482019190888411156151be57600080fd5b938501935b838510156147b457848903818112156151dc5760008081fd5b6151e461456f565b6151ed876142a7565b8152610200807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0840112156152225760008081fd5b61522a6145de565b92506152378989016147ce565b83526040615246818a01614b94565b8a8501526060615257818b01614b80565b828601526080915061526a828b01614b80565b9085015260a061527b8a8201614b80565b8286015260c0915061528e828b01614b94565b9085015260e061529f8a8201614b80565b8286015261010091506152b3828b01614b94565b908501526101206152c58a8201614b94565b8286015261014091506152d9828b01614b94565b908501526101606152eb8a8201614b80565b8286015261018091506152ff828b01614b80565b908501526101a06153118a82016142a7565b828601526101c09150615325828b01614b80565b908501526101e06153378a82016147ce565b82860152615346838b01615125565b90850152505080880191909152835293840193918501916151c3565b6000602080838503121561537557600080fd5b823567ffffffffffffffff81111561538c57600080fd5b8301601f8101851361539d57600080fd5b80356153ab6146f082614674565b81815260069190911b820183019083810190878311156153ca57600080fd5b928401925b8284101561541c57604084890312156153e85760008081fd5b6153f061456f565b6153f985614227565b81526154068686016142a7565b81870152825260409390930192908401906153cf565b979650505050505050565b60008060008060006080868803121561543f57600080fd5b615448866142a7565b945061545660208701614227565b935060408601359250606086013567ffffffffffffffff81111561547957600080fd5b61548588828901614fbc565b969995985093965092949392505050565b8381528215156020820152606060408201526000612e6060608301846143b2565b600080604083850312156154ca57600080fd5b6154d3836142a7565b9150602083013567ffffffffffffffff8111156154ef57600080fd5b830160a0818603121561550157600080fd5b809150509250929050565b6000806040838503121561551f57600080fd5b61552883614227565b9150614ee9602084016142a7565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80820281158282048414176112c3576112c3615536565b6000826155b2577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6183360301811261561a57600080fd5b9190910192915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261565957600080fd5b83018035915067ffffffffffffffff82111561567457600080fd5b60200191503681900382131561224157600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126156be57600080fd5b83018035915067ffffffffffffffff8211156156d957600080fd5b6020019150600681901b360382131561224157600080fd5b80357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116811461424b57600080fd5b60006040828403121561572f57600080fd5b61573761456f565b61574083614227565b815261574e602084016156f1565b60208201529392505050565b60006040828403121561576c57600080fd5b61577461456f565b615740836142a7565b6000602080838503121561579057600080fd5b823567ffffffffffffffff8111156157a757600080fd5b8301601f810185136157b857600080fd5b80356157c66146f082614674565b818152606091820283018401918482019190888411156157e557600080fd5b938501935b838510156147b45780858a0312156158025760008081fd5b61580a614602565b61581386614227565b81526158208787016156f1565b878201526040615831818801614b80565b90820152835293840193918501916157ea565b808201808211156112c3576112c3615536565b818103818111156112c3576112c3615536565b60ff81811683821601908111156112c3576112c3615536565b60ff82811682821603908111156112c3576112c3615536565b600181815b808511156158f557817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156158db576158db615536565b808516156158e857918102915b93841c93908002906158a1565b509250929050565b60008261590c575060016112c3565b81615919575060006112c3565b816001811461592f576002811461593957615955565b60019150506112c3565b60ff84111561594a5761594a615536565b50506001821b6112c3565b5060208310610133831016604e8410600b8410161715615978575081810a6112c3565b615982838361589c565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156159b4576159b4615536565b029392505050565b6000610b6960ff8416836158fd565b7fffffffff000000000000000000000000000000000000000000000000000000008135818116916004851015614b785760049490940360031b84901b1690921692915050565b60008085851115615a2157600080fd5b83861115615a2e57600080fd5b5050820193919092039150565b600060408284031215615a4d57600080fd5b615a5561456f565b82518152602083015161574e816147c0565b600060208284031215615a7957600080fd5b5051919050565b805169ffffffffffffffffffff8116811461424b57600080fd5b600080600080600060a08688031215615ab257600080fd5b615abb86615a80565b9450602086015193506040860151925060608601519150615ade60808701615a80565b90509295509295909350565b600060208284031215615afc57600080fd5b8151610b6981614698565b600060408284031215615b1957600080fd5b615b2161456f565b615b2a83614227565b8152602083013560208201528091505092915050565b63ffffffff8181168382160190808211156141c8576141c8615536565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea164736f6c6343000818000a", } -var PriceRegistryABI = PriceRegistryMetaData.ABI +var FeeQuoterABI = FeeQuoterMetaData.ABI -var PriceRegistryBin = PriceRegistryMetaData.Bin +var FeeQuoterBin = FeeQuoterMetaData.Bin -func DeployPriceRegistry(auth *bind.TransactOpts, backend bind.ContractBackend, staticConfig PriceRegistryStaticConfig, priceUpdaters []common.Address, feeTokens []common.Address, tokenPriceFeeds []PriceRegistryTokenPriceFeedUpdate, tokenTransferFeeConfigArgs []PriceRegistryTokenTransferFeeConfigArgs, premiumMultiplierWeiPerEthArgs []PriceRegistryPremiumMultiplierWeiPerEthArgs, destChainConfigArgs []PriceRegistryDestChainConfigArgs) (common.Address, *types.Transaction, *PriceRegistry, error) { - parsed, err := PriceRegistryMetaData.GetAbi() +func DeployFeeQuoter(auth *bind.TransactOpts, backend bind.ContractBackend, staticConfig FeeQuoterStaticConfig, priceUpdaters []common.Address, feeTokens []common.Address, tokenPriceFeeds []FeeQuoterTokenPriceFeedUpdate, tokenTransferFeeConfigArgs []FeeQuoterTokenTransferFeeConfigArgs, premiumMultiplierWeiPerEthArgs []FeeQuoterPremiumMultiplierWeiPerEthArgs, destChainConfigArgs []FeeQuoterDestChainConfigArgs) (common.Address, *types.Transaction, *FeeQuoter, error) { + parsed, err := FeeQuoterMetaData.GetAbi() if err != nil { return common.Address{}, nil, nil, err } @@ -171,132 +171,132 @@ func DeployPriceRegistry(auth *bind.TransactOpts, backend bind.ContractBackend, return common.Address{}, nil, nil, errors.New("GetABI returned nil") } - address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(PriceRegistryBin), backend, staticConfig, priceUpdaters, feeTokens, tokenPriceFeeds, tokenTransferFeeConfigArgs, premiumMultiplierWeiPerEthArgs, destChainConfigArgs) + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(FeeQuoterBin), backend, staticConfig, priceUpdaters, feeTokens, tokenPriceFeeds, tokenTransferFeeConfigArgs, premiumMultiplierWeiPerEthArgs, destChainConfigArgs) if err != nil { return common.Address{}, nil, nil, err } - return address, tx, &PriceRegistry{address: address, abi: *parsed, PriceRegistryCaller: PriceRegistryCaller{contract: contract}, PriceRegistryTransactor: PriceRegistryTransactor{contract: contract}, PriceRegistryFilterer: PriceRegistryFilterer{contract: contract}}, nil + return address, tx, &FeeQuoter{address: address, abi: *parsed, FeeQuoterCaller: FeeQuoterCaller{contract: contract}, FeeQuoterTransactor: FeeQuoterTransactor{contract: contract}, FeeQuoterFilterer: FeeQuoterFilterer{contract: contract}}, nil } -type PriceRegistry struct { +type FeeQuoter struct { address common.Address abi abi.ABI - PriceRegistryCaller - PriceRegistryTransactor - PriceRegistryFilterer + FeeQuoterCaller + FeeQuoterTransactor + FeeQuoterFilterer } -type PriceRegistryCaller struct { +type FeeQuoterCaller struct { contract *bind.BoundContract } -type PriceRegistryTransactor struct { +type FeeQuoterTransactor struct { contract *bind.BoundContract } -type PriceRegistryFilterer struct { +type FeeQuoterFilterer struct { contract *bind.BoundContract } -type PriceRegistrySession struct { - Contract *PriceRegistry +type FeeQuoterSession struct { + Contract *FeeQuoter CallOpts bind.CallOpts TransactOpts bind.TransactOpts } -type PriceRegistryCallerSession struct { - Contract *PriceRegistryCaller +type FeeQuoterCallerSession struct { + Contract *FeeQuoterCaller CallOpts bind.CallOpts } -type PriceRegistryTransactorSession struct { - Contract *PriceRegistryTransactor +type FeeQuoterTransactorSession struct { + Contract *FeeQuoterTransactor TransactOpts bind.TransactOpts } -type PriceRegistryRaw struct { - Contract *PriceRegistry +type FeeQuoterRaw struct { + Contract *FeeQuoter } -type PriceRegistryCallerRaw struct { - Contract *PriceRegistryCaller +type FeeQuoterCallerRaw struct { + Contract *FeeQuoterCaller } -type PriceRegistryTransactorRaw struct { - Contract *PriceRegistryTransactor +type FeeQuoterTransactorRaw struct { + Contract *FeeQuoterTransactor } -func NewPriceRegistry(address common.Address, backend bind.ContractBackend) (*PriceRegistry, error) { - abi, err := abi.JSON(strings.NewReader(PriceRegistryABI)) +func NewFeeQuoter(address common.Address, backend bind.ContractBackend) (*FeeQuoter, error) { + abi, err := abi.JSON(strings.NewReader(FeeQuoterABI)) if err != nil { return nil, err } - contract, err := bindPriceRegistry(address, backend, backend, backend) + contract, err := bindFeeQuoter(address, backend, backend, backend) if err != nil { return nil, err } - return &PriceRegistry{address: address, abi: abi, PriceRegistryCaller: PriceRegistryCaller{contract: contract}, PriceRegistryTransactor: PriceRegistryTransactor{contract: contract}, PriceRegistryFilterer: PriceRegistryFilterer{contract: contract}}, nil + return &FeeQuoter{address: address, abi: abi, FeeQuoterCaller: FeeQuoterCaller{contract: contract}, FeeQuoterTransactor: FeeQuoterTransactor{contract: contract}, FeeQuoterFilterer: FeeQuoterFilterer{contract: contract}}, nil } -func NewPriceRegistryCaller(address common.Address, caller bind.ContractCaller) (*PriceRegistryCaller, error) { - contract, err := bindPriceRegistry(address, caller, nil, nil) +func NewFeeQuoterCaller(address common.Address, caller bind.ContractCaller) (*FeeQuoterCaller, error) { + contract, err := bindFeeQuoter(address, caller, nil, nil) if err != nil { return nil, err } - return &PriceRegistryCaller{contract: contract}, nil + return &FeeQuoterCaller{contract: contract}, nil } -func NewPriceRegistryTransactor(address common.Address, transactor bind.ContractTransactor) (*PriceRegistryTransactor, error) { - contract, err := bindPriceRegistry(address, nil, transactor, nil) +func NewFeeQuoterTransactor(address common.Address, transactor bind.ContractTransactor) (*FeeQuoterTransactor, error) { + contract, err := bindFeeQuoter(address, nil, transactor, nil) if err != nil { return nil, err } - return &PriceRegistryTransactor{contract: contract}, nil + return &FeeQuoterTransactor{contract: contract}, nil } -func NewPriceRegistryFilterer(address common.Address, filterer bind.ContractFilterer) (*PriceRegistryFilterer, error) { - contract, err := bindPriceRegistry(address, nil, nil, filterer) +func NewFeeQuoterFilterer(address common.Address, filterer bind.ContractFilterer) (*FeeQuoterFilterer, error) { + contract, err := bindFeeQuoter(address, nil, nil, filterer) if err != nil { return nil, err } - return &PriceRegistryFilterer{contract: contract}, nil + return &FeeQuoterFilterer{contract: contract}, nil } -func bindPriceRegistry(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := PriceRegistryMetaData.GetAbi() +func bindFeeQuoter(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := FeeQuoterMetaData.GetAbi() if err != nil { return nil, err } return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil } -func (_PriceRegistry *PriceRegistryRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _PriceRegistry.Contract.PriceRegistryCaller.contract.Call(opts, result, method, params...) +func (_FeeQuoter *FeeQuoterRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _FeeQuoter.Contract.FeeQuoterCaller.contract.Call(opts, result, method, params...) } -func (_PriceRegistry *PriceRegistryRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _PriceRegistry.Contract.PriceRegistryTransactor.contract.Transfer(opts) +func (_FeeQuoter *FeeQuoterRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _FeeQuoter.Contract.FeeQuoterTransactor.contract.Transfer(opts) } -func (_PriceRegistry *PriceRegistryRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _PriceRegistry.Contract.PriceRegistryTransactor.contract.Transact(opts, method, params...) +func (_FeeQuoter *FeeQuoterRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _FeeQuoter.Contract.FeeQuoterTransactor.contract.Transact(opts, method, params...) } -func (_PriceRegistry *PriceRegistryCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _PriceRegistry.Contract.contract.Call(opts, result, method, params...) +func (_FeeQuoter *FeeQuoterCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _FeeQuoter.Contract.contract.Call(opts, result, method, params...) } -func (_PriceRegistry *PriceRegistryTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _PriceRegistry.Contract.contract.Transfer(opts) +func (_FeeQuoter *FeeQuoterTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _FeeQuoter.Contract.contract.Transfer(opts) } -func (_PriceRegistry *PriceRegistryTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _PriceRegistry.Contract.contract.Transact(opts, method, params...) +func (_FeeQuoter *FeeQuoterTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _FeeQuoter.Contract.contract.Transact(opts, method, params...) } -func (_PriceRegistry *PriceRegistryCaller) ConvertTokenAmount(opts *bind.CallOpts, fromToken common.Address, fromTokenAmount *big.Int, toToken common.Address) (*big.Int, error) { +func (_FeeQuoter *FeeQuoterCaller) ConvertTokenAmount(opts *bind.CallOpts, fromToken common.Address, fromTokenAmount *big.Int, toToken common.Address) (*big.Int, error) { var out []interface{} - err := _PriceRegistry.contract.Call(opts, &out, "convertTokenAmount", fromToken, fromTokenAmount, toToken) + err := _FeeQuoter.contract.Call(opts, &out, "convertTokenAmount", fromToken, fromTokenAmount, toToken) if err != nil { return *new(*big.Int), err @@ -308,17 +308,17 @@ func (_PriceRegistry *PriceRegistryCaller) ConvertTokenAmount(opts *bind.CallOpt } -func (_PriceRegistry *PriceRegistrySession) ConvertTokenAmount(fromToken common.Address, fromTokenAmount *big.Int, toToken common.Address) (*big.Int, error) { - return _PriceRegistry.Contract.ConvertTokenAmount(&_PriceRegistry.CallOpts, fromToken, fromTokenAmount, toToken) +func (_FeeQuoter *FeeQuoterSession) ConvertTokenAmount(fromToken common.Address, fromTokenAmount *big.Int, toToken common.Address) (*big.Int, error) { + return _FeeQuoter.Contract.ConvertTokenAmount(&_FeeQuoter.CallOpts, fromToken, fromTokenAmount, toToken) } -func (_PriceRegistry *PriceRegistryCallerSession) ConvertTokenAmount(fromToken common.Address, fromTokenAmount *big.Int, toToken common.Address) (*big.Int, error) { - return _PriceRegistry.Contract.ConvertTokenAmount(&_PriceRegistry.CallOpts, fromToken, fromTokenAmount, toToken) +func (_FeeQuoter *FeeQuoterCallerSession) ConvertTokenAmount(fromToken common.Address, fromTokenAmount *big.Int, toToken common.Address) (*big.Int, error) { + return _FeeQuoter.Contract.ConvertTokenAmount(&_FeeQuoter.CallOpts, fromToken, fromTokenAmount, toToken) } -func (_PriceRegistry *PriceRegistryCaller) GetAllAuthorizedCallers(opts *bind.CallOpts) ([]common.Address, error) { +func (_FeeQuoter *FeeQuoterCaller) GetAllAuthorizedCallers(opts *bind.CallOpts) ([]common.Address, error) { var out []interface{} - err := _PriceRegistry.contract.Call(opts, &out, "getAllAuthorizedCallers") + err := _FeeQuoter.contract.Call(opts, &out, "getAllAuthorizedCallers") if err != nil { return *new([]common.Address), err @@ -330,39 +330,39 @@ func (_PriceRegistry *PriceRegistryCaller) GetAllAuthorizedCallers(opts *bind.Ca } -func (_PriceRegistry *PriceRegistrySession) GetAllAuthorizedCallers() ([]common.Address, error) { - return _PriceRegistry.Contract.GetAllAuthorizedCallers(&_PriceRegistry.CallOpts) +func (_FeeQuoter *FeeQuoterSession) GetAllAuthorizedCallers() ([]common.Address, error) { + return _FeeQuoter.Contract.GetAllAuthorizedCallers(&_FeeQuoter.CallOpts) } -func (_PriceRegistry *PriceRegistryCallerSession) GetAllAuthorizedCallers() ([]common.Address, error) { - return _PriceRegistry.Contract.GetAllAuthorizedCallers(&_PriceRegistry.CallOpts) +func (_FeeQuoter *FeeQuoterCallerSession) GetAllAuthorizedCallers() ([]common.Address, error) { + return _FeeQuoter.Contract.GetAllAuthorizedCallers(&_FeeQuoter.CallOpts) } -func (_PriceRegistry *PriceRegistryCaller) GetDestChainConfig(opts *bind.CallOpts, destChainSelector uint64) (PriceRegistryDestChainConfig, error) { +func (_FeeQuoter *FeeQuoterCaller) GetDestChainConfig(opts *bind.CallOpts, destChainSelector uint64) (FeeQuoterDestChainConfig, error) { var out []interface{} - err := _PriceRegistry.contract.Call(opts, &out, "getDestChainConfig", destChainSelector) + err := _FeeQuoter.contract.Call(opts, &out, "getDestChainConfig", destChainSelector) if err != nil { - return *new(PriceRegistryDestChainConfig), err + return *new(FeeQuoterDestChainConfig), err } - out0 := *abi.ConvertType(out[0], new(PriceRegistryDestChainConfig)).(*PriceRegistryDestChainConfig) + out0 := *abi.ConvertType(out[0], new(FeeQuoterDestChainConfig)).(*FeeQuoterDestChainConfig) return out0, err } -func (_PriceRegistry *PriceRegistrySession) GetDestChainConfig(destChainSelector uint64) (PriceRegistryDestChainConfig, error) { - return _PriceRegistry.Contract.GetDestChainConfig(&_PriceRegistry.CallOpts, destChainSelector) +func (_FeeQuoter *FeeQuoterSession) GetDestChainConfig(destChainSelector uint64) (FeeQuoterDestChainConfig, error) { + return _FeeQuoter.Contract.GetDestChainConfig(&_FeeQuoter.CallOpts, destChainSelector) } -func (_PriceRegistry *PriceRegistryCallerSession) GetDestChainConfig(destChainSelector uint64) (PriceRegistryDestChainConfig, error) { - return _PriceRegistry.Contract.GetDestChainConfig(&_PriceRegistry.CallOpts, destChainSelector) +func (_FeeQuoter *FeeQuoterCallerSession) GetDestChainConfig(destChainSelector uint64) (FeeQuoterDestChainConfig, error) { + return _FeeQuoter.Contract.GetDestChainConfig(&_FeeQuoter.CallOpts, destChainSelector) } -func (_PriceRegistry *PriceRegistryCaller) GetDestinationChainGasPrice(opts *bind.CallOpts, destChainSelector uint64) (InternalTimestampedPackedUint224, error) { +func (_FeeQuoter *FeeQuoterCaller) GetDestinationChainGasPrice(opts *bind.CallOpts, destChainSelector uint64) (InternalTimestampedPackedUint224, error) { var out []interface{} - err := _PriceRegistry.contract.Call(opts, &out, "getDestinationChainGasPrice", destChainSelector) + err := _FeeQuoter.contract.Call(opts, &out, "getDestinationChainGasPrice", destChainSelector) if err != nil { return *new(InternalTimestampedPackedUint224), err @@ -374,17 +374,17 @@ func (_PriceRegistry *PriceRegistryCaller) GetDestinationChainGasPrice(opts *bin } -func (_PriceRegistry *PriceRegistrySession) GetDestinationChainGasPrice(destChainSelector uint64) (InternalTimestampedPackedUint224, error) { - return _PriceRegistry.Contract.GetDestinationChainGasPrice(&_PriceRegistry.CallOpts, destChainSelector) +func (_FeeQuoter *FeeQuoterSession) GetDestinationChainGasPrice(destChainSelector uint64) (InternalTimestampedPackedUint224, error) { + return _FeeQuoter.Contract.GetDestinationChainGasPrice(&_FeeQuoter.CallOpts, destChainSelector) } -func (_PriceRegistry *PriceRegistryCallerSession) GetDestinationChainGasPrice(destChainSelector uint64) (InternalTimestampedPackedUint224, error) { - return _PriceRegistry.Contract.GetDestinationChainGasPrice(&_PriceRegistry.CallOpts, destChainSelector) +func (_FeeQuoter *FeeQuoterCallerSession) GetDestinationChainGasPrice(destChainSelector uint64) (InternalTimestampedPackedUint224, error) { + return _FeeQuoter.Contract.GetDestinationChainGasPrice(&_FeeQuoter.CallOpts, destChainSelector) } -func (_PriceRegistry *PriceRegistryCaller) GetFeeTokens(opts *bind.CallOpts) ([]common.Address, error) { +func (_FeeQuoter *FeeQuoterCaller) GetFeeTokens(opts *bind.CallOpts) ([]common.Address, error) { var out []interface{} - err := _PriceRegistry.contract.Call(opts, &out, "getFeeTokens") + err := _FeeQuoter.contract.Call(opts, &out, "getFeeTokens") if err != nil { return *new([]common.Address), err @@ -396,17 +396,17 @@ func (_PriceRegistry *PriceRegistryCaller) GetFeeTokens(opts *bind.CallOpts) ([] } -func (_PriceRegistry *PriceRegistrySession) GetFeeTokens() ([]common.Address, error) { - return _PriceRegistry.Contract.GetFeeTokens(&_PriceRegistry.CallOpts) +func (_FeeQuoter *FeeQuoterSession) GetFeeTokens() ([]common.Address, error) { + return _FeeQuoter.Contract.GetFeeTokens(&_FeeQuoter.CallOpts) } -func (_PriceRegistry *PriceRegistryCallerSession) GetFeeTokens() ([]common.Address, error) { - return _PriceRegistry.Contract.GetFeeTokens(&_PriceRegistry.CallOpts) +func (_FeeQuoter *FeeQuoterCallerSession) GetFeeTokens() ([]common.Address, error) { + return _FeeQuoter.Contract.GetFeeTokens(&_FeeQuoter.CallOpts) } -func (_PriceRegistry *PriceRegistryCaller) GetPremiumMultiplierWeiPerEth(opts *bind.CallOpts, token common.Address) (uint64, error) { +func (_FeeQuoter *FeeQuoterCaller) GetPremiumMultiplierWeiPerEth(opts *bind.CallOpts, token common.Address) (uint64, error) { var out []interface{} - err := _PriceRegistry.contract.Call(opts, &out, "getPremiumMultiplierWeiPerEth", token) + err := _FeeQuoter.contract.Call(opts, &out, "getPremiumMultiplierWeiPerEth", token) if err != nil { return *new(uint64), err @@ -418,41 +418,41 @@ func (_PriceRegistry *PriceRegistryCaller) GetPremiumMultiplierWeiPerEth(opts *b } -func (_PriceRegistry *PriceRegistrySession) GetPremiumMultiplierWeiPerEth(token common.Address) (uint64, error) { - return _PriceRegistry.Contract.GetPremiumMultiplierWeiPerEth(&_PriceRegistry.CallOpts, token) +func (_FeeQuoter *FeeQuoterSession) GetPremiumMultiplierWeiPerEth(token common.Address) (uint64, error) { + return _FeeQuoter.Contract.GetPremiumMultiplierWeiPerEth(&_FeeQuoter.CallOpts, token) } -func (_PriceRegistry *PriceRegistryCallerSession) GetPremiumMultiplierWeiPerEth(token common.Address) (uint64, error) { - return _PriceRegistry.Contract.GetPremiumMultiplierWeiPerEth(&_PriceRegistry.CallOpts, token) +func (_FeeQuoter *FeeQuoterCallerSession) GetPremiumMultiplierWeiPerEth(token common.Address) (uint64, error) { + return _FeeQuoter.Contract.GetPremiumMultiplierWeiPerEth(&_FeeQuoter.CallOpts, token) } -func (_PriceRegistry *PriceRegistryCaller) GetStaticConfig(opts *bind.CallOpts) (PriceRegistryStaticConfig, error) { +func (_FeeQuoter *FeeQuoterCaller) GetStaticConfig(opts *bind.CallOpts) (FeeQuoterStaticConfig, error) { var out []interface{} - err := _PriceRegistry.contract.Call(opts, &out, "getStaticConfig") + err := _FeeQuoter.contract.Call(opts, &out, "getStaticConfig") if err != nil { - return *new(PriceRegistryStaticConfig), err + return *new(FeeQuoterStaticConfig), err } - out0 := *abi.ConvertType(out[0], new(PriceRegistryStaticConfig)).(*PriceRegistryStaticConfig) + out0 := *abi.ConvertType(out[0], new(FeeQuoterStaticConfig)).(*FeeQuoterStaticConfig) return out0, err } -func (_PriceRegistry *PriceRegistrySession) GetStaticConfig() (PriceRegistryStaticConfig, error) { - return _PriceRegistry.Contract.GetStaticConfig(&_PriceRegistry.CallOpts) +func (_FeeQuoter *FeeQuoterSession) GetStaticConfig() (FeeQuoterStaticConfig, error) { + return _FeeQuoter.Contract.GetStaticConfig(&_FeeQuoter.CallOpts) } -func (_PriceRegistry *PriceRegistryCallerSession) GetStaticConfig() (PriceRegistryStaticConfig, error) { - return _PriceRegistry.Contract.GetStaticConfig(&_PriceRegistry.CallOpts) +func (_FeeQuoter *FeeQuoterCallerSession) GetStaticConfig() (FeeQuoterStaticConfig, error) { + return _FeeQuoter.Contract.GetStaticConfig(&_FeeQuoter.CallOpts) } -func (_PriceRegistry *PriceRegistryCaller) GetTokenAndGasPrices(opts *bind.CallOpts, token common.Address, destChainSelector uint64) (GetTokenAndGasPrices, +func (_FeeQuoter *FeeQuoterCaller) GetTokenAndGasPrices(opts *bind.CallOpts, token common.Address, destChainSelector uint64) (GetTokenAndGasPrices, error) { var out []interface{} - err := _PriceRegistry.contract.Call(opts, &out, "getTokenAndGasPrices", token, destChainSelector) + err := _FeeQuoter.contract.Call(opts, &out, "getTokenAndGasPrices", token, destChainSelector) outstruct := new(GetTokenAndGasPrices) if err != nil { @@ -466,21 +466,21 @@ func (_PriceRegistry *PriceRegistryCaller) GetTokenAndGasPrices(opts *bind.CallO } -func (_PriceRegistry *PriceRegistrySession) GetTokenAndGasPrices(token common.Address, destChainSelector uint64) (GetTokenAndGasPrices, +func (_FeeQuoter *FeeQuoterSession) GetTokenAndGasPrices(token common.Address, destChainSelector uint64) (GetTokenAndGasPrices, error) { - return _PriceRegistry.Contract.GetTokenAndGasPrices(&_PriceRegistry.CallOpts, token, destChainSelector) + return _FeeQuoter.Contract.GetTokenAndGasPrices(&_FeeQuoter.CallOpts, token, destChainSelector) } -func (_PriceRegistry *PriceRegistryCallerSession) GetTokenAndGasPrices(token common.Address, destChainSelector uint64) (GetTokenAndGasPrices, +func (_FeeQuoter *FeeQuoterCallerSession) GetTokenAndGasPrices(token common.Address, destChainSelector uint64) (GetTokenAndGasPrices, error) { - return _PriceRegistry.Contract.GetTokenAndGasPrices(&_PriceRegistry.CallOpts, token, destChainSelector) + return _FeeQuoter.Contract.GetTokenAndGasPrices(&_FeeQuoter.CallOpts, token, destChainSelector) } -func (_PriceRegistry *PriceRegistryCaller) GetTokenPrice(opts *bind.CallOpts, token common.Address) (InternalTimestampedPackedUint224, error) { +func (_FeeQuoter *FeeQuoterCaller) GetTokenPrice(opts *bind.CallOpts, token common.Address) (InternalTimestampedPackedUint224, error) { var out []interface{} - err := _PriceRegistry.contract.Call(opts, &out, "getTokenPrice", token) + err := _FeeQuoter.contract.Call(opts, &out, "getTokenPrice", token) if err != nil { return *new(InternalTimestampedPackedUint224), err @@ -492,39 +492,39 @@ func (_PriceRegistry *PriceRegistryCaller) GetTokenPrice(opts *bind.CallOpts, to } -func (_PriceRegistry *PriceRegistrySession) GetTokenPrice(token common.Address) (InternalTimestampedPackedUint224, error) { - return _PriceRegistry.Contract.GetTokenPrice(&_PriceRegistry.CallOpts, token) +func (_FeeQuoter *FeeQuoterSession) GetTokenPrice(token common.Address) (InternalTimestampedPackedUint224, error) { + return _FeeQuoter.Contract.GetTokenPrice(&_FeeQuoter.CallOpts, token) } -func (_PriceRegistry *PriceRegistryCallerSession) GetTokenPrice(token common.Address) (InternalTimestampedPackedUint224, error) { - return _PriceRegistry.Contract.GetTokenPrice(&_PriceRegistry.CallOpts, token) +func (_FeeQuoter *FeeQuoterCallerSession) GetTokenPrice(token common.Address) (InternalTimestampedPackedUint224, error) { + return _FeeQuoter.Contract.GetTokenPrice(&_FeeQuoter.CallOpts, token) } -func (_PriceRegistry *PriceRegistryCaller) GetTokenPriceFeedConfig(opts *bind.CallOpts, token common.Address) (IPriceRegistryTokenPriceFeedConfig, error) { +func (_FeeQuoter *FeeQuoterCaller) GetTokenPriceFeedConfig(opts *bind.CallOpts, token common.Address) (IFeeQuoterTokenPriceFeedConfig, error) { var out []interface{} - err := _PriceRegistry.contract.Call(opts, &out, "getTokenPriceFeedConfig", token) + err := _FeeQuoter.contract.Call(opts, &out, "getTokenPriceFeedConfig", token) if err != nil { - return *new(IPriceRegistryTokenPriceFeedConfig), err + return *new(IFeeQuoterTokenPriceFeedConfig), err } - out0 := *abi.ConvertType(out[0], new(IPriceRegistryTokenPriceFeedConfig)).(*IPriceRegistryTokenPriceFeedConfig) + out0 := *abi.ConvertType(out[0], new(IFeeQuoterTokenPriceFeedConfig)).(*IFeeQuoterTokenPriceFeedConfig) return out0, err } -func (_PriceRegistry *PriceRegistrySession) GetTokenPriceFeedConfig(token common.Address) (IPriceRegistryTokenPriceFeedConfig, error) { - return _PriceRegistry.Contract.GetTokenPriceFeedConfig(&_PriceRegistry.CallOpts, token) +func (_FeeQuoter *FeeQuoterSession) GetTokenPriceFeedConfig(token common.Address) (IFeeQuoterTokenPriceFeedConfig, error) { + return _FeeQuoter.Contract.GetTokenPriceFeedConfig(&_FeeQuoter.CallOpts, token) } -func (_PriceRegistry *PriceRegistryCallerSession) GetTokenPriceFeedConfig(token common.Address) (IPriceRegistryTokenPriceFeedConfig, error) { - return _PriceRegistry.Contract.GetTokenPriceFeedConfig(&_PriceRegistry.CallOpts, token) +func (_FeeQuoter *FeeQuoterCallerSession) GetTokenPriceFeedConfig(token common.Address) (IFeeQuoterTokenPriceFeedConfig, error) { + return _FeeQuoter.Contract.GetTokenPriceFeedConfig(&_FeeQuoter.CallOpts, token) } -func (_PriceRegistry *PriceRegistryCaller) GetTokenPrices(opts *bind.CallOpts, tokens []common.Address) ([]InternalTimestampedPackedUint224, error) { +func (_FeeQuoter *FeeQuoterCaller) GetTokenPrices(opts *bind.CallOpts, tokens []common.Address) ([]InternalTimestampedPackedUint224, error) { var out []interface{} - err := _PriceRegistry.contract.Call(opts, &out, "getTokenPrices", tokens) + err := _FeeQuoter.contract.Call(opts, &out, "getTokenPrices", tokens) if err != nil { return *new([]InternalTimestampedPackedUint224), err @@ -536,39 +536,39 @@ func (_PriceRegistry *PriceRegistryCaller) GetTokenPrices(opts *bind.CallOpts, t } -func (_PriceRegistry *PriceRegistrySession) GetTokenPrices(tokens []common.Address) ([]InternalTimestampedPackedUint224, error) { - return _PriceRegistry.Contract.GetTokenPrices(&_PriceRegistry.CallOpts, tokens) +func (_FeeQuoter *FeeQuoterSession) GetTokenPrices(tokens []common.Address) ([]InternalTimestampedPackedUint224, error) { + return _FeeQuoter.Contract.GetTokenPrices(&_FeeQuoter.CallOpts, tokens) } -func (_PriceRegistry *PriceRegistryCallerSession) GetTokenPrices(tokens []common.Address) ([]InternalTimestampedPackedUint224, error) { - return _PriceRegistry.Contract.GetTokenPrices(&_PriceRegistry.CallOpts, tokens) +func (_FeeQuoter *FeeQuoterCallerSession) GetTokenPrices(tokens []common.Address) ([]InternalTimestampedPackedUint224, error) { + return _FeeQuoter.Contract.GetTokenPrices(&_FeeQuoter.CallOpts, tokens) } -func (_PriceRegistry *PriceRegistryCaller) GetTokenTransferFeeConfig(opts *bind.CallOpts, destChainSelector uint64, token common.Address) (PriceRegistryTokenTransferFeeConfig, error) { +func (_FeeQuoter *FeeQuoterCaller) GetTokenTransferFeeConfig(opts *bind.CallOpts, destChainSelector uint64, token common.Address) (FeeQuoterTokenTransferFeeConfig, error) { var out []interface{} - err := _PriceRegistry.contract.Call(opts, &out, "getTokenTransferFeeConfig", destChainSelector, token) + err := _FeeQuoter.contract.Call(opts, &out, "getTokenTransferFeeConfig", destChainSelector, token) if err != nil { - return *new(PriceRegistryTokenTransferFeeConfig), err + return *new(FeeQuoterTokenTransferFeeConfig), err } - out0 := *abi.ConvertType(out[0], new(PriceRegistryTokenTransferFeeConfig)).(*PriceRegistryTokenTransferFeeConfig) + out0 := *abi.ConvertType(out[0], new(FeeQuoterTokenTransferFeeConfig)).(*FeeQuoterTokenTransferFeeConfig) return out0, err } -func (_PriceRegistry *PriceRegistrySession) GetTokenTransferFeeConfig(destChainSelector uint64, token common.Address) (PriceRegistryTokenTransferFeeConfig, error) { - return _PriceRegistry.Contract.GetTokenTransferFeeConfig(&_PriceRegistry.CallOpts, destChainSelector, token) +func (_FeeQuoter *FeeQuoterSession) GetTokenTransferFeeConfig(destChainSelector uint64, token common.Address) (FeeQuoterTokenTransferFeeConfig, error) { + return _FeeQuoter.Contract.GetTokenTransferFeeConfig(&_FeeQuoter.CallOpts, destChainSelector, token) } -func (_PriceRegistry *PriceRegistryCallerSession) GetTokenTransferFeeConfig(destChainSelector uint64, token common.Address) (PriceRegistryTokenTransferFeeConfig, error) { - return _PriceRegistry.Contract.GetTokenTransferFeeConfig(&_PriceRegistry.CallOpts, destChainSelector, token) +func (_FeeQuoter *FeeQuoterCallerSession) GetTokenTransferFeeConfig(destChainSelector uint64, token common.Address) (FeeQuoterTokenTransferFeeConfig, error) { + return _FeeQuoter.Contract.GetTokenTransferFeeConfig(&_FeeQuoter.CallOpts, destChainSelector, token) } -func (_PriceRegistry *PriceRegistryCaller) GetValidatedFee(opts *bind.CallOpts, destChainSelector uint64, message ClientEVM2AnyMessage) (*big.Int, error) { +func (_FeeQuoter *FeeQuoterCaller) GetValidatedFee(opts *bind.CallOpts, destChainSelector uint64, message ClientEVM2AnyMessage) (*big.Int, error) { var out []interface{} - err := _PriceRegistry.contract.Call(opts, &out, "getValidatedFee", destChainSelector, message) + err := _FeeQuoter.contract.Call(opts, &out, "getValidatedFee", destChainSelector, message) if err != nil { return *new(*big.Int), err @@ -580,17 +580,17 @@ func (_PriceRegistry *PriceRegistryCaller) GetValidatedFee(opts *bind.CallOpts, } -func (_PriceRegistry *PriceRegistrySession) GetValidatedFee(destChainSelector uint64, message ClientEVM2AnyMessage) (*big.Int, error) { - return _PriceRegistry.Contract.GetValidatedFee(&_PriceRegistry.CallOpts, destChainSelector, message) +func (_FeeQuoter *FeeQuoterSession) GetValidatedFee(destChainSelector uint64, message ClientEVM2AnyMessage) (*big.Int, error) { + return _FeeQuoter.Contract.GetValidatedFee(&_FeeQuoter.CallOpts, destChainSelector, message) } -func (_PriceRegistry *PriceRegistryCallerSession) GetValidatedFee(destChainSelector uint64, message ClientEVM2AnyMessage) (*big.Int, error) { - return _PriceRegistry.Contract.GetValidatedFee(&_PriceRegistry.CallOpts, destChainSelector, message) +func (_FeeQuoter *FeeQuoterCallerSession) GetValidatedFee(destChainSelector uint64, message ClientEVM2AnyMessage) (*big.Int, error) { + return _FeeQuoter.Contract.GetValidatedFee(&_FeeQuoter.CallOpts, destChainSelector, message) } -func (_PriceRegistry *PriceRegistryCaller) GetValidatedTokenPrice(opts *bind.CallOpts, token common.Address) (*big.Int, error) { +func (_FeeQuoter *FeeQuoterCaller) GetValidatedTokenPrice(opts *bind.CallOpts, token common.Address) (*big.Int, error) { var out []interface{} - err := _PriceRegistry.contract.Call(opts, &out, "getValidatedTokenPrice", token) + err := _FeeQuoter.contract.Call(opts, &out, "getValidatedTokenPrice", token) if err != nil { return *new(*big.Int), err @@ -602,17 +602,17 @@ func (_PriceRegistry *PriceRegistryCaller) GetValidatedTokenPrice(opts *bind.Cal } -func (_PriceRegistry *PriceRegistrySession) GetValidatedTokenPrice(token common.Address) (*big.Int, error) { - return _PriceRegistry.Contract.GetValidatedTokenPrice(&_PriceRegistry.CallOpts, token) +func (_FeeQuoter *FeeQuoterSession) GetValidatedTokenPrice(token common.Address) (*big.Int, error) { + return _FeeQuoter.Contract.GetValidatedTokenPrice(&_FeeQuoter.CallOpts, token) } -func (_PriceRegistry *PriceRegistryCallerSession) GetValidatedTokenPrice(token common.Address) (*big.Int, error) { - return _PriceRegistry.Contract.GetValidatedTokenPrice(&_PriceRegistry.CallOpts, token) +func (_FeeQuoter *FeeQuoterCallerSession) GetValidatedTokenPrice(token common.Address) (*big.Int, error) { + return _FeeQuoter.Contract.GetValidatedTokenPrice(&_FeeQuoter.CallOpts, token) } -func (_PriceRegistry *PriceRegistryCaller) Owner(opts *bind.CallOpts) (common.Address, error) { +func (_FeeQuoter *FeeQuoterCaller) Owner(opts *bind.CallOpts) (common.Address, error) { var out []interface{} - err := _PriceRegistry.contract.Call(opts, &out, "owner") + err := _FeeQuoter.contract.Call(opts, &out, "owner") if err != nil { return *new(common.Address), err @@ -624,19 +624,19 @@ func (_PriceRegistry *PriceRegistryCaller) Owner(opts *bind.CallOpts) (common.Ad } -func (_PriceRegistry *PriceRegistrySession) Owner() (common.Address, error) { - return _PriceRegistry.Contract.Owner(&_PriceRegistry.CallOpts) +func (_FeeQuoter *FeeQuoterSession) Owner() (common.Address, error) { + return _FeeQuoter.Contract.Owner(&_FeeQuoter.CallOpts) } -func (_PriceRegistry *PriceRegistryCallerSession) Owner() (common.Address, error) { - return _PriceRegistry.Contract.Owner(&_PriceRegistry.CallOpts) +func (_FeeQuoter *FeeQuoterCallerSession) Owner() (common.Address, error) { + return _FeeQuoter.Contract.Owner(&_FeeQuoter.CallOpts) } -func (_PriceRegistry *PriceRegistryCaller) ProcessMessageArgs(opts *bind.CallOpts, destChainSelector uint64, feeToken common.Address, feeTokenAmount *big.Int, extraArgs []byte) (ProcessMessageArgs, +func (_FeeQuoter *FeeQuoterCaller) ProcessMessageArgs(opts *bind.CallOpts, destChainSelector uint64, feeToken common.Address, feeTokenAmount *big.Int, extraArgs []byte) (ProcessMessageArgs, error) { var out []interface{} - err := _PriceRegistry.contract.Call(opts, &out, "processMessageArgs", destChainSelector, feeToken, feeTokenAmount, extraArgs) + err := _FeeQuoter.contract.Call(opts, &out, "processMessageArgs", destChainSelector, feeToken, feeTokenAmount, extraArgs) outstruct := new(ProcessMessageArgs) if err != nil { @@ -651,21 +651,21 @@ func (_PriceRegistry *PriceRegistryCaller) ProcessMessageArgs(opts *bind.CallOpt } -func (_PriceRegistry *PriceRegistrySession) ProcessMessageArgs(destChainSelector uint64, feeToken common.Address, feeTokenAmount *big.Int, extraArgs []byte) (ProcessMessageArgs, +func (_FeeQuoter *FeeQuoterSession) ProcessMessageArgs(destChainSelector uint64, feeToken common.Address, feeTokenAmount *big.Int, extraArgs []byte) (ProcessMessageArgs, error) { - return _PriceRegistry.Contract.ProcessMessageArgs(&_PriceRegistry.CallOpts, destChainSelector, feeToken, feeTokenAmount, extraArgs) + return _FeeQuoter.Contract.ProcessMessageArgs(&_FeeQuoter.CallOpts, destChainSelector, feeToken, feeTokenAmount, extraArgs) } -func (_PriceRegistry *PriceRegistryCallerSession) ProcessMessageArgs(destChainSelector uint64, feeToken common.Address, feeTokenAmount *big.Int, extraArgs []byte) (ProcessMessageArgs, +func (_FeeQuoter *FeeQuoterCallerSession) ProcessMessageArgs(destChainSelector uint64, feeToken common.Address, feeTokenAmount *big.Int, extraArgs []byte) (ProcessMessageArgs, error) { - return _PriceRegistry.Contract.ProcessMessageArgs(&_PriceRegistry.CallOpts, destChainSelector, feeToken, feeTokenAmount, extraArgs) + return _FeeQuoter.Contract.ProcessMessageArgs(&_FeeQuoter.CallOpts, destChainSelector, feeToken, feeTokenAmount, extraArgs) } -func (_PriceRegistry *PriceRegistryCaller) ProcessPoolReturnData(opts *bind.CallOpts, destChainSelector uint64, rampTokenAmounts []InternalRampTokenAmount, sourceTokenAmounts []ClientEVMTokenAmount) ([][]byte, error) { +func (_FeeQuoter *FeeQuoterCaller) ProcessPoolReturnData(opts *bind.CallOpts, destChainSelector uint64, rampTokenAmounts []InternalRampTokenAmount, sourceTokenAmounts []ClientEVMTokenAmount) ([][]byte, error) { var out []interface{} - err := _PriceRegistry.contract.Call(opts, &out, "processPoolReturnData", destChainSelector, rampTokenAmounts, sourceTokenAmounts) + err := _FeeQuoter.contract.Call(opts, &out, "processPoolReturnData", destChainSelector, rampTokenAmounts, sourceTokenAmounts) if err != nil { return *new([][]byte), err @@ -677,17 +677,17 @@ func (_PriceRegistry *PriceRegistryCaller) ProcessPoolReturnData(opts *bind.Call } -func (_PriceRegistry *PriceRegistrySession) ProcessPoolReturnData(destChainSelector uint64, rampTokenAmounts []InternalRampTokenAmount, sourceTokenAmounts []ClientEVMTokenAmount) ([][]byte, error) { - return _PriceRegistry.Contract.ProcessPoolReturnData(&_PriceRegistry.CallOpts, destChainSelector, rampTokenAmounts, sourceTokenAmounts) +func (_FeeQuoter *FeeQuoterSession) ProcessPoolReturnData(destChainSelector uint64, rampTokenAmounts []InternalRampTokenAmount, sourceTokenAmounts []ClientEVMTokenAmount) ([][]byte, error) { + return _FeeQuoter.Contract.ProcessPoolReturnData(&_FeeQuoter.CallOpts, destChainSelector, rampTokenAmounts, sourceTokenAmounts) } -func (_PriceRegistry *PriceRegistryCallerSession) ProcessPoolReturnData(destChainSelector uint64, rampTokenAmounts []InternalRampTokenAmount, sourceTokenAmounts []ClientEVMTokenAmount) ([][]byte, error) { - return _PriceRegistry.Contract.ProcessPoolReturnData(&_PriceRegistry.CallOpts, destChainSelector, rampTokenAmounts, sourceTokenAmounts) +func (_FeeQuoter *FeeQuoterCallerSession) ProcessPoolReturnData(destChainSelector uint64, rampTokenAmounts []InternalRampTokenAmount, sourceTokenAmounts []ClientEVMTokenAmount) ([][]byte, error) { + return _FeeQuoter.Contract.ProcessPoolReturnData(&_FeeQuoter.CallOpts, destChainSelector, rampTokenAmounts, sourceTokenAmounts) } -func (_PriceRegistry *PriceRegistryCaller) TypeAndVersion(opts *bind.CallOpts) (string, error) { +func (_FeeQuoter *FeeQuoterCaller) TypeAndVersion(opts *bind.CallOpts) (string, error) { var out []interface{} - err := _PriceRegistry.contract.Call(opts, &out, "typeAndVersion") + err := _FeeQuoter.contract.Call(opts, &out, "typeAndVersion") if err != nil { return *new(string), err @@ -699,148 +699,148 @@ func (_PriceRegistry *PriceRegistryCaller) TypeAndVersion(opts *bind.CallOpts) ( } -func (_PriceRegistry *PriceRegistrySession) TypeAndVersion() (string, error) { - return _PriceRegistry.Contract.TypeAndVersion(&_PriceRegistry.CallOpts) +func (_FeeQuoter *FeeQuoterSession) TypeAndVersion() (string, error) { + return _FeeQuoter.Contract.TypeAndVersion(&_FeeQuoter.CallOpts) } -func (_PriceRegistry *PriceRegistryCallerSession) TypeAndVersion() (string, error) { - return _PriceRegistry.Contract.TypeAndVersion(&_PriceRegistry.CallOpts) +func (_FeeQuoter *FeeQuoterCallerSession) TypeAndVersion() (string, error) { + return _FeeQuoter.Contract.TypeAndVersion(&_FeeQuoter.CallOpts) } -func (_PriceRegistry *PriceRegistryTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { - return _PriceRegistry.contract.Transact(opts, "acceptOwnership") +func (_FeeQuoter *FeeQuoterTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _FeeQuoter.contract.Transact(opts, "acceptOwnership") } -func (_PriceRegistry *PriceRegistrySession) AcceptOwnership() (*types.Transaction, error) { - return _PriceRegistry.Contract.AcceptOwnership(&_PriceRegistry.TransactOpts) +func (_FeeQuoter *FeeQuoterSession) AcceptOwnership() (*types.Transaction, error) { + return _FeeQuoter.Contract.AcceptOwnership(&_FeeQuoter.TransactOpts) } -func (_PriceRegistry *PriceRegistryTransactorSession) AcceptOwnership() (*types.Transaction, error) { - return _PriceRegistry.Contract.AcceptOwnership(&_PriceRegistry.TransactOpts) +func (_FeeQuoter *FeeQuoterTransactorSession) AcceptOwnership() (*types.Transaction, error) { + return _FeeQuoter.Contract.AcceptOwnership(&_FeeQuoter.TransactOpts) } -func (_PriceRegistry *PriceRegistryTransactor) ApplyAuthorizedCallerUpdates(opts *bind.TransactOpts, authorizedCallerArgs AuthorizedCallersAuthorizedCallerArgs) (*types.Transaction, error) { - return _PriceRegistry.contract.Transact(opts, "applyAuthorizedCallerUpdates", authorizedCallerArgs) +func (_FeeQuoter *FeeQuoterTransactor) ApplyAuthorizedCallerUpdates(opts *bind.TransactOpts, authorizedCallerArgs AuthorizedCallersAuthorizedCallerArgs) (*types.Transaction, error) { + return _FeeQuoter.contract.Transact(opts, "applyAuthorizedCallerUpdates", authorizedCallerArgs) } -func (_PriceRegistry *PriceRegistrySession) ApplyAuthorizedCallerUpdates(authorizedCallerArgs AuthorizedCallersAuthorizedCallerArgs) (*types.Transaction, error) { - return _PriceRegistry.Contract.ApplyAuthorizedCallerUpdates(&_PriceRegistry.TransactOpts, authorizedCallerArgs) +func (_FeeQuoter *FeeQuoterSession) ApplyAuthorizedCallerUpdates(authorizedCallerArgs AuthorizedCallersAuthorizedCallerArgs) (*types.Transaction, error) { + return _FeeQuoter.Contract.ApplyAuthorizedCallerUpdates(&_FeeQuoter.TransactOpts, authorizedCallerArgs) } -func (_PriceRegistry *PriceRegistryTransactorSession) ApplyAuthorizedCallerUpdates(authorizedCallerArgs AuthorizedCallersAuthorizedCallerArgs) (*types.Transaction, error) { - return _PriceRegistry.Contract.ApplyAuthorizedCallerUpdates(&_PriceRegistry.TransactOpts, authorizedCallerArgs) +func (_FeeQuoter *FeeQuoterTransactorSession) ApplyAuthorizedCallerUpdates(authorizedCallerArgs AuthorizedCallersAuthorizedCallerArgs) (*types.Transaction, error) { + return _FeeQuoter.Contract.ApplyAuthorizedCallerUpdates(&_FeeQuoter.TransactOpts, authorizedCallerArgs) } -func (_PriceRegistry *PriceRegistryTransactor) ApplyDestChainConfigUpdates(opts *bind.TransactOpts, destChainConfigArgs []PriceRegistryDestChainConfigArgs) (*types.Transaction, error) { - return _PriceRegistry.contract.Transact(opts, "applyDestChainConfigUpdates", destChainConfigArgs) +func (_FeeQuoter *FeeQuoterTransactor) ApplyDestChainConfigUpdates(opts *bind.TransactOpts, destChainConfigArgs []FeeQuoterDestChainConfigArgs) (*types.Transaction, error) { + return _FeeQuoter.contract.Transact(opts, "applyDestChainConfigUpdates", destChainConfigArgs) } -func (_PriceRegistry *PriceRegistrySession) ApplyDestChainConfigUpdates(destChainConfigArgs []PriceRegistryDestChainConfigArgs) (*types.Transaction, error) { - return _PriceRegistry.Contract.ApplyDestChainConfigUpdates(&_PriceRegistry.TransactOpts, destChainConfigArgs) +func (_FeeQuoter *FeeQuoterSession) ApplyDestChainConfigUpdates(destChainConfigArgs []FeeQuoterDestChainConfigArgs) (*types.Transaction, error) { + return _FeeQuoter.Contract.ApplyDestChainConfigUpdates(&_FeeQuoter.TransactOpts, destChainConfigArgs) } -func (_PriceRegistry *PriceRegistryTransactorSession) ApplyDestChainConfigUpdates(destChainConfigArgs []PriceRegistryDestChainConfigArgs) (*types.Transaction, error) { - return _PriceRegistry.Contract.ApplyDestChainConfigUpdates(&_PriceRegistry.TransactOpts, destChainConfigArgs) +func (_FeeQuoter *FeeQuoterTransactorSession) ApplyDestChainConfigUpdates(destChainConfigArgs []FeeQuoterDestChainConfigArgs) (*types.Transaction, error) { + return _FeeQuoter.Contract.ApplyDestChainConfigUpdates(&_FeeQuoter.TransactOpts, destChainConfigArgs) } -func (_PriceRegistry *PriceRegistryTransactor) ApplyFeeTokensUpdates(opts *bind.TransactOpts, feeTokensToAdd []common.Address, feeTokensToRemove []common.Address) (*types.Transaction, error) { - return _PriceRegistry.contract.Transact(opts, "applyFeeTokensUpdates", feeTokensToAdd, feeTokensToRemove) +func (_FeeQuoter *FeeQuoterTransactor) ApplyFeeTokensUpdates(opts *bind.TransactOpts, feeTokensToAdd []common.Address, feeTokensToRemove []common.Address) (*types.Transaction, error) { + return _FeeQuoter.contract.Transact(opts, "applyFeeTokensUpdates", feeTokensToAdd, feeTokensToRemove) } -func (_PriceRegistry *PriceRegistrySession) ApplyFeeTokensUpdates(feeTokensToAdd []common.Address, feeTokensToRemove []common.Address) (*types.Transaction, error) { - return _PriceRegistry.Contract.ApplyFeeTokensUpdates(&_PriceRegistry.TransactOpts, feeTokensToAdd, feeTokensToRemove) +func (_FeeQuoter *FeeQuoterSession) ApplyFeeTokensUpdates(feeTokensToAdd []common.Address, feeTokensToRemove []common.Address) (*types.Transaction, error) { + return _FeeQuoter.Contract.ApplyFeeTokensUpdates(&_FeeQuoter.TransactOpts, feeTokensToAdd, feeTokensToRemove) } -func (_PriceRegistry *PriceRegistryTransactorSession) ApplyFeeTokensUpdates(feeTokensToAdd []common.Address, feeTokensToRemove []common.Address) (*types.Transaction, error) { - return _PriceRegistry.Contract.ApplyFeeTokensUpdates(&_PriceRegistry.TransactOpts, feeTokensToAdd, feeTokensToRemove) +func (_FeeQuoter *FeeQuoterTransactorSession) ApplyFeeTokensUpdates(feeTokensToAdd []common.Address, feeTokensToRemove []common.Address) (*types.Transaction, error) { + return _FeeQuoter.Contract.ApplyFeeTokensUpdates(&_FeeQuoter.TransactOpts, feeTokensToAdd, feeTokensToRemove) } -func (_PriceRegistry *PriceRegistryTransactor) ApplyPremiumMultiplierWeiPerEthUpdates(opts *bind.TransactOpts, premiumMultiplierWeiPerEthArgs []PriceRegistryPremiumMultiplierWeiPerEthArgs) (*types.Transaction, error) { - return _PriceRegistry.contract.Transact(opts, "applyPremiumMultiplierWeiPerEthUpdates", premiumMultiplierWeiPerEthArgs) +func (_FeeQuoter *FeeQuoterTransactor) ApplyPremiumMultiplierWeiPerEthUpdates(opts *bind.TransactOpts, premiumMultiplierWeiPerEthArgs []FeeQuoterPremiumMultiplierWeiPerEthArgs) (*types.Transaction, error) { + return _FeeQuoter.contract.Transact(opts, "applyPremiumMultiplierWeiPerEthUpdates", premiumMultiplierWeiPerEthArgs) } -func (_PriceRegistry *PriceRegistrySession) ApplyPremiumMultiplierWeiPerEthUpdates(premiumMultiplierWeiPerEthArgs []PriceRegistryPremiumMultiplierWeiPerEthArgs) (*types.Transaction, error) { - return _PriceRegistry.Contract.ApplyPremiumMultiplierWeiPerEthUpdates(&_PriceRegistry.TransactOpts, premiumMultiplierWeiPerEthArgs) +func (_FeeQuoter *FeeQuoterSession) ApplyPremiumMultiplierWeiPerEthUpdates(premiumMultiplierWeiPerEthArgs []FeeQuoterPremiumMultiplierWeiPerEthArgs) (*types.Transaction, error) { + return _FeeQuoter.Contract.ApplyPremiumMultiplierWeiPerEthUpdates(&_FeeQuoter.TransactOpts, premiumMultiplierWeiPerEthArgs) } -func (_PriceRegistry *PriceRegistryTransactorSession) ApplyPremiumMultiplierWeiPerEthUpdates(premiumMultiplierWeiPerEthArgs []PriceRegistryPremiumMultiplierWeiPerEthArgs) (*types.Transaction, error) { - return _PriceRegistry.Contract.ApplyPremiumMultiplierWeiPerEthUpdates(&_PriceRegistry.TransactOpts, premiumMultiplierWeiPerEthArgs) +func (_FeeQuoter *FeeQuoterTransactorSession) ApplyPremiumMultiplierWeiPerEthUpdates(premiumMultiplierWeiPerEthArgs []FeeQuoterPremiumMultiplierWeiPerEthArgs) (*types.Transaction, error) { + return _FeeQuoter.Contract.ApplyPremiumMultiplierWeiPerEthUpdates(&_FeeQuoter.TransactOpts, premiumMultiplierWeiPerEthArgs) } -func (_PriceRegistry *PriceRegistryTransactor) ApplyTokenTransferFeeConfigUpdates(opts *bind.TransactOpts, tokenTransferFeeConfigArgs []PriceRegistryTokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs []PriceRegistryTokenTransferFeeConfigRemoveArgs) (*types.Transaction, error) { - return _PriceRegistry.contract.Transact(opts, "applyTokenTransferFeeConfigUpdates", tokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs) +func (_FeeQuoter *FeeQuoterTransactor) ApplyTokenTransferFeeConfigUpdates(opts *bind.TransactOpts, tokenTransferFeeConfigArgs []FeeQuoterTokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs []FeeQuoterTokenTransferFeeConfigRemoveArgs) (*types.Transaction, error) { + return _FeeQuoter.contract.Transact(opts, "applyTokenTransferFeeConfigUpdates", tokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs) } -func (_PriceRegistry *PriceRegistrySession) ApplyTokenTransferFeeConfigUpdates(tokenTransferFeeConfigArgs []PriceRegistryTokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs []PriceRegistryTokenTransferFeeConfigRemoveArgs) (*types.Transaction, error) { - return _PriceRegistry.Contract.ApplyTokenTransferFeeConfigUpdates(&_PriceRegistry.TransactOpts, tokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs) +func (_FeeQuoter *FeeQuoterSession) ApplyTokenTransferFeeConfigUpdates(tokenTransferFeeConfigArgs []FeeQuoterTokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs []FeeQuoterTokenTransferFeeConfigRemoveArgs) (*types.Transaction, error) { + return _FeeQuoter.Contract.ApplyTokenTransferFeeConfigUpdates(&_FeeQuoter.TransactOpts, tokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs) } -func (_PriceRegistry *PriceRegistryTransactorSession) ApplyTokenTransferFeeConfigUpdates(tokenTransferFeeConfigArgs []PriceRegistryTokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs []PriceRegistryTokenTransferFeeConfigRemoveArgs) (*types.Transaction, error) { - return _PriceRegistry.Contract.ApplyTokenTransferFeeConfigUpdates(&_PriceRegistry.TransactOpts, tokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs) +func (_FeeQuoter *FeeQuoterTransactorSession) ApplyTokenTransferFeeConfigUpdates(tokenTransferFeeConfigArgs []FeeQuoterTokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs []FeeQuoterTokenTransferFeeConfigRemoveArgs) (*types.Transaction, error) { + return _FeeQuoter.Contract.ApplyTokenTransferFeeConfigUpdates(&_FeeQuoter.TransactOpts, tokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs) } -func (_PriceRegistry *PriceRegistryTransactor) OnReport(opts *bind.TransactOpts, metadata []byte, report []byte) (*types.Transaction, error) { - return _PriceRegistry.contract.Transact(opts, "onReport", metadata, report) +func (_FeeQuoter *FeeQuoterTransactor) OnReport(opts *bind.TransactOpts, metadata []byte, report []byte) (*types.Transaction, error) { + return _FeeQuoter.contract.Transact(opts, "onReport", metadata, report) } -func (_PriceRegistry *PriceRegistrySession) OnReport(metadata []byte, report []byte) (*types.Transaction, error) { - return _PriceRegistry.Contract.OnReport(&_PriceRegistry.TransactOpts, metadata, report) +func (_FeeQuoter *FeeQuoterSession) OnReport(metadata []byte, report []byte) (*types.Transaction, error) { + return _FeeQuoter.Contract.OnReport(&_FeeQuoter.TransactOpts, metadata, report) } -func (_PriceRegistry *PriceRegistryTransactorSession) OnReport(metadata []byte, report []byte) (*types.Transaction, error) { - return _PriceRegistry.Contract.OnReport(&_PriceRegistry.TransactOpts, metadata, report) +func (_FeeQuoter *FeeQuoterTransactorSession) OnReport(metadata []byte, report []byte) (*types.Transaction, error) { + return _FeeQuoter.Contract.OnReport(&_FeeQuoter.TransactOpts, metadata, report) } -func (_PriceRegistry *PriceRegistryTransactor) SetReportPermissions(opts *bind.TransactOpts, permissions []KeystoneFeedsPermissionHandlerPermission) (*types.Transaction, error) { - return _PriceRegistry.contract.Transact(opts, "setReportPermissions", permissions) +func (_FeeQuoter *FeeQuoterTransactor) SetReportPermissions(opts *bind.TransactOpts, permissions []KeystoneFeedsPermissionHandlerPermission) (*types.Transaction, error) { + return _FeeQuoter.contract.Transact(opts, "setReportPermissions", permissions) } -func (_PriceRegistry *PriceRegistrySession) SetReportPermissions(permissions []KeystoneFeedsPermissionHandlerPermission) (*types.Transaction, error) { - return _PriceRegistry.Contract.SetReportPermissions(&_PriceRegistry.TransactOpts, permissions) +func (_FeeQuoter *FeeQuoterSession) SetReportPermissions(permissions []KeystoneFeedsPermissionHandlerPermission) (*types.Transaction, error) { + return _FeeQuoter.Contract.SetReportPermissions(&_FeeQuoter.TransactOpts, permissions) } -func (_PriceRegistry *PriceRegistryTransactorSession) SetReportPermissions(permissions []KeystoneFeedsPermissionHandlerPermission) (*types.Transaction, error) { - return _PriceRegistry.Contract.SetReportPermissions(&_PriceRegistry.TransactOpts, permissions) +func (_FeeQuoter *FeeQuoterTransactorSession) SetReportPermissions(permissions []KeystoneFeedsPermissionHandlerPermission) (*types.Transaction, error) { + return _FeeQuoter.Contract.SetReportPermissions(&_FeeQuoter.TransactOpts, permissions) } -func (_PriceRegistry *PriceRegistryTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { - return _PriceRegistry.contract.Transact(opts, "transferOwnership", to) +func (_FeeQuoter *FeeQuoterTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { + return _FeeQuoter.contract.Transact(opts, "transferOwnership", to) } -func (_PriceRegistry *PriceRegistrySession) TransferOwnership(to common.Address) (*types.Transaction, error) { - return _PriceRegistry.Contract.TransferOwnership(&_PriceRegistry.TransactOpts, to) +func (_FeeQuoter *FeeQuoterSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _FeeQuoter.Contract.TransferOwnership(&_FeeQuoter.TransactOpts, to) } -func (_PriceRegistry *PriceRegistryTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { - return _PriceRegistry.Contract.TransferOwnership(&_PriceRegistry.TransactOpts, to) +func (_FeeQuoter *FeeQuoterTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _FeeQuoter.Contract.TransferOwnership(&_FeeQuoter.TransactOpts, to) } -func (_PriceRegistry *PriceRegistryTransactor) UpdatePrices(opts *bind.TransactOpts, priceUpdates InternalPriceUpdates) (*types.Transaction, error) { - return _PriceRegistry.contract.Transact(opts, "updatePrices", priceUpdates) +func (_FeeQuoter *FeeQuoterTransactor) UpdatePrices(opts *bind.TransactOpts, priceUpdates InternalPriceUpdates) (*types.Transaction, error) { + return _FeeQuoter.contract.Transact(opts, "updatePrices", priceUpdates) } -func (_PriceRegistry *PriceRegistrySession) UpdatePrices(priceUpdates InternalPriceUpdates) (*types.Transaction, error) { - return _PriceRegistry.Contract.UpdatePrices(&_PriceRegistry.TransactOpts, priceUpdates) +func (_FeeQuoter *FeeQuoterSession) UpdatePrices(priceUpdates InternalPriceUpdates) (*types.Transaction, error) { + return _FeeQuoter.Contract.UpdatePrices(&_FeeQuoter.TransactOpts, priceUpdates) } -func (_PriceRegistry *PriceRegistryTransactorSession) UpdatePrices(priceUpdates InternalPriceUpdates) (*types.Transaction, error) { - return _PriceRegistry.Contract.UpdatePrices(&_PriceRegistry.TransactOpts, priceUpdates) +func (_FeeQuoter *FeeQuoterTransactorSession) UpdatePrices(priceUpdates InternalPriceUpdates) (*types.Transaction, error) { + return _FeeQuoter.Contract.UpdatePrices(&_FeeQuoter.TransactOpts, priceUpdates) } -func (_PriceRegistry *PriceRegistryTransactor) UpdateTokenPriceFeeds(opts *bind.TransactOpts, tokenPriceFeedUpdates []PriceRegistryTokenPriceFeedUpdate) (*types.Transaction, error) { - return _PriceRegistry.contract.Transact(opts, "updateTokenPriceFeeds", tokenPriceFeedUpdates) +func (_FeeQuoter *FeeQuoterTransactor) UpdateTokenPriceFeeds(opts *bind.TransactOpts, tokenPriceFeedUpdates []FeeQuoterTokenPriceFeedUpdate) (*types.Transaction, error) { + return _FeeQuoter.contract.Transact(opts, "updateTokenPriceFeeds", tokenPriceFeedUpdates) } -func (_PriceRegistry *PriceRegistrySession) UpdateTokenPriceFeeds(tokenPriceFeedUpdates []PriceRegistryTokenPriceFeedUpdate) (*types.Transaction, error) { - return _PriceRegistry.Contract.UpdateTokenPriceFeeds(&_PriceRegistry.TransactOpts, tokenPriceFeedUpdates) +func (_FeeQuoter *FeeQuoterSession) UpdateTokenPriceFeeds(tokenPriceFeedUpdates []FeeQuoterTokenPriceFeedUpdate) (*types.Transaction, error) { + return _FeeQuoter.Contract.UpdateTokenPriceFeeds(&_FeeQuoter.TransactOpts, tokenPriceFeedUpdates) } -func (_PriceRegistry *PriceRegistryTransactorSession) UpdateTokenPriceFeeds(tokenPriceFeedUpdates []PriceRegistryTokenPriceFeedUpdate) (*types.Transaction, error) { - return _PriceRegistry.Contract.UpdateTokenPriceFeeds(&_PriceRegistry.TransactOpts, tokenPriceFeedUpdates) +func (_FeeQuoter *FeeQuoterTransactorSession) UpdateTokenPriceFeeds(tokenPriceFeedUpdates []FeeQuoterTokenPriceFeedUpdate) (*types.Transaction, error) { + return _FeeQuoter.Contract.UpdateTokenPriceFeeds(&_FeeQuoter.TransactOpts, tokenPriceFeedUpdates) } -type PriceRegistryAuthorizedCallerAddedIterator struct { - Event *PriceRegistryAuthorizedCallerAdded +type FeeQuoterAuthorizedCallerAddedIterator struct { + Event *FeeQuoterAuthorizedCallerAdded contract *bind.BoundContract event string @@ -851,7 +851,7 @@ type PriceRegistryAuthorizedCallerAddedIterator struct { fail error } -func (it *PriceRegistryAuthorizedCallerAddedIterator) Next() bool { +func (it *FeeQuoterAuthorizedCallerAddedIterator) Next() bool { if it.fail != nil { return false @@ -860,7 +860,7 @@ func (it *PriceRegistryAuthorizedCallerAddedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(PriceRegistryAuthorizedCallerAdded) + it.Event = new(FeeQuoterAuthorizedCallerAdded) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -875,7 +875,7 @@ func (it *PriceRegistryAuthorizedCallerAddedIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(PriceRegistryAuthorizedCallerAdded) + it.Event = new(FeeQuoterAuthorizedCallerAdded) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -890,32 +890,32 @@ func (it *PriceRegistryAuthorizedCallerAddedIterator) Next() bool { } } -func (it *PriceRegistryAuthorizedCallerAddedIterator) Error() error { +func (it *FeeQuoterAuthorizedCallerAddedIterator) Error() error { return it.fail } -func (it *PriceRegistryAuthorizedCallerAddedIterator) Close() error { +func (it *FeeQuoterAuthorizedCallerAddedIterator) Close() error { it.sub.Unsubscribe() return nil } -type PriceRegistryAuthorizedCallerAdded struct { +type FeeQuoterAuthorizedCallerAdded struct { Caller common.Address Raw types.Log } -func (_PriceRegistry *PriceRegistryFilterer) FilterAuthorizedCallerAdded(opts *bind.FilterOpts) (*PriceRegistryAuthorizedCallerAddedIterator, error) { +func (_FeeQuoter *FeeQuoterFilterer) FilterAuthorizedCallerAdded(opts *bind.FilterOpts) (*FeeQuoterAuthorizedCallerAddedIterator, error) { - logs, sub, err := _PriceRegistry.contract.FilterLogs(opts, "AuthorizedCallerAdded") + logs, sub, err := _FeeQuoter.contract.FilterLogs(opts, "AuthorizedCallerAdded") if err != nil { return nil, err } - return &PriceRegistryAuthorizedCallerAddedIterator{contract: _PriceRegistry.contract, event: "AuthorizedCallerAdded", logs: logs, sub: sub}, nil + return &FeeQuoterAuthorizedCallerAddedIterator{contract: _FeeQuoter.contract, event: "AuthorizedCallerAdded", logs: logs, sub: sub}, nil } -func (_PriceRegistry *PriceRegistryFilterer) WatchAuthorizedCallerAdded(opts *bind.WatchOpts, sink chan<- *PriceRegistryAuthorizedCallerAdded) (event.Subscription, error) { +func (_FeeQuoter *FeeQuoterFilterer) WatchAuthorizedCallerAdded(opts *bind.WatchOpts, sink chan<- *FeeQuoterAuthorizedCallerAdded) (event.Subscription, error) { - logs, sub, err := _PriceRegistry.contract.WatchLogs(opts, "AuthorizedCallerAdded") + logs, sub, err := _FeeQuoter.contract.WatchLogs(opts, "AuthorizedCallerAdded") if err != nil { return nil, err } @@ -925,8 +925,8 @@ func (_PriceRegistry *PriceRegistryFilterer) WatchAuthorizedCallerAdded(opts *bi select { case log := <-logs: - event := new(PriceRegistryAuthorizedCallerAdded) - if err := _PriceRegistry.contract.UnpackLog(event, "AuthorizedCallerAdded", log); err != nil { + event := new(FeeQuoterAuthorizedCallerAdded) + if err := _FeeQuoter.contract.UnpackLog(event, "AuthorizedCallerAdded", log); err != nil { return err } event.Raw = log @@ -947,17 +947,17 @@ func (_PriceRegistry *PriceRegistryFilterer) WatchAuthorizedCallerAdded(opts *bi }), nil } -func (_PriceRegistry *PriceRegistryFilterer) ParseAuthorizedCallerAdded(log types.Log) (*PriceRegistryAuthorizedCallerAdded, error) { - event := new(PriceRegistryAuthorizedCallerAdded) - if err := _PriceRegistry.contract.UnpackLog(event, "AuthorizedCallerAdded", log); err != nil { +func (_FeeQuoter *FeeQuoterFilterer) ParseAuthorizedCallerAdded(log types.Log) (*FeeQuoterAuthorizedCallerAdded, error) { + event := new(FeeQuoterAuthorizedCallerAdded) + if err := _FeeQuoter.contract.UnpackLog(event, "AuthorizedCallerAdded", log); err != nil { return nil, err } event.Raw = log return event, nil } -type PriceRegistryAuthorizedCallerRemovedIterator struct { - Event *PriceRegistryAuthorizedCallerRemoved +type FeeQuoterAuthorizedCallerRemovedIterator struct { + Event *FeeQuoterAuthorizedCallerRemoved contract *bind.BoundContract event string @@ -968,7 +968,7 @@ type PriceRegistryAuthorizedCallerRemovedIterator struct { fail error } -func (it *PriceRegistryAuthorizedCallerRemovedIterator) Next() bool { +func (it *FeeQuoterAuthorizedCallerRemovedIterator) Next() bool { if it.fail != nil { return false @@ -977,7 +977,7 @@ func (it *PriceRegistryAuthorizedCallerRemovedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(PriceRegistryAuthorizedCallerRemoved) + it.Event = new(FeeQuoterAuthorizedCallerRemoved) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -992,7 +992,7 @@ func (it *PriceRegistryAuthorizedCallerRemovedIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(PriceRegistryAuthorizedCallerRemoved) + it.Event = new(FeeQuoterAuthorizedCallerRemoved) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1007,32 +1007,32 @@ func (it *PriceRegistryAuthorizedCallerRemovedIterator) Next() bool { } } -func (it *PriceRegistryAuthorizedCallerRemovedIterator) Error() error { +func (it *FeeQuoterAuthorizedCallerRemovedIterator) Error() error { return it.fail } -func (it *PriceRegistryAuthorizedCallerRemovedIterator) Close() error { +func (it *FeeQuoterAuthorizedCallerRemovedIterator) Close() error { it.sub.Unsubscribe() return nil } -type PriceRegistryAuthorizedCallerRemoved struct { +type FeeQuoterAuthorizedCallerRemoved struct { Caller common.Address Raw types.Log } -func (_PriceRegistry *PriceRegistryFilterer) FilterAuthorizedCallerRemoved(opts *bind.FilterOpts) (*PriceRegistryAuthorizedCallerRemovedIterator, error) { +func (_FeeQuoter *FeeQuoterFilterer) FilterAuthorizedCallerRemoved(opts *bind.FilterOpts) (*FeeQuoterAuthorizedCallerRemovedIterator, error) { - logs, sub, err := _PriceRegistry.contract.FilterLogs(opts, "AuthorizedCallerRemoved") + logs, sub, err := _FeeQuoter.contract.FilterLogs(opts, "AuthorizedCallerRemoved") if err != nil { return nil, err } - return &PriceRegistryAuthorizedCallerRemovedIterator{contract: _PriceRegistry.contract, event: "AuthorizedCallerRemoved", logs: logs, sub: sub}, nil + return &FeeQuoterAuthorizedCallerRemovedIterator{contract: _FeeQuoter.contract, event: "AuthorizedCallerRemoved", logs: logs, sub: sub}, nil } -func (_PriceRegistry *PriceRegistryFilterer) WatchAuthorizedCallerRemoved(opts *bind.WatchOpts, sink chan<- *PriceRegistryAuthorizedCallerRemoved) (event.Subscription, error) { +func (_FeeQuoter *FeeQuoterFilterer) WatchAuthorizedCallerRemoved(opts *bind.WatchOpts, sink chan<- *FeeQuoterAuthorizedCallerRemoved) (event.Subscription, error) { - logs, sub, err := _PriceRegistry.contract.WatchLogs(opts, "AuthorizedCallerRemoved") + logs, sub, err := _FeeQuoter.contract.WatchLogs(opts, "AuthorizedCallerRemoved") if err != nil { return nil, err } @@ -1042,8 +1042,8 @@ func (_PriceRegistry *PriceRegistryFilterer) WatchAuthorizedCallerRemoved(opts * select { case log := <-logs: - event := new(PriceRegistryAuthorizedCallerRemoved) - if err := _PriceRegistry.contract.UnpackLog(event, "AuthorizedCallerRemoved", log); err != nil { + event := new(FeeQuoterAuthorizedCallerRemoved) + if err := _FeeQuoter.contract.UnpackLog(event, "AuthorizedCallerRemoved", log); err != nil { return err } event.Raw = log @@ -1064,17 +1064,17 @@ func (_PriceRegistry *PriceRegistryFilterer) WatchAuthorizedCallerRemoved(opts * }), nil } -func (_PriceRegistry *PriceRegistryFilterer) ParseAuthorizedCallerRemoved(log types.Log) (*PriceRegistryAuthorizedCallerRemoved, error) { - event := new(PriceRegistryAuthorizedCallerRemoved) - if err := _PriceRegistry.contract.UnpackLog(event, "AuthorizedCallerRemoved", log); err != nil { +func (_FeeQuoter *FeeQuoterFilterer) ParseAuthorizedCallerRemoved(log types.Log) (*FeeQuoterAuthorizedCallerRemoved, error) { + event := new(FeeQuoterAuthorizedCallerRemoved) + if err := _FeeQuoter.contract.UnpackLog(event, "AuthorizedCallerRemoved", log); err != nil { return nil, err } event.Raw = log return event, nil } -type PriceRegistryDestChainAddedIterator struct { - Event *PriceRegistryDestChainAdded +type FeeQuoterDestChainAddedIterator struct { + Event *FeeQuoterDestChainAdded contract *bind.BoundContract event string @@ -1085,7 +1085,7 @@ type PriceRegistryDestChainAddedIterator struct { fail error } -func (it *PriceRegistryDestChainAddedIterator) Next() bool { +func (it *FeeQuoterDestChainAddedIterator) Next() bool { if it.fail != nil { return false @@ -1094,7 +1094,7 @@ func (it *PriceRegistryDestChainAddedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(PriceRegistryDestChainAdded) + it.Event = new(FeeQuoterDestChainAdded) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1109,7 +1109,7 @@ func (it *PriceRegistryDestChainAddedIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(PriceRegistryDestChainAdded) + it.Event = new(FeeQuoterDestChainAdded) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1124,43 +1124,43 @@ func (it *PriceRegistryDestChainAddedIterator) Next() bool { } } -func (it *PriceRegistryDestChainAddedIterator) Error() error { +func (it *FeeQuoterDestChainAddedIterator) Error() error { return it.fail } -func (it *PriceRegistryDestChainAddedIterator) Close() error { +func (it *FeeQuoterDestChainAddedIterator) Close() error { it.sub.Unsubscribe() return nil } -type PriceRegistryDestChainAdded struct { +type FeeQuoterDestChainAdded struct { DestChainSelector uint64 - DestChainConfig PriceRegistryDestChainConfig + DestChainConfig FeeQuoterDestChainConfig Raw types.Log } -func (_PriceRegistry *PriceRegistryFilterer) FilterDestChainAdded(opts *bind.FilterOpts, destChainSelector []uint64) (*PriceRegistryDestChainAddedIterator, error) { +func (_FeeQuoter *FeeQuoterFilterer) FilterDestChainAdded(opts *bind.FilterOpts, destChainSelector []uint64) (*FeeQuoterDestChainAddedIterator, error) { var destChainSelectorRule []interface{} for _, destChainSelectorItem := range destChainSelector { destChainSelectorRule = append(destChainSelectorRule, destChainSelectorItem) } - logs, sub, err := _PriceRegistry.contract.FilterLogs(opts, "DestChainAdded", destChainSelectorRule) + logs, sub, err := _FeeQuoter.contract.FilterLogs(opts, "DestChainAdded", destChainSelectorRule) if err != nil { return nil, err } - return &PriceRegistryDestChainAddedIterator{contract: _PriceRegistry.contract, event: "DestChainAdded", logs: logs, sub: sub}, nil + return &FeeQuoterDestChainAddedIterator{contract: _FeeQuoter.contract, event: "DestChainAdded", logs: logs, sub: sub}, nil } -func (_PriceRegistry *PriceRegistryFilterer) WatchDestChainAdded(opts *bind.WatchOpts, sink chan<- *PriceRegistryDestChainAdded, destChainSelector []uint64) (event.Subscription, error) { +func (_FeeQuoter *FeeQuoterFilterer) WatchDestChainAdded(opts *bind.WatchOpts, sink chan<- *FeeQuoterDestChainAdded, destChainSelector []uint64) (event.Subscription, error) { var destChainSelectorRule []interface{} for _, destChainSelectorItem := range destChainSelector { destChainSelectorRule = append(destChainSelectorRule, destChainSelectorItem) } - logs, sub, err := _PriceRegistry.contract.WatchLogs(opts, "DestChainAdded", destChainSelectorRule) + logs, sub, err := _FeeQuoter.contract.WatchLogs(opts, "DestChainAdded", destChainSelectorRule) if err != nil { return nil, err } @@ -1170,8 +1170,8 @@ func (_PriceRegistry *PriceRegistryFilterer) WatchDestChainAdded(opts *bind.Watc select { case log := <-logs: - event := new(PriceRegistryDestChainAdded) - if err := _PriceRegistry.contract.UnpackLog(event, "DestChainAdded", log); err != nil { + event := new(FeeQuoterDestChainAdded) + if err := _FeeQuoter.contract.UnpackLog(event, "DestChainAdded", log); err != nil { return err } event.Raw = log @@ -1192,17 +1192,17 @@ func (_PriceRegistry *PriceRegistryFilterer) WatchDestChainAdded(opts *bind.Watc }), nil } -func (_PriceRegistry *PriceRegistryFilterer) ParseDestChainAdded(log types.Log) (*PriceRegistryDestChainAdded, error) { - event := new(PriceRegistryDestChainAdded) - if err := _PriceRegistry.contract.UnpackLog(event, "DestChainAdded", log); err != nil { +func (_FeeQuoter *FeeQuoterFilterer) ParseDestChainAdded(log types.Log) (*FeeQuoterDestChainAdded, error) { + event := new(FeeQuoterDestChainAdded) + if err := _FeeQuoter.contract.UnpackLog(event, "DestChainAdded", log); err != nil { return nil, err } event.Raw = log return event, nil } -type PriceRegistryDestChainConfigUpdatedIterator struct { - Event *PriceRegistryDestChainConfigUpdated +type FeeQuoterDestChainConfigUpdatedIterator struct { + Event *FeeQuoterDestChainConfigUpdated contract *bind.BoundContract event string @@ -1213,7 +1213,7 @@ type PriceRegistryDestChainConfigUpdatedIterator struct { fail error } -func (it *PriceRegistryDestChainConfigUpdatedIterator) Next() bool { +func (it *FeeQuoterDestChainConfigUpdatedIterator) Next() bool { if it.fail != nil { return false @@ -1222,7 +1222,7 @@ func (it *PriceRegistryDestChainConfigUpdatedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(PriceRegistryDestChainConfigUpdated) + it.Event = new(FeeQuoterDestChainConfigUpdated) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1237,7 +1237,7 @@ func (it *PriceRegistryDestChainConfigUpdatedIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(PriceRegistryDestChainConfigUpdated) + it.Event = new(FeeQuoterDestChainConfigUpdated) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1252,43 +1252,43 @@ func (it *PriceRegistryDestChainConfigUpdatedIterator) Next() bool { } } -func (it *PriceRegistryDestChainConfigUpdatedIterator) Error() error { +func (it *FeeQuoterDestChainConfigUpdatedIterator) Error() error { return it.fail } -func (it *PriceRegistryDestChainConfigUpdatedIterator) Close() error { +func (it *FeeQuoterDestChainConfigUpdatedIterator) Close() error { it.sub.Unsubscribe() return nil } -type PriceRegistryDestChainConfigUpdated struct { +type FeeQuoterDestChainConfigUpdated struct { DestChainSelector uint64 - DestChainConfig PriceRegistryDestChainConfig + DestChainConfig FeeQuoterDestChainConfig Raw types.Log } -func (_PriceRegistry *PriceRegistryFilterer) FilterDestChainConfigUpdated(opts *bind.FilterOpts, destChainSelector []uint64) (*PriceRegistryDestChainConfigUpdatedIterator, error) { +func (_FeeQuoter *FeeQuoterFilterer) FilterDestChainConfigUpdated(opts *bind.FilterOpts, destChainSelector []uint64) (*FeeQuoterDestChainConfigUpdatedIterator, error) { var destChainSelectorRule []interface{} for _, destChainSelectorItem := range destChainSelector { destChainSelectorRule = append(destChainSelectorRule, destChainSelectorItem) } - logs, sub, err := _PriceRegistry.contract.FilterLogs(opts, "DestChainConfigUpdated", destChainSelectorRule) + logs, sub, err := _FeeQuoter.contract.FilterLogs(opts, "DestChainConfigUpdated", destChainSelectorRule) if err != nil { return nil, err } - return &PriceRegistryDestChainConfigUpdatedIterator{contract: _PriceRegistry.contract, event: "DestChainConfigUpdated", logs: logs, sub: sub}, nil + return &FeeQuoterDestChainConfigUpdatedIterator{contract: _FeeQuoter.contract, event: "DestChainConfigUpdated", logs: logs, sub: sub}, nil } -func (_PriceRegistry *PriceRegistryFilterer) WatchDestChainConfigUpdated(opts *bind.WatchOpts, sink chan<- *PriceRegistryDestChainConfigUpdated, destChainSelector []uint64) (event.Subscription, error) { +func (_FeeQuoter *FeeQuoterFilterer) WatchDestChainConfigUpdated(opts *bind.WatchOpts, sink chan<- *FeeQuoterDestChainConfigUpdated, destChainSelector []uint64) (event.Subscription, error) { var destChainSelectorRule []interface{} for _, destChainSelectorItem := range destChainSelector { destChainSelectorRule = append(destChainSelectorRule, destChainSelectorItem) } - logs, sub, err := _PriceRegistry.contract.WatchLogs(opts, "DestChainConfigUpdated", destChainSelectorRule) + logs, sub, err := _FeeQuoter.contract.WatchLogs(opts, "DestChainConfigUpdated", destChainSelectorRule) if err != nil { return nil, err } @@ -1298,8 +1298,8 @@ func (_PriceRegistry *PriceRegistryFilterer) WatchDestChainConfigUpdated(opts *b select { case log := <-logs: - event := new(PriceRegistryDestChainConfigUpdated) - if err := _PriceRegistry.contract.UnpackLog(event, "DestChainConfigUpdated", log); err != nil { + event := new(FeeQuoterDestChainConfigUpdated) + if err := _FeeQuoter.contract.UnpackLog(event, "DestChainConfigUpdated", log); err != nil { return err } event.Raw = log @@ -1320,17 +1320,17 @@ func (_PriceRegistry *PriceRegistryFilterer) WatchDestChainConfigUpdated(opts *b }), nil } -func (_PriceRegistry *PriceRegistryFilterer) ParseDestChainConfigUpdated(log types.Log) (*PriceRegistryDestChainConfigUpdated, error) { - event := new(PriceRegistryDestChainConfigUpdated) - if err := _PriceRegistry.contract.UnpackLog(event, "DestChainConfigUpdated", log); err != nil { +func (_FeeQuoter *FeeQuoterFilterer) ParseDestChainConfigUpdated(log types.Log) (*FeeQuoterDestChainConfigUpdated, error) { + event := new(FeeQuoterDestChainConfigUpdated) + if err := _FeeQuoter.contract.UnpackLog(event, "DestChainConfigUpdated", log); err != nil { return nil, err } event.Raw = log return event, nil } -type PriceRegistryFeeTokenAddedIterator struct { - Event *PriceRegistryFeeTokenAdded +type FeeQuoterFeeTokenAddedIterator struct { + Event *FeeQuoterFeeTokenAdded contract *bind.BoundContract event string @@ -1341,7 +1341,7 @@ type PriceRegistryFeeTokenAddedIterator struct { fail error } -func (it *PriceRegistryFeeTokenAddedIterator) Next() bool { +func (it *FeeQuoterFeeTokenAddedIterator) Next() bool { if it.fail != nil { return false @@ -1350,7 +1350,7 @@ func (it *PriceRegistryFeeTokenAddedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(PriceRegistryFeeTokenAdded) + it.Event = new(FeeQuoterFeeTokenAdded) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1365,7 +1365,7 @@ func (it *PriceRegistryFeeTokenAddedIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(PriceRegistryFeeTokenAdded) + it.Event = new(FeeQuoterFeeTokenAdded) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1380,42 +1380,42 @@ func (it *PriceRegistryFeeTokenAddedIterator) Next() bool { } } -func (it *PriceRegistryFeeTokenAddedIterator) Error() error { +func (it *FeeQuoterFeeTokenAddedIterator) Error() error { return it.fail } -func (it *PriceRegistryFeeTokenAddedIterator) Close() error { +func (it *FeeQuoterFeeTokenAddedIterator) Close() error { it.sub.Unsubscribe() return nil } -type PriceRegistryFeeTokenAdded struct { +type FeeQuoterFeeTokenAdded struct { FeeToken common.Address Raw types.Log } -func (_PriceRegistry *PriceRegistryFilterer) FilterFeeTokenAdded(opts *bind.FilterOpts, feeToken []common.Address) (*PriceRegistryFeeTokenAddedIterator, error) { +func (_FeeQuoter *FeeQuoterFilterer) FilterFeeTokenAdded(opts *bind.FilterOpts, feeToken []common.Address) (*FeeQuoterFeeTokenAddedIterator, error) { var feeTokenRule []interface{} for _, feeTokenItem := range feeToken { feeTokenRule = append(feeTokenRule, feeTokenItem) } - logs, sub, err := _PriceRegistry.contract.FilterLogs(opts, "FeeTokenAdded", feeTokenRule) + logs, sub, err := _FeeQuoter.contract.FilterLogs(opts, "FeeTokenAdded", feeTokenRule) if err != nil { return nil, err } - return &PriceRegistryFeeTokenAddedIterator{contract: _PriceRegistry.contract, event: "FeeTokenAdded", logs: logs, sub: sub}, nil + return &FeeQuoterFeeTokenAddedIterator{contract: _FeeQuoter.contract, event: "FeeTokenAdded", logs: logs, sub: sub}, nil } -func (_PriceRegistry *PriceRegistryFilterer) WatchFeeTokenAdded(opts *bind.WatchOpts, sink chan<- *PriceRegistryFeeTokenAdded, feeToken []common.Address) (event.Subscription, error) { +func (_FeeQuoter *FeeQuoterFilterer) WatchFeeTokenAdded(opts *bind.WatchOpts, sink chan<- *FeeQuoterFeeTokenAdded, feeToken []common.Address) (event.Subscription, error) { var feeTokenRule []interface{} for _, feeTokenItem := range feeToken { feeTokenRule = append(feeTokenRule, feeTokenItem) } - logs, sub, err := _PriceRegistry.contract.WatchLogs(opts, "FeeTokenAdded", feeTokenRule) + logs, sub, err := _FeeQuoter.contract.WatchLogs(opts, "FeeTokenAdded", feeTokenRule) if err != nil { return nil, err } @@ -1425,8 +1425,8 @@ func (_PriceRegistry *PriceRegistryFilterer) WatchFeeTokenAdded(opts *bind.Watch select { case log := <-logs: - event := new(PriceRegistryFeeTokenAdded) - if err := _PriceRegistry.contract.UnpackLog(event, "FeeTokenAdded", log); err != nil { + event := new(FeeQuoterFeeTokenAdded) + if err := _FeeQuoter.contract.UnpackLog(event, "FeeTokenAdded", log); err != nil { return err } event.Raw = log @@ -1447,17 +1447,17 @@ func (_PriceRegistry *PriceRegistryFilterer) WatchFeeTokenAdded(opts *bind.Watch }), nil } -func (_PriceRegistry *PriceRegistryFilterer) ParseFeeTokenAdded(log types.Log) (*PriceRegistryFeeTokenAdded, error) { - event := new(PriceRegistryFeeTokenAdded) - if err := _PriceRegistry.contract.UnpackLog(event, "FeeTokenAdded", log); err != nil { +func (_FeeQuoter *FeeQuoterFilterer) ParseFeeTokenAdded(log types.Log) (*FeeQuoterFeeTokenAdded, error) { + event := new(FeeQuoterFeeTokenAdded) + if err := _FeeQuoter.contract.UnpackLog(event, "FeeTokenAdded", log); err != nil { return nil, err } event.Raw = log return event, nil } -type PriceRegistryFeeTokenRemovedIterator struct { - Event *PriceRegistryFeeTokenRemoved +type FeeQuoterFeeTokenRemovedIterator struct { + Event *FeeQuoterFeeTokenRemoved contract *bind.BoundContract event string @@ -1468,7 +1468,7 @@ type PriceRegistryFeeTokenRemovedIterator struct { fail error } -func (it *PriceRegistryFeeTokenRemovedIterator) Next() bool { +func (it *FeeQuoterFeeTokenRemovedIterator) Next() bool { if it.fail != nil { return false @@ -1477,7 +1477,7 @@ func (it *PriceRegistryFeeTokenRemovedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(PriceRegistryFeeTokenRemoved) + it.Event = new(FeeQuoterFeeTokenRemoved) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1492,7 +1492,7 @@ func (it *PriceRegistryFeeTokenRemovedIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(PriceRegistryFeeTokenRemoved) + it.Event = new(FeeQuoterFeeTokenRemoved) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1507,42 +1507,42 @@ func (it *PriceRegistryFeeTokenRemovedIterator) Next() bool { } } -func (it *PriceRegistryFeeTokenRemovedIterator) Error() error { +func (it *FeeQuoterFeeTokenRemovedIterator) Error() error { return it.fail } -func (it *PriceRegistryFeeTokenRemovedIterator) Close() error { +func (it *FeeQuoterFeeTokenRemovedIterator) Close() error { it.sub.Unsubscribe() return nil } -type PriceRegistryFeeTokenRemoved struct { +type FeeQuoterFeeTokenRemoved struct { FeeToken common.Address Raw types.Log } -func (_PriceRegistry *PriceRegistryFilterer) FilterFeeTokenRemoved(opts *bind.FilterOpts, feeToken []common.Address) (*PriceRegistryFeeTokenRemovedIterator, error) { +func (_FeeQuoter *FeeQuoterFilterer) FilterFeeTokenRemoved(opts *bind.FilterOpts, feeToken []common.Address) (*FeeQuoterFeeTokenRemovedIterator, error) { var feeTokenRule []interface{} for _, feeTokenItem := range feeToken { feeTokenRule = append(feeTokenRule, feeTokenItem) } - logs, sub, err := _PriceRegistry.contract.FilterLogs(opts, "FeeTokenRemoved", feeTokenRule) + logs, sub, err := _FeeQuoter.contract.FilterLogs(opts, "FeeTokenRemoved", feeTokenRule) if err != nil { return nil, err } - return &PriceRegistryFeeTokenRemovedIterator{contract: _PriceRegistry.contract, event: "FeeTokenRemoved", logs: logs, sub: sub}, nil + return &FeeQuoterFeeTokenRemovedIterator{contract: _FeeQuoter.contract, event: "FeeTokenRemoved", logs: logs, sub: sub}, nil } -func (_PriceRegistry *PriceRegistryFilterer) WatchFeeTokenRemoved(opts *bind.WatchOpts, sink chan<- *PriceRegistryFeeTokenRemoved, feeToken []common.Address) (event.Subscription, error) { +func (_FeeQuoter *FeeQuoterFilterer) WatchFeeTokenRemoved(opts *bind.WatchOpts, sink chan<- *FeeQuoterFeeTokenRemoved, feeToken []common.Address) (event.Subscription, error) { var feeTokenRule []interface{} for _, feeTokenItem := range feeToken { feeTokenRule = append(feeTokenRule, feeTokenItem) } - logs, sub, err := _PriceRegistry.contract.WatchLogs(opts, "FeeTokenRemoved", feeTokenRule) + logs, sub, err := _FeeQuoter.contract.WatchLogs(opts, "FeeTokenRemoved", feeTokenRule) if err != nil { return nil, err } @@ -1552,8 +1552,8 @@ func (_PriceRegistry *PriceRegistryFilterer) WatchFeeTokenRemoved(opts *bind.Wat select { case log := <-logs: - event := new(PriceRegistryFeeTokenRemoved) - if err := _PriceRegistry.contract.UnpackLog(event, "FeeTokenRemoved", log); err != nil { + event := new(FeeQuoterFeeTokenRemoved) + if err := _FeeQuoter.contract.UnpackLog(event, "FeeTokenRemoved", log); err != nil { return err } event.Raw = log @@ -1574,17 +1574,17 @@ func (_PriceRegistry *PriceRegistryFilterer) WatchFeeTokenRemoved(opts *bind.Wat }), nil } -func (_PriceRegistry *PriceRegistryFilterer) ParseFeeTokenRemoved(log types.Log) (*PriceRegistryFeeTokenRemoved, error) { - event := new(PriceRegistryFeeTokenRemoved) - if err := _PriceRegistry.contract.UnpackLog(event, "FeeTokenRemoved", log); err != nil { +func (_FeeQuoter *FeeQuoterFilterer) ParseFeeTokenRemoved(log types.Log) (*FeeQuoterFeeTokenRemoved, error) { + event := new(FeeQuoterFeeTokenRemoved) + if err := _FeeQuoter.contract.UnpackLog(event, "FeeTokenRemoved", log); err != nil { return nil, err } event.Raw = log return event, nil } -type PriceRegistryOwnershipTransferRequestedIterator struct { - Event *PriceRegistryOwnershipTransferRequested +type FeeQuoterOwnershipTransferRequestedIterator struct { + Event *FeeQuoterOwnershipTransferRequested contract *bind.BoundContract event string @@ -1595,7 +1595,7 @@ type PriceRegistryOwnershipTransferRequestedIterator struct { fail error } -func (it *PriceRegistryOwnershipTransferRequestedIterator) Next() bool { +func (it *FeeQuoterOwnershipTransferRequestedIterator) Next() bool { if it.fail != nil { return false @@ -1604,7 +1604,7 @@ func (it *PriceRegistryOwnershipTransferRequestedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(PriceRegistryOwnershipTransferRequested) + it.Event = new(FeeQuoterOwnershipTransferRequested) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1619,7 +1619,7 @@ func (it *PriceRegistryOwnershipTransferRequestedIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(PriceRegistryOwnershipTransferRequested) + it.Event = new(FeeQuoterOwnershipTransferRequested) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1634,22 +1634,22 @@ func (it *PriceRegistryOwnershipTransferRequestedIterator) Next() bool { } } -func (it *PriceRegistryOwnershipTransferRequestedIterator) Error() error { +func (it *FeeQuoterOwnershipTransferRequestedIterator) Error() error { return it.fail } -func (it *PriceRegistryOwnershipTransferRequestedIterator) Close() error { +func (it *FeeQuoterOwnershipTransferRequestedIterator) Close() error { it.sub.Unsubscribe() return nil } -type PriceRegistryOwnershipTransferRequested struct { +type FeeQuoterOwnershipTransferRequested struct { From common.Address To common.Address Raw types.Log } -func (_PriceRegistry *PriceRegistryFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*PriceRegistryOwnershipTransferRequestedIterator, error) { +func (_FeeQuoter *FeeQuoterFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*FeeQuoterOwnershipTransferRequestedIterator, error) { var fromRule []interface{} for _, fromItem := range from { @@ -1660,14 +1660,14 @@ func (_PriceRegistry *PriceRegistryFilterer) FilterOwnershipTransferRequested(op toRule = append(toRule, toItem) } - logs, sub, err := _PriceRegistry.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + logs, sub, err := _FeeQuoter.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) if err != nil { return nil, err } - return &PriceRegistryOwnershipTransferRequestedIterator{contract: _PriceRegistry.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil + return &FeeQuoterOwnershipTransferRequestedIterator{contract: _FeeQuoter.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil } -func (_PriceRegistry *PriceRegistryFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *PriceRegistryOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) { +func (_FeeQuoter *FeeQuoterFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *FeeQuoterOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) { var fromRule []interface{} for _, fromItem := range from { @@ -1678,7 +1678,7 @@ func (_PriceRegistry *PriceRegistryFilterer) WatchOwnershipTransferRequested(opt toRule = append(toRule, toItem) } - logs, sub, err := _PriceRegistry.contract.WatchLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + logs, sub, err := _FeeQuoter.contract.WatchLogs(opts, "OwnershipTransferRequested", fromRule, toRule) if err != nil { return nil, err } @@ -1688,8 +1688,8 @@ func (_PriceRegistry *PriceRegistryFilterer) WatchOwnershipTransferRequested(opt select { case log := <-logs: - event := new(PriceRegistryOwnershipTransferRequested) - if err := _PriceRegistry.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + event := new(FeeQuoterOwnershipTransferRequested) + if err := _FeeQuoter.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { return err } event.Raw = log @@ -1710,17 +1710,17 @@ func (_PriceRegistry *PriceRegistryFilterer) WatchOwnershipTransferRequested(opt }), nil } -func (_PriceRegistry *PriceRegistryFilterer) ParseOwnershipTransferRequested(log types.Log) (*PriceRegistryOwnershipTransferRequested, error) { - event := new(PriceRegistryOwnershipTransferRequested) - if err := _PriceRegistry.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { +func (_FeeQuoter *FeeQuoterFilterer) ParseOwnershipTransferRequested(log types.Log) (*FeeQuoterOwnershipTransferRequested, error) { + event := new(FeeQuoterOwnershipTransferRequested) + if err := _FeeQuoter.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { return nil, err } event.Raw = log return event, nil } -type PriceRegistryOwnershipTransferredIterator struct { - Event *PriceRegistryOwnershipTransferred +type FeeQuoterOwnershipTransferredIterator struct { + Event *FeeQuoterOwnershipTransferred contract *bind.BoundContract event string @@ -1731,7 +1731,7 @@ type PriceRegistryOwnershipTransferredIterator struct { fail error } -func (it *PriceRegistryOwnershipTransferredIterator) Next() bool { +func (it *FeeQuoterOwnershipTransferredIterator) Next() bool { if it.fail != nil { return false @@ -1740,7 +1740,7 @@ func (it *PriceRegistryOwnershipTransferredIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(PriceRegistryOwnershipTransferred) + it.Event = new(FeeQuoterOwnershipTransferred) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1755,7 +1755,7 @@ func (it *PriceRegistryOwnershipTransferredIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(PriceRegistryOwnershipTransferred) + it.Event = new(FeeQuoterOwnershipTransferred) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1770,22 +1770,22 @@ func (it *PriceRegistryOwnershipTransferredIterator) Next() bool { } } -func (it *PriceRegistryOwnershipTransferredIterator) Error() error { +func (it *FeeQuoterOwnershipTransferredIterator) Error() error { return it.fail } -func (it *PriceRegistryOwnershipTransferredIterator) Close() error { +func (it *FeeQuoterOwnershipTransferredIterator) Close() error { it.sub.Unsubscribe() return nil } -type PriceRegistryOwnershipTransferred struct { +type FeeQuoterOwnershipTransferred struct { From common.Address To common.Address Raw types.Log } -func (_PriceRegistry *PriceRegistryFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*PriceRegistryOwnershipTransferredIterator, error) { +func (_FeeQuoter *FeeQuoterFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*FeeQuoterOwnershipTransferredIterator, error) { var fromRule []interface{} for _, fromItem := range from { @@ -1796,14 +1796,14 @@ func (_PriceRegistry *PriceRegistryFilterer) FilterOwnershipTransferred(opts *bi toRule = append(toRule, toItem) } - logs, sub, err := _PriceRegistry.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) + logs, sub, err := _FeeQuoter.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) if err != nil { return nil, err } - return &PriceRegistryOwnershipTransferredIterator{contract: _PriceRegistry.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil + return &FeeQuoterOwnershipTransferredIterator{contract: _FeeQuoter.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil } -func (_PriceRegistry *PriceRegistryFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *PriceRegistryOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) { +func (_FeeQuoter *FeeQuoterFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *FeeQuoterOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) { var fromRule []interface{} for _, fromItem := range from { @@ -1814,7 +1814,7 @@ func (_PriceRegistry *PriceRegistryFilterer) WatchOwnershipTransferred(opts *bin toRule = append(toRule, toItem) } - logs, sub, err := _PriceRegistry.contract.WatchLogs(opts, "OwnershipTransferred", fromRule, toRule) + logs, sub, err := _FeeQuoter.contract.WatchLogs(opts, "OwnershipTransferred", fromRule, toRule) if err != nil { return nil, err } @@ -1824,8 +1824,8 @@ func (_PriceRegistry *PriceRegistryFilterer) WatchOwnershipTransferred(opts *bin select { case log := <-logs: - event := new(PriceRegistryOwnershipTransferred) - if err := _PriceRegistry.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + event := new(FeeQuoterOwnershipTransferred) + if err := _FeeQuoter.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { return err } event.Raw = log @@ -1846,17 +1846,17 @@ func (_PriceRegistry *PriceRegistryFilterer) WatchOwnershipTransferred(opts *bin }), nil } -func (_PriceRegistry *PriceRegistryFilterer) ParseOwnershipTransferred(log types.Log) (*PriceRegistryOwnershipTransferred, error) { - event := new(PriceRegistryOwnershipTransferred) - if err := _PriceRegistry.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { +func (_FeeQuoter *FeeQuoterFilterer) ParseOwnershipTransferred(log types.Log) (*FeeQuoterOwnershipTransferred, error) { + event := new(FeeQuoterOwnershipTransferred) + if err := _FeeQuoter.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { return nil, err } event.Raw = log return event, nil } -type PriceRegistryPremiumMultiplierWeiPerEthUpdatedIterator struct { - Event *PriceRegistryPremiumMultiplierWeiPerEthUpdated +type FeeQuoterPremiumMultiplierWeiPerEthUpdatedIterator struct { + Event *FeeQuoterPremiumMultiplierWeiPerEthUpdated contract *bind.BoundContract event string @@ -1867,7 +1867,7 @@ type PriceRegistryPremiumMultiplierWeiPerEthUpdatedIterator struct { fail error } -func (it *PriceRegistryPremiumMultiplierWeiPerEthUpdatedIterator) Next() bool { +func (it *FeeQuoterPremiumMultiplierWeiPerEthUpdatedIterator) Next() bool { if it.fail != nil { return false @@ -1876,7 +1876,7 @@ func (it *PriceRegistryPremiumMultiplierWeiPerEthUpdatedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(PriceRegistryPremiumMultiplierWeiPerEthUpdated) + it.Event = new(FeeQuoterPremiumMultiplierWeiPerEthUpdated) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1891,7 +1891,7 @@ func (it *PriceRegistryPremiumMultiplierWeiPerEthUpdatedIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(PriceRegistryPremiumMultiplierWeiPerEthUpdated) + it.Event = new(FeeQuoterPremiumMultiplierWeiPerEthUpdated) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1906,43 +1906,43 @@ func (it *PriceRegistryPremiumMultiplierWeiPerEthUpdatedIterator) Next() bool { } } -func (it *PriceRegistryPremiumMultiplierWeiPerEthUpdatedIterator) Error() error { +func (it *FeeQuoterPremiumMultiplierWeiPerEthUpdatedIterator) Error() error { return it.fail } -func (it *PriceRegistryPremiumMultiplierWeiPerEthUpdatedIterator) Close() error { +func (it *FeeQuoterPremiumMultiplierWeiPerEthUpdatedIterator) Close() error { it.sub.Unsubscribe() return nil } -type PriceRegistryPremiumMultiplierWeiPerEthUpdated struct { +type FeeQuoterPremiumMultiplierWeiPerEthUpdated struct { Token common.Address PremiumMultiplierWeiPerEth uint64 Raw types.Log } -func (_PriceRegistry *PriceRegistryFilterer) FilterPremiumMultiplierWeiPerEthUpdated(opts *bind.FilterOpts, token []common.Address) (*PriceRegistryPremiumMultiplierWeiPerEthUpdatedIterator, error) { +func (_FeeQuoter *FeeQuoterFilterer) FilterPremiumMultiplierWeiPerEthUpdated(opts *bind.FilterOpts, token []common.Address) (*FeeQuoterPremiumMultiplierWeiPerEthUpdatedIterator, error) { var tokenRule []interface{} for _, tokenItem := range token { tokenRule = append(tokenRule, tokenItem) } - logs, sub, err := _PriceRegistry.contract.FilterLogs(opts, "PremiumMultiplierWeiPerEthUpdated", tokenRule) + logs, sub, err := _FeeQuoter.contract.FilterLogs(opts, "PremiumMultiplierWeiPerEthUpdated", tokenRule) if err != nil { return nil, err } - return &PriceRegistryPremiumMultiplierWeiPerEthUpdatedIterator{contract: _PriceRegistry.contract, event: "PremiumMultiplierWeiPerEthUpdated", logs: logs, sub: sub}, nil + return &FeeQuoterPremiumMultiplierWeiPerEthUpdatedIterator{contract: _FeeQuoter.contract, event: "PremiumMultiplierWeiPerEthUpdated", logs: logs, sub: sub}, nil } -func (_PriceRegistry *PriceRegistryFilterer) WatchPremiumMultiplierWeiPerEthUpdated(opts *bind.WatchOpts, sink chan<- *PriceRegistryPremiumMultiplierWeiPerEthUpdated, token []common.Address) (event.Subscription, error) { +func (_FeeQuoter *FeeQuoterFilterer) WatchPremiumMultiplierWeiPerEthUpdated(opts *bind.WatchOpts, sink chan<- *FeeQuoterPremiumMultiplierWeiPerEthUpdated, token []common.Address) (event.Subscription, error) { var tokenRule []interface{} for _, tokenItem := range token { tokenRule = append(tokenRule, tokenItem) } - logs, sub, err := _PriceRegistry.contract.WatchLogs(opts, "PremiumMultiplierWeiPerEthUpdated", tokenRule) + logs, sub, err := _FeeQuoter.contract.WatchLogs(opts, "PremiumMultiplierWeiPerEthUpdated", tokenRule) if err != nil { return nil, err } @@ -1952,8 +1952,8 @@ func (_PriceRegistry *PriceRegistryFilterer) WatchPremiumMultiplierWeiPerEthUpda select { case log := <-logs: - event := new(PriceRegistryPremiumMultiplierWeiPerEthUpdated) - if err := _PriceRegistry.contract.UnpackLog(event, "PremiumMultiplierWeiPerEthUpdated", log); err != nil { + event := new(FeeQuoterPremiumMultiplierWeiPerEthUpdated) + if err := _FeeQuoter.contract.UnpackLog(event, "PremiumMultiplierWeiPerEthUpdated", log); err != nil { return err } event.Raw = log @@ -1974,17 +1974,17 @@ func (_PriceRegistry *PriceRegistryFilterer) WatchPremiumMultiplierWeiPerEthUpda }), nil } -func (_PriceRegistry *PriceRegistryFilterer) ParsePremiumMultiplierWeiPerEthUpdated(log types.Log) (*PriceRegistryPremiumMultiplierWeiPerEthUpdated, error) { - event := new(PriceRegistryPremiumMultiplierWeiPerEthUpdated) - if err := _PriceRegistry.contract.UnpackLog(event, "PremiumMultiplierWeiPerEthUpdated", log); err != nil { +func (_FeeQuoter *FeeQuoterFilterer) ParsePremiumMultiplierWeiPerEthUpdated(log types.Log) (*FeeQuoterPremiumMultiplierWeiPerEthUpdated, error) { + event := new(FeeQuoterPremiumMultiplierWeiPerEthUpdated) + if err := _FeeQuoter.contract.UnpackLog(event, "PremiumMultiplierWeiPerEthUpdated", log); err != nil { return nil, err } event.Raw = log return event, nil } -type PriceRegistryPriceFeedPerTokenUpdatedIterator struct { - Event *PriceRegistryPriceFeedPerTokenUpdated +type FeeQuoterPriceFeedPerTokenUpdatedIterator struct { + Event *FeeQuoterPriceFeedPerTokenUpdated contract *bind.BoundContract event string @@ -1995,7 +1995,7 @@ type PriceRegistryPriceFeedPerTokenUpdatedIterator struct { fail error } -func (it *PriceRegistryPriceFeedPerTokenUpdatedIterator) Next() bool { +func (it *FeeQuoterPriceFeedPerTokenUpdatedIterator) Next() bool { if it.fail != nil { return false @@ -2004,7 +2004,7 @@ func (it *PriceRegistryPriceFeedPerTokenUpdatedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(PriceRegistryPriceFeedPerTokenUpdated) + it.Event = new(FeeQuoterPriceFeedPerTokenUpdated) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -2019,7 +2019,7 @@ func (it *PriceRegistryPriceFeedPerTokenUpdatedIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(PriceRegistryPriceFeedPerTokenUpdated) + it.Event = new(FeeQuoterPriceFeedPerTokenUpdated) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -2034,43 +2034,43 @@ func (it *PriceRegistryPriceFeedPerTokenUpdatedIterator) Next() bool { } } -func (it *PriceRegistryPriceFeedPerTokenUpdatedIterator) Error() error { +func (it *FeeQuoterPriceFeedPerTokenUpdatedIterator) Error() error { return it.fail } -func (it *PriceRegistryPriceFeedPerTokenUpdatedIterator) Close() error { +func (it *FeeQuoterPriceFeedPerTokenUpdatedIterator) Close() error { it.sub.Unsubscribe() return nil } -type PriceRegistryPriceFeedPerTokenUpdated struct { +type FeeQuoterPriceFeedPerTokenUpdated struct { Token common.Address - PriceFeedConfig IPriceRegistryTokenPriceFeedConfig + PriceFeedConfig IFeeQuoterTokenPriceFeedConfig Raw types.Log } -func (_PriceRegistry *PriceRegistryFilterer) FilterPriceFeedPerTokenUpdated(opts *bind.FilterOpts, token []common.Address) (*PriceRegistryPriceFeedPerTokenUpdatedIterator, error) { +func (_FeeQuoter *FeeQuoterFilterer) FilterPriceFeedPerTokenUpdated(opts *bind.FilterOpts, token []common.Address) (*FeeQuoterPriceFeedPerTokenUpdatedIterator, error) { var tokenRule []interface{} for _, tokenItem := range token { tokenRule = append(tokenRule, tokenItem) } - logs, sub, err := _PriceRegistry.contract.FilterLogs(opts, "PriceFeedPerTokenUpdated", tokenRule) + logs, sub, err := _FeeQuoter.contract.FilterLogs(opts, "PriceFeedPerTokenUpdated", tokenRule) if err != nil { return nil, err } - return &PriceRegistryPriceFeedPerTokenUpdatedIterator{contract: _PriceRegistry.contract, event: "PriceFeedPerTokenUpdated", logs: logs, sub: sub}, nil + return &FeeQuoterPriceFeedPerTokenUpdatedIterator{contract: _FeeQuoter.contract, event: "PriceFeedPerTokenUpdated", logs: logs, sub: sub}, nil } -func (_PriceRegistry *PriceRegistryFilterer) WatchPriceFeedPerTokenUpdated(opts *bind.WatchOpts, sink chan<- *PriceRegistryPriceFeedPerTokenUpdated, token []common.Address) (event.Subscription, error) { +func (_FeeQuoter *FeeQuoterFilterer) WatchPriceFeedPerTokenUpdated(opts *bind.WatchOpts, sink chan<- *FeeQuoterPriceFeedPerTokenUpdated, token []common.Address) (event.Subscription, error) { var tokenRule []interface{} for _, tokenItem := range token { tokenRule = append(tokenRule, tokenItem) } - logs, sub, err := _PriceRegistry.contract.WatchLogs(opts, "PriceFeedPerTokenUpdated", tokenRule) + logs, sub, err := _FeeQuoter.contract.WatchLogs(opts, "PriceFeedPerTokenUpdated", tokenRule) if err != nil { return nil, err } @@ -2080,8 +2080,8 @@ func (_PriceRegistry *PriceRegistryFilterer) WatchPriceFeedPerTokenUpdated(opts select { case log := <-logs: - event := new(PriceRegistryPriceFeedPerTokenUpdated) - if err := _PriceRegistry.contract.UnpackLog(event, "PriceFeedPerTokenUpdated", log); err != nil { + event := new(FeeQuoterPriceFeedPerTokenUpdated) + if err := _FeeQuoter.contract.UnpackLog(event, "PriceFeedPerTokenUpdated", log); err != nil { return err } event.Raw = log @@ -2102,17 +2102,17 @@ func (_PriceRegistry *PriceRegistryFilterer) WatchPriceFeedPerTokenUpdated(opts }), nil } -func (_PriceRegistry *PriceRegistryFilterer) ParsePriceFeedPerTokenUpdated(log types.Log) (*PriceRegistryPriceFeedPerTokenUpdated, error) { - event := new(PriceRegistryPriceFeedPerTokenUpdated) - if err := _PriceRegistry.contract.UnpackLog(event, "PriceFeedPerTokenUpdated", log); err != nil { +func (_FeeQuoter *FeeQuoterFilterer) ParsePriceFeedPerTokenUpdated(log types.Log) (*FeeQuoterPriceFeedPerTokenUpdated, error) { + event := new(FeeQuoterPriceFeedPerTokenUpdated) + if err := _FeeQuoter.contract.UnpackLog(event, "PriceFeedPerTokenUpdated", log); err != nil { return nil, err } event.Raw = log return event, nil } -type PriceRegistryReportPermissionSetIterator struct { - Event *PriceRegistryReportPermissionSet +type FeeQuoterReportPermissionSetIterator struct { + Event *FeeQuoterReportPermissionSet contract *bind.BoundContract event string @@ -2123,7 +2123,7 @@ type PriceRegistryReportPermissionSetIterator struct { fail error } -func (it *PriceRegistryReportPermissionSetIterator) Next() bool { +func (it *FeeQuoterReportPermissionSetIterator) Next() bool { if it.fail != nil { return false @@ -2132,7 +2132,7 @@ func (it *PriceRegistryReportPermissionSetIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(PriceRegistryReportPermissionSet) + it.Event = new(FeeQuoterReportPermissionSet) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -2147,7 +2147,7 @@ func (it *PriceRegistryReportPermissionSetIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(PriceRegistryReportPermissionSet) + it.Event = new(FeeQuoterReportPermissionSet) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -2162,43 +2162,43 @@ func (it *PriceRegistryReportPermissionSetIterator) Next() bool { } } -func (it *PriceRegistryReportPermissionSetIterator) Error() error { +func (it *FeeQuoterReportPermissionSetIterator) Error() error { return it.fail } -func (it *PriceRegistryReportPermissionSetIterator) Close() error { +func (it *FeeQuoterReportPermissionSetIterator) Close() error { it.sub.Unsubscribe() return nil } -type PriceRegistryReportPermissionSet struct { +type FeeQuoterReportPermissionSet struct { ReportId [32]byte Permission KeystoneFeedsPermissionHandlerPermission Raw types.Log } -func (_PriceRegistry *PriceRegistryFilterer) FilterReportPermissionSet(opts *bind.FilterOpts, reportId [][32]byte) (*PriceRegistryReportPermissionSetIterator, error) { +func (_FeeQuoter *FeeQuoterFilterer) FilterReportPermissionSet(opts *bind.FilterOpts, reportId [][32]byte) (*FeeQuoterReportPermissionSetIterator, error) { var reportIdRule []interface{} for _, reportIdItem := range reportId { reportIdRule = append(reportIdRule, reportIdItem) } - logs, sub, err := _PriceRegistry.contract.FilterLogs(opts, "ReportPermissionSet", reportIdRule) + logs, sub, err := _FeeQuoter.contract.FilterLogs(opts, "ReportPermissionSet", reportIdRule) if err != nil { return nil, err } - return &PriceRegistryReportPermissionSetIterator{contract: _PriceRegistry.contract, event: "ReportPermissionSet", logs: logs, sub: sub}, nil + return &FeeQuoterReportPermissionSetIterator{contract: _FeeQuoter.contract, event: "ReportPermissionSet", logs: logs, sub: sub}, nil } -func (_PriceRegistry *PriceRegistryFilterer) WatchReportPermissionSet(opts *bind.WatchOpts, sink chan<- *PriceRegistryReportPermissionSet, reportId [][32]byte) (event.Subscription, error) { +func (_FeeQuoter *FeeQuoterFilterer) WatchReportPermissionSet(opts *bind.WatchOpts, sink chan<- *FeeQuoterReportPermissionSet, reportId [][32]byte) (event.Subscription, error) { var reportIdRule []interface{} for _, reportIdItem := range reportId { reportIdRule = append(reportIdRule, reportIdItem) } - logs, sub, err := _PriceRegistry.contract.WatchLogs(opts, "ReportPermissionSet", reportIdRule) + logs, sub, err := _FeeQuoter.contract.WatchLogs(opts, "ReportPermissionSet", reportIdRule) if err != nil { return nil, err } @@ -2208,8 +2208,8 @@ func (_PriceRegistry *PriceRegistryFilterer) WatchReportPermissionSet(opts *bind select { case log := <-logs: - event := new(PriceRegistryReportPermissionSet) - if err := _PriceRegistry.contract.UnpackLog(event, "ReportPermissionSet", log); err != nil { + event := new(FeeQuoterReportPermissionSet) + if err := _FeeQuoter.contract.UnpackLog(event, "ReportPermissionSet", log); err != nil { return err } event.Raw = log @@ -2230,17 +2230,17 @@ func (_PriceRegistry *PriceRegistryFilterer) WatchReportPermissionSet(opts *bind }), nil } -func (_PriceRegistry *PriceRegistryFilterer) ParseReportPermissionSet(log types.Log) (*PriceRegistryReportPermissionSet, error) { - event := new(PriceRegistryReportPermissionSet) - if err := _PriceRegistry.contract.UnpackLog(event, "ReportPermissionSet", log); err != nil { +func (_FeeQuoter *FeeQuoterFilterer) ParseReportPermissionSet(log types.Log) (*FeeQuoterReportPermissionSet, error) { + event := new(FeeQuoterReportPermissionSet) + if err := _FeeQuoter.contract.UnpackLog(event, "ReportPermissionSet", log); err != nil { return nil, err } event.Raw = log return event, nil } -type PriceRegistryTokenTransferFeeConfigDeletedIterator struct { - Event *PriceRegistryTokenTransferFeeConfigDeleted +type FeeQuoterTokenTransferFeeConfigDeletedIterator struct { + Event *FeeQuoterTokenTransferFeeConfigDeleted contract *bind.BoundContract event string @@ -2251,7 +2251,7 @@ type PriceRegistryTokenTransferFeeConfigDeletedIterator struct { fail error } -func (it *PriceRegistryTokenTransferFeeConfigDeletedIterator) Next() bool { +func (it *FeeQuoterTokenTransferFeeConfigDeletedIterator) Next() bool { if it.fail != nil { return false @@ -2260,7 +2260,7 @@ func (it *PriceRegistryTokenTransferFeeConfigDeletedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(PriceRegistryTokenTransferFeeConfigDeleted) + it.Event = new(FeeQuoterTokenTransferFeeConfigDeleted) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -2275,7 +2275,7 @@ func (it *PriceRegistryTokenTransferFeeConfigDeletedIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(PriceRegistryTokenTransferFeeConfigDeleted) + it.Event = new(FeeQuoterTokenTransferFeeConfigDeleted) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -2290,22 +2290,22 @@ func (it *PriceRegistryTokenTransferFeeConfigDeletedIterator) Next() bool { } } -func (it *PriceRegistryTokenTransferFeeConfigDeletedIterator) Error() error { +func (it *FeeQuoterTokenTransferFeeConfigDeletedIterator) Error() error { return it.fail } -func (it *PriceRegistryTokenTransferFeeConfigDeletedIterator) Close() error { +func (it *FeeQuoterTokenTransferFeeConfigDeletedIterator) Close() error { it.sub.Unsubscribe() return nil } -type PriceRegistryTokenTransferFeeConfigDeleted struct { +type FeeQuoterTokenTransferFeeConfigDeleted struct { DestChainSelector uint64 Token common.Address Raw types.Log } -func (_PriceRegistry *PriceRegistryFilterer) FilterTokenTransferFeeConfigDeleted(opts *bind.FilterOpts, destChainSelector []uint64, token []common.Address) (*PriceRegistryTokenTransferFeeConfigDeletedIterator, error) { +func (_FeeQuoter *FeeQuoterFilterer) FilterTokenTransferFeeConfigDeleted(opts *bind.FilterOpts, destChainSelector []uint64, token []common.Address) (*FeeQuoterTokenTransferFeeConfigDeletedIterator, error) { var destChainSelectorRule []interface{} for _, destChainSelectorItem := range destChainSelector { @@ -2316,14 +2316,14 @@ func (_PriceRegistry *PriceRegistryFilterer) FilterTokenTransferFeeConfigDeleted tokenRule = append(tokenRule, tokenItem) } - logs, sub, err := _PriceRegistry.contract.FilterLogs(opts, "TokenTransferFeeConfigDeleted", destChainSelectorRule, tokenRule) + logs, sub, err := _FeeQuoter.contract.FilterLogs(opts, "TokenTransferFeeConfigDeleted", destChainSelectorRule, tokenRule) if err != nil { return nil, err } - return &PriceRegistryTokenTransferFeeConfigDeletedIterator{contract: _PriceRegistry.contract, event: "TokenTransferFeeConfigDeleted", logs: logs, sub: sub}, nil + return &FeeQuoterTokenTransferFeeConfigDeletedIterator{contract: _FeeQuoter.contract, event: "TokenTransferFeeConfigDeleted", logs: logs, sub: sub}, nil } -func (_PriceRegistry *PriceRegistryFilterer) WatchTokenTransferFeeConfigDeleted(opts *bind.WatchOpts, sink chan<- *PriceRegistryTokenTransferFeeConfigDeleted, destChainSelector []uint64, token []common.Address) (event.Subscription, error) { +func (_FeeQuoter *FeeQuoterFilterer) WatchTokenTransferFeeConfigDeleted(opts *bind.WatchOpts, sink chan<- *FeeQuoterTokenTransferFeeConfigDeleted, destChainSelector []uint64, token []common.Address) (event.Subscription, error) { var destChainSelectorRule []interface{} for _, destChainSelectorItem := range destChainSelector { @@ -2334,7 +2334,7 @@ func (_PriceRegistry *PriceRegistryFilterer) WatchTokenTransferFeeConfigDeleted( tokenRule = append(tokenRule, tokenItem) } - logs, sub, err := _PriceRegistry.contract.WatchLogs(opts, "TokenTransferFeeConfigDeleted", destChainSelectorRule, tokenRule) + logs, sub, err := _FeeQuoter.contract.WatchLogs(opts, "TokenTransferFeeConfigDeleted", destChainSelectorRule, tokenRule) if err != nil { return nil, err } @@ -2344,8 +2344,8 @@ func (_PriceRegistry *PriceRegistryFilterer) WatchTokenTransferFeeConfigDeleted( select { case log := <-logs: - event := new(PriceRegistryTokenTransferFeeConfigDeleted) - if err := _PriceRegistry.contract.UnpackLog(event, "TokenTransferFeeConfigDeleted", log); err != nil { + event := new(FeeQuoterTokenTransferFeeConfigDeleted) + if err := _FeeQuoter.contract.UnpackLog(event, "TokenTransferFeeConfigDeleted", log); err != nil { return err } event.Raw = log @@ -2366,17 +2366,17 @@ func (_PriceRegistry *PriceRegistryFilterer) WatchTokenTransferFeeConfigDeleted( }), nil } -func (_PriceRegistry *PriceRegistryFilterer) ParseTokenTransferFeeConfigDeleted(log types.Log) (*PriceRegistryTokenTransferFeeConfigDeleted, error) { - event := new(PriceRegistryTokenTransferFeeConfigDeleted) - if err := _PriceRegistry.contract.UnpackLog(event, "TokenTransferFeeConfigDeleted", log); err != nil { +func (_FeeQuoter *FeeQuoterFilterer) ParseTokenTransferFeeConfigDeleted(log types.Log) (*FeeQuoterTokenTransferFeeConfigDeleted, error) { + event := new(FeeQuoterTokenTransferFeeConfigDeleted) + if err := _FeeQuoter.contract.UnpackLog(event, "TokenTransferFeeConfigDeleted", log); err != nil { return nil, err } event.Raw = log return event, nil } -type PriceRegistryTokenTransferFeeConfigUpdatedIterator struct { - Event *PriceRegistryTokenTransferFeeConfigUpdated +type FeeQuoterTokenTransferFeeConfigUpdatedIterator struct { + Event *FeeQuoterTokenTransferFeeConfigUpdated contract *bind.BoundContract event string @@ -2387,7 +2387,7 @@ type PriceRegistryTokenTransferFeeConfigUpdatedIterator struct { fail error } -func (it *PriceRegistryTokenTransferFeeConfigUpdatedIterator) Next() bool { +func (it *FeeQuoterTokenTransferFeeConfigUpdatedIterator) Next() bool { if it.fail != nil { return false @@ -2396,7 +2396,7 @@ func (it *PriceRegistryTokenTransferFeeConfigUpdatedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(PriceRegistryTokenTransferFeeConfigUpdated) + it.Event = new(FeeQuoterTokenTransferFeeConfigUpdated) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -2411,7 +2411,7 @@ func (it *PriceRegistryTokenTransferFeeConfigUpdatedIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(PriceRegistryTokenTransferFeeConfigUpdated) + it.Event = new(FeeQuoterTokenTransferFeeConfigUpdated) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -2426,23 +2426,23 @@ func (it *PriceRegistryTokenTransferFeeConfigUpdatedIterator) Next() bool { } } -func (it *PriceRegistryTokenTransferFeeConfigUpdatedIterator) Error() error { +func (it *FeeQuoterTokenTransferFeeConfigUpdatedIterator) Error() error { return it.fail } -func (it *PriceRegistryTokenTransferFeeConfigUpdatedIterator) Close() error { +func (it *FeeQuoterTokenTransferFeeConfigUpdatedIterator) Close() error { it.sub.Unsubscribe() return nil } -type PriceRegistryTokenTransferFeeConfigUpdated struct { +type FeeQuoterTokenTransferFeeConfigUpdated struct { DestChainSelector uint64 Token common.Address - TokenTransferFeeConfig PriceRegistryTokenTransferFeeConfig + TokenTransferFeeConfig FeeQuoterTokenTransferFeeConfig Raw types.Log } -func (_PriceRegistry *PriceRegistryFilterer) FilterTokenTransferFeeConfigUpdated(opts *bind.FilterOpts, destChainSelector []uint64, token []common.Address) (*PriceRegistryTokenTransferFeeConfigUpdatedIterator, error) { +func (_FeeQuoter *FeeQuoterFilterer) FilterTokenTransferFeeConfigUpdated(opts *bind.FilterOpts, destChainSelector []uint64, token []common.Address) (*FeeQuoterTokenTransferFeeConfigUpdatedIterator, error) { var destChainSelectorRule []interface{} for _, destChainSelectorItem := range destChainSelector { @@ -2453,14 +2453,14 @@ func (_PriceRegistry *PriceRegistryFilterer) FilterTokenTransferFeeConfigUpdated tokenRule = append(tokenRule, tokenItem) } - logs, sub, err := _PriceRegistry.contract.FilterLogs(opts, "TokenTransferFeeConfigUpdated", destChainSelectorRule, tokenRule) + logs, sub, err := _FeeQuoter.contract.FilterLogs(opts, "TokenTransferFeeConfigUpdated", destChainSelectorRule, tokenRule) if err != nil { return nil, err } - return &PriceRegistryTokenTransferFeeConfigUpdatedIterator{contract: _PriceRegistry.contract, event: "TokenTransferFeeConfigUpdated", logs: logs, sub: sub}, nil + return &FeeQuoterTokenTransferFeeConfigUpdatedIterator{contract: _FeeQuoter.contract, event: "TokenTransferFeeConfigUpdated", logs: logs, sub: sub}, nil } -func (_PriceRegistry *PriceRegistryFilterer) WatchTokenTransferFeeConfigUpdated(opts *bind.WatchOpts, sink chan<- *PriceRegistryTokenTransferFeeConfigUpdated, destChainSelector []uint64, token []common.Address) (event.Subscription, error) { +func (_FeeQuoter *FeeQuoterFilterer) WatchTokenTransferFeeConfigUpdated(opts *bind.WatchOpts, sink chan<- *FeeQuoterTokenTransferFeeConfigUpdated, destChainSelector []uint64, token []common.Address) (event.Subscription, error) { var destChainSelectorRule []interface{} for _, destChainSelectorItem := range destChainSelector { @@ -2471,7 +2471,7 @@ func (_PriceRegistry *PriceRegistryFilterer) WatchTokenTransferFeeConfigUpdated( tokenRule = append(tokenRule, tokenItem) } - logs, sub, err := _PriceRegistry.contract.WatchLogs(opts, "TokenTransferFeeConfigUpdated", destChainSelectorRule, tokenRule) + logs, sub, err := _FeeQuoter.contract.WatchLogs(opts, "TokenTransferFeeConfigUpdated", destChainSelectorRule, tokenRule) if err != nil { return nil, err } @@ -2481,8 +2481,8 @@ func (_PriceRegistry *PriceRegistryFilterer) WatchTokenTransferFeeConfigUpdated( select { case log := <-logs: - event := new(PriceRegistryTokenTransferFeeConfigUpdated) - if err := _PriceRegistry.contract.UnpackLog(event, "TokenTransferFeeConfigUpdated", log); err != nil { + event := new(FeeQuoterTokenTransferFeeConfigUpdated) + if err := _FeeQuoter.contract.UnpackLog(event, "TokenTransferFeeConfigUpdated", log); err != nil { return err } event.Raw = log @@ -2503,17 +2503,17 @@ func (_PriceRegistry *PriceRegistryFilterer) WatchTokenTransferFeeConfigUpdated( }), nil } -func (_PriceRegistry *PriceRegistryFilterer) ParseTokenTransferFeeConfigUpdated(log types.Log) (*PriceRegistryTokenTransferFeeConfigUpdated, error) { - event := new(PriceRegistryTokenTransferFeeConfigUpdated) - if err := _PriceRegistry.contract.UnpackLog(event, "TokenTransferFeeConfigUpdated", log); err != nil { +func (_FeeQuoter *FeeQuoterFilterer) ParseTokenTransferFeeConfigUpdated(log types.Log) (*FeeQuoterTokenTransferFeeConfigUpdated, error) { + event := new(FeeQuoterTokenTransferFeeConfigUpdated) + if err := _FeeQuoter.contract.UnpackLog(event, "TokenTransferFeeConfigUpdated", log); err != nil { return nil, err } event.Raw = log return event, nil } -type PriceRegistryUsdPerTokenUpdatedIterator struct { - Event *PriceRegistryUsdPerTokenUpdated +type FeeQuoterUsdPerTokenUpdatedIterator struct { + Event *FeeQuoterUsdPerTokenUpdated contract *bind.BoundContract event string @@ -2524,7 +2524,7 @@ type PriceRegistryUsdPerTokenUpdatedIterator struct { fail error } -func (it *PriceRegistryUsdPerTokenUpdatedIterator) Next() bool { +func (it *FeeQuoterUsdPerTokenUpdatedIterator) Next() bool { if it.fail != nil { return false @@ -2533,7 +2533,7 @@ func (it *PriceRegistryUsdPerTokenUpdatedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(PriceRegistryUsdPerTokenUpdated) + it.Event = new(FeeQuoterUsdPerTokenUpdated) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -2548,7 +2548,7 @@ func (it *PriceRegistryUsdPerTokenUpdatedIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(PriceRegistryUsdPerTokenUpdated) + it.Event = new(FeeQuoterUsdPerTokenUpdated) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -2563,44 +2563,44 @@ func (it *PriceRegistryUsdPerTokenUpdatedIterator) Next() bool { } } -func (it *PriceRegistryUsdPerTokenUpdatedIterator) Error() error { +func (it *FeeQuoterUsdPerTokenUpdatedIterator) Error() error { return it.fail } -func (it *PriceRegistryUsdPerTokenUpdatedIterator) Close() error { +func (it *FeeQuoterUsdPerTokenUpdatedIterator) Close() error { it.sub.Unsubscribe() return nil } -type PriceRegistryUsdPerTokenUpdated struct { +type FeeQuoterUsdPerTokenUpdated struct { Token common.Address Value *big.Int Timestamp *big.Int Raw types.Log } -func (_PriceRegistry *PriceRegistryFilterer) FilterUsdPerTokenUpdated(opts *bind.FilterOpts, token []common.Address) (*PriceRegistryUsdPerTokenUpdatedIterator, error) { +func (_FeeQuoter *FeeQuoterFilterer) FilterUsdPerTokenUpdated(opts *bind.FilterOpts, token []common.Address) (*FeeQuoterUsdPerTokenUpdatedIterator, error) { var tokenRule []interface{} for _, tokenItem := range token { tokenRule = append(tokenRule, tokenItem) } - logs, sub, err := _PriceRegistry.contract.FilterLogs(opts, "UsdPerTokenUpdated", tokenRule) + logs, sub, err := _FeeQuoter.contract.FilterLogs(opts, "UsdPerTokenUpdated", tokenRule) if err != nil { return nil, err } - return &PriceRegistryUsdPerTokenUpdatedIterator{contract: _PriceRegistry.contract, event: "UsdPerTokenUpdated", logs: logs, sub: sub}, nil + return &FeeQuoterUsdPerTokenUpdatedIterator{contract: _FeeQuoter.contract, event: "UsdPerTokenUpdated", logs: logs, sub: sub}, nil } -func (_PriceRegistry *PriceRegistryFilterer) WatchUsdPerTokenUpdated(opts *bind.WatchOpts, sink chan<- *PriceRegistryUsdPerTokenUpdated, token []common.Address) (event.Subscription, error) { +func (_FeeQuoter *FeeQuoterFilterer) WatchUsdPerTokenUpdated(opts *bind.WatchOpts, sink chan<- *FeeQuoterUsdPerTokenUpdated, token []common.Address) (event.Subscription, error) { var tokenRule []interface{} for _, tokenItem := range token { tokenRule = append(tokenRule, tokenItem) } - logs, sub, err := _PriceRegistry.contract.WatchLogs(opts, "UsdPerTokenUpdated", tokenRule) + logs, sub, err := _FeeQuoter.contract.WatchLogs(opts, "UsdPerTokenUpdated", tokenRule) if err != nil { return nil, err } @@ -2610,8 +2610,8 @@ func (_PriceRegistry *PriceRegistryFilterer) WatchUsdPerTokenUpdated(opts *bind. select { case log := <-logs: - event := new(PriceRegistryUsdPerTokenUpdated) - if err := _PriceRegistry.contract.UnpackLog(event, "UsdPerTokenUpdated", log); err != nil { + event := new(FeeQuoterUsdPerTokenUpdated) + if err := _FeeQuoter.contract.UnpackLog(event, "UsdPerTokenUpdated", log); err != nil { return err } event.Raw = log @@ -2632,17 +2632,17 @@ func (_PriceRegistry *PriceRegistryFilterer) WatchUsdPerTokenUpdated(opts *bind. }), nil } -func (_PriceRegistry *PriceRegistryFilterer) ParseUsdPerTokenUpdated(log types.Log) (*PriceRegistryUsdPerTokenUpdated, error) { - event := new(PriceRegistryUsdPerTokenUpdated) - if err := _PriceRegistry.contract.UnpackLog(event, "UsdPerTokenUpdated", log); err != nil { +func (_FeeQuoter *FeeQuoterFilterer) ParseUsdPerTokenUpdated(log types.Log) (*FeeQuoterUsdPerTokenUpdated, error) { + event := new(FeeQuoterUsdPerTokenUpdated) + if err := _FeeQuoter.contract.UnpackLog(event, "UsdPerTokenUpdated", log); err != nil { return nil, err } event.Raw = log return event, nil } -type PriceRegistryUsdPerUnitGasUpdatedIterator struct { - Event *PriceRegistryUsdPerUnitGasUpdated +type FeeQuoterUsdPerUnitGasUpdatedIterator struct { + Event *FeeQuoterUsdPerUnitGasUpdated contract *bind.BoundContract event string @@ -2653,7 +2653,7 @@ type PriceRegistryUsdPerUnitGasUpdatedIterator struct { fail error } -func (it *PriceRegistryUsdPerUnitGasUpdatedIterator) Next() bool { +func (it *FeeQuoterUsdPerUnitGasUpdatedIterator) Next() bool { if it.fail != nil { return false @@ -2662,7 +2662,7 @@ func (it *PriceRegistryUsdPerUnitGasUpdatedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(PriceRegistryUsdPerUnitGasUpdated) + it.Event = new(FeeQuoterUsdPerUnitGasUpdated) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -2677,7 +2677,7 @@ func (it *PriceRegistryUsdPerUnitGasUpdatedIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(PriceRegistryUsdPerUnitGasUpdated) + it.Event = new(FeeQuoterUsdPerUnitGasUpdated) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -2692,44 +2692,44 @@ func (it *PriceRegistryUsdPerUnitGasUpdatedIterator) Next() bool { } } -func (it *PriceRegistryUsdPerUnitGasUpdatedIterator) Error() error { +func (it *FeeQuoterUsdPerUnitGasUpdatedIterator) Error() error { return it.fail } -func (it *PriceRegistryUsdPerUnitGasUpdatedIterator) Close() error { +func (it *FeeQuoterUsdPerUnitGasUpdatedIterator) Close() error { it.sub.Unsubscribe() return nil } -type PriceRegistryUsdPerUnitGasUpdated struct { +type FeeQuoterUsdPerUnitGasUpdated struct { DestChain uint64 Value *big.Int Timestamp *big.Int Raw types.Log } -func (_PriceRegistry *PriceRegistryFilterer) FilterUsdPerUnitGasUpdated(opts *bind.FilterOpts, destChain []uint64) (*PriceRegistryUsdPerUnitGasUpdatedIterator, error) { +func (_FeeQuoter *FeeQuoterFilterer) FilterUsdPerUnitGasUpdated(opts *bind.FilterOpts, destChain []uint64) (*FeeQuoterUsdPerUnitGasUpdatedIterator, error) { var destChainRule []interface{} for _, destChainItem := range destChain { destChainRule = append(destChainRule, destChainItem) } - logs, sub, err := _PriceRegistry.contract.FilterLogs(opts, "UsdPerUnitGasUpdated", destChainRule) + logs, sub, err := _FeeQuoter.contract.FilterLogs(opts, "UsdPerUnitGasUpdated", destChainRule) if err != nil { return nil, err } - return &PriceRegistryUsdPerUnitGasUpdatedIterator{contract: _PriceRegistry.contract, event: "UsdPerUnitGasUpdated", logs: logs, sub: sub}, nil + return &FeeQuoterUsdPerUnitGasUpdatedIterator{contract: _FeeQuoter.contract, event: "UsdPerUnitGasUpdated", logs: logs, sub: sub}, nil } -func (_PriceRegistry *PriceRegistryFilterer) WatchUsdPerUnitGasUpdated(opts *bind.WatchOpts, sink chan<- *PriceRegistryUsdPerUnitGasUpdated, destChain []uint64) (event.Subscription, error) { +func (_FeeQuoter *FeeQuoterFilterer) WatchUsdPerUnitGasUpdated(opts *bind.WatchOpts, sink chan<- *FeeQuoterUsdPerUnitGasUpdated, destChain []uint64) (event.Subscription, error) { var destChainRule []interface{} for _, destChainItem := range destChain { destChainRule = append(destChainRule, destChainItem) } - logs, sub, err := _PriceRegistry.contract.WatchLogs(opts, "UsdPerUnitGasUpdated", destChainRule) + logs, sub, err := _FeeQuoter.contract.WatchLogs(opts, "UsdPerUnitGasUpdated", destChainRule) if err != nil { return nil, err } @@ -2739,8 +2739,8 @@ func (_PriceRegistry *PriceRegistryFilterer) WatchUsdPerUnitGasUpdated(opts *bin select { case log := <-logs: - event := new(PriceRegistryUsdPerUnitGasUpdated) - if err := _PriceRegistry.contract.UnpackLog(event, "UsdPerUnitGasUpdated", log); err != nil { + event := new(FeeQuoterUsdPerUnitGasUpdated) + if err := _FeeQuoter.contract.UnpackLog(event, "UsdPerUnitGasUpdated", log); err != nil { return err } event.Raw = log @@ -2761,9 +2761,9 @@ func (_PriceRegistry *PriceRegistryFilterer) WatchUsdPerUnitGasUpdated(opts *bin }), nil } -func (_PriceRegistry *PriceRegistryFilterer) ParseUsdPerUnitGasUpdated(log types.Log) (*PriceRegistryUsdPerUnitGasUpdated, error) { - event := new(PriceRegistryUsdPerUnitGasUpdated) - if err := _PriceRegistry.contract.UnpackLog(event, "UsdPerUnitGasUpdated", log); err != nil { +func (_FeeQuoter *FeeQuoterFilterer) ParseUsdPerUnitGasUpdated(log types.Log) (*FeeQuoterUsdPerUnitGasUpdated, error) { + event := new(FeeQuoterUsdPerUnitGasUpdated) + if err := _FeeQuoter.contract.UnpackLog(event, "UsdPerUnitGasUpdated", log); err != nil { return nil, err } event.Raw = log @@ -2780,114 +2780,114 @@ type ProcessMessageArgs struct { ConvertedExtraArgs []byte } -func (_PriceRegistry *PriceRegistry) ParseLog(log types.Log) (generated.AbigenLog, error) { +func (_FeeQuoter *FeeQuoter) ParseLog(log types.Log) (generated.AbigenLog, error) { switch log.Topics[0] { - case _PriceRegistry.abi.Events["AuthorizedCallerAdded"].ID: - return _PriceRegistry.ParseAuthorizedCallerAdded(log) - case _PriceRegistry.abi.Events["AuthorizedCallerRemoved"].ID: - return _PriceRegistry.ParseAuthorizedCallerRemoved(log) - case _PriceRegistry.abi.Events["DestChainAdded"].ID: - return _PriceRegistry.ParseDestChainAdded(log) - case _PriceRegistry.abi.Events["DestChainConfigUpdated"].ID: - return _PriceRegistry.ParseDestChainConfigUpdated(log) - case _PriceRegistry.abi.Events["FeeTokenAdded"].ID: - return _PriceRegistry.ParseFeeTokenAdded(log) - case _PriceRegistry.abi.Events["FeeTokenRemoved"].ID: - return _PriceRegistry.ParseFeeTokenRemoved(log) - case _PriceRegistry.abi.Events["OwnershipTransferRequested"].ID: - return _PriceRegistry.ParseOwnershipTransferRequested(log) - case _PriceRegistry.abi.Events["OwnershipTransferred"].ID: - return _PriceRegistry.ParseOwnershipTransferred(log) - case _PriceRegistry.abi.Events["PremiumMultiplierWeiPerEthUpdated"].ID: - return _PriceRegistry.ParsePremiumMultiplierWeiPerEthUpdated(log) - case _PriceRegistry.abi.Events["PriceFeedPerTokenUpdated"].ID: - return _PriceRegistry.ParsePriceFeedPerTokenUpdated(log) - case _PriceRegistry.abi.Events["ReportPermissionSet"].ID: - return _PriceRegistry.ParseReportPermissionSet(log) - case _PriceRegistry.abi.Events["TokenTransferFeeConfigDeleted"].ID: - return _PriceRegistry.ParseTokenTransferFeeConfigDeleted(log) - case _PriceRegistry.abi.Events["TokenTransferFeeConfigUpdated"].ID: - return _PriceRegistry.ParseTokenTransferFeeConfigUpdated(log) - case _PriceRegistry.abi.Events["UsdPerTokenUpdated"].ID: - return _PriceRegistry.ParseUsdPerTokenUpdated(log) - case _PriceRegistry.abi.Events["UsdPerUnitGasUpdated"].ID: - return _PriceRegistry.ParseUsdPerUnitGasUpdated(log) + case _FeeQuoter.abi.Events["AuthorizedCallerAdded"].ID: + return _FeeQuoter.ParseAuthorizedCallerAdded(log) + case _FeeQuoter.abi.Events["AuthorizedCallerRemoved"].ID: + return _FeeQuoter.ParseAuthorizedCallerRemoved(log) + case _FeeQuoter.abi.Events["DestChainAdded"].ID: + return _FeeQuoter.ParseDestChainAdded(log) + case _FeeQuoter.abi.Events["DestChainConfigUpdated"].ID: + return _FeeQuoter.ParseDestChainConfigUpdated(log) + case _FeeQuoter.abi.Events["FeeTokenAdded"].ID: + return _FeeQuoter.ParseFeeTokenAdded(log) + case _FeeQuoter.abi.Events["FeeTokenRemoved"].ID: + return _FeeQuoter.ParseFeeTokenRemoved(log) + case _FeeQuoter.abi.Events["OwnershipTransferRequested"].ID: + return _FeeQuoter.ParseOwnershipTransferRequested(log) + case _FeeQuoter.abi.Events["OwnershipTransferred"].ID: + return _FeeQuoter.ParseOwnershipTransferred(log) + case _FeeQuoter.abi.Events["PremiumMultiplierWeiPerEthUpdated"].ID: + return _FeeQuoter.ParsePremiumMultiplierWeiPerEthUpdated(log) + case _FeeQuoter.abi.Events["PriceFeedPerTokenUpdated"].ID: + return _FeeQuoter.ParsePriceFeedPerTokenUpdated(log) + case _FeeQuoter.abi.Events["ReportPermissionSet"].ID: + return _FeeQuoter.ParseReportPermissionSet(log) + case _FeeQuoter.abi.Events["TokenTransferFeeConfigDeleted"].ID: + return _FeeQuoter.ParseTokenTransferFeeConfigDeleted(log) + case _FeeQuoter.abi.Events["TokenTransferFeeConfigUpdated"].ID: + return _FeeQuoter.ParseTokenTransferFeeConfigUpdated(log) + case _FeeQuoter.abi.Events["UsdPerTokenUpdated"].ID: + return _FeeQuoter.ParseUsdPerTokenUpdated(log) + case _FeeQuoter.abi.Events["UsdPerUnitGasUpdated"].ID: + return _FeeQuoter.ParseUsdPerUnitGasUpdated(log) default: return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) } } -func (PriceRegistryAuthorizedCallerAdded) Topic() common.Hash { +func (FeeQuoterAuthorizedCallerAdded) Topic() common.Hash { return common.HexToHash("0xeb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef") } -func (PriceRegistryAuthorizedCallerRemoved) Topic() common.Hash { +func (FeeQuoterAuthorizedCallerRemoved) Topic() common.Hash { return common.HexToHash("0xc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda77580") } -func (PriceRegistryDestChainAdded) Topic() common.Hash { +func (FeeQuoterDestChainAdded) Topic() common.Hash { return common.HexToHash("0xd31c671936387b2f84ed402b553bd50c0e9c20408ea4e91a836d77b8180fb724") } -func (PriceRegistryDestChainConfigUpdated) Topic() common.Hash { +func (FeeQuoterDestChainConfigUpdated) Topic() common.Hash { return common.HexToHash("0x1edd6f3553cfa16f10b95b195abae3a1cfca4783de4843f95d674b1e1df5ab20") } -func (PriceRegistryFeeTokenAdded) Topic() common.Hash { +func (FeeQuoterFeeTokenAdded) Topic() common.Hash { return common.HexToHash("0xdf1b1bd32a69711488d71554706bb130b1fc63a5fa1a2cd85e8440f84065ba23") } -func (PriceRegistryFeeTokenRemoved) Topic() common.Hash { +func (FeeQuoterFeeTokenRemoved) Topic() common.Hash { return common.HexToHash("0x1795838dc8ab2ffc5f431a1729a6afa0b587f982f7b2be0b9d7187a1ef547f91") } -func (PriceRegistryOwnershipTransferRequested) Topic() common.Hash { +func (FeeQuoterOwnershipTransferRequested) Topic() common.Hash { return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") } -func (PriceRegistryOwnershipTransferred) Topic() common.Hash { +func (FeeQuoterOwnershipTransferred) Topic() common.Hash { return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") } -func (PriceRegistryPremiumMultiplierWeiPerEthUpdated) Topic() common.Hash { +func (FeeQuoterPremiumMultiplierWeiPerEthUpdated) Topic() common.Hash { return common.HexToHash("0xbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d") } -func (PriceRegistryPriceFeedPerTokenUpdated) Topic() common.Hash { +func (FeeQuoterPriceFeedPerTokenUpdated) Topic() common.Hash { return common.HexToHash("0x08a5f7f5bb38a81d8e43aca13ecd76431dbf8816ae4699affff7b00b2fc1c464") } -func (PriceRegistryReportPermissionSet) Topic() common.Hash { +func (FeeQuoterReportPermissionSet) Topic() common.Hash { return common.HexToHash("0x32a4ba3fa3351b11ad555d4c8ec70a744e8705607077a946807030d64b6ab1a3") } -func (PriceRegistryTokenTransferFeeConfigDeleted) Topic() common.Hash { +func (FeeQuoterTokenTransferFeeConfigDeleted) Topic() common.Hash { return common.HexToHash("0x4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b") } -func (PriceRegistryTokenTransferFeeConfigUpdated) Topic() common.Hash { +func (FeeQuoterTokenTransferFeeConfigUpdated) Topic() common.Hash { return common.HexToHash("0x94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b5") } -func (PriceRegistryUsdPerTokenUpdated) Topic() common.Hash { +func (FeeQuoterUsdPerTokenUpdated) Topic() common.Hash { return common.HexToHash("0x52f50aa6d1a95a4595361ecf953d095f125d442e4673716dede699e049de148a") } -func (PriceRegistryUsdPerUnitGasUpdated) Topic() common.Hash { +func (FeeQuoterUsdPerUnitGasUpdated) Topic() common.Hash { return common.HexToHash("0xdd84a3fa9ef9409f550d54d6affec7e9c480c878c6ab27b78912a03e1b371c6e") } -func (_PriceRegistry *PriceRegistry) Address() common.Address { - return _PriceRegistry.address +func (_FeeQuoter *FeeQuoter) Address() common.Address { + return _FeeQuoter.address } -type PriceRegistryInterface interface { +type FeeQuoterInterface interface { ConvertTokenAmount(opts *bind.CallOpts, fromToken common.Address, fromTokenAmount *big.Int, toToken common.Address) (*big.Int, error) GetAllAuthorizedCallers(opts *bind.CallOpts) ([]common.Address, error) - GetDestChainConfig(opts *bind.CallOpts, destChainSelector uint64) (PriceRegistryDestChainConfig, error) + GetDestChainConfig(opts *bind.CallOpts, destChainSelector uint64) (FeeQuoterDestChainConfig, error) GetDestinationChainGasPrice(opts *bind.CallOpts, destChainSelector uint64) (InternalTimestampedPackedUint224, error) @@ -2895,7 +2895,7 @@ type PriceRegistryInterface interface { GetPremiumMultiplierWeiPerEth(opts *bind.CallOpts, token common.Address) (uint64, error) - GetStaticConfig(opts *bind.CallOpts) (PriceRegistryStaticConfig, error) + GetStaticConfig(opts *bind.CallOpts) (FeeQuoterStaticConfig, error) GetTokenAndGasPrices(opts *bind.CallOpts, token common.Address, destChainSelector uint64) (GetTokenAndGasPrices, @@ -2903,11 +2903,11 @@ type PriceRegistryInterface interface { GetTokenPrice(opts *bind.CallOpts, token common.Address) (InternalTimestampedPackedUint224, error) - GetTokenPriceFeedConfig(opts *bind.CallOpts, token common.Address) (IPriceRegistryTokenPriceFeedConfig, error) + GetTokenPriceFeedConfig(opts *bind.CallOpts, token common.Address) (IFeeQuoterTokenPriceFeedConfig, error) GetTokenPrices(opts *bind.CallOpts, tokens []common.Address) ([]InternalTimestampedPackedUint224, error) - GetTokenTransferFeeConfig(opts *bind.CallOpts, destChainSelector uint64, token common.Address) (PriceRegistryTokenTransferFeeConfig, error) + GetTokenTransferFeeConfig(opts *bind.CallOpts, destChainSelector uint64, token common.Address) (FeeQuoterTokenTransferFeeConfig, error) GetValidatedFee(opts *bind.CallOpts, destChainSelector uint64, message ClientEVM2AnyMessage) (*big.Int, error) @@ -2927,13 +2927,13 @@ type PriceRegistryInterface interface { ApplyAuthorizedCallerUpdates(opts *bind.TransactOpts, authorizedCallerArgs AuthorizedCallersAuthorizedCallerArgs) (*types.Transaction, error) - ApplyDestChainConfigUpdates(opts *bind.TransactOpts, destChainConfigArgs []PriceRegistryDestChainConfigArgs) (*types.Transaction, error) + ApplyDestChainConfigUpdates(opts *bind.TransactOpts, destChainConfigArgs []FeeQuoterDestChainConfigArgs) (*types.Transaction, error) ApplyFeeTokensUpdates(opts *bind.TransactOpts, feeTokensToAdd []common.Address, feeTokensToRemove []common.Address) (*types.Transaction, error) - ApplyPremiumMultiplierWeiPerEthUpdates(opts *bind.TransactOpts, premiumMultiplierWeiPerEthArgs []PriceRegistryPremiumMultiplierWeiPerEthArgs) (*types.Transaction, error) + ApplyPremiumMultiplierWeiPerEthUpdates(opts *bind.TransactOpts, premiumMultiplierWeiPerEthArgs []FeeQuoterPremiumMultiplierWeiPerEthArgs) (*types.Transaction, error) - ApplyTokenTransferFeeConfigUpdates(opts *bind.TransactOpts, tokenTransferFeeConfigArgs []PriceRegistryTokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs []PriceRegistryTokenTransferFeeConfigRemoveArgs) (*types.Transaction, error) + ApplyTokenTransferFeeConfigUpdates(opts *bind.TransactOpts, tokenTransferFeeConfigArgs []FeeQuoterTokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs []FeeQuoterTokenTransferFeeConfigRemoveArgs) (*types.Transaction, error) OnReport(opts *bind.TransactOpts, metadata []byte, report []byte) (*types.Transaction, error) @@ -2943,97 +2943,97 @@ type PriceRegistryInterface interface { UpdatePrices(opts *bind.TransactOpts, priceUpdates InternalPriceUpdates) (*types.Transaction, error) - UpdateTokenPriceFeeds(opts *bind.TransactOpts, tokenPriceFeedUpdates []PriceRegistryTokenPriceFeedUpdate) (*types.Transaction, error) + UpdateTokenPriceFeeds(opts *bind.TransactOpts, tokenPriceFeedUpdates []FeeQuoterTokenPriceFeedUpdate) (*types.Transaction, error) - FilterAuthorizedCallerAdded(opts *bind.FilterOpts) (*PriceRegistryAuthorizedCallerAddedIterator, error) + FilterAuthorizedCallerAdded(opts *bind.FilterOpts) (*FeeQuoterAuthorizedCallerAddedIterator, error) - WatchAuthorizedCallerAdded(opts *bind.WatchOpts, sink chan<- *PriceRegistryAuthorizedCallerAdded) (event.Subscription, error) + WatchAuthorizedCallerAdded(opts *bind.WatchOpts, sink chan<- *FeeQuoterAuthorizedCallerAdded) (event.Subscription, error) - ParseAuthorizedCallerAdded(log types.Log) (*PriceRegistryAuthorizedCallerAdded, error) + ParseAuthorizedCallerAdded(log types.Log) (*FeeQuoterAuthorizedCallerAdded, error) - FilterAuthorizedCallerRemoved(opts *bind.FilterOpts) (*PriceRegistryAuthorizedCallerRemovedIterator, error) + FilterAuthorizedCallerRemoved(opts *bind.FilterOpts) (*FeeQuoterAuthorizedCallerRemovedIterator, error) - WatchAuthorizedCallerRemoved(opts *bind.WatchOpts, sink chan<- *PriceRegistryAuthorizedCallerRemoved) (event.Subscription, error) + WatchAuthorizedCallerRemoved(opts *bind.WatchOpts, sink chan<- *FeeQuoterAuthorizedCallerRemoved) (event.Subscription, error) - ParseAuthorizedCallerRemoved(log types.Log) (*PriceRegistryAuthorizedCallerRemoved, error) + ParseAuthorizedCallerRemoved(log types.Log) (*FeeQuoterAuthorizedCallerRemoved, error) - FilterDestChainAdded(opts *bind.FilterOpts, destChainSelector []uint64) (*PriceRegistryDestChainAddedIterator, error) + FilterDestChainAdded(opts *bind.FilterOpts, destChainSelector []uint64) (*FeeQuoterDestChainAddedIterator, error) - WatchDestChainAdded(opts *bind.WatchOpts, sink chan<- *PriceRegistryDestChainAdded, destChainSelector []uint64) (event.Subscription, error) + WatchDestChainAdded(opts *bind.WatchOpts, sink chan<- *FeeQuoterDestChainAdded, destChainSelector []uint64) (event.Subscription, error) - ParseDestChainAdded(log types.Log) (*PriceRegistryDestChainAdded, error) + ParseDestChainAdded(log types.Log) (*FeeQuoterDestChainAdded, error) - FilterDestChainConfigUpdated(opts *bind.FilterOpts, destChainSelector []uint64) (*PriceRegistryDestChainConfigUpdatedIterator, error) + FilterDestChainConfigUpdated(opts *bind.FilterOpts, destChainSelector []uint64) (*FeeQuoterDestChainConfigUpdatedIterator, error) - WatchDestChainConfigUpdated(opts *bind.WatchOpts, sink chan<- *PriceRegistryDestChainConfigUpdated, destChainSelector []uint64) (event.Subscription, error) + WatchDestChainConfigUpdated(opts *bind.WatchOpts, sink chan<- *FeeQuoterDestChainConfigUpdated, destChainSelector []uint64) (event.Subscription, error) - ParseDestChainConfigUpdated(log types.Log) (*PriceRegistryDestChainConfigUpdated, error) + ParseDestChainConfigUpdated(log types.Log) (*FeeQuoterDestChainConfigUpdated, error) - FilterFeeTokenAdded(opts *bind.FilterOpts, feeToken []common.Address) (*PriceRegistryFeeTokenAddedIterator, error) + FilterFeeTokenAdded(opts *bind.FilterOpts, feeToken []common.Address) (*FeeQuoterFeeTokenAddedIterator, error) - WatchFeeTokenAdded(opts *bind.WatchOpts, sink chan<- *PriceRegistryFeeTokenAdded, feeToken []common.Address) (event.Subscription, error) + WatchFeeTokenAdded(opts *bind.WatchOpts, sink chan<- *FeeQuoterFeeTokenAdded, feeToken []common.Address) (event.Subscription, error) - ParseFeeTokenAdded(log types.Log) (*PriceRegistryFeeTokenAdded, error) + ParseFeeTokenAdded(log types.Log) (*FeeQuoterFeeTokenAdded, error) - FilterFeeTokenRemoved(opts *bind.FilterOpts, feeToken []common.Address) (*PriceRegistryFeeTokenRemovedIterator, error) + FilterFeeTokenRemoved(opts *bind.FilterOpts, feeToken []common.Address) (*FeeQuoterFeeTokenRemovedIterator, error) - WatchFeeTokenRemoved(opts *bind.WatchOpts, sink chan<- *PriceRegistryFeeTokenRemoved, feeToken []common.Address) (event.Subscription, error) + WatchFeeTokenRemoved(opts *bind.WatchOpts, sink chan<- *FeeQuoterFeeTokenRemoved, feeToken []common.Address) (event.Subscription, error) - ParseFeeTokenRemoved(log types.Log) (*PriceRegistryFeeTokenRemoved, error) + ParseFeeTokenRemoved(log types.Log) (*FeeQuoterFeeTokenRemoved, error) - FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*PriceRegistryOwnershipTransferRequestedIterator, error) + FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*FeeQuoterOwnershipTransferRequestedIterator, error) - WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *PriceRegistryOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) + WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *FeeQuoterOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) - ParseOwnershipTransferRequested(log types.Log) (*PriceRegistryOwnershipTransferRequested, error) + ParseOwnershipTransferRequested(log types.Log) (*FeeQuoterOwnershipTransferRequested, error) - FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*PriceRegistryOwnershipTransferredIterator, error) + FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*FeeQuoterOwnershipTransferredIterator, error) - WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *PriceRegistryOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) + WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *FeeQuoterOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) - ParseOwnershipTransferred(log types.Log) (*PriceRegistryOwnershipTransferred, error) + ParseOwnershipTransferred(log types.Log) (*FeeQuoterOwnershipTransferred, error) - FilterPremiumMultiplierWeiPerEthUpdated(opts *bind.FilterOpts, token []common.Address) (*PriceRegistryPremiumMultiplierWeiPerEthUpdatedIterator, error) + FilterPremiumMultiplierWeiPerEthUpdated(opts *bind.FilterOpts, token []common.Address) (*FeeQuoterPremiumMultiplierWeiPerEthUpdatedIterator, error) - WatchPremiumMultiplierWeiPerEthUpdated(opts *bind.WatchOpts, sink chan<- *PriceRegistryPremiumMultiplierWeiPerEthUpdated, token []common.Address) (event.Subscription, error) + WatchPremiumMultiplierWeiPerEthUpdated(opts *bind.WatchOpts, sink chan<- *FeeQuoterPremiumMultiplierWeiPerEthUpdated, token []common.Address) (event.Subscription, error) - ParsePremiumMultiplierWeiPerEthUpdated(log types.Log) (*PriceRegistryPremiumMultiplierWeiPerEthUpdated, error) + ParsePremiumMultiplierWeiPerEthUpdated(log types.Log) (*FeeQuoterPremiumMultiplierWeiPerEthUpdated, error) - FilterPriceFeedPerTokenUpdated(opts *bind.FilterOpts, token []common.Address) (*PriceRegistryPriceFeedPerTokenUpdatedIterator, error) + FilterPriceFeedPerTokenUpdated(opts *bind.FilterOpts, token []common.Address) (*FeeQuoterPriceFeedPerTokenUpdatedIterator, error) - WatchPriceFeedPerTokenUpdated(opts *bind.WatchOpts, sink chan<- *PriceRegistryPriceFeedPerTokenUpdated, token []common.Address) (event.Subscription, error) + WatchPriceFeedPerTokenUpdated(opts *bind.WatchOpts, sink chan<- *FeeQuoterPriceFeedPerTokenUpdated, token []common.Address) (event.Subscription, error) - ParsePriceFeedPerTokenUpdated(log types.Log) (*PriceRegistryPriceFeedPerTokenUpdated, error) + ParsePriceFeedPerTokenUpdated(log types.Log) (*FeeQuoterPriceFeedPerTokenUpdated, error) - FilterReportPermissionSet(opts *bind.FilterOpts, reportId [][32]byte) (*PriceRegistryReportPermissionSetIterator, error) + FilterReportPermissionSet(opts *bind.FilterOpts, reportId [][32]byte) (*FeeQuoterReportPermissionSetIterator, error) - WatchReportPermissionSet(opts *bind.WatchOpts, sink chan<- *PriceRegistryReportPermissionSet, reportId [][32]byte) (event.Subscription, error) + WatchReportPermissionSet(opts *bind.WatchOpts, sink chan<- *FeeQuoterReportPermissionSet, reportId [][32]byte) (event.Subscription, error) - ParseReportPermissionSet(log types.Log) (*PriceRegistryReportPermissionSet, error) + ParseReportPermissionSet(log types.Log) (*FeeQuoterReportPermissionSet, error) - FilterTokenTransferFeeConfigDeleted(opts *bind.FilterOpts, destChainSelector []uint64, token []common.Address) (*PriceRegistryTokenTransferFeeConfigDeletedIterator, error) + FilterTokenTransferFeeConfigDeleted(opts *bind.FilterOpts, destChainSelector []uint64, token []common.Address) (*FeeQuoterTokenTransferFeeConfigDeletedIterator, error) - WatchTokenTransferFeeConfigDeleted(opts *bind.WatchOpts, sink chan<- *PriceRegistryTokenTransferFeeConfigDeleted, destChainSelector []uint64, token []common.Address) (event.Subscription, error) + WatchTokenTransferFeeConfigDeleted(opts *bind.WatchOpts, sink chan<- *FeeQuoterTokenTransferFeeConfigDeleted, destChainSelector []uint64, token []common.Address) (event.Subscription, error) - ParseTokenTransferFeeConfigDeleted(log types.Log) (*PriceRegistryTokenTransferFeeConfigDeleted, error) + ParseTokenTransferFeeConfigDeleted(log types.Log) (*FeeQuoterTokenTransferFeeConfigDeleted, error) - FilterTokenTransferFeeConfigUpdated(opts *bind.FilterOpts, destChainSelector []uint64, token []common.Address) (*PriceRegistryTokenTransferFeeConfigUpdatedIterator, error) + FilterTokenTransferFeeConfigUpdated(opts *bind.FilterOpts, destChainSelector []uint64, token []common.Address) (*FeeQuoterTokenTransferFeeConfigUpdatedIterator, error) - WatchTokenTransferFeeConfigUpdated(opts *bind.WatchOpts, sink chan<- *PriceRegistryTokenTransferFeeConfigUpdated, destChainSelector []uint64, token []common.Address) (event.Subscription, error) + WatchTokenTransferFeeConfigUpdated(opts *bind.WatchOpts, sink chan<- *FeeQuoterTokenTransferFeeConfigUpdated, destChainSelector []uint64, token []common.Address) (event.Subscription, error) - ParseTokenTransferFeeConfigUpdated(log types.Log) (*PriceRegistryTokenTransferFeeConfigUpdated, error) + ParseTokenTransferFeeConfigUpdated(log types.Log) (*FeeQuoterTokenTransferFeeConfigUpdated, error) - FilterUsdPerTokenUpdated(opts *bind.FilterOpts, token []common.Address) (*PriceRegistryUsdPerTokenUpdatedIterator, error) + FilterUsdPerTokenUpdated(opts *bind.FilterOpts, token []common.Address) (*FeeQuoterUsdPerTokenUpdatedIterator, error) - WatchUsdPerTokenUpdated(opts *bind.WatchOpts, sink chan<- *PriceRegistryUsdPerTokenUpdated, token []common.Address) (event.Subscription, error) + WatchUsdPerTokenUpdated(opts *bind.WatchOpts, sink chan<- *FeeQuoterUsdPerTokenUpdated, token []common.Address) (event.Subscription, error) - ParseUsdPerTokenUpdated(log types.Log) (*PriceRegistryUsdPerTokenUpdated, error) + ParseUsdPerTokenUpdated(log types.Log) (*FeeQuoterUsdPerTokenUpdated, error) - FilterUsdPerUnitGasUpdated(opts *bind.FilterOpts, destChain []uint64) (*PriceRegistryUsdPerUnitGasUpdatedIterator, error) + FilterUsdPerUnitGasUpdated(opts *bind.FilterOpts, destChain []uint64) (*FeeQuoterUsdPerUnitGasUpdatedIterator, error) - WatchUsdPerUnitGasUpdated(opts *bind.WatchOpts, sink chan<- *PriceRegistryUsdPerUnitGasUpdated, destChain []uint64) (event.Subscription, error) + WatchUsdPerUnitGasUpdated(opts *bind.WatchOpts, sink chan<- *FeeQuoterUsdPerUnitGasUpdated, destChain []uint64) (event.Subscription, error) - ParseUsdPerUnitGasUpdated(log types.Log) (*PriceRegistryUsdPerUnitGasUpdated, error) + ParseUsdPerUnitGasUpdated(log types.Log) (*FeeQuoterUsdPerUnitGasUpdated, error) ParseLog(log types.Log) (generated.AbigenLog, error) diff --git a/core/gethwrappers/ccip/generated/multi_aggregate_rate_limiter/multi_aggregate_rate_limiter.go b/core/gethwrappers/ccip/generated/multi_aggregate_rate_limiter/multi_aggregate_rate_limiter.go index d8a34b9483..e1942e68da 100644 --- a/core/gethwrappers/ccip/generated/multi_aggregate_rate_limiter/multi_aggregate_rate_limiter.go +++ b/core/gethwrappers/ccip/generated/multi_aggregate_rate_limiter/multi_aggregate_rate_limiter.go @@ -87,15 +87,15 @@ type RateLimiterTokenBucket struct { } var MultiAggregateRateLimiterMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"authorizedCallers\",\"type\":\"address[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"AggregateValueMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"}],\"name\":\"AggregateValueRateLimitReached\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BucketOverfilled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"errorReason\",\"type\":\"bytes\"}],\"name\":\"MessageValidationError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"PriceNotFoundForToken\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenRateLimitReached\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"UnauthorizedCaller\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroChainSelectorNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"AuthorizedCallerAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"AuthorizedCallerRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newPriceRegistry\",\"type\":\"address\"}],\"name\":\"PriceRegistrySet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"isOutboundLane\",\"type\":\"bool\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"RateLimiterConfigUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remoteToken\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"name\":\"TokenAggregateRateLimitAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"name\":\"TokenAggregateRateLimitRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"TokensConsumed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address[]\",\"name\":\"addedCallers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"removedCallers\",\"type\":\"address[]\"}],\"internalType\":\"structAuthorizedCallers.AuthorizedCallerArgs\",\"name\":\"authorizedCallerArgs\",\"type\":\"tuple\"}],\"name\":\"applyAuthorizedCallerUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isOutboundLane\",\"type\":\"bool\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"rateLimiterConfig\",\"type\":\"tuple\"}],\"internalType\":\"structMultiAggregateRateLimiter.RateLimiterConfigArgs[]\",\"name\":\"rateLimiterUpdates\",\"type\":\"tuple[]\"}],\"name\":\"applyRateLimiterConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isOutboundLane\",\"type\":\"bool\"}],\"name\":\"currentRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllAuthorizedCallers\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getAllRateLimitTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"localTokens\",\"type\":\"address[]\"},{\"internalType\":\"bytes[]\",\"name\":\"remoteTokens\",\"type\":\"bytes[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getPriceRegistry\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"destTokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structClient.Any2EVMMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"onInboundMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"onOutboundMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newPriceRegistry\",\"type\":\"address\"}],\"name\":\"setPriceRegistry\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"internalType\":\"structMultiAggregateRateLimiter.LocalRateLimitToken[]\",\"name\":\"removes\",\"type\":\"tuple[]\"},{\"components\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"internalType\":\"structMultiAggregateRateLimiter.LocalRateLimitToken\",\"name\":\"localTokenArgs\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"remoteToken\",\"type\":\"bytes\"}],\"internalType\":\"structMultiAggregateRateLimiter.RateLimitTokenArgs[]\",\"name\":\"adds\",\"type\":\"tuple[]\"}],\"name\":\"updateRateLimitTokens\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x60806040523480156200001157600080fd5b506040516200327338038062003273833981016040819052620000349162000538565b8033806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf8162000102565b5050604080518082018252838152815160008152602080820190935291810191909152620000ee9150620001ad565b50620000fa82620002fc565b50506200066f565b336001600160a01b038216036200015c5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b602081015160005b81518110156200023d576000828281518110620001d657620001d662000621565b60209081029190910101519050620001f060028262000378565b1562000233576040516001600160a01b03821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b50600101620001b5565b50815160005b8151811015620002f657600082828151811062000264576200026462000621565b6020026020010151905060006001600160a01b0316816001600160a01b031603620002a2576040516342bcdf7f60e11b815260040160405180910390fd5b620002af60028262000398565b506040516001600160a01b03821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a15060010162000243565b50505050565b6001600160a01b03811662000324576040516342bcdf7f60e11b815260040160405180910390fd5b600580546001600160a01b0319166001600160a01b0383169081179091556040519081527fdeaac1a8daeabcc5254b10b54edf3678fdfcd1cea89fe9d364b6285f6ace2df99060200160405180910390a150565b60006200038f836001600160a01b038416620003af565b90505b92915050565b60006200038f836001600160a01b038416620004b3565b60008181526001830160205260408120548015620004a8576000620003d660018362000637565b8554909150600090620003ec9060019062000637565b90508181146200045857600086600001828154811062000410576200041062000621565b906000526020600020015490508087600001848154811062000436576200043662000621565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806200046c576200046c62000659565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505062000392565b600091505062000392565b6000818152600183016020526040812054620004fc5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000392565b50600062000392565b80516001600160a01b03811681146200051d57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200054c57600080fd5b620005578362000505565b602084810151919350906001600160401b03808211156200057757600080fd5b818601915086601f8301126200058c57600080fd5b815181811115620005a157620005a162000522565b8060051b604051601f19603f83011681018181108582111715620005c957620005c962000522565b604052918252848201925083810185019189831115620005e857600080fd5b938501935b828510156200061157620006018562000505565b84529385019392850192620005ed565b8096505050505050509250929050565b634e487b7160e01b600052603260045260246000fd5b818103818111156200039257634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b612bf4806200067f6000396000f3fe608060405234801561001057600080fd5b50600436106100ea5760003560e01c8063537e304e1161008c57806391a2749a1161006657806391a2749a14610252578063e0a0e50614610265578063f2fde38b14610278578063fe843cd01461028b57600080fd5b8063537e304e1461020b57806379ba50971461022c5780638da5cb5b1461023457600080fd5b8063181f5a77116100c8578063181f5a77146101bb5780631af18b7b146101d05780632451a627146101e3578063508ee9de146101f857600080fd5b806308d450a1146100ef5780630a35bcc4146101045780630d6c107e1461017c575b600080fd5b6101026100fd366004612003565b61029e565b005b6101176101123660046120e3565b6102bd565b604051610173919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b60405180910390f35b60055473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610173565b6101c3610382565b604051610173919061217a565b6101026101de3660046122b4565b61039e565b6101eb6105ca565b60405161017391906123d1565b6101026102063660046123e4565b6105db565b61021e6102193660046123ff565b6105ec565b60405161017392919061241a565b610102610759565b60005473ffffffffffffffffffffffffffffffffffffffff16610196565b610102610260366004612510565b61085b565b6101026102733660046125a1565b61086c565b6101026102863660046123e4565b6108e1565b610102610299366004612616565b6108f2565b6102a6610c31565b6102ba816020015182608001516000610c76565b50565b6040805160a0810182526000808252602082018190529181018290526060810182905260808101919091526103796102f58484610d4d565b6040805160a08101825282546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff1660208501527401000000000000000000000000000000000000000090920460ff16151593830193909352600190930154808316606083015292909204166080820152610d7d565b90505b92915050565b604051806060016040528060238152602001612bc56023913981565b6103a6610e2f565b60005b82518110156104845760008382815181106103c6576103c661274a565b602002602001015160200151905060008483815181106103e8576103e861274a565b6020908102919091018101515167ffffffffffffffff811660009081526004909252604090912090915061041c9083610eb0565b1561047a576040805167ffffffffffffffff8316815273ffffffffffffffffffffffffffffffffffffffff841660208201527f530cabd30786b7235e124a6c0db77e0b685ef22813b1fe87554247f404eb8ed6910160405180910390a15b50506001016103a9565b5060005b81518110156105c55760008282815181106104a5576104a561274a565b602002602001015160000151905060008383815181106104c7576104c761274a565b6020026020010151602001519050600082602001519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16148061051857508151155b1561054f576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b825167ffffffffffffffff81166000908152600460205260409020610575908385610ed2565b156105b6577fad72a792d2a307f400c278be7deaeec6964276783304580cdc4e905436b8d5c58184846040516105ad93929190612779565b60405180910390a15b50505050806001019050610488565b505050565b60606105d66002610eff565b905090565b6105e3610e2f565b6102ba81610f0c565b67ffffffffffffffff81166000908152600460205260408120606091829161061390610fd2565b90508067ffffffffffffffff81111561062e5761062e611d74565b604051908082528060200260200182016040528015610657578160200160208202803683370190505b5092508067ffffffffffffffff81111561067357610673611d74565b6040519080825280602002602001820160405280156106a657816020015b60608152602001906001900390816106915790505b50915060005b818110156107525767ffffffffffffffff8516600090815260046020526040812081906106d99084610fdd565b91509150818684815181106106f0576106f061274a565b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508085848151811061073d5761073d61274a565b602090810291909101015250506001016106ac565b5050915091565b60015473ffffffffffffffffffffffffffffffffffffffff1633146107df576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610863610e2f565b6102ba81610ffc565b610874610c31565b6108dd8261088560408401846127c2565b808060200260200160405190810160405280939291908181526020016000905b828210156108d1576108c26040830286013681900381019061282a565b815260200190600101906108a5565b50505050506001610c76565b5050565b6108e9610e2f565b6102ba81611188565b6108fa610e2f565b60005b81518110156108dd57600082828151811061091a5761091a61274a565b6020908102919091010151604081015181519192509067ffffffffffffffff8116600003610974576040517fc656089500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602083015160006109858383610d4d565b8054909150700100000000000000000000000000000000900463ffffffff16600003610bd3576040805160a081018252602080870180516fffffffffffffffffffffffffffffffff908116845263ffffffff421692840192909252875115158385015251811660608301529186015190911660808201528215610aec5767ffffffffffffffff8416600090815260066020908152604091829020835160028201805493860151948601516fffffffffffffffffffffffffffffffff9283167fffffffffffffffffffffffff00000000000000000000000000000000000000009095169490941770010000000000000000000000000000000063ffffffff9096168602177fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000941515949094029390931790925560608401516080850151908316921690920217600390910155610bcd565b67ffffffffffffffff84166000908152600660209081526040918290208351815492850151938501516fffffffffffffffffffffffffffffffff9182167fffffffffffffffffffffffff00000000000000000000000000000000000000009094169390931770010000000000000000000000000000000063ffffffff9095168502177fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000093151593909302929092178155606084015160808501519083169216909202176001909101555b50610bdd565b610bdd818561127d565b8267ffffffffffffffff167ff14a5415ce6988a9e870a85fff0b9d7b7dd79bbc228cb63cad610daf6f7b6b978386604051610c19929190612846565b60405180910390a250505050508060010190506108fd565b610c3c60023361142c565b610c74576040517fd86ad9cf0000000000000000000000000000000000000000000000000000000081523360048201526024016107d6565b565b6000610c828483610d4d565b805490915074010000000000000000000000000000000000000000900460ff1615610d47576000805b8451811015610d3257610cf6858281518110610cc957610cc961274a565b6020908102919091018101515167ffffffffffffffff89166000908152600490925260409091209061145b565b15610d2a57610d1d858281518110610d1057610d1061274a565b602002602001015161147d565b610d2790836128b9565b91505b600101610cab565b508015610d4557610d45828260006115b9565b505b50505050565b67ffffffffffffffff821660009081526006602052604081208215610d7657600201905061037c565b905061037c565b6040805160a081018252600080825260208201819052918101829052606081018290526080810191909152610e0b82606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff1642610def91906128cc565b85608001516fffffffffffffffffffffffffffffffff1661193c565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b60005473ffffffffffffffffffffffffffffffffffffffff163314610c74576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016107d6565b60006103798373ffffffffffffffffffffffffffffffffffffffff8416611964565b6000610ef58473ffffffffffffffffffffffffffffffffffffffff851684611988565b90505b9392505050565b60606000610ef8836119ad565b73ffffffffffffffffffffffffffffffffffffffff8116610f59576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600580547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527fdeaac1a8daeabcc5254b10b54edf3678fdfcd1cea89fe9d364b6285f6ace2df99060200160405180910390a150565b600061037c82611a09565b600060608180610fed8686611a14565b909450925050505b9250929050565b602081015160005b81518110156110975760008282815181106110215761102161274a565b6020026020010151905061103f816002611ad190919063ffffffff16565b1561108e5760405173ffffffffffffffffffffffffffffffffffffffff821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b50600101611004565b50815160005b8151811015610d475760008282815181106110ba576110ba61274a565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361112a576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611135600282611af3565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a15060010161109d565b3373ffffffffffffffffffffffffffffffffffffffff821603611207576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016107d6565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b81546000906112a690700100000000000000000000000000000000900463ffffffff16426128cc565b9050801561134857600183015483546112ee916fffffffffffffffffffffffffffffffff8082169281169185917001000000000000000000000000000000009091041661193c565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177001000000000000000000000000000000004263ffffffff16021783555b6020820151835461136e916fffffffffffffffffffffffffffffffff9081169116611b15565b83548351151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff92831617178455602083015160408085015183167001000000000000000000000000000000000291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c199061141f9084906128df565b60405180910390a1505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515610379565b60006103798373ffffffffffffffffffffffffffffffffffffffff8416611b2b565b60055481516040517fd02641a000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff91821660048201526000928392169063d02641a0906024016040805180830381865afa1580156114f1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611515919061291b565b5190507bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811660000361158b5782516040517f9a655f7b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911660048201526024016107d6565b6020830151610ef8907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff831690611b37565b825474010000000000000000000000000000000000000000900460ff1615806115e0575081155b156115ea57505050565b825460018401546fffffffffffffffffffffffffffffffff8083169291169060009061163090700100000000000000000000000000000000900463ffffffff16426128cc565b905080156116f05781831115611672576040517f9725942a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018601546116ac9083908590849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff1661193c565b86547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004263ffffffff160217875592505b848210156117a75773ffffffffffffffffffffffffffffffffffffffff841661174f576040517ff94ebcd100000000000000000000000000000000000000000000000000000000815260048101839052602481018690526044016107d6565b6040517f1a76572a000000000000000000000000000000000000000000000000000000008152600481018390526024810186905273ffffffffffffffffffffffffffffffffffffffff851660448201526064016107d6565b848310156118ba5760018681015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff169060009082906117eb90826128cc565b6117f5878a6128cc565b6117ff91906128b9565b6118099190612986565b905073ffffffffffffffffffffffffffffffffffffffff8616611862576040517f15279c0800000000000000000000000000000000000000000000000000000000815260048101829052602481018690526044016107d6565b6040517fd0c8d23a000000000000000000000000000000000000000000000000000000008152600481018290526024810186905273ffffffffffffffffffffffffffffffffffffffff871660448201526064016107d6565b6118c485846128cc565b86547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff82161787556040518681529093507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a9060200160405180910390a1505050505050565b600061195b8561194c84866129c1565b61195690876128b9565b611b15565b95945050505050565b6000818152600283016020526040812061197e9082611d26565b6103798383611b74565b600082815260028401602052604081206119a28382612a7b565b50610ef58484611b80565b6060816000018054806020026020016040519081016040528092919081815260200182805480156119fd57602002820191906000526020600020905b8154815260200190600101908083116119e9575b50505050509050919050565b600061037c82611b8c565b6000606081611a238585611b96565b60008181526002870160205260409020805491925082918190611a45906129d8565b80601f0160208091040260200160405190810160405280929190818152602001828054611a71906129d8565b8015611abe5780601f10611a9357610100808354040283529160200191611abe565b820191906000526020600020905b815481529060010190602001808311611aa157829003601f168201915b5050505050905092509250509250929050565b60006103798373ffffffffffffffffffffffffffffffffffffffff8416611ba2565b60006103798373ffffffffffffffffffffffffffffffffffffffff8416611c95565b6000818310611b245781610379565b5090919050565b60006103798383611ce4565b6000670de0b6b3a7640000611b6a837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff86166129c1565b6103799190612986565b60006103798383611ba2565b60006103798383611c95565b600061037c825490565b60006103798383611cfc565b60008181526001830160205260408120548015611c8b576000611bc66001836128cc565b8554909150600090611bda906001906128cc565b9050818114611c3f576000866000018281548110611bfa57611bfa61274a565b9060005260206000200154905080876000018481548110611c1d57611c1d61274a565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080611c5057611c50612b95565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061037c565b600091505061037c565b6000818152600183016020526040812054611cdc5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561037c565b50600061037c565b60008181526001830160205260408120541515610379565b6000826000018281548110611d1357611d1361274a565b9060005260206000200154905092915050565b508054611d32906129d8565b6000825580601f10611d42575050565b601f0160209004906000526020600020908101906102ba91905b80821115611d705760008155600101611d5c565b5090565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715611dc657611dc6611d74565b60405290565b60405160a0810167ffffffffffffffff81118282101715611dc657611dc6611d74565b6040516060810167ffffffffffffffff81118282101715611dc657611dc6611d74565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611e5957611e59611d74565b604052919050565b803567ffffffffffffffff81168114611e7957600080fd5b919050565b600082601f830112611e8f57600080fd5b813567ffffffffffffffff811115611ea957611ea9611d74565b611eda60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611e12565b818152846020838601011115611eef57600080fd5b816020850160208301376000918101602001919091529392505050565b600067ffffffffffffffff821115611f2657611f26611d74565b5060051b60200190565b803573ffffffffffffffffffffffffffffffffffffffff81168114611e7957600080fd5b600060408284031215611f6657600080fd5b611f6e611da3565b9050611f7982611f30565b81526020820135602082015292915050565b600082601f830112611f9c57600080fd5b81356020611fb1611fac83611f0c565b611e12565b8083825260208201915060208460061b870101935086841115611fd357600080fd5b602086015b84811015611ff857611fea8882611f54565b835291830191604001611fd8565b509695505050505050565b60006020828403121561201557600080fd5b813567ffffffffffffffff8082111561202d57600080fd5b9083019060a0828603121561204157600080fd5b612049611dcc565b8235815261205960208401611e61565b602082015260408301358281111561207057600080fd5b61207c87828601611e7e565b60408301525060608301358281111561209457600080fd5b6120a087828601611e7e565b6060830152506080830135828111156120b857600080fd5b6120c487828601611f8b565b60808301525095945050505050565b80358015158114611e7957600080fd5b600080604083850312156120f657600080fd5b6120ff83611e61565b915061210d602084016120d3565b90509250929050565b6000815180845260005b8181101561213c57602081850181015186830182015201612120565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b6020815260006103796020830184612116565b60006040828403121561219f57600080fd5b6121a7611da3565b90506121b282611e61565b81526121c060208301611f30565b602082015292915050565b600082601f8301126121dc57600080fd5b813560206121ec611fac83611f0c565b82815260059290921b8401810191818101908684111561220b57600080fd5b8286015b84811015611ff857803567ffffffffffffffff808211156122305760008081fd5b81890191506060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848d030112156122695760008081fd5b612271611da3565b61227d8c89860161218d565b81529083013590828211156122925760008081fd5b6122a08c8984870101611e7e565b81890152865250505091830191830161220f565b60008060408084860312156122c857600080fd5b833567ffffffffffffffff808211156122e057600080fd5b818601915086601f8301126122f457600080fd5b81356020612304611fac83611f0c565b8083825260208201915060208460061b87010193508a84111561232657600080fd5b6020860195505b8386101561234e5761233f8b8761218d565b8252948601949082019061232d565b9750505050602086013592508083111561236757600080fd5b5050612375858286016121cb565b9150509250929050565b60008151808452602080850194506020840160005b838110156123c657815173ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101612394565b509495945050505050565b602081526000610379602083018461237f565b6000602082840312156123f657600080fd5b61037982611f30565b60006020828403121561241157600080fd5b61037982611e61565b60408152600061242d604083018561237f565b6020838203818501528185518084528284019150828160051b85010183880160005b8381101561249b577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0878403018552612489838351612116565b9486019492509085019060010161244f565b50909998505050505050505050565b600082601f8301126124bb57600080fd5b813560206124cb611fac83611f0c565b8083825260208201915060208460051b8701019350868411156124ed57600080fd5b602086015b84811015611ff85761250381611f30565b83529183019183016124f2565b60006020828403121561252257600080fd5b813567ffffffffffffffff8082111561253a57600080fd5b908301906040828603121561254e57600080fd5b612556611da3565b82358281111561256557600080fd5b612571878286016124aa565b82525060208301358281111561258657600080fd5b612592878286016124aa565b60208301525095945050505050565b600080604083850312156125b457600080fd5b6125bd83611e61565b9150602083013567ffffffffffffffff8111156125d957600080fd5b830160a081860312156125eb57600080fd5b809150509250929050565b80356fffffffffffffffffffffffffffffffff81168114611e7957600080fd5b6000602080838503121561262957600080fd5b823567ffffffffffffffff81111561264057600080fd5b8301601f8101851361265157600080fd5b803561265f611fac82611f0c565b81815260a0918202830184019184820191908884111561267e57600080fd5b938501935b8385101561273e578489038181121561269c5760008081fd5b6126a4611def565b6126ad87611e61565b81526126ba8888016120d3565b8882015260406060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0850112156126f25760008081fd5b6126fa611def565b9350612707828a016120d3565b8452612714818a016125f6565b8a85015250612725608089016125f6565b8382015281019190915283529384019391850191612683565b50979650505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b67ffffffffffffffff8416815260606020820152600061279c6060830185612116565b905073ffffffffffffffffffffffffffffffffffffffff83166040830152949350505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126127f757600080fd5b83018035915067ffffffffffffffff82111561281257600080fd5b6020019150600681901b3603821315610ff557600080fd5b60006040828403121561283c57600080fd5b6103798383611f54565b821515815260808101610ef860208301848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082018082111561037c5761037c61288a565b8181038181111561037c5761037c61288a565b6060810161037c82848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b60006040828403121561292d57600080fd5b612935611da3565b82517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116811461296157600080fd5b8152602083015163ffffffff8116811461297a57600080fd5b60208201529392505050565b6000826129bc577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b808202811582820484141761037c5761037c61288a565b600181811c908216806129ec57607f821691505b602082108103612a25577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b601f8211156105c5576000816000526020600020601f850160051c81016020861015612a545750805b601f850160051c820191505b81811015612a7357828155600101612a60565b505050505050565b815167ffffffffffffffff811115612a9557612a95611d74565b612aa981612aa384546129d8565b84612a2b565b602080601f831160018114612afc5760008415612ac65750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555612a73565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015612b4957888601518255948401946001909101908401612b2a565b5085821015612b8557878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfe4d756c7469416767726567617465526174654c696d6974657220312e362e302d646576a164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"authorizedCallers\",\"type\":\"address[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"AggregateValueMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"}],\"name\":\"AggregateValueRateLimitReached\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BucketOverfilled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"errorReason\",\"type\":\"bytes\"}],\"name\":\"MessageValidationError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"PriceNotFoundForToken\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"capacity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenMaxCapacityExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minWaitInSeconds\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"}],\"name\":\"TokenRateLimitReached\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"UnauthorizedCaller\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroChainSelectorNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"AuthorizedCallerAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"AuthorizedCallerRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newFeeQuoter\",\"type\":\"address\"}],\"name\":\"FeeQuoterSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"isOutboundLane\",\"type\":\"bool\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"indexed\":false,\"internalType\":\"structRateLimiter.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"RateLimiterConfigUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"remoteToken\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"name\":\"TokenAggregateRateLimitAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"name\":\"TokenAggregateRateLimitRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokens\",\"type\":\"uint256\"}],\"name\":\"TokensConsumed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address[]\",\"name\":\"addedCallers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"removedCallers\",\"type\":\"address[]\"}],\"internalType\":\"structAuthorizedCallers.AuthorizedCallerArgs\",\"name\":\"authorizedCallerArgs\",\"type\":\"tuple\"}],\"name\":\"applyAuthorizedCallerUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isOutboundLane\",\"type\":\"bool\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.Config\",\"name\":\"rateLimiterConfig\",\"type\":\"tuple\"}],\"internalType\":\"structMultiAggregateRateLimiter.RateLimiterConfigArgs[]\",\"name\":\"rateLimiterUpdates\",\"type\":\"tuple[]\"}],\"name\":\"applyRateLimiterConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isOutboundLane\",\"type\":\"bool\"}],\"name\":\"currentRateLimiterState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint128\",\"name\":\"tokens\",\"type\":\"uint128\"},{\"internalType\":\"uint32\",\"name\":\"lastUpdated\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint128\",\"name\":\"capacity\",\"type\":\"uint128\"},{\"internalType\":\"uint128\",\"name\":\"rate\",\"type\":\"uint128\"}],\"internalType\":\"structRateLimiter.TokenBucket\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllAuthorizedCallers\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"}],\"name\":\"getAllRateLimitTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"localTokens\",\"type\":\"address[]\"},{\"internalType\":\"bytes[]\",\"name\":\"remoteTokens\",\"type\":\"bytes[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getFeeQuoter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"destTokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structClient.Any2EVMMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"onInboundMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"onOutboundMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newFeeQuoter\",\"type\":\"address\"}],\"name\":\"setFeeQuoter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"internalType\":\"structMultiAggregateRateLimiter.LocalRateLimitToken[]\",\"name\":\"removes\",\"type\":\"tuple[]\"},{\"components\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"remoteChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"localToken\",\"type\":\"address\"}],\"internalType\":\"structMultiAggregateRateLimiter.LocalRateLimitToken\",\"name\":\"localTokenArgs\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"remoteToken\",\"type\":\"bytes\"}],\"internalType\":\"structMultiAggregateRateLimiter.RateLimitTokenArgs[]\",\"name\":\"adds\",\"type\":\"tuple[]\"}],\"name\":\"updateRateLimitTokens\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x60806040523480156200001157600080fd5b506040516200327338038062003273833981016040819052620000349162000538565b8033806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf8162000102565b5050604080518082018252838152815160008152602080820190935291810191909152620000ee9150620001ad565b50620000fa82620002fc565b50506200066f565b336001600160a01b038216036200015c5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b602081015160005b81518110156200023d576000828281518110620001d657620001d662000621565b60209081029190910101519050620001f060028262000378565b1562000233576040516001600160a01b03821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b50600101620001b5565b50815160005b8151811015620002f657600082828151811062000264576200026462000621565b6020026020010151905060006001600160a01b0316816001600160a01b031603620002a2576040516342bcdf7f60e11b815260040160405180910390fd5b620002af60028262000398565b506040516001600160a01b03821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a15060010162000243565b50505050565b6001600160a01b03811662000324576040516342bcdf7f60e11b815260040160405180910390fd5b600580546001600160a01b0319166001600160a01b0383169081179091556040519081527f7c737a8eddf62436489aa3600ed26e75e0a58b0f8c0d266bbcee64358c39fdac9060200160405180910390a150565b60006200038f836001600160a01b038416620003af565b90505b92915050565b60006200038f836001600160a01b038416620004b3565b60008181526001830160205260408120548015620004a8576000620003d660018362000637565b8554909150600090620003ec9060019062000637565b90508181146200045857600086600001828154811062000410576200041062000621565b906000526020600020015490508087600001848154811062000436576200043662000621565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806200046c576200046c62000659565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505062000392565b600091505062000392565b6000818152600183016020526040812054620004fc5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000392565b50600062000392565b80516001600160a01b03811681146200051d57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200054c57600080fd5b620005578362000505565b602084810151919350906001600160401b03808211156200057757600080fd5b818601915086601f8301126200058c57600080fd5b815181811115620005a157620005a162000522565b8060051b604051601f19603f83011681018181108582111715620005c957620005c962000522565b604052918252848201925083810185019189831115620005e857600080fd5b938501935b828510156200061157620006018562000505565b84529385019392850192620005ed565b8096505050505050509250929050565b634e487b7160e01b600052603260045260246000fd5b818103818111156200039257634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b612bf4806200067f6000396000f3fe608060405234801561001057600080fd5b50600436106100ea5760003560e01c80638da5cb5b1161008c578063e145291611610066578063e145291614610247578063e835232b14610265578063f2fde38b14610278578063fe843cd01461028b57600080fd5b80638da5cb5b146101e257806391a2749a14610221578063e0a0e5061461023457600080fd5b80631af18b7b116100c85780631af18b7b146101915780632451a627146101a4578063537e304e146101b957806379ba5097146101da57600080fd5b806308d450a1146100ef5780630a35bcc414610104578063181f5a771461017c575b600080fd5b6101026100fd366004612003565b61029e565b005b6101176101123660046120e3565b6102bd565b604051610173919081516fffffffffffffffffffffffffffffffff908116825260208084015163ffffffff1690830152604080840151151590830152606080840151821690830152608092830151169181019190915260a00190565b60405180910390f35b610184610382565b604051610173919061217a565b61010261019f3660046122b4565b61039e565b6101ac6105ca565b60405161017391906123d1565b6101cc6101c73660046123e4565b6105db565b6040516101739291906123ff565b610102610748565b60005473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610173565b61010261022f3660046124f5565b61084a565b610102610242366004612586565b61085b565b60055473ffffffffffffffffffffffffffffffffffffffff166101fc565b6101026102733660046125db565b6108d0565b6101026102863660046125db565b6108e1565b610102610299366004612616565b6108f2565b6102a6610c31565b6102ba816020015182608001516000610c76565b50565b6040805160a0810182526000808252602082018190529181018290526060810182905260808101919091526103796102f58484610d4d565b6040805160a08101825282546fffffffffffffffffffffffffffffffff808216835270010000000000000000000000000000000080830463ffffffff1660208501527401000000000000000000000000000000000000000090920460ff16151593830193909352600190930154808316606083015292909204166080820152610d7d565b90505b92915050565b604051806060016040528060238152602001612bc56023913981565b6103a6610e2f565b60005b82518110156104845760008382815181106103c6576103c661274a565b602002602001015160200151905060008483815181106103e8576103e861274a565b6020908102919091018101515167ffffffffffffffff811660009081526004909252604090912090915061041c9083610eb0565b1561047a576040805167ffffffffffffffff8316815273ffffffffffffffffffffffffffffffffffffffff841660208201527f530cabd30786b7235e124a6c0db77e0b685ef22813b1fe87554247f404eb8ed6910160405180910390a15b50506001016103a9565b5060005b81518110156105c55760008282815181106104a5576104a561274a565b602002602001015160000151905060008383815181106104c7576104c761274a565b6020026020010151602001519050600082602001519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16148061051857508151155b1561054f576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b825167ffffffffffffffff81166000908152600460205260409020610575908385610ed2565b156105b6577fad72a792d2a307f400c278be7deaeec6964276783304580cdc4e905436b8d5c58184846040516105ad93929190612779565b60405180910390a15b50505050806001019050610488565b505050565b60606105d66002610eff565b905090565b67ffffffffffffffff81166000908152600460205260408120606091829161060290610f0c565b90508067ffffffffffffffff81111561061d5761061d611d74565b604051908082528060200260200182016040528015610646578160200160208202803683370190505b5092508067ffffffffffffffff81111561066257610662611d74565b60405190808252806020026020018201604052801561069557816020015b60608152602001906001900390816106805790505b50915060005b818110156107415767ffffffffffffffff8516600090815260046020526040812081906106c89084610f17565b91509150818684815181106106df576106df61274a565b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508085848151811061072c5761072c61274a565b6020908102919091010152505060010161069b565b5050915091565b60015473ffffffffffffffffffffffffffffffffffffffff1633146107ce576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610852610e2f565b6102ba81610f36565b610863610c31565b6108cc8261087460408401846127c2565b808060200260200160405190810160405280939291908181526020016000905b828210156108c0576108b16040830286013681900381019061282a565b81526020019060010190610894565b50505050506001610c76565b5050565b6108d8610e2f565b6102ba816110c2565b6108e9610e2f565b6102ba81611188565b6108fa610e2f565b60005b81518110156108cc57600082828151811061091a5761091a61274a565b6020908102919091010151604081015181519192509067ffffffffffffffff8116600003610974576040517fc656089500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602083015160006109858383610d4d565b8054909150700100000000000000000000000000000000900463ffffffff16600003610bd3576040805160a081018252602080870180516fffffffffffffffffffffffffffffffff908116845263ffffffff421692840192909252875115158385015251811660608301529186015190911660808201528215610aec5767ffffffffffffffff8416600090815260066020908152604091829020835160028201805493860151948601516fffffffffffffffffffffffffffffffff9283167fffffffffffffffffffffffff00000000000000000000000000000000000000009095169490941770010000000000000000000000000000000063ffffffff9096168602177fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000941515949094029390931790925560608401516080850151908316921690920217600390910155610bcd565b67ffffffffffffffff84166000908152600660209081526040918290208351815492850151938501516fffffffffffffffffffffffffffffffff9182167fffffffffffffffffffffffff00000000000000000000000000000000000000009094169390931770010000000000000000000000000000000063ffffffff9095168502177fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000093151593909302929092178155606084015160808501519083169216909202176001909101555b50610bdd565b610bdd818561127d565b8267ffffffffffffffff167ff14a5415ce6988a9e870a85fff0b9d7b7dd79bbc228cb63cad610daf6f7b6b978386604051610c19929190612846565b60405180910390a250505050508060010190506108fd565b610c3c60023361142c565b610c74576040517fd86ad9cf0000000000000000000000000000000000000000000000000000000081523360048201526024016107c5565b565b6000610c828483610d4d565b805490915074010000000000000000000000000000000000000000900460ff1615610d47576000805b8451811015610d3257610cf6858281518110610cc957610cc961274a565b6020908102919091018101515167ffffffffffffffff89166000908152600490925260409091209061145b565b15610d2a57610d1d858281518110610d1057610d1061274a565b602002602001015161147d565b610d2790836128b9565b91505b600101610cab565b508015610d4557610d45828260006115b9565b505b50505050565b67ffffffffffffffff821660009081526006602052604081208215610d7657600201905061037c565b905061037c565b6040805160a081018252600080825260208201819052918101829052606081018290526080810191909152610e0b82606001516fffffffffffffffffffffffffffffffff1683600001516fffffffffffffffffffffffffffffffff16846020015163ffffffff1642610def91906128cc565b85608001516fffffffffffffffffffffffffffffffff1661193c565b6fffffffffffffffffffffffffffffffff1682525063ffffffff4216602082015290565b60005473ffffffffffffffffffffffffffffffffffffffff163314610c74576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016107c5565b60006103798373ffffffffffffffffffffffffffffffffffffffff8416611964565b6000610ef58473ffffffffffffffffffffffffffffffffffffffff851684611988565b90505b9392505050565b60606000610ef8836119ad565b600061037c82611a09565b600060608180610f278686611a14565b909450925050505b9250929050565b602081015160005b8151811015610fd1576000828281518110610f5b57610f5b61274a565b60200260200101519050610f79816002611ad190919063ffffffff16565b15610fc85760405173ffffffffffffffffffffffffffffffffffffffff821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b50600101610f3e565b50815160005b8151811015610d47576000828281518110610ff457610ff461274a565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611064576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61106f600282611af3565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a150600101610fd7565b73ffffffffffffffffffffffffffffffffffffffff811661110f576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600580547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527f7c737a8eddf62436489aa3600ed26e75e0a58b0f8c0d266bbcee64358c39fdac9060200160405180910390a150565b3373ffffffffffffffffffffffffffffffffffffffff821603611207576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016107c5565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b81546000906112a690700100000000000000000000000000000000900463ffffffff16426128cc565b9050801561134857600183015483546112ee916fffffffffffffffffffffffffffffffff8082169281169185917001000000000000000000000000000000009091041661193c565b83546fffffffffffffffffffffffffffffffff919091167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116177001000000000000000000000000000000004263ffffffff16021783555b6020820151835461136e916fffffffffffffffffffffffffffffffff9081169116611b15565b83548351151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffff000000000000000000000000000000009091166fffffffffffffffffffffffffffffffff92831617178455602083015160408085015183167001000000000000000000000000000000000291909216176001850155517f9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c199061141f9084906128df565b60405180910390a1505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515610379565b60006103798373ffffffffffffffffffffffffffffffffffffffff8416611b2b565b60055481516040517fd02641a000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff91821660048201526000928392169063d02641a0906024016040805180830381865afa1580156114f1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611515919061291b565b5190507bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811660000361158b5782516040517f9a655f7b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911660048201526024016107c5565b6020830151610ef8907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff831690611b37565b825474010000000000000000000000000000000000000000900460ff1615806115e0575081155b156115ea57505050565b825460018401546fffffffffffffffffffffffffffffffff8083169291169060009061163090700100000000000000000000000000000000900463ffffffff16426128cc565b905080156116f05781831115611672576040517f9725942a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018601546116ac9083908590849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff1661193c565b86547fffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000004263ffffffff160217875592505b848210156117a75773ffffffffffffffffffffffffffffffffffffffff841661174f576040517ff94ebcd100000000000000000000000000000000000000000000000000000000815260048101839052602481018690526044016107c5565b6040517f1a76572a000000000000000000000000000000000000000000000000000000008152600481018390526024810186905273ffffffffffffffffffffffffffffffffffffffff851660448201526064016107c5565b848310156118ba5760018681015470010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff169060009082906117eb90826128cc565b6117f5878a6128cc565b6117ff91906128b9565b6118099190612986565b905073ffffffffffffffffffffffffffffffffffffffff8616611862576040517f15279c0800000000000000000000000000000000000000000000000000000000815260048101829052602481018690526044016107c5565b6040517fd0c8d23a000000000000000000000000000000000000000000000000000000008152600481018290526024810186905273ffffffffffffffffffffffffffffffffffffffff871660448201526064016107c5565b6118c485846128cc565b86547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166fffffffffffffffffffffffffffffffff82161787556040518681529093507f1871cdf8010e63f2eb8384381a68dfa7416dc571a5517e66e88b2d2d0c0a690a9060200160405180910390a1505050505050565b600061195b8561194c84866129c1565b61195690876128b9565b611b15565b95945050505050565b6000818152600283016020526040812061197e9082611d26565b6103798383611b74565b600082815260028401602052604081206119a28382612a7b565b50610ef58484611b80565b6060816000018054806020026020016040519081016040528092919081815260200182805480156119fd57602002820191906000526020600020905b8154815260200190600101908083116119e9575b50505050509050919050565b600061037c82611b8c565b6000606081611a238585611b96565b60008181526002870160205260409020805491925082918190611a45906129d8565b80601f0160208091040260200160405190810160405280929190818152602001828054611a71906129d8565b8015611abe5780601f10611a9357610100808354040283529160200191611abe565b820191906000526020600020905b815481529060010190602001808311611aa157829003601f168201915b5050505050905092509250509250929050565b60006103798373ffffffffffffffffffffffffffffffffffffffff8416611ba2565b60006103798373ffffffffffffffffffffffffffffffffffffffff8416611c95565b6000818310611b245781610379565b5090919050565b60006103798383611ce4565b6000670de0b6b3a7640000611b6a837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff86166129c1565b6103799190612986565b60006103798383611ba2565b60006103798383611c95565b600061037c825490565b60006103798383611cfc565b60008181526001830160205260408120548015611c8b576000611bc66001836128cc565b8554909150600090611bda906001906128cc565b9050818114611c3f576000866000018281548110611bfa57611bfa61274a565b9060005260206000200154905080876000018481548110611c1d57611c1d61274a565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080611c5057611c50612b95565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061037c565b600091505061037c565b6000818152600183016020526040812054611cdc5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561037c565b50600061037c565b60008181526001830160205260408120541515610379565b6000826000018281548110611d1357611d1361274a565b9060005260206000200154905092915050565b508054611d32906129d8565b6000825580601f10611d42575050565b601f0160209004906000526020600020908101906102ba91905b80821115611d705760008155600101611d5c565b5090565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715611dc657611dc6611d74565b60405290565b60405160a0810167ffffffffffffffff81118282101715611dc657611dc6611d74565b6040516060810167ffffffffffffffff81118282101715611dc657611dc6611d74565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611e5957611e59611d74565b604052919050565b803567ffffffffffffffff81168114611e7957600080fd5b919050565b600082601f830112611e8f57600080fd5b813567ffffffffffffffff811115611ea957611ea9611d74565b611eda60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611e12565b818152846020838601011115611eef57600080fd5b816020850160208301376000918101602001919091529392505050565b600067ffffffffffffffff821115611f2657611f26611d74565b5060051b60200190565b803573ffffffffffffffffffffffffffffffffffffffff81168114611e7957600080fd5b600060408284031215611f6657600080fd5b611f6e611da3565b9050611f7982611f30565b81526020820135602082015292915050565b600082601f830112611f9c57600080fd5b81356020611fb1611fac83611f0c565b611e12565b8083825260208201915060208460061b870101935086841115611fd357600080fd5b602086015b84811015611ff857611fea8882611f54565b835291830191604001611fd8565b509695505050505050565b60006020828403121561201557600080fd5b813567ffffffffffffffff8082111561202d57600080fd5b9083019060a0828603121561204157600080fd5b612049611dcc565b8235815261205960208401611e61565b602082015260408301358281111561207057600080fd5b61207c87828601611e7e565b60408301525060608301358281111561209457600080fd5b6120a087828601611e7e565b6060830152506080830135828111156120b857600080fd5b6120c487828601611f8b565b60808301525095945050505050565b80358015158114611e7957600080fd5b600080604083850312156120f657600080fd5b6120ff83611e61565b915061210d602084016120d3565b90509250929050565b6000815180845260005b8181101561213c57602081850181015186830182015201612120565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b6020815260006103796020830184612116565b60006040828403121561219f57600080fd5b6121a7611da3565b90506121b282611e61565b81526121c060208301611f30565b602082015292915050565b600082601f8301126121dc57600080fd5b813560206121ec611fac83611f0c565b82815260059290921b8401810191818101908684111561220b57600080fd5b8286015b84811015611ff857803567ffffffffffffffff808211156122305760008081fd5b81890191506060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848d030112156122695760008081fd5b612271611da3565b61227d8c89860161218d565b81529083013590828211156122925760008081fd5b6122a08c8984870101611e7e565b81890152865250505091830191830161220f565b60008060408084860312156122c857600080fd5b833567ffffffffffffffff808211156122e057600080fd5b818601915086601f8301126122f457600080fd5b81356020612304611fac83611f0c565b8083825260208201915060208460061b87010193508a84111561232657600080fd5b6020860195505b8386101561234e5761233f8b8761218d565b8252948601949082019061232d565b9750505050602086013592508083111561236757600080fd5b5050612375858286016121cb565b9150509250929050565b60008151808452602080850194506020840160005b838110156123c657815173ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101612394565b509495945050505050565b602081526000610379602083018461237f565b6000602082840312156123f657600080fd5b61037982611e61565b604081526000612412604083018561237f565b6020838203818501528185518084528284019150828160051b85010183880160005b83811015612480577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe087840301855261246e838351612116565b94860194925090850190600101612434565b50909998505050505050505050565b600082601f8301126124a057600080fd5b813560206124b0611fac83611f0c565b8083825260208201915060208460051b8701019350868411156124d257600080fd5b602086015b84811015611ff8576124e881611f30565b83529183019183016124d7565b60006020828403121561250757600080fd5b813567ffffffffffffffff8082111561251f57600080fd5b908301906040828603121561253357600080fd5b61253b611da3565b82358281111561254a57600080fd5b6125568782860161248f565b82525060208301358281111561256b57600080fd5b6125778782860161248f565b60208301525095945050505050565b6000806040838503121561259957600080fd5b6125a283611e61565b9150602083013567ffffffffffffffff8111156125be57600080fd5b830160a081860312156125d057600080fd5b809150509250929050565b6000602082840312156125ed57600080fd5b61037982611f30565b80356fffffffffffffffffffffffffffffffff81168114611e7957600080fd5b6000602080838503121561262957600080fd5b823567ffffffffffffffff81111561264057600080fd5b8301601f8101851361265157600080fd5b803561265f611fac82611f0c565b81815260a0918202830184019184820191908884111561267e57600080fd5b938501935b8385101561273e578489038181121561269c5760008081fd5b6126a4611def565b6126ad87611e61565b81526126ba8888016120d3565b8882015260406060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0850112156126f25760008081fd5b6126fa611def565b9350612707828a016120d3565b8452612714818a016125f6565b8a85015250612725608089016125f6565b8382015281019190915283529384019391850191612683565b50979650505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b67ffffffffffffffff8416815260606020820152600061279c6060830185612116565b905073ffffffffffffffffffffffffffffffffffffffff83166040830152949350505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126127f757600080fd5b83018035915067ffffffffffffffff82111561281257600080fd5b6020019150600681901b3603821315610f2f57600080fd5b60006040828403121561283c57600080fd5b6103798383611f54565b821515815260808101610ef860208301848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082018082111561037c5761037c61288a565b8181038181111561037c5761037c61288a565b6060810161037c82848051151582526020808201516fffffffffffffffffffffffffffffffff9081169184019190915260409182015116910152565b60006040828403121561292d57600080fd5b612935611da3565b82517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116811461296157600080fd5b8152602083015163ffffffff8116811461297a57600080fd5b60208201529392505050565b6000826129bc577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b808202811582820484141761037c5761037c61288a565b600181811c908216806129ec57607f821691505b602082108103612a25577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b601f8211156105c5576000816000526020600020601f850160051c81016020861015612a545750805b601f850160051c820191505b81811015612a7357828155600101612a60565b505050505050565b815167ffffffffffffffff811115612a9557612a95611d74565b612aa981612aa384546129d8565b84612a2b565b602080601f831160018114612afc5760008415612ac65750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555612a73565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015612b4957888601518255948401946001909101908401612b2a565b5085821015612b8557878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfe4d756c7469416767726567617465526174654c696d6974657220312e362e302d646576a164736f6c6343000818000a", } var MultiAggregateRateLimiterABI = MultiAggregateRateLimiterMetaData.ABI var MultiAggregateRateLimiterBin = MultiAggregateRateLimiterMetaData.Bin -func DeployMultiAggregateRateLimiter(auth *bind.TransactOpts, backend bind.ContractBackend, priceRegistry common.Address, authorizedCallers []common.Address) (common.Address, *types.Transaction, *MultiAggregateRateLimiter, error) { +func DeployMultiAggregateRateLimiter(auth *bind.TransactOpts, backend bind.ContractBackend, feeQuoter common.Address, authorizedCallers []common.Address) (common.Address, *types.Transaction, *MultiAggregateRateLimiter, error) { parsed, err := MultiAggregateRateLimiterMetaData.GetAbi() if err != nil { return common.Address{}, nil, nil, err @@ -104,7 +104,7 @@ func DeployMultiAggregateRateLimiter(auth *bind.TransactOpts, backend bind.Contr return common.Address{}, nil, nil, errors.New("GetABI returned nil") } - address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(MultiAggregateRateLimiterBin), backend, priceRegistry, authorizedCallers) + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(MultiAggregateRateLimiterBin), backend, feeQuoter, authorizedCallers) if err != nil { return common.Address{}, nil, nil, err } @@ -301,9 +301,9 @@ func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterCallerSession) GetAll return _MultiAggregateRateLimiter.Contract.GetAllRateLimitTokens(&_MultiAggregateRateLimiter.CallOpts, remoteChainSelector) } -func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterCaller) GetPriceRegistry(opts *bind.CallOpts) (common.Address, error) { +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterCaller) GetFeeQuoter(opts *bind.CallOpts) (common.Address, error) { var out []interface{} - err := _MultiAggregateRateLimiter.contract.Call(opts, &out, "getPriceRegistry") + err := _MultiAggregateRateLimiter.contract.Call(opts, &out, "getFeeQuoter") if err != nil { return *new(common.Address), err @@ -315,12 +315,12 @@ func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterCaller) GetPriceRegis } -func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterSession) GetPriceRegistry() (common.Address, error) { - return _MultiAggregateRateLimiter.Contract.GetPriceRegistry(&_MultiAggregateRateLimiter.CallOpts) +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterSession) GetFeeQuoter() (common.Address, error) { + return _MultiAggregateRateLimiter.Contract.GetFeeQuoter(&_MultiAggregateRateLimiter.CallOpts) } -func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterCallerSession) GetPriceRegistry() (common.Address, error) { - return _MultiAggregateRateLimiter.Contract.GetPriceRegistry(&_MultiAggregateRateLimiter.CallOpts) +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterCallerSession) GetFeeQuoter() (common.Address, error) { + return _MultiAggregateRateLimiter.Contract.GetFeeQuoter(&_MultiAggregateRateLimiter.CallOpts) } func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterCaller) Owner(opts *bind.CallOpts) (common.Address, error) { @@ -427,16 +427,16 @@ func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterTransactorSession) On return _MultiAggregateRateLimiter.Contract.OnOutboundMessage(&_MultiAggregateRateLimiter.TransactOpts, destChainSelector, message) } -func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterTransactor) SetPriceRegistry(opts *bind.TransactOpts, newPriceRegistry common.Address) (*types.Transaction, error) { - return _MultiAggregateRateLimiter.contract.Transact(opts, "setPriceRegistry", newPriceRegistry) +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterTransactor) SetFeeQuoter(opts *bind.TransactOpts, newFeeQuoter common.Address) (*types.Transaction, error) { + return _MultiAggregateRateLimiter.contract.Transact(opts, "setFeeQuoter", newFeeQuoter) } -func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterSession) SetPriceRegistry(newPriceRegistry common.Address) (*types.Transaction, error) { - return _MultiAggregateRateLimiter.Contract.SetPriceRegistry(&_MultiAggregateRateLimiter.TransactOpts, newPriceRegistry) +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterSession) SetFeeQuoter(newFeeQuoter common.Address) (*types.Transaction, error) { + return _MultiAggregateRateLimiter.Contract.SetFeeQuoter(&_MultiAggregateRateLimiter.TransactOpts, newFeeQuoter) } -func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterTransactorSession) SetPriceRegistry(newPriceRegistry common.Address) (*types.Transaction, error) { - return _MultiAggregateRateLimiter.Contract.SetPriceRegistry(&_MultiAggregateRateLimiter.TransactOpts, newPriceRegistry) +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterTransactorSession) SetFeeQuoter(newFeeQuoter common.Address) (*types.Transaction, error) { + return _MultiAggregateRateLimiter.Contract.SetFeeQuoter(&_MultiAggregateRateLimiter.TransactOpts, newFeeQuoter) } func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { @@ -814,8 +814,8 @@ func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) ParseConfig return event, nil } -type MultiAggregateRateLimiterOwnershipTransferRequestedIterator struct { - Event *MultiAggregateRateLimiterOwnershipTransferRequested +type MultiAggregateRateLimiterFeeQuoterSetIterator struct { + Event *MultiAggregateRateLimiterFeeQuoterSet contract *bind.BoundContract event string @@ -826,7 +826,7 @@ type MultiAggregateRateLimiterOwnershipTransferRequestedIterator struct { fail error } -func (it *MultiAggregateRateLimiterOwnershipTransferRequestedIterator) Next() bool { +func (it *MultiAggregateRateLimiterFeeQuoterSetIterator) Next() bool { if it.fail != nil { return false @@ -835,7 +835,7 @@ func (it *MultiAggregateRateLimiterOwnershipTransferRequestedIterator) Next() bo if it.done { select { case log := <-it.logs: - it.Event = new(MultiAggregateRateLimiterOwnershipTransferRequested) + it.Event = new(MultiAggregateRateLimiterFeeQuoterSet) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -850,7 +850,7 @@ func (it *MultiAggregateRateLimiterOwnershipTransferRequestedIterator) Next() bo select { case log := <-it.logs: - it.Event = new(MultiAggregateRateLimiterOwnershipTransferRequested) + it.Event = new(MultiAggregateRateLimiterFeeQuoterSet) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -865,51 +865,32 @@ func (it *MultiAggregateRateLimiterOwnershipTransferRequestedIterator) Next() bo } } -func (it *MultiAggregateRateLimiterOwnershipTransferRequestedIterator) Error() error { +func (it *MultiAggregateRateLimiterFeeQuoterSetIterator) Error() error { return it.fail } -func (it *MultiAggregateRateLimiterOwnershipTransferRequestedIterator) Close() error { +func (it *MultiAggregateRateLimiterFeeQuoterSetIterator) Close() error { it.sub.Unsubscribe() return nil } -type MultiAggregateRateLimiterOwnershipTransferRequested struct { - From common.Address - To common.Address - Raw types.Log +type MultiAggregateRateLimiterFeeQuoterSet struct { + NewFeeQuoter common.Address + Raw types.Log } -func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*MultiAggregateRateLimiterOwnershipTransferRequestedIterator, error) { +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) FilterFeeQuoterSet(opts *bind.FilterOpts) (*MultiAggregateRateLimiterFeeQuoterSetIterator, error) { - var fromRule []interface{} - for _, fromItem := range from { - fromRule = append(fromRule, fromItem) - } - var toRule []interface{} - for _, toItem := range to { - toRule = append(toRule, toItem) - } - - logs, sub, err := _MultiAggregateRateLimiter.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + logs, sub, err := _MultiAggregateRateLimiter.contract.FilterLogs(opts, "FeeQuoterSet") if err != nil { return nil, err } - return &MultiAggregateRateLimiterOwnershipTransferRequestedIterator{contract: _MultiAggregateRateLimiter.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil + return &MultiAggregateRateLimiterFeeQuoterSetIterator{contract: _MultiAggregateRateLimiter.contract, event: "FeeQuoterSet", logs: logs, sub: sub}, nil } -func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *MultiAggregateRateLimiterOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) { - - var fromRule []interface{} - for _, fromItem := range from { - fromRule = append(fromRule, fromItem) - } - var toRule []interface{} - for _, toItem := range to { - toRule = append(toRule, toItem) - } +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) WatchFeeQuoterSet(opts *bind.WatchOpts, sink chan<- *MultiAggregateRateLimiterFeeQuoterSet) (event.Subscription, error) { - logs, sub, err := _MultiAggregateRateLimiter.contract.WatchLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + logs, sub, err := _MultiAggregateRateLimiter.contract.WatchLogs(opts, "FeeQuoterSet") if err != nil { return nil, err } @@ -919,8 +900,8 @@ func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) WatchOwners select { case log := <-logs: - event := new(MultiAggregateRateLimiterOwnershipTransferRequested) - if err := _MultiAggregateRateLimiter.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + event := new(MultiAggregateRateLimiterFeeQuoterSet) + if err := _MultiAggregateRateLimiter.contract.UnpackLog(event, "FeeQuoterSet", log); err != nil { return err } event.Raw = log @@ -941,17 +922,17 @@ func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) WatchOwners }), nil } -func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) ParseOwnershipTransferRequested(log types.Log) (*MultiAggregateRateLimiterOwnershipTransferRequested, error) { - event := new(MultiAggregateRateLimiterOwnershipTransferRequested) - if err := _MultiAggregateRateLimiter.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) ParseFeeQuoterSet(log types.Log) (*MultiAggregateRateLimiterFeeQuoterSet, error) { + event := new(MultiAggregateRateLimiterFeeQuoterSet) + if err := _MultiAggregateRateLimiter.contract.UnpackLog(event, "FeeQuoterSet", log); err != nil { return nil, err } event.Raw = log return event, nil } -type MultiAggregateRateLimiterOwnershipTransferredIterator struct { - Event *MultiAggregateRateLimiterOwnershipTransferred +type MultiAggregateRateLimiterOwnershipTransferRequestedIterator struct { + Event *MultiAggregateRateLimiterOwnershipTransferRequested contract *bind.BoundContract event string @@ -962,7 +943,7 @@ type MultiAggregateRateLimiterOwnershipTransferredIterator struct { fail error } -func (it *MultiAggregateRateLimiterOwnershipTransferredIterator) Next() bool { +func (it *MultiAggregateRateLimiterOwnershipTransferRequestedIterator) Next() bool { if it.fail != nil { return false @@ -971,7 +952,7 @@ func (it *MultiAggregateRateLimiterOwnershipTransferredIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(MultiAggregateRateLimiterOwnershipTransferred) + it.Event = new(MultiAggregateRateLimiterOwnershipTransferRequested) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -986,7 +967,7 @@ func (it *MultiAggregateRateLimiterOwnershipTransferredIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(MultiAggregateRateLimiterOwnershipTransferred) + it.Event = new(MultiAggregateRateLimiterOwnershipTransferRequested) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1001,22 +982,22 @@ func (it *MultiAggregateRateLimiterOwnershipTransferredIterator) Next() bool { } } -func (it *MultiAggregateRateLimiterOwnershipTransferredIterator) Error() error { +func (it *MultiAggregateRateLimiterOwnershipTransferRequestedIterator) Error() error { return it.fail } -func (it *MultiAggregateRateLimiterOwnershipTransferredIterator) Close() error { +func (it *MultiAggregateRateLimiterOwnershipTransferRequestedIterator) Close() error { it.sub.Unsubscribe() return nil } -type MultiAggregateRateLimiterOwnershipTransferred struct { +type MultiAggregateRateLimiterOwnershipTransferRequested struct { From common.Address To common.Address Raw types.Log } -func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*MultiAggregateRateLimiterOwnershipTransferredIterator, error) { +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*MultiAggregateRateLimiterOwnershipTransferRequestedIterator, error) { var fromRule []interface{} for _, fromItem := range from { @@ -1027,14 +1008,14 @@ func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) FilterOwner toRule = append(toRule, toItem) } - logs, sub, err := _MultiAggregateRateLimiter.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) + logs, sub, err := _MultiAggregateRateLimiter.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) if err != nil { return nil, err } - return &MultiAggregateRateLimiterOwnershipTransferredIterator{contract: _MultiAggregateRateLimiter.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil + return &MultiAggregateRateLimiterOwnershipTransferRequestedIterator{contract: _MultiAggregateRateLimiter.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil } -func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *MultiAggregateRateLimiterOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) { +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *MultiAggregateRateLimiterOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) { var fromRule []interface{} for _, fromItem := range from { @@ -1045,7 +1026,7 @@ func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) WatchOwners toRule = append(toRule, toItem) } - logs, sub, err := _MultiAggregateRateLimiter.contract.WatchLogs(opts, "OwnershipTransferred", fromRule, toRule) + logs, sub, err := _MultiAggregateRateLimiter.contract.WatchLogs(opts, "OwnershipTransferRequested", fromRule, toRule) if err != nil { return nil, err } @@ -1055,8 +1036,8 @@ func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) WatchOwners select { case log := <-logs: - event := new(MultiAggregateRateLimiterOwnershipTransferred) - if err := _MultiAggregateRateLimiter.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + event := new(MultiAggregateRateLimiterOwnershipTransferRequested) + if err := _MultiAggregateRateLimiter.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { return err } event.Raw = log @@ -1077,17 +1058,17 @@ func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) WatchOwners }), nil } -func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) ParseOwnershipTransferred(log types.Log) (*MultiAggregateRateLimiterOwnershipTransferred, error) { - event := new(MultiAggregateRateLimiterOwnershipTransferred) - if err := _MultiAggregateRateLimiter.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) ParseOwnershipTransferRequested(log types.Log) (*MultiAggregateRateLimiterOwnershipTransferRequested, error) { + event := new(MultiAggregateRateLimiterOwnershipTransferRequested) + if err := _MultiAggregateRateLimiter.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { return nil, err } event.Raw = log return event, nil } -type MultiAggregateRateLimiterPriceRegistrySetIterator struct { - Event *MultiAggregateRateLimiterPriceRegistrySet +type MultiAggregateRateLimiterOwnershipTransferredIterator struct { + Event *MultiAggregateRateLimiterOwnershipTransferred contract *bind.BoundContract event string @@ -1098,7 +1079,7 @@ type MultiAggregateRateLimiterPriceRegistrySetIterator struct { fail error } -func (it *MultiAggregateRateLimiterPriceRegistrySetIterator) Next() bool { +func (it *MultiAggregateRateLimiterOwnershipTransferredIterator) Next() bool { if it.fail != nil { return false @@ -1107,7 +1088,7 @@ func (it *MultiAggregateRateLimiterPriceRegistrySetIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(MultiAggregateRateLimiterPriceRegistrySet) + it.Event = new(MultiAggregateRateLimiterOwnershipTransferred) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1122,7 +1103,7 @@ func (it *MultiAggregateRateLimiterPriceRegistrySetIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(MultiAggregateRateLimiterPriceRegistrySet) + it.Event = new(MultiAggregateRateLimiterOwnershipTransferred) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1137,32 +1118,51 @@ func (it *MultiAggregateRateLimiterPriceRegistrySetIterator) Next() bool { } } -func (it *MultiAggregateRateLimiterPriceRegistrySetIterator) Error() error { +func (it *MultiAggregateRateLimiterOwnershipTransferredIterator) Error() error { return it.fail } -func (it *MultiAggregateRateLimiterPriceRegistrySetIterator) Close() error { +func (it *MultiAggregateRateLimiterOwnershipTransferredIterator) Close() error { it.sub.Unsubscribe() return nil } -type MultiAggregateRateLimiterPriceRegistrySet struct { - NewPriceRegistry common.Address - Raw types.Log +type MultiAggregateRateLimiterOwnershipTransferred struct { + From common.Address + To common.Address + Raw types.Log } -func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) FilterPriceRegistrySet(opts *bind.FilterOpts) (*MultiAggregateRateLimiterPriceRegistrySetIterator, error) { +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*MultiAggregateRateLimiterOwnershipTransferredIterator, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } - logs, sub, err := _MultiAggregateRateLimiter.contract.FilterLogs(opts, "PriceRegistrySet") + logs, sub, err := _MultiAggregateRateLimiter.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) if err != nil { return nil, err } - return &MultiAggregateRateLimiterPriceRegistrySetIterator{contract: _MultiAggregateRateLimiter.contract, event: "PriceRegistrySet", logs: logs, sub: sub}, nil + return &MultiAggregateRateLimiterOwnershipTransferredIterator{contract: _MultiAggregateRateLimiter.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil } -func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) WatchPriceRegistrySet(opts *bind.WatchOpts, sink chan<- *MultiAggregateRateLimiterPriceRegistrySet) (event.Subscription, error) { +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *MultiAggregateRateLimiterOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } - logs, sub, err := _MultiAggregateRateLimiter.contract.WatchLogs(opts, "PriceRegistrySet") + logs, sub, err := _MultiAggregateRateLimiter.contract.WatchLogs(opts, "OwnershipTransferred", fromRule, toRule) if err != nil { return nil, err } @@ -1172,8 +1172,8 @@ func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) WatchPriceR select { case log := <-logs: - event := new(MultiAggregateRateLimiterPriceRegistrySet) - if err := _MultiAggregateRateLimiter.contract.UnpackLog(event, "PriceRegistrySet", log); err != nil { + event := new(MultiAggregateRateLimiterOwnershipTransferred) + if err := _MultiAggregateRateLimiter.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { return err } event.Raw = log @@ -1194,9 +1194,9 @@ func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) WatchPriceR }), nil } -func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) ParsePriceRegistrySet(log types.Log) (*MultiAggregateRateLimiterPriceRegistrySet, error) { - event := new(MultiAggregateRateLimiterPriceRegistrySet) - if err := _MultiAggregateRateLimiter.contract.UnpackLog(event, "PriceRegistrySet", log); err != nil { +func (_MultiAggregateRateLimiter *MultiAggregateRateLimiterFilterer) ParseOwnershipTransferred(log types.Log) (*MultiAggregateRateLimiterOwnershipTransferred, error) { + event := new(MultiAggregateRateLimiterOwnershipTransferred) + if err := _MultiAggregateRateLimiter.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { return nil, err } event.Raw = log @@ -1699,12 +1699,12 @@ func (_MultiAggregateRateLimiter *MultiAggregateRateLimiter) ParseLog(log types. return _MultiAggregateRateLimiter.ParseAuthorizedCallerRemoved(log) case _MultiAggregateRateLimiter.abi.Events["ConfigChanged"].ID: return _MultiAggregateRateLimiter.ParseConfigChanged(log) + case _MultiAggregateRateLimiter.abi.Events["FeeQuoterSet"].ID: + return _MultiAggregateRateLimiter.ParseFeeQuoterSet(log) case _MultiAggregateRateLimiter.abi.Events["OwnershipTransferRequested"].ID: return _MultiAggregateRateLimiter.ParseOwnershipTransferRequested(log) case _MultiAggregateRateLimiter.abi.Events["OwnershipTransferred"].ID: return _MultiAggregateRateLimiter.ParseOwnershipTransferred(log) - case _MultiAggregateRateLimiter.abi.Events["PriceRegistrySet"].ID: - return _MultiAggregateRateLimiter.ParsePriceRegistrySet(log) case _MultiAggregateRateLimiter.abi.Events["RateLimiterConfigUpdated"].ID: return _MultiAggregateRateLimiter.ParseRateLimiterConfigUpdated(log) case _MultiAggregateRateLimiter.abi.Events["TokenAggregateRateLimitAdded"].ID: @@ -1731,6 +1731,10 @@ func (MultiAggregateRateLimiterConfigChanged) Topic() common.Hash { return common.HexToHash("0x9ea3374b67bf275e6bb9c8ae68f9cae023e1c528b4b27e092f0bb209d3531c19") } +func (MultiAggregateRateLimiterFeeQuoterSet) Topic() common.Hash { + return common.HexToHash("0x7c737a8eddf62436489aa3600ed26e75e0a58b0f8c0d266bbcee64358c39fdac") +} + func (MultiAggregateRateLimiterOwnershipTransferRequested) Topic() common.Hash { return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") } @@ -1739,10 +1743,6 @@ func (MultiAggregateRateLimiterOwnershipTransferred) Topic() common.Hash { return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") } -func (MultiAggregateRateLimiterPriceRegistrySet) Topic() common.Hash { - return common.HexToHash("0xdeaac1a8daeabcc5254b10b54edf3678fdfcd1cea89fe9d364b6285f6ace2df9") -} - func (MultiAggregateRateLimiterRateLimiterConfigUpdated) Topic() common.Hash { return common.HexToHash("0xf14a5415ce6988a9e870a85fff0b9d7b7dd79bbc228cb63cad610daf6f7b6b97") } @@ -1772,7 +1772,7 @@ type MultiAggregateRateLimiterInterface interface { error) - GetPriceRegistry(opts *bind.CallOpts) (common.Address, error) + GetFeeQuoter(opts *bind.CallOpts) (common.Address, error) Owner(opts *bind.CallOpts) (common.Address, error) @@ -1788,7 +1788,7 @@ type MultiAggregateRateLimiterInterface interface { OnOutboundMessage(opts *bind.TransactOpts, destChainSelector uint64, message ClientEVM2AnyMessage) (*types.Transaction, error) - SetPriceRegistry(opts *bind.TransactOpts, newPriceRegistry common.Address) (*types.Transaction, error) + SetFeeQuoter(opts *bind.TransactOpts, newFeeQuoter common.Address) (*types.Transaction, error) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) @@ -1812,6 +1812,12 @@ type MultiAggregateRateLimiterInterface interface { ParseConfigChanged(log types.Log) (*MultiAggregateRateLimiterConfigChanged, error) + FilterFeeQuoterSet(opts *bind.FilterOpts) (*MultiAggregateRateLimiterFeeQuoterSetIterator, error) + + WatchFeeQuoterSet(opts *bind.WatchOpts, sink chan<- *MultiAggregateRateLimiterFeeQuoterSet) (event.Subscription, error) + + ParseFeeQuoterSet(log types.Log) (*MultiAggregateRateLimiterFeeQuoterSet, error) + FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*MultiAggregateRateLimiterOwnershipTransferRequestedIterator, error) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *MultiAggregateRateLimiterOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) @@ -1824,12 +1830,6 @@ type MultiAggregateRateLimiterInterface interface { ParseOwnershipTransferred(log types.Log) (*MultiAggregateRateLimiterOwnershipTransferred, error) - FilterPriceRegistrySet(opts *bind.FilterOpts) (*MultiAggregateRateLimiterPriceRegistrySetIterator, error) - - WatchPriceRegistrySet(opts *bind.WatchOpts, sink chan<- *MultiAggregateRateLimiterPriceRegistrySet) (event.Subscription, error) - - ParsePriceRegistrySet(log types.Log) (*MultiAggregateRateLimiterPriceRegistrySet, error) - FilterRateLimiterConfigUpdated(opts *bind.FilterOpts, remoteChainSelector []uint64) (*MultiAggregateRateLimiterRateLimiterConfigUpdatedIterator, error) WatchRateLimiterConfigUpdated(opts *bind.WatchOpts, sink chan<- *MultiAggregateRateLimiterRateLimiterConfigUpdated, remoteChainSelector []uint64) (event.Subscription, error) diff --git a/core/gethwrappers/ccip/generated/offramp/offramp.go b/core/gethwrappers/ccip/generated/offramp/offramp.go index 0dd7280074..2ce6804b3c 100644 --- a/core/gethwrappers/ccip/generated/offramp/offramp.go +++ b/core/gethwrappers/ccip/generated/offramp/offramp.go @@ -119,7 +119,7 @@ type OffRampCommitReport struct { } type OffRampDynamicConfig struct { - PriceRegistry common.Address + FeeQuoter common.Address PermissionLessExecutionThresholdSeconds uint32 MaxTokenTransferGas uint32 MaxPoolReleaseOrMintGas uint32 @@ -164,7 +164,7 @@ type OffRampUnblessedRoot struct { } var OffRampMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CanOnlySelfCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"actual\",\"type\":\"bytes32\"}],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ExecutionError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"ForkedChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enumMultiOCR3Base.InvalidConfigErrorType\",\"name\":\"errorType\",\"type\":\"uint8\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"got\",\"type\":\"uint256\"}],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidEVMAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"internalType\":\"structOffRamp.Interval\",\"name\":\"interval\",\"type\":\"tuple\"}],\"name\":\"InvalidInterval\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"newLimit\",\"type\":\"uint256\"}],\"name\":\"InvalidManualExecutionGasLimit\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"messageDestChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidMessageDestChainSelector\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"newState\",\"type\":\"uint8\"}],\"name\":\"InvalidNewState\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRoot\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidStaticConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LeavesCannotBeEmpty\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ManualExecutionGasLimitMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"ManualExecutionNotYetEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"errorReason\",\"type\":\"bytes\"}],\"name\":\"MessageValidationError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonUniqueSignatures\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"notPool\",\"type\":\"address\"}],\"name\":\"NotACompatiblePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OracleCannotBeZeroAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ReceiverError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountReleased\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePre\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePost\",\"type\":\"uint256\"}],\"name\":\"ReleaseOrMintBalanceMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"name\":\"RootAlreadyCommitted\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"RootNotCommitted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignaturesOutOfRegistration\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"StaleCommitReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"StaticConfigCannotBeChanged\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"TokenDataMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"TokenHandlingError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnexpectedTokenData\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"WrongMessageLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WrongNumberOfSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroChainSelectorNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"AlreadyAttempted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"internalType\":\"structOffRamp.Interval\",\"name\":\"interval\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structOffRamp.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"report\",\"type\":\"tuple\"}],\"name\":\"CommitReportAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"DynamicConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"name\":\"ExecutionStateChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"RootRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"SkippedAlreadyExecutedMessage\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"sourceConfig\",\"type\":\"tuple\"}],\"name\":\"SourceChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainSelectorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"}],\"name\":\"StaticConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigUpdates\",\"type\":\"tuple[]\"}],\"name\":\"applySourceChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"destTokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structClient.Any2EVMMessage\",\"name\":\"\",\"type\":\"tuple\"}],\"name\":\"ccipReceive\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"rawVs\",\"type\":\"bytes32\"}],\"name\":\"commit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"execute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"bytes[]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[]\"}],\"name\":\"executeSingleMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"getExecutionState\",\"outputs\":[{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLatestPriceSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"getMerkleRoot\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"getSourceChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"isBlessed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"latestConfigDetails\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"n\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"}],\"internalType\":\"structMultiOCR3Base.ConfigInfo\",\"name\":\"configInfo\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfig\",\"name\":\"ocrConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage[]\",\"name\":\"messages\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[][]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[][]\"},{\"internalType\":\"bytes32[]\",\"name\":\"proofs\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"proofFlagBits\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.ExecutionReportSingleChain[]\",\"name\":\"reports\",\"type\":\"tuple[]\"},{\"internalType\":\"uint256[][]\",\"name\":\"gasLimitOverrides\",\"type\":\"uint256[][]\"}],\"name\":\"manuallyExecute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structOffRamp.UnblessedRoot[]\",\"name\":\"rootToReset\",\"type\":\"tuple[]\"}],\"name\":\"resetUnblessedRoots\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"setDynamicConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfigArgs[]\",\"name\":\"ocrConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"setOCR3Configs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CanOnlySelfCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"actual\",\"type\":\"bytes32\"}],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ExecutionError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"ForkedChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enumMultiOCR3Base.InvalidConfigErrorType\",\"name\":\"errorType\",\"type\":\"uint8\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"got\",\"type\":\"uint256\"}],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidEVMAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"internalType\":\"structOffRamp.Interval\",\"name\":\"interval\",\"type\":\"tuple\"}],\"name\":\"InvalidInterval\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"newLimit\",\"type\":\"uint256\"}],\"name\":\"InvalidManualExecutionGasLimit\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"messageDestChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidMessageDestChainSelector\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"newState\",\"type\":\"uint8\"}],\"name\":\"InvalidNewState\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRoot\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidStaticConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LeavesCannotBeEmpty\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ManualExecutionGasLimitMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"ManualExecutionNotYetEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"errorReason\",\"type\":\"bytes\"}],\"name\":\"MessageValidationError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonUniqueSignatures\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"notPool\",\"type\":\"address\"}],\"name\":\"NotACompatiblePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OracleCannotBeZeroAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ReceiverError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountReleased\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePre\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePost\",\"type\":\"uint256\"}],\"name\":\"ReleaseOrMintBalanceMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"name\":\"RootAlreadyCommitted\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"RootNotCommitted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignaturesOutOfRegistration\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"StaleCommitReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"StaticConfigCannotBeChanged\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"TokenDataMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"TokenHandlingError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnexpectedTokenData\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"WrongMessageLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WrongNumberOfSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroChainSelectorNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"AlreadyAttempted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"internalType\":\"structOffRamp.Interval\",\"name\":\"interval\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structOffRamp.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"report\",\"type\":\"tuple\"}],\"name\":\"CommitReportAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"DynamicConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"name\":\"ExecutionStateChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"RootRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"SkippedAlreadyExecutedMessage\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"sourceConfig\",\"type\":\"tuple\"}],\"name\":\"SourceChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainSelectorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"}],\"name\":\"StaticConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigUpdates\",\"type\":\"tuple[]\"}],\"name\":\"applySourceChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"destTokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structClient.Any2EVMMessage\",\"name\":\"\",\"type\":\"tuple\"}],\"name\":\"ccipReceive\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"rawVs\",\"type\":\"bytes32\"}],\"name\":\"commit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"execute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"bytes[]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[]\"}],\"name\":\"executeSingleMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"getExecutionState\",\"outputs\":[{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLatestPriceSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"getMerkleRoot\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"getSourceChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"isBlessed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"latestConfigDetails\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"n\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"}],\"internalType\":\"structMultiOCR3Base.ConfigInfo\",\"name\":\"configInfo\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfig\",\"name\":\"ocrConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage[]\",\"name\":\"messages\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[][]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[][]\"},{\"internalType\":\"bytes32[]\",\"name\":\"proofs\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"proofFlagBits\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.ExecutionReportSingleChain[]\",\"name\":\"reports\",\"type\":\"tuple[]\"},{\"internalType\":\"uint256[][]\",\"name\":\"gasLimitOverrides\",\"type\":\"uint256[][]\"}],\"name\":\"manuallyExecute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structOffRamp.UnblessedRoot[]\",\"name\":\"rootToReset\",\"type\":\"tuple[]\"}],\"name\":\"resetUnblessedRoots\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"setDynamicConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfigArgs[]\",\"name\":\"ocrConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"setOCR3Configs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", Bin: "0x6101206040523480156200001257600080fd5b5060405162006c1a38038062006c1a8339810160408190526200003591620008c7565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf81620001fa565b5050466080525060208301516001600160a01b03161580620000ec575060408301516001600160a01b0316155b8062000103575060608301516001600160a01b0316155b1562000122576040516342bcdf7f60e11b815260040160405180910390fd5b82516001600160401b03166000036200014e5760405163c656089560e01b815260040160405180910390fd5b82516001600160401b0390811660a052602080850180516001600160a01b0390811660c05260408088018051831660e0526060808a01805185166101005283518b519098168852945184169587019590955251821690850152905116908201527f683eb52ee924eb817377cfa8f41f238f4bb7a877da5267869dfffbad85f564d89060800160405180910390a1620001e682620002a5565b620001f181620003c1565b50505062000c67565b336001600160a01b03821603620002545760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b0316620002ce576040516342bcdf7f60e11b815260040160405180910390fd5b80516004805460208085018051604080880180516060808b0180516001600160a01b039b8c166001600160c01b0319909a168a17600160a01b63ffffffff98891602176001600160c01b0316600160c01b948816949094026001600160e01b031693909317600160e01b93871693909302929092179098556080808b018051600580546001600160a01b031916918d169190911790558451988952955185169688019690965290518316918601919091525116938301939093529151909216908201527fa55bd56595c45f517e5967a3067f3dca684445a3080e7c04a4e0d5a40cda627d9060a00160405180910390a150565b60005b815181101562000666576000828281518110620003e557620003e562000a1d565b60200260200101519050600081602001519050806001600160401b0316600003620004235760405163c656089560e01b815260040160405180910390fd5b81516001600160a01b03166200044c576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160401b0381166000908152600660205260408120600181018054919291620004789062000a33565b80601f0160208091040260200160405190810160405280929190818152602001828054620004a69062000a33565b8015620004f75780601f10620004cb57610100808354040283529160200191620004f7565b820191906000526020600020905b815481529060010190602001808311620004d957829003601f168201915b5050505050905060008460600151905081516000036200059e57805160000362000534576040516342bcdf7f60e11b815260040160405180910390fd5b6001830162000544828262000ac4565b508254600160a81b600160e81b031916600160a81b1783556040516001600160401b03851681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1620005d9565b8080519060200120828051906020012014620005d95760405163c39a620560e01b81526001600160401b038516600482015260240162000083565b604080860151845487516001600160a01b03166001600160a01b0319921515600160a01b02929092166001600160a81b031990911617178455516001600160401b038516907f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b906200064d90869062000b90565b60405180910390a25050505050806001019050620003c4565b5050565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b0381118282101715620006a557620006a56200066a565b60405290565b604051601f8201601f191681016001600160401b0381118282101715620006d657620006d66200066a565b604052919050565b80516001600160401b0381168114620006f657600080fd5b919050565b6001600160a01b03811681146200071157600080fd5b50565b805163ffffffff81168114620006f657600080fd5b6000601f83601f8401126200073d57600080fd5b825160206001600160401b03808311156200075c576200075c6200066a565b8260051b6200076d838201620006ab565b93845286810183019383810190898611156200078857600080fd5b84890192505b85831015620008ba57825184811115620007a85760008081fd5b89016080601f19828d038101821315620007c25760008081fd5b620007cc62000680565b88840151620007db81620006fb565b81526040620007ec858201620006de565b8a8301526060808601518015158114620008065760008081fd5b838301529385015193898511156200081e5760008081fd5b84860195508f603f8701126200083657600094508485fd5b8a8601519450898511156200084f576200084f6200066a565b620008608b858f88011601620006ab565b93508484528f82868801011115620008785760008081fd5b60005b8581101562000898578681018301518582018d01528b016200087b565b5060009484018b0194909452509182015283525091840191908401906200078e565b9998505050505050505050565b6000806000838503610140811215620008df57600080fd5b6080811215620008ee57600080fd5b620008f862000680565b6200090386620006de565b815260208601516200091581620006fb565b602082015260408601516200092a81620006fb565b604082015260608601516200093f81620006fb565b6060820152935060a0607f19820112156200095957600080fd5b5060405160a081016001600160401b0380821183831017156200098057620009806200066a565b81604052608087015191506200099682620006fb565b818352620009a760a0880162000714565b6020840152620009ba60c0880162000714565b6040840152620009cd60e0880162000714565b60608401526101008701519150620009e582620006fb565b608083018290526101208701519294508083111562000a0357600080fd5b505062000a138682870162000729565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b600181811c9082168062000a4857607f821691505b60208210810362000a6957634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111562000abf576000816000526020600020601f850160051c8101602086101562000a9a5750805b601f850160051c820191505b8181101562000abb5782815560010162000aa6565b5050505b505050565b81516001600160401b0381111562000ae05762000ae06200066a565b62000af88162000af1845462000a33565b8462000a6f565b602080601f83116001811462000b30576000841562000b175750858301515b600019600386901b1c1916600185901b17855562000abb565b600085815260208120601f198616915b8281101562000b615788860151825594840194600190910190840162000b40565b508582101562000b805787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b602080825282546001600160a01b0381168383015260a081901c60ff161515604084015260a81c6001600160401b0316606083015260808083015260018084018054600093929190849062000be58162000a33565b8060a089015260c0600183166000811462000c09576001811462000c265762000c58565b60ff19841660c08b015260c083151560051b8b0101945062000c58565b85600052602060002060005b8481101562000c4f5781548c820185015290880190890162000c32565b8b0160c0019550505b50929998505050505050505050565b60805160a05160c05160e05161010051615f4462000cd6600039600081816102660152612a010152600081816102370152612ef40152600081816102080152818161142b015261196d0152600081816101d801526125f00152600081816117f3015261183f0152615f446000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806385572ffb116100d8578063ccd37ba31161008c578063f2fde38b11610066578063f2fde38b14610583578063f716f99f14610596578063ff888fb1146105a957600080fd5b8063ccd37ba31461050b578063d2a15d3514610550578063e9d68a8e1461056357600080fd5b8063991a5018116100bd578063991a5018146104c5578063a80036b4146104d8578063c673e584146104eb57600080fd5b806385572ffb1461049c5780638da5cb5b146104aa57600080fd5b8063311cd5131161012f5780635e36480c116101145780635e36480c146103785780637437ff9f1461039857806379ba50971461049457600080fd5b8063311cd513146103495780633f4b04aa1461035c57600080fd5b806306285c691161016057806306285c69146101a4578063181f5a77146102ed5780632d04ab761461033657600080fd5b806304666f9c1461017c57806305d938b514610191575b600080fd5b61018f61018a3660046140af565b6105cc565b005b61018f61019f36600461473b565b6105e0565b61029660408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316815250905090565b6040516102e49190815167ffffffffffffffff1681526020808301516001600160a01b0390811691830191909152604080840151821690830152606092830151169181019190915260800190565b60405180910390f35b6103296040518060400160405280601181526020017f4f666652616d7020312e362e302d64657600000000000000000000000000000081525081565b6040516102e491906148b6565b61018f610344366004614961565b610785565b61018f610357366004614a14565b610b5c565b60095460405167ffffffffffffffff90911681526020016102e4565b61038b610386366004614a68565b610bc5565b6040516102e49190614ac5565b6104376040805160a081018252600080825260208201819052918101829052606081018290526080810191909152506040805160a0810182526004546001600160a01b03808216835263ffffffff600160a01b83048116602085015278010000000000000000000000000000000000000000000000008304811694840194909452600160e01b9091049092166060820152600554909116608082015290565b6040516102e49190600060a0820190506001600160a01b03808451168352602084015163ffffffff808216602086015280604087015116604086015280606087015116606086015250508060808501511660808401525092915050565b61018f610c1b565b61018f610177366004614ad3565b6000546040516001600160a01b0390911681526020016102e4565b61018f6104d3366004614b22565b610cd9565b61018f6104e6366004614b96565b610cea565b6104fe6104f9366004614c03565b61105d565b6040516102e49190614c63565b610542610519366004614cd8565b67ffffffffffffffff919091166000908152600860209081526040808320938352929052205490565b6040519081526020016102e4565b61018f61055e366004614d02565b6111bb565b610576610571366004614d77565b611275565b6040516102e49190614d92565b61018f610591366004614de0565b611382565b61018f6105a4366004614e65565b611393565b6105bc6105b7366004614fa3565b6113d5565b60405190151581526020016102e4565b6105d4611496565b6105dd816114f2565b50565b6105e86117f0565b815181518114610624576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8181101561077557600084828151811061064357610643614fbc565b6020026020010151905060008160200151519050600085848151811061066b5761066b614fbc565b60200260200101519050805182146106af576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b828110156107665760008282815181106106ce576106ce614fbc565b602002602001015190508060001461075d57846020015182815181106106f6576106f6614fbc565b60200260200101516080015181101561075d5784516040517fc8e9605100000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260248101839052604481018290526064015b60405180910390fd5b506001016106b2565b50505050806001019050610627565b506107808383611871565b505050565b600061079387890189615142565b805151519091501515806107ac57508051602001515115155b156108ac5760095460208a01359067ffffffffffffffff8083169116101561086b576009805467ffffffffffffffff191667ffffffffffffffff83161790556004805483516040517f3937306f0000000000000000000000000000000000000000000000000000000081526001600160a01b0390921692633937306f9261083492910161536a565b600060405180830381600087803b15801561084e57600080fd5b505af1158015610862573d6000803e3d6000fd5b505050506108aa565b8160200151516000036108aa576040517f2261116700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b60005b816020015151811015610aa5576000826020015182815181106108d4576108d4614fbc565b602002602001015190506000816000015190506108f081611921565b60006108fb82611a23565b602084015151815491925067ffffffffffffffff908116600160a81b9092041614158061093f575060208084015190810151905167ffffffffffffffff9182169116115b1561097f57825160208401516040517feefb0cac00000000000000000000000000000000000000000000000000000000815261075492919060040161537d565b6040830151806109bb576040517f504570e300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b835167ffffffffffffffff16600090815260086020908152604080832084845290915290205415610a2e5783516040517f32cf0cbf00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260248101829052604401610754565b6020808501510151610a419060016153c8565b82547fffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffff16600160a81b67ffffffffffffffff9283160217909255925116600090815260086020908152604080832094835293905291909120429055506001016108af565b507f3a3950e13dd607cc37980db0ef14266c40d2bba9c01b2e44bfe549808883095d81604051610ad591906153f0565b60405180910390a1610b5160008a8a8a8a8a8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808e0282810182019093528d82529093508d92508c9182918501908490808284376000920191909152508b9250611a8a915050565b505050505050505050565b610b9c610b6b8284018461548d565b6040805160008082526020820190925290610b96565b6060815260200190600190039081610b815790505b50611871565b604080516000808252602082019092529050610bbf600185858585866000611a8a565b50505050565b6000610bd3600160046154c2565b6002610be06080856154eb565b67ffffffffffffffff16610bf49190615512565b610bfe8585611e01565b901c166003811115610c1257610c12614a9b565b90505b92915050565b6001546001600160a01b03163314610c755760405162461bcd60e51b815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610754565b600080543373ffffffffffffffffffffffffffffffffffffffff19808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610ce1611496565b6105dd81611e48565b333014610d23576040517f371a732800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160008082526020820190925281610d60565b6040805180820190915260008082526020820152815260200190600190039081610d395790505b5060a08501515190915015610d9457610d918460a00151856020015186606001518760000151602001518787611fae565b90505b6040805160a0810182528551518152855160209081015167ffffffffffffffff1681830152808701518351600094840192610dd09291016148b6565b60408051601f19818403018152918152908252878101516020830152018390526005549091506001600160a01b03168015610edd576040517f08d450a10000000000000000000000000000000000000000000000000000000081526001600160a01b038216906308d450a190610e4a9085906004016155cb565b600060405180830381600087803b158015610e6457600080fd5b505af1925050508015610e75575060015b610edd573d808015610ea3576040519150601f19603f3d011682016040523d82523d6000602084013e610ea8565b606091505b50806040517f09c2532500000000000000000000000000000000000000000000000000000000815260040161075491906148b6565b604086015151158015610ef257506080860151155b80610f09575060608601516001600160a01b03163b155b80610f4957506060860151610f47906001600160a01b03167f85572ffb000000000000000000000000000000000000000000000000000000006120cd565b155b15610f5657505050505050565b855160209081015167ffffffffffffffff1660009081526006909152604080822054608089015160608a015192517f3cf9798300000000000000000000000000000000000000000000000000000000815284936001600160a01b0390931692633cf9798392610fce92899261138892916004016155de565b6000604051808303816000875af1158015610fed573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611015919081019061561a565b50915091508161105357806040517f0a8d6e8c00000000000000000000000000000000000000000000000000000000815260040161075491906148b6565b5050505050505050565b6110a06040805160e081019091526000606082018181526080830182905260a0830182905260c08301919091528190815260200160608152602001606081525090565b60ff808316600090815260026020818152604092839020835160e081018552815460608201908152600183015480881660808401526101008104881660a0840152620100009004909616151560c08201529485529182018054845181840281018401909552808552929385830193909283018282801561114957602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161112b575b50505050508152602001600382018054806020026020016040519081016040528092919081815260200182805480156111ab57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161118d575b5050505050815250509050919050565b6111c3611496565b60005b818110156107805760008383838181106111e2576111e2614fbc565b9050604002018036038101906111f891906156b0565b905061120781602001516113d5565b61126c57805167ffffffffffffffff1660009081526008602090815260408083208285018051855290835281842093909355915191519182527f202f1139a3e334b6056064c0e9b19fd07e44a88d8f6e5ded571b24cf8c371f12910160405180910390a15b506001016111c6565b604080516080808201835260008083526020808401829052838501829052606080850181905267ffffffffffffffff878116845260068352928690208651948501875280546001600160a01b0381168652600160a01b810460ff16151593860193909352600160a81b909204909216948301949094526001840180549394929391840191611302906156e9565b80601f016020809104026020016040519081016040528092919081815260200182805461132e906156e9565b80156111ab5780601f10611350576101008083540402835291602001916111ab565b820191906000526020600020905b81548152906001019060200180831161135e57505050919092525091949350505050565b61138a611496565b6105dd816120e9565b61139b611496565b60005b81518110156113d1576113c98282815181106113bc576113bc614fbc565b602002602001015161219f565b60010161139e565b5050565b6040805180820182523081526020810183815291517f4d61677100000000000000000000000000000000000000000000000000000000815290516001600160a01b039081166004830152915160248201526000917f00000000000000000000000000000000000000000000000000000000000000001690634d61677190604401602060405180830381865afa158015611472573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c159190615723565b6000546001600160a01b031633146114f05760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610754565b565b60005b81518110156113d157600082828151811061151257611512614fbc565b602002602001015190506000816020015190508067ffffffffffffffff16600003611569576040517fc656089500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81516001600160a01b0316611591576040516342bcdf7f60e11b815260040160405180910390fd5b67ffffffffffffffff811660009081526006602052604081206001810180549192916115bc906156e9565b80601f01602080910402602001604051908101604052809291908181526020018280546115e8906156e9565b80156116355780601f1061160a57610100808354040283529160200191611635565b820191906000526020600020905b81548152906001019060200180831161161857829003601f168201915b5050505050905060008460600151905081516000036116ed578051600003611670576040516342bcdf7f60e11b815260040160405180910390fd5b6001830161167e8282615788565b5082547fffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffff16600160a81b17835560405167ffffffffffffffff851681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1611740565b8080519060200120828051906020012014611740576040517fc39a620500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff85166004820152602401610754565b604080860151845487516001600160a01b031673ffffffffffffffffffffffffffffffffffffffff19921515600160a01b02929092167fffffffffffffffffffffff000000000000000000000000000000000000000000909116171784555167ffffffffffffffff8516907f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b906117d8908690615848565b60405180910390a250505050508060010190506114f5565b467f0000000000000000000000000000000000000000000000000000000000000000146114f0576040517f0f01ce850000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000006004820152466024820152604401610754565b81516000036118ab576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160408051600080825260208201909252911591905b845181101561191a576119128582815181106118e0576118e0614fbc565b60200260200101518461190c578583815181106118ff576118ff614fbc565b60200260200101516124e3565b836124e3565b6001016118c2565b5050505050565b6040517f2cbc26bb000000000000000000000000000000000000000000000000000000008152608082901b77ffffffffffffffff000000000000000000000000000000001660048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632cbc26bb90602401602060405180830381865afa1580156119bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119e09190615723565b156105dd576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610754565b67ffffffffffffffff811660009081526006602052604081208054600160a01b900460ff16610c15576040517fed053c5900000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610754565b60ff87811660009081526002602090815260408083208151608081018352815481526001909101548086169382019390935261010083048516918101919091526201000090910490921615156060830152873590611ae98760a4615916565b9050826060015115611b31578451611b02906020615512565b8651611b0f906020615512565b611b1a9060a0615916565b611b249190615916565b611b2e9082615916565b90505b368114611b73576040517f8e1192e100000000000000000000000000000000000000000000000000000000815260048101829052366024820152604401610754565b5081518114611bbb5781516040517f93df584c000000000000000000000000000000000000000000000000000000008152600481019190915260248101829052604401610754565b611bc36117f0565b60ff808a1660009081526003602090815260408083203384528252808320815180830190925280548086168352939491939092840191610100909104166002811115611c1157611c11614a9b565b6002811115611c2257611c22614a9b565b9052509050600281602001516002811115611c3f57611c3f614a9b565b148015611c935750600260008b60ff1660ff168152602001908152602001600020600301816000015160ff1681548110611c7b57611c7b614fbc565b6000918252602090912001546001600160a01b031633145b611cc9576040517fda0f08e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50816060015115611dab576020820151611ce4906001615929565b60ff16855114611d20576040517f71253a2500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8351855114611d5b576040517fa75d88af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008787604051611d6d929190615942565b604051908190038120611d84918b90602001615952565b604051602081830303815290604052805190602001209050611da98a82888888612c86565b505b6040805182815260208a81013567ffffffffffffffff169082015260ff8b16917f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef0910160405180910390a2505050505050505050565b67ffffffffffffffff8216600090815260076020526040812081611e26608085615966565b67ffffffffffffffff1681526020810191909152604001600020549392505050565b80516001600160a01b0316611e70576040516342bcdf7f60e11b815260040160405180910390fd5b80516004805460208085018051604080880180516060808b0180516001600160a01b039b8c167fffffffffffffffff000000000000000000000000000000000000000000000000909a168a17600160a01b63ffffffff988916021777ffffffffffffffffffffffffffffffffffffffffffffffff167801000000000000000000000000000000000000000000000000948816949094026001600160e01b031693909317600160e01b93871693909302929092179098556080808b0180516005805473ffffffffffffffffffffffffffffffffffffffff1916918d169190911790558451988952955185169688019690965290518316918601919091525116938301939093529151909216908201527fa55bd56595c45f517e5967a3067f3dca684445a3080e7c04a4e0d5a40cda627d9060a00160405180910390a150565b6060865167ffffffffffffffff811115611fca57611fca613ec6565b60405190808252806020026020018201604052801561200f57816020015b6040805180820190915260008082526020820152815260200190600190039081611fe85790505b50905060005b87518110156120c15761209c88828151811061203357612033614fbc565b602002602001015188888888888781811061205057612050614fbc565b9050602002810190612062919061598d565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612e9392505050565b8282815181106120ae576120ae614fbc565b6020908102919091010152600101612015565b505b9695505050505050565b60006120d883613238565b8015610c125750610c12838361329c565b336001600160a01b038216036121415760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610754565b6001805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b806040015160ff166000036121ca576000604051631b3fab5160e11b815260040161075491906159f2565b60208082015160ff8082166000908152600290935260408320600181015492939092839216900361223757606084015160018201805491151562010000027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff90921691909117905561228c565b6060840151600182015460ff620100009091041615159015151461228c576040517f87f6037c00000000000000000000000000000000000000000000000000000000815260ff84166004820152602401610754565b60a08401518051601f60ff821611156122bb576001604051631b3fab5160e11b815260040161075491906159f2565b612321858560030180548060200260200160405190810160405280929190818152602001828054801561231757602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116122f9575b5050505050613357565b8560600151156124505761238f8585600201805480602002602001604051908101604052809291908181526020018280548015612317576020028201919060005260206000209081546001600160a01b031681526001909101906020018083116122f9575050505050613357565b608086015180516123a99060028701906020840190613e20565b5080516001850180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1661010060ff841690810291909117909155601f1015612409576002604051631b3fab5160e11b815260040161075491906159f2565b6040880151612419906003615a0c565b60ff168160ff1611612441576003604051631b3fab5160e11b815260040161075491906159f2565b61244d878360016133c0565b50505b61245c858360026133c0565b81516124719060038601906020850190613e20565b5060408681015160018501805460ff191660ff8316179055875180865560a089015192517fab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f547936124ca938a939260028b01929190615a28565b60405180910390a16124db85613540565b505050505050565b81516124ee81611921565b60006124f982611a23565b602085015151909150600081900361253c576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b846040015151811461257a576040517f57e0e08300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008167ffffffffffffffff81111561259557612595613ec6565b6040519080825280602002602001820160405280156125be578160200160208202803683370190505b50905060005b82811015612733576000876020015182815181106125e4576125e4614fbc565b602002602001015190507f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681600001516040015167ffffffffffffffff161461267757805160409081015190517f38432a2200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610754565b61270d8186600101805461268a906156e9565b80601f01602080910402602001604051908101604052809291908181526020018280546126b6906156e9565b80156127035780601f106126d857610100808354040283529160200191612703565b820191906000526020600020905b8154815290600101906020018083116126e657829003601f168201915b505050505061355c565b83838151811061271f5761271f614fbc565b6020908102919091010152506001016125c4565b50600061274a858389606001518a6080015161367e565b905080600003612792576040517f7dd17a7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff86166004820152602401610754565b8551151560005b84811015610b515760005a905060008a6020015183815181106127be576127be614fbc565b6020026020010151905060006127dc8a836000015160600151610bc5565b905060008160038111156127f2576127f2614a9b565b148061280f5750600381600381111561280d5761280d614a9b565b145b612867578151606001516040805167ffffffffffffffff808e16825290921660208301527f3b575419319662b2a6f5e2467d84521517a3382b908eb3d557bb3fdb0c50e23c91015b60405180910390a1505050612c7e565b841561293757600454600090600160a01b900463ffffffff1661288a88426154c2565b11905080806128aa575060038260038111156128a8576128a8614a9b565b145b6128ec576040517fa9cfc86200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8c166004820152602401610754565b8b85815181106128fe576128fe614fbc565b6020026020010151600014612931578b858151811061291f5761291f614fbc565b60200260200101518360800181815250505b50612998565b600081600381111561294b5761294b614a9b565b14612998578151606001516040805167ffffffffffffffff808e16825290921660208301527f3ef2a99c550a751d4b0b261268f05a803dfb049ab43616a1ffb388f61fe651209101612857565b81516080015167ffffffffffffffff1615612a875760008160038111156129c1576129c1614a9b565b03612a875781516080015160208301516040517fe0e03cae0000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169263e0e03cae92612a38928f929190600401615ad4565b6020604051808303816000875af1158015612a57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a7b9190615723565b612a8757505050612c7e565b60008c604001518581518110612a9f57612a9f614fbc565b6020026020010151905080518360a001515114612b03578251606001516040517f1cfe6d8b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808e1660048301529091166024820152604401610754565b612b178b84600001516060015160016136d4565b600080612b24858461377c565b91509150612b3b8d866000015160600151846136d4565b8715612bab576003826003811115612b5557612b55614a9b565b03612bab576000846003811115612b6e57612b6e614a9b565b14612bab578451516040517f2b11b8d900000000000000000000000000000000000000000000000000000000815261075491908390600401615b01565b6002826003811115612bbf57612bbf614a9b565b14612c19576003826003811115612bd857612bd8614a9b565b14612c19578451606001516040517f926c5a3e000000000000000000000000000000000000000000000000000000008152610754918f918590600401615b1a565b8451805160609091015167ffffffffffffffff908116908f167fdc8ccbc35e0eebd81239bcd1971fcd53c7eb34034880142a0f43c809a458732f85855a612c60908d6154c2565b604051612c6f93929190615b40565b60405180910390a45050505050505b600101612799565b612c8e613e92565b835160005b81811015611053576000600188868460208110612cb257612cb2614fbc565b612cbf91901a601b615929565b898581518110612cd157612cd1614fbc565b6020026020010151898681518110612ceb57612ceb614fbc565b602002602001015160405160008152602001604052604051612d29949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015612d4b573d6000803e3d6000fd5b505060408051601f1981015160ff808e166000908152600360209081528582206001600160a01b03851683528152858220858701909652855480841686529397509095509293928401916101009004166002811115612dac57612dac614a9b565b6002811115612dbd57612dbd614a9b565b9052509050600181602001516002811115612dda57612dda614a9b565b14612e11576040517fca31867a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051859060ff16601f8110612e2857612e28614fbc565b602002015115612e64576040517ff67bc7c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600185826000015160ff16601f8110612e7f57612e7f614fbc565b911515602090920201525050600101612c93565b60408051808201909152600080825260208201526000612eb68760200151613846565b6040517fbbe4f6db0000000000000000000000000000000000000000000000000000000081526001600160a01b0380831660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063bbe4f6db90602401602060405180830381865afa158015612f3b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f5f9190615b70565b90506001600160a01b0381161580612fa75750612fa56001600160a01b0382167faff2afbf000000000000000000000000000000000000000000000000000000006120cd565b155b15612fe9576040517fae9b4ce90000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152602401610754565b600454600090819061300b9089908690600160e01b900463ffffffff166138ec565b9150915060008060006130d86040518061010001604052808e81526020018c67ffffffffffffffff1681526020018d6001600160a01b031681526020018f606001518152602001896001600160a01b031681526020018f6000015181526020018f6040015181526020018b8152506040516024016130899190615b8d565b60408051601f198184030181529190526020810180516001600160e01b03167f390775370000000000000000000000000000000000000000000000000000000017905287866113886084613a1a565b9250925092508261311757816040517fe1cd550900000000000000000000000000000000000000000000000000000000815260040161075491906148b6565b815160201461315f5781516040517f78ef8024000000000000000000000000000000000000000000000000000000008152602060048201526024810191909152604401610754565b6000828060200190518101906131759190615c5a565b9050866001600160a01b03168c6001600160a01b03161461320a5760006131a68d8a6131a1868a6154c2565b6138ec565b509050868110806131c05750816131bd88836154c2565b14155b15613208576040517fa966e21f000000000000000000000000000000000000000000000000000000008152600481018390526024810188905260448101829052606401610754565b505b604080518082019091526001600160a01b039098168852602088015250949550505050505095945050505050565b6000613264827f01ffc9a70000000000000000000000000000000000000000000000000000000061329c565b8015610c155750613295827fffffffff0000000000000000000000000000000000000000000000000000000061329c565b1592915050565b6040517fffffffff0000000000000000000000000000000000000000000000000000000082166024820152600090819060440160408051601f19818403018152919052602080820180516001600160e01b03167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825192935060009283928392909183918a617530fa92503d91506000519050828015613340575060208210155b801561334c5750600081115b979650505050505050565b60005b81518110156107805760ff83166000908152600360205260408120835190919084908490811061338c5761338c614fbc565b6020908102919091018101516001600160a01b03168252810191909152604001600020805461ffff1916905560010161335a565b60005b82518160ff161015610bbf576000838260ff16815181106133e6576133e6614fbc565b602002602001015190506000600281111561340357613403614a9b565b60ff80871660009081526003602090815260408083206001600160a01b0387168452909152902054610100900416600281111561344257613442614a9b565b14613463576004604051631b3fab5160e11b815260040161075491906159f2565b6001600160a01b0381166134a3576040517fd6c62c9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052808360ff1681526020018460028111156134c9576134c9614a9b565b905260ff80871660009081526003602090815260408083206001600160a01b0387168452825290912083518154931660ff198416811782559184015190929091839161ffff19161761010083600281111561352657613526614a9b565b0217905550905050508061353990615c73565b90506133c3565b60ff81166105dd576009805467ffffffffffffffff1916905550565b8151602080820151604092830151925160009384936135a2937f2425b0b9f9054c76ff151b0a175b18f37a4a4e82013a72e9f15c9caa095ed21f93909291889101615c92565b60408051601f1981840301815290829052805160209182012086518051888401516060808b0151908401516080808d015195015195976135eb9794969395929491939101615cc5565b604051602081830303815290604052805190602001208560400151805190602001208660a001516040516020016136229190615dd7565b60408051601f198184030181528282528051602091820120908301969096528101939093526060830191909152608082015260a081019190915260c0015b60405160208183030381529060405280519060200120905092915050565b60008061368c858585613b40565b9050613697816113d5565b6136a55760009150506136cc565b67ffffffffffffffff86166000908152600860209081526040808320938352929052205490505b949350505050565b600060026136e36080856154eb565b67ffffffffffffffff166136f79190615512565b905060006137058585611e01565b905081613714600160046154c2565b901b19168183600381111561372b5761372b614a9b565b67ffffffffffffffff871660009081526007602052604081209190921b9290921791829161375a608088615966565b67ffffffffffffffff1681526020810191909152604001600020555050505050565b6040517fa80036b4000000000000000000000000000000000000000000000000000000008152600090606090309063a80036b4906137c09087908790600401615e37565b600060405180830381600087803b1580156137da57600080fd5b505af19250505080156137eb575060015b61382a573d808015613819576040519150601f19603f3d011682016040523d82523d6000602084013e61381e565b606091505b5060039250905061383f565b50506040805160208101909152600081526002905b9250929050565b6000815160201461388557816040517f8d666f6000000000000000000000000000000000000000000000000000000000815260040161075491906148b6565b60008280602001905181019061389b9190615c5a565b90506001600160a01b038111806138b3575061040081105b15610c1557826040517f8d666f6000000000000000000000000000000000000000000000000000000000815260040161075491906148b6565b60008060008060006139668860405160240161391791906001600160a01b0391909116815260200190565b60408051601f198184030181529190526020810180516001600160e01b03167f70a082310000000000000000000000000000000000000000000000000000000017905288886113886084613a1a565b925092509250826139a557816040517fe1cd550900000000000000000000000000000000000000000000000000000000815260040161075491906148b6565b60208251146139ed5781516040517f78ef8024000000000000000000000000000000000000000000000000000000008152602060048201526024810191909152604401610754565b81806020019051810190613a019190615c5a565b613a0b82886154c2565b94509450505050935093915050565b6000606060008361ffff1667ffffffffffffffff811115613a3d57613a3d613ec6565b6040519080825280601f01601f191660200182016040528015613a67576020820181803683370190505b509150863b613a9a577f0c3b563c0000000000000000000000000000000000000000000000000000000060005260046000fd5b5a85811015613acd577fafa32a2c0000000000000000000000000000000000000000000000000000000060005260046000fd5b8590036040810481038710613b06577f37c3be290000000000000000000000000000000000000000000000000000000060005260046000fd5b505a6000808a5160208c0160008c8cf193505a900390503d84811115613b295750835b808352806000602085013e50955095509592505050565b8251825160009190818303613b81576040517f11a6b26400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6101018211801590613b9557506101018111155b613bb2576040516309bde33960e01b815260040160405180910390fd5b60001982820101610100811115613bdc576040516309bde33960e01b815260040160405180910390fd5b80600003613c095786600081518110613bf757613bf7614fbc565b60200260200101519350505050613dd8565b60008167ffffffffffffffff811115613c2457613c24613ec6565b604051908082528060200260200182016040528015613c4d578160200160208202803683370190505b50905060008080805b85811015613d775760006001821b8b811603613cb15788851015613c9a578c5160018601958e918110613c8b57613c8b614fbc565b60200260200101519050613cd3565b8551600185019487918110613c8b57613c8b614fbc565b8b5160018401938d918110613cc857613cc8614fbc565b602002602001015190505b600089861015613d03578d5160018701968f918110613cf457613cf4614fbc565b60200260200101519050613d25565b8651600186019588918110613d1a57613d1a614fbc565b602002602001015190505b82851115613d46576040516309bde33960e01b815260040160405180910390fd5b613d508282613ddf565b878481518110613d6257613d62614fbc565b60209081029190910101525050600101613c56565b506001850382148015613d8957508683145b8015613d9457508581145b613db1576040516309bde33960e01b815260040160405180910390fd5b836001860381518110613dc657613dc6614fbc565b60200260200101519750505050505050505b9392505050565b6000818310613df757613df28284613dfd565b610c12565b610c1283835b604080516001602082015290810183905260608101829052600090608001613660565b828054828255906000526020600020908101928215613e82579160200282015b82811115613e82578251825473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03909116178255602090920191600190910190613e40565b50613e8e929150613eb1565b5090565b604051806103e00160405280601f906020820280368337509192915050565b5b80821115613e8e5760008155600101613eb2565b634e487b7160e01b600052604160045260246000fd5b6040516080810167ffffffffffffffff81118282101715613eff57613eff613ec6565b60405290565b60405160a0810167ffffffffffffffff81118282101715613eff57613eff613ec6565b60405160c0810167ffffffffffffffff81118282101715613eff57613eff613ec6565b6040805190810167ffffffffffffffff81118282101715613eff57613eff613ec6565b6040516060810167ffffffffffffffff81118282101715613eff57613eff613ec6565b604051601f8201601f1916810167ffffffffffffffff81118282101715613fba57613fba613ec6565b604052919050565b600067ffffffffffffffff821115613fdc57613fdc613ec6565b5060051b60200190565b6001600160a01b03811681146105dd57600080fd5b803567ffffffffffffffff8116811461401357600080fd5b919050565b80151581146105dd57600080fd5b803561401381614018565b600067ffffffffffffffff82111561404b5761404b613ec6565b50601f01601f191660200190565b600082601f83011261406a57600080fd5b813561407d61407882614031565b613f91565b81815284602083860101111561409257600080fd5b816020850160208301376000918101602001919091529392505050565b600060208083850312156140c257600080fd5b823567ffffffffffffffff808211156140da57600080fd5b818501915085601f8301126140ee57600080fd5b81356140fc61407882613fc2565b81815260059190911b8301840190848101908883111561411b57600080fd5b8585015b838110156141c1578035858111156141375760008081fd5b86016080818c03601f190181131561414f5760008081fd5b614157613edc565b8983013561416481613fe6565b81526040614173848201613ffb565b8b83015260608085013561418681614018565b8383015292840135928984111561419f57600091508182fd5b6141ad8f8d86880101614059565b90830152508552505091860191860161411f565b5098975050505050505050565b600060a082840312156141e057600080fd5b6141e8613f05565b9050813581526141fa60208301613ffb565b602082015261420b60408301613ffb565b604082015261421c60608301613ffb565b606082015261422d60808301613ffb565b608082015292915050565b803561401381613fe6565b600082601f83011261425457600080fd5b8135602061426461407883613fc2565b82815260059290921b8401810191818101908684111561428357600080fd5b8286015b848110156120c157803567ffffffffffffffff808211156142a85760008081fd5b818901915060a080601f19848d030112156142c35760008081fd5b6142cb613f05565b87840135838111156142dd5760008081fd5b6142eb8d8a83880101614059565b825250604080850135848111156143025760008081fd5b6143108e8b83890101614059565b8a84015250606080860135858111156143295760008081fd5b6143378f8c838a0101614059565b8385015250608091508186013581840152508285013592508383111561435d5760008081fd5b61436b8d8a85880101614059565b908201528652505050918301918301614287565b6000610140828403121561439257600080fd5b61439a613f28565b90506143a683836141ce565b815260a082013567ffffffffffffffff808211156143c357600080fd5b6143cf85838601614059565b602084015260c08401359150808211156143e857600080fd5b6143f485838601614059565b604084015261440560e08501614238565b6060840152610100840135608084015261012084013591508082111561442a57600080fd5b5061443784828501614243565b60a08301525092915050565b600082601f83011261445457600080fd5b8135602061446461407883613fc2565b82815260059290921b8401810191818101908684111561448357600080fd5b8286015b848110156120c157803567ffffffffffffffff8111156144a75760008081fd5b6144b58986838b010161437f565b845250918301918301614487565b600082601f8301126144d457600080fd5b813560206144e461407883613fc2565b82815260059290921b8401810191818101908684111561450357600080fd5b8286015b848110156120c157803567ffffffffffffffff8082111561452757600080fd5b818901915089603f83011261453b57600080fd5b8582013561454b61407882613fc2565b81815260059190911b830160400190878101908c83111561456b57600080fd5b604085015b838110156145a45780358581111561458757600080fd5b6145968f6040838a0101614059565b845250918901918901614570565b50875250505092840192508301614507565b600082601f8301126145c757600080fd5b813560206145d761407883613fc2565b8083825260208201915060208460051b8701019350868411156145f957600080fd5b602086015b848110156120c157803583529183019183016145fe565b600082601f83011261462657600080fd5b8135602061463661407883613fc2565b82815260059290921b8401810191818101908684111561465557600080fd5b8286015b848110156120c157803567ffffffffffffffff8082111561467a5760008081fd5b818901915060a080601f19848d030112156146955760008081fd5b61469d613f05565b6146a8888501613ffb565b8152604080850135848111156146be5760008081fd5b6146cc8e8b83890101614443565b8a84015250606080860135858111156146e55760008081fd5b6146f38f8c838a01016144c3565b838501525060809150818601358581111561470e5760008081fd5b61471c8f8c838a01016145b6565b9184019190915250919093013590830152508352918301918301614659565b600080604080848603121561474f57600080fd5b833567ffffffffffffffff8082111561476757600080fd5b61477387838801614615565b945060209150818601358181111561478a57600080fd5b8601601f8101881361479b57600080fd5b80356147a961407882613fc2565b81815260059190911b8201840190848101908a8311156147c857600080fd5b8584015b83811015614854578035868111156147e45760008081fd5b8501603f81018d136147f65760008081fd5b8781013561480661407882613fc2565b81815260059190911b82018a0190898101908f8311156148265760008081fd5b928b01925b828410156148445783358252928a0192908a019061482b565b86525050509186019186016147cc565b50809750505050505050509250929050565b60005b83811015614881578181015183820152602001614869565b50506000910152565b600081518084526148a2816020860160208601614866565b601f01601f19169290920160200192915050565b602081526000610c12602083018461488a565b8060608101831015610c1557600080fd5b60008083601f8401126148ec57600080fd5b50813567ffffffffffffffff81111561490457600080fd5b60208301915083602082850101111561383f57600080fd5b60008083601f84011261492e57600080fd5b50813567ffffffffffffffff81111561494657600080fd5b6020830191508360208260051b850101111561383f57600080fd5b60008060008060008060008060e0898b03121561497d57600080fd5b6149878a8a6148c9565b9750606089013567ffffffffffffffff808211156149a457600080fd5b6149b08c838d016148da565b909950975060808b01359150808211156149c957600080fd5b6149d58c838d0161491c565b909750955060a08b01359150808211156149ee57600080fd5b506149fb8b828c0161491c565b999c989b50969995989497949560c00135949350505050565b600080600060808486031215614a2957600080fd5b614a3385856148c9565b9250606084013567ffffffffffffffff811115614a4f57600080fd5b614a5b868287016148da565b9497909650939450505050565b60008060408385031215614a7b57600080fd5b614a8483613ffb565b9150614a9260208401613ffb565b90509250929050565b634e487b7160e01b600052602160045260246000fd5b60048110614ac157614ac1614a9b565b9052565b60208101610c158284614ab1565b600060208284031215614ae557600080fd5b813567ffffffffffffffff811115614afc57600080fd5b820160a08185031215613dd857600080fd5b803563ffffffff8116811461401357600080fd5b600060a08284031215614b3457600080fd5b614b3c613f05565b8235614b4781613fe6565b8152614b5560208401614b0e565b6020820152614b6660408401614b0e565b6040820152614b7760608401614b0e565b60608201526080830135614b8a81613fe6565b60808201529392505050565b600080600060408486031215614bab57600080fd5b833567ffffffffffffffff80821115614bc357600080fd5b614bcf8783880161437f565b94506020860135915080821115614be557600080fd5b50614a5b8682870161491c565b803560ff8116811461401357600080fd5b600060208284031215614c1557600080fd5b610c1282614bf2565b60008151808452602080850194506020840160005b83811015614c585781516001600160a01b031687529582019590820190600101614c33565b509495945050505050565b60208152600082518051602084015260ff602082015116604084015260ff604082015116606084015260608101511515608084015250602083015160c060a0840152614cb260e0840182614c1e565b90506040840151601f198483030160c0850152614ccf8282614c1e565b95945050505050565b60008060408385031215614ceb57600080fd5b614cf483613ffb565b946020939093013593505050565b60008060208385031215614d1557600080fd5b823567ffffffffffffffff80821115614d2d57600080fd5b818501915085601f830112614d4157600080fd5b813581811115614d5057600080fd5b8660208260061b8501011115614d6557600080fd5b60209290920196919550909350505050565b600060208284031215614d8957600080fd5b610c1282613ffb565b602081526001600160a01b03825116602082015260208201511515604082015267ffffffffffffffff6040830151166060820152600060608301516080808401526136cc60a084018261488a565b600060208284031215614df257600080fd5b8135613dd881613fe6565b600082601f830112614e0e57600080fd5b81356020614e1e61407883613fc2565b8083825260208201915060208460051b870101935086841115614e4057600080fd5b602086015b848110156120c1578035614e5881613fe6565b8352918301918301614e45565b60006020808385031215614e7857600080fd5b823567ffffffffffffffff80821115614e9057600080fd5b818501915085601f830112614ea457600080fd5b8135614eb261407882613fc2565b81815260059190911b83018401908481019088831115614ed157600080fd5b8585015b838110156141c157803585811115614eec57600080fd5b860160c0818c03601f19011215614f035760008081fd5b614f0b613f28565b8882013581526040614f1e818401614bf2565b8a8301526060614f2f818501614bf2565b8284015260809150614f42828501614026565b9083015260a08381013589811115614f5a5760008081fd5b614f688f8d83880101614dfd565b838501525060c0840135915088821115614f825760008081fd5b614f908e8c84870101614dfd565b9083015250845250918601918601614ed5565b600060208284031215614fb557600080fd5b5035919050565b634e487b7160e01b600052603260045260246000fd5b80356001600160e01b038116811461401357600080fd5b600082601f830112614ffa57600080fd5b8135602061500a61407883613fc2565b82815260069290921b8401810191818101908684111561502957600080fd5b8286015b848110156120c157604081890312156150465760008081fd5b61504e613f4b565b61505782613ffb565b8152615064858301614fd2565b8186015283529183019160400161502d565b600082601f83011261508757600080fd5b8135602061509761407883613fc2565b82815260079290921b840181019181810190868411156150b657600080fd5b8286015b848110156120c15780880360808112156150d45760008081fd5b6150dc613f6e565b6150e583613ffb565b8152604080601f19840112156150fb5760008081fd5b615103613f4b565b9250615110878501613ffb565b835261511d818501613ffb565b83880152818701929092526060830135918101919091528352918301916080016150ba565b6000602080838503121561515557600080fd5b823567ffffffffffffffff8082111561516d57600080fd5b8185019150604080838803121561518357600080fd5b61518b613f4b565b83358381111561519a57600080fd5b84016040818a0312156151ac57600080fd5b6151b4613f4b565b8135858111156151c357600080fd5b8201601f81018b136151d457600080fd5b80356151e261407882613fc2565b81815260069190911b8201890190898101908d83111561520157600080fd5b928a01925b828410156152515787848f03121561521e5760008081fd5b615226613f4b565b843561523181613fe6565b815261523e858d01614fd2565b818d0152825292870192908a0190615206565b84525050508187013593508484111561526957600080fd5b6152758a858401614fe9565b818801528252508385013591508282111561528f57600080fd5b61529b88838601615076565b85820152809550505050505092915050565b805160408084528151848201819052600092602091908201906060870190855b8181101561530457835180516001600160a01b031684528501516001600160e01b03168584015292840192918501916001016152cd565b50508583015187820388850152805180835290840192506000918401905b8083101561535e578351805167ffffffffffffffff1683528501516001600160e01b031685830152928401926001929092019190850190615322565b50979650505050505050565b602081526000610c1260208301846152ad565b67ffffffffffffffff8316815260608101613dd86020830184805167ffffffffffffffff908116835260209182015116910152565b634e487b7160e01b600052601160045260246000fd5b67ffffffffffffffff8181168382160190808211156153e9576153e96153b2565b5092915050565b60006020808352606084516040808487015261540f60608701836152ad565b87850151878203601f19016040890152805180835290860193506000918601905b808310156141c157845167ffffffffffffffff81511683528781015161546f89850182805167ffffffffffffffff908116835260209182015116910152565b50840151828701529386019360019290920191608090910190615430565b60006020828403121561549f57600080fd5b813567ffffffffffffffff8111156154b657600080fd5b6136cc84828501614615565b81810381811115610c1557610c156153b2565b634e487b7160e01b600052601260045260246000fd5b600067ffffffffffffffff80841680615506576155066154d5565b92169190910692915050565b8082028115828204841417610c1557610c156153b2565b805182526000602067ffffffffffffffff81840151168185015260408084015160a0604087015261555d60a087018261488a565b905060608501518682036060880152615576828261488a565b608087810151898303918a01919091528051808352908601935060009250908501905b8083101561535e57835180516001600160a01b0316835286015186830152928501926001929092019190840190615599565b602081526000610c126020830184615529565b6080815260006155f16080830187615529565b61ffff9590951660208301525060408101929092526001600160a01b0316606090910152919050565b60008060006060848603121561562f57600080fd5b835161563a81614018565b602085015190935067ffffffffffffffff81111561565757600080fd5b8401601f8101861361566857600080fd5b805161567661407882614031565b81815287602083850101111561568b57600080fd5b61569c826020830160208601614866565b809450505050604084015190509250925092565b6000604082840312156156c257600080fd5b6156ca613f4b565b6156d383613ffb565b8152602083013560208201528091505092915050565b600181811c908216806156fd57607f821691505b60208210810361571d57634e487b7160e01b600052602260045260246000fd5b50919050565b60006020828403121561573557600080fd5b8151613dd881614018565b601f821115610780576000816000526020600020601f850160051c810160208610156157695750805b601f850160051c820191505b818110156124db57828155600101615775565b815167ffffffffffffffff8111156157a2576157a2613ec6565b6157b6816157b084546156e9565b84615740565b602080601f8311600181146157eb57600084156157d35750858301515b600019600386901b1c1916600185901b1785556124db565b600085815260208120601f198616915b8281101561581a578886015182559484019460019091019084016157fb565b50858210156158385787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6000602080835283546001600160a01b038116602085015260ff8160a01c161515604085015267ffffffffffffffff8160a81c1660608501525060018085016080808601526000815461589a816156e9565b8060a089015260c060018316600081146158bb57600181146158d757615907565b60ff19841660c08b015260c083151560051b8b01019450615907565b85600052602060002060005b848110156158fe5781548c82018501529088019089016158e3565b8b0160c0019550505b50929998505050505050505050565b80820180821115610c1557610c156153b2565b60ff8181168382160190811115610c1557610c156153b2565b8183823760009101908152919050565b828152606082602083013760800192915050565b600067ffffffffffffffff80841680615981576159816154d5565b92169190910492915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126159c257600080fd5b83018035915067ffffffffffffffff8211156159dd57600080fd5b60200191503681900382131561383f57600080fd5b6020810160058310615a0657615a06614a9b565b91905290565b60ff81811683821602908116908181146153e9576153e96153b2565b600060a0820160ff881683526020878185015260a0604085015281875480845260c0860191508860005282600020935060005b81811015615a805784546001600160a01b031683526001948501949284019201615a5b565b50508481036060860152865180825290820192508187019060005b81811015615ac05782516001600160a01b031685529383019391830191600101615a9b565b50505060ff851660808501525090506120c3565b600067ffffffffffffffff808616835280851660208401525060606040830152614ccf606083018461488a565b8281526040602082015260006136cc604083018461488a565b67ffffffffffffffff848116825283166020820152606081016136cc6040830184614ab1565b615b4a8185614ab1565b606060208201526000615b60606083018561488a565b9050826040830152949350505050565b600060208284031215615b8257600080fd5b8151613dd881613fe6565b6020815260008251610100806020850152615bac61012085018361488a565b91506020850151615bc9604086018267ffffffffffffffff169052565b5060408501516001600160a01b038116606086015250606085015160808501526080850151615c0360a08601826001600160a01b03169052565b5060a0850151601f19808685030160c0870152615c20848361488a565b935060c08701519150808685030160e0870152615c3d848361488a565b935060e08701519150808685030183870152506120c3838261488a565b600060208284031215615c6c57600080fd5b5051919050565b600060ff821660ff8103615c8957615c896153b2565b60010192915050565b848152600067ffffffffffffffff8086166020840152808516604084015250608060608301526120c3608083018461488a565b86815260c060208201526000615cde60c083018861488a565b6001600160a01b039690961660408301525067ffffffffffffffff9384166060820152608081019290925290911660a09091015292915050565b600082825180855260208086019550808260051b84010181860160005b84811015615dca57601f19868403018952815160a08151818652615d5b8287018261488a565b9150508582015185820387870152615d73828261488a565b91505060408083015186830382880152615d8d838261488a565b92505050606080830151818701525060808083015192508582038187015250615db6818361488a565b9a86019a9450505090830190600101615d35565b5090979650505050505050565b602081526000610c126020830184615d18565b60008282518085526020808601955060208260051b8401016020860160005b84811015615dca57601f19868403018952615e2583835161488a565b98840198925090830190600101615e09565b604081526000835180516040840152602081015167ffffffffffffffff80821660608601528060408401511660808601528060608401511660a08601528060808401511660c086015250505060208401516101408060e0850152615e9f61018085018361488a565b915060408601517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08086850301610100870152615edc848361488a565b935060608801519150615efb6101208701836001600160a01b03169052565b60808801518387015260a0880151925080868503016101608701525050615f228282615d18565b9150508281036020840152614ccf8185615dea56fea164736f6c6343000818000a", } diff --git a/core/gethwrappers/ccip/generated/onramp/onramp.go b/core/gethwrappers/ccip/generated/onramp/onramp.go index 46804a0e47..db21305dc8 100644 --- a/core/gethwrappers/ccip/generated/onramp/onramp.go +++ b/core/gethwrappers/ccip/generated/onramp/onramp.go @@ -81,7 +81,7 @@ type OnRampDestChainConfigArgs struct { } type OnRampDynamicConfig struct { - PriceRegistry common.Address + FeeQuoter common.Address MessageValidator common.Address FeeAggregator common.Address } @@ -94,7 +94,7 @@ type OnRampStaticConfig struct { } var OnRampMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CannotSendZeroTokens\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GetSupportedTokensFunctionalityRemovedCheckAdminRegistry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidDestChainConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeCalledByRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RouterMustSetOriginalSender\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"UnsupportedToken\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"CCIPSendRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOnRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOnRamp.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"name\":\"DestChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"feeValueJuels\",\"type\":\"uint256\"}],\"name\":\"FeePaid\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeeTokenWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyDestChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"}],\"name\":\"forwardFromRouter\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getExpectedNextSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"getFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"},{\"internalType\":\"contractIERC20\",\"name\":\"sourceToken\",\"type\":\"address\"}],\"name\":\"getPoolBySourceToken\",\"outputs\":[{\"internalType\":\"contractIPoolV1\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"contractIRouter\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"name\":\"getSupportedTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"priceRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"setDynamicConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"withdrawFeeTokens\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CannotSendZeroTokens\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GetSupportedTokensFunctionalityRemovedCheckAdminRegistry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidDestChainConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeCalledByRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RouterMustSetOriginalSender\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"UnsupportedToken\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"CCIPSendRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOnRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOnRamp.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"name\":\"DestChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"feeValueJuels\",\"type\":\"uint256\"}],\"name\":\"FeePaid\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeeTokenWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyDestChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"}],\"name\":\"forwardFromRouter\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getExpectedNextSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"getFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"},{\"internalType\":\"contractIERC20\",\"name\":\"sourceToken\",\"type\":\"address\"}],\"name\":\"getPoolBySourceToken\",\"outputs\":[{\"internalType\":\"contractIPoolV1\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"contractIRouter\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"name\":\"getSupportedTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"setDynamicConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"withdrawFeeTokens\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", Bin: "0x6101006040523480156200001257600080fd5b506040516200382d3803806200382d83398101604081905262000035916200069c565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf8162000186565b505083516001600160401b031615905080620000e6575060208301516001600160a01b0316155b80620000fd575060408301516001600160a01b0316155b8062000114575060608301516001600160a01b0316155b1562000133576040516306b7c75960e31b815260040160405180910390fd5b82516001600160401b031660805260208301516001600160a01b0390811660a0526040840151811660c05260608401511660e052620001728262000231565b6200017d816200036d565b5050506200079c565b336001600160a01b03821603620001e05760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b0316158062000254575060408101516001600160a01b0316155b1562000273576040516306b7c75960e31b815260040160405180910390fd5b8051600280546001600160a01b03199081166001600160a01b03938416179091556020808401805160038054851691861691909117905560408086018051600480549096169087161790945580516080808201835280516001600160401b031680835260a08051891684880190815260c080518b1686880190815260e080518d166060988901908152895196875293518d169a86019a909a52518b169684019690965251891693820193909352885188169181019190915292518616908301529251909316918301919091527f2d8f19dc1cd01460c3367a09d2d424f2b1940ba7c886047edd078c7b77ea4558910160405180910390a150565b60005b8151811015620004aa57600082828151811062000391576200039162000786565b602002602001015190506000838381518110620003b257620003b262000786565b6020026020010151600001519050806001600160401b0316600003620003f75760405163c35aa79d60e01b81526001600160401b038216600482015260240162000083565b6040805180820182526001600160401b03838116600081815260056020818152868320805480871688528a8301516001600160a01b03908116848a019081529587905293835287518551851668010000000000000000026001600160e01b0319909216971696871717905586519485529151169083015291927f324d4a7950b57da00ce533ad6697039be6281726a73da959d0ab3ff795181ec6910160405180910390a250505080600101905062000370565b5050565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b0381118282101715620004e957620004e9620004ae565b60405290565b604051601f8201601f191681016001600160401b03811182821017156200051a576200051a620004ae565b604052919050565b80516001600160401b03811681146200053a57600080fd5b919050565b6001600160a01b03811681146200055557600080fd5b50565b6000606082840312156200056b57600080fd5b604051606081016001600160401b0381118282101715620005905762000590620004ae565b80604052508091508251620005a5816200053f565b81526020830151620005b7816200053f565b60208201526040830151620005cc816200053f565b6040919091015292915050565b600082601f830112620005eb57600080fd5b815160206001600160401b03821115620006095762000609620004ae565b62000619818360051b01620004ef565b82815260069290921b840181019181810190868411156200063957600080fd5b8286015b84811015620006915760408189031215620006585760008081fd5b62000662620004c4565b6200066d8262000522565b8152848201516200067e816200053f565b818601528352918301916040016200063d565b509695505050505050565b6000806000838503610100811215620006b457600080fd5b6080811215620006c357600080fd5b50604051608081016001600160401b038082118383101715620006ea57620006ea620004ae565b81604052620006f98762000522565b8352602087015191506200070d826200053f565b8160208401526040870151915062000725826200053f565b816040840152606087015191506200073d826200053f565b81606084015282955062000755886080890162000558565b945060e08701519250808311156200076c57600080fd5b50506200077c86828701620005d9565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b60805160a05160c05160e05161301862000815600039600081816101eb015281816108a201526116700152600081816101af01528181610dc60152611649015260008181610173015281816104c4015261161f01526000818161014301528181610cec0152818161121101526115f201526130186000f3fe608060405234801561001057600080fd5b50600436106100f55760003560e01c80637437ff9f11610097578063d77d5ed011610066578063d77d5ed0146103ba578063df0aa9e914610406578063f2fde38b14610419578063fbca3b741461042c57600080fd5b80637437ff9f146102fb57806379ba5097146103685780638da5cb5b146103705780639041be3d1461038e57600080fd5b806320487ded116100d357806320487ded1461028757806334d560e4146102a85780633a019940146102bb57806348a98aa4146102c357600080fd5b80630242cf60146100fa57806306285c691461010f578063181f5a771461023e575b600080fd5b61010d610108366004612098565b61044c565b005b61022860408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16815250905090565b604051610235919061215b565b60405180910390f35b61027a6040518060400160405280601081526020017f4f6e52616d7020312e362e302d6465760000000000000000000000000000000081525081565b6040516102359190612220565b61029a61029536600461224b565b610460565b604051908152602001610235565b61010d6102b63660046122ab565b610619565b61010d61062a565b6102d66102d136600461231d565b61085a565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610235565b61035b6040805160608101825260008082526020820181905291810191909152506040805160608101825260025473ffffffffffffffffffffffffffffffffffffffff908116825260035481166020830152600454169181019190915290565b6040516102359190612356565b61010d61090f565b60005473ffffffffffffffffffffffffffffffffffffffff166102d6565b6103a161039c366004612393565b610a0c565b60405167ffffffffffffffff9091168152602001610235565b6102d66103c8366004612393565b67ffffffffffffffff1660009081526005602052604090205468010000000000000000900473ffffffffffffffffffffffffffffffffffffffff1690565b61029a6104143660046123b0565b610a35565b61010d61042736600461241c565b6112c6565b61043f61043a366004612393565b6112d7565b6040516102359190612439565b61045461130b565b61045d8161138e565b50565b6040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815277ffffffffffffffff00000000000000000000000000000000608084901b16600482015260009073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690632cbc26bb90602401602060405180830381865afa15801561050b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061052f91906124a3565b15610577576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024015b60405180910390fd5b6002546040517fd8694ccd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063d8694ccd906105cf90869086906004016125d2565b602060405180830381865afa1580156105ec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610610919061271b565b90505b92915050565b61062161130b565b61045d81611506565b600254604080517fcdc73d51000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163cdc73d5191600480830192869291908290030181865afa158015610699573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526106df9190810190612734565b60045490915073ffffffffffffffffffffffffffffffffffffffff1660005b825181101561085557600083828151811061071b5761071b6127c3565b60209081029190910101516040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915060009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa158015610796573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107ba919061271b565b9050801561084b576107e373ffffffffffffffffffffffffffffffffffffffff831685836116d0565b8173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f508d7d183612c18fc339b42618912b9fa3239f631dd7ec0671f950200a0fa66e8360405161084291815260200190565b60405180910390a35b50506001016106fe565b505050565b6040517fbbe4f6db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063bbe4f6db90602401602060405180830381865afa1580156108eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061061091906127f2565b60015473ffffffffffffffffffffffffffffffffffffffff163314610990576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e657200000000000000000000604482015260640161056e565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b67ffffffffffffffff80821660009081526005602052604081205490916106139116600161283e565b67ffffffffffffffff8416600090815260056020526040812073ffffffffffffffffffffffffffffffffffffffff8316610a9b576040517fa4ec747900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805468010000000000000000900473ffffffffffffffffffffffffffffffffffffffff163314610af7576040517f1c0a352900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60035473ffffffffffffffffffffffffffffffffffffffff168015610b9d576040517fe0a0e50600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82169063e0a0e50690610b6a908a908a906004016125d2565b600060405180830381600087803b158015610b8457600080fd5b505af1158015610b98573d6000803e3d6000fd5b505050505b506002546000908190819073ffffffffffffffffffffffffffffffffffffffff1663c4276bfc8a610bd460808c0160608d0161241c565b8a610be260808e018e612866565b6040518663ffffffff1660e01b8152600401610c029594939291906128cb565b600060405180830381865afa158015610c1f573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610c659190810190612993565b91945092509050610c7c6080890160608a0161241c565b73ffffffffffffffffffffffffffffffffffffffff167f075a2720282fdf622141dae0b048ef90a21a7e57c134c76912d19d006b3b3f6f84604051610cc391815260200190565b60405180910390a2604080516101a081019091526000610100820181815267ffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000081166101208501528c811661014085015287549293928392916101608401918a918791610d3891166129ea565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905567ffffffffffffffff16815260200186610e38576040517fea458c0c00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8f16600482015273ffffffffffffffffffffffffffffffffffffffff8c811660248301527f0000000000000000000000000000000000000000000000000000000000000000169063ea458c0c906044016020604051808303816000875af1158015610e0f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e339190612a11565b610e3b565b60005b67ffffffffffffffff1681525081526020018873ffffffffffffffffffffffffffffffffffffffff1681526020018a8060200190610e799190612866565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250505090825250602001610ebd8b80612866565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250505090825250602001610f0460808c018c612866565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250505090825250602001610f4e60808c0160608d0161241c565b73ffffffffffffffffffffffffffffffffffffffff1681526020018981526020018a8060400190610f7f9190612a2e565b905067ffffffffffffffff811115610f9957610f99611f95565b604051908082528060200260200182016040528015610ffc57816020015b610fe96040518060a0016040528060608152602001606081526020016060815260200160008152602001606081525090565b815260200190600190039081610fb75790505b509052905060005b61101160408b018b612a2e565b90508110156110c05761109761102a60408c018c612a2e565b8381811061103a5761103a6127c3565b9050604002018036038101906110509190612a96565b8c61105b8d80612866565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508e925061175d915050565b8260e0015182815181106110ad576110ad6127c3565b6020908102919091010152600101611004565b5060025460e082015160009173ffffffffffffffffffffffffffffffffffffffff169063085318f8908d906110f860408f018f612a2e565b6040518563ffffffff1660e01b81526004016111179493929190612bad565b600060405180830381865afa158015611134573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261117a9190810190612be3565b905060005b8260e00151518110156111d35781818151811061119e5761119e6127c3565b60200260200101518360e0015182815181106111bc576111bc6127c3565b60209081029190910101516080015260010161117f565b506080808301849052604080517f130ac867e79e2789f923760a88743d292acdf7002139a588206e2260f73f7321602082015267ffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811692820192909252908d166060820152309181019190915261126d90839060a00160405160208183030381529060405280519060200120611a83565b82515260405167ffffffffffffffff8c16907fcae3d9f68a9ed33d0a770e9bcc6fc25d4041dd6391e6cd8015546547a3c93140906112ac908590612c94565b60405180910390a25051519450505050505b949350505050565b6112ce61130b565b61045d81611b83565b60606040517f9e7177c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005473ffffffffffffffffffffffffffffffffffffffff16331461138c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640161056e565b565b60005b81518110156115025760008282815181106113ae576113ae6127c3565b6020026020010151905060008383815181106113cc576113cc6127c3565b60200260200101516000015190508067ffffffffffffffff1660000361142a576040517fc35aa79d00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8216600482015260240161056e565b60408051808201825267ffffffffffffffff838116600081815260056020818152868320805480871688528a83015173ffffffffffffffffffffffffffffffffffffffff908116848a019081529587905293835287518551851668010000000000000000027fffffffff00000000000000000000000000000000000000000000000000000000909216971696871717905586519485529151169083015291927f324d4a7950b57da00ce533ad6697039be6281726a73da959d0ab3ff795181ec6910160405180910390a2505050806001019050611391565b5050565b805173ffffffffffffffffffffffffffffffffffffffff1615806115425750604081015173ffffffffffffffffffffffffffffffffffffffff16155b15611579576040517f35be3ac800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051600280547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff93841617909155602080840151600380548416918516919091179055604080850151600480549094169085161790925581516080810183527f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681527f00000000000000000000000000000000000000000000000000000000000000008416918101919091527f00000000000000000000000000000000000000000000000000000000000000008316818301527f00000000000000000000000000000000000000000000000000000000000000009092166060830152517f2d8f19dc1cd01460c3367a09d2d424f2b1940ba7c886047edd078c7b77ea4558916116c5918490612de2565b60405180910390a150565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052610855908490611c78565b61178f6040518060a0016040528060608152602001606081526020016060815260200160008152602001606081525090565b84602001516000036117cd576040517f5cf0444900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006117dd85876000015161085a565b905073ffffffffffffffffffffffffffffffffffffffff811615806118ad57506040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527faff2afbf00000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff8216906301ffc9a790602401602060405180830381865afa158015611887573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118ab91906124a3565b155b156118ff5785516040517fbf16aab600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116600482015260240161056e565b60008173ffffffffffffffffffffffffffffffffffffffff16639a4575b96040518060a001604052808881526020018967ffffffffffffffff1681526020018773ffffffffffffffffffffffffffffffffffffffff1681526020018a6020015181526020018a6000015173ffffffffffffffffffffffffffffffffffffffff168152506040518263ffffffff1660e01b815260040161199e9190612e74565b6000604051808303816000875af11580156119bd573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611a039190810190612eea565b6040805160a0810190915273ffffffffffffffffffffffffffffffffffffffff841660c08201529091508060e0810160405160208183030381529060405281526020018260000151815260200182602001518152602001886020015181526020016040518060200160405280600081525081525092505050949350505050565b60008060001b82846020015185606001518660000151606001518760000151608001518860a001518960c00151604051602001611ac596959493929190612f7b565b604051602081830303815290604052805190602001208560400151805190602001208660e00151604051602001611afc9190612fdc565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201206080808c0151805190840120928501989098529183019590955260608201939093529384015260a083015260c082015260e00160405160208183030381529060405280519060200120905092915050565b3373ffffffffffffffffffffffffffffffffffffffff821603611c02576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161056e565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000611cda826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611d849092919063ffffffff16565b8051909150156108555780806020019051810190611cf891906124a3565b610855576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f74207375636365656400000000000000000000000000000000000000000000606482015260840161056e565b6060611d938484600085611d9d565b90505b9392505050565b606082471015611e2f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c0000000000000000000000000000000000000000000000000000606482015260840161056e565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051611e589190612fef565b60006040518083038185875af1925050503d8060008114611e95576040519150601f19603f3d011682016040523d82523d6000602084013e611e9a565b606091505b5091509150611eab87838387611eb6565b979650505050505050565b60608315611f4c578251600003611f455773ffffffffffffffffffffffffffffffffffffffff85163b611f45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161056e565b50816112be565b6112be8383815115611f615781518083602001fd5b806040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161056e9190612220565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715611fe757611fe7611f95565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561203457612034611f95565b604052919050565b600067ffffffffffffffff82111561205657612056611f95565b5060051b60200190565b67ffffffffffffffff8116811461045d57600080fd5b73ffffffffffffffffffffffffffffffffffffffff8116811461045d57600080fd5b600060208083850312156120ab57600080fd5b823567ffffffffffffffff8111156120c257600080fd5b8301601f810185136120d357600080fd5b80356120e66120e18261203c565b611fed565b81815260069190911b8201830190838101908783111561210557600080fd5b928401925b82841015611eab57604084890312156121235760008081fd5b61212b611fc4565b843561213681612060565b81528486013561214581612076565b818701528252604093909301929084019061210a565b60808101610613828467ffffffffffffffff8151168252602081015173ffffffffffffffffffffffffffffffffffffffff808216602085015280604084015116604085015280606084015116606085015250505050565b60005b838110156121cd5781810151838201526020016121b5565b50506000910152565b600081518084526121ee8160208601602086016121b2565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061061060208301846121d6565b600060a0828403121561224557600080fd5b50919050565b6000806040838503121561225e57600080fd5b823561226981612060565b9150602083013567ffffffffffffffff81111561228557600080fd5b61229185828601612233565b9150509250929050565b80356122a681612076565b919050565b6000606082840312156122bd57600080fd5b6040516060810181811067ffffffffffffffff821117156122e0576122e0611f95565b60405282356122ee81612076565b815260208301356122fe81612076565b6020820152604083013561231181612076565b60408201529392505050565b6000806040838503121561233057600080fd5b823561233b81612060565b9150602083013561234b81612076565b809150509250929050565b606081016106138284805173ffffffffffffffffffffffffffffffffffffffff908116835260208083015182169084015260409182015116910152565b6000602082840312156123a557600080fd5b8135611d9681612060565b600080600080608085870312156123c657600080fd5b84356123d181612060565b9350602085013567ffffffffffffffff8111156123ed57600080fd5b6123f987828801612233565b93505060408501359150606085013561241181612076565b939692955090935050565b60006020828403121561242e57600080fd5b8135611d9681612076565b6020808252825182820181905260009190848201906040850190845b8181101561248757835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101612455565b50909695505050505050565b805180151581146122a657600080fd5b6000602082840312156124b557600080fd5b61061082612493565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126124f357600080fd5b830160208101925035905067ffffffffffffffff81111561251357600080fd5b80360382131561252257600080fd5b9250929050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b8183526000602080850194508260005b858110156125c757813561259581612076565b73ffffffffffffffffffffffffffffffffffffffff168752818301358388015260409687019690910190600101612582565b509495945050505050565b600067ffffffffffffffff8085168352604060208401526125f384856124be565b60a0604086015261260860e086018284612529565b91505061261860208601866124be565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08087850301606088015261264e848385612529565b9350604088013592507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe188360301831261268757600080fd5b602092880192830192359150848211156126a057600080fd5b8160061b36038313156126b257600080fd5b808785030160808801526126c7848385612572565b94506126d56060890161229b565b73ffffffffffffffffffffffffffffffffffffffff811660a0890152935061270060808901896124be565b94509250808786030160c08801525050611eab838383612529565b60006020828403121561272d57600080fd5b5051919050565b6000602080838503121561274757600080fd5b825167ffffffffffffffff81111561275e57600080fd5b8301601f8101851361276f57600080fd5b805161277d6120e18261203c565b81815260059190911b8201830190838101908783111561279c57600080fd5b928401925b82841015611eab5783516127b481612076565b825292840192908401906127a1565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561280457600080fd5b8151611d9681612076565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b67ffffffffffffffff81811683821601908082111561285f5761285f61280f565b5092915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261289b57600080fd5b83018035915067ffffffffffffffff8211156128b657600080fd5b60200191503681900382131561252257600080fd5b67ffffffffffffffff8616815273ffffffffffffffffffffffffffffffffffffffff85166020820152836040820152608060608201526000611eab608083018486612529565b600082601f83011261292257600080fd5b815167ffffffffffffffff81111561293c5761293c611f95565b61296d60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611fed565b81815284602083860101111561298257600080fd5b6112be8260208301602087016121b2565b6000806000606084860312156129a857600080fd5b835192506129b860208501612493565b9150604084015167ffffffffffffffff8111156129d457600080fd5b6129e086828701612911565b9150509250925092565b600067ffffffffffffffff808316818103612a0757612a0761280f565b6001019392505050565b600060208284031215612a2357600080fd5b8151611d9681612060565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112612a6357600080fd5b83018035915067ffffffffffffffff821115612a7e57600080fd5b6020019150600681901b360382131561252257600080fd5b600060408284031215612aa857600080fd5b612ab0611fc4565b8235612abb81612076565b81526020928301359281019290925250919050565b600082825180855260208086019550808260051b84010181860160005b84811015612ba0577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018952815160a08151818652612b31828701826121d6565b9150508582015185820387870152612b4982826121d6565b91505060408083015186830382880152612b6383826121d6565b92505050606080830151818701525060808083015192508582038187015250612b8c81836121d6565b9a86019a9450505090830190600101612aed565b5090979650505050505050565b67ffffffffffffffff85168152606060208201526000612bd06060830186612ad0565b8281036040840152611eab818587612572565b60006020808385031215612bf657600080fd5b825167ffffffffffffffff80821115612c0e57600080fd5b818501915085601f830112612c2257600080fd5b8151612c306120e18261203c565b81815260059190911b83018401908481019088831115612c4f57600080fd5b8585015b83811015612c8757805185811115612c6b5760008081fd5b612c798b89838a0101612911565b845250918601918601612c53565b5098975050505050505050565b60208152612ce560208201835180518252602081015167ffffffffffffffff808216602085015280604084015116604085015280606084015116606085015280608084015116608085015250505050565b60006020830151612d0e60c084018273ffffffffffffffffffffffffffffffffffffffff169052565b5060408301516101808060e0850152612d2b6101a08501836121d6565b915060608501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08086850301610100870152612d6884836121d6565b9350608087015191508086850301610120870152612d8684836121d6565b935060a08701519150612db261014087018373ffffffffffffffffffffffffffffffffffffffff169052565b60c087015161016087015260e0870151915080868503018387015250612dd88382612ad0565b9695505050505050565b60e08101612e39828567ffffffffffffffff8151168252602081015173ffffffffffffffffffffffffffffffffffffffff808216602085015280604084015116604085015280606084015116606085015250505050565b825173ffffffffffffffffffffffffffffffffffffffff90811660808401526020840151811660a084015260408401511660c0830152611d96565b602081526000825160a06020840152612e9060c08401826121d6565b905067ffffffffffffffff6020850151166040840152604084015173ffffffffffffffffffffffffffffffffffffffff8082166060860152606086015160808601528060808701511660a086015250508091505092915050565b600060208284031215612efc57600080fd5b815167ffffffffffffffff80821115612f1457600080fd5b9083019060408286031215612f2857600080fd5b612f30611fc4565b825182811115612f3f57600080fd5b612f4b87828601612911565b825250602083015182811115612f6057600080fd5b612f6c87828601612911565b60208301525095945050505050565b600073ffffffffffffffffffffffffffffffffffffffff808916835260c06020840152612fab60c08401896121d6565b67ffffffffffffffff97881660408501529590961660608301525091909316608082015260a0019190915292915050565b6020815260006106106020830184612ad0565b600082516130018184602087016121b2565b919091019291505056fea164736f6c6343000818000a", } diff --git a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt index 4ebdb09e02..9fd0ac9e8d 100644 --- a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -11,6 +11,7 @@ commit_store_helper: ../../../contracts/solc/v0.8.24/CommitStoreHelper/CommitSto ether_sender_receiver: ../../../contracts/solc/v0.8.24/EtherSenderReceiver/EtherSenderReceiver.abi ../../../contracts/solc/v0.8.24/EtherSenderReceiver/EtherSenderReceiver.bin 09510a3f773f108a3c231e8d202835c845ded862d071ec54c4f89c12d868b8de evm_2_evm_offramp: ../../../contracts/solc/v0.8.24/EVM2EVMOffRamp/EVM2EVMOffRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMOffRamp/EVM2EVMOffRamp.bin b0d77babbe635cd6ba04c2af049badc9e9d28a4b6ed6bb75f830ad902a618beb evm_2_evm_onramp: ../../../contracts/solc/v0.8.24/EVM2EVMOnRamp/EVM2EVMOnRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMOnRamp/EVM2EVMOnRamp.bin 5c02c2b167946b3467636ff2bb58594cb4652fc63d8bdfee2488ed562e2a3e50 +fee_quoter: ../../../contracts/solc/v0.8.24/FeeQuoter/FeeQuoter.abi ../../../contracts/solc/v0.8.24/FeeQuoter/FeeQuoter.bin 95cdd54835272004bbe4a469b8529aa6f92ece2f903d914615010f1bf80a16c8 lock_release_token_pool: ../../../contracts/solc/v0.8.24/LockReleaseTokenPool/LockReleaseTokenPool.abi ../../../contracts/solc/v0.8.24/LockReleaseTokenPool/LockReleaseTokenPool.bin e6a8ec9e8faccb1da7d90e0f702ed72975964f97dc3222b54cfcca0a0ba3fea2 lock_release_token_pool_and_proxy: ../../../contracts/solc/v0.8.24/LockReleaseTokenPoolAndProxy/LockReleaseTokenPoolAndProxy.abi ../../../contracts/solc/v0.8.24/LockReleaseTokenPoolAndProxy/LockReleaseTokenPoolAndProxy.bin e632b08be0fbd1d013e8b3a9d75293d0d532b83071c531ff2be1deec1fa48ec1 maybe_revert_message_receiver: ../../../contracts/solc/v0.8.24/MaybeRevertMessageReceiver/MaybeRevertMessageReceiver.abi ../../../contracts/solc/v0.8.24/MaybeRevertMessageReceiver/MaybeRevertMessageReceiver.bin d73956c26232ebcc4a5444429fa99cbefed960e323be9b5a24925885c2e477d5 @@ -18,12 +19,12 @@ message_hasher: ../../../contracts/solc/v0.8.24/MessageHasher/MessageHasher.abi mock_usdc_token_messenger: ../../../contracts/solc/v0.8.24/MockE2EUSDCTokenMessenger/MockE2EUSDCTokenMessenger.abi ../../../contracts/solc/v0.8.24/MockE2EUSDCTokenMessenger/MockE2EUSDCTokenMessenger.bin d976651d36b33ac2196b32b9d2f4fa6690c6a18d41b621365659fce1c1d1e737 mock_usdc_token_transmitter: ../../../contracts/solc/v0.8.24/MockE2EUSDCTransmitter/MockE2EUSDCTransmitter.abi ../../../contracts/solc/v0.8.24/MockE2EUSDCTransmitter/MockE2EUSDCTransmitter.bin be0dbc3e475741ea0b7a54ec2b935a321b428baa9f4ce18180a87fb38bb87de2 mock_v3_aggregator_contract: ../../../contracts/solc/v0.8.24/MockV3Aggregator/MockV3Aggregator.abi ../../../contracts/solc/v0.8.24/MockV3Aggregator/MockV3Aggregator.bin 518e19efa2ff52b0fefd8e597b05765317ee7638189bfe34ca43de2f6599faf4 -multi_aggregate_rate_limiter: ../../../contracts/solc/v0.8.24/MultiAggregateRateLimiter/MultiAggregateRateLimiter.abi ../../../contracts/solc/v0.8.24/MultiAggregateRateLimiter/MultiAggregateRateLimiter.bin 51435ef057455bea49888b81b06ed92f6b82c58f59e3575e4c60833031e23750 +multi_aggregate_rate_limiter: ../../../contracts/solc/v0.8.24/MultiAggregateRateLimiter/MultiAggregateRateLimiter.abi ../../../contracts/solc/v0.8.24/MultiAggregateRateLimiter/MultiAggregateRateLimiter.bin 0b541232e49727e947dc164eadf35963c66e67576f21baa0ecaa06a8833148ed multi_ocr3_helper: ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Helper.abi ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Helper.bin aa299e0c2659d53aad4eace4d66be0e734b1366008593669cf30361ff529da6a nonce_manager: ../../../contracts/solc/v0.8.24/NonceManager/NonceManager.abi ../../../contracts/solc/v0.8.24/NonceManager/NonceManager.bin 6f64e1083b356c06ee66b9138e398b9c97a4cd3e8c9ec38cf3010cebc79af536 ocr3_config_encoder: ../../../contracts/solc/v0.8.24/IOCR3ConfigEncoder/IOCR3ConfigEncoder.abi ../../../contracts/solc/v0.8.24/IOCR3ConfigEncoder/IOCR3ConfigEncoder.bin e21180898e1ad54a045ee20add85a2793c681425ea06f66d1a9e5cab128b6487 -offramp: ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.abi ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.bin e47ad9f887ace1741af3147cbd82c89e10deb3c68d8ffcd7fcbca33dc017e35a -onramp: ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.abi ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.bin 5b00bebfbf22003a13a2bce78e35c90869ca1dc2ebd3febd9bdf8151d8fa11e0 +offramp: ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.abi ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.bin 4c1965d8e60a5ce133f71d46102b6cb932edce4538da096b048477154fac9fc1 +onramp: ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.abi ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.bin 13927b48bd09b9ab2c62143973c747f8c2e1ebc9f95f17a61ace67a68c71ec75 ping_pong_demo: ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.abi ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.bin c1c2f8a65c7ffd971899cae7fe62f2da57d09e936151e2b92163c4bebe699d6b price_registry: ../../../contracts/solc/v0.8.24/PriceRegistry/PriceRegistry.abi ../../../contracts/solc/v0.8.24/PriceRegistry/PriceRegistry.bin e7781d600c1bb7aa4620106af7f6e146a109b97f4cb6a7d06c9e15773340ecb2 registry_module_owner_custom: ../../../contracts/solc/v0.8.24/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.abi ../../../contracts/solc/v0.8.24/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.bin 75be86323c227917a9bbc3f799d7ed02f92db546653a36db30ed0ebe64461353 diff --git a/core/gethwrappers/ccip/go_generate.go b/core/gethwrappers/ccip/go_generate.go index a41b01c7ab..5c316af1ac 100644 --- a/core/gethwrappers/ccip/go_generate.go +++ b/core/gethwrappers/ccip/go_generate.go @@ -14,7 +14,7 @@ package ccip //go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.abi ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.bin OffRamp offramp //go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/MultiAggregateRateLimiter/MultiAggregateRateLimiter.abi ../../../contracts/solc/v0.8.24/MultiAggregateRateLimiter/MultiAggregateRateLimiter.bin MultiAggregateRateLimiter multi_aggregate_rate_limiter //go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/Router/Router.abi ../../../contracts/solc/v0.8.24/Router/Router.bin Router router -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/PriceRegistry/PriceRegistry.abi ../../../contracts/solc/v0.8.24/PriceRegistry/PriceRegistry.bin PriceRegistry price_registry +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/FeeQuoter/FeeQuoter.abi ../../../contracts/solc/v0.8.24/FeeQuoter/FeeQuoter.bin FeeQuoter fee_quoter //go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/CCIPConfig/CCIPConfig.abi ../../../contracts/solc/v0.8.24/CCIPConfig/CCIPConfig.bin CCIPConfig ccip_config //go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/NonceManager/NonceManager.abi ../../../contracts/solc/v0.8.24/NonceManager/NonceManager.bin NonceManager nonce_manager diff --git a/core/gethwrappers/ccip/mocks/fee_quoter_interface.go b/core/gethwrappers/ccip/mocks/fee_quoter_interface.go new file mode 100644 index 0000000000..27f53c0bd9 --- /dev/null +++ b/core/gethwrappers/ccip/mocks/fee_quoter_interface.go @@ -0,0 +1,4509 @@ +// Code generated by mockery v2.43.2. DO NOT EDIT. + +package mock_contracts + +import ( + big "math/big" + + bind "github.com/ethereum/go-ethereum/accounts/abi/bind" + common "github.com/ethereum/go-ethereum/common" + + event "github.com/ethereum/go-ethereum/event" + + fee_quoter "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/fee_quoter" + + generated "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated" + + mock "github.com/stretchr/testify/mock" + + types "github.com/ethereum/go-ethereum/core/types" +) + +// FeeQuoterInterface is an autogenerated mock type for the FeeQuoterInterface type +type FeeQuoterInterface struct { + mock.Mock +} + +type FeeQuoterInterface_Expecter struct { + mock *mock.Mock +} + +func (_m *FeeQuoterInterface) EXPECT() *FeeQuoterInterface_Expecter { + return &FeeQuoterInterface_Expecter{mock: &_m.Mock} +} + +// AcceptOwnership provides a mock function with given fields: opts +func (_m *FeeQuoterInterface) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + ret := _m.Called(opts) + + if len(ret) == 0 { + panic("no return value specified for AcceptOwnership") + } + + var r0 *types.Transaction + var r1 error + if rf, ok := ret.Get(0).(func(*bind.TransactOpts) (*types.Transaction, error)); ok { + return rf(opts) + } + if rf, ok := ret.Get(0).(func(*bind.TransactOpts) *types.Transaction); ok { + r0 = rf(opts) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.Transaction) + } + } + + if rf, ok := ret.Get(1).(func(*bind.TransactOpts) error); ok { + r1 = rf(opts) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_AcceptOwnership_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'AcceptOwnership' +type FeeQuoterInterface_AcceptOwnership_Call struct { + *mock.Call +} + +// AcceptOwnership is a helper method to define mock.On call +// - opts *bind.TransactOpts +func (_e *FeeQuoterInterface_Expecter) AcceptOwnership(opts interface{}) *FeeQuoterInterface_AcceptOwnership_Call { + return &FeeQuoterInterface_AcceptOwnership_Call{Call: _e.mock.On("AcceptOwnership", opts)} +} + +func (_c *FeeQuoterInterface_AcceptOwnership_Call) Run(run func(opts *bind.TransactOpts)) *FeeQuoterInterface_AcceptOwnership_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.TransactOpts)) + }) + return _c +} + +func (_c *FeeQuoterInterface_AcceptOwnership_Call) Return(_a0 *types.Transaction, _a1 error) *FeeQuoterInterface_AcceptOwnership_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_AcceptOwnership_Call) RunAndReturn(run func(*bind.TransactOpts) (*types.Transaction, error)) *FeeQuoterInterface_AcceptOwnership_Call { + _c.Call.Return(run) + return _c +} + +// Address provides a mock function with given fields: +func (_m *FeeQuoterInterface) Address() common.Address { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for Address") + } + + var r0 common.Address + if rf, ok := ret.Get(0).(func() common.Address); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(common.Address) + } + } + + return r0 +} + +// FeeQuoterInterface_Address_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Address' +type FeeQuoterInterface_Address_Call struct { + *mock.Call +} + +// Address is a helper method to define mock.On call +func (_e *FeeQuoterInterface_Expecter) Address() *FeeQuoterInterface_Address_Call { + return &FeeQuoterInterface_Address_Call{Call: _e.mock.On("Address")} +} + +func (_c *FeeQuoterInterface_Address_Call) Run(run func()) *FeeQuoterInterface_Address_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *FeeQuoterInterface_Address_Call) Return(_a0 common.Address) *FeeQuoterInterface_Address_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *FeeQuoterInterface_Address_Call) RunAndReturn(run func() common.Address) *FeeQuoterInterface_Address_Call { + _c.Call.Return(run) + return _c +} + +// ApplyAuthorizedCallerUpdates provides a mock function with given fields: opts, authorizedCallerArgs +func (_m *FeeQuoterInterface) ApplyAuthorizedCallerUpdates(opts *bind.TransactOpts, authorizedCallerArgs fee_quoter.AuthorizedCallersAuthorizedCallerArgs) (*types.Transaction, error) { + ret := _m.Called(opts, authorizedCallerArgs) + + if len(ret) == 0 { + panic("no return value specified for ApplyAuthorizedCallerUpdates") + } + + var r0 *types.Transaction + var r1 error + if rf, ok := ret.Get(0).(func(*bind.TransactOpts, fee_quoter.AuthorizedCallersAuthorizedCallerArgs) (*types.Transaction, error)); ok { + return rf(opts, authorizedCallerArgs) + } + if rf, ok := ret.Get(0).(func(*bind.TransactOpts, fee_quoter.AuthorizedCallersAuthorizedCallerArgs) *types.Transaction); ok { + r0 = rf(opts, authorizedCallerArgs) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.Transaction) + } + } + + if rf, ok := ret.Get(1).(func(*bind.TransactOpts, fee_quoter.AuthorizedCallersAuthorizedCallerArgs) error); ok { + r1 = rf(opts, authorizedCallerArgs) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_ApplyAuthorizedCallerUpdates_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ApplyAuthorizedCallerUpdates' +type FeeQuoterInterface_ApplyAuthorizedCallerUpdates_Call struct { + *mock.Call +} + +// ApplyAuthorizedCallerUpdates is a helper method to define mock.On call +// - opts *bind.TransactOpts +// - authorizedCallerArgs fee_quoter.AuthorizedCallersAuthorizedCallerArgs +func (_e *FeeQuoterInterface_Expecter) ApplyAuthorizedCallerUpdates(opts interface{}, authorizedCallerArgs interface{}) *FeeQuoterInterface_ApplyAuthorizedCallerUpdates_Call { + return &FeeQuoterInterface_ApplyAuthorizedCallerUpdates_Call{Call: _e.mock.On("ApplyAuthorizedCallerUpdates", opts, authorizedCallerArgs)} +} + +func (_c *FeeQuoterInterface_ApplyAuthorizedCallerUpdates_Call) Run(run func(opts *bind.TransactOpts, authorizedCallerArgs fee_quoter.AuthorizedCallersAuthorizedCallerArgs)) *FeeQuoterInterface_ApplyAuthorizedCallerUpdates_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.TransactOpts), args[1].(fee_quoter.AuthorizedCallersAuthorizedCallerArgs)) + }) + return _c +} + +func (_c *FeeQuoterInterface_ApplyAuthorizedCallerUpdates_Call) Return(_a0 *types.Transaction, _a1 error) *FeeQuoterInterface_ApplyAuthorizedCallerUpdates_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_ApplyAuthorizedCallerUpdates_Call) RunAndReturn(run func(*bind.TransactOpts, fee_quoter.AuthorizedCallersAuthorizedCallerArgs) (*types.Transaction, error)) *FeeQuoterInterface_ApplyAuthorizedCallerUpdates_Call { + _c.Call.Return(run) + return _c +} + +// ApplyDestChainConfigUpdates provides a mock function with given fields: opts, destChainConfigArgs +func (_m *FeeQuoterInterface) ApplyDestChainConfigUpdates(opts *bind.TransactOpts, destChainConfigArgs []fee_quoter.FeeQuoterDestChainConfigArgs) (*types.Transaction, error) { + ret := _m.Called(opts, destChainConfigArgs) + + if len(ret) == 0 { + panic("no return value specified for ApplyDestChainConfigUpdates") + } + + var r0 *types.Transaction + var r1 error + if rf, ok := ret.Get(0).(func(*bind.TransactOpts, []fee_quoter.FeeQuoterDestChainConfigArgs) (*types.Transaction, error)); ok { + return rf(opts, destChainConfigArgs) + } + if rf, ok := ret.Get(0).(func(*bind.TransactOpts, []fee_quoter.FeeQuoterDestChainConfigArgs) *types.Transaction); ok { + r0 = rf(opts, destChainConfigArgs) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.Transaction) + } + } + + if rf, ok := ret.Get(1).(func(*bind.TransactOpts, []fee_quoter.FeeQuoterDestChainConfigArgs) error); ok { + r1 = rf(opts, destChainConfigArgs) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_ApplyDestChainConfigUpdates_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ApplyDestChainConfigUpdates' +type FeeQuoterInterface_ApplyDestChainConfigUpdates_Call struct { + *mock.Call +} + +// ApplyDestChainConfigUpdates is a helper method to define mock.On call +// - opts *bind.TransactOpts +// - destChainConfigArgs []fee_quoter.FeeQuoterDestChainConfigArgs +func (_e *FeeQuoterInterface_Expecter) ApplyDestChainConfigUpdates(opts interface{}, destChainConfigArgs interface{}) *FeeQuoterInterface_ApplyDestChainConfigUpdates_Call { + return &FeeQuoterInterface_ApplyDestChainConfigUpdates_Call{Call: _e.mock.On("ApplyDestChainConfigUpdates", opts, destChainConfigArgs)} +} + +func (_c *FeeQuoterInterface_ApplyDestChainConfigUpdates_Call) Run(run func(opts *bind.TransactOpts, destChainConfigArgs []fee_quoter.FeeQuoterDestChainConfigArgs)) *FeeQuoterInterface_ApplyDestChainConfigUpdates_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.TransactOpts), args[1].([]fee_quoter.FeeQuoterDestChainConfigArgs)) + }) + return _c +} + +func (_c *FeeQuoterInterface_ApplyDestChainConfigUpdates_Call) Return(_a0 *types.Transaction, _a1 error) *FeeQuoterInterface_ApplyDestChainConfigUpdates_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_ApplyDestChainConfigUpdates_Call) RunAndReturn(run func(*bind.TransactOpts, []fee_quoter.FeeQuoterDestChainConfigArgs) (*types.Transaction, error)) *FeeQuoterInterface_ApplyDestChainConfigUpdates_Call { + _c.Call.Return(run) + return _c +} + +// ApplyFeeTokensUpdates provides a mock function with given fields: opts, feeTokensToAdd, feeTokensToRemove +func (_m *FeeQuoterInterface) ApplyFeeTokensUpdates(opts *bind.TransactOpts, feeTokensToAdd []common.Address, feeTokensToRemove []common.Address) (*types.Transaction, error) { + ret := _m.Called(opts, feeTokensToAdd, feeTokensToRemove) + + if len(ret) == 0 { + panic("no return value specified for ApplyFeeTokensUpdates") + } + + var r0 *types.Transaction + var r1 error + if rf, ok := ret.Get(0).(func(*bind.TransactOpts, []common.Address, []common.Address) (*types.Transaction, error)); ok { + return rf(opts, feeTokensToAdd, feeTokensToRemove) + } + if rf, ok := ret.Get(0).(func(*bind.TransactOpts, []common.Address, []common.Address) *types.Transaction); ok { + r0 = rf(opts, feeTokensToAdd, feeTokensToRemove) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.Transaction) + } + } + + if rf, ok := ret.Get(1).(func(*bind.TransactOpts, []common.Address, []common.Address) error); ok { + r1 = rf(opts, feeTokensToAdd, feeTokensToRemove) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_ApplyFeeTokensUpdates_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ApplyFeeTokensUpdates' +type FeeQuoterInterface_ApplyFeeTokensUpdates_Call struct { + *mock.Call +} + +// ApplyFeeTokensUpdates is a helper method to define mock.On call +// - opts *bind.TransactOpts +// - feeTokensToAdd []common.Address +// - feeTokensToRemove []common.Address +func (_e *FeeQuoterInterface_Expecter) ApplyFeeTokensUpdates(opts interface{}, feeTokensToAdd interface{}, feeTokensToRemove interface{}) *FeeQuoterInterface_ApplyFeeTokensUpdates_Call { + return &FeeQuoterInterface_ApplyFeeTokensUpdates_Call{Call: _e.mock.On("ApplyFeeTokensUpdates", opts, feeTokensToAdd, feeTokensToRemove)} +} + +func (_c *FeeQuoterInterface_ApplyFeeTokensUpdates_Call) Run(run func(opts *bind.TransactOpts, feeTokensToAdd []common.Address, feeTokensToRemove []common.Address)) *FeeQuoterInterface_ApplyFeeTokensUpdates_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.TransactOpts), args[1].([]common.Address), args[2].([]common.Address)) + }) + return _c +} + +func (_c *FeeQuoterInterface_ApplyFeeTokensUpdates_Call) Return(_a0 *types.Transaction, _a1 error) *FeeQuoterInterface_ApplyFeeTokensUpdates_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_ApplyFeeTokensUpdates_Call) RunAndReturn(run func(*bind.TransactOpts, []common.Address, []common.Address) (*types.Transaction, error)) *FeeQuoterInterface_ApplyFeeTokensUpdates_Call { + _c.Call.Return(run) + return _c +} + +// ApplyPremiumMultiplierWeiPerEthUpdates provides a mock function with given fields: opts, premiumMultiplierWeiPerEthArgs +func (_m *FeeQuoterInterface) ApplyPremiumMultiplierWeiPerEthUpdates(opts *bind.TransactOpts, premiumMultiplierWeiPerEthArgs []fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthArgs) (*types.Transaction, error) { + ret := _m.Called(opts, premiumMultiplierWeiPerEthArgs) + + if len(ret) == 0 { + panic("no return value specified for ApplyPremiumMultiplierWeiPerEthUpdates") + } + + var r0 *types.Transaction + var r1 error + if rf, ok := ret.Get(0).(func(*bind.TransactOpts, []fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthArgs) (*types.Transaction, error)); ok { + return rf(opts, premiumMultiplierWeiPerEthArgs) + } + if rf, ok := ret.Get(0).(func(*bind.TransactOpts, []fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthArgs) *types.Transaction); ok { + r0 = rf(opts, premiumMultiplierWeiPerEthArgs) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.Transaction) + } + } + + if rf, ok := ret.Get(1).(func(*bind.TransactOpts, []fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthArgs) error); ok { + r1 = rf(opts, premiumMultiplierWeiPerEthArgs) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_ApplyPremiumMultiplierWeiPerEthUpdates_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ApplyPremiumMultiplierWeiPerEthUpdates' +type FeeQuoterInterface_ApplyPremiumMultiplierWeiPerEthUpdates_Call struct { + *mock.Call +} + +// ApplyPremiumMultiplierWeiPerEthUpdates is a helper method to define mock.On call +// - opts *bind.TransactOpts +// - premiumMultiplierWeiPerEthArgs []fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthArgs +func (_e *FeeQuoterInterface_Expecter) ApplyPremiumMultiplierWeiPerEthUpdates(opts interface{}, premiumMultiplierWeiPerEthArgs interface{}) *FeeQuoterInterface_ApplyPremiumMultiplierWeiPerEthUpdates_Call { + return &FeeQuoterInterface_ApplyPremiumMultiplierWeiPerEthUpdates_Call{Call: _e.mock.On("ApplyPremiumMultiplierWeiPerEthUpdates", opts, premiumMultiplierWeiPerEthArgs)} +} + +func (_c *FeeQuoterInterface_ApplyPremiumMultiplierWeiPerEthUpdates_Call) Run(run func(opts *bind.TransactOpts, premiumMultiplierWeiPerEthArgs []fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthArgs)) *FeeQuoterInterface_ApplyPremiumMultiplierWeiPerEthUpdates_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.TransactOpts), args[1].([]fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthArgs)) + }) + return _c +} + +func (_c *FeeQuoterInterface_ApplyPremiumMultiplierWeiPerEthUpdates_Call) Return(_a0 *types.Transaction, _a1 error) *FeeQuoterInterface_ApplyPremiumMultiplierWeiPerEthUpdates_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_ApplyPremiumMultiplierWeiPerEthUpdates_Call) RunAndReturn(run func(*bind.TransactOpts, []fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthArgs) (*types.Transaction, error)) *FeeQuoterInterface_ApplyPremiumMultiplierWeiPerEthUpdates_Call { + _c.Call.Return(run) + return _c +} + +// ApplyTokenTransferFeeConfigUpdates provides a mock function with given fields: opts, tokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs +func (_m *FeeQuoterInterface) ApplyTokenTransferFeeConfigUpdates(opts *bind.TransactOpts, tokenTransferFeeConfigArgs []fee_quoter.FeeQuoterTokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs []fee_quoter.FeeQuoterTokenTransferFeeConfigRemoveArgs) (*types.Transaction, error) { + ret := _m.Called(opts, tokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs) + + if len(ret) == 0 { + panic("no return value specified for ApplyTokenTransferFeeConfigUpdates") + } + + var r0 *types.Transaction + var r1 error + if rf, ok := ret.Get(0).(func(*bind.TransactOpts, []fee_quoter.FeeQuoterTokenTransferFeeConfigArgs, []fee_quoter.FeeQuoterTokenTransferFeeConfigRemoveArgs) (*types.Transaction, error)); ok { + return rf(opts, tokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs) + } + if rf, ok := ret.Get(0).(func(*bind.TransactOpts, []fee_quoter.FeeQuoterTokenTransferFeeConfigArgs, []fee_quoter.FeeQuoterTokenTransferFeeConfigRemoveArgs) *types.Transaction); ok { + r0 = rf(opts, tokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.Transaction) + } + } + + if rf, ok := ret.Get(1).(func(*bind.TransactOpts, []fee_quoter.FeeQuoterTokenTransferFeeConfigArgs, []fee_quoter.FeeQuoterTokenTransferFeeConfigRemoveArgs) error); ok { + r1 = rf(opts, tokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_ApplyTokenTransferFeeConfigUpdates_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ApplyTokenTransferFeeConfigUpdates' +type FeeQuoterInterface_ApplyTokenTransferFeeConfigUpdates_Call struct { + *mock.Call +} + +// ApplyTokenTransferFeeConfigUpdates is a helper method to define mock.On call +// - opts *bind.TransactOpts +// - tokenTransferFeeConfigArgs []fee_quoter.FeeQuoterTokenTransferFeeConfigArgs +// - tokensToUseDefaultFeeConfigs []fee_quoter.FeeQuoterTokenTransferFeeConfigRemoveArgs +func (_e *FeeQuoterInterface_Expecter) ApplyTokenTransferFeeConfigUpdates(opts interface{}, tokenTransferFeeConfigArgs interface{}, tokensToUseDefaultFeeConfigs interface{}) *FeeQuoterInterface_ApplyTokenTransferFeeConfigUpdates_Call { + return &FeeQuoterInterface_ApplyTokenTransferFeeConfigUpdates_Call{Call: _e.mock.On("ApplyTokenTransferFeeConfigUpdates", opts, tokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs)} +} + +func (_c *FeeQuoterInterface_ApplyTokenTransferFeeConfigUpdates_Call) Run(run func(opts *bind.TransactOpts, tokenTransferFeeConfigArgs []fee_quoter.FeeQuoterTokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs []fee_quoter.FeeQuoterTokenTransferFeeConfigRemoveArgs)) *FeeQuoterInterface_ApplyTokenTransferFeeConfigUpdates_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.TransactOpts), args[1].([]fee_quoter.FeeQuoterTokenTransferFeeConfigArgs), args[2].([]fee_quoter.FeeQuoterTokenTransferFeeConfigRemoveArgs)) + }) + return _c +} + +func (_c *FeeQuoterInterface_ApplyTokenTransferFeeConfigUpdates_Call) Return(_a0 *types.Transaction, _a1 error) *FeeQuoterInterface_ApplyTokenTransferFeeConfigUpdates_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_ApplyTokenTransferFeeConfigUpdates_Call) RunAndReturn(run func(*bind.TransactOpts, []fee_quoter.FeeQuoterTokenTransferFeeConfigArgs, []fee_quoter.FeeQuoterTokenTransferFeeConfigRemoveArgs) (*types.Transaction, error)) *FeeQuoterInterface_ApplyTokenTransferFeeConfigUpdates_Call { + _c.Call.Return(run) + return _c +} + +// ConvertTokenAmount provides a mock function with given fields: opts, fromToken, fromTokenAmount, toToken +func (_m *FeeQuoterInterface) ConvertTokenAmount(opts *bind.CallOpts, fromToken common.Address, fromTokenAmount *big.Int, toToken common.Address) (*big.Int, error) { + ret := _m.Called(opts, fromToken, fromTokenAmount, toToken) + + if len(ret) == 0 { + panic("no return value specified for ConvertTokenAmount") + } + + var r0 *big.Int + var r1 error + if rf, ok := ret.Get(0).(func(*bind.CallOpts, common.Address, *big.Int, common.Address) (*big.Int, error)); ok { + return rf(opts, fromToken, fromTokenAmount, toToken) + } + if rf, ok := ret.Get(0).(func(*bind.CallOpts, common.Address, *big.Int, common.Address) *big.Int); ok { + r0 = rf(opts, fromToken, fromTokenAmount, toToken) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*big.Int) + } + } + + if rf, ok := ret.Get(1).(func(*bind.CallOpts, common.Address, *big.Int, common.Address) error); ok { + r1 = rf(opts, fromToken, fromTokenAmount, toToken) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_ConvertTokenAmount_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ConvertTokenAmount' +type FeeQuoterInterface_ConvertTokenAmount_Call struct { + *mock.Call +} + +// ConvertTokenAmount is a helper method to define mock.On call +// - opts *bind.CallOpts +// - fromToken common.Address +// - fromTokenAmount *big.Int +// - toToken common.Address +func (_e *FeeQuoterInterface_Expecter) ConvertTokenAmount(opts interface{}, fromToken interface{}, fromTokenAmount interface{}, toToken interface{}) *FeeQuoterInterface_ConvertTokenAmount_Call { + return &FeeQuoterInterface_ConvertTokenAmount_Call{Call: _e.mock.On("ConvertTokenAmount", opts, fromToken, fromTokenAmount, toToken)} +} + +func (_c *FeeQuoterInterface_ConvertTokenAmount_Call) Run(run func(opts *bind.CallOpts, fromToken common.Address, fromTokenAmount *big.Int, toToken common.Address)) *FeeQuoterInterface_ConvertTokenAmount_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.CallOpts), args[1].(common.Address), args[2].(*big.Int), args[3].(common.Address)) + }) + return _c +} + +func (_c *FeeQuoterInterface_ConvertTokenAmount_Call) Return(_a0 *big.Int, _a1 error) *FeeQuoterInterface_ConvertTokenAmount_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_ConvertTokenAmount_Call) RunAndReturn(run func(*bind.CallOpts, common.Address, *big.Int, common.Address) (*big.Int, error)) *FeeQuoterInterface_ConvertTokenAmount_Call { + _c.Call.Return(run) + return _c +} + +// FilterAuthorizedCallerAdded provides a mock function with given fields: opts +func (_m *FeeQuoterInterface) FilterAuthorizedCallerAdded(opts *bind.FilterOpts) (*fee_quoter.FeeQuoterAuthorizedCallerAddedIterator, error) { + ret := _m.Called(opts) + + if len(ret) == 0 { + panic("no return value specified for FilterAuthorizedCallerAdded") + } + + var r0 *fee_quoter.FeeQuoterAuthorizedCallerAddedIterator + var r1 error + if rf, ok := ret.Get(0).(func(*bind.FilterOpts) (*fee_quoter.FeeQuoterAuthorizedCallerAddedIterator, error)); ok { + return rf(opts) + } + if rf, ok := ret.Get(0).(func(*bind.FilterOpts) *fee_quoter.FeeQuoterAuthorizedCallerAddedIterator); ok { + r0 = rf(opts) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*fee_quoter.FeeQuoterAuthorizedCallerAddedIterator) + } + } + + if rf, ok := ret.Get(1).(func(*bind.FilterOpts) error); ok { + r1 = rf(opts) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_FilterAuthorizedCallerAdded_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterAuthorizedCallerAdded' +type FeeQuoterInterface_FilterAuthorizedCallerAdded_Call struct { + *mock.Call +} + +// FilterAuthorizedCallerAdded is a helper method to define mock.On call +// - opts *bind.FilterOpts +func (_e *FeeQuoterInterface_Expecter) FilterAuthorizedCallerAdded(opts interface{}) *FeeQuoterInterface_FilterAuthorizedCallerAdded_Call { + return &FeeQuoterInterface_FilterAuthorizedCallerAdded_Call{Call: _e.mock.On("FilterAuthorizedCallerAdded", opts)} +} + +func (_c *FeeQuoterInterface_FilterAuthorizedCallerAdded_Call) Run(run func(opts *bind.FilterOpts)) *FeeQuoterInterface_FilterAuthorizedCallerAdded_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.FilterOpts)) + }) + return _c +} + +func (_c *FeeQuoterInterface_FilterAuthorizedCallerAdded_Call) Return(_a0 *fee_quoter.FeeQuoterAuthorizedCallerAddedIterator, _a1 error) *FeeQuoterInterface_FilterAuthorizedCallerAdded_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_FilterAuthorizedCallerAdded_Call) RunAndReturn(run func(*bind.FilterOpts) (*fee_quoter.FeeQuoterAuthorizedCallerAddedIterator, error)) *FeeQuoterInterface_FilterAuthorizedCallerAdded_Call { + _c.Call.Return(run) + return _c +} + +// FilterAuthorizedCallerRemoved provides a mock function with given fields: opts +func (_m *FeeQuoterInterface) FilterAuthorizedCallerRemoved(opts *bind.FilterOpts) (*fee_quoter.FeeQuoterAuthorizedCallerRemovedIterator, error) { + ret := _m.Called(opts) + + if len(ret) == 0 { + panic("no return value specified for FilterAuthorizedCallerRemoved") + } + + var r0 *fee_quoter.FeeQuoterAuthorizedCallerRemovedIterator + var r1 error + if rf, ok := ret.Get(0).(func(*bind.FilterOpts) (*fee_quoter.FeeQuoterAuthorizedCallerRemovedIterator, error)); ok { + return rf(opts) + } + if rf, ok := ret.Get(0).(func(*bind.FilterOpts) *fee_quoter.FeeQuoterAuthorizedCallerRemovedIterator); ok { + r0 = rf(opts) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*fee_quoter.FeeQuoterAuthorizedCallerRemovedIterator) + } + } + + if rf, ok := ret.Get(1).(func(*bind.FilterOpts) error); ok { + r1 = rf(opts) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_FilterAuthorizedCallerRemoved_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterAuthorizedCallerRemoved' +type FeeQuoterInterface_FilterAuthorizedCallerRemoved_Call struct { + *mock.Call +} + +// FilterAuthorizedCallerRemoved is a helper method to define mock.On call +// - opts *bind.FilterOpts +func (_e *FeeQuoterInterface_Expecter) FilterAuthorizedCallerRemoved(opts interface{}) *FeeQuoterInterface_FilterAuthorizedCallerRemoved_Call { + return &FeeQuoterInterface_FilterAuthorizedCallerRemoved_Call{Call: _e.mock.On("FilterAuthorizedCallerRemoved", opts)} +} + +func (_c *FeeQuoterInterface_FilterAuthorizedCallerRemoved_Call) Run(run func(opts *bind.FilterOpts)) *FeeQuoterInterface_FilterAuthorizedCallerRemoved_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.FilterOpts)) + }) + return _c +} + +func (_c *FeeQuoterInterface_FilterAuthorizedCallerRemoved_Call) Return(_a0 *fee_quoter.FeeQuoterAuthorizedCallerRemovedIterator, _a1 error) *FeeQuoterInterface_FilterAuthorizedCallerRemoved_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_FilterAuthorizedCallerRemoved_Call) RunAndReturn(run func(*bind.FilterOpts) (*fee_quoter.FeeQuoterAuthorizedCallerRemovedIterator, error)) *FeeQuoterInterface_FilterAuthorizedCallerRemoved_Call { + _c.Call.Return(run) + return _c +} + +// FilterDestChainAdded provides a mock function with given fields: opts, destChainSelector +func (_m *FeeQuoterInterface) FilterDestChainAdded(opts *bind.FilterOpts, destChainSelector []uint64) (*fee_quoter.FeeQuoterDestChainAddedIterator, error) { + ret := _m.Called(opts, destChainSelector) + + if len(ret) == 0 { + panic("no return value specified for FilterDestChainAdded") + } + + var r0 *fee_quoter.FeeQuoterDestChainAddedIterator + var r1 error + if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []uint64) (*fee_quoter.FeeQuoterDestChainAddedIterator, error)); ok { + return rf(opts, destChainSelector) + } + if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []uint64) *fee_quoter.FeeQuoterDestChainAddedIterator); ok { + r0 = rf(opts, destChainSelector) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*fee_quoter.FeeQuoterDestChainAddedIterator) + } + } + + if rf, ok := ret.Get(1).(func(*bind.FilterOpts, []uint64) error); ok { + r1 = rf(opts, destChainSelector) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_FilterDestChainAdded_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterDestChainAdded' +type FeeQuoterInterface_FilterDestChainAdded_Call struct { + *mock.Call +} + +// FilterDestChainAdded is a helper method to define mock.On call +// - opts *bind.FilterOpts +// - destChainSelector []uint64 +func (_e *FeeQuoterInterface_Expecter) FilterDestChainAdded(opts interface{}, destChainSelector interface{}) *FeeQuoterInterface_FilterDestChainAdded_Call { + return &FeeQuoterInterface_FilterDestChainAdded_Call{Call: _e.mock.On("FilterDestChainAdded", opts, destChainSelector)} +} + +func (_c *FeeQuoterInterface_FilterDestChainAdded_Call) Run(run func(opts *bind.FilterOpts, destChainSelector []uint64)) *FeeQuoterInterface_FilterDestChainAdded_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.FilterOpts), args[1].([]uint64)) + }) + return _c +} + +func (_c *FeeQuoterInterface_FilterDestChainAdded_Call) Return(_a0 *fee_quoter.FeeQuoterDestChainAddedIterator, _a1 error) *FeeQuoterInterface_FilterDestChainAdded_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_FilterDestChainAdded_Call) RunAndReturn(run func(*bind.FilterOpts, []uint64) (*fee_quoter.FeeQuoterDestChainAddedIterator, error)) *FeeQuoterInterface_FilterDestChainAdded_Call { + _c.Call.Return(run) + return _c +} + +// FilterDestChainConfigUpdated provides a mock function with given fields: opts, destChainSelector +func (_m *FeeQuoterInterface) FilterDestChainConfigUpdated(opts *bind.FilterOpts, destChainSelector []uint64) (*fee_quoter.FeeQuoterDestChainConfigUpdatedIterator, error) { + ret := _m.Called(opts, destChainSelector) + + if len(ret) == 0 { + panic("no return value specified for FilterDestChainConfigUpdated") + } + + var r0 *fee_quoter.FeeQuoterDestChainConfigUpdatedIterator + var r1 error + if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []uint64) (*fee_quoter.FeeQuoterDestChainConfigUpdatedIterator, error)); ok { + return rf(opts, destChainSelector) + } + if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []uint64) *fee_quoter.FeeQuoterDestChainConfigUpdatedIterator); ok { + r0 = rf(opts, destChainSelector) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*fee_quoter.FeeQuoterDestChainConfigUpdatedIterator) + } + } + + if rf, ok := ret.Get(1).(func(*bind.FilterOpts, []uint64) error); ok { + r1 = rf(opts, destChainSelector) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_FilterDestChainConfigUpdated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterDestChainConfigUpdated' +type FeeQuoterInterface_FilterDestChainConfigUpdated_Call struct { + *mock.Call +} + +// FilterDestChainConfigUpdated is a helper method to define mock.On call +// - opts *bind.FilterOpts +// - destChainSelector []uint64 +func (_e *FeeQuoterInterface_Expecter) FilterDestChainConfigUpdated(opts interface{}, destChainSelector interface{}) *FeeQuoterInterface_FilterDestChainConfigUpdated_Call { + return &FeeQuoterInterface_FilterDestChainConfigUpdated_Call{Call: _e.mock.On("FilterDestChainConfigUpdated", opts, destChainSelector)} +} + +func (_c *FeeQuoterInterface_FilterDestChainConfigUpdated_Call) Run(run func(opts *bind.FilterOpts, destChainSelector []uint64)) *FeeQuoterInterface_FilterDestChainConfigUpdated_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.FilterOpts), args[1].([]uint64)) + }) + return _c +} + +func (_c *FeeQuoterInterface_FilterDestChainConfigUpdated_Call) Return(_a0 *fee_quoter.FeeQuoterDestChainConfigUpdatedIterator, _a1 error) *FeeQuoterInterface_FilterDestChainConfigUpdated_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_FilterDestChainConfigUpdated_Call) RunAndReturn(run func(*bind.FilterOpts, []uint64) (*fee_quoter.FeeQuoterDestChainConfigUpdatedIterator, error)) *FeeQuoterInterface_FilterDestChainConfigUpdated_Call { + _c.Call.Return(run) + return _c +} + +// FilterFeeTokenAdded provides a mock function with given fields: opts, feeToken +func (_m *FeeQuoterInterface) FilterFeeTokenAdded(opts *bind.FilterOpts, feeToken []common.Address) (*fee_quoter.FeeQuoterFeeTokenAddedIterator, error) { + ret := _m.Called(opts, feeToken) + + if len(ret) == 0 { + panic("no return value specified for FilterFeeTokenAdded") + } + + var r0 *fee_quoter.FeeQuoterFeeTokenAddedIterator + var r1 error + if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []common.Address) (*fee_quoter.FeeQuoterFeeTokenAddedIterator, error)); ok { + return rf(opts, feeToken) + } + if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []common.Address) *fee_quoter.FeeQuoterFeeTokenAddedIterator); ok { + r0 = rf(opts, feeToken) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*fee_quoter.FeeQuoterFeeTokenAddedIterator) + } + } + + if rf, ok := ret.Get(1).(func(*bind.FilterOpts, []common.Address) error); ok { + r1 = rf(opts, feeToken) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_FilterFeeTokenAdded_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterFeeTokenAdded' +type FeeQuoterInterface_FilterFeeTokenAdded_Call struct { + *mock.Call +} + +// FilterFeeTokenAdded is a helper method to define mock.On call +// - opts *bind.FilterOpts +// - feeToken []common.Address +func (_e *FeeQuoterInterface_Expecter) FilterFeeTokenAdded(opts interface{}, feeToken interface{}) *FeeQuoterInterface_FilterFeeTokenAdded_Call { + return &FeeQuoterInterface_FilterFeeTokenAdded_Call{Call: _e.mock.On("FilterFeeTokenAdded", opts, feeToken)} +} + +func (_c *FeeQuoterInterface_FilterFeeTokenAdded_Call) Run(run func(opts *bind.FilterOpts, feeToken []common.Address)) *FeeQuoterInterface_FilterFeeTokenAdded_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.FilterOpts), args[1].([]common.Address)) + }) + return _c +} + +func (_c *FeeQuoterInterface_FilterFeeTokenAdded_Call) Return(_a0 *fee_quoter.FeeQuoterFeeTokenAddedIterator, _a1 error) *FeeQuoterInterface_FilterFeeTokenAdded_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_FilterFeeTokenAdded_Call) RunAndReturn(run func(*bind.FilterOpts, []common.Address) (*fee_quoter.FeeQuoterFeeTokenAddedIterator, error)) *FeeQuoterInterface_FilterFeeTokenAdded_Call { + _c.Call.Return(run) + return _c +} + +// FilterFeeTokenRemoved provides a mock function with given fields: opts, feeToken +func (_m *FeeQuoterInterface) FilterFeeTokenRemoved(opts *bind.FilterOpts, feeToken []common.Address) (*fee_quoter.FeeQuoterFeeTokenRemovedIterator, error) { + ret := _m.Called(opts, feeToken) + + if len(ret) == 0 { + panic("no return value specified for FilterFeeTokenRemoved") + } + + var r0 *fee_quoter.FeeQuoterFeeTokenRemovedIterator + var r1 error + if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []common.Address) (*fee_quoter.FeeQuoterFeeTokenRemovedIterator, error)); ok { + return rf(opts, feeToken) + } + if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []common.Address) *fee_quoter.FeeQuoterFeeTokenRemovedIterator); ok { + r0 = rf(opts, feeToken) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*fee_quoter.FeeQuoterFeeTokenRemovedIterator) + } + } + + if rf, ok := ret.Get(1).(func(*bind.FilterOpts, []common.Address) error); ok { + r1 = rf(opts, feeToken) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_FilterFeeTokenRemoved_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterFeeTokenRemoved' +type FeeQuoterInterface_FilterFeeTokenRemoved_Call struct { + *mock.Call +} + +// FilterFeeTokenRemoved is a helper method to define mock.On call +// - opts *bind.FilterOpts +// - feeToken []common.Address +func (_e *FeeQuoterInterface_Expecter) FilterFeeTokenRemoved(opts interface{}, feeToken interface{}) *FeeQuoterInterface_FilterFeeTokenRemoved_Call { + return &FeeQuoterInterface_FilterFeeTokenRemoved_Call{Call: _e.mock.On("FilterFeeTokenRemoved", opts, feeToken)} +} + +func (_c *FeeQuoterInterface_FilterFeeTokenRemoved_Call) Run(run func(opts *bind.FilterOpts, feeToken []common.Address)) *FeeQuoterInterface_FilterFeeTokenRemoved_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.FilterOpts), args[1].([]common.Address)) + }) + return _c +} + +func (_c *FeeQuoterInterface_FilterFeeTokenRemoved_Call) Return(_a0 *fee_quoter.FeeQuoterFeeTokenRemovedIterator, _a1 error) *FeeQuoterInterface_FilterFeeTokenRemoved_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_FilterFeeTokenRemoved_Call) RunAndReturn(run func(*bind.FilterOpts, []common.Address) (*fee_quoter.FeeQuoterFeeTokenRemovedIterator, error)) *FeeQuoterInterface_FilterFeeTokenRemoved_Call { + _c.Call.Return(run) + return _c +} + +// FilterOwnershipTransferRequested provides a mock function with given fields: opts, from, to +func (_m *FeeQuoterInterface) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*fee_quoter.FeeQuoterOwnershipTransferRequestedIterator, error) { + ret := _m.Called(opts, from, to) + + if len(ret) == 0 { + panic("no return value specified for FilterOwnershipTransferRequested") + } + + var r0 *fee_quoter.FeeQuoterOwnershipTransferRequestedIterator + var r1 error + if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []common.Address, []common.Address) (*fee_quoter.FeeQuoterOwnershipTransferRequestedIterator, error)); ok { + return rf(opts, from, to) + } + if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []common.Address, []common.Address) *fee_quoter.FeeQuoterOwnershipTransferRequestedIterator); ok { + r0 = rf(opts, from, to) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*fee_quoter.FeeQuoterOwnershipTransferRequestedIterator) + } + } + + if rf, ok := ret.Get(1).(func(*bind.FilterOpts, []common.Address, []common.Address) error); ok { + r1 = rf(opts, from, to) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_FilterOwnershipTransferRequested_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterOwnershipTransferRequested' +type FeeQuoterInterface_FilterOwnershipTransferRequested_Call struct { + *mock.Call +} + +// FilterOwnershipTransferRequested is a helper method to define mock.On call +// - opts *bind.FilterOpts +// - from []common.Address +// - to []common.Address +func (_e *FeeQuoterInterface_Expecter) FilterOwnershipTransferRequested(opts interface{}, from interface{}, to interface{}) *FeeQuoterInterface_FilterOwnershipTransferRequested_Call { + return &FeeQuoterInterface_FilterOwnershipTransferRequested_Call{Call: _e.mock.On("FilterOwnershipTransferRequested", opts, from, to)} +} + +func (_c *FeeQuoterInterface_FilterOwnershipTransferRequested_Call) Run(run func(opts *bind.FilterOpts, from []common.Address, to []common.Address)) *FeeQuoterInterface_FilterOwnershipTransferRequested_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.FilterOpts), args[1].([]common.Address), args[2].([]common.Address)) + }) + return _c +} + +func (_c *FeeQuoterInterface_FilterOwnershipTransferRequested_Call) Return(_a0 *fee_quoter.FeeQuoterOwnershipTransferRequestedIterator, _a1 error) *FeeQuoterInterface_FilterOwnershipTransferRequested_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_FilterOwnershipTransferRequested_Call) RunAndReturn(run func(*bind.FilterOpts, []common.Address, []common.Address) (*fee_quoter.FeeQuoterOwnershipTransferRequestedIterator, error)) *FeeQuoterInterface_FilterOwnershipTransferRequested_Call { + _c.Call.Return(run) + return _c +} + +// FilterOwnershipTransferred provides a mock function with given fields: opts, from, to +func (_m *FeeQuoterInterface) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*fee_quoter.FeeQuoterOwnershipTransferredIterator, error) { + ret := _m.Called(opts, from, to) + + if len(ret) == 0 { + panic("no return value specified for FilterOwnershipTransferred") + } + + var r0 *fee_quoter.FeeQuoterOwnershipTransferredIterator + var r1 error + if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []common.Address, []common.Address) (*fee_quoter.FeeQuoterOwnershipTransferredIterator, error)); ok { + return rf(opts, from, to) + } + if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []common.Address, []common.Address) *fee_quoter.FeeQuoterOwnershipTransferredIterator); ok { + r0 = rf(opts, from, to) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*fee_quoter.FeeQuoterOwnershipTransferredIterator) + } + } + + if rf, ok := ret.Get(1).(func(*bind.FilterOpts, []common.Address, []common.Address) error); ok { + r1 = rf(opts, from, to) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_FilterOwnershipTransferred_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterOwnershipTransferred' +type FeeQuoterInterface_FilterOwnershipTransferred_Call struct { + *mock.Call +} + +// FilterOwnershipTransferred is a helper method to define mock.On call +// - opts *bind.FilterOpts +// - from []common.Address +// - to []common.Address +func (_e *FeeQuoterInterface_Expecter) FilterOwnershipTransferred(opts interface{}, from interface{}, to interface{}) *FeeQuoterInterface_FilterOwnershipTransferred_Call { + return &FeeQuoterInterface_FilterOwnershipTransferred_Call{Call: _e.mock.On("FilterOwnershipTransferred", opts, from, to)} +} + +func (_c *FeeQuoterInterface_FilterOwnershipTransferred_Call) Run(run func(opts *bind.FilterOpts, from []common.Address, to []common.Address)) *FeeQuoterInterface_FilterOwnershipTransferred_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.FilterOpts), args[1].([]common.Address), args[2].([]common.Address)) + }) + return _c +} + +func (_c *FeeQuoterInterface_FilterOwnershipTransferred_Call) Return(_a0 *fee_quoter.FeeQuoterOwnershipTransferredIterator, _a1 error) *FeeQuoterInterface_FilterOwnershipTransferred_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_FilterOwnershipTransferred_Call) RunAndReturn(run func(*bind.FilterOpts, []common.Address, []common.Address) (*fee_quoter.FeeQuoterOwnershipTransferredIterator, error)) *FeeQuoterInterface_FilterOwnershipTransferred_Call { + _c.Call.Return(run) + return _c +} + +// FilterPremiumMultiplierWeiPerEthUpdated provides a mock function with given fields: opts, token +func (_m *FeeQuoterInterface) FilterPremiumMultiplierWeiPerEthUpdated(opts *bind.FilterOpts, token []common.Address) (*fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthUpdatedIterator, error) { + ret := _m.Called(opts, token) + + if len(ret) == 0 { + panic("no return value specified for FilterPremiumMultiplierWeiPerEthUpdated") + } + + var r0 *fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthUpdatedIterator + var r1 error + if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []common.Address) (*fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthUpdatedIterator, error)); ok { + return rf(opts, token) + } + if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []common.Address) *fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthUpdatedIterator); ok { + r0 = rf(opts, token) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthUpdatedIterator) + } + } + + if rf, ok := ret.Get(1).(func(*bind.FilterOpts, []common.Address) error); ok { + r1 = rf(opts, token) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_FilterPremiumMultiplierWeiPerEthUpdated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterPremiumMultiplierWeiPerEthUpdated' +type FeeQuoterInterface_FilterPremiumMultiplierWeiPerEthUpdated_Call struct { + *mock.Call +} + +// FilterPremiumMultiplierWeiPerEthUpdated is a helper method to define mock.On call +// - opts *bind.FilterOpts +// - token []common.Address +func (_e *FeeQuoterInterface_Expecter) FilterPremiumMultiplierWeiPerEthUpdated(opts interface{}, token interface{}) *FeeQuoterInterface_FilterPremiumMultiplierWeiPerEthUpdated_Call { + return &FeeQuoterInterface_FilterPremiumMultiplierWeiPerEthUpdated_Call{Call: _e.mock.On("FilterPremiumMultiplierWeiPerEthUpdated", opts, token)} +} + +func (_c *FeeQuoterInterface_FilterPremiumMultiplierWeiPerEthUpdated_Call) Run(run func(opts *bind.FilterOpts, token []common.Address)) *FeeQuoterInterface_FilterPremiumMultiplierWeiPerEthUpdated_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.FilterOpts), args[1].([]common.Address)) + }) + return _c +} + +func (_c *FeeQuoterInterface_FilterPremiumMultiplierWeiPerEthUpdated_Call) Return(_a0 *fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthUpdatedIterator, _a1 error) *FeeQuoterInterface_FilterPremiumMultiplierWeiPerEthUpdated_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_FilterPremiumMultiplierWeiPerEthUpdated_Call) RunAndReturn(run func(*bind.FilterOpts, []common.Address) (*fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthUpdatedIterator, error)) *FeeQuoterInterface_FilterPremiumMultiplierWeiPerEthUpdated_Call { + _c.Call.Return(run) + return _c +} + +// FilterPriceFeedPerTokenUpdated provides a mock function with given fields: opts, token +func (_m *FeeQuoterInterface) FilterPriceFeedPerTokenUpdated(opts *bind.FilterOpts, token []common.Address) (*fee_quoter.FeeQuoterPriceFeedPerTokenUpdatedIterator, error) { + ret := _m.Called(opts, token) + + if len(ret) == 0 { + panic("no return value specified for FilterPriceFeedPerTokenUpdated") + } + + var r0 *fee_quoter.FeeQuoterPriceFeedPerTokenUpdatedIterator + var r1 error + if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []common.Address) (*fee_quoter.FeeQuoterPriceFeedPerTokenUpdatedIterator, error)); ok { + return rf(opts, token) + } + if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []common.Address) *fee_quoter.FeeQuoterPriceFeedPerTokenUpdatedIterator); ok { + r0 = rf(opts, token) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*fee_quoter.FeeQuoterPriceFeedPerTokenUpdatedIterator) + } + } + + if rf, ok := ret.Get(1).(func(*bind.FilterOpts, []common.Address) error); ok { + r1 = rf(opts, token) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_FilterPriceFeedPerTokenUpdated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterPriceFeedPerTokenUpdated' +type FeeQuoterInterface_FilterPriceFeedPerTokenUpdated_Call struct { + *mock.Call +} + +// FilterPriceFeedPerTokenUpdated is a helper method to define mock.On call +// - opts *bind.FilterOpts +// - token []common.Address +func (_e *FeeQuoterInterface_Expecter) FilterPriceFeedPerTokenUpdated(opts interface{}, token interface{}) *FeeQuoterInterface_FilterPriceFeedPerTokenUpdated_Call { + return &FeeQuoterInterface_FilterPriceFeedPerTokenUpdated_Call{Call: _e.mock.On("FilterPriceFeedPerTokenUpdated", opts, token)} +} + +func (_c *FeeQuoterInterface_FilterPriceFeedPerTokenUpdated_Call) Run(run func(opts *bind.FilterOpts, token []common.Address)) *FeeQuoterInterface_FilterPriceFeedPerTokenUpdated_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.FilterOpts), args[1].([]common.Address)) + }) + return _c +} + +func (_c *FeeQuoterInterface_FilterPriceFeedPerTokenUpdated_Call) Return(_a0 *fee_quoter.FeeQuoterPriceFeedPerTokenUpdatedIterator, _a1 error) *FeeQuoterInterface_FilterPriceFeedPerTokenUpdated_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_FilterPriceFeedPerTokenUpdated_Call) RunAndReturn(run func(*bind.FilterOpts, []common.Address) (*fee_quoter.FeeQuoterPriceFeedPerTokenUpdatedIterator, error)) *FeeQuoterInterface_FilterPriceFeedPerTokenUpdated_Call { + _c.Call.Return(run) + return _c +} + +// FilterReportPermissionSet provides a mock function with given fields: opts, reportId +func (_m *FeeQuoterInterface) FilterReportPermissionSet(opts *bind.FilterOpts, reportId [][32]byte) (*fee_quoter.FeeQuoterReportPermissionSetIterator, error) { + ret := _m.Called(opts, reportId) + + if len(ret) == 0 { + panic("no return value specified for FilterReportPermissionSet") + } + + var r0 *fee_quoter.FeeQuoterReportPermissionSetIterator + var r1 error + if rf, ok := ret.Get(0).(func(*bind.FilterOpts, [][32]byte) (*fee_quoter.FeeQuoterReportPermissionSetIterator, error)); ok { + return rf(opts, reportId) + } + if rf, ok := ret.Get(0).(func(*bind.FilterOpts, [][32]byte) *fee_quoter.FeeQuoterReportPermissionSetIterator); ok { + r0 = rf(opts, reportId) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*fee_quoter.FeeQuoterReportPermissionSetIterator) + } + } + + if rf, ok := ret.Get(1).(func(*bind.FilterOpts, [][32]byte) error); ok { + r1 = rf(opts, reportId) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_FilterReportPermissionSet_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterReportPermissionSet' +type FeeQuoterInterface_FilterReportPermissionSet_Call struct { + *mock.Call +} + +// FilterReportPermissionSet is a helper method to define mock.On call +// - opts *bind.FilterOpts +// - reportId [][32]byte +func (_e *FeeQuoterInterface_Expecter) FilterReportPermissionSet(opts interface{}, reportId interface{}) *FeeQuoterInterface_FilterReportPermissionSet_Call { + return &FeeQuoterInterface_FilterReportPermissionSet_Call{Call: _e.mock.On("FilterReportPermissionSet", opts, reportId)} +} + +func (_c *FeeQuoterInterface_FilterReportPermissionSet_Call) Run(run func(opts *bind.FilterOpts, reportId [][32]byte)) *FeeQuoterInterface_FilterReportPermissionSet_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.FilterOpts), args[1].([][32]byte)) + }) + return _c +} + +func (_c *FeeQuoterInterface_FilterReportPermissionSet_Call) Return(_a0 *fee_quoter.FeeQuoterReportPermissionSetIterator, _a1 error) *FeeQuoterInterface_FilterReportPermissionSet_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_FilterReportPermissionSet_Call) RunAndReturn(run func(*bind.FilterOpts, [][32]byte) (*fee_quoter.FeeQuoterReportPermissionSetIterator, error)) *FeeQuoterInterface_FilterReportPermissionSet_Call { + _c.Call.Return(run) + return _c +} + +// FilterTokenTransferFeeConfigDeleted provides a mock function with given fields: opts, destChainSelector, token +func (_m *FeeQuoterInterface) FilterTokenTransferFeeConfigDeleted(opts *bind.FilterOpts, destChainSelector []uint64, token []common.Address) (*fee_quoter.FeeQuoterTokenTransferFeeConfigDeletedIterator, error) { + ret := _m.Called(opts, destChainSelector, token) + + if len(ret) == 0 { + panic("no return value specified for FilterTokenTransferFeeConfigDeleted") + } + + var r0 *fee_quoter.FeeQuoterTokenTransferFeeConfigDeletedIterator + var r1 error + if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []uint64, []common.Address) (*fee_quoter.FeeQuoterTokenTransferFeeConfigDeletedIterator, error)); ok { + return rf(opts, destChainSelector, token) + } + if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []uint64, []common.Address) *fee_quoter.FeeQuoterTokenTransferFeeConfigDeletedIterator); ok { + r0 = rf(opts, destChainSelector, token) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*fee_quoter.FeeQuoterTokenTransferFeeConfigDeletedIterator) + } + } + + if rf, ok := ret.Get(1).(func(*bind.FilterOpts, []uint64, []common.Address) error); ok { + r1 = rf(opts, destChainSelector, token) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_FilterTokenTransferFeeConfigDeleted_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterTokenTransferFeeConfigDeleted' +type FeeQuoterInterface_FilterTokenTransferFeeConfigDeleted_Call struct { + *mock.Call +} + +// FilterTokenTransferFeeConfigDeleted is a helper method to define mock.On call +// - opts *bind.FilterOpts +// - destChainSelector []uint64 +// - token []common.Address +func (_e *FeeQuoterInterface_Expecter) FilterTokenTransferFeeConfigDeleted(opts interface{}, destChainSelector interface{}, token interface{}) *FeeQuoterInterface_FilterTokenTransferFeeConfigDeleted_Call { + return &FeeQuoterInterface_FilterTokenTransferFeeConfigDeleted_Call{Call: _e.mock.On("FilterTokenTransferFeeConfigDeleted", opts, destChainSelector, token)} +} + +func (_c *FeeQuoterInterface_FilterTokenTransferFeeConfigDeleted_Call) Run(run func(opts *bind.FilterOpts, destChainSelector []uint64, token []common.Address)) *FeeQuoterInterface_FilterTokenTransferFeeConfigDeleted_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.FilterOpts), args[1].([]uint64), args[2].([]common.Address)) + }) + return _c +} + +func (_c *FeeQuoterInterface_FilterTokenTransferFeeConfigDeleted_Call) Return(_a0 *fee_quoter.FeeQuoterTokenTransferFeeConfigDeletedIterator, _a1 error) *FeeQuoterInterface_FilterTokenTransferFeeConfigDeleted_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_FilterTokenTransferFeeConfigDeleted_Call) RunAndReturn(run func(*bind.FilterOpts, []uint64, []common.Address) (*fee_quoter.FeeQuoterTokenTransferFeeConfigDeletedIterator, error)) *FeeQuoterInterface_FilterTokenTransferFeeConfigDeleted_Call { + _c.Call.Return(run) + return _c +} + +// FilterTokenTransferFeeConfigUpdated provides a mock function with given fields: opts, destChainSelector, token +func (_m *FeeQuoterInterface) FilterTokenTransferFeeConfigUpdated(opts *bind.FilterOpts, destChainSelector []uint64, token []common.Address) (*fee_quoter.FeeQuoterTokenTransferFeeConfigUpdatedIterator, error) { + ret := _m.Called(opts, destChainSelector, token) + + if len(ret) == 0 { + panic("no return value specified for FilterTokenTransferFeeConfigUpdated") + } + + var r0 *fee_quoter.FeeQuoterTokenTransferFeeConfigUpdatedIterator + var r1 error + if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []uint64, []common.Address) (*fee_quoter.FeeQuoterTokenTransferFeeConfigUpdatedIterator, error)); ok { + return rf(opts, destChainSelector, token) + } + if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []uint64, []common.Address) *fee_quoter.FeeQuoterTokenTransferFeeConfigUpdatedIterator); ok { + r0 = rf(opts, destChainSelector, token) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*fee_quoter.FeeQuoterTokenTransferFeeConfigUpdatedIterator) + } + } + + if rf, ok := ret.Get(1).(func(*bind.FilterOpts, []uint64, []common.Address) error); ok { + r1 = rf(opts, destChainSelector, token) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_FilterTokenTransferFeeConfigUpdated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterTokenTransferFeeConfigUpdated' +type FeeQuoterInterface_FilterTokenTransferFeeConfigUpdated_Call struct { + *mock.Call +} + +// FilterTokenTransferFeeConfigUpdated is a helper method to define mock.On call +// - opts *bind.FilterOpts +// - destChainSelector []uint64 +// - token []common.Address +func (_e *FeeQuoterInterface_Expecter) FilterTokenTransferFeeConfigUpdated(opts interface{}, destChainSelector interface{}, token interface{}) *FeeQuoterInterface_FilterTokenTransferFeeConfigUpdated_Call { + return &FeeQuoterInterface_FilterTokenTransferFeeConfigUpdated_Call{Call: _e.mock.On("FilterTokenTransferFeeConfigUpdated", opts, destChainSelector, token)} +} + +func (_c *FeeQuoterInterface_FilterTokenTransferFeeConfigUpdated_Call) Run(run func(opts *bind.FilterOpts, destChainSelector []uint64, token []common.Address)) *FeeQuoterInterface_FilterTokenTransferFeeConfigUpdated_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.FilterOpts), args[1].([]uint64), args[2].([]common.Address)) + }) + return _c +} + +func (_c *FeeQuoterInterface_FilterTokenTransferFeeConfigUpdated_Call) Return(_a0 *fee_quoter.FeeQuoterTokenTransferFeeConfigUpdatedIterator, _a1 error) *FeeQuoterInterface_FilterTokenTransferFeeConfigUpdated_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_FilterTokenTransferFeeConfigUpdated_Call) RunAndReturn(run func(*bind.FilterOpts, []uint64, []common.Address) (*fee_quoter.FeeQuoterTokenTransferFeeConfigUpdatedIterator, error)) *FeeQuoterInterface_FilterTokenTransferFeeConfigUpdated_Call { + _c.Call.Return(run) + return _c +} + +// FilterUsdPerTokenUpdated provides a mock function with given fields: opts, token +func (_m *FeeQuoterInterface) FilterUsdPerTokenUpdated(opts *bind.FilterOpts, token []common.Address) (*fee_quoter.FeeQuoterUsdPerTokenUpdatedIterator, error) { + ret := _m.Called(opts, token) + + if len(ret) == 0 { + panic("no return value specified for FilterUsdPerTokenUpdated") + } + + var r0 *fee_quoter.FeeQuoterUsdPerTokenUpdatedIterator + var r1 error + if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []common.Address) (*fee_quoter.FeeQuoterUsdPerTokenUpdatedIterator, error)); ok { + return rf(opts, token) + } + if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []common.Address) *fee_quoter.FeeQuoterUsdPerTokenUpdatedIterator); ok { + r0 = rf(opts, token) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*fee_quoter.FeeQuoterUsdPerTokenUpdatedIterator) + } + } + + if rf, ok := ret.Get(1).(func(*bind.FilterOpts, []common.Address) error); ok { + r1 = rf(opts, token) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_FilterUsdPerTokenUpdated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterUsdPerTokenUpdated' +type FeeQuoterInterface_FilterUsdPerTokenUpdated_Call struct { + *mock.Call +} + +// FilterUsdPerTokenUpdated is a helper method to define mock.On call +// - opts *bind.FilterOpts +// - token []common.Address +func (_e *FeeQuoterInterface_Expecter) FilterUsdPerTokenUpdated(opts interface{}, token interface{}) *FeeQuoterInterface_FilterUsdPerTokenUpdated_Call { + return &FeeQuoterInterface_FilterUsdPerTokenUpdated_Call{Call: _e.mock.On("FilterUsdPerTokenUpdated", opts, token)} +} + +func (_c *FeeQuoterInterface_FilterUsdPerTokenUpdated_Call) Run(run func(opts *bind.FilterOpts, token []common.Address)) *FeeQuoterInterface_FilterUsdPerTokenUpdated_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.FilterOpts), args[1].([]common.Address)) + }) + return _c +} + +func (_c *FeeQuoterInterface_FilterUsdPerTokenUpdated_Call) Return(_a0 *fee_quoter.FeeQuoterUsdPerTokenUpdatedIterator, _a1 error) *FeeQuoterInterface_FilterUsdPerTokenUpdated_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_FilterUsdPerTokenUpdated_Call) RunAndReturn(run func(*bind.FilterOpts, []common.Address) (*fee_quoter.FeeQuoterUsdPerTokenUpdatedIterator, error)) *FeeQuoterInterface_FilterUsdPerTokenUpdated_Call { + _c.Call.Return(run) + return _c +} + +// FilterUsdPerUnitGasUpdated provides a mock function with given fields: opts, destChain +func (_m *FeeQuoterInterface) FilterUsdPerUnitGasUpdated(opts *bind.FilterOpts, destChain []uint64) (*fee_quoter.FeeQuoterUsdPerUnitGasUpdatedIterator, error) { + ret := _m.Called(opts, destChain) + + if len(ret) == 0 { + panic("no return value specified for FilterUsdPerUnitGasUpdated") + } + + var r0 *fee_quoter.FeeQuoterUsdPerUnitGasUpdatedIterator + var r1 error + if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []uint64) (*fee_quoter.FeeQuoterUsdPerUnitGasUpdatedIterator, error)); ok { + return rf(opts, destChain) + } + if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []uint64) *fee_quoter.FeeQuoterUsdPerUnitGasUpdatedIterator); ok { + r0 = rf(opts, destChain) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*fee_quoter.FeeQuoterUsdPerUnitGasUpdatedIterator) + } + } + + if rf, ok := ret.Get(1).(func(*bind.FilterOpts, []uint64) error); ok { + r1 = rf(opts, destChain) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_FilterUsdPerUnitGasUpdated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterUsdPerUnitGasUpdated' +type FeeQuoterInterface_FilterUsdPerUnitGasUpdated_Call struct { + *mock.Call +} + +// FilterUsdPerUnitGasUpdated is a helper method to define mock.On call +// - opts *bind.FilterOpts +// - destChain []uint64 +func (_e *FeeQuoterInterface_Expecter) FilterUsdPerUnitGasUpdated(opts interface{}, destChain interface{}) *FeeQuoterInterface_FilterUsdPerUnitGasUpdated_Call { + return &FeeQuoterInterface_FilterUsdPerUnitGasUpdated_Call{Call: _e.mock.On("FilterUsdPerUnitGasUpdated", opts, destChain)} +} + +func (_c *FeeQuoterInterface_FilterUsdPerUnitGasUpdated_Call) Run(run func(opts *bind.FilterOpts, destChain []uint64)) *FeeQuoterInterface_FilterUsdPerUnitGasUpdated_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.FilterOpts), args[1].([]uint64)) + }) + return _c +} + +func (_c *FeeQuoterInterface_FilterUsdPerUnitGasUpdated_Call) Return(_a0 *fee_quoter.FeeQuoterUsdPerUnitGasUpdatedIterator, _a1 error) *FeeQuoterInterface_FilterUsdPerUnitGasUpdated_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_FilterUsdPerUnitGasUpdated_Call) RunAndReturn(run func(*bind.FilterOpts, []uint64) (*fee_quoter.FeeQuoterUsdPerUnitGasUpdatedIterator, error)) *FeeQuoterInterface_FilterUsdPerUnitGasUpdated_Call { + _c.Call.Return(run) + return _c +} + +// GetAllAuthorizedCallers provides a mock function with given fields: opts +func (_m *FeeQuoterInterface) GetAllAuthorizedCallers(opts *bind.CallOpts) ([]common.Address, error) { + ret := _m.Called(opts) + + if len(ret) == 0 { + panic("no return value specified for GetAllAuthorizedCallers") + } + + var r0 []common.Address + var r1 error + if rf, ok := ret.Get(0).(func(*bind.CallOpts) ([]common.Address, error)); ok { + return rf(opts) + } + if rf, ok := ret.Get(0).(func(*bind.CallOpts) []common.Address); ok { + r0 = rf(opts) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]common.Address) + } + } + + if rf, ok := ret.Get(1).(func(*bind.CallOpts) error); ok { + r1 = rf(opts) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_GetAllAuthorizedCallers_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetAllAuthorizedCallers' +type FeeQuoterInterface_GetAllAuthorizedCallers_Call struct { + *mock.Call +} + +// GetAllAuthorizedCallers is a helper method to define mock.On call +// - opts *bind.CallOpts +func (_e *FeeQuoterInterface_Expecter) GetAllAuthorizedCallers(opts interface{}) *FeeQuoterInterface_GetAllAuthorizedCallers_Call { + return &FeeQuoterInterface_GetAllAuthorizedCallers_Call{Call: _e.mock.On("GetAllAuthorizedCallers", opts)} +} + +func (_c *FeeQuoterInterface_GetAllAuthorizedCallers_Call) Run(run func(opts *bind.CallOpts)) *FeeQuoterInterface_GetAllAuthorizedCallers_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.CallOpts)) + }) + return _c +} + +func (_c *FeeQuoterInterface_GetAllAuthorizedCallers_Call) Return(_a0 []common.Address, _a1 error) *FeeQuoterInterface_GetAllAuthorizedCallers_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_GetAllAuthorizedCallers_Call) RunAndReturn(run func(*bind.CallOpts) ([]common.Address, error)) *FeeQuoterInterface_GetAllAuthorizedCallers_Call { + _c.Call.Return(run) + return _c +} + +// GetDestChainConfig provides a mock function with given fields: opts, destChainSelector +func (_m *FeeQuoterInterface) GetDestChainConfig(opts *bind.CallOpts, destChainSelector uint64) (fee_quoter.FeeQuoterDestChainConfig, error) { + ret := _m.Called(opts, destChainSelector) + + if len(ret) == 0 { + panic("no return value specified for GetDestChainConfig") + } + + var r0 fee_quoter.FeeQuoterDestChainConfig + var r1 error + if rf, ok := ret.Get(0).(func(*bind.CallOpts, uint64) (fee_quoter.FeeQuoterDestChainConfig, error)); ok { + return rf(opts, destChainSelector) + } + if rf, ok := ret.Get(0).(func(*bind.CallOpts, uint64) fee_quoter.FeeQuoterDestChainConfig); ok { + r0 = rf(opts, destChainSelector) + } else { + r0 = ret.Get(0).(fee_quoter.FeeQuoterDestChainConfig) + } + + if rf, ok := ret.Get(1).(func(*bind.CallOpts, uint64) error); ok { + r1 = rf(opts, destChainSelector) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_GetDestChainConfig_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetDestChainConfig' +type FeeQuoterInterface_GetDestChainConfig_Call struct { + *mock.Call +} + +// GetDestChainConfig is a helper method to define mock.On call +// - opts *bind.CallOpts +// - destChainSelector uint64 +func (_e *FeeQuoterInterface_Expecter) GetDestChainConfig(opts interface{}, destChainSelector interface{}) *FeeQuoterInterface_GetDestChainConfig_Call { + return &FeeQuoterInterface_GetDestChainConfig_Call{Call: _e.mock.On("GetDestChainConfig", opts, destChainSelector)} +} + +func (_c *FeeQuoterInterface_GetDestChainConfig_Call) Run(run func(opts *bind.CallOpts, destChainSelector uint64)) *FeeQuoterInterface_GetDestChainConfig_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.CallOpts), args[1].(uint64)) + }) + return _c +} + +func (_c *FeeQuoterInterface_GetDestChainConfig_Call) Return(_a0 fee_quoter.FeeQuoterDestChainConfig, _a1 error) *FeeQuoterInterface_GetDestChainConfig_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_GetDestChainConfig_Call) RunAndReturn(run func(*bind.CallOpts, uint64) (fee_quoter.FeeQuoterDestChainConfig, error)) *FeeQuoterInterface_GetDestChainConfig_Call { + _c.Call.Return(run) + return _c +} + +// GetDestinationChainGasPrice provides a mock function with given fields: opts, destChainSelector +func (_m *FeeQuoterInterface) GetDestinationChainGasPrice(opts *bind.CallOpts, destChainSelector uint64) (fee_quoter.InternalTimestampedPackedUint224, error) { + ret := _m.Called(opts, destChainSelector) + + if len(ret) == 0 { + panic("no return value specified for GetDestinationChainGasPrice") + } + + var r0 fee_quoter.InternalTimestampedPackedUint224 + var r1 error + if rf, ok := ret.Get(0).(func(*bind.CallOpts, uint64) (fee_quoter.InternalTimestampedPackedUint224, error)); ok { + return rf(opts, destChainSelector) + } + if rf, ok := ret.Get(0).(func(*bind.CallOpts, uint64) fee_quoter.InternalTimestampedPackedUint224); ok { + r0 = rf(opts, destChainSelector) + } else { + r0 = ret.Get(0).(fee_quoter.InternalTimestampedPackedUint224) + } + + if rf, ok := ret.Get(1).(func(*bind.CallOpts, uint64) error); ok { + r1 = rf(opts, destChainSelector) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_GetDestinationChainGasPrice_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetDestinationChainGasPrice' +type FeeQuoterInterface_GetDestinationChainGasPrice_Call struct { + *mock.Call +} + +// GetDestinationChainGasPrice is a helper method to define mock.On call +// - opts *bind.CallOpts +// - destChainSelector uint64 +func (_e *FeeQuoterInterface_Expecter) GetDestinationChainGasPrice(opts interface{}, destChainSelector interface{}) *FeeQuoterInterface_GetDestinationChainGasPrice_Call { + return &FeeQuoterInterface_GetDestinationChainGasPrice_Call{Call: _e.mock.On("GetDestinationChainGasPrice", opts, destChainSelector)} +} + +func (_c *FeeQuoterInterface_GetDestinationChainGasPrice_Call) Run(run func(opts *bind.CallOpts, destChainSelector uint64)) *FeeQuoterInterface_GetDestinationChainGasPrice_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.CallOpts), args[1].(uint64)) + }) + return _c +} + +func (_c *FeeQuoterInterface_GetDestinationChainGasPrice_Call) Return(_a0 fee_quoter.InternalTimestampedPackedUint224, _a1 error) *FeeQuoterInterface_GetDestinationChainGasPrice_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_GetDestinationChainGasPrice_Call) RunAndReturn(run func(*bind.CallOpts, uint64) (fee_quoter.InternalTimestampedPackedUint224, error)) *FeeQuoterInterface_GetDestinationChainGasPrice_Call { + _c.Call.Return(run) + return _c +} + +// GetFeeTokens provides a mock function with given fields: opts +func (_m *FeeQuoterInterface) GetFeeTokens(opts *bind.CallOpts) ([]common.Address, error) { + ret := _m.Called(opts) + + if len(ret) == 0 { + panic("no return value specified for GetFeeTokens") + } + + var r0 []common.Address + var r1 error + if rf, ok := ret.Get(0).(func(*bind.CallOpts) ([]common.Address, error)); ok { + return rf(opts) + } + if rf, ok := ret.Get(0).(func(*bind.CallOpts) []common.Address); ok { + r0 = rf(opts) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]common.Address) + } + } + + if rf, ok := ret.Get(1).(func(*bind.CallOpts) error); ok { + r1 = rf(opts) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_GetFeeTokens_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetFeeTokens' +type FeeQuoterInterface_GetFeeTokens_Call struct { + *mock.Call +} + +// GetFeeTokens is a helper method to define mock.On call +// - opts *bind.CallOpts +func (_e *FeeQuoterInterface_Expecter) GetFeeTokens(opts interface{}) *FeeQuoterInterface_GetFeeTokens_Call { + return &FeeQuoterInterface_GetFeeTokens_Call{Call: _e.mock.On("GetFeeTokens", opts)} +} + +func (_c *FeeQuoterInterface_GetFeeTokens_Call) Run(run func(opts *bind.CallOpts)) *FeeQuoterInterface_GetFeeTokens_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.CallOpts)) + }) + return _c +} + +func (_c *FeeQuoterInterface_GetFeeTokens_Call) Return(_a0 []common.Address, _a1 error) *FeeQuoterInterface_GetFeeTokens_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_GetFeeTokens_Call) RunAndReturn(run func(*bind.CallOpts) ([]common.Address, error)) *FeeQuoterInterface_GetFeeTokens_Call { + _c.Call.Return(run) + return _c +} + +// GetPremiumMultiplierWeiPerEth provides a mock function with given fields: opts, token +func (_m *FeeQuoterInterface) GetPremiumMultiplierWeiPerEth(opts *bind.CallOpts, token common.Address) (uint64, error) { + ret := _m.Called(opts, token) + + if len(ret) == 0 { + panic("no return value specified for GetPremiumMultiplierWeiPerEth") + } + + var r0 uint64 + var r1 error + if rf, ok := ret.Get(0).(func(*bind.CallOpts, common.Address) (uint64, error)); ok { + return rf(opts, token) + } + if rf, ok := ret.Get(0).(func(*bind.CallOpts, common.Address) uint64); ok { + r0 = rf(opts, token) + } else { + r0 = ret.Get(0).(uint64) + } + + if rf, ok := ret.Get(1).(func(*bind.CallOpts, common.Address) error); ok { + r1 = rf(opts, token) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_GetPremiumMultiplierWeiPerEth_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetPremiumMultiplierWeiPerEth' +type FeeQuoterInterface_GetPremiumMultiplierWeiPerEth_Call struct { + *mock.Call +} + +// GetPremiumMultiplierWeiPerEth is a helper method to define mock.On call +// - opts *bind.CallOpts +// - token common.Address +func (_e *FeeQuoterInterface_Expecter) GetPremiumMultiplierWeiPerEth(opts interface{}, token interface{}) *FeeQuoterInterface_GetPremiumMultiplierWeiPerEth_Call { + return &FeeQuoterInterface_GetPremiumMultiplierWeiPerEth_Call{Call: _e.mock.On("GetPremiumMultiplierWeiPerEth", opts, token)} +} + +func (_c *FeeQuoterInterface_GetPremiumMultiplierWeiPerEth_Call) Run(run func(opts *bind.CallOpts, token common.Address)) *FeeQuoterInterface_GetPremiumMultiplierWeiPerEth_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.CallOpts), args[1].(common.Address)) + }) + return _c +} + +func (_c *FeeQuoterInterface_GetPremiumMultiplierWeiPerEth_Call) Return(_a0 uint64, _a1 error) *FeeQuoterInterface_GetPremiumMultiplierWeiPerEth_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_GetPremiumMultiplierWeiPerEth_Call) RunAndReturn(run func(*bind.CallOpts, common.Address) (uint64, error)) *FeeQuoterInterface_GetPremiumMultiplierWeiPerEth_Call { + _c.Call.Return(run) + return _c +} + +// GetStaticConfig provides a mock function with given fields: opts +func (_m *FeeQuoterInterface) GetStaticConfig(opts *bind.CallOpts) (fee_quoter.FeeQuoterStaticConfig, error) { + ret := _m.Called(opts) + + if len(ret) == 0 { + panic("no return value specified for GetStaticConfig") + } + + var r0 fee_quoter.FeeQuoterStaticConfig + var r1 error + if rf, ok := ret.Get(0).(func(*bind.CallOpts) (fee_quoter.FeeQuoterStaticConfig, error)); ok { + return rf(opts) + } + if rf, ok := ret.Get(0).(func(*bind.CallOpts) fee_quoter.FeeQuoterStaticConfig); ok { + r0 = rf(opts) + } else { + r0 = ret.Get(0).(fee_quoter.FeeQuoterStaticConfig) + } + + if rf, ok := ret.Get(1).(func(*bind.CallOpts) error); ok { + r1 = rf(opts) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_GetStaticConfig_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetStaticConfig' +type FeeQuoterInterface_GetStaticConfig_Call struct { + *mock.Call +} + +// GetStaticConfig is a helper method to define mock.On call +// - opts *bind.CallOpts +func (_e *FeeQuoterInterface_Expecter) GetStaticConfig(opts interface{}) *FeeQuoterInterface_GetStaticConfig_Call { + return &FeeQuoterInterface_GetStaticConfig_Call{Call: _e.mock.On("GetStaticConfig", opts)} +} + +func (_c *FeeQuoterInterface_GetStaticConfig_Call) Run(run func(opts *bind.CallOpts)) *FeeQuoterInterface_GetStaticConfig_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.CallOpts)) + }) + return _c +} + +func (_c *FeeQuoterInterface_GetStaticConfig_Call) Return(_a0 fee_quoter.FeeQuoterStaticConfig, _a1 error) *FeeQuoterInterface_GetStaticConfig_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_GetStaticConfig_Call) RunAndReturn(run func(*bind.CallOpts) (fee_quoter.FeeQuoterStaticConfig, error)) *FeeQuoterInterface_GetStaticConfig_Call { + _c.Call.Return(run) + return _c +} + +// GetTokenAndGasPrices provides a mock function with given fields: opts, token, destChainSelector +func (_m *FeeQuoterInterface) GetTokenAndGasPrices(opts *bind.CallOpts, token common.Address, destChainSelector uint64) (fee_quoter.GetTokenAndGasPrices, error) { + ret := _m.Called(opts, token, destChainSelector) + + if len(ret) == 0 { + panic("no return value specified for GetTokenAndGasPrices") + } + + var r0 fee_quoter.GetTokenAndGasPrices + var r1 error + if rf, ok := ret.Get(0).(func(*bind.CallOpts, common.Address, uint64) (fee_quoter.GetTokenAndGasPrices, error)); ok { + return rf(opts, token, destChainSelector) + } + if rf, ok := ret.Get(0).(func(*bind.CallOpts, common.Address, uint64) fee_quoter.GetTokenAndGasPrices); ok { + r0 = rf(opts, token, destChainSelector) + } else { + r0 = ret.Get(0).(fee_quoter.GetTokenAndGasPrices) + } + + if rf, ok := ret.Get(1).(func(*bind.CallOpts, common.Address, uint64) error); ok { + r1 = rf(opts, token, destChainSelector) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_GetTokenAndGasPrices_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetTokenAndGasPrices' +type FeeQuoterInterface_GetTokenAndGasPrices_Call struct { + *mock.Call +} + +// GetTokenAndGasPrices is a helper method to define mock.On call +// - opts *bind.CallOpts +// - token common.Address +// - destChainSelector uint64 +func (_e *FeeQuoterInterface_Expecter) GetTokenAndGasPrices(opts interface{}, token interface{}, destChainSelector interface{}) *FeeQuoterInterface_GetTokenAndGasPrices_Call { + return &FeeQuoterInterface_GetTokenAndGasPrices_Call{Call: _e.mock.On("GetTokenAndGasPrices", opts, token, destChainSelector)} +} + +func (_c *FeeQuoterInterface_GetTokenAndGasPrices_Call) Run(run func(opts *bind.CallOpts, token common.Address, destChainSelector uint64)) *FeeQuoterInterface_GetTokenAndGasPrices_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.CallOpts), args[1].(common.Address), args[2].(uint64)) + }) + return _c +} + +func (_c *FeeQuoterInterface_GetTokenAndGasPrices_Call) Return(_a0 fee_quoter.GetTokenAndGasPrices, _a1 error) *FeeQuoterInterface_GetTokenAndGasPrices_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_GetTokenAndGasPrices_Call) RunAndReturn(run func(*bind.CallOpts, common.Address, uint64) (fee_quoter.GetTokenAndGasPrices, error)) *FeeQuoterInterface_GetTokenAndGasPrices_Call { + _c.Call.Return(run) + return _c +} + +// GetTokenPrice provides a mock function with given fields: opts, token +func (_m *FeeQuoterInterface) GetTokenPrice(opts *bind.CallOpts, token common.Address) (fee_quoter.InternalTimestampedPackedUint224, error) { + ret := _m.Called(opts, token) + + if len(ret) == 0 { + panic("no return value specified for GetTokenPrice") + } + + var r0 fee_quoter.InternalTimestampedPackedUint224 + var r1 error + if rf, ok := ret.Get(0).(func(*bind.CallOpts, common.Address) (fee_quoter.InternalTimestampedPackedUint224, error)); ok { + return rf(opts, token) + } + if rf, ok := ret.Get(0).(func(*bind.CallOpts, common.Address) fee_quoter.InternalTimestampedPackedUint224); ok { + r0 = rf(opts, token) + } else { + r0 = ret.Get(0).(fee_quoter.InternalTimestampedPackedUint224) + } + + if rf, ok := ret.Get(1).(func(*bind.CallOpts, common.Address) error); ok { + r1 = rf(opts, token) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_GetTokenPrice_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetTokenPrice' +type FeeQuoterInterface_GetTokenPrice_Call struct { + *mock.Call +} + +// GetTokenPrice is a helper method to define mock.On call +// - opts *bind.CallOpts +// - token common.Address +func (_e *FeeQuoterInterface_Expecter) GetTokenPrice(opts interface{}, token interface{}) *FeeQuoterInterface_GetTokenPrice_Call { + return &FeeQuoterInterface_GetTokenPrice_Call{Call: _e.mock.On("GetTokenPrice", opts, token)} +} + +func (_c *FeeQuoterInterface_GetTokenPrice_Call) Run(run func(opts *bind.CallOpts, token common.Address)) *FeeQuoterInterface_GetTokenPrice_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.CallOpts), args[1].(common.Address)) + }) + return _c +} + +func (_c *FeeQuoterInterface_GetTokenPrice_Call) Return(_a0 fee_quoter.InternalTimestampedPackedUint224, _a1 error) *FeeQuoterInterface_GetTokenPrice_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_GetTokenPrice_Call) RunAndReturn(run func(*bind.CallOpts, common.Address) (fee_quoter.InternalTimestampedPackedUint224, error)) *FeeQuoterInterface_GetTokenPrice_Call { + _c.Call.Return(run) + return _c +} + +// GetTokenPriceFeedConfig provides a mock function with given fields: opts, token +func (_m *FeeQuoterInterface) GetTokenPriceFeedConfig(opts *bind.CallOpts, token common.Address) (fee_quoter.IFeeQuoterTokenPriceFeedConfig, error) { + ret := _m.Called(opts, token) + + if len(ret) == 0 { + panic("no return value specified for GetTokenPriceFeedConfig") + } + + var r0 fee_quoter.IFeeQuoterTokenPriceFeedConfig + var r1 error + if rf, ok := ret.Get(0).(func(*bind.CallOpts, common.Address) (fee_quoter.IFeeQuoterTokenPriceFeedConfig, error)); ok { + return rf(opts, token) + } + if rf, ok := ret.Get(0).(func(*bind.CallOpts, common.Address) fee_quoter.IFeeQuoterTokenPriceFeedConfig); ok { + r0 = rf(opts, token) + } else { + r0 = ret.Get(0).(fee_quoter.IFeeQuoterTokenPriceFeedConfig) + } + + if rf, ok := ret.Get(1).(func(*bind.CallOpts, common.Address) error); ok { + r1 = rf(opts, token) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_GetTokenPriceFeedConfig_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetTokenPriceFeedConfig' +type FeeQuoterInterface_GetTokenPriceFeedConfig_Call struct { + *mock.Call +} + +// GetTokenPriceFeedConfig is a helper method to define mock.On call +// - opts *bind.CallOpts +// - token common.Address +func (_e *FeeQuoterInterface_Expecter) GetTokenPriceFeedConfig(opts interface{}, token interface{}) *FeeQuoterInterface_GetTokenPriceFeedConfig_Call { + return &FeeQuoterInterface_GetTokenPriceFeedConfig_Call{Call: _e.mock.On("GetTokenPriceFeedConfig", opts, token)} +} + +func (_c *FeeQuoterInterface_GetTokenPriceFeedConfig_Call) Run(run func(opts *bind.CallOpts, token common.Address)) *FeeQuoterInterface_GetTokenPriceFeedConfig_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.CallOpts), args[1].(common.Address)) + }) + return _c +} + +func (_c *FeeQuoterInterface_GetTokenPriceFeedConfig_Call) Return(_a0 fee_quoter.IFeeQuoterTokenPriceFeedConfig, _a1 error) *FeeQuoterInterface_GetTokenPriceFeedConfig_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_GetTokenPriceFeedConfig_Call) RunAndReturn(run func(*bind.CallOpts, common.Address) (fee_quoter.IFeeQuoterTokenPriceFeedConfig, error)) *FeeQuoterInterface_GetTokenPriceFeedConfig_Call { + _c.Call.Return(run) + return _c +} + +// GetTokenPrices provides a mock function with given fields: opts, tokens +func (_m *FeeQuoterInterface) GetTokenPrices(opts *bind.CallOpts, tokens []common.Address) ([]fee_quoter.InternalTimestampedPackedUint224, error) { + ret := _m.Called(opts, tokens) + + if len(ret) == 0 { + panic("no return value specified for GetTokenPrices") + } + + var r0 []fee_quoter.InternalTimestampedPackedUint224 + var r1 error + if rf, ok := ret.Get(0).(func(*bind.CallOpts, []common.Address) ([]fee_quoter.InternalTimestampedPackedUint224, error)); ok { + return rf(opts, tokens) + } + if rf, ok := ret.Get(0).(func(*bind.CallOpts, []common.Address) []fee_quoter.InternalTimestampedPackedUint224); ok { + r0 = rf(opts, tokens) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]fee_quoter.InternalTimestampedPackedUint224) + } + } + + if rf, ok := ret.Get(1).(func(*bind.CallOpts, []common.Address) error); ok { + r1 = rf(opts, tokens) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_GetTokenPrices_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetTokenPrices' +type FeeQuoterInterface_GetTokenPrices_Call struct { + *mock.Call +} + +// GetTokenPrices is a helper method to define mock.On call +// - opts *bind.CallOpts +// - tokens []common.Address +func (_e *FeeQuoterInterface_Expecter) GetTokenPrices(opts interface{}, tokens interface{}) *FeeQuoterInterface_GetTokenPrices_Call { + return &FeeQuoterInterface_GetTokenPrices_Call{Call: _e.mock.On("GetTokenPrices", opts, tokens)} +} + +func (_c *FeeQuoterInterface_GetTokenPrices_Call) Run(run func(opts *bind.CallOpts, tokens []common.Address)) *FeeQuoterInterface_GetTokenPrices_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.CallOpts), args[1].([]common.Address)) + }) + return _c +} + +func (_c *FeeQuoterInterface_GetTokenPrices_Call) Return(_a0 []fee_quoter.InternalTimestampedPackedUint224, _a1 error) *FeeQuoterInterface_GetTokenPrices_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_GetTokenPrices_Call) RunAndReturn(run func(*bind.CallOpts, []common.Address) ([]fee_quoter.InternalTimestampedPackedUint224, error)) *FeeQuoterInterface_GetTokenPrices_Call { + _c.Call.Return(run) + return _c +} + +// GetTokenTransferFeeConfig provides a mock function with given fields: opts, destChainSelector, token +func (_m *FeeQuoterInterface) GetTokenTransferFeeConfig(opts *bind.CallOpts, destChainSelector uint64, token common.Address) (fee_quoter.FeeQuoterTokenTransferFeeConfig, error) { + ret := _m.Called(opts, destChainSelector, token) + + if len(ret) == 0 { + panic("no return value specified for GetTokenTransferFeeConfig") + } + + var r0 fee_quoter.FeeQuoterTokenTransferFeeConfig + var r1 error + if rf, ok := ret.Get(0).(func(*bind.CallOpts, uint64, common.Address) (fee_quoter.FeeQuoterTokenTransferFeeConfig, error)); ok { + return rf(opts, destChainSelector, token) + } + if rf, ok := ret.Get(0).(func(*bind.CallOpts, uint64, common.Address) fee_quoter.FeeQuoterTokenTransferFeeConfig); ok { + r0 = rf(opts, destChainSelector, token) + } else { + r0 = ret.Get(0).(fee_quoter.FeeQuoterTokenTransferFeeConfig) + } + + if rf, ok := ret.Get(1).(func(*bind.CallOpts, uint64, common.Address) error); ok { + r1 = rf(opts, destChainSelector, token) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_GetTokenTransferFeeConfig_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetTokenTransferFeeConfig' +type FeeQuoterInterface_GetTokenTransferFeeConfig_Call struct { + *mock.Call +} + +// GetTokenTransferFeeConfig is a helper method to define mock.On call +// - opts *bind.CallOpts +// - destChainSelector uint64 +// - token common.Address +func (_e *FeeQuoterInterface_Expecter) GetTokenTransferFeeConfig(opts interface{}, destChainSelector interface{}, token interface{}) *FeeQuoterInterface_GetTokenTransferFeeConfig_Call { + return &FeeQuoterInterface_GetTokenTransferFeeConfig_Call{Call: _e.mock.On("GetTokenTransferFeeConfig", opts, destChainSelector, token)} +} + +func (_c *FeeQuoterInterface_GetTokenTransferFeeConfig_Call) Run(run func(opts *bind.CallOpts, destChainSelector uint64, token common.Address)) *FeeQuoterInterface_GetTokenTransferFeeConfig_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.CallOpts), args[1].(uint64), args[2].(common.Address)) + }) + return _c +} + +func (_c *FeeQuoterInterface_GetTokenTransferFeeConfig_Call) Return(_a0 fee_quoter.FeeQuoterTokenTransferFeeConfig, _a1 error) *FeeQuoterInterface_GetTokenTransferFeeConfig_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_GetTokenTransferFeeConfig_Call) RunAndReturn(run func(*bind.CallOpts, uint64, common.Address) (fee_quoter.FeeQuoterTokenTransferFeeConfig, error)) *FeeQuoterInterface_GetTokenTransferFeeConfig_Call { + _c.Call.Return(run) + return _c +} + +// GetValidatedFee provides a mock function with given fields: opts, destChainSelector, message +func (_m *FeeQuoterInterface) GetValidatedFee(opts *bind.CallOpts, destChainSelector uint64, message fee_quoter.ClientEVM2AnyMessage) (*big.Int, error) { + ret := _m.Called(opts, destChainSelector, message) + + if len(ret) == 0 { + panic("no return value specified for GetValidatedFee") + } + + var r0 *big.Int + var r1 error + if rf, ok := ret.Get(0).(func(*bind.CallOpts, uint64, fee_quoter.ClientEVM2AnyMessage) (*big.Int, error)); ok { + return rf(opts, destChainSelector, message) + } + if rf, ok := ret.Get(0).(func(*bind.CallOpts, uint64, fee_quoter.ClientEVM2AnyMessage) *big.Int); ok { + r0 = rf(opts, destChainSelector, message) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*big.Int) + } + } + + if rf, ok := ret.Get(1).(func(*bind.CallOpts, uint64, fee_quoter.ClientEVM2AnyMessage) error); ok { + r1 = rf(opts, destChainSelector, message) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_GetValidatedFee_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetValidatedFee' +type FeeQuoterInterface_GetValidatedFee_Call struct { + *mock.Call +} + +// GetValidatedFee is a helper method to define mock.On call +// - opts *bind.CallOpts +// - destChainSelector uint64 +// - message fee_quoter.ClientEVM2AnyMessage +func (_e *FeeQuoterInterface_Expecter) GetValidatedFee(opts interface{}, destChainSelector interface{}, message interface{}) *FeeQuoterInterface_GetValidatedFee_Call { + return &FeeQuoterInterface_GetValidatedFee_Call{Call: _e.mock.On("GetValidatedFee", opts, destChainSelector, message)} +} + +func (_c *FeeQuoterInterface_GetValidatedFee_Call) Run(run func(opts *bind.CallOpts, destChainSelector uint64, message fee_quoter.ClientEVM2AnyMessage)) *FeeQuoterInterface_GetValidatedFee_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.CallOpts), args[1].(uint64), args[2].(fee_quoter.ClientEVM2AnyMessage)) + }) + return _c +} + +func (_c *FeeQuoterInterface_GetValidatedFee_Call) Return(_a0 *big.Int, _a1 error) *FeeQuoterInterface_GetValidatedFee_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_GetValidatedFee_Call) RunAndReturn(run func(*bind.CallOpts, uint64, fee_quoter.ClientEVM2AnyMessage) (*big.Int, error)) *FeeQuoterInterface_GetValidatedFee_Call { + _c.Call.Return(run) + return _c +} + +// GetValidatedTokenPrice provides a mock function with given fields: opts, token +func (_m *FeeQuoterInterface) GetValidatedTokenPrice(opts *bind.CallOpts, token common.Address) (*big.Int, error) { + ret := _m.Called(opts, token) + + if len(ret) == 0 { + panic("no return value specified for GetValidatedTokenPrice") + } + + var r0 *big.Int + var r1 error + if rf, ok := ret.Get(0).(func(*bind.CallOpts, common.Address) (*big.Int, error)); ok { + return rf(opts, token) + } + if rf, ok := ret.Get(0).(func(*bind.CallOpts, common.Address) *big.Int); ok { + r0 = rf(opts, token) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*big.Int) + } + } + + if rf, ok := ret.Get(1).(func(*bind.CallOpts, common.Address) error); ok { + r1 = rf(opts, token) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_GetValidatedTokenPrice_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetValidatedTokenPrice' +type FeeQuoterInterface_GetValidatedTokenPrice_Call struct { + *mock.Call +} + +// GetValidatedTokenPrice is a helper method to define mock.On call +// - opts *bind.CallOpts +// - token common.Address +func (_e *FeeQuoterInterface_Expecter) GetValidatedTokenPrice(opts interface{}, token interface{}) *FeeQuoterInterface_GetValidatedTokenPrice_Call { + return &FeeQuoterInterface_GetValidatedTokenPrice_Call{Call: _e.mock.On("GetValidatedTokenPrice", opts, token)} +} + +func (_c *FeeQuoterInterface_GetValidatedTokenPrice_Call) Run(run func(opts *bind.CallOpts, token common.Address)) *FeeQuoterInterface_GetValidatedTokenPrice_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.CallOpts), args[1].(common.Address)) + }) + return _c +} + +func (_c *FeeQuoterInterface_GetValidatedTokenPrice_Call) Return(_a0 *big.Int, _a1 error) *FeeQuoterInterface_GetValidatedTokenPrice_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_GetValidatedTokenPrice_Call) RunAndReturn(run func(*bind.CallOpts, common.Address) (*big.Int, error)) *FeeQuoterInterface_GetValidatedTokenPrice_Call { + _c.Call.Return(run) + return _c +} + +// OnReport provides a mock function with given fields: opts, metadata, report +func (_m *FeeQuoterInterface) OnReport(opts *bind.TransactOpts, metadata []byte, report []byte) (*types.Transaction, error) { + ret := _m.Called(opts, metadata, report) + + if len(ret) == 0 { + panic("no return value specified for OnReport") + } + + var r0 *types.Transaction + var r1 error + if rf, ok := ret.Get(0).(func(*bind.TransactOpts, []byte, []byte) (*types.Transaction, error)); ok { + return rf(opts, metadata, report) + } + if rf, ok := ret.Get(0).(func(*bind.TransactOpts, []byte, []byte) *types.Transaction); ok { + r0 = rf(opts, metadata, report) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.Transaction) + } + } + + if rf, ok := ret.Get(1).(func(*bind.TransactOpts, []byte, []byte) error); ok { + r1 = rf(opts, metadata, report) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_OnReport_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'OnReport' +type FeeQuoterInterface_OnReport_Call struct { + *mock.Call +} + +// OnReport is a helper method to define mock.On call +// - opts *bind.TransactOpts +// - metadata []byte +// - report []byte +func (_e *FeeQuoterInterface_Expecter) OnReport(opts interface{}, metadata interface{}, report interface{}) *FeeQuoterInterface_OnReport_Call { + return &FeeQuoterInterface_OnReport_Call{Call: _e.mock.On("OnReport", opts, metadata, report)} +} + +func (_c *FeeQuoterInterface_OnReport_Call) Run(run func(opts *bind.TransactOpts, metadata []byte, report []byte)) *FeeQuoterInterface_OnReport_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.TransactOpts), args[1].([]byte), args[2].([]byte)) + }) + return _c +} + +func (_c *FeeQuoterInterface_OnReport_Call) Return(_a0 *types.Transaction, _a1 error) *FeeQuoterInterface_OnReport_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_OnReport_Call) RunAndReturn(run func(*bind.TransactOpts, []byte, []byte) (*types.Transaction, error)) *FeeQuoterInterface_OnReport_Call { + _c.Call.Return(run) + return _c +} + +// Owner provides a mock function with given fields: opts +func (_m *FeeQuoterInterface) Owner(opts *bind.CallOpts) (common.Address, error) { + ret := _m.Called(opts) + + if len(ret) == 0 { + panic("no return value specified for Owner") + } + + var r0 common.Address + var r1 error + if rf, ok := ret.Get(0).(func(*bind.CallOpts) (common.Address, error)); ok { + return rf(opts) + } + if rf, ok := ret.Get(0).(func(*bind.CallOpts) common.Address); ok { + r0 = rf(opts) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(common.Address) + } + } + + if rf, ok := ret.Get(1).(func(*bind.CallOpts) error); ok { + r1 = rf(opts) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_Owner_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Owner' +type FeeQuoterInterface_Owner_Call struct { + *mock.Call +} + +// Owner is a helper method to define mock.On call +// - opts *bind.CallOpts +func (_e *FeeQuoterInterface_Expecter) Owner(opts interface{}) *FeeQuoterInterface_Owner_Call { + return &FeeQuoterInterface_Owner_Call{Call: _e.mock.On("Owner", opts)} +} + +func (_c *FeeQuoterInterface_Owner_Call) Run(run func(opts *bind.CallOpts)) *FeeQuoterInterface_Owner_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.CallOpts)) + }) + return _c +} + +func (_c *FeeQuoterInterface_Owner_Call) Return(_a0 common.Address, _a1 error) *FeeQuoterInterface_Owner_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_Owner_Call) RunAndReturn(run func(*bind.CallOpts) (common.Address, error)) *FeeQuoterInterface_Owner_Call { + _c.Call.Return(run) + return _c +} + +// ParseAuthorizedCallerAdded provides a mock function with given fields: log +func (_m *FeeQuoterInterface) ParseAuthorizedCallerAdded(log types.Log) (*fee_quoter.FeeQuoterAuthorizedCallerAdded, error) { + ret := _m.Called(log) + + if len(ret) == 0 { + panic("no return value specified for ParseAuthorizedCallerAdded") + } + + var r0 *fee_quoter.FeeQuoterAuthorizedCallerAdded + var r1 error + if rf, ok := ret.Get(0).(func(types.Log) (*fee_quoter.FeeQuoterAuthorizedCallerAdded, error)); ok { + return rf(log) + } + if rf, ok := ret.Get(0).(func(types.Log) *fee_quoter.FeeQuoterAuthorizedCallerAdded); ok { + r0 = rf(log) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*fee_quoter.FeeQuoterAuthorizedCallerAdded) + } + } + + if rf, ok := ret.Get(1).(func(types.Log) error); ok { + r1 = rf(log) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_ParseAuthorizedCallerAdded_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParseAuthorizedCallerAdded' +type FeeQuoterInterface_ParseAuthorizedCallerAdded_Call struct { + *mock.Call +} + +// ParseAuthorizedCallerAdded is a helper method to define mock.On call +// - log types.Log +func (_e *FeeQuoterInterface_Expecter) ParseAuthorizedCallerAdded(log interface{}) *FeeQuoterInterface_ParseAuthorizedCallerAdded_Call { + return &FeeQuoterInterface_ParseAuthorizedCallerAdded_Call{Call: _e.mock.On("ParseAuthorizedCallerAdded", log)} +} + +func (_c *FeeQuoterInterface_ParseAuthorizedCallerAdded_Call) Run(run func(log types.Log)) *FeeQuoterInterface_ParseAuthorizedCallerAdded_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(types.Log)) + }) + return _c +} + +func (_c *FeeQuoterInterface_ParseAuthorizedCallerAdded_Call) Return(_a0 *fee_quoter.FeeQuoterAuthorizedCallerAdded, _a1 error) *FeeQuoterInterface_ParseAuthorizedCallerAdded_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_ParseAuthorizedCallerAdded_Call) RunAndReturn(run func(types.Log) (*fee_quoter.FeeQuoterAuthorizedCallerAdded, error)) *FeeQuoterInterface_ParseAuthorizedCallerAdded_Call { + _c.Call.Return(run) + return _c +} + +// ParseAuthorizedCallerRemoved provides a mock function with given fields: log +func (_m *FeeQuoterInterface) ParseAuthorizedCallerRemoved(log types.Log) (*fee_quoter.FeeQuoterAuthorizedCallerRemoved, error) { + ret := _m.Called(log) + + if len(ret) == 0 { + panic("no return value specified for ParseAuthorizedCallerRemoved") + } + + var r0 *fee_quoter.FeeQuoterAuthorizedCallerRemoved + var r1 error + if rf, ok := ret.Get(0).(func(types.Log) (*fee_quoter.FeeQuoterAuthorizedCallerRemoved, error)); ok { + return rf(log) + } + if rf, ok := ret.Get(0).(func(types.Log) *fee_quoter.FeeQuoterAuthorizedCallerRemoved); ok { + r0 = rf(log) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*fee_quoter.FeeQuoterAuthorizedCallerRemoved) + } + } + + if rf, ok := ret.Get(1).(func(types.Log) error); ok { + r1 = rf(log) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_ParseAuthorizedCallerRemoved_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParseAuthorizedCallerRemoved' +type FeeQuoterInterface_ParseAuthorizedCallerRemoved_Call struct { + *mock.Call +} + +// ParseAuthorizedCallerRemoved is a helper method to define mock.On call +// - log types.Log +func (_e *FeeQuoterInterface_Expecter) ParseAuthorizedCallerRemoved(log interface{}) *FeeQuoterInterface_ParseAuthorizedCallerRemoved_Call { + return &FeeQuoterInterface_ParseAuthorizedCallerRemoved_Call{Call: _e.mock.On("ParseAuthorizedCallerRemoved", log)} +} + +func (_c *FeeQuoterInterface_ParseAuthorizedCallerRemoved_Call) Run(run func(log types.Log)) *FeeQuoterInterface_ParseAuthorizedCallerRemoved_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(types.Log)) + }) + return _c +} + +func (_c *FeeQuoterInterface_ParseAuthorizedCallerRemoved_Call) Return(_a0 *fee_quoter.FeeQuoterAuthorizedCallerRemoved, _a1 error) *FeeQuoterInterface_ParseAuthorizedCallerRemoved_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_ParseAuthorizedCallerRemoved_Call) RunAndReturn(run func(types.Log) (*fee_quoter.FeeQuoterAuthorizedCallerRemoved, error)) *FeeQuoterInterface_ParseAuthorizedCallerRemoved_Call { + _c.Call.Return(run) + return _c +} + +// ParseDestChainAdded provides a mock function with given fields: log +func (_m *FeeQuoterInterface) ParseDestChainAdded(log types.Log) (*fee_quoter.FeeQuoterDestChainAdded, error) { + ret := _m.Called(log) + + if len(ret) == 0 { + panic("no return value specified for ParseDestChainAdded") + } + + var r0 *fee_quoter.FeeQuoterDestChainAdded + var r1 error + if rf, ok := ret.Get(0).(func(types.Log) (*fee_quoter.FeeQuoterDestChainAdded, error)); ok { + return rf(log) + } + if rf, ok := ret.Get(0).(func(types.Log) *fee_quoter.FeeQuoterDestChainAdded); ok { + r0 = rf(log) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*fee_quoter.FeeQuoterDestChainAdded) + } + } + + if rf, ok := ret.Get(1).(func(types.Log) error); ok { + r1 = rf(log) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_ParseDestChainAdded_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParseDestChainAdded' +type FeeQuoterInterface_ParseDestChainAdded_Call struct { + *mock.Call +} + +// ParseDestChainAdded is a helper method to define mock.On call +// - log types.Log +func (_e *FeeQuoterInterface_Expecter) ParseDestChainAdded(log interface{}) *FeeQuoterInterface_ParseDestChainAdded_Call { + return &FeeQuoterInterface_ParseDestChainAdded_Call{Call: _e.mock.On("ParseDestChainAdded", log)} +} + +func (_c *FeeQuoterInterface_ParseDestChainAdded_Call) Run(run func(log types.Log)) *FeeQuoterInterface_ParseDestChainAdded_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(types.Log)) + }) + return _c +} + +func (_c *FeeQuoterInterface_ParseDestChainAdded_Call) Return(_a0 *fee_quoter.FeeQuoterDestChainAdded, _a1 error) *FeeQuoterInterface_ParseDestChainAdded_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_ParseDestChainAdded_Call) RunAndReturn(run func(types.Log) (*fee_quoter.FeeQuoterDestChainAdded, error)) *FeeQuoterInterface_ParseDestChainAdded_Call { + _c.Call.Return(run) + return _c +} + +// ParseDestChainConfigUpdated provides a mock function with given fields: log +func (_m *FeeQuoterInterface) ParseDestChainConfigUpdated(log types.Log) (*fee_quoter.FeeQuoterDestChainConfigUpdated, error) { + ret := _m.Called(log) + + if len(ret) == 0 { + panic("no return value specified for ParseDestChainConfigUpdated") + } + + var r0 *fee_quoter.FeeQuoterDestChainConfigUpdated + var r1 error + if rf, ok := ret.Get(0).(func(types.Log) (*fee_quoter.FeeQuoterDestChainConfigUpdated, error)); ok { + return rf(log) + } + if rf, ok := ret.Get(0).(func(types.Log) *fee_quoter.FeeQuoterDestChainConfigUpdated); ok { + r0 = rf(log) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*fee_quoter.FeeQuoterDestChainConfigUpdated) + } + } + + if rf, ok := ret.Get(1).(func(types.Log) error); ok { + r1 = rf(log) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_ParseDestChainConfigUpdated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParseDestChainConfigUpdated' +type FeeQuoterInterface_ParseDestChainConfigUpdated_Call struct { + *mock.Call +} + +// ParseDestChainConfigUpdated is a helper method to define mock.On call +// - log types.Log +func (_e *FeeQuoterInterface_Expecter) ParseDestChainConfigUpdated(log interface{}) *FeeQuoterInterface_ParseDestChainConfigUpdated_Call { + return &FeeQuoterInterface_ParseDestChainConfigUpdated_Call{Call: _e.mock.On("ParseDestChainConfigUpdated", log)} +} + +func (_c *FeeQuoterInterface_ParseDestChainConfigUpdated_Call) Run(run func(log types.Log)) *FeeQuoterInterface_ParseDestChainConfigUpdated_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(types.Log)) + }) + return _c +} + +func (_c *FeeQuoterInterface_ParseDestChainConfigUpdated_Call) Return(_a0 *fee_quoter.FeeQuoterDestChainConfigUpdated, _a1 error) *FeeQuoterInterface_ParseDestChainConfigUpdated_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_ParseDestChainConfigUpdated_Call) RunAndReturn(run func(types.Log) (*fee_quoter.FeeQuoterDestChainConfigUpdated, error)) *FeeQuoterInterface_ParseDestChainConfigUpdated_Call { + _c.Call.Return(run) + return _c +} + +// ParseFeeTokenAdded provides a mock function with given fields: log +func (_m *FeeQuoterInterface) ParseFeeTokenAdded(log types.Log) (*fee_quoter.FeeQuoterFeeTokenAdded, error) { + ret := _m.Called(log) + + if len(ret) == 0 { + panic("no return value specified for ParseFeeTokenAdded") + } + + var r0 *fee_quoter.FeeQuoterFeeTokenAdded + var r1 error + if rf, ok := ret.Get(0).(func(types.Log) (*fee_quoter.FeeQuoterFeeTokenAdded, error)); ok { + return rf(log) + } + if rf, ok := ret.Get(0).(func(types.Log) *fee_quoter.FeeQuoterFeeTokenAdded); ok { + r0 = rf(log) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*fee_quoter.FeeQuoterFeeTokenAdded) + } + } + + if rf, ok := ret.Get(1).(func(types.Log) error); ok { + r1 = rf(log) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_ParseFeeTokenAdded_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParseFeeTokenAdded' +type FeeQuoterInterface_ParseFeeTokenAdded_Call struct { + *mock.Call +} + +// ParseFeeTokenAdded is a helper method to define mock.On call +// - log types.Log +func (_e *FeeQuoterInterface_Expecter) ParseFeeTokenAdded(log interface{}) *FeeQuoterInterface_ParseFeeTokenAdded_Call { + return &FeeQuoterInterface_ParseFeeTokenAdded_Call{Call: _e.mock.On("ParseFeeTokenAdded", log)} +} + +func (_c *FeeQuoterInterface_ParseFeeTokenAdded_Call) Run(run func(log types.Log)) *FeeQuoterInterface_ParseFeeTokenAdded_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(types.Log)) + }) + return _c +} + +func (_c *FeeQuoterInterface_ParseFeeTokenAdded_Call) Return(_a0 *fee_quoter.FeeQuoterFeeTokenAdded, _a1 error) *FeeQuoterInterface_ParseFeeTokenAdded_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_ParseFeeTokenAdded_Call) RunAndReturn(run func(types.Log) (*fee_quoter.FeeQuoterFeeTokenAdded, error)) *FeeQuoterInterface_ParseFeeTokenAdded_Call { + _c.Call.Return(run) + return _c +} + +// ParseFeeTokenRemoved provides a mock function with given fields: log +func (_m *FeeQuoterInterface) ParseFeeTokenRemoved(log types.Log) (*fee_quoter.FeeQuoterFeeTokenRemoved, error) { + ret := _m.Called(log) + + if len(ret) == 0 { + panic("no return value specified for ParseFeeTokenRemoved") + } + + var r0 *fee_quoter.FeeQuoterFeeTokenRemoved + var r1 error + if rf, ok := ret.Get(0).(func(types.Log) (*fee_quoter.FeeQuoterFeeTokenRemoved, error)); ok { + return rf(log) + } + if rf, ok := ret.Get(0).(func(types.Log) *fee_quoter.FeeQuoterFeeTokenRemoved); ok { + r0 = rf(log) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*fee_quoter.FeeQuoterFeeTokenRemoved) + } + } + + if rf, ok := ret.Get(1).(func(types.Log) error); ok { + r1 = rf(log) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_ParseFeeTokenRemoved_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParseFeeTokenRemoved' +type FeeQuoterInterface_ParseFeeTokenRemoved_Call struct { + *mock.Call +} + +// ParseFeeTokenRemoved is a helper method to define mock.On call +// - log types.Log +func (_e *FeeQuoterInterface_Expecter) ParseFeeTokenRemoved(log interface{}) *FeeQuoterInterface_ParseFeeTokenRemoved_Call { + return &FeeQuoterInterface_ParseFeeTokenRemoved_Call{Call: _e.mock.On("ParseFeeTokenRemoved", log)} +} + +func (_c *FeeQuoterInterface_ParseFeeTokenRemoved_Call) Run(run func(log types.Log)) *FeeQuoterInterface_ParseFeeTokenRemoved_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(types.Log)) + }) + return _c +} + +func (_c *FeeQuoterInterface_ParseFeeTokenRemoved_Call) Return(_a0 *fee_quoter.FeeQuoterFeeTokenRemoved, _a1 error) *FeeQuoterInterface_ParseFeeTokenRemoved_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_ParseFeeTokenRemoved_Call) RunAndReturn(run func(types.Log) (*fee_quoter.FeeQuoterFeeTokenRemoved, error)) *FeeQuoterInterface_ParseFeeTokenRemoved_Call { + _c.Call.Return(run) + return _c +} + +// ParseLog provides a mock function with given fields: log +func (_m *FeeQuoterInterface) ParseLog(log types.Log) (generated.AbigenLog, error) { + ret := _m.Called(log) + + if len(ret) == 0 { + panic("no return value specified for ParseLog") + } + + var r0 generated.AbigenLog + var r1 error + if rf, ok := ret.Get(0).(func(types.Log) (generated.AbigenLog, error)); ok { + return rf(log) + } + if rf, ok := ret.Get(0).(func(types.Log) generated.AbigenLog); ok { + r0 = rf(log) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(generated.AbigenLog) + } + } + + if rf, ok := ret.Get(1).(func(types.Log) error); ok { + r1 = rf(log) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_ParseLog_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParseLog' +type FeeQuoterInterface_ParseLog_Call struct { + *mock.Call +} + +// ParseLog is a helper method to define mock.On call +// - log types.Log +func (_e *FeeQuoterInterface_Expecter) ParseLog(log interface{}) *FeeQuoterInterface_ParseLog_Call { + return &FeeQuoterInterface_ParseLog_Call{Call: _e.mock.On("ParseLog", log)} +} + +func (_c *FeeQuoterInterface_ParseLog_Call) Run(run func(log types.Log)) *FeeQuoterInterface_ParseLog_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(types.Log)) + }) + return _c +} + +func (_c *FeeQuoterInterface_ParseLog_Call) Return(_a0 generated.AbigenLog, _a1 error) *FeeQuoterInterface_ParseLog_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_ParseLog_Call) RunAndReturn(run func(types.Log) (generated.AbigenLog, error)) *FeeQuoterInterface_ParseLog_Call { + _c.Call.Return(run) + return _c +} + +// ParseOwnershipTransferRequested provides a mock function with given fields: log +func (_m *FeeQuoterInterface) ParseOwnershipTransferRequested(log types.Log) (*fee_quoter.FeeQuoterOwnershipTransferRequested, error) { + ret := _m.Called(log) + + if len(ret) == 0 { + panic("no return value specified for ParseOwnershipTransferRequested") + } + + var r0 *fee_quoter.FeeQuoterOwnershipTransferRequested + var r1 error + if rf, ok := ret.Get(0).(func(types.Log) (*fee_quoter.FeeQuoterOwnershipTransferRequested, error)); ok { + return rf(log) + } + if rf, ok := ret.Get(0).(func(types.Log) *fee_quoter.FeeQuoterOwnershipTransferRequested); ok { + r0 = rf(log) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*fee_quoter.FeeQuoterOwnershipTransferRequested) + } + } + + if rf, ok := ret.Get(1).(func(types.Log) error); ok { + r1 = rf(log) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_ParseOwnershipTransferRequested_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParseOwnershipTransferRequested' +type FeeQuoterInterface_ParseOwnershipTransferRequested_Call struct { + *mock.Call +} + +// ParseOwnershipTransferRequested is a helper method to define mock.On call +// - log types.Log +func (_e *FeeQuoterInterface_Expecter) ParseOwnershipTransferRequested(log interface{}) *FeeQuoterInterface_ParseOwnershipTransferRequested_Call { + return &FeeQuoterInterface_ParseOwnershipTransferRequested_Call{Call: _e.mock.On("ParseOwnershipTransferRequested", log)} +} + +func (_c *FeeQuoterInterface_ParseOwnershipTransferRequested_Call) Run(run func(log types.Log)) *FeeQuoterInterface_ParseOwnershipTransferRequested_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(types.Log)) + }) + return _c +} + +func (_c *FeeQuoterInterface_ParseOwnershipTransferRequested_Call) Return(_a0 *fee_quoter.FeeQuoterOwnershipTransferRequested, _a1 error) *FeeQuoterInterface_ParseOwnershipTransferRequested_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_ParseOwnershipTransferRequested_Call) RunAndReturn(run func(types.Log) (*fee_quoter.FeeQuoterOwnershipTransferRequested, error)) *FeeQuoterInterface_ParseOwnershipTransferRequested_Call { + _c.Call.Return(run) + return _c +} + +// ParseOwnershipTransferred provides a mock function with given fields: log +func (_m *FeeQuoterInterface) ParseOwnershipTransferred(log types.Log) (*fee_quoter.FeeQuoterOwnershipTransferred, error) { + ret := _m.Called(log) + + if len(ret) == 0 { + panic("no return value specified for ParseOwnershipTransferred") + } + + var r0 *fee_quoter.FeeQuoterOwnershipTransferred + var r1 error + if rf, ok := ret.Get(0).(func(types.Log) (*fee_quoter.FeeQuoterOwnershipTransferred, error)); ok { + return rf(log) + } + if rf, ok := ret.Get(0).(func(types.Log) *fee_quoter.FeeQuoterOwnershipTransferred); ok { + r0 = rf(log) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*fee_quoter.FeeQuoterOwnershipTransferred) + } + } + + if rf, ok := ret.Get(1).(func(types.Log) error); ok { + r1 = rf(log) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_ParseOwnershipTransferred_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParseOwnershipTransferred' +type FeeQuoterInterface_ParseOwnershipTransferred_Call struct { + *mock.Call +} + +// ParseOwnershipTransferred is a helper method to define mock.On call +// - log types.Log +func (_e *FeeQuoterInterface_Expecter) ParseOwnershipTransferred(log interface{}) *FeeQuoterInterface_ParseOwnershipTransferred_Call { + return &FeeQuoterInterface_ParseOwnershipTransferred_Call{Call: _e.mock.On("ParseOwnershipTransferred", log)} +} + +func (_c *FeeQuoterInterface_ParseOwnershipTransferred_Call) Run(run func(log types.Log)) *FeeQuoterInterface_ParseOwnershipTransferred_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(types.Log)) + }) + return _c +} + +func (_c *FeeQuoterInterface_ParseOwnershipTransferred_Call) Return(_a0 *fee_quoter.FeeQuoterOwnershipTransferred, _a1 error) *FeeQuoterInterface_ParseOwnershipTransferred_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_ParseOwnershipTransferred_Call) RunAndReturn(run func(types.Log) (*fee_quoter.FeeQuoterOwnershipTransferred, error)) *FeeQuoterInterface_ParseOwnershipTransferred_Call { + _c.Call.Return(run) + return _c +} + +// ParsePremiumMultiplierWeiPerEthUpdated provides a mock function with given fields: log +func (_m *FeeQuoterInterface) ParsePremiumMultiplierWeiPerEthUpdated(log types.Log) (*fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthUpdated, error) { + ret := _m.Called(log) + + if len(ret) == 0 { + panic("no return value specified for ParsePremiumMultiplierWeiPerEthUpdated") + } + + var r0 *fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthUpdated + var r1 error + if rf, ok := ret.Get(0).(func(types.Log) (*fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthUpdated, error)); ok { + return rf(log) + } + if rf, ok := ret.Get(0).(func(types.Log) *fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthUpdated); ok { + r0 = rf(log) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthUpdated) + } + } + + if rf, ok := ret.Get(1).(func(types.Log) error); ok { + r1 = rf(log) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_ParsePremiumMultiplierWeiPerEthUpdated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParsePremiumMultiplierWeiPerEthUpdated' +type FeeQuoterInterface_ParsePremiumMultiplierWeiPerEthUpdated_Call struct { + *mock.Call +} + +// ParsePremiumMultiplierWeiPerEthUpdated is a helper method to define mock.On call +// - log types.Log +func (_e *FeeQuoterInterface_Expecter) ParsePremiumMultiplierWeiPerEthUpdated(log interface{}) *FeeQuoterInterface_ParsePremiumMultiplierWeiPerEthUpdated_Call { + return &FeeQuoterInterface_ParsePremiumMultiplierWeiPerEthUpdated_Call{Call: _e.mock.On("ParsePremiumMultiplierWeiPerEthUpdated", log)} +} + +func (_c *FeeQuoterInterface_ParsePremiumMultiplierWeiPerEthUpdated_Call) Run(run func(log types.Log)) *FeeQuoterInterface_ParsePremiumMultiplierWeiPerEthUpdated_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(types.Log)) + }) + return _c +} + +func (_c *FeeQuoterInterface_ParsePremiumMultiplierWeiPerEthUpdated_Call) Return(_a0 *fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthUpdated, _a1 error) *FeeQuoterInterface_ParsePremiumMultiplierWeiPerEthUpdated_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_ParsePremiumMultiplierWeiPerEthUpdated_Call) RunAndReturn(run func(types.Log) (*fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthUpdated, error)) *FeeQuoterInterface_ParsePremiumMultiplierWeiPerEthUpdated_Call { + _c.Call.Return(run) + return _c +} + +// ParsePriceFeedPerTokenUpdated provides a mock function with given fields: log +func (_m *FeeQuoterInterface) ParsePriceFeedPerTokenUpdated(log types.Log) (*fee_quoter.FeeQuoterPriceFeedPerTokenUpdated, error) { + ret := _m.Called(log) + + if len(ret) == 0 { + panic("no return value specified for ParsePriceFeedPerTokenUpdated") + } + + var r0 *fee_quoter.FeeQuoterPriceFeedPerTokenUpdated + var r1 error + if rf, ok := ret.Get(0).(func(types.Log) (*fee_quoter.FeeQuoterPriceFeedPerTokenUpdated, error)); ok { + return rf(log) + } + if rf, ok := ret.Get(0).(func(types.Log) *fee_quoter.FeeQuoterPriceFeedPerTokenUpdated); ok { + r0 = rf(log) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*fee_quoter.FeeQuoterPriceFeedPerTokenUpdated) + } + } + + if rf, ok := ret.Get(1).(func(types.Log) error); ok { + r1 = rf(log) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_ParsePriceFeedPerTokenUpdated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParsePriceFeedPerTokenUpdated' +type FeeQuoterInterface_ParsePriceFeedPerTokenUpdated_Call struct { + *mock.Call +} + +// ParsePriceFeedPerTokenUpdated is a helper method to define mock.On call +// - log types.Log +func (_e *FeeQuoterInterface_Expecter) ParsePriceFeedPerTokenUpdated(log interface{}) *FeeQuoterInterface_ParsePriceFeedPerTokenUpdated_Call { + return &FeeQuoterInterface_ParsePriceFeedPerTokenUpdated_Call{Call: _e.mock.On("ParsePriceFeedPerTokenUpdated", log)} +} + +func (_c *FeeQuoterInterface_ParsePriceFeedPerTokenUpdated_Call) Run(run func(log types.Log)) *FeeQuoterInterface_ParsePriceFeedPerTokenUpdated_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(types.Log)) + }) + return _c +} + +func (_c *FeeQuoterInterface_ParsePriceFeedPerTokenUpdated_Call) Return(_a0 *fee_quoter.FeeQuoterPriceFeedPerTokenUpdated, _a1 error) *FeeQuoterInterface_ParsePriceFeedPerTokenUpdated_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_ParsePriceFeedPerTokenUpdated_Call) RunAndReturn(run func(types.Log) (*fee_quoter.FeeQuoterPriceFeedPerTokenUpdated, error)) *FeeQuoterInterface_ParsePriceFeedPerTokenUpdated_Call { + _c.Call.Return(run) + return _c +} + +// ParseReportPermissionSet provides a mock function with given fields: log +func (_m *FeeQuoterInterface) ParseReportPermissionSet(log types.Log) (*fee_quoter.FeeQuoterReportPermissionSet, error) { + ret := _m.Called(log) + + if len(ret) == 0 { + panic("no return value specified for ParseReportPermissionSet") + } + + var r0 *fee_quoter.FeeQuoterReportPermissionSet + var r1 error + if rf, ok := ret.Get(0).(func(types.Log) (*fee_quoter.FeeQuoterReportPermissionSet, error)); ok { + return rf(log) + } + if rf, ok := ret.Get(0).(func(types.Log) *fee_quoter.FeeQuoterReportPermissionSet); ok { + r0 = rf(log) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*fee_quoter.FeeQuoterReportPermissionSet) + } + } + + if rf, ok := ret.Get(1).(func(types.Log) error); ok { + r1 = rf(log) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_ParseReportPermissionSet_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParseReportPermissionSet' +type FeeQuoterInterface_ParseReportPermissionSet_Call struct { + *mock.Call +} + +// ParseReportPermissionSet is a helper method to define mock.On call +// - log types.Log +func (_e *FeeQuoterInterface_Expecter) ParseReportPermissionSet(log interface{}) *FeeQuoterInterface_ParseReportPermissionSet_Call { + return &FeeQuoterInterface_ParseReportPermissionSet_Call{Call: _e.mock.On("ParseReportPermissionSet", log)} +} + +func (_c *FeeQuoterInterface_ParseReportPermissionSet_Call) Run(run func(log types.Log)) *FeeQuoterInterface_ParseReportPermissionSet_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(types.Log)) + }) + return _c +} + +func (_c *FeeQuoterInterface_ParseReportPermissionSet_Call) Return(_a0 *fee_quoter.FeeQuoterReportPermissionSet, _a1 error) *FeeQuoterInterface_ParseReportPermissionSet_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_ParseReportPermissionSet_Call) RunAndReturn(run func(types.Log) (*fee_quoter.FeeQuoterReportPermissionSet, error)) *FeeQuoterInterface_ParseReportPermissionSet_Call { + _c.Call.Return(run) + return _c +} + +// ParseTokenTransferFeeConfigDeleted provides a mock function with given fields: log +func (_m *FeeQuoterInterface) ParseTokenTransferFeeConfigDeleted(log types.Log) (*fee_quoter.FeeQuoterTokenTransferFeeConfigDeleted, error) { + ret := _m.Called(log) + + if len(ret) == 0 { + panic("no return value specified for ParseTokenTransferFeeConfigDeleted") + } + + var r0 *fee_quoter.FeeQuoterTokenTransferFeeConfigDeleted + var r1 error + if rf, ok := ret.Get(0).(func(types.Log) (*fee_quoter.FeeQuoterTokenTransferFeeConfigDeleted, error)); ok { + return rf(log) + } + if rf, ok := ret.Get(0).(func(types.Log) *fee_quoter.FeeQuoterTokenTransferFeeConfigDeleted); ok { + r0 = rf(log) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*fee_quoter.FeeQuoterTokenTransferFeeConfigDeleted) + } + } + + if rf, ok := ret.Get(1).(func(types.Log) error); ok { + r1 = rf(log) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_ParseTokenTransferFeeConfigDeleted_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParseTokenTransferFeeConfigDeleted' +type FeeQuoterInterface_ParseTokenTransferFeeConfigDeleted_Call struct { + *mock.Call +} + +// ParseTokenTransferFeeConfigDeleted is a helper method to define mock.On call +// - log types.Log +func (_e *FeeQuoterInterface_Expecter) ParseTokenTransferFeeConfigDeleted(log interface{}) *FeeQuoterInterface_ParseTokenTransferFeeConfigDeleted_Call { + return &FeeQuoterInterface_ParseTokenTransferFeeConfigDeleted_Call{Call: _e.mock.On("ParseTokenTransferFeeConfigDeleted", log)} +} + +func (_c *FeeQuoterInterface_ParseTokenTransferFeeConfigDeleted_Call) Run(run func(log types.Log)) *FeeQuoterInterface_ParseTokenTransferFeeConfigDeleted_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(types.Log)) + }) + return _c +} + +func (_c *FeeQuoterInterface_ParseTokenTransferFeeConfigDeleted_Call) Return(_a0 *fee_quoter.FeeQuoterTokenTransferFeeConfigDeleted, _a1 error) *FeeQuoterInterface_ParseTokenTransferFeeConfigDeleted_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_ParseTokenTransferFeeConfigDeleted_Call) RunAndReturn(run func(types.Log) (*fee_quoter.FeeQuoterTokenTransferFeeConfigDeleted, error)) *FeeQuoterInterface_ParseTokenTransferFeeConfigDeleted_Call { + _c.Call.Return(run) + return _c +} + +// ParseTokenTransferFeeConfigUpdated provides a mock function with given fields: log +func (_m *FeeQuoterInterface) ParseTokenTransferFeeConfigUpdated(log types.Log) (*fee_quoter.FeeQuoterTokenTransferFeeConfigUpdated, error) { + ret := _m.Called(log) + + if len(ret) == 0 { + panic("no return value specified for ParseTokenTransferFeeConfigUpdated") + } + + var r0 *fee_quoter.FeeQuoterTokenTransferFeeConfigUpdated + var r1 error + if rf, ok := ret.Get(0).(func(types.Log) (*fee_quoter.FeeQuoterTokenTransferFeeConfigUpdated, error)); ok { + return rf(log) + } + if rf, ok := ret.Get(0).(func(types.Log) *fee_quoter.FeeQuoterTokenTransferFeeConfigUpdated); ok { + r0 = rf(log) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*fee_quoter.FeeQuoterTokenTransferFeeConfigUpdated) + } + } + + if rf, ok := ret.Get(1).(func(types.Log) error); ok { + r1 = rf(log) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_ParseTokenTransferFeeConfigUpdated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParseTokenTransferFeeConfigUpdated' +type FeeQuoterInterface_ParseTokenTransferFeeConfigUpdated_Call struct { + *mock.Call +} + +// ParseTokenTransferFeeConfigUpdated is a helper method to define mock.On call +// - log types.Log +func (_e *FeeQuoterInterface_Expecter) ParseTokenTransferFeeConfigUpdated(log interface{}) *FeeQuoterInterface_ParseTokenTransferFeeConfigUpdated_Call { + return &FeeQuoterInterface_ParseTokenTransferFeeConfigUpdated_Call{Call: _e.mock.On("ParseTokenTransferFeeConfigUpdated", log)} +} + +func (_c *FeeQuoterInterface_ParseTokenTransferFeeConfigUpdated_Call) Run(run func(log types.Log)) *FeeQuoterInterface_ParseTokenTransferFeeConfigUpdated_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(types.Log)) + }) + return _c +} + +func (_c *FeeQuoterInterface_ParseTokenTransferFeeConfigUpdated_Call) Return(_a0 *fee_quoter.FeeQuoterTokenTransferFeeConfigUpdated, _a1 error) *FeeQuoterInterface_ParseTokenTransferFeeConfigUpdated_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_ParseTokenTransferFeeConfigUpdated_Call) RunAndReturn(run func(types.Log) (*fee_quoter.FeeQuoterTokenTransferFeeConfigUpdated, error)) *FeeQuoterInterface_ParseTokenTransferFeeConfigUpdated_Call { + _c.Call.Return(run) + return _c +} + +// ParseUsdPerTokenUpdated provides a mock function with given fields: log +func (_m *FeeQuoterInterface) ParseUsdPerTokenUpdated(log types.Log) (*fee_quoter.FeeQuoterUsdPerTokenUpdated, error) { + ret := _m.Called(log) + + if len(ret) == 0 { + panic("no return value specified for ParseUsdPerTokenUpdated") + } + + var r0 *fee_quoter.FeeQuoterUsdPerTokenUpdated + var r1 error + if rf, ok := ret.Get(0).(func(types.Log) (*fee_quoter.FeeQuoterUsdPerTokenUpdated, error)); ok { + return rf(log) + } + if rf, ok := ret.Get(0).(func(types.Log) *fee_quoter.FeeQuoterUsdPerTokenUpdated); ok { + r0 = rf(log) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*fee_quoter.FeeQuoterUsdPerTokenUpdated) + } + } + + if rf, ok := ret.Get(1).(func(types.Log) error); ok { + r1 = rf(log) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_ParseUsdPerTokenUpdated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParseUsdPerTokenUpdated' +type FeeQuoterInterface_ParseUsdPerTokenUpdated_Call struct { + *mock.Call +} + +// ParseUsdPerTokenUpdated is a helper method to define mock.On call +// - log types.Log +func (_e *FeeQuoterInterface_Expecter) ParseUsdPerTokenUpdated(log interface{}) *FeeQuoterInterface_ParseUsdPerTokenUpdated_Call { + return &FeeQuoterInterface_ParseUsdPerTokenUpdated_Call{Call: _e.mock.On("ParseUsdPerTokenUpdated", log)} +} + +func (_c *FeeQuoterInterface_ParseUsdPerTokenUpdated_Call) Run(run func(log types.Log)) *FeeQuoterInterface_ParseUsdPerTokenUpdated_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(types.Log)) + }) + return _c +} + +func (_c *FeeQuoterInterface_ParseUsdPerTokenUpdated_Call) Return(_a0 *fee_quoter.FeeQuoterUsdPerTokenUpdated, _a1 error) *FeeQuoterInterface_ParseUsdPerTokenUpdated_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_ParseUsdPerTokenUpdated_Call) RunAndReturn(run func(types.Log) (*fee_quoter.FeeQuoterUsdPerTokenUpdated, error)) *FeeQuoterInterface_ParseUsdPerTokenUpdated_Call { + _c.Call.Return(run) + return _c +} + +// ParseUsdPerUnitGasUpdated provides a mock function with given fields: log +func (_m *FeeQuoterInterface) ParseUsdPerUnitGasUpdated(log types.Log) (*fee_quoter.FeeQuoterUsdPerUnitGasUpdated, error) { + ret := _m.Called(log) + + if len(ret) == 0 { + panic("no return value specified for ParseUsdPerUnitGasUpdated") + } + + var r0 *fee_quoter.FeeQuoterUsdPerUnitGasUpdated + var r1 error + if rf, ok := ret.Get(0).(func(types.Log) (*fee_quoter.FeeQuoterUsdPerUnitGasUpdated, error)); ok { + return rf(log) + } + if rf, ok := ret.Get(0).(func(types.Log) *fee_quoter.FeeQuoterUsdPerUnitGasUpdated); ok { + r0 = rf(log) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*fee_quoter.FeeQuoterUsdPerUnitGasUpdated) + } + } + + if rf, ok := ret.Get(1).(func(types.Log) error); ok { + r1 = rf(log) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_ParseUsdPerUnitGasUpdated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParseUsdPerUnitGasUpdated' +type FeeQuoterInterface_ParseUsdPerUnitGasUpdated_Call struct { + *mock.Call +} + +// ParseUsdPerUnitGasUpdated is a helper method to define mock.On call +// - log types.Log +func (_e *FeeQuoterInterface_Expecter) ParseUsdPerUnitGasUpdated(log interface{}) *FeeQuoterInterface_ParseUsdPerUnitGasUpdated_Call { + return &FeeQuoterInterface_ParseUsdPerUnitGasUpdated_Call{Call: _e.mock.On("ParseUsdPerUnitGasUpdated", log)} +} + +func (_c *FeeQuoterInterface_ParseUsdPerUnitGasUpdated_Call) Run(run func(log types.Log)) *FeeQuoterInterface_ParseUsdPerUnitGasUpdated_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(types.Log)) + }) + return _c +} + +func (_c *FeeQuoterInterface_ParseUsdPerUnitGasUpdated_Call) Return(_a0 *fee_quoter.FeeQuoterUsdPerUnitGasUpdated, _a1 error) *FeeQuoterInterface_ParseUsdPerUnitGasUpdated_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_ParseUsdPerUnitGasUpdated_Call) RunAndReturn(run func(types.Log) (*fee_quoter.FeeQuoterUsdPerUnitGasUpdated, error)) *FeeQuoterInterface_ParseUsdPerUnitGasUpdated_Call { + _c.Call.Return(run) + return _c +} + +// ProcessMessageArgs provides a mock function with given fields: opts, destChainSelector, feeToken, feeTokenAmount, extraArgs +func (_m *FeeQuoterInterface) ProcessMessageArgs(opts *bind.CallOpts, destChainSelector uint64, feeToken common.Address, feeTokenAmount *big.Int, extraArgs []byte) (fee_quoter.ProcessMessageArgs, error) { + ret := _m.Called(opts, destChainSelector, feeToken, feeTokenAmount, extraArgs) + + if len(ret) == 0 { + panic("no return value specified for ProcessMessageArgs") + } + + var r0 fee_quoter.ProcessMessageArgs + var r1 error + if rf, ok := ret.Get(0).(func(*bind.CallOpts, uint64, common.Address, *big.Int, []byte) (fee_quoter.ProcessMessageArgs, error)); ok { + return rf(opts, destChainSelector, feeToken, feeTokenAmount, extraArgs) + } + if rf, ok := ret.Get(0).(func(*bind.CallOpts, uint64, common.Address, *big.Int, []byte) fee_quoter.ProcessMessageArgs); ok { + r0 = rf(opts, destChainSelector, feeToken, feeTokenAmount, extraArgs) + } else { + r0 = ret.Get(0).(fee_quoter.ProcessMessageArgs) + } + + if rf, ok := ret.Get(1).(func(*bind.CallOpts, uint64, common.Address, *big.Int, []byte) error); ok { + r1 = rf(opts, destChainSelector, feeToken, feeTokenAmount, extraArgs) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_ProcessMessageArgs_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ProcessMessageArgs' +type FeeQuoterInterface_ProcessMessageArgs_Call struct { + *mock.Call +} + +// ProcessMessageArgs is a helper method to define mock.On call +// - opts *bind.CallOpts +// - destChainSelector uint64 +// - feeToken common.Address +// - feeTokenAmount *big.Int +// - extraArgs []byte +func (_e *FeeQuoterInterface_Expecter) ProcessMessageArgs(opts interface{}, destChainSelector interface{}, feeToken interface{}, feeTokenAmount interface{}, extraArgs interface{}) *FeeQuoterInterface_ProcessMessageArgs_Call { + return &FeeQuoterInterface_ProcessMessageArgs_Call{Call: _e.mock.On("ProcessMessageArgs", opts, destChainSelector, feeToken, feeTokenAmount, extraArgs)} +} + +func (_c *FeeQuoterInterface_ProcessMessageArgs_Call) Run(run func(opts *bind.CallOpts, destChainSelector uint64, feeToken common.Address, feeTokenAmount *big.Int, extraArgs []byte)) *FeeQuoterInterface_ProcessMessageArgs_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.CallOpts), args[1].(uint64), args[2].(common.Address), args[3].(*big.Int), args[4].([]byte)) + }) + return _c +} + +func (_c *FeeQuoterInterface_ProcessMessageArgs_Call) Return(_a0 fee_quoter.ProcessMessageArgs, _a1 error) *FeeQuoterInterface_ProcessMessageArgs_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_ProcessMessageArgs_Call) RunAndReturn(run func(*bind.CallOpts, uint64, common.Address, *big.Int, []byte) (fee_quoter.ProcessMessageArgs, error)) *FeeQuoterInterface_ProcessMessageArgs_Call { + _c.Call.Return(run) + return _c +} + +// ProcessPoolReturnData provides a mock function with given fields: opts, destChainSelector, rampTokenAmounts, sourceTokenAmounts +func (_m *FeeQuoterInterface) ProcessPoolReturnData(opts *bind.CallOpts, destChainSelector uint64, rampTokenAmounts []fee_quoter.InternalRampTokenAmount, sourceTokenAmounts []fee_quoter.ClientEVMTokenAmount) ([][]byte, error) { + ret := _m.Called(opts, destChainSelector, rampTokenAmounts, sourceTokenAmounts) + + if len(ret) == 0 { + panic("no return value specified for ProcessPoolReturnData") + } + + var r0 [][]byte + var r1 error + if rf, ok := ret.Get(0).(func(*bind.CallOpts, uint64, []fee_quoter.InternalRampTokenAmount, []fee_quoter.ClientEVMTokenAmount) ([][]byte, error)); ok { + return rf(opts, destChainSelector, rampTokenAmounts, sourceTokenAmounts) + } + if rf, ok := ret.Get(0).(func(*bind.CallOpts, uint64, []fee_quoter.InternalRampTokenAmount, []fee_quoter.ClientEVMTokenAmount) [][]byte); ok { + r0 = rf(opts, destChainSelector, rampTokenAmounts, sourceTokenAmounts) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([][]byte) + } + } + + if rf, ok := ret.Get(1).(func(*bind.CallOpts, uint64, []fee_quoter.InternalRampTokenAmount, []fee_quoter.ClientEVMTokenAmount) error); ok { + r1 = rf(opts, destChainSelector, rampTokenAmounts, sourceTokenAmounts) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_ProcessPoolReturnData_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ProcessPoolReturnData' +type FeeQuoterInterface_ProcessPoolReturnData_Call struct { + *mock.Call +} + +// ProcessPoolReturnData is a helper method to define mock.On call +// - opts *bind.CallOpts +// - destChainSelector uint64 +// - rampTokenAmounts []fee_quoter.InternalRampTokenAmount +// - sourceTokenAmounts []fee_quoter.ClientEVMTokenAmount +func (_e *FeeQuoterInterface_Expecter) ProcessPoolReturnData(opts interface{}, destChainSelector interface{}, rampTokenAmounts interface{}, sourceTokenAmounts interface{}) *FeeQuoterInterface_ProcessPoolReturnData_Call { + return &FeeQuoterInterface_ProcessPoolReturnData_Call{Call: _e.mock.On("ProcessPoolReturnData", opts, destChainSelector, rampTokenAmounts, sourceTokenAmounts)} +} + +func (_c *FeeQuoterInterface_ProcessPoolReturnData_Call) Run(run func(opts *bind.CallOpts, destChainSelector uint64, rampTokenAmounts []fee_quoter.InternalRampTokenAmount, sourceTokenAmounts []fee_quoter.ClientEVMTokenAmount)) *FeeQuoterInterface_ProcessPoolReturnData_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.CallOpts), args[1].(uint64), args[2].([]fee_quoter.InternalRampTokenAmount), args[3].([]fee_quoter.ClientEVMTokenAmount)) + }) + return _c +} + +func (_c *FeeQuoterInterface_ProcessPoolReturnData_Call) Return(_a0 [][]byte, _a1 error) *FeeQuoterInterface_ProcessPoolReturnData_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_ProcessPoolReturnData_Call) RunAndReturn(run func(*bind.CallOpts, uint64, []fee_quoter.InternalRampTokenAmount, []fee_quoter.ClientEVMTokenAmount) ([][]byte, error)) *FeeQuoterInterface_ProcessPoolReturnData_Call { + _c.Call.Return(run) + return _c +} + +// SetReportPermissions provides a mock function with given fields: opts, permissions +func (_m *FeeQuoterInterface) SetReportPermissions(opts *bind.TransactOpts, permissions []fee_quoter.KeystoneFeedsPermissionHandlerPermission) (*types.Transaction, error) { + ret := _m.Called(opts, permissions) + + if len(ret) == 0 { + panic("no return value specified for SetReportPermissions") + } + + var r0 *types.Transaction + var r1 error + if rf, ok := ret.Get(0).(func(*bind.TransactOpts, []fee_quoter.KeystoneFeedsPermissionHandlerPermission) (*types.Transaction, error)); ok { + return rf(opts, permissions) + } + if rf, ok := ret.Get(0).(func(*bind.TransactOpts, []fee_quoter.KeystoneFeedsPermissionHandlerPermission) *types.Transaction); ok { + r0 = rf(opts, permissions) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.Transaction) + } + } + + if rf, ok := ret.Get(1).(func(*bind.TransactOpts, []fee_quoter.KeystoneFeedsPermissionHandlerPermission) error); ok { + r1 = rf(opts, permissions) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_SetReportPermissions_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetReportPermissions' +type FeeQuoterInterface_SetReportPermissions_Call struct { + *mock.Call +} + +// SetReportPermissions is a helper method to define mock.On call +// - opts *bind.TransactOpts +// - permissions []fee_quoter.KeystoneFeedsPermissionHandlerPermission +func (_e *FeeQuoterInterface_Expecter) SetReportPermissions(opts interface{}, permissions interface{}) *FeeQuoterInterface_SetReportPermissions_Call { + return &FeeQuoterInterface_SetReportPermissions_Call{Call: _e.mock.On("SetReportPermissions", opts, permissions)} +} + +func (_c *FeeQuoterInterface_SetReportPermissions_Call) Run(run func(opts *bind.TransactOpts, permissions []fee_quoter.KeystoneFeedsPermissionHandlerPermission)) *FeeQuoterInterface_SetReportPermissions_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.TransactOpts), args[1].([]fee_quoter.KeystoneFeedsPermissionHandlerPermission)) + }) + return _c +} + +func (_c *FeeQuoterInterface_SetReportPermissions_Call) Return(_a0 *types.Transaction, _a1 error) *FeeQuoterInterface_SetReportPermissions_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_SetReportPermissions_Call) RunAndReturn(run func(*bind.TransactOpts, []fee_quoter.KeystoneFeedsPermissionHandlerPermission) (*types.Transaction, error)) *FeeQuoterInterface_SetReportPermissions_Call { + _c.Call.Return(run) + return _c +} + +// TransferOwnership provides a mock function with given fields: opts, to +func (_m *FeeQuoterInterface) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { + ret := _m.Called(opts, to) + + if len(ret) == 0 { + panic("no return value specified for TransferOwnership") + } + + var r0 *types.Transaction + var r1 error + if rf, ok := ret.Get(0).(func(*bind.TransactOpts, common.Address) (*types.Transaction, error)); ok { + return rf(opts, to) + } + if rf, ok := ret.Get(0).(func(*bind.TransactOpts, common.Address) *types.Transaction); ok { + r0 = rf(opts, to) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.Transaction) + } + } + + if rf, ok := ret.Get(1).(func(*bind.TransactOpts, common.Address) error); ok { + r1 = rf(opts, to) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_TransferOwnership_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'TransferOwnership' +type FeeQuoterInterface_TransferOwnership_Call struct { + *mock.Call +} + +// TransferOwnership is a helper method to define mock.On call +// - opts *bind.TransactOpts +// - to common.Address +func (_e *FeeQuoterInterface_Expecter) TransferOwnership(opts interface{}, to interface{}) *FeeQuoterInterface_TransferOwnership_Call { + return &FeeQuoterInterface_TransferOwnership_Call{Call: _e.mock.On("TransferOwnership", opts, to)} +} + +func (_c *FeeQuoterInterface_TransferOwnership_Call) Run(run func(opts *bind.TransactOpts, to common.Address)) *FeeQuoterInterface_TransferOwnership_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.TransactOpts), args[1].(common.Address)) + }) + return _c +} + +func (_c *FeeQuoterInterface_TransferOwnership_Call) Return(_a0 *types.Transaction, _a1 error) *FeeQuoterInterface_TransferOwnership_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_TransferOwnership_Call) RunAndReturn(run func(*bind.TransactOpts, common.Address) (*types.Transaction, error)) *FeeQuoterInterface_TransferOwnership_Call { + _c.Call.Return(run) + return _c +} + +// TypeAndVersion provides a mock function with given fields: opts +func (_m *FeeQuoterInterface) TypeAndVersion(opts *bind.CallOpts) (string, error) { + ret := _m.Called(opts) + + if len(ret) == 0 { + panic("no return value specified for TypeAndVersion") + } + + var r0 string + var r1 error + if rf, ok := ret.Get(0).(func(*bind.CallOpts) (string, error)); ok { + return rf(opts) + } + if rf, ok := ret.Get(0).(func(*bind.CallOpts) string); ok { + r0 = rf(opts) + } else { + r0 = ret.Get(0).(string) + } + + if rf, ok := ret.Get(1).(func(*bind.CallOpts) error); ok { + r1 = rf(opts) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_TypeAndVersion_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'TypeAndVersion' +type FeeQuoterInterface_TypeAndVersion_Call struct { + *mock.Call +} + +// TypeAndVersion is a helper method to define mock.On call +// - opts *bind.CallOpts +func (_e *FeeQuoterInterface_Expecter) TypeAndVersion(opts interface{}) *FeeQuoterInterface_TypeAndVersion_Call { + return &FeeQuoterInterface_TypeAndVersion_Call{Call: _e.mock.On("TypeAndVersion", opts)} +} + +func (_c *FeeQuoterInterface_TypeAndVersion_Call) Run(run func(opts *bind.CallOpts)) *FeeQuoterInterface_TypeAndVersion_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.CallOpts)) + }) + return _c +} + +func (_c *FeeQuoterInterface_TypeAndVersion_Call) Return(_a0 string, _a1 error) *FeeQuoterInterface_TypeAndVersion_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_TypeAndVersion_Call) RunAndReturn(run func(*bind.CallOpts) (string, error)) *FeeQuoterInterface_TypeAndVersion_Call { + _c.Call.Return(run) + return _c +} + +// UpdatePrices provides a mock function with given fields: opts, priceUpdates +func (_m *FeeQuoterInterface) UpdatePrices(opts *bind.TransactOpts, priceUpdates fee_quoter.InternalPriceUpdates) (*types.Transaction, error) { + ret := _m.Called(opts, priceUpdates) + + if len(ret) == 0 { + panic("no return value specified for UpdatePrices") + } + + var r0 *types.Transaction + var r1 error + if rf, ok := ret.Get(0).(func(*bind.TransactOpts, fee_quoter.InternalPriceUpdates) (*types.Transaction, error)); ok { + return rf(opts, priceUpdates) + } + if rf, ok := ret.Get(0).(func(*bind.TransactOpts, fee_quoter.InternalPriceUpdates) *types.Transaction); ok { + r0 = rf(opts, priceUpdates) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.Transaction) + } + } + + if rf, ok := ret.Get(1).(func(*bind.TransactOpts, fee_quoter.InternalPriceUpdates) error); ok { + r1 = rf(opts, priceUpdates) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_UpdatePrices_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdatePrices' +type FeeQuoterInterface_UpdatePrices_Call struct { + *mock.Call +} + +// UpdatePrices is a helper method to define mock.On call +// - opts *bind.TransactOpts +// - priceUpdates fee_quoter.InternalPriceUpdates +func (_e *FeeQuoterInterface_Expecter) UpdatePrices(opts interface{}, priceUpdates interface{}) *FeeQuoterInterface_UpdatePrices_Call { + return &FeeQuoterInterface_UpdatePrices_Call{Call: _e.mock.On("UpdatePrices", opts, priceUpdates)} +} + +func (_c *FeeQuoterInterface_UpdatePrices_Call) Run(run func(opts *bind.TransactOpts, priceUpdates fee_quoter.InternalPriceUpdates)) *FeeQuoterInterface_UpdatePrices_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.TransactOpts), args[1].(fee_quoter.InternalPriceUpdates)) + }) + return _c +} + +func (_c *FeeQuoterInterface_UpdatePrices_Call) Return(_a0 *types.Transaction, _a1 error) *FeeQuoterInterface_UpdatePrices_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_UpdatePrices_Call) RunAndReturn(run func(*bind.TransactOpts, fee_quoter.InternalPriceUpdates) (*types.Transaction, error)) *FeeQuoterInterface_UpdatePrices_Call { + _c.Call.Return(run) + return _c +} + +// UpdateTokenPriceFeeds provides a mock function with given fields: opts, tokenPriceFeedUpdates +func (_m *FeeQuoterInterface) UpdateTokenPriceFeeds(opts *bind.TransactOpts, tokenPriceFeedUpdates []fee_quoter.FeeQuoterTokenPriceFeedUpdate) (*types.Transaction, error) { + ret := _m.Called(opts, tokenPriceFeedUpdates) + + if len(ret) == 0 { + panic("no return value specified for UpdateTokenPriceFeeds") + } + + var r0 *types.Transaction + var r1 error + if rf, ok := ret.Get(0).(func(*bind.TransactOpts, []fee_quoter.FeeQuoterTokenPriceFeedUpdate) (*types.Transaction, error)); ok { + return rf(opts, tokenPriceFeedUpdates) + } + if rf, ok := ret.Get(0).(func(*bind.TransactOpts, []fee_quoter.FeeQuoterTokenPriceFeedUpdate) *types.Transaction); ok { + r0 = rf(opts, tokenPriceFeedUpdates) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.Transaction) + } + } + + if rf, ok := ret.Get(1).(func(*bind.TransactOpts, []fee_quoter.FeeQuoterTokenPriceFeedUpdate) error); ok { + r1 = rf(opts, tokenPriceFeedUpdates) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_UpdateTokenPriceFeeds_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateTokenPriceFeeds' +type FeeQuoterInterface_UpdateTokenPriceFeeds_Call struct { + *mock.Call +} + +// UpdateTokenPriceFeeds is a helper method to define mock.On call +// - opts *bind.TransactOpts +// - tokenPriceFeedUpdates []fee_quoter.FeeQuoterTokenPriceFeedUpdate +func (_e *FeeQuoterInterface_Expecter) UpdateTokenPriceFeeds(opts interface{}, tokenPriceFeedUpdates interface{}) *FeeQuoterInterface_UpdateTokenPriceFeeds_Call { + return &FeeQuoterInterface_UpdateTokenPriceFeeds_Call{Call: _e.mock.On("UpdateTokenPriceFeeds", opts, tokenPriceFeedUpdates)} +} + +func (_c *FeeQuoterInterface_UpdateTokenPriceFeeds_Call) Run(run func(opts *bind.TransactOpts, tokenPriceFeedUpdates []fee_quoter.FeeQuoterTokenPriceFeedUpdate)) *FeeQuoterInterface_UpdateTokenPriceFeeds_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.TransactOpts), args[1].([]fee_quoter.FeeQuoterTokenPriceFeedUpdate)) + }) + return _c +} + +func (_c *FeeQuoterInterface_UpdateTokenPriceFeeds_Call) Return(_a0 *types.Transaction, _a1 error) *FeeQuoterInterface_UpdateTokenPriceFeeds_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_UpdateTokenPriceFeeds_Call) RunAndReturn(run func(*bind.TransactOpts, []fee_quoter.FeeQuoterTokenPriceFeedUpdate) (*types.Transaction, error)) *FeeQuoterInterface_UpdateTokenPriceFeeds_Call { + _c.Call.Return(run) + return _c +} + +// WatchAuthorizedCallerAdded provides a mock function with given fields: opts, sink +func (_m *FeeQuoterInterface) WatchAuthorizedCallerAdded(opts *bind.WatchOpts, sink chan<- *fee_quoter.FeeQuoterAuthorizedCallerAdded) (event.Subscription, error) { + ret := _m.Called(opts, sink) + + if len(ret) == 0 { + panic("no return value specified for WatchAuthorizedCallerAdded") + } + + var r0 event.Subscription + var r1 error + if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterAuthorizedCallerAdded) (event.Subscription, error)); ok { + return rf(opts, sink) + } + if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterAuthorizedCallerAdded) event.Subscription); ok { + r0 = rf(opts, sink) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(event.Subscription) + } + } + + if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterAuthorizedCallerAdded) error); ok { + r1 = rf(opts, sink) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_WatchAuthorizedCallerAdded_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchAuthorizedCallerAdded' +type FeeQuoterInterface_WatchAuthorizedCallerAdded_Call struct { + *mock.Call +} + +// WatchAuthorizedCallerAdded is a helper method to define mock.On call +// - opts *bind.WatchOpts +// - sink chan<- *fee_quoter.FeeQuoterAuthorizedCallerAdded +func (_e *FeeQuoterInterface_Expecter) WatchAuthorizedCallerAdded(opts interface{}, sink interface{}) *FeeQuoterInterface_WatchAuthorizedCallerAdded_Call { + return &FeeQuoterInterface_WatchAuthorizedCallerAdded_Call{Call: _e.mock.On("WatchAuthorizedCallerAdded", opts, sink)} +} + +func (_c *FeeQuoterInterface_WatchAuthorizedCallerAdded_Call) Run(run func(opts *bind.WatchOpts, sink chan<- *fee_quoter.FeeQuoterAuthorizedCallerAdded)) *FeeQuoterInterface_WatchAuthorizedCallerAdded_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.WatchOpts), args[1].(chan<- *fee_quoter.FeeQuoterAuthorizedCallerAdded)) + }) + return _c +} + +func (_c *FeeQuoterInterface_WatchAuthorizedCallerAdded_Call) Return(_a0 event.Subscription, _a1 error) *FeeQuoterInterface_WatchAuthorizedCallerAdded_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_WatchAuthorizedCallerAdded_Call) RunAndReturn(run func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterAuthorizedCallerAdded) (event.Subscription, error)) *FeeQuoterInterface_WatchAuthorizedCallerAdded_Call { + _c.Call.Return(run) + return _c +} + +// WatchAuthorizedCallerRemoved provides a mock function with given fields: opts, sink +func (_m *FeeQuoterInterface) WatchAuthorizedCallerRemoved(opts *bind.WatchOpts, sink chan<- *fee_quoter.FeeQuoterAuthorizedCallerRemoved) (event.Subscription, error) { + ret := _m.Called(opts, sink) + + if len(ret) == 0 { + panic("no return value specified for WatchAuthorizedCallerRemoved") + } + + var r0 event.Subscription + var r1 error + if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterAuthorizedCallerRemoved) (event.Subscription, error)); ok { + return rf(opts, sink) + } + if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterAuthorizedCallerRemoved) event.Subscription); ok { + r0 = rf(opts, sink) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(event.Subscription) + } + } + + if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterAuthorizedCallerRemoved) error); ok { + r1 = rf(opts, sink) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_WatchAuthorizedCallerRemoved_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchAuthorizedCallerRemoved' +type FeeQuoterInterface_WatchAuthorizedCallerRemoved_Call struct { + *mock.Call +} + +// WatchAuthorizedCallerRemoved is a helper method to define mock.On call +// - opts *bind.WatchOpts +// - sink chan<- *fee_quoter.FeeQuoterAuthorizedCallerRemoved +func (_e *FeeQuoterInterface_Expecter) WatchAuthorizedCallerRemoved(opts interface{}, sink interface{}) *FeeQuoterInterface_WatchAuthorizedCallerRemoved_Call { + return &FeeQuoterInterface_WatchAuthorizedCallerRemoved_Call{Call: _e.mock.On("WatchAuthorizedCallerRemoved", opts, sink)} +} + +func (_c *FeeQuoterInterface_WatchAuthorizedCallerRemoved_Call) Run(run func(opts *bind.WatchOpts, sink chan<- *fee_quoter.FeeQuoterAuthorizedCallerRemoved)) *FeeQuoterInterface_WatchAuthorizedCallerRemoved_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.WatchOpts), args[1].(chan<- *fee_quoter.FeeQuoterAuthorizedCallerRemoved)) + }) + return _c +} + +func (_c *FeeQuoterInterface_WatchAuthorizedCallerRemoved_Call) Return(_a0 event.Subscription, _a1 error) *FeeQuoterInterface_WatchAuthorizedCallerRemoved_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_WatchAuthorizedCallerRemoved_Call) RunAndReturn(run func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterAuthorizedCallerRemoved) (event.Subscription, error)) *FeeQuoterInterface_WatchAuthorizedCallerRemoved_Call { + _c.Call.Return(run) + return _c +} + +// WatchDestChainAdded provides a mock function with given fields: opts, sink, destChainSelector +func (_m *FeeQuoterInterface) WatchDestChainAdded(opts *bind.WatchOpts, sink chan<- *fee_quoter.FeeQuoterDestChainAdded, destChainSelector []uint64) (event.Subscription, error) { + ret := _m.Called(opts, sink, destChainSelector) + + if len(ret) == 0 { + panic("no return value specified for WatchDestChainAdded") + } + + var r0 event.Subscription + var r1 error + if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterDestChainAdded, []uint64) (event.Subscription, error)); ok { + return rf(opts, sink, destChainSelector) + } + if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterDestChainAdded, []uint64) event.Subscription); ok { + r0 = rf(opts, sink, destChainSelector) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(event.Subscription) + } + } + + if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterDestChainAdded, []uint64) error); ok { + r1 = rf(opts, sink, destChainSelector) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_WatchDestChainAdded_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchDestChainAdded' +type FeeQuoterInterface_WatchDestChainAdded_Call struct { + *mock.Call +} + +// WatchDestChainAdded is a helper method to define mock.On call +// - opts *bind.WatchOpts +// - sink chan<- *fee_quoter.FeeQuoterDestChainAdded +// - destChainSelector []uint64 +func (_e *FeeQuoterInterface_Expecter) WatchDestChainAdded(opts interface{}, sink interface{}, destChainSelector interface{}) *FeeQuoterInterface_WatchDestChainAdded_Call { + return &FeeQuoterInterface_WatchDestChainAdded_Call{Call: _e.mock.On("WatchDestChainAdded", opts, sink, destChainSelector)} +} + +func (_c *FeeQuoterInterface_WatchDestChainAdded_Call) Run(run func(opts *bind.WatchOpts, sink chan<- *fee_quoter.FeeQuoterDestChainAdded, destChainSelector []uint64)) *FeeQuoterInterface_WatchDestChainAdded_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.WatchOpts), args[1].(chan<- *fee_quoter.FeeQuoterDestChainAdded), args[2].([]uint64)) + }) + return _c +} + +func (_c *FeeQuoterInterface_WatchDestChainAdded_Call) Return(_a0 event.Subscription, _a1 error) *FeeQuoterInterface_WatchDestChainAdded_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_WatchDestChainAdded_Call) RunAndReturn(run func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterDestChainAdded, []uint64) (event.Subscription, error)) *FeeQuoterInterface_WatchDestChainAdded_Call { + _c.Call.Return(run) + return _c +} + +// WatchDestChainConfigUpdated provides a mock function with given fields: opts, sink, destChainSelector +func (_m *FeeQuoterInterface) WatchDestChainConfigUpdated(opts *bind.WatchOpts, sink chan<- *fee_quoter.FeeQuoterDestChainConfigUpdated, destChainSelector []uint64) (event.Subscription, error) { + ret := _m.Called(opts, sink, destChainSelector) + + if len(ret) == 0 { + panic("no return value specified for WatchDestChainConfigUpdated") + } + + var r0 event.Subscription + var r1 error + if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterDestChainConfigUpdated, []uint64) (event.Subscription, error)); ok { + return rf(opts, sink, destChainSelector) + } + if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterDestChainConfigUpdated, []uint64) event.Subscription); ok { + r0 = rf(opts, sink, destChainSelector) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(event.Subscription) + } + } + + if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterDestChainConfigUpdated, []uint64) error); ok { + r1 = rf(opts, sink, destChainSelector) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_WatchDestChainConfigUpdated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchDestChainConfigUpdated' +type FeeQuoterInterface_WatchDestChainConfigUpdated_Call struct { + *mock.Call +} + +// WatchDestChainConfigUpdated is a helper method to define mock.On call +// - opts *bind.WatchOpts +// - sink chan<- *fee_quoter.FeeQuoterDestChainConfigUpdated +// - destChainSelector []uint64 +func (_e *FeeQuoterInterface_Expecter) WatchDestChainConfigUpdated(opts interface{}, sink interface{}, destChainSelector interface{}) *FeeQuoterInterface_WatchDestChainConfigUpdated_Call { + return &FeeQuoterInterface_WatchDestChainConfigUpdated_Call{Call: _e.mock.On("WatchDestChainConfigUpdated", opts, sink, destChainSelector)} +} + +func (_c *FeeQuoterInterface_WatchDestChainConfigUpdated_Call) Run(run func(opts *bind.WatchOpts, sink chan<- *fee_quoter.FeeQuoterDestChainConfigUpdated, destChainSelector []uint64)) *FeeQuoterInterface_WatchDestChainConfigUpdated_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.WatchOpts), args[1].(chan<- *fee_quoter.FeeQuoterDestChainConfigUpdated), args[2].([]uint64)) + }) + return _c +} + +func (_c *FeeQuoterInterface_WatchDestChainConfigUpdated_Call) Return(_a0 event.Subscription, _a1 error) *FeeQuoterInterface_WatchDestChainConfigUpdated_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_WatchDestChainConfigUpdated_Call) RunAndReturn(run func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterDestChainConfigUpdated, []uint64) (event.Subscription, error)) *FeeQuoterInterface_WatchDestChainConfigUpdated_Call { + _c.Call.Return(run) + return _c +} + +// WatchFeeTokenAdded provides a mock function with given fields: opts, sink, feeToken +func (_m *FeeQuoterInterface) WatchFeeTokenAdded(opts *bind.WatchOpts, sink chan<- *fee_quoter.FeeQuoterFeeTokenAdded, feeToken []common.Address) (event.Subscription, error) { + ret := _m.Called(opts, sink, feeToken) + + if len(ret) == 0 { + panic("no return value specified for WatchFeeTokenAdded") + } + + var r0 event.Subscription + var r1 error + if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterFeeTokenAdded, []common.Address) (event.Subscription, error)); ok { + return rf(opts, sink, feeToken) + } + if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterFeeTokenAdded, []common.Address) event.Subscription); ok { + r0 = rf(opts, sink, feeToken) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(event.Subscription) + } + } + + if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterFeeTokenAdded, []common.Address) error); ok { + r1 = rf(opts, sink, feeToken) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_WatchFeeTokenAdded_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchFeeTokenAdded' +type FeeQuoterInterface_WatchFeeTokenAdded_Call struct { + *mock.Call +} + +// WatchFeeTokenAdded is a helper method to define mock.On call +// - opts *bind.WatchOpts +// - sink chan<- *fee_quoter.FeeQuoterFeeTokenAdded +// - feeToken []common.Address +func (_e *FeeQuoterInterface_Expecter) WatchFeeTokenAdded(opts interface{}, sink interface{}, feeToken interface{}) *FeeQuoterInterface_WatchFeeTokenAdded_Call { + return &FeeQuoterInterface_WatchFeeTokenAdded_Call{Call: _e.mock.On("WatchFeeTokenAdded", opts, sink, feeToken)} +} + +func (_c *FeeQuoterInterface_WatchFeeTokenAdded_Call) Run(run func(opts *bind.WatchOpts, sink chan<- *fee_quoter.FeeQuoterFeeTokenAdded, feeToken []common.Address)) *FeeQuoterInterface_WatchFeeTokenAdded_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.WatchOpts), args[1].(chan<- *fee_quoter.FeeQuoterFeeTokenAdded), args[2].([]common.Address)) + }) + return _c +} + +func (_c *FeeQuoterInterface_WatchFeeTokenAdded_Call) Return(_a0 event.Subscription, _a1 error) *FeeQuoterInterface_WatchFeeTokenAdded_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_WatchFeeTokenAdded_Call) RunAndReturn(run func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterFeeTokenAdded, []common.Address) (event.Subscription, error)) *FeeQuoterInterface_WatchFeeTokenAdded_Call { + _c.Call.Return(run) + return _c +} + +// WatchFeeTokenRemoved provides a mock function with given fields: opts, sink, feeToken +func (_m *FeeQuoterInterface) WatchFeeTokenRemoved(opts *bind.WatchOpts, sink chan<- *fee_quoter.FeeQuoterFeeTokenRemoved, feeToken []common.Address) (event.Subscription, error) { + ret := _m.Called(opts, sink, feeToken) + + if len(ret) == 0 { + panic("no return value specified for WatchFeeTokenRemoved") + } + + var r0 event.Subscription + var r1 error + if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterFeeTokenRemoved, []common.Address) (event.Subscription, error)); ok { + return rf(opts, sink, feeToken) + } + if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterFeeTokenRemoved, []common.Address) event.Subscription); ok { + r0 = rf(opts, sink, feeToken) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(event.Subscription) + } + } + + if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterFeeTokenRemoved, []common.Address) error); ok { + r1 = rf(opts, sink, feeToken) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_WatchFeeTokenRemoved_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchFeeTokenRemoved' +type FeeQuoterInterface_WatchFeeTokenRemoved_Call struct { + *mock.Call +} + +// WatchFeeTokenRemoved is a helper method to define mock.On call +// - opts *bind.WatchOpts +// - sink chan<- *fee_quoter.FeeQuoterFeeTokenRemoved +// - feeToken []common.Address +func (_e *FeeQuoterInterface_Expecter) WatchFeeTokenRemoved(opts interface{}, sink interface{}, feeToken interface{}) *FeeQuoterInterface_WatchFeeTokenRemoved_Call { + return &FeeQuoterInterface_WatchFeeTokenRemoved_Call{Call: _e.mock.On("WatchFeeTokenRemoved", opts, sink, feeToken)} +} + +func (_c *FeeQuoterInterface_WatchFeeTokenRemoved_Call) Run(run func(opts *bind.WatchOpts, sink chan<- *fee_quoter.FeeQuoterFeeTokenRemoved, feeToken []common.Address)) *FeeQuoterInterface_WatchFeeTokenRemoved_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.WatchOpts), args[1].(chan<- *fee_quoter.FeeQuoterFeeTokenRemoved), args[2].([]common.Address)) + }) + return _c +} + +func (_c *FeeQuoterInterface_WatchFeeTokenRemoved_Call) Return(_a0 event.Subscription, _a1 error) *FeeQuoterInterface_WatchFeeTokenRemoved_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_WatchFeeTokenRemoved_Call) RunAndReturn(run func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterFeeTokenRemoved, []common.Address) (event.Subscription, error)) *FeeQuoterInterface_WatchFeeTokenRemoved_Call { + _c.Call.Return(run) + return _c +} + +// WatchOwnershipTransferRequested provides a mock function with given fields: opts, sink, from, to +func (_m *FeeQuoterInterface) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *fee_quoter.FeeQuoterOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) { + ret := _m.Called(opts, sink, from, to) + + if len(ret) == 0 { + panic("no return value specified for WatchOwnershipTransferRequested") + } + + var r0 event.Subscription + var r1 error + if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterOwnershipTransferRequested, []common.Address, []common.Address) (event.Subscription, error)); ok { + return rf(opts, sink, from, to) + } + if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterOwnershipTransferRequested, []common.Address, []common.Address) event.Subscription); ok { + r0 = rf(opts, sink, from, to) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(event.Subscription) + } + } + + if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterOwnershipTransferRequested, []common.Address, []common.Address) error); ok { + r1 = rf(opts, sink, from, to) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_WatchOwnershipTransferRequested_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchOwnershipTransferRequested' +type FeeQuoterInterface_WatchOwnershipTransferRequested_Call struct { + *mock.Call +} + +// WatchOwnershipTransferRequested is a helper method to define mock.On call +// - opts *bind.WatchOpts +// - sink chan<- *fee_quoter.FeeQuoterOwnershipTransferRequested +// - from []common.Address +// - to []common.Address +func (_e *FeeQuoterInterface_Expecter) WatchOwnershipTransferRequested(opts interface{}, sink interface{}, from interface{}, to interface{}) *FeeQuoterInterface_WatchOwnershipTransferRequested_Call { + return &FeeQuoterInterface_WatchOwnershipTransferRequested_Call{Call: _e.mock.On("WatchOwnershipTransferRequested", opts, sink, from, to)} +} + +func (_c *FeeQuoterInterface_WatchOwnershipTransferRequested_Call) Run(run func(opts *bind.WatchOpts, sink chan<- *fee_quoter.FeeQuoterOwnershipTransferRequested, from []common.Address, to []common.Address)) *FeeQuoterInterface_WatchOwnershipTransferRequested_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.WatchOpts), args[1].(chan<- *fee_quoter.FeeQuoterOwnershipTransferRequested), args[2].([]common.Address), args[3].([]common.Address)) + }) + return _c +} + +func (_c *FeeQuoterInterface_WatchOwnershipTransferRequested_Call) Return(_a0 event.Subscription, _a1 error) *FeeQuoterInterface_WatchOwnershipTransferRequested_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_WatchOwnershipTransferRequested_Call) RunAndReturn(run func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterOwnershipTransferRequested, []common.Address, []common.Address) (event.Subscription, error)) *FeeQuoterInterface_WatchOwnershipTransferRequested_Call { + _c.Call.Return(run) + return _c +} + +// WatchOwnershipTransferred provides a mock function with given fields: opts, sink, from, to +func (_m *FeeQuoterInterface) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *fee_quoter.FeeQuoterOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) { + ret := _m.Called(opts, sink, from, to) + + if len(ret) == 0 { + panic("no return value specified for WatchOwnershipTransferred") + } + + var r0 event.Subscription + var r1 error + if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterOwnershipTransferred, []common.Address, []common.Address) (event.Subscription, error)); ok { + return rf(opts, sink, from, to) + } + if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterOwnershipTransferred, []common.Address, []common.Address) event.Subscription); ok { + r0 = rf(opts, sink, from, to) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(event.Subscription) + } + } + + if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterOwnershipTransferred, []common.Address, []common.Address) error); ok { + r1 = rf(opts, sink, from, to) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_WatchOwnershipTransferred_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchOwnershipTransferred' +type FeeQuoterInterface_WatchOwnershipTransferred_Call struct { + *mock.Call +} + +// WatchOwnershipTransferred is a helper method to define mock.On call +// - opts *bind.WatchOpts +// - sink chan<- *fee_quoter.FeeQuoterOwnershipTransferred +// - from []common.Address +// - to []common.Address +func (_e *FeeQuoterInterface_Expecter) WatchOwnershipTransferred(opts interface{}, sink interface{}, from interface{}, to interface{}) *FeeQuoterInterface_WatchOwnershipTransferred_Call { + return &FeeQuoterInterface_WatchOwnershipTransferred_Call{Call: _e.mock.On("WatchOwnershipTransferred", opts, sink, from, to)} +} + +func (_c *FeeQuoterInterface_WatchOwnershipTransferred_Call) Run(run func(opts *bind.WatchOpts, sink chan<- *fee_quoter.FeeQuoterOwnershipTransferred, from []common.Address, to []common.Address)) *FeeQuoterInterface_WatchOwnershipTransferred_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.WatchOpts), args[1].(chan<- *fee_quoter.FeeQuoterOwnershipTransferred), args[2].([]common.Address), args[3].([]common.Address)) + }) + return _c +} + +func (_c *FeeQuoterInterface_WatchOwnershipTransferred_Call) Return(_a0 event.Subscription, _a1 error) *FeeQuoterInterface_WatchOwnershipTransferred_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_WatchOwnershipTransferred_Call) RunAndReturn(run func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterOwnershipTransferred, []common.Address, []common.Address) (event.Subscription, error)) *FeeQuoterInterface_WatchOwnershipTransferred_Call { + _c.Call.Return(run) + return _c +} + +// WatchPremiumMultiplierWeiPerEthUpdated provides a mock function with given fields: opts, sink, token +func (_m *FeeQuoterInterface) WatchPremiumMultiplierWeiPerEthUpdated(opts *bind.WatchOpts, sink chan<- *fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthUpdated, token []common.Address) (event.Subscription, error) { + ret := _m.Called(opts, sink, token) + + if len(ret) == 0 { + panic("no return value specified for WatchPremiumMultiplierWeiPerEthUpdated") + } + + var r0 event.Subscription + var r1 error + if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthUpdated, []common.Address) (event.Subscription, error)); ok { + return rf(opts, sink, token) + } + if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthUpdated, []common.Address) event.Subscription); ok { + r0 = rf(opts, sink, token) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(event.Subscription) + } + } + + if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthUpdated, []common.Address) error); ok { + r1 = rf(opts, sink, token) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_WatchPremiumMultiplierWeiPerEthUpdated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchPremiumMultiplierWeiPerEthUpdated' +type FeeQuoterInterface_WatchPremiumMultiplierWeiPerEthUpdated_Call struct { + *mock.Call +} + +// WatchPremiumMultiplierWeiPerEthUpdated is a helper method to define mock.On call +// - opts *bind.WatchOpts +// - sink chan<- *fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthUpdated +// - token []common.Address +func (_e *FeeQuoterInterface_Expecter) WatchPremiumMultiplierWeiPerEthUpdated(opts interface{}, sink interface{}, token interface{}) *FeeQuoterInterface_WatchPremiumMultiplierWeiPerEthUpdated_Call { + return &FeeQuoterInterface_WatchPremiumMultiplierWeiPerEthUpdated_Call{Call: _e.mock.On("WatchPremiumMultiplierWeiPerEthUpdated", opts, sink, token)} +} + +func (_c *FeeQuoterInterface_WatchPremiumMultiplierWeiPerEthUpdated_Call) Run(run func(opts *bind.WatchOpts, sink chan<- *fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthUpdated, token []common.Address)) *FeeQuoterInterface_WatchPremiumMultiplierWeiPerEthUpdated_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.WatchOpts), args[1].(chan<- *fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthUpdated), args[2].([]common.Address)) + }) + return _c +} + +func (_c *FeeQuoterInterface_WatchPremiumMultiplierWeiPerEthUpdated_Call) Return(_a0 event.Subscription, _a1 error) *FeeQuoterInterface_WatchPremiumMultiplierWeiPerEthUpdated_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_WatchPremiumMultiplierWeiPerEthUpdated_Call) RunAndReturn(run func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthUpdated, []common.Address) (event.Subscription, error)) *FeeQuoterInterface_WatchPremiumMultiplierWeiPerEthUpdated_Call { + _c.Call.Return(run) + return _c +} + +// WatchPriceFeedPerTokenUpdated provides a mock function with given fields: opts, sink, token +func (_m *FeeQuoterInterface) WatchPriceFeedPerTokenUpdated(opts *bind.WatchOpts, sink chan<- *fee_quoter.FeeQuoterPriceFeedPerTokenUpdated, token []common.Address) (event.Subscription, error) { + ret := _m.Called(opts, sink, token) + + if len(ret) == 0 { + panic("no return value specified for WatchPriceFeedPerTokenUpdated") + } + + var r0 event.Subscription + var r1 error + if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterPriceFeedPerTokenUpdated, []common.Address) (event.Subscription, error)); ok { + return rf(opts, sink, token) + } + if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterPriceFeedPerTokenUpdated, []common.Address) event.Subscription); ok { + r0 = rf(opts, sink, token) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(event.Subscription) + } + } + + if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterPriceFeedPerTokenUpdated, []common.Address) error); ok { + r1 = rf(opts, sink, token) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_WatchPriceFeedPerTokenUpdated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchPriceFeedPerTokenUpdated' +type FeeQuoterInterface_WatchPriceFeedPerTokenUpdated_Call struct { + *mock.Call +} + +// WatchPriceFeedPerTokenUpdated is a helper method to define mock.On call +// - opts *bind.WatchOpts +// - sink chan<- *fee_quoter.FeeQuoterPriceFeedPerTokenUpdated +// - token []common.Address +func (_e *FeeQuoterInterface_Expecter) WatchPriceFeedPerTokenUpdated(opts interface{}, sink interface{}, token interface{}) *FeeQuoterInterface_WatchPriceFeedPerTokenUpdated_Call { + return &FeeQuoterInterface_WatchPriceFeedPerTokenUpdated_Call{Call: _e.mock.On("WatchPriceFeedPerTokenUpdated", opts, sink, token)} +} + +func (_c *FeeQuoterInterface_WatchPriceFeedPerTokenUpdated_Call) Run(run func(opts *bind.WatchOpts, sink chan<- *fee_quoter.FeeQuoterPriceFeedPerTokenUpdated, token []common.Address)) *FeeQuoterInterface_WatchPriceFeedPerTokenUpdated_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.WatchOpts), args[1].(chan<- *fee_quoter.FeeQuoterPriceFeedPerTokenUpdated), args[2].([]common.Address)) + }) + return _c +} + +func (_c *FeeQuoterInterface_WatchPriceFeedPerTokenUpdated_Call) Return(_a0 event.Subscription, _a1 error) *FeeQuoterInterface_WatchPriceFeedPerTokenUpdated_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_WatchPriceFeedPerTokenUpdated_Call) RunAndReturn(run func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterPriceFeedPerTokenUpdated, []common.Address) (event.Subscription, error)) *FeeQuoterInterface_WatchPriceFeedPerTokenUpdated_Call { + _c.Call.Return(run) + return _c +} + +// WatchReportPermissionSet provides a mock function with given fields: opts, sink, reportId +func (_m *FeeQuoterInterface) WatchReportPermissionSet(opts *bind.WatchOpts, sink chan<- *fee_quoter.FeeQuoterReportPermissionSet, reportId [][32]byte) (event.Subscription, error) { + ret := _m.Called(opts, sink, reportId) + + if len(ret) == 0 { + panic("no return value specified for WatchReportPermissionSet") + } + + var r0 event.Subscription + var r1 error + if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterReportPermissionSet, [][32]byte) (event.Subscription, error)); ok { + return rf(opts, sink, reportId) + } + if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterReportPermissionSet, [][32]byte) event.Subscription); ok { + r0 = rf(opts, sink, reportId) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(event.Subscription) + } + } + + if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterReportPermissionSet, [][32]byte) error); ok { + r1 = rf(opts, sink, reportId) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_WatchReportPermissionSet_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchReportPermissionSet' +type FeeQuoterInterface_WatchReportPermissionSet_Call struct { + *mock.Call +} + +// WatchReportPermissionSet is a helper method to define mock.On call +// - opts *bind.WatchOpts +// - sink chan<- *fee_quoter.FeeQuoterReportPermissionSet +// - reportId [][32]byte +func (_e *FeeQuoterInterface_Expecter) WatchReportPermissionSet(opts interface{}, sink interface{}, reportId interface{}) *FeeQuoterInterface_WatchReportPermissionSet_Call { + return &FeeQuoterInterface_WatchReportPermissionSet_Call{Call: _e.mock.On("WatchReportPermissionSet", opts, sink, reportId)} +} + +func (_c *FeeQuoterInterface_WatchReportPermissionSet_Call) Run(run func(opts *bind.WatchOpts, sink chan<- *fee_quoter.FeeQuoterReportPermissionSet, reportId [][32]byte)) *FeeQuoterInterface_WatchReportPermissionSet_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.WatchOpts), args[1].(chan<- *fee_quoter.FeeQuoterReportPermissionSet), args[2].([][32]byte)) + }) + return _c +} + +func (_c *FeeQuoterInterface_WatchReportPermissionSet_Call) Return(_a0 event.Subscription, _a1 error) *FeeQuoterInterface_WatchReportPermissionSet_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_WatchReportPermissionSet_Call) RunAndReturn(run func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterReportPermissionSet, [][32]byte) (event.Subscription, error)) *FeeQuoterInterface_WatchReportPermissionSet_Call { + _c.Call.Return(run) + return _c +} + +// WatchTokenTransferFeeConfigDeleted provides a mock function with given fields: opts, sink, destChainSelector, token +func (_m *FeeQuoterInterface) WatchTokenTransferFeeConfigDeleted(opts *bind.WatchOpts, sink chan<- *fee_quoter.FeeQuoterTokenTransferFeeConfigDeleted, destChainSelector []uint64, token []common.Address) (event.Subscription, error) { + ret := _m.Called(opts, sink, destChainSelector, token) + + if len(ret) == 0 { + panic("no return value specified for WatchTokenTransferFeeConfigDeleted") + } + + var r0 event.Subscription + var r1 error + if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterTokenTransferFeeConfigDeleted, []uint64, []common.Address) (event.Subscription, error)); ok { + return rf(opts, sink, destChainSelector, token) + } + if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterTokenTransferFeeConfigDeleted, []uint64, []common.Address) event.Subscription); ok { + r0 = rf(opts, sink, destChainSelector, token) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(event.Subscription) + } + } + + if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterTokenTransferFeeConfigDeleted, []uint64, []common.Address) error); ok { + r1 = rf(opts, sink, destChainSelector, token) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_WatchTokenTransferFeeConfigDeleted_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchTokenTransferFeeConfigDeleted' +type FeeQuoterInterface_WatchTokenTransferFeeConfigDeleted_Call struct { + *mock.Call +} + +// WatchTokenTransferFeeConfigDeleted is a helper method to define mock.On call +// - opts *bind.WatchOpts +// - sink chan<- *fee_quoter.FeeQuoterTokenTransferFeeConfigDeleted +// - destChainSelector []uint64 +// - token []common.Address +func (_e *FeeQuoterInterface_Expecter) WatchTokenTransferFeeConfigDeleted(opts interface{}, sink interface{}, destChainSelector interface{}, token interface{}) *FeeQuoterInterface_WatchTokenTransferFeeConfigDeleted_Call { + return &FeeQuoterInterface_WatchTokenTransferFeeConfigDeleted_Call{Call: _e.mock.On("WatchTokenTransferFeeConfigDeleted", opts, sink, destChainSelector, token)} +} + +func (_c *FeeQuoterInterface_WatchTokenTransferFeeConfigDeleted_Call) Run(run func(opts *bind.WatchOpts, sink chan<- *fee_quoter.FeeQuoterTokenTransferFeeConfigDeleted, destChainSelector []uint64, token []common.Address)) *FeeQuoterInterface_WatchTokenTransferFeeConfigDeleted_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.WatchOpts), args[1].(chan<- *fee_quoter.FeeQuoterTokenTransferFeeConfigDeleted), args[2].([]uint64), args[3].([]common.Address)) + }) + return _c +} + +func (_c *FeeQuoterInterface_WatchTokenTransferFeeConfigDeleted_Call) Return(_a0 event.Subscription, _a1 error) *FeeQuoterInterface_WatchTokenTransferFeeConfigDeleted_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_WatchTokenTransferFeeConfigDeleted_Call) RunAndReturn(run func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterTokenTransferFeeConfigDeleted, []uint64, []common.Address) (event.Subscription, error)) *FeeQuoterInterface_WatchTokenTransferFeeConfigDeleted_Call { + _c.Call.Return(run) + return _c +} + +// WatchTokenTransferFeeConfigUpdated provides a mock function with given fields: opts, sink, destChainSelector, token +func (_m *FeeQuoterInterface) WatchTokenTransferFeeConfigUpdated(opts *bind.WatchOpts, sink chan<- *fee_quoter.FeeQuoterTokenTransferFeeConfigUpdated, destChainSelector []uint64, token []common.Address) (event.Subscription, error) { + ret := _m.Called(opts, sink, destChainSelector, token) + + if len(ret) == 0 { + panic("no return value specified for WatchTokenTransferFeeConfigUpdated") + } + + var r0 event.Subscription + var r1 error + if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterTokenTransferFeeConfigUpdated, []uint64, []common.Address) (event.Subscription, error)); ok { + return rf(opts, sink, destChainSelector, token) + } + if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterTokenTransferFeeConfigUpdated, []uint64, []common.Address) event.Subscription); ok { + r0 = rf(opts, sink, destChainSelector, token) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(event.Subscription) + } + } + + if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterTokenTransferFeeConfigUpdated, []uint64, []common.Address) error); ok { + r1 = rf(opts, sink, destChainSelector, token) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_WatchTokenTransferFeeConfigUpdated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchTokenTransferFeeConfigUpdated' +type FeeQuoterInterface_WatchTokenTransferFeeConfigUpdated_Call struct { + *mock.Call +} + +// WatchTokenTransferFeeConfigUpdated is a helper method to define mock.On call +// - opts *bind.WatchOpts +// - sink chan<- *fee_quoter.FeeQuoterTokenTransferFeeConfigUpdated +// - destChainSelector []uint64 +// - token []common.Address +func (_e *FeeQuoterInterface_Expecter) WatchTokenTransferFeeConfigUpdated(opts interface{}, sink interface{}, destChainSelector interface{}, token interface{}) *FeeQuoterInterface_WatchTokenTransferFeeConfigUpdated_Call { + return &FeeQuoterInterface_WatchTokenTransferFeeConfigUpdated_Call{Call: _e.mock.On("WatchTokenTransferFeeConfigUpdated", opts, sink, destChainSelector, token)} +} + +func (_c *FeeQuoterInterface_WatchTokenTransferFeeConfigUpdated_Call) Run(run func(opts *bind.WatchOpts, sink chan<- *fee_quoter.FeeQuoterTokenTransferFeeConfigUpdated, destChainSelector []uint64, token []common.Address)) *FeeQuoterInterface_WatchTokenTransferFeeConfigUpdated_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.WatchOpts), args[1].(chan<- *fee_quoter.FeeQuoterTokenTransferFeeConfigUpdated), args[2].([]uint64), args[3].([]common.Address)) + }) + return _c +} + +func (_c *FeeQuoterInterface_WatchTokenTransferFeeConfigUpdated_Call) Return(_a0 event.Subscription, _a1 error) *FeeQuoterInterface_WatchTokenTransferFeeConfigUpdated_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_WatchTokenTransferFeeConfigUpdated_Call) RunAndReturn(run func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterTokenTransferFeeConfigUpdated, []uint64, []common.Address) (event.Subscription, error)) *FeeQuoterInterface_WatchTokenTransferFeeConfigUpdated_Call { + _c.Call.Return(run) + return _c +} + +// WatchUsdPerTokenUpdated provides a mock function with given fields: opts, sink, token +func (_m *FeeQuoterInterface) WatchUsdPerTokenUpdated(opts *bind.WatchOpts, sink chan<- *fee_quoter.FeeQuoterUsdPerTokenUpdated, token []common.Address) (event.Subscription, error) { + ret := _m.Called(opts, sink, token) + + if len(ret) == 0 { + panic("no return value specified for WatchUsdPerTokenUpdated") + } + + var r0 event.Subscription + var r1 error + if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterUsdPerTokenUpdated, []common.Address) (event.Subscription, error)); ok { + return rf(opts, sink, token) + } + if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterUsdPerTokenUpdated, []common.Address) event.Subscription); ok { + r0 = rf(opts, sink, token) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(event.Subscription) + } + } + + if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterUsdPerTokenUpdated, []common.Address) error); ok { + r1 = rf(opts, sink, token) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_WatchUsdPerTokenUpdated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchUsdPerTokenUpdated' +type FeeQuoterInterface_WatchUsdPerTokenUpdated_Call struct { + *mock.Call +} + +// WatchUsdPerTokenUpdated is a helper method to define mock.On call +// - opts *bind.WatchOpts +// - sink chan<- *fee_quoter.FeeQuoterUsdPerTokenUpdated +// - token []common.Address +func (_e *FeeQuoterInterface_Expecter) WatchUsdPerTokenUpdated(opts interface{}, sink interface{}, token interface{}) *FeeQuoterInterface_WatchUsdPerTokenUpdated_Call { + return &FeeQuoterInterface_WatchUsdPerTokenUpdated_Call{Call: _e.mock.On("WatchUsdPerTokenUpdated", opts, sink, token)} +} + +func (_c *FeeQuoterInterface_WatchUsdPerTokenUpdated_Call) Run(run func(opts *bind.WatchOpts, sink chan<- *fee_quoter.FeeQuoterUsdPerTokenUpdated, token []common.Address)) *FeeQuoterInterface_WatchUsdPerTokenUpdated_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.WatchOpts), args[1].(chan<- *fee_quoter.FeeQuoterUsdPerTokenUpdated), args[2].([]common.Address)) + }) + return _c +} + +func (_c *FeeQuoterInterface_WatchUsdPerTokenUpdated_Call) Return(_a0 event.Subscription, _a1 error) *FeeQuoterInterface_WatchUsdPerTokenUpdated_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_WatchUsdPerTokenUpdated_Call) RunAndReturn(run func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterUsdPerTokenUpdated, []common.Address) (event.Subscription, error)) *FeeQuoterInterface_WatchUsdPerTokenUpdated_Call { + _c.Call.Return(run) + return _c +} + +// WatchUsdPerUnitGasUpdated provides a mock function with given fields: opts, sink, destChain +func (_m *FeeQuoterInterface) WatchUsdPerUnitGasUpdated(opts *bind.WatchOpts, sink chan<- *fee_quoter.FeeQuoterUsdPerUnitGasUpdated, destChain []uint64) (event.Subscription, error) { + ret := _m.Called(opts, sink, destChain) + + if len(ret) == 0 { + panic("no return value specified for WatchUsdPerUnitGasUpdated") + } + + var r0 event.Subscription + var r1 error + if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterUsdPerUnitGasUpdated, []uint64) (event.Subscription, error)); ok { + return rf(opts, sink, destChain) + } + if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterUsdPerUnitGasUpdated, []uint64) event.Subscription); ok { + r0 = rf(opts, sink, destChain) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(event.Subscription) + } + } + + if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterUsdPerUnitGasUpdated, []uint64) error); ok { + r1 = rf(opts, sink, destChain) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_WatchUsdPerUnitGasUpdated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchUsdPerUnitGasUpdated' +type FeeQuoterInterface_WatchUsdPerUnitGasUpdated_Call struct { + *mock.Call +} + +// WatchUsdPerUnitGasUpdated is a helper method to define mock.On call +// - opts *bind.WatchOpts +// - sink chan<- *fee_quoter.FeeQuoterUsdPerUnitGasUpdated +// - destChain []uint64 +func (_e *FeeQuoterInterface_Expecter) WatchUsdPerUnitGasUpdated(opts interface{}, sink interface{}, destChain interface{}) *FeeQuoterInterface_WatchUsdPerUnitGasUpdated_Call { + return &FeeQuoterInterface_WatchUsdPerUnitGasUpdated_Call{Call: _e.mock.On("WatchUsdPerUnitGasUpdated", opts, sink, destChain)} +} + +func (_c *FeeQuoterInterface_WatchUsdPerUnitGasUpdated_Call) Run(run func(opts *bind.WatchOpts, sink chan<- *fee_quoter.FeeQuoterUsdPerUnitGasUpdated, destChain []uint64)) *FeeQuoterInterface_WatchUsdPerUnitGasUpdated_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.WatchOpts), args[1].(chan<- *fee_quoter.FeeQuoterUsdPerUnitGasUpdated), args[2].([]uint64)) + }) + return _c +} + +func (_c *FeeQuoterInterface_WatchUsdPerUnitGasUpdated_Call) Return(_a0 event.Subscription, _a1 error) *FeeQuoterInterface_WatchUsdPerUnitGasUpdated_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_WatchUsdPerUnitGasUpdated_Call) RunAndReturn(run func(*bind.WatchOpts, chan<- *fee_quoter.FeeQuoterUsdPerUnitGasUpdated, []uint64) (event.Subscription, error)) *FeeQuoterInterface_WatchUsdPerUnitGasUpdated_Call { + _c.Call.Return(run) + return _c +} + +// NewFeeQuoterInterface creates a new instance of FeeQuoterInterface. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewFeeQuoterInterface(t interface { + mock.TestingT + Cleanup(func()) +}) *FeeQuoterInterface { + mock := &FeeQuoterInterface{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/core/gethwrappers/ccip/mocks/price_registry_interface.go b/core/gethwrappers/ccip/mocks/price_registry_interface.go deleted file mode 100644 index 04104ce835..0000000000 --- a/core/gethwrappers/ccip/mocks/price_registry_interface.go +++ /dev/null @@ -1,4509 +0,0 @@ -// Code generated by mockery v2.43.2. DO NOT EDIT. - -package mock_contracts - -import ( - big "math/big" - - bind "github.com/ethereum/go-ethereum/accounts/abi/bind" - common "github.com/ethereum/go-ethereum/common" - - event "github.com/ethereum/go-ethereum/event" - - generated "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated" - - mock "github.com/stretchr/testify/mock" - - price_registry "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/price_registry" - - types "github.com/ethereum/go-ethereum/core/types" -) - -// PriceRegistryInterface is an autogenerated mock type for the PriceRegistryInterface type -type PriceRegistryInterface struct { - mock.Mock -} - -type PriceRegistryInterface_Expecter struct { - mock *mock.Mock -} - -func (_m *PriceRegistryInterface) EXPECT() *PriceRegistryInterface_Expecter { - return &PriceRegistryInterface_Expecter{mock: &_m.Mock} -} - -// AcceptOwnership provides a mock function with given fields: opts -func (_m *PriceRegistryInterface) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { - ret := _m.Called(opts) - - if len(ret) == 0 { - panic("no return value specified for AcceptOwnership") - } - - var r0 *types.Transaction - var r1 error - if rf, ok := ret.Get(0).(func(*bind.TransactOpts) (*types.Transaction, error)); ok { - return rf(opts) - } - if rf, ok := ret.Get(0).(func(*bind.TransactOpts) *types.Transaction); ok { - r0 = rf(opts) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.Transaction) - } - } - - if rf, ok := ret.Get(1).(func(*bind.TransactOpts) error); ok { - r1 = rf(opts) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_AcceptOwnership_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'AcceptOwnership' -type PriceRegistryInterface_AcceptOwnership_Call struct { - *mock.Call -} - -// AcceptOwnership is a helper method to define mock.On call -// - opts *bind.TransactOpts -func (_e *PriceRegistryInterface_Expecter) AcceptOwnership(opts interface{}) *PriceRegistryInterface_AcceptOwnership_Call { - return &PriceRegistryInterface_AcceptOwnership_Call{Call: _e.mock.On("AcceptOwnership", opts)} -} - -func (_c *PriceRegistryInterface_AcceptOwnership_Call) Run(run func(opts *bind.TransactOpts)) *PriceRegistryInterface_AcceptOwnership_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.TransactOpts)) - }) - return _c -} - -func (_c *PriceRegistryInterface_AcceptOwnership_Call) Return(_a0 *types.Transaction, _a1 error) *PriceRegistryInterface_AcceptOwnership_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_AcceptOwnership_Call) RunAndReturn(run func(*bind.TransactOpts) (*types.Transaction, error)) *PriceRegistryInterface_AcceptOwnership_Call { - _c.Call.Return(run) - return _c -} - -// Address provides a mock function with given fields: -func (_m *PriceRegistryInterface) Address() common.Address { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for Address") - } - - var r0 common.Address - if rf, ok := ret.Get(0).(func() common.Address); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(common.Address) - } - } - - return r0 -} - -// PriceRegistryInterface_Address_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Address' -type PriceRegistryInterface_Address_Call struct { - *mock.Call -} - -// Address is a helper method to define mock.On call -func (_e *PriceRegistryInterface_Expecter) Address() *PriceRegistryInterface_Address_Call { - return &PriceRegistryInterface_Address_Call{Call: _e.mock.On("Address")} -} - -func (_c *PriceRegistryInterface_Address_Call) Run(run func()) *PriceRegistryInterface_Address_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *PriceRegistryInterface_Address_Call) Return(_a0 common.Address) *PriceRegistryInterface_Address_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *PriceRegistryInterface_Address_Call) RunAndReturn(run func() common.Address) *PriceRegistryInterface_Address_Call { - _c.Call.Return(run) - return _c -} - -// ApplyAuthorizedCallerUpdates provides a mock function with given fields: opts, authorizedCallerArgs -func (_m *PriceRegistryInterface) ApplyAuthorizedCallerUpdates(opts *bind.TransactOpts, authorizedCallerArgs price_registry.AuthorizedCallersAuthorizedCallerArgs) (*types.Transaction, error) { - ret := _m.Called(opts, authorizedCallerArgs) - - if len(ret) == 0 { - panic("no return value specified for ApplyAuthorizedCallerUpdates") - } - - var r0 *types.Transaction - var r1 error - if rf, ok := ret.Get(0).(func(*bind.TransactOpts, price_registry.AuthorizedCallersAuthorizedCallerArgs) (*types.Transaction, error)); ok { - return rf(opts, authorizedCallerArgs) - } - if rf, ok := ret.Get(0).(func(*bind.TransactOpts, price_registry.AuthorizedCallersAuthorizedCallerArgs) *types.Transaction); ok { - r0 = rf(opts, authorizedCallerArgs) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.Transaction) - } - } - - if rf, ok := ret.Get(1).(func(*bind.TransactOpts, price_registry.AuthorizedCallersAuthorizedCallerArgs) error); ok { - r1 = rf(opts, authorizedCallerArgs) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_ApplyAuthorizedCallerUpdates_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ApplyAuthorizedCallerUpdates' -type PriceRegistryInterface_ApplyAuthorizedCallerUpdates_Call struct { - *mock.Call -} - -// ApplyAuthorizedCallerUpdates is a helper method to define mock.On call -// - opts *bind.TransactOpts -// - authorizedCallerArgs price_registry.AuthorizedCallersAuthorizedCallerArgs -func (_e *PriceRegistryInterface_Expecter) ApplyAuthorizedCallerUpdates(opts interface{}, authorizedCallerArgs interface{}) *PriceRegistryInterface_ApplyAuthorizedCallerUpdates_Call { - return &PriceRegistryInterface_ApplyAuthorizedCallerUpdates_Call{Call: _e.mock.On("ApplyAuthorizedCallerUpdates", opts, authorizedCallerArgs)} -} - -func (_c *PriceRegistryInterface_ApplyAuthorizedCallerUpdates_Call) Run(run func(opts *bind.TransactOpts, authorizedCallerArgs price_registry.AuthorizedCallersAuthorizedCallerArgs)) *PriceRegistryInterface_ApplyAuthorizedCallerUpdates_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.TransactOpts), args[1].(price_registry.AuthorizedCallersAuthorizedCallerArgs)) - }) - return _c -} - -func (_c *PriceRegistryInterface_ApplyAuthorizedCallerUpdates_Call) Return(_a0 *types.Transaction, _a1 error) *PriceRegistryInterface_ApplyAuthorizedCallerUpdates_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_ApplyAuthorizedCallerUpdates_Call) RunAndReturn(run func(*bind.TransactOpts, price_registry.AuthorizedCallersAuthorizedCallerArgs) (*types.Transaction, error)) *PriceRegistryInterface_ApplyAuthorizedCallerUpdates_Call { - _c.Call.Return(run) - return _c -} - -// ApplyDestChainConfigUpdates provides a mock function with given fields: opts, destChainConfigArgs -func (_m *PriceRegistryInterface) ApplyDestChainConfigUpdates(opts *bind.TransactOpts, destChainConfigArgs []price_registry.PriceRegistryDestChainConfigArgs) (*types.Transaction, error) { - ret := _m.Called(opts, destChainConfigArgs) - - if len(ret) == 0 { - panic("no return value specified for ApplyDestChainConfigUpdates") - } - - var r0 *types.Transaction - var r1 error - if rf, ok := ret.Get(0).(func(*bind.TransactOpts, []price_registry.PriceRegistryDestChainConfigArgs) (*types.Transaction, error)); ok { - return rf(opts, destChainConfigArgs) - } - if rf, ok := ret.Get(0).(func(*bind.TransactOpts, []price_registry.PriceRegistryDestChainConfigArgs) *types.Transaction); ok { - r0 = rf(opts, destChainConfigArgs) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.Transaction) - } - } - - if rf, ok := ret.Get(1).(func(*bind.TransactOpts, []price_registry.PriceRegistryDestChainConfigArgs) error); ok { - r1 = rf(opts, destChainConfigArgs) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_ApplyDestChainConfigUpdates_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ApplyDestChainConfigUpdates' -type PriceRegistryInterface_ApplyDestChainConfigUpdates_Call struct { - *mock.Call -} - -// ApplyDestChainConfigUpdates is a helper method to define mock.On call -// - opts *bind.TransactOpts -// - destChainConfigArgs []price_registry.PriceRegistryDestChainConfigArgs -func (_e *PriceRegistryInterface_Expecter) ApplyDestChainConfigUpdates(opts interface{}, destChainConfigArgs interface{}) *PriceRegistryInterface_ApplyDestChainConfigUpdates_Call { - return &PriceRegistryInterface_ApplyDestChainConfigUpdates_Call{Call: _e.mock.On("ApplyDestChainConfigUpdates", opts, destChainConfigArgs)} -} - -func (_c *PriceRegistryInterface_ApplyDestChainConfigUpdates_Call) Run(run func(opts *bind.TransactOpts, destChainConfigArgs []price_registry.PriceRegistryDestChainConfigArgs)) *PriceRegistryInterface_ApplyDestChainConfigUpdates_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.TransactOpts), args[1].([]price_registry.PriceRegistryDestChainConfigArgs)) - }) - return _c -} - -func (_c *PriceRegistryInterface_ApplyDestChainConfigUpdates_Call) Return(_a0 *types.Transaction, _a1 error) *PriceRegistryInterface_ApplyDestChainConfigUpdates_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_ApplyDestChainConfigUpdates_Call) RunAndReturn(run func(*bind.TransactOpts, []price_registry.PriceRegistryDestChainConfigArgs) (*types.Transaction, error)) *PriceRegistryInterface_ApplyDestChainConfigUpdates_Call { - _c.Call.Return(run) - return _c -} - -// ApplyFeeTokensUpdates provides a mock function with given fields: opts, feeTokensToAdd, feeTokensToRemove -func (_m *PriceRegistryInterface) ApplyFeeTokensUpdates(opts *bind.TransactOpts, feeTokensToAdd []common.Address, feeTokensToRemove []common.Address) (*types.Transaction, error) { - ret := _m.Called(opts, feeTokensToAdd, feeTokensToRemove) - - if len(ret) == 0 { - panic("no return value specified for ApplyFeeTokensUpdates") - } - - var r0 *types.Transaction - var r1 error - if rf, ok := ret.Get(0).(func(*bind.TransactOpts, []common.Address, []common.Address) (*types.Transaction, error)); ok { - return rf(opts, feeTokensToAdd, feeTokensToRemove) - } - if rf, ok := ret.Get(0).(func(*bind.TransactOpts, []common.Address, []common.Address) *types.Transaction); ok { - r0 = rf(opts, feeTokensToAdd, feeTokensToRemove) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.Transaction) - } - } - - if rf, ok := ret.Get(1).(func(*bind.TransactOpts, []common.Address, []common.Address) error); ok { - r1 = rf(opts, feeTokensToAdd, feeTokensToRemove) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_ApplyFeeTokensUpdates_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ApplyFeeTokensUpdates' -type PriceRegistryInterface_ApplyFeeTokensUpdates_Call struct { - *mock.Call -} - -// ApplyFeeTokensUpdates is a helper method to define mock.On call -// - opts *bind.TransactOpts -// - feeTokensToAdd []common.Address -// - feeTokensToRemove []common.Address -func (_e *PriceRegistryInterface_Expecter) ApplyFeeTokensUpdates(opts interface{}, feeTokensToAdd interface{}, feeTokensToRemove interface{}) *PriceRegistryInterface_ApplyFeeTokensUpdates_Call { - return &PriceRegistryInterface_ApplyFeeTokensUpdates_Call{Call: _e.mock.On("ApplyFeeTokensUpdates", opts, feeTokensToAdd, feeTokensToRemove)} -} - -func (_c *PriceRegistryInterface_ApplyFeeTokensUpdates_Call) Run(run func(opts *bind.TransactOpts, feeTokensToAdd []common.Address, feeTokensToRemove []common.Address)) *PriceRegistryInterface_ApplyFeeTokensUpdates_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.TransactOpts), args[1].([]common.Address), args[2].([]common.Address)) - }) - return _c -} - -func (_c *PriceRegistryInterface_ApplyFeeTokensUpdates_Call) Return(_a0 *types.Transaction, _a1 error) *PriceRegistryInterface_ApplyFeeTokensUpdates_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_ApplyFeeTokensUpdates_Call) RunAndReturn(run func(*bind.TransactOpts, []common.Address, []common.Address) (*types.Transaction, error)) *PriceRegistryInterface_ApplyFeeTokensUpdates_Call { - _c.Call.Return(run) - return _c -} - -// ApplyPremiumMultiplierWeiPerEthUpdates provides a mock function with given fields: opts, premiumMultiplierWeiPerEthArgs -func (_m *PriceRegistryInterface) ApplyPremiumMultiplierWeiPerEthUpdates(opts *bind.TransactOpts, premiumMultiplierWeiPerEthArgs []price_registry.PriceRegistryPremiumMultiplierWeiPerEthArgs) (*types.Transaction, error) { - ret := _m.Called(opts, premiumMultiplierWeiPerEthArgs) - - if len(ret) == 0 { - panic("no return value specified for ApplyPremiumMultiplierWeiPerEthUpdates") - } - - var r0 *types.Transaction - var r1 error - if rf, ok := ret.Get(0).(func(*bind.TransactOpts, []price_registry.PriceRegistryPremiumMultiplierWeiPerEthArgs) (*types.Transaction, error)); ok { - return rf(opts, premiumMultiplierWeiPerEthArgs) - } - if rf, ok := ret.Get(0).(func(*bind.TransactOpts, []price_registry.PriceRegistryPremiumMultiplierWeiPerEthArgs) *types.Transaction); ok { - r0 = rf(opts, premiumMultiplierWeiPerEthArgs) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.Transaction) - } - } - - if rf, ok := ret.Get(1).(func(*bind.TransactOpts, []price_registry.PriceRegistryPremiumMultiplierWeiPerEthArgs) error); ok { - r1 = rf(opts, premiumMultiplierWeiPerEthArgs) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_ApplyPremiumMultiplierWeiPerEthUpdates_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ApplyPremiumMultiplierWeiPerEthUpdates' -type PriceRegistryInterface_ApplyPremiumMultiplierWeiPerEthUpdates_Call struct { - *mock.Call -} - -// ApplyPremiumMultiplierWeiPerEthUpdates is a helper method to define mock.On call -// - opts *bind.TransactOpts -// - premiumMultiplierWeiPerEthArgs []price_registry.PriceRegistryPremiumMultiplierWeiPerEthArgs -func (_e *PriceRegistryInterface_Expecter) ApplyPremiumMultiplierWeiPerEthUpdates(opts interface{}, premiumMultiplierWeiPerEthArgs interface{}) *PriceRegistryInterface_ApplyPremiumMultiplierWeiPerEthUpdates_Call { - return &PriceRegistryInterface_ApplyPremiumMultiplierWeiPerEthUpdates_Call{Call: _e.mock.On("ApplyPremiumMultiplierWeiPerEthUpdates", opts, premiumMultiplierWeiPerEthArgs)} -} - -func (_c *PriceRegistryInterface_ApplyPremiumMultiplierWeiPerEthUpdates_Call) Run(run func(opts *bind.TransactOpts, premiumMultiplierWeiPerEthArgs []price_registry.PriceRegistryPremiumMultiplierWeiPerEthArgs)) *PriceRegistryInterface_ApplyPremiumMultiplierWeiPerEthUpdates_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.TransactOpts), args[1].([]price_registry.PriceRegistryPremiumMultiplierWeiPerEthArgs)) - }) - return _c -} - -func (_c *PriceRegistryInterface_ApplyPremiumMultiplierWeiPerEthUpdates_Call) Return(_a0 *types.Transaction, _a1 error) *PriceRegistryInterface_ApplyPremiumMultiplierWeiPerEthUpdates_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_ApplyPremiumMultiplierWeiPerEthUpdates_Call) RunAndReturn(run func(*bind.TransactOpts, []price_registry.PriceRegistryPremiumMultiplierWeiPerEthArgs) (*types.Transaction, error)) *PriceRegistryInterface_ApplyPremiumMultiplierWeiPerEthUpdates_Call { - _c.Call.Return(run) - return _c -} - -// ApplyTokenTransferFeeConfigUpdates provides a mock function with given fields: opts, tokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs -func (_m *PriceRegistryInterface) ApplyTokenTransferFeeConfigUpdates(opts *bind.TransactOpts, tokenTransferFeeConfigArgs []price_registry.PriceRegistryTokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs []price_registry.PriceRegistryTokenTransferFeeConfigRemoveArgs) (*types.Transaction, error) { - ret := _m.Called(opts, tokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs) - - if len(ret) == 0 { - panic("no return value specified for ApplyTokenTransferFeeConfigUpdates") - } - - var r0 *types.Transaction - var r1 error - if rf, ok := ret.Get(0).(func(*bind.TransactOpts, []price_registry.PriceRegistryTokenTransferFeeConfigArgs, []price_registry.PriceRegistryTokenTransferFeeConfigRemoveArgs) (*types.Transaction, error)); ok { - return rf(opts, tokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs) - } - if rf, ok := ret.Get(0).(func(*bind.TransactOpts, []price_registry.PriceRegistryTokenTransferFeeConfigArgs, []price_registry.PriceRegistryTokenTransferFeeConfigRemoveArgs) *types.Transaction); ok { - r0 = rf(opts, tokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.Transaction) - } - } - - if rf, ok := ret.Get(1).(func(*bind.TransactOpts, []price_registry.PriceRegistryTokenTransferFeeConfigArgs, []price_registry.PriceRegistryTokenTransferFeeConfigRemoveArgs) error); ok { - r1 = rf(opts, tokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_ApplyTokenTransferFeeConfigUpdates_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ApplyTokenTransferFeeConfigUpdates' -type PriceRegistryInterface_ApplyTokenTransferFeeConfigUpdates_Call struct { - *mock.Call -} - -// ApplyTokenTransferFeeConfigUpdates is a helper method to define mock.On call -// - opts *bind.TransactOpts -// - tokenTransferFeeConfigArgs []price_registry.PriceRegistryTokenTransferFeeConfigArgs -// - tokensToUseDefaultFeeConfigs []price_registry.PriceRegistryTokenTransferFeeConfigRemoveArgs -func (_e *PriceRegistryInterface_Expecter) ApplyTokenTransferFeeConfigUpdates(opts interface{}, tokenTransferFeeConfigArgs interface{}, tokensToUseDefaultFeeConfigs interface{}) *PriceRegistryInterface_ApplyTokenTransferFeeConfigUpdates_Call { - return &PriceRegistryInterface_ApplyTokenTransferFeeConfigUpdates_Call{Call: _e.mock.On("ApplyTokenTransferFeeConfigUpdates", opts, tokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs)} -} - -func (_c *PriceRegistryInterface_ApplyTokenTransferFeeConfigUpdates_Call) Run(run func(opts *bind.TransactOpts, tokenTransferFeeConfigArgs []price_registry.PriceRegistryTokenTransferFeeConfigArgs, tokensToUseDefaultFeeConfigs []price_registry.PriceRegistryTokenTransferFeeConfigRemoveArgs)) *PriceRegistryInterface_ApplyTokenTransferFeeConfigUpdates_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.TransactOpts), args[1].([]price_registry.PriceRegistryTokenTransferFeeConfigArgs), args[2].([]price_registry.PriceRegistryTokenTransferFeeConfigRemoveArgs)) - }) - return _c -} - -func (_c *PriceRegistryInterface_ApplyTokenTransferFeeConfigUpdates_Call) Return(_a0 *types.Transaction, _a1 error) *PriceRegistryInterface_ApplyTokenTransferFeeConfigUpdates_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_ApplyTokenTransferFeeConfigUpdates_Call) RunAndReturn(run func(*bind.TransactOpts, []price_registry.PriceRegistryTokenTransferFeeConfigArgs, []price_registry.PriceRegistryTokenTransferFeeConfigRemoveArgs) (*types.Transaction, error)) *PriceRegistryInterface_ApplyTokenTransferFeeConfigUpdates_Call { - _c.Call.Return(run) - return _c -} - -// ConvertTokenAmount provides a mock function with given fields: opts, fromToken, fromTokenAmount, toToken -func (_m *PriceRegistryInterface) ConvertTokenAmount(opts *bind.CallOpts, fromToken common.Address, fromTokenAmount *big.Int, toToken common.Address) (*big.Int, error) { - ret := _m.Called(opts, fromToken, fromTokenAmount, toToken) - - if len(ret) == 0 { - panic("no return value specified for ConvertTokenAmount") - } - - var r0 *big.Int - var r1 error - if rf, ok := ret.Get(0).(func(*bind.CallOpts, common.Address, *big.Int, common.Address) (*big.Int, error)); ok { - return rf(opts, fromToken, fromTokenAmount, toToken) - } - if rf, ok := ret.Get(0).(func(*bind.CallOpts, common.Address, *big.Int, common.Address) *big.Int); ok { - r0 = rf(opts, fromToken, fromTokenAmount, toToken) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*big.Int) - } - } - - if rf, ok := ret.Get(1).(func(*bind.CallOpts, common.Address, *big.Int, common.Address) error); ok { - r1 = rf(opts, fromToken, fromTokenAmount, toToken) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_ConvertTokenAmount_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ConvertTokenAmount' -type PriceRegistryInterface_ConvertTokenAmount_Call struct { - *mock.Call -} - -// ConvertTokenAmount is a helper method to define mock.On call -// - opts *bind.CallOpts -// - fromToken common.Address -// - fromTokenAmount *big.Int -// - toToken common.Address -func (_e *PriceRegistryInterface_Expecter) ConvertTokenAmount(opts interface{}, fromToken interface{}, fromTokenAmount interface{}, toToken interface{}) *PriceRegistryInterface_ConvertTokenAmount_Call { - return &PriceRegistryInterface_ConvertTokenAmount_Call{Call: _e.mock.On("ConvertTokenAmount", opts, fromToken, fromTokenAmount, toToken)} -} - -func (_c *PriceRegistryInterface_ConvertTokenAmount_Call) Run(run func(opts *bind.CallOpts, fromToken common.Address, fromTokenAmount *big.Int, toToken common.Address)) *PriceRegistryInterface_ConvertTokenAmount_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.CallOpts), args[1].(common.Address), args[2].(*big.Int), args[3].(common.Address)) - }) - return _c -} - -func (_c *PriceRegistryInterface_ConvertTokenAmount_Call) Return(_a0 *big.Int, _a1 error) *PriceRegistryInterface_ConvertTokenAmount_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_ConvertTokenAmount_Call) RunAndReturn(run func(*bind.CallOpts, common.Address, *big.Int, common.Address) (*big.Int, error)) *PriceRegistryInterface_ConvertTokenAmount_Call { - _c.Call.Return(run) - return _c -} - -// FilterAuthorizedCallerAdded provides a mock function with given fields: opts -func (_m *PriceRegistryInterface) FilterAuthorizedCallerAdded(opts *bind.FilterOpts) (*price_registry.PriceRegistryAuthorizedCallerAddedIterator, error) { - ret := _m.Called(opts) - - if len(ret) == 0 { - panic("no return value specified for FilterAuthorizedCallerAdded") - } - - var r0 *price_registry.PriceRegistryAuthorizedCallerAddedIterator - var r1 error - if rf, ok := ret.Get(0).(func(*bind.FilterOpts) (*price_registry.PriceRegistryAuthorizedCallerAddedIterator, error)); ok { - return rf(opts) - } - if rf, ok := ret.Get(0).(func(*bind.FilterOpts) *price_registry.PriceRegistryAuthorizedCallerAddedIterator); ok { - r0 = rf(opts) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*price_registry.PriceRegistryAuthorizedCallerAddedIterator) - } - } - - if rf, ok := ret.Get(1).(func(*bind.FilterOpts) error); ok { - r1 = rf(opts) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_FilterAuthorizedCallerAdded_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterAuthorizedCallerAdded' -type PriceRegistryInterface_FilterAuthorizedCallerAdded_Call struct { - *mock.Call -} - -// FilterAuthorizedCallerAdded is a helper method to define mock.On call -// - opts *bind.FilterOpts -func (_e *PriceRegistryInterface_Expecter) FilterAuthorizedCallerAdded(opts interface{}) *PriceRegistryInterface_FilterAuthorizedCallerAdded_Call { - return &PriceRegistryInterface_FilterAuthorizedCallerAdded_Call{Call: _e.mock.On("FilterAuthorizedCallerAdded", opts)} -} - -func (_c *PriceRegistryInterface_FilterAuthorizedCallerAdded_Call) Run(run func(opts *bind.FilterOpts)) *PriceRegistryInterface_FilterAuthorizedCallerAdded_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.FilterOpts)) - }) - return _c -} - -func (_c *PriceRegistryInterface_FilterAuthorizedCallerAdded_Call) Return(_a0 *price_registry.PriceRegistryAuthorizedCallerAddedIterator, _a1 error) *PriceRegistryInterface_FilterAuthorizedCallerAdded_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_FilterAuthorizedCallerAdded_Call) RunAndReturn(run func(*bind.FilterOpts) (*price_registry.PriceRegistryAuthorizedCallerAddedIterator, error)) *PriceRegistryInterface_FilterAuthorizedCallerAdded_Call { - _c.Call.Return(run) - return _c -} - -// FilterAuthorizedCallerRemoved provides a mock function with given fields: opts -func (_m *PriceRegistryInterface) FilterAuthorizedCallerRemoved(opts *bind.FilterOpts) (*price_registry.PriceRegistryAuthorizedCallerRemovedIterator, error) { - ret := _m.Called(opts) - - if len(ret) == 0 { - panic("no return value specified for FilterAuthorizedCallerRemoved") - } - - var r0 *price_registry.PriceRegistryAuthorizedCallerRemovedIterator - var r1 error - if rf, ok := ret.Get(0).(func(*bind.FilterOpts) (*price_registry.PriceRegistryAuthorizedCallerRemovedIterator, error)); ok { - return rf(opts) - } - if rf, ok := ret.Get(0).(func(*bind.FilterOpts) *price_registry.PriceRegistryAuthorizedCallerRemovedIterator); ok { - r0 = rf(opts) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*price_registry.PriceRegistryAuthorizedCallerRemovedIterator) - } - } - - if rf, ok := ret.Get(1).(func(*bind.FilterOpts) error); ok { - r1 = rf(opts) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_FilterAuthorizedCallerRemoved_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterAuthorizedCallerRemoved' -type PriceRegistryInterface_FilterAuthorizedCallerRemoved_Call struct { - *mock.Call -} - -// FilterAuthorizedCallerRemoved is a helper method to define mock.On call -// - opts *bind.FilterOpts -func (_e *PriceRegistryInterface_Expecter) FilterAuthorizedCallerRemoved(opts interface{}) *PriceRegistryInterface_FilterAuthorizedCallerRemoved_Call { - return &PriceRegistryInterface_FilterAuthorizedCallerRemoved_Call{Call: _e.mock.On("FilterAuthorizedCallerRemoved", opts)} -} - -func (_c *PriceRegistryInterface_FilterAuthorizedCallerRemoved_Call) Run(run func(opts *bind.FilterOpts)) *PriceRegistryInterface_FilterAuthorizedCallerRemoved_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.FilterOpts)) - }) - return _c -} - -func (_c *PriceRegistryInterface_FilterAuthorizedCallerRemoved_Call) Return(_a0 *price_registry.PriceRegistryAuthorizedCallerRemovedIterator, _a1 error) *PriceRegistryInterface_FilterAuthorizedCallerRemoved_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_FilterAuthorizedCallerRemoved_Call) RunAndReturn(run func(*bind.FilterOpts) (*price_registry.PriceRegistryAuthorizedCallerRemovedIterator, error)) *PriceRegistryInterface_FilterAuthorizedCallerRemoved_Call { - _c.Call.Return(run) - return _c -} - -// FilterDestChainAdded provides a mock function with given fields: opts, destChainSelector -func (_m *PriceRegistryInterface) FilterDestChainAdded(opts *bind.FilterOpts, destChainSelector []uint64) (*price_registry.PriceRegistryDestChainAddedIterator, error) { - ret := _m.Called(opts, destChainSelector) - - if len(ret) == 0 { - panic("no return value specified for FilterDestChainAdded") - } - - var r0 *price_registry.PriceRegistryDestChainAddedIterator - var r1 error - if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []uint64) (*price_registry.PriceRegistryDestChainAddedIterator, error)); ok { - return rf(opts, destChainSelector) - } - if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []uint64) *price_registry.PriceRegistryDestChainAddedIterator); ok { - r0 = rf(opts, destChainSelector) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*price_registry.PriceRegistryDestChainAddedIterator) - } - } - - if rf, ok := ret.Get(1).(func(*bind.FilterOpts, []uint64) error); ok { - r1 = rf(opts, destChainSelector) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_FilterDestChainAdded_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterDestChainAdded' -type PriceRegistryInterface_FilterDestChainAdded_Call struct { - *mock.Call -} - -// FilterDestChainAdded is a helper method to define mock.On call -// - opts *bind.FilterOpts -// - destChainSelector []uint64 -func (_e *PriceRegistryInterface_Expecter) FilterDestChainAdded(opts interface{}, destChainSelector interface{}) *PriceRegistryInterface_FilterDestChainAdded_Call { - return &PriceRegistryInterface_FilterDestChainAdded_Call{Call: _e.mock.On("FilterDestChainAdded", opts, destChainSelector)} -} - -func (_c *PriceRegistryInterface_FilterDestChainAdded_Call) Run(run func(opts *bind.FilterOpts, destChainSelector []uint64)) *PriceRegistryInterface_FilterDestChainAdded_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.FilterOpts), args[1].([]uint64)) - }) - return _c -} - -func (_c *PriceRegistryInterface_FilterDestChainAdded_Call) Return(_a0 *price_registry.PriceRegistryDestChainAddedIterator, _a1 error) *PriceRegistryInterface_FilterDestChainAdded_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_FilterDestChainAdded_Call) RunAndReturn(run func(*bind.FilterOpts, []uint64) (*price_registry.PriceRegistryDestChainAddedIterator, error)) *PriceRegistryInterface_FilterDestChainAdded_Call { - _c.Call.Return(run) - return _c -} - -// FilterDestChainConfigUpdated provides a mock function with given fields: opts, destChainSelector -func (_m *PriceRegistryInterface) FilterDestChainConfigUpdated(opts *bind.FilterOpts, destChainSelector []uint64) (*price_registry.PriceRegistryDestChainConfigUpdatedIterator, error) { - ret := _m.Called(opts, destChainSelector) - - if len(ret) == 0 { - panic("no return value specified for FilterDestChainConfigUpdated") - } - - var r0 *price_registry.PriceRegistryDestChainConfigUpdatedIterator - var r1 error - if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []uint64) (*price_registry.PriceRegistryDestChainConfigUpdatedIterator, error)); ok { - return rf(opts, destChainSelector) - } - if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []uint64) *price_registry.PriceRegistryDestChainConfigUpdatedIterator); ok { - r0 = rf(opts, destChainSelector) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*price_registry.PriceRegistryDestChainConfigUpdatedIterator) - } - } - - if rf, ok := ret.Get(1).(func(*bind.FilterOpts, []uint64) error); ok { - r1 = rf(opts, destChainSelector) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_FilterDestChainConfigUpdated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterDestChainConfigUpdated' -type PriceRegistryInterface_FilterDestChainConfigUpdated_Call struct { - *mock.Call -} - -// FilterDestChainConfigUpdated is a helper method to define mock.On call -// - opts *bind.FilterOpts -// - destChainSelector []uint64 -func (_e *PriceRegistryInterface_Expecter) FilterDestChainConfigUpdated(opts interface{}, destChainSelector interface{}) *PriceRegistryInterface_FilterDestChainConfigUpdated_Call { - return &PriceRegistryInterface_FilterDestChainConfigUpdated_Call{Call: _e.mock.On("FilterDestChainConfigUpdated", opts, destChainSelector)} -} - -func (_c *PriceRegistryInterface_FilterDestChainConfigUpdated_Call) Run(run func(opts *bind.FilterOpts, destChainSelector []uint64)) *PriceRegistryInterface_FilterDestChainConfigUpdated_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.FilterOpts), args[1].([]uint64)) - }) - return _c -} - -func (_c *PriceRegistryInterface_FilterDestChainConfigUpdated_Call) Return(_a0 *price_registry.PriceRegistryDestChainConfigUpdatedIterator, _a1 error) *PriceRegistryInterface_FilterDestChainConfigUpdated_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_FilterDestChainConfigUpdated_Call) RunAndReturn(run func(*bind.FilterOpts, []uint64) (*price_registry.PriceRegistryDestChainConfigUpdatedIterator, error)) *PriceRegistryInterface_FilterDestChainConfigUpdated_Call { - _c.Call.Return(run) - return _c -} - -// FilterFeeTokenAdded provides a mock function with given fields: opts, feeToken -func (_m *PriceRegistryInterface) FilterFeeTokenAdded(opts *bind.FilterOpts, feeToken []common.Address) (*price_registry.PriceRegistryFeeTokenAddedIterator, error) { - ret := _m.Called(opts, feeToken) - - if len(ret) == 0 { - panic("no return value specified for FilterFeeTokenAdded") - } - - var r0 *price_registry.PriceRegistryFeeTokenAddedIterator - var r1 error - if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []common.Address) (*price_registry.PriceRegistryFeeTokenAddedIterator, error)); ok { - return rf(opts, feeToken) - } - if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []common.Address) *price_registry.PriceRegistryFeeTokenAddedIterator); ok { - r0 = rf(opts, feeToken) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*price_registry.PriceRegistryFeeTokenAddedIterator) - } - } - - if rf, ok := ret.Get(1).(func(*bind.FilterOpts, []common.Address) error); ok { - r1 = rf(opts, feeToken) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_FilterFeeTokenAdded_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterFeeTokenAdded' -type PriceRegistryInterface_FilterFeeTokenAdded_Call struct { - *mock.Call -} - -// FilterFeeTokenAdded is a helper method to define mock.On call -// - opts *bind.FilterOpts -// - feeToken []common.Address -func (_e *PriceRegistryInterface_Expecter) FilterFeeTokenAdded(opts interface{}, feeToken interface{}) *PriceRegistryInterface_FilterFeeTokenAdded_Call { - return &PriceRegistryInterface_FilterFeeTokenAdded_Call{Call: _e.mock.On("FilterFeeTokenAdded", opts, feeToken)} -} - -func (_c *PriceRegistryInterface_FilterFeeTokenAdded_Call) Run(run func(opts *bind.FilterOpts, feeToken []common.Address)) *PriceRegistryInterface_FilterFeeTokenAdded_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.FilterOpts), args[1].([]common.Address)) - }) - return _c -} - -func (_c *PriceRegistryInterface_FilterFeeTokenAdded_Call) Return(_a0 *price_registry.PriceRegistryFeeTokenAddedIterator, _a1 error) *PriceRegistryInterface_FilterFeeTokenAdded_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_FilterFeeTokenAdded_Call) RunAndReturn(run func(*bind.FilterOpts, []common.Address) (*price_registry.PriceRegistryFeeTokenAddedIterator, error)) *PriceRegistryInterface_FilterFeeTokenAdded_Call { - _c.Call.Return(run) - return _c -} - -// FilterFeeTokenRemoved provides a mock function with given fields: opts, feeToken -func (_m *PriceRegistryInterface) FilterFeeTokenRemoved(opts *bind.FilterOpts, feeToken []common.Address) (*price_registry.PriceRegistryFeeTokenRemovedIterator, error) { - ret := _m.Called(opts, feeToken) - - if len(ret) == 0 { - panic("no return value specified for FilterFeeTokenRemoved") - } - - var r0 *price_registry.PriceRegistryFeeTokenRemovedIterator - var r1 error - if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []common.Address) (*price_registry.PriceRegistryFeeTokenRemovedIterator, error)); ok { - return rf(opts, feeToken) - } - if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []common.Address) *price_registry.PriceRegistryFeeTokenRemovedIterator); ok { - r0 = rf(opts, feeToken) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*price_registry.PriceRegistryFeeTokenRemovedIterator) - } - } - - if rf, ok := ret.Get(1).(func(*bind.FilterOpts, []common.Address) error); ok { - r1 = rf(opts, feeToken) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_FilterFeeTokenRemoved_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterFeeTokenRemoved' -type PriceRegistryInterface_FilterFeeTokenRemoved_Call struct { - *mock.Call -} - -// FilterFeeTokenRemoved is a helper method to define mock.On call -// - opts *bind.FilterOpts -// - feeToken []common.Address -func (_e *PriceRegistryInterface_Expecter) FilterFeeTokenRemoved(opts interface{}, feeToken interface{}) *PriceRegistryInterface_FilterFeeTokenRemoved_Call { - return &PriceRegistryInterface_FilterFeeTokenRemoved_Call{Call: _e.mock.On("FilterFeeTokenRemoved", opts, feeToken)} -} - -func (_c *PriceRegistryInterface_FilterFeeTokenRemoved_Call) Run(run func(opts *bind.FilterOpts, feeToken []common.Address)) *PriceRegistryInterface_FilterFeeTokenRemoved_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.FilterOpts), args[1].([]common.Address)) - }) - return _c -} - -func (_c *PriceRegistryInterface_FilterFeeTokenRemoved_Call) Return(_a0 *price_registry.PriceRegistryFeeTokenRemovedIterator, _a1 error) *PriceRegistryInterface_FilterFeeTokenRemoved_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_FilterFeeTokenRemoved_Call) RunAndReturn(run func(*bind.FilterOpts, []common.Address) (*price_registry.PriceRegistryFeeTokenRemovedIterator, error)) *PriceRegistryInterface_FilterFeeTokenRemoved_Call { - _c.Call.Return(run) - return _c -} - -// FilterOwnershipTransferRequested provides a mock function with given fields: opts, from, to -func (_m *PriceRegistryInterface) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*price_registry.PriceRegistryOwnershipTransferRequestedIterator, error) { - ret := _m.Called(opts, from, to) - - if len(ret) == 0 { - panic("no return value specified for FilterOwnershipTransferRequested") - } - - var r0 *price_registry.PriceRegistryOwnershipTransferRequestedIterator - var r1 error - if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []common.Address, []common.Address) (*price_registry.PriceRegistryOwnershipTransferRequestedIterator, error)); ok { - return rf(opts, from, to) - } - if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []common.Address, []common.Address) *price_registry.PriceRegistryOwnershipTransferRequestedIterator); ok { - r0 = rf(opts, from, to) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*price_registry.PriceRegistryOwnershipTransferRequestedIterator) - } - } - - if rf, ok := ret.Get(1).(func(*bind.FilterOpts, []common.Address, []common.Address) error); ok { - r1 = rf(opts, from, to) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_FilterOwnershipTransferRequested_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterOwnershipTransferRequested' -type PriceRegistryInterface_FilterOwnershipTransferRequested_Call struct { - *mock.Call -} - -// FilterOwnershipTransferRequested is a helper method to define mock.On call -// - opts *bind.FilterOpts -// - from []common.Address -// - to []common.Address -func (_e *PriceRegistryInterface_Expecter) FilterOwnershipTransferRequested(opts interface{}, from interface{}, to interface{}) *PriceRegistryInterface_FilterOwnershipTransferRequested_Call { - return &PriceRegistryInterface_FilterOwnershipTransferRequested_Call{Call: _e.mock.On("FilterOwnershipTransferRequested", opts, from, to)} -} - -func (_c *PriceRegistryInterface_FilterOwnershipTransferRequested_Call) Run(run func(opts *bind.FilterOpts, from []common.Address, to []common.Address)) *PriceRegistryInterface_FilterOwnershipTransferRequested_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.FilterOpts), args[1].([]common.Address), args[2].([]common.Address)) - }) - return _c -} - -func (_c *PriceRegistryInterface_FilterOwnershipTransferRequested_Call) Return(_a0 *price_registry.PriceRegistryOwnershipTransferRequestedIterator, _a1 error) *PriceRegistryInterface_FilterOwnershipTransferRequested_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_FilterOwnershipTransferRequested_Call) RunAndReturn(run func(*bind.FilterOpts, []common.Address, []common.Address) (*price_registry.PriceRegistryOwnershipTransferRequestedIterator, error)) *PriceRegistryInterface_FilterOwnershipTransferRequested_Call { - _c.Call.Return(run) - return _c -} - -// FilterOwnershipTransferred provides a mock function with given fields: opts, from, to -func (_m *PriceRegistryInterface) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*price_registry.PriceRegistryOwnershipTransferredIterator, error) { - ret := _m.Called(opts, from, to) - - if len(ret) == 0 { - panic("no return value specified for FilterOwnershipTransferred") - } - - var r0 *price_registry.PriceRegistryOwnershipTransferredIterator - var r1 error - if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []common.Address, []common.Address) (*price_registry.PriceRegistryOwnershipTransferredIterator, error)); ok { - return rf(opts, from, to) - } - if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []common.Address, []common.Address) *price_registry.PriceRegistryOwnershipTransferredIterator); ok { - r0 = rf(opts, from, to) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*price_registry.PriceRegistryOwnershipTransferredIterator) - } - } - - if rf, ok := ret.Get(1).(func(*bind.FilterOpts, []common.Address, []common.Address) error); ok { - r1 = rf(opts, from, to) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_FilterOwnershipTransferred_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterOwnershipTransferred' -type PriceRegistryInterface_FilterOwnershipTransferred_Call struct { - *mock.Call -} - -// FilterOwnershipTransferred is a helper method to define mock.On call -// - opts *bind.FilterOpts -// - from []common.Address -// - to []common.Address -func (_e *PriceRegistryInterface_Expecter) FilterOwnershipTransferred(opts interface{}, from interface{}, to interface{}) *PriceRegistryInterface_FilterOwnershipTransferred_Call { - return &PriceRegistryInterface_FilterOwnershipTransferred_Call{Call: _e.mock.On("FilterOwnershipTransferred", opts, from, to)} -} - -func (_c *PriceRegistryInterface_FilterOwnershipTransferred_Call) Run(run func(opts *bind.FilterOpts, from []common.Address, to []common.Address)) *PriceRegistryInterface_FilterOwnershipTransferred_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.FilterOpts), args[1].([]common.Address), args[2].([]common.Address)) - }) - return _c -} - -func (_c *PriceRegistryInterface_FilterOwnershipTransferred_Call) Return(_a0 *price_registry.PriceRegistryOwnershipTransferredIterator, _a1 error) *PriceRegistryInterface_FilterOwnershipTransferred_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_FilterOwnershipTransferred_Call) RunAndReturn(run func(*bind.FilterOpts, []common.Address, []common.Address) (*price_registry.PriceRegistryOwnershipTransferredIterator, error)) *PriceRegistryInterface_FilterOwnershipTransferred_Call { - _c.Call.Return(run) - return _c -} - -// FilterPremiumMultiplierWeiPerEthUpdated provides a mock function with given fields: opts, token -func (_m *PriceRegistryInterface) FilterPremiumMultiplierWeiPerEthUpdated(opts *bind.FilterOpts, token []common.Address) (*price_registry.PriceRegistryPremiumMultiplierWeiPerEthUpdatedIterator, error) { - ret := _m.Called(opts, token) - - if len(ret) == 0 { - panic("no return value specified for FilterPremiumMultiplierWeiPerEthUpdated") - } - - var r0 *price_registry.PriceRegistryPremiumMultiplierWeiPerEthUpdatedIterator - var r1 error - if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []common.Address) (*price_registry.PriceRegistryPremiumMultiplierWeiPerEthUpdatedIterator, error)); ok { - return rf(opts, token) - } - if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []common.Address) *price_registry.PriceRegistryPremiumMultiplierWeiPerEthUpdatedIterator); ok { - r0 = rf(opts, token) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*price_registry.PriceRegistryPremiumMultiplierWeiPerEthUpdatedIterator) - } - } - - if rf, ok := ret.Get(1).(func(*bind.FilterOpts, []common.Address) error); ok { - r1 = rf(opts, token) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_FilterPremiumMultiplierWeiPerEthUpdated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterPremiumMultiplierWeiPerEthUpdated' -type PriceRegistryInterface_FilterPremiumMultiplierWeiPerEthUpdated_Call struct { - *mock.Call -} - -// FilterPremiumMultiplierWeiPerEthUpdated is a helper method to define mock.On call -// - opts *bind.FilterOpts -// - token []common.Address -func (_e *PriceRegistryInterface_Expecter) FilterPremiumMultiplierWeiPerEthUpdated(opts interface{}, token interface{}) *PriceRegistryInterface_FilterPremiumMultiplierWeiPerEthUpdated_Call { - return &PriceRegistryInterface_FilterPremiumMultiplierWeiPerEthUpdated_Call{Call: _e.mock.On("FilterPremiumMultiplierWeiPerEthUpdated", opts, token)} -} - -func (_c *PriceRegistryInterface_FilterPremiumMultiplierWeiPerEthUpdated_Call) Run(run func(opts *bind.FilterOpts, token []common.Address)) *PriceRegistryInterface_FilterPremiumMultiplierWeiPerEthUpdated_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.FilterOpts), args[1].([]common.Address)) - }) - return _c -} - -func (_c *PriceRegistryInterface_FilterPremiumMultiplierWeiPerEthUpdated_Call) Return(_a0 *price_registry.PriceRegistryPremiumMultiplierWeiPerEthUpdatedIterator, _a1 error) *PriceRegistryInterface_FilterPremiumMultiplierWeiPerEthUpdated_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_FilterPremiumMultiplierWeiPerEthUpdated_Call) RunAndReturn(run func(*bind.FilterOpts, []common.Address) (*price_registry.PriceRegistryPremiumMultiplierWeiPerEthUpdatedIterator, error)) *PriceRegistryInterface_FilterPremiumMultiplierWeiPerEthUpdated_Call { - _c.Call.Return(run) - return _c -} - -// FilterPriceFeedPerTokenUpdated provides a mock function with given fields: opts, token -func (_m *PriceRegistryInterface) FilterPriceFeedPerTokenUpdated(opts *bind.FilterOpts, token []common.Address) (*price_registry.PriceRegistryPriceFeedPerTokenUpdatedIterator, error) { - ret := _m.Called(opts, token) - - if len(ret) == 0 { - panic("no return value specified for FilterPriceFeedPerTokenUpdated") - } - - var r0 *price_registry.PriceRegistryPriceFeedPerTokenUpdatedIterator - var r1 error - if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []common.Address) (*price_registry.PriceRegistryPriceFeedPerTokenUpdatedIterator, error)); ok { - return rf(opts, token) - } - if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []common.Address) *price_registry.PriceRegistryPriceFeedPerTokenUpdatedIterator); ok { - r0 = rf(opts, token) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*price_registry.PriceRegistryPriceFeedPerTokenUpdatedIterator) - } - } - - if rf, ok := ret.Get(1).(func(*bind.FilterOpts, []common.Address) error); ok { - r1 = rf(opts, token) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_FilterPriceFeedPerTokenUpdated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterPriceFeedPerTokenUpdated' -type PriceRegistryInterface_FilterPriceFeedPerTokenUpdated_Call struct { - *mock.Call -} - -// FilterPriceFeedPerTokenUpdated is a helper method to define mock.On call -// - opts *bind.FilterOpts -// - token []common.Address -func (_e *PriceRegistryInterface_Expecter) FilterPriceFeedPerTokenUpdated(opts interface{}, token interface{}) *PriceRegistryInterface_FilterPriceFeedPerTokenUpdated_Call { - return &PriceRegistryInterface_FilterPriceFeedPerTokenUpdated_Call{Call: _e.mock.On("FilterPriceFeedPerTokenUpdated", opts, token)} -} - -func (_c *PriceRegistryInterface_FilterPriceFeedPerTokenUpdated_Call) Run(run func(opts *bind.FilterOpts, token []common.Address)) *PriceRegistryInterface_FilterPriceFeedPerTokenUpdated_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.FilterOpts), args[1].([]common.Address)) - }) - return _c -} - -func (_c *PriceRegistryInterface_FilterPriceFeedPerTokenUpdated_Call) Return(_a0 *price_registry.PriceRegistryPriceFeedPerTokenUpdatedIterator, _a1 error) *PriceRegistryInterface_FilterPriceFeedPerTokenUpdated_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_FilterPriceFeedPerTokenUpdated_Call) RunAndReturn(run func(*bind.FilterOpts, []common.Address) (*price_registry.PriceRegistryPriceFeedPerTokenUpdatedIterator, error)) *PriceRegistryInterface_FilterPriceFeedPerTokenUpdated_Call { - _c.Call.Return(run) - return _c -} - -// FilterReportPermissionSet provides a mock function with given fields: opts, reportId -func (_m *PriceRegistryInterface) FilterReportPermissionSet(opts *bind.FilterOpts, reportId [][32]byte) (*price_registry.PriceRegistryReportPermissionSetIterator, error) { - ret := _m.Called(opts, reportId) - - if len(ret) == 0 { - panic("no return value specified for FilterReportPermissionSet") - } - - var r0 *price_registry.PriceRegistryReportPermissionSetIterator - var r1 error - if rf, ok := ret.Get(0).(func(*bind.FilterOpts, [][32]byte) (*price_registry.PriceRegistryReportPermissionSetIterator, error)); ok { - return rf(opts, reportId) - } - if rf, ok := ret.Get(0).(func(*bind.FilterOpts, [][32]byte) *price_registry.PriceRegistryReportPermissionSetIterator); ok { - r0 = rf(opts, reportId) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*price_registry.PriceRegistryReportPermissionSetIterator) - } - } - - if rf, ok := ret.Get(1).(func(*bind.FilterOpts, [][32]byte) error); ok { - r1 = rf(opts, reportId) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_FilterReportPermissionSet_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterReportPermissionSet' -type PriceRegistryInterface_FilterReportPermissionSet_Call struct { - *mock.Call -} - -// FilterReportPermissionSet is a helper method to define mock.On call -// - opts *bind.FilterOpts -// - reportId [][32]byte -func (_e *PriceRegistryInterface_Expecter) FilterReportPermissionSet(opts interface{}, reportId interface{}) *PriceRegistryInterface_FilterReportPermissionSet_Call { - return &PriceRegistryInterface_FilterReportPermissionSet_Call{Call: _e.mock.On("FilterReportPermissionSet", opts, reportId)} -} - -func (_c *PriceRegistryInterface_FilterReportPermissionSet_Call) Run(run func(opts *bind.FilterOpts, reportId [][32]byte)) *PriceRegistryInterface_FilterReportPermissionSet_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.FilterOpts), args[1].([][32]byte)) - }) - return _c -} - -func (_c *PriceRegistryInterface_FilterReportPermissionSet_Call) Return(_a0 *price_registry.PriceRegistryReportPermissionSetIterator, _a1 error) *PriceRegistryInterface_FilterReportPermissionSet_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_FilterReportPermissionSet_Call) RunAndReturn(run func(*bind.FilterOpts, [][32]byte) (*price_registry.PriceRegistryReportPermissionSetIterator, error)) *PriceRegistryInterface_FilterReportPermissionSet_Call { - _c.Call.Return(run) - return _c -} - -// FilterTokenTransferFeeConfigDeleted provides a mock function with given fields: opts, destChainSelector, token -func (_m *PriceRegistryInterface) FilterTokenTransferFeeConfigDeleted(opts *bind.FilterOpts, destChainSelector []uint64, token []common.Address) (*price_registry.PriceRegistryTokenTransferFeeConfigDeletedIterator, error) { - ret := _m.Called(opts, destChainSelector, token) - - if len(ret) == 0 { - panic("no return value specified for FilterTokenTransferFeeConfigDeleted") - } - - var r0 *price_registry.PriceRegistryTokenTransferFeeConfigDeletedIterator - var r1 error - if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []uint64, []common.Address) (*price_registry.PriceRegistryTokenTransferFeeConfigDeletedIterator, error)); ok { - return rf(opts, destChainSelector, token) - } - if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []uint64, []common.Address) *price_registry.PriceRegistryTokenTransferFeeConfigDeletedIterator); ok { - r0 = rf(opts, destChainSelector, token) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*price_registry.PriceRegistryTokenTransferFeeConfigDeletedIterator) - } - } - - if rf, ok := ret.Get(1).(func(*bind.FilterOpts, []uint64, []common.Address) error); ok { - r1 = rf(opts, destChainSelector, token) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_FilterTokenTransferFeeConfigDeleted_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterTokenTransferFeeConfigDeleted' -type PriceRegistryInterface_FilterTokenTransferFeeConfigDeleted_Call struct { - *mock.Call -} - -// FilterTokenTransferFeeConfigDeleted is a helper method to define mock.On call -// - opts *bind.FilterOpts -// - destChainSelector []uint64 -// - token []common.Address -func (_e *PriceRegistryInterface_Expecter) FilterTokenTransferFeeConfigDeleted(opts interface{}, destChainSelector interface{}, token interface{}) *PriceRegistryInterface_FilterTokenTransferFeeConfigDeleted_Call { - return &PriceRegistryInterface_FilterTokenTransferFeeConfigDeleted_Call{Call: _e.mock.On("FilterTokenTransferFeeConfigDeleted", opts, destChainSelector, token)} -} - -func (_c *PriceRegistryInterface_FilterTokenTransferFeeConfigDeleted_Call) Run(run func(opts *bind.FilterOpts, destChainSelector []uint64, token []common.Address)) *PriceRegistryInterface_FilterTokenTransferFeeConfigDeleted_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.FilterOpts), args[1].([]uint64), args[2].([]common.Address)) - }) - return _c -} - -func (_c *PriceRegistryInterface_FilterTokenTransferFeeConfigDeleted_Call) Return(_a0 *price_registry.PriceRegistryTokenTransferFeeConfigDeletedIterator, _a1 error) *PriceRegistryInterface_FilterTokenTransferFeeConfigDeleted_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_FilterTokenTransferFeeConfigDeleted_Call) RunAndReturn(run func(*bind.FilterOpts, []uint64, []common.Address) (*price_registry.PriceRegistryTokenTransferFeeConfigDeletedIterator, error)) *PriceRegistryInterface_FilterTokenTransferFeeConfigDeleted_Call { - _c.Call.Return(run) - return _c -} - -// FilterTokenTransferFeeConfigUpdated provides a mock function with given fields: opts, destChainSelector, token -func (_m *PriceRegistryInterface) FilterTokenTransferFeeConfigUpdated(opts *bind.FilterOpts, destChainSelector []uint64, token []common.Address) (*price_registry.PriceRegistryTokenTransferFeeConfigUpdatedIterator, error) { - ret := _m.Called(opts, destChainSelector, token) - - if len(ret) == 0 { - panic("no return value specified for FilterTokenTransferFeeConfigUpdated") - } - - var r0 *price_registry.PriceRegistryTokenTransferFeeConfigUpdatedIterator - var r1 error - if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []uint64, []common.Address) (*price_registry.PriceRegistryTokenTransferFeeConfigUpdatedIterator, error)); ok { - return rf(opts, destChainSelector, token) - } - if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []uint64, []common.Address) *price_registry.PriceRegistryTokenTransferFeeConfigUpdatedIterator); ok { - r0 = rf(opts, destChainSelector, token) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*price_registry.PriceRegistryTokenTransferFeeConfigUpdatedIterator) - } - } - - if rf, ok := ret.Get(1).(func(*bind.FilterOpts, []uint64, []common.Address) error); ok { - r1 = rf(opts, destChainSelector, token) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_FilterTokenTransferFeeConfigUpdated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterTokenTransferFeeConfigUpdated' -type PriceRegistryInterface_FilterTokenTransferFeeConfigUpdated_Call struct { - *mock.Call -} - -// FilterTokenTransferFeeConfigUpdated is a helper method to define mock.On call -// - opts *bind.FilterOpts -// - destChainSelector []uint64 -// - token []common.Address -func (_e *PriceRegistryInterface_Expecter) FilterTokenTransferFeeConfigUpdated(opts interface{}, destChainSelector interface{}, token interface{}) *PriceRegistryInterface_FilterTokenTransferFeeConfigUpdated_Call { - return &PriceRegistryInterface_FilterTokenTransferFeeConfigUpdated_Call{Call: _e.mock.On("FilterTokenTransferFeeConfigUpdated", opts, destChainSelector, token)} -} - -func (_c *PriceRegistryInterface_FilterTokenTransferFeeConfigUpdated_Call) Run(run func(opts *bind.FilterOpts, destChainSelector []uint64, token []common.Address)) *PriceRegistryInterface_FilterTokenTransferFeeConfigUpdated_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.FilterOpts), args[1].([]uint64), args[2].([]common.Address)) - }) - return _c -} - -func (_c *PriceRegistryInterface_FilterTokenTransferFeeConfigUpdated_Call) Return(_a0 *price_registry.PriceRegistryTokenTransferFeeConfigUpdatedIterator, _a1 error) *PriceRegistryInterface_FilterTokenTransferFeeConfigUpdated_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_FilterTokenTransferFeeConfigUpdated_Call) RunAndReturn(run func(*bind.FilterOpts, []uint64, []common.Address) (*price_registry.PriceRegistryTokenTransferFeeConfigUpdatedIterator, error)) *PriceRegistryInterface_FilterTokenTransferFeeConfigUpdated_Call { - _c.Call.Return(run) - return _c -} - -// FilterUsdPerTokenUpdated provides a mock function with given fields: opts, token -func (_m *PriceRegistryInterface) FilterUsdPerTokenUpdated(opts *bind.FilterOpts, token []common.Address) (*price_registry.PriceRegistryUsdPerTokenUpdatedIterator, error) { - ret := _m.Called(opts, token) - - if len(ret) == 0 { - panic("no return value specified for FilterUsdPerTokenUpdated") - } - - var r0 *price_registry.PriceRegistryUsdPerTokenUpdatedIterator - var r1 error - if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []common.Address) (*price_registry.PriceRegistryUsdPerTokenUpdatedIterator, error)); ok { - return rf(opts, token) - } - if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []common.Address) *price_registry.PriceRegistryUsdPerTokenUpdatedIterator); ok { - r0 = rf(opts, token) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*price_registry.PriceRegistryUsdPerTokenUpdatedIterator) - } - } - - if rf, ok := ret.Get(1).(func(*bind.FilterOpts, []common.Address) error); ok { - r1 = rf(opts, token) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_FilterUsdPerTokenUpdated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterUsdPerTokenUpdated' -type PriceRegistryInterface_FilterUsdPerTokenUpdated_Call struct { - *mock.Call -} - -// FilterUsdPerTokenUpdated is a helper method to define mock.On call -// - opts *bind.FilterOpts -// - token []common.Address -func (_e *PriceRegistryInterface_Expecter) FilterUsdPerTokenUpdated(opts interface{}, token interface{}) *PriceRegistryInterface_FilterUsdPerTokenUpdated_Call { - return &PriceRegistryInterface_FilterUsdPerTokenUpdated_Call{Call: _e.mock.On("FilterUsdPerTokenUpdated", opts, token)} -} - -func (_c *PriceRegistryInterface_FilterUsdPerTokenUpdated_Call) Run(run func(opts *bind.FilterOpts, token []common.Address)) *PriceRegistryInterface_FilterUsdPerTokenUpdated_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.FilterOpts), args[1].([]common.Address)) - }) - return _c -} - -func (_c *PriceRegistryInterface_FilterUsdPerTokenUpdated_Call) Return(_a0 *price_registry.PriceRegistryUsdPerTokenUpdatedIterator, _a1 error) *PriceRegistryInterface_FilterUsdPerTokenUpdated_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_FilterUsdPerTokenUpdated_Call) RunAndReturn(run func(*bind.FilterOpts, []common.Address) (*price_registry.PriceRegistryUsdPerTokenUpdatedIterator, error)) *PriceRegistryInterface_FilterUsdPerTokenUpdated_Call { - _c.Call.Return(run) - return _c -} - -// FilterUsdPerUnitGasUpdated provides a mock function with given fields: opts, destChain -func (_m *PriceRegistryInterface) FilterUsdPerUnitGasUpdated(opts *bind.FilterOpts, destChain []uint64) (*price_registry.PriceRegistryUsdPerUnitGasUpdatedIterator, error) { - ret := _m.Called(opts, destChain) - - if len(ret) == 0 { - panic("no return value specified for FilterUsdPerUnitGasUpdated") - } - - var r0 *price_registry.PriceRegistryUsdPerUnitGasUpdatedIterator - var r1 error - if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []uint64) (*price_registry.PriceRegistryUsdPerUnitGasUpdatedIterator, error)); ok { - return rf(opts, destChain) - } - if rf, ok := ret.Get(0).(func(*bind.FilterOpts, []uint64) *price_registry.PriceRegistryUsdPerUnitGasUpdatedIterator); ok { - r0 = rf(opts, destChain) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*price_registry.PriceRegistryUsdPerUnitGasUpdatedIterator) - } - } - - if rf, ok := ret.Get(1).(func(*bind.FilterOpts, []uint64) error); ok { - r1 = rf(opts, destChain) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_FilterUsdPerUnitGasUpdated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FilterUsdPerUnitGasUpdated' -type PriceRegistryInterface_FilterUsdPerUnitGasUpdated_Call struct { - *mock.Call -} - -// FilterUsdPerUnitGasUpdated is a helper method to define mock.On call -// - opts *bind.FilterOpts -// - destChain []uint64 -func (_e *PriceRegistryInterface_Expecter) FilterUsdPerUnitGasUpdated(opts interface{}, destChain interface{}) *PriceRegistryInterface_FilterUsdPerUnitGasUpdated_Call { - return &PriceRegistryInterface_FilterUsdPerUnitGasUpdated_Call{Call: _e.mock.On("FilterUsdPerUnitGasUpdated", opts, destChain)} -} - -func (_c *PriceRegistryInterface_FilterUsdPerUnitGasUpdated_Call) Run(run func(opts *bind.FilterOpts, destChain []uint64)) *PriceRegistryInterface_FilterUsdPerUnitGasUpdated_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.FilterOpts), args[1].([]uint64)) - }) - return _c -} - -func (_c *PriceRegistryInterface_FilterUsdPerUnitGasUpdated_Call) Return(_a0 *price_registry.PriceRegistryUsdPerUnitGasUpdatedIterator, _a1 error) *PriceRegistryInterface_FilterUsdPerUnitGasUpdated_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_FilterUsdPerUnitGasUpdated_Call) RunAndReturn(run func(*bind.FilterOpts, []uint64) (*price_registry.PriceRegistryUsdPerUnitGasUpdatedIterator, error)) *PriceRegistryInterface_FilterUsdPerUnitGasUpdated_Call { - _c.Call.Return(run) - return _c -} - -// GetAllAuthorizedCallers provides a mock function with given fields: opts -func (_m *PriceRegistryInterface) GetAllAuthorizedCallers(opts *bind.CallOpts) ([]common.Address, error) { - ret := _m.Called(opts) - - if len(ret) == 0 { - panic("no return value specified for GetAllAuthorizedCallers") - } - - var r0 []common.Address - var r1 error - if rf, ok := ret.Get(0).(func(*bind.CallOpts) ([]common.Address, error)); ok { - return rf(opts) - } - if rf, ok := ret.Get(0).(func(*bind.CallOpts) []common.Address); ok { - r0 = rf(opts) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]common.Address) - } - } - - if rf, ok := ret.Get(1).(func(*bind.CallOpts) error); ok { - r1 = rf(opts) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_GetAllAuthorizedCallers_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetAllAuthorizedCallers' -type PriceRegistryInterface_GetAllAuthorizedCallers_Call struct { - *mock.Call -} - -// GetAllAuthorizedCallers is a helper method to define mock.On call -// - opts *bind.CallOpts -func (_e *PriceRegistryInterface_Expecter) GetAllAuthorizedCallers(opts interface{}) *PriceRegistryInterface_GetAllAuthorizedCallers_Call { - return &PriceRegistryInterface_GetAllAuthorizedCallers_Call{Call: _e.mock.On("GetAllAuthorizedCallers", opts)} -} - -func (_c *PriceRegistryInterface_GetAllAuthorizedCallers_Call) Run(run func(opts *bind.CallOpts)) *PriceRegistryInterface_GetAllAuthorizedCallers_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.CallOpts)) - }) - return _c -} - -func (_c *PriceRegistryInterface_GetAllAuthorizedCallers_Call) Return(_a0 []common.Address, _a1 error) *PriceRegistryInterface_GetAllAuthorizedCallers_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_GetAllAuthorizedCallers_Call) RunAndReturn(run func(*bind.CallOpts) ([]common.Address, error)) *PriceRegistryInterface_GetAllAuthorizedCallers_Call { - _c.Call.Return(run) - return _c -} - -// GetDestChainConfig provides a mock function with given fields: opts, destChainSelector -func (_m *PriceRegistryInterface) GetDestChainConfig(opts *bind.CallOpts, destChainSelector uint64) (price_registry.PriceRegistryDestChainConfig, error) { - ret := _m.Called(opts, destChainSelector) - - if len(ret) == 0 { - panic("no return value specified for GetDestChainConfig") - } - - var r0 price_registry.PriceRegistryDestChainConfig - var r1 error - if rf, ok := ret.Get(0).(func(*bind.CallOpts, uint64) (price_registry.PriceRegistryDestChainConfig, error)); ok { - return rf(opts, destChainSelector) - } - if rf, ok := ret.Get(0).(func(*bind.CallOpts, uint64) price_registry.PriceRegistryDestChainConfig); ok { - r0 = rf(opts, destChainSelector) - } else { - r0 = ret.Get(0).(price_registry.PriceRegistryDestChainConfig) - } - - if rf, ok := ret.Get(1).(func(*bind.CallOpts, uint64) error); ok { - r1 = rf(opts, destChainSelector) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_GetDestChainConfig_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetDestChainConfig' -type PriceRegistryInterface_GetDestChainConfig_Call struct { - *mock.Call -} - -// GetDestChainConfig is a helper method to define mock.On call -// - opts *bind.CallOpts -// - destChainSelector uint64 -func (_e *PriceRegistryInterface_Expecter) GetDestChainConfig(opts interface{}, destChainSelector interface{}) *PriceRegistryInterface_GetDestChainConfig_Call { - return &PriceRegistryInterface_GetDestChainConfig_Call{Call: _e.mock.On("GetDestChainConfig", opts, destChainSelector)} -} - -func (_c *PriceRegistryInterface_GetDestChainConfig_Call) Run(run func(opts *bind.CallOpts, destChainSelector uint64)) *PriceRegistryInterface_GetDestChainConfig_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.CallOpts), args[1].(uint64)) - }) - return _c -} - -func (_c *PriceRegistryInterface_GetDestChainConfig_Call) Return(_a0 price_registry.PriceRegistryDestChainConfig, _a1 error) *PriceRegistryInterface_GetDestChainConfig_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_GetDestChainConfig_Call) RunAndReturn(run func(*bind.CallOpts, uint64) (price_registry.PriceRegistryDestChainConfig, error)) *PriceRegistryInterface_GetDestChainConfig_Call { - _c.Call.Return(run) - return _c -} - -// GetDestinationChainGasPrice provides a mock function with given fields: opts, destChainSelector -func (_m *PriceRegistryInterface) GetDestinationChainGasPrice(opts *bind.CallOpts, destChainSelector uint64) (price_registry.InternalTimestampedPackedUint224, error) { - ret := _m.Called(opts, destChainSelector) - - if len(ret) == 0 { - panic("no return value specified for GetDestinationChainGasPrice") - } - - var r0 price_registry.InternalTimestampedPackedUint224 - var r1 error - if rf, ok := ret.Get(0).(func(*bind.CallOpts, uint64) (price_registry.InternalTimestampedPackedUint224, error)); ok { - return rf(opts, destChainSelector) - } - if rf, ok := ret.Get(0).(func(*bind.CallOpts, uint64) price_registry.InternalTimestampedPackedUint224); ok { - r0 = rf(opts, destChainSelector) - } else { - r0 = ret.Get(0).(price_registry.InternalTimestampedPackedUint224) - } - - if rf, ok := ret.Get(1).(func(*bind.CallOpts, uint64) error); ok { - r1 = rf(opts, destChainSelector) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_GetDestinationChainGasPrice_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetDestinationChainGasPrice' -type PriceRegistryInterface_GetDestinationChainGasPrice_Call struct { - *mock.Call -} - -// GetDestinationChainGasPrice is a helper method to define mock.On call -// - opts *bind.CallOpts -// - destChainSelector uint64 -func (_e *PriceRegistryInterface_Expecter) GetDestinationChainGasPrice(opts interface{}, destChainSelector interface{}) *PriceRegistryInterface_GetDestinationChainGasPrice_Call { - return &PriceRegistryInterface_GetDestinationChainGasPrice_Call{Call: _e.mock.On("GetDestinationChainGasPrice", opts, destChainSelector)} -} - -func (_c *PriceRegistryInterface_GetDestinationChainGasPrice_Call) Run(run func(opts *bind.CallOpts, destChainSelector uint64)) *PriceRegistryInterface_GetDestinationChainGasPrice_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.CallOpts), args[1].(uint64)) - }) - return _c -} - -func (_c *PriceRegistryInterface_GetDestinationChainGasPrice_Call) Return(_a0 price_registry.InternalTimestampedPackedUint224, _a1 error) *PriceRegistryInterface_GetDestinationChainGasPrice_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_GetDestinationChainGasPrice_Call) RunAndReturn(run func(*bind.CallOpts, uint64) (price_registry.InternalTimestampedPackedUint224, error)) *PriceRegistryInterface_GetDestinationChainGasPrice_Call { - _c.Call.Return(run) - return _c -} - -// GetFeeTokens provides a mock function with given fields: opts -func (_m *PriceRegistryInterface) GetFeeTokens(opts *bind.CallOpts) ([]common.Address, error) { - ret := _m.Called(opts) - - if len(ret) == 0 { - panic("no return value specified for GetFeeTokens") - } - - var r0 []common.Address - var r1 error - if rf, ok := ret.Get(0).(func(*bind.CallOpts) ([]common.Address, error)); ok { - return rf(opts) - } - if rf, ok := ret.Get(0).(func(*bind.CallOpts) []common.Address); ok { - r0 = rf(opts) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]common.Address) - } - } - - if rf, ok := ret.Get(1).(func(*bind.CallOpts) error); ok { - r1 = rf(opts) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_GetFeeTokens_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetFeeTokens' -type PriceRegistryInterface_GetFeeTokens_Call struct { - *mock.Call -} - -// GetFeeTokens is a helper method to define mock.On call -// - opts *bind.CallOpts -func (_e *PriceRegistryInterface_Expecter) GetFeeTokens(opts interface{}) *PriceRegistryInterface_GetFeeTokens_Call { - return &PriceRegistryInterface_GetFeeTokens_Call{Call: _e.mock.On("GetFeeTokens", opts)} -} - -func (_c *PriceRegistryInterface_GetFeeTokens_Call) Run(run func(opts *bind.CallOpts)) *PriceRegistryInterface_GetFeeTokens_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.CallOpts)) - }) - return _c -} - -func (_c *PriceRegistryInterface_GetFeeTokens_Call) Return(_a0 []common.Address, _a1 error) *PriceRegistryInterface_GetFeeTokens_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_GetFeeTokens_Call) RunAndReturn(run func(*bind.CallOpts) ([]common.Address, error)) *PriceRegistryInterface_GetFeeTokens_Call { - _c.Call.Return(run) - return _c -} - -// GetPremiumMultiplierWeiPerEth provides a mock function with given fields: opts, token -func (_m *PriceRegistryInterface) GetPremiumMultiplierWeiPerEth(opts *bind.CallOpts, token common.Address) (uint64, error) { - ret := _m.Called(opts, token) - - if len(ret) == 0 { - panic("no return value specified for GetPremiumMultiplierWeiPerEth") - } - - var r0 uint64 - var r1 error - if rf, ok := ret.Get(0).(func(*bind.CallOpts, common.Address) (uint64, error)); ok { - return rf(opts, token) - } - if rf, ok := ret.Get(0).(func(*bind.CallOpts, common.Address) uint64); ok { - r0 = rf(opts, token) - } else { - r0 = ret.Get(0).(uint64) - } - - if rf, ok := ret.Get(1).(func(*bind.CallOpts, common.Address) error); ok { - r1 = rf(opts, token) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_GetPremiumMultiplierWeiPerEth_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetPremiumMultiplierWeiPerEth' -type PriceRegistryInterface_GetPremiumMultiplierWeiPerEth_Call struct { - *mock.Call -} - -// GetPremiumMultiplierWeiPerEth is a helper method to define mock.On call -// - opts *bind.CallOpts -// - token common.Address -func (_e *PriceRegistryInterface_Expecter) GetPremiumMultiplierWeiPerEth(opts interface{}, token interface{}) *PriceRegistryInterface_GetPremiumMultiplierWeiPerEth_Call { - return &PriceRegistryInterface_GetPremiumMultiplierWeiPerEth_Call{Call: _e.mock.On("GetPremiumMultiplierWeiPerEth", opts, token)} -} - -func (_c *PriceRegistryInterface_GetPremiumMultiplierWeiPerEth_Call) Run(run func(opts *bind.CallOpts, token common.Address)) *PriceRegistryInterface_GetPremiumMultiplierWeiPerEth_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.CallOpts), args[1].(common.Address)) - }) - return _c -} - -func (_c *PriceRegistryInterface_GetPremiumMultiplierWeiPerEth_Call) Return(_a0 uint64, _a1 error) *PriceRegistryInterface_GetPremiumMultiplierWeiPerEth_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_GetPremiumMultiplierWeiPerEth_Call) RunAndReturn(run func(*bind.CallOpts, common.Address) (uint64, error)) *PriceRegistryInterface_GetPremiumMultiplierWeiPerEth_Call { - _c.Call.Return(run) - return _c -} - -// GetStaticConfig provides a mock function with given fields: opts -func (_m *PriceRegistryInterface) GetStaticConfig(opts *bind.CallOpts) (price_registry.PriceRegistryStaticConfig, error) { - ret := _m.Called(opts) - - if len(ret) == 0 { - panic("no return value specified for GetStaticConfig") - } - - var r0 price_registry.PriceRegistryStaticConfig - var r1 error - if rf, ok := ret.Get(0).(func(*bind.CallOpts) (price_registry.PriceRegistryStaticConfig, error)); ok { - return rf(opts) - } - if rf, ok := ret.Get(0).(func(*bind.CallOpts) price_registry.PriceRegistryStaticConfig); ok { - r0 = rf(opts) - } else { - r0 = ret.Get(0).(price_registry.PriceRegistryStaticConfig) - } - - if rf, ok := ret.Get(1).(func(*bind.CallOpts) error); ok { - r1 = rf(opts) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_GetStaticConfig_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetStaticConfig' -type PriceRegistryInterface_GetStaticConfig_Call struct { - *mock.Call -} - -// GetStaticConfig is a helper method to define mock.On call -// - opts *bind.CallOpts -func (_e *PriceRegistryInterface_Expecter) GetStaticConfig(opts interface{}) *PriceRegistryInterface_GetStaticConfig_Call { - return &PriceRegistryInterface_GetStaticConfig_Call{Call: _e.mock.On("GetStaticConfig", opts)} -} - -func (_c *PriceRegistryInterface_GetStaticConfig_Call) Run(run func(opts *bind.CallOpts)) *PriceRegistryInterface_GetStaticConfig_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.CallOpts)) - }) - return _c -} - -func (_c *PriceRegistryInterface_GetStaticConfig_Call) Return(_a0 price_registry.PriceRegistryStaticConfig, _a1 error) *PriceRegistryInterface_GetStaticConfig_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_GetStaticConfig_Call) RunAndReturn(run func(*bind.CallOpts) (price_registry.PriceRegistryStaticConfig, error)) *PriceRegistryInterface_GetStaticConfig_Call { - _c.Call.Return(run) - return _c -} - -// GetTokenAndGasPrices provides a mock function with given fields: opts, token, destChainSelector -func (_m *PriceRegistryInterface) GetTokenAndGasPrices(opts *bind.CallOpts, token common.Address, destChainSelector uint64) (price_registry.GetTokenAndGasPrices, error) { - ret := _m.Called(opts, token, destChainSelector) - - if len(ret) == 0 { - panic("no return value specified for GetTokenAndGasPrices") - } - - var r0 price_registry.GetTokenAndGasPrices - var r1 error - if rf, ok := ret.Get(0).(func(*bind.CallOpts, common.Address, uint64) (price_registry.GetTokenAndGasPrices, error)); ok { - return rf(opts, token, destChainSelector) - } - if rf, ok := ret.Get(0).(func(*bind.CallOpts, common.Address, uint64) price_registry.GetTokenAndGasPrices); ok { - r0 = rf(opts, token, destChainSelector) - } else { - r0 = ret.Get(0).(price_registry.GetTokenAndGasPrices) - } - - if rf, ok := ret.Get(1).(func(*bind.CallOpts, common.Address, uint64) error); ok { - r1 = rf(opts, token, destChainSelector) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_GetTokenAndGasPrices_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetTokenAndGasPrices' -type PriceRegistryInterface_GetTokenAndGasPrices_Call struct { - *mock.Call -} - -// GetTokenAndGasPrices is a helper method to define mock.On call -// - opts *bind.CallOpts -// - token common.Address -// - destChainSelector uint64 -func (_e *PriceRegistryInterface_Expecter) GetTokenAndGasPrices(opts interface{}, token interface{}, destChainSelector interface{}) *PriceRegistryInterface_GetTokenAndGasPrices_Call { - return &PriceRegistryInterface_GetTokenAndGasPrices_Call{Call: _e.mock.On("GetTokenAndGasPrices", opts, token, destChainSelector)} -} - -func (_c *PriceRegistryInterface_GetTokenAndGasPrices_Call) Run(run func(opts *bind.CallOpts, token common.Address, destChainSelector uint64)) *PriceRegistryInterface_GetTokenAndGasPrices_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.CallOpts), args[1].(common.Address), args[2].(uint64)) - }) - return _c -} - -func (_c *PriceRegistryInterface_GetTokenAndGasPrices_Call) Return(_a0 price_registry.GetTokenAndGasPrices, _a1 error) *PriceRegistryInterface_GetTokenAndGasPrices_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_GetTokenAndGasPrices_Call) RunAndReturn(run func(*bind.CallOpts, common.Address, uint64) (price_registry.GetTokenAndGasPrices, error)) *PriceRegistryInterface_GetTokenAndGasPrices_Call { - _c.Call.Return(run) - return _c -} - -// GetTokenPrice provides a mock function with given fields: opts, token -func (_m *PriceRegistryInterface) GetTokenPrice(opts *bind.CallOpts, token common.Address) (price_registry.InternalTimestampedPackedUint224, error) { - ret := _m.Called(opts, token) - - if len(ret) == 0 { - panic("no return value specified for GetTokenPrice") - } - - var r0 price_registry.InternalTimestampedPackedUint224 - var r1 error - if rf, ok := ret.Get(0).(func(*bind.CallOpts, common.Address) (price_registry.InternalTimestampedPackedUint224, error)); ok { - return rf(opts, token) - } - if rf, ok := ret.Get(0).(func(*bind.CallOpts, common.Address) price_registry.InternalTimestampedPackedUint224); ok { - r0 = rf(opts, token) - } else { - r0 = ret.Get(0).(price_registry.InternalTimestampedPackedUint224) - } - - if rf, ok := ret.Get(1).(func(*bind.CallOpts, common.Address) error); ok { - r1 = rf(opts, token) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_GetTokenPrice_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetTokenPrice' -type PriceRegistryInterface_GetTokenPrice_Call struct { - *mock.Call -} - -// GetTokenPrice is a helper method to define mock.On call -// - opts *bind.CallOpts -// - token common.Address -func (_e *PriceRegistryInterface_Expecter) GetTokenPrice(opts interface{}, token interface{}) *PriceRegistryInterface_GetTokenPrice_Call { - return &PriceRegistryInterface_GetTokenPrice_Call{Call: _e.mock.On("GetTokenPrice", opts, token)} -} - -func (_c *PriceRegistryInterface_GetTokenPrice_Call) Run(run func(opts *bind.CallOpts, token common.Address)) *PriceRegistryInterface_GetTokenPrice_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.CallOpts), args[1].(common.Address)) - }) - return _c -} - -func (_c *PriceRegistryInterface_GetTokenPrice_Call) Return(_a0 price_registry.InternalTimestampedPackedUint224, _a1 error) *PriceRegistryInterface_GetTokenPrice_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_GetTokenPrice_Call) RunAndReturn(run func(*bind.CallOpts, common.Address) (price_registry.InternalTimestampedPackedUint224, error)) *PriceRegistryInterface_GetTokenPrice_Call { - _c.Call.Return(run) - return _c -} - -// GetTokenPriceFeedConfig provides a mock function with given fields: opts, token -func (_m *PriceRegistryInterface) GetTokenPriceFeedConfig(opts *bind.CallOpts, token common.Address) (price_registry.IPriceRegistryTokenPriceFeedConfig, error) { - ret := _m.Called(opts, token) - - if len(ret) == 0 { - panic("no return value specified for GetTokenPriceFeedConfig") - } - - var r0 price_registry.IPriceRegistryTokenPriceFeedConfig - var r1 error - if rf, ok := ret.Get(0).(func(*bind.CallOpts, common.Address) (price_registry.IPriceRegistryTokenPriceFeedConfig, error)); ok { - return rf(opts, token) - } - if rf, ok := ret.Get(0).(func(*bind.CallOpts, common.Address) price_registry.IPriceRegistryTokenPriceFeedConfig); ok { - r0 = rf(opts, token) - } else { - r0 = ret.Get(0).(price_registry.IPriceRegistryTokenPriceFeedConfig) - } - - if rf, ok := ret.Get(1).(func(*bind.CallOpts, common.Address) error); ok { - r1 = rf(opts, token) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_GetTokenPriceFeedConfig_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetTokenPriceFeedConfig' -type PriceRegistryInterface_GetTokenPriceFeedConfig_Call struct { - *mock.Call -} - -// GetTokenPriceFeedConfig is a helper method to define mock.On call -// - opts *bind.CallOpts -// - token common.Address -func (_e *PriceRegistryInterface_Expecter) GetTokenPriceFeedConfig(opts interface{}, token interface{}) *PriceRegistryInterface_GetTokenPriceFeedConfig_Call { - return &PriceRegistryInterface_GetTokenPriceFeedConfig_Call{Call: _e.mock.On("GetTokenPriceFeedConfig", opts, token)} -} - -func (_c *PriceRegistryInterface_GetTokenPriceFeedConfig_Call) Run(run func(opts *bind.CallOpts, token common.Address)) *PriceRegistryInterface_GetTokenPriceFeedConfig_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.CallOpts), args[1].(common.Address)) - }) - return _c -} - -func (_c *PriceRegistryInterface_GetTokenPriceFeedConfig_Call) Return(_a0 price_registry.IPriceRegistryTokenPriceFeedConfig, _a1 error) *PriceRegistryInterface_GetTokenPriceFeedConfig_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_GetTokenPriceFeedConfig_Call) RunAndReturn(run func(*bind.CallOpts, common.Address) (price_registry.IPriceRegistryTokenPriceFeedConfig, error)) *PriceRegistryInterface_GetTokenPriceFeedConfig_Call { - _c.Call.Return(run) - return _c -} - -// GetTokenPrices provides a mock function with given fields: opts, tokens -func (_m *PriceRegistryInterface) GetTokenPrices(opts *bind.CallOpts, tokens []common.Address) ([]price_registry.InternalTimestampedPackedUint224, error) { - ret := _m.Called(opts, tokens) - - if len(ret) == 0 { - panic("no return value specified for GetTokenPrices") - } - - var r0 []price_registry.InternalTimestampedPackedUint224 - var r1 error - if rf, ok := ret.Get(0).(func(*bind.CallOpts, []common.Address) ([]price_registry.InternalTimestampedPackedUint224, error)); ok { - return rf(opts, tokens) - } - if rf, ok := ret.Get(0).(func(*bind.CallOpts, []common.Address) []price_registry.InternalTimestampedPackedUint224); ok { - r0 = rf(opts, tokens) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]price_registry.InternalTimestampedPackedUint224) - } - } - - if rf, ok := ret.Get(1).(func(*bind.CallOpts, []common.Address) error); ok { - r1 = rf(opts, tokens) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_GetTokenPrices_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetTokenPrices' -type PriceRegistryInterface_GetTokenPrices_Call struct { - *mock.Call -} - -// GetTokenPrices is a helper method to define mock.On call -// - opts *bind.CallOpts -// - tokens []common.Address -func (_e *PriceRegistryInterface_Expecter) GetTokenPrices(opts interface{}, tokens interface{}) *PriceRegistryInterface_GetTokenPrices_Call { - return &PriceRegistryInterface_GetTokenPrices_Call{Call: _e.mock.On("GetTokenPrices", opts, tokens)} -} - -func (_c *PriceRegistryInterface_GetTokenPrices_Call) Run(run func(opts *bind.CallOpts, tokens []common.Address)) *PriceRegistryInterface_GetTokenPrices_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.CallOpts), args[1].([]common.Address)) - }) - return _c -} - -func (_c *PriceRegistryInterface_GetTokenPrices_Call) Return(_a0 []price_registry.InternalTimestampedPackedUint224, _a1 error) *PriceRegistryInterface_GetTokenPrices_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_GetTokenPrices_Call) RunAndReturn(run func(*bind.CallOpts, []common.Address) ([]price_registry.InternalTimestampedPackedUint224, error)) *PriceRegistryInterface_GetTokenPrices_Call { - _c.Call.Return(run) - return _c -} - -// GetTokenTransferFeeConfig provides a mock function with given fields: opts, destChainSelector, token -func (_m *PriceRegistryInterface) GetTokenTransferFeeConfig(opts *bind.CallOpts, destChainSelector uint64, token common.Address) (price_registry.PriceRegistryTokenTransferFeeConfig, error) { - ret := _m.Called(opts, destChainSelector, token) - - if len(ret) == 0 { - panic("no return value specified for GetTokenTransferFeeConfig") - } - - var r0 price_registry.PriceRegistryTokenTransferFeeConfig - var r1 error - if rf, ok := ret.Get(0).(func(*bind.CallOpts, uint64, common.Address) (price_registry.PriceRegistryTokenTransferFeeConfig, error)); ok { - return rf(opts, destChainSelector, token) - } - if rf, ok := ret.Get(0).(func(*bind.CallOpts, uint64, common.Address) price_registry.PriceRegistryTokenTransferFeeConfig); ok { - r0 = rf(opts, destChainSelector, token) - } else { - r0 = ret.Get(0).(price_registry.PriceRegistryTokenTransferFeeConfig) - } - - if rf, ok := ret.Get(1).(func(*bind.CallOpts, uint64, common.Address) error); ok { - r1 = rf(opts, destChainSelector, token) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_GetTokenTransferFeeConfig_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetTokenTransferFeeConfig' -type PriceRegistryInterface_GetTokenTransferFeeConfig_Call struct { - *mock.Call -} - -// GetTokenTransferFeeConfig is a helper method to define mock.On call -// - opts *bind.CallOpts -// - destChainSelector uint64 -// - token common.Address -func (_e *PriceRegistryInterface_Expecter) GetTokenTransferFeeConfig(opts interface{}, destChainSelector interface{}, token interface{}) *PriceRegistryInterface_GetTokenTransferFeeConfig_Call { - return &PriceRegistryInterface_GetTokenTransferFeeConfig_Call{Call: _e.mock.On("GetTokenTransferFeeConfig", opts, destChainSelector, token)} -} - -func (_c *PriceRegistryInterface_GetTokenTransferFeeConfig_Call) Run(run func(opts *bind.CallOpts, destChainSelector uint64, token common.Address)) *PriceRegistryInterface_GetTokenTransferFeeConfig_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.CallOpts), args[1].(uint64), args[2].(common.Address)) - }) - return _c -} - -func (_c *PriceRegistryInterface_GetTokenTransferFeeConfig_Call) Return(_a0 price_registry.PriceRegistryTokenTransferFeeConfig, _a1 error) *PriceRegistryInterface_GetTokenTransferFeeConfig_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_GetTokenTransferFeeConfig_Call) RunAndReturn(run func(*bind.CallOpts, uint64, common.Address) (price_registry.PriceRegistryTokenTransferFeeConfig, error)) *PriceRegistryInterface_GetTokenTransferFeeConfig_Call { - _c.Call.Return(run) - return _c -} - -// GetValidatedFee provides a mock function with given fields: opts, destChainSelector, message -func (_m *PriceRegistryInterface) GetValidatedFee(opts *bind.CallOpts, destChainSelector uint64, message price_registry.ClientEVM2AnyMessage) (*big.Int, error) { - ret := _m.Called(opts, destChainSelector, message) - - if len(ret) == 0 { - panic("no return value specified for GetValidatedFee") - } - - var r0 *big.Int - var r1 error - if rf, ok := ret.Get(0).(func(*bind.CallOpts, uint64, price_registry.ClientEVM2AnyMessage) (*big.Int, error)); ok { - return rf(opts, destChainSelector, message) - } - if rf, ok := ret.Get(0).(func(*bind.CallOpts, uint64, price_registry.ClientEVM2AnyMessage) *big.Int); ok { - r0 = rf(opts, destChainSelector, message) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*big.Int) - } - } - - if rf, ok := ret.Get(1).(func(*bind.CallOpts, uint64, price_registry.ClientEVM2AnyMessage) error); ok { - r1 = rf(opts, destChainSelector, message) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_GetValidatedFee_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetValidatedFee' -type PriceRegistryInterface_GetValidatedFee_Call struct { - *mock.Call -} - -// GetValidatedFee is a helper method to define mock.On call -// - opts *bind.CallOpts -// - destChainSelector uint64 -// - message price_registry.ClientEVM2AnyMessage -func (_e *PriceRegistryInterface_Expecter) GetValidatedFee(opts interface{}, destChainSelector interface{}, message interface{}) *PriceRegistryInterface_GetValidatedFee_Call { - return &PriceRegistryInterface_GetValidatedFee_Call{Call: _e.mock.On("GetValidatedFee", opts, destChainSelector, message)} -} - -func (_c *PriceRegistryInterface_GetValidatedFee_Call) Run(run func(opts *bind.CallOpts, destChainSelector uint64, message price_registry.ClientEVM2AnyMessage)) *PriceRegistryInterface_GetValidatedFee_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.CallOpts), args[1].(uint64), args[2].(price_registry.ClientEVM2AnyMessage)) - }) - return _c -} - -func (_c *PriceRegistryInterface_GetValidatedFee_Call) Return(_a0 *big.Int, _a1 error) *PriceRegistryInterface_GetValidatedFee_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_GetValidatedFee_Call) RunAndReturn(run func(*bind.CallOpts, uint64, price_registry.ClientEVM2AnyMessage) (*big.Int, error)) *PriceRegistryInterface_GetValidatedFee_Call { - _c.Call.Return(run) - return _c -} - -// GetValidatedTokenPrice provides a mock function with given fields: opts, token -func (_m *PriceRegistryInterface) GetValidatedTokenPrice(opts *bind.CallOpts, token common.Address) (*big.Int, error) { - ret := _m.Called(opts, token) - - if len(ret) == 0 { - panic("no return value specified for GetValidatedTokenPrice") - } - - var r0 *big.Int - var r1 error - if rf, ok := ret.Get(0).(func(*bind.CallOpts, common.Address) (*big.Int, error)); ok { - return rf(opts, token) - } - if rf, ok := ret.Get(0).(func(*bind.CallOpts, common.Address) *big.Int); ok { - r0 = rf(opts, token) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*big.Int) - } - } - - if rf, ok := ret.Get(1).(func(*bind.CallOpts, common.Address) error); ok { - r1 = rf(opts, token) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_GetValidatedTokenPrice_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetValidatedTokenPrice' -type PriceRegistryInterface_GetValidatedTokenPrice_Call struct { - *mock.Call -} - -// GetValidatedTokenPrice is a helper method to define mock.On call -// - opts *bind.CallOpts -// - token common.Address -func (_e *PriceRegistryInterface_Expecter) GetValidatedTokenPrice(opts interface{}, token interface{}) *PriceRegistryInterface_GetValidatedTokenPrice_Call { - return &PriceRegistryInterface_GetValidatedTokenPrice_Call{Call: _e.mock.On("GetValidatedTokenPrice", opts, token)} -} - -func (_c *PriceRegistryInterface_GetValidatedTokenPrice_Call) Run(run func(opts *bind.CallOpts, token common.Address)) *PriceRegistryInterface_GetValidatedTokenPrice_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.CallOpts), args[1].(common.Address)) - }) - return _c -} - -func (_c *PriceRegistryInterface_GetValidatedTokenPrice_Call) Return(_a0 *big.Int, _a1 error) *PriceRegistryInterface_GetValidatedTokenPrice_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_GetValidatedTokenPrice_Call) RunAndReturn(run func(*bind.CallOpts, common.Address) (*big.Int, error)) *PriceRegistryInterface_GetValidatedTokenPrice_Call { - _c.Call.Return(run) - return _c -} - -// OnReport provides a mock function with given fields: opts, metadata, report -func (_m *PriceRegistryInterface) OnReport(opts *bind.TransactOpts, metadata []byte, report []byte) (*types.Transaction, error) { - ret := _m.Called(opts, metadata, report) - - if len(ret) == 0 { - panic("no return value specified for OnReport") - } - - var r0 *types.Transaction - var r1 error - if rf, ok := ret.Get(0).(func(*bind.TransactOpts, []byte, []byte) (*types.Transaction, error)); ok { - return rf(opts, metadata, report) - } - if rf, ok := ret.Get(0).(func(*bind.TransactOpts, []byte, []byte) *types.Transaction); ok { - r0 = rf(opts, metadata, report) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.Transaction) - } - } - - if rf, ok := ret.Get(1).(func(*bind.TransactOpts, []byte, []byte) error); ok { - r1 = rf(opts, metadata, report) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_OnReport_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'OnReport' -type PriceRegistryInterface_OnReport_Call struct { - *mock.Call -} - -// OnReport is a helper method to define mock.On call -// - opts *bind.TransactOpts -// - metadata []byte -// - report []byte -func (_e *PriceRegistryInterface_Expecter) OnReport(opts interface{}, metadata interface{}, report interface{}) *PriceRegistryInterface_OnReport_Call { - return &PriceRegistryInterface_OnReport_Call{Call: _e.mock.On("OnReport", opts, metadata, report)} -} - -func (_c *PriceRegistryInterface_OnReport_Call) Run(run func(opts *bind.TransactOpts, metadata []byte, report []byte)) *PriceRegistryInterface_OnReport_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.TransactOpts), args[1].([]byte), args[2].([]byte)) - }) - return _c -} - -func (_c *PriceRegistryInterface_OnReport_Call) Return(_a0 *types.Transaction, _a1 error) *PriceRegistryInterface_OnReport_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_OnReport_Call) RunAndReturn(run func(*bind.TransactOpts, []byte, []byte) (*types.Transaction, error)) *PriceRegistryInterface_OnReport_Call { - _c.Call.Return(run) - return _c -} - -// Owner provides a mock function with given fields: opts -func (_m *PriceRegistryInterface) Owner(opts *bind.CallOpts) (common.Address, error) { - ret := _m.Called(opts) - - if len(ret) == 0 { - panic("no return value specified for Owner") - } - - var r0 common.Address - var r1 error - if rf, ok := ret.Get(0).(func(*bind.CallOpts) (common.Address, error)); ok { - return rf(opts) - } - if rf, ok := ret.Get(0).(func(*bind.CallOpts) common.Address); ok { - r0 = rf(opts) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(common.Address) - } - } - - if rf, ok := ret.Get(1).(func(*bind.CallOpts) error); ok { - r1 = rf(opts) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_Owner_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Owner' -type PriceRegistryInterface_Owner_Call struct { - *mock.Call -} - -// Owner is a helper method to define mock.On call -// - opts *bind.CallOpts -func (_e *PriceRegistryInterface_Expecter) Owner(opts interface{}) *PriceRegistryInterface_Owner_Call { - return &PriceRegistryInterface_Owner_Call{Call: _e.mock.On("Owner", opts)} -} - -func (_c *PriceRegistryInterface_Owner_Call) Run(run func(opts *bind.CallOpts)) *PriceRegistryInterface_Owner_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.CallOpts)) - }) - return _c -} - -func (_c *PriceRegistryInterface_Owner_Call) Return(_a0 common.Address, _a1 error) *PriceRegistryInterface_Owner_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_Owner_Call) RunAndReturn(run func(*bind.CallOpts) (common.Address, error)) *PriceRegistryInterface_Owner_Call { - _c.Call.Return(run) - return _c -} - -// ParseAuthorizedCallerAdded provides a mock function with given fields: log -func (_m *PriceRegistryInterface) ParseAuthorizedCallerAdded(log types.Log) (*price_registry.PriceRegistryAuthorizedCallerAdded, error) { - ret := _m.Called(log) - - if len(ret) == 0 { - panic("no return value specified for ParseAuthorizedCallerAdded") - } - - var r0 *price_registry.PriceRegistryAuthorizedCallerAdded - var r1 error - if rf, ok := ret.Get(0).(func(types.Log) (*price_registry.PriceRegistryAuthorizedCallerAdded, error)); ok { - return rf(log) - } - if rf, ok := ret.Get(0).(func(types.Log) *price_registry.PriceRegistryAuthorizedCallerAdded); ok { - r0 = rf(log) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*price_registry.PriceRegistryAuthorizedCallerAdded) - } - } - - if rf, ok := ret.Get(1).(func(types.Log) error); ok { - r1 = rf(log) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_ParseAuthorizedCallerAdded_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParseAuthorizedCallerAdded' -type PriceRegistryInterface_ParseAuthorizedCallerAdded_Call struct { - *mock.Call -} - -// ParseAuthorizedCallerAdded is a helper method to define mock.On call -// - log types.Log -func (_e *PriceRegistryInterface_Expecter) ParseAuthorizedCallerAdded(log interface{}) *PriceRegistryInterface_ParseAuthorizedCallerAdded_Call { - return &PriceRegistryInterface_ParseAuthorizedCallerAdded_Call{Call: _e.mock.On("ParseAuthorizedCallerAdded", log)} -} - -func (_c *PriceRegistryInterface_ParseAuthorizedCallerAdded_Call) Run(run func(log types.Log)) *PriceRegistryInterface_ParseAuthorizedCallerAdded_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(types.Log)) - }) - return _c -} - -func (_c *PriceRegistryInterface_ParseAuthorizedCallerAdded_Call) Return(_a0 *price_registry.PriceRegistryAuthorizedCallerAdded, _a1 error) *PriceRegistryInterface_ParseAuthorizedCallerAdded_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_ParseAuthorizedCallerAdded_Call) RunAndReturn(run func(types.Log) (*price_registry.PriceRegistryAuthorizedCallerAdded, error)) *PriceRegistryInterface_ParseAuthorizedCallerAdded_Call { - _c.Call.Return(run) - return _c -} - -// ParseAuthorizedCallerRemoved provides a mock function with given fields: log -func (_m *PriceRegistryInterface) ParseAuthorizedCallerRemoved(log types.Log) (*price_registry.PriceRegistryAuthorizedCallerRemoved, error) { - ret := _m.Called(log) - - if len(ret) == 0 { - panic("no return value specified for ParseAuthorizedCallerRemoved") - } - - var r0 *price_registry.PriceRegistryAuthorizedCallerRemoved - var r1 error - if rf, ok := ret.Get(0).(func(types.Log) (*price_registry.PriceRegistryAuthorizedCallerRemoved, error)); ok { - return rf(log) - } - if rf, ok := ret.Get(0).(func(types.Log) *price_registry.PriceRegistryAuthorizedCallerRemoved); ok { - r0 = rf(log) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*price_registry.PriceRegistryAuthorizedCallerRemoved) - } - } - - if rf, ok := ret.Get(1).(func(types.Log) error); ok { - r1 = rf(log) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_ParseAuthorizedCallerRemoved_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParseAuthorizedCallerRemoved' -type PriceRegistryInterface_ParseAuthorizedCallerRemoved_Call struct { - *mock.Call -} - -// ParseAuthorizedCallerRemoved is a helper method to define mock.On call -// - log types.Log -func (_e *PriceRegistryInterface_Expecter) ParseAuthorizedCallerRemoved(log interface{}) *PriceRegistryInterface_ParseAuthorizedCallerRemoved_Call { - return &PriceRegistryInterface_ParseAuthorizedCallerRemoved_Call{Call: _e.mock.On("ParseAuthorizedCallerRemoved", log)} -} - -func (_c *PriceRegistryInterface_ParseAuthorizedCallerRemoved_Call) Run(run func(log types.Log)) *PriceRegistryInterface_ParseAuthorizedCallerRemoved_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(types.Log)) - }) - return _c -} - -func (_c *PriceRegistryInterface_ParseAuthorizedCallerRemoved_Call) Return(_a0 *price_registry.PriceRegistryAuthorizedCallerRemoved, _a1 error) *PriceRegistryInterface_ParseAuthorizedCallerRemoved_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_ParseAuthorizedCallerRemoved_Call) RunAndReturn(run func(types.Log) (*price_registry.PriceRegistryAuthorizedCallerRemoved, error)) *PriceRegistryInterface_ParseAuthorizedCallerRemoved_Call { - _c.Call.Return(run) - return _c -} - -// ParseDestChainAdded provides a mock function with given fields: log -func (_m *PriceRegistryInterface) ParseDestChainAdded(log types.Log) (*price_registry.PriceRegistryDestChainAdded, error) { - ret := _m.Called(log) - - if len(ret) == 0 { - panic("no return value specified for ParseDestChainAdded") - } - - var r0 *price_registry.PriceRegistryDestChainAdded - var r1 error - if rf, ok := ret.Get(0).(func(types.Log) (*price_registry.PriceRegistryDestChainAdded, error)); ok { - return rf(log) - } - if rf, ok := ret.Get(0).(func(types.Log) *price_registry.PriceRegistryDestChainAdded); ok { - r0 = rf(log) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*price_registry.PriceRegistryDestChainAdded) - } - } - - if rf, ok := ret.Get(1).(func(types.Log) error); ok { - r1 = rf(log) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_ParseDestChainAdded_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParseDestChainAdded' -type PriceRegistryInterface_ParseDestChainAdded_Call struct { - *mock.Call -} - -// ParseDestChainAdded is a helper method to define mock.On call -// - log types.Log -func (_e *PriceRegistryInterface_Expecter) ParseDestChainAdded(log interface{}) *PriceRegistryInterface_ParseDestChainAdded_Call { - return &PriceRegistryInterface_ParseDestChainAdded_Call{Call: _e.mock.On("ParseDestChainAdded", log)} -} - -func (_c *PriceRegistryInterface_ParseDestChainAdded_Call) Run(run func(log types.Log)) *PriceRegistryInterface_ParseDestChainAdded_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(types.Log)) - }) - return _c -} - -func (_c *PriceRegistryInterface_ParseDestChainAdded_Call) Return(_a0 *price_registry.PriceRegistryDestChainAdded, _a1 error) *PriceRegistryInterface_ParseDestChainAdded_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_ParseDestChainAdded_Call) RunAndReturn(run func(types.Log) (*price_registry.PriceRegistryDestChainAdded, error)) *PriceRegistryInterface_ParseDestChainAdded_Call { - _c.Call.Return(run) - return _c -} - -// ParseDestChainConfigUpdated provides a mock function with given fields: log -func (_m *PriceRegistryInterface) ParseDestChainConfigUpdated(log types.Log) (*price_registry.PriceRegistryDestChainConfigUpdated, error) { - ret := _m.Called(log) - - if len(ret) == 0 { - panic("no return value specified for ParseDestChainConfigUpdated") - } - - var r0 *price_registry.PriceRegistryDestChainConfigUpdated - var r1 error - if rf, ok := ret.Get(0).(func(types.Log) (*price_registry.PriceRegistryDestChainConfigUpdated, error)); ok { - return rf(log) - } - if rf, ok := ret.Get(0).(func(types.Log) *price_registry.PriceRegistryDestChainConfigUpdated); ok { - r0 = rf(log) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*price_registry.PriceRegistryDestChainConfigUpdated) - } - } - - if rf, ok := ret.Get(1).(func(types.Log) error); ok { - r1 = rf(log) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_ParseDestChainConfigUpdated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParseDestChainConfigUpdated' -type PriceRegistryInterface_ParseDestChainConfigUpdated_Call struct { - *mock.Call -} - -// ParseDestChainConfigUpdated is a helper method to define mock.On call -// - log types.Log -func (_e *PriceRegistryInterface_Expecter) ParseDestChainConfigUpdated(log interface{}) *PriceRegistryInterface_ParseDestChainConfigUpdated_Call { - return &PriceRegistryInterface_ParseDestChainConfigUpdated_Call{Call: _e.mock.On("ParseDestChainConfigUpdated", log)} -} - -func (_c *PriceRegistryInterface_ParseDestChainConfigUpdated_Call) Run(run func(log types.Log)) *PriceRegistryInterface_ParseDestChainConfigUpdated_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(types.Log)) - }) - return _c -} - -func (_c *PriceRegistryInterface_ParseDestChainConfigUpdated_Call) Return(_a0 *price_registry.PriceRegistryDestChainConfigUpdated, _a1 error) *PriceRegistryInterface_ParseDestChainConfigUpdated_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_ParseDestChainConfigUpdated_Call) RunAndReturn(run func(types.Log) (*price_registry.PriceRegistryDestChainConfigUpdated, error)) *PriceRegistryInterface_ParseDestChainConfigUpdated_Call { - _c.Call.Return(run) - return _c -} - -// ParseFeeTokenAdded provides a mock function with given fields: log -func (_m *PriceRegistryInterface) ParseFeeTokenAdded(log types.Log) (*price_registry.PriceRegistryFeeTokenAdded, error) { - ret := _m.Called(log) - - if len(ret) == 0 { - panic("no return value specified for ParseFeeTokenAdded") - } - - var r0 *price_registry.PriceRegistryFeeTokenAdded - var r1 error - if rf, ok := ret.Get(0).(func(types.Log) (*price_registry.PriceRegistryFeeTokenAdded, error)); ok { - return rf(log) - } - if rf, ok := ret.Get(0).(func(types.Log) *price_registry.PriceRegistryFeeTokenAdded); ok { - r0 = rf(log) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*price_registry.PriceRegistryFeeTokenAdded) - } - } - - if rf, ok := ret.Get(1).(func(types.Log) error); ok { - r1 = rf(log) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_ParseFeeTokenAdded_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParseFeeTokenAdded' -type PriceRegistryInterface_ParseFeeTokenAdded_Call struct { - *mock.Call -} - -// ParseFeeTokenAdded is a helper method to define mock.On call -// - log types.Log -func (_e *PriceRegistryInterface_Expecter) ParseFeeTokenAdded(log interface{}) *PriceRegistryInterface_ParseFeeTokenAdded_Call { - return &PriceRegistryInterface_ParseFeeTokenAdded_Call{Call: _e.mock.On("ParseFeeTokenAdded", log)} -} - -func (_c *PriceRegistryInterface_ParseFeeTokenAdded_Call) Run(run func(log types.Log)) *PriceRegistryInterface_ParseFeeTokenAdded_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(types.Log)) - }) - return _c -} - -func (_c *PriceRegistryInterface_ParseFeeTokenAdded_Call) Return(_a0 *price_registry.PriceRegistryFeeTokenAdded, _a1 error) *PriceRegistryInterface_ParseFeeTokenAdded_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_ParseFeeTokenAdded_Call) RunAndReturn(run func(types.Log) (*price_registry.PriceRegistryFeeTokenAdded, error)) *PriceRegistryInterface_ParseFeeTokenAdded_Call { - _c.Call.Return(run) - return _c -} - -// ParseFeeTokenRemoved provides a mock function with given fields: log -func (_m *PriceRegistryInterface) ParseFeeTokenRemoved(log types.Log) (*price_registry.PriceRegistryFeeTokenRemoved, error) { - ret := _m.Called(log) - - if len(ret) == 0 { - panic("no return value specified for ParseFeeTokenRemoved") - } - - var r0 *price_registry.PriceRegistryFeeTokenRemoved - var r1 error - if rf, ok := ret.Get(0).(func(types.Log) (*price_registry.PriceRegistryFeeTokenRemoved, error)); ok { - return rf(log) - } - if rf, ok := ret.Get(0).(func(types.Log) *price_registry.PriceRegistryFeeTokenRemoved); ok { - r0 = rf(log) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*price_registry.PriceRegistryFeeTokenRemoved) - } - } - - if rf, ok := ret.Get(1).(func(types.Log) error); ok { - r1 = rf(log) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_ParseFeeTokenRemoved_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParseFeeTokenRemoved' -type PriceRegistryInterface_ParseFeeTokenRemoved_Call struct { - *mock.Call -} - -// ParseFeeTokenRemoved is a helper method to define mock.On call -// - log types.Log -func (_e *PriceRegistryInterface_Expecter) ParseFeeTokenRemoved(log interface{}) *PriceRegistryInterface_ParseFeeTokenRemoved_Call { - return &PriceRegistryInterface_ParseFeeTokenRemoved_Call{Call: _e.mock.On("ParseFeeTokenRemoved", log)} -} - -func (_c *PriceRegistryInterface_ParseFeeTokenRemoved_Call) Run(run func(log types.Log)) *PriceRegistryInterface_ParseFeeTokenRemoved_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(types.Log)) - }) - return _c -} - -func (_c *PriceRegistryInterface_ParseFeeTokenRemoved_Call) Return(_a0 *price_registry.PriceRegistryFeeTokenRemoved, _a1 error) *PriceRegistryInterface_ParseFeeTokenRemoved_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_ParseFeeTokenRemoved_Call) RunAndReturn(run func(types.Log) (*price_registry.PriceRegistryFeeTokenRemoved, error)) *PriceRegistryInterface_ParseFeeTokenRemoved_Call { - _c.Call.Return(run) - return _c -} - -// ParseLog provides a mock function with given fields: log -func (_m *PriceRegistryInterface) ParseLog(log types.Log) (generated.AbigenLog, error) { - ret := _m.Called(log) - - if len(ret) == 0 { - panic("no return value specified for ParseLog") - } - - var r0 generated.AbigenLog - var r1 error - if rf, ok := ret.Get(0).(func(types.Log) (generated.AbigenLog, error)); ok { - return rf(log) - } - if rf, ok := ret.Get(0).(func(types.Log) generated.AbigenLog); ok { - r0 = rf(log) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(generated.AbigenLog) - } - } - - if rf, ok := ret.Get(1).(func(types.Log) error); ok { - r1 = rf(log) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_ParseLog_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParseLog' -type PriceRegistryInterface_ParseLog_Call struct { - *mock.Call -} - -// ParseLog is a helper method to define mock.On call -// - log types.Log -func (_e *PriceRegistryInterface_Expecter) ParseLog(log interface{}) *PriceRegistryInterface_ParseLog_Call { - return &PriceRegistryInterface_ParseLog_Call{Call: _e.mock.On("ParseLog", log)} -} - -func (_c *PriceRegistryInterface_ParseLog_Call) Run(run func(log types.Log)) *PriceRegistryInterface_ParseLog_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(types.Log)) - }) - return _c -} - -func (_c *PriceRegistryInterface_ParseLog_Call) Return(_a0 generated.AbigenLog, _a1 error) *PriceRegistryInterface_ParseLog_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_ParseLog_Call) RunAndReturn(run func(types.Log) (generated.AbigenLog, error)) *PriceRegistryInterface_ParseLog_Call { - _c.Call.Return(run) - return _c -} - -// ParseOwnershipTransferRequested provides a mock function with given fields: log -func (_m *PriceRegistryInterface) ParseOwnershipTransferRequested(log types.Log) (*price_registry.PriceRegistryOwnershipTransferRequested, error) { - ret := _m.Called(log) - - if len(ret) == 0 { - panic("no return value specified for ParseOwnershipTransferRequested") - } - - var r0 *price_registry.PriceRegistryOwnershipTransferRequested - var r1 error - if rf, ok := ret.Get(0).(func(types.Log) (*price_registry.PriceRegistryOwnershipTransferRequested, error)); ok { - return rf(log) - } - if rf, ok := ret.Get(0).(func(types.Log) *price_registry.PriceRegistryOwnershipTransferRequested); ok { - r0 = rf(log) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*price_registry.PriceRegistryOwnershipTransferRequested) - } - } - - if rf, ok := ret.Get(1).(func(types.Log) error); ok { - r1 = rf(log) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_ParseOwnershipTransferRequested_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParseOwnershipTransferRequested' -type PriceRegistryInterface_ParseOwnershipTransferRequested_Call struct { - *mock.Call -} - -// ParseOwnershipTransferRequested is a helper method to define mock.On call -// - log types.Log -func (_e *PriceRegistryInterface_Expecter) ParseOwnershipTransferRequested(log interface{}) *PriceRegistryInterface_ParseOwnershipTransferRequested_Call { - return &PriceRegistryInterface_ParseOwnershipTransferRequested_Call{Call: _e.mock.On("ParseOwnershipTransferRequested", log)} -} - -func (_c *PriceRegistryInterface_ParseOwnershipTransferRequested_Call) Run(run func(log types.Log)) *PriceRegistryInterface_ParseOwnershipTransferRequested_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(types.Log)) - }) - return _c -} - -func (_c *PriceRegistryInterface_ParseOwnershipTransferRequested_Call) Return(_a0 *price_registry.PriceRegistryOwnershipTransferRequested, _a1 error) *PriceRegistryInterface_ParseOwnershipTransferRequested_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_ParseOwnershipTransferRequested_Call) RunAndReturn(run func(types.Log) (*price_registry.PriceRegistryOwnershipTransferRequested, error)) *PriceRegistryInterface_ParseOwnershipTransferRequested_Call { - _c.Call.Return(run) - return _c -} - -// ParseOwnershipTransferred provides a mock function with given fields: log -func (_m *PriceRegistryInterface) ParseOwnershipTransferred(log types.Log) (*price_registry.PriceRegistryOwnershipTransferred, error) { - ret := _m.Called(log) - - if len(ret) == 0 { - panic("no return value specified for ParseOwnershipTransferred") - } - - var r0 *price_registry.PriceRegistryOwnershipTransferred - var r1 error - if rf, ok := ret.Get(0).(func(types.Log) (*price_registry.PriceRegistryOwnershipTransferred, error)); ok { - return rf(log) - } - if rf, ok := ret.Get(0).(func(types.Log) *price_registry.PriceRegistryOwnershipTransferred); ok { - r0 = rf(log) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*price_registry.PriceRegistryOwnershipTransferred) - } - } - - if rf, ok := ret.Get(1).(func(types.Log) error); ok { - r1 = rf(log) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_ParseOwnershipTransferred_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParseOwnershipTransferred' -type PriceRegistryInterface_ParseOwnershipTransferred_Call struct { - *mock.Call -} - -// ParseOwnershipTransferred is a helper method to define mock.On call -// - log types.Log -func (_e *PriceRegistryInterface_Expecter) ParseOwnershipTransferred(log interface{}) *PriceRegistryInterface_ParseOwnershipTransferred_Call { - return &PriceRegistryInterface_ParseOwnershipTransferred_Call{Call: _e.mock.On("ParseOwnershipTransferred", log)} -} - -func (_c *PriceRegistryInterface_ParseOwnershipTransferred_Call) Run(run func(log types.Log)) *PriceRegistryInterface_ParseOwnershipTransferred_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(types.Log)) - }) - return _c -} - -func (_c *PriceRegistryInterface_ParseOwnershipTransferred_Call) Return(_a0 *price_registry.PriceRegistryOwnershipTransferred, _a1 error) *PriceRegistryInterface_ParseOwnershipTransferred_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_ParseOwnershipTransferred_Call) RunAndReturn(run func(types.Log) (*price_registry.PriceRegistryOwnershipTransferred, error)) *PriceRegistryInterface_ParseOwnershipTransferred_Call { - _c.Call.Return(run) - return _c -} - -// ParsePremiumMultiplierWeiPerEthUpdated provides a mock function with given fields: log -func (_m *PriceRegistryInterface) ParsePremiumMultiplierWeiPerEthUpdated(log types.Log) (*price_registry.PriceRegistryPremiumMultiplierWeiPerEthUpdated, error) { - ret := _m.Called(log) - - if len(ret) == 0 { - panic("no return value specified for ParsePremiumMultiplierWeiPerEthUpdated") - } - - var r0 *price_registry.PriceRegistryPremiumMultiplierWeiPerEthUpdated - var r1 error - if rf, ok := ret.Get(0).(func(types.Log) (*price_registry.PriceRegistryPremiumMultiplierWeiPerEthUpdated, error)); ok { - return rf(log) - } - if rf, ok := ret.Get(0).(func(types.Log) *price_registry.PriceRegistryPremiumMultiplierWeiPerEthUpdated); ok { - r0 = rf(log) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*price_registry.PriceRegistryPremiumMultiplierWeiPerEthUpdated) - } - } - - if rf, ok := ret.Get(1).(func(types.Log) error); ok { - r1 = rf(log) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_ParsePremiumMultiplierWeiPerEthUpdated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParsePremiumMultiplierWeiPerEthUpdated' -type PriceRegistryInterface_ParsePremiumMultiplierWeiPerEthUpdated_Call struct { - *mock.Call -} - -// ParsePremiumMultiplierWeiPerEthUpdated is a helper method to define mock.On call -// - log types.Log -func (_e *PriceRegistryInterface_Expecter) ParsePremiumMultiplierWeiPerEthUpdated(log interface{}) *PriceRegistryInterface_ParsePremiumMultiplierWeiPerEthUpdated_Call { - return &PriceRegistryInterface_ParsePremiumMultiplierWeiPerEthUpdated_Call{Call: _e.mock.On("ParsePremiumMultiplierWeiPerEthUpdated", log)} -} - -func (_c *PriceRegistryInterface_ParsePremiumMultiplierWeiPerEthUpdated_Call) Run(run func(log types.Log)) *PriceRegistryInterface_ParsePremiumMultiplierWeiPerEthUpdated_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(types.Log)) - }) - return _c -} - -func (_c *PriceRegistryInterface_ParsePremiumMultiplierWeiPerEthUpdated_Call) Return(_a0 *price_registry.PriceRegistryPremiumMultiplierWeiPerEthUpdated, _a1 error) *PriceRegistryInterface_ParsePremiumMultiplierWeiPerEthUpdated_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_ParsePremiumMultiplierWeiPerEthUpdated_Call) RunAndReturn(run func(types.Log) (*price_registry.PriceRegistryPremiumMultiplierWeiPerEthUpdated, error)) *PriceRegistryInterface_ParsePremiumMultiplierWeiPerEthUpdated_Call { - _c.Call.Return(run) - return _c -} - -// ParsePriceFeedPerTokenUpdated provides a mock function with given fields: log -func (_m *PriceRegistryInterface) ParsePriceFeedPerTokenUpdated(log types.Log) (*price_registry.PriceRegistryPriceFeedPerTokenUpdated, error) { - ret := _m.Called(log) - - if len(ret) == 0 { - panic("no return value specified for ParsePriceFeedPerTokenUpdated") - } - - var r0 *price_registry.PriceRegistryPriceFeedPerTokenUpdated - var r1 error - if rf, ok := ret.Get(0).(func(types.Log) (*price_registry.PriceRegistryPriceFeedPerTokenUpdated, error)); ok { - return rf(log) - } - if rf, ok := ret.Get(0).(func(types.Log) *price_registry.PriceRegistryPriceFeedPerTokenUpdated); ok { - r0 = rf(log) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*price_registry.PriceRegistryPriceFeedPerTokenUpdated) - } - } - - if rf, ok := ret.Get(1).(func(types.Log) error); ok { - r1 = rf(log) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_ParsePriceFeedPerTokenUpdated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParsePriceFeedPerTokenUpdated' -type PriceRegistryInterface_ParsePriceFeedPerTokenUpdated_Call struct { - *mock.Call -} - -// ParsePriceFeedPerTokenUpdated is a helper method to define mock.On call -// - log types.Log -func (_e *PriceRegistryInterface_Expecter) ParsePriceFeedPerTokenUpdated(log interface{}) *PriceRegistryInterface_ParsePriceFeedPerTokenUpdated_Call { - return &PriceRegistryInterface_ParsePriceFeedPerTokenUpdated_Call{Call: _e.mock.On("ParsePriceFeedPerTokenUpdated", log)} -} - -func (_c *PriceRegistryInterface_ParsePriceFeedPerTokenUpdated_Call) Run(run func(log types.Log)) *PriceRegistryInterface_ParsePriceFeedPerTokenUpdated_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(types.Log)) - }) - return _c -} - -func (_c *PriceRegistryInterface_ParsePriceFeedPerTokenUpdated_Call) Return(_a0 *price_registry.PriceRegistryPriceFeedPerTokenUpdated, _a1 error) *PriceRegistryInterface_ParsePriceFeedPerTokenUpdated_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_ParsePriceFeedPerTokenUpdated_Call) RunAndReturn(run func(types.Log) (*price_registry.PriceRegistryPriceFeedPerTokenUpdated, error)) *PriceRegistryInterface_ParsePriceFeedPerTokenUpdated_Call { - _c.Call.Return(run) - return _c -} - -// ParseReportPermissionSet provides a mock function with given fields: log -func (_m *PriceRegistryInterface) ParseReportPermissionSet(log types.Log) (*price_registry.PriceRegistryReportPermissionSet, error) { - ret := _m.Called(log) - - if len(ret) == 0 { - panic("no return value specified for ParseReportPermissionSet") - } - - var r0 *price_registry.PriceRegistryReportPermissionSet - var r1 error - if rf, ok := ret.Get(0).(func(types.Log) (*price_registry.PriceRegistryReportPermissionSet, error)); ok { - return rf(log) - } - if rf, ok := ret.Get(0).(func(types.Log) *price_registry.PriceRegistryReportPermissionSet); ok { - r0 = rf(log) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*price_registry.PriceRegistryReportPermissionSet) - } - } - - if rf, ok := ret.Get(1).(func(types.Log) error); ok { - r1 = rf(log) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_ParseReportPermissionSet_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParseReportPermissionSet' -type PriceRegistryInterface_ParseReportPermissionSet_Call struct { - *mock.Call -} - -// ParseReportPermissionSet is a helper method to define mock.On call -// - log types.Log -func (_e *PriceRegistryInterface_Expecter) ParseReportPermissionSet(log interface{}) *PriceRegistryInterface_ParseReportPermissionSet_Call { - return &PriceRegistryInterface_ParseReportPermissionSet_Call{Call: _e.mock.On("ParseReportPermissionSet", log)} -} - -func (_c *PriceRegistryInterface_ParseReportPermissionSet_Call) Run(run func(log types.Log)) *PriceRegistryInterface_ParseReportPermissionSet_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(types.Log)) - }) - return _c -} - -func (_c *PriceRegistryInterface_ParseReportPermissionSet_Call) Return(_a0 *price_registry.PriceRegistryReportPermissionSet, _a1 error) *PriceRegistryInterface_ParseReportPermissionSet_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_ParseReportPermissionSet_Call) RunAndReturn(run func(types.Log) (*price_registry.PriceRegistryReportPermissionSet, error)) *PriceRegistryInterface_ParseReportPermissionSet_Call { - _c.Call.Return(run) - return _c -} - -// ParseTokenTransferFeeConfigDeleted provides a mock function with given fields: log -func (_m *PriceRegistryInterface) ParseTokenTransferFeeConfigDeleted(log types.Log) (*price_registry.PriceRegistryTokenTransferFeeConfigDeleted, error) { - ret := _m.Called(log) - - if len(ret) == 0 { - panic("no return value specified for ParseTokenTransferFeeConfigDeleted") - } - - var r0 *price_registry.PriceRegistryTokenTransferFeeConfigDeleted - var r1 error - if rf, ok := ret.Get(0).(func(types.Log) (*price_registry.PriceRegistryTokenTransferFeeConfigDeleted, error)); ok { - return rf(log) - } - if rf, ok := ret.Get(0).(func(types.Log) *price_registry.PriceRegistryTokenTransferFeeConfigDeleted); ok { - r0 = rf(log) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*price_registry.PriceRegistryTokenTransferFeeConfigDeleted) - } - } - - if rf, ok := ret.Get(1).(func(types.Log) error); ok { - r1 = rf(log) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_ParseTokenTransferFeeConfigDeleted_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParseTokenTransferFeeConfigDeleted' -type PriceRegistryInterface_ParseTokenTransferFeeConfigDeleted_Call struct { - *mock.Call -} - -// ParseTokenTransferFeeConfigDeleted is a helper method to define mock.On call -// - log types.Log -func (_e *PriceRegistryInterface_Expecter) ParseTokenTransferFeeConfigDeleted(log interface{}) *PriceRegistryInterface_ParseTokenTransferFeeConfigDeleted_Call { - return &PriceRegistryInterface_ParseTokenTransferFeeConfigDeleted_Call{Call: _e.mock.On("ParseTokenTransferFeeConfigDeleted", log)} -} - -func (_c *PriceRegistryInterface_ParseTokenTransferFeeConfigDeleted_Call) Run(run func(log types.Log)) *PriceRegistryInterface_ParseTokenTransferFeeConfigDeleted_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(types.Log)) - }) - return _c -} - -func (_c *PriceRegistryInterface_ParseTokenTransferFeeConfigDeleted_Call) Return(_a0 *price_registry.PriceRegistryTokenTransferFeeConfigDeleted, _a1 error) *PriceRegistryInterface_ParseTokenTransferFeeConfigDeleted_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_ParseTokenTransferFeeConfigDeleted_Call) RunAndReturn(run func(types.Log) (*price_registry.PriceRegistryTokenTransferFeeConfigDeleted, error)) *PriceRegistryInterface_ParseTokenTransferFeeConfigDeleted_Call { - _c.Call.Return(run) - return _c -} - -// ParseTokenTransferFeeConfigUpdated provides a mock function with given fields: log -func (_m *PriceRegistryInterface) ParseTokenTransferFeeConfigUpdated(log types.Log) (*price_registry.PriceRegistryTokenTransferFeeConfigUpdated, error) { - ret := _m.Called(log) - - if len(ret) == 0 { - panic("no return value specified for ParseTokenTransferFeeConfigUpdated") - } - - var r0 *price_registry.PriceRegistryTokenTransferFeeConfigUpdated - var r1 error - if rf, ok := ret.Get(0).(func(types.Log) (*price_registry.PriceRegistryTokenTransferFeeConfigUpdated, error)); ok { - return rf(log) - } - if rf, ok := ret.Get(0).(func(types.Log) *price_registry.PriceRegistryTokenTransferFeeConfigUpdated); ok { - r0 = rf(log) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*price_registry.PriceRegistryTokenTransferFeeConfigUpdated) - } - } - - if rf, ok := ret.Get(1).(func(types.Log) error); ok { - r1 = rf(log) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_ParseTokenTransferFeeConfigUpdated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParseTokenTransferFeeConfigUpdated' -type PriceRegistryInterface_ParseTokenTransferFeeConfigUpdated_Call struct { - *mock.Call -} - -// ParseTokenTransferFeeConfigUpdated is a helper method to define mock.On call -// - log types.Log -func (_e *PriceRegistryInterface_Expecter) ParseTokenTransferFeeConfigUpdated(log interface{}) *PriceRegistryInterface_ParseTokenTransferFeeConfigUpdated_Call { - return &PriceRegistryInterface_ParseTokenTransferFeeConfigUpdated_Call{Call: _e.mock.On("ParseTokenTransferFeeConfigUpdated", log)} -} - -func (_c *PriceRegistryInterface_ParseTokenTransferFeeConfigUpdated_Call) Run(run func(log types.Log)) *PriceRegistryInterface_ParseTokenTransferFeeConfigUpdated_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(types.Log)) - }) - return _c -} - -func (_c *PriceRegistryInterface_ParseTokenTransferFeeConfigUpdated_Call) Return(_a0 *price_registry.PriceRegistryTokenTransferFeeConfigUpdated, _a1 error) *PriceRegistryInterface_ParseTokenTransferFeeConfigUpdated_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_ParseTokenTransferFeeConfigUpdated_Call) RunAndReturn(run func(types.Log) (*price_registry.PriceRegistryTokenTransferFeeConfigUpdated, error)) *PriceRegistryInterface_ParseTokenTransferFeeConfigUpdated_Call { - _c.Call.Return(run) - return _c -} - -// ParseUsdPerTokenUpdated provides a mock function with given fields: log -func (_m *PriceRegistryInterface) ParseUsdPerTokenUpdated(log types.Log) (*price_registry.PriceRegistryUsdPerTokenUpdated, error) { - ret := _m.Called(log) - - if len(ret) == 0 { - panic("no return value specified for ParseUsdPerTokenUpdated") - } - - var r0 *price_registry.PriceRegistryUsdPerTokenUpdated - var r1 error - if rf, ok := ret.Get(0).(func(types.Log) (*price_registry.PriceRegistryUsdPerTokenUpdated, error)); ok { - return rf(log) - } - if rf, ok := ret.Get(0).(func(types.Log) *price_registry.PriceRegistryUsdPerTokenUpdated); ok { - r0 = rf(log) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*price_registry.PriceRegistryUsdPerTokenUpdated) - } - } - - if rf, ok := ret.Get(1).(func(types.Log) error); ok { - r1 = rf(log) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_ParseUsdPerTokenUpdated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParseUsdPerTokenUpdated' -type PriceRegistryInterface_ParseUsdPerTokenUpdated_Call struct { - *mock.Call -} - -// ParseUsdPerTokenUpdated is a helper method to define mock.On call -// - log types.Log -func (_e *PriceRegistryInterface_Expecter) ParseUsdPerTokenUpdated(log interface{}) *PriceRegistryInterface_ParseUsdPerTokenUpdated_Call { - return &PriceRegistryInterface_ParseUsdPerTokenUpdated_Call{Call: _e.mock.On("ParseUsdPerTokenUpdated", log)} -} - -func (_c *PriceRegistryInterface_ParseUsdPerTokenUpdated_Call) Run(run func(log types.Log)) *PriceRegistryInterface_ParseUsdPerTokenUpdated_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(types.Log)) - }) - return _c -} - -func (_c *PriceRegistryInterface_ParseUsdPerTokenUpdated_Call) Return(_a0 *price_registry.PriceRegistryUsdPerTokenUpdated, _a1 error) *PriceRegistryInterface_ParseUsdPerTokenUpdated_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_ParseUsdPerTokenUpdated_Call) RunAndReturn(run func(types.Log) (*price_registry.PriceRegistryUsdPerTokenUpdated, error)) *PriceRegistryInterface_ParseUsdPerTokenUpdated_Call { - _c.Call.Return(run) - return _c -} - -// ParseUsdPerUnitGasUpdated provides a mock function with given fields: log -func (_m *PriceRegistryInterface) ParseUsdPerUnitGasUpdated(log types.Log) (*price_registry.PriceRegistryUsdPerUnitGasUpdated, error) { - ret := _m.Called(log) - - if len(ret) == 0 { - panic("no return value specified for ParseUsdPerUnitGasUpdated") - } - - var r0 *price_registry.PriceRegistryUsdPerUnitGasUpdated - var r1 error - if rf, ok := ret.Get(0).(func(types.Log) (*price_registry.PriceRegistryUsdPerUnitGasUpdated, error)); ok { - return rf(log) - } - if rf, ok := ret.Get(0).(func(types.Log) *price_registry.PriceRegistryUsdPerUnitGasUpdated); ok { - r0 = rf(log) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*price_registry.PriceRegistryUsdPerUnitGasUpdated) - } - } - - if rf, ok := ret.Get(1).(func(types.Log) error); ok { - r1 = rf(log) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_ParseUsdPerUnitGasUpdated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParseUsdPerUnitGasUpdated' -type PriceRegistryInterface_ParseUsdPerUnitGasUpdated_Call struct { - *mock.Call -} - -// ParseUsdPerUnitGasUpdated is a helper method to define mock.On call -// - log types.Log -func (_e *PriceRegistryInterface_Expecter) ParseUsdPerUnitGasUpdated(log interface{}) *PriceRegistryInterface_ParseUsdPerUnitGasUpdated_Call { - return &PriceRegistryInterface_ParseUsdPerUnitGasUpdated_Call{Call: _e.mock.On("ParseUsdPerUnitGasUpdated", log)} -} - -func (_c *PriceRegistryInterface_ParseUsdPerUnitGasUpdated_Call) Run(run func(log types.Log)) *PriceRegistryInterface_ParseUsdPerUnitGasUpdated_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(types.Log)) - }) - return _c -} - -func (_c *PriceRegistryInterface_ParseUsdPerUnitGasUpdated_Call) Return(_a0 *price_registry.PriceRegistryUsdPerUnitGasUpdated, _a1 error) *PriceRegistryInterface_ParseUsdPerUnitGasUpdated_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_ParseUsdPerUnitGasUpdated_Call) RunAndReturn(run func(types.Log) (*price_registry.PriceRegistryUsdPerUnitGasUpdated, error)) *PriceRegistryInterface_ParseUsdPerUnitGasUpdated_Call { - _c.Call.Return(run) - return _c -} - -// ProcessMessageArgs provides a mock function with given fields: opts, destChainSelector, feeToken, feeTokenAmount, extraArgs -func (_m *PriceRegistryInterface) ProcessMessageArgs(opts *bind.CallOpts, destChainSelector uint64, feeToken common.Address, feeTokenAmount *big.Int, extraArgs []byte) (price_registry.ProcessMessageArgs, error) { - ret := _m.Called(opts, destChainSelector, feeToken, feeTokenAmount, extraArgs) - - if len(ret) == 0 { - panic("no return value specified for ProcessMessageArgs") - } - - var r0 price_registry.ProcessMessageArgs - var r1 error - if rf, ok := ret.Get(0).(func(*bind.CallOpts, uint64, common.Address, *big.Int, []byte) (price_registry.ProcessMessageArgs, error)); ok { - return rf(opts, destChainSelector, feeToken, feeTokenAmount, extraArgs) - } - if rf, ok := ret.Get(0).(func(*bind.CallOpts, uint64, common.Address, *big.Int, []byte) price_registry.ProcessMessageArgs); ok { - r0 = rf(opts, destChainSelector, feeToken, feeTokenAmount, extraArgs) - } else { - r0 = ret.Get(0).(price_registry.ProcessMessageArgs) - } - - if rf, ok := ret.Get(1).(func(*bind.CallOpts, uint64, common.Address, *big.Int, []byte) error); ok { - r1 = rf(opts, destChainSelector, feeToken, feeTokenAmount, extraArgs) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_ProcessMessageArgs_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ProcessMessageArgs' -type PriceRegistryInterface_ProcessMessageArgs_Call struct { - *mock.Call -} - -// ProcessMessageArgs is a helper method to define mock.On call -// - opts *bind.CallOpts -// - destChainSelector uint64 -// - feeToken common.Address -// - feeTokenAmount *big.Int -// - extraArgs []byte -func (_e *PriceRegistryInterface_Expecter) ProcessMessageArgs(opts interface{}, destChainSelector interface{}, feeToken interface{}, feeTokenAmount interface{}, extraArgs interface{}) *PriceRegistryInterface_ProcessMessageArgs_Call { - return &PriceRegistryInterface_ProcessMessageArgs_Call{Call: _e.mock.On("ProcessMessageArgs", opts, destChainSelector, feeToken, feeTokenAmount, extraArgs)} -} - -func (_c *PriceRegistryInterface_ProcessMessageArgs_Call) Run(run func(opts *bind.CallOpts, destChainSelector uint64, feeToken common.Address, feeTokenAmount *big.Int, extraArgs []byte)) *PriceRegistryInterface_ProcessMessageArgs_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.CallOpts), args[1].(uint64), args[2].(common.Address), args[3].(*big.Int), args[4].([]byte)) - }) - return _c -} - -func (_c *PriceRegistryInterface_ProcessMessageArgs_Call) Return(_a0 price_registry.ProcessMessageArgs, _a1 error) *PriceRegistryInterface_ProcessMessageArgs_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_ProcessMessageArgs_Call) RunAndReturn(run func(*bind.CallOpts, uint64, common.Address, *big.Int, []byte) (price_registry.ProcessMessageArgs, error)) *PriceRegistryInterface_ProcessMessageArgs_Call { - _c.Call.Return(run) - return _c -} - -// ProcessPoolReturnData provides a mock function with given fields: opts, destChainSelector, rampTokenAmounts, sourceTokenAmounts -func (_m *PriceRegistryInterface) ProcessPoolReturnData(opts *bind.CallOpts, destChainSelector uint64, rampTokenAmounts []price_registry.InternalRampTokenAmount, sourceTokenAmounts []price_registry.ClientEVMTokenAmount) ([][]byte, error) { - ret := _m.Called(opts, destChainSelector, rampTokenAmounts, sourceTokenAmounts) - - if len(ret) == 0 { - panic("no return value specified for ProcessPoolReturnData") - } - - var r0 [][]byte - var r1 error - if rf, ok := ret.Get(0).(func(*bind.CallOpts, uint64, []price_registry.InternalRampTokenAmount, []price_registry.ClientEVMTokenAmount) ([][]byte, error)); ok { - return rf(opts, destChainSelector, rampTokenAmounts, sourceTokenAmounts) - } - if rf, ok := ret.Get(0).(func(*bind.CallOpts, uint64, []price_registry.InternalRampTokenAmount, []price_registry.ClientEVMTokenAmount) [][]byte); ok { - r0 = rf(opts, destChainSelector, rampTokenAmounts, sourceTokenAmounts) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([][]byte) - } - } - - if rf, ok := ret.Get(1).(func(*bind.CallOpts, uint64, []price_registry.InternalRampTokenAmount, []price_registry.ClientEVMTokenAmount) error); ok { - r1 = rf(opts, destChainSelector, rampTokenAmounts, sourceTokenAmounts) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_ProcessPoolReturnData_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ProcessPoolReturnData' -type PriceRegistryInterface_ProcessPoolReturnData_Call struct { - *mock.Call -} - -// ProcessPoolReturnData is a helper method to define mock.On call -// - opts *bind.CallOpts -// - destChainSelector uint64 -// - rampTokenAmounts []price_registry.InternalRampTokenAmount -// - sourceTokenAmounts []price_registry.ClientEVMTokenAmount -func (_e *PriceRegistryInterface_Expecter) ProcessPoolReturnData(opts interface{}, destChainSelector interface{}, rampTokenAmounts interface{}, sourceTokenAmounts interface{}) *PriceRegistryInterface_ProcessPoolReturnData_Call { - return &PriceRegistryInterface_ProcessPoolReturnData_Call{Call: _e.mock.On("ProcessPoolReturnData", opts, destChainSelector, rampTokenAmounts, sourceTokenAmounts)} -} - -func (_c *PriceRegistryInterface_ProcessPoolReturnData_Call) Run(run func(opts *bind.CallOpts, destChainSelector uint64, rampTokenAmounts []price_registry.InternalRampTokenAmount, sourceTokenAmounts []price_registry.ClientEVMTokenAmount)) *PriceRegistryInterface_ProcessPoolReturnData_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.CallOpts), args[1].(uint64), args[2].([]price_registry.InternalRampTokenAmount), args[3].([]price_registry.ClientEVMTokenAmount)) - }) - return _c -} - -func (_c *PriceRegistryInterface_ProcessPoolReturnData_Call) Return(_a0 [][]byte, _a1 error) *PriceRegistryInterface_ProcessPoolReturnData_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_ProcessPoolReturnData_Call) RunAndReturn(run func(*bind.CallOpts, uint64, []price_registry.InternalRampTokenAmount, []price_registry.ClientEVMTokenAmount) ([][]byte, error)) *PriceRegistryInterface_ProcessPoolReturnData_Call { - _c.Call.Return(run) - return _c -} - -// SetReportPermissions provides a mock function with given fields: opts, permissions -func (_m *PriceRegistryInterface) SetReportPermissions(opts *bind.TransactOpts, permissions []price_registry.KeystoneFeedsPermissionHandlerPermission) (*types.Transaction, error) { - ret := _m.Called(opts, permissions) - - if len(ret) == 0 { - panic("no return value specified for SetReportPermissions") - } - - var r0 *types.Transaction - var r1 error - if rf, ok := ret.Get(0).(func(*bind.TransactOpts, []price_registry.KeystoneFeedsPermissionHandlerPermission) (*types.Transaction, error)); ok { - return rf(opts, permissions) - } - if rf, ok := ret.Get(0).(func(*bind.TransactOpts, []price_registry.KeystoneFeedsPermissionHandlerPermission) *types.Transaction); ok { - r0 = rf(opts, permissions) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.Transaction) - } - } - - if rf, ok := ret.Get(1).(func(*bind.TransactOpts, []price_registry.KeystoneFeedsPermissionHandlerPermission) error); ok { - r1 = rf(opts, permissions) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_SetReportPermissions_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetReportPermissions' -type PriceRegistryInterface_SetReportPermissions_Call struct { - *mock.Call -} - -// SetReportPermissions is a helper method to define mock.On call -// - opts *bind.TransactOpts -// - permissions []price_registry.KeystoneFeedsPermissionHandlerPermission -func (_e *PriceRegistryInterface_Expecter) SetReportPermissions(opts interface{}, permissions interface{}) *PriceRegistryInterface_SetReportPermissions_Call { - return &PriceRegistryInterface_SetReportPermissions_Call{Call: _e.mock.On("SetReportPermissions", opts, permissions)} -} - -func (_c *PriceRegistryInterface_SetReportPermissions_Call) Run(run func(opts *bind.TransactOpts, permissions []price_registry.KeystoneFeedsPermissionHandlerPermission)) *PriceRegistryInterface_SetReportPermissions_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.TransactOpts), args[1].([]price_registry.KeystoneFeedsPermissionHandlerPermission)) - }) - return _c -} - -func (_c *PriceRegistryInterface_SetReportPermissions_Call) Return(_a0 *types.Transaction, _a1 error) *PriceRegistryInterface_SetReportPermissions_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_SetReportPermissions_Call) RunAndReturn(run func(*bind.TransactOpts, []price_registry.KeystoneFeedsPermissionHandlerPermission) (*types.Transaction, error)) *PriceRegistryInterface_SetReportPermissions_Call { - _c.Call.Return(run) - return _c -} - -// TransferOwnership provides a mock function with given fields: opts, to -func (_m *PriceRegistryInterface) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { - ret := _m.Called(opts, to) - - if len(ret) == 0 { - panic("no return value specified for TransferOwnership") - } - - var r0 *types.Transaction - var r1 error - if rf, ok := ret.Get(0).(func(*bind.TransactOpts, common.Address) (*types.Transaction, error)); ok { - return rf(opts, to) - } - if rf, ok := ret.Get(0).(func(*bind.TransactOpts, common.Address) *types.Transaction); ok { - r0 = rf(opts, to) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.Transaction) - } - } - - if rf, ok := ret.Get(1).(func(*bind.TransactOpts, common.Address) error); ok { - r1 = rf(opts, to) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_TransferOwnership_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'TransferOwnership' -type PriceRegistryInterface_TransferOwnership_Call struct { - *mock.Call -} - -// TransferOwnership is a helper method to define mock.On call -// - opts *bind.TransactOpts -// - to common.Address -func (_e *PriceRegistryInterface_Expecter) TransferOwnership(opts interface{}, to interface{}) *PriceRegistryInterface_TransferOwnership_Call { - return &PriceRegistryInterface_TransferOwnership_Call{Call: _e.mock.On("TransferOwnership", opts, to)} -} - -func (_c *PriceRegistryInterface_TransferOwnership_Call) Run(run func(opts *bind.TransactOpts, to common.Address)) *PriceRegistryInterface_TransferOwnership_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.TransactOpts), args[1].(common.Address)) - }) - return _c -} - -func (_c *PriceRegistryInterface_TransferOwnership_Call) Return(_a0 *types.Transaction, _a1 error) *PriceRegistryInterface_TransferOwnership_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_TransferOwnership_Call) RunAndReturn(run func(*bind.TransactOpts, common.Address) (*types.Transaction, error)) *PriceRegistryInterface_TransferOwnership_Call { - _c.Call.Return(run) - return _c -} - -// TypeAndVersion provides a mock function with given fields: opts -func (_m *PriceRegistryInterface) TypeAndVersion(opts *bind.CallOpts) (string, error) { - ret := _m.Called(opts) - - if len(ret) == 0 { - panic("no return value specified for TypeAndVersion") - } - - var r0 string - var r1 error - if rf, ok := ret.Get(0).(func(*bind.CallOpts) (string, error)); ok { - return rf(opts) - } - if rf, ok := ret.Get(0).(func(*bind.CallOpts) string); ok { - r0 = rf(opts) - } else { - r0 = ret.Get(0).(string) - } - - if rf, ok := ret.Get(1).(func(*bind.CallOpts) error); ok { - r1 = rf(opts) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_TypeAndVersion_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'TypeAndVersion' -type PriceRegistryInterface_TypeAndVersion_Call struct { - *mock.Call -} - -// TypeAndVersion is a helper method to define mock.On call -// - opts *bind.CallOpts -func (_e *PriceRegistryInterface_Expecter) TypeAndVersion(opts interface{}) *PriceRegistryInterface_TypeAndVersion_Call { - return &PriceRegistryInterface_TypeAndVersion_Call{Call: _e.mock.On("TypeAndVersion", opts)} -} - -func (_c *PriceRegistryInterface_TypeAndVersion_Call) Run(run func(opts *bind.CallOpts)) *PriceRegistryInterface_TypeAndVersion_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.CallOpts)) - }) - return _c -} - -func (_c *PriceRegistryInterface_TypeAndVersion_Call) Return(_a0 string, _a1 error) *PriceRegistryInterface_TypeAndVersion_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_TypeAndVersion_Call) RunAndReturn(run func(*bind.CallOpts) (string, error)) *PriceRegistryInterface_TypeAndVersion_Call { - _c.Call.Return(run) - return _c -} - -// UpdatePrices provides a mock function with given fields: opts, priceUpdates -func (_m *PriceRegistryInterface) UpdatePrices(opts *bind.TransactOpts, priceUpdates price_registry.InternalPriceUpdates) (*types.Transaction, error) { - ret := _m.Called(opts, priceUpdates) - - if len(ret) == 0 { - panic("no return value specified for UpdatePrices") - } - - var r0 *types.Transaction - var r1 error - if rf, ok := ret.Get(0).(func(*bind.TransactOpts, price_registry.InternalPriceUpdates) (*types.Transaction, error)); ok { - return rf(opts, priceUpdates) - } - if rf, ok := ret.Get(0).(func(*bind.TransactOpts, price_registry.InternalPriceUpdates) *types.Transaction); ok { - r0 = rf(opts, priceUpdates) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.Transaction) - } - } - - if rf, ok := ret.Get(1).(func(*bind.TransactOpts, price_registry.InternalPriceUpdates) error); ok { - r1 = rf(opts, priceUpdates) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_UpdatePrices_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdatePrices' -type PriceRegistryInterface_UpdatePrices_Call struct { - *mock.Call -} - -// UpdatePrices is a helper method to define mock.On call -// - opts *bind.TransactOpts -// - priceUpdates price_registry.InternalPriceUpdates -func (_e *PriceRegistryInterface_Expecter) UpdatePrices(opts interface{}, priceUpdates interface{}) *PriceRegistryInterface_UpdatePrices_Call { - return &PriceRegistryInterface_UpdatePrices_Call{Call: _e.mock.On("UpdatePrices", opts, priceUpdates)} -} - -func (_c *PriceRegistryInterface_UpdatePrices_Call) Run(run func(opts *bind.TransactOpts, priceUpdates price_registry.InternalPriceUpdates)) *PriceRegistryInterface_UpdatePrices_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.TransactOpts), args[1].(price_registry.InternalPriceUpdates)) - }) - return _c -} - -func (_c *PriceRegistryInterface_UpdatePrices_Call) Return(_a0 *types.Transaction, _a1 error) *PriceRegistryInterface_UpdatePrices_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_UpdatePrices_Call) RunAndReturn(run func(*bind.TransactOpts, price_registry.InternalPriceUpdates) (*types.Transaction, error)) *PriceRegistryInterface_UpdatePrices_Call { - _c.Call.Return(run) - return _c -} - -// UpdateTokenPriceFeeds provides a mock function with given fields: opts, tokenPriceFeedUpdates -func (_m *PriceRegistryInterface) UpdateTokenPriceFeeds(opts *bind.TransactOpts, tokenPriceFeedUpdates []price_registry.PriceRegistryTokenPriceFeedUpdate) (*types.Transaction, error) { - ret := _m.Called(opts, tokenPriceFeedUpdates) - - if len(ret) == 0 { - panic("no return value specified for UpdateTokenPriceFeeds") - } - - var r0 *types.Transaction - var r1 error - if rf, ok := ret.Get(0).(func(*bind.TransactOpts, []price_registry.PriceRegistryTokenPriceFeedUpdate) (*types.Transaction, error)); ok { - return rf(opts, tokenPriceFeedUpdates) - } - if rf, ok := ret.Get(0).(func(*bind.TransactOpts, []price_registry.PriceRegistryTokenPriceFeedUpdate) *types.Transaction); ok { - r0 = rf(opts, tokenPriceFeedUpdates) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.Transaction) - } - } - - if rf, ok := ret.Get(1).(func(*bind.TransactOpts, []price_registry.PriceRegistryTokenPriceFeedUpdate) error); ok { - r1 = rf(opts, tokenPriceFeedUpdates) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_UpdateTokenPriceFeeds_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateTokenPriceFeeds' -type PriceRegistryInterface_UpdateTokenPriceFeeds_Call struct { - *mock.Call -} - -// UpdateTokenPriceFeeds is a helper method to define mock.On call -// - opts *bind.TransactOpts -// - tokenPriceFeedUpdates []price_registry.PriceRegistryTokenPriceFeedUpdate -func (_e *PriceRegistryInterface_Expecter) UpdateTokenPriceFeeds(opts interface{}, tokenPriceFeedUpdates interface{}) *PriceRegistryInterface_UpdateTokenPriceFeeds_Call { - return &PriceRegistryInterface_UpdateTokenPriceFeeds_Call{Call: _e.mock.On("UpdateTokenPriceFeeds", opts, tokenPriceFeedUpdates)} -} - -func (_c *PriceRegistryInterface_UpdateTokenPriceFeeds_Call) Run(run func(opts *bind.TransactOpts, tokenPriceFeedUpdates []price_registry.PriceRegistryTokenPriceFeedUpdate)) *PriceRegistryInterface_UpdateTokenPriceFeeds_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.TransactOpts), args[1].([]price_registry.PriceRegistryTokenPriceFeedUpdate)) - }) - return _c -} - -func (_c *PriceRegistryInterface_UpdateTokenPriceFeeds_Call) Return(_a0 *types.Transaction, _a1 error) *PriceRegistryInterface_UpdateTokenPriceFeeds_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_UpdateTokenPriceFeeds_Call) RunAndReturn(run func(*bind.TransactOpts, []price_registry.PriceRegistryTokenPriceFeedUpdate) (*types.Transaction, error)) *PriceRegistryInterface_UpdateTokenPriceFeeds_Call { - _c.Call.Return(run) - return _c -} - -// WatchAuthorizedCallerAdded provides a mock function with given fields: opts, sink -func (_m *PriceRegistryInterface) WatchAuthorizedCallerAdded(opts *bind.WatchOpts, sink chan<- *price_registry.PriceRegistryAuthorizedCallerAdded) (event.Subscription, error) { - ret := _m.Called(opts, sink) - - if len(ret) == 0 { - panic("no return value specified for WatchAuthorizedCallerAdded") - } - - var r0 event.Subscription - var r1 error - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryAuthorizedCallerAdded) (event.Subscription, error)); ok { - return rf(opts, sink) - } - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryAuthorizedCallerAdded) event.Subscription); ok { - r0 = rf(opts, sink) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(event.Subscription) - } - } - - if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryAuthorizedCallerAdded) error); ok { - r1 = rf(opts, sink) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_WatchAuthorizedCallerAdded_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchAuthorizedCallerAdded' -type PriceRegistryInterface_WatchAuthorizedCallerAdded_Call struct { - *mock.Call -} - -// WatchAuthorizedCallerAdded is a helper method to define mock.On call -// - opts *bind.WatchOpts -// - sink chan<- *price_registry.PriceRegistryAuthorizedCallerAdded -func (_e *PriceRegistryInterface_Expecter) WatchAuthorizedCallerAdded(opts interface{}, sink interface{}) *PriceRegistryInterface_WatchAuthorizedCallerAdded_Call { - return &PriceRegistryInterface_WatchAuthorizedCallerAdded_Call{Call: _e.mock.On("WatchAuthorizedCallerAdded", opts, sink)} -} - -func (_c *PriceRegistryInterface_WatchAuthorizedCallerAdded_Call) Run(run func(opts *bind.WatchOpts, sink chan<- *price_registry.PriceRegistryAuthorizedCallerAdded)) *PriceRegistryInterface_WatchAuthorizedCallerAdded_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.WatchOpts), args[1].(chan<- *price_registry.PriceRegistryAuthorizedCallerAdded)) - }) - return _c -} - -func (_c *PriceRegistryInterface_WatchAuthorizedCallerAdded_Call) Return(_a0 event.Subscription, _a1 error) *PriceRegistryInterface_WatchAuthorizedCallerAdded_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_WatchAuthorizedCallerAdded_Call) RunAndReturn(run func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryAuthorizedCallerAdded) (event.Subscription, error)) *PriceRegistryInterface_WatchAuthorizedCallerAdded_Call { - _c.Call.Return(run) - return _c -} - -// WatchAuthorizedCallerRemoved provides a mock function with given fields: opts, sink -func (_m *PriceRegistryInterface) WatchAuthorizedCallerRemoved(opts *bind.WatchOpts, sink chan<- *price_registry.PriceRegistryAuthorizedCallerRemoved) (event.Subscription, error) { - ret := _m.Called(opts, sink) - - if len(ret) == 0 { - panic("no return value specified for WatchAuthorizedCallerRemoved") - } - - var r0 event.Subscription - var r1 error - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryAuthorizedCallerRemoved) (event.Subscription, error)); ok { - return rf(opts, sink) - } - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryAuthorizedCallerRemoved) event.Subscription); ok { - r0 = rf(opts, sink) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(event.Subscription) - } - } - - if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryAuthorizedCallerRemoved) error); ok { - r1 = rf(opts, sink) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_WatchAuthorizedCallerRemoved_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchAuthorizedCallerRemoved' -type PriceRegistryInterface_WatchAuthorizedCallerRemoved_Call struct { - *mock.Call -} - -// WatchAuthorizedCallerRemoved is a helper method to define mock.On call -// - opts *bind.WatchOpts -// - sink chan<- *price_registry.PriceRegistryAuthorizedCallerRemoved -func (_e *PriceRegistryInterface_Expecter) WatchAuthorizedCallerRemoved(opts interface{}, sink interface{}) *PriceRegistryInterface_WatchAuthorizedCallerRemoved_Call { - return &PriceRegistryInterface_WatchAuthorizedCallerRemoved_Call{Call: _e.mock.On("WatchAuthorizedCallerRemoved", opts, sink)} -} - -func (_c *PriceRegistryInterface_WatchAuthorizedCallerRemoved_Call) Run(run func(opts *bind.WatchOpts, sink chan<- *price_registry.PriceRegistryAuthorizedCallerRemoved)) *PriceRegistryInterface_WatchAuthorizedCallerRemoved_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.WatchOpts), args[1].(chan<- *price_registry.PriceRegistryAuthorizedCallerRemoved)) - }) - return _c -} - -func (_c *PriceRegistryInterface_WatchAuthorizedCallerRemoved_Call) Return(_a0 event.Subscription, _a1 error) *PriceRegistryInterface_WatchAuthorizedCallerRemoved_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_WatchAuthorizedCallerRemoved_Call) RunAndReturn(run func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryAuthorizedCallerRemoved) (event.Subscription, error)) *PriceRegistryInterface_WatchAuthorizedCallerRemoved_Call { - _c.Call.Return(run) - return _c -} - -// WatchDestChainAdded provides a mock function with given fields: opts, sink, destChainSelector -func (_m *PriceRegistryInterface) WatchDestChainAdded(opts *bind.WatchOpts, sink chan<- *price_registry.PriceRegistryDestChainAdded, destChainSelector []uint64) (event.Subscription, error) { - ret := _m.Called(opts, sink, destChainSelector) - - if len(ret) == 0 { - panic("no return value specified for WatchDestChainAdded") - } - - var r0 event.Subscription - var r1 error - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryDestChainAdded, []uint64) (event.Subscription, error)); ok { - return rf(opts, sink, destChainSelector) - } - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryDestChainAdded, []uint64) event.Subscription); ok { - r0 = rf(opts, sink, destChainSelector) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(event.Subscription) - } - } - - if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryDestChainAdded, []uint64) error); ok { - r1 = rf(opts, sink, destChainSelector) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_WatchDestChainAdded_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchDestChainAdded' -type PriceRegistryInterface_WatchDestChainAdded_Call struct { - *mock.Call -} - -// WatchDestChainAdded is a helper method to define mock.On call -// - opts *bind.WatchOpts -// - sink chan<- *price_registry.PriceRegistryDestChainAdded -// - destChainSelector []uint64 -func (_e *PriceRegistryInterface_Expecter) WatchDestChainAdded(opts interface{}, sink interface{}, destChainSelector interface{}) *PriceRegistryInterface_WatchDestChainAdded_Call { - return &PriceRegistryInterface_WatchDestChainAdded_Call{Call: _e.mock.On("WatchDestChainAdded", opts, sink, destChainSelector)} -} - -func (_c *PriceRegistryInterface_WatchDestChainAdded_Call) Run(run func(opts *bind.WatchOpts, sink chan<- *price_registry.PriceRegistryDestChainAdded, destChainSelector []uint64)) *PriceRegistryInterface_WatchDestChainAdded_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.WatchOpts), args[1].(chan<- *price_registry.PriceRegistryDestChainAdded), args[2].([]uint64)) - }) - return _c -} - -func (_c *PriceRegistryInterface_WatchDestChainAdded_Call) Return(_a0 event.Subscription, _a1 error) *PriceRegistryInterface_WatchDestChainAdded_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_WatchDestChainAdded_Call) RunAndReturn(run func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryDestChainAdded, []uint64) (event.Subscription, error)) *PriceRegistryInterface_WatchDestChainAdded_Call { - _c.Call.Return(run) - return _c -} - -// WatchDestChainConfigUpdated provides a mock function with given fields: opts, sink, destChainSelector -func (_m *PriceRegistryInterface) WatchDestChainConfigUpdated(opts *bind.WatchOpts, sink chan<- *price_registry.PriceRegistryDestChainConfigUpdated, destChainSelector []uint64) (event.Subscription, error) { - ret := _m.Called(opts, sink, destChainSelector) - - if len(ret) == 0 { - panic("no return value specified for WatchDestChainConfigUpdated") - } - - var r0 event.Subscription - var r1 error - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryDestChainConfigUpdated, []uint64) (event.Subscription, error)); ok { - return rf(opts, sink, destChainSelector) - } - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryDestChainConfigUpdated, []uint64) event.Subscription); ok { - r0 = rf(opts, sink, destChainSelector) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(event.Subscription) - } - } - - if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryDestChainConfigUpdated, []uint64) error); ok { - r1 = rf(opts, sink, destChainSelector) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_WatchDestChainConfigUpdated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchDestChainConfigUpdated' -type PriceRegistryInterface_WatchDestChainConfigUpdated_Call struct { - *mock.Call -} - -// WatchDestChainConfigUpdated is a helper method to define mock.On call -// - opts *bind.WatchOpts -// - sink chan<- *price_registry.PriceRegistryDestChainConfigUpdated -// - destChainSelector []uint64 -func (_e *PriceRegistryInterface_Expecter) WatchDestChainConfigUpdated(opts interface{}, sink interface{}, destChainSelector interface{}) *PriceRegistryInterface_WatchDestChainConfigUpdated_Call { - return &PriceRegistryInterface_WatchDestChainConfigUpdated_Call{Call: _e.mock.On("WatchDestChainConfigUpdated", opts, sink, destChainSelector)} -} - -func (_c *PriceRegistryInterface_WatchDestChainConfigUpdated_Call) Run(run func(opts *bind.WatchOpts, sink chan<- *price_registry.PriceRegistryDestChainConfigUpdated, destChainSelector []uint64)) *PriceRegistryInterface_WatchDestChainConfigUpdated_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.WatchOpts), args[1].(chan<- *price_registry.PriceRegistryDestChainConfigUpdated), args[2].([]uint64)) - }) - return _c -} - -func (_c *PriceRegistryInterface_WatchDestChainConfigUpdated_Call) Return(_a0 event.Subscription, _a1 error) *PriceRegistryInterface_WatchDestChainConfigUpdated_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_WatchDestChainConfigUpdated_Call) RunAndReturn(run func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryDestChainConfigUpdated, []uint64) (event.Subscription, error)) *PriceRegistryInterface_WatchDestChainConfigUpdated_Call { - _c.Call.Return(run) - return _c -} - -// WatchFeeTokenAdded provides a mock function with given fields: opts, sink, feeToken -func (_m *PriceRegistryInterface) WatchFeeTokenAdded(opts *bind.WatchOpts, sink chan<- *price_registry.PriceRegistryFeeTokenAdded, feeToken []common.Address) (event.Subscription, error) { - ret := _m.Called(opts, sink, feeToken) - - if len(ret) == 0 { - panic("no return value specified for WatchFeeTokenAdded") - } - - var r0 event.Subscription - var r1 error - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryFeeTokenAdded, []common.Address) (event.Subscription, error)); ok { - return rf(opts, sink, feeToken) - } - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryFeeTokenAdded, []common.Address) event.Subscription); ok { - r0 = rf(opts, sink, feeToken) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(event.Subscription) - } - } - - if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryFeeTokenAdded, []common.Address) error); ok { - r1 = rf(opts, sink, feeToken) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_WatchFeeTokenAdded_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchFeeTokenAdded' -type PriceRegistryInterface_WatchFeeTokenAdded_Call struct { - *mock.Call -} - -// WatchFeeTokenAdded is a helper method to define mock.On call -// - opts *bind.WatchOpts -// - sink chan<- *price_registry.PriceRegistryFeeTokenAdded -// - feeToken []common.Address -func (_e *PriceRegistryInterface_Expecter) WatchFeeTokenAdded(opts interface{}, sink interface{}, feeToken interface{}) *PriceRegistryInterface_WatchFeeTokenAdded_Call { - return &PriceRegistryInterface_WatchFeeTokenAdded_Call{Call: _e.mock.On("WatchFeeTokenAdded", opts, sink, feeToken)} -} - -func (_c *PriceRegistryInterface_WatchFeeTokenAdded_Call) Run(run func(opts *bind.WatchOpts, sink chan<- *price_registry.PriceRegistryFeeTokenAdded, feeToken []common.Address)) *PriceRegistryInterface_WatchFeeTokenAdded_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.WatchOpts), args[1].(chan<- *price_registry.PriceRegistryFeeTokenAdded), args[2].([]common.Address)) - }) - return _c -} - -func (_c *PriceRegistryInterface_WatchFeeTokenAdded_Call) Return(_a0 event.Subscription, _a1 error) *PriceRegistryInterface_WatchFeeTokenAdded_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_WatchFeeTokenAdded_Call) RunAndReturn(run func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryFeeTokenAdded, []common.Address) (event.Subscription, error)) *PriceRegistryInterface_WatchFeeTokenAdded_Call { - _c.Call.Return(run) - return _c -} - -// WatchFeeTokenRemoved provides a mock function with given fields: opts, sink, feeToken -func (_m *PriceRegistryInterface) WatchFeeTokenRemoved(opts *bind.WatchOpts, sink chan<- *price_registry.PriceRegistryFeeTokenRemoved, feeToken []common.Address) (event.Subscription, error) { - ret := _m.Called(opts, sink, feeToken) - - if len(ret) == 0 { - panic("no return value specified for WatchFeeTokenRemoved") - } - - var r0 event.Subscription - var r1 error - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryFeeTokenRemoved, []common.Address) (event.Subscription, error)); ok { - return rf(opts, sink, feeToken) - } - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryFeeTokenRemoved, []common.Address) event.Subscription); ok { - r0 = rf(opts, sink, feeToken) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(event.Subscription) - } - } - - if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryFeeTokenRemoved, []common.Address) error); ok { - r1 = rf(opts, sink, feeToken) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_WatchFeeTokenRemoved_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchFeeTokenRemoved' -type PriceRegistryInterface_WatchFeeTokenRemoved_Call struct { - *mock.Call -} - -// WatchFeeTokenRemoved is a helper method to define mock.On call -// - opts *bind.WatchOpts -// - sink chan<- *price_registry.PriceRegistryFeeTokenRemoved -// - feeToken []common.Address -func (_e *PriceRegistryInterface_Expecter) WatchFeeTokenRemoved(opts interface{}, sink interface{}, feeToken interface{}) *PriceRegistryInterface_WatchFeeTokenRemoved_Call { - return &PriceRegistryInterface_WatchFeeTokenRemoved_Call{Call: _e.mock.On("WatchFeeTokenRemoved", opts, sink, feeToken)} -} - -func (_c *PriceRegistryInterface_WatchFeeTokenRemoved_Call) Run(run func(opts *bind.WatchOpts, sink chan<- *price_registry.PriceRegistryFeeTokenRemoved, feeToken []common.Address)) *PriceRegistryInterface_WatchFeeTokenRemoved_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.WatchOpts), args[1].(chan<- *price_registry.PriceRegistryFeeTokenRemoved), args[2].([]common.Address)) - }) - return _c -} - -func (_c *PriceRegistryInterface_WatchFeeTokenRemoved_Call) Return(_a0 event.Subscription, _a1 error) *PriceRegistryInterface_WatchFeeTokenRemoved_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_WatchFeeTokenRemoved_Call) RunAndReturn(run func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryFeeTokenRemoved, []common.Address) (event.Subscription, error)) *PriceRegistryInterface_WatchFeeTokenRemoved_Call { - _c.Call.Return(run) - return _c -} - -// WatchOwnershipTransferRequested provides a mock function with given fields: opts, sink, from, to -func (_m *PriceRegistryInterface) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *price_registry.PriceRegistryOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) { - ret := _m.Called(opts, sink, from, to) - - if len(ret) == 0 { - panic("no return value specified for WatchOwnershipTransferRequested") - } - - var r0 event.Subscription - var r1 error - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryOwnershipTransferRequested, []common.Address, []common.Address) (event.Subscription, error)); ok { - return rf(opts, sink, from, to) - } - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryOwnershipTransferRequested, []common.Address, []common.Address) event.Subscription); ok { - r0 = rf(opts, sink, from, to) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(event.Subscription) - } - } - - if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryOwnershipTransferRequested, []common.Address, []common.Address) error); ok { - r1 = rf(opts, sink, from, to) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_WatchOwnershipTransferRequested_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchOwnershipTransferRequested' -type PriceRegistryInterface_WatchOwnershipTransferRequested_Call struct { - *mock.Call -} - -// WatchOwnershipTransferRequested is a helper method to define mock.On call -// - opts *bind.WatchOpts -// - sink chan<- *price_registry.PriceRegistryOwnershipTransferRequested -// - from []common.Address -// - to []common.Address -func (_e *PriceRegistryInterface_Expecter) WatchOwnershipTransferRequested(opts interface{}, sink interface{}, from interface{}, to interface{}) *PriceRegistryInterface_WatchOwnershipTransferRequested_Call { - return &PriceRegistryInterface_WatchOwnershipTransferRequested_Call{Call: _e.mock.On("WatchOwnershipTransferRequested", opts, sink, from, to)} -} - -func (_c *PriceRegistryInterface_WatchOwnershipTransferRequested_Call) Run(run func(opts *bind.WatchOpts, sink chan<- *price_registry.PriceRegistryOwnershipTransferRequested, from []common.Address, to []common.Address)) *PriceRegistryInterface_WatchOwnershipTransferRequested_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.WatchOpts), args[1].(chan<- *price_registry.PriceRegistryOwnershipTransferRequested), args[2].([]common.Address), args[3].([]common.Address)) - }) - return _c -} - -func (_c *PriceRegistryInterface_WatchOwnershipTransferRequested_Call) Return(_a0 event.Subscription, _a1 error) *PriceRegistryInterface_WatchOwnershipTransferRequested_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_WatchOwnershipTransferRequested_Call) RunAndReturn(run func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryOwnershipTransferRequested, []common.Address, []common.Address) (event.Subscription, error)) *PriceRegistryInterface_WatchOwnershipTransferRequested_Call { - _c.Call.Return(run) - return _c -} - -// WatchOwnershipTransferred provides a mock function with given fields: opts, sink, from, to -func (_m *PriceRegistryInterface) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *price_registry.PriceRegistryOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) { - ret := _m.Called(opts, sink, from, to) - - if len(ret) == 0 { - panic("no return value specified for WatchOwnershipTransferred") - } - - var r0 event.Subscription - var r1 error - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryOwnershipTransferred, []common.Address, []common.Address) (event.Subscription, error)); ok { - return rf(opts, sink, from, to) - } - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryOwnershipTransferred, []common.Address, []common.Address) event.Subscription); ok { - r0 = rf(opts, sink, from, to) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(event.Subscription) - } - } - - if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryOwnershipTransferred, []common.Address, []common.Address) error); ok { - r1 = rf(opts, sink, from, to) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_WatchOwnershipTransferred_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchOwnershipTransferred' -type PriceRegistryInterface_WatchOwnershipTransferred_Call struct { - *mock.Call -} - -// WatchOwnershipTransferred is a helper method to define mock.On call -// - opts *bind.WatchOpts -// - sink chan<- *price_registry.PriceRegistryOwnershipTransferred -// - from []common.Address -// - to []common.Address -func (_e *PriceRegistryInterface_Expecter) WatchOwnershipTransferred(opts interface{}, sink interface{}, from interface{}, to interface{}) *PriceRegistryInterface_WatchOwnershipTransferred_Call { - return &PriceRegistryInterface_WatchOwnershipTransferred_Call{Call: _e.mock.On("WatchOwnershipTransferred", opts, sink, from, to)} -} - -func (_c *PriceRegistryInterface_WatchOwnershipTransferred_Call) Run(run func(opts *bind.WatchOpts, sink chan<- *price_registry.PriceRegistryOwnershipTransferred, from []common.Address, to []common.Address)) *PriceRegistryInterface_WatchOwnershipTransferred_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.WatchOpts), args[1].(chan<- *price_registry.PriceRegistryOwnershipTransferred), args[2].([]common.Address), args[3].([]common.Address)) - }) - return _c -} - -func (_c *PriceRegistryInterface_WatchOwnershipTransferred_Call) Return(_a0 event.Subscription, _a1 error) *PriceRegistryInterface_WatchOwnershipTransferred_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_WatchOwnershipTransferred_Call) RunAndReturn(run func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryOwnershipTransferred, []common.Address, []common.Address) (event.Subscription, error)) *PriceRegistryInterface_WatchOwnershipTransferred_Call { - _c.Call.Return(run) - return _c -} - -// WatchPremiumMultiplierWeiPerEthUpdated provides a mock function with given fields: opts, sink, token -func (_m *PriceRegistryInterface) WatchPremiumMultiplierWeiPerEthUpdated(opts *bind.WatchOpts, sink chan<- *price_registry.PriceRegistryPremiumMultiplierWeiPerEthUpdated, token []common.Address) (event.Subscription, error) { - ret := _m.Called(opts, sink, token) - - if len(ret) == 0 { - panic("no return value specified for WatchPremiumMultiplierWeiPerEthUpdated") - } - - var r0 event.Subscription - var r1 error - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryPremiumMultiplierWeiPerEthUpdated, []common.Address) (event.Subscription, error)); ok { - return rf(opts, sink, token) - } - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryPremiumMultiplierWeiPerEthUpdated, []common.Address) event.Subscription); ok { - r0 = rf(opts, sink, token) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(event.Subscription) - } - } - - if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryPremiumMultiplierWeiPerEthUpdated, []common.Address) error); ok { - r1 = rf(opts, sink, token) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_WatchPremiumMultiplierWeiPerEthUpdated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchPremiumMultiplierWeiPerEthUpdated' -type PriceRegistryInterface_WatchPremiumMultiplierWeiPerEthUpdated_Call struct { - *mock.Call -} - -// WatchPremiumMultiplierWeiPerEthUpdated is a helper method to define mock.On call -// - opts *bind.WatchOpts -// - sink chan<- *price_registry.PriceRegistryPremiumMultiplierWeiPerEthUpdated -// - token []common.Address -func (_e *PriceRegistryInterface_Expecter) WatchPremiumMultiplierWeiPerEthUpdated(opts interface{}, sink interface{}, token interface{}) *PriceRegistryInterface_WatchPremiumMultiplierWeiPerEthUpdated_Call { - return &PriceRegistryInterface_WatchPremiumMultiplierWeiPerEthUpdated_Call{Call: _e.mock.On("WatchPremiumMultiplierWeiPerEthUpdated", opts, sink, token)} -} - -func (_c *PriceRegistryInterface_WatchPremiumMultiplierWeiPerEthUpdated_Call) Run(run func(opts *bind.WatchOpts, sink chan<- *price_registry.PriceRegistryPremiumMultiplierWeiPerEthUpdated, token []common.Address)) *PriceRegistryInterface_WatchPremiumMultiplierWeiPerEthUpdated_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.WatchOpts), args[1].(chan<- *price_registry.PriceRegistryPremiumMultiplierWeiPerEthUpdated), args[2].([]common.Address)) - }) - return _c -} - -func (_c *PriceRegistryInterface_WatchPremiumMultiplierWeiPerEthUpdated_Call) Return(_a0 event.Subscription, _a1 error) *PriceRegistryInterface_WatchPremiumMultiplierWeiPerEthUpdated_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_WatchPremiumMultiplierWeiPerEthUpdated_Call) RunAndReturn(run func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryPremiumMultiplierWeiPerEthUpdated, []common.Address) (event.Subscription, error)) *PriceRegistryInterface_WatchPremiumMultiplierWeiPerEthUpdated_Call { - _c.Call.Return(run) - return _c -} - -// WatchPriceFeedPerTokenUpdated provides a mock function with given fields: opts, sink, token -func (_m *PriceRegistryInterface) WatchPriceFeedPerTokenUpdated(opts *bind.WatchOpts, sink chan<- *price_registry.PriceRegistryPriceFeedPerTokenUpdated, token []common.Address) (event.Subscription, error) { - ret := _m.Called(opts, sink, token) - - if len(ret) == 0 { - panic("no return value specified for WatchPriceFeedPerTokenUpdated") - } - - var r0 event.Subscription - var r1 error - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryPriceFeedPerTokenUpdated, []common.Address) (event.Subscription, error)); ok { - return rf(opts, sink, token) - } - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryPriceFeedPerTokenUpdated, []common.Address) event.Subscription); ok { - r0 = rf(opts, sink, token) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(event.Subscription) - } - } - - if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryPriceFeedPerTokenUpdated, []common.Address) error); ok { - r1 = rf(opts, sink, token) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_WatchPriceFeedPerTokenUpdated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchPriceFeedPerTokenUpdated' -type PriceRegistryInterface_WatchPriceFeedPerTokenUpdated_Call struct { - *mock.Call -} - -// WatchPriceFeedPerTokenUpdated is a helper method to define mock.On call -// - opts *bind.WatchOpts -// - sink chan<- *price_registry.PriceRegistryPriceFeedPerTokenUpdated -// - token []common.Address -func (_e *PriceRegistryInterface_Expecter) WatchPriceFeedPerTokenUpdated(opts interface{}, sink interface{}, token interface{}) *PriceRegistryInterface_WatchPriceFeedPerTokenUpdated_Call { - return &PriceRegistryInterface_WatchPriceFeedPerTokenUpdated_Call{Call: _e.mock.On("WatchPriceFeedPerTokenUpdated", opts, sink, token)} -} - -func (_c *PriceRegistryInterface_WatchPriceFeedPerTokenUpdated_Call) Run(run func(opts *bind.WatchOpts, sink chan<- *price_registry.PriceRegistryPriceFeedPerTokenUpdated, token []common.Address)) *PriceRegistryInterface_WatchPriceFeedPerTokenUpdated_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.WatchOpts), args[1].(chan<- *price_registry.PriceRegistryPriceFeedPerTokenUpdated), args[2].([]common.Address)) - }) - return _c -} - -func (_c *PriceRegistryInterface_WatchPriceFeedPerTokenUpdated_Call) Return(_a0 event.Subscription, _a1 error) *PriceRegistryInterface_WatchPriceFeedPerTokenUpdated_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_WatchPriceFeedPerTokenUpdated_Call) RunAndReturn(run func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryPriceFeedPerTokenUpdated, []common.Address) (event.Subscription, error)) *PriceRegistryInterface_WatchPriceFeedPerTokenUpdated_Call { - _c.Call.Return(run) - return _c -} - -// WatchReportPermissionSet provides a mock function with given fields: opts, sink, reportId -func (_m *PriceRegistryInterface) WatchReportPermissionSet(opts *bind.WatchOpts, sink chan<- *price_registry.PriceRegistryReportPermissionSet, reportId [][32]byte) (event.Subscription, error) { - ret := _m.Called(opts, sink, reportId) - - if len(ret) == 0 { - panic("no return value specified for WatchReportPermissionSet") - } - - var r0 event.Subscription - var r1 error - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryReportPermissionSet, [][32]byte) (event.Subscription, error)); ok { - return rf(opts, sink, reportId) - } - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryReportPermissionSet, [][32]byte) event.Subscription); ok { - r0 = rf(opts, sink, reportId) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(event.Subscription) - } - } - - if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryReportPermissionSet, [][32]byte) error); ok { - r1 = rf(opts, sink, reportId) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_WatchReportPermissionSet_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchReportPermissionSet' -type PriceRegistryInterface_WatchReportPermissionSet_Call struct { - *mock.Call -} - -// WatchReportPermissionSet is a helper method to define mock.On call -// - opts *bind.WatchOpts -// - sink chan<- *price_registry.PriceRegistryReportPermissionSet -// - reportId [][32]byte -func (_e *PriceRegistryInterface_Expecter) WatchReportPermissionSet(opts interface{}, sink interface{}, reportId interface{}) *PriceRegistryInterface_WatchReportPermissionSet_Call { - return &PriceRegistryInterface_WatchReportPermissionSet_Call{Call: _e.mock.On("WatchReportPermissionSet", opts, sink, reportId)} -} - -func (_c *PriceRegistryInterface_WatchReportPermissionSet_Call) Run(run func(opts *bind.WatchOpts, sink chan<- *price_registry.PriceRegistryReportPermissionSet, reportId [][32]byte)) *PriceRegistryInterface_WatchReportPermissionSet_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.WatchOpts), args[1].(chan<- *price_registry.PriceRegistryReportPermissionSet), args[2].([][32]byte)) - }) - return _c -} - -func (_c *PriceRegistryInterface_WatchReportPermissionSet_Call) Return(_a0 event.Subscription, _a1 error) *PriceRegistryInterface_WatchReportPermissionSet_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_WatchReportPermissionSet_Call) RunAndReturn(run func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryReportPermissionSet, [][32]byte) (event.Subscription, error)) *PriceRegistryInterface_WatchReportPermissionSet_Call { - _c.Call.Return(run) - return _c -} - -// WatchTokenTransferFeeConfigDeleted provides a mock function with given fields: opts, sink, destChainSelector, token -func (_m *PriceRegistryInterface) WatchTokenTransferFeeConfigDeleted(opts *bind.WatchOpts, sink chan<- *price_registry.PriceRegistryTokenTransferFeeConfigDeleted, destChainSelector []uint64, token []common.Address) (event.Subscription, error) { - ret := _m.Called(opts, sink, destChainSelector, token) - - if len(ret) == 0 { - panic("no return value specified for WatchTokenTransferFeeConfigDeleted") - } - - var r0 event.Subscription - var r1 error - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryTokenTransferFeeConfigDeleted, []uint64, []common.Address) (event.Subscription, error)); ok { - return rf(opts, sink, destChainSelector, token) - } - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryTokenTransferFeeConfigDeleted, []uint64, []common.Address) event.Subscription); ok { - r0 = rf(opts, sink, destChainSelector, token) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(event.Subscription) - } - } - - if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryTokenTransferFeeConfigDeleted, []uint64, []common.Address) error); ok { - r1 = rf(opts, sink, destChainSelector, token) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_WatchTokenTransferFeeConfigDeleted_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchTokenTransferFeeConfigDeleted' -type PriceRegistryInterface_WatchTokenTransferFeeConfigDeleted_Call struct { - *mock.Call -} - -// WatchTokenTransferFeeConfigDeleted is a helper method to define mock.On call -// - opts *bind.WatchOpts -// - sink chan<- *price_registry.PriceRegistryTokenTransferFeeConfigDeleted -// - destChainSelector []uint64 -// - token []common.Address -func (_e *PriceRegistryInterface_Expecter) WatchTokenTransferFeeConfigDeleted(opts interface{}, sink interface{}, destChainSelector interface{}, token interface{}) *PriceRegistryInterface_WatchTokenTransferFeeConfigDeleted_Call { - return &PriceRegistryInterface_WatchTokenTransferFeeConfigDeleted_Call{Call: _e.mock.On("WatchTokenTransferFeeConfigDeleted", opts, sink, destChainSelector, token)} -} - -func (_c *PriceRegistryInterface_WatchTokenTransferFeeConfigDeleted_Call) Run(run func(opts *bind.WatchOpts, sink chan<- *price_registry.PriceRegistryTokenTransferFeeConfigDeleted, destChainSelector []uint64, token []common.Address)) *PriceRegistryInterface_WatchTokenTransferFeeConfigDeleted_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.WatchOpts), args[1].(chan<- *price_registry.PriceRegistryTokenTransferFeeConfigDeleted), args[2].([]uint64), args[3].([]common.Address)) - }) - return _c -} - -func (_c *PriceRegistryInterface_WatchTokenTransferFeeConfigDeleted_Call) Return(_a0 event.Subscription, _a1 error) *PriceRegistryInterface_WatchTokenTransferFeeConfigDeleted_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_WatchTokenTransferFeeConfigDeleted_Call) RunAndReturn(run func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryTokenTransferFeeConfigDeleted, []uint64, []common.Address) (event.Subscription, error)) *PriceRegistryInterface_WatchTokenTransferFeeConfigDeleted_Call { - _c.Call.Return(run) - return _c -} - -// WatchTokenTransferFeeConfigUpdated provides a mock function with given fields: opts, sink, destChainSelector, token -func (_m *PriceRegistryInterface) WatchTokenTransferFeeConfigUpdated(opts *bind.WatchOpts, sink chan<- *price_registry.PriceRegistryTokenTransferFeeConfigUpdated, destChainSelector []uint64, token []common.Address) (event.Subscription, error) { - ret := _m.Called(opts, sink, destChainSelector, token) - - if len(ret) == 0 { - panic("no return value specified for WatchTokenTransferFeeConfigUpdated") - } - - var r0 event.Subscription - var r1 error - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryTokenTransferFeeConfigUpdated, []uint64, []common.Address) (event.Subscription, error)); ok { - return rf(opts, sink, destChainSelector, token) - } - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryTokenTransferFeeConfigUpdated, []uint64, []common.Address) event.Subscription); ok { - r0 = rf(opts, sink, destChainSelector, token) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(event.Subscription) - } - } - - if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryTokenTransferFeeConfigUpdated, []uint64, []common.Address) error); ok { - r1 = rf(opts, sink, destChainSelector, token) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_WatchTokenTransferFeeConfigUpdated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchTokenTransferFeeConfigUpdated' -type PriceRegistryInterface_WatchTokenTransferFeeConfigUpdated_Call struct { - *mock.Call -} - -// WatchTokenTransferFeeConfigUpdated is a helper method to define mock.On call -// - opts *bind.WatchOpts -// - sink chan<- *price_registry.PriceRegistryTokenTransferFeeConfigUpdated -// - destChainSelector []uint64 -// - token []common.Address -func (_e *PriceRegistryInterface_Expecter) WatchTokenTransferFeeConfigUpdated(opts interface{}, sink interface{}, destChainSelector interface{}, token interface{}) *PriceRegistryInterface_WatchTokenTransferFeeConfigUpdated_Call { - return &PriceRegistryInterface_WatchTokenTransferFeeConfigUpdated_Call{Call: _e.mock.On("WatchTokenTransferFeeConfigUpdated", opts, sink, destChainSelector, token)} -} - -func (_c *PriceRegistryInterface_WatchTokenTransferFeeConfigUpdated_Call) Run(run func(opts *bind.WatchOpts, sink chan<- *price_registry.PriceRegistryTokenTransferFeeConfigUpdated, destChainSelector []uint64, token []common.Address)) *PriceRegistryInterface_WatchTokenTransferFeeConfigUpdated_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.WatchOpts), args[1].(chan<- *price_registry.PriceRegistryTokenTransferFeeConfigUpdated), args[2].([]uint64), args[3].([]common.Address)) - }) - return _c -} - -func (_c *PriceRegistryInterface_WatchTokenTransferFeeConfigUpdated_Call) Return(_a0 event.Subscription, _a1 error) *PriceRegistryInterface_WatchTokenTransferFeeConfigUpdated_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_WatchTokenTransferFeeConfigUpdated_Call) RunAndReturn(run func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryTokenTransferFeeConfigUpdated, []uint64, []common.Address) (event.Subscription, error)) *PriceRegistryInterface_WatchTokenTransferFeeConfigUpdated_Call { - _c.Call.Return(run) - return _c -} - -// WatchUsdPerTokenUpdated provides a mock function with given fields: opts, sink, token -func (_m *PriceRegistryInterface) WatchUsdPerTokenUpdated(opts *bind.WatchOpts, sink chan<- *price_registry.PriceRegistryUsdPerTokenUpdated, token []common.Address) (event.Subscription, error) { - ret := _m.Called(opts, sink, token) - - if len(ret) == 0 { - panic("no return value specified for WatchUsdPerTokenUpdated") - } - - var r0 event.Subscription - var r1 error - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryUsdPerTokenUpdated, []common.Address) (event.Subscription, error)); ok { - return rf(opts, sink, token) - } - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryUsdPerTokenUpdated, []common.Address) event.Subscription); ok { - r0 = rf(opts, sink, token) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(event.Subscription) - } - } - - if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryUsdPerTokenUpdated, []common.Address) error); ok { - r1 = rf(opts, sink, token) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_WatchUsdPerTokenUpdated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchUsdPerTokenUpdated' -type PriceRegistryInterface_WatchUsdPerTokenUpdated_Call struct { - *mock.Call -} - -// WatchUsdPerTokenUpdated is a helper method to define mock.On call -// - opts *bind.WatchOpts -// - sink chan<- *price_registry.PriceRegistryUsdPerTokenUpdated -// - token []common.Address -func (_e *PriceRegistryInterface_Expecter) WatchUsdPerTokenUpdated(opts interface{}, sink interface{}, token interface{}) *PriceRegistryInterface_WatchUsdPerTokenUpdated_Call { - return &PriceRegistryInterface_WatchUsdPerTokenUpdated_Call{Call: _e.mock.On("WatchUsdPerTokenUpdated", opts, sink, token)} -} - -func (_c *PriceRegistryInterface_WatchUsdPerTokenUpdated_Call) Run(run func(opts *bind.WatchOpts, sink chan<- *price_registry.PriceRegistryUsdPerTokenUpdated, token []common.Address)) *PriceRegistryInterface_WatchUsdPerTokenUpdated_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.WatchOpts), args[1].(chan<- *price_registry.PriceRegistryUsdPerTokenUpdated), args[2].([]common.Address)) - }) - return _c -} - -func (_c *PriceRegistryInterface_WatchUsdPerTokenUpdated_Call) Return(_a0 event.Subscription, _a1 error) *PriceRegistryInterface_WatchUsdPerTokenUpdated_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_WatchUsdPerTokenUpdated_Call) RunAndReturn(run func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryUsdPerTokenUpdated, []common.Address) (event.Subscription, error)) *PriceRegistryInterface_WatchUsdPerTokenUpdated_Call { - _c.Call.Return(run) - return _c -} - -// WatchUsdPerUnitGasUpdated provides a mock function with given fields: opts, sink, destChain -func (_m *PriceRegistryInterface) WatchUsdPerUnitGasUpdated(opts *bind.WatchOpts, sink chan<- *price_registry.PriceRegistryUsdPerUnitGasUpdated, destChain []uint64) (event.Subscription, error) { - ret := _m.Called(opts, sink, destChain) - - if len(ret) == 0 { - panic("no return value specified for WatchUsdPerUnitGasUpdated") - } - - var r0 event.Subscription - var r1 error - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryUsdPerUnitGasUpdated, []uint64) (event.Subscription, error)); ok { - return rf(opts, sink, destChain) - } - if rf, ok := ret.Get(0).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryUsdPerUnitGasUpdated, []uint64) event.Subscription); ok { - r0 = rf(opts, sink, destChain) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(event.Subscription) - } - } - - if rf, ok := ret.Get(1).(func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryUsdPerUnitGasUpdated, []uint64) error); ok { - r1 = rf(opts, sink, destChain) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// PriceRegistryInterface_WatchUsdPerUnitGasUpdated_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WatchUsdPerUnitGasUpdated' -type PriceRegistryInterface_WatchUsdPerUnitGasUpdated_Call struct { - *mock.Call -} - -// WatchUsdPerUnitGasUpdated is a helper method to define mock.On call -// - opts *bind.WatchOpts -// - sink chan<- *price_registry.PriceRegistryUsdPerUnitGasUpdated -// - destChain []uint64 -func (_e *PriceRegistryInterface_Expecter) WatchUsdPerUnitGasUpdated(opts interface{}, sink interface{}, destChain interface{}) *PriceRegistryInterface_WatchUsdPerUnitGasUpdated_Call { - return &PriceRegistryInterface_WatchUsdPerUnitGasUpdated_Call{Call: _e.mock.On("WatchUsdPerUnitGasUpdated", opts, sink, destChain)} -} - -func (_c *PriceRegistryInterface_WatchUsdPerUnitGasUpdated_Call) Run(run func(opts *bind.WatchOpts, sink chan<- *price_registry.PriceRegistryUsdPerUnitGasUpdated, destChain []uint64)) *PriceRegistryInterface_WatchUsdPerUnitGasUpdated_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.WatchOpts), args[1].(chan<- *price_registry.PriceRegistryUsdPerUnitGasUpdated), args[2].([]uint64)) - }) - return _c -} - -func (_c *PriceRegistryInterface_WatchUsdPerUnitGasUpdated_Call) Return(_a0 event.Subscription, _a1 error) *PriceRegistryInterface_WatchUsdPerUnitGasUpdated_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *PriceRegistryInterface_WatchUsdPerUnitGasUpdated_Call) RunAndReturn(run func(*bind.WatchOpts, chan<- *price_registry.PriceRegistryUsdPerUnitGasUpdated, []uint64) (event.Subscription, error)) *PriceRegistryInterface_WatchUsdPerUnitGasUpdated_Call { - _c.Call.Return(run) - return _c -} - -// NewPriceRegistryInterface creates a new instance of PriceRegistryInterface. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -// The first argument is typically a *testing.T value. -func NewPriceRegistryInterface(t interface { - mock.TestingT - Cleanup(func()) -}) *PriceRegistryInterface { - mock := &PriceRegistryInterface{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/core/scripts/ccip/revert-reason/handler/reason.go b/core/scripts/ccip/revert-reason/handler/reason.go index 2e41935ffa..7256b85856 100644 --- a/core/scripts/ccip/revert-reason/handler/reason.go +++ b/core/scripts/ccip/revert-reason/handler/reason.go @@ -19,12 +19,12 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/commit_store" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_offramp" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_onramp" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/fee_quoter" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/lock_release_token_pool" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/lock_release_token_pool_1_4_0" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/maybe_revert_message_receiver" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/offramp" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/onramp" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/price_registry" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_contract" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/token_admin_registry" @@ -144,7 +144,7 @@ func getAllABIs() []string { usdc_token_pool.USDCTokenPoolABI, commit_store.CommitStoreABI, token_admin_registry.TokenAdminRegistryABI, - price_registry.PriceRegistryABI, + fee_quoter.FeeQuoterABI, evm_2_evm_onramp.EVM2EVMOnRampABI, evm_2_evm_offramp.EVM2EVMOffRampABI, router.RouterABI, diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/test_helpers.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/test_helpers.go index e7972d5f5f..fb991be59d 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/test_helpers.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/test_helpers.go @@ -9,37 +9,37 @@ import ( "github.com/stretchr/testify/require" cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/fee_quoter" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/price_registry" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipcalc" ) // ApplyPriceRegistryUpdate is a helper function used in tests only. func ApplyPriceRegistryUpdate(t *testing.T, user *bind.TransactOpts, addr common.Address, ec client.Client, gasPrices []cciptypes.GasPrice, tokenPrices []cciptypes.TokenPrice) common.Hash { require.True(t, len(gasPrices) <= 2) - pr, err := price_registry.NewPriceRegistry(addr, ec) + pr, err := fee_quoter.NewFeeQuoter(addr, ec) require.NoError(t, err) o, err := pr.Owner(nil) require.NoError(t, err) require.Equal(t, user.From, o) - var tps []price_registry.InternalTokenPriceUpdate + var tps []fee_quoter.InternalTokenPriceUpdate for _, tp := range tokenPrices { evmAddrs, err1 := ccipcalc.GenericAddrsToEvm(tp.Token) assert.NoError(t, err1) - tps = append(tps, price_registry.InternalTokenPriceUpdate{ + tps = append(tps, fee_quoter.InternalTokenPriceUpdate{ SourceToken: evmAddrs[0], UsdPerToken: tp.Value, }) } - var gps []price_registry.InternalGasPriceUpdate + var gps []fee_quoter.InternalGasPriceUpdate for _, gp := range gasPrices { - gps = append(gps, price_registry.InternalGasPriceUpdate{ + gps = append(gps, fee_quoter.InternalGasPriceUpdate{ DestChainSelector: gp.DestChainSelector, UsdPerUnitGas: gp.Value, }) } - tx, err := pr.UpdatePrices(user, price_registry.InternalPriceUpdates{ + tx, err := pr.UpdatePrices(user, fee_quoter.InternalPriceUpdates{ TokenPriceUpdates: tps, GasPriceUpdates: gps, }) diff --git a/integration-tests/ccip-tests/actions/ccip_helpers.go b/integration-tests/ccip-tests/actions/ccip_helpers.go index 60d1800ab3..e878233d53 100644 --- a/integration-tests/ccip-tests/actions/ccip_helpers.go +++ b/integration-tests/ccip-tests/actions/ccip_helpers.go @@ -56,8 +56,8 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_offramp" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_onramp" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_onramp_1_2_0" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/fee_quoter" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/mock_rmn_contract" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/price_registry" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_contract" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/token_pool" @@ -528,8 +528,8 @@ func (ccipModule *CCIPCommon) WaitForPriceUpdates( // of price update events and add the event details to watchers. It subscribes to 'UsdPerUnitGasUpdated' // and 'UsdPerTokenUpdated' event. func (ccipModule *CCIPCommon) WatchForPriceUpdates(ctx context.Context, lggr *zerolog.Logger) error { - gasUpdateEventLatest := make(chan *price_registry.PriceRegistryUsdPerUnitGasUpdated) - tokenUpdateEvent := make(chan *price_registry.PriceRegistryUsdPerTokenUpdated) + gasUpdateEventLatest := make(chan *fee_quoter.FeeQuoterUsdPerUnitGasUpdated) + tokenUpdateEvent := make(chan *fee_quoter.FeeQuoterUsdPerTokenUpdated) sub := event.Resubscribe(DefaultResubscriptionTimeout, func(_ context.Context) (event.Subscription, error) { lggr.Info().Msg("Subscribing to UsdPerUnitGasUpdated event") eventSub, err := ccipModule.PriceRegistry.WatchUsdPerUnitGasUpdated(nil, gasUpdateEventLatest, nil) diff --git a/integration-tests/ccip-tests/contracts/contract_models.go b/integration-tests/ccip-tests/contracts/contract_models.go index 26794816dd..9b59ce4008 100644 --- a/integration-tests/ccip-tests/contracts/contract_models.go +++ b/integration-tests/ccip-tests/contracts/contract_models.go @@ -27,13 +27,13 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_offramp_1_2_0" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_onramp" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_onramp_1_2_0" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/fee_quoter" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/lock_release_token_pool" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/lock_release_token_pool_1_4_0" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/maybe_revert_message_receiver" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/mock_rmn_contract" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/mock_usdc_token_transmitter" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/mock_v3_aggregator_contract" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/price_registry" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/price_registry_1_2_0" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_contract" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" @@ -1111,7 +1111,7 @@ type PriceRegistryUsdPerUnitGasUpdated struct { } type PriceRegistryWrapper struct { - Latest *price_registry.PriceRegistry + Latest *fee_quoter.FeeQuoter V1_2_0 *price_registry_1_2_0.PriceRegistry } @@ -1137,7 +1137,7 @@ func (p *PriceRegistryWrapper) AddPriceUpdater(opts *bind.TransactOpts, addr com if p.Latest != nil { return p.Latest.ApplyAuthorizedCallerUpdates( opts, - price_registry.AuthorizedCallersAuthorizedCallerArgs{ + fee_quoter.AuthorizedCallersAuthorizedCallerArgs{ AddedCallers: []common.Address{addr}, RemovedCallers: []common.Address{}, }, @@ -1243,21 +1243,21 @@ func (c *PriceRegistry) UpdatePrices(tokenUpdates []InternalTokenPriceUpdate, ga } var tx *types.Transaction if c.Instance.Latest != nil { - var tokenUpdatesLatest []price_registry.InternalTokenPriceUpdate - var gasUpdatesLatest []price_registry.InternalGasPriceUpdate + var tokenUpdatesLatest []fee_quoter.InternalTokenPriceUpdate + var gasUpdatesLatest []fee_quoter.InternalGasPriceUpdate for _, update := range tokenUpdates { - tokenUpdatesLatest = append(tokenUpdatesLatest, price_registry.InternalTokenPriceUpdate{ + tokenUpdatesLatest = append(tokenUpdatesLatest, fee_quoter.InternalTokenPriceUpdate{ SourceToken: update.SourceToken, UsdPerToken: update.UsdPerToken, }) } for _, update := range gasUpdates { - gasUpdatesLatest = append(gasUpdatesLatest, price_registry.InternalGasPriceUpdate{ + gasUpdatesLatest = append(gasUpdatesLatest, fee_quoter.InternalGasPriceUpdate{ DestChainSelector: update.DestChainSelector, UsdPerUnitGas: update.UsdPerUnitGas, }) } - tx, err = c.Instance.Latest.UpdatePrices(opts, price_registry.InternalPriceUpdates{ + tx, err = c.Instance.Latest.UpdatePrices(opts, fee_quoter.InternalPriceUpdates{ TokenPriceUpdates: tokenUpdatesLatest, GasPriceUpdates: gasUpdatesLatest, }) @@ -1299,12 +1299,12 @@ func (c *PriceRegistry) UpdatePrices(tokenUpdates []InternalTokenPriceUpdate, ga return c.client.ProcessTransaction(tx) } -func (c *PriceRegistry) WatchUsdPerUnitGasUpdated(opts *bind.WatchOpts, latest chan *price_registry.PriceRegistryUsdPerUnitGasUpdated, destChain []uint64) (event.Subscription, error) { +func (c *PriceRegistry) WatchUsdPerUnitGasUpdated(opts *bind.WatchOpts, latest chan *fee_quoter.FeeQuoterUsdPerUnitGasUpdated, destChain []uint64) (event.Subscription, error) { if c.Instance.Latest != nil { return c.Instance.Latest.WatchUsdPerUnitGasUpdated(opts, latest, destChain) } if c.Instance.V1_2_0 != nil { - newP, err := price_registry.NewPriceRegistry(c.Instance.V1_2_0.Address(), wrappers.MustNewWrappedContractBackend(c.client, nil)) + newP, err := fee_quoter.NewFeeQuoter(c.Instance.V1_2_0.Address(), wrappers.MustNewWrappedContractBackend(c.client, nil)) if err != nil { return nil, fmt.Errorf("failed to create new PriceRegistry contract: %w", err) } @@ -1313,12 +1313,12 @@ func (c *PriceRegistry) WatchUsdPerUnitGasUpdated(opts *bind.WatchOpts, latest c return nil, fmt.Errorf("no instance found to watch for price updates for gas") } -func (c *PriceRegistry) WatchUsdPerTokenUpdated(opts *bind.WatchOpts, latest chan *price_registry.PriceRegistryUsdPerTokenUpdated) (event.Subscription, error) { +func (c *PriceRegistry) WatchUsdPerTokenUpdated(opts *bind.WatchOpts, latest chan *fee_quoter.FeeQuoterUsdPerTokenUpdated) (event.Subscription, error) { if c.Instance.Latest != nil { return c.Instance.Latest.WatchUsdPerTokenUpdated(opts, latest, nil) } if c.Instance.V1_2_0 != nil { - newP, err := price_registry.NewPriceRegistry(c.Instance.V1_2_0.Address(), wrappers.MustNewWrappedContractBackend(c.client, nil)) + newP, err := fee_quoter.NewFeeQuoter(c.Instance.V1_2_0.Address(), wrappers.MustNewWrappedContractBackend(c.client, nil)) if err != nil { return nil, fmt.Errorf("failed to create new PriceRegistry contract: %w", err) } diff --git a/integration-tests/deployment/ccip/add_lane.go b/integration-tests/deployment/ccip/add_lane.go index 1f8dcd43f9..16384e0aba 100644 --- a/integration-tests/deployment/ccip/add_lane.go +++ b/integration-tests/deployment/ccip/add_lane.go @@ -7,10 +7,9 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/smartcontractkit/chainlink/integration-tests/deployment" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/fee_quoter" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/offramp" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/onramp" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/price_registry" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" ) @@ -37,8 +36,8 @@ func AddLane(e deployment.Environment, state CCIPOnChainState, from, to uint64) } _, err = state.Chains[from].PriceRegistry.UpdatePrices( - e.Chains[from].DeployerKey, price_registry.InternalPriceUpdates{ - TokenPriceUpdates: []price_registry.InternalTokenPriceUpdate{ + e.Chains[from].DeployerKey, fee_quoter.InternalPriceUpdates{ + TokenPriceUpdates: []fee_quoter.InternalTokenPriceUpdate{ { SourceToken: state.Chains[from].LinkToken.Address(), UsdPerToken: deployment.E18Mult(20), @@ -48,7 +47,7 @@ func AddLane(e deployment.Environment, state CCIPOnChainState, from, to uint64) UsdPerToken: deployment.E18Mult(4000), }, }, - GasPriceUpdates: []price_registry.InternalGasPriceUpdate{ + GasPriceUpdates: []fee_quoter.InternalGasPriceUpdate{ { DestChainSelector: to, UsdPerUnitGas: big.NewInt(2e12), @@ -60,7 +59,7 @@ func AddLane(e deployment.Environment, state CCIPOnChainState, from, to uint64) // Enable dest in price registry tx, err = state.Chains[from].PriceRegistry.ApplyDestChainConfigUpdates(e.Chains[from].DeployerKey, - []price_registry.PriceRegistryDestChainConfigArgs{ + []fee_quoter.FeeQuoterDestChainConfigArgs{ { DestChainSelector: to, DestChainConfig: defaultPriceRegistryDestChainConfig(), @@ -91,7 +90,7 @@ func AddLane(e deployment.Environment, state CCIPOnChainState, from, to uint64) return deployment.ConfirmIfNoError(e.Chains[to], tx, err) } -func defaultPriceRegistryDestChainConfig() price_registry.PriceRegistryDestChainConfig { +func defaultPriceRegistryDestChainConfig() fee_quoter.FeeQuoterDestChainConfig { // https://github.com/smartcontractkit/ccip/blob/c4856b64bd766f1ddbaf5d13b42d3c4b12efde3a/contracts/src/v0.8/ccip/libraries/Internal.sol#L337-L337 /* ```Solidity @@ -100,7 +99,7 @@ func defaultPriceRegistryDestChainConfig() price_registry.PriceRegistryDestChain ``` */ evmFamilySelector, _ := hex.DecodeString("2812d52c") - return price_registry.PriceRegistryDestChainConfig{ + return fee_quoter.FeeQuoterDestChainConfig{ IsEnabled: true, MaxNumberOfTokensPerMsg: 10, MaxDataBytes: 256, diff --git a/integration-tests/deployment/ccip/deploy.go b/integration-tests/deployment/ccip/deploy.go index 0b6aa5a646..ff589d1430 100644 --- a/integration-tests/deployment/ccip/deploy.go +++ b/integration-tests/deployment/ccip/deploy.go @@ -9,17 +9,16 @@ import ( "github.com/ethereum/go-ethereum/core/types" owner_helpers "github.com/smartcontractkit/ccip-owner-contracts/gethwrappers" + "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink/integration-tests/deployment" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/ccip_config" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/fee_quoter" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/maybe_revert_message_receiver" - - "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/mock_rmn_contract" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/nonce_manager" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/offramp" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/onramp" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/price_registry" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_proxy_contract" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/token_admin_registry" @@ -51,7 +50,7 @@ type Contracts interface { *rmn_proxy_contract.RMNProxyContract | *ccip_config.CCIPConfig | *nonce_manager.NonceManager | - *price_registry.PriceRegistry | + *fee_quoter.FeeQuoter | *router.Router | *token_admin_registry.TokenAdminRegistry | *weth9.WETH9 | @@ -154,7 +153,7 @@ func DeployCCIPContracts(e deployment.Environment, c DeployCCIPContractConfig) ( return ab, err } // Enable ramps on price registry/nonce manager - tx, err := chainState.PriceRegistry.ApplyAuthorizedCallerUpdates(chain.DeployerKey, price_registry.AuthorizedCallersAuthorizedCallerArgs{ + tx, err := chainState.PriceRegistry.ApplyAuthorizedCallerUpdates(chain.DeployerKey, fee_quoter.AuthorizedCallersAuthorizedCallerArgs{ // TODO: We enable the deployer initially to set prices AddedCallers: []common.Address{chainState.EvmOffRampV160.Address(), chain.DeployerKey.From}, }) @@ -377,21 +376,21 @@ func DeployChainContracts(e deployment.Environment, chain deployment.Chain, ab d return ab, err } - priceRegistry, err := deployContract(e.Logger, chain, ab, - func(chain deployment.Chain) ContractDeploy[*price_registry.PriceRegistry] { - prAddr, tx, pr, err2 := price_registry.DeployPriceRegistry( + feeQuoter, err := deployContract(e.Logger, chain, ab, + func(chain deployment.Chain) ContractDeploy[*fee_quoter.FeeQuoter] { + prAddr, tx, pr, err2 := fee_quoter.DeployFeeQuoter( chain.DeployerKey, chain.Client, - price_registry.PriceRegistryStaticConfig{ + fee_quoter.FeeQuoterStaticConfig{ MaxFeeJuelsPerMsg: big.NewInt(0).Mul(big.NewInt(2e2), big.NewInt(1e18)), LinkToken: linkToken.Address, StalenessThreshold: uint32(24 * 60 * 60), }, []common.Address{}, // ramps added after []common.Address{weth9.Address, linkToken.Address}, // fee tokens - []price_registry.PriceRegistryTokenPriceFeedUpdate{}, - []price_registry.PriceRegistryTokenTransferFeeConfigArgs{}, // TODO: tokens - []price_registry.PriceRegistryPremiumMultiplierWeiPerEthArgs{ + []fee_quoter.FeeQuoterTokenPriceFeedUpdate{}, + []fee_quoter.FeeQuoterTokenTransferFeeConfigArgs{}, // TODO: tokens + []fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthArgs{ { PremiumMultiplierWeiPerEth: 9e17, // 0.9 ETH Token: linkToken.Address, @@ -401,9 +400,9 @@ func DeployChainContracts(e deployment.Environment, chain deployment.Chain, ab d Token: weth9.Address, }, }, - []price_registry.PriceRegistryDestChainConfigArgs{}, + []fee_quoter.FeeQuoterDestChainConfigArgs{}, ) - return ContractDeploy[*price_registry.PriceRegistry]{ + return ContractDeploy[*fee_quoter.FeeQuoter]{ prAddr, pr, tx, deployment.NewTypeAndVersion(PriceRegistry, deployment.Version1_6_0_dev), err2, } }) @@ -424,7 +423,7 @@ func DeployChainContracts(e deployment.Environment, chain deployment.Chain, ab d TokenAdminRegistry: tokenAdminRegistry.Address, }, onramp.OnRampDynamicConfig{ - PriceRegistry: priceRegistry.Address, + FeeQuoter: feeQuoter.Address, FeeAggregator: common.HexToAddress("0x1"), // TODO real fee aggregator }, []onramp.OnRampDestChainConfigArgs{}, @@ -451,7 +450,7 @@ func DeployChainContracts(e deployment.Environment, chain deployment.Chain, ab d TokenAdminRegistry: tokenAdminRegistry.Address, }, offramp.OffRampDynamicConfig{ - PriceRegistry: priceRegistry.Address, + FeeQuoter: feeQuoter.Address, PermissionLessExecutionThresholdSeconds: uint32(86400), MaxTokenTransferGas: uint32(200_000), MaxPoolReleaseOrMintGas: uint32(200_000), diff --git a/integration-tests/deployment/ccip/state.go b/integration-tests/deployment/ccip/state.go index e9015dbfdc..f641d30ed4 100644 --- a/integration-tests/deployment/ccip/state.go +++ b/integration-tests/deployment/ccip/state.go @@ -7,29 +7,29 @@ import ( "github.com/pkg/errors" chainsel "github.com/smartcontractkit/chain-selectors" + owner_wrappers "github.com/smartcontractkit/ccip-owner-contracts/gethwrappers" + "github.com/smartcontractkit/chainlink/integration-tests/deployment" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/ccip_config" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/fee_quoter" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/maybe_revert_message_receiver" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/burn_mint_erc677" - - owner_wrappers "github.com/smartcontractkit/ccip-owner-contracts/gethwrappers" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/mock_rmn_contract" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/nonce_manager" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/offramp" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/onramp" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/price_registry" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_proxy_contract" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/token_admin_registry" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/weth9" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/burn_mint_erc677" ) type CCIPChainState struct { EvmOnRampV160 *onramp.OnRamp EvmOffRampV160 *offramp.OffRamp - PriceRegistry *price_registry.PriceRegistry + PriceRegistry *fee_quoter.FeeQuoter ArmProxy *rmn_proxy_contract.RMNProxyContract NonceManager *nonce_manager.NonceManager TokenAdminRegistry *token_admin_registry.TokenAdminRegistry @@ -245,7 +245,7 @@ func LoadChainState(chain deployment.Chain, addresses map[string]deployment.Type } state.Router = r case deployment.NewTypeAndVersion(PriceRegistry, deployment.Version1_6_0_dev).String(): - pr, err := price_registry.NewPriceRegistry(common.HexToAddress(address), chain.Client) + pr, err := fee_quoter.NewFeeQuoter(common.HexToAddress(address), chain.Client) if err != nil { return state, err } From 1652400e333a049984c3114dc10f5c871fe8911d Mon Sep 17 00:00:00 2001 From: amaechiokolobi <168412367+amaechiokolobi@users.noreply.github.com> Date: Tue, 27 Aug 2024 15:33:10 +0100 Subject: [PATCH 035/115] added custom treasure fatal error (#1354) ## Motivation ## Solution --- core/chains/evm/client/errors.go | 8 +++++++- core/chains/evm/client/errors_test.go | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/core/chains/evm/client/errors.go b/core/chains/evm/client/errors.go index e7fff8d0db..5980b0dd96 100644 --- a/core/chains/evm/client/errors.go +++ b/core/chains/evm/client/errors.go @@ -161,6 +161,12 @@ var arbitrum = ClientErrors{ ServiceUnavailable: regexp.MustCompile(`(: |^)502 Bad Gateway: [\s\S]*$|network is unreachable|i/o timeout`), } +// Treasure +var treasureFatal = regexp.MustCompile(`(: |^)invalid chain id for signer(:|$)`) +var treasure = ClientErrors{ + Fatal: treasureFatal, +} + var celo = ClientErrors{ TxFeeExceedsCap: regexp.MustCompile(`(: |^)tx fee \([0-9\.]+ of currency celo\) exceeds the configured cap \([0-9\.]+ [a-zA-Z]+\)$`), TerminallyUnderpriced: regexp.MustCompile(`(: |^)gasprice is less than gas price minimum floor`), @@ -270,7 +276,7 @@ var internal = ClientErrors{ TerminallyStuck: regexp.MustCompile(TerminallyStuckMsg), } -var clients = []ClientErrors{parity, geth, arbitrum, metis, substrate, avalanche, nethermind, harmony, besu, erigon, klaytn, celo, zkSync, zkEvm, mantle, aStar, gnosis, internal} +var clients = []ClientErrors{parity, geth, arbitrum, metis, substrate, avalanche, nethermind, harmony, besu, erigon, klaytn, celo, zkSync, zkEvm, treasure, mantle, aStar, gnosis, internal} // ClientErrorRegexes returns a map of compiled regexes for each error type func ClientErrorRegexes(errsRegex config.ClientErrors) *ClientErrors { diff --git a/core/chains/evm/client/errors_test.go b/core/chains/evm/client/errors_test.go index bddc7dd3db..47e8ee610b 100644 --- a/core/chains/evm/client/errors_test.go +++ b/core/chains/evm/client/errors_test.go @@ -401,6 +401,7 @@ func Test_Eth_Errors_Fatal(t *testing.T) { {"Failed to serialize transaction: oversized data. max: 1000000; actual: 1000000", true, "zkSync"}, {"client error fatal", true, "tomlConfig"}, + {"invalid chain id for signer", true, "Treasure"}, } for _, test := range tests { From bc7e5a220fe1e7a5c8c8444592db0b0f365ec880 Mon Sep 17 00:00:00 2001 From: Anirudh Warrier <12178754+anirudhwarrier@users.noreply.github.com> Date: Tue, 27 Aug 2024 20:07:32 +0400 Subject: [PATCH 036/115] fix client comp workflow - image name (#1374) ## Motivation CCIP Compatibility Test failing on CI ## Solution Fix incorrect ECR repo name in github workflow --- .github/workflows/ccip-client-compatibility-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ccip-client-compatibility-tests.yml b/.github/workflows/ccip-client-compatibility-tests.yml index 42daf280ca..0d485057c2 100644 --- a/.github/workflows/ccip-client-compatibility-tests.yml +++ b/.github/workflows/ccip-client-compatibility-tests.yml @@ -29,7 +29,7 @@ on: type: string env: - CHAINLINK_IMAGE: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/ccip + CHAINLINK_IMAGE: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink INTERNAL_DOCKER_REPO: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com MOD_CACHE_VERSION: 2 From b8dcb90b9343a374797af17000de378ddb62d376 Mon Sep 17 00:00:00 2001 From: Makram Date: Tue, 27 Aug 2024 20:44:05 +0300 Subject: [PATCH 037/115] core/capabilities/ccip: update ccipreader test (#1373) ## Motivation We want to add a test for GetExpectedNextSequenceNumber in ccipreader_test.go Related PR: https://github.com/smartcontractkit/chainlink-ccip/pull/81 ## Solution Add a test for GetExpectedNextSequenceNumber in ccipreader_test.go --- .../ccip/test/helpers/CCIPReaderTester.sol | 15 +++++++ .../ccipreader/ccipreader_test.go | 36 ++++++++++++++++ .../ccip_reader_tester/ccip_reader_tester.go | 42 ++++++++++++++++++- ...rapper-dependency-versions-do-not-edit.txt | 2 +- core/scripts/go.mod | 2 +- core/scripts/go.sum | 4 +- go.mod | 2 +- go.sum | 4 +- integration-tests/go.mod | 2 +- integration-tests/go.sum | 4 +- integration-tests/load/go.mod | 2 +- integration-tests/load/go.sum | 4 +- 12 files changed, 104 insertions(+), 15 deletions(-) diff --git a/contracts/src/v0.8/ccip/test/helpers/CCIPReaderTester.sol b/contracts/src/v0.8/ccip/test/helpers/CCIPReaderTester.sol index 707d38ddf2..c2acddc796 100644 --- a/contracts/src/v0.8/ccip/test/helpers/CCIPReaderTester.sol +++ b/contracts/src/v0.8/ccip/test/helpers/CCIPReaderTester.sol @@ -8,6 +8,21 @@ contract CCIPReaderTester { event CCIPSendRequested(uint64 indexed destChainSelector, Internal.EVM2AnyRampMessage message); mapping(uint64 sourceChainSelector => OffRamp.SourceChainConfig sourceChainConfig) internal s_sourceChainConfigs; + mapping(uint64 destChainSelector => uint64 sequenceNumber) internal s_destChainSeqNrs; + + /// @notice Gets the next sequence number to be used in the onRamp + /// @param destChainSelector The destination chain selector + /// @return nextSequenceNumber The next sequence number to be used + function getExpectedNextSequenceNumber(uint64 destChainSelector) external view returns (uint64) { + return s_destChainSeqNrs[destChainSelector] + 1; + } + + /// @notice Sets the sequence number in the onRamp + /// @param destChainSelector The destination chain selector + /// @param sequenceNumber The sequence number + function setDestChainSeqNr(uint64 destChainSelector, uint64 sequenceNumber) external { + s_destChainSeqNrs[destChainSelector] = sequenceNumber; + } function getSourceChainConfig(uint64 sourceChainSelector) external view returns (OffRamp.SourceChainConfig memory) { return s_sourceChainConfigs[sourceChainSelector]; diff --git a/core/capabilities/ccip/ccip_integration_tests/ccipreader/ccipreader_test.go b/core/capabilities/ccip/ccip_integration_tests/ccipreader/ccipreader_test.go index a179949d93..ed5fe1aedb 100644 --- a/core/capabilities/ccip/ccip_integration_tests/ccipreader/ccipreader_test.go +++ b/core/capabilities/ccip/ccip_integration_tests/ccipreader/ccipreader_test.go @@ -316,6 +316,42 @@ func TestCCIPReader_NextSeqNum(t *testing.T) { assert.Equal(t, cciptypes.SeqNum(30), seqNums[2]) } +func TestCCIPReader_GetExpectedNextSequenceNumber(t *testing.T) { + ctx := testutils.Context(t) + + cfg := evmtypes.ChainReaderConfig{ + Contracts: map[string]evmtypes.ChainContractReader{ + consts.ContractNameOnRamp: { + ContractABI: ccip_reader_tester.CCIPReaderTesterABI, + Configs: map[string]*evmtypes.ChainReaderDefinition{ + consts.MethodNameGetExpectedNextSequenceNumber: { + ChainSpecificName: "getExpectedNextSequenceNumber", + ReadType: evmtypes.Method, + }, + }, + }, + }, + } + + s := testSetup(ctx, t, chainS1, chainD, nil, cfg) + + _, err := s.contract.SetDestChainSeqNr(s.auth, uint64(chainD), 10) + require.NoError(t, err) + s.sb.Commit() + + seqNum, err := s.reader.GetExpectedNextSequenceNumber(ctx, chainS1, chainD) + require.NoError(t, err) + require.Equal(t, cciptypes.SeqNum(10)+1, seqNum) + + _, err = s.contract.SetDestChainSeqNr(s.auth, uint64(chainD), 25) + require.NoError(t, err) + s.sb.Commit() + + seqNum, err = s.reader.GetExpectedNextSequenceNumber(ctx, chainS1, chainD) + require.NoError(t, err) + require.Equal(t, cciptypes.SeqNum(25)+1, seqNum) +} + func testSetup(ctx context.Context, t *testing.T, readerChain, destChain cciptypes.ChainSelector, onChainSeqNums map[cciptypes.ChainSelector]cciptypes.SeqNum, cfg evmtypes.ChainReaderConfig) *testSetupData { const chainID = 1337 diff --git a/core/gethwrappers/ccip/generated/ccip_reader_tester/ccip_reader_tester.go b/core/gethwrappers/ccip/generated/ccip_reader_tester/ccip_reader_tester.go index 915a045c10..cce56e0d80 100644 --- a/core/gethwrappers/ccip/generated/ccip_reader_tester/ccip_reader_tester.go +++ b/core/gethwrappers/ccip/generated/ccip_reader_tester/ccip_reader_tester.go @@ -96,8 +96,8 @@ type OffRampSourceChainConfig struct { } var CCIPReaderTesterMetaData = &bind.MetaData{ - ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"CCIPSendRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"internalType\":\"structOffRamp.Interval\",\"name\":\"interval\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structOffRamp.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"report\",\"type\":\"tuple\"}],\"name\":\"CommitReportAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"name\":\"ExecutionStateChanged\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"emitCCIPSendRequested\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"internalType\":\"structOffRamp.Interval\",\"name\":\"interval\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structOffRamp.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"}],\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"report\",\"type\":\"tuple\"}],\"name\":\"emitCommitReportAccepted\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"name\":\"emitExecutionStateChanged\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"getSourceChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"sourceChainConfig\",\"type\":\"tuple\"}],\"name\":\"setSourceChainConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x608060405234801561001057600080fd5b5061118d806100206000396000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c80634cf66e361461005c57806385096da914610071578063e44302b714610084578063e83eabba14610097578063e9d68a8e146100aa575b600080fd5b61006f61006a3660046104c9565b6100d3565b005b61006f61007f366004610741565b610128565b61006f6100923660046109df565b61016d565b61006f6100a5366004610b49565b6101a7565b6100bd6100b8366004610c04565b610233565b6040516100ca9190610c6c565b60405180910390f35b82846001600160401b0316866001600160401b03167f8c324ce1367b83031769f6a813e3bb4c117aba2185789d66b98b791405be6df28585604051610119929190610cc4565b60405180910390a45050505050565b816001600160401b03167fcae3d9f68a9ed33d0a770e9bcc6fc25d4041dd6391e6cd8015546547a3c93140826040516101619190610dc7565b60405180910390a25050565b7f3a3950e13dd607cc37980db0ef14266c40d2bba9c01b2e44bfe549808883095d8160405161019c9190610f81565b60405180910390a150565b6001600160401b0380831660009081526020818152604091829020845181549286015193860151909416600160a81b02600160a81b600160e81b0319931515600160a01b026001600160a81b03199093166001600160a01b039095169490941791909117919091169190911781556060820151829190600182019061022c90826110c1565b5050505050565b60408051608080820183526000808352602080840182905283850182905260608085018190526001600160401b038781168452838352928690208651948501875280546001600160a01b0381168652600160a01b810460ff16151593860193909352600160a81b9092049092169483019490945260018401805493949293918401916102be90611036565b80601f01602080910402602001604051908101604052809291908181526020018280546102ea90611036565b80156103375780601f1061030c57610100808354040283529160200191610337565b820191906000526020600020905b81548152906001019060200180831161031a57829003601f168201915b5050505050815250509050919050565b80356001600160401b038116811461035e57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60405160a081016001600160401b038111828210171561039b5761039b610363565b60405290565b60405161010081016001600160401b038111828210171561039b5761039b610363565b604080519081016001600160401b038111828210171561039b5761039b610363565b604051606081016001600160401b038111828210171561039b5761039b610363565b604051608081016001600160401b038111828210171561039b5761039b610363565b604051601f8201601f191681016001600160401b038111828210171561045257610452610363565b604052919050565b600082601f83011261046b57600080fd5b81356001600160401b0381111561048457610484610363565b610497601f8201601f191660200161042a565b8181528460208386010111156104ac57600080fd5b816020850160208301376000918101602001919091529392505050565b600080600080600060a086880312156104e157600080fd5b6104ea86610347565b94506104f860208701610347565b93506040860135925060608601356004811061051357600080fd5b915060808601356001600160401b0381111561052e57600080fd5b61053a8882890161045a565b9150509295509295909350565b600060a0828403121561055957600080fd5b610561610379565b90508135815261057360208301610347565b602082015261058460408301610347565b604082015261059560608301610347565b60608201526105a660808301610347565b608082015292915050565b6001600160a01b03811681146105c657600080fd5b50565b803561035e816105b1565b60006001600160401b038211156105ed576105ed610363565b5060051b60200190565b600082601f83011261060857600080fd5b8135602061061d610618836105d4565b61042a565b82815260059290921b8401810191818101908684111561063c57600080fd5b8286015b848110156107365780356001600160401b03808211156106605760008081fd5b9088019060a0828b03601f190181131561067a5760008081fd5b610682610379565b87840135838111156106945760008081fd5b6106a28d8a8388010161045a565b825250604080850135848111156106b95760008081fd5b6106c78e8b8389010161045a565b8a84015250606080860135858111156106e05760008081fd5b6106ee8f8c838a010161045a565b838501525060809150818601358184015250828501359250838311156107145760008081fd5b6107228d8a8588010161045a565b908201528652505050918301918301610640565b509695505050505050565b6000806040838503121561075457600080fd5b61075d83610347565b915060208301356001600160401b038082111561077957600080fd5b90840190610180828703121561078e57600080fd5b6107966103a1565b6107a08784610547565b81526107ae60a084016105c9565b602082015260c0830135828111156107c557600080fd5b6107d18882860161045a565b60408301525060e0830135828111156107e957600080fd5b6107f58882860161045a565b6060830152506101008301358281111561080e57600080fd5b61081a8882860161045a565b60808301525061082d61012084016105c9565b60a082015261014083013560c08201526101608301358281111561085057600080fd5b61085c888286016105f7565b60e0830152508093505050509250929050565b80356001600160e01b038116811461035e57600080fd5b600082601f83011261089757600080fd5b813560206108a7610618836105d4565b82815260069290921b840181019181810190868411156108c657600080fd5b8286015b8481101561073657604081890312156108e35760008081fd5b6108eb6103c4565b6108f482610347565b815261090185830161086f565b818601528352918301916040016108ca565b600082601f83011261092457600080fd5b81356020610934610618836105d4565b82815260079290921b8401810191818101908684111561095357600080fd5b8286015b848110156107365780880360808112156109715760008081fd5b6109796103e6565b61098283610347565b8152604080601f19840112156109985760008081fd5b6109a06103c4565b92506109ad878501610347565b83526109ba818501610347565b8388015281870192909252606083013591810191909152835291830191608001610957565b600060208083850312156109f257600080fd5b82356001600160401b0380821115610a0957600080fd5b81850191506040808388031215610a1f57600080fd5b610a276103c4565b833583811115610a3657600080fd5b84016040818a031215610a4857600080fd5b610a506103c4565b813585811115610a5f57600080fd5b8201601f81018b13610a7057600080fd5b8035610a7e610618826105d4565b81815260069190911b8201890190898101908d831115610a9d57600080fd5b928a01925b82841015610aed5787848f031215610aba5760008081fd5b610ac26103c4565b8435610acd816105b1565b8152610ada858d0161086f565b818d0152825292870192908a0190610aa2565b845250505081870135935084841115610b0557600080fd5b610b118a858401610886565b8188015282525083850135915082821115610b2b57600080fd5b610b3788838601610913565b85820152809550505050505092915050565b60008060408385031215610b5c57600080fd5b610b6583610347565b915060208301356001600160401b0380821115610b8157600080fd5b9084019060808287031215610b9557600080fd5b610b9d610408565b8235610ba8816105b1565b815260208301358015158114610bbd57600080fd5b6020820152610bce60408401610347565b6040820152606083013582811115610be557600080fd5b610bf18882860161045a565b6060830152508093505050509250929050565b600060208284031215610c1657600080fd5b610c1f82610347565b9392505050565b6000815180845260005b81811015610c4c57602081850181015186830182015201610c30565b506000602082860101526020601f19601f83011685010191505092915050565b602080825282516001600160a01b03168282015282015115156040808301919091528201516001600160401b0316606080830191909152820151608080830152600090610cbc60a0840182610c26565b949350505050565b600060048410610ce457634e487b7160e01b600052602160045260246000fd5b83825260406020830152610cbc6040830184610c26565b6001600160a01b03169052565b600082825180855260208086019550808260051b84010181860160005b84811015610dba57601f19868403018952815160a08151818652610d4b82870182610c26565b9150508582015185820387870152610d638282610c26565b91505060408083015186830382880152610d7d8382610c26565b92505050606080830151818701525060808083015192508582038187015250610da68183610c26565b9a86019a9450505090830190600101610d25565b5090979650505050505050565b60208152610e14602082018351805182526020808201516001600160401b039081169184019190915260408083015182169084015260608083015182169084015260809182015116910152565b60006020830151610e2860c0840182610cfb565b5060408301516101808060e0850152610e456101a0850183610c26565b91506060850151601f198086850301610100870152610e648483610c26565b9350608087015191508086850301610120870152610e828483610c26565b935060a08701519150610e99610140870183610cfb565b60c087015161016087015260e0870151915080868503018387015250610ebf8382610d08565b9695505050505050565b60008151808452602080850194506020840160005b83811015610f1757815180516001600160401b031688528301516001600160e01b03168388015260409096019590820190600101610ede565b509495945050505050565b600081518084526020808501945080840160005b83811015610f1757815180516001600160401b0390811689528482015180518216868b0152850151166040898101919091520151606088015260809096019590820190600101610f36565b6000602080835283516040808386015260a0850182516040606088015281815180845260c0890191508683019350600092505b80831015610fef57835180516001600160a01b031683528701516001600160e01b031687830152928601926001929092019190840190610fb4565b5093850151878503605f190160808901529361100b8186610ec9565b945050505050818501519150601f1984820301604085015261102d8183610f22565b95945050505050565b600181811c9082168061104a57607f821691505b60208210810361106a57634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156110bc576000816000526020600020601f850160051c810160208610156110995750805b601f850160051c820191505b818110156110b8578281556001016110a5565b5050505b505050565b81516001600160401b038111156110da576110da610363565b6110ee816110e88454611036565b84611070565b602080601f831160018114611123576000841561110b5750858301515b600019600386901b1c1916600185901b1785556110b8565b600085815260208120601f198616915b8281101561115257888601518255948401946001909101908401611133565b50858210156111705787850151600019600388901b60f8161c191681555b5050505050600190811b0190555056fea164736f6c6343000818000a", + ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"CCIPSendRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"internalType\":\"structOffRamp.Interval\",\"name\":\"interval\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structOffRamp.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"report\",\"type\":\"tuple\"}],\"name\":\"CommitReportAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"name\":\"ExecutionStateChanged\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"emitCCIPSendRequested\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"internalType\":\"structOffRamp.Interval\",\"name\":\"interval\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structOffRamp.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"}],\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"report\",\"type\":\"tuple\"}],\"name\":\"emitCommitReportAccepted\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"name\":\"emitExecutionStateChanged\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getExpectedNextSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"getSourceChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"setDestChainSeqNr\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"sourceChainConfig\",\"type\":\"tuple\"}],\"name\":\"setSourceChainConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x608060405234801561001057600080fd5b5061129d806100206000396000f3fe608060405234801561001057600080fd5b506004361061006d5760003560e01c80634cf66e361461007257806385096da9146100875780639041be3d1461009a578063c1a5a355146100ca578063e44302b714610106578063e83eabba14610119578063e9d68a8e1461012c575b600080fd5b610085610080366004610571565b61014c565b005b6100856100953660046107e9565b6101a1565b6100ad6100a8366004610917565b6101e6565b6040516001600160401b0390911681526020015b60405180910390f35b6100856100d8366004610939565b6001600160401b03918216600090815260016020526040902080546001600160401b03191691909216179055565b610085610114366004610adc565b610215565b610085610127366004610c46565b61024f565b61013f61013a366004610917565b6102db565b6040516100c19190610d47565b82846001600160401b0316866001600160401b03167f8c324ce1367b83031769f6a813e3bb4c117aba2185789d66b98b791405be6df28585604051610192929190610d9f565b60405180910390a45050505050565b816001600160401b03167fcae3d9f68a9ed33d0a770e9bcc6fc25d4041dd6391e6cd8015546547a3c93140826040516101da9190610ea2565b60405180910390a25050565b6001600160401b038082166000908152600160208190526040822054919261020f921690610fa4565b92915050565b7f3a3950e13dd607cc37980db0ef14266c40d2bba9c01b2e44bfe549808883095d816040516102449190611091565b60405180910390a150565b6001600160401b0380831660009081526020818152604091829020845181549286015193860151909416600160a81b02600160a81b600160e81b0319931515600160a01b026001600160a81b03199093166001600160a01b03909516949094179190911791909116919091178155606082015182919060018201906102d490826111d1565b5050505050565b60408051608080820183526000808352602080840182905283850182905260608085018190526001600160401b038781168452838352928690208651948501875280546001600160a01b0381168652600160a01b810460ff16151593860193909352600160a81b90920490921694830194909452600184018054939492939184019161036690611146565b80601f016020809104026020016040519081016040528092919081815260200182805461039290611146565b80156103df5780601f106103b4576101008083540402835291602001916103df565b820191906000526020600020905b8154815290600101906020018083116103c257829003601f168201915b5050505050815250509050919050565b80356001600160401b038116811461040657600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60405160a081016001600160401b03811182821017156104435761044361040b565b60405290565b60405161010081016001600160401b03811182821017156104435761044361040b565b604080519081016001600160401b03811182821017156104435761044361040b565b604051606081016001600160401b03811182821017156104435761044361040b565b604051608081016001600160401b03811182821017156104435761044361040b565b604051601f8201601f191681016001600160401b03811182821017156104fa576104fa61040b565b604052919050565b600082601f83011261051357600080fd5b81356001600160401b0381111561052c5761052c61040b565b61053f601f8201601f19166020016104d2565b81815284602083860101111561055457600080fd5b816020850160208301376000918101602001919091529392505050565b600080600080600060a0868803121561058957600080fd5b610592866103ef565b94506105a0602087016103ef565b9350604086013592506060860135600481106105bb57600080fd5b915060808601356001600160401b038111156105d657600080fd5b6105e288828901610502565b9150509295509295909350565b600060a0828403121561060157600080fd5b610609610421565b90508135815261061b602083016103ef565b602082015261062c604083016103ef565b604082015261063d606083016103ef565b606082015261064e608083016103ef565b608082015292915050565b6001600160a01b038116811461066e57600080fd5b50565b803561040681610659565b60006001600160401b038211156106955761069561040b565b5060051b60200190565b600082601f8301126106b057600080fd5b813560206106c56106c08361067c565b6104d2565b82815260059290921b840181019181810190868411156106e457600080fd5b8286015b848110156107de5780356001600160401b03808211156107085760008081fd5b9088019060a0828b03601f19018113156107225760008081fd5b61072a610421565b878401358381111561073c5760008081fd5b61074a8d8a83880101610502565b825250604080850135848111156107615760008081fd5b61076f8e8b83890101610502565b8a84015250606080860135858111156107885760008081fd5b6107968f8c838a0101610502565b838501525060809150818601358184015250828501359250838311156107bc5760008081fd5b6107ca8d8a85880101610502565b9082015286525050509183019183016106e8565b509695505050505050565b600080604083850312156107fc57600080fd5b610805836103ef565b915060208301356001600160401b038082111561082157600080fd5b90840190610180828703121561083657600080fd5b61083e610449565b61084887846105ef565b815261085660a08401610671565b602082015260c08301358281111561086d57600080fd5b61087988828601610502565b60408301525060e08301358281111561089157600080fd5b61089d88828601610502565b606083015250610100830135828111156108b657600080fd5b6108c288828601610502565b6080830152506108d56101208401610671565b60a082015261014083013560c0820152610160830135828111156108f857600080fd5b6109048882860161069f565b60e0830152508093505050509250929050565b60006020828403121561092957600080fd5b610932826103ef565b9392505050565b6000806040838503121561094c57600080fd5b610955836103ef565b9150610963602084016103ef565b90509250929050565b80356001600160e01b038116811461040657600080fd5b600082601f83011261099457600080fd5b813560206109a46106c08361067c565b82815260069290921b840181019181810190868411156109c357600080fd5b8286015b848110156107de57604081890312156109e05760008081fd5b6109e861046c565b6109f1826103ef565b81526109fe85830161096c565b818601528352918301916040016109c7565b600082601f830112610a2157600080fd5b81356020610a316106c08361067c565b82815260079290921b84018101918181019086841115610a5057600080fd5b8286015b848110156107de578088036080811215610a6e5760008081fd5b610a7661048e565b610a7f836103ef565b8152604080601f1984011215610a955760008081fd5b610a9d61046c565b9250610aaa8785016103ef565b8352610ab78185016103ef565b8388015281870192909252606083013591810191909152835291830191608001610a54565b60006020808385031215610aef57600080fd5b82356001600160401b0380821115610b0657600080fd5b81850191506040808388031215610b1c57600080fd5b610b2461046c565b833583811115610b3357600080fd5b84016040818a031215610b4557600080fd5b610b4d61046c565b813585811115610b5c57600080fd5b8201601f81018b13610b6d57600080fd5b8035610b7b6106c08261067c565b81815260069190911b8201890190898101908d831115610b9a57600080fd5b928a01925b82841015610bea5787848f031215610bb75760008081fd5b610bbf61046c565b8435610bca81610659565b8152610bd7858d0161096c565b818d0152825292870192908a0190610b9f565b845250505081870135935084841115610c0257600080fd5b610c0e8a858401610983565b8188015282525083850135915082821115610c2857600080fd5b610c3488838601610a10565b85820152809550505050505092915050565b60008060408385031215610c5957600080fd5b610c62836103ef565b915060208301356001600160401b0380821115610c7e57600080fd5b9084019060808287031215610c9257600080fd5b610c9a6104b0565b8235610ca581610659565b815260208301358015158114610cba57600080fd5b6020820152610ccb604084016103ef565b6040820152606083013582811115610ce257600080fd5b610cee88828601610502565b6060830152508093505050509250929050565b6000815180845260005b81811015610d2757602081850181015186830182015201610d0b565b506000602082860101526020601f19601f83011685010191505092915050565b602080825282516001600160a01b03168282015282015115156040808301919091528201516001600160401b0316606080830191909152820151608080830152600090610d9760a0840182610d01565b949350505050565b600060048410610dbf57634e487b7160e01b600052602160045260246000fd5b83825260406020830152610d976040830184610d01565b6001600160a01b03169052565b600082825180855260208086019550808260051b84010181860160005b84811015610e9557601f19868403018952815160a08151818652610e2682870182610d01565b9150508582015185820387870152610e3e8282610d01565b91505060408083015186830382880152610e588382610d01565b92505050606080830151818701525060808083015192508582038187015250610e818183610d01565b9a86019a9450505090830190600101610e00565b5090979650505050505050565b60208152610eef602082018351805182526020808201516001600160401b039081169184019190915260408083015182169084015260608083015182169084015260809182015116910152565b60006020830151610f0360c0840182610dd6565b5060408301516101808060e0850152610f206101a0850183610d01565b91506060850151601f198086850301610100870152610f3f8483610d01565b9350608087015191508086850301610120870152610f5d8483610d01565b935060a08701519150610f74610140870183610dd6565b60c087015161016087015260e0870151915080868503018387015250610f9a8382610de3565b9695505050505050565b6001600160401b03818116838216019080821115610fd257634e487b7160e01b600052601160045260246000fd5b5092915050565b60008151808452602080850194506020840160005b8381101561102757815180516001600160401b031688528301516001600160e01b03168388015260409096019590820190600101610fee565b509495945050505050565b600081518084526020808501945080840160005b8381101561102757815180516001600160401b0390811689528482015180518216868b0152850151166040898101919091520151606088015260809096019590820190600101611046565b6000602080835283516040808386015260a0850182516040606088015281815180845260c0890191508683019350600092505b808310156110ff57835180516001600160a01b031683528701516001600160e01b0316878301529286019260019290920191908401906110c4565b5093850151878503605f190160808901529361111b8186610fd9565b945050505050818501519150601f1984820301604085015261113d8183611032565b95945050505050565b600181811c9082168061115a57607f821691505b60208210810361117a57634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156111cc576000816000526020600020601f850160051c810160208610156111a95750805b601f850160051c820191505b818110156111c8578281556001016111b5565b5050505b505050565b81516001600160401b038111156111ea576111ea61040b565b6111fe816111f88454611146565b84611180565b602080601f831160018114611233576000841561121b5750858301515b600019600386901b1c1916600185901b1785556111c8565b600085815260208120601f198616915b8281101561126257888601518255948401946001909101908401611243565b50858210156112805787850151600019600388901b60f8161c191681555b5050505050600190811b0190555056fea164736f6c6343000818000a", } var CCIPReaderTesterABI = CCIPReaderTesterMetaData.ABI @@ -236,6 +236,28 @@ func (_CCIPReaderTester *CCIPReaderTesterTransactorRaw) Transact(opts *bind.Tran return _CCIPReaderTester.Contract.contract.Transact(opts, method, params...) } +func (_CCIPReaderTester *CCIPReaderTesterCaller) GetExpectedNextSequenceNumber(opts *bind.CallOpts, destChainSelector uint64) (uint64, error) { + var out []interface{} + err := _CCIPReaderTester.contract.Call(opts, &out, "getExpectedNextSequenceNumber", destChainSelector) + + if err != nil { + return *new(uint64), err + } + + out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) + + return out0, err + +} + +func (_CCIPReaderTester *CCIPReaderTesterSession) GetExpectedNextSequenceNumber(destChainSelector uint64) (uint64, error) { + return _CCIPReaderTester.Contract.GetExpectedNextSequenceNumber(&_CCIPReaderTester.CallOpts, destChainSelector) +} + +func (_CCIPReaderTester *CCIPReaderTesterCallerSession) GetExpectedNextSequenceNumber(destChainSelector uint64) (uint64, error) { + return _CCIPReaderTester.Contract.GetExpectedNextSequenceNumber(&_CCIPReaderTester.CallOpts, destChainSelector) +} + func (_CCIPReaderTester *CCIPReaderTesterCaller) GetSourceChainConfig(opts *bind.CallOpts, sourceChainSelector uint64) (OffRampSourceChainConfig, error) { var out []interface{} err := _CCIPReaderTester.contract.Call(opts, &out, "getSourceChainConfig", sourceChainSelector) @@ -294,6 +316,18 @@ func (_CCIPReaderTester *CCIPReaderTesterTransactorSession) EmitExecutionStateCh return _CCIPReaderTester.Contract.EmitExecutionStateChanged(&_CCIPReaderTester.TransactOpts, sourceChainSelector, sequenceNumber, messageId, state, returnData) } +func (_CCIPReaderTester *CCIPReaderTesterTransactor) SetDestChainSeqNr(opts *bind.TransactOpts, destChainSelector uint64, sequenceNumber uint64) (*types.Transaction, error) { + return _CCIPReaderTester.contract.Transact(opts, "setDestChainSeqNr", destChainSelector, sequenceNumber) +} + +func (_CCIPReaderTester *CCIPReaderTesterSession) SetDestChainSeqNr(destChainSelector uint64, sequenceNumber uint64) (*types.Transaction, error) { + return _CCIPReaderTester.Contract.SetDestChainSeqNr(&_CCIPReaderTester.TransactOpts, destChainSelector, sequenceNumber) +} + +func (_CCIPReaderTester *CCIPReaderTesterTransactorSession) SetDestChainSeqNr(destChainSelector uint64, sequenceNumber uint64) (*types.Transaction, error) { + return _CCIPReaderTester.Contract.SetDestChainSeqNr(&_CCIPReaderTester.TransactOpts, destChainSelector, sequenceNumber) +} + func (_CCIPReaderTester *CCIPReaderTesterTransactor) SetSourceChainConfig(opts *bind.TransactOpts, sourceChainSelector uint64, sourceChainConfig OffRampSourceChainConfig) (*types.Transaction, error) { return _CCIPReaderTester.contract.Transact(opts, "setSourceChainConfig", sourceChainSelector, sourceChainConfig) } @@ -729,6 +763,8 @@ func (_CCIPReaderTester *CCIPReaderTester) Address() common.Address { } type CCIPReaderTesterInterface interface { + GetExpectedNextSequenceNumber(opts *bind.CallOpts, destChainSelector uint64) (uint64, error) + GetSourceChainConfig(opts *bind.CallOpts, sourceChainSelector uint64) (OffRampSourceChainConfig, error) EmitCCIPSendRequested(opts *bind.TransactOpts, destChainSelector uint64, message InternalEVM2AnyRampMessage) (*types.Transaction, error) @@ -737,6 +773,8 @@ type CCIPReaderTesterInterface interface { EmitExecutionStateChanged(opts *bind.TransactOpts, sourceChainSelector uint64, sequenceNumber uint64, messageId [32]byte, state uint8, returnData []byte) (*types.Transaction, error) + SetDestChainSeqNr(opts *bind.TransactOpts, destChainSelector uint64, sequenceNumber uint64) (*types.Transaction, error) + SetSourceChainConfig(opts *bind.TransactOpts, sourceChainSelector uint64, sourceChainConfig OffRampSourceChainConfig) (*types.Transaction, error) FilterCCIPSendRequested(opts *bind.FilterOpts, destChainSelector []uint64) (*CCIPReaderTesterCCIPSendRequestedIterator, error) diff --git a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt index 9fd0ac9e8d..98fb5dd620 100644 --- a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -5,7 +5,7 @@ burn_mint_token_pool_and_proxy: ../../../contracts/solc/v0.8.24/BurnMintTokenPoo burn_with_from_mint_token_pool: ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.abi ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.bin 6333d0314d0bd29e75ea5e05fe62a4516ade0c6db91c30b6f93645035db52ed8 burn_with_from_mint_token_pool_and_proxy: ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPoolAndProxy/BurnWithFromMintTokenPoolAndProxy.abi ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPoolAndProxy/BurnWithFromMintTokenPoolAndProxy.bin 08ed1235dda921ce8841b26aa18d0c0f36db4884779dd7670857159801b6d597 ccip_config: ../../../contracts/solc/v0.8.24/CCIPConfig/CCIPConfig.abi ../../../contracts/solc/v0.8.24/CCIPConfig/CCIPConfig.bin 213d4adc8634671aea16fb4207989375b1aac919b04d608f4767c29592affbf5 -ccip_reader_tester: ../../../contracts/solc/v0.8.24/CCIPReaderTester/CCIPReaderTester.abi ../../../contracts/solc/v0.8.24/CCIPReaderTester/CCIPReaderTester.bin 459ae9c785343bd032856baaacdfc8bf4f6b0d9f5d9082e1580b5846c2be80e5 +ccip_reader_tester: ../../../contracts/solc/v0.8.24/CCIPReaderTester/CCIPReaderTester.abi ../../../contracts/solc/v0.8.24/CCIPReaderTester/CCIPReaderTester.bin d8d70fe111bacc7702c7c263f8c4733dcb2fff77e52c9f60c30d303731bc97c1 commit_store: ../../../contracts/solc/v0.8.24/CommitStore/CommitStore.abi ../../../contracts/solc/v0.8.24/CommitStore/CommitStore.bin 274d87db70b643e00ab0a7e7845bb4b791f3b613bfc87708d33fc5a8369e2a41 commit_store_helper: ../../../contracts/solc/v0.8.24/CommitStoreHelper/CommitStoreHelper.abi ../../../contracts/solc/v0.8.24/CommitStoreHelper/CommitStoreHelper.bin f7128dcc2ee6dbcbc976288abcc16970ffb19b59412c5202ef6b259d2007f801 ether_sender_receiver: ../../../contracts/solc/v0.8.24/EtherSenderReceiver/EtherSenderReceiver.abi ../../../contracts/solc/v0.8.24/EtherSenderReceiver/EtherSenderReceiver.bin 09510a3f773f108a3c231e8d202835c845ded862d071ec54c4f89c12d868b8de diff --git a/core/scripts/go.mod b/core/scripts/go.mod index 1167821d05..b167d6cd02 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -274,7 +274,7 @@ require ( github.com/sethvargo/go-retry v0.2.4 // indirect github.com/shirou/gopsutil v3.21.11+incompatible // indirect github.com/shirou/gopsutil/v3 v3.24.3 // indirect - github.com/smartcontractkit/chainlink-ccip v0.0.0-20240827080218-11e3f1781d9e // indirect + github.com/smartcontractkit/chainlink-ccip v0.0.0-20240827164549-33f5819d7ddc // indirect github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240710121324-3ed288aa9b45 // indirect github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240718160222-2dc0c8136bfa // indirect github.com/smartcontractkit/chainlink-feeds v0.0.0-20240710170203-5b41615da827 // indirect diff --git a/core/scripts/go.sum b/core/scripts/go.sum index a155bfc334..7ab6113b2a 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -1070,8 +1070,8 @@ github.com/smartcontractkit/chain-selectors v1.0.21 h1:KCR9SA7PhOexaBzFieHoLv1Wo github.com/smartcontractkit/chain-selectors v1.0.21/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/smartcontractkit/chainlink-automation v1.0.4 h1:iyW181JjKHLNMnDleI8umfIfVVlwC7+n5izbLSFgjw8= github.com/smartcontractkit/chainlink-automation v1.0.4/go.mod h1:u4NbPZKJ5XiayfKHD/v3z3iflQWqvtdhj13jVZXj/cM= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20240827080218-11e3f1781d9e h1:ecZaltgIB+mRi9sXYYpOJQXEkeyvQYrKUUzKWv7D+J0= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20240827080218-11e3f1781d9e/go.mod h1:Z9lQ5t20kRk28pzRLnqAJZUVOw8E6/siA3P3MLyKqoM= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20240827164549-33f5819d7ddc h1:8267l5X5oF2JnGsDaEG4i0JSQO9o0eC61SscTfWc1bk= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20240827164549-33f5819d7ddc/go.mod h1:Z9lQ5t20kRk28pzRLnqAJZUVOw8E6/siA3P3MLyKqoM= github.com/smartcontractkit/chainlink-common v0.2.1-0.20240717132349-ee5af9b79834 h1:pTf4xdcmiWBqWZ6rTy2RMTDBzhHk89VC1pM7jXKQztI= github.com/smartcontractkit/chainlink-common v0.2.1-0.20240717132349-ee5af9b79834/go.mod h1:fh9eBbrReCmv31bfz52ENCAMa7nTKQbdhb2B3+S2VGo= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240710121324-3ed288aa9b45 h1:NBQLtqk8zsyY4qTJs+NElI3aDFTcAo83JHvqD04EvB0= diff --git a/go.mod b/go.mod index de8ef4d0fa..783b28e5a2 100644 --- a/go.mod +++ b/go.mod @@ -74,7 +74,7 @@ require ( github.com/shopspring/decimal v1.4.0 github.com/smartcontractkit/chain-selectors v1.0.21 github.com/smartcontractkit/chainlink-automation v1.0.4 - github.com/smartcontractkit/chainlink-ccip v0.0.0-20240827080218-11e3f1781d9e + github.com/smartcontractkit/chainlink-ccip v0.0.0-20240827164549-33f5819d7ddc github.com/smartcontractkit/chainlink-common v0.2.1-0.20240717132349-ee5af9b79834 github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240710121324-3ed288aa9b45 github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240718160222-2dc0c8136bfa diff --git a/go.sum b/go.sum index 5e5b72ed2c..081c0a2aee 100644 --- a/go.sum +++ b/go.sum @@ -1027,8 +1027,8 @@ github.com/smartcontractkit/chain-selectors v1.0.21 h1:KCR9SA7PhOexaBzFieHoLv1Wo github.com/smartcontractkit/chain-selectors v1.0.21/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/smartcontractkit/chainlink-automation v1.0.4 h1:iyW181JjKHLNMnDleI8umfIfVVlwC7+n5izbLSFgjw8= github.com/smartcontractkit/chainlink-automation v1.0.4/go.mod h1:u4NbPZKJ5XiayfKHD/v3z3iflQWqvtdhj13jVZXj/cM= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20240827080218-11e3f1781d9e h1:ecZaltgIB+mRi9sXYYpOJQXEkeyvQYrKUUzKWv7D+J0= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20240827080218-11e3f1781d9e/go.mod h1:Z9lQ5t20kRk28pzRLnqAJZUVOw8E6/siA3P3MLyKqoM= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20240827164549-33f5819d7ddc h1:8267l5X5oF2JnGsDaEG4i0JSQO9o0eC61SscTfWc1bk= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20240827164549-33f5819d7ddc/go.mod h1:Z9lQ5t20kRk28pzRLnqAJZUVOw8E6/siA3P3MLyKqoM= github.com/smartcontractkit/chainlink-common v0.2.1-0.20240717132349-ee5af9b79834 h1:pTf4xdcmiWBqWZ6rTy2RMTDBzhHk89VC1pM7jXKQztI= github.com/smartcontractkit/chainlink-common v0.2.1-0.20240717132349-ee5af9b79834/go.mod h1:fh9eBbrReCmv31bfz52ENCAMa7nTKQbdhb2B3+S2VGo= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240710121324-3ed288aa9b45 h1:NBQLtqk8zsyY4qTJs+NElI3aDFTcAo83JHvqD04EvB0= diff --git a/integration-tests/go.mod b/integration-tests/go.mod index 3e8db90744..e20e98bcf9 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -36,7 +36,7 @@ require ( github.com/smartcontractkit/ccip-owner-contracts v0.0.0-20240808195812-ae0378684685 github.com/smartcontractkit/chain-selectors v1.0.21 github.com/smartcontractkit/chainlink-automation v1.0.4 - github.com/smartcontractkit/chainlink-ccip v0.0.0-20240827080218-11e3f1781d9e + github.com/smartcontractkit/chainlink-ccip v0.0.0-20240827164549-33f5819d7ddc github.com/smartcontractkit/chainlink-common v0.2.1-0.20240717132349-ee5af9b79834 github.com/smartcontractkit/chainlink-testing-framework v1.34.5 github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240405215812-5a72bc9af239 diff --git a/integration-tests/go.sum b/integration-tests/go.sum index 3a75793f13..5789a6ccc2 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1396,8 +1396,8 @@ github.com/smartcontractkit/chain-selectors v1.0.21 h1:KCR9SA7PhOexaBzFieHoLv1Wo github.com/smartcontractkit/chain-selectors v1.0.21/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/smartcontractkit/chainlink-automation v1.0.4 h1:iyW181JjKHLNMnDleI8umfIfVVlwC7+n5izbLSFgjw8= github.com/smartcontractkit/chainlink-automation v1.0.4/go.mod h1:u4NbPZKJ5XiayfKHD/v3z3iflQWqvtdhj13jVZXj/cM= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20240827080218-11e3f1781d9e h1:ecZaltgIB+mRi9sXYYpOJQXEkeyvQYrKUUzKWv7D+J0= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20240827080218-11e3f1781d9e/go.mod h1:Z9lQ5t20kRk28pzRLnqAJZUVOw8E6/siA3P3MLyKqoM= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20240827164549-33f5819d7ddc h1:8267l5X5oF2JnGsDaEG4i0JSQO9o0eC61SscTfWc1bk= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20240827164549-33f5819d7ddc/go.mod h1:Z9lQ5t20kRk28pzRLnqAJZUVOw8E6/siA3P3MLyKqoM= github.com/smartcontractkit/chainlink-common v0.2.1-0.20240717132349-ee5af9b79834 h1:pTf4xdcmiWBqWZ6rTy2RMTDBzhHk89VC1pM7jXKQztI= github.com/smartcontractkit/chainlink-common v0.2.1-0.20240717132349-ee5af9b79834/go.mod h1:fh9eBbrReCmv31bfz52ENCAMa7nTKQbdhb2B3+S2VGo= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240710121324-3ed288aa9b45 h1:NBQLtqk8zsyY4qTJs+NElI3aDFTcAo83JHvqD04EvB0= diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index 970896b124..ef077ba768 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -42,7 +42,7 @@ require ( github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect - github.com/smartcontractkit/chainlink-ccip v0.0.0-20240827080218-11e3f1781d9e // indirect + github.com/smartcontractkit/chainlink-ccip v0.0.0-20240827164549-33f5819d7ddc // indirect github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240710121324-3ed288aa9b45 // indirect github.com/testcontainers/testcontainers-go v0.28.0 // indirect k8s.io/apimachinery v0.30.2 // indirect diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index 97ed754ba7..3e5d20d303 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -1360,8 +1360,8 @@ github.com/smartcontractkit/chain-selectors v1.0.21 h1:KCR9SA7PhOexaBzFieHoLv1Wo github.com/smartcontractkit/chain-selectors v1.0.21/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/smartcontractkit/chainlink-automation v1.0.4 h1:iyW181JjKHLNMnDleI8umfIfVVlwC7+n5izbLSFgjw8= github.com/smartcontractkit/chainlink-automation v1.0.4/go.mod h1:u4NbPZKJ5XiayfKHD/v3z3iflQWqvtdhj13jVZXj/cM= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20240827080218-11e3f1781d9e h1:ecZaltgIB+mRi9sXYYpOJQXEkeyvQYrKUUzKWv7D+J0= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20240827080218-11e3f1781d9e/go.mod h1:Z9lQ5t20kRk28pzRLnqAJZUVOw8E6/siA3P3MLyKqoM= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20240827164549-33f5819d7ddc h1:8267l5X5oF2JnGsDaEG4i0JSQO9o0eC61SscTfWc1bk= +github.com/smartcontractkit/chainlink-ccip v0.0.0-20240827164549-33f5819d7ddc/go.mod h1:Z9lQ5t20kRk28pzRLnqAJZUVOw8E6/siA3P3MLyKqoM= github.com/smartcontractkit/chainlink-common v0.2.1-0.20240717132349-ee5af9b79834 h1:pTf4xdcmiWBqWZ6rTy2RMTDBzhHk89VC1pM7jXKQztI= github.com/smartcontractkit/chainlink-common v0.2.1-0.20240717132349-ee5af9b79834/go.mod h1:fh9eBbrReCmv31bfz52ENCAMa7nTKQbdhb2B3+S2VGo= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240710121324-3ed288aa9b45 h1:NBQLtqk8zsyY4qTJs+NElI3aDFTcAo83JHvqD04EvB0= From 00ace85ca8e1db95307903d0e135161feedb15d6 Mon Sep 17 00:00:00 2001 From: kanth <70688600+defistar@users.noreply.github.com> Date: Tue, 27 Aug 2024 23:36:58 +0530 Subject: [PATCH 038/115] feat: emit msghash with offramp (#1370) ## Motivation RMN checks the full hash of the message. However, hash(Any2EVMMessage) != Any2EVMMessage.header.messageId . ## Solution emit `messageHash` along with `ExecutionStateChanged` event --------- Co-authored-by: app-token-issuer-infra-releng[bot] <120227048+app-token-issuer-infra-releng[bot]@users.noreply.github.com> Co-authored-by: Rens Rooimans --- contracts/gas-snapshots/ccip.gas-snapshot | 182 +++++++++--------- contracts/src/v0.8/ccip/offRamp/OffRamp.sol | 2 + .../src/v0.8/ccip/test/NonceManager.t.sol | 6 + .../v0.8/ccip/test/e2e/MultiRampsEnd2End.sol | 139 +++++++------ .../src/v0.8/ccip/test/offRamp/OffRamp.t.sol | 46 +++++ .../v0.8/ccip/test/offRamp/OffRampSetup.t.sol | 7 +- .../ccip/generated/offramp/offramp.go | 7 +- ...rapper-dependency-versions-do-not-edit.txt | 2 +- 8 files changed, 232 insertions(+), 159 deletions(-) diff --git a/contracts/gas-snapshots/ccip.gas-snapshot b/contracts/gas-snapshots/ccip.gas-snapshot index af1f296236..c13660452d 100644 --- a/contracts/gas-snapshots/ccip.gas-snapshot +++ b/contracts/gas-snapshots/ccip.gas-snapshot @@ -543,18 +543,18 @@ MultiOCR3Base_transmit:test_UnauthorizedSigner_Revert() (gas: 61409) MultiOCR3Base_transmit:test_UnconfiguredPlugin_Revert() (gas: 39890) MultiOCR3Base_transmit:test_ZeroSignatures_Revert() (gas: 32973) MultiOnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 410714) -MultiRampsE2E:test_E2E_3MessagesMMultiOffRampSuccess_gas() (gas: 1486877) +MultiRampsE2E:test_E2E_3MessagesMMultiOffRampSuccess_gas() (gas: 1504468) NonceManager_NonceIncrementation:test_getIncrementedOutboundNonce_Success() (gas: 37907) NonceManager_NonceIncrementation:test_incrementInboundNonce_Skip() (gas: 23694) NonceManager_NonceIncrementation:test_incrementInboundNonce_Success() (gas: 38763) NonceManager_NonceIncrementation:test_incrementNoncesInboundAndOutbound_Success() (gas: 71847) -NonceManager_OffRampUpgrade:test_NoPrevOffRampForChain_Success() (gas: 257298) -NonceManager_OffRampUpgrade:test_UpgradedNonceNewSenderStartsAtZero_Success() (gas: 259415) -NonceManager_OffRampUpgrade:test_UpgradedNonceStartsAtV1Nonce_Success() (gas: 320051) -NonceManager_OffRampUpgrade:test_UpgradedOffRampNonceSkipsIfMsgInFlight_Success() (gas: 295325) -NonceManager_OffRampUpgrade:test_UpgradedSenderNoncesReadsPreviousRampTransitive_Success() (gas: 244940) -NonceManager_OffRampUpgrade:test_UpgradedSenderNoncesReadsPreviousRamp_Success() (gas: 233260) -NonceManager_OffRampUpgrade:test_Upgraded_Success() (gas: 150194) +NonceManager_OffRampUpgrade:test_NoPrevOffRampForChain_Success() (gas: 260262) +NonceManager_OffRampUpgrade:test_UpgradedNonceNewSenderStartsAtZero_Success() (gas: 262359) +NonceManager_OffRampUpgrade:test_UpgradedNonceStartsAtV1Nonce_Success() (gas: 326051) +NonceManager_OffRampUpgrade:test_UpgradedOffRampNonceSkipsIfMsgInFlight_Success() (gas: 298263) +NonceManager_OffRampUpgrade:test_UpgradedSenderNoncesReadsPreviousRampTransitive_Success() (gas: 244814) +NonceManager_OffRampUpgrade:test_UpgradedSenderNoncesReadsPreviousRamp_Success() (gas: 233069) +NonceManager_OffRampUpgrade:test_Upgraded_Success() (gas: 153186) NonceManager_OnRampUpgrade:test_UpgradeNonceNewSenderStartsAtZero_Success() (gas: 168502) NonceManager_OnRampUpgrade:test_UpgradeNonceStartsAtV1Nonce_Success() (gas: 220478) NonceManager_OnRampUpgrade:test_UpgradeSenderNoncesReadsPreviousRamp_Success() (gas: 125070) @@ -591,7 +591,7 @@ OCR2Base_transmit:test_Transmit2SignersSuccess_gas() (gas: 51686) OCR2Base_transmit:test_UnAuthorizedTransmitter_Revert() (gas: 23484) OCR2Base_transmit:test_UnauthorizedSigner_Revert() (gas: 39665) OCR2Base_transmit:test_WrongNumberOfSignatures_Revert() (gas: 20557) -OffRamp__releaseOrMintSingleToken:test__releaseOrMintSingleToken_NotACompatiblePool_Revert() (gas: 40127) +OffRamp__releaseOrMintSingleToken:test__releaseOrMintSingleToken_NotACompatiblePool_Revert() (gas: 40149) OffRamp__releaseOrMintSingleToken:test__releaseOrMintSingleToken_Success() (gas: 107130) OffRamp__releaseOrMintSingleToken:test__releaseOrMintSingleToken_TokenHandlingError_transfer_Revert() (gas: 88331) OffRamp__releaseOrMintSingleToken:test_releaseOrMintToken_InvalidDataLength_Revert() (gas: 39848) @@ -599,129 +599,129 @@ OffRamp__releaseOrMintSingleToken:test_releaseOrMintToken_ReleaseOrMintBalanceMi OffRamp__releaseOrMintSingleToken:test_releaseOrMintToken_TokenHandlingError_BalanceOf_Revert() (gas: 42843) OffRamp__releaseOrMintSingleToken:test_releaseOrMintToken_skip_ReleaseOrMintBalanceMismatch_if_pool_Revert() (gas: 89579) OffRamp_applySourceChainConfigUpdates:test_AddMultipleChains_Success() (gas: 467917) -OffRamp_applySourceChainConfigUpdates:test_AddNewChain_Success() (gas: 99161) +OffRamp_applySourceChainConfigUpdates:test_AddNewChain_Success() (gas: 99183) OffRamp_applySourceChainConfigUpdates:test_ApplyZeroUpdates_Success() (gas: 12395) OffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChainOnRamp_Revert() (gas: 93181) OffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChain_Success() (gas: 109824) OffRamp_applySourceChainConfigUpdates:test_RouterAddress_Revert() (gas: 13263) OffRamp_applySourceChainConfigUpdates:test_ZeroOnRampAddress_Revert() (gas: 17988) -OffRamp_applySourceChainConfigUpdates:test_ZeroSourceChainSelector_Revert() (gas: 15343) -OffRamp_batchExecute:test_MultipleReportsDifferentChains_Success() (gas: 313729) -OffRamp_batchExecute:test_MultipleReportsSameChain_Success() (gas: 255119) -OffRamp_batchExecute:test_MultipleReportsSkipDuplicate_Success() (gas: 166168) -OffRamp_batchExecute:test_OutOfBoundsGasLimitsAccess_Revert() (gas: 187819) -OffRamp_batchExecute:test_SingleReport_Success() (gas: 153185) -OffRamp_batchExecute:test_Unhealthy_Revert() (gas: 532970) -OffRamp_batchExecute:test_ZeroReports_Revert() (gas: 10439) +OffRamp_applySourceChainConfigUpdates:test_ZeroSourceChainSelector_Revert() (gas: 15300) +OffRamp_batchExecute:test_MultipleReportsDifferentChains_Success() (gas: 322171) +OffRamp_batchExecute:test_MultipleReportsSameChain_Success() (gas: 263506) +OffRamp_batchExecute:test_MultipleReportsSkipDuplicate_Success() (gas: 169162) +OffRamp_batchExecute:test_OutOfBoundsGasLimitsAccess_Revert() (gas: 188589) +OffRamp_batchExecute:test_SingleReport_Success() (gas: 156230) +OffRamp_batchExecute:test_Unhealthy_Revert() (gas: 533834) +OffRamp_batchExecute:test_ZeroReports_Revert() (gas: 10461) OffRamp_ccipReceive:test_Reverts() (gas: 15773) -OffRamp_commit:test_InvalidIntervalMinLargerThanMax_Revert() (gas: 67436) +OffRamp_commit:test_InvalidIntervalMinLargerThanMax_Revert() (gas: 67458) OffRamp_commit:test_InvalidInterval_Revert() (gas: 59778) OffRamp_commit:test_InvalidRootRevert() (gas: 58858) -OffRamp_commit:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6551011) -OffRamp_commit:test_NoConfig_Revert() (gas: 6134083) -OffRamp_commit:test_OnlyGasPriceUpdates_Success() (gas: 106295) +OffRamp_commit:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6560573) +OffRamp_commit:test_NoConfig_Revert() (gas: 6143711) +OffRamp_commit:test_OnlyGasPriceUpdates_Success() (gas: 106317) OffRamp_commit:test_OnlyPriceUpdateStaleReport_Revert() (gas: 116369) -OffRamp_commit:test_OnlyTokenPriceUpdates_Success() (gas: 106316) +OffRamp_commit:test_OnlyTokenPriceUpdates_Success() (gas: 106338) OffRamp_commit:test_PriceSequenceNumberCleared_Success() (gas: 351652) OffRamp_commit:test_ReportAndPriceUpdate_Success() (gas: 159342) OffRamp_commit:test_ReportOnlyRootSuccess_gas() (gas: 136480) -OffRamp_commit:test_RootAlreadyCommitted_Revert() (gas: 136947) +OffRamp_commit:test_RootAlreadyCommitted_Revert() (gas: 136880) OffRamp_commit:test_SourceChainNotEnabled_Revert() (gas: 59126) OffRamp_commit:test_StaleReportWithRoot_Success() (gas: 225582) OffRamp_commit:test_UnauthorizedTransmitter_Revert() (gas: 117632) -OffRamp_commit:test_Unhealthy_Revert() (gas: 77652) +OffRamp_commit:test_Unhealthy_Revert() (gas: 77674) OffRamp_commit:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 205066) -OffRamp_commit:test_WrongConfigWithoutSigners_Revert() (gas: 6545334) +OffRamp_commit:test_WrongConfigWithoutSigners_Revert() (gas: 6554962) OffRamp_commit:test_ZeroEpochAndRound_Revert() (gas: 47832) -OffRamp_constructor:test_Constructor_Success() (gas: 6137987) -OffRamp_constructor:test_SourceChainSelector_Revert() (gas: 137086) -OffRamp_constructor:test_ZeroChainSelector_Revert() (gas: 103803) -OffRamp_constructor:test_ZeroNonceManager_Revert() (gas: 101696) -OffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 139661) -OffRamp_constructor:test_ZeroRMNProxy_Revert() (gas: 101573) -OffRamp_constructor:test_ZeroTokenAdminRegistry_Revert() (gas: 101618) +OffRamp_constructor:test_Constructor_Success() (gas: 6147616) +OffRamp_constructor:test_SourceChainSelector_Revert() (gas: 137128) +OffRamp_constructor:test_ZeroChainSelector_Revert() (gas: 103845) +OffRamp_constructor:test_ZeroNonceManager_Revert() (gas: 101716) +OffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 139680) +OffRamp_constructor:test_ZeroRMNProxy_Revert() (gas: 101593) +OffRamp_constructor:test_ZeroTokenAdminRegistry_Revert() (gas: 101660) OffRamp_execute:test_IncorrectArrayType_Revert() (gas: 17305) -OffRamp_execute:test_LargeBatch_Success() (gas: 1728220) -OffRamp_execute:test_MultipleReportsWithPartialValidationFailures_Success() (gas: 349589) -OffRamp_execute:test_MultipleReports_Success() (gas: 277112) -OffRamp_execute:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6601732) -OffRamp_execute:test_NoConfig_Revert() (gas: 6184566) -OffRamp_execute:test_NonArray_Revert() (gas: 27777) -OffRamp_execute:test_SingleReport_Success() (gas: 172547) -OffRamp_execute:test_UnauthorizedTransmitter_Revert() (gas: 147479) -OffRamp_execute:test_WrongConfigWithSigners_Revert() (gas: 6963806) -OffRamp_execute:test_ZeroReports_Revert() (gas: 17203) -OffRamp_executeSingleMessage:test_MessageSender_Revert() (gas: 18235) -OffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 249015) +OffRamp_execute:test_LargeBatch_Success() (gas: 1828972) +OffRamp_execute:test_MultipleReportsWithPartialValidationFailures_Success() (gas: 358063) +OffRamp_execute:test_MultipleReports_Success() (gas: 285617) +OffRamp_execute:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6611685) +OffRamp_execute:test_NoConfig_Revert() (gas: 6194563) +OffRamp_execute:test_NonArray_Revert() (gas: 27809) +OffRamp_execute:test_SingleReport_Success() (gas: 175620) +OffRamp_execute:test_UnauthorizedTransmitter_Revert() (gas: 147848) +OffRamp_execute:test_WrongConfigWithSigners_Revert() (gas: 6973803) +OffRamp_execute:test_ZeroReports_Revert() (gas: 17225) +OffRamp_executeSingleMessage:test_MessageSender_Revert() (gas: 18257) +OffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 249037) OffRamp_executeSingleMessage:test_NonContract_Success() (gas: 20517) -OffRamp_executeSingleMessage:test_TokenHandlingError_Revert() (gas: 207654) +OffRamp_executeSingleMessage:test_TokenHandlingError_Revert() (gas: 207676) OffRamp_executeSingleMessage:test_ZeroGasDONExecution_Revert() (gas: 48779) OffRamp_executeSingleMessage:test_executeSingleMessage_NoTokens_Success() (gas: 48302) -OffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidationNoRouterCall_Revert() (gas: 229610) -OffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidation_Revert() (gas: 86181) -OffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens_Success() (gas: 280837) -OffRamp_executeSingleMessage:test_executeSingleMessage_WithValidation_Success() (gas: 92415) -OffRamp_executeSingleReport:test_DisabledSourceChain_Revert() (gas: 35127) +OffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidationNoRouterCall_Revert() (gas: 229565) +OffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidation_Revert() (gas: 86203) +OffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens_Success() (gas: 280859) +OffRamp_executeSingleMessage:test_executeSingleMessage_WithValidation_Success() (gas: 92437) +OffRamp_executeSingleReport:test_DisabledSourceChain_Revert() (gas: 35104) OffRamp_executeSingleReport:test_EmptyReport_Revert() (gas: 23923) -OffRamp_executeSingleReport:test_InvalidSourcePoolAddress_Success() (gas: 486078) +OffRamp_executeSingleReport:test_InvalidSourcePoolAddress_Success() (gas: 492333) OffRamp_executeSingleReport:test_ManualExecutionNotYetEnabled_Revert() (gas: 54457) -OffRamp_executeSingleReport:test_MismatchingDestChainSelector_Revert() (gas: 35905) -OffRamp_executeSingleReport:test_MismatchingOnRampRoot_Revert() (gas: 154471) +OffRamp_executeSingleReport:test_MismatchingDestChainSelector_Revert() (gas: 35927) +OffRamp_executeSingleReport:test_MismatchingOnRampRoot_Revert() (gas: 154493) OffRamp_executeSingleReport:test_NonExistingSourceChain_Revert() (gas: 35338) -OffRamp_executeSingleReport:test_ReceiverError_Success() (gas: 184911) -OffRamp_executeSingleReport:test_RetryFailedMessageWithoutManualExecution_Revert() (gas: 196169) -OffRamp_executeSingleReport:test_RootNotCommitted_Revert() (gas: 48074) -OffRamp_executeSingleReport:test_RouterYULCall_Revert() (gas: 444732) -OffRamp_executeSingleReport:test_SingleMessageNoTokensOtherChain_Success() (gas: 250427) -OffRamp_executeSingleReport:test_SingleMessageNoTokensUnordered_Success() (gas: 187283) -OffRamp_executeSingleReport:test_SingleMessageNoTokens_Success() (gas: 206863) -OffRamp_executeSingleReport:test_SingleMessageToNonCCIPReceiver_Success() (gas: 263565) -OffRamp_executeSingleReport:test_SingleMessagesNoTokensSuccess_gas() (gas: 138454) -OffRamp_executeSingleReport:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 417627) +OffRamp_executeSingleReport:test_ReceiverError_Success() (gas: 187911) +OffRamp_executeSingleReport:test_RetryFailedMessageWithoutManualExecution_Revert() (gas: 199215) +OffRamp_executeSingleReport:test_RootNotCommitted_Revert() (gas: 48096) +OffRamp_executeSingleReport:test_RouterYULCall_Revert() (gas: 447759) +OffRamp_executeSingleReport:test_SingleMessageNoTokensOtherChain_Success() (gas: 251078) +OffRamp_executeSingleReport:test_SingleMessageNoTokensUnordered_Success() (gas: 193345) +OffRamp_executeSingleReport:test_SingleMessageNoTokens_Success() (gas: 212938) +OffRamp_executeSingleReport:test_SingleMessageToNonCCIPReceiver_Success() (gas: 266576) +OffRamp_executeSingleReport:test_SingleMessagesNoTokensSuccess_gas() (gas: 141488) +OffRamp_executeSingleReport:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 423378) OffRamp_executeSingleReport:test_SkippedIncorrectNonce_Success() (gas: 65877) -OffRamp_executeSingleReport:test_TokenDataMismatch_Revert() (gas: 80910) -OffRamp_executeSingleReport:test_TwoMessagesWithTokensAndGE_Success() (gas: 576137) -OffRamp_executeSingleReport:test_TwoMessagesWithTokensSuccess_gas() (gas: 525167) +OffRamp_executeSingleReport:test_TokenDataMismatch_Revert() (gas: 80932) +OffRamp_executeSingleReport:test_TwoMessagesWithTokensAndGE_Success() (gas: 587410) +OffRamp_executeSingleReport:test_TwoMessagesWithTokensSuccess_gas() (gas: 536450) OffRamp_executeSingleReport:test_UnexpectedTokenData_Revert() (gas: 35743) -OffRamp_executeSingleReport:test_UnhealthySingleChainCurse_Revert() (gas: 531800) -OffRamp_executeSingleReport:test_Unhealthy_Revert() (gas: 529168) -OffRamp_executeSingleReport:test_WithCurseOnAnotherSourceChain_Success() (gas: 494410) -OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessageUnordered_Success() (gas: 133560) -OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessage_Success() (gas: 162760) +OffRamp_executeSingleReport:test_UnhealthySingleChainCurse_Revert() (gas: 532474) +OffRamp_executeSingleReport:test_Unhealthy_Revert() (gas: 529798) +OffRamp_executeSingleReport:test_WithCurseOnAnotherSourceChain_Success() (gas: 495040) +OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessageUnordered_Success() (gas: 136580) +OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessage_Success() (gas: 165799) OffRamp_getExecutionState:test_FillExecutionState_Success() (gas: 3742124) -OffRamp_getExecutionState:test_GetDifferentChainExecutionState_Success() (gas: 118859) +OffRamp_getExecutionState:test_GetDifferentChainExecutionState_Success() (gas: 118836) OffRamp_getExecutionState:test_GetExecutionState_Success() (gas: 88048) OffRamp_manuallyExecute:test_ManualExecGasLimitMismatchSingleReport_Revert() (gas: 75551) OffRamp_manuallyExecute:test_ManualExecInvalidGasLimit_Revert() (gas: 26439) -OffRamp_manuallyExecute:test_manuallyExecute_DoesNotRevertIfUntouched_Success() (gas: 168628) -OffRamp_manuallyExecute:test_manuallyExecute_FailedTx_Revert() (gas: 205504) +OffRamp_manuallyExecute:test_manuallyExecute_DoesNotRevertIfUntouched_Success() (gas: 171639) +OffRamp_manuallyExecute:test_manuallyExecute_FailedTx_Revert() (gas: 205796) OffRamp_manuallyExecute:test_manuallyExecute_ForkedChain_Revert() (gas: 25993) OffRamp_manuallyExecute:test_manuallyExecute_GasLimitMismatchMultipleReports_Revert() (gas: 152822) -OffRamp_manuallyExecute:test_manuallyExecute_LowGasLimit_Success() (gas: 518556) -OffRamp_manuallyExecute:test_manuallyExecute_ReentrancyFails_Success() (gas: 2384534) -OffRamp_manuallyExecute:test_manuallyExecute_Success() (gas: 205857) -OffRamp_manuallyExecute:test_manuallyExecute_WithGasOverride_Success() (gas: 215965) -OffRamp_manuallyExecute:test_manuallyExecute_WithMultiReportGasOverride_Success() (gas: 649750) -OffRamp_manuallyExecute:test_manuallyExecute_WithPartialMessages_Success() (gas: 319062) +OffRamp_manuallyExecute:test_manuallyExecute_LowGasLimit_Success() (gas: 524603) +OffRamp_manuallyExecute:test_manuallyExecute_ReentrancyFails_Success() (gas: 2388943) +OffRamp_manuallyExecute:test_manuallyExecute_Success() (gas: 208553) +OffRamp_manuallyExecute:test_manuallyExecute_WithGasOverride_Success() (gas: 219343) +OffRamp_manuallyExecute:test_manuallyExecute_WithMultiReportGasOverride_Success() (gas: 663643) +OffRamp_manuallyExecute:test_manuallyExecute_WithPartialMessages_Success() (gas: 330148) OffRamp_releaseOrMintTokens:test_TokenHandlingError_Reverts() (gas: 165822) OffRamp_releaseOrMintTokens:test__releaseOrMintTokens_PoolIsNotAPool_Reverts() (gas: 24603) -OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_InvalidDataLengthReturnData_Revert() (gas: 66263) -OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_InvalidEVMAddress_Revert() (gas: 41294) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_InvalidDataLengthReturnData_Revert() (gas: 66285) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_InvalidEVMAddress_Revert() (gas: 41316) OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_PoolDoesNotSupportDest_Reverts() (gas: 83291) OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_Success() (gas: 177934) OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals_Success() (gas: 191136) OffRamp_resetUnblessedRoots:test_OnlyOwner_Revert() (gas: 11423) -OffRamp_resetUnblessedRoots:test_ResetUnblessedRoots_Success() (gas: 215351) +OffRamp_resetUnblessedRoots:test_ResetUnblessedRoots_Success() (gas: 215373) OffRamp_setDynamicConfig:test_FeeQuoterZeroAddress_Revert() (gas: 11585) -OffRamp_setDynamicConfig:test_NonOwner_Revert() (gas: 14130) -OffRamp_setDynamicConfig:test_SetDynamicConfigWithValidator_Success() (gas: 49093) -OffRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 27103) -OffRamp_trialExecute:test_RateLimitError_Success() (gas: 225773) -OffRamp_trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 234394) +OffRamp_setDynamicConfig:test_NonOwner_Revert() (gas: 14152) +OffRamp_setDynamicConfig:test_SetDynamicConfigWithValidator_Success() (gas: 49115) +OffRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 27037) +OffRamp_trialExecute:test_RateLimitError_Success() (gas: 225795) +OffRamp_trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 234416) OffRamp_trialExecute:test_TokenPoolIsNotAContract_Success() (gas: 309206) -OffRamp_trialExecute:test_trialExecute_Success() (gas: 283972) +OffRamp_trialExecute:test_trialExecute_Success() (gas: 283994) OffRamp_verify:test_Blessed_Success() (gas: 176664) -OffRamp_verify:test_NotBlessedWrongChainSelector_Success() (gas: 178732) +OffRamp_verify:test_NotBlessedWrongChainSelector_Success() (gas: 178754) OffRamp_verify:test_NotBlessed_Success() (gas: 141593) OffRamp_verify:test_TooManyLeaves_Revert() (gas: 51510) OnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 390336) diff --git a/contracts/src/v0.8/ccip/offRamp/OffRamp.sol b/contracts/src/v0.8/ccip/offRamp/OffRamp.sol index 20ce6115dc..d594597d18 100644 --- a/contracts/src/v0.8/ccip/offRamp/OffRamp.sol +++ b/contracts/src/v0.8/ccip/offRamp/OffRamp.sol @@ -68,6 +68,7 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { uint64 indexed sourceChainSelector, uint64 indexed sequenceNumber, bytes32 indexed messageId, + bytes32 messageHash, Internal.MessageExecutionState state, bytes returnData, uint256 gasUsed @@ -473,6 +474,7 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { sourceChainSelector, message.header.sequenceNumber, message.header.messageId, + hashedLeaves[i], newState, returnData, gasStart - gasleft() diff --git a/contracts/src/v0.8/ccip/test/NonceManager.t.sol b/contracts/src/v0.8/ccip/test/NonceManager.t.sol index 81da419253..ebb51a9619 100644 --- a/contracts/src/v0.8/ccip/test/NonceManager.t.sol +++ b/contracts/src/v0.8/ccip/test/NonceManager.t.sol @@ -395,6 +395,7 @@ contract NonceManager_OffRampUpgrade is OffRampSetup { SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber, messages[0].header.messageId, + Internal._hash(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -426,6 +427,7 @@ contract NonceManager_OffRampUpgrade is OffRampSetup { SOURCE_CHAIN_SELECTOR_3, messagesChain3[0].header.sequenceNumber, messagesChain3[0].header.messageId, + Internal._hash(messagesChain3[0], ON_RAMP_ADDRESS_3), Internal.MessageExecutionState.SUCCESS, "" ); @@ -507,6 +509,7 @@ contract NonceManager_OffRampUpgrade is OffRampSetup { SOURCE_CHAIN_SELECTOR_1, messagesMultiRamp[0].header.sequenceNumber, messagesMultiRamp[0].header.messageId, + Internal._hash(messagesMultiRamp[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -527,6 +530,7 @@ contract NonceManager_OffRampUpgrade is OffRampSetup { SOURCE_CHAIN_SELECTOR_1, messagesMultiRamp[0].header.sequenceNumber, messagesMultiRamp[0].header.messageId, + Internal._hash(messagesMultiRamp[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -561,6 +565,7 @@ contract NonceManager_OffRampUpgrade is OffRampSetup { SOURCE_CHAIN_SELECTOR_1, messagesMultiRamp[0].header.sequenceNumber, messagesMultiRamp[0].header.messageId, + Internal._hash(messagesMultiRamp[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -611,6 +616,7 @@ contract NonceManager_OffRampUpgrade is OffRampSetup { SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber, messages[0].header.messageId, + Internal._hash(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); diff --git a/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.sol b/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.sol index 4f9d0ac2c7..b22e4db9d4 100644 --- a/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.sol +++ b/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.sol @@ -105,74 +105,90 @@ contract MultiRampsE2E is OnRampSetup, OffRampSetup { function test_E2E_3MessagesMMultiOffRampSuccess_gas() public { vm.pauseGasMetering(); - IERC20 token0 = IERC20(s_sourceTokens[0]); - IERC20 token1 = IERC20(s_sourceTokens[1]); - uint256 balance0Pre = token0.balanceOf(OWNER); - uint256 balance1Pre = token1.balanceOf(OWNER); - // Send messages Internal.Any2EVMRampMessage[] memory messages1 = new Internal.Any2EVMRampMessage[](2); - messages1[0] = _sendRequest(1, SOURCE_CHAIN_SELECTOR, 1, s_metadataHash, s_sourceRouter, s_tokenAdminRegistry); - messages1[1] = _sendRequest(2, SOURCE_CHAIN_SELECTOR, 2, s_metadataHash, s_sourceRouter, s_tokenAdminRegistry); Internal.Any2EVMRampMessage[] memory messages2 = new Internal.Any2EVMRampMessage[](1); - messages2[0] = - _sendRequest(1, SOURCE_CHAIN_SELECTOR + 1, 1, s_metadataHash2, s_sourceRouter2, s_tokenAdminRegistry2); - uint256 expectedFee = s_sourceRouter.getFee(DEST_CHAIN_SELECTOR, _generateTokenMessage()); - // Asserts that the tokens have been sent and the fee has been paid. - assertEq( - balance0Pre - (messages1.length + messages2.length) * (i_tokenAmount0 + expectedFee), token0.balanceOf(OWNER) - ); - assertEq(balance1Pre - (messages1.length + messages2.length) * i_tokenAmount1, token1.balanceOf(OWNER)); + // Scoped to sending to reduce stack pressure + { + IERC20 token0 = IERC20(s_sourceTokens[0]); + IERC20 token1 = IERC20(s_sourceTokens[1]); - // Commit - bytes32[] memory hashedMessages1 = new bytes32[](2); - hashedMessages1[0] = messages1[0]._hash(abi.encode(address(s_onRamp))); - hashedMessages1[1] = messages1[1]._hash(abi.encode(address(s_onRamp))); - bytes32[] memory hashedMessages2 = new bytes32[](1); - hashedMessages2[0] = messages2[0]._hash(abi.encode(address(s_onRamp2))); + uint256 balance0Pre = token0.balanceOf(OWNER); + uint256 balance1Pre = token1.balanceOf(OWNER); - bytes32[] memory merkleRoots = new bytes32[](2); - merkleRoots[0] = MerkleHelper.getMerkleRoot(hashedMessages1); - merkleRoots[1] = MerkleHelper.getMerkleRoot(hashedMessages2); - - OffRamp.MerkleRoot[] memory roots = new OffRamp.MerkleRoot[](2); - roots[0] = OffRamp.MerkleRoot({ - sourceChainSelector: SOURCE_CHAIN_SELECTOR, - interval: OffRamp.Interval(messages1[0].header.sequenceNumber, messages1[1].header.sequenceNumber), - merkleRoot: merkleRoots[0] - }); - roots[1] = OffRamp.MerkleRoot({ - sourceChainSelector: SOURCE_CHAIN_SELECTOR + 1, - interval: OffRamp.Interval(messages2[0].header.sequenceNumber, messages2[0].header.sequenceNumber), - merkleRoot: merkleRoots[1] - }); + // Send messages + messages1[0] = _sendRequest(1, SOURCE_CHAIN_SELECTOR, 1, s_metadataHash, s_sourceRouter, s_tokenAdminRegistry); + messages1[1] = _sendRequest(2, SOURCE_CHAIN_SELECTOR, 2, s_metadataHash, s_sourceRouter, s_tokenAdminRegistry); + messages2[0] = + _sendRequest(1, SOURCE_CHAIN_SELECTOR + 1, 1, s_metadataHash2, s_sourceRouter2, s_tokenAdminRegistry2); - OffRamp.CommitReport memory report = - OffRamp.CommitReport({priceUpdates: _getEmptyPriceUpdates(), merkleRoots: roots}); + uint256 expectedFee = s_sourceRouter.getFee(DEST_CHAIN_SELECTOR, _generateTokenMessage()); + // Asserts that the tokens have been sent and the fee has been paid. + assertEq( + balance0Pre - (messages1.length + messages2.length) * (i_tokenAmount0 + expectedFee), token0.balanceOf(OWNER) + ); + assertEq(balance1Pre - (messages1.length + messages2.length) * i_tokenAmount1, token1.balanceOf(OWNER)); + } - vm.resumeGasMetering(); - _commit(report, ++s_latestSequenceNumber); - vm.pauseGasMetering(); + // Commit - s_mockRMN.setTaggedRootBlessed(IRMN.TaggedRoot({commitStore: address(s_offRamp), root: merkleRoots[0]}), true); - s_mockRMN.setTaggedRootBlessed(IRMN.TaggedRoot({commitStore: address(s_offRamp), root: merkleRoots[1]}), true); + bytes32[] memory merkleRoots = new bytes32[](2); - bytes32[] memory proofs = new bytes32[](0); - bytes32[] memory hashedLeaves = new bytes32[](1); - hashedLeaves[0] = merkleRoots[0]; - uint256 timestamp = s_offRamp.verify(SOURCE_CHAIN_SELECTOR, hashedLeaves, proofs, 2 ** 2 - 1); - assertEq(BLOCK_TIME, timestamp); - hashedLeaves[0] = merkleRoots[1]; - timestamp = s_offRamp.verify(SOURCE_CHAIN_SELECTOR + 1, hashedLeaves, proofs, 2 ** 2 - 1); - assertEq(BLOCK_TIME, timestamp); + // Scoped to commit to reduce stack pressure + { + bytes32[] memory hashedMessages1 = new bytes32[](2); + hashedMessages1[0] = messages1[0]._hash(abi.encode(address(s_onRamp))); + hashedMessages1[1] = messages1[1]._hash(abi.encode(address(s_onRamp))); + bytes32[] memory hashedMessages2 = new bytes32[](1); + hashedMessages2[0] = messages2[0]._hash(abi.encode(address(s_onRamp2))); + + merkleRoots[0] = MerkleHelper.getMerkleRoot(hashedMessages1); + merkleRoots[1] = MerkleHelper.getMerkleRoot(hashedMessages2); + + OffRamp.MerkleRoot[] memory roots = new OffRamp.MerkleRoot[](2); + roots[0] = OffRamp.MerkleRoot({ + sourceChainSelector: SOURCE_CHAIN_SELECTOR, + interval: OffRamp.Interval(messages1[0].header.sequenceNumber, messages1[1].header.sequenceNumber), + merkleRoot: merkleRoots[0] + }); + roots[1] = OffRamp.MerkleRoot({ + sourceChainSelector: SOURCE_CHAIN_SELECTOR + 1, + interval: OffRamp.Interval(messages2[0].header.sequenceNumber, messages2[0].header.sequenceNumber), + merkleRoot: merkleRoots[1] + }); + + OffRamp.CommitReport memory report = + OffRamp.CommitReport({priceUpdates: _getEmptyPriceUpdates(), merkleRoots: roots}); + + vm.resumeGasMetering(); + _commit(report, ++s_latestSequenceNumber); + vm.pauseGasMetering(); + } - // We change the block time so when execute would e.g. use the current - // block time instead of the committed block time the value would be - // incorrect in the checks below. - vm.warp(BLOCK_TIME + 2000); + // Scoped to RMN and verify to reduce stack pressure + { + s_mockRMN.setTaggedRootBlessed(IRMN.TaggedRoot({commitStore: address(s_offRamp), root: merkleRoots[0]}), true); + s_mockRMN.setTaggedRootBlessed(IRMN.TaggedRoot({commitStore: address(s_offRamp), root: merkleRoots[1]}), true); + + bytes32[] memory proofs = new bytes32[](0); + bytes32[] memory hashedLeaves = new bytes32[](1); + hashedLeaves[0] = merkleRoots[0]; + + uint256 timestamp = s_offRamp.verify(SOURCE_CHAIN_SELECTOR, hashedLeaves, proofs, 2 ** 2 - 1); + assertEq(BLOCK_TIME, timestamp); + hashedLeaves[0] = merkleRoots[1]; + timestamp = s_offRamp.verify(SOURCE_CHAIN_SELECTOR + 1, hashedLeaves, proofs, 2 ** 2 - 1); + assertEq(BLOCK_TIME, timestamp); + + // We change the block time so when execute would e.g. use the current + // block time instead of the committed block time the value would be + // incorrect in the checks below. + vm.warp(BLOCK_TIME + 2000); + } // Execute + Internal.ExecutionReportSingleChain[] memory reports = new Internal.ExecutionReportSingleChain[](2); reports[0] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR, messages1); reports[1] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR + 1, messages2); @@ -185,6 +201,7 @@ contract MultiRampsE2E is OnRampSetup, OffRampSetup { SOURCE_CHAIN_SELECTOR, messages1[0].header.sequenceNumber, messages1[0].header.messageId, + messages1[0]._hash(abi.encode(address(s_onRamp))), Internal.MessageExecutionState.SUCCESS, "" ); @@ -193,6 +210,7 @@ contract MultiRampsE2E is OnRampSetup, OffRampSetup { SOURCE_CHAIN_SELECTOR, messages1[1].header.sequenceNumber, messages1[1].header.messageId, + messages1[1]._hash(abi.encode(address(s_onRamp))), Internal.MessageExecutionState.SUCCESS, "" ); @@ -201,6 +219,7 @@ contract MultiRampsE2E is OnRampSetup, OffRampSetup { SOURCE_CHAIN_SELECTOR + 1, messages2[0].header.sequenceNumber, messages2[0].header.messageId, + messages2[0]._hash(abi.encode(address(s_onRamp2))), Internal.MessageExecutionState.SUCCESS, "" ); @@ -215,9 +234,7 @@ contract MultiRampsE2E is OnRampSetup, OffRampSetup { TokenAdminRegistry tokenAdminRegistry ) public returns (Internal.Any2EVMRampMessage memory) { Client.EVM2AnyMessage memory message = _generateTokenMessage(); - uint256 expectedFee = router.getFee(DEST_CHAIN_SELECTOR, message); - - IERC20(s_sourceTokens[0]).approve(address(router), i_tokenAmount0 + expectedFee); + IERC20(s_sourceTokens[0]).approve(address(router), i_tokenAmount0 + router.getFee(DEST_CHAIN_SELECTOR, message)); IERC20(s_sourceTokens[1]).approve(address(router), i_tokenAmount1); message.receiver = abi.encode(address(s_receiver)); @@ -227,7 +244,7 @@ contract MultiRampsE2E is OnRampSetup, OffRampSetup { DEST_CHAIN_SELECTOR, expectedSeqNum, nonce, - expectedFee, + router.getFee(DEST_CHAIN_SELECTOR, message), OWNER, metadataHash, tokenAdminRegistry @@ -240,8 +257,6 @@ contract MultiRampsE2E is OnRampSetup, OffRampSetup { router.ccipSend(DEST_CHAIN_SELECTOR, message); vm.pauseGasMetering(); - uint256 gasLimit = s_feeQuoter.parseEVMExtraArgsFromBytes(msgEvent.extraArgs, DEST_CHAIN_SELECTOR).gasLimit; - return Internal.Any2EVMRampMessage({ header: Internal.RampMessageHeader({ messageId: msgEvent.header.messageId, @@ -253,7 +268,7 @@ contract MultiRampsE2E is OnRampSetup, OffRampSetup { sender: abi.encode(msgEvent.sender), data: msgEvent.data, receiver: abi.decode(msgEvent.receiver, (address)), - gasLimit: gasLimit, + gasLimit: s_feeQuoter.parseEVMExtraArgsFromBytes(msgEvent.extraArgs, DEST_CHAIN_SELECTOR).gasLimit, tokenAmounts: msgEvent.tokenAmounts }); } diff --git a/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol index b3fb5de5a2..9167f3f075 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol @@ -346,6 +346,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { messages[0].header.sourceChainSelector, messages[0].header.sequenceNumber, messages[0].header.messageId, + Internal._hash(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -361,6 +362,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { messages[0].header.sourceChainSelector, messages[0].header.sequenceNumber, messages[0].header.messageId, + Internal._hash(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -381,6 +383,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { messages[0].header.sourceChainSelector, messages[0].header.sequenceNumber, messages[0].header.messageId, + Internal._hash(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -402,6 +405,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { messages[0].header.sourceChainSelector, messages[0].header.sequenceNumber, messages[0].header.messageId, + Internal._hash(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -455,6 +459,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { messages[0].header.sourceChainSelector, messages[0].header.sequenceNumber, messages[0].header.messageId, + Internal._hash(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.FAILURE, abi.encodeWithSelector( OffRamp.ReceiverError.selector, @@ -495,6 +500,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { messages[0].header.sourceChainSelector, messages[0].header.sequenceNumber, messages[0].header.messageId, + Internal._hash(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -510,6 +516,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber, messages[0].header.messageId, + Internal._hash(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -532,6 +539,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber, messages[0].header.messageId, + Internal._hash(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -557,6 +565,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { messages[0].header.sourceChainSelector, messages[0].header.sequenceNumber, messages[0].header.messageId, + Internal._hash(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -576,6 +585,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { messages[0].header.sourceChainSelector, messages[0].header.sequenceNumber, messages[0].header.messageId, + Internal._hash(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -598,6 +608,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber, messages[0].header.messageId, + Internal._hash(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -606,6 +617,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { SOURCE_CHAIN_SELECTOR_1, messages[1].header.sequenceNumber, messages[1].header.messageId, + Internal._hash(messages[1], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -628,6 +640,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber, messages[0].header.messageId, + Internal._hash(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -635,6 +648,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { SOURCE_CHAIN_SELECTOR_1, messages[1].header.sequenceNumber, messages[1].header.messageId, + Internal._hash(messages[1], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -676,6 +690,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { SOURCE_CHAIN_SELECTOR_1, messages[i].header.sequenceNumber, messages[i].header.messageId, + Internal._hash(messages[i], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -702,6 +717,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber, messages[0].header.messageId, + Internal._hash(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.FAILURE, abi.encodeWithSelector( OffRamp.TokenHandlingError.selector, @@ -891,6 +907,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { messages[0].header.sourceChainSelector, messages[0].header.sequenceNumber, messages[0].header.messageId, + Internal._hash(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.FAILURE, abi.encodeWithSelector(CallWithExactGas.NotEnoughGasForCall.selector) ); @@ -914,6 +931,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { messages[0].header.sourceChainSelector, messages[0].header.sequenceNumber, messages[0].header.messageId, + Internal._hash(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.FAILURE, abi.encodeWithSelector( OffRamp.ReceiverError.selector, @@ -1108,6 +1126,7 @@ contract OffRamp_batchExecute is OffRampSetup { messages[0].header.sourceChainSelector, messages[0].header.sequenceNumber, messages[0].header.messageId, + Internal._hash(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -1134,6 +1153,7 @@ contract OffRamp_batchExecute is OffRampSetup { messages1[0].header.sourceChainSelector, messages1[0].header.sequenceNumber, messages1[0].header.messageId, + Internal._hash(messages1[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -1142,6 +1162,7 @@ contract OffRamp_batchExecute is OffRampSetup { messages1[1].header.sourceChainSelector, messages1[1].header.sequenceNumber, messages1[1].header.messageId, + Internal._hash(messages1[1], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -1150,6 +1171,7 @@ contract OffRamp_batchExecute is OffRampSetup { messages2[0].header.sourceChainSelector, messages2[0].header.sequenceNumber, messages2[0].header.messageId, + Internal._hash(messages2[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -1177,6 +1199,7 @@ contract OffRamp_batchExecute is OffRampSetup { messages1[0].header.sourceChainSelector, messages1[0].header.sequenceNumber, messages1[0].header.messageId, + Internal._hash(messages1[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -1185,6 +1208,7 @@ contract OffRamp_batchExecute is OffRampSetup { messages1[1].header.sourceChainSelector, messages1[1].header.sequenceNumber, messages1[1].header.messageId, + Internal._hash(messages1[1], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -1193,6 +1217,7 @@ contract OffRamp_batchExecute is OffRampSetup { messages2[0].header.sourceChainSelector, messages2[0].header.sequenceNumber, messages2[0].header.messageId, + Internal._hash(messages2[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -1222,6 +1247,7 @@ contract OffRamp_batchExecute is OffRampSetup { messages[0].header.sourceChainSelector, messages[0].header.sequenceNumber, messages[0].header.messageId, + Internal._hash(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -1294,6 +1320,7 @@ contract OffRamp_manuallyExecute is OffRampSetup { SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber, messages[0].header.messageId, + Internal._hash(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -1317,6 +1344,7 @@ contract OffRamp_manuallyExecute is OffRampSetup { SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber, messages[0].header.messageId, + Internal._hash(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -1343,6 +1371,7 @@ contract OffRamp_manuallyExecute is OffRampSetup { SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber, messages[0].header.messageId, + Internal._hash(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.FAILURE, abi.encodeWithSelector( OffRamp.ReceiverError.selector, abi.encodeWithSelector(MaybeRevertMessageReceiver.CustomError.selector, "") @@ -1397,6 +1426,7 @@ contract OffRamp_manuallyExecute is OffRampSetup { SOURCE_CHAIN_SELECTOR_1, messages1[j].header.sequenceNumber, messages1[j].header.messageId, + Internal._hash(messages1[j], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -1407,6 +1437,7 @@ contract OffRamp_manuallyExecute is OffRampSetup { SOURCE_CHAIN_SELECTOR_1, messages2[k].header.sequenceNumber, messages2[k].header.messageId, + Internal._hash(messages2[k], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -1430,6 +1461,7 @@ contract OffRamp_manuallyExecute is OffRampSetup { SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber, messages[0].header.messageId, + Internal._hash(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -1438,6 +1470,7 @@ contract OffRamp_manuallyExecute is OffRampSetup { SOURCE_CHAIN_SELECTOR_1, messages[1].header.sequenceNumber, messages[1].header.messageId, + Internal._hash(messages[1], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.FAILURE, abi.encodeWithSelector( OffRamp.ReceiverError.selector, @@ -1449,6 +1482,7 @@ contract OffRamp_manuallyExecute is OffRampSetup { SOURCE_CHAIN_SELECTOR_1, messages[2].header.sequenceNumber, messages[2].header.messageId, + Internal._hash(messages[2], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -1469,6 +1503,7 @@ contract OffRamp_manuallyExecute is OffRampSetup { SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber, messages[0].header.messageId, + Internal._hash(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -1487,6 +1522,7 @@ contract OffRamp_manuallyExecute is OffRampSetup { SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber, messages[0].header.messageId, + Internal._hash(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.FAILURE, abi.encodeWithSelector(OffRamp.ReceiverError.selector, "") ); @@ -1504,6 +1540,7 @@ contract OffRamp_manuallyExecute is OffRampSetup { SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber, messages[0].header.messageId, + Internal._hash(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -1693,6 +1730,7 @@ contract OffRamp_manuallyExecute is OffRampSetup { SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber, messages[0].header.messageId, + Internal._hash(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -1729,6 +1767,7 @@ contract OffRamp_execute is OffRampSetup { SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber, messages[0].header.messageId, + Internal._hash(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -1757,6 +1796,7 @@ contract OffRamp_execute is OffRampSetup { messages1[0].header.sourceChainSelector, messages1[0].header.sequenceNumber, messages1[0].header.messageId, + Internal._hash(messages1[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -1765,6 +1805,7 @@ contract OffRamp_execute is OffRampSetup { messages1[1].header.sourceChainSelector, messages1[1].header.sequenceNumber, messages1[1].header.messageId, + Internal._hash(messages1[1], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -1773,6 +1814,7 @@ contract OffRamp_execute is OffRampSetup { messages2[0].header.sourceChainSelector, messages2[0].header.sequenceNumber, messages2[0].header.messageId, + Internal._hash(messages2[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -1803,6 +1845,7 @@ contract OffRamp_execute is OffRampSetup { reports[i].messages[j].header.sourceChainSelector, reports[i].messages[j].header.sequenceNumber, reports[i].messages[j].header.messageId, + Internal._hash(reports[i].messages[j], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -1838,6 +1881,7 @@ contract OffRamp_execute is OffRampSetup { messages1[0].header.sourceChainSelector, messages1[0].header.sequenceNumber, messages1[0].header.messageId, + Internal._hash(messages1[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.FAILURE, abi.encodeWithSelector( IMessageInterceptor.MessageValidationError.selector, @@ -1849,6 +1893,7 @@ contract OffRamp_execute is OffRampSetup { messages1[1].header.sourceChainSelector, messages1[1].header.sequenceNumber, messages1[1].header.messageId, + Internal._hash(messages1[1], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -1857,6 +1902,7 @@ contract OffRamp_execute is OffRampSetup { messages2[0].header.sourceChainSelector, messages2[0].header.sequenceNumber, messages2[0].header.messageId, + Internal._hash(messages2[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.FAILURE, abi.encodeWithSelector( IMessageInterceptor.MessageValidationError.selector, diff --git a/contracts/src/v0.8/ccip/test/offRamp/OffRampSetup.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRampSetup.t.sol index ff051cdd21..403655f10a 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/OffRampSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRampSetup.t.sol @@ -30,7 +30,7 @@ contract OffRampSetup is FeeQuoterSetup, MultiOCR3BaseSetup { uint64 internal constant SOURCE_CHAIN_SELECTOR_2 = 6433500567565415381; uint64 internal constant SOURCE_CHAIN_SELECTOR_3 = 4051577828743386545; bytes32 internal constant EXECUTION_STATE_CHANGE_TOPIC_HASH = - keccak256("ExecutionStateChanged(uint64,uint64,bytes32,uint8,bytes,uint256)"); + keccak256("ExecutionStateChanged(uint64,uint64,bytes32,bytes32,uint8,bytes,uint256)"); bytes internal constant ON_RAMP_ADDRESS_1 = abi.encode(ON_RAMP_ADDRESS); bytes internal constant ON_RAMP_ADDRESS_2 = abi.encode(0xaA3f843Cf8E33B1F02dd28303b6bD87B1aBF8AE4); @@ -484,6 +484,7 @@ contract OffRampSetup is FeeQuoterSetup, MultiOCR3BaseSetup { uint64 sourceChainSelector, uint64 sequenceNumber, bytes32 messageId, + bytes32 messageHash, Internal.MessageExecutionState state, bytes memory returnData ) public { @@ -493,11 +494,13 @@ contract OffRampSetup is FeeQuoterSetup, MultiOCR3BaseSetup { uint64 logSourceChainSelector = uint64(uint256(logs[i].topics[1])); uint64 logSequenceNumber = uint64(uint256(logs[i].topics[2])); bytes32 logMessageId = bytes32(logs[i].topics[3]); - (uint8 logState, bytes memory logReturnData,) = abi.decode(logs[i].data, (uint8, bytes, uint256)); + (bytes32 logMessageHash, uint8 logState, bytes memory logReturnData,) = + abi.decode(logs[i].data, (bytes32, uint8, bytes, uint256)); if (logMessageId == messageId) { assertEq(logSourceChainSelector, sourceChainSelector); assertEq(logSequenceNumber, sequenceNumber); assertEq(logMessageId, messageId); + assertEq(logMessageHash, messageHash); assertEq(logState, uint8(state)); assertEq(logReturnData, returnData); } diff --git a/core/gethwrappers/ccip/generated/offramp/offramp.go b/core/gethwrappers/ccip/generated/offramp/offramp.go index 2ce6804b3c..65795e0626 100644 --- a/core/gethwrappers/ccip/generated/offramp/offramp.go +++ b/core/gethwrappers/ccip/generated/offramp/offramp.go @@ -164,8 +164,8 @@ type OffRampUnblessedRoot struct { } var OffRampMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CanOnlySelfCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"actual\",\"type\":\"bytes32\"}],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ExecutionError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"ForkedChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enumMultiOCR3Base.InvalidConfigErrorType\",\"name\":\"errorType\",\"type\":\"uint8\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"got\",\"type\":\"uint256\"}],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidEVMAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"internalType\":\"structOffRamp.Interval\",\"name\":\"interval\",\"type\":\"tuple\"}],\"name\":\"InvalidInterval\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"newLimit\",\"type\":\"uint256\"}],\"name\":\"InvalidManualExecutionGasLimit\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"messageDestChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidMessageDestChainSelector\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"newState\",\"type\":\"uint8\"}],\"name\":\"InvalidNewState\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRoot\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidStaticConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LeavesCannotBeEmpty\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ManualExecutionGasLimitMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"ManualExecutionNotYetEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"errorReason\",\"type\":\"bytes\"}],\"name\":\"MessageValidationError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonUniqueSignatures\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"notPool\",\"type\":\"address\"}],\"name\":\"NotACompatiblePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OracleCannotBeZeroAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ReceiverError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountReleased\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePre\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePost\",\"type\":\"uint256\"}],\"name\":\"ReleaseOrMintBalanceMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"name\":\"RootAlreadyCommitted\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"RootNotCommitted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignaturesOutOfRegistration\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"StaleCommitReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"StaticConfigCannotBeChanged\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"TokenDataMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"TokenHandlingError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnexpectedTokenData\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"WrongMessageLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WrongNumberOfSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroChainSelectorNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"AlreadyAttempted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"internalType\":\"structOffRamp.Interval\",\"name\":\"interval\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structOffRamp.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"report\",\"type\":\"tuple\"}],\"name\":\"CommitReportAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"DynamicConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"name\":\"ExecutionStateChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"RootRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"SkippedAlreadyExecutedMessage\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"sourceConfig\",\"type\":\"tuple\"}],\"name\":\"SourceChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainSelectorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"}],\"name\":\"StaticConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigUpdates\",\"type\":\"tuple[]\"}],\"name\":\"applySourceChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"destTokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structClient.Any2EVMMessage\",\"name\":\"\",\"type\":\"tuple\"}],\"name\":\"ccipReceive\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"rawVs\",\"type\":\"bytes32\"}],\"name\":\"commit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"execute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"bytes[]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[]\"}],\"name\":\"executeSingleMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"getExecutionState\",\"outputs\":[{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLatestPriceSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"getMerkleRoot\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"getSourceChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"isBlessed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"latestConfigDetails\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"n\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"}],\"internalType\":\"structMultiOCR3Base.ConfigInfo\",\"name\":\"configInfo\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfig\",\"name\":\"ocrConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage[]\",\"name\":\"messages\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[][]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[][]\"},{\"internalType\":\"bytes32[]\",\"name\":\"proofs\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"proofFlagBits\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.ExecutionReportSingleChain[]\",\"name\":\"reports\",\"type\":\"tuple[]\"},{\"internalType\":\"uint256[][]\",\"name\":\"gasLimitOverrides\",\"type\":\"uint256[][]\"}],\"name\":\"manuallyExecute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structOffRamp.UnblessedRoot[]\",\"name\":\"rootToReset\",\"type\":\"tuple[]\"}],\"name\":\"resetUnblessedRoots\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"setDynamicConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfigArgs[]\",\"name\":\"ocrConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"setOCR3Configs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x6101206040523480156200001257600080fd5b5060405162006c1a38038062006c1a8339810160408190526200003591620008c7565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf81620001fa565b5050466080525060208301516001600160a01b03161580620000ec575060408301516001600160a01b0316155b8062000103575060608301516001600160a01b0316155b1562000122576040516342bcdf7f60e11b815260040160405180910390fd5b82516001600160401b03166000036200014e5760405163c656089560e01b815260040160405180910390fd5b82516001600160401b0390811660a052602080850180516001600160a01b0390811660c05260408088018051831660e0526060808a01805185166101005283518b519098168852945184169587019590955251821690850152905116908201527f683eb52ee924eb817377cfa8f41f238f4bb7a877da5267869dfffbad85f564d89060800160405180910390a1620001e682620002a5565b620001f181620003c1565b50505062000c67565b336001600160a01b03821603620002545760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b0316620002ce576040516342bcdf7f60e11b815260040160405180910390fd5b80516004805460208085018051604080880180516060808b0180516001600160a01b039b8c166001600160c01b0319909a168a17600160a01b63ffffffff98891602176001600160c01b0316600160c01b948816949094026001600160e01b031693909317600160e01b93871693909302929092179098556080808b018051600580546001600160a01b031916918d169190911790558451988952955185169688019690965290518316918601919091525116938301939093529151909216908201527fa55bd56595c45f517e5967a3067f3dca684445a3080e7c04a4e0d5a40cda627d9060a00160405180910390a150565b60005b815181101562000666576000828281518110620003e557620003e562000a1d565b60200260200101519050600081602001519050806001600160401b0316600003620004235760405163c656089560e01b815260040160405180910390fd5b81516001600160a01b03166200044c576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160401b0381166000908152600660205260408120600181018054919291620004789062000a33565b80601f0160208091040260200160405190810160405280929190818152602001828054620004a69062000a33565b8015620004f75780601f10620004cb57610100808354040283529160200191620004f7565b820191906000526020600020905b815481529060010190602001808311620004d957829003601f168201915b5050505050905060008460600151905081516000036200059e57805160000362000534576040516342bcdf7f60e11b815260040160405180910390fd5b6001830162000544828262000ac4565b508254600160a81b600160e81b031916600160a81b1783556040516001600160401b03851681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1620005d9565b8080519060200120828051906020012014620005d95760405163c39a620560e01b81526001600160401b038516600482015260240162000083565b604080860151845487516001600160a01b03166001600160a01b0319921515600160a01b02929092166001600160a81b031990911617178455516001600160401b038516907f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b906200064d90869062000b90565b60405180910390a25050505050806001019050620003c4565b5050565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b0381118282101715620006a557620006a56200066a565b60405290565b604051601f8201601f191681016001600160401b0381118282101715620006d657620006d66200066a565b604052919050565b80516001600160401b0381168114620006f657600080fd5b919050565b6001600160a01b03811681146200071157600080fd5b50565b805163ffffffff81168114620006f657600080fd5b6000601f83601f8401126200073d57600080fd5b825160206001600160401b03808311156200075c576200075c6200066a565b8260051b6200076d838201620006ab565b93845286810183019383810190898611156200078857600080fd5b84890192505b85831015620008ba57825184811115620007a85760008081fd5b89016080601f19828d038101821315620007c25760008081fd5b620007cc62000680565b88840151620007db81620006fb565b81526040620007ec858201620006de565b8a8301526060808601518015158114620008065760008081fd5b838301529385015193898511156200081e5760008081fd5b84860195508f603f8701126200083657600094508485fd5b8a8601519450898511156200084f576200084f6200066a565b620008608b858f88011601620006ab565b93508484528f82868801011115620008785760008081fd5b60005b8581101562000898578681018301518582018d01528b016200087b565b5060009484018b0194909452509182015283525091840191908401906200078e565b9998505050505050505050565b6000806000838503610140811215620008df57600080fd5b6080811215620008ee57600080fd5b620008f862000680565b6200090386620006de565b815260208601516200091581620006fb565b602082015260408601516200092a81620006fb565b604082015260608601516200093f81620006fb565b6060820152935060a0607f19820112156200095957600080fd5b5060405160a081016001600160401b0380821183831017156200098057620009806200066a565b81604052608087015191506200099682620006fb565b818352620009a760a0880162000714565b6020840152620009ba60c0880162000714565b6040840152620009cd60e0880162000714565b60608401526101008701519150620009e582620006fb565b608083018290526101208701519294508083111562000a0357600080fd5b505062000a138682870162000729565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b600181811c9082168062000a4857607f821691505b60208210810362000a6957634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111562000abf576000816000526020600020601f850160051c8101602086101562000a9a5750805b601f850160051c820191505b8181101562000abb5782815560010162000aa6565b5050505b505050565b81516001600160401b0381111562000ae05762000ae06200066a565b62000af88162000af1845462000a33565b8462000a6f565b602080601f83116001811462000b30576000841562000b175750858301515b600019600386901b1c1916600185901b17855562000abb565b600085815260208120601f198616915b8281101562000b615788860151825594840194600190910190840162000b40565b508582101562000b805787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b602080825282546001600160a01b0381168383015260a081901c60ff161515604084015260a81c6001600160401b0316606083015260808083015260018084018054600093929190849062000be58162000a33565b8060a089015260c0600183166000811462000c09576001811462000c265762000c58565b60ff19841660c08b015260c083151560051b8b0101945062000c58565b85600052602060002060005b8481101562000c4f5781548c820185015290880190890162000c32565b8b0160c0019550505b50929998505050505050505050565b60805160a05160c05160e05161010051615f4462000cd6600039600081816102660152612a010152600081816102370152612ef40152600081816102080152818161142b015261196d0152600081816101d801526125f00152600081816117f3015261183f0152615f446000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806385572ffb116100d8578063ccd37ba31161008c578063f2fde38b11610066578063f2fde38b14610583578063f716f99f14610596578063ff888fb1146105a957600080fd5b8063ccd37ba31461050b578063d2a15d3514610550578063e9d68a8e1461056357600080fd5b8063991a5018116100bd578063991a5018146104c5578063a80036b4146104d8578063c673e584146104eb57600080fd5b806385572ffb1461049c5780638da5cb5b146104aa57600080fd5b8063311cd5131161012f5780635e36480c116101145780635e36480c146103785780637437ff9f1461039857806379ba50971461049457600080fd5b8063311cd513146103495780633f4b04aa1461035c57600080fd5b806306285c691161016057806306285c69146101a4578063181f5a77146102ed5780632d04ab761461033657600080fd5b806304666f9c1461017c57806305d938b514610191575b600080fd5b61018f61018a3660046140af565b6105cc565b005b61018f61019f36600461473b565b6105e0565b61029660408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316815250905090565b6040516102e49190815167ffffffffffffffff1681526020808301516001600160a01b0390811691830191909152604080840151821690830152606092830151169181019190915260800190565b60405180910390f35b6103296040518060400160405280601181526020017f4f666652616d7020312e362e302d64657600000000000000000000000000000081525081565b6040516102e491906148b6565b61018f610344366004614961565b610785565b61018f610357366004614a14565b610b5c565b60095460405167ffffffffffffffff90911681526020016102e4565b61038b610386366004614a68565b610bc5565b6040516102e49190614ac5565b6104376040805160a081018252600080825260208201819052918101829052606081018290526080810191909152506040805160a0810182526004546001600160a01b03808216835263ffffffff600160a01b83048116602085015278010000000000000000000000000000000000000000000000008304811694840194909452600160e01b9091049092166060820152600554909116608082015290565b6040516102e49190600060a0820190506001600160a01b03808451168352602084015163ffffffff808216602086015280604087015116604086015280606087015116606086015250508060808501511660808401525092915050565b61018f610c1b565b61018f610177366004614ad3565b6000546040516001600160a01b0390911681526020016102e4565b61018f6104d3366004614b22565b610cd9565b61018f6104e6366004614b96565b610cea565b6104fe6104f9366004614c03565b61105d565b6040516102e49190614c63565b610542610519366004614cd8565b67ffffffffffffffff919091166000908152600860209081526040808320938352929052205490565b6040519081526020016102e4565b61018f61055e366004614d02565b6111bb565b610576610571366004614d77565b611275565b6040516102e49190614d92565b61018f610591366004614de0565b611382565b61018f6105a4366004614e65565b611393565b6105bc6105b7366004614fa3565b6113d5565b60405190151581526020016102e4565b6105d4611496565b6105dd816114f2565b50565b6105e86117f0565b815181518114610624576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8181101561077557600084828151811061064357610643614fbc565b6020026020010151905060008160200151519050600085848151811061066b5761066b614fbc565b60200260200101519050805182146106af576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b828110156107665760008282815181106106ce576106ce614fbc565b602002602001015190508060001461075d57846020015182815181106106f6576106f6614fbc565b60200260200101516080015181101561075d5784516040517fc8e9605100000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260248101839052604481018290526064015b60405180910390fd5b506001016106b2565b50505050806001019050610627565b506107808383611871565b505050565b600061079387890189615142565b805151519091501515806107ac57508051602001515115155b156108ac5760095460208a01359067ffffffffffffffff8083169116101561086b576009805467ffffffffffffffff191667ffffffffffffffff83161790556004805483516040517f3937306f0000000000000000000000000000000000000000000000000000000081526001600160a01b0390921692633937306f9261083492910161536a565b600060405180830381600087803b15801561084e57600080fd5b505af1158015610862573d6000803e3d6000fd5b505050506108aa565b8160200151516000036108aa576040517f2261116700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b60005b816020015151811015610aa5576000826020015182815181106108d4576108d4614fbc565b602002602001015190506000816000015190506108f081611921565b60006108fb82611a23565b602084015151815491925067ffffffffffffffff908116600160a81b9092041614158061093f575060208084015190810151905167ffffffffffffffff9182169116115b1561097f57825160208401516040517feefb0cac00000000000000000000000000000000000000000000000000000000815261075492919060040161537d565b6040830151806109bb576040517f504570e300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b835167ffffffffffffffff16600090815260086020908152604080832084845290915290205415610a2e5783516040517f32cf0cbf00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260248101829052604401610754565b6020808501510151610a419060016153c8565b82547fffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffff16600160a81b67ffffffffffffffff9283160217909255925116600090815260086020908152604080832094835293905291909120429055506001016108af565b507f3a3950e13dd607cc37980db0ef14266c40d2bba9c01b2e44bfe549808883095d81604051610ad591906153f0565b60405180910390a1610b5160008a8a8a8a8a8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808e0282810182019093528d82529093508d92508c9182918501908490808284376000920191909152508b9250611a8a915050565b505050505050505050565b610b9c610b6b8284018461548d565b6040805160008082526020820190925290610b96565b6060815260200190600190039081610b815790505b50611871565b604080516000808252602082019092529050610bbf600185858585866000611a8a565b50505050565b6000610bd3600160046154c2565b6002610be06080856154eb565b67ffffffffffffffff16610bf49190615512565b610bfe8585611e01565b901c166003811115610c1257610c12614a9b565b90505b92915050565b6001546001600160a01b03163314610c755760405162461bcd60e51b815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610754565b600080543373ffffffffffffffffffffffffffffffffffffffff19808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610ce1611496565b6105dd81611e48565b333014610d23576040517f371a732800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160008082526020820190925281610d60565b6040805180820190915260008082526020820152815260200190600190039081610d395790505b5060a08501515190915015610d9457610d918460a00151856020015186606001518760000151602001518787611fae565b90505b6040805160a0810182528551518152855160209081015167ffffffffffffffff1681830152808701518351600094840192610dd09291016148b6565b60408051601f19818403018152918152908252878101516020830152018390526005549091506001600160a01b03168015610edd576040517f08d450a10000000000000000000000000000000000000000000000000000000081526001600160a01b038216906308d450a190610e4a9085906004016155cb565b600060405180830381600087803b158015610e6457600080fd5b505af1925050508015610e75575060015b610edd573d808015610ea3576040519150601f19603f3d011682016040523d82523d6000602084013e610ea8565b606091505b50806040517f09c2532500000000000000000000000000000000000000000000000000000000815260040161075491906148b6565b604086015151158015610ef257506080860151155b80610f09575060608601516001600160a01b03163b155b80610f4957506060860151610f47906001600160a01b03167f85572ffb000000000000000000000000000000000000000000000000000000006120cd565b155b15610f5657505050505050565b855160209081015167ffffffffffffffff1660009081526006909152604080822054608089015160608a015192517f3cf9798300000000000000000000000000000000000000000000000000000000815284936001600160a01b0390931692633cf9798392610fce92899261138892916004016155de565b6000604051808303816000875af1158015610fed573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611015919081019061561a565b50915091508161105357806040517f0a8d6e8c00000000000000000000000000000000000000000000000000000000815260040161075491906148b6565b5050505050505050565b6110a06040805160e081019091526000606082018181526080830182905260a0830182905260c08301919091528190815260200160608152602001606081525090565b60ff808316600090815260026020818152604092839020835160e081018552815460608201908152600183015480881660808401526101008104881660a0840152620100009004909616151560c08201529485529182018054845181840281018401909552808552929385830193909283018282801561114957602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161112b575b50505050508152602001600382018054806020026020016040519081016040528092919081815260200182805480156111ab57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161118d575b5050505050815250509050919050565b6111c3611496565b60005b818110156107805760008383838181106111e2576111e2614fbc565b9050604002018036038101906111f891906156b0565b905061120781602001516113d5565b61126c57805167ffffffffffffffff1660009081526008602090815260408083208285018051855290835281842093909355915191519182527f202f1139a3e334b6056064c0e9b19fd07e44a88d8f6e5ded571b24cf8c371f12910160405180910390a15b506001016111c6565b604080516080808201835260008083526020808401829052838501829052606080850181905267ffffffffffffffff878116845260068352928690208651948501875280546001600160a01b0381168652600160a01b810460ff16151593860193909352600160a81b909204909216948301949094526001840180549394929391840191611302906156e9565b80601f016020809104026020016040519081016040528092919081815260200182805461132e906156e9565b80156111ab5780601f10611350576101008083540402835291602001916111ab565b820191906000526020600020905b81548152906001019060200180831161135e57505050919092525091949350505050565b61138a611496565b6105dd816120e9565b61139b611496565b60005b81518110156113d1576113c98282815181106113bc576113bc614fbc565b602002602001015161219f565b60010161139e565b5050565b6040805180820182523081526020810183815291517f4d61677100000000000000000000000000000000000000000000000000000000815290516001600160a01b039081166004830152915160248201526000917f00000000000000000000000000000000000000000000000000000000000000001690634d61677190604401602060405180830381865afa158015611472573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c159190615723565b6000546001600160a01b031633146114f05760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610754565b565b60005b81518110156113d157600082828151811061151257611512614fbc565b602002602001015190506000816020015190508067ffffffffffffffff16600003611569576040517fc656089500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81516001600160a01b0316611591576040516342bcdf7f60e11b815260040160405180910390fd5b67ffffffffffffffff811660009081526006602052604081206001810180549192916115bc906156e9565b80601f01602080910402602001604051908101604052809291908181526020018280546115e8906156e9565b80156116355780601f1061160a57610100808354040283529160200191611635565b820191906000526020600020905b81548152906001019060200180831161161857829003601f168201915b5050505050905060008460600151905081516000036116ed578051600003611670576040516342bcdf7f60e11b815260040160405180910390fd5b6001830161167e8282615788565b5082547fffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffff16600160a81b17835560405167ffffffffffffffff851681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1611740565b8080519060200120828051906020012014611740576040517fc39a620500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff85166004820152602401610754565b604080860151845487516001600160a01b031673ffffffffffffffffffffffffffffffffffffffff19921515600160a01b02929092167fffffffffffffffffffffff000000000000000000000000000000000000000000909116171784555167ffffffffffffffff8516907f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b906117d8908690615848565b60405180910390a250505050508060010190506114f5565b467f0000000000000000000000000000000000000000000000000000000000000000146114f0576040517f0f01ce850000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000006004820152466024820152604401610754565b81516000036118ab576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160408051600080825260208201909252911591905b845181101561191a576119128582815181106118e0576118e0614fbc565b60200260200101518461190c578583815181106118ff576118ff614fbc565b60200260200101516124e3565b836124e3565b6001016118c2565b5050505050565b6040517f2cbc26bb000000000000000000000000000000000000000000000000000000008152608082901b77ffffffffffffffff000000000000000000000000000000001660048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632cbc26bb90602401602060405180830381865afa1580156119bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119e09190615723565b156105dd576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610754565b67ffffffffffffffff811660009081526006602052604081208054600160a01b900460ff16610c15576040517fed053c5900000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610754565b60ff87811660009081526002602090815260408083208151608081018352815481526001909101548086169382019390935261010083048516918101919091526201000090910490921615156060830152873590611ae98760a4615916565b9050826060015115611b31578451611b02906020615512565b8651611b0f906020615512565b611b1a9060a0615916565b611b249190615916565b611b2e9082615916565b90505b368114611b73576040517f8e1192e100000000000000000000000000000000000000000000000000000000815260048101829052366024820152604401610754565b5081518114611bbb5781516040517f93df584c000000000000000000000000000000000000000000000000000000008152600481019190915260248101829052604401610754565b611bc36117f0565b60ff808a1660009081526003602090815260408083203384528252808320815180830190925280548086168352939491939092840191610100909104166002811115611c1157611c11614a9b565b6002811115611c2257611c22614a9b565b9052509050600281602001516002811115611c3f57611c3f614a9b565b148015611c935750600260008b60ff1660ff168152602001908152602001600020600301816000015160ff1681548110611c7b57611c7b614fbc565b6000918252602090912001546001600160a01b031633145b611cc9576040517fda0f08e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50816060015115611dab576020820151611ce4906001615929565b60ff16855114611d20576040517f71253a2500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8351855114611d5b576040517fa75d88af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008787604051611d6d929190615942565b604051908190038120611d84918b90602001615952565b604051602081830303815290604052805190602001209050611da98a82888888612c86565b505b6040805182815260208a81013567ffffffffffffffff169082015260ff8b16917f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef0910160405180910390a2505050505050505050565b67ffffffffffffffff8216600090815260076020526040812081611e26608085615966565b67ffffffffffffffff1681526020810191909152604001600020549392505050565b80516001600160a01b0316611e70576040516342bcdf7f60e11b815260040160405180910390fd5b80516004805460208085018051604080880180516060808b0180516001600160a01b039b8c167fffffffffffffffff000000000000000000000000000000000000000000000000909a168a17600160a01b63ffffffff988916021777ffffffffffffffffffffffffffffffffffffffffffffffff167801000000000000000000000000000000000000000000000000948816949094026001600160e01b031693909317600160e01b93871693909302929092179098556080808b0180516005805473ffffffffffffffffffffffffffffffffffffffff1916918d169190911790558451988952955185169688019690965290518316918601919091525116938301939093529151909216908201527fa55bd56595c45f517e5967a3067f3dca684445a3080e7c04a4e0d5a40cda627d9060a00160405180910390a150565b6060865167ffffffffffffffff811115611fca57611fca613ec6565b60405190808252806020026020018201604052801561200f57816020015b6040805180820190915260008082526020820152815260200190600190039081611fe85790505b50905060005b87518110156120c15761209c88828151811061203357612033614fbc565b602002602001015188888888888781811061205057612050614fbc565b9050602002810190612062919061598d565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612e9392505050565b8282815181106120ae576120ae614fbc565b6020908102919091010152600101612015565b505b9695505050505050565b60006120d883613238565b8015610c125750610c12838361329c565b336001600160a01b038216036121415760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610754565b6001805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b806040015160ff166000036121ca576000604051631b3fab5160e11b815260040161075491906159f2565b60208082015160ff8082166000908152600290935260408320600181015492939092839216900361223757606084015160018201805491151562010000027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff90921691909117905561228c565b6060840151600182015460ff620100009091041615159015151461228c576040517f87f6037c00000000000000000000000000000000000000000000000000000000815260ff84166004820152602401610754565b60a08401518051601f60ff821611156122bb576001604051631b3fab5160e11b815260040161075491906159f2565b612321858560030180548060200260200160405190810160405280929190818152602001828054801561231757602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116122f9575b5050505050613357565b8560600151156124505761238f8585600201805480602002602001604051908101604052809291908181526020018280548015612317576020028201919060005260206000209081546001600160a01b031681526001909101906020018083116122f9575050505050613357565b608086015180516123a99060028701906020840190613e20565b5080516001850180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1661010060ff841690810291909117909155601f1015612409576002604051631b3fab5160e11b815260040161075491906159f2565b6040880151612419906003615a0c565b60ff168160ff1611612441576003604051631b3fab5160e11b815260040161075491906159f2565b61244d878360016133c0565b50505b61245c858360026133c0565b81516124719060038601906020850190613e20565b5060408681015160018501805460ff191660ff8316179055875180865560a089015192517fab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f547936124ca938a939260028b01929190615a28565b60405180910390a16124db85613540565b505050505050565b81516124ee81611921565b60006124f982611a23565b602085015151909150600081900361253c576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b846040015151811461257a576040517f57e0e08300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008167ffffffffffffffff81111561259557612595613ec6565b6040519080825280602002602001820160405280156125be578160200160208202803683370190505b50905060005b82811015612733576000876020015182815181106125e4576125e4614fbc565b602002602001015190507f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681600001516040015167ffffffffffffffff161461267757805160409081015190517f38432a2200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610754565b61270d8186600101805461268a906156e9565b80601f01602080910402602001604051908101604052809291908181526020018280546126b6906156e9565b80156127035780601f106126d857610100808354040283529160200191612703565b820191906000526020600020905b8154815290600101906020018083116126e657829003601f168201915b505050505061355c565b83838151811061271f5761271f614fbc565b6020908102919091010152506001016125c4565b50600061274a858389606001518a6080015161367e565b905080600003612792576040517f7dd17a7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff86166004820152602401610754565b8551151560005b84811015610b515760005a905060008a6020015183815181106127be576127be614fbc565b6020026020010151905060006127dc8a836000015160600151610bc5565b905060008160038111156127f2576127f2614a9b565b148061280f5750600381600381111561280d5761280d614a9b565b145b612867578151606001516040805167ffffffffffffffff808e16825290921660208301527f3b575419319662b2a6f5e2467d84521517a3382b908eb3d557bb3fdb0c50e23c91015b60405180910390a1505050612c7e565b841561293757600454600090600160a01b900463ffffffff1661288a88426154c2565b11905080806128aa575060038260038111156128a8576128a8614a9b565b145b6128ec576040517fa9cfc86200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8c166004820152602401610754565b8b85815181106128fe576128fe614fbc565b6020026020010151600014612931578b858151811061291f5761291f614fbc565b60200260200101518360800181815250505b50612998565b600081600381111561294b5761294b614a9b565b14612998578151606001516040805167ffffffffffffffff808e16825290921660208301527f3ef2a99c550a751d4b0b261268f05a803dfb049ab43616a1ffb388f61fe651209101612857565b81516080015167ffffffffffffffff1615612a875760008160038111156129c1576129c1614a9b565b03612a875781516080015160208301516040517fe0e03cae0000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169263e0e03cae92612a38928f929190600401615ad4565b6020604051808303816000875af1158015612a57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a7b9190615723565b612a8757505050612c7e565b60008c604001518581518110612a9f57612a9f614fbc565b6020026020010151905080518360a001515114612b03578251606001516040517f1cfe6d8b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808e1660048301529091166024820152604401610754565b612b178b84600001516060015160016136d4565b600080612b24858461377c565b91509150612b3b8d866000015160600151846136d4565b8715612bab576003826003811115612b5557612b55614a9b565b03612bab576000846003811115612b6e57612b6e614a9b565b14612bab578451516040517f2b11b8d900000000000000000000000000000000000000000000000000000000815261075491908390600401615b01565b6002826003811115612bbf57612bbf614a9b565b14612c19576003826003811115612bd857612bd8614a9b565b14612c19578451606001516040517f926c5a3e000000000000000000000000000000000000000000000000000000008152610754918f918590600401615b1a565b8451805160609091015167ffffffffffffffff908116908f167fdc8ccbc35e0eebd81239bcd1971fcd53c7eb34034880142a0f43c809a458732f85855a612c60908d6154c2565b604051612c6f93929190615b40565b60405180910390a45050505050505b600101612799565b612c8e613e92565b835160005b81811015611053576000600188868460208110612cb257612cb2614fbc565b612cbf91901a601b615929565b898581518110612cd157612cd1614fbc565b6020026020010151898681518110612ceb57612ceb614fbc565b602002602001015160405160008152602001604052604051612d29949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015612d4b573d6000803e3d6000fd5b505060408051601f1981015160ff808e166000908152600360209081528582206001600160a01b03851683528152858220858701909652855480841686529397509095509293928401916101009004166002811115612dac57612dac614a9b565b6002811115612dbd57612dbd614a9b565b9052509050600181602001516002811115612dda57612dda614a9b565b14612e11576040517fca31867a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051859060ff16601f8110612e2857612e28614fbc565b602002015115612e64576040517ff67bc7c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600185826000015160ff16601f8110612e7f57612e7f614fbc565b911515602090920201525050600101612c93565b60408051808201909152600080825260208201526000612eb68760200151613846565b6040517fbbe4f6db0000000000000000000000000000000000000000000000000000000081526001600160a01b0380831660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063bbe4f6db90602401602060405180830381865afa158015612f3b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f5f9190615b70565b90506001600160a01b0381161580612fa75750612fa56001600160a01b0382167faff2afbf000000000000000000000000000000000000000000000000000000006120cd565b155b15612fe9576040517fae9b4ce90000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152602401610754565b600454600090819061300b9089908690600160e01b900463ffffffff166138ec565b9150915060008060006130d86040518061010001604052808e81526020018c67ffffffffffffffff1681526020018d6001600160a01b031681526020018f606001518152602001896001600160a01b031681526020018f6000015181526020018f6040015181526020018b8152506040516024016130899190615b8d565b60408051601f198184030181529190526020810180516001600160e01b03167f390775370000000000000000000000000000000000000000000000000000000017905287866113886084613a1a565b9250925092508261311757816040517fe1cd550900000000000000000000000000000000000000000000000000000000815260040161075491906148b6565b815160201461315f5781516040517f78ef8024000000000000000000000000000000000000000000000000000000008152602060048201526024810191909152604401610754565b6000828060200190518101906131759190615c5a565b9050866001600160a01b03168c6001600160a01b03161461320a5760006131a68d8a6131a1868a6154c2565b6138ec565b509050868110806131c05750816131bd88836154c2565b14155b15613208576040517fa966e21f000000000000000000000000000000000000000000000000000000008152600481018390526024810188905260448101829052606401610754565b505b604080518082019091526001600160a01b039098168852602088015250949550505050505095945050505050565b6000613264827f01ffc9a70000000000000000000000000000000000000000000000000000000061329c565b8015610c155750613295827fffffffff0000000000000000000000000000000000000000000000000000000061329c565b1592915050565b6040517fffffffff0000000000000000000000000000000000000000000000000000000082166024820152600090819060440160408051601f19818403018152919052602080820180516001600160e01b03167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825192935060009283928392909183918a617530fa92503d91506000519050828015613340575060208210155b801561334c5750600081115b979650505050505050565b60005b81518110156107805760ff83166000908152600360205260408120835190919084908490811061338c5761338c614fbc565b6020908102919091018101516001600160a01b03168252810191909152604001600020805461ffff1916905560010161335a565b60005b82518160ff161015610bbf576000838260ff16815181106133e6576133e6614fbc565b602002602001015190506000600281111561340357613403614a9b565b60ff80871660009081526003602090815260408083206001600160a01b0387168452909152902054610100900416600281111561344257613442614a9b565b14613463576004604051631b3fab5160e11b815260040161075491906159f2565b6001600160a01b0381166134a3576040517fd6c62c9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052808360ff1681526020018460028111156134c9576134c9614a9b565b905260ff80871660009081526003602090815260408083206001600160a01b0387168452825290912083518154931660ff198416811782559184015190929091839161ffff19161761010083600281111561352657613526614a9b565b0217905550905050508061353990615c73565b90506133c3565b60ff81166105dd576009805467ffffffffffffffff1916905550565b8151602080820151604092830151925160009384936135a2937f2425b0b9f9054c76ff151b0a175b18f37a4a4e82013a72e9f15c9caa095ed21f93909291889101615c92565b60408051601f1981840301815290829052805160209182012086518051888401516060808b0151908401516080808d015195015195976135eb9794969395929491939101615cc5565b604051602081830303815290604052805190602001208560400151805190602001208660a001516040516020016136229190615dd7565b60408051601f198184030181528282528051602091820120908301969096528101939093526060830191909152608082015260a081019190915260c0015b60405160208183030381529060405280519060200120905092915050565b60008061368c858585613b40565b9050613697816113d5565b6136a55760009150506136cc565b67ffffffffffffffff86166000908152600860209081526040808320938352929052205490505b949350505050565b600060026136e36080856154eb565b67ffffffffffffffff166136f79190615512565b905060006137058585611e01565b905081613714600160046154c2565b901b19168183600381111561372b5761372b614a9b565b67ffffffffffffffff871660009081526007602052604081209190921b9290921791829161375a608088615966565b67ffffffffffffffff1681526020810191909152604001600020555050505050565b6040517fa80036b4000000000000000000000000000000000000000000000000000000008152600090606090309063a80036b4906137c09087908790600401615e37565b600060405180830381600087803b1580156137da57600080fd5b505af19250505080156137eb575060015b61382a573d808015613819576040519150601f19603f3d011682016040523d82523d6000602084013e61381e565b606091505b5060039250905061383f565b50506040805160208101909152600081526002905b9250929050565b6000815160201461388557816040517f8d666f6000000000000000000000000000000000000000000000000000000000815260040161075491906148b6565b60008280602001905181019061389b9190615c5a565b90506001600160a01b038111806138b3575061040081105b15610c1557826040517f8d666f6000000000000000000000000000000000000000000000000000000000815260040161075491906148b6565b60008060008060006139668860405160240161391791906001600160a01b0391909116815260200190565b60408051601f198184030181529190526020810180516001600160e01b03167f70a082310000000000000000000000000000000000000000000000000000000017905288886113886084613a1a565b925092509250826139a557816040517fe1cd550900000000000000000000000000000000000000000000000000000000815260040161075491906148b6565b60208251146139ed5781516040517f78ef8024000000000000000000000000000000000000000000000000000000008152602060048201526024810191909152604401610754565b81806020019051810190613a019190615c5a565b613a0b82886154c2565b94509450505050935093915050565b6000606060008361ffff1667ffffffffffffffff811115613a3d57613a3d613ec6565b6040519080825280601f01601f191660200182016040528015613a67576020820181803683370190505b509150863b613a9a577f0c3b563c0000000000000000000000000000000000000000000000000000000060005260046000fd5b5a85811015613acd577fafa32a2c0000000000000000000000000000000000000000000000000000000060005260046000fd5b8590036040810481038710613b06577f37c3be290000000000000000000000000000000000000000000000000000000060005260046000fd5b505a6000808a5160208c0160008c8cf193505a900390503d84811115613b295750835b808352806000602085013e50955095509592505050565b8251825160009190818303613b81576040517f11a6b26400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6101018211801590613b9557506101018111155b613bb2576040516309bde33960e01b815260040160405180910390fd5b60001982820101610100811115613bdc576040516309bde33960e01b815260040160405180910390fd5b80600003613c095786600081518110613bf757613bf7614fbc565b60200260200101519350505050613dd8565b60008167ffffffffffffffff811115613c2457613c24613ec6565b604051908082528060200260200182016040528015613c4d578160200160208202803683370190505b50905060008080805b85811015613d775760006001821b8b811603613cb15788851015613c9a578c5160018601958e918110613c8b57613c8b614fbc565b60200260200101519050613cd3565b8551600185019487918110613c8b57613c8b614fbc565b8b5160018401938d918110613cc857613cc8614fbc565b602002602001015190505b600089861015613d03578d5160018701968f918110613cf457613cf4614fbc565b60200260200101519050613d25565b8651600186019588918110613d1a57613d1a614fbc565b602002602001015190505b82851115613d46576040516309bde33960e01b815260040160405180910390fd5b613d508282613ddf565b878481518110613d6257613d62614fbc565b60209081029190910101525050600101613c56565b506001850382148015613d8957508683145b8015613d9457508581145b613db1576040516309bde33960e01b815260040160405180910390fd5b836001860381518110613dc657613dc6614fbc565b60200260200101519750505050505050505b9392505050565b6000818310613df757613df28284613dfd565b610c12565b610c1283835b604080516001602082015290810183905260608101829052600090608001613660565b828054828255906000526020600020908101928215613e82579160200282015b82811115613e82578251825473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03909116178255602090920191600190910190613e40565b50613e8e929150613eb1565b5090565b604051806103e00160405280601f906020820280368337509192915050565b5b80821115613e8e5760008155600101613eb2565b634e487b7160e01b600052604160045260246000fd5b6040516080810167ffffffffffffffff81118282101715613eff57613eff613ec6565b60405290565b60405160a0810167ffffffffffffffff81118282101715613eff57613eff613ec6565b60405160c0810167ffffffffffffffff81118282101715613eff57613eff613ec6565b6040805190810167ffffffffffffffff81118282101715613eff57613eff613ec6565b6040516060810167ffffffffffffffff81118282101715613eff57613eff613ec6565b604051601f8201601f1916810167ffffffffffffffff81118282101715613fba57613fba613ec6565b604052919050565b600067ffffffffffffffff821115613fdc57613fdc613ec6565b5060051b60200190565b6001600160a01b03811681146105dd57600080fd5b803567ffffffffffffffff8116811461401357600080fd5b919050565b80151581146105dd57600080fd5b803561401381614018565b600067ffffffffffffffff82111561404b5761404b613ec6565b50601f01601f191660200190565b600082601f83011261406a57600080fd5b813561407d61407882614031565b613f91565b81815284602083860101111561409257600080fd5b816020850160208301376000918101602001919091529392505050565b600060208083850312156140c257600080fd5b823567ffffffffffffffff808211156140da57600080fd5b818501915085601f8301126140ee57600080fd5b81356140fc61407882613fc2565b81815260059190911b8301840190848101908883111561411b57600080fd5b8585015b838110156141c1578035858111156141375760008081fd5b86016080818c03601f190181131561414f5760008081fd5b614157613edc565b8983013561416481613fe6565b81526040614173848201613ffb565b8b83015260608085013561418681614018565b8383015292840135928984111561419f57600091508182fd5b6141ad8f8d86880101614059565b90830152508552505091860191860161411f565b5098975050505050505050565b600060a082840312156141e057600080fd5b6141e8613f05565b9050813581526141fa60208301613ffb565b602082015261420b60408301613ffb565b604082015261421c60608301613ffb565b606082015261422d60808301613ffb565b608082015292915050565b803561401381613fe6565b600082601f83011261425457600080fd5b8135602061426461407883613fc2565b82815260059290921b8401810191818101908684111561428357600080fd5b8286015b848110156120c157803567ffffffffffffffff808211156142a85760008081fd5b818901915060a080601f19848d030112156142c35760008081fd5b6142cb613f05565b87840135838111156142dd5760008081fd5b6142eb8d8a83880101614059565b825250604080850135848111156143025760008081fd5b6143108e8b83890101614059565b8a84015250606080860135858111156143295760008081fd5b6143378f8c838a0101614059565b8385015250608091508186013581840152508285013592508383111561435d5760008081fd5b61436b8d8a85880101614059565b908201528652505050918301918301614287565b6000610140828403121561439257600080fd5b61439a613f28565b90506143a683836141ce565b815260a082013567ffffffffffffffff808211156143c357600080fd5b6143cf85838601614059565b602084015260c08401359150808211156143e857600080fd5b6143f485838601614059565b604084015261440560e08501614238565b6060840152610100840135608084015261012084013591508082111561442a57600080fd5b5061443784828501614243565b60a08301525092915050565b600082601f83011261445457600080fd5b8135602061446461407883613fc2565b82815260059290921b8401810191818101908684111561448357600080fd5b8286015b848110156120c157803567ffffffffffffffff8111156144a75760008081fd5b6144b58986838b010161437f565b845250918301918301614487565b600082601f8301126144d457600080fd5b813560206144e461407883613fc2565b82815260059290921b8401810191818101908684111561450357600080fd5b8286015b848110156120c157803567ffffffffffffffff8082111561452757600080fd5b818901915089603f83011261453b57600080fd5b8582013561454b61407882613fc2565b81815260059190911b830160400190878101908c83111561456b57600080fd5b604085015b838110156145a45780358581111561458757600080fd5b6145968f6040838a0101614059565b845250918901918901614570565b50875250505092840192508301614507565b600082601f8301126145c757600080fd5b813560206145d761407883613fc2565b8083825260208201915060208460051b8701019350868411156145f957600080fd5b602086015b848110156120c157803583529183019183016145fe565b600082601f83011261462657600080fd5b8135602061463661407883613fc2565b82815260059290921b8401810191818101908684111561465557600080fd5b8286015b848110156120c157803567ffffffffffffffff8082111561467a5760008081fd5b818901915060a080601f19848d030112156146955760008081fd5b61469d613f05565b6146a8888501613ffb565b8152604080850135848111156146be5760008081fd5b6146cc8e8b83890101614443565b8a84015250606080860135858111156146e55760008081fd5b6146f38f8c838a01016144c3565b838501525060809150818601358581111561470e5760008081fd5b61471c8f8c838a01016145b6565b9184019190915250919093013590830152508352918301918301614659565b600080604080848603121561474f57600080fd5b833567ffffffffffffffff8082111561476757600080fd5b61477387838801614615565b945060209150818601358181111561478a57600080fd5b8601601f8101881361479b57600080fd5b80356147a961407882613fc2565b81815260059190911b8201840190848101908a8311156147c857600080fd5b8584015b83811015614854578035868111156147e45760008081fd5b8501603f81018d136147f65760008081fd5b8781013561480661407882613fc2565b81815260059190911b82018a0190898101908f8311156148265760008081fd5b928b01925b828410156148445783358252928a0192908a019061482b565b86525050509186019186016147cc565b50809750505050505050509250929050565b60005b83811015614881578181015183820152602001614869565b50506000910152565b600081518084526148a2816020860160208601614866565b601f01601f19169290920160200192915050565b602081526000610c12602083018461488a565b8060608101831015610c1557600080fd5b60008083601f8401126148ec57600080fd5b50813567ffffffffffffffff81111561490457600080fd5b60208301915083602082850101111561383f57600080fd5b60008083601f84011261492e57600080fd5b50813567ffffffffffffffff81111561494657600080fd5b6020830191508360208260051b850101111561383f57600080fd5b60008060008060008060008060e0898b03121561497d57600080fd5b6149878a8a6148c9565b9750606089013567ffffffffffffffff808211156149a457600080fd5b6149b08c838d016148da565b909950975060808b01359150808211156149c957600080fd5b6149d58c838d0161491c565b909750955060a08b01359150808211156149ee57600080fd5b506149fb8b828c0161491c565b999c989b50969995989497949560c00135949350505050565b600080600060808486031215614a2957600080fd5b614a3385856148c9565b9250606084013567ffffffffffffffff811115614a4f57600080fd5b614a5b868287016148da565b9497909650939450505050565b60008060408385031215614a7b57600080fd5b614a8483613ffb565b9150614a9260208401613ffb565b90509250929050565b634e487b7160e01b600052602160045260246000fd5b60048110614ac157614ac1614a9b565b9052565b60208101610c158284614ab1565b600060208284031215614ae557600080fd5b813567ffffffffffffffff811115614afc57600080fd5b820160a08185031215613dd857600080fd5b803563ffffffff8116811461401357600080fd5b600060a08284031215614b3457600080fd5b614b3c613f05565b8235614b4781613fe6565b8152614b5560208401614b0e565b6020820152614b6660408401614b0e565b6040820152614b7760608401614b0e565b60608201526080830135614b8a81613fe6565b60808201529392505050565b600080600060408486031215614bab57600080fd5b833567ffffffffffffffff80821115614bc357600080fd5b614bcf8783880161437f565b94506020860135915080821115614be557600080fd5b50614a5b8682870161491c565b803560ff8116811461401357600080fd5b600060208284031215614c1557600080fd5b610c1282614bf2565b60008151808452602080850194506020840160005b83811015614c585781516001600160a01b031687529582019590820190600101614c33565b509495945050505050565b60208152600082518051602084015260ff602082015116604084015260ff604082015116606084015260608101511515608084015250602083015160c060a0840152614cb260e0840182614c1e565b90506040840151601f198483030160c0850152614ccf8282614c1e565b95945050505050565b60008060408385031215614ceb57600080fd5b614cf483613ffb565b946020939093013593505050565b60008060208385031215614d1557600080fd5b823567ffffffffffffffff80821115614d2d57600080fd5b818501915085601f830112614d4157600080fd5b813581811115614d5057600080fd5b8660208260061b8501011115614d6557600080fd5b60209290920196919550909350505050565b600060208284031215614d8957600080fd5b610c1282613ffb565b602081526001600160a01b03825116602082015260208201511515604082015267ffffffffffffffff6040830151166060820152600060608301516080808401526136cc60a084018261488a565b600060208284031215614df257600080fd5b8135613dd881613fe6565b600082601f830112614e0e57600080fd5b81356020614e1e61407883613fc2565b8083825260208201915060208460051b870101935086841115614e4057600080fd5b602086015b848110156120c1578035614e5881613fe6565b8352918301918301614e45565b60006020808385031215614e7857600080fd5b823567ffffffffffffffff80821115614e9057600080fd5b818501915085601f830112614ea457600080fd5b8135614eb261407882613fc2565b81815260059190911b83018401908481019088831115614ed157600080fd5b8585015b838110156141c157803585811115614eec57600080fd5b860160c0818c03601f19011215614f035760008081fd5b614f0b613f28565b8882013581526040614f1e818401614bf2565b8a8301526060614f2f818501614bf2565b8284015260809150614f42828501614026565b9083015260a08381013589811115614f5a5760008081fd5b614f688f8d83880101614dfd565b838501525060c0840135915088821115614f825760008081fd5b614f908e8c84870101614dfd565b9083015250845250918601918601614ed5565b600060208284031215614fb557600080fd5b5035919050565b634e487b7160e01b600052603260045260246000fd5b80356001600160e01b038116811461401357600080fd5b600082601f830112614ffa57600080fd5b8135602061500a61407883613fc2565b82815260069290921b8401810191818101908684111561502957600080fd5b8286015b848110156120c157604081890312156150465760008081fd5b61504e613f4b565b61505782613ffb565b8152615064858301614fd2565b8186015283529183019160400161502d565b600082601f83011261508757600080fd5b8135602061509761407883613fc2565b82815260079290921b840181019181810190868411156150b657600080fd5b8286015b848110156120c15780880360808112156150d45760008081fd5b6150dc613f6e565b6150e583613ffb565b8152604080601f19840112156150fb5760008081fd5b615103613f4b565b9250615110878501613ffb565b835261511d818501613ffb565b83880152818701929092526060830135918101919091528352918301916080016150ba565b6000602080838503121561515557600080fd5b823567ffffffffffffffff8082111561516d57600080fd5b8185019150604080838803121561518357600080fd5b61518b613f4b565b83358381111561519a57600080fd5b84016040818a0312156151ac57600080fd5b6151b4613f4b565b8135858111156151c357600080fd5b8201601f81018b136151d457600080fd5b80356151e261407882613fc2565b81815260069190911b8201890190898101908d83111561520157600080fd5b928a01925b828410156152515787848f03121561521e5760008081fd5b615226613f4b565b843561523181613fe6565b815261523e858d01614fd2565b818d0152825292870192908a0190615206565b84525050508187013593508484111561526957600080fd5b6152758a858401614fe9565b818801528252508385013591508282111561528f57600080fd5b61529b88838601615076565b85820152809550505050505092915050565b805160408084528151848201819052600092602091908201906060870190855b8181101561530457835180516001600160a01b031684528501516001600160e01b03168584015292840192918501916001016152cd565b50508583015187820388850152805180835290840192506000918401905b8083101561535e578351805167ffffffffffffffff1683528501516001600160e01b031685830152928401926001929092019190850190615322565b50979650505050505050565b602081526000610c1260208301846152ad565b67ffffffffffffffff8316815260608101613dd86020830184805167ffffffffffffffff908116835260209182015116910152565b634e487b7160e01b600052601160045260246000fd5b67ffffffffffffffff8181168382160190808211156153e9576153e96153b2565b5092915050565b60006020808352606084516040808487015261540f60608701836152ad565b87850151878203601f19016040890152805180835290860193506000918601905b808310156141c157845167ffffffffffffffff81511683528781015161546f89850182805167ffffffffffffffff908116835260209182015116910152565b50840151828701529386019360019290920191608090910190615430565b60006020828403121561549f57600080fd5b813567ffffffffffffffff8111156154b657600080fd5b6136cc84828501614615565b81810381811115610c1557610c156153b2565b634e487b7160e01b600052601260045260246000fd5b600067ffffffffffffffff80841680615506576155066154d5565b92169190910692915050565b8082028115828204841417610c1557610c156153b2565b805182526000602067ffffffffffffffff81840151168185015260408084015160a0604087015261555d60a087018261488a565b905060608501518682036060880152615576828261488a565b608087810151898303918a01919091528051808352908601935060009250908501905b8083101561535e57835180516001600160a01b0316835286015186830152928501926001929092019190840190615599565b602081526000610c126020830184615529565b6080815260006155f16080830187615529565b61ffff9590951660208301525060408101929092526001600160a01b0316606090910152919050565b60008060006060848603121561562f57600080fd5b835161563a81614018565b602085015190935067ffffffffffffffff81111561565757600080fd5b8401601f8101861361566857600080fd5b805161567661407882614031565b81815287602083850101111561568b57600080fd5b61569c826020830160208601614866565b809450505050604084015190509250925092565b6000604082840312156156c257600080fd5b6156ca613f4b565b6156d383613ffb565b8152602083013560208201528091505092915050565b600181811c908216806156fd57607f821691505b60208210810361571d57634e487b7160e01b600052602260045260246000fd5b50919050565b60006020828403121561573557600080fd5b8151613dd881614018565b601f821115610780576000816000526020600020601f850160051c810160208610156157695750805b601f850160051c820191505b818110156124db57828155600101615775565b815167ffffffffffffffff8111156157a2576157a2613ec6565b6157b6816157b084546156e9565b84615740565b602080601f8311600181146157eb57600084156157d35750858301515b600019600386901b1c1916600185901b1785556124db565b600085815260208120601f198616915b8281101561581a578886015182559484019460019091019084016157fb565b50858210156158385787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6000602080835283546001600160a01b038116602085015260ff8160a01c161515604085015267ffffffffffffffff8160a81c1660608501525060018085016080808601526000815461589a816156e9565b8060a089015260c060018316600081146158bb57600181146158d757615907565b60ff19841660c08b015260c083151560051b8b01019450615907565b85600052602060002060005b848110156158fe5781548c82018501529088019089016158e3565b8b0160c0019550505b50929998505050505050505050565b80820180821115610c1557610c156153b2565b60ff8181168382160190811115610c1557610c156153b2565b8183823760009101908152919050565b828152606082602083013760800192915050565b600067ffffffffffffffff80841680615981576159816154d5565b92169190910492915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126159c257600080fd5b83018035915067ffffffffffffffff8211156159dd57600080fd5b60200191503681900382131561383f57600080fd5b6020810160058310615a0657615a06614a9b565b91905290565b60ff81811683821602908116908181146153e9576153e96153b2565b600060a0820160ff881683526020878185015260a0604085015281875480845260c0860191508860005282600020935060005b81811015615a805784546001600160a01b031683526001948501949284019201615a5b565b50508481036060860152865180825290820192508187019060005b81811015615ac05782516001600160a01b031685529383019391830191600101615a9b565b50505060ff851660808501525090506120c3565b600067ffffffffffffffff808616835280851660208401525060606040830152614ccf606083018461488a565b8281526040602082015260006136cc604083018461488a565b67ffffffffffffffff848116825283166020820152606081016136cc6040830184614ab1565b615b4a8185614ab1565b606060208201526000615b60606083018561488a565b9050826040830152949350505050565b600060208284031215615b8257600080fd5b8151613dd881613fe6565b6020815260008251610100806020850152615bac61012085018361488a565b91506020850151615bc9604086018267ffffffffffffffff169052565b5060408501516001600160a01b038116606086015250606085015160808501526080850151615c0360a08601826001600160a01b03169052565b5060a0850151601f19808685030160c0870152615c20848361488a565b935060c08701519150808685030160e0870152615c3d848361488a565b935060e08701519150808685030183870152506120c3838261488a565b600060208284031215615c6c57600080fd5b5051919050565b600060ff821660ff8103615c8957615c896153b2565b60010192915050565b848152600067ffffffffffffffff8086166020840152808516604084015250608060608301526120c3608083018461488a565b86815260c060208201526000615cde60c083018861488a565b6001600160a01b039690961660408301525067ffffffffffffffff9384166060820152608081019290925290911660a09091015292915050565b600082825180855260208086019550808260051b84010181860160005b84811015615dca57601f19868403018952815160a08151818652615d5b8287018261488a565b9150508582015185820387870152615d73828261488a565b91505060408083015186830382880152615d8d838261488a565b92505050606080830151818701525060808083015192508582038187015250615db6818361488a565b9a86019a9450505090830190600101615d35565b5090979650505050505050565b602081526000610c126020830184615d18565b60008282518085526020808601955060208260051b8401016020860160005b84811015615dca57601f19868403018952615e2583835161488a565b98840198925090830190600101615e09565b604081526000835180516040840152602081015167ffffffffffffffff80821660608601528060408401511660808601528060608401511660a08601528060808401511660c086015250505060208401516101408060e0850152615e9f61018085018361488a565b915060408601517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08086850301610100870152615edc848361488a565b935060608801519150615efb6101208701836001600160a01b03169052565b60808801518387015260a0880151925080868503016101608701525050615f228282615d18565b9150508281036020840152614ccf8185615dea56fea164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CanOnlySelfCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"actual\",\"type\":\"bytes32\"}],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ExecutionError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"ForkedChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enumMultiOCR3Base.InvalidConfigErrorType\",\"name\":\"errorType\",\"type\":\"uint8\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"got\",\"type\":\"uint256\"}],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidEVMAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"internalType\":\"structOffRamp.Interval\",\"name\":\"interval\",\"type\":\"tuple\"}],\"name\":\"InvalidInterval\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"newLimit\",\"type\":\"uint256\"}],\"name\":\"InvalidManualExecutionGasLimit\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"messageDestChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidMessageDestChainSelector\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"newState\",\"type\":\"uint8\"}],\"name\":\"InvalidNewState\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRoot\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidStaticConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LeavesCannotBeEmpty\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ManualExecutionGasLimitMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"ManualExecutionNotYetEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"errorReason\",\"type\":\"bytes\"}],\"name\":\"MessageValidationError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonUniqueSignatures\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"notPool\",\"type\":\"address\"}],\"name\":\"NotACompatiblePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OracleCannotBeZeroAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ReceiverError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountReleased\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePre\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePost\",\"type\":\"uint256\"}],\"name\":\"ReleaseOrMintBalanceMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"name\":\"RootAlreadyCommitted\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"RootNotCommitted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignaturesOutOfRegistration\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"StaleCommitReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"StaticConfigCannotBeChanged\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"TokenDataMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"TokenHandlingError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnexpectedTokenData\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"WrongMessageLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WrongNumberOfSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroChainSelectorNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"AlreadyAttempted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"internalType\":\"structOffRamp.Interval\",\"name\":\"interval\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structOffRamp.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"report\",\"type\":\"tuple\"}],\"name\":\"CommitReportAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"DynamicConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"messageHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"name\":\"ExecutionStateChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"RootRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"SkippedAlreadyExecutedMessage\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"sourceConfig\",\"type\":\"tuple\"}],\"name\":\"SourceChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainSelectorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"}],\"name\":\"StaticConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigUpdates\",\"type\":\"tuple[]\"}],\"name\":\"applySourceChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"destTokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structClient.Any2EVMMessage\",\"name\":\"\",\"type\":\"tuple\"}],\"name\":\"ccipReceive\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"rawVs\",\"type\":\"bytes32\"}],\"name\":\"commit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"execute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"bytes[]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[]\"}],\"name\":\"executeSingleMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"getExecutionState\",\"outputs\":[{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLatestPriceSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"getMerkleRoot\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"getSourceChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"isBlessed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"latestConfigDetails\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"n\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"}],\"internalType\":\"structMultiOCR3Base.ConfigInfo\",\"name\":\"configInfo\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfig\",\"name\":\"ocrConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage[]\",\"name\":\"messages\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[][]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[][]\"},{\"internalType\":\"bytes32[]\",\"name\":\"proofs\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"proofFlagBits\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.ExecutionReportSingleChain[]\",\"name\":\"reports\",\"type\":\"tuple[]\"},{\"internalType\":\"uint256[][]\",\"name\":\"gasLimitOverrides\",\"type\":\"uint256[][]\"}],\"name\":\"manuallyExecute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structOffRamp.UnblessedRoot[]\",\"name\":\"rootToReset\",\"type\":\"tuple[]\"}],\"name\":\"resetUnblessedRoots\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"setDynamicConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfigArgs[]\",\"name\":\"ocrConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"setOCR3Configs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x6101206040523480156200001257600080fd5b5060405162006c4a38038062006c4a8339810160408190526200003591620008c7565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf81620001fa565b5050466080525060208301516001600160a01b03161580620000ec575060408301516001600160a01b0316155b8062000103575060608301516001600160a01b0316155b1562000122576040516342bcdf7f60e11b815260040160405180910390fd5b82516001600160401b03166000036200014e5760405163c656089560e01b815260040160405180910390fd5b82516001600160401b0390811660a052602080850180516001600160a01b0390811660c05260408088018051831660e0526060808a01805185166101005283518b519098168852945184169587019590955251821690850152905116908201527f683eb52ee924eb817377cfa8f41f238f4bb7a877da5267869dfffbad85f564d89060800160405180910390a1620001e682620002a5565b620001f181620003c1565b50505062000c67565b336001600160a01b03821603620002545760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b0316620002ce576040516342bcdf7f60e11b815260040160405180910390fd5b80516004805460208085018051604080880180516060808b0180516001600160a01b039b8c166001600160c01b0319909a168a17600160a01b63ffffffff98891602176001600160c01b0316600160c01b948816949094026001600160e01b031693909317600160e01b93871693909302929092179098556080808b018051600580546001600160a01b031916918d169190911790558451988952955185169688019690965290518316918601919091525116938301939093529151909216908201527fa55bd56595c45f517e5967a3067f3dca684445a3080e7c04a4e0d5a40cda627d9060a00160405180910390a150565b60005b815181101562000666576000828281518110620003e557620003e562000a1d565b60200260200101519050600081602001519050806001600160401b0316600003620004235760405163c656089560e01b815260040160405180910390fd5b81516001600160a01b03166200044c576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160401b0381166000908152600660205260408120600181018054919291620004789062000a33565b80601f0160208091040260200160405190810160405280929190818152602001828054620004a69062000a33565b8015620004f75780601f10620004cb57610100808354040283529160200191620004f7565b820191906000526020600020905b815481529060010190602001808311620004d957829003601f168201915b5050505050905060008460600151905081516000036200059e57805160000362000534576040516342bcdf7f60e11b815260040160405180910390fd5b6001830162000544828262000ac4565b508254600160a81b600160e81b031916600160a81b1783556040516001600160401b03851681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1620005d9565b8080519060200120828051906020012014620005d95760405163c39a620560e01b81526001600160401b038516600482015260240162000083565b604080860151845487516001600160a01b03166001600160a01b0319921515600160a01b02929092166001600160a81b031990911617178455516001600160401b038516907f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b906200064d90869062000b90565b60405180910390a25050505050806001019050620003c4565b5050565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b0381118282101715620006a557620006a56200066a565b60405290565b604051601f8201601f191681016001600160401b0381118282101715620006d657620006d66200066a565b604052919050565b80516001600160401b0381168114620006f657600080fd5b919050565b6001600160a01b03811681146200071157600080fd5b50565b805163ffffffff81168114620006f657600080fd5b6000601f83601f8401126200073d57600080fd5b825160206001600160401b03808311156200075c576200075c6200066a565b8260051b6200076d838201620006ab565b93845286810183019383810190898611156200078857600080fd5b84890192505b85831015620008ba57825184811115620007a85760008081fd5b89016080601f19828d038101821315620007c25760008081fd5b620007cc62000680565b88840151620007db81620006fb565b81526040620007ec858201620006de565b8a8301526060808601518015158114620008065760008081fd5b838301529385015193898511156200081e5760008081fd5b84860195508f603f8701126200083657600094508485fd5b8a8601519450898511156200084f576200084f6200066a565b620008608b858f88011601620006ab565b93508484528f82868801011115620008785760008081fd5b60005b8581101562000898578681018301518582018d01528b016200087b565b5060009484018b0194909452509182015283525091840191908401906200078e565b9998505050505050505050565b6000806000838503610140811215620008df57600080fd5b6080811215620008ee57600080fd5b620008f862000680565b6200090386620006de565b815260208601516200091581620006fb565b602082015260408601516200092a81620006fb565b604082015260608601516200093f81620006fb565b6060820152935060a0607f19820112156200095957600080fd5b5060405160a081016001600160401b0380821183831017156200098057620009806200066a565b81604052608087015191506200099682620006fb565b818352620009a760a0880162000714565b6020840152620009ba60c0880162000714565b6040840152620009cd60e0880162000714565b60608401526101008701519150620009e582620006fb565b608083018290526101208701519294508083111562000a0357600080fd5b505062000a138682870162000729565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b600181811c9082168062000a4857607f821691505b60208210810362000a6957634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111562000abf576000816000526020600020601f850160051c8101602086101562000a9a5750805b601f850160051c820191505b8181101562000abb5782815560010162000aa6565b5050505b505050565b81516001600160401b0381111562000ae05762000ae06200066a565b62000af88162000af1845462000a33565b8462000a6f565b602080601f83116001811462000b30576000841562000b175750858301515b600019600386901b1c1916600185901b17855562000abb565b600085815260208120601f198616915b8281101562000b615788860151825594840194600190910190840162000b40565b508582101562000b805787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b602080825282546001600160a01b0381168383015260a081901c60ff161515604084015260a81c6001600160401b0316606083015260808083015260018084018054600093929190849062000be58162000a33565b8060a089015260c0600183166000811462000c09576001811462000c265762000c58565b60ff19841660c08b015260c083151560051b8b0101945062000c58565b85600052602060002060005b8481101562000c4f5781548c820185015290880190890162000c32565b8b0160c0019550505b50929998505050505050505050565b60805160a05160c05160e05161010051615f7462000cd6600039600081816102660152612a010152600081816102370152612f1d0152600081816102080152818161142b015261196d0152600081816101d801526125f00152600081816117f3015261183f0152615f746000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806385572ffb116100d8578063ccd37ba31161008c578063f2fde38b11610066578063f2fde38b14610583578063f716f99f14610596578063ff888fb1146105a957600080fd5b8063ccd37ba31461050b578063d2a15d3514610550578063e9d68a8e1461056357600080fd5b8063991a5018116100bd578063991a5018146104c5578063a80036b4146104d8578063c673e584146104eb57600080fd5b806385572ffb1461049c5780638da5cb5b146104aa57600080fd5b8063311cd5131161012f5780635e36480c116101145780635e36480c146103785780637437ff9f1461039857806379ba50971461049457600080fd5b8063311cd513146103495780633f4b04aa1461035c57600080fd5b806306285c691161016057806306285c69146101a4578063181f5a77146102ed5780632d04ab761461033657600080fd5b806304666f9c1461017c57806305d938b514610191575b600080fd5b61018f61018a3660046140d8565b6105cc565b005b61018f61019f366004614764565b6105e0565b61029660408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316815250905090565b6040516102e49190815167ffffffffffffffff1681526020808301516001600160a01b0390811691830191909152604080840151821690830152606092830151169181019190915260800190565b60405180910390f35b6103296040518060400160405280601181526020017f4f666652616d7020312e362e302d64657600000000000000000000000000000081525081565b6040516102e491906148df565b61018f61034436600461498a565b610785565b61018f610357366004614a3d565b610b5c565b60095460405167ffffffffffffffff90911681526020016102e4565b61038b610386366004614a91565b610bc5565b6040516102e49190614aee565b6104376040805160a081018252600080825260208201819052918101829052606081018290526080810191909152506040805160a0810182526004546001600160a01b03808216835263ffffffff600160a01b83048116602085015278010000000000000000000000000000000000000000000000008304811694840194909452600160e01b9091049092166060820152600554909116608082015290565b6040516102e49190600060a0820190506001600160a01b03808451168352602084015163ffffffff808216602086015280604087015116604086015280606087015116606086015250508060808501511660808401525092915050565b61018f610c1b565b61018f610177366004614afc565b6000546040516001600160a01b0390911681526020016102e4565b61018f6104d3366004614b4b565b610cd9565b61018f6104e6366004614bbf565b610cea565b6104fe6104f9366004614c2c565b61105d565b6040516102e49190614c8c565b610542610519366004614d01565b67ffffffffffffffff919091166000908152600860209081526040808320938352929052205490565b6040519081526020016102e4565b61018f61055e366004614d2b565b6111bb565b610576610571366004614da0565b611275565b6040516102e49190614dbb565b61018f610591366004614e09565b611382565b61018f6105a4366004614e8e565b611393565b6105bc6105b7366004614fcc565b6113d5565b60405190151581526020016102e4565b6105d4611496565b6105dd816114f2565b50565b6105e86117f0565b815181518114610624576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8181101561077557600084828151811061064357610643614fe5565b6020026020010151905060008160200151519050600085848151811061066b5761066b614fe5565b60200260200101519050805182146106af576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b828110156107665760008282815181106106ce576106ce614fe5565b602002602001015190508060001461075d57846020015182815181106106f6576106f6614fe5565b60200260200101516080015181101561075d5784516040517fc8e9605100000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260248101839052604481018290526064015b60405180910390fd5b506001016106b2565b50505050806001019050610627565b506107808383611871565b505050565b60006107938789018961516b565b805151519091501515806107ac57508051602001515115155b156108ac5760095460208a01359067ffffffffffffffff8083169116101561086b576009805467ffffffffffffffff191667ffffffffffffffff83161790556004805483516040517f3937306f0000000000000000000000000000000000000000000000000000000081526001600160a01b0390921692633937306f92610834929101615393565b600060405180830381600087803b15801561084e57600080fd5b505af1158015610862573d6000803e3d6000fd5b505050506108aa565b8160200151516000036108aa576040517f2261116700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b60005b816020015151811015610aa5576000826020015182815181106108d4576108d4614fe5565b602002602001015190506000816000015190506108f081611921565b60006108fb82611a23565b602084015151815491925067ffffffffffffffff908116600160a81b9092041614158061093f575060208084015190810151905167ffffffffffffffff9182169116115b1561097f57825160208401516040517feefb0cac0000000000000000000000000000000000000000000000000000000081526107549291906004016153a6565b6040830151806109bb576040517f504570e300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b835167ffffffffffffffff16600090815260086020908152604080832084845290915290205415610a2e5783516040517f32cf0cbf00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260248101829052604401610754565b6020808501510151610a419060016153f1565b82547fffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffff16600160a81b67ffffffffffffffff9283160217909255925116600090815260086020908152604080832094835293905291909120429055506001016108af565b507f3a3950e13dd607cc37980db0ef14266c40d2bba9c01b2e44bfe549808883095d81604051610ad59190615419565b60405180910390a1610b5160008a8a8a8a8a8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808e0282810182019093528d82529093508d92508c9182918501908490808284376000920191909152508b9250611a8a915050565b505050505050505050565b610b9c610b6b828401846154b6565b6040805160008082526020820190925290610b96565b6060815260200190600190039081610b815790505b50611871565b604080516000808252602082019092529050610bbf600185858585866000611a8a565b50505050565b6000610bd3600160046154eb565b6002610be0608085615514565b67ffffffffffffffff16610bf4919061553b565b610bfe8585611e01565b901c166003811115610c1257610c12614ac4565b90505b92915050565b6001546001600160a01b03163314610c755760405162461bcd60e51b815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610754565b600080543373ffffffffffffffffffffffffffffffffffffffff19808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610ce1611496565b6105dd81611e48565b333014610d23576040517f371a732800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160008082526020820190925281610d60565b6040805180820190915260008082526020820152815260200190600190039081610d395790505b5060a08501515190915015610d9457610d918460a00151856020015186606001518760000151602001518787611fae565b90505b6040805160a0810182528551518152855160209081015167ffffffffffffffff1681830152808701518351600094840192610dd09291016148df565b60408051601f19818403018152918152908252878101516020830152018390526005549091506001600160a01b03168015610edd576040517f08d450a10000000000000000000000000000000000000000000000000000000081526001600160a01b038216906308d450a190610e4a9085906004016155f4565b600060405180830381600087803b158015610e6457600080fd5b505af1925050508015610e75575060015b610edd573d808015610ea3576040519150601f19603f3d011682016040523d82523d6000602084013e610ea8565b606091505b50806040517f09c2532500000000000000000000000000000000000000000000000000000000815260040161075491906148df565b604086015151158015610ef257506080860151155b80610f09575060608601516001600160a01b03163b155b80610f4957506060860151610f47906001600160a01b03167f85572ffb000000000000000000000000000000000000000000000000000000006120cd565b155b15610f5657505050505050565b855160209081015167ffffffffffffffff1660009081526006909152604080822054608089015160608a015192517f3cf9798300000000000000000000000000000000000000000000000000000000815284936001600160a01b0390931692633cf9798392610fce9289926113889291600401615607565b6000604051808303816000875af1158015610fed573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526110159190810190615643565b50915091508161105357806040517f0a8d6e8c00000000000000000000000000000000000000000000000000000000815260040161075491906148df565b5050505050505050565b6110a06040805160e081019091526000606082018181526080830182905260a0830182905260c08301919091528190815260200160608152602001606081525090565b60ff808316600090815260026020818152604092839020835160e081018552815460608201908152600183015480881660808401526101008104881660a0840152620100009004909616151560c08201529485529182018054845181840281018401909552808552929385830193909283018282801561114957602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161112b575b50505050508152602001600382018054806020026020016040519081016040528092919081815260200182805480156111ab57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161118d575b5050505050815250509050919050565b6111c3611496565b60005b818110156107805760008383838181106111e2576111e2614fe5565b9050604002018036038101906111f891906156d9565b905061120781602001516113d5565b61126c57805167ffffffffffffffff1660009081526008602090815260408083208285018051855290835281842093909355915191519182527f202f1139a3e334b6056064c0e9b19fd07e44a88d8f6e5ded571b24cf8c371f12910160405180910390a15b506001016111c6565b604080516080808201835260008083526020808401829052838501829052606080850181905267ffffffffffffffff878116845260068352928690208651948501875280546001600160a01b0381168652600160a01b810460ff16151593860193909352600160a81b90920490921694830194909452600184018054939492939184019161130290615712565b80601f016020809104026020016040519081016040528092919081815260200182805461132e90615712565b80156111ab5780601f10611350576101008083540402835291602001916111ab565b820191906000526020600020905b81548152906001019060200180831161135e57505050919092525091949350505050565b61138a611496565b6105dd816120e9565b61139b611496565b60005b81518110156113d1576113c98282815181106113bc576113bc614fe5565b602002602001015161219f565b60010161139e565b5050565b6040805180820182523081526020810183815291517f4d61677100000000000000000000000000000000000000000000000000000000815290516001600160a01b039081166004830152915160248201526000917f00000000000000000000000000000000000000000000000000000000000000001690634d61677190604401602060405180830381865afa158015611472573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c15919061574c565b6000546001600160a01b031633146114f05760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610754565b565b60005b81518110156113d157600082828151811061151257611512614fe5565b602002602001015190506000816020015190508067ffffffffffffffff16600003611569576040517fc656089500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81516001600160a01b0316611591576040516342bcdf7f60e11b815260040160405180910390fd5b67ffffffffffffffff811660009081526006602052604081206001810180549192916115bc90615712565b80601f01602080910402602001604051908101604052809291908181526020018280546115e890615712565b80156116355780601f1061160a57610100808354040283529160200191611635565b820191906000526020600020905b81548152906001019060200180831161161857829003601f168201915b5050505050905060008460600151905081516000036116ed578051600003611670576040516342bcdf7f60e11b815260040160405180910390fd5b6001830161167e82826157b1565b5082547fffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffff16600160a81b17835560405167ffffffffffffffff851681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1611740565b8080519060200120828051906020012014611740576040517fc39a620500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff85166004820152602401610754565b604080860151845487516001600160a01b031673ffffffffffffffffffffffffffffffffffffffff19921515600160a01b02929092167fffffffffffffffffffffff000000000000000000000000000000000000000000909116171784555167ffffffffffffffff8516907f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b906117d8908690615871565b60405180910390a250505050508060010190506114f5565b467f0000000000000000000000000000000000000000000000000000000000000000146114f0576040517f0f01ce850000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000006004820152466024820152604401610754565b81516000036118ab576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160408051600080825260208201909252911591905b845181101561191a576119128582815181106118e0576118e0614fe5565b60200260200101518461190c578583815181106118ff576118ff614fe5565b60200260200101516124e3565b836124e3565b6001016118c2565b5050505050565b6040517f2cbc26bb000000000000000000000000000000000000000000000000000000008152608082901b77ffffffffffffffff000000000000000000000000000000001660048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632cbc26bb90602401602060405180830381865afa1580156119bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119e0919061574c565b156105dd576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610754565b67ffffffffffffffff811660009081526006602052604081208054600160a01b900460ff16610c15576040517fed053c5900000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610754565b60ff87811660009081526002602090815260408083208151608081018352815481526001909101548086169382019390935261010083048516918101919091526201000090910490921615156060830152873590611ae98760a461593f565b9050826060015115611b31578451611b0290602061553b565b8651611b0f90602061553b565b611b1a9060a061593f565b611b24919061593f565b611b2e908261593f565b90505b368114611b73576040517f8e1192e100000000000000000000000000000000000000000000000000000000815260048101829052366024820152604401610754565b5081518114611bbb5781516040517f93df584c000000000000000000000000000000000000000000000000000000008152600481019190915260248101829052604401610754565b611bc36117f0565b60ff808a1660009081526003602090815260408083203384528252808320815180830190925280548086168352939491939092840191610100909104166002811115611c1157611c11614ac4565b6002811115611c2257611c22614ac4565b9052509050600281602001516002811115611c3f57611c3f614ac4565b148015611c935750600260008b60ff1660ff168152602001908152602001600020600301816000015160ff1681548110611c7b57611c7b614fe5565b6000918252602090912001546001600160a01b031633145b611cc9576040517fda0f08e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50816060015115611dab576020820151611ce4906001615952565b60ff16855114611d20576040517f71253a2500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8351855114611d5b576040517fa75d88af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008787604051611d6d92919061596b565b604051908190038120611d84918b9060200161597b565b604051602081830303815290604052805190602001209050611da98a82888888612caf565b505b6040805182815260208a81013567ffffffffffffffff169082015260ff8b16917f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef0910160405180910390a2505050505050505050565b67ffffffffffffffff8216600090815260076020526040812081611e2660808561598f565b67ffffffffffffffff1681526020810191909152604001600020549392505050565b80516001600160a01b0316611e70576040516342bcdf7f60e11b815260040160405180910390fd5b80516004805460208085018051604080880180516060808b0180516001600160a01b039b8c167fffffffffffffffff000000000000000000000000000000000000000000000000909a168a17600160a01b63ffffffff988916021777ffffffffffffffffffffffffffffffffffffffffffffffff167801000000000000000000000000000000000000000000000000948816949094026001600160e01b031693909317600160e01b93871693909302929092179098556080808b0180516005805473ffffffffffffffffffffffffffffffffffffffff1916918d169190911790558451988952955185169688019690965290518316918601919091525116938301939093529151909216908201527fa55bd56595c45f517e5967a3067f3dca684445a3080e7c04a4e0d5a40cda627d9060a00160405180910390a150565b6060865167ffffffffffffffff811115611fca57611fca613eef565b60405190808252806020026020018201604052801561200f57816020015b6040805180820190915260008082526020820152815260200190600190039081611fe85790505b50905060005b87518110156120c15761209c88828151811061203357612033614fe5565b602002602001015188888888888781811061205057612050614fe5565b905060200281019061206291906159b6565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612ebc92505050565b8282815181106120ae576120ae614fe5565b6020908102919091010152600101612015565b505b9695505050505050565b60006120d883613261565b8015610c125750610c1283836132c5565b336001600160a01b038216036121415760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610754565b6001805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b806040015160ff166000036121ca576000604051631b3fab5160e11b81526004016107549190615a1b565b60208082015160ff8082166000908152600290935260408320600181015492939092839216900361223757606084015160018201805491151562010000027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff90921691909117905561228c565b6060840151600182015460ff620100009091041615159015151461228c576040517f87f6037c00000000000000000000000000000000000000000000000000000000815260ff84166004820152602401610754565b60a08401518051601f60ff821611156122bb576001604051631b3fab5160e11b81526004016107549190615a1b565b612321858560030180548060200260200160405190810160405280929190818152602001828054801561231757602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116122f9575b5050505050613380565b8560600151156124505761238f8585600201805480602002602001604051908101604052809291908181526020018280548015612317576020028201919060005260206000209081546001600160a01b031681526001909101906020018083116122f9575050505050613380565b608086015180516123a99060028701906020840190613e49565b5080516001850180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1661010060ff841690810291909117909155601f1015612409576002604051631b3fab5160e11b81526004016107549190615a1b565b6040880151612419906003615a35565b60ff168160ff1611612441576003604051631b3fab5160e11b81526004016107549190615a1b565b61244d878360016133e9565b50505b61245c858360026133e9565b81516124719060038601906020850190613e49565b5060408681015160018501805460ff191660ff8316179055875180865560a089015192517fab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f547936124ca938a939260028b01929190615a51565b60405180910390a16124db85613569565b505050505050565b81516124ee81611921565b60006124f982611a23565b602085015151909150600081900361253c576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b846040015151811461257a576040517f57e0e08300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008167ffffffffffffffff81111561259557612595613eef565b6040519080825280602002602001820160405280156125be578160200160208202803683370190505b50905060005b82811015612733576000876020015182815181106125e4576125e4614fe5565b602002602001015190507f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681600001516040015167ffffffffffffffff161461267757805160409081015190517f38432a2200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610754565b61270d8186600101805461268a90615712565b80601f01602080910402602001604051908101604052809291908181526020018280546126b690615712565b80156127035780601f106126d857610100808354040283529160200191612703565b820191906000526020600020905b8154815290600101906020018083116126e657829003601f168201915b5050505050613585565b83838151811061271f5761271f614fe5565b6020908102919091010152506001016125c4565b50600061274a858389606001518a608001516136a7565b905080600003612792576040517f7dd17a7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff86166004820152602401610754565b8551151560005b84811015610b515760005a905060008a6020015183815181106127be576127be614fe5565b6020026020010151905060006127dc8a836000015160600151610bc5565b905060008160038111156127f2576127f2614ac4565b148061280f5750600381600381111561280d5761280d614ac4565b145b612867578151606001516040805167ffffffffffffffff808e16825290921660208301527f3b575419319662b2a6f5e2467d84521517a3382b908eb3d557bb3fdb0c50e23c91015b60405180910390a1505050612ca7565b841561293757600454600090600160a01b900463ffffffff1661288a88426154eb565b11905080806128aa575060038260038111156128a8576128a8614ac4565b145b6128ec576040517fa9cfc86200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8c166004820152602401610754565b8b85815181106128fe576128fe614fe5565b6020026020010151600014612931578b858151811061291f5761291f614fe5565b60200260200101518360800181815250505b50612998565b600081600381111561294b5761294b614ac4565b14612998578151606001516040805167ffffffffffffffff808e16825290921660208301527f3ef2a99c550a751d4b0b261268f05a803dfb049ab43616a1ffb388f61fe651209101612857565b81516080015167ffffffffffffffff1615612a875760008160038111156129c1576129c1614ac4565b03612a875781516080015160208301516040517fe0e03cae0000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169263e0e03cae92612a38928f929190600401615afd565b6020604051808303816000875af1158015612a57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a7b919061574c565b612a8757505050612ca7565b60008c604001518581518110612a9f57612a9f614fe5565b6020026020010151905080518360a001515114612b03578251606001516040517f1cfe6d8b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808e1660048301529091166024820152604401610754565b612b178b84600001516060015160016136fd565b600080612b2485846137a5565b91509150612b3b8d866000015160600151846136fd565b8715612bab576003826003811115612b5557612b55614ac4565b03612bab576000846003811115612b6e57612b6e614ac4565b14612bab578451516040517f2b11b8d900000000000000000000000000000000000000000000000000000000815261075491908390600401615b2a565b6002826003811115612bbf57612bbf614ac4565b14612c19576003826003811115612bd857612bd8614ac4565b14612c19578451606001516040517f926c5a3e000000000000000000000000000000000000000000000000000000008152610754918f918590600401615b43565b84600001516000015185600001516060015167ffffffffffffffff168e67ffffffffffffffff167f05665fe9ad095383d018353f4cbcba77e84db27dd215081bbf7cdf9ae6fbe48b8d8b81518110612c7357612c73614fe5565b602002602001015186865a612c88908e6154eb565b604051612c989493929190615b69565b60405180910390a45050505050505b600101612799565b612cb7613ebb565b835160005b81811015611053576000600188868460208110612cdb57612cdb614fe5565b612ce891901a601b615952565b898581518110612cfa57612cfa614fe5565b6020026020010151898681518110612d1457612d14614fe5565b602002602001015160405160008152602001604052604051612d52949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015612d74573d6000803e3d6000fd5b505060408051601f1981015160ff808e166000908152600360209081528582206001600160a01b03851683528152858220858701909652855480841686529397509095509293928401916101009004166002811115612dd557612dd5614ac4565b6002811115612de657612de6614ac4565b9052509050600181602001516002811115612e0357612e03614ac4565b14612e3a576040517fca31867a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051859060ff16601f8110612e5157612e51614fe5565b602002015115612e8d576040517ff67bc7c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600185826000015160ff16601f8110612ea857612ea8614fe5565b911515602090920201525050600101612cbc565b60408051808201909152600080825260208201526000612edf876020015161386f565b6040517fbbe4f6db0000000000000000000000000000000000000000000000000000000081526001600160a01b0380831660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063bbe4f6db90602401602060405180830381865afa158015612f64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f889190615ba0565b90506001600160a01b0381161580612fd05750612fce6001600160a01b0382167faff2afbf000000000000000000000000000000000000000000000000000000006120cd565b155b15613012576040517fae9b4ce90000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152602401610754565b60045460009081906130349089908690600160e01b900463ffffffff16613915565b9150915060008060006131016040518061010001604052808e81526020018c67ffffffffffffffff1681526020018d6001600160a01b031681526020018f606001518152602001896001600160a01b031681526020018f6000015181526020018f6040015181526020018b8152506040516024016130b29190615bbd565b60408051601f198184030181529190526020810180516001600160e01b03167f390775370000000000000000000000000000000000000000000000000000000017905287866113886084613a43565b9250925092508261314057816040517fe1cd550900000000000000000000000000000000000000000000000000000000815260040161075491906148df565b81516020146131885781516040517f78ef8024000000000000000000000000000000000000000000000000000000008152602060048201526024810191909152604401610754565b60008280602001905181019061319e9190615c8a565b9050866001600160a01b03168c6001600160a01b0316146132335760006131cf8d8a6131ca868a6154eb565b613915565b509050868110806131e95750816131e688836154eb565b14155b15613231576040517fa966e21f000000000000000000000000000000000000000000000000000000008152600481018390526024810188905260448101829052606401610754565b505b604080518082019091526001600160a01b039098168852602088015250949550505050505095945050505050565b600061328d827f01ffc9a7000000000000000000000000000000000000000000000000000000006132c5565b8015610c1557506132be827fffffffff000000000000000000000000000000000000000000000000000000006132c5565b1592915050565b6040517fffffffff0000000000000000000000000000000000000000000000000000000082166024820152600090819060440160408051601f19818403018152919052602080820180516001600160e01b03167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825192935060009283928392909183918a617530fa92503d91506000519050828015613369575060208210155b80156133755750600081115b979650505050505050565b60005b81518110156107805760ff8316600090815260036020526040812083519091908490849081106133b5576133b5614fe5565b6020908102919091018101516001600160a01b03168252810191909152604001600020805461ffff19169055600101613383565b60005b82518160ff161015610bbf576000838260ff168151811061340f5761340f614fe5565b602002602001015190506000600281111561342c5761342c614ac4565b60ff80871660009081526003602090815260408083206001600160a01b0387168452909152902054610100900416600281111561346b5761346b614ac4565b1461348c576004604051631b3fab5160e11b81526004016107549190615a1b565b6001600160a01b0381166134cc576040517fd6c62c9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052808360ff1681526020018460028111156134f2576134f2614ac4565b905260ff80871660009081526003602090815260408083206001600160a01b0387168452825290912083518154931660ff198416811782559184015190929091839161ffff19161761010083600281111561354f5761354f614ac4565b0217905550905050508061356290615ca3565b90506133ec565b60ff81166105dd576009805467ffffffffffffffff1916905550565b8151602080820151604092830151925160009384936135cb937f2425b0b9f9054c76ff151b0a175b18f37a4a4e82013a72e9f15c9caa095ed21f93909291889101615cc2565b60408051601f1981840301815290829052805160209182012086518051888401516060808b0151908401516080808d015195015195976136149794969395929491939101615cf5565b604051602081830303815290604052805190602001208560400151805190602001208660a0015160405160200161364b9190615e07565b60408051601f198184030181528282528051602091820120908301969096528101939093526060830191909152608082015260a081019190915260c0015b60405160208183030381529060405280519060200120905092915050565b6000806136b5858585613b69565b90506136c0816113d5565b6136ce5760009150506136f5565b67ffffffffffffffff86166000908152600860209081526040808320938352929052205490505b949350505050565b6000600261370c608085615514565b67ffffffffffffffff16613720919061553b565b9050600061372e8585611e01565b90508161373d600160046154eb565b901b19168183600381111561375457613754614ac4565b67ffffffffffffffff871660009081526007602052604081209190921b9290921791829161378360808861598f565b67ffffffffffffffff1681526020810191909152604001600020555050505050565b6040517fa80036b4000000000000000000000000000000000000000000000000000000008152600090606090309063a80036b4906137e99087908790600401615e67565b600060405180830381600087803b15801561380357600080fd5b505af1925050508015613814575060015b613853573d808015613842576040519150601f19603f3d011682016040523d82523d6000602084013e613847565b606091505b50600392509050613868565b50506040805160208101909152600081526002905b9250929050565b600081516020146138ae57816040517f8d666f6000000000000000000000000000000000000000000000000000000000815260040161075491906148df565b6000828060200190518101906138c49190615c8a565b90506001600160a01b038111806138dc575061040081105b15610c1557826040517f8d666f6000000000000000000000000000000000000000000000000000000000815260040161075491906148df565b600080600080600061398f8860405160240161394091906001600160a01b0391909116815260200190565b60408051601f198184030181529190526020810180516001600160e01b03167f70a082310000000000000000000000000000000000000000000000000000000017905288886113886084613a43565b925092509250826139ce57816040517fe1cd550900000000000000000000000000000000000000000000000000000000815260040161075491906148df565b6020825114613a165781516040517f78ef8024000000000000000000000000000000000000000000000000000000008152602060048201526024810191909152604401610754565b81806020019051810190613a2a9190615c8a565b613a3482886154eb565b94509450505050935093915050565b6000606060008361ffff1667ffffffffffffffff811115613a6657613a66613eef565b6040519080825280601f01601f191660200182016040528015613a90576020820181803683370190505b509150863b613ac3577f0c3b563c0000000000000000000000000000000000000000000000000000000060005260046000fd5b5a85811015613af6577fafa32a2c0000000000000000000000000000000000000000000000000000000060005260046000fd5b8590036040810481038710613b2f577f37c3be290000000000000000000000000000000000000000000000000000000060005260046000fd5b505a6000808a5160208c0160008c8cf193505a900390503d84811115613b525750835b808352806000602085013e50955095509592505050565b8251825160009190818303613baa576040517f11a6b26400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6101018211801590613bbe57506101018111155b613bdb576040516309bde33960e01b815260040160405180910390fd5b60001982820101610100811115613c05576040516309bde33960e01b815260040160405180910390fd5b80600003613c325786600081518110613c2057613c20614fe5565b60200260200101519350505050613e01565b60008167ffffffffffffffff811115613c4d57613c4d613eef565b604051908082528060200260200182016040528015613c76578160200160208202803683370190505b50905060008080805b85811015613da05760006001821b8b811603613cda5788851015613cc3578c5160018601958e918110613cb457613cb4614fe5565b60200260200101519050613cfc565b8551600185019487918110613cb457613cb4614fe5565b8b5160018401938d918110613cf157613cf1614fe5565b602002602001015190505b600089861015613d2c578d5160018701968f918110613d1d57613d1d614fe5565b60200260200101519050613d4e565b8651600186019588918110613d4357613d43614fe5565b602002602001015190505b82851115613d6f576040516309bde33960e01b815260040160405180910390fd5b613d798282613e08565b878481518110613d8b57613d8b614fe5565b60209081029190910101525050600101613c7f565b506001850382148015613db257508683145b8015613dbd57508581145b613dda576040516309bde33960e01b815260040160405180910390fd5b836001860381518110613def57613def614fe5565b60200260200101519750505050505050505b9392505050565b6000818310613e2057613e1b8284613e26565b610c12565b610c1283835b604080516001602082015290810183905260608101829052600090608001613689565b828054828255906000526020600020908101928215613eab579160200282015b82811115613eab578251825473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03909116178255602090920191600190910190613e69565b50613eb7929150613eda565b5090565b604051806103e00160405280601f906020820280368337509192915050565b5b80821115613eb75760008155600101613edb565b634e487b7160e01b600052604160045260246000fd5b6040516080810167ffffffffffffffff81118282101715613f2857613f28613eef565b60405290565b60405160a0810167ffffffffffffffff81118282101715613f2857613f28613eef565b60405160c0810167ffffffffffffffff81118282101715613f2857613f28613eef565b6040805190810167ffffffffffffffff81118282101715613f2857613f28613eef565b6040516060810167ffffffffffffffff81118282101715613f2857613f28613eef565b604051601f8201601f1916810167ffffffffffffffff81118282101715613fe357613fe3613eef565b604052919050565b600067ffffffffffffffff82111561400557614005613eef565b5060051b60200190565b6001600160a01b03811681146105dd57600080fd5b803567ffffffffffffffff8116811461403c57600080fd5b919050565b80151581146105dd57600080fd5b803561403c81614041565b600067ffffffffffffffff82111561407457614074613eef565b50601f01601f191660200190565b600082601f83011261409357600080fd5b81356140a66140a18261405a565b613fba565b8181528460208386010111156140bb57600080fd5b816020850160208301376000918101602001919091529392505050565b600060208083850312156140eb57600080fd5b823567ffffffffffffffff8082111561410357600080fd5b818501915085601f83011261411757600080fd5b81356141256140a182613feb565b81815260059190911b8301840190848101908883111561414457600080fd5b8585015b838110156141ea578035858111156141605760008081fd5b86016080818c03601f19018113156141785760008081fd5b614180613f05565b8983013561418d8161400f565b8152604061419c848201614024565b8b8301526060808501356141af81614041565b838301529284013592898411156141c857600091508182fd5b6141d68f8d86880101614082565b908301525085525050918601918601614148565b5098975050505050505050565b600060a0828403121561420957600080fd5b614211613f2e565b90508135815261422360208301614024565b602082015261423460408301614024565b604082015261424560608301614024565b606082015261425660808301614024565b608082015292915050565b803561403c8161400f565b600082601f83011261427d57600080fd5b8135602061428d6140a183613feb565b82815260059290921b840181019181810190868411156142ac57600080fd5b8286015b848110156120c157803567ffffffffffffffff808211156142d15760008081fd5b818901915060a080601f19848d030112156142ec5760008081fd5b6142f4613f2e565b87840135838111156143065760008081fd5b6143148d8a83880101614082565b8252506040808501358481111561432b5760008081fd5b6143398e8b83890101614082565b8a84015250606080860135858111156143525760008081fd5b6143608f8c838a0101614082565b838501525060809150818601358184015250828501359250838311156143865760008081fd5b6143948d8a85880101614082565b9082015286525050509183019183016142b0565b600061014082840312156143bb57600080fd5b6143c3613f51565b90506143cf83836141f7565b815260a082013567ffffffffffffffff808211156143ec57600080fd5b6143f885838601614082565b602084015260c084013591508082111561441157600080fd5b61441d85838601614082565b604084015261442e60e08501614261565b6060840152610100840135608084015261012084013591508082111561445357600080fd5b506144608482850161426c565b60a08301525092915050565b600082601f83011261447d57600080fd5b8135602061448d6140a183613feb565b82815260059290921b840181019181810190868411156144ac57600080fd5b8286015b848110156120c157803567ffffffffffffffff8111156144d05760008081fd5b6144de8986838b01016143a8565b8452509183019183016144b0565b600082601f8301126144fd57600080fd5b8135602061450d6140a183613feb565b82815260059290921b8401810191818101908684111561452c57600080fd5b8286015b848110156120c157803567ffffffffffffffff8082111561455057600080fd5b818901915089603f83011261456457600080fd5b858201356145746140a182613feb565b81815260059190911b830160400190878101908c83111561459457600080fd5b604085015b838110156145cd578035858111156145b057600080fd5b6145bf8f6040838a0101614082565b845250918901918901614599565b50875250505092840192508301614530565b600082601f8301126145f057600080fd5b813560206146006140a183613feb565b8083825260208201915060208460051b87010193508684111561462257600080fd5b602086015b848110156120c15780358352918301918301614627565b600082601f83011261464f57600080fd5b8135602061465f6140a183613feb565b82815260059290921b8401810191818101908684111561467e57600080fd5b8286015b848110156120c157803567ffffffffffffffff808211156146a35760008081fd5b818901915060a080601f19848d030112156146be5760008081fd5b6146c6613f2e565b6146d1888501614024565b8152604080850135848111156146e75760008081fd5b6146f58e8b8389010161446c565b8a840152506060808601358581111561470e5760008081fd5b61471c8f8c838a01016144ec565b83850152506080915081860135858111156147375760008081fd5b6147458f8c838a01016145df565b9184019190915250919093013590830152508352918301918301614682565b600080604080848603121561477857600080fd5b833567ffffffffffffffff8082111561479057600080fd5b61479c8783880161463e565b94506020915081860135818111156147b357600080fd5b8601601f810188136147c457600080fd5b80356147d26140a182613feb565b81815260059190911b8201840190848101908a8311156147f157600080fd5b8584015b8381101561487d5780358681111561480d5760008081fd5b8501603f81018d1361481f5760008081fd5b8781013561482f6140a182613feb565b81815260059190911b82018a0190898101908f83111561484f5760008081fd5b928b01925b8284101561486d5783358252928a0192908a0190614854565b86525050509186019186016147f5565b50809750505050505050509250929050565b60005b838110156148aa578181015183820152602001614892565b50506000910152565b600081518084526148cb81602086016020860161488f565b601f01601f19169290920160200192915050565b602081526000610c1260208301846148b3565b8060608101831015610c1557600080fd5b60008083601f84011261491557600080fd5b50813567ffffffffffffffff81111561492d57600080fd5b60208301915083602082850101111561386857600080fd5b60008083601f84011261495757600080fd5b50813567ffffffffffffffff81111561496f57600080fd5b6020830191508360208260051b850101111561386857600080fd5b60008060008060008060008060e0898b0312156149a657600080fd5b6149b08a8a6148f2565b9750606089013567ffffffffffffffff808211156149cd57600080fd5b6149d98c838d01614903565b909950975060808b01359150808211156149f257600080fd5b6149fe8c838d01614945565b909750955060a08b0135915080821115614a1757600080fd5b50614a248b828c01614945565b999c989b50969995989497949560c00135949350505050565b600080600060808486031215614a5257600080fd5b614a5c85856148f2565b9250606084013567ffffffffffffffff811115614a7857600080fd5b614a8486828701614903565b9497909650939450505050565b60008060408385031215614aa457600080fd5b614aad83614024565b9150614abb60208401614024565b90509250929050565b634e487b7160e01b600052602160045260246000fd5b60048110614aea57614aea614ac4565b9052565b60208101610c158284614ada565b600060208284031215614b0e57600080fd5b813567ffffffffffffffff811115614b2557600080fd5b820160a08185031215613e0157600080fd5b803563ffffffff8116811461403c57600080fd5b600060a08284031215614b5d57600080fd5b614b65613f2e565b8235614b708161400f565b8152614b7e60208401614b37565b6020820152614b8f60408401614b37565b6040820152614ba060608401614b37565b60608201526080830135614bb38161400f565b60808201529392505050565b600080600060408486031215614bd457600080fd5b833567ffffffffffffffff80821115614bec57600080fd5b614bf8878388016143a8565b94506020860135915080821115614c0e57600080fd5b50614a8486828701614945565b803560ff8116811461403c57600080fd5b600060208284031215614c3e57600080fd5b610c1282614c1b565b60008151808452602080850194506020840160005b83811015614c815781516001600160a01b031687529582019590820190600101614c5c565b509495945050505050565b60208152600082518051602084015260ff602082015116604084015260ff604082015116606084015260608101511515608084015250602083015160c060a0840152614cdb60e0840182614c47565b90506040840151601f198483030160c0850152614cf88282614c47565b95945050505050565b60008060408385031215614d1457600080fd5b614d1d83614024565b946020939093013593505050565b60008060208385031215614d3e57600080fd5b823567ffffffffffffffff80821115614d5657600080fd5b818501915085601f830112614d6a57600080fd5b813581811115614d7957600080fd5b8660208260061b8501011115614d8e57600080fd5b60209290920196919550909350505050565b600060208284031215614db257600080fd5b610c1282614024565b602081526001600160a01b03825116602082015260208201511515604082015267ffffffffffffffff6040830151166060820152600060608301516080808401526136f560a08401826148b3565b600060208284031215614e1b57600080fd5b8135613e018161400f565b600082601f830112614e3757600080fd5b81356020614e476140a183613feb565b8083825260208201915060208460051b870101935086841115614e6957600080fd5b602086015b848110156120c1578035614e818161400f565b8352918301918301614e6e565b60006020808385031215614ea157600080fd5b823567ffffffffffffffff80821115614eb957600080fd5b818501915085601f830112614ecd57600080fd5b8135614edb6140a182613feb565b81815260059190911b83018401908481019088831115614efa57600080fd5b8585015b838110156141ea57803585811115614f1557600080fd5b860160c0818c03601f19011215614f2c5760008081fd5b614f34613f51565b8882013581526040614f47818401614c1b565b8a8301526060614f58818501614c1b565b8284015260809150614f6b82850161404f565b9083015260a08381013589811115614f835760008081fd5b614f918f8d83880101614e26565b838501525060c0840135915088821115614fab5760008081fd5b614fb98e8c84870101614e26565b9083015250845250918601918601614efe565b600060208284031215614fde57600080fd5b5035919050565b634e487b7160e01b600052603260045260246000fd5b80356001600160e01b038116811461403c57600080fd5b600082601f83011261502357600080fd5b813560206150336140a183613feb565b82815260069290921b8401810191818101908684111561505257600080fd5b8286015b848110156120c1576040818903121561506f5760008081fd5b615077613f74565b61508082614024565b815261508d858301614ffb565b81860152835291830191604001615056565b600082601f8301126150b057600080fd5b813560206150c06140a183613feb565b82815260079290921b840181019181810190868411156150df57600080fd5b8286015b848110156120c15780880360808112156150fd5760008081fd5b615105613f97565b61510e83614024565b8152604080601f19840112156151245760008081fd5b61512c613f74565b9250615139878501614024565b8352615146818501614024565b83880152818701929092526060830135918101919091528352918301916080016150e3565b6000602080838503121561517e57600080fd5b823567ffffffffffffffff8082111561519657600080fd5b818501915060408083880312156151ac57600080fd5b6151b4613f74565b8335838111156151c357600080fd5b84016040818a0312156151d557600080fd5b6151dd613f74565b8135858111156151ec57600080fd5b8201601f81018b136151fd57600080fd5b803561520b6140a182613feb565b81815260069190911b8201890190898101908d83111561522a57600080fd5b928a01925b8284101561527a5787848f0312156152475760008081fd5b61524f613f74565b843561525a8161400f565b8152615267858d01614ffb565b818d0152825292870192908a019061522f565b84525050508187013593508484111561529257600080fd5b61529e8a858401615012565b81880152825250838501359150828211156152b857600080fd5b6152c48883860161509f565b85820152809550505050505092915050565b805160408084528151848201819052600092602091908201906060870190855b8181101561532d57835180516001600160a01b031684528501516001600160e01b03168584015292840192918501916001016152f6565b50508583015187820388850152805180835290840192506000918401905b80831015615387578351805167ffffffffffffffff1683528501516001600160e01b03168583015292840192600192909201919085019061534b565b50979650505050505050565b602081526000610c1260208301846152d6565b67ffffffffffffffff8316815260608101613e016020830184805167ffffffffffffffff908116835260209182015116910152565b634e487b7160e01b600052601160045260246000fd5b67ffffffffffffffff818116838216019080821115615412576154126153db565b5092915050565b60006020808352606084516040808487015261543860608701836152d6565b87850151878203601f19016040890152805180835290860193506000918601905b808310156141ea57845167ffffffffffffffff81511683528781015161549889850182805167ffffffffffffffff908116835260209182015116910152565b50840151828701529386019360019290920191608090910190615459565b6000602082840312156154c857600080fd5b813567ffffffffffffffff8111156154df57600080fd5b6136f58482850161463e565b81810381811115610c1557610c156153db565b634e487b7160e01b600052601260045260246000fd5b600067ffffffffffffffff8084168061552f5761552f6154fe565b92169190910692915050565b8082028115828204841417610c1557610c156153db565b805182526000602067ffffffffffffffff81840151168185015260408084015160a0604087015261558660a08701826148b3565b90506060850151868203606088015261559f82826148b3565b608087810151898303918a01919091528051808352908601935060009250908501905b8083101561538757835180516001600160a01b03168352860151868301529285019260019290920191908401906155c2565b602081526000610c126020830184615552565b60808152600061561a6080830187615552565b61ffff9590951660208301525060408101929092526001600160a01b0316606090910152919050565b60008060006060848603121561565857600080fd5b835161566381614041565b602085015190935067ffffffffffffffff81111561568057600080fd5b8401601f8101861361569157600080fd5b805161569f6140a18261405a565b8181528760208385010111156156b457600080fd5b6156c582602083016020860161488f565b809450505050604084015190509250925092565b6000604082840312156156eb57600080fd5b6156f3613f74565b6156fc83614024565b8152602083013560208201528091505092915050565b600181811c9082168061572657607f821691505b60208210810361574657634e487b7160e01b600052602260045260246000fd5b50919050565b60006020828403121561575e57600080fd5b8151613e0181614041565b601f821115610780576000816000526020600020601f850160051c810160208610156157925750805b601f850160051c820191505b818110156124db5782815560010161579e565b815167ffffffffffffffff8111156157cb576157cb613eef565b6157df816157d98454615712565b84615769565b602080601f83116001811461581457600084156157fc5750858301515b600019600386901b1c1916600185901b1785556124db565b600085815260208120601f198616915b8281101561584357888601518255948401946001909101908401615824565b50858210156158615787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6000602080835283546001600160a01b038116602085015260ff8160a01c161515604085015267ffffffffffffffff8160a81c166060850152506001808501608080860152600081546158c381615712565b8060a089015260c060018316600081146158e4576001811461590057615930565b60ff19841660c08b015260c083151560051b8b01019450615930565b85600052602060002060005b848110156159275781548c820185015290880190890161590c565b8b0160c0019550505b50929998505050505050505050565b80820180821115610c1557610c156153db565b60ff8181168382160190811115610c1557610c156153db565b8183823760009101908152919050565b828152606082602083013760800192915050565b600067ffffffffffffffff808416806159aa576159aa6154fe565b92169190910492915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126159eb57600080fd5b83018035915067ffffffffffffffff821115615a0657600080fd5b60200191503681900382131561386857600080fd5b6020810160058310615a2f57615a2f614ac4565b91905290565b60ff8181168382160290811690818114615412576154126153db565b600060a0820160ff881683526020878185015260a0604085015281875480845260c0860191508860005282600020935060005b81811015615aa95784546001600160a01b031683526001948501949284019201615a84565b50508481036060860152865180825290820192508187019060005b81811015615ae95782516001600160a01b031685529383019391830191600101615ac4565b50505060ff851660808501525090506120c3565b600067ffffffffffffffff808616835280851660208401525060606040830152614cf860608301846148b3565b8281526040602082015260006136f560408301846148b3565b67ffffffffffffffff848116825283166020820152606081016136f56040830184614ada565b848152615b796020820185614ada565b608060408201526000615b8f60808301856148b3565b905082606083015295945050505050565b600060208284031215615bb257600080fd5b8151613e018161400f565b6020815260008251610100806020850152615bdc6101208501836148b3565b91506020850151615bf9604086018267ffffffffffffffff169052565b5060408501516001600160a01b038116606086015250606085015160808501526080850151615c3360a08601826001600160a01b03169052565b5060a0850151601f19808685030160c0870152615c5084836148b3565b935060c08701519150808685030160e0870152615c6d84836148b3565b935060e08701519150808685030183870152506120c383826148b3565b600060208284031215615c9c57600080fd5b5051919050565b600060ff821660ff8103615cb957615cb96153db565b60010192915050565b848152600067ffffffffffffffff8086166020840152808516604084015250608060608301526120c360808301846148b3565b86815260c060208201526000615d0e60c08301886148b3565b6001600160a01b039690961660408301525067ffffffffffffffff9384166060820152608081019290925290911660a09091015292915050565b600082825180855260208086019550808260051b84010181860160005b84811015615dfa57601f19868403018952815160a08151818652615d8b828701826148b3565b9150508582015185820387870152615da382826148b3565b91505060408083015186830382880152615dbd83826148b3565b92505050606080830151818701525060808083015192508582038187015250615de681836148b3565b9a86019a9450505090830190600101615d65565b5090979650505050505050565b602081526000610c126020830184615d48565b60008282518085526020808601955060208260051b8401016020860160005b84811015615dfa57601f19868403018952615e558383516148b3565b98840198925090830190600101615e39565b604081526000835180516040840152602081015167ffffffffffffffff80821660608601528060408401511660808601528060608401511660a08601528060808401511660c086015250505060208401516101408060e0850152615ecf6101808501836148b3565b915060408601517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08086850301610100870152615f0c84836148b3565b935060608801519150615f2b6101208701836001600160a01b03169052565b60808801518387015260a0880151925080868503016101608701525050615f528282615d48565b9150508281036020840152614cf88185615e1a56fea164736f6c6343000818000a", } var OffRampABI = OffRampMetaData.ABI @@ -1201,6 +1201,7 @@ type OffRampExecutionStateChanged struct { SourceChainSelector uint64 SequenceNumber uint64 MessageId [32]byte + MessageHash [32]byte State uint8 ReturnData []byte GasUsed *big.Int @@ -2334,7 +2335,7 @@ func (OffRampDynamicConfigSet) Topic() common.Hash { } func (OffRampExecutionStateChanged) Topic() common.Hash { - return common.HexToHash("0xdc8ccbc35e0eebd81239bcd1971fcd53c7eb34034880142a0f43c809a458732f") + return common.HexToHash("0x05665fe9ad095383d018353f4cbcba77e84db27dd215081bbf7cdf9ae6fbe48b") } func (OffRampOwnershipTransferRequested) Topic() common.Hash { diff --git a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt index 98fb5dd620..688818f694 100644 --- a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -23,7 +23,7 @@ multi_aggregate_rate_limiter: ../../../contracts/solc/v0.8.24/MultiAggregateRate multi_ocr3_helper: ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Helper.abi ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Helper.bin aa299e0c2659d53aad4eace4d66be0e734b1366008593669cf30361ff529da6a nonce_manager: ../../../contracts/solc/v0.8.24/NonceManager/NonceManager.abi ../../../contracts/solc/v0.8.24/NonceManager/NonceManager.bin 6f64e1083b356c06ee66b9138e398b9c97a4cd3e8c9ec38cf3010cebc79af536 ocr3_config_encoder: ../../../contracts/solc/v0.8.24/IOCR3ConfigEncoder/IOCR3ConfigEncoder.abi ../../../contracts/solc/v0.8.24/IOCR3ConfigEncoder/IOCR3ConfigEncoder.bin e21180898e1ad54a045ee20add85a2793c681425ea06f66d1a9e5cab128b6487 -offramp: ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.abi ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.bin 4c1965d8e60a5ce133f71d46102b6cb932edce4538da096b048477154fac9fc1 +offramp: ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.abi ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.bin a3b8a9644f0d450dbf53d3371555dcc4084fb2eaf138a3797ef5cf73ed665bae onramp: ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.abi ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.bin 13927b48bd09b9ab2c62143973c747f8c2e1ebc9f95f17a61ace67a68c71ec75 ping_pong_demo: ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.abi ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.bin c1c2f8a65c7ffd971899cae7fe62f2da57d09e936151e2b92163c4bebe699d6b price_registry: ../../../contracts/solc/v0.8.24/PriceRegistry/PriceRegistry.abi ../../../contracts/solc/v0.8.24/PriceRegistry/PriceRegistry.bin e7781d600c1bb7aa4620106af7f6e146a109b97f4cb6a7d06c9e15773340ecb2 From 8d54185c8f296d749a92b778dc51d13900e00110 Mon Sep 17 00:00:00 2001 From: Josh Weintraub <26035072+jhweintraub@users.noreply.github.com> Date: Tue, 27 Aug 2024 18:04:17 -0400 Subject: [PATCH 039/115] Multi-Mechanism USDC Token Pools (#1280) ## Motivation Currently all USDC token transfers occur using Burn/Mint with calls to Circle's CCTP system for cross-chain transfers. Certain chains in CCIP have non-canonical USDC deployed and want to integrate the ability to use CCIP as a canonical bridge whereby canonical-USDC is locked on the source-chain and then minted on the destination chain. Then at a later date, when circle decides to add that chain to CCTP, the non-canonical USDC will be converted into canonical by burning the locked-tokens on the source-chain. To accomplish this, the token pool needs to be capable of identifying when tokens should be burned/minted with CCTP, or if they should use regular lock-release, and act accordingly. ## Solution `USDCTokenPool.sol` was been modified into a new file to allow for two different mechanisms to be used simultaneously. The primary mechanism, which is opt-out, and the secondary-mechanism which is opt in. These mechanisms are configured on a per-chain-selector basis, and must be manually enabled. In this implementation CCTP is the primary mechanism, and Lock/Release is the alternative mechanism. There are two new files 1. `HybridLockReleaseUSDCTokenPool.sol`, The actual implementation of the hybrid pool structure. 3. `USDCBridgeMigrator.sol`, which contains the logic necessary to conform to [Circle's migration policy guide](https://github.com/circlefin/stablecoin-evm/blob/master/doc/bridged_USDC_standard.md#transferring-the-roles-to-circle) --- contracts/gas-snapshots/ccip.gas-snapshot | 22 + .../USDC/HybridLockReleaseUSDCTokenPool.sol | 220 ++++++ .../ccip/pools/USDC/USDCBridgeMigrator.sol | 119 ++++ .../HybridLockReleaseUSDCTokenPool.t.sol | 661 ++++++++++++++++++ 4 files changed, 1022 insertions(+) create mode 100644 contracts/src/v0.8/ccip/pools/USDC/HybridLockReleaseUSDCTokenPool.sol create mode 100644 contracts/src/v0.8/ccip/pools/USDC/USDCBridgeMigrator.sol create mode 100644 contracts/src/v0.8/ccip/test/pools/HybridLockReleaseUSDCTokenPool.t.sol diff --git a/contracts/gas-snapshots/ccip.gas-snapshot b/contracts/gas-snapshots/ccip.gas-snapshot index c13660452d..5abff8ca4c 100644 --- a/contracts/gas-snapshots/ccip.gas-snapshot +++ b/contracts/gas-snapshots/ccip.gas-snapshot @@ -431,6 +431,28 @@ FeeQuoter_validatePoolReturnData:test_InvalidEVMAddressDestToken_Revert() (gas: FeeQuoter_validatePoolReturnData:test_ProcessPoolReturnData_Success() (gas: 73252) FeeQuoter_validatePoolReturnData:test_SourceTokenDataTooLarge_Revert() (gas: 107744) FeeQuoter_validatePoolReturnData:test_TokenAmountArraysMismatching_Revert() (gas: 40091) +HybridUSDCTokenPoolMigrationTests:test_LockOrBurn_LocKReleaseMechanism_then_switchToPrimary_Success() (gas: 208137) +HybridUSDCTokenPoolMigrationTests:test_LockOrBurn_PrimaryMechanism_Success() (gas: 135392) +HybridUSDCTokenPoolMigrationTests:test_LockOrBurn_WhileMigrationPause_Revert() (gas: 106624) +HybridUSDCTokenPoolMigrationTests:test_LockOrBurn_onLockReleaseMechanism_Success() (gas: 143884) +HybridUSDCTokenPoolMigrationTests:test_MintOrRelease_OnLockReleaseMechanism_Success() (gas: 230399) +HybridUSDCTokenPoolMigrationTests:test_MintOrRelease_OnLockReleaseMechanism_then_switchToPrimary_Success() (gas: 438259) +HybridUSDCTokenPoolMigrationTests:test_MintOrRelease_incomingMessageWithPrimaryMechanism() (gas: 269968) +HybridUSDCTokenPoolMigrationTests:test_burnLockedUSDC_invalidPermissions_Revert() (gas: 39124) +HybridUSDCTokenPoolMigrationTests:test_cancelExistingCCTPMigrationProposal() (gas: 31124) +HybridUSDCTokenPoolMigrationTests:test_cannotCancelANonExistentMigrationProposal() (gas: 12628) +HybridUSDCTokenPoolMigrationTests:test_cannotModifyLiquidityWithoutPermissions_Revert() (gas: 17133) +HybridUSDCTokenPoolMigrationTests:test_lockOrBurn_then_BurnInCCTPMigration_Success() (gas: 252432) +HybridUSDCTokenPoolMigrationTests:test_transferLiquidity_Success() (gas: 157049) +HybridUSDCTokenPoolMigrationTests:test_withdrawLiquidity_Success() (gas: 140780) +HybridUSDCTokenPoolTests:test_LockOrBurn_LocKReleaseMechanism_then_switchToPrimary_Success() (gas: 208102) +HybridUSDCTokenPoolTests:test_LockOrBurn_PrimaryMechanism_Success() (gas: 135365) +HybridUSDCTokenPoolTests:test_LockOrBurn_WhileMigrationPause_Revert() (gas: 106589) +HybridUSDCTokenPoolTests:test_LockOrBurn_onLockReleaseMechanism_Success() (gas: 143832) +HybridUSDCTokenPoolTests:test_MintOrRelease_OnLockReleaseMechanism_Success() (gas: 230365) +HybridUSDCTokenPoolTests:test_MintOrRelease_OnLockReleaseMechanism_then_switchToPrimary_Success() (gas: 438171) +HybridUSDCTokenPoolTests:test_MintOrRelease_incomingMessageWithPrimaryMechanism() (gas: 269912) +HybridUSDCTokenPoolTests:test_withdrawLiquidity_Success() (gas: 140774) LockReleaseTokenPoolAndProxy_setRebalancer:test_SetRebalancer_Revert() (gas: 10970) LockReleaseTokenPoolAndProxy_setRebalancer:test_SetRebalancer_Success() (gas: 17992) LockReleaseTokenPoolPoolAndProxy_canAcceptLiquidity:test_CanAcceptLiquidity_Success() (gas: 3368110) diff --git a/contracts/src/v0.8/ccip/pools/USDC/HybridLockReleaseUSDCTokenPool.sol b/contracts/src/v0.8/ccip/pools/USDC/HybridLockReleaseUSDCTokenPool.sol new file mode 100644 index 0000000000..f38127825d --- /dev/null +++ b/contracts/src/v0.8/ccip/pools/USDC/HybridLockReleaseUSDCTokenPool.sol @@ -0,0 +1,220 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {ILiquidityContainer} from "../../../liquiditymanager/interfaces/ILiquidityContainer.sol"; +import {ITokenMessenger} from "../USDC/ITokenMessenger.sol"; + +import {Pool} from "../../libraries/Pool.sol"; +import {TokenPool} from "../TokenPool.sol"; +import {USDCTokenPool} from "../USDC/USDCTokenPool.sol"; +import {USDCBridgeMigrator} from "./USDCBridgeMigrator.sol"; + +import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; +import {SafeERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; +import {EnumerableSet} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableSet.sol"; + +/// @notice A token pool for USDC which uses CCTP for supported chains and Lock/Release for all others +/// @dev The functionality from LockReleaseTokenPool.sol has been duplicated due to lack of compiler support for shared +/// constructors between parents +/// @dev The primary token mechanism in this pool is Burn/Mint with CCTP, with Lock/Release as the +/// secondary, opt in mechanism for chains not currently supporting CCTP. +contract HybridLockReleaseUSDCTokenPool is USDCTokenPool, USDCBridgeMigrator { + using SafeERC20 for IERC20; + using EnumerableSet for EnumerableSet.UintSet; + + event LiquidityTransferred(address indexed from, uint64 indexed remoteChainSelector, uint256 amount); + event LiquidityProviderSet( + address indexed oldProvider, address indexed newProvider, uint64 indexed remoteChainSelector + ); + + event LockReleaseEnabled(uint64 indexed remoteChainSelector); + event LockReleaseDisabled(uint64 indexed remoteChainSelector); + + error LanePausedForCCTPMigration(uint64 remoteChainSelector); + error TokenLockingNotAllowedAfterMigration(uint64 remoteChainSelector); + + /// @notice The address of the liquidity provider for a specific chain. + /// External liquidity is not required when there is one canonical token deployed to a chain, + /// and CCIP is facilitating mint/burn on all the other chains, in which case the invariant + /// balanceOf(pool) on home chain >= sum(totalSupply(mint/burn "wrapped" token) on all remote chains) should always hold + mapping(uint64 remoteChainSelector => address liquidityProvider) internal s_liquidityProvider; + + constructor( + ITokenMessenger tokenMessenger, + IERC20 token, + address[] memory allowlist, + address rmnProxy, + address router + ) USDCTokenPool(tokenMessenger, token, allowlist, rmnProxy, router) USDCBridgeMigrator(address(token), router) {} + + // ================================================================ + // │ Incoming/Outgoing Mechanisms | + // ================================================================ + + /// @notice Locks the token in the pool + /// @dev The _validateLockOrBurn check is an essential security check + function lockOrBurn(Pool.LockOrBurnInV1 calldata lockOrBurnIn) + public + virtual + override + returns (Pool.LockOrBurnOutV1 memory) + { + // // If the alternative mechanism (L/R) for chains which have it enabled + if (!shouldUseLockRelease(lockOrBurnIn.remoteChainSelector)) { + return super.lockOrBurn(lockOrBurnIn); + } + + // Circle requires a supply-lock to prevent outgoing messages once the migration process begins. + // This prevents new outgoing messages once the migration has begun to ensure any the procedure runs as expected + if (s_proposedUSDCMigrationChain == lockOrBurnIn.remoteChainSelector) { + revert LanePausedForCCTPMigration(s_proposedUSDCMigrationChain); + } + + return _lockReleaseOutgoingMessage(lockOrBurnIn); + } + + /// @notice Release tokens from the pool to the recipient + /// @dev The _validateReleaseOrMint check is an essential security check + function releaseOrMint(Pool.ReleaseOrMintInV1 calldata releaseOrMintIn) + public + virtual + override + returns (Pool.ReleaseOrMintOutV1 memory) + { + if (!shouldUseLockRelease(releaseOrMintIn.remoteChainSelector)) { + return super.releaseOrMint(releaseOrMintIn); + } + return _lockReleaseIncomingMessage(releaseOrMintIn); + } + + /// @notice Contains the alternative mechanism for incoming tokens, in this implementation is "Release" incoming tokens + function _lockReleaseIncomingMessage(Pool.ReleaseOrMintInV1 calldata releaseOrMintIn) + internal + virtual + returns (Pool.ReleaseOrMintOutV1 memory) + { + _validateReleaseOrMint(releaseOrMintIn); + + // Decrease internal tracking of locked tokens to ensure accurate accounting for burnLockedUSDC() migration + s_lockedTokensByChainSelector[releaseOrMintIn.remoteChainSelector] -= releaseOrMintIn.amount; + + // Release to the offRamp, which forwards it to the recipient + getToken().safeTransfer(releaseOrMintIn.receiver, releaseOrMintIn.amount); + + emit Released(msg.sender, releaseOrMintIn.receiver, releaseOrMintIn.amount); + + return Pool.ReleaseOrMintOutV1({destinationAmount: releaseOrMintIn.amount}); + } + + /// @notice Contains the alternative mechanism, in this implementation is "Lock" on outgoing tokens + function _lockReleaseOutgoingMessage(Pool.LockOrBurnInV1 calldata lockOrBurnIn) + internal + virtual + returns (Pool.LockOrBurnOutV1 memory) + { + _validateLockOrBurn(lockOrBurnIn); + + // Increase internal accounting of locked tokens for burnLockedUSDC() migration + s_lockedTokensByChainSelector[lockOrBurnIn.remoteChainSelector] += lockOrBurnIn.amount; + + emit Locked(msg.sender, lockOrBurnIn.amount); + + return Pool.LockOrBurnOutV1({destTokenAddress: getRemoteToken(lockOrBurnIn.remoteChainSelector), destPoolData: ""}); + } + + // ================================================================ + // │ Liquidity Management | + // ================================================================ + + /// @notice Gets LiquidityManager, can be address(0) if none is configured. + /// @return The current liquidity manager for the given chain selector + function getLiquidityProvider(uint64 remoteChainSelector) external view returns (address) { + return s_liquidityProvider[remoteChainSelector]; + } + + /// @notice Sets the LiquidityManager address. + /// @dev Only callable by the owner. + function setLiquidityProvider(uint64 remoteChainSelector, address liquidityProvider) external onlyOwner { + address oldProvider = s_liquidityProvider[remoteChainSelector]; + + s_liquidityProvider[remoteChainSelector] = liquidityProvider; + + emit LiquidityProviderSet(oldProvider, liquidityProvider, remoteChainSelector); + } + + /// @notice Adds liquidity to the pool for a specific chain. The tokens should be approved first. + /// @dev Liquidity is expected to be added on a per chain basis. Parties are expected to provide liquidity for their + /// own chain which implements non canonical USDC and liquidity is not shared across lanes. + /// @param amount The amount of liquidity to provide. + /// @param remoteChainSelector The chain for which liquidity is provided to. Necessary to ensure there's accurate + /// parity between locked USDC in this contract and the circulating supply on the remote chain + function provideLiquidity(uint64 remoteChainSelector, uint256 amount) external { + if (s_liquidityProvider[remoteChainSelector] != msg.sender) revert TokenPool.Unauthorized(msg.sender); + + s_lockedTokensByChainSelector[remoteChainSelector] += amount; + + i_token.safeTransferFrom(msg.sender, address(this), amount); + + emit ILiquidityContainer.LiquidityAdded(msg.sender, amount); + } + + /// @notice Removed liquidity to the pool. The tokens will be sent to msg.sender. + /// @param remoteChainSelector The chain where liquidity is being released. + /// @param amount The amount of liquidity to remove. + /// @dev The function should only be called if non canonical USDC on the remote chain has been burned and is not being + /// withdrawn on this chain, otherwise a mismatch may occur between locked token balance and remote circulating supply + /// which may block a potential future migration of the chain to CCTP. + function withdrawLiquidity(uint64 remoteChainSelector, uint256 amount) external { + if (s_liquidityProvider[remoteChainSelector] != msg.sender) revert TokenPool.Unauthorized(msg.sender); + + s_lockedTokensByChainSelector[remoteChainSelector] -= amount; + + i_token.safeTransfer(msg.sender, amount); + emit ILiquidityContainer.LiquidityRemoved(msg.sender, amount); + } + + /// @notice This function can be used to transfer liquidity from an older version of the pool to this pool. To do so + /// this pool will have to be set as the liquidity provider in the older version of the pool. This allows it to transfer the + /// funds in the old pool to the new pool. + /// @dev When upgrading a LockRelease pool, this function can be called at the same time as the pool is changed in the + /// TokenAdminRegistry. This allows for a smooth transition of both liquidity and transactions to the new pool. + /// Alternatively, when no multicall is available, a portion of the funds can be transferred to the new pool before + /// changing which pool CCIP uses, to ensure both pools can operate. Then the pool should be changed in the + /// TokenAdminRegistry, which will activate the new pool. All new transactions will use the new pool and its + /// liquidity. Finally, the remaining liquidity can be transferred to the new pool using this function one more time. + /// @param from The address of the old pool. + /// @param amount The amount of liquidity to transfer. + function transferLiquidity(address from, uint64 remoteChainSelector, uint256 amount) external onlyOwner { + HybridLockReleaseUSDCTokenPool(from).withdrawLiquidity(remoteChainSelector, amount); + + s_lockedTokensByChainSelector[remoteChainSelector] += amount; + + emit LiquidityTransferred(from, remoteChainSelector, amount); + } + + // ================================================================ + // │ Alt Mechanism Logic | + // ================================================================ + + /// @notice Return whether a lane should use the alternative L/R mechanism in the token pool. + /// @param remoteChainSelector the remote chain the lane is interacting with + /// @return bool Return true if the alternative L/R mechanism should be used + function shouldUseLockRelease(uint64 remoteChainSelector) public view virtual returns (bool) { + return s_shouldUseLockRelease[remoteChainSelector]; + } + + /// @notice Updates Updates designations for chains on whether to use primary or alt mechanism on CCIP messages + /// @param removes A list of chain selectors to disable Lock-Release, and enforce BM + /// @param adds A list of chain selectors to enable LR instead of BM + function updateChainSelectorMechanisms(uint64[] calldata removes, uint64[] calldata adds) external onlyOwner { + for (uint256 i = 0; i < removes.length; ++i) { + delete s_shouldUseLockRelease[removes[i]]; + emit LockReleaseDisabled(removes[i]); + } + + for (uint256 i = 0; i < adds.length; ++i) { + s_shouldUseLockRelease[adds[i]] = true; + emit LockReleaseEnabled(adds[i]); + } + } +} diff --git a/contracts/src/v0.8/ccip/pools/USDC/USDCBridgeMigrator.sol b/contracts/src/v0.8/ccip/pools/USDC/USDCBridgeMigrator.sol new file mode 100644 index 0000000000..827787f4cf --- /dev/null +++ b/contracts/src/v0.8/ccip/pools/USDC/USDCBridgeMigrator.sol @@ -0,0 +1,119 @@ +pragma solidity ^0.8.24; + +import {OwnerIsCreator} from "../../../shared/access/OwnerIsCreator.sol"; +import {IBurnMintERC20} from "../../../shared/token/ERC20/IBurnMintERC20.sol"; + +import {EnumerableSet} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/structs/EnumerableSet.sol"; + +import {Router} from "../../Router.sol"; + +/// @notice Allows migration of a lane in a token pool from Lock/Release to CCTP supported Burn/Mint. Contract +/// functionality is based on hard requirements defined by Circle to allow future CCTP compatibility +/// @dev Once a migration for a lane has occured, it can never be reversed, and CCTP will be the mechanism forever. This makes the assumption that Circle will continue to support that lane indefinitely. +abstract contract USDCBridgeMigrator is OwnerIsCreator { + using EnumerableSet for EnumerableSet.UintSet; + + event CCTPMigrationProposed(uint64 remoteChainSelector); + event CCTPMigrationExecuted(uint64 remoteChainSelector, uint256 USDCBurned); + event CCTPMigrationCancelled(uint64 existingProposalSelector); + event CircleMigratorAddressSet(address migratorAddress); + + error onlyCircle(); + error ExistingMigrationProposal(); + error NoExistingMigrationProposal(); + error NoMigrationProposalPending(); + error InvalidChainSelector(uint64 remoteChainSelector); + + IBurnMintERC20 internal immutable i_USDC; + Router internal immutable i_router; + + address internal s_circleUSDCMigrator; + uint64 internal s_proposedUSDCMigrationChain; + + mapping(uint64 chainSelector => uint256 lockedBalance) internal s_lockedTokensByChainSelector; + + mapping(uint64 chainSelector => bool shouldUseLockRelease) internal s_shouldUseLockRelease; + + constructor(address token, address router) { + i_USDC = IBurnMintERC20(token); + i_router = Router(router); + } + + /// @notice Burn USDC locked for a specific lane so that destination USDC can be converted from + /// non-canonical to canonical USDC. + /// @dev This function can only be called by an address specified by the owner to be controlled by circle + /// @dev proposeCCTPMigration must be called first on an approved lane to execute properly. + /// @dev This function signature should NEVER be overwritten, otherwise it will be unable to be called by + /// circle to properly migrate USDC over to CCTP. + function burnLockedUSDC() public { + if (msg.sender != s_circleUSDCMigrator) revert onlyCircle(); + if (s_proposedUSDCMigrationChain == 0) revert ExistingMigrationProposal(); + + uint64 burnChainSelector = s_proposedUSDCMigrationChain; + uint256 tokensToBurn = s_lockedTokensByChainSelector[burnChainSelector]; + + // Even though USDC is a trusted call, ensure CEI by updating state first + delete s_lockedTokensByChainSelector[burnChainSelector]; + delete s_proposedUSDCMigrationChain; + + // This should only be called after this contract has been granted a "zero allowance minter role" on USDC by Circle, + // otherwise the call will revert. Executing this burn will functionally convert all USDC on the destination chain + // to canonical USDC by removing the canonical USDC backing it from circulation. + i_USDC.burn(tokensToBurn); + + // Disable L/R automatically on burned chain and enable CCTP + delete s_shouldUseLockRelease[burnChainSelector]; + + emit CCTPMigrationExecuted(burnChainSelector, tokensToBurn); + } + + /// @notice Propose a destination chain to migrate from lock/release mechanism to CCTP enabled burn/mint + /// through a Circle controlled burn. + /// @param remoteChainSelector the CCIP specific selector for the remote chain currently using a + /// non-canonical form of USDC which they wish to update to canonical. Function will revert if the chain + /// selector is zero, or if a migration has already occured for the specified selector. + /// @dev This function can only be called by the owner + function proposeCCTPMigration(uint64 remoteChainSelector) external onlyOwner { + // Prevent overwriting existing migration proposals until the current one is finished + if (s_proposedUSDCMigrationChain != 0) revert ExistingMigrationProposal(); + + s_proposedUSDCMigrationChain = remoteChainSelector; + + emit CCTPMigrationProposed(remoteChainSelector); + } + + /// @notice Cancel an existing proposal to migrate a lane to CCTP. + function cancelExistingCCTPMigrationProposal() external onlyOwner { + if (s_proposedUSDCMigrationChain == 0) revert NoExistingMigrationProposal(); + + uint64 currentProposalChainSelector = s_proposedUSDCMigrationChain; + delete s_proposedUSDCMigrationChain; + + emit CCTPMigrationCancelled(currentProposalChainSelector); + } + + /// @notice retrieve the chain selector for an ongoing CCTP migration in progress. + /// @return uint64 the chain selector of the lane to be migrated. Will be zero if no proposal currently + /// exists + function getCurrentProposedCCTPChainMigration() public view returns (uint64) { + return s_proposedUSDCMigrationChain; + } + + /// @notice Set the address of the circle-controlled wallet which will execute a CCTP lane migration + /// @dev The function should only be invoked once the address has been confirmed by Circle prior to + /// chain expansion. + function setCircleMigratorAddress(address migrator) external onlyOwner { + s_circleUSDCMigrator = migrator; + + emit CircleMigratorAddressSet(migrator); + } + + /// @notice Retrieve the amount of canonical USDC locked into this lane and minted on the destination + /// @param remoteChainSelector the CCIP specific destination chain implementing a mintable and + /// non-canonical form of USDC at present. + /// @return uint256 the amount of USDC locked into the specified lane. If non-zero, the number + /// should match the current circulating supply of USDC on the destination chain + function getLockedTokensForChain(uint64 remoteChainSelector) public view returns (uint256) { + return s_lockedTokensByChainSelector[remoteChainSelector]; + } +} diff --git a/contracts/src/v0.8/ccip/test/pools/HybridLockReleaseUSDCTokenPool.t.sol b/contracts/src/v0.8/ccip/test/pools/HybridLockReleaseUSDCTokenPool.t.sol new file mode 100644 index 0000000000..96216c6fcc --- /dev/null +++ b/contracts/src/v0.8/ccip/test/pools/HybridLockReleaseUSDCTokenPool.t.sol @@ -0,0 +1,661 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {ILiquidityContainer} from "../../../liquiditymanager/interfaces/ILiquidityContainer.sol"; +import {IBurnMintERC20} from "../../../shared/token/ERC20/IBurnMintERC20.sol"; +import {IPoolV1} from "../../interfaces/IPool.sol"; +import {ITokenMessenger} from "../../pools/USDC/ITokenMessenger.sol"; + +import {BurnMintERC677} from "../../../shared/token/ERC677/BurnMintERC677.sol"; +import {Router} from "../../Router.sol"; +import {Internal} from "../../libraries/Internal.sol"; +import {Pool} from "../../libraries/Pool.sol"; +import {RateLimiter} from "../../libraries/RateLimiter.sol"; + +import {TokenPool} from "../../pools/TokenPool.sol"; +import {HybridLockReleaseUSDCTokenPool} from "../../pools/USDC/HybridLockReleaseUSDCTokenPool.sol"; +import {USDCBridgeMigrator} from "../../pools/USDC/USDCBridgeMigrator.sol"; +import {USDCTokenPool} from "../../pools/USDC/USDCTokenPool.sol"; +import {BaseTest} from "../BaseTest.t.sol"; +import {USDCTokenPoolHelper} from "../helpers/USDCTokenPoolHelper.sol"; +import {MockE2EUSDCTransmitter} from "../mocks/MockE2EUSDCTransmitter.sol"; +import {MockUSDCTokenMessenger} from "../mocks/MockUSDCTokenMessenger.sol"; + +import {IERC165} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/introspection/IERC165.sol"; + +contract USDCTokenPoolSetup is BaseTest { + IBurnMintERC20 internal s_token; + MockUSDCTokenMessenger internal s_mockUSDC; + MockE2EUSDCTransmitter internal s_mockUSDCTransmitter; + uint32 internal constant USDC_DEST_TOKEN_GAS = 150_000; + + struct USDCMessage { + uint32 version; + uint32 sourceDomain; + uint32 destinationDomain; + uint64 nonce; + bytes32 sender; + bytes32 recipient; + bytes32 destinationCaller; + bytes messageBody; + } + + uint32 internal constant SOURCE_DOMAIN_IDENTIFIER = 0x02020202; + uint32 internal constant DEST_DOMAIN_IDENTIFIER = 0; + + bytes32 internal constant SOURCE_CHAIN_TOKEN_SENDER = bytes32(uint256(uint160(0x01111111221))); + address internal constant SOURCE_CHAIN_USDC_POOL = address(0x23789765456789); + address internal constant DEST_CHAIN_USDC_POOL = address(0x987384873458734); + address internal constant DEST_CHAIN_USDC_TOKEN = address(0x23598918358198766); + + address internal s_routerAllowedOnRamp = address(3456); + address internal s_routerAllowedOffRamp = address(234); + Router internal s_router; + + HybridLockReleaseUSDCTokenPool internal s_usdcTokenPool; + HybridLockReleaseUSDCTokenPool internal s_usdcTokenPoolTransferLiquidity; + address[] internal s_allowedList; + + function setUp() public virtual override { + BaseTest.setUp(); + BurnMintERC677 usdcToken = new BurnMintERC677("LINK", "LNK", 18, 0); + s_token = usdcToken; + deal(address(s_token), OWNER, type(uint256).max); + setUpRamps(); + + s_mockUSDCTransmitter = new MockE2EUSDCTransmitter(0, DEST_DOMAIN_IDENTIFIER, address(s_token)); + s_mockUSDC = new MockUSDCTokenMessenger(0, address(s_mockUSDCTransmitter)); + + usdcToken.grantMintAndBurnRoles(address(s_mockUSDCTransmitter)); + + s_usdcTokenPool = + new HybridLockReleaseUSDCTokenPool(s_mockUSDC, s_token, new address[](0), address(s_mockRMN), address(s_router)); + + s_usdcTokenPoolTransferLiquidity = + new HybridLockReleaseUSDCTokenPool(s_mockUSDC, s_token, new address[](0), address(s_mockRMN), address(s_router)); + + usdcToken.grantMintAndBurnRoles(address(s_mockUSDC)); + usdcToken.grantMintAndBurnRoles(address(s_usdcTokenPool)); + + TokenPool.ChainUpdate[] memory chainUpdates = new TokenPool.ChainUpdate[](2); + chainUpdates[0] = TokenPool.ChainUpdate({ + remoteChainSelector: SOURCE_CHAIN_SELECTOR, + remotePoolAddress: abi.encode(SOURCE_CHAIN_USDC_POOL), + remoteTokenAddress: abi.encode(address(s_token)), + allowed: true, + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + chainUpdates[1] = TokenPool.ChainUpdate({ + remoteChainSelector: DEST_CHAIN_SELECTOR, + remotePoolAddress: abi.encode(DEST_CHAIN_USDC_POOL), + remoteTokenAddress: abi.encode(DEST_CHAIN_USDC_TOKEN), + allowed: true, + outboundRateLimiterConfig: _getOutboundRateLimiterConfig(), + inboundRateLimiterConfig: _getInboundRateLimiterConfig() + }); + + s_usdcTokenPool.applyChainUpdates(chainUpdates); + + USDCTokenPool.DomainUpdate[] memory domains = new USDCTokenPool.DomainUpdate[](1); + domains[0] = USDCTokenPool.DomainUpdate({ + destChainSelector: DEST_CHAIN_SELECTOR, + domainIdentifier: 9999, + allowedCaller: keccak256("allowedCaller"), + enabled: true + }); + + s_usdcTokenPool.setDomains(domains); + + vm.expectEmit(); + emit HybridLockReleaseUSDCTokenPool.LiquidityProviderSet(address(0), OWNER, DEST_CHAIN_SELECTOR); + + s_usdcTokenPool.setLiquidityProvider(DEST_CHAIN_SELECTOR, OWNER); + } + + function setUpRamps() internal { + s_router = new Router(address(s_token), address(s_mockRMN)); + + Router.OnRamp[] memory onRampUpdates = new Router.OnRamp[](1); + onRampUpdates[0] = Router.OnRamp({destChainSelector: DEST_CHAIN_SELECTOR, onRamp: s_routerAllowedOnRamp}); + Router.OffRamp[] memory offRampUpdates = new Router.OffRamp[](1); + address[] memory offRamps = new address[](1); + offRamps[0] = s_routerAllowedOffRamp; + offRampUpdates[0] = Router.OffRamp({sourceChainSelector: SOURCE_CHAIN_SELECTOR, offRamp: offRamps[0]}); + + s_router.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), offRampUpdates); + } + + function _generateUSDCMessage(USDCMessage memory usdcMessage) internal pure returns (bytes memory) { + return abi.encodePacked( + usdcMessage.version, + usdcMessage.sourceDomain, + usdcMessage.destinationDomain, + usdcMessage.nonce, + usdcMessage.sender, + usdcMessage.recipient, + usdcMessage.destinationCaller, + usdcMessage.messageBody + ); + } +} + +contract HybridUSDCTokenPoolTests is USDCTokenPoolSetup { + function test_LockOrBurn_onLockReleaseMechanism_Success() public { + bytes32 receiver = bytes32(uint256(uint160(STRANGER))); + + // Mark the destination chain as supporting CCTP, so use L/R instead. + uint64[] memory destChainAdds = new uint64[](1); + destChainAdds[0] = DEST_CHAIN_SELECTOR; + + s_usdcTokenPool.updateChainSelectorMechanisms(new uint64[](0), destChainAdds); + + assertTrue( + s_usdcTokenPool.shouldUseLockRelease(DEST_CHAIN_SELECTOR), + "Lock/Release mech not configured for outgoing message to DEST_CHAIN_SELECTOR" + ); + + uint256 amount = 1e6; + + s_token.transfer(address(s_usdcTokenPool), amount); + + vm.startPrank(s_routerAllowedOnRamp); + + vm.expectEmit(); + emit TokenPool.Locked(s_routerAllowedOnRamp, amount); + + s_usdcTokenPool.lockOrBurn( + Pool.LockOrBurnInV1({ + originalSender: OWNER, + receiver: abi.encodePacked(receiver), + amount: amount, + remoteChainSelector: DEST_CHAIN_SELECTOR, + localToken: address(s_token) + }) + ); + + assertEq(s_token.balanceOf(address(s_usdcTokenPool)), amount, "Incorrect token amount in the tokenPool"); + } + + function test_MintOrRelease_OnLockReleaseMechanism_Success() public { + address recipient = address(1234); + + // Designate the SOURCE_CHAIN as not using native-USDC, and so the L/R mechanism must be used instead + uint64[] memory destChainAdds = new uint64[](1); + destChainAdds[0] = SOURCE_CHAIN_SELECTOR; + + s_usdcTokenPool.updateChainSelectorMechanisms(new uint64[](0), destChainAdds); + + assertTrue( + s_usdcTokenPool.shouldUseLockRelease(SOURCE_CHAIN_SELECTOR), + "Lock/Release mech not configured for incoming message from SOURCE_CHAIN_SELECTOR" + ); + + vm.startPrank(OWNER); + s_usdcTokenPool.setLiquidityProvider(SOURCE_CHAIN_SELECTOR, OWNER); + + // Add 1e12 liquidity so that there's enough to release + vm.startPrank(s_usdcTokenPool.getLiquidityProvider(SOURCE_CHAIN_SELECTOR)); + + s_token.approve(address(s_usdcTokenPool), type(uint256).max); + + uint256 liquidityAmount = 1e12; + s_usdcTokenPool.provideLiquidity(SOURCE_CHAIN_SELECTOR, liquidityAmount); + + Internal.SourceTokenData memory sourceTokenData = Internal.SourceTokenData({ + sourcePoolAddress: abi.encode(SOURCE_CHAIN_USDC_POOL), + destTokenAddress: abi.encode(address(s_usdcTokenPool)), + extraData: abi.encode(USDCTokenPool.SourceTokenDataPayload({nonce: 1, sourceDomain: SOURCE_DOMAIN_IDENTIFIER})), + destGasAmount: USDC_DEST_TOKEN_GAS + }); + + uint256 amount = 1e6; + + vm.startPrank(s_routerAllowedOffRamp); + + vm.expectEmit(); + emit TokenPool.Released(s_routerAllowedOffRamp, recipient, amount); + + Pool.ReleaseOrMintOutV1 memory poolReturnDataV1 = s_usdcTokenPool.releaseOrMint( + Pool.ReleaseOrMintInV1({ + originalSender: abi.encode(OWNER), + receiver: recipient, + amount: amount, + localToken: address(s_token), + remoteChainSelector: SOURCE_CHAIN_SELECTOR, + sourcePoolAddress: sourceTokenData.sourcePoolAddress, + sourcePoolData: "", + offchainTokenData: "" + }) + ); + + assertEq(poolReturnDataV1.destinationAmount, amount, "destinationAmount and actual amount transferred differ"); + + // Simulate the off-ramp forwarding tokens to the recipient on destination chain + // s_token.transfer(recipient, amount); + + assertEq( + s_token.balanceOf(address(s_usdcTokenPool)), + liquidityAmount - amount, + "Incorrect remaining liquidity in TokenPool" + ); + assertEq(s_token.balanceOf(recipient), amount, "Tokens not transferred to recipient"); + } + + function test_LockOrBurn_PrimaryMechanism_Success() public { + bytes32 receiver = bytes32(uint256(uint160(STRANGER))); + uint256 amount = 1; + + vm.startPrank(OWNER); + + s_token.transfer(address(s_usdcTokenPool), amount); + + vm.startPrank(s_routerAllowedOnRamp); + + USDCTokenPool.Domain memory expectedDomain = s_usdcTokenPool.getDomain(DEST_CHAIN_SELECTOR); + + vm.expectEmit(); + emit RateLimiter.TokensConsumed(amount); + + vm.expectEmit(); + emit ITokenMessenger.DepositForBurn( + s_mockUSDC.s_nonce(), + address(s_token), + amount, + address(s_usdcTokenPool), + receiver, + expectedDomain.domainIdentifier, + s_mockUSDC.DESTINATION_TOKEN_MESSENGER(), + expectedDomain.allowedCaller + ); + + vm.expectEmit(); + emit TokenPool.Burned(s_routerAllowedOnRamp, amount); + + Pool.LockOrBurnOutV1 memory poolReturnDataV1 = s_usdcTokenPool.lockOrBurn( + Pool.LockOrBurnInV1({ + originalSender: OWNER, + receiver: abi.encodePacked(receiver), + amount: amount, + remoteChainSelector: DEST_CHAIN_SELECTOR, + localToken: address(s_token) + }) + ); + + uint64 nonce = abi.decode(poolReturnDataV1.destPoolData, (uint64)); + assertEq(s_mockUSDC.s_nonce() - 1, nonce); + } + + // https://etherscan.io/tx/0xac9f501fe0b76df1f07a22e1db30929fd12524bc7068d74012dff948632f0883 + function test_MintOrRelease_incomingMessageWithPrimaryMechanism() public { + bytes memory encodedUsdcMessage = + hex"000000000000000300000000000000000000127a00000000000000000000000019330d10d9cc8751218eaf51e8885d058642e08a000000000000000000000000bd3fa81b58ba92a82136038b25adec7066af3155000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e58310000000000000000000000004af08f56978be7dce2d1be3c65c005b41e79401c000000000000000000000000000000000000000000000000000000002057ff7a0000000000000000000000003a23f943181408eac424116af7b7790c94cb97a50000000000000000000000000000000000000000000000000000000000000000000000000000008274119237535fd659626b090f87e365ff89ebc7096bb32e8b0e85f155626b73ae7c4bb2485c184b7cc3cf7909045487890b104efb62ae74a73e32901bdcec91df1bb9ee08ccb014fcbcfe77b74d1263fd4e0b0e8de05d6c9a5913554364abfd5ea768b222f50c715908183905d74044bb2b97527c7e70ae7983c443a603557cac3b1c000000000000000000000000000000000000000000000000000000000000"; + bytes memory attestation = bytes("attestation bytes"); + + uint32 nonce = 4730; + uint32 sourceDomain = 3; + uint256 amount = 100; + + Internal.SourceTokenData memory sourceTokenData = Internal.SourceTokenData({ + sourcePoolAddress: abi.encode(SOURCE_CHAIN_USDC_POOL), + destTokenAddress: abi.encode(address(s_usdcTokenPool)), + extraData: abi.encode(USDCTokenPool.SourceTokenDataPayload({nonce: nonce, sourceDomain: sourceDomain})), + destGasAmount: USDC_DEST_TOKEN_GAS + }); + + // The mocked receiver does not release the token to the pool, so we manually do it here + deal(address(s_token), address(s_usdcTokenPool), amount); + + bytes memory offchainTokenData = + abi.encode(USDCTokenPool.MessageAndAttestation({message: encodedUsdcMessage, attestation: attestation})); + + vm.expectCall( + address(s_mockUSDCTransmitter), + abi.encodeWithSelector(MockE2EUSDCTransmitter.receiveMessage.selector, encodedUsdcMessage, attestation) + ); + + vm.startPrank(s_routerAllowedOffRamp); + s_usdcTokenPool.releaseOrMint( + Pool.ReleaseOrMintInV1({ + originalSender: abi.encode(OWNER), + receiver: OWNER, + amount: amount, + localToken: address(s_token), + remoteChainSelector: SOURCE_CHAIN_SELECTOR, + sourcePoolAddress: sourceTokenData.sourcePoolAddress, + sourcePoolData: sourceTokenData.extraData, + offchainTokenData: offchainTokenData + }) + ); + } + + function test_LockOrBurn_LocKReleaseMechanism_then_switchToPrimary_Success() public { + // Test Enabling the LR mechanism and sending an outgoing message + test_LockOrBurn_PrimaryMechanism_Success(); + + // Disable the LR mechanism so that primary CCTP is used and then attempt to send a message + uint64[] memory destChainRemoves = new uint64[](1); + destChainRemoves[0] = DEST_CHAIN_SELECTOR; + + vm.startPrank(OWNER); + + vm.expectEmit(); + emit HybridLockReleaseUSDCTokenPool.LockReleaseDisabled(DEST_CHAIN_SELECTOR); + + s_usdcTokenPool.updateChainSelectorMechanisms(destChainRemoves, new uint64[](0)); + + // Send an outgoing message + test_LockOrBurn_PrimaryMechanism_Success(); + } + + function test_MintOrRelease_OnLockReleaseMechanism_then_switchToPrimary_Success() public { + test_MintOrRelease_OnLockReleaseMechanism_Success(); + + // Disable the LR mechanism so that primary CCTP is used and then attempt to send a message + uint64[] memory destChainRemoves = new uint64[](1); + destChainRemoves[0] = SOURCE_CHAIN_SELECTOR; + + vm.startPrank(OWNER); + + vm.expectEmit(); + emit HybridLockReleaseUSDCTokenPool.LockReleaseDisabled(SOURCE_CHAIN_SELECTOR); + + s_usdcTokenPool.updateChainSelectorMechanisms(destChainRemoves, new uint64[](0)); + + vm.expectEmit(); + emit HybridLockReleaseUSDCTokenPool.LiquidityProviderSet(OWNER, OWNER, SOURCE_CHAIN_SELECTOR); + + s_usdcTokenPool.setLiquidityProvider(SOURCE_CHAIN_SELECTOR, OWNER); + + // Test incoming on the primary mechanism after disable LR, simulating Circle's new support for CCTP on + // DEST_CHAIN_SELECTOR + test_MintOrRelease_incomingMessageWithPrimaryMechanism(); + } + + function test_withdrawLiquidity_Success() public { + uint256 liquidityAmount = 1e12; + + vm.startPrank(OWNER); + s_token.approve(address(s_usdcTokenPool), type(uint256).max); + + s_usdcTokenPool.setLiquidityProvider(SOURCE_CHAIN_SELECTOR, OWNER); + assertEq(s_usdcTokenPool.getLiquidityProvider(SOURCE_CHAIN_SELECTOR), OWNER, "Owner is not Rebalancer"); + + s_usdcTokenPool.provideLiquidity(SOURCE_CHAIN_SELECTOR, liquidityAmount); + + assertEq(s_usdcTokenPool.getLockedTokensForChain(SOURCE_CHAIN_SELECTOR), liquidityAmount); + + assertEq( + s_token.balanceOf(address(s_usdcTokenPool)), + liquidityAmount, + "Available tokens doesn't match provided liquidity amount" + ); + + uint256 withdrawalAmount = liquidityAmount / 2; // Withdraw half of the liquidity + + vm.expectEmit(); + emit ILiquidityContainer.LiquidityRemoved(OWNER, withdrawalAmount); + + s_usdcTokenPool.withdrawLiquidity(SOURCE_CHAIN_SELECTOR, withdrawalAmount); + + assertEq( + s_usdcTokenPool.getLockedTokensForChain(SOURCE_CHAIN_SELECTOR), + liquidityAmount - withdrawalAmount, + "Remaining liquidity incorrect" + ); + assertEq( + s_token.balanceOf(address(s_usdcTokenPool)), + liquidityAmount - withdrawalAmount, + "Available tokens doesn't match provided liquidity amount" + ); + } + + function test_LockOrBurn_WhileMigrationPause_Revert() public { + // Create a fake migration proposal + s_usdcTokenPool.proposeCCTPMigration(DEST_CHAIN_SELECTOR); + + assertEq(s_usdcTokenPool.getCurrentProposedCCTPChainMigration(), DEST_CHAIN_SELECTOR); + + bytes32 receiver = bytes32(uint256(uint160(STRANGER))); + + // Mark the destination chain as supporting CCTP, so use L/R instead. + uint64[] memory destChainAdds = new uint64[](1); + destChainAdds[0] = DEST_CHAIN_SELECTOR; + + s_usdcTokenPool.updateChainSelectorMechanisms(new uint64[](0), destChainAdds); + + assertTrue( + s_usdcTokenPool.shouldUseLockRelease(DEST_CHAIN_SELECTOR), + "Lock Release mech not configured for outgoing message to DEST_CHAIN_SELECTOR" + ); + + uint256 amount = 1e6; + + s_token.transfer(address(s_usdcTokenPool), amount); + + vm.startPrank(s_routerAllowedOnRamp); + + // Expect the lockOrBurn to fail because a pending CCTP-Migration has paused outgoing messages on CCIP + vm.expectRevert( + abi.encodeWithSelector(HybridLockReleaseUSDCTokenPool.LanePausedForCCTPMigration.selector, DEST_CHAIN_SELECTOR) + ); + + s_usdcTokenPool.lockOrBurn( + Pool.LockOrBurnInV1({ + originalSender: OWNER, + receiver: abi.encodePacked(receiver), + amount: amount, + remoteChainSelector: DEST_CHAIN_SELECTOR, + localToken: address(s_token) + }) + ); + } +} + +contract HybridUSDCTokenPoolMigrationTests is HybridUSDCTokenPoolTests { + function test_lockOrBurn_then_BurnInCCTPMigration_Success() public { + bytes32 receiver = bytes32(uint256(uint160(STRANGER))); + address CIRCLE = makeAddr("CIRCLE CCTP Migrator"); + + // Mark the destination chain as supporting CCTP, so use L/R instead. + uint64[] memory destChainAdds = new uint64[](1); + destChainAdds[0] = DEST_CHAIN_SELECTOR; + + s_usdcTokenPool.updateChainSelectorMechanisms(new uint64[](0), destChainAdds); + + assertTrue( + s_usdcTokenPool.shouldUseLockRelease(DEST_CHAIN_SELECTOR), + "Lock/Release mech not configured for outgoing message to DEST_CHAIN_SELECTOR" + ); + + uint256 amount = 1e6; + + s_token.transfer(address(s_usdcTokenPool), amount); + + vm.startPrank(s_routerAllowedOnRamp); + + vm.expectEmit(); + emit TokenPool.Locked(s_routerAllowedOnRamp, amount); + + s_usdcTokenPool.lockOrBurn( + Pool.LockOrBurnInV1({ + originalSender: OWNER, + receiver: abi.encodePacked(receiver), + amount: amount, + remoteChainSelector: DEST_CHAIN_SELECTOR, + localToken: address(s_token) + }) + ); + + // Ensure that the tokens are properly locked + assertEq(s_token.balanceOf(address(s_usdcTokenPool)), amount, "Incorrect token amount in the tokenPool"); + + assertEq( + s_usdcTokenPool.getLockedTokensForChain(DEST_CHAIN_SELECTOR), + amount, + "Internal locked token accounting is incorrect" + ); + + vm.startPrank(OWNER); + + vm.expectEmit(); + emit USDCBridgeMigrator.CircleMigratorAddressSet(CIRCLE); + + s_usdcTokenPool.setCircleMigratorAddress(CIRCLE); + + vm.expectEmit(); + emit USDCBridgeMigrator.CCTPMigrationProposed(DEST_CHAIN_SELECTOR); + + // Propose the migration to CCTP + s_usdcTokenPool.proposeCCTPMigration(DEST_CHAIN_SELECTOR); + + assertEq( + s_usdcTokenPool.getCurrentProposedCCTPChainMigration(), + DEST_CHAIN_SELECTOR, + "Current proposed chain migration does not match expected for DEST_CHAIN_SELECTOR" + ); + + // Impersonate the set circle address and execute the proposal + vm.startPrank(CIRCLE); + + vm.expectEmit(); + emit USDCBridgeMigrator.CCTPMigrationExecuted(DEST_CHAIN_SELECTOR, amount); + + // Ensure the call to the burn function is properly + vm.expectCall(address(s_token), abi.encodeWithSelector(bytes4(keccak256("burn(uint256)")), amount)); + + s_usdcTokenPool.burnLockedUSDC(); + + // Assert that the tokens were actually burned + assertEq(s_token.balanceOf(address(s_usdcTokenPool)), 0, "Tokens were not burned out of the tokenPool"); + + // Ensure the proposal slot was cleared and there's no tokens locked for the destination chain anymore + assertEq(s_usdcTokenPool.getCurrentProposedCCTPChainMigration(), 0, "Proposal Slot should be empty"); + assertEq( + s_usdcTokenPool.getLockedTokensForChain(DEST_CHAIN_SELECTOR), + 0, + "No tokens should be locked for DEST_CHAIN_SELECTOR after CCTP-approved burn" + ); + + assertFalse( + s_usdcTokenPool.shouldUseLockRelease(DEST_CHAIN_SELECTOR), "Lock/Release mech should be disabled after a burn" + ); + + test_LockOrBurn_PrimaryMechanism_Success(); + } + + function test_cancelExistingCCTPMigrationProposal() public { + vm.startPrank(OWNER); + + vm.expectEmit(); + emit USDCBridgeMigrator.CCTPMigrationProposed(DEST_CHAIN_SELECTOR); + + s_usdcTokenPool.proposeCCTPMigration(DEST_CHAIN_SELECTOR); + + assertEq( + s_usdcTokenPool.getCurrentProposedCCTPChainMigration(), + DEST_CHAIN_SELECTOR, + "migration proposal should exist, but doesn't" + ); + + vm.expectEmit(); + emit USDCBridgeMigrator.CCTPMigrationCancelled(DEST_CHAIN_SELECTOR); + + s_usdcTokenPool.cancelExistingCCTPMigrationProposal(); + + assertEq( + s_usdcTokenPool.getCurrentProposedCCTPChainMigration(), + 0, + "migration proposal exists, but shouldn't after being cancelled" + ); + + vm.expectRevert(USDCBridgeMigrator.NoExistingMigrationProposal.selector); + s_usdcTokenPool.cancelExistingCCTPMigrationProposal(); + } + + function test_burnLockedUSDC_invalidPermissions_Revert() public { + address CIRCLE = makeAddr("CIRCLE"); + + vm.startPrank(OWNER); + + // Set the circle migrator address for later, but don't start pranking as it yet + s_usdcTokenPool.setCircleMigratorAddress(CIRCLE); + + vm.expectRevert(abi.encodeWithSelector(USDCBridgeMigrator.onlyCircle.selector)); + + // Should fail because only Circle can call this function + s_usdcTokenPool.burnLockedUSDC(); + + vm.startPrank(CIRCLE); + + vm.expectRevert(abi.encodeWithSelector(USDCBridgeMigrator.ExistingMigrationProposal.selector)); + s_usdcTokenPool.burnLockedUSDC(); + } + + function test_transferLiquidity_Success() public { + // Set as the OWNER so we can provide liquidity + vm.startPrank(OWNER); + s_usdcTokenPoolTransferLiquidity.setLiquidityProvider(DEST_CHAIN_SELECTOR, OWNER); + + s_token.approve(address(s_usdcTokenPoolTransferLiquidity), type(uint256).max); + + uint256 liquidityAmount = 1e9; + + // Provide 1000 USDC as liquidity + s_usdcTokenPoolTransferLiquidity.provideLiquidity(DEST_CHAIN_SELECTOR, liquidityAmount); + + // Set the new token pool as the rebalancer + s_usdcTokenPoolTransferLiquidity.setLiquidityProvider(DEST_CHAIN_SELECTOR, address(s_usdcTokenPool)); + + vm.expectEmit(); + emit ILiquidityContainer.LiquidityRemoved(address(s_usdcTokenPool), liquidityAmount); + + vm.expectEmit(); + emit HybridLockReleaseUSDCTokenPool.LiquidityTransferred( + address(s_usdcTokenPoolTransferLiquidity), DEST_CHAIN_SELECTOR, liquidityAmount + ); + + s_usdcTokenPool.transferLiquidity(address(s_usdcTokenPoolTransferLiquidity), DEST_CHAIN_SELECTOR, liquidityAmount); + + assertEq( + s_usdcTokenPool.getLockedTokensForChain(DEST_CHAIN_SELECTOR), + liquidityAmount, + "Tokens locked for dest chain doesn't match expected amount in storage" + ); + + assertEq( + s_usdcTokenPoolTransferLiquidity.getLockedTokensForChain(DEST_CHAIN_SELECTOR), + 0, + "Tokens locked for dest chain in old token pool doesn't match expected amount in storage" + ); + + assertEq( + s_token.balanceOf(address(s_usdcTokenPool)), + liquidityAmount, + "Liquidity amount of tokens should be new in new pool, but aren't" + ); + } + + function test_cannotModifyLiquidityWithoutPermissions_Revert() public { + address randomAddr = makeAddr("RANDOM"); + + vm.startPrank(randomAddr); + + vm.expectRevert(abi.encodeWithSelector(TokenPool.Unauthorized.selector, randomAddr)); + + // Revert because there's insufficient permissions for the DEST_CHAIN_SELECTOR to provide liquidity + s_usdcTokenPool.provideLiquidity(DEST_CHAIN_SELECTOR, 1e6); + + vm.expectRevert(abi.encodeWithSelector(TokenPool.Unauthorized.selector, randomAddr)); + + // Revert because there's insufficient permissions for the DEST_CHAIN_SELECTOR to withdraw liquidity + s_usdcTokenPool.withdrawLiquidity(DEST_CHAIN_SELECTOR, 1e6); + } + + function test_cannotCancelANonExistentMigrationProposal() public { + vm.expectRevert(USDCBridgeMigrator.NoExistingMigrationProposal.selector); + + // Proposal to migrate doesn't exist, and so the chain selector is zero, and therefore should revert + s_usdcTokenPool.cancelExistingCCTPMigrationProposal(); + } +} From d2177fd01070d0a583ed709ce2b832127ad6ccee Mon Sep 17 00:00:00 2001 From: Kostis Karantias <732062+gtklocker@users.noreply.github.com> Date: Wed, 28 Aug 2024 15:17:57 +0300 Subject: [PATCH 040/115] Fix typo in RMN.sol doc (#1383) --- contracts/src/v0.8/ccip/RMN.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/src/v0.8/ccip/RMN.sol b/contracts/src/v0.8/ccip/RMN.sol index ef672bb7ab..deffb57fbe 100644 --- a/contracts/src/v0.8/ccip/RMN.sol +++ b/contracts/src/v0.8/ccip/RMN.sol @@ -13,7 +13,7 @@ import {EnumerableSet} from "../vendor/openzeppelin-solidity/v5.0.2/contracts/ut // deployed, relying on isCursed(). bytes16 constant LEGACY_CURSE_SUBJECT = 0x01000000000000000000000000000000; -// An active curse on this subject will cause isCursed() and isCursed(bytes32) to return true. Use this subject for +// An active curse on this subject will cause isCursed() and isCursed(bytes16) to return true. Use this subject for // issues affecting all of CCIP chains, or pertaining to the chain that this contract is deployed on, instead of using // the local chain selector as a subject. bytes16 constant GLOBAL_CURSE_SUBJECT = 0x01000000000000000000000000000001; From 3a62686589863107628eab0019fd5caec2f250b7 Mon Sep 17 00:00:00 2001 From: kanth <70688600+defistar@users.noreply.github.com> Date: Wed, 28 Aug 2024 19:14:14 +0530 Subject: [PATCH 041/115] feat: CCIP-3020 Add AllowList Config struct and implementation (#1335) ## Motivation The key objective of allowlisting senders is to restrict the senders (EOA or smart contract) that can send CCIP Messages from a given blockchain to a specified destination blockchain. While acknowledging this additional check may come with gas cost, we aim to achieve this objective with minimal gas cost increments. ### Requirements The CCIP OnRamp contract must be able to allow only specific senders (EOA or smart contract), identified by address, to send CCIP messages to a specific destination blockchain, identified by destinationChainSelector. CCIP messages for a specific destination blockchain for which the sender is not included in the allowlist must be rejected. A proper error must be returned. It should be possible to activate/deactivate the allowlist capability of an OnRamp for a given destination chain. Options include: - A flag that enables/disables allowlisting capability - The selected approach should consider gas cost, clarity and simplicity. Only a designed entity must be able to update the allowlist configuration. By default this is CCIP Owner, but it must be possible for CCIP Owner to also add a third party (i.e. AllowListAdmin) to have this privilege. ## Solution - Add new properties to DestChainConfig Struct ```js /// @dev Struct to hold the configs for a destination chain /// @dev sequenceNumber, allowListEnabled, router will all be packed in 1 slot struct DestChainConfig { // The last used sequence number. This is zero in the case where no messages have yet been sent. // 0 is not a valid sequence number for any real transaction. uint64 sequenceNumber; // boolean indicator to specify if allowList check is enabled bool allowListEnabled; // This is the local router address that is allowed to send messages to the destination chain. // This is NOT the receiving router address on the destination chain. IRouter router; // This is the list of addresses allowed to send messages from onRamp EnumerableSet.AddressSet allowedSendersList; } ``` - functions to applyAllowList ```js function applyAllowListUpdates(AllowListConfigArgs[] calldata allowListConfigArgsItems) external { ``` - a struct to hold the applyAllowList Information ```js struct AllowListConfigArgs { uint64 destChainSelector; // Destination chain selector bool allowListEnabled; // indicator to check if the allowedSendersList is enabled address[] addedAllowlistedSenders; // list of senders to be added to the allowedSendersList address[] removedAllowlistedSenders; // list of senders to be removed from the allowedSendersList } ``` --------- Co-authored-by: app-token-issuer-infra-releng[bot] <120227048+app-token-issuer-infra-releng[bot]@users.noreply.github.com> --- contracts/gas-snapshots/ccip.gas-snapshot | 96 ++-- contracts/src/v0.8/ccip/onRamp/OnRamp.sol | 124 ++++- .../src/v0.8/ccip/test/onRamp/OnRamp.t.sol | 215 +++++++- .../v0.8/ccip/test/onRamp/OnRampSetup.t.sol | 7 +- .../ccip/generated/onramp/onramp.go | 519 +++++++++++++++++- ...rapper-dependency-versions-do-not-edit.txt | 2 +- integration-tests/web/sdk/client/client.go | 4 +- 7 files changed, 887 insertions(+), 80 deletions(-) diff --git a/contracts/gas-snapshots/ccip.gas-snapshot b/contracts/gas-snapshots/ccip.gas-snapshot index 5abff8ca4c..e2c0c4ad78 100644 --- a/contracts/gas-snapshots/ccip.gas-snapshot +++ b/contracts/gas-snapshots/ccip.gas-snapshot @@ -564,8 +564,8 @@ MultiOCR3Base_transmit:test_UnAuthorizedTransmitter_Revert() (gas: 24191) MultiOCR3Base_transmit:test_UnauthorizedSigner_Revert() (gas: 61409) MultiOCR3Base_transmit:test_UnconfiguredPlugin_Revert() (gas: 39890) MultiOCR3Base_transmit:test_ZeroSignatures_Revert() (gas: 32973) -MultiOnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 410714) -MultiRampsE2E:test_E2E_3MessagesMMultiOffRampSuccess_gas() (gas: 1504468) +MultiOnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 410978) +MultiRampsE2E:test_E2E_3MessagesMMultiOffRampSuccess_gas() (gas: 1504783) NonceManager_NonceIncrementation:test_getIncrementedOutboundNonce_Success() (gas: 37907) NonceManager_NonceIncrementation:test_incrementInboundNonce_Skip() (gas: 23694) NonceManager_NonceIncrementation:test_incrementInboundNonce_Success() (gas: 38763) @@ -577,10 +577,10 @@ NonceManager_OffRampUpgrade:test_UpgradedOffRampNonceSkipsIfMsgInFlight_Success( NonceManager_OffRampUpgrade:test_UpgradedSenderNoncesReadsPreviousRampTransitive_Success() (gas: 244814) NonceManager_OffRampUpgrade:test_UpgradedSenderNoncesReadsPreviousRamp_Success() (gas: 233069) NonceManager_OffRampUpgrade:test_Upgraded_Success() (gas: 153186) -NonceManager_OnRampUpgrade:test_UpgradeNonceNewSenderStartsAtZero_Success() (gas: 168502) -NonceManager_OnRampUpgrade:test_UpgradeNonceStartsAtV1Nonce_Success() (gas: 220478) +NonceManager_OnRampUpgrade:test_UpgradeNonceNewSenderStartsAtZero_Success() (gas: 168681) +NonceManager_OnRampUpgrade:test_UpgradeNonceStartsAtV1Nonce_Success() (gas: 220836) NonceManager_OnRampUpgrade:test_UpgradeSenderNoncesReadsPreviousRamp_Success() (gas: 125070) -NonceManager_OnRampUpgrade:test_Upgrade_Success() (gas: 107731) +NonceManager_OnRampUpgrade:test_Upgrade_Success() (gas: 107910) NonceManager_applyPreviousRampsUpdates:test_MultipleRampsUpdates() (gas: 122943) NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySetOffRamp_Revert() (gas: 42959) NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySetOnRampAndOffRamp_Revert() (gas: 64282) @@ -747,47 +747,55 @@ OffRamp_verify:test_NotBlessedWrongChainSelector_Success() (gas: 178754) OffRamp_verify:test_NotBlessed_Success() (gas: 141593) OffRamp_verify:test_TooManyLeaves_Revert() (gas: 51510) OnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 390336) -OnRamp_applyDestChainConfigUpdates:test_ApplyDestChainConfigUpdates_Success() (gas: 63649) +OnRamp_allowListConfigUpdates:test_applyAllowList_Success() (gas: 323566) +OnRamp_allowListConfigUpdates:test_applyAllowList_Revert() (gas: 66509) +OnRamp_allowListConfigUpdates:test_setAllowListAdmin_ByNonOwner_Revert() (gas: 11833) +OnRamp_allowListConfigUpdates:test_setAllowListAdmin_Success() (gas: 36159) +OnRamp_applyDestChainConfigUpdates:test_ApplyDestChainConfigUpdates_WithInvalidChainSelector_Revert() (gas: 13242) +OnRamp_applyDestChainConfigUpdates:test_ApplyDestChainConfigUpdates_Success() (gas: 64501) OnRamp_applyDestChainConfigUpdates:test_ApplyDestChainConfigUpdates_WithInalidChainSelector_Revert() (gas: 13308) -OnRamp_constructor:test_Constructor_InvalidConfigChainSelectorEqZero_Revert() (gas: 94260) -OnRamp_constructor:test_Constructor_InvalidConfigNonceManagerEqAddressZero_Revert() (gas: 92177) -OnRamp_constructor:test_Constructor_InvalidConfigRMNProxyEqAddressZero_Revert() (gas: 97198) -OnRamp_constructor:test_Constructor_InvalidConfigTokenAdminRegistryEqAddressZero_Revert() (gas: 92235) -OnRamp_constructor:test_Constructor_Success() (gas: 2455004) -OnRamp_forwardFromRouter:test_CannotSendZeroTokens_Revert() (gas: 72010) -OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() (gas: 112791) -OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2_Success() (gas: 143561) -OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessCustomExtraArgs() (gas: 143137) -OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessEmptyExtraArgs() (gas: 141314) -OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessLegacyExtraArgs() (gas: 143367) -OnRamp_forwardFromRouter:test_ForwardFromRouter_Success() (gas: 142736) -OnRamp_forwardFromRouter:test_ForwardFromRouter_Success_ConfigurableSourceRouter() (gas: 135246) -OnRamp_forwardFromRouter:test_InvalidExtraArgsTag_Revert() (gas: 26349) -OnRamp_forwardFromRouter:test_MessageValidationError_Revert() (gas: 133253) -OnRamp_forwardFromRouter:test_MesssageFeeTooHigh_Revert() (gas: 24426) -OnRamp_forwardFromRouter:test_OriginalSender_Revert() (gas: 12872) -OnRamp_forwardFromRouter:test_Paused_Revert() (gas: 32033) -OnRamp_forwardFromRouter:test_Permissions_Revert() (gas: 15762) -OnRamp_forwardFromRouter:test_ShouldIncrementNonceOnlyOnOrdered_Success() (gas: 182032) -OnRamp_forwardFromRouter:test_ShouldIncrementSeqNumAndNonce_Success() (gas: 208301) -OnRamp_forwardFromRouter:test_ShouldStoreLinkFees() (gas: 122714) -OnRamp_forwardFromRouter:test_ShouldStoreNonLinkFees() (gas: 144094) -OnRamp_forwardFromRouter:test_SourceTokenDataTooLarge_Revert() (gas: 3887491) -OnRamp_forwardFromRouter:test_UnsupportedToken_Revert() (gas: 108659) -OnRamp_forwardFromRouter:test_forwardFromRouter_UnsupportedToken_Revert() (gas: 74066) -OnRamp_forwardFromRouter:test_forwardFromRouter_WithValidation_Success() (gas: 273416) -OnRamp_getFee:test_EmptyMessage_Success() (gas: 104351) -OnRamp_getFee:test_EnforceOutOfOrder_Revert() (gas: 73173) -OnRamp_getFee:test_SingleTokenMessage_Success() (gas: 119675) -OnRamp_getFee:test_Unhealthy_Revert() (gas: 43679) +OnRamp_constructor:test_Constructor_InvalidConfigChainSelectorEqZero_Revert() (gas: 94878) +OnRamp_constructor:test_Constructor_InvalidConfigNonceManagerEqAddressZero_Revert() (gas: 92812) +OnRamp_constructor:test_Constructor_InvalidConfigRMNProxyEqAddressZero_Revert() (gas: 97827) +OnRamp_constructor:test_Constructor_InvalidConfigTokenAdminRegistryEqAddressZero_Revert() (gas: 92870) +OnRamp_constructor:test_Constructor_Success() (gas: 2866937) +OnRamp_forwardFromRouter:test_CannotSendZeroTokens_Revert() (gas: 72097) +OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() (gas: 115250) +OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2_Success() (gas: 146019) +OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessCustomExtraArgs() (gas: 145615) +OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessEmptyExtraArgs() (gas: 143816) +OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessLegacyExtraArgs() (gas: 145847) +OnRamp_forwardFromRouter:test_ForwardFromRouter_Success() (gas: 145216) +OnRamp_forwardFromRouter:test_ForwardFromRouter_Success_ConfigurableSourceRouter() (gas: 140359) +OnRamp_forwardFromRouter:test_InvalidExtraArgsTag_Revert() (gas: 28810) +OnRamp_forwardFromRouter:test_MessageValidationError_Revert() (gas: 138683) +OnRamp_forwardFromRouter:test_MesssageFeeTooHigh_Revert() (gas: 26910) +OnRamp_forwardFromRouter:test_OriginalSender_Revert() (gas: 12918) +OnRamp_forwardFromRouter:test_Paused_Revert() (gas: 37224) +OnRamp_forwardFromRouter:test_Permissions_Revert() (gas: 18179) +OnRamp_forwardFromRouter:test_ShouldIncrementNonceOnlyOnOrdered_Success() (gas: 185252) +OnRamp_forwardFromRouter:test_ShouldIncrementSeqNumAndNonce_Success() (gas: 211543) +OnRamp_forwardFromRouter:test_ShouldStoreLinkFees() (gas: 125128) +OnRamp_forwardFromRouter:test_ShouldStoreNonLinkFees() (gas: 146530) +OnRamp_forwardFromRouter:test_SourceTokenDataTooLarge_Revert() (gas: 3891732) +OnRamp_forwardFromRouter:test_UnAllowedOriginalSender_Revert() (gas: 18609) +OnRamp_forwardFromRouter:test_UnsupportedToken_Revert() (gas: 111118) +OnRamp_forwardFromRouter:test_forwardFromRouter_UnsupportedToken_Revert() (gas: 76545) +OnRamp_forwardFromRouter:test_forwardFromRouter_WithValidation_Success() (gas: 278740) +OnRamp_forwardFromRouter:test_MultiCannotSendZeroTokens_Revert() (gas: 74456) +OnRamp_getFee:test_EmptyMessage_Success() (gas: 104331) +OnRamp_getFee:test_EnforceOutOfOrder_Revert() (gas: 73163) +OnRamp_getFee:test_SingleTokenMessage_Success() (gas: 119655) +OnRamp_getFee:test_Unhealthy_Revert() (gas: 43669) OnRamp_getSupportedTokens:test_GetSupportedTokens_Revert() (gas: 10438) -OnRamp_getTokenPool:test_GetTokenPool_Success() (gas: 35270) -OnRamp_setDynamicConfig:test_SetConfigInvalidConfigFeeAggregatorEqAddressZero_Revert() (gas: 11155) -OnRamp_setDynamicConfig:test_SetConfigInvalidConfigFeeQuoterEqAddressZero_Revert() (gas: 12763) -OnRamp_setDynamicConfig:test_SetConfigInvalidConfig_Revert() (gas: 11112) -OnRamp_setDynamicConfig:test_SetConfigOnlyOwner_Revert() (gas: 15939) -OnRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 52018) -OnRamp_withdrawFeeTokens:test_WithdrawFeeTokens_Success() (gas: 97192) +OnRamp_getTokenPool:test_GetTokenPool_Success() (gas: 35204) +OnRamp_setDynamicConfig:test_SetConfigInvalidConfigFeeAggregatorEqAddressZero_Revert() (gas: 11402) +OnRamp_setDynamicConfig:test_SetConfigInvalidConfigPriceRegistryEqAddressZero_Revert() (gas: 12978) +OnRamp_setDynamicConfig:test_SetConfigInvalidConfig_Revert() (gas: 11359) +OnRamp_setDynamicConfig:test_SetConfigOnlyOwner_Revert() (gas: 16385) +OnRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 55321) +OnRamp_setDynamicConfig:test_SetConfigInvalidConfigFeeQuoterEqAddressZero_Revert() (gas: 13001) +OnRamp_withdrawFeeTokens:test_WithdrawFeeTokens_Success() (gas: 97107) PingPong_ccipReceive:test_CcipReceive_Success() (gas: 150169) PingPong_plumbing:test_OutOfOrderExecution_Success() (gas: 20277) PingPong_plumbing:test_Pausing_Success() (gas: 17777) diff --git a/contracts/src/v0.8/ccip/onRamp/OnRamp.sol b/contracts/src/v0.8/ccip/onRamp/OnRamp.sol index aa4edba3ac..947859eb01 100644 --- a/contracts/src/v0.8/ccip/onRamp/OnRamp.sol +++ b/contracts/src/v0.8/ccip/onRamp/OnRamp.sol @@ -19,12 +19,14 @@ import {USDPriceWith18Decimals} from "../libraries/USDPriceWith18Decimals.sol"; import {IERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; import {SafeERC20} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; +import {EnumerableSet} from "../../vendor/openzeppelin-solidity/v5.0.2/contracts/utils/structs/EnumerableSet.sol"; /// @notice The OnRamp is a contract that handles lane-specific fee logic /// @dev The OnRamp and OffRamp form an xchain upgradeable unit. Any change to one of them /// results in an onchain upgrade of all 3. contract OnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCreator { using SafeERC20 for IERC20; + using EnumerableSet for EnumerableSet.AddressSet; using USDPriceWith18Decimals for uint224; error CannotSendZeroTokens(); @@ -35,13 +37,21 @@ contract OnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCreator { error CursedByRMN(uint64 sourceChainSelector); error GetSupportedTokensFunctionalityRemovedCheckAdminRegistry(); error InvalidDestChainConfig(uint64 sourceChainSelector); + error OnlyCallableByOwnerOrAllowlistAdmin(); + error SenderNotAllowed(address sender); + error InvalidAllowListRequest(uint64 destChainSelector); event ConfigSet(StaticConfig staticConfig, DynamicConfig dynamicConfig); - event DestChainConfigSet(uint64 indexed destChainSelector, DestChainConfig destChainConfig); + event DestChainConfigSet( + uint64 indexed destChainSelector, uint64 sequenceNumber, IRouter router, bool allowListEnabled + ); event FeePaid(address indexed feeToken, uint256 feeValueJuels); event FeeTokenWithdrawn(address indexed feeAggregator, address indexed feeToken, uint256 amount); /// RMN depends on this event, if changing, please notify the RMN maintainers. event CCIPSendRequested(uint64 indexed destChainSelector, Internal.EVM2AnyRampMessage message); + event AllowListAdminSet(address indexed allowListAdmin); + event AllowListSendersAdded(uint64 indexed destChainSelector, address[] senders); + event AllowListSendersRemoved(uint64 indexed destChainSelector, address[] senders); /// @dev Struct that contains the static configuration /// RMN depends on this struct, if changing, please notify the RMN maintainers. @@ -59,16 +69,19 @@ contract OnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCreator { address feeQuoter; // FeeQuoter address address messageValidator; // Optional message validator to validate outbound messages (zero address = no validator) address feeAggregator; // Fee aggregator address + address allowListAdmin; // authorized admin to add or remove allowed senders } /// @dev Struct to hold the configs for a destination chain + /// @dev sequenceNumber, allowListEnabled, router will all be packed in 1 slot struct DestChainConfig { // The last used sequence number. This is zero in the case where no messages have yet been sent. // 0 is not a valid sequence number for any real transaction. - uint64 sequenceNumber; - // This is the local router address that is allowed to send messages to the destination chain. - // This is NOT the receiving router address on the destination chain. - IRouter router; + uint64 sequenceNumber; // ──────╮ The last used sequence number + bool allowListEnabled; // │ boolean indicator to specify if allowList check is enabled + IRouter router; // ─────────────╯ Local router address that is allowed to send messages to the destination chain. + // This is the list of addresses allowed to send messages from onRamp + EnumerableSet.AddressSet allowedSendersList; } /// @dev Same as DestChainConfig but with the destChainSelector so that an array of these @@ -79,6 +92,19 @@ contract OnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCreator { IRouter router; // Source router address } + /// @dev Struct used to apply AllowList Senders for multiple destChainSelectors + /// @dev the senders in the AllowlistedSenders here is the user that sends the message + /// @dev the config restricts the chain to allow only allowedList of senders to send message from this chain to a destChainSelector + /// @dev destChainSelector, allowListEnabled will be packed in 1 slot + //solhint-disable gas-struct-packing + struct AllowListConfigArgs { + uint64 destChainSelector; // ─────────────╮ Destination chain selector + // │ destChainSelector and allowListEnabled are packed in the same slot + bool allowListEnabled; // ────────────────╯ boolean indicator to specify if allowList check is enabled. + address[] addedAllowlistedSenders; // list of senders to be added to the allowedSendersList + address[] removedAllowlistedSenders; // list of senders to be removed from the allowedSendersList + } + // STATIC CONFIG string public constant override typeAndVersion = "OnRamp 1.6.0-dev"; /// @dev The chain ID of the source chain that this contract is deployed to @@ -141,6 +167,13 @@ contract OnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCreator { // NOTE: assumes the message has already been validated through the getFee call // Validate message sender is set and allowed. Not validated in `getFee` since it is not user-driven. if (originalSender == address(0)) revert RouterMustSetOriginalSender(); + + if (destChainConfig.allowListEnabled) { + if (!destChainConfig.allowedSendersList.contains(originalSender)) { + revert SenderNotAllowed(originalSender); + } + } + // Router address may be zero intentionally to pause. if (msg.sender != address(destChainConfig.router)) revert MustBeCalledByRouter(); @@ -327,13 +360,82 @@ contract OnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCreator { revert InvalidDestChainConfig(destChainSelector); } - DestChainConfig memory newDestChainConfig = DestChainConfig({ - sequenceNumber: s_destChainConfigs[destChainSelector].sequenceNumber, - router: destChainConfigArg.router - }); - s_destChainConfigs[destChainSelector] = newDestChainConfig; + DestChainConfig storage destChainConfig = s_destChainConfigs[destChainSelector]; + destChainConfig.router = destChainConfigArg.router; + + emit DestChainConfigSet( + destChainSelector, destChainConfig.sequenceNumber, destChainConfigArg.router, destChainConfig.allowListEnabled + ); + } + } + + /// @notice get ChainConfig configured for the DestinationChainSelector + /// @param destChainSelector The destination chain selector + /// @return sequenceNumber The last used sequence number + /// @return allowListEnabled boolean indicator to specify if allowList check is enabled + /// @return router address of the router + function getDestChainConfig(uint64 destChainSelector) + public + view + returns (uint64 sequenceNumber, bool allowListEnabled, address router) + { + DestChainConfig storage config = s_destChainConfigs[destChainSelector]; + sequenceNumber = config.sequenceNumber; + allowListEnabled = config.allowListEnabled; + router = address(config.router); + return (sequenceNumber, allowListEnabled, router); + } + + /// @notice get allowedSenders List configured for the DestinationChainSelector + /// @param destChainSelector The destination chain selector + /// @return array of allowedList of Senders + function getAllowedSendersList(uint64 destChainSelector) public view returns (address[] memory) { + return s_destChainConfigs[destChainSelector].allowedSendersList.values(); + } + + // ================================================================ + // │ Allowlist │ + // ================================================================ + + /// @notice Updates allowListConfig for Senders + /// @dev configuration used to set the list of senders who are authorized to send messages + /// @param allowListConfigArgsItems Array of AllowListConfigArguments where each item is for a destChainSelector + function applyAllowListUpdates(AllowListConfigArgs[] calldata allowListConfigArgsItems) external { + if (msg.sender != owner()) { + if (msg.sender != s_dynamicConfig.allowListAdmin) { + revert OnlyCallableByOwnerOrAllowlistAdmin(); + } + } + + for (uint256 i = 0; i < allowListConfigArgsItems.length; ++i) { + AllowListConfigArgs memory allowListConfigArgs = allowListConfigArgsItems[i]; - emit DestChainConfigSet(destChainSelector, newDestChainConfig); + DestChainConfig storage destChainConfig = s_destChainConfigs[allowListConfigArgs.destChainSelector]; + destChainConfig.allowListEnabled = allowListConfigArgs.allowListEnabled; + + if (allowListConfigArgs.allowListEnabled) { + for (uint256 j = 0; j < allowListConfigArgs.addedAllowlistedSenders.length; ++j) { + address toAdd = allowListConfigArgs.addedAllowlistedSenders[j]; + if (toAdd == address(0)) { + revert InvalidAllowListRequest(allowListConfigArgs.destChainSelector); + } + destChainConfig.allowedSendersList.add(toAdd); + } + + if (allowListConfigArgs.addedAllowlistedSenders.length > 0) { + emit AllowListSendersAdded(allowListConfigArgs.destChainSelector, allowListConfigArgs.addedAllowlistedSenders); + } + } + + for (uint256 k = 0; k < allowListConfigArgs.removedAllowlistedSenders.length; ++k) { + destChainConfig.allowedSendersList.remove(allowListConfigArgs.removedAllowlistedSenders[k]); + } + + if (allowListConfigArgs.removedAllowlistedSenders.length > 0) { + emit AllowListSendersRemoved( + allowListConfigArgs.destChainSelector, allowListConfigArgs.removedAllowlistedSenders + ); + } } } diff --git a/contracts/src/v0.8/ccip/test/onRamp/OnRamp.t.sol b/contracts/src/v0.8/ccip/test/onRamp/OnRamp.t.sol index 43d57b4624..f69a4eafec 100644 --- a/contracts/src/v0.8/ccip/test/onRamp/OnRamp.t.sol +++ b/contracts/src/v0.8/ccip/test/onRamp/OnRamp.t.sol @@ -30,7 +30,7 @@ contract OnRamp_constructor is OnRampSetup { vm.expectEmit(); emit OnRamp.ConfigSet(staticConfig, dynamicConfig); vm.expectEmit(); - emit OnRamp.DestChainConfigSet(DEST_CHAIN_SELECTOR, OnRamp.DestChainConfig(0, s_sourceRouter)); + emit OnRamp.DestChainConfigSet(DEST_CHAIN_SELECTOR, 0, s_sourceRouter, false); _deployOnRamp(SOURCE_CHAIN_SELECTOR, s_sourceRouter, address(s_outboundNonceManager), address(s_tokenAdminRegistry)); @@ -117,6 +117,20 @@ contract OnRamp_forwardFromRouter is OnRampSetup { feeTokens[0] = s_sourceTokens[1]; s_feeQuoter.applyFeeTokensUpdates(feeTokens, new address[](0)); + uint64[] memory destinationChainSelectors = new uint64[](1); + destinationChainSelectors[0] = DEST_CHAIN_SELECTOR; + address[] memory addAllowedList = new address[](1); + addAllowedList[0] = OWNER; + OnRamp.AllowListConfigArgs memory allowListConfigArgs = OnRamp.AllowListConfigArgs({ + allowListEnabled: true, + destChainSelector: DEST_CHAIN_SELECTOR, + addedAllowlistedSenders: addAllowedList, + removedAllowlistedSenders: new address[](0) + }); + OnRamp.AllowListConfigArgs[] memory applyAllowListConfigArgsItems = new OnRamp.AllowListConfigArgs[](1); + applyAllowListConfigArgsItems[0] = allowListConfigArgs; + s_onRamp.applyAllowListUpdates(applyAllowListConfigArgsItems); + // Since we'll mostly be testing for valid calls from the router we'll // mock all calls to be originating from the router and re-mock in // tests that require failure. @@ -308,6 +322,25 @@ contract OnRamp_forwardFromRouter is OnRampSetup { vm.assume(originalSender != address(0)); vm.assume(uint160(receiver) >= Internal.PRECOMPILE_SPACE); feeTokenAmount = uint96(bound(feeTokenAmount, 0, MAX_MSG_FEES_JUELS)); + vm.stopPrank(); + + vm.startPrank(OWNER); + uint64[] memory destinationChainSelectors = new uint64[](1); + destinationChainSelectors[0] = uint64(DEST_CHAIN_SELECTOR); + address[] memory addAllowedList = new address[](1); + addAllowedList[0] = originalSender; + OnRamp.AllowListConfigArgs memory allowListConfigArgs = OnRamp.AllowListConfigArgs({ + allowListEnabled: true, + destChainSelector: DEST_CHAIN_SELECTOR, + addedAllowlistedSenders: addAllowedList, + removedAllowlistedSenders: new address[](0) + }); + OnRamp.AllowListConfigArgs[] memory applyAllowListConfigArgsItems = new OnRamp.AllowListConfigArgs[](1); + applyAllowListConfigArgsItems[0] = allowListConfigArgs; + s_onRamp.applyAllowListUpdates(applyAllowListConfigArgsItems); + vm.stopPrank(); + + vm.startPrank(address(s_sourceRouter)); Client.EVM2AnyMessage memory message = _generateEmptyMessage(); message.receiver = abi.encode(receiver); @@ -379,6 +412,13 @@ contract OnRamp_forwardFromRouter is OnRampSetup { s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, _generateEmptyMessage(), 0, address(0)); } + function test_UnAllowedOriginalSender_Revert() public { + vm.stopPrank(); + vm.startPrank(STRANGER); + vm.expectRevert(abi.encodeWithSelector(OnRamp.SenderNotAllowed.selector, STRANGER)); + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, _generateEmptyMessage(), 0, STRANGER); + } + function test_MessageValidationError_Revert() public { _enableOutboundMessageValidator(); @@ -398,13 +438,13 @@ contract OnRamp_forwardFromRouter is OnRampSetup { s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); } - function test_CannotSendZeroTokens_Revert() public { + function test_MultiCannotSendZeroTokens_Revert() public { Client.EVM2AnyMessage memory message = _generateEmptyMessage(); message.tokenAmounts = new Client.EVMTokenAmount[](1); message.tokenAmounts[0].amount = 0; message.tokenAmounts[0].token = s_sourceTokens[0]; vm.expectRevert(OnRamp.CannotSendZeroTokens.selector); - s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, STRANGER); + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); } function test_UnsupportedToken_Revert() public { @@ -602,7 +642,8 @@ contract OnRamp_setDynamicConfig is OnRampSetup { OnRamp.DynamicConfig memory newConfig = OnRamp.DynamicConfig({ feeQuoter: address(23423), messageValidator: makeAddr("messageValidator"), - feeAggregator: FEE_AGGREGATOR + feeAggregator: FEE_AGGREGATOR, + allowListAdmin: address(0) }); vm.expectEmit(); @@ -620,7 +661,8 @@ contract OnRamp_setDynamicConfig is OnRampSetup { OnRamp.DynamicConfig memory newConfig = OnRamp.DynamicConfig({ feeQuoter: address(0), feeAggregator: FEE_AGGREGATOR, - messageValidator: makeAddr("messageValidator") + messageValidator: makeAddr("messageValidator"), + allowListAdmin: address(0) }); vm.expectRevert(OnRamp.InvalidConfig.selector); @@ -628,8 +670,12 @@ contract OnRamp_setDynamicConfig is OnRampSetup { } function test_SetConfigInvalidConfig_Revert() public { - OnRamp.DynamicConfig memory newConfig = - OnRamp.DynamicConfig({feeQuoter: address(23423), messageValidator: address(0), feeAggregator: FEE_AGGREGATOR}); + OnRamp.DynamicConfig memory newConfig = OnRamp.DynamicConfig({ + feeQuoter: address(23423), + messageValidator: address(0), + feeAggregator: FEE_AGGREGATOR, + allowListAdmin: address(0) + }); // Invalid price reg reverts. newConfig.feeQuoter = address(0); @@ -638,8 +684,13 @@ contract OnRamp_setDynamicConfig is OnRampSetup { } function test_SetConfigInvalidConfigFeeAggregatorEqAddressZero_Revert() public { - OnRamp.DynamicConfig memory newConfig = - OnRamp.DynamicConfig({feeQuoter: address(23423), messageValidator: address(0), feeAggregator: address(0)}); + OnRamp.DynamicConfig memory newConfig = OnRamp.DynamicConfig({ + feeQuoter: address(23423), + messageValidator: address(0), + feeAggregator: address(0), + allowListAdmin: address(0) + }); + vm.expectRevert(OnRamp.InvalidConfig.selector); s_onRamp.setDynamicConfig(newConfig); } @@ -740,7 +791,7 @@ contract OnRamp_applyDestChainConfigUpdates is OnRampSetup { // supports disabling a lane by setting a router to zero vm.expectEmit(); - emit OnRamp.DestChainConfigSet(DEST_CHAIN_SELECTOR, OnRamp.DestChainConfig(0, IRouter(address(0)))); + emit OnRamp.DestChainConfigSet(DEST_CHAIN_SELECTOR, 0, IRouter(address(0)), false); s_onRamp.applyDestChainConfigUpdates(configArgs); assertEq(address(0), address(s_onRamp.getRouter(DEST_CHAIN_SELECTOR))); @@ -749,9 +800,9 @@ contract OnRamp_applyDestChainConfigUpdates is OnRampSetup { configArgs[0] = OnRamp.DestChainConfigArgs({destChainSelector: DEST_CHAIN_SELECTOR, router: s_sourceRouter}); configArgs[1] = OnRamp.DestChainConfigArgs({destChainSelector: 9999, router: IRouter(address(9999))}); vm.expectEmit(); - emit OnRamp.DestChainConfigSet(DEST_CHAIN_SELECTOR, OnRamp.DestChainConfig(0, s_sourceRouter)); + emit OnRamp.DestChainConfigSet(DEST_CHAIN_SELECTOR, 0, s_sourceRouter, false); vm.expectEmit(); - emit OnRamp.DestChainConfigSet(9999, OnRamp.DestChainConfig(0, IRouter(address(9999)))); + emit OnRamp.DestChainConfigSet(9999, 0, IRouter(address(9999)), false); s_onRamp.applyDestChainConfigUpdates(configArgs); assertEq(address(s_sourceRouter), address(s_onRamp.getRouter(DEST_CHAIN_SELECTOR))); assertEq(address(9999), address(s_onRamp.getRouter(9999))); @@ -763,7 +814,7 @@ contract OnRamp_applyDestChainConfigUpdates is OnRampSetup { assertEq(numLogs, vm.getRecordedLogs().length); // indicates no changes made } - function test_ApplyDestChainConfigUpdates_WithInalidChainSelector_Revert() external { + function test_ApplyDestChainConfigUpdates_WithInvalidChainSelector_Revert() external { vm.stopPrank(); vm.startPrank(OWNER); OnRamp.DestChainConfigArgs[] memory configArgs = new OnRamp.DestChainConfigArgs[](1); @@ -772,3 +823,141 @@ contract OnRamp_applyDestChainConfigUpdates is OnRampSetup { s_onRamp.applyDestChainConfigUpdates(configArgs); } } + +contract OnRamp_allowListConfigUpdates is OnRampSetup { + function test_applyAllowList_Success() public { + vm.stopPrank(); + vm.startPrank(OWNER); + + OnRamp.DestChainConfigArgs[] memory configArgs = new OnRamp.DestChainConfigArgs[](2); + configArgs[0] = OnRamp.DestChainConfigArgs({destChainSelector: DEST_CHAIN_SELECTOR, router: s_sourceRouter}); + configArgs[1] = OnRamp.DestChainConfigArgs({destChainSelector: 9999, router: IRouter(address(9999))}); + vm.expectEmit(); + emit OnRamp.DestChainConfigSet(DEST_CHAIN_SELECTOR, 0, s_sourceRouter, false); + vm.expectEmit(); + emit OnRamp.DestChainConfigSet(9999, 0, IRouter(address(9999)), false); + s_onRamp.applyDestChainConfigUpdates(configArgs); + + (uint64 sequenceNumber, bool allowListEnabled, address router) = s_onRamp.getDestChainConfig(9999); + assertEq(sequenceNumber, 0); + assertEq(allowListEnabled, false); + assertEq(router, address(9999)); + + uint64[] memory destinationChainSelectors = new uint64[](2); + destinationChainSelectors[0] = DEST_CHAIN_SELECTOR; + destinationChainSelectors[1] = uint64(99999); + + address[] memory addedAllowlistedSenders = new address[](4); + addedAllowlistedSenders[0] = vm.addr(1); + addedAllowlistedSenders[1] = vm.addr(2); + addedAllowlistedSenders[2] = vm.addr(3); + addedAllowlistedSenders[3] = vm.addr(4); + + vm.expectEmit(); + emit OnRamp.AllowListSendersAdded(DEST_CHAIN_SELECTOR, addedAllowlistedSenders); + + OnRamp.AllowListConfigArgs memory allowListConfigArgs = OnRamp.AllowListConfigArgs({ + allowListEnabled: true, + destChainSelector: DEST_CHAIN_SELECTOR, + addedAllowlistedSenders: addedAllowlistedSenders, + removedAllowlistedSenders: new address[](0) + }); + + OnRamp.AllowListConfigArgs[] memory applyAllowListConfigArgsItems = new OnRamp.AllowListConfigArgs[](1); + applyAllowListConfigArgsItems[0] = allowListConfigArgs; + + s_onRamp.applyAllowListUpdates(applyAllowListConfigArgsItems); + assertEq(4, s_onRamp.getAllowedSendersList(DEST_CHAIN_SELECTOR).length); + + assertEq(addedAllowlistedSenders, s_onRamp.getAllowedSendersList(DEST_CHAIN_SELECTOR)); + + address[] memory removedAllowlistedSenders = new address[](1); + removedAllowlistedSenders[0] = vm.addr(2); + + vm.expectEmit(); + emit OnRamp.AllowListSendersRemoved(DEST_CHAIN_SELECTOR, removedAllowlistedSenders); + + allowListConfigArgs = OnRamp.AllowListConfigArgs({ + allowListEnabled: true, + destChainSelector: DEST_CHAIN_SELECTOR, + addedAllowlistedSenders: new address[](0), + removedAllowlistedSenders: removedAllowlistedSenders + }); + + OnRamp.AllowListConfigArgs[] memory allowListConfigArgsItems_2 = new OnRamp.AllowListConfigArgs[](1); + allowListConfigArgsItems_2[0] = allowListConfigArgs; + + s_onRamp.applyAllowListUpdates(allowListConfigArgsItems_2); + assertEq(3, s_onRamp.getAllowedSendersList(DEST_CHAIN_SELECTOR).length); + + addedAllowlistedSenders = new address[](2); + addedAllowlistedSenders[0] = vm.addr(5); + addedAllowlistedSenders[1] = vm.addr(6); + + removedAllowlistedSenders = new address[](2); + removedAllowlistedSenders[0] = vm.addr(1); + removedAllowlistedSenders[1] = vm.addr(3); + + vm.expectEmit(); + emit OnRamp.AllowListSendersAdded(DEST_CHAIN_SELECTOR, addedAllowlistedSenders); + emit OnRamp.AllowListSendersRemoved(DEST_CHAIN_SELECTOR, removedAllowlistedSenders); + + allowListConfigArgs = OnRamp.AllowListConfigArgs({ + allowListEnabled: true, + destChainSelector: DEST_CHAIN_SELECTOR, + addedAllowlistedSenders: addedAllowlistedSenders, + removedAllowlistedSenders: removedAllowlistedSenders + }); + + OnRamp.AllowListConfigArgs[] memory allowListConfigArgsItems_3 = new OnRamp.AllowListConfigArgs[](1); + allowListConfigArgsItems_3[0] = allowListConfigArgs; + + s_onRamp.applyAllowListUpdates(allowListConfigArgsItems_3); + assertEq(3, s_onRamp.getAllowedSendersList(DEST_CHAIN_SELECTOR).length); + } + + function test_applyAllowList_Revert() public { + vm.stopPrank(); + vm.startPrank(OWNER); + + OnRamp.DestChainConfigArgs[] memory configArgs = new OnRamp.DestChainConfigArgs[](2); + configArgs[0] = OnRamp.DestChainConfigArgs({destChainSelector: DEST_CHAIN_SELECTOR, router: s_sourceRouter}); + configArgs[1] = OnRamp.DestChainConfigArgs({destChainSelector: 9999, router: IRouter(address(9999))}); + vm.expectEmit(); + emit OnRamp.DestChainConfigSet(DEST_CHAIN_SELECTOR, 0, s_sourceRouter, false); + vm.expectEmit(); + emit OnRamp.DestChainConfigSet(9999, 0, IRouter(address(9999)), false); + s_onRamp.applyDestChainConfigUpdates(configArgs); + + uint64[] memory destinationChainSelectors = new uint64[](2); + destinationChainSelectors[0] = DEST_CHAIN_SELECTOR; + destinationChainSelectors[1] = uint64(99999); + + address[] memory addedAllowlistedSenders = new address[](4); + addedAllowlistedSenders[0] = vm.addr(1); + addedAllowlistedSenders[1] = vm.addr(2); + addedAllowlistedSenders[2] = vm.addr(3); + addedAllowlistedSenders[3] = vm.addr(4); + + OnRamp.AllowListConfigArgs memory allowListConfigArgs = OnRamp.AllowListConfigArgs({ + allowListEnabled: true, + destChainSelector: DEST_CHAIN_SELECTOR, + addedAllowlistedSenders: addedAllowlistedSenders, + removedAllowlistedSenders: new address[](0) + }); + + OnRamp.AllowListConfigArgs[] memory applyAllowListConfigArgsItems = new OnRamp.AllowListConfigArgs[](1); + applyAllowListConfigArgsItems[0] = allowListConfigArgs; + + vm.startPrank(STRANGER); + vm.expectRevert(OnRamp.OnlyCallableByOwnerOrAllowlistAdmin.selector); + s_onRamp.applyAllowListUpdates(applyAllowListConfigArgsItems); + vm.stopPrank(); + + applyAllowListConfigArgsItems[0].addedAllowlistedSenders[0] = address(0); + vm.expectRevert(abi.encodeWithSelector(OnRamp.InvalidAllowListRequest.selector, DEST_CHAIN_SELECTOR)); + vm.startPrank(OWNER); + s_onRamp.applyAllowListUpdates(applyAllowListConfigArgsItems); + vm.stopPrank(); + } +} diff --git a/contracts/src/v0.8/ccip/test/onRamp/OnRampSetup.t.sol b/contracts/src/v0.8/ccip/test/onRamp/OnRampSetup.t.sol index 635a75c843..f43bce6a99 100644 --- a/contracts/src/v0.8/ccip/test/onRamp/OnRampSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/onRamp/OnRampSetup.t.sol @@ -85,7 +85,12 @@ contract OnRampSetup is FeeQuoterFeeSetup { } function _generateDynamicOnRampConfig(address feeQuoter) internal pure returns (OnRamp.DynamicConfig memory) { - return OnRamp.DynamicConfig({feeQuoter: feeQuoter, messageValidator: address(0), feeAggregator: FEE_AGGREGATOR}); + return OnRamp.DynamicConfig({ + feeQuoter: feeQuoter, + messageValidator: address(0), + feeAggregator: FEE_AGGREGATOR, + allowListAdmin: address(0) + }); } // Slicing is only available for calldata. So we have to build a new bytes array. diff --git a/core/gethwrappers/ccip/generated/onramp/onramp.go b/core/gethwrappers/ccip/generated/onramp/onramp.go index db21305dc8..dd2428a143 100644 --- a/core/gethwrappers/ccip/generated/onramp/onramp.go +++ b/core/gethwrappers/ccip/generated/onramp/onramp.go @@ -70,9 +70,11 @@ type InternalRampTokenAmount struct { DestExecData []byte } -type OnRampDestChainConfig struct { - SequenceNumber uint64 - Router common.Address +type OnRampAllowListConfigArgs struct { + DestChainSelector uint64 + AllowListEnabled bool + AddedAllowlistedSenders []common.Address + RemovedAllowlistedSenders []common.Address } type OnRampDestChainConfigArgs struct { @@ -84,6 +86,7 @@ type OnRampDynamicConfig struct { FeeQuoter common.Address MessageValidator common.Address FeeAggregator common.Address + AllowListAdmin common.Address } type OnRampStaticConfig struct { @@ -94,8 +97,8 @@ type OnRampStaticConfig struct { } var OnRampMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CannotSendZeroTokens\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GetSupportedTokensFunctionalityRemovedCheckAdminRegistry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidDestChainConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeCalledByRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RouterMustSetOriginalSender\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"UnsupportedToken\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"CCIPSendRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOnRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOnRamp.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"name\":\"DestChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"feeValueJuels\",\"type\":\"uint256\"}],\"name\":\"FeePaid\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeeTokenWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyDestChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"}],\"name\":\"forwardFromRouter\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getExpectedNextSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"getFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"},{\"internalType\":\"contractIERC20\",\"name\":\"sourceToken\",\"type\":\"address\"}],\"name\":\"getPoolBySourceToken\",\"outputs\":[{\"internalType\":\"contractIPoolV1\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"contractIRouter\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"name\":\"getSupportedTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"setDynamicConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"withdrawFeeTokens\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x6101006040523480156200001257600080fd5b506040516200382d3803806200382d83398101604081905262000035916200069c565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf8162000186565b505083516001600160401b031615905080620000e6575060208301516001600160a01b0316155b80620000fd575060408301516001600160a01b0316155b8062000114575060608301516001600160a01b0316155b1562000133576040516306b7c75960e31b815260040160405180910390fd5b82516001600160401b031660805260208301516001600160a01b0390811660a0526040840151811660c05260608401511660e052620001728262000231565b6200017d816200036d565b5050506200079c565b336001600160a01b03821603620001e05760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b0316158062000254575060408101516001600160a01b0316155b1562000273576040516306b7c75960e31b815260040160405180910390fd5b8051600280546001600160a01b03199081166001600160a01b03938416179091556020808401805160038054851691861691909117905560408086018051600480549096169087161790945580516080808201835280516001600160401b031680835260a08051891684880190815260c080518b1686880190815260e080518d166060988901908152895196875293518d169a86019a909a52518b169684019690965251891693820193909352885188169181019190915292518616908301529251909316918301919091527f2d8f19dc1cd01460c3367a09d2d424f2b1940ba7c886047edd078c7b77ea4558910160405180910390a150565b60005b8151811015620004aa57600082828151811062000391576200039162000786565b602002602001015190506000838381518110620003b257620003b262000786565b6020026020010151600001519050806001600160401b0316600003620003f75760405163c35aa79d60e01b81526001600160401b038216600482015260240162000083565b6040805180820182526001600160401b03838116600081815260056020818152868320805480871688528a8301516001600160a01b03908116848a019081529587905293835287518551851668010000000000000000026001600160e01b0319909216971696871717905586519485529151169083015291927f324d4a7950b57da00ce533ad6697039be6281726a73da959d0ab3ff795181ec6910160405180910390a250505080600101905062000370565b5050565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b0381118282101715620004e957620004e9620004ae565b60405290565b604051601f8201601f191681016001600160401b03811182821017156200051a576200051a620004ae565b604052919050565b80516001600160401b03811681146200053a57600080fd5b919050565b6001600160a01b03811681146200055557600080fd5b50565b6000606082840312156200056b57600080fd5b604051606081016001600160401b0381118282101715620005905762000590620004ae565b80604052508091508251620005a5816200053f565b81526020830151620005b7816200053f565b60208201526040830151620005cc816200053f565b6040919091015292915050565b600082601f830112620005eb57600080fd5b815160206001600160401b03821115620006095762000609620004ae565b62000619818360051b01620004ef565b82815260069290921b840181019181810190868411156200063957600080fd5b8286015b84811015620006915760408189031215620006585760008081fd5b62000662620004c4565b6200066d8262000522565b8152848201516200067e816200053f565b818601528352918301916040016200063d565b509695505050505050565b6000806000838503610100811215620006b457600080fd5b6080811215620006c357600080fd5b50604051608081016001600160401b038082118383101715620006ea57620006ea620004ae565b81604052620006f98762000522565b8352602087015191506200070d826200053f565b8160208401526040870151915062000725826200053f565b816040840152606087015191506200073d826200053f565b81606084015282955062000755886080890162000558565b945060e08701519250808311156200076c57600080fd5b50506200077c86828701620005d9565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b60805160a05160c05160e05161301862000815600039600081816101eb015281816108a201526116700152600081816101af01528181610dc60152611649015260008181610173015281816104c4015261161f01526000818161014301528181610cec0152818161121101526115f201526130186000f3fe608060405234801561001057600080fd5b50600436106100f55760003560e01c80637437ff9f11610097578063d77d5ed011610066578063d77d5ed0146103ba578063df0aa9e914610406578063f2fde38b14610419578063fbca3b741461042c57600080fd5b80637437ff9f146102fb57806379ba5097146103685780638da5cb5b146103705780639041be3d1461038e57600080fd5b806320487ded116100d357806320487ded1461028757806334d560e4146102a85780633a019940146102bb57806348a98aa4146102c357600080fd5b80630242cf60146100fa57806306285c691461010f578063181f5a771461023e575b600080fd5b61010d610108366004612098565b61044c565b005b61022860408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16815250905090565b604051610235919061215b565b60405180910390f35b61027a6040518060400160405280601081526020017f4f6e52616d7020312e362e302d6465760000000000000000000000000000000081525081565b6040516102359190612220565b61029a61029536600461224b565b610460565b604051908152602001610235565b61010d6102b63660046122ab565b610619565b61010d61062a565b6102d66102d136600461231d565b61085a565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610235565b61035b6040805160608101825260008082526020820181905291810191909152506040805160608101825260025473ffffffffffffffffffffffffffffffffffffffff908116825260035481166020830152600454169181019190915290565b6040516102359190612356565b61010d61090f565b60005473ffffffffffffffffffffffffffffffffffffffff166102d6565b6103a161039c366004612393565b610a0c565b60405167ffffffffffffffff9091168152602001610235565b6102d66103c8366004612393565b67ffffffffffffffff1660009081526005602052604090205468010000000000000000900473ffffffffffffffffffffffffffffffffffffffff1690565b61029a6104143660046123b0565b610a35565b61010d61042736600461241c565b6112c6565b61043f61043a366004612393565b6112d7565b6040516102359190612439565b61045461130b565b61045d8161138e565b50565b6040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815277ffffffffffffffff00000000000000000000000000000000608084901b16600482015260009073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690632cbc26bb90602401602060405180830381865afa15801561050b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061052f91906124a3565b15610577576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024015b60405180910390fd5b6002546040517fd8694ccd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063d8694ccd906105cf90869086906004016125d2565b602060405180830381865afa1580156105ec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610610919061271b565b90505b92915050565b61062161130b565b61045d81611506565b600254604080517fcdc73d51000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163cdc73d5191600480830192869291908290030181865afa158015610699573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526106df9190810190612734565b60045490915073ffffffffffffffffffffffffffffffffffffffff1660005b825181101561085557600083828151811061071b5761071b6127c3565b60209081029190910101516040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915060009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa158015610796573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107ba919061271b565b9050801561084b576107e373ffffffffffffffffffffffffffffffffffffffff831685836116d0565b8173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f508d7d183612c18fc339b42618912b9fa3239f631dd7ec0671f950200a0fa66e8360405161084291815260200190565b60405180910390a35b50506001016106fe565b505050565b6040517fbbe4f6db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063bbe4f6db90602401602060405180830381865afa1580156108eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061061091906127f2565b60015473ffffffffffffffffffffffffffffffffffffffff163314610990576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e657200000000000000000000604482015260640161056e565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b67ffffffffffffffff80821660009081526005602052604081205490916106139116600161283e565b67ffffffffffffffff8416600090815260056020526040812073ffffffffffffffffffffffffffffffffffffffff8316610a9b576040517fa4ec747900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805468010000000000000000900473ffffffffffffffffffffffffffffffffffffffff163314610af7576040517f1c0a352900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60035473ffffffffffffffffffffffffffffffffffffffff168015610b9d576040517fe0a0e50600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82169063e0a0e50690610b6a908a908a906004016125d2565b600060405180830381600087803b158015610b8457600080fd5b505af1158015610b98573d6000803e3d6000fd5b505050505b506002546000908190819073ffffffffffffffffffffffffffffffffffffffff1663c4276bfc8a610bd460808c0160608d0161241c565b8a610be260808e018e612866565b6040518663ffffffff1660e01b8152600401610c029594939291906128cb565b600060405180830381865afa158015610c1f573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610c659190810190612993565b91945092509050610c7c6080890160608a0161241c565b73ffffffffffffffffffffffffffffffffffffffff167f075a2720282fdf622141dae0b048ef90a21a7e57c134c76912d19d006b3b3f6f84604051610cc391815260200190565b60405180910390a2604080516101a081019091526000610100820181815267ffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000081166101208501528c811661014085015287549293928392916101608401918a918791610d3891166129ea565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905567ffffffffffffffff16815260200186610e38576040517fea458c0c00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8f16600482015273ffffffffffffffffffffffffffffffffffffffff8c811660248301527f0000000000000000000000000000000000000000000000000000000000000000169063ea458c0c906044016020604051808303816000875af1158015610e0f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e339190612a11565b610e3b565b60005b67ffffffffffffffff1681525081526020018873ffffffffffffffffffffffffffffffffffffffff1681526020018a8060200190610e799190612866565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250505090825250602001610ebd8b80612866565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250505090825250602001610f0460808c018c612866565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250505090825250602001610f4e60808c0160608d0161241c565b73ffffffffffffffffffffffffffffffffffffffff1681526020018981526020018a8060400190610f7f9190612a2e565b905067ffffffffffffffff811115610f9957610f99611f95565b604051908082528060200260200182016040528015610ffc57816020015b610fe96040518060a0016040528060608152602001606081526020016060815260200160008152602001606081525090565b815260200190600190039081610fb75790505b509052905060005b61101160408b018b612a2e565b90508110156110c05761109761102a60408c018c612a2e565b8381811061103a5761103a6127c3565b9050604002018036038101906110509190612a96565b8c61105b8d80612866565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508e925061175d915050565b8260e0015182815181106110ad576110ad6127c3565b6020908102919091010152600101611004565b5060025460e082015160009173ffffffffffffffffffffffffffffffffffffffff169063085318f8908d906110f860408f018f612a2e565b6040518563ffffffff1660e01b81526004016111179493929190612bad565b600060405180830381865afa158015611134573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261117a9190810190612be3565b905060005b8260e00151518110156111d35781818151811061119e5761119e6127c3565b60200260200101518360e0015182815181106111bc576111bc6127c3565b60209081029190910101516080015260010161117f565b506080808301849052604080517f130ac867e79e2789f923760a88743d292acdf7002139a588206e2260f73f7321602082015267ffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811692820192909252908d166060820152309181019190915261126d90839060a00160405160208183030381529060405280519060200120611a83565b82515260405167ffffffffffffffff8c16907fcae3d9f68a9ed33d0a770e9bcc6fc25d4041dd6391e6cd8015546547a3c93140906112ac908590612c94565b60405180910390a25051519450505050505b949350505050565b6112ce61130b565b61045d81611b83565b60606040517f9e7177c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005473ffffffffffffffffffffffffffffffffffffffff16331461138c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640161056e565b565b60005b81518110156115025760008282815181106113ae576113ae6127c3565b6020026020010151905060008383815181106113cc576113cc6127c3565b60200260200101516000015190508067ffffffffffffffff1660000361142a576040517fc35aa79d00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8216600482015260240161056e565b60408051808201825267ffffffffffffffff838116600081815260056020818152868320805480871688528a83015173ffffffffffffffffffffffffffffffffffffffff908116848a019081529587905293835287518551851668010000000000000000027fffffffff00000000000000000000000000000000000000000000000000000000909216971696871717905586519485529151169083015291927f324d4a7950b57da00ce533ad6697039be6281726a73da959d0ab3ff795181ec6910160405180910390a2505050806001019050611391565b5050565b805173ffffffffffffffffffffffffffffffffffffffff1615806115425750604081015173ffffffffffffffffffffffffffffffffffffffff16155b15611579576040517f35be3ac800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051600280547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff93841617909155602080840151600380548416918516919091179055604080850151600480549094169085161790925581516080810183527f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681527f00000000000000000000000000000000000000000000000000000000000000008416918101919091527f00000000000000000000000000000000000000000000000000000000000000008316818301527f00000000000000000000000000000000000000000000000000000000000000009092166060830152517f2d8f19dc1cd01460c3367a09d2d424f2b1940ba7c886047edd078c7b77ea4558916116c5918490612de2565b60405180910390a150565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052610855908490611c78565b61178f6040518060a0016040528060608152602001606081526020016060815260200160008152602001606081525090565b84602001516000036117cd576040517f5cf0444900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006117dd85876000015161085a565b905073ffffffffffffffffffffffffffffffffffffffff811615806118ad57506040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527faff2afbf00000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff8216906301ffc9a790602401602060405180830381865afa158015611887573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118ab91906124a3565b155b156118ff5785516040517fbf16aab600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116600482015260240161056e565b60008173ffffffffffffffffffffffffffffffffffffffff16639a4575b96040518060a001604052808881526020018967ffffffffffffffff1681526020018773ffffffffffffffffffffffffffffffffffffffff1681526020018a6020015181526020018a6000015173ffffffffffffffffffffffffffffffffffffffff168152506040518263ffffffff1660e01b815260040161199e9190612e74565b6000604051808303816000875af11580156119bd573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611a039190810190612eea565b6040805160a0810190915273ffffffffffffffffffffffffffffffffffffffff841660c08201529091508060e0810160405160208183030381529060405281526020018260000151815260200182602001518152602001886020015181526020016040518060200160405280600081525081525092505050949350505050565b60008060001b82846020015185606001518660000151606001518760000151608001518860a001518960c00151604051602001611ac596959493929190612f7b565b604051602081830303815290604052805190602001208560400151805190602001208660e00151604051602001611afc9190612fdc565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201206080808c0151805190840120928501989098529183019590955260608201939093529384015260a083015260c082015260e00160405160208183030381529060405280519060200120905092915050565b3373ffffffffffffffffffffffffffffffffffffffff821603611c02576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161056e565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000611cda826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611d849092919063ffffffff16565b8051909150156108555780806020019051810190611cf891906124a3565b610855576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f74207375636365656400000000000000000000000000000000000000000000606482015260840161056e565b6060611d938484600085611d9d565b90505b9392505050565b606082471015611e2f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c0000000000000000000000000000000000000000000000000000606482015260840161056e565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051611e589190612fef565b60006040518083038185875af1925050503d8060008114611e95576040519150601f19603f3d011682016040523d82523d6000602084013e611e9a565b606091505b5091509150611eab87838387611eb6565b979650505050505050565b60608315611f4c578251600003611f455773ffffffffffffffffffffffffffffffffffffffff85163b611f45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161056e565b50816112be565b6112be8383815115611f615781518083602001fd5b806040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161056e9190612220565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715611fe757611fe7611f95565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561203457612034611f95565b604052919050565b600067ffffffffffffffff82111561205657612056611f95565b5060051b60200190565b67ffffffffffffffff8116811461045d57600080fd5b73ffffffffffffffffffffffffffffffffffffffff8116811461045d57600080fd5b600060208083850312156120ab57600080fd5b823567ffffffffffffffff8111156120c257600080fd5b8301601f810185136120d357600080fd5b80356120e66120e18261203c565b611fed565b81815260069190911b8201830190838101908783111561210557600080fd5b928401925b82841015611eab57604084890312156121235760008081fd5b61212b611fc4565b843561213681612060565b81528486013561214581612076565b818701528252604093909301929084019061210a565b60808101610613828467ffffffffffffffff8151168252602081015173ffffffffffffffffffffffffffffffffffffffff808216602085015280604084015116604085015280606084015116606085015250505050565b60005b838110156121cd5781810151838201526020016121b5565b50506000910152565b600081518084526121ee8160208601602086016121b2565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061061060208301846121d6565b600060a0828403121561224557600080fd5b50919050565b6000806040838503121561225e57600080fd5b823561226981612060565b9150602083013567ffffffffffffffff81111561228557600080fd5b61229185828601612233565b9150509250929050565b80356122a681612076565b919050565b6000606082840312156122bd57600080fd5b6040516060810181811067ffffffffffffffff821117156122e0576122e0611f95565b60405282356122ee81612076565b815260208301356122fe81612076565b6020820152604083013561231181612076565b60408201529392505050565b6000806040838503121561233057600080fd5b823561233b81612060565b9150602083013561234b81612076565b809150509250929050565b606081016106138284805173ffffffffffffffffffffffffffffffffffffffff908116835260208083015182169084015260409182015116910152565b6000602082840312156123a557600080fd5b8135611d9681612060565b600080600080608085870312156123c657600080fd5b84356123d181612060565b9350602085013567ffffffffffffffff8111156123ed57600080fd5b6123f987828801612233565b93505060408501359150606085013561241181612076565b939692955090935050565b60006020828403121561242e57600080fd5b8135611d9681612076565b6020808252825182820181905260009190848201906040850190845b8181101561248757835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101612455565b50909695505050505050565b805180151581146122a657600080fd5b6000602082840312156124b557600080fd5b61061082612493565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126124f357600080fd5b830160208101925035905067ffffffffffffffff81111561251357600080fd5b80360382131561252257600080fd5b9250929050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b8183526000602080850194508260005b858110156125c757813561259581612076565b73ffffffffffffffffffffffffffffffffffffffff168752818301358388015260409687019690910190600101612582565b509495945050505050565b600067ffffffffffffffff8085168352604060208401526125f384856124be565b60a0604086015261260860e086018284612529565b91505061261860208601866124be565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08087850301606088015261264e848385612529565b9350604088013592507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe188360301831261268757600080fd5b602092880192830192359150848211156126a057600080fd5b8160061b36038313156126b257600080fd5b808785030160808801526126c7848385612572565b94506126d56060890161229b565b73ffffffffffffffffffffffffffffffffffffffff811660a0890152935061270060808901896124be565b94509250808786030160c08801525050611eab838383612529565b60006020828403121561272d57600080fd5b5051919050565b6000602080838503121561274757600080fd5b825167ffffffffffffffff81111561275e57600080fd5b8301601f8101851361276f57600080fd5b805161277d6120e18261203c565b81815260059190911b8201830190838101908783111561279c57600080fd5b928401925b82841015611eab5783516127b481612076565b825292840192908401906127a1565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561280457600080fd5b8151611d9681612076565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b67ffffffffffffffff81811683821601908082111561285f5761285f61280f565b5092915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261289b57600080fd5b83018035915067ffffffffffffffff8211156128b657600080fd5b60200191503681900382131561252257600080fd5b67ffffffffffffffff8616815273ffffffffffffffffffffffffffffffffffffffff85166020820152836040820152608060608201526000611eab608083018486612529565b600082601f83011261292257600080fd5b815167ffffffffffffffff81111561293c5761293c611f95565b61296d60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611fed565b81815284602083860101111561298257600080fd5b6112be8260208301602087016121b2565b6000806000606084860312156129a857600080fd5b835192506129b860208501612493565b9150604084015167ffffffffffffffff8111156129d457600080fd5b6129e086828701612911565b9150509250925092565b600067ffffffffffffffff808316818103612a0757612a0761280f565b6001019392505050565b600060208284031215612a2357600080fd5b8151611d9681612060565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112612a6357600080fd5b83018035915067ffffffffffffffff821115612a7e57600080fd5b6020019150600681901b360382131561252257600080fd5b600060408284031215612aa857600080fd5b612ab0611fc4565b8235612abb81612076565b81526020928301359281019290925250919050565b600082825180855260208086019550808260051b84010181860160005b84811015612ba0577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018952815160a08151818652612b31828701826121d6565b9150508582015185820387870152612b4982826121d6565b91505060408083015186830382880152612b6383826121d6565b92505050606080830151818701525060808083015192508582038187015250612b8c81836121d6565b9a86019a9450505090830190600101612aed565b5090979650505050505050565b67ffffffffffffffff85168152606060208201526000612bd06060830186612ad0565b8281036040840152611eab818587612572565b60006020808385031215612bf657600080fd5b825167ffffffffffffffff80821115612c0e57600080fd5b818501915085601f830112612c2257600080fd5b8151612c306120e18261203c565b81815260059190911b83018401908481019088831115612c4f57600080fd5b8585015b83811015612c8757805185811115612c6b5760008081fd5b612c798b89838a0101612911565b845250918601918601612c53565b5098975050505050505050565b60208152612ce560208201835180518252602081015167ffffffffffffffff808216602085015280604084015116604085015280606084015116606085015280608084015116608085015250505050565b60006020830151612d0e60c084018273ffffffffffffffffffffffffffffffffffffffff169052565b5060408301516101808060e0850152612d2b6101a08501836121d6565b915060608501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08086850301610100870152612d6884836121d6565b9350608087015191508086850301610120870152612d8684836121d6565b935060a08701519150612db261014087018373ffffffffffffffffffffffffffffffffffffffff169052565b60c087015161016087015260e0870151915080868503018387015250612dd88382612ad0565b9695505050505050565b60e08101612e39828567ffffffffffffffff8151168252602081015173ffffffffffffffffffffffffffffffffffffffff808216602085015280604084015116604085015280606084015116606085015250505050565b825173ffffffffffffffffffffffffffffffffffffffff90811660808401526020840151811660a084015260408401511660c0830152611d96565b602081526000825160a06020840152612e9060c08401826121d6565b905067ffffffffffffffff6020850151166040840152604084015173ffffffffffffffffffffffffffffffffffffffff8082166060860152606086015160808601528060808701511660a086015250508091505092915050565b600060208284031215612efc57600080fd5b815167ffffffffffffffff80821115612f1457600080fd5b9083019060408286031215612f2857600080fd5b612f30611fc4565b825182811115612f3f57600080fd5b612f4b87828601612911565b825250602083015182811115612f6057600080fd5b612f6c87828601612911565b60208301525095945050505050565b600073ffffffffffffffffffffffffffffffffffffffff808916835260c06020840152612fab60c08401896121d6565b67ffffffffffffffff97881660408501529590961660608301525091909316608082015260a0019190915292915050565b6020815260006106106020830184612ad0565b600082516130018184602087016121b2565b919091019291505056fea164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CannotSendZeroTokens\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GetSupportedTokensFunctionalityRemovedCheckAdminRegistry\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidAllowListRequest\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidDestChainConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeCalledByRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrAllowlistAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RouterMustSetOriginalSender\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"UnsupportedToken\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"name\":\"AllowListAdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"senders\",\"type\":\"address[]\"}],\"name\":\"AllowListSendersAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"senders\",\"type\":\"address[]\"}],\"name\":\"AllowListSendersRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"CCIPSendRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOnRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"allowListEnabled\",\"type\":\"bool\"}],\"name\":\"DestChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"feeValueJuels\",\"type\":\"uint256\"}],\"name\":\"FeePaid\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeeTokenWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"allowListEnabled\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"addedAllowlistedSenders\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"removedAllowlistedSenders\",\"type\":\"address[]\"}],\"internalType\":\"structOnRamp.AllowListConfigArgs[]\",\"name\":\"allowListConfigArgsItems\",\"type\":\"tuple[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyDestChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"}],\"name\":\"forwardFromRouter\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getAllowedSendersList\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getDestChainConfig\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"allowListEnabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getExpectedNextSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"getFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"},{\"internalType\":\"contractIERC20\",\"name\":\"sourceToken\",\"type\":\"address\"}],\"name\":\"getPoolBySourceToken\",\"outputs\":[{\"internalType\":\"contractIPoolV1\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"contractIRouter\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"name\":\"getSupportedTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"setDynamicConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"withdrawFeeTokens\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x6101006040523480156200001257600080fd5b506040516200407338038062004073833981016040819052620000359162000665565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf8162000186565b505083516001600160401b031615905080620000e6575060208301516001600160a01b0316155b80620000fd575060408301516001600160a01b0316155b8062000114575060608301516001600160a01b0316155b1562000133576040516306b7c75960e31b815260040160405180910390fd5b82516001600160401b031660805260208301516001600160a01b0390811660a0526040840151811660c05260608401511660e052620001728262000231565b6200017d8162000390565b5050506200079f565b336001600160a01b03821603620001e05760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b0316158062000254575060408101516001600160a01b0316155b1562000273576040516306b7c75960e31b815260040160405180910390fd5b8051600280546001600160a01b03199081166001600160a01b0393841617909155602080840180516003805485169186169190911790556040808601805160048054871691881691909117905560608088018051600580549098169089161790965582516080808201855280516001600160401b031680835260a080518b16848a0190815260c080518d16868a0190815260e080518f169789019788528a5195865292518e169b85019b909b5299518c169783019790975292518a169381019390935289518916908301529351871693810193909352518516928201929092529151909216918101919091527f23a1adf8ad7fad6091a4803227af2cee848c01a7c812404cade7c25636925e32906101000160405180910390a150565b60005b8151811015620004cf576000828281518110620003b457620003b462000789565b602002602001015190506000838381518110620003d557620003d562000789565b6020026020010151600001519050806001600160401b03166000036200041a5760405163c35aa79d60e01b81526001600160401b038216600482015260240162000083565b6001600160401b03818116600081815260066020908152604091829020868201518154600160481b600160e81b0319811669010000000000000000006001600160a01b03909316928302908117808555865192891691909816178152928301526801000000000000000090940460ff161515918101919091527fd5ad72bc37dc7a80a8b9b9df20500046fd7341adb1be2258a540466fdd7dcef59060600160405180910390a250505080600101905062000393565b5050565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b03811182821017156200050e576200050e620004d3565b60405290565b604080519081016001600160401b03811182821017156200050e576200050e620004d3565b604051601f8201601f191681016001600160401b0381118282101715620005645762000564620004d3565b604052919050565b80516001600160401b03811681146200058457600080fd5b919050565b6001600160a01b03811681146200059f57600080fd5b50565b600082601f830112620005b457600080fd5b815160206001600160401b03821115620005d257620005d2620004d3565b620005e2818360051b0162000539565b82815260069290921b840181019181810190868411156200060257600080fd5b8286015b848110156200065a5760408189031215620006215760008081fd5b6200062b62000514565b62000636826200056c565b815284820151620006478162000589565b8186015283529183019160400162000606565b509695505050505050565b60008060008385036101208112156200067d57600080fd5b60808112156200068c57600080fd5b62000696620004e9565b620006a1866200056c565b81526020860151620006b38162000589565b60208201526040860151620006c88162000589565b60408201526060860151620006dd8162000589565b606082015293506080607f1982011215620006f757600080fd5b5062000702620004e9565b6080850151620007128162000589565b815260a0850151620007248162000589565b602082015260c0850151620007398162000589565b604082015260e08501516200074e8162000589565b60608201526101008501519092506001600160401b038111156200077157600080fd5b6200077f86828701620005a2565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b60805160a05160c05160e05161385b620008186000396000818161022c01528181610c790152611beb0152600081816101f0015281816112480152611bc40152600081816101b4015281816105de0152611b9a0152600081816101840152818161116e015281816116930152611b6d015261385b6000f3fe608060405234801561001057600080fd5b50600436106101365760003560e01c806379ba5097116100b2578063a6f3ab6c11610081578063df0aa9e911610066578063df0aa9e91461052d578063f2fde38b14610540578063fbca3b741461055357600080fd5b8063a6f3ab6c146104cd578063d77d5ed0146104e057600080fd5b806379ba50971461045b5780638da5cb5b146104635780639041be3d14610481578063972b4612146104ad57600080fd5b806334adf4941161010957806348a98aa4116100ee57806348a98aa4146103045780636def4ce71461033c5780637437ff9f146103db57600080fd5b806334adf494146102e95780633a019940146102fc57600080fd5b80630242cf601461013b57806306285c6914610150578063181f5a771461027f57806320487ded146102c8575b600080fd5b61014e6101493660046126e0565b610566565b005b61026960408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16815250905090565b60405161027691906127a3565b60405180910390f35b6102bb6040518060400160405280601081526020017f4f6e52616d7020312e362e302d6465760000000000000000000000000000000081525081565b6040516102769190612868565b6102db6102d6366004612893565b61057a565b604051908152602001610276565b61014e6102f73660046128e3565b610733565b61014e610a06565b610317610312366004612958565b610c31565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610276565b61039f61034a366004612991565b67ffffffffffffffff9081166000908152600660205260409020549081169168010000000000000000820460ff16916901000000000000000000900473ffffffffffffffffffffffffffffffffffffffff1690565b6040805167ffffffffffffffff9094168452911515602084015273ffffffffffffffffffffffffffffffffffffffff1690820152606001610276565b61044e604080516080810182526000808252602082018190529181018290526060810191909152506040805160808101825260025473ffffffffffffffffffffffffffffffffffffffff908116825260035481166020830152600454811692820192909252600554909116606082015290565b60405161027691906129ae565b61014e610ce6565b60005473ffffffffffffffffffffffffffffffffffffffff16610317565b61049461048f366004612991565b610de3565b60405167ffffffffffffffff9091168152602001610276565b6104c06104bb366004612991565b610e0c565b60405161027691906129f7565b61014e6104db366004612a61565b610e34565b6103176104ee366004612991565b67ffffffffffffffff166000908152600660205260409020546901000000000000000000900473ffffffffffffffffffffffffffffffffffffffff1690565b6102db61053b366004612ac8565b610e45565b61014e61054e366004612b34565b611748565b6104c0610561366004612991565b611759565b61056e61178d565b61057781611810565b50565b6040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815277ffffffffffffffff00000000000000000000000000000000608084901b16600482015260009073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690632cbc26bb90602401602060405180830381865afa158015610625573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106499190612b5f565b15610691576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024015b60405180910390fd5b6002546040517fd8694ccd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063d8694ccd906106e99086908690600401612c90565b602060405180830381865afa158015610706573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061072a9190612dd9565b90505b92915050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146107a35760055473ffffffffffffffffffffffffffffffffffffffff1633146107a3576040517f905d7d9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015610a015760008383838181106107c2576107c2612df2565b90506020028101906107d49190612e21565b6107dd90612ed2565b805167ffffffffffffffff1660009081526006602090815260409091209082015181547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff16680100000000000000009115801592909202178255919250906109545760005b8260400151518110156108fd5760008360400151828151811061086757610867612df2565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036108e65783516040517f463258ff00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610688565b6108f36001840182611987565b5050600101610842565b506040820151511561095457816000015167ffffffffffffffff167f330939f6eafe8bb516716892fe962ff19770570838686e6579dbc1cc51fc3281836040015160405161094b91906129f7565b60405180910390a25b60005b8260600151518110156109a0576109978360600151828151811061097d5761097d612df2565b6020026020010151836001016119a990919063ffffffff16565b50600101610957565b50606082015151156109f757816000015167ffffffffffffffff167fc237ec1921f855ccd5e9a5af9733f2d58943a5a8501ec5988e305d7a4d42158683606001516040516109ee91906129f7565b60405180910390a25b50506001016107a6565b505050565b600254604080517fcdc73d51000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163cdc73d5191600480830192869291908290030181865afa158015610a75573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610abb9190810190612f65565b60045490915073ffffffffffffffffffffffffffffffffffffffff1660005b8251811015610a01576000838281518110610af757610af7612df2565b60209081029190910101516040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915060009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa158015610b72573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b969190612dd9565b90508015610c2757610bbf73ffffffffffffffffffffffffffffffffffffffff831685836119cb565b8173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f508d7d183612c18fc339b42618912b9fa3239f631dd7ec0671f950200a0fa66e83604051610c1e91815260200190565b60405180910390a35b5050600101610ada565b6040517fbbe4f6db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063bbe4f6db90602401602060405180830381865afa158015610cc2573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061072a9190612ff4565b60015473ffffffffffffffffffffffffffffffffffffffff163314610d67576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610688565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b67ffffffffffffffff808216600090815260066020526040812054909161072d91166001613040565b67ffffffffffffffff8116600090815260066020526040902060609061072d90600101611a58565b610e3c61178d565b61057781611a6c565b67ffffffffffffffff8416600090815260066020526040812073ffffffffffffffffffffffffffffffffffffffff8316610eab576040517fa4ec747900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805468010000000000000000900460ff1615610f1c57610ece6001820184611c4e565b610f1c576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152602401610688565b80546901000000000000000000900473ffffffffffffffffffffffffffffffffffffffff163314610f79576040517f1c0a352900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60035473ffffffffffffffffffffffffffffffffffffffff16801561101f576040517fe0a0e50600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82169063e0a0e50690610fec908a908a90600401612c90565b600060405180830381600087803b15801561100657600080fd5b505af115801561101a573d6000803e3d6000fd5b505050505b506002546000908190819073ffffffffffffffffffffffffffffffffffffffff1663c4276bfc8a61105660808c0160608d01612b34565b8a61106460808e018e613061565b6040518663ffffffff1660e01b81526004016110849594939291906130c6565b600060405180830381865afa1580156110a1573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526110e7919081019061318e565b919450925090506110fe6080890160608a01612b34565b73ffffffffffffffffffffffffffffffffffffffff167f075a2720282fdf622141dae0b048ef90a21a7e57c134c76912d19d006b3b3f6f8460405161114591815260200190565b60405180910390a2604080516101a081019091526000610100820181815267ffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000081166101208501528c811661014085015287549293928392916101608401918a9187916111ba91166131e8565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905567ffffffffffffffff168152602001866112ba576040517fea458c0c00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8f16600482015273ffffffffffffffffffffffffffffffffffffffff8c811660248301527f0000000000000000000000000000000000000000000000000000000000000000169063ea458c0c906044016020604051808303816000875af1158015611291573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112b5919061320f565b6112bd565b60005b67ffffffffffffffff1681525081526020018873ffffffffffffffffffffffffffffffffffffffff1681526020018a80602001906112fb9190613061565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050509082525060200161133f8b80613061565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050509082525060200161138660808c018c613061565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050908252506020016113d060808c0160608d01612b34565b73ffffffffffffffffffffffffffffffffffffffff1681526020018981526020018a8060400190611401919061322c565b905067ffffffffffffffff81111561141b5761141b6125ba565b60405190808252806020026020018201604052801561147e57816020015b61146b6040518060a0016040528060608152602001606081526020016060815260200160008152602001606081525090565b8152602001906001900390816114395790505b509052905060005b61149360408b018b61322c565b9050811015611542576115196114ac60408c018c61322c565b838181106114bc576114bc612df2565b9050604002018036038101906114d29190613294565b8c6114dd8d80613061565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508e9250611c7d915050565b8260e00151828151811061152f5761152f612df2565b6020908102919091010152600101611486565b5060025460e082015160009173ffffffffffffffffffffffffffffffffffffffff169063085318f8908d9061157a60408f018f61322c565b6040518563ffffffff1660e01b815260040161159994939291906133ab565b600060405180830381865afa1580156115b6573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526115fc91908101906133e1565b905060005b8260e00151518110156116555781818151811061162057611620612df2565b60200260200101518360e00151828151811061163e5761163e612df2565b602090810291909101015160800152600101611601565b506080808301849052604080517f130ac867e79e2789f923760a88743d292acdf7002139a588206e2260f73f7321602082015267ffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811692820192909252908d16606082015230918101919091526116ef90839060a00160405160208183030381529060405280519060200120611fa3565b82515260405167ffffffffffffffff8c16907fcae3d9f68a9ed33d0a770e9bcc6fc25d4041dd6391e6cd8015546547a3c931409061172e908590613492565b60405180910390a25051519450505050505b949350505050565b61175061178d565b610577816120a3565b60606040517f9e7177c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005473ffffffffffffffffffffffffffffffffffffffff16331461180e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610688565b565b60005b815181101561198357600082828151811061183057611830612df2565b60200260200101519050600083838151811061184e5761184e612df2565b60200260200101516000015190508067ffffffffffffffff166000036118ac576040517fc35aa79d00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610688565b67ffffffffffffffff8181166000818152600660209081526040918290208682015181547fffffff0000000000000000000000000000000000000000ffffffffffffffffff8116690100000000000000000073ffffffffffffffffffffffffffffffffffffffff909316928302908117808555865192891691909816178152928301526801000000000000000090940460ff161515918101919091527fd5ad72bc37dc7a80a8b9b9df20500046fd7341adb1be2258a540466fdd7dcef59060600160405180910390a2505050806001019050611813565b5050565b600061072a8373ffffffffffffffffffffffffffffffffffffffff8416612198565b600061072a8373ffffffffffffffffffffffffffffffffffffffff84166121e7565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052610a019084906122e1565b60606000611a65836123ed565b9392505050565b805173ffffffffffffffffffffffffffffffffffffffff161580611aa85750604081015173ffffffffffffffffffffffffffffffffffffffff16155b15611adf576040517f35be3ac800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051600280547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff93841617909155602080840151600380548416918516919091179055604080850151600480548516918616919091179055606080860151600580549095169086161790935580516080810182527f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681527f00000000000000000000000000000000000000000000000000000000000000008516928101929092527f00000000000000000000000000000000000000000000000000000000000000008416828201527f00000000000000000000000000000000000000000000000000000000000000009093169181019190915290517f23a1adf8ad7fad6091a4803227af2cee848c01a7c812404cade7c25636925e3291611c439184906135e0565b60405180910390a150565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600183016020526040812054151561072a565b611caf6040518060a0016040528060608152602001606081526020016060815260200160008152602001606081525090565b8460200151600003611ced576040517f5cf0444900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611cfd858760000151610c31565b905073ffffffffffffffffffffffffffffffffffffffff81161580611dcd57506040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527faff2afbf00000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff8216906301ffc9a790602401602060405180830381865afa158015611da7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dcb9190612b5f565b155b15611e1f5785516040517fbf16aab600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610688565b60008173ffffffffffffffffffffffffffffffffffffffff16639a4575b96040518060a001604052808881526020018967ffffffffffffffff1681526020018773ffffffffffffffffffffffffffffffffffffffff1681526020018a6020015181526020018a6000015173ffffffffffffffffffffffffffffffffffffffff168152506040518263ffffffff1660e01b8152600401611ebe919061367f565b6000604051808303816000875af1158015611edd573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611f2391908101906136f5565b6040805160a0810190915273ffffffffffffffffffffffffffffffffffffffff841660c08201529091508060e0810160405160208183030381529060405281526020018260000151815260200182602001518152602001886020015181526020016040518060200160405280600081525081525092505050949350505050565b60008060001b82846020015185606001518660000151606001518760000151608001518860a001518960c00151604051602001611fe596959493929190613786565b604051602081830303815290604052805190602001208560400151805190602001208660e0015160405160200161201c91906137e7565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201206080808c0151805190840120928501989098529183019590955260608201939093529384015260a083015260c082015260e00160405160208183030381529060405280519060200120905092915050565b3373ffffffffffffffffffffffffffffffffffffffff821603612122576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610688565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60008181526001830160205260408120546121df5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561072d565b50600061072d565b600081815260018301602052604081205480156122d057600061220b6001836137fa565b855490915060009061221f906001906137fa565b905080821461228457600086600001828154811061223f5761223f612df2565b906000526020600020015490508087600001848154811061226257612262612df2565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806122955761229561380d565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061072d565b600091505061072d565b5092915050565b6000612343826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166124499092919063ffffffff16565b805190915015610a0157808060200190518101906123619190612b5f565b610a01576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610688565b60608160000180548060200260200160405190810160405280929190818152602001828054801561243d57602002820191906000526020600020905b815481526020019060010190808311612429575b50505050509050919050565b60606117408484600085856000808673ffffffffffffffffffffffffffffffffffffffff16858760405161247d919061383c565b60006040518083038185875af1925050503d80600081146124ba576040519150601f19603f3d011682016040523d82523d6000602084013e6124bf565b606091505b50915091506124d0878383876124db565b979650505050505050565b6060831561257157825160000361256a5773ffffffffffffffffffffffffffffffffffffffff85163b61256a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610688565b5081611740565b61174083838151156125865781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106889190612868565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561260c5761260c6125ba565b60405290565b6040516080810167ffffffffffffffff8111828210171561260c5761260c6125ba565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561267c5761267c6125ba565b604052919050565b600067ffffffffffffffff82111561269e5761269e6125ba565b5060051b60200190565b67ffffffffffffffff8116811461057757600080fd5b73ffffffffffffffffffffffffffffffffffffffff8116811461057757600080fd5b600060208083850312156126f357600080fd5b823567ffffffffffffffff81111561270a57600080fd5b8301601f8101851361271b57600080fd5b803561272e61272982612684565b612635565b81815260069190911b8201830190838101908783111561274d57600080fd5b928401925b828410156124d0576040848903121561276b5760008081fd5b6127736125e9565b843561277e816126a8565b81528486013561278d816126be565b8187015282526040939093019290840190612752565b6080810161072d828467ffffffffffffffff8151168252602081015173ffffffffffffffffffffffffffffffffffffffff808216602085015280604084015116604085015280606084015116606085015250505050565b60005b838110156128155781810151838201526020016127fd565b50506000910152565b600081518084526128368160208601602086016127fa565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061072a602083018461281e565b600060a0828403121561288d57600080fd5b50919050565b600080604083850312156128a657600080fd5b82356128b1816126a8565b9150602083013567ffffffffffffffff8111156128cd57600080fd5b6128d98582860161287b565b9150509250929050565b600080602083850312156128f657600080fd5b823567ffffffffffffffff8082111561290e57600080fd5b818501915085601f83011261292257600080fd5b81358181111561293157600080fd5b8660208260051b850101111561294657600080fd5b60209290920196919550909350505050565b6000806040838503121561296b57600080fd5b8235612976816126a8565b91506020830135612986816126be565b809150509250929050565b6000602082840312156129a357600080fd5b8135611a65816126a8565b6080810161072d8284805173ffffffffffffffffffffffffffffffffffffffff908116835260208083015182169084015260408083015182169084015260609182015116910152565b6020808252825182820181905260009190848201906040850190845b81811015612a4557835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101612a13565b50909695505050505050565b8035612a5c816126be565b919050565b600060808284031215612a7357600080fd5b612a7b612612565b8235612a86816126be565b81526020830135612a96816126be565b60208201526040830135612aa9816126be565b60408201526060830135612abc816126be565b60608201529392505050565b60008060008060808587031215612ade57600080fd5b8435612ae9816126a8565b9350602085013567ffffffffffffffff811115612b0557600080fd5b612b118782880161287b565b935050604085013591506060850135612b29816126be565b939692955090935050565b600060208284031215612b4657600080fd5b8135611a65816126be565b801515811461057757600080fd5b600060208284031215612b7157600080fd5b8151611a6581612b51565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112612bb157600080fd5b830160208101925035905067ffffffffffffffff811115612bd157600080fd5b803603821315612be057600080fd5b9250929050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b8183526000602080850194508260005b85811015612c85578135612c53816126be565b73ffffffffffffffffffffffffffffffffffffffff168752818301358388015260409687019690910190600101612c40565b509495945050505050565b600067ffffffffffffffff808516835260406020840152612cb18485612b7c565b60a06040860152612cc660e086018284612be7565b915050612cd66020860186612b7c565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc080878503016060880152612d0c848385612be7565b9350604088013592507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1883603018312612d4557600080fd5b60209288019283019235915084821115612d5e57600080fd5b8160061b3603831315612d7057600080fd5b80878503016080880152612d85848385612c30565b9450612d9360608901612a51565b73ffffffffffffffffffffffffffffffffffffffff811660a08901529350612dbe6080890189612b7c565b94509250808786030160c088015250506124d0838383612be7565b600060208284031215612deb57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81833603018112612e5557600080fd5b9190910192915050565b600082601f830112612e7057600080fd5b81356020612e8061272983612684565b8083825260208201915060208460051b870101935086841115612ea257600080fd5b602086015b84811015612ec7578035612eba816126be565b8352918301918301612ea7565b509695505050505050565b600060808236031215612ee457600080fd5b612eec612612565b8235612ef7816126a8565b81526020830135612f0781612b51565b6020820152604083013567ffffffffffffffff80821115612f2757600080fd5b612f3336838701612e5f565b60408401526060850135915080821115612f4c57600080fd5b50612f5936828601612e5f565b60608301525092915050565b60006020808385031215612f7857600080fd5b825167ffffffffffffffff811115612f8f57600080fd5b8301601f81018513612fa057600080fd5b8051612fae61272982612684565b81815260059190911b82018301908381019087831115612fcd57600080fd5b928401925b828410156124d0578351612fe5816126be565b82529284019290840190612fd2565b60006020828403121561300657600080fd5b8151611a65816126be565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b67ffffffffffffffff8181168382160190808211156122da576122da613011565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261309657600080fd5b83018035915067ffffffffffffffff8211156130b157600080fd5b602001915036819003821315612be057600080fd5b67ffffffffffffffff8616815273ffffffffffffffffffffffffffffffffffffffff851660208201528360408201526080606082015260006124d0608083018486612be7565b600082601f83011261311d57600080fd5b815167ffffffffffffffff811115613137576131376125ba565b61316860207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601612635565b81815284602083860101111561317d57600080fd5b6117408260208301602087016127fa565b6000806000606084860312156131a357600080fd5b8351925060208401516131b581612b51565b604085015190925067ffffffffffffffff8111156131d257600080fd5b6131de8682870161310c565b9150509250925092565b600067ffffffffffffffff80831681810361320557613205613011565b6001019392505050565b60006020828403121561322157600080fd5b8151611a65816126a8565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261326157600080fd5b83018035915067ffffffffffffffff82111561327c57600080fd5b6020019150600681901b3603821315612be057600080fd5b6000604082840312156132a657600080fd5b6132ae6125e9565b82356132b9816126be565b81526020928301359281019290925250919050565b600082825180855260208086019550808260051b84010181860160005b8481101561339e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018952815160a0815181865261332f8287018261281e565b9150508582015185820387870152613347828261281e565b91505060408083015186830382880152613361838261281e565b9250505060608083015181870152506080808301519250858203818701525061338a818361281e565b9a86019a94505050908301906001016132eb565b5090979650505050505050565b67ffffffffffffffff851681526060602082015260006133ce60608301866132ce565b82810360408401526124d0818587612c30565b600060208083850312156133f457600080fd5b825167ffffffffffffffff8082111561340c57600080fd5b818501915085601f83011261342057600080fd5b815161342e61272982612684565b81815260059190911b8301840190848101908883111561344d57600080fd5b8585015b83811015613485578051858111156134695760008081fd5b6134778b89838a010161310c565b845250918601918601613451565b5098975050505050505050565b602081526134e360208201835180518252602081015167ffffffffffffffff808216602085015280604084015116604085015280606084015116606085015280608084015116608085015250505050565b6000602083015161350c60c084018273ffffffffffffffffffffffffffffffffffffffff169052565b5060408301516101808060e08501526135296101a085018361281e565b915060608501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08086850301610100870152613566848361281e565b9350608087015191508086850301610120870152613584848361281e565b935060a087015191506135b061014087018373ffffffffffffffffffffffffffffffffffffffff169052565b60c087015161016087015260e08701519150808685030183870152506135d683826132ce565b9695505050505050565b6101008101613638828567ffffffffffffffff8151168252602081015173ffffffffffffffffffffffffffffffffffffffff808216602085015280604084015116604085015280606084015116606085015250505050565b825173ffffffffffffffffffffffffffffffffffffffff90811660808401526020840151811660a08401526040840151811660c084015260608401511660e0830152611a65565b602081526000825160a0602084015261369b60c084018261281e565b905067ffffffffffffffff6020850151166040840152604084015173ffffffffffffffffffffffffffffffffffffffff8082166060860152606086015160808601528060808701511660a086015250508091505092915050565b60006020828403121561370757600080fd5b815167ffffffffffffffff8082111561371f57600080fd5b908301906040828603121561373357600080fd5b61373b6125e9565b82518281111561374a57600080fd5b6137568782860161310c565b82525060208301518281111561376b57600080fd5b6137778782860161310c565b60208301525095945050505050565b600073ffffffffffffffffffffffffffffffffffffffff808916835260c060208401526137b660c084018961281e565b67ffffffffffffffff97881660408501529590961660608301525091909316608082015260a0019190915292915050565b60208152600061072a60208301846132ce565b8181038181111561072d5761072d613011565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b60008251612e558184602087016127fa56fea164736f6c6343000818000a", } var OnRampABI = OnRampMetaData.ABI @@ -234,6 +237,59 @@ func (_OnRamp *OnRampTransactorRaw) Transact(opts *bind.TransactOpts, method str return _OnRamp.Contract.contract.Transact(opts, method, params...) } +func (_OnRamp *OnRampCaller) GetAllowedSendersList(opts *bind.CallOpts, destChainSelector uint64) ([]common.Address, error) { + var out []interface{} + err := _OnRamp.contract.Call(opts, &out, "getAllowedSendersList", destChainSelector) + + if err != nil { + return *new([]common.Address), err + } + + out0 := *abi.ConvertType(out[0], new([]common.Address)).(*[]common.Address) + + return out0, err + +} + +func (_OnRamp *OnRampSession) GetAllowedSendersList(destChainSelector uint64) ([]common.Address, error) { + return _OnRamp.Contract.GetAllowedSendersList(&_OnRamp.CallOpts, destChainSelector) +} + +func (_OnRamp *OnRampCallerSession) GetAllowedSendersList(destChainSelector uint64) ([]common.Address, error) { + return _OnRamp.Contract.GetAllowedSendersList(&_OnRamp.CallOpts, destChainSelector) +} + +func (_OnRamp *OnRampCaller) GetDestChainConfig(opts *bind.CallOpts, destChainSelector uint64) (GetDestChainConfig, + + error) { + var out []interface{} + err := _OnRamp.contract.Call(opts, &out, "getDestChainConfig", destChainSelector) + + outstruct := new(GetDestChainConfig) + if err != nil { + return *outstruct, err + } + + outstruct.SequenceNumber = *abi.ConvertType(out[0], new(uint64)).(*uint64) + outstruct.AllowListEnabled = *abi.ConvertType(out[1], new(bool)).(*bool) + outstruct.Router = *abi.ConvertType(out[2], new(common.Address)).(*common.Address) + + return *outstruct, err + +} + +func (_OnRamp *OnRampSession) GetDestChainConfig(destChainSelector uint64) (GetDestChainConfig, + + error) { + return _OnRamp.Contract.GetDestChainConfig(&_OnRamp.CallOpts, destChainSelector) +} + +func (_OnRamp *OnRampCallerSession) GetDestChainConfig(destChainSelector uint64) (GetDestChainConfig, + + error) { + return _OnRamp.Contract.GetDestChainConfig(&_OnRamp.CallOpts, destChainSelector) +} + func (_OnRamp *OnRampCaller) GetDynamicConfig(opts *bind.CallOpts) (OnRampDynamicConfig, error) { var out []interface{} err := _OnRamp.contract.Call(opts, &out, "getDynamicConfig") @@ -444,6 +500,18 @@ func (_OnRamp *OnRampTransactorSession) AcceptOwnership() (*types.Transaction, e return _OnRamp.Contract.AcceptOwnership(&_OnRamp.TransactOpts) } +func (_OnRamp *OnRampTransactor) ApplyAllowListUpdates(opts *bind.TransactOpts, allowListConfigArgsItems []OnRampAllowListConfigArgs) (*types.Transaction, error) { + return _OnRamp.contract.Transact(opts, "applyAllowListUpdates", allowListConfigArgsItems) +} + +func (_OnRamp *OnRampSession) ApplyAllowListUpdates(allowListConfigArgsItems []OnRampAllowListConfigArgs) (*types.Transaction, error) { + return _OnRamp.Contract.ApplyAllowListUpdates(&_OnRamp.TransactOpts, allowListConfigArgsItems) +} + +func (_OnRamp *OnRampTransactorSession) ApplyAllowListUpdates(allowListConfigArgsItems []OnRampAllowListConfigArgs) (*types.Transaction, error) { + return _OnRamp.Contract.ApplyAllowListUpdates(&_OnRamp.TransactOpts, allowListConfigArgsItems) +} + func (_OnRamp *OnRampTransactor) ApplyDestChainConfigUpdates(opts *bind.TransactOpts, destChainConfigArgs []OnRampDestChainConfigArgs) (*types.Transaction, error) { return _OnRamp.contract.Transact(opts, "applyDestChainConfigUpdates", destChainConfigArgs) } @@ -504,6 +572,389 @@ func (_OnRamp *OnRampTransactorSession) WithdrawFeeTokens() (*types.Transaction, return _OnRamp.Contract.WithdrawFeeTokens(&_OnRamp.TransactOpts) } +type OnRampAllowListAdminSetIterator struct { + Event *OnRampAllowListAdminSet + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *OnRampAllowListAdminSetIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(OnRampAllowListAdminSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(OnRampAllowListAdminSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *OnRampAllowListAdminSetIterator) Error() error { + return it.fail +} + +func (it *OnRampAllowListAdminSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type OnRampAllowListAdminSet struct { + AllowListAdmin common.Address + Raw types.Log +} + +func (_OnRamp *OnRampFilterer) FilterAllowListAdminSet(opts *bind.FilterOpts, allowListAdmin []common.Address) (*OnRampAllowListAdminSetIterator, error) { + + var allowListAdminRule []interface{} + for _, allowListAdminItem := range allowListAdmin { + allowListAdminRule = append(allowListAdminRule, allowListAdminItem) + } + + logs, sub, err := _OnRamp.contract.FilterLogs(opts, "AllowListAdminSet", allowListAdminRule) + if err != nil { + return nil, err + } + return &OnRampAllowListAdminSetIterator{contract: _OnRamp.contract, event: "AllowListAdminSet", logs: logs, sub: sub}, nil +} + +func (_OnRamp *OnRampFilterer) WatchAllowListAdminSet(opts *bind.WatchOpts, sink chan<- *OnRampAllowListAdminSet, allowListAdmin []common.Address) (event.Subscription, error) { + + var allowListAdminRule []interface{} + for _, allowListAdminItem := range allowListAdmin { + allowListAdminRule = append(allowListAdminRule, allowListAdminItem) + } + + logs, sub, err := _OnRamp.contract.WatchLogs(opts, "AllowListAdminSet", allowListAdminRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(OnRampAllowListAdminSet) + if err := _OnRamp.contract.UnpackLog(event, "AllowListAdminSet", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_OnRamp *OnRampFilterer) ParseAllowListAdminSet(log types.Log) (*OnRampAllowListAdminSet, error) { + event := new(OnRampAllowListAdminSet) + if err := _OnRamp.contract.UnpackLog(event, "AllowListAdminSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type OnRampAllowListSendersAddedIterator struct { + Event *OnRampAllowListSendersAdded + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *OnRampAllowListSendersAddedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(OnRampAllowListSendersAdded) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(OnRampAllowListSendersAdded) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *OnRampAllowListSendersAddedIterator) Error() error { + return it.fail +} + +func (it *OnRampAllowListSendersAddedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type OnRampAllowListSendersAdded struct { + DestChainSelector uint64 + Senders []common.Address + Raw types.Log +} + +func (_OnRamp *OnRampFilterer) FilterAllowListSendersAdded(opts *bind.FilterOpts, destChainSelector []uint64) (*OnRampAllowListSendersAddedIterator, error) { + + var destChainSelectorRule []interface{} + for _, destChainSelectorItem := range destChainSelector { + destChainSelectorRule = append(destChainSelectorRule, destChainSelectorItem) + } + + logs, sub, err := _OnRamp.contract.FilterLogs(opts, "AllowListSendersAdded", destChainSelectorRule) + if err != nil { + return nil, err + } + return &OnRampAllowListSendersAddedIterator{contract: _OnRamp.contract, event: "AllowListSendersAdded", logs: logs, sub: sub}, nil +} + +func (_OnRamp *OnRampFilterer) WatchAllowListSendersAdded(opts *bind.WatchOpts, sink chan<- *OnRampAllowListSendersAdded, destChainSelector []uint64) (event.Subscription, error) { + + var destChainSelectorRule []interface{} + for _, destChainSelectorItem := range destChainSelector { + destChainSelectorRule = append(destChainSelectorRule, destChainSelectorItem) + } + + logs, sub, err := _OnRamp.contract.WatchLogs(opts, "AllowListSendersAdded", destChainSelectorRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(OnRampAllowListSendersAdded) + if err := _OnRamp.contract.UnpackLog(event, "AllowListSendersAdded", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_OnRamp *OnRampFilterer) ParseAllowListSendersAdded(log types.Log) (*OnRampAllowListSendersAdded, error) { + event := new(OnRampAllowListSendersAdded) + if err := _OnRamp.contract.UnpackLog(event, "AllowListSendersAdded", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type OnRampAllowListSendersRemovedIterator struct { + Event *OnRampAllowListSendersRemoved + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *OnRampAllowListSendersRemovedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(OnRampAllowListSendersRemoved) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(OnRampAllowListSendersRemoved) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *OnRampAllowListSendersRemovedIterator) Error() error { + return it.fail +} + +func (it *OnRampAllowListSendersRemovedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type OnRampAllowListSendersRemoved struct { + DestChainSelector uint64 + Senders []common.Address + Raw types.Log +} + +func (_OnRamp *OnRampFilterer) FilterAllowListSendersRemoved(opts *bind.FilterOpts, destChainSelector []uint64) (*OnRampAllowListSendersRemovedIterator, error) { + + var destChainSelectorRule []interface{} + for _, destChainSelectorItem := range destChainSelector { + destChainSelectorRule = append(destChainSelectorRule, destChainSelectorItem) + } + + logs, sub, err := _OnRamp.contract.FilterLogs(opts, "AllowListSendersRemoved", destChainSelectorRule) + if err != nil { + return nil, err + } + return &OnRampAllowListSendersRemovedIterator{contract: _OnRamp.contract, event: "AllowListSendersRemoved", logs: logs, sub: sub}, nil +} + +func (_OnRamp *OnRampFilterer) WatchAllowListSendersRemoved(opts *bind.WatchOpts, sink chan<- *OnRampAllowListSendersRemoved, destChainSelector []uint64) (event.Subscription, error) { + + var destChainSelectorRule []interface{} + for _, destChainSelectorItem := range destChainSelector { + destChainSelectorRule = append(destChainSelectorRule, destChainSelectorItem) + } + + logs, sub, err := _OnRamp.contract.WatchLogs(opts, "AllowListSendersRemoved", destChainSelectorRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(OnRampAllowListSendersRemoved) + if err := _OnRamp.contract.UnpackLog(event, "AllowListSendersRemoved", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_OnRamp *OnRampFilterer) ParseAllowListSendersRemoved(log types.Log) (*OnRampAllowListSendersRemoved, error) { + event := new(OnRampAllowListSendersRemoved) + if err := _OnRamp.contract.UnpackLog(event, "AllowListSendersRemoved", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + type OnRampCCIPSendRequestedIterator struct { Event *OnRampCCIPSendRequested @@ -812,7 +1263,9 @@ func (it *OnRampDestChainConfigSetIterator) Close() error { type OnRampDestChainConfigSet struct { DestChainSelector uint64 - DestChainConfig OnRampDestChainConfig + SequenceNumber uint64 + Router common.Address + AllowListEnabled bool Raw types.Log } @@ -1415,8 +1868,20 @@ func (_OnRamp *OnRampFilterer) ParseOwnershipTransferred(log types.Log) (*OnRamp return event, nil } +type GetDestChainConfig struct { + SequenceNumber uint64 + AllowListEnabled bool + Router common.Address +} + func (_OnRamp *OnRamp) ParseLog(log types.Log) (generated.AbigenLog, error) { switch log.Topics[0] { + case _OnRamp.abi.Events["AllowListAdminSet"].ID: + return _OnRamp.ParseAllowListAdminSet(log) + case _OnRamp.abi.Events["AllowListSendersAdded"].ID: + return _OnRamp.ParseAllowListSendersAdded(log) + case _OnRamp.abi.Events["AllowListSendersRemoved"].ID: + return _OnRamp.ParseAllowListSendersRemoved(log) case _OnRamp.abi.Events["CCIPSendRequested"].ID: return _OnRamp.ParseCCIPSendRequested(log) case _OnRamp.abi.Events["ConfigSet"].ID: @@ -1437,16 +1902,28 @@ func (_OnRamp *OnRamp) ParseLog(log types.Log) (generated.AbigenLog, error) { } } +func (OnRampAllowListAdminSet) Topic() common.Hash { + return common.HexToHash("0xb8c9b44ae5b5e3afb195f67391d9ff50cb904f9c0fa5fd520e497a97c1aa5a1e") +} + +func (OnRampAllowListSendersAdded) Topic() common.Hash { + return common.HexToHash("0x330939f6eafe8bb516716892fe962ff19770570838686e6579dbc1cc51fc3281") +} + +func (OnRampAllowListSendersRemoved) Topic() common.Hash { + return common.HexToHash("0xc237ec1921f855ccd5e9a5af9733f2d58943a5a8501ec5988e305d7a4d421586") +} + func (OnRampCCIPSendRequested) Topic() common.Hash { return common.HexToHash("0xcae3d9f68a9ed33d0a770e9bcc6fc25d4041dd6391e6cd8015546547a3c93140") } func (OnRampConfigSet) Topic() common.Hash { - return common.HexToHash("0x2d8f19dc1cd01460c3367a09d2d424f2b1940ba7c886047edd078c7b77ea4558") + return common.HexToHash("0x23a1adf8ad7fad6091a4803227af2cee848c01a7c812404cade7c25636925e32") } func (OnRampDestChainConfigSet) Topic() common.Hash { - return common.HexToHash("0x324d4a7950b57da00ce533ad6697039be6281726a73da959d0ab3ff795181ec6") + return common.HexToHash("0xd5ad72bc37dc7a80a8b9b9df20500046fd7341adb1be2258a540466fdd7dcef5") } func (OnRampFeePaid) Topic() common.Hash { @@ -1470,6 +1947,12 @@ func (_OnRamp *OnRamp) Address() common.Address { } type OnRampInterface interface { + GetAllowedSendersList(opts *bind.CallOpts, destChainSelector uint64) ([]common.Address, error) + + GetDestChainConfig(opts *bind.CallOpts, destChainSelector uint64) (GetDestChainConfig, + + error) + GetDynamicConfig(opts *bind.CallOpts) (OnRampDynamicConfig, error) GetExpectedNextSequenceNumber(opts *bind.CallOpts, destChainSelector uint64) (uint64, error) @@ -1490,6 +1973,8 @@ type OnRampInterface interface { AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) + ApplyAllowListUpdates(opts *bind.TransactOpts, allowListConfigArgsItems []OnRampAllowListConfigArgs) (*types.Transaction, error) + ApplyDestChainConfigUpdates(opts *bind.TransactOpts, destChainConfigArgs []OnRampDestChainConfigArgs) (*types.Transaction, error) ForwardFromRouter(opts *bind.TransactOpts, destChainSelector uint64, message ClientEVM2AnyMessage, feeTokenAmount *big.Int, originalSender common.Address) (*types.Transaction, error) @@ -1500,6 +1985,24 @@ type OnRampInterface interface { WithdrawFeeTokens(opts *bind.TransactOpts) (*types.Transaction, error) + FilterAllowListAdminSet(opts *bind.FilterOpts, allowListAdmin []common.Address) (*OnRampAllowListAdminSetIterator, error) + + WatchAllowListAdminSet(opts *bind.WatchOpts, sink chan<- *OnRampAllowListAdminSet, allowListAdmin []common.Address) (event.Subscription, error) + + ParseAllowListAdminSet(log types.Log) (*OnRampAllowListAdminSet, error) + + FilterAllowListSendersAdded(opts *bind.FilterOpts, destChainSelector []uint64) (*OnRampAllowListSendersAddedIterator, error) + + WatchAllowListSendersAdded(opts *bind.WatchOpts, sink chan<- *OnRampAllowListSendersAdded, destChainSelector []uint64) (event.Subscription, error) + + ParseAllowListSendersAdded(log types.Log) (*OnRampAllowListSendersAdded, error) + + FilterAllowListSendersRemoved(opts *bind.FilterOpts, destChainSelector []uint64) (*OnRampAllowListSendersRemovedIterator, error) + + WatchAllowListSendersRemoved(opts *bind.WatchOpts, sink chan<- *OnRampAllowListSendersRemoved, destChainSelector []uint64) (event.Subscription, error) + + ParseAllowListSendersRemoved(log types.Log) (*OnRampAllowListSendersRemoved, error) + FilterCCIPSendRequested(opts *bind.FilterOpts, destChainSelector []uint64) (*OnRampCCIPSendRequestedIterator, error) WatchCCIPSendRequested(opts *bind.WatchOpts, sink chan<- *OnRampCCIPSendRequested, destChainSelector []uint64) (event.Subscription, error) diff --git a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt index 688818f694..f8a7a120af 100644 --- a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -24,7 +24,7 @@ multi_ocr3_helper: ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Help nonce_manager: ../../../contracts/solc/v0.8.24/NonceManager/NonceManager.abi ../../../contracts/solc/v0.8.24/NonceManager/NonceManager.bin 6f64e1083b356c06ee66b9138e398b9c97a4cd3e8c9ec38cf3010cebc79af536 ocr3_config_encoder: ../../../contracts/solc/v0.8.24/IOCR3ConfigEncoder/IOCR3ConfigEncoder.abi ../../../contracts/solc/v0.8.24/IOCR3ConfigEncoder/IOCR3ConfigEncoder.bin e21180898e1ad54a045ee20add85a2793c681425ea06f66d1a9e5cab128b6487 offramp: ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.abi ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.bin a3b8a9644f0d450dbf53d3371555dcc4084fb2eaf138a3797ef5cf73ed665bae -onramp: ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.abi ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.bin 13927b48bd09b9ab2c62143973c747f8c2e1ebc9f95f17a61ace67a68c71ec75 +onramp: ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.abi ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.bin 1ae9e3ebefc56d0382308c67c4ec066cdf3fa3eed2d31af8015d5d8db67f9c90 ping_pong_demo: ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.abi ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.bin c1c2f8a65c7ffd971899cae7fe62f2da57d09e936151e2b92163c4bebe699d6b price_registry: ../../../contracts/solc/v0.8.24/PriceRegistry/PriceRegistry.abi ../../../contracts/solc/v0.8.24/PriceRegistry/PriceRegistry.bin e7781d600c1bb7aa4620106af7f6e146a109b97f4cb6a7d06c9e15773340ecb2 registry_module_owner_custom: ../../../contracts/solc/v0.8.24/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.abi ../../../contracts/solc/v0.8.24/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.bin 75be86323c227917a9bbc3f799d7ed02f92db546653a36db30ed0ebe64461353 diff --git a/integration-tests/web/sdk/client/client.go b/integration-tests/web/sdk/client/client.go index bf0bf49f1b..e13a02aa5a 100644 --- a/integration-tests/web/sdk/client/client.go +++ b/integration-tests/web/sdk/client/client.go @@ -48,12 +48,12 @@ type Credentials struct { } func New(baseURI string, creds Credentials) (Client, error) { - e := endpoints{ + ep := endpoints{ Sessions: baseURI + "/sessions", Query: baseURI + "/query", } c := &client{ - endpoints: e, + endpoints: ep, credentials: creds, } From a3f61f7458e4499c2c62eb38581c60b4942b1160 Mon Sep 17 00:00:00 2001 From: dimitris Date: Wed, 28 Aug 2024 18:06:03 +0300 Subject: [PATCH 042/115] Use tests.WaitTimeout for CCIPReader e2e tests (#1382) We've noticed that this tests have failed a few times on the CI. I've run the tests with `go test ./... -count 100 -failfast` and it never failed locally. I assume it runs slow in CI that's why we have some failing cases, I am replacing `10s` with `tests.WaitTimeout(t)`. --- .../ccip_integration_tests/ccipreader/ccipreader_test.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/core/capabilities/ccip/ccip_integration_tests/ccipreader/ccipreader_test.go b/core/capabilities/ccip/ccip_integration_tests/ccipreader/ccipreader_test.go index ed5fe1aedb..05a91eb289 100644 --- a/core/capabilities/ccip/ccip_integration_tests/ccipreader/ccipreader_test.go +++ b/core/capabilities/ccip/ccip_integration_tests/ccipreader/ccipreader_test.go @@ -19,6 +19,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/types" cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker" @@ -115,7 +116,7 @@ func TestCCIPReader_CommitReportsGTETimestamp(t *testing.T) { ) require.NoError(t, err) return len(reports) == numReports-1 - }, 10*time.Second, 50*time.Millisecond) + }, tests.WaitTimeout(t), 50*time.Millisecond) assert.Len(t, reports[0].Report.MerkleRoots, 1) assert.Equal(t, chainS1, reports[0].Report.MerkleRoots[0].ChainSel) @@ -268,7 +269,7 @@ func TestCCIPReader_MsgsBetweenSeqNums(t *testing.T) { ) require.NoError(t, err) return len(msgs) == 2 - }, 10*time.Second, 100*time.Millisecond) + }, tests.WaitTimeout(t), 100*time.Millisecond) require.Len(t, msgs, 2) // sort to ensure ascending order of sequence numbers. From 6fe155bb49197603d54798150ad845a480279f99 Mon Sep 17 00:00:00 2001 From: Anirudh Warrier <12178754+anirudhwarrier@users.noreply.github.com> Date: Wed, 28 Aug 2024 20:53:18 +0400 Subject: [PATCH 043/115] replace contains with equals (#1385) ## Motivation When simulating slow load on testnet, the load gen was getting applied to multiple networks. ## Solution Replace contains check with EqualFold. Also add some logs to make it easier to understand. --- integration-tests/ccip-tests/load/helper.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/integration-tests/ccip-tests/load/helper.go b/integration-tests/ccip-tests/load/helper.go index 54d9fb2c11..dbb5ffc3e9 100644 --- a/integration-tests/ccip-tests/load/helper.go +++ b/integration-tests/ccip-tests/load/helper.go @@ -111,8 +111,15 @@ func (l *LoadArgs) scheduleForDest(destNetworkName string) []*wasp.Segment { // if found, use that frequency for the destination network // otherwise, use the default frequency if l.TestCfg.TestGroupInput.LoadProfile.FrequencyByDestination != nil { + l.lggr.Debug(). + Interface("FrequencyByDestination", l.TestCfg.TestGroupInput.LoadProfile.FrequencyByDestination). + Msg("LoadProfile provided") for networkName, freq := range l.TestCfg.TestGroupInput.LoadProfile.FrequencyByDestination { - if strings.Contains(destNetworkName, strings.ToLower(networkName)) { + l.lggr.Debug().Str("Destination", destNetworkName).Str("NetworkName", networkName).Msg("Checking frequency for destination") + if strings.EqualFold(destNetworkName, networkName) { + l.lggr.Info().Str("Destination", destNetworkName). + Ints64("RequestPerUnitTime", freq.RequestPerUnitTime). + Msg("Using frequency for destination") return WaspSchedule( freq.RequestPerUnitTime, l.TestCfg.TestGroupInput.LoadProfile.TestDuration, From 8572a7ad10dc024621d87d0b4555fa081c4d1da0 Mon Sep 17 00:00:00 2001 From: Anirudh Warrier <12178754+anirudhwarrier@users.noreply.github.com> Date: Wed, 28 Aug 2024 21:02:13 +0400 Subject: [PATCH 044/115] bump anvil version used in load tests (#1386) ## Motivation During load tests, when anvil node restarts, block history is lost. Identified this to be a bug in the pinned version of anvil. ## Solution Bump anvil version to latest nightly. --- integration-tests/ccip-tests/testsetups/test_env.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/integration-tests/ccip-tests/testsetups/test_env.go b/integration-tests/ccip-tests/testsetups/test_env.go index 85a5a10511..1eb7ebd452 100644 --- a/integration-tests/ccip-tests/testsetups/test_env.go +++ b/integration-tests/ccip-tests/testsetups/test_env.go @@ -490,8 +490,7 @@ func DeployEnvironments( "fullnameOverride": actions.NetworkName(network.Name), "image": map[string]interface{}{ "repository": "ghcr.io/foundry-rs/foundry", - "tag": "nightly-5ac78a9cd4b94dc53d1fe5e0f42372b28b5a7559", - // "tag": "nightly-ea2eff95b5c17edd3ffbdfc6daab5ce5cc80afc0", + "tag": "nightly-2442e7a5fc165d7d0b022aa8b9f09dcdf675157b", }, "anvil": map[string]interface{}{ "chainId": fmt.Sprintf("%d", network.ChainID), From caa03045318416c66ce6a9563f697d9da9f2c26c Mon Sep 17 00:00:00 2001 From: Lukasz <120112546+lukaszcl@users.noreply.github.com> Date: Wed, 28 Aug 2024 21:26:30 +0200 Subject: [PATCH 045/115] [TT-1396] [CCIP-2804] Migrate CCIP to test secrets (#1189) We're updating how we manage test secrets on GitHub CI to enhance security. Instead of passing secrets like the Chainlink image name or wallet key through secrets.toml, we will now load them from the `~/.testsecrets file in your home directory. This change helps us handle secrets more securely. To set test secrets, see instructions integration-tests/ccip-tests/testconfig/examples/.testsecrets.example --- TODO: - [x] @kalverra Run tests locally and see if all works fine - [ ] @kalverra Run all CI workflows and see if it all works fine - [x] @kalverra Update all documentation (docs in this repo are already updated by lukaszcl) - [x] @kalverra Notify CCIP developers that this change will be merged soon - [x] @lukaszcl Merge CTF PR which is a dependecy here https://github.com/smartcontractkit/chainlink-testing-framework/pull/1028/files - [x] @lukaszcl Update all CI workflows for CCIP - [x] @lukaszcl Update setup-create-base64-config-ccip in all workflows to correctly use output - [x] @lukaszcl Allow CI workflows to run with custom test secrets ([guide how to run it](https://github.com/smartcontractkit/chainlink-testing-framework/blob/main/config/README.md#run-github-workflow-with-your-test-secrets)) --------- Co-authored-by: Adam Hamrick --- .../action.yml | 70 ++---- .github/workflows/ccip-chaos-tests.yml | 39 +-- .../ccip-client-compatibility-tests.yml | 37 ++- .github/workflows/ccip-live-network-tests.yml | 66 ++--- .github/workflows/ccip-load-tests.yml | 38 +-- .../workflows/ccip-offchain-upgrade-tests.yml | 45 ++-- .github/workflows/integration-tests.yml | 14 +- integration-tests/ccip-tests/Makefile | 23 +- integration-tests/ccip-tests/README.md | 31 +-- .../ccip-tests/testconfig/README.md | 233 ++++++++++++++---- .../ccip-tests/testconfig/ccip.go | 12 + .../testconfig/examples/.testsecrets.example | 39 +++ .../testconfig/examples/secrets.toml.example | 52 ---- .../ccip-tests/testconfig/global.go | 214 +++++++++++++--- integration-tests/go.mod | 4 +- integration-tests/go.sum | 9 +- integration-tests/load/go.mod | 4 +- integration-tests/load/go.sum | 9 +- 18 files changed, 580 insertions(+), 359 deletions(-) create mode 100644 integration-tests/ccip-tests/testconfig/examples/.testsecrets.example delete mode 100644 integration-tests/ccip-tests/testconfig/examples/secrets.toml.example diff --git a/.github/actions/setup-create-base64-config-ccip/action.yml b/.github/actions/setup-create-base64-config-ccip/action.yml index 88d9fe8078..e741a2dac0 100644 --- a/.github/actions/setup-create-base64-config-ccip/action.yml +++ b/.github/actions/setup-create-base64-config-ccip/action.yml @@ -11,62 +11,39 @@ inputs: default: "false" selectedNetworks: description: The networks to run tests against - chainlinkImage: - description: The chainlink image to use - default: "public.ecr.aws/chainlink/chainlink" chainlinkVersion: description: The git commit sha to use for the image tag - upgradeImage: - description: The chainlink image to upgrade to - default: "" upgradeVersion: - description: The git commit sha to use for the image tag - lokiEndpoint: - description: Loki push endpoint - lokiTenantId: - description: Loki tenant id - lokiBasicAuth: - description: Loki basic auth + description: The git commit sha to use for the image tag logstreamLogTargets: description: Where to send logs (e.g. file, loki) - grafanaUrl: - description: Grafana URL - grafanaDashboardUrl: - description: Grafana dashboard URL - grafanaBearerToken: - description: Grafana bearer token customEvmNodes: description: Custom EVM nodes to use in key=value format, where key is chain id and value is docker image to use. If they are provided the number of networksSelected must be equal to the number of customEvmNodes evmNodeLogLevel: description: Log level for the custom EVM nodes default: "info" +outputs: + base64_config: + description: The base64-encoded config + value: ${{ steps.base64_config_override.outputs.base64_config }} runs: using: composite steps: - name: Prepare Base64 TOML override shell: bash - id: base64-config-override + id: base64_config_override env: RUN_ID: ${{ inputs.runId }} SELECTED_NETWORKS: ${{ inputs.selectedNetworks }} EXISTING_NAMESPACE: ${{ inputs.existingNamespace }} TEST_LOG_COLLECT: ${{ inputs.testLogCollect }} - CHAINLINK_IMAGE: ${{ inputs.chainlinkImage }} CHAINLINK_VERSION: ${{ inputs.chainlinkVersion }} - UPGRADE_IMAGE: ${{ inputs.upgradeImage }} UPGRADE_VERSION: ${{ inputs.upgradeVersion }} - LOKI_ENDPOINT: ${{ inputs.lokiEndpoint }} - LOKI_TENANT_ID: ${{ inputs.lokiTenantId }} - LOKI_BASIC_AUTH: ${{ inputs.lokiBasicAuth }} LOGSTREAM_LOG_TARGETS: ${{ inputs.logstreamLogTargets }} - GRAFANA_URL: ${{ inputs.grafanaUrl }} - GRAFANA_DASHBOARD_URL: ${{ inputs.grafanaDashboardUrl }} - GRAFANA_BEARER_TOKEN: ${{ inputs.grafanaBearerToken }} CUSTOM_EVM_NODES: ${{ inputs.customEvmNodes }} EVM_NODE_LOG_LEVEL: ${{ inputs.evmNodeLogLevel }} run: | - echo ::add-mask::$CHAINLINK_IMAGE function convert_to_toml_array() { local IFS=',' local input_array=($1) @@ -133,11 +110,6 @@ runs: fi fi - grafana_bearer_token="" - if [ -n "$GRAFANA_BEARER_TOKEN" ]; then - grafana_bearer_token="bearer_token_secret=\"$GRAFANA_BEARER_TOKEN\"" - fi - cat << EOF > config.toml [CCIP] [CCIP.Env] @@ -147,13 +119,8 @@ runs: [CCIP.Env.NewCLCluster] [CCIP.Env.NewCLCluster.Common] [CCIP.Env.NewCLCluster.Common.ChainlinkImage] - image="$CHAINLINK_IMAGE" version="$CHAINLINK_VERSION" - [CCIP.Env.NewCLCluster.Common.ChainlinkUpgradeImage] - image="$UPGRADE_IMAGE" - version="$UPGRADE_VERSION" - $custom_nodes_toml [CCIP.Env.Logging] @@ -163,16 +130,6 @@ runs: [CCIP.Env.Logging.LogStream] log_targets=$log_targets - [CCIP.Env.Logging.Loki] - tenant_id="$LOKI_TENANT_ID" - endpoint="$LOKI_ENDPOINT" - basic_auth_secret="$LOKI_BASIC_AUTH" - - [CCIP.Env.Logging.Grafana] - base_url="$GRAFANA_URL" - dashboard_url="$GRAFANA_DASHBOARD_URL" - $grafana_bearer_token - [CCIP.Groups.load] TestRunName = '$EXISTING_NAMESPACE' @@ -181,7 +138,14 @@ runs: EOF - BASE64_CCIP_SECRETS_CONFIG=$(cat config.toml | base64 -w 0) - echo ::add-mask::$BASE64_CCIP_SECRETS_CONFIG - echo "BASE64_CCIP_SECRETS_CONFIG=$BASE64_CCIP_SECRETS_CONFIG" >> $GITHUB_ENV - echo "TEST_BASE64_CCIP_SECRETS_CONFIG=$BASE64_CCIP_SECRETS_CONFIG" >> $GITHUB_ENV + # Check if UPGRADE_VERSION is not empty and append to config.toml + if [ -n "$UPGRADE_VERSION" ]; then + cat << EOF >> config.toml + [CCIP.Env.NewCLCluster.Common.ChainlinkUpgradeImage] + version="$UPGRADE_VERSION" + EOF + fi + + BASE64_CONFIG=$(cat config.toml | base64 -w 0) + echo ::add-mask::$BASE64_CONFIG + echo "base64_config=$BASE64_CONFIG" >> $GITHUB_OUTPUT diff --git a/.github/workflows/ccip-chaos-tests.yml b/.github/workflows/ccip-chaos-tests.yml index 6d1aaffb17..da868886f1 100644 --- a/.github/workflows/ccip-chaos-tests.yml +++ b/.github/workflows/ccip-chaos-tests.yml @@ -123,23 +123,20 @@ jobs: uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - name: Prepare Base64 TOML override for CCIP secrets uses: ./.github/actions/setup-create-base64-config-ccip + id: setup_create_base64_config_ccip with: runId: ${{ github.run_id }} testLogCollect: ${{ vars.TEST_LOG_COLLECT }} - chainlinkImage: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink chainlinkVersion: ${{ github.sha }} - lokiEndpoint: ${{ secrets.LOKI_URL }} - lokiTenantId: ${{ vars.LOKI_TENANT_ID }} logstreamLogTargets: ${{ vars.LOGSTREAM_LOG_TARGETS }} - grafanaUrl: ${{ vars.GRAFANA_URL }} - grafanaDashboardUrl: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" - name: Run Chaos Tests - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@b49a9d04744b0237908831730f8553f26d73a94b # v2.3.17 + uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@d38226be720c5ccc1ff4d3cee40608ebf264cd59 # v2.3.26 + env: + BASE64_CCIP_CONFIG_OVERRIDE: ${{ steps.setup_create_base64_config_ccip.outputs.base64_config }} + TEST_BASE64_CCIP_CONFIG_OVERRIDE: ${{ steps.setup_create_base64_config_ccip.outputs.base64_config }} with: test_command_to_run: cd ./integration-tests && go test -timeout 1h -count=1 -json -test.parallel 11 -run 'TestChaosCCIP' ./chaos 2>&1 | tee /tmp/gotest.log | gotestloghelper -ci test_download_vendor_packages_command: make gomod - cl_repo: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink - cl_image_tag: ${{ github.sha }} artifacts_location: ./integration-tests/chaos/logs publish_check_name: CCIP Chaos Test Results publish_report_paths: ./tests-chaos-report.xml @@ -153,6 +150,13 @@ jobs: aws_registries: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} cache_key_id: ccip-load-${{ env.MOD_CACHE_VERSION }} cache_restore_only: "true" + DEFAULT_LOKI_TENANT_ID: ${{ vars.LOKI_TENANT_ID }} + DEFAULT_LOKI_ENDPOINT: ${{ secrets.LOKI_URL }} + DEFAULT_LOKI_BASIC_AUTH: ${{ secrets.LOKI_BASIC_AUTH }} + DEFAULT_CHAINLINK_IMAGE: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink + DEFAULT_GRAFANA_BASE_URL: ${{ vars.GRAFANA_URL }} + DEFAULT_GRAFANA_DASHBOARD_URL: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" + ## Notify in slack if the job fails - name: Notify Slack if: failure() && github.event_name != 'workflow_dispatch' @@ -205,23 +209,20 @@ jobs: uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - name: Prepare Base64 TOML override for CCIP secrests uses: ./.github/actions/setup-create-base64-config-ccip + id: setup_create_base64_config_ccip with: runId: ${{ github.run_id }} testLogCollect: ${{ vars.TEST_LOG_COLLECT }} - chainlinkImage: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink chainlinkVersion: ${{ github.sha }} - lokiEndpoint: ${{ secrets.LOKI_URL }} - lokiTenantId: ${{ vars.LOKI_TENANT_ID }} logstreamLogTargets: ${{ vars.LOGSTREAM_LOG_TARGETS }} - grafanaUrl: ${{ vars.GRAFANA_URL }} - grafanaDashboardUrl: "/d/6vjVx-1V8/ccip-long-running-tests" - name: Run Load With Chaos Tests - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@b49a9d04744b0237908831730f8553f26d73a94b # v2.3.17 + uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@d38226be720c5ccc1ff4d3cee40608ebf264cd59 # v2.3.26 + env: + BASE64_CCIP_CONFIG_OVERRIDE: ${{ steps.setup_create_base64_config_ccip.outputs.base64_config }} + TEST_BASE64_CCIP_CONFIG_OVERRIDE: ${{ steps.setup_create_base64_config_ccip.outputs.base64_config }} with: test_command_to_run: cd ./integration-tests/ccip-tests && go test -timeout 2h -count=1 -json -test.parallel 4 -run '^TestLoadCCIPStableWithPodChaosDiffCommitAndExec' ./load 2>&1 | tee /tmp/gotest.log | gotestfmt test_download_vendor_packages_command: make gomod - cl_repo: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink - cl_image_tag: ${{ github.sha }} artifacts_location: ./integration-tests/load/logs publish_check_name: CCIP Chaos With Load Test Results publish_report_paths: ./tests-chaos-with-load-report.xml @@ -235,6 +236,12 @@ jobs: aws_registries: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} cache_key_id: ccip-load-${{ env.MOD_CACHE_VERSION }} cache_restore_only: "true" + DEFAULT_LOKI_TENANT_ID: ${{ vars.LOKI_TENANT_ID }} + DEFAULT_LOKI_ENDPOINT: ${{ secrets.LOKI_URL }} + DEFAULT_LOKI_BASIC_AUTH: ${{ secrets.LOKI_BASIC_AUTH }} + DEFAULT_CHAINLINK_IMAGE: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink + DEFAULT_GRAFANA_BASE_URL: ${{ vars.GRAFANA_URL }} + DEFAULT_GRAFANA_DASHBOARD_URL: "/d/6vjVx-1V8/ccip-long-running-tests" ## Notify in slack if the job fails - name: Notify Slack if: failure() && github.event_name != 'workflow_dispatch' diff --git a/.github/workflows/ccip-client-compatibility-tests.yml b/.github/workflows/ccip-client-compatibility-tests.yml index 0d485057c2..58c05f2f72 100644 --- a/.github/workflows/ccip-client-compatibility-tests.yml +++ b/.github/workflows/ccip-client-compatibility-tests.yml @@ -492,33 +492,18 @@ jobs: runId: ${{ github.run_id }} testLogCollect: ${{ vars.TEST_LOG_COLLECT }} selectedNetworks: ${{ matrix.evm_node.networks }} - chainlinkImage: ${{ env.CHAINLINK_IMAGE }} chainlinkVersion: ${{ needs.select-versions.outputs.chainlink_version }} - pyroscopeServer: ${{ !startsWith(github.ref, 'refs/tags/') && '' || secrets.QA_PYROSCOPE_INSTANCE }} # Avoid sending blank envs https://github.com/orgs/community/discussions/25725 - pyroscopeEnvironment: ci-ccip-bidirectional-lane-${{ matrix.evm_node.name }} - pyroscopeKey: ${{ secrets.QA_PYROSCOPE_KEY }} - lokiEndpoint: ${{ secrets.LOKI_URL_CI }} - lokiTenantId: ${{ vars.LOKI_TENANT_ID }} - lokiBasicAuth: ${{ secrets.LOKI_BASIC_AUTH }} logstreamLogTargets: ${{ vars.LOGSTREAM_LOG_TARGETS }} - grafanaUrl: ${{ vars.GRAFANA_URL }} - grafanaDashboardUrl: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" - name: Prepare Base64 TOML override for CCIP secrets uses: ./.github/actions/setup-create-base64-config-ccip + id: setup_create_base64_config_ccip with: runId: ${{ github.run_id }} - testLogCollect: ${{ vars.TEST_LOG_COLLECT }} selectedNetworks: ${{ matrix.evm_node.networks }} - chainlinkImage: ${{ env.CHAINLINK_IMAGE }} + testLogCollect: ${{ vars.TEST_LOG_COLLECT }} chainlinkVersion: ${{ needs.select-versions.outputs.chainlink_version }} - lokiEndpoint: ${{ secrets.LOKI_URL_CI }} - lokiTenantId: ${{ vars.LOKI_TENANT_ID }} - lokiBasicAuth: ${{ secrets.LOKI_BASIC_AUTH }} logstreamLogTargets: ${{ vars.LOGSTREAM_LOG_TARGETS }} - grafanaUrl: ${{ vars.GRAFANA_URL }} - grafanaDashboardUrl: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" customEvmNodes: ${{ matrix.evm_node.docker_image }} - evmNodeLogLevel: "trace" - name: Prepare test log name run: | replace_special_chars() { @@ -547,12 +532,13 @@ jobs: echo "EVM Implementation Networks: ${{ matrix.evm_node.networks }}" echo "Test identifier: ${{ matrix.evm_node.name }}" - name: Run Tests - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@fc3e0df622521019f50d772726d6bf8dc919dd38 # v2.3.19 + uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@d38226be720c5ccc1ff4d3cee40608ebf264cd59 # v2.3.26 + env: + BASE64_CCIP_CONFIG_OVERRIDE: ${{ steps.setup_create_base64_config_ccip.outputs.base64_config }} + TEST_BASE64_CCIP_CONFIG_OVERRIDE: ${{ steps.setup_create_base64_config_ccip.outputs.base64_config }} with: test_command_to_run: cd ./integration-tests && go test -timeout 30m -count=1 -json -test.parallel=2 ${{ matrix.evm_node.run }} 2>&1 | tee /tmp/gotest.log | gotestloghelper -ci test_download_vendor_packages_command: cd ./integration-tests && go mod download - cl_repo: ${{ env.CHAINLINK_IMAGE }} - cl_image_tag: ${{ needs.select-versions.outputs.chainlink_version }} aws_registries: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} artifacts_name: ${{ env.TEST_LOG_NAME }} artifacts_location: | @@ -568,6 +554,17 @@ jobs: QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} QA_KUBECONFIG: "" should_tidy: "false" + DEFAULT_LOKI_TENANT_ID: ${{ vars.LOKI_TENANT_ID }} + DEFAULT_LOKI_ENDPOINT: ${{ secrets.LOKI_URL_CI }} + DEFAULT_LOKI_BASIC_AUTH: ${{ secrets.LOKI_BASIC_AUTH }} + DEFAULT_CHAINLINK_IMAGE: ${{ env.CHAINLINK_IMAGE }} + DEFAULT_GRAFANA_BASE_URL: ${{ vars.GRAFANA_URL }} + DEFAULT_GRAFANA_DASHBOARD_URL: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" + DEFAULT_PYROSCOPE_SERVER_URL: ${{ !startsWith(github.ref, 'refs/tags/') && '' || secrets.QA_PYROSCOPE_INSTANCE }} # Avoid sending blank envs https://github.com/orgs/community/discussions/25725 + DEFAULT_PYROSCOPE_KEY: ${{ secrets.QA_PYROSCOPE_KEY }} + DEFAULT_PYROSCOPE_ENVIRONMENT: ci-ccip-bidirectional-lane-${{ matrix.evm_node.name }} + DEFAULT_PYROSCOPE_ENABLED: 'true' + - name: Print failed test summary if: always() uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/show-test-summary@1587f59bfd626b668d303abbc90fee41b12397e6 # v2.3.23 diff --git a/.github/workflows/ccip-live-network-tests.yml b/.github/workflows/ccip-live-network-tests.yml index 29792f77ed..3c638a1546 100644 --- a/.github/workflows/ccip-live-network-tests.yml +++ b/.github/workflows/ccip-live-network-tests.yml @@ -17,6 +17,10 @@ on: options: - 'load' - 'smoke' + test_secrets_override_key: + description: 'Key to run tests with custom test secrets' + required: false + type: string # Only run 1 of this workflow at a time per PR concurrency: @@ -25,8 +29,8 @@ concurrency: env: CHAINLINK_IMAGE: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink - CHAINLINK_VERSION: ${{ github.sha}} - CHAINLINK_TEST_VERSION: ${{ github.sha}} + CHAINLINK_VERSION: ${{ github.sha }} + CHAINLINK_TEST_VERSION: ${{ github.sha }} ENV_JOB_IMAGE: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink-ccip-tests:${{ github.sha }} INTERNAL_DOCKER_REPO: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com AWS_ECR_REPO_PUBLIC_REGISTRY: public.ecr.aws @@ -142,6 +146,7 @@ jobs: with: ref: ${{ env.REF_NAME }} - name: Prepare Base64 TOML override + id: set_override_config shell: bash run: | # this key secrets.QA_SHARED_803C_KEY has a story behind it. To know more, see CCIP-2875 and SECHD-16575 tickets. @@ -154,14 +159,12 @@ jobs: if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then BASE64_CCIP_CONFIG_OVERRIDE=$(jq -r '.inputs.base64_test_input' $GITHUB_EVENT_PATH) echo ::add-mask::$BASE64_CCIP_CONFIG_OVERRIDE - echo "BASE64_CCIP_CONFIG_OVERRIDE=$BASE64_CCIP_CONFIG_OVERRIDE" >> $GITHUB_ENV - echo "TEST_BASE64_CCIP_CONFIG_OVERRIDE=$BASE64_CCIP_CONFIG_OVERRIDE" >> $GITHUB_ENV + echo "base_64_override=$BASE64_CCIP_CONFIG_OVERRIDE" >> $GITHUB_OUTPUT fi if [[ "${{ github.event_name }}" == "schedule" ]]; then BASE64_CCIP_CONFIG_OVERRIDE=$(base64 -w 0 -i ./integration-tests/ccip-tests/testconfig/override/${{ matrix.config }}) echo ::add-mask::$BASE64_CCIP_CONFIG_OVERRIDE - echo "BASE64_CCIP_CONFIG_OVERRIDE=$BASE64_CCIP_CONFIG_OVERRIDE" >> $GITHUB_ENV - echo "TEST_BASE64_CCIP_CONFIG_OVERRIDE=$BASE64_CCIP_CONFIG_OVERRIDE" >> $GITHUB_ENV + echo "base_64_override=$BASE64_CCIP_CONFIG_OVERRIDE" >> $GITHUB_OUTPUT echo "SLACK_USER=${{ secrets.QA_SLACK_USER }}" >> $GITHUB_ENV fi - name: step summary @@ -173,19 +176,14 @@ jobs: echo "\`${{ env.CHAINLINK_TEST_VERSION }}\`" >> $GITHUB_STEP_SUMMARY - name: Prepare Base64 TOML override for CCIP secrets uses: ./.github/actions/setup-create-base64-config-ccip + id: setup_create_base64_config_ccip with: runId: ${{ github.run_id }} testLogCollect: ${{ vars.TEST_LOG_COLLECT }} - chainlinkImage: ${{ env.CHAINLINK_IMAGE }} - chainlinkVersion: ${{ github.sha }} - lokiEndpoint: ${{ secrets.LOKI_URL }} - lokiTenantId: ${{ vars.LOKI_TENANT_ID }} - lokiBasicAuth: ${{ secrets.LOKI_BASIC_AUTH }} + chainlinkVersion: ${{ env.CHAINLINK_VERSION }} logstreamLogTargets: ${{ vars.LOGSTREAM_LOG_TARGETS }} - grafanaUrl: ${{ vars.GRAFANA_URL }} - grafanaDashboardUrl: "/d/6vjVx-1V8/ccip-long-running-tests" - name: Run Tests - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@5dd916d08c03cb5f9a97304f4f174820421bb946 # v2.3.11 + uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@d38226be720c5ccc1ff4d3cee40608ebf264cd59 # v2.3.26 env: TEST_SUITE: load TEST_ARGS: -test.timeout 900h @@ -194,11 +192,12 @@ jobs: RR_CPU: 4 DETACH_RUNNER: true TEST_TRIGGERED_BY: ccip-load-test-ci + BASE64_CCIP_CONFIG_OVERRIDE: ${{ steps.set_override_config.outputs.base_64_override }},${{ steps.setup_create_base64_config_ccip.outputs.base64_config }} + TEST_BASE64_CCIP_CONFIG_OVERRIDE: ${{ steps.set_override_config.outputs.base_64_override }},${{ steps.setup_create_base64_config_ccip.outputs.base64_config }} with: test_command_to_run: cd ./integration-tests/ccip-tests && go test -v -timeout 70m -count=1 -json -run ^TestLoadCCIPStableRPS$ ./load 2>&1 | tee /tmp/gotest.log | gotestfmt test_download_vendor_packages_command: cd ./integration-tests && go mod download - cl_repo: ${{ env.CHAINLINK_IMAGE }} - cl_image_tag: ${{ env.CHAINLINK_VERSION }} + test_secrets_override_base64: ${{ secrets[inputs.test_secrets_override_key] }} token: ${{ secrets.GITHUB_TOKEN }} go_mod_path: ./integration-tests/go.mod QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} @@ -210,7 +209,13 @@ jobs: cache_key_id: ccip-load-${{ env.MOD_CACHE_VERSION }} cache_restore_only: "true" should_cleanup: false - + DEFAULT_CHAINLINK_IMAGE: ${{ env.CHAINLINK_IMAGE }} + DEFAULT_LOKI_TENANT_ID: ${{ vars.LOKI_TENANT_ID }} + DEFAULT_LOKI_ENDPOINT: ${{ secrets.LOKI_URL }} + DEFAULT_LOKI_BASIC_AUTH: ${{ secrets.LOKI_BASIC_AUTH }} + DEFAULT_GRAFANA_BASE_URL: ${{ vars.GRAFANA_URL }} + DEFAULT_GRAFANA_DASHBOARD_URL: "/d/6vjVx-1V8/ccip-long-running-tests" + ccip-smoke-test: name: CCIP smoke Test environment: integration @@ -249,6 +254,7 @@ jobs: with: ref: ${{ env.REF_NAME }} - name: Prepare Base64 TOML override + id: set_override_config shell: bash run: | BASE64_NETWORK_CONFIG=$(echo $BASE64_NETWORK_CONFIG | base64 -w 0 -d | sed -e 's/evm_key/${{ secrets.QA_SHARED_803C_KEY }}/g' | base64 -w 0) @@ -260,8 +266,7 @@ jobs: if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then BASE64_CCIP_CONFIG_OVERRIDE=$(jq -r '.inputs.base64_test_input' $GITHUB_EVENT_PATH) echo ::add-mask::$BASE64_CCIP_CONFIG_OVERRIDE - echo "BASE64_CCIP_CONFIG_OVERRIDE=$BASE64_CCIP_CONFIG_OVERRIDE" >> $GITHUB_ENV - echo "TEST_BASE64_CCIP_CONFIG_OVERRIDE=$BASE64_CCIP_CONFIG_OVERRIDE" >> $GITHUB_ENV + echo "base_64_override=$BASE64_CCIP_CONFIG_OVERRIDE" >> $GITHUB_OUTPUT fi - name: step summary shell: bash @@ -272,19 +277,14 @@ jobs: echo "\`${{ env.CHAINLINK_TEST_VERSION }}\`" >> $GITHUB_STEP_SUMMARY - name: Prepare Base64 TOML override for CCIP secrets uses: ./.github/actions/setup-create-base64-config-ccip + id: setup_create_base64_config_ccip with: runId: ${{ github.run_id }} testLogCollect: ${{ vars.TEST_LOG_COLLECT }} - chainlinkImage: ${{ env.CHAINLINK_IMAGE }} - chainlinkVersion: ${{ github.sha }} - lokiEndpoint: ${{ secrets.LOKI_URL }} - lokiTenantId: ${{ vars.LOKI_TENANT_ID }} - lokiBasicAuth: ${{ secrets.LOKI_BASIC_AUTH }} + chainlinkVersion: ${{ env.CHAINLINK_VERSION }} logstreamLogTargets: ${{ vars.LOGSTREAM_LOG_TARGETS }} - grafanaUrl: ${{ vars.GRAFANA_URL }} - grafanaDashboardUrl: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" - name: Run Tests - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@5dd916d08c03cb5f9a97304f4f174820421bb946 # v2.3.11 + uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@d38226be720c5ccc1ff4d3cee40608ebf264cd59 # v2.3.26 env: TEST_SUITE: smoke TEST_ARGS: -test.timeout 900h @@ -293,11 +293,11 @@ jobs: RR_MEM: 8Gi RR_CPU: 4 TEST_TRIGGERED_BY: ccip-smoke-test-ci + BASE64_CCIP_CONFIG_OVERRIDE: ${{ steps.set_override_config.outputs.base_64_override }},${{ steps.setup_create_base64_config_ccip.outputs.base64_config }} + TEST_BASE64_CCIP_CONFIG_OVERRIDE: ${{ steps.set_override_config.outputs.base_64_override }},${{ steps.setup_create_base64_config_ccip.outputs.base64_config }} with: test_command_to_run: cd ./integration-tests/ccip-tests && go test -v -timeout 70m -count=1 -p 30 -json -run ^TestSmokeCCIPForBidirectionalLane$ ./smoke 2>&1 | tee /tmp/gotest.log | gotestfmt test_download_vendor_packages_command: cd ./integration-tests && go mod download - cl_repo: ${{ env.CHAINLINK_IMAGE }} - cl_image_tag: ${{ env.CHAINLINK_VERSION }} token: ${{ secrets.GITHUB_TOKEN }} go_mod_path: ./integration-tests/go.mod QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} @@ -308,4 +308,10 @@ jobs: aws_registries: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} cache_key_id: ccip-smoke-${{ env.MOD_CACHE_VERSION }} cache_restore_only: "true" - should_cleanup: false \ No newline at end of file + should_cleanup: false + DEFAULT_CHAINLINK_IMAGE: ${{ env.CHAINLINK_IMAGE }} + DEFAULT_LOKI_TENANT_ID: ${{ vars.LOKI_TENANT_ID }} + DEFAULT_LOKI_ENDPOINT: ${{ secrets.LOKI_URL }} + DEFAULT_LOKI_BASIC_AUTH: ${{ secrets.LOKI_BASIC_AUTH }} + DEFAULT_GRAFANA_BASE_URL: ${{ vars.GRAFANA_URL }} + DEFAULT_GRAFANA_DASHBOARD_URL: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" \ No newline at end of file diff --git a/.github/workflows/ccip-load-tests.yml b/.github/workflows/ccip-load-tests.yml index 9f6a2b0878..f88f5bd143 100644 --- a/.github/workflows/ccip-load-tests.yml +++ b/.github/workflows/ccip-load-tests.yml @@ -10,6 +10,11 @@ on: base64_test_input: # base64 encoded toml for test input description: 'Base64 encoded toml test input' required: false + test_secrets_override_key: + description: 'Key to run tests with custom test secrets' + required: false + type: string + pull_request: # DEBUG: Checking run conditions # Only run 1 of this workflow at a time per PR concurrency: @@ -52,7 +57,7 @@ jobs: with: cl_repo: smartcontractkit/chainlink-ccip cl_ref: ${{ env.CHAINLINK_VERSION }} - push_tag: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink:${{ env.CHAINLINK_VERSION }} + push_tag: ${{ env.CHAINLINK_IMAGE }}:${{ env.CHAINLINK_VERSION }} QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} - name: Collect Metrics @@ -107,7 +112,6 @@ jobs: contents: read env: CHAINLINK_ENV_USER: ${{ github.actor }} - SLACK_USER: ${{ inputs.slackMemberID }} SLACK_API_KEY: ${{ secrets.QA_SLACK_API_KEY }} SLACK_CHANNEL: ${{ secrets.QA_SLACK_CHANNEL }} TEST_LOG_LEVEL: info @@ -143,20 +147,19 @@ jobs: with: ref: ${{ env.REF_NAME }} - name: Sets env vars + id: set_override_config shell: bash run: | # if the matrix.type.config_path is set, use it as the override config if [ -n "${{ matrix.type.config_path }}" ]; then - echo "BASE64_CCIP_CONFIG_OVERRIDE=$(base64 -w 0 -i ${{ matrix.type.config_path }})" >> $GITHUB_ENV - echo "TEST_BASE64_CCIP_CONFIG_OVERRIDE=$(base64 -w 0 -i ${{ matrix.type.config_path }})" >> $GITHUB_ENV + BASE64_CCIP_CONFIG_OVERRIDE=$(base64 -w 0 -i ${{ matrix.type.config_path }}) + echo ::add-mask::$BASE64_CCIP_CONFIG_OVERRIDE + echo "base_64_override=$BASE64_CCIP_CONFIG_OVERRIDE" >> $GITHUB_OUTPUT fi if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then BASE64_CCIP_CONFIG_OVERRIDE=$(jq -r '.inputs.base64_test_input' $GITHUB_EVENT_PATH) echo ::add-mask::$BASE64_CCIP_CONFIG_OVERRIDE - if [ -n "${BASE64_CCIP_CONFIG_OVERRIDE}" && "$BASE64_CCIP_CONFIG_OVERRIDE" != "null"]; then - echo "BASE64_CCIP_CONFIG_OVERRIDE=$BASE64_CCIP_CONFIG_OVERRIDE" >> $GITHUB_ENV - echo "TEST_BASE64_CCIP_CONFIG_OVERRIDE=$BASE64_CCIP_CONFIG_OVERRIDE" >> $GITHUB_ENV - fi + echo "base_64_override=$BASE64_CCIP_CONFIG_OVERRIDE" >> $GITHUB_OUTPUT fi - name: step summary shell: bash @@ -167,18 +170,14 @@ jobs: echo "\`${{ env.INPUT_CHAINLINK_TEST_VERSION }}\`" >> $GITHUB_STEP_SUMMARY - name: Prepare Base64 TOML override for CCIP secrets uses: ./.github/actions/setup-create-base64-config-ccip + id: setup_create_base64_config_ccip with: runId: ${{ github.run_id }} testLogCollect: ${{ vars.TEST_LOG_COLLECT }} - chainlinkImage: ${{ env.CHAINLINK_IMAGE }} chainlinkVersion: ${{ github.sha }} - lokiEndpoint: ${{ secrets.LOKI_URL }} - lokiTenantId: ${{ vars.LOKI_TENANT_ID }} logstreamLogTargets: ${{ vars.LOGSTREAM_LOG_TARGETS }} - grafanaUrl: ${{ vars.GRAFANA_URL }} - grafanaDashboardUrl: "/d/6vjVx-1V8/ccip-long-running-tests" - name: Run Tests - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@b49a9d04744b0237908831730f8553f26d73a94b # v2.3.17 + uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@d38226be720c5ccc1ff4d3cee40608ebf264cd59 # v2.3.26 env: TEST_SUITE: load TEST_ARGS: -test.timeout 900h @@ -186,11 +185,12 @@ jobs: RR_MEM: 8Gi RR_CPU: 4 TEST_TRIGGERED_BY: ccip-load-test-ci-${{ matrix.type.name }} + BASE64_CCIP_CONFIG_OVERRIDE: ${{ steps.set_override_config.outputs.base_64_override }},${{ steps.setup_create_base64_config_ccip.outputs.base64_config }} + TEST_BASE64_CCIP_CONFIG_OVERRIDE: ${{ steps.set_override_config.outputs.base_64_override }},${{ steps.setup_create_base64_config_ccip.outputs.base64_config }} with: test_command_to_run: cd ./integration-tests/ccip-tests && go test -v -timeout 70m -count=1 -json -run ${{ matrix.type.run }} ./load 2>&1 | tee /tmp/gotest.log | gotestloghelper -ci test_download_vendor_packages_command: cd ./integration-tests && go mod download - cl_repo: ${{ env.CHAINLINK_IMAGE }} - cl_image_tag: ${{ env.CHAINLINK_VERSION }} + test_secrets_override_base64: ${{ secrets[inputs.test_secrets_override_key] }} token: ${{ secrets.GITHUB_TOKEN }} go_mod_path: ./integration-tests/go.mod QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} @@ -203,6 +203,12 @@ jobs: cache_key_id: ccip-load-${{ env.MOD_CACHE_VERSION }} cache_restore_only: "true" should_cleanup: "true" + DEFAULT_CHAINLINK_IMAGE: ${{ env.CHAINLINK_IMAGE }} + DEFAULT_LOKI_TENANT_ID: ${{ vars.LOKI_TENANT_ID }} + DEFAULT_LOKI_ENDPOINT: ${{ secrets.LOKI_URL }} + DEFAULT_LOKI_BASIC_AUTH: ${{ secrets.LOKI_BASIC_AUTH }} + DEFAULT_GRAFANA_BASE_URL: ${{ vars.GRAFANA_URL }} + DEFAULT_GRAFANA_DASHBOARD_URL: "/d/6vjVx-1V8/ccip-long-running-tests" # Reporting Jobs start-slack-thread: diff --git a/.github/workflows/ccip-offchain-upgrade-tests.yml b/.github/workflows/ccip-offchain-upgrade-tests.yml index 50e02dfc55..147f727425 100644 --- a/.github/workflows/ccip-offchain-upgrade-tests.yml +++ b/.github/workflows/ccip-offchain-upgrade-tests.yml @@ -221,24 +221,19 @@ jobs: fi - name: Prepare Base64 TOML override for CCIP secrets uses: ./.github/actions/setup-create-base64-config-ccip + id: setup_create_base64_config_ccip with: runId: ${{ github.run_id }} testLogCollect: ${{ vars.TEST_LOG_COLLECT }} - selectedNetworks: SIMULATED_1,SIMULATED_2 - chainlinkImage: ${{ env.AWS_ECR_REPO_PUBLIC_REGISTRY }}/w0i8p0z9/chainlink-ccip chainlinkVersion: ${{ env.RELEASE_TAG }} - lokiEndpoint: ${{ secrets.LOKI_URL_CI }} - lokiTenantId: ${{ vars.LOKI_TENANT_ID }} - lokiBasicAuth: ${{ secrets.LOKI_BASIC_AUTH }} logstreamLogTargets: ${{ vars.LOGSTREAM_LOG_TARGETS }} - grafanaUrl: ${{ vars.GRAFANA_URL }} - grafanaDashboardUrl: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" + selectedNetworks: SIMULATED_1,SIMULATED_2 - name: Run Tests if: needs.changes.outputs.src == 'true' || github.event_name == 'workflow_dispatch' - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@b49a9d04744b0237908831730f8553f26d73a94b # v2.3.17 + uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@d38226be720c5ccc1ff4d3cee40608ebf264cd59 # v2.3.26 env: - BASE64_CCIP_CONFIG_OVERRIDE: ${{ steps.set_override_config.outputs.base_64_override }} - TEST_BASE64_CCIP_CONFIG_OVERRIDE: ${{ steps.set_override_config.outputs.base_64_override }} + BASE64_CCIP_CONFIG_OVERRIDE: ${{ steps.set_override_config.outputs.base_64_override }},${{ steps.setup_create_base64_config_ccip.outputs.base64_config }} + TEST_BASE64_CCIP_CONFIG_OVERRIDE: ${{ steps.set_override_config.outputs.base_64_override }},${{ steps.setup_create_base64_config_ccip.outputs.base64_config }} ENV_JOB_IMAGE: ${{ env.ENV_JOB_IMAGE_BASE }}:${{ github.sha }} TEST_SUITE: smoke TEST_ARGS: -test.timeout 30m @@ -266,6 +261,12 @@ jobs: triggered_by: ${{ env.TEST_TRIGGERED_BY }} should_tidy: "false" should_cleanup: "false" + DEFAULT_CHAINLINK_IMAGE: ${{ env.AWS_ECR_REPO_PUBLIC_REGISTRY }}/w0i8p0z9/chainlink-ccip + DEFAULT_LOKI_TENANT_ID: ${{ vars.LOKI_TENANT_ID }} + DEFAULT_LOKI_ENDPOINT: ${{ secrets.LOKI_URL_CI }} + DEFAULT_LOKI_BASIC_AUTH: ${{ secrets.LOKI_BASIC_AUTH }} + DEFAULT_GRAFANA_BASE_URL: ${{ vars.GRAFANA_URL }} + DEFAULT_GRAFANA_DASHBOARD_URL: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" - name: store laneconfig in artifacts uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 @@ -342,25 +343,20 @@ jobs: fi - name: Prepare Base64 TOML override for CCIP secrets uses: ./.github/actions/setup-create-base64-config-ccip + id: setup_create_base64_config_ccip with: runId: ${{ github.run_id }} - existingNamespace: ${{ needs.run-test-with-last-release.outputs.existing_namespace }} testLogCollect: ${{ vars.TEST_LOG_COLLECT }} - chainlinkImage: ${{ env.CHAINLINK_IMAGE }} chainlinkVersion: ${{ github.sha }} - upgradeImage: ${{ env.CHAINLINK_IMAGE }} upgradeVersion: ${{ github.sha }} - lokiEndpoint: ${{ secrets.LOKI_URL }} - lokiTenantId: ${{ vars.LOKI_TENANT_ID }} logstreamLogTargets: ${{ vars.LOGSTREAM_LOG_TARGETS }} - grafanaUrl: ${{ vars.GRAFANA_URL }} - grafanaDashboardUrl: "/d/6vjVx-1V8/ccip-long-running-tests" + existingNamespace: ${{ needs.run-test-with-last-release.outputs.existing_namespace }} - name: Run Tests if: needs.changes.outputs.src == 'true' || github.event_name == 'workflow_dispatch' - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@b49a9d04744b0237908831730f8553f26d73a94b # v2.3.17 + uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@d38226be720c5ccc1ff4d3cee40608ebf264cd59 # v2.3.26 env: - BASE64_CCIP_CONFIG_OVERRIDE: ${{ steps.set_override_config.outputs.base_64_override }} - TEST_BASE64_CCIP_CONFIG_OVERRIDE: ${{ steps.set_override_config.outputs.base_64_override }} + BASE64_CCIP_CONFIG_OVERRIDE: ${{ steps.set_override_config.outputs.base_64_override }},${{ steps.setup_create_base64_config_ccip.outputs.base64_config }} + TEST_BASE64_CCIP_CONFIG_OVERRIDE: ${{ steps.set_override_config.outputs.base_64_override }},${{ steps.setup_create_base64_config_ccip.outputs.base64_config }} ENV_JOB_IMAGE: ${{ env.ENV_JOB_IMAGE_BASE }}:${{ github.sha }} TEST_SUITE: load TEST_ARGS: -test.timeout 1h @@ -387,4 +383,11 @@ jobs: QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }} should_tidy: "false" should_cleanup: "true" - triggered_by: ${{ needs.run-test-with-last-release.outputs.triggered_by }} \ No newline at end of file + triggered_by: ${{ needs.run-test-with-last-release.outputs.triggered_by }} + DEFAULT_CHAINLINK_IMAGE: ${{ env.CHAINLINK_IMAGE }} + DEFAULT_CHAINLINK_UPGRADE_IMAGE: ${{ env.CHAINLINK_IMAGE }} + DEFAULT_LOKI_TENANT_ID: ${{ vars.LOKI_TENANT_ID }} + DEFAULT_LOKI_ENDPOINT: ${{ secrets.LOKI_URL }} + DEFAULT_LOKI_BASIC_AUTH: ${{ secrets.LOKI_BASIC_AUTH }} + DEFAULT_GRAFANA_BASE_URL: ${{ vars.GRAFANA_URL }} + DEFAULT_GRAFANA_DASHBOARD_URL: "/d/6vjVx-1V8/ccip-long-running-tests" \ No newline at end of file diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index a4d82ab67f..dba8aadec6 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -553,6 +553,7 @@ jobs: gc-org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - name: Prepare Base64 CCIP TOML secrets uses: ./.github/actions/setup-create-base64-config-ccip + id: setup_create_base64_config_ccip with: runId: ${{ github.run_id }} pyroscopeServer: ${{ matrix.product.pyroscope_env == '' && '' || !startsWith(github.ref, 'refs/tags/') && '' || secrets.QA_PYROSCOPE_INSTANCE }} # Avoid sending blank envs https://github.com/orgs/community/discussions/25725 @@ -560,23 +561,16 @@ jobs: pyroscopeKey: ${{ secrets.QA_PYROSCOPE_KEY }} testLogCollect: ${{ vars.TEST_LOG_COLLECT }} selectedNetworks: SIMULATED_1,SIMULATED_2 - chainlinkImage: ${{ env.CHAINLINK_IMAGE }} - chainlinkVersion: ${{ github.sha }} - lokiEndpoint: ${{ secrets.LOKI_URL_CI }} - lokiTenantId: ${{ vars.LOKI_TENANT_ID }} - lokiBasicAuth: ${{ secrets.LOKI_BASIC_AUTH }} + chainlinkVersion: ${{ inputs.evm-ref || github.sha }} logstreamLogTargets: ${{ vars.LOGSTREAM_LOG_TARGETS }} - grafanaUrl: "http://localhost:8080/primary" - grafanaDashboardUrl: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" - grafanaBearerToken: ${{ secrets.GRAFANA_INTERNAL_URL_SHORTENER_TOKEN }} ## Run this step when changes that require tests to be run are made - name: Run Tests if: needs.changes.outputs.src == 'true' || github.event_name == 'workflow_dispatch' uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@aa8eea635029ab8d95abd3c206f56dae1e22e623 # v2.3.28 env: - BASE64_CCIP_CONFIG_OVERRIDE: ${{ steps.set_override_config.outputs.base_64_override }} - TEST_BASE64_CCIP_CONFIG_OVERRIDE: ${{ steps.set_override_config.outputs.base_64_override }} + BASE64_CCIP_CONFIG_OVERRIDE: ${{ steps.set_override_config.outputs.base_64_override }},${{ steps.setup_create_base64_config_ccip.outputs.base64_config }} + TEST_BASE64_CCIP_CONFIG_OVERRIDE: ${{ steps.set_override_config.outputs.base_64_override }},${{ steps.setup_create_base64_config_ccip.outputs.base64_config }} DEBUG_RESTY: false with: test_command_to_run: cd ./integration-tests && go test -timeout 30m -count=1 -json -test.parallel=${{ matrix.product.nodes }} ${{ steps.build-go-test-command.outputs.run_command }} 2>&1 | tee /tmp/gotest.log | gotestloghelper -ci -singlepackage -hidepassingtests=false -hidepassinglogs diff --git a/integration-tests/ccip-tests/Makefile b/integration-tests/ccip-tests/Makefile index 5a40f7ca0f..d33d956915 100644 --- a/integration-tests/ccip-tests/Makefile +++ b/integration-tests/ccip-tests/Makefile @@ -1,11 +1,13 @@ -## To Override the default config, and secret config: -# example usage: make set_config override_toml=../config/config.toml secret_toml=../config/secret.toml network_config_toml=../config/network.toml +## To Override the default config: +# example usage: make set_config override_toml=../config/config.toml network_config_toml=../config/network.toml .PHONY: set_config set_config: if [ -s "$(override_toml)" ]; then \ echo "Overriding config with $(override_toml)"; \ echo "export BASE64_CCIP_CONFIG_OVERRIDE=$$(base64 -i $(override_toml))" > ./testconfig/override/.env; \ echo "export TEST_BASE64_CCIP_CONFIG_OVERRIDE=$$(base64 -i $(override_toml))" >> ./testconfig/override/.env; \ + echo "BASE64_CCIP_CONFIG_OVERRIDE=$$(base64 -i $(override_toml))" > ./testconfig/override/debug.env; \ + echo "TEST_BASE64_CCIP_CONFIG_OVERRIDE=$$(base64 -i $(override_toml))" >> ./testconfig/override/debug.env; \ else \ echo "No override config found, using default config"; \ echo > ./testconfig/override/.env; \ @@ -15,14 +17,15 @@ set_config: echo "export BASE64_NETWORK_CONFIG=$$(base64 -i $(network_config_toml))" >> ./testconfig/override/.env; \ fi - @echo "setting secret config with $(secret_toml)" - @echo "export BASE64_CCIP_SECRETS_CONFIG=$$(base64 -i $(secret_toml))" >> ./testconfig/override/.env - @echo "export TEST_BASE64_CCIP_SECRETS_CONFIG=$$(base64 -i $(secret_toml))" >> ./testconfig/override/.env - @echo "BASE64_CCIP_SECRETS_CONFIG=$$(base64 -i $(secret_toml))" > ./testconfig/override/debug.env - @echo "TEST_BASE64_CCIP_SECRETS_CONFIG=$$(base64 -i $(secret_toml))" >> ./testconfig/override/debug.env + @echo "Checking for test secrets file in ~/.testsecrets..."; + @if [ ! -f ~/.testsecrets ]; then \ + echo "WARNING: ~/.testsecrets file not found. No test secrets will be set. To set test secrets, refer to ./testconfig/examples/.testsecrets.example for the list of secrets and instruction how to set them up."; \ + else \ + echo "Test secrets will be loaded from ~/.testsecrets file."; \ + fi -# example usage: make test_load_ccip testimage=chainlink-ccip-tests:latest testname=TestLoadCCIPStableRPS override_toml=./testconfig/override/config.toml secret_toml=./testconfig/tomls/secrets.toml network_config_toml=../config/network.toml +# example usage: make test_load_ccip testimage=chainlink-ccip-tests:latest testname=TestLoadCCIPStableRPS override_toml=./testconfig/override/config.toml network_config_toml=../config/network.toml .PHONY: test_load_ccip test_load_ccip: set_config source ./testconfig/override/.env && \ @@ -36,7 +39,7 @@ test_load_ccip: set_config go test -timeout 24h -count=1 -v -run ^$(testname)$$ ./load -# example usage: make test_smoke_ccip testimage=chainlink-ccip-tests:latest testname=TestSmokeCCIPForBidirectionalLane override_toml=../testconfig/override/config.toml secret_toml=./testconfig/tomls/secrets.toml network_config_toml=../config/network.toml +# example usage: make test_smoke_ccip testimage=chainlink-ccip-tests:latest testname=TestSmokeCCIPForBidirectionalLane override_toml=../testconfig/override/config.toml network_config_toml=../config/network.toml .PHONY: test_smoke_ccip test_smoke_ccip: set_config source ./testconfig/override/.env && \ @@ -48,7 +51,7 @@ test_smoke_ccip: set_config go test -timeout 24h -count=1 -v -run ^$(testname)$$ ./smoke # run ccip smoke tests with default config; explicitly sets the override config to empty -# example usage: make test_smoke_ccip_default testname=TestSmokeCCIPForBidirectionalLane secret_toml=./testconfig/tomls/secrets.toml +# example usage: make test_smoke_ccip_default testname=TestSmokeCCIPForBidirectionalLane .PHONY: test_smoke_ccip_default test_smoke_ccip_default: set_config source ./testconfig/override/.env && \ diff --git a/integration-tests/ccip-tests/README.md b/integration-tests/ccip-tests/README.md index 0e000561fa..39b8360428 100644 --- a/integration-tests/ccip-tests/README.md +++ b/integration-tests/ccip-tests/README.md @@ -34,39 +34,12 @@ For example, if you want to override the `Network` input in test and want to run export BASE64_CCIP_CONFIG_OVERRIDE=$(base64 -i ./testconfig/override/mainnet.toml) ``` -3. Secrets - You also need to set some secrets. This is a mandatory step needed to run the tests. Please refer to [sample-secrets.toml](./testconfig/examples/secrets.toml.example) for the list of secrets that are mandatory to run the tests. - - The chainlink image and tag are required secrets for all the tests. +3. Secrets - You also need to set some secrets. This is a mandatory step needed to run the tests. Please refer to [.testsecrets.example](./examples/.testsecrets.example) for the list of secrets and instruction how to set them up. + - The chainlink image is a required secret for all tests - If you are running tests in live networks like testnet and mainnet, you need to set the secrets (rpc urls and private keys) for the respective networks. - - If you are running tests in simulated networks no network specific secrets are required. - here is a sample secrets.toml file, for running the tests in simulated networks, with the chainlink image and tag set as secrets: - - ```toml - [CCIP] - [CCIP.Env] - # ChainlinkImage is mandatory for all tests. - [CCIP.Env.NewCLCluster] - [CCIP.Env.NewCLCluster.Common] - [CCIP.Env.NewCLCluster.Common.ChainlinkImage] - image = "chainlink-ccip" - version = "latest" - ``` - - We consider secrets similar to test input overrides and encode them using `base64` command. - Once you have the secrets.toml file, you can encode it using `base64` command (similar to step 2) and set the env var `BASE64_CCIP_SECRETS_CONFIG` with the encoded content. - - ```bash - export BASE64_CCIP_SECRETS_CONFIG=$(base64 -i ./testconfig/tomls/secrets.toml) - ``` **Please note that the secrets should NOT be checked in to the repo and should be kept locally.** -We recommend against changing the content of [sample-secrets.toml](./testconfig/examples/secrets.toml.example). Please create a new file and set it as the secrets file. -You can run the command to ignore the changes to the file. - -```bash -git update-index --skip-worktree -``` - ## Running the Tests There are two ways to run the tests: diff --git a/integration-tests/ccip-tests/testconfig/README.md b/integration-tests/ccip-tests/testconfig/README.md index c32aee3d91..e22a5e4d59 100644 --- a/integration-tests/ccip-tests/testconfig/README.md +++ b/integration-tests/ccip-tests/testconfig/README.md @@ -1,21 +1,23 @@ # CCIP Configuration -The CCIP configuration is used to specify the test configuration for running the CCIP integration tests. +The CCIP configuration is used to specify the test configuration for running the CCIP integration tests. The configuration is specified in a TOML file. The configuration is used to specify the test environment, test type, test parameters, and other necessary details for running the tests. The test config is read in following order: -- The test reads the default configuration from [ccip-default.toml](./tomls/ccip-default.toml). -- The default can be overridden by specifying the test config in a separate file. - - The file content needs to be encoded in base64 format and set in `BASE64_CCIP_CONFIG_OVERRIDE` environment variable. + +- The test reads the default configuration from [ccip-default.toml](./tomls/ccip-default.toml). +- The default can be overridden by specifying the test config in a separate file. + - The file content needs to be encoded in base64 format and set in `BASE64_CCIP_CONFIG_OVERRIDE` environment variable. - The config mentioned in this file will override the default config. - Example override file - [override.toml.example](./examples/override.toml.example) -- If there are sensitive details like private keys, credentials in test config, they can be specified in a separate secret file. - - The file content needs to be encoded in base64 format and set in `BASE64_CCIP_SECRETS_CONFIG` environment variable. - - The config mentioned in this file will override the default and override config. - - Example secret file - [secrets.toml.example](./examples/secrets.toml.example) +- If there are sensitive details like private keys, credentials in test config, they can be specified in a separate dotenv file as env vars + - The `~/.testsecrets` file in home directory is automatically loaded and should have all test secrets as env vars + - Example secret file - [.testsecrets.example](./examples/.testsecrets.example) ## CCIP.ContractVersions + Specifies contract versions of different contracts to be referred by test. Supported versions are: + - **PriceRegistry**: '1.2.0', 'Latest' - **OffRamp**: '1.2.0', 'Latest' - **OnRamp**: '1.2.0', 'Latest' @@ -23,6 +25,7 @@ Supported versions are: - **CommitStore**: '1.2.0', 'Latest' Example Usage: + ```toml [CCIP.ContractVersions] PriceRegistry = "1.2.0" @@ -33,14 +36,17 @@ CommitStore = "1.2.0" ``` ## CCIP.Deployments -CCIP Deployment contains all necessary contract addresses for various networks. This is mandatory if the test are to be run for [existing deployments](#ccipgroupstestgroupexistingdeployment) + +CCIP Deployment contains all necessary contract addresses for various networks. This is mandatory if the test are to be run for [existing deployments](#ccipgroupstestgroupexistingdeployment) The deployment data can be specified - - - Under `CCIP.Deployments.Data` field with value as stringify format of json. - - Under `CCIP.Deployments.DataFile` field with value as the path of the file containing the deployment data in json format. + +- Under `CCIP.Deployments.Data` field with value as stringify format of json. +- Under `CCIP.Deployments.DataFile` field with value as the path of the file containing the deployment data in json format. The json schema is specified in https://github.com/smartcontractkit/ccip/blob/ccip-develop/integration-tests/ccip-tests/contracts/laneconfig/parse_contracts.go#L96 Example Usage: + ```toml [CCIP.Deployments] Data = """ @@ -96,32 +102,39 @@ Data = """ } """ ``` -Or + +Or, + ```toml [CCIP.Deployments] DataFile = '' ``` ## CCIP.Env + Specifies the environment details for the test to be run on. Mandatory fields are: + - **Networks**: [CCIP.Env.Networks](#ccipenvnetworks) - **NewCLCluster**: [CCIP.Env.NewCLCluster](#ccipenvnewclcluster) - This is mandatory if the test needs to deploy Chainlink nodes. - **ExistingCLCluster**: [CCIP.Env.ExistingCLCluster](#ccipenvexistingclcluster) - This is mandatory if the test needs to run on existing Chainlink nodes to deploy ccip jobs. Test needs network/chain details to be set through configuration. This configuration is mandatory for running the tests. you have option to set the network details in two ways: -1. Using [CCIP.Env.Networks](#ccipenvnetworks) + +1. Using [CCIP.Env.Networks](#ccipenvnetworks) 2. Using a separate network config file - - * refer to the example - [network_config.toml.example](./examples/network_config.toml.example) - * once all necessary values are set, encode the toml file content in base64 format, - * set the base64'ed string content in `BASE64_NETWORK_CONFIG` environment variable. + - refer to the example - [network_config.toml.example](./examples/network_config.toml.example) + - once all necessary values are set, encode the toml file content in base64 format, + - set the base64'ed string content in `BASE64_NETWORK_CONFIG` environment variable. ### CCIP.Env.Networks + Specifies the network details for the test to be run. The NetworkConfig is imported from https://github.com/smartcontractkit/chainlink-testing-framework/blob/main/config/network.go#L39 #### CCIP.Env.Networks.selected_networks + It denotes the network names in which tests will be run. These networks are used to deploy ccip contracts and set up lanes between them. If more than 2 networks are specified, then lanes will be set up between all possible pairs of networks. @@ -132,6 +145,7 @@ The name of the networks are taken from [known_networks](https://github.com/smar If the network is not present in known_networks, then the network details can be specified in the config file itself under the following `EVMNetworks` key. #### CCIP.Env.Network.EVMNetworks + Specifies the network config to be used while creating blockchain EVMClient for test. It is a map of network name to EVMNetworks where key is network name specified under `CCIP.Env.Networks.selected_networks` and value is `EVMNetwork`. The EVMNetwork is imported from [EVMNetwork](https://github.com/smartcontractkit/chainlink-testing-framework/blob/main/blockchain/config.go#L43) in chainlink-testing-framework. @@ -139,21 +153,24 @@ The EVMNetwork is imported from [EVMNetwork](https://github.com/smartcontractkit If `CCIP.Env.Network.EVMNetworks` config is not set for a network name specified under `CCIP.Env.Networks.selected_networks`, test will try to find the corresponding network config from defined networks in `MappedNetworks` under [known_networks.go](https://github.com/smartcontractkit/chainlink-testing-framework/blob/main/networks/known_networks.go) #### CCIP.Env.Network.AnvilConfigs -If the test needs to run on chains created using Anvil, then the AnvilConfigs can be specified. -It is a map of network name to `AnvilConfig` where key is network name specified under `CCIP.Env.Networks.selected_networks` and value is `AnvilConfig`. -The AnvilConfig is imported from [AnvilConfig](https://github.com/smartcontractkit/chainlink-testing-framework/blob/main/config/network.go#L20) in chainlink-testing-framework. +If the test needs to run on chains created using Anvil, then the AnvilConfigs can be specified. +It is a map of network name to `AnvilConfig` where key is network name specified under `CCIP.Env.Networks.selected_networks` and value is `AnvilConfig`. +The AnvilConfig is imported from [AnvilConfig](https://github.com/smartcontractkit/chainlink-testing-framework/blob/main/config/network.go#L20) in chainlink-testing-framework. **The following network configs are required for tests running on live networks. It can be ignored if the tests are running on simulated networks.** Refer to [secrets.toml.example](./examples/secrets.toml.example) for details. #### CCIP.ENV.Network.RpcHttpUrls + RpcHttpUrls is the RPC HTTP endpoints for each network, key is the network name as declared in selected_networks slice. #### CCIP.ENV.Network.RpcWsUrls + RpcWsUrls is the RPC WS endpoints for each network, key is the network name as declared in selected_networks slice. #### CCIP.ENV.Network.WalletKeys + WalletKeys is the private keys for each network, key is the network name as declared in selected_networks slice. Example Usage of Network Config: @@ -202,69 +219,95 @@ block_time = 1 ``` ### CCIP.Env.NewCLCluster -The NewCLCluster config holds the overall deployment configuration for Chainlink nodes. + +The NewCLCluster config holds the overall deployment configuration for Chainlink nodes. #### CCIP.Env.NewCLCluster.NoOfNodes + Specifies the number of Chainlink nodes to be deployed. #### CCIP.Env.NewCLCluster.Common + Specifies the common configuration for all Chainlink nodes if they share the same configuration. -##### Name: + +##### Name + Name of the node. -##### NeedsUpgrade: + +##### NeedsUpgrade + Indicates if the node needs an upgrade during test. -##### ChainlinkImage: + +##### ChainlinkImage + Configuration for the Chainlink image. -##### ChainlinkUpgradeImage: +##### ChainlinkUpgradeImage + Configuration for the Chainlink upgrade image. It is used when the node needs an upgrade. -##### BaseConfigTOML: +##### BaseConfigTOML + String containing the base configuration toml content for the Chainlink node config. -##### CommonChainConfigTOML: +##### CommonChainConfigTOML + String containing the common chain configuration toml content for all EVMNodes in chainlink node config. -##### ChainConfigTOMLByChain: +##### ChainConfigTOMLByChain + String containing the chain-specific configuration toml content for individual EVMNodes in chainlink node config. This is keyed by chain ID. -##### DBImage: +##### DBImage + Database image for the Chainlink node. -##### DBTag: +##### DBTag + Database tag/version for the Chainlink node. #### CCIP.Env.NewCLCluster.Nodes + Specifies the configuration for individual nodes if they differ from the common configuration. The fields are the same as the common configuration. #### CCIP.Env.NewCLCluster.NodeMemory + Specifies the memory to be allocated for each Chainlink node. This is valid only if the deployment is on Kubernetes. #### CCIP.Env.NewCLCluster.NodeCPU + Specifies the CPU to be allocated for each Chainlink node. This is valid only if the deployment is on Kubernetes. #### CCIP.Env.NewCLCluster.DBMemory + Specifies the memory to be allocated for the database. This is valid only if the deployment is on Kubernetes. #### CCIP.Env.NewCLCluster.DBCPU + Specifies the CPU to be allocated for the database. This is valid only if the deployment is on Kubernetes. #### CCIP.Env.NewCLCluster.IsStateful + Specifies whether the deployment is StatefulSet on Kubernetes. #### CCIP.Env.NewCLCluster.DBStorageClass + Specifies the storage class for the database. This is valid only if the deployment is StatefulSet on Kubernetes. #### CCIP.Env.NewCLCluster.DBCapacity + Specifies the capacity of the database. This is valid only if the deployment is StatefulSet on Kubernetes. #### CCIP.Env.NewCLCluster.PromPgExporter + Specifies whether to enable Prometheus PostgreSQL exporter. This is valid only if the deployment is on Kubernetes. #### CCIP.Env.NewCLCluster.DBArgs + Specifies the arguments to be passed to the database. This is valid only if the deployment is on Kubernetes. Example Usage: + ```toml [CCIP.Env.NewCLCluster] NoOfNodes = 17 @@ -294,29 +337,42 @@ FeeCapDefault = '200 gwei' ``` ### CCIP.Env.ExistingCLCluster -The ExistingCLCluster config holds the overall connection configuration for existing Chainlink nodes. -It is needed when the tests are to be run on Chainlink nodes already deployed on some environment. -If this is specified, test will not need to connect to k8 namespace using [CCIP.Env.EnvToConnect](#ccipenvenvtoconnect) . + +The ExistingCLCluster config holds the overall connection configuration for existing Chainlink nodes. +It is needed when the tests are to be run on Chainlink nodes already deployed on some environment. +If this is specified, test will not need to connect to k8 namespace using [CCIP.Env.EnvToConnect](#ccipenvenvtoconnect). Test can directly connect to the existing Chainlink nodes using node credentials without knowing the k8 namespace details. #### CCIP.Env.ExistingCLCluster.Name + Specifies the name of the existing Chainlink cluster. This is used to identify the cluster in the test. #### CCIP.Env.ExistingCLCluster.NoOfNodes + Specifies the number of Chainlink nodes in the existing cluster. #### CCIP.Env.ExistingCLCluster.NodeConfigs + Specifies the configuration for individual nodes in the existing cluster. Each node config contains the following fields to connect to the Chainlink node: + ##### CCIP.Env.ExistingCLCluster.NodeConfigs.URL + The URL of the Chainlink node. -##### CCIP.Env.ExistingCLCluster.NodeConfigs.Email + +##### CCIP.Env.ExistingCLCluster.NodeConfigs.Email + The username/email of the Chainlink node credential. + ##### CCIP.Env.ExistingCLCluster.NodeConfigs.Password + The password of the Chainlink node credential. + ##### CCIP.Env.ExistingCLCluster.NodeConfigs.InternalIP + The internal IP of the Chainlink node. Example Usage: + ```toml [CCIP.Env.ExistingCLCluster] Name = 'crib-sample' @@ -355,23 +411,30 @@ InternalIP = 'app-node-5' ``` ### CCIP.Env.EnvToConnect + This is specified when the test needs to connect to already existing k8s namespace. User needs to have access to the k8 namespace to run the tests through specific kubeconfig file. Example usage: + ```toml [CCIP.Env] EnvToConnect="load-ccip-c8972" ``` + ### CCIP.ENV.TTL + Specifies the time to live for the k8 namespace. This is used to terminate the namespace after the tests are run. This is only valid if the tests are run on k8s. Example usage: + ```toml [CCIP.Env] TTL = "11h" ``` ### CCIP.Env.Logging + Specifies the logging configuration for the test. Imported from [LoggingConfig](https://github.com/smartcontractkit/chainlink-testing-framework/blob/main/config/logging.go#L11) in chainlink-testing-framework. Example usage: + ```toml [CCIP.Env.Logging] test_log_collect = false # if set to true will save logs even if test did not fail @@ -394,53 +457,67 @@ dashboard_url = "/d/6vjVx-1V8/ccip-long-running-tests" ``` ### CCIP.Env.Lane.LeaderLaneEnabled + Specifies whether to enable the leader lane feature. This setting is only applicable for new deployments. ## CCIP.Groups + Specifies the test config specific to each test type. Available test types are: + - **CCIP.Groups.load** - **CCIP.Groups.smoke** - **CCIP.Groups.chaos** ### CCIP.Groups.[testgroup].KeepEnvAlive + Specifies whether to keep the k8 namespace alive after the test is run. This is only valid if the tests are run on k8s. ### CCIP.Groups.[testgroup].BiDirectionalLane -Specifies whether to set up bi-directional lanes between networks. + +Specifies whether to set up bi-directional lanes between networks. ### CCIP.Groups.[testgroup].CommitAndExecuteOnSameDON + Specifies whether commit and execution jobs are to be run on the same Chainlink node. ### CCIP.Groups.[testgroup].NoOfCommitNodes + Specifies the number of nodes on which commit jobs are to be run. This needs to be lesser than the total number of nodes mentioned in [CCIP.Env.NewCLCluster.NoOfNodes](#ccipenvnewclclusternoofnodes) or [CCIP.Env.ExistingCLCluster.NoOfNodes](#ccipenvexistingclclusternoofnodes). If the value of total nodes is `n`, then the max value of NoOfCommitNodes should be less than `n-1`. As the first node is used for bootstrap job. If the NoOfCommitNodes is lesser than `n-1`, then the remaining nodes are used for execution jobs if `CCIP.Groups.[testgroup].CommitAndExecuteOnSameDON` is set to false. ### CCIP.Groups.[testgroup].TokenConfig + Specifies the token configuration for the test. The token configuration is used to set up tokens and token pools for all chains. #### CCIP.Groups.[testgroup].TokenConfig.NoOfTokensPerChain + Specifies the number of tokens to be set up for each chain. #### CCIP.Groups.[testgroup].TokenConfig.WithPipeline -Specifies whether to set up token pipelines in commit jobspec. If set to false, the token prices will be set with DynamicPriceGetterConfig. + +Specifies whether to set up token pipelines in commit jobspec. If set to false, the token prices will be set with DynamicPriceGetterConfig. #### CCIP.Groups.[testgroup].TokenConfig.TimeoutForPriceUpdate -Specifies the timeout to wait for token and gas price updates to be available in price registry for each chain. + +Specifies the timeout to wait for token and gas price updates to be available in price registry for each chain. #### CCIP.Groups.[testgroup].TokenConfig.NoOfTokensWithDynamicPrice + Specifies the number of tokens to be set up with dynamic price update. The rest of the tokens will be set up with static price. This is only valid if [WithPipeline](#ccipgroupstestgrouptokenconfigwithpipeline) is set to false. #### CCIP.Groups.[testgroup].TokenConfig.DynamicPriceUpdateInterval + Specifies the interval for dynamic price update for tokens. This is only valid if [NoOfTokensWithDynamicPrice](#ccipgroupstestgrouptokenconfignooftokenswithdynamicprice) is set to value greater tha zero. #### CCIP.Groups.[testgroup].TokenConfig.CCIPOwnerTokens + Specifies the tokens to be owned by the CCIP owner. If this is false, the tokens and pools will be owned by an address other than rest of CCIP contract admin addresses. This is applicable only if the contract versions are '1.5' or higher. Example Usage: -```toml +```toml [CCIP.Groups.load.TokenConfig] TimeoutForPriceUpdate = '15m' NoOfTokensPerChain = 60 @@ -450,27 +527,36 @@ CCIPOwnerTokens = true ``` ### CCIP.Groups.[testgroup].MsgDetails -Specifies the ccip message details to be sent by the test. + +Specifies the ccip message details to be sent by the test. + #### CCIP.Groups.[testgroup].MsgDetails.MsgType + Specifies the type of message to be sent. The supported message types are: + - **Token** - **Data** - **DataWithToken** #### CCIP.Groups.[testgroup].MsgDetails.DestGasLimit + Specifies the gas limit for the destination chain. This is used to in `ExtraArgs` field of CCIPMessage. Change this to 0, if you are doing ccip-send to an EOA in the destination chain. #### CCIP.Groups.[testgroup].MsgDetails.DataLength + Specifies the length of data to be sent in the message. This is only valid if [MsgType](#ccipgroupstestgroupmsgdetailsmsgtype) is set to 'Data' or 'DataWithToken'. #### CCIP.Groups.[testgroup].MsgDetails.NoOfTokens + Specifies the number of tokens to be sent in the message. This is only valid if [MsgType](#ccipgroupstestgroupmsgdetailsmsgtype) is set to 'Token' or 'DataWithToken'. It needs to be less than or equal to [NoOfTokensPerChain](#ccipgroupstestgrouptokenconfignooftokensperchain) specified in the test config. #### CCIP.Groups.[testgroup].MsgDetails.TokenAmount + Specifies the amount for each token to be sent in the message. This is only valid if [MsgType](#ccipgroupstestgroupmsgdetailsmsgtype) is set to 'Token' or 'DataWithToken'. Example Usage: + ```toml [CCIP.Groups.smoke.MsgDetails] MsgType = 'DataWithToken' @@ -481,15 +567,19 @@ AmountPerToken = 1 ``` ### CCIP.Groups.[testgroup].MulticallInOneTx + Specifies whether to send multiple ccip messages in a single transaction. ### CCIP.Groups.[testgroup].NoOfSendsInMulticall + Specifies the number of ccip messages to be sent in a single transaction. This is only valid if [MulticallInOneTx](#ccipgroupstestgroupmulticallinonetx) is set to true. ### CCIP.Groups.[testgroup].PhaseTimeout + The test validates various events in a ccip request lifecycle, like commit, execute, etc. This field specifies the timeout for each phase in the lifecycle. The timeout is calculated from the time the previous phase event is received. The following contract events are validated: + - **CCIPSendRequested on OnRamp** - **CCIPSendRequested event log to be Finalized** - **ReportAccepted on CommitStore** @@ -497,13 +587,16 @@ The following contract events are validated: - **ExecutionStateChanged on OffRamp** ### CCIP.Groups.[testgroup].LocalCluster + Specifies whether the test is to be run on a local docker. If set to true, the test environment will be set up on a local docker. ### CCIP.Groups.[testgroup].ExistingDeployment + Specifies whether the test is to be run on existing deployments. If set to true, the test will use the deployment data specified in [CCIP.Deployments](#ccipdeployments) for interacting with the ccip contracts. If the deployment data does not contain the required contract addresses, the test will fail. ### CCIP.Groups.[testgroup].ReuseContracts + Test loads contract/lane config from [contracts.json](../contracts/laneconfig/contracts.json) if no lane config is specified in [CCIP.Deployments](#ccipdeployments) If a certain contract is present in the contracts.json, the test will use the contract address from the contracts.json. This field specifies whether to reuse the contracts from [contracts.json](../contracts/laneconfig/contracts.json) @@ -511,58 +604,74 @@ For example if the contracts.json contains the contract address for PriceRegistr If `ReuseContracts` is set to false, the test will redeploy the contract instead of using the contract address from contracts.json. ### CCIP.Groups.[testgroup].NodeFunding + Specified the native token funding for each Chainlink node. It assumes that the native token decimals is 18. The funding is done by the private key specified in [CCIP.Env.Networks](#ccipenvnetworks) for each network. The funding is done only if the test is run on local docker or k8s. This is not applicable for [existing deployments](#ccipgroupstestgroupexistingdeployment) is set to true. ### CCIP.Groups.[testgroup].NetworkPairs -Specifies the network pairs for which the test is to be run. The test will set up lanes only between the specified network pairs. + +Specifies the network pairs for which the test is to be run. The test will set up lanes only between the specified network pairs. If the network pairs are not specified, the test will set up lanes between all possible pairs of networks mentioned in selected_networks in [CCIP.Env.Networks](#ccipenvnetworksselectednetworks) ### CCIP.Groups.[testgroup].NoOfNetworks -Specifies the number of networks to be used for the test. -If the number of networks is greater than the total number of networks specified in [CCIP.Env.Networks.selected_networks](#ccipenvnetworksselectednetworks) : + +Specifies the number of networks to be used for the test. +If the number of networks is greater than the total number of networks specified in [CCIP.Env.Networks.selected_networks](#ccipenvnetworksselectednetworks): + - the test will fail if the networks are live networks. - the test will create equal number of replicas of the first network with a new chain id if the networks are simulated networks. For example, if the `selected_networks` is ['SIMULATED_1','SIMULATED_2'] and `NoOfNetworks` is 3, the test will create 1 more network config by copying the network config of `SIMULATED_1` with a different chain id and use that as 3rd network. ### CCIP.Groups.[testgroup].NoOfRoutersPerPair + Specifies the number of routers to be set up for each network. ### CCIP.Groups.[testgroup].MaxNoOfLanes + Specifies the maximum number of lanes to be set up between networks. If this values is not set, the test will set up lanes between all possible pairs of networks mentioned in `selected_networks` in [CCIP.Env.Networks](#ccipenvnetworksselectednetworks). For example, if `selected_networks = ['SIMULATED_1', 'SIMULATED_2', 'SIMULATED_3']`, and `MaxNoOfLanes` is set to 2, it denotes that the test will randomly select the 2 lanes between all possible pairs `SIMULATED_1`, `SIMULATED_2`, and `SIMULATED_3` for the test run. ### CCIP.Groups.[testgroup].DenselyConnectedNetworkChainIds -This is applicable only if [MaxNoOfLanes](#ccipgroupstestgroupmaxnooflanes) is specified. + +This is applicable only if [MaxNoOfLanes](#ccipgroupstestgroupmaxnooflanes) is specified. Specifies the chain ids for networks to be densely connected. If this is provided the test will include all possible pairs of networks mentioned in `DenselyConnectedNetworkChainIds`. The rest of the networks will be connected randomly based on the value of `MaxNoOfLanes`. ### CCIP.Groups.[testgroup].ChaosDuration + Specifies the duration for which the chaos experiment is to be run. This is only valid if the test type is 'chaos'. ### CCIP.Groups.[testgroup].USDCMockDeployment + Specifies whether to deploy USDC mock contract for the test. This is only valid if the test is not run on [existing deployments](#ccipgroupstestgroupexistingdeployment). The following fields are used for various parameters in OCR2 commit and execution jobspecs. All of these are only valid if the test is not run on [existing deployments](#ccipgroupstestgroupexistingdeployment). + ### CCIP.Groups.[testgroup].CommitOCRParams + Specifies the OCR parameters for the commit job. This is only valid if the test is not run on [existing deployments](#ccipgroupstestgroupexistingdeployment). ### CCIP.Groups.[testgroup].ExecuteOCRParams + Specifies the OCR parameters for the execute job. This is only valid if the test is not run on [existing deployments](#ccipgroupstestgroupexistingdeployment). ### CCIP.Groups.[testgroup].CommitInflightExpiry + Specifies the value for the `InflightExpiry` in commit job's offchain config. This is only valid if the test is not run on [existing deployments](#ccipgroupstestgroupexistingdeployment). ### CCIP.Groups.[testgroup].OffRampConfig + Specifies the offramp configuration for the execution job. This is only valid if the test is not run on [existing deployments](#ccipgroupstestgroupexistingdeployment). This is used to set values for following fields in execution jobspec's offchain and onchain config: + - **OffRampConfig.MaxDataBytes** - **OffRampConfig.BatchGasLimit** - **OffRampConfig.InflightExpiry** - **OffRampConfig.RootSnooze** Example Usage: + ```toml [CCIP.Groups.load] CommitInflightExpiry = '5m' @@ -594,43 +703,53 @@ BatchGasLimit = 11000000 MaxDataBytes = 1000 InflightExpiry = '5m' RootSnooze = '5m' - ``` ### CCIP.Groups.[testgroup].StoreLaneConfig + This is only valid if the tests are run on remote runners in k8s. If set to true, the test will store the lane config in the remote runner. ### CCIP.Groups.[testgroup].LoadProfile -Specifies the load profile for the test. Only valid if the testgroup is 'load'. + +Specifies the load profile for the test. Only valid if the testgroup is 'load'. ### CCIP.Groups.[testgroup].LoadProfile.LoadFrequency.[DestNetworkName] #### CCIP.Groups.[testgroup].LoadProfile.RequestPerUnitTime + Specifies the number of requests to be sent per unit time. This is applicable to all networks if [LoadFrequency](#ccipgroupstestgrouploadprofileloadfrequencydestnetworkname) is not specified for a destination network. #### CCIP.Groups.[testgroup].LoadProfile.TimeUnit + Specifies the unit of time for the load profile. This is applicable to all networks if [LoadFrequency](#ccipgroupstestgrouploadprofileloadfrequencydestnetworkname) is not specified for a destination network. #### CCIP.Groups.[testgroup].LoadProfile.StepDuration + Specifies the duration for each step in the load profile. This is applicable to all networks if [LoadFrequency](#ccipgroupstestgrouploadprofileloadfrequencydestnetworkname) is not specified for a destination network. #### CCIP.Groups.[testgroup].LoadProfile.TestDuration + Specifies the total duration for the load test. #### CCIP.Groups.[testgroup].LoadProfile.NetworkChaosDelay + Specifies the duration network delay used for `NetworkChaos` experiment. This is only valid if the test is run on k8s and not on [existing deployments](#ccipgroupstestgroupexistingdeployment). #### CCIP.Groups.[testgroup].LoadProfile.WaitBetweenChaosDuringLoad + If there are multiple chaos experiments, this specifies the duration to wait between each chaos experiment. This is only valid if the test is run on k8s and not on [existing deployments](#ccipgroupstestgroupexistingdeployment). #### CCIP.Groups.[testgroup].LoadProfile.SkipRequestIfAnotherRequestTriggeredWithin + If a request is triggered within this duration, the test will skip sending another request during load run. For Example, if `SkipRequestIfAnotherRequestTriggeredWithin` is set to `40m`, and a request is triggered at 0th second, the test will skip sending another request for another 40m. This particular field is used to avoid sending multiple requests in a short duration during load run. #### CCIP.Groups.[testgroup].LoadProfile.OptimizeSpace -This is used internally to optimize memory usage during load run. If set to true, after the initial lane set up is over the test will discard the lane config to save memory. -The test will only store contract addresses strictly necessary to trigger/validate ccip-send requests. + +This is used internally to optimize memory usage during load run. If set to true, after the initial lane set up is over the test will discard the lane config to save memory. +The test will only store contract addresses strictly necessary to trigger/validate ccip-send requests. Except for following contracts all other contract addresses will be discarded after the initial lane set up - + - Router - ARM - CommitStore @@ -638,37 +757,45 @@ Except for following contracts all other contract addresses will be discarded af - OnRamp #### CCIP.Groups.[testgroup].LoadProfile.FailOnFirstErrorInLoad + If set to true, the test will fail on the first error encountered during load run. If set to false, the test will continue to run even if there are errors during load run. #### CCIP.Groups.[testgroup].LoadProfile.SendMaxDataInEveryMsgCount -Specifies the number of requests to send with maximum data in every mentioned count iteration. + +Specifies the number of requests to send with maximum data in every mentioned count iteration. For example, if `SendMaxDataInEveryMsgCount` is set to 5, the test will send ccip message with max allowable data length(as set in onRamp config) in every 5th request. #### CCIP.Groups.[testgroup].LoadProfile.TestRunName + Specifies the name of the test run. This is used to identify the test run in CCIP test dashboard or logs. If multiple tests are run with same `TestRunName`, the test results will be aggregated under the same test run in grafana dashboard. This is used when multiple iterations of tests are run against same release version to aggregate the results under same dashboard view. #### CCIP.Groups.[testgroup].LoadProfile.MsgProfile + Specifies the message profile for the test. The message profile is used to set up multiple ccip message details during load test. ##### CCIP.Groups.[testgroup].LoadProfile.MsgProfile.Frequencies -Specifies the frequency of each message profile. + +Specifies the frequency of each message profile. For example, if `Frequencies` is set to [1, 2, 3], the test will send 1st message profile 1 time, 2nd message profile 2 times, and 3rd message profile 3 times in each iteration. Each iteration will be defined by (1+2+3) = 6 requests. Example Breakdown: + - Frequencies = [4, 12, 3, 1] - Total Sum of Frequencies = 4 + 12 + 3 + 1 = 20 - Percentages: - - Message Type 1: (4 / 20) * 100% = 20% - - Message Type 2: (12 / 20) * 100% = 60% - - Message Type 3: (3 / 20) * 100% = 15% - - Message Type 4: (1 / 20) * 100% = 5% + - Message Type 1: (4 / 20) * 100% = 20% + - Message Type 2: (12 / 20) * 100% = 60% + - Message Type 3: (3 / 20) * 100% = 15% + - Message Type 4: (1 / 20) * 100% = 5% These percentages reflect how often each message type should appear in the total set of messages. Please note - if the total set of messages is not equal to the multiple of sum of frequencies, the percentages will not be accurate. ##### CCIP.Groups.[testgroup].LoadProfile.MsgProfile.MsgDetails + Specifies the message details for each message profile. The fields are the same as [CCIP.Groups.[testgroup].MsgDetails](#ccipgroupstestgroupmsgdetails). example usage: + ```toml # to represent 20%, 60%, 15%, 5% of the total messages [CCIP.Groups.load.LoadProfile.MsgProfile] @@ -697,4 +824,4 @@ DataLength = 10000 MsgType = 'Data' DestGasLimit = 2500000 DataLength = 10000 -``` \ No newline at end of file +``` diff --git a/integration-tests/ccip-tests/testconfig/ccip.go b/integration-tests/ccip-tests/testconfig/ccip.go index 60d7055cb3..7d9419828e 100644 --- a/integration-tests/ccip-tests/testconfig/ccip.go +++ b/integration-tests/ccip-tests/testconfig/ccip.go @@ -387,6 +387,18 @@ type CCIP struct { Groups map[string]*CCIPTestGroupConfig `toml:",omitempty"` } +// LoadFromEnv loads selected env vars into the CCIP config +func (c *CCIP) LoadFromEnv() error { + if c.Env == nil { + c.Env = &Common{} + } + err := c.Env.ReadFromEnvVar() + if err != nil { + return err + } + return nil +} + func (c *CCIP) Validate() error { if c.Env != nil { err := c.Env.Validate() diff --git a/integration-tests/ccip-tests/testconfig/examples/.testsecrets.example b/integration-tests/ccip-tests/testconfig/examples/.testsecrets.example new file mode 100644 index 0000000000..e69ef9e854 --- /dev/null +++ b/integration-tests/ccip-tests/testconfig/examples/.testsecrets.example @@ -0,0 +1,39 @@ +# DO NOT UPDATE THIS FILE WITH ANY SECRET VALUES. +# This file serves as a template for the actual ~/.testsecrets file. Follow these steps to use it: +# 1. Create a copy of this template in your home directory under ~/.testsecrets +# 2. Update ~/.testsecrets with actual secret values required for your tests. The file will be automatically loaded by the test framework +# 3. Only include secrets necessary for the tests you are running. For example, if you are only running tests on Ethereum Mainnet, you do not need secrets for Base Mainnet. Comment other env vars. +# DO NOT COMMIT THE ACTUAL SECRETS FILE TO THE REPOSITORY. + +# Chainlink image used for NewCLCluster +E2E_TEST_CHAINLINK_IMAGE="***.dkr.ecr.***.amazonaws.com/chainlink-ccip" + +# Chainlink upgrade image for NewCLCluster. Used only for upgrade tests +E2E_TEST_CHAINLINK_UPGRADE_IMAGE="***.dkr.ecr.***.amazonaws.com/chainlink-ccip" + +# Ethereum network secrets +E2E_TEST_ETHEREUM_MAINNET_WALLET_KEY="" +E2E_TEST_ETHEREUM_MAINNET_RPC_HTTP_URL="" +E2E_TEST_ETHEREUM_MAINNET_RPC_HTTP_URL_1="" +E2E_TEST_ETHEREUM_MAINNET_RPC_WS_URL="" +E2E_TEST_ETHEREUM_MAINNET_RPC_WS_URL_1="" + +# Base network secrets +E2E_TEST_BASE_MAINNET_WALLET_KEY="" +E2E_TEST_BASE_MAINNET_RPC_HTTP_URL="" +E2E_TEST_BASE_MAINNET_RPC_HTTP_URL_1="" +E2E_TEST_BASE_MAINNET_RPC_WS_URL="" +E2E_TEST_BASE_MAINNET_RPC_WS_URL_1="" + +# Other networks secrets (pattern for envs) +# E2E_TEST_(.+)_WALLET_KEY_(\d+)="" +# E2E_TEST_(.+)_RPC_HTTP_URL_(\d+)="" +# E2E_TEST_(.+)_RPC_WS_URL_(\d+)="" + +# Loki secrets +E2E_TEST_LOKI_TENANT_ID="" +E2E_TEST_LOKI_ENDPOINT="" + +# Grafana secrets +E2E_TEST_GRAFANA_BASE_URL="" +E2E_TEST_GRAFANA_DASHBOARD_URL="/d/6vjVx-1V8/ccip-long-running-tests" diff --git a/integration-tests/ccip-tests/testconfig/examples/secrets.toml.example b/integration-tests/ccip-tests/testconfig/examples/secrets.toml.example deleted file mode 100644 index 3045f51759..0000000000 --- a/integration-tests/ccip-tests/testconfig/examples/secrets.toml.example +++ /dev/null @@ -1,52 +0,0 @@ -# This file contains all secret parameters for ccip tests. -# DO NOT UPDATE THIS FILE WITH ANY SECRET VALUES. -# Use this file as a template for the actual secret file and update all the parameter values accordingly. -# DO NOT COMMIT THE ACTUAL SECRET FILE TO THE REPOSITORY. -[CCIP] -[CCIP.Env] - -# ChainlinkImage is mandatory for all tests. -[CCIP.Env.NewCLCluster] -[CCIP.Env.NewCLCluster.Common] -[CCIP.Env.NewCLCluster.Common.ChainlinkImage] -image = "chainlink-ccip" -version = "latest" - -# Chainlink upgrade image is used only for upgrade tests -#[CCIP.Env.NewCLCluster.Common.ChainlinkUpgradeImage] -#image = "***.dkr.ecr.***.amazonaws.com/chainlink-ccip" -#version = "****" - - -# Networks configuration with rpc urls and wallet keys are mandatory only for tests running on live networks -# The following example is for 3 networks: Ethereum, Base and Arbitrum -# Network configuration can be ignored for tests running on simulated/private networks -[CCIP.Env.Network] -selected_networks= [ - 'ETHEREUM_MAINNET','BASE_MAINNET', 'ARBITRUM_MAINNET', -] - -[CCIP.Env.Network.RpcHttpUrls] -ETHEREUM_MAINNET = ['', ''] -BASE_MAINNET = ['', ''] -ARBITRUM_MAINNET = ['', ''] - -[CCIP.Env.Network.RpcWsUrls] -ETHEREUM_MAINNET = ['', ''] -BASE_MAINNET = ['', ''] -ARBITRUM_MAINNET = ['', ''] - -[CCIP.Env.Network.WalletKeys] -ETHEREUM_MAINNET = [''] -BASE_MAINNET = [''] -ARBITRUM_MAINNET = [''] - -# Used for tests using 1. loki logging for test results. -# Mandatory for load tests -[CCIP.Env.Logging.Loki] -tenant_id="" -endpoint="" - -[CCIP.Env.Logging.Grafana] -base_url="" -dashboard_url="/d/6vjVx-1V8/ccip-long-running-tests" diff --git a/integration-tests/ccip-tests/testconfig/global.go b/integration-tests/ccip-tests/testconfig/global.go index 331737c5fb..a1658a4841 100644 --- a/integration-tests/ccip-tests/testconfig/global.go +++ b/integration-tests/ccip-tests/testconfig/global.go @@ -15,6 +15,7 @@ import ( "github.com/smartcontractkit/seth" "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env" + "github.com/smartcontractkit/chainlink-testing-framework/logging" "github.com/smartcontractkit/chainlink-testing-framework/networks" "github.com/smartcontractkit/chainlink-testing-framework/blockchain" @@ -29,7 +30,6 @@ import ( const ( OVERIDECONFIG = "BASE64_CCIP_CONFIG_OVERRIDE" - SECRETSCONFIG = "BASE64_CCIP_SECRETS_CONFIG" ErrReadConfig = "failed to read TOML config" ErrUnmarshalConfig = "failed to unmarshal TOML config" Load string = "load" @@ -105,52 +105,46 @@ func EncodeConfigAndSetEnv(c any, envVar string) (string, error) { func NewConfig() (*Config, error) { cfg := &Config{} var override *Config - var secrets *Config + // var secrets *Config // load config from default file err := config.DecodeTOML(bytes.NewReader(DefaultConfig), cfg) if err != nil { return nil, errors.Wrap(err, ErrReadConfig) } - // load config from env var if specified - rawConfig, _ := osutil.GetEnv(OVERIDECONFIG) - if rawConfig != "" { - err = DecodeConfig(rawConfig, &override) - if err != nil { - return nil, fmt.Errorf("failed to decode override config: %w", err) - } - } - if override != nil { - // apply overrides for all products - if override.CCIP != nil { - if cfg.CCIP == nil { - cfg.CCIP = override.CCIP - } else { - err = cfg.CCIP.ApplyOverrides(override.CCIP) - if err != nil { - return nil, err + // load config overrides from env var if specified + // there can be multiple overrides separated by comma + rawConfigs, _ := osutil.GetEnv(OVERIDECONFIG) + if rawConfigs != "" { + for _, rawConfig := range strings.Split(rawConfigs, ",") { + err = DecodeConfig(rawConfig, &override) + if err != nil { + return nil, fmt.Errorf("failed to decode override config: %w", err) + } + if override != nil { + // apply overrides for all products + if override.CCIP != nil { + if cfg.CCIP == nil { + cfg.CCIP = override.CCIP + } else { + err = cfg.CCIP.ApplyOverrides(override.CCIP) + if err != nil { + return nil, err + } + } } } } } // read secrets for all products if cfg.CCIP != nil { - // load config from env var if specified for secrets - secretRawConfig, _ := osutil.GetEnv(SECRETSCONFIG) - if secretRawConfig != "" { - err = DecodeConfig(secretRawConfig, &secrets) - if err != nil { - return nil, fmt.Errorf("failed to decode secrets config: %w", err) - } - if secrets != nil { - // apply secrets for all products - if secrets.CCIP != nil { - err = cfg.CCIP.ApplyOverrides(secrets.CCIP) - if err != nil { - return nil, fmt.Errorf("failed to apply secrets: %w", err) - } - } - } + err := ctfconfig.LoadSecretEnvsFromFiles() + if err != nil { + return nil, errors.Wrap(err, "error loading testsecrets files") + } + err = cfg.CCIP.LoadFromEnv() + if err != nil { + return nil, errors.Wrap(err, "error loading env vars into CCIP config") } // validate all products err = cfg.CCIP.Validate() @@ -176,6 +170,156 @@ type Common struct { Logging *ctfconfig.LoggingConfig `toml:",omitempty"` } +// ReadFromEnvVar loads selected env vars into the config +func (p *Common) ReadFromEnvVar() error { + logger := logging.GetTestLogger(nil) + + lokiTenantID := ctfconfig.MustReadEnvVar_String(ctfconfig.E2E_TEST_LOKI_TENANT_ID_ENV) + if lokiTenantID != "" { + if p.Logging == nil { + p.Logging = &ctfconfig.LoggingConfig{} + } + if p.Logging.Loki == nil { + p.Logging.Loki = &ctfconfig.LokiConfig{} + } + logger.Debug().Msgf("Using %s env var to override Logging.Loki.TenantId", ctfconfig.E2E_TEST_LOKI_TENANT_ID_ENV) + p.Logging.Loki.TenantId = &lokiTenantID + } + + lokiEndpoint := ctfconfig.MustReadEnvVar_String(ctfconfig.E2E_TEST_LOKI_ENDPOINT_ENV) + if lokiEndpoint != "" { + if p.Logging == nil { + p.Logging = &ctfconfig.LoggingConfig{} + } + if p.Logging.Loki == nil { + p.Logging.Loki = &ctfconfig.LokiConfig{} + } + logger.Debug().Msgf("Using %s env var to override Logging.Loki.Endpoint", ctfconfig.E2E_TEST_LOKI_ENDPOINT_ENV) + p.Logging.Loki.Endpoint = &lokiEndpoint + } + + lokiBasicAuth := ctfconfig.MustReadEnvVar_String(ctfconfig.E2E_TEST_LOKI_BASIC_AUTH_ENV) + if lokiBasicAuth != "" { + if p.Logging == nil { + p.Logging = &ctfconfig.LoggingConfig{} + } + if p.Logging.Loki == nil { + p.Logging.Loki = &ctfconfig.LokiConfig{} + } + logger.Debug().Msgf("Using %s env var to override Logging.Loki.BasicAuth", ctfconfig.E2E_TEST_LOKI_BASIC_AUTH_ENV) + p.Logging.Loki.BasicAuth = &lokiBasicAuth + } + + lokiBearerToken := ctfconfig.MustReadEnvVar_String(ctfconfig.E2E_TEST_LOKI_BEARER_TOKEN_ENV) + if lokiBearerToken != "" { + if p.Logging == nil { + p.Logging = &ctfconfig.LoggingConfig{} + } + if p.Logging.Loki == nil { + p.Logging.Loki = &ctfconfig.LokiConfig{} + } + logger.Debug().Msgf("Using %s env var to override Logging.Loki.BearerToken", ctfconfig.E2E_TEST_LOKI_BEARER_TOKEN_ENV) + p.Logging.Loki.BearerToken = &lokiBearerToken + } + + grafanaBaseUrl := ctfconfig.MustReadEnvVar_String(ctfconfig.E2E_TEST_GRAFANA_BASE_URL_ENV) + if grafanaBaseUrl != "" { + if p.Logging == nil { + p.Logging = &ctfconfig.LoggingConfig{} + } + if p.Logging.Grafana == nil { + p.Logging.Grafana = &ctfconfig.GrafanaConfig{} + } + logger.Debug().Msgf("Using %s env var to override Logging.Grafana.BaseUrl", ctfconfig.E2E_TEST_GRAFANA_BASE_URL_ENV) + p.Logging.Grafana.BaseUrl = &grafanaBaseUrl + } + + grafanaDashboardUrl := ctfconfig.MustReadEnvVar_String(ctfconfig.E2E_TEST_GRAFANA_DASHBOARD_URL_ENV) + if grafanaDashboardUrl != "" { + if p.Logging == nil { + p.Logging = &ctfconfig.LoggingConfig{} + } + if p.Logging.Grafana == nil { + p.Logging.Grafana = &ctfconfig.GrafanaConfig{} + } + logger.Debug().Msgf("Using %s env var to override Logging.Grafana.DashboardUrl", ctfconfig.E2E_TEST_GRAFANA_DASHBOARD_URL_ENV) + p.Logging.Grafana.DashboardUrl = &grafanaDashboardUrl + } + + grafanaBearerToken := ctfconfig.MustReadEnvVar_String(ctfconfig.E2E_TEST_GRAFANA_BEARER_TOKEN_ENV) + if grafanaBearerToken != "" { + if p.Logging == nil { + p.Logging = &ctfconfig.LoggingConfig{} + } + if p.Logging.Grafana == nil { + p.Logging.Grafana = &ctfconfig.GrafanaConfig{} + } + logger.Debug().Msgf("Using %s env var to override Logging.Grafana.BearerToken", ctfconfig.E2E_TEST_GRAFANA_BEARER_TOKEN_ENV) + p.Logging.Grafana.BearerToken = &grafanaBearerToken + } + + walletKeys := ctfconfig.ReadEnvVarGroupedMap(ctfconfig.E2E_TEST_WALLET_KEY_ENV, ctfconfig.E2E_TEST_WALLET_KEYS_ENV) + if len(walletKeys) > 0 { + if p.Network == nil { + p.Network = &ctfconfig.NetworkConfig{} + } + logger.Debug().Msgf("Using %s and/or %s env vars to override Network.WalletKeys", ctfconfig.E2E_TEST_WALLET_KEY_ENV, ctfconfig.E2E_TEST_WALLET_KEYS_ENV) + p.Network.WalletKeys = walletKeys + } + + rpcHttpUrls := ctfconfig.ReadEnvVarGroupedMap(ctfconfig.E2E_TEST_RPC_HTTP_URL_ENV, ctfconfig.E2E_TEST_RPC_HTTP_URLS_ENV) + if len(rpcHttpUrls) > 0 { + if p.Network == nil { + p.Network = &ctfconfig.NetworkConfig{} + } + logger.Debug().Msgf("Using %s and/or %s env vars to override Network.RpcHttpUrls", ctfconfig.E2E_TEST_RPC_HTTP_URL_ENV, ctfconfig.E2E_TEST_RPC_HTTP_URLS_ENV) + p.Network.RpcHttpUrls = rpcHttpUrls + } + + rpcWsUrls := ctfconfig.ReadEnvVarGroupedMap(ctfconfig.E2E_TEST_RPC_WS_URL_ENV, ctfconfig.E2E_TEST_RPC_WS_URLS_ENV) + if len(rpcWsUrls) > 0 { + if p.Network == nil { + p.Network = &ctfconfig.NetworkConfig{} + } + logger.Debug().Msgf("Using %s and/or %s env vars to override Network.RpcWsUrls", ctfconfig.E2E_TEST_RPC_WS_URL_ENV, ctfconfig.E2E_TEST_RPC_WS_URLS_ENV) + p.Network.RpcWsUrls = rpcWsUrls + } + + chainlinkImage := ctfconfig.MustReadEnvVar_String(ctfconfig.E2E_TEST_CHAINLINK_IMAGE_ENV) + if chainlinkImage != "" { + if p.NewCLCluster == nil { + p.NewCLCluster = &ChainlinkDeployment{} + } + if p.NewCLCluster.Common == nil { + p.NewCLCluster.Common = &Node{} + } + if p.NewCLCluster.Common.ChainlinkImage == nil { + p.NewCLCluster.Common.ChainlinkImage = &ctfconfig.ChainlinkImageConfig{} + } + + logger.Debug().Msgf("Using %s env var to override NewCLCluster.Common.ChainlinkImage.Image", ctfconfig.E2E_TEST_CHAINLINK_IMAGE_ENV) + p.NewCLCluster.Common.ChainlinkImage.Image = &chainlinkImage + } + + chainlinkUpgradeImage := ctfconfig.MustReadEnvVar_String(ctfconfig.E2E_TEST_CHAINLINK_UPGRADE_IMAGE_ENV) + if chainlinkUpgradeImage != "" { + if p.NewCLCluster == nil { + p.NewCLCluster = &ChainlinkDeployment{} + } + if p.NewCLCluster.Common == nil { + p.NewCLCluster.Common = &Node{} + } + if p.NewCLCluster.Common.ChainlinkUpgradeImage == nil { + p.NewCLCluster.Common.ChainlinkUpgradeImage = &ctfconfig.ChainlinkImageConfig{} + } + + logger.Debug().Msgf("Using %s env var to override NewCLCluster.Common.ChainlinkUpgradeImage.Image", ctfconfig.E2E_TEST_CHAINLINK_UPGRADE_IMAGE_ENV) + p.NewCLCluster.Common.ChainlinkUpgradeImage.Image = &chainlinkUpgradeImage + } + + return nil +} + func (p *Common) GetNodeConfig() *ctfconfig.NodeConfig { return &ctfconfig.NodeConfig{ BaseConfigTOML: p.NewCLCluster.Common.BaseConfigTOML, diff --git a/integration-tests/go.mod b/integration-tests/go.mod index e20e98bcf9..f63a30fa31 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -258,7 +258,7 @@ require ( github.com/grafana/loki v1.6.2-0.20231215164305-b51b7d7b5503 // indirect github.com/grafana/loki/pkg/push v0.0.0-20231201111602-11ef833ed3e4 // indirect github.com/grafana/pyroscope-go v1.1.1 // indirect - github.com/grafana/pyroscope-go/godeltaprof v0.1.6 // indirect + github.com/grafana/pyroscope-go/godeltaprof v0.1.8 // indirect github.com/grafana/regexp v0.0.0-20221122212121-6b5c0a4cb7fd // indirect github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect @@ -314,7 +314,7 @@ require ( github.com/json-iterator/go v1.1.12 // indirect github.com/julienschmidt/httprouter v1.3.0 // indirect github.com/kelseyhightower/envconfig v1.4.0 // indirect - github.com/klauspost/compress v1.17.7 // indirect + github.com/klauspost/compress v1.17.8 // indirect github.com/klauspost/cpuid/v2 v2.2.5 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect diff --git a/integration-tests/go.sum b/integration-tests/go.sum index 5789a6ccc2..a573b2c41f 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -806,8 +806,8 @@ github.com/grafana/loki/pkg/push v0.0.0-20231201111602-11ef833ed3e4 h1:wQ0FnSeeb github.com/grafana/loki/pkg/push v0.0.0-20231201111602-11ef833ed3e4/go.mod h1:f3JSoxBTPXX5ec4FxxeC19nTBSxoTz+cBgS3cYLMcr0= github.com/grafana/pyroscope-go v1.1.1 h1:PQoUU9oWtO3ve/fgIiklYuGilvsm8qaGhlY4Vw6MAcQ= github.com/grafana/pyroscope-go v1.1.1/go.mod h1:Mw26jU7jsL/KStNSGGuuVYdUq7Qghem5P8aXYXSXG88= -github.com/grafana/pyroscope-go/godeltaprof v0.1.6 h1:nEdZ8louGAplSvIJi1HVp7kWvFvdiiYg3COLlTwJiFo= -github.com/grafana/pyroscope-go/godeltaprof v0.1.6/go.mod h1:Tk376Nbldo4Cha9RgiU7ik8WKFkNpfds98aUzS8omLE= +github.com/grafana/pyroscope-go/godeltaprof v0.1.8 h1:iwOtYXeeVSAeYefJNaxDytgjKtUuKQbJqgAIjlnicKg= +github.com/grafana/pyroscope-go/godeltaprof v0.1.8/go.mod h1:2+l7K7twW49Ct4wFluZD3tZ6e0SjanjcUUBPVD/UuGU= github.com/grafana/regexp v0.0.0-20221122212121-6b5c0a4cb7fd h1:PpuIBO5P3e9hpqBD0O/HjhShYuM6XE0i/lbE6J94kww= github.com/grafana/regexp v0.0.0-20221122212121-6b5c0a4cb7fd/go.mod h1:M5qHK+eWfAv8VR/265dIuEpL3fNfeC21tXXp9itM24A= github.com/graph-gophers/dataloader v5.0.0+incompatible h1:R+yjsbrNq1Mo3aPG+Z/EKYrXrXXUNJHOgbRt+U6jOug= @@ -1034,9 +1034,8 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o github.com/klauspost/compress v1.11.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= -github.com/klauspost/compress v1.17.3/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= -github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= -github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/klauspost/compress v1.17.8 h1:YcnTYrq7MikUT7k0Yb5eceMmALQPYBW/Xltxn0NAMnU= +github.com/klauspost/compress v1.17.8/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg= github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index ef077ba768..95d92451e0 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -234,7 +234,7 @@ require ( github.com/grafana/loki v1.6.2-0.20231215164305-b51b7d7b5503 // indirect github.com/grafana/loki/pkg/push v0.0.0-20231201111602-11ef833ed3e4 // indirect github.com/grafana/pyroscope-go v1.1.1 // indirect - github.com/grafana/pyroscope-go/godeltaprof v0.1.6 // indirect + github.com/grafana/pyroscope-go/godeltaprof v0.1.8 // indirect github.com/grafana/regexp v0.0.0-20221122212121-6b5c0a4cb7fd // indirect github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect @@ -291,7 +291,7 @@ require ( github.com/json-iterator/go v1.1.12 // indirect github.com/julienschmidt/httprouter v1.3.0 // indirect github.com/kelseyhightower/envconfig v1.4.0 // indirect - github.com/klauspost/compress v1.17.7 // indirect + github.com/klauspost/compress v1.17.8 // indirect github.com/klauspost/cpuid/v2 v2.2.5 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index 3e5d20d303..7ec40db665 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -780,8 +780,8 @@ github.com/grafana/loki/pkg/push v0.0.0-20231201111602-11ef833ed3e4 h1:wQ0FnSeeb github.com/grafana/loki/pkg/push v0.0.0-20231201111602-11ef833ed3e4/go.mod h1:f3JSoxBTPXX5ec4FxxeC19nTBSxoTz+cBgS3cYLMcr0= github.com/grafana/pyroscope-go v1.1.1 h1:PQoUU9oWtO3ve/fgIiklYuGilvsm8qaGhlY4Vw6MAcQ= github.com/grafana/pyroscope-go v1.1.1/go.mod h1:Mw26jU7jsL/KStNSGGuuVYdUq7Qghem5P8aXYXSXG88= -github.com/grafana/pyroscope-go/godeltaprof v0.1.6 h1:nEdZ8louGAplSvIJi1HVp7kWvFvdiiYg3COLlTwJiFo= -github.com/grafana/pyroscope-go/godeltaprof v0.1.6/go.mod h1:Tk376Nbldo4Cha9RgiU7ik8WKFkNpfds98aUzS8omLE= +github.com/grafana/pyroscope-go/godeltaprof v0.1.8 h1:iwOtYXeeVSAeYefJNaxDytgjKtUuKQbJqgAIjlnicKg= +github.com/grafana/pyroscope-go/godeltaprof v0.1.8/go.mod h1:2+l7K7twW49Ct4wFluZD3tZ6e0SjanjcUUBPVD/UuGU= github.com/grafana/regexp v0.0.0-20221122212121-6b5c0a4cb7fd h1:PpuIBO5P3e9hpqBD0O/HjhShYuM6XE0i/lbE6J94kww= github.com/grafana/regexp v0.0.0-20221122212121-6b5c0a4cb7fd/go.mod h1:M5qHK+eWfAv8VR/265dIuEpL3fNfeC21tXXp9itM24A= github.com/graph-gophers/dataloader v5.0.0+incompatible h1:R+yjsbrNq1Mo3aPG+Z/EKYrXrXXUNJHOgbRt+U6jOug= @@ -1006,9 +1006,8 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o github.com/klauspost/compress v1.11.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= -github.com/klauspost/compress v1.17.3/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= -github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= -github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/klauspost/compress v1.17.8 h1:YcnTYrq7MikUT7k0Yb5eceMmALQPYBW/Xltxn0NAMnU= +github.com/klauspost/compress v1.17.8/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg= github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= From 1659b9551af6f7643f7d6ab2582d182113aca8ef Mon Sep 17 00:00:00 2001 From: Makram Date: Wed, 28 Aug 2024 23:13:34 +0300 Subject: [PATCH 046/115] core/capabilities/ccip: fix oracle startup logic (#1348) Ticket: https://smartcontract-it.atlassian.net/browse/CCIP-3078 We can't start bootstrap oracles and plugin oracles on the same chainlink node. The main reason for this is that we have a singleton `SingletonPeerWrapper` object which manages all libocr peers for the application as a whole. Since this singleton only works with a single peer ID, it creates a single OCR peer, and all streams are created using this OCR peer. Since streams must have unique config digests for the same peer object, running a bootstrap oracle and a plugin oracle for the same config digest will fail because the stream will not be created. In order to remedy this we match what will be the case in production, which is: * Separate bootstrap node, with a peer ID that is either part of the OCR committee or not (most likely the latter, in order to avoid exporting / importing the P2P key from one node's DB to another). This bootstrap node will have to have a DNS name and be publicly accessible over the internet in order to be accessed by all nodes in the committee, at least initially, to facilitate peer discovery. * Plugin node that is more locked down, i.e no public DNS name required. To enable this, in this PR we: * Tweak the `launcher` component to launch bootstrap nodes only or plugin nodes only, and not both. This does NOT rely on the on-chain bootstrap P2P IDs that are set in the OCR config. This field will be removed in subsequent PRs. * Tweak the `OracleCreator` interface to support the above operation Follow ups: * Remove the `bootstrapP2PIds` field from the OCR config in CCIPConfig.sol --- core/capabilities/ccip/delegate.go | 48 +- core/capabilities/ccip/launcher/bluegreen.go | 54 +-- .../ccip/launcher/bluegreen_test.go | 428 ++---------------- core/capabilities/ccip/launcher/diff.go | 13 - core/capabilities/ccip/launcher/diff_test.go | 9 - .../ccip/launcher/integration_test.go | 18 +- core/capabilities/ccip/launcher/launcher.go | 65 +-- .../ccip/launcher/launcher_test.go | 278 ++++++------ .../ccip/oraclecreator/bootstrap.go | 97 ++++ .../ccip/oraclecreator/inprocess_test.go | 239 ---------- .../oraclecreator/{inprocess.go => plugin.go} | 305 +++++++------ .../ccip/types/mocks/oracle_creator.go | 74 ++- core/capabilities/ccip/types/types.go | 18 +- core/capabilities/ccip/validate/validate.go | 3 - integration-tests/deployment/ccip/jobs.go | 11 +- .../deployment/memory/environment.go | 19 +- 16 files changed, 550 insertions(+), 1129 deletions(-) create mode 100644 core/capabilities/ccip/oraclecreator/bootstrap.go delete mode 100644 core/capabilities/ccip/oraclecreator/inprocess_test.go rename core/capabilities/ccip/oraclecreator/{inprocess.go => plugin.go} (79%) diff --git a/core/capabilities/ccip/delegate.go b/core/capabilities/ccip/delegate.go index ef3822c4de..2a39334549 100644 --- a/core/capabilities/ccip/delegate.go +++ b/core/capabilities/ccip/delegate.go @@ -18,6 +18,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink-common/pkg/types/query/primitives" + cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" "github.com/smartcontractkit/chainlink/v2/core/config" kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" @@ -134,21 +135,36 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, spec job.Job) (services ccipConfigBinding, ) - oracleCreator := oraclecreator.New( - ocrKeys, - transmitterKeys, - d.chains, - d.peerWrapper, - spec.ExternalJobID, - spec.ID, - d.isNewlyCreatedJob, - spec.CCIPSpec.PluginConfig, - ocrDB, - d.lggr, - d.monitoringEndpointGen, - bootstrapperLocators, - hcr, - ) + // if bootstrappers are provided we assume that the node is a plugin oracle. + // the reason for this is that bootstrap oracles do not need to be aware + // of other bootstrap oracles. however, plugin oracles, at least initially, + // must be aware of available bootstrappers. + var oracleCreator cctypes.OracleCreator + if len(spec.CCIPSpec.P2PV2Bootstrappers) > 0 { + oracleCreator = oraclecreator.NewPluginOracleCreator( + ocrKeys, + transmitterKeys, + d.chains, + d.peerWrapper, + spec.ExternalJobID, + spec.ID, + d.isNewlyCreatedJob, + spec.CCIPSpec.PluginConfig, + ocrDB, + d.lggr, + d.monitoringEndpointGen, + bootstrapperLocators, + hcr, + ) + } else { + oracleCreator = oraclecreator.NewBootstrapOracleCreator( + d.peerWrapper, + bootstrapperLocators, + ocrDB, + d.monitoringEndpointGen, + d.lggr, + ) + } capLauncher := launcher.New( spec.CCIPSpec.CapabilityVersion, @@ -156,8 +172,8 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, spec job.Job) (services ragep2ptypes.PeerID(p2pID.PeerID()), d.lggr, hcr, - oracleCreator, 12*time.Second, + oracleCreator, ) // register the capability launcher with the registry syncer diff --git a/core/capabilities/ccip/launcher/bluegreen.go b/core/capabilities/ccip/launcher/bluegreen.go index 6245846629..c15f8c038f 100644 --- a/core/capabilities/ccip/launcher/bluegreen.go +++ b/core/capabilities/ccip/launcher/bluegreen.go @@ -16,21 +16,11 @@ type blueGreenDeployment struct { // blue must always be present. blue cctypes.CCIPOracle - // bootstrapBlue is the bootstrap node of the blue OCR instance. - // Only a subset of the DON will be running bootstrap instances, - // so this may be nil. - bootstrapBlue cctypes.CCIPOracle - // green is the green OCR instance. // green may or may not be present. // green must never be present if blue is not present. // TODO: should we enforce this invariant somehow? green cctypes.CCIPOracle - - // bootstrapGreen is the bootstrap node of the green OCR instance. - // Only a subset of the DON will be running bootstrap instances, - // so this may be nil, even when green is not nil. - bootstrapGreen cctypes.CCIPOracle } // ccipDeployment represents blue-green deployments of both commit and exec @@ -44,33 +34,21 @@ type ccipDeployment struct { func (c *ccipDeployment) Close() error { var err error - // shutdown blue commit instances. + // shutdown blue commit instance. err = multierr.Append(err, c.commit.blue.Close()) - if c.commit.bootstrapBlue != nil { - err = multierr.Append(err, c.commit.bootstrapBlue.Close()) - } - // shutdown green commit instances. + // shutdown green commit instance. if c.commit.green != nil { err = multierr.Append(err, c.commit.green.Close()) } - if c.commit.bootstrapGreen != nil { - err = multierr.Append(err, c.commit.bootstrapGreen.Close()) - } - // shutdown blue exec instances. + // shutdown blue exec instance. err = multierr.Append(err, c.exec.blue.Close()) - if c.exec.bootstrapBlue != nil { - err = multierr.Append(err, c.exec.bootstrapBlue.Close()) - } - // shutdown green exec instances. + // shutdown green exec instance. if c.exec.green != nil { err = multierr.Append(err, c.exec.green.Close()) } - if c.exec.bootstrapGreen != nil { - err = multierr.Append(err, c.exec.bootstrapGreen.Close()) - } return err } @@ -80,13 +58,7 @@ func (c *ccipDeployment) StartBlue() error { var err error err = multierr.Append(err, c.commit.blue.Start()) - if c.commit.bootstrapBlue != nil { - err = multierr.Append(err, c.commit.bootstrapBlue.Start()) - } err = multierr.Append(err, c.exec.blue.Start()) - if c.exec.bootstrapBlue != nil { - err = multierr.Append(err, c.exec.bootstrapBlue.Start()) - } return err } @@ -96,13 +68,7 @@ func (c *ccipDeployment) CloseBlue() error { var err error err = multierr.Append(err, c.commit.blue.Close()) - if c.commit.bootstrapBlue != nil { - err = multierr.Append(err, c.commit.bootstrapBlue.Close()) - } err = multierr.Append(err, c.exec.blue.Close()) - if c.exec.bootstrapBlue != nil { - err = multierr.Append(err, c.exec.bootstrapBlue.Close()) - } return err } @@ -127,28 +93,16 @@ func (c *ccipDeployment) HandleBlueGreen(prevDeployment *ccipDeployment) error { var err error if prevDeployment.commit.green != nil && c.commit.green == nil { err = multierr.Append(err, prevDeployment.commit.blue.Close()) - if prevDeployment.commit.bootstrapBlue != nil { - err = multierr.Append(err, prevDeployment.commit.bootstrapBlue.Close()) - } } else if prevDeployment.commit.green == nil && c.commit.green != nil { err = multierr.Append(err, c.commit.green.Start()) - if c.commit.bootstrapGreen != nil { - err = multierr.Append(err, c.commit.bootstrapGreen.Start()) - } } else { return fmt.Errorf("invalid blue-green deployment transition") } if prevDeployment.exec.green != nil && c.exec.green == nil { err = multierr.Append(err, prevDeployment.exec.blue.Close()) - if prevDeployment.exec.bootstrapBlue != nil { - err = multierr.Append(err, prevDeployment.exec.bootstrapBlue.Close()) - } } else if prevDeployment.exec.green == nil && c.exec.green != nil { err = multierr.Append(err, c.exec.green.Start()) - if c.exec.bootstrapGreen != nil { - err = multierr.Append(err, c.exec.bootstrapGreen.Start()) - } } else { return fmt.Errorf("invalid blue-green deployment transition") } diff --git a/core/capabilities/ccip/launcher/bluegreen_test.go b/core/capabilities/ccip/launcher/bluegreen_test.go index 9fd71a0cb4..965491180e 100644 --- a/core/capabilities/ccip/launcher/bluegreen_test.go +++ b/core/capabilities/ccip/launcher/bluegreen_test.go @@ -14,14 +14,10 @@ import ( func Test_ccipDeployment_Close(t *testing.T) { type args struct { - commitBlue *mocktypes.CCIPOracle - commitBlueBootstrap *mocktypes.CCIPOracle - commitGreen *mocktypes.CCIPOracle - commitGreenBootstrap *mocktypes.CCIPOracle - execBlue *mocktypes.CCIPOracle - execBlueBootstrap *mocktypes.CCIPOracle - execGreen *mocktypes.CCIPOracle - execGreenBootstrap *mocktypes.CCIPOracle + commitBlue *mocktypes.CCIPOracle + commitGreen *mocktypes.CCIPOracle + execBlue *mocktypes.CCIPOracle + execGreen *mocktypes.CCIPOracle } tests := []struct { name string @@ -33,12 +29,10 @@ func Test_ccipDeployment_Close(t *testing.T) { { name: "no errors, blue only", args: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - commitGreen: nil, - commitGreenBootstrap: nil, - execBlue: mocktypes.NewCCIPOracle(t), - execGreen: nil, - execGreenBootstrap: nil, + commitBlue: mocktypes.NewCCIPOracle(t), + commitGreen: nil, + execBlue: mocktypes.NewCCIPOracle(t), + execGreen: nil, }, expect: func(t *testing.T, args args) { args.commitBlue.On("Close").Return(nil).Once() @@ -90,62 +84,6 @@ func Test_ccipDeployment_Close(t *testing.T) { }, wantErr: true, }, - { - name: "bootstrap blue also closed", - args: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - commitBlueBootstrap: mocktypes.NewCCIPOracle(t), - execBlue: mocktypes.NewCCIPOracle(t), - execBlueBootstrap: mocktypes.NewCCIPOracle(t), - }, - expect: func(t *testing.T, args args) { - args.commitBlue.On("Close").Return(nil).Once() - args.commitBlueBootstrap.On("Close").Return(nil).Once() - args.execBlue.On("Close").Return(nil).Once() - args.execBlueBootstrap.On("Close").Return(nil).Once() - }, - asserts: func(t *testing.T, args args) { - args.commitBlue.AssertExpectations(t) - args.commitBlueBootstrap.AssertExpectations(t) - args.execBlue.AssertExpectations(t) - args.execBlueBootstrap.AssertExpectations(t) - }, - wantErr: false, - }, - { - name: "bootstrap green also closed", - args: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - commitBlueBootstrap: mocktypes.NewCCIPOracle(t), - commitGreen: mocktypes.NewCCIPOracle(t), - commitGreenBootstrap: mocktypes.NewCCIPOracle(t), - execBlue: mocktypes.NewCCIPOracle(t), - execBlueBootstrap: mocktypes.NewCCIPOracle(t), - execGreen: mocktypes.NewCCIPOracle(t), - execGreenBootstrap: mocktypes.NewCCIPOracle(t), - }, - expect: func(t *testing.T, args args) { - args.commitBlue.On("Close").Return(nil).Once() - args.commitBlueBootstrap.On("Close").Return(nil).Once() - args.commitGreen.On("Close").Return(nil).Once() - args.commitGreenBootstrap.On("Close").Return(nil).Once() - args.execBlue.On("Close").Return(nil).Once() - args.execBlueBootstrap.On("Close").Return(nil).Once() - args.execGreen.On("Close").Return(nil).Once() - args.execGreenBootstrap.On("Close").Return(nil).Once() - }, - asserts: func(t *testing.T, args args) { - args.commitBlue.AssertExpectations(t) - args.commitBlueBootstrap.AssertExpectations(t) - args.commitGreen.AssertExpectations(t) - args.commitGreenBootstrap.AssertExpectations(t) - args.execBlue.AssertExpectations(t) - args.execBlueBootstrap.AssertExpectations(t) - args.execGreen.AssertExpectations(t) - args.execGreenBootstrap.AssertExpectations(t) - }, - wantErr: false, - }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -160,22 +98,10 @@ func Test_ccipDeployment_Close(t *testing.T) { if tt.args.commitGreen != nil { c.commit.green = tt.args.commitGreen } - if tt.args.commitBlueBootstrap != nil { - c.commit.bootstrapBlue = tt.args.commitBlueBootstrap - } - if tt.args.commitGreenBootstrap != nil { - c.commit.bootstrapGreen = tt.args.commitGreenBootstrap - } if tt.args.execGreen != nil { c.exec.green = tt.args.execGreen } - if tt.args.execBlueBootstrap != nil { - c.exec.bootstrapBlue = tt.args.execBlueBootstrap - } - if tt.args.execGreenBootstrap != nil { - c.exec.bootstrapGreen = tt.args.execGreenBootstrap - } tt.expect(t, tt.args) defer tt.asserts(t, tt.args) @@ -191,10 +117,8 @@ func Test_ccipDeployment_Close(t *testing.T) { func Test_ccipDeployment_StartBlue(t *testing.T) { type args struct { - commitBlue *mocktypes.CCIPOracle - commitBlueBootstrap *mocktypes.CCIPOracle - execBlue *mocktypes.CCIPOracle - execBlueBootstrap *mocktypes.CCIPOracle + commitBlue *mocktypes.CCIPOracle + execBlue *mocktypes.CCIPOracle } tests := []struct { name string @@ -204,12 +128,10 @@ func Test_ccipDeployment_StartBlue(t *testing.T) { wantErr bool }{ { - name: "no errors, no bootstrap", + name: "no errors", args: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - execBlue: mocktypes.NewCCIPOracle(t), - commitBlueBootstrap: nil, - execBlueBootstrap: nil, + commitBlue: mocktypes.NewCCIPOracle(t), + execBlue: mocktypes.NewCCIPOracle(t), }, expect: func(t *testing.T, args args) { args.commitBlue.On("Start").Return(nil).Once() @@ -221,35 +143,11 @@ func Test_ccipDeployment_StartBlue(t *testing.T) { }, wantErr: false, }, - { - name: "no errors, with bootstrap", - args: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - execBlue: mocktypes.NewCCIPOracle(t), - commitBlueBootstrap: mocktypes.NewCCIPOracle(t), - execBlueBootstrap: mocktypes.NewCCIPOracle(t), - }, - expect: func(t *testing.T, args args) { - args.commitBlue.On("Start").Return(nil).Once() - args.commitBlueBootstrap.On("Start").Return(nil).Once() - args.execBlue.On("Start").Return(nil).Once() - args.execBlueBootstrap.On("Start").Return(nil).Once() - }, - asserts: func(t *testing.T, args args) { - args.commitBlue.AssertExpectations(t) - args.commitBlueBootstrap.AssertExpectations(t) - args.execBlue.AssertExpectations(t) - args.execBlueBootstrap.AssertExpectations(t) - }, - wantErr: false, - }, { name: "error on commit blue", args: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - execBlue: mocktypes.NewCCIPOracle(t), - commitBlueBootstrap: nil, - execBlueBootstrap: nil, + commitBlue: mocktypes.NewCCIPOracle(t), + execBlue: mocktypes.NewCCIPOracle(t), }, expect: func(t *testing.T, args args) { args.commitBlue.On("Start").Return(errors.New("failed")).Once() @@ -264,10 +162,8 @@ func Test_ccipDeployment_StartBlue(t *testing.T) { { name: "error on exec blue", args: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - execBlue: mocktypes.NewCCIPOracle(t), - commitBlueBootstrap: nil, - execBlueBootstrap: nil, + commitBlue: mocktypes.NewCCIPOracle(t), + execBlue: mocktypes.NewCCIPOracle(t), }, expect: func(t *testing.T, args args) { args.commitBlue.On("Start").Return(nil).Once() @@ -279,46 +175,6 @@ func Test_ccipDeployment_StartBlue(t *testing.T) { }, wantErr: true, }, - { - name: "error on commit blue bootstrap", - args: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - execBlue: mocktypes.NewCCIPOracle(t), - commitBlueBootstrap: mocktypes.NewCCIPOracle(t), - execBlueBootstrap: nil, - }, - expect: func(t *testing.T, args args) { - args.commitBlue.On("Start").Return(nil).Once() - args.commitBlueBootstrap.On("Start").Return(errors.New("failed")).Once() - args.execBlue.On("Start").Return(nil).Once() - }, - asserts: func(t *testing.T, args args) { - args.commitBlue.AssertExpectations(t) - args.commitBlueBootstrap.AssertExpectations(t) - args.execBlue.AssertExpectations(t) - }, - wantErr: true, - }, - { - name: "error on exec blue bootstrap", - args: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - execBlue: mocktypes.NewCCIPOracle(t), - commitBlueBootstrap: nil, - execBlueBootstrap: mocktypes.NewCCIPOracle(t), - }, - expect: func(t *testing.T, args args) { - args.commitBlue.On("Start").Return(nil).Once() - args.execBlue.On("Start").Return(nil).Once() - args.execBlueBootstrap.On("Start").Return(errors.New("failed")).Once() - }, - asserts: func(t *testing.T, args args) { - args.commitBlue.AssertExpectations(t) - args.execBlue.AssertExpectations(t) - args.execBlueBootstrap.AssertExpectations(t) - }, - wantErr: true, - }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -330,12 +186,6 @@ func Test_ccipDeployment_StartBlue(t *testing.T) { blue: tt.args.execBlue, }, } - if tt.args.commitBlueBootstrap != nil { - c.commit.bootstrapBlue = tt.args.commitBlueBootstrap - } - if tt.args.execBlueBootstrap != nil { - c.exec.bootstrapBlue = tt.args.execBlueBootstrap - } tt.expect(t, tt.args) defer tt.asserts(t, tt.args) @@ -351,10 +201,8 @@ func Test_ccipDeployment_StartBlue(t *testing.T) { func Test_ccipDeployment_CloseBlue(t *testing.T) { type args struct { - commitBlue *mocktypes.CCIPOracle - commitBlueBootstrap *mocktypes.CCIPOracle - execBlue *mocktypes.CCIPOracle - execBlueBootstrap *mocktypes.CCIPOracle + commitBlue *mocktypes.CCIPOracle + execBlue *mocktypes.CCIPOracle } tests := []struct { name string @@ -364,12 +212,10 @@ func Test_ccipDeployment_CloseBlue(t *testing.T) { wantErr bool }{ { - name: "no errors, no bootstrap", + name: "no errors", args: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - execBlue: mocktypes.NewCCIPOracle(t), - commitBlueBootstrap: nil, - execBlueBootstrap: nil, + commitBlue: mocktypes.NewCCIPOracle(t), + execBlue: mocktypes.NewCCIPOracle(t), }, expect: func(t *testing.T, args args) { args.commitBlue.On("Close").Return(nil).Once() @@ -381,35 +227,11 @@ func Test_ccipDeployment_CloseBlue(t *testing.T) { }, wantErr: false, }, - { - name: "no errors, with bootstrap", - args: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - execBlue: mocktypes.NewCCIPOracle(t), - commitBlueBootstrap: mocktypes.NewCCIPOracle(t), - execBlueBootstrap: mocktypes.NewCCIPOracle(t), - }, - expect: func(t *testing.T, args args) { - args.commitBlue.On("Close").Return(nil).Once() - args.commitBlueBootstrap.On("Close").Return(nil).Once() - args.execBlue.On("Close").Return(nil).Once() - args.execBlueBootstrap.On("Close").Return(nil).Once() - }, - asserts: func(t *testing.T, args args) { - args.commitBlue.AssertExpectations(t) - args.commitBlueBootstrap.AssertExpectations(t) - args.execBlue.AssertExpectations(t) - args.execBlueBootstrap.AssertExpectations(t) - }, - wantErr: false, - }, { name: "error on commit blue", args: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - execBlue: mocktypes.NewCCIPOracle(t), - commitBlueBootstrap: nil, - execBlueBootstrap: nil, + commitBlue: mocktypes.NewCCIPOracle(t), + execBlue: mocktypes.NewCCIPOracle(t), }, expect: func(t *testing.T, args args) { args.commitBlue.On("Close").Return(errors.New("failed")).Once() @@ -424,10 +246,8 @@ func Test_ccipDeployment_CloseBlue(t *testing.T) { { name: "error on exec blue", args: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - execBlue: mocktypes.NewCCIPOracle(t), - commitBlueBootstrap: nil, - execBlueBootstrap: nil, + commitBlue: mocktypes.NewCCIPOracle(t), + execBlue: mocktypes.NewCCIPOracle(t), }, expect: func(t *testing.T, args args) { args.commitBlue.On("Close").Return(nil).Once() @@ -439,46 +259,6 @@ func Test_ccipDeployment_CloseBlue(t *testing.T) { }, wantErr: true, }, - { - name: "error on commit blue bootstrap", - args: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - execBlue: mocktypes.NewCCIPOracle(t), - commitBlueBootstrap: mocktypes.NewCCIPOracle(t), - execBlueBootstrap: nil, - }, - expect: func(t *testing.T, args args) { - args.commitBlue.On("Close").Return(nil).Once() - args.commitBlueBootstrap.On("Close").Return(errors.New("failed")).Once() - args.execBlue.On("Close").Return(nil).Once() - }, - asserts: func(t *testing.T, args args) { - args.commitBlue.AssertExpectations(t) - args.commitBlueBootstrap.AssertExpectations(t) - args.execBlue.AssertExpectations(t) - }, - wantErr: true, - }, - { - name: "error on exec blue bootstrap", - args: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - execBlue: mocktypes.NewCCIPOracle(t), - commitBlueBootstrap: nil, - execBlueBootstrap: mocktypes.NewCCIPOracle(t), - }, - expect: func(t *testing.T, args args) { - args.commitBlue.On("Close").Return(nil).Once() - args.execBlue.On("Close").Return(nil).Once() - args.execBlueBootstrap.On("Close").Return(errors.New("failed")).Once() - }, - asserts: func(t *testing.T, args args) { - args.commitBlue.AssertExpectations(t) - args.execBlue.AssertExpectations(t) - args.execBlueBootstrap.AssertExpectations(t) - }, - wantErr: true, - }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -490,12 +270,6 @@ func Test_ccipDeployment_CloseBlue(t *testing.T) { blue: tt.args.execBlue, }, } - if tt.args.commitBlueBootstrap != nil { - c.commit.bootstrapBlue = tt.args.commitBlueBootstrap - } - if tt.args.execBlueBootstrap != nil { - c.exec.bootstrapBlue = tt.args.execBlueBootstrap - } tt.expect(t, tt.args) defer tt.asserts(t, tt.args) @@ -515,14 +289,10 @@ func Test_ccipDeployment_HandleBlueGreen_PrevDeploymentNil(t *testing.T) { func Test_ccipDeployment_HandleBlueGreen(t *testing.T) { type args struct { - commitBlue *mocktypes.CCIPOracle - commitBlueBootstrap *mocktypes.CCIPOracle - commitGreen *mocktypes.CCIPOracle - commitGreenBootstrap *mocktypes.CCIPOracle - execBlue *mocktypes.CCIPOracle - execBlueBootstrap *mocktypes.CCIPOracle - execGreen *mocktypes.CCIPOracle - execGreenBootstrap *mocktypes.CCIPOracle + commitBlue *mocktypes.CCIPOracle + commitGreen *mocktypes.CCIPOracle + execBlue *mocktypes.CCIPOracle + execGreen *mocktypes.CCIPOracle } tests := []struct { name string @@ -533,7 +303,7 @@ func Test_ccipDeployment_HandleBlueGreen(t *testing.T) { wantErr bool }{ { - name: "promotion blue to green, no bootstrap", + name: "promotion blue to green", argsPrevDeployment: args{ commitBlue: mocktypes.NewCCIPOracle(t), commitGreen: mocktypes.NewCCIPOracle(t), @@ -557,43 +327,7 @@ func Test_ccipDeployment_HandleBlueGreen(t *testing.T) { wantErr: false, }, { - name: "promotion blue to green, with bootstrap", - argsPrevDeployment: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - commitBlueBootstrap: mocktypes.NewCCIPOracle(t), - commitGreen: mocktypes.NewCCIPOracle(t), - commitGreenBootstrap: mocktypes.NewCCIPOracle(t), - execBlue: mocktypes.NewCCIPOracle(t), - execBlueBootstrap: mocktypes.NewCCIPOracle(t), - execGreen: mocktypes.NewCCIPOracle(t), - execGreenBootstrap: mocktypes.NewCCIPOracle(t), - }, - argsFutureDeployment: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - commitBlueBootstrap: mocktypes.NewCCIPOracle(t), - commitGreen: nil, - commitGreenBootstrap: nil, - execBlue: mocktypes.NewCCIPOracle(t), - execBlueBootstrap: mocktypes.NewCCIPOracle(t), - execGreen: nil, - execGreenBootstrap: nil, - }, - expect: func(t *testing.T, args args, argsPrevDeployment args) { - argsPrevDeployment.commitBlue.On("Close").Return(nil).Once() - argsPrevDeployment.commitBlueBootstrap.On("Close").Return(nil).Once() - argsPrevDeployment.execBlue.On("Close").Return(nil).Once() - argsPrevDeployment.execBlueBootstrap.On("Close").Return(nil).Once() - }, - asserts: func(t *testing.T, args args, argsPrevDeployment args) { - argsPrevDeployment.commitBlue.AssertExpectations(t) - argsPrevDeployment.commitBlueBootstrap.AssertExpectations(t) - argsPrevDeployment.execBlue.AssertExpectations(t) - argsPrevDeployment.execBlueBootstrap.AssertExpectations(t) - }, - wantErr: false, - }, - { - name: "new green deployment, no bootstrap", + name: "new green deployment", argsPrevDeployment: args{ commitBlue: mocktypes.NewCCIPOracle(t), commitGreen: nil, @@ -616,42 +350,6 @@ func Test_ccipDeployment_HandleBlueGreen(t *testing.T) { }, wantErr: false, }, - { - name: "new green deployment, with bootstrap", - argsPrevDeployment: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - commitBlueBootstrap: mocktypes.NewCCIPOracle(t), - commitGreen: nil, - commitGreenBootstrap: nil, - execBlue: mocktypes.NewCCIPOracle(t), - execBlueBootstrap: mocktypes.NewCCIPOracle(t), - execGreen: nil, - execGreenBootstrap: nil, - }, - argsFutureDeployment: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - commitBlueBootstrap: mocktypes.NewCCIPOracle(t), - commitGreen: mocktypes.NewCCIPOracle(t), - commitGreenBootstrap: mocktypes.NewCCIPOracle(t), - execBlue: mocktypes.NewCCIPOracle(t), - execBlueBootstrap: mocktypes.NewCCIPOracle(t), - execGreen: mocktypes.NewCCIPOracle(t), - execGreenBootstrap: mocktypes.NewCCIPOracle(t), - }, - expect: func(t *testing.T, args args, argsPrevDeployment args) { - args.commitGreen.On("Start").Return(nil).Once() - args.commitGreenBootstrap.On("Start").Return(nil).Once() - args.execGreen.On("Start").Return(nil).Once() - args.execGreenBootstrap.On("Start").Return(nil).Once() - }, - asserts: func(t *testing.T, args args, argsPrevDeployment args) { - args.commitGreen.AssertExpectations(t) - args.commitGreenBootstrap.AssertExpectations(t) - args.execGreen.AssertExpectations(t) - args.execGreenBootstrap.AssertExpectations(t) - }, - wantErr: false, - }, { name: "error on commit green start", argsPrevDeployment: args{ @@ -700,42 +398,6 @@ func Test_ccipDeployment_HandleBlueGreen(t *testing.T) { }, wantErr: true, }, - { - name: "error on commit green bootstrap start", - argsPrevDeployment: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - commitBlueBootstrap: mocktypes.NewCCIPOracle(t), - commitGreen: nil, - commitGreenBootstrap: nil, - execBlue: mocktypes.NewCCIPOracle(t), - execBlueBootstrap: mocktypes.NewCCIPOracle(t), - execGreen: nil, - execGreenBootstrap: nil, - }, - argsFutureDeployment: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - commitBlueBootstrap: mocktypes.NewCCIPOracle(t), - commitGreen: mocktypes.NewCCIPOracle(t), - commitGreenBootstrap: mocktypes.NewCCIPOracle(t), - execBlue: mocktypes.NewCCIPOracle(t), - execBlueBootstrap: mocktypes.NewCCIPOracle(t), - execGreen: mocktypes.NewCCIPOracle(t), - execGreenBootstrap: mocktypes.NewCCIPOracle(t), - }, - expect: func(t *testing.T, args args, argsPrevDeployment args) { - args.commitGreen.On("Start").Return(nil).Once() - args.commitGreenBootstrap.On("Start").Return(errors.New("failed")).Once() - args.execGreen.On("Start").Return(nil).Once() - args.execGreenBootstrap.On("Start").Return(nil).Once() - }, - asserts: func(t *testing.T, args args, argsPrevDeployment args) { - args.commitGreen.AssertExpectations(t) - args.commitGreenBootstrap.AssertExpectations(t) - args.execGreen.AssertExpectations(t) - args.execGreenBootstrap.AssertExpectations(t) - }, - wantErr: true, - }, { name: "invalid blue-green deployment transition commit: both prev and future deployment have green", argsPrevDeployment: args{ @@ -755,7 +417,7 @@ func Test_ccipDeployment_HandleBlueGreen(t *testing.T) { wantErr: true, }, { - name: "invalid blue-green deployment transition exec: both prev and future deployment have green", + name: "invalid blue-green deployment transition exec: both prev and future exec deployment have green", argsPrevDeployment: args{ commitBlue: mocktypes.NewCCIPOracle(t), commitGreen: nil, @@ -790,21 +452,9 @@ func Test_ccipDeployment_HandleBlueGreen(t *testing.T) { if tt.argsFutureDeployment.commitGreen != nil { futDeployment.commit.green = tt.argsFutureDeployment.commitGreen } - if tt.argsFutureDeployment.commitBlueBootstrap != nil { - futDeployment.commit.bootstrapBlue = tt.argsFutureDeployment.commitBlueBootstrap - } - if tt.argsFutureDeployment.commitGreenBootstrap != nil { - futDeployment.commit.bootstrapGreen = tt.argsFutureDeployment.commitGreenBootstrap - } if tt.argsFutureDeployment.execGreen != nil { futDeployment.exec.green = tt.argsFutureDeployment.execGreen } - if tt.argsFutureDeployment.execBlueBootstrap != nil { - futDeployment.exec.bootstrapBlue = tt.argsFutureDeployment.execBlueBootstrap - } - if tt.argsFutureDeployment.execGreenBootstrap != nil { - futDeployment.exec.bootstrapGreen = tt.argsFutureDeployment.execGreenBootstrap - } prevDeployment := &ccipDeployment{ commit: blueGreenDeployment{ @@ -817,21 +467,9 @@ func Test_ccipDeployment_HandleBlueGreen(t *testing.T) { if tt.argsPrevDeployment.commitGreen != nil { prevDeployment.commit.green = tt.argsPrevDeployment.commitGreen } - if tt.argsPrevDeployment.commitBlueBootstrap != nil { - prevDeployment.commit.bootstrapBlue = tt.argsPrevDeployment.commitBlueBootstrap - } - if tt.argsPrevDeployment.commitGreenBootstrap != nil { - prevDeployment.commit.bootstrapGreen = tt.argsPrevDeployment.commitGreenBootstrap - } if tt.argsPrevDeployment.execGreen != nil { prevDeployment.exec.green = tt.argsPrevDeployment.execGreen } - if tt.argsPrevDeployment.execBlueBootstrap != nil { - prevDeployment.exec.bootstrapBlue = tt.argsPrevDeployment.execBlueBootstrap - } - if tt.argsPrevDeployment.execGreenBootstrap != nil { - prevDeployment.exec.bootstrapGreen = tt.argsPrevDeployment.execGreenBootstrap - } tt.expect(t, tt.argsFutureDeployment, tt.argsPrevDeployment) defer tt.asserts(t, tt.argsFutureDeployment, tt.argsPrevDeployment) diff --git a/core/capabilities/ccip/launcher/diff.go b/core/capabilities/ccip/launcher/diff.go index e44b5478ed..787e33dadc 100644 --- a/core/capabilities/ccip/launcher/diff.go +++ b/core/capabilities/ccip/launcher/diff.go @@ -141,16 +141,3 @@ func isMemberOfDON(don kcr.CapabilitiesRegistryDONInfo, p2pID ragep2ptypes.PeerI } return false } - -// isMemberOfBootstrapSubcommittee returns true if and only if the given p2pID is a member of the given bootstrap subcommittee. -func isMemberOfBootstrapSubcommittee( - bootstrapP2PIDs [][32]byte, - p2pID ragep2ptypes.PeerID, -) bool { - for _, bootstrapID := range bootstrapP2PIDs { - if bootstrapID == p2pID { - return true - } - } - return false -} diff --git a/core/capabilities/ccip/launcher/diff_test.go b/core/capabilities/ccip/launcher/diff_test.go index 37371945ab..b1914e1770 100644 --- a/core/capabilities/ccip/launcher/diff_test.go +++ b/core/capabilities/ccip/launcher/diff_test.go @@ -467,15 +467,6 @@ func Test_isMemberOfDON(t *testing.T) { require.False(t, isMemberOfDON(don, ragep2ptypes.PeerID(p2pkey.MustNewV2XXXTestingOnly(big.NewInt(5)).PeerID()))) } -func Test_isMemberOfBootstrapSubcommittee(t *testing.T) { - var bootstrapKeys [][32]byte - for i := range [4]struct{}{} { - bootstrapKeys = append(bootstrapKeys, p2pkey.MustNewV2XXXTestingOnly(big.NewInt(int64(i+1))).PeerID()) - } - require.True(t, isMemberOfBootstrapSubcommittee(bootstrapKeys, ragep2ptypes.PeerID(p2pkey.MustNewV2XXXTestingOnly(big.NewInt(1)).PeerID()))) - require.False(t, isMemberOfBootstrapSubcommittee(bootstrapKeys, ragep2ptypes.PeerID(p2pkey.MustNewV2XXXTestingOnly(big.NewInt(5)).PeerID()))) -} - func mustHashedCapabilityID(capabilityLabelledName, capabilityVersion string) [32]byte { r, err := capcommon.HashedCapabilityID(capabilityLabelledName, capabilityVersion) if err != nil { diff --git a/core/capabilities/ccip/launcher/integration_test.go b/core/capabilities/ccip/launcher/integration_test.go index 58b6a5d6a2..da1ac36465 100644 --- a/core/capabilities/ccip/launcher/integration_test.go +++ b/core/capabilities/ccip/launcher/integration_test.go @@ -32,17 +32,17 @@ func TestIntegration_Launcher(t *testing.T) { regSyncer, err := registrysyncer.New(lggr, uni, uni.CapReg.Address().String()) require.NoError(t, err) - hcr := uni.HomeChainReader + oracleCreator := &oracleCreatorPrints{ + t: t, + } launcher := New( it.CcipCapabilityVersion, it.CcipCapabilityLabelledName, p2pIDs[0], logger.TestLogger(t), - hcr, - &oracleCreatorPrints{ - t: t, - }, + uni.HomeChainReader, 1*time.Second, + oracleCreator, ) regSyncer.AddLauncher(launcher) @@ -99,14 +99,14 @@ type oracleCreatorPrints struct { t *testing.T } -func (o *oracleCreatorPrints) CreatePluginOracle(pluginType cctypes.PluginType, config cctypes.OCR3ConfigWithMeta) (cctypes.CCIPOracle, error) { +func (o *oracleCreatorPrints) Create(config cctypes.OCR3ConfigWithMeta) (cctypes.CCIPOracle, error) { + pluginType := cctypes.PluginType(config.Config.PluginType) o.t.Logf("Creating plugin oracle (pluginType: %s) with config %+v\n", pluginType, config) return &oraclePrints{pluginType: pluginType, config: config, t: o.t}, nil } -func (o *oracleCreatorPrints) CreateBootstrapOracle(config cctypes.OCR3ConfigWithMeta) (cctypes.CCIPOracle, error) { - o.t.Logf("Creating bootstrap oracle with config %+v\n", config) - return &oraclePrints{pluginType: cctypes.PluginTypeCCIPCommit, config: config, isBootstrap: true, t: o.t}, nil +func (o *oracleCreatorPrints) Type() cctypes.OracleType { + return cctypes.OracleTypePlugin } var _ cctypes.OracleCreator = &oracleCreatorPrints{} diff --git a/core/capabilities/ccip/launcher/launcher.go b/core/capabilities/ccip/launcher/launcher.go index 9acfebfa9a..4d60bfcdc9 100644 --- a/core/capabilities/ccip/launcher/launcher.go +++ b/core/capabilities/ccip/launcher/launcher.go @@ -6,16 +6,14 @@ import ( "sync" "time" - cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" - "go.uber.org/multierr" ragep2ptypes "github.com/smartcontractkit/libocr/ragep2p/types" - ccipreaderpkg "github.com/smartcontractkit/chainlink-ccip/pkg/reader" "github.com/smartcontractkit/chainlink-common/pkg/services" ccipreader "github.com/smartcontractkit/chainlink-ccip/pkg/reader" + cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/job" @@ -34,8 +32,8 @@ func New( p2pID ragep2ptypes.PeerID, lggr logger.Logger, homeChainReader ccipreader.HomeChain, - oracleCreator cctypes.OracleCreator, tickInterval time.Duration, + oracleCreator cctypes.OracleCreator, ) *launcher { return &launcher{ capabilityVersion: capabilityVersion, @@ -48,9 +46,9 @@ func New( IDsToNodes: make(map[p2ptypes.PeerID]kcr.CapabilitiesRegistryNodeInfo), IDsToCapabilities: make(map[registrysyncer.HashedCapabilityID]kcr.CapabilitiesRegistryCapabilityInfo), }, - oracleCreator: oracleCreator, dons: make(map[registrysyncer.DonID]*ccipDeployment), tickInterval: tickInterval, + oracleCreator: oracleCreator, } } @@ -68,10 +66,10 @@ type launcher struct { latestState registrysyncer.State // regState is the latest capability registry state that we have successfully processed. regState registrysyncer.State - oracleCreator cctypes.OracleCreator lock sync.RWMutex wg sync.WaitGroup tickInterval time.Duration + oracleCreator cctypes.OracleCreator // dons is a map of CCIP DON IDs to the OCR instances that are running on them. // we can have up to two OCR instances per CCIP plugin, since we are running two plugins, @@ -197,9 +195,9 @@ func (l *launcher) processUpdate(updated map[registrysyncer.DonID]kcr.Capabiliti l.lggr, l.p2pID, l.homeChainReader, - l.oracleCreator, *prevDeployment, don, + l.oracleCreator, ) if err != nil { return err @@ -228,8 +226,8 @@ func (l *launcher) processAdded(added map[registrysyncer.DonID]kcr.CapabilitiesR l.lggr, l.p2pID, l.homeChainReader, - l.oracleCreator, don, + l.oracleCreator, ) if err != nil { return err @@ -287,9 +285,9 @@ func updateDON( lggr logger.Logger, p2pID ragep2ptypes.PeerID, homeChainReader ccipreader.HomeChain, - oracleCreator cctypes.OracleCreator, prevDeployment ccipDeployment, don kcr.CapabilitiesRegistryDONInfo, + oracleCreator cctypes.OracleCreator, ) (futDeployment *ccipDeployment, err error) { if !isMemberOfDON(don, p2pID) { lggr.Infow("Not a member of this DON, skipping", "donId", don.Id, "p2pId", p2pID.String()) @@ -331,14 +329,14 @@ func updateDON( // All other cases are invalid. This is enforced in the ccip config contract. func createFutureBlueGreenDeployment( prevDeployment ccipDeployment, - ocrConfigs []ccipreaderpkg.OCR3ConfigWithMeta, + ocrConfigs []ccipreader.OCR3ConfigWithMeta, oracleCreator cctypes.OracleCreator, pluginType cctypes.PluginType, ) (blueGreenDeployment, error) { var deployment blueGreenDeployment if isNewGreenInstance(pluginType, ocrConfigs, prevDeployment) { // this is a new green instance. - greenOracle, err := oracleCreator.CreatePluginOracle(pluginType, cctypes.OCR3ConfigWithMeta(ocrConfigs[1])) + greenOracle, err := oracleCreator.Create(cctypes.OCR3ConfigWithMeta(ocrConfigs[1])) if err != nil { return blueGreenDeployment{}, fmt.Errorf("failed to create CCIP commit oracle: %w", err) } @@ -361,14 +359,9 @@ func createDON( lggr logger.Logger, p2pID ragep2ptypes.PeerID, homeChainReader ccipreader.HomeChain, - oracleCreator cctypes.OracleCreator, don kcr.CapabilitiesRegistryDONInfo, + oracleCreator cctypes.OracleCreator, ) (*ccipDeployment, error) { - if !isMemberOfDON(don, p2pID) { - lggr.Infow("Not a member of this DON, skipping", "donId", don.Id, "p2pId", p2pID.String()) - return nil, nil - } - // this should be a retryable error. commitOCRConfigs, err := homeChainReader.GetOCRConfigs(context.Background(), don.Id, uint8(cctypes.PluginTypeCCIPCommit)) if err != nil { @@ -391,45 +384,29 @@ func createDON( return nil, fmt.Errorf("expected exactly one OCR config for CCIP exec plugin (don id: %d), got %d", don.Id, len(execOCRConfigs)) } - commitOracle, commitBootstrap, err := createOracle(p2pID, oracleCreator, cctypes.PluginTypeCCIPCommit, commitOCRConfigs) + if !isMemberOfDON(don, p2pID) && oracleCreator.Type() == cctypes.OracleTypePlugin { + lggr.Infow("Not a member of this DON and not a bootstrap node either, skipping", "donId", don.Id, "p2pId", p2pID.String()) + return nil, nil + } + + // at this point we know we are either a member of the DON or a bootstrap node. + // the injected oracleCreator will create the appropriate oracle. + commitOracle, err := oracleCreator.Create(cctypes.OCR3ConfigWithMeta(commitOCRConfigs[0])) if err != nil { return nil, fmt.Errorf("failed to create CCIP commit oracle: %w", err) } - execOracle, execBootstrap, err := createOracle(p2pID, oracleCreator, cctypes.PluginTypeCCIPExec, execOCRConfigs) + execOracle, err := oracleCreator.Create(cctypes.OCR3ConfigWithMeta(execOCRConfigs[0])) if err != nil { return nil, fmt.Errorf("failed to create CCIP exec oracle: %w", err) } return &ccipDeployment{ commit: blueGreenDeployment{ - blue: commitOracle, - bootstrapBlue: commitBootstrap, + blue: commitOracle, }, exec: blueGreenDeployment{ - blue: execOracle, - bootstrapBlue: execBootstrap, + blue: execOracle, }, }, nil } - -func createOracle( - p2pID ragep2ptypes.PeerID, - oracleCreator cctypes.OracleCreator, - pluginType cctypes.PluginType, - ocrConfigs []ccipreaderpkg.OCR3ConfigWithMeta, -) (pluginOracle, bootstrapOracle cctypes.CCIPOracle, err error) { - pluginOracle, err = oracleCreator.CreatePluginOracle(pluginType, cctypes.OCR3ConfigWithMeta(ocrConfigs[0])) - if err != nil { - return nil, nil, fmt.Errorf("failed to create CCIP plugin oracle (plugintype: %d): %w", pluginType, err) - } - - if isMemberOfBootstrapSubcommittee(ocrConfigs[0].Config.BootstrapP2PIds, p2pID) { - bootstrapOracle, err = oracleCreator.CreateBootstrapOracle(cctypes.OCR3ConfigWithMeta(ocrConfigs[0])) - if err != nil { - return nil, nil, fmt.Errorf("failed to create CCIP bootstrap oracle (plugintype: %d): %w", pluginType, err) - } - } - - return pluginOracle, bootstrapOracle, nil -} diff --git a/core/capabilities/ccip/launcher/launcher_test.go b/core/capabilities/ccip/launcher/launcher_test.go index 493f962c2c..bb24464c62 100644 --- a/core/capabilities/ccip/launcher/launcher_test.go +++ b/core/capabilities/ccip/launcher/launcher_test.go @@ -1,7 +1,6 @@ package launcher import ( - "errors" "math/big" "reflect" "testing" @@ -16,154 +15,69 @@ import ( ccipreaderpkg "github.com/smartcontractkit/chainlink-ccip/pkg/reader" kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" "github.com/smartcontractkit/chainlink/v2/core/services/registrysyncer" ) -func Test_createOracle(t *testing.T) { - var p2pKeys []ragep2ptypes.PeerID - for i := 0; i < 3; i++ { - p2pKeys = append(p2pKeys, ragep2ptypes.PeerID(p2pkey.MustNewV2XXXTestingOnly(big.NewInt(int64(i+1))).PeerID())) - } - myP2PKey := p2pKeys[0] +func Test_createDON(t *testing.T) { type args struct { - p2pID ragep2ptypes.PeerID - oracleCreator *mocks.OracleCreator - pluginType cctypes.PluginType - ocrConfigs []ccipreaderpkg.OCR3ConfigWithMeta + lggr logger.Logger + p2pID ragep2ptypes.PeerID + homeChainReader *mocks.HomeChainReader + oracleCreator *mocks.OracleCreator + don kcr.CapabilitiesRegistryDONInfo } tests := []struct { name string args args - expect func(t *testing.T, args args, oracleCreator *mocks.OracleCreator) + expect func(t *testing.T, args args, oracleCreator *mocks.OracleCreator, homeChainReader *mocks.HomeChainReader) wantErr bool }{ { - "success, no bootstrap", + "not a member of the DON and not a bootstrap node", args{ - myP2PKey, + logger.TestLogger(t), + ragep2ptypes.PeerID(p2pkey.MustNewV2XXXTestingOnly(big.NewInt(1)).PeerID()), + mocks.NewHomeChainReader(t), mocks.NewOracleCreator(t), - cctypes.PluginTypeCCIPCommit, - []ccipreaderpkg.OCR3ConfigWithMeta{ - { - Config: ccipreaderpkg.OCR3Config{}, - ConfigCount: 1, - ConfigDigest: testutils.Random32Byte(), + kcr.CapabilitiesRegistryDONInfo{ + NodeP2PIds: [][32]byte{ + p2pkey.MustNewV2XXXTestingOnly(big.NewInt(3)).PeerID(), + p2pkey.MustNewV2XXXTestingOnly(big.NewInt(4)).PeerID(), }, + Id: 2, }, }, - func(t *testing.T, args args, oracleCreator *mocks.OracleCreator) { - oracleCreator. - On("CreatePluginOracle", cctypes.PluginTypeCCIPCommit, cctypes.OCR3ConfigWithMeta(args.ocrConfigs[0])). - Return(mocks.NewCCIPOracle(t), nil) - }, - false, - }, - { - "success, with bootstrap", - args{ - myP2PKey, - mocks.NewOracleCreator(t), - cctypes.PluginTypeCCIPCommit, - []ccipreaderpkg.OCR3ConfigWithMeta{ - { + func(t *testing.T, args args, oracleCreator *mocks.OracleCreator, homeChainReader *mocks.HomeChainReader) { + homeChainReader. + On("GetOCRConfigs", mock.Anything, uint32(2), uint8(cctypes.PluginTypeCCIPCommit)). + Return([]ccipreaderpkg.OCR3ConfigWithMeta{{ Config: ccipreaderpkg.OCR3Config{ - BootstrapP2PIds: [][32]byte{myP2PKey}, + PluginType: uint8(cctypes.PluginTypeCCIPCommit), + P2PIds: [][32]byte{ + p2pkey.MustNewV2XXXTestingOnly(big.NewInt(3)).PeerID(), + p2pkey.MustNewV2XXXTestingOnly(big.NewInt(4)).PeerID(), + }, }, - ConfigCount: 1, - ConfigDigest: testutils.Random32Byte(), - }, - }, - }, - func(t *testing.T, args args, oracleCreator *mocks.OracleCreator) { - oracleCreator. - On("CreatePluginOracle", cctypes.PluginTypeCCIPCommit, cctypes.OCR3ConfigWithMeta(args.ocrConfigs[0])). - Return(mocks.NewCCIPOracle(t), nil) - oracleCreator. - On("CreateBootstrapOracle", cctypes.OCR3ConfigWithMeta(args.ocrConfigs[0])). - Return(mocks.NewCCIPOracle(t), nil) - }, - false, - }, - { - "error creating plugin oracle", - args{ - myP2PKey, - mocks.NewOracleCreator(t), - cctypes.PluginTypeCCIPCommit, - []ccipreaderpkg.OCR3ConfigWithMeta{ - { - Config: ccipreaderpkg.OCR3Config{}, - ConfigCount: 1, - ConfigDigest: testutils.Random32Byte(), - }, - }, - }, - func(t *testing.T, args args, oracleCreator *mocks.OracleCreator) { - oracleCreator. - On("CreatePluginOracle", cctypes.PluginTypeCCIPCommit, cctypes.OCR3ConfigWithMeta(args.ocrConfigs[0])). - Return(nil, errors.New("error creating oracle")) - }, - true, - }, - { - "error creating bootstrap oracle", - args{ - myP2PKey, - mocks.NewOracleCreator(t), - cctypes.PluginTypeCCIPCommit, - []ccipreaderpkg.OCR3ConfigWithMeta{ - { + }}, nil) + homeChainReader. + On("GetOCRConfigs", mock.Anything, uint32(2), uint8(cctypes.PluginTypeCCIPExec)). + Return([]ccipreaderpkg.OCR3ConfigWithMeta{{ Config: ccipreaderpkg.OCR3Config{ - BootstrapP2PIds: [][32]byte{myP2PKey}, + PluginType: uint8(cctypes.PluginTypeCCIPExec), + P2PIds: [][32]byte{ + p2pkey.MustNewV2XXXTestingOnly(big.NewInt(3)).PeerID(), + p2pkey.MustNewV2XXXTestingOnly(big.NewInt(4)).PeerID(), + }, }, - ConfigCount: 1, - ConfigDigest: testutils.Random32Byte(), - }, - }, + }}, nil) + oracleCreator.EXPECT().Type().Return(cctypes.OracleTypePlugin).Once() }, - func(t *testing.T, args args, oracleCreator *mocks.OracleCreator) { - oracleCreator. - On("CreatePluginOracle", cctypes.PluginTypeCCIPCommit, cctypes.OCR3ConfigWithMeta(args.ocrConfigs[0])). - Return(mocks.NewCCIPOracle(t), nil) - oracleCreator. - On("CreateBootstrapOracle", cctypes.OCR3ConfigWithMeta(args.ocrConfigs[0])). - Return(nil, errors.New("error creating oracle")) - }, - true, + false, }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - tt.expect(t, tt.args, tt.args.oracleCreator) - _, _, err := createOracle(tt.args.p2pID, tt.args.oracleCreator, tt.args.pluginType, tt.args.ocrConfigs) - if tt.wantErr { - require.Error(t, err) - } else { - require.NoError(t, err) - } - }) - } -} - -func Test_createDON(t *testing.T) { - type args struct { - lggr logger.Logger - p2pID ragep2ptypes.PeerID - homeChainReader *mocks.HomeChainReader - oracleCreator *mocks.OracleCreator - don kcr.CapabilitiesRegistryDONInfo - } - tests := []struct { - name string - args args - expect func(t *testing.T, args args, oracleCreator *mocks.OracleCreator, homeChainReader *mocks.HomeChainReader) - wantErr bool - }{ { - "not a member of the DON", + "not a member of the DON but a running a bootstrap oracle creator", args{ logger.TestLogger(t), ragep2ptypes.PeerID(p2pkey.MustNewV2XXXTestingOnly(big.NewInt(1)).PeerID()), @@ -171,17 +85,44 @@ func Test_createDON(t *testing.T) { mocks.NewOracleCreator(t), kcr.CapabilitiesRegistryDONInfo{ NodeP2PIds: [][32]byte{ - p2pkey.MustNewV2XXXTestingOnly(big.NewInt(2)).PeerID(), + p2pkey.MustNewV2XXXTestingOnly(big.NewInt(3)).PeerID(), + p2pkey.MustNewV2XXXTestingOnly(big.NewInt(4)).PeerID(), }, Id: 2, }, }, func(t *testing.T, args args, oracleCreator *mocks.OracleCreator, homeChainReader *mocks.HomeChainReader) { + homeChainReader. + On("GetOCRConfigs", mock.Anything, uint32(2), uint8(cctypes.PluginTypeCCIPCommit)). + Return([]ccipreaderpkg.OCR3ConfigWithMeta{{ + Config: ccipreaderpkg.OCR3Config{ + PluginType: uint8(cctypes.PluginTypeCCIPCommit), + P2PIds: [][32]byte{ + p2pkey.MustNewV2XXXTestingOnly(big.NewInt(3)).PeerID(), + p2pkey.MustNewV2XXXTestingOnly(big.NewInt(4)).PeerID(), + }, + }, + }}, nil) + homeChainReader. + On("GetOCRConfigs", mock.Anything, uint32(2), uint8(cctypes.PluginTypeCCIPExec)). + Return([]ccipreaderpkg.OCR3ConfigWithMeta{{ + Config: ccipreaderpkg.OCR3Config{ + PluginType: uint8(cctypes.PluginTypeCCIPExec), + P2PIds: [][32]byte{ + p2pkey.MustNewV2XXXTestingOnly(big.NewInt(3)).PeerID(), + p2pkey.MustNewV2XXXTestingOnly(big.NewInt(4)).PeerID(), + }, + }, + }}, nil) + oracleCreator.EXPECT().Type().Return(cctypes.OracleTypeBootstrap).Once() + oracleCreator. + On("Create", mock.Anything). + Return(mocks.NewCCIPOracle(t), nil).Twice() }, false, }, { - "success, no bootstrap", + "success", args{ logger.TestLogger(t), ragep2ptypes.PeerID(p2pkey.MustNewV2XXXTestingOnly(big.NewInt(1)).PeerID()), @@ -190,6 +131,7 @@ func Test_createDON(t *testing.T) { kcr.CapabilitiesRegistryDONInfo{ NodeP2PIds: [][32]byte{ p2pkey.MustNewV2XXXTestingOnly(big.NewInt(1)).PeerID(), + p2pkey.MustNewV2XXXTestingOnly(big.NewInt(2)).PeerID(), }, Id: 1, }, @@ -197,15 +139,34 @@ func Test_createDON(t *testing.T) { func(t *testing.T, args args, oracleCreator *mocks.OracleCreator, homeChainReader *mocks.HomeChainReader) { homeChainReader. On("GetOCRConfigs", mock.Anything, uint32(1), uint8(cctypes.PluginTypeCCIPCommit)). - Return([]ccipreaderpkg.OCR3ConfigWithMeta{{}}, nil) + Return([]ccipreaderpkg.OCR3ConfigWithMeta{{ + Config: ccipreaderpkg.OCR3Config{ + PluginType: uint8(cctypes.PluginTypeCCIPCommit), + P2PIds: [][32]byte{ + p2pkey.MustNewV2XXXTestingOnly(big.NewInt(1)).PeerID(), + p2pkey.MustNewV2XXXTestingOnly(big.NewInt(2)).PeerID(), + }, + }, + }}, nil) homeChainReader. On("GetOCRConfigs", mock.Anything, uint32(1), uint8(cctypes.PluginTypeCCIPExec)). - Return([]ccipreaderpkg.OCR3ConfigWithMeta{{}}, nil) - oracleCreator. - On("CreatePluginOracle", cctypes.PluginTypeCCIPCommit, mock.Anything). + Return([]ccipreaderpkg.OCR3ConfigWithMeta{{ + Config: ccipreaderpkg.OCR3Config{ + PluginType: uint8(cctypes.PluginTypeCCIPExec), + P2PIds: [][32]byte{ + p2pkey.MustNewV2XXXTestingOnly(big.NewInt(1)).PeerID(), + p2pkey.MustNewV2XXXTestingOnly(big.NewInt(2)).PeerID(), + }, + }, + }}, nil) + + oracleCreator.EXPECT().Create(mock.MatchedBy(func(cfg cctypes.OCR3ConfigWithMeta) bool { + return cfg.Config.PluginType == uint8(cctypes.PluginTypeCCIPCommit) + })). Return(mocks.NewCCIPOracle(t), nil) - oracleCreator. - On("CreatePluginOracle", cctypes.PluginTypeCCIPExec, mock.Anything). + oracleCreator.EXPECT().Create(mock.MatchedBy(func(cfg cctypes.OCR3ConfigWithMeta) bool { + return cfg.Config.PluginType == uint8(cctypes.PluginTypeCCIPExec) + })). Return(mocks.NewCCIPOracle(t), nil) }, false, @@ -216,7 +177,8 @@ func Test_createDON(t *testing.T) { if tt.expect != nil { tt.expect(t, tt.args, tt.args.oracleCreator, tt.args.homeChainReader) } - _, err := createDON(tt.args.lggr, tt.args.p2pID, tt.args.homeChainReader, tt.args.oracleCreator, tt.args.don) + + _, err := createDON(tt.args.lggr, tt.args.p2pID, tt.args.homeChainReader, tt.args.don, tt.args.oracleCreator) if tt.wantErr { require.Error(t, err) } else { @@ -274,7 +236,7 @@ func Test_updateDON(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - gotFutDeployment, err := updateDON(tt.args.lggr, tt.args.p2pID, tt.args.homeChainReader, tt.args.oracleCreator, tt.args.prevDeployment, tt.args.don) + gotFutDeployment, err := updateDON(tt.args.lggr, tt.args.p2pID, tt.args.homeChainReader, tt.args.prevDeployment, tt.args.don, tt.args.oracleCreator) if (err != nil) != tt.wantErr { t.Errorf("updateDON() error = %v, wantErr %v", err, tt.wantErr) return @@ -358,9 +320,17 @@ func Test_launcher_processDiff(t *testing.T) { return mocks.NewHomeChainReader(t) }, func(m *mocks.HomeChainReader) { m.On("GetOCRConfigs", mock.Anything, uint32(1), uint8(cctypes.PluginTypeCCIPCommit)). - Return([]ccipreaderpkg.OCR3ConfigWithMeta{{}}, nil) + Return([]ccipreaderpkg.OCR3ConfigWithMeta{{ + Config: ccipreaderpkg.OCR3Config{ + PluginType: uint8(cctypes.PluginTypeCCIPCommit), + }, + }}, nil) m.On("GetOCRConfigs", mock.Anything, uint32(1), uint8(cctypes.PluginTypeCCIPExec)). - Return([]ccipreaderpkg.OCR3ConfigWithMeta{{}}, nil) + Return([]ccipreaderpkg.OCR3ConfigWithMeta{{ + Config: ccipreaderpkg.OCR3Config{ + PluginType: uint8(cctypes.PluginTypeCCIPExec), + }, + }}, nil) }), oracleCreator: newMock(t, func(t *testing.T) *mocks.OracleCreator { return mocks.NewOracleCreator(t) @@ -369,9 +339,13 @@ func Test_launcher_processDiff(t *testing.T) { commitOracle.On("Start").Return(nil) execOracle := mocks.NewCCIPOracle(t) execOracle.On("Start").Return(nil) - m.On("CreatePluginOracle", cctypes.PluginTypeCCIPCommit, mock.Anything). + m.EXPECT().Create(mock.MatchedBy(func(cfg cctypes.OCR3ConfigWithMeta) bool { + return cfg.Config.PluginType == uint8(cctypes.PluginTypeCCIPCommit) + })). Return(commitOracle, nil) - m.On("CreatePluginOracle", cctypes.PluginTypeCCIPExec, mock.Anything). + m.EXPECT().Create(mock.MatchedBy(func(cfg cctypes.OCR3ConfigWithMeta) bool { + return cfg.Config.PluginType == uint8(cctypes.PluginTypeCCIPExec) + })). Return(execOracle, nil) }), dons: map[registrysyncer.DonID]*ccipDeployment{}, @@ -406,9 +380,25 @@ func Test_launcher_processDiff(t *testing.T) { return mocks.NewHomeChainReader(t) }, func(m *mocks.HomeChainReader) { m.On("GetOCRConfigs", mock.Anything, uint32(1), uint8(cctypes.PluginTypeCCIPCommit)). - Return([]ccipreaderpkg.OCR3ConfigWithMeta{{}, {}}, nil) + Return([]ccipreaderpkg.OCR3ConfigWithMeta{{ + Config: ccipreaderpkg.OCR3Config{ + PluginType: uint8(cctypes.PluginTypeCCIPCommit), + }, + }, { + Config: ccipreaderpkg.OCR3Config{ + PluginType: uint8(cctypes.PluginTypeCCIPCommit), + }, + }}, nil) m.On("GetOCRConfigs", mock.Anything, uint32(1), uint8(cctypes.PluginTypeCCIPExec)). - Return([]ccipreaderpkg.OCR3ConfigWithMeta{{}, {}}, nil) + Return([]ccipreaderpkg.OCR3ConfigWithMeta{{ + Config: ccipreaderpkg.OCR3Config{ + PluginType: uint8(cctypes.PluginTypeCCIPExec), + }, + }, { + Config: ccipreaderpkg.OCR3Config{ + PluginType: uint8(cctypes.PluginTypeCCIPExec), + }, + }}, nil) }), oracleCreator: newMock(t, func(t *testing.T) *mocks.OracleCreator { return mocks.NewOracleCreator(t) @@ -417,9 +407,13 @@ func Test_launcher_processDiff(t *testing.T) { commitOracle.On("Start").Return(nil) execOracle := mocks.NewCCIPOracle(t) execOracle.On("Start").Return(nil) - m.On("CreatePluginOracle", cctypes.PluginTypeCCIPCommit, mock.Anything). + m.EXPECT().Create(mock.MatchedBy(func(cfg cctypes.OCR3ConfigWithMeta) bool { + return cfg.Config.PluginType == uint8(cctypes.PluginTypeCCIPCommit) + })). Return(commitOracle, nil) - m.On("CreatePluginOracle", cctypes.PluginTypeCCIPExec, mock.Anything). + m.EXPECT().Create(mock.MatchedBy(func(cfg cctypes.OCR3ConfigWithMeta) bool { + return cfg.Config.PluginType == uint8(cctypes.PluginTypeCCIPExec) + })). Return(execOracle, nil) }), dons: map[registrysyncer.DonID]*ccipDeployment{ diff --git a/core/capabilities/ccip/oraclecreator/bootstrap.go b/core/capabilities/ccip/oraclecreator/bootstrap.go new file mode 100644 index 0000000000..a4bf03a4de --- /dev/null +++ b/core/capabilities/ccip/oraclecreator/bootstrap.go @@ -0,0 +1,97 @@ +package oraclecreator + +import ( + "context" + "fmt" + + "github.com/ethereum/go-ethereum/common/hexutil" + + chainsel "github.com/smartcontractkit/chain-selectors" + "github.com/smartcontractkit/libocr/commontypes" + libocr3 "github.com/smartcontractkit/libocr/offchainreporting2plus" + "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" + + "github.com/smartcontractkit/chainlink-common/pkg/types" + + "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ocrimpls" + cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" + "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore/chaintype" + "github.com/smartcontractkit/chainlink/v2/core/services/ocrcommon" + "github.com/smartcontractkit/chainlink/v2/core/services/synchronization" + "github.com/smartcontractkit/chainlink/v2/core/services/telemetry" +) + +var _ cctypes.OracleCreator = &bootstrapOracleCreator{} + +type bootstrapOracleCreator struct { + peerWrapper *ocrcommon.SingletonPeerWrapper + bootstrapperLocators []commontypes.BootstrapperLocator + db ocr3types.Database + monitoringEndpointGen telemetry.MonitoringEndpointGenerator + lggr logger.Logger +} + +func NewBootstrapOracleCreator( + peerWrapper *ocrcommon.SingletonPeerWrapper, + bootstrapperLocators []commontypes.BootstrapperLocator, + db ocr3types.Database, + monitoringEndpointGen telemetry.MonitoringEndpointGenerator, + lggr logger.Logger, +) cctypes.OracleCreator { + return &bootstrapOracleCreator{ + peerWrapper: peerWrapper, + bootstrapperLocators: bootstrapperLocators, + db: db, + monitoringEndpointGen: monitoringEndpointGen, + lggr: lggr, + } +} + +// Type implements types.OracleCreator. +func (i *bootstrapOracleCreator) Type() cctypes.OracleType { + return cctypes.OracleTypeBootstrap +} + +// Create implements types.OracleCreator. +func (i *bootstrapOracleCreator) Create(config cctypes.OCR3ConfigWithMeta) (cctypes.CCIPOracle, error) { + // Assuming that the chain selector is referring to an evm chain for now. + // TODO: add an api that returns chain family. + // NOTE: this doesn't really matter for the bootstrap node, it doesn't do anything on-chain. + // Its for the monitoring endpoint generation below. + chainID, err := chainsel.ChainIdFromSelector(uint64(config.Config.ChainSelector)) + if err != nil { + return nil, fmt.Errorf("failed to get chain ID from selector: %w", err) + } + + destChainFamily := chaintype.EVM + destRelayID := types.NewRelayID(string(destChainFamily), fmt.Sprintf("%d", chainID)) + + bootstrapperArgs := libocr3.BootstrapperArgs{ + BootstrapperFactory: i.peerWrapper.Peer2, + V2Bootstrappers: i.bootstrapperLocators, + ContractConfigTracker: ocrimpls.NewConfigTracker(config), + Database: i.db, + LocalConfig: defaultLocalConfig(), + Logger: ocrcommon.NewOCRWrapper( + i.lggr. + Named("CCIPBootstrap"). + Named(destRelayID.String()). + Named(config.Config.ChainSelector.String()). + Named(hexutil.Encode(config.Config.OfframpAddress)), + false, /* traceLogging */ + func(ctx context.Context, msg string) {}), + MonitoringEndpoint: i.monitoringEndpointGen.GenMonitoringEndpoint( + string(destChainFamily), + destRelayID.ChainID, + hexutil.Encode(config.Config.OfframpAddress), + synchronization.OCR3CCIPBootstrap, + ), + OffchainConfigDigester: ocrimpls.NewConfigDigester(config.ConfigDigest), + } + bootstrapper, err := libocr3.NewBootstrapper(bootstrapperArgs) + if err != nil { + return nil, err + } + return bootstrapper, nil +} diff --git a/core/capabilities/ccip/oraclecreator/inprocess_test.go b/core/capabilities/ccip/oraclecreator/inprocess_test.go deleted file mode 100644 index 639f01e62e..0000000000 --- a/core/capabilities/ccip/oraclecreator/inprocess_test.go +++ /dev/null @@ -1,239 +0,0 @@ -package oraclecreator_test - -import ( - "fmt" - "testing" - "time" - - "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/oraclecreator" - cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" - - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/google/uuid" - "github.com/hashicorp/consul/sdk/freeport" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "gopkg.in/guregu/null.v4" - - chainsel "github.com/smartcontractkit/chain-selectors" - "github.com/smartcontractkit/libocr/offchainreporting2/types" - confighelper2 "github.com/smartcontractkit/libocr/offchainreporting2plus/confighelper" - "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3confighelper" - - "github.com/smartcontractkit/chainlink-ccip/pkg/reader" - "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3" - "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" - - "github.com/smartcontractkit/libocr/commontypes" - - "github.com/smartcontractkit/chainlink/v2/core/bridges" - "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" - "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" - "github.com/smartcontractkit/chainlink/v2/core/services/job" - "github.com/smartcontractkit/chainlink/v2/core/services/keystore" - "github.com/smartcontractkit/chainlink/v2/core/services/keystore/chaintype" - "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2" - ocr2validate "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/validate" - "github.com/smartcontractkit/chainlink/v2/core/services/ocrcommon" - "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" - "github.com/smartcontractkit/chainlink/v2/core/services/synchronization" - "github.com/smartcontractkit/chainlink/v2/core/services/telemetry" - "github.com/smartcontractkit/chainlink/v2/core/testdata/testspecs" - "github.com/smartcontractkit/chainlink/v2/core/utils" -) - -func TestOracleCreator_CreateBootstrap(t *testing.T) { - db := pgtest.NewSqlxDB(t) - - keyStore := keystore.New(db, utils.DefaultScryptParams, logger.NullLogger) - require.NoError(t, keyStore.Unlock(testutils.Context(t), cltest.Password), "unable to unlock keystore") - p2pKey, err := keyStore.P2P().Create(testutils.Context(t)) - require.NoError(t, err) - peerID := p2pKey.PeerID() - listenPort := freeport.GetOne(t) - generalConfig := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { - c.P2P.PeerID = ptr(peerID) - c.P2P.TraceLogging = ptr(false) - c.P2P.V2.Enabled = ptr(true) - c.P2P.V2.ListenAddresses = ptr([]string{fmt.Sprintf("127.0.0.1:%d", listenPort)}) - - c.OCR2.Enabled = ptr(true) - }) - peerWrapper := ocrcommon.NewSingletonPeerWrapper(keyStore, generalConfig.P2P(), generalConfig.OCR(), db, logger.NullLogger) - require.NoError(t, peerWrapper.Start(testutils.Context(t))) - t.Cleanup(func() { assert.NoError(t, peerWrapper.Close()) }) - - // NOTE: this is a bit of a hack to get the OCR2 job created in order to use the ocr db - // the ocr2_contract_configs table has a foreign key constraint on ocr2_oracle_spec_id - // which is passed into ocr2.NewDB. - pipelineORM := pipeline.NewORM(db, - logger.NullLogger, generalConfig.JobPipeline().MaxSuccessfulRuns()) - bridgesORM := bridges.NewORM(db) - - jobORM := job.NewORM(db, pipelineORM, bridgesORM, keyStore, logger.TestLogger(t)) - t.Cleanup(func() { assert.NoError(t, jobORM.Close()) }) - - jb, err := ocr2validate.ValidatedOracleSpecToml(testutils.Context(t), generalConfig.OCR2(), generalConfig.Insecure(), testspecs.GetOCR2EVMSpecMinimal(), nil) - require.NoError(t, err) - const juelsPerFeeCoinSource = ` - ds [type=http method=GET url="https://chain.link/ETH-USD"]; - ds_parse [type=jsonparse path="data.price" separator="."]; - ds_multiply [type=multiply times=100]; - ds -> ds_parse -> ds_multiply;` - - _, address := cltest.MustInsertRandomKey(t, keyStore.Eth()) - jb.Name = null.StringFrom("Job 1") - jb.OCR2OracleSpec.TransmitterID = null.StringFrom(address.String()) - jb.OCR2OracleSpec.PluginConfig["juelsPerFeeCoinSource"] = juelsPerFeeCoinSource - - err = jobORM.CreateJob(testutils.Context(t), &jb) - require.NoError(t, err) - - cltest.AssertCount(t, db, "ocr2_oracle_specs", 1) - cltest.AssertCount(t, db, "jobs", 1) - - var oracleSpecID int32 - err = db.Get(&oracleSpecID, "SELECT id FROM ocr2_oracle_specs LIMIT 1") - require.NoError(t, err) - - ocrdb := ocr2.NewDB(db, oracleSpecID, 0, logger.NullLogger) - - oc := oraclecreator.New( - nil, - nil, - nil, - peerWrapper, - uuid.Max, - 0, - false, - nil, - ocrdb, - logger.TestLogger(t), - &mockEndpointGen{}, - []commontypes.BootstrapperLocator{}, - nil, - ) - - chainSelector := chainsel.GETH_TESTNET.Selector - oracles, offchainConfig := ocrOffchainConfig(t, keyStore) - bootstrapP2PID, err := p2pkey.MakePeerID(oracles[0].PeerID) - require.NoError(t, err) - transmitters := func() [][]byte { - var transmitters [][]byte - for _, o := range oracles { - transmitters = append(transmitters, hexutil.MustDecode(string(o.TransmitAccount))) - } - return transmitters - }() - configDigest := ccipConfigDigest() - bootstrap, err := oc.CreateBootstrapOracle(cctypes.OCR3ConfigWithMeta{ - ConfigDigest: configDigest, - ConfigCount: 1, - Config: reader.OCR3Config{ - ChainSelector: ccipocr3.ChainSelector(chainSelector), - OfframpAddress: testutils.NewAddress().Bytes(), - PluginType: uint8(cctypes.PluginTypeCCIPCommit), - F: 1, - OffchainConfigVersion: 30, - BootstrapP2PIds: [][32]byte{bootstrapP2PID}, - P2PIds: func() [][32]byte { - var ids [][32]byte - for _, o := range oracles { - id, err2 := p2pkey.MakePeerID(o.PeerID) - require.NoError(t, err2) - ids = append(ids, id) - } - return ids - }(), - Signers: func() [][]byte { - var signers [][]byte - for _, o := range oracles { - signers = append(signers, o.OnchainPublicKey) - } - return signers - }(), - Transmitters: transmitters, - OffchainConfig: offchainConfig, - }, - }) - require.NoError(t, err) - require.NoError(t, bootstrap.Start()) - t.Cleanup(func() { assert.NoError(t, bootstrap.Close()) }) - - tests.AssertEventually(t, func() bool { - c, err := ocrdb.ReadConfig(testutils.Context(t)) - require.NoError(t, err) - return c.ConfigDigest == configDigest - }) -} - -func ccipConfigDigest() [32]byte { - rand32Bytes := testutils.Random32Byte() - // overwrite first four bytes to be 0x000a, to match the prefix in libocr. - rand32Bytes[0] = 0x00 - rand32Bytes[1] = 0x0a - return rand32Bytes -} - -type mockEndpointGen struct{} - -func (m *mockEndpointGen) GenMonitoringEndpoint(network string, chainID string, contractID string, telemType synchronization.TelemetryType) commontypes.MonitoringEndpoint { - return &telemetry.NoopAgent{} -} - -func ptr[T any](b T) *T { - return &b -} - -func ocrOffchainConfig(t *testing.T, ks keystore.Master) (oracles []confighelper2.OracleIdentityExtra, offchainConfig []byte) { - for i := 0; i < 4; i++ { - kb, err := ks.OCR2().Create(testutils.Context(t), chaintype.EVM) - require.NoError(t, err) - p2pKey, err := ks.P2P().Create(testutils.Context(t)) - require.NoError(t, err) - ethKey, err := ks.Eth().Create(testutils.Context(t)) - require.NoError(t, err) - oracles = append(oracles, confighelper2.OracleIdentityExtra{ - OracleIdentity: confighelper2.OracleIdentity{ - OffchainPublicKey: kb.OffchainPublicKey(), - OnchainPublicKey: types.OnchainPublicKey(kb.OnChainPublicKey()), - PeerID: p2pKey.ID(), - TransmitAccount: types.Account(ethKey.Address.Hex()), - }, - ConfigEncryptionPublicKey: kb.ConfigEncryptionPublicKey(), - }) - } - var schedule []int - for range oracles { - schedule = append(schedule, 1) - } - offchainConfig, onchainConfig := []byte{}, []byte{} - f := uint8(1) - - _, _, _, _, _, offchainConfig, err := ocr3confighelper.ContractSetConfigArgsForTests( - 30*time.Second, // deltaProgress - 10*time.Second, // deltaResend - 20*time.Second, // deltaInitial - 2*time.Second, // deltaRound - 20*time.Second, // deltaGrace - 10*time.Second, // deltaCertifiedCommitRequest - 10*time.Second, // deltaStage - 3, // rmax - schedule, - oracles, - offchainConfig, - 50*time.Millisecond, // maxDurationQuery - 5*time.Second, // maxDurationObservation - 10*time.Second, // maxDurationShouldAcceptAttestedReport - 10*time.Second, // maxDurationShouldTransmitAcceptedReport - int(f), - onchainConfig) - require.NoError(t, err, "failed to create contract config") - - return oracles, offchainConfig -} diff --git a/core/capabilities/ccip/oraclecreator/inprocess.go b/core/capabilities/ccip/oraclecreator/plugin.go similarity index 79% rename from core/capabilities/ccip/oraclecreator/inprocess.go rename to core/capabilities/ccip/oraclecreator/plugin.go index 21e9bcec6d..c87c4e97c1 100644 --- a/core/capabilities/ccip/oraclecreator/inprocess.go +++ b/core/capabilities/ccip/oraclecreator/plugin.go @@ -36,7 +36,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/job" - "github.com/smartcontractkit/chainlink/v2/core/services/keystore/chaintype" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ocr2key" "github.com/smartcontractkit/chainlink/v2/core/services/ocrcommon" "github.com/smartcontractkit/chainlink/v2/core/services/relay" @@ -46,15 +45,15 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/telemetry" ) -var _ cctypes.OracleCreator = &inprocessOracleCreator{} +var _ cctypes.OracleCreator = &pluginOracleCreator{} const ( defaultCommitGasLimit = 500_000 ) -// inprocessOracleCreator creates oracles that reference plugins running +// pluginOracleCreator creates oracles that reference plugins running // in the same process as the chainlink node, i.e not LOOPPs. -type inprocessOracleCreator struct { +type pluginOracleCreator struct { ocrKeyBundles map[string]ocr2key.KeyBundle transmitters map[types.RelayID][]string chains legacyevm.LegacyChainContainer @@ -70,7 +69,7 @@ type inprocessOracleCreator struct { homeChainReader ccipreaderpkg.HomeChain } -func New( +func NewPluginOracleCreator( ocrKeyBundles map[string]ocr2key.KeyBundle, transmitters map[types.RelayID][]string, chains legacyevm.LegacyChainContainer, @@ -85,7 +84,7 @@ func New( bootstrapperLocators []commontypes.BootstrapperLocator, homeChainReader ccipreaderpkg.HomeChain, ) cctypes.OracleCreator { - return &inprocessOracleCreator{ + return &pluginOracleCreator{ ocrKeyBundles: ocrKeyBundles, transmitters: transmitters, chains: chains, @@ -102,49 +101,15 @@ func New( } } -// CreateBootstrapOracle implements types.OracleCreator. -func (i *inprocessOracleCreator) CreateBootstrapOracle(config cctypes.OCR3ConfigWithMeta) (cctypes.CCIPOracle, error) { - // Assuming that the chain selector is referring to an evm chain for now. - // TODO: add an api that returns chain family. - chainID, err := chainsel.ChainIdFromSelector(uint64(config.Config.ChainSelector)) - if err != nil { - return nil, fmt.Errorf("failed to get chain ID from selector: %w", err) - } - - destChainFamily := chaintype.EVM - destRelayID := types.NewRelayID(string(destChainFamily), fmt.Sprintf("%d", chainID)) - - bootstrapperArgs := libocr3.BootstrapperArgs{ - BootstrapperFactory: i.peerWrapper.Peer2, - V2Bootstrappers: i.bootstrapperLocators, - ContractConfigTracker: ocrimpls.NewConfigTracker(config), - Database: i.db, - LocalConfig: defaultLocalConfig(), - Logger: ocrcommon.NewOCRWrapper( - i.lggr. - Named("CCIPBootstrap"). - Named(destRelayID.String()). - Named(config.Config.ChainSelector.String()). - Named(hexutil.Encode(config.Config.OfframpAddress)), - false, /* traceLogging */ - func(ctx context.Context, msg string) {}), - MonitoringEndpoint: i.monitoringEndpointGen.GenMonitoringEndpoint( - string(destChainFamily), - destRelayID.ChainID, - hexutil.Encode(config.Config.OfframpAddress), - synchronization.OCR3CCIPBootstrap, - ), - OffchainConfigDigester: ocrimpls.NewConfigDigester(config.ConfigDigest), - } - bootstrapper, err := libocr3.NewBootstrapper(bootstrapperArgs) - if err != nil { - return nil, err - } - return bootstrapper, nil +// Type implements types.OracleCreator. +func (i *pluginOracleCreator) Type() cctypes.OracleType { + return cctypes.OracleTypePlugin } -// CreatePluginOracle implements types.OracleCreator. -func (i *inprocessOracleCreator) CreatePluginOracle(pluginType cctypes.PluginType, config cctypes.OCR3ConfigWithMeta) (cctypes.CCIPOracle, error) { +// Create implements types.OracleCreator. +func (i *pluginOracleCreator) Create(config cctypes.OCR3ConfigWithMeta) (cctypes.CCIPOracle, error) { + pluginType := cctypes.PluginType(config.Config.PluginType) + // Assuming that the chain selector is referring to an evm chain for now. // TODO: add an api that returns chain family. destChainID, err := chainsel.ChainIdFromSelector(uint64(config.Config.ChainSelector)) @@ -172,7 +137,141 @@ func (i *inprocessOracleCreator) CreatePluginOracle(pluginType cctypes.PluginTyp execBatchGasLimit = execOffchainConfig.BatchGasLimit } - // this is so that we can use the msg hasher and report encoder from that dest chain relayer's provider. + contractReaders, chainWriters, err := i.createReadersAndWriters( + destChainID, + pluginType, + config, + execBatchGasLimit, + ) + if err != nil { + return nil, fmt.Errorf("failed to create readers and writers: %w", err) + } + + // build the onchain keyring. it will be the signing key for the destination chain family. + keybundle, ok := i.ocrKeyBundles[destChainFamily] + if !ok { + return nil, fmt.Errorf("no OCR key bundle found for chain family %s, forgot to create one?", destChainFamily) + } + onchainKeyring := ocrimpls.NewOnchainKeyring[[]byte](keybundle, i.lggr) + + // build the contract transmitter + // assume that we are using the first account in the keybundle as the from account + // and that we are able to transmit to the dest chain. + // TODO: revisit this in the future, since not all oracles will be able to transmit to the dest chain. + destChainWriter, ok := chainWriters[config.Config.ChainSelector] + if !ok { + return nil, fmt.Errorf("no chain writer found for dest chain selector %d, can't create contract transmitter", + config.Config.ChainSelector) + } + destFromAccounts, ok := i.transmitters[destRelayID] + if !ok { + return nil, fmt.Errorf("no transmitter found for dest relay ID %s, can't create contract transmitter", destRelayID) + } + + // TODO: Extract the correct transmitter address from the destsFromAccount + factory, transmitter, err := i.createFactoryAndTransmitter(config, destRelayID, contractReaders, chainWriters, destChainWriter, destFromAccounts) + if err != nil { + return nil, fmt.Errorf("failed to create factory and transmitter: %w", err) + } + + oracleArgs := libocr3.OCR3OracleArgs[[]byte]{ + BinaryNetworkEndpointFactory: i.peerWrapper.Peer2, + Database: i.db, + // NOTE: when specifying V2Bootstrappers here we actually do NOT need to run a full bootstrap node! + // Thus it is vital that the bootstrapper locators are correctly set in the job spec. + V2Bootstrappers: i.bootstrapperLocators, + ContractConfigTracker: configTracker, + ContractTransmitter: transmitter, + LocalConfig: defaultLocalConfig(), + Logger: ocrcommon.NewOCRWrapper( + i.lggr. + Named(fmt.Sprintf("CCIP%sOCR3", pluginType.String())). + Named(destRelayID.String()). + Named(hexutil.Encode(config.Config.OfframpAddress)), + false, + func(ctx context.Context, msg string) {}), + MetricsRegisterer: prometheus.WrapRegistererWith(map[string]string{"name": fmt.Sprintf("commit-%d", config.Config.ChainSelector)}, prometheus.DefaultRegisterer), + MonitoringEndpoint: i.monitoringEndpointGen.GenMonitoringEndpoint( + destChainFamily, + destRelayID.ChainID, + string(config.Config.OfframpAddress), + synchronization.OCR3CCIPCommit, + ), + OffchainConfigDigester: ocrimpls.NewConfigDigester(config.ConfigDigest), + OffchainKeyring: keybundle, + OnchainKeyring: onchainKeyring, + ReportingPluginFactory: factory, + } + oracle, err := libocr3.NewOracle(oracleArgs) + if err != nil { + return nil, err + } + return oracle, nil +} + +func (i *pluginOracleCreator) createFactoryAndTransmitter( + config cctypes.OCR3ConfigWithMeta, + destRelayID types.RelayID, + contractReaders map[cciptypes.ChainSelector]types.ContractReader, + chainWriters map[cciptypes.ChainSelector]types.ChainWriter, + destChainWriter types.ChainWriter, + destFromAccounts []string, +) (ocr3types.ReportingPluginFactory[[]byte], ocr3types.ContractTransmitter[[]byte], error) { + var factory ocr3types.ReportingPluginFactory[[]byte] + var transmitter ocr3types.ContractTransmitter[[]byte] + if config.Config.PluginType == uint8(cctypes.PluginTypeCCIPCommit) { + factory = commitocr3.NewPluginFactory( + i.lggr. + Named("CCIPCommitPlugin"). + Named(destRelayID.String()). + Named(fmt.Sprintf("%d", config.Config.ChainSelector)). + Named(hexutil.Encode(config.Config.OfframpAddress)), + ccipreaderpkg.OCR3ConfigWithMeta(config), + ccipevm.NewCommitPluginCodecV1(), + ccipevm.NewMessageHasherV1(), + i.homeChainReader, + contractReaders, + chainWriters, + ) + transmitter = ocrimpls.NewCommitContractTransmitter[[]byte](destChainWriter, + ocrtypes.Account(destFromAccounts[0]), + hexutil.Encode(config.Config.OfframpAddress), // TODO: this works for evm only, how about non-evm? + ) + } else if config.Config.PluginType == uint8(cctypes.PluginTypeCCIPExec) { + factory = execocr3.NewPluginFactory( + i.lggr. + Named("CCIPExecPlugin"). + Named(destRelayID.String()). + Named(hexutil.Encode(config.Config.OfframpAddress)), + ccipreaderpkg.OCR3ConfigWithMeta(config), + ccipevm.NewExecutePluginCodecV1(), + ccipevm.NewMessageHasherV1(), + i.homeChainReader, + superfakes.NewNilTokenDataReader(), + ccipevm.NewGasEstimateProvider(), + contractReaders, + chainWriters, + ) + transmitter = ocrimpls.NewExecContractTransmitter[[]byte](destChainWriter, + ocrtypes.Account(destFromAccounts[0]), + hexutil.Encode(config.Config.OfframpAddress), // TODO: this works for evm only, how about non-evm? + ) + } else { + return nil, nil, fmt.Errorf("unsupported plugin type %d", config.Config.PluginType) + } + return factory, transmitter, nil +} + +func (i *pluginOracleCreator) createReadersAndWriters( + destChainID uint64, + pluginType cctypes.PluginType, + config cctypes.OCR3ConfigWithMeta, + execBatchGasLimit uint64, +) ( + map[cciptypes.ChainSelector]types.ContractReader, + map[cciptypes.ChainSelector]types.ChainWriter, + error, +) { contractReaders := make(map[cciptypes.ChainSelector]types.ContractReader) chainWriters := make(map[cciptypes.ChainSelector]types.ChainWriter) for _, chain := range i.chains.Slice() { @@ -194,7 +293,7 @@ func (i *inprocessOracleCreator) CreatePluginOracle(pluginType cctypes.PluginTyp chainReaderConfig, ) if err2 != nil { - return nil, fmt.Errorf("failed to create contract reader for chain %s: %w", chain.ID(), err2) + return nil, nil, fmt.Errorf("failed to create contract reader for chain %s: %w", chain.ID(), err2) } if chain.ID().Uint64() == destChainID { @@ -207,7 +306,7 @@ func (i *inprocessOracleCreator) CreatePluginOracle(pluginType cctypes.PluginTyp }, }) if err3 != nil { - return nil, fmt.Errorf("failed to bind chain reader for dest chain %s's offramp at %s: %w", chain.ID(), offrampAddressHex, err3) + return nil, nil, fmt.Errorf("failed to bind chain reader for dest chain %s's offramp at %s: %w", chain.ID(), offrampAddressHex, err3) } } @@ -215,7 +314,7 @@ func (i *inprocessOracleCreator) CreatePluginOracle(pluginType cctypes.PluginTyp // maybe from the plugin directly? err2 = cr.Start(context.Background()) if err2 != nil { - return nil, fmt.Errorf("failed to start contract reader for chain %s: %w", chain.ID(), err2) + return nil, nil, fmt.Errorf("failed to start contract reader for chain %s: %w", chain.ID(), err2) } // Even though we only write to the dest chain, we need to create chain writers for all chains @@ -240,121 +339,25 @@ func (i *inprocessOracleCreator) CreatePluginOracle(pluginType cctypes.PluginTyp ), ) if err2 != nil { - return nil, fmt.Errorf("failed to create chain writer for chain %s: %w", chain.ID(), err2) + return nil, nil, fmt.Errorf("failed to create chain writer for chain %s: %w", chain.ID(), err2) } // TODO: figure out shutdown. // maybe from the plugin directly? err2 = cw.Start(context.Background()) if err2 != nil { - return nil, fmt.Errorf("failed to start chain writer for chain %s: %w", chain.ID(), err2) + return nil, nil, fmt.Errorf("failed to start chain writer for chain %s: %w", chain.ID(), err2) } chainSelector, ok := chainsel.EvmChainIdToChainSelector()[chain.ID().Uint64()] if !ok { - return nil, fmt.Errorf("failed to get chain selector from chain ID %s", chain.ID()) + return nil, nil, fmt.Errorf("failed to get chain selector from chain ID %s", chain.ID()) } contractReaders[cciptypes.ChainSelector(chainSelector)] = cr chainWriters[cciptypes.ChainSelector(chainSelector)] = cw } - - // build the onchain keyring. it will be the signing key for the destination chain family. - keybundle, ok := i.ocrKeyBundles[destChainFamily] - if !ok { - return nil, fmt.Errorf("no OCR key bundle found for chain family %s, forgot to create one?", destChainFamily) - } - onchainKeyring := ocrimpls.NewOnchainKeyring[[]byte](keybundle, i.lggr) - - // build the contract transmitter - // assume that we are using the first account in the keybundle as the from account - // and that we are able to transmit to the dest chain. - // TODO: revisit this in the future, since not all oracles will be able to transmit to the dest chain. - destChainWriter, ok := chainWriters[config.Config.ChainSelector] - if !ok { - return nil, fmt.Errorf("no chain writer found for dest chain selector %d, can't create contract transmitter", - config.Config.ChainSelector) - } - destFromAccounts, ok := i.transmitters[destRelayID] - if !ok { - return nil, fmt.Errorf("no transmitter found for dest relay ID %s, can't create contract transmitter", destRelayID) - } - - // TODO: Extract the correct transmitter address from the destsFromAccount - var factory ocr3types.ReportingPluginFactory[[]byte] - var transmitter ocr3types.ContractTransmitter[[]byte] - if config.Config.PluginType == uint8(cctypes.PluginTypeCCIPCommit) { - factory = commitocr3.NewPluginFactory( - i.lggr. - Named("CCIPCommitPlugin"). - Named(destRelayID.String()). - Named(fmt.Sprintf("%d", config.Config.ChainSelector)). - Named(hexutil.Encode(config.Config.OfframpAddress)), - ccipreaderpkg.OCR3ConfigWithMeta(config), - ccipevm.NewCommitPluginCodecV1(), - ccipevm.NewMessageHasherV1(), - i.homeChainReader, - contractReaders, - chainWriters, - ) - transmitter = ocrimpls.NewCommitContractTransmitter[[]byte](destChainWriter, - ocrtypes.Account(destFromAccounts[0]), - hexutil.Encode(config.Config.OfframpAddress), // TODO: this works for evm only, how about non-evm? - ) - } else if config.Config.PluginType == uint8(cctypes.PluginTypeCCIPExec) { - factory = execocr3.NewPluginFactory( - i.lggr. - Named("CCIPExecPlugin"). - Named(destRelayID.String()). - Named(hexutil.Encode(config.Config.OfframpAddress)), - ccipreaderpkg.OCR3ConfigWithMeta(config), - ccipevm.NewExecutePluginCodecV1(), - ccipevm.NewMessageHasherV1(), - i.homeChainReader, - superfakes.NewNilTokenDataReader(), - ccipevm.NewGasEstimateProvider(), // TODO: this works for evm only, how about non-evm? - contractReaders, - chainWriters, - ) - transmitter = ocrimpls.NewExecContractTransmitter[[]byte](destChainWriter, - ocrtypes.Account(destFromAccounts[0]), - hexutil.Encode(config.Config.OfframpAddress), // TODO: this works for evm only, how about non-evm? - ) - } else { - return nil, fmt.Errorf("unsupported plugin type %d", config.Config.PluginType) - } - - oracleArgs := libocr3.OCR3OracleArgs[[]byte]{ - BinaryNetworkEndpointFactory: i.peerWrapper.Peer2, - Database: i.db, - V2Bootstrappers: i.bootstrapperLocators, - ContractConfigTracker: configTracker, - ContractTransmitter: transmitter, - LocalConfig: defaultLocalConfig(), - Logger: ocrcommon.NewOCRWrapper( - i.lggr. - Named(fmt.Sprintf("CCIP%sOCR3", pluginType.String())). - Named(destRelayID.String()). - Named(hexutil.Encode(config.Config.OfframpAddress)), - false, - func(ctx context.Context, msg string) {}), - MetricsRegisterer: prometheus.WrapRegistererWith(map[string]string{"name": fmt.Sprintf("commit-%d", config.Config.ChainSelector)}, prometheus.DefaultRegisterer), - MonitoringEndpoint: i.monitoringEndpointGen.GenMonitoringEndpoint( - destChainFamily, - destRelayID.ChainID, - string(config.Config.OfframpAddress), - synchronization.OCR3CCIPCommit, - ), - OffchainConfigDigester: ocrimpls.NewConfigDigester(config.ConfigDigest), - OffchainKeyring: keybundle, - OnchainKeyring: onchainKeyring, - ReportingPluginFactory: factory, - } - oracle, err := libocr3.NewOracle(oracleArgs) - if err != nil { - return nil, err - } - return oracle, nil + return contractReaders, chainWriters, nil } func defaultLocalConfig() ocrtypes.LocalConfig { diff --git a/core/capabilities/ccip/types/mocks/oracle_creator.go b/core/capabilities/ccip/types/mocks/oracle_creator.go index d83ad042bf..1d327e9652 100644 --- a/core/capabilities/ccip/types/mocks/oracle_creator.go +++ b/core/capabilities/ccip/types/mocks/oracle_creator.go @@ -20,12 +20,12 @@ func (_m *OracleCreator) EXPECT() *OracleCreator_Expecter { return &OracleCreator_Expecter{mock: &_m.Mock} } -// CreateBootstrapOracle provides a mock function with given fields: config -func (_m *OracleCreator) CreateBootstrapOracle(config types.OCR3ConfigWithMeta) (types.CCIPOracle, error) { +// Create provides a mock function with given fields: config +func (_m *OracleCreator) Create(config types.OCR3ConfigWithMeta) (types.CCIPOracle, error) { ret := _m.Called(config) if len(ret) == 0 { - panic("no return value specified for CreateBootstrapOracle") + panic("no return value specified for Create") } var r0 types.CCIPOracle @@ -50,89 +50,75 @@ func (_m *OracleCreator) CreateBootstrapOracle(config types.OCR3ConfigWithMeta) return r0, r1 } -// OracleCreator_CreateBootstrapOracle_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CreateBootstrapOracle' -type OracleCreator_CreateBootstrapOracle_Call struct { +// OracleCreator_Create_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Create' +type OracleCreator_Create_Call struct { *mock.Call } -// CreateBootstrapOracle is a helper method to define mock.On call +// Create is a helper method to define mock.On call // - config types.OCR3ConfigWithMeta -func (_e *OracleCreator_Expecter) CreateBootstrapOracle(config interface{}) *OracleCreator_CreateBootstrapOracle_Call { - return &OracleCreator_CreateBootstrapOracle_Call{Call: _e.mock.On("CreateBootstrapOracle", config)} +func (_e *OracleCreator_Expecter) Create(config interface{}) *OracleCreator_Create_Call { + return &OracleCreator_Create_Call{Call: _e.mock.On("Create", config)} } -func (_c *OracleCreator_CreateBootstrapOracle_Call) Run(run func(config types.OCR3ConfigWithMeta)) *OracleCreator_CreateBootstrapOracle_Call { +func (_c *OracleCreator_Create_Call) Run(run func(config types.OCR3ConfigWithMeta)) *OracleCreator_Create_Call { _c.Call.Run(func(args mock.Arguments) { run(args[0].(types.OCR3ConfigWithMeta)) }) return _c } -func (_c *OracleCreator_CreateBootstrapOracle_Call) Return(_a0 types.CCIPOracle, _a1 error) *OracleCreator_CreateBootstrapOracle_Call { +func (_c *OracleCreator_Create_Call) Return(_a0 types.CCIPOracle, _a1 error) *OracleCreator_Create_Call { _c.Call.Return(_a0, _a1) return _c } -func (_c *OracleCreator_CreateBootstrapOracle_Call) RunAndReturn(run func(types.OCR3ConfigWithMeta) (types.CCIPOracle, error)) *OracleCreator_CreateBootstrapOracle_Call { +func (_c *OracleCreator_Create_Call) RunAndReturn(run func(types.OCR3ConfigWithMeta) (types.CCIPOracle, error)) *OracleCreator_Create_Call { _c.Call.Return(run) return _c } -// CreatePluginOracle provides a mock function with given fields: pluginType, config -func (_m *OracleCreator) CreatePluginOracle(pluginType types.PluginType, config types.OCR3ConfigWithMeta) (types.CCIPOracle, error) { - ret := _m.Called(pluginType, config) +// Type provides a mock function with given fields: +func (_m *OracleCreator) Type() types.OracleType { + ret := _m.Called() if len(ret) == 0 { - panic("no return value specified for CreatePluginOracle") + panic("no return value specified for Type") } - var r0 types.CCIPOracle - var r1 error - if rf, ok := ret.Get(0).(func(types.PluginType, types.OCR3ConfigWithMeta) (types.CCIPOracle, error)); ok { - return rf(pluginType, config) - } - if rf, ok := ret.Get(0).(func(types.PluginType, types.OCR3ConfigWithMeta) types.CCIPOracle); ok { - r0 = rf(pluginType, config) + var r0 types.OracleType + if rf, ok := ret.Get(0).(func() types.OracleType); ok { + r0 = rf() } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(types.CCIPOracle) - } + r0 = ret.Get(0).(types.OracleType) } - if rf, ok := ret.Get(1).(func(types.PluginType, types.OCR3ConfigWithMeta) error); ok { - r1 = rf(pluginType, config) - } else { - r1 = ret.Error(1) - } - - return r0, r1 + return r0 } -// OracleCreator_CreatePluginOracle_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CreatePluginOracle' -type OracleCreator_CreatePluginOracle_Call struct { +// OracleCreator_Type_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Type' +type OracleCreator_Type_Call struct { *mock.Call } -// CreatePluginOracle is a helper method to define mock.On call -// - pluginType types.PluginType -// - config types.OCR3ConfigWithMeta -func (_e *OracleCreator_Expecter) CreatePluginOracle(pluginType interface{}, config interface{}) *OracleCreator_CreatePluginOracle_Call { - return &OracleCreator_CreatePluginOracle_Call{Call: _e.mock.On("CreatePluginOracle", pluginType, config)} +// Type is a helper method to define mock.On call +func (_e *OracleCreator_Expecter) Type() *OracleCreator_Type_Call { + return &OracleCreator_Type_Call{Call: _e.mock.On("Type")} } -func (_c *OracleCreator_CreatePluginOracle_Call) Run(run func(pluginType types.PluginType, config types.OCR3ConfigWithMeta)) *OracleCreator_CreatePluginOracle_Call { +func (_c *OracleCreator_Type_Call) Run(run func()) *OracleCreator_Type_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(types.PluginType), args[1].(types.OCR3ConfigWithMeta)) + run() }) return _c } -func (_c *OracleCreator_CreatePluginOracle_Call) Return(_a0 types.CCIPOracle, _a1 error) *OracleCreator_CreatePluginOracle_Call { - _c.Call.Return(_a0, _a1) +func (_c *OracleCreator_Type_Call) Return(_a0 types.OracleType) *OracleCreator_Type_Call { + _c.Call.Return(_a0) return _c } -func (_c *OracleCreator_CreatePluginOracle_Call) RunAndReturn(run func(types.PluginType, types.OCR3ConfigWithMeta) (types.CCIPOracle, error)) *OracleCreator_CreatePluginOracle_Call { +func (_c *OracleCreator_Type_Call) RunAndReturn(run func() types.OracleType) *OracleCreator_Type_Call { _c.Call.Return(run) return _c } diff --git a/core/capabilities/ccip/types/types.go b/core/capabilities/ccip/types/types.go index 952b8fe446..e42990f4c4 100644 --- a/core/capabilities/ccip/types/types.go +++ b/core/capabilities/ccip/types/types.go @@ -27,6 +27,13 @@ func (pt PluginType) String() string { } } +type OracleType uint8 + +const ( + OracleTypePlugin OracleType = 0 + OracleTypeBootstrap OracleType = 1 +) + // CCIPOracle represents either a CCIP commit or exec oracle or a bootstrap node. type CCIPOracle interface { Close() error @@ -36,11 +43,12 @@ type CCIPOracle interface { // OracleCreator is an interface for creating CCIP oracles. // Whether the oracle uses a LOOPP or not is an implementation detail. type OracleCreator interface { - // CreatePlugin creates a new oracle that will run either the commit or exec ccip plugin. + // Create creates a new oracle that will run either the commit or exec ccip plugin, + // if its a plugin oracle, or a bootstrap oracle if its a bootstrap oracle. // The oracle must be returned unstarted. - CreatePluginOracle(pluginType PluginType, config OCR3ConfigWithMeta) (CCIPOracle, error) + Create(config OCR3ConfigWithMeta) (CCIPOracle, error) - // CreateBootstrapOracle creates a new bootstrap node with the given OCR config. - // The oracle must be returned unstarted. - CreateBootstrapOracle(config OCR3ConfigWithMeta) (CCIPOracle, error) + // Type returns the type of oracle that this creator creates. + // The only valid values are OracleTypePlugin and OracleTypeBootstrap. + Type() OracleType } diff --git a/core/capabilities/ccip/validate/validate.go b/core/capabilities/ccip/validate/validate.go index 04f4f4a495..02e1cb5c8e 100644 --- a/core/capabilities/ccip/validate/validate.go +++ b/core/capabilities/ccip/validate/validate.go @@ -40,9 +40,6 @@ func ValidatedCCIPSpec(tomlString string) (jb job.Job, err error) { if jb.CCIPSpec.P2PKeyID == "" { return job.Job{}, fmt.Errorf("p2pKeyID must be set") } - if len(jb.CCIPSpec.P2PV2Bootstrappers) == 0 { - return job.Job{}, fmt.Errorf("p2pV2Bootstrappers must be set") - } // ensure that the P2PV2Bootstrappers is in the right format. for _, bootstrapperLocator := range jb.CCIPSpec.P2PV2Bootstrappers { diff --git a/integration-tests/deployment/ccip/jobs.go b/integration-tests/deployment/ccip/jobs.go index f45fe4c553..923bda45f6 100644 --- a/integration-tests/deployment/ccip/jobs.go +++ b/integration-tests/deployment/ccip/jobs.go @@ -48,8 +48,17 @@ func NewCCIPJobSpecs(nodeIds []string, oc deployment.OffchainClient) (map[string if err != nil { return nil, err } + + // only set P2PV2Bootstrappers in the job spec if the node is a plugin node. + var p2pV2Bootstrappers []string + for _, chainConfig := range nodeChainConfigs.ChainConfigs { + if !chainConfig.Ocr2Config.IsBootstrap { + p2pV2Bootstrappers = bootstraps + break + } + } spec, err := validate.NewCCIPSpecToml(validate.SpecArgs{ - P2PV2Bootstrappers: bootstraps, + P2PV2Bootstrappers: p2pV2Bootstrappers, CapabilityVersion: CapabilityVersion, CapabilityLabelledName: CapabilityLabelledName, OCRKeyBundleIDs: map[string]string{ diff --git a/integration-tests/deployment/memory/environment.go b/integration-tests/deployment/memory/environment.go index d496d173c0..a6fa690135 100644 --- a/integration-tests/deployment/memory/environment.go +++ b/integration-tests/deployment/memory/environment.go @@ -71,15 +71,18 @@ func NewNodes(t *testing.T, logLevel zapcore.Level, chains map[uint64]deployment } } nodesByPeerID := make(map[string]Node) - ports := freeport.GetN(t, numNodes) - var existingNumBootstraps int + ports := freeport.GetN(t, numBootstraps+numNodes) + // bootstrap nodes must be separate nodes from plugin nodes, + // since we won't run a bootstrapper and a plugin oracle on the same + // chainlink node in production. + for i := 0; i < numBootstraps; i++ { + node := NewNode(t, ports[i], mchains, logLevel, true /* bootstrap */, registryConfig) + nodesByPeerID[node.Keys.PeerID.String()] = *node + // Note in real env, this ID is allocated by JD. + } for i := 0; i < numNodes; i++ { - bootstrap := false - if existingNumBootstraps < numBootstraps { - bootstrap = true - existingNumBootstraps++ - } - node := NewNode(t, ports[i], mchains, logLevel, bootstrap, registryConfig) + // grab port offset by numBootstraps, since above loop also takes some ports. + node := NewNode(t, ports[numBootstraps+i], mchains, logLevel, false /* bootstrap */, registryConfig) nodesByPeerID[node.Keys.PeerID.String()] = *node // Note in real env, this ID is allocated by JD. } From 28ee41a2fde991791fd4d711ba1e5346cb8f9843 Mon Sep 17 00:00:00 2001 From: Anindita Ghosh <88458927+AnieeG@users.noreply.github.com> Date: Thu, 29 Aug 2024 00:55:23 -0700 Subject: [PATCH 047/115] Update prod testnet config for Ethereum/Sepolia to have slower load frequency than other chains (#1339) ## Motivation ## Solution --------- Co-authored-by: Mateusz Sekara --- .../tomls/ccip1.4-stress/prod-testnet.toml | 35 ++++++++++--------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/integration-tests/ccip-tests/testconfig/tomls/ccip1.4-stress/prod-testnet.toml b/integration-tests/ccip-tests/testconfig/tomls/ccip1.4-stress/prod-testnet.toml index f8321584c8..7a6cf93f17 100644 --- a/integration-tests/ccip-tests/testconfig/tomls/ccip1.4-stress/prod-testnet.toml +++ b/integration-tests/ccip-tests/testconfig/tomls/ccip1.4-stress/prod-testnet.toml @@ -901,26 +901,23 @@ Data = """ """ [CCIP.Env] -TTL = '8h' +TTL = '2h' + +[CCIP.Env.NewCLCluster.Common.ChainlinkImage] +version = "ccip-develop" [CCIP.Env.Network] selected_networks = [ - 'ARBITRUM_SEPOLIA', - 'AVALANCHE_FUJI', - 'OPTIMISM_SEPOLIA', - 'BASE_SEPOLIA', - 'BSC_TESTNET', - 'WEMIX_TESTNET', - 'SEPOLIA', - 'POLYGON_AMOY', - 'KROMA_SEPOLIA', - 'BLAST_SEPOLIA' + 'AVALANCHE_FUJI', + 'OPTIMISM_SEPOLIA', + 'BASE_SEPOLIA', + 'SEPOLIA', ] [CCIP.Groups.load] NetworkPairs = [ - 'AVALANCHE_FUJI,SEPOLIA', - 'OPTIMISM_SEPOLIA,BASE_SEPOLIA' + 'AVALANCHE_FUJI,SEPOLIA', + 'OPTIMISM_SEPOLIA,BASE_SEPOLIA' ] BiDirectionalLane = true @@ -929,15 +926,21 @@ ExistingDeployment = true NoOfTokensPerChain = 1 +# 1msg/5sec = 12msg/min [CCIP.Groups.load.LoadProfile] -RequestPerUnitTime = [1] -TimeUnit = '5s' +RequestPerUnitTime = [12] +TimeUnit = '1m' TestDuration = '1h' TestRunName = 'v2.12.0-ccip1.4.16-load' +# There is slower exec rounds in Sepolia/Ethereum, therefore reducing the frequency +# 1msg/12sec = 5msg/min +[CCIP.Groups.load.LoadProfile.FrequencyByDestination.sepolia-testnet] +RequestPerUnitTime = [5] + # to represent 20%, 60%, 15%, 5% of the total messages [CCIP.Groups.load.LoadProfile.MsgProfile] -Frequencies = [4,12,3,1] +Frequencies = [4, 12, 3, 1] [[CCIP.Groups.load.LoadProfile.MsgProfile.MsgDetails]] MsgType = 'Token' From 181302f7c3f0d8b2a2f513b35401639f1f4a0bf7 Mon Sep 17 00:00:00 2001 From: Mateusz Sekara Date: Thu, 29 Aug 2024 10:11:04 +0200 Subject: [PATCH 048/115] Moving CCIP.Env.NewCLCluster.Common.ChainlinkImage to the common config (#1389) --- .../ccip-tests/testconfig/tomls/ccip-default.toml | 4 ++++ .../testconfig/tomls/ccip1.4-stress/prod-testnet.toml | 3 --- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/integration-tests/ccip-tests/testconfig/tomls/ccip-default.toml b/integration-tests/ccip-tests/testconfig/tomls/ccip-default.toml index 77dc97f77f..076c334e07 100644 --- a/integration-tests/ccip-tests/testconfig/tomls/ccip-default.toml +++ b/integration-tests/ccip-tests/testconfig/tomls/ccip-default.toml @@ -229,6 +229,10 @@ BlockHistorySize = 200 EIP1559FeeCapBufferBlocks = 0 """ +# Run by default using latest version from `ccip-develop` branch, override this value to use a specific version +[CCIP.Env.NewCLCluster.Common.ChainlinkImage] +version = "ccip-develop" + # the following configs are specific to each test type, smoke, load , chaos, etc... [CCIP.Groups] [CCIP.Groups.smoke] diff --git a/integration-tests/ccip-tests/testconfig/tomls/ccip1.4-stress/prod-testnet.toml b/integration-tests/ccip-tests/testconfig/tomls/ccip1.4-stress/prod-testnet.toml index 7a6cf93f17..917a739b18 100644 --- a/integration-tests/ccip-tests/testconfig/tomls/ccip1.4-stress/prod-testnet.toml +++ b/integration-tests/ccip-tests/testconfig/tomls/ccip1.4-stress/prod-testnet.toml @@ -903,9 +903,6 @@ Data = """ [CCIP.Env] TTL = '2h' -[CCIP.Env.NewCLCluster.Common.ChainlinkImage] -version = "ccip-develop" - [CCIP.Env.Network] selected_networks = [ 'AVALANCHE_FUJI', From 7c701482fe478a9cf2846e76a6b1068a4a4e2220 Mon Sep 17 00:00:00 2001 From: Rens Rooimans Date: Thu, 29 Aug 2024 13:02:54 +0200 Subject: [PATCH 049/115] assert fees can be set to zero (#1380) Assert we would have the option to set any of the fee components to zero if we would want. --------- Co-authored-by: app-token-issuer-infra-releng[bot] <120227048+app-token-issuer-infra-releng[bot]@users.noreply.github.com> --- contracts/gas-snapshots/ccip.gas-snapshot | 56 +++++++++---------- contracts/src/v0.8/ccip/FeeQuoter.sol | 5 +- .../v0.8/ccip/test/feeQuoter/FeeQuoter.t.sol | 2 +- .../v0.8/ccip/test/onRamp/EVM2EVMOnRamp.t.sol | 26 +++++++++ .../src/v0.8/ccip/test/onRamp/OnRamp.t.sol | 29 ++++++++++ .../ccip/generated/fee_quoter/fee_quoter.go | 4 +- ...rapper-dependency-versions-do-not-edit.txt | 2 +- 7 files changed, 89 insertions(+), 35 deletions(-) diff --git a/contracts/gas-snapshots/ccip.gas-snapshot b/contracts/gas-snapshots/ccip.gas-snapshot index e2c0c4ad78..97609ff3aa 100644 --- a/contracts/gas-snapshots/ccip.gas-snapshot +++ b/contracts/gas-snapshots/ccip.gas-snapshot @@ -252,6 +252,7 @@ EVM2EVMOnRamp_forwardFromRouter_upgrade:test_V2_Success() (gas: 95349) EVM2EVMOnRamp_getDataAvailabilityCost:test_EmptyMessageCalculatesDataAvailabilityCost_Success() (gas: 20544) EVM2EVMOnRamp_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCost_Success() (gas: 20912) EVM2EVMOnRamp_getFee:test_EmptyMessage_Success() (gas: 78230) +EVM2EVMOnRamp_getFee:test_GetFeeOfZeroForTokenMessage_Success() (gas: 81762) EVM2EVMOnRamp_getFee:test_HighGasMessage_Success() (gas: 234078) EVM2EVMOnRamp_getFee:test_MessageGasLimitTooHigh_Revert() (gas: 16715) EVM2EVMOnRamp_getFee:test_MessageTooLarge_Revert() (gas: 95271) @@ -343,10 +344,10 @@ FeeQuoter_applyTokenTransferFeeConfigUpdates:test_ApplyTokenTransferFeeConfig_Su FeeQuoter_applyTokenTransferFeeConfigUpdates:test_ApplyTokenTransferFeeZeroInput() (gas: 13089) FeeQuoter_applyTokenTransferFeeConfigUpdates:test_InvalidDestBytesOverhead_Revert() (gas: 17071) FeeQuoter_applyTokenTransferFeeConfigUpdates:test_OnlyCallableByOwnerOrAdmin_Revert() (gas: 12240) -FeeQuoter_constructor:test_InvalidLinkTokenEqZeroAddress_Revert() (gas: 107016) -FeeQuoter_constructor:test_InvalidMaxFeeJuelsPerMsg_Revert() (gas: 111366) -FeeQuoter_constructor:test_InvalidStalenessThreshold_Revert() (gas: 111419) -FeeQuoter_constructor:test_Setup_Success() (gas: 5336824) +FeeQuoter_constructor:test_InvalidLinkTokenEqZeroAddress_Revert() (gas: 107046) +FeeQuoter_constructor:test_InvalidMaxFeeJuelsPerMsg_Revert() (gas: 111396) +FeeQuoter_constructor:test_InvalidStalenessThreshold_Revert() (gas: 111449) +FeeQuoter_constructor:test_Setup_Success() (gas: 5358690) FeeQuoter_convertTokenAmount:test_ConvertTokenAmount_Success() (gas: 72739) FeeQuoter_convertTokenAmount:test_LinkTokenNotSupported_Revert() (gas: 30963) FeeQuoter_getDataAvailabilityCost:test_EmptyMessageCalculatesDataAvailabilityCost_Success() (gas: 94303) @@ -368,17 +369,17 @@ FeeQuoter_getTokenTransferCost:test_ZeroAmountTokenTransferChargesMinFeeAndGas_S FeeQuoter_getTokenTransferCost:test_ZeroFeeConfigChargesMinFee_Success() (gas: 40013) FeeQuoter_getTokenTransferCost:test_getTokenTransferCost_selfServeUsesDefaults_Success() (gas: 29299) FeeQuoter_getValidatedFee:test_DestinationChainNotEnabled_Revert() (gas: 18180) -FeeQuoter_getValidatedFee:test_EmptyMessage_Success() (gas: 81054) -FeeQuoter_getValidatedFee:test_EnforceOutOfOrder_Revert() (gas: 54294) -FeeQuoter_getValidatedFee:test_HighGasMessage_Success() (gas: 237472) -FeeQuoter_getValidatedFee:test_InvalidEVMAddress_Revert() (gas: 19949) -FeeQuoter_getValidatedFee:test_MessageGasLimitTooHigh_Revert() (gas: 31746) -FeeQuoter_getValidatedFee:test_MessageTooLarge_Revert() (gas: 97692) -FeeQuoter_getValidatedFee:test_MessageWithDataAndTokenTransfer_Success() (gas: 142833) -FeeQuoter_getValidatedFee:test_NotAFeeToken_Revert() (gas: 29407) -FeeQuoter_getValidatedFee:test_SingleTokenMessage_Success() (gas: 111861) -FeeQuoter_getValidatedFee:test_TooManyTokens_Revert() (gas: 20085) -FeeQuoter_getValidatedFee:test_ZeroDataAvailabilityMultiplier_Success() (gas: 61933) +FeeQuoter_getValidatedFee:test_EmptyMessage_Success() (gas: 85936) +FeeQuoter_getValidatedFee:test_EnforceOutOfOrder_Revert() (gas: 56735) +FeeQuoter_getValidatedFee:test_HighGasMessage_Success() (gas: 242354) +FeeQuoter_getValidatedFee:test_InvalidEVMAddress_Revert() (gas: 22390) +FeeQuoter_getValidatedFee:test_MessageGasLimitTooHigh_Revert() (gas: 34187) +FeeQuoter_getValidatedFee:test_MessageTooLarge_Revert() (gas: 100133) +FeeQuoter_getValidatedFee:test_MessageWithDataAndTokenTransfer_Success() (gas: 147715) +FeeQuoter_getValidatedFee:test_NotAFeeToken_Revert() (gas: 21043) +FeeQuoter_getValidatedFee:test_SingleTokenMessage_Success() (gas: 116743) +FeeQuoter_getValidatedFee:test_TooManyTokens_Revert() (gas: 22526) +FeeQuoter_getValidatedFee:test_ZeroDataAvailabilityMultiplier_Success() (gas: 64374) FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Above18Decimals_Success() (gas: 2094539) FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Below18Decimals_Success() (gas: 2094497) FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt0Decimals_Success() (gas: 2074616) @@ -564,8 +565,8 @@ MultiOCR3Base_transmit:test_UnAuthorizedTransmitter_Revert() (gas: 24191) MultiOCR3Base_transmit:test_UnauthorizedSigner_Revert() (gas: 61409) MultiOCR3Base_transmit:test_UnconfiguredPlugin_Revert() (gas: 39890) MultiOCR3Base_transmit:test_ZeroSignatures_Revert() (gas: 32973) -MultiOnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 410978) -MultiRampsE2E:test_E2E_3MessagesMMultiOffRampSuccess_gas() (gas: 1504783) +MultiOnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 414301) +MultiRampsE2E:test_E2E_3MessagesMMultiOffRampSuccess_gas() (gas: 1506106) NonceManager_NonceIncrementation:test_getIncrementedOutboundNonce_Success() (gas: 37907) NonceManager_NonceIncrementation:test_incrementInboundNonce_Skip() (gas: 23694) NonceManager_NonceIncrementation:test_incrementInboundNonce_Success() (gas: 38763) @@ -747,19 +748,15 @@ OffRamp_verify:test_NotBlessedWrongChainSelector_Success() (gas: 178754) OffRamp_verify:test_NotBlessed_Success() (gas: 141593) OffRamp_verify:test_TooManyLeaves_Revert() (gas: 51510) OnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 390336) -OnRamp_allowListConfigUpdates:test_applyAllowList_Success() (gas: 323566) OnRamp_allowListConfigUpdates:test_applyAllowList_Revert() (gas: 66509) -OnRamp_allowListConfigUpdates:test_setAllowListAdmin_ByNonOwner_Revert() (gas: 11833) -OnRamp_allowListConfigUpdates:test_setAllowListAdmin_Success() (gas: 36159) -OnRamp_applyDestChainConfigUpdates:test_ApplyDestChainConfigUpdates_WithInvalidChainSelector_Revert() (gas: 13242) +OnRamp_allowListConfigUpdates:test_applyAllowList_Success() (gas: 323566) OnRamp_applyDestChainConfigUpdates:test_ApplyDestChainConfigUpdates_Success() (gas: 64501) -OnRamp_applyDestChainConfigUpdates:test_ApplyDestChainConfigUpdates_WithInalidChainSelector_Revert() (gas: 13308) +OnRamp_applyDestChainConfigUpdates:test_ApplyDestChainConfigUpdates_WithInvalidChainSelector_Revert() (gas: 13242) OnRamp_constructor:test_Constructor_InvalidConfigChainSelectorEqZero_Revert() (gas: 94878) OnRamp_constructor:test_Constructor_InvalidConfigNonceManagerEqAddressZero_Revert() (gas: 92812) OnRamp_constructor:test_Constructor_InvalidConfigRMNProxyEqAddressZero_Revert() (gas: 97827) OnRamp_constructor:test_Constructor_InvalidConfigTokenAdminRegistryEqAddressZero_Revert() (gas: 92870) OnRamp_constructor:test_Constructor_Success() (gas: 2866937) -OnRamp_forwardFromRouter:test_CannotSendZeroTokens_Revert() (gas: 72097) OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() (gas: 115250) OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2_Success() (gas: 146019) OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessCustomExtraArgs() (gas: 145615) @@ -770,6 +767,7 @@ OnRamp_forwardFromRouter:test_ForwardFromRouter_Success_ConfigurableSourceRouter OnRamp_forwardFromRouter:test_InvalidExtraArgsTag_Revert() (gas: 28810) OnRamp_forwardFromRouter:test_MessageValidationError_Revert() (gas: 138683) OnRamp_forwardFromRouter:test_MesssageFeeTooHigh_Revert() (gas: 26910) +OnRamp_forwardFromRouter:test_MultiCannotSendZeroTokens_Revert() (gas: 74456) OnRamp_forwardFromRouter:test_OriginalSender_Revert() (gas: 12918) OnRamp_forwardFromRouter:test_Paused_Revert() (gas: 37224) OnRamp_forwardFromRouter:test_Permissions_Revert() (gas: 18179) @@ -782,19 +780,19 @@ OnRamp_forwardFromRouter:test_UnAllowedOriginalSender_Revert() (gas: 18609) OnRamp_forwardFromRouter:test_UnsupportedToken_Revert() (gas: 111118) OnRamp_forwardFromRouter:test_forwardFromRouter_UnsupportedToken_Revert() (gas: 76545) OnRamp_forwardFromRouter:test_forwardFromRouter_WithValidation_Success() (gas: 278740) -OnRamp_forwardFromRouter:test_MultiCannotSendZeroTokens_Revert() (gas: 74456) -OnRamp_getFee:test_EmptyMessage_Success() (gas: 104331) -OnRamp_getFee:test_EnforceOutOfOrder_Revert() (gas: 73163) -OnRamp_getFee:test_SingleTokenMessage_Success() (gas: 119655) +OnRamp_getFee:test_EmptyMessage_Success() (gas: 110107) +OnRamp_getFee:test_EnforceOutOfOrder_Revert() (gas: 75610) +OnRamp_getFee:test_GetFeeOfZeroForTokenMessage_Success() (gas: 95456) +OnRamp_getFee:test_NotAFeeTokenButPricedToken_Revert() (gas: 41814) +OnRamp_getFee:test_SingleTokenMessage_Success() (gas: 125476) OnRamp_getFee:test_Unhealthy_Revert() (gas: 43669) OnRamp_getSupportedTokens:test_GetSupportedTokens_Revert() (gas: 10438) OnRamp_getTokenPool:test_GetTokenPool_Success() (gas: 35204) OnRamp_setDynamicConfig:test_SetConfigInvalidConfigFeeAggregatorEqAddressZero_Revert() (gas: 11402) -OnRamp_setDynamicConfig:test_SetConfigInvalidConfigPriceRegistryEqAddressZero_Revert() (gas: 12978) +OnRamp_setDynamicConfig:test_SetConfigInvalidConfigFeeQuoterEqAddressZero_Revert() (gas: 13001) OnRamp_setDynamicConfig:test_SetConfigInvalidConfig_Revert() (gas: 11359) OnRamp_setDynamicConfig:test_SetConfigOnlyOwner_Revert() (gas: 16385) OnRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 55321) -OnRamp_setDynamicConfig:test_SetConfigInvalidConfigFeeQuoterEqAddressZero_Revert() (gas: 13001) OnRamp_withdrawFeeTokens:test_WithdrawFeeTokens_Success() (gas: 97107) PingPong_ccipReceive:test_CcipReceive_Success() (gas: 150169) PingPong_plumbing:test_OutOfOrderExecution_Success() (gas: 20277) diff --git a/contracts/src/v0.8/ccip/FeeQuoter.sol b/contracts/src/v0.8/ccip/FeeQuoter.sol index c2a7231d96..aea632fc4e 100644 --- a/contracts/src/v0.8/ccip/FeeQuoter.sol +++ b/contracts/src/v0.8/ccip/FeeQuoter.sol @@ -28,6 +28,7 @@ contract FeeQuoter is AuthorizedCallers, IFeeQuoter, ITypeAndVersion, IReceiver, using KeystoneFeedDefaultMetadataLib for bytes; error TokenNotSupported(address token); + error FeeTokenNotSupported(address token); error ChainNotSupported(uint64 chain); error StaleGasPrice(uint64 destChainSelector, uint256 threshold, uint256 timePassed); error StaleKeystoneUpdate(address token, uint256 feedTimestamp, uint256 storedTimeStamp); @@ -147,7 +148,7 @@ contract FeeQuoter is AuthorizedCallers, IFeeQuoter, ITypeAndVersion, IReceiver, /// applyPremiumMultiplierWeiPerEthUpdates to set the mapping struct PremiumMultiplierWeiPerEthArgs { address token; // // ───────────────────╮ Token address - uint64 premiumMultiplierWeiPerEth; // ──╯ Multiplier for destination chain specific premiums. Should never be 0 so can be used as an isEnabled flag + uint64 premiumMultiplierWeiPerEth; // ──╯ Multiplier for destination chain specific premiums. } string public constant override typeAndVersion = "FeeQuoter 1.6.0-dev"; @@ -174,7 +175,6 @@ contract FeeQuoter is AuthorizedCallers, IFeeQuoter, ITypeAndVersion, IReceiver, mapping(address token => IFeeQuoter.TokenPriceFeedConfig dataFeedAddress) private s_usdPriceFeedsPerToken; /// @dev The multiplier for destination chain specific premiums that can be set by the owner or fee admin - /// This should never be 0 once set, so it can be used as an isEnabled flag mapping(address token => uint64 premiumMultiplierWeiPerEth) internal s_premiumMultiplierWeiPerEth; /// @dev The destination chain specific fee configs @@ -473,6 +473,7 @@ contract FeeQuoter is AuthorizedCallers, IFeeQuoter, ITypeAndVersion, IReceiver, ) external view returns (uint256 feeTokenAmount) { DestChainConfig memory destChainConfig = s_destChainConfigs[destChainSelector]; if (!destChainConfig.isEnabled) revert DestinationChainNotEnabled(destChainSelector); + if (!s_feeTokens.contains(message.feeToken)) revert FeeTokenNotSupported(message.feeToken); uint256 numberOfTokens = message.tokenAmounts.length; _validateMessage(destChainConfig, message.data.length, numberOfTokens, message.receiver); diff --git a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.t.sol b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.t.sol index 11836b3d7b..cdbf1cef7a 100644 --- a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.t.sol +++ b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.t.sol @@ -1706,7 +1706,7 @@ contract FeeQuoter_getValidatedFee is FeeQuoterFeeSetup { Client.EVM2AnyMessage memory message = _generateSingleTokenMessage(notAFeeToken, 1); message.feeToken = notAFeeToken; - vm.expectRevert(abi.encodeWithSelector(FeeQuoter.TokenNotSupported.selector, notAFeeToken)); + vm.expectRevert(abi.encodeWithSelector(FeeQuoter.FeeTokenNotSupported.selector, notAFeeToken)); s_feeQuoter.getValidatedFee(DEST_CHAIN_SELECTOR, message); } diff --git a/contracts/src/v0.8/ccip/test/onRamp/EVM2EVMOnRamp.t.sol b/contracts/src/v0.8/ccip/test/onRamp/EVM2EVMOnRamp.t.sol index 7b400c0df6..f0cd0f80ed 100644 --- a/contracts/src/v0.8/ccip/test/onRamp/EVM2EVMOnRamp.t.sol +++ b/contracts/src/v0.8/ccip/test/onRamp/EVM2EVMOnRamp.t.sol @@ -1407,6 +1407,32 @@ contract EVM2EVMOnRamp_getFee is EVM2EVMOnRamp_getFeeSetup { } } + function test_GetFeeOfZeroForTokenMessage_Success() public { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + + uint256 feeAmount = s_onRamp.getFee(DEST_CHAIN_SELECTOR, message); + assertTrue(feeAmount > 0); + + EVM2EVMOnRamp.FeeTokenConfigArgs[] memory feeTokenConfigArgs = new EVM2EVMOnRamp.FeeTokenConfigArgs[](1); + feeTokenConfigArgs[0] = EVM2EVMOnRamp.FeeTokenConfigArgs({ + token: message.feeToken, + networkFeeUSDCents: 0, + gasMultiplierWeiPerEth: 0, + premiumMultiplierWeiPerEth: 0, + enabled: true + }); + + s_onRamp.setFeeTokenConfig(feeTokenConfigArgs); + EVM2EVMOnRamp.DynamicConfig memory config = + generateDynamicOnRampConfig(address(s_sourceRouter), address(s_feeQuoter)); + config.destDataAvailabilityMultiplierBps = 0; + + s_onRamp.setDynamicConfig(config); + + feeAmount = s_onRamp.getFee(DEST_CHAIN_SELECTOR, message); + assertEq(0, feeAmount); + } + function test_ZeroDataAvailabilityMultiplier_Success() public { EVM2EVMOnRamp.DynamicConfig memory dynamicConfig = s_onRamp.getDynamicConfig(); dynamicConfig.destDataAvailabilityMultiplierBps = 0; diff --git a/contracts/src/v0.8/ccip/test/onRamp/OnRamp.t.sol b/contracts/src/v0.8/ccip/test/onRamp/OnRamp.t.sol index f69a4eafec..a6f4205ee1 100644 --- a/contracts/src/v0.8/ccip/test/onRamp/OnRamp.t.sol +++ b/contracts/src/v0.8/ccip/test/onRamp/OnRamp.t.sol @@ -609,6 +609,26 @@ contract OnRamp_getFee is OnRampSetup { } } + function test_GetFeeOfZeroForTokenMessage_Success() public { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + + uint256 feeAmount = s_onRamp.getFee(DEST_CHAIN_SELECTOR, message); + assertTrue(feeAmount > 0); + + FeeQuoter.PremiumMultiplierWeiPerEthArgs[] memory tokenMults = new FeeQuoter.PremiumMultiplierWeiPerEthArgs[](1); + tokenMults[0] = FeeQuoter.PremiumMultiplierWeiPerEthArgs({token: message.feeToken, premiumMultiplierWeiPerEth: 0}); + s_feeQuoter.applyPremiumMultiplierWeiPerEthUpdates(tokenMults); + + FeeQuoter.DestChainConfigArgs[] memory destChainConfigArgs = _generateFeeQuoterDestChainConfigArgs(); + destChainConfigArgs[0].destChainConfig.destDataAvailabilityMultiplierBps = 0; + destChainConfigArgs[0].destChainConfig.gasMultiplierWeiPerEth = 0; + s_feeQuoter.applyDestChainConfigUpdates(destChainConfigArgs); + + feeAmount = s_onRamp.getFee(DEST_CHAIN_SELECTOR, message); + + assertEq(0, feeAmount); + } + // Reverts function test_Unhealthy_Revert() public { @@ -634,6 +654,15 @@ contract OnRamp_getFee is OnRampSetup { vm.expectRevert(FeeQuoter.ExtraArgOutOfOrderExecutionMustBeTrue.selector); s_onRamp.getFee(DEST_CHAIN_SELECTOR, message); } + + function test_NotAFeeTokenButPricedToken_Revert() public { + Client.EVM2AnyMessage memory message = _generateEmptyMessage(); + message.feeToken = s_sourceTokens[1]; + + vm.expectRevert(abi.encodeWithSelector(FeeQuoter.FeeTokenNotSupported.selector, message.feeToken)); + + s_onRamp.getFee(DEST_CHAIN_SELECTOR, message); + } } contract OnRamp_setDynamicConfig is OnRampSetup { diff --git a/core/gethwrappers/ccip/generated/fee_quoter/fee_quoter.go b/core/gethwrappers/ccip/generated/fee_quoter/fee_quoter.go index 74ed33b73a..807a932da6 100644 --- a/core/gethwrappers/ccip/generated/fee_quoter/fee_quoter.go +++ b/core/gethwrappers/ccip/generated/fee_quoter/fee_quoter.go @@ -154,8 +154,8 @@ type KeystoneFeedsPermissionHandlerPermission struct { } var FeeQuoterMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint96\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"linkToken\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"stalenessThreshold\",\"type\":\"uint32\"}],\"internalType\":\"structFeeQuoter.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"priceUpdaters\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"feeTokens\",\"type\":\"address[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"}],\"internalType\":\"structIFeeQuoter.TokenPriceFeedConfig\",\"name\":\"feedConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.TokenPriceFeedUpdate[]\",\"name\":\"tokenPriceFeeds\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigSingleTokenArgs[]\",\"name\":\"tokenTransferFeeConfigs\",\"type\":\"tuple[]\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigArgs[]\",\"name\":\"tokenTransferFeeConfigArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"internalType\":\"structFeeQuoter.PremiumMultiplierWeiPerEthArgs[]\",\"name\":\"premiumMultiplierWeiPerEthArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chain\",\"type\":\"uint64\"}],\"name\":\"ChainNotSupported\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DataFeedValueOutOfUint224Range\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"DestinationChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ExtraArgOutOfOrderExecutionMustBeTrue\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"}],\"name\":\"InvalidDestBytesOverhead\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidDestChainConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidEVMAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidExtraArgsTag\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidStaticConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"msgFeeJuels\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint256\"}],\"name\":\"MessageFeeTooHigh\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MessageGasLimitTooHigh\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"maxSize\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualSize\",\"type\":\"uint256\"}],\"name\":\"MessageTooLarge\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"internalType\":\"bytes10\",\"name\":\"workflowName\",\"type\":\"bytes10\"},{\"internalType\":\"bytes2\",\"name\":\"reportName\",\"type\":\"bytes2\"}],\"name\":\"ReportForwarderUnauthorized\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"SourceTokenDataTooLarge\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"threshold\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timePassed\",\"type\":\"uint256\"}],\"name\":\"StaleGasPrice\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feedTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"storedTimeStamp\",\"type\":\"uint256\"}],\"name\":\"StaleKeystoneUpdate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"TokenNotSupported\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"UnauthorizedCaller\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnsupportedNumberOfTokens\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"AuthorizedCallerAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"AuthorizedCallerRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"indexed\":false,\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"name\":\"DestChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"indexed\":false,\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"name\":\"DestChainConfigUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"}],\"name\":\"FeeTokenAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"}],\"name\":\"FeeTokenRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"name\":\"PremiumMultiplierWeiPerEthUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"}],\"indexed\":false,\"internalType\":\"structIFeeQuoter.TokenPriceFeedConfig\",\"name\":\"priceFeedConfig\",\"type\":\"tuple\"}],\"name\":\"PriceFeedPerTokenUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"reportId\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"},{\"internalType\":\"bytes10\",\"name\":\"workflowName\",\"type\":\"bytes10\"},{\"internalType\":\"bytes2\",\"name\":\"reportName\",\"type\":\"bytes2\"},{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isAllowed\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"structKeystoneFeedsPermissionHandler.Permission\",\"name\":\"permission\",\"type\":\"tuple\"}],\"name\":\"ReportPermissionSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"TokenTransferFeeConfigDeleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"name\":\"TokenTransferFeeConfigUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"UsdPerTokenUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChain\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"UsdPerUnitGasUpdated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address[]\",\"name\":\"addedCallers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"removedCallers\",\"type\":\"address[]\"}],\"internalType\":\"structAuthorizedCallers.AuthorizedCallerArgs\",\"name\":\"authorizedCallerArgs\",\"type\":\"tuple\"}],\"name\":\"applyAuthorizedCallerUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyDestChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"feeTokensToAdd\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"feeTokensToRemove\",\"type\":\"address[]\"}],\"name\":\"applyFeeTokensUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"internalType\":\"structFeeQuoter.PremiumMultiplierWeiPerEthArgs[]\",\"name\":\"premiumMultiplierWeiPerEthArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyPremiumMultiplierWeiPerEthUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigSingleTokenArgs[]\",\"name\":\"tokenTransferFeeConfigs\",\"type\":\"tuple[]\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigArgs[]\",\"name\":\"tokenTransferFeeConfigArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigRemoveArgs[]\",\"name\":\"tokensToUseDefaultFeeConfigs\",\"type\":\"tuple[]\"}],\"name\":\"applyTokenTransferFeeConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"fromToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fromTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"toToken\",\"type\":\"address\"}],\"name\":\"convertTokenAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllAuthorizedCallers\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getDestChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getDestinationChainGasPrice\",\"outputs\":[{\"components\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"internalType\":\"structInternal.TimestampedPackedUint224\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getFeeTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getPremiumMultiplierWeiPerEth\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint96\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"linkToken\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"stalenessThreshold\",\"type\":\"uint32\"}],\"internalType\":\"structFeeQuoter.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getTokenAndGasPrices\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"tokenPrice\",\"type\":\"uint224\"},{\"internalType\":\"uint224\",\"name\":\"gasPriceValue\",\"type\":\"uint224\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenPrice\",\"outputs\":[{\"components\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"internalType\":\"structInternal.TimestampedPackedUint224\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenPriceFeedConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"}],\"internalType\":\"structIFeeQuoter.TokenPriceFeedConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"tokens\",\"type\":\"address[]\"}],\"name\":\"getTokenPrices\",\"outputs\":[{\"components\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"internalType\":\"structInternal.TimestampedPackedUint224[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenTransferFeeConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"getValidatedFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getValidatedTokenPrice\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"\",\"type\":\"uint224\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"onReport\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"name\":\"processMessageArgs\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"msgFeeJuels\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isOutOfOrderExecution\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"convertedExtraArgs\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"rampTokenAmounts\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"sourceTokenAmounts\",\"type\":\"tuple[]\"}],\"name\":\"processPoolReturnData\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"destExecDataPerToken\",\"type\":\"bytes[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"},{\"internalType\":\"bytes10\",\"name\":\"workflowName\",\"type\":\"bytes10\"},{\"internalType\":\"bytes2\",\"name\":\"reportName\",\"type\":\"bytes2\"},{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isAllowed\",\"type\":\"bool\"}],\"internalType\":\"structKeystoneFeedsPermissionHandler.Permission[]\",\"name\":\"permissions\",\"type\":\"tuple[]\"}],\"name\":\"setReportPermissions\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"}],\"name\":\"updatePrices\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"}],\"internalType\":\"structIFeeQuoter.TokenPriceFeedConfig\",\"name\":\"feedConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.TokenPriceFeedUpdate[]\",\"name\":\"tokenPriceFeedUpdates\",\"type\":\"tuple[]\"}],\"name\":\"updateTokenPriceFeeds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x60e06040523480156200001157600080fd5b50604051620076d8380380620076d8833981016040819052620000349162001834565b8533806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf8162000207565b5050604080518082018252838152815160008152602080820190935291810191909152620000ee9150620002b2565b5060208701516001600160a01b0316158062000112575086516001600160601b0316155b80620001265750604087015163ffffffff16155b15620001455760405163d794ef9560e01b815260040160405180910390fd5b6020878101516001600160a01b031660a05287516001600160601b031660805260408089015163ffffffff1660c05280516000815291820190526200018c90869062000401565b620001978462000549565b620001a2816200061a565b620001ad8262000a5a565b60408051600080825260208201909252620001fa91859190620001f3565b6040805180820190915260008082526020820152815260200190600190039081620001cb5790505b5062000b26565b5050505050505062001ae5565b336001600160a01b03821603620002615760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b602081015160005b815181101562000342576000828281518110620002db57620002db62001953565b60209081029190910101519050620002f560028262000e5f565b1562000338576040516001600160a01b03821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b50600101620002ba565b50815160005b8151811015620003fb57600082828151811062000369576200036962001953565b6020026020010151905060006001600160a01b0316816001600160a01b031603620003a7576040516342bcdf7f60e11b815260040160405180910390fd5b620003b460028262000e7f565b506040516001600160a01b03821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a15060010162000348565b50505050565b60005b8251811015620004a2576200044083828151811062000427576200042762001953565b6020026020010151600b62000e7f60201b90919060201c565b1562000499578281815181106200045b576200045b62001953565b60200260200101516001600160a01b03167fdf1b1bd32a69711488d71554706bb130b1fc63a5fa1a2cd85e8440f84065ba2360405160405180910390a25b60010162000404565b5060005b81518110156200054457620004e2828281518110620004c957620004c962001953565b6020026020010151600b62000e9660201b90919060201c565b156200053b57818181518110620004fd57620004fd62001953565b60200260200101516001600160a01b03167f1795838dc8ab2ffc5f431a1729a6afa0b587f982f7b2be0b9d7187a1ef547f9160405160405180910390a25b600101620004a6565b505050565b60005b8151811015620006165760008282815181106200056d576200056d62001953565b6020908102919091018101518051818301516001600160a01b0380831660008181526007875260409081902084518154868a018051929096166001600160a81b03199091168117600160a01b60ff9384160217909255825191825293519093169683019690965293955091939092917f08a5f7f5bb38a81d8e43aca13ecd76431dbf8816ae4699affff7b00b2fc1c464910160405180910390a25050508060010190506200054c565b5050565b60005b8151811015620006165760008282815181106200063e576200063e62001953565b6020026020010151905060008383815181106200065f576200065f62001953565b6020026020010151600001519050600082602001519050816001600160401b03166000148062000698575061016081015163ffffffff16155b80620006ba57506101e08101516001600160e01b031916630a04b54b60e21b14155b80620006da5750806060015163ffffffff1681610160015163ffffffff16115b15620007055760405163c35aa79d60e01b81526001600160401b038316600482015260240162000083565b6001600160401b038216600090815260096020526040812060010154600160881b900460e01b6001600160e01b03191690036200078557816001600160401b03167fd31c671936387b2f84ed402b553bd50c0e9c20408ea4e91a836d77b8180fb7248260405162000777919062001969565b60405180910390a2620007c9565b816001600160401b03167f1edd6f3553cfa16f10b95b195abae3a1cfca4783de4843f95d674b1e1df5ab2082604051620007c0919062001969565b60405180910390a25b8060096000846001600160401b03166001600160401b0316815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548161ffff021916908361ffff16021790555060408201518160000160036101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160076101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600b6101000a81548163ffffffff021916908363ffffffff16021790555060a082015181600001600f6101000a81548161ffff021916908361ffff16021790555060c08201518160000160116101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160000160156101000a81548161ffff021916908361ffff1602179055506101008201518160000160176101000a81548161ffff021916908361ffff1602179055506101208201518160000160196101000a81548161ffff021916908361ffff16021790555061014082015181600001601b6101000a81548163ffffffff021916908363ffffffff1602179055506101608201518160010160006101000a81548163ffffffff021916908363ffffffff1602179055506101808201518160010160046101000a8154816001600160401b0302191690836001600160401b031602179055506101a082015181600101600c6101000a81548163ffffffff021916908363ffffffff1602179055506101c08201518160010160106101000a81548160ff0219169083151502179055506101e08201518160010160116101000a81548163ffffffff021916908360e01c02179055509050505050508060010190506200061d565b60005b81518110156200061657600082828151811062000a7e5762000a7e62001953565b6020026020010151600001519050600083838151811062000aa35762000aa362001953565b6020908102919091018101518101516001600160a01b03841660008181526008845260409081902080546001600160401b0319166001600160401b0385169081179091559051908152919350917fbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d910160405180910390a2505060010162000a5d565b60005b825181101562000d9957600083828151811062000b4a5762000b4a62001953565b6020026020010151905060008160000151905060005b82602001515181101562000d8a5760008360200151828151811062000b895762000b8962001953565b602002602001015160200151905060008460200151838151811062000bb25762000bb262001953565b6020026020010151600001519050602063ffffffff16826080015163ffffffff16101562000c115760808201516040516312766e0160e11b81526001600160a01b038316600482015263ffffffff909116602482015260440162000083565b6001600160401b0384166000818152600a602090815260408083206001600160a01b0386168085529083529281902086518154938801518389015160608a015160808b015160a08c01511515600160901b0260ff60901b1963ffffffff928316600160701b021664ffffffffff60701b199383166a01000000000000000000000263ffffffff60501b1961ffff90961668010000000000000000029590951665ffffffffffff60401b19968416640100000000026001600160401b0319909b16939097169290921798909817939093169390931717919091161792909217909155519091907f94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b59062000d77908690600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60405180910390a3505060010162000b60565b50505080600101905062000b29565b5060005b81518110156200054457600082828151811062000dbe5762000dbe62001953565b6020026020010151600001519050600083838151811062000de35762000de362001953565b6020908102919091018101518101516001600160401b0384166000818152600a845260408082206001600160a01b038516808452955280822080546001600160981b03191690555192945090917f4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b9190a3505060010162000d9d565b600062000e76836001600160a01b03841662000ead565b90505b92915050565b600062000e76836001600160a01b03841662000fb1565b600062000e76836001600160a01b03841662001003565b6000818152600183016020526040812054801562000fa657600062000ed460018362001aad565b855490915060009062000eea9060019062001aad565b905081811462000f5657600086600001828154811062000f0e5762000f0e62001953565b906000526020600020015490508087600001848154811062000f345762000f3462001953565b6000918252602080832090910192909255918252600188019052604090208390555b855486908062000f6a5762000f6a62001acf565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505062000e79565b600091505062000e79565b600081815260018301602052604081205462000ffa5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000e79565b50600062000e79565b6000818152600183016020526040812054801562000fa65760006200102a60018362001aad565b8554909150600090620010409060019062001aad565b905080821462000f5657600086600001828154811062000f0e5762000f0e62001953565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b03811182821017156200109f576200109f62001064565b60405290565b60405160c081016001600160401b03811182821017156200109f576200109f62001064565b60405161020081016001600160401b03811182821017156200109f576200109f62001064565b604051601f8201601f191681016001600160401b03811182821017156200111b576200111b62001064565b604052919050565b80516001600160a01b03811681146200113b57600080fd5b919050565b805163ffffffff811681146200113b57600080fd5b6000606082840312156200116857600080fd5b604051606081016001600160401b03811182821017156200118d576200118d62001064565b604052825190915081906001600160601b0381168114620011ad57600080fd5b8152620011bd6020840162001123565b6020820152620011d06040840162001140565b60408201525092915050565b60006001600160401b03821115620011f857620011f862001064565b5060051b60200190565b600082601f8301126200121457600080fd5b815160206200122d6200122783620011dc565b620010f0565b8083825260208201915060208460051b8701019350868411156200125057600080fd5b602086015b848110156200127757620012698162001123565b835291830191830162001255565b509695505050505050565b600082601f8301126200129457600080fd5b81516020620012a76200122783620011dc565b82815260609283028501820192828201919087851115620012c757600080fd5b8387015b858110156200135a5780890382811215620012e65760008081fd5b620012f06200107a565b620012fb8362001123565b8152604080601f1984011215620013125760008081fd5b6200131c6200107a565b92506200132b88850162001123565b835283015160ff81168114620013415760008081fd5b82880152808701919091528452928401928101620012cb565b5090979650505050505050565b80516001600160401b03811681146200113b57600080fd5b805161ffff811681146200113b57600080fd5b805180151581146200113b57600080fd5b600082601f830112620013b557600080fd5b81516020620013c86200122783620011dc565b82815260059290921b84018101918181019086841115620013e857600080fd5b8286015b84811015620012775780516001600160401b03808211156200140d57600080fd5b908801906040601f19838c0381018213156200142857600080fd5b620014326200107a565b6200143f89860162001367565b815282850151848111156200145357600080fd5b8086019550508c603f8601126200146957600080fd5b8885015193506200147e6200122785620011dc565b84815260e09094028501830193898101908e8611156200149d57600080fd5b958401955b858710156200157657868f0360e0811215620014bd57600080fd5b620014c76200107a565b620014d28962001123565b815260c08683011215620014e557600080fd5b620014ef620010a5565b9150620014fe8d8a0162001140565b82526200150d878a0162001140565b8d8301526200151f60608a016200137f565b878301526200153160808a0162001140565b60608301526200154460a08a0162001140565b60808301526200155760c08a0162001392565b60a0830152808d0191909152825260e09690960195908a0190620014a2565b828b015250875250505092840192508301620013ec565b600082601f8301126200159f57600080fd5b81516020620015b26200122783620011dc565b82815260069290921b84018101918181019086841115620015d257600080fd5b8286015b84811015620012775760408189031215620015f15760008081fd5b620015fb6200107a565b620016068262001123565b81526200161585830162001367565b81860152835291830191604001620015d6565b80516001600160e01b0319811681146200113b57600080fd5b600082601f8301126200165357600080fd5b81516020620016666200122783620011dc565b82815261022092830285018201928282019190878511156200168757600080fd5b8387015b858110156200135a5780890382811215620016a65760008081fd5b620016b06200107a565b620016bb8362001367565b815261020080601f1984011215620016d35760008081fd5b620016dd620010ca565b9250620016ec88850162001392565b83526040620016fd8186016200137f565b8985015260606200171081870162001140565b82860152608091506200172582870162001140565b9085015260a06200173886820162001140565b8286015260c091506200174d8287016200137f565b9085015260e06200176086820162001140565b828601526101009150620017768287016200137f565b908501526101206200178a8682016200137f565b828601526101409150620017a08287016200137f565b90850152610160620017b486820162001140565b828601526101809150620017ca82870162001140565b908501526101a0620017de86820162001367565b828601526101c09150620017f482870162001140565b908501526101e06200180886820162001392565b828601526200181983870162001628565b9085015250508087019190915284529284019281016200168b565b6000806000806000806000610120888a0312156200185157600080fd5b6200185d898962001155565b60608901519097506001600160401b03808211156200187b57600080fd5b620018898b838c0162001202565b975060808a0151915080821115620018a057600080fd5b620018ae8b838c0162001202565b965060a08a0151915080821115620018c557600080fd5b620018d38b838c0162001282565b955060c08a0151915080821115620018ea57600080fd5b620018f88b838c01620013a3565b945060e08a01519150808211156200190f57600080fd5b6200191d8b838c016200158d565b93506101008a01519150808211156200193557600080fd5b50620019448a828b0162001641565b91505092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b815115158152610200810160208301516200198a602084018261ffff169052565b506040830151620019a3604084018263ffffffff169052565b506060830151620019bc606084018263ffffffff169052565b506080830151620019d5608084018263ffffffff169052565b5060a0830151620019ec60a084018261ffff169052565b5060c083015162001a0560c084018263ffffffff169052565b5060e083015162001a1c60e084018261ffff169052565b506101008381015161ffff9081169184019190915261012080850151909116908301526101408084015163ffffffff9081169184019190915261016080850151821690840152610180808501516001600160401b0316908401526101a080850151909116908301526101c0808401511515908301526101e0928301516001600160e01b031916929091019190915290565b8181038181111562000e7957634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b60805160a05160c051615b9962001b3f600039600081816102ef0152818161219101526121fa0152600081816102b301528181611917015261197701526000818161027f015281816119a00152611a100152615b996000f3fe608060405234801561001057600080fd5b50600436106101ce5760003560e01c806379ba509711610104578063a69c64c0116100a2578063d02641a011610071578063d02641a014610a81578063d8694ccd14610a94578063f2fde38b14610aa7578063ffdb4b3714610aba57600080fd5b8063a69c64c014610997578063bf78e03f146109aa578063c4276bfc14610a57578063cdc73d5114610a7957600080fd5b806382b49eb0116100de57806382b49eb0146107d95780638da5cb5b1461094957806391a2749a146109715780639ea600261461098457600080fd5b806379ba5097146107ab5780637afac322146107b3578063805f2132146107c657600080fd5b8063407e1086116101715780634ab35b0b1161014b5780634ab35b0b14610441578063514e8cff146104815780636def4ce714610524578063770e2dc41461079857600080fd5b8063407e1086146103fb57806341ed29e71461040e57806345ac924d1461042157600080fd5b8063085318f8116101ad578063085318f814610368578063181f5a77146103885780632451a627146103d15780633937306f146103e657600080fd5b806241e5be146101d3578063061877e3146101f957806306285c6914610252575b600080fd5b6101e66101e1366004614250565b610b02565b6040519081526020015b60405180910390f35b61023961020736600461428c565b73ffffffffffffffffffffffffffffffffffffffff1660009081526008602052604090205467ffffffffffffffff1690565b60405167ffffffffffffffff90911681526020016101f0565b61031c604080516060810182526000808252602082018190529181019190915260405180606001604052807f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000063ffffffff16815250905090565b6040805182516bffffffffffffffffffffffff16815260208084015173ffffffffffffffffffffffffffffffffffffffff16908201529181015163ffffffff16908201526060016101f0565b61037b610376366004614304565b610b70565b6040516101f09190614416565b6103c46040518060400160405280601381526020017f46656551756f74657220312e362e302d6465760000000000000000000000000081525081565b6040516101f09190614498565b6103d9610ee2565b6040516101f091906144ab565b6103f96103f4366004614505565b610ef3565b005b6103f96104093660046146a7565b6111a8565b6103f961041c3660046147d9565b6111bc565b61043461042f366004614914565b6111fe565b6040516101f09190614956565b61045461044f36600461428c565b6112c9565b6040517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff90911681526020016101f0565b61051761048f3660046149d1565b60408051808201909152600080825260208201525067ffffffffffffffff166000908152600560209081526040918290208251808401909352547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811683527c0100000000000000000000000000000000000000000000000000000000900463ffffffff169082015290565b6040516101f091906149ec565b61078b6105323660046149d1565b6040805161020081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a081018290526101c081018290526101e08101919091525067ffffffffffffffff908116600090815260096020908152604091829020825161020081018452815460ff8082161515835261ffff61010080840482169685019690965263ffffffff630100000084048116978501979097526701000000000000008304871660608501526b0100000000000000000000008304871660808501526f010000000000000000000000000000008304811660a085015271010000000000000000000000000000000000808404881660c086015275010000000000000000000000000000000000000000008404821660e08087019190915277010000000000000000000000000000000000000000000000850483169786019790975279010000000000000000000000000000000000000000000000000084049091166101208501527b01000000000000000000000000000000000000000000000000000000909204861661014084015260019093015480861661016084015264010000000081049096166101808301526c0100000000000000000000000086049094166101a0820152700100000000000000000000000000000000850490911615156101c08201527fffffffff0000000000000000000000000000000000000000000000000000000092909304901b166101e082015290565b6040516101f09190614a27565b6103f96107a6366004614c3e565b6112d4565b6103f96112e6565b6103f96107c1366004614f58565b6113e3565b6103f96107d4366004614ffe565b6113f5565b6108e96107e736600461506a565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101919091525067ffffffffffffffff919091166000908152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff94909416835292815290829020825160c081018452905463ffffffff8082168352640100000000820481169383019390935268010000000000000000810461ffff16938201939093526a01000000000000000000008304821660608201526e01000000000000000000000000000083049091166080820152720100000000000000000000000000000000000090910460ff16151560a082015290565b6040516101f09190600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101f0565b6103f961097f366004615094565b6118dd565b6103f9610992366004615155565b6118ee565b6103f96109a5366004615362565b6118ff565b610a236109b836600461428c565b6040805180820182526000808252602091820181905273ffffffffffffffffffffffffffffffffffffffff93841681526007825282902082518084019093525492831682527401000000000000000000000000000000000000000090920460ff169181019190915290565b60408051825173ffffffffffffffffffffffffffffffffffffffff16815260209283015160ff1692810192909252016101f0565b610a6a610a65366004615427565b611910565b6040516101f093929190615496565b6103d9611b06565b610517610a8f36600461428c565b611b12565b6101e6610aa23660046154b7565b611c0e565b6103f9610ab536600461428c565b6120ac565b610acd610ac836600461550c565b6120bd565b604080517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff9384168152929091166020830152016101f0565b6000610b0d82612248565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16610b3485612248565b610b5c907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1685615565565b610b66919061557c565b90505b9392505050565b67ffffffffffffffff8086166000908152600960205260409020600101546060917101000000000000000000000000000000000090910460e01b908590811115610bbc57610bbc614540565b604051908082528060200260200182016040528015610bef57816020015b6060815260200190600190039081610bda5790505b50915060005b85811015610ed7576000858583818110610c1157610c116155b7565b610c27926020604090920201908101915061428c565b90506000888884818110610c3d57610c3d6155b7565b9050602002810190610c4f91906155e6565b610c5d906040810190615624565b9150506020811115610d125767ffffffffffffffff8a166000908152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff861684529091529020546e010000000000000000000000000000900463ffffffff16811115610d12576040517f36f536ca00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526024015b60405180910390fd5b610d82848a8a86818110610d2857610d286155b7565b9050602002810190610d3a91906155e6565b610d48906020810190615624565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506122e292505050565b67ffffffffffffffff8a166000818152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684528252808320815160c081018352905463ffffffff8082168352640100000000820481168386015268010000000000000000820461ffff16838501526a01000000000000000000008204811660608401526e010000000000000000000000000000820481166080840152720100000000000000000000000000000000000090910460ff16151560a08301908152958552600990935290832054935190937b0100000000000000000000000000000000000000000000000000000090049091169190610e815781610e87565b82606001515b6040805163ffffffff8316602082015291925001604051602081830303815290604052888781518110610ebc57610ebc6155b7565b60200260200101819052505050505050806001019050610bf5565b505095945050505050565b6060610eee6002612339565b905090565b610efb612346565b6000610f078280615689565b9050905060005b81811015611051576000610f228480615689565b83818110610f3257610f326155b7565b905060400201803603810190610f48919061571d565b604080518082018252602080840180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff908116845263ffffffff42818116858701908152885173ffffffffffffffffffffffffffffffffffffffff9081166000908152600690975295889020965190519092167c010000000000000000000000000000000000000000000000000000000002919092161790935584519051935194955016927f52f50aa6d1a95a4595361ecf953d095f125d442e4673716dede699e049de148a926110409290917bffffffffffffffffffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b60405180910390a250600101610f0e565b5060006110616020840184615689565b9050905060005b818110156111a257600061107f6020860186615689565b8381811061108f5761108f6155b7565b9050604002018036038101906110a5919061575a565b604080518082018252602080840180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff908116845263ffffffff42818116858701908152885167ffffffffffffffff9081166000908152600590975295889020965190519092167c010000000000000000000000000000000000000000000000000000000002919092161790935584519051935194955016927fdd84a3fa9ef9409f550d54d6affec7e9c480c878c6ab27b78912a03e1b371c6e926111919290917bffffffffffffffffffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b60405180910390a250600101611068565b50505050565b6111b061238b565b6111b98161240c565b50565b6111c461238b565b60005b81518110156111fa576111f28282815181106111e5576111e56155b7565b602002602001015161250a565b6001016111c7565b5050565b60608160008167ffffffffffffffff81111561121c5761121c614540565b60405190808252806020026020018201604052801561126157816020015b604080518082019091526000808252602082015281526020019060019003908161123a5790505b50905060005b828110156112be57611299868683818110611284576112846155b7565b9050602002016020810190610a8f919061428c565b8282815181106112ab576112ab6155b7565b6020908102919091010152600101611267565b509150505b92915050565b60006112c382612248565b6112dc61238b565b6111fa82826126dc565b60015473ffffffffffffffffffffffffffffffffffffffff163314611367576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610d09565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6113eb61238b565b6111fa8282612ae9565b600080600061143987878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612c3092505050565b92509250925061144b33838584612c4b565b60006114598587018761577d565b905060005b81518110156118d25760006007600084848151811061147f5761147f6155b7565b6020908102919091018101515173ffffffffffffffffffffffffffffffffffffffff16825281019190915260400160009081205474010000000000000000000000000000000000000000900460ff169150819003611540578282815181106114e9576114e96155b7565b6020908102919091010151516040517f06439c6b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610d09565b600061158960128386868151811061155a5761155a6155b7565b6020026020010151602001517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16612da3565b9050600660008585815181106115a1576115a16155b7565b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001601c9054906101000a900463ffffffff1663ffffffff16848481518110611613576116136155b7565b60200260200101516040015163ffffffff16101561171d5783838151811061163d5761163d6155b7565b60200260200101516000015184848151811061165b5761165b6155b7565b6020026020010151604001516006600087878151811061167d5761167d6155b7565b6020908102919091018101515173ffffffffffffffffffffffffffffffffffffffff90811683529082019290925260409081016000205490517f191ec70600000000000000000000000000000000000000000000000000000000815293909116600484015263ffffffff91821660248401527c01000000000000000000000000000000000000000000000000000000009004166044820152606401610d09565b6040518060400160405280827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16815260200185858151811061175e5761175e6155b7565b60200260200101516040015163ffffffff1681525060066000868681518110611789576117896155b7565b6020908102919091018101515173ffffffffffffffffffffffffffffffffffffffff168252818101929092526040016000208251929091015163ffffffff167c0100000000000000000000000000000000000000000000000000000000027bffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092169190911790558351849084908110611821576118216155b7565b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff167f52f50aa6d1a95a4595361ecf953d095f125d442e4673716dede699e049de148a82868681518110611877576118776155b7565b6020026020010151604001516040516118c09291907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff92909216825263ffffffff16602082015260400190565b60405180910390a2505060010161145e565b505050505050505050565b6118e561238b565b6111b981612e69565b6118f661238b565b6111b981612ff5565b61190761238b565b6111b98161349b565b60008060607f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff16036119705785925061199e565b61199b87877f0000000000000000000000000000000000000000000000000000000000000000610b02565b92505b7f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff16831115611a3d576040517f6a92a483000000000000000000000000000000000000000000000000000000008152600481018490526bffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166024820152604401610d09565b67ffffffffffffffff881660009081526009602052604081206001015463ffffffff1690611a6c878784613585565b9050806020015193508484611af3836040805182516024820152602092830151151560448083019190915282518083039091018152606490910190915290810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f181dcf100000000000000000000000000000000000000000000000000000000017905290565b9450945094505050955095509592505050565b6060610eee600b612339565b604080518082019091526000808252602082015273ffffffffffffffffffffffffffffffffffffffff8281166000908152600760209081526040918290208251808401909352549283168083527401000000000000000000000000000000000000000090930460ff169082015290611c0557505073ffffffffffffffffffffffffffffffffffffffff166000908152600660209081526040918290208251808401909352547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811683527c0100000000000000000000000000000000000000000000000000000000900463ffffffff169082015290565b610b698161372e565b67ffffffffffffffff8083166000908152600960209081526040808320815161020081018352815460ff808216151580845261ffff61010080850482169886019890985263ffffffff630100000085048116978601979097526701000000000000008404871660608601526b0100000000000000000000008404871660808601526f010000000000000000000000000000008404811660a086015271010000000000000000000000000000000000808504881660c087015275010000000000000000000000000000000000000000008504821660e08088019190915277010000000000000000000000000000000000000000000000860483169987019990995279010000000000000000000000000000000000000000000000000085049091166101208601527b01000000000000000000000000000000000000000000000000000000909304861661014085015260019094015480861661016085015264010000000081049098166101808401526c0100000000000000000000000088049094166101a0830152700100000000000000000000000000000000870490931615156101c08201527fffffffff000000000000000000000000000000000000000000000000000000009290950490921b166101e0840152909190611e28576040517f99ac52f200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff85166004820152602401610d09565b6000611e376040850185615689565b9150611e93905082611e4c6020870187615624565b905083611e598880615624565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506138bd92505050565b6000600881611ea8608088016060890161428c565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160009081205467ffffffffffffffff16915080611ef7611ef16080890160608a0161428c565b896120bd565b9092509050600080808615611f3d57611f31888c611f1b60808e0160608f0161428c565b888e8060400190611f2c9190615689565b613967565b91945092509050611f5d565b6101a0880151611f5a9063ffffffff16662386f26fc10000615565565b92505b61010088015160009061ffff1615611fa157611f9e896dffffffffffffffffffffffffffff607088901c16611f9560208f018f615624565b90508b86613c3f565b90505b61018089015160009067ffffffffffffffff16611fca611fc460808f018f615624565b8d613cef565b600001518563ffffffff168c60a0015161ffff168f8060200190611fee9190615624565b611ff9929150615565565b8d6080015163ffffffff1661200e9190615844565b6120189190615844565b6120229190615844565b61203c906dffffffffffffffffffffffffffff8916615565565b6120469190615565565b90507bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8716828261207d67ffffffffffffffff8c1689615565565b6120879190615844565b6120919190615844565b61209b919061557c565b9d9c50505050505050505050505050565b6120b461238b565b6111b981613db0565b67ffffffffffffffff811660009081526005602090815260408083208151808301909252547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811682527c0100000000000000000000000000000000000000000000000000000000900463ffffffff1691810182905282918203612175576040517f2e59db3a00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff85166004820152602401610d09565b6000816020015163ffffffff164261218d9190615857565b90507f000000000000000000000000000000000000000000000000000000000000000063ffffffff1681111561222e576040517ff08bcb3e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8616600482015263ffffffff7f000000000000000000000000000000000000000000000000000000000000000016602482015260448101829052606401610d09565b61223786612248565b9151919350909150505b9250929050565b60008061225483611b12565b9050806020015163ffffffff166000148061228c575080517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16155b156122db576040517f06439c6b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152602401610d09565b5192915050565b7fd7ed2ad4000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316016111fa5761233481613ea5565b505050565b60606000610b6983613f58565b612351600233613fb4565b612389576040517fd86ad9cf000000000000000000000000000000000000000000000000000000008152336004820152602401610d09565b565b60005473ffffffffffffffffffffffffffffffffffffffff163314612389576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610d09565b60005b81518110156111fa57600082828151811061242c5761242c6155b7565b60209081029190910181015180518183015173ffffffffffffffffffffffffffffffffffffffff80831660008181526007875260409081902084518154868a018051929096167fffffffffffffffffffffff00000000000000000000000000000000000000000090911681177401000000000000000000000000000000000000000060ff9384160217909255825191825293519093169683019690965293955091939092917f08a5f7f5bb38a81d8e43aca13ecd76431dbf8816ae4699affff7b00b2fc1c464910160405180910390a250505080600101905061240f565b60006125c382600001518360600151846020015185604001516040805173ffffffffffffffffffffffffffffffffffffffff80871660208301528516918101919091527fffffffffffffffffffff00000000000000000000000000000000000000000000831660608201527fffff0000000000000000000000000000000000000000000000000000000000008216608082015260009060a001604051602081830303815290604052805190602001209050949350505050565b60808301516000828152600460205260409081902080549215157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00909316929092179091555190915081907f32a4ba3fa3351b11ad555d4c8ec70a744e8705607077a946807030d64b6ab1a3906126d0908590600060a08201905073ffffffffffffffffffffffffffffffffffffffff8084511683527fffffffffffffffffffff0000000000000000000000000000000000000000000060208501511660208401527fffff00000000000000000000000000000000000000000000000000000000000060408501511660408401528060608501511660608401525060808301511515608083015292915050565b60405180910390a25050565b60005b8251811015612a055760008382815181106126fc576126fc6155b7565b6020026020010151905060008160000151905060005b8260200151518110156129f757600083602001518281518110612737576127376155b7565b602002602001015160200151905060008460200151838151811061275d5761275d6155b7565b6020026020010151600001519050602063ffffffff16826080015163ffffffff1610156127e05760808201516040517f24ecdc0200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8316600482015263ffffffff9091166024820152604401610d09565b67ffffffffffffffff84166000818152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff86168085529083529281902086518154938801518389015160608a015160808b015160a08c015115157201000000000000000000000000000000000000027fffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffff63ffffffff9283166e01000000000000000000000000000002167fffffffffffffffffffffffffff0000000000ffffffffffffffffffffffffffff9383166a0100000000000000000000027fffffffffffffffffffffffffffffffffffff00000000ffffffffffffffffffff61ffff9096166801000000000000000002959095167fffffffffffffffffffffffffffffffffffff000000000000ffffffffffffffff968416640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000909b16939097169290921798909817939093169390931717919091161792909217909155519091907f94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b5906129e5908690600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60405180910390a35050600101612712565b5050508060010190506126df565b5060005b8151811015612334576000828281518110612a2657612a266155b7565b60200260200101516000015190506000838381518110612a4857612a486155b7565b60209081029190910181015181015167ffffffffffffffff84166000818152600a8452604080822073ffffffffffffffffffffffffffffffffffffffff8516808452955280822080547fffffffffffffffffffffffffff000000000000000000000000000000000000001690555192945090917f4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b9190a35050600101612a09565b60005b8251811015612b8c57612b22838281518110612b0a57612b0a6155b7565b6020026020010151600b613fe390919063ffffffff16565b15612b8457828181518110612b3957612b396155b7565b602002602001015173ffffffffffffffffffffffffffffffffffffffff167fdf1b1bd32a69711488d71554706bb130b1fc63a5fa1a2cd85e8440f84065ba2360405160405180910390a25b600101612aec565b5060005b815181101561233457612bc6828281518110612bae57612bae6155b7565b6020026020010151600b61400590919063ffffffff16565b15612c2857818181518110612bdd57612bdd6155b7565b602002602001015173ffffffffffffffffffffffffffffffffffffffff167f1795838dc8ab2ffc5f431a1729a6afa0b587f982f7b2be0b9d7187a1ef547f9160405160405180910390a25b600101612b90565b6040810151604a820151605e90920151909260609290921c91565b6040805173ffffffffffffffffffffffffffffffffffffffff868116602080840191909152908616828401527fffffffffffffffffffff00000000000000000000000000000000000000000000851660608301527fffff00000000000000000000000000000000000000000000000000000000000084166080808401919091528351808403909101815260a09092018352815191810191909120600081815260049092529190205460ff16612d9c576040517f097e17ff00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8087166004830152851660248201527fffffffffffffffffffff00000000000000000000000000000000000000000000841660448201527fffff00000000000000000000000000000000000000000000000000000000000083166064820152608401610d09565b5050505050565b600080612db0848661586a565b9050600060248260ff161115612de757612dcb602483615883565b612dd690600a6159bc565b612de0908561557c565b9050612e0a565b612df2826024615883565b612dfd90600a6159bc565b612e079085615565565b90505b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811115612e60576040517f10cb51d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b95945050505050565b602081015160005b8151811015612f04576000828281518110612e8e57612e8e6155b7565b60200260200101519050612eac81600261402790919063ffffffff16565b15612efb5760405173ffffffffffffffffffffffffffffffffffffffff821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b50600101612e71565b50815160005b81518110156111a2576000828281518110612f2757612f276155b7565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603612f97576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612fa2600282613fe3565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a150600101612f0a565b60005b81518110156111fa576000828281518110613015576130156155b7565b602002602001015190506000838381518110613033576130336155b7565b60200260200101516000015190506000826020015190508167ffffffffffffffff166000148061306c575061016081015163ffffffff16155b806130be57506101e08101517fffffffff00000000000000000000000000000000000000000000000000000000167f2812d52c0000000000000000000000000000000000000000000000000000000014155b806130dd5750806060015163ffffffff1681610160015163ffffffff16115b15613120576040517fc35aa79d00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff83166004820152602401610d09565b67ffffffffffffffff821660009081526009602052604081206001015471010000000000000000000000000000000000900460e01b7fffffffff000000000000000000000000000000000000000000000000000000001690036131c4578167ffffffffffffffff167fd31c671936387b2f84ed402b553bd50c0e9c20408ea4e91a836d77b8180fb724826040516131b79190614a27565b60405180910390a2613207565b8167ffffffffffffffff167f1edd6f3553cfa16f10b95b195abae3a1cfca4783de4843f95d674b1e1df5ab20826040516131fe9190614a27565b60405180910390a25b80600960008467ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548161ffff021916908361ffff16021790555060408201518160000160036101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160076101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600b6101000a81548163ffffffff021916908363ffffffff16021790555060a082015181600001600f6101000a81548161ffff021916908361ffff16021790555060c08201518160000160116101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160000160156101000a81548161ffff021916908361ffff1602179055506101008201518160000160176101000a81548161ffff021916908361ffff1602179055506101208201518160000160196101000a81548161ffff021916908361ffff16021790555061014082015181600001601b6101000a81548163ffffffff021916908363ffffffff1602179055506101608201518160010160006101000a81548163ffffffff021916908363ffffffff1602179055506101808201518160010160046101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506101a082015181600101600c6101000a81548163ffffffff021916908363ffffffff1602179055506101c08201518160010160106101000a81548160ff0219169083151502179055506101e08201518160010160116101000a81548163ffffffff021916908360e01c0217905550905050505050806001019050612ff8565b60005b81518110156111fa5760008282815181106134bb576134bb6155b7565b602002602001015160000151905060008383815181106134dd576134dd6155b7565b60209081029190910181015181015173ffffffffffffffffffffffffffffffffffffffff841660008181526008845260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff85169081179091559051908152919350917fbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d910160405180910390a2505060010161349e565b604080518082019091526000808252602082015260008390036135c657506040805180820190915267ffffffffffffffff8216815260006020820152610b69565b60006135d284866159cb565b905060006135e38560048189615a11565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505050507fffffffff0000000000000000000000000000000000000000000000000000000082167fe7e230f0000000000000000000000000000000000000000000000000000000000161368057808060200190518101906136779190615a3b565b92505050610b69565b7f6859a837000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316016136fc576040518060400160405280828060200190518101906136e89190615a67565b815260006020909101529250610b69915050565b6040517f5247fdce00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080518082019091526000808252602082015260008260000151905060008173ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015613798573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137bc9190615a9a565b50505091505060008112156137fd576040517f10cb51d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061387c8373ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561384d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138719190615aea565b866020015184612da3565b604080518082019091527bffffffffffffffffffffffffffffffffffffffffffffffffffffffff909116815263ffffffff4216602082015295945050505050565b836040015163ffffffff168311156139165760408085015190517f8693378900000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015260248101849052604401610d09565b836020015161ffff16821115613958576040517f4c056b6a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6111a2846101e00151826122e2565b6000808083815b81811015613c3157600087878381811061398a5761398a6155b7565b9050604002018036038101906139a09190615b07565b67ffffffffffffffff8c166000908152600a60209081526040808320845173ffffffffffffffffffffffffffffffffffffffff168452825291829020825160c081018452905463ffffffff8082168352640100000000820481169383019390935268010000000000000000810461ffff16938201939093526a01000000000000000000008304821660608201526e01000000000000000000000000000083049091166080820152720100000000000000000000000000000000000090910460ff16151560a0820181905291925090613ac0576101208d0151613a8d9061ffff16662386f26fc10000615565565b613a979088615844565b96508c610140015186613aaa9190615b40565b9550613ab7602086615b40565b94505050613c29565b604081015160009061ffff1615613b795760008c73ffffffffffffffffffffffffffffffffffffffff16846000015173ffffffffffffffffffffffffffffffffffffffff1614613b1c578351613b1590612248565b9050613b1f565b508a5b620186a0836040015161ffff16613b618660200151847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1661404990919063ffffffff16565b613b6b9190615565565b613b75919061557c565b9150505b6060820151613b889088615b40565b9650816080015186613b9a9190615b40565b8251909650600090613bb99063ffffffff16662386f26fc10000615565565b905080821015613bd857613bcd818a615844565b985050505050613c29565b6000836020015163ffffffff16662386f26fc10000613bf79190615565565b905080831115613c1757613c0b818b615844565b99505050505050613c29565b613c21838b615844565b995050505050505b60010161396e565b505096509650969350505050565b60008063ffffffff8316613c5561016086615565565b613c61876101c0615844565b613c6b9190615844565b613c759190615844565b905060008760c0015163ffffffff168860e0015161ffff1683613c989190615565565b613ca29190615844565b61010089015190915061ffff16613cc96dffffffffffffffffffffffffffff891683615565565b613cd39190615565565b613ce390655af3107a4000615565565b98975050505050505050565b60408051808201909152600080825260208201526000613d1b858585610160015163ffffffff16613585565b9050826060015163ffffffff1681600001511115613d65576040517f4c4fc93a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b826101c001518015613d7957508060200151155b15610b66576040517fee433e9900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff821603613e2f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610d09565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60008151602014613ee457816040517f8d666f60000000000000000000000000000000000000000000000000000000008152600401610d099190614498565b600082806020019051810190613efa9190615a67565b905073ffffffffffffffffffffffffffffffffffffffff811180613f1f575061040081105b156112c357826040517f8d666f60000000000000000000000000000000000000000000000000000000008152600401610d099190614498565b606081600001805480602002602001604051908101604052809291908181526020018280548015613fa857602002820191906000526020600020905b815481526020019060010190808311613f94575b50505050509050919050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515610b69565b6000610b698373ffffffffffffffffffffffffffffffffffffffff8416614086565b6000610b698373ffffffffffffffffffffffffffffffffffffffff84166140d5565b6000610b698373ffffffffffffffffffffffffffffffffffffffff84166141cf565b6000670de0b6b3a764000061407c837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8616615565565b610b69919061557c565b60008181526001830160205260408120546140cd575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556112c3565b5060006112c3565b600081815260018301602052604081205480156141be5760006140f9600183615857565b855490915060009061410d90600190615857565b905080821461417257600086600001828154811061412d5761412d6155b7565b9060005260206000200154905080876000018481548110614150576141506155b7565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061418357614183615b5d565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506112c3565b60009150506112c3565b5092915050565b600081815260018301602052604081205480156141be5760006141f3600183615857565b855490915060009061420790600190615857565b905081811461417257600086600001828154811061412d5761412d6155b7565b803573ffffffffffffffffffffffffffffffffffffffff8116811461424b57600080fd5b919050565b60008060006060848603121561426557600080fd5b61426e84614227565b92506020840135915061428360408501614227565b90509250925092565b60006020828403121561429e57600080fd5b610b6982614227565b803567ffffffffffffffff8116811461424b57600080fd5b60008083601f8401126142d157600080fd5b50813567ffffffffffffffff8111156142e957600080fd5b6020830191508360208260051b850101111561224157600080fd5b60008060008060006060868803121561431c57600080fd5b614325866142a7565b9450602086013567ffffffffffffffff8082111561434257600080fd5b61434e89838a016142bf565b9096509450604088013591508082111561436757600080fd5b818801915088601f83011261437b57600080fd5b81358181111561438a57600080fd5b8960208260061b850101111561439f57600080fd5b9699959850939650602001949392505050565b6000815180845260005b818110156143d8576020818501810151868301820152016143bc565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b8281101561448b577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526144798583516143b2565b9450928501929085019060010161443f565b5092979650505050505050565b602081526000610b6960208301846143b2565b6020808252825182820181905260009190848201906040850190845b818110156144f957835173ffffffffffffffffffffffffffffffffffffffff16835292840192918401916001016144c7565b50909695505050505050565b60006020828403121561451757600080fd5b813567ffffffffffffffff81111561452e57600080fd5b820160408185031215610b6957600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561459257614592614540565b60405290565b60405160a0810167ffffffffffffffff8111828210171561459257614592614540565b60405160c0810167ffffffffffffffff8111828210171561459257614592614540565b604051610200810167ffffffffffffffff8111828210171561459257614592614540565b6040516060810167ffffffffffffffff8111828210171561459257614592614540565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561466c5761466c614540565b604052919050565b600067ffffffffffffffff82111561468e5761468e614540565b5060051b60200190565b60ff811681146111b957600080fd5b600060208083850312156146ba57600080fd5b823567ffffffffffffffff8111156146d157600080fd5b8301601f810185136146e257600080fd5b80356146f56146f082614674565b614625565b8181526060918202830184019184820191908884111561471457600080fd5b938501935b838510156147b457848903818112156147325760008081fd5b61473a61456f565b61474387614227565b81526040807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0840112156147775760008081fd5b61477f61456f565b925061478c898901614227565b835287013561479a81614698565b828901528088019190915283529384019391850191614719565b50979650505050505050565b80151581146111b957600080fd5b803561424b816147c0565b600060208083850312156147ec57600080fd5b823567ffffffffffffffff81111561480357600080fd5b8301601f8101851361481457600080fd5b80356148226146f082614674565b81815260a0918202830184019184820191908884111561484157600080fd5b938501935b838510156147b45780858a03121561485e5760008081fd5b614866614598565b61486f86614227565b8152868601357fffffffffffffffffffff00000000000000000000000000000000000000000000811681146148a45760008081fd5b818801526040868101357fffff000000000000000000000000000000000000000000000000000000000000811681146148dd5760008081fd5b9082015260606148ee878201614227565b90820152608086810135614901816147c0565b9082015283529384019391850191614846565b6000806020838503121561492757600080fd5b823567ffffffffffffffff81111561493e57600080fd5b61494a858286016142bf565b90969095509350505050565b602080825282518282018190526000919060409081850190868401855b828110156149c4576149b484835180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16825260209081015163ffffffff16910152565b9284019290850190600101614973565b5091979650505050505050565b6000602082840312156149e357600080fd5b610b69826142a7565b81517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16815260208083015163ffffffff1690820152604081016112c3565b81511515815261020081016020830151614a47602084018261ffff169052565b506040830151614a5f604084018263ffffffff169052565b506060830151614a77606084018263ffffffff169052565b506080830151614a8f608084018263ffffffff169052565b5060a0830151614aa560a084018261ffff169052565b5060c0830151614abd60c084018263ffffffff169052565b5060e0830151614ad360e084018261ffff169052565b506101008381015161ffff9081169184019190915261012080850151909116908301526101408084015163ffffffff90811691840191909152610160808501518216908401526101808085015167ffffffffffffffff16908401526101a080850151909116908301526101c0808401511515908301526101e0808401517fffffffff000000000000000000000000000000000000000000000000000000008116828501525b505092915050565b803563ffffffff8116811461424b57600080fd5b803561ffff8116811461424b57600080fd5b600082601f830112614bb757600080fd5b81356020614bc76146f083614674565b82815260069290921b84018101918181019086841115614be657600080fd5b8286015b84811015614c335760408189031215614c035760008081fd5b614c0b61456f565b614c14826142a7565b8152614c21858301614227565b81860152835291830191604001614bea565b509695505050505050565b60008060408385031215614c5157600080fd5b67ffffffffffffffff83351115614c6757600080fd5b83601f843585010112614c7957600080fd5b614c896146f08435850135614674565b8335840180358083526020808401939260059290921b90910101861015614caf57600080fd5b602085358601015b85358601803560051b01602001811015614ebc5767ffffffffffffffff81351115614ce157600080fd5b8035863587010160407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0828a03011215614d1a57600080fd5b614d2261456f565b614d2e602083016142a7565b815267ffffffffffffffff60408301351115614d4957600080fd5b88603f604084013584010112614d5e57600080fd5b614d746146f06020604085013585010135614674565b6020604084810135850182810135808552928401939260e00201018b1015614d9b57600080fd5b6040808501358501015b6040858101358601602081013560e0020101811015614e9d5760e0818d031215614dce57600080fd5b614dd661456f565b614ddf82614227565b815260c07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0838f03011215614e1357600080fd5b614e1b6145bb565b614e2760208401614b80565b8152614e3560408401614b80565b6020820152614e4660608401614b94565b6040820152614e5760808401614b80565b6060820152614e6860a08401614b80565b6080820152614e7a60c08401356147c0565b60c083013560a0820152602082810191909152908452929092019160e001614da5565b5080602084015250508085525050602083019250602081019050614cb7565b5092505067ffffffffffffffff60208401351115614ed957600080fd5b614ee98460208501358501614ba6565b90509250929050565b600082601f830112614f0357600080fd5b81356020614f136146f083614674565b8083825260208201915060208460051b870101935086841115614f3557600080fd5b602086015b84811015614c3357614f4b81614227565b8352918301918301614f3a565b60008060408385031215614f6b57600080fd5b823567ffffffffffffffff80821115614f8357600080fd5b614f8f86838701614ef2565b93506020850135915080821115614fa557600080fd5b50614fb285828601614ef2565b9150509250929050565b60008083601f840112614fce57600080fd5b50813567ffffffffffffffff811115614fe657600080fd5b60208301915083602082850101111561224157600080fd5b6000806000806040858703121561501457600080fd5b843567ffffffffffffffff8082111561502c57600080fd5b61503888838901614fbc565b9096509450602087013591508082111561505157600080fd5b5061505e87828801614fbc565b95989497509550505050565b6000806040838503121561507d57600080fd5b615086836142a7565b9150614ee960208401614227565b6000602082840312156150a657600080fd5b813567ffffffffffffffff808211156150be57600080fd5b90830190604082860312156150d257600080fd5b6150da61456f565b8235828111156150e957600080fd5b6150f587828601614ef2565b82525060208301358281111561510a57600080fd5b61511687828601614ef2565b60208301525095945050505050565b80357fffffffff000000000000000000000000000000000000000000000000000000008116811461424b57600080fd5b6000602080838503121561516857600080fd5b823567ffffffffffffffff81111561517f57600080fd5b8301601f8101851361519057600080fd5b803561519e6146f082614674565b81815261022091820283018401918482019190888411156151be57600080fd5b938501935b838510156147b457848903818112156151dc5760008081fd5b6151e461456f565b6151ed876142a7565b8152610200807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0840112156152225760008081fd5b61522a6145de565b92506152378989016147ce565b83526040615246818a01614b94565b8a8501526060615257818b01614b80565b828601526080915061526a828b01614b80565b9085015260a061527b8a8201614b80565b8286015260c0915061528e828b01614b94565b9085015260e061529f8a8201614b80565b8286015261010091506152b3828b01614b94565b908501526101206152c58a8201614b94565b8286015261014091506152d9828b01614b94565b908501526101606152eb8a8201614b80565b8286015261018091506152ff828b01614b80565b908501526101a06153118a82016142a7565b828601526101c09150615325828b01614b80565b908501526101e06153378a82016147ce565b82860152615346838b01615125565b90850152505080880191909152835293840193918501916151c3565b6000602080838503121561537557600080fd5b823567ffffffffffffffff81111561538c57600080fd5b8301601f8101851361539d57600080fd5b80356153ab6146f082614674565b81815260069190911b820183019083810190878311156153ca57600080fd5b928401925b8284101561541c57604084890312156153e85760008081fd5b6153f061456f565b6153f985614227565b81526154068686016142a7565b81870152825260409390930192908401906153cf565b979650505050505050565b60008060008060006080868803121561543f57600080fd5b615448866142a7565b945061545660208701614227565b935060408601359250606086013567ffffffffffffffff81111561547957600080fd5b61548588828901614fbc565b969995985093965092949392505050565b8381528215156020820152606060408201526000612e6060608301846143b2565b600080604083850312156154ca57600080fd5b6154d3836142a7565b9150602083013567ffffffffffffffff8111156154ef57600080fd5b830160a0818603121561550157600080fd5b809150509250929050565b6000806040838503121561551f57600080fd5b61552883614227565b9150614ee9602084016142a7565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80820281158282048414176112c3576112c3615536565b6000826155b2577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6183360301811261561a57600080fd5b9190910192915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261565957600080fd5b83018035915067ffffffffffffffff82111561567457600080fd5b60200191503681900382131561224157600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126156be57600080fd5b83018035915067ffffffffffffffff8211156156d957600080fd5b6020019150600681901b360382131561224157600080fd5b80357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116811461424b57600080fd5b60006040828403121561572f57600080fd5b61573761456f565b61574083614227565b815261574e602084016156f1565b60208201529392505050565b60006040828403121561576c57600080fd5b61577461456f565b615740836142a7565b6000602080838503121561579057600080fd5b823567ffffffffffffffff8111156157a757600080fd5b8301601f810185136157b857600080fd5b80356157c66146f082614674565b818152606091820283018401918482019190888411156157e557600080fd5b938501935b838510156147b45780858a0312156158025760008081fd5b61580a614602565b61581386614227565b81526158208787016156f1565b878201526040615831818801614b80565b90820152835293840193918501916157ea565b808201808211156112c3576112c3615536565b818103818111156112c3576112c3615536565b60ff81811683821601908111156112c3576112c3615536565b60ff82811682821603908111156112c3576112c3615536565b600181815b808511156158f557817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156158db576158db615536565b808516156158e857918102915b93841c93908002906158a1565b509250929050565b60008261590c575060016112c3565b81615919575060006112c3565b816001811461592f576002811461593957615955565b60019150506112c3565b60ff84111561594a5761594a615536565b50506001821b6112c3565b5060208310610133831016604e8410600b8410161715615978575081810a6112c3565b615982838361589c565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156159b4576159b4615536565b029392505050565b6000610b6960ff8416836158fd565b7fffffffff000000000000000000000000000000000000000000000000000000008135818116916004851015614b785760049490940360031b84901b1690921692915050565b60008085851115615a2157600080fd5b83861115615a2e57600080fd5b5050820193919092039150565b600060408284031215615a4d57600080fd5b615a5561456f565b82518152602083015161574e816147c0565b600060208284031215615a7957600080fd5b5051919050565b805169ffffffffffffffffffff8116811461424b57600080fd5b600080600080600060a08688031215615ab257600080fd5b615abb86615a80565b9450602086015193506040860151925060608601519150615ade60808701615a80565b90509295509295909350565b600060208284031215615afc57600080fd5b8151610b6981614698565b600060408284031215615b1957600080fd5b615b2161456f565b615b2a83614227565b8152602083013560208201528091505092915050565b63ffffffff8181168382160190808211156141c8576141c8615536565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint96\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"linkToken\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"stalenessThreshold\",\"type\":\"uint32\"}],\"internalType\":\"structFeeQuoter.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"priceUpdaters\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"feeTokens\",\"type\":\"address[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"}],\"internalType\":\"structIFeeQuoter.TokenPriceFeedConfig\",\"name\":\"feedConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.TokenPriceFeedUpdate[]\",\"name\":\"tokenPriceFeeds\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigSingleTokenArgs[]\",\"name\":\"tokenTransferFeeConfigs\",\"type\":\"tuple[]\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigArgs[]\",\"name\":\"tokenTransferFeeConfigArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"internalType\":\"structFeeQuoter.PremiumMultiplierWeiPerEthArgs[]\",\"name\":\"premiumMultiplierWeiPerEthArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chain\",\"type\":\"uint64\"}],\"name\":\"ChainNotSupported\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DataFeedValueOutOfUint224Range\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"DestinationChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ExtraArgOutOfOrderExecutionMustBeTrue\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"FeeTokenNotSupported\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"}],\"name\":\"InvalidDestBytesOverhead\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidDestChainConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidEVMAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidExtraArgsTag\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidStaticConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"msgFeeJuels\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint256\"}],\"name\":\"MessageFeeTooHigh\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MessageGasLimitTooHigh\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"maxSize\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualSize\",\"type\":\"uint256\"}],\"name\":\"MessageTooLarge\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"internalType\":\"bytes10\",\"name\":\"workflowName\",\"type\":\"bytes10\"},{\"internalType\":\"bytes2\",\"name\":\"reportName\",\"type\":\"bytes2\"}],\"name\":\"ReportForwarderUnauthorized\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"SourceTokenDataTooLarge\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"threshold\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timePassed\",\"type\":\"uint256\"}],\"name\":\"StaleGasPrice\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feedTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"storedTimeStamp\",\"type\":\"uint256\"}],\"name\":\"StaleKeystoneUpdate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"TokenNotSupported\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"UnauthorizedCaller\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnsupportedNumberOfTokens\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"AuthorizedCallerAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"AuthorizedCallerRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"indexed\":false,\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"name\":\"DestChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"indexed\":false,\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"name\":\"DestChainConfigUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"}],\"name\":\"FeeTokenAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"}],\"name\":\"FeeTokenRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"name\":\"PremiumMultiplierWeiPerEthUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"}],\"indexed\":false,\"internalType\":\"structIFeeQuoter.TokenPriceFeedConfig\",\"name\":\"priceFeedConfig\",\"type\":\"tuple\"}],\"name\":\"PriceFeedPerTokenUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"reportId\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"},{\"internalType\":\"bytes10\",\"name\":\"workflowName\",\"type\":\"bytes10\"},{\"internalType\":\"bytes2\",\"name\":\"reportName\",\"type\":\"bytes2\"},{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isAllowed\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"structKeystoneFeedsPermissionHandler.Permission\",\"name\":\"permission\",\"type\":\"tuple\"}],\"name\":\"ReportPermissionSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"TokenTransferFeeConfigDeleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"name\":\"TokenTransferFeeConfigUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"UsdPerTokenUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChain\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"UsdPerUnitGasUpdated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address[]\",\"name\":\"addedCallers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"removedCallers\",\"type\":\"address[]\"}],\"internalType\":\"structAuthorizedCallers.AuthorizedCallerArgs\",\"name\":\"authorizedCallerArgs\",\"type\":\"tuple\"}],\"name\":\"applyAuthorizedCallerUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyDestChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"feeTokensToAdd\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"feeTokensToRemove\",\"type\":\"address[]\"}],\"name\":\"applyFeeTokensUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"internalType\":\"structFeeQuoter.PremiumMultiplierWeiPerEthArgs[]\",\"name\":\"premiumMultiplierWeiPerEthArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyPremiumMultiplierWeiPerEthUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigSingleTokenArgs[]\",\"name\":\"tokenTransferFeeConfigs\",\"type\":\"tuple[]\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigArgs[]\",\"name\":\"tokenTransferFeeConfigArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigRemoveArgs[]\",\"name\":\"tokensToUseDefaultFeeConfigs\",\"type\":\"tuple[]\"}],\"name\":\"applyTokenTransferFeeConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"fromToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fromTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"toToken\",\"type\":\"address\"}],\"name\":\"convertTokenAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllAuthorizedCallers\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getDestChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getDestinationChainGasPrice\",\"outputs\":[{\"components\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"internalType\":\"structInternal.TimestampedPackedUint224\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getFeeTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getPremiumMultiplierWeiPerEth\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint96\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"linkToken\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"stalenessThreshold\",\"type\":\"uint32\"}],\"internalType\":\"structFeeQuoter.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getTokenAndGasPrices\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"tokenPrice\",\"type\":\"uint224\"},{\"internalType\":\"uint224\",\"name\":\"gasPriceValue\",\"type\":\"uint224\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenPrice\",\"outputs\":[{\"components\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"internalType\":\"structInternal.TimestampedPackedUint224\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenPriceFeedConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"}],\"internalType\":\"structIFeeQuoter.TokenPriceFeedConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"tokens\",\"type\":\"address[]\"}],\"name\":\"getTokenPrices\",\"outputs\":[{\"components\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"internalType\":\"structInternal.TimestampedPackedUint224[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenTransferFeeConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"getValidatedFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getValidatedTokenPrice\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"\",\"type\":\"uint224\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"onReport\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"name\":\"processMessageArgs\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"msgFeeJuels\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isOutOfOrderExecution\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"convertedExtraArgs\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"rampTokenAmounts\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"sourceTokenAmounts\",\"type\":\"tuple[]\"}],\"name\":\"processPoolReturnData\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"destExecDataPerToken\",\"type\":\"bytes[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"},{\"internalType\":\"bytes10\",\"name\":\"workflowName\",\"type\":\"bytes10\"},{\"internalType\":\"bytes2\",\"name\":\"reportName\",\"type\":\"bytes2\"},{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isAllowed\",\"type\":\"bool\"}],\"internalType\":\"structKeystoneFeedsPermissionHandler.Permission[]\",\"name\":\"permissions\",\"type\":\"tuple[]\"}],\"name\":\"setReportPermissions\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"}],\"name\":\"updatePrices\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"}],\"internalType\":\"structIFeeQuoter.TokenPriceFeedConfig\",\"name\":\"feedConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.TokenPriceFeedUpdate[]\",\"name\":\"tokenPriceFeedUpdates\",\"type\":\"tuple[]\"}],\"name\":\"updateTokenPriceFeeds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x60e06040523480156200001157600080fd5b506040516200775238038062007752833981016040819052620000349162001834565b8533806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf8162000207565b5050604080518082018252838152815160008152602080820190935291810191909152620000ee9150620002b2565b5060208701516001600160a01b0316158062000112575086516001600160601b0316155b80620001265750604087015163ffffffff16155b15620001455760405163d794ef9560e01b815260040160405180910390fd5b6020878101516001600160a01b031660a05287516001600160601b031660805260408089015163ffffffff1660c05280516000815291820190526200018c90869062000401565b620001978462000549565b620001a2816200061a565b620001ad8262000a5a565b60408051600080825260208201909252620001fa91859190620001f3565b6040805180820190915260008082526020820152815260200190600190039081620001cb5790505b5062000b26565b5050505050505062001ae5565b336001600160a01b03821603620002615760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b602081015160005b815181101562000342576000828281518110620002db57620002db62001953565b60209081029190910101519050620002f560028262000e5f565b1562000338576040516001600160a01b03821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b50600101620002ba565b50815160005b8151811015620003fb57600082828151811062000369576200036962001953565b6020026020010151905060006001600160a01b0316816001600160a01b031603620003a7576040516342bcdf7f60e11b815260040160405180910390fd5b620003b460028262000e7f565b506040516001600160a01b03821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a15060010162000348565b50505050565b60005b8251811015620004a2576200044083828151811062000427576200042762001953565b6020026020010151600b62000e7f60201b90919060201c565b1562000499578281815181106200045b576200045b62001953565b60200260200101516001600160a01b03167fdf1b1bd32a69711488d71554706bb130b1fc63a5fa1a2cd85e8440f84065ba2360405160405180910390a25b60010162000404565b5060005b81518110156200054457620004e2828281518110620004c957620004c962001953565b6020026020010151600b62000e9660201b90919060201c565b156200053b57818181518110620004fd57620004fd62001953565b60200260200101516001600160a01b03167f1795838dc8ab2ffc5f431a1729a6afa0b587f982f7b2be0b9d7187a1ef547f9160405160405180910390a25b600101620004a6565b505050565b60005b8151811015620006165760008282815181106200056d576200056d62001953565b6020908102919091018101518051818301516001600160a01b0380831660008181526007875260409081902084518154868a018051929096166001600160a81b03199091168117600160a01b60ff9384160217909255825191825293519093169683019690965293955091939092917f08a5f7f5bb38a81d8e43aca13ecd76431dbf8816ae4699affff7b00b2fc1c464910160405180910390a25050508060010190506200054c565b5050565b60005b8151811015620006165760008282815181106200063e576200063e62001953565b6020026020010151905060008383815181106200065f576200065f62001953565b6020026020010151600001519050600082602001519050816001600160401b03166000148062000698575061016081015163ffffffff16155b80620006ba57506101e08101516001600160e01b031916630a04b54b60e21b14155b80620006da5750806060015163ffffffff1681610160015163ffffffff16115b15620007055760405163c35aa79d60e01b81526001600160401b038316600482015260240162000083565b6001600160401b038216600090815260096020526040812060010154600160881b900460e01b6001600160e01b03191690036200078557816001600160401b03167fd31c671936387b2f84ed402b553bd50c0e9c20408ea4e91a836d77b8180fb7248260405162000777919062001969565b60405180910390a2620007c9565b816001600160401b03167f1edd6f3553cfa16f10b95b195abae3a1cfca4783de4843f95d674b1e1df5ab2082604051620007c0919062001969565b60405180910390a25b8060096000846001600160401b03166001600160401b0316815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548161ffff021916908361ffff16021790555060408201518160000160036101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160076101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600b6101000a81548163ffffffff021916908363ffffffff16021790555060a082015181600001600f6101000a81548161ffff021916908361ffff16021790555060c08201518160000160116101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160000160156101000a81548161ffff021916908361ffff1602179055506101008201518160000160176101000a81548161ffff021916908361ffff1602179055506101208201518160000160196101000a81548161ffff021916908361ffff16021790555061014082015181600001601b6101000a81548163ffffffff021916908363ffffffff1602179055506101608201518160010160006101000a81548163ffffffff021916908363ffffffff1602179055506101808201518160010160046101000a8154816001600160401b0302191690836001600160401b031602179055506101a082015181600101600c6101000a81548163ffffffff021916908363ffffffff1602179055506101c08201518160010160106101000a81548160ff0219169083151502179055506101e08201518160010160116101000a81548163ffffffff021916908360e01c02179055509050505050508060010190506200061d565b60005b81518110156200061657600082828151811062000a7e5762000a7e62001953565b6020026020010151600001519050600083838151811062000aa35762000aa362001953565b6020908102919091018101518101516001600160a01b03841660008181526008845260409081902080546001600160401b0319166001600160401b0385169081179091559051908152919350917fbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d910160405180910390a2505060010162000a5d565b60005b825181101562000d9957600083828151811062000b4a5762000b4a62001953565b6020026020010151905060008160000151905060005b82602001515181101562000d8a5760008360200151828151811062000b895762000b8962001953565b602002602001015160200151905060008460200151838151811062000bb25762000bb262001953565b6020026020010151600001519050602063ffffffff16826080015163ffffffff16101562000c115760808201516040516312766e0160e11b81526001600160a01b038316600482015263ffffffff909116602482015260440162000083565b6001600160401b0384166000818152600a602090815260408083206001600160a01b0386168085529083529281902086518154938801518389015160608a015160808b015160a08c01511515600160901b0260ff60901b1963ffffffff928316600160701b021664ffffffffff60701b199383166a01000000000000000000000263ffffffff60501b1961ffff90961668010000000000000000029590951665ffffffffffff60401b19968416640100000000026001600160401b0319909b16939097169290921798909817939093169390931717919091161792909217909155519091907f94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b59062000d77908690600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60405180910390a3505060010162000b60565b50505080600101905062000b29565b5060005b81518110156200054457600082828151811062000dbe5762000dbe62001953565b6020026020010151600001519050600083838151811062000de35762000de362001953565b6020908102919091018101518101516001600160401b0384166000818152600a845260408082206001600160a01b038516808452955280822080546001600160981b03191690555192945090917f4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b9190a3505060010162000d9d565b600062000e76836001600160a01b03841662000ead565b90505b92915050565b600062000e76836001600160a01b03841662000fb1565b600062000e76836001600160a01b03841662001003565b6000818152600183016020526040812054801562000fa657600062000ed460018362001aad565b855490915060009062000eea9060019062001aad565b905081811462000f5657600086600001828154811062000f0e5762000f0e62001953565b906000526020600020015490508087600001848154811062000f345762000f3462001953565b6000918252602080832090910192909255918252600188019052604090208390555b855486908062000f6a5762000f6a62001acf565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505062000e79565b600091505062000e79565b600081815260018301602052604081205462000ffa5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000e79565b50600062000e79565b6000818152600183016020526040812054801562000fa65760006200102a60018362001aad565b8554909150600090620010409060019062001aad565b905080821462000f5657600086600001828154811062000f0e5762000f0e62001953565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b03811182821017156200109f576200109f62001064565b60405290565b60405160c081016001600160401b03811182821017156200109f576200109f62001064565b60405161020081016001600160401b03811182821017156200109f576200109f62001064565b604051601f8201601f191681016001600160401b03811182821017156200111b576200111b62001064565b604052919050565b80516001600160a01b03811681146200113b57600080fd5b919050565b805163ffffffff811681146200113b57600080fd5b6000606082840312156200116857600080fd5b604051606081016001600160401b03811182821017156200118d576200118d62001064565b604052825190915081906001600160601b0381168114620011ad57600080fd5b8152620011bd6020840162001123565b6020820152620011d06040840162001140565b60408201525092915050565b60006001600160401b03821115620011f857620011f862001064565b5060051b60200190565b600082601f8301126200121457600080fd5b815160206200122d6200122783620011dc565b620010f0565b8083825260208201915060208460051b8701019350868411156200125057600080fd5b602086015b848110156200127757620012698162001123565b835291830191830162001255565b509695505050505050565b600082601f8301126200129457600080fd5b81516020620012a76200122783620011dc565b82815260609283028501820192828201919087851115620012c757600080fd5b8387015b858110156200135a5780890382811215620012e65760008081fd5b620012f06200107a565b620012fb8362001123565b8152604080601f1984011215620013125760008081fd5b6200131c6200107a565b92506200132b88850162001123565b835283015160ff81168114620013415760008081fd5b82880152808701919091528452928401928101620012cb565b5090979650505050505050565b80516001600160401b03811681146200113b57600080fd5b805161ffff811681146200113b57600080fd5b805180151581146200113b57600080fd5b600082601f830112620013b557600080fd5b81516020620013c86200122783620011dc565b82815260059290921b84018101918181019086841115620013e857600080fd5b8286015b84811015620012775780516001600160401b03808211156200140d57600080fd5b908801906040601f19838c0381018213156200142857600080fd5b620014326200107a565b6200143f89860162001367565b815282850151848111156200145357600080fd5b8086019550508c603f8601126200146957600080fd5b8885015193506200147e6200122785620011dc565b84815260e09094028501830193898101908e8611156200149d57600080fd5b958401955b858710156200157657868f0360e0811215620014bd57600080fd5b620014c76200107a565b620014d28962001123565b815260c08683011215620014e557600080fd5b620014ef620010a5565b9150620014fe8d8a0162001140565b82526200150d878a0162001140565b8d8301526200151f60608a016200137f565b878301526200153160808a0162001140565b60608301526200154460a08a0162001140565b60808301526200155760c08a0162001392565b60a0830152808d0191909152825260e09690960195908a0190620014a2565b828b015250875250505092840192508301620013ec565b600082601f8301126200159f57600080fd5b81516020620015b26200122783620011dc565b82815260069290921b84018101918181019086841115620015d257600080fd5b8286015b84811015620012775760408189031215620015f15760008081fd5b620015fb6200107a565b620016068262001123565b81526200161585830162001367565b81860152835291830191604001620015d6565b80516001600160e01b0319811681146200113b57600080fd5b600082601f8301126200165357600080fd5b81516020620016666200122783620011dc565b82815261022092830285018201928282019190878511156200168757600080fd5b8387015b858110156200135a5780890382811215620016a65760008081fd5b620016b06200107a565b620016bb8362001367565b815261020080601f1984011215620016d35760008081fd5b620016dd620010ca565b9250620016ec88850162001392565b83526040620016fd8186016200137f565b8985015260606200171081870162001140565b82860152608091506200172582870162001140565b9085015260a06200173886820162001140565b8286015260c091506200174d8287016200137f565b9085015260e06200176086820162001140565b828601526101009150620017768287016200137f565b908501526101206200178a8682016200137f565b828601526101409150620017a08287016200137f565b90850152610160620017b486820162001140565b828601526101809150620017ca82870162001140565b908501526101a0620017de86820162001367565b828601526101c09150620017f482870162001140565b908501526101e06200180886820162001392565b828601526200181983870162001628565b9085015250508087019190915284529284019281016200168b565b6000806000806000806000610120888a0312156200185157600080fd5b6200185d898962001155565b60608901519097506001600160401b03808211156200187b57600080fd5b620018898b838c0162001202565b975060808a0151915080821115620018a057600080fd5b620018ae8b838c0162001202565b965060a08a0151915080821115620018c557600080fd5b620018d38b838c0162001282565b955060c08a0151915080821115620018ea57600080fd5b620018f88b838c01620013a3565b945060e08a01519150808211156200190f57600080fd5b6200191d8b838c016200158d565b93506101008a01519150808211156200193557600080fd5b50620019448a828b0162001641565b91505092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b815115158152610200810160208301516200198a602084018261ffff169052565b506040830151620019a3604084018263ffffffff169052565b506060830151620019bc606084018263ffffffff169052565b506080830151620019d5608084018263ffffffff169052565b5060a0830151620019ec60a084018261ffff169052565b5060c083015162001a0560c084018263ffffffff169052565b5060e083015162001a1c60e084018261ffff169052565b506101008381015161ffff9081169184019190915261012080850151909116908301526101408084015163ffffffff9081169184019190915261016080850151821690840152610180808501516001600160401b0316908401526101a080850151909116908301526101c0808401511515908301526101e0928301516001600160e01b031916929091019190915290565b8181038181111562000e7957634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b60805160a05160c051615c1362001b3f600039600081816102ef0152818161220b01526122740152600081816102b301528181611917015261197701526000818161027f015281816119a00152611a100152615c136000f3fe608060405234801561001057600080fd5b50600436106101ce5760003560e01c806379ba509711610104578063a69c64c0116100a2578063d02641a011610071578063d02641a014610a81578063d8694ccd14610a94578063f2fde38b14610aa7578063ffdb4b3714610aba57600080fd5b8063a69c64c014610997578063bf78e03f146109aa578063c4276bfc14610a57578063cdc73d5114610a7957600080fd5b806382b49eb0116100de57806382b49eb0146107d95780638da5cb5b1461094957806391a2749a146109715780639ea600261461098457600080fd5b806379ba5097146107ab5780637afac322146107b3578063805f2132146107c657600080fd5b8063407e1086116101715780634ab35b0b1161014b5780634ab35b0b14610441578063514e8cff146104815780636def4ce714610524578063770e2dc41461079857600080fd5b8063407e1086146103fb57806341ed29e71461040e57806345ac924d1461042157600080fd5b8063085318f8116101ad578063085318f814610368578063181f5a77146103885780632451a627146103d15780633937306f146103e657600080fd5b806241e5be146101d3578063061877e3146101f957806306285c6914610252575b600080fd5b6101e66101e13660046142ca565b610b02565b6040519081526020015b60405180910390f35b610239610207366004614306565b73ffffffffffffffffffffffffffffffffffffffff1660009081526008602052604090205467ffffffffffffffff1690565b60405167ffffffffffffffff90911681526020016101f0565b61031c604080516060810182526000808252602082018190529181019190915260405180606001604052807f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000063ffffffff16815250905090565b6040805182516bffffffffffffffffffffffff16815260208084015173ffffffffffffffffffffffffffffffffffffffff16908201529181015163ffffffff16908201526060016101f0565b61037b61037636600461437e565b610b70565b6040516101f09190614490565b6103c46040518060400160405280601381526020017f46656551756f74657220312e362e302d6465760000000000000000000000000081525081565b6040516101f09190614512565b6103d9610ee2565b6040516101f09190614525565b6103f96103f436600461457f565b610ef3565b005b6103f9610409366004614721565b6111a8565b6103f961041c366004614853565b6111bc565b61043461042f36600461498e565b6111fe565b6040516101f091906149d0565b61045461044f366004614306565b6112c9565b6040517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff90911681526020016101f0565b61051761048f366004614a4b565b60408051808201909152600080825260208201525067ffffffffffffffff166000908152600560209081526040918290208251808401909352547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811683527c0100000000000000000000000000000000000000000000000000000000900463ffffffff169082015290565b6040516101f09190614a66565b61078b610532366004614a4b565b6040805161020081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a081018290526101c081018290526101e08101919091525067ffffffffffffffff908116600090815260096020908152604091829020825161020081018452815460ff8082161515835261ffff61010080840482169685019690965263ffffffff630100000084048116978501979097526701000000000000008304871660608501526b0100000000000000000000008304871660808501526f010000000000000000000000000000008304811660a085015271010000000000000000000000000000000000808404881660c086015275010000000000000000000000000000000000000000008404821660e08087019190915277010000000000000000000000000000000000000000000000850483169786019790975279010000000000000000000000000000000000000000000000000084049091166101208501527b01000000000000000000000000000000000000000000000000000000909204861661014084015260019093015480861661016084015264010000000081049096166101808301526c0100000000000000000000000086049094166101a0820152700100000000000000000000000000000000850490911615156101c08201527fffffffff0000000000000000000000000000000000000000000000000000000092909304901b166101e082015290565b6040516101f09190614aa1565b6103f96107a6366004614cb8565b6112d4565b6103f96112e6565b6103f96107c1366004614fd2565b6113e3565b6103f96107d4366004615078565b6113f5565b6108e96107e73660046150e4565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101919091525067ffffffffffffffff919091166000908152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff94909416835292815290829020825160c081018452905463ffffffff8082168352640100000000820481169383019390935268010000000000000000810461ffff16938201939093526a01000000000000000000008304821660608201526e01000000000000000000000000000083049091166080820152720100000000000000000000000000000000000090910460ff16151560a082015290565b6040516101f09190600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101f0565b6103f961097f36600461510e565b6118dd565b6103f96109923660046151cf565b6118ee565b6103f96109a53660046153dc565b6118ff565b610a236109b8366004614306565b6040805180820182526000808252602091820181905273ffffffffffffffffffffffffffffffffffffffff93841681526007825282902082518084019093525492831682527401000000000000000000000000000000000000000090920460ff169181019190915290565b60408051825173ffffffffffffffffffffffffffffffffffffffff16815260209283015160ff1692810192909252016101f0565b610a6a610a653660046154a1565b611910565b6040516101f093929190615510565b6103d9611b06565b610517610a8f366004614306565b611b12565b6101e6610aa2366004615531565b611c0e565b6103f9610ab5366004614306565b612126565b610acd610ac8366004615586565b612137565b604080517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff9384168152929091166020830152016101f0565b6000610b0d826122c2565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16610b34856122c2565b610b5c907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16856155df565b610b6691906155f6565b90505b9392505050565b67ffffffffffffffff8086166000908152600960205260409020600101546060917101000000000000000000000000000000000090910460e01b908590811115610bbc57610bbc6145ba565b604051908082528060200260200182016040528015610bef57816020015b6060815260200190600190039081610bda5790505b50915060005b85811015610ed7576000858583818110610c1157610c11615631565b610c279260206040909202019081019150614306565b90506000888884818110610c3d57610c3d615631565b9050602002810190610c4f9190615660565b610c5d90604081019061569e565b9150506020811115610d125767ffffffffffffffff8a166000908152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff861684529091529020546e010000000000000000000000000000900463ffffffff16811115610d12576040517f36f536ca00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526024015b60405180910390fd5b610d82848a8a86818110610d2857610d28615631565b9050602002810190610d3a9190615660565b610d4890602081019061569e565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061235c92505050565b67ffffffffffffffff8a166000818152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684528252808320815160c081018352905463ffffffff8082168352640100000000820481168386015268010000000000000000820461ffff16838501526a01000000000000000000008204811660608401526e010000000000000000000000000000820481166080840152720100000000000000000000000000000000000090910460ff16151560a08301908152958552600990935290832054935190937b0100000000000000000000000000000000000000000000000000000090049091169190610e815781610e87565b82606001515b6040805163ffffffff8316602082015291925001604051602081830303815290604052888781518110610ebc57610ebc615631565b60200260200101819052505050505050806001019050610bf5565b505095945050505050565b6060610eee60026123b3565b905090565b610efb6123c0565b6000610f078280615703565b9050905060005b81811015611051576000610f228480615703565b83818110610f3257610f32615631565b905060400201803603810190610f489190615797565b604080518082018252602080840180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff908116845263ffffffff42818116858701908152885173ffffffffffffffffffffffffffffffffffffffff9081166000908152600690975295889020965190519092167c010000000000000000000000000000000000000000000000000000000002919092161790935584519051935194955016927f52f50aa6d1a95a4595361ecf953d095f125d442e4673716dede699e049de148a926110409290917bffffffffffffffffffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b60405180910390a250600101610f0e565b5060006110616020840184615703565b9050905060005b818110156111a257600061107f6020860186615703565b8381811061108f5761108f615631565b9050604002018036038101906110a591906157d4565b604080518082018252602080840180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff908116845263ffffffff42818116858701908152885167ffffffffffffffff9081166000908152600590975295889020965190519092167c010000000000000000000000000000000000000000000000000000000002919092161790935584519051935194955016927fdd84a3fa9ef9409f550d54d6affec7e9c480c878c6ab27b78912a03e1b371c6e926111919290917bffffffffffffffffffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b60405180910390a250600101611068565b50505050565b6111b0612405565b6111b981612486565b50565b6111c4612405565b60005b81518110156111fa576111f28282815181106111e5576111e5615631565b6020026020010151612584565b6001016111c7565b5050565b60608160008167ffffffffffffffff81111561121c5761121c6145ba565b60405190808252806020026020018201604052801561126157816020015b604080518082019091526000808252602082015281526020019060019003908161123a5790505b50905060005b828110156112be5761129986868381811061128457611284615631565b9050602002016020810190610a8f9190614306565b8282815181106112ab576112ab615631565b6020908102919091010152600101611267565b509150505b92915050565b60006112c3826122c2565b6112dc612405565b6111fa8282612756565b60015473ffffffffffffffffffffffffffffffffffffffff163314611367576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610d09565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6113eb612405565b6111fa8282612b63565b600080600061143987878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612caa92505050565b92509250925061144b33838584612cc5565b6000611459858701876157f7565b905060005b81518110156118d25760006007600084848151811061147f5761147f615631565b6020908102919091018101515173ffffffffffffffffffffffffffffffffffffffff16825281019190915260400160009081205474010000000000000000000000000000000000000000900460ff169150819003611540578282815181106114e9576114e9615631565b6020908102919091010151516040517f06439c6b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610d09565b600061158960128386868151811061155a5761155a615631565b6020026020010151602001517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16612e1d565b9050600660008585815181106115a1576115a1615631565b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001601c9054906101000a900463ffffffff1663ffffffff1684848151811061161357611613615631565b60200260200101516040015163ffffffff16101561171d5783838151811061163d5761163d615631565b60200260200101516000015184848151811061165b5761165b615631565b6020026020010151604001516006600087878151811061167d5761167d615631565b6020908102919091018101515173ffffffffffffffffffffffffffffffffffffffff90811683529082019290925260409081016000205490517f191ec70600000000000000000000000000000000000000000000000000000000815293909116600484015263ffffffff91821660248401527c01000000000000000000000000000000000000000000000000000000009004166044820152606401610d09565b6040518060400160405280827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16815260200185858151811061175e5761175e615631565b60200260200101516040015163ffffffff168152506006600086868151811061178957611789615631565b6020908102919091018101515173ffffffffffffffffffffffffffffffffffffffff168252818101929092526040016000208251929091015163ffffffff167c0100000000000000000000000000000000000000000000000000000000027bffffffffffffffffffffffffffffffffffffffffffffffffffffffff909216919091179055835184908490811061182157611821615631565b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff167f52f50aa6d1a95a4595361ecf953d095f125d442e4673716dede699e049de148a8286868151811061187757611877615631565b6020026020010151604001516040516118c09291907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff92909216825263ffffffff16602082015260400190565b60405180910390a2505060010161145e565b505050505050505050565b6118e5612405565b6111b981612ee3565b6118f6612405565b6111b98161306f565b611907612405565b6111b981613515565b60008060607f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff16036119705785925061199e565b61199b87877f0000000000000000000000000000000000000000000000000000000000000000610b02565b92505b7f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff16831115611a3d576040517f6a92a483000000000000000000000000000000000000000000000000000000008152600481018490526bffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166024820152604401610d09565b67ffffffffffffffff881660009081526009602052604081206001015463ffffffff1690611a6c8787846135ff565b9050806020015193508484611af3836040805182516024820152602092830151151560448083019190915282518083039091018152606490910190915290810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f181dcf100000000000000000000000000000000000000000000000000000000017905290565b9450945094505050955095509592505050565b6060610eee600b6123b3565b604080518082019091526000808252602082015273ffffffffffffffffffffffffffffffffffffffff8281166000908152600760209081526040918290208251808401909352549283168083527401000000000000000000000000000000000000000090930460ff169082015290611c0557505073ffffffffffffffffffffffffffffffffffffffff166000908152600660209081526040918290208251808401909352547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811683527c0100000000000000000000000000000000000000000000000000000000900463ffffffff169082015290565b610b69816137a8565b67ffffffffffffffff8083166000908152600960209081526040808320815161020081018352815460ff808216151580845261ffff61010080850482169886019890985263ffffffff630100000085048116978601979097526701000000000000008404871660608601526b0100000000000000000000008404871660808601526f010000000000000000000000000000008404811660a086015271010000000000000000000000000000000000808504881660c087015275010000000000000000000000000000000000000000008504821660e08088019190915277010000000000000000000000000000000000000000000000860483169987019990995279010000000000000000000000000000000000000000000000000085049091166101208601527b01000000000000000000000000000000000000000000000000000000909304861661014085015260019094015480861661016085015264010000000081049098166101808401526c0100000000000000000000000088049094166101a0830152700100000000000000000000000000000000870490931615156101c08201527fffffffff000000000000000000000000000000000000000000000000000000009290950490921b166101e0840152909190611e28576040517f99ac52f200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff85166004820152602401610d09565b611e43611e3b6080850160608601614306565b600b90613937565b611ea257611e576080840160608501614306565b6040517f2502348c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610d09565b6000611eb16040850185615703565b9150611f0d905082611ec6602087018761569e565b905083611ed3888061569e565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061396692505050565b6000600881611f226080880160608901614306565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160009081205467ffffffffffffffff16915080611f71611f6b6080890160608a01614306565b89612137565b9092509050600080808615611fb757611fab888c611f9560808e0160608f01614306565b888e8060400190611fa69190615703565b613a10565b91945092509050611fd7565b6101a0880151611fd49063ffffffff16662386f26fc100006155df565b92505b61010088015160009061ffff161561201b57612018896dffffffffffffffffffffffffffff607088901c1661200f60208f018f61569e565b90508b86613ce8565b90505b61018089015160009067ffffffffffffffff1661204461203e60808f018f61569e565b8d613d98565b600001518563ffffffff168c60a0015161ffff168f8060200190612068919061569e565b6120739291506155df565b8d6080015163ffffffff1661208891906158be565b61209291906158be565b61209c91906158be565b6120b6906dffffffffffffffffffffffffffff89166155df565b6120c091906155df565b90507bffffffffffffffffffffffffffffffffffffffffffffffffffffffff871682826120f767ffffffffffffffff8c16896155df565b61210191906158be565b61210b91906158be565b61211591906155f6565b9d9c50505050505050505050505050565b61212e612405565b6111b981613e59565b67ffffffffffffffff811660009081526005602090815260408083208151808301909252547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811682527c0100000000000000000000000000000000000000000000000000000000900463ffffffff16918101829052829182036121ef576040517f2e59db3a00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff85166004820152602401610d09565b6000816020015163ffffffff164261220791906158d1565b90507f000000000000000000000000000000000000000000000000000000000000000063ffffffff168111156122a8576040517ff08bcb3e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8616600482015263ffffffff7f000000000000000000000000000000000000000000000000000000000000000016602482015260448101829052606401610d09565b6122b1866122c2565b9151919350909150505b9250929050565b6000806122ce83611b12565b9050806020015163ffffffff1660001480612306575080517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16155b15612355576040517f06439c6b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152602401610d09565b5192915050565b7fd7ed2ad4000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316016111fa576123ae81613f4e565b505050565b60606000610b6983614001565b6123cb600233613937565b612403576040517fd86ad9cf000000000000000000000000000000000000000000000000000000008152336004820152602401610d09565b565b60005473ffffffffffffffffffffffffffffffffffffffff163314612403576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610d09565b60005b81518110156111fa5760008282815181106124a6576124a6615631565b60209081029190910181015180518183015173ffffffffffffffffffffffffffffffffffffffff80831660008181526007875260409081902084518154868a018051929096167fffffffffffffffffffffff00000000000000000000000000000000000000000090911681177401000000000000000000000000000000000000000060ff9384160217909255825191825293519093169683019690965293955091939092917f08a5f7f5bb38a81d8e43aca13ecd76431dbf8816ae4699affff7b00b2fc1c464910160405180910390a2505050806001019050612489565b600061263d82600001518360600151846020015185604001516040805173ffffffffffffffffffffffffffffffffffffffff80871660208301528516918101919091527fffffffffffffffffffff00000000000000000000000000000000000000000000831660608201527fffff0000000000000000000000000000000000000000000000000000000000008216608082015260009060a001604051602081830303815290604052805190602001209050949350505050565b60808301516000828152600460205260409081902080549215157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00909316929092179091555190915081907f32a4ba3fa3351b11ad555d4c8ec70a744e8705607077a946807030d64b6ab1a39061274a908590600060a08201905073ffffffffffffffffffffffffffffffffffffffff8084511683527fffffffffffffffffffff0000000000000000000000000000000000000000000060208501511660208401527fffff00000000000000000000000000000000000000000000000000000000000060408501511660408401528060608501511660608401525060808301511515608083015292915050565b60405180910390a25050565b60005b8251811015612a7f57600083828151811061277657612776615631565b6020026020010151905060008160000151905060005b826020015151811015612a71576000836020015182815181106127b1576127b1615631565b60200260200101516020015190506000846020015183815181106127d7576127d7615631565b6020026020010151600001519050602063ffffffff16826080015163ffffffff16101561285a5760808201516040517f24ecdc0200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8316600482015263ffffffff9091166024820152604401610d09565b67ffffffffffffffff84166000818152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff86168085529083529281902086518154938801518389015160608a015160808b015160a08c015115157201000000000000000000000000000000000000027fffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffff63ffffffff9283166e01000000000000000000000000000002167fffffffffffffffffffffffffff0000000000ffffffffffffffffffffffffffff9383166a0100000000000000000000027fffffffffffffffffffffffffffffffffffff00000000ffffffffffffffffffff61ffff9096166801000000000000000002959095167fffffffffffffffffffffffffffffffffffff000000000000ffffffffffffffff968416640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000909b16939097169290921798909817939093169390931717919091161792909217909155519091907f94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b590612a5f908690600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60405180910390a3505060010161278c565b505050806001019050612759565b5060005b81518110156123ae576000828281518110612aa057612aa0615631565b60200260200101516000015190506000838381518110612ac257612ac2615631565b60209081029190910181015181015167ffffffffffffffff84166000818152600a8452604080822073ffffffffffffffffffffffffffffffffffffffff8516808452955280822080547fffffffffffffffffffffffffff000000000000000000000000000000000000001690555192945090917f4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b9190a35050600101612a83565b60005b8251811015612c0657612b9c838281518110612b8457612b84615631565b6020026020010151600b61405d90919063ffffffff16565b15612bfe57828181518110612bb357612bb3615631565b602002602001015173ffffffffffffffffffffffffffffffffffffffff167fdf1b1bd32a69711488d71554706bb130b1fc63a5fa1a2cd85e8440f84065ba2360405160405180910390a25b600101612b66565b5060005b81518110156123ae57612c40828281518110612c2857612c28615631565b6020026020010151600b61407f90919063ffffffff16565b15612ca257818181518110612c5757612c57615631565b602002602001015173ffffffffffffffffffffffffffffffffffffffff167f1795838dc8ab2ffc5f431a1729a6afa0b587f982f7b2be0b9d7187a1ef547f9160405160405180910390a25b600101612c0a565b6040810151604a820151605e90920151909260609290921c91565b6040805173ffffffffffffffffffffffffffffffffffffffff868116602080840191909152908616828401527fffffffffffffffffffff00000000000000000000000000000000000000000000851660608301527fffff00000000000000000000000000000000000000000000000000000000000084166080808401919091528351808403909101815260a09092018352815191810191909120600081815260049092529190205460ff16612e16576040517f097e17ff00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8087166004830152851660248201527fffffffffffffffffffff00000000000000000000000000000000000000000000841660448201527fffff00000000000000000000000000000000000000000000000000000000000083166064820152608401610d09565b5050505050565b600080612e2a84866158e4565b9050600060248260ff161115612e6157612e456024836158fd565b612e5090600a615a36565b612e5a90856155f6565b9050612e84565b612e6c8260246158fd565b612e7790600a615a36565b612e8190856155df565b90505b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811115612eda576040517f10cb51d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b95945050505050565b602081015160005b8151811015612f7e576000828281518110612f0857612f08615631565b60200260200101519050612f268160026140a190919063ffffffff16565b15612f755760405173ffffffffffffffffffffffffffffffffffffffff821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b50600101612eeb565b50815160005b81518110156111a2576000828281518110612fa157612fa1615631565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603613011576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61301c60028261405d565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a150600101612f84565b60005b81518110156111fa57600082828151811061308f5761308f615631565b6020026020010151905060008383815181106130ad576130ad615631565b60200260200101516000015190506000826020015190508167ffffffffffffffff16600014806130e6575061016081015163ffffffff16155b8061313857506101e08101517fffffffff00000000000000000000000000000000000000000000000000000000167f2812d52c0000000000000000000000000000000000000000000000000000000014155b806131575750806060015163ffffffff1681610160015163ffffffff16115b1561319a576040517fc35aa79d00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff83166004820152602401610d09565b67ffffffffffffffff821660009081526009602052604081206001015471010000000000000000000000000000000000900460e01b7fffffffff0000000000000000000000000000000000000000000000000000000016900361323e578167ffffffffffffffff167fd31c671936387b2f84ed402b553bd50c0e9c20408ea4e91a836d77b8180fb724826040516132319190614aa1565b60405180910390a2613281565b8167ffffffffffffffff167f1edd6f3553cfa16f10b95b195abae3a1cfca4783de4843f95d674b1e1df5ab20826040516132789190614aa1565b60405180910390a25b80600960008467ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548161ffff021916908361ffff16021790555060408201518160000160036101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160076101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600b6101000a81548163ffffffff021916908363ffffffff16021790555060a082015181600001600f6101000a81548161ffff021916908361ffff16021790555060c08201518160000160116101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160000160156101000a81548161ffff021916908361ffff1602179055506101008201518160000160176101000a81548161ffff021916908361ffff1602179055506101208201518160000160196101000a81548161ffff021916908361ffff16021790555061014082015181600001601b6101000a81548163ffffffff021916908363ffffffff1602179055506101608201518160010160006101000a81548163ffffffff021916908363ffffffff1602179055506101808201518160010160046101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506101a082015181600101600c6101000a81548163ffffffff021916908363ffffffff1602179055506101c08201518160010160106101000a81548160ff0219169083151502179055506101e08201518160010160116101000a81548163ffffffff021916908360e01c0217905550905050505050806001019050613072565b60005b81518110156111fa57600082828151811061353557613535615631565b6020026020010151600001519050600083838151811061355757613557615631565b60209081029190910181015181015173ffffffffffffffffffffffffffffffffffffffff841660008181526008845260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff85169081179091559051908152919350917fbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d910160405180910390a25050600101613518565b6040805180820190915260008082526020820152600083900361364057506040805180820190915267ffffffffffffffff8216815260006020820152610b69565b600061364c8486615a45565b9050600061365d8560048189615a8b565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505050507fffffffff0000000000000000000000000000000000000000000000000000000082167fe7e230f000000000000000000000000000000000000000000000000000000000016136fa57808060200190518101906136f19190615ab5565b92505050610b69565b7f6859a837000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831601613776576040518060400160405280828060200190518101906137629190615ae1565b815260006020909101529250610b69915050565b6040517f5247fdce00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080518082019091526000808252602082015260008260000151905060008173ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015613812573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138369190615b14565b5050509150506000811215613877576040517f10cb51d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006138f68373ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156138c7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138eb9190615b64565b866020015184612e1d565b604080518082019091527bffffffffffffffffffffffffffffffffffffffffffffffffffffffff909116815263ffffffff4216602082015295945050505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515610b69565b836040015163ffffffff168311156139bf5760408085015190517f8693378900000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015260248101849052604401610d09565b836020015161ffff16821115613a01576040517f4c056b6a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6111a2846101e001518261235c565b6000808083815b81811015613cda576000878783818110613a3357613a33615631565b905060400201803603810190613a499190615b81565b67ffffffffffffffff8c166000908152600a60209081526040808320845173ffffffffffffffffffffffffffffffffffffffff168452825291829020825160c081018452905463ffffffff8082168352640100000000820481169383019390935268010000000000000000810461ffff16938201939093526a01000000000000000000008304821660608201526e01000000000000000000000000000083049091166080820152720100000000000000000000000000000000000090910460ff16151560a0820181905291925090613b69576101208d0151613b369061ffff16662386f26fc100006155df565b613b4090886158be565b96508c610140015186613b539190615bba565b9550613b60602086615bba565b94505050613cd2565b604081015160009061ffff1615613c225760008c73ffffffffffffffffffffffffffffffffffffffff16846000015173ffffffffffffffffffffffffffffffffffffffff1614613bc5578351613bbe906122c2565b9050613bc8565b508a5b620186a0836040015161ffff16613c0a8660200151847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166140c390919063ffffffff16565b613c1491906155df565b613c1e91906155f6565b9150505b6060820151613c319088615bba565b9650816080015186613c439190615bba565b8251909650600090613c629063ffffffff16662386f26fc100006155df565b905080821015613c8157613c76818a6158be565b985050505050613cd2565b6000836020015163ffffffff16662386f26fc10000613ca091906155df565b905080831115613cc057613cb4818b6158be565b99505050505050613cd2565b613cca838b6158be565b995050505050505b600101613a17565b505096509650969350505050565b60008063ffffffff8316613cfe610160866155df565b613d0a876101c06158be565b613d1491906158be565b613d1e91906158be565b905060008760c0015163ffffffff168860e0015161ffff1683613d4191906155df565b613d4b91906158be565b61010089015190915061ffff16613d726dffffffffffffffffffffffffffff8916836155df565b613d7c91906155df565b613d8c90655af3107a40006155df565b98975050505050505050565b60408051808201909152600080825260208201526000613dc4858585610160015163ffffffff166135ff565b9050826060015163ffffffff1681600001511115613e0e576040517f4c4fc93a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b826101c001518015613e2257508060200151155b15610b66576040517fee433e9900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff821603613ed8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610d09565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60008151602014613f8d57816040517f8d666f60000000000000000000000000000000000000000000000000000000008152600401610d099190614512565b600082806020019051810190613fa39190615ae1565b905073ffffffffffffffffffffffffffffffffffffffff811180613fc8575061040081105b156112c357826040517f8d666f60000000000000000000000000000000000000000000000000000000008152600401610d099190614512565b60608160000180548060200260200160405190810160405280929190818152602001828054801561405157602002820191906000526020600020905b81548152602001906001019080831161403d575b50505050509050919050565b6000610b698373ffffffffffffffffffffffffffffffffffffffff8416614100565b6000610b698373ffffffffffffffffffffffffffffffffffffffff841661414f565b6000610b698373ffffffffffffffffffffffffffffffffffffffff8416614249565b6000670de0b6b3a76400006140f6837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff86166155df565b610b6991906155f6565b6000818152600183016020526040812054614147575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556112c3565b5060006112c3565b600081815260018301602052604081205480156142385760006141736001836158d1565b8554909150600090614187906001906158d1565b90508082146141ec5760008660000182815481106141a7576141a7615631565b90600052602060002001549050808760000184815481106141ca576141ca615631565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806141fd576141fd615bd7565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506112c3565b60009150506112c3565b5092915050565b6000818152600183016020526040812054801561423857600061426d6001836158d1565b8554909150600090614281906001906158d1565b90508181146141ec5760008660000182815481106141a7576141a7615631565b803573ffffffffffffffffffffffffffffffffffffffff811681146142c557600080fd5b919050565b6000806000606084860312156142df57600080fd5b6142e8846142a1565b9250602084013591506142fd604085016142a1565b90509250925092565b60006020828403121561431857600080fd5b610b69826142a1565b803567ffffffffffffffff811681146142c557600080fd5b60008083601f84011261434b57600080fd5b50813567ffffffffffffffff81111561436357600080fd5b6020830191508360208260051b85010111156122bb57600080fd5b60008060008060006060868803121561439657600080fd5b61439f86614321565b9450602086013567ffffffffffffffff808211156143bc57600080fd5b6143c889838a01614339565b909650945060408801359150808211156143e157600080fd5b818801915088601f8301126143f557600080fd5b81358181111561440457600080fd5b8960208260061b850101111561441957600080fd5b9699959850939650602001949392505050565b6000815180845260005b8181101561445257602081850181015186830182015201614436565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b82811015614505577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526144f385835161442c565b945092850192908501906001016144b9565b5092979650505050505050565b602081526000610b69602083018461442c565b6020808252825182820181905260009190848201906040850190845b8181101561457357835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101614541565b50909695505050505050565b60006020828403121561459157600080fd5b813567ffffffffffffffff8111156145a857600080fd5b820160408185031215610b6957600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561460c5761460c6145ba565b60405290565b60405160a0810167ffffffffffffffff8111828210171561460c5761460c6145ba565b60405160c0810167ffffffffffffffff8111828210171561460c5761460c6145ba565b604051610200810167ffffffffffffffff8111828210171561460c5761460c6145ba565b6040516060810167ffffffffffffffff8111828210171561460c5761460c6145ba565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156146e6576146e66145ba565b604052919050565b600067ffffffffffffffff821115614708576147086145ba565b5060051b60200190565b60ff811681146111b957600080fd5b6000602080838503121561473457600080fd5b823567ffffffffffffffff81111561474b57600080fd5b8301601f8101851361475c57600080fd5b803561476f61476a826146ee565b61469f565b8181526060918202830184019184820191908884111561478e57600080fd5b938501935b8385101561482e57848903818112156147ac5760008081fd5b6147b46145e9565b6147bd876142a1565b81526040807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0840112156147f15760008081fd5b6147f96145e9565b92506148068989016142a1565b835287013561481481614712565b828901528088019190915283529384019391850191614793565b50979650505050505050565b80151581146111b957600080fd5b80356142c58161483a565b6000602080838503121561486657600080fd5b823567ffffffffffffffff81111561487d57600080fd5b8301601f8101851361488e57600080fd5b803561489c61476a826146ee565b81815260a091820283018401918482019190888411156148bb57600080fd5b938501935b8385101561482e5780858a0312156148d85760008081fd5b6148e0614612565b6148e9866142a1565b8152868601357fffffffffffffffffffff000000000000000000000000000000000000000000008116811461491e5760008081fd5b818801526040868101357fffff000000000000000000000000000000000000000000000000000000000000811681146149575760008081fd5b9082015260606149688782016142a1565b9082015260808681013561497b8161483a565b90820152835293840193918501916148c0565b600080602083850312156149a157600080fd5b823567ffffffffffffffff8111156149b857600080fd5b6149c485828601614339565b90969095509350505050565b602080825282518282018190526000919060409081850190868401855b82811015614a3e57614a2e84835180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16825260209081015163ffffffff16910152565b92840192908501906001016149ed565b5091979650505050505050565b600060208284031215614a5d57600080fd5b610b6982614321565b81517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16815260208083015163ffffffff1690820152604081016112c3565b81511515815261020081016020830151614ac1602084018261ffff169052565b506040830151614ad9604084018263ffffffff169052565b506060830151614af1606084018263ffffffff169052565b506080830151614b09608084018263ffffffff169052565b5060a0830151614b1f60a084018261ffff169052565b5060c0830151614b3760c084018263ffffffff169052565b5060e0830151614b4d60e084018261ffff169052565b506101008381015161ffff9081169184019190915261012080850151909116908301526101408084015163ffffffff90811691840191909152610160808501518216908401526101808085015167ffffffffffffffff16908401526101a080850151909116908301526101c0808401511515908301526101e0808401517fffffffff000000000000000000000000000000000000000000000000000000008116828501525b505092915050565b803563ffffffff811681146142c557600080fd5b803561ffff811681146142c557600080fd5b600082601f830112614c3157600080fd5b81356020614c4161476a836146ee565b82815260069290921b84018101918181019086841115614c6057600080fd5b8286015b84811015614cad5760408189031215614c7d5760008081fd5b614c856145e9565b614c8e82614321565b8152614c9b8583016142a1565b81860152835291830191604001614c64565b509695505050505050565b60008060408385031215614ccb57600080fd5b67ffffffffffffffff83351115614ce157600080fd5b83601f843585010112614cf357600080fd5b614d0361476a84358501356146ee565b8335840180358083526020808401939260059290921b90910101861015614d2957600080fd5b602085358601015b85358601803560051b01602001811015614f365767ffffffffffffffff81351115614d5b57600080fd5b8035863587010160407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0828a03011215614d9457600080fd5b614d9c6145e9565b614da860208301614321565b815267ffffffffffffffff60408301351115614dc357600080fd5b88603f604084013584010112614dd857600080fd5b614dee61476a60206040850135850101356146ee565b6020604084810135850182810135808552928401939260e00201018b1015614e1557600080fd5b6040808501358501015b6040858101358601602081013560e0020101811015614f175760e0818d031215614e4857600080fd5b614e506145e9565b614e59826142a1565b815260c07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0838f03011215614e8d57600080fd5b614e95614635565b614ea160208401614bfa565b8152614eaf60408401614bfa565b6020820152614ec060608401614c0e565b6040820152614ed160808401614bfa565b6060820152614ee260a08401614bfa565b6080820152614ef460c084013561483a565b60c083013560a0820152602082810191909152908452929092019160e001614e1f565b5080602084015250508085525050602083019250602081019050614d31565b5092505067ffffffffffffffff60208401351115614f5357600080fd5b614f638460208501358501614c20565b90509250929050565b600082601f830112614f7d57600080fd5b81356020614f8d61476a836146ee565b8083825260208201915060208460051b870101935086841115614faf57600080fd5b602086015b84811015614cad57614fc5816142a1565b8352918301918301614fb4565b60008060408385031215614fe557600080fd5b823567ffffffffffffffff80821115614ffd57600080fd5b61500986838701614f6c565b9350602085013591508082111561501f57600080fd5b5061502c85828601614f6c565b9150509250929050565b60008083601f84011261504857600080fd5b50813567ffffffffffffffff81111561506057600080fd5b6020830191508360208285010111156122bb57600080fd5b6000806000806040858703121561508e57600080fd5b843567ffffffffffffffff808211156150a657600080fd5b6150b288838901615036565b909650945060208701359150808211156150cb57600080fd5b506150d887828801615036565b95989497509550505050565b600080604083850312156150f757600080fd5b61510083614321565b9150614f63602084016142a1565b60006020828403121561512057600080fd5b813567ffffffffffffffff8082111561513857600080fd5b908301906040828603121561514c57600080fd5b6151546145e9565b82358281111561516357600080fd5b61516f87828601614f6c565b82525060208301358281111561518457600080fd5b61519087828601614f6c565b60208301525095945050505050565b80357fffffffff00000000000000000000000000000000000000000000000000000000811681146142c557600080fd5b600060208083850312156151e257600080fd5b823567ffffffffffffffff8111156151f957600080fd5b8301601f8101851361520a57600080fd5b803561521861476a826146ee565b818152610220918202830184019184820191908884111561523857600080fd5b938501935b8385101561482e57848903818112156152565760008081fd5b61525e6145e9565b61526787614321565b8152610200807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08401121561529c5760008081fd5b6152a4614658565b92506152b1898901614848565b835260406152c0818a01614c0e565b8a85015260606152d1818b01614bfa565b82860152608091506152e4828b01614bfa565b9085015260a06152f58a8201614bfa565b8286015260c09150615308828b01614c0e565b9085015260e06153198a8201614bfa565b82860152610100915061532d828b01614c0e565b9085015261012061533f8a8201614c0e565b828601526101409150615353828b01614c0e565b908501526101606153658a8201614bfa565b828601526101809150615379828b01614bfa565b908501526101a061538b8a8201614321565b828601526101c0915061539f828b01614bfa565b908501526101e06153b18a8201614848565b828601526153c0838b0161519f565b908501525050808801919091528352938401939185019161523d565b600060208083850312156153ef57600080fd5b823567ffffffffffffffff81111561540657600080fd5b8301601f8101851361541757600080fd5b803561542561476a826146ee565b81815260069190911b8201830190838101908783111561544457600080fd5b928401925b8284101561549657604084890312156154625760008081fd5b61546a6145e9565b615473856142a1565b8152615480868601614321565b8187015282526040939093019290840190615449565b979650505050505050565b6000806000806000608086880312156154b957600080fd5b6154c286614321565b94506154d0602087016142a1565b935060408601359250606086013567ffffffffffffffff8111156154f357600080fd5b6154ff88828901615036565b969995985093965092949392505050565b8381528215156020820152606060408201526000612eda606083018461442c565b6000806040838503121561554457600080fd5b61554d83614321565b9150602083013567ffffffffffffffff81111561556957600080fd5b830160a0818603121561557b57600080fd5b809150509250929050565b6000806040838503121561559957600080fd5b6155a2836142a1565b9150614f6360208401614321565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80820281158282048414176112c3576112c36155b0565b60008261562c577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6183360301811261569457600080fd5b9190910192915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126156d357600080fd5b83018035915067ffffffffffffffff8211156156ee57600080fd5b6020019150368190038213156122bb57600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261573857600080fd5b83018035915067ffffffffffffffff82111561575357600080fd5b6020019150600681901b36038213156122bb57600080fd5b80357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811681146142c557600080fd5b6000604082840312156157a957600080fd5b6157b16145e9565b6157ba836142a1565b81526157c86020840161576b565b60208201529392505050565b6000604082840312156157e657600080fd5b6157ee6145e9565b6157ba83614321565b6000602080838503121561580a57600080fd5b823567ffffffffffffffff81111561582157600080fd5b8301601f8101851361583257600080fd5b803561584061476a826146ee565b8181526060918202830184019184820191908884111561585f57600080fd5b938501935b8385101561482e5780858a03121561587c5760008081fd5b61588461467c565b61588d866142a1565b815261589a87870161576b565b8782015260406158ab818801614bfa565b9082015283529384019391850191615864565b808201808211156112c3576112c36155b0565b818103818111156112c3576112c36155b0565b60ff81811683821601908111156112c3576112c36155b0565b60ff82811682821603908111156112c3576112c36155b0565b600181815b8085111561596f57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115615955576159556155b0565b8085161561596257918102915b93841c939080029061591b565b509250929050565b600082615986575060016112c3565b81615993575060006112c3565b81600181146159a957600281146159b3576159cf565b60019150506112c3565b60ff8411156159c4576159c46155b0565b50506001821b6112c3565b5060208310610133831016604e8410600b84101617156159f2575081810a6112c3565b6159fc8383615916565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115615a2e57615a2e6155b0565b029392505050565b6000610b6960ff841683615977565b7fffffffff000000000000000000000000000000000000000000000000000000008135818116916004851015614bf25760049490940360031b84901b1690921692915050565b60008085851115615a9b57600080fd5b83861115615aa857600080fd5b5050820193919092039150565b600060408284031215615ac757600080fd5b615acf6145e9565b8251815260208301516157c88161483a565b600060208284031215615af357600080fd5b5051919050565b805169ffffffffffffffffffff811681146142c557600080fd5b600080600080600060a08688031215615b2c57600080fd5b615b3586615afa565b9450602086015193506040860151925060608601519150615b5860808701615afa565b90509295509295909350565b600060208284031215615b7657600080fd5b8151610b6981614712565b600060408284031215615b9357600080fd5b615b9b6145e9565b615ba4836142a1565b8152602083013560208201528091505092915050565b63ffffffff818116838216019080821115614242576142426155b0565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea164736f6c6343000818000a", } var FeeQuoterABI = FeeQuoterMetaData.ABI diff --git a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt index f8a7a120af..afbdd51c79 100644 --- a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -11,7 +11,7 @@ commit_store_helper: ../../../contracts/solc/v0.8.24/CommitStoreHelper/CommitSto ether_sender_receiver: ../../../contracts/solc/v0.8.24/EtherSenderReceiver/EtherSenderReceiver.abi ../../../contracts/solc/v0.8.24/EtherSenderReceiver/EtherSenderReceiver.bin 09510a3f773f108a3c231e8d202835c845ded862d071ec54c4f89c12d868b8de evm_2_evm_offramp: ../../../contracts/solc/v0.8.24/EVM2EVMOffRamp/EVM2EVMOffRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMOffRamp/EVM2EVMOffRamp.bin b0d77babbe635cd6ba04c2af049badc9e9d28a4b6ed6bb75f830ad902a618beb evm_2_evm_onramp: ../../../contracts/solc/v0.8.24/EVM2EVMOnRamp/EVM2EVMOnRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMOnRamp/EVM2EVMOnRamp.bin 5c02c2b167946b3467636ff2bb58594cb4652fc63d8bdfee2488ed562e2a3e50 -fee_quoter: ../../../contracts/solc/v0.8.24/FeeQuoter/FeeQuoter.abi ../../../contracts/solc/v0.8.24/FeeQuoter/FeeQuoter.bin 95cdd54835272004bbe4a469b8529aa6f92ece2f903d914615010f1bf80a16c8 +fee_quoter: ../../../contracts/solc/v0.8.24/FeeQuoter/FeeQuoter.abi ../../../contracts/solc/v0.8.24/FeeQuoter/FeeQuoter.bin 920b7a293165fe8306fbed0cafd866bafc5943e8759486f7803bfbbd40309b6b lock_release_token_pool: ../../../contracts/solc/v0.8.24/LockReleaseTokenPool/LockReleaseTokenPool.abi ../../../contracts/solc/v0.8.24/LockReleaseTokenPool/LockReleaseTokenPool.bin e6a8ec9e8faccb1da7d90e0f702ed72975964f97dc3222b54cfcca0a0ba3fea2 lock_release_token_pool_and_proxy: ../../../contracts/solc/v0.8.24/LockReleaseTokenPoolAndProxy/LockReleaseTokenPoolAndProxy.abi ../../../contracts/solc/v0.8.24/LockReleaseTokenPoolAndProxy/LockReleaseTokenPoolAndProxy.bin e632b08be0fbd1d013e8b3a9d75293d0d532b83071c531ff2be1deec1fa48ec1 maybe_revert_message_receiver: ../../../contracts/solc/v0.8.24/MaybeRevertMessageReceiver/MaybeRevertMessageReceiver.abi ../../../contracts/solc/v0.8.24/MaybeRevertMessageReceiver/MaybeRevertMessageReceiver.bin d73956c26232ebcc4a5444429fa99cbefed960e323be9b5a24925885c2e477d5 From 87b71197e8c786d582caa9c89b1860c2784d1305 Mon Sep 17 00:00:00 2001 From: Mateusz Sekara Date: Thu, 29 Aug 2024 14:47:33 +0200 Subject: [PATCH 050/115] Exposing image version in baseline.toml test (#1390) ## Motivation ## Solution --- .../tomls/ccip1.4-stress/baseline.toml | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/integration-tests/ccip-tests/testconfig/tomls/ccip1.4-stress/baseline.toml b/integration-tests/ccip-tests/testconfig/tomls/ccip1.4-stress/baseline.toml index 02ca2f4d9f..c404d3a0c0 100644 --- a/integration-tests/ccip-tests/testconfig/tomls/ccip1.4-stress/baseline.toml +++ b/integration-tests/ccip-tests/testconfig/tomls/ccip1.4-stress/baseline.toml @@ -7,8 +7,15 @@ ## ## make test_load_ccip testimage=.dkr.ecr..amazonaws.com/chainlink-ccip-tests:ccip-develop \ ## testname=TestLoadCCIPStableRequestTriggeringWithNetworkChaos \ -## override_toml=./testconfig/tomls/ccip-1.4-stress/baseline.toml \ -## secret_toml=./testconfig/tomls/secrets.toml +## override_toml=./testconfig/tomls/ccip-1.4-stress/baseline.toml + +## Adjust this value depending on what you want to test. +# Using releases and git tag requires changing the image name to the correct one in `~/.testsecrets`, e.g. +# E2E_TEST_CHAINLINK_IMAGE="public.ecr.aws/w0i8p0z9/chainlink-ccip" +# If you want to use a specific commit or a branch you need to switch to the internal ECR in `~/.testsecrets` +# E2E_TEST_CHAINLINK_IMAGE=".dkr.ecr..amazonaws.com/chainlink-ccip" +[CCIP.Env.NewCLCluster.Common.ChainlinkImage] +version = "2.14.0-ccip1.5.0" [CCIP] [CCIP.ContractVersions] @@ -22,7 +29,7 @@ CommitStore = '1.2.0' TTL = '10h' [CCIP.Env.Network] -selected_networks= ['PRIVATE-CHAIN-1', 'PRIVATE-CHAIN-2'] +selected_networks = ['PRIVATE-CHAIN-1', 'PRIVATE-CHAIN-2'] [CCIP.Env.Network.EVMNetworks.PRIVATE-CHAIN-1] evm_name = 'private-chain-1' @@ -152,7 +159,7 @@ BatchGasLimit = 11000000 TimeoutForPriceUpdate = '15m' NoOfTokensPerChain = 10 NoOfTokensWithDynamicPrice = 10 -DynamicPriceUpdateInterval ='15s' +DynamicPriceUpdateInterval = '15s' CCIPOwnerTokens = true [CCIP.Groups.load.LoadProfile] @@ -164,7 +171,7 @@ NetworkChaosDelay = '100ms' # to represent 20%, 60%, 15%, 5% of the total messages [CCIP.Groups.load.LoadProfile.MsgProfile] -Frequencies = [4,12,3,1] +Frequencies = [4, 12, 3, 1] [[CCIP.Groups.load.LoadProfile.MsgProfile.MsgDetails]] MsgType = 'Token' From cfbe3269021053df54b314ad5a8030b6b6af7f51 Mon Sep 17 00:00:00 2001 From: Valerii Kabisov <172247313+valerii-kabisov-cll@users.noreply.github.com> Date: Thu, 29 Aug 2024 23:12:58 +0900 Subject: [PATCH 051/115] [CCIP-2590] Transfer Data Availability costs to the DAGasEstimator (#1161) ## Motivation We use DAGasPriceEstimator to roughly estimate execution cost of a message in the Exec plugin. During this execution cost estimation, we need to account for the data availability component: ``` type DAGasPriceEstimator struct { daOverheadGas int64 gasPerDAByte int64 daMultiplier int64 } ``` however, these fields are not used atm, they remain 0 during cost estimation. The challenge is they live in OnRamp.sol DynamicConfig, ``` struct DynamicConfig { uint32 destDataAvailabilityOverheadGas; // Extra data availability gas charged on top of the message, e.g. for OCR uint16 destGasPerDataAvailabilityByte; // Amount of gas to charge per byte of message data that needs availability uint16 destDataAvailabilityMultiplierBps; // Multiplier for data availability gas, multiples of bps, or 0.0001 } ``` We need to read them via the OnRamp reader and pass that into the DAGasPriceEstimator one way or another. ## Solution New service implemented to transfer onRamp config to offRamp/commit plugins. It provides weak dependency between plugins and provides actual data on demand. --- .mockery.yaml | 3 + .../ocr2/plugins/ccip/ccipcommit/ocr2_test.go | 12 +- .../plugins/ccip/ccipexec/initializers.go | 4 +- .../ocr2/plugins/ccip/ccipexec/ocr2_test.go | 19 ++-- .../plugins/ccip/estimatorconfig/config.go | 49 ++++++++ .../ccip/estimatorconfig/config_test.go | 45 ++++++++ .../ocr2/plugins/ccip/exportinternal.go | 16 +-- .../ccip/internal/cache/commit_roots_test.go | 14 ++- .../ccipdata/commit_store_reader_test.go | 13 ++- .../internal/ccipdata/factory/commit_store.go | 14 +-- .../ccipdata/factory/commit_store_test.go | 8 +- .../ccip/internal/ccipdata/factory/offramp.go | 16 +-- .../internal/ccipdata/factory/offramp_test.go | 7 +- .../internal/ccipdata/fee_estimator_config.go | 9 ++ .../mocks/fee_estimator_config_mock.go | 106 ++++++++++++++++++ .../internal/ccipdata/offramp_reader_test.go | 11 +- .../ccip/internal/ccipdata/v1_0_0/offramp.go | 10 +- .../ccipdata/v1_0_0/offramp_reader_test.go | 5 +- .../v1_0_0/offramp_reader_unit_test.go | 11 +- .../ccip/internal/ccipdata/v1_0_0/onramp.go | 80 ++++++------- .../internal/ccipdata/v1_2_0/commit_store.go | 15 ++- .../ccipdata/v1_2_0/commit_store_test.go | 6 +- .../ccip/internal/ccipdata/v1_2_0/offramp.go | 22 +++- .../ccipdata/v1_2_0/offramp_reader_test.go | 5 +- .../ccip/internal/ccipdata/v1_2_0/onramp.go | 77 ++++++------- .../internal/ccipdata/v1_5_0/commit_store.go | 12 +- .../ccip/internal/ccipdata/v1_5_0/offramp.go | 20 +++- .../ccip/internal/ccipdata/v1_5_0/onramp.go | 79 ++++++------- .../plugins/ccip/prices/da_price_estimator.go | 26 +++-- .../ccip/prices/da_price_estimator_test.go | 104 +++++++++++------ .../ccip/prices/gas_price_estimator.go | 5 +- core/services/relay/evm/ccip.go | 38 ++++--- core/services/relay/evm/commit_provider.go | 46 +++++--- core/services/relay/evm/evm.go | 9 ++ core/services/relay/evm/exec_provider.go | 22 +++- 35 files changed, 652 insertions(+), 286 deletions(-) create mode 100644 core/services/ocr2/plugins/ccip/estimatorconfig/config.go create mode 100644 core/services/ocr2/plugins/ccip/estimatorconfig/config_test.go create mode 100644 core/services/ocr2/plugins/ccip/internal/ccipdata/fee_estimator_config.go create mode 100644 core/services/ocr2/plugins/ccip/internal/ccipdata/mocks/fee_estimator_config_mock.go diff --git a/.mockery.yaml b/.mockery.yaml index 18749da4f3..6902232c30 100644 --- a/.mockery.yaml +++ b/.mockery.yaml @@ -499,6 +499,9 @@ packages: PriceRegistryReader: config: filename: price_registry_reader_mock.go + FeeEstimatorConfigReader: + config: + filename: fee_estimator_config_mock.go TokenPoolReader: config: filename: token_pool_reader_mock.go diff --git a/core/services/ocr2/plugins/ccip/ccipcommit/ocr2_test.go b/core/services/ocr2/plugins/ccip/ccipcommit/ocr2_test.go index f1ca4d91cd..b02b7138a1 100644 --- a/core/services/ocr2/plugins/ccip/ccipcommit/ocr2_test.go +++ b/core/services/ocr2/plugins/ccip/ccipcommit/ocr2_test.go @@ -20,15 +20,13 @@ import ( "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" - "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" - "github.com/smartcontractkit/libocr/offchainreporting2plus/types" "github.com/smartcontractkit/chainlink-common/pkg/config" "github.com/smartcontractkit/chainlink-common/pkg/hashutil" "github.com/smartcontractkit/chainlink-common/pkg/merklemulti" cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" - + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/mocks" mocks2 "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller/mocks" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" @@ -45,7 +43,6 @@ import ( ccipdatamocks "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/mocks" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_0_0" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0" - ccipdbmocks "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdb/mocks" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/prices" ) @@ -410,7 +407,9 @@ func TestCommitReportingPlugin_Report(t *testing.T) { evmEstimator := mocks.NewEvmFeeEstimator(t) evmEstimator.On("L1Oracle").Return(nil) - gasPriceEstimator := prices.NewDAGasPriceEstimator(evmEstimator, nil, 2e9, 2e9) // 200% deviation + + feeEstimatorConfig := ccipdatamocks.NewFeeEstimatorConfigReader(t) + gasPriceEstimator := prices.NewDAGasPriceEstimator(evmEstimator, nil, 2e9, 2e9, feeEstimatorConfig) // 200% deviation var destTokens []cciptypes.Address for tk := range tc.tokenDecimals { @@ -434,7 +433,7 @@ func TestCommitReportingPlugin_Report(t *testing.T) { })).Return(destDecimals, nil).Maybe() lp := mocks2.NewLogPoller(t) - commitStoreReader, err := v1_2_0.NewCommitStore(logger.TestLogger(t), utils.RandomAddress(), nil, lp) + commitStoreReader, err := v1_2_0.NewCommitStore(logger.TestLogger(t), utils.RandomAddress(), nil, lp, feeEstimatorConfig) assert.NoError(t, err) healthCheck := ccipcachemocks.NewChainHealthcheck(t) @@ -1532,6 +1531,7 @@ func TestCommitReportingPlugin_calculatePriceUpdates(t *testing.T) { nil, tc.daGasPriceDeviationPPB, tc.execGasPriceDeviationPPB, + ccipdatamocks.NewFeeEstimatorConfigReader(t), ) r := &CommitReportingPlugin{ diff --git a/core/services/ocr2/plugins/ccip/ccipexec/initializers.go b/core/services/ocr2/plugins/ccip/ccipexec/initializers.go index c8d079b263..aa42ff2828 100644 --- a/core/services/ocr2/plugins/ccip/ccipexec/initializers.go +++ b/core/services/ocr2/plugins/ccip/ccipexec/initializers.go @@ -18,8 +18,6 @@ import ( cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/cache" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipcalc" "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/statuschecker" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" @@ -27,6 +25,8 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/job" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip" ccipconfig "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/config" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/cache" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipcalc" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/factory" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/observability" diff --git a/core/services/ocr2/plugins/ccip/ccipexec/ocr2_test.go b/core/services/ocr2/plugins/ccip/ccipexec/ocr2_test.go index 84cb73c664..627afda975 100644 --- a/core/services/ocr2/plugins/ccip/ccipexec/ocr2_test.go +++ b/core/services/ocr2/plugins/ccip/ccipexec/ocr2_test.go @@ -16,17 +16,18 @@ import ( mapset "github.com/deckarep/golang-set/v2" "github.com/ethereum/go-ethereum/common" "github.com/pkg/errors" - "github.com/smartcontractkit/libocr/commontypes" - "github.com/smartcontractkit/libocr/offchainreporting2/types" - ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" - cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" + "github.com/smartcontractkit/libocr/commontypes" + "github.com/smartcontractkit/libocr/offchainreporting2/types" + ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" + cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" lpMocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller/mocks" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/cache" @@ -41,8 +42,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/prices" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/testhelpers" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/tokendata" - - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" ) func TestExecutionReportingPlugin_Observation(t *testing.T) { @@ -428,8 +427,10 @@ func TestExecutionReportingPlugin_buildReport(t *testing.T) { p.metricsCollector = ccip.NoopMetricsCollector p.commitStoreReader = commitStore + feeEstimatorConfig := ccipdatamocks.NewFeeEstimatorConfigReader(t) + lp := lpMocks.NewLogPoller(t) - offRampReader, err := v1_0_0.NewOffRamp(logger.TestLogger(t), utils.RandomAddress(), nil, lp, nil, nil) + offRampReader, err := v1_0_0.NewOffRamp(logger.TestLogger(t), utils.RandomAddress(), nil, lp, nil, nil, feeEstimatorConfig) assert.NoError(t, err) p.offRampReader = offRampReader @@ -1376,7 +1377,9 @@ func Test_prepareTokenExecData(t *testing.T) { } func encodeExecutionReport(t *testing.T, report cciptypes.ExecReport) []byte { - reader, err := v1_2_0.NewOffRamp(logger.TestLogger(t), utils.RandomAddress(), nil, nil, nil, nil) + feeEstimatorConfig := ccipdatamocks.NewFeeEstimatorConfigReader(t) + + reader, err := v1_2_0.NewOffRamp(logger.TestLogger(t), utils.RandomAddress(), nil, nil, nil, nil, feeEstimatorConfig) require.NoError(t, err) ctx := testutils.Context(t) encodedReport, err := reader.EncodeExecutionReport(ctx, report) diff --git a/core/services/ocr2/plugins/ccip/estimatorconfig/config.go b/core/services/ocr2/plugins/ccip/estimatorconfig/config.go new file mode 100644 index 0000000000..2eda88d441 --- /dev/null +++ b/core/services/ocr2/plugins/ccip/estimatorconfig/config.go @@ -0,0 +1,49 @@ +package estimatorconfig + +import ( + "context" + "errors" + + "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" +) + +// FeeEstimatorConfigProvider implements abstract storage for the DataAvailability settings in onRamp dynamic Config. +// It's implemented to transfer DA config from different entities offRamp, onRamp, commitStore without injecting the +// strong dependency between modules. ConfigProvider fetch ccip.OnRampReader object reads and returns only relevant +// fields for the daGasEstimator from the encapsulated onRampReader. +type FeeEstimatorConfigProvider interface { + SetOnRampReader(reader ccip.OnRampReader) + GetDataAvailabilityConfig(ctx context.Context) (destDataAvailabilityOverheadGas, destGasPerDataAvailabilityByte, destDataAvailabilityMultiplierBps int64, err error) +} + +type FeeEstimatorConfigService struct { + onRampReader ccip.OnRampReader +} + +func NewFeeEstimatorConfigService() *FeeEstimatorConfigService { + return &FeeEstimatorConfigService{} +} + +// SetOnRampReader Sets the onRamp reader instance. +// must be called once for each instance. +func (c *FeeEstimatorConfigService) SetOnRampReader(reader ccip.OnRampReader) { + c.onRampReader = reader +} + +// GetDataAvailabilityConfig Returns dynamic config data availability parameters. +// GetDynamicConfig should be cached in the onRamp reader to avoid unnecessary on-chain calls +func (c *FeeEstimatorConfigService) GetDataAvailabilityConfig(ctx context.Context) (destDataAvailabilityOverheadGas, destGasPerDataAvailabilityByte, destDataAvailabilityMultiplierBps int64, err error) { + if c.onRampReader == nil { + return 0, 0, 0, errors.New("no OnRampReader has been configured") + } + + cfg, err := c.onRampReader.GetDynamicConfig(ctx) + if err != nil { + return 0, 0, 0, err + } + + return int64(cfg.DestDataAvailabilityOverheadGas), + int64(cfg.DestGasPerDataAvailabilityByte), + int64(cfg.DestDataAvailabilityMultiplierBps), + err +} diff --git a/core/services/ocr2/plugins/ccip/estimatorconfig/config_test.go b/core/services/ocr2/plugins/ccip/estimatorconfig/config_test.go new file mode 100644 index 0000000000..05226f8b48 --- /dev/null +++ b/core/services/ocr2/plugins/ccip/estimatorconfig/config_test.go @@ -0,0 +1,45 @@ +package estimatorconfig_test + +import ( + "context" + "errors" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/estimatorconfig" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/mocks" +) + +func TestFeeEstimatorConfigService(t *testing.T) { + svc := estimatorconfig.NewFeeEstimatorConfigService() + ctx := context.Background() + + var expectedDestDataAvailabilityOverheadGas int64 = 1 + var expectedDestGasPerDataAvailabilityByte int64 = 2 + var expectedDestDataAvailabilityMultiplierBps int64 = 3 + + onRampReader := mocks.NewOnRampReader(t) + _, _, _, err := svc.GetDataAvailabilityConfig(ctx) + require.Error(t, err) + svc.SetOnRampReader(onRampReader) + + onRampReader.On("GetDynamicConfig", ctx). + Return(ccip.OnRampDynamicConfig{ + DestDataAvailabilityOverheadGas: uint32(expectedDestDataAvailabilityOverheadGas), + DestGasPerDataAvailabilityByte: uint16(expectedDestGasPerDataAvailabilityByte), + DestDataAvailabilityMultiplierBps: uint16(expectedDestDataAvailabilityMultiplierBps), + }, nil).Once() + + destDataAvailabilityOverheadGas, destGasPerDataAvailabilityByte, destDataAvailabilityMultiplierBps, err := svc.GetDataAvailabilityConfig(ctx) + require.NoError(t, err) + require.Equal(t, expectedDestDataAvailabilityOverheadGas, destDataAvailabilityOverheadGas) + require.Equal(t, expectedDestGasPerDataAvailabilityByte, destGasPerDataAvailabilityByte) + require.Equal(t, expectedDestDataAvailabilityMultiplierBps, destDataAvailabilityMultiplierBps) + + onRampReader.On("GetDynamicConfig", ctx). + Return(ccip.OnRampDynamicConfig{}, errors.New("test")).Once() + _, _, _, err = svc.GetDataAvailabilityConfig(ctx) + require.Error(t, err) +} diff --git a/core/services/ocr2/plugins/ccip/exportinternal.go b/core/services/ocr2/plugins/ccip/exportinternal.go index 2a5767ac85..2f924085fb 100644 --- a/core/services/ocr2/plugins/ccip/exportinternal.go +++ b/core/services/ocr2/plugins/ccip/exportinternal.go @@ -37,20 +37,20 @@ func NewEvmPriceRegistry(lp logpoller.LogPoller, ec client.Client, lggr logger.L type VersionFinder = factory.VersionFinder -func NewCommitStoreReader(lggr logger.Logger, versionFinder VersionFinder, address ccip.Address, ec client.Client, lp logpoller.LogPoller) (ccipdata.CommitStoreReader, error) { - return factory.NewCommitStoreReader(lggr, versionFinder, address, ec, lp) +func NewCommitStoreReader(lggr logger.Logger, versionFinder VersionFinder, address ccip.Address, ec client.Client, lp logpoller.LogPoller, feeEstimatorConfig ccipdata.FeeEstimatorConfigReader) (ccipdata.CommitStoreReader, error) { + return factory.NewCommitStoreReader(lggr, versionFinder, address, ec, lp, feeEstimatorConfig) } -func CloseCommitStoreReader(lggr logger.Logger, versionFinder VersionFinder, address ccip.Address, ec client.Client, lp logpoller.LogPoller) error { - return factory.CloseCommitStoreReader(lggr, versionFinder, address, ec, lp) +func CloseCommitStoreReader(lggr logger.Logger, versionFinder VersionFinder, address ccip.Address, ec client.Client, lp logpoller.LogPoller, feeEstimatorConfig ccipdata.FeeEstimatorConfigReader) error { + return factory.CloseCommitStoreReader(lggr, versionFinder, address, ec, lp, feeEstimatorConfig) } -func NewOffRampReader(lggr logger.Logger, versionFinder VersionFinder, addr ccip.Address, destClient client.Client, lp logpoller.LogPoller, estimator gas.EvmFeeEstimator, destMaxGasPrice *big.Int, registerFilters bool) (ccipdata.OffRampReader, error) { - return factory.NewOffRampReader(lggr, versionFinder, addr, destClient, lp, estimator, destMaxGasPrice, registerFilters) +func NewOffRampReader(lggr logger.Logger, versionFinder VersionFinder, addr ccip.Address, destClient client.Client, lp logpoller.LogPoller, estimator gas.EvmFeeEstimator, destMaxGasPrice *big.Int, registerFilters bool, feeEstimatorConfig ccipdata.FeeEstimatorConfigReader) (ccipdata.OffRampReader, error) { + return factory.NewOffRampReader(lggr, versionFinder, addr, destClient, lp, estimator, destMaxGasPrice, registerFilters, feeEstimatorConfig) } -func CloseOffRampReader(lggr logger.Logger, versionFinder VersionFinder, addr ccip.Address, destClient client.Client, lp logpoller.LogPoller, estimator gas.EvmFeeEstimator, destMaxGasPrice *big.Int) error { - return factory.CloseOffRampReader(lggr, versionFinder, addr, destClient, lp, estimator, destMaxGasPrice) +func CloseOffRampReader(lggr logger.Logger, versionFinder VersionFinder, addr ccip.Address, destClient client.Client, lp logpoller.LogPoller, estimator gas.EvmFeeEstimator, destMaxGasPrice *big.Int, feeEstimatorConfig ccipdata.FeeEstimatorConfigReader) error { + return factory.CloseOffRampReader(lggr, versionFinder, addr, destClient, lp, estimator, destMaxGasPrice, feeEstimatorConfig) } func NewEvmVersionFinder() factory.EvmVersionFinder { diff --git a/core/services/ocr2/plugins/ccip/internal/cache/commit_roots_test.go b/core/services/ocr2/plugins/ccip/internal/cache/commit_roots_test.go index dc0a844349..d8289212e8 100644 --- a/core/services/ocr2/plugins/ccip/internal/cache/commit_roots_test.go +++ b/core/services/ocr2/plugins/ccip/internal/cache/commit_roots_test.go @@ -9,7 +9,6 @@ import ( "github.com/stretchr/testify/require" cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" @@ -18,6 +17,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/cache" + ccipdatamocks "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/mocks" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0" ) @@ -54,7 +54,9 @@ func Test_RootsEligibleForExecution(t *testing.T) { } require.NoError(t, orm.InsertLogsWithBlock(ctx, inputLogs, logpoller.NewLogPollerBlock(utils.RandomBytes32(), 2, time.Now(), 1))) - commitStore, err := v1_2_0.NewCommitStore(logger.TestLogger(t), commitStoreAddr, nil, lp) + feeEstimatorConfig := ccipdatamocks.NewFeeEstimatorConfigReader(t) + + commitStore, err := v1_2_0.NewCommitStore(logger.TestLogger(t), commitStoreAddr, nil, lp, feeEstimatorConfig) require.NoError(t, err) rootsCache := cache.NewCommitRootsCache(logger.TestLogger(t), commitStore, 10*time.Hour, time.Second) @@ -162,7 +164,9 @@ func Test_RootsEligibleForExecutionWithReorgs(t *testing.T) { } require.NoError(t, orm.InsertLogsWithBlock(ctx, inputLogs, logpoller.NewLogPollerBlock(utils.RandomBytes32(), 3, time.Now(), 1))) - commitStore, err := v1_2_0.NewCommitStore(logger.TestLogger(t), commitStoreAddr, nil, lp) + feeEstimatorConfig := ccipdatamocks.NewFeeEstimatorConfigReader(t) + + commitStore, err := v1_2_0.NewCommitStore(logger.TestLogger(t), commitStoreAddr, nil, lp, feeEstimatorConfig) require.NoError(t, err) rootsCache := cache.NewCommitRootsCache(logger.TestLogger(t), commitStore, 10*time.Hour, time.Second) @@ -221,7 +225,9 @@ func Test_BlocksWithTheSameTimestamps(t *testing.T) { } require.NoError(t, orm.InsertLogsWithBlock(ctx, inputLogs, logpoller.NewLogPollerBlock(utils.RandomBytes32(), 2, time.Now(), 2))) - commitStore, err := v1_2_0.NewCommitStore(logger.TestLogger(t), commitStoreAddr, nil, lp) + feeEstimatorConfig := ccipdatamocks.NewFeeEstimatorConfigReader(t) + + commitStore, err := v1_2_0.NewCommitStore(logger.TestLogger(t), commitStoreAddr, nil, lp, feeEstimatorConfig) require.NoError(t, err) rootsCache := cache.NewCommitRootsCache(logger.TestLogger(t), commitStore, 10*time.Hour, time.Second) diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/commit_store_reader_test.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/commit_store_reader_test.go index 7f6b1c1bb7..6b075be50c 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/commit_store_reader_test.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/commit_store_reader_test.go @@ -13,7 +13,6 @@ import ( "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink-common/pkg/config" - cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" @@ -38,6 +37,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipcalc" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/factory" + ccipdatamocks "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/mocks" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_0_0" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0" ) @@ -193,15 +193,17 @@ func TestCommitStoreReaders(t *testing.T) { lm := new(rollupMocks.L1Oracle) ge.On("L1Oracle").Return(lm) + feeEstimatorConfig := ccipdatamocks.NewFeeEstimatorConfigReader(t) + maxGasPrice := big.NewInt(1e8) - c10r, err := factory.NewCommitStoreReader(lggr, factory.NewEvmVersionFinder(), ccipcalc.EvmAddrToGeneric(addr), ec, lp) // ge, maxGasPrice + c10r, err := factory.NewCommitStoreReader(lggr, factory.NewEvmVersionFinder(), ccipcalc.EvmAddrToGeneric(addr), ec, lp, feeEstimatorConfig) // ge, maxGasPrice require.NoError(t, err) err = c10r.SetGasEstimator(ctx, ge) require.NoError(t, err) err = c10r.SetSourceMaxGasPrice(ctx, maxGasPrice) require.NoError(t, err) assert.Equal(t, reflect.TypeOf(c10r).String(), reflect.TypeOf(&v1_0_0.CommitStore{}).String()) - c12r, err := factory.NewCommitStoreReader(lggr, factory.NewEvmVersionFinder(), ccipcalc.EvmAddrToGeneric(addr2), ec, lp) + c12r, err := factory.NewCommitStoreReader(lggr, factory.NewEvmVersionFinder(), ccipcalc.EvmAddrToGeneric(addr2), ec, lp, feeEstimatorConfig) require.NoError(t, err) err = c12r.SetGasEstimator(ctx, ge) require.NoError(t, err) @@ -412,7 +414,10 @@ func TestNewCommitStoreReader(t *testing.T) { if tc.expectedErr == "" { lp.On("RegisterFilter", mock.Anything, mock.Anything).Return(nil) } - _, err = factory.NewCommitStoreReader(logger.TestLogger(t), factory.NewEvmVersionFinder(), addr, c, lp) + + feeEstimatorConfig := ccipdatamocks.NewFeeEstimatorConfigReader(t) + + _, err = factory.NewCommitStoreReader(logger.TestLogger(t), factory.NewEvmVersionFinder(), addr, c, lp, feeEstimatorConfig) if tc.expectedErr != "" { require.EqualError(t, err, tc.expectedErr) } else { diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/factory/commit_store.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/factory/commit_store.go index d431d2863a..c5f32ba91c 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/factory/commit_store.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/factory/commit_store.go @@ -21,16 +21,16 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_5_0" ) -func NewCommitStoreReader(lggr logger.Logger, versionFinder VersionFinder, address cciptypes.Address, ec client.Client, lp logpoller.LogPoller) (ccipdata.CommitStoreReader, error) { - return initOrCloseCommitStoreReader(lggr, versionFinder, address, ec, lp, false) +func NewCommitStoreReader(lggr logger.Logger, versionFinder VersionFinder, address cciptypes.Address, ec client.Client, lp logpoller.LogPoller, feeEstimatorConfig ccipdata.FeeEstimatorConfigReader) (ccipdata.CommitStoreReader, error) { + return initOrCloseCommitStoreReader(lggr, versionFinder, address, ec, lp, feeEstimatorConfig, false) } -func CloseCommitStoreReader(lggr logger.Logger, versionFinder VersionFinder, address cciptypes.Address, ec client.Client, lp logpoller.LogPoller) error { - _, err := initOrCloseCommitStoreReader(lggr, versionFinder, address, ec, lp, true) +func CloseCommitStoreReader(lggr logger.Logger, versionFinder VersionFinder, address cciptypes.Address, ec client.Client, lp logpoller.LogPoller, feeEstimatorConfig ccipdata.FeeEstimatorConfigReader) error { + _, err := initOrCloseCommitStoreReader(lggr, versionFinder, address, ec, lp, feeEstimatorConfig, true) return err } -func initOrCloseCommitStoreReader(lggr logger.Logger, versionFinder VersionFinder, address cciptypes.Address, ec client.Client, lp logpoller.LogPoller, closeReader bool) (ccipdata.CommitStoreReader, error) { +func initOrCloseCommitStoreReader(lggr logger.Logger, versionFinder VersionFinder, address cciptypes.Address, ec client.Client, lp logpoller.LogPoller, feeEstimatorConfig ccipdata.FeeEstimatorConfigReader, closeReader bool) (ccipdata.CommitStoreReader, error) { contractType, version, err := versionFinder.TypeAndVersion(address, ec) if err != nil { return nil, errors.Wrapf(err, "unable to read type and version") @@ -57,7 +57,7 @@ func initOrCloseCommitStoreReader(lggr logger.Logger, versionFinder VersionFinde } return cs, cs.RegisterFilters() case ccipdata.V1_2_0: - cs, err := v1_2_0.NewCommitStore(lggr, evmAddr, ec, lp) + cs, err := v1_2_0.NewCommitStore(lggr, evmAddr, ec, lp, feeEstimatorConfig) if err != nil { return nil, err } @@ -66,7 +66,7 @@ func initOrCloseCommitStoreReader(lggr logger.Logger, versionFinder VersionFinde } return cs, cs.RegisterFilters() case ccipdata.V1_5_0: - cs, err := v1_5_0.NewCommitStore(lggr, evmAddr, ec, lp) + cs, err := v1_5_0.NewCommitStore(lggr, evmAddr, ec, lp, feeEstimatorConfig) if err != nil { return nil, err } diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/factory/commit_store_test.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/factory/commit_store_test.go index e1b8ff929c..987b6f848e 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/factory/commit_store_test.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/factory/commit_store_test.go @@ -8,13 +8,13 @@ import ( "github.com/stretchr/testify/mock" cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" mocks2 "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller/mocks" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/logger" ccipconfig "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/config" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata" + ccipdatamocks "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/mocks" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_0_0" ) @@ -24,14 +24,16 @@ func TestCommitStore(t *testing.T) { addr := cciptypes.Address(utils.RandomAddress().String()) lp := mocks2.NewLogPoller(t) + feeEstimatorConfig := ccipdatamocks.NewFeeEstimatorConfigReader(t) + lp.On("RegisterFilter", mock.Anything, mock.Anything).Return(nil) versionFinder := newMockVersionFinder(ccipconfig.CommitStore, *semver.MustParse(versionStr), nil) - _, err := NewCommitStoreReader(lggr, versionFinder, addr, nil, lp) + _, err := NewCommitStoreReader(lggr, versionFinder, addr, nil, lp, feeEstimatorConfig) assert.NoError(t, err) expFilterName := logpoller.FilterName(v1_0_0.EXEC_REPORT_ACCEPTS, addr) lp.On("UnregisterFilter", mock.Anything, expFilterName).Return(nil) - err = CloseCommitStoreReader(lggr, versionFinder, addr, nil, lp) + err = CloseCommitStoreReader(lggr, versionFinder, addr, nil, lp, feeEstimatorConfig) assert.NoError(t, err) } } diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/factory/offramp.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/factory/offramp.go index c6fa63ee82..5d9b751d0b 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/factory/offramp.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/factory/offramp.go @@ -26,16 +26,16 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_5_0" ) -func NewOffRampReader(lggr logger.Logger, versionFinder VersionFinder, addr cciptypes.Address, destClient client.Client, lp logpoller.LogPoller, estimator gas.EvmFeeEstimator, destMaxGasPrice *big.Int, registerFilters bool) (ccipdata.OffRampReader, error) { - return initOrCloseOffRampReader(lggr, versionFinder, addr, destClient, lp, estimator, destMaxGasPrice, false, registerFilters) +func NewOffRampReader(lggr logger.Logger, versionFinder VersionFinder, addr cciptypes.Address, destClient client.Client, lp logpoller.LogPoller, estimator gas.EvmFeeEstimator, destMaxGasPrice *big.Int, registerFilters bool, feeEstimatorConfig ccipdata.FeeEstimatorConfigReader) (ccipdata.OffRampReader, error) { + return initOrCloseOffRampReader(lggr, versionFinder, addr, destClient, lp, estimator, destMaxGasPrice, false, registerFilters, feeEstimatorConfig) } -func CloseOffRampReader(lggr logger.Logger, versionFinder VersionFinder, addr cciptypes.Address, destClient client.Client, lp logpoller.LogPoller, estimator gas.EvmFeeEstimator, destMaxGasPrice *big.Int) error { - _, err := initOrCloseOffRampReader(lggr, versionFinder, addr, destClient, lp, estimator, destMaxGasPrice, true, false) +func CloseOffRampReader(lggr logger.Logger, versionFinder VersionFinder, addr cciptypes.Address, destClient client.Client, lp logpoller.LogPoller, estimator gas.EvmFeeEstimator, destMaxGasPrice *big.Int, feeEstimatorConfig ccipdata.FeeEstimatorConfigReader) error { + _, err := initOrCloseOffRampReader(lggr, versionFinder, addr, destClient, lp, estimator, destMaxGasPrice, true, false, feeEstimatorConfig) return err } -func initOrCloseOffRampReader(lggr logger.Logger, versionFinder VersionFinder, addr cciptypes.Address, destClient client.Client, lp logpoller.LogPoller, estimator gas.EvmFeeEstimator, destMaxGasPrice *big.Int, closeReader bool, registerFilters bool) (ccipdata.OffRampReader, error) { +func initOrCloseOffRampReader(lggr logger.Logger, versionFinder VersionFinder, addr cciptypes.Address, destClient client.Client, lp logpoller.LogPoller, estimator gas.EvmFeeEstimator, destMaxGasPrice *big.Int, closeReader bool, registerFilters bool, feeEstimatorConfig ccipdata.FeeEstimatorConfigReader) (ccipdata.OffRampReader, error) { contractType, version, err := versionFinder.TypeAndVersion(addr, destClient) if err != nil { return nil, errors.Wrapf(err, "unable to read type and version") @@ -53,7 +53,7 @@ func initOrCloseOffRampReader(lggr logger.Logger, versionFinder VersionFinder, a switch version.String() { case ccipdata.V1_0_0, ccipdata.V1_1_0: - offRamp, err := v1_0_0.NewOffRamp(lggr, evmAddr, destClient, lp, estimator, destMaxGasPrice) + offRamp, err := v1_0_0.NewOffRamp(lggr, evmAddr, destClient, lp, estimator, destMaxGasPrice, feeEstimatorConfig) if err != nil { return nil, err } @@ -62,7 +62,7 @@ func initOrCloseOffRampReader(lggr logger.Logger, versionFinder VersionFinder, a } return offRamp, offRamp.RegisterFilters() case ccipdata.V1_2_0: - offRamp, err := v1_2_0.NewOffRamp(lggr, evmAddr, destClient, lp, estimator, destMaxGasPrice) + offRamp, err := v1_2_0.NewOffRamp(lggr, evmAddr, destClient, lp, estimator, destMaxGasPrice, feeEstimatorConfig) if err != nil { return nil, err } @@ -71,7 +71,7 @@ func initOrCloseOffRampReader(lggr logger.Logger, versionFinder VersionFinder, a } return offRamp, offRamp.RegisterFilters() case ccipdata.V1_5_0: - offRamp, err := v1_5_0.NewOffRamp(lggr, evmAddr, destClient, lp, estimator, destMaxGasPrice) + offRamp, err := v1_5_0.NewOffRamp(lggr, evmAddr, destClient, lp, estimator, destMaxGasPrice, feeEstimatorConfig) if err != nil { return nil, err } diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/factory/offramp_test.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/factory/offramp_test.go index 4b9e57ecfb..c00d9e134b 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/factory/offramp_test.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/factory/offramp_test.go @@ -15,6 +15,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/logger" ccipconfig "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/config" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata" + ccipdatamocks "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/mocks" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_0_0" ) @@ -24,6 +25,8 @@ func TestOffRamp(t *testing.T) { addr := cciptypes.Address(utils.RandomAddress().String()) lp := mocks2.NewLogPoller(t) + feeEstimatorConfig := ccipdatamocks.NewFeeEstimatorConfigReader(t) + expFilterNames := []string{ logpoller.FilterName(v1_0_0.EXEC_EXECUTION_STATE_CHANGES, addr), logpoller.FilterName(v1_0_0.EXEC_TOKEN_POOL_ADDED, addr), @@ -32,13 +35,13 @@ func TestOffRamp(t *testing.T) { versionFinder := newMockVersionFinder(ccipconfig.EVM2EVMOffRamp, *semver.MustParse(versionStr), nil) lp.On("RegisterFilter", mock.Anything, mock.Anything).Return(nil).Times(len(expFilterNames)) - _, err := NewOffRampReader(lggr, versionFinder, addr, nil, lp, nil, nil, true) + _, err := NewOffRampReader(lggr, versionFinder, addr, nil, lp, nil, nil, true, feeEstimatorConfig) assert.NoError(t, err) for _, f := range expFilterNames { lp.On("UnregisterFilter", mock.Anything, f).Return(nil) } - err = CloseOffRampReader(lggr, versionFinder, addr, nil, lp, nil, nil) + err = CloseOffRampReader(lggr, versionFinder, addr, nil, lp, nil, nil, feeEstimatorConfig) assert.NoError(t, err) } } diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/fee_estimator_config.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/fee_estimator_config.go new file mode 100644 index 0000000000..a1a9370528 --- /dev/null +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/fee_estimator_config.go @@ -0,0 +1,9 @@ +package ccipdata + +import ( + "context" +) + +type FeeEstimatorConfigReader interface { + GetDataAvailabilityConfig(ctx context.Context) (destDAOverheadGas, destGasPerDAByte, destDAMultiplierBps int64, err error) +} diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/mocks/fee_estimator_config_mock.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/mocks/fee_estimator_config_mock.go new file mode 100644 index 0000000000..b19f4cd882 --- /dev/null +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/mocks/fee_estimator_config_mock.go @@ -0,0 +1,106 @@ +// Code generated by mockery v2.43.2. DO NOT EDIT. + +package mocks + +import ( + context "context" + + mock "github.com/stretchr/testify/mock" +) + +// FeeEstimatorConfigReader is an autogenerated mock type for the FeeEstimatorConfigReader type +type FeeEstimatorConfigReader struct { + mock.Mock +} + +type FeeEstimatorConfigReader_Expecter struct { + mock *mock.Mock +} + +func (_m *FeeEstimatorConfigReader) EXPECT() *FeeEstimatorConfigReader_Expecter { + return &FeeEstimatorConfigReader_Expecter{mock: &_m.Mock} +} + +// GetDataAvailabilityConfig provides a mock function with given fields: ctx +func (_m *FeeEstimatorConfigReader) GetDataAvailabilityConfig(ctx context.Context) (int64, int64, int64, error) { + ret := _m.Called(ctx) + + if len(ret) == 0 { + panic("no return value specified for GetDataAvailabilityConfig") + } + + var r0 int64 + var r1 int64 + var r2 int64 + var r3 error + if rf, ok := ret.Get(0).(func(context.Context) (int64, int64, int64, error)); ok { + return rf(ctx) + } + if rf, ok := ret.Get(0).(func(context.Context) int64); ok { + r0 = rf(ctx) + } else { + r0 = ret.Get(0).(int64) + } + + if rf, ok := ret.Get(1).(func(context.Context) int64); ok { + r1 = rf(ctx) + } else { + r1 = ret.Get(1).(int64) + } + + if rf, ok := ret.Get(2).(func(context.Context) int64); ok { + r2 = rf(ctx) + } else { + r2 = ret.Get(2).(int64) + } + + if rf, ok := ret.Get(3).(func(context.Context) error); ok { + r3 = rf(ctx) + } else { + r3 = ret.Error(3) + } + + return r0, r1, r2, r3 +} + +// FeeEstimatorConfigReader_GetDataAvailabilityConfig_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetDataAvailabilityConfig' +type FeeEstimatorConfigReader_GetDataAvailabilityConfig_Call struct { + *mock.Call +} + +// GetDataAvailabilityConfig is a helper method to define mock.On call +// - ctx context.Context +func (_e *FeeEstimatorConfigReader_Expecter) GetDataAvailabilityConfig(ctx interface{}) *FeeEstimatorConfigReader_GetDataAvailabilityConfig_Call { + return &FeeEstimatorConfigReader_GetDataAvailabilityConfig_Call{Call: _e.mock.On("GetDataAvailabilityConfig", ctx)} +} + +func (_c *FeeEstimatorConfigReader_GetDataAvailabilityConfig_Call) Run(run func(ctx context.Context)) *FeeEstimatorConfigReader_GetDataAvailabilityConfig_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context)) + }) + return _c +} + +func (_c *FeeEstimatorConfigReader_GetDataAvailabilityConfig_Call) Return(destDAOverheadGas int64, destGasPerDAByte int64, destDAMultiplierBps int64, err error) *FeeEstimatorConfigReader_GetDataAvailabilityConfig_Call { + _c.Call.Return(destDAOverheadGas, destGasPerDAByte, destDAMultiplierBps, err) + return _c +} + +func (_c *FeeEstimatorConfigReader_GetDataAvailabilityConfig_Call) RunAndReturn(run func(context.Context) (int64, int64, int64, error)) *FeeEstimatorConfigReader_GetDataAvailabilityConfig_Call { + _c.Call.Return(run) + return _c +} + +// NewFeeEstimatorConfigReader creates a new instance of FeeEstimatorConfigReader. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewFeeEstimatorConfigReader(t interface { + mock.TestingT + Cleanup(func()) +}) *FeeEstimatorConfigReader { + mock := &FeeEstimatorConfigReader{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/offramp_reader_test.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/offramp_reader_test.go index f5711422bd..df405a5a61 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/offramp_reader_test.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/offramp_reader_test.go @@ -13,7 +13,6 @@ import ( "github.com/stretchr/testify/require" cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" evmclientmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker" @@ -32,6 +31,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipcalc" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/factory" + ccipdatamocks "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/mocks" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_0_0" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0" ) @@ -194,8 +194,10 @@ func setupOffRampReaderTH(t *testing.T, version string) offRampReaderTH { require.Fail(t, "Unknown version: ", version) } + feeEstimatorConfig := ccipdatamocks.NewFeeEstimatorConfigReader(t) + // Create the version-specific reader. - reader, err := factory.NewOffRampReader(log, factory.NewEvmVersionFinder(), ccipcalc.EvmAddrToGeneric(offRampAddress), bc, lp, nil, nil, true) + reader, err := factory.NewOffRampReader(log, factory.NewEvmVersionFinder(), ccipcalc.EvmAddrToGeneric(offRampAddress), bc, lp, nil, nil, true, feeEstimatorConfig) require.NoError(t, err) addr, err := reader.Address(ctx) require.NoError(t, err) @@ -401,11 +403,14 @@ func TestNewOffRampReader(t *testing.T) { b, err := utils.ABIEncode(`[{"type":"string"}]`, tc.typeAndVersion) require.NoError(t, err) c := evmclientmocks.NewClient(t) + + feeEstimatorConfig := ccipdatamocks.NewFeeEstimatorConfigReader(t) + c.On("CallContract", mock.Anything, mock.Anything, mock.Anything).Return(b, nil) addr := ccipcalc.EvmAddrToGeneric(utils.RandomAddress()) lp := lpmocks.NewLogPoller(t) lp.On("RegisterFilter", mock.Anything, mock.Anything).Return(nil).Maybe() - _, err = factory.NewOffRampReader(logger.TestLogger(t), factory.NewEvmVersionFinder(), addr, c, lp, nil, nil, true) + _, err = factory.NewOffRampReader(logger.TestLogger(t), factory.NewEvmVersionFinder(), addr, c, lp, nil, nil, true, feeEstimatorConfig) if tc.expectedErr != "" { assert.EqualError(t, err, tc.expectedErr) } else { diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_0_0/offramp.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_0_0/offramp.go index 137cbaf451..b5625c59d0 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_0_0/offramp.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_0_0/offramp.go @@ -156,6 +156,7 @@ type OffRamp struct { eventSig common.Hash cachedOffRampTokens cache.AutoSync[cciptypes.OffRampTokens] sourceToDestTokensCache sync.Map + feeEstimatorConfig ccipdata.FeeEstimatorConfigReader // Dynamic config // configMu guards all the dynamic config fields. @@ -627,7 +628,7 @@ func (o *OffRamp) RegisterFilters() error { return logpollerutil.RegisterLpFilters(o.lp, o.filters) } -func NewOffRamp(lggr logger.Logger, addr common.Address, ec client.Client, lp logpoller.LogPoller, estimator gas.EvmFeeEstimator, destMaxGasPrice *big.Int) (*OffRamp, error) { +func NewOffRamp(lggr logger.Logger, addr common.Address, ec client.Client, lp logpoller.LogPoller, estimator gas.EvmFeeEstimator, destMaxGasPrice *big.Int, feeEstimatorConfig ccipdata.FeeEstimatorConfigReader) (*OffRamp, error) { offRamp, err := evm_2_evm_offramp_1_0_0.NewEVM2EVMOffRamp(addr, ec) if err != nil { return nil, err @@ -682,8 +683,9 @@ func NewOffRamp(lggr logger.Logger, addr common.Address, ec client.Client, lp lo offRamp.Address(), ), // values set on the fly after ChangeConfig is called - gasPriceEstimator: prices.ExecGasPriceEstimator{}, - offchainConfig: cciptypes.ExecOffchainConfig{}, - onchainConfig: cciptypes.ExecOnchainConfig{}, + gasPriceEstimator: prices.ExecGasPriceEstimator{}, + offchainConfig: cciptypes.ExecOffchainConfig{}, + onchainConfig: cciptypes.ExecOnchainConfig{}, + feeEstimatorConfig: feeEstimatorConfig, }, nil } diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_0_0/offramp_reader_test.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_0_0/offramp_reader_test.go index d834b792ce..455c1dbcb8 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_0_0/offramp_reader_test.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_0_0/offramp_reader_test.go @@ -11,6 +11,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/mocks" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_0_0" ) @@ -25,7 +26,9 @@ func TestExecutionReportEncodingV100(t *testing.T) { ProofFlagBits: big.NewInt(133), } - offRamp, err := v1_0_0.NewOffRamp(logger.TestLogger(t), utils.RandomAddress(), nil, lpmocks.NewLogPoller(t), nil, nil) + feeEstimatorConfig := mocks.NewFeeEstimatorConfigReader(t) + + offRamp, err := v1_0_0.NewOffRamp(logger.TestLogger(t), utils.RandomAddress(), nil, lpmocks.NewLogPoller(t), nil, nil, feeEstimatorConfig) require.NoError(t, err) ctx := testutils.Context(t) diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_0_0/offramp_reader_unit_test.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_0_0/offramp_reader_unit_test.go index f8b1dc4e61..6cde3753b7 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_0_0/offramp_reader_unit_test.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_0_0/offramp_reader_unit_test.go @@ -6,16 +6,12 @@ import ( "slices" "testing" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/rpclib" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/rpclib/rpclibmocks" - "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" - evmclimocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller/mocks" @@ -27,6 +23,9 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/cache" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipcalc" + ccipdatamocks "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/mocks" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/rpclib" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/rpclib/rpclibmocks" ) func TestOffRampGetDestinationTokensFromSourceTokens(t *testing.T) { @@ -190,13 +189,15 @@ func Test_LogsAreProperlyMarkedAsFinalized(t *testing.T) { t.Run(tt.name, func(t *testing.T) { offrampAddress := utils.RandomAddress() + feeEstimatorConfig := ccipdatamocks.NewFeeEstimatorConfigReader(t) + lp := mocks.NewLogPoller(t) lp.On("LatestBlock", mock.Anything). Return(logpoller.LogPollerBlock{FinalizedBlockNumber: int64(tt.lastFinalizedBlock)}, nil) lp.On("IndexedLogsTopicRange", mock.Anything, ExecutionStateChangedEvent, offrampAddress, 1, logpoller.EvmWord(minSeqNr), logpoller.EvmWord(maxSeqNr), evmtypes.Confirmations(0)). Return(inputLogs, nil) - offRamp, err := NewOffRamp(logger.TestLogger(t), offrampAddress, evmclimocks.NewClient(t), lp, nil, nil) + offRamp, err := NewOffRamp(logger.TestLogger(t), offrampAddress, evmclimocks.NewClient(t), lp, nil, nil, feeEstimatorConfig) require.NoError(t, err) logs, err := offRamp.GetExecutionStateChangesBetweenSeqNums(testutils.Context(t), minSeqNr, maxSeqNr, 0) require.NoError(t, err) diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_0_0/onramp.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_0_0/onramp.go index 6737abe64c..d6f3094af7 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_0_0/onramp.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_0_0/onramp.go @@ -30,16 +30,16 @@ const ( var _ ccipdata.OnRampReader = &OnRamp{} type OnRamp struct { - address common.Address - onRamp *evm_2_evm_onramp_1_0_0.EVM2EVMOnRamp - lp logpoller.LogPoller - lggr logger.Logger - client client.Client - leafHasher ccipdata.LeafHasherInterface[[32]byte] - sendRequestedEventSig common.Hash - sendRequestedSeqNumberWord int - filters []logpoller.Filter - cachedSourcePriceRegistryAddress cache.AutoSync[cciptypes.Address] + address common.Address + onRamp *evm_2_evm_onramp_1_0_0.EVM2EVMOnRamp + lp logpoller.LogPoller + lggr logger.Logger + client client.Client + leafHasher ccipdata.LeafHasherInterface[[32]byte] + sendRequestedEventSig common.Hash + sendRequestedSeqNumberWord int + filters []logpoller.Filter + cachedOnRampDynamicConfig cache.AutoSync[cciptypes.OnRampDynamicConfig] // Static config can be cached, because it's never expected to change. // The only way to change that is through the contract's constructor (redeployment) cachedStaticConfig cache.OnceCtxFunction[evm_2_evm_onramp_1_0_0.EVM2EVMOnRampStaticConfig] @@ -90,7 +90,7 @@ func NewOnRamp(lggr logger.Logger, sourceSelector, destSelector uint64, onRampAd // offset || sourceChainID || seqNum || ... sendRequestedSeqNumberWord: 2, sendRequestedEventSig: eventSig, - cachedSourcePriceRegistryAddress: cache.NewLogpollerEventsBased[cciptypes.Address]( + cachedOnRampDynamicConfig: cache.NewLogpollerEventsBased[cciptypes.OnRampDynamicConfig]( sourceLP, []common.Hash{configSetEventSig}, onRampAddress, @@ -104,38 +104,38 @@ func (o *OnRamp) Address(context.Context) (cciptypes.Address, error) { return cciptypes.Address(o.onRamp.Address().String()), nil } -func (o *OnRamp) GetDynamicConfig(context.Context) (cciptypes.OnRampDynamicConfig, error) { - if o.onRamp == nil { - return cciptypes.OnRampDynamicConfig{}, fmt.Errorf("onramp not initialized") - } - legacyDynamicConfig, err := o.onRamp.GetDynamicConfig(nil) - if err != nil { - return cciptypes.OnRampDynamicConfig{}, err - } - return cciptypes.OnRampDynamicConfig{ - Router: cciptypes.Address(legacyDynamicConfig.Router.String()), - MaxNumberOfTokensPerMsg: legacyDynamicConfig.MaxTokensLength, - DestGasOverhead: 0, - DestGasPerPayloadByte: 0, - DestDataAvailabilityOverheadGas: 0, - DestGasPerDataAvailabilityByte: 0, - DestDataAvailabilityMultiplierBps: 0, - PriceRegistry: cciptypes.Address(legacyDynamicConfig.PriceRegistry.String()), - MaxDataBytes: legacyDynamicConfig.MaxDataSize, - MaxPerMsgGasLimit: uint32(legacyDynamicConfig.MaxGasLimit), - }, nil -} - -func (o *OnRamp) SourcePriceRegistryAddress(ctx context.Context) (cciptypes.Address, error) { - return o.cachedSourcePriceRegistryAddress.Get(ctx, func(ctx context.Context) (cciptypes.Address, error) { - c, err := o.GetDynamicConfig(ctx) +func (o *OnRamp) GetDynamicConfig(ctx context.Context) (cciptypes.OnRampDynamicConfig, error) { + return o.cachedOnRampDynamicConfig.Get(ctx, func(ctx context.Context) (cciptypes.OnRampDynamicConfig, error) { + if o.onRamp == nil { + return cciptypes.OnRampDynamicConfig{}, fmt.Errorf("onramp not initialized") + } + legacyDynamicConfig, err := o.onRamp.GetDynamicConfig(&bind.CallOpts{Context: ctx}) if err != nil { - return "", err + return cciptypes.OnRampDynamicConfig{}, err } - return c.PriceRegistry, nil + return cciptypes.OnRampDynamicConfig{ + Router: cciptypes.Address(legacyDynamicConfig.Router.String()), + MaxNumberOfTokensPerMsg: legacyDynamicConfig.MaxTokensLength, + DestGasOverhead: 0, + DestGasPerPayloadByte: 0, + DestDataAvailabilityOverheadGas: 0, + DestGasPerDataAvailabilityByte: 0, + DestDataAvailabilityMultiplierBps: 0, + PriceRegistry: cciptypes.Address(legacyDynamicConfig.PriceRegistry.String()), + MaxDataBytes: legacyDynamicConfig.MaxDataSize, + MaxPerMsgGasLimit: uint32(legacyDynamicConfig.MaxGasLimit), + }, nil }) } +func (o *OnRamp) SourcePriceRegistryAddress(ctx context.Context) (cciptypes.Address, error) { + c, err := o.GetDynamicConfig(ctx) + if err != nil { + return "", err + } + return c.PriceRegistry, nil +} + func (o *OnRamp) GetSendRequestsBetweenSeqNums(ctx context.Context, seqNumMin, seqNumMax uint64, finalized bool) ([]cciptypes.EVM2EVMMessageWithTxMeta, error) { logs, err := o.lp.LogsDataWordRange( ctx, @@ -165,8 +165,8 @@ func (o *OnRamp) GetSendRequestsBetweenSeqNums(ctx context.Context, seqNumMin, s return res, nil } -func (o *OnRamp) RouterAddress(context.Context) (cciptypes.Address, error) { - config, err := o.onRamp.GetDynamicConfig(nil) +func (o *OnRamp) RouterAddress(ctx context.Context) (cciptypes.Address, error) { + config, err := o.onRamp.GetDynamicConfig(&bind.CallOpts{Context: ctx}) if err != nil { return "", err } diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/commit_store.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/commit_store.go index 7612e54419..ecc8acb576 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/commit_store.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/commit_store.go @@ -49,9 +49,10 @@ type CommitStore struct { commitReportArgs abi.Arguments // Dynamic config - configMu sync.RWMutex - gasPriceEstimator *prices.DAGasPriceEstimator - offchainConfig cciptypes.CommitOffchainConfig + configMu sync.RWMutex + gasPriceEstimator *prices.DAGasPriceEstimator + offchainConfig cciptypes.CommitOffchainConfig + feeEstimatorConfig ccipdata.FeeEstimatorConfigReader } func (c *CommitStore) GetCommitStoreStaticConfig(ctx context.Context) (cciptypes.CommitStoreStaticConfig, error) { @@ -255,6 +256,7 @@ func (c *CommitStore) ChangeConfig(_ context.Context, onchainConfig []byte, offc c.sourceMaxGasPrice, int64(offchainConfigParsed.ExecGasPriceDeviationPPB), int64(offchainConfigParsed.DAGasPriceDeviationPPB), + c.feeEstimatorConfig, ) c.offchainConfig = ccipdata.NewCommitOffchainConfig( offchainConfigParsed.ExecGasPriceDeviationPPB, @@ -430,7 +432,7 @@ func (c *CommitStore) RegisterFilters() error { return logpollerutil.RegisterLpFilters(c.lp, c.filters) } -func NewCommitStore(lggr logger.Logger, addr common.Address, ec client.Client, lp logpoller.LogPoller) (*CommitStore, error) { +func NewCommitStore(lggr logger.Logger, addr common.Address, ec client.Client, lp logpoller.LogPoller, feeEstimatorConfig ccipdata.FeeEstimatorConfigReader) (*CommitStore, error) { commitStore, err := commit_store_1_2_0.NewCommitStore(addr, ec) if err != nil { return nil, err @@ -463,7 +465,8 @@ func NewCommitStore(lggr logger.Logger, addr common.Address, ec client.Client, l configMu: sync.RWMutex{}, // The fields below are initially empty and set on ChangeConfig method - offchainConfig: cciptypes.CommitOffchainConfig{}, - gasPriceEstimator: nil, + offchainConfig: cciptypes.CommitOffchainConfig{}, + gasPriceEstimator: nil, + feeEstimatorConfig: feeEstimatorConfig, }, nil } diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/commit_store_test.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/commit_store_test.go index 8b29309633..4307be0353 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/commit_store_test.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/commit_store_test.go @@ -10,7 +10,6 @@ import ( "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink-common/pkg/config" - cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller/mocks" @@ -18,6 +17,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/logger" ccipconfig "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/config" + ccipdatamocks "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/mocks" ) func TestCommitReportEncoding(t *testing.T) { @@ -48,7 +48,9 @@ func TestCommitReportEncoding(t *testing.T) { Interval: cciptypes.CommitStoreInterval{Min: 1, Max: 10}, } - c, err := NewCommitStore(logger.TestLogger(t), utils.RandomAddress(), nil, mocks.NewLogPoller(t)) + feeEstimatorConfig := ccipdatamocks.NewFeeEstimatorConfigReader(t) + + c, err := NewCommitStore(logger.TestLogger(t), utils.RandomAddress(), nil, mocks.NewLogPoller(t), feeEstimatorConfig) assert.NoError(t, err) encodedReport, err := c.EncodeCommitReport(ctx, report) diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/offramp.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/offramp.go index fa00894b38..f853adfb6f 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/offramp.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/offramp.go @@ -123,7 +123,8 @@ func (c JSONExecOffchainConfig) Validate() error { // OffRamp In 1.2 we have a different estimator impl type OffRamp struct { *v1_0_0.OffRamp - offRampV120 evm_2_evm_offramp_1_2_0.EVM2EVMOffRampInterface + offRampV120 evm_2_evm_offramp_1_2_0.EVM2EVMOffRampInterface + feeEstimatorConfig ccipdata.FeeEstimatorConfigReader } func (o *OffRamp) CurrentRateLimiterState(ctx context.Context) (cciptypes.TokenBucketRateLimit, error) { @@ -180,7 +181,7 @@ func (o *OffRamp) ChangeConfig(ctx context.Context, onchainConfigBytes []byte, o PermissionLessExecutionThresholdSeconds: time.Second * time.Duration(onchainConfigParsed.PermissionLessExecutionThresholdSeconds), Router: cciptypes.Address(onchainConfigParsed.Router.String()), } - priceEstimator := prices.NewDAGasPriceEstimator(o.Estimator, o.DestMaxGasPrice, 0, 0) + priceEstimator := prices.NewDAGasPriceEstimator(o.Estimator, o.DestMaxGasPrice, 0, 0, o.feeEstimatorConfig) o.UpdateDynamicConfig(onchainConfig, offchainConfig, priceEstimator) @@ -320,8 +321,16 @@ func (o *OffRamp) DecodeExecutionReport(ctx context.Context, report []byte) (cci return DecodeExecReport(ctx, o.ExecutionReportArgs, report) } -func NewOffRamp(lggr logger.Logger, addr common.Address, ec client.Client, lp logpoller.LogPoller, estimator gas.EvmFeeEstimator, destMaxGasPrice *big.Int) (*OffRamp, error) { - v100, err := v1_0_0.NewOffRamp(lggr, addr, ec, lp, estimator, destMaxGasPrice) +func NewOffRamp( + lggr logger.Logger, + addr common.Address, + ec client.Client, + lp logpoller.LogPoller, + estimator gas.EvmFeeEstimator, + destMaxGasPrice *big.Int, + feeEstimatorConfig ccipdata.FeeEstimatorConfigReader, +) (*OffRamp, error) { + v100, err := v1_0_0.NewOffRamp(lggr, addr, ec, lp, estimator, destMaxGasPrice, feeEstimatorConfig) if err != nil { return nil, err } @@ -334,7 +343,8 @@ func NewOffRamp(lggr logger.Logger, addr common.Address, ec client.Client, lp lo v100.ExecutionReportArgs = abihelpers.MustGetMethodInputs("manuallyExecute", abiOffRamp)[:1] return &OffRamp{ - OffRamp: v100, - offRampV120: offRamp, + OffRamp: v100, + offRampV120: offRamp, + feeEstimatorConfig: feeEstimatorConfig, }, nil } diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/offramp_reader_test.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/offramp_reader_test.go index f87fc8842f..c298349261 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/offramp_reader_test.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/offramp_reader_test.go @@ -11,6 +11,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/logger" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/mocks" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0" ) @@ -25,7 +26,9 @@ func TestExecutionReportEncodingV120(t *testing.T) { ProofFlagBits: big.NewInt(133), } - offRamp, err := v1_2_0.NewOffRamp(logger.TestLogger(t), utils.RandomAddress(), nil, lpmocks.NewLogPoller(t), nil, nil) + feeEstimatorConfig := mocks.NewFeeEstimatorConfigReader(t) + + offRamp, err := v1_2_0.NewOffRamp(logger.TestLogger(t), utils.RandomAddress(), nil, lpmocks.NewLogPoller(t), nil, nil, feeEstimatorConfig) require.NoError(t, err) ctx := testutils.Context(t) diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/onramp.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/onramp.go index 2939682347..2de2b104c9 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/onramp.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_2_0/onramp.go @@ -49,16 +49,16 @@ var _ ccipdata.OnRampReader = &OnRamp{} // Significant change in 1.2: // - CCIPSendRequested event signature has changed type OnRamp struct { - onRamp *evm_2_evm_onramp_1_2_0.EVM2EVMOnRamp - address common.Address - lggr logger.Logger - lp logpoller.LogPoller - leafHasher ccipdata.LeafHasherInterface[[32]byte] - client client.Client - sendRequestedEventSig common.Hash - sendRequestedSeqNumberWord int - filters []logpoller.Filter - cachedSourcePriceRegistryAddress cache.AutoSync[cciptypes.Address] + onRamp *evm_2_evm_onramp_1_2_0.EVM2EVMOnRamp + address common.Address + lggr logger.Logger + lp logpoller.LogPoller + leafHasher ccipdata.LeafHasherInterface[[32]byte] + client client.Client + sendRequestedEventSig common.Hash + sendRequestedSeqNumberWord int + filters []logpoller.Filter + cachedOnRampDynamicConfig cache.AutoSync[cciptypes.OnRampDynamicConfig] // Static config can be cached, because it's never expected to change. // The only way to change that is through the contract's constructor (redeployment) cachedStaticConfig cache.OnceCtxFunction[evm_2_evm_onramp_1_2_0.EVM2EVMOnRampStaticConfig] @@ -107,7 +107,7 @@ func NewOnRamp(lggr logger.Logger, sourceSelector, destSelector uint64, onRampAd address: onRampAddress, sendRequestedSeqNumberWord: CCIPSendRequestSeqNumIndex, sendRequestedEventSig: CCIPSendRequestEventSig, - cachedSourcePriceRegistryAddress: cache.NewLogpollerEventsBased[cciptypes.Address]( + cachedOnRampDynamicConfig: cache.NewLogpollerEventsBased[cciptypes.OnRampDynamicConfig]( sourceLP, []common.Hash{ConfigSetEventSig}, onRampAddress, @@ -121,38 +121,39 @@ func (o *OnRamp) Address(context.Context) (cciptypes.Address, error) { return cciptypes.Address(o.onRamp.Address().String()), nil } -func (o *OnRamp) GetDynamicConfig(context.Context) (cciptypes.OnRampDynamicConfig, error) { - if o.onRamp == nil { - return cciptypes.OnRampDynamicConfig{}, fmt.Errorf("onramp not initialized") - } - config, err := o.onRamp.GetDynamicConfig(&bind.CallOpts{}) - if err != nil { - return cciptypes.OnRampDynamicConfig{}, fmt.Errorf("get dynamic config v1.2: %w", err) - } - return cciptypes.OnRampDynamicConfig{ - Router: cciptypes.Address(config.Router.String()), - MaxNumberOfTokensPerMsg: config.MaxNumberOfTokensPerMsg, - DestGasOverhead: config.DestGasOverhead, - DestGasPerPayloadByte: config.DestGasPerPayloadByte, - DestDataAvailabilityOverheadGas: config.DestDataAvailabilityOverheadGas, - DestGasPerDataAvailabilityByte: config.DestGasPerDataAvailabilityByte, - DestDataAvailabilityMultiplierBps: config.DestDataAvailabilityMultiplierBps, - PriceRegistry: cciptypes.Address(config.PriceRegistry.String()), - MaxDataBytes: config.MaxDataBytes, - MaxPerMsgGasLimit: config.MaxPerMsgGasLimit, - }, nil -} - -func (o *OnRamp) SourcePriceRegistryAddress(ctx context.Context) (cciptypes.Address, error) { - return o.cachedSourcePriceRegistryAddress.Get(ctx, func(ctx context.Context) (cciptypes.Address, error) { - c, err := o.GetDynamicConfig(ctx) +func (o *OnRamp) GetDynamicConfig(ctx context.Context) (cciptypes.OnRampDynamicConfig, error) { + return o.cachedOnRampDynamicConfig.Get(ctx, func(ctx context.Context) (cciptypes.OnRampDynamicConfig, error) { + if o.onRamp == nil { + return cciptypes.OnRampDynamicConfig{}, fmt.Errorf("onramp not initialized") + } + config, err := o.onRamp.GetDynamicConfig(&bind.CallOpts{Context: ctx}) if err != nil { - return "", err + return cciptypes.OnRampDynamicConfig{}, fmt.Errorf("get dynamic config v1.2: %w", err) } - return c.PriceRegistry, nil + + return cciptypes.OnRampDynamicConfig{ + Router: cciptypes.Address(config.Router.String()), + MaxNumberOfTokensPerMsg: config.MaxNumberOfTokensPerMsg, + DestGasOverhead: config.DestGasOverhead, + DestGasPerPayloadByte: config.DestGasPerPayloadByte, + DestDataAvailabilityOverheadGas: config.DestDataAvailabilityOverheadGas, + DestGasPerDataAvailabilityByte: config.DestGasPerDataAvailabilityByte, + DestDataAvailabilityMultiplierBps: config.DestDataAvailabilityMultiplierBps, + PriceRegistry: cciptypes.Address(config.PriceRegistry.String()), + MaxDataBytes: config.MaxDataBytes, + MaxPerMsgGasLimit: config.MaxPerMsgGasLimit, + }, nil }) } +func (o *OnRamp) SourcePriceRegistryAddress(ctx context.Context) (cciptypes.Address, error) { + c, err := o.GetDynamicConfig(ctx) + if err != nil { + return "", err + } + return c.PriceRegistry, nil +} + func (o *OnRamp) GetSendRequestsBetweenSeqNums(ctx context.Context, seqNumMin, seqNumMax uint64, finalized bool) ([]cciptypes.EVM2EVMMessageWithTxMeta, error) { logs, err := o.lp.LogsDataWordRange( ctx, diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_5_0/commit_store.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_5_0/commit_store.go index 3bb582f3a2..d5545174cb 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_5_0/commit_store.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_5_0/commit_store.go @@ -3,6 +3,8 @@ package v1_5_0 import ( "context" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" @@ -41,8 +43,14 @@ func (c *CommitStore) IsDown(ctx context.Context) (bool, error) { return !unPausedAndNotCursed, nil } -func NewCommitStore(lggr logger.Logger, addr common.Address, ec client.Client, lp logpoller.LogPoller) (*CommitStore, error) { - v120, err := v1_2_0.NewCommitStore(lggr, addr, ec, lp) +func NewCommitStore( + lggr logger.Logger, + addr common.Address, + ec client.Client, + lp logpoller.LogPoller, + feeEstimatorConfig ccipdata.FeeEstimatorConfigReader, +) (*CommitStore, error) { + v120, err := v1_2_0.NewCommitStore(lggr, addr, ec, lp, feeEstimatorConfig) if err != nil { return nil, err } diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_5_0/offramp.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_5_0/offramp.go index 15f52bd713..11e7be1a55 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_5_0/offramp.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_5_0/offramp.go @@ -70,6 +70,7 @@ type OffRamp struct { *v1_2_0.OffRamp offRampV150 evm_2_evm_offramp.EVM2EVMOffRampInterface cachedRateLimitTokens cache.AutoSync[cciptypes.OffRampTokens] + feeEstimatorConfig ccipdata.FeeEstimatorConfigReader } // GetTokens Returns no data as the offRamps no longer have this information. @@ -155,7 +156,7 @@ func (o *OffRamp) ChangeConfig(ctx context.Context, onchainConfigBytes []byte, o PermissionLessExecutionThresholdSeconds: time.Second * time.Duration(onchainConfigParsed.PermissionLessExecutionThresholdSeconds), Router: cciptypes.Address(onchainConfigParsed.Router.String()), } - priceEstimator := prices.NewDAGasPriceEstimator(o.Estimator, o.DestMaxGasPrice, 0, 0) + priceEstimator := prices.NewDAGasPriceEstimator(o.Estimator, o.DestMaxGasPrice, 0, 0, o.feeEstimatorConfig) o.UpdateDynamicConfig(onchainConfig, offchainConfig, priceEstimator) @@ -166,8 +167,16 @@ func (o *OffRamp) ChangeConfig(ctx context.Context, onchainConfigBytes []byte, o cciptypes.Address(destWrappedNative.String()), nil } -func NewOffRamp(lggr logger.Logger, addr common.Address, ec client.Client, lp logpoller.LogPoller, estimator gas.EvmFeeEstimator, destMaxGasPrice *big.Int) (*OffRamp, error) { - v120, err := v1_2_0.NewOffRamp(lggr, addr, ec, lp, estimator, destMaxGasPrice) +func NewOffRamp( + lggr logger.Logger, + addr common.Address, + ec client.Client, + lp logpoller.LogPoller, + estimator gas.EvmFeeEstimator, + destMaxGasPrice *big.Int, + feeEstimatorConfig ccipdata.FeeEstimatorConfigReader, +) (*OffRamp, error) { + v120, err := v1_2_0.NewOffRamp(lggr, addr, ec, lp, estimator, destMaxGasPrice, feeEstimatorConfig) if err != nil { return nil, err } @@ -180,8 +189,9 @@ func NewOffRamp(lggr logger.Logger, addr common.Address, ec client.Client, lp lo v120.ExecutionReportArgs = abihelpers.MustGetMethodInputs("manuallyExecute", abiOffRamp)[:1] return &OffRamp{ - OffRamp: v120, - offRampV150: offRamp, + feeEstimatorConfig: feeEstimatorConfig, + OffRamp: v120, + offRampV150: offRamp, cachedRateLimitTokens: cache.NewLogpollerEventsBased[cciptypes.OffRampTokens]( lp, []common.Hash{RateLimitTokenAddedEvent, RateLimitTokenRemovedEvent}, diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_5_0/onramp.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_5_0/onramp.go index 354a5defdd..5a9377858d 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_5_0/onramp.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_5_0/onramp.go @@ -50,17 +50,17 @@ func init() { var _ ccipdata.OnRampReader = &OnRamp{} type OnRamp struct { - onRamp *evm_2_evm_onramp.EVM2EVMOnRamp - address common.Address - destChainSelectorBytes [16]byte - lggr logger.Logger - lp logpoller.LogPoller - leafHasher ccipdata.LeafHasherInterface[[32]byte] - client client.Client - sendRequestedEventSig common.Hash - sendRequestedSeqNumberWord int - filters []logpoller.Filter - cachedSourcePriceRegistryAddress cache.AutoSync[cciptypes.Address] + onRamp *evm_2_evm_onramp.EVM2EVMOnRamp + address common.Address + destChainSelectorBytes [16]byte + lggr logger.Logger + lp logpoller.LogPoller + leafHasher ccipdata.LeafHasherInterface[[32]byte] + client client.Client + sendRequestedEventSig common.Hash + sendRequestedSeqNumberWord int + filters []logpoller.Filter + cachedOnRampDynamicConfig cache.AutoSync[cciptypes.OnRampDynamicConfig] // Static config can be cached, because it's never expected to change. // The only way to change that is through the contract's constructor (redeployment) cachedStaticConfig cache.OnceCtxFunction[evm_2_evm_onramp.EVM2EVMOnRampStaticConfig] @@ -112,7 +112,7 @@ func NewOnRamp(lggr logger.Logger, sourceSelector, destSelector uint64, onRampAd address: onRampAddress, sendRequestedSeqNumberWord: CCIPSendRequestSeqNumIndex, sendRequestedEventSig: CCIPSendRequestEventSig, - cachedSourcePriceRegistryAddress: cache.NewLogpollerEventsBased[cciptypes.Address]( + cachedOnRampDynamicConfig: cache.NewLogpollerEventsBased[cciptypes.OnRampDynamicConfig]( sourceLP, []common.Hash{ConfigSetEventSig}, onRampAddress, @@ -126,38 +126,39 @@ func (o *OnRamp) Address(context.Context) (cciptypes.Address, error) { return ccipcalc.EvmAddrToGeneric(o.onRamp.Address()), nil } -func (o *OnRamp) GetDynamicConfig(context.Context) (cciptypes.OnRampDynamicConfig, error) { - if o.onRamp == nil { - return cciptypes.OnRampDynamicConfig{}, fmt.Errorf("onramp not initialized") - } - config, err := o.onRamp.GetDynamicConfig(&bind.CallOpts{}) - if err != nil { - return cciptypes.OnRampDynamicConfig{}, fmt.Errorf("get dynamic config v1.5: %w", err) - } - return cciptypes.OnRampDynamicConfig{ - Router: ccipcalc.EvmAddrToGeneric(config.Router), - MaxNumberOfTokensPerMsg: config.MaxNumberOfTokensPerMsg, - DestGasOverhead: config.DestGasOverhead, - DestGasPerPayloadByte: config.DestGasPerPayloadByte, - DestDataAvailabilityOverheadGas: config.DestDataAvailabilityOverheadGas, - DestGasPerDataAvailabilityByte: config.DestGasPerDataAvailabilityByte, - DestDataAvailabilityMultiplierBps: config.DestDataAvailabilityMultiplierBps, - PriceRegistry: ccipcalc.EvmAddrToGeneric(config.PriceRegistry), - MaxDataBytes: config.MaxDataBytes, - MaxPerMsgGasLimit: config.MaxPerMsgGasLimit, - }, nil -} - -func (o *OnRamp) SourcePriceRegistryAddress(ctx context.Context) (cciptypes.Address, error) { - return o.cachedSourcePriceRegistryAddress.Get(ctx, func(ctx context.Context) (cciptypes.Address, error) { - c, err := o.GetDynamicConfig(ctx) +func (o *OnRamp) GetDynamicConfig(ctx context.Context) (cciptypes.OnRampDynamicConfig, error) { + return o.cachedOnRampDynamicConfig.Get(ctx, func(ctx context.Context) (cciptypes.OnRampDynamicConfig, error) { + if o.onRamp == nil { + return cciptypes.OnRampDynamicConfig{}, fmt.Errorf("onramp not initialized") + } + config, err := o.onRamp.GetDynamicConfig(&bind.CallOpts{}) if err != nil { - return "", err + return cciptypes.OnRampDynamicConfig{}, fmt.Errorf("get dynamic config v1.5: %w", err) } - return c.PriceRegistry, nil + + return cciptypes.OnRampDynamicConfig{ + Router: ccipcalc.EvmAddrToGeneric(config.Router), + MaxNumberOfTokensPerMsg: config.MaxNumberOfTokensPerMsg, + DestGasOverhead: config.DestGasOverhead, + DestGasPerPayloadByte: config.DestGasPerPayloadByte, + DestDataAvailabilityOverheadGas: config.DestDataAvailabilityOverheadGas, + DestGasPerDataAvailabilityByte: config.DestGasPerDataAvailabilityByte, + DestDataAvailabilityMultiplierBps: config.DestDataAvailabilityMultiplierBps, + PriceRegistry: ccipcalc.EvmAddrToGeneric(config.PriceRegistry), + MaxDataBytes: config.MaxDataBytes, + MaxPerMsgGasLimit: config.MaxPerMsgGasLimit, + }, nil }) } +func (o *OnRamp) SourcePriceRegistryAddress(ctx context.Context) (cciptypes.Address, error) { + c, err := o.GetDynamicConfig(ctx) + if err != nil { + return "", err + } + return c.PriceRegistry, nil +} + func (o *OnRamp) GetSendRequestsBetweenSeqNums(ctx context.Context, seqNumMin, seqNumMax uint64, finalized bool) ([]cciptypes.EVM2EVMMessageWithTxMeta, error) { logs, err := o.lp.LogsDataWordRange( ctx, diff --git a/core/services/ocr2/plugins/ccip/prices/da_price_estimator.go b/core/services/ocr2/plugins/ccip/prices/da_price_estimator.go index 7c75b9bdd9..b27494ad60 100644 --- a/core/services/ocr2/plugins/ccip/prices/da_price_estimator.go +++ b/core/services/ocr2/plugins/ccip/prices/da_price_estimator.go @@ -5,6 +5,8 @@ import ( "fmt" "math/big" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata" + cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/rollups" @@ -14,11 +16,9 @@ import ( type DAGasPriceEstimator struct { execEstimator GasPriceEstimator l1Oracle rollups.L1Oracle + feeEstimatorConfig ccipdata.FeeEstimatorConfigReader priceEncodingLength uint daDeviationPPB int64 - daOverheadGas int64 - gasPerDAByte int64 - daMultiplier int64 } func NewDAGasPriceEstimator( @@ -26,12 +26,14 @@ func NewDAGasPriceEstimator( maxGasPrice *big.Int, deviationPPB int64, daDeviationPPB int64, + feeEstimatorConfig ccipdata.FeeEstimatorConfigReader, // DA Config Cache updates in the onRamp reader and shares the state ) *DAGasPriceEstimator { return &DAGasPriceEstimator{ execEstimator: NewExecGasPriceEstimator(estimator, maxGasPrice, deviationPPB), l1Oracle: estimator.L1Oracle(), priceEncodingLength: daGasPriceEncodingLength, daDeviationPPB: daDeviationPPB, + feeEstimatorConfig: feeEstimatorConfig, } } @@ -141,7 +143,10 @@ func (g DAGasPriceEstimator) EstimateMsgCostUSD(p *big.Int, wrappedNativePrice * // If there is data availability price component, then include data availability cost in fee estimation if daGasPrice.Cmp(big.NewInt(0)) > 0 { - daGasCostUSD := g.estimateDACostUSD(daGasPrice, wrappedNativePrice, msg) + daGasCostUSD, err := g.estimateDACostUSD(daGasPrice, wrappedNativePrice, msg) + if err != nil { + return nil, err + } execCostUSD = new(big.Int).Add(daGasCostUSD, execCostUSD) } return execCostUSD, nil @@ -160,17 +165,22 @@ func (g DAGasPriceEstimator) parseEncodedGasPrice(p *big.Int) (*big.Int, *big.In return daGasPrice, execGasPrice, nil } -func (g DAGasPriceEstimator) estimateDACostUSD(daGasPrice *big.Int, wrappedNativePrice *big.Int, msg cciptypes.EVM2EVMOnRampCCIPSendRequestedWithMeta) *big.Int { +func (g DAGasPriceEstimator) estimateDACostUSD(daGasPrice *big.Int, wrappedNativePrice *big.Int, msg cciptypes.EVM2EVMOnRampCCIPSendRequestedWithMeta) (*big.Int, error) { var sourceTokenDataLen int for _, tokenData := range msg.SourceTokenData { sourceTokenDataLen += len(tokenData) } + daOverheadGas, gasPerDAByte, daMultiplier, err := g.feeEstimatorConfig.GetDataAvailabilityConfig(context.Background()) + if err != nil { + return nil, err + } + dataLen := evmMessageFixedBytes + len(msg.Data) + len(msg.TokenAmounts)*evmMessageBytesPerToken + sourceTokenDataLen - dataGas := big.NewInt(int64(dataLen)*g.gasPerDAByte + g.daOverheadGas) + dataGas := big.NewInt(int64(dataLen)*gasPerDAByte + daOverheadGas) dataGasEstimate := new(big.Int).Mul(dataGas, daGasPrice) - dataGasEstimate = new(big.Int).Div(new(big.Int).Mul(dataGasEstimate, big.NewInt(g.daMultiplier)), big.NewInt(daMultiplierBase)) + dataGasEstimate = new(big.Int).Div(new(big.Int).Mul(dataGasEstimate, big.NewInt(daMultiplier)), big.NewInt(daMultiplierBase)) - return ccipcalc.CalculateUsdPerUnitGas(dataGasEstimate, wrappedNativePrice) + return ccipcalc.CalculateUsdPerUnitGas(dataGasEstimate, wrappedNativePrice), nil } diff --git a/core/services/ocr2/plugins/ccip/prices/da_price_estimator_test.go b/core/services/ocr2/plugins/ccip/prices/da_price_estimator_test.go index 2f8616a866..158f02c4f0 100644 --- a/core/services/ocr2/plugins/ccip/prices/da_price_estimator_test.go +++ b/core/services/ocr2/plugins/ccip/prices/da_price_estimator_test.go @@ -2,6 +2,7 @@ package prices import ( "context" + "errors" "math/big" "testing" @@ -11,6 +12,7 @@ import ( cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/rollups/mocks" + ccipdatamocks "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/mocks" ) func encodeGasPrice(daPrice, execPrice *big.Int) *big.Int { @@ -325,14 +327,17 @@ func TestDAPriceEstimator_EstimateMsgCostUSD(t *testing.T) { execCostUSD := big.NewInt(100_000) testCases := []struct { - name string - gasPrice *big.Int - wrappedNativePrice *big.Int - msg cciptypes.EVM2EVMOnRampCCIPSendRequestedWithMeta - daOverheadGas int64 - gasPerDAByte int64 - daMultiplier int64 - expUSD *big.Int + name string + gasPrice *big.Int + wrappedNativePrice *big.Int + msg cciptypes.EVM2EVMOnRampCCIPSendRequestedWithMeta + daOverheadGas int64 + gasPerDAByte int64 + daMultiplier int64 + expUSD *big.Int + onRampConfig cciptypes.OnRampDynamicConfig + execEstimatorResponse []any + execEstimatorErr error }{ { name: "only DA overhead", @@ -345,10 +350,8 @@ func TestDAPriceEstimator_EstimateMsgCostUSD(t *testing.T) { SourceTokenData: [][]byte{}, }, }, - daOverheadGas: 100_000, - gasPerDAByte: 0, - daMultiplier: 10_000, // 1x multiplier - expUSD: new(big.Int).Add(execCostUSD, big.NewInt(100_000e9)), + expUSD: new(big.Int).Add(execCostUSD, big.NewInt(100_000e9)), + execEstimatorResponse: []any{int64(100_000), int64(0), int64(10_000), nil}, }, { name: "include message data gas", @@ -363,10 +366,8 @@ func TestDAPriceEstimator_EstimateMsgCostUSD(t *testing.T) { }, }, }, - daOverheadGas: 100_000, - gasPerDAByte: 16, - daMultiplier: 10_000, // 1x multiplier - expUSD: new(big.Int).Add(execCostUSD, big.NewInt(134_208e9)), + expUSD: new(big.Int).Add(execCostUSD, big.NewInt(134_208e9)), + execEstimatorResponse: []any{int64(100_000), int64(16), int64(10_000), nil}, }, { name: "zero DA price", @@ -379,10 +380,7 @@ func TestDAPriceEstimator_EstimateMsgCostUSD(t *testing.T) { SourceTokenData: [][]byte{}, }, }, - daOverheadGas: 100_000, - gasPerDAByte: 16, - daMultiplier: 10_000, // 1x multiplier - expUSD: execCostUSD, + expUSD: execCostUSD, }, { name: "double native price", @@ -395,10 +393,8 @@ func TestDAPriceEstimator_EstimateMsgCostUSD(t *testing.T) { SourceTokenData: [][]byte{}, }, }, - daOverheadGas: 100_000, - gasPerDAByte: 0, - daMultiplier: 10_000, // 1x multiplier - expUSD: new(big.Int).Add(execCostUSD, big.NewInt(200_000e9)), + expUSD: new(big.Int).Add(execCostUSD, big.NewInt(200_000e9)), + execEstimatorResponse: []any{int64(100_000), int64(0), int64(10_000), nil}, }, { name: "half multiplier", @@ -411,30 +407,66 @@ func TestDAPriceEstimator_EstimateMsgCostUSD(t *testing.T) { SourceTokenData: [][]byte{}, }, }, - daOverheadGas: 100_000, - gasPerDAByte: 0, - daMultiplier: 5_000, // 0.5x multiplier - expUSD: new(big.Int).Add(execCostUSD, big.NewInt(50_000e9)), + expUSD: new(big.Int).Add(execCostUSD, big.NewInt(50_000e9)), + execEstimatorResponse: []any{int64(100_000), int64(0), int64(5_000), nil}, + }, + { + name: "onRamp reader error", + gasPrice: encodeGasPrice(big.NewInt(1e9), big.NewInt(0)), // 1 gwei DA price, 0 exec price + wrappedNativePrice: big.NewInt(1e18), // $1 + msg: cciptypes.EVM2EVMOnRampCCIPSendRequestedWithMeta{ + EVM2EVMMessage: cciptypes.EVM2EVMMessage{ + Data: []byte{}, + TokenAmounts: []cciptypes.TokenAmount{}, + SourceTokenData: [][]byte{}, + }, + }, + execEstimatorResponse: []any{int64(0), int64(0), int64(0), errors.New("some reader error")}, + }, + { + name: "execEstimator error", + gasPrice: encodeGasPrice(big.NewInt(1e9), big.NewInt(0)), // 1 gwei DA price, 0 exec price + wrappedNativePrice: big.NewInt(1e18), // $1 + msg: cciptypes.EVM2EVMOnRampCCIPSendRequestedWithMeta{ + EVM2EVMMessage: cciptypes.EVM2EVMMessage{ + Data: []byte{}, + TokenAmounts: []cciptypes.TokenAmount{}, + SourceTokenData: [][]byte{}, + }, + }, + execEstimatorErr: errors.New("some estimator error"), }, } for _, tc := range testCases { - execEstimator := NewMockGasPriceEstimator(t) - execEstimator.On("EstimateMsgCostUSD", mock.Anything, tc.wrappedNativePrice, tc.msg).Return(execCostUSD, nil) - t.Run(tc.name, func(t *testing.T) { + execEstimator := NewMockGasPriceEstimator(t) + execEstimator.On("EstimateMsgCostUSD", mock.Anything, tc.wrappedNativePrice, tc.msg). + Return(execCostUSD, tc.execEstimatorErr) + + feeEstimatorConfig := ccipdatamocks.NewFeeEstimatorConfigReader(t) + if len(tc.execEstimatorResponse) > 0 { + feeEstimatorConfig.On("GetDataAvailabilityConfig", mock.Anything). + Return(tc.execEstimatorResponse...) + } + g := DAGasPriceEstimator{ execEstimator: execEstimator, l1Oracle: nil, priceEncodingLength: daGasPriceEncodingLength, - daOverheadGas: tc.daOverheadGas, - gasPerDAByte: tc.gasPerDAByte, - daMultiplier: tc.daMultiplier, + feeEstimatorConfig: feeEstimatorConfig, } costUSD, err := g.EstimateMsgCostUSD(tc.gasPrice, tc.wrappedNativePrice, tc.msg) - assert.NoError(t, err) - assert.Equal(t, tc.expUSD, costUSD) + + switch { + case len(tc.execEstimatorResponse) == 4 && tc.execEstimatorResponse[3] != nil, + tc.execEstimatorErr != nil: + assert.Error(t, err) + default: + assert.NoError(t, err) + assert.Equal(t, tc.expUSD, costUSD) + } }) } } diff --git a/core/services/ocr2/plugins/ccip/prices/gas_price_estimator.go b/core/services/ocr2/plugins/ccip/prices/gas_price_estimator.go index 49a6fbcc4a..4aac664e33 100644 --- a/core/services/ocr2/plugins/ccip/prices/gas_price_estimator.go +++ b/core/services/ocr2/plugins/ccip/prices/gas_price_estimator.go @@ -3,6 +3,8 @@ package prices import ( "math/big" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata" + "github.com/Masterminds/semver/v3" "github.com/pkg/errors" @@ -47,12 +49,13 @@ func NewGasPriceEstimatorForCommitPlugin( maxExecGasPrice *big.Int, daDeviationPPB int64, execDeviationPPB int64, + feeEstimatorConfig ccipdata.FeeEstimatorConfigReader, ) (GasPriceEstimatorCommit, error) { switch commitStoreVersion.String() { case "1.0.0", "1.1.0": return NewExecGasPriceEstimator(estimator, maxExecGasPrice, execDeviationPPB), nil case "1.2.0": - return NewDAGasPriceEstimator(estimator, maxExecGasPrice, execDeviationPPB, daDeviationPPB), nil + return NewDAGasPriceEstimator(estimator, maxExecGasPrice, execDeviationPPB, daDeviationPPB, feeEstimatorConfig), nil default: return nil, errors.Errorf("Invalid commitStore version: %s", commitStoreVersion) } diff --git a/core/services/relay/evm/ccip.go b/core/services/relay/evm/ccip.go index 34a732e145..945763de85 100644 --- a/core/services/relay/evm/ccip.go +++ b/core/services/relay/evm/ccip.go @@ -6,18 +6,16 @@ import ( "math/big" "time" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/abihelpers" - + cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" "github.com/smartcontractkit/chainlink/v2/core/logger" - - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/abihelpers" ccipconfig "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/config" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/estimatorconfig" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/prices" - - cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" ) var _ cciptypes.CommitStoreReader = (*IncompleteSourceCommitStoreReader)(nil) @@ -26,16 +24,18 @@ var _ cciptypes.CommitStoreReader = (*IncompleteDestCommitStoreReader)(nil) // IncompleteSourceCommitStoreReader is an implementation of CommitStoreReader with the only valid methods being // GasPriceEstimator, ChangeConfig, and OffchainConfig type IncompleteSourceCommitStoreReader struct { - estimator gas.EvmFeeEstimator - gasPriceEstimator *prices.DAGasPriceEstimator - sourceMaxGasPrice *big.Int - offchainConfig cciptypes.CommitOffchainConfig + estimator gas.EvmFeeEstimator + gasPriceEstimator *prices.DAGasPriceEstimator + sourceMaxGasPrice *big.Int + offchainConfig cciptypes.CommitOffchainConfig + feeEstimatorConfig estimatorconfig.FeeEstimatorConfigProvider } -func NewIncompleteSourceCommitStoreReader(estimator gas.EvmFeeEstimator, sourceMaxGasPrice *big.Int) *IncompleteSourceCommitStoreReader { +func NewIncompleteSourceCommitStoreReader(estimator gas.EvmFeeEstimator, sourceMaxGasPrice *big.Int, feeEstimatorConfig estimatorconfig.FeeEstimatorConfigProvider) *IncompleteSourceCommitStoreReader { return &IncompleteSourceCommitStoreReader{ - estimator: estimator, - sourceMaxGasPrice: sourceMaxGasPrice, + estimator: estimator, + sourceMaxGasPrice: sourceMaxGasPrice, + feeEstimatorConfig: feeEstimatorConfig, } } @@ -55,6 +55,7 @@ func (i *IncompleteSourceCommitStoreReader) ChangeConfig(ctx context.Context, on i.sourceMaxGasPrice, int64(offchainConfigParsed.ExecGasPriceDeviationPPB), int64(offchainConfigParsed.DAGasPriceDeviationPPB), + i.feeEstimatorConfig, ) i.offchainConfig = ccip.NewCommitOffchainConfig( offchainConfigParsed.ExecGasPriceDeviationPPB, @@ -133,8 +134,15 @@ type IncompleteDestCommitStoreReader struct { cs cciptypes.CommitStoreReader } -func NewIncompleteDestCommitStoreReader(lggr logger.Logger, versionFinder ccip.VersionFinder, address cciptypes.Address, ec client.Client, lp logpoller.LogPoller) (*IncompleteDestCommitStoreReader, error) { - cs, err := ccip.NewCommitStoreReader(lggr, versionFinder, address, ec, lp) +func NewIncompleteDestCommitStoreReader( + lggr logger.Logger, + versionFinder ccip.VersionFinder, + address cciptypes.Address, + ec client.Client, + lp logpoller.LogPoller, + feeEstimatorConfig estimatorconfig.FeeEstimatorConfigProvider, +) (*IncompleteDestCommitStoreReader, error) { + cs, err := ccip.NewCommitStoreReader(lggr, versionFinder, address, ec, lp, feeEstimatorConfig) if err != nil { return nil, err } diff --git a/core/services/relay/evm/commit_provider.go b/core/services/relay/evm/commit_provider.go index 35de8efbd8..780d1cee7b 100644 --- a/core/services/relay/evm/commit_provider.go +++ b/core/services/relay/evm/commit_provider.go @@ -18,18 +18,20 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/estimatorconfig" ) var _ commontypes.CCIPCommitProvider = (*SrcCommitProvider)(nil) var _ commontypes.CCIPCommitProvider = (*DstCommitProvider)(nil) type SrcCommitProvider struct { - lggr logger.Logger - startBlock uint64 - client client.Client - lp logpoller.LogPoller - estimator gas.EvmFeeEstimator - maxGasPrice *big.Int + lggr logger.Logger + startBlock uint64 + client client.Client + lp logpoller.LogPoller + estimator gas.EvmFeeEstimator + maxGasPrice *big.Int + feeEstimatorConfig estimatorconfig.FeeEstimatorConfigProvider // these values will be lazily initialized seenOnRampAddress *cciptypes.Address @@ -44,14 +46,16 @@ func NewSrcCommitProvider( lp logpoller.LogPoller, srcEstimator gas.EvmFeeEstimator, maxGasPrice *big.Int, + feeEstimatorConfig estimatorconfig.FeeEstimatorConfigProvider, ) commontypes.CCIPCommitProvider { return &SrcCommitProvider{ - lggr: lggr, - startBlock: startBlock, - client: client, - lp: lp, - estimator: srcEstimator, - maxGasPrice: maxGasPrice, + lggr: lggr, + startBlock: startBlock, + client: client, + lp: lp, + estimator: srcEstimator, + maxGasPrice: maxGasPrice, + feeEstimatorConfig: feeEstimatorConfig, } } @@ -65,6 +69,7 @@ type DstCommitProvider struct { configWatcher *configWatcher gasEstimator gas.EvmFeeEstimator maxGasPrice big.Int + feeEstimatorConfig estimatorconfig.FeeEstimatorConfigProvider // these values will be lazily initialized seenCommitStoreAddress *cciptypes.Address @@ -81,6 +86,7 @@ func NewDstCommitProvider( maxGasPrice big.Int, contractTransmitter contractTransmitter, configWatcher *configWatcher, + feeEstimatorConfig estimatorconfig.FeeEstimatorConfigProvider, ) commontypes.CCIPCommitProvider { return &DstCommitProvider{ lggr: lggr, @@ -92,6 +98,7 @@ func NewDstCommitProvider( configWatcher: configWatcher, gasEstimator: gasEstimator, maxGasPrice: maxGasPrice, + feeEstimatorConfig: feeEstimatorConfig, } } @@ -170,13 +177,13 @@ func (P *DstCommitProvider) Close() error { if P.seenCommitStoreAddress == nil { return nil } - return ccip.CloseCommitStoreReader(P.lggr, versionFinder, *P.seenCommitStoreAddress, P.client, P.lp) + return ccip.CloseCommitStoreReader(P.lggr, versionFinder, *P.seenCommitStoreAddress, P.client, P.lp, P.feeEstimatorConfig) }) unregisterFuncs = append(unregisterFuncs, func() error { if P.seenOffRampAddress == nil { return nil } - return ccip.CloseOffRampReader(P.lggr, versionFinder, *P.seenOffRampAddress, P.client, P.lp, nil, big.NewInt(0)) + return ccip.CloseOffRampReader(P.lggr, versionFinder, *P.seenOffRampAddress, P.client, P.lp, nil, big.NewInt(0), P.feeEstimatorConfig) }) var multiErr error @@ -241,7 +248,7 @@ func (P *DstCommitProvider) NewPriceGetter(ctx context.Context) (priceGetter cci } func (P *SrcCommitProvider) NewCommitStoreReader(ctx context.Context, commitStoreAddress cciptypes.Address) (commitStoreReader cciptypes.CommitStoreReader, err error) { - commitStoreReader = NewIncompleteSourceCommitStoreReader(P.estimator, P.maxGasPrice) + commitStoreReader = NewIncompleteSourceCommitStoreReader(P.estimator, P.maxGasPrice, P.feeEstimatorConfig) return } @@ -249,7 +256,7 @@ func (P *DstCommitProvider) NewCommitStoreReader(ctx context.Context, commitStor P.seenCommitStoreAddress = &commitStoreAddress versionFinder := ccip.NewEvmVersionFinder() - commitStoreReader, err = NewIncompleteDestCommitStoreReader(P.lggr, versionFinder, commitStoreAddress, P.client, P.lp) + commitStoreReader, err = NewIncompleteDestCommitStoreReader(P.lggr, versionFinder, commitStoreAddress, P.client, P.lp, P.feeEstimatorConfig) return } @@ -259,7 +266,12 @@ func (P *SrcCommitProvider) NewOnRampReader(ctx context.Context, onRampAddress c P.seenDestChainSelector = &destChainSelector versionFinder := ccip.NewEvmVersionFinder() + onRampReader, err = ccip.NewOnRampReader(P.lggr, versionFinder, sourceChainSelector, destChainSelector, onRampAddress, P.lp, P.client) + if err != nil { + return nil, err + } + P.feeEstimatorConfig.SetOnRampReader(onRampReader) return } @@ -272,7 +284,7 @@ func (P *SrcCommitProvider) NewOffRampReader(ctx context.Context, offRampAddr cc } func (P *DstCommitProvider) NewOffRampReader(ctx context.Context, offRampAddr cciptypes.Address) (offRampReader cciptypes.OffRampReader, err error) { - offRampReader, err = ccip.NewOffRampReader(P.lggr, P.versionFinder, offRampAddr, P.client, P.lp, P.gasEstimator, &P.maxGasPrice, true) + offRampReader, err = ccip.NewOffRampReader(P.lggr, P.versionFinder, offRampAddr, P.client, P.lp, P.gasEstimator, &P.maxGasPrice, true, P.feeEstimatorConfig) return } diff --git a/core/services/relay/evm/evm.go b/core/services/relay/evm/evm.go index fe84949903..85cb3486ca 100644 --- a/core/services/relay/evm/evm.go +++ b/core/services/relay/evm/evm.go @@ -45,6 +45,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/keystore" "github.com/smartcontractkit/chainlink/v2/core/services/llo" "github.com/smartcontractkit/chainlink/v2/core/services/llo/bm" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/estimatorconfig" lloconfig "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/llo/config" mercuryconfig "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/mercury/config" "github.com/smartcontractkit/chainlink/v2/core/services/ocrcommon" @@ -406,6 +407,8 @@ func (r *Relayer) NewCCIPCommitProvider(rargs commontypes.RelayArgs, pargs commo sourceStartBlock := commitPluginConfig.SourceStartBlock destStartBlock := commitPluginConfig.DestStartBlock + feeEstimatorConfig := estimatorconfig.NewFeeEstimatorConfigService() + // The src chain implementation of this provider does not need a configWatcher or contractTransmitter; // bail early. if commitPluginConfig.IsSourceProvider { @@ -416,6 +419,7 @@ func (r *Relayer) NewCCIPCommitProvider(rargs commontypes.RelayArgs, pargs commo r.chain.LogPoller(), r.chain.GasEstimator(), r.chain.Config().EVM().GasEstimator().PriceMax().ToInt(), + feeEstimatorConfig, ), nil } @@ -451,6 +455,7 @@ func (r *Relayer) NewCCIPCommitProvider(rargs commontypes.RelayArgs, pargs commo *r.chain.Config().EVM().GasEstimator().PriceMax().ToInt(), *contractTransmitter, configWatcher, + feeEstimatorConfig, ), nil } @@ -473,6 +478,8 @@ func (r *Relayer) NewCCIPExecProvider(rargs commontypes.RelayArgs, pargs commont usdcConfig := execPluginConfig.USDCConfig + feeEstimatorConfig := estimatorconfig.NewFeeEstimatorConfigService() + // The src chain implementation of this provider does not need a configWatcher or contractTransmitter; // bail early. if execPluginConfig.IsSourceProvider { @@ -489,6 +496,7 @@ func (r *Relayer) NewCCIPExecProvider(rargs commontypes.RelayArgs, pargs commont int(usdcConfig.AttestationAPITimeoutSeconds), usdcConfig.AttestationAPIIntervalMilliseconds, usdcConfig.SourceMessageTransmitterAddress, + feeEstimatorConfig, ) } @@ -524,6 +532,7 @@ func (r *Relayer) NewCCIPExecProvider(rargs commontypes.RelayArgs, pargs commont configWatcher, r.chain.GasEstimator(), *r.chain.Config().EVM().GasEstimator().PriceMax().ToInt(), + feeEstimatorConfig, r.chain.TxManager(), cciptypes.Address(rargs.ContractID), ) diff --git a/core/services/relay/evm/exec_provider.go b/core/services/relay/evm/exec_provider.go index d0e567af73..e50ae41351 100644 --- a/core/services/relay/evm/exec_provider.go +++ b/core/services/relay/evm/exec_provider.go @@ -23,6 +23,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/estimatorconfig" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/tokendata/usdc" ) @@ -40,6 +41,8 @@ type SrcExecProvider struct { usdcAttestationAPIIntervalMilliseconds int usdcSrcMsgTransmitterAddr common.Address + feeEstimatorConfig estimatorconfig.FeeEstimatorConfigProvider + // these values are nil and are updated for Close() seenOnRampAddress *cciptypes.Address seenSourceChainSelector *uint64 @@ -59,6 +62,7 @@ func NewSrcExecProvider( usdcAttestationAPITimeoutSeconds int, usdcAttestationAPIIntervalMilliseconds int, usdcSrcMsgTransmitterAddr common.Address, + feeEstimatorConfig estimatorconfig.FeeEstimatorConfigProvider, ) (commontypes.CCIPExecProvider, error) { var usdcReader *ccip.USDCReaderImpl var err error @@ -82,6 +86,7 @@ func NewSrcExecProvider( usdcAttestationAPITimeoutSeconds: usdcAttestationAPITimeoutSeconds, usdcAttestationAPIIntervalMilliseconds: usdcAttestationAPIIntervalMilliseconds, usdcSrcMsgTransmitterAddr: usdcSrcMsgTransmitterAddr, + feeEstimatorConfig: feeEstimatorConfig, }, nil } @@ -163,7 +168,7 @@ func (s *SrcExecProvider) GetTransactionStatus(ctx context.Context, transactionI } func (s *SrcExecProvider) NewCommitStoreReader(ctx context.Context, addr cciptypes.Address) (commitStoreReader cciptypes.CommitStoreReader, err error) { - commitStoreReader = NewIncompleteSourceCommitStoreReader(s.estimator, s.maxGasPrice) + commitStoreReader = NewIncompleteSourceCommitStoreReader(s.estimator, s.maxGasPrice, s.feeEstimatorConfig) return } @@ -176,6 +181,10 @@ func (s *SrcExecProvider) NewOnRampReader(ctx context.Context, onRampAddress cci versionFinder := ccip.NewEvmVersionFinder() onRampReader, err = ccip.NewOnRampReader(s.lggr, versionFinder, sourceChainSelector, destChainSelector, onRampAddress, s.lp, s.client) + if err != nil { + return nil, err + } + s.feeEstimatorConfig.SetOnRampReader(onRampReader) return } @@ -236,6 +245,7 @@ type DstExecProvider struct { configWatcher *configWatcher gasEstimator gas.EvmFeeEstimator maxGasPrice big.Int + feeEstimatorConfig estimatorconfig.FeeEstimatorConfigProvider txm txmgr.TxManager offRampAddress cciptypes.Address @@ -253,6 +263,7 @@ func NewDstExecProvider( configWatcher *configWatcher, gasEstimator gas.EvmFeeEstimator, maxGasPrice big.Int, + feeEstimatorConfig estimatorconfig.FeeEstimatorConfigProvider, txm txmgr.TxManager, offRampAddress cciptypes.Address, ) (commontypes.CCIPExecProvider, error) { @@ -266,6 +277,7 @@ func NewDstExecProvider( configWatcher: configWatcher, gasEstimator: gasEstimator, maxGasPrice: maxGasPrice, + feeEstimatorConfig: feeEstimatorConfig, txm: txm, offRampAddress: offRampAddress, }, nil @@ -295,10 +307,10 @@ func (d *DstExecProvider) Close() error { if d.seenCommitStoreAddr == nil { return nil } - return ccip.CloseCommitStoreReader(d.lggr, versionFinder, *d.seenCommitStoreAddr, d.client, d.lp) + return ccip.CloseCommitStoreReader(d.lggr, versionFinder, *d.seenCommitStoreAddr, d.client, d.lp, d.feeEstimatorConfig) }) unregisterFuncs = append(unregisterFuncs, func() error { - return ccip.CloseOffRampReader(d.lggr, versionFinder, d.offRampAddress, d.client, d.lp, nil, big.NewInt(0)) + return ccip.CloseOffRampReader(d.lggr, versionFinder, d.offRampAddress, d.client, d.lp, nil, big.NewInt(0), d.feeEstimatorConfig) }) var multiErr error @@ -346,12 +358,12 @@ func (d *DstExecProvider) NewCommitStoreReader(ctx context.Context, addr cciptyp d.seenCommitStoreAddr = &addr versionFinder := ccip.NewEvmVersionFinder() - commitStoreReader, err = NewIncompleteDestCommitStoreReader(d.lggr, versionFinder, addr, d.client, d.lp) + commitStoreReader, err = NewIncompleteDestCommitStoreReader(d.lggr, versionFinder, addr, d.client, d.lp, d.feeEstimatorConfig) return } func (d *DstExecProvider) NewOffRampReader(ctx context.Context, offRampAddress cciptypes.Address) (offRampReader cciptypes.OffRampReader, err error) { - offRampReader, err = ccip.NewOffRampReader(d.lggr, d.versionFinder, offRampAddress, d.client, d.lp, d.gasEstimator, &d.maxGasPrice, true) + offRampReader, err = ccip.NewOffRampReader(d.lggr, d.versionFinder, offRampAddress, d.client, d.lp, d.gasEstimator, &d.maxGasPrice, true, d.feeEstimatorConfig) return } From af392bb7da94f45345dc6114ab58b9677207242a Mon Sep 17 00:00:00 2001 From: Bartek Tofel Date: Fri, 9 Aug 2024 12:48:22 +0200 Subject: [PATCH 052/115] [TT-1326] Update Solidty Foundry pipeline with Slither (#13986) * More univeral lcov prunning * update Shared code cov * exclude deleted files from Slither * use single source of truth for all Solidity Foundry jobs * fix json * compact output with jq * fix condition for fmt * try to scope tests to changes * move matrix check to step level * fix outputs path * trigger * test with Automation change * try with shared * run fmt also if any sol files were modified * fix job name in collect metrics * trigger pipeline only for localised change + update changes info * add changeset * remove test change * do not run forge fmt if shared contracts have changed * try artifact pipeline by hijacking hardhat * # This is a combination of 2 commits. CR changes + test them use shell array * CR changes + test them use shell array init array CR changes + test them use shell array init array * remove test files * do not run Slither for test files * do not run fmt if test files were modified * remove unused config file * restore old Hardhat pipeline * add missing transmission setup * fix basic info condition, join 2 steps into 1, define higher-level coverage exclusions * define actions for installing Slither and solc-select * run all tests also if package.json changes; run them on all non_src changes * add action for validating whether all Slither reports and UML diagrams were generated * fetch origin in validation action * compare with HEAD in validate action * compare with origin in validation action * handle both csv and shell arrays in the validation action * update artifact pipeline with new actions * fix workflow after tests * fix how validation actions works with commits * treat shared as any other product * small fixes * apply CR changes * remove special handling for deleted files * remove apt-get update * use only dorny/paths * remove unused input * CR changes: use dorny/paths with quantifier, move scope validation to an action, remove whitespaces * fix workflow * fail bash scripts on erors * add set -euo pipefail to bash scripts * define action to detect foundry version * fix select solc version script, better slither report output * checkout repo * add id --- .../action.yml | 26 ++ .github/actions/setup-slither/action.yaml | 10 + .github/actions/setup-solc-select/action.yaml | 30 ++ .../validate-artifact-scope/action.yaml | 103 +++++ .../validate-solidity-artifacts/action.yaml | 115 ++++++ .../workflows/solidity-foundry-artifacts.yml | 371 ++++++++++++++++++ .github/workflows/solidity-foundry.yml | 336 +++++++++++----- .github/workflows/solidity-hardhat.yml | 206 ++++------ contracts/.changeset/itchy-deers-deny.md | 5 + .../slither/.slither.config-artifacts.json | 3 + .../slither/.slither.config-ccip-pr.json | 4 + .../slither/.slither.config-default-pr.json | 4 + .../scripts/ci/generate_slither_report.sh | 87 ++++ contracts/scripts/ci/generate_uml.sh | 121 ++++++ contracts/scripts/ci/modify_remappings.sh | 30 ++ contracts/scripts/ci/select_solc_version.sh | 118 ++++++ contracts/scripts/lcov_prune | 77 ++++ tools/ci/ccip_lcov_prune | 30 -- 18 files changed, 1435 insertions(+), 241 deletions(-) create mode 100644 .github/actions/detect-solidity-foundry-version/action.yml create mode 100644 .github/actions/setup-slither/action.yaml create mode 100644 .github/actions/setup-solc-select/action.yaml create mode 100644 .github/actions/validate-artifact-scope/action.yaml create mode 100644 .github/actions/validate-solidity-artifacts/action.yaml create mode 100644 .github/workflows/solidity-foundry-artifacts.yml create mode 100644 contracts/.changeset/itchy-deers-deny.md create mode 100644 contracts/configs/slither/.slither.config-artifacts.json create mode 100644 contracts/configs/slither/.slither.config-ccip-pr.json create mode 100644 contracts/configs/slither/.slither.config-default-pr.json create mode 100755 contracts/scripts/ci/generate_slither_report.sh create mode 100755 contracts/scripts/ci/generate_uml.sh create mode 100755 contracts/scripts/ci/modify_remappings.sh create mode 100755 contracts/scripts/ci/select_solc_version.sh create mode 100755 contracts/scripts/lcov_prune delete mode 100755 tools/ci/ccip_lcov_prune diff --git a/.github/actions/detect-solidity-foundry-version/action.yml b/.github/actions/detect-solidity-foundry-version/action.yml new file mode 100644 index 0000000000..b37f1e2509 --- /dev/null +++ b/.github/actions/detect-solidity-foundry-version/action.yml @@ -0,0 +1,26 @@ +name: 'Detect Foundry version in GNUmakefile' +description: 'Detects Foundry version in GNUmakefile' +inputs: + working-directory: + description: 'The GNUmakefile directory' + required: false + default: 'contracts' +outputs: + foundry-version: + description: 'Foundry version found in GNUmakefile' + value: ${{ steps.extract-foundry-version.outputs.foundry-version }} +runs: + using: 'composite' + steps: + - name: Extract Foundry version + id: extract-foundry-version + shell: bash + working-directory: ${{ inputs.working-directory }} + run: | + foundry_version=$(grep -Eo "foundryup --version [^ ]+" GNUmakefile | awk '{print $3}') + if [ -z "$foundry_version" ]; then + echo "::error::Foundry version not found in GNUmakefile" + exit 1 + fi + echo "Foundry version found: $foundry_version" + echo "foundry-version=$foundry_version" >> $GITHUB_OUTPUT diff --git a/.github/actions/setup-slither/action.yaml b/.github/actions/setup-slither/action.yaml new file mode 100644 index 0000000000..b8bef38575 --- /dev/null +++ b/.github/actions/setup-slither/action.yaml @@ -0,0 +1,10 @@ +name: Setup Slither +description: Installs Slither 0.10.3 for contract analysis. Requires Python 3.6 or higher. +runs: + using: composite + steps: + - name: Install Slither + shell: bash + run: | + python -m pip install --upgrade pip + pip install slither-analyzer==0.10.3 diff --git a/.github/actions/setup-solc-select/action.yaml b/.github/actions/setup-solc-select/action.yaml new file mode 100644 index 0000000000..b74ffae018 --- /dev/null +++ b/.github/actions/setup-solc-select/action.yaml @@ -0,0 +1,30 @@ +name: Setup Solc Select +description: Installs Solc Select, required versions and selects the version to use. Requires Python 3.6 or higher. +inputs: + to_install: + description: Comma-separated list of solc versions to install + required: true + to_use: + description: Solc version to use + required: true + +runs: + using: composite + steps: + - name: Install solc-select and solc + shell: bash + run: | + pip3 install solc-select + sudo ln -s /usr/local/bin/solc-select /usr/bin/solc-select + + IFS=',' read -ra versions <<< "${{ inputs.to_install }}" + for version in "${versions[@]}"; do + solc-select install $version + if [ $? -ne 0 ]; then + echo "Failed to install Solc $version" + exit 1 + fi + done + + solc-select install ${{ inputs.to_use }} + solc-select use ${{ inputs.to_use }} diff --git a/.github/actions/validate-artifact-scope/action.yaml b/.github/actions/validate-artifact-scope/action.yaml new file mode 100644 index 0000000000..7440efc63a --- /dev/null +++ b/.github/actions/validate-artifact-scope/action.yaml @@ -0,0 +1,103 @@ +name: Validate Artifact Scope +description: Checks there are any modified Solidity files outside of the specified scope. If so, it prints a warning message, but does not fail the workflow. +inputs: + product: + description: The product for which the artifacts are being generated + required: true + sol_files: + description: Comma-separated (CSV) or space-separated (shell) list of Solidity files to check + required: true + +runs: + using: composite + steps: + - name: Transform input array + id: transform_input_array + shell: bash + run: | + is_csv_format() { + local input="$1" + if [[ "$input" =~ "," ]]; then + return 0 + else + return 1 + fi + } + + is_space_separated_string() { + local input="$1" + if [[ "$input" =~ ^[^[:space:]]+([[:space:]][^[:space:]]+)*$ ]]; then + return 0 + else + return 1 + fi + } + + array="${{ inputs.sol_files }}" + + if is_csv_format "$array"; then + echo "::debug::CSV format detected, nothing to do" + echo "sol_files=$array" >> $GITHUB_OUTPUT + exit 0 + fi + + if is_space_separated_string "$array"; then + echo "::debug::Space-separated format detected, converting to CSV" + csv_array="${array// /,}" + echo "sol_files=$csv_array" >> $GITHUB_OUTPUT + exit 0 + fi + + echo "::error::Invalid input format for sol_files. Please provide a comma-separated (CSV) or space-separated (shell) list of Solidity files" + exit 1 + + - name: Check for changes outside of artifact scope + shell: bash + run: | + echo "::debug::All modified contracts:" + echo "${{ steps.transform_input_array.outputs.sol_files }}" | tr ',' '\n' + if [ "${{ inputs.product }}" = "shared" ]; then + excluded_paths_pattern="!/^contracts\/src\/v0\.8\/interfaces/ && !/^contracts\/src\/v0\.8\/${{ inputs.product }}/ && !/^contracts\/src\/v0\.8\/[^\/]+\.sol$/" + else + excluded_paths_pattern="!/^contracts\/src\/v0\.8\/${{ inputs.product }}/" + fi + echo "::debug::Excluded paths: $excluded_paths_pattern" + unexpected_files=$(echo "${{ steps.transform_input_array.outputs.sol_files }}" | tr ',' '\n' | awk "$excluded_paths_pattern") + missing_files="" + set -e + set -o pipefail + if [[ -n "$unexpected_files" ]]; then + products=() + productsStr="" + IFS=$'\n' read -r -d '' -a files <<< "$unexpected_files" || true + echo "Files: ${files[@]}" + + for file in "${files[@]}"; do + missing_files+="$file," + + product=$(echo "$file" | awk -F'src/v0.8/' '{if ($2 ~ /\//) print substr($2, 1, index($2, "/")-1); else print "shared"}') + if [[ ! " ${products[@]} " =~ " ${product} " ]]; then + products+=("$product") + productsStr+="$product, " + fi + done + productsStr=${productsStr%, } + + set +e + set +o pipefail + + missing_files=$(echo $missing_files | tr ',' '\n') + + echo "Error: Found modified contracts outside of the expected scope: ${{ inputs.product }}" + echo "Files:" + echo "$missing_files" + echo "Action required: If you want to generate artifacts for other products ($productsStr) run this workflow again with updated configuration" + + echo "# Warning!" >> $GITHUB_STEP_SUMMARY + echo "## Reason: Found modified contracts outside of the expected scope: ${{ inputs.product }}" >> $GITHUB_STEP_SUMMARY + echo "### Files:" >> $GITHUB_STEP_SUMMARY + echo "$missing_files" >> $GITHUB_STEP_SUMMARY + echo "## Action required: If you want to generate artifacts for other products ($productsStr) run this workflow again with updated configuration" >> $GITHUB_STEP_SUMMARY + else + echo "No unexpected files found." + fi diff --git a/.github/actions/validate-solidity-artifacts/action.yaml b/.github/actions/validate-solidity-artifacts/action.yaml new file mode 100644 index 0000000000..5357a87f96 --- /dev/null +++ b/.github/actions/validate-solidity-artifacts/action.yaml @@ -0,0 +1,115 @@ +name: Validate Solidity Artifacts +description: Checks whether Slither reports and UML diagrams were generated for all necessary files. If not, a warning is printed in job summary, but the job is not marked as failed. +inputs: + slither_reports_path: + description: Path to the Slither reports directory (without trailing slash) + required: true + uml_diagrams_path: + description: Path to the UML diagrams directory (without trailing slash) + required: true + validate_slither_reports: + description: Whether Slither reports should be validated + required: true + validate_uml_diagrams: + description: Whether UML diagrams should be validated + required: true + sol_files: + description: Comma-separated (CSV) or space-separated (shell) list of Solidity files to check + required: true + +runs: + using: composite + steps: + - name: Transform input array + id: transform_input_array + shell: bash + run: | + is_csv_format() { + local input="$1" + if [[ "$input" =~ "," ]]; then + return 0 + else + return 1 + fi + } + + is_space_separated_string() { + local input="$1" + if [[ "$input" =~ ^[^[:space:]]+([[:space:]][^[:space:]]+)*$ ]]; then + return 0 + else + return 1 + fi + } + + array="${{ inputs.sol_files }}" + + if is_csv_format "$array"; then + echo "::debug::CSV format detected, nothing to do" + echo "sol_files=$array" >> $GITHUB_OUTPUT + exit 0 + fi + + if is_space_separated_string "$array"; then + echo "::debug::Space-separated format detected, converting to CSV" + csv_array="${array// /,}" + echo "sol_files=$csv_array" >> $GITHUB_OUTPUT + exit 0 + fi + + echo "::error::Invalid input format for sol_files. Please provide a comma-separated (CSV) or space-separated (shell) list of Solidity files" + exit 1 + + - name: Validate UML diagrams + if: ${{ inputs.validate_uml_diagrams == 'true' }} + shell: bash + run: | + echo "Validating UML diagrams" + IFS=',' read -r -a modified_files <<< "${{ steps.transform_input_array.outputs.sol_files }}" + missing_svgs=() + for file in "${modified_files[@]}"; do + svg_file="$(basename "${file%.sol}").svg" + if [ ! -f "${{ inputs.uml_diagrams_path }}/$svg_file" ]; then + echo "Error: UML diagram for $file not found" + missing_svgs+=("$file") + fi + done + + if [ ${#missing_svgs[@]} -gt 0 ]; then + echo "Error: Missing UML diagrams for files: ${missing_svgs[@]}" + echo "# Warning!" >> $GITHUB_STEP_SUMMARY + echo "## Reason: Missing UML diagrams for files:" >> $GITHUB_STEP_SUMMARY + for file in "${missing_svgs[@]}"; do + echo " $file" >> $GITHUB_STEP_SUMMARY + done + echo "## Action required: Please try to generate artifacts for them locally or using a different tool" >> $GITHUB_STEP_SUMMARY + else + echo "All UML diagrams generated successfully" + fi + + - name: Validate Slither reports + if: ${{ inputs.validate_slither_reports == 'true' }} + shell: bash + run: | + echo "Validating Slither reports" + IFS=',' read -r -a modified_files <<< "${{ steps.transform_input_array.outputs.sol_files }}" + missing_reports=() + for file in "${modified_files[@]}"; do + report_file="$(basename "${file%.sol}")-slither-report.md" + if [ ! -f "${{ inputs.slither_reports_path }}/$report_file" ]; then + echo "Error: Slither report for $file not found" + missing_reports+=("$file") + fi + done + + if [ ${#missing_reports[@]} -gt 0 ]; then + echo "Error: Missing Slither reports for files: ${missing_reports[@]}" + echo "# Warning!" >> $GITHUB_STEP_SUMMARY + echo "## Reason: Missing Slither reports for files:" >> $GITHUB_STEP_SUMMARY + for file in "${missing_reports[@]}"; do + echo " $file" >> $GITHUB_STEP_SUMMARY + done + echo "## Action required: Please try to generate artifacts for them locally" >> $GITHUB_STEP_SUMMARY + else + echo "All Slither reports generated successfully" + fi diff --git a/.github/workflows/solidity-foundry-artifacts.yml b/.github/workflows/solidity-foundry-artifacts.yml new file mode 100644 index 0000000000..e489033d67 --- /dev/null +++ b/.github/workflows/solidity-foundry-artifacts.yml @@ -0,0 +1,371 @@ +name: Solidity Foundry Artifact Generation +on: + workflow_dispatch: + inputs: + product: + type: choice + description: 'product for which to generate artifacts; should be the same as Foundry profile' + required: true + options: + - "automation" + - "ccip" + - "functions" + - "keystone" + - "l2ep" + - "liquiditymanager" + - "llo-feeds" + - "operatorforwarder" + - "shared" + - "transmission" + - "vrf" + base_ref: + description: 'commit or tag to be used as base reference, when looking for modified Solidity files' + required: true + +env: + FOUNDRY_PROFILE: ci + +jobs: + changes: + name: Detect changes + runs-on: ubuntu-latest + outputs: + changes: ${{ steps.changes.outputs.sol }} + product_changes: ${{ steps.changes-transform.outputs.product_changes }} + product_files: ${{ steps.changes-transform.outputs.product_files }} + changeset_changes: ${{ steps.changes-dorny.outputs.changeset }} + changeset_files: ${{ steps.changes-dorny.outputs.changeset_files }} + steps: + - name: Checkout the repo + uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + - name: Find modified contracts + uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 + id: changes + with: + list-files: 'csv' + base: ${{ inputs.base_ref }} + predicate-quantifier: every + filters: | + ignored: &ignored + - '!contracts/src/v0.8/**/test/**' + - '!contracts/src/v0.8/**/tests/**' + - '!contracts/src/v0.8/**/mock/**' + - '!contracts/src/v0.8/**/mocks/**' + - '!contracts/src/v0.8/**/*.t.sol' + - '!contracts/src/v0.8/*.t.sol' + - '!contracts/src/v0.8/**/testhelpers/**' + - '!contracts/src/v0.8/testhelpers/**' + - '!contracts/src/v0.8/vendor/**' + other_shared: + - modified|added: 'contracts/src/v0.8/(interfaces/**/*.sol|*.sol)' + - *ignored + sol: + - modified|added: 'contracts/src/v0.8/**/*.sol' + - *ignored + product: &product + - modified|added: 'contracts/src/v0.8/${{ inputs.product }}/**/*.sol' + - *ignored + changeset: + - modified|added: 'contracts/.changeset/!(README)*.md' + + # Manual transformation needed, because shared contracts have a different folder structure + - name: Transform modified files + id: changes-transform + shell: bash + run: | + if [ "${{ inputs.product }}" = "shared" ]; then + echo "::debug:: Product is shared, transforming changes" + if [[ "${{ steps.changes.outputs.product }}" == "true" && "${{ steps.changes.outputs.other_shared }}" == "true" ]]; then + echo "::debug:: Changes were found in 'shared' folder and in 'interfaces' and root folders" + echo "product_changes=true" >> $GITHUB_OUTPUT + echo "product_files=${{ steps.changes.outputs.product_files }},${{ steps.changes.outputs.other_shared_files }}" >> $GITHUB_OUTPUT + elif [[ "${{ steps.changes.outputs.product }}" == "false" && "${{ steps.changes.outputs.other_shared }}" == "true" ]]; then + echo "::debug:: Only contracts in' interfaces' and root folders were modified" + echo "product_changes=true" >> $GITHUB_OUTPUT + echo "product_files=${{ steps.changes.outputs.other_shared_files }}" >> $GITHUB_OUTPUT + elif [[ "${{ steps.changes.outputs.product }}" == "true" && "${{ steps.changes.outputs.other_shared }}" == "false" ]]; then + echo "::debug:: Only contracts in 'shared' folder were modified" + echo "product_changes=true" >> $GITHUB_OUTPUT + echo "product_files=${{ steps.changes.outputs.product_files }}" >> $GITHUB_OUTPUT + else + echo "::debug:: No contracts were modified" + echo "product_changes=false" >> $GITHUB_OUTPUT + echo "product_files=" >> $GITHUB_OUTPUT + fi + else + echo "product_changes=${{ steps.changes.outputs.product }}" >> $GITHUB_OUTPUT + echo "product_files=${{ steps.changes.outputs.product_files }}" >> $GITHUB_OUTPUT + fi + + - name: Check for changes outside of artifact scope + uses: ./.github/actions/validate-artifact-scope + if: ${{ steps.changes.outputs.sol == 'true' }} + with: + sol_files: ${{ steps.changes.outputs.sol_files }} + product: ${{ inputs.product }} + + gather-basic-info: + name: Gather basic info + if: ${{ needs.changes.outputs.product_changes == 'true' }} + runs-on: ubuntu-22.04 + needs: [ changes ] + outputs: + foundry_version: ${{ steps.extract-foundry-version.outputs.foundry-version }} + steps: + - name: Checkout the repo + uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + with: + fetch-depth: 0 + + - name: Extract Foundry version + uses: ./.github/actions/detect-solidity-foundry-version + with: + working-directory: contracts + + - name: Copy modified changesets + if: ${{ needs.changes.outputs.changeset_changes == 'true' }} + run: | + mkdir -p contracts/changesets + files="${{ needs.changes.outputs.changeset_files }}" + IFS=",' + for changeset in $files; do + echo "::debug:: Copying $changeset" + cp $changeset contracts/changesets + done + + - name: Generate basic info and modified contracts list + shell: bash + run: | + echo "Commit SHA used to generate artifacts: ${{ github.sha }}" > contracts/commit_sha_base_ref.txt + echo "Base reference SHA used to find modified contracts: ${{ inputs.base_ref }}" >> contracts/commit_sha_base_ref.txt + + IFS=',' read -r -a modified_files <<< "${{ needs.changes.outputs.product_files }}" + echo "# Modified contracts:" > contracts/modified_contracts.md + for file in "${modified_files[@]}"; do + echo " - [$file](${{ github.server_url }}/${{ github.repository }}/blob/${{ github.sha }}/$file)" >> contracts/modified_contracts.md + echo "$file" >> contracts/modified_contracts.txt + done + + - name: Upload basic info and modified contracts list + uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4.3.4 + timeout-minutes: 2 + continue-on-error: true + with: + name: tmp-basic-info + path: | + contracts/modified_contracts.md + contracts/modified_contracts.txt + contracts/commit_sha_base_ref.txt + contracts/changesets + retention-days: 7 + + # some of the artifacts can only be generated on product level, and we cannot scope them to single contracts + # some product-level modifications might also require shared contracts changes, so if these happened we need to generate artifacts for shared contracts as well + coverage-and-book: + if: ${{ needs.changes.outputs.product_changes == 'true' }} + name: Generate Docs and Code Coverage reports + runs-on: ubuntu-22.04 + needs: [changes, gather-basic-info] + steps: + - name: Prepare exclusion list + id: prepare-exclusion-list + run: | + cat < coverage_exclusions.json + ["automation", "functions", "vrf"] + EOF + coverage_exclusions=$(cat coverage_exclusions.json | jq -c .) + echo "coverage_exclusions=$coverage_exclusions" >> $GITHUB_OUTPUT + + - name: Checkout the repo + uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + + - name: Setup NodeJS + uses: ./.github/actions/setup-nodejs + + - name: Create directories + shell: bash + run: | + mkdir -p contracts/code-coverage + + - name: Install Foundry + uses: foundry-rs/foundry-toolchain@8f1998e9878d786675189ef566a2e4bf24869773 # v1.2.0 + with: + version: ${{ needs.gather-basic-info.outputs.foundry_version }} + + # required for code coverage report generation + - name: Setup LCOV + uses: hrishikesh-kadam/setup-lcov@f5da1b26b0dcf5d893077a3c4f29cf78079c841d # v1.0.0 + + - name: Run Forge build for product contracts + if: ${{ needs.changes.outputs.product_changes == 'true' }} + run: | + forge --version + forge build + working-directory: contracts + env: + FOUNDRY_PROFILE: ${{ inputs.product }} + + - name: Run coverage for product contracts + if: ${{ !contains(fromJson(steps.prepare-exclusion-list.outputs.coverage_exclusions), inputs.product) && needs.changes.outputs.product_changes == 'true' }} + working-directory: contracts + run: forge coverage --report lcov --report-file code-coverage/lcov.info + env: + FOUNDRY_PROFILE: ${{ inputs.product }} + + - name: Generate Code Coverage HTML report for product contracts + if: ${{ !contains(fromJson(steps.prepare-exclusion-list.outputs.coverage_exclusions), inputs.product) && needs.changes.outputs.product_changes == 'true' }} + shell: bash + working-directory: contracts + run: genhtml code-coverage/lcov.info --branch-coverage --output-directory code-coverage + + - name: Run Forge doc for product contracts + if: ${{ needs.changes.outputs.product_changes == 'true' }} + run: forge doc --build -o docs + working-directory: contracts + env: + FOUNDRY_PROFILE: ${{ inputs.product }} + + - name: Upload Artifacts for product contracts + if: ${{ needs.changes.outputs.product_changes == 'true' }} + uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4.3.4 + timeout-minutes: 2 + continue-on-error: true + with: + name: tmp-${{ inputs.product }}-artifacts + path: | + contracts/docs + contracts/code-coverage/lcov-.info + contracts/code-coverage + retention-days: 7 + + # Generates UML diagrams and Slither reports for modified contracts + uml-static-analysis: + if: ${{ needs.changes.outputs.product_changes == 'true' }} + name: Generate UML and Slither reports for modified contracts + runs-on: ubuntu-22.04 + needs: [changes, gather-basic-info] + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + steps: + - name: Checkout the repo + uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + with: + fetch-depth: 0 + + - name: Setup NodeJS + uses: ./.github/actions/setup-nodejs + + - name: Install Foundry + uses: foundry-rs/foundry-toolchain@8f1998e9878d786675189ef566a2e4bf24869773 # v1.2.0 + with: + version: ${{ needs.gather-basic-info.outputs.foundry_version }} + + - name: Install Sol2uml + run: | + npm link sol2uml --only=production + + - name: Set up Python + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f #v5.1.1 + with: + python-version: '3.8' + + - name: Install solc-select and solc + uses: ./.github/actions/setup-solc-select + with: + to_install: '0.8.19' + to_use: '0.8.19' + + - name: Install Slither + uses: ./.github/actions/setup-slither + + - name: Generate UML + shell: bash + run: | + contract_list="${{ needs.changes.outputs.product_files }}" + + # modify remappings so that solc can find dependencies + ./contracts/scripts/ci/modify_remappings.sh contracts contracts/remappings.txt + mv remappings_modified.txt remappings.txt + + ./contracts/scripts/ci/generate_uml.sh "./" "contracts/uml-diagrams" "$contract_list" + + - name: Generate Slither Markdown reports + run: | + contract_list="${{ needs.changes.outputs.product_files }}" + + echo "::debug::Processing contracts: $contract_list" + ./contracts/scripts/ci/generate_slither_report.sh "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.sha }}/" contracts/configs/slither/.slither.config-artifacts.json "." "$contract_list" "contracts/slither-reports" "--solc-remaps @=contracts/node_modules/@" + + - name: Upload UMLs and Slither reports + uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4.3.4 + timeout-minutes: 10 + continue-on-error: true + with: + name: tmp-contracts-artifacts + path: | + contracts/uml-diagrams + contracts/slither-reports + retention-days: 7 + + - name: Validate if all Slither run for all contracts + uses: ./.github/actions/validate-solidity-artifacts + with: + validate_slither_reports: 'true' + validate_uml_diagrams: 'true' + slither_reports_path: 'contracts/slither-reports' + uml_diagrams_path: 'contracts/uml-diagrams' + sol_files: ${{ needs.changes.outputs.product_files }} + + gather-all-artifacts: + name: Gather all artifacts + if: ${{ needs.changes.outputs.product_changes == 'true' }} + runs-on: ubuntu-latest + needs: [coverage-and-book, uml-static-analysis, gather-basic-info, changes] + steps: + - name: Download all artifacts + uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 + with: + path: review_artifacts + merge-multiple: true + + - name: Upload all artifacts as single package + uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4.3.4 + with: + name: review-artifacts-${{ inputs.product }}-${{ github.sha }} + path: review_artifacts + retention-days: 60 + + - name: Remove temporary artifacts + uses: geekyeggo/delete-artifact@24928e75e6e6590170563b8ddae9fac674508aa1 # v5.0 + with: + name: tmp-* + + - name: Print Artifact URL in job summary + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + ARTIFACTS=$(gh api -X GET repos/${{ github.repository }}/actions/runs/${{ github.run_id }}/artifacts) + ARTIFACT_ID=$(echo "$ARTIFACTS" | jq '.artifacts[] | select(.name=="review-artifacts-${{ inputs.product }}-${{ github.sha }}") | .id') + echo "Artifact ID: $ARTIFACT_ID" + + echo "# Solidity Review Artifact Generated" >> $GITHUB_STEP_SUMMARY + echo "Base Ref used: **${{ inputs.base_ref }}**" >> $GITHUB_STEP_SUMMARY + echo "Commit SHA used: **${{ github.sha }}**" >> $GITHUB_STEP_SUMMARY + echo "[Artifact URL](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}/artifacts/$ARTIFACT_ID)" >> $GITHUB_STEP_SUMMARY + + notify-no-changes: + if: ${{ needs.changes.outputs.product_changes == 'false' }} + needs: [changes] + runs-on: ubuntu-latest + steps: + - name: Print warning in job summary + shell: bash + run: | + echo "# Solidity Review Artifact NOT Generated" >> $GITHUB_STEP_SUMMARY + echo "Base Ref used: **${{ inputs.base_ref }}**" >> $GITHUB_STEP_SUMMARY + echo "Commit SHA used: **${{ github.sha }}**" >> $GITHUB_STEP_SUMMARY + echo "## Reason: No modified Solidity files found for ${{ inputs.product }}" >> $GITHUB_STEP_SUMMARY + echo "* no modified Solidity files found between ${{ inputs.base_ref }} and ${{ github.sha }} commits" >> $GITHUB_STEP_SUMMARY + echo "* or they are located outside of ./contracts/src/v0.8 folder" >> $GITHUB_STEP_SUMMARY + echo "* or they were limited to test files" >> $GITHUB_STEP_SUMMARY + exit 1 diff --git a/.github/workflows/solidity-foundry.yml b/.github/workflows/solidity-foundry.yml index e43a4c1320..906cb76ffe 100644 --- a/.github/workflows/solidity-foundry.yml +++ b/.github/workflows/solidity-foundry.yml @@ -3,42 +3,122 @@ on: [pull_request] env: FOUNDRY_PROFILE: ci - # Has to match the `make foundry` version in `contracts/GNUmakefile` - FOUNDRY_VERSION: nightly-de33b6af53005037b463318d2628b5cfcaf39916 + +# Making changes: +# * use the top-level matrix to decide, which checks should run for each product. +# * when enabling code coverage, remember to adjust the minimum code coverage as it's set to 98.5% by default. jobs: + define-matrix: + name: Define test matrix + runs-on: ubuntu-latest + outputs: + matrix: ${{ steps.define-matrix.outputs.matrix }} + foundry-version: ${{ steps.extract-foundry-version.outputs.foundry-version }} + steps: + - name: Define test matrix + id: define-matrix + shell: bash + run: | + cat < matrix.json + [ + { "name": "automation", "setup": { "run-coverage": false, "min-coverage": 98.5, "run-gas-snapshot": false, "run-forge-fmt": false }}, + { "name": "ccip", "setup": { "run-coverage": true, "min-coverage": 98.5, "run-gas-snapshot": true, "run-forge-fmt": true }}, + { "name": "functions", "setup": { "run-coverage": false, "min-coverage": 98.5, "run-gas-snapshot": true, "run-forge-fmt": false }}, + { "name": "keystone", "setup": { "run-coverage": true, "min-coverage": 74.1, "run-gas-snapshot": false, "run-forge-fmt": false }}, + { "name": "l2ep", "setup": { "run-coverage": true, "min-coverage": 65.6, "run-gas-snapshot": true, "run-forge-fmt": false }}, + { "name": "liquiditymanager", "setup": { "run-coverage": true, "min-coverage": 46.3, "run-gas-snapshot": true, "run-forge-fmt": false }}, + { "name": "llo-feeds", "setup": { "run-coverage": true, "min-coverage": 49.3, "run-gas-snapshot": true, "run-forge-fmt": false }}, + { "name": "operatorforwarder", "setup": { "run-coverage": true, "min-coverage": 55.7, "run-gas-snapshot": true, "run-forge-fmt": false }}, + { "name": "shared", "setup": { "run-coverage": true, "min-coverage": 32.6, "run-gas-snapshot": true, "run-forge-fmt": false }}, + { "name": "transmission", "setup": { "run-coverage": true, "min-coverage": 65.6, "run-gas-snapshot": true, "run-forge-fmt": false }}, + { "name": "vrf", "setup": { "run-coverage": false, "min-coverage": 98.5, "run-gas-snapshot": false, "run-forge-fmt": false }} + ] + EOF + + matrix=$(cat matrix.json | jq -c .) + echo "matrix=$matrix" >> $GITHUB_OUTPUT + + - name: Checkout the repo + uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + + - name: Extract Foundry version + id: extract-foundry-version + uses: ./.github/actions/detect-solidity-foundry-version + with: + working-directory: contracts + changes: name: Detect changes runs-on: ubuntu-latest outputs: - changes: ${{ steps.changes.outputs.src }} + non_src_changes: ${{ steps.changes.outputs.non_src }} + sol_modified: ${{ steps.changes.outputs.sol }} + sol_modified_files: ${{ steps.changes.outputs.sol_files }} + not_test_sol_modified: ${{ steps.changes.outputs.not_test_sol }} + not_test_sol_modified_files: ${{ steps.changes.outputs.not_test_sol_files }} + all_changes: ${{ steps.changes.outputs.changes }} steps: - name: Checkout the repo uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 id: changes with: + list-files: 'shell' filters: | - src: - - 'contracts/src/v0.8/**/*' + non_src: - '.github/workflows/solidity-foundry.yml' - 'contracts/foundry.toml' - 'contracts/gas-snapshots/*.gas-snapshot' + - 'contracts/package.json' + sol: + - modified|added: 'contracts/src/v0.8/**/*.sol' + not_test_sol: + - modified|added: 'contracts/src/v0.8/**/!(*.t).sol' + automation: + - 'contracts/src/v0.8/automation/**/*.sol' + ccip: + - 'contracts/src/v0.8/ccip/**/*.sol' + functions: + - 'contracts/src/v0.8/functions/**/*.sol' + keystone: + - 'contracts/src/v0.8/keystone/**/*.sol' + l2ep: + - 'contracts/src/v0.8/l2ep/**/*.sol' + liquiditymanager: + - 'contracts/src/v0.8/liquiditymanager/**/*.sol' + llo-feeds: + - 'contracts/src/v0.8/llo-feeds/**/*.sol' + operatorforwarder: + - 'contracts/src/v0.8/operatorforwarder/**/*.sol' + vrf: + - 'contracts/src/v0.8/vrf/**/*.sol' + shared: + - 'contracts/src/v0.8/shared/**/*.sol' + - 'contracts/src/v0.8/*.sol' + - 'contracts/src/v0.8/mocks/**/*.sol' + - 'contracts/src/v0.8/tests/**/*.sol' + - 'contracts/src/v0.8/vendor/**/*.sol' + transmission: + - 'contracts/src/v0.8/transmission/**/*.sol' tests: + if: ${{ needs.changes.outputs.non_src_changes == 'true' || needs.changes.outputs.sol_modified == 'true' }} strategy: fail-fast: false matrix: - product: [automation, functions, keystone, l2ep, llo-feeds, operatorforwarder, shared, vrf, ccip, liquiditymanager] - needs: [changes] - name: Foundry Tests ${{ matrix.product }} - # See https://github.com/foundry-rs/foundry/issues/3827 + product: ${{fromJson(needs.define-matrix.outputs.matrix)}} + needs: [define-matrix, changes] + name: Foundry Tests ${{ matrix.product.name }} runs-on: ubuntu-22.04 # The if statements for steps after checkout repo is workaround for # passing required check for PRs that don't have filtered changes. steps: - name: Checkout the repo + if: ${{ contains(fromJson(needs.changes.outputs.all_changes), matrix.product.name) + || contains(fromJson(needs.changes.outputs.all_changes), 'shared') + || needs.changes.outputs.non_src_changes == 'true' }} uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 with: submodules: recursive @@ -47,169 +127,241 @@ jobs: # and not native Foundry. This is to make sure the dependencies # stay in sync. - name: Setup NodeJS - if: needs.changes.outputs.changes == 'true' + if: ${{ contains(fromJson(needs.changes.outputs.all_changes), matrix.product.name) + || contains(fromJson(needs.changes.outputs.all_changes), 'shared') + || needs.changes.outputs.non_src_changes == 'true' }} uses: ./.github/actions/setup-nodejs - name: Install Foundry - if: needs.changes.outputs.changes == 'true' + if: ${{ contains(fromJson(needs.changes.outputs.all_changes), matrix.product.name) + || contains(fromJson(needs.changes.outputs.all_changes), 'shared') + || needs.changes.outputs.non_src_changes == 'true' }} uses: foundry-rs/foundry-toolchain@8f1998e9878d786675189ef566a2e4bf24869773 # v1.2.0 with: - version: ${{ env.FOUNDRY_VERSION }} + version: ${{ needs.define-matrix.outputs.foundry-version }} - name: Run Forge build - if: needs.changes.outputs.changes == 'true' + if: ${{ contains(fromJson(needs.changes.outputs.all_changes), matrix.product.name) + || contains(fromJson(needs.changes.outputs.all_changes), 'shared') + || needs.changes.outputs.non_src_changes == 'true' }} run: | forge --version forge build id: build working-directory: contracts env: - FOUNDRY_PROFILE: ${{ matrix.product }} + FOUNDRY_PROFILE: ${{ matrix.product.name }} - name: Run Forge tests - if: needs.changes.outputs.changes == 'true' + if: ${{ contains(fromJson(needs.changes.outputs.all_changes), matrix.product.name) + || contains(fromJson(needs.changes.outputs.all_changes), 'shared') + || needs.changes.outputs.non_src_changes == 'true' }} run: | forge test -vvv id: test working-directory: contracts env: - FOUNDRY_PROFILE: ${{ matrix.product }} + FOUNDRY_PROFILE: ${{ matrix.product.name }} - name: Run Forge snapshot - if: ${{ !contains(fromJson('["vrf"]'), matrix.product) && !contains(fromJson('["automation"]'), matrix.product) && !contains(fromJson('["keystone"]'), matrix.product) && needs.changes.outputs.changes == 'true' }} + if: ${{ (contains(fromJson(needs.changes.outputs.all_changes), matrix.product.name) + || contains(fromJson(needs.changes.outputs.all_changes), 'shared') + || needs.changes.outputs.non_src_changes == 'true') + && matrix.product.setup.run-gas-snapshot }} run: | - forge snapshot --nmt "test_?Fuzz_\w{1,}?" --check gas-snapshots/${{ matrix.product }}.gas-snapshot + forge snapshot --nmt "test_?Fuzz_\w{1,}?" --check gas-snapshots/${{ matrix.product.name }}.gas-snapshot id: snapshot working-directory: contracts env: - FOUNDRY_PROFILE: ${{ matrix.product }} + FOUNDRY_PROFILE: ${{ matrix.product.name }} - - name: Collect Metrics - if: needs.changes.outputs.changes == 'true' - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 - with: - id: solidity-foundry - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: Foundry Tests ${{ matrix.product }} - continue-on-error: true + # required for code coverage report generation + - name: Setup LCOV + if: ${{ (contains(fromJson(needs.changes.outputs.all_changes), matrix.product.name) + || contains(fromJson(needs.changes.outputs.all_changes), 'shared') + || needs.changes.outputs.non_src_changes == 'true') + && matrix.product.setup.run-coverage }} + uses: hrishikesh-kadam/setup-lcov@f5da1b26b0dcf5d893077a3c4f29cf78079c841d # v1.0.0 - coverage: - needs: [changes] - name: Coverage - runs-on: ubuntu-latest - env: - FOUNDRY_PROFILE: ccip + - name: Run coverage for ${{ matrix.product.name }} + if: ${{ (contains(fromJson(needs.changes.outputs.all_changes), matrix.product.name) + || contains(fromJson(needs.changes.outputs.all_changes), 'shared') + || needs.changes.outputs.non_src_changes == 'true') + && matrix.product.setup.run-coverage }} + working-directory: contracts + run: forge coverage --report lcov + env: + FOUNDRY_PROFILE: ${{ matrix.product.name }} + + - name: Prune lcov report + if: ${{ (contains(fromJson(needs.changes.outputs.all_changes), matrix.product.name) + || contains(fromJson(needs.changes.outputs.all_changes), 'shared') + || needs.changes.outputs.non_src_changes == 'true') + && matrix.product.setup.run-coverage }} + run: | + sudo apt-get install lcov + ./contracts/scripts/lcov_prune ${{ matrix.product.name }} ./contracts/lcov.info ./contracts/lcov.info.pruned + + - name: Report code coverage for ${{ matrix.product.name }} + if: ${{ (contains(fromJson(needs.changes.outputs.all_changes), matrix.product.name) + || contains(fromJson(needs.changes.outputs.all_changes), 'shared') + || needs.changes.outputs.non_src_changes == 'true') + && matrix.product.setup.run-coverage }} + uses: zgosalvez/github-actions-report-lcov@a546f89a65a0cdcd82a92ae8d65e74d450ff3fbc # v4.1.4 + with: + update-comment: false + coverage-files: ./contracts/lcov.info.pruned + minimum-coverage: ${{ matrix.product.min-coverage }} + artifact-name: code-coverage-report-${{ matrix.product.name }} + working-directory: ./contracts - steps: - name: Collect Metrics - if: ${{ needs.changes.outputs.changes == 'true' }} + if: ${{ contains(fromJson(needs.changes.outputs.all_changes), matrix.product.name) + || contains(fromJson(needs.changes.outputs.all_changes), 'shared') + || needs.changes.outputs.non_src_changes == 'true' }} id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@dea9b546553cb4ca936607c2267a09c004e4ab3f # v3.0.0 + uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 with: - id: ccip-solidity-foundry-coverage + id: ${{ matrix.product.name }}-solidity-foundry org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: Coverage + this-job-name: Foundry Tests ${{ matrix.product.name }} continue-on-error: true - - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + analyze: + needs: [ changes, define-matrix ] + name: Run static analysis + if: needs.changes.outputs.not_test_sol_modified == 'true' + runs-on: ubuntu-22.04 + steps: + - name: Checkout the repo + uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 with: submodules: recursive - # Only needed because we use the NPM versions of packages - # and not native Foundry. This is to make sure the dependencies - # stay in sync. - name: Setup NodeJS uses: ./.github/actions/setup-nodejs - name: Install Foundry - if: needs.changes.outputs.changes == 'true' uses: foundry-rs/foundry-toolchain@8f1998e9878d786675189ef566a2e4bf24869773 # v1.2.0 with: - version: ${{ env.FOUNDRY_VERSION }} + version: ${{ needs.define-matrix.outputs.foundry-version }} - - name: Run Forge build - if: ${{ needs.changes.outputs.changes == 'true' }} - working-directory: contracts - run: | - forge --version - forge build - id: build + - name: Set up Python + uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f #v5.1.1 + with: + python-version: '3.8' - - name: Run coverage - if: ${{ needs.changes.outputs.changes == 'true' }} - working-directory: contracts - run: forge coverage --report lcov + - name: Install solc-select and solc + uses: ./.github/actions/setup-solc-select + with: + to_install: '0.8.19' + to_use: '0.8.19' + + - name: Install Slither + uses: ./.github/actions/setup-slither + + - name: Run Slither + shell: bash + run: | + # modify remappings so that solc can find dependencies + ./contracts/scripts/ci/modify_remappings.sh contracts contracts/remappings.txt + mv remappings_modified.txt remappings.txt + + FILES="${{ needs.changes.outputs.not_test_sol_modified_files }}" + + for FILE in $FILES; do + PRODUCT=$(echo "$FILE" | awk -F'src/[^/]*/' '{print $2}' | cut -d'/' -f1) + echo "::debug::Running Slither for $FILE in $PRODUCT" + SLITHER_CONFIG="contracts/configs/slither/.slither.config-$PRODUCT-pr.json" + if [ ! -f $SLITHER_CONFIG ]; then + echo "::debug::No Slither config found for $PRODUCT, using default" + SLITHER_CONFIG="contracts/configs/slither/.slither.config-default-pr.json" + fi + ./contracts/scripts/ci/generate_slither_report.sh "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.sha }}/" "$SLITHER_CONFIG" "." "$FILE" "contracts/slither-reports" "--solc-remaps @=contracts/node_modules/@" + done - - name: Prune report - if: ${{ needs.changes.outputs.changes == 'true' }} + - name: Print Slither summary + shell: bash run: | - sudo apt-get install lcov - ./tools/ci/ccip_lcov_prune ./contracts/lcov.info ./lcov.info.pruned + echo "# Static analysis results " >> $GITHUB_STEP_SUMMARY + for file in "contracts/slither-reports"/*.md; do + if [ -e "$file" ]; then + cat "$file" >> $GITHUB_STEP_SUMMARY + fi + done - - name: Report code coverage - if: ${{ needs.changes.outputs.changes == 'true' }} - uses: zgosalvez/github-actions-report-lcov@a546f89a65a0cdcd82a92ae8d65e74d450ff3fbc # v4.1.4 + - name: Validate if all Slither run for all contracts + uses: ./.github/actions/validate-solidity-artifacts with: - update-comment: true - coverage-files: lcov.info.pruned - minimum-coverage: 98.5 - artifact-name: code-coverage-report - working-directory: ./contracts - github-token: ${{ secrets.GITHUB_TOKEN }} + validate_slither_reports: 'true' + slither_reports_path: 'contracts/slither-reports' + sol_files: ${{ needs.changes.outputs.not_test_sol_modified_files }} - fmt: + - name: Upload Slither report + uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4.3.4 + timeout-minutes: 10 + continue-on-error: true + with: + name: slither-reports-${{ github.sha }} + path: | + contracts/slither-reports + retention-days: 7 + + - name: Collect Metrics + id: collect-gha-metrics + uses: smartcontractkit/push-gha-metrics-action@dea9b546553cb4ca936607c2267a09c004e4ab3f # v3.0.0 + with: + id: solidity-foundry-slither + org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} + basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} + hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} + this-job-name: Run static analysis + continue-on-error: true + + solidity-forge-fmt: + name: Forge fmt ${{ matrix.product.name }} + if: ${{ needs.changes.outputs.non_src_changes == 'true' || needs.changes.outputs.not_test_sol_modified == 'true' }} + needs: [define-matrix, changes] strategy: fail-fast: false matrix: - product: [ ccip ] - needs: [ changes ] - name: Forge fmt ${{ matrix.product }} - # See https://github.com/foundry-rs/foundry/issues/3827 + product: ${{fromJson(needs.define-matrix.outputs.matrix)}} runs-on: ubuntu-22.04 - - # The if statements for steps after checkout repo is workaround for - # passing required check for PRs that don't have filtered changes. steps: - name: Checkout the repo + if: ${{ contains(fromJson(needs.changes.outputs.all_changes), matrix.product.name) && matrix.product.setup.run-forge-fmt }} uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 with: submodules: recursive - # Only needed because we use the NPM versions of packages - # and not native Foundry. This is to make sure the dependencies - # stay in sync. - name: Setup NodeJS - if: needs.changes.outputs.changes == 'true' + if: ${{ contains(fromJson(needs.changes.outputs.all_changes), matrix.product.name) && matrix.product.setup.run-forge-fmt }} uses: ./.github/actions/setup-nodejs - name: Install Foundry - if: needs.changes.outputs.changes == 'true' + if: ${{ contains(fromJson(needs.changes.outputs.all_changes), matrix.product.name) && matrix.product.setup.run-forge-fmt }} uses: foundry-rs/foundry-toolchain@8f1998e9878d786675189ef566a2e4bf24869773 # v1.2.0 with: - version: ${{ env.FOUNDRY_VERSION }} + version: ${{ needs.define-matrix.outputs.foundry-version }} - name: Run Forge fmt - if: needs.changes.outputs.changes == 'true' - run: | - forge fmt --check + if: ${{ contains(fromJson(needs.changes.outputs.all_changes), matrix.product.name) && matrix.product.setup.run-forge-fmt }} + run: forge fmt --check id: fmt working-directory: contracts env: - FOUNDRY_PROFILE: ${{ matrix.product }} + FOUNDRY_PROFILE: ${{ matrix.product.name }} - name: Collect Metrics - if: needs.changes.outputs.changes == 'true' + if: ${{ contains(fromJson(needs.changes.outputs.all_changes), matrix.product.name) && matrix.product.setup.run-forge-fmt }} id: collect-gha-metrics uses: smartcontractkit/push-gha-metrics-action@dea9b546553cb4ca936607c2267a09c004e4ab3f # v3.0.0 with: - id: ccip-solidity-foundry-fmt + id: solidity-forge-fmt-${{ matrix.product.name }} org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: Foundry Tests ${{ matrix.product }} + this-job-name: Forge fmt ${{ matrix.product.name }} continue-on-error: true diff --git a/.github/workflows/solidity-hardhat.yml b/.github/workflows/solidity-hardhat.yml index 42d47d519e..705fad3be6 100644 --- a/.github/workflows/solidity-hardhat.yml +++ b/.github/workflows/solidity-hardhat.yml @@ -1,119 +1,87 @@ -#name: Solidity-Hardhat -# -#on: -# merge_group: -# push: -# -#env: -# NODE_OPTIONS: --max_old_space_size=8192 -# -#defaults: -# run: -# shell: bash -# -#jobs: -# changes: -# name: Detect changes -# runs-on: ubuntu-latest -# outputs: -# changes: ${{ steps.changes.outputs.src }} -# steps: -# - name: Checkout the repo -# uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 -# - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 -# id: changes -# with: -# filters: | -# src: -# - 'contracts/src/!(v0.8/(llo-feeds|keystone|ccip|liquiditymanager|functions|transmission)/**)/**/*' -# - 'contracts/test/**/*' -# - 'contracts/package.json' -# - 'contracts/pnpm-lock.yaml' -# - 'contracts/hardhat.config.ts' -# - 'contracts/ci.json' -# - '.github/workflows/solidity-hardhat.yml' -# -# split-tests: -# name: Split Solidity Tests -# runs-on: ubuntu-latest -# outputs: -# splits: ${{ steps.split.outputs.splits }} -# steps: -# - name: Checkout the repo -# uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 -# - name: Generate splits -# id: split -# uses: ./.github/actions/split-tests -# with: -# config: ./contracts/ci.json -# - name: Collect Metrics -# id: collect-gha-metrics -# uses: smartcontractkit/push-gha-metrics-action@dea9b546553cb4ca936607c2267a09c004e4ab3f # v3.0.0 -# with: -# id: solidity-split-tests -# org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} -# basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} -# hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} -# this-job-name: Split Solidity Tests -# continue-on-error: true -# -# solidity-splits: -# needs: [changes, split-tests] -# if: needs.changes.outputs.changes == 'true' -# name: Solidity ${{ matrix.split.id }} ${{ fromJSON('["(skipped)", ""]')[needs.changes.outputs.changes == 'true'] }} -# strategy: -# fail-fast: false -# matrix: -# split: ${{ fromJson(needs.split-tests.outputs.splits) }} -# runs-on: ubuntu-latest -# steps: -# - name: Checkout the repo -# uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 -# - name: Setup NodeJS -# uses: ./.github/actions/setup-nodejs -# - name: Setup Hardhat -# uses: ./.github/actions/setup-hardhat -# with: -# namespace: coverage -# - name: Run tests -# env: -# SPLIT: ${{ matrix.split.tests }} -# working-directory: contracts -# run: pnpm test -- $SPLIT -# - name: Collect Metrics -# id: collect-gha-metrics -# uses: smartcontractkit/push-gha-metrics-action@dea9b546553cb4ca936607c2267a09c004e4ab3f # v3.0.0 -# with: -# id: solidity-splits -# org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} -# basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} -# hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} -# this-job-name: Solidity ${{ matrix.split.id }} -# continue-on-error: true -# -# solidity: -# needs: [changes, solidity-splits] -# name: Solidity -# runs-on: ubuntu-latest -# if: always() -# steps: -# - run: echo 'Solidity tests finished!' -# - name: Check test results -# run: | -# if [[ "${{ needs.changes.result }}" = "failure" || "${{ needs.solidity-splits.result }}" = "failure" ]]; then -# echo "One or more changes / solidity-splits jobs failed" -# exit 1 -# else -# echo "All test jobs passed successfully" -# fi -# - name: Collect Metrics -# if: always() -# id: collect-gha-metrics -# uses: smartcontractkit/push-gha-metrics-action@dea9b546553cb4ca936607c2267a09c004e4ab3f # v3.0.0 -# with: -# id: solidity-tests -# org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} -# basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} -# hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} -# this-job-name: Solidity -# continue-on-error: true +name: Solidity-Hardhat + +on: + merge_group: + push: + +env: + NODE_OPTIONS: --max_old_space_size=8192 + +defaults: + run: + shell: bash + +jobs: + changes: + name: Detect changes + runs-on: ubuntu-latest + outputs: + changes: ${{ steps.changes.outputs.src }} + steps: + - name: Checkout the repo + uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 + id: changes + with: + filters: | + src: + - 'contracts/src/!(v0.8/(ccip|functions|keystone|l2ep|liquiditymanager|llo-feeds|transmission|vrf)/**)/**/*' + - 'contracts/test/**/*' + - 'contracts/package.json' + - 'contracts/pnpm-lock.yaml' + - 'contracts/hardhat.config.ts' + - '.github/workflows/solidity-hardhat.yml' + + hardhat-test: + needs: [changes] + if: needs.changes.outputs.changes == 'true' + name: Solidity ${{ fromJSON('["(skipped)", ""]')[needs.changes.outputs.changes == 'true'] }} + runs-on: ubuntu-latest + steps: + - name: Checkout the repo + uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + - name: Setup NodeJS + uses: ./.github/actions/setup-nodejs + - name: Setup Hardhat + uses: ./.github/actions/setup-hardhat + with: + namespace: coverage + - name: Run tests + working-directory: contracts + run: pnpm test + - name: Collect Metrics + id: collect-gha-metrics + uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 + with: + id: hardhat-test + org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} + basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} + hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} + continue-on-error: true + + solidity: + needs: [changes, hardhat-test] + name: Solidity + runs-on: ubuntu-latest + if: always() + steps: + - run: echo 'Solidity tests finished!' + - name: Check test results + run: | + if [[ "${{ needs.changes.result }}" = "failure" || "${{ needs.solidity-splits.result }}" = "failure" ]]; then + echo "One or more changes / solidity-splits jobs failed" + exit 1 + else + echo "All test jobs passed successfully" + fi + - name: Collect Metrics + if: always() + id: collect-gha-metrics + uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 + with: + id: solidity-tests + org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} + basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} + hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} + this-job-name: Solidity + continue-on-error: true diff --git a/contracts/.changeset/itchy-deers-deny.md b/contracts/.changeset/itchy-deers-deny.md new file mode 100644 index 0000000000..888d58ce31 --- /dev/null +++ b/contracts/.changeset/itchy-deers-deny.md @@ -0,0 +1,5 @@ +--- +"@chainlink/contracts": patch +--- + +More comprehensive & product-scoped Solidity Foundry pipeline diff --git a/contracts/configs/slither/.slither.config-artifacts.json b/contracts/configs/slither/.slither.config-artifacts.json new file mode 100644 index 0000000000..75071341f5 --- /dev/null +++ b/contracts/configs/slither/.slither.config-artifacts.json @@ -0,0 +1,3 @@ +{ + "filter_paths": "(openzeppelin|mocks/|test/|tests/|testhelpers)" +} diff --git a/contracts/configs/slither/.slither.config-ccip-pr.json b/contracts/configs/slither/.slither.config-ccip-pr.json new file mode 100644 index 0000000000..84d231ea07 --- /dev/null +++ b/contracts/configs/slither/.slither.config-ccip-pr.json @@ -0,0 +1,4 @@ +{ + "filter_paths": "(openzeppelin|mocks/|test/|tests/|testhelpers)", + "detectors_to_exclude": "pragma,solc-version,naming-convention,assembly,reentrancy-events,timestamp,calls-loop,unused-return" +} diff --git a/contracts/configs/slither/.slither.config-default-pr.json b/contracts/configs/slither/.slither.config-default-pr.json new file mode 100644 index 0000000000..1ef145a795 --- /dev/null +++ b/contracts/configs/slither/.slither.config-default-pr.json @@ -0,0 +1,4 @@ +{ + "filter_paths": "(openzeppelin|mocks/|test/|tests/|testhelpers)", + "detectors_to_exclude": "pragma" +} diff --git a/contracts/scripts/ci/generate_slither_report.sh b/contracts/scripts/ci/generate_slither_report.sh new file mode 100755 index 0000000000..7fe31d40ef --- /dev/null +++ b/contracts/scripts/ci/generate_slither_report.sh @@ -0,0 +1,87 @@ +#!/usr/bin/env bash + +set -euo pipefail + +function check_chainlink_dir() { + local param_dir="chainlink" + current_dir=$(pwd) + + current_base=$(basename "$current_dir") + + if [[ "$current_base" != "$param_dir" ]]; then + >&2 echo "The script must be run from the root of $param_dir directory" + exit 1 + fi +} + +check_chainlink_dir + +if [ "$#" -lt 5 ]; then + >&2 echo "Generates Markdown Slither reports and saves them to a target directory." + >&2 echo "Usage: $0 [slither extra params]" + exit 1 +fi + +REPO_URL=$1 +CONFIG_FILE=$2 +SOURCE_DIR=$3 +FILES=${4// /} # Remove any spaces from the list of files +TARGET_DIR=$5 +SLITHER_EXTRA_PARAMS=$6 + +run_slither() { + local FILE=$1 + local TARGET_DIR=$2 + + if [[ ! -f "$FILE" ]]; then + >&2 echo "::error:File not found: $FILE" + return 1 + fi + + set +e + source ./contracts/scripts/ci/select_solc_version.sh "$FILE" + if [[ $? -ne 0 ]]; then + >&2 echo "::error::Failed to select Solc version for $FILE" + return 1 + fi + set -e + + SLITHER_OUTPUT_FILE="$TARGET_DIR/$(basename "${FILE%.sol}")-slither-report.md" + + output=$(slither --config-file "$CONFIG_FILE" "$FILE" --checklist --markdown-root "$REPO_URL" --fail-none $SLITHER_EXTRA_PARAMS) + if [ $? -ne 0 ]; then + >&2 echo "::error::Slither failed for $FILE" + exit 1 + fi + output=$(echo "$output" | sed '/\*\*THIS CHECKLIST IS NOT COMPLETE\*\*. Use `--show-ignored-findings` to show all the results./d' | sed '/Summary/d') + + echo "# Summary for $FILE" > "$SLITHER_OUTPUT_FILE" + echo "$output" >> "$SLITHER_OUTPUT_FILE" + + if [[ -z "$output" ]]; then + echo "No issues found." >> "$SLITHER_OUTPUT_FILE" + fi +} + +process_files() { + local SOURCE_DIR=$1 + local TARGET_DIR=$2 + local FILES=(${3//,/ }) # Split the comma-separated list into an array + + mkdir -p "$TARGET_DIR" + + for FILE in "${FILES[@]}"; do + FILE=${FILE//\"/} + run_slither "$SOURCE_DIR/$FILE" "$TARGET_DIR" + done +} + +set +e +process_files "$SOURCE_DIR" "$TARGET_DIR" "${FILES[@]}" + +if [[ $? -ne 0 ]]; then + >&2 echo "::error::Failed to generate Slither reports" + exit 1 +fi + +echo "Slither reports saved in $TARGET_DIR folder" diff --git a/contracts/scripts/ci/generate_uml.sh b/contracts/scripts/ci/generate_uml.sh new file mode 100755 index 0000000000..65745c93bb --- /dev/null +++ b/contracts/scripts/ci/generate_uml.sh @@ -0,0 +1,121 @@ +#!/usr/bin/env bash + +set -euo pipefail + +function check_chainlink_dir() { + local param_dir="chainlink" + current_dir=$(pwd) + + current_base=$(basename "$current_dir") + + if [[ "$current_base" != "$param_dir" ]]; then + >&2 echo "The script must be run from the root of $param_dir directory" + exit 1 + fi +} + +check_chainlink_dir + +if [ "$#" -lt 2 ]; then + >&2 echo "Generates UML diagrams for all contracts in a directory after flattening them to avoid call stack overflows." + >&2 echo "Usage: $0 [comma-separated list of files]" + exit 1 +fi + +SOURCE_DIR="$1" +TARGET_DIR="$2" +FILES=${3// /} # Remove any spaces from the list of files +FAILED_FILES=() + +flatten_and_generate_uml() { + local FILE=$1 + local TARGET_DIR=$2 + + set +e + FLATTENED_FILE="$TARGET_DIR/flattened_$(basename "$FILE")" + echo "::debug::Flattening $FILE to $FLATTENED_FILE" + forge flatten "$FILE" -o "$FLATTENED_FILE" --root contracts + if [[ $? -ne 0 ]]; then + >&2 echo "::error::Failed to flatten $FILE" + FAILED_FILES+=("$FILE") + return + fi + + OUTPUT_FILE=${FLATTENED_FILE//"flattened_"/""} + OUTPUT_FILE_SVG="${OUTPUT_FILE%.sol}.svg" + echo "::debug::Generating SVG UML for $FLATTENED_FILE to $OUTPUT_FILE_SVG" + sol2uml "$FLATTENED_FILE" -o "$OUTPUT_FILE_SVG" + if [[ $? -ne 0 ]]; then + >&2 echo "::error::Failed to generate UML diagram in SVG format for $FILE" + FAILED_FILES+=("$FILE") + rm "$FLATTENED_FILE" + return + fi + OUTPUT_FILE_DOT="${OUTPUT_FILE%.sol}.dot" + echo "::debug::Generating DOT UML for $FLATTENED_FILE to $OUTPUT_FILE_DOT" + sol2uml "$FLATTENED_FILE" -o "$OUTPUT_FILE_DOT" -f dot + if [[ $? -ne 0 ]]; then + >&2 echo "::error::Failed to generate UML diagram in DOT format for $FILE" + FAILED_FILES+=("$FILE") + rm "$FLATTENED_FILE" + return + fi + + rm "$FLATTENED_FILE" + set -e +} + +process_all_files_in_directory() { + local SOURCE_DIR=$1 + local TARGET_DIR=$2 + + mkdir -p "$TARGET_DIR" + + find "$SOURCE_DIR" -type f -name '*.sol' | while read -r ITEM; do + flatten_and_generate_uml "$ITEM" "$TARGET_DIR" + done +} + +process_selected_files() { + local SOURCE_DIR=$1 + local TARGET_DIR=$2 + local FILES=(${3//,/ }) # Split the comma-separated list into an array + + mkdir -p "$TARGET_DIR" + + for FILE in "${FILES[@]}"; do + FILE=${FILE//\"/} + MATCHES=($(find "$SOURCE_DIR" -type f -path "*/$FILE")) + + if [[ ${#MATCHES[@]} -gt 1 ]]; then + >&2 echo "Error: Multiple matches found for $FILE:" + for MATCH in "${MATCHES[@]}"; do + >&2 echo " $MATCH" + done + exit 1 + elif [[ ${#MATCHES[@]} -eq 1 ]]; then + >&2 echo "::debug::File found: ${MATCHES[0]}" + flatten_and_generate_uml "${MATCHES[0]}" "$TARGET_DIR" + else + >&2 echo "::error::File $FILE does not exist within the source directory $SOURCE_DIR." + exit 1 + fi + done +} + +# if FILES is empty, process all files in the directory, otherwise process only the selected files +if [[ -z "$FILES" ]]; then + process_all_files_in_directory "$SOURCE_DIR" "$TARGET_DIR" +else + process_selected_files "$SOURCE_DIR" "$TARGET_DIR" "$FILES" +fi + +if [[ "${#FAILED_FILES[@]}" -gt 0 ]]; then + >&2 echo ":error::Failed to generate UML diagrams for ${#FAILED_FILES[@]} files:" + for FILE in "${FAILED_FILES[@]}"; do + >&2 echo " $FILE" + echo "$FILE" >> "$TARGET_DIR/uml_generation_failures.txt" + done +fi + +echo "UML diagrams saved in $TARGET_DIR folder" diff --git a/contracts/scripts/ci/modify_remappings.sh b/contracts/scripts/ci/modify_remappings.sh new file mode 100755 index 0000000000..e64ca369b0 --- /dev/null +++ b/contracts/scripts/ci/modify_remappings.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env bash + +set -euo pipefail + +if [ "$#" -ne 2 ]; then + >&2 echo "Usage: $0 " + exit 1 +fi + +DIR_PREFIX=$1 +REMAPPINGS_FILE=$2 + +if [ ! -f "$REMAPPINGS_FILE" ]; then + >&2 echo "::error:: Remappings file '$REMAPPINGS_FILE' not found." + exit 1 +fi + +OUTPUT_FILE="remappings_modified.txt" + +while IFS= read -r line; do + if [[ "$line" =~ ^[^=]+= ]]; then + REMAPPED_PATH="${line#*=}" + MODIFIED_LINE="${line%=*}=${DIR_PREFIX}/${REMAPPED_PATH}" + echo "$MODIFIED_LINE" >> "$OUTPUT_FILE" + else + echo "$line" >> "$OUTPUT_FILE" + fi +done < "$REMAPPINGS_FILE" + +echo "Modified remappings have been saved to: $OUTPUT_FILE" diff --git a/contracts/scripts/ci/select_solc_version.sh b/contracts/scripts/ci/select_solc_version.sh new file mode 100755 index 0000000000..3f7d7864ab --- /dev/null +++ b/contracts/scripts/ci/select_solc_version.sh @@ -0,0 +1,118 @@ +#!/usr/bin/env bash + +set -euo pipefail + +function check_chainlink_dir() { + local param_dir="chainlink" + current_dir=$(pwd) + + current_base=$(basename "$current_dir") + + if [[ "$current_base" != "$param_dir" ]]; then + >&2 echo "::error::The script must be run from the root of $param_dir directory" + exit 1 + fi +} + +check_chainlink_dir + +FILE="$1" + +if [[ "$#" -lt 1 ]]; then + echo "Detects the Solidity version of a file and selects the appropriate Solc version." + echo "If the version is not installed, it will be installed and selected." + echo "Will prefer to use the version from Foundry profile if it satisfies the version in the file." + echo "Usage: $0 " + exit 1 +fi + +if [[ -z "$FILE" ]]; then + >&2 echo "::error:: File not provided." + exit 1 +fi + +extract_product() { + local path=$1 + + echo "$path" | awk -F'src/[^/]*/' '{print $2}' | cut -d'/' -f1 +} + +extract_pragma() { + local FILE=$1 + + if [[ -f "$FILE" ]]; then + SOLCVER="$(grep --no-filename '^pragma solidity' "$FILE" | cut -d' ' -f3)" + else + >&2 echo ":error::$FILE is not a file or it could not be found. Exiting." + return 1 + fi + SOLCVER="$(echo "$SOLCVER" | sed 's/[^0-9\.^]//g')" + >&2 echo "::debug::Detected Solidity version in pragma: $SOLCVER" + echo "$SOLCVER" +} + +echo "Detecting Solc version for $FILE" + +# Set FOUNDRY_PROFILE to the product name only if it is set; otherwise either already set value will be used or it will be empty +PRODUCT=$(extract_product "$FILE") +if [ -n "$PRODUCT" ]; then + FOUNDRY_PROFILE="$PRODUCT" +fi +SOLC_IN_PROFILE=$(forge config --json --root contracts | jq ".solc") +SOLC_IN_PROFILE=$(echo "$SOLC_IN_PROFILE" | tr -d "'\"") +echo "::debug::Detected Solidity version in profile: $SOLC_IN_PROFILE" + +set +e +SOLCVER=$(extract_pragma "$FILE") + +if [[ $? -ne 0 ]]; then + echo "Error: Failed to extract the Solidity version from $FILE." + return 1 +fi + +set -e + +SOLCVER=$(echo "$SOLCVER" | tr -d "'\"") + +if [[ "$SOLC_IN_PROFILE" != "null" && -n "$SOLCVER" ]]; then + set +e + COMPAT_SOLC_VERSION=$(npx semver "$SOLC_IN_PROFILE" -r "$SOLCVER") + exit_code=$? + set -e + if [[ $exit_code -eq 0 && -n "$COMPAT_SOLC_VERSION" ]]; then + echo "::debug::Version $SOLC_IN_PROFILE satisfies the constraint $SOLCVER" + SOLC_TO_USE="$SOLC_IN_PROFILE" + else + echo "::debug::Version $SOLC_IN_PROFILE does not satisfy the constraint $SOLCVER" + SOLC_TO_USE="$SOLCVER" + fi + elif [[ "$SOLC_IN_PROFILE" != "null" && -z "$SOLCVER" ]]; then + >&2 echo "::error::No version found in the Solidity file. Exiting" + return 1 + elif [[ "$SOLC_IN_PROFILE" == "null" && -n "$SOLCVER" ]]; then + echo "::debug::Using the version from the file: $SOLCVER" + SOLC_TO_USE="$SOLCVER" + else + >&2 echo "::error::No version found in the profile or the Solidity file." + return 1 +fi + +echo "Will use $SOLC_TO_USE" +SOLC_TO_USE=$(echo "$SOLC_TO_USE" | tr -d "'\"") +SOLC_TO_USE="$(echo "$SOLC_TO_USE" | sed 's/[^0-9\.]//g')" + +INSTALLED_VERSIONS=$(solc-select versions) + +if echo "$INSTALLED_VERSIONS" | grep -q "$SOLC_TO_USE"; then + echo "::debug::Version $SOLCVER is already installed." + if echo "$INSTALLED_VERSIONS" | grep "$SOLC_TO_USE" | grep -q "current"; then + echo "::debug::Version $SOLCVER is already selected." + else + echo "::debug::Selecting $SOLC_TO_USE" + solc-select use "$SOLC_TO_USE" + fi +else + echo "::debug::Version $SOLC_TO_USE is not installed." + solc-select install "$SOLC_TO_USE" + solc-select use "$SOLC_TO_USE" +fi diff --git a/contracts/scripts/lcov_prune b/contracts/scripts/lcov_prune new file mode 100755 index 0000000000..0f16715cb2 --- /dev/null +++ b/contracts/scripts/lcov_prune @@ -0,0 +1,77 @@ +#!/bin/bash + +if [ "$#" -ne 3 ]; then + >&2 echo "Usage: $0 " + exit 1 +fi + +set -e + +product_name=$1 +input_coverage_file=$2 +output_coverage_file=$3 + +# src/v0.8/ccip/libraries/Internal.sol +# src/v0.8/ccip/libraries/RateLimiter.sol +# src/v0.8/ccip/libraries/USDPriceWith18Decimals.sol +# src/v0.8/ccip/libraries/MerkleMultiProof.sol +# src/v0.8/ccip/libraries/Pool.sol +# excluded because Foundry doesn't support coverage on library files + +# BurnWithFromMintTokenPool is excluded because Forge doesn't seem to +# register coverage, even though it is 100% covered. +exclusion_list_ccip=( + "src/v0.8/ccip/ocr/OCR2Abstract.sol" + "src/v0.8/ccip/libraries/Internal.sol" + "src/v0.8/ccip/libraries/RateLimiter.sol" + "src/v0.8/ccip/libraries/USDPriceWith18Decimals.sol" + "src/v0.8/ccip/libraries/MerkleMultiProof.sol" + "src/v0.8/ccip/libraries/Pool.sol" + "src/v0.8/ConfirmedOwnerWithProposal.sol" + "src/v0.8/tests/MockV3Aggregator.sol" + "src/v0.8/ccip/applications/CCIPClientExample.sol" + "src/v0.8/ccip/pools/BurnWithFromMintTokenPool.sol" +) + +exclusion_list_shared=( + "*/shared/*" +) + +exclusion_list_common=( + "*/$product_name/test/*" + "*/vendor/*" +) + +all_exclusions=() + +case "$product_name" in + "ccip") + all_exclusions+=("${exclusion_list_ccip[@]}") + ;; + "shared") + # No product-specific exclusions for shared + ;; + *) + ;; +esac + +all_exclusions+=("${exclusion_list_common[@]}") + +if [ "$product_name" != "shared" ]; then + all_exclusions+=("${exclusion_list_shared[@]}") +fi + +echo "Excluding the following files for product $product_name:" +for exclusion in "${all_exclusions[@]}"; do + echo "$exclusion" +done + +lcov_command="lcov --remove $input_coverage_file -o $output_coverage_file" + +for exclusion in "${all_exclusions[@]}"; do + lcov_command+=" \"$exclusion\"" +done + +lcov_command+=" --rc lcov_branch_coverage=1" + +eval $lcov_command diff --git a/tools/ci/ccip_lcov_prune b/tools/ci/ccip_lcov_prune deleted file mode 100755 index 0c6355f626..0000000000 --- a/tools/ci/ccip_lcov_prune +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env bash - -set -e - -# src/v0.8/ccip/libraries/Internal.sol -# src/v0.8/ccip/libraries/RateLimiter.sol -# src/v0.8/ccip/libraries/USDPriceWith18Decimals.sol -# src/v0.8/ccip/libraries/MerkleMultiProof.sol -# src/v0.8/ccip/libraries/Pool.sol -# excluded because Foundry doesn't support coverage on library files - -# BurnWithFromMintTokenPool is excluded because Forge doesn't seem to -# register coverage, even though it is 100% covered. - - -lcov --remove $1 -o $2 \ - '*/ccip/test/*' \ - '*/vendor/*' \ - '*/shared/*' \ - 'src/v0.8/ccip/ocr/OCR2Abstract.sol' \ - 'src/v0.8/ccip/libraries/Internal.sol' \ - 'src/v0.8/ccip/libraries/RateLimiter.sol' \ - 'src/v0.8/ccip/libraries/USDPriceWith18Decimals.sol' \ - 'src/v0.8/ccip/libraries/MerkleMultiProof.sol' \ - 'src/v0.8/ccip/libraries/Pool.sol' \ - 'src/v0.8/ConfirmedOwnerWithProposal.sol' \ - 'src/v0.8/tests/MockV3Aggregator.sol' \ - 'src/v0.8/ccip/applications/CCIPClientExample.sol' \ - 'src/v0.8/ccip/pools/BurnWithFromMintTokenPool.sol' \ - --rc lcov_branch_coverage=1 From c4dc7a59c394caffb5619597f3a59fef5d9ccb84 Mon Sep 17 00:00:00 2001 From: Bartek Tofel Date: Fri, 9 Aug 2024 16:16:24 +0200 Subject: [PATCH 053/115] add missing step id to action (#14088) * add missing step id * do not fail if Slither fails * try with not failing generation --- .github/workflows/solidity-foundry-artifacts.yml | 1 + contracts/scripts/ci/generate_slither_report.sh | 14 ++++++-------- contracts/scripts/ci/generate_uml.sh | 2 +- contracts/scripts/ci/select_solc_version.sh | 2 +- 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/.github/workflows/solidity-foundry-artifacts.yml b/.github/workflows/solidity-foundry-artifacts.yml index e489033d67..50a77e2846 100644 --- a/.github/workflows/solidity-foundry-artifacts.yml +++ b/.github/workflows/solidity-foundry-artifacts.yml @@ -118,6 +118,7 @@ jobs: fetch-depth: 0 - name: Extract Foundry version + id: extract-foundry-version uses: ./.github/actions/detect-solidity-foundry-version with: working-directory: contracts diff --git a/contracts/scripts/ci/generate_slither_report.sh b/contracts/scripts/ci/generate_slither_report.sh index 7fe31d40ef..bc876ae118 100755 --- a/contracts/scripts/ci/generate_slither_report.sh +++ b/contracts/scripts/ci/generate_slither_report.sh @@ -44,15 +44,13 @@ run_slither() { >&2 echo "::error::Failed to select Solc version for $FILE" return 1 fi - set -e SLITHER_OUTPUT_FILE="$TARGET_DIR/$(basename "${FILE%.sol}")-slither-report.md" - - output=$(slither --config-file "$CONFIG_FILE" "$FILE" --checklist --markdown-root "$REPO_URL" --fail-none $SLITHER_EXTRA_PARAMS) - if [ $? -ne 0 ]; then - >&2 echo "::error::Slither failed for $FILE" - exit 1 + if ! output=$(slither --config-file "$CONFIG_FILE" "$FILE" --checklist --markdown-root "$REPO_URL" --fail-none $SLITHER_EXTRA_PARAMS); then + >&2 echo "::warning::Slither failed for $FILE" + return 0 fi + set -e output=$(echo "$output" | sed '/\*\*THIS CHECKLIST IS NOT COMPLETE\*\*. Use `--show-ignored-findings` to show all the results./d' | sed '/Summary/d') echo "# Summary for $FILE" > "$SLITHER_OUTPUT_FILE" @@ -80,8 +78,8 @@ set +e process_files "$SOURCE_DIR" "$TARGET_DIR" "${FILES[@]}" if [[ $? -ne 0 ]]; then - >&2 echo "::error::Failed to generate Slither reports" - exit 1 + >&2 echo "::warning::Failed to generate some Slither reports" + exit 0 fi echo "Slither reports saved in $TARGET_DIR folder" diff --git a/contracts/scripts/ci/generate_uml.sh b/contracts/scripts/ci/generate_uml.sh index 65745c93bb..c71d0a1ac7 100755 --- a/contracts/scripts/ci/generate_uml.sh +++ b/contracts/scripts/ci/generate_uml.sh @@ -88,7 +88,7 @@ process_selected_files() { MATCHES=($(find "$SOURCE_DIR" -type f -path "*/$FILE")) if [[ ${#MATCHES[@]} -gt 1 ]]; then - >&2 echo "Error: Multiple matches found for $FILE:" + >&2 echo "::error:: Multiple matches found for $FILE:" for MATCH in "${MATCHES[@]}"; do >&2 echo " $MATCH" done diff --git a/contracts/scripts/ci/select_solc_version.sh b/contracts/scripts/ci/select_solc_version.sh index 3f7d7864ab..cfa13de0f6 100755 --- a/contracts/scripts/ci/select_solc_version.sh +++ b/contracts/scripts/ci/select_solc_version.sh @@ -66,7 +66,7 @@ set +e SOLCVER=$(extract_pragma "$FILE") if [[ $? -ne 0 ]]; then - echo "Error: Failed to extract the Solidity version from $FILE." + >&2 echo "::error:: Failed to extract the Solidity version from $FILE." return 1 fi From 1cdeaef45aefbc2bec7fbc1c5dc805066b079191 Mon Sep 17 00:00:00 2001 From: Rens Rooimans Date: Mon, 26 Aug 2024 15:57:50 +0200 Subject: [PATCH 054/115] Bump NPM and Forge dependencies (#14093) * bump npm * more npm * bump foundry dep * make snapshot * rm gas tests * fix change in gas cost * fix blockhash, this breaks the proof * Regenerated VRF proofs and fixed payment outputs in Foundry tests * Updated gas cost for LINK payments in unit tests * try with no coverage, exclude test files from Slither * add support for extra code coverage params * fix warnings and snapshot * changeset * fix codeowners * fix tests and bump foundry * add missing changes quantifier --------- Co-authored-by: Iva Brajer Co-authored-by: Bartek Tofel --- .github/CODEOWNERS | 7 +- .github/workflows/solidity-foundry.yml | 254 ++- contracts/.changeset/few-camels-tan.md | 5 + contracts/GNUmakefile | 2 +- contracts/gas-snapshots/ccip.gas-snapshot | 1241 +++++++-------- .../gas-snapshots/functions.gas-snapshot | 248 +-- contracts/gas-snapshots/keystone.gas-snapshot | 167 +- contracts/gas-snapshots/l2ep.gas-snapshot | 44 +- .../liquiditymanager.gas-snapshot | 2 +- .../gas-snapshots/llo-feeds.gas-snapshot | 246 ++- .../operatorforwarder.gas-snapshot | 8 +- contracts/gas-snapshots/shared.gas-snapshot | 24 +- contracts/package.json | 30 +- contracts/pnpm-lock.yaml | 1417 +++++------------ .../ArbitrumSequencerUptimeFeed.t.sol | 196 --- .../OptimismSequencerUptimeFeed.t.sol | 204 --- .../scroll/ScrollSequencerUptimeFeed.t.sol | 204 --- .../v0.8/llo-feeds/test/ByteUtilTest.t.sol | 24 +- .../test/testhelpers/MaliciousConsumer.sol | 2 +- .../MaliciousMultiWordConsumer.sol | 2 +- .../shared/test/call/CallWithExactGas.t.sol | 4 +- .../shared/test/testhelpers/GasConsumer.sol | 5 +- .../test/token/ERC677/BurnMintERC677.t.sol | 2 +- .../token/ERC677/OpStackBurnMintERC677.t.sol | 2 +- .../test/util/SortedSetValidationUtil.t.sol | 8 +- .../vrf/test/BatchVRFCoordinatorV2Plus.t.sol | 80 +- contracts/src/v0.8/vrf/test/VRFV2Plus.t.sol | 249 +-- core/scripts/vrfv2plus/testnet/proofs.go | 2 +- 28 files changed, 1917 insertions(+), 2762 deletions(-) create mode 100644 contracts/.changeset/few-camels-tan.md diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index eae41c622d..ea3f1419e8 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -50,6 +50,9 @@ core/services/relay/evm/functions @smartcontractkit/functions core/scripts/functions @smartcontractkit/functions core/scripts/gateway @smartcontractkit/functions +# Contracts +/contracts/ @RensR @matYang @RayXpub @elatoskinas + # First we match on project names to catch files like the compilation scripts, # gas snapshots and other files not places in the project directories. # This could give some false positives, so afterwards we match on the project directories @@ -76,8 +79,8 @@ core/scripts/gateway @smartcontractkit/functions /contracts/src/v0.8/l2ep @chris-de-leon-cll /contracts/src/v0.8/llo-feeds @smartcontractkit/mercury-team # TODO: mocks folder, folder should be removed and files moved to the correct folders -/contracts/src/v0.8/operatorforwarder @austinborn -/contracts/src/v0.8/shared @RensR +/contracts/src/v0.8/operatorforwarder @smartcontractkit/data-feeds-engineers +/contracts/src/v0.8/shared @RensR @matYang @RayXpub @elatoskinas # TODO: tests folder, folder should be removed and files moved to the correct folders # TODO: transmission folder, owner should be found /contracts/src/v0.8/vrf @smartcontractkit/vrf-team diff --git a/.github/workflows/solidity-foundry.yml b/.github/workflows/solidity-foundry.yml index 906cb76ffe..0c0c3be434 100644 --- a/.github/workflows/solidity-foundry.yml +++ b/.github/workflows/solidity-foundry.yml @@ -8,6 +8,11 @@ env: # * use the top-level matrix to decide, which checks should run for each product. # * when enabling code coverage, remember to adjust the minimum code coverage as it's set to 98.5% by default. +# This pipeline will run product tests only if product-specific contracts were modified or if broad-impact changes were made (e.g. changes to this pipeline, Foundry configuration, etc.) +# For modified contracts we use a LLM to extract new issues introduced by the changes. For new contracts full report is delivered. +# Slither has a default configuration, but also supports per-product configuration. If a product-specific configuration is not found, the default one is used. +# Changes to test files do not trigger static analysis or formatting checks. + jobs: define-matrix: name: Define test matrix @@ -30,7 +35,7 @@ jobs: { "name": "liquiditymanager", "setup": { "run-coverage": true, "min-coverage": 46.3, "run-gas-snapshot": true, "run-forge-fmt": false }}, { "name": "llo-feeds", "setup": { "run-coverage": true, "min-coverage": 49.3, "run-gas-snapshot": true, "run-forge-fmt": false }}, { "name": "operatorforwarder", "setup": { "run-coverage": true, "min-coverage": 55.7, "run-gas-snapshot": true, "run-forge-fmt": false }}, - { "name": "shared", "setup": { "run-coverage": true, "min-coverage": 32.6, "run-gas-snapshot": true, "run-forge-fmt": false }}, + { "name": "shared", "setup": { "run-coverage": true, "extra-coverage-params": "--no-match-path='*CallWithExactGas*'", "min-coverage": 32.6, "run-gas-snapshot": true, "run-forge-fmt": false }}, { "name": "transmission", "setup": { "run-coverage": true, "min-coverage": 65.6, "run-gas-snapshot": true, "run-forge-fmt": false }}, { "name": "vrf", "setup": { "run-coverage": false, "min-coverage": 98.5, "run-gas-snapshot": false, "run-forge-fmt": false }} ] @@ -53,28 +58,33 @@ jobs: runs-on: ubuntu-latest outputs: non_src_changes: ${{ steps.changes.outputs.non_src }} - sol_modified: ${{ steps.changes.outputs.sol }} - sol_modified_files: ${{ steps.changes.outputs.sol_files }} - not_test_sol_modified: ${{ steps.changes.outputs.not_test_sol }} - not_test_sol_modified_files: ${{ steps.changes.outputs.not_test_sol_files }} + sol_modified_added: ${{ steps.changes.outputs.sol }} + sol_modified_added_files: ${{ steps.changes.outputs.sol_files }} + sol_mod_only: ${{ steps.changes.outputs.sol_mod_only }} + sol_mod_only_files: ${{ steps.changes.outputs.sol_mod_only_files }} + not_test_sol_modified: ${{ steps.changes-non-test.outputs.not_test_sol }} + not_test_sol_modified_files: ${{ steps.changes-non-test.outputs.not_test_sol_files }} all_changes: ${{ steps.changes.outputs.changes }} steps: - name: Checkout the repo uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 + - name: Detect changes + uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 id: changes with: list-files: 'shell' filters: | non_src: - - '.github/workflows/solidity-foundry.yml' + - '.github/workflows/solidity-foundry.yml' - 'contracts/foundry.toml' - 'contracts/gas-snapshots/*.gas-snapshot' - 'contracts/package.json' sol: - modified|added: 'contracts/src/v0.8/**/*.sol' + sol_mod_only: + - modified: 'contracts/src/v0.8/**/!(tests|mocks)/!(*.t).sol' not_test_sol: - - modified|added: 'contracts/src/v0.8/**/!(*.t).sol' + - modified|added: 'contracts/src/v0.8/**/!(tests|mocks)/!(*.t).sol' automation: - 'contracts/src/v0.8/automation/**/*.sol' ccip: @@ -102,8 +112,28 @@ jobs: transmission: - 'contracts/src/v0.8/transmission/**/*.sol' + - name: Detect non-test changes + uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 + id: changes-non-test + with: + list-files: 'shell' + # This is a valid input, see https://github.com/dorny/paths-filter/pull/226 + predicate-quantifier: every + filters: | + not_test_sol: + - modified|added: 'contracts/src/v0.8/**/!(*.t).sol' + - '!contracts/src/v0.8/**/test/**' + - '!contracts/src/v0.8/**/tests/**' + - '!contracts/src/v0.8/**/mock/**' + - '!contracts/src/v0.8/**/mocks/**' + - '!contracts/src/v0.8/**/*.t.sol' + - '!contracts/src/v0.8/*.t.sol' + - '!contracts/src/v0.8/**/testhelpers/**' + - '!contracts/src/v0.8/testhelpers/**' + - '!contracts/src/v0.8/vendor/**' + tests: - if: ${{ needs.changes.outputs.non_src_changes == 'true' || needs.changes.outputs.sol_modified == 'true' }} + if: ${{ needs.changes.outputs.non_src_changes == 'true' || needs.changes.outputs.sol_modified_added == 'true' }} strategy: fail-fast: false matrix: @@ -189,7 +219,13 @@ jobs: || needs.changes.outputs.non_src_changes == 'true') && matrix.product.setup.run-coverage }} working-directory: contracts - run: forge coverage --report lcov + shell: bash + run: | + if [[ -n "${{ matrix.product.setup.extra-coverage-params }}" ]]; then + forge coverage --report lcov ${{ matrix.product.setup.extra-coverage-params }} + else + forge coverage --report lcov + fi env: FOUNDRY_PROFILE: ${{ matrix.product.name }} @@ -199,7 +235,6 @@ jobs: || needs.changes.outputs.non_src_changes == 'true') && matrix.product.setup.run-coverage }} run: | - sudo apt-get install lcov ./contracts/scripts/lcov_prune ${{ matrix.product.name }} ./contracts/lcov.info ./contracts/lcov.info.pruned - name: Report code coverage for ${{ matrix.product.name }} @@ -229,6 +264,7 @@ jobs: this-job-name: Foundry Tests ${{ matrix.product.name }} continue-on-error: true + # runs only if non-test contracts were modified; scoped only to modified or added contracts analyze: needs: [ changes, define-matrix ] name: Run static analysis @@ -268,25 +304,164 @@ jobs: # modify remappings so that solc can find dependencies ./contracts/scripts/ci/modify_remappings.sh contracts contracts/remappings.txt mv remappings_modified.txt remappings.txt + + # without it Slither sometimes fails to use remappings correctly + cp contracts/foundry.toml foundry.toml + + FILES="${{ needs.changes.outputs.not_test_sol_modified_files }}" + + for FILE in $FILES; do + PRODUCT=$(echo "$FILE" | awk -F'src/[^/]*/' '{print $2}' | cut -d'/' -f1) + echo "::debug::Running Slither for $FILE in $PRODUCT" + SLITHER_CONFIG="contracts/configs/slither/.slither.config-$PRODUCT-pr.json" + if [[ ! -f $SLITHER_CONFIG ]]; then + echo "::debug::No Slither config found for $PRODUCT, using default" + SLITHER_CONFIG="contracts/configs/slither/.slither.config-default-pr.json" + fi + ./contracts/scripts/ci/generate_slither_report.sh "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.sha }}/" "$SLITHER_CONFIG" "." "$FILE" "contracts/slither-reports-current" "--solc-remaps @=contracts/node_modules/@" + done + + # all the actions below, up to printing results, run only if any existing contracts were modified + # in that case we extract new issues introduced by the changes by using an LLM model + - name: Upload Slither results for current branch + if: needs.changes.outputs.sol_mod_only == 'true' + uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4.3.4 + timeout-minutes: 2 + continue-on-error: true + with: + name: slither-reports-current-${{ github.sha }} + path: contracts/slither-reports-current + retention-days: 7 + + # we need to upload scripts and configuration in case base_ref doesn't have the scripts, or they are in different version + - name: Upload Slither scripts + if: needs.changes.outputs.sol_mod_only == 'true' + uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4.3.4 + timeout-minutes: 2 + continue-on-error: true + with: + name: tmp-slither-scripts-${{ github.sha }} + path: contracts/scripts/ci + retention-days: 7 + + - name: Upload configs + if: needs.changes.outputs.sol_mod_only == 'true' + uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4.3.4 + timeout-minutes: 2 + continue-on-error: true + with: + name: tmp-configs-${{ github.sha }} + path: contracts/configs + retention-days: 7 + + - name: Checkout the repo + if: needs.changes.outputs.sol_mod_only == 'true' + uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + with: + ref: ${{ github.base_ref }} + + - name: Download Slither scripts + if: needs.changes.outputs.sol_mod_only == 'true' + uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 + with: + name: tmp-slither-scripts-${{ github.sha }} + path: contracts/scripts/ci + + - name: Download configs + if: needs.changes.outputs.sol_mod_only == 'true' + uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 + with: + name: tmp-configs-${{ github.sha }} + path: contracts/configs + + # since we have just checked out the repository again, we lose NPM dependencies installs previously, we need to install them again to compile contracts + - name: Setup NodeJS + if: needs.changes.outputs.sol_mod_only == 'true' + uses: ./.github/actions/setup-nodejs - FILES="${{ needs.changes.outputs.not_test_sol_modified_files }}" + - name: Run Slither for base reference + if: needs.changes.outputs.sol_mod_only == 'true' + shell: bash + run: | + # we need to set file permission again since they are lost during download + for file in contracts/scripts/ci/*.sh; do + chmod +x "$file" + done + + # modify remappings so that solc can find dependencies + ./contracts/scripts/ci/modify_remappings.sh contracts contracts/remappings.txt + mv remappings_modified.txt remappings.txt + + # without it Slither sometimes fails to use remappings correctly + cp contracts/foundry.toml foundry.toml + + FILES="${{ needs.changes.outputs.sol_mod_only_files }}" for FILE in $FILES; do PRODUCT=$(echo "$FILE" | awk -F'src/[^/]*/' '{print $2}' | cut -d'/' -f1) echo "::debug::Running Slither for $FILE in $PRODUCT" SLITHER_CONFIG="contracts/configs/slither/.slither.config-$PRODUCT-pr.json" - if [ ! -f $SLITHER_CONFIG ]; then + if [[ ! -f $SLITHER_CONFIG ]]; then echo "::debug::No Slither config found for $PRODUCT, using default" SLITHER_CONFIG="contracts/configs/slither/.slither.config-default-pr.json" fi - ./contracts/scripts/ci/generate_slither_report.sh "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.sha }}/" "$SLITHER_CONFIG" "." "$FILE" "contracts/slither-reports" "--solc-remaps @=contracts/node_modules/@" + ./contracts/scripts/ci/generate_slither_report.sh "${{ github.server_url }}/${{ github.repository }}/blob/${{ github.sha }}/" "$SLITHER_CONFIG" "." "$FILE" "contracts/slither-reports-base-ref" "--solc-remaps @=contracts/node_modules/@" + done + + - name: Upload Slither report + if: needs.changes.outputs.sol_mod_only == 'true' + uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4.3.4 + timeout-minutes: 10 + continue-on-error: true + with: + name: slither-reports-base-${{ github.sha }} + path: | + contracts/slither-reports-base-ref + retention-days: 7 + + - name: Download Slither results for current branch + if: needs.changes.outputs.sol_mod_only == 'true' + uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7 + with: + name: slither-reports-current-${{ github.sha }} + path: contracts/slither-reports-current + + - name: Generate diff of Slither reports for modified files + if: needs.changes.outputs.sol_mod_only == 'true' + env: + OPEN_API_KEY: ${{ secrets.OPEN_AI_SLITHER_API_KEY }} + shell: bash + run: | + set -euo pipefail + for base_report in contracts/slither-reports-base-ref/*.md; do + filename=$(basename "$base_report") + current_report="contracts/slither-reports-current/$filename" + new_issues_report="contracts/slither-reports-current/${filename%.md}_new_issues.md" + if [ -f "$current_report" ]; then + if ./contracts/scripts/ci/find_slither_report_diff.sh "$base_report" "$current_report" "$new_issues_report" "contracts/scripts/ci/prompt-difference.md" "contracts/scripts/ci/prompt-validation.md"; then + if [[ -s $new_issues_report ]]; then + awk 'NR==2{print "*This new issues report has been automatically generated by LLM model using two Slither reports. One based on `${{ github.base_ref}}` and another on `${{ github.sha }}` commits.*"}1' $new_issues_report > tmp.md && mv tmp.md $new_issues_report + echo "Replacing full Slither report with diff for $current_report" + rm $current_report && mv $new_issues_report $current_report + else + echo "No difference detected between $base_report and $current_report reports. Won't include any of them." + rm $current_report + fi + else + echo "::warning::Failed to generate a diff report with new issues for $base_report using an LLM model, will use full report." + fi + + else + echo "::warning::Failed to find current commit's equivalent of $base_report (file $current_report doesn't exist, but should have been generated). Please check Slither logs." + fi done + # actions that execute only if any existing contracts were modified end here - name: Print Slither summary shell: bash run: | echo "# Static analysis results " >> $GITHUB_STEP_SUMMARY - for file in "contracts/slither-reports"/*.md; do + for file in "contracts/slither-reports-current"/*.md; do if [ -e "$file" ]; then cat "$file" >> $GITHUB_STEP_SUMMARY fi @@ -296,19 +471,62 @@ jobs: uses: ./.github/actions/validate-solidity-artifacts with: validate_slither_reports: 'true' - slither_reports_path: 'contracts/slither-reports' + slither_reports_path: 'contracts/slither-reports-current' sol_files: ${{ needs.changes.outputs.not_test_sol_modified_files }} - - name: Upload Slither report + - name: Upload Slither reports uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # v4.3.4 timeout-minutes: 10 continue-on-error: true with: name: slither-reports-${{ github.sha }} path: | - contracts/slither-reports + contracts/slither-reports-current retention-days: 7 + - name: Find Slither comment in the PR + uses: peter-evans/find-comment@3eae4d37986fb5a8592848f6a574fdf654e61f9e # v3.0.0 + id: find-comment + with: + issue-number: ${{ github.event.pull_request.number }} + comment-author: 'github-actions[bot]' + body-includes: 'Static analysis results' + + - name: Extract job summary URL + id: job-summary-url + uses: pl-strflt/job-summary-url-action@df2d22c5351f73e0a187d20879854b8d98e6e001 # v1.0.0 + with: + job: 'Run static analysis' + + - name: Build Slither reports artifacts URL + id: build-slither-artifact-url + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + ARTIFACTS=$(gh api -X GET repos/${{ github.repository }}/actions/runs/${{ github.run_id }}/artifacts) + ARTIFACT_ID=$(echo "$ARTIFACTS" | jq '.artifacts[] | select(.name=="slither-reports-${{ github.sha }}") | .id') + echo "Artifact ID: $ARTIFACT_ID" + + slither_artifact_url="https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}/artifacts/$ARTIFACT_ID" + echo "slither_artifact_url=$slither_artifact_url" >> $GITHUB_OUTPUT + + - name: Create or update Slither comment in the PR + uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4.0.0 + with: + comment-id: ${{ steps.find-comment.outputs.comment-id }} + issue-number: ${{ github.event.pull_request.number }} + body: | + ## Static analysis results are available + Hey @${{ github.event.push && github.event.push.pusher && github.event.push.pusher.username || github.actor }}, you can view Slither reports in the job summary [here](${{ steps.job-summary-url.outputs.job_summary_url }}) or download them as artifact [here](${{ steps.build-slither-artifact-url.outputs.slither_artifact_url }}). + + Please check them before merging and make sure you have addressed all issues. + edit-mode: replace + + - name: Remove temp artifacts + uses: geekyeggo/delete-artifact@24928e75e6e6590170563b8ddae9fac674508aa1 # v5.0 + with: + name: tmp-* + - name: Collect Metrics id: collect-gha-metrics uses: smartcontractkit/push-gha-metrics-action@dea9b546553cb4ca936607c2267a09c004e4ab3f # v3.0.0 diff --git a/contracts/.changeset/few-camels-tan.md b/contracts/.changeset/few-camels-tan.md new file mode 100644 index 0000000000..ca2574171d --- /dev/null +++ b/contracts/.changeset/few-camels-tan.md @@ -0,0 +1,5 @@ +--- +'@chainlink/contracts': patch +--- + +bump dependencies diff --git a/contracts/GNUmakefile b/contracts/GNUmakefile index 3da2d5f205..862d75a432 100644 --- a/contracts/GNUmakefile +++ b/contracts/GNUmakefile @@ -43,7 +43,7 @@ mockery: $(mockery) ## Install mockery. .PHONY: foundry foundry: ## Install foundry. - foundryup --version nightly-de33b6af53005037b463318d2628b5cfcaf39916 + foundryup --version nightly-515a4cc8aba1627a717a1057ff4f09c8cd3bf51f .PHONY: foundry-refresh foundry-refresh: foundry diff --git a/contracts/gas-snapshots/ccip.gas-snapshot b/contracts/gas-snapshots/ccip.gas-snapshot index 97609ff3aa..eb96103c40 100644 --- a/contracts/gas-snapshots/ccip.gas-snapshot +++ b/contracts/gas-snapshots/ccip.gas-snapshot @@ -10,8 +10,8 @@ AggregateTokenLimiter_getTokenBucket:test_GetTokenBucket_Success() (gas: 19691) AggregateTokenLimiter_getTokenBucket:test_Refill_Success() (gas: 40911) AggregateTokenLimiter_getTokenBucket:test_TimeUnderflow_Revert() (gas: 15368) AggregateTokenLimiter_getTokenLimitAdmin:test_GetTokenLimitAdmin_Success() (gas: 10531) -AggregateTokenLimiter_getTokenValue:test_GetTokenValue_Success() (gas: 19668) -AggregateTokenLimiter_getTokenValue:test_NoTokenPrice_Reverts() (gas: 21253) +AggregateTokenLimiter_getTokenValue:test_GetTokenValue_Success() (gas: 19696) +AggregateTokenLimiter_getTokenValue:test_NoTokenPrice_Reverts() (gas: 21281) AggregateTokenLimiter_rateLimitValue:test_AggregateValueMaxCapacityExceeded_Revert() (gas: 16418) AggregateTokenLimiter_rateLimitValue:test_RateLimitValueSuccess_gas() (gas: 18306) AggregateTokenLimiter_setAdmin:test_OnlyOwnerOrAdmin_Revert() (gas: 13047) @@ -19,62 +19,59 @@ AggregateTokenLimiter_setAdmin:test_Owner_Success() (gas: 18989) AggregateTokenLimiter_setRateLimiterConfig:test_OnlyOnlyCallableByAdminOrOwner_Revert() (gas: 17479) AggregateTokenLimiter_setRateLimiterConfig:test_Owner_Success() (gas: 30062) AggregateTokenLimiter_setRateLimiterConfig:test_TokenLimitAdmin_Success() (gas: 32071) -BurnFromMintTokenPool_lockOrBurn:test_ChainNotAllowed_Revert() (gas: 28761) -BurnFromMintTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 55115) -BurnFromMintTokenPool_lockOrBurn:test_PoolBurn_Success() (gas: 243491) -BurnFromMintTokenPool_lockOrBurn:test_Setup_Success() (gas: 23947) -BurnMintTokenPool_lockOrBurn:test_ChainNotAllowed_Revert() (gas: 27522) -BurnMintTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 55115) -BurnMintTokenPool_lockOrBurn:test_PoolBurn_Success() (gas: 241381) -BurnMintTokenPool_lockOrBurn:test_Setup_Success() (gas: 17677) -BurnMintTokenPool_releaseOrMint:test_ChainNotAllowed_Revert() (gas: 28757) -BurnMintTokenPool_releaseOrMint:test_PoolMintNotHealthy_Revert() (gas: 56190) -BurnMintTokenPool_releaseOrMint:test_PoolMint_Success() (gas: 112319) -BurnWithFromMintTokenPool_lockOrBurn:test_ChainNotAllowed_Revert() (gas: 28761) -BurnWithFromMintTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 55115) -BurnWithFromMintTokenPool_lockOrBurn:test_PoolBurn_Success() (gas: 243517) -BurnWithFromMintTokenPool_lockOrBurn:test_Setup_Success() (gas: 23951) -CCIPClientExample_sanity:test_ImmutableExamples_Success() (gas: 2132684) -CCIPConfigSetup:test_getCapabilityConfiguration_Success() (gas: 9517) -CCIPConfig_ConfigStateMachine:test__computeConfigDigest_Success() (gas: 70831) -CCIPConfig_ConfigStateMachine:test__computeNewConfigWithMeta_InitToRunning_Success() (gas: 363664) -CCIPConfig_ConfigStateMachine:test__computeNewConfigWithMeta_RunningToStaging_Success() (gas: 488826) -CCIPConfig_ConfigStateMachine:test__computeNewConfigWithMeta_StagingToRunning_Success() (gas: 453439) -CCIPConfig_ConfigStateMachine:test__groupByPluginType_TooManyOCR3Configs_Reverts() (gas: 37049) -CCIPConfig_ConfigStateMachine:test__groupByPluginType_threeCommitConfigs_Reverts() (gas: 61065) -CCIPConfig_ConfigStateMachine:test__groupByPluginType_threeExecutionConfigs_Reverts() (gas: 60985) -CCIPConfig_ConfigStateMachine:test__stateFromConfigLength_Success() (gas: 11635) -CCIPConfig_ConfigStateMachine:test__validateConfigStateTransition_Success() (gas: 8831) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_InitToRunning_Success() (gas: 312055) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_InitToRunning_WrongConfigCount_Reverts() (gas: 49727) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_NonExistentConfigTransition_Reverts() (gas: 32320) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_RunningToStaging_Success() (gas: 376678) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_RunningToStaging_WrongConfigCount_Reverts() (gas: 121045) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_RunningToStaging_WrongConfigDigestBlueGreen_Reverts() (gas: 157245) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_StagingToRunning_Success() (gas: 376454) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_StagingToRunning_WrongConfigDigest_Reverts() (gas: 157312) -CCIPConfig_ConfigStateMachine:test_getCapabilityConfiguration_Success() (gas: 9605) -CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_CommitAndExecConfig_Success() (gas: 1851094) -CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_CommitConfigOnly_Success() (gas: 1068315) -CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_ExecConfigOnly_Success() (gas: 1068346) +BurnFromMintTokenPool_lockOrBurn:test_ChainNotAllowed_Revert() (gas: 28675) +BurnFromMintTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 55158) +BurnFromMintTokenPool_lockOrBurn:test_PoolBurn_Success() (gas: 243525) +BurnFromMintTokenPool_lockOrBurn:test_Setup_Success() (gas: 23907) +BurnMintTokenPool_lockOrBurn:test_ChainNotAllowed_Revert() (gas: 27565) +BurnMintTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 55158) +BurnMintTokenPool_lockOrBurn:test_PoolBurn_Success() (gas: 241416) +BurnMintTokenPool_lockOrBurn:test_Setup_Success() (gas: 17633) +BurnMintTokenPool_releaseOrMint:test_ChainNotAllowed_Revert() (gas: 28537) +BurnMintTokenPool_releaseOrMint:test_PoolMintNotHealthy_Revert() (gas: 55991) +BurnMintTokenPool_releaseOrMint:test_PoolMint_Success() (gas: 110657) +BurnWithFromMintTokenPool_lockOrBurn:test_ChainNotAllowed_Revert() (gas: 28675) +BurnWithFromMintTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 55158) +BurnWithFromMintTokenPool_lockOrBurn:test_PoolBurn_Success() (gas: 243552) +BurnWithFromMintTokenPool_lockOrBurn:test_Setup_Success() (gas: 24260) +CCIPClientExample_sanity:test_ImmutableExamples_Success() (gas: 2131281) +CCIPConfigSetup:test_getCapabilityConfiguration_Success() (gas: 9495) +CCIPConfig_ConfigStateMachine:test__computeConfigDigest_Success() (gas: 70755) +CCIPConfig_ConfigStateMachine:test__computeNewConfigWithMeta_InitToRunning_Success() (gas: 363647) +CCIPConfig_ConfigStateMachine:test__computeNewConfigWithMeta_RunningToStaging_Success() (gas: 488774) +CCIPConfig_ConfigStateMachine:test__computeNewConfigWithMeta_StagingToRunning_Success() (gas: 453384) +CCIPConfig_ConfigStateMachine:test__groupByPluginType_TooManyOCR3Configs_Reverts() (gas: 37027) +CCIPConfig_ConfigStateMachine:test__groupByPluginType_threeCommitConfigs_Reverts() (gas: 61043) +CCIPConfig_ConfigStateMachine:test__groupByPluginType_threeExecutionConfigs_Reverts() (gas: 60963) +CCIPConfig_ConfigStateMachine:test__stateFromConfigLength_Success() (gas: 11764) +CCIPConfig_ConfigStateMachine:test__validateConfigStateTransition_Success() (gas: 8765) +CCIPConfig_ConfigStateMachine:test__validateConfigTransition_InitToRunning_Success() (gas: 311991) +CCIPConfig_ConfigStateMachine:test__validateConfigTransition_InitToRunning_WrongConfigCount_Reverts() (gas: 49663) +CCIPConfig_ConfigStateMachine:test__validateConfigTransition_NonExistentConfigTransition_Reverts() (gas: 32275) +CCIPConfig_ConfigStateMachine:test__validateConfigTransition_RunningToStaging_Success() (gas: 376576) +CCIPConfig_ConfigStateMachine:test__validateConfigTransition_RunningToStaging_WrongConfigCount_Reverts() (gas: 120943) +CCIPConfig_ConfigStateMachine:test__validateConfigTransition_RunningToStaging_WrongConfigDigestBlueGreen_Reverts() (gas: 157105) +CCIPConfig_ConfigStateMachine:test__validateConfigTransition_StagingToRunning_Success() (gas: 376352) +CCIPConfig_ConfigStateMachine:test__validateConfigTransition_StagingToRunning_WrongConfigDigest_Reverts() (gas: 157172) +CCIPConfig_ConfigStateMachine:test_getCapabilityConfiguration_Success() (gas: 9583) +CCIPConfig__updatePluginConfig:test__updatePluginConfig_InitToRunning_Success() (gas: 1057393) +CCIPConfig__updatePluginConfig:test__updatePluginConfig_InvalidConfigLength_Reverts() (gas: 27539) +CCIPConfig__updatePluginConfig:test__updatePluginConfig_InvalidConfigStateTransition_Reverts() (gas: 23105) +CCIPConfig__updatePluginConfig:test__updatePluginConfig_RunningToStaging_Success() (gas: 2009309) +CCIPConfig__updatePluginConfig:test__updatePluginConfig_StagingToRunning_Success() (gas: 2616177) +CCIPConfig__updatePluginConfig:test_getCapabilityConfiguration_Success() (gas: 9583) +CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_CommitAndExecConfig_Success() (gas: 1851188) +CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_CommitConfigOnly_Success() (gas: 1068362) +CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_ExecConfigOnly_Success() (gas: 1068393) CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_OnlyCapabilitiesRegistryCanCall_Reverts() (gas: 9599) CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_ZeroLengthConfig_Success() (gas: 16070) -CCIPConfig_beforeCapabilityConfigSet:test_getCapabilityConfiguration_Success() (gas: 9605) +CCIPConfig_beforeCapabilityConfigSet:test_getCapabilityConfiguration_Success() (gas: 9583) CCIPConfig_chainConfig:test__applyChainConfigUpdates_FChainNotPositive_Reverts() (gas: 184703) -CCIPConfig_chainConfig:test_applyChainConfigUpdates_addChainConfigs_Success() (gas: 344881) +CCIPConfig_chainConfig:test_applyChainConfigUpdates_addChainConfigs_Success() (gas: 344332) CCIPConfig_chainConfig:test_applyChainConfigUpdates_nodeNotInRegistry_Reverts() (gas: 20258) CCIPConfig_chainConfig:test_applyChainConfigUpdates_removeChainConfigs_Success() (gas: 267558) CCIPConfig_chainConfig:test_applyChainConfigUpdates_selectorNotFound_Reverts() (gas: 14829) CCIPConfig_chainConfig:test_getCapabilityConfiguration_Success() (gas: 9626) -CCIPConfig_chainConfig:test_getPaginatedCCIPConfigs_Success() (gas: 370235) -CCIPConfig_constructor:test_constructor_Success() (gas: 3612901) -CCIPConfig_constructor:test_constructor_ZeroAddressNotAllowed_Revert() (gas: 61777) -CCIPConfig_updatePluginConfig:test__updatePluginConfig_InitToRunning_Success() (gas: 1057368) -CCIPConfig_updatePluginConfig:test__updatePluginConfig_InvalidConfigLength_Reverts() (gas: 27561) -CCIPConfig_updatePluginConfig:test__updatePluginConfig_InvalidConfigStateTransition_Reverts() (gas: 23127) -CCIPConfig_updatePluginConfig:test__updatePluginConfig_RunningToStaging_Success() (gas: 2009285) -CCIPConfig_updatePluginConfig:test__updatePluginConfig_StagingToRunning_Success() (gas: 2616133) -CCIPConfig_updatePluginConfig:test_getCapabilityConfiguration_Success() (gas: 9605) CCIPConfig_validateConfig:test__validateConfig_BootstrapP2PIdsHasDuplicates_Reverts() (gas: 294893) CCIPConfig_validateConfig:test__validateConfig_BootstrapP2PIdsNotASubsetOfP2PIds_Reverts() (gas: 298325) CCIPConfig_validateConfig:test__validateConfig_BootstrapP2PIdsNotSorted_Reverts() (gas: 295038) @@ -92,22 +89,22 @@ CCIPConfig_validateConfig:test__validateConfig_Success() (gas: 302186) CCIPConfig_validateConfig:test__validateConfig_TooManyBootstrapP2PIds_Reverts() (gas: 294539) CCIPConfig_validateConfig:test__validateConfig_TooManySigners_Reverts() (gas: 1215861) CCIPConfig_validateConfig:test__validateConfig_TooManyTransmitters_Reverts() (gas: 1214264) -CCIPConfig_validateConfig:test_getCapabilityConfiguration_Success() (gas: 9584) +CCIPConfig_validateConfig:test_getCapabilityConfiguration_Success() (gas: 9562) CommitStore_constructor:test_Constructor_Success() (gas: 3091326) CommitStore_isUnpausedAndRMNHealthy:test_RMN_Success() (gas: 73420) CommitStore_report:test_InvalidIntervalMinLargerThanMax_Revert() (gas: 28670) CommitStore_report:test_InvalidInterval_Revert() (gas: 28610) CommitStore_report:test_InvalidRootRevert() (gas: 27843) -CommitStore_report:test_OnlyGasPriceUpdates_Success() (gas: 53275) -CommitStore_report:test_OnlyPriceUpdateStaleReport_Revert() (gas: 59071) -CommitStore_report:test_OnlyTokenPriceUpdates_Success() (gas: 53273) +CommitStore_report:test_OnlyGasPriceUpdates_Success() (gas: 53253) +CommitStore_report:test_OnlyPriceUpdateStaleReport_Revert() (gas: 59049) +CommitStore_report:test_OnlyTokenPriceUpdates_Success() (gas: 53251) CommitStore_report:test_Paused_Revert() (gas: 21259) -CommitStore_report:test_ReportAndPriceUpdate_Success() (gas: 84264) -CommitStore_report:test_ReportOnlyRootSuccess_gas() (gas: 56313) +CommitStore_report:test_ReportAndPriceUpdate_Success() (gas: 84242) +CommitStore_report:test_ReportOnlyRootSuccess_gas() (gas: 56249) CommitStore_report:test_RootAlreadyCommitted_Revert() (gas: 63969) -CommitStore_report:test_StaleReportWithRoot_Success() (gas: 119364) +CommitStore_report:test_StaleReportWithRoot_Success() (gas: 119420) CommitStore_report:test_Unhealthy_Revert() (gas: 44751) -CommitStore_report:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 100752) +CommitStore_report:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 100758) CommitStore_report:test_ZeroEpochAndRound_Revert() (gas: 27626) CommitStore_resetUnblessedRoots:test_OnlyOwner_Revert() (gas: 11325) CommitStore_resetUnblessedRoots:test_ResetUnblessedRoots_Success() (gas: 143718) @@ -122,193 +119,349 @@ CommitStore_verify:test_NotBlessed_Success() (gas: 61374) CommitStore_verify:test_Paused_Revert() (gas: 18496) CommitStore_verify:test_TooManyLeaves_Revert() (gas: 36785) DefensiveExampleTest:test_HappyPath_Success() (gas: 200018) -DefensiveExampleTest:test_Recovery() (gas: 424256) -E2E:test_E2E_3MessagesSuccess_gas() (gas: 1104033) -EVM2EVMOffRamp__releaseOrMintToken:test__releaseOrMintToken_NotACompatiblePool_Revert() (gas: 37797) -EVM2EVMOffRamp__releaseOrMintToken:test__releaseOrMintToken_Success() (gas: 103733) -EVM2EVMOffRamp__releaseOrMintToken:test__releaseOrMintToken_TokenHandlingError_transfer_Revert() (gas: 85258) -EVM2EVMOffRamp__releaseOrMintToken:test_releaseOrMintToken_InvalidDataLength_Revert() (gas: 36786) -EVM2EVMOffRamp__releaseOrMintToken:test_releaseOrMintToken_ReleaseOrMintBalanceMismatch_Revert() (gas: 94302) -EVM2EVMOffRamp__releaseOrMintToken:test_releaseOrMintToken_TokenHandlingError_BalanceOf_Revert() (gas: 39768) -EVM2EVMOffRamp__releaseOrMintToken:test_releaseOrMintToken_skip_ReleaseOrMintBalanceMismatch_if_pool_Revert() (gas: 86559) -EVM2EVMOffRamp__releaseOrMintTokens:test_OverValueWithARLOff_Success() (gas: 385246) -EVM2EVMOffRamp__releaseOrMintTokens:test_PriceNotFoundForToken_Reverts() (gas: 141896) -EVM2EVMOffRamp__releaseOrMintTokens:test_RateLimitErrors_Reverts() (gas: 803071) -EVM2EVMOffRamp__releaseOrMintTokens:test_TokenHandlingError_Reverts() (gas: 179244) -EVM2EVMOffRamp__releaseOrMintTokens:test__releaseOrMintTokens_NotACompatiblePool_Reverts() (gas: 29240) -EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_InvalidDataLengthReturnData_Revert() (gas: 66444) -EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_InvalidEVMAddress_Revert() (gas: 43320) -EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_Success() (gas: 210968) -EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals_Success() (gas: 222232) -EVM2EVMOffRamp__report:test_Report_Success() (gas: 126637) -EVM2EVMOffRamp__trialExecute:test_RateLimitError_Success() (gas: 237791) -EVM2EVMOffRamp__trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 246391) -EVM2EVMOffRamp__trialExecute:test_TokenPoolIsNotAContract_Success() (gas: 329828) -EVM2EVMOffRamp__trialExecute:test_trialExecute_Success() (gas: 312265) -EVM2EVMOffRamp_ccipReceive:test_Reverts() (gas: 17030) -EVM2EVMOffRamp_constructor:test_CommitStoreAlreadyInUse_Revert() (gas: 153727) -EVM2EVMOffRamp_constructor:test_Constructor_Success() (gas: 5665947) -EVM2EVMOffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 144461) -EVM2EVMOffRamp_execute:test_EmptyReport_Revert() (gas: 21318) -EVM2EVMOffRamp_execute:test_InvalidMessageId_Revert() (gas: 36432) -EVM2EVMOffRamp_execute:test_InvalidSourceChain_Revert() (gas: 51598) -EVM2EVMOffRamp_execute:test_InvalidSourcePoolAddress_Success() (gas: 473329) -EVM2EVMOffRamp_execute:test_ManualExecutionNotYetEnabled_Revert() (gas: 47668) -EVM2EVMOffRamp_execute:test_MessageTooLarge_Revert() (gas: 152359) -EVM2EVMOffRamp_execute:test_Paused_Revert() (gas: 102842) -EVM2EVMOffRamp_execute:test_ReceiverError_Success() (gas: 163804) -EVM2EVMOffRamp_execute:test_RetryFailedMessageWithoutManualExecution_Success() (gas: 178205) -EVM2EVMOffRamp_execute:test_RootNotCommitted_Revert() (gas: 42539) -EVM2EVMOffRamp_execute:test_SingleMessageNoTokensUnordered_Success() (gas: 157347) -EVM2EVMOffRamp_execute:test_SingleMessageNoTokens_Success() (gas: 172692) -EVM2EVMOffRamp_execute:test_SingleMessageToNonCCIPReceiver_Success() (gas: 247069) -EVM2EVMOffRamp_execute:test_SingleMessagesNoTokensSuccess_gas() (gas: 114153) -EVM2EVMOffRamp_execute:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 407451) -EVM2EVMOffRamp_execute:test_SkippedIncorrectNonce_Success() (gas: 54096) -EVM2EVMOffRamp_execute:test_StrictUntouchedToSuccess_Success() (gas: 131047) -EVM2EVMOffRamp_execute:test_TokenDataMismatch_Revert() (gas: 52090) -EVM2EVMOffRamp_execute:test_TwoMessagesWithTokensAndGE_Success() (gas: 563385) -EVM2EVMOffRamp_execute:test_TwoMessagesWithTokensSuccess_gas() (gas: 495508) -EVM2EVMOffRamp_execute:test_UnexpectedTokenData_Revert() (gas: 35383) -EVM2EVMOffRamp_execute:test_Unhealthy_Revert() (gas: 544641) -EVM2EVMOffRamp_execute:test_UnsupportedNumberOfTokens_Revert() (gas: 64326) -EVM2EVMOffRamp_execute:test__execute_SkippedAlreadyExecutedMessageUnordered_Success() (gas: 122322) -EVM2EVMOffRamp_execute:test__execute_SkippedAlreadyExecutedMessage_Success() (gas: 142532) -EVM2EVMOffRamp_execute:test_execute_RouterYULCall_Success() (gas: 427337) -EVM2EVMOffRamp_executeSingleMessage:test_MessageSender_Revert() (gas: 18502) -EVM2EVMOffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 278097) -EVM2EVMOffRamp_executeSingleMessage:test_NonContract_Success() (gas: 18659) -EVM2EVMOffRamp_executeSingleMessage:test_TokenHandlingError_Revert() (gas: 221421) -EVM2EVMOffRamp_executeSingleMessage:test_ZeroGasDONExecution_Revert() (gas: 47881) -EVM2EVMOffRamp_executeSingleMessage:test_executeSingleMessage_NoTokens_Success() (gas: 47352) -EVM2EVMOffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens_Success() (gas: 313917) -EVM2EVMOffRamp_executeSingleMessage:test_executeSingleMessage_ZeroGasZeroData_Success() (gas: 70008) -EVM2EVMOffRamp_execute_upgrade:test_V2NonceNewSenderStartsAtZero_Success() (gas: 229319) -EVM2EVMOffRamp_execute_upgrade:test_V2NonceStartsAtV1Nonce_Success() (gas: 276790) -EVM2EVMOffRamp_execute_upgrade:test_V2OffRampNonceSkipsIfMsgInFlight_Success() (gas: 258696) -EVM2EVMOffRamp_execute_upgrade:test_V2SenderNoncesReadsPreviousRamp_Success() (gas: 226253) -EVM2EVMOffRamp_execute_upgrade:test_V2_Success() (gas: 130745) -EVM2EVMOffRamp_getAllRateLimitTokens:test_GetAllRateLimitTokens_Success() (gas: 38446) -EVM2EVMOffRamp_getExecutionState:test_FillExecutionState_Success() (gas: 3247348) -EVM2EVMOffRamp_getExecutionState:test_GetExecutionState_Success() (gas: 83333) -EVM2EVMOffRamp_manuallyExecute:test_ManualExecFailedTx_Revert() (gas: 185829) -EVM2EVMOffRamp_manuallyExecute:test_ManualExecForkedChain_Revert() (gas: 27049) -EVM2EVMOffRamp_manuallyExecute:test_ManualExecGasLimitMismatch_Revert() (gas: 45155) -EVM2EVMOffRamp_manuallyExecute:test_ManualExecInvalidGasLimit_Revert() (gas: 27468) -EVM2EVMOffRamp_manuallyExecute:test_ManualExecWithMultipleMessagesAndSourceTokens_Success() (gas: 530151) -EVM2EVMOffRamp_manuallyExecute:test_ManualExecWithSourceTokens_Success() (gas: 345758) -EVM2EVMOffRamp_manuallyExecute:test_ManualExec_Success() (gas: 187324) -EVM2EVMOffRamp_manuallyExecute:test_ReentrancyManualExecuteFails_Success() (gas: 2321906) -EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_DestinationGasAmountCountMismatch_Revert() (gas: 362965) -EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_DoesNotRevertIfUntouched_Success() (gas: 143900) -EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_InvalidTokenGasOverride_Revert() (gas: 366104) -EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_LowGasLimitManualExec_Success() (gas: 482691) -EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_WithGasOverride_Success() (gas: 189727) -EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_WithInvalidReceiverExecutionGasOverride_Revert() (gas: 153641) -EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_WithInvalidSourceTokenDataCount_Revert() (gas: 59894) -EVM2EVMOffRamp_metadataHash:test_MetadataHash_Success() (gas: 8838) -EVM2EVMOffRamp_setDynamicConfig:test_NonOwner_Revert() (gas: 40153) -EVM2EVMOffRamp_setDynamicConfig:test_RouterZeroAddress_Revert() (gas: 38236) -EVM2EVMOffRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 141962) -EVM2EVMOffRamp_updateRateLimitTokens:test_updateRateLimitTokens_AddsAndRemoves_Success() (gas: 162525) -EVM2EVMOffRamp_updateRateLimitTokens:test_updateRateLimitTokens_NonOwner_Revert() (gas: 16690) -EVM2EVMOffRamp_updateRateLimitTokens:test_updateRateLimitTokens_Success() (gas: 197721) -EVM2EVMOnRamp_constructor:test_Constructor_Success() (gas: 5579769) +DefensiveExampleTest:test_Recovery() (gas: 424253) +E2E:test_E2E_3MessagesSuccess_gas() (gas: 1100092) +EVM2EVMMultiOffRamp__releaseOrMintSingleToken:test__releaseOrMintSingleToken_NotACompatiblePool_Revert() (gas: 38157) +EVM2EVMMultiOffRamp__releaseOrMintSingleToken:test__releaseOrMintSingleToken_Success() (gas: 108343) +EVM2EVMMultiOffRamp__releaseOrMintSingleToken:test__releaseOrMintSingleToken_TokenHandlingError_revert_Revert() (gas: 116811) +EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_AddMultipleChains_Success() (gas: 460560) +EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_AddNewChain_Success() (gas: 95542) +EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ApplyZeroUpdates_Success() (gas: 12463) +EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChainOnRamp_Revert() (gas: 90385) +EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChain_Success() (gas: 105586) +EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ZeroOnRampAddress_Revert() (gas: 15719) +EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ZeroSourceChainSelector_Revert() (gas: 13057) +EVM2EVMMultiOffRamp_batchExecute:test_MultipleReportsDifferentChains_Success() (gas: 298564) +EVM2EVMMultiOffRamp_batchExecute:test_MultipleReportsSameChain_Success() (gas: 239899) +EVM2EVMMultiOffRamp_batchExecute:test_MultipleReportsSkipDuplicate_Success() (gas: 158863) +EVM2EVMMultiOffRamp_batchExecute:test_OutOfBoundsGasLimitsAccess_Revert() (gas: 189303) +EVM2EVMMultiOffRamp_batchExecute:test_SingleReport_Success() (gas: 147582) +EVM2EVMMultiOffRamp_batchExecute:test_Unhealthy_Revert() (gas: 521508) +EVM2EVMMultiOffRamp_batchExecute:test_ZeroReports_Revert() (gas: 10459) +EVM2EVMMultiOffRamp_ccipReceive:test_Reverts() (gas: 15662) +EVM2EVMMultiOffRamp_commit:test_InvalidIntervalMinLargerThanMax_Revert() (gas: 67195) +EVM2EVMMultiOffRamp_commit:test_InvalidInterval_Revert() (gas: 59698) +EVM2EVMMultiOffRamp_commit:test_InvalidRootRevert() (gas: 58778) +EVM2EVMMultiOffRamp_commit:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6394741) +EVM2EVMMultiOffRamp_commit:test_NoConfig_Revert() (gas: 5977968) +EVM2EVMMultiOffRamp_commit:test_OnlyGasPriceUpdates_Success() (gas: 106229) +EVM2EVMMultiOffRamp_commit:test_OnlyPriceUpdateStaleReport_Revert() (gas: 116228) +EVM2EVMMultiOffRamp_commit:test_OnlyTokenPriceUpdates_Success() (gas: 106272) +EVM2EVMMultiOffRamp_commit:test_PriceSequenceNumberCleared_Success() (gas: 351414) +EVM2EVMMultiOffRamp_commit:test_ReportAndPriceUpdate_Success() (gas: 159132) +EVM2EVMMultiOffRamp_commit:test_ReportOnlyRootSuccess_gas() (gas: 136253) +EVM2EVMMultiOffRamp_commit:test_RootAlreadyCommitted_Revert() (gas: 136831) +EVM2EVMMultiOffRamp_commit:test_SourceChainNotEnabled_Revert() (gas: 59046) +EVM2EVMMultiOffRamp_commit:test_StaleReportWithRoot_Success() (gas: 227807) +EVM2EVMMultiOffRamp_commit:test_UnauthorizedTransmitter_Revert() (gas: 117527) +EVM2EVMMultiOffRamp_commit:test_Unhealthy_Revert() (gas: 77605) +EVM2EVMMultiOffRamp_commit:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 207057) +EVM2EVMMultiOffRamp_commit:test_WrongConfigWithoutSigners_Revert() (gas: 6389130) +EVM2EVMMultiOffRamp_commit:test_ZeroEpochAndRound_Revert() (gas: 47785) +EVM2EVMMultiOffRamp_constructor:test_Constructor_Success() (gas: 5981174) +EVM2EVMMultiOffRamp_constructor:test_SourceChainSelector_Revert() (gas: 157326) +EVM2EVMMultiOffRamp_constructor:test_ZeroChainSelector_Revert() (gas: 103815) +EVM2EVMMultiOffRamp_constructor:test_ZeroNonceManager_Revert() (gas: 101686) +EVM2EVMMultiOffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 159832) +EVM2EVMMultiOffRamp_constructor:test_ZeroRMNProxy_Revert() (gas: 101585) +EVM2EVMMultiOffRamp_constructor:test_ZeroTokenAdminRegistry_Revert() (gas: 101652) +EVM2EVMMultiOffRamp_execute:test_IncorrectArrayType_Revert() (gas: 17280) +EVM2EVMMultiOffRamp_execute:test_LargeBatch_Success() (gas: 1559406) +EVM2EVMMultiOffRamp_execute:test_MultipleReportsWithPartialValidationFailures_Success() (gas: 342924) +EVM2EVMMultiOffRamp_execute:test_MultipleReports_Success() (gas: 260178) +EVM2EVMMultiOffRamp_execute:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6445247) +EVM2EVMMultiOffRamp_execute:test_NoConfig_Revert() (gas: 6028193) +EVM2EVMMultiOffRamp_execute:test_NonArray_Revert() (gas: 27681) +EVM2EVMMultiOffRamp_execute:test_SingleReport_Success() (gas: 165181) +EVM2EVMMultiOffRamp_execute:test_UnauthorizedTransmitter_Revert() (gas: 149137) +EVM2EVMMultiOffRamp_execute:test_WrongConfigWithSigners_Revert() (gas: 6807322) +EVM2EVMMultiOffRamp_execute:test_ZeroReports_Revert() (gas: 17154) +EVM2EVMMultiOffRamp_executeSingleMessage:test_MessageSender_Revert() (gas: 18413) +EVM2EVMMultiOffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 249368) +EVM2EVMMultiOffRamp_executeSingleMessage:test_NonContract_Success() (gas: 20672) +EVM2EVMMultiOffRamp_executeSingleMessage:test_TokenHandlingError_Revert() (gas: 204173) +EVM2EVMMultiOffRamp_executeSingleMessage:test_ZeroGasDONExecution_Revert() (gas: 48860) +EVM2EVMMultiOffRamp_executeSingleMessage:test_executeSingleMessage_NoTokens_Success() (gas: 48381) +EVM2EVMMultiOffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidationNoRouterCall_Revert() (gas: 232798) +EVM2EVMMultiOffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidation_Revert() (gas: 89392) +EVM2EVMMultiOffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens_Success() (gas: 278146) +EVM2EVMMultiOffRamp_executeSingleMessage:test_executeSingleMessage_WithValidation_Success() (gas: 93615) +EVM2EVMMultiOffRamp_executeSingleReport:test_DisabledSourceChain_Revert() (gas: 35083) +EVM2EVMMultiOffRamp_executeSingleReport:test_EmptyReport_Revert() (gas: 23907) +EVM2EVMMultiOffRamp_executeSingleReport:test_InvalidSourcePoolAddress_Success() (gas: 451358) +EVM2EVMMultiOffRamp_executeSingleReport:test_ManualExecutionNotYetEnabled_Revert() (gas: 54475) +EVM2EVMMultiOffRamp_executeSingleReport:test_MismatchingDestChainSelector_Revert() (gas: 35917) +EVM2EVMMultiOffRamp_executeSingleReport:test_MismatchingOnRampRoot_Revert() (gas: 154369) +EVM2EVMMultiOffRamp_executeSingleReport:test_NonExistingSourceChain_Revert() (gas: 35317) +EVM2EVMMultiOffRamp_executeSingleReport:test_ReceiverError_Success() (gas: 181353) +EVM2EVMMultiOffRamp_executeSingleReport:test_RetryFailedMessageWithoutManualExecution_Revert() (gas: 190627) +EVM2EVMMultiOffRamp_executeSingleReport:test_RootNotCommitted_Revert() (gas: 48053) +EVM2EVMMultiOffRamp_executeSingleReport:test_RouterYULCall_Revert() (gas: 443030) +EVM2EVMMultiOffRamp_executeSingleReport:test_SingleMessageNoTokensOtherChain_Success() (gas: 251770) +EVM2EVMMultiOffRamp_executeSingleReport:test_SingleMessageNoTokensUnordered_Success() (gas: 173962) +EVM2EVMMultiOffRamp_executeSingleReport:test_SingleMessageNoTokens_Success() (gas: 193657) +EVM2EVMMultiOffRamp_executeSingleReport:test_SingleMessageToNonCCIPReceiver_Success() (gas: 259648) +EVM2EVMMultiOffRamp_executeSingleReport:test_SingleMessagesNoTokensSuccess_gas() (gas: 129288) +EVM2EVMMultiOffRamp_executeSingleReport:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 391710) +EVM2EVMMultiOffRamp_executeSingleReport:test_SkippedIncorrectNonce_Success() (gas: 65899) +EVM2EVMMultiOffRamp_executeSingleReport:test_TokenDataMismatch_Revert() (gas: 80955) +EVM2EVMMultiOffRamp_executeSingleReport:test_TwoMessagesWithTokensAndGE_Success() (gas: 535429) +EVM2EVMMultiOffRamp_executeSingleReport:test_TwoMessagesWithTokensSuccess_gas() (gas: 479260) +EVM2EVMMultiOffRamp_executeSingleReport:test_UnexpectedTokenData_Revert() (gas: 35763) +EVM2EVMMultiOffRamp_executeSingleReport:test_UnhealthySingleChainCurse_Revert() (gas: 520344) +EVM2EVMMultiOffRamp_executeSingleReport:test_Unhealthy_Revert() (gas: 517712) +EVM2EVMMultiOffRamp_executeSingleReport:test_WithCurseOnAnotherSourceChain_Success() (gas: 487848) +EVM2EVMMultiOffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessageUnordered_Success() (gas: 127921) +EVM2EVMMultiOffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessage_Success() (gas: 157144) +EVM2EVMMultiOffRamp_getExecutionState:test_FillExecutionState_Success() (gas: 3655340) +EVM2EVMMultiOffRamp_getExecutionState:test_GetDifferentChainExecutionState_Success() (gas: 118224) +EVM2EVMMultiOffRamp_getExecutionState:test_GetExecutionState_Success() (gas: 87461) +EVM2EVMMultiOffRamp_manuallyExecute:test_ManualExecGasLimitMismatchSingleReport_Revert() (gas: 75600) +EVM2EVMMultiOffRamp_manuallyExecute:test_ManualExecInvalidGasLimit_Revert() (gas: 26461) +EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_DoesNotRevertIfUntouched_Success() (gas: 163081) +EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_FailedTx_Revert() (gas: 207379) +EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_ForkedChain_Revert() (gas: 26004) +EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_GasLimitMismatchMultipleReports_Revert() (gas: 152867) +EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_LowGasLimit_Success() (gas: 507480) +EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_ReentrancyFails() (gas: 2307925) +EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_Success() (gas: 209633) +EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_WithGasOverride_Success() (gas: 210210) +EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_WithMultiReportGasOverride_Success() (gas: 668610) +EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_WithPartialMessages_Success() (gas: 299477) +EVM2EVMMultiOffRamp_releaseOrMintTokens:test_TokenHandlingError_Reverts() (gas: 160598) +EVM2EVMMultiOffRamp_releaseOrMintTokens:test__releaseOrMintTokens_PoolIsNotAPool_Reverts() (gas: 24131) +EVM2EVMMultiOffRamp_releaseOrMintTokens:test_releaseOrMintTokens_InvalidDataLengthReturnData_Revert() (gas: 59105) +EVM2EVMMultiOffRamp_releaseOrMintTokens:test_releaseOrMintTokens_InvalidEVMAddress_Revert() (gas: 40405) +EVM2EVMMultiOffRamp_releaseOrMintTokens:test_releaseOrMintTokens_PoolDoesNotSupportDest_Reverts() (gas: 76130) +EVM2EVMMultiOffRamp_releaseOrMintTokens:test_releaseOrMintTokens_Success() (gas: 178951) +EVM2EVMMultiOffRamp_releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals_Success() (gas: 278805) +EVM2EVMMultiOffRamp_resetUnblessedRoots:test_OnlyOwner_Revert() (gas: 11379) +EVM2EVMMultiOffRamp_resetUnblessedRoots:test_ResetUnblessedRoots_Success() (gas: 215406) +EVM2EVMMultiOffRamp_setDynamicConfig:test_NonOwner_Revert() (gas: 14374) +EVM2EVMMultiOffRamp_setDynamicConfig:test_PriceRegistryZeroAddress_Revert() (gas: 11898) +EVM2EVMMultiOffRamp_setDynamicConfig:test_RouterZeroAddress_Revert() (gas: 14054) +EVM2EVMMultiOffRamp_setDynamicConfig:test_SetDynamicConfigWithValidator_Success() (gas: 55771) +EVM2EVMMultiOffRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 33781) +EVM2EVMMultiOffRamp_trialExecute:test_RateLimitError_Success() (gas: 238004) +EVM2EVMMultiOffRamp_trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 246667) +EVM2EVMMultiOffRamp_trialExecute:test_TokenPoolIsNotAContract_Success() (gas: 299499) +EVM2EVMMultiOffRamp_trialExecute:test_trialExecute_Success() (gas: 280579) +EVM2EVMMultiOffRamp_verify:test_Blessed_Success() (gas: 176604) +EVM2EVMMultiOffRamp_verify:test_NotBlessedWrongChainSelector_Success() (gas: 178672) +EVM2EVMMultiOffRamp_verify:test_NotBlessed_Success() (gas: 141533) +EVM2EVMMultiOffRamp_verify:test_TooManyLeaves_Revert() (gas: 51508) +EVM2EVMMultiOnRamp_constructor:test_Constructor_InvalidConfigChainSelectorEqZero_Revert() (gas: 94528) +EVM2EVMMultiOnRamp_constructor:test_Constructor_InvalidConfigNonceManagerEqAddressZero_Revert() (gas: 92480) +EVM2EVMMultiOnRamp_constructor:test_Constructor_InvalidConfigRMNProxyEqAddressZero_Revert() (gas: 97483) +EVM2EVMMultiOnRamp_constructor:test_Constructor_InvalidConfigTokenAdminRegistryEqAddressZero_Revert() (gas: 92538) +EVM2EVMMultiOnRamp_constructor:test_Constructor_Success() (gas: 2260144) +EVM2EVMMultiOnRamp_forwardFromRouter:test_CannotSendZeroTokens_Revert() (gas: 90987) +EVM2EVMMultiOnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() (gas: 130983) +EVM2EVMMultiOnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2_Success() (gas: 161753) +EVM2EVMMultiOnRamp_forwardFromRouter:test_ForwardFromRouterSuccessCustomExtraArgs() (gas: 161306) +EVM2EVMMultiOnRamp_forwardFromRouter:test_ForwardFromRouterSuccessEmptyExtraArgs() (gas: 159506) +EVM2EVMMultiOnRamp_forwardFromRouter:test_ForwardFromRouterSuccessLegacyExtraArgs() (gas: 161536) +EVM2EVMMultiOnRamp_forwardFromRouter:test_ForwardFromRouter_Success() (gas: 160928) +EVM2EVMMultiOnRamp_forwardFromRouter:test_InvalidExtraArgsTag_Revert() (gas: 26206) +EVM2EVMMultiOnRamp_forwardFromRouter:test_MessageValidationError_Revert() (gas: 134082) +EVM2EVMMultiOnRamp_forwardFromRouter:test_MesssageFeeTooHigh_Revert() (gas: 24272) +EVM2EVMMultiOnRamp_forwardFromRouter:test_OriginalSender_Revert() (gas: 12819) +EVM2EVMMultiOnRamp_forwardFromRouter:test_Paused_Revert() (gas: 30695) +EVM2EVMMultiOnRamp_forwardFromRouter:test_Permissions_Revert() (gas: 15675) +EVM2EVMMultiOnRamp_forwardFromRouter:test_ShouldIncrementNonceOnlyOnOrdered_Success() (gas: 198276) +EVM2EVMMultiOnRamp_forwardFromRouter:test_ShouldIncrementSeqNumAndNonce_Success() (gas: 224545) +EVM2EVMMultiOnRamp_forwardFromRouter:test_ShouldStoreLinkFees() (gas: 140840) +EVM2EVMMultiOnRamp_forwardFromRouter:test_ShouldStoreNonLinkFees() (gas: 162262) +EVM2EVMMultiOnRamp_forwardFromRouter:test_SourceTokenDataTooLarge_Revert() (gas: 3805757) +EVM2EVMMultiOnRamp_forwardFromRouter:test_UnsupportedToken_Revert() (gas: 127615) +EVM2EVMMultiOnRamp_forwardFromRouter:test_forwardFromRouter_UnsupportedToken_Revert() (gas: 93044) +EVM2EVMMultiOnRamp_forwardFromRouter:test_forwardFromRouter_WithValidation_Success() (gas: 285076) +EVM2EVMMultiOnRamp_getFee:test_EmptyMessage_Success() (gas: 104423) +EVM2EVMMultiOnRamp_getFee:test_EnforceOutOfOrder_Revert() (gas: 74041) +EVM2EVMMultiOnRamp_getFee:test_SingleTokenMessage_Success() (gas: 119755) +EVM2EVMMultiOnRamp_getFee:test_Unhealthy_Revert() (gas: 43657) +EVM2EVMMultiOnRamp_getSupportedTokens:test_GetSupportedTokens_Revert() (gas: 10438) +EVM2EVMMultiOnRamp_getTokenPool:test_GetTokenPool_Success() (gas: 35204) +EVM2EVMMultiOnRamp_setDynamicConfig:test_SetConfigInvalidConfigFeeAggregatorEqAddressZero_Revert() (gas: 11356) +EVM2EVMMultiOnRamp_setDynamicConfig:test_SetConfigInvalidConfigPriceRegistryEqAddressZero_Revert() (gas: 12956) +EVM2EVMMultiOnRamp_setDynamicConfig:test_SetConfigInvalidConfig_Revert() (gas: 11313) +EVM2EVMMultiOnRamp_setDynamicConfig:test_SetConfigOnlyOwner_Revert() (gas: 16287) +EVM2EVMMultiOnRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 58439) +EVM2EVMMultiOnRamp_withdrawFeeTokens:test_WithdrawFeeTokens_Success() (gas: 97185) +EVM2EVMOffRamp__releaseOrMintToken:test__releaseOrMintToken_NotACompatiblePool_Revert() (gas: 38028) +EVM2EVMOffRamp__releaseOrMintToken:test__releaseOrMintToken_Success() (gas: 108191) +EVM2EVMOffRamp__releaseOrMintToken:test__releaseOrMintToken_TokenHandlingError_revert_Revert() (gas: 116732) +EVM2EVMOffRamp__releaseOrMintTokens:test_OverValueWithARLOff_Success() (gas: 391880) +EVM2EVMOffRamp__releaseOrMintTokens:test_PriceNotFoundForToken_Reverts() (gas: 145379) +EVM2EVMOffRamp__releaseOrMintTokens:test_RateLimitErrors_Reverts() (gas: 788000) +EVM2EVMOffRamp__releaseOrMintTokens:test_TokenHandlingError_Reverts() (gas: 176208) +EVM2EVMOffRamp__releaseOrMintTokens:test__releaseOrMintTokens_NotACompatiblePool_Reverts() (gas: 29700) +EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_InvalidDataLengthReturnData_Revert() (gas: 63325) +EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_InvalidEVMAddress_Revert() (gas: 44501) +EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_Success() (gas: 214151) +EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals_Success() (gas: 306912) +EVM2EVMOffRamp__report:test_Report_Success() (gas: 127459) +EVM2EVMOffRamp__trialExecute:test_RateLimitError_Success() (gas: 255047) +EVM2EVMOffRamp__trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 263638) +EVM2EVMOffRamp__trialExecute:test_TokenPoolIsNotAContract_Success() (gas: 335707) +EVM2EVMOffRamp__trialExecute:test_trialExecute_Success() (gas: 314443) +EVM2EVMOffRamp_ccipReceive:test_Reverts() (gas: 17009) +EVM2EVMOffRamp_constructor:test_CommitStoreAlreadyInUse_Revert() (gas: 153427) +EVM2EVMOffRamp_constructor:test_Constructor_Success() (gas: 5464875) +EVM2EVMOffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 144183) +EVM2EVMOffRamp_execute:test_EmptyReport_Revert() (gas: 21345) +EVM2EVMOffRamp_execute:test_InvalidMessageId_Revert() (gas: 36442) +EVM2EVMOffRamp_execute:test_InvalidSourceChain_Revert() (gas: 51701) +EVM2EVMOffRamp_execute:test_InvalidSourcePoolAddress_Success() (gas: 473575) +EVM2EVMOffRamp_execute:test_ManualExecutionNotYetEnabled_Revert() (gas: 46423) +EVM2EVMOffRamp_execute:test_MessageTooLarge_Revert() (gas: 152453) +EVM2EVMOffRamp_execute:test_Paused_Revert() (gas: 101458) +EVM2EVMOffRamp_execute:test_ReceiverError_Success() (gas: 165036) +EVM2EVMOffRamp_execute:test_RetryFailedMessageWithoutManualExecution_Revert() (gas: 177824) +EVM2EVMOffRamp_execute:test_RootNotCommitted_Revert() (gas: 41317) +EVM2EVMOffRamp_execute:test_RouterYULCall_Revert() (gas: 402506) +EVM2EVMOffRamp_execute:test_SingleMessageNoTokensUnordered_Success() (gas: 159387) +EVM2EVMOffRamp_execute:test_SingleMessageNoTokens_Success() (gas: 174622) +EVM2EVMOffRamp_execute:test_SingleMessageToNonCCIPReceiver_Success() (gas: 248634) +EVM2EVMOffRamp_execute:test_SingleMessagesNoTokensSuccess_gas() (gas: 114706) +EVM2EVMOffRamp_execute:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 409338) +EVM2EVMOffRamp_execute:test_SkippedIncorrectNonce_Success() (gas: 54173) +EVM2EVMOffRamp_execute:test_StrictUntouchedToSuccess_Success() (gas: 132056) +EVM2EVMOffRamp_execute:test_TokenDataMismatch_Revert() (gas: 52200) +EVM2EVMOffRamp_execute:test_TwoMessagesWithTokensAndGE_Success() (gas: 560178) +EVM2EVMOffRamp_execute:test_TwoMessagesWithTokensSuccess_gas() (gas: 498159) +EVM2EVMOffRamp_execute:test_UnexpectedTokenData_Revert() (gas: 35442) +EVM2EVMOffRamp_execute:test_Unhealthy_Revert() (gas: 546987) +EVM2EVMOffRamp_execute:test_UnsupportedNumberOfTokens_Revert() (gas: 64045) +EVM2EVMOffRamp_execute:test__execute_SkippedAlreadyExecutedMessageUnordered_Success() (gas: 123223) +EVM2EVMOffRamp_execute:test__execute_SkippedAlreadyExecutedMessage_Success() (gas: 143388) +EVM2EVMOffRamp_executeSingleMessage:test_MessageSender_Revert() (gas: 20582) +EVM2EVMOffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 281891) +EVM2EVMOffRamp_executeSingleMessage:test_NonContract_Success() (gas: 20231) +EVM2EVMOffRamp_executeSingleMessage:test_TokenHandlingError_Revert() (gas: 221728) +EVM2EVMOffRamp_executeSingleMessage:test_ZeroGasDONExecution_Revert() (gas: 48632) +EVM2EVMOffRamp_executeSingleMessage:test_executeSingleMessage_NoTokens_Success() (gas: 48120) +EVM2EVMOffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens_Success() (gas: 316477) +EVM2EVMOffRamp_executeSingleMessage:test_executeSingleMessage_ZeroGasZeroData_Success() (gas: 72423) +EVM2EVMOffRamp_execute_upgrade:test_V2NonceNewSenderStartsAtZero_Success() (gas: 231326) +EVM2EVMOffRamp_execute_upgrade:test_V2NonceStartsAtV1Nonce_Success() (gas: 279867) +EVM2EVMOffRamp_execute_upgrade:test_V2OffRampNonceSkipsIfMsgInFlight_Success() (gas: 261109) +EVM2EVMOffRamp_execute_upgrade:test_V2SenderNoncesReadsPreviousRamp_Success() (gas: 229397) +EVM2EVMOffRamp_execute_upgrade:test_V2_Success() (gas: 131682) +EVM2EVMOffRamp_getAllRateLimitTokens:test_GetAllRateLimitTokens_Success() (gas: 38408) +EVM2EVMOffRamp_getExecutionState:test_FillExecutionState_Success() (gas: 3213556) +EVM2EVMOffRamp_getExecutionState:test_GetExecutionState_Success() (gas: 83091) +EVM2EVMOffRamp_manuallyExecute:test_LowGasLimitManualExec_Success() (gas: 483328) +EVM2EVMOffRamp_manuallyExecute:test_ManualExecFailedTx_Revert() (gas: 186413) +EVM2EVMOffRamp_manuallyExecute:test_ManualExecForkedChain_Revert() (gas: 25824) +EVM2EVMOffRamp_manuallyExecute:test_ManualExecGasLimitMismatch_Revert() (gas: 43449) +EVM2EVMOffRamp_manuallyExecute:test_ManualExecInvalidGasLimit_Revert() (gas: 25927) +EVM2EVMOffRamp_manuallyExecute:test_ManualExecWithGasOverride_Success() (gas: 188518) +EVM2EVMOffRamp_manuallyExecute:test_ManualExec_Success() (gas: 187965) +EVM2EVMOffRamp_manuallyExecute:test_ReentrancyManualExecuteFails() (gas: 2027441) +EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_DoesNotRevertIfUntouched_Success() (gas: 143803) +EVM2EVMOffRamp_metadataHash:test_MetadataHash_Success() (gas: 8871) +EVM2EVMOffRamp_setDynamicConfig:test_NonOwner_Revert() (gas: 40429) +EVM2EVMOffRamp_setDynamicConfig:test_RouterZeroAddress_Revert() (gas: 38804) +EVM2EVMOffRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 146790) +EVM2EVMOffRamp_updateRateLimitTokens:test_updateRateLimitTokens_AddsAndRemoves_Success() (gas: 162464) +EVM2EVMOffRamp_updateRateLimitTokens:test_updateRateLimitTokens_NonOwner_Revert() (gas: 16667) +EVM2EVMOffRamp_updateRateLimitTokens:test_updateRateLimitTokens_Success() (gas: 197660) +EVM2EVMOnRamp_constructor:test_Constructor_Success() (gas: 5619710) EVM2EVMOnRamp_forwardFromRouter:test_CannotSendZeroTokens_Revert() (gas: 35778) -EVM2EVMOnRamp_forwardFromRouter:test_EnforceOutOfOrder_Revert() (gas: 98428) -EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() (gas: 114198) -EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2_Success() (gas: 114240) -EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterSuccessCustomExtraArgs() (gas: 130207) -EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterSuccessLegacyExtraArgs() (gas: 138653) -EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouter_Success() (gas: 129829) -EVM2EVMOnRamp_forwardFromRouter:test_InvalidAddressEncodePacked_Revert() (gas: 38257) -EVM2EVMOnRamp_forwardFromRouter:test_InvalidAddress_Revert() (gas: 38440) -EVM2EVMOnRamp_forwardFromRouter:test_InvalidChainSelector_Revert() (gas: 25489) -EVM2EVMOnRamp_forwardFromRouter:test_InvalidExtraArgsTag_Revert() (gas: 25275) -EVM2EVMOnRamp_forwardFromRouter:test_MaxCapacityExceeded_Revert() (gas: 86013) +EVM2EVMOnRamp_forwardFromRouter:test_EnforceOutOfOrder_Revert() (gas: 99470) +EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() (gas: 114210) +EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2_Success() (gas: 114252) +EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterSuccessCustomExtraArgs() (gas: 130118) +EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterSuccessLegacyExtraArgs() (gas: 138650) +EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouter_Success() (gas: 129804) +EVM2EVMOnRamp_forwardFromRouter:test_InvalidAddressEncodePacked_Revert() (gas: 38254) +EVM2EVMOnRamp_forwardFromRouter:test_InvalidAddress_Revert() (gas: 38370) +EVM2EVMOnRamp_forwardFromRouter:test_InvalidChainSelector_Revert() (gas: 25511) +EVM2EVMOnRamp_forwardFromRouter:test_InvalidExtraArgsTag_Revert() (gas: 25297) +EVM2EVMOnRamp_forwardFromRouter:test_MaxCapacityExceeded_Revert() (gas: 86041) EVM2EVMOnRamp_forwardFromRouter:test_MaxFeeBalanceReached_Revert() (gas: 36457) -EVM2EVMOnRamp_forwardFromRouter:test_MessageGasLimitTooHigh_Revert() (gas: 29015) -EVM2EVMOnRamp_forwardFromRouter:test_MessageTooLarge_Revert() (gas: 107571) -EVM2EVMOnRamp_forwardFromRouter:test_OriginalSender_Revert() (gas: 22679) -EVM2EVMOnRamp_forwardFromRouter:test_OverValueWithARLOff_Success() (gas: 224619) -EVM2EVMOnRamp_forwardFromRouter:test_Paused_Revert() (gas: 53072) +EVM2EVMOnRamp_forwardFromRouter:test_MessageGasLimitTooHigh_Revert() (gas: 29037) +EVM2EVMOnRamp_forwardFromRouter:test_MessageTooLarge_Revert() (gas: 107526) +EVM2EVMOnRamp_forwardFromRouter:test_OriginalSender_Revert() (gas: 22635) +EVM2EVMOnRamp_forwardFromRouter:test_OverValueWithARLOff_Success() (gas: 226165) +EVM2EVMOnRamp_forwardFromRouter:test_Paused_Revert() (gas: 53935) EVM2EVMOnRamp_forwardFromRouter:test_Permissions_Revert() (gas: 25481) -EVM2EVMOnRamp_forwardFromRouter:test_PriceNotFoundForToken_Revert() (gas: 59341) -EVM2EVMOnRamp_forwardFromRouter:test_ShouldIncrementNonceOnlyOnOrdered_Success() (gas: 179148) -EVM2EVMOnRamp_forwardFromRouter:test_ShouldIncrementSeqNumAndNonce_Success() (gas: 177430) -EVM2EVMOnRamp_forwardFromRouter:test_ShouldStoreNonLinkFees() (gas: 137254) -EVM2EVMOnRamp_forwardFromRouter:test_SourceTokenDataTooLarge_Revert() (gas: 3822827) +EVM2EVMOnRamp_forwardFromRouter:test_PriceNotFoundForToken_Revert() (gas: 59303) +EVM2EVMOnRamp_forwardFromRouter:test_ShouldIncrementNonceOnlyOnOrdered_Success() (gas: 179141) +EVM2EVMOnRamp_forwardFromRouter:test_ShouldIncrementSeqNumAndNonce_Success() (gas: 177355) +EVM2EVMOnRamp_forwardFromRouter:test_ShouldStoreNonLinkFees() (gas: 137297) +EVM2EVMOnRamp_forwardFromRouter:test_SourceTokenDataTooLarge_Revert() (gas: 3734267) EVM2EVMOnRamp_forwardFromRouter:test_TooManyTokens_Revert() (gas: 30187) EVM2EVMOnRamp_forwardFromRouter:test_Unhealthy_Revert() (gas: 43300) -EVM2EVMOnRamp_forwardFromRouter:test_UnsupportedToken_Revert() (gas: 109305) -EVM2EVMOnRamp_forwardFromRouter:test_ZeroAddressReceiver_Revert() (gas: 312579) -EVM2EVMOnRamp_forwardFromRouter:test_forwardFromRouter_ShouldStoreLinkFees_Success() (gas: 112322) -EVM2EVMOnRamp_forwardFromRouter:test_forwardFromRouter_UnsupportedToken_Revert() (gas: 72206) -EVM2EVMOnRamp_forwardFromRouter:test_forwardFromRouter_correctSourceTokenData_Success() (gas: 710475) -EVM2EVMOnRamp_forwardFromRouter_upgrade:test_V2NonceNewSenderStartsAtZero_Success() (gas: 147664) -EVM2EVMOnRamp_forwardFromRouter_upgrade:test_V2NonceStartsAtV1Nonce_Success() (gas: 190529) -EVM2EVMOnRamp_forwardFromRouter_upgrade:test_V2SenderNoncesReadsPreviousRamp_Success() (gas: 121320) -EVM2EVMOnRamp_forwardFromRouter_upgrade:test_V2_Success() (gas: 95349) -EVM2EVMOnRamp_getDataAvailabilityCost:test_EmptyMessageCalculatesDataAvailabilityCost_Success() (gas: 20544) -EVM2EVMOnRamp_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCost_Success() (gas: 20912) -EVM2EVMOnRamp_getFee:test_EmptyMessage_Success() (gas: 78230) -EVM2EVMOnRamp_getFee:test_GetFeeOfZeroForTokenMessage_Success() (gas: 81762) -EVM2EVMOnRamp_getFee:test_HighGasMessage_Success() (gas: 234078) +EVM2EVMOnRamp_forwardFromRouter:test_UnsupportedToken_Revert() (gas: 109258) +EVM2EVMOnRamp_forwardFromRouter:test_ZeroAddressReceiver_Revert() (gas: 312351) +EVM2EVMOnRamp_forwardFromRouter:test_forwardFromRouter_ShouldStoreLinkFees_Success() (gas: 112319) +EVM2EVMOnRamp_forwardFromRouter:test_forwardFromRouter_UnsupportedToken_Revert() (gas: 72181) +EVM2EVMOnRamp_forwardFromRouter_upgrade:test_V2NonceNewSenderStartsAtZero_Success() (gas: 147614) +EVM2EVMOnRamp_forwardFromRouter_upgrade:test_V2NonceStartsAtV1Nonce_Success() (gas: 190454) +EVM2EVMOnRamp_forwardFromRouter_upgrade:test_V2SenderNoncesReadsPreviousRamp_Success() (gas: 121245) +EVM2EVMOnRamp_forwardFromRouter_upgrade:test_V2_Success() (gas: 95324) +EVM2EVMOnRamp_getDataAvailabilityCost:test_EmptyMessageCalculatesDataAvailabilityCost_Success() (gas: 20760) +EVM2EVMOnRamp_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCost_Success() (gas: 21128) +EVM2EVMOnRamp_getFee:test_EmptyMessage_Success() (gas: 78242) +EVM2EVMOnRamp_getFee:test_HighGasMessage_Success() (gas: 234090) EVM2EVMOnRamp_getFee:test_MessageGasLimitTooHigh_Revert() (gas: 16715) EVM2EVMOnRamp_getFee:test_MessageTooLarge_Revert() (gas: 95271) -EVM2EVMOnRamp_getFee:test_MessageWithDataAndTokenTransfer_Success() (gas: 159436) +EVM2EVMOnRamp_getFee:test_MessageWithDataAndTokenTransfer_Success() (gas: 159220) EVM2EVMOnRamp_getFee:test_NotAFeeToken_Revert() (gas: 24089) -EVM2EVMOnRamp_getFee:test_SingleTokenMessage_Success() (gas: 117922) +EVM2EVMOnRamp_getFee:test_SingleTokenMessage_Success() (gas: 117858) EVM2EVMOnRamp_getFee:test_TooManyTokens_Revert() (gas: 19902) -EVM2EVMOnRamp_getFee:test_ZeroDataAvailabilityMultiplier_Success() (gas: 64648) +EVM2EVMOnRamp_getFee:test_ZeroDataAvailabilityMultiplier_Success() (gas: 65663) EVM2EVMOnRamp_getSupportedTokens:test_GetSupportedTokens_Revert() (gas: 10460) EVM2EVMOnRamp_getTokenPool:test_GetTokenPool_Success() (gas: 35195) -EVM2EVMOnRamp_getTokenTransferCost:test_CustomTokenBpsFee_Success() (gas: 45120) -EVM2EVMOnRamp_getTokenTransferCost:test_FeeTokenBpsFee_Success() (gas: 33019) +EVM2EVMOnRamp_getTokenTransferCost:test_CustomTokenBpsFee_Success() (gas: 45037) +EVM2EVMOnRamp_getTokenTransferCost:test_FeeTokenBpsFee_Success() (gas: 33041) EVM2EVMOnRamp_getTokenTransferCost:test_LargeTokenTransferChargesMaxFeeAndGas_Success() (gas: 28296) -EVM2EVMOnRamp_getTokenTransferCost:test_MixedTokenTransferFee_Success() (gas: 126453) -EVM2EVMOnRamp_getTokenTransferCost:test_NoTokenTransferChargesZeroFee_Success() (gas: 15238) +EVM2EVMOnRamp_getTokenTransferCost:test_MixedTokenTransferFee_Success() (gas: 130189) +EVM2EVMOnRamp_getTokenTransferCost:test_NoTokenTransferChargesZeroFee_Success() (gas: 15260) EVM2EVMOnRamp_getTokenTransferCost:test_SmallTokenTransferChargesMinFeeAndGas_Success() (gas: 28104) EVM2EVMOnRamp_getTokenTransferCost:test_UnsupportedToken_Revert() (gas: 21248) -EVM2EVMOnRamp_getTokenTransferCost:test_ZeroAmountTokenTransferChargesMinFeeAndGas_Success() (gas: 28127) -EVM2EVMOnRamp_getTokenTransferCost:test_ZeroFeeConfigChargesMinFee_Success() (gas: 38599) -EVM2EVMOnRamp_getTokenTransferCost:test__getTokenTransferCost_selfServeUsesDefaults_Success() (gas: 29404) +EVM2EVMOnRamp_getTokenTransferCost:test_WETHTokenBpsFee_Success() (gas: 38922) +EVM2EVMOnRamp_getTokenTransferCost:test_ZeroAmountTokenTransferChargesMinFeeAndGas_Success() (gas: 28149) +EVM2EVMOnRamp_getTokenTransferCost:test_ZeroFeeConfigChargesMinFee_Success() (gas: 38615) +EVM2EVMOnRamp_getTokenTransferCost:test__getTokenTransferCost_selfServeUsesDefaults_Success() (gas: 29527) EVM2EVMOnRamp_linkAvailableForPayment:test_InsufficientLinkBalance_Success() (gas: 32615) EVM2EVMOnRamp_linkAvailableForPayment:test_LinkAvailableForPayment_Success() (gas: 134833) -EVM2EVMOnRamp_payNops:test_AdminPayNops_Success() (gas: 143159) -EVM2EVMOnRamp_payNops:test_InsufficientBalance_Revert() (gas: 26543) +EVM2EVMOnRamp_payNops:test_AdminPayNops_Success() (gas: 143054) +EVM2EVMOnRamp_payNops:test_InsufficientBalance_Revert() (gas: 29043) EVM2EVMOnRamp_payNops:test_NoFeesToPay_Revert() (gas: 127367) EVM2EVMOnRamp_payNops:test_NoNopsToPay_Revert() (gas: 133251) -EVM2EVMOnRamp_payNops:test_NopPayNops_Success() (gas: 146446) -EVM2EVMOnRamp_payNops:test_OwnerPayNops_Success() (gas: 141021) -EVM2EVMOnRamp_payNops:test_PayNopsSuccessAfterSetNops() (gas: 297510) +EVM2EVMOnRamp_payNops:test_NopPayNops_Success() (gas: 146341) +EVM2EVMOnRamp_payNops:test_OwnerPayNops_Success() (gas: 140916) +EVM2EVMOnRamp_payNops:test_PayNopsSuccessAfterSetNops() (gas: 297485) EVM2EVMOnRamp_payNops:test_WrongPermissions_Revert() (gas: 15294) -EVM2EVMOnRamp_setDynamicConfig:test_SetConfigInvalidConfig_Revert() (gas: 42365) -EVM2EVMOnRamp_setDynamicConfig:test_SetConfigOnlyOwner_Revert() (gas: 21246) -EVM2EVMOnRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 53764) +EVM2EVMOnRamp_setDynamicConfig:test_SetConfigInvalidConfig_Revert() (gas: 43376) +EVM2EVMOnRamp_setDynamicConfig:test_SetConfigOnlyOwner_Revert() (gas: 21646) +EVM2EVMOnRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 55086) EVM2EVMOnRamp_setFeeTokenConfig:test_OnlyCallableByOwnerOrAdmin_Revert() (gas: 13464) EVM2EVMOnRamp_setFeeTokenConfig:test_SetFeeTokenConfigByAdmin_Success() (gas: 16449) EVM2EVMOnRamp_setFeeTokenConfig:test_SetFeeTokenConfig_Success() (gas: 13994) EVM2EVMOnRamp_setNops:test_AdminCanSetNops_Success() (gas: 61759) -EVM2EVMOnRamp_setNops:test_IncludesPayment_Success() (gas: 469227) +EVM2EVMOnRamp_setNops:test_IncludesPayment_Success() (gas: 469097) EVM2EVMOnRamp_setNops:test_LinkTokenCannotBeNop_Revert() (gas: 57255) EVM2EVMOnRamp_setNops:test_NonOwnerOrAdmin_Revert() (gas: 14665) -EVM2EVMOnRamp_setNops:test_NotEnoughFundsForPayout_Revert() (gas: 84480) +EVM2EVMOnRamp_setNops:test_NotEnoughFundsForPayout_Revert() (gas: 84455) EVM2EVMOnRamp_setNops:test_SetNopsRemovesOldNopsCompletely_Success() (gas: 60637) -EVM2EVMOnRamp_setNops:test_SetNops_Success() (gas: 173782) +EVM2EVMOnRamp_setNops:test_SetNops_Success() (gas: 173677) EVM2EVMOnRamp_setNops:test_TooManyNops_Revert() (gas: 190338) EVM2EVMOnRamp_setNops:test_ZeroAddressCannotBeNop_Revert() (gas: 53596) -EVM2EVMOnRamp_setTokenTransferFeeConfig:test__setTokenTransferFeeConfig_InvalidDestBytesOverhead_Revert() (gas: 14499) +EVM2EVMOnRamp_setTokenTransferFeeConfig:test__setTokenTransferFeeConfig_InvalidDestBytesOverhead_Revert() (gas: 14493) EVM2EVMOnRamp_setTokenTransferFeeConfig:test__setTokenTransferFeeConfig_OnlyCallableByOwnerOrAdmin_Revert() (gas: 14277) -EVM2EVMOnRamp_setTokenTransferFeeConfig:test__setTokenTransferFeeConfig_Success() (gas: 84029) +EVM2EVMOnRamp_setTokenTransferFeeConfig:test__setTokenTransferFeeConfig_Success() (gas: 84017) EVM2EVMOnRamp_setTokenTransferFeeConfig:test__setTokenTransferFeeConfig_byAdmin_Success() (gas: 17369) -EVM2EVMOnRamp_withdrawNonLinkFees:test_LinkBalanceNotSettled_Revert() (gas: 83005) +EVM2EVMOnRamp_withdrawNonLinkFees:test_LinkBalanceNotSettled_Revert() (gas: 82980) EVM2EVMOnRamp_withdrawNonLinkFees:test_NonOwnerOrAdmin_Revert() (gas: 15275) -EVM2EVMOnRamp_withdrawNonLinkFees:test_SettlingBalance_Success() (gas: 272035) +EVM2EVMOnRamp_withdrawNonLinkFees:test_SettlingBalance_Success() (gas: 272015) EVM2EVMOnRamp_withdrawNonLinkFees:test_WithdrawNonLinkFees_Success() (gas: 53446) EVM2EVMOnRamp_withdrawNonLinkFees:test_WithdrawToZeroAddress_Revert() (gas: 12830) EtherSenderReceiverTest_ccipReceive:test_ccipReceive_fallbackToWethTransfer() (gas: 96729) -EtherSenderReceiverTest_ccipReceive:test_ccipReceive_happyPath() (gas: 47688) +EtherSenderReceiverTest_ccipReceive:test_ccipReceive_happyPath() (gas: 49688) EtherSenderReceiverTest_ccipReceive:test_ccipReceive_wrongToken() (gas: 17384) EtherSenderReceiverTest_ccipReceive:test_ccipReceive_wrongTokenAmount() (gas: 15677) EtherSenderReceiverTest_ccipSend:test_ccipSend_reverts_insufficientFee_feeToken() (gas: 99741) @@ -328,158 +481,38 @@ EtherSenderReceiverTest_validatedMessage:test_validatedMessage_emptyDataOverwrit EtherSenderReceiverTest_validatedMessage:test_validatedMessage_invalidTokenAmounts() (gas: 17895) EtherSenderReceiverTest_validatedMessage:test_validatedMessage_tokenOverwrittenToWeth() (gas: 25287) EtherSenderReceiverTest_validatedMessage:test_validatedMessage_validMessage_extraArgs() (gas: 26292) -FeeQuoter_applyDestChainConfigUpdates:test_InvalidChainFamilySelector_Revert() (gas: 16503) -FeeQuoter_applyDestChainConfigUpdates:test_InvalidDestChainConfigDestChainSelectorEqZero_Revert() (gas: 16417) -FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesDefaultTxGasLimitEqZero_Revert() (gas: 16459) -FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesDefaultTxGasLimitGtMaxPerMessageGasLimit_Revert() (gas: 39957) -FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesZeroIntput_Success() (gas: 12342) -FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdates_Success() (gas: 135870) -FeeQuoter_applyFeeTokensUpdates:test_ApplyFeeTokensUpdates_Success() (gas: 79896) -FeeQuoter_applyFeeTokensUpdates:test_OnlyCallableByOwner_Revert() (gas: 12603) -FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_OnlyCallableByOwnerOrAdmin_Revert() (gas: 11421) -FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesMultipleTokens_Success() (gas: 54105) -FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesSingleToken_Success() (gas: 44791) -FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesZeroInput() (gas: 12257) -FeeQuoter_applyTokenTransferFeeConfigUpdates:test_ApplyTokenTransferFeeConfig_Success() (gas: 86926) -FeeQuoter_applyTokenTransferFeeConfigUpdates:test_ApplyTokenTransferFeeZeroInput() (gas: 13089) -FeeQuoter_applyTokenTransferFeeConfigUpdates:test_InvalidDestBytesOverhead_Revert() (gas: 17071) -FeeQuoter_applyTokenTransferFeeConfigUpdates:test_OnlyCallableByOwnerOrAdmin_Revert() (gas: 12240) -FeeQuoter_constructor:test_InvalidLinkTokenEqZeroAddress_Revert() (gas: 107046) -FeeQuoter_constructor:test_InvalidMaxFeeJuelsPerMsg_Revert() (gas: 111396) -FeeQuoter_constructor:test_InvalidStalenessThreshold_Revert() (gas: 111449) -FeeQuoter_constructor:test_Setup_Success() (gas: 5358690) -FeeQuoter_convertTokenAmount:test_ConvertTokenAmount_Success() (gas: 72739) -FeeQuoter_convertTokenAmount:test_LinkTokenNotSupported_Revert() (gas: 30963) -FeeQuoter_getDataAvailabilityCost:test_EmptyMessageCalculatesDataAvailabilityCost_Success() (gas: 94303) -FeeQuoter_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCostUnsupportedDestChainSelector_Success() (gas: 14614) -FeeQuoter_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCost_Success() (gas: 20410) -FeeQuoter_getTokenAndGasPrices:test_GetFeeTokenAndGasPrices_Success() (gas: 70443) -FeeQuoter_getTokenAndGasPrices:test_StaleGasPrice_Revert() (gas: 16838) -FeeQuoter_getTokenAndGasPrices:test_UnsupportedChain_Revert() (gas: 16140) -FeeQuoter_getTokenAndGasPrices:test_ZeroGasPrice_Success() (gas: 45750) -FeeQuoter_getTokenPrice:test_GetTokenPriceFromFeed_Success() (gas: 62252) -FeeQuoter_getTokenPrices:test_GetTokenPrices_Success() (gas: 84800) -FeeQuoter_getTokenTransferCost:test_CustomTokenBpsFee_Success() (gas: 41227) -FeeQuoter_getTokenTransferCost:test_FeeTokenBpsFee_Success() (gas: 34682) -FeeQuoter_getTokenTransferCost:test_LargeTokenTransferChargesMaxFeeAndGas_Success() (gas: 27756) -FeeQuoter_getTokenTransferCost:test_MixedTokenTransferFee_Success() (gas: 101624) -FeeQuoter_getTokenTransferCost:test_NoTokenTransferChargesZeroFee_Success() (gas: 20354) -FeeQuoter_getTokenTransferCost:test_SmallTokenTransferChargesMinFeeAndGas_Success() (gas: 27631) -FeeQuoter_getTokenTransferCost:test_ZeroAmountTokenTransferChargesMinFeeAndGas_Success() (gas: 27587) -FeeQuoter_getTokenTransferCost:test_ZeroFeeConfigChargesMinFee_Success() (gas: 40013) -FeeQuoter_getTokenTransferCost:test_getTokenTransferCost_selfServeUsesDefaults_Success() (gas: 29299) -FeeQuoter_getValidatedFee:test_DestinationChainNotEnabled_Revert() (gas: 18180) -FeeQuoter_getValidatedFee:test_EmptyMessage_Success() (gas: 85936) -FeeQuoter_getValidatedFee:test_EnforceOutOfOrder_Revert() (gas: 56735) -FeeQuoter_getValidatedFee:test_HighGasMessage_Success() (gas: 242354) -FeeQuoter_getValidatedFee:test_InvalidEVMAddress_Revert() (gas: 22390) -FeeQuoter_getValidatedFee:test_MessageGasLimitTooHigh_Revert() (gas: 34187) -FeeQuoter_getValidatedFee:test_MessageTooLarge_Revert() (gas: 100133) -FeeQuoter_getValidatedFee:test_MessageWithDataAndTokenTransfer_Success() (gas: 147715) -FeeQuoter_getValidatedFee:test_NotAFeeToken_Revert() (gas: 21043) -FeeQuoter_getValidatedFee:test_SingleTokenMessage_Success() (gas: 116743) -FeeQuoter_getValidatedFee:test_TooManyTokens_Revert() (gas: 22526) -FeeQuoter_getValidatedFee:test_ZeroDataAvailabilityMultiplier_Success() (gas: 64374) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Above18Decimals_Success() (gas: 2094539) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Below18Decimals_Success() (gas: 2094497) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt0Decimals_Success() (gas: 2074616) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt18Decimals_Success() (gas: 2094271) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFlippedDecimals_Success() (gas: 2094475) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedMaxInt224Value_Success() (gas: 2094287) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedOverStalenessPeriod_Success() (gas: 62004) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeed_Success() (gas: 61884) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPrice_Success() (gas: 61036) -FeeQuoter_getValidatedTokenPrice:test_OverflowFeedPrice_Revert() (gas: 2093974) -FeeQuoter_getValidatedTokenPrice:test_StaleFeeToken_Success() (gas: 61563) -FeeQuoter_getValidatedTokenPrice:test_TokenNotSupportedFeed_Revert() (gas: 109120) -FeeQuoter_getValidatedTokenPrice:test_TokenNotSupported_Revert() (gas: 13857) -FeeQuoter_getValidatedTokenPrice:test_UnderflowFeedPrice_Revert() (gas: 2092636) -FeeQuoter_onReport:test_OnReport_StaleUpdate_Revert() (gas: 43334) -FeeQuoter_onReport:test_onReport_InvalidForwarder_Reverts() (gas: 23294) -FeeQuoter_onReport:test_onReport_Success() (gas: 80639) -FeeQuoter_onReport:test_onReport_UnsupportedToken_Reverts() (gas: 26677) -FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsDefault_Success() (gas: 17185) -FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsEnforceOutOfOrder_Revert() (gas: 21290) -FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsGasLimitTooHigh_Revert() (gas: 18387) -FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsInvalidExtraArgsTag_Revert() (gas: 17911) -FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsV1_Success() (gas: 18285) -FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsV2_Success() (gas: 18401) -FeeQuoter_processMessageArgs:test_InvalidExtraArgs_Revert() (gas: 18361) -FeeQuoter_processMessageArgs:test_MalformedEVMExtraArgs_Revert() (gas: 18907) -FeeQuoter_processMessageArgs:test_MessageFeeTooHigh_Revert() (gas: 16426) -FeeQuoter_processMessageArgs:test_WitEVMExtraArgsV2_Success() (gas: 26269) -FeeQuoter_processMessageArgs:test_WithConvertedTokenAmount_Success() (gas: 32441) -FeeQuoter_processMessageArgs:test_WithEVMExtraArgsV1_Success() (gas: 25881) -FeeQuoter_processMessageArgs:test_WithEmptyEVMExtraArgs_Success() (gas: 23696) -FeeQuoter_processMessageArgs:test_WithLinkTokenAmount_Success() (gas: 17375) -FeeQuoter_updatePrices:test_OnlyCallableByUpdater_Revert() (gas: 12102) -FeeQuoter_updatePrices:test_OnlyGasPrice_Success() (gas: 23599) -FeeQuoter_updatePrices:test_OnlyTokenPrice_Success() (gas: 30631) -FeeQuoter_updatePrices:test_UpdatableByAuthorizedCaller_Success() (gas: 76003) -FeeQuoter_updatePrices:test_UpdateMultiplePrices_Success() (gas: 151393) -FeeQuoter_updateTokenPriceFeeds:test_FeedNotUpdated() (gas: 50527) -FeeQuoter_updateTokenPriceFeeds:test_FeedUnset_Success() (gas: 63626) -FeeQuoter_updateTokenPriceFeeds:test_FeedUpdatedByNonOwner_Revert() (gas: 19932) -FeeQuoter_updateTokenPriceFeeds:test_MultipleFeedUpdate_Success() (gas: 88972) -FeeQuoter_updateTokenPriceFeeds:test_SingleFeedUpdate_Success() (gas: 50821) -FeeQuoter_updateTokenPriceFeeds:test_ZeroFeeds_Success() (gas: 12296) -FeeQuoter_validateDestFamilyAddress:test_InvalidEVMAddressEncodePacked_Revert() (gas: 10616) -FeeQuoter_validateDestFamilyAddress:test_InvalidEVMAddressPrecompiles_Revert() (gas: 3961646) -FeeQuoter_validateDestFamilyAddress:test_InvalidEVMAddress_Revert() (gas: 10800) -FeeQuoter_validateDestFamilyAddress:test_ValidEVMAddress_Success() (gas: 6704) -FeeQuoter_validateDestFamilyAddress:test_ValidNonEVMAddress_Success() (gas: 6484) -FeeQuoter_validatePoolReturnData:test_InvalidEVMAddressDestToken_Revert() (gas: 42748) -FeeQuoter_validatePoolReturnData:test_ProcessPoolReturnData_Success() (gas: 73252) -FeeQuoter_validatePoolReturnData:test_SourceTokenDataTooLarge_Revert() (gas: 107744) -FeeQuoter_validatePoolReturnData:test_TokenAmountArraysMismatching_Revert() (gas: 40091) -HybridUSDCTokenPoolMigrationTests:test_LockOrBurn_LocKReleaseMechanism_then_switchToPrimary_Success() (gas: 208137) -HybridUSDCTokenPoolMigrationTests:test_LockOrBurn_PrimaryMechanism_Success() (gas: 135392) -HybridUSDCTokenPoolMigrationTests:test_LockOrBurn_WhileMigrationPause_Revert() (gas: 106624) -HybridUSDCTokenPoolMigrationTests:test_LockOrBurn_onLockReleaseMechanism_Success() (gas: 143884) -HybridUSDCTokenPoolMigrationTests:test_MintOrRelease_OnLockReleaseMechanism_Success() (gas: 230399) -HybridUSDCTokenPoolMigrationTests:test_MintOrRelease_OnLockReleaseMechanism_then_switchToPrimary_Success() (gas: 438259) -HybridUSDCTokenPoolMigrationTests:test_MintOrRelease_incomingMessageWithPrimaryMechanism() (gas: 269968) -HybridUSDCTokenPoolMigrationTests:test_burnLockedUSDC_invalidPermissions_Revert() (gas: 39124) -HybridUSDCTokenPoolMigrationTests:test_cancelExistingCCTPMigrationProposal() (gas: 31124) -HybridUSDCTokenPoolMigrationTests:test_cannotCancelANonExistentMigrationProposal() (gas: 12628) -HybridUSDCTokenPoolMigrationTests:test_cannotModifyLiquidityWithoutPermissions_Revert() (gas: 17133) -HybridUSDCTokenPoolMigrationTests:test_lockOrBurn_then_BurnInCCTPMigration_Success() (gas: 252432) -HybridUSDCTokenPoolMigrationTests:test_transferLiquidity_Success() (gas: 157049) -HybridUSDCTokenPoolMigrationTests:test_withdrawLiquidity_Success() (gas: 140780) -HybridUSDCTokenPoolTests:test_LockOrBurn_LocKReleaseMechanism_then_switchToPrimary_Success() (gas: 208102) -HybridUSDCTokenPoolTests:test_LockOrBurn_PrimaryMechanism_Success() (gas: 135365) -HybridUSDCTokenPoolTests:test_LockOrBurn_WhileMigrationPause_Revert() (gas: 106589) -HybridUSDCTokenPoolTests:test_LockOrBurn_onLockReleaseMechanism_Success() (gas: 143832) -HybridUSDCTokenPoolTests:test_MintOrRelease_OnLockReleaseMechanism_Success() (gas: 230365) -HybridUSDCTokenPoolTests:test_MintOrRelease_OnLockReleaseMechanism_then_switchToPrimary_Success() (gas: 438171) -HybridUSDCTokenPoolTests:test_MintOrRelease_incomingMessageWithPrimaryMechanism() (gas: 269912) -HybridUSDCTokenPoolTests:test_withdrawLiquidity_Success() (gas: 140774) +LockReleaseTokenPoolAndProxy_setRateLimitAdmin:test_SetRateLimitAdmin_Revert() (gas: 11058) +LockReleaseTokenPoolAndProxy_setRateLimitAdmin:test_SetRateLimitAdmin_Success() (gas: 35097) LockReleaseTokenPoolAndProxy_setRebalancer:test_SetRebalancer_Revert() (gas: 10970) -LockReleaseTokenPoolAndProxy_setRebalancer:test_SetRebalancer_Success() (gas: 17992) -LockReleaseTokenPoolPoolAndProxy_canAcceptLiquidity:test_CanAcceptLiquidity_Success() (gas: 3368110) -LockReleaseTokenPoolPoolAndProxy_provideLiquidity:test_LiquidityNotAccepted_Revert() (gas: 3364509) +LockReleaseTokenPoolAndProxy_setRebalancer:test_SetRebalancer_Success() (gas: 18036) +LockReleaseTokenPoolPoolAndProxy_canAcceptLiquidity:test_CanAcceptLiquidity_Success() (gas: 3313980) +LockReleaseTokenPoolPoolAndProxy_provideLiquidity:test_LiquidityNotAccepted_Revert() (gas: 3310379) LockReleaseTokenPoolPoolAndProxy_provideLiquidity:test_Unauthorized_Revert() (gas: 11380) +LockReleaseTokenPoolPoolAndProxy_setChainRateLimiterConfig:test_NonExistentChain_Revert() (gas: 17135) +LockReleaseTokenPoolPoolAndProxy_setChainRateLimiterConfig:test_OnlyOwnerOrRateLimitAdmin_Revert() (gas: 69142) +LockReleaseTokenPoolPoolAndProxy_setChainRateLimiterConfig:test_OnlyOwner_Revert() (gas: 17319) LockReleaseTokenPoolPoolAndProxy_supportsInterface:test_SupportsInterface_Success() (gas: 9977) LockReleaseTokenPoolPoolAndProxy_withdrawalLiquidity:test_InsufficientLiquidity_Revert() (gas: 60043) LockReleaseTokenPoolPoolAndProxy_withdrawalLiquidity:test_Unauthorized_Revert() (gas: 11355) -LockReleaseTokenPool_canAcceptLiquidity:test_CanAcceptLiquidity_Success() (gas: 3124819) +LockReleaseTokenPool_canAcceptLiquidity:test_CanAcceptLiquidity_Success() (gas: 3067883) LockReleaseTokenPool_lockOrBurn:test_LockOrBurnWithAllowList_Revert() (gas: 29942) LockReleaseTokenPool_lockOrBurn:test_LockOrBurnWithAllowList_Success() (gas: 79844) LockReleaseTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 59464) -LockReleaseTokenPool_provideLiquidity:test_LiquidityNotAccepted_Revert() (gas: 3121261) +LockReleaseTokenPool_provideLiquidity:test_LiquidityNotAccepted_Revert() (gas: 3064325) LockReleaseTokenPool_provideLiquidity:test_Unauthorized_Revert() (gas: 11380) -LockReleaseTokenPool_releaseOrMint:test_ChainNotAllowed_Revert() (gas: 72644) -LockReleaseTokenPool_releaseOrMint:test_PoolMintNotHealthy_Revert() (gas: 56196) -LockReleaseTokenPool_releaseOrMint:test_ReleaseOrMint_Success() (gas: 225108) +LockReleaseTokenPool_releaseOrMint:test_ChainNotAllowed_Revert() (gas: 72662) +LockReleaseTokenPool_releaseOrMint:test_PoolMintNotHealthy_Revert() (gas: 56131) +LockReleaseTokenPool_releaseOrMint:test_ReleaseOrMint_Success() (gas: 238673) +LockReleaseTokenPool_setChainRateLimiterConfig:test_NonExistentChain_Revert() (gas: 17102) +LockReleaseTokenPool_setChainRateLimiterConfig:test_OnlyOwnerOrRateLimitAdmin_Revert() (gas: 69075) +LockReleaseTokenPool_setChainRateLimiterConfig:test_OnlyOwner_Revert() (gas: 17297) +LockReleaseTokenPool_setRateLimitAdmin:test_SetRateLimitAdmin_Revert() (gas: 11057) +LockReleaseTokenPool_setRateLimitAdmin:test_SetRateLimitAdmin_Success() (gas: 35140) LockReleaseTokenPool_setRebalancer:test_SetRebalancer_Revert() (gas: 10992) -LockReleaseTokenPool_setRebalancer:test_SetRebalancer_Success() (gas: 18058) +LockReleaseTokenPool_setRebalancer:test_SetRebalancer_Success() (gas: 17926) LockReleaseTokenPool_supportsInterface:test_SupportsInterface_Success() (gas: 9977) -LockReleaseTokenPool_transferLiquidity:test_transferLiquidity_Success() (gas: 83171) -LockReleaseTokenPool_transferLiquidity:test_transferLiquidity_transferTooMuch_Revert() (gas: 55878) LockReleaseTokenPool_withdrawalLiquidity:test_InsufficientLiquidity_Revert() (gas: 60043) LockReleaseTokenPool_withdrawalLiquidity:test_Unauthorized_Revert() (gas: 11355) -LockRelease_setRateLimitAdmin:test_SetRateLimitAdmin_Revert() (gas: 11029) -LockRelease_setRateLimitAdmin:test_SetRateLimitAdmin_Success() (gas: 35030) MerkleMultiProofTest:test_CVE_2023_34459() (gas: 5451) MerkleMultiProofTest:test_EmptyLeaf_Revert() (gas: 3552) MerkleMultiProofTest:test_MerkleRoot256() (gas: 394876) @@ -499,42 +532,42 @@ MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_UpdateExistingConfi MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_UpdateExistingConfig_Success() (gas: 53092) MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_ZeroChainSelector_Revert() (gas: 17019) MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_ZeroConfigs_Success() (gas: 12295) -MultiAggregateRateLimiter_constructor:test_ConstructorNoAuthorizedCallers_Success() (gas: 2149547) -MultiAggregateRateLimiter_constructor:test_Constructor_Success() (gas: 2265849) +MultiAggregateRateLimiter_constructor:test_ConstructorNoAuthorizedCallers_Success() (gas: 1971805) +MultiAggregateRateLimiter_constructor:test_Constructor_Success() (gas: 2085252) MultiAggregateRateLimiter_getTokenBucket:test_GetTokenBucket_Success() (gas: 30248) MultiAggregateRateLimiter_getTokenBucket:test_Refill_Success() (gas: 47358) MultiAggregateRateLimiter_getTokenBucket:test_TimeUnderflow_Revert() (gas: 15821) -MultiAggregateRateLimiter_getTokenValue:test_GetTokenValue_Success() (gas: 19662) -MultiAggregateRateLimiter_getTokenValue:test_NoTokenPrice_Reverts() (gas: 21247) +MultiAggregateRateLimiter_getTokenValue:test_GetTokenValue_Success() (gas: 19668) +MultiAggregateRateLimiter_getTokenValue:test_NoTokenPrice_Reverts() (gas: 21253) MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageFromUnauthorizedCaller_Revert() (gas: 14527) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithDifferentTokensOnDifferentChains_Success() (gas: 213638) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithDisabledRateLimitToken_Success() (gas: 60437) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithDifferentTokensOnDifferentChains_Success() (gas: 189450) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithDisabledRateLimitToken_Success() (gas: 59927) MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithNoTokens_Success() (gas: 17593) MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitDisabled_Success() (gas: 44895) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitExceeded_Revert() (gas: 50542) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitReset_Success() (gas: 78668) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithTokensOnDifferentChains_Success() (gas: 311927) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithTokens_Success() (gas: 54728) -MultiAggregateRateLimiter_onOutboundMessage:test_RateLimitValueDifferentLanes_Success() (gas: 9223372036854754743) -MultiAggregateRateLimiter_onOutboundMessage:test_ValidateMessageWithNoTokens_Success() (gas: 19149) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageFromUnauthorizedCaller_Revert() (gas: 15823) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithDifferentTokensOnDifferentChains_Success() (gas: 213716) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithDisabledRateLimitToken_Success() (gas: 62217) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitDisabled_Success() (gas: 46728) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitExceeded_Revert() (gas: 52360) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitReset_Success() (gas: 79913) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithTokensOnDifferentChains_Success() (gas: 312231) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithTokens_Success() (gas: 56530) -MultiAggregateRateLimiter_setFeeQuoter:test_OnlyOwner_Revert() (gas: 11313) -MultiAggregateRateLimiter_setFeeQuoter:test_Owner_Success() (gas: 19066) -MultiAggregateRateLimiter_setFeeQuoter:test_ZeroAddress_Revert() (gas: 10585) -MultiAggregateRateLimiter_updateRateLimitTokens:test_NonOwner_Revert() (gas: 18850) -MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokensMultipleChains_Success() (gas: 279972) -MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokensSingleChain_Success() (gas: 254523) -MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokens_AddsAndRemoves_Success() (gas: 204488) -MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokens_RemoveNonExistentToken_Success() (gas: 28703) -MultiAggregateRateLimiter_updateRateLimitTokens:test_ZeroDestToken_Revert() (gas: 18287) -MultiAggregateRateLimiter_updateRateLimitTokens:test_ZeroSourceToken_Revert() (gas: 18216) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitExceeded_Revert() (gas: 50598) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitReset_Success() (gas: 78780) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithTokensOnDifferentChains_Success() (gas: 263510) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithTokens_Success() (gas: 54784) +MultiAggregateRateLimiter_onOutboundMessage:test_RateLimitValueDifferentLanes_Success() (gas: 1073667518) +MultiAggregateRateLimiter_onOutboundMessage:test_ValidateMessageWithNoTokens_Success() (gas: 19104) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageFromUnauthorizedCaller_Revert() (gas: 15778) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithDifferentTokensOnDifferentChains_Success() (gas: 189438) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithDisabledRateLimitToken_Success() (gas: 61662) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitDisabled_Success() (gas: 46683) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitExceeded_Revert() (gas: 52371) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitReset_Success() (gas: 79845) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithTokensOnDifferentChains_Success() (gas: 263724) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithTokens_Success() (gas: 56541) +MultiAggregateRateLimiter_setPriceRegistry:test_OnlyOwner_Revert() (gas: 11336) +MultiAggregateRateLimiter_setPriceRegistry:test_Owner_Success() (gas: 19124) +MultiAggregateRateLimiter_setPriceRegistry:test_ZeroAddress_Revert() (gas: 10608) +MultiAggregateRateLimiter_updateRateLimitTokens:test_NonOwner_Revert() (gas: 16085) +MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokensMultipleChains_Success() (gas: 225643) +MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokensSingleChain_Success() (gas: 200192) +MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokens_AddsAndRemoves_Success() (gas: 162053) +MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokens_RemoveNonExistentToken_Success() (gas: 28509) +MultiAggregateRateLimiter_updateRateLimitTokens:test_ZeroDestToken_Revert() (gas: 17430) +MultiAggregateRateLimiter_updateRateLimitTokens:test_ZeroSourceToken_Revert() (gas: 17485) MultiOCR3Base_setOCR3Configs:test_FMustBePositive_Revert() (gas: 59331) MultiOCR3Base_setOCR3Configs:test_FTooHigh_Revert() (gas: 44298) MultiOCR3Base_setOCR3Configs:test_RepeatSignerAddress_Revert() (gas: 283711) @@ -557,38 +590,37 @@ MultiOCR3Base_transmit:test_InsufficientSignatures_Revert() (gas: 76930) MultiOCR3Base_transmit:test_NonUniqueSignature_Revert() (gas: 66127) MultiOCR3Base_transmit:test_SignatureOutOfRegistration_Revert() (gas: 33419) MultiOCR3Base_transmit:test_TooManySignatures_Revert() (gas: 79521) -MultiOCR3Base_transmit:test_TransmitSigners_gas_Success() (gas: 34131) +MultiOCR3Base_transmit:test_TransmitSigners_gas_Success() (gas: 34020) MultiOCR3Base_transmit:test_TransmitWithExtraCalldataArgs_Revert() (gas: 47114) MultiOCR3Base_transmit:test_TransmitWithLessCalldataArgs_Revert() (gas: 25682) -MultiOCR3Base_transmit:test_TransmitWithoutSignatureVerification_gas_Success() (gas: 18726) +MultiOCR3Base_transmit:test_TransmitWithoutSignatureVerification_gas_Success() (gas: 18714) MultiOCR3Base_transmit:test_UnAuthorizedTransmitter_Revert() (gas: 24191) MultiOCR3Base_transmit:test_UnauthorizedSigner_Revert() (gas: 61409) MultiOCR3Base_transmit:test_UnconfiguredPlugin_Revert() (gas: 39890) MultiOCR3Base_transmit:test_ZeroSignatures_Revert() (gas: 32973) -MultiOnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 414301) -MultiRampsE2E:test_E2E_3MessagesMMultiOffRampSuccess_gas() (gas: 1506106) +MultiOnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 412349) +MultiRampsE2E:test_E2E_3MessagesSuccess_gas() (gas: 1423227) NonceManager_NonceIncrementation:test_getIncrementedOutboundNonce_Success() (gas: 37907) NonceManager_NonceIncrementation:test_incrementInboundNonce_Skip() (gas: 23694) NonceManager_NonceIncrementation:test_incrementInboundNonce_Success() (gas: 38763) NonceManager_NonceIncrementation:test_incrementNoncesInboundAndOutbound_Success() (gas: 71847) -NonceManager_OffRampUpgrade:test_NoPrevOffRampForChain_Success() (gas: 260262) -NonceManager_OffRampUpgrade:test_UpgradedNonceNewSenderStartsAtZero_Success() (gas: 262359) -NonceManager_OffRampUpgrade:test_UpgradedNonceStartsAtV1Nonce_Success() (gas: 326051) -NonceManager_OffRampUpgrade:test_UpgradedOffRampNonceSkipsIfMsgInFlight_Success() (gas: 298263) -NonceManager_OffRampUpgrade:test_UpgradedSenderNoncesReadsPreviousRampTransitive_Success() (gas: 244814) -NonceManager_OffRampUpgrade:test_UpgradedSenderNoncesReadsPreviousRamp_Success() (gas: 233069) -NonceManager_OffRampUpgrade:test_Upgraded_Success() (gas: 153186) -NonceManager_OnRampUpgrade:test_UpgradeNonceNewSenderStartsAtZero_Success() (gas: 168681) -NonceManager_OnRampUpgrade:test_UpgradeNonceStartsAtV1Nonce_Success() (gas: 220836) -NonceManager_OnRampUpgrade:test_UpgradeSenderNoncesReadsPreviousRamp_Success() (gas: 125070) -NonceManager_OnRampUpgrade:test_Upgrade_Success() (gas: 107910) -NonceManager_applyPreviousRampsUpdates:test_MultipleRampsUpdates() (gas: 122943) +NonceManager_OffRampUpgrade:test_NoPrevOffRampForChain_Success() (gas: 252566) +NonceManager_OffRampUpgrade:test_UpgradedNonceNewSenderStartsAtZero_Success() (gas: 254866) +NonceManager_OffRampUpgrade:test_UpgradedNonceStartsAtV1Nonce_Success() (gas: 307885) +NonceManager_OffRampUpgrade:test_UpgradedOffRampNonceSkipsIfMsgInFlight_Success() (gas: 290962) +NonceManager_OffRampUpgrade:test_UpgradedSenderNoncesReadsPreviousRampTransitive_Success() (gas: 247990) +NonceManager_OffRampUpgrade:test_UpgradedSenderNoncesReadsPreviousRamp_Success() (gas: 236024) +NonceManager_OffRampUpgrade:test_Upgraded_Success() (gas: 144774) +NonceManager_OnRampUpgrade:test_UpgradeNonceNewSenderStartsAtZero_Success() (gas: 186669) +NonceManager_OnRampUpgrade:test_UpgradeNonceStartsAtV1Nonce_Success() (gas: 237737) +NonceManager_OnRampUpgrade:test_UpgradeSenderNoncesReadsPreviousRamp_Success() (gas: 124995) +NonceManager_OnRampUpgrade:test_Upgrade_Success() (gas: 125923) +NonceManager_applyPreviousRampsUpdates:test_MultipleRampsUpdates() (gas: 122899) NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySetOffRamp_Revert() (gas: 42959) NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySetOnRampAndOffRamp_Revert() (gas: 64282) NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySetOnRamp_Revert() (gas: 42823) -NonceManager_applyPreviousRampsUpdates:test_SingleRampUpdate() (gas: 66570) +NonceManager_applyPreviousRampsUpdates:test_SingleRampUpdate() (gas: 66548) NonceManager_applyPreviousRampsUpdates:test_ZeroInput() (gas: 12025) -NonceManager_typeAndVersion:test_typeAndVersion() (gas: 9675) OCR2BaseNoChecks_setOCR2Config:test_FMustBePositive_Revert() (gas: 12171) OCR2BaseNoChecks_setOCR2Config:test_RepeatAddress_Revert() (gas: 42233) OCR2BaseNoChecks_setOCR2Config:test_SetConfigSuccess_gas() (gas: 84124) @@ -596,7 +628,7 @@ OCR2BaseNoChecks_setOCR2Config:test_TooManyTransmitter_Revert() (gas: 36938) OCR2BaseNoChecks_setOCR2Config:test_TransmitterCannotBeZeroAddress_Revert() (gas: 24158) OCR2BaseNoChecks_transmit:test_ConfigDigestMismatch_Revert() (gas: 17448) OCR2BaseNoChecks_transmit:test_ForkedChain_Revert() (gas: 26726) -OCR2BaseNoChecks_transmit:test_TransmitSuccess_gas() (gas: 27478) +OCR2BaseNoChecks_transmit:test_TransmitSuccess_gas() (gas: 27466) OCR2BaseNoChecks_transmit:test_UnAuthorizedTransmitter_Revert() (gas: 21296) OCR2Base_setOCR2Config:test_FMustBePositive_Revert() (gas: 12189) OCR2Base_setOCR2Config:test_FTooHigh_Revert() (gas: 12345) @@ -610,196 +642,116 @@ OCR2Base_transmit:test_ConfigDigestMismatch_Revert() (gas: 19623) OCR2Base_transmit:test_ForkedChain_Revert() (gas: 37683) OCR2Base_transmit:test_NonUniqueSignature_Revert() (gas: 55309) OCR2Base_transmit:test_SignatureOutOfRegistration_Revert() (gas: 20962) -OCR2Base_transmit:test_Transmit2SignersSuccess_gas() (gas: 51686) +OCR2Base_transmit:test_Transmit2SignersSuccess_gas() (gas: 51674) OCR2Base_transmit:test_UnAuthorizedTransmitter_Revert() (gas: 23484) OCR2Base_transmit:test_UnauthorizedSigner_Revert() (gas: 39665) OCR2Base_transmit:test_WrongNumberOfSignatures_Revert() (gas: 20557) -OffRamp__releaseOrMintSingleToken:test__releaseOrMintSingleToken_NotACompatiblePool_Revert() (gas: 40149) -OffRamp__releaseOrMintSingleToken:test__releaseOrMintSingleToken_Success() (gas: 107130) -OffRamp__releaseOrMintSingleToken:test__releaseOrMintSingleToken_TokenHandlingError_transfer_Revert() (gas: 88331) -OffRamp__releaseOrMintSingleToken:test_releaseOrMintToken_InvalidDataLength_Revert() (gas: 39848) -OffRamp__releaseOrMintSingleToken:test_releaseOrMintToken_ReleaseOrMintBalanceMismatch_Revert() (gas: 97399) -OffRamp__releaseOrMintSingleToken:test_releaseOrMintToken_TokenHandlingError_BalanceOf_Revert() (gas: 42843) -OffRamp__releaseOrMintSingleToken:test_releaseOrMintToken_skip_ReleaseOrMintBalanceMismatch_if_pool_Revert() (gas: 89579) -OffRamp_applySourceChainConfigUpdates:test_AddMultipleChains_Success() (gas: 467917) -OffRamp_applySourceChainConfigUpdates:test_AddNewChain_Success() (gas: 99183) -OffRamp_applySourceChainConfigUpdates:test_ApplyZeroUpdates_Success() (gas: 12395) -OffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChainOnRamp_Revert() (gas: 93181) -OffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChain_Success() (gas: 109824) -OffRamp_applySourceChainConfigUpdates:test_RouterAddress_Revert() (gas: 13263) -OffRamp_applySourceChainConfigUpdates:test_ZeroOnRampAddress_Revert() (gas: 17988) -OffRamp_applySourceChainConfigUpdates:test_ZeroSourceChainSelector_Revert() (gas: 15300) -OffRamp_batchExecute:test_MultipleReportsDifferentChains_Success() (gas: 322171) -OffRamp_batchExecute:test_MultipleReportsSameChain_Success() (gas: 263506) -OffRamp_batchExecute:test_MultipleReportsSkipDuplicate_Success() (gas: 169162) -OffRamp_batchExecute:test_OutOfBoundsGasLimitsAccess_Revert() (gas: 188589) -OffRamp_batchExecute:test_SingleReport_Success() (gas: 156230) -OffRamp_batchExecute:test_Unhealthy_Revert() (gas: 533834) -OffRamp_batchExecute:test_ZeroReports_Revert() (gas: 10461) -OffRamp_ccipReceive:test_Reverts() (gas: 15773) -OffRamp_commit:test_InvalidIntervalMinLargerThanMax_Revert() (gas: 67458) -OffRamp_commit:test_InvalidInterval_Revert() (gas: 59778) -OffRamp_commit:test_InvalidRootRevert() (gas: 58858) -OffRamp_commit:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6560573) -OffRamp_commit:test_NoConfig_Revert() (gas: 6143711) -OffRamp_commit:test_OnlyGasPriceUpdates_Success() (gas: 106317) -OffRamp_commit:test_OnlyPriceUpdateStaleReport_Revert() (gas: 116369) -OffRamp_commit:test_OnlyTokenPriceUpdates_Success() (gas: 106338) -OffRamp_commit:test_PriceSequenceNumberCleared_Success() (gas: 351652) -OffRamp_commit:test_ReportAndPriceUpdate_Success() (gas: 159342) -OffRamp_commit:test_ReportOnlyRootSuccess_gas() (gas: 136480) -OffRamp_commit:test_RootAlreadyCommitted_Revert() (gas: 136880) -OffRamp_commit:test_SourceChainNotEnabled_Revert() (gas: 59126) -OffRamp_commit:test_StaleReportWithRoot_Success() (gas: 225582) -OffRamp_commit:test_UnauthorizedTransmitter_Revert() (gas: 117632) -OffRamp_commit:test_Unhealthy_Revert() (gas: 77674) -OffRamp_commit:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 205066) -OffRamp_commit:test_WrongConfigWithoutSigners_Revert() (gas: 6554962) -OffRamp_commit:test_ZeroEpochAndRound_Revert() (gas: 47832) -OffRamp_constructor:test_Constructor_Success() (gas: 6147616) -OffRamp_constructor:test_SourceChainSelector_Revert() (gas: 137128) -OffRamp_constructor:test_ZeroChainSelector_Revert() (gas: 103845) -OffRamp_constructor:test_ZeroNonceManager_Revert() (gas: 101716) -OffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 139680) -OffRamp_constructor:test_ZeroRMNProxy_Revert() (gas: 101593) -OffRamp_constructor:test_ZeroTokenAdminRegistry_Revert() (gas: 101660) -OffRamp_execute:test_IncorrectArrayType_Revert() (gas: 17305) -OffRamp_execute:test_LargeBatch_Success() (gas: 1828972) -OffRamp_execute:test_MultipleReportsWithPartialValidationFailures_Success() (gas: 358063) -OffRamp_execute:test_MultipleReports_Success() (gas: 285617) -OffRamp_execute:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6611685) -OffRamp_execute:test_NoConfig_Revert() (gas: 6194563) -OffRamp_execute:test_NonArray_Revert() (gas: 27809) -OffRamp_execute:test_SingleReport_Success() (gas: 175620) -OffRamp_execute:test_UnauthorizedTransmitter_Revert() (gas: 147848) -OffRamp_execute:test_WrongConfigWithSigners_Revert() (gas: 6973803) -OffRamp_execute:test_ZeroReports_Revert() (gas: 17225) -OffRamp_executeSingleMessage:test_MessageSender_Revert() (gas: 18257) -OffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 249037) -OffRamp_executeSingleMessage:test_NonContract_Success() (gas: 20517) -OffRamp_executeSingleMessage:test_TokenHandlingError_Revert() (gas: 207676) -OffRamp_executeSingleMessage:test_ZeroGasDONExecution_Revert() (gas: 48779) -OffRamp_executeSingleMessage:test_executeSingleMessage_NoTokens_Success() (gas: 48302) -OffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidationNoRouterCall_Revert() (gas: 229565) -OffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidation_Revert() (gas: 86203) -OffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens_Success() (gas: 280859) -OffRamp_executeSingleMessage:test_executeSingleMessage_WithValidation_Success() (gas: 92437) -OffRamp_executeSingleReport:test_DisabledSourceChain_Revert() (gas: 35104) -OffRamp_executeSingleReport:test_EmptyReport_Revert() (gas: 23923) -OffRamp_executeSingleReport:test_InvalidSourcePoolAddress_Success() (gas: 492333) -OffRamp_executeSingleReport:test_ManualExecutionNotYetEnabled_Revert() (gas: 54457) -OffRamp_executeSingleReport:test_MismatchingDestChainSelector_Revert() (gas: 35927) -OffRamp_executeSingleReport:test_MismatchingOnRampRoot_Revert() (gas: 154493) -OffRamp_executeSingleReport:test_NonExistingSourceChain_Revert() (gas: 35338) -OffRamp_executeSingleReport:test_ReceiverError_Success() (gas: 187911) -OffRamp_executeSingleReport:test_RetryFailedMessageWithoutManualExecution_Revert() (gas: 199215) -OffRamp_executeSingleReport:test_RootNotCommitted_Revert() (gas: 48096) -OffRamp_executeSingleReport:test_RouterYULCall_Revert() (gas: 447759) -OffRamp_executeSingleReport:test_SingleMessageNoTokensOtherChain_Success() (gas: 251078) -OffRamp_executeSingleReport:test_SingleMessageNoTokensUnordered_Success() (gas: 193345) -OffRamp_executeSingleReport:test_SingleMessageNoTokens_Success() (gas: 212938) -OffRamp_executeSingleReport:test_SingleMessageToNonCCIPReceiver_Success() (gas: 266576) -OffRamp_executeSingleReport:test_SingleMessagesNoTokensSuccess_gas() (gas: 141488) -OffRamp_executeSingleReport:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 423378) -OffRamp_executeSingleReport:test_SkippedIncorrectNonce_Success() (gas: 65877) -OffRamp_executeSingleReport:test_TokenDataMismatch_Revert() (gas: 80932) -OffRamp_executeSingleReport:test_TwoMessagesWithTokensAndGE_Success() (gas: 587410) -OffRamp_executeSingleReport:test_TwoMessagesWithTokensSuccess_gas() (gas: 536450) -OffRamp_executeSingleReport:test_UnexpectedTokenData_Revert() (gas: 35743) -OffRamp_executeSingleReport:test_UnhealthySingleChainCurse_Revert() (gas: 532474) -OffRamp_executeSingleReport:test_Unhealthy_Revert() (gas: 529798) -OffRamp_executeSingleReport:test_WithCurseOnAnotherSourceChain_Success() (gas: 495040) -OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessageUnordered_Success() (gas: 136580) -OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessage_Success() (gas: 165799) -OffRamp_getExecutionState:test_FillExecutionState_Success() (gas: 3742124) -OffRamp_getExecutionState:test_GetDifferentChainExecutionState_Success() (gas: 118836) -OffRamp_getExecutionState:test_GetExecutionState_Success() (gas: 88048) -OffRamp_manuallyExecute:test_ManualExecGasLimitMismatchSingleReport_Revert() (gas: 75551) -OffRamp_manuallyExecute:test_ManualExecInvalidGasLimit_Revert() (gas: 26439) -OffRamp_manuallyExecute:test_manuallyExecute_DoesNotRevertIfUntouched_Success() (gas: 171639) -OffRamp_manuallyExecute:test_manuallyExecute_FailedTx_Revert() (gas: 205796) -OffRamp_manuallyExecute:test_manuallyExecute_ForkedChain_Revert() (gas: 25993) -OffRamp_manuallyExecute:test_manuallyExecute_GasLimitMismatchMultipleReports_Revert() (gas: 152822) -OffRamp_manuallyExecute:test_manuallyExecute_LowGasLimit_Success() (gas: 524603) -OffRamp_manuallyExecute:test_manuallyExecute_ReentrancyFails_Success() (gas: 2388943) -OffRamp_manuallyExecute:test_manuallyExecute_Success() (gas: 208553) -OffRamp_manuallyExecute:test_manuallyExecute_WithGasOverride_Success() (gas: 219343) -OffRamp_manuallyExecute:test_manuallyExecute_WithMultiReportGasOverride_Success() (gas: 663643) -OffRamp_manuallyExecute:test_manuallyExecute_WithPartialMessages_Success() (gas: 330148) -OffRamp_releaseOrMintTokens:test_TokenHandlingError_Reverts() (gas: 165822) -OffRamp_releaseOrMintTokens:test__releaseOrMintTokens_PoolIsNotAPool_Reverts() (gas: 24603) -OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_InvalidDataLengthReturnData_Revert() (gas: 66285) -OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_InvalidEVMAddress_Revert() (gas: 41316) -OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_PoolDoesNotSupportDest_Reverts() (gas: 83291) -OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_Success() (gas: 177934) -OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals_Success() (gas: 191136) -OffRamp_resetUnblessedRoots:test_OnlyOwner_Revert() (gas: 11423) -OffRamp_resetUnblessedRoots:test_ResetUnblessedRoots_Success() (gas: 215373) -OffRamp_setDynamicConfig:test_FeeQuoterZeroAddress_Revert() (gas: 11585) -OffRamp_setDynamicConfig:test_NonOwner_Revert() (gas: 14152) -OffRamp_setDynamicConfig:test_SetDynamicConfigWithValidator_Success() (gas: 49115) -OffRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 27037) -OffRamp_trialExecute:test_RateLimitError_Success() (gas: 225795) -OffRamp_trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 234416) -OffRamp_trialExecute:test_TokenPoolIsNotAContract_Success() (gas: 309206) -OffRamp_trialExecute:test_trialExecute_Success() (gas: 283994) -OffRamp_verify:test_Blessed_Success() (gas: 176664) -OffRamp_verify:test_NotBlessedWrongChainSelector_Success() (gas: 178754) -OffRamp_verify:test_NotBlessed_Success() (gas: 141593) -OffRamp_verify:test_TooManyLeaves_Revert() (gas: 51510) -OnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 390336) -OnRamp_allowListConfigUpdates:test_applyAllowList_Revert() (gas: 66509) -OnRamp_allowListConfigUpdates:test_applyAllowList_Success() (gas: 323566) -OnRamp_applyDestChainConfigUpdates:test_ApplyDestChainConfigUpdates_Success() (gas: 64501) -OnRamp_applyDestChainConfigUpdates:test_ApplyDestChainConfigUpdates_WithInvalidChainSelector_Revert() (gas: 13242) -OnRamp_constructor:test_Constructor_InvalidConfigChainSelectorEqZero_Revert() (gas: 94878) -OnRamp_constructor:test_Constructor_InvalidConfigNonceManagerEqAddressZero_Revert() (gas: 92812) -OnRamp_constructor:test_Constructor_InvalidConfigRMNProxyEqAddressZero_Revert() (gas: 97827) -OnRamp_constructor:test_Constructor_InvalidConfigTokenAdminRegistryEqAddressZero_Revert() (gas: 92870) -OnRamp_constructor:test_Constructor_Success() (gas: 2866937) -OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() (gas: 115250) -OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2_Success() (gas: 146019) -OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessCustomExtraArgs() (gas: 145615) -OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessEmptyExtraArgs() (gas: 143816) -OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessLegacyExtraArgs() (gas: 145847) -OnRamp_forwardFromRouter:test_ForwardFromRouter_Success() (gas: 145216) -OnRamp_forwardFromRouter:test_ForwardFromRouter_Success_ConfigurableSourceRouter() (gas: 140359) -OnRamp_forwardFromRouter:test_InvalidExtraArgsTag_Revert() (gas: 28810) -OnRamp_forwardFromRouter:test_MessageValidationError_Revert() (gas: 138683) -OnRamp_forwardFromRouter:test_MesssageFeeTooHigh_Revert() (gas: 26910) -OnRamp_forwardFromRouter:test_MultiCannotSendZeroTokens_Revert() (gas: 74456) -OnRamp_forwardFromRouter:test_OriginalSender_Revert() (gas: 12918) -OnRamp_forwardFromRouter:test_Paused_Revert() (gas: 37224) -OnRamp_forwardFromRouter:test_Permissions_Revert() (gas: 18179) -OnRamp_forwardFromRouter:test_ShouldIncrementNonceOnlyOnOrdered_Success() (gas: 185252) -OnRamp_forwardFromRouter:test_ShouldIncrementSeqNumAndNonce_Success() (gas: 211543) -OnRamp_forwardFromRouter:test_ShouldStoreLinkFees() (gas: 125128) -OnRamp_forwardFromRouter:test_ShouldStoreNonLinkFees() (gas: 146530) -OnRamp_forwardFromRouter:test_SourceTokenDataTooLarge_Revert() (gas: 3891732) -OnRamp_forwardFromRouter:test_UnAllowedOriginalSender_Revert() (gas: 18609) -OnRamp_forwardFromRouter:test_UnsupportedToken_Revert() (gas: 111118) -OnRamp_forwardFromRouter:test_forwardFromRouter_UnsupportedToken_Revert() (gas: 76545) -OnRamp_forwardFromRouter:test_forwardFromRouter_WithValidation_Success() (gas: 278740) -OnRamp_getFee:test_EmptyMessage_Success() (gas: 110107) -OnRamp_getFee:test_EnforceOutOfOrder_Revert() (gas: 75610) -OnRamp_getFee:test_GetFeeOfZeroForTokenMessage_Success() (gas: 95456) -OnRamp_getFee:test_NotAFeeTokenButPricedToken_Revert() (gas: 41814) -OnRamp_getFee:test_SingleTokenMessage_Success() (gas: 125476) -OnRamp_getFee:test_Unhealthy_Revert() (gas: 43669) -OnRamp_getSupportedTokens:test_GetSupportedTokens_Revert() (gas: 10438) -OnRamp_getTokenPool:test_GetTokenPool_Success() (gas: 35204) -OnRamp_setDynamicConfig:test_SetConfigInvalidConfigFeeAggregatorEqAddressZero_Revert() (gas: 11402) -OnRamp_setDynamicConfig:test_SetConfigInvalidConfigFeeQuoterEqAddressZero_Revert() (gas: 13001) -OnRamp_setDynamicConfig:test_SetConfigInvalidConfig_Revert() (gas: 11359) -OnRamp_setDynamicConfig:test_SetConfigOnlyOwner_Revert() (gas: 16385) -OnRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 55321) -OnRamp_withdrawFeeTokens:test_WithdrawFeeTokens_Success() (gas: 97107) -PingPong_ccipReceive:test_CcipReceive_Success() (gas: 150169) -PingPong_plumbing:test_OutOfOrderExecution_Success() (gas: 20277) -PingPong_plumbing:test_Pausing_Success() (gas: 17777) -PingPong_startPingPong:test_StartPingPong_With_OOO_Success() (gas: 163187) -PingPong_startPingPong:test_StartPingPong_With_Sequenced_Ordered_Success() (gas: 182599) -RMNHome:test() (gas: 186) +OnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 380360) +PingPong_ccipReceive:test_CcipReceive_Success() (gas: 150880) +PingPong_plumbing:test_Pausing_Success() (gas: 17803) +PingPong_startPingPong:test_StartPingPong_Success() (gas: 178340) +PriceRegistry_applyDestChainConfigUpdates:test_InvalidChainFamilySelector_Revert() (gas: 16719) +PriceRegistry_applyDestChainConfigUpdates:test_InvalidDestBytesOverhead_Revert() (gas: 16784) +PriceRegistry_applyDestChainConfigUpdates:test_InvalidDestChainConfigDestChainSelectorEqZero_Revert() (gas: 16611) +PriceRegistry_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesDefaultTxGasLimitEqZero_Revert() (gas: 16675) +PriceRegistry_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesDefaultTxGasLimitGtMaxPerMessageGasLimit_Revert() (gas: 40953) +PriceRegistry_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesZeroIntput_Success() (gas: 12341) +PriceRegistry_applyDestChainConfigUpdates:test_applyDestChainConfigUpdates_Success() (gas: 139564) +PriceRegistry_applyFeeTokensUpdates:test_ApplyFeeTokensUpdates_Success() (gas: 80002) +PriceRegistry_applyFeeTokensUpdates:test_OnlyCallableByOwner_Revert() (gas: 12603) +PriceRegistry_applyPremiumMultiplierWeiPerEthUpdates:test_OnlyCallableByOwnerOrAdmin_Revert() (gas: 11465) +PriceRegistry_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesMultipleTokens_Success() (gas: 54149) +PriceRegistry_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesSingleToken_Success() (gas: 44835) +PriceRegistry_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesZeroInput() (gas: 12301) +PriceRegistry_applyTokenTransferFeeConfigUpdates:test_ApplyTokenTransferFeeConfig_Success() (gas: 86826) +PriceRegistry_applyTokenTransferFeeConfigUpdates:test_ApplyTokenTransferFeeZeroInput() (gas: 13089) +PriceRegistry_applyTokenTransferFeeConfigUpdates:test_InvalidDestBytesOverhead_Revert() (gas: 17045) +PriceRegistry_applyTokenTransferFeeConfigUpdates:test_OnlyCallableByOwnerOrAdmin_Revert() (gas: 12240) +PriceRegistry_constructor:test_InvalidLinkTokenEqZeroAddress_Revert() (gas: 105966) +PriceRegistry_constructor:test_InvalidMaxFeeJuelsPerMsg_Revert() (gas: 110316) +PriceRegistry_constructor:test_InvalidStalenessThreshold_Revert() (gas: 110369) +PriceRegistry_constructor:test_Setup_Success() (gas: 4650895) +PriceRegistry_convertTokenAmount:test_ConvertTokenAmount_Success() (gas: 72751) +PriceRegistry_convertTokenAmount:test_LinkTokenNotSupported_Revert() (gas: 30981) +PriceRegistry_getDataAvailabilityCost:test_EmptyMessageCalculatesDataAvailabilityCost_Success() (gas: 95575) +PriceRegistry_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCostUnsupportedDestChainSelector_Success() (gas: 14636) +PriceRegistry_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCost_Success() (gas: 20614) +PriceRegistry_getTokenAndGasPrices:test_GetFeeTokenAndGasPrices_Success() (gas: 70449) +PriceRegistry_getTokenAndGasPrices:test_StaleGasPrice_Revert() (gas: 16838) +PriceRegistry_getTokenAndGasPrices:test_UnsupportedChain_Revert() (gas: 16140) +PriceRegistry_getTokenAndGasPrices:test_ZeroGasPrice_Success() (gas: 45734) +PriceRegistry_getTokenPrice:test_GetTokenPriceFromFeed_Success() (gas: 62311) +PriceRegistry_getTokenPrices:test_GetTokenPrices_Success() (gas: 84774) +PriceRegistry_getTokenTransferCost:test_CustomTokenBpsFee_Success() (gas: 41283) +PriceRegistry_getTokenTransferCost:test_FeeTokenBpsFee_Success() (gas: 34733) +PriceRegistry_getTokenTransferCost:test_LargeTokenTransferChargesMaxFeeAndGas_Success() (gas: 27807) +PriceRegistry_getTokenTransferCost:test_MixedTokenTransferFee_Success() (gas: 108018) +PriceRegistry_getTokenTransferCost:test_NoTokenTransferChargesZeroFee_Success() (gas: 20359) +PriceRegistry_getTokenTransferCost:test_SmallTokenTransferChargesMinFeeAndGas_Success() (gas: 27615) +PriceRegistry_getTokenTransferCost:test_WETHTokenBpsFee_Success() (gas: 40668) +PriceRegistry_getTokenTransferCost:test_ZeroAmountTokenTransferChargesMinFeeAndGas_Success() (gas: 27638) +PriceRegistry_getTokenTransferCost:test_ZeroFeeConfigChargesMinFee_Success() (gas: 40015) +PriceRegistry_getTokenTransferCost:test_getTokenTransferCost_selfServeUsesDefaults_Success() (gas: 29343) +PriceRegistry_getValidatedFee:test_DestinationChainNotEnabled_Revert() (gas: 18203) +PriceRegistry_getValidatedFee:test_EmptyMessage_Success() (gas: 81464) +PriceRegistry_getValidatedFee:test_EnforceOutOfOrder_Revert() (gas: 55184) +PriceRegistry_getValidatedFee:test_HighGasMessage_Success() (gas: 237926) +PriceRegistry_getValidatedFee:test_InvalidEVMAddress_Revert() (gas: 19971) +PriceRegistry_getValidatedFee:test_MessageGasLimitTooHigh_Revert() (gas: 31775) +PriceRegistry_getValidatedFee:test_MessageTooLarge_Revert() (gas: 97714) +PriceRegistry_getValidatedFee:test_MessageWithDataAndTokenTransfer_Success() (gas: 143193) +PriceRegistry_getValidatedFee:test_NotAFeeToken_Revert() (gas: 29435) +PriceRegistry_getValidatedFee:test_SingleTokenMessage_Success() (gas: 112283) +PriceRegistry_getValidatedFee:test_TooManyTokens_Revert() (gas: 20107) +PriceRegistry_getValidatedFee:test_ZeroDataAvailabilityMultiplier_Success() (gas: 62956) +PriceRegistry_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Above18Decimals_Success() (gas: 2094532) +PriceRegistry_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Below18Decimals_Success() (gas: 2094490) +PriceRegistry_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt0Decimals_Success() (gas: 2074609) +PriceRegistry_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt18Decimals_Success() (gas: 2094264) +PriceRegistry_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFlippedDecimals_Success() (gas: 2094468) +PriceRegistry_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedMaxInt224Value_Success() (gas: 2094280) +PriceRegistry_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedOverStalenessPeriod_Success() (gas: 61997) +PriceRegistry_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeed_Success() (gas: 61877) +PriceRegistry_getValidatedTokenPrice:test_GetValidatedTokenPrice_Success() (gas: 60998) +PriceRegistry_getValidatedTokenPrice:test_OverflowFeedPrice_Revert() (gas: 2093992) +PriceRegistry_getValidatedTokenPrice:test_StaleFeeToken_Success() (gas: 61525) +PriceRegistry_getValidatedTokenPrice:test_TokenNotSupportedFeed_Revert() (gas: 109113) +PriceRegistry_getValidatedTokenPrice:test_TokenNotSupported_Revert() (gas: 13819) +PriceRegistry_getValidatedTokenPrice:test_UnderflowFeedPrice_Revert() (gas: 2092670) +PriceRegistry_parseEVMExtraArgsFromBytes:test_EVMExtraArgsDefault_Success() (gas: 17360) +PriceRegistry_parseEVMExtraArgsFromBytes:test_EVMExtraArgsEnforceOutOfOrder_Revert() (gas: 21454) +PriceRegistry_parseEVMExtraArgsFromBytes:test_EVMExtraArgsGasLimitTooHigh_Revert() (gas: 18551) +PriceRegistry_parseEVMExtraArgsFromBytes:test_EVMExtraArgsInvalidExtraArgsTag_Revert() (gas: 18075) +PriceRegistry_parseEVMExtraArgsFromBytes:test_EVMExtraArgsV1_Success() (gas: 18452) +PriceRegistry_parseEVMExtraArgsFromBytes:test_EVMExtraArgsV2_Success() (gas: 18569) +PriceRegistry_processMessageArgs:test_InvalidExtraArgs_Revert() (gas: 18306) +PriceRegistry_processMessageArgs:test_MalformedEVMExtraArgs_Revert() (gas: 18852) +PriceRegistry_processMessageArgs:test_MessageFeeTooHigh_Revert() (gas: 16360) +PriceRegistry_processMessageArgs:test_WitEVMExtraArgsV2_Success() (gas: 26236) +PriceRegistry_processMessageArgs:test_WithConvertedTokenAmount_Success() (gas: 32410) +PriceRegistry_processMessageArgs:test_WithEVMExtraArgsV1_Success() (gas: 25848) +PriceRegistry_processMessageArgs:test_WithEmptyEVMExtraArgs_Success() (gas: 23663) +PriceRegistry_processMessageArgs:test_WithLinkTokenAmount_Success() (gas: 17320) +PriceRegistry_updatePrices:test_OnlyCallableByUpdater_Revert() (gas: 12080) +PriceRegistry_updatePrices:test_OnlyGasPrice_Success() (gas: 23599) +PriceRegistry_updatePrices:test_OnlyTokenPrice_Success() (gas: 30637) +PriceRegistry_updatePrices:test_UpdatableByAuthorizedCaller_Success() (gas: 76043) +PriceRegistry_updatePrices:test_UpdateMultiplePrices_Success() (gas: 151521) +PriceRegistry_updateTokenPriceFeeds:test_FeedNotUpdated() (gas: 50699) +PriceRegistry_updateTokenPriceFeeds:test_FeedUnset_Success() (gas: 63882) +PriceRegistry_updateTokenPriceFeeds:test_FeedUpdatedByNonOwner_Revert() (gas: 19998) +PriceRegistry_updateTokenPriceFeeds:test_MultipleFeedUpdate_Success() (gas: 89162) +PriceRegistry_updateTokenPriceFeeds:test_SingleFeedUpdate_Success() (gas: 50949) +PriceRegistry_updateTokenPriceFeeds:test_ZeroFeeds_Success() (gas: 12362) +PriceRegistry_validateDestFamilyAddress:test_InvalidEVMAddressEncodePacked_Revert() (gas: 10572) +PriceRegistry_validateDestFamilyAddress:test_InvalidEVMAddressPrecompiles_Revert() (gas: 3916546) +PriceRegistry_validateDestFamilyAddress:test_InvalidEVMAddress_Revert() (gas: 10756) +PriceRegistry_validateDestFamilyAddress:test_ValidEVMAddress_Success() (gas: 6660) +PriceRegistry_validateDestFamilyAddress:test_ValidNonEVMAddress_Success() (gas: 6440) +PriceRegistry_validatePoolReturnData:test_InvalidEVMAddressDestToken_Revert() (gas: 35457) +PriceRegistry_validatePoolReturnData:test_SourceTokenDataTooLarge_Revert() (gas: 90631) +PriceRegistry_validatePoolReturnData:test_TokenAmountArraysMismatching_Revert() (gas: 32749) +PriceRegistry_validatePoolReturnData:test_WithSingleToken_Success() (gas: 31293) RMN_constructor:test_Constructor_Success() (gas: 48838) RMN_getRecordedCurseRelatedOps:test_OpsPostDeployment() (gas: 19666) RMN_lazyVoteToCurseUpdate_Benchmark:test_VoteToCurseLazilyRetain3VotersUponConfigChange_gas() (gas: 152152) @@ -807,7 +759,7 @@ RMN_ownerUnbless:test_Unbless_Success() (gas: 74699) RMN_ownerUnvoteToCurse:test_CanBlessAndCurseAfterGlobalCurseIsLifted() (gas: 470965) RMN_ownerUnvoteToCurse:test_IsIdempotent() (gas: 397532) RMN_ownerUnvoteToCurse:test_NonOwner_Revert() (gas: 18591) -RMN_ownerUnvoteToCurse:test_OwnerUnvoteToCurseSuccess_gas() (gas: 357403) +RMN_ownerUnvoteToCurse:test_OwnerUnvoteToCurseSuccess_gas() (gas: 357400) RMN_ownerUnvoteToCurse:test_UnknownVoter_Revert() (gas: 32980) RMN_ownerUnvoteToCurse_Benchmark:test_OwnerUnvoteToCurse_1Voter_LiftsCurse_gas() (gas: 261985) RMN_permaBlessing:test_PermaBlessing() (gas: 202686) @@ -815,7 +767,7 @@ RMN_setConfig:test_BlessVoterIsZeroAddress_Revert() (gas: 15494) RMN_setConfig:test_EitherThresholdIsZero_Revert() (gas: 21095) RMN_setConfig:test_NonOwner_Revert() (gas: 14713) RMN_setConfig:test_RepeatedAddress_Revert() (gas: 18213) -RMN_setConfig:test_SetConfigSuccess_gas() (gas: 104204) +RMN_setConfig:test_SetConfigSuccess_gas() (gas: 104022) RMN_setConfig:test_TotalWeightsSmallerThanEachThreshold_Revert() (gas: 30173) RMN_setConfig:test_VoteToBlessByEjectedVoter_Revert() (gas: 130303) RMN_setConfig:test_VotersLengthIsZero_Revert() (gas: 12128) @@ -870,7 +822,7 @@ RateLimiter_consume:test_TokenRateLimitReached_Revert() (gas: 24706) RateLimiter_currentTokenBucketState:test_CurrentTokenBucketState_Success() (gas: 38647) RateLimiter_currentTokenBucketState:test_Refill_Success() (gas: 46384) RateLimiter_setTokenBucketConfig:test_SetRateLimiterConfig_Success() (gas: 38017) -RegistryModuleOwnerCustom_constructor:test_constructor_Revert() (gas: 36028) +RegistryModuleOwnerCustom_constructor:test_constructor_Revert() (gas: 36031) RegistryModuleOwnerCustom_registerAdminViaGetCCIPAdmin:test_registerAdminViaGetCCIPAdmin_Revert() (gas: 19637) RegistryModuleOwnerCustom_registerAdminViaGetCCIPAdmin:test_registerAdminViaGetCCIPAdmin_Success() (gas: 129918) RegistryModuleOwnerCustom_registerAdminViaOwner:test_registerAdminViaOwner_Revert() (gas: 19451) @@ -879,40 +831,40 @@ Router_applyRampUpdates:test_OffRampMismatch_Revert() (gas: 89288) Router_applyRampUpdates:test_OffRampUpdatesWithRouting() (gas: 10642128) Router_applyRampUpdates:test_OnRampDisable() (gas: 55913) Router_applyRampUpdates:test_OnlyOwner_Revert() (gas: 12311) -Router_ccipSend:test_CCIPSendLinkFeeNoTokenSuccess_gas() (gas: 113880) -Router_ccipSend:test_CCIPSendLinkFeeOneTokenSuccess_gas() (gas: 201336) -Router_ccipSend:test_CCIPSendNativeFeeNoTokenSuccess_gas() (gas: 128515) -Router_ccipSend:test_CCIPSendNativeFeeOneTokenSuccess_gas() (gas: 215973) -Router_ccipSend:test_FeeTokenAmountTooLow_Revert() (gas: 66269) +Router_ccipSend:test_CCIPSendLinkFeeNoTokenSuccess_gas() (gas: 113861) +Router_ccipSend:test_CCIPSendLinkFeeOneTokenSuccess_gas() (gas: 200634) +Router_ccipSend:test_CCIPSendNativeFeeNoTokenSuccess_gas() (gas: 128508) +Router_ccipSend:test_CCIPSendNativeFeeOneTokenSuccess_gas() (gas: 215283) +Router_ccipSend:test_FeeTokenAmountTooLow_Revert() (gas: 66275) Router_ccipSend:test_InvalidMsgValue() (gas: 31963) -Router_ccipSend:test_NativeFeeTokenInsufficientValue() (gas: 68740) -Router_ccipSend:test_NativeFeeTokenOverpay_Success() (gas: 173606) -Router_ccipSend:test_NativeFeeTokenZeroValue() (gas: 56031) -Router_ccipSend:test_NativeFeeToken_Success() (gas: 172200) -Router_ccipSend:test_NonLinkFeeToken_Success() (gas: 242714) +Router_ccipSend:test_NativeFeeTokenInsufficientValue() (gas: 68711) +Router_ccipSend:test_NativeFeeTokenOverpay_Success() (gas: 173605) +Router_ccipSend:test_NativeFeeTokenZeroValue() (gas: 56037) +Router_ccipSend:test_NativeFeeToken_Success() (gas: 172199) +Router_ccipSend:test_NonLinkFeeToken_Success() (gas: 242707) Router_ccipSend:test_UnsupportedDestinationChain_Revert() (gas: 24749) Router_ccipSend:test_WhenNotHealthy_Revert() (gas: 44724) -Router_ccipSend:test_WrappedNativeFeeToken_Success() (gas: 174416) -Router_ccipSend:test_ZeroFeeAndGasPrice_Success() (gas: 244854) +Router_ccipSend:test_WrappedNativeFeeToken_Success() (gas: 174415) +Router_ccipSend:test_ZeroFeeAndGasPrice_Success() (gas: 245121) Router_constructor:test_Constructor_Success() (gas: 13074) Router_getArmProxy:test_getArmProxy() (gas: 10561) -Router_getFee:test_GetFeeSupportedChain_Success() (gas: 46458) +Router_getFee:test_GetFeeSupportedChain_Success() (gas: 46464) Router_getFee:test_UnsupportedDestinationChain_Revert() (gas: 17138) Router_getSupportedTokens:test_GetSupportedTokens_Revert() (gas: 10460) Router_recoverTokens:test_RecoverTokensInvalidRecipient_Revert() (gas: 11316) -Router_recoverTokens:test_RecoverTokensNoFunds_Revert() (gas: 17761) +Router_recoverTokens:test_RecoverTokensNoFunds_Revert() (gas: 20261) Router_recoverTokens:test_RecoverTokensNonOwner_Revert() (gas: 11159) Router_recoverTokens:test_RecoverTokensValueReceiver_Revert() (gas: 422138) -Router_recoverTokens:test_RecoverTokens_Success() (gas: 50437) +Router_recoverTokens:test_RecoverTokens_Success() (gas: 52437) Router_routeMessage:test_AutoExec_Success() (gas: 42684) -Router_routeMessage:test_ExecutionEvent_Success() (gas: 157980) +Router_routeMessage:test_ExecutionEvent_Success() (gas: 158002) Router_routeMessage:test_ManualExec_Success() (gas: 35381) Router_routeMessage:test_OnlyOffRamp_Revert() (gas: 25116) Router_routeMessage:test_WhenNotHealthy_Revert() (gas: 44724) Router_setWrappedNative:test_OnlyOwner_Revert() (gas: 10985) -SelfFundedPingPong_ccipReceive:test_FundingIfNotANop_Revert() (gas: 53531) -SelfFundedPingPong_ccipReceive:test_Funding_Success() (gas: 416966) -SelfFundedPingPong_setCountIncrBeforeFunding:test_setCountIncrBeforeFunding() (gas: 20151) +SelfFundedPingPong_ccipReceive:test_FundingIfNotANop_Revert() (gas: 55540) +SelfFundedPingPong_ccipReceive:test_Funding_Success() (gas: 419430) +SelfFundedPingPong_setCountIncrBeforeFunding:test_setCountIncrBeforeFunding() (gas: 20157) TokenAdminRegistry_acceptAdminRole:test_acceptAdminRole_OnlyPendingAdministrator_Revert() (gas: 51085) TokenAdminRegistry_acceptAdminRole:test_acceptAdminRole_Success() (gas: 43947) TokenAdminRegistry_addRegistryModule:test_addRegistryModule_OnlyOwner_Revert() (gas: 12629) @@ -935,58 +887,57 @@ TokenAdminRegistry_setPool:test_setPool_Success() (gas: 35943) TokenAdminRegistry_setPool:test_setPool_ZeroAddressRemovesPool_Success() (gas: 30617) TokenAdminRegistry_transferAdminRole:test_transferAdminRole_OnlyAdministrator_Revert() (gas: 18043) TokenAdminRegistry_transferAdminRole:test_transferAdminRole_Success() (gas: 49390) -TokenPoolAndProxy:test_lockOrBurn_burnMint_Success() (gas: 6070353) -TokenPoolAndProxy:test_lockOrBurn_burnWithFromMint_Success() (gas: 6101826) -TokenPoolAndProxy:test_lockOrBurn_lockRelease_Success() (gas: 6319594) -TokenPoolAndProxy:test_setPreviousPool_Success() (gas: 3387124) -TokenPoolAndProxyMigration:test_tokenPoolMigration_Success_1_2() (gas: 6913778) -TokenPoolAndProxyMigration:test_tokenPoolMigration_Success_1_4() (gas: 7097803) -TokenPoolWithAllowList_applyAllowListUpdates:test_AllowListNotEnabled_Revert() (gas: 2209837) +TokenPoolAndProxy:test_lockOrBurn_burnMint_Success() (gas: 6036775) +TokenPoolAndProxy:test_lockOrBurn_lockRelease_Success() (gas: 6282531) +TokenPoolAndProxyMigration:test_tokenPoolMigration_Success_1_2() (gas: 6885897) +TokenPoolAndProxyMigration:test_tokenPoolMigration_Success_1_4() (gas: 7070012) +TokenPoolWithAllowList_applyAllowListUpdates:test_AllowListNotEnabled_Revert() (gas: 2169749) TokenPoolWithAllowList_applyAllowListUpdates:test_OnlyOwner_Revert() (gas: 12089) -TokenPoolWithAllowList_applyAllowListUpdates:test_SetAllowListSkipsZero_Success() (gas: 23324) -TokenPoolWithAllowList_applyAllowListUpdates:test_SetAllowList_Success() (gas: 177568) -TokenPoolWithAllowList_getAllowList:test_GetAllowList_Success() (gas: 23670) +TokenPoolWithAllowList_applyAllowListUpdates:test_SetAllowListSkipsZero_Success() (gas: 23280) +TokenPoolWithAllowList_applyAllowListUpdates:test_SetAllowList_Success() (gas: 177516) +TokenPoolWithAllowList_getAllowList:test_GetAllowList_Success() (gas: 23648) TokenPoolWithAllowList_getAllowListEnabled:test_GetAllowListEnabled_Success() (gas: 8363) -TokenPoolWithAllowList_setRouter:test_SetRouter_Success() (gas: 24831) +TokenPoolWithAllowList_setRouter:test_SetRouter_Success() (gas: 24765) TokenPool_applyChainUpdates:test_applyChainUpdates_DisabledNonZeroRateLimit_Revert() (gas: 271305) TokenPool_applyChainUpdates:test_applyChainUpdates_InvalidRateLimitRate_Revert() (gas: 541162) TokenPool_applyChainUpdates:test_applyChainUpdates_NonExistentChain_Revert() (gas: 18344) TokenPool_applyChainUpdates:test_applyChainUpdates_OnlyCallableByOwner_Revert() (gas: 11385) -TokenPool_applyChainUpdates:test_applyChainUpdates_Success() (gas: 476468) +TokenPool_applyChainUpdates:test_applyChainUpdates_Success() (gas: 476472) TokenPool_applyChainUpdates:test_applyChainUpdates_ZeroAddressNotAllowed_Revert() (gas: 157074) -TokenPool_constructor:test_ZeroAddressNotAllowed_Revert() (gas: 70721) -TokenPool_constructor:test_immutableFields_Success() (gas: 20544) +TokenPool_constructor:test_ZeroAddressNotAllowed_Revert() (gas: 70676) +TokenPool_constructor:test_immutableFields_Success() (gas: 20522) TokenPool_getRemotePool:test_getRemotePool_Success() (gas: 273962) -TokenPool_onlyOffRamp:test_CallerIsNotARampOnRouter_Revert() (gas: 276909) -TokenPool_onlyOffRamp:test_ChainNotAllowed_Revert() (gas: 289406) -TokenPool_onlyOffRamp:test_onlyOffRamp_Success() (gas: 349720) +TokenPool_onlyOffRamp:test_CallerIsNotARampOnRouter_Revert() (gas: 276952) +TokenPool_onlyOffRamp:test_ChainNotAllowed_Revert() (gas: 289509) +TokenPool_onlyOffRamp:test_onlyOffRamp_Success() (gas: 349763) TokenPool_onlyOnRamp:test_CallerIsNotARampOnRouter_Revert() (gas: 276643) -TokenPool_onlyOnRamp:test_ChainNotAllowed_Revert() (gas: 253432) +TokenPool_onlyOnRamp:test_ChainNotAllowed_Revert() (gas: 253466) TokenPool_onlyOnRamp:test_onlyOnRamp_Success() (gas: 304761) -TokenPool_setChainRateLimiterConfig:test_NonExistentChain_Revert() (gas: 17061) -TokenPool_setChainRateLimiterConfig:test_OnlyOwnerOrRateLimitAdmin_Revert() (gas: 15062) -TokenPool_setRemotePool:test_setRemotePool_NonExistentChain_Reverts() (gas: 15620) -TokenPool_setRemotePool:test_setRemotePool_OnlyOwner_Reverts() (gas: 13195) -TokenPool_setRemotePool:test_setRemotePool_Success() (gas: 281912) +TokenPool_setChainRateLimiterConfig:test_NonExistentChain_Revert() (gas: 14906) +TokenPool_setChainRateLimiterConfig:test_OnlyOwner_Revert() (gas: 12565) +TokenPool_setRemotePool:test_setRemotePool_NonExistentChain_Reverts() (gas: 15598) +TokenPool_setRemotePool:test_setRemotePool_OnlyOwner_Reverts() (gas: 13173) +TokenPool_setRemotePool:test_setRemotePool_Success() (gas: 281890) TokenProxy_ccipSend:test_CcipSendGasShouldBeZero_Revert() (gas: 17109) -TokenProxy_ccipSend:test_CcipSendInsufficientAllowance_Revert() (gas: 136222) +TokenProxy_ccipSend:test_CcipSendInsufficientAllowance_Revert() (gas: 136351) TokenProxy_ccipSend:test_CcipSendInvalidToken_Revert() (gas: 15919) -TokenProxy_ccipSend:test_CcipSendNative_Success() (gas: 245173) +TokenProxy_ccipSend:test_CcipSendNative_Success() (gas: 244483) TokenProxy_ccipSend:test_CcipSendNoDataAllowed_Revert() (gas: 16303) -TokenProxy_ccipSend:test_CcipSend_Success() (gas: 261558) +TokenProxy_ccipSend:test_CcipSend_Success() (gas: 261100) TokenProxy_constructor:test_Constructor() (gas: 13812) TokenProxy_getFee:test_GetFeeGasShouldBeZero_Revert() (gas: 16827) TokenProxy_getFee:test_GetFeeInvalidToken_Revert() (gas: 12658) TokenProxy_getFee:test_GetFeeNoDataAllowed_Revert() (gas: 15849) -TokenProxy_getFee:test_GetFee_Success() (gas: 86690) -USDCTokenPool__validateMessage:test_ValidateInvalidMessage_Revert() (gas: 25290) -USDCTokenPool_lockOrBurn:test_CallerIsNotARampOnRouter_Revert() (gas: 35322) -USDCTokenPool_lockOrBurn:test_LockOrBurnWithAllowList_Revert() (gas: 30073) -USDCTokenPool_lockOrBurn:test_LockOrBurn_Success() (gas: 133102) -USDCTokenPool_lockOrBurn:test_UnknownDomain_Revert() (gas: 477183) -USDCTokenPool_releaseOrMint:test_ReleaseOrMintRealTx_Success() (gas: 268111) -USDCTokenPool_releaseOrMint:test_TokenMaxCapacityExceeded_Revert() (gas: 50676) -USDCTokenPool_releaseOrMint:test_UnlockingUSDCFailed_Revert() (gas: 98591) +TokenProxy_getFee:test_GetFee_Success() (gas: 86948) +USDCTokenPool__validateMessage:test_ValidateInvalidMessage_Revert() (gas: 24960) +USDCTokenPool_lockOrBurn:test_CallerIsNotARampOnRouter_Revert() (gas: 35312) +USDCTokenPool_lockOrBurn:test_LockOrBurnWithAllowList_Revert() (gas: 30063) +USDCTokenPool_lockOrBurn:test_LockOrBurn_Success() (gas: 132864) +USDCTokenPool_lockOrBurn:test_UnknownDomain_Revert() (gas: 477209) +USDCTokenPool_lockOrBurn:test_lockOrBurn_InvalidReceiver_Revert() (gas: 52606) +USDCTokenPool_releaseOrMint:test_ReleaseOrMintRealTx_Success() (gas: 289268) +USDCTokenPool_releaseOrMint:test_TokenMaxCapacityExceeded_Revert() (gas: 50682) +USDCTokenPool_releaseOrMint:test_UnlockingUSDCFailed_Revert() (gas: 119185) USDCTokenPool_setDomains:test_InvalidDomain_Revert() (gas: 66150) -USDCTokenPool_setDomains:test_OnlyOwner_Revert() (gas: 11333) +USDCTokenPool_setDomains:test_OnlyOwner_Revert() (gas: 11339) USDCTokenPool_supportsInterface:test_SupportsInterface_Success() (gas: 9876) \ No newline at end of file diff --git a/contracts/gas-snapshots/functions.gas-snapshot b/contracts/gas-snapshots/functions.gas-snapshot index d7945f225e..69e0271684 100644 --- a/contracts/gas-snapshots/functions.gas-snapshot +++ b/contracts/gas-snapshots/functions.gas-snapshot @@ -1,21 +1,21 @@ -ChainSpecificUtil__getL1FeeUpperLimit_Arbitrum:test__getL1FeeUpperLimit_SuccessWhenArbitrumGoerli() (gas: 15903239) -ChainSpecificUtil__getL1FeeUpperLimit_Arbitrum:test__getL1FeeUpperLimit_SuccessWhenArbitrumMainnet() (gas: 15903196) -ChainSpecificUtil__getL1FeeUpperLimit_Arbitrum:test__getL1FeeUpperLimit_SuccessWhenArbitrumSepolia() (gas: 15903265) -ChainSpecificUtil__getL1FeeUpperLimit_Base:test__getL1FeeUpperLimit_SuccessWhenBaseGoerli() (gas: 15903033) -ChainSpecificUtil__getL1FeeUpperLimit_Base:test__getL1FeeUpperLimit_SuccessWhenBaseMainnet() (gas: 15903011) -ChainSpecificUtil__getL1FeeUpperLimit_Base:test__getL1FeeUpperLimit_SuccessWhenBaseSepolia() (gas: 15903060) -ChainSpecificUtil__getL1FeeUpperLimit_Optimism:test__getL1FeeUpperLimit_SuccessWhenOptimismGoerli() (gas: 15902946) -ChainSpecificUtil__getL1FeeUpperLimit_Optimism:test__getL1FeeUpperLimit_SuccessWhenOptimismMainnet() (gas: 15902968) -ChainSpecificUtil__getL1FeeUpperLimit_Optimism:test__getL1FeeUpperLimit_SuccessWhenOptimismSepolia() (gas: 15903011) +ChainSpecificUtil__getL1FeeUpperLimit_Arbitrum:test__getL1FeeUpperLimit_SuccessWhenArbitrumGoerli() (gas: 16076840) +ChainSpecificUtil__getL1FeeUpperLimit_Arbitrum:test__getL1FeeUpperLimit_SuccessWhenArbitrumMainnet() (gas: 16076819) +ChainSpecificUtil__getL1FeeUpperLimit_Arbitrum:test__getL1FeeUpperLimit_SuccessWhenArbitrumSepolia() (gas: 16076888) +ChainSpecificUtil__getL1FeeUpperLimit_Base:test__getL1FeeUpperLimit_SuccessWhenBaseGoerli() (gas: 16076608) +ChainSpecificUtil__getL1FeeUpperLimit_Base:test__getL1FeeUpperLimit_SuccessWhenBaseMainnet() (gas: 16076564) +ChainSpecificUtil__getL1FeeUpperLimit_Base:test__getL1FeeUpperLimit_SuccessWhenBaseSepolia() (gas: 16076635) +ChainSpecificUtil__getL1FeeUpperLimit_Optimism:test__getL1FeeUpperLimit_SuccessWhenOptimismGoerli() (gas: 16076521) +ChainSpecificUtil__getL1FeeUpperLimit_Optimism:test__getL1FeeUpperLimit_SuccessWhenOptimismMainnet() (gas: 16076543) +ChainSpecificUtil__getL1FeeUpperLimit_Optimism:test__getL1FeeUpperLimit_SuccessWhenOptimismSepolia() (gas: 16076586) FunctionsBilling_Constructor:test_Constructor_Success() (gas: 17982) -FunctionsBilling_DeleteCommitment:test_DeleteCommitment_RevertIfNotRouter() (gas: 13260) -FunctionsBilling_DeleteCommitment:test_DeleteCommitment_Success() (gas: 15875) +FunctionsBilling_DeleteCommitment:test_DeleteCommitment_RevertIfNotRouter() (gas: 13283) +FunctionsBilling_DeleteCommitment:test_DeleteCommitment_Success() (gas: 15853) FunctionsBilling_EstimateCost:test_EstimateCost_RevertsIfGasPriceAboveCeiling() (gas: 32450) -FunctionsBilling_EstimateCost:test_EstimateCost_Success() (gas: 90999) +FunctionsBilling_EstimateCost:test_EstimateCost_Success() (gas: 90977) FunctionsBilling_EstimateCost:test_EstimateCost_SuccessLowGasPrice() (gas: 91102) FunctionsBilling_GetAdminFeeJuels:test_GetAdminFeeJuels_Success() (gas: 18671) -FunctionsBilling_GetConfig:test_GetConfig_Success() (gas: 30727) -FunctionsBilling_GetDONFeeJuels:test_GetDONFeeJuels_Success() (gas: 41128) +FunctionsBilling_GetConfig:test_GetConfig_Success() (gas: 30750) +FunctionsBilling_GetDONFeeJuels:test_GetDONFeeJuels_Success() (gas: 41151) FunctionsBilling_GetOperationFee:test_GetOperationFeeJuels_Success() (gas: 40548) FunctionsBilling_GetWeiPerUnitLink:test_GetWeiPerUnitLink_Success() (gas: 29751) FunctionsBilling_OracleWithdraw:test_OracleWithdraw_RevertIfInsufficientBalance() (gas: 70136) @@ -23,41 +23,41 @@ FunctionsBilling_OracleWithdraw:test_OracleWithdraw_RevertWithNoBalance() (gas: FunctionsBilling_OracleWithdraw:test_OracleWithdraw_SuccessCoordinatorOwner() (gas: 129908) FunctionsBilling_OracleWithdraw:test_OracleWithdraw_SuccessTransmitterWithBalanceNoAmountGiven() (gas: 171930) FunctionsBilling_OracleWithdraw:test_OracleWithdraw_SuccessTransmitterWithBalanceValidAmountGiven() (gas: 145165) -FunctionsBilling_OracleWithdrawAll:test_OracleWithdrawAll_RevertIfNotOwner() (gas: 13297) +FunctionsBilling_OracleWithdrawAll:test_OracleWithdrawAll_RevertIfNotOwner() (gas: 13320) FunctionsBilling_OracleWithdrawAll:test_OracleWithdrawAll_SuccessPaysTransmittersWithBalance() (gas: 222357) -FunctionsBilling_UpdateConfig:test_UpdateConfig_RevertIfNotOwner() (gas: 21654) -FunctionsBilling_UpdateConfig:test_UpdateConfig_Success() (gas: 54121) +FunctionsBilling_UpdateConfig:test_UpdateConfig_RevertIfNotOwner() (gas: 21632) +FunctionsBilling_UpdateConfig:test_UpdateConfig_Success() (gas: 54099) FunctionsBilling__DisperseFeePool:test__DisperseFeePool_RevertIfNotSet() (gas: 8810) -FunctionsBilling__FulfillAndBill:test__FulfillAndBill_RevertIfInvalidCommitment() (gas: 13375) -FunctionsBilling__FulfillAndBill:test__FulfillAndBill_Success() (gas: 185953) +FunctionsBilling__FulfillAndBill:test__FulfillAndBill_RevertIfInvalidCommitment() (gas: 13353) +FunctionsBilling__FulfillAndBill:test__FulfillAndBill_Success() (gas: 185976) FunctionsBilling__StartBilling:test__FulfillAndBill_HasUniqueGlobalRequestId() (gas: 524582) FunctionsClient_Constructor:test_Constructor_Success() (gas: 10407) -FunctionsClient_HandleOracleFulfillment:test_HandleOracleFulfillment_RevertIfNotRouter() (gas: 14617) -FunctionsClient_HandleOracleFulfillment:test_HandleOracleFulfillment_Success() (gas: 22917) +FunctionsClient_HandleOracleFulfillment:test_HandleOracleFulfillment_RevertIfNotRouter() (gas: 14595) +FunctionsClient_HandleOracleFulfillment:test_HandleOracleFulfillment_Success() (gas: 22983) FunctionsClient__SendRequest:test__SendRequest_RevertIfInvalidCallbackGasLimit() (gas: 55069) FunctionsCoordinator_Constructor:test_Constructor_Success() (gas: 15085) -FunctionsCoordinator_GetDONPublicKey:test_GetDONPublicKey_RevertIfEmpty() (gas: 15378) +FunctionsCoordinator_GetDONPublicKey:test_GetDONPublicKey_RevertIfEmpty() (gas: 15356) FunctionsCoordinator_GetDONPublicKey:test_GetDONPublicKey_Success() (gas: 91691) -FunctionsCoordinator_GetThresholdPublicKey:test_GetThresholdPublicKey_RevertIfEmpty() (gas: 15356) -FunctionsCoordinator_GetThresholdPublicKey:test_GetThresholdPublicKey_Success() (gas: 515973) -FunctionsCoordinator_SetDONPublicKey:test_SetDONPublicKey_RevertNotOwner() (gas: 20365) +FunctionsCoordinator_GetThresholdPublicKey:test_GetThresholdPublicKey_RevertIfEmpty() (gas: 15334) +FunctionsCoordinator_GetThresholdPublicKey:test_GetThresholdPublicKey_Success() (gas: 515951) +FunctionsCoordinator_SetDONPublicKey:test_SetDONPublicKey_RevertNotOwner() (gas: 20409) FunctionsCoordinator_SetDONPublicKey:test_SetDONPublicKey_Success() (gas: 88970) -FunctionsCoordinator_SetThresholdPublicKey:test_SetThresholdPublicKey_RevertNotOwner() (gas: 13892) +FunctionsCoordinator_SetThresholdPublicKey:test_SetThresholdPublicKey_RevertNotOwner() (gas: 13915) FunctionsCoordinator_SetThresholdPublicKey:test_SetThresholdPublicKey_Success() (gas: 513165) -FunctionsCoordinator_StartRequest:test_StartRequest_RevertIfNotRouter() (gas: 22736) -FunctionsCoordinator_StartRequest:test_StartRequest_Success() (gas: 150172) +FunctionsCoordinator_StartRequest:test_StartRequest_RevertIfNotRouter() (gas: 22802) +FunctionsCoordinator_StartRequest:test_StartRequest_Success() (gas: 152650) FunctionsCoordinator__IsTransmitter:test__IsTransmitter_SuccessFound() (gas: 15106) -FunctionsCoordinator__IsTransmitter:test__IsTransmitter_SuccessNotFound() (gas: 22938) +FunctionsCoordinator__IsTransmitter:test__IsTransmitter_SuccessNotFound() (gas: 22916) FunctionsRequest_DEFAULT_BUFFER_SIZE:test_DEFAULT_BUFFER_SIZE() (gas: 3089) FunctionsRequest_EncodeCBOR:test_EncodeCBOR_Success() (gas: 3066) FunctionsRequest_REQUEST_DATA_VERSION:test_REQUEST_DATA_VERSION() (gas: 3068) FunctionsRouter_Constructor:test_Constructor_Success() (gas: 15107) -FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedCostExceedsCommitment() (gas: 172497) +FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedCostExceedsCommitment() (gas: 172475) FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedInsufficientGas() (gas: 163010) FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedInvalidCommitment() (gas: 38777) FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedInvalidRequestId() (gas: 35900) FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedSubscriptionBalanceInvariant() (gas: 180976) -FunctionsRouter_Fulfill:test_Fulfill_RevertIfNotCommittedCoordinator() (gas: 28086) +FunctionsRouter_Fulfill:test_Fulfill_RevertIfNotCommittedCoordinator() (gas: 28152) FunctionsRouter_Fulfill:test_Fulfill_RevertIfPaused() (gas: 156535) FunctionsRouter_Fulfill:test_Fulfill_SuccessClientNoLongerExists() (gas: 335070) FunctionsRouter_Fulfill:test_Fulfill_SuccessFulfilled() (gas: 348695) @@ -65,19 +65,19 @@ FunctionsRouter_Fulfill:test_Fulfill_SuccessUserCallbackReverts() (gas: 2627478) FunctionsRouter_Fulfill:test_Fulfill_SuccessUserCallbackRunsOutOfGas() (gas: 658423) FunctionsRouter_GetAdminFee:test_GetAdminFee_Success() (gas: 18323) FunctionsRouter_GetAllowListId:test_GetAllowListId_Success() (gas: 13241) -FunctionsRouter_GetConfig:test_GetConfig_Success() (gas: 40170) -FunctionsRouter_GetContractById:test_GetContractById_RevertIfRouteDoesNotExist() (gas: 13839) +FunctionsRouter_GetConfig:test_GetConfig_Success() (gas: 40193) +FunctionsRouter_GetContractById:test_GetContractById_RevertIfRouteDoesNotExist() (gas: 13862) FunctionsRouter_GetContractById:test_GetContractById_SuccessIfRouteExists() (gas: 17704) -FunctionsRouter_GetProposedContractById:test_GetProposedContractById_RevertIfRouteDoesNotExist() (gas: 16373) -FunctionsRouter_GetProposedContractById:test_GetProposedContractById_SuccessIfRouteExists() (gas: 24266) +FunctionsRouter_GetProposedContractById:test_GetProposedContractById_RevertIfRouteDoesNotExist() (gas: 16417) +FunctionsRouter_GetProposedContractById:test_GetProposedContractById_SuccessIfRouteExists() (gas: 24289) FunctionsRouter_GetProposedContractSet:test_GetProposedContractSet_Success() (gas: 27289) FunctionsRouter_IsValidCallbackGasLimit:test_IsValidCallbackGasLimit_RevertGasLimitTooBig() (gas: 28087) FunctionsRouter_IsValidCallbackGasLimit:test_IsValidCallbackGasLimit_RevertInvalidConfig() (gas: 41095) FunctionsRouter_IsValidCallbackGasLimit:test_IsValidCallbackGasLimit_Success() (gas: 24632) -FunctionsRouter_Pause:test_Pause_RevertIfNotOwner() (gas: 13338) -FunctionsRouter_Pause:test_Pause_Success() (gas: 20669) -FunctionsRouter_ProposeContractsUpdate:test_ProposeContractsUpdate_RevertIfEmptyAddress() (gas: 14791) -FunctionsRouter_ProposeContractsUpdate:test_ProposeContractsUpdate_RevertIfExceedsMaxProposal() (gas: 21693) +FunctionsRouter_Pause:test_Pause_RevertIfNotOwner() (gas: 13361) +FunctionsRouter_Pause:test_Pause_Success() (gas: 20647) +FunctionsRouter_ProposeContractsUpdate:test_ProposeContractsUpdate_RevertIfEmptyAddress() (gas: 14769) +FunctionsRouter_ProposeContractsUpdate:test_ProposeContractsUpdate_RevertIfExceedsMaxProposal() (gas: 21716) FunctionsRouter_ProposeContractsUpdate:test_ProposeContractsUpdate_RevertIfLengthMismatch() (gas: 14670) FunctionsRouter_ProposeContractsUpdate:test_ProposeContractsUpdate_RevertIfNotNewContract() (gas: 19048) FunctionsRouter_ProposeContractsUpdate:test_ProposeContractsUpdate_RevertIfNotOwner() (gas: 23392) @@ -85,155 +85,157 @@ FunctionsRouter_ProposeContractsUpdate:test_ProposeContractsUpdate_Success() (ga FunctionsRouter_SendRequest:test_SendRequest_RevertIfConsumerNotAllowed() (gas: 59400) FunctionsRouter_SendRequest:test_SendRequest_RevertIfDuplicateRequestId() (gas: 217996) FunctionsRouter_SendRequest:test_SendRequest_RevertIfEmptyData() (gas: 29426) -FunctionsRouter_SendRequest:test_SendRequest_RevertIfIncorrectDonId() (gas: 57904) +FunctionsRouter_SendRequest:test_SendRequest_RevertIfIncorrectDonId() (gas: 57882) FunctionsRouter_SendRequest:test_SendRequest_RevertIfInsufficientSubscriptionBalance() (gas: 208451) FunctionsRouter_SendRequest:test_SendRequest_RevertIfInvalidCallbackGasLimit() (gas: 50953) FunctionsRouter_SendRequest:test_SendRequest_RevertIfInvalidDonId() (gas: 25082) -FunctionsRouter_SendRequest:test_SendRequest_RevertIfNoSubscription() (gas: 29132) +FunctionsRouter_SendRequest:test_SendRequest_RevertIfNoSubscription() (gas: 29177) FunctionsRouter_SendRequest:test_SendRequest_RevertIfPaused() (gas: 34291) -FunctionsRouter_SendRequest:test_SendRequest_Success() (gas: 226346) -FunctionsRouter_SendRequestToProposed:test_SendRequestToProposed_RevertIfConsumerNotAllowed() (gas: 65896) +FunctionsRouter_SendRequest:test_SendRequest_Success() (gas: 226324) +FunctionsRouter_SendRequestToProposed:test_SendRequestToProposed_RevertIfConsumerNotAllowed() (gas: 65918) FunctionsRouter_SendRequestToProposed:test_SendRequestToProposed_RevertIfEmptyData() (gas: 36012) FunctionsRouter_SendRequestToProposed:test_SendRequestToProposed_RevertIfIncorrectDonId() (gas: 29896) FunctionsRouter_SendRequestToProposed:test_SendRequestToProposed_RevertIfInvalidCallbackGasLimit() (gas: 57539) FunctionsRouter_SendRequestToProposed:test_SendRequestToProposed_RevertIfInvalidDonId() (gas: 27503) -FunctionsRouter_SendRequestToProposed:test_SendRequestToProposed_RevertIfNoSubscription() (gas: 35717) +FunctionsRouter_SendRequestToProposed:test_SendRequestToProposed_RevertIfNoSubscription() (gas: 35672) FunctionsRouter_SendRequestToProposed:test_SendRequestToProposed_RevertIfPaused() (gas: 40810) FunctionsRouter_SendRequestToProposed:test_SendRequestToProposed_Success() (gas: 232783) FunctionsRouter_SendRequestToProposed:test_SendRequest_RevertIfInsufficientSubscriptionBalance() (gas: 214899) FunctionsRouter_SetAllowListId:test_SetAllowListId_Success() (gas: 33531) -FunctionsRouter_SetAllowListId:test_UpdateConfig_RevertIfNotOwner() (gas: 13403) -FunctionsRouter_Unpause:test_Unpause_RevertIfNotOwner() (gas: 13293) -FunctionsRouter_Unpause:test_Unpause_Success() (gas: 77725) -FunctionsRouter_UpdateConfig:test_UpdateConfig_RevertIfNotOwner() (gas: 24437) -FunctionsRouter_UpdateConfig:test_UpdateConfig_Success() (gas: 63353) -FunctionsRouter_UpdateContracts:test_UpdateContracts_RevertIfNotOwner() (gas: 13336) +FunctionsRouter_SetAllowListId:test_UpdateConfig_RevertIfNotOwner() (gas: 13381) +FunctionsRouter_Unpause:test_Unpause_RevertIfNotOwner() (gas: 13337) +FunctionsRouter_Unpause:test_Unpause_Success() (gas: 77748) +FunctionsRouter_UpdateConfig:test_UpdateConfig_RevertIfNotOwner() (gas: 24415) +FunctionsRouter_UpdateConfig:test_UpdateConfig_Success() (gas: 63331) +FunctionsRouter_UpdateContracts:test_UpdateContracts_RevertIfNotOwner() (gas: 13314) FunctionsRouter_UpdateContracts:test_UpdateContracts_Success() (gas: 39269) FunctionsSubscriptions_AcceptSubscriptionOwnerTransfer:test_AcceptSubscriptionOwnerTransfer_RevertIfNotAllowedSender() (gas: 60413) FunctionsSubscriptions_AcceptSubscriptionOwnerTransfer:test_AcceptSubscriptionOwnerTransfer_RevertIfPaused() (gas: 61040) FunctionsSubscriptions_AcceptSubscriptionOwnerTransfer:test_AcceptSubscriptionOwnerTransfer_RevertIfSenderBecomesBlocked() (gas: 139706) FunctionsSubscriptions_AcceptSubscriptionOwnerTransfer:test_AcceptSubscriptionOwnerTransfer_RevertIfSenderIsNotNewOwner() (gas: 62780) -FunctionsSubscriptions_AcceptSubscriptionOwnerTransfer:test_AcceptSubscriptionOwnerTransfer_Success() (gas: 239911) +FunctionsSubscriptions_AcceptSubscriptionOwnerTransfer:test_AcceptSubscriptionOwnerTransfer_Success() (gas: 239919) FunctionsSubscriptions_AddConsumer:test_AddConsumer_RevertIfMaximumConsumers() (gas: 138033) FunctionsSubscriptions_AddConsumer:test_AddConsumer_RevertIfMaximumConsumersAfterConfigUpdate() (gas: 164977) -FunctionsSubscriptions_AddConsumer:test_AddConsumer_RevertIfNoSubscription() (gas: 12955) -FunctionsSubscriptions_AddConsumer:test_AddConsumer_RevertIfNotAllowedSender() (gas: 102450) -FunctionsSubscriptions_AddConsumer:test_AddConsumer_RevertIfNotSubscriptionOwner() (gas: 87205) +FunctionsSubscriptions_AddConsumer:test_AddConsumer_RevertIfNoSubscription() (gas: 12933) +FunctionsSubscriptions_AddConsumer:test_AddConsumer_RevertIfNotAllowedSender() (gas: 102428) +FunctionsSubscriptions_AddConsumer:test_AddConsumer_RevertIfNotSubscriptionOwner() (gas: 87272) FunctionsSubscriptions_AddConsumer:test_AddConsumer_RevertIfPaused() (gas: 18100) FunctionsSubscriptions_AddConsumer:test_AddConsumer_Success() (gas: 96221) FunctionsSubscriptions_CancelSubscription:test_CancelSubscription_RevertIfNoSubscription() (gas: 15053) -FunctionsSubscriptions_CancelSubscription:test_CancelSubscription_RevertIfNotAllowedSender() (gas: 102529) -FunctionsSubscriptions_CancelSubscription:test_CancelSubscription_RevertIfNotSubscriptionOwner() (gas: 89318) +FunctionsSubscriptions_CancelSubscription:test_CancelSubscription_RevertIfNotAllowedSender() (gas: 102507) +FunctionsSubscriptions_CancelSubscription:test_CancelSubscription_RevertIfNotSubscriptionOwner() (gas: 89341) FunctionsSubscriptions_CancelSubscription:test_CancelSubscription_RevertIfPaused() (gas: 20157) -FunctionsSubscriptions_CancelSubscription:test_CancelSubscription_RevertIfPendingRequests() (gas: 218330) +FunctionsSubscriptions_CancelSubscription:test_CancelSubscription_RevertIfPendingRequests() (gas: 218308) FunctionsSubscriptions_CancelSubscription:test_CancelSubscription_SuccessForfeitAllBalanceAsDeposit() (gas: 115656) FunctionsSubscriptions_CancelSubscription:test_CancelSubscription_SuccessForfeitSomeBalanceAsDeposit() (gas: 126964) FunctionsSubscriptions_CancelSubscription_ReceiveDeposit:test_CancelSubscription_SuccessRecieveDeposit() (gas: 75369) FunctionsSubscriptions_Constructor:test_Constructor_Success() (gas: 10488) FunctionsSubscriptions_CreateSubscriptionWithConsumer:test_CreateSubscriptionWithConsumer_RevertIfNotAllowedSender() (gas: 28688) -FunctionsSubscriptions_CreateSubscriptionWithConsumer:test_CreateSubscriptionWithConsumer_RevertIfPaused() (gas: 17994) +FunctionsSubscriptions_CreateSubscriptionWithConsumer:test_CreateSubscriptionWithConsumer_RevertIfPaused() (gas: 18038) FunctionsSubscriptions_CreateSubscriptionWithConsumer:test_CreateSubscriptionWithConsumer_Success() (gas: 353899) -FunctionsSubscriptions_GetConsumer:test_GetConsumer_Success() (gas: 17256) -FunctionsSubscriptions_GetFlags:test_GetFlags_SuccessInvalidSubscription() (gas: 13438) -FunctionsSubscriptions_GetFlags:test_GetFlags_SuccessValidSubscription() (gas: 41243) +FunctionsSubscriptions_GetConsumer:test_GetConsumer_Success() (gas: 17279) +FunctionsSubscriptions_GetFlags:test_GetFlags_SuccessInvalidSubscription() (gas: 13504) +FunctionsSubscriptions_GetFlags:test_GetFlags_SuccessValidSubscription() (gas: 41221) FunctionsSubscriptions_GetSubscription:test_GetSubscription_Success() (gas: 32968) FunctionsSubscriptions_GetSubscriptionCount:test_GetSubscriptionCount_Success() (gas: 13305) -FunctionsSubscriptions_GetSubscriptionsInRange:test_GetSubscriptionsInRange_RevertIfEndIsAfterLastSubscription() (gas: 16547) +FunctionsSubscriptions_GetSubscriptionsInRange:test_GetSubscriptionsInRange_RevertIfEndIsAfterLastSubscription() (gas: 16570) FunctionsSubscriptions_GetSubscriptionsInRange:test_GetSubscriptionsInRange_RevertIfStartIsAfterEnd() (gas: 13465) -FunctionsSubscriptions_GetSubscriptionsInRange:test_GetSubscriptionsInRange_Success() (gas: 65990) -FunctionsSubscriptions_GetTotalBalance:test_GetTotalBalance_Success() (gas: 15347) +FunctionsSubscriptions_GetSubscriptionsInRange:test_GetSubscriptionsInRange_Success() (gas: 65968) +FunctionsSubscriptions_GetTotalBalance:test_GetTotalBalance_Success() (gas: 15370) FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_RevertIfCallerIsNoCalldata() (gas: 39908) FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_RevertIfCallerIsNoSubscription() (gas: 42382) FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_RevertIfCallerIsNotLink() (gas: 13419) FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_RevertIfPaused() (gas: 47325) FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_Success() (gas: 84314) -FunctionsSubscriptions_OracleWithdraw:test_OracleWithdraw_RevertIfAmountMoreThanBalance() (gas: 20766) +FunctionsSubscriptions_OracleWithdraw:test_OracleWithdraw_RevertIfAmountMoreThanBalance() (gas: 20744) FunctionsSubscriptions_OracleWithdraw:test_OracleWithdraw_RevertIfBalanceInvariant() (gas: 189) -FunctionsSubscriptions_OracleWithdraw:test_OracleWithdraw_RevertIfNoAmount() (gas: 15641) +FunctionsSubscriptions_OracleWithdraw:test_OracleWithdraw_RevertIfNoAmount() (gas: 15686) FunctionsSubscriptions_OracleWithdraw:test_OracleWithdraw_RevertIfPaused() (gas: 20859) -FunctionsSubscriptions_OracleWithdraw:test_OracleWithdraw_SuccessPaysRecipient() (gas: 60075) +FunctionsSubscriptions_OracleWithdraw:test_OracleWithdraw_SuccessPaysRecipient() (gas: 60119) FunctionsSubscriptions_OracleWithdraw:test_OracleWithdraw_SuccessSetsBalanceToZero() (gas: 57716) -FunctionsSubscriptions_OwnerCancelSubscription:test_OwnerCancelSubscription_RevertIfNoSubscription() (gas: 12818) -FunctionsSubscriptions_OwnerCancelSubscription:test_OwnerCancelSubscription_RevertIfNotOwner() (gas: 15549) -FunctionsSubscriptions_OwnerCancelSubscription:test_OwnerCancelSubscription_Success() (gas: 55141) +FunctionsSubscriptions_OwnerCancelSubscription:test_OwnerCancelSubscription_RevertIfNoSubscription() (gas: 12796) +FunctionsSubscriptions_OwnerCancelSubscription:test_OwnerCancelSubscription_RevertIfNotOwner() (gas: 15594) +FunctionsSubscriptions_OwnerCancelSubscription:test_OwnerCancelSubscription_Success() (gas: 55177) FunctionsSubscriptions_OwnerCancelSubscription:test_OwnerCancelSubscription_SuccessDeletesSubscription() (gas: 49607) FunctionsSubscriptions_OwnerCancelSubscription:test_OwnerCancelSubscription_SuccessSubOwnerRefunded() (gas: 53166) -FunctionsSubscriptions_OwnerCancelSubscription:test_OwnerCancelSubscription_SuccessWhenRequestInFlight() (gas: 186533) -FunctionsSubscriptions_OwnerWithdraw:test_OwnerWithdraw_RevertIfAmountMoreThanBalance() (gas: 17945) +FunctionsSubscriptions_OwnerCancelSubscription:test_OwnerCancelSubscription_SuccessWhenRequestInFlight() (gas: 186511) +FunctionsSubscriptions_OwnerWithdraw:test_OwnerWithdraw_RevertIfAmountMoreThanBalance() (gas: 17923) FunctionsSubscriptions_OwnerWithdraw:test_OwnerWithdraw_RevertIfBalanceInvariant() (gas: 210) -FunctionsSubscriptions_OwnerWithdraw:test_OwnerWithdraw_RevertIfNotOwner() (gas: 15555) +FunctionsSubscriptions_OwnerWithdraw:test_OwnerWithdraw_RevertIfNotOwner() (gas: 15600) FunctionsSubscriptions_OwnerWithdraw:test_OwnerWithdraw_SuccessIfNoAmount() (gas: 33839) -FunctionsSubscriptions_OwnerWithdraw:test_OwnerWithdraw_SuccessIfRecipientAddressZero() (gas: 31649) +FunctionsSubscriptions_OwnerWithdraw:test_OwnerWithdraw_SuccessIfRecipientAddressZero() (gas: 31627) FunctionsSubscriptions_OwnerWithdraw:test_OwnerWithdraw_SuccessPaysRecipient() (gas: 33935) FunctionsSubscriptions_OwnerWithdraw:test_OwnerWithdraw_SuccessSetsBalanceToZero() (gas: 31584) -FunctionsSubscriptions_PendingRequestExists:test_PendingRequestExists_SuccessFalseIfNoPendingRequests() (gas: 17818) -FunctionsSubscriptions_PendingRequestExists:test_PendingRequestExists_SuccessTrueIfPendingRequests() (gas: 203333) -FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_RevertIfEmptyNewOwner() (gas: 27664) -FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_RevertIfInvalidNewOwner() (gas: 57815) +FunctionsSubscriptions_PendingRequestExists:test_PendingRequestExists_SuccessFalseIfNoPendingRequests() (gas: 17796) +FunctionsSubscriptions_PendingRequestExists:test_PendingRequestExists_SuccessTrueIfPendingRequests() (gas: 203311) +FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_RevertIfEmptyNewOwner() (gas: 27642) +FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_RevertIfInvalidNewOwner() (gas: 57793) FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_RevertIfNoSubscription() (gas: 15013) -FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_RevertIfNotAllowedSender() (gas: 119775) -FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_RevertIfNotSubscriptionOwner() (gas: 17969) -FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_RevertIfPaused() (gas: 20137) -FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_Success() (gas: 68596) -FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_SuccessChangeProposedOwner() (gas: 83539) -FunctionsSubscriptions_RecoverFunds:test_OwnerCancelSubscription_RevertIfNotOwner() (gas: 15554) -FunctionsSubscriptions_RecoverFunds:test_RecoverFunds_Success() (gas: 41376) +FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_RevertIfNotAllowedSender() (gas: 119820) +FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_RevertIfNotSubscriptionOwner() (gas: 17947) +FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_RevertIfPaused() (gas: 20181) +FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_Success() (gas: 68574) +FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_SuccessChangeProposedOwner() (gas: 83582) +FunctionsSubscriptions_RecoverFunds:test_OwnerCancelSubscription_RevertIfNotOwner() (gas: 15577) +FunctionsSubscriptions_RecoverFunds:test_RecoverFunds_Success() (gas: 41358) FunctionsSubscriptions_RemoveConsumer:test_RemoveConsumer_RevertIfInvalidConsumer() (gas: 30310) FunctionsSubscriptions_RemoveConsumer:test_RemoveConsumer_RevertIfNoSubscription() (gas: 15031) FunctionsSubscriptions_RemoveConsumer:test_RemoveConsumer_RevertIfNotAllowedSender() (gas: 102444) -FunctionsSubscriptions_RemoveConsumer:test_RemoveConsumer_RevertIfNotSubscriptionOwner() (gas: 87254) -FunctionsSubscriptions_RemoveConsumer:test_RemoveConsumer_RevertIfPaused() (gas: 18058) +FunctionsSubscriptions_RemoveConsumer:test_RemoveConsumer_RevertIfNotSubscriptionOwner() (gas: 87277) +FunctionsSubscriptions_RemoveConsumer:test_RemoveConsumer_RevertIfPaused() (gas: 18103) FunctionsSubscriptions_RemoveConsumer:test_RemoveConsumer_RevertIfPendingRequests() (gas: 215863) -FunctionsSubscriptions_RemoveConsumer:test_RemoveConsumer_Success() (gas: 42088) +FunctionsSubscriptions_RemoveConsumer:test_RemoveConsumer_Success() (gas: 42066) FunctionsSubscriptions_SetFlags:test_SetFlags_RevertIfNoSubscription() (gas: 12888) FunctionsSubscriptions_SetFlags:test_SetFlags_RevertIfNotOwner() (gas: 15684) FunctionsSubscriptions_SetFlags:test_SetFlags_Success() (gas: 38434) FunctionsSubscriptions_TimeoutRequests:test_TimeoutRequests_RevertIfPaused() (gas: 25955) FunctionsSubscriptions_TimeoutRequests:test_TimeoutRequests_RevertIfTimeoutNotExceeded() (gas: 25261) -FunctionsSubscriptions_TimeoutRequests:test_TimeoutRequests_RevertInvalidRequest() (gas: 28242) -FunctionsSubscriptions_TimeoutRequests:test_TimeoutRequests_Success() (gas: 58416) -FunctionsSubscriptions_createSubscription:test_CreateSubscription_RevertIfNotAllowedSender() (gas: 26418) +FunctionsSubscriptions_TimeoutRequests:test_TimeoutRequests_RevertInvalidRequest() (gas: 28220) +FunctionsSubscriptions_TimeoutRequests:test_TimeoutRequests_Success() (gas: 58394) +FunctionsSubscriptions_createSubscription:test_CreateSubscription_RevertIfNotAllowedSender() (gas: 26462) FunctionsSubscriptions_createSubscription:test_CreateSubscription_RevertIfPaused() (gas: 15759) FunctionsSubscriptions_createSubscription:test_CreateSubscription_Success() (gas: 153701) -FunctionsTermsOfServiceAllowList_AcceptTermsOfService:testAcceptTermsOfService_InvalidSigner_vuln() (gas: 94913) -FunctionsTermsOfServiceAllowList_AcceptTermsOfService:test_AcceptTermsOfService_RevertIfAcceptorIsNotSender() (gas: 25859) -FunctionsTermsOfServiceAllowList_AcceptTermsOfService:test_AcceptTermsOfService_RevertIfBlockedSender() (gas: 88990) -FunctionsTermsOfServiceAllowList_AcceptTermsOfService:test_AcceptTermsOfService_RevertIfInvalidSigner() (gas: 23619) -FunctionsTermsOfServiceAllowList_AcceptTermsOfService:test_AcceptTermsOfService_RevertIfRecipientContractIsNotSender() (gas: 1866552) -FunctionsTermsOfServiceAllowList_AcceptTermsOfService:test_AcceptTermsOfService_RevertIfRecipientIsNotSender() (gas: 26025) -FunctionsTermsOfServiceAllowList_AcceptTermsOfService:test_AcceptTermsOfService_SuccessIfAcceptingForContract() (gas: 1946965) -FunctionsTermsOfServiceAllowList_AcceptTermsOfService:test_AcceptTermsOfService_SuccessIfAcceptingForSelf() (gas: 104509) -FunctionsTermsOfServiceAllowList_BlockSender:test_BlockSender_RevertIfNotOwner() (gas: 15491) -FunctionsTermsOfServiceAllowList_BlockSender:test_BlockSender_Success() (gas: 97541) +FunctionsTermsOfServiceAllowList_AcceptTermsOfService:testAcceptTermsOfService_InvalidSigner_vuln() (gas: 94943) +FunctionsTermsOfServiceAllowList_AcceptTermsOfService:test_AcceptTermsOfService_RevertIfAcceptorIsNotSender() (gas: 25925) +FunctionsTermsOfServiceAllowList_AcceptTermsOfService:test_AcceptTermsOfService_RevertIfBlockedSender() (gas: 89013) +FunctionsTermsOfServiceAllowList_AcceptTermsOfService:test_AcceptTermsOfService_RevertIfInvalidSigner() (gas: 23620) +FunctionsTermsOfServiceAllowList_AcceptTermsOfService:test_AcceptTermsOfService_RevertIfRecipientContractIsNotSender() (gas: 1866619) +FunctionsTermsOfServiceAllowList_AcceptTermsOfService:test_AcceptTermsOfService_RevertIfRecipientIsNotSender() (gas: 28526) +FunctionsTermsOfServiceAllowList_AcceptTermsOfService:test_AcceptTermsOfService_SuccessIfAcceptingForContract() (gas: 1946966) +FunctionsTermsOfServiceAllowList_AcceptTermsOfService:test_AcceptTermsOfService_SuccessIfAcceptingForSelf() (gas: 104555) +FunctionsTermsOfServiceAllowList_BlockSender:test_BlockSender_RevertIfNotOwner() (gas: 15535) +FunctionsTermsOfServiceAllowList_BlockSender:test_BlockSender_Success() (gas: 97587) FunctionsTermsOfServiceAllowList_Constructor:test_Constructor_Success() (gas: 15345) FunctionsTermsOfServiceAllowList_GetAllAllowedSenders:test_GetAllAllowedSenders_Success() (gas: 19243) FunctionsTermsOfServiceAllowList_GetAllowedSendersCount:test_GetAllowedSendersCount_Success() (gas: 13332) -FunctionsTermsOfServiceAllowList_GetAllowedSendersInRange:test_GetAllowedSendersInRange_RevertIfAllowedSendersIsEmpty() (gas: 13153024) -FunctionsTermsOfServiceAllowList_GetAllowedSendersInRange:test_GetAllowedSendersInRange_RevertIfEndIsAfterLastAllowedSender() (gas: 16554) -FunctionsTermsOfServiceAllowList_GetAllowedSendersInRange:test_GetAllowedSendersInRange_RevertIfStartIsAfterEnd() (gas: 13284) -FunctionsTermsOfServiceAllowList_GetAllowedSendersInRange:test_GetAllowedSendersInRange_Success() (gas: 20312) +FunctionsTermsOfServiceAllowList_GetAllowedSendersInRange:test_GetAllowedSendersInRange_RevertIfAllowedSendersIsEmpty() (gas: 13326576) +FunctionsTermsOfServiceAllowList_GetAllowedSendersInRange:test_GetAllowedSendersInRange_RevertIfEndIsAfterLastAllowedSender() (gas: 16532) +FunctionsTermsOfServiceAllowList_GetAllowedSendersInRange:test_GetAllowedSendersInRange_RevertIfStartIsAfterEnd() (gas: 13307) +FunctionsTermsOfServiceAllowList_GetAllowedSendersInRange:test_GetAllowedSendersInRange_Success() (gas: 20335) FunctionsTermsOfServiceAllowList_GetBlockedSendersCount:test_GetBlockedSendersCount_Success() (gas: 13268) -FunctionsTermsOfServiceAllowList_GetBlockedSendersInRange:test_GetBlockedSendersInRange_RevertIfAllowedSendersIsEmpty() (gas: 13153034) +FunctionsTermsOfServiceAllowList_GetBlockedSendersInRange:test_GetBlockedSendersInRange_RevertIfAllowedSendersIsEmpty() (gas: 13326564) FunctionsTermsOfServiceAllowList_GetBlockedSendersInRange:test_GetBlockedSendersInRange_RevertIfEndIsAfterLastAllowedSender() (gas: 16549) -FunctionsTermsOfServiceAllowList_GetBlockedSendersInRange:test_GetBlockedSendersInRange_RevertIfStartIsAfterEnd() (gas: 13367) -FunctionsTermsOfServiceAllowList_GetBlockedSendersInRange:test_GetBlockedSendersInRange_Success() (gas: 18537) -FunctionsTermsOfServiceAllowList_GetConfig:test_GetConfig_Success() (gas: 16388) +FunctionsTermsOfServiceAllowList_GetBlockedSendersInRange:test_GetBlockedSendersInRange_RevertIfStartIsAfterEnd() (gas: 13345) +FunctionsTermsOfServiceAllowList_GetBlockedSendersInRange:test_GetBlockedSendersInRange_Success() (gas: 18580) +FunctionsTermsOfServiceAllowList_GetConfig:test_GetConfig_Success() (gas: 16411) FunctionsTermsOfServiceAllowList_GetMessage:test_GetMessage_Success() (gas: 11918) -FunctionsTermsOfServiceAllowList_HasAccess:test_HasAccess_FalseWhenEnabled() (gas: 16257) -FunctionsTermsOfServiceAllowList_HasAccess:test_HasAccess_TrueWhenDisabled() (gas: 23848) +FunctionsTermsOfServiceAllowList_HasAccess:test_HasAccess_FalseWhenEnabled() (gas: 16235) +FunctionsTermsOfServiceAllowList_HasAccess:test_HasAccess_TrueWhenDisabled() (gas: 23877) FunctionsTermsOfServiceAllowList_IsBlockedSender:test_IsBlockedSender_SuccessFalse() (gas: 15776) FunctionsTermsOfServiceAllowList_IsBlockedSender:test_IsBlockedSender_SuccessTrue() (gas: 86974) -FunctionsTermsOfServiceAllowList_UnblockSender:test_UnblockSender_RevertIfNotOwner() (gas: 13502) -FunctionsTermsOfServiceAllowList_UnblockSender:test_UnblockSender_Success() (gas: 96216) -FunctionsTermsOfServiceAllowList_UpdateConfig:test_UpdateConfig_RevertIfNotOwner() (gas: 13812) -FunctionsTermsOfServiceAllowList_UpdateConfig:test_UpdateConfig_Success() (gas: 22817) -Gas_AcceptTermsOfService:test_AcceptTermsOfService_Gas() (gas: 84702) +FunctionsTermsOfServiceAllowList_MigratePreviouslyAllowedSenders:test_MigratePreviouslyAllowedSenders_RevertIfNotOwner() (gas: 13987) +FunctionsTermsOfServiceAllowList_MigratePreviouslyAllowedSenders:test_MigratePreviouslyAllowedSenders_Success() (gas: 210636) +FunctionsTermsOfServiceAllowList_UnblockSender:test_UnblockSender_RevertIfNotOwner() (gas: 13548) +FunctionsTermsOfServiceAllowList_UnblockSender:test_UnblockSender_Success() (gas: 96240) +FunctionsTermsOfServiceAllowList_UpdateConfig:test_UpdateConfig_RevertIfNotOwner() (gas: 13819) +FunctionsTermsOfServiceAllowList_UpdateConfig:test_UpdateConfig_Success() (gas: 22824) +Gas_AcceptTermsOfService:test_AcceptTermsOfService_Gas() (gas: 84725) Gas_AddConsumer:test_AddConsumer_Gas() (gas: 79140) Gas_CreateSubscription:test_CreateSubscription_Gas() (gas: 73419) -Gas_FulfillRequest_DuplicateRequestID:test_FulfillRequest_DuplicateRequestID_MaximumGas() (gas: 20717) -Gas_FulfillRequest_DuplicateRequestID:test_FulfillRequest_DuplicateRequestID_MinimumGas() (gas: 20157) -Gas_FulfillRequest_Success:test_FulfillRequest_Success_MaximumGas() (gas: 501339) -Gas_FulfillRequest_Success:test_FulfillRequest_Success_MinimumGas() (gas: 202509) -Gas_FundSubscription:test_FundSubscription_Gas() (gas: 38524) -Gas_SendRequest:test_SendRequest_MaximumGas() (gas: 988895) -Gas_SendRequest:test_SendRequest_MinimumGas() (gas: 181579) \ No newline at end of file +Gas_FulfillRequest_DuplicateRequestID:test_FulfillRequest_DuplicateRequestID_MaximumGas() (gas: 20562) +Gas_FulfillRequest_DuplicateRequestID:test_FulfillRequest_DuplicateRequestID_MinimumGas() (gas: 20024) +Gas_FulfillRequest_Success:test_FulfillRequest_Success_MaximumGas() (gas: 501184) +Gas_FulfillRequest_Success:test_FulfillRequest_Success_MinimumGas() (gas: 202376) +Gas_FundSubscription:test_FundSubscription_Gas() (gas: 38518) +Gas_SendRequest:test_SendRequest_MaximumGas() (gas: 984338) +Gas_SendRequest:test_SendRequest_MinimumGas() (gas: 181561) \ No newline at end of file diff --git a/contracts/gas-snapshots/keystone.gas-snapshot b/contracts/gas-snapshots/keystone.gas-snapshot index 2880e4c0e3..d75d68a172 100644 --- a/contracts/gas-snapshots/keystone.gas-snapshot +++ b/contracts/gas-snapshots/keystone.gas-snapshot @@ -1,107 +1,114 @@ -CapabilitiesRegistry_AddCapabilitiesTest:test_AddCapability_NoConfigurationContract() (gas: 154832) -CapabilitiesRegistry_AddCapabilitiesTest:test_AddCapability_WithConfiguration() (gas: 178813) -CapabilitiesRegistry_AddCapabilitiesTest:test_RevertWhen_CalledByNonAdmin() (gas: 24723) -CapabilitiesRegistry_AddCapabilitiesTest:test_RevertWhen_CapabilityExists() (gas: 145703) -CapabilitiesRegistry_AddCapabilitiesTest:test_RevertWhen_ConfigurationContractDoesNotMatchInterface() (gas: 94606) -CapabilitiesRegistry_AddCapabilitiesTest:test_RevertWhen_ConfigurationContractNotDeployed() (gas: 92961) -CapabilitiesRegistry_AddDONTest:test_AddDON() (gas: 372302) +CapabilitiesRegistry_AddCapabilitiesTest:test_AddCapability_NoConfigurationContract() (gas: 154809) +CapabilitiesRegistry_AddCapabilitiesTest:test_AddCapability_WithConfiguration() (gas: 178790) +CapabilitiesRegistry_AddCapabilitiesTest:test_RevertWhen_CalledByNonAdmin() (gas: 24678) +CapabilitiesRegistry_AddCapabilitiesTest:test_RevertWhen_CapabilityExists() (gas: 145613) +CapabilitiesRegistry_AddCapabilitiesTest:test_RevertWhen_ConfigurationContractDoesNotMatchInterface() (gas: 94561) +CapabilitiesRegistry_AddCapabilitiesTest:test_RevertWhen_ConfigurationContractNotDeployed() (gas: 92916) +CapabilitiesRegistry_AddDONTest:test_AddDON() (gas: 373685) CapabilitiesRegistry_AddDONTest:test_RevertWhen_CalledByNonAdmin() (gas: 19273) CapabilitiesRegistry_AddDONTest:test_RevertWhen_CapabilityDoesNotExist() (gas: 169752) -CapabilitiesRegistry_AddDONTest:test_RevertWhen_DeprecatedCapabilityAdded() (gas: 239789) -CapabilitiesRegistry_AddDONTest:test_RevertWhen_DuplicateCapabilityAdded() (gas: 249596) +CapabilitiesRegistry_AddDONTest:test_RevertWhen_DeprecatedCapabilityAdded() (gas: 239724) +CapabilitiesRegistry_AddDONTest:test_RevertWhen_DuplicateCapabilityAdded() (gas: 250935) CapabilitiesRegistry_AddDONTest:test_RevertWhen_DuplicateNodeAdded() (gas: 116890) CapabilitiesRegistry_AddDONTest:test_RevertWhen_FaultToleranceIsZero() (gas: 43358) CapabilitiesRegistry_AddDONTest:test_RevertWhen_NodeAlreadyBelongsToWorkflowDON() (gas: 343924) CapabilitiesRegistry_AddDONTest:test_RevertWhen_NodeDoesNotSupportCapability() (gas: 180150) -CapabilitiesRegistry_AddNodeOperatorsTest:test_AddNodeOperators() (gas: 184135) -CapabilitiesRegistry_AddNodeOperatorsTest:test_RevertWhen_CalledByNonAdmin() (gas: 17602) -CapabilitiesRegistry_AddNodeOperatorsTest:test_RevertWhen_NodeOperatorAdminAddressZero() (gas: 18498) -CapabilitiesRegistry_AddNodesTest:test_AddsNodeParams() (gas: 358448) -CapabilitiesRegistry_AddNodesTest:test_OwnerCanAddNodes() (gas: 358414) -CapabilitiesRegistry_AddNodesTest:test_RevertWhen_AddingDuplicateP2PId() (gas: 301229) -CapabilitiesRegistry_AddNodesTest:test_RevertWhen_AddingNodeWithInvalidCapability() (gas: 55174) -CapabilitiesRegistry_AddNodesTest:test_RevertWhen_AddingNodeWithInvalidNodeOperator() (gas: 24895) -CapabilitiesRegistry_AddNodesTest:test_RevertWhen_AddingNodeWithoutCapabilities() (gas: 27669) -CapabilitiesRegistry_AddNodesTest:test_RevertWhen_CalledByNonNodeOperatorAdminAndNonOwner() (gas: 25108) -CapabilitiesRegistry_AddNodesTest:test_RevertWhen_P2PIDEmpty() (gas: 27408) -CapabilitiesRegistry_AddNodesTest:test_RevertWhen_SignerAddressEmpty() (gas: 27047) -CapabilitiesRegistry_AddNodesTest:test_RevertWhen_SignerAddressNotUnique() (gas: 309679) -CapabilitiesRegistry_DeprecateCapabilitiesTest:test_DeprecatesCapability() (gas: 89807) -CapabilitiesRegistry_DeprecateCapabilitiesTest:test_EmitsEvent() (gas: 89935) -CapabilitiesRegistry_DeprecateCapabilitiesTest:test_RevertWhen_CalledByNonAdmin() (gas: 22944) -CapabilitiesRegistry_DeprecateCapabilitiesTest:test_RevertWhen_CapabilityDoesNotExist() (gas: 16231) -CapabilitiesRegistry_DeprecateCapabilitiesTest:test_RevertWhen_CapabilityIsDeprecated() (gas: 91264) -CapabilitiesRegistry_GetCapabilitiesTest:test_ReturnsCapabilities() (gas: 135553) +CapabilitiesRegistry_AddDONTest_WhenMaliciousCapabilityConfigurationConfigured:test_RevertWhen_MaliciousCapabilitiesConfigContractTriesToRemoveCapabilitiesFromDONNodes() (gas: 340499) +CapabilitiesRegistry_AddNodeOperatorsTest:test_AddNodeOperators() (gas: 184157) +CapabilitiesRegistry_AddNodeOperatorsTest:test_RevertWhen_CalledByNonAdmin() (gas: 17624) +CapabilitiesRegistry_AddNodeOperatorsTest:test_RevertWhen_NodeOperatorAdminAddressZero() (gas: 18520) +CapabilitiesRegistry_AddNodesTest:test_AddsNodeParams() (gas: 358492) +CapabilitiesRegistry_AddNodesTest:test_OwnerCanAddNodes() (gas: 358458) +CapabilitiesRegistry_AddNodesTest:test_RevertWhen_AddingDuplicateP2PId() (gas: 301273) +CapabilitiesRegistry_AddNodesTest:test_RevertWhen_AddingNodeWithInvalidCapability() (gas: 55196) +CapabilitiesRegistry_AddNodesTest:test_RevertWhen_AddingNodeWithInvalidNodeOperator() (gas: 24917) +CapabilitiesRegistry_AddNodesTest:test_RevertWhen_AddingNodeWithoutCapabilities() (gas: 27691) +CapabilitiesRegistry_AddNodesTest:test_RevertWhen_CalledByNonNodeOperatorAdminAndNonOwner() (gas: 25130) +CapabilitiesRegistry_AddNodesTest:test_RevertWhen_P2PIDEmpty() (gas: 27430) +CapabilitiesRegistry_AddNodesTest:test_RevertWhen_SignerAddressEmpty() (gas: 27069) +CapabilitiesRegistry_AddNodesTest:test_RevertWhen_SignerAddressNotUnique() (gas: 309723) +CapabilitiesRegistry_DeprecateCapabilitiesTest:test_DeprecatesCapability() (gas: 89742) +CapabilitiesRegistry_DeprecateCapabilitiesTest:test_EmitsEvent() (gas: 89870) +CapabilitiesRegistry_DeprecateCapabilitiesTest:test_RevertWhen_CalledByNonAdmin() (gas: 22879) +CapabilitiesRegistry_DeprecateCapabilitiesTest:test_RevertWhen_CapabilityDoesNotExist() (gas: 16166) +CapabilitiesRegistry_DeprecateCapabilitiesTest:test_RevertWhen_CapabilityIsDeprecated() (gas: 91134) +CapabilitiesRegistry_GetCapabilitiesTest:test_ReturnsCapabilities() (gas: 135488) CapabilitiesRegistry_GetDONsTest:test_CorrectlyFetchesDONs() (gas: 65468) CapabilitiesRegistry_GetDONsTest:test_DoesNotIncludeRemovedDONs() (gas: 64924) CapabilitiesRegistry_GetHashedCapabilityTest:test_CorrectlyGeneratesHashedCapabilityId() (gas: 11428) CapabilitiesRegistry_GetHashedCapabilityTest:test_DoesNotCauseIncorrectClashes() (gas: 13087) -CapabilitiesRegistry_GetNodeOperatorsTest:test_CorrectlyFetchesNodeOperators() (gas: 36407) -CapabilitiesRegistry_GetNodeOperatorsTest:test_DoesNotIncludeRemovedNodeOperators() (gas: 38692) +CapabilitiesRegistry_GetNodeOperatorsTest:test_CorrectlyFetchesNodeOperators() (gas: 36429) +CapabilitiesRegistry_GetNodeOperatorsTest:test_DoesNotIncludeRemovedNodeOperators() (gas: 38714) CapabilitiesRegistry_GetNodesTest:test_CorrectlyFetchesNodes() (gas: 65288) -CapabilitiesRegistry_GetNodesTest:test_DoesNotIncludeRemovedNodes() (gas: 73533) -CapabilitiesRegistry_RemoveDONsTest:test_RemovesDON() (gas: 54761) +CapabilitiesRegistry_GetNodesTest:test_DoesNotIncludeRemovedNodes() (gas: 73497) +CapabilitiesRegistry_RemoveDONsTest:test_RemovesDON() (gas: 54783) CapabilitiesRegistry_RemoveDONsTest:test_RevertWhen_CalledByNonAdmin() (gas: 15647) CapabilitiesRegistry_RemoveDONsTest:test_RevertWhen_DONDoesNotExist() (gas: 16550) CapabilitiesRegistry_RemoveNodeOperatorsTest:test_RemovesNodeOperator() (gas: 36122) CapabilitiesRegistry_RemoveNodeOperatorsTest:test_RevertWhen_CalledByNonOwner() (gas: 15816) -CapabilitiesRegistry_RemoveNodesTest:test_CanAddNodeWithSameSignerAddressAfterRemoving() (gas: 115151) -CapabilitiesRegistry_RemoveNodesTest:test_CanRemoveWhenDONDeleted() (gas: 287716) -CapabilitiesRegistry_RemoveNodesTest:test_CanRemoveWhenNodeNoLongerPartOfDON() (gas: 561023) -CapabilitiesRegistry_RemoveNodesTest:test_OwnerCanRemoveNodes() (gas: 73376) -CapabilitiesRegistry_RemoveNodesTest:test_RemovesNode() (gas: 75211) -CapabilitiesRegistry_RemoveNodesTest:test_RevertWhen_CalledByNonNodeOperatorAdminAndNonOwner() (gas: 25053) -CapabilitiesRegistry_RemoveNodesTest:test_RevertWhen_NodeDoesNotExist() (gas: 18418) -CapabilitiesRegistry_RemoveNodesTest:test_RevertWhen_NodePartOfCapabilitiesDON() (gas: 385369) -CapabilitiesRegistry_RemoveNodesTest:test_RevertWhen_P2PIDEmpty() (gas: 18408) +CapabilitiesRegistry_RemoveNodesTest:test_CanAddNodeWithSameSignerAddressAfterRemoving() (gas: 115150) +CapabilitiesRegistry_RemoveNodesTest:test_CanRemoveWhenDONDeleted() (gas: 287648) +CapabilitiesRegistry_RemoveNodesTest:test_CanRemoveWhenNodeNoLongerPartOfDON() (gas: 560993) +CapabilitiesRegistry_RemoveNodesTest:test_OwnerCanRemoveNodes() (gas: 73358) +CapabilitiesRegistry_RemoveNodesTest:test_RemovesNode() (gas: 75192) +CapabilitiesRegistry_RemoveNodesTest:test_RevertWhen_CalledByNonNodeOperatorAdminAndNonOwner() (gas: 25008) +CapabilitiesRegistry_RemoveNodesTest:test_RevertWhen_NodeDoesNotExist() (gas: 18373) +CapabilitiesRegistry_RemoveNodesTest:test_RevertWhen_NodePartOfCapabilitiesDON() (gas: 385324) +CapabilitiesRegistry_RemoveNodesTest:test_RevertWhen_P2PIDEmpty() (gas: 18363) CapabilitiesRegistry_TypeAndVersionTest:test_TypeAndVersion() (gas: 9796) -CapabilitiesRegistry_UpdateDONTest:test_RevertWhen_CalledByNonAdmin() (gas: 19415) -CapabilitiesRegistry_UpdateDONTest:test_RevertWhen_CapabilityDoesNotExist() (gas: 152914) -CapabilitiesRegistry_UpdateDONTest:test_RevertWhen_DONDoesNotExist() (gas: 17835) -CapabilitiesRegistry_UpdateDONTest:test_RevertWhen_DeprecatedCapabilityAdded() (gas: 222996) -CapabilitiesRegistry_UpdateDONTest:test_RevertWhen_DuplicateCapabilityAdded() (gas: 232804) -CapabilitiesRegistry_UpdateDONTest:test_RevertWhen_DuplicateNodeAdded() (gas: 107643) -CapabilitiesRegistry_UpdateDONTest:test_RevertWhen_NodeDoesNotSupportCapability() (gas: 163357) -CapabilitiesRegistry_UpdateDONTest:test_UpdatesDON() (gas: 371909) -CapabilitiesRegistry_UpdateNodeOperatorTest:test_RevertWhen_CalledByNonAdminAndNonOwner() (gas: 20631) -CapabilitiesRegistry_UpdateNodeOperatorTest:test_RevertWhen_NodeOperatorAdminIsZeroAddress() (gas: 20052) -CapabilitiesRegistry_UpdateNodeOperatorTest:test_RevertWhen_NodeOperatorDoesNotExist() (gas: 19790) -CapabilitiesRegistry_UpdateNodeOperatorTest:test_RevertWhen_NodeOperatorIdAndParamLengthsMismatch() (gas: 15430) -CapabilitiesRegistry_UpdateNodeOperatorTest:test_UpdatesNodeOperator() (gas: 36937) -CapabilitiesRegistry_UpdateNodesTest:test_CanUpdateParamsIfNodeSignerAddressNoLongerUsed() (gas: 256157) -CapabilitiesRegistry_UpdateNodesTest:test_OwnerCanUpdateNodes() (gas: 162059) -CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_AddingNodeWithInvalidCapability() (gas: 35766) -CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_CalledByNonNodeOperatorAdminAndNonOwner() (gas: 25069) -CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_NodeDoesNotExist() (gas: 27308) -CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_NodeSignerAlreadyAssignedToAnotherNode() (gas: 29219) -CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_P2PIDEmpty() (gas: 27296) -CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_RemovingCapabilityRequiredByCapabilityDON() (gas: 470803) -CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_RemovingCapabilityRequiredByWorkflowDON() (gas: 341084) -CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_SignerAddressEmpty() (gas: 26951) -CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_UpdatingNodeWithoutCapabilities() (gas: 25480) -CapabilitiesRegistry_UpdateNodesTest:test_UpdatesNodeParams() (gas: 162113) -KeystoneForwarder_ReportTest:test_Report_ConfigVersion() (gas: 1797755) -KeystoneForwarder_ReportTest:test_Report_FailedDeliveryWhenReceiverInterfaceNotSupported() (gas: 125910) -KeystoneForwarder_ReportTest:test_Report_FailedDeliveryWhenReceiverNotContract() (gas: 127403) -KeystoneForwarder_ReportTest:test_Report_SuccessfulDelivery() (gas: 155928) -KeystoneForwarder_ReportTest:test_RevertWhen_AlreadyAttempted() (gas: 152358) -KeystoneForwarder_ReportTest:test_RevertWhen_AnySignatureIsInvalid() (gas: 86348) -KeystoneForwarder_ReportTest:test_RevertWhen_AnySignerIsInvalid() (gas: 118486) +CapabilitiesRegistry_UpdateDONTest:test_RevertWhen_CalledByNonAdmin() (gas: 19314) +CapabilitiesRegistry_UpdateDONTest:test_RevertWhen_CapabilityDoesNotExist() (gas: 152949) +CapabilitiesRegistry_UpdateDONTest:test_RevertWhen_DONDoesNotExist() (gas: 17740) +CapabilitiesRegistry_UpdateDONTest:test_RevertWhen_DeprecatedCapabilityAdded() (gas: 222966) +CapabilitiesRegistry_UpdateDONTest:test_RevertWhen_DuplicateCapabilityAdded() (gas: 236977) +CapabilitiesRegistry_UpdateDONTest:test_RevertWhen_DuplicateNodeAdded() (gas: 107678) +CapabilitiesRegistry_UpdateDONTest:test_RevertWhen_NodeDoesNotSupportCapability() (gas: 163392) +CapabilitiesRegistry_UpdateDONTest:test_UpdatesDON() (gas: 373308) +CapabilitiesRegistry_UpdateNodeOperatorTest:test_RevertWhen_CalledByNonAdminAndNonOwner() (gas: 20684) +CapabilitiesRegistry_UpdateNodeOperatorTest:test_RevertWhen_NodeOperatorAdminIsZeroAddress() (gas: 20008) +CapabilitiesRegistry_UpdateNodeOperatorTest:test_RevertWhen_NodeOperatorDoesNotExist() (gas: 19746) +CapabilitiesRegistry_UpdateNodeOperatorTest:test_RevertWhen_NodeOperatorIdAndParamLengthsMismatch() (gas: 15386) +CapabilitiesRegistry_UpdateNodeOperatorTest:test_UpdatesNodeOperator() (gas: 36990) +CapabilitiesRegistry_UpdateNodesTest:test_CanUpdateParamsIfNodeSignerAddressNoLongerUsed() (gas: 256437) +CapabilitiesRegistry_UpdateNodesTest:test_OwnerCanUpdateNodes() (gas: 162210) +CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_AddingNodeWithInvalidCapability() (gas: 35895) +CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_CalledByAnotherNodeOperatorAdmin() (gas: 29222) +CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_CalledByNonNodeOperatorAdminAndNonOwner() (gas: 29399) +CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_NodeDoesNotExist() (gas: 29221) +CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_NodeSignerAlreadyAssignedToAnotherNode() (gas: 31348) +CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_P2PIDEmpty() (gas: 29187) +CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_RemovingCapabilityRequiredByCapabilityDON() (gas: 470932) +CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_RemovingCapabilityRequiredByWorkflowDON() (gas: 341213) +CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_SignerAddressEmpty() (gas: 29080) +CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_UpdatingNodeWithoutCapabilities() (gas: 27609) +CapabilitiesRegistry_UpdateNodesTest:test_UpdatesNodeParams() (gas: 162264) +KeystoneForwarder_ReportTest:test_Report_ConfigVersion() (gas: 2003568) +KeystoneForwarder_ReportTest:test_Report_FailedDeliveryWhenReceiverInterfaceNotSupported() (gas: 124908) +KeystoneForwarder_ReportTest:test_Report_FailedDeliveryWhenReceiverNotContract() (gas: 126927) +KeystoneForwarder_ReportTest:test_Report_SuccessfulDelivery() (gas: 361243) +KeystoneForwarder_ReportTest:test_Report_SuccessfulRetryWithMoreGas() (gas: 501084) +KeystoneForwarder_ReportTest:test_RevertWhen_AnySignatureIsInvalid() (gas: 86326) +KeystoneForwarder_ReportTest:test_RevertWhen_AnySignerIsInvalid() (gas: 118521) +KeystoneForwarder_ReportTest:test_RevertWhen_AttemptingTransmissionWithInsufficientGas() (gas: 96279) KeystoneForwarder_ReportTest:test_RevertWhen_ReportHasDuplicateSignatures() (gas: 94516) KeystoneForwarder_ReportTest:test_RevertWhen_ReportHasIncorrectDON() (gas: 75930) KeystoneForwarder_ReportTest:test_RevertWhen_ReportHasInexistentConfigVersion() (gas: 76298) -KeystoneForwarder_ReportTest:test_RevertWhen_ReportIsMalformed() (gas: 45585) +KeystoneForwarder_ReportTest:test_RevertWhen_ReportIsMalformed() (gas: 45563) +KeystoneForwarder_ReportTest:test_RevertWhen_RetryingInvalidContractTransmission() (gas: 143591) +KeystoneForwarder_ReportTest:test_RevertWhen_RetryingSuccessfulTransmission() (gas: 354042) KeystoneForwarder_ReportTest:test_RevertWhen_TooFewSignatures() (gas: 55292) KeystoneForwarder_ReportTest:test_RevertWhen_TooManySignatures() (gas: 56050) KeystoneForwarder_SetConfigTest:test_RevertWhen_ExcessSigners() (gas: 20184) KeystoneForwarder_SetConfigTest:test_RevertWhen_FaultToleranceIsZero() (gas: 88057) KeystoneForwarder_SetConfigTest:test_RevertWhen_InsufficientSigners() (gas: 14533) -KeystoneForwarder_SetConfigTest:test_RevertWhen_NotOwner() (gas: 88788) -KeystoneForwarder_SetConfigTest:test_RevertWhen_ProvidingDuplicateSigners() (gas: 114507) -KeystoneForwarder_SetConfigTest:test_SetConfig_FirstTime() (gas: 1539921) -KeystoneForwarder_SetConfigTest:test_SetConfig_WhenSignersAreRemoved() (gas: 1534476) +KeystoneForwarder_SetConfigTest:test_RevertWhen_NotOwner() (gas: 88766) +KeystoneForwarder_SetConfigTest:test_RevertWhen_ProvidingDuplicateSigners() (gas: 114570) +KeystoneForwarder_SetConfigTest:test_RevertWhen_ProvidingZeroAddressSigner() (gas: 114225) +KeystoneForwarder_SetConfigTest:test_SetConfig_FirstTime() (gas: 1540541) +KeystoneForwarder_SetConfigTest:test_SetConfig_WhenSignersAreRemoved() (gas: 1535211) KeystoneForwarder_TypeAndVersionTest:test_TypeAndVersion() (gas: 9641) KeystoneRouter_SetConfigTest:test_AddForwarder_RevertWhen_NotOwner() (gas: 10978) KeystoneRouter_SetConfigTest:test_RemoveForwarder_RevertWhen_NotOwner() (gas: 10923) -KeystoneRouter_SetConfigTest:test_Route_RevertWhen_UnauthorizedForwarder() (gas: 18553) -KeystoneRouter_SetConfigTest:test_Route_Success() (gas: 75629) \ No newline at end of file +KeystoneRouter_SetConfigTest:test_RemoveForwarder_Success() (gas: 17599) +KeystoneRouter_SetConfigTest:test_Route_RevertWhen_UnauthorizedForwarder() (gas: 18552) +KeystoneRouter_SetConfigTest:test_Route_Success() (gas: 79379) \ No newline at end of file diff --git a/contracts/gas-snapshots/l2ep.gas-snapshot b/contracts/gas-snapshots/l2ep.gas-snapshot index 324cacfc02..42a9aa0b35 100644 --- a/contracts/gas-snapshots/l2ep.gas-snapshot +++ b/contracts/gas-snapshots/l2ep.gas-snapshot @@ -24,17 +24,9 @@ ArbitrumCrossDomainGovernor_TransferL1Ownership:test_CallableByL1Owner() (gas: 4 ArbitrumCrossDomainGovernor_TransferL1Ownership:test_CallableByL1OwnerOrZeroAddress() (gas: 19312) ArbitrumCrossDomainGovernor_TransferL1Ownership:test_NotCallableByL2Owner() (gas: 18671) ArbitrumCrossDomainGovernor_TransferL1Ownership:test_NotCallableByNonOwners() (gas: 13219) -ArbitrumSequencerUptimeFeed_AggregatorInterfaceGasCosts:test_GasUsageForGetAnswer() (gas: 92790) -ArbitrumSequencerUptimeFeed_AggregatorInterfaceGasCosts:test_GasUsageForGetRoundData() (gas: 93351) -ArbitrumSequencerUptimeFeed_AggregatorInterfaceGasCosts:test_GasUsageForGetTimestamp() (gas: 92711) -ArbitrumSequencerUptimeFeed_AggregatorInterfaceGasCosts:test_GasUsageForLatestAnswer() (gas: 90485) -ArbitrumSequencerUptimeFeed_AggregatorInterfaceGasCosts:test_GasUsageForLatestRound() (gas: 90377) -ArbitrumSequencerUptimeFeed_AggregatorInterfaceGasCosts:test_GasUsageForLatestRoundData() (gas: 90924) -ArbitrumSequencerUptimeFeed_AggregatorInterfaceGasCosts:test_GasUsageForLatestTimestamp() (gas: 90362) ArbitrumSequencerUptimeFeed_AggregatorV3Interface:test_AggregatorV3Interface() (gas: 104994) ArbitrumSequencerUptimeFeed_AggregatorV3Interface:test_Return0WhenRoundDoesNotExistYet() (gas: 20033) ArbitrumSequencerUptimeFeed_Constants:test_InitialState() (gas: 8530) -ArbitrumSequencerUptimeFeed_GasCosts:test_GasCosts() (gas: 99865) ArbitrumSequencerUptimeFeed_ProtectReadsOnAggregatorV2V3InterfaceFunctions:test_AggregatorV2V3InterfaceAllowReadsIfConsumingContractIsWhitelisted() (gas: 604414) ArbitrumSequencerUptimeFeed_ProtectReadsOnAggregatorV2V3InterfaceFunctions:test_AggregatorV2V3InterfaceDisallowReadsIfConsumingContractIsNotWhitelisted() (gas: 574476) ArbitrumSequencerUptimeFeed_UpdateStatus:test_IgnoreOutOfOrderUpdates() (gas: 99662) @@ -68,27 +60,19 @@ OptimismCrossDomainGovernor_TransferL1Ownership:test_CallableByL1Owner() (gas: 4 OptimismCrossDomainGovernor_TransferL1Ownership:test_CallableByL1OwnerOrZeroAddress() (gas: 28775) OptimismCrossDomainGovernor_TransferL1Ownership:test_NotCallableByL2Owner() (gas: 16482) OptimismCrossDomainGovernor_TransferL1Ownership:test_NotCallableByNonOwners() (gas: 11030) -OptimismSequencerUptimeFeed_AggregatorInterfaceGasCosts:test_GasUsageForGetAnswer() (gas: 59785) -OptimismSequencerUptimeFeed_AggregatorInterfaceGasCosts:test_GasUsageForGetRoundData() (gas: 60331) -OptimismSequencerUptimeFeed_AggregatorInterfaceGasCosts:test_GasUsageForGetTimestamp() (gas: 59640) -OptimismSequencerUptimeFeed_AggregatorInterfaceGasCosts:test_GasUsageForLatestAnswer() (gas: 57577) -OptimismSequencerUptimeFeed_AggregatorInterfaceGasCosts:test_GasUsageForLatestRound() (gas: 57463) -OptimismSequencerUptimeFeed_AggregatorInterfaceGasCosts:test_GasUsageForLatestRoundData() (gas: 58005) -OptimismSequencerUptimeFeed_AggregatorInterfaceGasCosts:test_GasUsageForLatestTimestamp() (gas: 57430) -OptimismSequencerUptimeFeed_AggregatorV3Interface:test_AggregatorV3Interface() (gas: 71804) +OptimismSequencerUptimeFeed_AggregatorV3Interface:test_AggregatorV3Interface() (gas: 74304) OptimismSequencerUptimeFeed_AggregatorV3Interface:test_RevertGetAnswerWhenRoundDoesNotExistYet() (gas: 17679) OptimismSequencerUptimeFeed_AggregatorV3Interface:test_RevertGetRoundDataWhenRoundDoesNotExistYet() (gas: 17897) OptimismSequencerUptimeFeed_AggregatorV3Interface:test_RevertGetTimestampWhenRoundDoesNotExistYet() (gas: 17603) OptimismSequencerUptimeFeed_Constructor:test_InitialState() (gas: 22110) -OptimismSequencerUptimeFeed_GasCosts:test_GasCosts() (gas: 69567) OptimismSequencerUptimeFeed_ProtectReadsOnAggregatorV2V3InterfaceFunctions:test_AggregatorV2V3InterfaceAllowReadsIfConsumingContractIsWhitelisted() (gas: 601843) OptimismSequencerUptimeFeed_ProtectReadsOnAggregatorV2V3InterfaceFunctions:test_AggregatorV2V3InterfaceDisallowReadsIfConsumingContractIsNotWhitelisted() (gas: 574481) -OptimismSequencerUptimeFeed_UpdateStatus:test_IgnoreOutOfOrderUpdates() (gas: 67230) +OptimismSequencerUptimeFeed_UpdateStatus:test_IgnoreOutOfOrderUpdates() (gas: 69730) OptimismSequencerUptimeFeed_UpdateStatus:test_RevertIfNotL2CrossDomainMessengerAddr() (gas: 13214) OptimismSequencerUptimeFeed_UpdateStatus:test_RevertIfNotL2CrossDomainMessengerAddrAndNotL1SenderAddr() (gas: 23632) -OptimismSequencerUptimeFeed_UpdateStatus:test_UpdateStatusWhenNoChange() (gas: 77137) -OptimismSequencerUptimeFeed_UpdateStatus:test_UpdateStatusWhenStatusChangeAndNoTimeChange() (gas: 97545) -OptimismSequencerUptimeFeed_UpdateStatus:test_UpdateStatusWhenStatusChangeAndTimeChange() (gas: 97605) +OptimismSequencerUptimeFeed_UpdateStatus:test_UpdateStatusWhenNoChange() (gas: 79637) +OptimismSequencerUptimeFeed_UpdateStatus:test_UpdateStatusWhenStatusChangeAndNoTimeChange() (gas: 100045) +OptimismSequencerUptimeFeed_UpdateStatus:test_UpdateStatusWhenStatusChangeAndTimeChange() (gas: 100105) OptimismValidator_SetGasLimit:test_CorrectlyUpdatesTheGasLimit() (gas: 18695) OptimismValidator_Validate:test_PostSequencerOffline() (gas: 74813) OptimismValidator_Validate:test_PostSequencerStatusWhenThereIsNotStatusChange() (gas: 74869) @@ -119,27 +103,19 @@ ScrollCrossDomainGovernor_TransferL1Ownership:test_CallableByL1Owner() (gas: 489 ScrollCrossDomainGovernor_TransferL1Ownership:test_CallableByL1OwnerOrZeroAddress() (gas: 28841) ScrollCrossDomainGovernor_TransferL1Ownership:test_NotCallableByL2Owner() (gas: 16482) ScrollCrossDomainGovernor_TransferL1Ownership:test_NotCallableByNonOwners() (gas: 11030) -ScrollSequencerUptimeFeed_AggregatorInterfaceGasCosts:test_GasUsageForGetAnswer() (gas: 57940) -ScrollSequencerUptimeFeed_AggregatorInterfaceGasCosts:test_GasUsageForGetRoundData() (gas: 58476) -ScrollSequencerUptimeFeed_AggregatorInterfaceGasCosts:test_GasUsageForGetTimestamp() (gas: 57795) -ScrollSequencerUptimeFeed_AggregatorInterfaceGasCosts:test_GasUsageForLatestAnswer() (gas: 55578) -ScrollSequencerUptimeFeed_AggregatorInterfaceGasCosts:test_GasUsageForLatestRound() (gas: 55458) -ScrollSequencerUptimeFeed_AggregatorInterfaceGasCosts:test_GasUsageForLatestRoundData() (gas: 56169) -ScrollSequencerUptimeFeed_AggregatorInterfaceGasCosts:test_GasUsageForLatestTimestamp() (gas: 55448) -ScrollSequencerUptimeFeed_AggregatorV3Interface:test_AggregatorV3Interface() (gas: 70090) +ScrollSequencerUptimeFeed_AggregatorV3Interface:test_AggregatorV3Interface() (gas: 72590) ScrollSequencerUptimeFeed_AggregatorV3Interface:test_RevertGetAnswerWhenRoundDoesNotExistYet() (gas: 17675) ScrollSequencerUptimeFeed_AggregatorV3Interface:test_RevertGetRoundDataWhenRoundDoesNotExistYet() (gas: 17893) ScrollSequencerUptimeFeed_AggregatorV3Interface:test_RevertGetTimestampWhenRoundDoesNotExistYet() (gas: 17599) ScrollSequencerUptimeFeed_Constructor:test_InitialState() (gas: 103508) -ScrollSequencerUptimeFeed_GasCosts:test_GasCosts() (gas: 67258) ScrollSequencerUptimeFeed_ProtectReadsOnAggregatorV2V3InterfaceFunctions:test_AggregatorV2V3InterfaceAllowReadsIfConsumingContractIsWhitelisted() (gas: 601694) ScrollSequencerUptimeFeed_ProtectReadsOnAggregatorV2V3InterfaceFunctions:test_AggregatorV2V3InterfaceDisallowReadsIfConsumingContractIsNotWhitelisted() (gas: 574481) -ScrollSequencerUptimeFeed_UpdateStatus:test_IgnoreOutOfOrderUpdates() (gas: 65115) +ScrollSequencerUptimeFeed_UpdateStatus:test_IgnoreOutOfOrderUpdates() (gas: 67615) ScrollSequencerUptimeFeed_UpdateStatus:test_RevertIfNotL2CrossDomainMessengerAddr() (gas: 13214) ScrollSequencerUptimeFeed_UpdateStatus:test_RevertIfNotL2CrossDomainMessengerAddrAndNotL1SenderAddr() (gas: 23632) -ScrollSequencerUptimeFeed_UpdateStatus:test_UpdateStatusWhenNoChange() (gas: 74720) -ScrollSequencerUptimeFeed_UpdateStatus:test_UpdateStatusWhenStatusChangeAndNoTimeChange() (gas: 93408) -ScrollSequencerUptimeFeed_UpdateStatus:test_UpdateStatusWhenStatusChangeAndTimeChange() (gas: 93468) +ScrollSequencerUptimeFeed_UpdateStatus:test_UpdateStatusWhenNoChange() (gas: 77220) +ScrollSequencerUptimeFeed_UpdateStatus:test_UpdateStatusWhenStatusChangeAndNoTimeChange() (gas: 95908) +ScrollSequencerUptimeFeed_UpdateStatus:test_UpdateStatusWhenStatusChangeAndTimeChange() (gas: 95968) ScrollValidator_SetGasLimit:test_CorrectlyUpdatesTheGasLimit() (gas: 18829) ScrollValidator_Validate:test_PostSequencerOffline() (gas: 78349) ScrollValidator_Validate:test_PostSequencerStatusWhenThereIsNotStatusChange() (gas: 78411) diff --git a/contracts/gas-snapshots/liquiditymanager.gas-snapshot b/contracts/gas-snapshots/liquiditymanager.gas-snapshot index ffd46c2e4e..6f67684cfc 100644 --- a/contracts/gas-snapshots/liquiditymanager.gas-snapshot +++ b/contracts/gas-snapshots/liquiditymanager.gas-snapshot @@ -39,7 +39,7 @@ OCR3Base_transmit:testForkedChainReverts() (gas: 42846) OCR3Base_transmit:testNonIncreasingSequenceNumberReverts() (gas: 30522) OCR3Base_transmit:testNonUniqueSignatureReverts() (gas: 60370) OCR3Base_transmit:testSignatureOutOfRegistrationReverts() (gas: 26128) -OCR3Base_transmit:testTransmit2SignersSuccess_gas() (gas: 56783) +OCR3Base_transmit:testTransmit2SignersSuccess_gas() (gas: 56771) OCR3Base_transmit:testUnAuthorizedTransmitterReverts() (gas: 28618) OCR3Base_transmit:testUnauthorizedSignerReverts() (gas: 44759) OCR3Base_transmit:testWrongNumberOfSignaturesReverts() (gas: 25678) diff --git a/contracts/gas-snapshots/llo-feeds.gas-snapshot b/contracts/gas-snapshots/llo-feeds.gas-snapshot index 0162809e90..68f3c016f6 100644 --- a/contracts/gas-snapshots/llo-feeds.gas-snapshot +++ b/contracts/gas-snapshots/llo-feeds.gas-snapshot @@ -18,6 +18,223 @@ ByteUtilTest:test_readUint32MultiWord() (gas: 3393) ByteUtilTest:test_readUint32WithEmptyArray() (gas: 3253) ByteUtilTest:test_readUint32WithNotEnoughBytes() (gas: 3272) ByteUtilTest:test_readZeroAddress() (gas: 3365) +ChannelConfigStoreTest:testSetChannelDefinitions() (gas: 46927) +ChannelConfigStoreTest:testSupportsInterface() (gas: 8367) +ChannelConfigStoreTest:testTypeAndVersion() (gas: 9621) +DestinationFeeManagerProcessFeeTest:test_DiscountIsAppliedForNative() (gas: 52669) +DestinationFeeManagerProcessFeeTest:test_DiscountIsReturnedForNative() (gas: 52685) +DestinationFeeManagerProcessFeeTest:test_DiscountIsReturnedForNativeWithSurcharge() (gas: 78876) +DestinationFeeManagerProcessFeeTest:test_V1PayloadVerifies() (gas: 29324) +DestinationFeeManagerProcessFeeTest:test_V1PayloadVerifiesAndReturnsChange() (gas: 61187) +DestinationFeeManagerProcessFeeTest:test_V2PayloadVerifies() (gas: 121137) +DestinationFeeManagerProcessFeeTest:test_V2PayloadWithoutQuoteFails() (gas: 29669) +DestinationFeeManagerProcessFeeTest:test_V2PayloadWithoutZeroFee() (gas: 74797) +DestinationFeeManagerProcessFeeTest:test_WithdrawERC20() (gas: 72796) +DestinationFeeManagerProcessFeeTest:test_WithdrawNonAdminAddr() (gas: 56334) +DestinationFeeManagerProcessFeeTest:test_WithdrawUnwrappedNative() (gas: 26411) +DestinationFeeManagerProcessFeeTest:test_addVerifier() (gas: 131079) +DestinationFeeManagerProcessFeeTest:test_addVerifierExistingAddress() (gas: 34148) +DestinationFeeManagerProcessFeeTest:test_baseFeeIsAppliedForLink() (gas: 17214) +DestinationFeeManagerProcessFeeTest:test_baseFeeIsAppliedForNative() (gas: 20152) +DestinationFeeManagerProcessFeeTest:test_correctDiscountIsAppliedWhenBothTokensAreDiscounted() (gas: 91103) +DestinationFeeManagerProcessFeeTest:test_discountAIsNotAppliedWhenSetForOtherUsers() (gas: 56580) +DestinationFeeManagerProcessFeeTest:test_discountFeeRoundsDownWhenUneven() (gas: 52871) +DestinationFeeManagerProcessFeeTest:test_discountIsAppliedForLink() (gas: 49682) +DestinationFeeManagerProcessFeeTest:test_discountIsAppliedWith100PercentSurcharge() (gas: 78949) +DestinationFeeManagerProcessFeeTest:test_discountIsNoLongerAppliedAfterRemoving() (gas: 46567) +DestinationFeeManagerProcessFeeTest:test_discountIsNotAppliedForInvalidTokenAddress() (gas: 17582) +DestinationFeeManagerProcessFeeTest:test_discountIsNotAppliedToOtherFeeds() (gas: 54628) +DestinationFeeManagerProcessFeeTest:test_discountIsReturnedForLink() (gas: 49654) +DestinationFeeManagerProcessFeeTest:test_emptyQuoteRevertsWithError() (gas: 12231) +DestinationFeeManagerProcessFeeTest:test_eventIsEmittedAfterSurchargeIsSet() (gas: 41424) +DestinationFeeManagerProcessFeeTest:test_eventIsEmittedIfNotEnoughLink() (gas: 179229) +DestinationFeeManagerProcessFeeTest:test_eventIsEmittedUponWithdraw() (gas: 69057) +DestinationFeeManagerProcessFeeTest:test_feeIsUpdatedAfterDiscountIsRemoved() (gas: 49831) +DestinationFeeManagerProcessFeeTest:test_feeIsUpdatedAfterNewDiscountIsApplied() (gas: 67769) +DestinationFeeManagerProcessFeeTest:test_feeIsUpdatedAfterNewSurchargeIsApplied() (gas: 64460) +DestinationFeeManagerProcessFeeTest:test_feeIsZeroWith100PercentDiscount() (gas: 52091) +DestinationFeeManagerProcessFeeTest:test_getBaseRewardWithLinkQuote() (gas: 17231) +DestinationFeeManagerProcessFeeTest:test_getLinkFeeIsRoundedUp() (gas: 49853) +DestinationFeeManagerProcessFeeTest:test_getLinkRewardIsSameAsFee() (gas: 55711) +DestinationFeeManagerProcessFeeTest:test_getLinkRewardWithNativeQuoteAndSurchargeWithLinkDiscount() (gas: 82833) +DestinationFeeManagerProcessFeeTest:test_getRewardWithLinkDiscount() (gas: 49700) +DestinationFeeManagerProcessFeeTest:test_getRewardWithLinkQuoteAndLinkDiscount() (gas: 49681) +DestinationFeeManagerProcessFeeTest:test_getRewardWithNativeQuote() (gas: 20150) +DestinationFeeManagerProcessFeeTest:test_getRewardWithNativeQuoteAndSurcharge() (gas: 50885) +DestinationFeeManagerProcessFeeTest:test_linkAvailableForPaymentReturnsLinkBalance() (gas: 53172) +DestinationFeeManagerProcessFeeTest:test_nativeSurcharge0Percent() (gas: 30937) +DestinationFeeManagerProcessFeeTest:test_nativeSurcharge100Percent() (gas: 50887) +DestinationFeeManagerProcessFeeTest:test_nativeSurchargeCannotExceed100Percent() (gas: 17220) +DestinationFeeManagerProcessFeeTest:test_nativeSurchargeEventIsEmittedOnUpdate() (gas: 41402) +DestinationFeeManagerProcessFeeTest:test_noFeeIsAppliedWhenReportHasZeroFee() (gas: 51914) +DestinationFeeManagerProcessFeeTest:test_noFeeIsAppliedWhenReportHasZeroFeeAndDiscountAndSurchargeIsSet() (gas: 78172) +DestinationFeeManagerProcessFeeTest:test_nonAdminProxyUserCannotProcessFee() (gas: 24185) +DestinationFeeManagerProcessFeeTest:test_nonAdminUserCanNotSetDiscount() (gas: 19871) +DestinationFeeManagerProcessFeeTest:test_onlyCallableByOwnerReverts() (gas: 15453) +DestinationFeeManagerProcessFeeTest:test_payLinkDeficit() (gas: 198072) +DestinationFeeManagerProcessFeeTest:test_payLinkDeficitOnlyCallableByAdmin() (gas: 17415) +DestinationFeeManagerProcessFeeTest:test_payLinkDeficitPaysAllFeesProcessed() (gas: 218691) +DestinationFeeManagerProcessFeeTest:test_payLinkDeficitTwice() (gas: 202446) +DestinationFeeManagerProcessFeeTest:test_poolIdsCannotBeZeroAddress() (gas: 115317) +DestinationFeeManagerProcessFeeTest:test_processFeeAsProxy() (gas: 121475) +DestinationFeeManagerProcessFeeTest:test_processFeeDefaultReportsStillVerifiesWithEmptyQuote() (gas: 29745) +DestinationFeeManagerProcessFeeTest:test_processFeeEmitsEventIfNotEnoughLink() (gas: 165393) +DestinationFeeManagerProcessFeeTest:test_processFeeIfSubscriberIsSelf() (gas: 32563) +DestinationFeeManagerProcessFeeTest:test_processFeeNative() (gas: 178204) +DestinationFeeManagerProcessFeeTest:test_processFeeUsesCorrectDigest() (gas: 122766) +DestinationFeeManagerProcessFeeTest:test_processFeeWithDefaultReportPayloadAndQuoteStillVerifies() (gas: 31822) +DestinationFeeManagerProcessFeeTest:test_processFeeWithDiscountEmitsEvent() (gas: 245890) +DestinationFeeManagerProcessFeeTest:test_processFeeWithInvalidReportVersionFailsToDecode() (gas: 30770) +DestinationFeeManagerProcessFeeTest:test_processFeeWithNoDiscountDoesNotEmitEvent() (gas: 171109) +DestinationFeeManagerProcessFeeTest:test_processFeeWithUnwrappedNative() (gas: 186069) +DestinationFeeManagerProcessFeeTest:test_processFeeWithUnwrappedNativeLinkAddress() (gas: 135874) +DestinationFeeManagerProcessFeeTest:test_processFeeWithUnwrappedNativeLinkAddressExcessiveFee() (gas: 161459) +DestinationFeeManagerProcessFeeTest:test_processFeeWithUnwrappedNativeShortFunds() (gas: 94841) +DestinationFeeManagerProcessFeeTest:test_processFeeWithUnwrappedNativeWithExcessiveFee() (gas: 193032) +DestinationFeeManagerProcessFeeTest:test_processFeeWithWithCorruptQuotePayload() (gas: 75084) +DestinationFeeManagerProcessFeeTest:test_processFeeWithWithEmptyQuotePayload() (gas: 30006) +DestinationFeeManagerProcessFeeTest:test_processFeeWithWithZeroQuotePayload() (gas: 30056) +DestinationFeeManagerProcessFeeTest:test_processFeeWithZeroLinkNonZeroNativeWithLinkQuote() (gas: 35320) +DestinationFeeManagerProcessFeeTest:test_processFeeWithZeroLinkNonZeroNativeWithNativeQuote() (gas: 158081) +DestinationFeeManagerProcessFeeTest:test_processFeeWithZeroNativeNonZeroLinkReturnsChange() (gas: 56059) +DestinationFeeManagerProcessFeeTest:test_processFeeWithZeroNativeNonZeroLinkWithLinkQuote() (gas: 121473) +DestinationFeeManagerProcessFeeTest:test_processFeeWithZeroNativeNonZeroLinkWithNativeQuote() (gas: 38024) +DestinationFeeManagerProcessFeeTest:test_processMultipleLinkReports() (gas: 230434) +DestinationFeeManagerProcessFeeTest:test_processMultipleUnwrappedNativeReports() (gas: 264223) +DestinationFeeManagerProcessFeeTest:test_processMultipleV1Reports() (gas: 81155) +DestinationFeeManagerProcessFeeTest:test_processMultipleWrappedNativeReports() (gas: 247072) +DestinationFeeManagerProcessFeeTest:test_processPoolIdsPassedMismatched() (gas: 98793) +DestinationFeeManagerProcessFeeTest:test_processV1V2V3Reports() (gas: 215445) +DestinationFeeManagerProcessFeeTest:test_processV1V2V3ReportsWithUnwrapped() (gas: 257087) +DestinationFeeManagerProcessFeeTest:test_removeVerifierNonExistentAddress() (gas: 12822) +DestinationFeeManagerProcessFeeTest:test_removeVerifierZeroAaddress() (gas: 10678) +DestinationFeeManagerProcessFeeTest:test_reportWithNoExpiryOrFeeReturnsZero() (gas: 13615) +DestinationFeeManagerProcessFeeTest:test_revertOnSettingAnAddressZeroVerifier() (gas: 10614) +DestinationFeeManagerProcessFeeTest:test_rewardsAreCorrectlySentToEachAssociatedPoolWhenVerifyingInBulk() (gas: 263181) +DestinationFeeManagerProcessFeeTest:test_setDiscountOver100Percent() (gas: 19562) +DestinationFeeManagerProcessFeeTest:test_setRewardManagerZeroAddress() (gas: 10626) +DestinationFeeManagerProcessFeeTest:test_subscriberDiscountEventIsEmittedOnUpdate() (gas: 46329) +DestinationFeeManagerProcessFeeTest:test_surchargeFeeRoundsUpWhenUneven() (gas: 51261) +DestinationFeeManagerProcessFeeTest:test_surchargeIsApplied() (gas: 51165) +DestinationFeeManagerProcessFeeTest:test_surchargeIsAppliedForNativeFeeWithDiscount() (gas: 79356) +DestinationFeeManagerProcessFeeTest:test_surchargeIsNoLongerAppliedAfterRemoving() (gas: 47132) +DestinationFeeManagerProcessFeeTest:test_surchargeIsNotAppliedForLinkFee() (gas: 49962) +DestinationFeeManagerProcessFeeTest:test_surchargeIsNotAppliedWith100PercentDiscount() (gas: 78352) +DestinationFeeManagerProcessFeeTest:test_testRevertIfReportHasExpired() (gas: 14943) +DestinationRewardManagerClaimTest:test_claimAllRecipients() (gas: 277191) +DestinationRewardManagerClaimTest:test_claimMultipleRecipients() (gas: 154371) +DestinationRewardManagerClaimTest:test_claimRewardsWithDuplicatePoolIdsDoesNotPayoutTwice() (gas: 330208) +DestinationRewardManagerClaimTest:test_claimSingleRecipient() (gas: 89039) +DestinationRewardManagerClaimTest:test_claimUnevenAmountRoundsDown() (gas: 315411) +DestinationRewardManagerClaimTest:test_claimUnregisteredPoolId() (gas: 35164) +DestinationRewardManagerClaimTest:test_claimUnregisteredRecipient() (gas: 41201) +DestinationRewardManagerClaimTest:test_eventIsEmittedUponClaim() (gas: 86084) +DestinationRewardManagerClaimTest:test_eventIsNotEmittedUponUnsuccessfulClaim() (gas: 25050) +DestinationRewardManagerClaimTest:test_recipientsClaimMultipleDeposits() (gas: 386857) +DestinationRewardManagerClaimTest:test_singleRecipientClaimMultipleDeposits() (gas: 137777) +DestinationRewardManagerNoRecipientSet:test_claimAllRecipientsAfterRecipientsSet() (gas: 492227) +DestinationRewardManagerPayRecipientsTest:test_addFundsToPoolAsNonOwnerOrFeeManager() (gas: 11503) +DestinationRewardManagerPayRecipientsTest:test_addFundsToPoolAsOwner() (gas: 53944) +DestinationRewardManagerPayRecipientsTest:test_payAllRecipients() (gas: 250829) +DestinationRewardManagerPayRecipientsTest:test_payAllRecipientsFromNonAdminUser() (gas: 20496) +DestinationRewardManagerPayRecipientsTest:test_payAllRecipientsFromRecipientInPool() (gas: 251075) +DestinationRewardManagerPayRecipientsTest:test_payAllRecipientsWithAdditionalInvalidRecipient() (gas: 262275) +DestinationRewardManagerPayRecipientsTest:test_payAllRecipientsWithAdditionalUnregisteredRecipient() (gas: 265760) +DestinationRewardManagerPayRecipientsTest:test_payRecipientWithInvalidPool() (gas: 28908) +DestinationRewardManagerPayRecipientsTest:test_payRecipientsEmptyRecipientList() (gas: 25333) +DestinationRewardManagerPayRecipientsTest:test_payRecipientsWithInvalidPoolId() (gas: 31402) +DestinationRewardManagerPayRecipientsTest:test_paySingleRecipient() (gas: 84709) +DestinationRewardManagerPayRecipientsTest:test_paySubsetOfRecipientsInPool() (gas: 198474) +DestinationRewardManagerRecipientClaimDifferentWeightsTest:test_allRecipientsClaimingReceiveExpectedAmount() (gas: 280853) +DestinationRewardManagerRecipientClaimMultiplePoolsTest:test_claimAllRecipientsMultiplePools() (gas: 512489) +DestinationRewardManagerRecipientClaimMultiplePoolsTest:test_claimAllRecipientsSinglePool() (gas: 283649) +DestinationRewardManagerRecipientClaimMultiplePoolsTest:test_claimEmptyPoolWhenSecondPoolContainsFunds() (gas: 293497) +DestinationRewardManagerRecipientClaimMultiplePoolsTest:test_claimMultipleRecipientsMultiplePools() (gas: 263075) +DestinationRewardManagerRecipientClaimMultiplePoolsTest:test_claimMultipleRecipientsSinglePool() (gas: 154537) +DestinationRewardManagerRecipientClaimMultiplePoolsTest:test_claimSingleRecipientMultiplePools() (gas: 132653) +DestinationRewardManagerRecipientClaimMultiplePoolsTest:test_claimSingleUniqueRecipient() (gas: 106056) +DestinationRewardManagerRecipientClaimMultiplePoolsTest:test_claimUnevenAmountRoundsDown() (gas: 579776) +DestinationRewardManagerRecipientClaimMultiplePoolsTest:test_claimUnregisteredRecipient() (gas: 64664) +DestinationRewardManagerRecipientClaimMultiplePoolsTest:test_getAvailableRewardsCursorAndTotalPoolsEqual() (gas: 13074) +DestinationRewardManagerRecipientClaimMultiplePoolsTest:test_getAvailableRewardsCursorCannotBeGreaterThanTotalPools() (gas: 12703) +DestinationRewardManagerRecipientClaimMultiplePoolsTest:test_getAvailableRewardsCursorSingleResult() (gas: 22471) +DestinationRewardManagerRecipientClaimMultiplePoolsTest:test_getRewardsAvailableToRecipientInBothPools() (gas: 32248) +DestinationRewardManagerRecipientClaimMultiplePoolsTest:test_getRewardsAvailableToRecipientInBothPoolsWhereAlreadyClaimed() (gas: 148629) +DestinationRewardManagerRecipientClaimMultiplePoolsTest:test_getRewardsAvailableToRecipientInNoPools() (gas: 21728) +DestinationRewardManagerRecipientClaimMultiplePoolsTest:test_getRewardsAvailableToRecipientInSinglePool() (gas: 27765) +DestinationRewardManagerRecipientClaimMultiplePoolsTest:test_recipientsClaimMultipleDeposits() (gas: 391427) +DestinationRewardManagerRecipientClaimMultiplePoolsTest:test_singleRecipientClaimMultipleDeposits() (gas: 137862) +DestinationRewardManagerRecipientClaimUnevenWeightTest:test_allRecipientsClaimingReceiveExpectedAmount() (gas: 199546) +DestinationRewardManagerRecipientClaimUnevenWeightTest:test_allRecipientsClaimingReceiveExpectedAmountWithSmallDeposit() (gas: 219419) +DestinationRewardManagerSetRecipientsTest:test_eventIsEmittedUponSetRecipients() (gas: 191707) +DestinationRewardManagerSetRecipientsTest:test_setRecipientContainsDuplicateRecipients() (gas: 126060) +DestinationRewardManagerSetRecipientsTest:test_setRewardRecipientFromManagerAddress() (gas: 214117) +DestinationRewardManagerSetRecipientsTest:test_setRewardRecipientFromNonOwnerOrFeeManagerAddress() (gas: 21496) +DestinationRewardManagerSetRecipientsTest:test_setRewardRecipientTwice() (gas: 193280) +DestinationRewardManagerSetRecipientsTest:test_setRewardRecipientWeights() (gas: 180608) +DestinationRewardManagerSetRecipientsTest:test_setRewardRecipientWithZeroAddress() (gas: 90202) +DestinationRewardManagerSetRecipientsTest:test_setRewardRecipientWithZeroWeight() (gas: 191312) +DestinationRewardManagerSetRecipientsTest:test_setRewardRecipients() (gas: 185567) +DestinationRewardManagerSetRecipientsTest:test_setRewardRecipientsIsEmpty() (gas: 87091) +DestinationRewardManagerSetRecipientsTest:test_setSingleRewardRecipient() (gas: 110349) +DestinationRewardManagerSetupTest:test_addFeeManagerExistingAddress() (gas: 35281) +DestinationRewardManagerSetupTest:test_addFeeManagerZeroAddress() (gas: 10580) +DestinationRewardManagerSetupTest:test_addRemoveFeeManager() (gas: 48248) +DestinationRewardManagerSetupTest:test_eventEmittedUponFeeManagerUpdate() (gas: 41581) +DestinationRewardManagerSetupTest:test_eventEmittedUponFeePaid() (gas: 259172) +DestinationRewardManagerSetupTest:test_rejectsZeroLinkAddressOnConstruction() (gas: 59610) +DestinationRewardManagerSetupTest:test_removeFeeManagerNonExistentAddress() (gas: 12778) +DestinationRewardManagerSetupTest:test_setFeeManagerZeroAddress() (gas: 17084) +DestinationRewardManagerUpdateRewardRecipientsMultiplePoolsTest:test_updatePrimaryRecipientWeights() (gas: 376674) +DestinationRewardManagerUpdateRewardRecipientsTest:test_eventIsEmittedUponUpdateRecipients() (gas: 280411) +DestinationRewardManagerUpdateRewardRecipientsTest:test_onlyAdminCanUpdateRecipients() (gas: 19705) +DestinationRewardManagerUpdateRewardRecipientsTest:test_partialUpdateRecipientWeights() (gas: 221004) +DestinationRewardManagerUpdateRewardRecipientsTest:test_updateAllRecipientsWithSameAddressAndWeight() (gas: 274233) +DestinationRewardManagerUpdateRewardRecipientsTest:test_updatePartialRecipientsToSubset() (gas: 254156) +DestinationRewardManagerUpdateRewardRecipientsTest:test_updatePartialRecipientsWithExcessiveWeight() (gas: 259143) +DestinationRewardManagerUpdateRewardRecipientsTest:test_updatePartialRecipientsWithSameAddressAndWeight() (gas: 149856) +DestinationRewardManagerUpdateRewardRecipientsTest:test_updatePartialRecipientsWithUnderWeightSet() (gas: 259217) +DestinationRewardManagerUpdateRewardRecipientsTest:test_updateRecipientWeights() (gas: 372155) +DestinationRewardManagerUpdateRewardRecipientsTest:test_updateRecipientWithNewZeroAddress() (gas: 270700) +DestinationRewardManagerUpdateRewardRecipientsTest:test_updateRecipientsContainsDuplicateRecipients() (gas: 288483) +DestinationRewardManagerUpdateRewardRecipientsTest:test_updateRecipientsToDifferentLargerSet() (gas: 407780) +DestinationRewardManagerUpdateRewardRecipientsTest:test_updateRecipientsToDifferentPartialSet() (gas: 317945) +DestinationRewardManagerUpdateRewardRecipientsTest:test_updateRecipientsToDifferentSet() (gas: 377692) +DestinationRewardManagerUpdateRewardRecipientsTest:test_updateRecipientsToDifferentSetWithInvalidWeights() (gas: 312038) +DestinationRewardManagerUpdateRewardRecipientsTest:test_updateRecipientsUpdateAndRemoveExistingForLargerSet() (gas: 399603) +DestinationRewardManagerUpdateRewardRecipientsTest:test_updateRecipientsUpdateAndRemoveExistingForSmallerSet() (gas: 289433) +DestinationVerifierBulkVerifyBillingReport:test_verifyWithBulkLink() (gas: 639153) +DestinationVerifierBulkVerifyBillingReport:test_verifyWithBulkNative() (gas: 640232) +DestinationVerifierBulkVerifyBillingReport:test_verifyWithBulkNativeUnwrapped() (gas: 661796) +DestinationVerifierBulkVerifyBillingReport:test_verifyWithBulkNativeUnwrappedReturnsChange() (gas: 661751) +DestinationVerifierConstructorTest:test_falseIfIsNotCorrectInterface() (gas: 8719) +DestinationVerifierConstructorTest:test_revertsIfInitializedWithEmptyVerifierProxy() (gas: 61121) +DestinationVerifierConstructorTest:test_trueIfIsCorrectInterface() (gas: 8604) +DestinationVerifierConstructorTest:test_typeAndVersion() (gas: 2818189) +DestinationVerifierProxyInitializeVerifierTest:test_correctlySetsTheOwner() (gas: 1035181) +DestinationVerifierProxyInitializeVerifierTest:test_correctlySetsVersion() (gas: 9841) +DestinationVerifierProxyInitializeVerifierTest:test_setVerifierCalledByNoOwner() (gas: 17483) +DestinationVerifierProxyInitializeVerifierTest:test_setVerifierOk() (gas: 30622) +DestinationVerifierProxyInitializeVerifierTest:test_setVerifierWhichDoesntHonourInterface() (gas: 16851) +DestinationVerifierSetAccessControllerTest:test_emitsTheCorrectEvent() (gas: 35391) +DestinationVerifierSetAccessControllerTest:test_revertsIfCalledByNonOwner() (gas: 15089) +DestinationVerifierSetAccessControllerTest:test_successfullySetsNewAccessController() (gas: 34885) +DestinationVerifierSetAccessControllerTest:test_successfullySetsNewAccessControllerIsEmpty() (gas: 15007) +DestinationVerifierSetConfigTest:test_NoDonConfigAlreadyExists() (gas: 2874492) +DestinationVerifierSetConfigTest:test_addressesAndWeightsDoNotProduceSideEffectsInDonConfigIds() (gas: 1323177) +DestinationVerifierSetConfigTest:test_donConfigIdIsSameForSignersInDifferentOrder() (gas: 1290374) +DestinationVerifierSetConfigTest:test_removeLatestConfig() (gas: 786275) +DestinationVerifierSetConfigTest:test_removeLatestConfigWhenNoConfigShouldFail() (gas: 12870) +DestinationVerifierSetConfigTest:test_revertsIfCalledByNonOwner() (gas: 174936) +DestinationVerifierSetConfigTest:test_revertsIfDuplicateSigners() (gas: 171604) +DestinationVerifierSetConfigTest:test_revertsIfFaultToleranceIsZero() (gas: 168484) +DestinationVerifierSetConfigTest:test_revertsIfNotEnoughSigners() (gas: 11571) +DestinationVerifierSetConfigTest:test_revertsIfSetWithTooManySigners() (gas: 17943) +DestinationVerifierSetConfigTest:test_revertsIfSignerContainsZeroAddress() (gas: 324333) +DestinationVerifierSetConfigTest:test_setConfigActiveUnknownDonConfigId() (gas: 13102) +DestinationVerifierSetConfigTest:test_setConfigWithActivationTime() (gas: 1088176) +DestinationVerifierSetConfigTest:test_setConfigWithActivationTimeEarlierThanLatestConfigShouldFail() (gas: 1963414) +DestinationVerifierSetConfigTest:test_setConfigWithActivationTimeNoFutureTimeShouldFail() (gas: 259797) FeeManagerProcessFeeTest:test_DiscountIsAppliedForNative() (gas: 52645) FeeManagerProcessFeeTest:test_DiscountIsReturnedForNative() (gas: 52595) FeeManagerProcessFeeTest:test_DiscountIsReturnedForNativeWithSurcharge() (gas: 78808) @@ -72,7 +289,7 @@ FeeManagerProcessFeeTest:test_payLinkDeficitTwice() (gas: 198803) FeeManagerProcessFeeTest:test_processFeeAsProxy() (gas: 117088) FeeManagerProcessFeeTest:test_processFeeDefaultReportsStillVerifiesWithEmptyQuote() (gas: 27462) FeeManagerProcessFeeTest:test_processFeeEmitsEventIfNotEnoughLink() (gas: 163205) -FeeManagerProcessFeeTest:test_processFeeIfSubscriberIsSelf() (gas: 27827) +FeeManagerProcessFeeTest:test_processFeeIfSubscriberIsSelf() (gas: 30327) FeeManagerProcessFeeTest:test_processFeeNative() (gas: 173826) FeeManagerProcessFeeTest:test_processFeeUsesCorrectDigest() (gas: 118379) FeeManagerProcessFeeTest:test_processFeeWithDefaultReportPayloadAndQuoteStillVerifies() (gas: 29536) @@ -108,6 +325,7 @@ FeeManagerProcessFeeTest:test_surchargeIsNoLongerAppliedAfterRemoving() (gas: 47 FeeManagerProcessFeeTest:test_surchargeIsNotAppliedForLinkFee() (gas: 49938) FeeManagerProcessFeeTest:test_surchargeIsNotAppliedWith100PercentDiscount() (gas: 78261) FeeManagerProcessFeeTest:test_testRevertIfReportHasExpired() (gas: 14919) +MultiVerifierBillingTests:test_multipleFeeManagersAndVerifiers() (gas: 4586990) RewardManagerClaimTest:test_claimAllRecipients() (gas: 277131) RewardManagerClaimTest:test_claimMultipleRecipients() (gas: 154341) RewardManagerClaimTest:test_claimRewardsWithDuplicatePoolIdsDoesNotPayoutTwice() (gas: 330086) @@ -200,6 +418,13 @@ VerifierActivateFeedTest:test_revertsIfNoFeedExistsActivate() (gas: 13179) VerifierActivateFeedTest:test_revertsIfNoFeedExistsDeactivate() (gas: 13157) VerifierActivateFeedTest:test_revertsIfNotOwnerActivateFeed() (gas: 17109) VerifierActivateFeedTest:test_revertsIfNotOwnerDeactivateFeed() (gas: 17164) +VerifierBillingTests:test_rewardsAreDistributedAccordingToWeights() (gas: 1731717) +VerifierBillingTests:test_rewardsAreDistributedAccordingToWeightsMultipleWeigths() (gas: 4460715) +VerifierBillingTests:test_rewardsAreDistributedAccordingToWeightsUsingHistoricalConfigs() (gas: 2098833) +VerifierBillingTests:test_verifyWithLinkV3Report() (gas: 1591346) +VerifierBillingTests:test_verifyWithNativeERC20() (gas: 1467256) +VerifierBillingTests:test_verifyWithNativeUnwrapped() (gas: 1376447) +VerifierBillingTests:test_verifyWithNativeUnwrappedReturnsChange() (gas: 1383493) VerifierBulkVerifyBillingReport:test_verifyMultiVersions() (gas: 476595) VerifierBulkVerifyBillingReport:test_verifyMultiVersionsReturnsVerifiedReports() (gas: 474853) VerifierBulkVerifyBillingReport:test_verifyWithBulkLink() (gas: 557541) @@ -212,6 +437,7 @@ VerifierDeactivateFeedWithVerifyTest:test_currentReportAllowsVerification() (gas VerifierDeactivateFeedWithVerifyTest:test_currentReportFailsVerification() (gas: 113388) VerifierDeactivateFeedWithVerifyTest:test_previousReportAllowsVerification() (gas: 99624) VerifierDeactivateFeedWithVerifyTest:test_previousReportFailsVerification() (gas: 69943) +VerifierInterfacesTest:test_DestinationContractInterfaces() (gas: 623467) VerifierProxyAccessControlledVerificationTest:test_proxiesToTheVerifierIfHasAccess() (gas: 208529) VerifierProxyAccessControlledVerificationTest:test_revertsIfNoAccess() (gas: 112345) VerifierProxyConstructorTest:test_correctlySetsTheCorrectAccessControllerInterface() (gas: 1485359) @@ -236,6 +462,9 @@ VerifierProxyUnsetVerifierWithPreviouslySetVerifierTest:test_correctlyUnsetsVeri VerifierProxyUnsetVerifierWithPreviouslySetVerifierTest:test_emitsAnEventAfterUnsettingVerifier() (gas: 17961) VerifierProxyVerifyTest:test_proxiesToTheCorrectVerifier() (gas: 204342) VerifierProxyVerifyTest:test_revertsIfNoVerifierConfigured() (gas: 117264) +VerifierSetAccessControllerTest:test_revertsIfCalledByNonOwner() (gas: 17196) +VerifierSetAccessControllerTest:test_setFeeManagerWhichDoesntHonourInterface() (gas: 16571) +VerifierSetAccessControllerTest:test_successfullySetsNewFeeManager() (gas: 44855) VerifierSetConfigFromSourceMultipleDigestsTest:test_correctlySetsConfigWhenDigestsAreRemoved() (gas: 542302) VerifierSetConfigFromSourceMultipleDigestsTest:test_correctlyUpdatesDigestsOnMultipleVerifiersInTheProxy() (gas: 967768) VerifierSetConfigFromSourceMultipleDigestsTest:test_correctlyUpdatesTheDigestInTheProxy() (gas: 523251) @@ -256,6 +485,9 @@ VerifierTestBillingReport:test_verifyWithLink() (gas: 275293) VerifierTestBillingReport:test_verifyWithNative() (gas: 316326) VerifierTestBillingReport:test_verifyWithNativeUnwrapped() (gas: 318574) VerifierTestBillingReport:test_verifyWithNativeUnwrappedReturnsChange() (gas: 325642) +VerifierVerifyBulkTest:test_revertsVerifyBulkIfNoAccess() (gas: 112867) +VerifierVerifyBulkTest:test_verifyBulkSingleCaseWithSingleConfig() (gas: 745046) +VerifierVerifyBulkTest:test_verifyBulkWithSingleConfigOneVerifyFails() (gas: 698203) VerifierVerifyMultipleConfigDigestTest:test_canVerifyNewerReportsWithNewerConfigs() (gas: 133961) VerifierVerifyMultipleConfigDigestTest:test_canVerifyOlderReportsWithOlderConfigs() (gas: 189865) VerifierVerifyMultipleConfigDigestTest:test_revertsIfAReportIsVerifiedWithAnExistingButIncorrectDigest() (gas: 88216) @@ -270,6 +502,18 @@ VerifierVerifySingleConfigDigestTest:test_revertsIfVerifiedByNonProxy() (gas: 10 VerifierVerifySingleConfigDigestTest:test_revertsIfVerifiedWithIncorrectAddresses() (gas: 184077) VerifierVerifySingleConfigDigestTest:test_revertsIfWrongNumberOfSigners() (gas: 110042) VerifierVerifySingleConfigDigestTest:test_setsTheCorrectEpoch() (gas: 194592) +VerifierVerifyTest:test_canVerifyNewerReportsWithNewerConfigs() (gas: 861741) +VerifierVerifyTest:test_canVerifyOlderV3ReportsWithOlderConfigs() (gas: 815984) +VerifierVerifyTest:test_failToVerifyReportIfDupSigners() (gas: 450715) +VerifierVerifyTest:test_failToVerifyReportIfNoSigners() (gas: 426492) +VerifierVerifyTest:test_failToVerifyReportIfNotEnoughSigners() (gas: 434814) +VerifierVerifyTest:test_failToVerifyReportIfSignerNotInConfig() (gas: 456866) +VerifierVerifyTest:test_revertsVerifyIfNoAccess() (gas: 109465) +VerifierVerifyTest:test_rollingOutConfiguration() (gas: 1497254) +VerifierVerifyTest:test_scenarioRollingNewChainWithHistoricConfigs() (gas: 976162) +VerifierVerifyTest:test_verifyFailsWhenReportIsOlderThanConfig() (gas: 2303366) +VerifierVerifyTest:test_verifyReport() (gas: 1434811) +VerifierVerifyTest:test_verifyTooglingActiveFlagsDonConfigs() (gas: 1918797) Verifier_accessControlledVerify:testVerifyWithAccessControl_gas() (gas: 212077) Verifier_bulkVerifyWithFee:testBulkVerifyProxyWithLinkFeeSuccess_gas() (gas: 519389) Verifier_bulkVerifyWithFee:testBulkVerifyProxyWithNativeFeeSuccess_gas() (gas: 542808) diff --git a/contracts/gas-snapshots/operatorforwarder.gas-snapshot b/contracts/gas-snapshots/operatorforwarder.gas-snapshot index 7cfc963f74..66bb19f1f6 100644 --- a/contracts/gas-snapshots/operatorforwarder.gas-snapshot +++ b/contracts/gas-snapshots/operatorforwarder.gas-snapshot @@ -2,8 +2,8 @@ FactoryTest:test_DeployNewForwarderAndTransferOwnership_Success() (gas: 1059722) FactoryTest:test_DeployNewForwarder_Success() (gas: 1048209) FactoryTest:test_DeployNewOperatorAndForwarder_Success() (gas: 4069305) FactoryTest:test_DeployNewOperator_Success() (gas: 3020464) -ForwarderTest:test_Forward_Success(uint256) (runs: 256, μ: 226200, ~: 227289) -ForwarderTest:test_MultiForward_Success(uint256,uint256) (runs: 256, μ: 257876, ~: 259120) +ForwarderTest:test_Forward_Success(uint256) (runs: 257, μ: 226979, ~: 227289) +ForwarderTest:test_MultiForward_Success(uint256,uint256) (runs: 257, μ: 258577, ~: 259120) ForwarderTest:test_OwnerForward_Success() (gas: 30118) ForwarderTest:test_SetAuthorizedSenders_Success() (gas: 160524) ForwarderTest:test_TransferOwnershipWithMessage_Success() (gas: 35123) @@ -11,5 +11,5 @@ OperatorTest:test_CancelOracleRequest_Success() (gas: 274436) OperatorTest:test_FulfillOracleRequest_Success() (gas: 330603) OperatorTest:test_NotAuthorizedSender_Revert() (gas: 246716) OperatorTest:test_OracleRequest_Success() (gas: 250019) -OperatorTest:test_SendRequestAndCancelRequest_Success(uint96) (runs: 256, μ: 387120, ~: 387124) -OperatorTest:test_SendRequest_Success(uint96) (runs: 256, μ: 303611, ~: 303615) \ No newline at end of file +OperatorTest:test_SendRequestAndCancelRequest_Success(uint96) (runs: 257, μ: 387121, ~: 387124) +OperatorTest:test_SendRequest_Success(uint96) (runs: 257, μ: 303612, ~: 303615) \ No newline at end of file diff --git a/contracts/gas-snapshots/shared.gas-snapshot b/contracts/gas-snapshots/shared.gas-snapshot index c194511ca6..d7a4e21978 100644 --- a/contracts/gas-snapshots/shared.gas-snapshot +++ b/contracts/gas-snapshots/shared.gas-snapshot @@ -39,41 +39,41 @@ CallWithExactGas__callWithExactGas:test_CallWithExactGasSafeReturnDataExactGas() CallWithExactGas__callWithExactGas:test_NoContractReverts() (gas: 11559) CallWithExactGas__callWithExactGas:test_NoGasForCallExactCheckReverts() (gas: 15788) CallWithExactGas__callWithExactGas:test_NotEnoughGasForCallReverts() (gas: 16241) -CallWithExactGas__callWithExactGas:test_callWithExactGasSuccess(bytes,bytes4) (runs: 256, μ: 15812, ~: 15752) +CallWithExactGas__callWithExactGas:test_callWithExactGasSuccess(bytes,bytes4) (runs: 257, μ: 15766, ~: 15719) CallWithExactGas__callWithExactGasEvenIfTargetIsNoContract:test_CallWithExactGasEvenIfTargetIsNoContractExactGasSuccess() (gas: 20116) CallWithExactGas__callWithExactGasEvenIfTargetIsNoContract:test_CallWithExactGasEvenIfTargetIsNoContractReceiverErrorSuccess() (gas: 67721) -CallWithExactGas__callWithExactGasEvenIfTargetIsNoContract:test_CallWithExactGasEvenIfTargetIsNoContractSuccess(bytes,bytes4) (runs: 256, μ: 16321, ~: 16262) +CallWithExactGas__callWithExactGasEvenIfTargetIsNoContract:test_CallWithExactGasEvenIfTargetIsNoContractSuccess(bytes,bytes4) (runs: 257, μ: 16276, ~: 16229) CallWithExactGas__callWithExactGasEvenIfTargetIsNoContract:test_NoContractSuccess() (gas: 12962) CallWithExactGas__callWithExactGasEvenIfTargetIsNoContract:test_NoGasForCallExactCheckReturnFalseSuccess() (gas: 13005) CallWithExactGas__callWithExactGasEvenIfTargetIsNoContract:test_NotEnoughGasForCallReturnsFalseSuccess() (gas: 13317) CallWithExactGas__callWithExactGasSafeReturnData:test_CallWithExactGasSafeReturnDataExactGas() (gas: 20331) CallWithExactGas__callWithExactGasSafeReturnData:test_NoContractReverts() (gas: 13917) CallWithExactGas__callWithExactGasSafeReturnData:test_NoGasForCallExactCheckReverts() (gas: 16139) -CallWithExactGas__callWithExactGasSafeReturnData:test_NotEnoughGasForCallReverts() (gas: 16547) -CallWithExactGas__callWithExactGasSafeReturnData:test_callWithExactGasSafeReturnData_ThrowOOGError_Revert() (gas: 36752) +CallWithExactGas__callWithExactGasSafeReturnData:test_NotEnoughGasForCallReverts() (gas: 16569) +CallWithExactGas__callWithExactGasSafeReturnData:test_callWithExactGasSafeReturnData_ThrowOOGError_Revert() (gas: 36708) EnumerableMapAddresses_at:testAtSuccess() (gas: 95086) EnumerableMapAddresses_at:testBytes32AtSuccess() (gas: 94877) +EnumerableMapAddresses_at:testBytesAtSuccess() (gas: 96564) EnumerableMapAddresses_contains:testBytes32ContainsSuccess() (gas: 93518) +EnumerableMapAddresses_contains:testBytesContainsSuccess() (gas: 94012) EnumerableMapAddresses_contains:testContainsSuccess() (gas: 93696) EnumerableMapAddresses_get:testBytes32GetSuccess() (gas: 94278) +EnumerableMapAddresses_get:testBytesGetSuccess() (gas: 95879) EnumerableMapAddresses_get:testGetSuccess() (gas: 94453) +EnumerableMapAddresses_get_errorMessage:testBytesGetErrorMessageSuccess() (gas: 95878) EnumerableMapAddresses_get_errorMessage:testGetErrorMessageSuccess() (gas: 94489) EnumerableMapAddresses_length:testBytes32LengthSuccess() (gas: 72445) +EnumerableMapAddresses_length:testBytesLengthSuccess() (gas: 73011) EnumerableMapAddresses_length:testLengthSuccess() (gas: 72640) EnumerableMapAddresses_remove:testBytes32RemoveSuccess() (gas: 73462) +EnumerableMapAddresses_remove:testBytesRemoveSuccess() (gas: 74249) EnumerableMapAddresses_remove:testRemoveSuccess() (gas: 73686) EnumerableMapAddresses_set:testBytes32SetSuccess() (gas: 94496) +EnumerableMapAddresses_set:testBytesSetSuccess() (gas: 95428) EnumerableMapAddresses_set:testSetSuccess() (gas: 94685) EnumerableMapAddresses_tryGet:testBytes32TryGetSuccess() (gas: 94622) -EnumerableMapAddresses_tryGet:testTryGetSuccess() (gas: 94893) -EnumerableMapAddresses_at:testBytesAtSuccess() (gas: 96564) -EnumerableMapAddresses_contains:testBytesContainsSuccess() (gas: 94012) -EnumerableMapAddresses_get:testBytesGetSuccess() (gas: 95879) -EnumerableMapAddresses_get_errorMessage:testBytesGetErrorMessageSuccess() (gas: 95878) -EnumerableMapAddresses_length:testBytesLengthSuccess() (gas: 73011) -EnumerableMapAddresses_remove:testBytesRemoveSuccess() (gas: 74249) -EnumerableMapAddresses_set:testBytesSetSuccess() (gas: 95428) EnumerableMapAddresses_tryGet:testBytesTryGetSuccess() (gas: 96279) +EnumerableMapAddresses_tryGet:testTryGetSuccess() (gas: 94893) OpStackBurnMintERC677_constructor:testConstructorSuccess() (gas: 1743649) OpStackBurnMintERC677_interfaceCompatibility:testBurnCompatibility() (gas: 298649) OpStackBurnMintERC677_interfaceCompatibility:testMintCompatibility() (gas: 137957) diff --git a/contracts/package.json b/contracts/package.json index 334b75701c..f8cc3a505e 100644 --- a/contracts/package.json +++ b/contracts/package.json @@ -79,26 +79,26 @@ "@ethersproject/providers": "~5.7.2", "@nomicfoundation/hardhat-chai-matchers": "^1.0.6", "@nomicfoundation/hardhat-ethers": "^3.0.6", - "@nomicfoundation/hardhat-network-helpers": "^1.0.9", - "@nomicfoundation/hardhat-verify": "^2.0.7", + "@nomicfoundation/hardhat-network-helpers": "^1.0.11", + "@nomicfoundation/hardhat-verify": "^2.0.9", "@typechain/ethers-v5": "^7.2.0", "@typechain/hardhat": "^7.0.0", "@types/cbor": "~5.0.1", - "@types/chai": "^4.3.16", + "@types/chai": "^4.3.17", "@types/debug": "^4.1.12", "@types/deep-equal-in-any-order": "^1.0.3", - "@types/mocha": "^10.0.6", - "@types/node": "^20.12.12", - "@typescript-eslint/eslint-plugin": "^7.10.0", - "@typescript-eslint/parser": "^7.10.0", + "@types/mocha": "^10.0.7", + "@types/node": "^20.14.15", + "@typescript-eslint/eslint-plugin": "^7.18.0", + "@typescript-eslint/parser": "^7.18.0", "abi-to-sol": "^0.6.6", "cbor": "^5.2.0", - "chai": "^4.3.10", - "debug": "^4.3.4", + "chai": "^4.5.0", + "debug": "^4.3.6", "deep-equal-in-any-order": "^2.0.6", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", - "eslint-plugin-prettier": "^5.1.3", + "eslint-plugin-prettier": "^5.2.1", "ethers": "~5.7.2", "hardhat": "~2.20.1", "hardhat-abi-exporter": "^2.10.1", @@ -106,25 +106,25 @@ "husky": "^9.0.11", "lint-staged": "^15.2.2", "moment": "^2.30.1", - "prettier": "^3.2.5", + "prettier": "^3.3.3", "prettier-plugin-solidity": "^1.3.1", - "solhint": "^5.0.1", + "solhint": "^5.0.3", "solhint-plugin-chainlink-solidity": "git+https://github.com/smartcontractkit/chainlink-solhint-rules.git#v1.2.1", "solhint-plugin-prettier": "^0.1.0", "ts-node": "^10.9.2", "typechain": "^8.2.1", - "typescript": "^5.4.5" + "typescript": "^5.5.4" }, "dependencies": { "@arbitrum/nitro-contracts": "1.1.1", "@arbitrum/token-bridge-contracts": "1.1.2", "@changesets/changelog-github": "^0.5.0", - "@changesets/cli": "~2.27.3", + "@changesets/cli": "~2.27.7", "@eth-optimism/contracts": "0.6.0", "@openzeppelin/contracts": "4.9.3", "@openzeppelin/contracts-upgradeable": "4.9.3", "@scroll-tech/contracts": "0.1.0", - "semver": "^7.6.2" + "semver": "^7.6.3" }, "lint-staged": { "*.sol": [ diff --git a/contracts/pnpm-lock.yaml b/contracts/pnpm-lock.yaml index 5c1dfecb44..5c45da8ab0 100644 --- a/contracts/pnpm-lock.yaml +++ b/contracts/pnpm-lock.yaml @@ -21,8 +21,8 @@ importers: specifier: ^0.5.0 version: 0.5.0 '@changesets/cli': - specifier: ~2.27.3 - version: 2.27.3 + specifier: ~2.27.7 + version: 2.27.7 '@eth-optimism/contracts': specifier: 0.6.0 version: 0.6.0(ethers@5.7.2) @@ -36,8 +36,8 @@ importers: specifier: 0.1.0 version: 0.1.0 semver: - specifier: ^7.6.2 - version: 7.6.2 + specifier: ^7.6.3 + version: 7.6.3 devDependencies: '@ethereum-waffle/mock-contract': specifier: ^3.4.4 @@ -56,28 +56,28 @@ importers: version: 5.7.2 '@nomicfoundation/hardhat-chai-matchers': specifier: ^1.0.6 - version: 1.0.6(@nomiclabs/hardhat-ethers@2.2.3(ethers@5.7.2)(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5)))(chai@4.4.1)(ethers@5.7.2)(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5)) + version: 1.0.6(@nomiclabs/hardhat-ethers@2.2.3(ethers@5.7.2)(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.14.15)(typescript@5.5.4))(typescript@5.5.4)))(chai@4.5.0)(ethers@5.7.2)(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.14.15)(typescript@5.5.4))(typescript@5.5.4)) '@nomicfoundation/hardhat-ethers': specifier: ^3.0.6 - version: 3.0.6(ethers@5.7.2)(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5)) + version: 3.0.6(ethers@5.7.2)(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.14.15)(typescript@5.5.4))(typescript@5.5.4)) '@nomicfoundation/hardhat-network-helpers': - specifier: ^1.0.9 - version: 1.0.10(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5)) + specifier: ^1.0.11 + version: 1.0.11(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.14.15)(typescript@5.5.4))(typescript@5.5.4)) '@nomicfoundation/hardhat-verify': - specifier: ^2.0.7 - version: 2.0.7(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5)) + specifier: ^2.0.9 + version: 2.0.9(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.14.15)(typescript@5.5.4))(typescript@5.5.4)) '@typechain/ethers-v5': specifier: ^7.2.0 - version: 7.2.0(@ethersproject/abi@5.7.0)(@ethersproject/bytes@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.2(typescript@5.4.5))(typescript@5.4.5) + version: 7.2.0(@ethersproject/abi@5.7.0)(@ethersproject/bytes@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.2(typescript@5.5.4))(typescript@5.5.4) '@typechain/hardhat': specifier: ^7.0.0 - version: 7.0.0(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(@typechain/ethers-v5@7.2.0(@ethersproject/abi@5.7.0)(@ethersproject/bytes@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.2(typescript@5.4.5))(typescript@5.4.5))(ethers@5.7.2)(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5))(typechain@8.3.2(typescript@5.4.5)) + version: 7.0.0(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(@typechain/ethers-v5@7.2.0(@ethersproject/abi@5.7.0)(@ethersproject/bytes@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.2(typescript@5.5.4))(typescript@5.5.4))(ethers@5.7.2)(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.14.15)(typescript@5.5.4))(typescript@5.5.4))(typechain@8.3.2(typescript@5.5.4)) '@types/cbor': specifier: ~5.0.1 version: 5.0.1 '@types/chai': - specifier: ^4.3.16 - version: 4.3.16 + specifier: ^4.3.17 + version: 4.3.17 '@types/debug': specifier: ^4.1.12 version: 4.1.12 @@ -85,17 +85,17 @@ importers: specifier: ^1.0.3 version: 1.0.3 '@types/mocha': - specifier: ^10.0.6 - version: 10.0.6 + specifier: ^10.0.7 + version: 10.0.7 '@types/node': - specifier: ^20.12.12 - version: 20.12.12 + specifier: ^20.14.15 + version: 20.14.15 '@typescript-eslint/eslint-plugin': - specifier: ^7.10.0 - version: 7.10.0(@typescript-eslint/parser@7.10.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5) + specifier: ^7.18.0 + version: 7.18.0(@typescript-eslint/parser@7.18.0(eslint@8.57.0)(typescript@5.5.4))(eslint@8.57.0)(typescript@5.5.4) '@typescript-eslint/parser': - specifier: ^7.10.0 - version: 7.10.0(eslint@8.57.0)(typescript@5.4.5) + specifier: ^7.18.0 + version: 7.18.0(eslint@8.57.0)(typescript@5.5.4) abi-to-sol: specifier: ^0.6.6 version: 0.6.6 @@ -103,11 +103,11 @@ importers: specifier: ^5.2.0 version: 5.2.0 chai: - specifier: ^4.3.10 - version: 4.4.1 + specifier: ^4.5.0 + version: 4.5.0 debug: - specifier: ^4.3.4 - version: 4.3.4(supports-color@8.1.1) + specifier: ^4.3.6 + version: 4.3.6 deep-equal-in-any-order: specifier: ^2.0.6 version: 2.0.6 @@ -118,53 +118,47 @@ importers: specifier: ^9.1.0 version: 9.1.0(eslint@8.57.0) eslint-plugin-prettier: - specifier: ^5.1.3 - version: 5.1.3(eslint-config-prettier@9.1.0(eslint@8.57.0))(eslint@8.57.0)(prettier@3.2.5) + specifier: ^5.2.1 + version: 5.2.1(eslint-config-prettier@9.1.0(eslint@8.57.0))(eslint@8.57.0)(prettier@3.3.3) ethers: specifier: ~5.7.2 version: 5.7.2 hardhat: specifier: ~2.20.1 - version: 2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5) + version: 2.20.1(ts-node@10.9.2(@types/node@20.14.15)(typescript@5.5.4))(typescript@5.5.4) hardhat-abi-exporter: specifier: ^2.10.1 - version: 2.10.1(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5)) + version: 2.10.1(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.14.15)(typescript@5.5.4))(typescript@5.5.4)) hardhat-ignore-warnings: specifier: ^0.2.6 version: 0.2.11 - husky: - specifier: ^9.0.11 - version: 9.0.11 - lint-staged: - specifier: ^15.2.2 - version: 15.2.2 moment: specifier: ^2.30.1 version: 2.30.1 prettier: - specifier: ^3.2.5 - version: 3.2.5 + specifier: ^3.3.3 + version: 3.3.3 prettier-plugin-solidity: specifier: ^1.3.1 - version: 1.3.1(prettier@3.2.5) + version: 1.3.1(prettier@3.3.3) solhint: - specifier: ^5.0.1 - version: 5.0.1 + specifier: ^5.0.3 + version: 5.0.3 solhint-plugin-chainlink-solidity: specifier: git+https://github.com/smartcontractkit/chainlink-solhint-rules.git#v1.2.1 version: '@chainlink/solhint-plugin-chainlink-solidity@https://codeload.github.com/smartcontractkit/chainlink-solhint-rules/tar.gz/1b4c0c2663fcd983589d4f33a2e73908624ed43c' solhint-plugin-prettier: specifier: ^0.1.0 - version: 0.1.0(prettier-plugin-solidity@1.3.1(prettier@3.2.5))(prettier@3.2.5) + version: 0.1.0(prettier-plugin-solidity@1.3.1(prettier@3.3.3))(prettier@3.3.3) ts-node: specifier: ^10.9.2 - version: 10.9.2(@types/node@20.12.12)(typescript@5.4.5) + version: 10.9.2(@types/node@20.14.15)(typescript@5.5.4) typechain: specifier: ^8.2.1 - version: 8.3.2(typescript@5.4.5) + version: 8.3.2(typescript@5.5.4) typescript: - specifier: ^5.4.5 - version: 5.4.5 + specifier: ^5.5.4 + version: 5.5.4 packages: @@ -198,11 +192,11 @@ packages: resolution: {tarball: https://codeload.github.com/smartcontractkit/chainlink-solhint-rules/tar.gz/1b4c0c2663fcd983589d4f33a2e73908624ed43c} version: 1.2.0 - '@changesets/apply-release-plan@7.0.1': - resolution: {integrity: sha512-aPdSq/R++HOyfEeBGjEe6LNG8gs0KMSyRETD/J2092OkNq8mOioAxyKjMbvVUdzgr/HTawzMOz7lfw339KnsCA==} + '@changesets/apply-release-plan@7.0.4': + resolution: {integrity: sha512-HLFwhKWayKinWAul0Vj+76jVx1Pc2v55MGPVjZ924Y/ROeSsBMFutv9heHmCUj48lJyRfOTJG5+ar+29FUky/A==} - '@changesets/assemble-release-plan@6.0.0': - resolution: {integrity: sha512-4QG7NuisAjisbW4hkLCmGW2lRYdPrKzro+fCtZaILX+3zdUELSvYjpL4GTv0E4aM9Mef3PuIQp89VmHJ4y2bfw==} + '@changesets/assemble-release-plan@6.0.3': + resolution: {integrity: sha512-bLNh9/Lgl1VwkjWZTq8JmRqH+hj7/Yzfz0jsQ/zJJ+FTmVqmqPj3szeKOri8O/hEM8JmHW019vh2gTO9iq5Cuw==} '@changesets/changelog-git@0.2.0': resolution: {integrity: sha512-bHOx97iFI4OClIT35Lok3sJAwM31VbUM++gnMBV16fdbtBhgYu4dxsphBF/0AZZsyAHMrnM0yFcj5gZM1py6uQ==} @@ -210,24 +204,24 @@ packages: '@changesets/changelog-github@0.5.0': resolution: {integrity: sha512-zoeq2LJJVcPJcIotHRJEEA2qCqX0AQIeFE+L21L8sRLPVqDhSXY8ZWAt2sohtBpFZkBwu+LUwMSKRr2lMy3LJA==} - '@changesets/cli@2.27.3': - resolution: {integrity: sha512-ve/VpWApILlSs8cr0okNx5C2LKRawI9XZgvfmf58S8sar2nhx5DPJREFXYZBahs0FeTfvH0rdVl+nGe8QF45Ig==} + '@changesets/cli@2.27.7': + resolution: {integrity: sha512-6lr8JltiiXPIjDeYg4iM2MeePP6VN/JkmqBsVA5XRiy01hGS3y629LtSDvKcycj/w/5Eur1rEwby/MjcYS+e2A==} hasBin: true - '@changesets/config@3.0.0': - resolution: {integrity: sha512-o/rwLNnAo/+j9Yvw9mkBQOZySDYyOr/q+wptRLcAVGlU6djOeP9v1nlalbL9MFsobuBVQbZCTp+dIzdq+CLQUA==} + '@changesets/config@3.0.2': + resolution: {integrity: sha512-cdEhS4t8woKCX2M8AotcV2BOWnBp09sqICxKapgLHf9m5KdENpWjyrFNMjkLqGJtUys9U+w93OxWT0czorVDfw==} '@changesets/errors@0.2.0': resolution: {integrity: sha512-6BLOQUscTpZeGljvyQXlWOItQyU71kCdGz7Pi8H8zdw6BI0g3m43iL4xKUVPWtG+qrrL9DTjpdn8eYuCQSRpow==} - '@changesets/get-dependents-graph@2.0.0': - resolution: {integrity: sha512-cafUXponivK4vBgZ3yLu944mTvam06XEn2IZGjjKc0antpenkYANXiiE6GExV/yKdsCnE8dXVZ25yGqLYZmScA==} + '@changesets/get-dependents-graph@2.1.1': + resolution: {integrity: sha512-LRFjjvigBSzfnPU2n/AhFsuWR5DK++1x47aq6qZ8dzYsPtS/I5mNhIGAS68IAxh1xjO9BTtz55FwefhANZ+FCA==} '@changesets/get-github-info@0.6.0': resolution: {integrity: sha512-v/TSnFVXI8vzX9/w3DU2Ol+UlTZcu3m0kXTjTT4KlAdwSvwutcByYwyYn9hwerPWfPkT2JfpoX0KgvCEi8Q/SA==} - '@changesets/get-release-plan@4.0.0': - resolution: {integrity: sha512-9L9xCUeD/Tb6L/oKmpm8nyzsOzhdNBBbt/ZNcjynbHC07WW4E1eX8NMGC5g5SbM5z/V+MOrYsJ4lRW41GCbg3w==} + '@changesets/get-release-plan@4.0.3': + resolution: {integrity: sha512-6PLgvOIwTSdJPTtpdcr3sLtGatT+Jr22+cQwEBJBy6wP0rjB4yJ9lv583J9fVpn1bfQlBkDa8JxbS2g/n9lIyA==} '@changesets/get-version-range-type@0.4.0': resolution: {integrity: sha512-hwawtob9DryoGTpixy1D3ZXbGgJu1Rhr+ySH2PvTLHvkZuQ7sRT4oQwMh0hbqZH1weAooedEjRsbrWcGLCeyVQ==} @@ -247,6 +241,9 @@ packages: '@changesets/read@0.6.0': resolution: {integrity: sha512-ZypqX8+/im1Fm98K4YcZtmLKgjs1kDQ5zHpc2U1qdtNBmZZfo/IBiG162RoP0CUF05tvp2y4IspH11PLnPxuuw==} + '@changesets/should-skip-package@0.1.0': + resolution: {integrity: sha512-FxG6Mhjw7yFStlSM7Z0Gmg3RiyQ98d/9VpQAZ3Fzr59dCOM9G6ZdYbjiSAt0XtFr9JR5U2tBaJWPjrkGGc618g==} + '@changesets/types@4.1.0': resolution: {integrity: sha512-LDQvVDv5Kb50ny2s25Fhm3d9QSZimsoUGBsUioj6MC3qbMUCuC8GPIvk/M6IvXx3lYhAs0lwWUQLb+VIEUCECw==} @@ -509,15 +506,15 @@ packages: ethers: ^6.1.0 hardhat: ^2.0.0 - '@nomicfoundation/hardhat-network-helpers@1.0.10': - resolution: {integrity: sha512-R35/BMBlx7tWN5V6d/8/19QCwEmIdbnA4ZrsuXgvs8i2qFx5i7h6mH5pBS4Pwi4WigLH+upl6faYusrNPuzMrQ==} + '@nomicfoundation/hardhat-network-helpers@1.0.11': + resolution: {integrity: sha512-uGPL7QSKvxrHRU69dx8jzoBvuztlLCtyFsbgfXIwIjnO3dqZRz2GNMHJoO3C3dIiUNM6jdNF4AUnoQKDscdYrA==} peerDependencies: hardhat: ^2.9.5 - '@nomicfoundation/hardhat-verify@2.0.7': - resolution: {integrity: sha512-jiYHBX+K6bBN0YhwFHQ5SWWc3dQZliM3pdgpH33C7tnsVACsX1ubZn6gZ9hfwlzG0tyjFM72XQhpaXQ56cE6Ew==} + '@nomicfoundation/hardhat-verify@2.0.9': + resolution: {integrity: sha512-7kD8hu1+zlnX87gC+UN4S0HTKBnIsDfXZ/pproq1gYsK94hgCk+exvzXbwR0X2giiY/RZPkqY9oKRi0Uev91hQ==} peerDependencies: - hardhat: ^2.0.4 + hardhat: ^2.22.72.0.4 '@nomicfoundation/solidity-analyzer-darwin-arm64@0.1.0': resolution: {integrity: sha512-vEF3yKuuzfMHsZecHQcnkUrqm8mnTWfJeEVFHpg+cO+le96xQA4lAJYdUan8pXZohQxv1fSReQsn4QGNuBNuCw==} @@ -616,8 +613,8 @@ packages: '@openzeppelin/contracts@4.9.3': resolution: {integrity: sha512-He3LieZ1pP2TNt5JbkPA4PNT9WC3gOTOlDcFGJW4Le4QKqwmiNJCRt44APfxMxvq7OugU/cqYuPcSBzOw38DAg==} - '@openzeppelin/upgrades-core@1.32.5': - resolution: {integrity: sha512-R0wprsyJ4xWiRW05kaTfZZkRVpG2g0af3/hpjE7t2mX0Eb2n40MQLokTwqIk4LDzpp910JfLSpB0vBuZ6WNPog==} + '@openzeppelin/upgrades-core@1.34.4': + resolution: {integrity: sha512-iGN3StqYHYVqqSKs8hWY+Gz6VkiEqOkQccBhHl7lHLGBJF91QUZ8wNMZ59SA5Usg1Fstu/HurvZTCEshPJAZ8w==} hasBin: true '@pkgr/core@0.1.1': @@ -748,8 +745,8 @@ packages: '@types/chai-as-promised@7.1.8': resolution: {integrity: sha512-ThlRVIJhr69FLlh6IctTXFkmhtP3NpMZ2QGq69StYLyKZFp/HOp1VdKZj7RvfNWYYcJ1xlbLGLLWj1UvP5u/Gw==} - '@types/chai@4.3.16': - resolution: {integrity: sha512-PatH4iOdyh3MyWtmHVFXLWCCIhUbopaltqddG9BzB+gMIzee2MJrvd+jouii9Z3wzQJruGWAm7WOMjgfG8hQlQ==} + '@types/chai@4.3.17': + resolution: {integrity: sha512-zmZ21EWzR71B4Sscphjief5djsLre50M6lI622OSySTmn9DB3j+C3kWroHfBQWXbOBwbgg/M8CG/hUxDLIloow==} '@types/debug@4.1.12': resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==} @@ -766,11 +763,8 @@ packages: '@types/lru-cache@5.1.1': resolution: {integrity: sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw==} - '@types/minimist@1.2.5': - resolution: {integrity: sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==} - - '@types/mocha@10.0.6': - resolution: {integrity: sha512-dJvrYWxP/UcXm36Qn36fxhUKu8A/xMRXVT2cliFF1Z7UA9liG5Psj3ezNSZw+5puH2czDXRLcXQxf8JbJt0ejg==} + '@types/mocha@10.0.7': + resolution: {integrity: sha512-GN8yJ1mNTcFcah/wKEFIJckJx9iJLoMSzWcfRRuxz/Jk+U6KQNnml+etbtxFK8lPjzOw3zp4Ha/kjSst9fsHYw==} '@types/ms@0.7.31': resolution: {integrity: sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==} @@ -778,11 +772,8 @@ packages: '@types/node@12.19.16': resolution: {integrity: sha512-7xHmXm/QJ7cbK2laF+YYD7gb5MggHIIQwqyjin3bpEGiSuvScMQ5JZZXPvRipi1MwckTQbJZROMns/JxdnIL1Q==} - '@types/node@20.12.12': - resolution: {integrity: sha512-eWLDGF/FOSPtAvEqeRAQ4C8LSA7M1I7i0ky1I8U7kD1J5ITyW3AsRhQrKVoWf5pFKZ2kILsEGJhsI9r93PYnOw==} - - '@types/normalize-package-data@2.4.4': - resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} + '@types/node@20.14.15': + resolution: {integrity: sha512-Fz1xDMCF/B00/tYSVMlmK7hVeLh7jE5f3B7X1/hmV0MJBwE27KlS7EvD/Yp+z1lm8mVhwV5w+n8jOZG8AfTlKw==} '@types/pbkdf2@3.1.0': resolution: {integrity: sha512-Cf63Rv7jCQ0LaL8tNXmEyqTHuIJxRdlS5vMh1mj5voN4+QFhVZnlZruezqpWYDiJ8UTzhP0VmeLXCmBk66YrMQ==} @@ -802,8 +793,8 @@ packages: '@types/semver@7.5.0': resolution: {integrity: sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==} - '@typescript-eslint/eslint-plugin@7.10.0': - resolution: {integrity: sha512-PzCr+a/KAef5ZawX7nbyNwBDtM1HdLIT53aSA2DDlxmxMngZ43O8SIePOeX8H5S+FHXeI6t97mTt/dDdzY4Fyw==} + '@typescript-eslint/eslint-plugin@7.18.0': + resolution: {integrity: sha512-94EQTWZ40mzBc42ATNIBimBEDltSJ9RQHCC8vc/PDbxi4k8dVwUAv4o98dk50M1zB+JGFxp43FP7f8+FP8R6Sw==} engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: '@typescript-eslint/parser': ^7.0.0 @@ -813,8 +804,8 @@ packages: typescript: optional: true - '@typescript-eslint/parser@7.10.0': - resolution: {integrity: sha512-2EjZMA0LUW5V5tGQiaa2Gys+nKdfrn2xiTIBLR4fxmPmVSvgPcKNW+AE/ln9k0A4zDUti0J/GZXMDupQoI+e1w==} + '@typescript-eslint/parser@7.18.0': + resolution: {integrity: sha512-4Z+L8I2OqhZV8qA132M4wNL30ypZGYOQVBfMgxDH/K5UX0PNqTu1c6za9ST5r9+tavvHiTWmBnKzpCJ/GlVFtg==} engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: eslint: ^8.56.0 @@ -823,12 +814,12 @@ packages: typescript: optional: true - '@typescript-eslint/scope-manager@7.10.0': - resolution: {integrity: sha512-7L01/K8W/VGl7noe2mgH0K7BE29Sq6KAbVmxurj8GGaPDZXPr8EEQ2seOeAS+mEV9DnzxBQB6ax6qQQ5C6P4xg==} + '@typescript-eslint/scope-manager@7.18.0': + resolution: {integrity: sha512-jjhdIE/FPF2B7Z1uzc6i3oWKbGcHb87Qw7AWj6jmEqNOfDFbJWtjt/XfwCpvNkpGWlcJaog5vTR+VV8+w9JflA==} engines: {node: ^18.18.0 || >=20.0.0} - '@typescript-eslint/type-utils@7.10.0': - resolution: {integrity: sha512-D7tS4WDkJWrVkuzgm90qYw9RdgBcrWmbbRkrLA4d7Pg3w0ttVGDsvYGV19SH8gPR5L7OtcN5J1hTtyenO9xE9g==} + '@typescript-eslint/type-utils@7.18.0': + resolution: {integrity: sha512-XL0FJXuCLaDuX2sYqZUUSOJ2sG5/i1AAze+axqmLnSkNEVMVYLF+cbwlB2w8D1tinFuSikHmFta+P+HOofrLeA==} engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: eslint: ^8.56.0 @@ -837,12 +828,12 @@ packages: typescript: optional: true - '@typescript-eslint/types@7.10.0': - resolution: {integrity: sha512-7fNj+Ya35aNyhuqrA1E/VayQX9Elwr8NKZ4WueClR3KwJ7Xx9jcCdOrLW04h51de/+gNbyFMs+IDxh5xIwfbNg==} + '@typescript-eslint/types@7.18.0': + resolution: {integrity: sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==} engines: {node: ^18.18.0 || >=20.0.0} - '@typescript-eslint/typescript-estree@7.10.0': - resolution: {integrity: sha512-LXFnQJjL9XIcxeVfqmNj60YhatpRLt6UhdlFwAkjNc6jSUlK8zQOl1oktAP8PlWFzPQC1jny/8Bai3/HPuvN5g==} + '@typescript-eslint/typescript-estree@7.18.0': + resolution: {integrity: sha512-aP1v/BSPnnyhMHts8cf1qQ6Q1IFwwRvAQGRvBFkWlo3/lH29OXA3Pts+c10nxRxIBrDnoMqzhgdwVe5f2D6OzA==} engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: typescript: '*' @@ -850,14 +841,14 @@ packages: typescript: optional: true - '@typescript-eslint/utils@7.10.0': - resolution: {integrity: sha512-olzif1Fuo8R8m/qKkzJqT7qwy16CzPRWBvERS0uvyc+DHd8AKbO4Jb7kpAvVzMmZm8TrHnI7hvjN4I05zow+tg==} + '@typescript-eslint/utils@7.18.0': + resolution: {integrity: sha512-kK0/rNa2j74XuHVcoCZxdFBMF+aq/vH83CXAOHieC+2Gis4mF8jJXT5eAfyD3K0sAxtPuwxaIOIOvhwzVDt/kw==} engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: eslint: ^8.56.0 - '@typescript-eslint/visitor-keys@7.10.0': - resolution: {integrity: sha512-9ntIVgsi6gg6FIq9xjEO4VQJvwOqA3jaBFQJ/6TK5AvEup2+cECI6Fh7QiBxmfMHXU0V0J4RyPeOU1VDNzl9cg==} + '@typescript-eslint/visitor-keys@7.18.0': + resolution: {integrity: sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg==} engines: {node: ^18.18.0 || >=20.0.0} '@ungap/structured-clone@1.2.0': @@ -925,10 +916,6 @@ packages: resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} engines: {node: '>=8'} - ansi-escapes@6.2.1: - resolution: {integrity: sha512-4nJ3yixlEthEJ9Rk4vPcdBRkZvQZlYyu8j4/Mqz5sgIkddmEnH2Yj2ZrnP9S3tQOvSNRUIgVNF/1yPpRAGNRig==} - engines: {node: '>=14.16'} - ansi-regex@2.1.1: resolution: {integrity: sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==} engines: {node: '>=0.10.0'} @@ -937,10 +924,6 @@ packages: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} - ansi-regex@6.0.1: - resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} - engines: {node: '>=12'} - ansi-styles@3.2.1: resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} engines: {node: '>=4'} @@ -949,10 +932,6 @@ packages: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} - ansi-styles@6.2.1: - resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} - engines: {node: '>=12'} - antlr4@4.13.1-patch-1: resolution: {integrity: sha512-OjFLWWLzDMV9rdFhpvroCWR4ooktNg9/nvVYSA5z28wuVpU36QUNuioR1XLnQtcjVlf8npjyz593PxnU/f/Cow==} engines: {node: '>=16'} @@ -993,10 +972,6 @@ packages: resolution: {integrity: sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==} engines: {node: '>= 0.4'} - array.prototype.flat@1.3.2: - resolution: {integrity: sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==} - engines: {node: '>= 0.4'} - arraybuffer.prototype.slice@1.0.2: resolution: {integrity: sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==} engines: {node: '>= 0.4'} @@ -1005,10 +980,6 @@ packages: resolution: {integrity: sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==} engines: {node: '>= 0.4'} - arrify@1.0.1: - resolution: {integrity: sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==} - engines: {node: '>=0.10.0'} - assertion-error@1.1.0: resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} @@ -1086,9 +1057,6 @@ packages: resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} engines: {node: '>=8'} - breakword@1.0.6: - resolution: {integrity: sha512-yjxDAYyK/pBvws9H4xKYpLDpYKEH6CzrBPAuXq3x18I+c/2MkVtT3qAr7Oloi6Dss9qNhPVueAAVU1CSeNDIXw==} - brorand@1.1.0: resolution: {integrity: sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==} @@ -1140,14 +1108,6 @@ packages: camel-case@3.0.0: resolution: {integrity: sha512-+MbKztAYHXPr1jNTSKQF52VpcFjwY5RkR7fxksV8Doo4KAYc5Fl4UJRgthBbTmEx8C54DqahhbLJkDwjI3PI/w==} - camelcase-keys@6.2.2: - resolution: {integrity: sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==} - engines: {node: '>=8'} - - camelcase@5.3.1: - resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} - engines: {node: '>=6'} - camelcase@6.3.0: resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} engines: {node: '>=10'} @@ -1169,8 +1129,8 @@ packages: peerDependencies: chai: '>= 2.1.2 < 5' - chai@4.4.1: - resolution: {integrity: sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==} + chai@4.5.0: + resolution: {integrity: sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw==} engines: {node: '>=4'} chalk@2.4.2: @@ -1181,10 +1141,6 @@ packages: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} - chalk@5.3.0: - resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==} - engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} - change-case@3.0.2: resolution: {integrity: sha512-Mww+SLF6MZ0U6kdg11algyKd5BARbyM4TbFBepwowYSR5ClfQGCGtxNXgykpN0uF/bstWeaGDT4JWaDh8zWAHA==} @@ -1216,31 +1172,12 @@ packages: resolution: {integrity: sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==} engines: {node: '>=6'} - cli-cursor@4.0.0: - resolution: {integrity: sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - - cli-truncate@4.0.0: - resolution: {integrity: sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==} - engines: {node: '>=18'} - - cliui@6.0.0: - resolution: {integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==} - cliui@7.0.4: resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} - cliui@8.0.1: - resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} - engines: {node: '>=12'} - clone-response@1.0.2: resolution: {integrity: sha512-yjLXh88P599UOyPTFX0POsd7WxnbsVsGohcwzHOLspIhhpalPw1BcqED8NblyZLKcGrL8dTgMlcaZxV2jAD41Q==} - clone@1.0.4: - resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} - engines: {node: '>=0.8'} - code-error-fragment@0.0.230: resolution: {integrity: sha512-cadkfKp6932H8UkhzE/gcUqhRMNf8jHzkAN7+5Myabswaghu4xABTgPHDCjW+dBAJxj/SpkTYokpzDqY4pCzQw==} engines: {node: '>= 4'} @@ -1258,9 +1195,6 @@ packages: color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - colorette@2.0.20: - resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} - command-exists@1.2.9: resolution: {integrity: sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==} @@ -1276,15 +1210,11 @@ packages: resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==} engines: {node: '>=14'} - commander@11.1.0: - resolution: {integrity: sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==} - engines: {node: '>=16'} - commander@3.0.2: resolution: {integrity: sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow==} - compare-versions@6.1.0: - resolution: {integrity: sha512-LNZQXhqUvqUTotpZ00qLSaify3b4VFD588aRr8MKFw4CMUr98ytzCW5wDH5qx/DEY5kCDXcbcRuCqL0szEf2tg==} + compare-versions@6.1.1: + resolution: {integrity: sha512-4hm4VPpIecmlg59CHXnRDnqGplJFrbLG4aFEl5vl6cK1u76ws3LLvX7ikFnTDl5vo39sjWD6AaDPYodJp/NNHg==} concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} @@ -1326,19 +1256,6 @@ packages: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} engines: {node: '>= 8'} - csv-generate@3.4.3: - resolution: {integrity: sha512-w/T+rqR0vwvHqWs/1ZyMDWtHHSJaN06klRqJXBEpDJaM/+dZkso0OKh1VcuuYvK3XM53KysVNq8Ko/epCK8wOw==} - - csv-parse@4.16.3: - resolution: {integrity: sha512-cO1I/zmz4w2dcKHVvpCr7JVRu8/FymG5OEpmvsZYlccYolPBLoVGKUHgNoc4ZGkFeFlWGEDmMyBM+TTqRdW/wg==} - - csv-stringify@5.6.5: - resolution: {integrity: sha512-PjiQ659aQ+fUTQqSrd1XEDnOr52jh30RBurfzkscaE2tPaFsDH5wOAHJiw8XAHphRknCwMUE9KRayc4K/NbO8A==} - - csv@5.5.3: - resolution: {integrity: sha512-QTaY0XjjhTQOdguARF0lGKm5/mEq9PD9/VhZZegHDIBq2tQwgNpHc3dneD4mGo2iJs+fTKv5Bp0fZ+BRuY3Z0g==} - engines: {node: '>= 0.1.90'} - data-view-buffer@1.0.1: resolution: {integrity: sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==} engines: {node: '>= 0.4'} @@ -1363,13 +1280,14 @@ packages: supports-color: optional: true - decamelize-keys@1.1.1: - resolution: {integrity: sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==} - engines: {node: '>=0.10.0'} - - decamelize@1.2.0: - resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} - engines: {node: '>=0.10.0'} + debug@4.3.6: + resolution: {integrity: sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true decamelize@4.0.0: resolution: {integrity: sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==} @@ -1393,9 +1311,6 @@ packages: deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} - defaults@1.0.4: - resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} - defer-to-connect@2.0.1: resolution: {integrity: sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==} engines: {node: '>=10'} @@ -1451,9 +1366,6 @@ packages: elliptic@6.5.4: resolution: {integrity: sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==} - emoji-regex@10.3.0: - resolution: {integrity: sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==} - emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} @@ -1524,8 +1436,8 @@ packages: peerDependencies: eslint: '>=7.0.0' - eslint-plugin-prettier@5.1.3: - resolution: {integrity: sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==} + eslint-plugin-prettier@5.2.1: + resolution: {integrity: sha512-gH3iR3g4JfF+yYPaJYkN7jEl9QbweL/YfkoRlNnuIEHEz1vHVlCmWOS+eGGiRuzHQXdJFCOTxRgvju9b8VUmrw==} engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: '@types/eslint': '>=8.0.0' @@ -1606,16 +1518,9 @@ packages: resolution: {integrity: sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==} engines: {node: '>=6.5.0', npm: '>=3'} - eventemitter3@5.0.1: - resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} - evp_bytestokey@1.0.3: resolution: {integrity: sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==} - execa@8.0.1: - resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} - engines: {node: '>=16.17'} - extendable-error@0.1.7: resolution: {integrity: sha512-UOiS2in6/Q0FK0R0q6UY9vYpQ21mr/Qn1KOnte7vsACuNJf514WvCCUHSRCPcgjPT2bAhNIJdlE6bVap1GKmeg==} @@ -1742,10 +1647,6 @@ packages: resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} engines: {node: 6.* || 8.* || >= 10.*} - get-east-asian-width@1.2.0: - resolution: {integrity: sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==} - engines: {node: '>=18'} - get-func-name@2.0.2: resolution: {integrity: sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==} @@ -1764,10 +1665,6 @@ packages: resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} engines: {node: '>=10'} - get-stream@8.0.1: - resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} - engines: {node: '>=16'} - get-symbol-description@1.0.0: resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==} engines: {node: '>= 0.4'} @@ -1796,6 +1693,7 @@ packages: glob@8.1.0: resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} engines: {node: '>=12'} + deprecated: Glob versions prior to v9 are no longer supported globals@13.24.0: resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} @@ -1825,10 +1723,6 @@ packages: graphemer@1.4.0: resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} - hard-rejection@2.1.0: - resolution: {integrity: sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==} - engines: {node: '>=6'} - hardhat-abi-exporter@2.10.1: resolution: {integrity: sha512-X8GRxUTtebMAd2k4fcPyVnCdPa6dYK4lBsrwzKP5yiSq4i+WadWPIumaLfce53TUf/o2TnLpLOduyO1ylE2NHQ==} engines: {node: '>=14.14.0'} @@ -1887,10 +1781,6 @@ packages: resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} engines: {node: '>= 0.4'} - has@1.0.3: - resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} - engines: {node: '>= 0.4.0'} - hash-base@3.1.0: resolution: {integrity: sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==} engines: {node: '>=4'} @@ -1916,9 +1806,6 @@ packages: hmac-drbg@1.0.1: resolution: {integrity: sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==} - hosted-git-info@2.8.9: - resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} - http-cache-semantics@4.0.3: resolution: {integrity: sha512-TcIMG3qeVLgDr1TEd2XvHaTnMPwYQUQMIBLy+5pLSDKYFc7UIqj39w8EGzZkaxoLv/l2K8HaI0t5AVA+YYgUew==} @@ -1937,15 +1824,6 @@ packages: human-id@1.0.2: resolution: {integrity: sha512-UNopramDEhHJD+VR+ehk8rOslwSfByxPIZyJRfV739NDhN5LF1fa1MqnzKm2lGTQRjNrjK19Q5fhkgIfjlVUKw==} - human-signals@5.0.0: - resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} - engines: {node: '>=16.17.0'} - - husky@9.0.11: - resolution: {integrity: sha512-AB6lFlbwwyIqMdHYhwPe+kjOC3Oc5P3nThEoW/AaO2BX3vJDjWPFxYLxokUZOo6RNX20He3AaT8sESs9NJcmEw==} - engines: {node: '>=18'} - hasBin: true - iconv-lite@0.4.24: resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} engines: {node: '>=0.10.0'} @@ -2022,9 +1900,6 @@ packages: resolution: {integrity: sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==} hasBin: true - is-core-module@2.10.0: - resolution: {integrity: sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==} - is-data-view@1.0.1: resolution: {integrity: sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==} engines: {node: '>= 0.4'} @@ -2046,14 +1921,6 @@ packages: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} engines: {node: '>=8'} - is-fullwidth-code-point@4.0.0: - resolution: {integrity: sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==} - engines: {node: '>=12'} - - is-fullwidth-code-point@5.0.0: - resolution: {integrity: sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==} - engines: {node: '>=18'} - is-glob@4.0.3: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} @@ -2085,10 +1952,6 @@ packages: resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} engines: {node: '>=8'} - is-plain-obj@1.1.0: - resolution: {integrity: sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==} - engines: {node: '>=0.10.0'} - is-plain-obj@2.1.0: resolution: {integrity: sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==} engines: {node: '>=8'} @@ -2104,10 +1967,6 @@ packages: resolution: {integrity: sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==} engines: {node: '>= 0.4'} - is-stream@3.0.0: - resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - is-string@1.0.7: resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} engines: {node: '>= 0.4'} @@ -2205,26 +2064,15 @@ packages: resolution: {integrity: sha512-PyKKjkH53wDMLGrvmRGSNWgmSxZOUqbnXwKL9tmgbFYA1iAYqW21kfR7mZXV0MlESiefxQQE9X9fTa3X+2MPDQ==} engines: {node: '>=10.0.0'} - keyv@4.5.0: - resolution: {integrity: sha512-2YvuMsA+jnFGtBareKqgANOEKe1mk3HKiXu2fRmAfyxG0MJAywNhi5ttWA3PMjl4NmpyjZNbFifR2vNjW1znfA==} - keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} - kind-of@6.0.3: - resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} - engines: {node: '>=0.10.0'} - klaw-sync@6.0.0: resolution: {integrity: sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ==} klaw@1.3.1: resolution: {integrity: sha512-TED5xi9gGQjGpNnvRWknrwAB1eL5GciPfVFOt3Vk1OJCVDQbzuSfrF3hkUQKlsgKrG1F+0t5W0m+Fje1jIt8rw==} - kleur@4.1.5: - resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} - engines: {node: '>=6'} - latest-version@7.0.0: resolution: {integrity: sha512-KvNT4XqAMzdcL6ka6Tl3i2lYeFDgXNCuIX+xNx6ZMVR1dFq+idXd9FLKNMOIx0t9mJ9/HudyX4oZWXZQ0UJHeg==} engines: {node: '>=14.16'} @@ -2237,22 +2085,9 @@ packages: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} - lilconfig@3.0.0: - resolution: {integrity: sha512-K2U4W2Ff5ibV7j7ydLr+zLAkIg5JJ4lPn1Ltsdt+Tz/IjQ8buJ55pZAxoP34lqIiwtF9iAvtLv3JGv7CAyAg+g==} - engines: {node: '>=14'} - lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - lint-staged@15.2.2: - resolution: {integrity: sha512-TiTt93OPh1OZOsb5B7k96A/ATl2AjIZo+vnzFZ6oHK5FuTk63ByDtxGQpHm+kFETjEWqgkF95M8FRXKR/LEBcw==} - engines: {node: '>=18.12.0'} - hasBin: true - - listr2@8.0.1: - resolution: {integrity: sha512-ovJXBXkKGfq+CwmKTjluEqFi3p4h8xvkxGQQAQan22YCgef4KZ1mKGjzfGh6PL6AW5Csw0QiQPNuQyH+6Xk3hA==} - engines: {node: '>=18.0.0'} - load-yaml-file@0.2.0: resolution: {integrity: sha512-OfCBkGEw4nN6JLtgRidPX6QxjBQGQf72q3si2uvqyFEMbycSFFHwAZeXx6cJgFM9wmLrf9zBwCP3Ivqa+LLZPw==} engines: {node: '>=6'} @@ -2297,10 +2132,6 @@ packages: resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} engines: {node: '>=10'} - log-update@6.0.0: - resolution: {integrity: sha512-niTvB4gqvtof056rRIrTZvjNYE4rCUzO6X/X+kYjd7WFxXeJ0NwEFnRxX6ehkvv3jTwrXnNdtAak5XYZuIyPFw==} - engines: {node: '>=18'} - loupe@2.3.7: resolution: {integrity: sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==} @@ -2331,14 +2162,6 @@ packages: make-error@1.3.6: resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} - map-obj@1.0.1: - resolution: {integrity: sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==} - engines: {node: '>=0.10.0'} - - map-obj@4.3.0: - resolution: {integrity: sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==} - engines: {node: '>=8'} - md5.js@1.3.5: resolution: {integrity: sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==} @@ -2346,13 +2169,6 @@ packages: resolution: {integrity: sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==} engines: {node: '>= 0.10.0'} - meow@6.1.1: - resolution: {integrity: sha512-3YffViIt2QWgTy6Pale5QpopX/IvU3LPL03jOTqp6pGj3VjesdO/U8CuHMKpnQr4shCNCM5fd5XFFvIIl6JBHg==} - engines: {node: '>=8'} - - merge-stream@2.0.0: - resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} - merge2@1.4.1: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} @@ -2361,14 +2177,6 @@ packages: resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} engines: {node: '>=8.6'} - mimic-fn@2.1.0: - resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} - engines: {node: '>=6'} - - mimic-fn@4.0.0: - resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} - engines: {node: '>=12'} - mimic-response@1.0.1: resolution: {integrity: sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==} engines: {node: '>=4'} @@ -2377,10 +2185,6 @@ packages: resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} engines: {node: '>=10'} - min-indent@1.0.1: - resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} - engines: {node: '>=4'} - minimalistic-assert@1.0.1: resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} @@ -2402,17 +2206,9 @@ packages: resolution: {integrity: sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==} engines: {node: '>=16 || 14 >=14.17'} - minimist-options@4.1.0: - resolution: {integrity: sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==} - engines: {node: '>= 6'} - minimist@1.2.8: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - mixme@0.5.10: - resolution: {integrity: sha512-5H76ANWinB1H3twpJ6JY8uvAtpmFvHNArpilJAjXRKXSDDLPIMoZArw5SH0q9z+lLs8IrMw7Q2VWpWimFKFT1Q==} - engines: {node: '>= 8.0.0'} - mkdirp@1.0.4: resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} engines: {node: '>=10'} @@ -2429,6 +2225,10 @@ packages: moment@2.30.1: resolution: {integrity: sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==} + mri@1.2.0: + resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} + engines: {node: '>=4'} + ms@2.1.2: resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} @@ -2480,9 +2280,6 @@ packages: resolution: {integrity: sha512-l2NNj07e9afPnhAhvgVrCD/oy2Ai1yfLpuo3EpiO1jFTsB4sFz6oIfAfSZyQzVpkZQ9xS8ZS5g1jCBgq4Hwo0g==} engines: {node: '>=12.19'} - normalize-package-data@2.5.0: - resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} - normalize-path@3.0.0: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} @@ -2491,10 +2288,6 @@ packages: resolution: {integrity: sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==} engines: {node: '>=10'} - npm-run-path@5.3.0: - resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - number-to-bn@1.7.0: resolution: {integrity: sha512-wsJ9gfSz1/s4ZsJN01lyonwuxA1tml6X1yBDnfpMglypcBRFZZkus26EdPSlqS5GJfYddVZa22p3VNb3z5m5Ig==} engines: {node: '>=6.5.0', npm: '>=3'} @@ -2520,14 +2313,6 @@ packages: once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - onetime@5.1.2: - resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} - engines: {node: '>=6'} - - onetime@6.0.0: - resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} - engines: {node: '>=12'} - open@7.4.2: resolution: {integrity: sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==} engines: {node: '>=8'} @@ -2640,10 +2425,6 @@ packages: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} - path-key@4.0.0: - resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} - engines: {node: '>=12'} - path-parse@1.0.7: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} @@ -2666,11 +2447,6 @@ packages: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} - pidtree@0.6.0: - resolution: {integrity: sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==} - engines: {node: '>=0.10'} - hasBin: true - pify@4.0.1: resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} engines: {node: '>=6'} @@ -2710,8 +2486,8 @@ packages: engines: {node: '>=10.13.0'} hasBin: true - prettier@3.2.5: - resolution: {integrity: sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==} + prettier@3.3.3: + resolution: {integrity: sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==} engines: {node: '>=14'} hasBin: true @@ -2734,10 +2510,6 @@ packages: pure-rand@5.0.3: resolution: {integrity: sha512-9N8x1h8dptBQpHyC7aZMS+iNOAm97WMGY0AFrguU1cpfW3I5jINkWe5BIY5md0ofy+1TCIELsVcm/GJXZSaPbw==} - quick-lru@4.0.1: - resolution: {integrity: sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==} - engines: {node: '>=8'} - quick-lru@5.1.1: resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==} engines: {node: '>=10'} @@ -2753,14 +2525,6 @@ packages: resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} hasBin: true - read-pkg-up@7.0.1: - resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==} - engines: {node: '>=8'} - - read-pkg@5.2.0: - resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==} - engines: {node: '>=8'} - read-yaml-file@1.1.0: resolution: {integrity: sha512-VIMnQi/Z4HT2Fxuwg5KrY174U1VdUIASQVWXXyqtNRtxSr9IYkn1rsI6Tb6HsrHCmB7gVpNwX6JxPTHcH6IoTA==} engines: {node: '>=6'} @@ -2773,10 +2537,6 @@ packages: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} - redent@3.0.0: - resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} - engines: {node: '>=8'} - reduce-flatten@2.0.0: resolution: {integrity: sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w==} engines: {node: '>=6'} @@ -2808,9 +2568,6 @@ packages: resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} engines: {node: '>=0.10.0'} - require-main-filename@2.0.0: - resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==} - resolve-alpn@1.2.1: resolution: {integrity: sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==} @@ -2825,17 +2582,9 @@ packages: resolve@1.17.0: resolution: {integrity: sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==} - resolve@1.22.1: - resolution: {integrity: sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==} - hasBin: true - responselike@2.0.1: resolution: {integrity: sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==} - restore-cursor@4.0.0: - resolution: {integrity: sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - retry@0.12.0: resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==} engines: {node: '>= 4'} @@ -2844,9 +2593,6 @@ packages: resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - rfdc@1.3.1: - resolution: {integrity: sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg==} - rimraf@2.7.1: resolution: {integrity: sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==} hasBin: true @@ -2910,8 +2656,8 @@ packages: resolution: {integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==} hasBin: true - semver@7.6.2: - resolution: {integrity: sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==} + semver@7.6.3: + resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==} engines: {node: '>=10'} hasBin: true @@ -2921,9 +2667,6 @@ packages: serialize-javascript@6.0.0: resolution: {integrity: sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==} - set-blocking@2.0.0: - resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} - set-function-length@1.1.1: resolution: {integrity: sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==} engines: {node: '>= 0.4'} @@ -2971,10 +2714,6 @@ packages: signal-exit@3.0.7: resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} - signal-exit@4.1.0: - resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} - engines: {node: '>=14'} - slash@2.0.0: resolution: {integrity: sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==} engines: {node: '>=6'} @@ -2987,19 +2726,6 @@ packages: resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==} engines: {node: '>=10'} - slice-ansi@5.0.0: - resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==} - engines: {node: '>=12'} - - slice-ansi@7.1.0: - resolution: {integrity: sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==} - engines: {node: '>=18'} - - smartwrap@2.0.2: - resolution: {integrity: sha512-vCsKNQxb7PnCNd2wY1WClWifAc2lwqsG8OaswpJkVJsvMGcnEntdTCDajZCkk93Ay1U3t/9puJmb525Rg5MZBA==} - engines: {node: '>=6'} - hasBin: true - snake-case@2.1.0: resolution: {integrity: sha512-FMR5YoPFwOLuh4rRz92dywJjyKYZNLpMn1R5ujVpIYkbA9p01fq8RMg0FkO4M+Yobt4MjHeLTJVm5xFFBHSV2Q==} @@ -3014,8 +2740,8 @@ packages: prettier: ^3.0.0 prettier-plugin-solidity: ^1.0.0 - solhint@5.0.1: - resolution: {integrity: sha512-QeQLS9HGCnIiibt+xiOa/+MuP7BWz9N7C5+Mj9pLHshdkNhuo3AzCpWmjfWVZBUuwIUO3YyCRVIcYLR3YOKGfg==} + solhint@5.0.3: + resolution: {integrity: sha512-OLCH6qm/mZTCpplTXzXTJGId1zrtNuDYP5c2e6snIv/hdRVxPfBBz/bAlL91bY/Accavkayp2Zp2BaDSrLVXTQ==} hasBin: true solidity-ast@0.4.56: @@ -3101,18 +2827,6 @@ packages: spawndamnit@2.0.0: resolution: {integrity: sha512-j4JKEcncSjFlqIwU5L/rp2N5SIPsdxaRsIv678+TZxZ0SRDJTm8JrxJMjE/XuiEZNEir3S8l0Fa3Ke339WI4qA==} - spdx-correct@3.1.1: - resolution: {integrity: sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==} - - spdx-exceptions@2.3.0: - resolution: {integrity: sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==} - - spdx-expression-parse@3.0.1: - resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} - - spdx-license-ids@3.0.12: - resolution: {integrity: sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA==} - sprintf-js@1.0.3: resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} @@ -3124,13 +2838,6 @@ packages: resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} engines: {node: '>= 0.8'} - stream-transform@2.1.3: - resolution: {integrity: sha512-9GHUiM5hMiCi6Y03jD2ARC1ettBXkQBoQAe7nJsPknnI0ow10aXjTnew8QtYQmLjzn974BnmWEAJgCY6ZP1DeQ==} - - string-argv@0.3.2: - resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} - engines: {node: '>=0.6.19'} - string-format@2.0.0: resolution: {integrity: sha512-bbEs3scLeYNXLecRRuk6uJxdXUSj6le/8rNPHChIJTn2V79aXVTR1EH2OH5zLKKoz0V02fOUKZZcw01pLUShZA==} @@ -3138,10 +2845,6 @@ packages: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} - string-width@7.1.0: - resolution: {integrity: sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==} - engines: {node: '>=18'} - string.prototype.trim@1.2.8: resolution: {integrity: sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==} engines: {node: '>= 0.4'} @@ -3170,26 +2873,14 @@ packages: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} - strip-ansi@7.1.0: - resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} - engines: {node: '>=12'} - strip-bom@3.0.0: resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} engines: {node: '>=4'} - strip-final-newline@3.0.0: - resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} - engines: {node: '>=12'} - strip-hex-prefix@1.0.0: resolution: {integrity: sha1-DF8VX+8RUTczd96du1iNoFUA428=} engines: {node: '>=6.5.0', npm: '>=3'} - strip-indent@3.0.0: - resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} - engines: {node: '>=8'} - strip-json-comments@2.0.1: resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} engines: {node: '>=0.10.0'} @@ -3210,15 +2901,11 @@ packages: resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} engines: {node: '>=10'} - supports-preserve-symlinks-flag@1.0.0: - resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} - engines: {node: '>= 0.4'} - swap-case@1.1.2: resolution: {integrity: sha512-BAmWG6/bx8syfc6qXPprof3Mn5vQgf5dwdUNJhsNqU9WdPt5P+ES/wQ5bxfijy8zwZgZZHslC3iAsxsuQMCzJQ==} - synckit@0.8.8: - resolution: {integrity: sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==} + synckit@0.9.1: + resolution: {integrity: sha512-7gr8p9TQP6RAHusBOSLs46F4564ZrjV8xFmw5zCmgmhGUcw2hxsShhJ6CEiHQMgPDwAQ1fWHPM0ypc4RMAig4A==} engines: {node: ^14.18.0 || >=16.0.0} table-layout@1.0.2: @@ -3254,10 +2941,6 @@ packages: tr46@0.0.3: resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} - trim-newlines@3.0.1: - resolution: {integrity: sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==} - engines: {node: '>=8'} - ts-api-utils@1.3.0: resolution: {integrity: sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==} engines: {node: '>=16'} @@ -3296,11 +2979,6 @@ packages: tsort@0.0.1: resolution: {integrity: sha512-Tyrf5mxF8Ofs1tNoxA13lFeZ2Zrbd6cKbuH3V+MQ5sb6DtBj5FjrXVsRWT8YvNAQTqNoz66dz1WsbigI22aEnw==} - tty-table@4.2.3: - resolution: {integrity: sha512-Fs15mu0vGzCrj8fmJNP7Ynxt5J7praPXqFN0leZeZBXJwkMxv9cb2D454k1ltrtUSJbZ4yH4e0CynsHLxmUfFA==} - engines: {node: '>=8.0.0'} - hasBin: true - tweetnacl-util@0.15.1: resolution: {integrity: sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw==} @@ -3315,9 +2993,9 @@ packages: resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} engines: {node: '>=4'} - type-fest@0.13.1: - resolution: {integrity: sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==} - engines: {node: '>=10'} + type-detect@4.1.0: + resolution: {integrity: sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==} + engines: {node: '>=4'} type-fest@0.20.2: resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} @@ -3327,18 +3005,10 @@ packages: resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} engines: {node: '>=10'} - type-fest@0.6.0: - resolution: {integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==} - engines: {node: '>=8'} - type-fest@0.7.1: resolution: {integrity: sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==} engines: {node: '>=8'} - type-fest@0.8.1: - resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==} - engines: {node: '>=8'} - typechain@8.3.2: resolution: {integrity: sha512-x/sQYr5w9K7yv3es7jo4KTX05CLxOf7TRWwoHlrjRh8H82G64g+k7VuWPJlgMo6qrjfCulOdfBjiaDtmhFYD/Q==} hasBin: true @@ -3376,8 +3046,8 @@ packages: resolution: {integrity: sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==} engines: {node: '>= 0.4'} - typescript@5.4.5: - resolution: {integrity: sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==} + typescript@5.5.4: + resolution: {integrity: sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==} engines: {node: '>=14.17'} hasBin: true @@ -3433,12 +3103,6 @@ packages: v8-compile-cache-lib@3.0.1: resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} - validate-npm-package-license@3.0.4: - resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} - - wcwidth@1.0.1: - resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} - web3-utils@1.7.4: resolution: {integrity: sha512-acBdm6Evd0TEZRnChM/MCvGsMwYKmSh7OaUfNf5OKG0CIeGWD/6gqLOWIwmwSnre/2WrA1nKGId5uW2e5EfluA==} engines: {node: '>=8.0.0'} @@ -3452,9 +3116,6 @@ packages: which-boxed-primitive@1.0.2: resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} - which-module@2.0.0: - resolution: {integrity: sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q==} - which-pm@2.0.0: resolution: {integrity: sha512-Lhs9Pmyph0p5n5Z3mVnN0yWcbQYUAD7rbQUiMsQxOJ3T57k7RFe35SUwWMf7dsbDZks1uOmw4AecB/JMDj3v/w==} engines: {node: '>=8.15'} @@ -3487,18 +3148,10 @@ packages: workerpool@6.2.1: resolution: {integrity: sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==} - wrap-ansi@6.2.0: - resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} - engines: {node: '>=8'} - wrap-ansi@7.0.0: resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} engines: {node: '>=10'} - wrap-ansi@9.0.0: - resolution: {integrity: sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==} - engines: {node: '>=18'} - wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} @@ -3526,9 +3179,6 @@ packages: utf-8-validate: optional: true - y18n@4.0.3: - resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==} - y18n@5.0.8: resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} engines: {node: '>=10'} @@ -3540,38 +3190,18 @@ packages: resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==} engines: {node: '>= 6'} - yaml@2.3.4: - resolution: {integrity: sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==} - engines: {node: '>= 14'} - - yargs-parser@18.1.3: - resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==} - engines: {node: '>=6'} - yargs-parser@20.2.4: resolution: {integrity: sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==} engines: {node: '>=10'} - yargs-parser@21.1.1: - resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} - engines: {node: '>=12'} - yargs-unparser@2.0.0: resolution: {integrity: sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==} engines: {node: '>=10'} - yargs@15.4.1: - resolution: {integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==} - engines: {node: '>=8'} - yargs@16.2.0: resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==} engines: {node: '>=10'} - yargs@17.7.2: - resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} - engines: {node: '>=12'} - yn@3.1.1: resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} engines: {node: '>=6'} @@ -3598,7 +3228,7 @@ snapshots: '@openzeppelin/contracts': 4.8.3 '@openzeppelin/contracts-upgradeable': 4.8.3 optionalDependencies: - '@openzeppelin/upgrades-core': 1.32.5 + '@openzeppelin/upgrades-core': 1.34.4 transitivePeerDependencies: - supports-color @@ -3620,12 +3250,13 @@ snapshots: '@chainlink/solhint-plugin-chainlink-solidity@https://codeload.github.com/smartcontractkit/chainlink-solhint-rules/tar.gz/1b4c0c2663fcd983589d4f33a2e73908624ed43c': {} - '@changesets/apply-release-plan@7.0.1': + '@changesets/apply-release-plan@7.0.4': dependencies: '@babel/runtime': 7.24.0 - '@changesets/config': 3.0.0 + '@changesets/config': 3.0.2 '@changesets/get-version-range-type': 0.4.0 '@changesets/git': 3.0.0 + '@changesets/should-skip-package': 0.1.0 '@changesets/types': 6.0.0 '@manypkg/get-packages': 1.1.3 detect-indent: 6.1.0 @@ -3634,16 +3265,17 @@ snapshots: outdent: 0.5.0 prettier: 2.8.8 resolve-from: 5.0.0 - semver: 7.6.2 + semver: 7.6.3 - '@changesets/assemble-release-plan@6.0.0': + '@changesets/assemble-release-plan@6.0.3': dependencies: '@babel/runtime': 7.24.0 '@changesets/errors': 0.2.0 - '@changesets/get-dependents-graph': 2.0.0 + '@changesets/get-dependents-graph': 2.1.1 + '@changesets/should-skip-package': 0.1.0 '@changesets/types': 6.0.0 '@manypkg/get-packages': 1.1.3 - semver: 7.6.2 + semver: 7.6.3 '@changesets/changelog-git@0.2.0': dependencies: @@ -3657,20 +3289,21 @@ snapshots: transitivePeerDependencies: - encoding - '@changesets/cli@2.27.3': + '@changesets/cli@2.27.7': dependencies: '@babel/runtime': 7.24.0 - '@changesets/apply-release-plan': 7.0.1 - '@changesets/assemble-release-plan': 6.0.0 + '@changesets/apply-release-plan': 7.0.4 + '@changesets/assemble-release-plan': 6.0.3 '@changesets/changelog-git': 0.2.0 - '@changesets/config': 3.0.0 + '@changesets/config': 3.0.2 '@changesets/errors': 0.2.0 - '@changesets/get-dependents-graph': 2.0.0 - '@changesets/get-release-plan': 4.0.0 + '@changesets/get-dependents-graph': 2.1.1 + '@changesets/get-release-plan': 4.0.3 '@changesets/git': 3.0.0 '@changesets/logger': 0.1.0 '@changesets/pre': 2.0.0 '@changesets/read': 0.6.0 + '@changesets/should-skip-package': 0.1.0 '@changesets/types': 6.0.0 '@changesets/write': 0.3.1 '@manypkg/get-packages': 1.1.3 @@ -3682,20 +3315,19 @@ snapshots: external-editor: 3.1.0 fs-extra: 7.0.1 human-id: 1.0.2 - meow: 6.1.1 + mri: 1.2.0 outdent: 0.5.0 p-limit: 2.3.0 preferred-pm: 3.1.3 resolve-from: 5.0.0 - semver: 7.6.2 + semver: 7.6.3 spawndamnit: 2.0.0 term-size: 2.2.1 - tty-table: 4.2.3 - '@changesets/config@3.0.0': + '@changesets/config@3.0.2': dependencies: '@changesets/errors': 0.2.0 - '@changesets/get-dependents-graph': 2.0.0 + '@changesets/get-dependents-graph': 2.1.1 '@changesets/logger': 0.1.0 '@changesets/types': 6.0.0 '@manypkg/get-packages': 1.1.3 @@ -3706,13 +3338,13 @@ snapshots: dependencies: extendable-error: 0.1.7 - '@changesets/get-dependents-graph@2.0.0': + '@changesets/get-dependents-graph@2.1.1': dependencies: '@changesets/types': 6.0.0 '@manypkg/get-packages': 1.1.3 chalk: 2.4.2 fs-extra: 7.0.1 - semver: 7.6.2 + semver: 7.6.3 '@changesets/get-github-info@0.6.0': dependencies: @@ -3721,11 +3353,11 @@ snapshots: transitivePeerDependencies: - encoding - '@changesets/get-release-plan@4.0.0': + '@changesets/get-release-plan@4.0.3': dependencies: '@babel/runtime': 7.24.0 - '@changesets/assemble-release-plan': 6.0.0 - '@changesets/config': 3.0.0 + '@changesets/assemble-release-plan': 6.0.3 + '@changesets/config': 3.0.2 '@changesets/pre': 2.0.0 '@changesets/read': 0.6.0 '@changesets/types': 6.0.0 @@ -3771,6 +3403,12 @@ snapshots: fs-extra: 7.0.1 p-filter: 2.1.0 + '@changesets/should-skip-package@0.1.0': + dependencies: + '@babel/runtime': 7.24.0 + '@changesets/types': 6.0.0 + '@manypkg/get-packages': 1.1.3 + '@changesets/types@4.1.0': {} '@changesets/types@6.0.0': {} @@ -3797,7 +3435,7 @@ snapshots: '@eslint/eslintrc@2.1.4': dependencies: ajv: 6.12.6 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.6 espree: 9.6.1 globals: 13.24.0 ignore: 5.3.1 @@ -3837,7 +3475,7 @@ snapshots: '@ethersproject/transactions': 5.7.0 '@ethersproject/web': 5.7.1 bufio: 1.0.7 - chai: 4.4.1 + chai: 4.5.0 transitivePeerDependencies: - bufferutil - utf-8-validate @@ -4110,7 +3748,7 @@ snapshots: '@humanwhocodes/config-array@0.11.14': dependencies: '@humanwhocodes/object-schema': 2.0.3 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.6 minimatch: 3.1.2 transitivePeerDependencies: - supports-color @@ -4188,7 +3826,7 @@ snapshots: '@nomicfoundation/ethereumjs-trie': 6.0.4 '@nomicfoundation/ethereumjs-tx': 5.0.4 '@nomicfoundation/ethereumjs-util': 9.0.4 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.6 ethereum-cryptography: 0.1.3 lru-cache: 10.2.2 transitivePeerDependencies: @@ -4218,7 +3856,7 @@ snapshots: '@nomicfoundation/ethereumjs-tx': 5.0.4 '@nomicfoundation/ethereumjs-util': 9.0.4 '@types/debug': 4.1.12 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.6 ethereum-cryptography: 0.1.3 rustbn-wasm: 0.2.0 transitivePeerDependencies: @@ -4234,7 +3872,7 @@ snapshots: '@nomicfoundation/ethereumjs-rlp': 5.0.4 '@nomicfoundation/ethereumjs-trie': 6.0.4 '@nomicfoundation/ethereumjs-util': 9.0.4 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.6 ethereum-cryptography: 0.1.3 js-sdsl: 4.4.2 lru-cache: 10.2.2 @@ -4287,47 +3925,47 @@ snapshots: '@nomicfoundation/ethereumjs-trie': 6.0.4 '@nomicfoundation/ethereumjs-tx': 5.0.4 '@nomicfoundation/ethereumjs-util': 9.0.4 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.6 ethereum-cryptography: 0.1.3 transitivePeerDependencies: - '@nomicfoundation/ethereumjs-verkle' - c-kzg - supports-color - '@nomicfoundation/hardhat-chai-matchers@1.0.6(@nomiclabs/hardhat-ethers@2.2.3(ethers@5.7.2)(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5)))(chai@4.4.1)(ethers@5.7.2)(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5))': + '@nomicfoundation/hardhat-chai-matchers@1.0.6(@nomiclabs/hardhat-ethers@2.2.3(ethers@5.7.2)(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.14.15)(typescript@5.5.4))(typescript@5.5.4)))(chai@4.5.0)(ethers@5.7.2)(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.14.15)(typescript@5.5.4))(typescript@5.5.4))': dependencies: '@ethersproject/abi': 5.7.0 - '@nomiclabs/hardhat-ethers': 2.2.3(ethers@5.7.2)(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5)) + '@nomiclabs/hardhat-ethers': 2.2.3(ethers@5.7.2)(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.14.15)(typescript@5.5.4))(typescript@5.5.4)) '@types/chai-as-promised': 7.1.8 - chai: 4.4.1 - chai-as-promised: 7.1.1(chai@4.4.1) + chai: 4.5.0 + chai-as-promised: 7.1.1(chai@4.5.0) deep-eql: 4.1.3 ethers: 5.7.2 - hardhat: 2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5) + hardhat: 2.20.1(ts-node@10.9.2(@types/node@20.14.15)(typescript@5.5.4))(typescript@5.5.4) ordinal: 1.0.3 - '@nomicfoundation/hardhat-ethers@3.0.6(ethers@5.7.2)(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5))': + '@nomicfoundation/hardhat-ethers@3.0.6(ethers@5.7.2)(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.14.15)(typescript@5.5.4))(typescript@5.5.4))': dependencies: - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.6 ethers: 5.7.2 - hardhat: 2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5) + hardhat: 2.20.1(ts-node@10.9.2(@types/node@20.14.15)(typescript@5.5.4))(typescript@5.5.4) lodash.isequal: 4.5.0 transitivePeerDependencies: - supports-color - '@nomicfoundation/hardhat-network-helpers@1.0.10(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5))': + '@nomicfoundation/hardhat-network-helpers@1.0.11(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.14.15)(typescript@5.5.4))(typescript@5.5.4))': dependencies: ethereumjs-util: 7.1.5 - hardhat: 2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5) + hardhat: 2.20.1(ts-node@10.9.2(@types/node@20.14.15)(typescript@5.5.4))(typescript@5.5.4) - '@nomicfoundation/hardhat-verify@2.0.7(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5))': + '@nomicfoundation/hardhat-verify@2.0.9(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.14.15)(typescript@5.5.4))(typescript@5.5.4))': dependencies: '@ethersproject/abi': 5.7.0 '@ethersproject/address': 5.7.0 cbor: 8.1.0 chalk: 2.4.2 - debug: 4.3.4(supports-color@8.1.1) - hardhat: 2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5) + debug: 4.3.6 + hardhat: 2.20.1(ts-node@10.9.2(@types/node@20.14.15)(typescript@5.5.4))(typescript@5.5.4) lodash.clonedeep: 4.5.0 semver: 6.3.0 table: 6.8.1 @@ -4378,10 +4016,10 @@ snapshots: '@nomicfoundation/solidity-analyzer-win32-ia32-msvc': 0.1.0 '@nomicfoundation/solidity-analyzer-win32-x64-msvc': 0.1.0 - '@nomiclabs/hardhat-ethers@2.2.3(ethers@5.7.2)(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5))': + '@nomiclabs/hardhat-ethers@2.2.3(ethers@5.7.2)(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.14.15)(typescript@5.5.4))(typescript@5.5.4))': dependencies: ethers: 5.7.2 - hardhat: 2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5) + hardhat: 2.20.1(ts-node@10.9.2(@types/node@20.14.15)(typescript@5.5.4))(typescript@5.5.4) '@offchainlabs/upgrade-executor@1.1.0-beta.0': dependencies: @@ -4404,12 +4042,12 @@ snapshots: '@openzeppelin/contracts@4.9.3': {} - '@openzeppelin/upgrades-core@1.32.5': + '@openzeppelin/upgrades-core@1.34.4': dependencies: cbor: 9.0.2 chalk: 4.1.2 - compare-versions: 6.1.0 - debug: 4.3.4(supports-color@8.1.1) + compare-versions: 6.1.1 + debug: 4.3.6 ethereumjs-util: 7.1.5 minimist: 1.2.8 proper-lockfile: 4.1.2 @@ -4432,9 +4070,9 @@ snapshots: '@pnpm/network.ca-file': 1.0.2 config-chain: 1.1.13 - '@prettier/sync@0.3.0(prettier@3.2.5)': + '@prettier/sync@0.3.0(prettier@3.3.3)': dependencies: - prettier: 3.2.5 + prettier: 3.3.3 '@scroll-tech/contracts@0.1.0': {} @@ -4519,7 +4157,7 @@ snapshots: '@truffle/contract-schema@3.4.10': dependencies: ajv: 6.12.6 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.6 transitivePeerDependencies: - supports-color @@ -4531,51 +4169,51 @@ snapshots: '@tsconfig/node16@1.0.3': {} - '@typechain/ethers-v5@7.2.0(@ethersproject/abi@5.7.0)(@ethersproject/bytes@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.2(typescript@5.4.5))(typescript@5.4.5)': + '@typechain/ethers-v5@7.2.0(@ethersproject/abi@5.7.0)(@ethersproject/bytes@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.2(typescript@5.5.4))(typescript@5.5.4)': dependencies: '@ethersproject/abi': 5.7.0 '@ethersproject/bytes': 5.7.0 '@ethersproject/providers': 5.7.2 ethers: 5.7.2 lodash: 4.17.21 - ts-essentials: 7.0.3(typescript@5.4.5) - typechain: 8.3.2(typescript@5.4.5) - typescript: 5.4.5 + ts-essentials: 7.0.3(typescript@5.5.4) + typechain: 8.3.2(typescript@5.5.4) + typescript: 5.5.4 - '@typechain/hardhat@7.0.0(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(@typechain/ethers-v5@7.2.0(@ethersproject/abi@5.7.0)(@ethersproject/bytes@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.2(typescript@5.4.5))(typescript@5.4.5))(ethers@5.7.2)(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5))(typechain@8.3.2(typescript@5.4.5))': + '@typechain/hardhat@7.0.0(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(@typechain/ethers-v5@7.2.0(@ethersproject/abi@5.7.0)(@ethersproject/bytes@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.2(typescript@5.5.4))(typescript@5.5.4))(ethers@5.7.2)(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.14.15)(typescript@5.5.4))(typescript@5.5.4))(typechain@8.3.2(typescript@5.5.4))': dependencies: '@ethersproject/abi': 5.7.0 '@ethersproject/providers': 5.7.2 - '@typechain/ethers-v5': 7.2.0(@ethersproject/abi@5.7.0)(@ethersproject/bytes@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.2(typescript@5.4.5))(typescript@5.4.5) + '@typechain/ethers-v5': 7.2.0(@ethersproject/abi@5.7.0)(@ethersproject/bytes@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.2(typescript@5.5.4))(typescript@5.5.4) ethers: 5.7.2 fs-extra: 9.1.0 - hardhat: 2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5) - typechain: 8.3.2(typescript@5.4.5) + hardhat: 2.20.1(ts-node@10.9.2(@types/node@20.14.15)(typescript@5.5.4))(typescript@5.5.4) + typechain: 8.3.2(typescript@5.5.4) '@types/bn.js@4.11.6': dependencies: - '@types/node': 20.12.12 + '@types/node': 20.14.15 '@types/bn.js@5.1.1': dependencies: - '@types/node': 20.12.12 + '@types/node': 20.14.15 '@types/cacheable-request@6.0.2': dependencies: '@types/http-cache-semantics': 4.0.1 '@types/keyv': 3.1.4 - '@types/node': 20.12.12 + '@types/node': 20.14.15 '@types/responselike': 1.0.0 '@types/cbor@5.0.1': dependencies: - '@types/node': 20.12.12 + '@types/node': 20.14.15 '@types/chai-as-promised@7.1.8': dependencies: - '@types/chai': 4.3.16 + '@types/chai': 4.3.17 - '@types/chai@4.3.16': {} + '@types/chai@4.3.17': {} '@types/debug@4.1.12': dependencies: @@ -4587,124 +4225,120 @@ snapshots: '@types/keyv@3.1.4': dependencies: - '@types/node': 20.12.12 + '@types/node': 20.14.15 '@types/lru-cache@5.1.1': {} - '@types/minimist@1.2.5': {} - - '@types/mocha@10.0.6': {} + '@types/mocha@10.0.7': {} '@types/ms@0.7.31': {} '@types/node@12.19.16': {} - '@types/node@20.12.12': + '@types/node@20.14.15': dependencies: undici-types: 5.26.5 - '@types/normalize-package-data@2.4.4': {} - '@types/pbkdf2@3.1.0': dependencies: - '@types/node': 20.12.12 + '@types/node': 20.14.15 '@types/prettier@2.7.1': {} '@types/readable-stream@2.3.15': dependencies: - '@types/node': 20.12.12 + '@types/node': 20.14.15 safe-buffer: 5.1.2 '@types/responselike@1.0.0': dependencies: - '@types/node': 20.12.12 + '@types/node': 20.14.15 '@types/secp256k1@4.0.3': dependencies: - '@types/node': 20.12.12 + '@types/node': 20.14.15 '@types/semver@7.5.0': {} - '@typescript-eslint/eslint-plugin@7.10.0(@typescript-eslint/parser@7.10.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5)': + '@typescript-eslint/eslint-plugin@7.18.0(@typescript-eslint/parser@7.18.0(eslint@8.57.0)(typescript@5.5.4))(eslint@8.57.0)(typescript@5.5.4)': dependencies: '@eslint-community/regexpp': 4.10.0 - '@typescript-eslint/parser': 7.10.0(eslint@8.57.0)(typescript@5.4.5) - '@typescript-eslint/scope-manager': 7.10.0 - '@typescript-eslint/type-utils': 7.10.0(eslint@8.57.0)(typescript@5.4.5) - '@typescript-eslint/utils': 7.10.0(eslint@8.57.0)(typescript@5.4.5) - '@typescript-eslint/visitor-keys': 7.10.0 + '@typescript-eslint/parser': 7.18.0(eslint@8.57.0)(typescript@5.5.4) + '@typescript-eslint/scope-manager': 7.18.0 + '@typescript-eslint/type-utils': 7.18.0(eslint@8.57.0)(typescript@5.5.4) + '@typescript-eslint/utils': 7.18.0(eslint@8.57.0)(typescript@5.5.4) + '@typescript-eslint/visitor-keys': 7.18.0 eslint: 8.57.0 graphemer: 1.4.0 ignore: 5.3.1 natural-compare: 1.4.0 - ts-api-utils: 1.3.0(typescript@5.4.5) + ts-api-utils: 1.3.0(typescript@5.5.4) optionalDependencies: - typescript: 5.4.5 + typescript: 5.5.4 transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@7.10.0(eslint@8.57.0)(typescript@5.4.5)': + '@typescript-eslint/parser@7.18.0(eslint@8.57.0)(typescript@5.5.4)': dependencies: - '@typescript-eslint/scope-manager': 7.10.0 - '@typescript-eslint/types': 7.10.0 - '@typescript-eslint/typescript-estree': 7.10.0(typescript@5.4.5) - '@typescript-eslint/visitor-keys': 7.10.0 - debug: 4.3.4(supports-color@8.1.1) + '@typescript-eslint/scope-manager': 7.18.0 + '@typescript-eslint/types': 7.18.0 + '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.5.4) + '@typescript-eslint/visitor-keys': 7.18.0 + debug: 4.3.6 eslint: 8.57.0 optionalDependencies: - typescript: 5.4.5 + typescript: 5.5.4 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@7.10.0': + '@typescript-eslint/scope-manager@7.18.0': dependencies: - '@typescript-eslint/types': 7.10.0 - '@typescript-eslint/visitor-keys': 7.10.0 + '@typescript-eslint/types': 7.18.0 + '@typescript-eslint/visitor-keys': 7.18.0 - '@typescript-eslint/type-utils@7.10.0(eslint@8.57.0)(typescript@5.4.5)': + '@typescript-eslint/type-utils@7.18.0(eslint@8.57.0)(typescript@5.5.4)': dependencies: - '@typescript-eslint/typescript-estree': 7.10.0(typescript@5.4.5) - '@typescript-eslint/utils': 7.10.0(eslint@8.57.0)(typescript@5.4.5) - debug: 4.3.4(supports-color@8.1.1) + '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.5.4) + '@typescript-eslint/utils': 7.18.0(eslint@8.57.0)(typescript@5.5.4) + debug: 4.3.6 eslint: 8.57.0 - ts-api-utils: 1.3.0(typescript@5.4.5) + ts-api-utils: 1.3.0(typescript@5.5.4) optionalDependencies: - typescript: 5.4.5 + typescript: 5.5.4 transitivePeerDependencies: - supports-color - '@typescript-eslint/types@7.10.0': {} + '@typescript-eslint/types@7.18.0': {} - '@typescript-eslint/typescript-estree@7.10.0(typescript@5.4.5)': + '@typescript-eslint/typescript-estree@7.18.0(typescript@5.5.4)': dependencies: - '@typescript-eslint/types': 7.10.0 - '@typescript-eslint/visitor-keys': 7.10.0 - debug: 4.3.4(supports-color@8.1.1) + '@typescript-eslint/types': 7.18.0 + '@typescript-eslint/visitor-keys': 7.18.0 + debug: 4.3.6 globby: 11.1.0 is-glob: 4.0.3 minimatch: 9.0.4 - semver: 7.6.2 - ts-api-utils: 1.3.0(typescript@5.4.5) + semver: 7.6.3 + ts-api-utils: 1.3.0(typescript@5.5.4) optionalDependencies: - typescript: 5.4.5 + typescript: 5.5.4 transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@7.10.0(eslint@8.57.0)(typescript@5.4.5)': + '@typescript-eslint/utils@7.18.0(eslint@8.57.0)(typescript@5.5.4)': dependencies: '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) - '@typescript-eslint/scope-manager': 7.10.0 - '@typescript-eslint/types': 7.10.0 - '@typescript-eslint/typescript-estree': 7.10.0(typescript@5.4.5) + '@typescript-eslint/scope-manager': 7.18.0 + '@typescript-eslint/types': 7.18.0 + '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.5.4) eslint: 8.57.0 transitivePeerDependencies: - supports-color - typescript - '@typescript-eslint/visitor-keys@7.10.0': + '@typescript-eslint/visitor-keys@7.18.0': dependencies: - '@typescript-eslint/types': 7.10.0 + '@typescript-eslint/types': 7.18.0 eslint-visitor-keys: 3.4.3 '@ungap/structured-clone@1.2.0': {} @@ -4718,7 +4352,7 @@ snapshots: ajv: 6.12.6 better-ajv-errors: 0.8.2(ajv@6.12.6) neodoc: 2.0.2 - semver: 7.6.2 + semver: 7.6.3 source-map-support: 0.5.21 optionalDependencies: prettier: 2.8.8 @@ -4742,7 +4376,7 @@ snapshots: agent-base@6.0.2: dependencies: - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.6 transitivePeerDependencies: - supports-color @@ -4777,14 +4411,10 @@ snapshots: dependencies: type-fest: 0.21.3 - ansi-escapes@6.2.1: {} - ansi-regex@2.1.1: {} ansi-regex@5.0.1: {} - ansi-regex@6.0.1: {} - ansi-styles@3.2.1: dependencies: color-convert: 1.9.3 @@ -4793,8 +4423,6 @@ snapshots: dependencies: color-convert: 2.0.1 - ansi-styles@6.2.1: {} - antlr4@4.13.1-patch-1: {} anymatch@3.1.2: @@ -4818,6 +4446,7 @@ snapshots: dependencies: call-bind: 1.0.5 is-array-buffer: 3.0.2 + optional: true array-buffer-byte-length@1.0.1: dependencies: @@ -4837,13 +4466,6 @@ snapshots: es-shim-unscopables: 1.0.2 optional: true - array.prototype.flat@1.3.2: - dependencies: - call-bind: 1.0.5 - define-properties: 1.2.1 - es-abstract: 1.22.3 - es-shim-unscopables: 1.0.2 - arraybuffer.prototype.slice@1.0.2: dependencies: array-buffer-byte-length: 1.0.0 @@ -4853,6 +4475,7 @@ snapshots: get-intrinsic: 1.2.2 is-array-buffer: 3.0.2 is-shared-array-buffer: 1.0.2 + optional: true arraybuffer.prototype.slice@1.0.3: dependencies: @@ -4866,8 +4489,6 @@ snapshots: is-shared-array-buffer: 1.0.3 optional: true - arrify@1.0.1: {} - assertion-error@1.1.0: {} ast-parents@0.0.1: {} @@ -4876,7 +4497,8 @@ snapshots: at-least-node@1.0.0: {} - available-typed-arrays@1.0.5: {} + available-typed-arrays@1.0.5: + optional: true available-typed-arrays@1.0.7: dependencies: @@ -4944,10 +4566,6 @@ snapshots: dependencies: fill-range: 7.0.1 - breakword@1.0.6: - dependencies: - wcwidth: 1.0.1 - brorand@1.1.0: {} browser-stdout@1.3.1: {} @@ -4986,7 +4604,7 @@ snapshots: clone-response: 1.0.2 get-stream: 5.1.0 http-cache-semantics: 4.0.3 - keyv: 4.5.0 + keyv: 4.5.4 lowercase-keys: 2.0.0 normalize-url: 6.1.0 responselike: 2.0.1 @@ -4996,6 +4614,7 @@ snapshots: function-bind: 1.1.2 get-intrinsic: 1.2.2 set-function-length: 1.1.1 + optional: true call-bind@1.0.7: dependencies: @@ -5013,14 +4632,6 @@ snapshots: no-case: 2.3.2 upper-case: 1.1.3 - camelcase-keys@6.2.2: - dependencies: - camelcase: 5.3.1 - map-obj: 4.3.0 - quick-lru: 4.0.1 - - camelcase@5.3.1: {} - camelcase@6.3.0: {} cbor@5.2.0: @@ -5037,12 +4648,12 @@ snapshots: nofilter: 3.1.0 optional: true - chai-as-promised@7.1.1(chai@4.4.1): + chai-as-promised@7.1.1(chai@4.5.0): dependencies: - chai: 4.4.1 + chai: 4.5.0 check-error: 1.0.3 - chai@4.4.1: + chai@4.5.0: dependencies: assertion-error: 1.1.0 check-error: 1.0.3 @@ -5050,7 +4661,7 @@ snapshots: get-func-name: 2.0.2 loupe: 2.3.7 pathval: 1.1.1 - type-detect: 4.0.8 + type-detect: 4.1.0 chalk@2.4.2: dependencies: @@ -5063,8 +4674,6 @@ snapshots: ansi-styles: 4.3.0 supports-color: 7.2.0 - chalk@5.3.0: {} - change-case@3.0.2: dependencies: camel-case: 3.0.0 @@ -5117,39 +4726,16 @@ snapshots: cli-boxes@2.2.1: {} - cli-cursor@4.0.0: - dependencies: - restore-cursor: 4.0.0 - - cli-truncate@4.0.0: - dependencies: - slice-ansi: 5.0.0 - string-width: 7.1.0 - - cliui@6.0.0: - dependencies: - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 6.2.0 - cliui@7.0.4: dependencies: string-width: 4.2.3 strip-ansi: 6.0.1 wrap-ansi: 7.0.0 - cliui@8.0.1: - dependencies: - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 7.0.0 - clone-response@1.0.2: dependencies: mimic-response: 1.0.1 - clone@1.0.4: {} - code-error-fragment@0.0.230: {} color-convert@1.9.3: @@ -5164,8 +4750,6 @@ snapshots: color-name@1.1.4: {} - colorette@2.0.20: {} - command-exists@1.2.9: {} command-line-args@5.2.1: @@ -5184,11 +4768,9 @@ snapshots: commander@10.0.1: {} - commander@11.1.0: {} - commander@3.0.2: {} - compare-versions@6.1.0: + compare-versions@6.1.1: optional: true concat-map@0.0.1: {} @@ -5253,19 +4835,6 @@ snapshots: shebang-command: 2.0.0 which: 2.0.2 - csv-generate@3.4.3: {} - - csv-parse@4.16.3: {} - - csv-stringify@5.6.5: {} - - csv@5.5.3: - dependencies: - csv-generate: 3.4.3 - csv-parse: 4.16.3 - csv-stringify: 5.6.5 - stream-transform: 2.1.3 - data-view-buffer@1.0.1: dependencies: call-bind: 1.0.7 @@ -5295,12 +4864,9 @@ snapshots: optionalDependencies: supports-color: 8.1.1 - decamelize-keys@1.1.1: + debug@4.3.6: dependencies: - decamelize: 1.2.0 - map-obj: 1.0.1 - - decamelize@1.2.0: {} + ms: 2.1.2 decamelize@4.0.0: {} @@ -5321,10 +4887,6 @@ snapshots: deep-is@0.1.4: {} - defaults@1.0.4: - dependencies: - clone: 1.0.4 - defer-to-connect@2.0.1: {} define-data-property@1.1.1: @@ -5332,6 +4894,7 @@ snapshots: get-intrinsic: 1.2.2 gopd: 1.0.1 has-property-descriptors: 1.0.0 + optional: true define-data-property@1.1.4: dependencies: @@ -5345,6 +4908,7 @@ snapshots: define-data-property: 1.1.1 has-property-descriptors: 1.0.0 object-keys: 1.1.1 + optional: true delete-empty@3.0.0: dependencies: @@ -5385,8 +4949,6 @@ snapshots: minimalistic-assert: 1.0.1 minimalistic-crypto-utils: 1.0.1 - emoji-regex@10.3.0: {} - emoji-regex@8.0.0: {} end-of-stream@1.4.4: @@ -5444,6 +5006,7 @@ snapshots: typed-array-length: 1.0.4 unbox-primitive: 1.0.2 which-typed-array: 1.1.13 + optional: true es-abstract@1.23.3: dependencies: @@ -5513,6 +5076,7 @@ snapshots: get-intrinsic: 1.2.2 has-tostringtag: 1.0.0 hasown: 2.0.0 + optional: true es-set-tostringtag@2.0.3: dependencies: @@ -5524,12 +5088,14 @@ snapshots: es-shim-unscopables@1.0.2: dependencies: hasown: 2.0.0 + optional: true es-to-primitive@1.2.1: dependencies: is-callable: 1.2.7 is-date-object: 1.0.2 is-symbol: 1.0.3 + optional: true escalade@3.1.1: {} @@ -5541,12 +5107,12 @@ snapshots: dependencies: eslint: 8.57.0 - eslint-plugin-prettier@5.1.3(eslint-config-prettier@9.1.0(eslint@8.57.0))(eslint@8.57.0)(prettier@3.2.5): + eslint-plugin-prettier@5.2.1(eslint-config-prettier@9.1.0(eslint@8.57.0))(eslint@8.57.0)(prettier@3.3.3): dependencies: eslint: 8.57.0 - prettier: 3.2.5 + prettier: 3.3.3 prettier-linter-helpers: 1.0.0 - synckit: 0.8.8 + synckit: 0.9.1 optionalDependencies: eslint-config-prettier: 9.1.0(eslint@8.57.0) @@ -5570,7 +5136,7 @@ snapshots: ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.3 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.6 doctrine: 3.0.0 escape-string-regexp: 4.0.0 eslint-scope: 7.2.2 @@ -5718,25 +5284,11 @@ snapshots: is-hex-prefixed: 1.0.0 strip-hex-prefix: 1.0.0 - eventemitter3@5.0.1: {} - evp_bytestokey@1.0.3: dependencies: md5.js: 1.3.5 safe-buffer: 5.2.1 - execa@8.0.1: - dependencies: - cross-spawn: 7.0.3 - get-stream: 8.0.1 - human-signals: 5.0.0 - is-stream: 3.0.0 - merge-stream: 2.0.0 - npm-run-path: 5.3.0 - onetime: 6.0.0 - signal-exit: 4.1.0 - strip-final-newline: 3.0.0 - extendable-error@0.1.7: {} external-editor@3.1.0: @@ -5814,13 +5366,14 @@ snapshots: flatted@3.3.1: {} - follow-redirects@1.15.6(debug@4.3.4): + follow-redirects@1.15.6(debug@4.3.6): optionalDependencies: - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.6 for-each@0.3.3: dependencies: is-callable: 1.2.7 + optional: true form-data-encoder@1.7.1: {} @@ -5858,7 +5411,8 @@ snapshots: fsevents@2.3.2: optional: true - function-bind@1.1.2: {} + function-bind@1.1.2: + optional: true function.prototype.name@1.1.6: dependencies: @@ -5866,13 +5420,13 @@ snapshots: define-properties: 1.2.1 es-abstract: 1.22.3 functions-have-names: 1.2.3 + optional: true - functions-have-names@1.2.3: {} + functions-have-names@1.2.3: + optional: true get-caller-file@2.0.5: {} - get-east-asian-width@1.2.0: {} - get-func-name@2.0.2: {} get-intrinsic@1.2.2: @@ -5881,6 +5435,7 @@ snapshots: has-proto: 1.0.1 has-symbols: 1.0.3 hasown: 2.0.0 + optional: true get-intrinsic@1.2.4: dependencies: @@ -5897,12 +5452,11 @@ snapshots: get-stream@6.0.1: {} - get-stream@8.0.1: {} - get-symbol-description@1.0.0: dependencies: call-bind: 1.0.5 get-intrinsic: 1.2.2 + optional: true get-symbol-description@1.0.2: dependencies: @@ -5961,6 +5515,7 @@ snapshots: globalthis@1.0.3: dependencies: define-properties: 1.2.1 + optional: true globby@11.1.0: dependencies: @@ -5974,6 +5529,7 @@ snapshots: gopd@1.0.1: dependencies: get-intrinsic: 1.2.2 + optional: true got@12.1.0: dependencies: @@ -5997,13 +5553,11 @@ snapshots: graphemer@1.4.0: {} - hard-rejection@2.1.0: {} - - hardhat-abi-exporter@2.10.1(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5)): + hardhat-abi-exporter@2.10.1(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.14.15)(typescript@5.5.4))(typescript@5.5.4)): dependencies: '@ethersproject/abi': 5.7.0 delete-empty: 3.0.0 - hardhat: 2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5) + hardhat: 2.20.1(ts-node@10.9.2(@types/node@20.14.15)(typescript@5.5.4))(typescript@5.5.4) hardhat-ignore-warnings@0.2.11: dependencies: @@ -6011,7 +5565,7 @@ snapshots: node-interval-tree: 2.1.2 solidity-comments: 0.0.2 - hardhat@2.20.1(ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5))(typescript@5.4.5): + hardhat@2.20.1(ts-node@10.9.2(@types/node@20.14.15)(typescript@5.5.4))(typescript@5.5.4): dependencies: '@ethersproject/abi': 5.7.0 '@metamask/eth-sig-util': 4.0.1 @@ -6037,7 +5591,7 @@ snapshots: chalk: 2.4.2 chokidar: 3.5.3 ci-info: 2.0.0 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.6 enquirer: 2.3.6 env-paths: 2.2.1 ethereum-cryptography: 1.1.2 @@ -6056,7 +5610,7 @@ snapshots: raw-body: 2.5.1 resolve: 1.17.0 semver: 6.3.0 - solc: 0.7.3(debug@4.3.4) + solc: 0.7.3(debug@4.3.6) source-map-support: 0.5.21 stacktrace-parser: 0.1.10 tsort: 0.0.1 @@ -6064,15 +5618,16 @@ snapshots: uuid: 8.3.2 ws: 7.5.9 optionalDependencies: - ts-node: 10.9.2(@types/node@20.12.12)(typescript@5.4.5) - typescript: 5.4.5 + ts-node: 10.9.2(@types/node@20.14.15)(typescript@5.5.4) + typescript: 5.5.4 transitivePeerDependencies: - bufferutil - c-kzg - supports-color - utf-8-validate - has-bigints@1.0.2: {} + has-bigints@1.0.2: + optional: true has-flag@3.0.0: {} @@ -6081,32 +5636,32 @@ snapshots: has-property-descriptors@1.0.0: dependencies: get-intrinsic: 1.2.2 + optional: true has-property-descriptors@1.0.2: dependencies: es-define-property: 1.0.0 optional: true - has-proto@1.0.1: {} + has-proto@1.0.1: + optional: true has-proto@1.0.3: optional: true - has-symbols@1.0.3: {} + has-symbols@1.0.3: + optional: true has-tostringtag@1.0.0: dependencies: has-symbols: 1.0.3 + optional: true has-tostringtag@1.0.2: dependencies: has-symbols: 1.0.3 optional: true - has@1.0.3: - dependencies: - function-bind: 1.1.2 - hash-base@3.1.0: dependencies: inherits: 2.0.4 @@ -6121,6 +5676,7 @@ snapshots: hasown@2.0.0: dependencies: function-bind: 1.1.2 + optional: true hasown@2.0.2: dependencies: @@ -6140,8 +5696,6 @@ snapshots: minimalistic-assert: 1.0.1 minimalistic-crypto-utils: 1.0.1 - hosted-git-info@2.8.9: {} - http-cache-semantics@4.0.3: {} http-errors@2.0.0: @@ -6160,16 +5714,12 @@ snapshots: https-proxy-agent@5.0.1: dependencies: agent-base: 6.0.2 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.6 transitivePeerDependencies: - supports-color human-id@1.0.2: {} - human-signals@5.0.0: {} - - husky@9.0.11: {} - iconv-lite@0.4.24: dependencies: safer-buffer: 2.1.2 @@ -6203,6 +5753,7 @@ snapshots: get-intrinsic: 1.2.2 hasown: 2.0.0 side-channel: 1.0.4 + optional: true internal-slot@1.0.7: dependencies: @@ -6220,6 +5771,7 @@ snapshots: call-bind: 1.0.5 get-intrinsic: 1.2.2 is-typed-array: 1.1.12 + optional: true is-array-buffer@3.0.4: dependencies: @@ -6232,6 +5784,7 @@ snapshots: is-bigint@1.0.4: dependencies: has-bigints: 1.0.2 + optional: true is-binary-path@2.1.0: dependencies: @@ -6241,23 +5794,22 @@ snapshots: dependencies: call-bind: 1.0.5 has-tostringtag: 1.0.0 + optional: true - is-callable@1.2.7: {} + is-callable@1.2.7: + optional: true is-ci@2.0.0: dependencies: ci-info: 2.0.0 - is-core-module@2.10.0: - dependencies: - has: 1.0.3 - is-data-view@1.0.1: dependencies: is-typed-array: 1.1.13 optional: true - is-date-object@1.0.2: {} + is-date-object@1.0.2: + optional: true is-docker@2.2.1: {} @@ -6265,12 +5817,6 @@ snapshots: is-fullwidth-code-point@3.0.0: {} - is-fullwidth-code-point@4.0.0: {} - - is-fullwidth-code-point@5.0.0: - dependencies: - get-east-asian-width: 1.2.0 - is-glob@4.0.3: dependencies: is-extglob: 2.1.1 @@ -6281,7 +5827,8 @@ snapshots: dependencies: lower-case: 1.1.4 - is-negative-zero@2.0.2: {} + is-negative-zero@2.0.2: + optional: true is-negative-zero@2.0.3: optional: true @@ -6289,34 +5836,34 @@ snapshots: is-number-object@1.0.7: dependencies: has-tostringtag: 1.0.0 + optional: true is-number@7.0.0: {} is-path-inside@3.0.3: {} - is-plain-obj@1.1.0: {} - is-plain-obj@2.1.0: {} is-regex@1.1.4: dependencies: call-bind: 1.0.5 has-tostringtag: 1.0.0 + optional: true is-shared-array-buffer@1.0.2: dependencies: call-bind: 1.0.5 + optional: true is-shared-array-buffer@1.0.3: dependencies: call-bind: 1.0.7 optional: true - is-stream@3.0.0: {} - is-string@1.0.7: dependencies: has-tostringtag: 1.0.0 + optional: true is-subdir@1.2.0: dependencies: @@ -6325,10 +5872,12 @@ snapshots: is-symbol@1.0.3: dependencies: has-symbols: 1.0.3 + optional: true is-typed-array@1.1.12: dependencies: which-typed-array: 1.1.13 + optional: true is-typed-array@1.1.13: dependencies: @@ -6344,6 +5893,7 @@ snapshots: is-weakref@1.0.2: dependencies: call-bind: 1.0.5 + optional: true is-windows@1.0.2: {} @@ -6351,7 +5901,8 @@ snapshots: dependencies: is-docker: 2.2.1 - isarray@2.0.5: {} + isarray@2.0.5: + optional: true isexe@2.0.0: {} @@ -6407,16 +5958,10 @@ snapshots: node-gyp-build: 4.5.0 readable-stream: 3.6.0 - keyv@4.5.0: - dependencies: - json-buffer: 3.0.1 - keyv@4.5.4: dependencies: json-buffer: 3.0.1 - kind-of@6.0.3: {} - klaw-sync@6.0.0: dependencies: graceful-fs: 4.2.10 @@ -6425,8 +5970,6 @@ snapshots: optionalDependencies: graceful-fs: 4.2.10 - kleur@4.1.5: {} - latest-version@7.0.0: dependencies: package-json: 8.1.1 @@ -6438,34 +5981,8 @@ snapshots: prelude-ls: 1.2.1 type-check: 0.4.0 - lilconfig@3.0.0: {} - lines-and-columns@1.2.4: {} - lint-staged@15.2.2: - dependencies: - chalk: 5.3.0 - commander: 11.1.0 - debug: 4.3.4(supports-color@8.1.1) - execa: 8.0.1 - lilconfig: 3.0.0 - listr2: 8.0.1 - micromatch: 4.0.5 - pidtree: 0.6.0 - string-argv: 0.3.2 - yaml: 2.3.4 - transitivePeerDependencies: - - supports-color - - listr2@8.0.1: - dependencies: - cli-truncate: 4.0.0 - colorette: 2.0.20 - eventemitter3: 5.0.1 - log-update: 6.0.0 - rfdc: 1.3.1 - wrap-ansi: 9.0.0 - load-yaml-file@0.2.0: dependencies: graceful-fs: 4.2.10 @@ -6507,14 +6024,6 @@ snapshots: chalk: 4.1.2 is-unicode-supported: 0.1.0 - log-update@6.0.0: - dependencies: - ansi-escapes: 6.2.1 - cli-cursor: 4.0.0 - slice-ansi: 7.1.0 - strip-ansi: 7.1.0 - wrap-ansi: 9.0.0 - loupe@2.3.7: dependencies: get-func-name: 2.0.2 @@ -6540,10 +6049,6 @@ snapshots: make-error@1.3.6: {} - map-obj@1.0.1: {} - - map-obj@4.3.0: {} - md5.js@1.3.5: dependencies: hash-base: 3.1.0 @@ -6552,22 +6057,6 @@ snapshots: memorystream@0.3.1: {} - meow@6.1.1: - dependencies: - '@types/minimist': 1.2.5 - camelcase-keys: 6.2.2 - decamelize-keys: 1.1.1 - hard-rejection: 2.1.0 - minimist-options: 4.1.0 - normalize-package-data: 2.5.0 - read-pkg-up: 7.0.1 - redent: 3.0.0 - trim-newlines: 3.0.1 - type-fest: 0.13.1 - yargs-parser: 18.1.3 - - merge-stream@2.0.0: {} - merge2@1.4.1: {} micromatch@4.0.5: @@ -6575,16 +6064,10 @@ snapshots: braces: 3.0.2 picomatch: 2.3.1 - mimic-fn@2.1.0: {} - - mimic-fn@4.0.0: {} - mimic-response@1.0.1: {} mimic-response@3.1.0: {} - min-indent@1.0.1: {} - minimalistic-assert@1.0.1: {} minimalistic-crypto-utils@1.0.1: {} @@ -6605,16 +6088,8 @@ snapshots: dependencies: brace-expansion: 2.0.1 - minimist-options@4.1.0: - dependencies: - arrify: 1.0.1 - is-plain-obj: 1.1.0 - kind-of: 6.0.3 - minimist@1.2.8: {} - mixme@0.5.10: {} - mkdirp@1.0.4: {} mnemonist@0.38.5: @@ -6647,6 +6122,8 @@ snapshots: moment@2.30.1: {} + mri@1.2.0: {} + ms@2.1.2: {} ms@2.1.3: {} @@ -6681,29 +6158,20 @@ snapshots: nofilter@3.1.0: {} - normalize-package-data@2.5.0: - dependencies: - hosted-git-info: 2.8.9 - resolve: 1.22.1 - semver: 5.7.1 - validate-npm-package-license: 3.0.4 - normalize-path@3.0.0: {} normalize-url@6.1.0: {} - npm-run-path@5.3.0: - dependencies: - path-key: 4.0.0 - number-to-bn@1.7.0: dependencies: bn.js: 4.11.6 strip-hex-prefix: 1.0.0 - object-inspect@1.13.1: {} + object-inspect@1.13.1: + optional: true - object-keys@1.1.1: {} + object-keys@1.1.1: + optional: true object.assign@4.1.4: dependencies: @@ -6711,6 +6179,7 @@ snapshots: define-properties: 1.2.1 has-symbols: 1.0.3 object-keys: 1.1.1 + optional: true object.assign@4.1.5: dependencies: @@ -6726,14 +6195,6 @@ snapshots: dependencies: wrappy: 1.0.2 - onetime@5.1.2: - dependencies: - mimic-fn: 2.1.0 - - onetime@6.0.0: - dependencies: - mimic-fn: 4.0.0 - open@7.4.2: dependencies: is-docker: 2.2.1 @@ -6799,7 +6260,7 @@ snapshots: got: 12.1.0 registry-auth-token: 5.0.2 registry-url: 6.0.1 - semver: 7.6.2 + semver: 7.6.3 param-case@2.1.1: dependencies: @@ -6852,8 +6313,6 @@ snapshots: path-key@3.1.1: {} - path-key@4.0.0: {} - path-parse@1.0.7: {} path-starts-with@2.0.1: {} @@ -6872,8 +6331,6 @@ snapshots: picomatch@2.3.1: {} - pidtree@0.6.0: {} - pify@4.0.1: {} pkg-dir@4.2.0: @@ -6902,20 +6359,20 @@ snapshots: dependencies: '@solidity-parser/parser': 0.17.0 prettier: 2.8.8 - semver: 7.6.2 + semver: 7.6.3 solidity-comments-extractor: 0.0.8 optional: true - prettier-plugin-solidity@1.3.1(prettier@3.2.5): + prettier-plugin-solidity@1.3.1(prettier@3.3.3): dependencies: '@solidity-parser/parser': 0.17.0 - prettier: 3.2.5 - semver: 7.6.2 + prettier: 3.3.3 + semver: 7.6.3 solidity-comments-extractor: 0.0.8 prettier@2.8.8: {} - prettier@3.2.5: {} + prettier@3.3.3: {} proper-lockfile@4.1.2: dependencies: @@ -6937,8 +6394,6 @@ snapshots: pure-rand@5.0.3: {} - quick-lru@4.0.1: {} - quick-lru@5.1.1: {} randombytes@2.1.0: @@ -6959,19 +6414,6 @@ snapshots: minimist: 1.2.8 strip-json-comments: 2.0.1 - read-pkg-up@7.0.1: - dependencies: - find-up: 4.1.0 - read-pkg: 5.2.0 - type-fest: 0.8.1 - - read-pkg@5.2.0: - dependencies: - '@types/normalize-package-data': 2.4.4 - normalize-package-data: 2.5.0 - parse-json: 5.2.0 - type-fest: 0.6.0 - read-yaml-file@1.1.0: dependencies: graceful-fs: 4.2.10 @@ -6989,11 +6431,6 @@ snapshots: dependencies: picomatch: 2.3.1 - redent@3.0.0: - dependencies: - indent-string: 4.0.0 - strip-indent: 3.0.0 - reduce-flatten@2.0.0: {} regenerator-runtime@0.14.1: {} @@ -7003,6 +6440,7 @@ snapshots: call-bind: 1.0.5 define-properties: 1.2.1 set-function-name: 2.0.1 + optional: true regexp.prototype.flags@1.5.2: dependencies: @@ -7024,8 +6462,6 @@ snapshots: require-from-string@2.0.2: {} - require-main-filename@2.0.0: {} - resolve-alpn@1.2.1: {} resolve-from@4.0.0: {} @@ -7036,28 +6472,15 @@ snapshots: dependencies: path-parse: 1.0.7 - resolve@1.22.1: - dependencies: - is-core-module: 2.10.0 - path-parse: 1.0.7 - supports-preserve-symlinks-flag: 1.0.0 - responselike@2.0.1: dependencies: lowercase-keys: 2.0.0 - restore-cursor@4.0.0: - dependencies: - onetime: 5.1.2 - signal-exit: 3.0.7 - retry@0.12.0: optional: true reusify@1.0.4: {} - rfdc@1.3.1: {} - rimraf@2.7.1: dependencies: glob: 7.2.3 @@ -7089,6 +6512,7 @@ snapshots: get-intrinsic: 1.2.2 has-symbols: 1.0.3 isarray: 2.0.5 + optional: true safe-array-concat@1.1.2: dependencies: @@ -7107,6 +6531,7 @@ snapshots: call-bind: 1.0.5 get-intrinsic: 1.2.2 is-regex: 1.1.4 + optional: true safe-regex-test@1.0.3: dependencies: @@ -7129,7 +6554,7 @@ snapshots: semver@6.3.0: {} - semver@7.6.2: {} + semver@7.6.3: {} sentence-case@2.1.1: dependencies: @@ -7140,14 +6565,13 @@ snapshots: dependencies: randombytes: 2.1.0 - set-blocking@2.0.0: {} - set-function-length@1.1.1: dependencies: define-data-property: 1.1.1 get-intrinsic: 1.2.2 gopd: 1.0.1 has-property-descriptors: 1.0.0 + optional: true set-function-length@1.2.2: dependencies: @@ -7164,6 +6588,7 @@ snapshots: define-data-property: 1.1.1 functions-have-names: 1.2.3 has-property-descriptors: 1.0.0 + optional: true setimmediate@1.0.5: {} @@ -7193,11 +6618,10 @@ snapshots: call-bind: 1.0.5 get-intrinsic: 1.2.2 object-inspect: 1.13.1 + optional: true signal-exit@3.0.7: {} - signal-exit@4.1.0: {} - slash@2.0.0: {} slash@3.0.0: {} @@ -7208,34 +6632,15 @@ snapshots: astral-regex: 2.0.0 is-fullwidth-code-point: 3.0.0 - slice-ansi@5.0.0: - dependencies: - ansi-styles: 6.2.1 - is-fullwidth-code-point: 4.0.0 - - slice-ansi@7.1.0: - dependencies: - ansi-styles: 6.2.1 - is-fullwidth-code-point: 5.0.0 - - smartwrap@2.0.2: - dependencies: - array.prototype.flat: 1.3.2 - breakword: 1.0.6 - grapheme-splitter: 1.0.4 - strip-ansi: 6.0.1 - wcwidth: 1.0.1 - yargs: 15.4.1 - snake-case@2.1.0: dependencies: no-case: 2.3.2 - solc@0.7.3(debug@4.3.4): + solc@0.7.3(debug@4.3.6): dependencies: command-exists: 1.2.9 commander: 3.0.2 - follow-redirects: 1.15.6(debug@4.3.4) + follow-redirects: 1.15.6(debug@4.3.6) fs-extra: 0.30.0 js-sha3: 0.8.0 memorystream: 0.3.1 @@ -7245,14 +6650,14 @@ snapshots: transitivePeerDependencies: - debug - solhint-plugin-prettier@0.1.0(prettier-plugin-solidity@1.3.1(prettier@3.2.5))(prettier@3.2.5): + solhint-plugin-prettier@0.1.0(prettier-plugin-solidity@1.3.1(prettier@3.3.3))(prettier@3.3.3): dependencies: - '@prettier/sync': 0.3.0(prettier@3.2.5) - prettier: 3.2.5 + '@prettier/sync': 0.3.0(prettier@3.3.3) + prettier: 3.3.3 prettier-linter-helpers: 1.0.0 - prettier-plugin-solidity: 1.3.1(prettier@3.2.5) + prettier-plugin-solidity: 1.3.1(prettier@3.3.3) - solhint@5.0.1: + solhint@5.0.3: dependencies: '@solidity-parser/parser': 0.18.0 ajv: 6.12.6 @@ -7263,12 +6668,12 @@ snapshots: cosmiconfig: 8.2.0 fast-diff: 1.2.0 glob: 8.1.0 - ignore: 5.2.4 + ignore: 5.3.1 js-yaml: 4.1.0 latest-version: 7.0.0 lodash: 4.17.21 pluralize: 8.0.0 - semver: 7.6.2 + semver: 7.6.3 strip-ansi: 6.0.1 table: 6.8.1 text-table: 0.2.0 @@ -7341,20 +6746,6 @@ snapshots: cross-spawn: 5.1.0 signal-exit: 3.0.7 - spdx-correct@3.1.1: - dependencies: - spdx-expression-parse: 3.0.1 - spdx-license-ids: 3.0.12 - - spdx-exceptions@2.3.0: {} - - spdx-expression-parse@3.0.1: - dependencies: - spdx-exceptions: 2.3.0 - spdx-license-ids: 3.0.12 - - spdx-license-ids@3.0.12: {} - sprintf-js@1.0.3: {} stacktrace-parser@0.1.10: @@ -7363,12 +6754,6 @@ snapshots: statuses@2.0.1: {} - stream-transform@2.1.3: - dependencies: - mixme: 0.5.10 - - string-argv@0.3.2: {} - string-format@2.0.0: {} string-width@4.2.3: @@ -7377,17 +6762,12 @@ snapshots: is-fullwidth-code-point: 3.0.0 strip-ansi: 6.0.1 - string-width@7.1.0: - dependencies: - emoji-regex: 10.3.0 - get-east-asian-width: 1.2.0 - strip-ansi: 7.1.0 - string.prototype.trim@1.2.8: dependencies: call-bind: 1.0.5 define-properties: 1.2.1 es-abstract: 1.22.3 + optional: true string.prototype.trim@1.2.9: dependencies: @@ -7402,6 +6782,7 @@ snapshots: call-bind: 1.0.5 define-properties: 1.2.1 es-abstract: 1.22.3 + optional: true string.prototype.trimend@1.0.8: dependencies: @@ -7415,6 +6796,7 @@ snapshots: call-bind: 1.0.5 define-properties: 1.2.1 es-abstract: 1.22.3 + optional: true string.prototype.trimstart@1.0.8: dependencies: @@ -7431,22 +6813,12 @@ snapshots: dependencies: ansi-regex: 5.0.1 - strip-ansi@7.1.0: - dependencies: - ansi-regex: 6.0.1 - strip-bom@3.0.0: {} - strip-final-newline@3.0.0: {} - strip-hex-prefix@1.0.0: dependencies: is-hex-prefixed: 1.0.0 - strip-indent@3.0.0: - dependencies: - min-indent: 1.0.1 - strip-json-comments@2.0.1: {} strip-json-comments@3.1.1: {} @@ -7463,14 +6835,12 @@ snapshots: dependencies: has-flag: 4.0.0 - supports-preserve-symlinks-flag@1.0.0: {} - swap-case@1.1.2: dependencies: lower-case: 1.1.4 upper-case: 1.1.3 - synckit@0.8.8: + synckit@0.9.1: dependencies: '@pkgr/core': 0.1.1 tslib: 2.6.2 @@ -7511,11 +6881,9 @@ snapshots: tr46@0.0.3: {} - trim-newlines@3.0.1: {} - - ts-api-utils@1.3.0(typescript@5.4.5): + ts-api-utils@1.3.0(typescript@5.5.4): dependencies: - typescript: 5.4.5 + typescript: 5.5.4 ts-command-line-args@2.5.1: dependencies: @@ -7524,25 +6892,25 @@ snapshots: command-line-usage: 6.1.3 string-format: 2.0.0 - ts-essentials@7.0.3(typescript@5.4.5): + ts-essentials@7.0.3(typescript@5.5.4): dependencies: - typescript: 5.4.5 + typescript: 5.5.4 - ts-node@10.9.2(@types/node@20.12.12)(typescript@5.4.5): + ts-node@10.9.2(@types/node@20.14.15)(typescript@5.5.4): dependencies: '@cspotcode/source-map-support': 0.8.1 '@tsconfig/node10': 1.0.9 '@tsconfig/node12': 1.0.11 '@tsconfig/node14': 1.0.3 '@tsconfig/node16': 1.0.3 - '@types/node': 20.12.12 + '@types/node': 20.14.15 acorn: 8.10.0 acorn-walk: 8.2.0 arg: 4.1.3 create-require: 1.1.1 diff: 4.0.2 make-error: 1.3.6 - typescript: 5.4.5 + typescript: 5.5.4 v8-compile-cache-lib: 3.0.1 yn: 3.1.1 @@ -7552,16 +6920,6 @@ snapshots: tsort@0.0.1: {} - tty-table@4.2.3: - dependencies: - chalk: 4.1.2 - csv: 5.5.3 - kleur: 4.1.5 - smartwrap: 2.0.2 - strip-ansi: 6.0.1 - wcwidth: 1.0.1 - yargs: 17.7.2 - tweetnacl-util@0.15.1: {} tweetnacl@1.0.3: {} @@ -7572,22 +6930,18 @@ snapshots: type-detect@4.0.8: {} - type-fest@0.13.1: {} + type-detect@4.1.0: {} type-fest@0.20.2: {} type-fest@0.21.3: {} - type-fest@0.6.0: {} - type-fest@0.7.1: {} - type-fest@0.8.1: {} - - typechain@8.3.2(typescript@5.4.5): + typechain@8.3.2(typescript@5.5.4): dependencies: '@types/prettier': 2.7.1 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.6 fs-extra: 7.0.1 glob: 7.1.7 js-sha3: 0.8.0 @@ -7595,8 +6949,8 @@ snapshots: mkdirp: 1.0.4 prettier: 2.8.8 ts-command-line-args: 2.5.1 - ts-essentials: 7.0.3(typescript@5.4.5) - typescript: 5.4.5 + ts-essentials: 7.0.3(typescript@5.5.4) + typescript: 5.5.4 transitivePeerDependencies: - supports-color @@ -7605,6 +6959,7 @@ snapshots: call-bind: 1.0.5 get-intrinsic: 1.2.2 is-typed-array: 1.1.12 + optional: true typed-array-buffer@1.0.2: dependencies: @@ -7619,6 +6974,7 @@ snapshots: for-each: 0.3.3 has-proto: 1.0.1 is-typed-array: 1.1.12 + optional: true typed-array-byte-length@1.0.1: dependencies: @@ -7636,6 +6992,7 @@ snapshots: for-each: 0.3.3 has-proto: 1.0.1 is-typed-array: 1.1.12 + optional: true typed-array-byte-offset@1.0.2: dependencies: @@ -7652,6 +7009,7 @@ snapshots: call-bind: 1.0.5 for-each: 0.3.3 is-typed-array: 1.1.12 + optional: true typed-array-length@1.0.6: dependencies: @@ -7663,7 +7021,7 @@ snapshots: possible-typed-array-names: 1.0.0 optional: true - typescript@5.4.5: {} + typescript@5.5.4: {} typical@4.0.0: {} @@ -7675,6 +7033,7 @@ snapshots: has-bigints: 1.0.2 has-symbols: 1.0.3 which-boxed-primitive: 1.0.2 + optional: true undici-types@5.26.5: {} @@ -7706,15 +7065,6 @@ snapshots: v8-compile-cache-lib@3.0.1: {} - validate-npm-package-license@3.0.4: - dependencies: - spdx-correct: 3.1.1 - spdx-expression-parse: 3.0.1 - - wcwidth@1.0.1: - dependencies: - defaults: 1.0.4 - web3-utils@1.7.4: dependencies: bn.js: 5.2.1 @@ -7739,8 +7089,7 @@ snapshots: is-number-object: 1.0.7 is-string: 1.0.7 is-symbol: 1.0.3 - - which-module@2.0.0: {} + optional: true which-pm@2.0.0: dependencies: @@ -7754,6 +7103,7 @@ snapshots: for-each: 0.3.3 gopd: 1.0.1 has-tostringtag: 1.0.0 + optional: true which-typed-array@1.1.15: dependencies: @@ -7783,49 +7133,26 @@ snapshots: workerpool@6.2.1: {} - wrap-ansi@6.2.0: - dependencies: - ansi-styles: 4.3.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi@7.0.0: dependencies: ansi-styles: 4.3.0 string-width: 4.2.3 strip-ansi: 6.0.1 - wrap-ansi@9.0.0: - dependencies: - ansi-styles: 6.2.1 - string-width: 7.1.0 - strip-ansi: 7.1.0 - wrappy@1.0.2: {} ws@7.4.6: {} ws@7.5.9: {} - y18n@4.0.3: {} - y18n@5.0.8: {} yallist@2.1.2: {} yaml@1.10.2: {} - yaml@2.3.4: {} - - yargs-parser@18.1.3: - dependencies: - camelcase: 5.3.1 - decamelize: 1.2.0 - yargs-parser@20.2.4: {} - yargs-parser@21.1.1: {} - yargs-unparser@2.0.0: dependencies: camelcase: 6.3.0 @@ -7833,20 +7160,6 @@ snapshots: flat: 5.0.2 is-plain-obj: 2.1.0 - yargs@15.4.1: - dependencies: - cliui: 6.0.0 - decamelize: 1.2.0 - find-up: 4.1.0 - get-caller-file: 2.0.5 - require-directory: 2.1.1 - require-main-filename: 2.0.0 - set-blocking: 2.0.0 - string-width: 4.2.3 - which-module: 2.0.0 - y18n: 4.0.3 - yargs-parser: 18.1.3 - yargs@16.2.0: dependencies: cliui: 7.0.4 @@ -7857,16 +7170,6 @@ snapshots: y18n: 5.0.8 yargs-parser: 20.2.4 - yargs@17.7.2: - dependencies: - cliui: 8.0.1 - escalade: 3.1.1 - get-caller-file: 2.0.5 - require-directory: 2.1.1 - string-width: 4.2.3 - y18n: 5.0.8 - yargs-parser: 21.1.1 - yn@3.1.1: {} yocto-queue@0.1.0: {} diff --git a/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumSequencerUptimeFeed.t.sol b/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumSequencerUptimeFeed.t.sol index 3b9df3bf91..5565409709 100644 --- a/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumSequencerUptimeFeed.t.sol +++ b/contracts/src/v0.8/l2ep/test/v1_0_0/arbitrum/ArbitrumSequencerUptimeFeed.t.sol @@ -246,199 +246,3 @@ contract ArbitrumSequencerUptimeFeed_ProtectReadsOnAggregatorV2V3InterfaceFuncti assertEq(answer, 0); } } - -contract ArbitrumSequencerUptimeFeed_GasCosts is ArbitrumSequencerUptimeFeedTest { - /// @notice it should consume a known amount of gas for updates - function test_GasCosts() public { - // Sets msg.sender and tx.origin to a valid address - vm.startPrank(s_l2MessengerAddr, s_l2MessengerAddr); - - // Assert initial conditions - uint256 timestamp = s_arbitrumSequencerUptimeFeed.latestTimestamp(); - assertEq(s_arbitrumSequencerUptimeFeed.latestAnswer(), 0); - - // Defines helper variables for measuring gas usage - uint256 expectedGasUsed; - uint256 gasStart; - uint256 gasFinal; - - // measures gas used for no update - expectedGasUsed = 5507; // NOTE: used to be 28300 in hardhat tests - gasStart = gasleft(); - s_arbitrumSequencerUptimeFeed.updateStatus(false, uint64(timestamp + 1000)); - gasFinal = gasleft(); - assertEq(s_arbitrumSequencerUptimeFeed.latestAnswer(), 0); - assertGasUsageIsCloseTo(expectedGasUsed, gasStart, gasFinal, GAS_USED_DEVIATION); - - // measures gas used for update - expectedGasUsed = 68198; // NOTE: used to be 93015 in hardhat tests - gasStart = gasleft(); - s_arbitrumSequencerUptimeFeed.updateStatus(true, uint64(timestamp + 1000)); - gasFinal = gasleft(); - assertEq(s_arbitrumSequencerUptimeFeed.latestAnswer(), 1); - assertGasUsageIsCloseTo(expectedGasUsed, gasStart, gasFinal, GAS_USED_DEVIATION); - } -} - -contract ArbitrumSequencerUptimeFeed_AggregatorInterfaceGasCosts is ArbitrumSequencerUptimeFeedTest { - /// @notice it should consume a known amount of gas for getRoundData(uint80) - function test_GasUsageForGetRoundData() public { - // Sets msg.sender and tx.origin to a valid address - vm.startPrank(s_l2MessengerAddr, s_l2MessengerAddr); - - // Defines helper variables for measuring gas usage - uint256 expectedGasUsed = 4658; // NOTE: used to be 31157 in hardhat tests - uint256 gasStart; - uint256 gasFinal; - - // Initializes a round - uint256 timestamp = s_arbitrumSequencerUptimeFeed.latestTimestamp() + 1000; - s_arbitrumSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - - // Measures gas usage - gasStart = gasleft(); - s_arbitrumSequencerUptimeFeed.getRoundData(1); - gasFinal = gasleft(); - - // Checks that gas usage is within expected range - assertGasUsageIsCloseTo(expectedGasUsed, gasStart, gasFinal, GAS_USED_DEVIATION); - } - - /// @notice it should consume a known amount of gas for latestRoundData() - function test_GasUsageForLatestRoundData() public { - // Sets msg.sender and tx.origin to a valid address - vm.startPrank(s_l2MessengerAddr, s_l2MessengerAddr); - - // Defines helper variables for measuring gas usage - uint256 expectedGasUsed = 2154; // NOTE: used to be 28523 in hardhat tests - uint256 gasStart; - uint256 gasFinal; - - // Initializes a round - uint256 timestamp = s_arbitrumSequencerUptimeFeed.latestTimestamp() + 1000; - s_arbitrumSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - - // Measures gas usage - gasStart = gasleft(); - s_arbitrumSequencerUptimeFeed.latestRoundData(); - gasFinal = gasleft(); - - // Checks that gas usage is within expected range - assertGasUsageIsCloseTo(expectedGasUsed, gasStart, gasFinal, GAS_USED_DEVIATION); - } - - /// @notice it should consume a known amount of gas for latestAnswer() - function test_GasUsageForLatestAnswer() public { - // Sets msg.sender and tx.origin to a valid address - vm.startPrank(s_l2MessengerAddr, s_l2MessengerAddr); - - // Defines helper variables for measuring gas usage - uint256 expectedGasUsed = 1722; // NOTE: used to be 28329 in hardhat tests - uint256 gasStart; - uint256 gasFinal; - - // Initializes a round - uint256 timestamp = s_arbitrumSequencerUptimeFeed.latestTimestamp() + 1000; - s_arbitrumSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - - // Measures gas usage - gasStart = gasleft(); - s_arbitrumSequencerUptimeFeed.latestAnswer(); - gasFinal = gasleft(); - - // Checks that gas usage is within expected range - assertGasUsageIsCloseTo(expectedGasUsed, gasStart, gasFinal, GAS_USED_DEVIATION); - } - - /// @notice it should consume a known amount of gas for latestTimestamp() - function test_GasUsageForLatestTimestamp() public { - // Sets msg.sender and tx.origin to a valid address - vm.startPrank(s_l2MessengerAddr, s_l2MessengerAddr); - - // Defines helper variables for measuring gas usage - uint256 expectedGasUsed = 1652; // NOTE: used to be 28229 in hardhat tests - uint256 gasStart; - uint256 gasFinal; - - // Initializes a round - uint256 timestamp = s_arbitrumSequencerUptimeFeed.latestTimestamp() + 1000; - s_arbitrumSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - - // Measures gas usage - gasStart = gasleft(); - s_arbitrumSequencerUptimeFeed.latestTimestamp(); - gasFinal = gasleft(); - - // Checks that gas usage is within expected range - assertGasUsageIsCloseTo(expectedGasUsed, gasStart, gasFinal, GAS_USED_DEVIATION); - } - - /// @notice it should consume a known amount of gas for latestRound() - function test_GasUsageForLatestRound() public { - // Sets msg.sender and tx.origin to a valid address - vm.startPrank(s_l2MessengerAddr, s_l2MessengerAddr); - - // Defines helper variables for measuring gas usage - uint256 expectedGasUsed = 1632; // NOTE: used to be 28245 in hardhat tests - uint256 gasStart; - uint256 gasFinal; - - // Initializes a round - uint256 timestamp = s_arbitrumSequencerUptimeFeed.latestTimestamp() + 1000; - s_arbitrumSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - - // Measures gas usage - gasStart = gasleft(); - s_arbitrumSequencerUptimeFeed.latestRound(); - gasFinal = gasleft(); - - // Checks that gas usage is within expected range - assertGasUsageIsCloseTo(expectedGasUsed, gasStart, gasFinal, GAS_USED_DEVIATION); - } - - /// @notice it should consume a known amount of gas for getAnswer() - function test_GasUsageForGetAnswer() public { - // Sets msg.sender and tx.origin to a valid address - vm.startPrank(s_l2MessengerAddr, s_l2MessengerAddr); - - // Defines helper variables for measuring gas usage - uint256 expectedGasUsed = 4059; // NOTE: used to be 30799 in hardhat tests - uint256 gasStart; - uint256 gasFinal; - - // Initializes a round - uint256 timestamp = s_arbitrumSequencerUptimeFeed.latestTimestamp() + 1000; - s_arbitrumSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - - // Measures gas usage - gasStart = gasleft(); - s_arbitrumSequencerUptimeFeed.getAnswer(1); - gasFinal = gasleft(); - - // Checks that gas usage is within expected range - assertGasUsageIsCloseTo(expectedGasUsed, gasStart, gasFinal, GAS_USED_DEVIATION); - } - - /// @notice it should consume a known amount of gas for getTimestamp() - function test_GasUsageForGetTimestamp() public { - // Sets msg.sender and tx.origin to a valid address - vm.startPrank(s_l2MessengerAddr, s_l2MessengerAddr); - - // Defines helper variables for measuring gas usage - uint256 expectedGasUsed = 4024; // NOTE: used to be 30753 in hardhat tests - uint256 gasStart; - uint256 gasFinal; - - // Initializes a round - uint256 timestamp = s_arbitrumSequencerUptimeFeed.latestTimestamp() + 1000; - s_arbitrumSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - - // Measures gas usage - gasStart = gasleft(); - s_arbitrumSequencerUptimeFeed.getTimestamp(1); - gasFinal = gasleft(); - - // Checks that gas usage is within expected range - assertGasUsageIsCloseTo(expectedGasUsed, gasStart, gasFinal, GAS_USED_DEVIATION); - } -} diff --git a/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismSequencerUptimeFeed.t.sol b/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismSequencerUptimeFeed.t.sol index 60598b9f95..071d6e5b42 100644 --- a/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismSequencerUptimeFeed.t.sol +++ b/contracts/src/v0.8/l2ep/test/v1_0_0/optimism/OptimismSequencerUptimeFeed.t.sol @@ -318,207 +318,3 @@ contract OptimismSequencerUptimeFeed_ProtectReadsOnAggregatorV2V3InterfaceFuncti assertEq(answer, 0); } } - -contract OptimismSequencerUptimeFeed_GasCosts is OptimismSequencerUptimeFeedTest { - /// @notice it should consume a known amount of gas for updates - function test_GasCosts() public { - // Sets msg.sender and tx.origin to a valid address - address l2MessengerAddr = address(s_mockOptimismL2CrossDomainMessenger); - vm.startPrank(l2MessengerAddr, l2MessengerAddr); - - // Assert initial conditions - uint256 timestamp = s_optimismSequencerUptimeFeed.latestTimestamp(); - assertEq(s_optimismSequencerUptimeFeed.latestAnswer(), 0); - - // Defines helper variables for measuring gas usage - uint256 expectedGasUsed; - uint256 gasStart; - uint256 gasFinal; - - // measures gas used for no update - expectedGasUsed = 10197; // NOTE: used to be 38594 in hardhat tests - gasStart = gasleft(); - s_optimismSequencerUptimeFeed.updateStatus(false, uint64(timestamp + 1000)); - gasFinal = gasleft(); - assertEq(s_optimismSequencerUptimeFeed.latestAnswer(), 0); - assertGasUsageIsCloseTo(expectedGasUsed, gasStart, gasFinal, GAS_USED_DEVIATION); - - // measures gas used for update - expectedGasUsed = 33348; // NOTE: used to be 60170 in hardhat tests - gasStart = gasleft(); - s_optimismSequencerUptimeFeed.updateStatus(true, uint64(timestamp + 1000)); - gasFinal = gasleft(); - assertEq(s_optimismSequencerUptimeFeed.latestAnswer(), 1); - assertGasUsageIsCloseTo(expectedGasUsed, gasStart, gasFinal, GAS_USED_DEVIATION); - } -} - -contract OptimismSequencerUptimeFeed_AggregatorInterfaceGasCosts is OptimismSequencerUptimeFeedTest { - /// @notice it should consume a known amount of gas for getRoundData(uint80) - function test_GasUsageForGetRoundData() public { - // Sets msg.sender and tx.origin to a valid address - address l2MessengerAddr = address(s_mockOptimismL2CrossDomainMessenger); - vm.startPrank(l2MessengerAddr, l2MessengerAddr); - - // Defines helper variables for measuring gas usage - uint256 expectedGasUsed = 4504; // NOTE: used to be 30952 in hardhat tests - uint256 gasStart; - uint256 gasFinal; - - // Initializes a round - uint256 timestamp = s_optimismSequencerUptimeFeed.latestTimestamp() + 1000; - s_optimismSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - - // Measures gas usage - gasStart = gasleft(); - s_optimismSequencerUptimeFeed.getRoundData(1); - gasFinal = gasleft(); - - // Checks that gas usage is within expected range - assertGasUsageIsCloseTo(expectedGasUsed, gasStart, gasFinal, GAS_USED_DEVIATION); - } - - /// @notice it should consume a known amount of gas for latestRoundData() - function test_GasUsageForLatestRoundData() public { - // Sets msg.sender and tx.origin to a valid address - address l2MessengerAddr = address(s_mockOptimismL2CrossDomainMessenger); - vm.startPrank(l2MessengerAddr, l2MessengerAddr); - - // Defines helper variables for measuring gas usage - uint256 expectedGasUsed = 2154; // NOTE: used to be 28523 in hardhat tests - uint256 gasStart; - uint256 gasFinal; - - // Initializes a round - uint256 timestamp = s_optimismSequencerUptimeFeed.latestTimestamp() + 1000; - s_optimismSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - - // Measures gas usage - gasStart = gasleft(); - s_optimismSequencerUptimeFeed.latestRoundData(); - gasFinal = gasleft(); - - // Checks that gas usage is within expected range - assertGasUsageIsCloseTo(expectedGasUsed, gasStart, gasFinal, GAS_USED_DEVIATION); - } - - /// @notice it should consume a known amount of gas for latestAnswer() - function test_GasUsageForLatestAnswer() public { - // Sets msg.sender and tx.origin to a valid address - address l2MessengerAddr = address(s_mockOptimismL2CrossDomainMessenger); - vm.startPrank(l2MessengerAddr, l2MessengerAddr); - - // Defines helper variables for measuring gas usage - uint256 expectedGasUsed = 1722; // NOTE: used to be 28329 in hardhat tests - uint256 gasStart; - uint256 gasFinal; - - // Initializes a round - uint256 timestamp = s_optimismSequencerUptimeFeed.latestTimestamp() + 1000; - s_optimismSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - - // Measures gas usage - gasStart = gasleft(); - s_optimismSequencerUptimeFeed.latestAnswer(); - gasFinal = gasleft(); - - // Checks that gas usage is within expected range - assertGasUsageIsCloseTo(expectedGasUsed, gasStart, gasFinal, GAS_USED_DEVIATION); - } - - /// @notice it should consume a known amount of gas for latestTimestamp() - function test_GasUsageForLatestTimestamp() public { - // Sets msg.sender and tx.origin to a valid address - address l2MessengerAddr = address(s_mockOptimismL2CrossDomainMessenger); - vm.startPrank(l2MessengerAddr, l2MessengerAddr); - - // Defines helper variables for measuring gas usage - uint256 expectedGasUsed = 1598; // NOTE: used to be 28229 in hardhat tests - uint256 gasStart; - uint256 gasFinal; - - // Initializes a round - uint256 timestamp = s_optimismSequencerUptimeFeed.latestTimestamp() + 1000; - s_optimismSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - - // Measures gas usage - gasStart = gasleft(); - s_optimismSequencerUptimeFeed.latestTimestamp(); - gasFinal = gasleft(); - - // Checks that gas usage is within expected range - assertGasUsageIsCloseTo(expectedGasUsed, gasStart, gasFinal, GAS_USED_DEVIATION); - } - - /// @notice it should consume a known amount of gas for latestRound() - function test_GasUsageForLatestRound() public { - // Sets msg.sender and tx.origin to a valid address - address l2MessengerAddr = address(s_mockOptimismL2CrossDomainMessenger); - vm.startPrank(l2MessengerAddr, l2MessengerAddr); - - // Defines helper variables for measuring gas usage - uint256 expectedGasUsed = 1632; // NOTE: used to be 28245 in hardhat tests - uint256 gasStart; - uint256 gasFinal; - - // Initializes a round - uint256 timestamp = s_optimismSequencerUptimeFeed.latestTimestamp() + 1000; - s_optimismSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - - // Measures gas usage - gasStart = gasleft(); - s_optimismSequencerUptimeFeed.latestRound(); - gasFinal = gasleft(); - - // Checks that gas usage is within expected range - assertGasUsageIsCloseTo(expectedGasUsed, gasStart, gasFinal, GAS_USED_DEVIATION); - } - - /// @notice it should consume a known amount of gas for getAnswer() - function test_GasUsageForGetAnswer() public { - // Sets msg.sender and tx.origin to a valid address - address l2MessengerAddr = address(s_mockOptimismL2CrossDomainMessenger); - vm.startPrank(l2MessengerAddr, l2MessengerAddr); - - // Defines helper variables for measuring gas usage - uint256 expectedGasUsed = 3929; // NOTE: used to be 30682 in hardhat tests - uint256 gasStart; - uint256 gasFinal; - - // Initializes a round - uint256 timestamp = s_optimismSequencerUptimeFeed.latestTimestamp() + 1000; - s_optimismSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - - // Measures gas usage - gasStart = gasleft(); - s_optimismSequencerUptimeFeed.getAnswer(1); - gasFinal = gasleft(); - - // Checks that gas usage is within expected range - assertGasUsageIsCloseTo(expectedGasUsed, gasStart, gasFinal, GAS_USED_DEVIATION); - } - - /// @notice it should consume a known amount of gas for getTimestamp() - function test_GasUsageForGetTimestamp() public { - // Sets msg.sender and tx.origin to a valid address - address l2MessengerAddr = address(s_mockOptimismL2CrossDomainMessenger); - vm.startPrank(l2MessengerAddr, l2MessengerAddr); - - // Defines helper variables for measuring gas usage - uint256 expectedGasUsed = 3817; // NOTE: used to be 30570 in hardhat tests - uint256 gasStart; - uint256 gasFinal; - - // Initializes a round - uint256 timestamp = s_optimismSequencerUptimeFeed.latestTimestamp() + 1000; - s_optimismSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - - // Measures gas usage - gasStart = gasleft(); - s_optimismSequencerUptimeFeed.getTimestamp(1); - gasFinal = gasleft(); - - // Checks that gas usage is within expected range - assertGasUsageIsCloseTo(expectedGasUsed, gasStart, gasFinal, GAS_USED_DEVIATION); - } -} diff --git a/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollSequencerUptimeFeed.t.sol b/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollSequencerUptimeFeed.t.sol index 520fbf6dfd..3aac50e7c1 100644 --- a/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollSequencerUptimeFeed.t.sol +++ b/contracts/src/v0.8/l2ep/test/v1_0_0/scroll/ScrollSequencerUptimeFeed.t.sol @@ -322,207 +322,3 @@ contract ScrollSequencerUptimeFeed_ProtectReadsOnAggregatorV2V3InterfaceFunction assertEq(answer, 0); } } - -contract ScrollSequencerUptimeFeed_GasCosts is ScrollSequencerUptimeFeedTest { - /// @notice it should consume a known amount of gas for updates - function test_GasCosts() public { - // Sets msg.sender and tx.origin to a valid address - address l2MessengerAddr = address(s_mockScrollL2CrossDomainMessenger); - vm.startPrank(l2MessengerAddr, l2MessengerAddr); - - // Assert initial conditions - uint256 timestamp = s_scrollSequencerUptimeFeed.latestTimestamp(); - assertEq(s_scrollSequencerUptimeFeed.latestAnswer(), 0); - - // Defines helper variables for measuring gas usage - uint256 expectedGasUsed; - uint256 gasStart; - uint256 gasFinal; - - // measures gas used for no update - expectedGasUsed = 10197; // NOTE: used to be 38594 in hardhat tests - gasStart = gasleft(); - s_scrollSequencerUptimeFeed.updateStatus(false, uint64(timestamp + 1000)); - gasFinal = gasleft(); - assertEq(s_scrollSequencerUptimeFeed.latestAnswer(), 0); - assertGasUsageIsCloseTo(expectedGasUsed, gasStart, gasFinal, GAS_USED_DEVIATION); - - // measures gas used for update - expectedGasUsed = 31644; // NOTE: used to be 58458 in hardhat tests - gasStart = gasleft(); - s_scrollSequencerUptimeFeed.updateStatus(true, uint64(timestamp + 1000)); - gasFinal = gasleft(); - assertEq(s_scrollSequencerUptimeFeed.latestAnswer(), 1); - assertGasUsageIsCloseTo(expectedGasUsed, gasStart, gasFinal, GAS_USED_DEVIATION); - } -} - -contract ScrollSequencerUptimeFeed_AggregatorInterfaceGasCosts is ScrollSequencerUptimeFeedTest { - /// @notice it should consume a known amount of gas for getRoundData(uint80) - function test_GasUsageForGetRoundData() public { - // Sets msg.sender and tx.origin to a valid address - address l2MessengerAddr = address(s_mockScrollL2CrossDomainMessenger); - vm.startPrank(l2MessengerAddr, l2MessengerAddr); - - // Defines helper variables for measuring gas usage - uint256 expectedGasUsed = 4504; // NOTE: used to be 30952 in hardhat tesst - uint256 gasStart; - uint256 gasFinal; - - // Initializes a round - uint256 timestamp = s_scrollSequencerUptimeFeed.latestTimestamp() + 1000; - s_scrollSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - - // Measures gas usage - gasStart = gasleft(); - s_scrollSequencerUptimeFeed.getRoundData(1); - gasFinal = gasleft(); - - // Checks that gas usage is within expected range - assertGasUsageIsCloseTo(expectedGasUsed, gasStart, gasFinal, GAS_USED_DEVIATION); - } - - /// @notice it should consume a known amount of gas for latestRoundData() - function test_GasUsageForLatestRoundData() public { - // Sets msg.sender and tx.origin to a valid address - address l2MessengerAddr = address(s_mockScrollL2CrossDomainMessenger); - vm.startPrank(l2MessengerAddr, l2MessengerAddr); - - // Defines helper variables for measuring gas usage - uint256 expectedGasUsed = 2154; // NOTE: used to be 28523 in hardhat tests - uint256 gasStart; - uint256 gasFinal; - - // Initializes a round - uint256 timestamp = s_scrollSequencerUptimeFeed.latestTimestamp() + 1000; - s_scrollSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - - // Measures gas usage - gasStart = gasleft(); - s_scrollSequencerUptimeFeed.latestRoundData(); - gasFinal = gasleft(); - - // Checks that gas usage is within expected range - assertGasUsageIsCloseTo(expectedGasUsed, gasStart, gasFinal, GAS_USED_DEVIATION); - } - - /// @notice it should consume a known amount of gas for latestAnswer() - function test_GasUsageForLatestAnswer() public { - // Sets msg.sender and tx.origin to a valid address - address l2MessengerAddr = address(s_mockScrollL2CrossDomainMessenger); - vm.startPrank(l2MessengerAddr, l2MessengerAddr); - - // Defines helper variables for measuring gas usage - uint256 expectedGasUsed = 1566; // NOTE: used to be 28229 in hardhat tests - uint256 gasStart; - uint256 gasFinal; - - // Initializes a round - uint256 timestamp = s_scrollSequencerUptimeFeed.latestTimestamp() + 1000; - s_scrollSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - - // Measures gas usage - gasStart = gasleft(); - s_scrollSequencerUptimeFeed.latestAnswer(); - gasFinal = gasleft(); - - // Checks that gas usage is within expected range - assertGasUsageIsCloseTo(expectedGasUsed, gasStart, gasFinal, GAS_USED_DEVIATION); - } - - /// @notice it should consume a known amount of gas for latestTimestamp() - function test_GasUsageForLatestTimestamp() public { - // Sets msg.sender and tx.origin to a valid address - address l2MessengerAddr = address(s_mockScrollL2CrossDomainMessenger); - vm.startPrank(l2MessengerAddr, l2MessengerAddr); - - // Defines helper variables for measuring gas usage - uint256 expectedGasUsed = 1459; // NOTE: used to be 28129 in hardhat tests - uint256 gasStart; - uint256 gasFinal; - - // Initializes a round - uint256 timestamp = s_scrollSequencerUptimeFeed.latestTimestamp() + 1000; - s_scrollSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - - // Measures gas usage - gasStart = gasleft(); - s_scrollSequencerUptimeFeed.latestTimestamp(); - gasFinal = gasleft(); - - // Checks that gas usage is within expected range - assertGasUsageIsCloseTo(expectedGasUsed, gasStart, gasFinal, GAS_USED_DEVIATION); - } - - /// @notice it should consume a known amount of gas for latestRound() - function test_GasUsageForLatestRound() public { - // Sets msg.sender and tx.origin to a valid address - address l2MessengerAddr = address(s_mockScrollL2CrossDomainMessenger); - vm.startPrank(l2MessengerAddr, l2MessengerAddr); - - // Defines helper variables for measuring gas usage - uint256 expectedGasUsed = 1470; // NOTE: used to be 28145 in hardhat tests - uint256 gasStart; - uint256 gasFinal; - - // Initializes a round - uint256 timestamp = s_scrollSequencerUptimeFeed.latestTimestamp() + 1000; - s_scrollSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - - // Measures gas usage - gasStart = gasleft(); - s_scrollSequencerUptimeFeed.latestRound(); - gasFinal = gasleft(); - - // Checks that gas usage is within expected range - assertGasUsageIsCloseTo(expectedGasUsed, gasStart, gasFinal, GAS_USED_DEVIATION); - } - - /// @notice it should consume a known amount of gas for getAnswer() - function test_GasUsageForGetAnswer() public { - // Sets msg.sender and tx.origin to a valid address - address l2MessengerAddr = address(s_mockScrollL2CrossDomainMessenger); - vm.startPrank(l2MessengerAddr, l2MessengerAddr); - - // Defines helper variables for measuring gas usage - uint256 expectedGasUsed = 3929; // NOTE: used to be 30682 in hardhat tests - uint256 gasStart; - uint256 gasFinal; - - // Initializes a round - uint256 timestamp = s_scrollSequencerUptimeFeed.latestTimestamp() + 1000; - s_scrollSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - - // Measures gas usage - gasStart = gasleft(); - s_scrollSequencerUptimeFeed.getAnswer(1); - gasFinal = gasleft(); - - // Checks that gas usage is within expected range - assertGasUsageIsCloseTo(expectedGasUsed, gasStart, gasFinal, GAS_USED_DEVIATION); - } - - /// @notice it should consume a known amount of gas for getTimestamp() - function test_GasUsageForGetTimestamp() public { - // Sets msg.sender and tx.origin to a valid address - address l2MessengerAddr = address(s_mockScrollL2CrossDomainMessenger); - vm.startPrank(l2MessengerAddr, l2MessengerAddr); - - // Defines helper variables for measuring gas usage - uint256 expectedGasUsed = 3817; // NOTE: used to be 30570 in hardhat tests - uint256 gasStart; - uint256 gasFinal; - - // Initializes a round - uint256 timestamp = s_scrollSequencerUptimeFeed.latestTimestamp() + 1000; - s_scrollSequencerUptimeFeed.updateStatus(true, uint64(timestamp)); - - // Measures gas usage - gasStart = gasleft(); - s_scrollSequencerUptimeFeed.getTimestamp(1); - gasFinal = gasleft(); - - // Checks that gas usage is within expected range - assertGasUsageIsCloseTo(expectedGasUsed, gasStart, gasFinal, GAS_USED_DEVIATION); - } -} diff --git a/contracts/src/v0.8/llo-feeds/test/ByteUtilTest.t.sol b/contracts/src/v0.8/llo-feeds/test/ByteUtilTest.t.sol index 21bd957e4e..fdabaaf3d9 100644 --- a/contracts/src/v0.8/llo-feeds/test/ByteUtilTest.t.sol +++ b/contracts/src/v0.8/llo-feeds/test/ByteUtilTest.t.sol @@ -15,7 +15,7 @@ contract ByteUtilTest is Test { bytes4 internal constant MALFORMED_ERROR_SELECTOR = bytes4(keccak256("MalformedData()")); - function test_readUint256Max() public { + function test_readUint256Max() public pure { //read the first 32 bytes uint256 result = B_512._readUint256(0); @@ -23,7 +23,7 @@ contract ByteUtilTest is Test { assertEq(result, type(uint256).max); } - function test_readUint192Max() public { + function test_readUint192Max() public pure { //read the first 24 bytes uint256 result = B_512._readUint192(0); @@ -31,7 +31,7 @@ contract ByteUtilTest is Test { assertEq(result, type(uint192).max); } - function test_readUint32Max() public { + function test_readUint32Max() public pure { //read the first 4 bytes uint256 result = B_512._readUint32(0); @@ -39,7 +39,7 @@ contract ByteUtilTest is Test { assertEq(result, type(uint32).max); } - function test_readUint256Min() public { + function test_readUint256Min() public pure { //read the second 32 bytes uint256 result = B_512._readUint256(32); @@ -47,7 +47,7 @@ contract ByteUtilTest is Test { assertEq(result, type(uint256).min); } - function test_readUint192Min() public { + function test_readUint192Min() public pure { //read the second 24 bytes uint256 result = B_512._readUint192(32); @@ -55,7 +55,7 @@ contract ByteUtilTest is Test { assertEq(result, type(uint192).min); } - function test_readUint32Min() public { + function test_readUint32Min() public pure { //read the second 4 bytes uint256 result = B_512._readUint32(32); @@ -63,7 +63,7 @@ contract ByteUtilTest is Test { assertEq(result, type(uint32).min); } - function test_readUint256MultiWord() public { + function test_readUint256MultiWord() public pure { //read the first 32 bytes uint256 result = B_512._readUint256(31); @@ -71,7 +71,7 @@ contract ByteUtilTest is Test { assertEq(result, type(uint256).max << 248); } - function test_readUint192MultiWord() public { + function test_readUint192MultiWord() public pure { //read the first 24 bytes uint256 result = B_512._readUint192(31); @@ -79,7 +79,7 @@ contract ByteUtilTest is Test { assertEq(result, type(uint192).max << 184); } - function test_readUint32MultiWord() public { + function test_readUint32MultiWord() public pure { //read the first 4 bytes uint256 result = B_512._readUint32(31); @@ -135,7 +135,7 @@ contract ByteUtilTest is Test { B_EMPTY._readUint32(0); } - function test_readAddress() public { + function test_readAddress() public pure { //read the first 20 bytes address result = B_512._readAddress(0); @@ -143,7 +143,7 @@ contract ByteUtilTest is Test { assertEq(result, address(type(uint160).max)); } - function test_readZeroAddress() public { + function test_readZeroAddress() public pure { //read the first 32 bytes after the first word address result = B_512._readAddress(32); @@ -151,7 +151,7 @@ contract ByteUtilTest is Test { assertEq(result, address(type(uint160).min)); } - function test_readAddressMultiWord() public { + function test_readAddressMultiWord() public pure { //read the first 20 bytes after byte 13 address result = B_512._readAddress(13); diff --git a/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousConsumer.sol b/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousConsumer.sol index 842eec9054..bd731c7718 100644 --- a/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousConsumer.sol +++ b/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousConsumer.sol @@ -7,7 +7,7 @@ contract MaliciousConsumer is Chainlinked { uint256 private constant ORACLE_PAYMENT = 1 ether; uint256 private s_expiration; - constructor(address _link, address _oracle) public payable { + constructor(address _link, address _oracle) payable { setLinkToken(_link); setOracle(_oracle); } diff --git a/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousMultiWordConsumer.sol b/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousMultiWordConsumer.sol index 6e5881524f..93af16f64f 100644 --- a/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousMultiWordConsumer.sol +++ b/contracts/src/v0.8/operatorforwarder/test/testhelpers/MaliciousMultiWordConsumer.sol @@ -8,7 +8,7 @@ contract MaliciousMultiWordConsumer is ChainlinkClient { uint256 private constant ORACLE_PAYMENT = 1 ether; uint256 private s_expiration; - constructor(address _link, address _oracle) public payable { + constructor(address _link, address _oracle) payable { _setChainlinkToken(_link); _setChainlinkOracle(_oracle); } diff --git a/contracts/src/v0.8/shared/test/call/CallWithExactGas.t.sol b/contracts/src/v0.8/shared/test/call/CallWithExactGas.t.sol index 444112d2d8..3623cb8b12 100644 --- a/contracts/src/v0.8/shared/test/call/CallWithExactGas.t.sol +++ b/contracts/src/v0.8/shared/test/call/CallWithExactGas.t.sol @@ -220,7 +220,7 @@ contract CallWithExactGas__callWithExactGasSafeReturnData is CallWithExactGasSet assertGt(gasUsed, 500); } - function testFuzz_CallWithExactGasSafeReturnData_ConsumeAllGas_Success(uint8 gasLimitMultiplier) external { + function test_Fuzz_CallWithExactGasSafeReturnData_ConsumeAllGas_Success(uint8 gasLimitMultiplier) external { vm.assume(gasLimitMultiplier > 0); // Assume not zero to avoid zero gas being passed to s_gasConsumer uint16 maxRetBytes = 0; @@ -244,7 +244,7 @@ contract CallWithExactGas__callWithExactGasSafeReturnData is CallWithExactGasSet assertTrue(success, "Error: External Call Failed"); - //Assert equal within a margin of error of 1/64 of the gas limit to account for excess gas used by execution library + // Assert equal within a margin of error of 1/64 of the gas limit to account for excess gas used by execution library assertApproxEqAbs( gasUsed - CALL_WITH_EXACT_GAS_SAFE_RETURN_DATA_GAS_OVERHEAD, gasLimit, diff --git a/contracts/src/v0.8/shared/test/testhelpers/GasConsumer.sol b/contracts/src/v0.8/shared/test/testhelpers/GasConsumer.sol index 3c7bd2d596..efac2d15c1 100644 --- a/contracts/src/v0.8/shared/test/testhelpers/GasConsumer.sol +++ b/contracts/src/v0.8/shared/test/testhelpers/GasConsumer.sol @@ -9,8 +9,9 @@ contract GasConsumer { } lt(0, 1) { } { - // If 60 gas is remaining, then exit the loop by returning. 60 was determined by manual binary search to be the minimal amount of gas needed but less than the cost of another loop - if lt(gas(), 60) { + // If 100 gas is remaining, then exit the loop by returning. 100 was determined by manual binary search to be + // the minimal amount of gas needed but less than the cost of another loop + if lt(gas(), 100) { return(0x0, 0x0) // Return with no return data } } diff --git a/contracts/src/v0.8/shared/test/token/ERC677/BurnMintERC677.t.sol b/contracts/src/v0.8/shared/test/token/ERC677/BurnMintERC677.t.sol index de9067a569..2815f99256 100644 --- a/contracts/src/v0.8/shared/test/token/ERC677/BurnMintERC677.t.sol +++ b/contracts/src/v0.8/shared/test/token/ERC677/BurnMintERC677.t.sol @@ -338,7 +338,7 @@ contract BurnMintERC677_increaseApproval is BurnMintERC677Setup { } contract BurnMintERC677_supportsInterface is BurnMintERC677Setup { - function testConstructorSuccess() public { + function testConstructorSuccess() public view { assertTrue(s_burnMintERC677.supportsInterface(type(IERC20).interfaceId)); assertTrue(s_burnMintERC677.supportsInterface(type(IERC677).interfaceId)); assertTrue(s_burnMintERC677.supportsInterface(type(IBurnMintERC20).interfaceId)); diff --git a/contracts/src/v0.8/shared/test/token/ERC677/OpStackBurnMintERC677.t.sol b/contracts/src/v0.8/shared/test/token/ERC677/OpStackBurnMintERC677.t.sol index 7987fefec4..614b3bea15 100644 --- a/contracts/src/v0.8/shared/test/token/ERC677/OpStackBurnMintERC677.t.sol +++ b/contracts/src/v0.8/shared/test/token/ERC677/OpStackBurnMintERC677.t.sol @@ -41,7 +41,7 @@ contract OpStackBurnMintERC677_constructor is OpStackBurnMintERC677Setup { } contract OpStackBurnMintERC677_supportsInterface is OpStackBurnMintERC677Setup { - function testConstructorSuccess() public { + function testConstructorSuccess() public view { assertTrue(s_opStackBurnMintERC677.supportsInterface(type(IOptimismMintableERC20Minimal).interfaceId)); assertTrue(s_opStackBurnMintERC677.supportsInterface(type(IERC677).interfaceId)); assertTrue(s_opStackBurnMintERC677.supportsInterface(type(IBurnMintERC20).interfaceId)); diff --git a/contracts/src/v0.8/shared/test/util/SortedSetValidationUtil.t.sol b/contracts/src/v0.8/shared/test/util/SortedSetValidationUtil.t.sol index ae7eba479f..bf88df64ad 100644 --- a/contracts/src/v0.8/shared/test/util/SortedSetValidationUtil.t.sol +++ b/contracts/src/v0.8/shared/test/util/SortedSetValidationUtil.t.sol @@ -50,7 +50,7 @@ contract SortedSetValidationUtilBaseTest is BaseTest { contract SortedSetValidationUtil_CheckIsValidUniqueSubsetTest is SortedSetValidationUtilBaseTest { // Successes. - function test__checkIsValidUniqueSubset_ValidSubset_Success() public { + function test__checkIsValidUniqueSubset_ValidSubset_Success() public pure { (bytes32[] memory subset, bytes32[] memory superset) = _createSets(3, 5); _convertArrayToSortedSet(superset, OFFSET); _convertArrayToSubset(subset, superset); @@ -123,7 +123,7 @@ contract SortedSetValidationUtil_CheckIsValidUniqueSubsetTest is SortedSetValida SortedSetValidationUtil._checkIsValidUniqueSubset(subset, superset); } - function test__checkIsValidUniqueSubset_SubsetEqualsSuperset_NoRevert() public { + function test__checkIsValidUniqueSubset_SubsetEqualsSuperset_NoRevert() public pure { (bytes32[] memory subset, bytes32[] memory superset) = _createSets(5, 5); _convertArrayToSortedSet(subset, OFFSET); _convertArrayToSortedSet(superset, OFFSET); @@ -131,7 +131,7 @@ contract SortedSetValidationUtil_CheckIsValidUniqueSubsetTest is SortedSetValida SortedSetValidationUtil._checkIsValidUniqueSubset(subset, superset); } - function test__checkIsValidUniqueSubset_SingleElementSubset() public { + function test__checkIsValidUniqueSubset_SingleElementSubset() public pure { (bytes32[] memory subset, bytes32[] memory superset) = _createSets(1, 5); _convertArrayToSortedSet(superset, OFFSET); _convertArrayToSubset(subset, superset); @@ -139,7 +139,7 @@ contract SortedSetValidationUtil_CheckIsValidUniqueSubsetTest is SortedSetValida SortedSetValidationUtil._checkIsValidUniqueSubset(subset, superset); } - function test__checkIsValidUniqueSubset_SingleElementSubsetAndSuperset_Equal() public { + function test__checkIsValidUniqueSubset_SingleElementSubsetAndSuperset_Equal() public pure { (bytes32[] memory subset, bytes32[] memory superset) = _createSets(1, 1); _convertArrayToSortedSet(subset, OFFSET); _convertArrayToSortedSet(superset, OFFSET); diff --git a/contracts/src/v0.8/vrf/test/BatchVRFCoordinatorV2Plus.t.sol b/contracts/src/v0.8/vrf/test/BatchVRFCoordinatorV2Plus.t.sol index c2938cb35b..4197073aa5 100644 --- a/contracts/src/v0.8/vrf/test/BatchVRFCoordinatorV2Plus.t.sol +++ b/contracts/src/v0.8/vrf/test/BatchVRFCoordinatorV2Plus.t.sol @@ -48,17 +48,26 @@ contract BatchVRFCoordinatorV2PlusTest is FixtureVRFCoordinatorV2_5 { // Store the previous block's blockhash. vm.roll(requestBlock + 1); s_bhs.store(requestBlock); + assertEq(hex"1a192fabce13988b84994d4296e6cdc418d55e2f1d7f942188d4040b94fc57ac", s_bhs.getBlockhash(requestBlock)); VRFTypes.Proof[] memory proofs = new VRFTypes.Proof[](2); VRFTypes.RequestCommitmentV2Plus[] memory rcs = new VRFTypes.RequestCommitmentV2Plus[](2); - // Proof generated via the generate-proof-v2-plus script command. Example usage: - // _printGenerateProofV2PlusCommand(address(s_consumer), 1, requestBlock, true); + // Proof generated via the generate-proof-v2-plus script command. + // 1st step: Uncomment the print command below and run the test to print the output. + // _printGenerateProofV2PlusCommand(address(s_consumer1), 1, requestBlock, false); + // 2nd step: export the following environment variables to run the generate-proof-v2-plus script. + // export ETH_URL=https://ethereum-sepolia-rpc.publicnode.com # or any other RPC provider you prefer + // export ETH_CHAIN_ID=11155111 # or switch to any other chain + // export ACCOUNT_KEY= + // 3rd step: copy the output from the 1st step and update the command below, then run the command + // and copy the command output in the proof section below /* + Run from this folder: chainlink/core/scripts/vrfv2plus/testnet go run . generate-proof-v2-plus \ -key-hash 0x9f2353bde94264dbc3d554a94cceba2d7d2b4fdce4304d3e09a1fea9fbeb1528 \ - -pre-seed 33855227690351884611579800220581891477580182035146587491531555927634180294480 \ - -block-hash 0x0a \ + -pre-seed 4430852740828987645228960511496023658059009607317025880962658187812299131155 \ + -block-hash 0x1a192fabce13988b84994d4296e6cdc418d55e2f1d7f942188d4040b94fc57ac \ -block-num 10 \ -sender 0xdc90e8ce61c1af8a638b95264037c8e67ee5765c \ -native-payment true @@ -70,22 +79,22 @@ contract BatchVRFCoordinatorV2PlusTest is FixtureVRFCoordinatorV2_5 { 62070622898698443831883535403436258712770888294397026493185421712108624767191 ], gamma: [ - 80420391742429647505172101941811820476888293644816377569181566466584288434705, - 24046736031266889997051641830469514057863365715722268340801477580836256044582 + 26762213923453052192184693334574145607290366984305044804336172347176490943606, + 70503534560525619072578237689732581746976650376431765635714023643649039207077 ], - c: 74775128390693502914275156263410881155583102046081919417827483535122161050585, - s: 69563235412360165148368009853509434870917653835330501139204071967997764190111, - seed: 33855227690351884611579800220581891477580182035146587491531555927634180294480, - uWitness: 0xfB0663eaf48785540dE0FD0F837FD9c09BF4B80A, + c: 10992233996918874905152274435276937088064589467016709044984819613170049539489, + s: 79662863379962724455809192044326025082567113176696761949197261107120333769102, + seed: 4430852740828987645228960511496023658059009607317025880962658187812299131155, + uWitness: 0x421A52Fb797d76Fb610aA1a0c020346fC1Ee2DeB, cGammaWitness: [ - 53711159452748734758194447734939737695995909567499536035707522847057731697403, - 113650002631484103366420937668971311744887820666944514581352028601506700116835 + 50748523246052507241857300891945475679319243536065937584940024494820365165901, + 85746856994474260612851047426766648416105284284185975301552792881940939754570 ], sHashWitness: [ - 89656531714223714144489731263049239277719465105516547297952288438117443488525, - 90859682705760125677895017864538514058733199985667976488434404721197234427011 + 78637275871978664522379716948105702461748200460627087255706483027519919611423, + 82219236913923465822780520561305604064850823877720616893986252854976640396959 ], - zInv: 97275608653505690744303242942631893944856831559408852202478373762878300587548 + zInv: 60547558497534848069125896511700272238016171243048151035528198622956754542730 }); rcs[0] = VRFTypes.RequestCommitmentV2Plus({ blockNum: requestBlock, @@ -116,14 +125,23 @@ contract BatchVRFCoordinatorV2PlusTest is FixtureVRFCoordinatorV2_5 { // Store the previous block's blockhash. vm.roll(requestBlock + 1); s_bhs.store(requestBlock); + assertEq(hex"731dc163f73d31d8c68f9917ce4ff967753939f70432973c04fd2c2a48148607", s_bhs.getBlockhash(requestBlock)); - // Proof generated via the generate-proof-v2-plus script command. Example usage: + // Proof generated via the generate-proof-v2-plus script command. + // 1st step: Uncomment the print command below and run the test to print the output. // _printGenerateProofV2PlusCommand(address(s_consumer1), 1, requestBlock, false); + // 2nd step: export the following environment variables to run the generate-proof-v2-plus script. + // export ETH_URL=https://ethereum-sepolia-rpc.publicnode.com # or any other RPC provider you prefer + // export ETH_CHAIN_ID=11155111 # or switch to any other chain + // export ACCOUNT_KEY= + // 3rd step: copy the output from the 1st step and update the command below, then run the command + // and copy the command output in the proof section below /* + Run from this folder: chainlink/core/scripts/vrfv2plus/testnet go run . generate-proof-v2-plus \ -key-hash 0x9f2353bde94264dbc3d554a94cceba2d7d2b4fdce4304d3e09a1fea9fbeb1528 \ - -pre-seed 76568185840201037774581758921393822690942290841865097674309745036496166431060 \ - -block-hash 0x14 \ + -pre-seed 14541556911652758131165474365357244907354309169650401973525070879190071151266 \ + -block-hash 0x731dc163f73d31d8c68f9917ce4ff967753939f70432973c04fd2c2a48148607 \ -block-num 20 \ -sender 0x2f1c0761d6e4b1e5f01968d6c746f695e5f3e25d \ -native-payment false @@ -134,22 +152,22 @@ contract BatchVRFCoordinatorV2PlusTest is FixtureVRFCoordinatorV2_5 { 62070622898698443831883535403436258712770888294397026493185421712108624767191 ], gamma: [ - 21323932463597506192387578758854201988004673105893105492473194972397109828006, - 96834737826889397196571646974355352644437196500310392203712129010026003355112 + 97658842840420719674383370910135023062422561858595941631054490821636116883585, + 44255438468488339528368406358785988551798314198954634050943346751039644360856 ], - c: 8775807990949224376582975115621037245862755412370175152581490650310350359728, - s: 6805708577951013810918872616271445638109899206333819877111740872779453350091, - seed: 76568185840201037774581758921393822690942290841865097674309745036496166431060, - uWitness: 0xE82fF24Fecfbe73d682f38308bE3E039Dfabdf5c, + c: 5233652943248967403606766735502925802264855214922758107203237169366748118852, + s: 87931642435666855739510477620068257005869145374865238974094299759068218698655, + seed: 14541556911652758131165474365357244907354309169650401973525070879190071151266, + uWitness: 0x0A87a9CB71983cE0F2C4bA41D0c1A6Fb1785c46A, cGammaWitness: [ - 92810770919624535241476539842820168209710445519252592382122118536598338376923, - 17271305664006119131434661141858450289379246199095231636439133258170648418554 + 54062743217909816783918413821204010151082432359411822104552882037459289383418, + 67491004534731980264926765871774299056809003077448271411776926359153820235981 ], sHashWitness: [ - 29540023305939374439696120003978246982707698669656874393367212257432197207536, - 93902323936532381028323379401739289810874348405259732508442252936582467730050 + 7745933951617569731026754652291310837540252155195826133994719499558406927394, + 58405861596456412358325504621101233475720292237067230796670629212111423924259 ], - zInv: 88845170436601946907659333156418518556235340365885668267853966404617557948692 + zInv: 44253513765558903217330502897662324213800000485156126961643960636269885275795 }); rcs[1] = VRFTypes.RequestCommitmentV2Plus({ blockNum: requestBlock, @@ -168,9 +186,9 @@ contract BatchVRFCoordinatorV2PlusTest is FixtureVRFCoordinatorV2_5 { // The payments are NOT pre-calculated and simply copied from the actual event. // We can assert and ignore the payment field but the code will be considerably longer. vm.expectEmit(true, true, false, true, address(s_coordinator)); - emit RandomWordsFulfilled(output.requestId, output.randomness, s_subId, 500000000000143283, true, true, false); + emit RandomWordsFulfilled(output.requestId, output.randomness, s_subId, 500000000000143261, true, true, false); vm.expectEmit(true, true, false, true, address(s_coordinator)); - emit RandomWordsFulfilled(output1.requestId, output1.randomness, s_subId, 800000000000306143, false, true, false); + emit RandomWordsFulfilled(output1.requestId, output1.randomness, s_subId, 800000000000312358, false, true, false); // Fulfill the requests. s_batchCoordinator.fulfillRandomWords(proofs, rcs); diff --git a/contracts/src/v0.8/vrf/test/VRFV2Plus.t.sol b/contracts/src/v0.8/vrf/test/VRFV2Plus.t.sol index 75a8d96927..dd3f54b580 100644 --- a/contracts/src/v0.8/vrf/test/VRFV2Plus.t.sol +++ b/contracts/src/v0.8/vrf/test/VRFV2Plus.t.sol @@ -513,26 +513,33 @@ contract VRFV2Plus is BaseTest { assertEq(fulfilled, false); assertTrue(s_testCoordinator.pendingRequestExists(subId)); - // Uncomment these console logs to see info about the request: - // console.log("requestId: ", requestId); - // console.log("preSeed: ", preSeed); - // console.log("sender: ", address(s_testConsumer)); - // Move on to the next block. // Store the previous block's blockhash, and assert that it is as expected. vm.roll(requestBlock + 1); s_bhs.store(requestBlock); - assertEq(hex"0000000000000000000000000000000000000000000000000000000000000014", s_bhs.getBlockhash(requestBlock)); + assertEq(hex"731dc163f73d31d8c68f9917ce4ff967753939f70432973c04fd2c2a48148607", s_bhs.getBlockhash(requestBlock)); // Fulfill the request. - // Proof generated via the generate-proof-v2-plus script command. Example usage: + // Proof generated via the generate-proof-v2-plus script command. + // 1st step: Uncomment these 3 console logs to see info about the request and run the test to get output: + // console.log("requestId: ", requestId); + // console.log("preSeed: ", preSeed); + // console.log("sender: ", address(s_testConsumer)); + // 2nd step: Update pre-seed in the command commented out below with new value printed in console logs. + // 3rd step: export the following environment variables to run the generate-proof-v2-plus script. + // export ETH_URL=https://ethereum-sepolia-rpc.publicnode.com # or any other RPC provider you prefer + // export ETH_CHAIN_ID=11155111 # or switch to any other chain + // export ACCOUNT_KEY= + // 4th step: run the command and copy the command output in the proof section below. /* + Run from this folder: chainlink/core/scripts/vrfv2plus/testnet go run . generate-proof-v2-plus \ -key-hash 0x9f2353bde94264dbc3d554a94cceba2d7d2b4fdce4304d3e09a1fea9fbeb1528 \ - -pre-seed 58424872742560034068603954318478134981993109073728628043159461959392650534066 \ - -block-hash 0x0000000000000000000000000000000000000000000000000000000000000014 \ + -pre-seed 77134414723242246520332717536018735794426514244521954002798799849127623496871 \ + -block-hash 0x731dc163f73d31d8c68f9917ce4ff967753939f70432973c04fd2c2a48148607 \ -block-num 20 \ - -sender 0x90A8820424CC8a819d14cBdE54D12fD3fbFa9bb2 + -sender 0x90A8820424CC8a819d14cBdE54D12fD3fbFa9bb2 \ + -native-payment false */ proof = VRF.Proof({ pk: [ @@ -540,22 +547,22 @@ contract VRFV2Plus is BaseTest { 62070622898698443831883535403436258712770888294397026493185421712108624767191 ], gamma: [ - 38041205470219573731614166317842050442610096576830191475863676359766283013831, - 31897503406364148988967447112698248795931483458172800286988696482435433838056 + 103927982338770370318312316555080928288985522873495041111817988974598585393796, + 56789421278806198480964888112155620425048056183534931202752833185923411715624 ], - c: 114706080610174375269579192101772790158458728655229562781479812703475130740224, - s: 91869928024010088265014058436030407245056128545665425448353233998362687232253, - seed: 58424872742560034068603954318478134981993109073728628043159461959392650534066, - uWitness: 0x1514536B09a51E671d070312bcD3653386d5a82b, + c: 23645475075665525321781505993434124657388421977074956645288621921391376468128, + s: 106817081950846808215350231311242951539230271757396902089035477907017240898689, + seed: 77134414723242246520332717536018735794426514244521954002798799849127623496871, + uWitness: 0xD6899602060d574DE03FE1cf76fDf66afE12d549, cGammaWitness: [ - 90605489216274499662544489893800286859751132311034850249229378789467669572783, - 76568417372883461229305641415175605031997103681542349721251313705711146936024 + 9892458071712426452033749279561067220589549155902380165087951541202159693388, + 61235995320721681444549354910430438435754757626312862714628885100042911955139 ], sHashWitness: [ - 43417948503950579681520475434461454031791886587406480417092620950034789197994, - 100772571879140362396088596211082924128900752544164141322636815729889228000249 + 101478618362722903511580105256015180591690884037598276249676652094434483808775, + 82512235485399822034680598942438982472006937353405384896956013889074719896188 ], - zInv: 82374292458278672300647114418593830323283909625362447038989596015264004164958 + zInv: 82281039329215616805111360985152709712368762415186906218863971780664103705723 }); rc = VRFTypes.RequestCommitmentV2Plus({ blockNum: requestBlock, @@ -602,24 +609,30 @@ contract VRFV2Plus is BaseTest { assertEq(fulfilled, false); assertTrue(s_testCoordinator.pendingRequestExists(subId)); - // Uncomment these console logs to see info about the request: - // console.log("requestId: ", requestId); - // console.log("preSeed: ", preSeed); - // console.log("sender: ", address(s_testConsumer)); - // Move on to the next block. // Store the previous block's blockhash, and assert that it is as expected. vm.roll(requestBlock + 1); s_bhs.store(requestBlock); - assertEq(hex"000000000000000000000000000000000000000000000000000000000000000a", s_bhs.getBlockhash(requestBlock)); + assertEq(hex"1a192fabce13988b84994d4296e6cdc418d55e2f1d7f942188d4040b94fc57ac", s_bhs.getBlockhash(requestBlock)); // Fulfill the request. - // Proof generated via the generate-proof-v2-plus script command. Example usage: + // Proof generated via the generate-proof-v2-plus script command. + // 1st step: Uncomment these 3 console logs to see info about the request and run the test to get output: + // console.log("requestId: ", requestId); + // console.log("preSeed: ", preSeed); + // console.log("sender: ", address(s_testConsumer)); + // 2nd step: Update pre-seed in the command commented out below with new value printed in console logs. + // 3rd step: export the following environment variables to run the generate-proof-v2-plus script. + // export ETH_URL=https://ethereum-sepolia-rpc.publicnode.com # or any other RPC provider you prefer + // export ETH_CHAIN_ID=11155111 # or switch to any other chain + // export ACCOUNT_KEY= + // 4th step: run the command and copy the command output in the proof section below. /* + Run from this folder: chainlink/core/scripts/vrfv2plus/testnet go run . generate-proof-v2-plus \ -key-hash 0x9f2353bde94264dbc3d554a94cceba2d7d2b4fdce4304d3e09a1fea9fbeb1528 \ - -pre-seed 83266692323404068105564931899467966321583332182309426611016082057597749986430 \ - -block-hash 0x000000000000000000000000000000000000000000000000000000000000000a \ + -pre-seed 88177119495082281213609405072572269421661478022189589823108119237563684383163 \ + -block-hash 0x1a192fabce13988b84994d4296e6cdc418d55e2f1d7f942188d4040b94fc57ac \ -block-num 10 \ -sender 0x90A8820424CC8a819d14cBdE54D12fD3fbFa9bb2 \ -native-payment true @@ -630,22 +643,22 @@ contract VRFV2Plus is BaseTest { 62070622898698443831883535403436258712770888294397026493185421712108624767191 ], gamma: [ - 47144451677122876068574640250190132179872561942855874114516471019540736524783, - 63001220656590641645486673489302242739512599229187442248048295264418080499391 + 102142782721757938350759722545721736888276217484353597703162772276193136052353, + 87167280284008869627768921028415708350806510214000539818296353518495698939660 ], - c: 42928477813589729783511577059394077774341588261592343937605454161333818133643, - s: 14447529458406454898597883219032514356523135029224613793880920230249515634875, - seed: 83266692323404068105564931899467966321583332182309426611016082057597749986430, - uWitness: 0x5Ed3bb2AA8EAFe168a23079644d5dfBf892B1038, + c: 78738462581063211677832865654743924688552792392007862664964608134754001810280, + s: 97066881804257970453329086439696419448135613089654606517271688187030953014593, + seed: 88177119495082281213609405072572269421661478022189589823108119237563684383163, + uWitness: 0xa335ea8dF652d5331a276B60b16c9733435D4f73, cGammaWitness: [ - 40742088032247467257043132769297935807697466810312051815364187117543257089153, - 110399474382135664619186049639190334359061769014381608543009407662815758204131 + 114435126227922602743444254494036972095649501991695809092954325430947992864624, + 63032211040463927862594425238691911311087931119674607521158894139074063158678 ], sHashWitness: [ - 26556776392895292893984393164594214244553035014769995354896600239759043777485, - 67126706735912782218279556535631175449291035782208850310724682668198932501077 + 105043781471073183057173130563345930784924139079040814418442661347864735908726, + 68696469914696211053833437482938344908217760552761185546164836556562945431554 ], - zInv: 88742453392918610091640193378775723954629905126315835248392650970979000380325 + zInv: 73325637847357165955904789471972164751975373195750497508525598331798833112175 }); rc = VRFTypes.RequestCommitmentV2Plus({ blockNum: requestBlock, @@ -750,26 +763,26 @@ contract VRFV2Plus is BaseTest { (bool fulfilled, , ) = s_testConsumer.s_requests(requestId); assertEq(fulfilled, true); - // The cost of fulfillRandomWords is approximately 86_700 gas. + // The cost of fulfillRandomWords is approximately 89_100 gas. // gasAfterPaymentCalculation is 50_000. // // The cost of the VRF fulfillment charged to the user is: // paymentNoFee = (weiPerUnitGas * (gasAfterPaymentCalculation + startGas - gasleft() + l1CostWei) / link_native_ratio) // network gas price is capped at gas lane max gas (5000 gwei) - // paymentNoFee = (5e12 * (50_000 + 86_700 + 0)) / .5 - // paymentNoFee = 1.367e+18 + // paymentNoFee = (5e12 * (50_000 + 89_100 + 0)) / .5 + // paymentNoFee = 1.391e+18 // flatFeeWei = 1e12 * (fulfillmentFlatFeeNativePPM - fulfillmentFlatFeeLinkDiscountPPM) // flatFeeWei = 1e12 * (500_000 - 100_000) // flatFeeJuels = 1e18 * flatFeeWei / link_native_ratio // flatFeeJuels = 4e17 / 0.5 = 8e17 // billed_fee = paymentNoFee * (10 / 100) + 8e17 - // billed_fee = 1.367e+18 * 0.1 + 8e17 - // billed_fee = 9.367e+17 + // billed_fee = 1.391e+18 * 0.1 + 8e17 + // billed_fee = 9.391e+17 // note: delta is doubled from the native test to account for more variance due to the link/native ratio (uint96 linkBalanceAfter, , , , ) = s_testCoordinator.getSubscription(subId); // 1e15 is less than 1 percent discrepancy - assertApproxEqAbs(payment, 9.367 * 1e17, 1e15); - assertApproxEqAbs(linkBalanceAfter, linkBalanceBefore - 9.367 * 1e17, 1e15); + assertApproxEqAbs(payment, 9.391 * 1e17, 1e15); + assertApproxEqAbs(linkBalanceAfter, linkBalanceBefore - 9.391 * 1e17, 1e15); assertFalse(s_testCoordinator.pendingRequestExists(subId)); } @@ -834,24 +847,30 @@ contract VRFV2Plus is BaseTest { ); assertTrue(s_testCoordinator.pendingRequestExists(subId)); - // 3. Fulfill the request above - //console.log("requestId: ", requestId); - //console.log("preSeed: ", preSeed); - //console.log("sender: ", address(consumer)); - // Move on to the next block. // Store the previous block's blockhash, and assert that it is as expected. vm.roll(requestBlock + 1); s_bhs.store(requestBlock); - assertEq(hex"000000000000000000000000000000000000000000000000000000000000000a", s_bhs.getBlockhash(requestBlock)); + assertEq(hex"1a192fabce13988b84994d4296e6cdc418d55e2f1d7f942188d4040b94fc57ac", s_bhs.getBlockhash(requestBlock)); - // Fulfill the request. - // Proof generated via the generate-proof-v2-plus script command. Example usage: + // 3. Fulfill the request above + // Proof generated via the generate-proof-v2-plus script command. + // 1st step: Uncomment these 3 console logs to see info about the request and run the test to get output: + // console.log("requestId: ", requestId); + // console.log("preSeed: ", preSeed); + // console.log("sender: ", address(s_testConsumer)); + // 2nd step: Update pre-seed in the command commented out below with new value printed in console logs. + // 3rd step: export the following environment variables to run the generate-proof-v2-plus script. + // export ETH_URL=https://ethereum-sepolia-rpc.publicnode.com # or any other RPC provider you prefer + // export ETH_CHAIN_ID=11155111 # or switch to any other chain + // export ACCOUNT_KEY= + // 4th step: run the command and copy the command output in the proof section below. /* + Run from this folder: chainlink/core/scripts/vrfv2plus/testnet go run . generate-proof-v2-plus \ -key-hash 0x9f2353bde94264dbc3d554a94cceba2d7d2b4fdce4304d3e09a1fea9fbeb1528 \ - -pre-seed 94043941380654896554739370173616551044559721638888689173752661912204412136884 \ - -block-hash 0x000000000000000000000000000000000000000000000000000000000000000a \ + -pre-seed 78857362017365444144484359594634073685493503942324326290718892836953423263381 \ + -block-hash 0x1a192fabce13988b84994d4296e6cdc418d55e2f1d7f942188d4040b94fc57ac \ -block-num 10 \ -sender 0x44CAfC03154A0708F9DCf988681821f648dA74aF \ -native-payment true @@ -862,22 +881,22 @@ contract VRFV2Plus is BaseTest { 62070622898698443831883535403436258712770888294397026493185421712108624767191 ], gamma: [ - 18593555375562408458806406536059989757338587469093035962641476877033456068708, - 55675218112764789548330682504442195066741636758414578491295297591596761905475 + 65913937398148449626792563067325648649534055460473988721938103219381973178278, + 63156327344180203180831822252171874192175272818200597638000091892096122362120 ], - c: 56595337384472359782910435918403237878894172750128610188222417200315739516270, - s: 60666722370046279064490737533582002977678558769715798604164042022636022215663, - seed: 94043941380654896554739370173616551044559721638888689173752661912204412136884, - uWitness: 0xEdbE15fd105cfEFb9CCcbBD84403d1F62719E50d, + c: 96524997218413735279221574381819903278651909890109201564980667824986706861580, + s: 32941032142956097592442894642111025677491308239274769364799856748447418202313, + seed: 78857362017365444144484359594634073685493503942324326290718892836953423263381, + uWitness: 0xda613621Dc2347d9A6670a1cBA812d52A7ec3A3A, cGammaWitness: [ - 11752391553651713021860307604522059957920042356542944931263270793211985356642, - 14713353048309058367510422609936133400473710094544154206129568172815229277104 + 6776842114900054689355891239487365968068230823400902903493665825747641410781, + 753482930067864853610521010650481816782338376846697006021590704037205560592 ], sHashWitness: [ - 109716108880570827107616596438987062129934448629902940427517663799192095060206, - 79378277044196229730810703755304140279837983575681427317104232794580059801930 + 76619528582417858778905184311764104068650968652636772643050945629834129417915, + 27947566794040118487986033070014357750801611688958204148187927873566412002355 ], - zInv: 18898957977631212231148068121702167284572066246731769473720131179584458697812 + zInv: 77351076831418813780936064446565588198113457019145030499544500588309236458362 }); VRFTypes.RequestCommitmentV2Plus memory rc = VRFTypes.RequestCommitmentV2Plus({ blockNum: requestBlock, @@ -988,20 +1007,26 @@ contract VRFV2Plus is BaseTest { // Store the previous block's blockhash, and assert that it is as expected. vm.roll(requestBlock + 1); s_bhs.store(requestBlock); - assertEq(hex"000000000000000000000000000000000000000000000000000000000000000a", s_bhs.getBlockhash(requestBlock)); + assertEq(hex"1a192fabce13988b84994d4296e6cdc418d55e2f1d7f942188d4040b94fc57ac", s_bhs.getBlockhash(requestBlock)); // 3. Fulfill the 1st request above - console.log("requestId: ", requestId1); - console.log("preSeed: ", preSeed1); - console.log("sender: ", address(consumer1)); - - // Fulfill the request. - // Proof generated via the generate-proof-v2-plus script command. Example usage: + // Proof generated via the generate-proof-v2-plus script command. + // 1st step: Uncomment these 3 console logs to see info about the request and run the test to get output: + // console.log("requestId: ", requestId); + // console.log("preSeed: ", preSeed); + // console.log("sender: ", address(s_testConsumer)); + // 2nd step: Update pre-seed in the command commented out below with new value printed in console logs. + // 3rd step: export the following environment variables to run the generate-proof-v2-plus script. + // export ETH_URL=https://ethereum-sepolia-rpc.publicnode.com # or any other RPC provider you prefer + // export ETH_CHAIN_ID=11155111 # or switch to any other chain + // export ACCOUNT_KEY= + // 4th step: run the command and copy the command output in the proof section below. /* + Run from this folder: chainlink/core/scripts/vrfv2plus/testnet go run . generate-proof-v2-plus \ -key-hash 0x9f2353bde94264dbc3d554a94cceba2d7d2b4fdce4304d3e09a1fea9fbeb1528 \ - -pre-seed 94043941380654896554739370173616551044559721638888689173752661912204412136884 \ - -block-hash 0x000000000000000000000000000000000000000000000000000000000000000a \ + -pre-seed 78857362017365444144484359594634073685493503942324326290718892836953423263381 \ + -block-hash 0x1a192fabce13988b84994d4296e6cdc418d55e2f1d7f942188d4040b94fc57ac \ -block-num 10 \ -sender 0x44CAfC03154A0708F9DCf988681821f648dA74aF \ -native-payment true @@ -1012,22 +1037,22 @@ contract VRFV2Plus is BaseTest { 62070622898698443831883535403436258712770888294397026493185421712108624767191 ], gamma: [ - 18593555375562408458806406536059989757338587469093035962641476877033456068708, - 55675218112764789548330682504442195066741636758414578491295297591596761905475 + 65913937398148449626792563067325648649534055460473988721938103219381973178278, + 63156327344180203180831822252171874192175272818200597638000091892096122362120 ], - c: 56595337384472359782910435918403237878894172750128610188222417200315739516270, - s: 60666722370046279064490737533582002977678558769715798604164042022636022215663, - seed: 94043941380654896554739370173616551044559721638888689173752661912204412136884, - uWitness: 0xEdbE15fd105cfEFb9CCcbBD84403d1F62719E50d, + c: 103296526941774692908067234360350834482645116475454593803823148315342533216203, + s: 50291245814080656739779812653411869801334231723444391096753849942661931376590, + seed: 78857362017365444144484359594634073685493503942324326290718892836953423263381, + uWitness: 0x38500711AdcB471ac1A566c4b915759eb9cBCE2F, cGammaWitness: [ - 11752391553651713021860307604522059957920042356542944931263270793211985356642, - 14713353048309058367510422609936133400473710094544154206129568172815229277104 + 56476970720509547210740928951846471668018949971632948991136782499758110143588, + 44326075300781389077656415325167171692706436527877070415603658305817367373598 ], sHashWitness: [ - 109716108880570827107616596438987062129934448629902940427517663799192095060206, - 79378277044196229730810703755304140279837983575681427317104232794580059801930 + 109524696164787283409393383708118913934136014139634321235031691839206768278439, + 52690039857779635909051684567562068782378693408005554345469129234366171822741 ], - zInv: 18898957977631212231148068121702167284572066246731769473720131179584458697812 + zInv: 108537983043800425266290112227943788107669768716438017124275578856644517258573 }); VRFTypes.RequestCommitmentV2Plus memory rc = VRFTypes.RequestCommitmentV2Plus({ blockNum: requestBlock, @@ -1040,18 +1065,24 @@ contract VRFV2Plus is BaseTest { s_testCoordinator.fulfillRandomWords(proof, rc, true /* onlyPremium */); assertTrue(s_testCoordinator.pendingRequestExists(subId)); - //4. Fulfill the 2nd request - console.log("requestId: ", requestId2); - console.log("preSeed: ", preSeed2); - console.log("sender: ", address(consumer2)); - - // Fulfill the request. - // Proof generated via the generate-proof-v2-plus script command. Example usage: + // 4. Fulfill the 2nd request + // Proof generated via the generate-proof-v2-plus script command. + // 1st step: Uncomment these 3 console logs to see info about the request and run the test to get output: + // console.log("requestId: ", requestId); + // console.log("preSeed: ", preSeed); + // console.log("sender: ", address(s_testConsumer)); + // 2nd step: Update pre-seed in the command commented out below with new value printed in console logs. + // 3rd step: export the following environment variables to run the generate-proof-v2-plus script. + // export ETH_URL=https://ethereum-sepolia-rpc.publicnode.com # or any other RPC provider you prefer + // export ETH_CHAIN_ID=11155111 # or switch to any other chain + // export ACCOUNT_KEY= + // 4th step: run the command and copy the command output in the proof section below. /* + Run from this folder: chainlink/core/scripts/vrfv2plus/testnet go run . generate-proof-v2-plus \ -key-hash 0x9f2353bde94264dbc3d554a94cceba2d7d2b4fdce4304d3e09a1fea9fbeb1528 \ - -pre-seed 60086281972849674111646805013521068579710860774417505336898013292594859262126 \ - -block-hash 0x000000000000000000000000000000000000000000000000000000000000000a \ + -pre-seed 53330100288105770463016865504321558518073051667771993294213115153676065708950 \ + -block-hash 0x1a192fabce13988b84994d4296e6cdc418d55e2f1d7f942188d4040b94fc57ac \ -block-num 10 \ -sender 0xf5a165378E120f93784395aDF1E08a437e902865 \ -native-payment true @@ -1062,22 +1093,22 @@ contract VRFV2Plus is BaseTest { 62070622898698443831883535403436258712770888294397026493185421712108624767191 ], gamma: [ - 8781676794493524976318989249067879326013864868749595045909181134740761572122, - 70144896394968351242907510966944756907625107566821127114847472296460405612124 + 7260273098301741284457725182313945178888499328441106869722941415453613782770, + 91648498042618923465107471165504200585847250228048015102713552756245653299952 ], - c: 67847193668837615807355025316836592349514589069599294392546721746916067719949, - s: 114946531382736685625345450298146929067341928840493664822961336014597880904075, - seed: 60086281972849674111646805013521068579710860774417505336898013292594859262126, - uWitness: 0xe1de4fD69277D0C5516cAE4d760b1d08BC340A28, + c: 64987886290696558870328339791409334400119338012796549091587853494368167422332, + s: 69469162696695326295567645789624554797683340898724555794078876350372084267572, + seed: 53330100288105770463016865504321558518073051667771993294213115153676065708950, + uWitness: 0xa6ce21aD47eC5E90Ac7a2c6152D9710234Afe8ab, cGammaWitness: [ - 90301582727701442026215692513959255065128476395727596945643431833363167168678, - 61501369717028493801369453424028509804064958915788808540582630993703331669978 + 57318358662553647785891634403735348577492991113152343207139729697842283565417, + 57942043484796308689103390068712967247519265087617809262260051163954389512396 ], sHashWitness: [ - 98738650825542176387169085844714248077697103572877410412808249468787326424906, - 85647963391545223707301702874240345890884970941786094239896961457539737216630 + 113345999157319332195230171660555736547709417795439282230372737104445523493539, + 113358219039155973560933190466797830695088313506343976960055230355894888727567 ], - zInv: 29080001901010358083725892808339807464533563010468652346220922643802059192842 + zInv: 68349552569605209428774574139615352877146713490794995768725549089572297658255 }); rc = VRFTypes.RequestCommitmentV2Plus({ blockNum: requestBlock, diff --git a/core/scripts/vrfv2plus/testnet/proofs.go b/core/scripts/vrfv2plus/testnet/proofs.go index 23ddc8ecfd..ea6943c63f 100644 --- a/core/scripts/vrfv2plus/testnet/proofs.go +++ b/core/scripts/vrfv2plus/testnet/proofs.go @@ -54,7 +54,7 @@ var rcTemplate = `{ ` func generateProofForV2Plus(e helpers.Environment) { - deployCmd := flag.NewFlagSet("generate-proof", flag.ExitOnError) + deployCmd := flag.NewFlagSet("generate-proof-v2-plus", flag.ExitOnError) keyHashString := deployCmd.String("key-hash", "", "key hash for VRF request") preSeedString := deployCmd.String("pre-seed", "", "pre-seed for VRF request") From 5c0514ff40f14ed3337f98f5b0a36aba1691b51f Mon Sep 17 00:00:00 2001 From: Rens Rooimans Date: Thu, 29 Aug 2024 16:23:49 +0200 Subject: [PATCH 055/115] pnpm i && snapshot && forge fmt --- contracts/gas-snapshots/ccip.gas-snapshot | 1219 +++++++++-------- .../gas-snapshots/functions.gas-snapshot | 234 ++-- contracts/gas-snapshots/keystone.gas-snapshot | 167 ++- .../gas-snapshots/llo-feeds.gas-snapshot | 244 ---- contracts/gas-snapshots/shared.gas-snapshot | 4 +- contracts/pnpm-lock.yaml | 352 +++++ contracts/src/v0.8/ccip/FeeQuoter.sol | 35 +- .../v0.8/ccip/MultiAggregateRateLimiter.sol | 8 +- contracts/src/v0.8/ccip/RMN.sol | 12 +- .../ccip/applications/CCIPClientExample.sol | 10 +- .../ccip/applications/DefensiveExample.sol | 17 +- .../ccip/applications/EtherSenderReceiver.sol | 8 +- .../v0.8/ccip/applications/PingPongDemo.sol | 2 +- .../src/v0.8/ccip/capability/CCIPConfig.sol | 4 +- contracts/src/v0.8/ccip/interfaces/IPool.sol | 12 +- .../v0.8/ccip/interfaces/IPriceRegistry.sol | 7 +- .../src/v0.8/ccip/onRamp/EVM2EVMOnRamp.sol | 8 +- contracts/src/v0.8/ccip/onRamp/OnRamp.sol | 8 +- .../ccip/pools/BurnMintTokenPoolAbstract.sol | 18 +- .../ccip/pools/BurnMintTokenPoolAndProxy.sol | 18 +- .../BurnWithFromMintTokenPoolAndProxy.sol | 18 +- .../v0.8/ccip/pools/LockReleaseTokenPool.sol | 18 +- .../pools/LockReleaseTokenPoolAndProxy.sol | 18 +- contracts/src/v0.8/ccip/pools/TokenPool.sol | 16 +- .../USDC/HybridLockReleaseUSDCTokenPool.sol | 34 +- .../v0.8/ccip/pools/USDC/USDCTokenPool.sol | 18 +- .../src/v0.8/ccip/test/NonceManager.t.sol | 8 +- .../onRamp/ReentrantMaliciousTokenPool.sol | 17 +- .../ccip/test/capability/CCIPConfig.t.sol | 7 +- .../v0.8/ccip/test/feeQuoter/FeeQuoter.t.sol | 6 +- .../test/helpers/BurnMintMultiTokenPool.sol | 18 +- .../ccip/test/helpers/CCIPConfigHelper.sol | 4 +- .../MaybeRevertingBurnMintTokenPool.sol | 18 +- .../v0.8/ccip/test/helpers/MessageHasher.sol | 8 +- .../ccip/test/helpers/TokenPoolHelper.sol | 18 +- .../helpers/receivers/ReentrancyAbuser.sol | 8 +- .../ccip/test/legacy/BurnMintTokenPool1_4.sol | 16 +- .../test/offRamp/EVM2EVMOffRampSetup.t.sol | 40 +- .../src/v0.8/ccip/test/offRamp/OffRamp.t.sol | 6 +- .../v0.8/ccip/test/offRamp/OffRampSetup.t.sol | 24 +- .../v0.8/ccip/test/pools/USDCTokenPool.t.sol | 8 +- .../MultiAggregateRateLimiter.t.sol | 16 +- 42 files changed, 1375 insertions(+), 1356 deletions(-) diff --git a/contracts/gas-snapshots/ccip.gas-snapshot b/contracts/gas-snapshots/ccip.gas-snapshot index eb96103c40..1658bd8dcb 100644 --- a/contracts/gas-snapshots/ccip.gas-snapshot +++ b/contracts/gas-snapshots/ccip.gas-snapshot @@ -10,8 +10,8 @@ AggregateTokenLimiter_getTokenBucket:test_GetTokenBucket_Success() (gas: 19691) AggregateTokenLimiter_getTokenBucket:test_Refill_Success() (gas: 40911) AggregateTokenLimiter_getTokenBucket:test_TimeUnderflow_Revert() (gas: 15368) AggregateTokenLimiter_getTokenLimitAdmin:test_GetTokenLimitAdmin_Success() (gas: 10531) -AggregateTokenLimiter_getTokenValue:test_GetTokenValue_Success() (gas: 19696) -AggregateTokenLimiter_getTokenValue:test_NoTokenPrice_Reverts() (gas: 21281) +AggregateTokenLimiter_getTokenValue:test_GetTokenValue_Success() (gas: 19668) +AggregateTokenLimiter_getTokenValue:test_NoTokenPrice_Reverts() (gas: 21253) AggregateTokenLimiter_rateLimitValue:test_AggregateValueMaxCapacityExceeded_Revert() (gas: 16418) AggregateTokenLimiter_rateLimitValue:test_RateLimitValueSuccess_gas() (gas: 18306) AggregateTokenLimiter_setAdmin:test_OnlyOwnerOrAdmin_Revert() (gas: 13047) @@ -19,59 +19,62 @@ AggregateTokenLimiter_setAdmin:test_Owner_Success() (gas: 18989) AggregateTokenLimiter_setRateLimiterConfig:test_OnlyOnlyCallableByAdminOrOwner_Revert() (gas: 17479) AggregateTokenLimiter_setRateLimiterConfig:test_Owner_Success() (gas: 30062) AggregateTokenLimiter_setRateLimiterConfig:test_TokenLimitAdmin_Success() (gas: 32071) -BurnFromMintTokenPool_lockOrBurn:test_ChainNotAllowed_Revert() (gas: 28675) -BurnFromMintTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 55158) -BurnFromMintTokenPool_lockOrBurn:test_PoolBurn_Success() (gas: 243525) -BurnFromMintTokenPool_lockOrBurn:test_Setup_Success() (gas: 23907) -BurnMintTokenPool_lockOrBurn:test_ChainNotAllowed_Revert() (gas: 27565) -BurnMintTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 55158) -BurnMintTokenPool_lockOrBurn:test_PoolBurn_Success() (gas: 241416) -BurnMintTokenPool_lockOrBurn:test_Setup_Success() (gas: 17633) -BurnMintTokenPool_releaseOrMint:test_ChainNotAllowed_Revert() (gas: 28537) -BurnMintTokenPool_releaseOrMint:test_PoolMintNotHealthy_Revert() (gas: 55991) -BurnMintTokenPool_releaseOrMint:test_PoolMint_Success() (gas: 110657) -BurnWithFromMintTokenPool_lockOrBurn:test_ChainNotAllowed_Revert() (gas: 28675) -BurnWithFromMintTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 55158) -BurnWithFromMintTokenPool_lockOrBurn:test_PoolBurn_Success() (gas: 243552) -BurnWithFromMintTokenPool_lockOrBurn:test_Setup_Success() (gas: 24260) -CCIPClientExample_sanity:test_ImmutableExamples_Success() (gas: 2131281) -CCIPConfigSetup:test_getCapabilityConfiguration_Success() (gas: 9495) -CCIPConfig_ConfigStateMachine:test__computeConfigDigest_Success() (gas: 70755) -CCIPConfig_ConfigStateMachine:test__computeNewConfigWithMeta_InitToRunning_Success() (gas: 363647) -CCIPConfig_ConfigStateMachine:test__computeNewConfigWithMeta_RunningToStaging_Success() (gas: 488774) -CCIPConfig_ConfigStateMachine:test__computeNewConfigWithMeta_StagingToRunning_Success() (gas: 453384) -CCIPConfig_ConfigStateMachine:test__groupByPluginType_TooManyOCR3Configs_Reverts() (gas: 37027) -CCIPConfig_ConfigStateMachine:test__groupByPluginType_threeCommitConfigs_Reverts() (gas: 61043) -CCIPConfig_ConfigStateMachine:test__groupByPluginType_threeExecutionConfigs_Reverts() (gas: 60963) -CCIPConfig_ConfigStateMachine:test__stateFromConfigLength_Success() (gas: 11764) -CCIPConfig_ConfigStateMachine:test__validateConfigStateTransition_Success() (gas: 8765) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_InitToRunning_Success() (gas: 311991) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_InitToRunning_WrongConfigCount_Reverts() (gas: 49663) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_NonExistentConfigTransition_Reverts() (gas: 32275) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_RunningToStaging_Success() (gas: 376576) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_RunningToStaging_WrongConfigCount_Reverts() (gas: 120943) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_RunningToStaging_WrongConfigDigestBlueGreen_Reverts() (gas: 157105) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_StagingToRunning_Success() (gas: 376352) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_StagingToRunning_WrongConfigDigest_Reverts() (gas: 157172) -CCIPConfig_ConfigStateMachine:test_getCapabilityConfiguration_Success() (gas: 9583) -CCIPConfig__updatePluginConfig:test__updatePluginConfig_InitToRunning_Success() (gas: 1057393) -CCIPConfig__updatePluginConfig:test__updatePluginConfig_InvalidConfigLength_Reverts() (gas: 27539) -CCIPConfig__updatePluginConfig:test__updatePluginConfig_InvalidConfigStateTransition_Reverts() (gas: 23105) -CCIPConfig__updatePluginConfig:test__updatePluginConfig_RunningToStaging_Success() (gas: 2009309) -CCIPConfig__updatePluginConfig:test__updatePluginConfig_StagingToRunning_Success() (gas: 2616177) -CCIPConfig__updatePluginConfig:test_getCapabilityConfiguration_Success() (gas: 9583) -CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_CommitAndExecConfig_Success() (gas: 1851188) -CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_CommitConfigOnly_Success() (gas: 1068362) -CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_ExecConfigOnly_Success() (gas: 1068393) +BurnFromMintTokenPool_lockOrBurn:test_ChainNotAllowed_Revert() (gas: 28761) +BurnFromMintTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 55115) +BurnFromMintTokenPool_lockOrBurn:test_PoolBurn_Success() (gas: 243491) +BurnFromMintTokenPool_lockOrBurn:test_Setup_Success() (gas: 23947) +BurnMintTokenPool_lockOrBurn:test_ChainNotAllowed_Revert() (gas: 27522) +BurnMintTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 55115) +BurnMintTokenPool_lockOrBurn:test_PoolBurn_Success() (gas: 241381) +BurnMintTokenPool_lockOrBurn:test_Setup_Success() (gas: 17677) +BurnMintTokenPool_releaseOrMint:test_ChainNotAllowed_Revert() (gas: 28757) +BurnMintTokenPool_releaseOrMint:test_PoolMintNotHealthy_Revert() (gas: 56190) +BurnMintTokenPool_releaseOrMint:test_PoolMint_Success() (gas: 112319) +BurnWithFromMintTokenPool_lockOrBurn:test_ChainNotAllowed_Revert() (gas: 28761) +BurnWithFromMintTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 55115) +BurnWithFromMintTokenPool_lockOrBurn:test_PoolBurn_Success() (gas: 243517) +BurnWithFromMintTokenPool_lockOrBurn:test_Setup_Success() (gas: 23951) +CCIPClientExample_sanity:test_ImmutableExamples_Success() (gas: 2132684) +CCIPConfigSetup:test_getCapabilityConfiguration_Success() (gas: 9517) +CCIPConfig_ConfigStateMachine:test__computeConfigDigest_Success() (gas: 70831) +CCIPConfig_ConfigStateMachine:test__computeNewConfigWithMeta_InitToRunning_Success() (gas: 363664) +CCIPConfig_ConfigStateMachine:test__computeNewConfigWithMeta_RunningToStaging_Success() (gas: 488826) +CCIPConfig_ConfigStateMachine:test__computeNewConfigWithMeta_StagingToRunning_Success() (gas: 453439) +CCIPConfig_ConfigStateMachine:test__groupByPluginType_TooManyOCR3Configs_Reverts() (gas: 37049) +CCIPConfig_ConfigStateMachine:test__groupByPluginType_threeCommitConfigs_Reverts() (gas: 61065) +CCIPConfig_ConfigStateMachine:test__groupByPluginType_threeExecutionConfigs_Reverts() (gas: 60985) +CCIPConfig_ConfigStateMachine:test__stateFromConfigLength_Success() (gas: 11635) +CCIPConfig_ConfigStateMachine:test__validateConfigStateTransition_Success() (gas: 8831) +CCIPConfig_ConfigStateMachine:test__validateConfigTransition_InitToRunning_Success() (gas: 312055) +CCIPConfig_ConfigStateMachine:test__validateConfigTransition_InitToRunning_WrongConfigCount_Reverts() (gas: 49727) +CCIPConfig_ConfigStateMachine:test__validateConfigTransition_NonExistentConfigTransition_Reverts() (gas: 32320) +CCIPConfig_ConfigStateMachine:test__validateConfigTransition_RunningToStaging_Success() (gas: 376678) +CCIPConfig_ConfigStateMachine:test__validateConfigTransition_RunningToStaging_WrongConfigCount_Reverts() (gas: 121045) +CCIPConfig_ConfigStateMachine:test__validateConfigTransition_RunningToStaging_WrongConfigDigestBlueGreen_Reverts() (gas: 157245) +CCIPConfig_ConfigStateMachine:test__validateConfigTransition_StagingToRunning_Success() (gas: 376454) +CCIPConfig_ConfigStateMachine:test__validateConfigTransition_StagingToRunning_WrongConfigDigest_Reverts() (gas: 157312) +CCIPConfig_ConfigStateMachine:test_getCapabilityConfiguration_Success() (gas: 9605) +CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_CommitAndExecConfig_Success() (gas: 1851094) +CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_CommitConfigOnly_Success() (gas: 1068315) +CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_ExecConfigOnly_Success() (gas: 1068346) CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_OnlyCapabilitiesRegistryCanCall_Reverts() (gas: 9599) CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_ZeroLengthConfig_Success() (gas: 16070) -CCIPConfig_beforeCapabilityConfigSet:test_getCapabilityConfiguration_Success() (gas: 9583) +CCIPConfig_beforeCapabilityConfigSet:test_getCapabilityConfiguration_Success() (gas: 9605) CCIPConfig_chainConfig:test__applyChainConfigUpdates_FChainNotPositive_Reverts() (gas: 184703) -CCIPConfig_chainConfig:test_applyChainConfigUpdates_addChainConfigs_Success() (gas: 344332) +CCIPConfig_chainConfig:test_applyChainConfigUpdates_addChainConfigs_Success() (gas: 344881) CCIPConfig_chainConfig:test_applyChainConfigUpdates_nodeNotInRegistry_Reverts() (gas: 20258) CCIPConfig_chainConfig:test_applyChainConfigUpdates_removeChainConfigs_Success() (gas: 267558) CCIPConfig_chainConfig:test_applyChainConfigUpdates_selectorNotFound_Reverts() (gas: 14829) CCIPConfig_chainConfig:test_getCapabilityConfiguration_Success() (gas: 9626) +CCIPConfig_chainConfig:test_getPaginatedCCIPConfigs_Success() (gas: 370235) +CCIPConfig_constructor:test_constructor_Success() (gas: 3612901) +CCIPConfig_constructor:test_constructor_ZeroAddressNotAllowed_Revert() (gas: 61777) +CCIPConfig_updatePluginConfig:test__updatePluginConfig_InitToRunning_Success() (gas: 1057368) +CCIPConfig_updatePluginConfig:test__updatePluginConfig_InvalidConfigLength_Reverts() (gas: 27561) +CCIPConfig_updatePluginConfig:test__updatePluginConfig_InvalidConfigStateTransition_Reverts() (gas: 23127) +CCIPConfig_updatePluginConfig:test__updatePluginConfig_RunningToStaging_Success() (gas: 2009285) +CCIPConfig_updatePluginConfig:test__updatePluginConfig_StagingToRunning_Success() (gas: 2616133) +CCIPConfig_updatePluginConfig:test_getCapabilityConfiguration_Success() (gas: 9605) CCIPConfig_validateConfig:test__validateConfig_BootstrapP2PIdsHasDuplicates_Reverts() (gas: 294893) CCIPConfig_validateConfig:test__validateConfig_BootstrapP2PIdsNotASubsetOfP2PIds_Reverts() (gas: 298325) CCIPConfig_validateConfig:test__validateConfig_BootstrapP2PIdsNotSorted_Reverts() (gas: 295038) @@ -89,22 +92,22 @@ CCIPConfig_validateConfig:test__validateConfig_Success() (gas: 302186) CCIPConfig_validateConfig:test__validateConfig_TooManyBootstrapP2PIds_Reverts() (gas: 294539) CCIPConfig_validateConfig:test__validateConfig_TooManySigners_Reverts() (gas: 1215861) CCIPConfig_validateConfig:test__validateConfig_TooManyTransmitters_Reverts() (gas: 1214264) -CCIPConfig_validateConfig:test_getCapabilityConfiguration_Success() (gas: 9562) +CCIPConfig_validateConfig:test_getCapabilityConfiguration_Success() (gas: 9584) CommitStore_constructor:test_Constructor_Success() (gas: 3091326) CommitStore_isUnpausedAndRMNHealthy:test_RMN_Success() (gas: 73420) CommitStore_report:test_InvalidIntervalMinLargerThanMax_Revert() (gas: 28670) CommitStore_report:test_InvalidInterval_Revert() (gas: 28610) CommitStore_report:test_InvalidRootRevert() (gas: 27843) -CommitStore_report:test_OnlyGasPriceUpdates_Success() (gas: 53253) -CommitStore_report:test_OnlyPriceUpdateStaleReport_Revert() (gas: 59049) -CommitStore_report:test_OnlyTokenPriceUpdates_Success() (gas: 53251) +CommitStore_report:test_OnlyGasPriceUpdates_Success() (gas: 53275) +CommitStore_report:test_OnlyPriceUpdateStaleReport_Revert() (gas: 59071) +CommitStore_report:test_OnlyTokenPriceUpdates_Success() (gas: 53273) CommitStore_report:test_Paused_Revert() (gas: 21259) -CommitStore_report:test_ReportAndPriceUpdate_Success() (gas: 84242) +CommitStore_report:test_ReportAndPriceUpdate_Success() (gas: 84264) CommitStore_report:test_ReportOnlyRootSuccess_gas() (gas: 56249) CommitStore_report:test_RootAlreadyCommitted_Revert() (gas: 63969) -CommitStore_report:test_StaleReportWithRoot_Success() (gas: 119420) +CommitStore_report:test_StaleReportWithRoot_Success() (gas: 119364) CommitStore_report:test_Unhealthy_Revert() (gas: 44751) -CommitStore_report:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 100758) +CommitStore_report:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 100752) CommitStore_report:test_ZeroEpochAndRound_Revert() (gas: 27626) CommitStore_resetUnblessedRoots:test_OnlyOwner_Revert() (gas: 11325) CommitStore_resetUnblessedRoots:test_ResetUnblessedRoots_Success() (gas: 143718) @@ -119,345 +122,189 @@ CommitStore_verify:test_NotBlessed_Success() (gas: 61374) CommitStore_verify:test_Paused_Revert() (gas: 18496) CommitStore_verify:test_TooManyLeaves_Revert() (gas: 36785) DefensiveExampleTest:test_HappyPath_Success() (gas: 200018) -DefensiveExampleTest:test_Recovery() (gas: 424253) -E2E:test_E2E_3MessagesSuccess_gas() (gas: 1100092) -EVM2EVMMultiOffRamp__releaseOrMintSingleToken:test__releaseOrMintSingleToken_NotACompatiblePool_Revert() (gas: 38157) -EVM2EVMMultiOffRamp__releaseOrMintSingleToken:test__releaseOrMintSingleToken_Success() (gas: 108343) -EVM2EVMMultiOffRamp__releaseOrMintSingleToken:test__releaseOrMintSingleToken_TokenHandlingError_revert_Revert() (gas: 116811) -EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_AddMultipleChains_Success() (gas: 460560) -EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_AddNewChain_Success() (gas: 95542) -EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ApplyZeroUpdates_Success() (gas: 12463) -EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChainOnRamp_Revert() (gas: 90385) -EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChain_Success() (gas: 105586) -EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ZeroOnRampAddress_Revert() (gas: 15719) -EVM2EVMMultiOffRamp_applySourceChainConfigUpdates:test_ZeroSourceChainSelector_Revert() (gas: 13057) -EVM2EVMMultiOffRamp_batchExecute:test_MultipleReportsDifferentChains_Success() (gas: 298564) -EVM2EVMMultiOffRamp_batchExecute:test_MultipleReportsSameChain_Success() (gas: 239899) -EVM2EVMMultiOffRamp_batchExecute:test_MultipleReportsSkipDuplicate_Success() (gas: 158863) -EVM2EVMMultiOffRamp_batchExecute:test_OutOfBoundsGasLimitsAccess_Revert() (gas: 189303) -EVM2EVMMultiOffRamp_batchExecute:test_SingleReport_Success() (gas: 147582) -EVM2EVMMultiOffRamp_batchExecute:test_Unhealthy_Revert() (gas: 521508) -EVM2EVMMultiOffRamp_batchExecute:test_ZeroReports_Revert() (gas: 10459) -EVM2EVMMultiOffRamp_ccipReceive:test_Reverts() (gas: 15662) -EVM2EVMMultiOffRamp_commit:test_InvalidIntervalMinLargerThanMax_Revert() (gas: 67195) -EVM2EVMMultiOffRamp_commit:test_InvalidInterval_Revert() (gas: 59698) -EVM2EVMMultiOffRamp_commit:test_InvalidRootRevert() (gas: 58778) -EVM2EVMMultiOffRamp_commit:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6394741) -EVM2EVMMultiOffRamp_commit:test_NoConfig_Revert() (gas: 5977968) -EVM2EVMMultiOffRamp_commit:test_OnlyGasPriceUpdates_Success() (gas: 106229) -EVM2EVMMultiOffRamp_commit:test_OnlyPriceUpdateStaleReport_Revert() (gas: 116228) -EVM2EVMMultiOffRamp_commit:test_OnlyTokenPriceUpdates_Success() (gas: 106272) -EVM2EVMMultiOffRamp_commit:test_PriceSequenceNumberCleared_Success() (gas: 351414) -EVM2EVMMultiOffRamp_commit:test_ReportAndPriceUpdate_Success() (gas: 159132) -EVM2EVMMultiOffRamp_commit:test_ReportOnlyRootSuccess_gas() (gas: 136253) -EVM2EVMMultiOffRamp_commit:test_RootAlreadyCommitted_Revert() (gas: 136831) -EVM2EVMMultiOffRamp_commit:test_SourceChainNotEnabled_Revert() (gas: 59046) -EVM2EVMMultiOffRamp_commit:test_StaleReportWithRoot_Success() (gas: 227807) -EVM2EVMMultiOffRamp_commit:test_UnauthorizedTransmitter_Revert() (gas: 117527) -EVM2EVMMultiOffRamp_commit:test_Unhealthy_Revert() (gas: 77605) -EVM2EVMMultiOffRamp_commit:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 207057) -EVM2EVMMultiOffRamp_commit:test_WrongConfigWithoutSigners_Revert() (gas: 6389130) -EVM2EVMMultiOffRamp_commit:test_ZeroEpochAndRound_Revert() (gas: 47785) -EVM2EVMMultiOffRamp_constructor:test_Constructor_Success() (gas: 5981174) -EVM2EVMMultiOffRamp_constructor:test_SourceChainSelector_Revert() (gas: 157326) -EVM2EVMMultiOffRamp_constructor:test_ZeroChainSelector_Revert() (gas: 103815) -EVM2EVMMultiOffRamp_constructor:test_ZeroNonceManager_Revert() (gas: 101686) -EVM2EVMMultiOffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 159832) -EVM2EVMMultiOffRamp_constructor:test_ZeroRMNProxy_Revert() (gas: 101585) -EVM2EVMMultiOffRamp_constructor:test_ZeroTokenAdminRegistry_Revert() (gas: 101652) -EVM2EVMMultiOffRamp_execute:test_IncorrectArrayType_Revert() (gas: 17280) -EVM2EVMMultiOffRamp_execute:test_LargeBatch_Success() (gas: 1559406) -EVM2EVMMultiOffRamp_execute:test_MultipleReportsWithPartialValidationFailures_Success() (gas: 342924) -EVM2EVMMultiOffRamp_execute:test_MultipleReports_Success() (gas: 260178) -EVM2EVMMultiOffRamp_execute:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6445247) -EVM2EVMMultiOffRamp_execute:test_NoConfig_Revert() (gas: 6028193) -EVM2EVMMultiOffRamp_execute:test_NonArray_Revert() (gas: 27681) -EVM2EVMMultiOffRamp_execute:test_SingleReport_Success() (gas: 165181) -EVM2EVMMultiOffRamp_execute:test_UnauthorizedTransmitter_Revert() (gas: 149137) -EVM2EVMMultiOffRamp_execute:test_WrongConfigWithSigners_Revert() (gas: 6807322) -EVM2EVMMultiOffRamp_execute:test_ZeroReports_Revert() (gas: 17154) -EVM2EVMMultiOffRamp_executeSingleMessage:test_MessageSender_Revert() (gas: 18413) -EVM2EVMMultiOffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 249368) -EVM2EVMMultiOffRamp_executeSingleMessage:test_NonContract_Success() (gas: 20672) -EVM2EVMMultiOffRamp_executeSingleMessage:test_TokenHandlingError_Revert() (gas: 204173) -EVM2EVMMultiOffRamp_executeSingleMessage:test_ZeroGasDONExecution_Revert() (gas: 48860) -EVM2EVMMultiOffRamp_executeSingleMessage:test_executeSingleMessage_NoTokens_Success() (gas: 48381) -EVM2EVMMultiOffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidationNoRouterCall_Revert() (gas: 232798) -EVM2EVMMultiOffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidation_Revert() (gas: 89392) -EVM2EVMMultiOffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens_Success() (gas: 278146) -EVM2EVMMultiOffRamp_executeSingleMessage:test_executeSingleMessage_WithValidation_Success() (gas: 93615) -EVM2EVMMultiOffRamp_executeSingleReport:test_DisabledSourceChain_Revert() (gas: 35083) -EVM2EVMMultiOffRamp_executeSingleReport:test_EmptyReport_Revert() (gas: 23907) -EVM2EVMMultiOffRamp_executeSingleReport:test_InvalidSourcePoolAddress_Success() (gas: 451358) -EVM2EVMMultiOffRamp_executeSingleReport:test_ManualExecutionNotYetEnabled_Revert() (gas: 54475) -EVM2EVMMultiOffRamp_executeSingleReport:test_MismatchingDestChainSelector_Revert() (gas: 35917) -EVM2EVMMultiOffRamp_executeSingleReport:test_MismatchingOnRampRoot_Revert() (gas: 154369) -EVM2EVMMultiOffRamp_executeSingleReport:test_NonExistingSourceChain_Revert() (gas: 35317) -EVM2EVMMultiOffRamp_executeSingleReport:test_ReceiverError_Success() (gas: 181353) -EVM2EVMMultiOffRamp_executeSingleReport:test_RetryFailedMessageWithoutManualExecution_Revert() (gas: 190627) -EVM2EVMMultiOffRamp_executeSingleReport:test_RootNotCommitted_Revert() (gas: 48053) -EVM2EVMMultiOffRamp_executeSingleReport:test_RouterYULCall_Revert() (gas: 443030) -EVM2EVMMultiOffRamp_executeSingleReport:test_SingleMessageNoTokensOtherChain_Success() (gas: 251770) -EVM2EVMMultiOffRamp_executeSingleReport:test_SingleMessageNoTokensUnordered_Success() (gas: 173962) -EVM2EVMMultiOffRamp_executeSingleReport:test_SingleMessageNoTokens_Success() (gas: 193657) -EVM2EVMMultiOffRamp_executeSingleReport:test_SingleMessageToNonCCIPReceiver_Success() (gas: 259648) -EVM2EVMMultiOffRamp_executeSingleReport:test_SingleMessagesNoTokensSuccess_gas() (gas: 129288) -EVM2EVMMultiOffRamp_executeSingleReport:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 391710) -EVM2EVMMultiOffRamp_executeSingleReport:test_SkippedIncorrectNonce_Success() (gas: 65899) -EVM2EVMMultiOffRamp_executeSingleReport:test_TokenDataMismatch_Revert() (gas: 80955) -EVM2EVMMultiOffRamp_executeSingleReport:test_TwoMessagesWithTokensAndGE_Success() (gas: 535429) -EVM2EVMMultiOffRamp_executeSingleReport:test_TwoMessagesWithTokensSuccess_gas() (gas: 479260) -EVM2EVMMultiOffRamp_executeSingleReport:test_UnexpectedTokenData_Revert() (gas: 35763) -EVM2EVMMultiOffRamp_executeSingleReport:test_UnhealthySingleChainCurse_Revert() (gas: 520344) -EVM2EVMMultiOffRamp_executeSingleReport:test_Unhealthy_Revert() (gas: 517712) -EVM2EVMMultiOffRamp_executeSingleReport:test_WithCurseOnAnotherSourceChain_Success() (gas: 487848) -EVM2EVMMultiOffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessageUnordered_Success() (gas: 127921) -EVM2EVMMultiOffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessage_Success() (gas: 157144) -EVM2EVMMultiOffRamp_getExecutionState:test_FillExecutionState_Success() (gas: 3655340) -EVM2EVMMultiOffRamp_getExecutionState:test_GetDifferentChainExecutionState_Success() (gas: 118224) -EVM2EVMMultiOffRamp_getExecutionState:test_GetExecutionState_Success() (gas: 87461) -EVM2EVMMultiOffRamp_manuallyExecute:test_ManualExecGasLimitMismatchSingleReport_Revert() (gas: 75600) -EVM2EVMMultiOffRamp_manuallyExecute:test_ManualExecInvalidGasLimit_Revert() (gas: 26461) -EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_DoesNotRevertIfUntouched_Success() (gas: 163081) -EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_FailedTx_Revert() (gas: 207379) -EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_ForkedChain_Revert() (gas: 26004) -EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_GasLimitMismatchMultipleReports_Revert() (gas: 152867) -EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_LowGasLimit_Success() (gas: 507480) -EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_ReentrancyFails() (gas: 2307925) -EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_Success() (gas: 209633) -EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_WithGasOverride_Success() (gas: 210210) -EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_WithMultiReportGasOverride_Success() (gas: 668610) -EVM2EVMMultiOffRamp_manuallyExecute:test_manuallyExecute_WithPartialMessages_Success() (gas: 299477) -EVM2EVMMultiOffRamp_releaseOrMintTokens:test_TokenHandlingError_Reverts() (gas: 160598) -EVM2EVMMultiOffRamp_releaseOrMintTokens:test__releaseOrMintTokens_PoolIsNotAPool_Reverts() (gas: 24131) -EVM2EVMMultiOffRamp_releaseOrMintTokens:test_releaseOrMintTokens_InvalidDataLengthReturnData_Revert() (gas: 59105) -EVM2EVMMultiOffRamp_releaseOrMintTokens:test_releaseOrMintTokens_InvalidEVMAddress_Revert() (gas: 40405) -EVM2EVMMultiOffRamp_releaseOrMintTokens:test_releaseOrMintTokens_PoolDoesNotSupportDest_Reverts() (gas: 76130) -EVM2EVMMultiOffRamp_releaseOrMintTokens:test_releaseOrMintTokens_Success() (gas: 178951) -EVM2EVMMultiOffRamp_releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals_Success() (gas: 278805) -EVM2EVMMultiOffRamp_resetUnblessedRoots:test_OnlyOwner_Revert() (gas: 11379) -EVM2EVMMultiOffRamp_resetUnblessedRoots:test_ResetUnblessedRoots_Success() (gas: 215406) -EVM2EVMMultiOffRamp_setDynamicConfig:test_NonOwner_Revert() (gas: 14374) -EVM2EVMMultiOffRamp_setDynamicConfig:test_PriceRegistryZeroAddress_Revert() (gas: 11898) -EVM2EVMMultiOffRamp_setDynamicConfig:test_RouterZeroAddress_Revert() (gas: 14054) -EVM2EVMMultiOffRamp_setDynamicConfig:test_SetDynamicConfigWithValidator_Success() (gas: 55771) -EVM2EVMMultiOffRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 33781) -EVM2EVMMultiOffRamp_trialExecute:test_RateLimitError_Success() (gas: 238004) -EVM2EVMMultiOffRamp_trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 246667) -EVM2EVMMultiOffRamp_trialExecute:test_TokenPoolIsNotAContract_Success() (gas: 299499) -EVM2EVMMultiOffRamp_trialExecute:test_trialExecute_Success() (gas: 280579) -EVM2EVMMultiOffRamp_verify:test_Blessed_Success() (gas: 176604) -EVM2EVMMultiOffRamp_verify:test_NotBlessedWrongChainSelector_Success() (gas: 178672) -EVM2EVMMultiOffRamp_verify:test_NotBlessed_Success() (gas: 141533) -EVM2EVMMultiOffRamp_verify:test_TooManyLeaves_Revert() (gas: 51508) -EVM2EVMMultiOnRamp_constructor:test_Constructor_InvalidConfigChainSelectorEqZero_Revert() (gas: 94528) -EVM2EVMMultiOnRamp_constructor:test_Constructor_InvalidConfigNonceManagerEqAddressZero_Revert() (gas: 92480) -EVM2EVMMultiOnRamp_constructor:test_Constructor_InvalidConfigRMNProxyEqAddressZero_Revert() (gas: 97483) -EVM2EVMMultiOnRamp_constructor:test_Constructor_InvalidConfigTokenAdminRegistryEqAddressZero_Revert() (gas: 92538) -EVM2EVMMultiOnRamp_constructor:test_Constructor_Success() (gas: 2260144) -EVM2EVMMultiOnRamp_forwardFromRouter:test_CannotSendZeroTokens_Revert() (gas: 90987) -EVM2EVMMultiOnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() (gas: 130983) -EVM2EVMMultiOnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2_Success() (gas: 161753) -EVM2EVMMultiOnRamp_forwardFromRouter:test_ForwardFromRouterSuccessCustomExtraArgs() (gas: 161306) -EVM2EVMMultiOnRamp_forwardFromRouter:test_ForwardFromRouterSuccessEmptyExtraArgs() (gas: 159506) -EVM2EVMMultiOnRamp_forwardFromRouter:test_ForwardFromRouterSuccessLegacyExtraArgs() (gas: 161536) -EVM2EVMMultiOnRamp_forwardFromRouter:test_ForwardFromRouter_Success() (gas: 160928) -EVM2EVMMultiOnRamp_forwardFromRouter:test_InvalidExtraArgsTag_Revert() (gas: 26206) -EVM2EVMMultiOnRamp_forwardFromRouter:test_MessageValidationError_Revert() (gas: 134082) -EVM2EVMMultiOnRamp_forwardFromRouter:test_MesssageFeeTooHigh_Revert() (gas: 24272) -EVM2EVMMultiOnRamp_forwardFromRouter:test_OriginalSender_Revert() (gas: 12819) -EVM2EVMMultiOnRamp_forwardFromRouter:test_Paused_Revert() (gas: 30695) -EVM2EVMMultiOnRamp_forwardFromRouter:test_Permissions_Revert() (gas: 15675) -EVM2EVMMultiOnRamp_forwardFromRouter:test_ShouldIncrementNonceOnlyOnOrdered_Success() (gas: 198276) -EVM2EVMMultiOnRamp_forwardFromRouter:test_ShouldIncrementSeqNumAndNonce_Success() (gas: 224545) -EVM2EVMMultiOnRamp_forwardFromRouter:test_ShouldStoreLinkFees() (gas: 140840) -EVM2EVMMultiOnRamp_forwardFromRouter:test_ShouldStoreNonLinkFees() (gas: 162262) -EVM2EVMMultiOnRamp_forwardFromRouter:test_SourceTokenDataTooLarge_Revert() (gas: 3805757) -EVM2EVMMultiOnRamp_forwardFromRouter:test_UnsupportedToken_Revert() (gas: 127615) -EVM2EVMMultiOnRamp_forwardFromRouter:test_forwardFromRouter_UnsupportedToken_Revert() (gas: 93044) -EVM2EVMMultiOnRamp_forwardFromRouter:test_forwardFromRouter_WithValidation_Success() (gas: 285076) -EVM2EVMMultiOnRamp_getFee:test_EmptyMessage_Success() (gas: 104423) -EVM2EVMMultiOnRamp_getFee:test_EnforceOutOfOrder_Revert() (gas: 74041) -EVM2EVMMultiOnRamp_getFee:test_SingleTokenMessage_Success() (gas: 119755) -EVM2EVMMultiOnRamp_getFee:test_Unhealthy_Revert() (gas: 43657) -EVM2EVMMultiOnRamp_getSupportedTokens:test_GetSupportedTokens_Revert() (gas: 10438) -EVM2EVMMultiOnRamp_getTokenPool:test_GetTokenPool_Success() (gas: 35204) -EVM2EVMMultiOnRamp_setDynamicConfig:test_SetConfigInvalidConfigFeeAggregatorEqAddressZero_Revert() (gas: 11356) -EVM2EVMMultiOnRamp_setDynamicConfig:test_SetConfigInvalidConfigPriceRegistryEqAddressZero_Revert() (gas: 12956) -EVM2EVMMultiOnRamp_setDynamicConfig:test_SetConfigInvalidConfig_Revert() (gas: 11313) -EVM2EVMMultiOnRamp_setDynamicConfig:test_SetConfigOnlyOwner_Revert() (gas: 16287) -EVM2EVMMultiOnRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 58439) -EVM2EVMMultiOnRamp_withdrawFeeTokens:test_WithdrawFeeTokens_Success() (gas: 97185) -EVM2EVMOffRamp__releaseOrMintToken:test__releaseOrMintToken_NotACompatiblePool_Revert() (gas: 38028) -EVM2EVMOffRamp__releaseOrMintToken:test__releaseOrMintToken_Success() (gas: 108191) -EVM2EVMOffRamp__releaseOrMintToken:test__releaseOrMintToken_TokenHandlingError_revert_Revert() (gas: 116732) -EVM2EVMOffRamp__releaseOrMintTokens:test_OverValueWithARLOff_Success() (gas: 391880) -EVM2EVMOffRamp__releaseOrMintTokens:test_PriceNotFoundForToken_Reverts() (gas: 145379) -EVM2EVMOffRamp__releaseOrMintTokens:test_RateLimitErrors_Reverts() (gas: 788000) -EVM2EVMOffRamp__releaseOrMintTokens:test_TokenHandlingError_Reverts() (gas: 176208) -EVM2EVMOffRamp__releaseOrMintTokens:test__releaseOrMintTokens_NotACompatiblePool_Reverts() (gas: 29700) -EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_InvalidDataLengthReturnData_Revert() (gas: 63325) -EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_InvalidEVMAddress_Revert() (gas: 44501) -EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_Success() (gas: 214151) -EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals_Success() (gas: 306912) -EVM2EVMOffRamp__report:test_Report_Success() (gas: 127459) -EVM2EVMOffRamp__trialExecute:test_RateLimitError_Success() (gas: 255047) -EVM2EVMOffRamp__trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 263638) -EVM2EVMOffRamp__trialExecute:test_TokenPoolIsNotAContract_Success() (gas: 335707) -EVM2EVMOffRamp__trialExecute:test_trialExecute_Success() (gas: 314443) -EVM2EVMOffRamp_ccipReceive:test_Reverts() (gas: 17009) -EVM2EVMOffRamp_constructor:test_CommitStoreAlreadyInUse_Revert() (gas: 153427) -EVM2EVMOffRamp_constructor:test_Constructor_Success() (gas: 5464875) -EVM2EVMOffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 144183) -EVM2EVMOffRamp_execute:test_EmptyReport_Revert() (gas: 21345) -EVM2EVMOffRamp_execute:test_InvalidMessageId_Revert() (gas: 36442) -EVM2EVMOffRamp_execute:test_InvalidSourceChain_Revert() (gas: 51701) -EVM2EVMOffRamp_execute:test_InvalidSourcePoolAddress_Success() (gas: 473575) -EVM2EVMOffRamp_execute:test_ManualExecutionNotYetEnabled_Revert() (gas: 46423) -EVM2EVMOffRamp_execute:test_MessageTooLarge_Revert() (gas: 152453) -EVM2EVMOffRamp_execute:test_Paused_Revert() (gas: 101458) -EVM2EVMOffRamp_execute:test_ReceiverError_Success() (gas: 165036) -EVM2EVMOffRamp_execute:test_RetryFailedMessageWithoutManualExecution_Revert() (gas: 177824) -EVM2EVMOffRamp_execute:test_RootNotCommitted_Revert() (gas: 41317) -EVM2EVMOffRamp_execute:test_RouterYULCall_Revert() (gas: 402506) -EVM2EVMOffRamp_execute:test_SingleMessageNoTokensUnordered_Success() (gas: 159387) -EVM2EVMOffRamp_execute:test_SingleMessageNoTokens_Success() (gas: 174622) -EVM2EVMOffRamp_execute:test_SingleMessageToNonCCIPReceiver_Success() (gas: 248634) -EVM2EVMOffRamp_execute:test_SingleMessagesNoTokensSuccess_gas() (gas: 114706) -EVM2EVMOffRamp_execute:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 409338) -EVM2EVMOffRamp_execute:test_SkippedIncorrectNonce_Success() (gas: 54173) -EVM2EVMOffRamp_execute:test_StrictUntouchedToSuccess_Success() (gas: 132056) -EVM2EVMOffRamp_execute:test_TokenDataMismatch_Revert() (gas: 52200) -EVM2EVMOffRamp_execute:test_TwoMessagesWithTokensAndGE_Success() (gas: 560178) -EVM2EVMOffRamp_execute:test_TwoMessagesWithTokensSuccess_gas() (gas: 498159) -EVM2EVMOffRamp_execute:test_UnexpectedTokenData_Revert() (gas: 35442) -EVM2EVMOffRamp_execute:test_Unhealthy_Revert() (gas: 546987) -EVM2EVMOffRamp_execute:test_UnsupportedNumberOfTokens_Revert() (gas: 64045) -EVM2EVMOffRamp_execute:test__execute_SkippedAlreadyExecutedMessageUnordered_Success() (gas: 123223) -EVM2EVMOffRamp_execute:test__execute_SkippedAlreadyExecutedMessage_Success() (gas: 143388) -EVM2EVMOffRamp_executeSingleMessage:test_MessageSender_Revert() (gas: 20582) -EVM2EVMOffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 281891) -EVM2EVMOffRamp_executeSingleMessage:test_NonContract_Success() (gas: 20231) -EVM2EVMOffRamp_executeSingleMessage:test_TokenHandlingError_Revert() (gas: 221728) -EVM2EVMOffRamp_executeSingleMessage:test_ZeroGasDONExecution_Revert() (gas: 48632) -EVM2EVMOffRamp_executeSingleMessage:test_executeSingleMessage_NoTokens_Success() (gas: 48120) -EVM2EVMOffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens_Success() (gas: 316477) -EVM2EVMOffRamp_executeSingleMessage:test_executeSingleMessage_ZeroGasZeroData_Success() (gas: 72423) -EVM2EVMOffRamp_execute_upgrade:test_V2NonceNewSenderStartsAtZero_Success() (gas: 231326) -EVM2EVMOffRamp_execute_upgrade:test_V2NonceStartsAtV1Nonce_Success() (gas: 279867) -EVM2EVMOffRamp_execute_upgrade:test_V2OffRampNonceSkipsIfMsgInFlight_Success() (gas: 261109) -EVM2EVMOffRamp_execute_upgrade:test_V2SenderNoncesReadsPreviousRamp_Success() (gas: 229397) -EVM2EVMOffRamp_execute_upgrade:test_V2_Success() (gas: 131682) -EVM2EVMOffRamp_getAllRateLimitTokens:test_GetAllRateLimitTokens_Success() (gas: 38408) -EVM2EVMOffRamp_getExecutionState:test_FillExecutionState_Success() (gas: 3213556) -EVM2EVMOffRamp_getExecutionState:test_GetExecutionState_Success() (gas: 83091) -EVM2EVMOffRamp_manuallyExecute:test_LowGasLimitManualExec_Success() (gas: 483328) -EVM2EVMOffRamp_manuallyExecute:test_ManualExecFailedTx_Revert() (gas: 186413) -EVM2EVMOffRamp_manuallyExecute:test_ManualExecForkedChain_Revert() (gas: 25824) -EVM2EVMOffRamp_manuallyExecute:test_ManualExecGasLimitMismatch_Revert() (gas: 43449) -EVM2EVMOffRamp_manuallyExecute:test_ManualExecInvalidGasLimit_Revert() (gas: 25927) -EVM2EVMOffRamp_manuallyExecute:test_ManualExecWithGasOverride_Success() (gas: 188518) -EVM2EVMOffRamp_manuallyExecute:test_ManualExec_Success() (gas: 187965) -EVM2EVMOffRamp_manuallyExecute:test_ReentrancyManualExecuteFails() (gas: 2027441) -EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_DoesNotRevertIfUntouched_Success() (gas: 143803) -EVM2EVMOffRamp_metadataHash:test_MetadataHash_Success() (gas: 8871) -EVM2EVMOffRamp_setDynamicConfig:test_NonOwner_Revert() (gas: 40429) -EVM2EVMOffRamp_setDynamicConfig:test_RouterZeroAddress_Revert() (gas: 38804) -EVM2EVMOffRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 146790) -EVM2EVMOffRamp_updateRateLimitTokens:test_updateRateLimitTokens_AddsAndRemoves_Success() (gas: 162464) -EVM2EVMOffRamp_updateRateLimitTokens:test_updateRateLimitTokens_NonOwner_Revert() (gas: 16667) -EVM2EVMOffRamp_updateRateLimitTokens:test_updateRateLimitTokens_Success() (gas: 197660) -EVM2EVMOnRamp_constructor:test_Constructor_Success() (gas: 5619710) +DefensiveExampleTest:test_Recovery() (gas: 424256) +E2E:test_E2E_3MessagesSuccess_gas() (gas: 1100023) +EVM2EVMOffRamp__releaseOrMintToken:test__releaseOrMintToken_NotACompatiblePool_Revert() (gas: 37797) +EVM2EVMOffRamp__releaseOrMintToken:test__releaseOrMintToken_Success() (gas: 103733) +EVM2EVMOffRamp__releaseOrMintToken:test__releaseOrMintToken_TokenHandlingError_transfer_Revert() (gas: 85258) +EVM2EVMOffRamp__releaseOrMintToken:test_releaseOrMintToken_InvalidDataLength_Revert() (gas: 36786) +EVM2EVMOffRamp__releaseOrMintToken:test_releaseOrMintToken_ReleaseOrMintBalanceMismatch_Revert() (gas: 94302) +EVM2EVMOffRamp__releaseOrMintToken:test_releaseOrMintToken_TokenHandlingError_BalanceOf_Revert() (gas: 39768) +EVM2EVMOffRamp__releaseOrMintToken:test_releaseOrMintToken_skip_ReleaseOrMintBalanceMismatch_if_pool_Revert() (gas: 86559) +EVM2EVMOffRamp__releaseOrMintTokens:test_OverValueWithARLOff_Success() (gas: 385246) +EVM2EVMOffRamp__releaseOrMintTokens:test_PriceNotFoundForToken_Reverts() (gas: 141896) +EVM2EVMOffRamp__releaseOrMintTokens:test_RateLimitErrors_Reverts() (gas: 803071) +EVM2EVMOffRamp__releaseOrMintTokens:test_TokenHandlingError_Reverts() (gas: 179244) +EVM2EVMOffRamp__releaseOrMintTokens:test__releaseOrMintTokens_NotACompatiblePool_Reverts() (gas: 29240) +EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_InvalidDataLengthReturnData_Revert() (gas: 66444) +EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_InvalidEVMAddress_Revert() (gas: 43320) +EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_Success() (gas: 210968) +EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals_Success() (gas: 222232) +EVM2EVMOffRamp__report:test_Report_Success() (gas: 126637) +EVM2EVMOffRamp__trialExecute:test_RateLimitError_Success() (gas: 237791) +EVM2EVMOffRamp__trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 246391) +EVM2EVMOffRamp__trialExecute:test_TokenPoolIsNotAContract_Success() (gas: 329828) +EVM2EVMOffRamp__trialExecute:test_trialExecute_Success() (gas: 312265) +EVM2EVMOffRamp_ccipReceive:test_Reverts() (gas: 17030) +EVM2EVMOffRamp_constructor:test_CommitStoreAlreadyInUse_Revert() (gas: 153727) +EVM2EVMOffRamp_constructor:test_Constructor_Success() (gas: 5665947) +EVM2EVMOffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 144461) +EVM2EVMOffRamp_execute:test_EmptyReport_Revert() (gas: 21318) +EVM2EVMOffRamp_execute:test_InvalidMessageId_Revert() (gas: 36432) +EVM2EVMOffRamp_execute:test_InvalidSourceChain_Revert() (gas: 51598) +EVM2EVMOffRamp_execute:test_InvalidSourcePoolAddress_Success() (gas: 473329) +EVM2EVMOffRamp_execute:test_ManualExecutionNotYetEnabled_Revert() (gas: 47668) +EVM2EVMOffRamp_execute:test_MessageTooLarge_Revert() (gas: 152359) +EVM2EVMOffRamp_execute:test_Paused_Revert() (gas: 102842) +EVM2EVMOffRamp_execute:test_ReceiverError_Success() (gas: 163804) +EVM2EVMOffRamp_execute:test_RetryFailedMessageWithoutManualExecution_Success() (gas: 178205) +EVM2EVMOffRamp_execute:test_RootNotCommitted_Revert() (gas: 42539) +EVM2EVMOffRamp_execute:test_SingleMessageNoTokensUnordered_Success() (gas: 157347) +EVM2EVMOffRamp_execute:test_SingleMessageNoTokens_Success() (gas: 172692) +EVM2EVMOffRamp_execute:test_SingleMessageToNonCCIPReceiver_Success() (gas: 247069) +EVM2EVMOffRamp_execute:test_SingleMessagesNoTokensSuccess_gas() (gas: 113842) +EVM2EVMOffRamp_execute:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 407451) +EVM2EVMOffRamp_execute:test_SkippedIncorrectNonce_Success() (gas: 54096) +EVM2EVMOffRamp_execute:test_StrictUntouchedToSuccess_Success() (gas: 131047) +EVM2EVMOffRamp_execute:test_TokenDataMismatch_Revert() (gas: 52090) +EVM2EVMOffRamp_execute:test_TwoMessagesWithTokensAndGE_Success() (gas: 563385) +EVM2EVMOffRamp_execute:test_TwoMessagesWithTokensSuccess_gas() (gas: 494182) +EVM2EVMOffRamp_execute:test_UnexpectedTokenData_Revert() (gas: 35383) +EVM2EVMOffRamp_execute:test_Unhealthy_Revert() (gas: 544641) +EVM2EVMOffRamp_execute:test_UnsupportedNumberOfTokens_Revert() (gas: 64326) +EVM2EVMOffRamp_execute:test__execute_SkippedAlreadyExecutedMessageUnordered_Success() (gas: 122322) +EVM2EVMOffRamp_execute:test__execute_SkippedAlreadyExecutedMessage_Success() (gas: 142532) +EVM2EVMOffRamp_execute:test_execute_RouterYULCall_Success() (gas: 427337) +EVM2EVMOffRamp_executeSingleMessage:test_MessageSender_Revert() (gas: 18502) +EVM2EVMOffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 278097) +EVM2EVMOffRamp_executeSingleMessage:test_NonContract_Success() (gas: 18659) +EVM2EVMOffRamp_executeSingleMessage:test_TokenHandlingError_Revert() (gas: 223921) +EVM2EVMOffRamp_executeSingleMessage:test_ZeroGasDONExecution_Revert() (gas: 47881) +EVM2EVMOffRamp_executeSingleMessage:test_executeSingleMessage_NoTokens_Success() (gas: 47352) +EVM2EVMOffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens_Success() (gas: 313917) +EVM2EVMOffRamp_executeSingleMessage:test_executeSingleMessage_ZeroGasZeroData_Success() (gas: 70008) +EVM2EVMOffRamp_execute_upgrade:test_V2NonceNewSenderStartsAtZero_Success() (gas: 229319) +EVM2EVMOffRamp_execute_upgrade:test_V2NonceStartsAtV1Nonce_Success() (gas: 276790) +EVM2EVMOffRamp_execute_upgrade:test_V2OffRampNonceSkipsIfMsgInFlight_Success() (gas: 258696) +EVM2EVMOffRamp_execute_upgrade:test_V2SenderNoncesReadsPreviousRamp_Success() (gas: 226253) +EVM2EVMOffRamp_execute_upgrade:test_V2_Success() (gas: 130745) +EVM2EVMOffRamp_getAllRateLimitTokens:test_GetAllRateLimitTokens_Success() (gas: 38446) +EVM2EVMOffRamp_getExecutionState:test_FillExecutionState_Success() (gas: 3247348) +EVM2EVMOffRamp_getExecutionState:test_GetExecutionState_Success() (gas: 83333) +EVM2EVMOffRamp_manuallyExecute:test_ManualExecFailedTx_Revert() (gas: 185829) +EVM2EVMOffRamp_manuallyExecute:test_ManualExecForkedChain_Revert() (gas: 27049) +EVM2EVMOffRamp_manuallyExecute:test_ManualExecGasLimitMismatch_Revert() (gas: 45155) +EVM2EVMOffRamp_manuallyExecute:test_ManualExecInvalidGasLimit_Revert() (gas: 27468) +EVM2EVMOffRamp_manuallyExecute:test_ManualExecWithMultipleMessagesAndSourceTokens_Success() (gas: 530151) +EVM2EVMOffRamp_manuallyExecute:test_ManualExecWithSourceTokens_Success() (gas: 345758) +EVM2EVMOffRamp_manuallyExecute:test_ManualExec_Success() (gas: 187324) +EVM2EVMOffRamp_manuallyExecute:test_ReentrancyManualExecuteFails_Success() (gas: 2321906) +EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_DestinationGasAmountCountMismatch_Revert() (gas: 362965) +EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_DoesNotRevertIfUntouched_Success() (gas: 143900) +EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_InvalidTokenGasOverride_Revert() (gas: 366104) +EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_LowGasLimitManualExec_Success() (gas: 482691) +EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_WithGasOverride_Success() (gas: 189727) +EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_WithInvalidReceiverExecutionGasOverride_Revert() (gas: 153641) +EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_WithInvalidSourceTokenDataCount_Revert() (gas: 59894) +EVM2EVMOffRamp_metadataHash:test_MetadataHash_Success() (gas: 8838) +EVM2EVMOffRamp_setDynamicConfig:test_NonOwner_Revert() (gas: 40153) +EVM2EVMOffRamp_setDynamicConfig:test_RouterZeroAddress_Revert() (gas: 38236) +EVM2EVMOffRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 141962) +EVM2EVMOffRamp_updateRateLimitTokens:test_updateRateLimitTokens_AddsAndRemoves_Success() (gas: 162525) +EVM2EVMOffRamp_updateRateLimitTokens:test_updateRateLimitTokens_NonOwner_Revert() (gas: 16690) +EVM2EVMOffRamp_updateRateLimitTokens:test_updateRateLimitTokens_Success() (gas: 197721) +EVM2EVMOnRamp_constructor:test_Constructor_Success() (gas: 5579769) EVM2EVMOnRamp_forwardFromRouter:test_CannotSendZeroTokens_Revert() (gas: 35778) -EVM2EVMOnRamp_forwardFromRouter:test_EnforceOutOfOrder_Revert() (gas: 99470) -EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() (gas: 114210) -EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2_Success() (gas: 114252) -EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterSuccessCustomExtraArgs() (gas: 130118) -EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterSuccessLegacyExtraArgs() (gas: 138650) -EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouter_Success() (gas: 129804) -EVM2EVMOnRamp_forwardFromRouter:test_InvalidAddressEncodePacked_Revert() (gas: 38254) -EVM2EVMOnRamp_forwardFromRouter:test_InvalidAddress_Revert() (gas: 38370) -EVM2EVMOnRamp_forwardFromRouter:test_InvalidChainSelector_Revert() (gas: 25511) -EVM2EVMOnRamp_forwardFromRouter:test_InvalidExtraArgsTag_Revert() (gas: 25297) -EVM2EVMOnRamp_forwardFromRouter:test_MaxCapacityExceeded_Revert() (gas: 86041) +EVM2EVMOnRamp_forwardFromRouter:test_EnforceOutOfOrder_Revert() (gas: 98428) +EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() (gas: 114198) +EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2_Success() (gas: 114240) +EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterSuccessCustomExtraArgs() (gas: 130207) +EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterSuccessLegacyExtraArgs() (gas: 138653) +EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouter_Success() (gas: 129829) +EVM2EVMOnRamp_forwardFromRouter:test_InvalidAddressEncodePacked_Revert() (gas: 38257) +EVM2EVMOnRamp_forwardFromRouter:test_InvalidAddress_Revert() (gas: 38440) +EVM2EVMOnRamp_forwardFromRouter:test_InvalidChainSelector_Revert() (gas: 25489) +EVM2EVMOnRamp_forwardFromRouter:test_InvalidExtraArgsTag_Revert() (gas: 25275) +EVM2EVMOnRamp_forwardFromRouter:test_MaxCapacityExceeded_Revert() (gas: 86013) EVM2EVMOnRamp_forwardFromRouter:test_MaxFeeBalanceReached_Revert() (gas: 36457) -EVM2EVMOnRamp_forwardFromRouter:test_MessageGasLimitTooHigh_Revert() (gas: 29037) -EVM2EVMOnRamp_forwardFromRouter:test_MessageTooLarge_Revert() (gas: 107526) -EVM2EVMOnRamp_forwardFromRouter:test_OriginalSender_Revert() (gas: 22635) -EVM2EVMOnRamp_forwardFromRouter:test_OverValueWithARLOff_Success() (gas: 226165) -EVM2EVMOnRamp_forwardFromRouter:test_Paused_Revert() (gas: 53935) +EVM2EVMOnRamp_forwardFromRouter:test_MessageGasLimitTooHigh_Revert() (gas: 29015) +EVM2EVMOnRamp_forwardFromRouter:test_MessageTooLarge_Revert() (gas: 107571) +EVM2EVMOnRamp_forwardFromRouter:test_OriginalSender_Revert() (gas: 22679) +EVM2EVMOnRamp_forwardFromRouter:test_OverValueWithARLOff_Success() (gas: 227119) +EVM2EVMOnRamp_forwardFromRouter:test_Paused_Revert() (gas: 53072) EVM2EVMOnRamp_forwardFromRouter:test_Permissions_Revert() (gas: 25481) -EVM2EVMOnRamp_forwardFromRouter:test_PriceNotFoundForToken_Revert() (gas: 59303) -EVM2EVMOnRamp_forwardFromRouter:test_ShouldIncrementNonceOnlyOnOrdered_Success() (gas: 179141) -EVM2EVMOnRamp_forwardFromRouter:test_ShouldIncrementSeqNumAndNonce_Success() (gas: 177355) -EVM2EVMOnRamp_forwardFromRouter:test_ShouldStoreNonLinkFees() (gas: 137297) -EVM2EVMOnRamp_forwardFromRouter:test_SourceTokenDataTooLarge_Revert() (gas: 3734267) +EVM2EVMOnRamp_forwardFromRouter:test_PriceNotFoundForToken_Revert() (gas: 59341) +EVM2EVMOnRamp_forwardFromRouter:test_ShouldIncrementNonceOnlyOnOrdered_Success() (gas: 179148) +EVM2EVMOnRamp_forwardFromRouter:test_ShouldIncrementSeqNumAndNonce_Success() (gas: 177430) +EVM2EVMOnRamp_forwardFromRouter:test_ShouldStoreNonLinkFees() (gas: 137254) +EVM2EVMOnRamp_forwardFromRouter:test_SourceTokenDataTooLarge_Revert() (gas: 3825327) EVM2EVMOnRamp_forwardFromRouter:test_TooManyTokens_Revert() (gas: 30187) EVM2EVMOnRamp_forwardFromRouter:test_Unhealthy_Revert() (gas: 43300) -EVM2EVMOnRamp_forwardFromRouter:test_UnsupportedToken_Revert() (gas: 109258) -EVM2EVMOnRamp_forwardFromRouter:test_ZeroAddressReceiver_Revert() (gas: 312351) -EVM2EVMOnRamp_forwardFromRouter:test_forwardFromRouter_ShouldStoreLinkFees_Success() (gas: 112319) -EVM2EVMOnRamp_forwardFromRouter:test_forwardFromRouter_UnsupportedToken_Revert() (gas: 72181) -EVM2EVMOnRamp_forwardFromRouter_upgrade:test_V2NonceNewSenderStartsAtZero_Success() (gas: 147614) -EVM2EVMOnRamp_forwardFromRouter_upgrade:test_V2NonceStartsAtV1Nonce_Success() (gas: 190454) -EVM2EVMOnRamp_forwardFromRouter_upgrade:test_V2SenderNoncesReadsPreviousRamp_Success() (gas: 121245) -EVM2EVMOnRamp_forwardFromRouter_upgrade:test_V2_Success() (gas: 95324) -EVM2EVMOnRamp_getDataAvailabilityCost:test_EmptyMessageCalculatesDataAvailabilityCost_Success() (gas: 20760) -EVM2EVMOnRamp_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCost_Success() (gas: 21128) -EVM2EVMOnRamp_getFee:test_EmptyMessage_Success() (gas: 78242) -EVM2EVMOnRamp_getFee:test_HighGasMessage_Success() (gas: 234090) +EVM2EVMOnRamp_forwardFromRouter:test_UnsupportedToken_Revert() (gas: 109305) +EVM2EVMOnRamp_forwardFromRouter:test_ZeroAddressReceiver_Revert() (gas: 312579) +EVM2EVMOnRamp_forwardFromRouter:test_forwardFromRouter_ShouldStoreLinkFees_Success() (gas: 112322) +EVM2EVMOnRamp_forwardFromRouter:test_forwardFromRouter_UnsupportedToken_Revert() (gas: 72206) +EVM2EVMOnRamp_forwardFromRouter:test_forwardFromRouter_correctSourceTokenData_Success() (gas: 712975) +EVM2EVMOnRamp_forwardFromRouter_upgrade:test_V2NonceNewSenderStartsAtZero_Success() (gas: 147664) +EVM2EVMOnRamp_forwardFromRouter_upgrade:test_V2NonceStartsAtV1Nonce_Success() (gas: 190529) +EVM2EVMOnRamp_forwardFromRouter_upgrade:test_V2SenderNoncesReadsPreviousRamp_Success() (gas: 121320) +EVM2EVMOnRamp_forwardFromRouter_upgrade:test_V2_Success() (gas: 95349) +EVM2EVMOnRamp_getDataAvailabilityCost:test_EmptyMessageCalculatesDataAvailabilityCost_Success() (gas: 20544) +EVM2EVMOnRamp_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCost_Success() (gas: 20912) +EVM2EVMOnRamp_getFee:test_EmptyMessage_Success() (gas: 78230) +EVM2EVMOnRamp_getFee:test_GetFeeOfZeroForTokenMessage_Success() (gas: 81762) +EVM2EVMOnRamp_getFee:test_HighGasMessage_Success() (gas: 234078) EVM2EVMOnRamp_getFee:test_MessageGasLimitTooHigh_Revert() (gas: 16715) EVM2EVMOnRamp_getFee:test_MessageTooLarge_Revert() (gas: 95271) -EVM2EVMOnRamp_getFee:test_MessageWithDataAndTokenTransfer_Success() (gas: 159220) +EVM2EVMOnRamp_getFee:test_MessageWithDataAndTokenTransfer_Success() (gas: 159436) EVM2EVMOnRamp_getFee:test_NotAFeeToken_Revert() (gas: 24089) -EVM2EVMOnRamp_getFee:test_SingleTokenMessage_Success() (gas: 117858) +EVM2EVMOnRamp_getFee:test_SingleTokenMessage_Success() (gas: 117922) EVM2EVMOnRamp_getFee:test_TooManyTokens_Revert() (gas: 19902) -EVM2EVMOnRamp_getFee:test_ZeroDataAvailabilityMultiplier_Success() (gas: 65663) +EVM2EVMOnRamp_getFee:test_ZeroDataAvailabilityMultiplier_Success() (gas: 64648) EVM2EVMOnRamp_getSupportedTokens:test_GetSupportedTokens_Revert() (gas: 10460) EVM2EVMOnRamp_getTokenPool:test_GetTokenPool_Success() (gas: 35195) -EVM2EVMOnRamp_getTokenTransferCost:test_CustomTokenBpsFee_Success() (gas: 45037) -EVM2EVMOnRamp_getTokenTransferCost:test_FeeTokenBpsFee_Success() (gas: 33041) +EVM2EVMOnRamp_getTokenTransferCost:test_CustomTokenBpsFee_Success() (gas: 45120) +EVM2EVMOnRamp_getTokenTransferCost:test_FeeTokenBpsFee_Success() (gas: 33019) EVM2EVMOnRamp_getTokenTransferCost:test_LargeTokenTransferChargesMaxFeeAndGas_Success() (gas: 28296) -EVM2EVMOnRamp_getTokenTransferCost:test_MixedTokenTransferFee_Success() (gas: 130189) -EVM2EVMOnRamp_getTokenTransferCost:test_NoTokenTransferChargesZeroFee_Success() (gas: 15260) +EVM2EVMOnRamp_getTokenTransferCost:test_MixedTokenTransferFee_Success() (gas: 126453) +EVM2EVMOnRamp_getTokenTransferCost:test_NoTokenTransferChargesZeroFee_Success() (gas: 15238) EVM2EVMOnRamp_getTokenTransferCost:test_SmallTokenTransferChargesMinFeeAndGas_Success() (gas: 28104) EVM2EVMOnRamp_getTokenTransferCost:test_UnsupportedToken_Revert() (gas: 21248) -EVM2EVMOnRamp_getTokenTransferCost:test_WETHTokenBpsFee_Success() (gas: 38922) -EVM2EVMOnRamp_getTokenTransferCost:test_ZeroAmountTokenTransferChargesMinFeeAndGas_Success() (gas: 28149) -EVM2EVMOnRamp_getTokenTransferCost:test_ZeroFeeConfigChargesMinFee_Success() (gas: 38615) -EVM2EVMOnRamp_getTokenTransferCost:test__getTokenTransferCost_selfServeUsesDefaults_Success() (gas: 29527) +EVM2EVMOnRamp_getTokenTransferCost:test_ZeroAmountTokenTransferChargesMinFeeAndGas_Success() (gas: 28127) +EVM2EVMOnRamp_getTokenTransferCost:test_ZeroFeeConfigChargesMinFee_Success() (gas: 38599) +EVM2EVMOnRamp_getTokenTransferCost:test__getTokenTransferCost_selfServeUsesDefaults_Success() (gas: 29404) EVM2EVMOnRamp_linkAvailableForPayment:test_InsufficientLinkBalance_Success() (gas: 32615) EVM2EVMOnRamp_linkAvailableForPayment:test_LinkAvailableForPayment_Success() (gas: 134833) -EVM2EVMOnRamp_payNops:test_AdminPayNops_Success() (gas: 143054) +EVM2EVMOnRamp_payNops:test_AdminPayNops_Success() (gas: 143159) EVM2EVMOnRamp_payNops:test_InsufficientBalance_Revert() (gas: 29043) EVM2EVMOnRamp_payNops:test_NoFeesToPay_Revert() (gas: 127367) EVM2EVMOnRamp_payNops:test_NoNopsToPay_Revert() (gas: 133251) -EVM2EVMOnRamp_payNops:test_NopPayNops_Success() (gas: 146341) -EVM2EVMOnRamp_payNops:test_OwnerPayNops_Success() (gas: 140916) -EVM2EVMOnRamp_payNops:test_PayNopsSuccessAfterSetNops() (gas: 297485) +EVM2EVMOnRamp_payNops:test_NopPayNops_Success() (gas: 146446) +EVM2EVMOnRamp_payNops:test_OwnerPayNops_Success() (gas: 141021) +EVM2EVMOnRamp_payNops:test_PayNopsSuccessAfterSetNops() (gas: 297510) EVM2EVMOnRamp_payNops:test_WrongPermissions_Revert() (gas: 15294) -EVM2EVMOnRamp_setDynamicConfig:test_SetConfigInvalidConfig_Revert() (gas: 43376) -EVM2EVMOnRamp_setDynamicConfig:test_SetConfigOnlyOwner_Revert() (gas: 21646) -EVM2EVMOnRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 55086) +EVM2EVMOnRamp_setDynamicConfig:test_SetConfigInvalidConfig_Revert() (gas: 42365) +EVM2EVMOnRamp_setDynamicConfig:test_SetConfigOnlyOwner_Revert() (gas: 21246) +EVM2EVMOnRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 53764) EVM2EVMOnRamp_setFeeTokenConfig:test_OnlyCallableByOwnerOrAdmin_Revert() (gas: 13464) EVM2EVMOnRamp_setFeeTokenConfig:test_SetFeeTokenConfigByAdmin_Success() (gas: 16449) EVM2EVMOnRamp_setFeeTokenConfig:test_SetFeeTokenConfig_Success() (gas: 13994) EVM2EVMOnRamp_setNops:test_AdminCanSetNops_Success() (gas: 61759) -EVM2EVMOnRamp_setNops:test_IncludesPayment_Success() (gas: 469097) +EVM2EVMOnRamp_setNops:test_IncludesPayment_Success() (gas: 469227) EVM2EVMOnRamp_setNops:test_LinkTokenCannotBeNop_Revert() (gas: 57255) EVM2EVMOnRamp_setNops:test_NonOwnerOrAdmin_Revert() (gas: 14665) -EVM2EVMOnRamp_setNops:test_NotEnoughFundsForPayout_Revert() (gas: 84455) +EVM2EVMOnRamp_setNops:test_NotEnoughFundsForPayout_Revert() (gas: 84480) EVM2EVMOnRamp_setNops:test_SetNopsRemovesOldNopsCompletely_Success() (gas: 60637) -EVM2EVMOnRamp_setNops:test_SetNops_Success() (gas: 173677) +EVM2EVMOnRamp_setNops:test_SetNops_Success() (gas: 173782) EVM2EVMOnRamp_setNops:test_TooManyNops_Revert() (gas: 190338) EVM2EVMOnRamp_setNops:test_ZeroAddressCannotBeNop_Revert() (gas: 53596) -EVM2EVMOnRamp_setTokenTransferFeeConfig:test__setTokenTransferFeeConfig_InvalidDestBytesOverhead_Revert() (gas: 14493) +EVM2EVMOnRamp_setTokenTransferFeeConfig:test__setTokenTransferFeeConfig_InvalidDestBytesOverhead_Revert() (gas: 14499) EVM2EVMOnRamp_setTokenTransferFeeConfig:test__setTokenTransferFeeConfig_OnlyCallableByOwnerOrAdmin_Revert() (gas: 14277) -EVM2EVMOnRamp_setTokenTransferFeeConfig:test__setTokenTransferFeeConfig_Success() (gas: 84017) +EVM2EVMOnRamp_setTokenTransferFeeConfig:test__setTokenTransferFeeConfig_Success() (gas: 84029) EVM2EVMOnRamp_setTokenTransferFeeConfig:test__setTokenTransferFeeConfig_byAdmin_Success() (gas: 17369) -EVM2EVMOnRamp_withdrawNonLinkFees:test_LinkBalanceNotSettled_Revert() (gas: 82980) +EVM2EVMOnRamp_withdrawNonLinkFees:test_LinkBalanceNotSettled_Revert() (gas: 83005) EVM2EVMOnRamp_withdrawNonLinkFees:test_NonOwnerOrAdmin_Revert() (gas: 15275) -EVM2EVMOnRamp_withdrawNonLinkFees:test_SettlingBalance_Success() (gas: 272015) +EVM2EVMOnRamp_withdrawNonLinkFees:test_SettlingBalance_Success() (gas: 272035) EVM2EVMOnRamp_withdrawNonLinkFees:test_WithdrawNonLinkFees_Success() (gas: 53446) EVM2EVMOnRamp_withdrawNonLinkFees:test_WithdrawToZeroAddress_Revert() (gas: 12830) EtherSenderReceiverTest_ccipReceive:test_ccipReceive_fallbackToWethTransfer() (gas: 96729) @@ -481,38 +328,158 @@ EtherSenderReceiverTest_validatedMessage:test_validatedMessage_emptyDataOverwrit EtherSenderReceiverTest_validatedMessage:test_validatedMessage_invalidTokenAmounts() (gas: 17895) EtherSenderReceiverTest_validatedMessage:test_validatedMessage_tokenOverwrittenToWeth() (gas: 25287) EtherSenderReceiverTest_validatedMessage:test_validatedMessage_validMessage_extraArgs() (gas: 26292) -LockReleaseTokenPoolAndProxy_setRateLimitAdmin:test_SetRateLimitAdmin_Revert() (gas: 11058) -LockReleaseTokenPoolAndProxy_setRateLimitAdmin:test_SetRateLimitAdmin_Success() (gas: 35097) +FeeQuoter_applyDestChainConfigUpdates:test_InvalidChainFamilySelector_Revert() (gas: 16503) +FeeQuoter_applyDestChainConfigUpdates:test_InvalidDestChainConfigDestChainSelectorEqZero_Revert() (gas: 16417) +FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesDefaultTxGasLimitEqZero_Revert() (gas: 16459) +FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesDefaultTxGasLimitGtMaxPerMessageGasLimit_Revert() (gas: 39957) +FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesZeroIntput_Success() (gas: 12342) +FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdates_Success() (gas: 135870) +FeeQuoter_applyFeeTokensUpdates:test_ApplyFeeTokensUpdates_Success() (gas: 79896) +FeeQuoter_applyFeeTokensUpdates:test_OnlyCallableByOwner_Revert() (gas: 12603) +FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_OnlyCallableByOwnerOrAdmin_Revert() (gas: 11421) +FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesMultipleTokens_Success() (gas: 54105) +FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesSingleToken_Success() (gas: 44791) +FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesZeroInput() (gas: 12257) +FeeQuoter_applyTokenTransferFeeConfigUpdates:test_ApplyTokenTransferFeeConfig_Success() (gas: 86926) +FeeQuoter_applyTokenTransferFeeConfigUpdates:test_ApplyTokenTransferFeeZeroInput() (gas: 13089) +FeeQuoter_applyTokenTransferFeeConfigUpdates:test_InvalidDestBytesOverhead_Revert() (gas: 17071) +FeeQuoter_applyTokenTransferFeeConfigUpdates:test_OnlyCallableByOwnerOrAdmin_Revert() (gas: 12240) +FeeQuoter_constructor:test_InvalidLinkTokenEqZeroAddress_Revert() (gas: 107046) +FeeQuoter_constructor:test_InvalidMaxFeeJuelsPerMsg_Revert() (gas: 111396) +FeeQuoter_constructor:test_InvalidStalenessThreshold_Revert() (gas: 111449) +FeeQuoter_constructor:test_Setup_Success() (gas: 5358690) +FeeQuoter_convertTokenAmount:test_ConvertTokenAmount_Success() (gas: 72739) +FeeQuoter_convertTokenAmount:test_LinkTokenNotSupported_Revert() (gas: 30963) +FeeQuoter_getDataAvailabilityCost:test_EmptyMessageCalculatesDataAvailabilityCost_Success() (gas: 94303) +FeeQuoter_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCostUnsupportedDestChainSelector_Success() (gas: 14614) +FeeQuoter_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCost_Success() (gas: 20410) +FeeQuoter_getTokenAndGasPrices:test_GetFeeTokenAndGasPrices_Success() (gas: 70443) +FeeQuoter_getTokenAndGasPrices:test_StaleGasPrice_Revert() (gas: 16838) +FeeQuoter_getTokenAndGasPrices:test_UnsupportedChain_Revert() (gas: 16140) +FeeQuoter_getTokenAndGasPrices:test_ZeroGasPrice_Success() (gas: 45750) +FeeQuoter_getTokenPrice:test_GetTokenPriceFromFeed_Success() (gas: 62252) +FeeQuoter_getTokenPrices:test_GetTokenPrices_Success() (gas: 84800) +FeeQuoter_getTokenTransferCost:test_CustomTokenBpsFee_Success() (gas: 41227) +FeeQuoter_getTokenTransferCost:test_FeeTokenBpsFee_Success() (gas: 34682) +FeeQuoter_getTokenTransferCost:test_LargeTokenTransferChargesMaxFeeAndGas_Success() (gas: 27756) +FeeQuoter_getTokenTransferCost:test_MixedTokenTransferFee_Success() (gas: 101624) +FeeQuoter_getTokenTransferCost:test_NoTokenTransferChargesZeroFee_Success() (gas: 20354) +FeeQuoter_getTokenTransferCost:test_SmallTokenTransferChargesMinFeeAndGas_Success() (gas: 27631) +FeeQuoter_getTokenTransferCost:test_ZeroAmountTokenTransferChargesMinFeeAndGas_Success() (gas: 27587) +FeeQuoter_getTokenTransferCost:test_ZeroFeeConfigChargesMinFee_Success() (gas: 40013) +FeeQuoter_getTokenTransferCost:test_getTokenTransferCost_selfServeUsesDefaults_Success() (gas: 29299) +FeeQuoter_getValidatedFee:test_DestinationChainNotEnabled_Revert() (gas: 18180) +FeeQuoter_getValidatedFee:test_EmptyMessage_Success() (gas: 85936) +FeeQuoter_getValidatedFee:test_EnforceOutOfOrder_Revert() (gas: 56735) +FeeQuoter_getValidatedFee:test_HighGasMessage_Success() (gas: 242354) +FeeQuoter_getValidatedFee:test_InvalidEVMAddress_Revert() (gas: 22390) +FeeQuoter_getValidatedFee:test_MessageGasLimitTooHigh_Revert() (gas: 34187) +FeeQuoter_getValidatedFee:test_MessageTooLarge_Revert() (gas: 100133) +FeeQuoter_getValidatedFee:test_MessageWithDataAndTokenTransfer_Success() (gas: 147715) +FeeQuoter_getValidatedFee:test_NotAFeeToken_Revert() (gas: 21043) +FeeQuoter_getValidatedFee:test_SingleTokenMessage_Success() (gas: 116743) +FeeQuoter_getValidatedFee:test_TooManyTokens_Revert() (gas: 22526) +FeeQuoter_getValidatedFee:test_ZeroDataAvailabilityMultiplier_Success() (gas: 64374) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Above18Decimals_Success() (gas: 2094539) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Below18Decimals_Success() (gas: 2094497) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt0Decimals_Success() (gas: 2074616) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt18Decimals_Success() (gas: 2094271) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFlippedDecimals_Success() (gas: 2094475) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedMaxInt224Value_Success() (gas: 2094287) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedOverStalenessPeriod_Success() (gas: 62004) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeed_Success() (gas: 61884) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPrice_Success() (gas: 61036) +FeeQuoter_getValidatedTokenPrice:test_OverflowFeedPrice_Revert() (gas: 2093974) +FeeQuoter_getValidatedTokenPrice:test_StaleFeeToken_Success() (gas: 61563) +FeeQuoter_getValidatedTokenPrice:test_TokenNotSupportedFeed_Revert() (gas: 109120) +FeeQuoter_getValidatedTokenPrice:test_TokenNotSupported_Revert() (gas: 13857) +FeeQuoter_getValidatedTokenPrice:test_UnderflowFeedPrice_Revert() (gas: 2092636) +FeeQuoter_onReport:test_OnReport_StaleUpdate_Revert() (gas: 43334) +FeeQuoter_onReport:test_onReport_InvalidForwarder_Reverts() (gas: 23294) +FeeQuoter_onReport:test_onReport_Success() (gas: 80639) +FeeQuoter_onReport:test_onReport_UnsupportedToken_Reverts() (gas: 26677) +FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsDefault_Success() (gas: 17185) +FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsEnforceOutOfOrder_Revert() (gas: 21290) +FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsGasLimitTooHigh_Revert() (gas: 18387) +FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsInvalidExtraArgsTag_Revert() (gas: 17911) +FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsV1_Success() (gas: 18285) +FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsV2_Success() (gas: 18401) +FeeQuoter_processMessageArgs:test_InvalidExtraArgs_Revert() (gas: 18361) +FeeQuoter_processMessageArgs:test_MalformedEVMExtraArgs_Revert() (gas: 18907) +FeeQuoter_processMessageArgs:test_MessageFeeTooHigh_Revert() (gas: 16426) +FeeQuoter_processMessageArgs:test_WitEVMExtraArgsV2_Success() (gas: 26269) +FeeQuoter_processMessageArgs:test_WithConvertedTokenAmount_Success() (gas: 32441) +FeeQuoter_processMessageArgs:test_WithEVMExtraArgsV1_Success() (gas: 25881) +FeeQuoter_processMessageArgs:test_WithEmptyEVMExtraArgs_Success() (gas: 23696) +FeeQuoter_processMessageArgs:test_WithLinkTokenAmount_Success() (gas: 17375) +FeeQuoter_updatePrices:test_OnlyCallableByUpdater_Revert() (gas: 12102) +FeeQuoter_updatePrices:test_OnlyGasPrice_Success() (gas: 23599) +FeeQuoter_updatePrices:test_OnlyTokenPrice_Success() (gas: 30631) +FeeQuoter_updatePrices:test_UpdatableByAuthorizedCaller_Success() (gas: 76003) +FeeQuoter_updatePrices:test_UpdateMultiplePrices_Success() (gas: 151393) +FeeQuoter_updateTokenPriceFeeds:test_FeedNotUpdated() (gas: 50527) +FeeQuoter_updateTokenPriceFeeds:test_FeedUnset_Success() (gas: 63626) +FeeQuoter_updateTokenPriceFeeds:test_FeedUpdatedByNonOwner_Revert() (gas: 19932) +FeeQuoter_updateTokenPriceFeeds:test_MultipleFeedUpdate_Success() (gas: 88972) +FeeQuoter_updateTokenPriceFeeds:test_SingleFeedUpdate_Success() (gas: 50821) +FeeQuoter_updateTokenPriceFeeds:test_ZeroFeeds_Success() (gas: 12296) +FeeQuoter_validateDestFamilyAddress:test_InvalidEVMAddressEncodePacked_Revert() (gas: 10616) +FeeQuoter_validateDestFamilyAddress:test_InvalidEVMAddressPrecompiles_Revert() (gas: 3961646) +FeeQuoter_validateDestFamilyAddress:test_InvalidEVMAddress_Revert() (gas: 10800) +FeeQuoter_validateDestFamilyAddress:test_ValidEVMAddress_Success() (gas: 6704) +FeeQuoter_validateDestFamilyAddress:test_ValidNonEVMAddress_Success() (gas: 6484) +FeeQuoter_validatePoolReturnData:test_InvalidEVMAddressDestToken_Revert() (gas: 42748) +FeeQuoter_validatePoolReturnData:test_ProcessPoolReturnData_Success() (gas: 73252) +FeeQuoter_validatePoolReturnData:test_SourceTokenDataTooLarge_Revert() (gas: 107744) +FeeQuoter_validatePoolReturnData:test_TokenAmountArraysMismatching_Revert() (gas: 40091) +HybridUSDCTokenPoolMigrationTests:test_LockOrBurn_LocKReleaseMechanism_then_switchToPrimary_Success() (gas: 208137) +HybridUSDCTokenPoolMigrationTests:test_LockOrBurn_PrimaryMechanism_Success() (gas: 135392) +HybridUSDCTokenPoolMigrationTests:test_LockOrBurn_WhileMigrationPause_Revert() (gas: 106624) +HybridUSDCTokenPoolMigrationTests:test_LockOrBurn_onLockReleaseMechanism_Success() (gas: 143884) +HybridUSDCTokenPoolMigrationTests:test_MintOrRelease_OnLockReleaseMechanism_Success() (gas: 230399) +HybridUSDCTokenPoolMigrationTests:test_MintOrRelease_OnLockReleaseMechanism_then_switchToPrimary_Success() (gas: 438259) +HybridUSDCTokenPoolMigrationTests:test_MintOrRelease_incomingMessageWithPrimaryMechanism() (gas: 269968) +HybridUSDCTokenPoolMigrationTests:test_burnLockedUSDC_invalidPermissions_Revert() (gas: 39124) +HybridUSDCTokenPoolMigrationTests:test_cancelExistingCCTPMigrationProposal() (gas: 31124) +HybridUSDCTokenPoolMigrationTests:test_cannotCancelANonExistentMigrationProposal() (gas: 12628) +HybridUSDCTokenPoolMigrationTests:test_cannotModifyLiquidityWithoutPermissions_Revert() (gas: 17133) +HybridUSDCTokenPoolMigrationTests:test_lockOrBurn_then_BurnInCCTPMigration_Success() (gas: 252432) +HybridUSDCTokenPoolMigrationTests:test_transferLiquidity_Success() (gas: 157049) +HybridUSDCTokenPoolMigrationTests:test_withdrawLiquidity_Success() (gas: 140780) +HybridUSDCTokenPoolTests:test_LockOrBurn_LocKReleaseMechanism_then_switchToPrimary_Success() (gas: 208102) +HybridUSDCTokenPoolTests:test_LockOrBurn_PrimaryMechanism_Success() (gas: 135365) +HybridUSDCTokenPoolTests:test_LockOrBurn_WhileMigrationPause_Revert() (gas: 106589) +HybridUSDCTokenPoolTests:test_LockOrBurn_onLockReleaseMechanism_Success() (gas: 143832) +HybridUSDCTokenPoolTests:test_MintOrRelease_OnLockReleaseMechanism_Success() (gas: 230365) +HybridUSDCTokenPoolTests:test_MintOrRelease_OnLockReleaseMechanism_then_switchToPrimary_Success() (gas: 438171) +HybridUSDCTokenPoolTests:test_MintOrRelease_incomingMessageWithPrimaryMechanism() (gas: 269912) +HybridUSDCTokenPoolTests:test_withdrawLiquidity_Success() (gas: 140774) LockReleaseTokenPoolAndProxy_setRebalancer:test_SetRebalancer_Revert() (gas: 10970) -LockReleaseTokenPoolAndProxy_setRebalancer:test_SetRebalancer_Success() (gas: 18036) -LockReleaseTokenPoolPoolAndProxy_canAcceptLiquidity:test_CanAcceptLiquidity_Success() (gas: 3313980) -LockReleaseTokenPoolPoolAndProxy_provideLiquidity:test_LiquidityNotAccepted_Revert() (gas: 3310379) +LockReleaseTokenPoolAndProxy_setRebalancer:test_SetRebalancer_Success() (gas: 17992) +LockReleaseTokenPoolPoolAndProxy_canAcceptLiquidity:test_CanAcceptLiquidity_Success() (gas: 3368110) +LockReleaseTokenPoolPoolAndProxy_provideLiquidity:test_LiquidityNotAccepted_Revert() (gas: 3364509) LockReleaseTokenPoolPoolAndProxy_provideLiquidity:test_Unauthorized_Revert() (gas: 11380) -LockReleaseTokenPoolPoolAndProxy_setChainRateLimiterConfig:test_NonExistentChain_Revert() (gas: 17135) -LockReleaseTokenPoolPoolAndProxy_setChainRateLimiterConfig:test_OnlyOwnerOrRateLimitAdmin_Revert() (gas: 69142) -LockReleaseTokenPoolPoolAndProxy_setChainRateLimiterConfig:test_OnlyOwner_Revert() (gas: 17319) LockReleaseTokenPoolPoolAndProxy_supportsInterface:test_SupportsInterface_Success() (gas: 9977) LockReleaseTokenPoolPoolAndProxy_withdrawalLiquidity:test_InsufficientLiquidity_Revert() (gas: 60043) LockReleaseTokenPoolPoolAndProxy_withdrawalLiquidity:test_Unauthorized_Revert() (gas: 11355) -LockReleaseTokenPool_canAcceptLiquidity:test_CanAcceptLiquidity_Success() (gas: 3067883) +LockReleaseTokenPool_canAcceptLiquidity:test_CanAcceptLiquidity_Success() (gas: 3124819) LockReleaseTokenPool_lockOrBurn:test_LockOrBurnWithAllowList_Revert() (gas: 29942) LockReleaseTokenPool_lockOrBurn:test_LockOrBurnWithAllowList_Success() (gas: 79844) LockReleaseTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 59464) -LockReleaseTokenPool_provideLiquidity:test_LiquidityNotAccepted_Revert() (gas: 3064325) +LockReleaseTokenPool_provideLiquidity:test_LiquidityNotAccepted_Revert() (gas: 3121261) LockReleaseTokenPool_provideLiquidity:test_Unauthorized_Revert() (gas: 11380) -LockReleaseTokenPool_releaseOrMint:test_ChainNotAllowed_Revert() (gas: 72662) -LockReleaseTokenPool_releaseOrMint:test_PoolMintNotHealthy_Revert() (gas: 56131) -LockReleaseTokenPool_releaseOrMint:test_ReleaseOrMint_Success() (gas: 238673) -LockReleaseTokenPool_setChainRateLimiterConfig:test_NonExistentChain_Revert() (gas: 17102) -LockReleaseTokenPool_setChainRateLimiterConfig:test_OnlyOwnerOrRateLimitAdmin_Revert() (gas: 69075) -LockReleaseTokenPool_setChainRateLimiterConfig:test_OnlyOwner_Revert() (gas: 17297) -LockReleaseTokenPool_setRateLimitAdmin:test_SetRateLimitAdmin_Revert() (gas: 11057) -LockReleaseTokenPool_setRateLimitAdmin:test_SetRateLimitAdmin_Success() (gas: 35140) +LockReleaseTokenPool_releaseOrMint:test_ChainNotAllowed_Revert() (gas: 72644) +LockReleaseTokenPool_releaseOrMint:test_PoolMintNotHealthy_Revert() (gas: 56196) +LockReleaseTokenPool_releaseOrMint:test_ReleaseOrMint_Success() (gas: 225108) LockReleaseTokenPool_setRebalancer:test_SetRebalancer_Revert() (gas: 10992) -LockReleaseTokenPool_setRebalancer:test_SetRebalancer_Success() (gas: 17926) +LockReleaseTokenPool_setRebalancer:test_SetRebalancer_Success() (gas: 18058) LockReleaseTokenPool_supportsInterface:test_SupportsInterface_Success() (gas: 9977) +LockReleaseTokenPool_transferLiquidity:test_transferLiquidity_Success() (gas: 83171) +LockReleaseTokenPool_transferLiquidity:test_transferLiquidity_transferTooMuch_Revert() (gas: 55878) LockReleaseTokenPool_withdrawalLiquidity:test_InsufficientLiquidity_Revert() (gas: 60043) LockReleaseTokenPool_withdrawalLiquidity:test_Unauthorized_Revert() (gas: 11355) +LockRelease_setRateLimitAdmin:test_SetRateLimitAdmin_Revert() (gas: 11029) +LockRelease_setRateLimitAdmin:test_SetRateLimitAdmin_Success() (gas: 35030) MerkleMultiProofTest:test_CVE_2023_34459() (gas: 5451) MerkleMultiProofTest:test_EmptyLeaf_Revert() (gas: 3552) MerkleMultiProofTest:test_MerkleRoot256() (gas: 394876) @@ -532,42 +499,42 @@ MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_UpdateExistingConfi MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_UpdateExistingConfig_Success() (gas: 53092) MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_ZeroChainSelector_Revert() (gas: 17019) MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_ZeroConfigs_Success() (gas: 12295) -MultiAggregateRateLimiter_constructor:test_ConstructorNoAuthorizedCallers_Success() (gas: 1971805) -MultiAggregateRateLimiter_constructor:test_Constructor_Success() (gas: 2085252) +MultiAggregateRateLimiter_constructor:test_ConstructorNoAuthorizedCallers_Success() (gas: 2149547) +MultiAggregateRateLimiter_constructor:test_Constructor_Success() (gas: 2265849) MultiAggregateRateLimiter_getTokenBucket:test_GetTokenBucket_Success() (gas: 30248) MultiAggregateRateLimiter_getTokenBucket:test_Refill_Success() (gas: 47358) MultiAggregateRateLimiter_getTokenBucket:test_TimeUnderflow_Revert() (gas: 15821) -MultiAggregateRateLimiter_getTokenValue:test_GetTokenValue_Success() (gas: 19668) -MultiAggregateRateLimiter_getTokenValue:test_NoTokenPrice_Reverts() (gas: 21253) +MultiAggregateRateLimiter_getTokenValue:test_GetTokenValue_Success() (gas: 19662) +MultiAggregateRateLimiter_getTokenValue:test_NoTokenPrice_Reverts() (gas: 21247) MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageFromUnauthorizedCaller_Revert() (gas: 14527) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithDifferentTokensOnDifferentChains_Success() (gas: 189450) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithDisabledRateLimitToken_Success() (gas: 59927) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithDifferentTokensOnDifferentChains_Success() (gas: 213638) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithDisabledRateLimitToken_Success() (gas: 60437) MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithNoTokens_Success() (gas: 17593) MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitDisabled_Success() (gas: 44895) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitExceeded_Revert() (gas: 50598) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitReset_Success() (gas: 78780) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithTokensOnDifferentChains_Success() (gas: 263510) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithTokens_Success() (gas: 54784) -MultiAggregateRateLimiter_onOutboundMessage:test_RateLimitValueDifferentLanes_Success() (gas: 1073667518) -MultiAggregateRateLimiter_onOutboundMessage:test_ValidateMessageWithNoTokens_Success() (gas: 19104) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageFromUnauthorizedCaller_Revert() (gas: 15778) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithDifferentTokensOnDifferentChains_Success() (gas: 189438) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithDisabledRateLimitToken_Success() (gas: 61662) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitDisabled_Success() (gas: 46683) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitExceeded_Revert() (gas: 52371) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitReset_Success() (gas: 79845) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithTokensOnDifferentChains_Success() (gas: 263724) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithTokens_Success() (gas: 56541) -MultiAggregateRateLimiter_setPriceRegistry:test_OnlyOwner_Revert() (gas: 11336) -MultiAggregateRateLimiter_setPriceRegistry:test_Owner_Success() (gas: 19124) -MultiAggregateRateLimiter_setPriceRegistry:test_ZeroAddress_Revert() (gas: 10608) -MultiAggregateRateLimiter_updateRateLimitTokens:test_NonOwner_Revert() (gas: 16085) -MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokensMultipleChains_Success() (gas: 225643) -MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokensSingleChain_Success() (gas: 200192) -MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokens_AddsAndRemoves_Success() (gas: 162053) -MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokens_RemoveNonExistentToken_Success() (gas: 28509) -MultiAggregateRateLimiter_updateRateLimitTokens:test_ZeroDestToken_Revert() (gas: 17430) -MultiAggregateRateLimiter_updateRateLimitTokens:test_ZeroSourceToken_Revert() (gas: 17485) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitExceeded_Revert() (gas: 50542) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitReset_Success() (gas: 78668) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithTokensOnDifferentChains_Success() (gas: 311927) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithTokens_Success() (gas: 54728) +MultiAggregateRateLimiter_onOutboundMessage:test_RateLimitValueDifferentLanes_Success() (gas: 1073667529) +MultiAggregateRateLimiter_onOutboundMessage:test_ValidateMessageWithNoTokens_Success() (gas: 19149) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageFromUnauthorizedCaller_Revert() (gas: 15823) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithDifferentTokensOnDifferentChains_Success() (gas: 213716) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithDisabledRateLimitToken_Success() (gas: 62217) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitDisabled_Success() (gas: 46728) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitExceeded_Revert() (gas: 52360) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitReset_Success() (gas: 79913) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithTokensOnDifferentChains_Success() (gas: 312231) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithTokens_Success() (gas: 56530) +MultiAggregateRateLimiter_setFeeQuoter:test_OnlyOwner_Revert() (gas: 11313) +MultiAggregateRateLimiter_setFeeQuoter:test_Owner_Success() (gas: 19066) +MultiAggregateRateLimiter_setFeeQuoter:test_ZeroAddress_Revert() (gas: 10585) +MultiAggregateRateLimiter_updateRateLimitTokens:test_NonOwner_Revert() (gas: 18850) +MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokensMultipleChains_Success() (gas: 279972) +MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokensSingleChain_Success() (gas: 254523) +MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokens_AddsAndRemoves_Success() (gas: 204488) +MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokens_RemoveNonExistentToken_Success() (gas: 28703) +MultiAggregateRateLimiter_updateRateLimitTokens:test_ZeroDestToken_Revert() (gas: 18287) +MultiAggregateRateLimiter_updateRateLimitTokens:test_ZeroSourceToken_Revert() (gas: 18216) MultiOCR3Base_setOCR3Configs:test_FMustBePositive_Revert() (gas: 59331) MultiOCR3Base_setOCR3Configs:test_FTooHigh_Revert() (gas: 44298) MultiOCR3Base_setOCR3Configs:test_RepeatSignerAddress_Revert() (gas: 283711) @@ -598,29 +565,30 @@ MultiOCR3Base_transmit:test_UnAuthorizedTransmitter_Revert() (gas: 24191) MultiOCR3Base_transmit:test_UnauthorizedSigner_Revert() (gas: 61409) MultiOCR3Base_transmit:test_UnconfiguredPlugin_Revert() (gas: 39890) MultiOCR3Base_transmit:test_ZeroSignatures_Revert() (gas: 32973) -MultiOnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 412349) -MultiRampsE2E:test_E2E_3MessagesSuccess_gas() (gas: 1423227) +MultiOnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 414301) +MultiRampsE2E:test_E2E_3MessagesMMultiOffRampSuccess_gas() (gas: 1501445) NonceManager_NonceIncrementation:test_getIncrementedOutboundNonce_Success() (gas: 37907) NonceManager_NonceIncrementation:test_incrementInboundNonce_Skip() (gas: 23694) NonceManager_NonceIncrementation:test_incrementInboundNonce_Success() (gas: 38763) NonceManager_NonceIncrementation:test_incrementNoncesInboundAndOutbound_Success() (gas: 71847) -NonceManager_OffRampUpgrade:test_NoPrevOffRampForChain_Success() (gas: 252566) -NonceManager_OffRampUpgrade:test_UpgradedNonceNewSenderStartsAtZero_Success() (gas: 254866) -NonceManager_OffRampUpgrade:test_UpgradedNonceStartsAtV1Nonce_Success() (gas: 307885) -NonceManager_OffRampUpgrade:test_UpgradedOffRampNonceSkipsIfMsgInFlight_Success() (gas: 290962) -NonceManager_OffRampUpgrade:test_UpgradedSenderNoncesReadsPreviousRampTransitive_Success() (gas: 247990) -NonceManager_OffRampUpgrade:test_UpgradedSenderNoncesReadsPreviousRamp_Success() (gas: 236024) -NonceManager_OffRampUpgrade:test_Upgraded_Success() (gas: 144774) -NonceManager_OnRampUpgrade:test_UpgradeNonceNewSenderStartsAtZero_Success() (gas: 186669) -NonceManager_OnRampUpgrade:test_UpgradeNonceStartsAtV1Nonce_Success() (gas: 237737) -NonceManager_OnRampUpgrade:test_UpgradeSenderNoncesReadsPreviousRamp_Success() (gas: 124995) -NonceManager_OnRampUpgrade:test_Upgrade_Success() (gas: 125923) -NonceManager_applyPreviousRampsUpdates:test_MultipleRampsUpdates() (gas: 122899) +NonceManager_OffRampUpgrade:test_NoPrevOffRampForChain_Success() (gas: 260262) +NonceManager_OffRampUpgrade:test_UpgradedNonceNewSenderStartsAtZero_Success() (gas: 262359) +NonceManager_OffRampUpgrade:test_UpgradedNonceStartsAtV1Nonce_Success() (gas: 326051) +NonceManager_OffRampUpgrade:test_UpgradedOffRampNonceSkipsIfMsgInFlight_Success() (gas: 298263) +NonceManager_OffRampUpgrade:test_UpgradedSenderNoncesReadsPreviousRampTransitive_Success() (gas: 244814) +NonceManager_OffRampUpgrade:test_UpgradedSenderNoncesReadsPreviousRamp_Success() (gas: 233069) +NonceManager_OffRampUpgrade:test_Upgraded_Success() (gas: 153186) +NonceManager_OnRampUpgrade:test_UpgradeNonceNewSenderStartsAtZero_Success() (gas: 168681) +NonceManager_OnRampUpgrade:test_UpgradeNonceStartsAtV1Nonce_Success() (gas: 220836) +NonceManager_OnRampUpgrade:test_UpgradeSenderNoncesReadsPreviousRamp_Success() (gas: 125070) +NonceManager_OnRampUpgrade:test_Upgrade_Success() (gas: 107910) +NonceManager_applyPreviousRampsUpdates:test_MultipleRampsUpdates() (gas: 122943) NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySetOffRamp_Revert() (gas: 42959) NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySetOnRampAndOffRamp_Revert() (gas: 64282) NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySetOnRamp_Revert() (gas: 42823) -NonceManager_applyPreviousRampsUpdates:test_SingleRampUpdate() (gas: 66548) +NonceManager_applyPreviousRampsUpdates:test_SingleRampUpdate() (gas: 66570) NonceManager_applyPreviousRampsUpdates:test_ZeroInput() (gas: 12025) +NonceManager_typeAndVersion:test_typeAndVersion() (gas: 9675) OCR2BaseNoChecks_setOCR2Config:test_FMustBePositive_Revert() (gas: 12171) OCR2BaseNoChecks_setOCR2Config:test_RepeatAddress_Revert() (gas: 42233) OCR2BaseNoChecks_setOCR2Config:test_SetConfigSuccess_gas() (gas: 84124) @@ -646,112 +614,192 @@ OCR2Base_transmit:test_Transmit2SignersSuccess_gas() (gas: 51674) OCR2Base_transmit:test_UnAuthorizedTransmitter_Revert() (gas: 23484) OCR2Base_transmit:test_UnauthorizedSigner_Revert() (gas: 39665) OCR2Base_transmit:test_WrongNumberOfSignatures_Revert() (gas: 20557) -OnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 380360) -PingPong_ccipReceive:test_CcipReceive_Success() (gas: 150880) -PingPong_plumbing:test_Pausing_Success() (gas: 17803) -PingPong_startPingPong:test_StartPingPong_Success() (gas: 178340) -PriceRegistry_applyDestChainConfigUpdates:test_InvalidChainFamilySelector_Revert() (gas: 16719) -PriceRegistry_applyDestChainConfigUpdates:test_InvalidDestBytesOverhead_Revert() (gas: 16784) -PriceRegistry_applyDestChainConfigUpdates:test_InvalidDestChainConfigDestChainSelectorEqZero_Revert() (gas: 16611) -PriceRegistry_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesDefaultTxGasLimitEqZero_Revert() (gas: 16675) -PriceRegistry_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesDefaultTxGasLimitGtMaxPerMessageGasLimit_Revert() (gas: 40953) -PriceRegistry_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesZeroIntput_Success() (gas: 12341) -PriceRegistry_applyDestChainConfigUpdates:test_applyDestChainConfigUpdates_Success() (gas: 139564) -PriceRegistry_applyFeeTokensUpdates:test_ApplyFeeTokensUpdates_Success() (gas: 80002) -PriceRegistry_applyFeeTokensUpdates:test_OnlyCallableByOwner_Revert() (gas: 12603) -PriceRegistry_applyPremiumMultiplierWeiPerEthUpdates:test_OnlyCallableByOwnerOrAdmin_Revert() (gas: 11465) -PriceRegistry_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesMultipleTokens_Success() (gas: 54149) -PriceRegistry_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesSingleToken_Success() (gas: 44835) -PriceRegistry_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesZeroInput() (gas: 12301) -PriceRegistry_applyTokenTransferFeeConfigUpdates:test_ApplyTokenTransferFeeConfig_Success() (gas: 86826) -PriceRegistry_applyTokenTransferFeeConfigUpdates:test_ApplyTokenTransferFeeZeroInput() (gas: 13089) -PriceRegistry_applyTokenTransferFeeConfigUpdates:test_InvalidDestBytesOverhead_Revert() (gas: 17045) -PriceRegistry_applyTokenTransferFeeConfigUpdates:test_OnlyCallableByOwnerOrAdmin_Revert() (gas: 12240) -PriceRegistry_constructor:test_InvalidLinkTokenEqZeroAddress_Revert() (gas: 105966) -PriceRegistry_constructor:test_InvalidMaxFeeJuelsPerMsg_Revert() (gas: 110316) -PriceRegistry_constructor:test_InvalidStalenessThreshold_Revert() (gas: 110369) -PriceRegistry_constructor:test_Setup_Success() (gas: 4650895) -PriceRegistry_convertTokenAmount:test_ConvertTokenAmount_Success() (gas: 72751) -PriceRegistry_convertTokenAmount:test_LinkTokenNotSupported_Revert() (gas: 30981) -PriceRegistry_getDataAvailabilityCost:test_EmptyMessageCalculatesDataAvailabilityCost_Success() (gas: 95575) -PriceRegistry_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCostUnsupportedDestChainSelector_Success() (gas: 14636) -PriceRegistry_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCost_Success() (gas: 20614) -PriceRegistry_getTokenAndGasPrices:test_GetFeeTokenAndGasPrices_Success() (gas: 70449) -PriceRegistry_getTokenAndGasPrices:test_StaleGasPrice_Revert() (gas: 16838) -PriceRegistry_getTokenAndGasPrices:test_UnsupportedChain_Revert() (gas: 16140) -PriceRegistry_getTokenAndGasPrices:test_ZeroGasPrice_Success() (gas: 45734) -PriceRegistry_getTokenPrice:test_GetTokenPriceFromFeed_Success() (gas: 62311) -PriceRegistry_getTokenPrices:test_GetTokenPrices_Success() (gas: 84774) -PriceRegistry_getTokenTransferCost:test_CustomTokenBpsFee_Success() (gas: 41283) -PriceRegistry_getTokenTransferCost:test_FeeTokenBpsFee_Success() (gas: 34733) -PriceRegistry_getTokenTransferCost:test_LargeTokenTransferChargesMaxFeeAndGas_Success() (gas: 27807) -PriceRegistry_getTokenTransferCost:test_MixedTokenTransferFee_Success() (gas: 108018) -PriceRegistry_getTokenTransferCost:test_NoTokenTransferChargesZeroFee_Success() (gas: 20359) -PriceRegistry_getTokenTransferCost:test_SmallTokenTransferChargesMinFeeAndGas_Success() (gas: 27615) -PriceRegistry_getTokenTransferCost:test_WETHTokenBpsFee_Success() (gas: 40668) -PriceRegistry_getTokenTransferCost:test_ZeroAmountTokenTransferChargesMinFeeAndGas_Success() (gas: 27638) -PriceRegistry_getTokenTransferCost:test_ZeroFeeConfigChargesMinFee_Success() (gas: 40015) -PriceRegistry_getTokenTransferCost:test_getTokenTransferCost_selfServeUsesDefaults_Success() (gas: 29343) -PriceRegistry_getValidatedFee:test_DestinationChainNotEnabled_Revert() (gas: 18203) -PriceRegistry_getValidatedFee:test_EmptyMessage_Success() (gas: 81464) -PriceRegistry_getValidatedFee:test_EnforceOutOfOrder_Revert() (gas: 55184) -PriceRegistry_getValidatedFee:test_HighGasMessage_Success() (gas: 237926) -PriceRegistry_getValidatedFee:test_InvalidEVMAddress_Revert() (gas: 19971) -PriceRegistry_getValidatedFee:test_MessageGasLimitTooHigh_Revert() (gas: 31775) -PriceRegistry_getValidatedFee:test_MessageTooLarge_Revert() (gas: 97714) -PriceRegistry_getValidatedFee:test_MessageWithDataAndTokenTransfer_Success() (gas: 143193) -PriceRegistry_getValidatedFee:test_NotAFeeToken_Revert() (gas: 29435) -PriceRegistry_getValidatedFee:test_SingleTokenMessage_Success() (gas: 112283) -PriceRegistry_getValidatedFee:test_TooManyTokens_Revert() (gas: 20107) -PriceRegistry_getValidatedFee:test_ZeroDataAvailabilityMultiplier_Success() (gas: 62956) -PriceRegistry_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Above18Decimals_Success() (gas: 2094532) -PriceRegistry_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Below18Decimals_Success() (gas: 2094490) -PriceRegistry_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt0Decimals_Success() (gas: 2074609) -PriceRegistry_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt18Decimals_Success() (gas: 2094264) -PriceRegistry_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFlippedDecimals_Success() (gas: 2094468) -PriceRegistry_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedMaxInt224Value_Success() (gas: 2094280) -PriceRegistry_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedOverStalenessPeriod_Success() (gas: 61997) -PriceRegistry_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeed_Success() (gas: 61877) -PriceRegistry_getValidatedTokenPrice:test_GetValidatedTokenPrice_Success() (gas: 60998) -PriceRegistry_getValidatedTokenPrice:test_OverflowFeedPrice_Revert() (gas: 2093992) -PriceRegistry_getValidatedTokenPrice:test_StaleFeeToken_Success() (gas: 61525) -PriceRegistry_getValidatedTokenPrice:test_TokenNotSupportedFeed_Revert() (gas: 109113) -PriceRegistry_getValidatedTokenPrice:test_TokenNotSupported_Revert() (gas: 13819) -PriceRegistry_getValidatedTokenPrice:test_UnderflowFeedPrice_Revert() (gas: 2092670) -PriceRegistry_parseEVMExtraArgsFromBytes:test_EVMExtraArgsDefault_Success() (gas: 17360) -PriceRegistry_parseEVMExtraArgsFromBytes:test_EVMExtraArgsEnforceOutOfOrder_Revert() (gas: 21454) -PriceRegistry_parseEVMExtraArgsFromBytes:test_EVMExtraArgsGasLimitTooHigh_Revert() (gas: 18551) -PriceRegistry_parseEVMExtraArgsFromBytes:test_EVMExtraArgsInvalidExtraArgsTag_Revert() (gas: 18075) -PriceRegistry_parseEVMExtraArgsFromBytes:test_EVMExtraArgsV1_Success() (gas: 18452) -PriceRegistry_parseEVMExtraArgsFromBytes:test_EVMExtraArgsV2_Success() (gas: 18569) -PriceRegistry_processMessageArgs:test_InvalidExtraArgs_Revert() (gas: 18306) -PriceRegistry_processMessageArgs:test_MalformedEVMExtraArgs_Revert() (gas: 18852) -PriceRegistry_processMessageArgs:test_MessageFeeTooHigh_Revert() (gas: 16360) -PriceRegistry_processMessageArgs:test_WitEVMExtraArgsV2_Success() (gas: 26236) -PriceRegistry_processMessageArgs:test_WithConvertedTokenAmount_Success() (gas: 32410) -PriceRegistry_processMessageArgs:test_WithEVMExtraArgsV1_Success() (gas: 25848) -PriceRegistry_processMessageArgs:test_WithEmptyEVMExtraArgs_Success() (gas: 23663) -PriceRegistry_processMessageArgs:test_WithLinkTokenAmount_Success() (gas: 17320) -PriceRegistry_updatePrices:test_OnlyCallableByUpdater_Revert() (gas: 12080) -PriceRegistry_updatePrices:test_OnlyGasPrice_Success() (gas: 23599) -PriceRegistry_updatePrices:test_OnlyTokenPrice_Success() (gas: 30637) -PriceRegistry_updatePrices:test_UpdatableByAuthorizedCaller_Success() (gas: 76043) -PriceRegistry_updatePrices:test_UpdateMultiplePrices_Success() (gas: 151521) -PriceRegistry_updateTokenPriceFeeds:test_FeedNotUpdated() (gas: 50699) -PriceRegistry_updateTokenPriceFeeds:test_FeedUnset_Success() (gas: 63882) -PriceRegistry_updateTokenPriceFeeds:test_FeedUpdatedByNonOwner_Revert() (gas: 19998) -PriceRegistry_updateTokenPriceFeeds:test_MultipleFeedUpdate_Success() (gas: 89162) -PriceRegistry_updateTokenPriceFeeds:test_SingleFeedUpdate_Success() (gas: 50949) -PriceRegistry_updateTokenPriceFeeds:test_ZeroFeeds_Success() (gas: 12362) -PriceRegistry_validateDestFamilyAddress:test_InvalidEVMAddressEncodePacked_Revert() (gas: 10572) -PriceRegistry_validateDestFamilyAddress:test_InvalidEVMAddressPrecompiles_Revert() (gas: 3916546) -PriceRegistry_validateDestFamilyAddress:test_InvalidEVMAddress_Revert() (gas: 10756) -PriceRegistry_validateDestFamilyAddress:test_ValidEVMAddress_Success() (gas: 6660) -PriceRegistry_validateDestFamilyAddress:test_ValidNonEVMAddress_Success() (gas: 6440) -PriceRegistry_validatePoolReturnData:test_InvalidEVMAddressDestToken_Revert() (gas: 35457) -PriceRegistry_validatePoolReturnData:test_SourceTokenDataTooLarge_Revert() (gas: 90631) -PriceRegistry_validatePoolReturnData:test_TokenAmountArraysMismatching_Revert() (gas: 32749) -PriceRegistry_validatePoolReturnData:test_WithSingleToken_Success() (gas: 31293) +OffRamp__releaseOrMintSingleToken:test__releaseOrMintSingleToken_NotACompatiblePool_Revert() (gas: 40149) +OffRamp__releaseOrMintSingleToken:test__releaseOrMintSingleToken_Success() (gas: 107130) +OffRamp__releaseOrMintSingleToken:test__releaseOrMintSingleToken_TokenHandlingError_transfer_Revert() (gas: 88331) +OffRamp__releaseOrMintSingleToken:test_releaseOrMintToken_InvalidDataLength_Revert() (gas: 39848) +OffRamp__releaseOrMintSingleToken:test_releaseOrMintToken_ReleaseOrMintBalanceMismatch_Revert() (gas: 97399) +OffRamp__releaseOrMintSingleToken:test_releaseOrMintToken_TokenHandlingError_BalanceOf_Revert() (gas: 42843) +OffRamp__releaseOrMintSingleToken:test_releaseOrMintToken_skip_ReleaseOrMintBalanceMismatch_if_pool_Revert() (gas: 89579) +OffRamp_applySourceChainConfigUpdates:test_AddMultipleChains_Success() (gas: 467917) +OffRamp_applySourceChainConfigUpdates:test_AddNewChain_Success() (gas: 99183) +OffRamp_applySourceChainConfigUpdates:test_ApplyZeroUpdates_Success() (gas: 12395) +OffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChainOnRamp_Revert() (gas: 93181) +OffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChain_Success() (gas: 109824) +OffRamp_applySourceChainConfigUpdates:test_RouterAddress_Revert() (gas: 13263) +OffRamp_applySourceChainConfigUpdates:test_ZeroOnRampAddress_Revert() (gas: 17988) +OffRamp_applySourceChainConfigUpdates:test_ZeroSourceChainSelector_Revert() (gas: 15300) +OffRamp_batchExecute:test_MultipleReportsDifferentChains_Success() (gas: 322171) +OffRamp_batchExecute:test_MultipleReportsSameChain_Success() (gas: 263506) +OffRamp_batchExecute:test_MultipleReportsSkipDuplicate_Success() (gas: 169162) +OffRamp_batchExecute:test_OutOfBoundsGasLimitsAccess_Revert() (gas: 188589) +OffRamp_batchExecute:test_SingleReport_Success() (gas: 156230) +OffRamp_batchExecute:test_Unhealthy_Revert() (gas: 533834) +OffRamp_batchExecute:test_ZeroReports_Revert() (gas: 10461) +OffRamp_ccipReceive:test_Reverts() (gas: 15773) +OffRamp_commit:test_InvalidIntervalMinLargerThanMax_Revert() (gas: 67458) +OffRamp_commit:test_InvalidInterval_Revert() (gas: 59778) +OffRamp_commit:test_InvalidRootRevert() (gas: 58858) +OffRamp_commit:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6560573) +OffRamp_commit:test_NoConfig_Revert() (gas: 6143711) +OffRamp_commit:test_OnlyGasPriceUpdates_Success() (gas: 106317) +OffRamp_commit:test_OnlyPriceUpdateStaleReport_Revert() (gas: 116369) +OffRamp_commit:test_OnlyTokenPriceUpdates_Success() (gas: 106338) +OffRamp_commit:test_PriceSequenceNumberCleared_Success() (gas: 351652) +OffRamp_commit:test_ReportAndPriceUpdate_Success() (gas: 159342) +OffRamp_commit:test_ReportOnlyRootSuccess_gas() (gas: 136480) +OffRamp_commit:test_RootAlreadyCommitted_Revert() (gas: 136880) +OffRamp_commit:test_SourceChainNotEnabled_Revert() (gas: 59126) +OffRamp_commit:test_StaleReportWithRoot_Success() (gas: 225582) +OffRamp_commit:test_UnauthorizedTransmitter_Revert() (gas: 117632) +OffRamp_commit:test_Unhealthy_Revert() (gas: 77674) +OffRamp_commit:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 205066) +OffRamp_commit:test_WrongConfigWithoutSigners_Revert() (gas: 6554962) +OffRamp_commit:test_ZeroEpochAndRound_Revert() (gas: 47832) +OffRamp_constructor:test_Constructor_Success() (gas: 6147616) +OffRamp_constructor:test_SourceChainSelector_Revert() (gas: 137128) +OffRamp_constructor:test_ZeroChainSelector_Revert() (gas: 103845) +OffRamp_constructor:test_ZeroNonceManager_Revert() (gas: 101716) +OffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 139680) +OffRamp_constructor:test_ZeroRMNProxy_Revert() (gas: 101593) +OffRamp_constructor:test_ZeroTokenAdminRegistry_Revert() (gas: 101660) +OffRamp_execute:test_IncorrectArrayType_Revert() (gas: 17305) +OffRamp_execute:test_LargeBatch_Success() (gas: 1828972) +OffRamp_execute:test_MultipleReportsWithPartialValidationFailures_Success() (gas: 358063) +OffRamp_execute:test_MultipleReports_Success() (gas: 285617) +OffRamp_execute:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6611685) +OffRamp_execute:test_NoConfig_Revert() (gas: 6194563) +OffRamp_execute:test_NonArray_Revert() (gas: 27809) +OffRamp_execute:test_SingleReport_Success() (gas: 175620) +OffRamp_execute:test_UnauthorizedTransmitter_Revert() (gas: 147848) +OffRamp_execute:test_WrongConfigWithSigners_Revert() (gas: 6973803) +OffRamp_execute:test_ZeroReports_Revert() (gas: 17225) +OffRamp_executeSingleMessage:test_MessageSender_Revert() (gas: 18257) +OffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 249037) +OffRamp_executeSingleMessage:test_NonContract_Success() (gas: 20517) +OffRamp_executeSingleMessage:test_TokenHandlingError_Revert() (gas: 210176) +OffRamp_executeSingleMessage:test_ZeroGasDONExecution_Revert() (gas: 48779) +OffRamp_executeSingleMessage:test_executeSingleMessage_NoTokens_Success() (gas: 48302) +OffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidationNoRouterCall_Revert() (gas: 229565) +OffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidation_Revert() (gas: 86203) +OffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens_Success() (gas: 280859) +OffRamp_executeSingleMessage:test_executeSingleMessage_WithValidation_Success() (gas: 92437) +OffRamp_executeSingleReport:test_DisabledSourceChain_Revert() (gas: 35104) +OffRamp_executeSingleReport:test_EmptyReport_Revert() (gas: 23923) +OffRamp_executeSingleReport:test_InvalidSourcePoolAddress_Success() (gas: 492333) +OffRamp_executeSingleReport:test_ManualExecutionNotYetEnabled_Revert() (gas: 54457) +OffRamp_executeSingleReport:test_MismatchingDestChainSelector_Revert() (gas: 35927) +OffRamp_executeSingleReport:test_MismatchingOnRampRoot_Revert() (gas: 154493) +OffRamp_executeSingleReport:test_NonExistingSourceChain_Revert() (gas: 35338) +OffRamp_executeSingleReport:test_ReceiverError_Success() (gas: 187911) +OffRamp_executeSingleReport:test_RetryFailedMessageWithoutManualExecution_Revert() (gas: 199215) +OffRamp_executeSingleReport:test_RootNotCommitted_Revert() (gas: 48096) +OffRamp_executeSingleReport:test_RouterYULCall_Revert() (gas: 447759) +OffRamp_executeSingleReport:test_SingleMessageNoTokensOtherChain_Success() (gas: 251078) +OffRamp_executeSingleReport:test_SingleMessageNoTokensUnordered_Success() (gas: 193345) +OffRamp_executeSingleReport:test_SingleMessageNoTokens_Success() (gas: 212938) +OffRamp_executeSingleReport:test_SingleMessageToNonCCIPReceiver_Success() (gas: 266576) +OffRamp_executeSingleReport:test_SingleMessagesNoTokensSuccess_gas() (gas: 141191) +OffRamp_executeSingleReport:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 423378) +OffRamp_executeSingleReport:test_SkippedIncorrectNonce_Success() (gas: 65877) +OffRamp_executeSingleReport:test_TokenDataMismatch_Revert() (gas: 80932) +OffRamp_executeSingleReport:test_TwoMessagesWithTokensAndGE_Success() (gas: 587410) +OffRamp_executeSingleReport:test_TwoMessagesWithTokensSuccess_gas() (gas: 535220) +OffRamp_executeSingleReport:test_UnexpectedTokenData_Revert() (gas: 35743) +OffRamp_executeSingleReport:test_UnhealthySingleChainCurse_Revert() (gas: 532474) +OffRamp_executeSingleReport:test_Unhealthy_Revert() (gas: 529798) +OffRamp_executeSingleReport:test_WithCurseOnAnotherSourceChain_Success() (gas: 495040) +OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessageUnordered_Success() (gas: 136580) +OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessage_Success() (gas: 165799) +OffRamp_getExecutionState:test_FillExecutionState_Success() (gas: 3742124) +OffRamp_getExecutionState:test_GetDifferentChainExecutionState_Success() (gas: 118836) +OffRamp_getExecutionState:test_GetExecutionState_Success() (gas: 88048) +OffRamp_manuallyExecute:test_ManualExecGasLimitMismatchSingleReport_Revert() (gas: 75551) +OffRamp_manuallyExecute:test_ManualExecInvalidGasLimit_Revert() (gas: 26439) +OffRamp_manuallyExecute:test_manuallyExecute_DoesNotRevertIfUntouched_Success() (gas: 171639) +OffRamp_manuallyExecute:test_manuallyExecute_FailedTx_Revert() (gas: 205796) +OffRamp_manuallyExecute:test_manuallyExecute_ForkedChain_Revert() (gas: 25993) +OffRamp_manuallyExecute:test_manuallyExecute_GasLimitMismatchMultipleReports_Revert() (gas: 152822) +OffRamp_manuallyExecute:test_manuallyExecute_LowGasLimit_Success() (gas: 524603) +OffRamp_manuallyExecute:test_manuallyExecute_ReentrancyFails_Success() (gas: 2388943) +OffRamp_manuallyExecute:test_manuallyExecute_Success() (gas: 208553) +OffRamp_manuallyExecute:test_manuallyExecute_WithGasOverride_Success() (gas: 219343) +OffRamp_manuallyExecute:test_manuallyExecute_WithMultiReportGasOverride_Success() (gas: 663643) +OffRamp_manuallyExecute:test_manuallyExecute_WithPartialMessages_Success() (gas: 330148) +OffRamp_releaseOrMintTokens:test_TokenHandlingError_Reverts() (gas: 165822) +OffRamp_releaseOrMintTokens:test__releaseOrMintTokens_PoolIsNotAPool_Reverts() (gas: 24603) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_InvalidDataLengthReturnData_Revert() (gas: 66285) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_InvalidEVMAddress_Revert() (gas: 41316) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_PoolDoesNotSupportDest_Reverts() (gas: 83291) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_Success() (gas: 177934) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals_Success() (gas: 191136) +OffRamp_resetUnblessedRoots:test_OnlyOwner_Revert() (gas: 11423) +OffRamp_resetUnblessedRoots:test_ResetUnblessedRoots_Success() (gas: 215373) +OffRamp_setDynamicConfig:test_FeeQuoterZeroAddress_Revert() (gas: 11585) +OffRamp_setDynamicConfig:test_NonOwner_Revert() (gas: 14152) +OffRamp_setDynamicConfig:test_SetDynamicConfigWithValidator_Success() (gas: 49115) +OffRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 27037) +OffRamp_trialExecute:test_RateLimitError_Success() (gas: 225795) +OffRamp_trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 234416) +OffRamp_trialExecute:test_TokenPoolIsNotAContract_Success() (gas: 309206) +OffRamp_trialExecute:test_trialExecute_Success() (gas: 283994) +OffRamp_verify:test_Blessed_Success() (gas: 176664) +OffRamp_verify:test_NotBlessedWrongChainSelector_Success() (gas: 178754) +OffRamp_verify:test_NotBlessed_Success() (gas: 141593) +OffRamp_verify:test_TooManyLeaves_Revert() (gas: 51510) +OnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 390336) +OnRamp_allowListConfigUpdates:test_applyAllowList_Revert() (gas: 66509) +OnRamp_allowListConfigUpdates:test_applyAllowList_Success() (gas: 323566) +OnRamp_applyDestChainConfigUpdates:test_ApplyDestChainConfigUpdates_Success() (gas: 64501) +OnRamp_applyDestChainConfigUpdates:test_ApplyDestChainConfigUpdates_WithInvalidChainSelector_Revert() (gas: 13242) +OnRamp_constructor:test_Constructor_InvalidConfigChainSelectorEqZero_Revert() (gas: 94878) +OnRamp_constructor:test_Constructor_InvalidConfigNonceManagerEqAddressZero_Revert() (gas: 92812) +OnRamp_constructor:test_Constructor_InvalidConfigRMNProxyEqAddressZero_Revert() (gas: 97827) +OnRamp_constructor:test_Constructor_InvalidConfigTokenAdminRegistryEqAddressZero_Revert() (gas: 92870) +OnRamp_constructor:test_Constructor_Success() (gas: 2866937) +OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() (gas: 115250) +OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2_Success() (gas: 146019) +OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessCustomExtraArgs() (gas: 145615) +OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessEmptyExtraArgs() (gas: 143816) +OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessLegacyExtraArgs() (gas: 145847) +OnRamp_forwardFromRouter:test_ForwardFromRouter_Success() (gas: 145216) +OnRamp_forwardFromRouter:test_ForwardFromRouter_Success_ConfigurableSourceRouter() (gas: 140359) +OnRamp_forwardFromRouter:test_InvalidExtraArgsTag_Revert() (gas: 28810) +OnRamp_forwardFromRouter:test_MessageValidationError_Revert() (gas: 138683) +OnRamp_forwardFromRouter:test_MesssageFeeTooHigh_Revert() (gas: 26910) +OnRamp_forwardFromRouter:test_MultiCannotSendZeroTokens_Revert() (gas: 74456) +OnRamp_forwardFromRouter:test_OriginalSender_Revert() (gas: 12918) +OnRamp_forwardFromRouter:test_Paused_Revert() (gas: 37224) +OnRamp_forwardFromRouter:test_Permissions_Revert() (gas: 18179) +OnRamp_forwardFromRouter:test_ShouldIncrementNonceOnlyOnOrdered_Success() (gas: 185252) +OnRamp_forwardFromRouter:test_ShouldIncrementSeqNumAndNonce_Success() (gas: 211543) +OnRamp_forwardFromRouter:test_ShouldStoreLinkFees() (gas: 125128) +OnRamp_forwardFromRouter:test_ShouldStoreNonLinkFees() (gas: 146530) +OnRamp_forwardFromRouter:test_SourceTokenDataTooLarge_Revert() (gas: 3894232) +OnRamp_forwardFromRouter:test_UnAllowedOriginalSender_Revert() (gas: 18609) +OnRamp_forwardFromRouter:test_UnsupportedToken_Revert() (gas: 111118) +OnRamp_forwardFromRouter:test_forwardFromRouter_UnsupportedToken_Revert() (gas: 76545) +OnRamp_forwardFromRouter:test_forwardFromRouter_WithValidation_Success() (gas: 281240) +OnRamp_getFee:test_EmptyMessage_Success() (gas: 110107) +OnRamp_getFee:test_EnforceOutOfOrder_Revert() (gas: 75610) +OnRamp_getFee:test_GetFeeOfZeroForTokenMessage_Success() (gas: 95456) +OnRamp_getFee:test_NotAFeeTokenButPricedToken_Revert() (gas: 41814) +OnRamp_getFee:test_SingleTokenMessage_Success() (gas: 125476) +OnRamp_getFee:test_Unhealthy_Revert() (gas: 43669) +OnRamp_getSupportedTokens:test_GetSupportedTokens_Revert() (gas: 10438) +OnRamp_getTokenPool:test_GetTokenPool_Success() (gas: 35204) +OnRamp_setDynamicConfig:test_SetConfigInvalidConfigFeeAggregatorEqAddressZero_Revert() (gas: 11402) +OnRamp_setDynamicConfig:test_SetConfigInvalidConfigFeeQuoterEqAddressZero_Revert() (gas: 13001) +OnRamp_setDynamicConfig:test_SetConfigInvalidConfig_Revert() (gas: 11359) +OnRamp_setDynamicConfig:test_SetConfigOnlyOwner_Revert() (gas: 16385) +OnRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 55321) +OnRamp_withdrawFeeTokens:test_WithdrawFeeTokens_Success() (gas: 97107) +PingPong_ccipReceive:test_CcipReceive_Success() (gas: 152669) +PingPong_plumbing:test_OutOfOrderExecution_Success() (gas: 20277) +PingPong_plumbing:test_Pausing_Success() (gas: 17777) +PingPong_startPingPong:test_StartPingPong_With_OOO_Success() (gas: 163187) +PingPong_startPingPong:test_StartPingPong_With_Sequenced_Ordered_Success() (gas: 182599) +RMNHome:test() (gas: 186) RMN_constructor:test_Constructor_Success() (gas: 48838) RMN_getRecordedCurseRelatedOps:test_OpsPostDeployment() (gas: 19666) RMN_lazyVoteToCurseUpdate_Benchmark:test_VoteToCurseLazilyRetain3VotersUponConfigChange_gas() (gas: 152152) @@ -822,7 +870,7 @@ RateLimiter_consume:test_TokenRateLimitReached_Revert() (gas: 24706) RateLimiter_currentTokenBucketState:test_CurrentTokenBucketState_Success() (gas: 38647) RateLimiter_currentTokenBucketState:test_Refill_Success() (gas: 46384) RateLimiter_setTokenBucketConfig:test_SetRateLimiterConfig_Success() (gas: 38017) -RegistryModuleOwnerCustom_constructor:test_constructor_Revert() (gas: 36031) +RegistryModuleOwnerCustom_constructor:test_constructor_Revert() (gas: 36028) RegistryModuleOwnerCustom_registerAdminViaGetCCIPAdmin:test_registerAdminViaGetCCIPAdmin_Revert() (gas: 19637) RegistryModuleOwnerCustom_registerAdminViaGetCCIPAdmin:test_registerAdminViaGetCCIPAdmin_Success() (gas: 129918) RegistryModuleOwnerCustom_registerAdminViaOwner:test_registerAdminViaOwner_Revert() (gas: 19451) @@ -831,24 +879,24 @@ Router_applyRampUpdates:test_OffRampMismatch_Revert() (gas: 89288) Router_applyRampUpdates:test_OffRampUpdatesWithRouting() (gas: 10642128) Router_applyRampUpdates:test_OnRampDisable() (gas: 55913) Router_applyRampUpdates:test_OnlyOwner_Revert() (gas: 12311) -Router_ccipSend:test_CCIPSendLinkFeeNoTokenSuccess_gas() (gas: 113861) -Router_ccipSend:test_CCIPSendLinkFeeOneTokenSuccess_gas() (gas: 200634) -Router_ccipSend:test_CCIPSendNativeFeeNoTokenSuccess_gas() (gas: 128508) -Router_ccipSend:test_CCIPSendNativeFeeOneTokenSuccess_gas() (gas: 215283) -Router_ccipSend:test_FeeTokenAmountTooLow_Revert() (gas: 66275) +Router_ccipSend:test_CCIPSendLinkFeeNoTokenSuccess_gas() (gas: 113880) +Router_ccipSend:test_CCIPSendLinkFeeOneTokenSuccess_gas() (gas: 201336) +Router_ccipSend:test_CCIPSendNativeFeeNoTokenSuccess_gas() (gas: 128515) +Router_ccipSend:test_CCIPSendNativeFeeOneTokenSuccess_gas() (gas: 215973) +Router_ccipSend:test_FeeTokenAmountTooLow_Revert() (gas: 66269) Router_ccipSend:test_InvalidMsgValue() (gas: 31963) -Router_ccipSend:test_NativeFeeTokenInsufficientValue() (gas: 68711) -Router_ccipSend:test_NativeFeeTokenOverpay_Success() (gas: 173605) -Router_ccipSend:test_NativeFeeTokenZeroValue() (gas: 56037) -Router_ccipSend:test_NativeFeeToken_Success() (gas: 172199) -Router_ccipSend:test_NonLinkFeeToken_Success() (gas: 242707) +Router_ccipSend:test_NativeFeeTokenInsufficientValue() (gas: 68740) +Router_ccipSend:test_NativeFeeTokenOverpay_Success() (gas: 173606) +Router_ccipSend:test_NativeFeeTokenZeroValue() (gas: 56031) +Router_ccipSend:test_NativeFeeToken_Success() (gas: 172200) +Router_ccipSend:test_NonLinkFeeToken_Success() (gas: 242714) Router_ccipSend:test_UnsupportedDestinationChain_Revert() (gas: 24749) Router_ccipSend:test_WhenNotHealthy_Revert() (gas: 44724) -Router_ccipSend:test_WrappedNativeFeeToken_Success() (gas: 174415) -Router_ccipSend:test_ZeroFeeAndGasPrice_Success() (gas: 245121) +Router_ccipSend:test_WrappedNativeFeeToken_Success() (gas: 174416) +Router_ccipSend:test_ZeroFeeAndGasPrice_Success() (gas: 244854) Router_constructor:test_Constructor_Success() (gas: 13074) Router_getArmProxy:test_getArmProxy() (gas: 10561) -Router_getFee:test_GetFeeSupportedChain_Success() (gas: 46464) +Router_getFee:test_GetFeeSupportedChain_Success() (gas: 46458) Router_getFee:test_UnsupportedDestinationChain_Revert() (gas: 17138) Router_getSupportedTokens:test_GetSupportedTokens_Revert() (gas: 10460) Router_recoverTokens:test_RecoverTokensInvalidRecipient_Revert() (gas: 11316) @@ -857,14 +905,14 @@ Router_recoverTokens:test_RecoverTokensNonOwner_Revert() (gas: 11159) Router_recoverTokens:test_RecoverTokensValueReceiver_Revert() (gas: 422138) Router_recoverTokens:test_RecoverTokens_Success() (gas: 52437) Router_routeMessage:test_AutoExec_Success() (gas: 42684) -Router_routeMessage:test_ExecutionEvent_Success() (gas: 158002) +Router_routeMessage:test_ExecutionEvent_Success() (gas: 157980) Router_routeMessage:test_ManualExec_Success() (gas: 35381) Router_routeMessage:test_OnlyOffRamp_Revert() (gas: 25116) Router_routeMessage:test_WhenNotHealthy_Revert() (gas: 44724) Router_setWrappedNative:test_OnlyOwner_Revert() (gas: 10985) -SelfFundedPingPong_ccipReceive:test_FundingIfNotANop_Revert() (gas: 55540) -SelfFundedPingPong_ccipReceive:test_Funding_Success() (gas: 419430) -SelfFundedPingPong_setCountIncrBeforeFunding:test_setCountIncrBeforeFunding() (gas: 20157) +SelfFundedPingPong_ccipReceive:test_FundingIfNotANop_Revert() (gas: 55531) +SelfFundedPingPong_ccipReceive:test_Funding_Success() (gas: 419466) +SelfFundedPingPong_setCountIncrBeforeFunding:test_setCountIncrBeforeFunding() (gas: 20151) TokenAdminRegistry_acceptAdminRole:test_acceptAdminRole_OnlyPendingAdministrator_Revert() (gas: 51085) TokenAdminRegistry_acceptAdminRole:test_acceptAdminRole_Success() (gas: 43947) TokenAdminRegistry_addRegistryModule:test_addRegistryModule_OnlyOwner_Revert() (gas: 12629) @@ -887,57 +935,58 @@ TokenAdminRegistry_setPool:test_setPool_Success() (gas: 35943) TokenAdminRegistry_setPool:test_setPool_ZeroAddressRemovesPool_Success() (gas: 30617) TokenAdminRegistry_transferAdminRole:test_transferAdminRole_OnlyAdministrator_Revert() (gas: 18043) TokenAdminRegistry_transferAdminRole:test_transferAdminRole_Success() (gas: 49390) -TokenPoolAndProxy:test_lockOrBurn_burnMint_Success() (gas: 6036775) -TokenPoolAndProxy:test_lockOrBurn_lockRelease_Success() (gas: 6282531) -TokenPoolAndProxyMigration:test_tokenPoolMigration_Success_1_2() (gas: 6885897) -TokenPoolAndProxyMigration:test_tokenPoolMigration_Success_1_4() (gas: 7070012) -TokenPoolWithAllowList_applyAllowListUpdates:test_AllowListNotEnabled_Revert() (gas: 2169749) +TokenPoolAndProxy:test_lockOrBurn_burnMint_Success() (gas: 6070353) +TokenPoolAndProxy:test_lockOrBurn_burnWithFromMint_Success() (gas: 6101826) +TokenPoolAndProxy:test_lockOrBurn_lockRelease_Success() (gas: 6319594) +TokenPoolAndProxy:test_setPreviousPool_Success() (gas: 3387124) +TokenPoolAndProxyMigration:test_tokenPoolMigration_Success_1_2() (gas: 6916278) +TokenPoolAndProxyMigration:test_tokenPoolMigration_Success_1_4() (gas: 7100303) +TokenPoolWithAllowList_applyAllowListUpdates:test_AllowListNotEnabled_Revert() (gas: 2209837) TokenPoolWithAllowList_applyAllowListUpdates:test_OnlyOwner_Revert() (gas: 12089) -TokenPoolWithAllowList_applyAllowListUpdates:test_SetAllowListSkipsZero_Success() (gas: 23280) -TokenPoolWithAllowList_applyAllowListUpdates:test_SetAllowList_Success() (gas: 177516) -TokenPoolWithAllowList_getAllowList:test_GetAllowList_Success() (gas: 23648) +TokenPoolWithAllowList_applyAllowListUpdates:test_SetAllowListSkipsZero_Success() (gas: 23324) +TokenPoolWithAllowList_applyAllowListUpdates:test_SetAllowList_Success() (gas: 177568) +TokenPoolWithAllowList_getAllowList:test_GetAllowList_Success() (gas: 23670) TokenPoolWithAllowList_getAllowListEnabled:test_GetAllowListEnabled_Success() (gas: 8363) -TokenPoolWithAllowList_setRouter:test_SetRouter_Success() (gas: 24765) +TokenPoolWithAllowList_setRouter:test_SetRouter_Success() (gas: 24831) TokenPool_applyChainUpdates:test_applyChainUpdates_DisabledNonZeroRateLimit_Revert() (gas: 271305) TokenPool_applyChainUpdates:test_applyChainUpdates_InvalidRateLimitRate_Revert() (gas: 541162) TokenPool_applyChainUpdates:test_applyChainUpdates_NonExistentChain_Revert() (gas: 18344) TokenPool_applyChainUpdates:test_applyChainUpdates_OnlyCallableByOwner_Revert() (gas: 11385) -TokenPool_applyChainUpdates:test_applyChainUpdates_Success() (gas: 476472) +TokenPool_applyChainUpdates:test_applyChainUpdates_Success() (gas: 476468) TokenPool_applyChainUpdates:test_applyChainUpdates_ZeroAddressNotAllowed_Revert() (gas: 157074) -TokenPool_constructor:test_ZeroAddressNotAllowed_Revert() (gas: 70676) -TokenPool_constructor:test_immutableFields_Success() (gas: 20522) +TokenPool_constructor:test_ZeroAddressNotAllowed_Revert() (gas: 70721) +TokenPool_constructor:test_immutableFields_Success() (gas: 20544) TokenPool_getRemotePool:test_getRemotePool_Success() (gas: 273962) -TokenPool_onlyOffRamp:test_CallerIsNotARampOnRouter_Revert() (gas: 276952) -TokenPool_onlyOffRamp:test_ChainNotAllowed_Revert() (gas: 289509) -TokenPool_onlyOffRamp:test_onlyOffRamp_Success() (gas: 349763) +TokenPool_onlyOffRamp:test_CallerIsNotARampOnRouter_Revert() (gas: 276909) +TokenPool_onlyOffRamp:test_ChainNotAllowed_Revert() (gas: 289406) +TokenPool_onlyOffRamp:test_onlyOffRamp_Success() (gas: 349720) TokenPool_onlyOnRamp:test_CallerIsNotARampOnRouter_Revert() (gas: 276643) -TokenPool_onlyOnRamp:test_ChainNotAllowed_Revert() (gas: 253466) +TokenPool_onlyOnRamp:test_ChainNotAllowed_Revert() (gas: 253432) TokenPool_onlyOnRamp:test_onlyOnRamp_Success() (gas: 304761) -TokenPool_setChainRateLimiterConfig:test_NonExistentChain_Revert() (gas: 14906) -TokenPool_setChainRateLimiterConfig:test_OnlyOwner_Revert() (gas: 12565) -TokenPool_setRemotePool:test_setRemotePool_NonExistentChain_Reverts() (gas: 15598) -TokenPool_setRemotePool:test_setRemotePool_OnlyOwner_Reverts() (gas: 13173) -TokenPool_setRemotePool:test_setRemotePool_Success() (gas: 281890) +TokenPool_setChainRateLimiterConfig:test_NonExistentChain_Revert() (gas: 17061) +TokenPool_setChainRateLimiterConfig:test_OnlyOwnerOrRateLimitAdmin_Revert() (gas: 15062) +TokenPool_setRemotePool:test_setRemotePool_NonExistentChain_Reverts() (gas: 15620) +TokenPool_setRemotePool:test_setRemotePool_OnlyOwner_Reverts() (gas: 13195) +TokenPool_setRemotePool:test_setRemotePool_Success() (gas: 281912) TokenProxy_ccipSend:test_CcipSendGasShouldBeZero_Revert() (gas: 17109) -TokenProxy_ccipSend:test_CcipSendInsufficientAllowance_Revert() (gas: 136351) +TokenProxy_ccipSend:test_CcipSendInsufficientAllowance_Revert() (gas: 136222) TokenProxy_ccipSend:test_CcipSendInvalidToken_Revert() (gas: 15919) -TokenProxy_ccipSend:test_CcipSendNative_Success() (gas: 244483) +TokenProxy_ccipSend:test_CcipSendNative_Success() (gas: 245173) TokenProxy_ccipSend:test_CcipSendNoDataAllowed_Revert() (gas: 16303) -TokenProxy_ccipSend:test_CcipSend_Success() (gas: 261100) +TokenProxy_ccipSend:test_CcipSend_Success() (gas: 261558) TokenProxy_constructor:test_Constructor() (gas: 13812) TokenProxy_getFee:test_GetFeeGasShouldBeZero_Revert() (gas: 16827) TokenProxy_getFee:test_GetFeeInvalidToken_Revert() (gas: 12658) TokenProxy_getFee:test_GetFeeNoDataAllowed_Revert() (gas: 15849) -TokenProxy_getFee:test_GetFee_Success() (gas: 86948) -USDCTokenPool__validateMessage:test_ValidateInvalidMessage_Revert() (gas: 24960) -USDCTokenPool_lockOrBurn:test_CallerIsNotARampOnRouter_Revert() (gas: 35312) -USDCTokenPool_lockOrBurn:test_LockOrBurnWithAllowList_Revert() (gas: 30063) -USDCTokenPool_lockOrBurn:test_LockOrBurn_Success() (gas: 132864) -USDCTokenPool_lockOrBurn:test_UnknownDomain_Revert() (gas: 477209) -USDCTokenPool_lockOrBurn:test_lockOrBurn_InvalidReceiver_Revert() (gas: 52606) -USDCTokenPool_releaseOrMint:test_ReleaseOrMintRealTx_Success() (gas: 289268) -USDCTokenPool_releaseOrMint:test_TokenMaxCapacityExceeded_Revert() (gas: 50682) -USDCTokenPool_releaseOrMint:test_UnlockingUSDCFailed_Revert() (gas: 119185) +TokenProxy_getFee:test_GetFee_Success() (gas: 86690) +USDCTokenPool__validateMessage:test_ValidateInvalidMessage_Revert() (gas: 25290) +USDCTokenPool_lockOrBurn:test_CallerIsNotARampOnRouter_Revert() (gas: 35322) +USDCTokenPool_lockOrBurn:test_LockOrBurnWithAllowList_Revert() (gas: 30073) +USDCTokenPool_lockOrBurn:test_LockOrBurn_Success() (gas: 133102) +USDCTokenPool_lockOrBurn:test_UnknownDomain_Revert() (gas: 477183) +USDCTokenPool_releaseOrMint:test_ReleaseOrMintRealTx_Success() (gas: 268111) +USDCTokenPool_releaseOrMint:test_TokenMaxCapacityExceeded_Revert() (gas: 50676) +USDCTokenPool_releaseOrMint:test_UnlockingUSDCFailed_Revert() (gas: 98591) USDCTokenPool_setDomains:test_InvalidDomain_Revert() (gas: 66150) -USDCTokenPool_setDomains:test_OnlyOwner_Revert() (gas: 11339) +USDCTokenPool_setDomains:test_OnlyOwner_Revert() (gas: 11333) USDCTokenPool_supportsInterface:test_SupportsInterface_Success() (gas: 9876) \ No newline at end of file diff --git a/contracts/gas-snapshots/functions.gas-snapshot b/contracts/gas-snapshots/functions.gas-snapshot index 69e0271684..b54662b868 100644 --- a/contracts/gas-snapshots/functions.gas-snapshot +++ b/contracts/gas-snapshots/functions.gas-snapshot @@ -1,21 +1,21 @@ -ChainSpecificUtil__getL1FeeUpperLimit_Arbitrum:test__getL1FeeUpperLimit_SuccessWhenArbitrumGoerli() (gas: 16076840) -ChainSpecificUtil__getL1FeeUpperLimit_Arbitrum:test__getL1FeeUpperLimit_SuccessWhenArbitrumMainnet() (gas: 16076819) -ChainSpecificUtil__getL1FeeUpperLimit_Arbitrum:test__getL1FeeUpperLimit_SuccessWhenArbitrumSepolia() (gas: 16076888) -ChainSpecificUtil__getL1FeeUpperLimit_Base:test__getL1FeeUpperLimit_SuccessWhenBaseGoerli() (gas: 16076608) -ChainSpecificUtil__getL1FeeUpperLimit_Base:test__getL1FeeUpperLimit_SuccessWhenBaseMainnet() (gas: 16076564) -ChainSpecificUtil__getL1FeeUpperLimit_Base:test__getL1FeeUpperLimit_SuccessWhenBaseSepolia() (gas: 16076635) -ChainSpecificUtil__getL1FeeUpperLimit_Optimism:test__getL1FeeUpperLimit_SuccessWhenOptimismGoerli() (gas: 16076521) -ChainSpecificUtil__getL1FeeUpperLimit_Optimism:test__getL1FeeUpperLimit_SuccessWhenOptimismMainnet() (gas: 16076543) -ChainSpecificUtil__getL1FeeUpperLimit_Optimism:test__getL1FeeUpperLimit_SuccessWhenOptimismSepolia() (gas: 16076586) +ChainSpecificUtil__getL1FeeUpperLimit_Arbitrum:test__getL1FeeUpperLimit_SuccessWhenArbitrumGoerli() (gas: 15903239) +ChainSpecificUtil__getL1FeeUpperLimit_Arbitrum:test__getL1FeeUpperLimit_SuccessWhenArbitrumMainnet() (gas: 15903196) +ChainSpecificUtil__getL1FeeUpperLimit_Arbitrum:test__getL1FeeUpperLimit_SuccessWhenArbitrumSepolia() (gas: 15903265) +ChainSpecificUtil__getL1FeeUpperLimit_Base:test__getL1FeeUpperLimit_SuccessWhenBaseGoerli() (gas: 15903033) +ChainSpecificUtil__getL1FeeUpperLimit_Base:test__getL1FeeUpperLimit_SuccessWhenBaseMainnet() (gas: 15903011) +ChainSpecificUtil__getL1FeeUpperLimit_Base:test__getL1FeeUpperLimit_SuccessWhenBaseSepolia() (gas: 15903060) +ChainSpecificUtil__getL1FeeUpperLimit_Optimism:test__getL1FeeUpperLimit_SuccessWhenOptimismGoerli() (gas: 15902946) +ChainSpecificUtil__getL1FeeUpperLimit_Optimism:test__getL1FeeUpperLimit_SuccessWhenOptimismMainnet() (gas: 15902968) +ChainSpecificUtil__getL1FeeUpperLimit_Optimism:test__getL1FeeUpperLimit_SuccessWhenOptimismSepolia() (gas: 15903011) FunctionsBilling_Constructor:test_Constructor_Success() (gas: 17982) -FunctionsBilling_DeleteCommitment:test_DeleteCommitment_RevertIfNotRouter() (gas: 13283) -FunctionsBilling_DeleteCommitment:test_DeleteCommitment_Success() (gas: 15853) +FunctionsBilling_DeleteCommitment:test_DeleteCommitment_RevertIfNotRouter() (gas: 13260) +FunctionsBilling_DeleteCommitment:test_DeleteCommitment_Success() (gas: 15875) FunctionsBilling_EstimateCost:test_EstimateCost_RevertsIfGasPriceAboveCeiling() (gas: 32450) -FunctionsBilling_EstimateCost:test_EstimateCost_Success() (gas: 90977) +FunctionsBilling_EstimateCost:test_EstimateCost_Success() (gas: 90999) FunctionsBilling_EstimateCost:test_EstimateCost_SuccessLowGasPrice() (gas: 91102) FunctionsBilling_GetAdminFeeJuels:test_GetAdminFeeJuels_Success() (gas: 18671) -FunctionsBilling_GetConfig:test_GetConfig_Success() (gas: 30750) -FunctionsBilling_GetDONFeeJuels:test_GetDONFeeJuels_Success() (gas: 41151) +FunctionsBilling_GetConfig:test_GetConfig_Success() (gas: 30727) +FunctionsBilling_GetDONFeeJuels:test_GetDONFeeJuels_Success() (gas: 41128) FunctionsBilling_GetOperationFee:test_GetOperationFeeJuels_Success() (gas: 40548) FunctionsBilling_GetWeiPerUnitLink:test_GetWeiPerUnitLink_Success() (gas: 29751) FunctionsBilling_OracleWithdraw:test_OracleWithdraw_RevertIfInsufficientBalance() (gas: 70136) @@ -23,41 +23,41 @@ FunctionsBilling_OracleWithdraw:test_OracleWithdraw_RevertWithNoBalance() (gas: FunctionsBilling_OracleWithdraw:test_OracleWithdraw_SuccessCoordinatorOwner() (gas: 129908) FunctionsBilling_OracleWithdraw:test_OracleWithdraw_SuccessTransmitterWithBalanceNoAmountGiven() (gas: 171930) FunctionsBilling_OracleWithdraw:test_OracleWithdraw_SuccessTransmitterWithBalanceValidAmountGiven() (gas: 145165) -FunctionsBilling_OracleWithdrawAll:test_OracleWithdrawAll_RevertIfNotOwner() (gas: 13320) +FunctionsBilling_OracleWithdrawAll:test_OracleWithdrawAll_RevertIfNotOwner() (gas: 13297) FunctionsBilling_OracleWithdrawAll:test_OracleWithdrawAll_SuccessPaysTransmittersWithBalance() (gas: 222357) -FunctionsBilling_UpdateConfig:test_UpdateConfig_RevertIfNotOwner() (gas: 21632) -FunctionsBilling_UpdateConfig:test_UpdateConfig_Success() (gas: 54099) +FunctionsBilling_UpdateConfig:test_UpdateConfig_RevertIfNotOwner() (gas: 21654) +FunctionsBilling_UpdateConfig:test_UpdateConfig_Success() (gas: 54121) FunctionsBilling__DisperseFeePool:test__DisperseFeePool_RevertIfNotSet() (gas: 8810) -FunctionsBilling__FulfillAndBill:test__FulfillAndBill_RevertIfInvalidCommitment() (gas: 13353) -FunctionsBilling__FulfillAndBill:test__FulfillAndBill_Success() (gas: 185976) +FunctionsBilling__FulfillAndBill:test__FulfillAndBill_RevertIfInvalidCommitment() (gas: 13375) +FunctionsBilling__FulfillAndBill:test__FulfillAndBill_Success() (gas: 185953) FunctionsBilling__StartBilling:test__FulfillAndBill_HasUniqueGlobalRequestId() (gas: 524582) FunctionsClient_Constructor:test_Constructor_Success() (gas: 10407) -FunctionsClient_HandleOracleFulfillment:test_HandleOracleFulfillment_RevertIfNotRouter() (gas: 14595) -FunctionsClient_HandleOracleFulfillment:test_HandleOracleFulfillment_Success() (gas: 22983) +FunctionsClient_HandleOracleFulfillment:test_HandleOracleFulfillment_RevertIfNotRouter() (gas: 14617) +FunctionsClient_HandleOracleFulfillment:test_HandleOracleFulfillment_Success() (gas: 22917) FunctionsClient__SendRequest:test__SendRequest_RevertIfInvalidCallbackGasLimit() (gas: 55069) FunctionsCoordinator_Constructor:test_Constructor_Success() (gas: 15085) -FunctionsCoordinator_GetDONPublicKey:test_GetDONPublicKey_RevertIfEmpty() (gas: 15356) +FunctionsCoordinator_GetDONPublicKey:test_GetDONPublicKey_RevertIfEmpty() (gas: 15378) FunctionsCoordinator_GetDONPublicKey:test_GetDONPublicKey_Success() (gas: 91691) -FunctionsCoordinator_GetThresholdPublicKey:test_GetThresholdPublicKey_RevertIfEmpty() (gas: 15334) -FunctionsCoordinator_GetThresholdPublicKey:test_GetThresholdPublicKey_Success() (gas: 515951) -FunctionsCoordinator_SetDONPublicKey:test_SetDONPublicKey_RevertNotOwner() (gas: 20409) +FunctionsCoordinator_GetThresholdPublicKey:test_GetThresholdPublicKey_RevertIfEmpty() (gas: 15356) +FunctionsCoordinator_GetThresholdPublicKey:test_GetThresholdPublicKey_Success() (gas: 515973) +FunctionsCoordinator_SetDONPublicKey:test_SetDONPublicKey_RevertNotOwner() (gas: 20365) FunctionsCoordinator_SetDONPublicKey:test_SetDONPublicKey_Success() (gas: 88970) -FunctionsCoordinator_SetThresholdPublicKey:test_SetThresholdPublicKey_RevertNotOwner() (gas: 13915) +FunctionsCoordinator_SetThresholdPublicKey:test_SetThresholdPublicKey_RevertNotOwner() (gas: 13892) FunctionsCoordinator_SetThresholdPublicKey:test_SetThresholdPublicKey_Success() (gas: 513165) -FunctionsCoordinator_StartRequest:test_StartRequest_RevertIfNotRouter() (gas: 22802) -FunctionsCoordinator_StartRequest:test_StartRequest_Success() (gas: 152650) +FunctionsCoordinator_StartRequest:test_StartRequest_RevertIfNotRouter() (gas: 22736) +FunctionsCoordinator_StartRequest:test_StartRequest_Success() (gas: 152672) FunctionsCoordinator__IsTransmitter:test__IsTransmitter_SuccessFound() (gas: 15106) -FunctionsCoordinator__IsTransmitter:test__IsTransmitter_SuccessNotFound() (gas: 22916) +FunctionsCoordinator__IsTransmitter:test__IsTransmitter_SuccessNotFound() (gas: 22938) FunctionsRequest_DEFAULT_BUFFER_SIZE:test_DEFAULT_BUFFER_SIZE() (gas: 3089) FunctionsRequest_EncodeCBOR:test_EncodeCBOR_Success() (gas: 3066) FunctionsRequest_REQUEST_DATA_VERSION:test_REQUEST_DATA_VERSION() (gas: 3068) FunctionsRouter_Constructor:test_Constructor_Success() (gas: 15107) -FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedCostExceedsCommitment() (gas: 172475) +FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedCostExceedsCommitment() (gas: 172497) FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedInsufficientGas() (gas: 163010) FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedInvalidCommitment() (gas: 38777) FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedInvalidRequestId() (gas: 35900) FunctionsRouter_Fulfill:test_Fulfill_RequestNotProcessedSubscriptionBalanceInvariant() (gas: 180976) -FunctionsRouter_Fulfill:test_Fulfill_RevertIfNotCommittedCoordinator() (gas: 28152) +FunctionsRouter_Fulfill:test_Fulfill_RevertIfNotCommittedCoordinator() (gas: 28086) FunctionsRouter_Fulfill:test_Fulfill_RevertIfPaused() (gas: 156535) FunctionsRouter_Fulfill:test_Fulfill_SuccessClientNoLongerExists() (gas: 335070) FunctionsRouter_Fulfill:test_Fulfill_SuccessFulfilled() (gas: 348695) @@ -65,19 +65,19 @@ FunctionsRouter_Fulfill:test_Fulfill_SuccessUserCallbackReverts() (gas: 2627478) FunctionsRouter_Fulfill:test_Fulfill_SuccessUserCallbackRunsOutOfGas() (gas: 658423) FunctionsRouter_GetAdminFee:test_GetAdminFee_Success() (gas: 18323) FunctionsRouter_GetAllowListId:test_GetAllowListId_Success() (gas: 13241) -FunctionsRouter_GetConfig:test_GetConfig_Success() (gas: 40193) -FunctionsRouter_GetContractById:test_GetContractById_RevertIfRouteDoesNotExist() (gas: 13862) +FunctionsRouter_GetConfig:test_GetConfig_Success() (gas: 40170) +FunctionsRouter_GetContractById:test_GetContractById_RevertIfRouteDoesNotExist() (gas: 13839) FunctionsRouter_GetContractById:test_GetContractById_SuccessIfRouteExists() (gas: 17704) -FunctionsRouter_GetProposedContractById:test_GetProposedContractById_RevertIfRouteDoesNotExist() (gas: 16417) -FunctionsRouter_GetProposedContractById:test_GetProposedContractById_SuccessIfRouteExists() (gas: 24289) +FunctionsRouter_GetProposedContractById:test_GetProposedContractById_RevertIfRouteDoesNotExist() (gas: 16373) +FunctionsRouter_GetProposedContractById:test_GetProposedContractById_SuccessIfRouteExists() (gas: 24266) FunctionsRouter_GetProposedContractSet:test_GetProposedContractSet_Success() (gas: 27289) FunctionsRouter_IsValidCallbackGasLimit:test_IsValidCallbackGasLimit_RevertGasLimitTooBig() (gas: 28087) FunctionsRouter_IsValidCallbackGasLimit:test_IsValidCallbackGasLimit_RevertInvalidConfig() (gas: 41095) FunctionsRouter_IsValidCallbackGasLimit:test_IsValidCallbackGasLimit_Success() (gas: 24632) -FunctionsRouter_Pause:test_Pause_RevertIfNotOwner() (gas: 13361) -FunctionsRouter_Pause:test_Pause_Success() (gas: 20647) -FunctionsRouter_ProposeContractsUpdate:test_ProposeContractsUpdate_RevertIfEmptyAddress() (gas: 14769) -FunctionsRouter_ProposeContractsUpdate:test_ProposeContractsUpdate_RevertIfExceedsMaxProposal() (gas: 21716) +FunctionsRouter_Pause:test_Pause_RevertIfNotOwner() (gas: 13338) +FunctionsRouter_Pause:test_Pause_Success() (gas: 20669) +FunctionsRouter_ProposeContractsUpdate:test_ProposeContractsUpdate_RevertIfEmptyAddress() (gas: 14791) +FunctionsRouter_ProposeContractsUpdate:test_ProposeContractsUpdate_RevertIfExceedsMaxProposal() (gas: 21693) FunctionsRouter_ProposeContractsUpdate:test_ProposeContractsUpdate_RevertIfLengthMismatch() (gas: 14670) FunctionsRouter_ProposeContractsUpdate:test_ProposeContractsUpdate_RevertIfNotNewContract() (gas: 19048) FunctionsRouter_ProposeContractsUpdate:test_ProposeContractsUpdate_RevertIfNotOwner() (gas: 23392) @@ -85,151 +85,149 @@ FunctionsRouter_ProposeContractsUpdate:test_ProposeContractsUpdate_Success() (ga FunctionsRouter_SendRequest:test_SendRequest_RevertIfConsumerNotAllowed() (gas: 59400) FunctionsRouter_SendRequest:test_SendRequest_RevertIfDuplicateRequestId() (gas: 217996) FunctionsRouter_SendRequest:test_SendRequest_RevertIfEmptyData() (gas: 29426) -FunctionsRouter_SendRequest:test_SendRequest_RevertIfIncorrectDonId() (gas: 57882) +FunctionsRouter_SendRequest:test_SendRequest_RevertIfIncorrectDonId() (gas: 57904) FunctionsRouter_SendRequest:test_SendRequest_RevertIfInsufficientSubscriptionBalance() (gas: 208451) FunctionsRouter_SendRequest:test_SendRequest_RevertIfInvalidCallbackGasLimit() (gas: 50953) FunctionsRouter_SendRequest:test_SendRequest_RevertIfInvalidDonId() (gas: 25082) -FunctionsRouter_SendRequest:test_SendRequest_RevertIfNoSubscription() (gas: 29177) +FunctionsRouter_SendRequest:test_SendRequest_RevertIfNoSubscription() (gas: 29132) FunctionsRouter_SendRequest:test_SendRequest_RevertIfPaused() (gas: 34291) -FunctionsRouter_SendRequest:test_SendRequest_Success() (gas: 226324) -FunctionsRouter_SendRequestToProposed:test_SendRequestToProposed_RevertIfConsumerNotAllowed() (gas: 65918) +FunctionsRouter_SendRequest:test_SendRequest_Success() (gas: 226346) +FunctionsRouter_SendRequestToProposed:test_SendRequestToProposed_RevertIfConsumerNotAllowed() (gas: 65896) FunctionsRouter_SendRequestToProposed:test_SendRequestToProposed_RevertIfEmptyData() (gas: 36012) FunctionsRouter_SendRequestToProposed:test_SendRequestToProposed_RevertIfIncorrectDonId() (gas: 29896) FunctionsRouter_SendRequestToProposed:test_SendRequestToProposed_RevertIfInvalidCallbackGasLimit() (gas: 57539) FunctionsRouter_SendRequestToProposed:test_SendRequestToProposed_RevertIfInvalidDonId() (gas: 27503) -FunctionsRouter_SendRequestToProposed:test_SendRequestToProposed_RevertIfNoSubscription() (gas: 35672) +FunctionsRouter_SendRequestToProposed:test_SendRequestToProposed_RevertIfNoSubscription() (gas: 35717) FunctionsRouter_SendRequestToProposed:test_SendRequestToProposed_RevertIfPaused() (gas: 40810) FunctionsRouter_SendRequestToProposed:test_SendRequestToProposed_Success() (gas: 232783) FunctionsRouter_SendRequestToProposed:test_SendRequest_RevertIfInsufficientSubscriptionBalance() (gas: 214899) FunctionsRouter_SetAllowListId:test_SetAllowListId_Success() (gas: 33531) -FunctionsRouter_SetAllowListId:test_UpdateConfig_RevertIfNotOwner() (gas: 13381) -FunctionsRouter_Unpause:test_Unpause_RevertIfNotOwner() (gas: 13337) -FunctionsRouter_Unpause:test_Unpause_Success() (gas: 77748) -FunctionsRouter_UpdateConfig:test_UpdateConfig_RevertIfNotOwner() (gas: 24415) -FunctionsRouter_UpdateConfig:test_UpdateConfig_Success() (gas: 63331) -FunctionsRouter_UpdateContracts:test_UpdateContracts_RevertIfNotOwner() (gas: 13314) +FunctionsRouter_SetAllowListId:test_UpdateConfig_RevertIfNotOwner() (gas: 13403) +FunctionsRouter_Unpause:test_Unpause_RevertIfNotOwner() (gas: 13293) +FunctionsRouter_Unpause:test_Unpause_Success() (gas: 77725) +FunctionsRouter_UpdateConfig:test_UpdateConfig_RevertIfNotOwner() (gas: 24437) +FunctionsRouter_UpdateConfig:test_UpdateConfig_Success() (gas: 63353) +FunctionsRouter_UpdateContracts:test_UpdateContracts_RevertIfNotOwner() (gas: 13336) FunctionsRouter_UpdateContracts:test_UpdateContracts_Success() (gas: 39269) FunctionsSubscriptions_AcceptSubscriptionOwnerTransfer:test_AcceptSubscriptionOwnerTransfer_RevertIfNotAllowedSender() (gas: 60413) FunctionsSubscriptions_AcceptSubscriptionOwnerTransfer:test_AcceptSubscriptionOwnerTransfer_RevertIfPaused() (gas: 61040) FunctionsSubscriptions_AcceptSubscriptionOwnerTransfer:test_AcceptSubscriptionOwnerTransfer_RevertIfSenderBecomesBlocked() (gas: 139706) FunctionsSubscriptions_AcceptSubscriptionOwnerTransfer:test_AcceptSubscriptionOwnerTransfer_RevertIfSenderIsNotNewOwner() (gas: 62780) -FunctionsSubscriptions_AcceptSubscriptionOwnerTransfer:test_AcceptSubscriptionOwnerTransfer_Success() (gas: 239919) +FunctionsSubscriptions_AcceptSubscriptionOwnerTransfer:test_AcceptSubscriptionOwnerTransfer_Success() (gas: 239911) FunctionsSubscriptions_AddConsumer:test_AddConsumer_RevertIfMaximumConsumers() (gas: 138033) FunctionsSubscriptions_AddConsumer:test_AddConsumer_RevertIfMaximumConsumersAfterConfigUpdate() (gas: 164977) -FunctionsSubscriptions_AddConsumer:test_AddConsumer_RevertIfNoSubscription() (gas: 12933) -FunctionsSubscriptions_AddConsumer:test_AddConsumer_RevertIfNotAllowedSender() (gas: 102428) -FunctionsSubscriptions_AddConsumer:test_AddConsumer_RevertIfNotSubscriptionOwner() (gas: 87272) +FunctionsSubscriptions_AddConsumer:test_AddConsumer_RevertIfNoSubscription() (gas: 12955) +FunctionsSubscriptions_AddConsumer:test_AddConsumer_RevertIfNotAllowedSender() (gas: 102450) +FunctionsSubscriptions_AddConsumer:test_AddConsumer_RevertIfNotSubscriptionOwner() (gas: 87205) FunctionsSubscriptions_AddConsumer:test_AddConsumer_RevertIfPaused() (gas: 18100) FunctionsSubscriptions_AddConsumer:test_AddConsumer_Success() (gas: 96221) FunctionsSubscriptions_CancelSubscription:test_CancelSubscription_RevertIfNoSubscription() (gas: 15053) -FunctionsSubscriptions_CancelSubscription:test_CancelSubscription_RevertIfNotAllowedSender() (gas: 102507) -FunctionsSubscriptions_CancelSubscription:test_CancelSubscription_RevertIfNotSubscriptionOwner() (gas: 89341) +FunctionsSubscriptions_CancelSubscription:test_CancelSubscription_RevertIfNotAllowedSender() (gas: 102529) +FunctionsSubscriptions_CancelSubscription:test_CancelSubscription_RevertIfNotSubscriptionOwner() (gas: 89318) FunctionsSubscriptions_CancelSubscription:test_CancelSubscription_RevertIfPaused() (gas: 20157) -FunctionsSubscriptions_CancelSubscription:test_CancelSubscription_RevertIfPendingRequests() (gas: 218308) +FunctionsSubscriptions_CancelSubscription:test_CancelSubscription_RevertIfPendingRequests() (gas: 218330) FunctionsSubscriptions_CancelSubscription:test_CancelSubscription_SuccessForfeitAllBalanceAsDeposit() (gas: 115656) FunctionsSubscriptions_CancelSubscription:test_CancelSubscription_SuccessForfeitSomeBalanceAsDeposit() (gas: 126964) FunctionsSubscriptions_CancelSubscription_ReceiveDeposit:test_CancelSubscription_SuccessRecieveDeposit() (gas: 75369) FunctionsSubscriptions_Constructor:test_Constructor_Success() (gas: 10488) FunctionsSubscriptions_CreateSubscriptionWithConsumer:test_CreateSubscriptionWithConsumer_RevertIfNotAllowedSender() (gas: 28688) -FunctionsSubscriptions_CreateSubscriptionWithConsumer:test_CreateSubscriptionWithConsumer_RevertIfPaused() (gas: 18038) +FunctionsSubscriptions_CreateSubscriptionWithConsumer:test_CreateSubscriptionWithConsumer_RevertIfPaused() (gas: 17994) FunctionsSubscriptions_CreateSubscriptionWithConsumer:test_CreateSubscriptionWithConsumer_Success() (gas: 353899) -FunctionsSubscriptions_GetConsumer:test_GetConsumer_Success() (gas: 17279) -FunctionsSubscriptions_GetFlags:test_GetFlags_SuccessInvalidSubscription() (gas: 13504) -FunctionsSubscriptions_GetFlags:test_GetFlags_SuccessValidSubscription() (gas: 41221) +FunctionsSubscriptions_GetConsumer:test_GetConsumer_Success() (gas: 17256) +FunctionsSubscriptions_GetFlags:test_GetFlags_SuccessInvalidSubscription() (gas: 13438) +FunctionsSubscriptions_GetFlags:test_GetFlags_SuccessValidSubscription() (gas: 41243) FunctionsSubscriptions_GetSubscription:test_GetSubscription_Success() (gas: 32968) FunctionsSubscriptions_GetSubscriptionCount:test_GetSubscriptionCount_Success() (gas: 13305) -FunctionsSubscriptions_GetSubscriptionsInRange:test_GetSubscriptionsInRange_RevertIfEndIsAfterLastSubscription() (gas: 16570) +FunctionsSubscriptions_GetSubscriptionsInRange:test_GetSubscriptionsInRange_RevertIfEndIsAfterLastSubscription() (gas: 16547) FunctionsSubscriptions_GetSubscriptionsInRange:test_GetSubscriptionsInRange_RevertIfStartIsAfterEnd() (gas: 13465) -FunctionsSubscriptions_GetSubscriptionsInRange:test_GetSubscriptionsInRange_Success() (gas: 65968) -FunctionsSubscriptions_GetTotalBalance:test_GetTotalBalance_Success() (gas: 15370) +FunctionsSubscriptions_GetSubscriptionsInRange:test_GetSubscriptionsInRange_Success() (gas: 65990) +FunctionsSubscriptions_GetTotalBalance:test_GetTotalBalance_Success() (gas: 15347) FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_RevertIfCallerIsNoCalldata() (gas: 39908) FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_RevertIfCallerIsNoSubscription() (gas: 42382) FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_RevertIfCallerIsNotLink() (gas: 13419) FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_RevertIfPaused() (gas: 47325) FunctionsSubscriptions_OnTokenTransfer:test_OnTokenTransfer_Success() (gas: 84314) -FunctionsSubscriptions_OracleWithdraw:test_OracleWithdraw_RevertIfAmountMoreThanBalance() (gas: 20744) +FunctionsSubscriptions_OracleWithdraw:test_OracleWithdraw_RevertIfAmountMoreThanBalance() (gas: 20766) FunctionsSubscriptions_OracleWithdraw:test_OracleWithdraw_RevertIfBalanceInvariant() (gas: 189) -FunctionsSubscriptions_OracleWithdraw:test_OracleWithdraw_RevertIfNoAmount() (gas: 15686) +FunctionsSubscriptions_OracleWithdraw:test_OracleWithdraw_RevertIfNoAmount() (gas: 15641) FunctionsSubscriptions_OracleWithdraw:test_OracleWithdraw_RevertIfPaused() (gas: 20859) -FunctionsSubscriptions_OracleWithdraw:test_OracleWithdraw_SuccessPaysRecipient() (gas: 60119) +FunctionsSubscriptions_OracleWithdraw:test_OracleWithdraw_SuccessPaysRecipient() (gas: 60075) FunctionsSubscriptions_OracleWithdraw:test_OracleWithdraw_SuccessSetsBalanceToZero() (gas: 57716) -FunctionsSubscriptions_OwnerCancelSubscription:test_OwnerCancelSubscription_RevertIfNoSubscription() (gas: 12796) -FunctionsSubscriptions_OwnerCancelSubscription:test_OwnerCancelSubscription_RevertIfNotOwner() (gas: 15594) -FunctionsSubscriptions_OwnerCancelSubscription:test_OwnerCancelSubscription_Success() (gas: 55177) +FunctionsSubscriptions_OwnerCancelSubscription:test_OwnerCancelSubscription_RevertIfNoSubscription() (gas: 12818) +FunctionsSubscriptions_OwnerCancelSubscription:test_OwnerCancelSubscription_RevertIfNotOwner() (gas: 15549) +FunctionsSubscriptions_OwnerCancelSubscription:test_OwnerCancelSubscription_Success() (gas: 55141) FunctionsSubscriptions_OwnerCancelSubscription:test_OwnerCancelSubscription_SuccessDeletesSubscription() (gas: 49607) FunctionsSubscriptions_OwnerCancelSubscription:test_OwnerCancelSubscription_SuccessSubOwnerRefunded() (gas: 53166) -FunctionsSubscriptions_OwnerCancelSubscription:test_OwnerCancelSubscription_SuccessWhenRequestInFlight() (gas: 186511) -FunctionsSubscriptions_OwnerWithdraw:test_OwnerWithdraw_RevertIfAmountMoreThanBalance() (gas: 17923) +FunctionsSubscriptions_OwnerCancelSubscription:test_OwnerCancelSubscription_SuccessWhenRequestInFlight() (gas: 186533) +FunctionsSubscriptions_OwnerWithdraw:test_OwnerWithdraw_RevertIfAmountMoreThanBalance() (gas: 17945) FunctionsSubscriptions_OwnerWithdraw:test_OwnerWithdraw_RevertIfBalanceInvariant() (gas: 210) -FunctionsSubscriptions_OwnerWithdraw:test_OwnerWithdraw_RevertIfNotOwner() (gas: 15600) +FunctionsSubscriptions_OwnerWithdraw:test_OwnerWithdraw_RevertIfNotOwner() (gas: 15555) FunctionsSubscriptions_OwnerWithdraw:test_OwnerWithdraw_SuccessIfNoAmount() (gas: 33839) -FunctionsSubscriptions_OwnerWithdraw:test_OwnerWithdraw_SuccessIfRecipientAddressZero() (gas: 31627) +FunctionsSubscriptions_OwnerWithdraw:test_OwnerWithdraw_SuccessIfRecipientAddressZero() (gas: 31649) FunctionsSubscriptions_OwnerWithdraw:test_OwnerWithdraw_SuccessPaysRecipient() (gas: 33935) FunctionsSubscriptions_OwnerWithdraw:test_OwnerWithdraw_SuccessSetsBalanceToZero() (gas: 31584) -FunctionsSubscriptions_PendingRequestExists:test_PendingRequestExists_SuccessFalseIfNoPendingRequests() (gas: 17796) -FunctionsSubscriptions_PendingRequestExists:test_PendingRequestExists_SuccessTrueIfPendingRequests() (gas: 203311) -FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_RevertIfEmptyNewOwner() (gas: 27642) -FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_RevertIfInvalidNewOwner() (gas: 57793) +FunctionsSubscriptions_PendingRequestExists:test_PendingRequestExists_SuccessFalseIfNoPendingRequests() (gas: 17818) +FunctionsSubscriptions_PendingRequestExists:test_PendingRequestExists_SuccessTrueIfPendingRequests() (gas: 203333) +FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_RevertIfEmptyNewOwner() (gas: 27664) +FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_RevertIfInvalidNewOwner() (gas: 57815) FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_RevertIfNoSubscription() (gas: 15013) -FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_RevertIfNotAllowedSender() (gas: 119820) -FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_RevertIfNotSubscriptionOwner() (gas: 17947) -FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_RevertIfPaused() (gas: 20181) -FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_Success() (gas: 68574) -FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_SuccessChangeProposedOwner() (gas: 83582) -FunctionsSubscriptions_RecoverFunds:test_OwnerCancelSubscription_RevertIfNotOwner() (gas: 15577) -FunctionsSubscriptions_RecoverFunds:test_RecoverFunds_Success() (gas: 41358) +FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_RevertIfNotAllowedSender() (gas: 119775) +FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_RevertIfNotSubscriptionOwner() (gas: 17969) +FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_RevertIfPaused() (gas: 20137) +FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_Success() (gas: 68596) +FunctionsSubscriptions_ProposeSubscriptionOwnerTransfer:test_ProposeSubscriptionOwnerTransfer_SuccessChangeProposedOwner() (gas: 83539) +FunctionsSubscriptions_RecoverFunds:test_OwnerCancelSubscription_RevertIfNotOwner() (gas: 15554) +FunctionsSubscriptions_RecoverFunds:test_RecoverFunds_Success() (gas: 41376) FunctionsSubscriptions_RemoveConsumer:test_RemoveConsumer_RevertIfInvalidConsumer() (gas: 30310) FunctionsSubscriptions_RemoveConsumer:test_RemoveConsumer_RevertIfNoSubscription() (gas: 15031) FunctionsSubscriptions_RemoveConsumer:test_RemoveConsumer_RevertIfNotAllowedSender() (gas: 102444) -FunctionsSubscriptions_RemoveConsumer:test_RemoveConsumer_RevertIfNotSubscriptionOwner() (gas: 87277) -FunctionsSubscriptions_RemoveConsumer:test_RemoveConsumer_RevertIfPaused() (gas: 18103) +FunctionsSubscriptions_RemoveConsumer:test_RemoveConsumer_RevertIfNotSubscriptionOwner() (gas: 87254) +FunctionsSubscriptions_RemoveConsumer:test_RemoveConsumer_RevertIfPaused() (gas: 18058) FunctionsSubscriptions_RemoveConsumer:test_RemoveConsumer_RevertIfPendingRequests() (gas: 215863) -FunctionsSubscriptions_RemoveConsumer:test_RemoveConsumer_Success() (gas: 42066) +FunctionsSubscriptions_RemoveConsumer:test_RemoveConsumer_Success() (gas: 42088) FunctionsSubscriptions_SetFlags:test_SetFlags_RevertIfNoSubscription() (gas: 12888) FunctionsSubscriptions_SetFlags:test_SetFlags_RevertIfNotOwner() (gas: 15684) FunctionsSubscriptions_SetFlags:test_SetFlags_Success() (gas: 38434) FunctionsSubscriptions_TimeoutRequests:test_TimeoutRequests_RevertIfPaused() (gas: 25955) FunctionsSubscriptions_TimeoutRequests:test_TimeoutRequests_RevertIfTimeoutNotExceeded() (gas: 25261) -FunctionsSubscriptions_TimeoutRequests:test_TimeoutRequests_RevertInvalidRequest() (gas: 28220) -FunctionsSubscriptions_TimeoutRequests:test_TimeoutRequests_Success() (gas: 58394) -FunctionsSubscriptions_createSubscription:test_CreateSubscription_RevertIfNotAllowedSender() (gas: 26462) +FunctionsSubscriptions_TimeoutRequests:test_TimeoutRequests_RevertInvalidRequest() (gas: 28242) +FunctionsSubscriptions_TimeoutRequests:test_TimeoutRequests_Success() (gas: 58416) +FunctionsSubscriptions_createSubscription:test_CreateSubscription_RevertIfNotAllowedSender() (gas: 26418) FunctionsSubscriptions_createSubscription:test_CreateSubscription_RevertIfPaused() (gas: 15759) FunctionsSubscriptions_createSubscription:test_CreateSubscription_Success() (gas: 153701) -FunctionsTermsOfServiceAllowList_AcceptTermsOfService:testAcceptTermsOfService_InvalidSigner_vuln() (gas: 94943) -FunctionsTermsOfServiceAllowList_AcceptTermsOfService:test_AcceptTermsOfService_RevertIfAcceptorIsNotSender() (gas: 25925) -FunctionsTermsOfServiceAllowList_AcceptTermsOfService:test_AcceptTermsOfService_RevertIfBlockedSender() (gas: 89013) -FunctionsTermsOfServiceAllowList_AcceptTermsOfService:test_AcceptTermsOfService_RevertIfInvalidSigner() (gas: 23620) -FunctionsTermsOfServiceAllowList_AcceptTermsOfService:test_AcceptTermsOfService_RevertIfRecipientContractIsNotSender() (gas: 1866619) -FunctionsTermsOfServiceAllowList_AcceptTermsOfService:test_AcceptTermsOfService_RevertIfRecipientIsNotSender() (gas: 28526) -FunctionsTermsOfServiceAllowList_AcceptTermsOfService:test_AcceptTermsOfService_SuccessIfAcceptingForContract() (gas: 1946966) -FunctionsTermsOfServiceAllowList_AcceptTermsOfService:test_AcceptTermsOfService_SuccessIfAcceptingForSelf() (gas: 104555) -FunctionsTermsOfServiceAllowList_BlockSender:test_BlockSender_RevertIfNotOwner() (gas: 15535) -FunctionsTermsOfServiceAllowList_BlockSender:test_BlockSender_Success() (gas: 97587) +FunctionsTermsOfServiceAllowList_AcceptTermsOfService:testAcceptTermsOfService_InvalidSigner_vuln() (gas: 94913) +FunctionsTermsOfServiceAllowList_AcceptTermsOfService:test_AcceptTermsOfService_RevertIfAcceptorIsNotSender() (gas: 25859) +FunctionsTermsOfServiceAllowList_AcceptTermsOfService:test_AcceptTermsOfService_RevertIfBlockedSender() (gas: 88990) +FunctionsTermsOfServiceAllowList_AcceptTermsOfService:test_AcceptTermsOfService_RevertIfInvalidSigner() (gas: 23619) +FunctionsTermsOfServiceAllowList_AcceptTermsOfService:test_AcceptTermsOfService_RevertIfRecipientContractIsNotSender() (gas: 1866552) +FunctionsTermsOfServiceAllowList_AcceptTermsOfService:test_AcceptTermsOfService_RevertIfRecipientIsNotSender() (gas: 28525) +FunctionsTermsOfServiceAllowList_AcceptTermsOfService:test_AcceptTermsOfService_SuccessIfAcceptingForContract() (gas: 1946965) +FunctionsTermsOfServiceAllowList_AcceptTermsOfService:test_AcceptTermsOfService_SuccessIfAcceptingForSelf() (gas: 104509) +FunctionsTermsOfServiceAllowList_BlockSender:test_BlockSender_RevertIfNotOwner() (gas: 15491) +FunctionsTermsOfServiceAllowList_BlockSender:test_BlockSender_Success() (gas: 97541) FunctionsTermsOfServiceAllowList_Constructor:test_Constructor_Success() (gas: 15345) FunctionsTermsOfServiceAllowList_GetAllAllowedSenders:test_GetAllAllowedSenders_Success() (gas: 19243) FunctionsTermsOfServiceAllowList_GetAllowedSendersCount:test_GetAllowedSendersCount_Success() (gas: 13332) -FunctionsTermsOfServiceAllowList_GetAllowedSendersInRange:test_GetAllowedSendersInRange_RevertIfAllowedSendersIsEmpty() (gas: 13326576) -FunctionsTermsOfServiceAllowList_GetAllowedSendersInRange:test_GetAllowedSendersInRange_RevertIfEndIsAfterLastAllowedSender() (gas: 16532) -FunctionsTermsOfServiceAllowList_GetAllowedSendersInRange:test_GetAllowedSendersInRange_RevertIfStartIsAfterEnd() (gas: 13307) -FunctionsTermsOfServiceAllowList_GetAllowedSendersInRange:test_GetAllowedSendersInRange_Success() (gas: 20335) +FunctionsTermsOfServiceAllowList_GetAllowedSendersInRange:test_GetAllowedSendersInRange_RevertIfAllowedSendersIsEmpty() (gas: 13153024) +FunctionsTermsOfServiceAllowList_GetAllowedSendersInRange:test_GetAllowedSendersInRange_RevertIfEndIsAfterLastAllowedSender() (gas: 16554) +FunctionsTermsOfServiceAllowList_GetAllowedSendersInRange:test_GetAllowedSendersInRange_RevertIfStartIsAfterEnd() (gas: 13284) +FunctionsTermsOfServiceAllowList_GetAllowedSendersInRange:test_GetAllowedSendersInRange_Success() (gas: 20312) FunctionsTermsOfServiceAllowList_GetBlockedSendersCount:test_GetBlockedSendersCount_Success() (gas: 13268) -FunctionsTermsOfServiceAllowList_GetBlockedSendersInRange:test_GetBlockedSendersInRange_RevertIfAllowedSendersIsEmpty() (gas: 13326564) +FunctionsTermsOfServiceAllowList_GetBlockedSendersInRange:test_GetBlockedSendersInRange_RevertIfAllowedSendersIsEmpty() (gas: 13153034) FunctionsTermsOfServiceAllowList_GetBlockedSendersInRange:test_GetBlockedSendersInRange_RevertIfEndIsAfterLastAllowedSender() (gas: 16549) -FunctionsTermsOfServiceAllowList_GetBlockedSendersInRange:test_GetBlockedSendersInRange_RevertIfStartIsAfterEnd() (gas: 13345) -FunctionsTermsOfServiceAllowList_GetBlockedSendersInRange:test_GetBlockedSendersInRange_Success() (gas: 18580) -FunctionsTermsOfServiceAllowList_GetConfig:test_GetConfig_Success() (gas: 16411) +FunctionsTermsOfServiceAllowList_GetBlockedSendersInRange:test_GetBlockedSendersInRange_RevertIfStartIsAfterEnd() (gas: 13367) +FunctionsTermsOfServiceAllowList_GetBlockedSendersInRange:test_GetBlockedSendersInRange_Success() (gas: 18537) +FunctionsTermsOfServiceAllowList_GetConfig:test_GetConfig_Success() (gas: 16388) FunctionsTermsOfServiceAllowList_GetMessage:test_GetMessage_Success() (gas: 11918) -FunctionsTermsOfServiceAllowList_HasAccess:test_HasAccess_FalseWhenEnabled() (gas: 16235) -FunctionsTermsOfServiceAllowList_HasAccess:test_HasAccess_TrueWhenDisabled() (gas: 23877) +FunctionsTermsOfServiceAllowList_HasAccess:test_HasAccess_FalseWhenEnabled() (gas: 16257) +FunctionsTermsOfServiceAllowList_HasAccess:test_HasAccess_TrueWhenDisabled() (gas: 23848) FunctionsTermsOfServiceAllowList_IsBlockedSender:test_IsBlockedSender_SuccessFalse() (gas: 15776) FunctionsTermsOfServiceAllowList_IsBlockedSender:test_IsBlockedSender_SuccessTrue() (gas: 86974) -FunctionsTermsOfServiceAllowList_MigratePreviouslyAllowedSenders:test_MigratePreviouslyAllowedSenders_RevertIfNotOwner() (gas: 13987) -FunctionsTermsOfServiceAllowList_MigratePreviouslyAllowedSenders:test_MigratePreviouslyAllowedSenders_Success() (gas: 210636) -FunctionsTermsOfServiceAllowList_UnblockSender:test_UnblockSender_RevertIfNotOwner() (gas: 13548) -FunctionsTermsOfServiceAllowList_UnblockSender:test_UnblockSender_Success() (gas: 96240) -FunctionsTermsOfServiceAllowList_UpdateConfig:test_UpdateConfig_RevertIfNotOwner() (gas: 13819) -FunctionsTermsOfServiceAllowList_UpdateConfig:test_UpdateConfig_Success() (gas: 22824) -Gas_AcceptTermsOfService:test_AcceptTermsOfService_Gas() (gas: 84725) +FunctionsTermsOfServiceAllowList_UnblockSender:test_UnblockSender_RevertIfNotOwner() (gas: 13502) +FunctionsTermsOfServiceAllowList_UnblockSender:test_UnblockSender_Success() (gas: 96216) +FunctionsTermsOfServiceAllowList_UpdateConfig:test_UpdateConfig_RevertIfNotOwner() (gas: 13812) +FunctionsTermsOfServiceAllowList_UpdateConfig:test_UpdateConfig_Success() (gas: 22817) +Gas_AcceptTermsOfService:test_AcceptTermsOfService_Gas() (gas: 84702) Gas_AddConsumer:test_AddConsumer_Gas() (gas: 79140) Gas_CreateSubscription:test_CreateSubscription_Gas() (gas: 73419) Gas_FulfillRequest_DuplicateRequestID:test_FulfillRequest_DuplicateRequestID_MaximumGas() (gas: 20562) diff --git a/contracts/gas-snapshots/keystone.gas-snapshot b/contracts/gas-snapshots/keystone.gas-snapshot index d75d68a172..2880e4c0e3 100644 --- a/contracts/gas-snapshots/keystone.gas-snapshot +++ b/contracts/gas-snapshots/keystone.gas-snapshot @@ -1,114 +1,107 @@ -CapabilitiesRegistry_AddCapabilitiesTest:test_AddCapability_NoConfigurationContract() (gas: 154809) -CapabilitiesRegistry_AddCapabilitiesTest:test_AddCapability_WithConfiguration() (gas: 178790) -CapabilitiesRegistry_AddCapabilitiesTest:test_RevertWhen_CalledByNonAdmin() (gas: 24678) -CapabilitiesRegistry_AddCapabilitiesTest:test_RevertWhen_CapabilityExists() (gas: 145613) -CapabilitiesRegistry_AddCapabilitiesTest:test_RevertWhen_ConfigurationContractDoesNotMatchInterface() (gas: 94561) -CapabilitiesRegistry_AddCapabilitiesTest:test_RevertWhen_ConfigurationContractNotDeployed() (gas: 92916) -CapabilitiesRegistry_AddDONTest:test_AddDON() (gas: 373685) +CapabilitiesRegistry_AddCapabilitiesTest:test_AddCapability_NoConfigurationContract() (gas: 154832) +CapabilitiesRegistry_AddCapabilitiesTest:test_AddCapability_WithConfiguration() (gas: 178813) +CapabilitiesRegistry_AddCapabilitiesTest:test_RevertWhen_CalledByNonAdmin() (gas: 24723) +CapabilitiesRegistry_AddCapabilitiesTest:test_RevertWhen_CapabilityExists() (gas: 145703) +CapabilitiesRegistry_AddCapabilitiesTest:test_RevertWhen_ConfigurationContractDoesNotMatchInterface() (gas: 94606) +CapabilitiesRegistry_AddCapabilitiesTest:test_RevertWhen_ConfigurationContractNotDeployed() (gas: 92961) +CapabilitiesRegistry_AddDONTest:test_AddDON() (gas: 372302) CapabilitiesRegistry_AddDONTest:test_RevertWhen_CalledByNonAdmin() (gas: 19273) CapabilitiesRegistry_AddDONTest:test_RevertWhen_CapabilityDoesNotExist() (gas: 169752) -CapabilitiesRegistry_AddDONTest:test_RevertWhen_DeprecatedCapabilityAdded() (gas: 239724) -CapabilitiesRegistry_AddDONTest:test_RevertWhen_DuplicateCapabilityAdded() (gas: 250935) +CapabilitiesRegistry_AddDONTest:test_RevertWhen_DeprecatedCapabilityAdded() (gas: 239789) +CapabilitiesRegistry_AddDONTest:test_RevertWhen_DuplicateCapabilityAdded() (gas: 249596) CapabilitiesRegistry_AddDONTest:test_RevertWhen_DuplicateNodeAdded() (gas: 116890) CapabilitiesRegistry_AddDONTest:test_RevertWhen_FaultToleranceIsZero() (gas: 43358) CapabilitiesRegistry_AddDONTest:test_RevertWhen_NodeAlreadyBelongsToWorkflowDON() (gas: 343924) CapabilitiesRegistry_AddDONTest:test_RevertWhen_NodeDoesNotSupportCapability() (gas: 180150) -CapabilitiesRegistry_AddDONTest_WhenMaliciousCapabilityConfigurationConfigured:test_RevertWhen_MaliciousCapabilitiesConfigContractTriesToRemoveCapabilitiesFromDONNodes() (gas: 340499) -CapabilitiesRegistry_AddNodeOperatorsTest:test_AddNodeOperators() (gas: 184157) -CapabilitiesRegistry_AddNodeOperatorsTest:test_RevertWhen_CalledByNonAdmin() (gas: 17624) -CapabilitiesRegistry_AddNodeOperatorsTest:test_RevertWhen_NodeOperatorAdminAddressZero() (gas: 18520) -CapabilitiesRegistry_AddNodesTest:test_AddsNodeParams() (gas: 358492) -CapabilitiesRegistry_AddNodesTest:test_OwnerCanAddNodes() (gas: 358458) -CapabilitiesRegistry_AddNodesTest:test_RevertWhen_AddingDuplicateP2PId() (gas: 301273) -CapabilitiesRegistry_AddNodesTest:test_RevertWhen_AddingNodeWithInvalidCapability() (gas: 55196) -CapabilitiesRegistry_AddNodesTest:test_RevertWhen_AddingNodeWithInvalidNodeOperator() (gas: 24917) -CapabilitiesRegistry_AddNodesTest:test_RevertWhen_AddingNodeWithoutCapabilities() (gas: 27691) -CapabilitiesRegistry_AddNodesTest:test_RevertWhen_CalledByNonNodeOperatorAdminAndNonOwner() (gas: 25130) -CapabilitiesRegistry_AddNodesTest:test_RevertWhen_P2PIDEmpty() (gas: 27430) -CapabilitiesRegistry_AddNodesTest:test_RevertWhen_SignerAddressEmpty() (gas: 27069) -CapabilitiesRegistry_AddNodesTest:test_RevertWhen_SignerAddressNotUnique() (gas: 309723) -CapabilitiesRegistry_DeprecateCapabilitiesTest:test_DeprecatesCapability() (gas: 89742) -CapabilitiesRegistry_DeprecateCapabilitiesTest:test_EmitsEvent() (gas: 89870) -CapabilitiesRegistry_DeprecateCapabilitiesTest:test_RevertWhen_CalledByNonAdmin() (gas: 22879) -CapabilitiesRegistry_DeprecateCapabilitiesTest:test_RevertWhen_CapabilityDoesNotExist() (gas: 16166) -CapabilitiesRegistry_DeprecateCapabilitiesTest:test_RevertWhen_CapabilityIsDeprecated() (gas: 91134) -CapabilitiesRegistry_GetCapabilitiesTest:test_ReturnsCapabilities() (gas: 135488) +CapabilitiesRegistry_AddNodeOperatorsTest:test_AddNodeOperators() (gas: 184135) +CapabilitiesRegistry_AddNodeOperatorsTest:test_RevertWhen_CalledByNonAdmin() (gas: 17602) +CapabilitiesRegistry_AddNodeOperatorsTest:test_RevertWhen_NodeOperatorAdminAddressZero() (gas: 18498) +CapabilitiesRegistry_AddNodesTest:test_AddsNodeParams() (gas: 358448) +CapabilitiesRegistry_AddNodesTest:test_OwnerCanAddNodes() (gas: 358414) +CapabilitiesRegistry_AddNodesTest:test_RevertWhen_AddingDuplicateP2PId() (gas: 301229) +CapabilitiesRegistry_AddNodesTest:test_RevertWhen_AddingNodeWithInvalidCapability() (gas: 55174) +CapabilitiesRegistry_AddNodesTest:test_RevertWhen_AddingNodeWithInvalidNodeOperator() (gas: 24895) +CapabilitiesRegistry_AddNodesTest:test_RevertWhen_AddingNodeWithoutCapabilities() (gas: 27669) +CapabilitiesRegistry_AddNodesTest:test_RevertWhen_CalledByNonNodeOperatorAdminAndNonOwner() (gas: 25108) +CapabilitiesRegistry_AddNodesTest:test_RevertWhen_P2PIDEmpty() (gas: 27408) +CapabilitiesRegistry_AddNodesTest:test_RevertWhen_SignerAddressEmpty() (gas: 27047) +CapabilitiesRegistry_AddNodesTest:test_RevertWhen_SignerAddressNotUnique() (gas: 309679) +CapabilitiesRegistry_DeprecateCapabilitiesTest:test_DeprecatesCapability() (gas: 89807) +CapabilitiesRegistry_DeprecateCapabilitiesTest:test_EmitsEvent() (gas: 89935) +CapabilitiesRegistry_DeprecateCapabilitiesTest:test_RevertWhen_CalledByNonAdmin() (gas: 22944) +CapabilitiesRegistry_DeprecateCapabilitiesTest:test_RevertWhen_CapabilityDoesNotExist() (gas: 16231) +CapabilitiesRegistry_DeprecateCapabilitiesTest:test_RevertWhen_CapabilityIsDeprecated() (gas: 91264) +CapabilitiesRegistry_GetCapabilitiesTest:test_ReturnsCapabilities() (gas: 135553) CapabilitiesRegistry_GetDONsTest:test_CorrectlyFetchesDONs() (gas: 65468) CapabilitiesRegistry_GetDONsTest:test_DoesNotIncludeRemovedDONs() (gas: 64924) CapabilitiesRegistry_GetHashedCapabilityTest:test_CorrectlyGeneratesHashedCapabilityId() (gas: 11428) CapabilitiesRegistry_GetHashedCapabilityTest:test_DoesNotCauseIncorrectClashes() (gas: 13087) -CapabilitiesRegistry_GetNodeOperatorsTest:test_CorrectlyFetchesNodeOperators() (gas: 36429) -CapabilitiesRegistry_GetNodeOperatorsTest:test_DoesNotIncludeRemovedNodeOperators() (gas: 38714) +CapabilitiesRegistry_GetNodeOperatorsTest:test_CorrectlyFetchesNodeOperators() (gas: 36407) +CapabilitiesRegistry_GetNodeOperatorsTest:test_DoesNotIncludeRemovedNodeOperators() (gas: 38692) CapabilitiesRegistry_GetNodesTest:test_CorrectlyFetchesNodes() (gas: 65288) -CapabilitiesRegistry_GetNodesTest:test_DoesNotIncludeRemovedNodes() (gas: 73497) -CapabilitiesRegistry_RemoveDONsTest:test_RemovesDON() (gas: 54783) +CapabilitiesRegistry_GetNodesTest:test_DoesNotIncludeRemovedNodes() (gas: 73533) +CapabilitiesRegistry_RemoveDONsTest:test_RemovesDON() (gas: 54761) CapabilitiesRegistry_RemoveDONsTest:test_RevertWhen_CalledByNonAdmin() (gas: 15647) CapabilitiesRegistry_RemoveDONsTest:test_RevertWhen_DONDoesNotExist() (gas: 16550) CapabilitiesRegistry_RemoveNodeOperatorsTest:test_RemovesNodeOperator() (gas: 36122) CapabilitiesRegistry_RemoveNodeOperatorsTest:test_RevertWhen_CalledByNonOwner() (gas: 15816) -CapabilitiesRegistry_RemoveNodesTest:test_CanAddNodeWithSameSignerAddressAfterRemoving() (gas: 115150) -CapabilitiesRegistry_RemoveNodesTest:test_CanRemoveWhenDONDeleted() (gas: 287648) -CapabilitiesRegistry_RemoveNodesTest:test_CanRemoveWhenNodeNoLongerPartOfDON() (gas: 560993) -CapabilitiesRegistry_RemoveNodesTest:test_OwnerCanRemoveNodes() (gas: 73358) -CapabilitiesRegistry_RemoveNodesTest:test_RemovesNode() (gas: 75192) -CapabilitiesRegistry_RemoveNodesTest:test_RevertWhen_CalledByNonNodeOperatorAdminAndNonOwner() (gas: 25008) -CapabilitiesRegistry_RemoveNodesTest:test_RevertWhen_NodeDoesNotExist() (gas: 18373) -CapabilitiesRegistry_RemoveNodesTest:test_RevertWhen_NodePartOfCapabilitiesDON() (gas: 385324) -CapabilitiesRegistry_RemoveNodesTest:test_RevertWhen_P2PIDEmpty() (gas: 18363) +CapabilitiesRegistry_RemoveNodesTest:test_CanAddNodeWithSameSignerAddressAfterRemoving() (gas: 115151) +CapabilitiesRegistry_RemoveNodesTest:test_CanRemoveWhenDONDeleted() (gas: 287716) +CapabilitiesRegistry_RemoveNodesTest:test_CanRemoveWhenNodeNoLongerPartOfDON() (gas: 561023) +CapabilitiesRegistry_RemoveNodesTest:test_OwnerCanRemoveNodes() (gas: 73376) +CapabilitiesRegistry_RemoveNodesTest:test_RemovesNode() (gas: 75211) +CapabilitiesRegistry_RemoveNodesTest:test_RevertWhen_CalledByNonNodeOperatorAdminAndNonOwner() (gas: 25053) +CapabilitiesRegistry_RemoveNodesTest:test_RevertWhen_NodeDoesNotExist() (gas: 18418) +CapabilitiesRegistry_RemoveNodesTest:test_RevertWhen_NodePartOfCapabilitiesDON() (gas: 385369) +CapabilitiesRegistry_RemoveNodesTest:test_RevertWhen_P2PIDEmpty() (gas: 18408) CapabilitiesRegistry_TypeAndVersionTest:test_TypeAndVersion() (gas: 9796) -CapabilitiesRegistry_UpdateDONTest:test_RevertWhen_CalledByNonAdmin() (gas: 19314) -CapabilitiesRegistry_UpdateDONTest:test_RevertWhen_CapabilityDoesNotExist() (gas: 152949) -CapabilitiesRegistry_UpdateDONTest:test_RevertWhen_DONDoesNotExist() (gas: 17740) -CapabilitiesRegistry_UpdateDONTest:test_RevertWhen_DeprecatedCapabilityAdded() (gas: 222966) -CapabilitiesRegistry_UpdateDONTest:test_RevertWhen_DuplicateCapabilityAdded() (gas: 236977) -CapabilitiesRegistry_UpdateDONTest:test_RevertWhen_DuplicateNodeAdded() (gas: 107678) -CapabilitiesRegistry_UpdateDONTest:test_RevertWhen_NodeDoesNotSupportCapability() (gas: 163392) -CapabilitiesRegistry_UpdateDONTest:test_UpdatesDON() (gas: 373308) -CapabilitiesRegistry_UpdateNodeOperatorTest:test_RevertWhen_CalledByNonAdminAndNonOwner() (gas: 20684) -CapabilitiesRegistry_UpdateNodeOperatorTest:test_RevertWhen_NodeOperatorAdminIsZeroAddress() (gas: 20008) -CapabilitiesRegistry_UpdateNodeOperatorTest:test_RevertWhen_NodeOperatorDoesNotExist() (gas: 19746) -CapabilitiesRegistry_UpdateNodeOperatorTest:test_RevertWhen_NodeOperatorIdAndParamLengthsMismatch() (gas: 15386) -CapabilitiesRegistry_UpdateNodeOperatorTest:test_UpdatesNodeOperator() (gas: 36990) -CapabilitiesRegistry_UpdateNodesTest:test_CanUpdateParamsIfNodeSignerAddressNoLongerUsed() (gas: 256437) -CapabilitiesRegistry_UpdateNodesTest:test_OwnerCanUpdateNodes() (gas: 162210) -CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_AddingNodeWithInvalidCapability() (gas: 35895) -CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_CalledByAnotherNodeOperatorAdmin() (gas: 29222) -CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_CalledByNonNodeOperatorAdminAndNonOwner() (gas: 29399) -CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_NodeDoesNotExist() (gas: 29221) -CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_NodeSignerAlreadyAssignedToAnotherNode() (gas: 31348) -CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_P2PIDEmpty() (gas: 29187) -CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_RemovingCapabilityRequiredByCapabilityDON() (gas: 470932) -CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_RemovingCapabilityRequiredByWorkflowDON() (gas: 341213) -CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_SignerAddressEmpty() (gas: 29080) -CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_UpdatingNodeWithoutCapabilities() (gas: 27609) -CapabilitiesRegistry_UpdateNodesTest:test_UpdatesNodeParams() (gas: 162264) -KeystoneForwarder_ReportTest:test_Report_ConfigVersion() (gas: 2003568) -KeystoneForwarder_ReportTest:test_Report_FailedDeliveryWhenReceiverInterfaceNotSupported() (gas: 124908) -KeystoneForwarder_ReportTest:test_Report_FailedDeliveryWhenReceiverNotContract() (gas: 126927) -KeystoneForwarder_ReportTest:test_Report_SuccessfulDelivery() (gas: 361243) -KeystoneForwarder_ReportTest:test_Report_SuccessfulRetryWithMoreGas() (gas: 501084) -KeystoneForwarder_ReportTest:test_RevertWhen_AnySignatureIsInvalid() (gas: 86326) -KeystoneForwarder_ReportTest:test_RevertWhen_AnySignerIsInvalid() (gas: 118521) -KeystoneForwarder_ReportTest:test_RevertWhen_AttemptingTransmissionWithInsufficientGas() (gas: 96279) +CapabilitiesRegistry_UpdateDONTest:test_RevertWhen_CalledByNonAdmin() (gas: 19415) +CapabilitiesRegistry_UpdateDONTest:test_RevertWhen_CapabilityDoesNotExist() (gas: 152914) +CapabilitiesRegistry_UpdateDONTest:test_RevertWhen_DONDoesNotExist() (gas: 17835) +CapabilitiesRegistry_UpdateDONTest:test_RevertWhen_DeprecatedCapabilityAdded() (gas: 222996) +CapabilitiesRegistry_UpdateDONTest:test_RevertWhen_DuplicateCapabilityAdded() (gas: 232804) +CapabilitiesRegistry_UpdateDONTest:test_RevertWhen_DuplicateNodeAdded() (gas: 107643) +CapabilitiesRegistry_UpdateDONTest:test_RevertWhen_NodeDoesNotSupportCapability() (gas: 163357) +CapabilitiesRegistry_UpdateDONTest:test_UpdatesDON() (gas: 371909) +CapabilitiesRegistry_UpdateNodeOperatorTest:test_RevertWhen_CalledByNonAdminAndNonOwner() (gas: 20631) +CapabilitiesRegistry_UpdateNodeOperatorTest:test_RevertWhen_NodeOperatorAdminIsZeroAddress() (gas: 20052) +CapabilitiesRegistry_UpdateNodeOperatorTest:test_RevertWhen_NodeOperatorDoesNotExist() (gas: 19790) +CapabilitiesRegistry_UpdateNodeOperatorTest:test_RevertWhen_NodeOperatorIdAndParamLengthsMismatch() (gas: 15430) +CapabilitiesRegistry_UpdateNodeOperatorTest:test_UpdatesNodeOperator() (gas: 36937) +CapabilitiesRegistry_UpdateNodesTest:test_CanUpdateParamsIfNodeSignerAddressNoLongerUsed() (gas: 256157) +CapabilitiesRegistry_UpdateNodesTest:test_OwnerCanUpdateNodes() (gas: 162059) +CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_AddingNodeWithInvalidCapability() (gas: 35766) +CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_CalledByNonNodeOperatorAdminAndNonOwner() (gas: 25069) +CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_NodeDoesNotExist() (gas: 27308) +CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_NodeSignerAlreadyAssignedToAnotherNode() (gas: 29219) +CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_P2PIDEmpty() (gas: 27296) +CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_RemovingCapabilityRequiredByCapabilityDON() (gas: 470803) +CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_RemovingCapabilityRequiredByWorkflowDON() (gas: 341084) +CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_SignerAddressEmpty() (gas: 26951) +CapabilitiesRegistry_UpdateNodesTest:test_RevertWhen_UpdatingNodeWithoutCapabilities() (gas: 25480) +CapabilitiesRegistry_UpdateNodesTest:test_UpdatesNodeParams() (gas: 162113) +KeystoneForwarder_ReportTest:test_Report_ConfigVersion() (gas: 1797755) +KeystoneForwarder_ReportTest:test_Report_FailedDeliveryWhenReceiverInterfaceNotSupported() (gas: 125910) +KeystoneForwarder_ReportTest:test_Report_FailedDeliveryWhenReceiverNotContract() (gas: 127403) +KeystoneForwarder_ReportTest:test_Report_SuccessfulDelivery() (gas: 155928) +KeystoneForwarder_ReportTest:test_RevertWhen_AlreadyAttempted() (gas: 152358) +KeystoneForwarder_ReportTest:test_RevertWhen_AnySignatureIsInvalid() (gas: 86348) +KeystoneForwarder_ReportTest:test_RevertWhen_AnySignerIsInvalid() (gas: 118486) KeystoneForwarder_ReportTest:test_RevertWhen_ReportHasDuplicateSignatures() (gas: 94516) KeystoneForwarder_ReportTest:test_RevertWhen_ReportHasIncorrectDON() (gas: 75930) KeystoneForwarder_ReportTest:test_RevertWhen_ReportHasInexistentConfigVersion() (gas: 76298) -KeystoneForwarder_ReportTest:test_RevertWhen_ReportIsMalformed() (gas: 45563) -KeystoneForwarder_ReportTest:test_RevertWhen_RetryingInvalidContractTransmission() (gas: 143591) -KeystoneForwarder_ReportTest:test_RevertWhen_RetryingSuccessfulTransmission() (gas: 354042) +KeystoneForwarder_ReportTest:test_RevertWhen_ReportIsMalformed() (gas: 45585) KeystoneForwarder_ReportTest:test_RevertWhen_TooFewSignatures() (gas: 55292) KeystoneForwarder_ReportTest:test_RevertWhen_TooManySignatures() (gas: 56050) KeystoneForwarder_SetConfigTest:test_RevertWhen_ExcessSigners() (gas: 20184) KeystoneForwarder_SetConfigTest:test_RevertWhen_FaultToleranceIsZero() (gas: 88057) KeystoneForwarder_SetConfigTest:test_RevertWhen_InsufficientSigners() (gas: 14533) -KeystoneForwarder_SetConfigTest:test_RevertWhen_NotOwner() (gas: 88766) -KeystoneForwarder_SetConfigTest:test_RevertWhen_ProvidingDuplicateSigners() (gas: 114570) -KeystoneForwarder_SetConfigTest:test_RevertWhen_ProvidingZeroAddressSigner() (gas: 114225) -KeystoneForwarder_SetConfigTest:test_SetConfig_FirstTime() (gas: 1540541) -KeystoneForwarder_SetConfigTest:test_SetConfig_WhenSignersAreRemoved() (gas: 1535211) +KeystoneForwarder_SetConfigTest:test_RevertWhen_NotOwner() (gas: 88788) +KeystoneForwarder_SetConfigTest:test_RevertWhen_ProvidingDuplicateSigners() (gas: 114507) +KeystoneForwarder_SetConfigTest:test_SetConfig_FirstTime() (gas: 1539921) +KeystoneForwarder_SetConfigTest:test_SetConfig_WhenSignersAreRemoved() (gas: 1534476) KeystoneForwarder_TypeAndVersionTest:test_TypeAndVersion() (gas: 9641) KeystoneRouter_SetConfigTest:test_AddForwarder_RevertWhen_NotOwner() (gas: 10978) KeystoneRouter_SetConfigTest:test_RemoveForwarder_RevertWhen_NotOwner() (gas: 10923) -KeystoneRouter_SetConfigTest:test_RemoveForwarder_Success() (gas: 17599) -KeystoneRouter_SetConfigTest:test_Route_RevertWhen_UnauthorizedForwarder() (gas: 18552) -KeystoneRouter_SetConfigTest:test_Route_Success() (gas: 79379) \ No newline at end of file +KeystoneRouter_SetConfigTest:test_Route_RevertWhen_UnauthorizedForwarder() (gas: 18553) +KeystoneRouter_SetConfigTest:test_Route_Success() (gas: 75629) \ No newline at end of file diff --git a/contracts/gas-snapshots/llo-feeds.gas-snapshot b/contracts/gas-snapshots/llo-feeds.gas-snapshot index 68f3c016f6..187d3cd89f 100644 --- a/contracts/gas-snapshots/llo-feeds.gas-snapshot +++ b/contracts/gas-snapshots/llo-feeds.gas-snapshot @@ -18,223 +18,6 @@ ByteUtilTest:test_readUint32MultiWord() (gas: 3393) ByteUtilTest:test_readUint32WithEmptyArray() (gas: 3253) ByteUtilTest:test_readUint32WithNotEnoughBytes() (gas: 3272) ByteUtilTest:test_readZeroAddress() (gas: 3365) -ChannelConfigStoreTest:testSetChannelDefinitions() (gas: 46927) -ChannelConfigStoreTest:testSupportsInterface() (gas: 8367) -ChannelConfigStoreTest:testTypeAndVersion() (gas: 9621) -DestinationFeeManagerProcessFeeTest:test_DiscountIsAppliedForNative() (gas: 52669) -DestinationFeeManagerProcessFeeTest:test_DiscountIsReturnedForNative() (gas: 52685) -DestinationFeeManagerProcessFeeTest:test_DiscountIsReturnedForNativeWithSurcharge() (gas: 78876) -DestinationFeeManagerProcessFeeTest:test_V1PayloadVerifies() (gas: 29324) -DestinationFeeManagerProcessFeeTest:test_V1PayloadVerifiesAndReturnsChange() (gas: 61187) -DestinationFeeManagerProcessFeeTest:test_V2PayloadVerifies() (gas: 121137) -DestinationFeeManagerProcessFeeTest:test_V2PayloadWithoutQuoteFails() (gas: 29669) -DestinationFeeManagerProcessFeeTest:test_V2PayloadWithoutZeroFee() (gas: 74797) -DestinationFeeManagerProcessFeeTest:test_WithdrawERC20() (gas: 72796) -DestinationFeeManagerProcessFeeTest:test_WithdrawNonAdminAddr() (gas: 56334) -DestinationFeeManagerProcessFeeTest:test_WithdrawUnwrappedNative() (gas: 26411) -DestinationFeeManagerProcessFeeTest:test_addVerifier() (gas: 131079) -DestinationFeeManagerProcessFeeTest:test_addVerifierExistingAddress() (gas: 34148) -DestinationFeeManagerProcessFeeTest:test_baseFeeIsAppliedForLink() (gas: 17214) -DestinationFeeManagerProcessFeeTest:test_baseFeeIsAppliedForNative() (gas: 20152) -DestinationFeeManagerProcessFeeTest:test_correctDiscountIsAppliedWhenBothTokensAreDiscounted() (gas: 91103) -DestinationFeeManagerProcessFeeTest:test_discountAIsNotAppliedWhenSetForOtherUsers() (gas: 56580) -DestinationFeeManagerProcessFeeTest:test_discountFeeRoundsDownWhenUneven() (gas: 52871) -DestinationFeeManagerProcessFeeTest:test_discountIsAppliedForLink() (gas: 49682) -DestinationFeeManagerProcessFeeTest:test_discountIsAppliedWith100PercentSurcharge() (gas: 78949) -DestinationFeeManagerProcessFeeTest:test_discountIsNoLongerAppliedAfterRemoving() (gas: 46567) -DestinationFeeManagerProcessFeeTest:test_discountIsNotAppliedForInvalidTokenAddress() (gas: 17582) -DestinationFeeManagerProcessFeeTest:test_discountIsNotAppliedToOtherFeeds() (gas: 54628) -DestinationFeeManagerProcessFeeTest:test_discountIsReturnedForLink() (gas: 49654) -DestinationFeeManagerProcessFeeTest:test_emptyQuoteRevertsWithError() (gas: 12231) -DestinationFeeManagerProcessFeeTest:test_eventIsEmittedAfterSurchargeIsSet() (gas: 41424) -DestinationFeeManagerProcessFeeTest:test_eventIsEmittedIfNotEnoughLink() (gas: 179229) -DestinationFeeManagerProcessFeeTest:test_eventIsEmittedUponWithdraw() (gas: 69057) -DestinationFeeManagerProcessFeeTest:test_feeIsUpdatedAfterDiscountIsRemoved() (gas: 49831) -DestinationFeeManagerProcessFeeTest:test_feeIsUpdatedAfterNewDiscountIsApplied() (gas: 67769) -DestinationFeeManagerProcessFeeTest:test_feeIsUpdatedAfterNewSurchargeIsApplied() (gas: 64460) -DestinationFeeManagerProcessFeeTest:test_feeIsZeroWith100PercentDiscount() (gas: 52091) -DestinationFeeManagerProcessFeeTest:test_getBaseRewardWithLinkQuote() (gas: 17231) -DestinationFeeManagerProcessFeeTest:test_getLinkFeeIsRoundedUp() (gas: 49853) -DestinationFeeManagerProcessFeeTest:test_getLinkRewardIsSameAsFee() (gas: 55711) -DestinationFeeManagerProcessFeeTest:test_getLinkRewardWithNativeQuoteAndSurchargeWithLinkDiscount() (gas: 82833) -DestinationFeeManagerProcessFeeTest:test_getRewardWithLinkDiscount() (gas: 49700) -DestinationFeeManagerProcessFeeTest:test_getRewardWithLinkQuoteAndLinkDiscount() (gas: 49681) -DestinationFeeManagerProcessFeeTest:test_getRewardWithNativeQuote() (gas: 20150) -DestinationFeeManagerProcessFeeTest:test_getRewardWithNativeQuoteAndSurcharge() (gas: 50885) -DestinationFeeManagerProcessFeeTest:test_linkAvailableForPaymentReturnsLinkBalance() (gas: 53172) -DestinationFeeManagerProcessFeeTest:test_nativeSurcharge0Percent() (gas: 30937) -DestinationFeeManagerProcessFeeTest:test_nativeSurcharge100Percent() (gas: 50887) -DestinationFeeManagerProcessFeeTest:test_nativeSurchargeCannotExceed100Percent() (gas: 17220) -DestinationFeeManagerProcessFeeTest:test_nativeSurchargeEventIsEmittedOnUpdate() (gas: 41402) -DestinationFeeManagerProcessFeeTest:test_noFeeIsAppliedWhenReportHasZeroFee() (gas: 51914) -DestinationFeeManagerProcessFeeTest:test_noFeeIsAppliedWhenReportHasZeroFeeAndDiscountAndSurchargeIsSet() (gas: 78172) -DestinationFeeManagerProcessFeeTest:test_nonAdminProxyUserCannotProcessFee() (gas: 24185) -DestinationFeeManagerProcessFeeTest:test_nonAdminUserCanNotSetDiscount() (gas: 19871) -DestinationFeeManagerProcessFeeTest:test_onlyCallableByOwnerReverts() (gas: 15453) -DestinationFeeManagerProcessFeeTest:test_payLinkDeficit() (gas: 198072) -DestinationFeeManagerProcessFeeTest:test_payLinkDeficitOnlyCallableByAdmin() (gas: 17415) -DestinationFeeManagerProcessFeeTest:test_payLinkDeficitPaysAllFeesProcessed() (gas: 218691) -DestinationFeeManagerProcessFeeTest:test_payLinkDeficitTwice() (gas: 202446) -DestinationFeeManagerProcessFeeTest:test_poolIdsCannotBeZeroAddress() (gas: 115317) -DestinationFeeManagerProcessFeeTest:test_processFeeAsProxy() (gas: 121475) -DestinationFeeManagerProcessFeeTest:test_processFeeDefaultReportsStillVerifiesWithEmptyQuote() (gas: 29745) -DestinationFeeManagerProcessFeeTest:test_processFeeEmitsEventIfNotEnoughLink() (gas: 165393) -DestinationFeeManagerProcessFeeTest:test_processFeeIfSubscriberIsSelf() (gas: 32563) -DestinationFeeManagerProcessFeeTest:test_processFeeNative() (gas: 178204) -DestinationFeeManagerProcessFeeTest:test_processFeeUsesCorrectDigest() (gas: 122766) -DestinationFeeManagerProcessFeeTest:test_processFeeWithDefaultReportPayloadAndQuoteStillVerifies() (gas: 31822) -DestinationFeeManagerProcessFeeTest:test_processFeeWithDiscountEmitsEvent() (gas: 245890) -DestinationFeeManagerProcessFeeTest:test_processFeeWithInvalidReportVersionFailsToDecode() (gas: 30770) -DestinationFeeManagerProcessFeeTest:test_processFeeWithNoDiscountDoesNotEmitEvent() (gas: 171109) -DestinationFeeManagerProcessFeeTest:test_processFeeWithUnwrappedNative() (gas: 186069) -DestinationFeeManagerProcessFeeTest:test_processFeeWithUnwrappedNativeLinkAddress() (gas: 135874) -DestinationFeeManagerProcessFeeTest:test_processFeeWithUnwrappedNativeLinkAddressExcessiveFee() (gas: 161459) -DestinationFeeManagerProcessFeeTest:test_processFeeWithUnwrappedNativeShortFunds() (gas: 94841) -DestinationFeeManagerProcessFeeTest:test_processFeeWithUnwrappedNativeWithExcessiveFee() (gas: 193032) -DestinationFeeManagerProcessFeeTest:test_processFeeWithWithCorruptQuotePayload() (gas: 75084) -DestinationFeeManagerProcessFeeTest:test_processFeeWithWithEmptyQuotePayload() (gas: 30006) -DestinationFeeManagerProcessFeeTest:test_processFeeWithWithZeroQuotePayload() (gas: 30056) -DestinationFeeManagerProcessFeeTest:test_processFeeWithZeroLinkNonZeroNativeWithLinkQuote() (gas: 35320) -DestinationFeeManagerProcessFeeTest:test_processFeeWithZeroLinkNonZeroNativeWithNativeQuote() (gas: 158081) -DestinationFeeManagerProcessFeeTest:test_processFeeWithZeroNativeNonZeroLinkReturnsChange() (gas: 56059) -DestinationFeeManagerProcessFeeTest:test_processFeeWithZeroNativeNonZeroLinkWithLinkQuote() (gas: 121473) -DestinationFeeManagerProcessFeeTest:test_processFeeWithZeroNativeNonZeroLinkWithNativeQuote() (gas: 38024) -DestinationFeeManagerProcessFeeTest:test_processMultipleLinkReports() (gas: 230434) -DestinationFeeManagerProcessFeeTest:test_processMultipleUnwrappedNativeReports() (gas: 264223) -DestinationFeeManagerProcessFeeTest:test_processMultipleV1Reports() (gas: 81155) -DestinationFeeManagerProcessFeeTest:test_processMultipleWrappedNativeReports() (gas: 247072) -DestinationFeeManagerProcessFeeTest:test_processPoolIdsPassedMismatched() (gas: 98793) -DestinationFeeManagerProcessFeeTest:test_processV1V2V3Reports() (gas: 215445) -DestinationFeeManagerProcessFeeTest:test_processV1V2V3ReportsWithUnwrapped() (gas: 257087) -DestinationFeeManagerProcessFeeTest:test_removeVerifierNonExistentAddress() (gas: 12822) -DestinationFeeManagerProcessFeeTest:test_removeVerifierZeroAaddress() (gas: 10678) -DestinationFeeManagerProcessFeeTest:test_reportWithNoExpiryOrFeeReturnsZero() (gas: 13615) -DestinationFeeManagerProcessFeeTest:test_revertOnSettingAnAddressZeroVerifier() (gas: 10614) -DestinationFeeManagerProcessFeeTest:test_rewardsAreCorrectlySentToEachAssociatedPoolWhenVerifyingInBulk() (gas: 263181) -DestinationFeeManagerProcessFeeTest:test_setDiscountOver100Percent() (gas: 19562) -DestinationFeeManagerProcessFeeTest:test_setRewardManagerZeroAddress() (gas: 10626) -DestinationFeeManagerProcessFeeTest:test_subscriberDiscountEventIsEmittedOnUpdate() (gas: 46329) -DestinationFeeManagerProcessFeeTest:test_surchargeFeeRoundsUpWhenUneven() (gas: 51261) -DestinationFeeManagerProcessFeeTest:test_surchargeIsApplied() (gas: 51165) -DestinationFeeManagerProcessFeeTest:test_surchargeIsAppliedForNativeFeeWithDiscount() (gas: 79356) -DestinationFeeManagerProcessFeeTest:test_surchargeIsNoLongerAppliedAfterRemoving() (gas: 47132) -DestinationFeeManagerProcessFeeTest:test_surchargeIsNotAppliedForLinkFee() (gas: 49962) -DestinationFeeManagerProcessFeeTest:test_surchargeIsNotAppliedWith100PercentDiscount() (gas: 78352) -DestinationFeeManagerProcessFeeTest:test_testRevertIfReportHasExpired() (gas: 14943) -DestinationRewardManagerClaimTest:test_claimAllRecipients() (gas: 277191) -DestinationRewardManagerClaimTest:test_claimMultipleRecipients() (gas: 154371) -DestinationRewardManagerClaimTest:test_claimRewardsWithDuplicatePoolIdsDoesNotPayoutTwice() (gas: 330208) -DestinationRewardManagerClaimTest:test_claimSingleRecipient() (gas: 89039) -DestinationRewardManagerClaimTest:test_claimUnevenAmountRoundsDown() (gas: 315411) -DestinationRewardManagerClaimTest:test_claimUnregisteredPoolId() (gas: 35164) -DestinationRewardManagerClaimTest:test_claimUnregisteredRecipient() (gas: 41201) -DestinationRewardManagerClaimTest:test_eventIsEmittedUponClaim() (gas: 86084) -DestinationRewardManagerClaimTest:test_eventIsNotEmittedUponUnsuccessfulClaim() (gas: 25050) -DestinationRewardManagerClaimTest:test_recipientsClaimMultipleDeposits() (gas: 386857) -DestinationRewardManagerClaimTest:test_singleRecipientClaimMultipleDeposits() (gas: 137777) -DestinationRewardManagerNoRecipientSet:test_claimAllRecipientsAfterRecipientsSet() (gas: 492227) -DestinationRewardManagerPayRecipientsTest:test_addFundsToPoolAsNonOwnerOrFeeManager() (gas: 11503) -DestinationRewardManagerPayRecipientsTest:test_addFundsToPoolAsOwner() (gas: 53944) -DestinationRewardManagerPayRecipientsTest:test_payAllRecipients() (gas: 250829) -DestinationRewardManagerPayRecipientsTest:test_payAllRecipientsFromNonAdminUser() (gas: 20496) -DestinationRewardManagerPayRecipientsTest:test_payAllRecipientsFromRecipientInPool() (gas: 251075) -DestinationRewardManagerPayRecipientsTest:test_payAllRecipientsWithAdditionalInvalidRecipient() (gas: 262275) -DestinationRewardManagerPayRecipientsTest:test_payAllRecipientsWithAdditionalUnregisteredRecipient() (gas: 265760) -DestinationRewardManagerPayRecipientsTest:test_payRecipientWithInvalidPool() (gas: 28908) -DestinationRewardManagerPayRecipientsTest:test_payRecipientsEmptyRecipientList() (gas: 25333) -DestinationRewardManagerPayRecipientsTest:test_payRecipientsWithInvalidPoolId() (gas: 31402) -DestinationRewardManagerPayRecipientsTest:test_paySingleRecipient() (gas: 84709) -DestinationRewardManagerPayRecipientsTest:test_paySubsetOfRecipientsInPool() (gas: 198474) -DestinationRewardManagerRecipientClaimDifferentWeightsTest:test_allRecipientsClaimingReceiveExpectedAmount() (gas: 280853) -DestinationRewardManagerRecipientClaimMultiplePoolsTest:test_claimAllRecipientsMultiplePools() (gas: 512489) -DestinationRewardManagerRecipientClaimMultiplePoolsTest:test_claimAllRecipientsSinglePool() (gas: 283649) -DestinationRewardManagerRecipientClaimMultiplePoolsTest:test_claimEmptyPoolWhenSecondPoolContainsFunds() (gas: 293497) -DestinationRewardManagerRecipientClaimMultiplePoolsTest:test_claimMultipleRecipientsMultiplePools() (gas: 263075) -DestinationRewardManagerRecipientClaimMultiplePoolsTest:test_claimMultipleRecipientsSinglePool() (gas: 154537) -DestinationRewardManagerRecipientClaimMultiplePoolsTest:test_claimSingleRecipientMultiplePools() (gas: 132653) -DestinationRewardManagerRecipientClaimMultiplePoolsTest:test_claimSingleUniqueRecipient() (gas: 106056) -DestinationRewardManagerRecipientClaimMultiplePoolsTest:test_claimUnevenAmountRoundsDown() (gas: 579776) -DestinationRewardManagerRecipientClaimMultiplePoolsTest:test_claimUnregisteredRecipient() (gas: 64664) -DestinationRewardManagerRecipientClaimMultiplePoolsTest:test_getAvailableRewardsCursorAndTotalPoolsEqual() (gas: 13074) -DestinationRewardManagerRecipientClaimMultiplePoolsTest:test_getAvailableRewardsCursorCannotBeGreaterThanTotalPools() (gas: 12703) -DestinationRewardManagerRecipientClaimMultiplePoolsTest:test_getAvailableRewardsCursorSingleResult() (gas: 22471) -DestinationRewardManagerRecipientClaimMultiplePoolsTest:test_getRewardsAvailableToRecipientInBothPools() (gas: 32248) -DestinationRewardManagerRecipientClaimMultiplePoolsTest:test_getRewardsAvailableToRecipientInBothPoolsWhereAlreadyClaimed() (gas: 148629) -DestinationRewardManagerRecipientClaimMultiplePoolsTest:test_getRewardsAvailableToRecipientInNoPools() (gas: 21728) -DestinationRewardManagerRecipientClaimMultiplePoolsTest:test_getRewardsAvailableToRecipientInSinglePool() (gas: 27765) -DestinationRewardManagerRecipientClaimMultiplePoolsTest:test_recipientsClaimMultipleDeposits() (gas: 391427) -DestinationRewardManagerRecipientClaimMultiplePoolsTest:test_singleRecipientClaimMultipleDeposits() (gas: 137862) -DestinationRewardManagerRecipientClaimUnevenWeightTest:test_allRecipientsClaimingReceiveExpectedAmount() (gas: 199546) -DestinationRewardManagerRecipientClaimUnevenWeightTest:test_allRecipientsClaimingReceiveExpectedAmountWithSmallDeposit() (gas: 219419) -DestinationRewardManagerSetRecipientsTest:test_eventIsEmittedUponSetRecipients() (gas: 191707) -DestinationRewardManagerSetRecipientsTest:test_setRecipientContainsDuplicateRecipients() (gas: 126060) -DestinationRewardManagerSetRecipientsTest:test_setRewardRecipientFromManagerAddress() (gas: 214117) -DestinationRewardManagerSetRecipientsTest:test_setRewardRecipientFromNonOwnerOrFeeManagerAddress() (gas: 21496) -DestinationRewardManagerSetRecipientsTest:test_setRewardRecipientTwice() (gas: 193280) -DestinationRewardManagerSetRecipientsTest:test_setRewardRecipientWeights() (gas: 180608) -DestinationRewardManagerSetRecipientsTest:test_setRewardRecipientWithZeroAddress() (gas: 90202) -DestinationRewardManagerSetRecipientsTest:test_setRewardRecipientWithZeroWeight() (gas: 191312) -DestinationRewardManagerSetRecipientsTest:test_setRewardRecipients() (gas: 185567) -DestinationRewardManagerSetRecipientsTest:test_setRewardRecipientsIsEmpty() (gas: 87091) -DestinationRewardManagerSetRecipientsTest:test_setSingleRewardRecipient() (gas: 110349) -DestinationRewardManagerSetupTest:test_addFeeManagerExistingAddress() (gas: 35281) -DestinationRewardManagerSetupTest:test_addFeeManagerZeroAddress() (gas: 10580) -DestinationRewardManagerSetupTest:test_addRemoveFeeManager() (gas: 48248) -DestinationRewardManagerSetupTest:test_eventEmittedUponFeeManagerUpdate() (gas: 41581) -DestinationRewardManagerSetupTest:test_eventEmittedUponFeePaid() (gas: 259172) -DestinationRewardManagerSetupTest:test_rejectsZeroLinkAddressOnConstruction() (gas: 59610) -DestinationRewardManagerSetupTest:test_removeFeeManagerNonExistentAddress() (gas: 12778) -DestinationRewardManagerSetupTest:test_setFeeManagerZeroAddress() (gas: 17084) -DestinationRewardManagerUpdateRewardRecipientsMultiplePoolsTest:test_updatePrimaryRecipientWeights() (gas: 376674) -DestinationRewardManagerUpdateRewardRecipientsTest:test_eventIsEmittedUponUpdateRecipients() (gas: 280411) -DestinationRewardManagerUpdateRewardRecipientsTest:test_onlyAdminCanUpdateRecipients() (gas: 19705) -DestinationRewardManagerUpdateRewardRecipientsTest:test_partialUpdateRecipientWeights() (gas: 221004) -DestinationRewardManagerUpdateRewardRecipientsTest:test_updateAllRecipientsWithSameAddressAndWeight() (gas: 274233) -DestinationRewardManagerUpdateRewardRecipientsTest:test_updatePartialRecipientsToSubset() (gas: 254156) -DestinationRewardManagerUpdateRewardRecipientsTest:test_updatePartialRecipientsWithExcessiveWeight() (gas: 259143) -DestinationRewardManagerUpdateRewardRecipientsTest:test_updatePartialRecipientsWithSameAddressAndWeight() (gas: 149856) -DestinationRewardManagerUpdateRewardRecipientsTest:test_updatePartialRecipientsWithUnderWeightSet() (gas: 259217) -DestinationRewardManagerUpdateRewardRecipientsTest:test_updateRecipientWeights() (gas: 372155) -DestinationRewardManagerUpdateRewardRecipientsTest:test_updateRecipientWithNewZeroAddress() (gas: 270700) -DestinationRewardManagerUpdateRewardRecipientsTest:test_updateRecipientsContainsDuplicateRecipients() (gas: 288483) -DestinationRewardManagerUpdateRewardRecipientsTest:test_updateRecipientsToDifferentLargerSet() (gas: 407780) -DestinationRewardManagerUpdateRewardRecipientsTest:test_updateRecipientsToDifferentPartialSet() (gas: 317945) -DestinationRewardManagerUpdateRewardRecipientsTest:test_updateRecipientsToDifferentSet() (gas: 377692) -DestinationRewardManagerUpdateRewardRecipientsTest:test_updateRecipientsToDifferentSetWithInvalidWeights() (gas: 312038) -DestinationRewardManagerUpdateRewardRecipientsTest:test_updateRecipientsUpdateAndRemoveExistingForLargerSet() (gas: 399603) -DestinationRewardManagerUpdateRewardRecipientsTest:test_updateRecipientsUpdateAndRemoveExistingForSmallerSet() (gas: 289433) -DestinationVerifierBulkVerifyBillingReport:test_verifyWithBulkLink() (gas: 639153) -DestinationVerifierBulkVerifyBillingReport:test_verifyWithBulkNative() (gas: 640232) -DestinationVerifierBulkVerifyBillingReport:test_verifyWithBulkNativeUnwrapped() (gas: 661796) -DestinationVerifierBulkVerifyBillingReport:test_verifyWithBulkNativeUnwrappedReturnsChange() (gas: 661751) -DestinationVerifierConstructorTest:test_falseIfIsNotCorrectInterface() (gas: 8719) -DestinationVerifierConstructorTest:test_revertsIfInitializedWithEmptyVerifierProxy() (gas: 61121) -DestinationVerifierConstructorTest:test_trueIfIsCorrectInterface() (gas: 8604) -DestinationVerifierConstructorTest:test_typeAndVersion() (gas: 2818189) -DestinationVerifierProxyInitializeVerifierTest:test_correctlySetsTheOwner() (gas: 1035181) -DestinationVerifierProxyInitializeVerifierTest:test_correctlySetsVersion() (gas: 9841) -DestinationVerifierProxyInitializeVerifierTest:test_setVerifierCalledByNoOwner() (gas: 17483) -DestinationVerifierProxyInitializeVerifierTest:test_setVerifierOk() (gas: 30622) -DestinationVerifierProxyInitializeVerifierTest:test_setVerifierWhichDoesntHonourInterface() (gas: 16851) -DestinationVerifierSetAccessControllerTest:test_emitsTheCorrectEvent() (gas: 35391) -DestinationVerifierSetAccessControllerTest:test_revertsIfCalledByNonOwner() (gas: 15089) -DestinationVerifierSetAccessControllerTest:test_successfullySetsNewAccessController() (gas: 34885) -DestinationVerifierSetAccessControllerTest:test_successfullySetsNewAccessControllerIsEmpty() (gas: 15007) -DestinationVerifierSetConfigTest:test_NoDonConfigAlreadyExists() (gas: 2874492) -DestinationVerifierSetConfigTest:test_addressesAndWeightsDoNotProduceSideEffectsInDonConfigIds() (gas: 1323177) -DestinationVerifierSetConfigTest:test_donConfigIdIsSameForSignersInDifferentOrder() (gas: 1290374) -DestinationVerifierSetConfigTest:test_removeLatestConfig() (gas: 786275) -DestinationVerifierSetConfigTest:test_removeLatestConfigWhenNoConfigShouldFail() (gas: 12870) -DestinationVerifierSetConfigTest:test_revertsIfCalledByNonOwner() (gas: 174936) -DestinationVerifierSetConfigTest:test_revertsIfDuplicateSigners() (gas: 171604) -DestinationVerifierSetConfigTest:test_revertsIfFaultToleranceIsZero() (gas: 168484) -DestinationVerifierSetConfigTest:test_revertsIfNotEnoughSigners() (gas: 11571) -DestinationVerifierSetConfigTest:test_revertsIfSetWithTooManySigners() (gas: 17943) -DestinationVerifierSetConfigTest:test_revertsIfSignerContainsZeroAddress() (gas: 324333) -DestinationVerifierSetConfigTest:test_setConfigActiveUnknownDonConfigId() (gas: 13102) -DestinationVerifierSetConfigTest:test_setConfigWithActivationTime() (gas: 1088176) -DestinationVerifierSetConfigTest:test_setConfigWithActivationTimeEarlierThanLatestConfigShouldFail() (gas: 1963414) -DestinationVerifierSetConfigTest:test_setConfigWithActivationTimeNoFutureTimeShouldFail() (gas: 259797) FeeManagerProcessFeeTest:test_DiscountIsAppliedForNative() (gas: 52645) FeeManagerProcessFeeTest:test_DiscountIsReturnedForNative() (gas: 52595) FeeManagerProcessFeeTest:test_DiscountIsReturnedForNativeWithSurcharge() (gas: 78808) @@ -325,7 +108,6 @@ FeeManagerProcessFeeTest:test_surchargeIsNoLongerAppliedAfterRemoving() (gas: 47 FeeManagerProcessFeeTest:test_surchargeIsNotAppliedForLinkFee() (gas: 49938) FeeManagerProcessFeeTest:test_surchargeIsNotAppliedWith100PercentDiscount() (gas: 78261) FeeManagerProcessFeeTest:test_testRevertIfReportHasExpired() (gas: 14919) -MultiVerifierBillingTests:test_multipleFeeManagersAndVerifiers() (gas: 4586990) RewardManagerClaimTest:test_claimAllRecipients() (gas: 277131) RewardManagerClaimTest:test_claimMultipleRecipients() (gas: 154341) RewardManagerClaimTest:test_claimRewardsWithDuplicatePoolIdsDoesNotPayoutTwice() (gas: 330086) @@ -418,13 +200,6 @@ VerifierActivateFeedTest:test_revertsIfNoFeedExistsActivate() (gas: 13179) VerifierActivateFeedTest:test_revertsIfNoFeedExistsDeactivate() (gas: 13157) VerifierActivateFeedTest:test_revertsIfNotOwnerActivateFeed() (gas: 17109) VerifierActivateFeedTest:test_revertsIfNotOwnerDeactivateFeed() (gas: 17164) -VerifierBillingTests:test_rewardsAreDistributedAccordingToWeights() (gas: 1731717) -VerifierBillingTests:test_rewardsAreDistributedAccordingToWeightsMultipleWeigths() (gas: 4460715) -VerifierBillingTests:test_rewardsAreDistributedAccordingToWeightsUsingHistoricalConfigs() (gas: 2098833) -VerifierBillingTests:test_verifyWithLinkV3Report() (gas: 1591346) -VerifierBillingTests:test_verifyWithNativeERC20() (gas: 1467256) -VerifierBillingTests:test_verifyWithNativeUnwrapped() (gas: 1376447) -VerifierBillingTests:test_verifyWithNativeUnwrappedReturnsChange() (gas: 1383493) VerifierBulkVerifyBillingReport:test_verifyMultiVersions() (gas: 476595) VerifierBulkVerifyBillingReport:test_verifyMultiVersionsReturnsVerifiedReports() (gas: 474853) VerifierBulkVerifyBillingReport:test_verifyWithBulkLink() (gas: 557541) @@ -437,7 +212,6 @@ VerifierDeactivateFeedWithVerifyTest:test_currentReportAllowsVerification() (gas VerifierDeactivateFeedWithVerifyTest:test_currentReportFailsVerification() (gas: 113388) VerifierDeactivateFeedWithVerifyTest:test_previousReportAllowsVerification() (gas: 99624) VerifierDeactivateFeedWithVerifyTest:test_previousReportFailsVerification() (gas: 69943) -VerifierInterfacesTest:test_DestinationContractInterfaces() (gas: 623467) VerifierProxyAccessControlledVerificationTest:test_proxiesToTheVerifierIfHasAccess() (gas: 208529) VerifierProxyAccessControlledVerificationTest:test_revertsIfNoAccess() (gas: 112345) VerifierProxyConstructorTest:test_correctlySetsTheCorrectAccessControllerInterface() (gas: 1485359) @@ -462,9 +236,6 @@ VerifierProxyUnsetVerifierWithPreviouslySetVerifierTest:test_correctlyUnsetsVeri VerifierProxyUnsetVerifierWithPreviouslySetVerifierTest:test_emitsAnEventAfterUnsettingVerifier() (gas: 17961) VerifierProxyVerifyTest:test_proxiesToTheCorrectVerifier() (gas: 204342) VerifierProxyVerifyTest:test_revertsIfNoVerifierConfigured() (gas: 117264) -VerifierSetAccessControllerTest:test_revertsIfCalledByNonOwner() (gas: 17196) -VerifierSetAccessControllerTest:test_setFeeManagerWhichDoesntHonourInterface() (gas: 16571) -VerifierSetAccessControllerTest:test_successfullySetsNewFeeManager() (gas: 44855) VerifierSetConfigFromSourceMultipleDigestsTest:test_correctlySetsConfigWhenDigestsAreRemoved() (gas: 542302) VerifierSetConfigFromSourceMultipleDigestsTest:test_correctlyUpdatesDigestsOnMultipleVerifiersInTheProxy() (gas: 967768) VerifierSetConfigFromSourceMultipleDigestsTest:test_correctlyUpdatesTheDigestInTheProxy() (gas: 523251) @@ -485,9 +256,6 @@ VerifierTestBillingReport:test_verifyWithLink() (gas: 275293) VerifierTestBillingReport:test_verifyWithNative() (gas: 316326) VerifierTestBillingReport:test_verifyWithNativeUnwrapped() (gas: 318574) VerifierTestBillingReport:test_verifyWithNativeUnwrappedReturnsChange() (gas: 325642) -VerifierVerifyBulkTest:test_revertsVerifyBulkIfNoAccess() (gas: 112867) -VerifierVerifyBulkTest:test_verifyBulkSingleCaseWithSingleConfig() (gas: 745046) -VerifierVerifyBulkTest:test_verifyBulkWithSingleConfigOneVerifyFails() (gas: 698203) VerifierVerifyMultipleConfigDigestTest:test_canVerifyNewerReportsWithNewerConfigs() (gas: 133961) VerifierVerifyMultipleConfigDigestTest:test_canVerifyOlderReportsWithOlderConfigs() (gas: 189865) VerifierVerifyMultipleConfigDigestTest:test_revertsIfAReportIsVerifiedWithAnExistingButIncorrectDigest() (gas: 88216) @@ -502,18 +270,6 @@ VerifierVerifySingleConfigDigestTest:test_revertsIfVerifiedByNonProxy() (gas: 10 VerifierVerifySingleConfigDigestTest:test_revertsIfVerifiedWithIncorrectAddresses() (gas: 184077) VerifierVerifySingleConfigDigestTest:test_revertsIfWrongNumberOfSigners() (gas: 110042) VerifierVerifySingleConfigDigestTest:test_setsTheCorrectEpoch() (gas: 194592) -VerifierVerifyTest:test_canVerifyNewerReportsWithNewerConfigs() (gas: 861741) -VerifierVerifyTest:test_canVerifyOlderV3ReportsWithOlderConfigs() (gas: 815984) -VerifierVerifyTest:test_failToVerifyReportIfDupSigners() (gas: 450715) -VerifierVerifyTest:test_failToVerifyReportIfNoSigners() (gas: 426492) -VerifierVerifyTest:test_failToVerifyReportIfNotEnoughSigners() (gas: 434814) -VerifierVerifyTest:test_failToVerifyReportIfSignerNotInConfig() (gas: 456866) -VerifierVerifyTest:test_revertsVerifyIfNoAccess() (gas: 109465) -VerifierVerifyTest:test_rollingOutConfiguration() (gas: 1497254) -VerifierVerifyTest:test_scenarioRollingNewChainWithHistoricConfigs() (gas: 976162) -VerifierVerifyTest:test_verifyFailsWhenReportIsOlderThanConfig() (gas: 2303366) -VerifierVerifyTest:test_verifyReport() (gas: 1434811) -VerifierVerifyTest:test_verifyTooglingActiveFlagsDonConfigs() (gas: 1918797) Verifier_accessControlledVerify:testVerifyWithAccessControl_gas() (gas: 212077) Verifier_bulkVerifyWithFee:testBulkVerifyProxyWithLinkFeeSuccess_gas() (gas: 519389) Verifier_bulkVerifyWithFee:testBulkVerifyProxyWithNativeFeeSuccess_gas() (gas: 542808) diff --git a/contracts/gas-snapshots/shared.gas-snapshot b/contracts/gas-snapshots/shared.gas-snapshot index d7a4e21978..0848baa098 100644 --- a/contracts/gas-snapshots/shared.gas-snapshot +++ b/contracts/gas-snapshots/shared.gas-snapshot @@ -39,10 +39,10 @@ CallWithExactGas__callWithExactGas:test_CallWithExactGasSafeReturnDataExactGas() CallWithExactGas__callWithExactGas:test_NoContractReverts() (gas: 11559) CallWithExactGas__callWithExactGas:test_NoGasForCallExactCheckReverts() (gas: 15788) CallWithExactGas__callWithExactGas:test_NotEnoughGasForCallReverts() (gas: 16241) -CallWithExactGas__callWithExactGas:test_callWithExactGasSuccess(bytes,bytes4) (runs: 257, μ: 15766, ~: 15719) +CallWithExactGas__callWithExactGas:test_callWithExactGasSuccess(bytes,bytes4) (runs: 257, μ: 15767, ~: 15719) CallWithExactGas__callWithExactGasEvenIfTargetIsNoContract:test_CallWithExactGasEvenIfTargetIsNoContractExactGasSuccess() (gas: 20116) CallWithExactGas__callWithExactGasEvenIfTargetIsNoContract:test_CallWithExactGasEvenIfTargetIsNoContractReceiverErrorSuccess() (gas: 67721) -CallWithExactGas__callWithExactGasEvenIfTargetIsNoContract:test_CallWithExactGasEvenIfTargetIsNoContractSuccess(bytes,bytes4) (runs: 257, μ: 16276, ~: 16229) +CallWithExactGas__callWithExactGasEvenIfTargetIsNoContract:test_CallWithExactGasEvenIfTargetIsNoContractSuccess(bytes,bytes4) (runs: 257, μ: 16277, ~: 16229) CallWithExactGas__callWithExactGasEvenIfTargetIsNoContract:test_NoContractSuccess() (gas: 12962) CallWithExactGas__callWithExactGasEvenIfTargetIsNoContract:test_NoGasForCallExactCheckReturnFalseSuccess() (gas: 13005) CallWithExactGas__callWithExactGasEvenIfTargetIsNoContract:test_NotEnoughGasForCallReturnsFalseSuccess() (gas: 13317) diff --git a/contracts/pnpm-lock.yaml b/contracts/pnpm-lock.yaml index 5c45da8ab0..e2a4f29137 100644 --- a/contracts/pnpm-lock.yaml +++ b/contracts/pnpm-lock.yaml @@ -132,6 +132,12 @@ importers: hardhat-ignore-warnings: specifier: ^0.2.6 version: 0.2.11 + husky: + specifier: ^9.0.11 + version: 9.1.5 + lint-staged: + specifier: ^15.2.2 + version: 15.2.9 moment: specifier: ^2.30.1 version: 2.30.1 @@ -916,6 +922,10 @@ packages: resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} engines: {node: '>=8'} + ansi-escapes@7.0.0: + resolution: {integrity: sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==} + engines: {node: '>=18'} + ansi-regex@2.1.1: resolution: {integrity: sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==} engines: {node: '>=0.10.0'} @@ -924,6 +934,10 @@ packages: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} + ansi-regex@6.0.1: + resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} + engines: {node: '>=12'} + ansi-styles@3.2.1: resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} engines: {node: '>=4'} @@ -932,6 +946,10 @@ packages: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} + ansi-styles@6.2.1: + resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} + engines: {node: '>=12'} + antlr4@4.13.1-patch-1: resolution: {integrity: sha512-OjFLWWLzDMV9rdFhpvroCWR4ooktNg9/nvVYSA5z28wuVpU36QUNuioR1XLnQtcjVlf8npjyz593PxnU/f/Cow==} engines: {node: '>=16'} @@ -1057,6 +1075,10 @@ packages: resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} engines: {node: '>=8'} + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + brorand@1.1.0: resolution: {integrity: sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==} @@ -1141,6 +1163,10 @@ packages: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} + chalk@5.3.0: + resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + change-case@3.0.2: resolution: {integrity: sha512-Mww+SLF6MZ0U6kdg11algyKd5BARbyM4TbFBepwowYSR5ClfQGCGtxNXgykpN0uF/bstWeaGDT4JWaDh8zWAHA==} @@ -1172,6 +1198,14 @@ packages: resolution: {integrity: sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==} engines: {node: '>=6'} + cli-cursor@5.0.0: + resolution: {integrity: sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==} + engines: {node: '>=18'} + + cli-truncate@4.0.0: + resolution: {integrity: sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==} + engines: {node: '>=18'} + cliui@7.0.4: resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} @@ -1195,6 +1229,9 @@ packages: color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + colorette@2.0.20: + resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} + command-exists@1.2.9: resolution: {integrity: sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==} @@ -1210,6 +1247,10 @@ packages: resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==} engines: {node: '>=14'} + commander@12.1.0: + resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==} + engines: {node: '>=18'} + commander@3.0.2: resolution: {integrity: sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow==} @@ -1366,6 +1407,9 @@ packages: elliptic@6.5.4: resolution: {integrity: sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==} + emoji-regex@10.4.0: + resolution: {integrity: sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==} + emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} @@ -1380,6 +1424,10 @@ packages: resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} engines: {node: '>=6'} + environment@1.1.0: + resolution: {integrity: sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==} + engines: {node: '>=18'} + error-ex@1.3.2: resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} @@ -1518,9 +1566,16 @@ packages: resolution: {integrity: sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==} engines: {node: '>=6.5.0', npm: '>=3'} + eventemitter3@5.0.1: + resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} + evp_bytestokey@1.0.3: resolution: {integrity: sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==} + execa@8.0.1: + resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} + engines: {node: '>=16.17'} + extendable-error@0.1.7: resolution: {integrity: sha512-UOiS2in6/Q0FK0R0q6UY9vYpQ21mr/Qn1KOnte7vsACuNJf514WvCCUHSRCPcgjPT2bAhNIJdlE6bVap1GKmeg==} @@ -1559,6 +1614,10 @@ packages: resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} engines: {node: '>=8'} + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + find-replace@3.0.0: resolution: {integrity: sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==} engines: {node: '>=4.0.0'} @@ -1647,6 +1706,10 @@ packages: resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} engines: {node: 6.* || 8.* || >= 10.*} + get-east-asian-width@1.2.0: + resolution: {integrity: sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==} + engines: {node: '>=18'} + get-func-name@2.0.2: resolution: {integrity: sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==} @@ -1665,6 +1728,10 @@ packages: resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} engines: {node: '>=10'} + get-stream@8.0.1: + resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} + engines: {node: '>=16'} + get-symbol-description@1.0.0: resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==} engines: {node: '>= 0.4'} @@ -1824,6 +1891,15 @@ packages: human-id@1.0.2: resolution: {integrity: sha512-UNopramDEhHJD+VR+ehk8rOslwSfByxPIZyJRfV739NDhN5LF1fa1MqnzKm2lGTQRjNrjK19Q5fhkgIfjlVUKw==} + human-signals@5.0.0: + resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} + engines: {node: '>=16.17.0'} + + husky@9.1.5: + resolution: {integrity: sha512-rowAVRUBfI0b4+niA4SJMhfQwc107VLkBUgEYYAOQAbqDCnra1nYh83hF/MDmhYs9t9n1E3DuKOrs2LYNC+0Ag==} + engines: {node: '>=18'} + hasBin: true + iconv-lite@0.4.24: resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} engines: {node: '>=0.10.0'} @@ -1921,6 +1997,14 @@ packages: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} engines: {node: '>=8'} + is-fullwidth-code-point@4.0.0: + resolution: {integrity: sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==} + engines: {node: '>=12'} + + is-fullwidth-code-point@5.0.0: + resolution: {integrity: sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==} + engines: {node: '>=18'} + is-glob@4.0.3: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} @@ -1967,6 +2051,10 @@ packages: resolution: {integrity: sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==} engines: {node: '>= 0.4'} + is-stream@3.0.0: + resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + is-string@1.0.7: resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} engines: {node: '>= 0.4'} @@ -2085,9 +2173,22 @@ packages: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} + lilconfig@3.1.2: + resolution: {integrity: sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==} + engines: {node: '>=14'} + lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + lint-staged@15.2.9: + resolution: {integrity: sha512-BZAt8Lk3sEnxw7tfxM7jeZlPRuT4M68O0/CwZhhaw6eeWu0Lz5eERE3m386InivXB64fp/mDID452h48tvKlRQ==} + engines: {node: '>=18.12.0'} + hasBin: true + + listr2@8.2.4: + resolution: {integrity: sha512-opevsywziHd3zHCVQGAj8zu+Z3yHNkkoYhWIGnq54RrCVwLz0MozotJEDnKsIBLvkfLGN6BLOyAeRrYI0pKA4g==} + engines: {node: '>=18.0.0'} + load-yaml-file@0.2.0: resolution: {integrity: sha512-OfCBkGEw4nN6JLtgRidPX6QxjBQGQf72q3si2uvqyFEMbycSFFHwAZeXx6cJgFM9wmLrf9zBwCP3Ivqa+LLZPw==} engines: {node: '>=6'} @@ -2132,6 +2233,10 @@ packages: resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} engines: {node: '>=10'} + log-update@6.1.0: + resolution: {integrity: sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==} + engines: {node: '>=18'} + loupe@2.3.7: resolution: {integrity: sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==} @@ -2169,6 +2274,9 @@ packages: resolution: {integrity: sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==} engines: {node: '>= 0.10.0'} + merge-stream@2.0.0: + resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + merge2@1.4.1: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} @@ -2177,6 +2285,18 @@ packages: resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} engines: {node: '>=8.6'} + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} + engines: {node: '>=8.6'} + + mimic-fn@4.0.0: + resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} + engines: {node: '>=12'} + + mimic-function@5.0.1: + resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==} + engines: {node: '>=18'} + mimic-response@1.0.1: resolution: {integrity: sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==} engines: {node: '>=4'} @@ -2288,6 +2408,10 @@ packages: resolution: {integrity: sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==} engines: {node: '>=10'} + npm-run-path@5.3.0: + resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + number-to-bn@1.7.0: resolution: {integrity: sha512-wsJ9gfSz1/s4ZsJN01lyonwuxA1tml6X1yBDnfpMglypcBRFZZkus26EdPSlqS5GJfYddVZa22p3VNb3z5m5Ig==} engines: {node: '>=6.5.0', npm: '>=3'} @@ -2313,6 +2437,14 @@ packages: once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + onetime@6.0.0: + resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} + engines: {node: '>=12'} + + onetime@7.0.0: + resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==} + engines: {node: '>=18'} + open@7.4.2: resolution: {integrity: sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==} engines: {node: '>=8'} @@ -2425,6 +2557,10 @@ packages: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} + path-key@4.0.0: + resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} + engines: {node: '>=12'} + path-parse@1.0.7: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} @@ -2447,6 +2583,11 @@ packages: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} + pidtree@0.6.0: + resolution: {integrity: sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==} + engines: {node: '>=0.10'} + hasBin: true + pify@4.0.1: resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} engines: {node: '>=6'} @@ -2585,6 +2726,10 @@ packages: responselike@2.0.1: resolution: {integrity: sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==} + restore-cursor@5.1.0: + resolution: {integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==} + engines: {node: '>=18'} + retry@0.12.0: resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==} engines: {node: '>= 4'} @@ -2593,6 +2738,9 @@ packages: resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + rfdc@1.4.1: + resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} + rimraf@2.7.1: resolution: {integrity: sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==} hasBin: true @@ -2714,6 +2862,10 @@ packages: signal-exit@3.0.7: resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + slash@2.0.0: resolution: {integrity: sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==} engines: {node: '>=6'} @@ -2726,6 +2878,14 @@ packages: resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==} engines: {node: '>=10'} + slice-ansi@5.0.0: + resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==} + engines: {node: '>=12'} + + slice-ansi@7.1.0: + resolution: {integrity: sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==} + engines: {node: '>=18'} + snake-case@2.1.0: resolution: {integrity: sha512-FMR5YoPFwOLuh4rRz92dywJjyKYZNLpMn1R5ujVpIYkbA9p01fq8RMg0FkO4M+Yobt4MjHeLTJVm5xFFBHSV2Q==} @@ -2838,6 +2998,10 @@ packages: resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} engines: {node: '>= 0.8'} + string-argv@0.3.2: + resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} + engines: {node: '>=0.6.19'} + string-format@2.0.0: resolution: {integrity: sha512-bbEs3scLeYNXLecRRuk6uJxdXUSj6le/8rNPHChIJTn2V79aXVTR1EH2OH5zLKKoz0V02fOUKZZcw01pLUShZA==} @@ -2845,6 +3009,10 @@ packages: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} + string-width@7.2.0: + resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} + engines: {node: '>=18'} + string.prototype.trim@1.2.8: resolution: {integrity: sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==} engines: {node: '>= 0.4'} @@ -2873,10 +3041,18 @@ packages: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} + strip-ansi@7.1.0: + resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} + engines: {node: '>=12'} + strip-bom@3.0.0: resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} engines: {node: '>=4'} + strip-final-newline@3.0.0: + resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} + engines: {node: '>=12'} + strip-hex-prefix@1.0.0: resolution: {integrity: sha1-DF8VX+8RUTczd96du1iNoFUA428=} engines: {node: '>=6.5.0', npm: '>=3'} @@ -3152,6 +3328,10 @@ packages: resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} engines: {node: '>=10'} + wrap-ansi@9.0.0: + resolution: {integrity: sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==} + engines: {node: '>=18'} + wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} @@ -3190,6 +3370,11 @@ packages: resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==} engines: {node: '>= 6'} + yaml@2.5.0: + resolution: {integrity: sha512-2wWLbGbYDiSqqIKoPjar3MPgB94ErzCtrNE1FdqGuaO0pi2JGjmE8aW8TDZwzU7vuxcGRdL/4gPQwQ7hD5AMSw==} + engines: {node: '>= 14'} + hasBin: true + yargs-parser@20.2.4: resolution: {integrity: sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==} engines: {node: '>=10'} @@ -4411,10 +4596,16 @@ snapshots: dependencies: type-fest: 0.21.3 + ansi-escapes@7.0.0: + dependencies: + environment: 1.1.0 + ansi-regex@2.1.1: {} ansi-regex@5.0.1: {} + ansi-regex@6.0.1: {} + ansi-styles@3.2.1: dependencies: color-convert: 1.9.3 @@ -4423,6 +4614,8 @@ snapshots: dependencies: color-convert: 2.0.1 + ansi-styles@6.2.1: {} + antlr4@4.13.1-patch-1: {} anymatch@3.1.2: @@ -4566,6 +4759,10 @@ snapshots: dependencies: fill-range: 7.0.1 + braces@3.0.3: + dependencies: + fill-range: 7.1.1 + brorand@1.1.0: {} browser-stdout@1.3.1: {} @@ -4674,6 +4871,8 @@ snapshots: ansi-styles: 4.3.0 supports-color: 7.2.0 + chalk@5.3.0: {} + change-case@3.0.2: dependencies: camel-case: 3.0.0 @@ -4726,6 +4925,15 @@ snapshots: cli-boxes@2.2.1: {} + cli-cursor@5.0.0: + dependencies: + restore-cursor: 5.1.0 + + cli-truncate@4.0.0: + dependencies: + slice-ansi: 5.0.0 + string-width: 7.2.0 + cliui@7.0.4: dependencies: string-width: 4.2.3 @@ -4750,6 +4958,8 @@ snapshots: color-name@1.1.4: {} + colorette@2.0.20: {} + command-exists@1.2.9: {} command-line-args@5.2.1: @@ -4768,6 +4978,8 @@ snapshots: commander@10.0.1: {} + commander@12.1.0: {} + commander@3.0.2: {} compare-versions@6.1.1: @@ -4949,6 +5161,8 @@ snapshots: minimalistic-assert: 1.0.1 minimalistic-crypto-utils: 1.0.1 + emoji-regex@10.4.0: {} + emoji-regex@8.0.0: {} end-of-stream@1.4.4: @@ -4961,6 +5175,8 @@ snapshots: env-paths@2.2.1: {} + environment@1.1.0: {} + error-ex@1.3.2: dependencies: is-arrayish: 0.2.1 @@ -5284,11 +5500,25 @@ snapshots: is-hex-prefixed: 1.0.0 strip-hex-prefix: 1.0.0 + eventemitter3@5.0.1: {} + evp_bytestokey@1.0.3: dependencies: md5.js: 1.3.5 safe-buffer: 5.2.1 + execa@8.0.1: + dependencies: + cross-spawn: 7.0.3 + get-stream: 8.0.1 + human-signals: 5.0.0 + is-stream: 3.0.0 + merge-stream: 2.0.0 + npm-run-path: 5.3.0 + onetime: 6.0.0 + signal-exit: 4.1.0 + strip-final-newline: 3.0.0 + extendable-error@0.1.7: {} external-editor@3.1.0: @@ -5329,6 +5559,10 @@ snapshots: dependencies: to-regex-range: 5.0.1 + fill-range@7.1.1: + dependencies: + to-regex-range: 5.0.1 + find-replace@3.0.0: dependencies: array-back: 3.1.0 @@ -5427,6 +5661,8 @@ snapshots: get-caller-file@2.0.5: {} + get-east-asian-width@1.2.0: {} + get-func-name@2.0.2: {} get-intrinsic@1.2.2: @@ -5452,6 +5688,8 @@ snapshots: get-stream@6.0.1: {} + get-stream@8.0.1: {} + get-symbol-description@1.0.0: dependencies: call-bind: 1.0.5 @@ -5720,6 +5958,10 @@ snapshots: human-id@1.0.2: {} + human-signals@5.0.0: {} + + husky@9.1.5: {} + iconv-lite@0.4.24: dependencies: safer-buffer: 2.1.2 @@ -5817,6 +6059,12 @@ snapshots: is-fullwidth-code-point@3.0.0: {} + is-fullwidth-code-point@4.0.0: {} + + is-fullwidth-code-point@5.0.0: + dependencies: + get-east-asian-width: 1.2.0 + is-glob@4.0.3: dependencies: is-extglob: 2.1.1 @@ -5860,6 +6108,8 @@ snapshots: call-bind: 1.0.7 optional: true + is-stream@3.0.0: {} + is-string@1.0.7: dependencies: has-tostringtag: 1.0.0 @@ -5981,8 +6231,34 @@ snapshots: prelude-ls: 1.2.1 type-check: 0.4.0 + lilconfig@3.1.2: {} + lines-and-columns@1.2.4: {} + lint-staged@15.2.9: + dependencies: + chalk: 5.3.0 + commander: 12.1.0 + debug: 4.3.6 + execa: 8.0.1 + lilconfig: 3.1.2 + listr2: 8.2.4 + micromatch: 4.0.8 + pidtree: 0.6.0 + string-argv: 0.3.2 + yaml: 2.5.0 + transitivePeerDependencies: + - supports-color + + listr2@8.2.4: + dependencies: + cli-truncate: 4.0.0 + colorette: 2.0.20 + eventemitter3: 5.0.1 + log-update: 6.1.0 + rfdc: 1.4.1 + wrap-ansi: 9.0.0 + load-yaml-file@0.2.0: dependencies: graceful-fs: 4.2.10 @@ -6024,6 +6300,14 @@ snapshots: chalk: 4.1.2 is-unicode-supported: 0.1.0 + log-update@6.1.0: + dependencies: + ansi-escapes: 7.0.0 + cli-cursor: 5.0.0 + slice-ansi: 7.1.0 + strip-ansi: 7.1.0 + wrap-ansi: 9.0.0 + loupe@2.3.7: dependencies: get-func-name: 2.0.2 @@ -6057,6 +6341,8 @@ snapshots: memorystream@0.3.1: {} + merge-stream@2.0.0: {} + merge2@1.4.1: {} micromatch@4.0.5: @@ -6064,6 +6350,15 @@ snapshots: braces: 3.0.2 picomatch: 2.3.1 + micromatch@4.0.8: + dependencies: + braces: 3.0.3 + picomatch: 2.3.1 + + mimic-fn@4.0.0: {} + + mimic-function@5.0.1: {} + mimic-response@1.0.1: {} mimic-response@3.1.0: {} @@ -6162,6 +6457,10 @@ snapshots: normalize-url@6.1.0: {} + npm-run-path@5.3.0: + dependencies: + path-key: 4.0.0 + number-to-bn@1.7.0: dependencies: bn.js: 4.11.6 @@ -6195,6 +6494,14 @@ snapshots: dependencies: wrappy: 1.0.2 + onetime@6.0.0: + dependencies: + mimic-fn: 4.0.0 + + onetime@7.0.0: + dependencies: + mimic-function: 5.0.1 + open@7.4.2: dependencies: is-docker: 2.2.1 @@ -6313,6 +6620,8 @@ snapshots: path-key@3.1.1: {} + path-key@4.0.0: {} + path-parse@1.0.7: {} path-starts-with@2.0.1: {} @@ -6331,6 +6640,8 @@ snapshots: picomatch@2.3.1: {} + pidtree@0.6.0: {} + pify@4.0.1: {} pkg-dir@4.2.0: @@ -6476,11 +6787,18 @@ snapshots: dependencies: lowercase-keys: 2.0.0 + restore-cursor@5.1.0: + dependencies: + onetime: 7.0.0 + signal-exit: 4.1.0 + retry@0.12.0: optional: true reusify@1.0.4: {} + rfdc@1.4.1: {} + rimraf@2.7.1: dependencies: glob: 7.2.3 @@ -6622,6 +6940,8 @@ snapshots: signal-exit@3.0.7: {} + signal-exit@4.1.0: {} + slash@2.0.0: {} slash@3.0.0: {} @@ -6632,6 +6952,16 @@ snapshots: astral-regex: 2.0.0 is-fullwidth-code-point: 3.0.0 + slice-ansi@5.0.0: + dependencies: + ansi-styles: 6.2.1 + is-fullwidth-code-point: 4.0.0 + + slice-ansi@7.1.0: + dependencies: + ansi-styles: 6.2.1 + is-fullwidth-code-point: 5.0.0 + snake-case@2.1.0: dependencies: no-case: 2.3.2 @@ -6754,6 +7084,8 @@ snapshots: statuses@2.0.1: {} + string-argv@0.3.2: {} + string-format@2.0.0: {} string-width@4.2.3: @@ -6762,6 +7094,12 @@ snapshots: is-fullwidth-code-point: 3.0.0 strip-ansi: 6.0.1 + string-width@7.2.0: + dependencies: + emoji-regex: 10.4.0 + get-east-asian-width: 1.2.0 + strip-ansi: 7.1.0 + string.prototype.trim@1.2.8: dependencies: call-bind: 1.0.5 @@ -6813,8 +7151,14 @@ snapshots: dependencies: ansi-regex: 5.0.1 + strip-ansi@7.1.0: + dependencies: + ansi-regex: 6.0.1 + strip-bom@3.0.0: {} + strip-final-newline@3.0.0: {} + strip-hex-prefix@1.0.0: dependencies: is-hex-prefixed: 1.0.0 @@ -7139,6 +7483,12 @@ snapshots: string-width: 4.2.3 strip-ansi: 6.0.1 + wrap-ansi@9.0.0: + dependencies: + ansi-styles: 6.2.1 + string-width: 7.2.0 + strip-ansi: 7.1.0 + wrappy@1.0.2: {} ws@7.4.6: {} @@ -7151,6 +7501,8 @@ snapshots: yaml@1.10.2: {} + yaml@2.5.0: {} + yargs-parser@20.2.4: {} yargs-unparser@2.0.0: diff --git a/contracts/src/v0.8/ccip/FeeQuoter.sol b/contracts/src/v0.8/ccip/FeeQuoter.sol index aea632fc4e..970485e90f 100644 --- a/contracts/src/v0.8/ccip/FeeQuoter.sol +++ b/contracts/src/v0.8/ccip/FeeQuoter.sol @@ -241,12 +241,9 @@ contract FeeQuoter is AuthorizedCallers, IFeeQuoter, ITypeAndVersion, IReceiver, } /// @inheritdoc IPriceRegistry - function getTokenPrices(address[] calldata tokens) - external - view - override - returns (Internal.TimestampedPackedUint224[] memory) - { + function getTokenPrices( + address[] calldata tokens + ) external view override returns (Internal.TimestampedPackedUint224[] memory) { uint256 length = tokens.length; Internal.TimestampedPackedUint224[] memory tokenPrices = new Internal.TimestampedPackedUint224[](length); for (uint256 i = 0; i < length; ++i) { @@ -256,22 +253,16 @@ contract FeeQuoter is AuthorizedCallers, IFeeQuoter, ITypeAndVersion, IReceiver, } /// @inheritdoc IFeeQuoter - function getTokenPriceFeedConfig(address token) - external - view - override - returns (IFeeQuoter.TokenPriceFeedConfig memory) - { + function getTokenPriceFeedConfig( + address token + ) external view override returns (IFeeQuoter.TokenPriceFeedConfig memory) { return s_usdPriceFeedsPerToken[token]; } /// @inheritdoc IPriceRegistry - function getDestinationChainGasPrice(uint64 destChainSelector) - external - view - override - returns (Internal.TimestampedPackedUint224 memory) - { + function getDestinationChainGasPrice( + uint64 destChainSelector + ) external view override returns (Internal.TimestampedPackedUint224 memory) { return s_usdPerUnitGasByDestChainSelector[destChainSelector]; } @@ -319,11 +310,9 @@ contract FeeQuoter is AuthorizedCallers, IFeeQuoter, ITypeAndVersion, IReceiver, /// @notice Gets the token price from a data feed address, rebased to the same units as s_usdPerToken /// @param priceFeedConfig token data feed configuration with valid data feed address (used to retrieve price & timestamp) /// @return tokenPrice data feed price answer rebased to s_usdPerToken units, with latest block timestamp - function _getTokenPriceFromDataFeed(IFeeQuoter.TokenPriceFeedConfig memory priceFeedConfig) - internal - view - returns (Internal.TimestampedPackedUint224 memory tokenPrice) - { + function _getTokenPriceFromDataFeed( + IFeeQuoter.TokenPriceFeedConfig memory priceFeedConfig + ) internal view returns (Internal.TimestampedPackedUint224 memory tokenPrice) { AggregatorV3Interface dataFeedContract = AggregatorV3Interface(priceFeedConfig.dataFeedAddress); ( /* uint80 roundID */ diff --git a/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol b/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol index 0f1e9b9702..1fbfd22d1c 100644 --- a/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol +++ b/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol @@ -196,11 +196,9 @@ contract MultiAggregateRateLimiter is IMessageInterceptor, AuthorizedCallers, IT /// @param remoteChainSelector chain selector to get rate limit tokens for. /// @return localTokens The local chain representation of the tokens that are rate limited. /// @return remoteTokens The remote representation of the tokens that are rate limited. - function getAllRateLimitTokens(uint64 remoteChainSelector) - external - view - returns (address[] memory localTokens, bytes[] memory remoteTokens) - { + function getAllRateLimitTokens( + uint64 remoteChainSelector + ) external view returns (address[] memory localTokens, bytes[] memory remoteTokens) { uint256 tokenCount = s_rateLimitedTokensLocalToRemote[remoteChainSelector].length(); localTokens = new address[](tokenCount); diff --git a/contracts/src/v0.8/ccip/RMN.sol b/contracts/src/v0.8/ccip/RMN.sol index deffb57fbe..3b9af7e0ce 100644 --- a/contracts/src/v0.8/ccip/RMN.sol +++ b/contracts/src/v0.8/ccip/RMN.sol @@ -732,11 +732,9 @@ contract RMN is IRMN, OwnerIsCreator, ITypeAndVersion { /// @return accumulatedWeight sum of weights of voters, will be zero if voting took place with an older config version /// @return blessed will be accurate regardless of when voting took place /// @dev This is a helper method for offchain code so efficiency is not really a concern. - function getBlessProgress(IRMN.TaggedRoot calldata taggedRoot) - external - view - returns (address[] memory blessVoteAddrs, uint16 accumulatedWeight, bool blessed) - { + function getBlessProgress( + IRMN.TaggedRoot calldata taggedRoot + ) external view returns (address[] memory blessVoteAddrs, uint16 accumulatedWeight, bool blessed) { bytes32 taggedRootHash = _taggedRootHash(taggedRoot); BlessVoteProgress memory progress = s_blessVoteProgressByTaggedRootHash[taggedRootHash]; blessed = progress.weightThresholdMet; @@ -762,7 +760,9 @@ contract RMN is IRMN, OwnerIsCreator, ITypeAndVersion { /// @return cursed might be true even if the owner has no active vote and accumulatedWeight < curseWeightThreshold, /// due to a retained curse from a prior config /// @dev This is a helper method for offchain code so efficiency is not really a concern. - function getCurseProgress(bytes16 subject) + function getCurseProgress( + bytes16 subject + ) external view returns (address[] memory curseVoteAddrs, bytes28[] memory cursesHashes, uint16 accumulatedWeight, bool cursed) diff --git a/contracts/src/v0.8/ccip/applications/CCIPClientExample.sol b/contracts/src/v0.8/ccip/applications/CCIPClientExample.sol index b105cf8b00..77816ceadb 100644 --- a/contracts/src/v0.8/ccip/applications/CCIPClientExample.sol +++ b/contracts/src/v0.8/ccip/applications/CCIPClientExample.sol @@ -57,13 +57,9 @@ contract CCIPClientExample is CCIPReceiver, OwnerIsCreator { delete s_chains[chainSelector]; } - function ccipReceive(Client.Any2EVMMessage calldata message) - external - virtual - override - onlyRouter - validChain(message.sourceChainSelector) - { + function ccipReceive( + Client.Any2EVMMessage calldata message + ) external virtual override onlyRouter validChain(message.sourceChainSelector) { // Extremely important to ensure only router calls this. // Tokens in message if any will be transferred to this contract // TODO: Validate sender/origin chain and process message and/or tokens. diff --git a/contracts/src/v0.8/ccip/applications/DefensiveExample.sol b/contracts/src/v0.8/ccip/applications/DefensiveExample.sol index 30b0972bb3..89435ccbf1 100644 --- a/contracts/src/v0.8/ccip/applications/DefensiveExample.sol +++ b/contracts/src/v0.8/ccip/applications/DefensiveExample.sol @@ -45,12 +45,9 @@ contract DefensiveExample is CCIPClientExample { /// never revert, all errors should be handled internally in this contract. /// @param message The message to process. /// @dev Extremely important to ensure only router calls this. - function ccipReceive(Client.Any2EVMMessage calldata message) - external - override - onlyRouter - validChain(message.sourceChainSelector) - { + function ccipReceive( + Client.Any2EVMMessage calldata message + ) external override onlyRouter validChain(message.sourceChainSelector) { try this.processMessage(message) {} catch (bytes memory err) { // Could set different error codes based on the caught error. Each could be @@ -70,11 +67,9 @@ contract DefensiveExample is CCIPClientExample { /// @dev This example just sends the tokens to the owner of this contracts. More /// interesting functions could be implemented. /// @dev It has to be external because of the try/catch. - function processMessage(Client.Any2EVMMessage calldata message) - external - onlySelf - validChain(message.sourceChainSelector) - { + function processMessage( + Client.Any2EVMMessage calldata message + ) external onlySelf validChain(message.sourceChainSelector) { // Simulate a revert if (s_simRevert) revert ErrorCase(); diff --git a/contracts/src/v0.8/ccip/applications/EtherSenderReceiver.sol b/contracts/src/v0.8/ccip/applications/EtherSenderReceiver.sol index ce8ed1ff7a..05d604d9c1 100644 --- a/contracts/src/v0.8/ccip/applications/EtherSenderReceiver.sol +++ b/contracts/src/v0.8/ccip/applications/EtherSenderReceiver.sol @@ -115,11 +115,9 @@ contract EtherSenderReceiver is CCIPReceiver, ITypeAndVersion { /// @notice Validate the message content. /// @dev Only allows a single token to be sent. Always overwritten to be address(i_weth) /// and receiver is always msg.sender. - function _validatedMessage(Client.EVM2AnyMessage calldata message) - internal - view - returns (Client.EVM2AnyMessage memory) - { + function _validatedMessage( + Client.EVM2AnyMessage calldata message + ) internal view returns (Client.EVM2AnyMessage memory) { Client.EVM2AnyMessage memory validatedMessage = message; if (validatedMessage.tokenAmounts.length != 1) { diff --git a/contracts/src/v0.8/ccip/applications/PingPongDemo.sol b/contracts/src/v0.8/ccip/applications/PingPongDemo.sol index 3697c7ff5a..b902c47618 100644 --- a/contracts/src/v0.8/ccip/applications/PingPongDemo.sol +++ b/contracts/src/v0.8/ccip/applications/PingPongDemo.sol @@ -62,7 +62,7 @@ contract PingPongDemo is CCIPReceiver, OwnerIsCreator, ITypeAndVersion { tokenAmounts: new Client.EVMTokenAmount[](0), extraArgs: Client._argsToBytes( Client.EVMExtraArgsV2({gasLimit: uint256(DEFAULT_GAS_LIMIT), allowOutOfOrderExecution: s_outOfOrderExecution}) - ), + ), feeToken: address(s_feeToken) }); IRouterClient(getRouter()).ccipSend(s_counterpartChainSelector, message); diff --git a/contracts/src/v0.8/ccip/capability/CCIPConfig.sol b/contracts/src/v0.8/ccip/capability/CCIPConfig.sol index 9e43f23f66..ae1e4cc597 100644 --- a/contracts/src/v0.8/ccip/capability/CCIPConfig.sol +++ b/contracts/src/v0.8/ccip/capability/CCIPConfig.sol @@ -346,7 +346,9 @@ contract CCIPConfig is ITypeAndVersion, ICapabilityConfiguration, OwnerIsCreator /// @param ocr3Configs The OCR3 configurations to group. /// @return commitConfigs The commit configurations. /// @return execConfigs The execution configurations. - function _groupByPluginType(CCIPConfigTypes.OCR3Config[] memory ocr3Configs) + function _groupByPluginType( + CCIPConfigTypes.OCR3Config[] memory ocr3Configs + ) internal pure returns (CCIPConfigTypes.OCR3Config[] memory commitConfigs, CCIPConfigTypes.OCR3Config[] memory execConfigs) diff --git a/contracts/src/v0.8/ccip/interfaces/IPool.sol b/contracts/src/v0.8/ccip/interfaces/IPool.sol index e01f5fe38e..a2b9281228 100644 --- a/contracts/src/v0.8/ccip/interfaces/IPool.sol +++ b/contracts/src/v0.8/ccip/interfaces/IPool.sol @@ -11,9 +11,9 @@ interface IPoolV1 is IERC165 { /// @notice Lock tokens into the pool or burn the tokens. /// @param lockOrBurnIn Encoded data fields for the processing of tokens on the source chain. /// @return lockOrBurnOut Encoded data fields for the processing of tokens on the destination chain. - function lockOrBurn(Pool.LockOrBurnInV1 calldata lockOrBurnIn) - external - returns (Pool.LockOrBurnOutV1 memory lockOrBurnOut); + function lockOrBurn( + Pool.LockOrBurnInV1 calldata lockOrBurnIn + ) external returns (Pool.LockOrBurnOutV1 memory lockOrBurnOut); /// @notice Releases or mints tokens to the receiver address. /// @param releaseOrMintIn All data required to release or mint tokens. @@ -21,9 +21,9 @@ interface IPoolV1 is IERC165 { /// in the local token's decimals. /// @dev The offramp asserts that the balanceOf of the receiver has been incremented by exactly the number /// of tokens that is returned in ReleaseOrMintOutV1.destinationAmount. If the amounts do not match, the tx reverts. - function releaseOrMint(Pool.ReleaseOrMintInV1 calldata releaseOrMintIn) - external - returns (Pool.ReleaseOrMintOutV1 memory); + function releaseOrMint( + Pool.ReleaseOrMintInV1 calldata releaseOrMintIn + ) external returns (Pool.ReleaseOrMintOutV1 memory); /// @notice Checks whether a remote chain is supported in the token pool. /// @param remoteChainSelector The selector of the remote chain. diff --git a/contracts/src/v0.8/ccip/interfaces/IPriceRegistry.sol b/contracts/src/v0.8/ccip/interfaces/IPriceRegistry.sol index a2c7bc1880..757ef09b0c 100644 --- a/contracts/src/v0.8/ccip/interfaces/IPriceRegistry.sol +++ b/contracts/src/v0.8/ccip/interfaces/IPriceRegistry.sol @@ -32,10 +32,9 @@ interface IPriceRegistry { /// PriceRegistry does not contain chain-specific logic to parse destination chain price components. /// @param destChainSelector The destination chain to get the price for. /// @return gasPrice The encoded gasPrice for the given destination chain ID. - function getDestinationChainGasPrice(uint64 destChainSelector) - external - view - returns (Internal.TimestampedPackedUint224 memory); + function getDestinationChainGasPrice( + uint64 destChainSelector + ) external view returns (Internal.TimestampedPackedUint224 memory); /// @notice Gets the fee token price and the gas price, both denominated in dollars. /// @param token The source token to get the price for. diff --git a/contracts/src/v0.8/ccip/onRamp/EVM2EVMOnRamp.sol b/contracts/src/v0.8/ccip/onRamp/EVM2EVMOnRamp.sol index 8ccd94b5e9..0c48b10e64 100644 --- a/contracts/src/v0.8/ccip/onRamp/EVM2EVMOnRamp.sol +++ b/contracts/src/v0.8/ccip/onRamp/EVM2EVMOnRamp.sol @@ -716,11 +716,9 @@ contract EVM2EVMOnRamp is IEVM2AnyOnRamp, ILinkAvailable, AggregateRateLimiter, } /// @notice Gets the transfer fee config for a given token. - function getTokenTransferFeeConfig(address token) - external - view - returns (TokenTransferFeeConfig memory tokenTransferFeeConfig) - { + function getTokenTransferFeeConfig( + address token + ) external view returns (TokenTransferFeeConfig memory tokenTransferFeeConfig) { return s_tokenTransferFeeConfig[token]; } diff --git a/contracts/src/v0.8/ccip/onRamp/OnRamp.sol b/contracts/src/v0.8/ccip/onRamp/OnRamp.sol index 947859eb01..3587854e90 100644 --- a/contracts/src/v0.8/ccip/onRamp/OnRamp.sol +++ b/contracts/src/v0.8/ccip/onRamp/OnRamp.sol @@ -374,11 +374,9 @@ contract OnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCreator { /// @return sequenceNumber The last used sequence number /// @return allowListEnabled boolean indicator to specify if allowList check is enabled /// @return router address of the router - function getDestChainConfig(uint64 destChainSelector) - public - view - returns (uint64 sequenceNumber, bool allowListEnabled, address router) - { + function getDestChainConfig( + uint64 destChainSelector + ) public view returns (uint64 sequenceNumber, bool allowListEnabled, address router) { DestChainConfig storage config = s_destChainConfigs[destChainSelector]; sequenceNumber = config.sequenceNumber; allowListEnabled = config.allowListEnabled; diff --git a/contracts/src/v0.8/ccip/pools/BurnMintTokenPoolAbstract.sol b/contracts/src/v0.8/ccip/pools/BurnMintTokenPoolAbstract.sol index a31d4fd219..99908c91d0 100644 --- a/contracts/src/v0.8/ccip/pools/BurnMintTokenPoolAbstract.sol +++ b/contracts/src/v0.8/ccip/pools/BurnMintTokenPoolAbstract.sol @@ -14,12 +14,9 @@ abstract contract BurnMintTokenPoolAbstract is TokenPool { /// @notice Burn the token in the pool /// @dev The _validateLockOrBurn check is an essential security check - function lockOrBurn(Pool.LockOrBurnInV1 calldata lockOrBurnIn) - external - virtual - override - returns (Pool.LockOrBurnOutV1 memory) - { + function lockOrBurn( + Pool.LockOrBurnInV1 calldata lockOrBurnIn + ) external virtual override returns (Pool.LockOrBurnOutV1 memory) { _validateLockOrBurn(lockOrBurnIn); _burn(lockOrBurnIn.amount); @@ -31,12 +28,9 @@ abstract contract BurnMintTokenPoolAbstract is TokenPool { /// @notice Mint tokens from the pool to the recipient /// @dev The _validateReleaseOrMint check is an essential security check - function releaseOrMint(Pool.ReleaseOrMintInV1 calldata releaseOrMintIn) - external - virtual - override - returns (Pool.ReleaseOrMintOutV1 memory) - { + function releaseOrMint( + Pool.ReleaseOrMintInV1 calldata releaseOrMintIn + ) external virtual override returns (Pool.ReleaseOrMintOutV1 memory) { _validateReleaseOrMint(releaseOrMintIn); // Mint to the receiver diff --git a/contracts/src/v0.8/ccip/pools/BurnMintTokenPoolAndProxy.sol b/contracts/src/v0.8/ccip/pools/BurnMintTokenPoolAndProxy.sol index 6ca8b7d6a0..6e3fb0f479 100644 --- a/contracts/src/v0.8/ccip/pools/BurnMintTokenPoolAndProxy.sol +++ b/contracts/src/v0.8/ccip/pools/BurnMintTokenPoolAndProxy.sol @@ -19,12 +19,9 @@ contract BurnMintTokenPoolAndProxy is ITypeAndVersion, LegacyPoolWrapper { /// @notice Burn the token in the pool /// @dev The _validateLockOrBurn check is an essential security check - function lockOrBurn(Pool.LockOrBurnInV1 calldata lockOrBurnIn) - external - virtual - override - returns (Pool.LockOrBurnOutV1 memory) - { + function lockOrBurn( + Pool.LockOrBurnInV1 calldata lockOrBurnIn + ) external virtual override returns (Pool.LockOrBurnOutV1 memory) { _validateLockOrBurn(lockOrBurnIn); if (!_hasLegacyPool()) { @@ -40,12 +37,9 @@ contract BurnMintTokenPoolAndProxy is ITypeAndVersion, LegacyPoolWrapper { /// @notice Mint tokens from the pool to the recipient /// @dev The _validateReleaseOrMint check is an essential security check - function releaseOrMint(Pool.ReleaseOrMintInV1 calldata releaseOrMintIn) - external - virtual - override - returns (Pool.ReleaseOrMintOutV1 memory) - { + function releaseOrMint( + Pool.ReleaseOrMintInV1 calldata releaseOrMintIn + ) external virtual override returns (Pool.ReleaseOrMintOutV1 memory) { _validateReleaseOrMint(releaseOrMintIn); if (!_hasLegacyPool()) { diff --git a/contracts/src/v0.8/ccip/pools/BurnWithFromMintTokenPoolAndProxy.sol b/contracts/src/v0.8/ccip/pools/BurnWithFromMintTokenPoolAndProxy.sol index 7890d85824..324fd484a7 100644 --- a/contracts/src/v0.8/ccip/pools/BurnWithFromMintTokenPoolAndProxy.sol +++ b/contracts/src/v0.8/ccip/pools/BurnWithFromMintTokenPoolAndProxy.sol @@ -27,12 +27,9 @@ contract BurnWithFromMintTokenPoolAndProxy is ITypeAndVersion, LegacyPoolWrapper /// @notice Burn the token in the pool /// @dev The _validateLockOrBurn check is an essential security check - function lockOrBurn(Pool.LockOrBurnInV1 calldata lockOrBurnIn) - external - virtual - override - returns (Pool.LockOrBurnOutV1 memory) - { + function lockOrBurn( + Pool.LockOrBurnInV1 calldata lockOrBurnIn + ) external virtual override returns (Pool.LockOrBurnOutV1 memory) { _validateLockOrBurn(lockOrBurnIn); if (!_hasLegacyPool()) { @@ -48,12 +45,9 @@ contract BurnWithFromMintTokenPoolAndProxy is ITypeAndVersion, LegacyPoolWrapper /// @notice Mint tokens from the pool to the recipient /// @dev The _validateReleaseOrMint check is an essential security check - function releaseOrMint(Pool.ReleaseOrMintInV1 calldata releaseOrMintIn) - external - virtual - override - returns (Pool.ReleaseOrMintOutV1 memory) - { + function releaseOrMint( + Pool.ReleaseOrMintInV1 calldata releaseOrMintIn + ) external virtual override returns (Pool.ReleaseOrMintOutV1 memory) { _validateReleaseOrMint(releaseOrMintIn); if (!_hasLegacyPool()) { diff --git a/contracts/src/v0.8/ccip/pools/LockReleaseTokenPool.sol b/contracts/src/v0.8/ccip/pools/LockReleaseTokenPool.sol index bc451f435a..3a4a4aef6d 100644 --- a/contracts/src/v0.8/ccip/pools/LockReleaseTokenPool.sol +++ b/contracts/src/v0.8/ccip/pools/LockReleaseTokenPool.sol @@ -44,12 +44,9 @@ contract LockReleaseTokenPool is TokenPool, ILiquidityContainer, ITypeAndVersion /// @notice Locks the token in the pool /// @dev The _validateLockOrBurn check is an essential security check - function lockOrBurn(Pool.LockOrBurnInV1 calldata lockOrBurnIn) - external - virtual - override - returns (Pool.LockOrBurnOutV1 memory) - { + function lockOrBurn( + Pool.LockOrBurnInV1 calldata lockOrBurnIn + ) external virtual override returns (Pool.LockOrBurnOutV1 memory) { _validateLockOrBurn(lockOrBurnIn); emit Locked(msg.sender, lockOrBurnIn.amount); @@ -59,12 +56,9 @@ contract LockReleaseTokenPool is TokenPool, ILiquidityContainer, ITypeAndVersion /// @notice Release tokens from the pool to the recipient /// @dev The _validateReleaseOrMint check is an essential security check - function releaseOrMint(Pool.ReleaseOrMintInV1 calldata releaseOrMintIn) - external - virtual - override - returns (Pool.ReleaseOrMintOutV1 memory) - { + function releaseOrMint( + Pool.ReleaseOrMintInV1 calldata releaseOrMintIn + ) external virtual override returns (Pool.ReleaseOrMintOutV1 memory) { _validateReleaseOrMint(releaseOrMintIn); // Release to the recipient diff --git a/contracts/src/v0.8/ccip/pools/LockReleaseTokenPoolAndProxy.sol b/contracts/src/v0.8/ccip/pools/LockReleaseTokenPoolAndProxy.sol index af79e821b8..e8c39127de 100644 --- a/contracts/src/v0.8/ccip/pools/LockReleaseTokenPoolAndProxy.sol +++ b/contracts/src/v0.8/ccip/pools/LockReleaseTokenPoolAndProxy.sol @@ -42,12 +42,9 @@ contract LockReleaseTokenPoolAndProxy is LegacyPoolWrapper, ILiquidityContainer, /// @notice Locks the token in the pool /// @dev The _validateLockOrBurn check is an essential security check - function lockOrBurn(Pool.LockOrBurnInV1 calldata lockOrBurnIn) - external - virtual - override - returns (Pool.LockOrBurnOutV1 memory) - { + function lockOrBurn( + Pool.LockOrBurnInV1 calldata lockOrBurnIn + ) external virtual override returns (Pool.LockOrBurnOutV1 memory) { _validateLockOrBurn(lockOrBurnIn); if (_hasLegacyPool()) { @@ -61,12 +58,9 @@ contract LockReleaseTokenPoolAndProxy is LegacyPoolWrapper, ILiquidityContainer, /// @notice Release tokens from the pool to the recipient /// @dev The _validateReleaseOrMint check is an essential security check - function releaseOrMint(Pool.ReleaseOrMintInV1 calldata releaseOrMintIn) - external - virtual - override - returns (Pool.ReleaseOrMintOutV1 memory) - { + function releaseOrMint( + Pool.ReleaseOrMintInV1 calldata releaseOrMintIn + ) external virtual override returns (Pool.ReleaseOrMintOutV1 memory) { _validateReleaseOrMint(releaseOrMintIn); if (!_hasLegacyPool()) { diff --git a/contracts/src/v0.8/ccip/pools/TokenPool.sol b/contracts/src/v0.8/ccip/pools/TokenPool.sol index 0b87b6dfcb..b12a12ca7a 100644 --- a/contracts/src/v0.8/ccip/pools/TokenPool.sol +++ b/contracts/src/v0.8/ccip/pools/TokenPool.sol @@ -325,21 +325,17 @@ abstract contract TokenPool is IPoolV1, OwnerIsCreator { /// @notice Gets the token bucket with its values for the block it was requested at. /// @return The token bucket. - function getCurrentOutboundRateLimiterState(uint64 remoteChainSelector) - external - view - returns (RateLimiter.TokenBucket memory) - { + function getCurrentOutboundRateLimiterState( + uint64 remoteChainSelector + ) external view returns (RateLimiter.TokenBucket memory) { return s_remoteChainConfigs[remoteChainSelector].outboundRateLimiterConfig._currentTokenBucketState(); } /// @notice Gets the token bucket with its values for the block it was requested at. /// @return The token bucket. - function getCurrentInboundRateLimiterState(uint64 remoteChainSelector) - external - view - returns (RateLimiter.TokenBucket memory) - { + function getCurrentInboundRateLimiterState( + uint64 remoteChainSelector + ) external view returns (RateLimiter.TokenBucket memory) { return s_remoteChainConfigs[remoteChainSelector].inboundRateLimiterConfig._currentTokenBucketState(); } diff --git a/contracts/src/v0.8/ccip/pools/USDC/HybridLockReleaseUSDCTokenPool.sol b/contracts/src/v0.8/ccip/pools/USDC/HybridLockReleaseUSDCTokenPool.sol index f38127825d..49cdeafcbc 100644 --- a/contracts/src/v0.8/ccip/pools/USDC/HybridLockReleaseUSDCTokenPool.sol +++ b/contracts/src/v0.8/ccip/pools/USDC/HybridLockReleaseUSDCTokenPool.sol @@ -53,12 +53,9 @@ contract HybridLockReleaseUSDCTokenPool is USDCTokenPool, USDCBridgeMigrator { /// @notice Locks the token in the pool /// @dev The _validateLockOrBurn check is an essential security check - function lockOrBurn(Pool.LockOrBurnInV1 calldata lockOrBurnIn) - public - virtual - override - returns (Pool.LockOrBurnOutV1 memory) - { + function lockOrBurn( + Pool.LockOrBurnInV1 calldata lockOrBurnIn + ) public virtual override returns (Pool.LockOrBurnOutV1 memory) { // // If the alternative mechanism (L/R) for chains which have it enabled if (!shouldUseLockRelease(lockOrBurnIn.remoteChainSelector)) { return super.lockOrBurn(lockOrBurnIn); @@ -75,12 +72,9 @@ contract HybridLockReleaseUSDCTokenPool is USDCTokenPool, USDCBridgeMigrator { /// @notice Release tokens from the pool to the recipient /// @dev The _validateReleaseOrMint check is an essential security check - function releaseOrMint(Pool.ReleaseOrMintInV1 calldata releaseOrMintIn) - public - virtual - override - returns (Pool.ReleaseOrMintOutV1 memory) - { + function releaseOrMint( + Pool.ReleaseOrMintInV1 calldata releaseOrMintIn + ) public virtual override returns (Pool.ReleaseOrMintOutV1 memory) { if (!shouldUseLockRelease(releaseOrMintIn.remoteChainSelector)) { return super.releaseOrMint(releaseOrMintIn); } @@ -88,11 +82,9 @@ contract HybridLockReleaseUSDCTokenPool is USDCTokenPool, USDCBridgeMigrator { } /// @notice Contains the alternative mechanism for incoming tokens, in this implementation is "Release" incoming tokens - function _lockReleaseIncomingMessage(Pool.ReleaseOrMintInV1 calldata releaseOrMintIn) - internal - virtual - returns (Pool.ReleaseOrMintOutV1 memory) - { + function _lockReleaseIncomingMessage( + Pool.ReleaseOrMintInV1 calldata releaseOrMintIn + ) internal virtual returns (Pool.ReleaseOrMintOutV1 memory) { _validateReleaseOrMint(releaseOrMintIn); // Decrease internal tracking of locked tokens to ensure accurate accounting for burnLockedUSDC() migration @@ -107,11 +99,9 @@ contract HybridLockReleaseUSDCTokenPool is USDCTokenPool, USDCBridgeMigrator { } /// @notice Contains the alternative mechanism, in this implementation is "Lock" on outgoing tokens - function _lockReleaseOutgoingMessage(Pool.LockOrBurnInV1 calldata lockOrBurnIn) - internal - virtual - returns (Pool.LockOrBurnOutV1 memory) - { + function _lockReleaseOutgoingMessage( + Pool.LockOrBurnInV1 calldata lockOrBurnIn + ) internal virtual returns (Pool.LockOrBurnOutV1 memory) { _validateLockOrBurn(lockOrBurnIn); // Increase internal accounting of locked tokens for burnLockedUSDC() migration diff --git a/contracts/src/v0.8/ccip/pools/USDC/USDCTokenPool.sol b/contracts/src/v0.8/ccip/pools/USDC/USDCTokenPool.sol index e58b6374db..56ab40c9b5 100644 --- a/contracts/src/v0.8/ccip/pools/USDC/USDCTokenPool.sol +++ b/contracts/src/v0.8/ccip/pools/USDC/USDCTokenPool.sol @@ -96,12 +96,9 @@ contract USDCTokenPool is TokenPool, ITypeAndVersion { /// @notice Burn the token in the pool /// @dev emits ITokenMessenger.DepositForBurn /// @dev Assumes caller has validated destinationReceiver - function lockOrBurn(Pool.LockOrBurnInV1 calldata lockOrBurnIn) - public - virtual - override - returns (Pool.LockOrBurnOutV1 memory) - { + function lockOrBurn( + Pool.LockOrBurnInV1 calldata lockOrBurnIn + ) public virtual override returns (Pool.LockOrBurnOutV1 memory) { _validateLockOrBurn(lockOrBurnIn); Domain memory domain = s_chainToDomain[lockOrBurnIn.remoteChainSelector]; @@ -138,12 +135,9 @@ contract USDCTokenPool is TokenPool, ITypeAndVersion { /// for that message, including its (nonce, sourceDomain). This way, the only /// non-reverting offchainTokenData that can be supplied is a valid attestation for the /// specific message that was sent on source. - function releaseOrMint(Pool.ReleaseOrMintInV1 calldata releaseOrMintIn) - public - virtual - override - returns (Pool.ReleaseOrMintOutV1 memory) - { + function releaseOrMint( + Pool.ReleaseOrMintInV1 calldata releaseOrMintIn + ) public virtual override returns (Pool.ReleaseOrMintOutV1 memory) { _validateReleaseOrMint(releaseOrMintIn); SourceTokenDataPayload memory sourceTokenDataPayload = abi.decode(releaseOrMintIn.sourcePoolData, (SourceTokenDataPayload)); diff --git a/contracts/src/v0.8/ccip/test/NonceManager.t.sol b/contracts/src/v0.8/ccip/test/NonceManager.t.sol index ebb51a9619..69afc7104e 100644 --- a/contracts/src/v0.8/ccip/test/NonceManager.t.sol +++ b/contracts/src/v0.8/ccip/test/NonceManager.t.sol @@ -623,11 +623,9 @@ contract NonceManager_OffRampUpgrade is OffRampSetup { assertEq(startNonce + 2, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender)); } - function _generateSingleLaneRampReportFromMessages(Internal.EVM2EVMMessage[] memory messages) - internal - pure - returns (Internal.ExecutionReport memory) - { + function _generateSingleLaneRampReportFromMessages( + Internal.EVM2EVMMessage[] memory messages + ) internal pure returns (Internal.ExecutionReport memory) { bytes[][] memory offchainTokenData = new bytes[][](messages.length); for (uint256 i = 0; i < messages.length; ++i) { diff --git a/contracts/src/v0.8/ccip/test/attacks/onRamp/ReentrantMaliciousTokenPool.sol b/contracts/src/v0.8/ccip/test/attacks/onRamp/ReentrantMaliciousTokenPool.sol index 17c13a8148..5b6b367984 100644 --- a/contracts/src/v0.8/ccip/test/attacks/onRamp/ReentrantMaliciousTokenPool.sol +++ b/contracts/src/v0.8/ccip/test/attacks/onRamp/ReentrantMaliciousTokenPool.sol @@ -22,11 +22,9 @@ contract ReentrantMaliciousTokenPool is TokenPool { } /// @dev Calls into Facade to reenter Router exactly 1 time - function lockOrBurn(Pool.LockOrBurnInV1 calldata lockOrBurnIn) - external - override - returns (Pool.LockOrBurnOutV1 memory) - { + function lockOrBurn( + Pool.LockOrBurnInV1 calldata lockOrBurnIn + ) external override returns (Pool.LockOrBurnOutV1 memory) { if (s_attacked) { return Pool.LockOrBurnOutV1({destTokenAddress: getRemoteToken(lockOrBurnIn.remoteChainSelector), destPoolData: ""}); @@ -39,12 +37,9 @@ contract ReentrantMaliciousTokenPool is TokenPool { return Pool.LockOrBurnOutV1({destTokenAddress: getRemoteToken(lockOrBurnIn.remoteChainSelector), destPoolData: ""}); } - function releaseOrMint(Pool.ReleaseOrMintInV1 calldata releaseOrMintIn) - external - pure - override - returns (Pool.ReleaseOrMintOutV1 memory) - { + function releaseOrMint( + Pool.ReleaseOrMintInV1 calldata releaseOrMintIn + ) external pure override returns (Pool.ReleaseOrMintOutV1 memory) { return Pool.ReleaseOrMintOutV1({destinationAmount: releaseOrMintIn.amount}); } } diff --git a/contracts/src/v0.8/ccip/test/capability/CCIPConfig.t.sol b/contracts/src/v0.8/ccip/test/capability/CCIPConfig.t.sol index 2ac30b355a..ca7f2114a6 100644 --- a/contracts/src/v0.8/ccip/test/capability/CCIPConfig.t.sol +++ b/contracts/src/v0.8/ccip/test/capability/CCIPConfig.t.sol @@ -63,10 +63,9 @@ contract CCIPConfigSetup is Test { if (i < right) _sort(arr, i, right); } - function _addChainConfig(uint256 numNodes) - internal - returns (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) - { + function _addChainConfig( + uint256 numNodes + ) internal returns (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) { p2pIds = _makeBytes32Array(numNodes, 0); _sort(p2pIds, 0, int256(numNodes - 1)); signers = _makeBytesArray(numNodes, 10); diff --git a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.t.sol b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.t.sol index cdbf1cef7a..f6dc8c25bf 100644 --- a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.t.sol +++ b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.t.sol @@ -725,9 +725,9 @@ contract FeeQuoter_updateTokenPriceFeeds is FeeQuoterSetup { } contract FeeQuoter_applyDestChainConfigUpdates is FeeQuoterSetup { - function test_Fuzz_applyDestChainConfigUpdates_Success(FeeQuoter.DestChainConfigArgs memory destChainConfigArgs) - public - { + function test_Fuzz_applyDestChainConfigUpdates_Success( + FeeQuoter.DestChainConfigArgs memory destChainConfigArgs + ) public { vm.assume(destChainConfigArgs.destChainSelector != 0); vm.assume(destChainConfigArgs.destChainConfig.maxPerMsgGasLimit != 0); destChainConfigArgs.destChainConfig.defaultTxGasLimit = uint32( diff --git a/contracts/src/v0.8/ccip/test/helpers/BurnMintMultiTokenPool.sol b/contracts/src/v0.8/ccip/test/helpers/BurnMintMultiTokenPool.sol index ec6f1d2047..bb1d4c9af3 100644 --- a/contracts/src/v0.8/ccip/test/helpers/BurnMintMultiTokenPool.sol +++ b/contracts/src/v0.8/ccip/test/helpers/BurnMintMultiTokenPool.sol @@ -18,12 +18,9 @@ contract BurnMintMultiTokenPool is MultiTokenPool { /// @notice Burn the token in the pool /// @dev The _validateLockOrBurn check is an essential security check - function lockOrBurn(Pool.LockOrBurnInV1 calldata lockOrBurnIn) - external - virtual - override - returns (Pool.LockOrBurnOutV1 memory) - { + function lockOrBurn( + Pool.LockOrBurnInV1 calldata lockOrBurnIn + ) external virtual override returns (Pool.LockOrBurnOutV1 memory) { _validateLockOrBurn(lockOrBurnIn); IBurnMintERC20(lockOrBurnIn.localToken).burn(lockOrBurnIn.amount); @@ -38,12 +35,9 @@ contract BurnMintMultiTokenPool is MultiTokenPool { /// @notice Mint tokens from the pool to the recipient /// @dev The _validateReleaseOrMint check is an essential security check - function releaseOrMint(Pool.ReleaseOrMintInV1 calldata releaseOrMintIn) - external - virtual - override - returns (Pool.ReleaseOrMintOutV1 memory) - { + function releaseOrMint( + Pool.ReleaseOrMintInV1 calldata releaseOrMintIn + ) external virtual override returns (Pool.ReleaseOrMintOutV1 memory) { _validateReleaseOrMint(releaseOrMintIn); // Mint to the receiver diff --git a/contracts/src/v0.8/ccip/test/helpers/CCIPConfigHelper.sol b/contracts/src/v0.8/ccip/test/helpers/CCIPConfigHelper.sol index 74f03890d3..efade5190b 100644 --- a/contracts/src/v0.8/ccip/test/helpers/CCIPConfigHelper.sol +++ b/contracts/src/v0.8/ccip/test/helpers/CCIPConfigHelper.sol @@ -36,7 +36,9 @@ contract CCIPConfigHelper is CCIPConfig { return _computeNewConfigWithMeta(donId, currentConfig, newConfig, currentState, newState); } - function groupByPluginType(CCIPConfigTypes.OCR3Config[] memory ocr3Configs) + function groupByPluginType( + CCIPConfigTypes.OCR3Config[] memory ocr3Configs + ) public pure returns (CCIPConfigTypes.OCR3Config[] memory commitConfigs, CCIPConfigTypes.OCR3Config[] memory execConfigs) diff --git a/contracts/src/v0.8/ccip/test/helpers/MaybeRevertingBurnMintTokenPool.sol b/contracts/src/v0.8/ccip/test/helpers/MaybeRevertingBurnMintTokenPool.sol index b203315bc6..73e764ae03 100644 --- a/contracts/src/v0.8/ccip/test/helpers/MaybeRevertingBurnMintTokenPool.sol +++ b/contracts/src/v0.8/ccip/test/helpers/MaybeRevertingBurnMintTokenPool.sol @@ -30,12 +30,9 @@ contract MaybeRevertingBurnMintTokenPool is BurnMintTokenPool { s_releaseOrMintMultiplier = multiplier; } - function lockOrBurn(Pool.LockOrBurnInV1 calldata lockOrBurnIn) - external - virtual - override - returns (Pool.LockOrBurnOutV1 memory) - { + function lockOrBurn( + Pool.LockOrBurnInV1 calldata lockOrBurnIn + ) external virtual override returns (Pool.LockOrBurnOutV1 memory) { _validateLockOrBurn(lockOrBurnIn); bytes memory revertReason = s_revertReason; @@ -54,12 +51,9 @@ contract MaybeRevertingBurnMintTokenPool is BurnMintTokenPool { } /// @notice Reverts depending on the value of `s_revertReason` - function releaseOrMint(Pool.ReleaseOrMintInV1 calldata releaseOrMintIn) - external - virtual - override - returns (Pool.ReleaseOrMintOutV1 memory) - { + function releaseOrMint( + Pool.ReleaseOrMintInV1 calldata releaseOrMintIn + ) external virtual override returns (Pool.ReleaseOrMintOutV1 memory) { _validateReleaseOrMint(releaseOrMintIn); bytes memory revertReason = s_revertReason; diff --git a/contracts/src/v0.8/ccip/test/helpers/MessageHasher.sol b/contracts/src/v0.8/ccip/test/helpers/MessageHasher.sol index 19f35df796..d56cf8949a 100644 --- a/contracts/src/v0.8/ccip/test/helpers/MessageHasher.sol +++ b/contracts/src/v0.8/ccip/test/helpers/MessageHasher.sol @@ -12,11 +12,9 @@ contract MessageHasher { return Internal._hash(message, onRamp); } - function encodeTokenAmountsHashPreimage(Internal.RampTokenAmount[] memory rampTokenAmounts) - public - pure - returns (bytes memory) - { + function encodeTokenAmountsHashPreimage( + Internal.RampTokenAmount[] memory rampTokenAmounts + ) public pure returns (bytes memory) { return abi.encode(rampTokenAmounts); } diff --git a/contracts/src/v0.8/ccip/test/helpers/TokenPoolHelper.sol b/contracts/src/v0.8/ccip/test/helpers/TokenPoolHelper.sol index c57bfa3311..4965d1ed2f 100644 --- a/contracts/src/v0.8/ccip/test/helpers/TokenPoolHelper.sol +++ b/contracts/src/v0.8/ccip/test/helpers/TokenPoolHelper.sol @@ -14,21 +14,15 @@ contract TokenPoolHelper is TokenPool { address router ) TokenPool(token, allowlist, rmnProxy, router) {} - function lockOrBurn(Pool.LockOrBurnInV1 calldata lockOrBurnIn) - external - view - override - returns (Pool.LockOrBurnOutV1 memory) - { + function lockOrBurn( + Pool.LockOrBurnInV1 calldata lockOrBurnIn + ) external view override returns (Pool.LockOrBurnOutV1 memory) { return Pool.LockOrBurnOutV1({destTokenAddress: getRemoteToken(lockOrBurnIn.remoteChainSelector), destPoolData: ""}); } - function releaseOrMint(Pool.ReleaseOrMintInV1 calldata releaseOrMintIn) - external - pure - override - returns (Pool.ReleaseOrMintOutV1 memory) - { + function releaseOrMint( + Pool.ReleaseOrMintInV1 calldata releaseOrMintIn + ) external pure override returns (Pool.ReleaseOrMintOutV1 memory) { return Pool.ReleaseOrMintOutV1({destinationAmount: releaseOrMintIn.amount}); } diff --git a/contracts/src/v0.8/ccip/test/helpers/receivers/ReentrancyAbuser.sol b/contracts/src/v0.8/ccip/test/helpers/receivers/ReentrancyAbuser.sol index e53df4de1b..b69bbcaa43 100644 --- a/contracts/src/v0.8/ccip/test/helpers/receivers/ReentrancyAbuser.sol +++ b/contracts/src/v0.8/ccip/test/helpers/receivers/ReentrancyAbuser.sol @@ -36,11 +36,9 @@ contract ReentrancyAbuser is CCIPReceiver { } } - function _getGasLimitsFromMessages(Internal.EVM2EVMMessage[] memory messages) - internal - pure - returns (EVM2EVMOffRamp.GasLimitOverride[] memory) - { + function _getGasLimitsFromMessages( + Internal.EVM2EVMMessage[] memory messages + ) internal pure returns (EVM2EVMOffRamp.GasLimitOverride[] memory) { EVM2EVMOffRamp.GasLimitOverride[] memory gasLimitOverrides = new EVM2EVMOffRamp.GasLimitOverride[](messages.length); for (uint256 i = 0; i < messages.length; ++i) { gasLimitOverrides[i].receiverExecutionGasLimit = messages[i].gasLimit; diff --git a/contracts/src/v0.8/ccip/test/legacy/BurnMintTokenPool1_4.sol b/contracts/src/v0.8/ccip/test/legacy/BurnMintTokenPool1_4.sol index 9e80438239..168afee4f0 100644 --- a/contracts/src/v0.8/ccip/test/legacy/BurnMintTokenPool1_4.sol +++ b/contracts/src/v0.8/ccip/test/legacy/BurnMintTokenPool1_4.sol @@ -211,21 +211,17 @@ abstract contract TokenPool1_4 is IPoolPriorTo1_5, OwnerIsCreator, IERC165 { /// @notice Gets the token bucket with its values for the block it was requested at. /// @return The token bucket. - function getCurrentOutboundRateLimiterState(uint64 remoteChainSelector) - external - view - returns (RateLimiter.TokenBucket memory) - { + function getCurrentOutboundRateLimiterState( + uint64 remoteChainSelector + ) external view returns (RateLimiter.TokenBucket memory) { return s_outboundRateLimits[remoteChainSelector]._currentTokenBucketState(); } /// @notice Gets the token bucket with its values for the block it was requested at. /// @return The token bucket. - function getCurrentInboundRateLimiterState(uint64 remoteChainSelector) - external - view - returns (RateLimiter.TokenBucket memory) - { + function getCurrentInboundRateLimiterState( + uint64 remoteChainSelector + ) external view returns (RateLimiter.TokenBucket memory) { return s_inboundRateLimits[remoteChainSelector]._currentTokenBucketState(); } diff --git a/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMOffRampSetup.t.sol b/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMOffRampSetup.t.sol index a5cb4f3d2b..8399637718 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMOffRampSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/EVM2EVMOffRampSetup.t.sol @@ -91,11 +91,9 @@ contract EVM2EVMOffRampSetup is TokenSetup, FeeQuoterSetup, OCR2BaseSetup { }); } - function _convertToGeneralMessage(Internal.EVM2EVMMessage memory original) - internal - view - returns (Client.Any2EVMMessage memory message) - { + function _convertToGeneralMessage( + Internal.EVM2EVMMessage memory original + ) internal view returns (Client.Any2EVMMessage memory message) { uint256 numberOfTokens = original.tokenAmounts.length; Client.EVMTokenAmount[] memory destTokenAmounts = new Client.EVMTokenAmount[](numberOfTokens); @@ -118,11 +116,9 @@ contract EVM2EVMOffRampSetup is TokenSetup, FeeQuoterSetup, OCR2BaseSetup { }); } - function _generateAny2EVMMessageNoTokens(uint64 sequenceNumber) - internal - view - returns (Internal.EVM2EVMMessage memory) - { + function _generateAny2EVMMessageNoTokens( + uint64 sequenceNumber + ) internal view returns (Internal.EVM2EVMMessage memory) { return _generateAny2EVMMessage(sequenceNumber, new Client.EVMTokenAmount[](0), false); } @@ -206,11 +202,9 @@ contract EVM2EVMOffRampSetup is TokenSetup, FeeQuoterSetup, OCR2BaseSetup { return messages; } - function _generateReportFromMessages(Internal.EVM2EVMMessage[] memory messages) - internal - pure - returns (Internal.ExecutionReport memory) - { + function _generateReportFromMessages( + Internal.EVM2EVMMessage[] memory messages + ) internal pure returns (Internal.ExecutionReport memory) { bytes[][] memory offchainTokenData = new bytes[][](messages.length); for (uint256 i = 0; i < messages.length; ++i) { @@ -225,11 +219,9 @@ contract EVM2EVMOffRampSetup is TokenSetup, FeeQuoterSetup, OCR2BaseSetup { }); } - function _getGasLimitsFromMessages(Internal.EVM2EVMMessage[] memory messages) - internal - pure - returns (EVM2EVMOffRamp.GasLimitOverride[] memory) - { + function _getGasLimitsFromMessages( + Internal.EVM2EVMMessage[] memory messages + ) internal pure returns (EVM2EVMOffRamp.GasLimitOverride[] memory) { EVM2EVMOffRamp.GasLimitOverride[] memory gasLimitOverrides = new EVM2EVMOffRamp.GasLimitOverride[](messages.length); for (uint256 i = 0; i < messages.length; ++i) { gasLimitOverrides[i].receiverExecutionGasLimit = messages[i].gasLimit; @@ -251,11 +243,9 @@ contract EVM2EVMOffRampSetup is TokenSetup, FeeQuoterSetup, OCR2BaseSetup { assertEq(a.maxDataBytes, b.maxDataBytes); } - function _getDefaultSourceTokenData(Client.EVMTokenAmount[] memory srcTokenAmounts) - internal - view - returns (bytes[] memory) - { + function _getDefaultSourceTokenData( + Client.EVMTokenAmount[] memory srcTokenAmounts + ) internal view returns (bytes[] memory) { bytes[] memory sourceTokenData = new bytes[](srcTokenAmounts.length); for (uint256 i = 0; i < srcTokenAmounts.length; ++i) { sourceTokenData[i] = abi.encode( diff --git a/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol index 9167f3f075..ec8ac65008 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol @@ -2841,9 +2841,9 @@ contract OffRamp_applySourceChainConfigUpdates is OffRampSetup { } } - function test_Fuzz_applySourceChainConfigUpdate_Success(OffRamp.SourceChainConfigArgs memory sourceChainConfigArgs) - public - { + function test_Fuzz_applySourceChainConfigUpdate_Success( + OffRamp.SourceChainConfigArgs memory sourceChainConfigArgs + ) public { // Skip invalid inputs vm.assume(sourceChainConfigArgs.sourceChainSelector != 0); vm.assume(sourceChainConfigArgs.onRamp.length != 0); diff --git a/contracts/src/v0.8/ccip/test/offRamp/OffRampSetup.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRampSetup.t.sol index 403655f10a..ae9fc044ac 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/OffRampSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRampSetup.t.sol @@ -234,11 +234,9 @@ contract OffRampSetup is FeeQuoterSetup, MultiOCR3BaseSetup { }); } - function _convertToGeneralMessage(Internal.Any2EVMRampMessage memory original) - internal - view - returns (Client.Any2EVMMessage memory message) - { + function _convertToGeneralMessage( + Internal.Any2EVMRampMessage memory original + ) internal view returns (Client.Any2EVMMessage memory message) { uint256 numberOfTokens = original.tokenAmounts.length; Client.EVMTokenAmount[] memory destTokenAmounts = new Client.EVMTokenAmount[](numberOfTokens); @@ -374,11 +372,9 @@ contract OffRampSetup is FeeQuoterSetup, MultiOCR3BaseSetup { return reports; } - function _getGasLimitsFromMessages(Internal.Any2EVMRampMessage[] memory messages) - internal - pure - returns (uint256[] memory) - { + function _getGasLimitsFromMessages( + Internal.Any2EVMRampMessage[] memory messages + ) internal pure returns (uint256[] memory) { uint256[] memory gasLimits = new uint256[](messages.length); for (uint256 i = 0; i < messages.length; ++i) { gasLimits[i] = messages[i].gasLimit; @@ -405,11 +401,9 @@ contract OffRampSetup is FeeQuoterSetup, MultiOCR3BaseSetup { assertEq(address(config1.router), address(config2.router)); } - function _getDefaultSourceTokenData(Client.EVMTokenAmount[] memory srcTokenAmounts) - internal - view - returns (Internal.RampTokenAmount[] memory) - { + function _getDefaultSourceTokenData( + Client.EVMTokenAmount[] memory srcTokenAmounts + ) internal view returns (Internal.RampTokenAmount[] memory) { Internal.RampTokenAmount[] memory sourceTokenData = new Internal.RampTokenAmount[](srcTokenAmounts.length); for (uint256 i = 0; i < srcTokenAmounts.length; ++i) { sourceTokenData[i] = Internal.RampTokenAmount({ diff --git a/contracts/src/v0.8/ccip/test/pools/USDCTokenPool.t.sol b/contracts/src/v0.8/ccip/test/pools/USDCTokenPool.t.sol index e60d5542f4..b71094a310 100644 --- a/contracts/src/v0.8/ccip/test/pools/USDCTokenPool.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/USDCTokenPool.t.sol @@ -352,7 +352,7 @@ contract USDCTokenPool_releaseOrMint is USDCTokenPoolSetup { bytes32(uint256(uint160(recipient))), amount, bytes32(uint256(uint160(OWNER))) - ) + ) }); bytes memory message = _generateUSDCMessage(usdcMessage); @@ -363,7 +363,7 @@ contract USDCTokenPool_releaseOrMint is USDCTokenPoolSetup { destTokenAddress: abi.encode(address(s_usdcTokenPool)), extraData: abi.encode( USDCTokenPool.SourceTokenDataPayload({nonce: usdcMessage.nonce, sourceDomain: SOURCE_DOMAIN_IDENTIFIER}) - ), + ), destGasAmount: USDC_DEST_TOKEN_GAS }); @@ -460,7 +460,7 @@ contract USDCTokenPool_releaseOrMint is USDCTokenPoolSetup { bytes32(uint256(uint160(OWNER))), amount, bytes32(uint256(uint160(OWNER))) - ) + ) }); Internal.SourceTokenData memory sourceTokenData = Internal.SourceTokenData({ @@ -468,7 +468,7 @@ contract USDCTokenPool_releaseOrMint is USDCTokenPoolSetup { destTokenAddress: abi.encode(address(s_usdcTokenPool)), extraData: abi.encode( USDCTokenPool.SourceTokenDataPayload({nonce: usdcMessage.nonce, sourceDomain: SOURCE_DOMAIN_IDENTIFIER}) - ), + ), destGasAmount: USDC_DEST_TOKEN_GAS }); diff --git a/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol b/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol index 9fcf08f722..a7d73cc8b3 100644 --- a/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol +++ b/contracts/src/v0.8/ccip/test/rateLimiter/MultiAggregateRateLimiter.t.sol @@ -101,11 +101,9 @@ contract MultiAggregateRateLimiterSetup is BaseTest, FeeQuoterSetup { }); } - function _generateAny2EVMMessageNoTokens(uint64 sourceChainSelector) - internal - pure - returns (Client.Any2EVMMessage memory) - { + function _generateAny2EVMMessageNoTokens( + uint64 sourceChainSelector + ) internal pure returns (Client.Any2EVMMessage memory) { return _generateAny2EVMMessage(sourceChainSelector, new Client.EVMTokenAmount[](0)); } } @@ -1180,11 +1178,9 @@ contract MultiAggregateRateLimiter_onOutboundMessage is MultiAggregateRateLimite s_rateLimiter.onOutboundMessage(CHAIN_SELECTOR_1, _generateEVM2AnyMessageNoTokens()); } - function _generateEVM2AnyMessage(Client.EVMTokenAmount[] memory tokenAmounts) - public - view - returns (Client.EVM2AnyMessage memory) - { + function _generateEVM2AnyMessage( + Client.EVMTokenAmount[] memory tokenAmounts + ) public view returns (Client.EVM2AnyMessage memory) { return Client.EVM2AnyMessage({ receiver: abi.encode(OWNER), data: "", From 54ef6639f7f591f9d03ea37b6cf7d45173d2fe2f Mon Sep 17 00:00:00 2001 From: Rens Rooimans Date: Fri, 30 Aug 2024 09:43:03 +0200 Subject: [PATCH 056/115] Put back previous cov --- .github/workflows/solidity-foundry.yml | 68 +++++++++++++++- .github/workflows/solidity-hardhat.yml | 106 ++++++++++++------------- tools/ci/ccip_lcov_prune | 30 +++++++ 3 files changed, 150 insertions(+), 54 deletions(-) create mode 100755 tools/ci/ccip_lcov_prune diff --git a/.github/workflows/solidity-foundry.yml b/.github/workflows/solidity-foundry.yml index 0c0c3be434..30fc562a05 100644 --- a/.github/workflows/solidity-foundry.yml +++ b/.github/workflows/solidity-foundry.yml @@ -268,7 +268,7 @@ jobs: analyze: needs: [ changes, define-matrix ] name: Run static analysis - if: needs.changes.outputs.not_test_sol_modified == 'true' + if: needs.changes.outputs.not_test_sol_modified == 'true' && false runs-on: ubuntu-22.04 steps: - name: Checkout the repo @@ -583,3 +583,69 @@ jobs: hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} this-job-name: Forge fmt ${{ matrix.product.name }} continue-on-error: true + + coverage: + needs: [define-matrix, changes] + name: Coverage + runs-on: ubuntu-latest + env: + FOUNDRY_PROFILE: ccip + + steps: + - name: Collect Metrics + if: ${{ needs.changes.outputs.non_src_changes == 'true' || needs.changes.outputs.sol_modified_added == 'true' }} + id: collect-gha-metrics + uses: smartcontractkit/push-gha-metrics-action@dea9b546553cb4ca936607c2267a09c004e4ab3f # v3.0.0 + with: + id: ccip-solidity-foundry-coverage + org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} + basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} + hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} + this-job-name: Coverage + continue-on-error: true + + - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + with: + submodules: recursive + + # Only needed because we use the NPM versions of packages + # and not native Foundry. This is to make sure the dependencies + # stay in sync. + - name: Setup NodeJS + uses: ./.github/actions/setup-nodejs + + - name: Install Foundry + if: ${{ needs.changes.outputs.non_src_changes == 'true' || needs.changes.outputs.sol_modified_added == 'true' }} + uses: foundry-rs/foundry-toolchain@8f1998e9878d786675189ef566a2e4bf24869773 # v1.2.0 + with: + version: ${{ needs.define-matrix.outputs.foundry-version }} + + - name: Run Forge build + if: ${{ needs.changes.outputs.non_src_changes == 'true' || needs.changes.outputs.sol_modified_added == 'true' }} + working-directory: contracts + run: | + forge --version + forge build + id: build + + - name: Run coverage + if: ${{ needs.changes.outputs.non_src_changes == 'true' || needs.changes.outputs.sol_modified_added == 'true' }} + working-directory: contracts + run: forge coverage --report lcov + + - name: Prune report + if: ${{ needs.changes.outputs.non_src_changes == 'true' || needs.changes.outputs.sol_modified_added == 'true' }} + run: | + sudo apt-get install lcov + ./tools/ci/ccip_lcov_prune ./contracts/lcov.info ./lcov.info.pruned + + - name: Report code coverage + if: ${{ needs.changes.outputs.non_src_changes == 'true' || needs.changes.outputs.sol_modified_added == 'true' }} + uses: zgosalvez/github-actions-report-lcov@a546f89a65a0cdcd82a92ae8d65e74d450ff3fbc # v4.1.4 + with: + update-comment: true + coverage-files: lcov.info.pruned + minimum-coverage: 97.6 + artifact-name: code-coverage-report + working-directory: ./contracts + github-token: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/solidity-hardhat.yml b/.github/workflows/solidity-hardhat.yml index 705fad3be6..4fb43ee962 100644 --- a/.github/workflows/solidity-hardhat.yml +++ b/.github/workflows/solidity-hardhat.yml @@ -32,56 +32,56 @@ jobs: - 'contracts/hardhat.config.ts' - '.github/workflows/solidity-hardhat.yml' - hardhat-test: - needs: [changes] - if: needs.changes.outputs.changes == 'true' - name: Solidity ${{ fromJSON('["(skipped)", ""]')[needs.changes.outputs.changes == 'true'] }} - runs-on: ubuntu-latest - steps: - - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - - name: Setup NodeJS - uses: ./.github/actions/setup-nodejs - - name: Setup Hardhat - uses: ./.github/actions/setup-hardhat - with: - namespace: coverage - - name: Run tests - working-directory: contracts - run: pnpm test - - name: Collect Metrics - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 - with: - id: hardhat-test - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - continue-on-error: true - - solidity: - needs: [changes, hardhat-test] - name: Solidity - runs-on: ubuntu-latest - if: always() - steps: - - run: echo 'Solidity tests finished!' - - name: Check test results - run: | - if [[ "${{ needs.changes.result }}" = "failure" || "${{ needs.solidity-splits.result }}" = "failure" ]]; then - echo "One or more changes / solidity-splits jobs failed" - exit 1 - else - echo "All test jobs passed successfully" - fi - - name: Collect Metrics - if: always() - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 - with: - id: solidity-tests - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: Solidity - continue-on-error: true +# hardhat-test: +# needs: [changes] +# if: needs.changes.outputs.changes == 'true' +# name: Solidity ${{ fromJSON('["(skipped)", ""]')[needs.changes.outputs.changes == 'true'] }} +# runs-on: ubuntu-latest +# steps: +# - name: Checkout the repo +# uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 +# - name: Setup NodeJS +# uses: ./.github/actions/setup-nodejs +# - name: Setup Hardhat +# uses: ./.github/actions/setup-hardhat +# with: +# namespace: coverage +# - name: Run tests +# working-directory: contracts +# run: pnpm test +# - name: Collect Metrics +# id: collect-gha-metrics +# uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 +# with: +# id: hardhat-test +# org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} +# basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} +# hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} +# continue-on-error: true +# +# solidity: +# needs: [changes, hardhat-test] +# name: Solidity +# runs-on: ubuntu-latest +# if: always() +# steps: +# - run: echo 'Solidity tests finished!' +# - name: Check test results +# run: | +# if [[ "${{ needs.changes.result }}" = "failure" || "${{ needs.solidity-splits.result }}" = "failure" ]]; then +# echo "One or more changes / solidity-splits jobs failed" +# exit 1 +# else +# echo "All test jobs passed successfully" +# fi +# - name: Collect Metrics +# if: always() +# id: collect-gha-metrics +# uses: smartcontractkit/push-gha-metrics-action@d9da21a2747016b3e13de58c7d4115a3d5c97935 # v3.0.1 +# with: +# id: solidity-tests +# org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} +# basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} +# hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} +# this-job-name: Solidity +# continue-on-error: true diff --git a/tools/ci/ccip_lcov_prune b/tools/ci/ccip_lcov_prune new file mode 100755 index 0000000000..494b2d526c --- /dev/null +++ b/tools/ci/ccip_lcov_prune @@ -0,0 +1,30 @@ +#!/usr/bin/env bash + +set -e + +# src/v0.8/ccip/libraries/Internal.sol +# src/v0.8/ccip/libraries/RateLimiter.sol +# src/v0.8/ccip/libraries/USDPriceWith18Decimals.sol +# src/v0.8/ccip/libraries/MerkleMultiProof.sol +# src/v0.8/ccip/libraries/Pool.sol +# excluded because Foundry doesn't support coverage on library files + +# BurnWithFromMintTokenPool is excluded because Forge doesn't seem to +# register coverage, even though it is 100% covered. + + +lcov --remove $1 -o $2 \ + '*/ccip/test/*' \ + '*/vendor/*' \ + '*/shared/*' \ + 'src/v0.8/ccip/ocr/OCR2Abstract.sol' \ + 'src/v0.8/ccip/libraries/Internal.sol' \ + 'src/v0.8/ccip/libraries/RateLimiter.sol' \ + 'src/v0.8/ccip/libraries/USDPriceWith18Decimals.sol' \ + 'src/v0.8/ccip/libraries/MerkleMultiProof.sol' \ + 'src/v0.8/ccip/libraries/Pool.sol' \ + 'src/v0.8/ConfirmedOwnerWithProposal.sol' \ + 'src/v0.8/tests/MockV3Aggregator.sol' \ + 'src/v0.8/ccip/applications/CCIPClientExample.sol' \ + 'src/v0.8/ccip/pools/BurnWithFromMintTokenPool.sol' \ + --rc lcov_branch_coverage=1 \ No newline at end of file From 6bdc1dc03992f698d0dbf60a104a0a5ec8847a34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Friedemann=20F=C3=BCrst?= <59653747+friedemannf@users.noreply.github.com> Date: Fri, 30 Aug 2024 11:39:21 +0200 Subject: [PATCH 057/115] Bump chain-selectors => v1.0.23 (#1395) Bumping chain-selectors to https://github.com/smartcontractkit/chain-selectors/pull/53 --- core/scripts/ccip/manual-execution/go.mod | 2 +- core/scripts/ccip/manual-execution/go.sum | 4 ++-- core/scripts/go.mod | 2 +- core/scripts/go.sum | 4 ++-- go.mod | 2 +- go.sum | 4 ++-- integration-tests/go.mod | 2 +- integration-tests/go.sum | 4 ++-- integration-tests/load/go.mod | 2 +- integration-tests/load/go.sum | 4 ++-- 10 files changed, 15 insertions(+), 15 deletions(-) diff --git a/core/scripts/ccip/manual-execution/go.mod b/core/scripts/ccip/manual-execution/go.mod index 8d646c03f8..ec295ec868 100644 --- a/core/scripts/ccip/manual-execution/go.mod +++ b/core/scripts/ccip/manual-execution/go.mod @@ -5,7 +5,7 @@ go 1.20 require ( github.com/ethereum/go-ethereum v1.11.3 github.com/pkg/errors v0.9.1 - github.com/smartcontractkit/chain-selectors v1.0.21 + github.com/smartcontractkit/chain-selectors v1.0.23 go.uber.org/multierr v1.1.0 golang.org/x/crypto v0.1.0 ) diff --git a/core/scripts/ccip/manual-execution/go.sum b/core/scripts/ccip/manual-execution/go.sum index d79872f13f..a5bf3ee297 100644 --- a/core/scripts/ccip/manual-execution/go.sum +++ b/core/scripts/ccip/manual-execution/go.sum @@ -70,8 +70,8 @@ github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU= github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= -github.com/smartcontractkit/chain-selectors v1.0.21 h1:KCR9SA7PhOexaBzFieHoLv1WonwhVOPtOStpqTmLC4E= -github.com/smartcontractkit/chain-selectors v1.0.21/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= +github.com/smartcontractkit/chain-selectors v1.0.23 h1:D2Eaex4Cw/O7Lg3tX6WklOqnjjIQAEBnutCtksPzVDY= +github.com/smartcontractkit/chain-selectors v1.0.23/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= diff --git a/core/scripts/go.mod b/core/scripts/go.mod index b167d6cd02..cdc8492eea 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -22,7 +22,7 @@ require ( github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.17.0 github.com/shopspring/decimal v1.4.0 - github.com/smartcontractkit/chain-selectors v1.0.21 + github.com/smartcontractkit/chain-selectors v1.0.23 github.com/smartcontractkit/chainlink-automation v1.0.4 github.com/smartcontractkit/chainlink-common v0.2.1-0.20240717132349-ee5af9b79834 github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000 diff --git a/core/scripts/go.sum b/core/scripts/go.sum index 7ab6113b2a..4b567f016e 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -1066,8 +1066,8 @@ github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMB github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/smartcontractkit/chain-selectors v1.0.21 h1:KCR9SA7PhOexaBzFieHoLv1WonwhVOPtOStpqTmLC4E= -github.com/smartcontractkit/chain-selectors v1.0.21/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= +github.com/smartcontractkit/chain-selectors v1.0.23 h1:D2Eaex4Cw/O7Lg3tX6WklOqnjjIQAEBnutCtksPzVDY= +github.com/smartcontractkit/chain-selectors v1.0.23/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/smartcontractkit/chainlink-automation v1.0.4 h1:iyW181JjKHLNMnDleI8umfIfVVlwC7+n5izbLSFgjw8= github.com/smartcontractkit/chainlink-automation v1.0.4/go.mod h1:u4NbPZKJ5XiayfKHD/v3z3iflQWqvtdhj13jVZXj/cM= github.com/smartcontractkit/chainlink-ccip v0.0.0-20240827164549-33f5819d7ddc h1:8267l5X5oF2JnGsDaEG4i0JSQO9o0eC61SscTfWc1bk= diff --git a/go.mod b/go.mod index 783b28e5a2..f376b25643 100644 --- a/go.mod +++ b/go.mod @@ -72,7 +72,7 @@ require ( github.com/scylladb/go-reflectx v1.0.1 github.com/shirou/gopsutil/v3 v3.24.3 github.com/shopspring/decimal v1.4.0 - github.com/smartcontractkit/chain-selectors v1.0.21 + github.com/smartcontractkit/chain-selectors v1.0.23 github.com/smartcontractkit/chainlink-automation v1.0.4 github.com/smartcontractkit/chainlink-ccip v0.0.0-20240827164549-33f5819d7ddc github.com/smartcontractkit/chainlink-common v0.2.1-0.20240717132349-ee5af9b79834 diff --git a/go.sum b/go.sum index 081c0a2aee..ec3ca45b16 100644 --- a/go.sum +++ b/go.sum @@ -1023,8 +1023,8 @@ github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMB github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/smartcontractkit/chain-selectors v1.0.21 h1:KCR9SA7PhOexaBzFieHoLv1WonwhVOPtOStpqTmLC4E= -github.com/smartcontractkit/chain-selectors v1.0.21/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= +github.com/smartcontractkit/chain-selectors v1.0.23 h1:D2Eaex4Cw/O7Lg3tX6WklOqnjjIQAEBnutCtksPzVDY= +github.com/smartcontractkit/chain-selectors v1.0.23/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/smartcontractkit/chainlink-automation v1.0.4 h1:iyW181JjKHLNMnDleI8umfIfVVlwC7+n5izbLSFgjw8= github.com/smartcontractkit/chainlink-automation v1.0.4/go.mod h1:u4NbPZKJ5XiayfKHD/v3z3iflQWqvtdhj13jVZXj/cM= github.com/smartcontractkit/chainlink-ccip v0.0.0-20240827164549-33f5819d7ddc h1:8267l5X5oF2JnGsDaEG4i0JSQO9o0eC61SscTfWc1bk= diff --git a/integration-tests/go.mod b/integration-tests/go.mod index f63a30fa31..37f3ba0973 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -34,7 +34,7 @@ require ( github.com/shopspring/decimal v1.4.0 github.com/slack-go/slack v0.12.2 github.com/smartcontractkit/ccip-owner-contracts v0.0.0-20240808195812-ae0378684685 - github.com/smartcontractkit/chain-selectors v1.0.21 + github.com/smartcontractkit/chain-selectors v1.0.23 github.com/smartcontractkit/chainlink-automation v1.0.4 github.com/smartcontractkit/chainlink-ccip v0.0.0-20240827164549-33f5819d7ddc github.com/smartcontractkit/chainlink-common v0.2.1-0.20240717132349-ee5af9b79834 diff --git a/integration-tests/go.sum b/integration-tests/go.sum index a573b2c41f..b21f0a2c4a 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1391,8 +1391,8 @@ github.com/slack-go/slack v0.12.2 h1:x3OppyMyGIbbiyFhsBmpf9pwkUzMhthJMRNmNlA4LaQ github.com/slack-go/slack v0.12.2/go.mod h1:hlGi5oXA+Gt+yWTPP0plCdRKmjsDxecdHxYQdlMQKOw= github.com/smartcontractkit/ccip-owner-contracts v0.0.0-20240808195812-ae0378684685 h1:jakAsdhDxV4cMgRAcSvHraXjyePi8umG5SEUTGFvuy8= github.com/smartcontractkit/ccip-owner-contracts v0.0.0-20240808195812-ae0378684685/go.mod h1:p7L/xNEQpHDdZtgFA6/FavuZHqvV3kYhQysxBywmq1k= -github.com/smartcontractkit/chain-selectors v1.0.21 h1:KCR9SA7PhOexaBzFieHoLv1WonwhVOPtOStpqTmLC4E= -github.com/smartcontractkit/chain-selectors v1.0.21/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= +github.com/smartcontractkit/chain-selectors v1.0.23 h1:D2Eaex4Cw/O7Lg3tX6WklOqnjjIQAEBnutCtksPzVDY= +github.com/smartcontractkit/chain-selectors v1.0.23/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/smartcontractkit/chainlink-automation v1.0.4 h1:iyW181JjKHLNMnDleI8umfIfVVlwC7+n5izbLSFgjw8= github.com/smartcontractkit/chainlink-automation v1.0.4/go.mod h1:u4NbPZKJ5XiayfKHD/v3z3iflQWqvtdhj13jVZXj/cM= github.com/smartcontractkit/chainlink-ccip v0.0.0-20240827164549-33f5819d7ddc h1:8267l5X5oF2JnGsDaEG4i0JSQO9o0eC61SscTfWc1bk= diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index 95d92451e0..aab626f3bd 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -375,7 +375,7 @@ require ( github.com/shoenig/go-m1cpu v0.1.6 // indirect github.com/shopspring/decimal v1.4.0 // indirect github.com/sirupsen/logrus v1.9.3 // indirect - github.com/smartcontractkit/chain-selectors v1.0.21 // indirect + github.com/smartcontractkit/chain-selectors v1.0.23 // indirect github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240718160222-2dc0c8136bfa // indirect github.com/smartcontractkit/chainlink-feeds v0.0.0-20240710170203-5b41615da827 // indirect github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240712132946-267a37c5ac6e // indirect diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index 7ec40db665..f4f3567b5d 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -1355,8 +1355,8 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/slack-go/slack v0.12.2 h1:x3OppyMyGIbbiyFhsBmpf9pwkUzMhthJMRNmNlA4LaQ= github.com/slack-go/slack v0.12.2/go.mod h1:hlGi5oXA+Gt+yWTPP0plCdRKmjsDxecdHxYQdlMQKOw= -github.com/smartcontractkit/chain-selectors v1.0.21 h1:KCR9SA7PhOexaBzFieHoLv1WonwhVOPtOStpqTmLC4E= -github.com/smartcontractkit/chain-selectors v1.0.21/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= +github.com/smartcontractkit/chain-selectors v1.0.23 h1:D2Eaex4Cw/O7Lg3tX6WklOqnjjIQAEBnutCtksPzVDY= +github.com/smartcontractkit/chain-selectors v1.0.23/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/smartcontractkit/chainlink-automation v1.0.4 h1:iyW181JjKHLNMnDleI8umfIfVVlwC7+n5izbLSFgjw8= github.com/smartcontractkit/chainlink-automation v1.0.4/go.mod h1:u4NbPZKJ5XiayfKHD/v3z3iflQWqvtdhj13jVZXj/cM= github.com/smartcontractkit/chainlink-ccip v0.0.0-20240827164549-33f5819d7ddc h1:8267l5X5oF2JnGsDaEG4i0JSQO9o0eC61SscTfWc1bk= From 9952bca03713bf8ea1bfbdae72427cc221eb8501 Mon Sep 17 00:00:00 2001 From: "Abdelrahman Soliman (Boda)" <2677789+asoliman92@users.noreply.github.com> Date: Fri, 30 Aug 2024 22:18:51 +0400 Subject: [PATCH 058/115] Remove capabilities/ccip and integration-tests/deployment (#1399) All development should move to Chainlink repo. To do so make sure you have ccip repo as a remote to your git. 1. cd chainlink/ 2. `git remote add ccipr org-25111032@github.com:smartcontractkit/ccip.git` 3. `git fetch ccipr` 4. `git checkout -b new-branch` 5. `git cherry-pick old-feature-branch~X..old-feature-branch` #These are the first and last commit from your currently open PR in ccip. --------- Co-authored-by: AnieeG --- .github/workflows/ci-core.yml | 4 - .github/workflows/solidity-foundry.yml | 1 - .mockery.yaml | 4 - .../ccip/ccip_integration_tests/.gitignore | 1 - .../ccipreader/ccipreader_test.go | 461 ----- .../chainreader/Makefile | 12 - .../chainreader/chainreader_test.go | 273 --- .../chainreader/mycontract.go | 519 ----- .../chainreader/mycontract.sol | 31 - .../ccip/ccip_integration_tests/helpers.go | 957 --------- .../ccip_integration_tests/home_chain_test.go | 113 -- .../integrationhelpers/integration_helpers.go | 305 --- .../ccip_integration_tests/ping_pong_test.go | 95 - core/capabilities/ccip/ccipevm/commitcodec.go | 138 -- .../ccip/ccipevm/commitcodec_test.go | 135 -- .../capabilities/ccip/ccipevm/executecodec.go | 181 -- .../ccip/ccipevm/executecodec_test.go | 174 -- core/capabilities/ccip/ccipevm/gas_helpers.go | 89 - .../ccip/ccipevm/gas_helpers_test.go | 157 -- core/capabilities/ccip/ccipevm/helpers.go | 33 - .../capabilities/ccip/ccipevm/helpers_test.go | 41 - core/capabilities/ccip/ccipevm/msghasher.go | 127 -- .../ccip/ccipevm/msghasher_test.go | 189 -- core/capabilities/ccip/common/common.go | 23 - core/capabilities/ccip/common/common_test.go | 51 - .../ccip/configs/evm/chain_writer.go | 75 - .../ccip/configs/evm/contract_reader.go | 213 -- core/capabilities/ccip/delegate.go | 312 --- core/capabilities/ccip/delegate_test.go | 1 - core/capabilities/ccip/launcher/README.md | 69 - core/capabilities/ccip/launcher/bluegreen.go | 132 -- .../ccip/launcher/bluegreen_test.go | 681 ------- .../launcher/ccip_capability_launcher.png | Bin 253433 -> 0 bytes .../launcher/ccip_config_state_machine.png | Bin 96958 -> 0 bytes core/capabilities/ccip/launcher/diff.go | 143 -- core/capabilities/ccip/launcher/diff_test.go | 476 ----- .../ccip/launcher/integration_test.go | 113 -- core/capabilities/ccip/launcher/launcher.go | 412 ---- .../ccip/launcher/launcher_test.go | 490 ----- .../ccip/ocrimpls/config_digester.go | 23 - .../ccip/ocrimpls/config_tracker.go | 77 - .../ccip/ocrimpls/contract_transmitter.go | 188 -- .../ocrimpls/contract_transmitter_test.go | 690 ------- core/capabilities/ccip/ocrimpls/keyring.go | 61 - .../ccip/oraclecreator/bootstrap.go | 97 - .../capabilities/ccip/oraclecreator/plugin.go | 377 ---- .../ccip/superfakes/token_data_reader.go | 23 - .../ccip/types/mocks/ccip_oracle.go | 122 -- .../ccip/types/mocks/home_chain_reader.go | 129 -- .../ccip/types/mocks/oracle_creator.go | 138 -- core/capabilities/ccip/types/types.go | 54 - core/capabilities/ccip/validate/validate.go | 91 - .../ccip/validate/validate_test.go | 58 - core/scripts/go.mod | 1 - core/scripts/go.sum | 2 - core/services/chainlink/application.go | 14 - core/services/job/job_orm_test.go | 118 -- go.md | 4 - go.mod | 1 - go.sum | 2 - integration-tests/deployment/address_book.go | 158 -- .../deployment/address_book_test.go | 112 -- integration-tests/deployment/ccip/add_lane.go | 119 -- .../deployment/ccip/add_lane_test.go | 1 - .../deployment/ccip/changeset/1_cap_reg.go | 21 - .../ccip/changeset/2_initial_deploy.go | 33 - .../ccip/changeset/2_initial_deploy_test.go | 241 --- integration-tests/deployment/ccip/deploy.go | 470 ----- .../deployment/ccip/deploy_home_chain.go | 401 ---- .../deployment/ccip/deploy_test.go | 58 - integration-tests/deployment/ccip/jobs.go | 79 - integration-tests/deployment/ccip/propose.go | 64 - integration-tests/deployment/ccip/state.go | 276 --- .../deployment/ccip/test_helpers.go | 75 - integration-tests/deployment/changeset.go | 28 - integration-tests/deployment/environment.go | 195 -- .../deployment/jd/job/v1/job.pb.go | 1767 ----------------- .../deployment/jd/job/v1/job_grpc.pb.go | 345 ---- .../deployment/jd/node/v1/node.pb.go | 1652 --------------- .../deployment/jd/node/v1/node_grpc.pb.go | 187 -- .../deployment/jd/node/v1/shared.pb.go | 239 --- .../deployment/jd/shared/ptypes/label.pb.go | 311 --- integration-tests/deployment/memory/chain.go | 74 - .../deployment/memory/environment.go | 142 -- .../deployment/memory/job_client.go | 126 -- integration-tests/deployment/memory/node.go | 291 --- .../deployment/memory/node_test.go | 23 - integration-tests/go.mod | 9 +- integration-tests/go.sum | 5 +- integration-tests/load/go.mod | 1 - integration-tests/load/go.sum | 2 - tools/bin/go_core_ccip_deployment_tests | 43 - 92 files changed, 4 insertions(+), 17045 deletions(-) delete mode 100644 core/capabilities/ccip/ccip_integration_tests/.gitignore delete mode 100644 core/capabilities/ccip/ccip_integration_tests/ccipreader/ccipreader_test.go delete mode 100644 core/capabilities/ccip/ccip_integration_tests/chainreader/Makefile delete mode 100644 core/capabilities/ccip/ccip_integration_tests/chainreader/chainreader_test.go delete mode 100644 core/capabilities/ccip/ccip_integration_tests/chainreader/mycontract.go delete mode 100644 core/capabilities/ccip/ccip_integration_tests/chainreader/mycontract.sol delete mode 100644 core/capabilities/ccip/ccip_integration_tests/helpers.go delete mode 100644 core/capabilities/ccip/ccip_integration_tests/home_chain_test.go delete mode 100644 core/capabilities/ccip/ccip_integration_tests/integrationhelpers/integration_helpers.go delete mode 100644 core/capabilities/ccip/ccip_integration_tests/ping_pong_test.go delete mode 100644 core/capabilities/ccip/ccipevm/commitcodec.go delete mode 100644 core/capabilities/ccip/ccipevm/commitcodec_test.go delete mode 100644 core/capabilities/ccip/ccipevm/executecodec.go delete mode 100644 core/capabilities/ccip/ccipevm/executecodec_test.go delete mode 100644 core/capabilities/ccip/ccipevm/gas_helpers.go delete mode 100644 core/capabilities/ccip/ccipevm/gas_helpers_test.go delete mode 100644 core/capabilities/ccip/ccipevm/helpers.go delete mode 100644 core/capabilities/ccip/ccipevm/helpers_test.go delete mode 100644 core/capabilities/ccip/ccipevm/msghasher.go delete mode 100644 core/capabilities/ccip/ccipevm/msghasher_test.go delete mode 100644 core/capabilities/ccip/common/common.go delete mode 100644 core/capabilities/ccip/common/common_test.go delete mode 100644 core/capabilities/ccip/configs/evm/chain_writer.go delete mode 100644 core/capabilities/ccip/configs/evm/contract_reader.go delete mode 100644 core/capabilities/ccip/delegate.go delete mode 100644 core/capabilities/ccip/delegate_test.go delete mode 100644 core/capabilities/ccip/launcher/README.md delete mode 100644 core/capabilities/ccip/launcher/bluegreen.go delete mode 100644 core/capabilities/ccip/launcher/bluegreen_test.go delete mode 100644 core/capabilities/ccip/launcher/ccip_capability_launcher.png delete mode 100644 core/capabilities/ccip/launcher/ccip_config_state_machine.png delete mode 100644 core/capabilities/ccip/launcher/diff.go delete mode 100644 core/capabilities/ccip/launcher/diff_test.go delete mode 100644 core/capabilities/ccip/launcher/integration_test.go delete mode 100644 core/capabilities/ccip/launcher/launcher.go delete mode 100644 core/capabilities/ccip/launcher/launcher_test.go delete mode 100644 core/capabilities/ccip/ocrimpls/config_digester.go delete mode 100644 core/capabilities/ccip/ocrimpls/config_tracker.go delete mode 100644 core/capabilities/ccip/ocrimpls/contract_transmitter.go delete mode 100644 core/capabilities/ccip/ocrimpls/contract_transmitter_test.go delete mode 100644 core/capabilities/ccip/ocrimpls/keyring.go delete mode 100644 core/capabilities/ccip/oraclecreator/bootstrap.go delete mode 100644 core/capabilities/ccip/oraclecreator/plugin.go delete mode 100644 core/capabilities/ccip/superfakes/token_data_reader.go delete mode 100644 core/capabilities/ccip/types/mocks/ccip_oracle.go delete mode 100644 core/capabilities/ccip/types/mocks/home_chain_reader.go delete mode 100644 core/capabilities/ccip/types/mocks/oracle_creator.go delete mode 100644 core/capabilities/ccip/types/types.go delete mode 100644 core/capabilities/ccip/validate/validate.go delete mode 100644 core/capabilities/ccip/validate/validate_test.go delete mode 100644 integration-tests/deployment/address_book.go delete mode 100644 integration-tests/deployment/address_book_test.go delete mode 100644 integration-tests/deployment/ccip/add_lane.go delete mode 100644 integration-tests/deployment/ccip/add_lane_test.go delete mode 100644 integration-tests/deployment/ccip/changeset/1_cap_reg.go delete mode 100644 integration-tests/deployment/ccip/changeset/2_initial_deploy.go delete mode 100644 integration-tests/deployment/ccip/changeset/2_initial_deploy_test.go delete mode 100644 integration-tests/deployment/ccip/deploy.go delete mode 100644 integration-tests/deployment/ccip/deploy_home_chain.go delete mode 100644 integration-tests/deployment/ccip/deploy_test.go delete mode 100644 integration-tests/deployment/ccip/jobs.go delete mode 100644 integration-tests/deployment/ccip/propose.go delete mode 100644 integration-tests/deployment/ccip/state.go delete mode 100644 integration-tests/deployment/ccip/test_helpers.go delete mode 100644 integration-tests/deployment/changeset.go delete mode 100644 integration-tests/deployment/environment.go delete mode 100644 integration-tests/deployment/jd/job/v1/job.pb.go delete mode 100644 integration-tests/deployment/jd/job/v1/job_grpc.pb.go delete mode 100644 integration-tests/deployment/jd/node/v1/node.pb.go delete mode 100644 integration-tests/deployment/jd/node/v1/node_grpc.pb.go delete mode 100644 integration-tests/deployment/jd/node/v1/shared.pb.go delete mode 100644 integration-tests/deployment/jd/shared/ptypes/label.pb.go delete mode 100644 integration-tests/deployment/memory/chain.go delete mode 100644 integration-tests/deployment/memory/environment.go delete mode 100644 integration-tests/deployment/memory/job_client.go delete mode 100644 integration-tests/deployment/memory/node.go delete mode 100644 integration-tests/deployment/memory/node_test.go delete mode 100755 tools/bin/go_core_ccip_deployment_tests diff --git a/.github/workflows/ci-core.yml b/.github/workflows/ci-core.yml index 209c9f9192..ddb89e517b 100644 --- a/.github/workflows/ci-core.yml +++ b/.github/workflows/ci-core.yml @@ -92,10 +92,6 @@ jobs: id: core_unit os: ubuntu22.04-32cores-128GB printResults: true - - cmd: go_core_ccip_deployment_tests - id: core_unit - os: ubuntu22.04-32cores-128GB - printResults: true - cmd: go_core_race_tests id: core_race # use 64cores for overnight runs only due to massive number of runs from PRs diff --git a/.github/workflows/solidity-foundry.yml b/.github/workflows/solidity-foundry.yml index 30fc562a05..7ba1d9bba2 100644 --- a/.github/workflows/solidity-foundry.yml +++ b/.github/workflows/solidity-foundry.yml @@ -133,7 +133,6 @@ jobs: - '!contracts/src/v0.8/vendor/**' tests: - if: ${{ needs.changes.outputs.non_src_changes == 'true' || needs.changes.outputs.sol_modified_added == 'true' }} strategy: fail-fast: false matrix: diff --git a/.mockery.yaml b/.mockery.yaml index 6902232c30..6e56f27795 100644 --- a/.mockery.yaml +++ b/.mockery.yaml @@ -476,10 +476,6 @@ packages: outpkg: mock_optimism_dispute_game_factory interfaces: OptimismDisputeGameFactoryInterface: - github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types: - interfaces: - CCIPOracle: - OracleCreator: github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/cache: config: filename: chain_health_mock.go diff --git a/core/capabilities/ccip/ccip_integration_tests/.gitignore b/core/capabilities/ccip/ccip_integration_tests/.gitignore deleted file mode 100644 index 567609b123..0000000000 --- a/core/capabilities/ccip/ccip_integration_tests/.gitignore +++ /dev/null @@ -1 +0,0 @@ -build/ diff --git a/core/capabilities/ccip/ccip_integration_tests/ccipreader/ccipreader_test.go b/core/capabilities/ccip/ccip_integration_tests/ccipreader/ccipreader_test.go deleted file mode 100644 index 05a91eb289..0000000000 --- a/core/capabilities/ccip/ccip_integration_tests/ccipreader/ccipreader_test.go +++ /dev/null @@ -1,461 +0,0 @@ -package ccipreader - -import ( - "context" - "math/big" - "sort" - "testing" - "time" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/crypto" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "go.uber.org/zap/zapcore" - "golang.org/x/exp/maps" - - "github.com/smartcontractkit/chainlink-common/pkg/types" - cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3" - "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" - - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/ccip_reader_tester" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" - "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" - evmtypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" - - "github.com/smartcontractkit/chainlink-ccip/pkg/consts" - "github.com/smartcontractkit/chainlink-ccip/pkg/contractreader" - ccipreaderpkg "github.com/smartcontractkit/chainlink-ccip/pkg/reader" - "github.com/smartcontractkit/chainlink-ccip/plugintypes" -) - -const ( - chainS1 = cciptypes.ChainSelector(1) - chainS2 = cciptypes.ChainSelector(2) - chainS3 = cciptypes.ChainSelector(3) - chainD = cciptypes.ChainSelector(4) -) - -func TestCCIPReader_CommitReportsGTETimestamp(t *testing.T) { - ctx := testutils.Context(t) - - cfg := evmtypes.ChainReaderConfig{ - Contracts: map[string]evmtypes.ChainContractReader{ - consts.ContractNameOffRamp: { - ContractPollingFilter: evmtypes.ContractPollingFilter{ - GenericEventNames: []string{consts.EventNameCommitReportAccepted}, - }, - ContractABI: ccip_reader_tester.CCIPReaderTesterABI, - Configs: map[string]*evmtypes.ChainReaderDefinition{ - consts.EventNameCommitReportAccepted: { - ChainSpecificName: consts.EventNameCommitReportAccepted, - ReadType: evmtypes.Event, - }, - }, - }, - }, - } - - s := testSetup(ctx, t, chainD, chainD, nil, cfg) - - tokenA := common.HexToAddress("123") - const numReports = 5 - - for i := uint8(0); i < numReports; i++ { - _, err := s.contract.EmitCommitReportAccepted(s.auth, ccip_reader_tester.OffRampCommitReport{ - PriceUpdates: ccip_reader_tester.InternalPriceUpdates{ - TokenPriceUpdates: []ccip_reader_tester.InternalTokenPriceUpdate{ - { - SourceToken: tokenA, - UsdPerToken: big.NewInt(1000), - }, - }, - GasPriceUpdates: []ccip_reader_tester.InternalGasPriceUpdate{ - { - DestChainSelector: uint64(chainD), - UsdPerUnitGas: big.NewInt(90), - }, - }, - }, - MerkleRoots: []ccip_reader_tester.OffRampMerkleRoot{ - { - SourceChainSelector: uint64(chainS1), - Interval: ccip_reader_tester.OffRampInterval{ - Min: 10, - Max: 20, - }, - MerkleRoot: [32]byte{i + 1}, - }, - }, - }) - assert.NoError(t, err) - s.sb.Commit() - } - - // Need to replay as sometimes the logs are not picked up by the log poller (?) - // Maybe another situation where chain reader doesn't register filters as expected. - require.NoError(t, s.lp.Replay(ctx, 1)) - - var reports []plugintypes.CommitPluginReportWithMeta - var err error - require.Eventually(t, func() bool { - reports, err = s.reader.CommitReportsGTETimestamp( - ctx, - chainD, - time.Unix(30, 0), // Skips first report, simulated backend report timestamps are [20, 30, 40, ...] - 10, - ) - require.NoError(t, err) - return len(reports) == numReports-1 - }, tests.WaitTimeout(t), 50*time.Millisecond) - - assert.Len(t, reports[0].Report.MerkleRoots, 1) - assert.Equal(t, chainS1, reports[0].Report.MerkleRoots[0].ChainSel) - assert.Equal(t, cciptypes.SeqNum(10), reports[0].Report.MerkleRoots[0].SeqNumsRange.Start()) - assert.Equal(t, cciptypes.SeqNum(20), reports[0].Report.MerkleRoots[0].SeqNumsRange.End()) - assert.Equal(t, "0x0200000000000000000000000000000000000000000000000000000000000000", - reports[0].Report.MerkleRoots[0].MerkleRoot.String()) - - assert.Equal(t, tokenA.String(), string(reports[0].Report.PriceUpdates.TokenPriceUpdates[0].TokenID)) - assert.Equal(t, uint64(1000), reports[0].Report.PriceUpdates.TokenPriceUpdates[0].Price.Uint64()) - - assert.Equal(t, chainD, reports[0].Report.PriceUpdates.GasPriceUpdates[0].ChainSel) - assert.Equal(t, uint64(90), reports[0].Report.PriceUpdates.GasPriceUpdates[0].GasPrice.Uint64()) -} - -func TestCCIPReader_ExecutedMessageRanges(t *testing.T) { - ctx := testutils.Context(t) - cfg := evmtypes.ChainReaderConfig{ - Contracts: map[string]evmtypes.ChainContractReader{ - consts.ContractNameOffRamp: { - ContractPollingFilter: evmtypes.ContractPollingFilter{ - GenericEventNames: []string{consts.EventNameExecutionStateChanged}, - }, - ContractABI: ccip_reader_tester.CCIPReaderTesterABI, - Configs: map[string]*evmtypes.ChainReaderDefinition{ - consts.EventNameExecutionStateChanged: { - ChainSpecificName: consts.EventNameExecutionStateChanged, - ReadType: evmtypes.Event, - }, - }, - }, - }, - } - - s := testSetup(ctx, t, chainD, chainD, nil, cfg) - - _, err := s.contract.EmitExecutionStateChanged( - s.auth, - uint64(chainS1), - 14, - cciptypes.Bytes32{1, 0, 0, 1}, - 1, - []byte{1, 2, 3, 4}, - ) - assert.NoError(t, err) - s.sb.Commit() - - _, err = s.contract.EmitExecutionStateChanged( - s.auth, - uint64(chainS1), - 15, - cciptypes.Bytes32{1, 0, 0, 2}, - 1, - []byte{1, 2, 3, 4, 5}, - ) - assert.NoError(t, err) - s.sb.Commit() - - // Need to replay as sometimes the logs are not picked up by the log poller (?) - // Maybe another situation where chain reader doesn't register filters as expected. - require.NoError(t, s.lp.Replay(ctx, 1)) - - var executedRanges []cciptypes.SeqNumRange - require.Eventually(t, func() bool { - executedRanges, err = s.reader.ExecutedMessageRanges( - ctx, - chainS1, - chainD, - cciptypes.NewSeqNumRange(14, 15), - ) - require.NoError(t, err) - return len(executedRanges) == 2 - }, testutils.WaitTimeout(t), 50*time.Millisecond) - - assert.Equal(t, cciptypes.SeqNum(14), executedRanges[0].Start()) - assert.Equal(t, cciptypes.SeqNum(14), executedRanges[0].End()) - - assert.Equal(t, cciptypes.SeqNum(15), executedRanges[1].Start()) - assert.Equal(t, cciptypes.SeqNum(15), executedRanges[1].End()) -} - -func TestCCIPReader_MsgsBetweenSeqNums(t *testing.T) { - ctx := testutils.Context(t) - - cfg := evmtypes.ChainReaderConfig{ - Contracts: map[string]evmtypes.ChainContractReader{ - consts.ContractNameOnRamp: { - ContractPollingFilter: evmtypes.ContractPollingFilter{ - GenericEventNames: []string{consts.EventNameCCIPSendRequested}, - }, - ContractABI: ccip_reader_tester.CCIPReaderTesterABI, - Configs: map[string]*evmtypes.ChainReaderDefinition{ - consts.EventNameCCIPSendRequested: { - ChainSpecificName: consts.EventNameCCIPSendRequested, - ReadType: evmtypes.Event, - }, - }, - }, - }, - } - - s := testSetup(ctx, t, chainS1, chainD, nil, cfg) - - _, err := s.contract.EmitCCIPSendRequested(s.auth, uint64(chainD), ccip_reader_tester.InternalEVM2AnyRampMessage{ - Header: ccip_reader_tester.InternalRampMessageHeader{ - MessageId: [32]byte{1, 0, 0, 0, 0}, - SourceChainSelector: uint64(chainS1), - DestChainSelector: uint64(chainD), - SequenceNumber: 10, - }, - Sender: utils.RandomAddress(), - Data: make([]byte, 0), - Receiver: utils.RandomAddress().Bytes(), - ExtraArgs: make([]byte, 0), - FeeToken: utils.RandomAddress(), - FeeTokenAmount: big.NewInt(0), - TokenAmounts: make([]ccip_reader_tester.InternalRampTokenAmount, 0), - }) - assert.NoError(t, err) - - _, err = s.contract.EmitCCIPSendRequested(s.auth, uint64(chainD), ccip_reader_tester.InternalEVM2AnyRampMessage{ - Header: ccip_reader_tester.InternalRampMessageHeader{ - MessageId: [32]byte{1, 0, 0, 0, 1}, - SourceChainSelector: uint64(chainS1), - DestChainSelector: uint64(chainD), - SequenceNumber: 15, - }, - Sender: utils.RandomAddress(), - Data: make([]byte, 0), - Receiver: utils.RandomAddress().Bytes(), - ExtraArgs: make([]byte, 0), - FeeToken: utils.RandomAddress(), - FeeTokenAmount: big.NewInt(0), - TokenAmounts: make([]ccip_reader_tester.InternalRampTokenAmount, 0), - }) - assert.NoError(t, err) - - s.sb.Commit() - - // Need to replay as sometimes the logs are not picked up by the log poller (?) - // Maybe another situation where chain reader doesn't register filters as expected. - require.NoError(t, s.lp.Replay(ctx, 1)) - - var msgs []cciptypes.Message - require.Eventually(t, func() bool { - msgs, err = s.reader.MsgsBetweenSeqNums( - ctx, - chainS1, - cciptypes.NewSeqNumRange(5, 20), - ) - require.NoError(t, err) - return len(msgs) == 2 - }, tests.WaitTimeout(t), 100*time.Millisecond) - - require.Len(t, msgs, 2) - // sort to ensure ascending order of sequence numbers. - sort.Slice(msgs, func(i, j int) bool { - return msgs[i].Header.SequenceNumber < msgs[j].Header.SequenceNumber - }) - require.Equal(t, cciptypes.SeqNum(10), msgs[0].Header.SequenceNumber) - require.Equal(t, cciptypes.SeqNum(15), msgs[1].Header.SequenceNumber) - for _, msg := range msgs { - require.Equal(t, chainS1, msg.Header.SourceChainSelector) - require.Equal(t, chainD, msg.Header.DestChainSelector) - } -} - -func TestCCIPReader_NextSeqNum(t *testing.T) { - ctx := testutils.Context(t) - - onChainSeqNums := map[cciptypes.ChainSelector]cciptypes.SeqNum{ - chainS1: 10, - chainS2: 20, - chainS3: 30, - } - - cfg := evmtypes.ChainReaderConfig{ - Contracts: map[string]evmtypes.ChainContractReader{ - consts.ContractNameOffRamp: { - ContractABI: ccip_reader_tester.CCIPReaderTesterABI, - Configs: map[string]*evmtypes.ChainReaderDefinition{ - consts.MethodNameGetSourceChainConfig: { - ChainSpecificName: "getSourceChainConfig", - ReadType: evmtypes.Method, - }, - }, - }, - }, - } - - s := testSetup(ctx, t, chainD, chainD, onChainSeqNums, cfg) - - seqNums, err := s.reader.NextSeqNum(ctx, []cciptypes.ChainSelector{chainS1, chainS2, chainS3}) - assert.NoError(t, err) - assert.Len(t, seqNums, 3) - assert.Equal(t, cciptypes.SeqNum(10), seqNums[0]) - assert.Equal(t, cciptypes.SeqNum(20), seqNums[1]) - assert.Equal(t, cciptypes.SeqNum(30), seqNums[2]) -} - -func TestCCIPReader_GetExpectedNextSequenceNumber(t *testing.T) { - ctx := testutils.Context(t) - - cfg := evmtypes.ChainReaderConfig{ - Contracts: map[string]evmtypes.ChainContractReader{ - consts.ContractNameOnRamp: { - ContractABI: ccip_reader_tester.CCIPReaderTesterABI, - Configs: map[string]*evmtypes.ChainReaderDefinition{ - consts.MethodNameGetExpectedNextSequenceNumber: { - ChainSpecificName: "getExpectedNextSequenceNumber", - ReadType: evmtypes.Method, - }, - }, - }, - }, - } - - s := testSetup(ctx, t, chainS1, chainD, nil, cfg) - - _, err := s.contract.SetDestChainSeqNr(s.auth, uint64(chainD), 10) - require.NoError(t, err) - s.sb.Commit() - - seqNum, err := s.reader.GetExpectedNextSequenceNumber(ctx, chainS1, chainD) - require.NoError(t, err) - require.Equal(t, cciptypes.SeqNum(10)+1, seqNum) - - _, err = s.contract.SetDestChainSeqNr(s.auth, uint64(chainD), 25) - require.NoError(t, err) - s.sb.Commit() - - seqNum, err = s.reader.GetExpectedNextSequenceNumber(ctx, chainS1, chainD) - require.NoError(t, err) - require.Equal(t, cciptypes.SeqNum(25)+1, seqNum) -} - -func testSetup(ctx context.Context, t *testing.T, readerChain, destChain cciptypes.ChainSelector, onChainSeqNums map[cciptypes.ChainSelector]cciptypes.SeqNum, cfg evmtypes.ChainReaderConfig) *testSetupData { - const chainID = 1337 - - // Generate a new key pair for the simulated account - privateKey, err := crypto.GenerateKey() - assert.NoError(t, err) - // Set up the genesis account with balance - blnc, ok := big.NewInt(0).SetString("999999999999999999999999999999999999", 10) - assert.True(t, ok) - alloc := map[common.Address]core.GenesisAccount{crypto.PubkeyToAddress(privateKey.PublicKey): {Balance: blnc}} - simulatedBackend := backends.NewSimulatedBackend(alloc, 0) - // Create a transactor - - auth, err := bind.NewKeyedTransactorWithChainID(privateKey, big.NewInt(chainID)) - assert.NoError(t, err) - auth.GasLimit = uint64(0) - - // Deploy the contract - address, _, _, err := ccip_reader_tester.DeployCCIPReaderTester(auth, simulatedBackend) - assert.NoError(t, err) - simulatedBackend.Commit() - - // Setup contract client - contract, err := ccip_reader_tester.NewCCIPReaderTester(address, simulatedBackend) - assert.NoError(t, err) - - lggr := logger.TestLogger(t) - lggr.SetLogLevel(zapcore.ErrorLevel) - db := pgtest.NewSqlxDB(t) - lpOpts := logpoller.Opts{ - PollPeriod: time.Millisecond, - FinalityDepth: 0, - BackfillBatchSize: 10, - RpcBatchSize: 10, - KeepFinalizedBlocksDepth: 100000, - } - cl := client.NewSimulatedBackendClient(t, simulatedBackend, big.NewInt(0).SetUint64(uint64(readerChain))) - headTracker := headtracker.NewSimulatedHeadTracker(cl, lpOpts.UseFinalityTag, lpOpts.FinalityDepth) - lp := logpoller.NewLogPoller(logpoller.NewORM(big.NewInt(0).SetUint64(uint64(readerChain)), db, lggr), - cl, - lggr, - headTracker, - lpOpts, - ) - assert.NoError(t, lp.Start(ctx)) - - for sourceChain, seqNum := range onChainSeqNums { - _, err1 := contract.SetSourceChainConfig(auth, uint64(sourceChain), ccip_reader_tester.OffRampSourceChainConfig{ - IsEnabled: true, - MinSeqNr: uint64(seqNum), - }) - assert.NoError(t, err1) - simulatedBackend.Commit() - scc, err1 := contract.GetSourceChainConfig(&bind.CallOpts{Context: ctx}, uint64(sourceChain)) - assert.NoError(t, err1) - assert.Equal(t, seqNum, cciptypes.SeqNum(scc.MinSeqNr)) - } - - contractNames := maps.Keys(cfg.Contracts) - assert.Len(t, contractNames, 1, "test setup assumes there is only one contract") - - cr, err := evm.NewChainReaderService(ctx, lggr, lp, headTracker, cl, cfg) - require.NoError(t, err) - - extendedCr := contractreader.NewExtendedContractReader(cr) - err = extendedCr.Bind(ctx, []types.BoundContract{ - { - Address: address.String(), - Name: contractNames[0], - }, - }) - require.NoError(t, err) - - err = cr.Start(ctx) - require.NoError(t, err) - - contractReaders := map[cciptypes.ChainSelector]contractreader.Extended{readerChain: extendedCr} - contractWriters := make(map[cciptypes.ChainSelector]types.ChainWriter) - reader := ccipreaderpkg.NewCCIPReaderWithExtendedContractReaders(lggr, contractReaders, contractWriters, destChain) - - t.Cleanup(func() { - require.NoError(t, cr.Close()) - require.NoError(t, lp.Close()) - require.NoError(t, db.Close()) - }) - - return &testSetupData{ - contractAddr: address, - contract: contract, - sb: simulatedBackend, - auth: auth, - lp: lp, - cl: cl, - reader: reader, - } -} - -type testSetupData struct { - contractAddr common.Address - contract *ccip_reader_tester.CCIPReaderTester - sb *backends.SimulatedBackend - auth *bind.TransactOpts - lp logpoller.LogPoller - cl client.Client - reader ccipreaderpkg.CCIPReader -} diff --git a/core/capabilities/ccip/ccip_integration_tests/chainreader/Makefile b/core/capabilities/ccip/ccip_integration_tests/chainreader/Makefile deleted file mode 100644 index e9c88564e6..0000000000 --- a/core/capabilities/ccip/ccip_integration_tests/chainreader/Makefile +++ /dev/null @@ -1,12 +0,0 @@ - -# IMPORTANT: If you encounter any issues try using solc 0.8.18 and abigen 1.14.5 - -.PHONY: build -build: - rm -rf build/ - solc --evm-version paris --abi --bin mycontract.sol -o build - abigen --abi build/mycontract_sol_SimpleContract.abi --bin build/mycontract_sol_SimpleContract.bin --pkg=chainreader --out=mycontract.go - -.PHONY: test -test: build - go test -v --tags "playground" ./... diff --git a/core/capabilities/ccip/ccip_integration_tests/chainreader/chainreader_test.go b/core/capabilities/ccip/ccip_integration_tests/chainreader/chainreader_test.go deleted file mode 100644 index 52a3de0dae..0000000000 --- a/core/capabilities/ccip/ccip_integration_tests/chainreader/chainreader_test.go +++ /dev/null @@ -1,273 +0,0 @@ -//go:build playground -// +build playground - -package chainreader - -import ( - "context" - _ "embed" - "math/big" - "strconv" - "sync" - "testing" - "time" - - "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/stretchr/testify/assert" - - "github.com/smartcontractkit/chainlink-common/pkg/codec" - types2 "github.com/smartcontractkit/chainlink-common/pkg/types" - query2 "github.com/smartcontractkit/chainlink-common/pkg/types/query" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" - logger2 "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" - evmtypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" -) - -const chainID = 1337 - -type testSetupData struct { - contractAddr common.Address - contract *Chainreader - sb *backends.SimulatedBackend - auth *bind.TransactOpts -} - -func TestChainReader(t *testing.T) { - ctx := testutils.Context(t) - lggr := logger2.NullLogger - d := testSetup(t, ctx) - - db := pgtest.NewSqlxDB(t) - lpOpts := logpoller.Opts{ - PollPeriod: time.Millisecond, - FinalityDepth: 0, - BackfillBatchSize: 10, - RpcBatchSize: 10, - KeepFinalizedBlocksDepth: 100000, - } - cl := client.NewSimulatedBackendClient(t, d.sb, big.NewInt(chainID)) - headTracker := headtracker.NewSimulatedHeadTracker(cl, lpOpts.UseFinalityTag, lpOpts.FinalityDepth) - lp := logpoller.NewLogPoller(logpoller.NewORM(big.NewInt(chainID), db, lggr), - cl, - lggr, - headTracker, - lpOpts, - ) - assert.NoError(t, lp.Start(ctx)) - - const ( - ContractNameAlias = "myCoolContract" - - FnAliasGetCount = "myCoolFunction" - FnGetCount = "getEventCount" - - FnAliasGetNumbers = "GetNumbers" - FnGetNumbers = "getNumbers" - - FnAliasGetPerson = "GetPerson" - FnGetPerson = "getPerson" - - EventNameAlias = "myCoolEvent" - EventName = "SimpleEvent" - ) - - // Initialize chainReader - cfg := evmtypes.ChainReaderConfig{ - Contracts: map[string]evmtypes.ChainContractReader{ - ContractNameAlias: { - ContractPollingFilter: evmtypes.ContractPollingFilter{ - GenericEventNames: []string{EventNameAlias}, - }, - ContractABI: ChainreaderMetaData.ABI, - Configs: map[string]*evmtypes.ChainReaderDefinition{ - EventNameAlias: { - ChainSpecificName: EventName, - ReadType: evmtypes.Event, - ConfidenceConfirmations: map[string]int{"0.0": 0, "1.0": 0}, - }, - FnAliasGetCount: { - ChainSpecificName: FnGetCount, - }, - FnAliasGetNumbers: { - ChainSpecificName: FnGetNumbers, - OutputModifications: codec.ModifiersConfig{}, - }, - FnAliasGetPerson: { - ChainSpecificName: FnGetPerson, - OutputModifications: codec.ModifiersConfig{ - &codec.RenameModifierConfig{ - Fields: map[string]string{"Name": "NameField"}, // solidity name -> go struct name - }, - }, - }, - }, - }, - }, - } - - cr, err := evm.NewChainReaderService(ctx, lggr, lp, cl, cfg) - assert.NoError(t, err) - err = cr.Bind(ctx, []types2.BoundContract{ - { - Address: d.contractAddr.String(), - Name: ContractNameAlias, - Pending: false, - }, - }) - assert.NoError(t, err) - - err = cr.Start(ctx) - assert.NoError(t, err) - for { - if err := cr.Ready(); err == nil { - break - } - } - - emitEvents(t, d, ctx) // Calls the contract to emit events - - // (hack) Sometimes LP logs are missing, commit several times and wait few seconds to make it work. - for i := 0; i < 100; i++ { - d.sb.Commit() - } - time.Sleep(5 * time.Second) - - t.Run("simple contract read", func(t *testing.T) { - var cnt big.Int - err = cr.GetLatestValue(ctx, ContractNameAlias, FnAliasGetCount, map[string]interface{}{}, &cnt) - assert.NoError(t, err) - assert.Equal(t, int64(10), cnt.Int64()) - }) - - t.Run("read array", func(t *testing.T) { - var nums []big.Int - err = cr.GetLatestValue(ctx, ContractNameAlias, FnAliasGetNumbers, map[string]interface{}{}, &nums) - assert.NoError(t, err) - assert.Len(t, nums, 10) - for i := 1; i <= 10; i++ { - assert.Equal(t, int64(i), nums[i-1].Int64()) - } - }) - - t.Run("read struct", func(t *testing.T) { - person := struct { - NameField string - Age *big.Int // WARN: specifying a wrong data type e.g. int instead of *big.Int fails silently with a default value of 0 - }{} - err = cr.GetLatestValue(ctx, ContractNameAlias, FnAliasGetPerson, map[string]interface{}{}, &person) - assert.Equal(t, "Dim", person.NameField) - assert.Equal(t, int64(18), person.Age.Int64()) - }) - - t.Run("read events", func(t *testing.T) { - var myDataType *big.Int - seq, err := cr.QueryKey( - ctx, - ContractNameAlias, - query2.KeyFilter{ - Key: EventNameAlias, - Expressions: []query2.Expression{}, - }, - query2.LimitAndSort{}, - myDataType, - ) - assert.NoError(t, err) - assert.Equal(t, 10, len(seq), "expected 10 events from chain reader") - for _, v := range seq { - // TODO: for some reason log poller does not populate event data - blockNum, err := strconv.ParseUint(v.Identifier, 10, 64) - assert.NoError(t, err) - assert.Positive(t, blockNum) - t.Logf("(chain reader) got event: (data=%v) (hash=%x)", v.Data, v.Hash) - } - }) -} - -func testSetup(t *testing.T, ctx context.Context) *testSetupData { - // Generate a new key pair for the simulated account - privateKey, err := crypto.GenerateKey() - assert.NoError(t, err) - // Set up the genesis account with balance - blnc, ok := big.NewInt(0).SetString("999999999999999999999999999999999999", 10) - assert.True(t, ok) - alloc := map[common.Address]core.GenesisAccount{crypto.PubkeyToAddress(privateKey.PublicKey): {Balance: blnc}} - simulatedBackend := backends.NewSimulatedBackend(alloc, 0) - // Create a transactor - - auth, err := bind.NewKeyedTransactorWithChainID(privateKey, big.NewInt(chainID)) - assert.NoError(t, err) - auth.GasLimit = uint64(0) - - // Deploy the contract - address, tx, _, err := DeployChainreader(auth, simulatedBackend) - assert.NoError(t, err) - simulatedBackend.Commit() - t.Logf("contract deployed: addr=%s tx=%s", address.Hex(), tx.Hash()) - - // Setup contract client - contract, err := NewChainreader(address, simulatedBackend) - assert.NoError(t, err) - - return &testSetupData{ - contractAddr: address, - contract: contract, - sb: simulatedBackend, - auth: auth, - } -} - -func emitEvents(t *testing.T, d *testSetupData, ctx context.Context) { - var wg sync.WaitGroup - wg.Add(2) - - // Start emitting events - go func() { - defer wg.Done() - for i := 0; i < 10; i++ { - _, err := d.contract.EmitEvent(d.auth) - assert.NoError(t, err) - d.sb.Commit() - } - }() - - // Listen events using go-ethereum lib - go func() { - query := ethereum.FilterQuery{ - FromBlock: big.NewInt(0), - Addresses: []common.Address{d.contractAddr}, - } - logs := make(chan types.Log) - sub, err := d.sb.SubscribeFilterLogs(ctx, query, logs) - assert.NoError(t, err) - - numLogs := 0 - defer wg.Done() - for { - // Wait for the events - select { - case err := <-sub.Err(): - assert.NoError(t, err, "got an unexpected error") - case vLog := <-logs: - assert.Equal(t, d.contractAddr, vLog.Address, "got an unexpected address") - t.Logf("(geth) got new log (cnt=%d) (data=%x) (topics=%s)", numLogs, vLog.Data, vLog.Topics) - numLogs++ - if numLogs == 10 { - return - } - } - } - }() - - wg.Wait() // wait for all the events to be consumed -} diff --git a/core/capabilities/ccip/ccip_integration_tests/chainreader/mycontract.go b/core/capabilities/ccip/ccip_integration_tests/chainreader/mycontract.go deleted file mode 100644 index c7d480eed4..0000000000 --- a/core/capabilities/ccip/ccip_integration_tests/chainreader/mycontract.go +++ /dev/null @@ -1,519 +0,0 @@ -// Code generated - DO NOT EDIT. -// This file is a generated binding and any manual changes will be lost. - -package chainreader - -import ( - "errors" - "math/big" - "strings" - - ethereum "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/event" -) - -// Reference imports to suppress errors if they are not otherwise used. -var ( - _ = errors.New - _ = big.NewInt - _ = strings.NewReader - _ = ethereum.NotFound - _ = bind.Bind - _ = common.Big1 - _ = types.BloomLookup - _ = event.NewSubscription - _ = abi.ConvertType -) - -// SimpleContractPerson is an auto generated low-level Go binding around an user-defined struct. -type SimpleContractPerson struct { - Name string - Age *big.Int -} - -// ChainreaderMetaData contains all meta data concerning the Chainreader contract. -var ChainreaderMetaData = &bind.MetaData{ - ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"SimpleEvent\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"emitEvent\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"eventCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getEventCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNumbers\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getPerson\",\"outputs\":[{\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"uint256\",\"name\":\"age\",\"type\":\"uint256\"}],\"internalType\":\"structSimpleContract.Person\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"numbers\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x608060405234801561001057600080fd5b506105a1806100206000396000f3fe608060405234801561001057600080fd5b50600436106100625760003560e01c806371be2e4a146100675780637b0cb8391461008557806389f915f61461008f5780638ec4dc95146100ad578063d39fa233146100cb578063d9e48f5c146100fb575b600080fd5b61006f610119565b60405161007c91906102ac565b60405180910390f35b61008d61011f565b005b61009761019c565b6040516100a49190610385565b60405180910390f35b6100b56101f4565b6040516100c29190610474565b60405180910390f35b6100e560048036038101906100e091906104c7565b61024c565b6040516100f291906102ac565b60405180910390f35b610103610270565b60405161011091906102ac565b60405180910390f35b60005481565b60008081548092919061013190610523565b9190505550600160005490806001815401808255809150506001900390600052602060002001600090919091909150557f12d199749b3f4c44df8d9386c63d725b7756ec47204f3aa0bf05ea832f89effb60005460405161019291906102ac565b60405180910390a1565b606060018054806020026020016040519081016040528092919081815260200182805480156101ea57602002820191906000526020600020905b8154815260200190600101908083116101d6575b5050505050905090565b6101fc610279565b60405180604001604052806040518060400160405280600381526020017f44696d000000000000000000000000000000000000000000000000000000000081525081526020016012815250905090565b6001818154811061025c57600080fd5b906000526020600020016000915090505481565b60008054905090565b604051806040016040528060608152602001600081525090565b6000819050919050565b6102a681610293565b82525050565b60006020820190506102c1600083018461029d565b92915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6102fc81610293565b82525050565b600061030e83836102f3565b60208301905092915050565b6000602082019050919050565b6000610332826102c7565b61033c81856102d2565b9350610347836102e3565b8060005b8381101561037857815161035f8882610302565b975061036a8361031a565b92505060018101905061034b565b5085935050505092915050565b6000602082019050818103600083015261039f8184610327565b905092915050565b600081519050919050565b600082825260208201905092915050565b60005b838110156103e15780820151818401526020810190506103c6565b60008484015250505050565b6000601f19601f8301169050919050565b6000610409826103a7565b61041381856103b2565b93506104238185602086016103c3565b61042c816103ed565b840191505092915050565b6000604083016000830151848203600086015261045482826103fe565b915050602083015161046960208601826102f3565b508091505092915050565b6000602082019050818103600083015261048e8184610437565b905092915050565b600080fd5b6104a481610293565b81146104af57600080fd5b50565b6000813590506104c18161049b565b92915050565b6000602082840312156104dd576104dc610496565b5b60006104eb848285016104b2565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061052e82610293565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036105605761055f6104f4565b5b60018201905091905056fea2646970667358221220f7986dc9efbc0d9ef58e2925ffddc62ea13a6bab8b3a2c03ad2d85d50653129664736f6c63430008120033", -} - -// ChainreaderABI is the input ABI used to generate the binding from. -// Deprecated: Use ChainreaderMetaData.ABI instead. -var ChainreaderABI = ChainreaderMetaData.ABI - -// ChainreaderBin is the compiled bytecode used for deploying new contracts. -// Deprecated: Use ChainreaderMetaData.Bin instead. -var ChainreaderBin = ChainreaderMetaData.Bin - -// DeployChainreader deploys a new Ethereum contract, binding an instance of Chainreader to it. -func DeployChainreader(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *Chainreader, error) { - parsed, err := ChainreaderMetaData.GetAbi() - if err != nil { - return common.Address{}, nil, nil, err - } - if parsed == nil { - return common.Address{}, nil, nil, errors.New("GetABI returned nil") - } - - address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(ChainreaderBin), backend) - if err != nil { - return common.Address{}, nil, nil, err - } - return address, tx, &Chainreader{ChainreaderCaller: ChainreaderCaller{contract: contract}, ChainreaderTransactor: ChainreaderTransactor{contract: contract}, ChainreaderFilterer: ChainreaderFilterer{contract: contract}}, nil -} - -// Chainreader is an auto generated Go binding around an Ethereum contract. -type Chainreader struct { - ChainreaderCaller // Read-only binding to the contract - ChainreaderTransactor // Write-only binding to the contract - ChainreaderFilterer // Log filterer for contract events -} - -// ChainreaderCaller is an auto generated read-only Go binding around an Ethereum contract. -type ChainreaderCaller struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// ChainreaderTransactor is an auto generated write-only Go binding around an Ethereum contract. -type ChainreaderTransactor struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// ChainreaderFilterer is an auto generated log filtering Go binding around an Ethereum contract events. -type ChainreaderFilterer struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// ChainreaderSession is an auto generated Go binding around an Ethereum contract, -// with pre-set call and transact options. -type ChainreaderSession struct { - Contract *Chainreader // Generic contract binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// ChainreaderCallerSession is an auto generated read-only Go binding around an Ethereum contract, -// with pre-set call options. -type ChainreaderCallerSession struct { - Contract *ChainreaderCaller // Generic contract caller binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session -} - -// ChainreaderTransactorSession is an auto generated write-only Go binding around an Ethereum contract, -// with pre-set transact options. -type ChainreaderTransactorSession struct { - Contract *ChainreaderTransactor // Generic contract transactor binding to set the session for - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// ChainreaderRaw is an auto generated low-level Go binding around an Ethereum contract. -type ChainreaderRaw struct { - Contract *Chainreader // Generic contract binding to access the raw methods on -} - -// ChainreaderCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. -type ChainreaderCallerRaw struct { - Contract *ChainreaderCaller // Generic read-only contract binding to access the raw methods on -} - -// ChainreaderTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. -type ChainreaderTransactorRaw struct { - Contract *ChainreaderTransactor // Generic write-only contract binding to access the raw methods on -} - -// NewChainreader creates a new instance of Chainreader, bound to a specific deployed contract. -func NewChainreader(address common.Address, backend bind.ContractBackend) (*Chainreader, error) { - contract, err := bindChainreader(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &Chainreader{ChainreaderCaller: ChainreaderCaller{contract: contract}, ChainreaderTransactor: ChainreaderTransactor{contract: contract}, ChainreaderFilterer: ChainreaderFilterer{contract: contract}}, nil -} - -// NewChainreaderCaller creates a new read-only instance of Chainreader, bound to a specific deployed contract. -func NewChainreaderCaller(address common.Address, caller bind.ContractCaller) (*ChainreaderCaller, error) { - contract, err := bindChainreader(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &ChainreaderCaller{contract: contract}, nil -} - -// NewChainreaderTransactor creates a new write-only instance of Chainreader, bound to a specific deployed contract. -func NewChainreaderTransactor(address common.Address, transactor bind.ContractTransactor) (*ChainreaderTransactor, error) { - contract, err := bindChainreader(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &ChainreaderTransactor{contract: contract}, nil -} - -// NewChainreaderFilterer creates a new log filterer instance of Chainreader, bound to a specific deployed contract. -func NewChainreaderFilterer(address common.Address, filterer bind.ContractFilterer) (*ChainreaderFilterer, error) { - contract, err := bindChainreader(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &ChainreaderFilterer{contract: contract}, nil -} - -// bindChainreader binds a generic wrapper to an already deployed contract. -func bindChainreader(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := ChainreaderMetaData.GetAbi() - if err != nil { - return nil, err - } - return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_Chainreader *ChainreaderRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _Chainreader.Contract.ChainreaderCaller.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_Chainreader *ChainreaderRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _Chainreader.Contract.ChainreaderTransactor.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_Chainreader *ChainreaderRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _Chainreader.Contract.ChainreaderTransactor.contract.Transact(opts, method, params...) -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_Chainreader *ChainreaderCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _Chainreader.Contract.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_Chainreader *ChainreaderTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _Chainreader.Contract.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_Chainreader *ChainreaderTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _Chainreader.Contract.contract.Transact(opts, method, params...) -} - -// EventCount is a free data retrieval call binding the contract method 0x71be2e4a. -// -// Solidity: function eventCount() view returns(uint256) -func (_Chainreader *ChainreaderCaller) EventCount(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _Chainreader.contract.Call(opts, &out, "eventCount") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// EventCount is a free data retrieval call binding the contract method 0x71be2e4a. -// -// Solidity: function eventCount() view returns(uint256) -func (_Chainreader *ChainreaderSession) EventCount() (*big.Int, error) { - return _Chainreader.Contract.EventCount(&_Chainreader.CallOpts) -} - -// EventCount is a free data retrieval call binding the contract method 0x71be2e4a. -// -// Solidity: function eventCount() view returns(uint256) -func (_Chainreader *ChainreaderCallerSession) EventCount() (*big.Int, error) { - return _Chainreader.Contract.EventCount(&_Chainreader.CallOpts) -} - -// GetEventCount is a free data retrieval call binding the contract method 0xd9e48f5c. -// -// Solidity: function getEventCount() view returns(uint256) -func (_Chainreader *ChainreaderCaller) GetEventCount(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _Chainreader.contract.Call(opts, &out, "getEventCount") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// GetEventCount is a free data retrieval call binding the contract method 0xd9e48f5c. -// -// Solidity: function getEventCount() view returns(uint256) -func (_Chainreader *ChainreaderSession) GetEventCount() (*big.Int, error) { - return _Chainreader.Contract.GetEventCount(&_Chainreader.CallOpts) -} - -// GetEventCount is a free data retrieval call binding the contract method 0xd9e48f5c. -// -// Solidity: function getEventCount() view returns(uint256) -func (_Chainreader *ChainreaderCallerSession) GetEventCount() (*big.Int, error) { - return _Chainreader.Contract.GetEventCount(&_Chainreader.CallOpts) -} - -// GetNumbers is a free data retrieval call binding the contract method 0x89f915f6. -// -// Solidity: function getNumbers() view returns(uint256[]) -func (_Chainreader *ChainreaderCaller) GetNumbers(opts *bind.CallOpts) ([]*big.Int, error) { - var out []interface{} - err := _Chainreader.contract.Call(opts, &out, "getNumbers") - - if err != nil { - return *new([]*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new([]*big.Int)).(*[]*big.Int) - - return out0, err - -} - -// GetNumbers is a free data retrieval call binding the contract method 0x89f915f6. -// -// Solidity: function getNumbers() view returns(uint256[]) -func (_Chainreader *ChainreaderSession) GetNumbers() ([]*big.Int, error) { - return _Chainreader.Contract.GetNumbers(&_Chainreader.CallOpts) -} - -// GetNumbers is a free data retrieval call binding the contract method 0x89f915f6. -// -// Solidity: function getNumbers() view returns(uint256[]) -func (_Chainreader *ChainreaderCallerSession) GetNumbers() ([]*big.Int, error) { - return _Chainreader.Contract.GetNumbers(&_Chainreader.CallOpts) -} - -// GetPerson is a free data retrieval call binding the contract method 0x8ec4dc95. -// -// Solidity: function getPerson() pure returns((string,uint256)) -func (_Chainreader *ChainreaderCaller) GetPerson(opts *bind.CallOpts) (SimpleContractPerson, error) { - var out []interface{} - err := _Chainreader.contract.Call(opts, &out, "getPerson") - - if err != nil { - return *new(SimpleContractPerson), err - } - - out0 := *abi.ConvertType(out[0], new(SimpleContractPerson)).(*SimpleContractPerson) - - return out0, err - -} - -// GetPerson is a free data retrieval call binding the contract method 0x8ec4dc95. -// -// Solidity: function getPerson() pure returns((string,uint256)) -func (_Chainreader *ChainreaderSession) GetPerson() (SimpleContractPerson, error) { - return _Chainreader.Contract.GetPerson(&_Chainreader.CallOpts) -} - -// GetPerson is a free data retrieval call binding the contract method 0x8ec4dc95. -// -// Solidity: function getPerson() pure returns((string,uint256)) -func (_Chainreader *ChainreaderCallerSession) GetPerson() (SimpleContractPerson, error) { - return _Chainreader.Contract.GetPerson(&_Chainreader.CallOpts) -} - -// Numbers is a free data retrieval call binding the contract method 0xd39fa233. -// -// Solidity: function numbers(uint256 ) view returns(uint256) -func (_Chainreader *ChainreaderCaller) Numbers(opts *bind.CallOpts, arg0 *big.Int) (*big.Int, error) { - var out []interface{} - err := _Chainreader.contract.Call(opts, &out, "numbers", arg0) - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// Numbers is a free data retrieval call binding the contract method 0xd39fa233. -// -// Solidity: function numbers(uint256 ) view returns(uint256) -func (_Chainreader *ChainreaderSession) Numbers(arg0 *big.Int) (*big.Int, error) { - return _Chainreader.Contract.Numbers(&_Chainreader.CallOpts, arg0) -} - -// Numbers is a free data retrieval call binding the contract method 0xd39fa233. -// -// Solidity: function numbers(uint256 ) view returns(uint256) -func (_Chainreader *ChainreaderCallerSession) Numbers(arg0 *big.Int) (*big.Int, error) { - return _Chainreader.Contract.Numbers(&_Chainreader.CallOpts, arg0) -} - -// EmitEvent is a paid mutator transaction binding the contract method 0x7b0cb839. -// -// Solidity: function emitEvent() returns() -func (_Chainreader *ChainreaderTransactor) EmitEvent(opts *bind.TransactOpts) (*types.Transaction, error) { - return _Chainreader.contract.Transact(opts, "emitEvent") -} - -// EmitEvent is a paid mutator transaction binding the contract method 0x7b0cb839. -// -// Solidity: function emitEvent() returns() -func (_Chainreader *ChainreaderSession) EmitEvent() (*types.Transaction, error) { - return _Chainreader.Contract.EmitEvent(&_Chainreader.TransactOpts) -} - -// EmitEvent is a paid mutator transaction binding the contract method 0x7b0cb839. -// -// Solidity: function emitEvent() returns() -func (_Chainreader *ChainreaderTransactorSession) EmitEvent() (*types.Transaction, error) { - return _Chainreader.Contract.EmitEvent(&_Chainreader.TransactOpts) -} - -// ChainreaderSimpleEventIterator is returned from FilterSimpleEvent and is used to iterate over the raw logs and unpacked data for SimpleEvent events raised by the Chainreader contract. -type ChainreaderSimpleEventIterator struct { - Event *ChainreaderSimpleEvent // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *ChainreaderSimpleEventIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(ChainreaderSimpleEvent) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(ChainreaderSimpleEvent) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *ChainreaderSimpleEventIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *ChainreaderSimpleEventIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// ChainreaderSimpleEvent represents a SimpleEvent event raised by the Chainreader contract. -type ChainreaderSimpleEvent struct { - Value *big.Int - Raw types.Log // Blockchain specific contextual infos -} - -// FilterSimpleEvent is a free log retrieval operation binding the contract event 0x12d199749b3f4c44df8d9386c63d725b7756ec47204f3aa0bf05ea832f89effb. -// -// Solidity: event SimpleEvent(uint256 value) -func (_Chainreader *ChainreaderFilterer) FilterSimpleEvent(opts *bind.FilterOpts) (*ChainreaderSimpleEventIterator, error) { - - logs, sub, err := _Chainreader.contract.FilterLogs(opts, "SimpleEvent") - if err != nil { - return nil, err - } - return &ChainreaderSimpleEventIterator{contract: _Chainreader.contract, event: "SimpleEvent", logs: logs, sub: sub}, nil -} - -// WatchSimpleEvent is a free log subscription operation binding the contract event 0x12d199749b3f4c44df8d9386c63d725b7756ec47204f3aa0bf05ea832f89effb. -// -// Solidity: event SimpleEvent(uint256 value) -func (_Chainreader *ChainreaderFilterer) WatchSimpleEvent(opts *bind.WatchOpts, sink chan<- *ChainreaderSimpleEvent) (event.Subscription, error) { - - logs, sub, err := _Chainreader.contract.WatchLogs(opts, "SimpleEvent") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(ChainreaderSimpleEvent) - if err := _Chainreader.contract.UnpackLog(event, "SimpleEvent", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ParseSimpleEvent is a log parse operation binding the contract event 0x12d199749b3f4c44df8d9386c63d725b7756ec47204f3aa0bf05ea832f89effb. -// -// Solidity: event SimpleEvent(uint256 value) -func (_Chainreader *ChainreaderFilterer) ParseSimpleEvent(log types.Log) (*ChainreaderSimpleEvent, error) { - event := new(ChainreaderSimpleEvent) - if err := _Chainreader.contract.UnpackLog(event, "SimpleEvent", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} diff --git a/core/capabilities/ccip/ccip_integration_tests/chainreader/mycontract.sol b/core/capabilities/ccip/ccip_integration_tests/chainreader/mycontract.sol deleted file mode 100644 index 0fae1f4baa..0000000000 --- a/core/capabilities/ccip/ccip_integration_tests/chainreader/mycontract.sol +++ /dev/null @@ -1,31 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.18; - -contract SimpleContract { - event SimpleEvent(uint256 value); - uint256 public eventCount; - uint[] public numbers; - - struct Person { - string name; - uint age; - } - - function emitEvent() public { - eventCount++; - numbers.push(eventCount); - emit SimpleEvent(eventCount); - } - - function getEventCount() public view returns (uint256) { - return eventCount; - } - - function getNumbers() public view returns (uint256[] memory) { - return numbers; - } - - function getPerson() public pure returns (Person memory) { - return Person("Dim", 18); - } -} diff --git a/core/capabilities/ccip/ccip_integration_tests/helpers.go b/core/capabilities/ccip/ccip_integration_tests/helpers.go deleted file mode 100644 index 0cc06bc30d..0000000000 --- a/core/capabilities/ccip/ccip_integration_tests/helpers.go +++ /dev/null @@ -1,957 +0,0 @@ -package ccip_integration_tests - -import ( - "bytes" - "encoding/hex" - "math/big" - "sort" - "testing" - "time" - - "github.com/smartcontractkit/chainlink-ccip/chainconfig" - "github.com/smartcontractkit/chainlink-ccip/pluginconfig" - commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" - "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3" - "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccip_integration_tests/integrationhelpers" - cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/fee_quoter" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core" - - confighelper2 "github.com/smartcontractkit/libocr/offchainreporting2plus/confighelper" - "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3confighelper" - - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/ccip_config" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/maybe_revert_message_receiver" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/mock_rmn_contract" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/nonce_manager" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/ocr3_config_encoder" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/offramp" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/onramp" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_proxy_contract" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/token_admin_registry" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/weth9" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/link_token" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - - chainsel "github.com/smartcontractkit/chain-selectors" - - "github.com/stretchr/testify/require" -) - -var ( - homeChainID = chainsel.GETH_TESTNET.EvmChainID - ccipSendRequestedTopic = onramp.OnRampCCIPSendRequested{}.Topic() - commitReportAcceptedTopic = offramp.OffRampCommitReportAccepted{}.Topic() - executionStateChangedTopic = offramp.OffRampExecutionStateChanged{}.Topic() -) - -const ( - CapabilityLabelledName = "ccip" - CapabilityVersion = "v1.0.0" - NodeOperatorID = 1 - - // These constants drive what is set in the plugin offchain configs. - FirstBlockAge = 8 * time.Hour - RemoteGasPriceBatchWriteFrequency = 30 * time.Minute - BatchGasLimit = 6_500_000 - RelativeBoostPerWaitHour = 1.5 - InflightCacheExpiry = 10 * time.Minute - RootSnoozeTime = 30 * time.Minute - BatchingStrategyID = 0 - DeltaProgress = 30 * time.Second - DeltaResend = 10 * time.Second - DeltaInitial = 20 * time.Second - DeltaRound = 2 * time.Second - DeltaGrace = 2 * time.Second - DeltaCertifiedCommitRequest = 10 * time.Second - DeltaStage = 10 * time.Second - Rmax = 3 - MaxDurationQuery = 50 * time.Millisecond - MaxDurationObservation = 5 * time.Second - MaxDurationShouldAcceptAttestedReport = 10 * time.Second - MaxDurationShouldTransmitAcceptedReport = 10 * time.Second -) - -func e18Mult(amount uint64) *big.Int { - return new(big.Int).Mul(uBigInt(amount), uBigInt(1e18)) -} - -func uBigInt(i uint64) *big.Int { - return new(big.Int).SetUint64(i) -} - -type homeChain struct { - backend *backends.SimulatedBackend - owner *bind.TransactOpts - chainID uint64 - capabilityRegistry *kcr.CapabilitiesRegistry - ccipConfig *ccip_config.CCIPConfig -} - -type onchainUniverse struct { - backend *backends.SimulatedBackend - owner *bind.TransactOpts - chainID uint64 - linkToken *link_token.LinkToken - weth *weth9.WETH9 - router *router.Router - rmnProxy *rmn_proxy_contract.RMNProxyContract - rmn *mock_rmn_contract.MockRMNContract - onramp *onramp.OnRamp - offramp *offramp.OffRamp - priceRegistry *fee_quoter.FeeQuoter - tokenAdminRegistry *token_admin_registry.TokenAdminRegistry - nonceManager *nonce_manager.NonceManager - receiver *maybe_revert_message_receiver.MaybeRevertMessageReceiver -} - -type requestData struct { - destChainSelector uint64 - receiverAddress common.Address - data []byte -} - -func (u *onchainUniverse) SendCCIPRequests(t *testing.T, requestDatas []requestData) { - for _, reqData := range requestDatas { - msg := router.ClientEVM2AnyMessage{ - Receiver: common.LeftPadBytes(reqData.receiverAddress.Bytes(), 32), - Data: reqData.data, - TokenAmounts: nil, // TODO: no tokens for now - FeeToken: u.weth.Address(), - ExtraArgs: nil, // TODO: no extra args for now, falls back to default - } - fee, err := u.router.GetFee(&bind.CallOpts{Context: testutils.Context(t)}, reqData.destChainSelector, msg) - require.NoError(t, err) - _, err = u.weth.Deposit(&bind.TransactOpts{ - From: u.owner.From, - Signer: u.owner.Signer, - Value: fee, - }) - require.NoError(t, err) - u.backend.Commit() - _, err = u.weth.Approve(u.owner, u.router.Address(), fee) - require.NoError(t, err) - u.backend.Commit() - - t.Logf("Sending CCIP request from chain %d (selector %d) to chain selector %d", - u.chainID, getSelector(u.chainID), reqData.destChainSelector) - _, err = u.router.CcipSend(u.owner, reqData.destChainSelector, msg) - require.NoError(t, err) - u.backend.Commit() - } -} - -type chainBase struct { - backend *backends.SimulatedBackend - owner *bind.TransactOpts -} - -// createUniverses does the following: -// 1. Creates 1 home chain and `numChains`-1 non-home chains -// 2. Sets up home chain with the capability registry and the CCIP config contract -// 2. Deploys the CCIP contracts to all chains. -// 3. Sets up the initial configurations for the contracts on all chains. -// 4. Wires the chains together. -// -// Conceptually one universe is ONE chain with all the contracts deployed on it and all the dependencies initialized. -func createUniverses( - t *testing.T, - numChains int, -) (homeChainUni homeChain, universes map[uint64]onchainUniverse) { - chains := createChains(t, numChains) - - homeChainBase, ok := chains[homeChainID] - require.True(t, ok, "home chain backend not available") - // Set up home chain first - homeChainUniverse := setupHomeChain(t, homeChainBase.owner, homeChainBase.backend) - - // deploy the ccip contracts on all chains - universes = make(map[uint64]onchainUniverse) - for chainID, base := range chains { - owner := base.owner - backend := base.backend - // deploy the CCIP contracts - linkToken := deployLinkToken(t, owner, backend, chainID) - rmn := deployMockRMNContract(t, owner, backend, chainID) - rmnProxy := deployRMNProxyContract(t, owner, backend, rmn.Address(), chainID) - weth := deployWETHContract(t, owner, backend, chainID) - rout := deployRouter(t, owner, backend, weth.Address(), rmnProxy.Address(), chainID) - priceRegistry := deployPriceRegistry(t, owner, backend, linkToken.Address(), weth.Address(), big.NewInt(1e18), chainID) - tokenAdminRegistry := deployTokenAdminRegistry(t, owner, backend, chainID) - nonceManager := deployNonceManager(t, owner, backend, chainID) - - // ====================================================================== - // OnRamp - // ====================================================================== - onRampAddr, _, _, err := onramp.DeployOnRamp( - owner, - backend, - onramp.OnRampStaticConfig{ - ChainSelector: getSelector(chainID), - RmnProxy: rmnProxy.Address(), - NonceManager: nonceManager.Address(), - TokenAdminRegistry: tokenAdminRegistry.Address(), - }, - onramp.OnRampDynamicConfig{ - FeeQuoter: priceRegistry.Address(), - // `withdrawFeeTokens` onRamp function is not part of the message flow - // so we can set this to any address - FeeAggregator: testutils.NewAddress(), - }, - // Destination chain configs will be set up later once we have all chains - []onramp.OnRampDestChainConfigArgs{}, - ) - require.NoErrorf(t, err, "failed to deploy onramp on chain id %d", chainID) - backend.Commit() - onramp, err := onramp.NewOnRamp(onRampAddr, backend) - require.NoError(t, err) - - // ====================================================================== - // OffRamp - // ====================================================================== - offrampAddr, _, _, err := offramp.DeployOffRamp( - owner, - backend, - offramp.OffRampStaticConfig{ - ChainSelector: getSelector(chainID), - RmnProxy: rmnProxy.Address(), - TokenAdminRegistry: tokenAdminRegistry.Address(), - NonceManager: nonceManager.Address(), - }, - offramp.OffRampDynamicConfig{ - FeeQuoter: priceRegistry.Address(), - }, - // Source chain configs will be set up later once we have all chains - []offramp.OffRampSourceChainConfigArgs{}, - ) - require.NoErrorf(t, err, "failed to deploy offramp on chain id %d", chainID) - backend.Commit() - offramp, err := offramp.NewOffRamp(offrampAddr, backend) - require.NoError(t, err) - - receiverAddress, _, _, err := maybe_revert_message_receiver.DeployMaybeRevertMessageReceiver( - owner, - backend, - false, - ) - require.NoError(t, err, "failed to deploy MaybeRevertMessageReceiver on chain id %d", chainID) - backend.Commit() - receiver, err := maybe_revert_message_receiver.NewMaybeRevertMessageReceiver(receiverAddress, backend) - require.NoError(t, err) - - universe := onchainUniverse{ - backend: backend, - owner: owner, - chainID: chainID, - linkToken: linkToken, - weth: weth, - router: rout, - rmnProxy: rmnProxy, - rmn: rmn, - onramp: onramp, - offramp: offramp, - priceRegistry: priceRegistry, - tokenAdminRegistry: tokenAdminRegistry, - nonceManager: nonceManager, - receiver: receiver, - } - // Set up the initial configurations for the contracts - setupUniverseBasics(t, universe) - - universes[chainID] = universe - } - - // Once we have all chains created and contracts deployed, we can set up the initial configurations and wire chains together - connectUniverses(t, universes) - - // print out all contract addresses for debugging purposes - for chainID, uni := range universes { - t.Logf("Chain ID: %d\n Chain Selector: %d\n LinkToken: %s\n WETH: %s\n Router: %s\n RMNProxy: %s\n RMN: %s\n OnRamp: %s\n OffRamp: %s\n PriceRegistry: %s\n TokenAdminRegistry: %s\n NonceManager: %s\n", - chainID, - getSelector(chainID), - uni.linkToken.Address().Hex(), - uni.weth.Address().Hex(), - uni.router.Address().Hex(), - uni.rmnProxy.Address().Hex(), - uni.rmn.Address().Hex(), - uni.onramp.Address().Hex(), - uni.offramp.Address().Hex(), - uni.priceRegistry.Address().Hex(), - uni.tokenAdminRegistry.Address().Hex(), - uni.nonceManager.Address().Hex(), - ) - } - - // print out topic hashes of relevant events for debugging purposes - t.Logf("Topic hash of CommitReportAccepted: %s", commitReportAcceptedTopic.Hex()) - t.Logf("Topic hash of ExecutionStateChanged: %s", executionStateChangedTopic.Hex()) - t.Logf("Topic hash of CCIPSendRequested: %s", ccipSendRequestedTopic.Hex()) - - return homeChainUniverse, universes -} - -// Creates 1 home chain and `numChains`-1 non-home chains -func createChains(t *testing.T, numChains int) map[uint64]chainBase { - chains := make(map[uint64]chainBase) - - homeChainOwner := testutils.MustNewSimTransactor(t) - homeChainBackend := backends.NewSimulatedBackend(core.GenesisAlloc{ - homeChainOwner.From: core.GenesisAccount{ - Balance: assets.Ether(10_000).ToInt(), - }, - }, 30e6) - tweakChainTimestamp(t, homeChainBackend, FirstBlockAge) - - chains[homeChainID] = chainBase{ - owner: homeChainOwner, - backend: homeChainBackend, - } - - for chainID := chainsel.TEST_90000001.EvmChainID; len(chains) < numChains && chainID < chainsel.TEST_90000020.EvmChainID; chainID++ { - owner := testutils.MustNewSimTransactor(t) - backend := backends.NewSimulatedBackend(core.GenesisAlloc{ - owner.From: core.GenesisAccount{ - Balance: assets.Ether(10_000).ToInt(), - }, - }, 30e6) - - tweakChainTimestamp(t, backend, FirstBlockAge) - - chains[chainID] = chainBase{ - owner: owner, - backend: backend, - } - } - - return chains -} - -// CCIP relies on block timestamps, but SimulatedBackend uses by default clock starting from 1970-01-01 -// This trick is used to move the clock closer to the current time. We set first block to be X hours ago. -// Tests create plenty of transactions so this number can't be too low, every new block mined will tick the clock, -// if you mine more than "X hours" transactions, SimulatedBackend will panic because generated timestamps will be in the future. -func tweakChainTimestamp(t *testing.T, backend *backends.SimulatedBackend, tweak time.Duration) { - blockTime := time.Unix(int64(backend.Blockchain().CurrentHeader().Time), 0) - sinceBlockTime := time.Since(blockTime) - diff := sinceBlockTime - tweak - err := backend.AdjustTime(diff) - require.NoError(t, err, "unable to adjust time on simulated chain") - backend.Commit() - backend.Commit() -} - -func setupHomeChain(t *testing.T, owner *bind.TransactOpts, backend *backends.SimulatedBackend) homeChain { - // deploy the capability registry on the home chain - crAddress, _, _, err := kcr.DeployCapabilitiesRegistry(owner, backend) - require.NoError(t, err, "failed to deploy capability registry on home chain") - backend.Commit() - - capabilityRegistry, err := kcr.NewCapabilitiesRegistry(crAddress, backend) - require.NoError(t, err) - - ccAddress, _, _, err := ccip_config.DeployCCIPConfig(owner, backend, crAddress) - require.NoError(t, err) - backend.Commit() - - capabilityConfig, err := ccip_config.NewCCIPConfig(ccAddress, backend) - require.NoError(t, err) - - _, err = capabilityRegistry.AddCapabilities(owner, []kcr.CapabilitiesRegistryCapability{ - { - LabelledName: CapabilityLabelledName, - Version: CapabilityVersion, - CapabilityType: 2, // consensus. not used (?) - ResponseType: 0, // report. not used (?) - ConfigurationContract: ccAddress, - }, - }) - require.NoError(t, err, "failed to add capabilities to the capability registry") - backend.Commit() - - // Add NodeOperator, for simplicity we'll add one NodeOperator only - // First NodeOperator will have NodeOperatorId = 1 - _, err = capabilityRegistry.AddNodeOperators(owner, []kcr.CapabilitiesRegistryNodeOperator{ - { - Admin: owner.From, - Name: "NodeOperator", - }, - }) - require.NoError(t, err, "failed to add node operator to the capability registry") - backend.Commit() - - return homeChain{ - backend: backend, - owner: owner, - chainID: homeChainID, - capabilityRegistry: capabilityRegistry, - ccipConfig: capabilityConfig, - } -} - -func sortP2PIDS(p2pIDs [][32]byte) { - sort.Slice(p2pIDs, func(i, j int) bool { - return bytes.Compare(p2pIDs[i][:], p2pIDs[j][:]) < 0 - }) -} - -func (h *homeChain) AddNodes( - t *testing.T, - p2pIDs [][32]byte, - capabilityIDs [][32]byte, -) { - // Need to sort, otherwise _checkIsValidUniqueSubset onChain will fail - sortP2PIDS(p2pIDs) - var nodeParams []kcr.CapabilitiesRegistryNodeParams - for _, p2pID := range p2pIDs { - nodeParam := kcr.CapabilitiesRegistryNodeParams{ - NodeOperatorId: NodeOperatorID, - Signer: p2pID, // Not used in tests - P2pId: p2pID, - HashedCapabilityIds: capabilityIDs, - } - nodeParams = append(nodeParams, nodeParam) - } - _, err := h.capabilityRegistry.AddNodes(h.owner, nodeParams) - require.NoError(t, err, "failed to add node operator oracles") - h.backend.Commit() -} - -func AddChainConfig( - t *testing.T, - h homeChain, - chainSelector uint64, - p2pIDs [][32]byte, - f uint8, -) ccip_config.CCIPConfigTypesChainConfigInfo { - // Need to sort, otherwise _checkIsValidUniqueSubset onChain will fail - sortP2PIDS(p2pIDs) - // First Add ChainConfig that includes all p2pIDs as readers - encodedExtraChainConfig, err := chainconfig.EncodeChainConfig(chainconfig.ChainConfig{ - GasPriceDeviationPPB: ccipocr3.NewBigIntFromInt64(1000), - DAGasPriceDeviationPPB: ccipocr3.NewBigIntFromInt64(0), - FinalityDepth: 10, - OptimisticConfirmations: 1, - }) - require.NoError(t, err) - chainConfig := integrationhelpers.SetupConfigInfo(chainSelector, p2pIDs, f, encodedExtraChainConfig) - inputConfig := []ccip_config.CCIPConfigTypesChainConfigInfo{ - chainConfig, - } - _, err = h.ccipConfig.ApplyChainConfigUpdates(h.owner, nil, inputConfig) - require.NoError(t, err) - h.backend.Commit() - return chainConfig -} - -func (h *homeChain) AddDON( - t *testing.T, - ccipCapabilityID [32]byte, - chainSelector uint64, - uni onchainUniverse, - f uint8, - bootstrapP2PID [32]byte, - p2pIDs [][32]byte, - oracles []confighelper2.OracleIdentityExtra, -) { - // Get OCR3 Config from helper - var schedule []int - for range oracles { - schedule = append(schedule, 1) - } - - tabi, err := ocr3_config_encoder.IOCR3ConfigEncoderMetaData.GetAbi() - require.NoError(t, err) - - // Add DON on capability registry contract - var ocr3Configs []ocr3_config_encoder.CCIPConfigTypesOCR3Config - for _, pluginType := range []cctypes.PluginType{cctypes.PluginTypeCCIPCommit, cctypes.PluginTypeCCIPExec} { - var encodedOffchainConfig []byte - var err2 error - if pluginType == cctypes.PluginTypeCCIPCommit { - encodedOffchainConfig, err2 = pluginconfig.EncodeCommitOffchainConfig(pluginconfig.CommitOffchainConfig{ - RemoteGasPriceBatchWriteFrequency: *commonconfig.MustNewDuration(RemoteGasPriceBatchWriteFrequency), - // TODO: implement token price writes - // TokenPriceBatchWriteFrequency: *commonconfig.MustNewDuration(tokenPriceBatchWriteFrequency), - }) - require.NoError(t, err2) - } else { - encodedOffchainConfig, err2 = pluginconfig.EncodeExecuteOffchainConfig(pluginconfig.ExecuteOffchainConfig{ - BatchGasLimit: BatchGasLimit, - RelativeBoostPerWaitHour: RelativeBoostPerWaitHour, - MessageVisibilityInterval: *commonconfig.MustNewDuration(FirstBlockAge), - InflightCacheExpiry: *commonconfig.MustNewDuration(InflightCacheExpiry), - RootSnoozeTime: *commonconfig.MustNewDuration(RootSnoozeTime), - BatchingStrategyID: BatchingStrategyID, - }) - require.NoError(t, err2) - } - signers, transmitters, configF, _, offchainConfigVersion, offchainConfig, err2 := ocr3confighelper.ContractSetConfigArgsForTests( - DeltaProgress, - DeltaResend, - DeltaInitial, - DeltaRound, - DeltaGrace, - DeltaCertifiedCommitRequest, - DeltaStage, - Rmax, - schedule, - oracles, - encodedOffchainConfig, - MaxDurationQuery, - MaxDurationObservation, - MaxDurationShouldAcceptAttestedReport, - MaxDurationShouldTransmitAcceptedReport, - int(f), - []byte{}, // empty OnChainConfig - ) - require.NoError(t, err2, "failed to create contract config") - - signersBytes := make([][]byte, len(signers)) - for i, signer := range signers { - signersBytes[i] = signer - } - - transmittersBytes := make([][]byte, len(transmitters)) - for i, transmitter := range transmitters { - // anotherErr because linting doesn't want to shadow err - parsed, anotherErr := common.ParseHexOrString(string(transmitter)) - require.NoError(t, anotherErr) - transmittersBytes[i] = parsed - } - - ocr3Configs = append(ocr3Configs, ocr3_config_encoder.CCIPConfigTypesOCR3Config{ - PluginType: uint8(pluginType), - ChainSelector: chainSelector, - F: configF, - OffchainConfigVersion: offchainConfigVersion, - OfframpAddress: uni.offramp.Address().Bytes(), - BootstrapP2PIds: [][32]byte{bootstrapP2PID}, - P2pIds: p2pIDs, - Signers: signersBytes, - Transmitters: transmittersBytes, - OffchainConfig: offchainConfig, - }) - } - - encodedCall, err := tabi.Pack("exposeOCR3Config", ocr3Configs) - require.NoError(t, err) - - // Trim first four bytes to remove function selector. - encodedConfigs := encodedCall[4:] - - // commit so that we have an empty block to filter events from - h.backend.Commit() - - _, err = h.capabilityRegistry.AddDON(h.owner, p2pIDs, []kcr.CapabilitiesRegistryCapabilityConfiguration{ - { - CapabilityId: ccipCapabilityID, - Config: encodedConfigs, - }, - }, false, false, f) - require.NoError(t, err) - h.backend.Commit() - - endBlock := h.backend.Blockchain().CurrentBlock().Number.Uint64() - iter, err := h.capabilityRegistry.FilterConfigSet(&bind.FilterOpts{ - Start: h.backend.Blockchain().CurrentBlock().Number.Uint64() - 1, - End: &endBlock, - }) - require.NoError(t, err, "failed to filter config set events") - var donID uint32 - for iter.Next() { - donID = iter.Event.DonId - break - } - require.NotZero(t, donID, "failed to get donID from config set event") - - var signerAddresses []common.Address - for _, oracle := range oracles { - signerAddresses = append(signerAddresses, common.BytesToAddress(oracle.OnchainPublicKey)) - } - - var transmitterAddresses []common.Address - for _, oracle := range oracles { - transmitterAddresses = append(transmitterAddresses, common.HexToAddress(string(oracle.TransmitAccount))) - } - - // get the config digest from the ccip config contract and set config on the offramp. - var offrampOCR3Configs []offramp.MultiOCR3BaseOCRConfigArgs - for _, pluginType := range []cctypes.PluginType{cctypes.PluginTypeCCIPCommit, cctypes.PluginTypeCCIPExec} { - ocrConfig, err1 := h.ccipConfig.GetOCRConfig(&bind.CallOpts{ - Context: testutils.Context(t), - }, donID, uint8(pluginType)) - require.NoError(t, err1, "failed to get OCR3 config from ccip config contract") - require.Len(t, ocrConfig, 1, "expected exactly one OCR3 config") - offrampOCR3Configs = append(offrampOCR3Configs, offramp.MultiOCR3BaseOCRConfigArgs{ - ConfigDigest: ocrConfig[0].ConfigDigest, - OcrPluginType: uint8(pluginType), - F: f, - IsSignatureVerificationEnabled: pluginType == cctypes.PluginTypeCCIPCommit, - Signers: signerAddresses, - Transmitters: transmitterAddresses, - }) - } - - uni.backend.Commit() - - _, err = uni.offramp.SetOCR3Configs(uni.owner, offrampOCR3Configs) - require.NoError(t, err, "failed to set ocr3 configs on offramp") - uni.backend.Commit() - - for _, pluginType := range []cctypes.PluginType{cctypes.PluginTypeCCIPCommit, cctypes.PluginTypeCCIPExec} { - ocrConfig, err := uni.offramp.LatestConfigDetails(&bind.CallOpts{ - Context: testutils.Context(t), - }, uint8(pluginType)) - require.NoError(t, err, "failed to get latest commit OCR3 config") - require.Equalf(t, offrampOCR3Configs[pluginType].ConfigDigest, ocrConfig.ConfigInfo.ConfigDigest, "%s OCR3 config digest mismatch", pluginType.String()) - require.Equalf(t, offrampOCR3Configs[pluginType].F, ocrConfig.ConfigInfo.F, "%s OCR3 config F mismatch", pluginType.String()) - require.Equalf(t, offrampOCR3Configs[pluginType].IsSignatureVerificationEnabled, ocrConfig.ConfigInfo.IsSignatureVerificationEnabled, "%s OCR3 config signature verification mismatch", pluginType.String()) - if pluginType == cctypes.PluginTypeCCIPCommit { - // only commit will set signers, exec doesn't need them. - require.Equalf(t, offrampOCR3Configs[pluginType].Signers, ocrConfig.Signers, "%s OCR3 config signers mismatch", pluginType.String()) - } - require.Equalf(t, offrampOCR3Configs[pluginType].Transmitters, ocrConfig.Transmitters, "%s OCR3 config transmitters mismatch", pluginType.String()) - } - - t.Logf("set ocr3 config on the offramp, signers: %+v, transmitters: %+v", signerAddresses, transmitterAddresses) -} - -func connectUniverses( - t *testing.T, - universes map[uint64]onchainUniverse, -) { - for _, uni := range universes { - wireRouter(t, uni, universes) - wirePriceRegistry(t, uni, universes) - wireOnRamp(t, uni, universes) - wireOffRamp(t, uni, universes) - initRemoteChainsGasPrices(t, uni, universes) - } -} - -// setupUniverseBasics sets up the initial configurations for the CCIP contracts on a single chain. -// 1. Mint 1000 LINK to the owner -// 2. Set the price registry with local token prices -// 3. Authorize the onRamp and offRamp on the nonce manager -func setupUniverseBasics(t *testing.T, uni onchainUniverse) { - // ============================================================================= - // Universe specific updates/configs - // These updates are specific to each universe and are set up here - // These updates don't depend on other chains - // ============================================================================= - owner := uni.owner - // ============================================================================= - // Mint 1000 LINK to owner - // ============================================================================= - _, err := uni.linkToken.GrantMintRole(owner, owner.From) - require.NoError(t, err) - _, err = uni.linkToken.Mint(owner, owner.From, e18Mult(1000)) - require.NoError(t, err) - uni.backend.Commit() - - // ============================================================================= - // Price updates for tokens - // These are the prices of the fee tokens of local chain in USD - // ============================================================================= - tokenPriceUpdates := []fee_quoter.InternalTokenPriceUpdate{ - { - SourceToken: uni.linkToken.Address(), - UsdPerToken: e18Mult(20), - }, - { - SourceToken: uni.weth.Address(), - UsdPerToken: e18Mult(4000), - }, - } - _, err = uni.priceRegistry.UpdatePrices(owner, fee_quoter.InternalPriceUpdates{ - TokenPriceUpdates: tokenPriceUpdates, - }) - require.NoErrorf(t, err, "failed to update prices in price registry on chain id %d", uni.chainID) - uni.backend.Commit() - - _, err = uni.priceRegistry.ApplyAuthorizedCallerUpdates(owner, fee_quoter.AuthorizedCallersAuthorizedCallerArgs{ - AddedCallers: []common.Address{ - uni.offramp.Address(), - }, - }) - require.NoError(t, err, "failed to authorize offramp on price registry") - uni.backend.Commit() - - // ============================================================================= - // Authorize OnRamp & OffRamp on NonceManager - // Otherwise the onramp will not be able to call the nonceManager to get next Nonce - // ============================================================================= - authorizedCallersAuthorizedCallerArgs := nonce_manager.AuthorizedCallersAuthorizedCallerArgs{ - AddedCallers: []common.Address{ - uni.onramp.Address(), - uni.offramp.Address(), - }, - } - _, err = uni.nonceManager.ApplyAuthorizedCallerUpdates(owner, authorizedCallersAuthorizedCallerArgs) - require.NoError(t, err) - uni.backend.Commit() -} - -// As we can't change router contract. The contract was expecting onRamp and offRamp per lane and not per chain -// In the new architecture we have only one onRamp and one offRamp per chain. -// hence we add the mapping for all remote chains to the onRamp/offRamp contract of the local chain -func wireRouter(t *testing.T, uni onchainUniverse, universes map[uint64]onchainUniverse) { - owner := uni.owner - var ( - routerOnrampUpdates []router.RouterOnRamp - routerOfframpUpdates []router.RouterOffRamp - ) - for remoteChainID := range universes { - if remoteChainID == uni.chainID { - continue - } - routerOnrampUpdates = append(routerOnrampUpdates, router.RouterOnRamp{ - DestChainSelector: getSelector(remoteChainID), - OnRamp: uni.onramp.Address(), - }) - routerOfframpUpdates = append(routerOfframpUpdates, router.RouterOffRamp{ - SourceChainSelector: getSelector(remoteChainID), - OffRamp: uni.offramp.Address(), - }) - } - _, err := uni.router.ApplyRampUpdates(owner, routerOnrampUpdates, []router.RouterOffRamp{}, routerOfframpUpdates) - require.NoErrorf(t, err, "failed to apply ramp updates on router on chain id %d", uni.chainID) - uni.backend.Commit() -} - -// Setting OnRampDestChainConfigs -func wirePriceRegistry(t *testing.T, uni onchainUniverse, universes map[uint64]onchainUniverse) { - owner := uni.owner - var priceRegistryDestChainConfigArgs []fee_quoter.FeeQuoterDestChainConfigArgs - for remoteChainID := range universes { - if remoteChainID == uni.chainID { - continue - } - priceRegistryDestChainConfigArgs = append(priceRegistryDestChainConfigArgs, fee_quoter.FeeQuoterDestChainConfigArgs{ - DestChainSelector: getSelector(remoteChainID), - DestChainConfig: defaultPriceRegistryDestChainConfig(t), - }) - } - _, err := uni.priceRegistry.ApplyDestChainConfigUpdates(owner, priceRegistryDestChainConfigArgs) - require.NoErrorf(t, err, "failed to apply dest chain config updates on price registry on chain id %d", uni.chainID) - uni.backend.Commit() -} - -// Setting OnRampDestChainConfigs -func wireOnRamp(t *testing.T, uni onchainUniverse, universes map[uint64]onchainUniverse) { - owner := uni.owner - var onrampSourceChainConfigArgs []onramp.OnRampDestChainConfigArgs - for remoteChainID := range universes { - if remoteChainID == uni.chainID { - continue - } - onrampSourceChainConfigArgs = append(onrampSourceChainConfigArgs, onramp.OnRampDestChainConfigArgs{ - DestChainSelector: getSelector(remoteChainID), - Router: uni.router.Address(), - }) - } - _, err := uni.onramp.ApplyDestChainConfigUpdates(owner, onrampSourceChainConfigArgs) - require.NoErrorf(t, err, "failed to apply dest chain config updates on onramp with chain id %d", uni.chainID) - uni.backend.Commit() -} - -// Setting OffRampSourceChainConfigs -func wireOffRamp(t *testing.T, uni onchainUniverse, universes map[uint64]onchainUniverse) { - owner := uni.owner - var offrampSourceChainConfigArgs []offramp.OffRampSourceChainConfigArgs - for remoteChainID, remoteUniverse := range universes { - if remoteChainID == uni.chainID { - continue - } - offrampSourceChainConfigArgs = append(offrampSourceChainConfigArgs, offramp.OffRampSourceChainConfigArgs{ - SourceChainSelector: getSelector(remoteChainID), - IsEnabled: true, - Router: uni.router.Address(), - OnRamp: remoteUniverse.onramp.Address().Bytes(), - }) - } - _, err := uni.offramp.ApplySourceChainConfigUpdates(owner, offrampSourceChainConfigArgs) - require.NoErrorf(t, err, "failed to apply source chain config updates on offramp on chain id %d", uni.chainID) - uni.backend.Commit() - for remoteChainID, remoteUniverse := range universes { - if remoteChainID == uni.chainID { - continue - } - sourceCfg, err2 := uni.offramp.GetSourceChainConfig(&bind.CallOpts{}, getSelector(remoteChainID)) - require.NoError(t, err2) - require.True(t, sourceCfg.IsEnabled, "source chain config should be enabled") - require.Equal(t, remoteUniverse.onramp.Address(), common.BytesToAddress(sourceCfg.OnRamp), "source chain config onRamp address mismatch") - } -} - -func getSelector(chainID uint64) uint64 { - selector, err := chainsel.SelectorFromChainId(chainID) - if err != nil { - panic(err) - } - return selector -} - -// initRemoteChainsGasPrices sets the gas prices for all chains except the local chain in the local price registry -func initRemoteChainsGasPrices(t *testing.T, uni onchainUniverse, universes map[uint64]onchainUniverse) { - var gasPriceUpdates []fee_quoter.InternalGasPriceUpdate - for remoteChainID := range universes { - if remoteChainID == uni.chainID { - continue - } - gasPriceUpdates = append(gasPriceUpdates, - fee_quoter.InternalGasPriceUpdate{ - DestChainSelector: getSelector(remoteChainID), - UsdPerUnitGas: big.NewInt(2e12), - }, - ) - } - _, err := uni.priceRegistry.UpdatePrices(uni.owner, fee_quoter.InternalPriceUpdates{ - GasPriceUpdates: gasPriceUpdates, - }) - require.NoError(t, err) -} - -func defaultPriceRegistryDestChainConfig(t *testing.T) fee_quoter.FeeQuoterDestChainConfig { - // https://github.com/smartcontractkit/ccip/blob/c4856b64bd766f1ddbaf5d13b42d3c4b12efde3a/contracts/src/v0.8/ccip/libraries/Internal.sol#L337-L337 - /* - ```Solidity - // bytes4(keccak256("CCIP ChainFamilySelector EVM")) - bytes4 public constant CHAIN_FAMILY_SELECTOR_EVM = 0x2812d52c; - ``` - */ - evmFamilySelector, err := hex.DecodeString("2812d52c") - require.NoError(t, err) - return fee_quoter.FeeQuoterDestChainConfig{ - IsEnabled: true, - MaxNumberOfTokensPerMsg: 10, - MaxDataBytes: 256, - MaxPerMsgGasLimit: 3_000_000, - DestGasOverhead: 50_000, - DefaultTokenFeeUSDCents: 1, - DestGasPerPayloadByte: 10, - DestDataAvailabilityOverheadGas: 0, - DestGasPerDataAvailabilityByte: 100, - DestDataAvailabilityMultiplierBps: 1, - DefaultTokenDestGasOverhead: 125_000, - DefaultTxGasLimit: 200_000, - GasMultiplierWeiPerEth: 1, - NetworkFeeUSDCents: 1, - ChainFamilySelector: [4]byte(evmFamilySelector), - } -} - -func deployLinkToken(t *testing.T, owner *bind.TransactOpts, backend *backends.SimulatedBackend, chainID uint64) *link_token.LinkToken { - linkAddr, _, _, err := link_token.DeployLinkToken(owner, backend) - require.NoErrorf(t, err, "failed to deploy link token on chain id %d", chainID) - backend.Commit() - linkToken, err := link_token.NewLinkToken(linkAddr, backend) - require.NoError(t, err) - return linkToken -} - -func deployMockRMNContract(t *testing.T, owner *bind.TransactOpts, backend *backends.SimulatedBackend, chainID uint64) *mock_rmn_contract.MockRMNContract { - rmnAddr, _, _, err := mock_rmn_contract.DeployMockRMNContract(owner, backend) - require.NoErrorf(t, err, "failed to deploy mock arm on chain id %d", chainID) - backend.Commit() - rmn, err := mock_rmn_contract.NewMockRMNContract(rmnAddr, backend) - require.NoError(t, err) - return rmn -} - -func deployRMNProxyContract(t *testing.T, owner *bind.TransactOpts, backend *backends.SimulatedBackend, rmnAddr common.Address, chainID uint64) *rmn_proxy_contract.RMNProxyContract { - rmnProxyAddr, _, _, err := rmn_proxy_contract.DeployRMNProxyContract(owner, backend, rmnAddr) - require.NoErrorf(t, err, "failed to deploy arm proxy on chain id %d", chainID) - backend.Commit() - rmnProxy, err := rmn_proxy_contract.NewRMNProxyContract(rmnProxyAddr, backend) - require.NoError(t, err) - return rmnProxy -} - -func deployWETHContract(t *testing.T, owner *bind.TransactOpts, backend *backends.SimulatedBackend, chainID uint64) *weth9.WETH9 { - wethAddr, _, _, err := weth9.DeployWETH9(owner, backend) - require.NoErrorf(t, err, "failed to deploy weth contract on chain id %d", chainID) - backend.Commit() - weth, err := weth9.NewWETH9(wethAddr, backend) - require.NoError(t, err) - return weth -} - -func deployRouter(t *testing.T, owner *bind.TransactOpts, backend *backends.SimulatedBackend, wethAddr, rmnProxyAddr common.Address, chainID uint64) *router.Router { - routerAddr, _, _, err := router.DeployRouter(owner, backend, wethAddr, rmnProxyAddr) - require.NoErrorf(t, err, "failed to deploy router on chain id %d", chainID) - backend.Commit() - rout, err := router.NewRouter(routerAddr, backend) - require.NoError(t, err) - return rout -} - -func deployPriceRegistry( - t *testing.T, - owner *bind.TransactOpts, - backend *backends.SimulatedBackend, - linkAddr, - wethAddr common.Address, - maxFeeJuelsPerMsg *big.Int, - chainID uint64, -) *fee_quoter.FeeQuoter { - priceRegistryAddr, _, _, err := fee_quoter.DeployFeeQuoter( - owner, - backend, - fee_quoter.FeeQuoterStaticConfig{ - MaxFeeJuelsPerMsg: maxFeeJuelsPerMsg, - LinkToken: linkAddr, - StalenessThreshold: 24 * 60 * 60, // 24 hours - }, - []common.Address{ - owner.From, // owner can update prices in this test - }, // price updaters, will be set to offramp later - []common.Address{linkAddr, wethAddr}, // fee tokens - // empty for now, need to fill in when testing token transfers - []fee_quoter.FeeQuoterTokenPriceFeedUpdate{}, - // empty for now, need to fill in when testing token transfers - []fee_quoter.FeeQuoterTokenTransferFeeConfigArgs{}, - []fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthArgs{ - { - PremiumMultiplierWeiPerEth: 9e17, // 0.9 ETH - Token: linkAddr, - }, - { - PremiumMultiplierWeiPerEth: 1e18, - Token: wethAddr, - }, - }, - // Destination chain configs will be set up later once we have all chains - []fee_quoter.FeeQuoterDestChainConfigArgs{}, - ) - require.NoErrorf(t, err, "failed to deploy price registry on chain id %d", chainID) - backend.Commit() - priceRegistry, err := fee_quoter.NewFeeQuoter(priceRegistryAddr, backend) - require.NoError(t, err) - return priceRegistry -} - -func deployTokenAdminRegistry(t *testing.T, owner *bind.TransactOpts, backend *backends.SimulatedBackend, chainID uint64) *token_admin_registry.TokenAdminRegistry { - tarAddr, _, _, err := token_admin_registry.DeployTokenAdminRegistry(owner, backend) - require.NoErrorf(t, err, "failed to deploy token admin registry on chain id %d", chainID) - backend.Commit() - tokenAdminRegistry, err := token_admin_registry.NewTokenAdminRegistry(tarAddr, backend) - require.NoError(t, err) - return tokenAdminRegistry -} - -func deployNonceManager(t *testing.T, owner *bind.TransactOpts, backend *backends.SimulatedBackend, chainID uint64) *nonce_manager.NonceManager { - nonceManagerAddr, _, _, err := nonce_manager.DeployNonceManager(owner, backend, []common.Address{owner.From}) - require.NoErrorf(t, err, "failed to deploy nonce_manager on chain id %d", chainID) - backend.Commit() - nonceManager, err := nonce_manager.NewNonceManager(nonceManagerAddr, backend) - require.NoError(t, err) - return nonceManager -} diff --git a/core/capabilities/ccip/ccip_integration_tests/home_chain_test.go b/core/capabilities/ccip/ccip_integration_tests/home_chain_test.go deleted file mode 100644 index c8b261eba1..0000000000 --- a/core/capabilities/ccip/ccip_integration_tests/home_chain_test.go +++ /dev/null @@ -1,113 +0,0 @@ -package ccip_integration_tests - -import ( - "math/big" - "testing" - "time" - - "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccip_integration_tests/integrationhelpers" - - mapset "github.com/deckarep/golang-set/v2" - "github.com/onsi/gomega" - - libocrtypes "github.com/smartcontractkit/libocr/ragep2p/types" - - "github.com/smartcontractkit/chainlink-ccip/chainconfig" - ccipreader "github.com/smartcontractkit/chainlink-ccip/pkg/reader" - - cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3" - - "github.com/stretchr/testify/require" - - capcfg "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/ccip_config" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - "github.com/smartcontractkit/chainlink/v2/core/logger" -) - -func TestHomeChainReader(t *testing.T) { - ctx := testutils.Context(t) - lggr := logger.TestLogger(t) - uni := integrationhelpers.NewTestUniverse(ctx, t, lggr) - // We need 3*f + 1 p2pIDs to have enough nodes to bootstrap - var arr []int64 - n := int(integrationhelpers.FChainA*3 + 1) - for i := 0; i <= n; i++ { - arr = append(arr, int64(i)) - } - p2pIDs := integrationhelpers.P2pIDsFromInts(arr) - uni.AddCapability(p2pIDs) - - //==============================Apply configs to Capability Contract================================= - encodedChainConfig, err := chainconfig.EncodeChainConfig(chainconfig.ChainConfig{ - GasPriceDeviationPPB: cciptypes.NewBigIntFromInt64(1000), - DAGasPriceDeviationPPB: cciptypes.NewBigIntFromInt64(1_000_000), - FinalityDepth: -1, - OptimisticConfirmations: 1, - }) - require.NoError(t, err) - inputConfig := []capcfg.CCIPConfigTypesChainConfigInfo{ - integrationhelpers.SetupConfigInfo(integrationhelpers.ChainA, p2pIDs, integrationhelpers.FChainA, encodedChainConfig), - integrationhelpers.SetupConfigInfo(integrationhelpers.ChainB, p2pIDs[1:], integrationhelpers.FChainB, encodedChainConfig), - integrationhelpers.SetupConfigInfo(integrationhelpers.ChainC, p2pIDs[2:], integrationhelpers.FChainC, encodedChainConfig), - } - _, err = uni.CcipCfg.ApplyChainConfigUpdates(uni.Transactor, nil, inputConfig) - require.NoError(t, err) - uni.Backend.Commit() - chainConfigInfos, err := uni.CcipCfg.GetAllChainConfigs(nil, big.NewInt(0), big.NewInt(100)) - require.NoError(t, err) - require.Len(t, chainConfigInfos, len(inputConfig)) - - // Wait for the home chain reader to read the expected amount of chain configs. - gomega.NewWithT(t).Eventually(func() bool { - configs, _ := uni.HomeChainReader.GetAllChainConfigs() - return len(configs) == len(inputConfig) - }, testutils.WaitTimeout(t), 1*time.Second).Should(gomega.BeTrue()) - - t.Logf("homchain reader is ready") - - //================================Test HomeChain Reader=============================== - expectedChainConfigs := map[cciptypes.ChainSelector]ccipreader.ChainConfig{} - for _, c := range inputConfig { - expectedChainConfigs[cciptypes.ChainSelector(c.ChainSelector)] = ccipreader.ChainConfig{ - FChain: int(c.ChainConfig.FChain), - SupportedNodes: toPeerIDs(c.ChainConfig.Readers), - Config: mustDecodeChainConfig(t, c.ChainConfig.Config), - } - } - - configs, err := uni.HomeChainReader.GetAllChainConfigs() - require.NoError(t, err) - - require.Equal(t, expectedChainConfigs, configs) - - // Remove chain C from the chain configs and expect the home chain reader to - // update its state accordingly. - _, err = uni.CcipCfg.ApplyChainConfigUpdates(uni.Transactor, []uint64{integrationhelpers.ChainC}, nil) - require.NoError(t, err) - uni.Backend.Commit() - - // Wait for the home chain reader to read the expected amount of chain configs. - gomega.NewWithT(t).Eventually(func() bool { - chainConfigs, _ := uni.HomeChainReader.GetAllChainConfigs() - return len(chainConfigs) == len(inputConfig)-1 - }, testutils.WaitTimeout(t), 1*time.Second).Should(gomega.BeTrue()) - configs, err = uni.HomeChainReader.GetAllChainConfigs() - require.NoError(t, err) - - delete(expectedChainConfigs, cciptypes.ChainSelector(integrationhelpers.ChainC)) - require.Equal(t, expectedChainConfigs, configs) -} - -func toPeerIDs(readers [][32]byte) mapset.Set[libocrtypes.PeerID] { - peerIDs := mapset.NewSet[libocrtypes.PeerID]() - for _, r := range readers { - peerIDs.Add(r) - } - return peerIDs -} - -func mustDecodeChainConfig(t *testing.T, encodedChainConfig []byte) chainconfig.ChainConfig { - chainConfig, err := chainconfig.DecodeChainConfig(encodedChainConfig) - require.NoError(t, err) - return chainConfig -} diff --git a/core/capabilities/ccip/ccip_integration_tests/integrationhelpers/integration_helpers.go b/core/capabilities/ccip/ccip_integration_tests/integrationhelpers/integration_helpers.go deleted file mode 100644 index 4b6a0c84e6..0000000000 --- a/core/capabilities/ccip/ccip_integration_tests/integrationhelpers/integration_helpers.go +++ /dev/null @@ -1,305 +0,0 @@ -package integrationhelpers - -import ( - "context" - "encoding/json" - "fmt" - "math/big" - "sort" - "testing" - "time" - - configsevm "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/configs/evm" - cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core" - - "github.com/smartcontractkit/chainlink-ccip/pkg/consts" - ccipreader "github.com/smartcontractkit/chainlink-ccip/pkg/reader" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/ccip_config" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/ocr3_config_encoder" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" - - "github.com/smartcontractkit/chainlink-common/pkg/types" - - "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" - "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" - evmrelaytypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" -) - -const chainID = 1337 - -func NewReader( - t *testing.T, - logPoller logpoller.LogPoller, - headTracker logpoller.HeadTracker, - client client.Client, - address common.Address, - chainReaderConfig evmrelaytypes.ChainReaderConfig, -) types.ContractReader { - cr, err := evm.NewChainReaderService(testutils.Context(t), logger.TestLogger(t), logPoller, headTracker, client, chainReaderConfig) - require.NoError(t, err) - err = cr.Bind(testutils.Context(t), []types.BoundContract{ - { - Address: address.String(), - Name: consts.ContractNameCCIPConfig, - }, - }) - require.NoError(t, err) - require.NoError(t, cr.Start(testutils.Context(t))) - for { - if err := cr.Ready(); err == nil { - break - } - } - - return cr -} - -const ( - ChainA uint64 = 1 - FChainA uint8 = 1 - - ChainB uint64 = 2 - FChainB uint8 = 2 - - ChainC uint64 = 3 - FChainC uint8 = 3 - - CcipCapabilityLabelledName = "ccip" - CcipCapabilityVersion = "v1.0" -) - -type TestUniverse struct { - Transactor *bind.TransactOpts - Backend *backends.SimulatedBackend - CapReg *kcr.CapabilitiesRegistry - CcipCfg *ccip_config.CCIPConfig - TestingT *testing.T - LogPoller logpoller.LogPoller - HeadTracker logpoller.HeadTracker - SimClient client.Client - HomeChainReader ccipreader.HomeChain -} - -func NewTestUniverse(ctx context.Context, t *testing.T, lggr logger.Logger) TestUniverse { - transactor := testutils.MustNewSimTransactor(t) - backend := backends.NewSimulatedBackend(core.GenesisAlloc{ - transactor.From: {Balance: assets.Ether(1000).ToInt()}, - }, 30e6) - - crAddress, _, _, err := kcr.DeployCapabilitiesRegistry(transactor, backend) - require.NoError(t, err) - backend.Commit() - - capReg, err := kcr.NewCapabilitiesRegistry(crAddress, backend) - require.NoError(t, err) - - ccAddress, _, _, err := ccip_config.DeployCCIPConfig(transactor, backend, crAddress) - require.NoError(t, err) - backend.Commit() - - cc, err := ccip_config.NewCCIPConfig(ccAddress, backend) - require.NoError(t, err) - - db := pgtest.NewSqlxDB(t) - lpOpts := logpoller.Opts{ - PollPeriod: time.Millisecond, - FinalityDepth: 0, - BackfillBatchSize: 10, - RpcBatchSize: 10, - KeepFinalizedBlocksDepth: 100000, - } - cl := client.NewSimulatedBackendClient(t, backend, big.NewInt(chainID)) - headTracker := headtracker.NewSimulatedHeadTracker(cl, lpOpts.UseFinalityTag, lpOpts.FinalityDepth) - if lpOpts.PollPeriod == 0 { - lpOpts.PollPeriod = 1 * time.Hour - } - lp := logpoller.NewLogPoller(logpoller.NewORM(big.NewInt(chainID), db, lggr), cl, logger.NullLogger, headTracker, lpOpts) - require.NoError(t, lp.Start(ctx)) - t.Cleanup(func() { require.NoError(t, lp.Close()) }) - - hcr := NewHomeChainReader(t, lp, headTracker, cl, ccAddress) - return TestUniverse{ - Transactor: transactor, - Backend: backend, - CapReg: capReg, - CcipCfg: cc, - TestingT: t, - SimClient: cl, - LogPoller: lp, - HeadTracker: headTracker, - HomeChainReader: hcr, - } -} - -func (t TestUniverse) NewContractReader(ctx context.Context, cfg []byte) (types.ContractReader, error) { - var config evmrelaytypes.ChainReaderConfig - err := json.Unmarshal(cfg, &config) - require.NoError(t.TestingT, err) - return evm.NewChainReaderService(ctx, logger.TestLogger(t.TestingT), t.LogPoller, t.HeadTracker, t.SimClient, config) -} - -func P2pIDsFromInts(ints []int64) [][32]byte { - var p2pIDs [][32]byte - for _, i := range ints { - p2pID := p2pkey.MustNewV2XXXTestingOnly(big.NewInt(i)).PeerID() - p2pIDs = append(p2pIDs, p2pID) - } - sort.Slice(p2pIDs, func(i, j int) bool { - for k := 0; k < 32; k++ { - if p2pIDs[i][k] < p2pIDs[j][k] { - return true - } else if p2pIDs[i][k] > p2pIDs[j][k] { - return false - } - } - return false - }) - return p2pIDs -} - -func (t *TestUniverse) AddCapability(p2pIDs [][32]byte) { - _, err := t.CapReg.AddCapabilities(t.Transactor, []kcr.CapabilitiesRegistryCapability{ - { - LabelledName: CcipCapabilityLabelledName, - Version: CcipCapabilityVersion, - CapabilityType: 0, - ResponseType: 0, - ConfigurationContract: t.CcipCfg.Address(), - }, - }) - require.NoError(t.TestingT, err, "failed to add capability to registry") - t.Backend.Commit() - - ccipCapabilityID, err := t.CapReg.GetHashedCapabilityId(nil, CcipCapabilityLabelledName, CcipCapabilityVersion) - require.NoError(t.TestingT, err) - - for i := 0; i < len(p2pIDs); i++ { - _, err = t.CapReg.AddNodeOperators(t.Transactor, []kcr.CapabilitiesRegistryNodeOperator{ - { - Admin: t.Transactor.From, - Name: fmt.Sprintf("nop-%d", i), - }, - }) - require.NoError(t.TestingT, err) - t.Backend.Commit() - - // get the node operator id from the event - it, err := t.CapReg.FilterNodeOperatorAdded(nil, nil, nil) - require.NoError(t.TestingT, err) - var nodeOperatorID uint32 - for it.Next() { - if it.Event.Name == fmt.Sprintf("nop-%d", i) { - nodeOperatorID = it.Event.NodeOperatorId - break - } - } - require.NotZero(t.TestingT, nodeOperatorID) - - _, err = t.CapReg.AddNodes(t.Transactor, []kcr.CapabilitiesRegistryNodeParams{ - { - NodeOperatorId: nodeOperatorID, - Signer: testutils.Random32Byte(), - P2pId: p2pIDs[i], - HashedCapabilityIds: [][32]byte{ccipCapabilityID}, - }, - }) - require.NoError(t.TestingT, err) - t.Backend.Commit() - - // verify that the node was added successfully - nodeInfo, err := t.CapReg.GetNode(nil, p2pIDs[i]) - require.NoError(t.TestingT, err) - - require.Equal(t.TestingT, nodeOperatorID, nodeInfo.NodeOperatorId) - require.Equal(t.TestingT, p2pIDs[i][:], nodeInfo.P2pId[:]) - } -} - -func NewHomeChainReader(t *testing.T, logPoller logpoller.LogPoller, headTracker logpoller.HeadTracker, client client.Client, ccAddress common.Address) ccipreader.HomeChain { - cr := NewReader(t, logPoller, headTracker, client, ccAddress, configsevm.HomeChainReaderConfigRaw) - - hcr := ccipreader.NewHomeChainReader(cr, logger.TestLogger(t), 500*time.Millisecond, types.BoundContract{ - Address: ccAddress.String(), - Name: consts.ContractNameCCIPConfig, - }) - require.NoError(t, hcr.Start(testutils.Context(t))) - t.Cleanup(func() { require.NoError(t, hcr.Close()) }) - - return hcr -} - -func (t *TestUniverse) AddDONToRegistry( - ccipCapabilityID [32]byte, - chainSelector uint64, - f uint8, - bootstrapP2PID [32]byte, - p2pIDs [][32]byte, -) { - tabi, err := ocr3_config_encoder.IOCR3ConfigEncoderMetaData.GetAbi() - require.NoError(t.TestingT, err) - - var ( - signers [][]byte - transmitters [][]byte - ) - for range p2pIDs { - signers = append(signers, testutils.NewAddress().Bytes()) - transmitters = append(transmitters, testutils.NewAddress().Bytes()) - } - - var ocr3Configs []ocr3_config_encoder.CCIPConfigTypesOCR3Config - for _, pluginType := range []cctypes.PluginType{cctypes.PluginTypeCCIPCommit, cctypes.PluginTypeCCIPExec} { - ocr3Configs = append(ocr3Configs, ocr3_config_encoder.CCIPConfigTypesOCR3Config{ - PluginType: uint8(pluginType), - ChainSelector: chainSelector, - F: f, - OffchainConfigVersion: 30, - OfframpAddress: testutils.NewAddress().Bytes(), - BootstrapP2PIds: [][32]byte{bootstrapP2PID}, - P2pIds: p2pIDs, - Signers: signers, - Transmitters: transmitters, - OffchainConfig: []byte("offchain config"), - }) - } - - encodedCall, err := tabi.Pack("exposeOCR3Config", ocr3Configs) - require.NoError(t.TestingT, err) - - // Trim first four bytes to remove function selector. - encodedConfigs := encodedCall[4:] - - _, err = t.CapReg.AddDON(t.Transactor, p2pIDs, []kcr.CapabilitiesRegistryCapabilityConfiguration{ - { - CapabilityId: ccipCapabilityID, - Config: encodedConfigs, - }, - }, false, false, f) - require.NoError(t.TestingT, err) - t.Backend.Commit() -} - -func SetupConfigInfo(chainSelector uint64, readers [][32]byte, fChain uint8, cfg []byte) ccip_config.CCIPConfigTypesChainConfigInfo { - return ccip_config.CCIPConfigTypesChainConfigInfo{ - ChainSelector: chainSelector, - ChainConfig: ccip_config.CCIPConfigTypesChainConfig{ - Readers: readers, - FChain: fChain, - Config: cfg, - }, - } -} diff --git a/core/capabilities/ccip/ccip_integration_tests/ping_pong_test.go b/core/capabilities/ccip/ccip_integration_tests/ping_pong_test.go deleted file mode 100644 index 8a65ff5167..0000000000 --- a/core/capabilities/ccip/ccip_integration_tests/ping_pong_test.go +++ /dev/null @@ -1,95 +0,0 @@ -package ccip_integration_tests - -import ( - "testing" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - gethcommon "github.com/ethereum/go-ethereum/common" - - "github.com/stretchr/testify/require" - - "golang.org/x/exp/maps" - - pp "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/ping_pong_demo" -) - -/* -* Test is setting up 3 chains (let's call them A, B, C), each chain deploys and starts 2 ping pong contracts for the other 2. -* A ---deploy+start---> (pingPongB, pingPongC) -* B ---deploy+start---> (pingPongA, pingPongC) -* C ---deploy+start---> (pingPongA, pingPongB) -* and then checks that each ping pong contract emitted `CCIPSendRequested` event from the expected source to destination. -* Test fails if any wiring between contracts is not correct. - */ -func TestPingPong(t *testing.T) { - _, universes := createUniverses(t, 3) - pingPongs := initializePingPongContracts(t, universes) - for chainID, universe := range universes { - for otherChain, pingPong := range pingPongs[chainID] { - t.Log("PingPong From: ", chainID, " To: ", otherChain) - _, err := pingPong.StartPingPong(universe.owner) - require.NoError(t, err) - universe.backend.Commit() - - logIter, err := universe.onramp.FilterCCIPSendRequested(&bind.FilterOpts{Start: 0}, nil) - require.NoError(t, err) - // Iterate until latest event - for logIter.Next() { - } - log := logIter.Event - require.Equal(t, getSelector(otherChain), log.DestChainSelector) - require.Equal(t, pingPong.Address(), log.Message.Sender) - chainPingPongAddr := pingPongs[otherChain][chainID].Address().Bytes() - // With chain agnostic addresses we need to pad the address to the correct length if the receiver is zero prefixed - paddedAddr := gethcommon.LeftPadBytes(chainPingPongAddr, len(log.Message.Receiver)) - require.Equal(t, paddedAddr, log.Message.Receiver) - } - } -} - -// InitializeContracts initializes ping pong contracts on all chains and -// connects them all to each other. -func initializePingPongContracts( - t *testing.T, - chainUniverses map[uint64]onchainUniverse, -) map[uint64]map[uint64]*pp.PingPongDemo { - pingPongs := make(map[uint64]map[uint64]*pp.PingPongDemo) - chainIDs := maps.Keys(chainUniverses) - // For each chain initialize N ping pong contracts, where N is the (number of chains - 1) - for chainID, universe := range chainUniverses { - pingPongs[chainID] = make(map[uint64]*pp.PingPongDemo) - for _, chainToConnect := range chainIDs { - if chainToConnect == chainID { - continue // don't connect chain to itself - } - backend := universe.backend - owner := universe.owner - pingPongAddr, _, _, err := pp.DeployPingPongDemo(owner, backend, universe.router.Address(), universe.linkToken.Address()) - require.NoError(t, err) - backend.Commit() - pingPong, err := pp.NewPingPongDemo(pingPongAddr, backend) - require.NoError(t, err) - backend.Commit() - // Fund the ping pong contract with LINK - _, err = universe.linkToken.Transfer(owner, pingPong.Address(), e18Mult(10)) - backend.Commit() - require.NoError(t, err) - pingPongs[chainID][chainToConnect] = pingPong - } - } - - // Set up each ping pong contract to its counterpart on the other chain - for chainID, universe := range chainUniverses { - for chainToConnect, pingPong := range pingPongs[chainID] { - _, err := pingPong.SetCounterpart( - universe.owner, - getSelector(chainUniverses[chainToConnect].chainID), - // This is the address of the ping pong contract on the other chain - pingPongs[chainToConnect][chainID].Address(), - ) - require.NoError(t, err) - universe.backend.Commit() - } - } - return pingPongs -} diff --git a/core/capabilities/ccip/ccipevm/commitcodec.go b/core/capabilities/ccip/ccipevm/commitcodec.go deleted file mode 100644 index 2346c9f141..0000000000 --- a/core/capabilities/ccip/ccipevm/commitcodec.go +++ /dev/null @@ -1,138 +0,0 @@ -package ccipevm - -import ( - "context" - "fmt" - "math/big" - "strings" - - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/common" - "github.com/smartcontractkit/libocr/offchainreporting2plus/types" - - cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/offramp" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/abihelpers" -) - -// CommitPluginCodecV1 is a codec for encoding and decoding commit plugin reports. -// Compatible with: -// - "OffRamp 1.6.0-dev" -type CommitPluginCodecV1 struct { - commitReportAcceptedEventInputs abi.Arguments -} - -func NewCommitPluginCodecV1() *CommitPluginCodecV1 { - abiParsed, err := abi.JSON(strings.NewReader(offramp.OffRampABI)) - if err != nil { - panic(fmt.Errorf("parse multi offramp abi: %s", err)) - } - eventInputs := abihelpers.MustGetEventInputs("CommitReportAccepted", abiParsed) - return &CommitPluginCodecV1{commitReportAcceptedEventInputs: eventInputs} -} - -func (c *CommitPluginCodecV1) Encode(ctx context.Context, report cciptypes.CommitPluginReport) ([]byte, error) { - merkleRoots := make([]offramp.OffRampMerkleRoot, 0, len(report.MerkleRoots)) - for _, root := range report.MerkleRoots { - merkleRoots = append(merkleRoots, offramp.OffRampMerkleRoot{ - SourceChainSelector: uint64(root.ChainSel), - Interval: offramp.OffRampInterval{ - Min: uint64(root.SeqNumsRange.Start()), - Max: uint64(root.SeqNumsRange.End()), - }, - MerkleRoot: root.MerkleRoot, - }) - } - - tokenPriceUpdates := make([]offramp.InternalTokenPriceUpdate, 0, len(report.PriceUpdates.TokenPriceUpdates)) - for _, update := range report.PriceUpdates.TokenPriceUpdates { - if !common.IsHexAddress(string(update.TokenID)) { - return nil, fmt.Errorf("invalid token address: %s", update.TokenID) - } - if update.Price.IsEmpty() { - return nil, fmt.Errorf("empty price for token: %s", update.TokenID) - } - tokenPriceUpdates = append(tokenPriceUpdates, offramp.InternalTokenPriceUpdate{ - SourceToken: common.HexToAddress(string(update.TokenID)), - UsdPerToken: update.Price.Int, - }) - } - - gasPriceUpdates := make([]offramp.InternalGasPriceUpdate, 0, len(report.PriceUpdates.GasPriceUpdates)) - for _, update := range report.PriceUpdates.GasPriceUpdates { - if update.GasPrice.IsEmpty() { - return nil, fmt.Errorf("empty gas price for chain: %d", update.ChainSel) - } - - gasPriceUpdates = append(gasPriceUpdates, offramp.InternalGasPriceUpdate{ - DestChainSelector: uint64(update.ChainSel), - UsdPerUnitGas: update.GasPrice.Int, - }) - } - - evmReport := offramp.OffRampCommitReport{ - PriceUpdates: offramp.InternalPriceUpdates{ - TokenPriceUpdates: tokenPriceUpdates, - GasPriceUpdates: gasPriceUpdates, - }, - MerkleRoots: merkleRoots, - } - - return c.commitReportAcceptedEventInputs.PackValues([]interface{}{evmReport}) -} - -func (c *CommitPluginCodecV1) Decode(ctx context.Context, bytes []byte) (cciptypes.CommitPluginReport, error) { - unpacked, err := c.commitReportAcceptedEventInputs.Unpack(bytes) - if err != nil { - return cciptypes.CommitPluginReport{}, err - } - if len(unpacked) != 1 { - return cciptypes.CommitPluginReport{}, fmt.Errorf("expected 1 argument, got %d", len(unpacked)) - } - - commitReportRaw := abi.ConvertType(unpacked[0], new(offramp.OffRampCommitReport)) - commitReport, is := commitReportRaw.(*offramp.OffRampCommitReport) - if !is { - return cciptypes.CommitPluginReport{}, - fmt.Errorf("expected OffRampCommitReport, got %T", unpacked[0]) - } - - merkleRoots := make([]cciptypes.MerkleRootChain, 0, len(commitReport.MerkleRoots)) - for _, root := range commitReport.MerkleRoots { - merkleRoots = append(merkleRoots, cciptypes.MerkleRootChain{ - ChainSel: cciptypes.ChainSelector(root.SourceChainSelector), - SeqNumsRange: cciptypes.NewSeqNumRange( - cciptypes.SeqNum(root.Interval.Min), - cciptypes.SeqNum(root.Interval.Max), - ), - MerkleRoot: root.MerkleRoot, - }) - } - - tokenPriceUpdates := make([]cciptypes.TokenPrice, 0, len(commitReport.PriceUpdates.TokenPriceUpdates)) - for _, update := range commitReport.PriceUpdates.TokenPriceUpdates { - tokenPriceUpdates = append(tokenPriceUpdates, cciptypes.TokenPrice{ - TokenID: types.Account(update.SourceToken.String()), - Price: cciptypes.NewBigInt(big.NewInt(0).Set(update.UsdPerToken)), - }) - } - - gasPriceUpdates := make([]cciptypes.GasPriceChain, 0, len(commitReport.PriceUpdates.GasPriceUpdates)) - for _, update := range commitReport.PriceUpdates.GasPriceUpdates { - gasPriceUpdates = append(gasPriceUpdates, cciptypes.GasPriceChain{ - GasPrice: cciptypes.NewBigInt(big.NewInt(0).Set(update.UsdPerUnitGas)), - ChainSel: cciptypes.ChainSelector(update.DestChainSelector), - }) - } - - return cciptypes.CommitPluginReport{ - MerkleRoots: merkleRoots, - PriceUpdates: cciptypes.PriceUpdates{ - TokenPriceUpdates: tokenPriceUpdates, - GasPriceUpdates: gasPriceUpdates, - }, - }, nil -} - -// Ensure CommitPluginCodec implements the CommitPluginCodec interface -var _ cciptypes.CommitPluginCodec = (*CommitPluginCodecV1)(nil) diff --git a/core/capabilities/ccip/ccipevm/commitcodec_test.go b/core/capabilities/ccip/ccipevm/commitcodec_test.go deleted file mode 100644 index 737f7be1d6..0000000000 --- a/core/capabilities/ccip/ccipevm/commitcodec_test.go +++ /dev/null @@ -1,135 +0,0 @@ -package ccipevm - -import ( - "math/big" - "math/rand" - "testing" - - "github.com/smartcontractkit/libocr/offchainreporting2plus/types" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" -) - -var randomCommitReport = func() cciptypes.CommitPluginReport { - return cciptypes.CommitPluginReport{ - MerkleRoots: []cciptypes.MerkleRootChain{ - { - ChainSel: cciptypes.ChainSelector(rand.Uint64()), - SeqNumsRange: cciptypes.NewSeqNumRange( - cciptypes.SeqNum(rand.Uint64()), - cciptypes.SeqNum(rand.Uint64()), - ), - MerkleRoot: utils.RandomBytes32(), - }, - { - ChainSel: cciptypes.ChainSelector(rand.Uint64()), - SeqNumsRange: cciptypes.NewSeqNumRange( - cciptypes.SeqNum(rand.Uint64()), - cciptypes.SeqNum(rand.Uint64()), - ), - MerkleRoot: utils.RandomBytes32(), - }, - }, - PriceUpdates: cciptypes.PriceUpdates{ - TokenPriceUpdates: []cciptypes.TokenPrice{ - { - TokenID: types.Account(utils.RandomAddress().String()), - Price: cciptypes.NewBigInt(utils.RandUint256()), - }, - }, - GasPriceUpdates: []cciptypes.GasPriceChain{ - {GasPrice: cciptypes.NewBigInt(utils.RandUint256()), ChainSel: cciptypes.ChainSelector(rand.Uint64())}, - {GasPrice: cciptypes.NewBigInt(utils.RandUint256()), ChainSel: cciptypes.ChainSelector(rand.Uint64())}, - {GasPrice: cciptypes.NewBigInt(utils.RandUint256()), ChainSel: cciptypes.ChainSelector(rand.Uint64())}, - }, - }, - } -} - -func TestCommitPluginCodecV1(t *testing.T) { - testCases := []struct { - name string - report func(report cciptypes.CommitPluginReport) cciptypes.CommitPluginReport - expErr bool - }{ - { - name: "base report", - report: func(report cciptypes.CommitPluginReport) cciptypes.CommitPluginReport { - return report - }, - }, - { - name: "empty token address", - report: func(report cciptypes.CommitPluginReport) cciptypes.CommitPluginReport { - report.PriceUpdates.TokenPriceUpdates[0].TokenID = "" - return report - }, - expErr: true, - }, - { - name: "empty merkle root", - report: func(report cciptypes.CommitPluginReport) cciptypes.CommitPluginReport { - report.MerkleRoots[0].MerkleRoot = cciptypes.Bytes32{} - return report - }, - }, - { - name: "zero token price", - report: func(report cciptypes.CommitPluginReport) cciptypes.CommitPluginReport { - report.PriceUpdates.TokenPriceUpdates[0].Price = cciptypes.NewBigInt(big.NewInt(0)) - return report - }, - }, - { - name: "zero gas price", - report: func(report cciptypes.CommitPluginReport) cciptypes.CommitPluginReport { - report.PriceUpdates.GasPriceUpdates[0].GasPrice = cciptypes.NewBigInt(big.NewInt(0)) - return report - }, - }, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - report := tc.report(randomCommitReport()) - commitCodec := NewCommitPluginCodecV1() - ctx := testutils.Context(t) - encodedReport, err := commitCodec.Encode(ctx, report) - if tc.expErr { - assert.Error(t, err) - return - } - require.NoError(t, err) - decodedReport, err := commitCodec.Decode(ctx, encodedReport) - require.NoError(t, err) - require.Equal(t, report, decodedReport) - }) - } -} - -func BenchmarkCommitPluginCodecV1_Encode(b *testing.B) { - commitCodec := NewCommitPluginCodecV1() - ctx := testutils.Context(b) - - rep := randomCommitReport() - for i := 0; i < b.N; i++ { - _, err := commitCodec.Encode(ctx, rep) - require.NoError(b, err) - } -} - -func BenchmarkCommitPluginCodecV1_Decode(b *testing.B) { - commitCodec := NewCommitPluginCodecV1() - ctx := testutils.Context(b) - encodedReport, err := commitCodec.Encode(ctx, randomCommitReport()) - require.NoError(b, err) - - for i := 0; i < b.N; i++ { - _, err := commitCodec.Decode(ctx, encodedReport) - require.NoError(b, err) - } -} diff --git a/core/capabilities/ccip/ccipevm/executecodec.go b/core/capabilities/ccip/ccipevm/executecodec.go deleted file mode 100644 index 2349beb390..0000000000 --- a/core/capabilities/ccip/ccipevm/executecodec.go +++ /dev/null @@ -1,181 +0,0 @@ -package ccipevm - -import ( - "context" - "fmt" - "strings" - - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/common" - - cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3" - - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/offramp" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/abihelpers" -) - -// ExecutePluginCodecV1 is a codec for encoding and decoding execute plugin reports. -// Compatible with: -// - "OffRamp 1.6.0-dev" -type ExecutePluginCodecV1 struct { - executeReportMethodInputs abi.Arguments -} - -func NewExecutePluginCodecV1() *ExecutePluginCodecV1 { - abiParsed, err := abi.JSON(strings.NewReader(offramp.OffRampABI)) - if err != nil { - panic(fmt.Errorf("parse multi offramp abi: %s", err)) - } - methodInputs := abihelpers.MustGetMethodInputs("manuallyExecute", abiParsed) - if len(methodInputs) == 0 { - panic("no inputs found for method: manuallyExecute") - } - - return &ExecutePluginCodecV1{ - executeReportMethodInputs: methodInputs[:1], - } -} - -func (e *ExecutePluginCodecV1) Encode(ctx context.Context, report cciptypes.ExecutePluginReport) ([]byte, error) { - evmReport := make([]offramp.InternalExecutionReportSingleChain, 0, len(report.ChainReports)) - - for _, chainReport := range report.ChainReports { - if chainReport.ProofFlagBits.IsEmpty() { - return nil, fmt.Errorf("proof flag bits are empty") - } - - evmProofs := make([][32]byte, 0, len(chainReport.Proofs)) - for _, proof := range chainReport.Proofs { - evmProofs = append(evmProofs, proof) - } - - evmMessages := make([]offramp.InternalAny2EVMRampMessage, 0, len(chainReport.Messages)) - for _, message := range chainReport.Messages { - receiver := common.BytesToAddress(message.Receiver) - - tokenAmounts := make([]offramp.InternalRampTokenAmount, 0, len(message.TokenAmounts)) - for _, tokenAmount := range message.TokenAmounts { - if tokenAmount.Amount.IsEmpty() { - return nil, fmt.Errorf("empty amount for token: %s", tokenAmount.DestTokenAddress) - } - - tokenAmounts = append(tokenAmounts, offramp.InternalRampTokenAmount{ - SourcePoolAddress: tokenAmount.SourcePoolAddress, - DestTokenAddress: tokenAmount.DestTokenAddress, - ExtraData: tokenAmount.ExtraData, - Amount: tokenAmount.Amount.Int, - }) - } - - gasLimit, err := decodeExtraArgsV1V2(message.ExtraArgs) - if err != nil { - return nil, fmt.Errorf("decode extra args to get gas limit: %w", err) - } - - evmMessages = append(evmMessages, offramp.InternalAny2EVMRampMessage{ - Header: offramp.InternalRampMessageHeader{ - MessageId: message.Header.MessageID, - SourceChainSelector: uint64(message.Header.SourceChainSelector), - DestChainSelector: uint64(message.Header.DestChainSelector), - SequenceNumber: uint64(message.Header.SequenceNumber), - Nonce: message.Header.Nonce, - }, - Sender: message.Sender, - Data: message.Data, - Receiver: receiver, - GasLimit: gasLimit, - TokenAmounts: tokenAmounts, - }) - } - - evmChainReport := offramp.InternalExecutionReportSingleChain{ - SourceChainSelector: uint64(chainReport.SourceChainSelector), - Messages: evmMessages, - OffchainTokenData: chainReport.OffchainTokenData, - Proofs: evmProofs, - ProofFlagBits: chainReport.ProofFlagBits.Int, - } - evmReport = append(evmReport, evmChainReport) - } - - return e.executeReportMethodInputs.PackValues([]interface{}{&evmReport}) -} - -func (e *ExecutePluginCodecV1) Decode(ctx context.Context, encodedReport []byte) (cciptypes.ExecutePluginReport, error) { - unpacked, err := e.executeReportMethodInputs.Unpack(encodedReport) - if err != nil { - return cciptypes.ExecutePluginReport{}, fmt.Errorf("unpack encoded report: %w", err) - } - if len(unpacked) != 1 { - return cciptypes.ExecutePluginReport{}, fmt.Errorf("unpacked report is empty") - } - - evmReportRaw := abi.ConvertType(unpacked[0], new([]offramp.InternalExecutionReportSingleChain)) - evmReportPtr, is := evmReportRaw.(*[]offramp.InternalExecutionReportSingleChain) - if !is { - return cciptypes.ExecutePluginReport{}, fmt.Errorf("got an unexpected report type %T", unpacked[0]) - } - if evmReportPtr == nil { - return cciptypes.ExecutePluginReport{}, fmt.Errorf("evm report is nil") - } - - evmReport := *evmReportPtr - executeReport := cciptypes.ExecutePluginReport{ - ChainReports: make([]cciptypes.ExecutePluginReportSingleChain, 0, len(evmReport)), - } - - for _, evmChainReport := range evmReport { - proofs := make([]cciptypes.Bytes32, 0, len(evmChainReport.Proofs)) - for _, proof := range evmChainReport.Proofs { - proofs = append(proofs, proof) - } - - messages := make([]cciptypes.Message, 0, len(evmChainReport.Messages)) - for _, evmMessage := range evmChainReport.Messages { - tokenAmounts := make([]cciptypes.RampTokenAmount, 0, len(evmMessage.TokenAmounts)) - for _, tokenAmount := range evmMessage.TokenAmounts { - tokenAmounts = append(tokenAmounts, cciptypes.RampTokenAmount{ - SourcePoolAddress: tokenAmount.SourcePoolAddress, - DestTokenAddress: tokenAmount.DestTokenAddress, - ExtraData: tokenAmount.ExtraData, - Amount: cciptypes.NewBigInt(tokenAmount.Amount), - }) - } - - message := cciptypes.Message{ - Header: cciptypes.RampMessageHeader{ - MessageID: evmMessage.Header.MessageId, - SourceChainSelector: cciptypes.ChainSelector(evmMessage.Header.SourceChainSelector), - DestChainSelector: cciptypes.ChainSelector(evmMessage.Header.DestChainSelector), - SequenceNumber: cciptypes.SeqNum(evmMessage.Header.SequenceNumber), - Nonce: evmMessage.Header.Nonce, - MsgHash: cciptypes.Bytes32{}, // <-- todo: info not available, but not required atm - OnRamp: cciptypes.Bytes{}, // <-- todo: info not available, but not required atm - }, - Sender: evmMessage.Sender, - Data: evmMessage.Data, - Receiver: evmMessage.Receiver.Bytes(), - ExtraArgs: cciptypes.Bytes{}, // <-- todo: info not available, but not required atm - FeeToken: cciptypes.Bytes{}, // <-- todo: info not available, but not required atm - FeeTokenAmount: cciptypes.BigInt{}, // <-- todo: info not available, but not required atm - TokenAmounts: tokenAmounts, - } - messages = append(messages, message) - } - - chainReport := cciptypes.ExecutePluginReportSingleChain{ - SourceChainSelector: cciptypes.ChainSelector(evmChainReport.SourceChainSelector), - Messages: messages, - OffchainTokenData: evmChainReport.OffchainTokenData, - Proofs: proofs, - ProofFlagBits: cciptypes.NewBigInt(evmChainReport.ProofFlagBits), - } - - executeReport.ChainReports = append(executeReport.ChainReports, chainReport) - } - - return executeReport, nil -} - -// Ensure ExecutePluginCodec implements the ExecutePluginCodec interface -var _ cciptypes.ExecutePluginCodec = (*ExecutePluginCodecV1)(nil) diff --git a/core/capabilities/ccip/ccipevm/executecodec_test.go b/core/capabilities/ccip/ccipevm/executecodec_test.go deleted file mode 100644 index 4f207fdb0e..0000000000 --- a/core/capabilities/ccip/ccipevm/executecodec_test.go +++ /dev/null @@ -1,174 +0,0 @@ -package ccipevm - -import ( - "math/rand" - "testing" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" - "github.com/ethereum/go-ethereum/core" - - cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3" - - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/message_hasher" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/report_codec" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -var randomExecuteReport = func(t *testing.T, d *testSetupData) cciptypes.ExecutePluginReport { - const numChainReports = 10 - const msgsPerReport = 10 - const numTokensPerMsg = 3 - - chainReports := make([]cciptypes.ExecutePluginReportSingleChain, numChainReports) - for i := 0; i < numChainReports; i++ { - reportMessages := make([]cciptypes.Message, msgsPerReport) - for j := 0; j < msgsPerReport; j++ { - data, err := cciptypes.NewBytesFromString(utils.RandomAddress().String()) - assert.NoError(t, err) - - tokenAmounts := make([]cciptypes.RampTokenAmount, numTokensPerMsg) - for z := 0; z < numTokensPerMsg; z++ { - tokenAmounts[z] = cciptypes.RampTokenAmount{ - SourcePoolAddress: utils.RandomAddress().Bytes(), - DestTokenAddress: utils.RandomAddress().Bytes(), - ExtraData: data, - Amount: cciptypes.NewBigInt(utils.RandUint256()), - } - } - - extraArgs, err := d.contract.EncodeEVMExtraArgsV1(nil, message_hasher.ClientEVMExtraArgsV1{ - GasLimit: utils.RandUint256(), - }) - assert.NoError(t, err) - - reportMessages[j] = cciptypes.Message{ - Header: cciptypes.RampMessageHeader{ - MessageID: utils.RandomBytes32(), - SourceChainSelector: cciptypes.ChainSelector(rand.Uint64()), - DestChainSelector: cciptypes.ChainSelector(rand.Uint64()), - SequenceNumber: cciptypes.SeqNum(rand.Uint64()), - Nonce: rand.Uint64(), - MsgHash: utils.RandomBytes32(), - OnRamp: utils.RandomAddress().Bytes(), - }, - Sender: utils.RandomAddress().Bytes(), - Data: data, - Receiver: utils.RandomAddress().Bytes(), - ExtraArgs: extraArgs, - FeeToken: utils.RandomAddress().Bytes(), - FeeTokenAmount: cciptypes.NewBigInt(utils.RandUint256()), - TokenAmounts: tokenAmounts, - } - } - - tokenData := make([][][]byte, numTokensPerMsg) - for j := 0; j < numTokensPerMsg; j++ { - tokenData[j] = [][]byte{{0x1}, {0x2, 0x3}} - } - - chainReports[i] = cciptypes.ExecutePluginReportSingleChain{ - SourceChainSelector: cciptypes.ChainSelector(rand.Uint64()), - Messages: reportMessages, - OffchainTokenData: tokenData, - Proofs: []cciptypes.Bytes32{utils.RandomBytes32(), utils.RandomBytes32()}, - ProofFlagBits: cciptypes.NewBigInt(utils.RandUint256()), - } - } - - return cciptypes.ExecutePluginReport{ChainReports: chainReports} -} - -func TestExecutePluginCodecV1(t *testing.T) { - d := testSetup(t) - - testCases := []struct { - name string - report func(report cciptypes.ExecutePluginReport) cciptypes.ExecutePluginReport - expErr bool - }{ - { - name: "base report", - report: func(report cciptypes.ExecutePluginReport) cciptypes.ExecutePluginReport { return report }, - expErr: false, - }, - { - name: "reports have empty msgs", - report: func(report cciptypes.ExecutePluginReport) cciptypes.ExecutePluginReport { - report.ChainReports[0].Messages = []cciptypes.Message{} - report.ChainReports[4].Messages = []cciptypes.Message{} - return report - }, - expErr: false, - }, - { - name: "reports have empty offchain token data", - report: func(report cciptypes.ExecutePluginReport) cciptypes.ExecutePluginReport { - report.ChainReports[0].OffchainTokenData = [][][]byte{} - report.ChainReports[4].OffchainTokenData[1] = [][]byte{} - return report - }, - expErr: false, - }, - } - - ctx := testutils.Context(t) - - // Deploy the contract - transactor := testutils.MustNewSimTransactor(t) - simulatedBackend := backends.NewSimulatedBackend(core.GenesisAlloc{ - transactor.From: {Balance: assets.Ether(1000).ToInt()}, - }, 30e6) - address, _, _, err := report_codec.DeployReportCodec(transactor, simulatedBackend) - require.NoError(t, err) - simulatedBackend.Commit() - contract, err := report_codec.NewReportCodec(address, simulatedBackend) - require.NoError(t, err) - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - codec := NewExecutePluginCodecV1() - report := tc.report(randomExecuteReport(t, d)) - bytes, err := codec.Encode(ctx, report) - if tc.expErr { - assert.Error(t, err) - return - } - assert.NoError(t, err) - - testSetup(t) - - // ignore msg hash in comparison - for i := range report.ChainReports { - for j := range report.ChainReports[i].Messages { - report.ChainReports[i].Messages[j].Header.MsgHash = cciptypes.Bytes32{} - report.ChainReports[i].Messages[j].Header.OnRamp = cciptypes.Bytes{} - report.ChainReports[i].Messages[j].FeeToken = cciptypes.Bytes{} - report.ChainReports[i].Messages[j].ExtraArgs = cciptypes.Bytes{} - report.ChainReports[i].Messages[j].FeeTokenAmount = cciptypes.BigInt{} - } - } - - // decode using the contract - contractDecodedReport, err := contract.DecodeExecuteReport(&bind.CallOpts{Context: ctx}, bytes) - assert.NoError(t, err) - assert.Equal(t, len(report.ChainReports), len(contractDecodedReport)) - for i, expReport := range report.ChainReports { - actReport := contractDecodedReport[i] - assert.Equal(t, expReport.OffchainTokenData, actReport.OffchainTokenData) - assert.Equal(t, len(expReport.Messages), len(actReport.Messages)) - assert.Equal(t, uint64(expReport.SourceChainSelector), actReport.SourceChainSelector) - } - - // decode using the codec - codecDecoded, err := codec.Decode(ctx, bytes) - assert.NoError(t, err) - assert.Equal(t, report, codecDecoded) - }) - } -} diff --git a/core/capabilities/ccip/ccipevm/gas_helpers.go b/core/capabilities/ccip/ccipevm/gas_helpers.go deleted file mode 100644 index 41acb2a15f..0000000000 --- a/core/capabilities/ccip/ccipevm/gas_helpers.go +++ /dev/null @@ -1,89 +0,0 @@ -package ccipevm - -import ( - "math" - - cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3" -) - -const ( - EvmAddressLengthBytes = 20 - EvmWordBytes = 32 - CalldataGasPerByte = 16 - TokenAdminRegistryWarmupCost = 2_500 - TokenAdminRegistryPoolLookupGas = 100 + // WARM_ACCESS_COST TokenAdminRegistry - 700 + // CALL cost for TokenAdminRegistry - 2_100 // COLD_SLOAD_COST loading the pool address - SupportsInterfaceCheck = 2600 + // because the receiver will be untouched initially - 30_000*3 // supportsInterface of ERC165Checker library performs 3 static-calls of 30k gas each - PerTokenOverheadGas = TokenAdminRegistryPoolLookupGas + - SupportsInterfaceCheck + - 200_000 + // releaseOrMint using callWithExactGas - 50_000 // transfer using callWithExactGas - RateLimiterOverheadGas = 2_100 + // COLD_SLOAD_COST for accessing token bucket - 5_000 // SSTORE_RESET_GAS for updating & decreasing token bucket - ConstantMessagePartBytes = 10 * 32 // A message consists of 10 abi encoded fields 32B each (after encoding) - ExecutionStateProcessingOverheadGas = 2_100 + // COLD_SLOAD_COST for first reading the state - 20_000 + // SSTORE_SET_GAS for writing from 0 (untouched) to non-zero (in-progress) - 100 //# SLOAD_GAS = WARM_STORAGE_READ_COST for rewriting from non-zero (in-progress) to non-zero (success/failure) -) - -func NewGasEstimateProvider() EstimateProvider { - return EstimateProvider{} -} - -type EstimateProvider struct { -} - -// CalculateMerkleTreeGas estimates the merkle tree gas based on number of requests -func (gp EstimateProvider) CalculateMerkleTreeGas(numRequests int) uint64 { - if numRequests == 0 { - return 0 - } - merkleProofBytes := (math.Ceil(math.Log2(float64(numRequests))))*32 + (1+2)*32 // only ever one outer root hash - return uint64(merkleProofBytes * CalldataGasPerByte) -} - -// return the size of bytes for msg tokens -func bytesForMsgTokens(numTokens int) int { - // token address (address) + token amount (uint256) - return (EvmAddressLengthBytes + EvmWordBytes) * numTokens -} - -// CalculateMessageMaxGas computes the maximum gas overhead for a message. -func (gp EstimateProvider) CalculateMessageMaxGas(msg cciptypes.Message) uint64 { - numTokens := len(msg.TokenAmounts) - var data []byte = msg.Data - dataLength := len(data) - - // TODO: update interface to return error? - // Although this decoding should never fail. - messageGasLimit, err := decodeExtraArgsV1V2(msg.ExtraArgs) - if err != nil { - panic(err) - } - - messageBytes := ConstantMessagePartBytes + - bytesForMsgTokens(numTokens) + - dataLength - - messageCallDataGas := uint64(messageBytes * CalldataGasPerByte) - - // Rate limiter only limits value in tokens. It's not called if there are no - // tokens in the message. The same goes for the admin registry, it's only loaded - // if there are tokens, and it's only loaded once. - rateLimiterOverhead := uint64(0) - adminRegistryOverhead := uint64(0) - if numTokens >= 1 { - rateLimiterOverhead = RateLimiterOverheadGas - adminRegistryOverhead = TokenAdminRegistryWarmupCost - } - - return messageGasLimit.Uint64() + - messageCallDataGas + - ExecutionStateProcessingOverheadGas + - SupportsInterfaceCheck + - adminRegistryOverhead + - rateLimiterOverhead + - PerTokenOverheadGas*uint64(numTokens) -} diff --git a/core/capabilities/ccip/ccipevm/gas_helpers_test.go b/core/capabilities/ccip/ccipevm/gas_helpers_test.go deleted file mode 100644 index f7897898fb..0000000000 --- a/core/capabilities/ccip/ccipevm/gas_helpers_test.go +++ /dev/null @@ -1,157 +0,0 @@ -package ccipevm - -import ( - "math/big" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/stretchr/testify/assert" - - "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3" -) - -func Test_calculateMessageMaxGas(t *testing.T) { - type args struct { - dataLen int - numTokens int - extraArgs []byte - } - tests := []struct { - name string - args args - want uint64 - }{ - { - name: "base", - args: args{dataLen: 5, numTokens: 2, extraArgs: makeExtraArgsV1(200_000)}, - want: 1_022_264, - }, - { - name: "large", - args: args{dataLen: 1000, numTokens: 1000, extraArgs: makeExtraArgsV1(200_000)}, - want: 346_677_520, - }, - { - name: "overheadGas test 1", - args: args{dataLen: 0, numTokens: 0, extraArgs: makeExtraArgsV1(200_000)}, - want: 319_920, - }, - { - name: "overheadGas test 2", - args: args{dataLen: len([]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0}), numTokens: 1, extraArgs: makeExtraArgsV1(200_000)}, - want: 675_948, - }, - { - name: "allowOOO set to true makes no difference to final gas estimate", - args: args{dataLen: 5, numTokens: 2, extraArgs: makeExtraArgsV2(200_000, true)}, - want: 1_022_264, - }, - { - name: "allowOOO set to false makes no difference to final gas estimate", - args: args{dataLen: 5, numTokens: 2, extraArgs: makeExtraArgsV2(200_000, false)}, - want: 1_022_264, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - msg := ccipocr3.Message{ - Data: make([]byte, tt.args.dataLen), - TokenAmounts: make([]ccipocr3.RampTokenAmount, tt.args.numTokens), - ExtraArgs: tt.args.extraArgs, - } - ep := EstimateProvider{} - got := ep.CalculateMessageMaxGas(msg) - t.Log(got) - assert.Equalf(t, tt.want, got, "calculateMessageMaxGas(%v, %v)", tt.args.dataLen, tt.args.numTokens) - }) - } -} - -// TestCalculateMaxGas is taken from the ccip repo where the CalculateMerkleTreeGas and CalculateMessageMaxGas values -// are combined to one function. -func TestCalculateMaxGas(t *testing.T) { - tests := []struct { - name string - numRequests int - dataLength int - numberOfTokens int - extraArgs []byte - want uint64 - }{ - { - name: "maxGasOverheadGas 1", - numRequests: 6, - dataLength: 0, - numberOfTokens: 0, - extraArgs: makeExtraArgsV1(200_000), - want: 322_992, - }, - { - name: "maxGasOverheadGas 2", - numRequests: 3, - dataLength: len([]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0}), - numberOfTokens: 1, - extraArgs: makeExtraArgsV1(200_000), - want: 678_508, - }, - { - name: "v2 extra args", - numRequests: 3, - dataLength: len([]byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0}), - numberOfTokens: 1, - extraArgs: makeExtraArgsV2(200_000, true), - want: 678_508, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - msg := ccipocr3.Message{ - Data: make([]byte, tt.dataLength), - TokenAmounts: make([]ccipocr3.RampTokenAmount, tt.numberOfTokens), - ExtraArgs: tt.extraArgs, - } - ep := EstimateProvider{} - - gotTree := ep.CalculateMerkleTreeGas(tt.numRequests) - gotMsg := ep.CalculateMessageMaxGas(msg) - t.Log("want", tt.want, "got", gotTree+gotMsg) - assert.Equal(t, tt.want, gotTree+gotMsg) - }) - } -} - -func makeExtraArgsV1(gasLimit uint64) []byte { - // extra args is the tag followed by the gas limit abi-encoded. - var extraArgs []byte - extraArgs = append(extraArgs, evmExtraArgsV1Tag...) - gasLimitBytes := new(big.Int).SetUint64(gasLimit).Bytes() - // pad from the left to 32 bytes - gasLimitBytes = common.LeftPadBytes(gasLimitBytes, 32) - extraArgs = append(extraArgs, gasLimitBytes...) - return extraArgs -} - -func makeExtraArgsV2(gasLimit uint64, allowOOO bool) []byte { - // extra args is the tag followed by the gas limit and allowOOO abi-encoded. - var extraArgs []byte - extraArgs = append(extraArgs, evmExtraArgsV2Tag...) - gasLimitBytes := new(big.Int).SetUint64(gasLimit).Bytes() - // pad from the left to 32 bytes - gasLimitBytes = common.LeftPadBytes(gasLimitBytes, 32) - - // abi-encode allowOOO - var allowOOOBytes []byte - if allowOOO { - allowOOOBytes = append(allowOOOBytes, 1) - } else { - allowOOOBytes = append(allowOOOBytes, 0) - } - // pad from the left to 32 bytes - allowOOOBytes = common.LeftPadBytes(allowOOOBytes, 32) - - extraArgs = append(extraArgs, gasLimitBytes...) - extraArgs = append(extraArgs, allowOOOBytes...) - return extraArgs -} diff --git a/core/capabilities/ccip/ccipevm/helpers.go b/core/capabilities/ccip/ccipevm/helpers.go deleted file mode 100644 index ee83230a4c..0000000000 --- a/core/capabilities/ccip/ccipevm/helpers.go +++ /dev/null @@ -1,33 +0,0 @@ -package ccipevm - -import ( - "bytes" - "fmt" - "math/big" -) - -func decodeExtraArgsV1V2(extraArgs []byte) (gasLimit *big.Int, err error) { - if len(extraArgs) < 4 { - return nil, fmt.Errorf("extra args too short: %d, should be at least 4 (i.e the extraArgs tag)", len(extraArgs)) - } - - var method string - if bytes.Equal(extraArgs[:4], evmExtraArgsV1Tag) { - method = "decodeEVMExtraArgsV1" - } else if bytes.Equal(extraArgs[:4], evmExtraArgsV2Tag) { - method = "decodeEVMExtraArgsV2" - } else { - return nil, fmt.Errorf("unknown extra args tag: %x", extraArgs) - } - ifaces, err := messageHasherABI.Methods[method].Inputs.UnpackValues(extraArgs[4:]) - if err != nil { - return nil, fmt.Errorf("abi decode extra args v1: %w", err) - } - // gas limit is always the first argument, and allow OOO isn't set explicitly - // on the message. - _, ok := ifaces[0].(*big.Int) - if !ok { - return nil, fmt.Errorf("expected *big.Int, got %T", ifaces[0]) - } - return ifaces[0].(*big.Int), nil -} diff --git a/core/capabilities/ccip/ccipevm/helpers_test.go b/core/capabilities/ccip/ccipevm/helpers_test.go deleted file mode 100644 index 95a5d4439b..0000000000 --- a/core/capabilities/ccip/ccipevm/helpers_test.go +++ /dev/null @@ -1,41 +0,0 @@ -package ccipevm - -import ( - "math/big" - "math/rand" - "testing" - - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/message_hasher" - - "github.com/stretchr/testify/require" -) - -func Test_decodeExtraArgs(t *testing.T) { - d := testSetup(t) - gasLimit := big.NewInt(rand.Int63()) - - t.Run("v1", func(t *testing.T) { - encoded, err := d.contract.EncodeEVMExtraArgsV1(nil, message_hasher.ClientEVMExtraArgsV1{ - GasLimit: gasLimit, - }) - require.NoError(t, err) - - decodedGasLimit, err := decodeExtraArgsV1V2(encoded) - require.NoError(t, err) - - require.Equal(t, gasLimit, decodedGasLimit) - }) - - t.Run("v2", func(t *testing.T) { - encoded, err := d.contract.EncodeEVMExtraArgsV2(nil, message_hasher.ClientEVMExtraArgsV2{ - GasLimit: gasLimit, - AllowOutOfOrderExecution: true, - }) - require.NoError(t, err) - - decodedGasLimit, err := decodeExtraArgsV1V2(encoded) - require.NoError(t, err) - - require.Equal(t, gasLimit, decodedGasLimit) - }) -} diff --git a/core/capabilities/ccip/ccipevm/msghasher.go b/core/capabilities/ccip/ccipevm/msghasher.go deleted file mode 100644 index e620d96a43..0000000000 --- a/core/capabilities/ccip/ccipevm/msghasher.go +++ /dev/null @@ -1,127 +0,0 @@ -package ccipevm - -import ( - "context" - "fmt" - - cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/message_hasher" -) - -var ( - // bytes32 internal constant LEAF_DOMAIN_SEPARATOR = 0x0000000000000000000000000000000000000000000000000000000000000000; - leafDomainSeparator = [32]byte{} - - // bytes32 internal constant ANY_2_EVM_MESSAGE_HASH = keccak256("Any2EVMMessageHashV1"); - ANY_2_EVM_MESSAGE_HASH = utils.Keccak256Fixed([]byte("Any2EVMMessageHashV1")) - - messageHasherABI = types.MustGetABI(message_hasher.MessageHasherABI) - - // bytes4 public constant EVM_EXTRA_ARGS_V1_TAG = 0x97a657c9; - evmExtraArgsV1Tag = hexutil.MustDecode("0x97a657c9") - - // bytes4 public constant EVM_EXTRA_ARGS_V2_TAG = 0x181dcf10; - evmExtraArgsV2Tag = hexutil.MustDecode("0x181dcf10") -) - -// MessageHasherV1 implements the MessageHasher interface. -// Compatible with: -// - "OnRamp 1.6.0-dev" -type MessageHasherV1 struct{} - -func NewMessageHasherV1() *MessageHasherV1 { - return &MessageHasherV1{} -} - -// Hash implements the MessageHasher interface. -// It constructs all of the inputs to the final keccak256 hash in Internal._hash(Any2EVMRampMessage). -// The main structure of the hash is as follows: -/* - keccak256( - leafDomainSeparator, - keccak256(any_2_evm_message_hash, header.sourceChainSelector, header.destinationChainSelector, onRamp), - keccak256(fixedSizeMessageFields), - keccak256(messageData), - keccak256(encodedRampTokenAmounts), - ) -*/ -func (h *MessageHasherV1) Hash(_ context.Context, msg cciptypes.Message) (cciptypes.Bytes32, error) { - var rampTokenAmounts []message_hasher.InternalRampTokenAmount - for _, rta := range msg.TokenAmounts { - rampTokenAmounts = append(rampTokenAmounts, message_hasher.InternalRampTokenAmount{ - SourcePoolAddress: rta.SourcePoolAddress, - DestTokenAddress: rta.DestTokenAddress, - ExtraData: rta.ExtraData, - Amount: rta.Amount.Int, - }) - } - encodedRampTokenAmounts, err := abiEncode("encodeTokenAmountsHashPreimage", rampTokenAmounts) - if err != nil { - return [32]byte{}, fmt.Errorf("abi encode token amounts: %w", err) - } - - metaDataHashInput, err := abiEncode( - "encodeMetadataHashPreimage", - ANY_2_EVM_MESSAGE_HASH, - uint64(msg.Header.SourceChainSelector), - uint64(msg.Header.DestChainSelector), - []byte(msg.Header.OnRamp), - ) - if err != nil { - return [32]byte{}, fmt.Errorf("abi encode metadata hash input: %w", err) - } - - // Need to decode the extra args to get the gas limit. - // TODO: we assume that extra args is always abi-encoded for now, but we need - // to decode according to source chain selector family. We should add a family - // lookup API to the chain-selectors library. - gasLimit, err := decodeExtraArgsV1V2(msg.ExtraArgs) - if err != nil { - return [32]byte{}, fmt.Errorf("decode extra args: %w", err) - } - - fixedSizeFieldsEncoded, err := abiEncode( - "encodeFixedSizeFieldsHashPreimage", - msg.Header.MessageID, - []byte(msg.Sender), - common.BytesToAddress(msg.Receiver), - uint64(msg.Header.SequenceNumber), - gasLimit, - msg.Header.Nonce, - ) - if err != nil { - return [32]byte{}, fmt.Errorf("abi encode fixed size values: %w", err) - } - - packedValues, err := abiEncode( - "encodeFinalHashPreimage", - leafDomainSeparator, - utils.Keccak256Fixed(metaDataHashInput), - utils.Keccak256Fixed(fixedSizeFieldsEncoded), - utils.Keccak256Fixed(msg.Data), - utils.Keccak256Fixed(encodedRampTokenAmounts), - ) - if err != nil { - return [32]byte{}, fmt.Errorf("abi encode packed values: %w", err) - } - - return utils.Keccak256Fixed(packedValues), nil -} - -func abiEncode(method string, values ...interface{}) ([]byte, error) { - res, err := messageHasherABI.Pack(method, values...) - if err != nil { - return nil, err - } - // trim the method selector. - return res[4:], nil -} - -// Interface compliance check -var _ cciptypes.MessageHasher = (*MessageHasherV1)(nil) diff --git a/core/capabilities/ccip/ccipevm/msghasher_test.go b/core/capabilities/ccip/ccipevm/msghasher_test.go deleted file mode 100644 index 911a10b26a..0000000000 --- a/core/capabilities/ccip/ccipevm/msghasher_test.go +++ /dev/null @@ -1,189 +0,0 @@ -package ccipevm - -import ( - "context" - cryptorand "crypto/rand" - "fmt" - "math/big" - "math/rand" - "strings" - "testing" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core" - "github.com/stretchr/testify/require" - - cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/message_hasher" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" -) - -// NOTE: these test cases are only EVM <-> EVM. -// Update these cases once we have non-EVM examples. -func TestMessageHasher_EVM2EVM(t *testing.T) { - ctx := testutils.Context(t) - d := testSetup(t) - - testCases := []evmExtraArgs{ - {version: "v1", gasLimit: big.NewInt(rand.Int63())}, - {version: "v2", gasLimit: big.NewInt(rand.Int63()), allowOOO: false}, - {version: "v2", gasLimit: big.NewInt(rand.Int63()), allowOOO: true}, - } - for i, tc := range testCases { - t.Run(fmt.Sprintf("tc_%d", i), func(tt *testing.T) { - testHasherEVM2EVM(ctx, tt, d, tc) - }) - } -} - -func testHasherEVM2EVM(ctx context.Context, t *testing.T, d *testSetupData, evmExtraArgs evmExtraArgs) { - ccipMsg := createEVM2EVMMessage(t, d.contract, evmExtraArgs) - - var tokenAmounts []message_hasher.InternalRampTokenAmount - for _, rta := range ccipMsg.TokenAmounts { - tokenAmounts = append(tokenAmounts, message_hasher.InternalRampTokenAmount{ - SourcePoolAddress: rta.SourcePoolAddress, - DestTokenAddress: rta.DestTokenAddress, - ExtraData: rta.ExtraData[:], - Amount: rta.Amount.Int, - }) - } - evmMsg := message_hasher.InternalAny2EVMRampMessage{ - Header: message_hasher.InternalRampMessageHeader{ - MessageId: ccipMsg.Header.MessageID, - SourceChainSelector: uint64(ccipMsg.Header.SourceChainSelector), - DestChainSelector: uint64(ccipMsg.Header.DestChainSelector), - SequenceNumber: uint64(ccipMsg.Header.SequenceNumber), - Nonce: ccipMsg.Header.Nonce, - }, - Sender: ccipMsg.Sender, - Receiver: common.BytesToAddress(ccipMsg.Receiver), - GasLimit: evmExtraArgs.gasLimit, - Data: ccipMsg.Data, - TokenAmounts: tokenAmounts, - } - - expectedHash, err := d.contract.Hash(&bind.CallOpts{Context: ctx}, evmMsg, ccipMsg.Header.OnRamp) - require.NoError(t, err) - - evmMsgHasher := NewMessageHasherV1() - actualHash, err := evmMsgHasher.Hash(ctx, ccipMsg) - require.NoError(t, err) - - require.Equal(t, fmt.Sprintf("%x", expectedHash), strings.TrimPrefix(actualHash.String(), "0x")) -} - -type evmExtraArgs struct { - version string - gasLimit *big.Int - allowOOO bool -} - -func createEVM2EVMMessage(t *testing.T, messageHasher *message_hasher.MessageHasher, evmExtraArgs evmExtraArgs) cciptypes.Message { - messageID := utils.RandomBytes32() - - sourceTokenData := make([]byte, rand.Intn(2048)) - _, err := cryptorand.Read(sourceTokenData) - require.NoError(t, err) - - sourceChain := rand.Uint64() - seqNum := rand.Uint64() - nonce := rand.Uint64() - destChain := rand.Uint64() - - var extraArgsBytes []byte - if evmExtraArgs.version == "v1" { - extraArgsBytes, err = messageHasher.EncodeEVMExtraArgsV1(nil, message_hasher.ClientEVMExtraArgsV1{ - GasLimit: evmExtraArgs.gasLimit, - }) - require.NoError(t, err) - } else if evmExtraArgs.version == "v2" { - extraArgsBytes, err = messageHasher.EncodeEVMExtraArgsV2(nil, message_hasher.ClientEVMExtraArgsV2{ - GasLimit: evmExtraArgs.gasLimit, - AllowOutOfOrderExecution: evmExtraArgs.allowOOO, - }) - require.NoError(t, err) - } else { - require.FailNowf(t, "unknown extra args version", "version: %s", evmExtraArgs.version) - } - - messageData := make([]byte, rand.Intn(2048)) - _, err = cryptorand.Read(messageData) - require.NoError(t, err) - - numTokens := rand.Intn(10) - var sourceTokenDatas [][]byte - for i := 0; i < numTokens; i++ { - sourceTokenDatas = append(sourceTokenDatas, sourceTokenData) - } - - var tokenAmounts []cciptypes.RampTokenAmount - for i := 0; i < len(sourceTokenDatas); i++ { - extraData := utils.RandomBytes32() - tokenAmounts = append(tokenAmounts, cciptypes.RampTokenAmount{ - SourcePoolAddress: abiEncodedAddress(t), - DestTokenAddress: abiEncodedAddress(t), - ExtraData: extraData[:], - Amount: cciptypes.NewBigInt(big.NewInt(0).SetUint64(rand.Uint64())), - }) - } - - return cciptypes.Message{ - Header: cciptypes.RampMessageHeader{ - MessageID: messageID, - SourceChainSelector: cciptypes.ChainSelector(sourceChain), - DestChainSelector: cciptypes.ChainSelector(destChain), - SequenceNumber: cciptypes.SeqNum(seqNum), - Nonce: nonce, - OnRamp: abiEncodedAddress(t), - }, - Sender: abiEncodedAddress(t), - Receiver: abiEncodedAddress(t), - Data: messageData, - TokenAmounts: tokenAmounts, - FeeToken: abiEncodedAddress(t), - FeeTokenAmount: cciptypes.NewBigInt(big.NewInt(0).SetUint64(rand.Uint64())), - ExtraArgs: extraArgsBytes, - } -} - -func abiEncodedAddress(t *testing.T) []byte { - addr := utils.RandomAddress() - encoded, err := utils.ABIEncode(`[{"type": "address"}]`, addr) - require.NoError(t, err) - return encoded -} - -type testSetupData struct { - contractAddr common.Address - contract *message_hasher.MessageHasher - sb *backends.SimulatedBackend - auth *bind.TransactOpts -} - -func testSetup(t *testing.T) *testSetupData { - transactor := testutils.MustNewSimTransactor(t) - simulatedBackend := backends.NewSimulatedBackend(core.GenesisAlloc{ - transactor.From: {Balance: assets.Ether(1000).ToInt()}, - }, 30e6) - - // Deploy the contract - address, _, _, err := message_hasher.DeployMessageHasher(transactor, simulatedBackend) - require.NoError(t, err) - simulatedBackend.Commit() - - // Setup contract client - contract, err := message_hasher.NewMessageHasher(address, simulatedBackend) - require.NoError(t, err) - - return &testSetupData{ - contractAddr: address, - contract: contract, - sb: simulatedBackend, - auth: transactor, - } -} diff --git a/core/capabilities/ccip/common/common.go b/core/capabilities/ccip/common/common.go deleted file mode 100644 index 6409345ed9..0000000000 --- a/core/capabilities/ccip/common/common.go +++ /dev/null @@ -1,23 +0,0 @@ -package common - -import ( - "fmt" - - "github.com/ethereum/go-ethereum/crypto" - - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" -) - -// HashedCapabilityID returns the hashed capability id in a manner equivalent to the capability registry. -func HashedCapabilityID(capabilityLabelledName, capabilityVersion string) (r [32]byte, err error) { - // TODO: investigate how to avoid parsing the ABI everytime. - tabi := `[{"type": "string"}, {"type": "string"}]` - abiEncoded, err := utils.ABIEncode(tabi, capabilityLabelledName, capabilityVersion) - if err != nil { - return r, fmt.Errorf("failed to ABI encode capability version and labelled name: %w", err) - } - - h := crypto.Keccak256(abiEncoded) - copy(r[:], h) - return r, nil -} diff --git a/core/capabilities/ccip/common/common_test.go b/core/capabilities/ccip/common/common_test.go deleted file mode 100644 index a7484a83ad..0000000000 --- a/core/capabilities/ccip/common/common_test.go +++ /dev/null @@ -1,51 +0,0 @@ -package common_test - -import ( - "testing" - - capcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" - - "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core" - "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" -) - -func Test_HashedCapabilityId(t *testing.T) { - transactor := testutils.MustNewSimTransactor(t) - sb := backends.NewSimulatedBackend(core.GenesisAlloc{ - transactor.From: {Balance: assets.Ether(1000).ToInt()}, - }, 30e6) - - crAddress, _, _, err := kcr.DeployCapabilitiesRegistry(transactor, sb) - require.NoError(t, err) - sb.Commit() - - cr, err := kcr.NewCapabilitiesRegistry(crAddress, sb) - require.NoError(t, err) - - // add a capability, ignore cap config for simplicity. - _, err = cr.AddCapabilities(transactor, []kcr.CapabilitiesRegistryCapability{ - { - LabelledName: "ccip", - Version: "v1.0.0", - CapabilityType: 0, - ResponseType: 0, - ConfigurationContract: common.Address{}, - }, - }) - require.NoError(t, err) - sb.Commit() - - hidExpected, err := cr.GetHashedCapabilityId(nil, "ccip", "v1.0.0") - require.NoError(t, err) - - hid, err := capcommon.HashedCapabilityID("ccip", "v1.0.0") - require.NoError(t, err) - - require.Equal(t, hidExpected, hid) -} diff --git a/core/capabilities/ccip/configs/evm/chain_writer.go b/core/capabilities/ccip/configs/evm/chain_writer.go deleted file mode 100644 index 6f8c4a1570..0000000000 --- a/core/capabilities/ccip/configs/evm/chain_writer.go +++ /dev/null @@ -1,75 +0,0 @@ -package evm - -import ( - "encoding/json" - "fmt" - - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/common" - - "github.com/smartcontractkit/chainlink-ccip/pkg/consts" - "github.com/smartcontractkit/chainlink/v2/common/txmgr" - - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" - evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/offramp" - evmrelaytypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" -) - -var ( - offrampABI = evmtypes.MustGetABI(offramp.OffRampABI) -) - -func MustChainWriterConfig( - fromAddress common.Address, - maxGasPrice *assets.Wei, - commitGasLimit, - execBatchGasLimit uint64, -) []byte { - rawConfig := ChainWriterConfigRaw(fromAddress, maxGasPrice, commitGasLimit, execBatchGasLimit) - encoded, err := json.Marshal(rawConfig) - if err != nil { - panic(fmt.Errorf("failed to marshal ChainWriterConfig: %w", err)) - } - - return encoded -} - -// ChainWriterConfigRaw returns a ChainWriterConfig that can be used to transmit commit and execute reports. -func ChainWriterConfigRaw( - fromAddress common.Address, - maxGasPrice *assets.Wei, - commitGasLimit, - execBatchGasLimit uint64, -) evmrelaytypes.ChainWriterConfig { - return evmrelaytypes.ChainWriterConfig{ - Contracts: map[string]*evmrelaytypes.ContractConfig{ - consts.ContractNameOffRamp: { - ContractABI: offramp.OffRampABI, - Configs: map[string]*evmrelaytypes.ChainWriterDefinition{ - consts.MethodCommit: { - ChainSpecificName: mustGetMethodName("commit", offrampABI), - FromAddress: fromAddress, - GasLimit: commitGasLimit, - }, - consts.MethodExecute: { - ChainSpecificName: mustGetMethodName("execute", offrampABI), - FromAddress: fromAddress, - GasLimit: execBatchGasLimit, - }, - }, - }, - }, - SendStrategy: txmgr.NewSendEveryStrategy(), - MaxGasPrice: maxGasPrice, - } -} - -// mustGetMethodName panics if the method name is not found in the provided ABI. -func mustGetMethodName(name string, tabi abi.ABI) (methodName string) { - m, ok := tabi.Methods[name] - if !ok { - panic(fmt.Sprintf("missing method %s in the abi", name)) - } - return m.Name -} diff --git a/core/capabilities/ccip/configs/evm/contract_reader.go b/core/capabilities/ccip/configs/evm/contract_reader.go deleted file mode 100644 index cd89e96337..0000000000 --- a/core/capabilities/ccip/configs/evm/contract_reader.go +++ /dev/null @@ -1,213 +0,0 @@ -package evm - -import ( - "encoding/json" - "fmt" - - "github.com/ethereum/go-ethereum/accounts/abi" - - "github.com/smartcontractkit/chainlink-ccip/pkg/consts" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/onramp" - - evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/ccip_config" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/fee_quoter" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/offramp" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" - evmrelaytypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" -) - -var ( - onrampABI = evmtypes.MustGetABI(onramp.OnRampABI) - capabilitiesRegsitryABI = evmtypes.MustGetABI(kcr.CapabilitiesRegistryABI) - ccipConfigABI = evmtypes.MustGetABI(ccip_config.CCIPConfigABI) - priceRegistryABI = evmtypes.MustGetABI(fee_quoter.FeeQuoterABI) -) - -// MustSourceReaderConfig returns a ChainReaderConfig that can be used to read from the onramp. -// The configuration is marshaled into JSON so that it can be passed to the relayer NewContractReader() method. -func MustSourceReaderConfig() []byte { - rawConfig := SourceReaderConfig - encoded, err := json.Marshal(rawConfig) - if err != nil { - panic(fmt.Errorf("failed to marshal ChainReaderConfig into JSON: %w", err)) - } - - return encoded -} - -// MustDestReaderConfig returns a ChainReaderConfig that can be used to read from the offramp. -// The configuration is marshaled into JSON so that it can be passed to the relayer NewContractReader() method. -func MustDestReaderConfig() []byte { - rawConfig := DestReaderConfig - encoded, err := json.Marshal(rawConfig) - if err != nil { - panic(fmt.Errorf("failed to marshal ChainReaderConfig into JSON: %w", err)) - } - - return encoded -} - -// DestReaderConfig returns a ChainReaderConfig that can be used to read from the offramp. -var DestReaderConfig = evmrelaytypes.ChainReaderConfig{ - Contracts: map[string]evmrelaytypes.ChainContractReader{ - consts.ContractNameOffRamp: { - ContractABI: offramp.OffRampABI, - ContractPollingFilter: evmrelaytypes.ContractPollingFilter{ - GenericEventNames: []string{ - mustGetEventName(consts.EventNameExecutionStateChanged, offrampABI), - mustGetEventName(consts.EventNameCommitReportAccepted, offrampABI), - }, - }, - Configs: map[string]*evmrelaytypes.ChainReaderDefinition{ - consts.MethodNameGetExecutionState: { - ChainSpecificName: mustGetMethodName("getExecutionState", offrampABI), - ReadType: evmrelaytypes.Method, - }, - consts.MethodNameGetMerkleRoot: { - ChainSpecificName: mustGetMethodName("getMerkleRoot", offrampABI), - ReadType: evmrelaytypes.Method, - }, - consts.MethodNameIsBlessed: { - ChainSpecificName: mustGetMethodName("isBlessed", offrampABI), - ReadType: evmrelaytypes.Method, - }, - consts.MethodNameGetLatestPriceSequenceNumber: { - ChainSpecificName: mustGetMethodName("getLatestPriceSequenceNumber", offrampABI), - ReadType: evmrelaytypes.Method, - }, - consts.MethodNameOfframpGetStaticConfig: { - ChainSpecificName: mustGetMethodName("getStaticConfig", offrampABI), - ReadType: evmrelaytypes.Method, - }, - consts.MethodNameOfframpGetDynamicConfig: { - ChainSpecificName: mustGetMethodName("getDynamicConfig", offrampABI), - ReadType: evmrelaytypes.Method, - }, - consts.MethodNameGetSourceChainConfig: { - ChainSpecificName: mustGetMethodName("getSourceChainConfig", offrampABI), - ReadType: evmrelaytypes.Method, - }, - consts.EventNameCommitReportAccepted: { - ChainSpecificName: mustGetEventName(consts.EventNameCommitReportAccepted, offrampABI), - ReadType: evmrelaytypes.Event, - }, - consts.EventNameExecutionStateChanged: { - ChainSpecificName: mustGetEventName(consts.EventNameExecutionStateChanged, offrampABI), - ReadType: evmrelaytypes.Event, - }, - }, - }, - }, -} - -// SourceReaderConfig returns a ChainReaderConfig that can be used to read from the onramp. -var SourceReaderConfig = evmrelaytypes.ChainReaderConfig{ - Contracts: map[string]evmrelaytypes.ChainContractReader{ - consts.ContractNameOnRamp: { - ContractABI: onramp.OnRampABI, - ContractPollingFilter: evmrelaytypes.ContractPollingFilter{ - GenericEventNames: []string{ - mustGetEventName(consts.EventNameCCIPSendRequested, onrampABI), - }, - }, - Configs: map[string]*evmrelaytypes.ChainReaderDefinition{ - // all "{external|public} view" functions in the onramp except for getFee and getPoolBySourceToken are here. - // getFee is not expected to get called offchain and is only called by end-user contracts. - consts.MethodNameGetExpectedNextSequenceNumber: { - ChainSpecificName: mustGetMethodName("getExpectedNextSequenceNumber", onrampABI), - ReadType: evmrelaytypes.Method, - }, - consts.MethodNameOnrampGetStaticConfig: { - ChainSpecificName: mustGetMethodName("getStaticConfig", onrampABI), - ReadType: evmrelaytypes.Method, - }, - consts.MethodNameOnrampGetDynamicConfig: { - ChainSpecificName: mustGetMethodName("getDynamicConfig", onrampABI), - ReadType: evmrelaytypes.Method, - }, - consts.EventNameCCIPSendRequested: { - ChainSpecificName: mustGetEventName(consts.EventNameCCIPSendRequested, onrampABI), - ReadType: evmrelaytypes.Event, - EventDefinitions: &evmrelaytypes.EventDefinitions{ - GenericDataWordNames: map[string]uint8{ - consts.EventAttributeSequenceNumber: 5, - }, - }, - }, - }, - }, - consts.ContractNamePriceRegistry: { - ContractABI: fee_quoter.FeeQuoterABI, - Configs: map[string]*evmrelaytypes.ChainReaderDefinition{ - // TODO: update with the consts from https://github.com/smartcontractkit/chainlink-ccip/pull/39 - // in a followup. - "GetStaticConfig": { - ChainSpecificName: mustGetMethodName("getStaticConfig", priceRegistryABI), - ReadType: evmrelaytypes.Method, - }, - "GetDestChainConfig": { - ChainSpecificName: mustGetMethodName("getDestChainConfig", priceRegistryABI), - ReadType: evmrelaytypes.Method, - }, - "GetPremiumMultiplierWeiPerEth": { - ChainSpecificName: mustGetMethodName("getPremiumMultiplierWeiPerEth", priceRegistryABI), - ReadType: evmrelaytypes.Method, - }, - "GetTokenTransferFeeConfig": { - ChainSpecificName: mustGetMethodName("getTokenTransferFeeConfig", priceRegistryABI), - ReadType: evmrelaytypes.Method, - }, - "ProcessMessageArgs": { - ChainSpecificName: mustGetMethodName("processMessageArgs", priceRegistryABI), - ReadType: evmrelaytypes.Method, - }, - "ProcessPoolReturnData": { - ChainSpecificName: mustGetMethodName("processPoolReturnData", priceRegistryABI), - ReadType: evmrelaytypes.Method, - }, - "GetValidatedTokenPrice": { - ChainSpecificName: mustGetMethodName("getValidatedTokenPrice", priceRegistryABI), - ReadType: evmrelaytypes.Method, - }, - "GetFeeTokens": { - ChainSpecificName: mustGetMethodName("getFeeTokens", priceRegistryABI), - ReadType: evmrelaytypes.Method, - }, - }, - }, - }, -} - -// HomeChainReaderConfigRaw returns a ChainReaderConfig that can be used to read from the home chain. -var HomeChainReaderConfigRaw = evmrelaytypes.ChainReaderConfig{ - Contracts: map[string]evmrelaytypes.ChainContractReader{ - consts.ContractNameCapabilitiesRegistry: { - ContractABI: kcr.CapabilitiesRegistryABI, - Configs: map[string]*evmrelaytypes.ChainReaderDefinition{ - consts.MethodNameGetCapability: { - ChainSpecificName: mustGetMethodName("getCapability", capabilitiesRegsitryABI), - }, - }, - }, - consts.ContractNameCCIPConfig: { - ContractABI: ccip_config.CCIPConfigABI, - Configs: map[string]*evmrelaytypes.ChainReaderDefinition{ - consts.MethodNameGetAllChainConfigs: { - ChainSpecificName: mustGetMethodName("getAllChainConfigs", ccipConfigABI), - }, - consts.MethodNameGetOCRConfig: { - ChainSpecificName: mustGetMethodName("getOCRConfig", ccipConfigABI), - }, - }, - }, - }, -} - -func mustGetEventName(event string, tabi abi.ABI) string { - e, ok := tabi.Events[event] - if !ok { - panic(fmt.Sprintf("missing event %s in onrampABI", event)) - } - return e.Name -} diff --git a/core/capabilities/ccip/delegate.go b/core/capabilities/ccip/delegate.go deleted file mode 100644 index 2a39334549..0000000000 --- a/core/capabilities/ccip/delegate.go +++ /dev/null @@ -1,312 +0,0 @@ -package ccip - -import ( - "context" - "fmt" - "time" - - "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" - configsevm "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/configs/evm" - "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/launcher" - "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/oraclecreator" - - ragep2ptypes "github.com/smartcontractkit/libocr/ragep2p/types" - - "github.com/smartcontractkit/chainlink-ccip/pkg/consts" - ccipreaderpkg "github.com/smartcontractkit/chainlink-ccip/pkg/reader" - "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" - "github.com/smartcontractkit/chainlink-common/pkg/types" - "github.com/smartcontractkit/chainlink-common/pkg/types/query/primitives" - - cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" - "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" - "github.com/smartcontractkit/chainlink/v2/core/config" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" - "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/job" - "github.com/smartcontractkit/chainlink/v2/core/services/keystore" - "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ocr2key" - "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" - "github.com/smartcontractkit/chainlink/v2/core/services/ocr2" - "github.com/smartcontractkit/chainlink/v2/core/services/ocrcommon" - "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" - "github.com/smartcontractkit/chainlink/v2/core/services/registrysyncer" - "github.com/smartcontractkit/chainlink/v2/core/services/relay" - "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" - "github.com/smartcontractkit/chainlink/v2/core/services/telemetry" - "github.com/smartcontractkit/chainlink/v2/plugins" -) - -type Delegate struct { - lggr logger.Logger - registrarConfig plugins.RegistrarConfig - pipelineRunner pipeline.Runner - chains legacyevm.LegacyChainContainer - keystore keystore.Master - ds sqlutil.DataSource - peerWrapper *ocrcommon.SingletonPeerWrapper - monitoringEndpointGen telemetry.MonitoringEndpointGenerator - registrySyncer registrysyncer.Syncer - capabilityConfig config.Capabilities - - isNewlyCreatedJob bool -} - -func NewDelegate( - lggr logger.Logger, - registrarConfig plugins.RegistrarConfig, - pipelineRunner pipeline.Runner, - chains legacyevm.LegacyChainContainer, - registrySyncer registrysyncer.Syncer, - keystore keystore.Master, - ds sqlutil.DataSource, - peerWrapper *ocrcommon.SingletonPeerWrapper, - monitoringEndpointGen telemetry.MonitoringEndpointGenerator, - capabilityConfig config.Capabilities, -) *Delegate { - return &Delegate{ - lggr: lggr, - registrarConfig: registrarConfig, - pipelineRunner: pipelineRunner, - chains: chains, - registrySyncer: registrySyncer, - ds: ds, - keystore: keystore, - peerWrapper: peerWrapper, - monitoringEndpointGen: monitoringEndpointGen, - capabilityConfig: capabilityConfig, - } -} - -func (d *Delegate) JobType() job.Type { - return job.CCIP -} - -func (d *Delegate) BeforeJobCreated(job.Job) { - // This is only called first time the job is created - d.isNewlyCreatedJob = true -} - -func (d *Delegate) ServicesForSpec(ctx context.Context, spec job.Job) (services []job.ServiceCtx, err error) { - // In general there should only be one P2P key but the node may have multiple. - // The job spec should specify the correct P2P key to use. - peerID, err := p2pkey.MakePeerID(spec.CCIPSpec.P2PKeyID) - if err != nil { - return nil, fmt.Errorf("failed to make peer ID from provided spec p2p id (%s): %w", spec.CCIPSpec.P2PKeyID, err) - } - - p2pID, err := d.keystore.P2P().Get(peerID) - if err != nil { - return nil, fmt.Errorf("failed to get all p2p keys: %w", err) - } - - ocrKeys, err := d.getOCRKeys(spec.CCIPSpec.OCRKeyBundleIDs) - if err != nil { - return nil, err - } - - transmitterKeys, err := d.getTransmitterKeys(ctx, d.chains) - if err != nil { - return nil, err - } - - bootstrapperLocators, err := ocrcommon.ParseBootstrapPeers(spec.CCIPSpec.P2PV2Bootstrappers) - if err != nil { - return nil, fmt.Errorf("failed to parse bootstrapper locators: %w", err) - } - - // NOTE: we can use the same DB for all plugin instances, - // since all queries are scoped by config digest. - ocrDB := ocr2.NewDB(d.ds, spec.ID, 0, d.lggr) - - homeChainContractReader, ccipConfigBinding, err := d.getHomeChainContractReader( - ctx, - d.chains, - spec.CCIPSpec.CapabilityLabelledName, - spec.CCIPSpec.CapabilityVersion) - if err != nil { - return nil, fmt.Errorf("failed to get home chain contract reader: %w", err) - } - - hcr := ccipreaderpkg.NewHomeChainReader( - homeChainContractReader, - d.lggr.Named("HomeChainReader"), - 100*time.Millisecond, - ccipConfigBinding, - ) - - // if bootstrappers are provided we assume that the node is a plugin oracle. - // the reason for this is that bootstrap oracles do not need to be aware - // of other bootstrap oracles. however, plugin oracles, at least initially, - // must be aware of available bootstrappers. - var oracleCreator cctypes.OracleCreator - if len(spec.CCIPSpec.P2PV2Bootstrappers) > 0 { - oracleCreator = oraclecreator.NewPluginOracleCreator( - ocrKeys, - transmitterKeys, - d.chains, - d.peerWrapper, - spec.ExternalJobID, - spec.ID, - d.isNewlyCreatedJob, - spec.CCIPSpec.PluginConfig, - ocrDB, - d.lggr, - d.monitoringEndpointGen, - bootstrapperLocators, - hcr, - ) - } else { - oracleCreator = oraclecreator.NewBootstrapOracleCreator( - d.peerWrapper, - bootstrapperLocators, - ocrDB, - d.monitoringEndpointGen, - d.lggr, - ) - } - - capLauncher := launcher.New( - spec.CCIPSpec.CapabilityVersion, - spec.CCIPSpec.CapabilityLabelledName, - ragep2ptypes.PeerID(p2pID.PeerID()), - d.lggr, - hcr, - 12*time.Second, - oracleCreator, - ) - - // register the capability launcher with the registry syncer - d.registrySyncer.AddLauncher(capLauncher) - - return []job.ServiceCtx{ - hcr, - capLauncher, - }, nil -} - -func (d *Delegate) AfterJobCreated(spec job.Job) {} - -func (d *Delegate) BeforeJobDeleted(spec job.Job) {} - -func (d *Delegate) OnDeleteJob(ctx context.Context, spec job.Job) error { - // TODO: shut down needed services? - return nil -} - -func (d *Delegate) getOCRKeys(ocrKeyBundleIDs job.JSONConfig) (map[string]ocr2key.KeyBundle, error) { - ocrKeys := make(map[string]ocr2key.KeyBundle) - for networkType, bundleIDRaw := range ocrKeyBundleIDs { - if networkType != relay.NetworkEVM { - return nil, fmt.Errorf("unsupported chain type: %s", networkType) - } - - bundleID, ok := bundleIDRaw.(string) - if !ok { - return nil, fmt.Errorf("OCRKeyBundleIDs must be a map of chain types to OCR key bundle IDs, got: %T", bundleIDRaw) - } - - bundle, err2 := d.keystore.OCR2().Get(bundleID) - if err2 != nil { - return nil, fmt.Errorf("OCR key bundle with ID %s not found: %w", bundleID, err2) - } - - ocrKeys[networkType] = bundle - } - return ocrKeys, nil -} - -func (d *Delegate) getTransmitterKeys(ctx context.Context, chains legacyevm.LegacyChainContainer) (map[types.RelayID][]string, error) { - transmitterKeys := make(map[types.RelayID][]string) - for _, chain := range chains.Slice() { - relayID := types.NewRelayID(relay.NetworkEVM, chain.ID().String()) - ethKeys, err2 := d.keystore.Eth().EnabledAddressesForChain(ctx, chain.ID()) - if err2 != nil { - return nil, fmt.Errorf("error getting enabled addresses for chain: %s %w", chain.ID().String(), err2) - } - - transmitterKeys[relayID] = func() (r []string) { - for _, key := range ethKeys { - r = append(r, key.Hex()) - } - return - }() - } - return transmitterKeys, nil -} - -func (d *Delegate) getHomeChainContractReader( - ctx context.Context, - chains legacyevm.LegacyChainContainer, - capabilityLabelledName, - capabilityVersion string, -) (types.ContractReader, types.BoundContract, error) { - // home chain is where the capability registry is deployed, - // which should be set correctly in toml config. - homeChainRelayID := d.capabilityConfig.ExternalRegistry().RelayID() - homeChain, err := chains.Get(homeChainRelayID.ChainID) - if err != nil { - return nil, types.BoundContract{}, fmt.Errorf("home chain relayer not found, chain id: %s, err: %w", homeChainRelayID.String(), err) - } - - reader, err := evm.NewChainReaderService( - context.Background(), - d.lggr, - homeChain.LogPoller(), - homeChain.HeadTracker(), - homeChain.Client(), - configsevm.HomeChainReaderConfigRaw, - ) - if err != nil { - return nil, types.BoundContract{}, fmt.Errorf("failed to create home chain contract reader: %w", err) - } - - reader, ccipConfigBinding, err := bindReader(ctx, reader, d.capabilityConfig.ExternalRegistry().Address(), capabilityLabelledName, capabilityVersion) - if err != nil { - return nil, types.BoundContract{}, fmt.Errorf("failed to bind home chain contract reader: %w", err) - } - - return reader, ccipConfigBinding, nil -} - -func bindReader(ctx context.Context, - reader types.ContractReader, - capRegAddress, - capabilityLabelledName, - capabilityVersion string, -) (boundReader types.ContractReader, ccipConfigBinding types.BoundContract, err error) { - err = reader.Bind(ctx, []types.BoundContract{ - { - Address: capRegAddress, - Name: consts.ContractNameCapabilitiesRegistry, - }, - }) - if err != nil { - return nil, types.BoundContract{}, fmt.Errorf("failed to bind home chain contract reader: %w", err) - } - - hid, err := common.HashedCapabilityID(capabilityLabelledName, capabilityVersion) - if err != nil { - return nil, types.BoundContract{}, fmt.Errorf("failed to hash capability id: %w", err) - } - - var ccipCapabilityInfo kcr.CapabilitiesRegistryCapabilityInfo - err = reader.GetLatestValue(ctx, consts.ContractNameCapabilitiesRegistry, consts.MethodNameGetCapability, primitives.Unconfirmed, map[string]any{ - "hashedId": hid, - }, &ccipCapabilityInfo) - if err != nil { - return nil, types.BoundContract{}, fmt.Errorf("failed to get CCIP capability info from chain reader: %w", err) - } - - // bind the ccip capability configuration contract - ccipConfigBinding = types.BoundContract{ - Address: ccipCapabilityInfo.ConfigurationContract.String(), - Name: consts.ContractNameCCIPConfig, - } - err = reader.Bind(ctx, []types.BoundContract{ccipConfigBinding}) - if err != nil { - return nil, types.BoundContract{}, fmt.Errorf("failed to bind CCIP capability configuration contract: %w", err) - } - - return reader, ccipConfigBinding, nil -} diff --git a/core/capabilities/ccip/delegate_test.go b/core/capabilities/ccip/delegate_test.go deleted file mode 100644 index dd8a5124b5..0000000000 --- a/core/capabilities/ccip/delegate_test.go +++ /dev/null @@ -1 +0,0 @@ -package ccip diff --git a/core/capabilities/ccip/launcher/README.md b/core/capabilities/ccip/launcher/README.md deleted file mode 100644 index 41fbecfdbd..0000000000 --- a/core/capabilities/ccip/launcher/README.md +++ /dev/null @@ -1,69 +0,0 @@ -# CCIP Capability Launcher - -The CCIP capability launcher is responsible for listening to -[Capabilities Registry](../../../../contracts/src/v0.8/keystone/CapabilitiesRegistry.sol) (CR) updates -for the particular CCIP capability (labelled name, version) pair and reacting to them. In -particular, there are three kinds of events that would affect a particular capability: - -1. DON Creation: when `addDON` is called on the CR, the capabilities of this new DON are specified. -If CCIP is one of those capabilities, the launcher will launch a commit and an execution plugin -with the OCR configuration specified in the DON creation process. See -[Types.sol](../../../../contracts/src/v0.8/ccip/capability/libraries/Types.sol) for more details -on what the OCR configuration contains. -2. DON update: when `updateDON` is called on the CR, capabilities of the DON can be updated. In the -CCIP use case specifically, `updateDON` is used to update OCR configuration of that DON. Updates -follow the blue/green deployment pattern (explained in detail below with a state diagram). In this -scenario the launcher must either launch brand new instances of the commit and execution plugins -(in the event a green deployment is made) or promote the currently running green instance to be -the blue instance. -3. DON deletion: when `deleteDON` is called on the CR, the launcher must shut down all running plugins -related to that DON. When a DON is deleted it effectively means that it should no longer function. -DON deletion is permanent. - -## Architecture Diagram - -![CCIP Capability Launcher](ccip_capability_launcher.png) - -The above diagram shows how the CCIP capability launcher interacts with the rest of the components -in the CCIP system. - -The CCIP capability job, which is created on the Chainlink node, will spin up the CCIP capability -launcher alongside the home chain reader, which reads the [CCIPConfig.sol](../../../../contracts/src/v0.8/ccip/capability/CCIPConfig.sol) -contract deployed on the home chain (typically Ethereum Mainnet, though could be "any chain" in theory). - -Injected into the launcher is the [OracleCreator](../types/types.go) object which knows how to spin up CCIP -oracles (both bootstrap and plugin oracles). This is used by the launcher at the appropriate time in order -to create oracle instances but not start them right away. - -After all the required oracles have been created, the launcher will start and shut them down as required -in order to match the configuration that was posted on-chain in the CR and the CCIPConfig.sol contract. - - -## Config State Diagram - -![CCIP Config State Machine](ccip_config_state_machine.png) - -CCIP's blue/green deployment paradigm is intentionally kept as simple as possible. - -Every CCIP DON starts in the `Init` state. Upon DON creation, which must provide a valid OCR -configuration, the CCIP DON will move into the `Running` state. In this state, the DON is -presumed to be fully functional from a configuration standpoint. - -When we want to update configuration, we propose a new configuration to the CR that consists of -an array of two OCR configurations: - -1. The first element of the array is the current OCR configuration that is running (termed "blue"). -2. The second element of the array is the future OCR configuration that we want to run (termed "green"). - -Various checks are done on-chain in order to validate this particular state transition, in particular, -related to config counts. Doing this will move the state of the configuration to the `Staging` state. - -In the `Staging` state, there are effectively four plugins running - one (commit, execution) pair for the -blue configuration, and one (commit, execution) pair for the green configuration. However, only the blue -configuration will actually be writing on-chain, where as the green configuration will be "dry running", -i.e doing everything except transmitting. - -This allows us to test out new configurations without committing to them immediately. - -Finally, from the `Staging` state, there is only one transition, which is to promote the green configuration -to be the new blue configuration, and go back into the `Running` state. diff --git a/core/capabilities/ccip/launcher/bluegreen.go b/core/capabilities/ccip/launcher/bluegreen.go deleted file mode 100644 index c15f8c038f..0000000000 --- a/core/capabilities/ccip/launcher/bluegreen.go +++ /dev/null @@ -1,132 +0,0 @@ -package launcher - -import ( - "fmt" - - cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" - - "go.uber.org/multierr" - - ccipreaderpkg "github.com/smartcontractkit/chainlink-ccip/pkg/reader" -) - -// blueGreenDeployment represents a blue-green deployment of OCR instances. -type blueGreenDeployment struct { - // blue is the blue OCR instance. - // blue must always be present. - blue cctypes.CCIPOracle - - // green is the green OCR instance. - // green may or may not be present. - // green must never be present if blue is not present. - // TODO: should we enforce this invariant somehow? - green cctypes.CCIPOracle -} - -// ccipDeployment represents blue-green deployments of both commit and exec -// OCR instances. -type ccipDeployment struct { - commit blueGreenDeployment - exec blueGreenDeployment -} - -// Close shuts down all OCR instances in the deployment. -func (c *ccipDeployment) Close() error { - var err error - - // shutdown blue commit instance. - err = multierr.Append(err, c.commit.blue.Close()) - - // shutdown green commit instance. - if c.commit.green != nil { - err = multierr.Append(err, c.commit.green.Close()) - } - - // shutdown blue exec instance. - err = multierr.Append(err, c.exec.blue.Close()) - - // shutdown green exec instance. - if c.exec.green != nil { - err = multierr.Append(err, c.exec.green.Close()) - } - - return err -} - -// StartBlue starts the blue OCR instances. -func (c *ccipDeployment) StartBlue() error { - var err error - - err = multierr.Append(err, c.commit.blue.Start()) - err = multierr.Append(err, c.exec.blue.Start()) - - return err -} - -// CloseBlue shuts down the blue OCR instances. -func (c *ccipDeployment) CloseBlue() error { - var err error - - err = multierr.Append(err, c.commit.blue.Close()) - err = multierr.Append(err, c.exec.blue.Close()) - - return err -} - -// HandleBlueGreen handles the blue-green deployment transition. -// prevDeployment is the previous deployment state. -// there are two possible cases: -// -// 1. both blue and green are present in prevDeployment, but only blue is present in c. -// this is a promotion of green to blue, so we need to shut down the blue deployment -// and make green the new blue. In this case green is already running, so there's no -// need to start it. However, we need to shut down the blue deployment. -// -// 2. only blue is present in prevDeployment, both blue and green are present in c. -// In this case, blue is already running, so there's no need to start it. We need to -// start green. -func (c *ccipDeployment) HandleBlueGreen(prevDeployment *ccipDeployment) error { - if prevDeployment == nil { - return fmt.Errorf("previous deployment is nil") - } - - var err error - if prevDeployment.commit.green != nil && c.commit.green == nil { - err = multierr.Append(err, prevDeployment.commit.blue.Close()) - } else if prevDeployment.commit.green == nil && c.commit.green != nil { - err = multierr.Append(err, c.commit.green.Start()) - } else { - return fmt.Errorf("invalid blue-green deployment transition") - } - - if prevDeployment.exec.green != nil && c.exec.green == nil { - err = multierr.Append(err, prevDeployment.exec.blue.Close()) - } else if prevDeployment.exec.green == nil && c.exec.green != nil { - err = multierr.Append(err, c.exec.green.Start()) - } else { - return fmt.Errorf("invalid blue-green deployment transition") - } - - return err -} - -// HasGreenInstance returns true if the deployment has a green instance for the -// given plugin type. -func (c *ccipDeployment) HasGreenInstance(pluginType cctypes.PluginType) bool { - switch pluginType { - case cctypes.PluginTypeCCIPCommit: - return c.commit.green != nil - case cctypes.PluginTypeCCIPExec: - return c.exec.green != nil - default: - return false - } -} - -func isNewGreenInstance(pluginType cctypes.PluginType, ocrConfigs []ccipreaderpkg.OCR3ConfigWithMeta, prevDeployment ccipDeployment) bool { - return len(ocrConfigs) == 2 && !prevDeployment.HasGreenInstance(pluginType) -} - -func isPromotion(pluginType cctypes.PluginType, ocrConfigs []ccipreaderpkg.OCR3ConfigWithMeta, prevDeployment ccipDeployment) bool { - return len(ocrConfigs) == 1 && prevDeployment.HasGreenInstance(pluginType) -} diff --git a/core/capabilities/ccip/launcher/bluegreen_test.go b/core/capabilities/ccip/launcher/bluegreen_test.go deleted file mode 100644 index 965491180e..0000000000 --- a/core/capabilities/ccip/launcher/bluegreen_test.go +++ /dev/null @@ -1,681 +0,0 @@ -package launcher - -import ( - "errors" - "testing" - - cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" - mocktypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types/mocks" - - "github.com/stretchr/testify/require" - - ccipreaderpkg "github.com/smartcontractkit/chainlink-ccip/pkg/reader" -) - -func Test_ccipDeployment_Close(t *testing.T) { - type args struct { - commitBlue *mocktypes.CCIPOracle - commitGreen *mocktypes.CCIPOracle - execBlue *mocktypes.CCIPOracle - execGreen *mocktypes.CCIPOracle - } - tests := []struct { - name string - args args - expect func(t *testing.T, args args) - asserts func(t *testing.T, args args) - wantErr bool - }{ - { - name: "no errors, blue only", - args: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - commitGreen: nil, - execBlue: mocktypes.NewCCIPOracle(t), - execGreen: nil, - }, - expect: func(t *testing.T, args args) { - args.commitBlue.On("Close").Return(nil).Once() - args.execBlue.On("Close").Return(nil).Once() - }, - asserts: func(t *testing.T, args args) { - args.commitBlue.AssertExpectations(t) - args.execBlue.AssertExpectations(t) - }, - wantErr: false, - }, - { - name: "no errors, blue and green", - args: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - commitGreen: mocktypes.NewCCIPOracle(t), - execBlue: mocktypes.NewCCIPOracle(t), - execGreen: mocktypes.NewCCIPOracle(t), - }, - expect: func(t *testing.T, args args) { - args.commitBlue.On("Close").Return(nil).Once() - args.commitGreen.On("Close").Return(nil).Once() - args.execBlue.On("Close").Return(nil).Once() - args.execGreen.On("Close").Return(nil).Once() - }, - asserts: func(t *testing.T, args args) { - args.commitBlue.AssertExpectations(t) - args.commitGreen.AssertExpectations(t) - args.execBlue.AssertExpectations(t) - args.execGreen.AssertExpectations(t) - }, - wantErr: false, - }, - { - name: "error on commit blue", - args: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - commitGreen: nil, - execBlue: mocktypes.NewCCIPOracle(t), - execGreen: nil, - }, - expect: func(t *testing.T, args args) { - args.commitBlue.On("Close").Return(errors.New("failed")).Once() - args.execBlue.On("Close").Return(nil).Once() - }, - asserts: func(t *testing.T, args args) { - args.commitBlue.AssertExpectations(t) - args.execBlue.AssertExpectations(t) - }, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - c := &ccipDeployment{ - commit: blueGreenDeployment{ - blue: tt.args.commitBlue, - }, - exec: blueGreenDeployment{ - blue: tt.args.execBlue, - }, - } - if tt.args.commitGreen != nil { - c.commit.green = tt.args.commitGreen - } - - if tt.args.execGreen != nil { - c.exec.green = tt.args.execGreen - } - - tt.expect(t, tt.args) - defer tt.asserts(t, tt.args) - err := c.Close() - if tt.wantErr { - require.Error(t, err) - } else { - require.NoError(t, err) - } - }) - } -} - -func Test_ccipDeployment_StartBlue(t *testing.T) { - type args struct { - commitBlue *mocktypes.CCIPOracle - execBlue *mocktypes.CCIPOracle - } - tests := []struct { - name string - args args - expect func(t *testing.T, args args) - asserts func(t *testing.T, args args) - wantErr bool - }{ - { - name: "no errors", - args: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - execBlue: mocktypes.NewCCIPOracle(t), - }, - expect: func(t *testing.T, args args) { - args.commitBlue.On("Start").Return(nil).Once() - args.execBlue.On("Start").Return(nil).Once() - }, - asserts: func(t *testing.T, args args) { - args.commitBlue.AssertExpectations(t) - args.execBlue.AssertExpectations(t) - }, - wantErr: false, - }, - { - name: "error on commit blue", - args: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - execBlue: mocktypes.NewCCIPOracle(t), - }, - expect: func(t *testing.T, args args) { - args.commitBlue.On("Start").Return(errors.New("failed")).Once() - args.execBlue.On("Start").Return(nil).Once() - }, - asserts: func(t *testing.T, args args) { - args.commitBlue.AssertExpectations(t) - args.execBlue.AssertExpectations(t) - }, - wantErr: true, - }, - { - name: "error on exec blue", - args: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - execBlue: mocktypes.NewCCIPOracle(t), - }, - expect: func(t *testing.T, args args) { - args.commitBlue.On("Start").Return(nil).Once() - args.execBlue.On("Start").Return(errors.New("failed")).Once() - }, - asserts: func(t *testing.T, args args) { - args.commitBlue.AssertExpectations(t) - args.execBlue.AssertExpectations(t) - }, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - c := &ccipDeployment{ - commit: blueGreenDeployment{ - blue: tt.args.commitBlue, - }, - exec: blueGreenDeployment{ - blue: tt.args.execBlue, - }, - } - - tt.expect(t, tt.args) - defer tt.asserts(t, tt.args) - err := c.StartBlue() - if tt.wantErr { - require.Error(t, err) - } else { - require.NoError(t, err) - } - }) - } -} - -func Test_ccipDeployment_CloseBlue(t *testing.T) { - type args struct { - commitBlue *mocktypes.CCIPOracle - execBlue *mocktypes.CCIPOracle - } - tests := []struct { - name string - args args - expect func(t *testing.T, args args) - asserts func(t *testing.T, args args) - wantErr bool - }{ - { - name: "no errors", - args: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - execBlue: mocktypes.NewCCIPOracle(t), - }, - expect: func(t *testing.T, args args) { - args.commitBlue.On("Close").Return(nil).Once() - args.execBlue.On("Close").Return(nil).Once() - }, - asserts: func(t *testing.T, args args) { - args.commitBlue.AssertExpectations(t) - args.execBlue.AssertExpectations(t) - }, - wantErr: false, - }, - { - name: "error on commit blue", - args: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - execBlue: mocktypes.NewCCIPOracle(t), - }, - expect: func(t *testing.T, args args) { - args.commitBlue.On("Close").Return(errors.New("failed")).Once() - args.execBlue.On("Close").Return(nil).Once() - }, - asserts: func(t *testing.T, args args) { - args.commitBlue.AssertExpectations(t) - args.execBlue.AssertExpectations(t) - }, - wantErr: true, - }, - { - name: "error on exec blue", - args: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - execBlue: mocktypes.NewCCIPOracle(t), - }, - expect: func(t *testing.T, args args) { - args.commitBlue.On("Close").Return(nil).Once() - args.execBlue.On("Close").Return(errors.New("failed")).Once() - }, - asserts: func(t *testing.T, args args) { - args.commitBlue.AssertExpectations(t) - args.execBlue.AssertExpectations(t) - }, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - c := &ccipDeployment{ - commit: blueGreenDeployment{ - blue: tt.args.commitBlue, - }, - exec: blueGreenDeployment{ - blue: tt.args.execBlue, - }, - } - - tt.expect(t, tt.args) - defer tt.asserts(t, tt.args) - err := c.CloseBlue() - if tt.wantErr { - require.Error(t, err) - } else { - require.NoError(t, err) - } - }) - } -} - -func Test_ccipDeployment_HandleBlueGreen_PrevDeploymentNil(t *testing.T) { - require.Error(t, (&ccipDeployment{}).HandleBlueGreen(nil)) -} - -func Test_ccipDeployment_HandleBlueGreen(t *testing.T) { - type args struct { - commitBlue *mocktypes.CCIPOracle - commitGreen *mocktypes.CCIPOracle - execBlue *mocktypes.CCIPOracle - execGreen *mocktypes.CCIPOracle - } - tests := []struct { - name string - argsPrevDeployment args - argsFutureDeployment args - expect func(t *testing.T, args args, argsPrevDeployment args) - asserts func(t *testing.T, args args, argsPrevDeployment args) - wantErr bool - }{ - { - name: "promotion blue to green", - argsPrevDeployment: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - commitGreen: mocktypes.NewCCIPOracle(t), - execBlue: mocktypes.NewCCIPOracle(t), - execGreen: mocktypes.NewCCIPOracle(t), - }, - argsFutureDeployment: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - commitGreen: nil, - execBlue: mocktypes.NewCCIPOracle(t), - execGreen: nil, - }, - expect: func(t *testing.T, args args, argsPrevDeployment args) { - argsPrevDeployment.commitBlue.On("Close").Return(nil).Once() - argsPrevDeployment.execBlue.On("Close").Return(nil).Once() - }, - asserts: func(t *testing.T, args args, argsPrevDeployment args) { - argsPrevDeployment.commitBlue.AssertExpectations(t) - argsPrevDeployment.execBlue.AssertExpectations(t) - }, - wantErr: false, - }, - { - name: "new green deployment", - argsPrevDeployment: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - commitGreen: nil, - execBlue: mocktypes.NewCCIPOracle(t), - execGreen: nil, - }, - argsFutureDeployment: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - commitGreen: mocktypes.NewCCIPOracle(t), - execBlue: mocktypes.NewCCIPOracle(t), - execGreen: mocktypes.NewCCIPOracle(t), - }, - expect: func(t *testing.T, args args, argsPrevDeployment args) { - args.commitGreen.On("Start").Return(nil).Once() - args.execGreen.On("Start").Return(nil).Once() - }, - asserts: func(t *testing.T, args args, argsPrevDeployment args) { - args.commitGreen.AssertExpectations(t) - args.execGreen.AssertExpectations(t) - }, - wantErr: false, - }, - { - name: "error on commit green start", - argsPrevDeployment: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - commitGreen: nil, - execBlue: mocktypes.NewCCIPOracle(t), - execGreen: nil, - }, - argsFutureDeployment: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - commitGreen: mocktypes.NewCCIPOracle(t), - execBlue: mocktypes.NewCCIPOracle(t), - execGreen: mocktypes.NewCCIPOracle(t), - }, - expect: func(t *testing.T, args args, argsPrevDeployment args) { - args.commitGreen.On("Start").Return(errors.New("failed")).Once() - args.execGreen.On("Start").Return(nil).Once() - }, - asserts: func(t *testing.T, args args, argsPrevDeployment args) { - args.commitGreen.AssertExpectations(t) - args.execGreen.AssertExpectations(t) - }, - wantErr: true, - }, - { - name: "error on exec green start", - argsPrevDeployment: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - commitGreen: nil, - execBlue: mocktypes.NewCCIPOracle(t), - execGreen: nil, - }, - argsFutureDeployment: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - commitGreen: mocktypes.NewCCIPOracle(t), - execBlue: mocktypes.NewCCIPOracle(t), - execGreen: mocktypes.NewCCIPOracle(t), - }, - expect: func(t *testing.T, args args, argsPrevDeployment args) { - args.commitGreen.On("Start").Return(nil).Once() - args.execGreen.On("Start").Return(errors.New("failed")).Once() - }, - asserts: func(t *testing.T, args args, argsPrevDeployment args) { - args.commitGreen.AssertExpectations(t) - args.execGreen.AssertExpectations(t) - }, - wantErr: true, - }, - { - name: "invalid blue-green deployment transition commit: both prev and future deployment have green", - argsPrevDeployment: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - commitGreen: mocktypes.NewCCIPOracle(t), - execBlue: mocktypes.NewCCIPOracle(t), - execGreen: mocktypes.NewCCIPOracle(t), - }, - argsFutureDeployment: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - commitGreen: mocktypes.NewCCIPOracle(t), - execBlue: mocktypes.NewCCIPOracle(t), - execGreen: mocktypes.NewCCIPOracle(t), - }, - expect: func(t *testing.T, args args, argsPrevDeployment args) {}, - asserts: func(t *testing.T, args args, argsPrevDeployment args) {}, - wantErr: true, - }, - { - name: "invalid blue-green deployment transition exec: both prev and future exec deployment have green", - argsPrevDeployment: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - commitGreen: nil, - execBlue: mocktypes.NewCCIPOracle(t), - execGreen: mocktypes.NewCCIPOracle(t), - }, - argsFutureDeployment: args{ - commitBlue: mocktypes.NewCCIPOracle(t), - commitGreen: mocktypes.NewCCIPOracle(t), - execBlue: mocktypes.NewCCIPOracle(t), - execGreen: mocktypes.NewCCIPOracle(t), - }, - expect: func(t *testing.T, args args, argsPrevDeployment args) { - args.commitGreen.On("Start").Return(nil).Once() - }, - asserts: func(t *testing.T, args args, argsPrevDeployment args) { - args.commitGreen.AssertExpectations(t) - }, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - futDeployment := &ccipDeployment{ - commit: blueGreenDeployment{ - blue: tt.argsFutureDeployment.commitBlue, - }, - exec: blueGreenDeployment{ - blue: tt.argsFutureDeployment.execBlue, - }, - } - if tt.argsFutureDeployment.commitGreen != nil { - futDeployment.commit.green = tt.argsFutureDeployment.commitGreen - } - if tt.argsFutureDeployment.execGreen != nil { - futDeployment.exec.green = tt.argsFutureDeployment.execGreen - } - - prevDeployment := &ccipDeployment{ - commit: blueGreenDeployment{ - blue: tt.argsPrevDeployment.commitBlue, - }, - exec: blueGreenDeployment{ - blue: tt.argsPrevDeployment.execBlue, - }, - } - if tt.argsPrevDeployment.commitGreen != nil { - prevDeployment.commit.green = tt.argsPrevDeployment.commitGreen - } - if tt.argsPrevDeployment.execGreen != nil { - prevDeployment.exec.green = tt.argsPrevDeployment.execGreen - } - - tt.expect(t, tt.argsFutureDeployment, tt.argsPrevDeployment) - defer tt.asserts(t, tt.argsFutureDeployment, tt.argsPrevDeployment) - err := futDeployment.HandleBlueGreen(prevDeployment) - if tt.wantErr { - require.Error(t, err) - } else { - require.NoError(t, err) - } - }) - } -} - -func Test_isNewGreenInstance(t *testing.T) { - type args struct { - pluginType cctypes.PluginType - ocrConfigs []ccipreaderpkg.OCR3ConfigWithMeta - prevDeployment ccipDeployment - } - tests := []struct { - name string - args args - want bool - }{ - { - "prev deployment only blue", - args{ - pluginType: cctypes.PluginTypeCCIPCommit, - ocrConfigs: []ccipreaderpkg.OCR3ConfigWithMeta{ - {}, {}, - }, - prevDeployment: ccipDeployment{ - commit: blueGreenDeployment{ - blue: mocktypes.NewCCIPOracle(t), - }, - }, - }, - true, - }, - { - "green -> blue promotion", - args{ - pluginType: cctypes.PluginTypeCCIPCommit, - ocrConfigs: []ccipreaderpkg.OCR3ConfigWithMeta{ - {}, - }, - prevDeployment: ccipDeployment{ - commit: blueGreenDeployment{ - blue: mocktypes.NewCCIPOracle(t), - green: mocktypes.NewCCIPOracle(t), - }, - }, - }, - false, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got := isNewGreenInstance(tt.args.pluginType, tt.args.ocrConfigs, tt.args.prevDeployment) - require.Equal(t, tt.want, got) - }) - } -} - -func Test_isPromotion(t *testing.T) { - type args struct { - pluginType cctypes.PluginType - ocrConfigs []ccipreaderpkg.OCR3ConfigWithMeta - prevDeployment ccipDeployment - } - tests := []struct { - name string - args args - want bool - }{ - { - "prev deployment only blue", - args{ - pluginType: cctypes.PluginTypeCCIPCommit, - ocrConfigs: []ccipreaderpkg.OCR3ConfigWithMeta{ - {}, {}, - }, - prevDeployment: ccipDeployment{ - commit: blueGreenDeployment{ - blue: mocktypes.NewCCIPOracle(t), - }, - }, - }, - false, - }, - { - "green -> blue promotion", - args{ - pluginType: cctypes.PluginTypeCCIPCommit, - ocrConfigs: []ccipreaderpkg.OCR3ConfigWithMeta{ - {}, - }, - prevDeployment: ccipDeployment{ - commit: blueGreenDeployment{ - blue: mocktypes.NewCCIPOracle(t), - green: mocktypes.NewCCIPOracle(t), - }, - }, - }, - true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if got := isPromotion(tt.args.pluginType, tt.args.ocrConfigs, tt.args.prevDeployment); got != tt.want { - t.Errorf("isPromotion() = %v, want %v", got, tt.want) - } - }) - } -} - -func Test_ccipDeployment_HasGreenInstance(t *testing.T) { - type fields struct { - commit blueGreenDeployment - exec blueGreenDeployment - } - type args struct { - pluginType cctypes.PluginType - } - tests := []struct { - name string - fields fields - args args - want bool - }{ - { - "commit green present", - fields{ - commit: blueGreenDeployment{ - blue: mocktypes.NewCCIPOracle(t), - green: mocktypes.NewCCIPOracle(t), - }, - }, - args{ - pluginType: cctypes.PluginTypeCCIPCommit, - }, - true, - }, - { - "commit green not present", - fields{ - commit: blueGreenDeployment{ - blue: mocktypes.NewCCIPOracle(t), - }, - }, - args{ - pluginType: cctypes.PluginTypeCCIPCommit, - }, - false, - }, - { - "exec green present", - fields{ - exec: blueGreenDeployment{ - blue: mocktypes.NewCCIPOracle(t), - green: mocktypes.NewCCIPOracle(t), - }, - }, - args{ - pluginType: cctypes.PluginTypeCCIPExec, - }, - true, - }, - { - "exec green not present", - fields{ - exec: blueGreenDeployment{ - blue: mocktypes.NewCCIPOracle(t), - }, - }, - args{ - pluginType: cctypes.PluginTypeCCIPExec, - }, - false, - }, - { - "invalid plugin type", - fields{}, - args{ - pluginType: cctypes.PluginType(100), - }, - false, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - c := &ccipDeployment{} - if tt.fields.commit.blue != nil { - c.commit.blue = tt.fields.commit.blue - } - if tt.fields.commit.green != nil { - c.commit.green = tt.fields.commit.green - } - if tt.fields.exec.blue != nil { - c.exec.blue = tt.fields.exec.blue - } - if tt.fields.exec.green != nil { - c.exec.green = tt.fields.exec.green - } - got := c.HasGreenInstance(tt.args.pluginType) - require.Equal(t, tt.want, got) - }) - } -} diff --git a/core/capabilities/ccip/launcher/ccip_capability_launcher.png b/core/capabilities/ccip/launcher/ccip_capability_launcher.png deleted file mode 100644 index 5e90d5ff7daa3643fde8185f49b4c83840b2c298..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 253433 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

}`U=fGbo%nS)w* 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%0DbN!YhqTG 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„JG$8DMFvpn~5IY)uJ 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

q)*yZZGJ|G0u*#`zvW(_ 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

esQpm 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

j#E!8a{;^ic**L3%PFs%{p91&%QJl)>04h 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 q^%lt6$0)pb>!L#|YvY`t>=p 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 diff --git a/core/capabilities/ccip/launcher/diff.go b/core/capabilities/ccip/launcher/diff.go deleted file mode 100644 index 787e33dadc..0000000000 --- a/core/capabilities/ccip/launcher/diff.go +++ /dev/null @@ -1,143 +0,0 @@ -package launcher - -import ( - "fmt" - - "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" - - ragep2ptypes "github.com/smartcontractkit/libocr/ragep2p/types" - - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" - "github.com/smartcontractkit/chainlink/v2/core/services/registrysyncer" -) - -// diffResult contains the added, removed and updated CCIP DONs. -// It is determined by using the `diff` function below. -type diffResult struct { - added map[registrysyncer.DonID]kcr.CapabilitiesRegistryDONInfo - removed map[registrysyncer.DonID]kcr.CapabilitiesRegistryDONInfo - updated map[registrysyncer.DonID]kcr.CapabilitiesRegistryDONInfo -} - -// diff compares the old and new state and returns the added, removed and updated CCIP DONs. -func diff( - capabilityVersion, - capabilityLabelledName string, - oldState, - newState registrysyncer.State, -) (diffResult, error) { - ccipCapability, err := checkCapabilityPresence(capabilityVersion, capabilityLabelledName, newState) - if err != nil { - return diffResult{}, fmt.Errorf("failed to check capability presence: %w", err) - } - - newCCIPDONs, err := filterCCIPDONs(ccipCapability, newState) - if err != nil { - return diffResult{}, fmt.Errorf("failed to filter CCIP DONs from new state: %w", err) - } - - currCCIPDONs, err := filterCCIPDONs(ccipCapability, oldState) - if err != nil { - return diffResult{}, fmt.Errorf("failed to filter CCIP DONs from old state: %w", err) - } - - // compare curr with new and launch or update OCR instances as needed - diffRes, err := compareDONs(currCCIPDONs, newCCIPDONs) - if err != nil { - return diffResult{}, fmt.Errorf("failed to compare CCIP DONs: %w", err) - } - - return diffRes, nil -} - -// compareDONs compares the current and new CCIP DONs and returns the added, removed and updated DONs. -func compareDONs( - currCCIPDONs, - newCCIPDONs map[registrysyncer.DonID]kcr.CapabilitiesRegistryDONInfo, -) ( - dr diffResult, - err error, -) { - added := make(map[registrysyncer.DonID]kcr.CapabilitiesRegistryDONInfo) - removed := make(map[registrysyncer.DonID]kcr.CapabilitiesRegistryDONInfo) - updated := make(map[registrysyncer.DonID]kcr.CapabilitiesRegistryDONInfo) - - for id, don := range newCCIPDONs { - if currDONState, ok := currCCIPDONs[id]; !ok { - // Not in current state, so mark as added. - added[id] = don - } else { - // If its in the current state and the config count for the DON has changed, mark as updated. - // Since the registry returns the full state we need to compare the config count. - if don.ConfigCount > currDONState.ConfigCount { - updated[id] = don - } - } - } - - for id, don := range currCCIPDONs { - if _, ok := newCCIPDONs[id]; !ok { - // In current state but not in latest registry state, so should remove. - removed[id] = don - } - } - - return diffResult{ - added: added, - removed: removed, - updated: updated, - }, nil -} - -// filterCCIPDONs filters the CCIP DONs from the given state. -func filterCCIPDONs( - ccipCapability kcr.CapabilitiesRegistryCapabilityInfo, - state registrysyncer.State, -) (map[registrysyncer.DonID]kcr.CapabilitiesRegistryDONInfo, error) { - ccipDONs := make(map[registrysyncer.DonID]kcr.CapabilitiesRegistryDONInfo) - for _, don := range state.IDsToDONs { - for _, donCapabilities := range don.CapabilityConfigurations { - hid, err := common.HashedCapabilityID(ccipCapability.LabelledName, ccipCapability.Version) - if err != nil { - return nil, fmt.Errorf("failed to hash capability id: %w", err) - } - if donCapabilities.CapabilityId == hid { - ccipDONs[registrysyncer.DonID(don.Id)] = don - } - } - } - - return ccipDONs, nil -} - -// checkCapabilityPresence checks if the capability with the given version and -// labelled name is present in the given capability registry state. -func checkCapabilityPresence( - capabilityVersion, - capabilityLabelledName string, - state registrysyncer.State, -) (kcr.CapabilitiesRegistryCapabilityInfo, error) { - // Sanity check to make sure the capability registry has the capability we are looking for. - hid, err := common.HashedCapabilityID(capabilityLabelledName, capabilityVersion) - if err != nil { - return kcr.CapabilitiesRegistryCapabilityInfo{}, fmt.Errorf("failed to hash capability id: %w", err) - } - ccipCapability, ok := state.IDsToCapabilities[hid] - if !ok { - return kcr.CapabilitiesRegistryCapabilityInfo{}, - fmt.Errorf("failed to find capability with name %s and version %s in capability registry state", - capabilityLabelledName, capabilityVersion) - } - - return ccipCapability, nil -} - -// isMemberOfDON returns true if and only if the given p2pID is a member of the given DON. -func isMemberOfDON(don kcr.CapabilitiesRegistryDONInfo, p2pID ragep2ptypes.PeerID) bool { - for _, node := range don.NodeP2PIds { - if node == p2pID { - return true - } - } - return false -} diff --git a/core/capabilities/ccip/launcher/diff_test.go b/core/capabilities/ccip/launcher/diff_test.go deleted file mode 100644 index b1914e1770..0000000000 --- a/core/capabilities/ccip/launcher/diff_test.go +++ /dev/null @@ -1,476 +0,0 @@ -package launcher - -import ( - "fmt" - "math/big" - "reflect" - "testing" - - capcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" - - ragep2ptypes "github.com/smartcontractkit/libocr/ragep2p/types" - "github.com/stretchr/testify/require" - - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" - "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" - "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" - "github.com/smartcontractkit/chainlink/v2/core/services/registrysyncer" -) - -const ( - ccipCapVersion = "v1.0.0" - ccipCapNewVersion = "v1.1.0" - ccipCapName = "ccip" -) - -func Test_diff(t *testing.T) { - type args struct { - capabilityVersion string - capabilityLabelledName string - oldState registrysyncer.State - newState registrysyncer.State - } - tests := []struct { - name string - args args - want diffResult - wantErr bool - }{ - { - "no diff", - args{ - capabilityVersion: ccipCapVersion, - capabilityLabelledName: ccipCapName, - oldState: registrysyncer.State{ - IDsToCapabilities: map[registrysyncer.HashedCapabilityID]kcr.CapabilitiesRegistryCapabilityInfo{ - mustHashedCapabilityID(ccipCapName, ccipCapVersion): { - LabelledName: ccipCapName, - Version: ccipCapVersion, - }, - }, - IDsToDONs: map[registrysyncer.DonID]kcr.CapabilitiesRegistryDONInfo{ - 1: { - Id: 1, - CapabilityConfigurations: []kcr.CapabilitiesRegistryCapabilityConfiguration{ - { - CapabilityId: mustHashedCapabilityID(ccipCapName, ccipCapVersion), - }, - }, - }, - }, - IDsToNodes: map[types.PeerID]kcr.CapabilitiesRegistryNodeInfo{}, - }, - newState: registrysyncer.State{ - IDsToCapabilities: map[registrysyncer.HashedCapabilityID]kcr.CapabilitiesRegistryCapabilityInfo{ - mustHashedCapabilityID(ccipCapName, ccipCapVersion): { - LabelledName: ccipCapName, - Version: ccipCapVersion, - }, - }, - IDsToDONs: map[registrysyncer.DonID]kcr.CapabilitiesRegistryDONInfo{ - 1: { - Id: 1, - CapabilityConfigurations: []kcr.CapabilitiesRegistryCapabilityConfiguration{ - { - CapabilityId: mustHashedCapabilityID(ccipCapName, ccipCapVersion), - }, - }, - }, - }, - IDsToNodes: map[types.PeerID]kcr.CapabilitiesRegistryNodeInfo{}, - }, - }, - diffResult{ - added: map[registrysyncer.DonID]kcr.CapabilitiesRegistryDONInfo{}, - removed: map[registrysyncer.DonID]kcr.CapabilitiesRegistryDONInfo{}, - updated: map[registrysyncer.DonID]kcr.CapabilitiesRegistryDONInfo{}, - }, - false, - }, - { - "capability not present", - args{ - capabilityVersion: ccipCapVersion, - capabilityLabelledName: ccipCapName, - oldState: registrysyncer.State{ - IDsToCapabilities: map[registrysyncer.HashedCapabilityID]kcr.CapabilitiesRegistryCapabilityInfo{ - mustHashedCapabilityID(ccipCapName, ccipCapNewVersion): { - LabelledName: ccipCapName, - Version: ccipCapNewVersion, - }, - }, - }, - newState: registrysyncer.State{ - IDsToCapabilities: map[registrysyncer.HashedCapabilityID]kcr.CapabilitiesRegistryCapabilityInfo{ - mustHashedCapabilityID(ccipCapName, ccipCapNewVersion): { - LabelledName: ccipCapName, - Version: ccipCapNewVersion, - }, - }, - }, - }, - diffResult{}, - true, - }, - { - "diff present, new don", - args{ - capabilityVersion: ccipCapVersion, - capabilityLabelledName: ccipCapName, - oldState: registrysyncer.State{ - IDsToCapabilities: map[registrysyncer.HashedCapabilityID]kcr.CapabilitiesRegistryCapabilityInfo{ - mustHashedCapabilityID(ccipCapName, ccipCapVersion): { - LabelledName: ccipCapName, - Version: ccipCapVersion, - }, - }, - IDsToDONs: map[registrysyncer.DonID]kcr.CapabilitiesRegistryDONInfo{}, - }, - newState: registrysyncer.State{ - IDsToCapabilities: map[registrysyncer.HashedCapabilityID]kcr.CapabilitiesRegistryCapabilityInfo{ - mustHashedCapabilityID(ccipCapName, ccipCapVersion): { - LabelledName: ccipCapName, - Version: ccipCapVersion, - }, - }, - IDsToDONs: map[registrysyncer.DonID]kcr.CapabilitiesRegistryDONInfo{ - 1: { - Id: 1, - CapabilityConfigurations: []kcr.CapabilitiesRegistryCapabilityConfiguration{ - { - CapabilityId: mustHashedCapabilityID(ccipCapName, ccipCapVersion), - }, - }, - }, - }, - }, - }, - diffResult{ - added: map[registrysyncer.DonID]kcr.CapabilitiesRegistryDONInfo{ - 1: { - Id: 1, - CapabilityConfigurations: []kcr.CapabilitiesRegistryCapabilityConfiguration{ - { - CapabilityId: mustHashedCapabilityID(ccipCapName, ccipCapVersion), - }, - }, - }, - }, - removed: map[registrysyncer.DonID]kcr.CapabilitiesRegistryDONInfo{}, - updated: map[registrysyncer.DonID]kcr.CapabilitiesRegistryDONInfo{}, - }, - false, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := diff(tt.args.capabilityVersion, tt.args.capabilityLabelledName, tt.args.oldState, tt.args.newState) - if tt.wantErr { - require.Error(t, err) - } else { - require.NoError(t, err) - require.Equal(t, tt.want, got) - } - }) - } -} - -func Test_compareDONs(t *testing.T) { - type args struct { - currCCIPDONs map[registrysyncer.DonID]kcr.CapabilitiesRegistryDONInfo - newCCIPDONs map[registrysyncer.DonID]kcr.CapabilitiesRegistryDONInfo - } - tests := []struct { - name string - args args - wantAdded map[registrysyncer.DonID]kcr.CapabilitiesRegistryDONInfo - wantRemoved map[registrysyncer.DonID]kcr.CapabilitiesRegistryDONInfo - wantUpdated map[registrysyncer.DonID]kcr.CapabilitiesRegistryDONInfo - wantErr bool - }{ - { - "added dons", - args{ - currCCIPDONs: map[registrysyncer.DonID]kcr.CapabilitiesRegistryDONInfo{}, - newCCIPDONs: map[registrysyncer.DonID]kcr.CapabilitiesRegistryDONInfo{ - 1: { - Id: 1, - }, - }, - }, - map[registrysyncer.DonID]kcr.CapabilitiesRegistryDONInfo{ - 1: { - Id: 1, - }, - }, - map[registrysyncer.DonID]kcr.CapabilitiesRegistryDONInfo{}, - map[registrysyncer.DonID]kcr.CapabilitiesRegistryDONInfo{}, - false, - }, - { - "removed dons", - args{ - currCCIPDONs: map[registrysyncer.DonID]kcr.CapabilitiesRegistryDONInfo{ - 1: { - Id: 1, - }, - }, - newCCIPDONs: map[registrysyncer.DonID]kcr.CapabilitiesRegistryDONInfo{}, - }, - map[registrysyncer.DonID]kcr.CapabilitiesRegistryDONInfo{}, - map[registrysyncer.DonID]kcr.CapabilitiesRegistryDONInfo{ - 1: { - Id: 1, - }, - }, - map[registrysyncer.DonID]kcr.CapabilitiesRegistryDONInfo{}, - false, - }, - { - "updated dons", - args{ - currCCIPDONs: map[registrysyncer.DonID]kcr.CapabilitiesRegistryDONInfo{ - 1: { - Id: 1, - ConfigCount: 1, - }, - }, - newCCIPDONs: map[registrysyncer.DonID]kcr.CapabilitiesRegistryDONInfo{ - 1: { - Id: 1, - ConfigCount: 2, - }, - }, - }, - map[registrysyncer.DonID]kcr.CapabilitiesRegistryDONInfo{}, - map[registrysyncer.DonID]kcr.CapabilitiesRegistryDONInfo{}, - map[registrysyncer.DonID]kcr.CapabilitiesRegistryDONInfo{ - 1: { - Id: 1, - ConfigCount: 2, - }, - }, - false, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - dr, err := compareDONs(tt.args.currCCIPDONs, tt.args.newCCIPDONs) - if tt.wantErr { - require.Error(t, err) - } else { - require.NoError(t, err) - require.Equal(t, tt.wantAdded, dr.added) - require.Equal(t, tt.wantRemoved, dr.removed) - require.Equal(t, tt.wantUpdated, dr.updated) - } - }) - } -} - -func Test_filterCCIPDONs(t *testing.T) { - type args struct { - ccipCapability kcr.CapabilitiesRegistryCapabilityInfo - state registrysyncer.State - } - tests := []struct { - name string - args args - want map[registrysyncer.DonID]kcr.CapabilitiesRegistryDONInfo - wantErr bool - }{ - { - "one ccip don", - args{ - ccipCapability: kcr.CapabilitiesRegistryCapabilityInfo{ - LabelledName: ccipCapName, - Version: ccipCapVersion, - }, - state: registrysyncer.State{ - IDsToDONs: map[registrysyncer.DonID]kcr.CapabilitiesRegistryDONInfo{ - 1: { - Id: 1, - CapabilityConfigurations: []kcr.CapabilitiesRegistryCapabilityConfiguration{ - { - CapabilityId: mustHashedCapabilityID(ccipCapName, ccipCapVersion), - }, - }, - }, - }, - }, - }, - map[registrysyncer.DonID]kcr.CapabilitiesRegistryDONInfo{ - 1: { - Id: 1, - CapabilityConfigurations: []kcr.CapabilitiesRegistryCapabilityConfiguration{ - { - CapabilityId: mustHashedCapabilityID(ccipCapName, ccipCapVersion), - }, - }, - }, - }, - false, - }, - { - "no ccip dons", - args{ - ccipCapability: kcr.CapabilitiesRegistryCapabilityInfo{ - LabelledName: ccipCapName, - Version: ccipCapVersion, - }, - state: registrysyncer.State{ - IDsToDONs: map[registrysyncer.DonID]kcr.CapabilitiesRegistryDONInfo{ - 1: { - Id: 1, - CapabilityConfigurations: []kcr.CapabilitiesRegistryCapabilityConfiguration{ - { - CapabilityId: mustHashedCapabilityID(ccipCapName, ccipCapNewVersion), - }, - }, - }, - }, - }, - }, - map[registrysyncer.DonID]kcr.CapabilitiesRegistryDONInfo{}, - false, - }, - { - "don with multiple capabilities, one of them ccip", - args{ - ccipCapability: kcr.CapabilitiesRegistryCapabilityInfo{ - LabelledName: ccipCapName, - Version: ccipCapVersion, - }, - state: registrysyncer.State{ - IDsToDONs: map[registrysyncer.DonID]kcr.CapabilitiesRegistryDONInfo{ - 1: { - Id: 1, - CapabilityConfigurations: []kcr.CapabilitiesRegistryCapabilityConfiguration{ - { - CapabilityId: mustHashedCapabilityID(ccipCapName, ccipCapVersion), - }, - { - CapabilityId: mustHashedCapabilityID(ccipCapName, ccipCapNewVersion), - }, - }, - }, - }, - }, - }, - map[registrysyncer.DonID]kcr.CapabilitiesRegistryDONInfo{ - 1: { - Id: 1, - CapabilityConfigurations: []kcr.CapabilitiesRegistryCapabilityConfiguration{ - { - CapabilityId: mustHashedCapabilityID(ccipCapName, ccipCapVersion), - }, - { - CapabilityId: mustHashedCapabilityID(ccipCapName, ccipCapNewVersion), - }, - }, - }, - }, - false, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := filterCCIPDONs(tt.args.ccipCapability, tt.args.state) - if tt.wantErr { - require.Error(t, err) - } else { - require.NoError(t, err) - require.Equal(t, tt.want, got) - } - }) - } -} - -func Test_checkCapabilityPresence(t *testing.T) { - type args struct { - capabilityVersion string - capabilityLabelledName string - state registrysyncer.State - } - tests := []struct { - name string - args args - want kcr.CapabilitiesRegistryCapabilityInfo - wantErr bool - }{ - { - "in registry state", - args{ - capabilityVersion: ccipCapVersion, - capabilityLabelledName: ccipCapName, - state: registrysyncer.State{ - IDsToCapabilities: map[registrysyncer.HashedCapabilityID]kcr.CapabilitiesRegistryCapabilityInfo{ - mustHashedCapabilityID(ccipCapName, ccipCapVersion): { - LabelledName: ccipCapName, - Version: ccipCapVersion, - }, - mustHashedCapabilityID(ccipCapName, ccipCapNewVersion): { - LabelledName: ccipCapName, - Version: ccipCapNewVersion, - }, - }, - }, - }, - kcr.CapabilitiesRegistryCapabilityInfo{ - LabelledName: ccipCapName, - Version: ccipCapVersion, - }, - false, - }, - { - "not in registry state", - args{ - capabilityVersion: ccipCapVersion, - capabilityLabelledName: ccipCapName, - state: registrysyncer.State{ - IDsToCapabilities: map[registrysyncer.HashedCapabilityID]kcr.CapabilitiesRegistryCapabilityInfo{ - mustHashedCapabilityID(ccipCapName, ccipCapNewVersion): { - LabelledName: ccipCapName, - Version: ccipCapNewVersion, - }, - }, - }, - }, - kcr.CapabilitiesRegistryCapabilityInfo{}, - true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := checkCapabilityPresence(tt.args.capabilityVersion, tt.args.capabilityLabelledName, tt.args.state) - if (err != nil) != tt.wantErr { - t.Errorf("checkCapabilityPresence() error = %v, wantErr %v", err, tt.wantErr) - return - } - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("checkCapabilityPresence() = %v, want %v", got, tt.want) - } - }) - } -} - -func Test_isMemberOfDON(t *testing.T) { - var p2pIDs [][32]byte - for i := range [4]struct{}{} { - p2pIDs = append(p2pIDs, p2pkey.MustNewV2XXXTestingOnly(big.NewInt(int64(i+1))).PeerID()) - } - don := kcr.CapabilitiesRegistryDONInfo{ - Id: 1, - NodeP2PIds: p2pIDs, - } - require.True(t, isMemberOfDON(don, ragep2ptypes.PeerID(p2pkey.MustNewV2XXXTestingOnly(big.NewInt(1)).PeerID()))) - require.False(t, isMemberOfDON(don, ragep2ptypes.PeerID(p2pkey.MustNewV2XXXTestingOnly(big.NewInt(5)).PeerID()))) -} - -func mustHashedCapabilityID(capabilityLabelledName, capabilityVersion string) [32]byte { - r, err := capcommon.HashedCapabilityID(capabilityLabelledName, capabilityVersion) - if err != nil { - panic(fmt.Errorf("failed to hash capability id (labelled name: %s, version: %s): %w", capabilityLabelledName, capabilityVersion, err)) - } - return r -} diff --git a/core/capabilities/ccip/launcher/integration_test.go b/core/capabilities/ccip/launcher/integration_test.go deleted file mode 100644 index da1ac36465..0000000000 --- a/core/capabilities/ccip/launcher/integration_test.go +++ /dev/null @@ -1,113 +0,0 @@ -package launcher - -import ( - "testing" - "time" - - it "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccip_integration_tests/integrationhelpers" - cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" - - "github.com/onsi/gomega" - "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/ccip_config" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/registrysyncer" -) - -func TestIntegration_Launcher(t *testing.T) { - ctx := testutils.Context(t) - lggr := logger.TestLogger(t) - uni := it.NewTestUniverse(ctx, t, lggr) - // We need 3*f + 1 p2pIDs to have enough nodes to bootstrap - var arr []int64 - n := int(it.FChainA*3 + 1) - for i := 0; i <= n; i++ { - arr = append(arr, int64(i)) - } - p2pIDs := it.P2pIDsFromInts(arr) - uni.AddCapability(p2pIDs) - - regSyncer, err := registrysyncer.New(lggr, uni, uni.CapReg.Address().String()) - require.NoError(t, err) - - oracleCreator := &oracleCreatorPrints{ - t: t, - } - launcher := New( - it.CcipCapabilityVersion, - it.CcipCapabilityLabelledName, - p2pIDs[0], - logger.TestLogger(t), - uni.HomeChainReader, - 1*time.Second, - oracleCreator, - ) - regSyncer.AddLauncher(launcher) - - require.NoError(t, launcher.Start(ctx)) - require.NoError(t, regSyncer.Start(ctx)) - t.Cleanup(func() { require.NoError(t, regSyncer.Close()) }) - t.Cleanup(func() { require.NoError(t, launcher.Close()) }) - - chainAConf := it.SetupConfigInfo(it.ChainA, p2pIDs, it.FChainA, []byte("ChainA")) - chainBConf := it.SetupConfigInfo(it.ChainB, p2pIDs[1:], it.FChainB, []byte("ChainB")) - chainCConf := it.SetupConfigInfo(it.ChainC, p2pIDs[2:], it.FChainC, []byte("ChainC")) - inputConfig := []ccip_config.CCIPConfigTypesChainConfigInfo{ - chainAConf, - chainBConf, - chainCConf, - } - _, err = uni.CcipCfg.ApplyChainConfigUpdates(uni.Transactor, nil, inputConfig) - require.NoError(t, err) - uni.Backend.Commit() - - ccipCapabilityID, err := uni.CapReg.GetHashedCapabilityId(nil, it.CcipCapabilityLabelledName, it.CcipCapabilityVersion) - require.NoError(t, err) - - uni.AddDONToRegistry( - ccipCapabilityID, - it.ChainA, - it.FChainA, - p2pIDs[1], - p2pIDs) - - gomega.NewWithT(t).Eventually(func() bool { - return len(launcher.runningDONIDs()) == 1 - }, testutils.WaitTimeout(t), testutils.TestInterval).Should(gomega.BeTrue()) -} - -type oraclePrints struct { - t *testing.T - pluginType cctypes.PluginType - config cctypes.OCR3ConfigWithMeta - isBootstrap bool -} - -func (o *oraclePrints) Start() error { - o.t.Logf("Starting oracle (pluginType: %s, isBootstrap: %t) with config %+v\n", o.pluginType, o.isBootstrap, o.config) - return nil -} - -func (o *oraclePrints) Close() error { - o.t.Logf("Closing oracle (pluginType: %s, isBootstrap: %t) with config %+v\n", o.pluginType, o.isBootstrap, o.config) - return nil -} - -type oracleCreatorPrints struct { - t *testing.T -} - -func (o *oracleCreatorPrints) Create(config cctypes.OCR3ConfigWithMeta) (cctypes.CCIPOracle, error) { - pluginType := cctypes.PluginType(config.Config.PluginType) - o.t.Logf("Creating plugin oracle (pluginType: %s) with config %+v\n", pluginType, config) - return &oraclePrints{pluginType: pluginType, config: config, t: o.t}, nil -} - -func (o *oracleCreatorPrints) Type() cctypes.OracleType { - return cctypes.OracleTypePlugin -} - -var _ cctypes.OracleCreator = &oracleCreatorPrints{} -var _ cctypes.CCIPOracle = &oraclePrints{} diff --git a/core/capabilities/ccip/launcher/launcher.go b/core/capabilities/ccip/launcher/launcher.go deleted file mode 100644 index 4d60bfcdc9..0000000000 --- a/core/capabilities/ccip/launcher/launcher.go +++ /dev/null @@ -1,412 +0,0 @@ -package launcher - -import ( - "context" - "fmt" - "sync" - "time" - - "go.uber.org/multierr" - - ragep2ptypes "github.com/smartcontractkit/libocr/ragep2p/types" - - "github.com/smartcontractkit/chainlink-common/pkg/services" - - ccipreader "github.com/smartcontractkit/chainlink-ccip/pkg/reader" - cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" - "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/job" - p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" - "github.com/smartcontractkit/chainlink/v2/core/services/registrysyncer" -) - -var ( - _ job.ServiceCtx = (*launcher)(nil) - _ registrysyncer.Launcher = (*launcher)(nil) -) - -func New( - capabilityVersion, - capabilityLabelledName string, - p2pID ragep2ptypes.PeerID, - lggr logger.Logger, - homeChainReader ccipreader.HomeChain, - tickInterval time.Duration, - oracleCreator cctypes.OracleCreator, -) *launcher { - return &launcher{ - capabilityVersion: capabilityVersion, - capabilityLabelledName: capabilityLabelledName, - p2pID: p2pID, - lggr: lggr, - homeChainReader: homeChainReader, - regState: registrysyncer.State{ - IDsToDONs: make(map[registrysyncer.DonID]kcr.CapabilitiesRegistryDONInfo), - IDsToNodes: make(map[p2ptypes.PeerID]kcr.CapabilitiesRegistryNodeInfo), - IDsToCapabilities: make(map[registrysyncer.HashedCapabilityID]kcr.CapabilitiesRegistryCapabilityInfo), - }, - dons: make(map[registrysyncer.DonID]*ccipDeployment), - tickInterval: tickInterval, - oracleCreator: oracleCreator, - } -} - -// launcher manages the lifecycles of the CCIP capability on all chains. -type launcher struct { - services.StateMachine - - capabilityVersion string - capabilityLabelledName string - p2pID ragep2ptypes.PeerID - lggr logger.Logger - homeChainReader ccipreader.HomeChain - stopChan chan struct{} - // latestState is the latest capability registry state received from the syncer. - latestState registrysyncer.State - // regState is the latest capability registry state that we have successfully processed. - regState registrysyncer.State - lock sync.RWMutex - wg sync.WaitGroup - tickInterval time.Duration - oracleCreator cctypes.OracleCreator - - // dons is a map of CCIP DON IDs to the OCR instances that are running on them. - // we can have up to two OCR instances per CCIP plugin, since we are running two plugins, - // thats four OCR instances per CCIP DON maximum. - dons map[registrysyncer.DonID]*ccipDeployment -} - -// Launch implements registrysyncer.Launcher. -func (l *launcher) Launch(ctx context.Context, state registrysyncer.State) error { - l.lock.Lock() - defer l.lock.Unlock() - l.lggr.Debugw("Received new state from syncer", "dons", state.IDsToDONs) - l.latestState = state - return nil -} - -func (l *launcher) getLatestState() registrysyncer.State { - l.lock.RLock() - defer l.lock.RUnlock() - return l.latestState -} - -func (l *launcher) runningDONIDs() []registrysyncer.DonID { - l.lock.RLock() - defer l.lock.RUnlock() - var runningDONs []registrysyncer.DonID - for id := range l.dons { - runningDONs = append(runningDONs, id) - } - return runningDONs -} - -// Close implements job.ServiceCtx. -func (l *launcher) Close() error { - return l.StateMachine.StopOnce("launcher", func() error { - // shut down the monitor goroutine. - close(l.stopChan) - l.wg.Wait() - - // shut down all running oracles. - var err error - for _, ceDep := range l.dons { - err = multierr.Append(err, ceDep.Close()) - } - - return err - }) -} - -// Start implements job.ServiceCtx. -func (l *launcher) Start(context.Context) error { - return l.StartOnce("launcher", func() error { - l.stopChan = make(chan struct{}) - l.wg.Add(1) - go l.monitor() - return nil - }) -} - -func (l *launcher) monitor() { - defer l.wg.Done() - ticker := time.NewTicker(l.tickInterval) - for { - select { - case <-l.stopChan: - return - case <-ticker.C: - if err := l.tick(); err != nil { - l.lggr.Errorw("Failed to tick", "err", err) - } - } - } -} - -func (l *launcher) tick() error { - // Ensure that the home chain reader is healthy. - // For new jobs it may be possible that the home chain reader is not yet ready - // so we won't be able to fetch configs and start any OCR instances. - if ready := l.homeChainReader.Ready(); ready != nil { - return fmt.Errorf("home chain reader is not ready: %w", ready) - } - - // Fetch the latest state from the capability registry and determine if we need to - // launch or update any OCR instances. - latestState := l.getLatestState() - - diffRes, err := diff(l.capabilityVersion, l.capabilityLabelledName, l.regState, latestState) - if err != nil { - return fmt.Errorf("failed to diff capability registry states: %w", err) - } - - err = l.processDiff(diffRes) - if err != nil { - return fmt.Errorf("failed to process diff: %w", err) - } - - return nil -} - -// processDiff processes the diff between the current and latest capability registry states. -// for any added OCR instances, it will launch them. -// for any removed OCR instances, it will shut them down. -// for any updated OCR instances, it will restart them with the new configuration. -func (l *launcher) processDiff(diff diffResult) error { - err := l.processRemoved(diff.removed) - err = multierr.Append(err, l.processAdded(diff.added)) - err = multierr.Append(err, l.processUpdate(diff.updated)) - - return err -} - -func (l *launcher) processUpdate(updated map[registrysyncer.DonID]kcr.CapabilitiesRegistryDONInfo) error { - l.lock.Lock() - defer l.lock.Unlock() - - for donID, don := range updated { - prevDeployment, ok := l.dons[registrysyncer.DonID(don.Id)] - if !ok { - return fmt.Errorf("invariant violation: expected to find CCIP DON %d in the map of running deployments", don.Id) - } - - futDeployment, err := updateDON( - l.lggr, - l.p2pID, - l.homeChainReader, - *prevDeployment, - don, - l.oracleCreator, - ) - if err != nil { - return err - } - if err := futDeployment.HandleBlueGreen(prevDeployment); err != nil { - // TODO: how to handle a failed blue-green deployment? - return fmt.Errorf("failed to handle blue-green deployment for CCIP DON %d: %w", donID, err) - } - - // update state. - l.dons[donID] = futDeployment - // update the state with the latest config. - // this way if one of the starts errors, we don't retry all of them. - l.regState.IDsToDONs[donID] = updated[donID] - } - - return nil -} - -func (l *launcher) processAdded(added map[registrysyncer.DonID]kcr.CapabilitiesRegistryDONInfo) error { - l.lock.Lock() - defer l.lock.Unlock() - - for donID, don := range added { - dep, err := createDON( - l.lggr, - l.p2pID, - l.homeChainReader, - don, - l.oracleCreator, - ) - if err != nil { - return err - } - if dep == nil { - // not a member of this DON. - continue - } - - if err := dep.StartBlue(); err != nil { - if shutdownErr := dep.CloseBlue(); shutdownErr != nil { - l.lggr.Errorw("Failed to shutdown blue instance after failed start", "donId", donID, "err", shutdownErr) - } - return fmt.Errorf("failed to start oracles for CCIP DON %d: %w", donID, err) - } - - // update state. - l.dons[donID] = dep - // update the state with the latest config. - // this way if one of the starts errors, we don't retry all of them. - l.regState.IDsToDONs[donID] = added[donID] - } - - return nil -} - -func (l *launcher) processRemoved(removed map[registrysyncer.DonID]kcr.CapabilitiesRegistryDONInfo) error { - l.lock.Lock() - defer l.lock.Unlock() - - for id := range removed { - ceDep, ok := l.dons[id] - if !ok { - // not running this particular DON. - continue - } - - if err := ceDep.Close(); err != nil { - return fmt.Errorf("failed to shutdown oracles for CCIP DON %d: %w", id, err) - } - - // after a successful shutdown we can safely remove the DON deployment from the map. - delete(l.dons, id) - delete(l.regState.IDsToDONs, id) - } - - return nil -} - -// updateDON is a pure function that handles the case where a DON in the capability registry -// has received a new configuration. -// It returns a new ccipDeployment that can then be used to perform the blue-green deployment, -// based on the previous deployment. -func updateDON( - lggr logger.Logger, - p2pID ragep2ptypes.PeerID, - homeChainReader ccipreader.HomeChain, - prevDeployment ccipDeployment, - don kcr.CapabilitiesRegistryDONInfo, - oracleCreator cctypes.OracleCreator, -) (futDeployment *ccipDeployment, err error) { - if !isMemberOfDON(don, p2pID) { - lggr.Infow("Not a member of this DON, skipping", "donId", don.Id, "p2pId", p2pID.String()) - return nil, nil - } - - // this should be a retryable error. - commitOCRConfigs, err := homeChainReader.GetOCRConfigs(context.Background(), don.Id, uint8(cctypes.PluginTypeCCIPCommit)) - if err != nil { - return nil, fmt.Errorf("failed to fetch OCR configs for CCIP commit plugin (don id: %d) from home chain config contract: %w", - don.Id, err) - } - - execOCRConfigs, err := homeChainReader.GetOCRConfigs(context.Background(), don.Id, uint8(cctypes.PluginTypeCCIPExec)) - if err != nil { - return nil, fmt.Errorf("failed to fetch OCR configs for CCIP exec plugin (don id: %d) from home chain config contract: %w", - don.Id, err) - } - - commitBgd, err := createFutureBlueGreenDeployment(prevDeployment, commitOCRConfigs, oracleCreator, cctypes.PluginTypeCCIPCommit) - if err != nil { - return nil, fmt.Errorf("failed to create future blue-green deployment for CCIP commit plugin: %w, don id: %d", err, don.Id) - } - - execBgd, err := createFutureBlueGreenDeployment(prevDeployment, execOCRConfigs, oracleCreator, cctypes.PluginTypeCCIPExec) - if err != nil { - return nil, fmt.Errorf("failed to create future blue-green deployment for CCIP exec plugin: %w, don id: %d", err, don.Id) - } - - return &ccipDeployment{ - commit: commitBgd, - exec: execBgd, - }, nil -} - -// valid cases: -// a) len(ocrConfigs) == 2 && !prevDeployment.HasGreenInstance(pluginType): this is a new green instance. -// b) len(ocrConfigs) == 1 && prevDeployment.HasGreenInstance(): this is a promotion of green->blue. -// All other cases are invalid. This is enforced in the ccip config contract. -func createFutureBlueGreenDeployment( - prevDeployment ccipDeployment, - ocrConfigs []ccipreader.OCR3ConfigWithMeta, - oracleCreator cctypes.OracleCreator, - pluginType cctypes.PluginType, -) (blueGreenDeployment, error) { - var deployment blueGreenDeployment - if isNewGreenInstance(pluginType, ocrConfigs, prevDeployment) { - // this is a new green instance. - greenOracle, err := oracleCreator.Create(cctypes.OCR3ConfigWithMeta(ocrConfigs[1])) - if err != nil { - return blueGreenDeployment{}, fmt.Errorf("failed to create CCIP commit oracle: %w", err) - } - - deployment.blue = prevDeployment.commit.blue - deployment.green = greenOracle - } else if isPromotion(pluginType, ocrConfigs, prevDeployment) { - // this is a promotion of green->blue. - deployment.blue = prevDeployment.commit.green - } else { - return blueGreenDeployment{}, fmt.Errorf("invariant violation: expected 1 or 2 OCR configs for CCIP plugin (type: %d), got %d", pluginType, len(ocrConfigs)) - } - - return deployment, nil -} - -// createDON is a pure function that handles the case where a new DON is added to the capability registry. -// It returns a new ccipDeployment that can then be used to start the blue instance. -func createDON( - lggr logger.Logger, - p2pID ragep2ptypes.PeerID, - homeChainReader ccipreader.HomeChain, - don kcr.CapabilitiesRegistryDONInfo, - oracleCreator cctypes.OracleCreator, -) (*ccipDeployment, error) { - // this should be a retryable error. - commitOCRConfigs, err := homeChainReader.GetOCRConfigs(context.Background(), don.Id, uint8(cctypes.PluginTypeCCIPCommit)) - if err != nil { - return nil, fmt.Errorf("failed to fetch OCR configs for CCIP commit plugin (don id: %d) from home chain config contract: %w", - don.Id, err) - } - - execOCRConfigs, err := homeChainReader.GetOCRConfigs(context.Background(), don.Id, uint8(cctypes.PluginTypeCCIPExec)) - if err != nil { - return nil, fmt.Errorf("failed to fetch OCR configs for CCIP exec plugin (don id: %d) from home chain config contract: %w", - don.Id, err) - } - - // upon creation we should only have one OCR config per plugin type. - if len(commitOCRConfigs) != 1 { - return nil, fmt.Errorf("expected exactly one OCR config for CCIP commit plugin (don id: %d), got %d", don.Id, len(commitOCRConfigs)) - } - - if len(execOCRConfigs) != 1 { - return nil, fmt.Errorf("expected exactly one OCR config for CCIP exec plugin (don id: %d), got %d", don.Id, len(execOCRConfigs)) - } - - if !isMemberOfDON(don, p2pID) && oracleCreator.Type() == cctypes.OracleTypePlugin { - lggr.Infow("Not a member of this DON and not a bootstrap node either, skipping", "donId", don.Id, "p2pId", p2pID.String()) - return nil, nil - } - - // at this point we know we are either a member of the DON or a bootstrap node. - // the injected oracleCreator will create the appropriate oracle. - commitOracle, err := oracleCreator.Create(cctypes.OCR3ConfigWithMeta(commitOCRConfigs[0])) - if err != nil { - return nil, fmt.Errorf("failed to create CCIP commit oracle: %w", err) - } - - execOracle, err := oracleCreator.Create(cctypes.OCR3ConfigWithMeta(execOCRConfigs[0])) - if err != nil { - return nil, fmt.Errorf("failed to create CCIP exec oracle: %w", err) - } - - return &ccipDeployment{ - commit: blueGreenDeployment{ - blue: commitOracle, - }, - exec: blueGreenDeployment{ - blue: execOracle, - }, - }, nil -} diff --git a/core/capabilities/ccip/launcher/launcher_test.go b/core/capabilities/ccip/launcher/launcher_test.go deleted file mode 100644 index bb24464c62..0000000000 --- a/core/capabilities/ccip/launcher/launcher_test.go +++ /dev/null @@ -1,490 +0,0 @@ -package launcher - -import ( - "math/big" - "reflect" - "testing" - - cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" - "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types/mocks" - - ragep2ptypes "github.com/smartcontractkit/libocr/ragep2p/types" - "github.com/stretchr/testify/mock" - "github.com/stretchr/testify/require" - - ccipreaderpkg "github.com/smartcontractkit/chainlink-ccip/pkg/reader" - - kcr "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" - "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" - "github.com/smartcontractkit/chainlink/v2/core/services/registrysyncer" -) - -func Test_createDON(t *testing.T) { - type args struct { - lggr logger.Logger - p2pID ragep2ptypes.PeerID - homeChainReader *mocks.HomeChainReader - oracleCreator *mocks.OracleCreator - don kcr.CapabilitiesRegistryDONInfo - } - tests := []struct { - name string - args args - expect func(t *testing.T, args args, oracleCreator *mocks.OracleCreator, homeChainReader *mocks.HomeChainReader) - wantErr bool - }{ - { - "not a member of the DON and not a bootstrap node", - args{ - logger.TestLogger(t), - ragep2ptypes.PeerID(p2pkey.MustNewV2XXXTestingOnly(big.NewInt(1)).PeerID()), - mocks.NewHomeChainReader(t), - mocks.NewOracleCreator(t), - kcr.CapabilitiesRegistryDONInfo{ - NodeP2PIds: [][32]byte{ - p2pkey.MustNewV2XXXTestingOnly(big.NewInt(3)).PeerID(), - p2pkey.MustNewV2XXXTestingOnly(big.NewInt(4)).PeerID(), - }, - Id: 2, - }, - }, - func(t *testing.T, args args, oracleCreator *mocks.OracleCreator, homeChainReader *mocks.HomeChainReader) { - homeChainReader. - On("GetOCRConfigs", mock.Anything, uint32(2), uint8(cctypes.PluginTypeCCIPCommit)). - Return([]ccipreaderpkg.OCR3ConfigWithMeta{{ - Config: ccipreaderpkg.OCR3Config{ - PluginType: uint8(cctypes.PluginTypeCCIPCommit), - P2PIds: [][32]byte{ - p2pkey.MustNewV2XXXTestingOnly(big.NewInt(3)).PeerID(), - p2pkey.MustNewV2XXXTestingOnly(big.NewInt(4)).PeerID(), - }, - }, - }}, nil) - homeChainReader. - On("GetOCRConfigs", mock.Anything, uint32(2), uint8(cctypes.PluginTypeCCIPExec)). - Return([]ccipreaderpkg.OCR3ConfigWithMeta{{ - Config: ccipreaderpkg.OCR3Config{ - PluginType: uint8(cctypes.PluginTypeCCIPExec), - P2PIds: [][32]byte{ - p2pkey.MustNewV2XXXTestingOnly(big.NewInt(3)).PeerID(), - p2pkey.MustNewV2XXXTestingOnly(big.NewInt(4)).PeerID(), - }, - }, - }}, nil) - oracleCreator.EXPECT().Type().Return(cctypes.OracleTypePlugin).Once() - }, - false, - }, - { - "not a member of the DON but a running a bootstrap oracle creator", - args{ - logger.TestLogger(t), - ragep2ptypes.PeerID(p2pkey.MustNewV2XXXTestingOnly(big.NewInt(1)).PeerID()), - mocks.NewHomeChainReader(t), - mocks.NewOracleCreator(t), - kcr.CapabilitiesRegistryDONInfo{ - NodeP2PIds: [][32]byte{ - p2pkey.MustNewV2XXXTestingOnly(big.NewInt(3)).PeerID(), - p2pkey.MustNewV2XXXTestingOnly(big.NewInt(4)).PeerID(), - }, - Id: 2, - }, - }, - func(t *testing.T, args args, oracleCreator *mocks.OracleCreator, homeChainReader *mocks.HomeChainReader) { - homeChainReader. - On("GetOCRConfigs", mock.Anything, uint32(2), uint8(cctypes.PluginTypeCCIPCommit)). - Return([]ccipreaderpkg.OCR3ConfigWithMeta{{ - Config: ccipreaderpkg.OCR3Config{ - PluginType: uint8(cctypes.PluginTypeCCIPCommit), - P2PIds: [][32]byte{ - p2pkey.MustNewV2XXXTestingOnly(big.NewInt(3)).PeerID(), - p2pkey.MustNewV2XXXTestingOnly(big.NewInt(4)).PeerID(), - }, - }, - }}, nil) - homeChainReader. - On("GetOCRConfigs", mock.Anything, uint32(2), uint8(cctypes.PluginTypeCCIPExec)). - Return([]ccipreaderpkg.OCR3ConfigWithMeta{{ - Config: ccipreaderpkg.OCR3Config{ - PluginType: uint8(cctypes.PluginTypeCCIPExec), - P2PIds: [][32]byte{ - p2pkey.MustNewV2XXXTestingOnly(big.NewInt(3)).PeerID(), - p2pkey.MustNewV2XXXTestingOnly(big.NewInt(4)).PeerID(), - }, - }, - }}, nil) - oracleCreator.EXPECT().Type().Return(cctypes.OracleTypeBootstrap).Once() - oracleCreator. - On("Create", mock.Anything). - Return(mocks.NewCCIPOracle(t), nil).Twice() - }, - false, - }, - { - "success", - args{ - logger.TestLogger(t), - ragep2ptypes.PeerID(p2pkey.MustNewV2XXXTestingOnly(big.NewInt(1)).PeerID()), - mocks.NewHomeChainReader(t), - mocks.NewOracleCreator(t), - kcr.CapabilitiesRegistryDONInfo{ - NodeP2PIds: [][32]byte{ - p2pkey.MustNewV2XXXTestingOnly(big.NewInt(1)).PeerID(), - p2pkey.MustNewV2XXXTestingOnly(big.NewInt(2)).PeerID(), - }, - Id: 1, - }, - }, - func(t *testing.T, args args, oracleCreator *mocks.OracleCreator, homeChainReader *mocks.HomeChainReader) { - homeChainReader. - On("GetOCRConfigs", mock.Anything, uint32(1), uint8(cctypes.PluginTypeCCIPCommit)). - Return([]ccipreaderpkg.OCR3ConfigWithMeta{{ - Config: ccipreaderpkg.OCR3Config{ - PluginType: uint8(cctypes.PluginTypeCCIPCommit), - P2PIds: [][32]byte{ - p2pkey.MustNewV2XXXTestingOnly(big.NewInt(1)).PeerID(), - p2pkey.MustNewV2XXXTestingOnly(big.NewInt(2)).PeerID(), - }, - }, - }}, nil) - homeChainReader. - On("GetOCRConfigs", mock.Anything, uint32(1), uint8(cctypes.PluginTypeCCIPExec)). - Return([]ccipreaderpkg.OCR3ConfigWithMeta{{ - Config: ccipreaderpkg.OCR3Config{ - PluginType: uint8(cctypes.PluginTypeCCIPExec), - P2PIds: [][32]byte{ - p2pkey.MustNewV2XXXTestingOnly(big.NewInt(1)).PeerID(), - p2pkey.MustNewV2XXXTestingOnly(big.NewInt(2)).PeerID(), - }, - }, - }}, nil) - - oracleCreator.EXPECT().Create(mock.MatchedBy(func(cfg cctypes.OCR3ConfigWithMeta) bool { - return cfg.Config.PluginType == uint8(cctypes.PluginTypeCCIPCommit) - })). - Return(mocks.NewCCIPOracle(t), nil) - oracleCreator.EXPECT().Create(mock.MatchedBy(func(cfg cctypes.OCR3ConfigWithMeta) bool { - return cfg.Config.PluginType == uint8(cctypes.PluginTypeCCIPExec) - })). - Return(mocks.NewCCIPOracle(t), nil) - }, - false, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if tt.expect != nil { - tt.expect(t, tt.args, tt.args.oracleCreator, tt.args.homeChainReader) - } - - _, err := createDON(tt.args.lggr, tt.args.p2pID, tt.args.homeChainReader, tt.args.don, tt.args.oracleCreator) - if tt.wantErr { - require.Error(t, err) - } else { - require.NoError(t, err) - } - }) - } -} - -func Test_createFutureBlueGreenDeployment(t *testing.T) { - type args struct { - prevDeployment ccipDeployment - ocrConfigs []ccipreaderpkg.OCR3ConfigWithMeta - oracleCreator *mocks.OracleCreator - pluginType cctypes.PluginType - } - tests := []struct { - name string - args args - want blueGreenDeployment - wantErr bool - }{ - // TODO: Add test cases. - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := createFutureBlueGreenDeployment(tt.args.prevDeployment, tt.args.ocrConfigs, tt.args.oracleCreator, tt.args.pluginType) - if (err != nil) != tt.wantErr { - t.Errorf("createFutureBlueGreenDeployment() error = %v, wantErr %v", err, tt.wantErr) - return - } - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("createFutureBlueGreenDeployment() = %v, want %v", got, tt.want) - } - }) - } -} - -func Test_updateDON(t *testing.T) { - type args struct { - lggr logger.Logger - p2pID ragep2ptypes.PeerID - homeChainReader *mocks.HomeChainReader - oracleCreator *mocks.OracleCreator - prevDeployment ccipDeployment - don kcr.CapabilitiesRegistryDONInfo - } - tests := []struct { - name string - args args - wantFutDeployment *ccipDeployment - wantErr bool - }{ - // TODO: Add test cases. - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - gotFutDeployment, err := updateDON(tt.args.lggr, tt.args.p2pID, tt.args.homeChainReader, tt.args.prevDeployment, tt.args.don, tt.args.oracleCreator) - if (err != nil) != tt.wantErr { - t.Errorf("updateDON() error = %v, wantErr %v", err, tt.wantErr) - return - } - if !reflect.DeepEqual(gotFutDeployment, tt.wantFutDeployment) { - t.Errorf("updateDON() = %v, want %v", gotFutDeployment, tt.wantFutDeployment) - } - }) - } -} - -func Test_launcher_processDiff(t *testing.T) { - type fields struct { - lggr logger.Logger - p2pID ragep2ptypes.PeerID - homeChainReader *mocks.HomeChainReader - oracleCreator *mocks.OracleCreator - dons map[registrysyncer.DonID]*ccipDeployment - regState registrysyncer.State - } - type args struct { - diff diffResult - } - tests := []struct { - name string - fields fields - args args - assert func(t *testing.T, l *launcher) - wantErr bool - }{ - { - "don removed success", - fields{ - dons: map[registrysyncer.DonID]*ccipDeployment{ - 1: { - commit: blueGreenDeployment{ - blue: newMock(t, - func(t *testing.T) *mocks.CCIPOracle { return mocks.NewCCIPOracle(t) }, - func(m *mocks.CCIPOracle) { - m.On("Close").Return(nil) - }), - }, - exec: blueGreenDeployment{ - blue: newMock(t, - func(t *testing.T) *mocks.CCIPOracle { return mocks.NewCCIPOracle(t) }, - func(m *mocks.CCIPOracle) { - m.On("Close").Return(nil) - }), - }, - }, - }, - regState: registrysyncer.State{ - IDsToDONs: map[registrysyncer.DonID]kcr.CapabilitiesRegistryDONInfo{ - 1: { - Id: 1, - }, - }, - }, - }, - args{ - diff: diffResult{ - removed: map[registrysyncer.DonID]kcr.CapabilitiesRegistryDONInfo{ - 1: { - Id: 1, - }, - }, - }, - }, - func(t *testing.T, l *launcher) { - require.Len(t, l.dons, 0) - require.Len(t, l.regState.IDsToDONs, 0) - }, - false, - }, - { - "don added success", - fields{ - lggr: logger.TestLogger(t), - p2pID: ragep2ptypes.PeerID(p2pkey.MustNewV2XXXTestingOnly(big.NewInt(1)).PeerID()), - homeChainReader: newMock(t, func(t *testing.T) *mocks.HomeChainReader { - return mocks.NewHomeChainReader(t) - }, func(m *mocks.HomeChainReader) { - m.On("GetOCRConfigs", mock.Anything, uint32(1), uint8(cctypes.PluginTypeCCIPCommit)). - Return([]ccipreaderpkg.OCR3ConfigWithMeta{{ - Config: ccipreaderpkg.OCR3Config{ - PluginType: uint8(cctypes.PluginTypeCCIPCommit), - }, - }}, nil) - m.On("GetOCRConfigs", mock.Anything, uint32(1), uint8(cctypes.PluginTypeCCIPExec)). - Return([]ccipreaderpkg.OCR3ConfigWithMeta{{ - Config: ccipreaderpkg.OCR3Config{ - PluginType: uint8(cctypes.PluginTypeCCIPExec), - }, - }}, nil) - }), - oracleCreator: newMock(t, func(t *testing.T) *mocks.OracleCreator { - return mocks.NewOracleCreator(t) - }, func(m *mocks.OracleCreator) { - commitOracle := mocks.NewCCIPOracle(t) - commitOracle.On("Start").Return(nil) - execOracle := mocks.NewCCIPOracle(t) - execOracle.On("Start").Return(nil) - m.EXPECT().Create(mock.MatchedBy(func(cfg cctypes.OCR3ConfigWithMeta) bool { - return cfg.Config.PluginType == uint8(cctypes.PluginTypeCCIPCommit) - })). - Return(commitOracle, nil) - m.EXPECT().Create(mock.MatchedBy(func(cfg cctypes.OCR3ConfigWithMeta) bool { - return cfg.Config.PluginType == uint8(cctypes.PluginTypeCCIPExec) - })). - Return(execOracle, nil) - }), - dons: map[registrysyncer.DonID]*ccipDeployment{}, - regState: registrysyncer.State{ - IDsToDONs: map[registrysyncer.DonID]kcr.CapabilitiesRegistryDONInfo{}, - }, - }, - args{ - diff: diffResult{ - added: map[registrysyncer.DonID]kcr.CapabilitiesRegistryDONInfo{ - 1: { - Id: 1, - NodeP2PIds: [][32]byte{ - p2pkey.MustNewV2XXXTestingOnly(big.NewInt(1)).PeerID(), - }, - }, - }, - }, - }, - func(t *testing.T, l *launcher) { - require.Len(t, l.dons, 1) - require.Len(t, l.regState.IDsToDONs, 1) - }, - false, - }, - { - "don updated new green instance success", - fields{ - lggr: logger.TestLogger(t), - p2pID: ragep2ptypes.PeerID(p2pkey.MustNewV2XXXTestingOnly(big.NewInt(1)).PeerID()), - homeChainReader: newMock(t, func(t *testing.T) *mocks.HomeChainReader { - return mocks.NewHomeChainReader(t) - }, func(m *mocks.HomeChainReader) { - m.On("GetOCRConfigs", mock.Anything, uint32(1), uint8(cctypes.PluginTypeCCIPCommit)). - Return([]ccipreaderpkg.OCR3ConfigWithMeta{{ - Config: ccipreaderpkg.OCR3Config{ - PluginType: uint8(cctypes.PluginTypeCCIPCommit), - }, - }, { - Config: ccipreaderpkg.OCR3Config{ - PluginType: uint8(cctypes.PluginTypeCCIPCommit), - }, - }}, nil) - m.On("GetOCRConfigs", mock.Anything, uint32(1), uint8(cctypes.PluginTypeCCIPExec)). - Return([]ccipreaderpkg.OCR3ConfigWithMeta{{ - Config: ccipreaderpkg.OCR3Config{ - PluginType: uint8(cctypes.PluginTypeCCIPExec), - }, - }, { - Config: ccipreaderpkg.OCR3Config{ - PluginType: uint8(cctypes.PluginTypeCCIPExec), - }, - }}, nil) - }), - oracleCreator: newMock(t, func(t *testing.T) *mocks.OracleCreator { - return mocks.NewOracleCreator(t) - }, func(m *mocks.OracleCreator) { - commitOracle := mocks.NewCCIPOracle(t) - commitOracle.On("Start").Return(nil) - execOracle := mocks.NewCCIPOracle(t) - execOracle.On("Start").Return(nil) - m.EXPECT().Create(mock.MatchedBy(func(cfg cctypes.OCR3ConfigWithMeta) bool { - return cfg.Config.PluginType == uint8(cctypes.PluginTypeCCIPCommit) - })). - Return(commitOracle, nil) - m.EXPECT().Create(mock.MatchedBy(func(cfg cctypes.OCR3ConfigWithMeta) bool { - return cfg.Config.PluginType == uint8(cctypes.PluginTypeCCIPExec) - })). - Return(execOracle, nil) - }), - dons: map[registrysyncer.DonID]*ccipDeployment{ - 1: { - commit: blueGreenDeployment{ - blue: newMock(t, func(t *testing.T) *mocks.CCIPOracle { - return mocks.NewCCIPOracle(t) - }, func(m *mocks.CCIPOracle) {}), - }, - exec: blueGreenDeployment{ - blue: newMock(t, func(t *testing.T) *mocks.CCIPOracle { - return mocks.NewCCIPOracle(t) - }, func(m *mocks.CCIPOracle) {}), - }, - }, - }, - regState: registrysyncer.State{ - IDsToDONs: map[registrysyncer.DonID]kcr.CapabilitiesRegistryDONInfo{ - 1: { - Id: 1, - NodeP2PIds: [][32]byte{ - p2pkey.MustNewV2XXXTestingOnly(big.NewInt(1)).PeerID(), - }, - }, - }, - }, - }, - args{ - diff: diffResult{ - updated: map[registrysyncer.DonID]kcr.CapabilitiesRegistryDONInfo{ - 1: { - Id: 1, - NodeP2PIds: [][32]byte{ - p2pkey.MustNewV2XXXTestingOnly(big.NewInt(1)).PeerID(), - p2pkey.MustNewV2XXXTestingOnly(big.NewInt(2)).PeerID(), // new node in don - }, - }, - }, - }, - }, - func(t *testing.T, l *launcher) { - require.Len(t, l.dons, 1) - require.Len(t, l.regState.IDsToDONs, 1) - require.Len(t, l.regState.IDsToDONs[1].NodeP2PIds, 2) - }, - false, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - l := &launcher{ - dons: tt.fields.dons, - regState: tt.fields.regState, - p2pID: tt.fields.p2pID, - lggr: tt.fields.lggr, - homeChainReader: tt.fields.homeChainReader, - oracleCreator: tt.fields.oracleCreator, - } - err := l.processDiff(tt.args.diff) - if tt.wantErr { - require.Error(t, err) - } else { - require.NoError(t, err) - } - tt.assert(t, l) - }) - } -} - -func newMock[T any](t *testing.T, newer func(t *testing.T) T, expect func(m T)) T { - o := newer(t) - expect(o) - return o -} diff --git a/core/capabilities/ccip/ocrimpls/config_digester.go b/core/capabilities/ccip/ocrimpls/config_digester.go deleted file mode 100644 index ef0c5e7ca3..0000000000 --- a/core/capabilities/ccip/ocrimpls/config_digester.go +++ /dev/null @@ -1,23 +0,0 @@ -package ocrimpls - -import "github.com/smartcontractkit/libocr/offchainreporting2plus/types" - -type configDigester struct { - d types.ConfigDigest -} - -func NewConfigDigester(d types.ConfigDigest) *configDigester { - return &configDigester{d: d} -} - -// ConfigDigest implements types.OffchainConfigDigester. -func (c *configDigester) ConfigDigest(types.ContractConfig) (types.ConfigDigest, error) { - return c.d, nil -} - -// ConfigDigestPrefix implements types.OffchainConfigDigester. -func (c *configDigester) ConfigDigestPrefix() (types.ConfigDigestPrefix, error) { - return types.ConfigDigestPrefixCCIPMultiRole, nil -} - -var _ types.OffchainConfigDigester = (*configDigester)(nil) diff --git a/core/capabilities/ccip/ocrimpls/config_tracker.go b/core/capabilities/ccip/ocrimpls/config_tracker.go deleted file mode 100644 index 3a6a27fa40..0000000000 --- a/core/capabilities/ccip/ocrimpls/config_tracker.go +++ /dev/null @@ -1,77 +0,0 @@ -package ocrimpls - -import ( - "context" - - cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" - - gethcommon "github.com/ethereum/go-ethereum/common" - "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3confighelper" - "github.com/smartcontractkit/libocr/offchainreporting2plus/types" -) - -type configTracker struct { - cfg cctypes.OCR3ConfigWithMeta -} - -func NewConfigTracker(cfg cctypes.OCR3ConfigWithMeta) *configTracker { - return &configTracker{cfg: cfg} -} - -// LatestBlockHeight implements types.ContractConfigTracker. -func (c *configTracker) LatestBlockHeight(ctx context.Context) (blockHeight uint64, err error) { - return 0, nil -} - -// LatestConfig implements types.ContractConfigTracker. -func (c *configTracker) LatestConfig(ctx context.Context, changedInBlock uint64) (types.ContractConfig, error) { - return c.contractConfig(), nil -} - -// LatestConfigDetails implements types.ContractConfigTracker. -func (c *configTracker) LatestConfigDetails(ctx context.Context) (changedInBlock uint64, configDigest types.ConfigDigest, err error) { - return 0, c.cfg.ConfigDigest, nil -} - -// Notify implements types.ContractConfigTracker. -func (c *configTracker) Notify() <-chan struct{} { - return nil -} - -func (c *configTracker) contractConfig() types.ContractConfig { - return types.ContractConfig{ - ConfigDigest: c.cfg.ConfigDigest, - ConfigCount: c.cfg.ConfigCount, - Signers: toOnchainPublicKeys(c.cfg.Config.Signers), - Transmitters: toOCRAccounts(c.cfg.Config.Transmitters), - F: c.cfg.Config.F, - OnchainConfig: []byte{}, - OffchainConfigVersion: c.cfg.Config.OffchainConfigVersion, - OffchainConfig: c.cfg.Config.OffchainConfig, - } -} - -// PublicConfig returns the OCR configuration as a PublicConfig so that we can -// access ReportingPluginConfig and other fields prior to launching the plugins. -func (c *configTracker) PublicConfig() (ocr3confighelper.PublicConfig, error) { - return ocr3confighelper.PublicConfigFromContractConfig(false, c.contractConfig()) -} - -func toOnchainPublicKeys(signers [][]byte) []types.OnchainPublicKey { - keys := make([]types.OnchainPublicKey, len(signers)) - for i, signer := range signers { - keys[i] = types.OnchainPublicKey(signer) - } - return keys -} - -func toOCRAccounts(transmitters [][]byte) []types.Account { - accounts := make([]types.Account, len(transmitters)) - for i, transmitter := range transmitters { - // TODO: string-encode the transmitter appropriately to the dest chain family. - accounts[i] = types.Account(gethcommon.BytesToAddress(transmitter).Hex()) - } - return accounts -} - -var _ types.ContractConfigTracker = (*configTracker)(nil) diff --git a/core/capabilities/ccip/ocrimpls/contract_transmitter.go b/core/capabilities/ccip/ocrimpls/contract_transmitter.go deleted file mode 100644 index fd8e206d0e..0000000000 --- a/core/capabilities/ccip/ocrimpls/contract_transmitter.go +++ /dev/null @@ -1,188 +0,0 @@ -package ocrimpls - -import ( - "context" - "errors" - "fmt" - "math/big" - - "github.com/google/uuid" - "github.com/smartcontractkit/libocr/offchainreporting2/chains/evmutil" - "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" - ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" - - "github.com/smartcontractkit/chainlink-ccip/pkg/consts" - commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" -) - -type ToCalldataFunc func(rawReportCtx [3][32]byte, report []byte, rs, ss [][32]byte, vs [32]byte) any - -func ToCommitCalldata(rawReportCtx [3][32]byte, report []byte, rs, ss [][32]byte, vs [32]byte) any { - // Note that the name of the struct field is very important, since the encoder used - // by the chainwriter uses mapstructure, which will use the struct field name to map - // to the argument name in the function call. - // If, for whatever reason, we want to change the field name, make sure to add a `mapstructure:""` tag - // for that field. - return struct { - ReportContext [3][32]byte - Report []byte - Rs [][32]byte - Ss [][32]byte - RawVs [32]byte - }{ - ReportContext: rawReportCtx, - Report: report, - Rs: rs, - Ss: ss, - RawVs: vs, - } -} - -func ToExecCalldata(rawReportCtx [3][32]byte, report []byte, _, _ [][32]byte, _ [32]byte) any { - // Note that the name of the struct field is very important, since the encoder used - // by the chainwriter uses mapstructure, which will use the struct field name to map - // to the argument name in the function call. - // If, for whatever reason, we want to change the field name, make sure to add a `mapstructure:""` tag - // for that field. - return struct { - ReportContext [3][32]byte - Report []byte - }{ - ReportContext: rawReportCtx, - Report: report, - } -} - -var _ ocr3types.ContractTransmitter[[]byte] = &commitTransmitter[[]byte]{} - -type commitTransmitter[RI any] struct { - cw commontypes.ChainWriter - fromAccount ocrtypes.Account - contractName string - method string - offrampAddress string - toCalldataFn ToCalldataFunc -} - -func XXXNewContractTransmitterTestsOnly[RI any]( - cw commontypes.ChainWriter, - fromAccount ocrtypes.Account, - contractName string, - method string, - offrampAddress string, - toCalldataFn ToCalldataFunc, -) ocr3types.ContractTransmitter[RI] { - return &commitTransmitter[RI]{ - cw: cw, - fromAccount: fromAccount, - contractName: contractName, - method: method, - offrampAddress: offrampAddress, - toCalldataFn: toCalldataFn, - } -} - -func NewCommitContractTransmitter[RI any]( - cw commontypes.ChainWriter, - fromAccount ocrtypes.Account, - offrampAddress string, -) ocr3types.ContractTransmitter[RI] { - return &commitTransmitter[RI]{ - cw: cw, - fromAccount: fromAccount, - contractName: consts.ContractNameOffRamp, - method: consts.MethodCommit, - offrampAddress: offrampAddress, - toCalldataFn: ToCommitCalldata, - } -} - -func NewExecContractTransmitter[RI any]( - cw commontypes.ChainWriter, - fromAccount ocrtypes.Account, - offrampAddress string, -) ocr3types.ContractTransmitter[RI] { - return &commitTransmitter[RI]{ - cw: cw, - fromAccount: fromAccount, - contractName: consts.ContractNameOffRamp, - method: consts.MethodExecute, - offrampAddress: offrampAddress, - toCalldataFn: ToExecCalldata, - } -} - -// FromAccount implements ocr3types.ContractTransmitter. -func (c *commitTransmitter[RI]) FromAccount() (ocrtypes.Account, error) { - return c.fromAccount, nil -} - -// Transmit implements ocr3types.ContractTransmitter. -func (c *commitTransmitter[RI]) Transmit( - ctx context.Context, - configDigest ocrtypes.ConfigDigest, - seqNr uint64, - reportWithInfo ocr3types.ReportWithInfo[RI], - sigs []ocrtypes.AttributedOnchainSignature, -) error { - var rs [][32]byte - var ss [][32]byte - var vs [32]byte - if len(sigs) > 32 { - return errors.New("too many signatures, maximum is 32") - } - for i, as := range sigs { - r, s, v, err := evmutil.SplitSignature(as.Signature) - if err != nil { - return fmt.Errorf("failed to split signature: %w", err) - } - rs = append(rs, r) - ss = append(ss, s) - vs[i] = v - } - - // report ctx for OCR3 consists of the following - // reportContext[0]: ConfigDigest - // reportContext[1]: 24 byte padding, 8 byte sequence number - // reportContext[2]: unused - // convert seqNum, which is a uint64, into a uint32 epoch and uint8 round - // while this does truncate the sequence number, it is not a problem because - // it still gives us 2^40 - 1 possible sequence numbers. - // assuming a sequence number is generated every second, this gives us - // 1099511627775 seconds, or approximately 34,865 years, before we run out - // of sequence numbers. - epoch, round := uint64ToUint32AndUint8(seqNr) - rawReportCtx := evmutil.RawReportContext(ocrtypes.ReportContext{ - ReportTimestamp: ocrtypes.ReportTimestamp{ - ConfigDigest: configDigest, - Epoch: epoch, - Round: round, - }, - // ExtraData not used in OCR3 - }) - - if c.toCalldataFn == nil { - return errors.New("toCalldataFn is nil") - } - - // chain writer takes in the raw calldata and packs it on its own. - args := c.toCalldataFn(rawReportCtx, reportWithInfo.Report, rs, ss, vs) - - // TODO: no meta fields yet, what should we add? - // probably whats in the info part of the report? - meta := commontypes.TxMeta{} - txID, err := uuid.NewRandom() // NOTE: CW expects us to generate an ID, rather than return one - if err != nil { - return fmt.Errorf("failed to generate UUID: %w", err) - } - zero := big.NewInt(0) - if err := c.cw.SubmitTransaction(ctx, c.contractName, c.method, args, fmt.Sprintf("%s-%s-%s", c.contractName, c.offrampAddress, txID.String()), c.offrampAddress, &meta, zero); err != nil { - return fmt.Errorf("failed to submit transaction thru chainwriter: %w", err) - } - - return nil -} - -func uint64ToUint32AndUint8(x uint64) (uint32, uint8) { - return uint32(x >> 32), uint8(x) -} diff --git a/core/capabilities/ccip/ocrimpls/contract_transmitter_test.go b/core/capabilities/ccip/ocrimpls/contract_transmitter_test.go deleted file mode 100644 index 4e0a7162aa..0000000000 --- a/core/capabilities/ccip/ocrimpls/contract_transmitter_test.go +++ /dev/null @@ -1,690 +0,0 @@ -package ocrimpls_test - -import ( - "crypto/rand" - "math/big" - "net/url" - "testing" - "time" - - "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ocrimpls" - cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/core" - "github.com/jmoiron/sqlx" - "github.com/onsi/gomega" - "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/libocr/commontypes" - "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" - ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" - - "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" - txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr" - - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" - evmconfig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/chaintype" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/keystore" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" - "github.com/smartcontractkit/chainlink/v2/core/config" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/multi_ocr3_helper" - "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" - "github.com/smartcontractkit/chainlink/v2/core/logger" - kschaintype "github.com/smartcontractkit/chainlink/v2/core/services/keystore/chaintype" - "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ocr2key" - "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" - evmrelaytypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" -) - -func Test_ContractTransmitter_TransmitWithoutSignatures(t *testing.T) { - type testCase struct { - name string - pluginType uint8 - withSigs bool - expectedSigsEnabled bool - report []byte - } - - testCases := []testCase{ - { - "empty report with sigs", - uint8(cctypes.PluginTypeCCIPCommit), - true, - true, - []byte{}, - }, - { - "empty report without sigs", - uint8(cctypes.PluginTypeCCIPExec), - false, - false, - []byte{}, - }, - { - "report with data with sigs", - uint8(cctypes.PluginTypeCCIPCommit), - true, - true, - randomReport(t, 96), - }, - { - "report with data without sigs", - uint8(cctypes.PluginTypeCCIPExec), - false, - false, - randomReport(t, 96), - }, - } - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - tc := tc - t.Parallel() - testTransmitter(t, tc.pluginType, tc.withSigs, tc.expectedSigsEnabled, tc.report) - }) - } -} - -func testTransmitter( - t *testing.T, - pluginType uint8, - withSigs bool, - expectedSigsEnabled bool, - report []byte, -) { - uni := newTestUniverse[[]byte](t, nil) - - c, err := uni.wrapper.LatestConfigDetails(nil, pluginType) - require.NoError(t, err, "failed to get latest config details") - configDigest := c.ConfigInfo.ConfigDigest - require.Equal(t, expectedSigsEnabled, c.ConfigInfo.IsSignatureVerificationEnabled, "signature verification enabled setting not correct") - - // set the plugin type on the helper so it fetches the right config info. - // the important aspect is whether signatures should be enabled or not. - _, err = uni.wrapper.SetTransmitOcrPluginType(uni.deployer, pluginType) - require.NoError(t, err, "failed to set plugin type") - uni.backend.Commit() - - // create attributed sigs - // only need f+1 which is 2 in this case - rwi := ocr3types.ReportWithInfo[[]byte]{ - Report: report, - Info: []byte{}, - } - seqNr := uint64(1) - attributedSigs := uni.SignReport(t, configDigest, rwi, seqNr) - - account, err := uni.transmitterWithSigs.FromAccount() - require.NoError(t, err, "failed to get from account") - require.Equal(t, ocrtypes.Account(uni.transmitters[0].Hex()), account, "from account mismatch") - if withSigs { - err = uni.transmitterWithSigs.Transmit(testutils.Context(t), configDigest, seqNr, rwi, attributedSigs) - } else { - err = uni.transmitterWithoutSigs.Transmit(testutils.Context(t), configDigest, seqNr, rwi, attributedSigs) - } - require.NoError(t, err, "failed to transmit") - uni.backend.Commit() - - var txStatus uint64 - gomega.NewWithT(t).Eventually(func() bool { - uni.backend.Commit() - rows, err := uni.db.QueryContext(testutils.Context(t), `SELECT hash FROM evm.tx_attempts LIMIT 1`) - require.NoError(t, err, "failed to query txes") - defer rows.Close() - var txHash []byte - for rows.Next() { - require.NoError(t, rows.Scan(&txHash), "failed to scan") - } - t.Log("txHash:", txHash) - receipt, err := uni.simClient.TransactionReceipt(testutils.Context(t), common.BytesToHash(txHash)) - if err != nil { - t.Log("tx not found yet:", hexutil.Encode(txHash)) - return false - } - t.Log("tx found:", hexutil.Encode(txHash), "status:", receipt.Status) - txStatus = receipt.Status - return true - }, testutils.WaitTimeout(t), 1*time.Second).Should(gomega.BeTrue()) - - // wait for receipt to be written to the db - gomega.NewWithT(t).Eventually(func() bool { - rows, err := uni.db.QueryContext(testutils.Context(t), `SELECT count(*) as cnt FROM evm.receipts LIMIT 1`) - require.NoError(t, err, "failed to query receipts") - defer rows.Close() - var count int - for rows.Next() { - require.NoError(t, rows.Scan(&count), "failed to scan") - } - return count == 1 - }, testutils.WaitTimeout(t), 2*time.Second).Should(gomega.BeTrue()) - - require.Equal(t, uint64(1), txStatus, "tx status should be success") - - // check that the event was emitted - events := uni.TransmittedEvents(t) - require.Len(t, events, 1, "expected 1 event") - require.Equal(t, configDigest, events[0].ConfigDigest, "config digest mismatch") - require.Equal(t, seqNr, events[0].SequenceNumber, "seq num mismatch") -} - -type testUniverse[RI any] struct { - simClient *client.SimulatedBackendClient - backend *backends.SimulatedBackend - deployer *bind.TransactOpts - transmitters []common.Address - signers []common.Address - wrapper *multi_ocr3_helper.MultiOCR3Helper - transmitterWithSigs ocr3types.ContractTransmitter[RI] - transmitterWithoutSigs ocr3types.ContractTransmitter[RI] - keyrings []ocr3types.OnchainKeyring[RI] - f uint8 - db *sqlx.DB - txm txmgr.TxManager - gasEstimator gas.EvmFeeEstimator -} - -type keyringsAndSigners[RI any] struct { - keyrings []ocr3types.OnchainKeyring[RI] - signers []common.Address -} - -func newTestUniverse[RI any](t *testing.T, ks *keyringsAndSigners[RI]) *testUniverse[RI] { - t.Helper() - - db := pgtest.NewSqlxDB(t) - owner := testutils.MustNewSimTransactor(t) - - // create many transmitters but only need to fund one, rest are to get - // setOCR3Config to pass. - keyStore := cltest.NewKeyStore(t, db) - var transmitters []common.Address - for i := 0; i < 4; i++ { - key, err := keyStore.Eth().Create(testutils.Context(t), big.NewInt(1337)) - require.NoError(t, err, "failed to create key") - transmitters = append(transmitters, key.Address) - } - - backend := backends.NewSimulatedBackend(core.GenesisAlloc{ - owner.From: core.GenesisAccount{ - Balance: assets.Ether(1000).ToInt(), - }, - transmitters[0]: core.GenesisAccount{ - Balance: assets.Ether(1000).ToInt(), - }, - }, 30e6) - - ocr3HelperAddr, _, _, err := multi_ocr3_helper.DeployMultiOCR3Helper(owner, backend) - require.NoError(t, err) - backend.Commit() - wrapper, err := multi_ocr3_helper.NewMultiOCR3Helper(ocr3HelperAddr, backend) - require.NoError(t, err) - - // create the oracle identities for setConfig - // need to create at least 4 identities otherwise setConfig will fail - var ( - keyrings []ocr3types.OnchainKeyring[RI] - signers []common.Address - ) - if ks != nil { - keyrings = ks.keyrings - signers = ks.signers - } else { - for i := 0; i < 4; i++ { - kb, err2 := ocr2key.New(kschaintype.EVM) - require.NoError(t, err2, "failed to create key") - kr := ocrimpls.NewOnchainKeyring[RI](kb, logger.TestLogger(t)) - signers = append(signers, common.BytesToAddress(kr.PublicKey())) - keyrings = append(keyrings, kr) - } - } - f := uint8(1) - commitConfigDigest := testutils.Random32Byte() - execConfigDigest := testutils.Random32Byte() - _, err = wrapper.SetOCR3Configs( - owner, - []multi_ocr3_helper.MultiOCR3BaseOCRConfigArgs{ - { - ConfigDigest: commitConfigDigest, - OcrPluginType: uint8(cctypes.PluginTypeCCIPCommit), - F: f, - IsSignatureVerificationEnabled: true, - Signers: signers, - Transmitters: []common.Address{ - transmitters[0], - transmitters[1], - transmitters[2], - transmitters[3], - }, - }, - { - ConfigDigest: execConfigDigest, - OcrPluginType: uint8(cctypes.PluginTypeCCIPExec), - F: f, - IsSignatureVerificationEnabled: false, - Signers: signers, - Transmitters: []common.Address{ - transmitters[0], - transmitters[1], - transmitters[2], - transmitters[3], - }, - }, - }, - ) - require.NoError(t, err) - backend.Commit() - - commitConfig, err := wrapper.LatestConfigDetails(nil, uint8(cctypes.PluginTypeCCIPCommit)) - require.NoError(t, err, "failed to get latest commit config") - require.Equal(t, commitConfigDigest, commitConfig.ConfigInfo.ConfigDigest, "commit config digest mismatch") - execConfig, err := wrapper.LatestConfigDetails(nil, uint8(cctypes.PluginTypeCCIPExec)) - require.NoError(t, err, "failed to get latest exec config") - require.Equal(t, execConfigDigest, execConfig.ConfigInfo.ConfigDigest, "exec config digest mismatch") - - simClient := client.NewSimulatedBackendClient(t, backend, testutils.SimulatedChainID) - - // create the chain writer service - txm, gasEstimator := makeTestEvmTxm(t, db, simClient, keyStore.Eth()) - require.NoError(t, txm.Start(testutils.Context(t)), "failed to start tx manager") - t.Cleanup(func() { require.NoError(t, txm.Close()) }) - - chainWriter, err := evm.NewChainWriterService( - logger.TestLogger(t), - simClient, - txm, - gasEstimator, - chainWriterConfigRaw(transmitters[0], assets.GWei(1))) - require.NoError(t, err, "failed to create chain writer") - require.NoError(t, chainWriter.Start(testutils.Context(t)), "failed to start chain writer") - t.Cleanup(func() { require.NoError(t, chainWriter.Close()) }) - - transmitterWithSigs := ocrimpls.XXXNewContractTransmitterTestsOnly[RI]( - chainWriter, - ocrtypes.Account(transmitters[0].Hex()), - contractName, - methodTransmitWithSignatures, - ocr3HelperAddr.Hex(), - ocrimpls.ToCommitCalldata, - ) - transmitterWithoutSigs := ocrimpls.XXXNewContractTransmitterTestsOnly[RI]( - chainWriter, - ocrtypes.Account(transmitters[0].Hex()), - contractName, - methodTransmitWithoutSignatures, - ocr3HelperAddr.Hex(), - ocrimpls.ToExecCalldata, - ) - - return &testUniverse[RI]{ - simClient: simClient, - backend: backend, - deployer: owner, - transmitters: transmitters, - signers: signers, - wrapper: wrapper, - transmitterWithSigs: transmitterWithSigs, - transmitterWithoutSigs: transmitterWithoutSigs, - keyrings: keyrings, - f: f, - db: db, - txm: txm, - gasEstimator: gasEstimator, - } -} - -func (uni testUniverse[RI]) SignReport(t *testing.T, configDigest ocrtypes.ConfigDigest, rwi ocr3types.ReportWithInfo[RI], seqNum uint64) []ocrtypes.AttributedOnchainSignature { - var attributedSigs []ocrtypes.AttributedOnchainSignature - for i := uint8(0); i < uni.f+1; i++ { - t.Log("signing report with", hexutil.Encode(uni.keyrings[i].PublicKey())) - sig, err := uni.keyrings[i].Sign(configDigest, seqNum, rwi) - require.NoError(t, err, "failed to sign report") - attributedSigs = append(attributedSigs, ocrtypes.AttributedOnchainSignature{ - Signature: sig, - Signer: commontypes.OracleID(i), - }) - } - return attributedSigs -} - -func (uni testUniverse[RI]) TransmittedEvents(t *testing.T) []*multi_ocr3_helper.MultiOCR3HelperTransmitted { - iter, err := uni.wrapper.FilterTransmitted(&bind.FilterOpts{ - Start: 0, - }, nil) - require.NoError(t, err, "failed to create filter iterator") - var events []*multi_ocr3_helper.MultiOCR3HelperTransmitted - for iter.Next() { - event := iter.Event - events = append(events, event) - } - return events -} - -func randomReport(t *testing.T, len int) []byte { - report := make([]byte, len) - _, err := rand.Reader.Read(report) - require.NoError(t, err, "failed to read random bytes") - return report -} - -const ( - contractName = "MultiOCR3Helper" - methodTransmitWithSignatures = "TransmitWithSignatures" - methodTransmitWithoutSignatures = "TransmitWithoutSignatures" -) - -func chainWriterConfigRaw(fromAddress common.Address, maxGasPrice *assets.Wei) evmrelaytypes.ChainWriterConfig { - return evmrelaytypes.ChainWriterConfig{ - Contracts: map[string]*evmrelaytypes.ContractConfig{ - contractName: { - ContractABI: multi_ocr3_helper.MultiOCR3HelperABI, - Configs: map[string]*evmrelaytypes.ChainWriterDefinition{ - methodTransmitWithSignatures: { - ChainSpecificName: "transmitWithSignatures", - GasLimit: 1e6, - FromAddress: fromAddress, - }, - methodTransmitWithoutSignatures: { - ChainSpecificName: "transmitWithoutSignatures", - GasLimit: 1e6, - FromAddress: fromAddress, - }, - }, - }, - }, - SendStrategy: txmgrcommon.NewSendEveryStrategy(), - MaxGasPrice: maxGasPrice, - } -} - -func makeTestEvmTxm( - t *testing.T, - db *sqlx.DB, - ethClient client.Client, - keyStore keystore.Eth) (txmgr.TxManager, gas.EvmFeeEstimator) { - config, dbConfig, evmConfig := MakeTestConfigs(t) - - estimator, err := gas.NewEstimator(logger.TestLogger(t), ethClient, config, evmConfig.GasEstimator()) - require.NoError(t, err, "failed to create gas estimator") - - lggr := logger.TestLogger(t) - lpOpts := logpoller.Opts{ - PollPeriod: 100 * time.Millisecond, - FinalityDepth: 2, - BackfillBatchSize: 3, - RpcBatchSize: 2, - KeepFinalizedBlocksDepth: 1000, - } - - chainID := big.NewInt(1337) - headSaver := headtracker.NewHeadSaver( - logger.NullLogger, - headtracker.NewORM(*chainID, db), - evmConfig, - evmConfig.HeadTrackerConfig, - ) - - broadcaster := headtracker.NewHeadBroadcaster(logger.NullLogger) - require.NoError(t, broadcaster.Start(testutils.Context(t)), "failed to start head broadcaster") - t.Cleanup(func() { require.NoError(t, broadcaster.Close()) }) - - ht := headtracker.NewHeadTracker( - logger.NullLogger, - ethClient, - evmConfig, - evmConfig.HeadTrackerConfig, - broadcaster, - headSaver, - mailbox.NewMonitor("contract_transmitter_test", logger.NullLogger), - ) - require.NoError(t, ht.Start(testutils.Context(t)), "failed to start head tracker") - t.Cleanup(func() { require.NoError(t, ht.Close()) }) - - lp := logpoller.NewLogPoller(logpoller.NewORM(testutils.FixtureChainID, db, logger.NullLogger), - ethClient, logger.NullLogger, ht, lpOpts) - require.NoError(t, lp.Start(testutils.Context(t)), "failed to start log poller") - t.Cleanup(func() { require.NoError(t, lp.Close()) }) - - // logic for building components (from evm/evm_txm.go) ------- - lggr.Infow("Initializing EVM transaction manager", - "bumpTxDepth", evmConfig.GasEstimator().BumpTxDepth(), - "maxInFlightTransactions", config.EvmConfig.Transactions().MaxInFlight(), - "maxQueuedTransactions", config.EvmConfig.Transactions().MaxQueued(), - "nonceAutoSync", evmConfig.NonceAutoSync(), - "limitDefault", evmConfig.GasEstimator().LimitDefault(), - ) - - txm, err := txmgr.NewTxm( - db, - config, - config.EvmConfig.GasEstimator(), - config.EvmConfig.Transactions(), - nil, - dbConfig, - dbConfig.Listener(), - ethClient, - lggr, - lp, - keyStore, - estimator) - require.NoError(t, err, "can't create tx manager") - - _, unsub := broadcaster.Subscribe(txm) - t.Cleanup(unsub) - - return txm, estimator -} - -// Code below copied/pasted and slightly modified in order to work from core/chains/evm/txmgr/test_helpers.go. - -func ptr[T any](t T) *T { return &t } - -type TestDatabaseConfig struct { - config.Database - defaultQueryTimeout time.Duration -} - -func (d *TestDatabaseConfig) DefaultQueryTimeout() time.Duration { - return d.defaultQueryTimeout -} - -func (d *TestDatabaseConfig) LogSQL() bool { - return false -} - -type TestListenerConfig struct { - config.Listener -} - -func (l *TestListenerConfig) FallbackPollInterval() time.Duration { - return 1 * time.Minute -} - -func (d *TestDatabaseConfig) Listener() config.Listener { - return &TestListenerConfig{} -} - -type TestHeadTrackerConfig struct{} - -// FinalityTagBypass implements config.HeadTracker. -func (t *TestHeadTrackerConfig) FinalityTagBypass() bool { - return false -} - -// HistoryDepth implements config.HeadTracker. -func (t *TestHeadTrackerConfig) HistoryDepth() uint32 { - return 50 -} - -// MaxAllowedFinalityDepth implements config.HeadTracker. -func (t *TestHeadTrackerConfig) MaxAllowedFinalityDepth() uint32 { - return 100 -} - -// MaxBufferSize implements config.HeadTracker. -func (t *TestHeadTrackerConfig) MaxBufferSize() uint32 { - return 100 -} - -// SamplingInterval implements config.HeadTracker. -func (t *TestHeadTrackerConfig) SamplingInterval() time.Duration { - return 1 * time.Second -} - -var _ evmconfig.HeadTracker = (*TestHeadTrackerConfig)(nil) - -type TestEvmConfig struct { - evmconfig.EVM - HeadTrackerConfig evmconfig.HeadTracker - MaxInFlight uint32 - ReaperInterval time.Duration - ReaperThreshold time.Duration - ResendAfterThreshold time.Duration - BumpThreshold uint64 - MaxQueued uint64 - Enabled bool - Threshold uint32 - MinAttempts uint32 - DetectionApiUrl *url.URL -} - -func (e *TestEvmConfig) FinalityTagEnabled() bool { - return false -} - -func (e *TestEvmConfig) FinalityDepth() uint32 { - return 42 -} - -func (e *TestEvmConfig) FinalizedBlockOffset() uint32 { - return 42 -} - -func (e *TestEvmConfig) BlockEmissionIdleWarningThreshold() time.Duration { - return 10 * time.Second -} - -func (e *TestEvmConfig) Transactions() evmconfig.Transactions { - return &transactionsConfig{e: e, autoPurge: &autoPurgeConfig{}} -} - -func (e *TestEvmConfig) NonceAutoSync() bool { return true } - -func (e *TestEvmConfig) ChainType() chaintype.ChainType { return "" } - -type TestGasEstimatorConfig struct { - bumpThreshold uint64 -} - -func (g *TestGasEstimatorConfig) BlockHistory() evmconfig.BlockHistory { - return &TestBlockHistoryConfig{} -} - -func (g *TestGasEstimatorConfig) EIP1559DynamicFees() bool { return false } -func (g *TestGasEstimatorConfig) LimitDefault() uint64 { return 1e6 } -func (g *TestGasEstimatorConfig) BumpPercent() uint16 { return 2 } -func (g *TestGasEstimatorConfig) BumpThreshold() uint64 { return g.bumpThreshold } -func (g *TestGasEstimatorConfig) BumpMin() *assets.Wei { return assets.GWei(1) } -func (g *TestGasEstimatorConfig) FeeCapDefault() *assets.Wei { return assets.GWei(1) } -func (g *TestGasEstimatorConfig) PriceDefault() *assets.Wei { return assets.GWei(1) } -func (g *TestGasEstimatorConfig) TipCapDefault() *assets.Wei { return assets.GWei(1) } -func (g *TestGasEstimatorConfig) TipCapMin() *assets.Wei { return assets.GWei(1) } -func (g *TestGasEstimatorConfig) LimitMax() uint64 { return 0 } -func (g *TestGasEstimatorConfig) LimitMultiplier() float32 { return 1 } -func (g *TestGasEstimatorConfig) BumpTxDepth() uint32 { return 42 } -func (g *TestGasEstimatorConfig) LimitTransfer() uint64 { return 42 } -func (g *TestGasEstimatorConfig) PriceMax() *assets.Wei { return assets.GWei(1) } -func (g *TestGasEstimatorConfig) PriceMin() *assets.Wei { return assets.GWei(1) } -func (g *TestGasEstimatorConfig) Mode() string { return "FixedPrice" } -func (g *TestGasEstimatorConfig) LimitJobType() evmconfig.LimitJobType { - return &TestLimitJobTypeConfig{} -} -func (g *TestGasEstimatorConfig) PriceMaxKey(addr common.Address) *assets.Wei { - return assets.GWei(1) -} - -func (e *TestEvmConfig) GasEstimator() evmconfig.GasEstimator { - return &TestGasEstimatorConfig{bumpThreshold: e.BumpThreshold} -} - -type TestLimitJobTypeConfig struct { -} - -func (l *TestLimitJobTypeConfig) OCR() *uint32 { return ptr(uint32(0)) } -func (l *TestLimitJobTypeConfig) OCR2() *uint32 { return ptr(uint32(0)) } -func (l *TestLimitJobTypeConfig) DR() *uint32 { return ptr(uint32(0)) } -func (l *TestLimitJobTypeConfig) FM() *uint32 { return ptr(uint32(0)) } -func (l *TestLimitJobTypeConfig) Keeper() *uint32 { return ptr(uint32(0)) } -func (l *TestLimitJobTypeConfig) VRF() *uint32 { return ptr(uint32(0)) } - -type TestBlockHistoryConfig struct { - evmconfig.BlockHistory -} - -func (b *TestBlockHistoryConfig) BatchSize() uint32 { return 42 } -func (b *TestBlockHistoryConfig) BlockDelay() uint16 { return 42 } -func (b *TestBlockHistoryConfig) BlockHistorySize() uint16 { return 42 } -func (b *TestBlockHistoryConfig) EIP1559FeeCapBufferBlocks() uint16 { return 42 } -func (b *TestBlockHistoryConfig) TransactionPercentile() uint16 { return 42 } - -type transactionsConfig struct { - evmconfig.Transactions - e *TestEvmConfig - autoPurge evmconfig.AutoPurgeConfig -} - -func (*transactionsConfig) ForwardersEnabled() bool { return false } -func (t *transactionsConfig) MaxInFlight() uint32 { return t.e.MaxInFlight } -func (t *transactionsConfig) MaxQueued() uint64 { return t.e.MaxQueued } -func (t *transactionsConfig) ReaperInterval() time.Duration { return t.e.ReaperInterval } -func (t *transactionsConfig) ReaperThreshold() time.Duration { return t.e.ReaperThreshold } -func (t *transactionsConfig) ResendAfterThreshold() time.Duration { return t.e.ResendAfterThreshold } -func (t *transactionsConfig) AutoPurge() evmconfig.AutoPurgeConfig { return t.autoPurge } - -type autoPurgeConfig struct { - evmconfig.AutoPurgeConfig -} - -func (a *autoPurgeConfig) Enabled() bool { return false } - -type MockConfig struct { - EvmConfig *TestEvmConfig - RpcDefaultBatchSize uint32 - finalityDepth uint32 - finalityTagEnabled bool -} - -func (c *MockConfig) EVM() evmconfig.EVM { - return c.EvmConfig -} - -func (c *MockConfig) NonceAutoSync() bool { return true } -func (c *MockConfig) ChainType() chaintype.ChainType { return "" } -func (c *MockConfig) FinalityDepth() uint32 { return c.finalityDepth } -func (c *MockConfig) SetFinalityDepth(fd uint32) { c.finalityDepth = fd } -func (c *MockConfig) FinalityTagEnabled() bool { return c.finalityTagEnabled } -func (c *MockConfig) RPCDefaultBatchSize() uint32 { return c.RpcDefaultBatchSize } - -func MakeTestConfigs(t *testing.T) (*MockConfig, *TestDatabaseConfig, *TestEvmConfig) { - db := &TestDatabaseConfig{defaultQueryTimeout: utils.DefaultQueryTimeout} - ec := &TestEvmConfig{ - HeadTrackerConfig: &TestHeadTrackerConfig{}, - BumpThreshold: 42, - MaxInFlight: uint32(42), - MaxQueued: uint64(0), - ReaperInterval: time.Duration(0), - ReaperThreshold: time.Duration(0), - } - config := &MockConfig{EvmConfig: ec} - return config, db, ec -} diff --git a/core/capabilities/ccip/ocrimpls/keyring.go b/core/capabilities/ccip/ocrimpls/keyring.go deleted file mode 100644 index 4b15c75b09..0000000000 --- a/core/capabilities/ccip/ocrimpls/keyring.go +++ /dev/null @@ -1,61 +0,0 @@ -package ocrimpls - -import ( - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" - "github.com/smartcontractkit/libocr/offchainreporting2plus/types" - - "github.com/smartcontractkit/chainlink/v2/core/logger" -) - -var _ ocr3types.OnchainKeyring[[]byte] = &ocr3Keyring[[]byte]{} - -type ocr3Keyring[RI any] struct { - core types.OnchainKeyring - lggr logger.Logger -} - -func NewOnchainKeyring[RI any](keyring types.OnchainKeyring, lggr logger.Logger) *ocr3Keyring[RI] { - return &ocr3Keyring[RI]{ - core: keyring, - lggr: lggr.Named("OCR3Keyring"), - } -} - -func (w *ocr3Keyring[RI]) PublicKey() types.OnchainPublicKey { - return w.core.PublicKey() -} - -func (w *ocr3Keyring[RI]) MaxSignatureLength() int { - return w.core.MaxSignatureLength() -} - -func (w *ocr3Keyring[RI]) Sign(configDigest types.ConfigDigest, seqNr uint64, r ocr3types.ReportWithInfo[RI]) (signature []byte, err error) { - epoch, round := uint64ToUint32AndUint8(seqNr) - rCtx := types.ReportContext{ - ReportTimestamp: types.ReportTimestamp{ - ConfigDigest: configDigest, - Epoch: epoch, - Round: round, - }, - } - - w.lggr.Debugw("signing report", "configDigest", configDigest.Hex(), "seqNr", seqNr, "report", hexutil.Encode(r.Report)) - - return w.core.Sign(rCtx, r.Report) -} - -func (w *ocr3Keyring[RI]) Verify(key types.OnchainPublicKey, configDigest types.ConfigDigest, seqNr uint64, r ocr3types.ReportWithInfo[RI], signature []byte) bool { - epoch, round := uint64ToUint32AndUint8(seqNr) - rCtx := types.ReportContext{ - ReportTimestamp: types.ReportTimestamp{ - ConfigDigest: configDigest, - Epoch: epoch, - Round: round, - }, - } - - w.lggr.Debugw("verifying report", "configDigest", configDigest.Hex(), "seqNr", seqNr, "report", hexutil.Encode(r.Report)) - - return w.core.Verify(key, rCtx, r.Report, signature) -} diff --git a/core/capabilities/ccip/oraclecreator/bootstrap.go b/core/capabilities/ccip/oraclecreator/bootstrap.go deleted file mode 100644 index a4bf03a4de..0000000000 --- a/core/capabilities/ccip/oraclecreator/bootstrap.go +++ /dev/null @@ -1,97 +0,0 @@ -package oraclecreator - -import ( - "context" - "fmt" - - "github.com/ethereum/go-ethereum/common/hexutil" - - chainsel "github.com/smartcontractkit/chain-selectors" - "github.com/smartcontractkit/libocr/commontypes" - libocr3 "github.com/smartcontractkit/libocr/offchainreporting2plus" - "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" - - "github.com/smartcontractkit/chainlink-common/pkg/types" - - "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ocrimpls" - cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" - "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/keystore/chaintype" - "github.com/smartcontractkit/chainlink/v2/core/services/ocrcommon" - "github.com/smartcontractkit/chainlink/v2/core/services/synchronization" - "github.com/smartcontractkit/chainlink/v2/core/services/telemetry" -) - -var _ cctypes.OracleCreator = &bootstrapOracleCreator{} - -type bootstrapOracleCreator struct { - peerWrapper *ocrcommon.SingletonPeerWrapper - bootstrapperLocators []commontypes.BootstrapperLocator - db ocr3types.Database - monitoringEndpointGen telemetry.MonitoringEndpointGenerator - lggr logger.Logger -} - -func NewBootstrapOracleCreator( - peerWrapper *ocrcommon.SingletonPeerWrapper, - bootstrapperLocators []commontypes.BootstrapperLocator, - db ocr3types.Database, - monitoringEndpointGen telemetry.MonitoringEndpointGenerator, - lggr logger.Logger, -) cctypes.OracleCreator { - return &bootstrapOracleCreator{ - peerWrapper: peerWrapper, - bootstrapperLocators: bootstrapperLocators, - db: db, - monitoringEndpointGen: monitoringEndpointGen, - lggr: lggr, - } -} - -// Type implements types.OracleCreator. -func (i *bootstrapOracleCreator) Type() cctypes.OracleType { - return cctypes.OracleTypeBootstrap -} - -// Create implements types.OracleCreator. -func (i *bootstrapOracleCreator) Create(config cctypes.OCR3ConfigWithMeta) (cctypes.CCIPOracle, error) { - // Assuming that the chain selector is referring to an evm chain for now. - // TODO: add an api that returns chain family. - // NOTE: this doesn't really matter for the bootstrap node, it doesn't do anything on-chain. - // Its for the monitoring endpoint generation below. - chainID, err := chainsel.ChainIdFromSelector(uint64(config.Config.ChainSelector)) - if err != nil { - return nil, fmt.Errorf("failed to get chain ID from selector: %w", err) - } - - destChainFamily := chaintype.EVM - destRelayID := types.NewRelayID(string(destChainFamily), fmt.Sprintf("%d", chainID)) - - bootstrapperArgs := libocr3.BootstrapperArgs{ - BootstrapperFactory: i.peerWrapper.Peer2, - V2Bootstrappers: i.bootstrapperLocators, - ContractConfigTracker: ocrimpls.NewConfigTracker(config), - Database: i.db, - LocalConfig: defaultLocalConfig(), - Logger: ocrcommon.NewOCRWrapper( - i.lggr. - Named("CCIPBootstrap"). - Named(destRelayID.String()). - Named(config.Config.ChainSelector.String()). - Named(hexutil.Encode(config.Config.OfframpAddress)), - false, /* traceLogging */ - func(ctx context.Context, msg string) {}), - MonitoringEndpoint: i.monitoringEndpointGen.GenMonitoringEndpoint( - string(destChainFamily), - destRelayID.ChainID, - hexutil.Encode(config.Config.OfframpAddress), - synchronization.OCR3CCIPBootstrap, - ), - OffchainConfigDigester: ocrimpls.NewConfigDigester(config.ConfigDigest), - } - bootstrapper, err := libocr3.NewBootstrapper(bootstrapperArgs) - if err != nil { - return nil, err - } - return bootstrapper, nil -} diff --git a/core/capabilities/ccip/oraclecreator/plugin.go b/core/capabilities/ccip/oraclecreator/plugin.go deleted file mode 100644 index c87c4e97c1..0000000000 --- a/core/capabilities/ccip/oraclecreator/plugin.go +++ /dev/null @@ -1,377 +0,0 @@ -package oraclecreator - -import ( - "context" - "fmt" - "time" - - "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ccipevm" - evmconfig "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/configs/evm" - "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ocrimpls" - "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/superfakes" - cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/google/uuid" - "github.com/prometheus/client_golang/prometheus" - - chainsel "github.com/smartcontractkit/chain-selectors" - - "github.com/smartcontractkit/chainlink-ccip/pkg/consts" - "github.com/smartcontractkit/chainlink-ccip/pluginconfig" - - "github.com/smartcontractkit/libocr/commontypes" - libocr3 "github.com/smartcontractkit/libocr/offchainreporting2plus" - "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3types" - ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" - - cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3" - - commitocr3 "github.com/smartcontractkit/chainlink-ccip/commit" - execocr3 "github.com/smartcontractkit/chainlink-ccip/execute" - ccipreaderpkg "github.com/smartcontractkit/chainlink-ccip/pkg/reader" - - "github.com/smartcontractkit/chainlink-common/pkg/types" - "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" - "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/job" - "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ocr2key" - "github.com/smartcontractkit/chainlink/v2/core/services/ocrcommon" - "github.com/smartcontractkit/chainlink/v2/core/services/relay" - "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm" - evmrelaytypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" - "github.com/smartcontractkit/chainlink/v2/core/services/synchronization" - "github.com/smartcontractkit/chainlink/v2/core/services/telemetry" -) - -var _ cctypes.OracleCreator = &pluginOracleCreator{} - -const ( - defaultCommitGasLimit = 500_000 -) - -// pluginOracleCreator creates oracles that reference plugins running -// in the same process as the chainlink node, i.e not LOOPPs. -type pluginOracleCreator struct { - ocrKeyBundles map[string]ocr2key.KeyBundle - transmitters map[types.RelayID][]string - chains legacyevm.LegacyChainContainer - peerWrapper *ocrcommon.SingletonPeerWrapper - externalJobID uuid.UUID - jobID int32 - isNewlyCreatedJob bool - pluginConfig job.JSONConfig - db ocr3types.Database - lggr logger.Logger - monitoringEndpointGen telemetry.MonitoringEndpointGenerator - bootstrapperLocators []commontypes.BootstrapperLocator - homeChainReader ccipreaderpkg.HomeChain -} - -func NewPluginOracleCreator( - ocrKeyBundles map[string]ocr2key.KeyBundle, - transmitters map[types.RelayID][]string, - chains legacyevm.LegacyChainContainer, - peerWrapper *ocrcommon.SingletonPeerWrapper, - externalJobID uuid.UUID, - jobID int32, - isNewlyCreatedJob bool, - pluginConfig job.JSONConfig, - db ocr3types.Database, - lggr logger.Logger, - monitoringEndpointGen telemetry.MonitoringEndpointGenerator, - bootstrapperLocators []commontypes.BootstrapperLocator, - homeChainReader ccipreaderpkg.HomeChain, -) cctypes.OracleCreator { - return &pluginOracleCreator{ - ocrKeyBundles: ocrKeyBundles, - transmitters: transmitters, - chains: chains, - peerWrapper: peerWrapper, - externalJobID: externalJobID, - jobID: jobID, - isNewlyCreatedJob: isNewlyCreatedJob, - pluginConfig: pluginConfig, - db: db, - lggr: lggr, - monitoringEndpointGen: monitoringEndpointGen, - bootstrapperLocators: bootstrapperLocators, - homeChainReader: homeChainReader, - } -} - -// Type implements types.OracleCreator. -func (i *pluginOracleCreator) Type() cctypes.OracleType { - return cctypes.OracleTypePlugin -} - -// Create implements types.OracleCreator. -func (i *pluginOracleCreator) Create(config cctypes.OCR3ConfigWithMeta) (cctypes.CCIPOracle, error) { - pluginType := cctypes.PluginType(config.Config.PluginType) - - // Assuming that the chain selector is referring to an evm chain for now. - // TODO: add an api that returns chain family. - destChainID, err := chainsel.ChainIdFromSelector(uint64(config.Config.ChainSelector)) - if err != nil { - return nil, fmt.Errorf("failed to get chain ID from selector %d: %w", config.Config.ChainSelector, err) - } - destChainFamily := relay.NetworkEVM - destRelayID := types.NewRelayID(destChainFamily, fmt.Sprintf("%d", destChainID)) - - configTracker := ocrimpls.NewConfigTracker(config) - publicConfig, err := configTracker.PublicConfig() - if err != nil { - return nil, fmt.Errorf("failed to get public config from OCR config: %w", err) - } - var execBatchGasLimit uint64 - if pluginType == cctypes.PluginTypeCCIPExec { - execOffchainConfig, err2 := pluginconfig.DecodeExecuteOffchainConfig(publicConfig.ReportingPluginConfig) - if err2 != nil { - return nil, fmt.Errorf("failed to decode execute offchain config: %w, raw: %s", - err2, string(publicConfig.ReportingPluginConfig)) - } - if execOffchainConfig.BatchGasLimit == 0 && destChainFamily == relay.NetworkEVM { - return nil, fmt.Errorf("BatchGasLimit not set in execute offchain config, must be > 0") - } - execBatchGasLimit = execOffchainConfig.BatchGasLimit - } - - contractReaders, chainWriters, err := i.createReadersAndWriters( - destChainID, - pluginType, - config, - execBatchGasLimit, - ) - if err != nil { - return nil, fmt.Errorf("failed to create readers and writers: %w", err) - } - - // build the onchain keyring. it will be the signing key for the destination chain family. - keybundle, ok := i.ocrKeyBundles[destChainFamily] - if !ok { - return nil, fmt.Errorf("no OCR key bundle found for chain family %s, forgot to create one?", destChainFamily) - } - onchainKeyring := ocrimpls.NewOnchainKeyring[[]byte](keybundle, i.lggr) - - // build the contract transmitter - // assume that we are using the first account in the keybundle as the from account - // and that we are able to transmit to the dest chain. - // TODO: revisit this in the future, since not all oracles will be able to transmit to the dest chain. - destChainWriter, ok := chainWriters[config.Config.ChainSelector] - if !ok { - return nil, fmt.Errorf("no chain writer found for dest chain selector %d, can't create contract transmitter", - config.Config.ChainSelector) - } - destFromAccounts, ok := i.transmitters[destRelayID] - if !ok { - return nil, fmt.Errorf("no transmitter found for dest relay ID %s, can't create contract transmitter", destRelayID) - } - - // TODO: Extract the correct transmitter address from the destsFromAccount - factory, transmitter, err := i.createFactoryAndTransmitter(config, destRelayID, contractReaders, chainWriters, destChainWriter, destFromAccounts) - if err != nil { - return nil, fmt.Errorf("failed to create factory and transmitter: %w", err) - } - - oracleArgs := libocr3.OCR3OracleArgs[[]byte]{ - BinaryNetworkEndpointFactory: i.peerWrapper.Peer2, - Database: i.db, - // NOTE: when specifying V2Bootstrappers here we actually do NOT need to run a full bootstrap node! - // Thus it is vital that the bootstrapper locators are correctly set in the job spec. - V2Bootstrappers: i.bootstrapperLocators, - ContractConfigTracker: configTracker, - ContractTransmitter: transmitter, - LocalConfig: defaultLocalConfig(), - Logger: ocrcommon.NewOCRWrapper( - i.lggr. - Named(fmt.Sprintf("CCIP%sOCR3", pluginType.String())). - Named(destRelayID.String()). - Named(hexutil.Encode(config.Config.OfframpAddress)), - false, - func(ctx context.Context, msg string) {}), - MetricsRegisterer: prometheus.WrapRegistererWith(map[string]string{"name": fmt.Sprintf("commit-%d", config.Config.ChainSelector)}, prometheus.DefaultRegisterer), - MonitoringEndpoint: i.monitoringEndpointGen.GenMonitoringEndpoint( - destChainFamily, - destRelayID.ChainID, - string(config.Config.OfframpAddress), - synchronization.OCR3CCIPCommit, - ), - OffchainConfigDigester: ocrimpls.NewConfigDigester(config.ConfigDigest), - OffchainKeyring: keybundle, - OnchainKeyring: onchainKeyring, - ReportingPluginFactory: factory, - } - oracle, err := libocr3.NewOracle(oracleArgs) - if err != nil { - return nil, err - } - return oracle, nil -} - -func (i *pluginOracleCreator) createFactoryAndTransmitter( - config cctypes.OCR3ConfigWithMeta, - destRelayID types.RelayID, - contractReaders map[cciptypes.ChainSelector]types.ContractReader, - chainWriters map[cciptypes.ChainSelector]types.ChainWriter, - destChainWriter types.ChainWriter, - destFromAccounts []string, -) (ocr3types.ReportingPluginFactory[[]byte], ocr3types.ContractTransmitter[[]byte], error) { - var factory ocr3types.ReportingPluginFactory[[]byte] - var transmitter ocr3types.ContractTransmitter[[]byte] - if config.Config.PluginType == uint8(cctypes.PluginTypeCCIPCommit) { - factory = commitocr3.NewPluginFactory( - i.lggr. - Named("CCIPCommitPlugin"). - Named(destRelayID.String()). - Named(fmt.Sprintf("%d", config.Config.ChainSelector)). - Named(hexutil.Encode(config.Config.OfframpAddress)), - ccipreaderpkg.OCR3ConfigWithMeta(config), - ccipevm.NewCommitPluginCodecV1(), - ccipevm.NewMessageHasherV1(), - i.homeChainReader, - contractReaders, - chainWriters, - ) - transmitter = ocrimpls.NewCommitContractTransmitter[[]byte](destChainWriter, - ocrtypes.Account(destFromAccounts[0]), - hexutil.Encode(config.Config.OfframpAddress), // TODO: this works for evm only, how about non-evm? - ) - } else if config.Config.PluginType == uint8(cctypes.PluginTypeCCIPExec) { - factory = execocr3.NewPluginFactory( - i.lggr. - Named("CCIPExecPlugin"). - Named(destRelayID.String()). - Named(hexutil.Encode(config.Config.OfframpAddress)), - ccipreaderpkg.OCR3ConfigWithMeta(config), - ccipevm.NewExecutePluginCodecV1(), - ccipevm.NewMessageHasherV1(), - i.homeChainReader, - superfakes.NewNilTokenDataReader(), - ccipevm.NewGasEstimateProvider(), - contractReaders, - chainWriters, - ) - transmitter = ocrimpls.NewExecContractTransmitter[[]byte](destChainWriter, - ocrtypes.Account(destFromAccounts[0]), - hexutil.Encode(config.Config.OfframpAddress), // TODO: this works for evm only, how about non-evm? - ) - } else { - return nil, nil, fmt.Errorf("unsupported plugin type %d", config.Config.PluginType) - } - return factory, transmitter, nil -} - -func (i *pluginOracleCreator) createReadersAndWriters( - destChainID uint64, - pluginType cctypes.PluginType, - config cctypes.OCR3ConfigWithMeta, - execBatchGasLimit uint64, -) ( - map[cciptypes.ChainSelector]types.ContractReader, - map[cciptypes.ChainSelector]types.ChainWriter, - error, -) { - contractReaders := make(map[cciptypes.ChainSelector]types.ContractReader) - chainWriters := make(map[cciptypes.ChainSelector]types.ChainWriter) - for _, chain := range i.chains.Slice() { - var chainReaderConfig evmrelaytypes.ChainReaderConfig - if chain.ID().Uint64() == destChainID { - chainReaderConfig = evmconfig.DestReaderConfig - } else { - chainReaderConfig = evmconfig.SourceReaderConfig - } - cr, err2 := evm.NewChainReaderService( - context.Background(), - i.lggr. - Named("EVMChainReaderService"). - Named(chain.ID().String()). - Named(pluginType.String()), - chain.LogPoller(), - chain.HeadTracker(), - chain.Client(), - chainReaderConfig, - ) - if err2 != nil { - return nil, nil, fmt.Errorf("failed to create contract reader for chain %s: %w", chain.ID(), err2) - } - - if chain.ID().Uint64() == destChainID { - // bind the chain reader to the dest chain's offramp. - offrampAddressHex := common.BytesToAddress(config.Config.OfframpAddress).Hex() - err3 := cr.Bind(context.Background(), []types.BoundContract{ - { - Address: offrampAddressHex, - Name: consts.ContractNameOffRamp, - }, - }) - if err3 != nil { - return nil, nil, fmt.Errorf("failed to bind chain reader for dest chain %s's offramp at %s: %w", chain.ID(), offrampAddressHex, err3) - } - } - - // TODO: figure out shutdown. - // maybe from the plugin directly? - err2 = cr.Start(context.Background()) - if err2 != nil { - return nil, nil, fmt.Errorf("failed to start contract reader for chain %s: %w", chain.ID(), err2) - } - - // Even though we only write to the dest chain, we need to create chain writers for all chains - // we know about in order to post gas prices on the dest. - var fromAddress common.Address - transmitter, ok := i.transmitters[types.NewRelayID(relay.NetworkEVM, chain.ID().String())] - if ok { - fromAddress = common.HexToAddress(transmitter[0]) - } - cw, err2 := evm.NewChainWriterService( - i.lggr.Named("EVMChainWriterService"). - Named(chain.ID().String()). - Named(pluginType.String()), - chain.Client(), - chain.TxManager(), - chain.GasEstimator(), - evmconfig.ChainWriterConfigRaw( - fromAddress, - chain.Config().EVM().GasEstimator().PriceMaxKey(fromAddress), - defaultCommitGasLimit, - execBatchGasLimit, - ), - ) - if err2 != nil { - return nil, nil, fmt.Errorf("failed to create chain writer for chain %s: %w", chain.ID(), err2) - } - - // TODO: figure out shutdown. - // maybe from the plugin directly? - err2 = cw.Start(context.Background()) - if err2 != nil { - return nil, nil, fmt.Errorf("failed to start chain writer for chain %s: %w", chain.ID(), err2) - } - - chainSelector, ok := chainsel.EvmChainIdToChainSelector()[chain.ID().Uint64()] - if !ok { - return nil, nil, fmt.Errorf("failed to get chain selector from chain ID %s", chain.ID()) - } - - contractReaders[cciptypes.ChainSelector(chainSelector)] = cr - chainWriters[cciptypes.ChainSelector(chainSelector)] = cw - } - return contractReaders, chainWriters, nil -} - -func defaultLocalConfig() ocrtypes.LocalConfig { - return ocrtypes.LocalConfig{ - BlockchainTimeout: 10 * time.Second, - // Config tracking is handled by the launcher, since we're doing blue-green - // deployments we're not going to be using OCR's built-in config switching, - // which always shuts down the previous instance. - ContractConfigConfirmations: 1, - SkipContractConfigConfirmations: true, - ContractConfigTrackerPollInterval: 10 * time.Second, - ContractTransmitterTransmitTimeout: 10 * time.Second, - DatabaseTimeout: 10 * time.Second, - MinOCR2MaxDurationQuery: 1 * time.Second, - DevelopmentMode: "false", - } -} diff --git a/core/capabilities/ccip/superfakes/token_data_reader.go b/core/capabilities/ccip/superfakes/token_data_reader.go deleted file mode 100644 index ff6a88076c..0000000000 --- a/core/capabilities/ccip/superfakes/token_data_reader.go +++ /dev/null @@ -1,23 +0,0 @@ -package superfakes - -import ( - "context" - - "github.com/smartcontractkit/chainlink-ccip/execute/exectypes" - "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3" -) - -// NewNilTokenDataReader returns a new nilTokenDataReader. -// This token data reader always returns nil for the token data. -func NewNilTokenDataReader() exectypes.TokenDataReader { - return &nilTokenDataReader{} -} - -type nilTokenDataReader struct{} - -// ReadTokenData implements exectypes.TokenDataReader. -func (t *nilTokenDataReader) ReadTokenData(ctx context.Context, srcChain ccipocr3.ChainSelector, num ccipocr3.SeqNum) (r [][]byte, err error) { - return nil, nil -} - -var _ exectypes.TokenDataReader = (*nilTokenDataReader)(nil) diff --git a/core/capabilities/ccip/types/mocks/ccip_oracle.go b/core/capabilities/ccip/types/mocks/ccip_oracle.go deleted file mode 100644 index c849b3d941..0000000000 --- a/core/capabilities/ccip/types/mocks/ccip_oracle.go +++ /dev/null @@ -1,122 +0,0 @@ -// Code generated by mockery v2.43.2. DO NOT EDIT. - -package mocks - -import mock "github.com/stretchr/testify/mock" - -// CCIPOracle is an autogenerated mock type for the CCIPOracle type -type CCIPOracle struct { - mock.Mock -} - -type CCIPOracle_Expecter struct { - mock *mock.Mock -} - -func (_m *CCIPOracle) EXPECT() *CCIPOracle_Expecter { - return &CCIPOracle_Expecter{mock: &_m.Mock} -} - -// Close provides a mock function with given fields: -func (_m *CCIPOracle) Close() error { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for Close") - } - - var r0 error - if rf, ok := ret.Get(0).(func() error); ok { - r0 = rf() - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// CCIPOracle_Close_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Close' -type CCIPOracle_Close_Call struct { - *mock.Call -} - -// Close is a helper method to define mock.On call -func (_e *CCIPOracle_Expecter) Close() *CCIPOracle_Close_Call { - return &CCIPOracle_Close_Call{Call: _e.mock.On("Close")} -} - -func (_c *CCIPOracle_Close_Call) Run(run func()) *CCIPOracle_Close_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *CCIPOracle_Close_Call) Return(_a0 error) *CCIPOracle_Close_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *CCIPOracle_Close_Call) RunAndReturn(run func() error) *CCIPOracle_Close_Call { - _c.Call.Return(run) - return _c -} - -// Start provides a mock function with given fields: -func (_m *CCIPOracle) Start() error { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for Start") - } - - var r0 error - if rf, ok := ret.Get(0).(func() error); ok { - r0 = rf() - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// CCIPOracle_Start_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Start' -type CCIPOracle_Start_Call struct { - *mock.Call -} - -// Start is a helper method to define mock.On call -func (_e *CCIPOracle_Expecter) Start() *CCIPOracle_Start_Call { - return &CCIPOracle_Start_Call{Call: _e.mock.On("Start")} -} - -func (_c *CCIPOracle_Start_Call) Run(run func()) *CCIPOracle_Start_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *CCIPOracle_Start_Call) Return(_a0 error) *CCIPOracle_Start_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *CCIPOracle_Start_Call) RunAndReturn(run func() error) *CCIPOracle_Start_Call { - _c.Call.Return(run) - return _c -} - -// NewCCIPOracle creates a new instance of CCIPOracle. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -// The first argument is typically a *testing.T value. -func NewCCIPOracle(t interface { - mock.TestingT - Cleanup(func()) -}) *CCIPOracle { - mock := &CCIPOracle{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/core/capabilities/ccip/types/mocks/home_chain_reader.go b/core/capabilities/ccip/types/mocks/home_chain_reader.go deleted file mode 100644 index a5a581a1d2..0000000000 --- a/core/capabilities/ccip/types/mocks/home_chain_reader.go +++ /dev/null @@ -1,129 +0,0 @@ -package mocks - -import ( - "context" - - mapset "github.com/deckarep/golang-set/v2" - "github.com/stretchr/testify/mock" - - ccipreaderpkg "github.com/smartcontractkit/chainlink-ccip/pkg/reader" - - cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3" - - "github.com/smartcontractkit/libocr/ragep2p/types" -) - -var _ ccipreaderpkg.HomeChain = (*HomeChainReader)(nil) - -type HomeChainReader struct { - mock.Mock -} - -func (_m *HomeChainReader) GetChainConfig(chainSelector cciptypes.ChainSelector) (ccipreaderpkg.ChainConfig, error) { - //TODO implement me - panic("implement me") -} - -func (_m *HomeChainReader) GetAllChainConfigs() (map[cciptypes.ChainSelector]ccipreaderpkg.ChainConfig, error) { - //TODO implement me - panic("implement me") -} - -func (_m *HomeChainReader) GetSupportedChainsForPeer(id types.PeerID) (mapset.Set[cciptypes.ChainSelector], error) { - //TODO implement me - panic("implement me") -} - -func (_m *HomeChainReader) GetKnownCCIPChains() (mapset.Set[cciptypes.ChainSelector], error) { - //TODO implement me - panic("implement me") -} - -func (_m *HomeChainReader) GetFChain() (map[cciptypes.ChainSelector]int, error) { - //TODO implement me - panic("implement me") -} - -func (_m *HomeChainReader) Start(ctx context.Context) error { - //TODO implement me - panic("implement me") -} - -func (_m *HomeChainReader) Close() error { - //TODO implement me - panic("implement me") -} - -func (_m *HomeChainReader) HealthReport() map[string]error { - //TODO implement me - panic("implement me") -} - -func (_m *HomeChainReader) Name() string { - //TODO implement me - panic("implement me") -} - -// GetOCRConfigs provides a mock function with given fields: ctx, donID, pluginType -func (_m *HomeChainReader) GetOCRConfigs(ctx context.Context, donID uint32, pluginType uint8) ([]ccipreaderpkg.OCR3ConfigWithMeta, error) { - ret := _m.Called(ctx, donID, pluginType) - - if len(ret) == 0 { - panic("no return value specified for GetOCRConfigs") - } - - var r0 []ccipreaderpkg.OCR3ConfigWithMeta - var r1 error - if rf, ok := ret.Get(0).(func(ctx context.Context, donID uint32, pluginType uint8) ([]ccipreaderpkg.OCR3ConfigWithMeta, error)); ok { - return rf(ctx, donID, pluginType) - } - if rf, ok := ret.Get(0).(func(ctx context.Context, donID uint32, pluginType uint8) []ccipreaderpkg.OCR3ConfigWithMeta); ok { - r0 = rf(ctx, donID, pluginType) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]ccipreaderpkg.OCR3ConfigWithMeta) - } - } - - if rf, ok := ret.Get(1).(func(ctx context.Context, donID uint32, pluginType uint8) error); ok { - r1 = rf(ctx, donID, pluginType) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -func (_m *HomeChainReader) Ready() error { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for Ready") - } - - var r0 error - if rf, ok := ret.Get(0).(func() error); ok { - return rf() - } - if rf, ok := ret.Get(0).(func() error); ok { - r0 = rf() - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// NewHomeChainReader creates a new instance of HomeChainReader. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -// The first argument is typically a *testing.T value. -func NewHomeChainReader(t interface { - mock.TestingT - Cleanup(func()) -}) *HomeChainReader { - mock := &HomeChainReader{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/core/capabilities/ccip/types/mocks/oracle_creator.go b/core/capabilities/ccip/types/mocks/oracle_creator.go deleted file mode 100644 index 1d327e9652..0000000000 --- a/core/capabilities/ccip/types/mocks/oracle_creator.go +++ /dev/null @@ -1,138 +0,0 @@ -// Code generated by mockery v2.43.2. DO NOT EDIT. - -package mocks - -import ( - types "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" - mock "github.com/stretchr/testify/mock" -) - -// OracleCreator is an autogenerated mock type for the OracleCreator type -type OracleCreator struct { - mock.Mock -} - -type OracleCreator_Expecter struct { - mock *mock.Mock -} - -func (_m *OracleCreator) EXPECT() *OracleCreator_Expecter { - return &OracleCreator_Expecter{mock: &_m.Mock} -} - -// Create provides a mock function with given fields: config -func (_m *OracleCreator) Create(config types.OCR3ConfigWithMeta) (types.CCIPOracle, error) { - ret := _m.Called(config) - - if len(ret) == 0 { - panic("no return value specified for Create") - } - - var r0 types.CCIPOracle - var r1 error - if rf, ok := ret.Get(0).(func(types.OCR3ConfigWithMeta) (types.CCIPOracle, error)); ok { - return rf(config) - } - if rf, ok := ret.Get(0).(func(types.OCR3ConfigWithMeta) types.CCIPOracle); ok { - r0 = rf(config) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(types.CCIPOracle) - } - } - - if rf, ok := ret.Get(1).(func(types.OCR3ConfigWithMeta) error); ok { - r1 = rf(config) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// OracleCreator_Create_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Create' -type OracleCreator_Create_Call struct { - *mock.Call -} - -// Create is a helper method to define mock.On call -// - config types.OCR3ConfigWithMeta -func (_e *OracleCreator_Expecter) Create(config interface{}) *OracleCreator_Create_Call { - return &OracleCreator_Create_Call{Call: _e.mock.On("Create", config)} -} - -func (_c *OracleCreator_Create_Call) Run(run func(config types.OCR3ConfigWithMeta)) *OracleCreator_Create_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(types.OCR3ConfigWithMeta)) - }) - return _c -} - -func (_c *OracleCreator_Create_Call) Return(_a0 types.CCIPOracle, _a1 error) *OracleCreator_Create_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *OracleCreator_Create_Call) RunAndReturn(run func(types.OCR3ConfigWithMeta) (types.CCIPOracle, error)) *OracleCreator_Create_Call { - _c.Call.Return(run) - return _c -} - -// Type provides a mock function with given fields: -func (_m *OracleCreator) Type() types.OracleType { - ret := _m.Called() - - if len(ret) == 0 { - panic("no return value specified for Type") - } - - var r0 types.OracleType - if rf, ok := ret.Get(0).(func() types.OracleType); ok { - r0 = rf() - } else { - r0 = ret.Get(0).(types.OracleType) - } - - return r0 -} - -// OracleCreator_Type_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Type' -type OracleCreator_Type_Call struct { - *mock.Call -} - -// Type is a helper method to define mock.On call -func (_e *OracleCreator_Expecter) Type() *OracleCreator_Type_Call { - return &OracleCreator_Type_Call{Call: _e.mock.On("Type")} -} - -func (_c *OracleCreator_Type_Call) Run(run func()) *OracleCreator_Type_Call { - _c.Call.Run(func(args mock.Arguments) { - run() - }) - return _c -} - -func (_c *OracleCreator_Type_Call) Return(_a0 types.OracleType) *OracleCreator_Type_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *OracleCreator_Type_Call) RunAndReturn(run func() types.OracleType) *OracleCreator_Type_Call { - _c.Call.Return(run) - return _c -} - -// NewOracleCreator creates a new instance of OracleCreator. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -// The first argument is typically a *testing.T value. -func NewOracleCreator(t interface { - mock.TestingT - Cleanup(func()) -}) *OracleCreator { - mock := &OracleCreator{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/core/capabilities/ccip/types/types.go b/core/capabilities/ccip/types/types.go deleted file mode 100644 index e42990f4c4..0000000000 --- a/core/capabilities/ccip/types/types.go +++ /dev/null @@ -1,54 +0,0 @@ -package types - -import ( - ccipreaderpkg "github.com/smartcontractkit/chainlink-ccip/pkg/reader" -) - -// OCR3ConfigWithMeta is a type alias in order to generate correct mocks for the OracleCreator interface. -type OCR3ConfigWithMeta ccipreaderpkg.OCR3ConfigWithMeta - -// PluginType represents the type of CCIP plugin. -// It mirrors the OCRPluginType in Internal.sol. -type PluginType uint8 - -const ( - PluginTypeCCIPCommit PluginType = 0 - PluginTypeCCIPExec PluginType = 1 -) - -func (pt PluginType) String() string { - switch pt { - case PluginTypeCCIPCommit: - return "CCIPCommit" - case PluginTypeCCIPExec: - return "CCIPExec" - default: - return "Unknown" - } -} - -type OracleType uint8 - -const ( - OracleTypePlugin OracleType = 0 - OracleTypeBootstrap OracleType = 1 -) - -// CCIPOracle represents either a CCIP commit or exec oracle or a bootstrap node. -type CCIPOracle interface { - Close() error - Start() error -} - -// OracleCreator is an interface for creating CCIP oracles. -// Whether the oracle uses a LOOPP or not is an implementation detail. -type OracleCreator interface { - // Create creates a new oracle that will run either the commit or exec ccip plugin, - // if its a plugin oracle, or a bootstrap oracle if its a bootstrap oracle. - // The oracle must be returned unstarted. - Create(config OCR3ConfigWithMeta) (CCIPOracle, error) - - // Type returns the type of oracle that this creator creates. - // The only valid values are OracleTypePlugin and OracleTypeBootstrap. - Type() OracleType -} diff --git a/core/capabilities/ccip/validate/validate.go b/core/capabilities/ccip/validate/validate.go deleted file mode 100644 index 02e1cb5c8e..0000000000 --- a/core/capabilities/ccip/validate/validate.go +++ /dev/null @@ -1,91 +0,0 @@ -package validate - -import ( - "fmt" - - "github.com/google/uuid" - "github.com/pelletier/go-toml" - - "github.com/smartcontractkit/chainlink/v2/core/services/job" - "github.com/smartcontractkit/chainlink/v2/core/services/ocrcommon" -) - -// ValidatedCCIPSpec validates the given toml string as a CCIP spec. -func ValidatedCCIPSpec(tomlString string) (jb job.Job, err error) { - var spec job.CCIPSpec - tree, err := toml.Load(tomlString) - if err != nil { - return job.Job{}, fmt.Errorf("toml error on load: %w", err) - } - // Note this validates all the fields which implement an UnmarshalText - err = tree.Unmarshal(&spec) - if err != nil { - return job.Job{}, fmt.Errorf("toml unmarshal error on spec: %w", err) - } - err = tree.Unmarshal(&jb) - if err != nil { - return job.Job{}, fmt.Errorf("toml unmarshal error on job: %w", err) - } - jb.CCIPSpec = &spec - - if jb.Type != job.CCIP { - return job.Job{}, fmt.Errorf("the only supported type is currently 'ccip', got %s", jb.Type) - } - if jb.CCIPSpec.CapabilityLabelledName == "" { - return job.Job{}, fmt.Errorf("capabilityLabelledName must be set") - } - if jb.CCIPSpec.CapabilityVersion == "" { - return job.Job{}, fmt.Errorf("capabilityVersion must be set") - } - if jb.CCIPSpec.P2PKeyID == "" { - return job.Job{}, fmt.Errorf("p2pKeyID must be set") - } - - // ensure that the P2PV2Bootstrappers is in the right format. - for _, bootstrapperLocator := range jb.CCIPSpec.P2PV2Bootstrappers { - // needs to be of the form @: - _, err := ocrcommon.ParseBootstrapPeers([]string{bootstrapperLocator}) - if err != nil { - return job.Job{}, fmt.Errorf("p2p v2 bootstrapper locator %s is not in the correct format: %w", bootstrapperLocator, err) - } - } - - return jb, nil -} - -type SpecArgs struct { - P2PV2Bootstrappers []string `toml:"p2pV2Bootstrappers"` - CapabilityVersion string `toml:"capabilityVersion"` - CapabilityLabelledName string `toml:"capabilityLabelledName"` - OCRKeyBundleIDs map[string]string `toml:"ocrKeyBundleIDs"` - P2PKeyID string `toml:"p2pKeyID"` - RelayConfigs map[string]any `toml:"relayConfigs"` - PluginConfig map[string]any `toml:"pluginConfig"` -} - -// NewCCIPSpecToml creates a new CCIP spec in toml format from the given spec args. -func NewCCIPSpecToml(spec SpecArgs) (string, error) { - type fullSpec struct { - SpecArgs - Type string `toml:"type"` - SchemaVersion uint64 `toml:"schemaVersion"` - Name string `toml:"name"` - ExternalJobID string `toml:"externalJobID"` - } - extJobID, err := uuid.NewRandom() - if err != nil { - return "", fmt.Errorf("failed to generate external job id: %w", err) - } - marshaled, err := toml.Marshal(fullSpec{ - SpecArgs: spec, - Type: "ccip", - SchemaVersion: 1, - Name: fmt.Sprintf("%s-%s", "ccip", extJobID.String()), - ExternalJobID: extJobID.String(), - }) - if err != nil { - return "", fmt.Errorf("failed to marshal spec into toml: %w", err) - } - - return string(marshaled), nil -} diff --git a/core/capabilities/ccip/validate/validate_test.go b/core/capabilities/ccip/validate/validate_test.go deleted file mode 100644 index 97958f4cf9..0000000000 --- a/core/capabilities/ccip/validate/validate_test.go +++ /dev/null @@ -1,58 +0,0 @@ -package validate_test - -import ( - "testing" - - "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/validate" - - "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/chainlink/v2/core/services/job" -) - -func TestNewCCIPSpecToml(t *testing.T) { - tests := []struct { - name string - specArgs validate.SpecArgs - want string - wantErr bool - }{ - // TODO: Add test cases. - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := validate.NewCCIPSpecToml(tt.specArgs) - if tt.wantErr { - require.Error(t, err) - } else { - require.NoError(t, err) - require.Equal(t, tt.want, got) - } - }) - } -} - -func TestValidatedCCIPSpec(t *testing.T) { - type args struct { - tomlString string - } - tests := []struct { - name string - args args - wantJb job.Job - wantErr bool - }{ - // TODO: Add test cases. - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - gotJb, err := validate.ValidatedCCIPSpec(tt.args.tomlString) - if tt.wantErr { - require.Error(t, err) - } else { - require.NoError(t, err) - require.Equal(t, tt.wantJb, gotJb) - } - }) - } -} diff --git a/core/scripts/go.mod b/core/scripts/go.mod index cdc8492eea..7ee9ff2513 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -274,7 +274,6 @@ require ( github.com/sethvargo/go-retry v0.2.4 // indirect github.com/shirou/gopsutil v3.21.11+incompatible // indirect github.com/shirou/gopsutil/v3 v3.24.3 // indirect - github.com/smartcontractkit/chainlink-ccip v0.0.0-20240827164549-33f5819d7ddc // indirect github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240710121324-3ed288aa9b45 // indirect github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240718160222-2dc0c8136bfa // indirect github.com/smartcontractkit/chainlink-feeds v0.0.0-20240710170203-5b41615da827 // indirect diff --git a/core/scripts/go.sum b/core/scripts/go.sum index 4b567f016e..192357740f 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -1070,8 +1070,6 @@ github.com/smartcontractkit/chain-selectors v1.0.23 h1:D2Eaex4Cw/O7Lg3tX6WklOqnj github.com/smartcontractkit/chain-selectors v1.0.23/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/smartcontractkit/chainlink-automation v1.0.4 h1:iyW181JjKHLNMnDleI8umfIfVVlwC7+n5izbLSFgjw8= github.com/smartcontractkit/chainlink-automation v1.0.4/go.mod h1:u4NbPZKJ5XiayfKHD/v3z3iflQWqvtdhj13jVZXj/cM= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20240827164549-33f5819d7ddc h1:8267l5X5oF2JnGsDaEG4i0JSQO9o0eC61SscTfWc1bk= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20240827164549-33f5819d7ddc/go.mod h1:Z9lQ5t20kRk28pzRLnqAJZUVOw8E6/siA3P3MLyKqoM= github.com/smartcontractkit/chainlink-common v0.2.1-0.20240717132349-ee5af9b79834 h1:pTf4xdcmiWBqWZ6rTy2RMTDBzhHk89VC1pM7jXKQztI= github.com/smartcontractkit/chainlink-common v0.2.1-0.20240717132349-ee5af9b79834/go.mod h1:fh9eBbrReCmv31bfz52ENCAMa7nTKQbdhb2B3+S2VGo= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240710121324-3ed288aa9b45 h1:NBQLtqk8zsyY4qTJs+NElI3aDFTcAo83JHvqD04EvB0= diff --git a/core/services/chainlink/application.go b/core/services/chainlink/application.go index a759f0ee11..94619b7ce6 100644 --- a/core/services/chainlink/application.go +++ b/core/services/chainlink/application.go @@ -8,8 +8,6 @@ import ( "net/http" "sync" - "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip" - "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/google/uuid" @@ -529,18 +527,6 @@ func NewApplication(opts ApplicationOpts) (Application, error) { cfg.Insecure(), opts.RelayerChainInteroperators, ) - delegates[job.CCIP] = ccip.NewDelegate( - globalLogger, - loopRegistrarConfig, - pipelineRunner, - opts.RelayerChainInteroperators.LegacyEVMChains(), - capabilityRegistrySyncer, - opts.KeyStore, - opts.DS, - peerWrapper, - telemetryManager, - cfg.Capabilities(), - ) } else { globalLogger.Debug("Off-chain reporting v2 disabled") } diff --git a/core/services/job/job_orm_test.go b/core/services/job/job_orm_test.go index c26cf828cc..37be1b7955 100644 --- a/core/services/job/job_orm_test.go +++ b/core/services/job/job_orm_test.go @@ -7,8 +7,6 @@ import ( "testing" "time" - "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/validate" - "github.com/ethereum/go-ethereum/common" "github.com/google/uuid" "github.com/lib/pq" @@ -433,39 +431,6 @@ func TestORM_DeleteJob_DeletesAssociatedRecords(t *testing.T) { cltest.AssertCount(t, db, "jobs", 0) }) - t.Run("it creates and deletes records for ccip jobs", func(t *testing.T) { - ctx := testutils.Context(t) - p2pKey, err := keyStore.P2P().Create(ctx) - require.NoError(t, err) - specArgs := validate.SpecArgs{ - P2PV2Bootstrappers: []string{ - fmt.Sprintf("%s@somechainlinknode.com:%d", p2pKey.ID(), 8080), - }, - CapabilityVersion: "v1.0.0", - CapabilityLabelledName: "ccip", - OCRKeyBundleIDs: map[string]string{ - relay.NetworkEVM: cltest.DefaultOCRKey.ID(), - }, - P2PKeyID: p2pKey.ID(), - PluginConfig: map[string]any{ - "pricesPipeline": ".... the pipeline ....", - }, - } - specToml, err := validate.NewCCIPSpecToml(specArgs) - require.NoError(t, err) - jb, err := validate.ValidatedCCIPSpec(specToml) - require.NoError(t, err) - - err = jobORM.CreateJob(ctx, &jb) - require.NoError(t, err) - cltest.AssertCount(t, db, "ccip_specs", 1) - cltest.AssertCount(t, db, "jobs", 1) - err = jobORM.DeleteJob(ctx, jb.ID) - require.NoError(t, err) - cltest.AssertCount(t, db, "ccip_specs", 0) - cltest.AssertCount(t, db, "jobs", 0) - }) - t.Run("it deletes records for webhook jobs", func(t *testing.T) { ctx := testutils.Context(t) ei := cltest.MustInsertExternalInitiator(t, bridges.NewORM(db)) @@ -666,89 +631,6 @@ func TestORM_CreateJob_VRFV2Plus(t *testing.T) { cltest.AssertCount(t, db, "jobs", 0) } -func TestORM_CreateJob_CCIP(t *testing.T) { - ctx := testutils.Context(t) - config := configtest.NewTestGeneralConfig(t) - db := pgtest.NewSqlxDB(t) - keyStore := cltest.NewKeyStore(t, db) - require.NoError(t, keyStore.OCR().Add(ctx, cltest.DefaultOCRKey)) - - p2pKey, err := keyStore.P2P().Create(ctx) - require.NoError(t, err) - - lggr := logger.TestLogger(t) - pipelineORM := pipeline.NewORM(db, lggr, config.JobPipeline().MaxSuccessfulRuns()) - bridgesORM := bridges.NewORM(db) - jobORM := NewTestORM(t, db, pipelineORM, bridgesORM, keyStore) - - specArgs := validate.SpecArgs{ - P2PV2Bootstrappers: []string{ - fmt.Sprintf("%s@somechainlinknode.com:%d", p2pKey.ID(), 8080), - }, - CapabilityVersion: "v1.0.0", - CapabilityLabelledName: "ccip", - OCRKeyBundleIDs: map[string]string{ - relay.NetworkEVM: cltest.DefaultOCRKey.ID(), - }, - P2PKeyID: p2pKey.ID(), - RelayConfigs: map[string]any{ - "hello": "world", - }, - PluginConfig: map[string]any{ - "pricesPipeline": ".... the pipeline ....", - }, - } - specToml, err := validate.NewCCIPSpecToml(specArgs) - require.NoError(t, err) - jb, err := validate.ValidatedCCIPSpec(specToml) - require.NoError(t, err) - - require.NoError(t, jobORM.CreateJob(ctx, &jb)) - cltest.AssertCount(t, db, "ccip_specs", 1) - cltest.AssertCount(t, db, "jobs", 1) - - var capabilityVersion string - require.NoError(t, db.Get(&capabilityVersion, `SELECT capability_version FROM ccip_specs LIMIT 1`)) - require.Equal(t, specArgs.CapabilityVersion, capabilityVersion) - - var capabilityLabelledName string - require.NoError(t, db.Get(&capabilityLabelledName, `SELECT capability_labelled_name FROM ccip_specs LIMIT 1`)) - require.Equal(t, specArgs.CapabilityLabelledName, capabilityLabelledName) - - var ocrKeyBundleIDs job.JSONConfig - require.NoError(t, db.Get(&ocrKeyBundleIDs, `SELECT ocr_key_bundle_ids FROM ccip_specs LIMIT 1`)) - actual, ok := ocrKeyBundleIDs[relay.NetworkEVM] - require.True(t, ok) - actualStr, ok := actual.(string) - require.True(t, ok) - require.Equal(t, specArgs.OCRKeyBundleIDs[relay.NetworkEVM], actualStr) - - var p2pV2Bootstrappers pq.StringArray - require.NoError(t, db.Get(&p2pV2Bootstrappers, `SELECT p2pv2_bootstrappers FROM ccip_specs LIMIT 1`)) - require.Len(t, p2pV2Bootstrappers, len(specArgs.P2PV2Bootstrappers)) - require.Equal(t, specArgs.P2PV2Bootstrappers[0], p2pV2Bootstrappers[0]) - - var p2pKeyID string - require.NoError(t, db.Get(&p2pKeyID, `SELECT p2p_key_id FROM ccip_specs LIMIT 1`)) - require.Equal(t, p2pKey.ID(), p2pKeyID) - - var relayConfigs job.JSONConfig - require.NoError(t, db.Get(&relayConfigs, `SELECT relay_configs FROM ccip_specs LIMIT 1`)) - actual, ok = relayConfigs["hello"] - require.True(t, ok) - actualStr, ok = actual.(string) - require.True(t, ok) - require.Equal(t, specArgs.RelayConfigs["hello"], actualStr) - - var pluginConfig job.JSONConfig - require.NoError(t, db.Get(&pluginConfig, `SELECT plugin_config FROM ccip_specs LIMIT 1`)) - actual, ok = pluginConfig["pricesPipeline"] - require.True(t, ok) - actualStr, ok = actual.(string) - require.True(t, ok) - require.Equal(t, specArgs.PluginConfig["pricesPipeline"], actualStr) -} - func TestORM_CreateJob_OCRBootstrap(t *testing.T) { ctx := testutils.Context(t) config := configtest.NewTestGeneralConfig(t) diff --git a/go.md b/go.md index 697d6b52ce..d9ed0d0a66 100644 --- a/go.md +++ b/go.md @@ -28,8 +28,6 @@ flowchart LR click chain-selectors href "https://github.com/smartcontractkit/chain-selectors" chainlink/v2 --> chainlink-automation click chainlink-automation href "https://github.com/smartcontractkit/chainlink-automation" - chainlink/v2 --> chainlink-ccip - click chainlink-ccip href "https://github.com/smartcontractkit/chainlink-ccip" chainlink/v2 --> chainlink-common click chainlink-common href "https://github.com/smartcontractkit/chainlink-common" chainlink/v2 --> chainlink-cosmos @@ -52,8 +50,6 @@ flowchart LR click wsrpc href "https://github.com/smartcontractkit/wsrpc" chainlink-automation --> chainlink-common chainlink-automation --> libocr - chainlink-ccip --> chainlink-common - chainlink-ccip --> libocr chainlink-common --> libocr chainlink-cosmos --> chainlink-common chainlink-cosmos --> libocr diff --git a/go.mod b/go.mod index f376b25643..ee87e23f30 100644 --- a/go.mod +++ b/go.mod @@ -74,7 +74,6 @@ require ( github.com/shopspring/decimal v1.4.0 github.com/smartcontractkit/chain-selectors v1.0.23 github.com/smartcontractkit/chainlink-automation v1.0.4 - github.com/smartcontractkit/chainlink-ccip v0.0.0-20240827164549-33f5819d7ddc github.com/smartcontractkit/chainlink-common v0.2.1-0.20240717132349-ee5af9b79834 github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240710121324-3ed288aa9b45 github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240718160222-2dc0c8136bfa diff --git a/go.sum b/go.sum index ec3ca45b16..ac442571a9 100644 --- a/go.sum +++ b/go.sum @@ -1027,8 +1027,6 @@ github.com/smartcontractkit/chain-selectors v1.0.23 h1:D2Eaex4Cw/O7Lg3tX6WklOqnj github.com/smartcontractkit/chain-selectors v1.0.23/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/smartcontractkit/chainlink-automation v1.0.4 h1:iyW181JjKHLNMnDleI8umfIfVVlwC7+n5izbLSFgjw8= github.com/smartcontractkit/chainlink-automation v1.0.4/go.mod h1:u4NbPZKJ5XiayfKHD/v3z3iflQWqvtdhj13jVZXj/cM= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20240827164549-33f5819d7ddc h1:8267l5X5oF2JnGsDaEG4i0JSQO9o0eC61SscTfWc1bk= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20240827164549-33f5819d7ddc/go.mod h1:Z9lQ5t20kRk28pzRLnqAJZUVOw8E6/siA3P3MLyKqoM= github.com/smartcontractkit/chainlink-common v0.2.1-0.20240717132349-ee5af9b79834 h1:pTf4xdcmiWBqWZ6rTy2RMTDBzhHk89VC1pM7jXKQztI= github.com/smartcontractkit/chainlink-common v0.2.1-0.20240717132349-ee5af9b79834/go.mod h1:fh9eBbrReCmv31bfz52ENCAMa7nTKQbdhb2B3+S2VGo= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240710121324-3ed288aa9b45 h1:NBQLtqk8zsyY4qTJs+NElI3aDFTcAo83JHvqD04EvB0= diff --git a/integration-tests/deployment/address_book.go b/integration-tests/deployment/address_book.go deleted file mode 100644 index 4a5916111c..0000000000 --- a/integration-tests/deployment/address_book.go +++ /dev/null @@ -1,158 +0,0 @@ -package deployment - -import ( - "fmt" - "strings" - - "github.com/Masterminds/semver/v3" - "github.com/ethereum/go-ethereum/common" - "github.com/pkg/errors" - chainsel "github.com/smartcontractkit/chain-selectors" -) - -var ( - ErrInvalidChainSelector = fmt.Errorf("invalid chain selector") - ErrInvalidAddress = fmt.Errorf("invalid address") -) - -// ContractType is a simple string type for identifying contract types. -type ContractType string - -var ( - Version1_0_0 = *semver.MustParse("1.0.0") - Version1_1_0 = *semver.MustParse("1.1.0") - Version1_2_0 = *semver.MustParse("1.2.0") - Version1_5_0 = *semver.MustParse("1.5.0") - Version1_6_0_dev = *semver.MustParse("1.6.0-dev") -) - -type TypeAndVersion struct { - Type ContractType - Version semver.Version -} - -func (tv TypeAndVersion) String() string { - return fmt.Sprintf("%s %s", tv.Type, tv.Version.String()) -} - -func (tv TypeAndVersion) Equal(other TypeAndVersion) bool { - return tv.String() == other.String() -} - -func MustTypeAndVersionFromString(s string) TypeAndVersion { - tv, err := TypeAndVersionFromString(s) - if err != nil { - panic(err) - } - return tv -} - -// Note this will become useful for validation. When we want -// to assert an onchain call to typeAndVersion yields whats expected. -func TypeAndVersionFromString(s string) (TypeAndVersion, error) { - parts := strings.Split(s, " ") - if len(parts) != 2 { - return TypeAndVersion{}, fmt.Errorf("invalid type and version string: %s", s) - } - v, err := semver.NewVersion(parts[1]) - if err != nil { - return TypeAndVersion{}, err - } - return TypeAndVersion{ - Type: ContractType(parts[0]), - Version: *v, - }, nil -} - -func NewTypeAndVersion(t ContractType, v semver.Version) TypeAndVersion { - return TypeAndVersion{ - Type: t, - Version: v, - } -} - -// AddressBook is a simple interface for storing and retrieving contract addresses across -// chains. It is family agnostic as the keys are chain selectors. -// We store rather than derive typeAndVersion as some contracts do not support it. -// For ethereum addresses are always stored in EIP55 format. -type AddressBook interface { - Save(chainSelector uint64, address string, tv TypeAndVersion) error - Addresses() (map[uint64]map[string]TypeAndVersion, error) - AddressesForChain(chain uint64) (map[string]TypeAndVersion, error) - // Allows for merging address books (e.g. new deployments with existing ones) - Merge(other AddressBook) error -} - -type AddressBookMap struct { - AddressesByChain map[uint64]map[string]TypeAndVersion -} - -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) - } - if address == "" || address == common.HexToAddress("0x0").Hex() { - return errors.Wrap(ErrInvalidAddress, "address cannot be empty") - } - if common.IsHexAddress(address) { - // IMPORTANT: WE ALWAYS STANDARDIZE ETHEREUM ADDRESS STRINGS TO EIP55 - address = common.HexToAddress(address).Hex() - } else { - return errors.Wrapf(ErrInvalidAddress, "address %s is not a valid Ethereum address, only Ethereum addresses supported", address) - } - if typeAndVersion.Type == "" { - return fmt.Errorf("type cannot be empty") - } - if _, exists := m.AddressesByChain[chainSelector]; !exists { - // First time chain add, create map - m.AddressesByChain[chainSelector] = make(map[string]TypeAndVersion) - } - if _, exists := m.AddressesByChain[chainSelector][address]; exists { - return fmt.Errorf("address %s already exists for chain %d", address, chainSelector) - } - m.AddressesByChain[chainSelector][address] = typeAndVersion - return nil -} - -func (m *AddressBookMap) Addresses() (map[uint64]map[string]TypeAndVersion, error) { - 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) - } - return m.AddressesByChain[chain], nil -} - -// Attention this will mutate existing book -func (m *AddressBookMap) Merge(ab AddressBook) error { - addresses, err := ab.Addresses() - if err != nil { - return err - } - for chain, chainAddresses := range addresses { - for address, typeAndVersions := range chainAddresses { - if err := m.Save(chain, address, typeAndVersions); err != nil { - return err - } - } - } - return nil -} - -// TODO: Maybe could add an environment argument -// which would ensure only mainnet/testnet chain selectors are used -// for further safety? -func NewMemoryAddressBook() *AddressBookMap { - return &AddressBookMap{ - AddressesByChain: make(map[uint64]map[string]TypeAndVersion), - } -} - -func NewMemoryAddressBookFromMap(addressesByChain map[uint64]map[string]TypeAndVersion) *AddressBookMap { - return &AddressBookMap{ - AddressesByChain: addressesByChain, - } -} diff --git a/integration-tests/deployment/address_book_test.go b/integration-tests/deployment/address_book_test.go deleted file mode 100644 index c6967df0ca..0000000000 --- a/integration-tests/deployment/address_book_test.go +++ /dev/null @@ -1,112 +0,0 @@ -package deployment - -import ( - "errors" - "testing" - - "github.com/ethereum/go-ethereum/common" - chainsel "github.com/smartcontractkit/chain-selectors" - "github.com/stretchr/testify/require" - "gotest.tools/v3/assert" -) - -func TestAddressBook_Save(t *testing.T) { - ab := NewMemoryAddressBook() - onRamp100 := NewTypeAndVersion("OnRamp", Version1_0_0) - onRamp110 := NewTypeAndVersion("OnRamp", Version1_1_0) - addr1 := common.HexToAddress("0x1").String() - addr2 := common.HexToAddress("0x2").String() - - err := ab.Save(chainsel.TEST_90000001.Selector, addr1, onRamp100) - require.NoError(t, err) - - // Check input validation - err = ab.Save(chainsel.TEST_90000001.Selector, "asdlfkj", onRamp100) - require.Error(t, err) - assert.Equal(t, errors.Is(err, ErrInvalidAddress), true, "err %s", err) - 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) - - // Distinct address same TV will not - err = ab.Save(chainsel.TEST_90000001.Selector, addr2, onRamp100) - require.NoError(t, err) - // Same address different chain will not error - err = ab.Save(chainsel.TEST_90000002.Selector, addr1, onRamp100) - require.NoError(t, err) - // We can save different versions of the same contract - err = ab.Save(chainsel.TEST_90000002.Selector, addr2, onRamp110) - require.NoError(t, err) - - addresses, err := ab.Addresses() - require.NoError(t, err) - assert.DeepEqual(t, addresses, map[uint64]map[string]TypeAndVersion{ - chainsel.TEST_90000001.Selector: { - addr1: onRamp100, - addr2: onRamp100, - }, - chainsel.TEST_90000002.Selector: { - addr1: onRamp100, - addr2: onRamp110, - }, - }) -} - -func TestAddressBook_Merge(t *testing.T) { - onRamp100 := NewTypeAndVersion("OnRamp", Version1_0_0) - onRamp110 := NewTypeAndVersion("OnRamp", Version1_1_0) - addr1 := common.HexToAddress("0x1").String() - addr2 := common.HexToAddress("0x2").String() - a1 := NewMemoryAddressBookFromMap(map[uint64]map[string]TypeAndVersion{ - chainsel.TEST_90000001.Selector: { - addr1: onRamp100, - }, - }) - a2 := NewMemoryAddressBookFromMap(map[uint64]map[string]TypeAndVersion{ - chainsel.TEST_90000001.Selector: { - addr2: onRamp100, - }, - chainsel.TEST_90000002.Selector: { - addr1: onRamp110, - }, - }) - require.NoError(t, a1.Merge(a2)) - - addresses, err := a1.Addresses() - require.NoError(t, err) - assert.DeepEqual(t, addresses, map[uint64]map[string]TypeAndVersion{ - chainsel.TEST_90000001.Selector: { - addr1: onRamp100, - addr2: onRamp100, - }, - chainsel.TEST_90000002.Selector: { - addr1: onRamp110, - }, - }) - - // Merge with conflicting addresses should error - a3 := NewMemoryAddressBookFromMap(map[uint64]map[string]TypeAndVersion{ - chainsel.TEST_90000001.Selector: { - addr1: onRamp100, - }, - }) - require.Error(t, a1.Merge(a3)) - // a1 should not have changed - addresses, err = a1.Addresses() - require.NoError(t, err) - assert.DeepEqual(t, addresses, map[uint64]map[string]TypeAndVersion{ - chainsel.TEST_90000001.Selector: { - addr1: onRamp100, - addr2: onRamp100, - }, - chainsel.TEST_90000002.Selector: { - addr1: onRamp110, - }, - }) -} diff --git a/integration-tests/deployment/ccip/add_lane.go b/integration-tests/deployment/ccip/add_lane.go deleted file mode 100644 index 16384e0aba..0000000000 --- a/integration-tests/deployment/ccip/add_lane.go +++ /dev/null @@ -1,119 +0,0 @@ -package ccipdeployment - -import ( - "encoding/hex" - "math/big" - - "github.com/ethereum/go-ethereum/common" - - "github.com/smartcontractkit/chainlink/integration-tests/deployment" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/fee_quoter" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/offramp" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/onramp" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" -) - -func AddLane(e deployment.Environment, state CCIPOnChainState, from, to uint64) error { - // TODO: Batch - tx, err := state.Chains[from].Router.ApplyRampUpdates(e.Chains[from].DeployerKey, []router.RouterOnRamp{ - { - DestChainSelector: to, - OnRamp: state.Chains[from].EvmOnRampV160.Address(), - }, - }, []router.RouterOffRamp{}, []router.RouterOffRamp{}) - if err := deployment.ConfirmIfNoError(e.Chains[from], tx, err); err != nil { - return err - } - tx, err = state.Chains[from].EvmOnRampV160.ApplyDestChainConfigUpdates(e.Chains[from].DeployerKey, - []onramp.OnRampDestChainConfigArgs{ - { - DestChainSelector: to, - Router: state.Chains[from].Router.Address(), - }, - }) - if err := deployment.ConfirmIfNoError(e.Chains[from], tx, err); err != nil { - return err - } - - _, err = state.Chains[from].PriceRegistry.UpdatePrices( - e.Chains[from].DeployerKey, fee_quoter.InternalPriceUpdates{ - TokenPriceUpdates: []fee_quoter.InternalTokenPriceUpdate{ - { - SourceToken: state.Chains[from].LinkToken.Address(), - UsdPerToken: deployment.E18Mult(20), - }, - { - SourceToken: state.Chains[from].Weth9.Address(), - UsdPerToken: deployment.E18Mult(4000), - }, - }, - GasPriceUpdates: []fee_quoter.InternalGasPriceUpdate{ - { - DestChainSelector: to, - UsdPerUnitGas: big.NewInt(2e12), - }, - }}) - if err := deployment.ConfirmIfNoError(e.Chains[from], tx, err); err != nil { - return err - } - - // Enable dest in price registry - tx, err = state.Chains[from].PriceRegistry.ApplyDestChainConfigUpdates(e.Chains[from].DeployerKey, - []fee_quoter.FeeQuoterDestChainConfigArgs{ - { - DestChainSelector: to, - DestChainConfig: defaultPriceRegistryDestChainConfig(), - }, - }) - if err := deployment.ConfirmIfNoError(e.Chains[from], tx, err); err != nil { - return err - } - - tx, err = state.Chains[to].EvmOffRampV160.ApplySourceChainConfigUpdates(e.Chains[to].DeployerKey, - []offramp.OffRampSourceChainConfigArgs{ - { - Router: state.Chains[to].Router.Address(), - SourceChainSelector: from, - IsEnabled: true, - OnRamp: common.LeftPadBytes(state.Chains[from].EvmOnRampV160.Address().Bytes(), 32), - }, - }) - if err := deployment.ConfirmIfNoError(e.Chains[to], tx, err); err != nil { - return err - } - tx, err = state.Chains[to].Router.ApplyRampUpdates(e.Chains[to].DeployerKey, []router.RouterOnRamp{}, []router.RouterOffRamp{}, []router.RouterOffRamp{ - { - SourceChainSelector: from, - OffRamp: state.Chains[to].EvmOffRampV160.Address(), - }, - }) - return deployment.ConfirmIfNoError(e.Chains[to], tx, err) -} - -func defaultPriceRegistryDestChainConfig() fee_quoter.FeeQuoterDestChainConfig { - // https://github.com/smartcontractkit/ccip/blob/c4856b64bd766f1ddbaf5d13b42d3c4b12efde3a/contracts/src/v0.8/ccip/libraries/Internal.sol#L337-L337 - /* - ```Solidity - // bytes4(keccak256("CCIP ChainFamilySelector EVM")) - bytes4 public constant CHAIN_FAMILY_SELECTOR_EVM = 0x2812d52c; - ``` - */ - evmFamilySelector, _ := hex.DecodeString("2812d52c") - return fee_quoter.FeeQuoterDestChainConfig{ - IsEnabled: true, - MaxNumberOfTokensPerMsg: 10, - MaxDataBytes: 256, - MaxPerMsgGasLimit: 3_000_000, - DestGasOverhead: 50_000, - DefaultTokenFeeUSDCents: 1, - DestGasPerPayloadByte: 10, - DestDataAvailabilityOverheadGas: 0, - DestGasPerDataAvailabilityByte: 100, - DestDataAvailabilityMultiplierBps: 1, - DefaultTokenDestGasOverhead: 125_000, - DefaultTxGasLimit: 200_000, - GasMultiplierWeiPerEth: 1, - NetworkFeeUSDCents: 1, - ChainFamilySelector: [4]byte(evmFamilySelector), - } -} diff --git a/integration-tests/deployment/ccip/add_lane_test.go b/integration-tests/deployment/ccip/add_lane_test.go deleted file mode 100644 index 567f5ca685..0000000000 --- a/integration-tests/deployment/ccip/add_lane_test.go +++ /dev/null @@ -1 +0,0 @@ -package ccipdeployment diff --git a/integration-tests/deployment/ccip/changeset/1_cap_reg.go b/integration-tests/deployment/ccip/changeset/1_cap_reg.go deleted file mode 100644 index 1929aede02..0000000000 --- a/integration-tests/deployment/ccip/changeset/1_cap_reg.go +++ /dev/null @@ -1,21 +0,0 @@ -package changeset - -import ( - "github.com/smartcontractkit/chainlink/integration-tests/deployment" - ccipdeployment "github.com/smartcontractkit/chainlink/integration-tests/deployment/ccip" -) - -// Separate migration because cap reg is an env var for CL nodes. -func Apply0001(env deployment.Environment, homeChainSel uint64) (deployment.ChangesetOutput, error) { - // Note we also deploy the cap reg. - ab, _, err := ccipdeployment.DeployCapReg(env.Logger, env.Chains, homeChainSel) - if err != nil { - env.Logger.Errorw("Failed to deploy cap reg", "err", err, "addresses", ab) - return deployment.ChangesetOutput{}, err - } - return deployment.ChangesetOutput{ - Proposals: []deployment.Proposal{}, - AddressBook: ab, - JobSpecs: nil, - }, nil -} diff --git a/integration-tests/deployment/ccip/changeset/2_initial_deploy.go b/integration-tests/deployment/ccip/changeset/2_initial_deploy.go deleted file mode 100644 index b20ffb2d4a..0000000000 --- a/integration-tests/deployment/ccip/changeset/2_initial_deploy.go +++ /dev/null @@ -1,33 +0,0 @@ -package changeset - -import ( - "github.com/smartcontractkit/chainlink/integration-tests/deployment" - - ccipdeployment "github.com/smartcontractkit/chainlink/integration-tests/deployment/ccip" -) - -// We expect the change set input to be unique per change set. -// TODO: Maybe there's a generics approach here? -// Note if the change set is a deployment and it fails we have 2 options: -// - Just throw away the addresses, fix issue and try again (potentially expensive on mainnet) -func Apply0002(env deployment.Environment, c ccipdeployment.DeployCCIPContractConfig) (deployment.ChangesetOutput, error) { - ab, err := ccipdeployment.DeployCCIPContracts(env, c) - if err != nil { - env.Logger.Errorw("Failed to deploy CCIP contracts", "err", err, "addresses", ab) - return deployment.ChangesetOutput{}, err - } - js, err := ccipdeployment.NewCCIPJobSpecs(env.NodeIDs, env.Offchain) - if err != nil { - return deployment.ChangesetOutput{}, err - } - proposal, err := ccipdeployment.GenerateAcceptOwnershipProposal(env, env.AllChainSelectors(), ab) - if err != nil { - return deployment.ChangesetOutput{}, err - } - return deployment.ChangesetOutput{ - Proposals: []deployment.Proposal{proposal}, - AddressBook: ab, - // Mapping of which nodes get which jobs. - JobSpecs: js, - }, nil -} diff --git a/integration-tests/deployment/ccip/changeset/2_initial_deploy_test.go b/integration-tests/deployment/ccip/changeset/2_initial_deploy_test.go deleted file mode 100644 index db9fd994fd..0000000000 --- a/integration-tests/deployment/ccip/changeset/2_initial_deploy_test.go +++ /dev/null @@ -1,241 +0,0 @@ -package changeset - -import ( - "context" - "sync" - "testing" - "time" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" - "github.com/ethereum/go-ethereum/common" - "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/chainlink/integration-tests/deployment" - - "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3" - - jobv1 "github.com/smartcontractkit/chainlink/integration-tests/deployment/jd/job/v1" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/offramp" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" - - ccipdeployment "github.com/smartcontractkit/chainlink/integration-tests/deployment/ccip" - "github.com/smartcontractkit/chainlink/integration-tests/deployment/memory" - - "github.com/smartcontractkit/chainlink/v2/core/logger" -) - -func Test0002_InitialDeploy(t *testing.T) { - lggr := logger.TestLogger(t) - ctx := ccipdeployment.Context(t) - tenv := ccipdeployment.NewDeployedTestEnvironment(t, lggr) - e := tenv.Env - nodes := tenv.Nodes - chains := e.Chains - - state, err := ccipdeployment.LoadOnchainState(tenv.Env, tenv.Ab) - require.NoError(t, err) - - // Apply migration - output, err := Apply0002(tenv.Env, ccipdeployment.DeployCCIPContractConfig{ - HomeChainSel: tenv.HomeChainSel, - // Capreg/config already exist. - CCIPOnChainState: state, - }) - require.NoError(t, err) - // Get new state after migration. - state, err = ccipdeployment.LoadOnchainState(e, output.AddressBook) - require.NoError(t, err) - - // Ensure capreg logs are up to date. - require.NoError(t, ReplayAllLogs(nodes, chains)) - - // Apply the jobs. - for nodeID, jobs := range output.JobSpecs { - for _, job := range jobs { - // Note these auto-accept - _, err := e.Offchain.ProposeJob(ctx, - &jobv1.ProposeJobRequest{ - NodeId: nodeID, - Spec: job, - }) - require.NoError(t, err) - } - } - // Wait for plugins to register filters? - // TODO: Investigate how to avoid. - time.Sleep(30 * time.Second) - - // Ensure job related logs are up to date. - require.NoError(t, ReplayAllLogs(nodes, chains)) - - // Send a request from every router - // Add all lanes - for source := range e.Chains { - for dest := range e.Chains { - if source != dest { - require.NoError(t, ccipdeployment.AddLane(e, state, source, dest)) - } - } - } - - // Send a message from each chain to every other chain. - for src, srcChain := range e.Chains { - for dest := range e.Chains { - if src == dest { - continue - } - msg := router.ClientEVM2AnyMessage{ - Receiver: common.LeftPadBytes(state.Chains[dest].Receiver.Address().Bytes(), 32), - Data: []byte("hello"), - TokenAmounts: nil, // TODO: no tokens for now - FeeToken: state.Chains[src].Weth9.Address(), - ExtraArgs: nil, // TODO: no extra args for now, falls back to default - } - fee, err := state.Chains[src].Router.GetFee( - &bind.CallOpts{Context: context.Background()}, dest, msg) - require.NoError(t, err, deployment.MaybeDataErr(err)) - tx, err := state.Chains[src].Weth9.Deposit(&bind.TransactOpts{ - From: e.Chains[src].DeployerKey.From, - Signer: e.Chains[src].DeployerKey.Signer, - Value: fee, - }) - require.NoError(t, err) - require.NoError(t, srcChain.Confirm(tx.Hash())) - - // TODO: should be able to avoid this by using native? - tx, err = state.Chains[src].Weth9.Approve(e.Chains[src].DeployerKey, - state.Chains[src].Router.Address(), fee) - require.NoError(t, err) - require.NoError(t, srcChain.Confirm(tx.Hash())) - - t.Logf("Sending CCIP request from chain selector %d to chain selector %d", - src, dest) - tx, err = state.Chains[src].Router.CcipSend(e.Chains[src].DeployerKey, dest, msg) - require.NoError(t, err) - require.NoError(t, srcChain.Confirm(tx.Hash())) - } - } - - // Wait for all commit reports to land. - var wg sync.WaitGroup - for src, srcChain := range e.Chains { - for dest, dstChain := range e.Chains { - if src == dest { - continue - } - srcChain := srcChain - dstChain := dstChain - wg.Add(1) - go func(src, dest uint64) { - defer wg.Done() - waitForCommitWithInterval(t, srcChain, dstChain, state.Chains[dest].EvmOffRampV160, ccipocr3.SeqNumRange{1, 1}) - }(src, dest) - } - } - wg.Wait() - - // Wait for all exec reports to land - for src, srcChain := range e.Chains { - for dest, dstChain := range e.Chains { - if src == dest { - continue - } - srcChain := srcChain - dstChain := dstChain - wg.Add(1) - go func(src, dest deployment.Chain) { - defer wg.Done() - waitForExecWithSeqNr(t, src, dest, state.Chains[dest.Selector].EvmOffRampV160, 1) - }(srcChain, dstChain) - } - } - wg.Wait() - - // TODO: Apply the proposal. -} - -func ReplayAllLogs(nodes map[string]memory.Node, chains map[uint64]deployment.Chain) error { - for _, node := range nodes { - for sel := range chains { - if err := node.ReplayLogs(map[uint64]uint64{sel: 1}); err != nil { - return err - } - } - } - return nil -} - -func waitForCommitWithInterval( - t *testing.T, - src deployment.Chain, - dest deployment.Chain, - offRamp *offramp.OffRamp, - expectedSeqNumRange ccipocr3.SeqNumRange, -) { - sink := make(chan *offramp.OffRampCommitReportAccepted) - subscription, err := offRamp.WatchCommitReportAccepted(&bind.WatchOpts{ - Context: context.Background(), - }, sink) - require.NoError(t, err) - ticker := time.NewTicker(1 * time.Second) - defer ticker.Stop() - - //revive:disable - for { - select { - case <-ticker.C: - src.Client.(*backends.SimulatedBackend).Commit() - dest.Client.(*backends.SimulatedBackend).Commit() - t.Logf("Waiting for commit report on chain selector %d from source selector %d expected seq nr range %s", - dest.Selector, src.Selector, expectedSeqNumRange.String()) - case subErr := <-subscription.Err(): - t.Fatalf("Subscription error: %+v", subErr) - case report := <-sink: - if len(report.Report.MerkleRoots) > 0 { - // Check the interval of sequence numbers and make sure it matches - // the expected range. - for _, mr := range report.Report.MerkleRoots { - if mr.SourceChainSelector == src.Selector && - uint64(expectedSeqNumRange.Start()) == mr.Interval.Min && - uint64(expectedSeqNumRange.End()) == mr.Interval.Max { - t.Logf("Received commit report on selector %d from source selector %d expected seq nr range %s", - dest.Selector, src.Selector, expectedSeqNumRange.String()) - return - } - } - } - } - } -} - -func waitForExecWithSeqNr(t *testing.T, - source, dest deployment.Chain, - offramp *offramp.OffRamp, - expectedSeqNr uint64) { - tick := time.NewTicker(5 * time.Second) - defer tick.Stop() - for range tick.C { - // TODO: Clean this up - source.Client.(*backends.SimulatedBackend).Commit() - dest.Client.(*backends.SimulatedBackend).Commit() - scc, err := offramp.GetSourceChainConfig(nil, source.Selector) - require.NoError(t, err) - t.Logf("Waiting for ExecutionStateChanged on chain %d from chain %d with expected sequence number %d, current onchain minSeqNr: %d", - dest.Selector, source.Selector, expectedSeqNr, scc.MinSeqNr) - iter, err := offramp.FilterExecutionStateChanged(nil, - []uint64{source.Selector}, []uint64{expectedSeqNr}, nil) - require.NoError(t, err) - var count int - for iter.Next() { - if iter.Event.SequenceNumber == expectedSeqNr && iter.Event.SourceChainSelector == source.Selector { - count++ - } - } - if count == 1 { - t.Logf("Received ExecutionStateChanged on chain %d from chain %d with expected sequence number %d", - dest.Selector, source.Selector, expectedSeqNr) - return - } - } -} diff --git a/integration-tests/deployment/ccip/deploy.go b/integration-tests/deployment/ccip/deploy.go deleted file mode 100644 index ff589d1430..0000000000 --- a/integration-tests/deployment/ccip/deploy.go +++ /dev/null @@ -1,470 +0,0 @@ -package ccipdeployment - -import ( - "fmt" - "math/big" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - owner_helpers "github.com/smartcontractkit/ccip-owner-contracts/gethwrappers" - - "github.com/smartcontractkit/chainlink-common/pkg/logger" - "github.com/smartcontractkit/chainlink/integration-tests/deployment" - - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/ccip_config" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/fee_quoter" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/maybe_revert_message_receiver" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/mock_rmn_contract" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/nonce_manager" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/offramp" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/onramp" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_proxy_contract" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/token_admin_registry" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/weth9" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/burn_mint_erc677" -) - -var ( - MockARM deployment.ContractType = "MockRMN" - LinkToken deployment.ContractType = "LinkToken" - ARMProxy deployment.ContractType = "ARMProxy" - WETH9 deployment.ContractType = "WETH9" - Router deployment.ContractType = "Router" - TokenAdminRegistry deployment.ContractType = "TokenAdminRegistry" - NonceManager deployment.ContractType = "NonceManager" - PriceRegistry deployment.ContractType = "PriceRegistry" - ManyChainMultisig deployment.ContractType = "ManyChainMultiSig" - CCIPConfig deployment.ContractType = "CCIPConfig" - RBACTimelock deployment.ContractType = "RBACTimelock" - OnRamp deployment.ContractType = "OnRamp" - OffRamp deployment.ContractType = "OffRamp" - CCIPReceiver deployment.ContractType = "CCIPReceiver" - CapabilitiesRegistry deployment.ContractType = "CapabilitiesRegistry" -) - -type Contracts interface { - *capabilities_registry.CapabilitiesRegistry | - *rmn_proxy_contract.RMNProxyContract | - *ccip_config.CCIPConfig | - *nonce_manager.NonceManager | - *fee_quoter.FeeQuoter | - *router.Router | - *token_admin_registry.TokenAdminRegistry | - *weth9.WETH9 | - *mock_rmn_contract.MockRMNContract | - *owner_helpers.ManyChainMultiSig | - *owner_helpers.RBACTimelock | - *offramp.OffRamp | - *onramp.OnRamp | - *burn_mint_erc677.BurnMintERC677 | - *maybe_revert_message_receiver.MaybeRevertMessageReceiver -} - -type ContractDeploy[C Contracts] struct { - // We just keep all the deploy return values - // since some will be empty if there's an error. - Address common.Address - Contract C - Tx *types.Transaction - Tv deployment.TypeAndVersion - Err error -} - -// TODO: pull up to general deployment pkg somehow -// without exposing all product specific contracts? -func deployContract[C Contracts]( - lggr logger.Logger, - chain deployment.Chain, - addressBook deployment.AddressBook, - deploy func(chain deployment.Chain) ContractDeploy[C], -) (*ContractDeploy[C], error) { - contractDeploy := deploy(chain) - if contractDeploy.Err != nil { - lggr.Errorw("Failed to deploy contract", "err", contractDeploy.Err) - return nil, contractDeploy.Err - } - err := chain.Confirm(contractDeploy.Tx.Hash()) - if err != nil { - lggr.Errorw("Failed to confirm deployment", "err", err) - return nil, err - } - err = addressBook.Save(chain.Selector, contractDeploy.Address.String(), contractDeploy.Tv) - if err != nil { - lggr.Errorw("Failed to save contract address", "err", err) - return nil, err - } - return &contractDeploy, nil -} - -type DeployCCIPContractConfig struct { - HomeChainSel uint64 - // Existing contracts which we want to skip deployment - // Leave empty if we want to deploy everything - // TODO: Add skips to deploy function. - CCIPOnChainState -} - -// TODO: Likely we'll want to further parameterize the deployment -// For example a list of contracts to skip deploying if they already exist. -// Or mock vs real RMN. -// Deployment produces an address book of everything it deployed. -func DeployCCIPContracts(e deployment.Environment, c DeployCCIPContractConfig) (deployment.AddressBook, error) { - var ab deployment.AddressBook = deployment.NewMemoryAddressBook() - nodes, err := deployment.NodeInfo(e.NodeIDs, e.Offchain) - if err != nil || len(nodes) == 0 { - e.Logger.Errorw("Failed to get node info", "err", err) - return ab, err - } - if c.Chains[c.HomeChainSel].CapabilityRegistry == nil { - return ab, fmt.Errorf("Capability registry not found for home chain %d, needs to be deployed first", c.HomeChainSel) - } - cr, err := c.Chains[c.HomeChainSel].CapabilityRegistry.GetHashedCapabilityId( - &bind.CallOpts{}, CapabilityLabelledName, CapabilityVersion) - if err != nil { - e.Logger.Errorw("Failed to get hashed capability id", "err", err) - return ab, err - } - // Signal to CR that our nodes support CCIP capability. - if err := AddNodes( - c.Chains[c.HomeChainSel].CapabilityRegistry, - e.Chains[c.HomeChainSel], - nodes.PeerIDs(c.HomeChainSel), // Doesn't actually matter which sel here - [][32]byte{cr}, - ); err != nil { - return ab, err - } - - for _, chain := range e.Chains { - ab, err = DeployChainContracts(e, chain, ab) - if err != nil { - return ab, err - } - chainAddresses, err := ab.AddressesForChain(chain.Selector) - if err != nil { - e.Logger.Errorw("Failed to get chain addresses", "err", err) - return ab, err - } - chainState, err := LoadChainState(chain, chainAddresses) - if err != nil { - e.Logger.Errorw("Failed to load chain state", "err", err) - return ab, err - } - // Enable ramps on price registry/nonce manager - tx, err := chainState.PriceRegistry.ApplyAuthorizedCallerUpdates(chain.DeployerKey, fee_quoter.AuthorizedCallersAuthorizedCallerArgs{ - // TODO: We enable the deployer initially to set prices - AddedCallers: []common.Address{chainState.EvmOffRampV160.Address(), chain.DeployerKey.From}, - }) - if err := deployment.ConfirmIfNoError(chain, tx, err); err != nil { - e.Logger.Errorw("Failed to confirm price registry authorized caller update", "err", err) - return ab, err - } - - tx, err = chainState.NonceManager.ApplyAuthorizedCallerUpdates(chain.DeployerKey, nonce_manager.AuthorizedCallersAuthorizedCallerArgs{ - AddedCallers: []common.Address{chainState.EvmOffRampV160.Address(), chainState.EvmOnRampV160.Address()}, - }) - if err := deployment.ConfirmIfNoError(chain, tx, err); err != nil { - e.Logger.Errorw("Failed to update nonce manager with ramps", "err", err) - return ab, err - } - - // Add chain config for each chain. - _, err = AddChainConfig(e.Logger, - e.Chains[c.HomeChainSel], - c.Chains[c.HomeChainSel].CCIPConfig, - chain.Selector, - nodes.PeerIDs(chain.Selector), - uint8(len(nodes)/3)) - if err != nil { - return ab, err - } - - // For each chain, we create a DON on the home chain. - if err := AddDON(e.Logger, - cr, - c.Chains[c.HomeChainSel].CapabilityRegistry, - c.Chains[c.HomeChainSel].CCIPConfig, - chainState.EvmOffRampV160, - chain, - e.Chains[c.HomeChainSel], - uint8(len(nodes)/3), - nodes.BootstrapPeerIDs(chain.Selector)[0], - nodes.PeerIDs(chain.Selector), - nodes, - ); err != nil { - e.Logger.Errorw("Failed to add DON", "err", err) - return ab, err - } - } - - return ab, nil -} - -func DeployChainContracts(e deployment.Environment, chain deployment.Chain, ab deployment.AddressBook) (deployment.AddressBook, error) { - ccipReceiver, err := deployContract(e.Logger, chain, ab, - func(chain deployment.Chain) ContractDeploy[*maybe_revert_message_receiver.MaybeRevertMessageReceiver] { - receiverAddr, tx, receiver, err2 := maybe_revert_message_receiver.DeployMaybeRevertMessageReceiver( - chain.DeployerKey, - chain.Client, - false, - ) - return ContractDeploy[*maybe_revert_message_receiver.MaybeRevertMessageReceiver]{ - receiverAddr, receiver, tx, deployment.NewTypeAndVersion(CCIPReceiver, deployment.Version1_0_0), err2, - } - }) - if err != nil { - e.Logger.Errorw("Failed to deploy receiver", "err", err) - return ab, err - } - e.Logger.Infow("deployed receiver", "addr", ccipReceiver.Address) - - // TODO: Still waiting for RMNRemote/RMNHome contracts etc. - mockARM, err := deployContract(e.Logger, chain, ab, - func(chain deployment.Chain) ContractDeploy[*mock_rmn_contract.MockRMNContract] { - mockARMAddr, tx, mockARM, err2 := mock_rmn_contract.DeployMockRMNContract( - chain.DeployerKey, - chain.Client, - ) - return ContractDeploy[*mock_rmn_contract.MockRMNContract]{ - mockARMAddr, mockARM, tx, deployment.NewTypeAndVersion(MockARM, deployment.Version1_0_0), err2, - } - }) - if err != nil { - e.Logger.Errorw("Failed to deploy mockARM", "err", err) - return ab, err - } - e.Logger.Infow("deployed mockARM", "addr", mockARM) - - mcm, err := deployContract(e.Logger, chain, ab, - func(chain deployment.Chain) ContractDeploy[*owner_helpers.ManyChainMultiSig] { - mcmAddr, tx, mcm, err2 := owner_helpers.DeployManyChainMultiSig( - chain.DeployerKey, - chain.Client, - ) - return ContractDeploy[*owner_helpers.ManyChainMultiSig]{ - mcmAddr, mcm, tx, deployment.NewTypeAndVersion(ManyChainMultisig, deployment.Version1_0_0), err2, - } - }) - if err != nil { - e.Logger.Errorw("Failed to deploy mcm", "err", err) - return ab, err - } - // TODO: Address soon - e.Logger.Infow("deployed mcm", "addr", mcm.Address) - - _, err = deployContract(e.Logger, chain, ab, - func(chain deployment.Chain) ContractDeploy[*owner_helpers.RBACTimelock] { - timelock, tx, cc, err2 := owner_helpers.DeployRBACTimelock( - chain.DeployerKey, - chain.Client, - big.NewInt(0), // minDelay - mcm.Address, - []common.Address{mcm.Address}, // proposers - []common.Address{chain.DeployerKey.From}, //executors - []common.Address{mcm.Address}, // cancellers - []common.Address{mcm.Address}, // bypassers - ) - return ContractDeploy[*owner_helpers.RBACTimelock]{ - timelock, cc, tx, deployment.NewTypeAndVersion(RBACTimelock, deployment.Version1_0_0), err2, - } - }) - if err != nil { - e.Logger.Errorw("Failed to deploy timelock", "err", err) - return ab, err - } - e.Logger.Infow("deployed timelock", "addr", mcm.Address) - - rmnProxy, err := deployContract(e.Logger, chain, ab, - func(chain deployment.Chain) ContractDeploy[*rmn_proxy_contract.RMNProxyContract] { - rmnProxyAddr, tx, rmnProxy, err2 := rmn_proxy_contract.DeployRMNProxyContract( - chain.DeployerKey, - chain.Client, - mockARM.Address, - ) - return ContractDeploy[*rmn_proxy_contract.RMNProxyContract]{ - rmnProxyAddr, rmnProxy, tx, deployment.NewTypeAndVersion(ARMProxy, deployment.Version1_0_0), err2, - } - }) - if err != nil { - e.Logger.Errorw("Failed to deploy rmnProxy", "err", err) - return ab, err - } - e.Logger.Infow("deployed rmnProxy", "addr", rmnProxy.Address) - - weth9, err := deployContract(e.Logger, chain, ab, - func(chain deployment.Chain) ContractDeploy[*weth9.WETH9] { - weth9Addr, tx, weth9c, err2 := weth9.DeployWETH9( - chain.DeployerKey, - chain.Client, - ) - return ContractDeploy[*weth9.WETH9]{ - weth9Addr, weth9c, tx, deployment.NewTypeAndVersion(WETH9, deployment.Version1_0_0), err2, - } - }) - if err != nil { - e.Logger.Errorw("Failed to deploy weth9", "err", err) - return ab, err - } - - linkToken, err := deployContract(e.Logger, chain, ab, - func(chain deployment.Chain) ContractDeploy[*burn_mint_erc677.BurnMintERC677] { - linkTokenAddr, tx, linkToken, err2 := burn_mint_erc677.DeployBurnMintERC677( - chain.DeployerKey, - chain.Client, - "Link Token", - "LINK", - uint8(18), - big.NewInt(0).Mul(big.NewInt(1e9), big.NewInt(1e18)), - ) - return ContractDeploy[*burn_mint_erc677.BurnMintERC677]{ - linkTokenAddr, linkToken, tx, deployment.NewTypeAndVersion(LinkToken, deployment.Version1_0_0), err2, - } - }) - if err != nil { - e.Logger.Errorw("Failed to deploy linkToken", "err", err) - return ab, err - } - - routerContract, err := deployContract(e.Logger, chain, ab, - func(chain deployment.Chain) ContractDeploy[*router.Router] { - routerAddr, tx, routerC, err2 := router.DeployRouter( - chain.DeployerKey, - chain.Client, - weth9.Address, - rmnProxy.Address, - ) - return ContractDeploy[*router.Router]{ - routerAddr, routerC, tx, deployment.NewTypeAndVersion(Router, deployment.Version1_2_0), err2, - } - }) - if err != nil { - e.Logger.Errorw("Failed to deploy router", "err", err) - return ab, err - } - e.Logger.Infow("deployed router", "addr", routerContract) - - tokenAdminRegistry, err := deployContract(e.Logger, chain, ab, - func(chain deployment.Chain) ContractDeploy[*token_admin_registry.TokenAdminRegistry] { - tokenAdminRegistryAddr, tx, tokenAdminRegistry, err2 := token_admin_registry.DeployTokenAdminRegistry( - chain.DeployerKey, - chain.Client) - return ContractDeploy[*token_admin_registry.TokenAdminRegistry]{ - tokenAdminRegistryAddr, tokenAdminRegistry, tx, deployment.NewTypeAndVersion(TokenAdminRegistry, deployment.Version1_5_0), err2, - } - }) - if err != nil { - e.Logger.Errorw("Failed to deploy token admin registry", "err", err) - return ab, err - } - e.Logger.Infow("deployed tokenAdminRegistry", "addr", tokenAdminRegistry) - - nonceManager, err := deployContract(e.Logger, chain, ab, - func(chain deployment.Chain) ContractDeploy[*nonce_manager.NonceManager] { - nonceManagerAddr, tx, nonceManager, err2 := nonce_manager.DeployNonceManager( - chain.DeployerKey, - chain.Client, - []common.Address{}, // Need to add onRamp after - ) - return ContractDeploy[*nonce_manager.NonceManager]{ - nonceManagerAddr, nonceManager, tx, deployment.NewTypeAndVersion(NonceManager, deployment.Version1_6_0_dev), err2, - } - }) - if err != nil { - e.Logger.Errorw("Failed to deploy router", "err", err) - return ab, err - } - - feeQuoter, err := deployContract(e.Logger, chain, ab, - func(chain deployment.Chain) ContractDeploy[*fee_quoter.FeeQuoter] { - prAddr, tx, pr, err2 := fee_quoter.DeployFeeQuoter( - chain.DeployerKey, - chain.Client, - fee_quoter.FeeQuoterStaticConfig{ - MaxFeeJuelsPerMsg: big.NewInt(0).Mul(big.NewInt(2e2), big.NewInt(1e18)), - LinkToken: linkToken.Address, - StalenessThreshold: uint32(24 * 60 * 60), - }, - []common.Address{}, // ramps added after - []common.Address{weth9.Address, linkToken.Address}, // fee tokens - []fee_quoter.FeeQuoterTokenPriceFeedUpdate{}, - []fee_quoter.FeeQuoterTokenTransferFeeConfigArgs{}, // TODO: tokens - []fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthArgs{ - { - PremiumMultiplierWeiPerEth: 9e17, // 0.9 ETH - Token: linkToken.Address, - }, - { - PremiumMultiplierWeiPerEth: 1e18, - Token: weth9.Address, - }, - }, - []fee_quoter.FeeQuoterDestChainConfigArgs{}, - ) - return ContractDeploy[*fee_quoter.FeeQuoter]{ - prAddr, pr, tx, deployment.NewTypeAndVersion(PriceRegistry, deployment.Version1_6_0_dev), err2, - } - }) - if err != nil { - e.Logger.Errorw("Failed to deploy price registry", "err", err) - return ab, err - } - - onRamp, err := deployContract(e.Logger, chain, ab, - func(chain deployment.Chain) ContractDeploy[*onramp.OnRamp] { - onRampAddr, tx, onRamp, err2 := onramp.DeployOnRamp( - chain.DeployerKey, - chain.Client, - onramp.OnRampStaticConfig{ - ChainSelector: chain.Selector, - RmnProxy: rmnProxy.Address, - NonceManager: nonceManager.Address, - TokenAdminRegistry: tokenAdminRegistry.Address, - }, - onramp.OnRampDynamicConfig{ - FeeQuoter: feeQuoter.Address, - FeeAggregator: common.HexToAddress("0x1"), // TODO real fee aggregator - }, - []onramp.OnRampDestChainConfigArgs{}, - ) - return ContractDeploy[*onramp.OnRamp]{ - onRampAddr, onRamp, tx, deployment.NewTypeAndVersion(OnRamp, deployment.Version1_6_0_dev), err2, - } - }) - if err != nil { - e.Logger.Errorw("Failed to deploy onramp", "err", err) - return ab, err - } - e.Logger.Infow("deployed onramp", "addr", onRamp.Address) - - offRamp, err := deployContract(e.Logger, chain, ab, - func(chain deployment.Chain) ContractDeploy[*offramp.OffRamp] { - offRampAddr, tx, offRamp, err2 := offramp.DeployOffRamp( - chain.DeployerKey, - chain.Client, - offramp.OffRampStaticConfig{ - ChainSelector: chain.Selector, - RmnProxy: rmnProxy.Address, - NonceManager: nonceManager.Address, - TokenAdminRegistry: tokenAdminRegistry.Address, - }, - offramp.OffRampDynamicConfig{ - FeeQuoter: feeQuoter.Address, - PermissionLessExecutionThresholdSeconds: uint32(86400), - MaxTokenTransferGas: uint32(200_000), - MaxPoolReleaseOrMintGas: uint32(200_000), - }, - []offramp.OffRampSourceChainConfigArgs{}, - ) - return ContractDeploy[*offramp.OffRamp]{ - offRampAddr, offRamp, tx, deployment.NewTypeAndVersion(OffRamp, deployment.Version1_6_0_dev), err2, - } - }) - if err != nil { - e.Logger.Errorw("Failed to deploy offramp", "err", err) - return ab, err - } - e.Logger.Infow("deployed offramp", "addr", offRamp) - return ab, nil -} diff --git a/integration-tests/deployment/ccip/deploy_home_chain.go b/integration-tests/deployment/ccip/deploy_home_chain.go deleted file mode 100644 index 10e7e9552b..0000000000 --- a/integration-tests/deployment/ccip/deploy_home_chain.go +++ /dev/null @@ -1,401 +0,0 @@ -package ccipdeployment - -import ( - "bytes" - "context" - "errors" - "sort" - "time" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - confighelper2 "github.com/smartcontractkit/libocr/offchainreporting2plus/confighelper" - "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3confighelper" - - "github.com/smartcontractkit/chainlink-ccip/chainconfig" - "github.com/smartcontractkit/chainlink-ccip/pluginconfig" - commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" - "github.com/smartcontractkit/chainlink-common/pkg/logger" - "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3" - - "github.com/smartcontractkit/chainlink/integration-tests/deployment" - cctypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/types" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/ccip_config" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/ocr3_config_encoder" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/offramp" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" -) - -const ( - NodeOperatorID = 1 - CapabilityLabelledName = "ccip" - CapabilityVersion = "v1.0.0" - - FirstBlockAge = 8 * time.Hour - RemoteGasPriceBatchWriteFrequency = 30 * time.Minute - BatchGasLimit = 6_500_000 - RelativeBoostPerWaitHour = 1.5 - InflightCacheExpiry = 10 * time.Minute - RootSnoozeTime = 30 * time.Minute - BatchingStrategyID = 0 - DeltaProgress = 30 * time.Second - DeltaResend = 10 * time.Second - DeltaInitial = 20 * time.Second - DeltaRound = 2 * time.Second - DeltaGrace = 2 * time.Second - DeltaCertifiedCommitRequest = 10 * time.Second - DeltaStage = 10 * time.Second - Rmax = 3 - MaxDurationQuery = 50 * time.Millisecond - MaxDurationObservation = 5 * time.Second - MaxDurationShouldAcceptAttestedReport = 10 * time.Second - MaxDurationShouldTransmitAcceptedReport = 10 * time.Second -) - -func DeployCapReg(lggr logger.Logger, chains map[uint64]deployment.Chain, chainSel uint64) (deployment.AddressBook, common.Address, error) { - ab := deployment.NewMemoryAddressBook() - chain := chains[chainSel] - capReg, err := deployContract(lggr, chain, ab, - func(chain deployment.Chain) ContractDeploy[*capabilities_registry.CapabilitiesRegistry] { - crAddr, tx, cr, err2 := capabilities_registry.DeployCapabilitiesRegistry( - chain.DeployerKey, - chain.Client, - ) - return ContractDeploy[*capabilities_registry.CapabilitiesRegistry]{ - Address: crAddr, Contract: cr, Tv: deployment.NewTypeAndVersion(CapabilitiesRegistry, deployment.Version1_0_0), Tx: tx, Err: err2, - } - }) - if err != nil { - lggr.Errorw("Failed to deploy capreg", "err", err) - return ab, common.Address{}, err - } - lggr.Infow("deployed capreg", "addr", capReg.Address) - ccipConfig, err := deployContract( - lggr, chain, ab, - func(chain deployment.Chain) ContractDeploy[*ccip_config.CCIPConfig] { - ccAddr, tx, cc, err2 := ccip_config.DeployCCIPConfig( - chain.DeployerKey, - chain.Client, - capReg.Address, - ) - return ContractDeploy[*ccip_config.CCIPConfig]{ - Address: ccAddr, Tv: deployment.NewTypeAndVersion(CCIPConfig, deployment.Version1_6_0_dev), Tx: tx, Err: err2, Contract: cc, - } - }) - if err != nil { - lggr.Errorw("Failed to deploy ccip config", "err", err) - return ab, common.Address{}, err - } - lggr.Infow("deployed ccip config", "addr", ccipConfig.Address) - - tx, err := capReg.Contract.AddCapabilities(chain.DeployerKey, []capabilities_registry.CapabilitiesRegistryCapability{ - { - LabelledName: CapabilityLabelledName, - Version: CapabilityVersion, - CapabilityType: 2, // consensus. not used (?) - ResponseType: 0, // report. not used (?) - ConfigurationContract: ccipConfig.Address, - }, - }) - if err := deployment.ConfirmIfNoError(chain, tx, err); err != nil { - lggr.Errorw("Failed to add capabilities", "err", err) - return ab, common.Address{}, err - } - // TODO: Just one for testing. - tx, err = capReg.Contract.AddNodeOperators(chain.DeployerKey, []capabilities_registry.CapabilitiesRegistryNodeOperator{ - { - Admin: chain.DeployerKey.From, - Name: "NodeOperator", - }, - }) - if err := deployment.ConfirmIfNoError(chain, tx, err); err != nil { - lggr.Errorw("Failed to add node operators", "err", err) - return ab, common.Address{}, err - } - return ab, capReg.Address, nil -} - -func sortP2PIDS(p2pIDs [][32]byte) { - sort.Slice(p2pIDs, func(i, j int) bool { - return bytes.Compare(p2pIDs[i][:], p2pIDs[j][:]) < 0 - }) -} - -func AddNodes( - capReg *capabilities_registry.CapabilitiesRegistry, - chain deployment.Chain, - p2pIDs [][32]byte, - capabilityIDs [][32]byte, -) error { - // Need to sort, otherwise _checkIsValidUniqueSubset onChain will fail - sortP2PIDS(p2pIDs) - var nodeParams []capabilities_registry.CapabilitiesRegistryNodeParams - for _, p2pID := range p2pIDs { - nodeParam := capabilities_registry.CapabilitiesRegistryNodeParams{ - NodeOperatorId: NodeOperatorID, - Signer: p2pID, // Not used in tests - P2pId: p2pID, - HashedCapabilityIds: capabilityIDs, - } - nodeParams = append(nodeParams, nodeParam) - } - tx, err := capReg.AddNodes(chain.DeployerKey, nodeParams) - if err != nil { - return err - } - return chain.Confirm(tx.Hash()) -} - -func SetupConfigInfo(chainSelector uint64, readers [][32]byte, fChain uint8, cfg []byte) ccip_config.CCIPConfigTypesChainConfigInfo { - return ccip_config.CCIPConfigTypesChainConfigInfo{ - ChainSelector: chainSelector, - ChainConfig: ccip_config.CCIPConfigTypesChainConfig{ - Readers: readers, - FChain: fChain, - Config: cfg, - }, - } -} - -func AddChainConfig( - lggr logger.Logger, - h deployment.Chain, - ccipConfig *ccip_config.CCIPConfig, - chainSelector uint64, - p2pIDs [][32]byte, - f uint8, -) (ccip_config.CCIPConfigTypesChainConfigInfo, error) { - // Need to sort, otherwise _checkIsValidUniqueSubset onChain will fail - sortP2PIDS(p2pIDs) - // First Add ChainConfig that includes all p2pIDs as readers - encodedExtraChainConfig, err := chainconfig.EncodeChainConfig(chainconfig.ChainConfig{ - GasPriceDeviationPPB: ccipocr3.NewBigIntFromInt64(1000), - DAGasPriceDeviationPPB: ccipocr3.NewBigIntFromInt64(0), - FinalityDepth: 10, - OptimisticConfirmations: 1, - }) - if err != nil { - return ccip_config.CCIPConfigTypesChainConfigInfo{}, err - } - chainConfig := SetupConfigInfo(chainSelector, p2pIDs, f, encodedExtraChainConfig) - inputConfig := []ccip_config.CCIPConfigTypesChainConfigInfo{ - chainConfig, - } - tx, err := ccipConfig.ApplyChainConfigUpdates(h.DeployerKey, nil, inputConfig) - if err := deployment.ConfirmIfNoError(h, tx, err); err != nil { - return ccip_config.CCIPConfigTypesChainConfigInfo{}, err - } - lggr.Infow("Applied chain config updates", "chainConfig", chainConfig) - return chainConfig, nil -} - -func AddDON( - lggr logger.Logger, - ccipCapabilityID [32]byte, - capReg *capabilities_registry.CapabilitiesRegistry, - ccipConfig *ccip_config.CCIPConfig, - offRamp *offramp.OffRamp, - dest deployment.Chain, - home deployment.Chain, - f uint8, - bootstrapP2PID [32]byte, - p2pIDs [][32]byte, - nodes []deployment.Node, -) error { - sortP2PIDS(p2pIDs) - // Get OCR3 Config from helper - var schedule []int - var oracles []confighelper2.OracleIdentityExtra - for _, node := range nodes { - schedule = append(schedule, 1) - cfg := node.SelToOCRConfig[dest.Selector] - oracles = append(oracles, confighelper2.OracleIdentityExtra{ - OracleIdentity: confighelper2.OracleIdentity{ - OnchainPublicKey: cfg.OnchainPublicKey, - TransmitAccount: cfg.TransmitAccount, - OffchainPublicKey: cfg.OffchainPublicKey, - PeerID: cfg.PeerID.String()[4:], - }, ConfigEncryptionPublicKey: cfg.ConfigEncryptionPublicKey, - }) - } - - tabi, err := ocr3_config_encoder.IOCR3ConfigEncoderMetaData.GetAbi() - if err != nil { - return err - } - - // Add DON on capability registry contract - var ocr3Configs []ocr3_config_encoder.CCIPConfigTypesOCR3Config - for _, pluginType := range []cctypes.PluginType{cctypes.PluginTypeCCIPCommit, cctypes.PluginTypeCCIPExec} { - var encodedOffchainConfig []byte - var err2 error - if pluginType == cctypes.PluginTypeCCIPCommit { - encodedOffchainConfig, err2 = pluginconfig.EncodeCommitOffchainConfig(pluginconfig.CommitOffchainConfig{ - RemoteGasPriceBatchWriteFrequency: *commonconfig.MustNewDuration(RemoteGasPriceBatchWriteFrequency), - // TODO: implement token price writes - // TokenPriceBatchWriteFrequency: *commonconfig.MustNewDuration(tokenPriceBatchWriteFrequency), - }) - } else { - encodedOffchainConfig, err2 = pluginconfig.EncodeExecuteOffchainConfig(pluginconfig.ExecuteOffchainConfig{ - BatchGasLimit: BatchGasLimit, - RelativeBoostPerWaitHour: RelativeBoostPerWaitHour, - MessageVisibilityInterval: *commonconfig.MustNewDuration(FirstBlockAge), - InflightCacheExpiry: *commonconfig.MustNewDuration(InflightCacheExpiry), - RootSnoozeTime: *commonconfig.MustNewDuration(RootSnoozeTime), - BatchingStrategyID: BatchingStrategyID, - }) - } - if err2 != nil { - return err2 - } - signers, transmitters, configF, _, offchainConfigVersion, offchainConfig, err2 := ocr3confighelper.ContractSetConfigArgsForTests( - DeltaProgress, - DeltaResend, - DeltaInitial, - DeltaRound, - DeltaGrace, - DeltaCertifiedCommitRequest, - DeltaStage, - Rmax, - schedule, - oracles, - encodedOffchainConfig, - MaxDurationQuery, - MaxDurationObservation, - MaxDurationShouldAcceptAttestedReport, - MaxDurationShouldTransmitAcceptedReport, - int(f), - []byte{}, // empty OnChainConfig - ) - if err2 != nil { - return err2 - } - - signersBytes := make([][]byte, len(signers)) - for i, signer := range signers { - signersBytes[i] = signer - } - - transmittersBytes := make([][]byte, len(transmitters)) - for i, transmitter := range transmitters { - parsed, err2 := common.ParseHexOrString(string(transmitter)) - if err2 != nil { - return err2 - } - transmittersBytes[i] = parsed - } - - ocr3Configs = append(ocr3Configs, ocr3_config_encoder.CCIPConfigTypesOCR3Config{ - PluginType: uint8(pluginType), - ChainSelector: dest.Selector, - F: configF, - OffchainConfigVersion: offchainConfigVersion, - OfframpAddress: offRamp.Address().Bytes(), - BootstrapP2PIds: [][32]byte{bootstrapP2PID}, - P2pIds: p2pIDs, - Signers: signersBytes, - Transmitters: transmittersBytes, - OffchainConfig: offchainConfig, - }) - } - - encodedCall, err := tabi.Pack("exposeOCR3Config", ocr3Configs) - if err != nil { - return err - } - - // Trim first four bytes to remove function selector. - encodedConfigs := encodedCall[4:] - - tx, err := capReg.AddDON(home.DeployerKey, p2pIDs, []capabilities_registry.CapabilitiesRegistryCapabilityConfiguration{ - { - CapabilityId: ccipCapabilityID, - Config: encodedConfigs, - }, - }, false, false, f) - if err := deployment.ConfirmIfNoError(home, tx, err); err != nil { - return err - } - - latestBlock, err := home.Client.HeaderByNumber(context.Background(), nil) - if err != nil { - return err - } - endBlock := latestBlock.Number.Uint64() - iter, err := capReg.FilterConfigSet(&bind.FilterOpts{ - Start: endBlock - 1, - End: &endBlock, - }) - if err != nil { - return err - } - var donID uint32 - for iter.Next() { - donID = iter.Event.DonId - break - } - if donID == 0 { - return errors.New("failed to get donID") - } - - var signerAddresses []common.Address - for _, oracle := range oracles { - signerAddresses = append(signerAddresses, common.BytesToAddress(oracle.OnchainPublicKey)) - } - - var transmitterAddresses []common.Address - for _, oracle := range oracles { - transmitterAddresses = append(transmitterAddresses, common.HexToAddress(string(oracle.TransmitAccount))) - } - - // get the config digest from the ccip config contract and set config on the offramp. - var offrampOCR3Configs []offramp.MultiOCR3BaseOCRConfigArgs - for _, pluginType := range []cctypes.PluginType{cctypes.PluginTypeCCIPCommit, cctypes.PluginTypeCCIPExec} { - ocrConfig, err2 := ccipConfig.GetOCRConfig(&bind.CallOpts{ - Context: context.Background(), - }, donID, uint8(pluginType)) - if err2 != nil { - return err2 - } - if len(ocrConfig) != 1 { - return errors.New("expected exactly one OCR3 config") - } - - offrampOCR3Configs = append(offrampOCR3Configs, offramp.MultiOCR3BaseOCRConfigArgs{ - ConfigDigest: ocrConfig[0].ConfigDigest, - OcrPluginType: uint8(pluginType), - F: f, - IsSignatureVerificationEnabled: pluginType == cctypes.PluginTypeCCIPCommit, - Signers: signerAddresses, - Transmitters: transmitterAddresses, - }) - } - - tx, err = offRamp.SetOCR3Configs(dest.DeployerKey, offrampOCR3Configs) - if err := deployment.ConfirmIfNoError(dest, tx, err); err != nil { - return err - } - - for _, pluginType := range []cctypes.PluginType{cctypes.PluginTypeCCIPCommit, cctypes.PluginTypeCCIPExec} { - _, err = offRamp.LatestConfigDetails(&bind.CallOpts{ - Context: context.Background(), - }, uint8(pluginType)) - if err != nil { - //return err - return deployment.MaybeDataErr(err) - } - // TODO: assertions to be done as part of full state - // resprentation validation CCIP-3047 - //require.Equalf(t, offrampOCR3Configs[pluginType].ConfigDigest, ocrConfig.ConfigInfo.ConfigDigest, "%s OCR3 config digest mismatch", pluginType.String()) - //require.Equalf(t, offrampOCR3Configs[pluginType].F, ocrConfig.ConfigInfo.F, "%s OCR3 config F mismatch", pluginType.String()) - //require.Equalf(t, offrampOCR3Configs[pluginType].IsSignatureVerificationEnabled, ocrConfig.ConfigInfo.IsSignatureVerificationEnabled, "%s OCR3 config signature verification mismatch", pluginType.String()) - //if pluginType == cctypes.PluginTypeCCIPCommit { - // // only commit will set signers, exec doesn't need them. - // require.Equalf(t, offrampOCR3Configs[pluginType].Signers, ocrConfig.Signers, "%s OCR3 config signers mismatch", pluginType.String()) - //} - //require.Equalf(t, offrampOCR3Configs[pluginType].TransmittersByEVMChainID, ocrConfig.TransmittersByEVMChainID, "%s OCR3 config transmitters mismatch", pluginType.String()) - } - - lggr.Infof("set ocr3 config on the offramp, signers: %+v, transmitters: %+v", signerAddresses, transmitterAddresses) - return nil -} diff --git a/integration-tests/deployment/ccip/deploy_test.go b/integration-tests/deployment/ccip/deploy_test.go deleted file mode 100644 index 7bc56f82f7..0000000000 --- a/integration-tests/deployment/ccip/deploy_test.go +++ /dev/null @@ -1,58 +0,0 @@ -package ccipdeployment - -import ( - "encoding/json" - "fmt" - "testing" - - "github.com/stretchr/testify/require" - "go.uber.org/zap/zapcore" - - "github.com/smartcontractkit/chainlink/integration-tests/deployment/memory" - - "github.com/smartcontractkit/chainlink/v2/core/logger" -) - -func TestDeployCCIPContracts(t *testing.T) { - lggr := logger.TestLogger(t) - e := memory.NewMemoryEnvironment(t, lggr, zapcore.InfoLevel, memory.MemoryEnvironmentConfig{ - Bootstraps: 1, - Chains: 1, - Nodes: 4, - }) - // Deploy all the CCIP contracts. - homeChain := e.AllChainSelectors()[0] - capRegAddresses, _, err := DeployCapReg(lggr, e.Chains, homeChain) - require.NoError(t, err) - s, err := LoadOnchainState(e, capRegAddresses) - require.NoError(t, err) - ab, err := DeployCCIPContracts(e, DeployCCIPContractConfig{ - HomeChainSel: homeChain, - CCIPOnChainState: s, - }) - require.NoError(t, err) - state, err := LoadOnchainState(e, ab) - require.NoError(t, err) - snap, err := state.Snapshot(e.AllChainSelectors()) - require.NoError(t, err) - - // Assert expect every deployed address to be in the address book. - // TODO (CCIP-3047): Add the rest of CCIPv2 representation - b, err := json.MarshalIndent(snap, "", " ") - require.NoError(t, err) - fmt.Println(string(b)) -} - -func TestJobSpecGeneration(t *testing.T) { - lggr := logger.TestLogger(t) - e := memory.NewMemoryEnvironment(t, lggr, zapcore.InfoLevel, memory.MemoryEnvironmentConfig{ - Chains: 1, - Nodes: 1, - }) - js, err := NewCCIPJobSpecs(e.NodeIDs, e.Offchain) - require.NoError(t, err) - for node, jb := range js { - fmt.Println(node, jb) - } - // TODO: Add job assertions -} diff --git a/integration-tests/deployment/ccip/jobs.go b/integration-tests/deployment/ccip/jobs.go deleted file mode 100644 index 923bda45f6..0000000000 --- a/integration-tests/deployment/ccip/jobs.go +++ /dev/null @@ -1,79 +0,0 @@ -package ccipdeployment - -import ( - "context" - "fmt" - - "github.com/smartcontractkit/chainlink/integration-tests/deployment" - nodev1 "github.com/smartcontractkit/chainlink/integration-tests/deployment/jd/node/v1" - "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/validate" - "github.com/smartcontractkit/chainlink/v2/core/services/relay" -) - -// In our case, the only address needed is the cap registry which is actually an env var. -// and will pre-exist for our deployment. So the job specs only depend on the environment operators. -func NewCCIPJobSpecs(nodeIds []string, oc deployment.OffchainClient) (map[string][]string, error) { - // Generate a set of brand new job specs for CCIP for a specific environment - // (including NOPs) and new addresses. - // We want to assign one CCIP capability job to each node. And node with - // an addr we'll list as bootstrapper. - // Find the bootstrap nodes - bootstrapMp := make(map[string]struct{}) - for _, node := range nodeIds { - // TODO: Filter should accept multiple nodes - nodeChainConfigs, err := oc.ListNodeChainConfigs(context.Background(), &nodev1.ListNodeChainConfigsRequest{Filter: &nodev1.ListNodeChainConfigsRequest_Filter{ - NodeId: node, - }}) - if err != nil { - return nil, err - } - for _, chainConfig := range nodeChainConfigs.ChainConfigs { - if chainConfig.Ocr2Config.IsBootstrap { - bootstrapMp[fmt.Sprintf("%s@%s", - // p2p_12D3... -> 12D3... - chainConfig.Ocr2Config.P2PKeyBundle.PeerId[4:], chainConfig.Ocr2Config.Multiaddr)] = struct{}{} - } - } - } - var bootstraps []string - for b := range bootstrapMp { - bootstraps = append(bootstraps, b) - } - nodesToJobSpecs := make(map[string][]string) - for _, node := range nodeIds { - // TODO: Filter should accept multiple. - nodeChainConfigs, err := oc.ListNodeChainConfigs(context.Background(), &nodev1.ListNodeChainConfigsRequest{Filter: &nodev1.ListNodeChainConfigsRequest_Filter{ - NodeId: node, - }}) - if err != nil { - return nil, err - } - - // only set P2PV2Bootstrappers in the job spec if the node is a plugin node. - var p2pV2Bootstrappers []string - for _, chainConfig := range nodeChainConfigs.ChainConfigs { - if !chainConfig.Ocr2Config.IsBootstrap { - p2pV2Bootstrappers = bootstraps - break - } - } - spec, err := validate.NewCCIPSpecToml(validate.SpecArgs{ - P2PV2Bootstrappers: p2pV2Bootstrappers, - CapabilityVersion: CapabilityVersion, - CapabilityLabelledName: CapabilityLabelledName, - OCRKeyBundleIDs: map[string]string{ - // TODO: Validate that that all EVM chains are using the same keybundle. - relay.NetworkEVM: nodeChainConfigs.ChainConfigs[0].Ocr2Config.OcrKeyBundle.BundleId, - }, - // TODO: validate that all EVM chains are using the same keybundle - P2PKeyID: nodeChainConfigs.ChainConfigs[0].Ocr2Config.P2PKeyBundle.PeerId, - RelayConfigs: nil, - PluginConfig: map[string]any{}, - }) - if err != nil { - return nil, err - } - nodesToJobSpecs[node] = append(nodesToJobSpecs[node], spec) - } - return nodesToJobSpecs, nil -} diff --git a/integration-tests/deployment/ccip/propose.go b/integration-tests/deployment/ccip/propose.go deleted file mode 100644 index 4fc38965ea..0000000000 --- a/integration-tests/deployment/ccip/propose.go +++ /dev/null @@ -1,64 +0,0 @@ -package ccipdeployment - -import ( - "math/big" - "time" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - owner_helpers "github.com/smartcontractkit/ccip-owner-contracts/gethwrappers" - chainsel "github.com/smartcontractkit/chain-selectors" - - "github.com/smartcontractkit/chainlink/integration-tests/deployment" -) - -// TODO: Pull up to deploy -func SimTransactOpts() *bind.TransactOpts { - return &bind.TransactOpts{Signer: func(address common.Address, transaction *types.Transaction) (*types.Transaction, error) { - return transaction, nil - }, From: common.HexToAddress("0x0"), NoSend: true, GasLimit: 200_000} -} - -func GenerateAcceptOwnershipProposal( - e deployment.Environment, - chains []uint64, - ab deployment.AddressBook, -) (deployment.Proposal, error) { - state, err := LoadOnchainState(e, ab) - if err != nil { - return deployment.Proposal{}, err - } - // TODO: Just onramp as an example - var ops []owner_helpers.ManyChainMultiSigOp - for _, sel := range chains { - opCount, err := state.Chains[sel].Mcm.GetOpCount(nil) - if err != nil { - return deployment.Proposal{}, err - } - - txData, err := state.Chains[sel].EvmOnRampV160.AcceptOwnership(SimTransactOpts()) - if err != nil { - return deployment.Proposal{}, err - } - evmID, err := chainsel.ChainIdFromSelector(sel) - if err != nil { - return deployment.Proposal{}, err - } - ops = append(ops, owner_helpers.ManyChainMultiSigOp{ - ChainId: big.NewInt(int64(evmID)), - MultiSig: state.Chains[sel].McmsAddr, - Nonce: opCount, - To: state.Chains[sel].EvmOnRampV160.Address(), - Value: big.NewInt(0), - Data: txData.Data(), - }) - } - // TODO: Real valid until. - return deployment.Proposal{ValidUntil: uint32(time.Now().Unix()), Ops: ops}, nil -} - -func ApplyProposal(env deployment.Environment, p deployment.Proposal, state CCIPOnChainState) error { - // TODO - return nil -} diff --git a/integration-tests/deployment/ccip/state.go b/integration-tests/deployment/ccip/state.go deleted file mode 100644 index f641d30ed4..0000000000 --- a/integration-tests/deployment/ccip/state.go +++ /dev/null @@ -1,276 +0,0 @@ -package ccipdeployment - -import ( - "fmt" - - "github.com/ethereum/go-ethereum/common" - "github.com/pkg/errors" - chainsel "github.com/smartcontractkit/chain-selectors" - - owner_wrappers "github.com/smartcontractkit/ccip-owner-contracts/gethwrappers" - - "github.com/smartcontractkit/chainlink/integration-tests/deployment" - - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/ccip_config" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/fee_quoter" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/maybe_revert_message_receiver" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/mock_rmn_contract" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/nonce_manager" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/offramp" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/onramp" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_proxy_contract" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/token_admin_registry" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/weth9" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/capabilities_registry" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/burn_mint_erc677" -) - -type CCIPChainState struct { - EvmOnRampV160 *onramp.OnRamp - EvmOffRampV160 *offramp.OffRamp - PriceRegistry *fee_quoter.FeeQuoter - ArmProxy *rmn_proxy_contract.RMNProxyContract - NonceManager *nonce_manager.NonceManager - TokenAdminRegistry *token_admin_registry.TokenAdminRegistry - Router *router.Router - Weth9 *weth9.WETH9 - MockRmn *mock_rmn_contract.MockRMNContract - // TODO: May need to support older link too - LinkToken *burn_mint_erc677.BurnMintERC677 - // Note we only expect one of these (on the home chain) - CapabilityRegistry *capabilities_registry.CapabilitiesRegistry - CCIPConfig *ccip_config.CCIPConfig - Mcm *owner_wrappers.ManyChainMultiSig - // TODO: remove once we have Address() on wrappers - McmsAddr common.Address - Timelock *owner_wrappers.RBACTimelock - - // Test contracts - Receiver *maybe_revert_message_receiver.MaybeRevertMessageReceiver -} - -// Onchain state always derivable from an address book. -// Offchain state always derivable from a list of nodeIds. -// Note can translate this into Go struct needed for MCMS/Docs/UI. -type CCIPOnChainState struct { - // Populated go bindings for the appropriate version for all contracts. - // We would hold 2 versions of each contract here. Once we upgrade we can phase out the old one. - // When generating bindings, make sure the package name corresponds to the version. - Chains map[uint64]CCIPChainState -} - -type CCIPSnapShot struct { - Chains map[string]Chain `json:"chains"` -} - -type Contract struct { - TypeAndVersion string `json:"typeAndVersion"` - Address common.Address `json:"address"` -} - -type TokenAdminRegistryView struct { - Contract - Tokens []common.Address `json:"tokens"` -} - -type NonceManagerView struct { - Contract - AuthorizedCallers []common.Address `json:"authorizedCallers"` -} - -type Chain struct { - // TODO: this will have to be versioned for getting state during upgrades. - TokenAdminRegistry TokenAdminRegistryView `json:"tokenAdminRegistry"` - NonceManager NonceManagerView `json:"nonceManager"` -} - -func (s CCIPOnChainState) Snapshot(chains []uint64) (CCIPSnapShot, error) { - snapshot := CCIPSnapShot{ - Chains: make(map[string]Chain), - } - for _, chainSelector := range chains { - // TODO: Need a utility for this - chainid, err := chainsel.ChainIdFromSelector(chainSelector) - if err != nil { - return snapshot, err - } - chainName, err := chainsel.NameFromChainId(chainid) - if err != nil { - return snapshot, err - } - if _, ok := s.Chains[chainSelector]; !ok { - return snapshot, fmt.Errorf("chain not supported %d", chainSelector) - } - var c Chain - ta := s.Chains[chainSelector].TokenAdminRegistry - if ta != nil { - tokens, err := ta.GetAllConfiguredTokens(nil, 0, 10) - if err != nil { - return snapshot, err - } - tv, err := ta.TypeAndVersion(nil) - if err != nil { - return snapshot, err - } - c.TokenAdminRegistry = TokenAdminRegistryView{ - Contract: Contract{ - TypeAndVersion: tv, - Address: ta.Address(), - }, - Tokens: tokens, - } - } - nm := s.Chains[chainSelector].NonceManager - if nm != nil { - authorizedCallers, err := nm.GetAllAuthorizedCallers(nil) - if err != nil { - return snapshot, err - } - tv, err := nm.TypeAndVersion(nil) - if err != nil { - return snapshot, err - } - c.NonceManager = NonceManagerView{ - Contract: Contract{ - TypeAndVersion: tv, - Address: nm.Address(), - }, - // TODO: these can be resolved using an address book - AuthorizedCallers: authorizedCallers, - } - } - snapshot.Chains[chainName] = c - } - return snapshot, nil -} - -func SnapshotState(e deployment.Environment, ab deployment.AddressBook) (CCIPSnapShot, error) { - state, err := LoadOnchainState(e, ab) - if err != nil { - return CCIPSnapShot{}, err - } - return state.Snapshot(e.AllChainSelectors()) -} - -func LoadOnchainState(e deployment.Environment, ab deployment.AddressBook) (CCIPOnChainState, error) { - 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) - if err != nil { - return state, err - } - state.Chains[chainSelector] = chainState - } - return state, nil -} - -// Loads all state for a chain into state -// Modifies map in place -func LoadChainState(chain deployment.Chain, addresses map[string]deployment.TypeAndVersion) (CCIPChainState, error) { - var state CCIPChainState - for address, tvStr := range addresses { - switch tvStr.String() { - case deployment.NewTypeAndVersion(RBACTimelock, deployment.Version1_0_0).String(): - tl, err := owner_wrappers.NewRBACTimelock(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - state.Timelock = tl - case deployment.NewTypeAndVersion(ManyChainMultisig, deployment.Version1_0_0).String(): - mcms, err := owner_wrappers.NewManyChainMultiSig(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - state.Mcm = mcms - state.McmsAddr = common.HexToAddress(address) - case deployment.NewTypeAndVersion(CapabilitiesRegistry, deployment.Version1_0_0).String(): - cr, err := capabilities_registry.NewCapabilitiesRegistry(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - state.CapabilityRegistry = cr - case deployment.NewTypeAndVersion(OnRamp, deployment.Version1_6_0_dev).String(): - onRampC, err := onramp.NewOnRamp(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - state.EvmOnRampV160 = onRampC - case deployment.NewTypeAndVersion(OffRamp, deployment.Version1_6_0_dev).String(): - offRamp, err := offramp.NewOffRamp(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - state.EvmOffRampV160 = offRamp - case deployment.NewTypeAndVersion(ARMProxy, deployment.Version1_0_0).String(): - armProxy, err := rmn_proxy_contract.NewRMNProxyContract(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - state.ArmProxy = armProxy - case deployment.NewTypeAndVersion(MockARM, deployment.Version1_0_0).String(): - mockARM, err := mock_rmn_contract.NewMockRMNContract(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - state.MockRmn = mockARM - case deployment.NewTypeAndVersion(WETH9, deployment.Version1_0_0).String(): - weth9, err := weth9.NewWETH9(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - state.Weth9 = weth9 - case deployment.NewTypeAndVersion(NonceManager, deployment.Version1_6_0_dev).String(): - nm, err := nonce_manager.NewNonceManager(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - state.NonceManager = nm - case deployment.NewTypeAndVersion(TokenAdminRegistry, deployment.Version1_5_0).String(): - tm, err := token_admin_registry.NewTokenAdminRegistry(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - state.TokenAdminRegistry = tm - case deployment.NewTypeAndVersion(Router, deployment.Version1_2_0).String(): - r, err := router.NewRouter(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - state.Router = r - case deployment.NewTypeAndVersion(PriceRegistry, deployment.Version1_6_0_dev).String(): - pr, err := fee_quoter.NewFeeQuoter(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - state.PriceRegistry = pr - case deployment.NewTypeAndVersion(LinkToken, deployment.Version1_0_0).String(): - lt, err := burn_mint_erc677.NewBurnMintERC677(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - state.LinkToken = lt - case deployment.NewTypeAndVersion(CCIPConfig, deployment.Version1_6_0_dev).String(): - cc, err := ccip_config.NewCCIPConfig(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - state.CCIPConfig = cc - case deployment.NewTypeAndVersion(CCIPReceiver, deployment.Version1_0_0).String(): - mr, err := maybe_revert_message_receiver.NewMaybeRevertMessageReceiver(common.HexToAddress(address), chain.Client) - if err != nil { - return state, err - } - state.Receiver = mr - default: - return state, fmt.Errorf("unknown contract %s", tvStr) - } - } - return state, nil -} diff --git a/integration-tests/deployment/ccip/test_helpers.go b/integration-tests/deployment/ccip/test_helpers.go deleted file mode 100644 index 2ec837c9ee..0000000000 --- a/integration-tests/deployment/ccip/test_helpers.go +++ /dev/null @@ -1,75 +0,0 @@ -package ccipdeployment - -import ( - "context" - "testing" - - chainsel "github.com/smartcontractkit/chain-selectors" - "github.com/stretchr/testify/require" - "go.uber.org/zap/zapcore" - - "github.com/smartcontractkit/chainlink/integration-tests/deployment" - "github.com/smartcontractkit/chainlink/integration-tests/deployment/memory" - - "github.com/smartcontractkit/chainlink-common/pkg/logger" -) - -// Context returns a context with the test's deadline, if available. -func Context(tb testing.TB) context.Context { - ctx := context.Background() - var cancel func() - switch t := tb.(type) { - case *testing.T: - if d, ok := t.Deadline(); ok { - ctx, cancel = context.WithDeadline(ctx, d) - } - } - if cancel == nil { - ctx, cancel = context.WithCancel(ctx) - } - tb.Cleanup(cancel) - return ctx -} - -type DeployedTestEnvironment struct { - Ab deployment.AddressBook - Env deployment.Environment - HomeChainSel uint64 - Nodes map[string]memory.Node -} - -// NewDeployedEnvironment creates a new CCIP environment -// with capreg and nodes set up. -func NewDeployedTestEnvironment(t *testing.T, lggr logger.Logger) DeployedTestEnvironment { - ctx := Context(t) - chains := memory.NewMemoryChains(t, 3) - homeChainSel := uint64(0) - homeChainEVM := uint64(0) - // Say first chain is home chain. - for chainSel := range chains { - homeChainEVM, _ = chainsel.ChainIdFromSelector(chainSel) - homeChainSel = chainSel - break - } - ab, capReg, err := DeployCapReg(lggr, chains, homeChainSel) - require.NoError(t, err) - - nodes := memory.NewNodes(t, zapcore.InfoLevel, chains, 4, 1, memory.RegistryConfig{ - EVMChainID: homeChainEVM, - Contract: capReg, - }) - for _, node := range nodes { - require.NoError(t, node.App.Start(ctx)) - t.Cleanup(func() { - require.NoError(t, node.App.Stop()) - }) - } - - e := memory.NewMemoryEnvironmentFromChainsNodes(t, lggr, chains, nodes) - return DeployedTestEnvironment{ - Ab: ab, - Env: e, - HomeChainSel: homeChainSel, - Nodes: nodes, - } -} diff --git a/integration-tests/deployment/changeset.go b/integration-tests/deployment/changeset.go deleted file mode 100644 index d929022ed9..0000000000 --- a/integration-tests/deployment/changeset.go +++ /dev/null @@ -1,28 +0,0 @@ -package deployment - -import ( - owner_wrappers "github.com/smartcontractkit/ccip-owner-contracts/gethwrappers" -) - -// TODO: Move to real MCM structs once available. -type Proposal struct { - // keccak256(abi.encode(root, validUntil)) is what is signed by MCMS - // signers. - ValidUntil uint32 - // Leaves are the items in the proposal. - // Uses these to generate the root as well as display whats in the root. - // These Ops may be destined for distinct chains. - Ops []owner_wrappers.ManyChainMultiSigOp -} - -func (p Proposal) String() string { - // TODO - return "" -} - -// Services as input to CI/Async tasks -type ChangesetOutput struct { - JobSpecs map[string][]string - Proposals []Proposal - AddressBook AddressBook -} diff --git a/integration-tests/deployment/environment.go b/integration-tests/deployment/environment.go deleted file mode 100644 index 7d8fb6e631..0000000000 --- a/integration-tests/deployment/environment.go +++ /dev/null @@ -1,195 +0,0 @@ -package deployment - -import ( - "context" - "errors" - "fmt" - "math/big" - "strconv" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/rpc" - chain_selectors "github.com/smartcontractkit/chain-selectors" - types2 "github.com/smartcontractkit/libocr/offchainreporting2/types" - types3 "github.com/smartcontractkit/libocr/offchainreporting2plus/types" - - jobv1 "github.com/smartcontractkit/chainlink/integration-tests/deployment/jd/job/v1" - nodev1 "github.com/smartcontractkit/chainlink/integration-tests/deployment/jd/node/v1" - "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" - - "github.com/smartcontractkit/chainlink-common/pkg/logger" -) - -type OnchainClient interface { - // For EVM specifically we can use existing geth interface - // to abstract chain clients. - bind.ContractBackend -} - -type OffchainClient interface { - // The job distributor grpc interface can be used to abstract offchain read/writes - jobv1.JobServiceClient - nodev1.NodeServiceClient -} - -type Chain struct { - // Selectors used as canonical chain identifier. - Selector uint64 - Client OnchainClient - // Note the Sign function can be abstract supporting a variety of key storage mechanisms (e.g. KMS etc). - DeployerKey *bind.TransactOpts - Confirm func(tx common.Hash) error -} - -type Environment struct { - Name string - Chains map[uint64]Chain - Offchain OffchainClient - NodeIDs []string - Logger logger.Logger -} - -func (e Environment) AllChainSelectors() []uint64 { - var selectors []uint64 - for sel := range e.Chains { - selectors = append(selectors, sel) - } - return selectors -} - -func ConfirmIfNoError(chain Chain, tx *types.Transaction, err error) error { - if err != nil { - //revive:disable - var d rpc.DataError - ok := errors.As(err, &d) - if ok { - return fmt.Errorf("got Data Error: %s", d.ErrorData()) - } - return err - } - return chain.Confirm(tx.Hash()) -} - -func MaybeDataErr(err error) error { - //revive:disable - var d rpc.DataError - ok := errors.As(err, &d) - if ok { - return d - } - return err -} - -func UBigInt(i uint64) *big.Int { - return new(big.Int).SetUint64(i) -} - -func E18Mult(amount uint64) *big.Int { - return new(big.Int).Mul(UBigInt(amount), UBigInt(1e18)) -} - -type OCRConfig struct { - OffchainPublicKey types2.OffchainPublicKey - // For EVM-chains, this an *address*. - OnchainPublicKey types2.OnchainPublicKey - PeerID p2pkey.PeerID - TransmitAccount types2.Account - ConfigEncryptionPublicKey types3.ConfigEncryptionPublicKey - IsBootstrap bool - MultiAddr string // TODO: type -} - -type Nodes []Node - -func (n Nodes) PeerIDs(chainSel uint64) [][32]byte { - var peerIDs [][32]byte - for _, node := range n { - cfg := node.SelToOCRConfig[chainSel] - // NOTE: Assume same peerID for all chains. - // Might make sense to change proto as peerID is 1-1 with node? - peerIDs = append(peerIDs, cfg.PeerID) - } - return peerIDs -} - -func (n Nodes) BootstrapPeerIDs(chainSel uint64) [][32]byte { - var peerIDs [][32]byte - for _, node := range n { - cfg := node.SelToOCRConfig[chainSel] - if !cfg.IsBootstrap { - continue - } - peerIDs = append(peerIDs, cfg.PeerID) - } - return peerIDs -} - -// OffchainPublicKey types.OffchainPublicKey -// // For EVM-chains, this an *address*. -// OnchainPublicKey types.OnchainPublicKey -// PeerID string -// TransmitAccount types.Account -type Node struct { - SelToOCRConfig map[uint64]OCRConfig -} - -func MustPeerIDFromString(s string) p2pkey.PeerID { - p := p2pkey.PeerID{} - if err := p.UnmarshalString(s); err != nil { - panic(err) - } - return p -} - -// Gathers all the node info through JD required to be able to set -// OCR config for example. -func NodeInfo(nodeIDs []string, oc OffchainClient) (Nodes, error) { - var nodes []Node - for _, node := range nodeIDs { - // TODO: Filter should accept multiple nodes - nodeChainConfigs, err := oc.ListNodeChainConfigs(context.Background(), &nodev1.ListNodeChainConfigsRequest{Filter: &nodev1.ListNodeChainConfigsRequest_Filter{ - NodeId: node, - }}) - if err != nil { - return nil, err - } - selToOCRConfig := make(map[uint64]OCRConfig) - for _, chainConfig := range nodeChainConfigs.ChainConfigs { - if chainConfig.Chain.Type == nodev1.ChainType_CHAIN_TYPE_SOLANA { - // Note supported for CCIP yet. - continue - } - evmChainID, err := strconv.Atoi(chainConfig.Chain.Id) - if err != nil { - return nil, err - } - sel, err := chain_selectors.SelectorFromChainId(uint64(evmChainID)) - if err != nil { - return nil, err - } - b := common.Hex2Bytes(chainConfig.Ocr2Config.OcrKeyBundle.OffchainPublicKey) - var opk types2.OffchainPublicKey - copy(opk[:], b) - - b = common.Hex2Bytes(chainConfig.Ocr2Config.OcrKeyBundle.ConfigPublicKey) - var cpk types3.ConfigEncryptionPublicKey - copy(cpk[:], b) - - selToOCRConfig[sel] = OCRConfig{ - OffchainPublicKey: opk, - OnchainPublicKey: common.HexToAddress(chainConfig.Ocr2Config.OcrKeyBundle.OnchainSigningAddress).Bytes(), - PeerID: MustPeerIDFromString(chainConfig.Ocr2Config.P2PKeyBundle.PeerId), - TransmitAccount: types2.Account(chainConfig.AccountAddress), - ConfigEncryptionPublicKey: cpk, - IsBootstrap: chainConfig.Ocr2Config.IsBootstrap, - MultiAddr: chainConfig.Ocr2Config.Multiaddr, - } - } - nodes = append(nodes, Node{ - SelToOCRConfig: selToOCRConfig, - }) - } - return nodes, nil -} diff --git a/integration-tests/deployment/jd/job/v1/job.pb.go b/integration-tests/deployment/jd/job/v1/job.pb.go deleted file mode 100644 index deaf1ccf30..0000000000 --- a/integration-tests/deployment/jd/job/v1/job.pb.go +++ /dev/null @@ -1,1767 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.29.0 -// protoc v4.25.3 -// source: job/v1/job.proto - -package v1 - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - timestamppb "google.golang.org/protobuf/types/known/timestamppb" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// ProposalStatus defines the possible states of a job proposal. -type ProposalStatus int32 - -const ( - ProposalStatus_PROPOSAL_STATUS_UNSPECIFIED ProposalStatus = 0 - ProposalStatus_PROPOSAL_STATUS_PROPOSED ProposalStatus = 1 // Proposal has been made but not yet decided upon. - ProposalStatus_PROPOSAL_STATUS_APPROVED ProposalStatus = 2 // Proposal has been accepted. - ProposalStatus_PROPOSAL_STATUS_REJECTED ProposalStatus = 3 // Proposal has been rejected. - ProposalStatus_PROPOSAL_STATUS_CANCELLED ProposalStatus = 4 // Proposal has been cancelled. - ProposalStatus_PROPOSAL_STATUS_PENDING ProposalStatus = 5 // Proposal is pending review. - ProposalStatus_PROPOSAL_STATUS_REVOKED ProposalStatus = 6 // Proposal has been revoked after being proposed. -) - -// Enum value maps for ProposalStatus. -var ( - ProposalStatus_name = map[int32]string{ - 0: "PROPOSAL_STATUS_UNSPECIFIED", - 1: "PROPOSAL_STATUS_PROPOSED", - 2: "PROPOSAL_STATUS_APPROVED", - 3: "PROPOSAL_STATUS_REJECTED", - 4: "PROPOSAL_STATUS_CANCELLED", - 5: "PROPOSAL_STATUS_PENDING", - 6: "PROPOSAL_STATUS_REVOKED", - } - ProposalStatus_value = map[string]int32{ - "PROPOSAL_STATUS_UNSPECIFIED": 0, - "PROPOSAL_STATUS_PROPOSED": 1, - "PROPOSAL_STATUS_APPROVED": 2, - "PROPOSAL_STATUS_REJECTED": 3, - "PROPOSAL_STATUS_CANCELLED": 4, - "PROPOSAL_STATUS_PENDING": 5, - "PROPOSAL_STATUS_REVOKED": 6, - } -) - -func (x ProposalStatus) Enum() *ProposalStatus { - p := new(ProposalStatus) - *p = x - return p -} - -func (x ProposalStatus) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (ProposalStatus) Descriptor() protoreflect.EnumDescriptor { - return file_job_v1_job_proto_enumTypes[0].Descriptor() -} - -func (ProposalStatus) Type() protoreflect.EnumType { - return &file_job_v1_job_proto_enumTypes[0] -} - -func (x ProposalStatus) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use ProposalStatus.Descriptor instead. -func (ProposalStatus) EnumDescriptor() ([]byte, []int) { - return file_job_v1_job_proto_rawDescGZIP(), []int{0} -} - -// ProposalDeliveryStatus defines the delivery status of the proposal to the node. -type ProposalDeliveryStatus int32 - -const ( - ProposalDeliveryStatus_PROPOSAL_DELIVERY_STATUS_UNSPECIFIED ProposalDeliveryStatus = 0 - ProposalDeliveryStatus_PROPOSAL_DELIVERY_STATUS_DELIVERED ProposalDeliveryStatus = 1 // Delivered to the node. - ProposalDeliveryStatus_PROPOSAL_DELIVERY_STATUS_ACKNOWLEDGED ProposalDeliveryStatus = 2 // Acknowledged by the node. - ProposalDeliveryStatus_PROPOSAL_DELIVERY_STATUS_FAILED ProposalDeliveryStatus = 3 // Delivery failed. -) - -// Enum value maps for ProposalDeliveryStatus. -var ( - ProposalDeliveryStatus_name = map[int32]string{ - 0: "PROPOSAL_DELIVERY_STATUS_UNSPECIFIED", - 1: "PROPOSAL_DELIVERY_STATUS_DELIVERED", - 2: "PROPOSAL_DELIVERY_STATUS_ACKNOWLEDGED", - 3: "PROPOSAL_DELIVERY_STATUS_FAILED", - } - ProposalDeliveryStatus_value = map[string]int32{ - "PROPOSAL_DELIVERY_STATUS_UNSPECIFIED": 0, - "PROPOSAL_DELIVERY_STATUS_DELIVERED": 1, - "PROPOSAL_DELIVERY_STATUS_ACKNOWLEDGED": 2, - "PROPOSAL_DELIVERY_STATUS_FAILED": 3, - } -) - -func (x ProposalDeliveryStatus) Enum() *ProposalDeliveryStatus { - p := new(ProposalDeliveryStatus) - *p = x - return p -} - -func (x ProposalDeliveryStatus) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (ProposalDeliveryStatus) Descriptor() protoreflect.EnumDescriptor { - return file_job_v1_job_proto_enumTypes[1].Descriptor() -} - -func (ProposalDeliveryStatus) Type() protoreflect.EnumType { - return &file_job_v1_job_proto_enumTypes[1] -} - -func (x ProposalDeliveryStatus) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use ProposalDeliveryStatus.Descriptor instead. -func (ProposalDeliveryStatus) EnumDescriptor() ([]byte, []int) { - return file_job_v1_job_proto_rawDescGZIP(), []int{1} -} - -// Job represents the structured data of a job within the system. -type Job struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` // Unique identifier for the job. - Uuid string `protobuf:"bytes,2,opt,name=uuid,proto3" json:"uuid,omitempty"` // Universally unique identifier for the job. - NodeId string `protobuf:"bytes,3,opt,name=node_id,json=nodeId,proto3" json:"node_id,omitempty"` // ID of the node associated with this job. - ProposalIds []string `protobuf:"bytes,4,rep,name=proposal_ids,json=proposalIds,proto3" json:"proposal_ids,omitempty"` // List of proposal IDs associated with this job. - CreatedAt *timestamppb.Timestamp `protobuf:"bytes,5,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"` // Timestamp when the job was created. - UpdatedAt *timestamppb.Timestamp `protobuf:"bytes,6,opt,name=updated_at,json=updatedAt,proto3" json:"updated_at,omitempty"` // Timestamp when the job was last updated. - DeletedAt *timestamppb.Timestamp `protobuf:"bytes,7,opt,name=deleted_at,json=deletedAt,proto3" json:"deleted_at,omitempty"` // Timestamp when the job was deleted, if applicable. -} - -func (x *Job) Reset() { - *x = Job{} - if protoimpl.UnsafeEnabled { - mi := &file_job_v1_job_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Job) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Job) ProtoMessage() {} - -func (x *Job) ProtoReflect() protoreflect.Message { - mi := &file_job_v1_job_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Job.ProtoReflect.Descriptor instead. -func (*Job) Descriptor() ([]byte, []int) { - return file_job_v1_job_proto_rawDescGZIP(), []int{0} -} - -func (x *Job) GetId() string { - if x != nil { - return x.Id - } - return "" -} - -func (x *Job) GetUuid() string { - if x != nil { - return x.Uuid - } - return "" -} - -func (x *Job) GetNodeId() string { - if x != nil { - return x.NodeId - } - return "" -} - -func (x *Job) GetProposalIds() []string { - if x != nil { - return x.ProposalIds - } - return nil -} - -func (x *Job) GetCreatedAt() *timestamppb.Timestamp { - if x != nil { - return x.CreatedAt - } - return nil -} - -func (x *Job) GetUpdatedAt() *timestamppb.Timestamp { - if x != nil { - return x.UpdatedAt - } - return nil -} - -func (x *Job) GetDeletedAt() *timestamppb.Timestamp { - if x != nil { - return x.DeletedAt - } - return nil -} - -// Proposal represents a job proposal. -type Proposal struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` // Unique identifier for the proposal. - Version int64 `protobuf:"varint,2,opt,name=version,proto3" json:"version,omitempty"` // Version number of the proposal. - Status ProposalStatus `protobuf:"varint,3,opt,name=status,proto3,enum=api.job.v1.ProposalStatus" json:"status,omitempty"` // Current status of the proposal. - DeliveryStatus ProposalDeliveryStatus `protobuf:"varint,4,opt,name=delivery_status,json=deliveryStatus,proto3,enum=api.job.v1.ProposalDeliveryStatus" json:"delivery_status,omitempty"` // Delivery status of the proposal. - Spec string `protobuf:"bytes,5,opt,name=spec,proto3" json:"spec,omitempty"` // Specification of the job proposed. - JobId string `protobuf:"bytes,6,opt,name=job_id,json=jobId,proto3" json:"job_id,omitempty"` // ID of the job associated with this proposal. - CreatedAt *timestamppb.Timestamp `protobuf:"bytes,7,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"` // Timestamp when the proposal was created. - UpdatedAt *timestamppb.Timestamp `protobuf:"bytes,8,opt,name=updated_at,json=updatedAt,proto3" json:"updated_at,omitempty"` // Timestamp when the proposal was last updated. - AckedAt *timestamppb.Timestamp `protobuf:"bytes,9,opt,name=acked_at,json=ackedAt,proto3,oneof" json:"acked_at,omitempty"` // Timestamp when the proposal was acknowledged. - ResponseReceivedAt *timestamppb.Timestamp `protobuf:"bytes,10,opt,name=response_received_at,json=responseReceivedAt,proto3,oneof" json:"response_received_at,omitempty"` // Timestamp when a response was received. -} - -func (x *Proposal) Reset() { - *x = Proposal{} - if protoimpl.UnsafeEnabled { - mi := &file_job_v1_job_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Proposal) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Proposal) ProtoMessage() {} - -func (x *Proposal) ProtoReflect() protoreflect.Message { - mi := &file_job_v1_job_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Proposal.ProtoReflect.Descriptor instead. -func (*Proposal) Descriptor() ([]byte, []int) { - return file_job_v1_job_proto_rawDescGZIP(), []int{1} -} - -func (x *Proposal) GetId() string { - if x != nil { - return x.Id - } - return "" -} - -func (x *Proposal) GetVersion() int64 { - if x != nil { - return x.Version - } - return 0 -} - -func (x *Proposal) GetStatus() ProposalStatus { - if x != nil { - return x.Status - } - return ProposalStatus_PROPOSAL_STATUS_UNSPECIFIED -} - -func (x *Proposal) GetDeliveryStatus() ProposalDeliveryStatus { - if x != nil { - return x.DeliveryStatus - } - return ProposalDeliveryStatus_PROPOSAL_DELIVERY_STATUS_UNSPECIFIED -} - -func (x *Proposal) GetSpec() string { - if x != nil { - return x.Spec - } - return "" -} - -func (x *Proposal) GetJobId() string { - if x != nil { - return x.JobId - } - return "" -} - -func (x *Proposal) GetCreatedAt() *timestamppb.Timestamp { - if x != nil { - return x.CreatedAt - } - return nil -} - -func (x *Proposal) GetUpdatedAt() *timestamppb.Timestamp { - if x != nil { - return x.UpdatedAt - } - return nil -} - -func (x *Proposal) GetAckedAt() *timestamppb.Timestamp { - if x != nil { - return x.AckedAt - } - return nil -} - -func (x *Proposal) GetResponseReceivedAt() *timestamppb.Timestamp { - if x != nil { - return x.ResponseReceivedAt - } - return nil -} - -// GetJobRequest specifies the criteria for retrieving a job. -type GetJobRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Types that are assignable to IdOneof: - // - // *GetJobRequest_Id - // *GetJobRequest_Uuid - IdOneof isGetJobRequest_IdOneof `protobuf_oneof:"id_oneof"` -} - -func (x *GetJobRequest) Reset() { - *x = GetJobRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_job_v1_job_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetJobRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetJobRequest) ProtoMessage() {} - -func (x *GetJobRequest) ProtoReflect() protoreflect.Message { - mi := &file_job_v1_job_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetJobRequest.ProtoReflect.Descriptor instead. -func (*GetJobRequest) Descriptor() ([]byte, []int) { - return file_job_v1_job_proto_rawDescGZIP(), []int{2} -} - -func (m *GetJobRequest) GetIdOneof() isGetJobRequest_IdOneof { - if m != nil { - return m.IdOneof - } - return nil -} - -func (x *GetJobRequest) GetId() string { - if x, ok := x.GetIdOneof().(*GetJobRequest_Id); ok { - return x.Id - } - return "" -} - -func (x *GetJobRequest) GetUuid() string { - if x, ok := x.GetIdOneof().(*GetJobRequest_Uuid); ok { - return x.Uuid - } - return "" -} - -type isGetJobRequest_IdOneof interface { - isGetJobRequest_IdOneof() -} - -type GetJobRequest_Id struct { - Id string `protobuf:"bytes,1,opt,name=id,proto3,oneof"` // Unique identifier of the job. -} - -type GetJobRequest_Uuid struct { - Uuid string `protobuf:"bytes,2,opt,name=uuid,proto3,oneof"` // Universally unique identifier of the job. -} - -func (*GetJobRequest_Id) isGetJobRequest_IdOneof() {} - -func (*GetJobRequest_Uuid) isGetJobRequest_IdOneof() {} - -// GetJobResponse contains the job details. -type GetJobResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Job *Job `protobuf:"bytes,1,opt,name=job,proto3" json:"job,omitempty"` // Details of the retrieved job. -} - -func (x *GetJobResponse) Reset() { - *x = GetJobResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_job_v1_job_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetJobResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetJobResponse) ProtoMessage() {} - -func (x *GetJobResponse) ProtoReflect() protoreflect.Message { - mi := &file_job_v1_job_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetJobResponse.ProtoReflect.Descriptor instead. -func (*GetJobResponse) Descriptor() ([]byte, []int) { - return file_job_v1_job_proto_rawDescGZIP(), []int{3} -} - -func (x *GetJobResponse) GetJob() *Job { - if x != nil { - return x.Job - } - return nil -} - -// GetProposalRequest specifies the criteria for retrieving a proposal. -type GetProposalRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` // Unique identifier of the proposal to retrieve. -} - -func (x *GetProposalRequest) Reset() { - *x = GetProposalRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_job_v1_job_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetProposalRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetProposalRequest) ProtoMessage() {} - -func (x *GetProposalRequest) ProtoReflect() protoreflect.Message { - mi := &file_job_v1_job_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetProposalRequest.ProtoReflect.Descriptor instead. -func (*GetProposalRequest) Descriptor() ([]byte, []int) { - return file_job_v1_job_proto_rawDescGZIP(), []int{4} -} - -func (x *GetProposalRequest) GetId() string { - if x != nil { - return x.Id - } - return "" -} - -// GetProposalResponse contains the proposal details. -type GetProposalResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Proposal *Proposal `protobuf:"bytes,1,opt,name=proposal,proto3" json:"proposal,omitempty"` // Details of the retrieved proposal. -} - -func (x *GetProposalResponse) Reset() { - *x = GetProposalResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_job_v1_job_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetProposalResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetProposalResponse) ProtoMessage() {} - -func (x *GetProposalResponse) ProtoReflect() protoreflect.Message { - mi := &file_job_v1_job_proto_msgTypes[5] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetProposalResponse.ProtoReflect.Descriptor instead. -func (*GetProposalResponse) Descriptor() ([]byte, []int) { - return file_job_v1_job_proto_rawDescGZIP(), []int{5} -} - -func (x *GetProposalResponse) GetProposal() *Proposal { - if x != nil { - return x.Proposal - } - return nil -} - -// ListJobsRequest specifies filters for listing jobs. -type ListJobsRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Filter *ListJobsRequest_Filter `protobuf:"bytes,1,opt,name=filter,proto3" json:"filter,omitempty"` // Filters applied to the job listing. -} - -func (x *ListJobsRequest) Reset() { - *x = ListJobsRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_job_v1_job_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ListJobsRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ListJobsRequest) ProtoMessage() {} - -func (x *ListJobsRequest) ProtoReflect() protoreflect.Message { - mi := &file_job_v1_job_proto_msgTypes[6] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ListJobsRequest.ProtoReflect.Descriptor instead. -func (*ListJobsRequest) Descriptor() ([]byte, []int) { - return file_job_v1_job_proto_rawDescGZIP(), []int{6} -} - -func (x *ListJobsRequest) GetFilter() *ListJobsRequest_Filter { - if x != nil { - return x.Filter - } - return nil -} - -// ListJobsResponse contains a list of jobs that match the filters. -type ListJobsResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Jobs []*Job `protobuf:"bytes,1,rep,name=jobs,proto3" json:"jobs,omitempty"` // List of jobs. -} - -func (x *ListJobsResponse) Reset() { - *x = ListJobsResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_job_v1_job_proto_msgTypes[7] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ListJobsResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ListJobsResponse) ProtoMessage() {} - -func (x *ListJobsResponse) ProtoReflect() protoreflect.Message { - mi := &file_job_v1_job_proto_msgTypes[7] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ListJobsResponse.ProtoReflect.Descriptor instead. -func (*ListJobsResponse) Descriptor() ([]byte, []int) { - return file_job_v1_job_proto_rawDescGZIP(), []int{7} -} - -func (x *ListJobsResponse) GetJobs() []*Job { - if x != nil { - return x.Jobs - } - return nil -} - -// ListProposalsRequest specifies filters for listing proposals. -type ListProposalsRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Filter *ListProposalsRequest_Filter `protobuf:"bytes,1,opt,name=filter,proto3" json:"filter,omitempty"` // Filters applied to the proposal listing. -} - -func (x *ListProposalsRequest) Reset() { - *x = ListProposalsRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_job_v1_job_proto_msgTypes[8] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ListProposalsRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ListProposalsRequest) ProtoMessage() {} - -func (x *ListProposalsRequest) ProtoReflect() protoreflect.Message { - mi := &file_job_v1_job_proto_msgTypes[8] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ListProposalsRequest.ProtoReflect.Descriptor instead. -func (*ListProposalsRequest) Descriptor() ([]byte, []int) { - return file_job_v1_job_proto_rawDescGZIP(), []int{8} -} - -func (x *ListProposalsRequest) GetFilter() *ListProposalsRequest_Filter { - if x != nil { - return x.Filter - } - return nil -} - -// ListProposalsResponse contains a list of proposals that match the filters. -type ListProposalsResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Proposals []*Proposal `protobuf:"bytes,1,rep,name=proposals,proto3" json:"proposals,omitempty"` // List of proposals. -} - -func (x *ListProposalsResponse) Reset() { - *x = ListProposalsResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_job_v1_job_proto_msgTypes[9] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ListProposalsResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ListProposalsResponse) ProtoMessage() {} - -func (x *ListProposalsResponse) ProtoReflect() protoreflect.Message { - mi := &file_job_v1_job_proto_msgTypes[9] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ListProposalsResponse.ProtoReflect.Descriptor instead. -func (*ListProposalsResponse) Descriptor() ([]byte, []int) { - return file_job_v1_job_proto_rawDescGZIP(), []int{9} -} - -func (x *ListProposalsResponse) GetProposals() []*Proposal { - if x != nil { - return x.Proposals - } - return nil -} - -// ProposeJobRequest contains the information needed to submit a new job proposal. -type ProposeJobRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - NodeId string `protobuf:"bytes,1,opt,name=node_id,json=nodeId,proto3" json:"node_id,omitempty"` // ID of the node to which the job is proposed. - Spec string `protobuf:"bytes,2,opt,name=spec,proto3" json:"spec,omitempty"` // Specification of the job being proposed. -} - -func (x *ProposeJobRequest) Reset() { - *x = ProposeJobRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_job_v1_job_proto_msgTypes[10] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ProposeJobRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ProposeJobRequest) ProtoMessage() {} - -func (x *ProposeJobRequest) ProtoReflect() protoreflect.Message { - mi := &file_job_v1_job_proto_msgTypes[10] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ProposeJobRequest.ProtoReflect.Descriptor instead. -func (*ProposeJobRequest) Descriptor() ([]byte, []int) { - return file_job_v1_job_proto_rawDescGZIP(), []int{10} -} - -func (x *ProposeJobRequest) GetNodeId() string { - if x != nil { - return x.NodeId - } - return "" -} - -func (x *ProposeJobRequest) GetSpec() string { - if x != nil { - return x.Spec - } - return "" -} - -// ProposeJobResponse returns the newly created proposal. -type ProposeJobResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Proposal *Proposal `protobuf:"bytes,1,opt,name=proposal,proto3" json:"proposal,omitempty"` // Details of the newly created proposal. -} - -func (x *ProposeJobResponse) Reset() { - *x = ProposeJobResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_job_v1_job_proto_msgTypes[11] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ProposeJobResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ProposeJobResponse) ProtoMessage() {} - -func (x *ProposeJobResponse) ProtoReflect() protoreflect.Message { - mi := &file_job_v1_job_proto_msgTypes[11] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ProposeJobResponse.ProtoReflect.Descriptor instead. -func (*ProposeJobResponse) Descriptor() ([]byte, []int) { - return file_job_v1_job_proto_rawDescGZIP(), []int{11} -} - -func (x *ProposeJobResponse) GetProposal() *Proposal { - if x != nil { - return x.Proposal - } - return nil -} - -// RevokeJobRequest specifies the criteria for revoking a job proposal. -type RevokeJobRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Types that are assignable to IdOneof: - // - // *RevokeJobRequest_Id - // *RevokeJobRequest_Uuid - IdOneof isRevokeJobRequest_IdOneof `protobuf_oneof:"id_oneof"` -} - -func (x *RevokeJobRequest) Reset() { - *x = RevokeJobRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_job_v1_job_proto_msgTypes[12] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *RevokeJobRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RevokeJobRequest) ProtoMessage() {} - -func (x *RevokeJobRequest) ProtoReflect() protoreflect.Message { - mi := &file_job_v1_job_proto_msgTypes[12] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use RevokeJobRequest.ProtoReflect.Descriptor instead. -func (*RevokeJobRequest) Descriptor() ([]byte, []int) { - return file_job_v1_job_proto_rawDescGZIP(), []int{12} -} - -func (m *RevokeJobRequest) GetIdOneof() isRevokeJobRequest_IdOneof { - if m != nil { - return m.IdOneof - } - return nil -} - -func (x *RevokeJobRequest) GetId() string { - if x, ok := x.GetIdOneof().(*RevokeJobRequest_Id); ok { - return x.Id - } - return "" -} - -func (x *RevokeJobRequest) GetUuid() string { - if x, ok := x.GetIdOneof().(*RevokeJobRequest_Uuid); ok { - return x.Uuid - } - return "" -} - -type isRevokeJobRequest_IdOneof interface { - isRevokeJobRequest_IdOneof() -} - -type RevokeJobRequest_Id struct { - Id string `protobuf:"bytes,1,opt,name=id,proto3,oneof"` // Unique identifier of the proposal to revoke. -} - -type RevokeJobRequest_Uuid struct { - Uuid string `protobuf:"bytes,2,opt,name=uuid,proto3,oneof"` // Universally unique identifier of the proposal to revoke. -} - -func (*RevokeJobRequest_Id) isRevokeJobRequest_IdOneof() {} - -func (*RevokeJobRequest_Uuid) isRevokeJobRequest_IdOneof() {} - -// RevokeJobResponse returns the revoked proposal. -type RevokeJobResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Proposal *Proposal `protobuf:"bytes,1,opt,name=proposal,proto3" json:"proposal,omitempty"` // Details of the revoked proposal. -} - -func (x *RevokeJobResponse) Reset() { - *x = RevokeJobResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_job_v1_job_proto_msgTypes[13] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *RevokeJobResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RevokeJobResponse) ProtoMessage() {} - -func (x *RevokeJobResponse) ProtoReflect() protoreflect.Message { - mi := &file_job_v1_job_proto_msgTypes[13] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use RevokeJobResponse.ProtoReflect.Descriptor instead. -func (*RevokeJobResponse) Descriptor() ([]byte, []int) { - return file_job_v1_job_proto_rawDescGZIP(), []int{13} -} - -func (x *RevokeJobResponse) GetProposal() *Proposal { - if x != nil { - return x.Proposal - } - return nil -} - -// DeleteJobRequest specifies the criteria for deleting a job. -type DeleteJobRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Types that are assignable to IdOneof: - // - // *DeleteJobRequest_Id - // *DeleteJobRequest_Uuid - IdOneof isDeleteJobRequest_IdOneof `protobuf_oneof:"id_oneof"` -} - -func (x *DeleteJobRequest) Reset() { - *x = DeleteJobRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_job_v1_job_proto_msgTypes[14] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DeleteJobRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DeleteJobRequest) ProtoMessage() {} - -func (x *DeleteJobRequest) ProtoReflect() protoreflect.Message { - mi := &file_job_v1_job_proto_msgTypes[14] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use DeleteJobRequest.ProtoReflect.Descriptor instead. -func (*DeleteJobRequest) Descriptor() ([]byte, []int) { - return file_job_v1_job_proto_rawDescGZIP(), []int{14} -} - -func (m *DeleteJobRequest) GetIdOneof() isDeleteJobRequest_IdOneof { - if m != nil { - return m.IdOneof - } - return nil -} - -func (x *DeleteJobRequest) GetId() string { - if x, ok := x.GetIdOneof().(*DeleteJobRequest_Id); ok { - return x.Id - } - return "" -} - -func (x *DeleteJobRequest) GetUuid() string { - if x, ok := x.GetIdOneof().(*DeleteJobRequest_Uuid); ok { - return x.Uuid - } - return "" -} - -type isDeleteJobRequest_IdOneof interface { - isDeleteJobRequest_IdOneof() -} - -type DeleteJobRequest_Id struct { - Id string `protobuf:"bytes,1,opt,name=id,proto3,oneof"` // Unique identifier of the job to delete. -} - -type DeleteJobRequest_Uuid struct { - Uuid string `protobuf:"bytes,2,opt,name=uuid,proto3,oneof"` // Universally unique identifier of the job to delete. -} - -func (*DeleteJobRequest_Id) isDeleteJobRequest_IdOneof() {} - -func (*DeleteJobRequest_Uuid) isDeleteJobRequest_IdOneof() {} - -// DeleteJobResponse returns details of the deleted job. -type DeleteJobResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Job *Job `protobuf:"bytes,1,opt,name=job,proto3" json:"job,omitempty"` // Details of the deleted job. -} - -func (x *DeleteJobResponse) Reset() { - *x = DeleteJobResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_job_v1_job_proto_msgTypes[15] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *DeleteJobResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*DeleteJobResponse) ProtoMessage() {} - -func (x *DeleteJobResponse) ProtoReflect() protoreflect.Message { - mi := &file_job_v1_job_proto_msgTypes[15] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use DeleteJobResponse.ProtoReflect.Descriptor instead. -func (*DeleteJobResponse) Descriptor() ([]byte, []int) { - return file_job_v1_job_proto_rawDescGZIP(), []int{15} -} - -func (x *DeleteJobResponse) GetJob() *Job { - if x != nil { - return x.Job - } - return nil -} - -type ListJobsRequest_Filter struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Ids []string `protobuf:"bytes,1,rep,name=ids,proto3" json:"ids,omitempty"` // Filter by job IDs. - NodeIds []string `protobuf:"bytes,2,rep,name=node_ids,json=nodeIds,proto3" json:"node_ids,omitempty"` // Filter by node IDs. -} - -func (x *ListJobsRequest_Filter) Reset() { - *x = ListJobsRequest_Filter{} - if protoimpl.UnsafeEnabled { - mi := &file_job_v1_job_proto_msgTypes[16] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ListJobsRequest_Filter) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ListJobsRequest_Filter) ProtoMessage() {} - -func (x *ListJobsRequest_Filter) ProtoReflect() protoreflect.Message { - mi := &file_job_v1_job_proto_msgTypes[16] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ListJobsRequest_Filter.ProtoReflect.Descriptor instead. -func (*ListJobsRequest_Filter) Descriptor() ([]byte, []int) { - return file_job_v1_job_proto_rawDescGZIP(), []int{6, 0} -} - -func (x *ListJobsRequest_Filter) GetIds() []string { - if x != nil { - return x.Ids - } - return nil -} - -func (x *ListJobsRequest_Filter) GetNodeIds() []string { - if x != nil { - return x.NodeIds - } - return nil -} - -type ListProposalsRequest_Filter struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Ids []string `protobuf:"bytes,1,rep,name=ids,proto3" json:"ids,omitempty"` // Filter by proposal IDs. - JobIds []string `protobuf:"bytes,2,rep,name=job_ids,json=jobIds,proto3" json:"job_ids,omitempty"` // Filter by job IDs. -} - -func (x *ListProposalsRequest_Filter) Reset() { - *x = ListProposalsRequest_Filter{} - if protoimpl.UnsafeEnabled { - mi := &file_job_v1_job_proto_msgTypes[17] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ListProposalsRequest_Filter) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ListProposalsRequest_Filter) ProtoMessage() {} - -func (x *ListProposalsRequest_Filter) ProtoReflect() protoreflect.Message { - mi := &file_job_v1_job_proto_msgTypes[17] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ListProposalsRequest_Filter.ProtoReflect.Descriptor instead. -func (*ListProposalsRequest_Filter) Descriptor() ([]byte, []int) { - return file_job_v1_job_proto_rawDescGZIP(), []int{8, 0} -} - -func (x *ListProposalsRequest_Filter) GetIds() []string { - if x != nil { - return x.Ids - } - return nil -} - -func (x *ListProposalsRequest_Filter) GetJobIds() []string { - if x != nil { - return x.JobIds - } - return nil -} - -var File_job_v1_job_proto protoreflect.FileDescriptor - -var file_job_v1_job_proto_rawDesc = []byte{ - 0x0a, 0x10, 0x6a, 0x6f, 0x62, 0x2f, 0x76, 0x31, 0x2f, 0x6a, 0x6f, 0x62, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x12, 0x0a, 0x61, 0x70, 0x69, 0x2e, 0x6a, 0x6f, 0x62, 0x2e, 0x76, 0x31, 0x1a, 0x1f, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, - 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, - 0x96, 0x02, 0x0a, 0x03, 0x4a, 0x6f, 0x62, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x75, 0x69, 0x64, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x75, 0x69, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x6e, - 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6e, 0x6f, - 0x64, 0x65, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, - 0x5f, 0x69, 0x64, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x70, - 0x6f, 0x73, 0x61, 0x6c, 0x49, 0x64, 0x73, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, - 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, - 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, - 0x41, 0x74, 0x12, 0x39, 0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, - 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, - 0x6d, 0x70, 0x52, 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x39, 0x0a, - 0x0a, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x64, - 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x41, 0x74, 0x22, 0x8b, 0x04, 0x0a, 0x08, 0x50, 0x72, 0x6f, - 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, - 0x32, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, - 0x1a, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x6a, 0x6f, 0x62, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, - 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x12, 0x4b, 0x0a, 0x0f, 0x64, 0x65, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x79, 0x5f, - 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x22, 0x2e, 0x61, - 0x70, 0x69, 0x2e, 0x6a, 0x6f, 0x62, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, - 0x61, 0x6c, 0x44, 0x65, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x79, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x52, 0x0e, 0x64, 0x65, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x79, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x12, 0x12, 0x0a, 0x04, 0x73, 0x70, 0x65, 0x63, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, - 0x73, 0x70, 0x65, 0x63, 0x12, 0x15, 0x0a, 0x06, 0x6a, 0x6f, 0x62, 0x5f, 0x69, 0x64, 0x18, 0x06, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6a, 0x6f, 0x62, 0x49, 0x64, 0x12, 0x39, 0x0a, 0x0a, 0x63, - 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x39, 0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x64, 0x5f, 0x61, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, - 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, - 0x74, 0x12, 0x3a, 0x0a, 0x08, 0x61, 0x63, 0x6b, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x09, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x48, - 0x00, 0x52, 0x07, 0x61, 0x63, 0x6b, 0x65, 0x64, 0x41, 0x74, 0x88, 0x01, 0x01, 0x12, 0x51, 0x0a, - 0x14, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, - 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, - 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x48, 0x01, 0x52, 0x12, 0x72, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x64, 0x41, 0x74, 0x88, 0x01, 0x01, - 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x61, 0x63, 0x6b, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x42, 0x17, 0x0a, - 0x15, 0x5f, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x72, 0x65, 0x63, 0x65, 0x69, - 0x76, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x22, 0x43, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x4a, 0x6f, 0x62, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x04, 0x75, 0x75, 0x69, - 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x04, 0x75, 0x75, 0x69, 0x64, 0x42, - 0x0a, 0x0a, 0x08, 0x69, 0x64, 0x5f, 0x6f, 0x6e, 0x65, 0x6f, 0x66, 0x22, 0x33, 0x0a, 0x0e, 0x47, - 0x65, 0x74, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x21, 0x0a, - 0x03, 0x6a, 0x6f, 0x62, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x61, 0x70, 0x69, - 0x2e, 0x6a, 0x6f, 0x62, 0x2e, 0x76, 0x31, 0x2e, 0x4a, 0x6f, 0x62, 0x52, 0x03, 0x6a, 0x6f, 0x62, - 0x22, 0x24, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x47, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, - 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x30, 0x0a, - 0x08, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x14, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x6a, 0x6f, 0x62, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, - 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x22, - 0x84, 0x01, 0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74, 0x4a, 0x6f, 0x62, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x3a, 0x0a, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x6a, 0x6f, 0x62, 0x2e, 0x76, 0x31, - 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4a, 0x6f, 0x62, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x2e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x1a, - 0x35, 0x0a, 0x06, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x10, 0x0a, 0x03, 0x69, 0x64, 0x73, - 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x03, 0x69, 0x64, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x6e, - 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x6e, - 0x6f, 0x64, 0x65, 0x49, 0x64, 0x73, 0x22, 0x37, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, 0x4a, 0x6f, - 0x62, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x23, 0x0a, 0x04, 0x6a, 0x6f, - 0x62, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x6a, - 0x6f, 0x62, 0x2e, 0x76, 0x31, 0x2e, 0x4a, 0x6f, 0x62, 0x52, 0x04, 0x6a, 0x6f, 0x62, 0x73, 0x22, - 0x8c, 0x01, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3f, 0x0a, 0x06, 0x66, 0x69, 0x6c, 0x74, - 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x6a, - 0x6f, 0x62, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, - 0x61, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x46, 0x69, 0x6c, 0x74, 0x65, - 0x72, 0x52, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x1a, 0x33, 0x0a, 0x06, 0x46, 0x69, 0x6c, - 0x74, 0x65, 0x72, 0x12, 0x10, 0x0a, 0x03, 0x69, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, - 0x52, 0x03, 0x69, 0x64, 0x73, 0x12, 0x17, 0x0a, 0x07, 0x6a, 0x6f, 0x62, 0x5f, 0x69, 0x64, 0x73, - 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x6a, 0x6f, 0x62, 0x49, 0x64, 0x73, 0x22, 0x4b, - 0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x73, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x32, 0x0a, 0x09, 0x70, 0x72, 0x6f, 0x70, 0x6f, - 0x73, 0x61, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x61, 0x70, 0x69, - 0x2e, 0x6a, 0x6f, 0x62, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, - 0x52, 0x09, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x73, 0x22, 0x40, 0x0a, 0x11, 0x50, - 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x17, 0x0a, 0x07, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x06, 0x6e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x70, 0x65, - 0x63, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x73, 0x70, 0x65, 0x63, 0x22, 0x46, 0x0a, - 0x12, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x30, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x6a, 0x6f, 0x62, 0x2e, - 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x52, 0x08, 0x70, 0x72, 0x6f, - 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x22, 0x46, 0x0a, 0x10, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x4a, - 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x02, 0x69, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x04, 0x75, - 0x75, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x04, 0x75, 0x75, 0x69, - 0x64, 0x42, 0x0a, 0x0a, 0x08, 0x69, 0x64, 0x5f, 0x6f, 0x6e, 0x65, 0x6f, 0x66, 0x22, 0x45, 0x0a, - 0x11, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x30, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x6a, 0x6f, 0x62, 0x2e, 0x76, - 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x70, - 0x6f, 0x73, 0x61, 0x6c, 0x22, 0x46, 0x0a, 0x10, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4a, 0x6f, - 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x04, 0x75, 0x75, - 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x04, 0x75, 0x75, 0x69, 0x64, - 0x42, 0x0a, 0x0a, 0x08, 0x69, 0x64, 0x5f, 0x6f, 0x6e, 0x65, 0x6f, 0x66, 0x22, 0x36, 0x0a, 0x11, - 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x21, 0x0a, 0x03, 0x6a, 0x6f, 0x62, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, - 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x6a, 0x6f, 0x62, 0x2e, 0x76, 0x31, 0x2e, 0x4a, 0x6f, 0x62, 0x52, - 0x03, 0x6a, 0x6f, 0x62, 0x2a, 0xe4, 0x01, 0x0a, 0x0e, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, - 0x6c, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1f, 0x0a, 0x1b, 0x50, 0x52, 0x4f, 0x50, 0x4f, - 0x53, 0x41, 0x4c, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, - 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1c, 0x0a, 0x18, 0x50, 0x52, 0x4f, 0x50, - 0x4f, 0x53, 0x41, 0x4c, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x50, 0x52, 0x4f, 0x50, - 0x4f, 0x53, 0x45, 0x44, 0x10, 0x01, 0x12, 0x1c, 0x0a, 0x18, 0x50, 0x52, 0x4f, 0x50, 0x4f, 0x53, - 0x41, 0x4c, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x41, 0x50, 0x50, 0x52, 0x4f, 0x56, - 0x45, 0x44, 0x10, 0x02, 0x12, 0x1c, 0x0a, 0x18, 0x50, 0x52, 0x4f, 0x50, 0x4f, 0x53, 0x41, 0x4c, - 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x52, 0x45, 0x4a, 0x45, 0x43, 0x54, 0x45, 0x44, - 0x10, 0x03, 0x12, 0x1d, 0x0a, 0x19, 0x50, 0x52, 0x4f, 0x50, 0x4f, 0x53, 0x41, 0x4c, 0x5f, 0x53, - 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x43, 0x41, 0x4e, 0x43, 0x45, 0x4c, 0x4c, 0x45, 0x44, 0x10, - 0x04, 0x12, 0x1b, 0x0a, 0x17, 0x50, 0x52, 0x4f, 0x50, 0x4f, 0x53, 0x41, 0x4c, 0x5f, 0x53, 0x54, - 0x41, 0x54, 0x55, 0x53, 0x5f, 0x50, 0x45, 0x4e, 0x44, 0x49, 0x4e, 0x47, 0x10, 0x05, 0x12, 0x1b, - 0x0a, 0x17, 0x50, 0x52, 0x4f, 0x50, 0x4f, 0x53, 0x41, 0x4c, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, - 0x53, 0x5f, 0x52, 0x45, 0x56, 0x4f, 0x4b, 0x45, 0x44, 0x10, 0x06, 0x2a, 0xba, 0x01, 0x0a, 0x16, - 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x44, 0x65, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x79, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x28, 0x0a, 0x24, 0x50, 0x52, 0x4f, 0x50, 0x4f, 0x53, - 0x41, 0x4c, 0x5f, 0x44, 0x45, 0x4c, 0x49, 0x56, 0x45, 0x52, 0x59, 0x5f, 0x53, 0x54, 0x41, 0x54, - 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, - 0x12, 0x26, 0x0a, 0x22, 0x50, 0x52, 0x4f, 0x50, 0x4f, 0x53, 0x41, 0x4c, 0x5f, 0x44, 0x45, 0x4c, - 0x49, 0x56, 0x45, 0x52, 0x59, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x44, 0x45, 0x4c, - 0x49, 0x56, 0x45, 0x52, 0x45, 0x44, 0x10, 0x01, 0x12, 0x29, 0x0a, 0x25, 0x50, 0x52, 0x4f, 0x50, - 0x4f, 0x53, 0x41, 0x4c, 0x5f, 0x44, 0x45, 0x4c, 0x49, 0x56, 0x45, 0x52, 0x59, 0x5f, 0x53, 0x54, - 0x41, 0x54, 0x55, 0x53, 0x5f, 0x41, 0x43, 0x4b, 0x4e, 0x4f, 0x57, 0x4c, 0x45, 0x44, 0x47, 0x45, - 0x44, 0x10, 0x02, 0x12, 0x23, 0x0a, 0x1f, 0x50, 0x52, 0x4f, 0x50, 0x4f, 0x53, 0x41, 0x4c, 0x5f, - 0x44, 0x45, 0x4c, 0x49, 0x56, 0x45, 0x52, 0x59, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, - 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44, 0x10, 0x03, 0x32, 0xa9, 0x04, 0x0a, 0x0a, 0x4a, 0x6f, 0x62, - 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x41, 0x0a, 0x06, 0x47, 0x65, 0x74, 0x4a, 0x6f, - 0x62, 0x12, 0x19, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x6a, 0x6f, 0x62, 0x2e, 0x76, 0x31, 0x2e, 0x47, - 0x65, 0x74, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x61, - 0x70, 0x69, 0x2e, 0x6a, 0x6f, 0x62, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4a, 0x6f, 0x62, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x50, 0x0a, 0x0b, 0x47, 0x65, - 0x74, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x12, 0x1e, 0x2e, 0x61, 0x70, 0x69, 0x2e, - 0x6a, 0x6f, 0x62, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, - 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x61, 0x70, 0x69, 0x2e, - 0x6a, 0x6f, 0x62, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, - 0x61, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x47, 0x0a, 0x08, - 0x4c, 0x69, 0x73, 0x74, 0x4a, 0x6f, 0x62, 0x73, 0x12, 0x1b, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x6a, - 0x6f, 0x62, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4a, 0x6f, 0x62, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x6a, 0x6f, 0x62, 0x2e, - 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4a, 0x6f, 0x62, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x56, 0x0a, 0x0d, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x6f, - 0x70, 0x6f, 0x73, 0x61, 0x6c, 0x73, 0x12, 0x20, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x6a, 0x6f, 0x62, - 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x61, 0x6c, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x6a, - 0x6f, 0x62, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, - 0x61, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4d, 0x0a, - 0x0a, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x4a, 0x6f, 0x62, 0x12, 0x1d, 0x2e, 0x61, 0x70, - 0x69, 0x2e, 0x6a, 0x6f, 0x62, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, - 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x61, 0x70, 0x69, - 0x2e, 0x6a, 0x6f, 0x62, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x6f, 0x73, 0x65, 0x4a, - 0x6f, 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4a, 0x0a, 0x09, - 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x4a, 0x6f, 0x62, 0x12, 0x1c, 0x2e, 0x61, 0x70, 0x69, 0x2e, - 0x6a, 0x6f, 0x62, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x4a, 0x6f, 0x62, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x6a, 0x6f, - 0x62, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x4a, 0x6f, 0x62, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4a, 0x0a, 0x09, 0x44, 0x65, 0x6c, 0x65, - 0x74, 0x65, 0x4a, 0x6f, 0x62, 0x12, 0x1c, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x6a, 0x6f, 0x62, 0x2e, - 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x6a, 0x6f, 0x62, 0x2e, 0x76, 0x31, - 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x00, 0x42, 0x08, 0x5a, 0x06, 0x6a, 0x6f, 0x62, 0x2f, 0x76, 0x31, 0x62, 0x06, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_job_v1_job_proto_rawDescOnce sync.Once - file_job_v1_job_proto_rawDescData = file_job_v1_job_proto_rawDesc -) - -func file_job_v1_job_proto_rawDescGZIP() []byte { - file_job_v1_job_proto_rawDescOnce.Do(func() { - file_job_v1_job_proto_rawDescData = protoimpl.X.CompressGZIP(file_job_v1_job_proto_rawDescData) - }) - return file_job_v1_job_proto_rawDescData -} - -var file_job_v1_job_proto_enumTypes = make([]protoimpl.EnumInfo, 2) -var file_job_v1_job_proto_msgTypes = make([]protoimpl.MessageInfo, 18) -var file_job_v1_job_proto_goTypes = []interface{}{ - (ProposalStatus)(0), // 0: api.job.v1.ProposalStatus - (ProposalDeliveryStatus)(0), // 1: api.job.v1.ProposalDeliveryStatus - (*Job)(nil), // 2: api.job.v1.Job - (*Proposal)(nil), // 3: api.job.v1.Proposal - (*GetJobRequest)(nil), // 4: api.job.v1.GetJobRequest - (*GetJobResponse)(nil), // 5: api.job.v1.GetJobResponse - (*GetProposalRequest)(nil), // 6: api.job.v1.GetProposalRequest - (*GetProposalResponse)(nil), // 7: api.job.v1.GetProposalResponse - (*ListJobsRequest)(nil), // 8: api.job.v1.ListJobsRequest - (*ListJobsResponse)(nil), // 9: api.job.v1.ListJobsResponse - (*ListProposalsRequest)(nil), // 10: api.job.v1.ListProposalsRequest - (*ListProposalsResponse)(nil), // 11: api.job.v1.ListProposalsResponse - (*ProposeJobRequest)(nil), // 12: api.job.v1.ProposeJobRequest - (*ProposeJobResponse)(nil), // 13: api.job.v1.ProposeJobResponse - (*RevokeJobRequest)(nil), // 14: api.job.v1.RevokeJobRequest - (*RevokeJobResponse)(nil), // 15: api.job.v1.RevokeJobResponse - (*DeleteJobRequest)(nil), // 16: api.job.v1.DeleteJobRequest - (*DeleteJobResponse)(nil), // 17: api.job.v1.DeleteJobResponse - (*ListJobsRequest_Filter)(nil), // 18: api.job.v1.ListJobsRequest.Filter - (*ListProposalsRequest_Filter)(nil), // 19: api.job.v1.ListProposalsRequest.Filter - (*timestamppb.Timestamp)(nil), // 20: google.protobuf.Timestamp -} -var file_job_v1_job_proto_depIdxs = []int32{ - 20, // 0: api.job.v1.Job.created_at:type_name -> google.protobuf.Timestamp - 20, // 1: api.job.v1.Job.updated_at:type_name -> google.protobuf.Timestamp - 20, // 2: api.job.v1.Job.deleted_at:type_name -> google.protobuf.Timestamp - 0, // 3: api.job.v1.Proposal.status:type_name -> api.job.v1.ProposalStatus - 1, // 4: api.job.v1.Proposal.delivery_status:type_name -> api.job.v1.ProposalDeliveryStatus - 20, // 5: api.job.v1.Proposal.created_at:type_name -> google.protobuf.Timestamp - 20, // 6: api.job.v1.Proposal.updated_at:type_name -> google.protobuf.Timestamp - 20, // 7: api.job.v1.Proposal.acked_at:type_name -> google.protobuf.Timestamp - 20, // 8: api.job.v1.Proposal.response_received_at:type_name -> google.protobuf.Timestamp - 2, // 9: api.job.v1.GetJobResponse.job:type_name -> api.job.v1.Job - 3, // 10: api.job.v1.GetProposalResponse.proposal:type_name -> api.job.v1.Proposal - 18, // 11: api.job.v1.ListJobsRequest.filter:type_name -> api.job.v1.ListJobsRequest.Filter - 2, // 12: api.job.v1.ListJobsResponse.jobs:type_name -> api.job.v1.Job - 19, // 13: api.job.v1.ListProposalsRequest.filter:type_name -> api.job.v1.ListProposalsRequest.Filter - 3, // 14: api.job.v1.ListProposalsResponse.proposals:type_name -> api.job.v1.Proposal - 3, // 15: api.job.v1.ProposeJobResponse.proposal:type_name -> api.job.v1.Proposal - 3, // 16: api.job.v1.RevokeJobResponse.proposal:type_name -> api.job.v1.Proposal - 2, // 17: api.job.v1.DeleteJobResponse.job:type_name -> api.job.v1.Job - 4, // 18: api.job.v1.JobService.GetJob:input_type -> api.job.v1.GetJobRequest - 6, // 19: api.job.v1.JobService.GetProposal:input_type -> api.job.v1.GetProposalRequest - 8, // 20: api.job.v1.JobService.ListJobs:input_type -> api.job.v1.ListJobsRequest - 10, // 21: api.job.v1.JobService.ListProposals:input_type -> api.job.v1.ListProposalsRequest - 12, // 22: api.job.v1.JobService.ProposeJob:input_type -> api.job.v1.ProposeJobRequest - 14, // 23: api.job.v1.JobService.RevokeJob:input_type -> api.job.v1.RevokeJobRequest - 16, // 24: api.job.v1.JobService.DeleteJob:input_type -> api.job.v1.DeleteJobRequest - 5, // 25: api.job.v1.JobService.GetJob:output_type -> api.job.v1.GetJobResponse - 7, // 26: api.job.v1.JobService.GetProposal:output_type -> api.job.v1.GetProposalResponse - 9, // 27: api.job.v1.JobService.ListJobs:output_type -> api.job.v1.ListJobsResponse - 11, // 28: api.job.v1.JobService.ListProposals:output_type -> api.job.v1.ListProposalsResponse - 13, // 29: api.job.v1.JobService.ProposeJob:output_type -> api.job.v1.ProposeJobResponse - 15, // 30: api.job.v1.JobService.RevokeJob:output_type -> api.job.v1.RevokeJobResponse - 17, // 31: api.job.v1.JobService.DeleteJob:output_type -> api.job.v1.DeleteJobResponse - 25, // [25:32] is the sub-list for method output_type - 18, // [18:25] is the sub-list for method input_type - 18, // [18:18] is the sub-list for extension type_name - 18, // [18:18] is the sub-list for extension extendee - 0, // [0:18] is the sub-list for field type_name -} - -func init() { file_job_v1_job_proto_init() } -func file_job_v1_job_proto_init() { - if File_job_v1_job_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_job_v1_job_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Job); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_job_v1_job_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Proposal); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_job_v1_job_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetJobRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_job_v1_job_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetJobResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_job_v1_job_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetProposalRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_job_v1_job_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetProposalResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_job_v1_job_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListJobsRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_job_v1_job_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListJobsResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_job_v1_job_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListProposalsRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_job_v1_job_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListProposalsResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_job_v1_job_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ProposeJobRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_job_v1_job_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ProposeJobResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_job_v1_job_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RevokeJobRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_job_v1_job_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RevokeJobResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_job_v1_job_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DeleteJobRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_job_v1_job_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*DeleteJobResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_job_v1_job_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListJobsRequest_Filter); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_job_v1_job_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListProposalsRequest_Filter); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - file_job_v1_job_proto_msgTypes[1].OneofWrappers = []interface{}{} - file_job_v1_job_proto_msgTypes[2].OneofWrappers = []interface{}{ - (*GetJobRequest_Id)(nil), - (*GetJobRequest_Uuid)(nil), - } - file_job_v1_job_proto_msgTypes[12].OneofWrappers = []interface{}{ - (*RevokeJobRequest_Id)(nil), - (*RevokeJobRequest_Uuid)(nil), - } - file_job_v1_job_proto_msgTypes[14].OneofWrappers = []interface{}{ - (*DeleteJobRequest_Id)(nil), - (*DeleteJobRequest_Uuid)(nil), - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_job_v1_job_proto_rawDesc, - NumEnums: 2, - NumMessages: 18, - NumExtensions: 0, - NumServices: 1, - }, - GoTypes: file_job_v1_job_proto_goTypes, - DependencyIndexes: file_job_v1_job_proto_depIdxs, - EnumInfos: file_job_v1_job_proto_enumTypes, - MessageInfos: file_job_v1_job_proto_msgTypes, - }.Build() - File_job_v1_job_proto = out.File - file_job_v1_job_proto_rawDesc = nil - file_job_v1_job_proto_goTypes = nil - file_job_v1_job_proto_depIdxs = nil -} diff --git a/integration-tests/deployment/jd/job/v1/job_grpc.pb.go b/integration-tests/deployment/jd/job/v1/job_grpc.pb.go deleted file mode 100644 index 9b9207c020..0000000000 --- a/integration-tests/deployment/jd/job/v1/job_grpc.pb.go +++ /dev/null @@ -1,345 +0,0 @@ -// Code generated by protoc-gen-go-grpc. DO NOT EDIT. -// versions: -// - protoc-gen-go-grpc v1.3.0 -// - protoc v4.25.3 -// source: job/v1/job.proto - -package v1 - -import ( - context "context" - grpc "google.golang.org/grpc" - codes "google.golang.org/grpc/codes" - status "google.golang.org/grpc/status" -) - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the grpc package it is being compiled against. -// Requires gRPC-Go v1.32.0 or later. -const _ = grpc.SupportPackageIsVersion7 - -const ( - JobService_GetJob_FullMethodName = "/api.job.v1.JobService/GetJob" - JobService_GetProposal_FullMethodName = "/api.job.v1.JobService/GetProposal" - JobService_ListJobs_FullMethodName = "/api.job.v1.JobService/ListJobs" - JobService_ListProposals_FullMethodName = "/api.job.v1.JobService/ListProposals" - JobService_ProposeJob_FullMethodName = "/api.job.v1.JobService/ProposeJob" - JobService_RevokeJob_FullMethodName = "/api.job.v1.JobService/RevokeJob" - JobService_DeleteJob_FullMethodName = "/api.job.v1.JobService/DeleteJob" -) - -// JobServiceClient is the client API for JobService service. -// -// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. -type JobServiceClient interface { - // GetJob retrieves the details of a specific job by its ID or UUID. - GetJob(ctx context.Context, in *GetJobRequest, opts ...grpc.CallOption) (*GetJobResponse, error) - // GetProposal retrieves the details of a specific proposal by its ID. - GetProposal(ctx context.Context, in *GetProposalRequest, opts ...grpc.CallOption) (*GetProposalResponse, error) - // ListJobs returns a list of jobs, optionally filtered by IDs or node IDs. - ListJobs(ctx context.Context, in *ListJobsRequest, opts ...grpc.CallOption) (*ListJobsResponse, error) - // ListProposals returns a list of proposals, optionally filtered by proposal or job IDs. - ListProposals(ctx context.Context, in *ListProposalsRequest, opts ...grpc.CallOption) (*ListProposalsResponse, error) - // ProposeJob submits a new job proposal to a node. - ProposeJob(ctx context.Context, in *ProposeJobRequest, opts ...grpc.CallOption) (*ProposeJobResponse, error) - // RevokeJob revokes an existing job proposal. - RevokeJob(ctx context.Context, in *RevokeJobRequest, opts ...grpc.CallOption) (*RevokeJobResponse, error) - // DeleteJob deletes a job from the system. - DeleteJob(ctx context.Context, in *DeleteJobRequest, opts ...grpc.CallOption) (*DeleteJobResponse, error) -} - -type jobServiceClient struct { - cc grpc.ClientConnInterface -} - -func NewJobServiceClient(cc grpc.ClientConnInterface) JobServiceClient { - return &jobServiceClient{cc} -} - -func (c *jobServiceClient) GetJob(ctx context.Context, in *GetJobRequest, opts ...grpc.CallOption) (*GetJobResponse, error) { - out := new(GetJobResponse) - err := c.cc.Invoke(ctx, JobService_GetJob_FullMethodName, in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *jobServiceClient) GetProposal(ctx context.Context, in *GetProposalRequest, opts ...grpc.CallOption) (*GetProposalResponse, error) { - out := new(GetProposalResponse) - err := c.cc.Invoke(ctx, JobService_GetProposal_FullMethodName, in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *jobServiceClient) ListJobs(ctx context.Context, in *ListJobsRequest, opts ...grpc.CallOption) (*ListJobsResponse, error) { - out := new(ListJobsResponse) - err := c.cc.Invoke(ctx, JobService_ListJobs_FullMethodName, in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *jobServiceClient) ListProposals(ctx context.Context, in *ListProposalsRequest, opts ...grpc.CallOption) (*ListProposalsResponse, error) { - out := new(ListProposalsResponse) - err := c.cc.Invoke(ctx, JobService_ListProposals_FullMethodName, in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *jobServiceClient) ProposeJob(ctx context.Context, in *ProposeJobRequest, opts ...grpc.CallOption) (*ProposeJobResponse, error) { - out := new(ProposeJobResponse) - err := c.cc.Invoke(ctx, JobService_ProposeJob_FullMethodName, in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *jobServiceClient) RevokeJob(ctx context.Context, in *RevokeJobRequest, opts ...grpc.CallOption) (*RevokeJobResponse, error) { - out := new(RevokeJobResponse) - err := c.cc.Invoke(ctx, JobService_RevokeJob_FullMethodName, in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *jobServiceClient) DeleteJob(ctx context.Context, in *DeleteJobRequest, opts ...grpc.CallOption) (*DeleteJobResponse, error) { - out := new(DeleteJobResponse) - err := c.cc.Invoke(ctx, JobService_DeleteJob_FullMethodName, in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -// JobServiceServer is the server API for JobService service. -// All implementations must embed UnimplementedJobServiceServer -// for forward compatibility -type JobServiceServer interface { - // GetJob retrieves the details of a specific job by its ID or UUID. - GetJob(context.Context, *GetJobRequest) (*GetJobResponse, error) - // GetProposal retrieves the details of a specific proposal by its ID. - GetProposal(context.Context, *GetProposalRequest) (*GetProposalResponse, error) - // ListJobs returns a list of jobs, optionally filtered by IDs or node IDs. - ListJobs(context.Context, *ListJobsRequest) (*ListJobsResponse, error) - // ListProposals returns a list of proposals, optionally filtered by proposal or job IDs. - ListProposals(context.Context, *ListProposalsRequest) (*ListProposalsResponse, error) - // ProposeJob submits a new job proposal to a node. - ProposeJob(context.Context, *ProposeJobRequest) (*ProposeJobResponse, error) - // RevokeJob revokes an existing job proposal. - RevokeJob(context.Context, *RevokeJobRequest) (*RevokeJobResponse, error) - // DeleteJob deletes a job from the system. - DeleteJob(context.Context, *DeleteJobRequest) (*DeleteJobResponse, error) - mustEmbedUnimplementedJobServiceServer() -} - -// UnimplementedJobServiceServer must be embedded to have forward compatible implementations. -type UnimplementedJobServiceServer struct { -} - -func (UnimplementedJobServiceServer) GetJob(context.Context, *GetJobRequest) (*GetJobResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method GetJob not implemented") -} -func (UnimplementedJobServiceServer) GetProposal(context.Context, *GetProposalRequest) (*GetProposalResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method GetProposal not implemented") -} -func (UnimplementedJobServiceServer) ListJobs(context.Context, *ListJobsRequest) (*ListJobsResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method ListJobs not implemented") -} -func (UnimplementedJobServiceServer) ListProposals(context.Context, *ListProposalsRequest) (*ListProposalsResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method ListProposals not implemented") -} -func (UnimplementedJobServiceServer) ProposeJob(context.Context, *ProposeJobRequest) (*ProposeJobResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method ProposeJob not implemented") -} -func (UnimplementedJobServiceServer) RevokeJob(context.Context, *RevokeJobRequest) (*RevokeJobResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method RevokeJob not implemented") -} -func (UnimplementedJobServiceServer) DeleteJob(context.Context, *DeleteJobRequest) (*DeleteJobResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method DeleteJob not implemented") -} -func (UnimplementedJobServiceServer) mustEmbedUnimplementedJobServiceServer() {} - -// UnsafeJobServiceServer may be embedded to opt out of forward compatibility for this service. -// Use of this interface is not recommended, as added methods to JobServiceServer will -// result in compilation errors. -type UnsafeJobServiceServer interface { - mustEmbedUnimplementedJobServiceServer() -} - -func RegisterJobServiceServer(s grpc.ServiceRegistrar, srv JobServiceServer) { - s.RegisterService(&JobService_ServiceDesc, srv) -} - -func _JobService_GetJob_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(GetJobRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(JobServiceServer).GetJob(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: JobService_GetJob_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(JobServiceServer).GetJob(ctx, req.(*GetJobRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _JobService_GetProposal_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(GetProposalRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(JobServiceServer).GetProposal(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: JobService_GetProposal_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(JobServiceServer).GetProposal(ctx, req.(*GetProposalRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _JobService_ListJobs_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(ListJobsRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(JobServiceServer).ListJobs(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: JobService_ListJobs_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(JobServiceServer).ListJobs(ctx, req.(*ListJobsRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _JobService_ListProposals_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(ListProposalsRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(JobServiceServer).ListProposals(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: JobService_ListProposals_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(JobServiceServer).ListProposals(ctx, req.(*ListProposalsRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _JobService_ProposeJob_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(ProposeJobRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(JobServiceServer).ProposeJob(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: JobService_ProposeJob_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(JobServiceServer).ProposeJob(ctx, req.(*ProposeJobRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _JobService_RevokeJob_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(RevokeJobRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(JobServiceServer).RevokeJob(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: JobService_RevokeJob_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(JobServiceServer).RevokeJob(ctx, req.(*RevokeJobRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _JobService_DeleteJob_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(DeleteJobRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(JobServiceServer).DeleteJob(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: JobService_DeleteJob_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(JobServiceServer).DeleteJob(ctx, req.(*DeleteJobRequest)) - } - return interceptor(ctx, in, info, handler) -} - -// JobService_ServiceDesc is the grpc.ServiceDesc for JobService service. -// It's only intended for direct use with grpc.RegisterService, -// and not to be introspected or modified (even as a copy) -var JobService_ServiceDesc = grpc.ServiceDesc{ - ServiceName: "api.job.v1.JobService", - HandlerType: (*JobServiceServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "GetJob", - Handler: _JobService_GetJob_Handler, - }, - { - MethodName: "GetProposal", - Handler: _JobService_GetProposal_Handler, - }, - { - MethodName: "ListJobs", - Handler: _JobService_ListJobs_Handler, - }, - { - MethodName: "ListProposals", - Handler: _JobService_ListProposals_Handler, - }, - { - MethodName: "ProposeJob", - Handler: _JobService_ProposeJob_Handler, - }, - { - MethodName: "RevokeJob", - Handler: _JobService_RevokeJob_Handler, - }, - { - MethodName: "DeleteJob", - Handler: _JobService_DeleteJob_Handler, - }, - }, - Streams: []grpc.StreamDesc{}, - Metadata: "job/v1/job.proto", -} diff --git a/integration-tests/deployment/jd/node/v1/node.pb.go b/integration-tests/deployment/jd/node/v1/node.pb.go deleted file mode 100644 index f5b22ba3ae..0000000000 --- a/integration-tests/deployment/jd/node/v1/node.pb.go +++ /dev/null @@ -1,1652 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.29.0 -// protoc v4.25.3 -// source: node/v1/node.proto - -package v1 - -import ( - "reflect" - "sync" - - "google.golang.org/protobuf/reflect/protoreflect" - "google.golang.org/protobuf/runtime/protoimpl" - _ "google.golang.org/protobuf/types/known/timestamppb" - - "github.com/smartcontractkit/chainlink/integration-tests/deployment/jd/shared/ptypes" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type ChainType int32 - -const ( - ChainType_CHAIN_TYPE_UNSPECIFIED ChainType = 0 - ChainType_CHAIN_TYPE_EVM ChainType = 1 - ChainType_CHAIN_TYPE_SOLANA ChainType = 2 -) - -// Enum value maps for ChainType. -var ( - ChainType_name = map[int32]string{ - 0: "CHAIN_TYPE_UNSPECIFIED", - 1: "CHAIN_TYPE_EVM", - 2: "CHAIN_TYPE_SOLANA", - } - ChainType_value = map[string]int32{ - "CHAIN_TYPE_UNSPECIFIED": 0, - "CHAIN_TYPE_EVM": 1, - "CHAIN_TYPE_SOLANA": 2, - } -) - -func (x ChainType) Enum() *ChainType { - p := new(ChainType) - *p = x - return p -} - -func (x ChainType) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (ChainType) Descriptor() protoreflect.EnumDescriptor { - return file_node_v1_node_proto_enumTypes[0].Descriptor() -} - -func (ChainType) Type() protoreflect.EnumType { - return &file_node_v1_node_proto_enumTypes[0] -} - -func (x ChainType) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use ChainType.Descriptor instead. -func (ChainType) EnumDescriptor() ([]byte, []int) { - return file_node_v1_node_proto_rawDescGZIP(), []int{0} -} - -// ArchiveState represents the archived state of the node. -type ArchiveState int32 - -const ( - ArchiveState_ARCHIVE_STATE_UNSPECIFIED ArchiveState = 0 - ArchiveState_ARCHIVE_STATE_ARCHIVED ArchiveState = 1 - ArchiveState_ARCHIVE_STATE_ACTIVE ArchiveState = 2 -) - -// Enum value maps for ArchiveState. -var ( - ArchiveState_name = map[int32]string{ - 0: "ARCHIVE_STATE_UNSPECIFIED", - 1: "ARCHIVE_STATE_ARCHIVED", - 2: "ARCHIVE_STATE_ACTIVE", - } - ArchiveState_value = map[string]int32{ - "ARCHIVE_STATE_UNSPECIFIED": 0, - "ARCHIVE_STATE_ARCHIVED": 1, - "ARCHIVE_STATE_ACTIVE": 2, - } -) - -func (x ArchiveState) Enum() *ArchiveState { - p := new(ArchiveState) - *p = x - return p -} - -func (x ArchiveState) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (ArchiveState) Descriptor() protoreflect.EnumDescriptor { - return file_node_v1_node_proto_enumTypes[1].Descriptor() -} - -func (ArchiveState) Type() protoreflect.EnumType { - return &file_node_v1_node_proto_enumTypes[1] -} - -func (x ArchiveState) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use ArchiveState.Descriptor instead. -func (ArchiveState) EnumDescriptor() ([]byte, []int) { - return file_node_v1_node_proto_rawDescGZIP(), []int{1} -} - -type Chain struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - Type ChainType `protobuf:"varint,2,opt,name=type,proto3,enum=api.node.v1.ChainType" json:"type,omitempty"` -} - -func (x *Chain) Reset() { - *x = Chain{} - if protoimpl.UnsafeEnabled { - mi := &file_node_v1_node_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Chain) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Chain) ProtoMessage() {} - -func (x *Chain) ProtoReflect() protoreflect.Message { - mi := &file_node_v1_node_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Chain.ProtoReflect.Descriptor instead. -func (*Chain) Descriptor() ([]byte, []int) { - return file_node_v1_node_proto_rawDescGZIP(), []int{0} -} - -func (x *Chain) GetId() string { - if x != nil { - return x.Id - } - return "" -} - -func (x *Chain) GetType() ChainType { - if x != nil { - return x.Type - } - return ChainType_CHAIN_TYPE_UNSPECIFIED -} - -type OCR1Config struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"` - IsBootstrap bool `protobuf:"varint,2,opt,name=is_bootstrap,json=isBootstrap,proto3" json:"is_bootstrap,omitempty"` - P2PKeyBundle *OCR1Config_P2PKeyBundle `protobuf:"bytes,3,opt,name=p2p_key_bundle,json=p2pKeyBundle,proto3" json:"p2p_key_bundle,omitempty"` - OcrKeyBundle *OCR1Config_OCRKeyBundle `protobuf:"bytes,4,opt,name=ocr_key_bundle,json=ocrKeyBundle,proto3" json:"ocr_key_bundle,omitempty"` - Multiaddr string `protobuf:"bytes,5,opt,name=multiaddr,proto3" json:"multiaddr,omitempty"` -} - -func (x *OCR1Config) Reset() { - *x = OCR1Config{} - if protoimpl.UnsafeEnabled { - mi := &file_node_v1_node_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *OCR1Config) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*OCR1Config) ProtoMessage() {} - -func (x *OCR1Config) ProtoReflect() protoreflect.Message { - mi := &file_node_v1_node_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use OCR1Config.ProtoReflect.Descriptor instead. -func (*OCR1Config) Descriptor() ([]byte, []int) { - return file_node_v1_node_proto_rawDescGZIP(), []int{1} -} - -func (x *OCR1Config) GetEnabled() bool { - if x != nil { - return x.Enabled - } - return false -} - -func (x *OCR1Config) GetIsBootstrap() bool { - if x != nil { - return x.IsBootstrap - } - return false -} - -func (x *OCR1Config) GetP2PKeyBundle() *OCR1Config_P2PKeyBundle { - if x != nil { - return x.P2PKeyBundle - } - return nil -} - -func (x *OCR1Config) GetOcrKeyBundle() *OCR1Config_OCRKeyBundle { - if x != nil { - return x.OcrKeyBundle - } - return nil -} - -func (x *OCR1Config) GetMultiaddr() string { - if x != nil { - return x.Multiaddr - } - return "" -} - -type OCR2Config struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"` - IsBootstrap bool `protobuf:"varint,2,opt,name=is_bootstrap,json=isBootstrap,proto3" json:"is_bootstrap,omitempty"` - P2PKeyBundle *OCR2Config_P2PKeyBundle `protobuf:"bytes,3,opt,name=p2p_key_bundle,json=p2pKeyBundle,proto3" json:"p2p_key_bundle,omitempty"` - OcrKeyBundle *OCR2Config_OCRKeyBundle `protobuf:"bytes,4,opt,name=ocr_key_bundle,json=ocrKeyBundle,proto3" json:"ocr_key_bundle,omitempty"` - Multiaddr string `protobuf:"bytes,5,opt,name=multiaddr,proto3" json:"multiaddr,omitempty"` - Plugins *OCR2Config_Plugins `protobuf:"bytes,6,opt,name=plugins,proto3" json:"plugins,omitempty"` - ForwarderAddress string `protobuf:"bytes,7,opt,name=forwarder_address,json=forwarderAddress,proto3" json:"forwarder_address,omitempty"` -} - -func (x *OCR2Config) Reset() { - *x = OCR2Config{} - if protoimpl.UnsafeEnabled { - mi := &file_node_v1_node_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *OCR2Config) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*OCR2Config) ProtoMessage() {} - -func (x *OCR2Config) ProtoReflect() protoreflect.Message { - mi := &file_node_v1_node_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use OCR2Config.ProtoReflect.Descriptor instead. -func (*OCR2Config) Descriptor() ([]byte, []int) { - return file_node_v1_node_proto_rawDescGZIP(), []int{2} -} - -func (x *OCR2Config) GetEnabled() bool { - if x != nil { - return x.Enabled - } - return false -} - -func (x *OCR2Config) GetIsBootstrap() bool { - if x != nil { - return x.IsBootstrap - } - return false -} - -func (x *OCR2Config) GetP2PKeyBundle() *OCR2Config_P2PKeyBundle { - if x != nil { - return x.P2PKeyBundle - } - return nil -} - -func (x *OCR2Config) GetOcrKeyBundle() *OCR2Config_OCRKeyBundle { - if x != nil { - return x.OcrKeyBundle - } - return nil -} - -func (x *OCR2Config) GetMultiaddr() string { - if x != nil { - return x.Multiaddr - } - return "" -} - -func (x *OCR2Config) GetPlugins() *OCR2Config_Plugins { - if x != nil { - return x.Plugins - } - return nil -} - -func (x *OCR2Config) GetForwarderAddress() string { - if x != nil { - return x.ForwarderAddress - } - return "" -} - -type ChainConfig struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Chain *Chain `protobuf:"bytes,1,opt,name=chain,proto3" json:"chain,omitempty"` - AccountAddress string `protobuf:"bytes,2,opt,name=account_address,json=accountAddress,proto3" json:"account_address,omitempty"` - AdminAddress string `protobuf:"bytes,3,opt,name=admin_address,json=adminAddress,proto3" json:"admin_address,omitempty"` - Ocr1Config *OCR1Config `protobuf:"bytes,4,opt,name=ocr1_config,json=ocr1Config,proto3" json:"ocr1_config,omitempty"` - Ocr2Config *OCR2Config `protobuf:"bytes,5,opt,name=ocr2_config,json=ocr2Config,proto3" json:"ocr2_config,omitempty"` -} - -func (x *ChainConfig) Reset() { - *x = ChainConfig{} - if protoimpl.UnsafeEnabled { - mi := &file_node_v1_node_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ChainConfig) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ChainConfig) ProtoMessage() {} - -func (x *ChainConfig) ProtoReflect() protoreflect.Message { - mi := &file_node_v1_node_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ChainConfig.ProtoReflect.Descriptor instead. -func (*ChainConfig) Descriptor() ([]byte, []int) { - return file_node_v1_node_proto_rawDescGZIP(), []int{3} -} - -func (x *ChainConfig) GetChain() *Chain { - if x != nil { - return x.Chain - } - return nil -} - -func (x *ChainConfig) GetAccountAddress() string { - if x != nil { - return x.AccountAddress - } - return "" -} - -func (x *ChainConfig) GetAdminAddress() string { - if x != nil { - return x.AdminAddress - } - return "" -} - -func (x *ChainConfig) GetOcr1Config() *OCR1Config { - if x != nil { - return x.Ocr1Config - } - return nil -} - -func (x *ChainConfig) GetOcr2Config() *OCR2Config { - if x != nil { - return x.Ocr2Config - } - return nil -} - -// GetNodeRequest is the request to retrieve a single node by its ID. -type GetNodeRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` // Unique identifier of the node to retrieve. -} - -func (x *GetNodeRequest) Reset() { - *x = GetNodeRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_node_v1_node_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetNodeRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetNodeRequest) ProtoMessage() {} - -func (x *GetNodeRequest) ProtoReflect() protoreflect.Message { - mi := &file_node_v1_node_proto_msgTypes[4] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetNodeRequest.ProtoReflect.Descriptor instead. -func (*GetNodeRequest) Descriptor() ([]byte, []int) { - return file_node_v1_node_proto_rawDescGZIP(), []int{4} -} - -func (x *GetNodeRequest) GetId() string { - if x != nil { - return x.Id - } - return "" -} - -// GetNodeResponse is the response containing the requested node. -type GetNodeResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Node *Node `protobuf:"bytes,1,opt,name=node,proto3" json:"node,omitempty"` // Details of the retrieved node. -} - -func (x *GetNodeResponse) Reset() { - *x = GetNodeResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_node_v1_node_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *GetNodeResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetNodeResponse) ProtoMessage() {} - -func (x *GetNodeResponse) ProtoReflect() protoreflect.Message { - mi := &file_node_v1_node_proto_msgTypes[5] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GetNodeResponse.ProtoReflect.Descriptor instead. -func (*GetNodeResponse) Descriptor() ([]byte, []int) { - return file_node_v1_node_proto_rawDescGZIP(), []int{5} -} - -func (x *GetNodeResponse) GetNode() *Node { - if x != nil { - return x.Node - } - return nil -} - -// * -// ListNodesRequest is the request object for the ListNodes method. -// -// Provide a filter to return a subset of data. Nodes can be filtered by: -// - ids - A list of node ids. -// - archived - The archived state of the node. -// - selectors - A list of selectors to filter nodes by their labels. -// -// If no filter is provided, all nodes are returned. -type ListNodesRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Filter *ListNodesRequest_Filter `protobuf:"bytes,1,opt,name=filter,proto3" json:"filter,omitempty"` -} - -func (x *ListNodesRequest) Reset() { - *x = ListNodesRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_node_v1_node_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ListNodesRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ListNodesRequest) ProtoMessage() {} - -func (x *ListNodesRequest) ProtoReflect() protoreflect.Message { - mi := &file_node_v1_node_proto_msgTypes[6] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ListNodesRequest.ProtoReflect.Descriptor instead. -func (*ListNodesRequest) Descriptor() ([]byte, []int) { - return file_node_v1_node_proto_rawDescGZIP(), []int{6} -} - -func (x *ListNodesRequest) GetFilter() *ListNodesRequest_Filter { - if x != nil { - return x.Filter - } - return nil -} - -// * -// ListNodesResponse is the response object for the ListNodes method. -// -// It returns a list of nodes that match the filter criteria. -type ListNodesResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Nodes []*Node `protobuf:"bytes,1,rep,name=nodes,proto3" json:"nodes,omitempty"` // List of nodes. -} - -func (x *ListNodesResponse) Reset() { - *x = ListNodesResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_node_v1_node_proto_msgTypes[7] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ListNodesResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ListNodesResponse) ProtoMessage() {} - -func (x *ListNodesResponse) ProtoReflect() protoreflect.Message { - mi := &file_node_v1_node_proto_msgTypes[7] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ListNodesResponse.ProtoReflect.Descriptor instead. -func (*ListNodesResponse) Descriptor() ([]byte, []int) { - return file_node_v1_node_proto_rawDescGZIP(), []int{7} -} - -func (x *ListNodesResponse) GetNodes() []*Node { - if x != nil { - return x.Nodes - } - return nil -} - -type ListNodeChainConfigsRequest struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Filter *ListNodeChainConfigsRequest_Filter `protobuf:"bytes,1,opt,name=filter,proto3" json:"filter,omitempty"` -} - -func (x *ListNodeChainConfigsRequest) Reset() { - *x = ListNodeChainConfigsRequest{} - if protoimpl.UnsafeEnabled { - mi := &file_node_v1_node_proto_msgTypes[8] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ListNodeChainConfigsRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ListNodeChainConfigsRequest) ProtoMessage() {} - -func (x *ListNodeChainConfigsRequest) ProtoReflect() protoreflect.Message { - mi := &file_node_v1_node_proto_msgTypes[8] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ListNodeChainConfigsRequest.ProtoReflect.Descriptor instead. -func (*ListNodeChainConfigsRequest) Descriptor() ([]byte, []int) { - return file_node_v1_node_proto_rawDescGZIP(), []int{8} -} - -func (x *ListNodeChainConfigsRequest) GetFilter() *ListNodeChainConfigsRequest_Filter { - if x != nil { - return x.Filter - } - return nil -} - -type ListNodeChainConfigsResponse struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - ChainConfigs []*ChainConfig `protobuf:"bytes,1,rep,name=chain_configs,json=chainConfigs,proto3" json:"chain_configs,omitempty"` -} - -func (x *ListNodeChainConfigsResponse) Reset() { - *x = ListNodeChainConfigsResponse{} - if protoimpl.UnsafeEnabled { - mi := &file_node_v1_node_proto_msgTypes[9] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ListNodeChainConfigsResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ListNodeChainConfigsResponse) ProtoMessage() {} - -func (x *ListNodeChainConfigsResponse) ProtoReflect() protoreflect.Message { - mi := &file_node_v1_node_proto_msgTypes[9] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ListNodeChainConfigsResponse.ProtoReflect.Descriptor instead. -func (*ListNodeChainConfigsResponse) Descriptor() ([]byte, []int) { - return file_node_v1_node_proto_rawDescGZIP(), []int{9} -} - -func (x *ListNodeChainConfigsResponse) GetChainConfigs() []*ChainConfig { - if x != nil { - return x.ChainConfigs - } - return nil -} - -type OCR1Config_P2PKeyBundle struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - PeerId string `protobuf:"bytes,1,opt,name=peer_id,json=peerId,proto3" json:"peer_id,omitempty"` - PublicKey string `protobuf:"bytes,2,opt,name=public_key,json=publicKey,proto3" json:"public_key,omitempty"` -} - -func (x *OCR1Config_P2PKeyBundle) Reset() { - *x = OCR1Config_P2PKeyBundle{} - if protoimpl.UnsafeEnabled { - mi := &file_node_v1_node_proto_msgTypes[10] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *OCR1Config_P2PKeyBundle) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*OCR1Config_P2PKeyBundle) ProtoMessage() {} - -func (x *OCR1Config_P2PKeyBundle) ProtoReflect() protoreflect.Message { - mi := &file_node_v1_node_proto_msgTypes[10] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use OCR1Config_P2PKeyBundle.ProtoReflect.Descriptor instead. -func (*OCR1Config_P2PKeyBundle) Descriptor() ([]byte, []int) { - return file_node_v1_node_proto_rawDescGZIP(), []int{1, 0} -} - -func (x *OCR1Config_P2PKeyBundle) GetPeerId() string { - if x != nil { - return x.PeerId - } - return "" -} - -func (x *OCR1Config_P2PKeyBundle) GetPublicKey() string { - if x != nil { - return x.PublicKey - } - return "" -} - -type OCR1Config_OCRKeyBundle struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - BundleId string `protobuf:"bytes,1,opt,name=bundle_id,json=bundleId,proto3" json:"bundle_id,omitempty"` - ConfigPublicKey string `protobuf:"bytes,2,opt,name=config_public_key,json=configPublicKey,proto3" json:"config_public_key,omitempty"` - OffchainPublicKey string `protobuf:"bytes,3,opt,name=offchain_public_key,json=offchainPublicKey,proto3" json:"offchain_public_key,omitempty"` - OnchainSigningAddress string `protobuf:"bytes,4,opt,name=onchain_signing_address,json=onchainSigningAddress,proto3" json:"onchain_signing_address,omitempty"` -} - -func (x *OCR1Config_OCRKeyBundle) Reset() { - *x = OCR1Config_OCRKeyBundle{} - if protoimpl.UnsafeEnabled { - mi := &file_node_v1_node_proto_msgTypes[11] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *OCR1Config_OCRKeyBundle) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*OCR1Config_OCRKeyBundle) ProtoMessage() {} - -func (x *OCR1Config_OCRKeyBundle) ProtoReflect() protoreflect.Message { - mi := &file_node_v1_node_proto_msgTypes[11] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use OCR1Config_OCRKeyBundle.ProtoReflect.Descriptor instead. -func (*OCR1Config_OCRKeyBundle) Descriptor() ([]byte, []int) { - return file_node_v1_node_proto_rawDescGZIP(), []int{1, 1} -} - -func (x *OCR1Config_OCRKeyBundle) GetBundleId() string { - if x != nil { - return x.BundleId - } - return "" -} - -func (x *OCR1Config_OCRKeyBundle) GetConfigPublicKey() string { - if x != nil { - return x.ConfigPublicKey - } - return "" -} - -func (x *OCR1Config_OCRKeyBundle) GetOffchainPublicKey() string { - if x != nil { - return x.OffchainPublicKey - } - return "" -} - -func (x *OCR1Config_OCRKeyBundle) GetOnchainSigningAddress() string { - if x != nil { - return x.OnchainSigningAddress - } - return "" -} - -type OCR2Config_P2PKeyBundle struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - PeerId string `protobuf:"bytes,1,opt,name=peer_id,json=peerId,proto3" json:"peer_id,omitempty"` - PublicKey string `protobuf:"bytes,2,opt,name=public_key,json=publicKey,proto3" json:"public_key,omitempty"` -} - -func (x *OCR2Config_P2PKeyBundle) Reset() { - *x = OCR2Config_P2PKeyBundle{} - if protoimpl.UnsafeEnabled { - mi := &file_node_v1_node_proto_msgTypes[12] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *OCR2Config_P2PKeyBundle) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*OCR2Config_P2PKeyBundle) ProtoMessage() {} - -func (x *OCR2Config_P2PKeyBundle) ProtoReflect() protoreflect.Message { - mi := &file_node_v1_node_proto_msgTypes[12] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use OCR2Config_P2PKeyBundle.ProtoReflect.Descriptor instead. -func (*OCR2Config_P2PKeyBundle) Descriptor() ([]byte, []int) { - return file_node_v1_node_proto_rawDescGZIP(), []int{2, 0} -} - -func (x *OCR2Config_P2PKeyBundle) GetPeerId() string { - if x != nil { - return x.PeerId - } - return "" -} - -func (x *OCR2Config_P2PKeyBundle) GetPublicKey() string { - if x != nil { - return x.PublicKey - } - return "" -} - -type OCR2Config_OCRKeyBundle struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - BundleId string `protobuf:"bytes,1,opt,name=bundle_id,json=bundleId,proto3" json:"bundle_id,omitempty"` - ConfigPublicKey string `protobuf:"bytes,2,opt,name=config_public_key,json=configPublicKey,proto3" json:"config_public_key,omitempty"` - OffchainPublicKey string `protobuf:"bytes,3,opt,name=offchain_public_key,json=offchainPublicKey,proto3" json:"offchain_public_key,omitempty"` - OnchainSigningAddress string `protobuf:"bytes,4,opt,name=onchain_signing_address,json=onchainSigningAddress,proto3" json:"onchain_signing_address,omitempty"` -} - -func (x *OCR2Config_OCRKeyBundle) Reset() { - *x = OCR2Config_OCRKeyBundle{} - if protoimpl.UnsafeEnabled { - mi := &file_node_v1_node_proto_msgTypes[13] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *OCR2Config_OCRKeyBundle) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*OCR2Config_OCRKeyBundle) ProtoMessage() {} - -func (x *OCR2Config_OCRKeyBundle) ProtoReflect() protoreflect.Message { - mi := &file_node_v1_node_proto_msgTypes[13] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use OCR2Config_OCRKeyBundle.ProtoReflect.Descriptor instead. -func (*OCR2Config_OCRKeyBundle) Descriptor() ([]byte, []int) { - return file_node_v1_node_proto_rawDescGZIP(), []int{2, 1} -} - -func (x *OCR2Config_OCRKeyBundle) GetBundleId() string { - if x != nil { - return x.BundleId - } - return "" -} - -func (x *OCR2Config_OCRKeyBundle) GetConfigPublicKey() string { - if x != nil { - return x.ConfigPublicKey - } - return "" -} - -func (x *OCR2Config_OCRKeyBundle) GetOffchainPublicKey() string { - if x != nil { - return x.OffchainPublicKey - } - return "" -} - -func (x *OCR2Config_OCRKeyBundle) GetOnchainSigningAddress() string { - if x != nil { - return x.OnchainSigningAddress - } - return "" -} - -type OCR2Config_Plugins struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Commit bool `protobuf:"varint,1,opt,name=commit,proto3" json:"commit,omitempty"` - Execute bool `protobuf:"varint,2,opt,name=execute,proto3" json:"execute,omitempty"` - Median bool `protobuf:"varint,3,opt,name=median,proto3" json:"median,omitempty"` - Mercury bool `protobuf:"varint,4,opt,name=mercury,proto3" json:"mercury,omitempty"` - Rebalancer bool `protobuf:"varint,5,opt,name=rebalancer,proto3" json:"rebalancer,omitempty"` -} - -func (x *OCR2Config_Plugins) Reset() { - *x = OCR2Config_Plugins{} - if protoimpl.UnsafeEnabled { - mi := &file_node_v1_node_proto_msgTypes[14] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *OCR2Config_Plugins) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*OCR2Config_Plugins) ProtoMessage() {} - -func (x *OCR2Config_Plugins) ProtoReflect() protoreflect.Message { - mi := &file_node_v1_node_proto_msgTypes[14] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use OCR2Config_Plugins.ProtoReflect.Descriptor instead. -func (*OCR2Config_Plugins) Descriptor() ([]byte, []int) { - return file_node_v1_node_proto_rawDescGZIP(), []int{2, 2} -} - -func (x *OCR2Config_Plugins) GetCommit() bool { - if x != nil { - return x.Commit - } - return false -} - -func (x *OCR2Config_Plugins) GetExecute() bool { - if x != nil { - return x.Execute - } - return false -} - -func (x *OCR2Config_Plugins) GetMedian() bool { - if x != nil { - return x.Median - } - return false -} - -func (x *OCR2Config_Plugins) GetMercury() bool { - if x != nil { - return x.Mercury - } - return false -} - -func (x *OCR2Config_Plugins) GetRebalancer() bool { - if x != nil { - return x.Rebalancer - } - return false -} - -type ListNodesRequest_Filter struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Ids []string `protobuf:"bytes,1,rep,name=ids,proto3" json:"ids,omitempty"` - Archived ArchiveState `protobuf:"varint,2,opt,name=archived,proto3,enum=api.node.v1.ArchiveState" json:"archived,omitempty"` - Selectors []*ptypes.Selector `protobuf:"bytes,3,rep,name=selectors,proto3" json:"selectors,omitempty"` -} - -func (x *ListNodesRequest_Filter) Reset() { - *x = ListNodesRequest_Filter{} - if protoimpl.UnsafeEnabled { - mi := &file_node_v1_node_proto_msgTypes[15] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ListNodesRequest_Filter) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ListNodesRequest_Filter) ProtoMessage() {} - -func (x *ListNodesRequest_Filter) ProtoReflect() protoreflect.Message { - mi := &file_node_v1_node_proto_msgTypes[15] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ListNodesRequest_Filter.ProtoReflect.Descriptor instead. -func (*ListNodesRequest_Filter) Descriptor() ([]byte, []int) { - return file_node_v1_node_proto_rawDescGZIP(), []int{6, 0} -} - -func (x *ListNodesRequest_Filter) GetIds() []string { - if x != nil { - return x.Ids - } - return nil -} - -func (x *ListNodesRequest_Filter) GetArchived() ArchiveState { - if x != nil { - return x.Archived - } - return ArchiveState_ARCHIVE_STATE_UNSPECIFIED -} - -func (x *ListNodesRequest_Filter) GetSelectors() []*ptypes.Selector { - if x != nil { - return x.Selectors - } - return nil -} - -type ListNodeChainConfigsRequest_Filter struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - NodeId string `protobuf:"bytes,1,opt,name=node_id,json=nodeId,proto3" json:"node_id,omitempty"` -} - -func (x *ListNodeChainConfigsRequest_Filter) Reset() { - *x = ListNodeChainConfigsRequest_Filter{} - if protoimpl.UnsafeEnabled { - mi := &file_node_v1_node_proto_msgTypes[16] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ListNodeChainConfigsRequest_Filter) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ListNodeChainConfigsRequest_Filter) ProtoMessage() {} - -func (x *ListNodeChainConfigsRequest_Filter) ProtoReflect() protoreflect.Message { - mi := &file_node_v1_node_proto_msgTypes[16] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ListNodeChainConfigsRequest_Filter.ProtoReflect.Descriptor instead. -func (*ListNodeChainConfigsRequest_Filter) Descriptor() ([]byte, []int) { - return file_node_v1_node_proto_rawDescGZIP(), []int{8, 0} -} - -func (x *ListNodeChainConfigsRequest_Filter) GetNodeId() string { - if x != nil { - return x.NodeId - } - return "" -} - -var File_node_v1_node_proto protoreflect.FileDescriptor - -var file_node_v1_node_proto_rawDesc = []byte{ - 0x0a, 0x12, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0b, 0x61, 0x70, 0x69, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, - 0x31, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x1a, 0x14, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x68, 0x61, 0x72, - 0x65, 0x64, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x19, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, - 0x2f, 0x70, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x22, 0x43, 0x0a, 0x05, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x12, 0x0e, 0x0a, 0x02, - 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x2a, 0x0a, 0x04, - 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x16, 0x2e, 0x61, 0x70, 0x69, - 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x54, 0x79, - 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x22, 0x89, 0x04, 0x0a, 0x0a, 0x4f, 0x43, 0x52, - 0x31, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, - 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, - 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x73, 0x5f, 0x62, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, - 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x73, 0x42, 0x6f, 0x6f, 0x74, 0x73, - 0x74, 0x72, 0x61, 0x70, 0x12, 0x4a, 0x0a, 0x0e, 0x70, 0x32, 0x70, 0x5f, 0x6b, 0x65, 0x79, 0x5f, - 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x61, - 0x70, 0x69, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x43, 0x52, 0x31, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x50, 0x32, 0x50, 0x4b, 0x65, 0x79, 0x42, 0x75, 0x6e, 0x64, - 0x6c, 0x65, 0x52, 0x0c, 0x70, 0x32, 0x70, 0x4b, 0x65, 0x79, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, - 0x12, 0x4a, 0x0a, 0x0e, 0x6f, 0x63, 0x72, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x62, 0x75, 0x6e, 0x64, - 0x6c, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x6e, - 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x43, 0x52, 0x31, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x2e, 0x4f, 0x43, 0x52, 0x4b, 0x65, 0x79, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x0c, - 0x6f, 0x63, 0x72, 0x4b, 0x65, 0x79, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x12, 0x1c, 0x0a, 0x09, - 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x61, 0x64, 0x64, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x09, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x61, 0x64, 0x64, 0x72, 0x1a, 0x46, 0x0a, 0x0c, 0x50, 0x32, - 0x50, 0x4b, 0x65, 0x79, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x70, 0x65, - 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x65, 0x65, - 0x72, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, - 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, - 0x65, 0x79, 0x1a, 0xbf, 0x01, 0x0a, 0x0c, 0x4f, 0x43, 0x52, 0x4b, 0x65, 0x79, 0x42, 0x75, 0x6e, - 0x64, 0x6c, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x5f, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x49, 0x64, - 0x12, 0x2a, 0x0a, 0x11, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, - 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x63, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x2e, 0x0a, 0x13, - 0x6f, 0x66, 0x66, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, - 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x6f, 0x66, 0x66, 0x63, 0x68, - 0x61, 0x69, 0x6e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x36, 0x0a, 0x17, - 0x6f, 0x6e, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x5f, - 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x15, 0x6f, - 0x6e, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x41, 0x64, 0x64, - 0x72, 0x65, 0x73, 0x73, 0x22, 0x81, 0x06, 0x0a, 0x0a, 0x4f, 0x43, 0x52, 0x32, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x21, 0x0a, - 0x0c, 0x69, 0x73, 0x5f, 0x62, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x73, 0x42, 0x6f, 0x6f, 0x74, 0x73, 0x74, 0x72, 0x61, 0x70, - 0x12, 0x4a, 0x0a, 0x0e, 0x70, 0x32, 0x70, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x62, 0x75, 0x6e, 0x64, - 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x6e, - 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x43, 0x52, 0x32, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x2e, 0x50, 0x32, 0x50, 0x4b, 0x65, 0x79, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x0c, - 0x70, 0x32, 0x70, 0x4b, 0x65, 0x79, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x12, 0x4a, 0x0a, 0x0e, - 0x6f, 0x63, 0x72, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, - 0x76, 0x31, 0x2e, 0x4f, 0x43, 0x52, 0x32, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x4f, 0x43, - 0x52, 0x4b, 0x65, 0x79, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x0c, 0x6f, 0x63, 0x72, 0x4b, - 0x65, 0x79, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x6d, 0x75, 0x6c, 0x74, - 0x69, 0x61, 0x64, 0x64, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6d, 0x75, 0x6c, - 0x74, 0x69, 0x61, 0x64, 0x64, 0x72, 0x12, 0x39, 0x0a, 0x07, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, - 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x6e, 0x6f, - 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x43, 0x52, 0x32, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x2e, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x52, 0x07, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, - 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x66, 0x6f, 0x72, 0x77, 0x61, 0x72, 0x64, 0x65, 0x72, 0x5f, 0x61, - 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x66, 0x6f, - 0x72, 0x77, 0x61, 0x72, 0x64, 0x65, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x1a, 0x46, - 0x0a, 0x0c, 0x50, 0x32, 0x50, 0x4b, 0x65, 0x79, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x12, 0x17, - 0x0a, 0x07, 0x70, 0x65, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x06, 0x70, 0x65, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, - 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x75, 0x62, - 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x1a, 0xbf, 0x01, 0x0a, 0x0c, 0x4f, 0x43, 0x52, 0x4b, 0x65, - 0x79, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x62, 0x75, 0x6e, 0x64, 0x6c, - 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x62, 0x75, 0x6e, 0x64, - 0x6c, 0x65, 0x49, 0x64, 0x12, 0x2a, 0x0a, 0x11, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x70, - 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, - 0x12, 0x2e, 0x0a, 0x13, 0x6f, 0x66, 0x66, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x70, 0x75, 0x62, - 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x6f, - 0x66, 0x66, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, - 0x12, 0x36, 0x0a, 0x17, 0x6f, 0x6e, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x73, 0x69, 0x67, 0x6e, - 0x69, 0x6e, 0x67, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x15, 0x6f, 0x6e, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, - 0x67, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x1a, 0x8d, 0x01, 0x0a, 0x07, 0x50, 0x6c, 0x75, - 0x67, 0x69, 0x6e, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x12, 0x18, 0x0a, 0x07, - 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, - 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x6e, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x6e, 0x12, 0x18, - 0x0a, 0x07, 0x6d, 0x65, 0x72, 0x63, 0x75, 0x72, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x07, 0x6d, 0x65, 0x72, 0x63, 0x75, 0x72, 0x79, 0x12, 0x1e, 0x0a, 0x0a, 0x72, 0x65, 0x62, 0x61, - 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x72, 0x65, - 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x22, 0xf9, 0x01, 0x0a, 0x0b, 0x43, 0x68, 0x61, - 0x69, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x28, 0x0a, 0x05, 0x63, 0x68, 0x61, 0x69, - 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x6e, 0x6f, - 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x52, 0x05, 0x63, 0x68, 0x61, - 0x69, 0x6e, 0x12, 0x27, 0x0a, 0x0f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x61, 0x64, - 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x61, 0x63, 0x63, - 0x6f, 0x75, 0x6e, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x61, - 0x64, 0x6d, 0x69, 0x6e, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0c, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x12, 0x38, 0x0a, 0x0b, 0x6f, 0x63, 0x72, 0x31, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x6e, 0x6f, 0x64, 0x65, - 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x43, 0x52, 0x31, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0a, - 0x6f, 0x63, 0x72, 0x31, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x38, 0x0a, 0x0b, 0x6f, 0x63, - 0x72, 0x32, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x17, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x43, - 0x52, 0x32, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0a, 0x6f, 0x63, 0x72, 0x32, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x22, 0x20, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x38, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x64, - 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x25, 0x0a, 0x04, 0x6e, 0x6f, 0x64, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x6e, 0x6f, - 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x6e, 0x6f, 0x64, 0x65, - 0x22, 0xd7, 0x01, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3c, 0x0a, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x6e, 0x6f, 0x64, 0x65, - 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x2e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x06, 0x66, 0x69, 0x6c, - 0x74, 0x65, 0x72, 0x1a, 0x84, 0x01, 0x0a, 0x06, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x10, - 0x0a, 0x03, 0x69, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x03, 0x69, 0x64, 0x73, - 0x12, 0x35, 0x0a, 0x08, 0x61, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0e, 0x32, 0x19, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, - 0x2e, 0x41, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x08, 0x61, - 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x64, 0x12, 0x31, 0x0a, 0x09, 0x73, 0x65, 0x6c, 0x65, 0x63, - 0x74, 0x6f, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x61, 0x70, 0x69, - 0x2e, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x2e, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x52, - 0x09, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x22, 0x3c, 0x0a, 0x11, 0x4c, 0x69, - 0x73, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x27, 0x0a, 0x05, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, - 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x64, - 0x65, 0x52, 0x05, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x22, 0x89, 0x01, 0x0a, 0x1b, 0x4c, 0x69, 0x73, - 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x47, 0x0a, 0x06, 0x66, 0x69, 0x6c, 0x74, - 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x6e, - 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x43, - 0x68, 0x61, 0x69, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x2e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, - 0x72, 0x1a, 0x21, 0x0a, 0x06, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x17, 0x0a, 0x07, 0x6e, - 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6e, 0x6f, - 0x64, 0x65, 0x49, 0x64, 0x22, 0x5d, 0x0a, 0x1c, 0x4c, 0x69, 0x73, 0x74, 0x4e, 0x6f, 0x64, 0x65, - 0x43, 0x68, 0x61, 0x69, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3d, 0x0a, 0x0d, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x63, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x61, 0x70, - 0x69, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0c, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x43, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x73, 0x2a, 0x52, 0x0a, 0x09, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x54, 0x79, 0x70, 0x65, - 0x12, 0x1a, 0x0a, 0x16, 0x43, 0x48, 0x41, 0x49, 0x4e, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, - 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x12, 0x0a, 0x0e, - 0x43, 0x48, 0x41, 0x49, 0x4e, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x45, 0x56, 0x4d, 0x10, 0x01, - 0x12, 0x15, 0x0a, 0x11, 0x43, 0x48, 0x41, 0x49, 0x4e, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, - 0x4f, 0x4c, 0x41, 0x4e, 0x41, 0x10, 0x02, 0x2a, 0x63, 0x0a, 0x0c, 0x41, 0x72, 0x63, 0x68, 0x69, - 0x76, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x1d, 0x0a, 0x19, 0x41, 0x52, 0x43, 0x48, 0x49, - 0x56, 0x45, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, - 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1a, 0x0a, 0x16, 0x41, 0x52, 0x43, 0x48, 0x49, 0x56, - 0x45, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x41, 0x52, 0x43, 0x48, 0x49, 0x56, 0x45, 0x44, - 0x10, 0x01, 0x12, 0x18, 0x0a, 0x14, 0x41, 0x52, 0x43, 0x48, 0x49, 0x56, 0x45, 0x5f, 0x53, 0x54, - 0x41, 0x54, 0x45, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x10, 0x02, 0x32, 0x92, 0x02, 0x0a, - 0x0b, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x46, 0x0a, 0x07, - 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x1b, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x6e, 0x6f, - 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, - 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x00, 0x12, 0x4c, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x4e, 0x6f, 0x64, 0x65, - 0x73, 0x12, 0x1d, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, - 0x4c, 0x69, 0x73, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x1e, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, - 0x69, 0x73, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x00, 0x12, 0x6d, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x43, 0x68, - 0x61, 0x69, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x12, 0x28, 0x2e, 0x61, 0x70, 0x69, - 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4e, 0x6f, 0x64, - 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x6e, 0x6f, 0x64, 0x65, 0x2e, - 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4e, 0x6f, 0x64, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x00, 0x42, 0x09, 0x5a, 0x07, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_node_v1_node_proto_rawDescOnce sync.Once - file_node_v1_node_proto_rawDescData = file_node_v1_node_proto_rawDesc -) - -func file_node_v1_node_proto_rawDescGZIP() []byte { - file_node_v1_node_proto_rawDescOnce.Do(func() { - file_node_v1_node_proto_rawDescData = protoimpl.X.CompressGZIP(file_node_v1_node_proto_rawDescData) - }) - return file_node_v1_node_proto_rawDescData -} - -var file_node_v1_node_proto_enumTypes = make([]protoimpl.EnumInfo, 2) -var file_node_v1_node_proto_msgTypes = make([]protoimpl.MessageInfo, 17) -var file_node_v1_node_proto_goTypes = []interface{}{ - (ChainType)(0), // 0: api.node.v1.ChainType - (ArchiveState)(0), // 1: api.node.v1.ArchiveState - (*Chain)(nil), // 2: api.node.v1.Chain - (*OCR1Config)(nil), // 3: api.node.v1.OCR1Config - (*OCR2Config)(nil), // 4: api.node.v1.OCR2Config - (*ChainConfig)(nil), // 5: api.node.v1.ChainConfig - (*GetNodeRequest)(nil), // 6: api.node.v1.GetNodeRequest - (*GetNodeResponse)(nil), // 7: api.node.v1.GetNodeResponse - (*ListNodesRequest)(nil), // 8: api.node.v1.ListNodesRequest - (*ListNodesResponse)(nil), // 9: api.node.v1.ListNodesResponse - (*ListNodeChainConfigsRequest)(nil), // 10: api.node.v1.ListNodeChainConfigsRequest - (*ListNodeChainConfigsResponse)(nil), // 11: api.node.v1.ListNodeChainConfigsResponse - (*OCR1Config_P2PKeyBundle)(nil), // 12: api.node.v1.OCR1Config.P2PKeyBundle - (*OCR1Config_OCRKeyBundle)(nil), // 13: api.node.v1.OCR1Config.OCRKeyBundle - (*OCR2Config_P2PKeyBundle)(nil), // 14: api.node.v1.OCR2Config.P2PKeyBundle - (*OCR2Config_OCRKeyBundle)(nil), // 15: api.node.v1.OCR2Config.OCRKeyBundle - (*OCR2Config_Plugins)(nil), // 16: api.node.v1.OCR2Config.Plugins - (*ListNodesRequest_Filter)(nil), // 17: api.node.v1.ListNodesRequest.Filter - (*ListNodeChainConfigsRequest_Filter)(nil), // 18: api.node.v1.ListNodeChainConfigsRequest.Filter - (*Node)(nil), // 19: api.node.v1.Node - (*ptypes.Selector)(nil), // 20: api.label.Selector -} -var file_node_v1_node_proto_depIdxs = []int32{ - 0, // 0: api.node.v1.Chain.type:type_name -> api.node.v1.ChainType - 12, // 1: api.node.v1.OCR1Config.p2p_key_bundle:type_name -> api.node.v1.OCR1Config.P2PKeyBundle - 13, // 2: api.node.v1.OCR1Config.ocr_key_bundle:type_name -> api.node.v1.OCR1Config.OCRKeyBundle - 14, // 3: api.node.v1.OCR2Config.p2p_key_bundle:type_name -> api.node.v1.OCR2Config.P2PKeyBundle - 15, // 4: api.node.v1.OCR2Config.ocr_key_bundle:type_name -> api.node.v1.OCR2Config.OCRKeyBundle - 16, // 5: api.node.v1.OCR2Config.plugins:type_name -> api.node.v1.OCR2Config.Plugins - 2, // 6: api.node.v1.ChainConfig.chain:type_name -> api.node.v1.Chain - 3, // 7: api.node.v1.ChainConfig.ocr1_config:type_name -> api.node.v1.OCR1Config - 4, // 8: api.node.v1.ChainConfig.ocr2_config:type_name -> api.node.v1.OCR2Config - 19, // 9: api.node.v1.GetNodeResponse.node:type_name -> api.node.v1.Node - 17, // 10: api.node.v1.ListNodesRequest.filter:type_name -> api.node.v1.ListNodesRequest.Filter - 19, // 11: api.node.v1.ListNodesResponse.nodes:type_name -> api.node.v1.Node - 18, // 12: api.node.v1.ListNodeChainConfigsRequest.filter:type_name -> api.node.v1.ListNodeChainConfigsRequest.Filter - 5, // 13: api.node.v1.ListNodeChainConfigsResponse.chain_configs:type_name -> api.node.v1.ChainConfig - 1, // 14: api.node.v1.ListNodesRequest.Filter.archived:type_name -> api.node.v1.ArchiveState - 20, // 15: api.node.v1.ListNodesRequest.Filter.selectors:type_name -> api.label.Selector - 6, // 16: api.node.v1.NodeService.GetNode:input_type -> api.node.v1.GetNodeRequest - 8, // 17: api.node.v1.NodeService.ListNodes:input_type -> api.node.v1.ListNodesRequest - 10, // 18: api.node.v1.NodeService.ListNodeChainConfigs:input_type -> api.node.v1.ListNodeChainConfigsRequest - 7, // 19: api.node.v1.NodeService.GetNode:output_type -> api.node.v1.GetNodeResponse - 9, // 20: api.node.v1.NodeService.ListNodes:output_type -> api.node.v1.ListNodesResponse - 11, // 21: api.node.v1.NodeService.ListNodeChainConfigs:output_type -> api.node.v1.ListNodeChainConfigsResponse - 19, // [19:22] is the sub-list for method output_type - 16, // [16:19] is the sub-list for method input_type - 16, // [16:16] is the sub-list for extension type_name - 16, // [16:16] is the sub-list for extension extendee - 0, // [0:16] is the sub-list for field type_name -} - -func init() { file_node_v1_node_proto_init() } -func file_node_v1_node_proto_init() { - if File_node_v1_node_proto != nil { - return - } - file_node_v1_shared_proto_init() - if !protoimpl.UnsafeEnabled { - file_node_v1_node_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Chain); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_node_v1_node_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*OCR1Config); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_node_v1_node_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*OCR2Config); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_node_v1_node_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ChainConfig); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_node_v1_node_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetNodeRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_node_v1_node_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetNodeResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_node_v1_node_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListNodesRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_node_v1_node_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListNodesResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_node_v1_node_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListNodeChainConfigsRequest); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_node_v1_node_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListNodeChainConfigsResponse); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_node_v1_node_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*OCR1Config_P2PKeyBundle); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_node_v1_node_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*OCR1Config_OCRKeyBundle); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_node_v1_node_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*OCR2Config_P2PKeyBundle); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_node_v1_node_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*OCR2Config_OCRKeyBundle); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_node_v1_node_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*OCR2Config_Plugins); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_node_v1_node_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListNodesRequest_Filter); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_node_v1_node_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ListNodeChainConfigsRequest_Filter); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_node_v1_node_proto_rawDesc, - NumEnums: 2, - NumMessages: 17, - NumExtensions: 0, - NumServices: 1, - }, - GoTypes: file_node_v1_node_proto_goTypes, - DependencyIndexes: file_node_v1_node_proto_depIdxs, - EnumInfos: file_node_v1_node_proto_enumTypes, - MessageInfos: file_node_v1_node_proto_msgTypes, - }.Build() - File_node_v1_node_proto = out.File - file_node_v1_node_proto_rawDesc = nil - file_node_v1_node_proto_goTypes = nil - file_node_v1_node_proto_depIdxs = nil -} diff --git a/integration-tests/deployment/jd/node/v1/node_grpc.pb.go b/integration-tests/deployment/jd/node/v1/node_grpc.pb.go deleted file mode 100644 index 5fc0c505ee..0000000000 --- a/integration-tests/deployment/jd/node/v1/node_grpc.pb.go +++ /dev/null @@ -1,187 +0,0 @@ -// Code generated by protoc-gen-go-grpc. DO NOT EDIT. -// versions: -// - protoc-gen-go-grpc v1.3.0 -// - protoc v4.25.3 -// source: node/v1/node.proto - -package v1 - -import ( - context "context" - grpc "google.golang.org/grpc" - codes "google.golang.org/grpc/codes" - status "google.golang.org/grpc/status" -) - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the grpc package it is being compiled against. -// Requires gRPC-Go v1.32.0 or later. -const _ = grpc.SupportPackageIsVersion7 - -const ( - NodeService_GetNode_FullMethodName = "/api.node.v1.NodeService/GetNode" - NodeService_ListNodes_FullMethodName = "/api.node.v1.NodeService/ListNodes" - NodeService_ListNodeChainConfigs_FullMethodName = "/api.node.v1.NodeService/ListNodeChainConfigs" -) - -// NodeServiceClient is the client API for NodeService service. -// -// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. -type NodeServiceClient interface { - // GetNode retrieves the details of a node by its unique identifier. - GetNode(ctx context.Context, in *GetNodeRequest, opts ...grpc.CallOption) (*GetNodeResponse, error) - // ListNodes returns a list of nodes, optionally filtered by the provided criteria. - ListNodes(ctx context.Context, in *ListNodesRequest, opts ...grpc.CallOption) (*ListNodesResponse, error) - ListNodeChainConfigs(ctx context.Context, in *ListNodeChainConfigsRequest, opts ...grpc.CallOption) (*ListNodeChainConfigsResponse, error) -} - -type nodeServiceClient struct { - cc grpc.ClientConnInterface -} - -func NewNodeServiceClient(cc grpc.ClientConnInterface) NodeServiceClient { - return &nodeServiceClient{cc} -} - -func (c *nodeServiceClient) GetNode(ctx context.Context, in *GetNodeRequest, opts ...grpc.CallOption) (*GetNodeResponse, error) { - out := new(GetNodeResponse) - err := c.cc.Invoke(ctx, NodeService_GetNode_FullMethodName, in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *nodeServiceClient) ListNodes(ctx context.Context, in *ListNodesRequest, opts ...grpc.CallOption) (*ListNodesResponse, error) { - out := new(ListNodesResponse) - err := c.cc.Invoke(ctx, NodeService_ListNodes_FullMethodName, in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *nodeServiceClient) ListNodeChainConfigs(ctx context.Context, in *ListNodeChainConfigsRequest, opts ...grpc.CallOption) (*ListNodeChainConfigsResponse, error) { - out := new(ListNodeChainConfigsResponse) - err := c.cc.Invoke(ctx, NodeService_ListNodeChainConfigs_FullMethodName, in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -// NodeServiceServer is the server API for NodeService service. -// All implementations must embed UnimplementedNodeServiceServer -// for forward compatibility -type NodeServiceServer interface { - // GetNode retrieves the details of a node by its unique identifier. - GetNode(context.Context, *GetNodeRequest) (*GetNodeResponse, error) - // ListNodes returns a list of nodes, optionally filtered by the provided criteria. - ListNodes(context.Context, *ListNodesRequest) (*ListNodesResponse, error) - ListNodeChainConfigs(context.Context, *ListNodeChainConfigsRequest) (*ListNodeChainConfigsResponse, error) - mustEmbedUnimplementedNodeServiceServer() -} - -// UnimplementedNodeServiceServer must be embedded to have forward compatible implementations. -type UnimplementedNodeServiceServer struct { -} - -func (UnimplementedNodeServiceServer) GetNode(context.Context, *GetNodeRequest) (*GetNodeResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method GetNode not implemented") -} -func (UnimplementedNodeServiceServer) ListNodes(context.Context, *ListNodesRequest) (*ListNodesResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method ListNodes not implemented") -} -func (UnimplementedNodeServiceServer) ListNodeChainConfigs(context.Context, *ListNodeChainConfigsRequest) (*ListNodeChainConfigsResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method ListNodeChainConfigs not implemented") -} -func (UnimplementedNodeServiceServer) mustEmbedUnimplementedNodeServiceServer() {} - -// UnsafeNodeServiceServer may be embedded to opt out of forward compatibility for this service. -// Use of this interface is not recommended, as added methods to NodeServiceServer will -// result in compilation errors. -type UnsafeNodeServiceServer interface { - mustEmbedUnimplementedNodeServiceServer() -} - -func RegisterNodeServiceServer(s grpc.ServiceRegistrar, srv NodeServiceServer) { - s.RegisterService(&NodeService_ServiceDesc, srv) -} - -func _NodeService_GetNode_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(GetNodeRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(NodeServiceServer).GetNode(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: NodeService_GetNode_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(NodeServiceServer).GetNode(ctx, req.(*GetNodeRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _NodeService_ListNodes_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(ListNodesRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(NodeServiceServer).ListNodes(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: NodeService_ListNodes_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(NodeServiceServer).ListNodes(ctx, req.(*ListNodesRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _NodeService_ListNodeChainConfigs_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(ListNodeChainConfigsRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(NodeServiceServer).ListNodeChainConfigs(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: NodeService_ListNodeChainConfigs_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(NodeServiceServer).ListNodeChainConfigs(ctx, req.(*ListNodeChainConfigsRequest)) - } - return interceptor(ctx, in, info, handler) -} - -// NodeService_ServiceDesc is the grpc.ServiceDesc for NodeService service. -// It's only intended for direct use with grpc.RegisterService, -// and not to be introspected or modified (even as a copy) -var NodeService_ServiceDesc = grpc.ServiceDesc{ - ServiceName: "api.node.v1.NodeService", - HandlerType: (*NodeServiceServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "GetNode", - Handler: _NodeService_GetNode_Handler, - }, - { - MethodName: "ListNodes", - Handler: _NodeService_ListNodes_Handler, - }, - { - MethodName: "ListNodeChainConfigs", - Handler: _NodeService_ListNodeChainConfigs_Handler, - }, - }, - Streams: []grpc.StreamDesc{}, - Metadata: "node/v1/node.proto", -} diff --git a/integration-tests/deployment/jd/node/v1/shared.pb.go b/integration-tests/deployment/jd/node/v1/shared.pb.go deleted file mode 100644 index 4099dd6bd7..0000000000 --- a/integration-tests/deployment/jd/node/v1/shared.pb.go +++ /dev/null @@ -1,239 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.29.0 -// protoc v4.25.3 -// source: node/v1/shared.proto - -package v1 - -import ( - "github.com/smartcontractkit/chainlink/integration-tests/deployment/jd/shared/ptypes" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - timestamppb "google.golang.org/protobuf/types/known/timestamppb" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// Node represents a node within the Job Distributor system. -type Node struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` // Unique identifier for the node. - Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` // Human-readable name for the node. - PublicKey string `protobuf:"bytes,3,opt,name=public_key,json=publicKey,proto3" json:"public_key,omitempty"` // Public key used for secure communications. - IsEnabled bool `protobuf:"varint,4,opt,name=is_enabled,json=isEnabled,proto3" json:"is_enabled,omitempty"` // Indicates if the node is currently enabled. - IsConnected bool `protobuf:"varint,5,opt,name=is_connected,json=isConnected,proto3" json:"is_connected,omitempty"` // Indicates if the node is currently connected to the network. - Labels []*ptypes.Label `protobuf:"bytes,6,rep,name=labels,proto3" json:"labels,omitempty"` // Set of labels associated with the node. - CreatedAt *timestamppb.Timestamp `protobuf:"bytes,7,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"` // Timestamp when the node was created. - UpdatedAt *timestamppb.Timestamp `protobuf:"bytes,8,opt,name=updated_at,json=updatedAt,proto3" json:"updated_at,omitempty"` // Timestamp when the node was last updated. - ArchivedAt *timestamppb.Timestamp `protobuf:"bytes,9,opt,name=archived_at,json=archivedAt,proto3" json:"archived_at,omitempty"` // Timestamp when the node was archived. -} - -func (x *Node) Reset() { - *x = Node{} - if protoimpl.UnsafeEnabled { - mi := &file_node_v1_shared_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Node) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Node) ProtoMessage() {} - -func (x *Node) ProtoReflect() protoreflect.Message { - mi := &file_node_v1_shared_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Node.ProtoReflect.Descriptor instead. -func (*Node) Descriptor() ([]byte, []int) { - return file_node_v1_shared_proto_rawDescGZIP(), []int{0} -} - -func (x *Node) GetId() string { - if x != nil { - return x.Id - } - return "" -} - -func (x *Node) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (x *Node) GetPublicKey() string { - if x != nil { - return x.PublicKey - } - return "" -} - -func (x *Node) GetIsEnabled() bool { - if x != nil { - return x.IsEnabled - } - return false -} - -func (x *Node) GetIsConnected() bool { - if x != nil { - return x.IsConnected - } - return false -} - -func (x *Node) GetLabels() []*ptypes.Label { - if x != nil { - return x.Labels - } - return nil -} - -func (x *Node) GetCreatedAt() *timestamppb.Timestamp { - if x != nil { - return x.CreatedAt - } - return nil -} - -func (x *Node) GetUpdatedAt() *timestamppb.Timestamp { - if x != nil { - return x.UpdatedAt - } - return nil -} - -func (x *Node) GetArchivedAt() *timestamppb.Timestamp { - if x != nil { - return x.ArchivedAt - } - return nil -} - -var File_node_v1_shared_proto protoreflect.FileDescriptor - -var file_node_v1_shared_proto_rawDesc = []byte{ - 0x0a, 0x14, 0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0b, 0x61, 0x70, 0x69, 0x2e, 0x6e, 0x6f, 0x64, 0x65, - 0x2e, 0x76, 0x31, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x19, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x2f, 0x70, 0x74, 0x79, - 0x70, 0x65, 0x73, 0x2f, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, - 0xe8, 0x02, 0x0a, 0x04, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, - 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x1d, 0x0a, 0x0a, 0x69, - 0x73, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x09, 0x69, 0x73, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x73, - 0x5f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x0b, 0x69, 0x73, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x12, 0x28, 0x0a, - 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, - 0x61, 0x70, 0x69, 0x2e, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x52, - 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, - 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, - 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, - 0x41, 0x74, 0x12, 0x39, 0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, - 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, - 0x6d, 0x70, 0x52, 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x3b, 0x0a, - 0x0b, 0x61, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x09, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, - 0x61, 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x64, 0x41, 0x74, 0x42, 0x09, 0x5a, 0x07, 0x6e, 0x6f, - 0x64, 0x65, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_node_v1_shared_proto_rawDescOnce sync.Once - file_node_v1_shared_proto_rawDescData = file_node_v1_shared_proto_rawDesc -) - -func file_node_v1_shared_proto_rawDescGZIP() []byte { - file_node_v1_shared_proto_rawDescOnce.Do(func() { - file_node_v1_shared_proto_rawDescData = protoimpl.X.CompressGZIP(file_node_v1_shared_proto_rawDescData) - }) - return file_node_v1_shared_proto_rawDescData -} - -var file_node_v1_shared_proto_msgTypes = make([]protoimpl.MessageInfo, 1) -var file_node_v1_shared_proto_goTypes = []interface{}{ - (*Node)(nil), // 0: api.node.v1.Node - (*ptypes.Label)(nil), // 1: api.label.Label - (*timestamppb.Timestamp)(nil), // 2: google.protobuf.Timestamp -} -var file_node_v1_shared_proto_depIdxs = []int32{ - 1, // 0: api.node.v1.Node.labels:type_name -> api.label.Label - 2, // 1: api.node.v1.Node.created_at:type_name -> google.protobuf.Timestamp - 2, // 2: api.node.v1.Node.updated_at:type_name -> google.protobuf.Timestamp - 2, // 3: api.node.v1.Node.archived_at:type_name -> google.protobuf.Timestamp - 4, // [4:4] is the sub-list for method output_type - 4, // [4:4] is the sub-list for method input_type - 4, // [4:4] is the sub-list for extension type_name - 4, // [4:4] is the sub-list for extension extendee - 0, // [0:4] is the sub-list for field type_name -} - -func init() { file_node_v1_shared_proto_init() } -func file_node_v1_shared_proto_init() { - if File_node_v1_shared_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_node_v1_shared_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Node); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_node_v1_shared_proto_rawDesc, - NumEnums: 0, - NumMessages: 1, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_node_v1_shared_proto_goTypes, - DependencyIndexes: file_node_v1_shared_proto_depIdxs, - MessageInfos: file_node_v1_shared_proto_msgTypes, - }.Build() - File_node_v1_shared_proto = out.File - file_node_v1_shared_proto_rawDesc = nil - file_node_v1_shared_proto_goTypes = nil - file_node_v1_shared_proto_depIdxs = nil -} diff --git a/integration-tests/deployment/jd/shared/ptypes/label.pb.go b/integration-tests/deployment/jd/shared/ptypes/label.pb.go deleted file mode 100644 index e8195bd6c3..0000000000 --- a/integration-tests/deployment/jd/shared/ptypes/label.pb.go +++ /dev/null @@ -1,311 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.29.0 -// protoc v4.25.3 -// source: shared/ptypes/label.proto - -package ptypes - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// SelectorOp defines the operation to be used in a selector -type SelectorOp int32 - -const ( - SelectorOp_EQ SelectorOp = 0 - SelectorOp_NOT_EQ SelectorOp = 1 - SelectorOp_IN SelectorOp = 2 - SelectorOp_NOT_IN SelectorOp = 3 - SelectorOp_EXIST SelectorOp = 4 - SelectorOp_NOT_EXIST SelectorOp = 5 -) - -// Enum value maps for SelectorOp. -var ( - SelectorOp_name = map[int32]string{ - 0: "EQ", - 1: "NOT_EQ", - 2: "IN", - 3: "NOT_IN", - 4: "EXIST", - 5: "NOT_EXIST", - } - SelectorOp_value = map[string]int32{ - "EQ": 0, - "NOT_EQ": 1, - "IN": 2, - "NOT_IN": 3, - "EXIST": 4, - "NOT_EXIST": 5, - } -) - -func (x SelectorOp) Enum() *SelectorOp { - p := new(SelectorOp) - *p = x - return p -} - -func (x SelectorOp) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (SelectorOp) Descriptor() protoreflect.EnumDescriptor { - return file_shared_ptypes_label_proto_enumTypes[0].Descriptor() -} - -func (SelectorOp) Type() protoreflect.EnumType { - return &file_shared_ptypes_label_proto_enumTypes[0] -} - -func (x SelectorOp) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use SelectorOp.Descriptor instead. -func (SelectorOp) EnumDescriptor() ([]byte, []int) { - return file_shared_ptypes_label_proto_rawDescGZIP(), []int{0} -} - -// Label defines a label as a key value pair -type Label struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` - Value *string `protobuf:"bytes,2,opt,name=value,proto3,oneof" json:"value,omitempty"` -} - -func (x *Label) Reset() { - *x = Label{} - if protoimpl.UnsafeEnabled { - mi := &file_shared_ptypes_label_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Label) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Label) ProtoMessage() {} - -func (x *Label) ProtoReflect() protoreflect.Message { - mi := &file_shared_ptypes_label_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Label.ProtoReflect.Descriptor instead. -func (*Label) Descriptor() ([]byte, []int) { - return file_shared_ptypes_label_proto_rawDescGZIP(), []int{0} -} - -func (x *Label) GetKey() string { - if x != nil { - return x.Key - } - return "" -} - -func (x *Label) GetValue() string { - if x != nil && x.Value != nil { - return *x.Value - } - return "" -} - -// Selector defines a selector as a key value pair with an operation -type Selector struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` - Op SelectorOp `protobuf:"varint,2,opt,name=op,proto3,enum=api.label.SelectorOp" json:"op,omitempty"` - Value *string `protobuf:"bytes,3,opt,name=value,proto3,oneof" json:"value,omitempty"` -} - -func (x *Selector) Reset() { - *x = Selector{} - if protoimpl.UnsafeEnabled { - mi := &file_shared_ptypes_label_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Selector) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Selector) ProtoMessage() {} - -func (x *Selector) ProtoReflect() protoreflect.Message { - mi := &file_shared_ptypes_label_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Selector.ProtoReflect.Descriptor instead. -func (*Selector) Descriptor() ([]byte, []int) { - return file_shared_ptypes_label_proto_rawDescGZIP(), []int{1} -} - -func (x *Selector) GetKey() string { - if x != nil { - return x.Key - } - return "" -} - -func (x *Selector) GetOp() SelectorOp { - if x != nil { - return x.Op - } - return SelectorOp_EQ -} - -func (x *Selector) GetValue() string { - if x != nil && x.Value != nil { - return *x.Value - } - return "" -} - -var File_shared_ptypes_label_proto protoreflect.FileDescriptor - -var file_shared_ptypes_label_proto_rawDesc = []byte{ - 0x0a, 0x19, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x2f, 0x70, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, - 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x09, 0x61, 0x70, 0x69, - 0x2e, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x3e, 0x0a, 0x05, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x12, - 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, - 0x79, 0x12, 0x19, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x48, 0x00, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x88, 0x01, 0x01, 0x42, 0x08, 0x0a, 0x06, - 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x68, 0x0a, 0x08, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, - 0x6f, 0x72, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x03, 0x6b, 0x65, 0x79, 0x12, 0x25, 0x0a, 0x02, 0x6f, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, - 0x32, 0x15, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x2e, 0x53, 0x65, 0x6c, - 0x65, 0x63, 0x74, 0x6f, 0x72, 0x4f, 0x70, 0x52, 0x02, 0x6f, 0x70, 0x12, 0x19, 0x0a, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x88, 0x01, 0x01, 0x42, 0x08, 0x0a, 0x06, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x2a, 0x4e, 0x0a, 0x0a, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x4f, 0x70, 0x12, 0x06, - 0x0a, 0x02, 0x45, 0x51, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x4e, 0x4f, 0x54, 0x5f, 0x45, 0x51, - 0x10, 0x01, 0x12, 0x06, 0x0a, 0x02, 0x49, 0x4e, 0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06, 0x4e, 0x4f, - 0x54, 0x5f, 0x49, 0x4e, 0x10, 0x03, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x58, 0x49, 0x53, 0x54, 0x10, - 0x04, 0x12, 0x0d, 0x0a, 0x09, 0x4e, 0x4f, 0x54, 0x5f, 0x45, 0x58, 0x49, 0x53, 0x54, 0x10, 0x05, - 0x42, 0x47, 0x5a, 0x45, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x73, - 0x6d, 0x61, 0x72, 0x74, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x6b, 0x69, 0x74, 0x2f, - 0x6a, 0x6f, 0x62, 0x2d, 0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x2f, - 0x70, 0x6b, 0x67, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x73, 0x68, 0x61, 0x72, - 0x65, 0x64, 0x2f, 0x70, 0x74, 0x79, 0x70, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x33, -} - -var ( - file_shared_ptypes_label_proto_rawDescOnce sync.Once - file_shared_ptypes_label_proto_rawDescData = file_shared_ptypes_label_proto_rawDesc -) - -func file_shared_ptypes_label_proto_rawDescGZIP() []byte { - file_shared_ptypes_label_proto_rawDescOnce.Do(func() { - file_shared_ptypes_label_proto_rawDescData = protoimpl.X.CompressGZIP(file_shared_ptypes_label_proto_rawDescData) - }) - return file_shared_ptypes_label_proto_rawDescData -} - -var file_shared_ptypes_label_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_shared_ptypes_label_proto_msgTypes = make([]protoimpl.MessageInfo, 2) -var file_shared_ptypes_label_proto_goTypes = []interface{}{ - (SelectorOp)(0), // 0: api.label.SelectorOp - (*Label)(nil), // 1: api.label.Label - (*Selector)(nil), // 2: api.label.Selector -} -var file_shared_ptypes_label_proto_depIdxs = []int32{ - 0, // 0: api.label.Selector.op:type_name -> api.label.SelectorOp - 1, // [1:1] is the sub-list for method output_type - 1, // [1:1] is the sub-list for method input_type - 1, // [1:1] is the sub-list for extension type_name - 1, // [1:1] is the sub-list for extension extendee - 0, // [0:1] is the sub-list for field type_name -} - -func init() { file_shared_ptypes_label_proto_init() } -func file_shared_ptypes_label_proto_init() { - if File_shared_ptypes_label_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_shared_ptypes_label_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Label); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_shared_ptypes_label_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Selector); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - file_shared_ptypes_label_proto_msgTypes[0].OneofWrappers = []interface{}{} - file_shared_ptypes_label_proto_msgTypes[1].OneofWrappers = []interface{}{} - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_shared_ptypes_label_proto_rawDesc, - NumEnums: 1, - NumMessages: 2, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_shared_ptypes_label_proto_goTypes, - DependencyIndexes: file_shared_ptypes_label_proto_depIdxs, - EnumInfos: file_shared_ptypes_label_proto_enumTypes, - MessageInfos: file_shared_ptypes_label_proto_msgTypes, - }.Build() - File_shared_ptypes_label_proto = out.File - file_shared_ptypes_label_proto_rawDesc = nil - file_shared_ptypes_label_proto_goTypes = nil - file_shared_ptypes_label_proto_depIdxs = nil -} diff --git a/integration-tests/deployment/memory/chain.go b/integration-tests/deployment/memory/chain.go deleted file mode 100644 index 153d9d19e9..0000000000 --- a/integration-tests/deployment/memory/chain.go +++ /dev/null @@ -1,74 +0,0 @@ -package memory - -import ( - "math/big" - "testing" - "time" - - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core" - gethtypes "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/params" - chainsel "github.com/smartcontractkit/chain-selectors" - "github.com/stretchr/testify/require" -) - -type EVMChain struct { - Backend *backends.SimulatedBackend - DeployerKey *bind.TransactOpts -} - -// CCIP relies on block timestamps, but SimulatedBackend uses by default clock starting from 1970-01-01 -// This trick is used to move the clock closer to the current time. We set first block to be X hours ago. -// Tests create plenty of transactions so this number can't be too low, every new block mined will tick the clock, -// if you mine more than "X hours" transactions, SimulatedBackend will panic because generated timestamps will be in the future. -func tweakChainTimestamp(t *testing.T, backend *backends.SimulatedBackend, tweak time.Duration) { - blockTime := time.Unix(int64(backend.Blockchain().CurrentHeader().Time), 0) - sinceBlockTime := time.Since(blockTime) - diff := sinceBlockTime - tweak - err := backend.AdjustTime(diff) - require.NoError(t, err, "unable to adjust time on simulated chain") - backend.Commit() - backend.Commit() -} - -func fundAddress(t *testing.T, from *bind.TransactOpts, to common.Address, amount *big.Int, backend *backends.SimulatedBackend) { - nonce, err := backend.PendingNonceAt(Context(t), from.From) - require.NoError(t, err) - gp, err := backend.SuggestGasPrice(Context(t)) - require.NoError(t, err) - rawTx := gethtypes.NewTx(&gethtypes.LegacyTx{ - Nonce: nonce, - GasPrice: gp, - Gas: 21000, - To: &to, - Value: amount, - }) - signedTx, err := from.Signer(from.From, rawTx) - require.NoError(t, err) - err = backend.SendTransaction(Context(t), signedTx) - require.NoError(t, err) - backend.Commit() -} - -func GenerateChains(t *testing.T, numChains int) map[uint64]EVMChain { - chains := make(map[uint64]EVMChain) - for i := 0; i < numChains; i++ { - chainID := chainsel.TEST_90000001.EvmChainID + uint64(i) - key, err := crypto.GenerateKey() - require.NoError(t, err) - owner, err := bind.NewKeyedTransactorWithChainID(key, big.NewInt(1337)) - require.NoError(t, err) - backend := backends.NewSimulatedBackend(core.GenesisAlloc{ - owner.From: {Balance: big.NewInt(0).Mul(big.NewInt(100), big.NewInt(params.Ether))}}, 10000000) - tweakChainTimestamp(t, backend, time.Hour*8) - chains[chainID] = EVMChain{ - Backend: backend, - DeployerKey: owner, - } - } - return chains -} diff --git a/integration-tests/deployment/memory/environment.go b/integration-tests/deployment/memory/environment.go deleted file mode 100644 index a6fa690135..0000000000 --- a/integration-tests/deployment/memory/environment.go +++ /dev/null @@ -1,142 +0,0 @@ -package memory - -import ( - "context" - "testing" - - "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" - "github.com/ethereum/go-ethereum/common" - "github.com/hashicorp/consul/sdk/freeport" - chainsel "github.com/smartcontractkit/chain-selectors" - "github.com/stretchr/testify/require" - "go.uber.org/zap/zapcore" - - "github.com/smartcontractkit/chainlink/integration-tests/deployment" - - "github.com/smartcontractkit/chainlink-common/pkg/logger" -) - -const ( - Memory = "memory" -) - -type MemoryEnvironmentConfig struct { - Chains int - Nodes int - Bootstraps int - RegistryConfig RegistryConfig -} - -// Needed for environment variables on the node which point to prexisitng addresses. -// i.e. CapReg. -func NewMemoryChains(t *testing.T, numChains int) map[uint64]deployment.Chain { - mchains := GenerateChains(t, numChains) - chains := make(map[uint64]deployment.Chain) - for cid, chain := range mchains { - sel, err := chainsel.SelectorFromChainId(cid) - require.NoError(t, err) - chains[sel] = deployment.Chain{ - Selector: sel, - Client: chain.Backend, - DeployerKey: chain.DeployerKey, - Confirm: func(tx common.Hash) error { - for { - chain.Backend.Commit() - receipt, err := chain.Backend.TransactionReceipt(context.Background(), tx) - if err != nil { - t.Log("failed to get receipt", err) - continue - } - if receipt.Status == 0 { - t.Logf("Status (reverted) %d for txhash %s\n", receipt.Status, tx.String()) - } - return nil - } - }, - } - } - return chains -} - -func NewNodes(t *testing.T, logLevel zapcore.Level, chains map[uint64]deployment.Chain, numNodes, numBootstraps int, registryConfig RegistryConfig) map[string]Node { - mchains := make(map[uint64]EVMChain) - for _, chain := range chains { - evmChainID, err := chainsel.ChainIdFromSelector(chain.Selector) - if err != nil { - t.Fatal(err) - } - mchains[evmChainID] = EVMChain{ - Backend: chain.Client.(*backends.SimulatedBackend), - DeployerKey: chain.DeployerKey, - } - } - nodesByPeerID := make(map[string]Node) - ports := freeport.GetN(t, numBootstraps+numNodes) - // bootstrap nodes must be separate nodes from plugin nodes, - // since we won't run a bootstrapper and a plugin oracle on the same - // chainlink node in production. - for i := 0; i < numBootstraps; i++ { - node := NewNode(t, ports[i], mchains, logLevel, true /* bootstrap */, registryConfig) - nodesByPeerID[node.Keys.PeerID.String()] = *node - // Note in real env, this ID is allocated by JD. - } - for i := 0; i < numNodes; i++ { - // grab port offset by numBootstraps, since above loop also takes some ports. - node := NewNode(t, ports[numBootstraps+i], mchains, logLevel, false /* bootstrap */, registryConfig) - nodesByPeerID[node.Keys.PeerID.String()] = *node - // Note in real env, this ID is allocated by JD. - } - return nodesByPeerID -} - -func NewMemoryEnvironmentFromChainsNodes(t *testing.T, - lggr logger.Logger, - chains map[uint64]deployment.Chain, - nodes map[string]Node) deployment.Environment { - var nodeIDs []string - for id := range nodes { - nodeIDs = append(nodeIDs, id) - } - return deployment.Environment{ - Name: Memory, - Offchain: NewMemoryJobClient(nodes), - // Note these have the p2p_ prefix. - NodeIDs: nodeIDs, - Chains: chains, - Logger: lggr, - } -} - -//func NewMemoryEnvironmentExistingChains(t *testing.T, lggr logger.Logger, -// chains map[uint64]deployment.Chain, config MemoryEnvironmentConfig) deployment.Environment { -// nodes := NewNodes(t, chains, config.Nodes, config.Bootstraps, config.RegistryConfig) -// var nodeIDs []string -// for id := range nodes { -// nodeIDs = append(nodeIDs, id) -// } -// return deployment.Environment{ -// Name: Memory, -// Offchain: NewMemoryJobClient(nodes), -// // Note these have the p2p_ prefix. -// NodeIDs: nodeIDs, -// Chains: chains, -// Logger: lggr, -// } -//} - -// To be used by tests and any kind of deployment logic. -func NewMemoryEnvironment(t *testing.T, lggr logger.Logger, logLevel zapcore.Level, config MemoryEnvironmentConfig) deployment.Environment { - chains := NewMemoryChains(t, config.Chains) - nodes := NewNodes(t, logLevel, chains, config.Nodes, config.Bootstraps, config.RegistryConfig) - var nodeIDs []string - for id := range nodes { - nodeIDs = append(nodeIDs, id) - } - return deployment.Environment{ - Name: Memory, - Offchain: NewMemoryJobClient(nodes), - NodeIDs: nodeIDs, - Chains: chains, - Logger: lggr, - } -} diff --git a/integration-tests/deployment/memory/job_client.go b/integration-tests/deployment/memory/job_client.go deleted file mode 100644 index a9e837eab2..0000000000 --- a/integration-tests/deployment/memory/job_client.go +++ /dev/null @@ -1,126 +0,0 @@ -package memory - -import ( - "context" - "strconv" - - "github.com/ethereum/go-ethereum/common" - "google.golang.org/grpc" - - jobv1 "github.com/smartcontractkit/chainlink/integration-tests/deployment/jd/job/v1" - nodev1 "github.com/smartcontractkit/chainlink/integration-tests/deployment/jd/node/v1" - "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/validate" -) - -type JobClient struct { - Nodes map[string]Node -} - -func (j JobClient) GetNode(ctx context.Context, in *nodev1.GetNodeRequest, opts ...grpc.CallOption) (*nodev1.GetNodeResponse, error) { - //TODO implement me - panic("implement me") -} - -func (j JobClient) ListNodes(ctx context.Context, in *nodev1.ListNodesRequest, opts ...grpc.CallOption) (*nodev1.ListNodesResponse, error) { - //TODO implement me - panic("implement me") -} - -func (j JobClient) ListNodeChainConfigs(ctx context.Context, in *nodev1.ListNodeChainConfigsRequest, opts ...grpc.CallOption) (*nodev1.ListNodeChainConfigsResponse, error) { - n := j.Nodes[in.Filter.NodeId] - offpk := n.Keys.OCRKeyBundle.OffchainPublicKey() - cpk := n.Keys.OCRKeyBundle.ConfigEncryptionPublicKey() - var chainConfigs []*nodev1.ChainConfig - for evmChainID, transmitter := range n.Keys.TransmittersByEVMChainID { - chainConfigs = append(chainConfigs, &nodev1.ChainConfig{ - Chain: &nodev1.Chain{ - Id: strconv.Itoa(int(evmChainID)), - Type: nodev1.ChainType_CHAIN_TYPE_EVM, - }, - AccountAddress: transmitter.String(), - AdminAddress: "", - Ocr1Config: nil, - Ocr2Config: &nodev1.OCR2Config{ - Enabled: true, - IsBootstrap: n.IsBoostrap, - P2PKeyBundle: &nodev1.OCR2Config_P2PKeyBundle{ - PeerId: n.Keys.PeerID.String(), - }, - OcrKeyBundle: &nodev1.OCR2Config_OCRKeyBundle{ - BundleId: n.Keys.OCRKeyBundle.ID(), - ConfigPublicKey: common.Bytes2Hex(cpk[:]), - OffchainPublicKey: common.Bytes2Hex(offpk[:]), - OnchainSigningAddress: n.Keys.OCRKeyBundle.OnChainPublicKey(), - }, - Multiaddr: n.Addr.String(), - Plugins: nil, - ForwarderAddress: "", - }, - }) - } - - // TODO: I think we can pull it from the feeds manager. - return &nodev1.ListNodeChainConfigsResponse{ - ChainConfigs: chainConfigs, - }, nil -} - -func (j JobClient) GetJob(ctx context.Context, in *jobv1.GetJobRequest, opts ...grpc.CallOption) (*jobv1.GetJobResponse, error) { - //TODO implement me - panic("implement me") -} - -func (j JobClient) GetProposal(ctx context.Context, in *jobv1.GetProposalRequest, opts ...grpc.CallOption) (*jobv1.GetProposalResponse, error) { - //TODO implement me - panic("implement me") -} - -func (j JobClient) ListJobs(ctx context.Context, in *jobv1.ListJobsRequest, opts ...grpc.CallOption) (*jobv1.ListJobsResponse, error) { - //TODO implement me - panic("implement me") -} - -func (j JobClient) ListProposals(ctx context.Context, in *jobv1.ListProposalsRequest, opts ...grpc.CallOption) (*jobv1.ListProposalsResponse, error) { - //TODO implement me - panic("implement me") -} - -func (j JobClient) ProposeJob(ctx context.Context, in *jobv1.ProposeJobRequest, opts ...grpc.CallOption) (*jobv1.ProposeJobResponse, error) { - n := j.Nodes[in.NodeId] - // TODO: Use FMS - jb, err := validate.ValidatedCCIPSpec(in.Spec) - if err != nil { - return nil, err - } - err = n.App.AddJobV2(ctx, &jb) - if err != nil { - return nil, err - } - return &jobv1.ProposeJobResponse{Proposal: &jobv1.Proposal{ - Id: "", - Version: 0, - // Auto approve for now - Status: jobv1.ProposalStatus_PROPOSAL_STATUS_APPROVED, - DeliveryStatus: jobv1.ProposalDeliveryStatus_PROPOSAL_DELIVERY_STATUS_DELIVERED, - Spec: in.Spec, - JobId: jb.ExternalJobID.String(), - CreatedAt: nil, - UpdatedAt: nil, - AckedAt: nil, - ResponseReceivedAt: nil, - }}, nil -} - -func (j JobClient) RevokeJob(ctx context.Context, in *jobv1.RevokeJobRequest, opts ...grpc.CallOption) (*jobv1.RevokeJobResponse, error) { - //TODO implement me - panic("implement me") -} - -func (j JobClient) DeleteJob(ctx context.Context, in *jobv1.DeleteJobRequest, opts ...grpc.CallOption) (*jobv1.DeleteJobResponse, error) { - //TODO implement me - panic("implement me") -} - -func NewMemoryJobClient(nodesByPeerID map[string]Node) *JobClient { - return &JobClient{nodesByPeerID} -} diff --git a/integration-tests/deployment/memory/node.go b/integration-tests/deployment/memory/node.go deleted file mode 100644 index 7050cad53d..0000000000 --- a/integration-tests/deployment/memory/node.go +++ /dev/null @@ -1,291 +0,0 @@ -package memory - -import ( - "context" - "fmt" - "math/big" - "net" - "net/http" - "strconv" - "testing" - "time" - - "github.com/ethereum/go-ethereum/common" - gethtypes "github.com/ethereum/go-ethereum/core/types" - chainsel "github.com/smartcontractkit/chain-selectors" - "github.com/stretchr/testify/require" - "go.uber.org/zap/zapcore" - - "github.com/smartcontractkit/chainlink-common/pkg/config" - "github.com/smartcontractkit/chainlink-common/pkg/loop" - "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" - v2toml "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" - evmutils "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" - "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" - configv2 "github.com/smartcontractkit/chainlink/v2/core/config/toml" - "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/logger/audit" - "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" - "github.com/smartcontractkit/chainlink/v2/core/services/keystore" - "github.com/smartcontractkit/chainlink/v2/core/services/keystore/chaintype" - "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ocr2key" - "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" - "github.com/smartcontractkit/chainlink/v2/core/services/relay" - "github.com/smartcontractkit/chainlink/v2/core/utils" - "github.com/smartcontractkit/chainlink/v2/core/utils/testutils/heavyweight" - "github.com/smartcontractkit/chainlink/v2/plugins" -) - -func Context(tb testing.TB) context.Context { - ctx := context.Background() - var cancel func() - switch t := tb.(type) { - case *testing.T: - if d, ok := t.Deadline(); ok { - ctx, cancel = context.WithDeadline(ctx, d) - } - } - if cancel == nil { - ctx, cancel = context.WithCancel(ctx) - } - tb.Cleanup(cancel) - return ctx -} - -type Node struct { - App chainlink.Application - // Transmitter key/OCR keys for this node - Keys Keys - Addr net.TCPAddr - IsBoostrap bool -} - -func (n Node) ReplayLogs(chains map[uint64]uint64) error { - for sel, block := range chains { - chainID, _ := chainsel.ChainIdFromSelector(sel) - if err := n.App.ReplayFromBlock(big.NewInt(int64(chainID)), block, false); err != nil { - return err - } - } - return nil -} - -type RegistryConfig struct { - EVMChainID uint64 - Contract common.Address -} - -// Creates a CL node which is: -// - Configured for OCR -// - Configured for the chains specified -// - Transmitter keys funded. -func NewNode( - t *testing.T, - port int, // Port for the P2P V2 listener. - chains map[uint64]EVMChain, - logLevel zapcore.Level, - bootstrap bool, - registryConfig RegistryConfig, -) *Node { - // Do not want to load fixtures as they contain a dummy chainID. - // Create database and initial configuration. - cfg, db := heavyweight.FullTestDBNoFixturesV2(t, func(c *chainlink.Config, s *chainlink.Secrets) { - c.Insecure.OCRDevelopmentMode = ptr(true) // Disables ocr spec validation so we can have fast polling for the test. - - c.Feature.LogPoller = ptr(true) - - // P2P V2 configs. - c.P2P.V2.Enabled = ptr(true) - c.P2P.V2.DeltaDial = config.MustNewDuration(500 * time.Millisecond) - c.P2P.V2.DeltaReconcile = config.MustNewDuration(5 * time.Second) - c.P2P.V2.ListenAddresses = &[]string{fmt.Sprintf("127.0.0.1:%d", port)} - - // Enable Capabilities, This is a pre-requisite for registrySyncer to work. - if registryConfig.Contract != common.HexToAddress("0x0") { - c.Capabilities.ExternalRegistry.NetworkID = ptr(relay.NetworkEVM) - c.Capabilities.ExternalRegistry.ChainID = ptr(strconv.FormatUint(uint64(registryConfig.EVMChainID), 10)) - c.Capabilities.ExternalRegistry.Address = ptr(registryConfig.Contract.String()) - } - - // OCR configs - c.OCR.Enabled = ptr(false) - c.OCR.DefaultTransactionQueueDepth = ptr(uint32(200)) - c.OCR2.Enabled = ptr(true) - c.OCR2.ContractPollInterval = config.MustNewDuration(5 * time.Second) - - c.Log.Level = ptr(configv2.LogLevel(logLevel)) - - var chainConfigs v2toml.EVMConfigs - for chainID := range chains { - chainConfigs = append(chainConfigs, createConfigV2Chain(chainID)) - } - c.EVM = chainConfigs - }) - - // Set logging. - lggr := logger.TestLogger(t) - lggr.SetLogLevel(logLevel) - - // Create clients for the core node backed by sim. - clients := make(map[uint64]client.Client) - for chainID, chain := range chains { - clients[chainID] = client.NewSimulatedBackendClient(t, chain.Backend, big.NewInt(int64(chainID))) - } - - // Create keystore - master := keystore.New(db, utils.FastScryptParams, lggr) - kStore := KeystoreSim{ - eks: &EthKeystoreSim{ - Eth: master.Eth(), - }, - csa: master.CSA(), - } - - // Build evm factory using clients + keystore. - mailMon := mailbox.NewMonitor("node", lggr.Named("mailbox")) - evmOpts := chainlink.EVMFactoryConfig{ - ChainOpts: legacyevm.ChainOpts{ - AppConfig: cfg, - GenEthClient: func(i *big.Int) client.Client { - ethClient, ok := clients[i.Uint64()] - if !ok { - t.Fatal("no backend for chainID", i) - } - return ethClient - }, - MailMon: mailMon, - DS: db, - }, - CSAETHKeystore: kStore, - } - - // Build relayer factory with EVM. - relayerFactory := chainlink.RelayerFactory{ - Logger: lggr, - LoopRegistry: plugins.NewLoopRegistry(lggr.Named("LoopRegistry"), cfg.Tracing()), - GRPCOpts: loop.GRPCOpts{}, - } - initOps := []chainlink.CoreRelayerChainInitFunc{chainlink.InitEVM(context.Background(), relayerFactory, evmOpts)} - rci, err := chainlink.NewCoreRelayerChainInteroperators(initOps...) - require.NoError(t, err) - - app, err := chainlink.NewApplication(chainlink.ApplicationOpts{ - Config: cfg, - DS: db, - KeyStore: master, - RelayerChainInteroperators: rci, - Logger: lggr, - ExternalInitiatorManager: nil, - CloseLogger: lggr.Sync, - UnrestrictedHTTPClient: &http.Client{}, - RestrictedHTTPClient: &http.Client{}, - AuditLogger: audit.NoopLogger, - MailMon: mailMon, - LoopRegistry: plugins.NewLoopRegistry(lggr, cfg.Tracing()), - }) - require.NoError(t, err) - t.Cleanup(func() { - require.NoError(t, db.Close()) - }) - keys := CreateKeys(t, app, chains) - - return &Node{ - App: app, - Keys: keys, - Addr: net.TCPAddr{IP: net.ParseIP("127.0.0.1"), Port: port}, - IsBoostrap: bootstrap, - } -} - -type Keys struct { - PeerID p2pkey.PeerID - TransmittersByEVMChainID map[uint64]common.Address - OCRKeyBundle ocr2key.KeyBundle -} - -func CreateKeys(t *testing.T, - app chainlink.Application, chains map[uint64]EVMChain) Keys { - ctx := Context(t) - require.NoError(t, app.GetKeyStore().Unlock(ctx, "password")) - _, err := app.GetKeyStore().P2P().Create(ctx) - require.NoError(t, err) - - p2pIDs, err := app.GetKeyStore().P2P().GetAll() - require.NoError(t, err) - require.Len(t, p2pIDs, 1) - peerID := p2pIDs[0].PeerID() - // create a transmitter for each chain - transmitters := make(map[uint64]common.Address) - for chainID, chain := range chains { - cid := big.NewInt(int64(chainID)) - addrs, err2 := app.GetKeyStore().Eth().EnabledAddressesForChain(Context(t), cid) - require.NoError(t, err2) - if len(addrs) == 1 { - // just fund the address - fundAddress(t, chain.DeployerKey, addrs[0], assets.Ether(10).ToInt(), chain.Backend) - transmitters[chainID] = addrs[0] - } else { - // create key and fund it - _, err3 := app.GetKeyStore().Eth().Create(Context(t), cid) - require.NoError(t, err3, "failed to create key for chain", chainID) - sendingKeys, err3 := app.GetKeyStore().Eth().EnabledAddressesForChain(Context(t), cid) - require.NoError(t, err3) - require.Len(t, sendingKeys, 1) - fundAddress(t, chain.DeployerKey, sendingKeys[0], assets.Ether(10).ToInt(), chain.Backend) - transmitters[chainID] = sendingKeys[0] - } - } - require.Len(t, transmitters, len(chains)) - - keybundle, err := app.GetKeyStore().OCR2().Create(ctx, chaintype.EVM) - require.NoError(t, err) - return Keys{ - PeerID: peerID, - TransmittersByEVMChainID: transmitters, - OCRKeyBundle: keybundle, - } -} - -func createConfigV2Chain(chainID uint64) *v2toml.EVMConfig { - chainIDBig := evmutils.NewI(int64(chainID)) - chain := v2toml.Defaults(chainIDBig) - chain.GasEstimator.LimitDefault = ptr(uint64(5e6)) - chain.LogPollInterval = config.MustNewDuration(1000 * time.Millisecond) - chain.Transactions.ForwardersEnabled = ptr(false) - chain.FinalityDepth = ptr(uint32(2)) - return &v2toml.EVMConfig{ - ChainID: chainIDBig, - Enabled: ptr(true), - Chain: chain, - Nodes: v2toml.EVMNodes{&v2toml.Node{}}, - } -} - -func ptr[T any](v T) *T { return &v } - -var _ keystore.Eth = &EthKeystoreSim{} - -type EthKeystoreSim struct { - keystore.Eth -} - -// override -func (e *EthKeystoreSim) SignTx(ctx context.Context, address common.Address, tx *gethtypes.Transaction, chainID *big.Int) (*gethtypes.Transaction, error) { - // always sign with chain id 1337 for the simulated backend - return e.Eth.SignTx(ctx, address, tx, big.NewInt(1337)) -} - -type KeystoreSim struct { - eks keystore.Eth - csa keystore.CSA -} - -func (e KeystoreSim) Eth() keystore.Eth { - return e.eks -} - -func (e KeystoreSim) CSA() keystore.CSA { - return e.csa -} diff --git a/integration-tests/deployment/memory/node_test.go b/integration-tests/deployment/memory/node_test.go deleted file mode 100644 index d64c7717fc..0000000000 --- a/integration-tests/deployment/memory/node_test.go +++ /dev/null @@ -1,23 +0,0 @@ -package memory - -import ( - "testing" - - "github.com/hashicorp/consul/sdk/freeport" - "github.com/stretchr/testify/require" - "go.uber.org/zap/zapcore" -) - -func TestNode(t *testing.T) { - chains := GenerateChains(t, 3) - ports := freeport.GetN(t, 1) - node := NewNode(t, ports[0], chains, zapcore.DebugLevel, false, RegistryConfig{}) - // We expect 3 transmitter keys - keys, err := node.App.GetKeyStore().Eth().GetAll(Context(t)) - require.NoError(t, err) - require.Len(t, keys, 3) - // We expect 3 chains supported - evmChains := node.App.GetRelayers().LegacyEVMChains().Slice() - require.NoError(t, err) - require.Len(t, evmChains, 3) -} diff --git a/integration-tests/go.mod b/integration-tests/go.mod index 37f3ba0973..8eed200342 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -19,7 +19,6 @@ require ( github.com/go-resty/resty/v2 v2.11.0 github.com/google/go-cmp v0.6.0 github.com/google/uuid v1.6.0 - github.com/hashicorp/consul/sdk v0.16.0 github.com/jmoiron/sqlx v1.4.0 github.com/lib/pq v1.10.9 github.com/manifoldco/promptui v0.9.0 @@ -33,10 +32,8 @@ require ( github.com/segmentio/ksuid v1.0.4 github.com/shopspring/decimal v1.4.0 github.com/slack-go/slack v0.12.2 - github.com/smartcontractkit/ccip-owner-contracts v0.0.0-20240808195812-ae0378684685 github.com/smartcontractkit/chain-selectors v1.0.23 github.com/smartcontractkit/chainlink-automation v1.0.4 - github.com/smartcontractkit/chainlink-ccip v0.0.0-20240827164549-33f5819d7ddc github.com/smartcontractkit/chainlink-common v0.2.1-0.20240717132349-ee5af9b79834 github.com/smartcontractkit/chainlink-testing-framework v1.34.5 github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240405215812-5a72bc9af239 @@ -58,12 +55,9 @@ require ( golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 golang.org/x/sync v0.8.0 golang.org/x/text v0.17.0 - google.golang.org/grpc v1.65.0 - google.golang.org/protobuf v1.34.2 gopkg.in/guregu/null.v4 v4.0.0 gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v3 v3.0.1 - gotest.tools/v3 v3.5.1 k8s.io/apimachinery v0.28.2 ) @@ -270,6 +264,7 @@ require ( github.com/gtank/merlin v0.1.1 // indirect github.com/gtank/ristretto255 v0.1.2 // indirect github.com/hashicorp/consul/api v1.28.2 // indirect + github.com/hashicorp/consul/sdk v0.16.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-envparse v0.1.0 // indirect @@ -475,6 +470,8 @@ require ( google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240711142825-46eb208f015d // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240711142825-46eb208f015d // indirect + google.golang.org/grpc v1.65.0 // indirect + google.golang.org/protobuf v1.34.2 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect diff --git a/integration-tests/go.sum b/integration-tests/go.sum index b21f0a2c4a..d7ec061aeb 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1389,14 +1389,10 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/slack-go/slack v0.12.2 h1:x3OppyMyGIbbiyFhsBmpf9pwkUzMhthJMRNmNlA4LaQ= github.com/slack-go/slack v0.12.2/go.mod h1:hlGi5oXA+Gt+yWTPP0plCdRKmjsDxecdHxYQdlMQKOw= -github.com/smartcontractkit/ccip-owner-contracts v0.0.0-20240808195812-ae0378684685 h1:jakAsdhDxV4cMgRAcSvHraXjyePi8umG5SEUTGFvuy8= -github.com/smartcontractkit/ccip-owner-contracts v0.0.0-20240808195812-ae0378684685/go.mod h1:p7L/xNEQpHDdZtgFA6/FavuZHqvV3kYhQysxBywmq1k= github.com/smartcontractkit/chain-selectors v1.0.23 h1:D2Eaex4Cw/O7Lg3tX6WklOqnjjIQAEBnutCtksPzVDY= github.com/smartcontractkit/chain-selectors v1.0.23/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/smartcontractkit/chainlink-automation v1.0.4 h1:iyW181JjKHLNMnDleI8umfIfVVlwC7+n5izbLSFgjw8= github.com/smartcontractkit/chainlink-automation v1.0.4/go.mod h1:u4NbPZKJ5XiayfKHD/v3z3iflQWqvtdhj13jVZXj/cM= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20240827164549-33f5819d7ddc h1:8267l5X5oF2JnGsDaEG4i0JSQO9o0eC61SscTfWc1bk= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20240827164549-33f5819d7ddc/go.mod h1:Z9lQ5t20kRk28pzRLnqAJZUVOw8E6/siA3P3MLyKqoM= github.com/smartcontractkit/chainlink-common v0.2.1-0.20240717132349-ee5af9b79834 h1:pTf4xdcmiWBqWZ6rTy2RMTDBzhHk89VC1pM7jXKQztI= github.com/smartcontractkit/chainlink-common v0.2.1-0.20240717132349-ee5af9b79834/go.mod h1:fh9eBbrReCmv31bfz52ENCAMa7nTKQbdhb2B3+S2VGo= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240710121324-3ed288aa9b45 h1:NBQLtqk8zsyY4qTJs+NElI3aDFTcAo83JHvqD04EvB0= @@ -2172,6 +2168,7 @@ gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index aab626f3bd..c8ef675d05 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -42,7 +42,6 @@ require ( github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect - github.com/smartcontractkit/chainlink-ccip v0.0.0-20240827164549-33f5819d7ddc // indirect github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240710121324-3ed288aa9b45 // indirect github.com/testcontainers/testcontainers-go v0.28.0 // indirect k8s.io/apimachinery v0.30.2 // indirect diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index f4f3567b5d..714ba7700b 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -1359,8 +1359,6 @@ github.com/smartcontractkit/chain-selectors v1.0.23 h1:D2Eaex4Cw/O7Lg3tX6WklOqnj github.com/smartcontractkit/chain-selectors v1.0.23/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/smartcontractkit/chainlink-automation v1.0.4 h1:iyW181JjKHLNMnDleI8umfIfVVlwC7+n5izbLSFgjw8= github.com/smartcontractkit/chainlink-automation v1.0.4/go.mod h1:u4NbPZKJ5XiayfKHD/v3z3iflQWqvtdhj13jVZXj/cM= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20240827164549-33f5819d7ddc h1:8267l5X5oF2JnGsDaEG4i0JSQO9o0eC61SscTfWc1bk= -github.com/smartcontractkit/chainlink-ccip v0.0.0-20240827164549-33f5819d7ddc/go.mod h1:Z9lQ5t20kRk28pzRLnqAJZUVOw8E6/siA3P3MLyKqoM= github.com/smartcontractkit/chainlink-common v0.2.1-0.20240717132349-ee5af9b79834 h1:pTf4xdcmiWBqWZ6rTy2RMTDBzhHk89VC1pM7jXKQztI= github.com/smartcontractkit/chainlink-common v0.2.1-0.20240717132349-ee5af9b79834/go.mod h1:fh9eBbrReCmv31bfz52ENCAMa7nTKQbdhb2B3+S2VGo= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240710121324-3ed288aa9b45 h1:NBQLtqk8zsyY4qTJs+NElI3aDFTcAo83JHvqD04EvB0= diff --git a/tools/bin/go_core_ccip_deployment_tests b/tools/bin/go_core_ccip_deployment_tests deleted file mode 100755 index 54f9b70d26..0000000000 --- a/tools/bin/go_core_ccip_deployment_tests +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/env bash -set -o pipefail -set +e - -SCRIPT_PATH=`dirname "$0"`; SCRIPT_PATH=`eval "cd \"$SCRIPT_PATH\" && pwd"` -OUTPUT_FILE="../output.txt" -USE_TEE="${USE_TEE:-true}" - -# To allow reuse in CI from other repositories -TOOLS_PATH=${TOOLS_PATH:-"./tools"} - -echo "Failed tests and panics: ---------------------" -echo "" -use_tee() { - if [ "$USE_TEE" = "true" ]; then - tee "$@" - else - cat > "$@" - fi -} - -cd ./integration-tests || exit -go mod download -go test -json ./deployment/... -covermode=atomic -coverpkg=./... -coverprofile=coverage.txt | use_tee $OUTPUT_FILE -EXITCODE=${PIPESTATUS[0]} - -# Assert no known sensitive strings present in test logger output -printf "\n----------------------------------------------\n\n" -echo "Beginning check of output logs for sensitive strings" -$SCRIPT_PATH/scrub_logs $OUTPUT_FILE -cd .. -if [[ $? != 0 ]]; then - exit 1 -fi - -echo "Exit code: $EXITCODE" -if [[ $EXITCODE != 0 ]]; then - echo "Encountered test failures." -else - echo "All tests passed!" -fi -echo "go_core_ccip_deployment_tests exiting with code $EXITCODE" -exit $EXITCODE From c8c7d9253e1b18bedd043b3400620b8c94bd83e8 Mon Sep 17 00:00:00 2001 From: nogo <110664798+0xnogo@users.noreply.github.com> Date: Sun, 1 Sep 2024 13:32:59 +0200 Subject: [PATCH 059/115] Consensus threshold to 2f+1 for zk overflow chains (#1313) Consensus threshold to 2f+1 for zk overflow chains --- .../ocr2/plugins/ccip/ccipexec/batching.go | 19 ++++- .../plugins/ccip/ccipexec/batching_test.go | 11 ++- .../ocr2/plugins/ccip/ccipexec/ocr2.go | 23 +++++- .../ocr2/plugins/ccip/ccipexec/ocr2_test.go | 75 ++++++++++++++++--- 4 files changed, 110 insertions(+), 18 deletions(-) diff --git a/core/services/ocr2/plugins/ccip/ccipexec/batching.go b/core/services/ocr2/plugins/ccip/ccipexec/batching.go index b457dd986d..f096953f5d 100644 --- a/core/services/ocr2/plugins/ccip/ccipexec/batching.go +++ b/core/services/ocr2/plugins/ccip/ccipexec/batching.go @@ -24,6 +24,12 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/statuschecker" ) +// Batching strategies +const ( + BestEffortBatchingStrategyID = uint32(0) + ZKOverflowBatchingStrategyID = uint32(1) +) + type BatchContext struct { report commitReportWithSendRequests inflight []InflightInternalExecutionReport @@ -47,6 +53,7 @@ type BatchContext struct { type BatchingStrategy interface { BuildBatch(ctx context.Context, batchCtx *BatchContext) ([]ccip.ObservedMessage, []messageExecStatus) + GetBatchingStrategyID() uint32 } type BestEffortBatchingStrategy struct{} @@ -58,9 +65,9 @@ type ZKOverflowBatchingStrategy struct { func NewBatchingStrategy(batchingStrategyID uint32, statusChecker statuschecker.CCIPTransactionStatusChecker) (BatchingStrategy, error) { var batchingStrategy BatchingStrategy switch batchingStrategyID { - case 0: + case BestEffortBatchingStrategyID: batchingStrategy = &BestEffortBatchingStrategy{} - case 1: + case ZKOverflowBatchingStrategyID: batchingStrategy = &ZKOverflowBatchingStrategy{ statuschecker: statusChecker, } @@ -70,6 +77,10 @@ func NewBatchingStrategy(batchingStrategyID uint32, statusChecker statuschecker. return batchingStrategy, nil } +func (s *BestEffortBatchingStrategy) GetBatchingStrategyID() uint32 { + return BestEffortBatchingStrategyID +} + // BestEffortBatchingStrategy is a batching strategy that tries to batch as many messages as possible (up to certain limits). func (s *BestEffortBatchingStrategy) BuildBatch( ctx context.Context, @@ -95,6 +106,10 @@ func (s *BestEffortBatchingStrategy) BuildBatch( return batchBuilder.batch, batchBuilder.statuses } +func (bs *ZKOverflowBatchingStrategy) GetBatchingStrategyID() uint32 { + return ZKOverflowBatchingStrategyID +} + // ZKOverflowBatchingStrategy is a batching strategy for ZK chains overflowing under certain conditions. // It is a simple batching strategy that only allows one message to be added to the batch. // TXM is used to perform the ZK check: if the message failed the check, it will be skipped. diff --git a/core/services/ocr2/plugins/ccip/ccipexec/batching_test.go b/core/services/ocr2/plugins/ccip/ccipexec/batching_test.go index 3647556a6d..4393fc5f58 100644 --- a/core/services/ocr2/plugins/ccip/ccipexec/batching_test.go +++ b/core/services/ocr2/plugins/ccip/ccipexec/batching_test.go @@ -850,13 +850,13 @@ func runBatchingStrategyTests(t *testing.T, strategy BatchingStrategy, available seqNrs, execStates := strategy.BuildBatch(context.Background(), batchContext) - runAssertions(t, tc, seqNrs, execStates) + runAssertions(t, tc, seqNrs, execStates, strategy) }) } } // Utility function to run common assertions -func runAssertions(t *testing.T, tc testCase, seqNrs []ccip.ObservedMessage, execStates []messageExecStatus) { +func runAssertions(t *testing.T, tc testCase, seqNrs []ccip.ObservedMessage, execStates []messageExecStatus, strategy BatchingStrategy) { if tc.expectedSeqNrs == nil { assert.Len(t, seqNrs, 0) } else { @@ -868,6 +868,13 @@ func runAssertions(t *testing.T, tc testCase, seqNrs []ccip.ObservedMessage, exe } else { assert.Equal(t, tc.expectedStates, execStates) } + + batchingStratID := strategy.GetBatchingStrategyID() + if strategyType := reflect.TypeOf(strategy); strategyType == reflect.TypeOf(&BestEffortBatchingStrategy{}) { + assert.Equal(t, batchingStratID, uint32(0)) + } else { + assert.Equal(t, batchingStratID, uint32(1)) + } } func createTestMessage(seqNr uint64, sender cciptypes.Address, nonce uint64, feeToken cciptypes.Address, feeAmount *big.Int, executed bool, data []byte) cciptypes.EVM2EVMOnRampCCIPSendRequestedWithMeta { diff --git a/core/services/ocr2/plugins/ccip/ccipexec/ocr2.go b/core/services/ocr2/plugins/ccip/ccipexec/ocr2.go index 4a09cf37b4..2c70cac497 100644 --- a/core/services/ocr2/plugins/ccip/ccipexec/ocr2.go +++ b/core/services/ocr2/plugins/ccip/ccipexec/ocr2.go @@ -468,6 +468,19 @@ func (r *ExecutionReportingPlugin) buildReport(ctx context.Context, lggr logger. return encodedReport, nil } +// Returns required number of observations to reach consensus +func (r *ExecutionReportingPlugin) getConsensusThreshold() int { + // Default consensus threshold is F+1 + consensusThreshold := r.F + 1 + if r.batchingStrategy.GetBatchingStrategyID() == ZKOverflowBatchingStrategyID { + // For batching strategy 1, consensus threshold is 2F+1 + // This is because chains that can overflow need to reach consensus during the inflight cache period + // to avoid 2 transmissions round of an overflown message. + consensusThreshold = 2*r.F + 1 + } + return consensusThreshold +} + func (r *ExecutionReportingPlugin) Report(ctx context.Context, timestamp types.ReportTimestamp, query types.Query, observations []types.AttributedObservation) (bool, types.Report, error) { lggr := r.lggr.Named("ExecutionReport") if healthy, err := r.chainHealthcheck.IsHealthy(ctx); err != nil { @@ -475,14 +488,16 @@ func (r *ExecutionReportingPlugin) Report(ctx context.Context, timestamp types.R } else if !healthy { return false, nil, ccip.ErrChainIsNotHealthy } + consensusThreshold := r.getConsensusThreshold() + lggr.Infof("Consensus threshold set to: %d", consensusThreshold) + parsableObservations := ccip.GetParsableObservations[ccip.ExecutionObservation](lggr, observations) - // Need at least F+1 observations - if len(parsableObservations) <= r.F { - lggr.Warn("Non-empty observations <= F, need at least F+1 to continue") + if len(parsableObservations) < consensusThreshold { + lggr.Warnf("Insufficient observations: only %d received, but need more than %d to proceed", len(parsableObservations), consensusThreshold) return false, nil, nil } - observedMessages, err := calculateObservedMessagesConsensus(parsableObservations, r.F) + observedMessages, err := calculateObservedMessagesConsensus(parsableObservations, consensusThreshold) if err != nil { return false, nil, err } diff --git a/core/services/ocr2/plugins/ccip/ccipexec/ocr2_test.go b/core/services/ocr2/plugins/ccip/ccipexec/ocr2_test.go index 627afda975..fea05ab61c 100644 --- a/core/services/ocr2/plugins/ccip/ccipexec/ocr2_test.go +++ b/core/services/ocr2/plugins/ccip/ccipexec/ocr2_test.go @@ -42,6 +42,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/prices" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/testhelpers" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/tokendata" + "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/statuschecker" ) func TestExecutionReportingPlugin_Observation(t *testing.T) { @@ -232,19 +233,21 @@ func TestExecutionReportingPlugin_Observation(t *testing.T) { func TestExecutionReportingPlugin_Report(t *testing.T) { testCases := []struct { - name string - f int - committedSeqNum uint64 - observations []ccip.ExecutionObservation + name string + f int + batchingStrategyId uint32 + committedSeqNum uint64 + observations []ccip.ExecutionObservation expectingSomeReport bool expectedReport cciptypes.ExecReport expectingSomeErr bool }{ { - name: "not enough observations to form consensus", - f: 5, - committedSeqNum: 5, + name: "not enough observations to form consensus - best effort batching", + f: 5, + batchingStrategyId: 0, + committedSeqNum: 5, observations: []ccip.ExecutionObservation{ {Messages: map[uint64]ccip.MsgData{3: {}, 4: {}}}, {Messages: map[uint64]ccip.MsgData{3: {}, 4: {}}}, @@ -252,6 +255,21 @@ func TestExecutionReportingPlugin_Report(t *testing.T) { expectingSomeErr: false, expectingSomeReport: false, }, + { + name: "not enough observaitons to form consensus - zk batching", + f: 5, + batchingStrategyId: 1, + committedSeqNum: 5, + observations: []ccip.ExecutionObservation{ + {Messages: map[uint64]ccip.MsgData{3: {}, 4: {}}}, + {Messages: map[uint64]ccip.MsgData{3: {}, 4: {}}}, + {Messages: map[uint64]ccip.MsgData{3: {}, 4: {}}}, + {Messages: map[uint64]ccip.MsgData{3: {}, 4: {}}}, + {Messages: map[uint64]ccip.MsgData{3: {}, 4: {}}}, + {Messages: map[uint64]ccip.MsgData{3: {}, 4: {}}}, + {Messages: map[uint64]ccip.MsgData{3: {}, 4: {}}}, + }, + }, { name: "zero observations", f: 0, @@ -268,6 +286,9 @@ func TestExecutionReportingPlugin_Report(t *testing.T) { p := ExecutionReportingPlugin{} p.lggr = logger.TestLogger(t) p.F = tc.f + bs, err := NewBatchingStrategy(tc.batchingStrategyId, &statuschecker.TxmStatusChecker{}) + assert.NoError(t, err) + p.batchingStrategy = bs p.commitStoreReader = ccipdatamocks.NewCommitStoreReader(t) chainHealthcheck := ccipcachemocks.NewChainHealthcheck(t) @@ -281,12 +302,12 @@ func TestExecutionReportingPlugin_Report(t *testing.T) { observations[i] = types.AttributedObservation{Observation: b, Observer: commontypes.OracleID(i + 1)} } - _, _, err := p.Report(ctx, types.ReportTimestamp{}, types.Query{}, observations) + _, _, err2 := p.Report(ctx, types.ReportTimestamp{}, types.Query{}, observations) if tc.expectingSomeErr { - assert.Error(t, err) + assert.Error(t, err2) return } - assert.NoError(t, err) + assert.NoError(t, err2) }) } } @@ -1422,3 +1443,37 @@ func TestExecutionReportingPlugin_ensurePriceRegistrySynchronization(t *testing. require.NoError(t, err) require.Equal(t, mockPriceRegistryReader2, p.sourcePriceRegistry) } + +func TestExecutionReportingPlugin_getConsensusThreshold(t *testing.T) { + tests := []struct { + name string + batchingStrategyID uint32 + F int + expectedConsensusThreshold int + }{ + { + name: "zk batching strategy", + batchingStrategyID: uint32(1), + F: 5, + expectedConsensusThreshold: 11, + }, + { + name: "default batching strategy", + batchingStrategyID: uint32(0), + F: 5, + expectedConsensusThreshold: 6, + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + p := &ExecutionReportingPlugin{} + p.F = tc.F + bs, err := NewBatchingStrategy(tc.batchingStrategyID, &statuschecker.TxmStatusChecker{}) + assert.NoError(t, err) + p.batchingStrategy = bs + + require.Equal(t, tc.expectedConsensusThreshold, p.getConsensusThreshold()) + }) + } +} From a793f34cdd1e87b31511860d10cc9a91e53ee4d5 Mon Sep 17 00:00:00 2001 From: Lukasz <120112546+lukaszcl@users.noreply.github.com> Date: Mon, 2 Sep 2024 11:17:30 +0200 Subject: [PATCH 060/115] Remove BASE64_NETWORK_CONFIG and use default test secrets instead (#1398) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR eliminates the BASE64_NETWORK_CONFIG environment variable from E2E test workflows, replacing it with default test secrets from secrets.CCIP_DEFAULT_TEST_SECRETS GitHub Secret. Following the merge of this PR, secrets.BASE64_NETWORK_CONFIG will be removed. Content of `secrets.CCIP_DEFAULT_TEST_SECRETS` GitHub Secret can be found in `1Password->QA->CCIP_DEFAULT_TEST_SECRETS`. This was tested using ccip-live-network-tests.yml workflow - https://github.com/smartcontractkit/ccip/actions/runs/10628096213 🟢 - [x] @b-gopalswami please do additional testing needed ([DONE](https://chainlink-core.slack.com/archives/C0361N0LJ6A/p1725037426281989?thread_ts=1725009288.027129&cid=C0361N0LJ6A)) --------- Co-authored-by: Adam Hamrick Co-authored-by: Anindita Ghosh <88458927+AnieeG@users.noreply.github.com> --- .github/workflows/ccip-live-network-tests.yml | 56 +++--- .github/workflows/ccip-load-tests.yml | 33 +++- .../workflows/ccip-offchain-upgrade-tests.yml | 50 ++++-- integration-tests/ccip-tests/Makefile | 6 +- .../ccip-tests/testconfig/README.md | 11 +- .../examples/network_config.toml.example | 168 ------------------ 6 files changed, 93 insertions(+), 231 deletions(-) delete mode 100644 integration-tests/ccip-tests/testconfig/examples/network_config.toml.example diff --git a/.github/workflows/ccip-live-network-tests.yml b/.github/workflows/ccip-live-network-tests.yml index 3c638a1546..7d908d9718 100644 --- a/.github/workflows/ccip-live-network-tests.yml +++ b/.github/workflows/ccip-live-network-tests.yml @@ -34,7 +34,27 @@ env: ENV_JOB_IMAGE: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink-ccip-tests:${{ github.sha }} INTERNAL_DOCKER_REPO: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com AWS_ECR_REPO_PUBLIC_REGISTRY: public.ecr.aws - + E2E_TEST_CHAINLINK_IMAGE: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink + E2E_TEST_LOKI_TENANT_ID: ${{ vars.LOKI_TENANT_ID }} + E2E_TEST_LOKI_ENDPOINT: ${{ secrets.LOKI_URL }} + E2E_TEST_LOKI_BASIC_AUTH: ${{ secrets.LOKI_BASIC_AUTH }} + E2E_TEST_GRAFANA_BASE_URL: ${{ vars.GRAFANA_URL }} + # Default private key test secret loaded from Github Secret as only security team has access to it. + # this key secrets.QA_SHARED_803C_KEY has a story behind it. To know more, see CCIP-2875 and SECHD-16575 tickets. + E2E_TEST_ETHEREUM_MAINNET_WALLET_KEY: ${{ secrets.QA_SHARED_803C_KEY }} + E2E_TEST_ARBITRUM_MAINNET_WALLET_KEY: ${{ secrets.QA_SHARED_803C_KEY }} + E2E_TEST_BASE_MAINNET_WALLET_KEY: ${{ secrets.QA_SHARED_803C_KEY }} + E2E_TEST_WEMIX_MAINNET_WALLET_KEY: ${{ secrets.QA_SHARED_803C_KEY }} + E2E_TEST_AVALANCHE_MAINNET_WALLET_KEY: ${{ secrets.QA_SHARED_803C_KEY }} + E2E_TEST_ZKSYNC_MAINNET_WALLET_KEY: ${{ secrets.QA_SHARED_803C_KEY }} + E2E_TEST_MODE_MAINNET_WALLET_KEY: ${{ secrets.QA_SHARED_803C_KEY }} + E2E_TEST_METIS_ANDROMEDA_WALLET_KEY: ${{ secrets.QA_SHARED_803C_KEY }} + E2E_TEST_OPTIMISM_MAINNET_WALLET_KEY: ${{ secrets.QA_SHARED_803C_KEY }} + E2E_TEST_KROMA_MAINNET_WALLET_KEY: ${{ secrets.QA_SHARED_803C_KEY }} + E2E_TEST_GNOSIS_MAINNET_WALLET_KEY: ${{ secrets.QA_SHARED_803C_KEY }} + E2E_TEST_POLYGON_MAINNET_WALLET_KEY: ${{ secrets.QA_SHARED_803C_KEY }} + E2E_TEST_BSC_MAINNET_WALLET_KEY: ${{ secrets.QA_SHARED_803C_KEY }} + jobs: build-chainlink: environment: integration @@ -128,7 +148,6 @@ jobs: TEST_LOG_LEVEL: info REF_NAME: ${{ github.head_ref || github.ref_name }} ENV_JOB_IMAGE_BASE: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink-ccip-tests - BASE64_NETWORK_CONFIG: ${{ secrets.BASE64_NETWORK_CONFIG }} steps: - name: Collect Metrics @@ -149,10 +168,6 @@ jobs: id: set_override_config shell: bash run: | - # this key secrets.QA_SHARED_803C_KEY has a story behind it. To know more, see CCIP-2875 and SECHD-16575 tickets. - BASE64_NETWORK_CONFIG=$(echo $BASE64_NETWORK_CONFIG | base64 -w 0 -d | sed -e 's/evm_key/${{ secrets.QA_SHARED_803C_KEY }}/g' | base64 -w 0) - echo ::add-mask::$BASE64_NETWORK_CONFIG - echo "BASE64_NETWORK_CONFIG=$BASE64_NETWORK_CONFIG" >> "$GITHUB_ENV" SLACK_USER=$(jq -r '.inputs.slackMemberID' $GITHUB_EVENT_PATH) echo ::add-mask::$SLACK_USER echo "SLACK_USER=$SLACK_USER" >> "$GITHUB_ENV" @@ -183,7 +198,7 @@ jobs: chainlinkVersion: ${{ env.CHAINLINK_VERSION }} logstreamLogTargets: ${{ vars.LOGSTREAM_LOG_TARGETS }} - name: Run Tests - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@d38226be720c5ccc1ff4d3cee40608ebf264cd59 # v2.3.26 + uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@94cb11f4bd545607a2f221c6685052b3abee723d # v2.3.32 env: TEST_SUITE: load TEST_ARGS: -test.timeout 900h @@ -194,9 +209,12 @@ jobs: TEST_TRIGGERED_BY: ccip-load-test-ci BASE64_CCIP_CONFIG_OVERRIDE: ${{ steps.set_override_config.outputs.base_64_override }},${{ steps.setup_create_base64_config_ccip.outputs.base64_config }} TEST_BASE64_CCIP_CONFIG_OVERRIDE: ${{ steps.set_override_config.outputs.base_64_override }},${{ steps.setup_create_base64_config_ccip.outputs.base64_config }} + E2E_TEST_GRAFANA_DASHBOARD_URL: "/d/6vjVx-1V8/ccip-long-running-tests" with: test_command_to_run: cd ./integration-tests/ccip-tests && go test -v -timeout 70m -count=1 -json -run ^TestLoadCCIPStableRPS$ ./load 2>&1 | tee /tmp/gotest.log | gotestfmt test_download_vendor_packages_command: cd ./integration-tests && go mod download + # Other default test secrets loaded from dotenv Github Secret. + test_secrets_defaults_base64: ${{ secrets.CCIP_DEFAULT_TEST_SECRETS }} test_secrets_override_base64: ${{ secrets[inputs.test_secrets_override_key] }} token: ${{ secrets.GITHUB_TOKEN }} go_mod_path: ./integration-tests/go.mod @@ -209,12 +227,6 @@ jobs: cache_key_id: ccip-load-${{ env.MOD_CACHE_VERSION }} cache_restore_only: "true" should_cleanup: false - DEFAULT_CHAINLINK_IMAGE: ${{ env.CHAINLINK_IMAGE }} - DEFAULT_LOKI_TENANT_ID: ${{ vars.LOKI_TENANT_ID }} - DEFAULT_LOKI_ENDPOINT: ${{ secrets.LOKI_URL }} - DEFAULT_LOKI_BASIC_AUTH: ${{ secrets.LOKI_BASIC_AUTH }} - DEFAULT_GRAFANA_BASE_URL: ${{ vars.GRAFANA_URL }} - DEFAULT_GRAFANA_DASHBOARD_URL: "/d/6vjVx-1V8/ccip-long-running-tests" ccip-smoke-test: name: CCIP smoke Test @@ -236,7 +248,6 @@ jobs: TEST_LOG_LEVEL: info REF_NAME: ${{ github.head_ref || github.ref_name }} ENV_JOB_IMAGE_BASE: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink-ccip-tests - BASE64_NETWORK_CONFIG: ${{ secrets.BASE64_NETWORK_CONFIG }} steps: - name: Collect Metrics @@ -257,9 +268,6 @@ jobs: id: set_override_config shell: bash run: | - BASE64_NETWORK_CONFIG=$(echo $BASE64_NETWORK_CONFIG | base64 -w 0 -d | sed -e 's/evm_key/${{ secrets.QA_SHARED_803C_KEY }}/g' | base64 -w 0) - echo ::add-mask::$BASE64_NETWORK_CONFIG - echo "BASE64_NETWORK_CONFIG=$BASE64_NETWORK_CONFIG" >> "$GITHUB_ENV" SLACK_USER=$(jq -r '.inputs.slackMemberID' $GITHUB_EVENT_PATH) echo ::add-mask::$SLACK_USER echo "SLACK_USER=$SLACK_USER" >> "$GITHUB_ENV" @@ -284,7 +292,7 @@ jobs: chainlinkVersion: ${{ env.CHAINLINK_VERSION }} logstreamLogTargets: ${{ vars.LOGSTREAM_LOG_TARGETS }} - name: Run Tests - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@d38226be720c5ccc1ff4d3cee40608ebf264cd59 # v2.3.26 + uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@94cb11f4bd545607a2f221c6685052b3abee723d # v2.3.32 env: TEST_SUITE: smoke TEST_ARGS: -test.timeout 900h @@ -295,9 +303,13 @@ jobs: TEST_TRIGGERED_BY: ccip-smoke-test-ci BASE64_CCIP_CONFIG_OVERRIDE: ${{ steps.set_override_config.outputs.base_64_override }},${{ steps.setup_create_base64_config_ccip.outputs.base64_config }} TEST_BASE64_CCIP_CONFIG_OVERRIDE: ${{ steps.set_override_config.outputs.base_64_override }},${{ steps.setup_create_base64_config_ccip.outputs.base64_config }} + E2E_TEST_GRAFANA_DASHBOARD_URL: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" with: test_command_to_run: cd ./integration-tests/ccip-tests && go test -v -timeout 70m -count=1 -p 30 -json -run ^TestSmokeCCIPForBidirectionalLane$ ./smoke 2>&1 | tee /tmp/gotest.log | gotestfmt test_download_vendor_packages_command: cd ./integration-tests && go mod download + # Other default test secrets loaded from dotenv Github Secret. + test_secrets_defaults_base64: ${{ secrets.CCIP_DEFAULT_TEST_SECRETS }} + test_secrets_override_base64: ${{ secrets[inputs.test_secrets_override_key] }} token: ${{ secrets.GITHUB_TOKEN }} go_mod_path: ./integration-tests/go.mod QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} @@ -308,10 +320,4 @@ jobs: aws_registries: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} cache_key_id: ccip-smoke-${{ env.MOD_CACHE_VERSION }} cache_restore_only: "true" - should_cleanup: false - DEFAULT_CHAINLINK_IMAGE: ${{ env.CHAINLINK_IMAGE }} - DEFAULT_LOKI_TENANT_ID: ${{ vars.LOKI_TENANT_ID }} - DEFAULT_LOKI_ENDPOINT: ${{ secrets.LOKI_URL }} - DEFAULT_LOKI_BASIC_AUTH: ${{ secrets.LOKI_BASIC_AUTH }} - DEFAULT_GRAFANA_BASE_URL: ${{ vars.GRAFANA_URL }} - DEFAULT_GRAFANA_DASHBOARD_URL: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" \ No newline at end of file + should_cleanup: false \ No newline at end of file diff --git a/.github/workflows/ccip-load-tests.yml b/.github/workflows/ccip-load-tests.yml index f88f5bd143..633effd86c 100644 --- a/.github/workflows/ccip-load-tests.yml +++ b/.github/workflows/ccip-load-tests.yml @@ -29,6 +29,26 @@ env: INTERNAL_DOCKER_REPO: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com AWS_ECR_REPO_PUBLIC_REGISTRY: public.ecr.aws MOD_CACHE_VERSION: 1 + E2E_TEST_CHAINLINK_IMAGE: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink + E2E_TEST_LOKI_TENANT_ID: ${{ vars.LOKI_TENANT_ID }} + E2E_TEST_LOKI_ENDPOINT: ${{ secrets.LOKI_URL }} + E2E_TEST_LOKI_BASIC_AUTH: ${{ secrets.LOKI_BASIC_AUTH }} + E2E_TEST_GRAFANA_BASE_URL: ${{ vars.GRAFANA_URL }} + # Default private key test secret loaded from Github Secret as only security team has access to it. + # this key secrets.QA_SHARED_803C_KEY has a story behind it. To know more, see CCIP-2875 and SECHD-16575 tickets. + E2E_TEST_ETHEREUM_MAINNET_WALLET_KEY: ${{ secrets.QA_SHARED_803C_KEY }} + E2E_TEST_ARBITRUM_MAINNET_WALLET_KEY: ${{ secrets.QA_SHARED_803C_KEY }} + E2E_TEST_BASE_MAINNET_WALLET_KEY: ${{ secrets.QA_SHARED_803C_KEY }} + E2E_TEST_WEMIX_MAINNET_WALLET_KEY: ${{ secrets.QA_SHARED_803C_KEY }} + E2E_TEST_AVALANCHE_MAINNET_WALLET_KEY: ${{ secrets.QA_SHARED_803C_KEY }} + E2E_TEST_ZKSYNC_MAINNET_WALLET_KEY: ${{ secrets.QA_SHARED_803C_KEY }} + E2E_TEST_MODE_MAINNET_WALLET_KEY: ${{ secrets.QA_SHARED_803C_KEY }} + E2E_TEST_METIS_ANDROMEDA_WALLET_KEY: ${{ secrets.QA_SHARED_803C_KEY }} + E2E_TEST_OPTIMISM_MAINNET_WALLET_KEY: ${{ secrets.QA_SHARED_803C_KEY }} + E2E_TEST_KROMA_MAINNET_WALLET_KEY: ${{ secrets.QA_SHARED_803C_KEY }} + E2E_TEST_GNOSIS_MAINNET_WALLET_KEY: ${{ secrets.QA_SHARED_803C_KEY }} + E2E_TEST_POLYGON_MAINNET_WALLET_KEY: ${{ secrets.QA_SHARED_803C_KEY }} + E2E_TEST_BSC_MAINNET_WALLET_KEY: ${{ secrets.QA_SHARED_803C_KEY }} jobs: build-chainlink: @@ -116,7 +136,6 @@ jobs: SLACK_CHANNEL: ${{ secrets.QA_SLACK_CHANNEL }} TEST_LOG_LEVEL: info REF_NAME: ${{ github.head_ref || github.ref_name }} - BASE64_NETWORK_CONFIG: ${{ secrets.BASE64_NETWORK_CONFIG }} strategy: fail-fast: false matrix: @@ -177,7 +196,7 @@ jobs: chainlinkVersion: ${{ github.sha }} logstreamLogTargets: ${{ vars.LOGSTREAM_LOG_TARGETS }} - name: Run Tests - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@d38226be720c5ccc1ff4d3cee40608ebf264cd59 # v2.3.26 + uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@94cb11f4bd545607a2f221c6685052b3abee723d # v2.3.32 env: TEST_SUITE: load TEST_ARGS: -test.timeout 900h @@ -187,9 +206,13 @@ jobs: TEST_TRIGGERED_BY: ccip-load-test-ci-${{ matrix.type.name }} BASE64_CCIP_CONFIG_OVERRIDE: ${{ steps.set_override_config.outputs.base_64_override }},${{ steps.setup_create_base64_config_ccip.outputs.base64_config }} TEST_BASE64_CCIP_CONFIG_OVERRIDE: ${{ steps.set_override_config.outputs.base_64_override }},${{ steps.setup_create_base64_config_ccip.outputs.base64_config }} + E2E_TEST_GRAFANA_DASHBOARD_URL: "/d/6vjVx-1V8/ccip-long-running-tests" with: test_command_to_run: cd ./integration-tests/ccip-tests && go test -v -timeout 70m -count=1 -json -run ${{ matrix.type.run }} ./load 2>&1 | tee /tmp/gotest.log | gotestloghelper -ci test_download_vendor_packages_command: cd ./integration-tests && go mod download + # Load default test secrets + test_secrets_defaults_base64: ${{ secrets.CCIP_DEFAULT_TEST_SECRETS }} + # Override default test secrets with custom test secrets if provided test_secrets_override_base64: ${{ secrets[inputs.test_secrets_override_key] }} token: ${{ secrets.GITHUB_TOKEN }} go_mod_path: ./integration-tests/go.mod @@ -203,12 +226,6 @@ jobs: cache_key_id: ccip-load-${{ env.MOD_CACHE_VERSION }} cache_restore_only: "true" should_cleanup: "true" - DEFAULT_CHAINLINK_IMAGE: ${{ env.CHAINLINK_IMAGE }} - DEFAULT_LOKI_TENANT_ID: ${{ vars.LOKI_TENANT_ID }} - DEFAULT_LOKI_ENDPOINT: ${{ secrets.LOKI_URL }} - DEFAULT_LOKI_BASIC_AUTH: ${{ secrets.LOKI_BASIC_AUTH }} - DEFAULT_GRAFANA_BASE_URL: ${{ vars.GRAFANA_URL }} - DEFAULT_GRAFANA_DASHBOARD_URL: "/d/6vjVx-1V8/ccip-long-running-tests" # Reporting Jobs start-slack-thread: diff --git a/.github/workflows/ccip-offchain-upgrade-tests.yml b/.github/workflows/ccip-offchain-upgrade-tests.yml index 147f727425..3fe3c79cdd 100644 --- a/.github/workflows/ccip-offchain-upgrade-tests.yml +++ b/.github/workflows/ccip-offchain-upgrade-tests.yml @@ -19,6 +19,21 @@ env: INTERNAL_DOCKER_REPO: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com MOD_CACHE_VERSION: 2 AWS_ECR_REPO_PUBLIC_REGISTRY: public.ecr.aws + # Default private key test secret loaded from Github Secret as only security team has access to it. + # this key secrets.QA_SHARED_803C_KEY has a story behind it. To know more, see CCIP-2875 and SECHD-16575 tickets. + E2E_TEST_ETHEREUM_MAINNET_WALLET_KEY: ${{ secrets.QA_SHARED_803C_KEY }} + E2E_TEST_ARBITRUM_MAINNET_WALLET_KEY: ${{ secrets.QA_SHARED_803C_KEY }} + E2E_TEST_BASE_MAINNET_WALLET_KEY: ${{ secrets.QA_SHARED_803C_KEY }} + E2E_TEST_WEMIX_MAINNET_WALLET_KEY: ${{ secrets.QA_SHARED_803C_KEY }} + E2E_TEST_AVALANCHE_MAINNET_WALLET_KEY: ${{ secrets.QA_SHARED_803C_KEY }} + E2E_TEST_ZKSYNC_MAINNET_WALLET_KEY: ${{ secrets.QA_SHARED_803C_KEY }} + E2E_TEST_MODE_MAINNET_WALLET_KEY: ${{ secrets.QA_SHARED_803C_KEY }} + E2E_TEST_METIS_ANDROMEDA_WALLET_KEY: ${{ secrets.QA_SHARED_803C_KEY }} + E2E_TEST_OPTIMISM_MAINNET_WALLET_KEY: ${{ secrets.QA_SHARED_803C_KEY }} + E2E_TEST_KROMA_MAINNET_WALLET_KEY: ${{ secrets.QA_SHARED_803C_KEY }} + E2E_TEST_GNOSIS_MAINNET_WALLET_KEY: ${{ secrets.QA_SHARED_803C_KEY }} + E2E_TEST_POLYGON_MAINNET_WALLET_KEY: ${{ secrets.QA_SHARED_803C_KEY }} + E2E_TEST_BSC_MAINNET_WALLET_KEY: ${{ secrets.QA_SHARED_803C_KEY }} jobs: # Build Test Dependencies @@ -230,7 +245,7 @@ jobs: selectedNetworks: SIMULATED_1,SIMULATED_2 - name: Run Tests if: needs.changes.outputs.src == 'true' || github.event_name == 'workflow_dispatch' - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@d38226be720c5ccc1ff4d3cee40608ebf264cd59 # v2.3.26 + uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@94cb11f4bd545607a2f221c6685052b3abee723d # v2.3.32 env: BASE64_CCIP_CONFIG_OVERRIDE: ${{ steps.set_override_config.outputs.base_64_override }},${{ steps.setup_create_base64_config_ccip.outputs.base64_config }} TEST_BASE64_CCIP_CONFIG_OVERRIDE: ${{ steps.set_override_config.outputs.base_64_override }},${{ steps.setup_create_base64_config_ccip.outputs.base64_config }} @@ -241,10 +256,17 @@ jobs: DATABASE_URL: postgresql://postgres:node@localhost:5432/chainlink_test?sslmode=disable RR_MEM: 8Gi RR_CPU: 4 - BASE64_NETWORK_CONFIG: ${{ secrets.BASE64_NETWORK_CONFIG }} + E2E_TEST_CHAINLINK_IMAGE: ${{ env.AWS_ECR_REPO_PUBLIC_REGISTRY }}/w0i8p0z9/chainlink-ccip + E2E_TEST_LOKI_TENANT_ID: ${{ vars.LOKI_TENANT_ID }} + E2E_TEST_LOKI_ENDPOINT: ${{ secrets.LOKI_URL_CI }} + E2E_TEST_LOKI_BASIC_AUTH: ${{ secrets.LOKI_BASIC_AUTH }} + E2E_TEST_GRAFANA_BASE_URL: ${{ vars.GRAFANA_URL }} + E2E_TEST_GRAFANA_DASHBOARD_URL: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" with: test_command_to_run: cd ./integration-tests/ccip-tests && go test -timeout 30m -count=1 -json -run ${{ matrix.product.run }} ./smoke 2>&1 | tee /tmp/gotest.log | gotestloghelper -ci test_download_vendor_packages_command: cd ./integration-tests && go mod download + # Load default test secrets + test_secrets_defaults_base64: ${{ secrets.CCIP_DEFAULT_TEST_SECRETS }} cl_repo: ${{ env.AWS_ECR_REPO_PUBLIC_REGISTRY }}/w0i8p0z9/chainlink-ccip # releases are published to public registry cl_image_tag: ${{ env.RELEASE_TAG }} aws_registries: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} @@ -261,12 +283,6 @@ jobs: triggered_by: ${{ env.TEST_TRIGGERED_BY }} should_tidy: "false" should_cleanup: "false" - DEFAULT_CHAINLINK_IMAGE: ${{ env.AWS_ECR_REPO_PUBLIC_REGISTRY }}/w0i8p0z9/chainlink-ccip - DEFAULT_LOKI_TENANT_ID: ${{ vars.LOKI_TENANT_ID }} - DEFAULT_LOKI_ENDPOINT: ${{ secrets.LOKI_URL_CI }} - DEFAULT_LOKI_BASIC_AUTH: ${{ secrets.LOKI_BASIC_AUTH }} - DEFAULT_GRAFANA_BASE_URL: ${{ vars.GRAFANA_URL }} - DEFAULT_GRAFANA_DASHBOARD_URL: "/d/ddf75041-1e39-42af-aa46-361fe4c36e9e/ci-e2e-tests-logs" - name: store laneconfig in artifacts uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 @@ -353,7 +369,7 @@ jobs: existingNamespace: ${{ needs.run-test-with-last-release.outputs.existing_namespace }} - name: Run Tests if: needs.changes.outputs.src == 'true' || github.event_name == 'workflow_dispatch' - uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@d38226be720c5ccc1ff4d3cee40608ebf264cd59 # v2.3.26 + uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@94cb11f4bd545607a2f221c6685052b3abee723d # v2.3.32 env: BASE64_CCIP_CONFIG_OVERRIDE: ${{ steps.set_override_config.outputs.base_64_override }},${{ steps.setup_create_base64_config_ccip.outputs.base64_config }} TEST_BASE64_CCIP_CONFIG_OVERRIDE: ${{ steps.set_override_config.outputs.base_64_override }},${{ steps.setup_create_base64_config_ccip.outputs.base64_config }} @@ -363,9 +379,18 @@ jobs: DATABASE_URL: postgresql://postgres:node@localhost:5432/chainlink_test?sslmode=disable RR_MEM: 8Gi RR_CPU: 4 + E2E_TEST_GRAFANA_DASHBOARD_URL: "/d/6vjVx-1V8/ccip-long-running-tests" + E2E_TEST_CHAINLINK_IMAGE: ${{ env.CHAINLINK_IMAGE }} + E2E_TEST_CHAINLINK_UPGRADE_IMAGE: ${{ env.CHAINLINK_IMAGE }} + E2E_TEST_LOKI_TENANT_ID: ${{ vars.LOKI_TENANT_ID }} + E2E_TEST_LOKI_ENDPOINT: ${{ secrets.LOKI_URL }} + E2E_TEST_LOKI_BASIC_AUTH: ${{ secrets.LOKI_BASIC_AUTH }} + E2E_TEST_GRAFANA_BASE_URL: ${{ vars.GRAFANA_URL }} with: test_command_to_run: cd ./integration-tests/ccip-tests && go test -timeout 1h -count=1 -json -run ${{ matrix.product.run }} ./load 2>&1 | tee /tmp/gotest.log | gotestloghelper -ci test_download_vendor_packages_command: cd ./integration-tests && go mod download + # Load default test secrets + test_secrets_defaults_base64: ${{ secrets.CCIP_DEFAULT_TEST_SECRETS }} cl_repo: ${{ env.CHAINLINK_IMAGE }} cl_image_tag: ${{ github.sha }} aws_registries: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} @@ -384,10 +409,3 @@ jobs: should_tidy: "false" should_cleanup: "true" triggered_by: ${{ needs.run-test-with-last-release.outputs.triggered_by }} - DEFAULT_CHAINLINK_IMAGE: ${{ env.CHAINLINK_IMAGE }} - DEFAULT_CHAINLINK_UPGRADE_IMAGE: ${{ env.CHAINLINK_IMAGE }} - DEFAULT_LOKI_TENANT_ID: ${{ vars.LOKI_TENANT_ID }} - DEFAULT_LOKI_ENDPOINT: ${{ secrets.LOKI_URL }} - DEFAULT_LOKI_BASIC_AUTH: ${{ secrets.LOKI_BASIC_AUTH }} - DEFAULT_GRAFANA_BASE_URL: ${{ vars.GRAFANA_URL }} - DEFAULT_GRAFANA_DASHBOARD_URL: "/d/6vjVx-1V8/ccip-long-running-tests" \ No newline at end of file diff --git a/integration-tests/ccip-tests/Makefile b/integration-tests/ccip-tests/Makefile index d33d956915..8fdd635fd6 100644 --- a/integration-tests/ccip-tests/Makefile +++ b/integration-tests/ccip-tests/Makefile @@ -1,5 +1,5 @@ ## To Override the default config: -# example usage: make set_config override_toml=../config/config.toml network_config_toml=../config/network.toml +# example usage: make set_config override_toml=../config/config.toml .PHONY: set_config set_config: if [ -s "$(override_toml)" ]; then \ @@ -12,10 +12,6 @@ set_config: echo "No override config found, using default config"; \ echo > ./testconfig/override/.env; \ fi - if [ -s "$(network_config_toml)" ]; then \ - echo "Overriding network config with $(network_config_toml)"; \ - echo "export BASE64_NETWORK_CONFIG=$$(base64 -i $(network_config_toml))" >> ./testconfig/override/.env; \ - fi @echo "Checking for test secrets file in ~/.testsecrets..."; @if [ ! -f ~/.testsecrets ]; then \ diff --git a/integration-tests/ccip-tests/testconfig/README.md b/integration-tests/ccip-tests/testconfig/README.md index e22a5e4d59..bcf468a36c 100644 --- a/integration-tests/ccip-tests/testconfig/README.md +++ b/integration-tests/ccip-tests/testconfig/README.md @@ -10,7 +10,7 @@ The test config is read in following order: - The config mentioned in this file will override the default config. - Example override file - [override.toml.example](./examples/override.toml.example) - If there are sensitive details like private keys, credentials in test config, they can be specified in a separate dotenv file as env vars - - The `~/.testsecrets` file in home directory is automatically loaded and should have all test secrets as env vars + - The `~/.testsecrets` file in home directory is automatically loaded and should have all test secrets as env vars. Learn more about it [here](https://github.com/smartcontractkit/chainlink-testing-framework/blob/main/config/README.md#test-secrets) - Example secret file - [.testsecrets.example](./examples/.testsecrets.example) ## CCIP.ContractVersions @@ -119,14 +119,7 @@ Mandatory fields are: - **NewCLCluster**: [CCIP.Env.NewCLCluster](#ccipenvnewclcluster) - This is mandatory if the test needs to deploy Chainlink nodes. - **ExistingCLCluster**: [CCIP.Env.ExistingCLCluster](#ccipenvexistingclcluster) - This is mandatory if the test needs to run on existing Chainlink nodes to deploy ccip jobs. -Test needs network/chain details to be set through configuration. This configuration is mandatory for running the tests. -you have option to set the network details in two ways: - -1. Using [CCIP.Env.Networks](#ccipenvnetworks) -2. Using a separate network config file - - - refer to the example - [network_config.toml.example](./examples/network_config.toml.example) - - once all necessary values are set, encode the toml file content in base64 format, - - set the base64'ed string content in `BASE64_NETWORK_CONFIG` environment variable. +Test needs network/chain details to be set through configuration. Set network urls in ~/.testsecrets [see docs](https://github.com/smartcontractkit/chainlink-testing-framework/blob/main/config/README.md#test-secrets). ### CCIP.Env.Networks diff --git a/integration-tests/ccip-tests/testconfig/examples/network_config.toml.example b/integration-tests/ccip-tests/testconfig/examples/network_config.toml.example deleted file mode 100644 index ffed99a771..0000000000 --- a/integration-tests/ccip-tests/testconfig/examples/network_config.toml.example +++ /dev/null @@ -1,168 +0,0 @@ -[RpcHttpUrls] -ETHEREUM_MAINNET = [ - 'https:....', - 'https:......', -] -AVALANCHE_MAINNET = [ - 'https:....', - 'https:......', -] -BASE_MAINNET = [ - 'https:....', - 'https:......', -] -ARBITRUM_MAINNET = [ - 'https:....', - 'https:......', -] -BSC_MAINNET = [ - 'https:....', - 'https:......', -] -OPTIMISM_MAINNET = [ - 'https:....', - 'https:......', -] -POLYGON_MAINNET = [ - 'https:....', - 'https:......', -] -WEMIX_MAINNET = [ - 'https:....', - 'https:......', -] -KROMA_MAINNET = [ - 'https:....', - 'https:......', -] - -OPTIMISM_SEPOLIA = [ - 'https:....', - 'https:......', -] -SEPOLIA = [ - 'https:....', - 'https:......', -] -AVALANCHE_FUJI = [ - 'https:....', - 'https:......', -] -ARBITRUM_SEPOLIA = [ - 'https:....', - 'https:......', -] -POLYGON_MUMBAI = [ - 'https:....', - 'https:......', -] -BASE_SEPOLIA = [ - 'https:....', - 'https:......', -] -BSC_TESTNET = [ - 'https:....', - 'https:......', -] -KROMA_SEPOLIA = [ - 'https:....', - 'https:......', -] -WEMIX_TESTNET = [ - 'https:....', - 'https:......', -] - -[RpcWsUrls] -ETHEREUM_MAINNET = [ - 'wss://......', - 'wss://.........' -] -AVALANCHE_MAINNET = [ - 'wss://......', - 'wss://.........' -] -BASE_MAINNET = [ - 'wss://......', - 'wss://.........' -] -ARBITRUM_MAINNET = [ - 'wss://......', - 'wss://.........' -] -BSC_MAINNET = [ - 'wss://......', - 'wss://.........' -] -POLYGON_MAINNET = [ - 'wss://......', - 'wss://.........' -] -OPTIMISM_MAINNET = [ - 'wss://......', - 'wss://.........' -] -WEMIX_MAINNET = [ - 'wss://......', - 'wss://.........' -] -KROMA_MAINNET = [ - 'wss://......', - 'wss://.........' -] -OPTIMISM_SEPOLIA = [ - 'wss://......', - 'wss://.........' -] -SEPOLIA = [ - 'wss://......', - 'wss://.........' -] -AVALANCHE_FUJI = [ - 'wss://......', - 'wss://.........' -] -ARBITRUM_SEPOLIA = [ - 'wss://......', - 'wss://.........' -] -POLYGON_MUMBAI = [ - 'wss://......', - 'wss://.........' -] -BASE_SEPOLIA = [ - 'wss://......', - 'wss://.........' -] -BSC_TESTNET = [ - 'wss://......', - 'wss://.........' -] -KROMA_SEPOLIA = [ - 'wss://......', - 'wss://.........' -] -WEMIX_TESTNET = [ - 'wss://......', - 'wss://.........' -] - -[WalletKeys] -ETHEREUM_MAINNET = [''] -AVALANCHE_MAINNET = [''] -BASE_MAINNET = [''] -ARBITRUM_MAINNET = [''] -BSC_MAINNET = [''] -POLYGON_MAINNET = [''] -OPTIMISM_MAINNET = [''] -WEMIX_MAINNET = [''] -KROMA_MAINNET = [''] -OPTIMISM_SEPOLIA = [''] -SEPOLIA = [''] -AVALANCHE_FUJI = [''] -ARBITRUM_SEPOLIA = [''] -POLYGON_MUMBAI = [''] -BASE_SEPOLIA = [''] -BSC_TESTNET = [''] -KROMA_SEPOLIA = [''] -WEMIX_TESTNET = [''] \ No newline at end of file From f105b1b56a0f3cb312200fe48eba5486ddca95c1 Mon Sep 17 00:00:00 2001 From: Mateusz Sekara Date: Mon, 2 Sep 2024 09:56:59 +0200 Subject: [PATCH 061/115] Post merge fixes --- .../v0.8/keystone/KeystoneFeedsConsumer.sol | 77 ++++++++++++++-- core/capabilities/integration_tests/setup.go | 1 + core/internal/cltest/cltest.go | 2 - core/services/chainlink/application.go | 28 ++---- integration-tests/go.mod | 19 +--- integration-tests/go.sum | 38 +------- integration-tests/load/go.mod | 55 ++++++------ integration-tests/load/go.sum | 90 ++++++++++--------- 8 files changed, 157 insertions(+), 153 deletions(-) diff --git a/contracts/src/v0.8/keystone/KeystoneFeedsConsumer.sol b/contracts/src/v0.8/keystone/KeystoneFeedsConsumer.sol index bc722eff29..ba1a7c6a8c 100644 --- a/contracts/src/v0.8/keystone/KeystoneFeedsConsumer.sol +++ b/contracts/src/v0.8/keystone/KeystoneFeedsConsumer.sol @@ -1,15 +1,17 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.24; +import {IERC165} from "../vendor/openzeppelin-solidity/v4.8.3/contracts/interfaces/IERC165.sol"; +import {OwnerIsCreator} from "../shared/access/OwnerIsCreator.sol"; import {IReceiver} from "./interfaces/IReceiver.sol"; -import {KeystoneFeedsPermissionHandler} from "./KeystoneFeedsPermissionHandler.sol"; -import {KeystoneFeedDefaultMetadataLib} from "./lib/KeystoneFeedDefaultMetadataLib.sol"; - -contract KeystoneFeedsConsumer is IReceiver, KeystoneFeedsPermissionHandler { - using KeystoneFeedDefaultMetadataLib for bytes; +contract KeystoneFeedsConsumer is IReceiver, OwnerIsCreator, IERC165 { event FeedReceived(bytes32 indexed feedId, uint224 price, uint32 timestamp); + error UnauthorizedSender(address sender); + error UnauthorizedWorkflowOwner(address workflowOwner); + error UnauthorizedWorkflowName(bytes10 workflowName); + struct ReceivedFeedReport { bytes32 FeedId; uint224 Price; @@ -22,11 +24,53 @@ contract KeystoneFeedsConsumer is IReceiver, KeystoneFeedsPermissionHandler { } mapping(bytes32 feedId => StoredFeedReport feedReport) internal s_feedReports; + address[] internal s_allowedSendersList; + mapping(address sender => bool) internal s_allowedSenders; + address[] internal s_allowedWorkflowOwnersList; + mapping(address owner => bool) internal s_allowedWorkflowOwners; + bytes10[] internal s_allowedWorkflowNamesList; + mapping(bytes10 workflowName => bool) internal s_allowedWorkflowNames; + + function setConfig( + address[] calldata _allowedSendersList, + address[] calldata _allowedWorkflowOwnersList, + bytes10[] calldata _allowedWorkflowNamesList + ) external onlyOwner { + for (uint32 i = 0; i < s_allowedSendersList.length; ++i) { + s_allowedSenders[s_allowedSendersList[i]] = false; + } + for (uint32 i = 0; i < _allowedSendersList.length; ++i) { + s_allowedSenders[_allowedSendersList[i]] = true; + } + s_allowedSendersList = _allowedSendersList; + for (uint32 i = 0; i < s_allowedWorkflowOwnersList.length; ++i) { + s_allowedWorkflowOwners[s_allowedWorkflowOwnersList[i]] = false; + } + for (uint32 i = 0; i < _allowedWorkflowOwnersList.length; ++i) { + s_allowedWorkflowOwners[_allowedWorkflowOwnersList[i]] = true; + } + s_allowedWorkflowOwnersList = _allowedWorkflowOwnersList; + for (uint32 i = 0; i < s_allowedWorkflowNamesList.length; ++i) { + s_allowedWorkflowNames[s_allowedWorkflowNamesList[i]] = false; + } + for (uint32 i = 0; i < _allowedWorkflowNamesList.length; ++i) { + s_allowedWorkflowNames[_allowedWorkflowNamesList[i]] = true; + } + s_allowedWorkflowNamesList = _allowedWorkflowNamesList; + } function onReport(bytes calldata metadata, bytes calldata rawReport) external { - (bytes10 workflowName, address workflowOwner, bytes2 reportName) = metadata._extractMetadataInfo(); + if (!s_allowedSenders[msg.sender]) { + revert UnauthorizedSender(msg.sender); + } - _validateReportPermission(msg.sender, workflowOwner, workflowName, reportName); + (bytes10 workflowName, address workflowOwner) = _getInfo(metadata); + if (!s_allowedWorkflowNames[workflowName]) { + revert UnauthorizedWorkflowName(workflowName); + } + if (!s_allowedWorkflowOwners[workflowOwner]) { + revert UnauthorizedWorkflowOwner(workflowOwner); + } ReceivedFeedReport[] memory feeds = abi.decode(rawReport, (ReceivedFeedReport[])); for (uint256 i = 0; i < feeds.length; ++i) { @@ -35,8 +79,27 @@ contract KeystoneFeedsConsumer is IReceiver, KeystoneFeedsPermissionHandler { } } + // solhint-disable-next-line chainlink-solidity/explicit-returns + function _getInfo(bytes memory metadata) internal pure returns (bytes10 workflowName, address workflowOwner) { + // (first 32 bytes contain length of the byte array) + // workflow_cid // offset 32, size 32 + // workflow_name // offset 64, size 10 + // workflow_owner // offset 74, size 20 + // report_name // offset 94, size 2 + assembly { + // no shifting needed for bytes10 type + workflowName := mload(add(metadata, 64)) + // shift right by 12 bytes to get the actual value + workflowOwner := shr(mul(12, 8), mload(add(metadata, 74))) + } + } + function getPrice(bytes32 feedId) external view returns (uint224, uint32) { StoredFeedReport memory report = s_feedReports[feedId]; return (report.Price, report.Timestamp); } + + function supportsInterface(bytes4 interfaceId) public pure override returns (bool) { + return interfaceId == this.onReport.selector; + } } diff --git a/core/capabilities/integration_tests/setup.go b/core/capabilities/integration_tests/setup.go index bb1d6d087e..6347d55878 100644 --- a/core/capabilities/integration_tests/setup.go +++ b/core/capabilities/integration_tests/setup.go @@ -21,6 +21,7 @@ import ( ocrTypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/keystone/generated/feeds_consumer" + "github.com/smartcontractkit/chainlink/v2/core/utils/testutils/heavyweight" commoncap "github.com/smartcontractkit/chainlink-common/pkg/capabilities" "github.com/smartcontractkit/chainlink-common/pkg/capabilities/consensus/ocr3" diff --git a/core/internal/cltest/cltest.go b/core/internal/cltest/cltest.go index 12491300bf..dc51ddd32f 100644 --- a/core/internal/cltest/cltest.go +++ b/core/internal/cltest/cltest.go @@ -461,8 +461,6 @@ func NewApplicationWithConfig(t testing.TB, cfg chainlink.GeneralConfig, flagsAn LoopRegistry: plugins.NewLoopRegistry(lggr, nil), MercuryPool: mercuryPool, CapabilitiesRegistry: capabilitiesRegistry, - CapabilitiesDispatcher: dispatcher, - CapabilitiesPeerWrapper: peerWrapper, }) require.NoError(t, err) diff --git a/core/services/chainlink/application.go b/core/services/chainlink/application.go index 6eade4879f..cc130d0283 100644 --- a/core/services/chainlink/application.go +++ b/core/services/chainlink/application.go @@ -23,6 +23,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink-common/pkg/utils/jsonserializable" "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" + "github.com/smartcontractkit/chainlink/v2/core/capabilities" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" "github.com/smartcontractkit/chainlink/v2/core/services/standardcapabilities" @@ -31,7 +32,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/bridges" "github.com/smartcontractkit/chainlink/v2/core/build" "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote" - remotetypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" evmutils "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" @@ -180,8 +180,6 @@ type ApplicationOpts struct { GRPCOpts loop.GRPCOpts MercuryPool wsrpc.Pool CapabilitiesRegistry *capabilities.Registry - CapabilitiesDispatcher remotetypes.Dispatcher - CapabilitiesPeerWrapper p2ptypes.PeerWrapper } // NewApplication initializes a new store if one is not already @@ -201,29 +199,14 @@ func NewApplication(opts ApplicationOpts) (Application, error) { restrictedHTTPClient := opts.RestrictedHTTPClient unrestrictedHTTPClient := opts.UnrestrictedHTTPClient - if opts.CapabilitiesRegistry == nil { - // for tests only, in prod Registry should always be set at this point + if opts.CapabilitiesRegistry == nil { // for tests only, in prod Registry is always set at this point opts.CapabilitiesRegistry = capabilities.NewRegistry(globalLogger) } var externalPeerWrapper p2ptypes.PeerWrapper - if cfg.Capabilities().Peering().Enabled() { - var dispatcher remotetypes.Dispatcher - if opts.CapabilitiesDispatcher == nil { - externalPeer := externalp2p.NewExternalPeerWrapper(keyStore.P2P(), cfg.Capabilities().Peering(), opts.DS, globalLogger) - signer := externalPeer - externalPeerWrapper = externalPeer - remoteDispatcher := remote.NewDispatcher(externalPeerWrapper, signer, opts.CapabilitiesRegistry, globalLogger) - srvcs = append(srvcs, remoteDispatcher) - - dispatcher = remoteDispatcher - } else { - dispatcher = opts.CapabilitiesDispatcher - externalPeerWrapper = opts.CapabilitiesPeerWrapper - } - - srvcs = append(srvcs, externalPeerWrapper) + var capabilityRegistrySyncer registrysyncer.Syncer + if cfg.Capabilities().ExternalRegistry().Address() != "" { rid := cfg.Capabilities().ExternalRegistry().RelayID() registryAddress := cfg.Capabilities().ExternalRegistry().Address() relayer, err := relayerChainInterops.Get(rid) @@ -263,7 +246,8 @@ func NewApplication(opts ApplicationOpts) (Application, error) { opts.CapabilitiesRegistry, ) - srvcs = append(srvcs, dispatcher, wfLauncher, registrySyncer) + capabilityRegistrySyncer.AddLauncher(wfLauncher) + srvcs = append(srvcs, dispatcher, wfLauncher) } // LOOPs can be created as options, in the case of LOOP relayers, or diff --git a/integration-tests/go.mod b/integration-tests/go.mod index 487064e286..38bce599a7 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -35,8 +35,9 @@ require ( github.com/smartcontractkit/chain-selectors v1.0.23 github.com/smartcontractkit/chainlink-automation v1.0.4 github.com/smartcontractkit/chainlink-common v0.2.2-0.20240723123524-e407ecd120b1 - github.com/smartcontractkit/chainlink-testing-framework v1.34.12 + github.com/smartcontractkit/chainlink-testing-framework v1.34.5 github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240405215812-5a72bc9af239 + github.com/smartcontractkit/chainlink-testing-framework/seth v1.2.1 github.com/smartcontractkit/chainlink/integration-tests v0.0.0-00010101000000-000000000000 github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000 github.com/smartcontractkit/havoc/k8schaos v0.0.0-20240409145249-e78d20847e37 @@ -104,22 +105,8 @@ require ( github.com/avast/retry-go v3.0.0+incompatible // indirect github.com/awalterschulze/gographviz v2.0.3+incompatible // indirect github.com/aws/aws-sdk-go v1.45.25 // indirect - github.com/aws/aws-sdk-go-v2 v1.30.4 // indirect - github.com/aws/aws-sdk-go-v2/config v1.27.28 // indirect - github.com/aws/aws-sdk-go-v2/credentials v1.17.28 // indirect - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.12 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.16 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.16 // indirect - github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.4 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.18 // indirect - github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.32.5 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.22.5 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.5 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.30.4 // indirect github.com/aws/constructs-go/constructs/v10 v10.1.255 // indirect github.com/aws/jsii-runtime-go v1.75.0 // indirect - github.com/aws/smithy-go v1.20.4 // indirect github.com/bahlo/generic-list-go v0.2.0 // indirect github.com/benbjohnson/clock v1.3.5 // indirect github.com/beorn7/perks v1.0.1 // indirect @@ -409,8 +396,6 @@ require ( github.com/smartcontractkit/chainlink-feeds v0.0.0-20240710170203-5b41615da827 // indirect github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240712132946-267a37c5ac6e // indirect github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240709043547-03612098f799 // indirect - github.com/smartcontractkit/chainlink-testing-framework/seth v1.2.1-0.20240827112945-bd8c580392d6 // indirect - github.com/smartcontractkit/chainlink-testing-framework/wasp v0.4.9 // indirect github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 // indirect github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1 // indirect github.com/smartcontractkit/wsrpc v0.8.1 // indirect diff --git a/integration-tests/go.sum b/integration-tests/go.sum index c44820aa4f..3f6009ae72 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -215,38 +215,10 @@ github.com/aws/aws-sdk-go v1.23.20/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpi github.com/aws/aws-sdk-go v1.38.35/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= github.com/aws/aws-sdk-go v1.45.25 h1:c4fLlh5sLdK2DCRTY1z0hyuJZU4ygxX8m1FswL6/nF4= github.com/aws/aws-sdk-go v1.45.25/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= -github.com/aws/aws-sdk-go-v2 v1.30.4 h1:frhcagrVNrzmT95RJImMHgabt99vkXGslubDaDagTk8= -github.com/aws/aws-sdk-go-v2 v1.30.4/go.mod h1:CT+ZPWXbYrci8chcARI3OmI/qgd+f6WtuLOoaIA8PR0= -github.com/aws/aws-sdk-go-v2/config v1.27.28 h1:OTxWGW/91C61QlneCtnD62NLb4W616/NM1jA8LhJqbg= -github.com/aws/aws-sdk-go-v2/config v1.27.28/go.mod h1:uzVRVtJSU5EFv6Fu82AoVFKozJi2ZCY6WRCXj06rbvs= -github.com/aws/aws-sdk-go-v2/credentials v1.17.28 h1:m8+AHY/ND8CMHJnPoH7PJIRakWGa4gbfbxuY9TGTUXM= -github.com/aws/aws-sdk-go-v2/credentials v1.17.28/go.mod h1:6TF7dSc78ehD1SL6KpRIPKMA1GyyWflIkjqg+qmf4+c= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.12 h1:yjwoSyDZF8Jth+mUk5lSPJCkMC0lMy6FaCD51jm6ayE= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.12/go.mod h1:fuR57fAgMk7ot3WcNQfb6rSEn+SUffl7ri+aa8uKysI= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.16 h1:TNyt/+X43KJ9IJJMjKfa3bNTiZbUP7DeCxfbTROESwY= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.16/go.mod h1:2DwJF39FlNAUiX5pAc0UNeiz16lK2t7IaFcm0LFHEgc= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.16 h1:jYfy8UPmd+6kJW5YhY0L1/KftReOGxI/4NtVSTh9O/I= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.16/go.mod h1:7ZfEPZxkW42Afq4uQB8H2E2e6ebh6mXTueEpYzjCzcs= -github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 h1:VaRN3TlFdd6KxX1x3ILT5ynH6HvKgqdiXoTxAF4HQcQ= -github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1/go.mod h1:FbtygfRFze9usAadmnGJNc8KsP346kEe+y2/oyhGAGc= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.4 h1:KypMCbLPPHEmf9DgMGw51jMj77VfGPAN2Kv4cfhlfgI= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.4/go.mod h1:Vz1JQXliGcQktFTN/LN6uGppAIRoLBR2bMvIMP0gOjc= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.18 h1:tJ5RnkHCiSH0jyd6gROjlJtNwov0eGYNz8s8nFcR0jQ= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.18/go.mod h1:++NHzT+nAF7ZPrHPsA+ENvsXkOO8wEu+C6RXltAG4/c= -github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.32.5 h1:UDXu9dqpCZYonj7poM4kFISjzTdWI0v3WUusM+w+Gfc= -github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.32.5/go.mod h1:5NPkI3RsTOhwz1CuG7VVSgJCm3CINKkoIaUbUZWQ67w= -github.com/aws/aws-sdk-go-v2/service/sso v1.22.5 h1:zCsFCKvbj25i7p1u94imVoO447I/sFv8qq+lGJhRN0c= -github.com/aws/aws-sdk-go-v2/service/sso v1.22.5/go.mod h1:ZeDX1SnKsVlejeuz41GiajjZpRSWR7/42q/EyA/QEiM= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.5 h1:SKvPgvdvmiTWoi0GAJ7AsJfOz3ngVkD/ERbs5pUnHNI= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.5/go.mod h1:20sz31hv/WsPa3HhU3hfrIet2kxM4Pe0r20eBZ20Tac= -github.com/aws/aws-sdk-go-v2/service/sts v1.30.4 h1:iAckBT2OeEK/kBDyN/jDtpEExhjeeA/Im2q4X0rJZT8= -github.com/aws/aws-sdk-go-v2/service/sts v1.30.4/go.mod h1:vmSqFK+BVIwVpDAGZB3CoCXHzurt4qBE8lf+I/kRTh0= github.com/aws/constructs-go/constructs/v10 v10.1.255 h1:5hARfEmhBqHSTQf/C3QLA3sWOxO2Dfja0iA1W7ZcI7g= github.com/aws/constructs-go/constructs/v10 v10.1.255/go.mod h1:DCdBSjN04Ck2pajCacTD4RKFqSA7Utya8d62XreYctI= github.com/aws/jsii-runtime-go v1.75.0 h1:NhpUfyiL7/wsRuUekFsz8FFBCYLfPD/l61kKg9kL/a4= github.com/aws/jsii-runtime-go v1.75.0/go.mod h1:TKCyrtM0pygEPo4rDZzbMSDNCDNTSYSN6/mGyHI6O3I= -github.com/aws/smithy-go v1.20.4 h1:2HK1zBdPgRbjFOHlfeQZfpC4r72MOb9bZkiFwggKO+4= -github.com/aws/smithy-go v1.20.4/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg= github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk= github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg= github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df h1:GSoSVRLoBaFpOOds6QyY1L8AX7uoY+Ln3BHc22W40X0= @@ -1437,14 +1409,12 @@ github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240712132946-267a37c5ac6 github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240712132946-267a37c5ac6e/go.mod h1:hsFhop+SlQHKD+DEFjZrMJmbauT1A/wvtZIeeo4PxFU= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240709043547-03612098f799 h1:HyLTySm7BR+oNfZqDTkVJ25wnmcTtxBBD31UkFL+kEM= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240709043547-03612098f799/go.mod h1:UVFRacRkP7O7TQAzFmR52v5mUlxf+G1ovMlCQAB/cHU= -github.com/smartcontractkit/chainlink-testing-framework v1.34.12 h1:pI0ESAspOcEqQ1fm53+3o2laGNwP8wbQNAmrGp5Tw1A= -github.com/smartcontractkit/chainlink-testing-framework v1.34.12/go.mod h1:ekYJbRAxXcs/YgOjHsY9/tlvDvXzv3lxcZK2eFUZduc= +github.com/smartcontractkit/chainlink-testing-framework v1.34.5 h1:6itLSDW4NHDDNR+Y+Z8YDzxxCN9SjdKb6SmLCl0vTFM= +github.com/smartcontractkit/chainlink-testing-framework v1.34.5/go.mod h1:hRZEDh2+afO8MSZb9qYNscmWb+3mHZf01J5ACZuIdTQ= github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240405215812-5a72bc9af239 h1:Kk5OVlx/5g9q3Z3lhxytZS4/f8ds1MiNM8yaHgK3Oe8= github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240405215812-5a72bc9af239/go.mod h1:DC8sQMyTlI/44UCTL8QWFwb0bYNoXCfjwCv2hMivYZU= -github.com/smartcontractkit/chainlink-testing-framework/seth v1.2.1-0.20240827112945-bd8c580392d6 h1:ItZ75xmt+VHR/lw+GJwSWj9XICpgZ94dJ+I/5jdet7c= -github.com/smartcontractkit/chainlink-testing-framework/seth v1.2.1-0.20240827112945-bd8c580392d6/go.mod h1:afY3QmNgeR/VI1pRbGH8g3YXGy7C2RrFOwUzEFvL3L8= -github.com/smartcontractkit/chainlink-testing-framework/wasp v0.4.9 h1:zyp3Ic0lvseZEKh4/Afcsjk9RAnnxHEI6ajqNXWbRL0= -github.com/smartcontractkit/chainlink-testing-framework/wasp v0.4.9/go.mod h1:OMadmu2D8J0ju4XZ+tiTX3EOz0QBsfrw1zym+ZXuNVk= +github.com/smartcontractkit/chainlink-testing-framework/seth v1.2.1 h1:GRAAvtn2+jhO/8Z3lig10eQXVcV4VuOI4UgCyoPdJBg= +github.com/smartcontractkit/chainlink-testing-framework/seth v1.2.1/go.mod h1:afY3QmNgeR/VI1pRbGH8g3YXGy7C2RrFOwUzEFvL3L8= github.com/smartcontractkit/go-plugin v0.0.0-20240208201424-b3b91517de16 h1:TFe+FvzxClblt6qRfqEhUfa4kFQx5UobuoFGO2W4mMo= github.com/smartcontractkit/go-plugin v0.0.0-20240208201424-b3b91517de16/go.mod h1:lBS5MtSSBZk0SHc66KACcjjlU6WzEVP/8pwz68aMkCI= github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f h1:hgJif132UCdjo8u43i7iPN1/MFnu49hv7lFGFftCHKU= diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index 6de9075f0a..4806e99bdd 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -13,10 +13,10 @@ require ( github.com/go-resty/resty/v2 v2.11.0 github.com/pelletier/go-toml/v2 v2.2.2 github.com/pkg/errors v0.9.1 - github.com/rs/zerolog v1.32.0 + github.com/rs/zerolog v1.33.0 github.com/slack-go/slack v0.12.2 github.com/smartcontractkit/chainlink-automation v1.0.4 - github.com/smartcontractkit/chainlink-common v0.2.2-0.20240723123524-e407ecd120b1 + github.com/smartcontractkit/chainlink-common v0.2.2-0.20240829145110-4a45c426fbe8 github.com/smartcontractkit/chainlink-testing-framework v1.34.12 github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20240214231432-4ad5eb95178c github.com/smartcontractkit/chainlink/v2 v2.9.0-beta0.0.20240216210048-da02459ddad8 @@ -51,16 +51,17 @@ require ( github.com/aws/aws-sdk-go-v2/service/sts v1.30.4 // indirect github.com/aws/smithy-go v1.20.4 // indirect github.com/containerd/errdefs v0.1.0 // indirect + github.com/go-viper/mapstructure/v2 v2.1.0 // indirect github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240710121324-3ed288aa9b45 // indirect - github.com/smartcontractkit/chainlink-testing-framework/seth v1.2.1-0.20240827112945-bd8c580392d6 // indirect - github.com/smartcontractkit/chainlink-testing-framework/wasp v0.4.9 // indirect + github.com/smartcontractkit/chainlink-testing-framework/seth v1.2.1 // indirect + github.com/smartcontractkit/chainlink-testing-framework/wasp v0.4.10 // indirect github.com/testcontainers/testcontainers-go v0.28.0 // indirect - k8s.io/apimachinery v0.30.2 // indirect + k8s.io/apimachinery v0.31.0 // indirect ) // avoids ambigious imports of indirect dependencies @@ -119,7 +120,7 @@ require ( github.com/cespare/xxhash v1.1.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/chai2010/gettext-go v1.0.2 // indirect - github.com/chaos-mesh/chaos-mesh/api v0.0.0-20240709130330-9f4feec7553f // indirect + github.com/chaos-mesh/chaos-mesh/api v0.0.0-20240821051457-da69c6d9617a // indirect github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect github.com/chenzhuoyu/iasm v0.9.0 // indirect github.com/cockroachdb/errors v1.10.0 // indirect @@ -180,7 +181,7 @@ require ( github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/fvbommel/sortorder v1.1.0 // indirect - github.com/fxamacker/cbor/v2 v2.6.0 // indirect + github.com/fxamacker/cbor/v2 v2.7.0 // indirect github.com/gabriel-vasile/mimetype v1.4.3 // indirect github.com/gagliardetto/binary v0.7.7 // indirect github.com/gagliardetto/solana-go v1.8.4 // indirect @@ -233,7 +234,7 @@ require ( github.com/google/go-querystring v1.1.0 // indirect github.com/google/go-tpm v0.9.0 // indirect github.com/google/gofuzz v1.2.0 // indirect - github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6 // indirect + github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect github.com/google/uuid v1.6.0 // indirect github.com/gorilla/context v1.1.1 // indirect @@ -248,7 +249,7 @@ require ( github.com/grafana/grafana-foundation-sdk/go v0.0.0-20240326122733-6f96a993222b // indirect github.com/grafana/loki v1.6.2-0.20231215164305-b51b7d7b5503 // indirect github.com/grafana/loki/pkg/push v0.0.0-20231201111602-11ef833ed3e4 // indirect - github.com/grafana/pyroscope-go v1.1.1 // indirect + github.com/grafana/pyroscope-go v1.1.2 // indirect github.com/grafana/pyroscope-go/godeltaprof v0.1.8 // indirect github.com/grafana/regexp v0.0.0-20221122212121-6b5c0a4cb7fd // indirect github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect @@ -256,7 +257,7 @@ require ( github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.1 // indirect github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 // indirect github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 // indirect github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect github.com/gtank/merlin v0.1.1 // indirect github.com/gtank/ristretto255 v0.1.2 // indirect @@ -395,7 +396,7 @@ require ( github.com/smartcontractkit/chainlink-feeds v0.0.0-20240710170203-5b41615da827 // indirect github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240712132946-267a37c5ac6e // indirect github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240709043547-03612098f799 // indirect - github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240405215812-5a72bc9af239 // indirect + github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.1 // indirect github.com/smartcontractkit/havoc/k8schaos v0.0.0-20240409145249-e78d20847e37 // indirect github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 // indirect github.com/smartcontractkit/wsrpc v0.8.1 // indirect @@ -439,10 +440,10 @@ require ( github.com/zondax/ledger-go v0.14.3 // indirect go.dedis.ch/fixbuf v1.0.3 // indirect go.dedis.ch/kyber/v3 v3.1.0 // indirect - go.etcd.io/bbolt v1.3.8 // indirect - go.etcd.io/etcd/api/v3 v3.5.12 // indirect - go.etcd.io/etcd/client/pkg/v3 v3.5.12 // indirect - go.etcd.io/etcd/client/v3 v3.5.12 // indirect + go.etcd.io/bbolt v1.3.9 // indirect + go.etcd.io/etcd/api/v3 v3.5.14 // indirect + go.etcd.io/etcd/client/pkg/v3 v3.5.14 // indirect + go.etcd.io/etcd/client/v3 v3.5.14 // indirect go.mongodb.org/mongo-driver v1.15.0 // indirect go.opencensus.io v0.24.0 // indirect go.opentelemetry.io/collector/pdata v1.0.0-rcv0016 // indirect @@ -464,21 +465,21 @@ require ( go4.org/netipx v0.0.0-20230125063823-8449b0a6169f // indirect golang.org/x/arch v0.8.0 // indirect golang.org/x/crypto v0.26.0 // indirect - golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect - golang.org/x/mod v0.19.0 // indirect - golang.org/x/net v0.27.0 // indirect - golang.org/x/oauth2 v0.21.0 // indirect + golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa // indirect + golang.org/x/mod v0.20.0 // indirect + golang.org/x/net v0.28.0 // indirect + golang.org/x/oauth2 v0.22.0 // indirect golang.org/x/sync v0.8.0 // indirect - golang.org/x/sys v0.23.0 // indirect + golang.org/x/sys v0.24.0 // indirect golang.org/x/term v0.23.0 // indirect golang.org/x/text v0.17.0 // indirect golang.org/x/time v0.6.0 // indirect - golang.org/x/tools v0.23.0 // indirect + golang.org/x/tools v0.24.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect gonum.org/v1/gonum v0.15.0 // indirect google.golang.org/genproto v0.0.0-20240711142825-46eb208f015d // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240711142825-46eb208f015d // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240711142825-46eb208f015d // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240822170219-fc7c04adadcd // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240822170219-fc7c04adadcd // indirect google.golang.org/grpc v1.65.0 // indirect google.golang.org/protobuf v1.34.2 // indirect gopkg.in/guregu/null.v4 v4.0.0 // indirect @@ -487,15 +488,15 @@ require ( gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/api v0.30.2 // indirect - k8s.io/apiextensions-apiserver v0.30.2 // indirect + k8s.io/api v0.31.0 // indirect + k8s.io/apiextensions-apiserver v0.31.0 // indirect k8s.io/cli-runtime v0.28.2 // indirect k8s.io/client-go v1.5.2 // indirect - k8s.io/component-base v0.30.2 // indirect + k8s.io/component-base v0.31.0 // indirect k8s.io/klog/v2 v2.130.1 // indirect k8s.io/kube-openapi v0.0.0-20240709000822-3c01b740850f // indirect k8s.io/kubectl v0.28.2 // indirect - k8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0 // indirect + k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 // indirect nhooyr.io/websocket v1.8.10 // indirect pgregory.net/rapid v1.1.0 // indirect rsc.io/tmplfunc v0.0.3 // indirect diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index 3d91811051..da5b0c3cdf 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -505,8 +505,8 @@ github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nos github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/fvbommel/sortorder v1.1.0 h1:fUmoe+HLsBTctBDoaBwpQo5N+nrCp8g/BjKb/6ZQmYw= github.com/fvbommel/sortorder v1.1.0/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0= -github.com/fxamacker/cbor/v2 v2.6.0 h1:sU6J2usfADwWlYDAFhZBQ6TnLFBHxgesMrQfQgk1tWA= -github.com/fxamacker/cbor/v2 v2.6.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= +github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= +github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= github.com/gagliardetto/binary v0.7.7 h1:QZpT38+sgoPg+TIQjH94sLbl/vX+nlIRA37pEyOsjfY= @@ -624,6 +624,8 @@ github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1v github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= github.com/go-test/deep v1.0.4 h1:u2CU3YKy9I2pmu9pX0eq50wCgjfGIt539SqR7FbHiho= github.com/go-test/deep v1.0.4/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= +github.com/go-viper/mapstructure/v2 v2.1.0 h1:gHnMa2Y/pIxElCH2GlZZ1lZSsn6XMtufpGyP1XxdC/w= +github.com/go-viper/mapstructure/v2 v2.1.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/go-webauthn/webauthn v0.9.4 h1:YxvHSqgUyc5AK2pZbqkWWR55qKeDPhP8zLDr6lpIc2g= github.com/go-webauthn/webauthn v0.9.4/go.mod h1:LqupCtzSef38FcxzaklmOn7AykGKhAhr9xlRbdbgnTw= github.com/go-webauthn/x v0.1.5 h1:V2TCzDU2TGLd0kSZOXdrqDVV5JB9ILnKxA9S53CSBw0= @@ -760,8 +762,8 @@ github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6 h1:k7nVchz72niMH6YLQNvHSdIE7iqsQxK1P41mySCvssg= -github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw= +github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af h1:kmjWCqn2qkEml422C2Rrd27c3VGxi6a/6HNq8QmHRKM= +github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= @@ -810,8 +812,8 @@ github.com/grafana/loki v1.6.2-0.20231215164305-b51b7d7b5503 h1:gdrsYbmk8822v6qv github.com/grafana/loki v1.6.2-0.20231215164305-b51b7d7b5503/go.mod h1:d8seWXCEXkL42mhuIJYcGi6DxfehzoIpLrMQWJojvOo= github.com/grafana/loki/pkg/push v0.0.0-20231201111602-11ef833ed3e4 h1:wQ0FnSeebhJIBkgYOD06Mxk9HV2KhtEG0hp/7R+5RUQ= github.com/grafana/loki/pkg/push v0.0.0-20231201111602-11ef833ed3e4/go.mod h1:f3JSoxBTPXX5ec4FxxeC19nTBSxoTz+cBgS3cYLMcr0= -github.com/grafana/pyroscope-go v1.1.1 h1:PQoUU9oWtO3ve/fgIiklYuGilvsm8qaGhlY4Vw6MAcQ= -github.com/grafana/pyroscope-go v1.1.1/go.mod h1:Mw26jU7jsL/KStNSGGuuVYdUq7Qghem5P8aXYXSXG88= +github.com/grafana/pyroscope-go v1.1.2 h1:7vCfdORYQMCxIzI3NlYAs3FcBP760+gWuYWOyiVyYx8= +github.com/grafana/pyroscope-go v1.1.2/go.mod h1:HSSmHo2KRn6FasBA4vK7BMiQqyQq8KSuBKvrhkXxYPU= github.com/grafana/pyroscope-go/godeltaprof v0.1.8 h1:iwOtYXeeVSAeYefJNaxDytgjKtUuKQbJqgAIjlnicKg= github.com/grafana/pyroscope-go/godeltaprof v0.1.8/go.mod h1:2+l7K7twW49Ct4wFluZD3tZ6e0SjanjcUUBPVD/UuGU= github.com/grafana/regexp v0.0.0-20221122212121-6b5c0a4cb7fd h1:PpuIBO5P3e9hpqBD0O/HjhShYuM6XE0i/lbE6J94kww= @@ -833,8 +835,8 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgf github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 h1:asbCHRVmodnJTuQ3qamDwqVOIjwqUPTYmYuemVOx+Ys= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0/go.mod h1:ggCgvZ2r7uOoQjOyu2Y1NhHmEPPzzuhWgcza5M1Ji1I= github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645/go.mod h1:6iZfnjpejD4L/4DwD7NryNaJyCQdzwWwH2MWhCA90Kw= github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c h1:6rhixN/i8ZofjG1Y75iExal34USq5p+wiN1tpie8IrU= github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c/go.mod h1:NMPJylDgVpX0MLRlPy15sqSwOFv/U1GZ2m21JhFfek0= @@ -1335,8 +1337,8 @@ github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= -github.com/rs/zerolog v1.32.0 h1:keLypqrlIjaFsbmJOBdB/qvyF8KEtCWHwobLp5l/mQ0= -github.com/rs/zerolog v1.32.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= +github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8= +github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= @@ -1391,8 +1393,8 @@ github.com/smartcontractkit/chain-selectors v1.0.23 h1:D2Eaex4Cw/O7Lg3tX6WklOqnj github.com/smartcontractkit/chain-selectors v1.0.23/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/smartcontractkit/chainlink-automation v1.0.4 h1:iyW181JjKHLNMnDleI8umfIfVVlwC7+n5izbLSFgjw8= github.com/smartcontractkit/chainlink-automation v1.0.4/go.mod h1:u4NbPZKJ5XiayfKHD/v3z3iflQWqvtdhj13jVZXj/cM= -github.com/smartcontractkit/chainlink-common v0.2.2-0.20240723123524-e407ecd120b1 h1:pdEpjgbZ5w/Sd5lzg/XiuC5gVyrmSovOo+3nUD46SP8= -github.com/smartcontractkit/chainlink-common v0.2.2-0.20240723123524-e407ecd120b1/go.mod h1:Jg1sCTsbxg76YByI8ifpFby3FvVqISStHT8ypy9ocmY= +github.com/smartcontractkit/chainlink-common v0.2.2-0.20240829145110-4a45c426fbe8 h1:MOFuL1J4/rRcR0x09qSlOsKIiq4I7YzbZcQ421KqUZA= +github.com/smartcontractkit/chainlink-common v0.2.2-0.20240829145110-4a45c426fbe8/go.mod h1:TJSY2ETKiXLRPvGHNO7Dp1tlpFIPSCWwN3iIdrsadIE= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240710121324-3ed288aa9b45 h1:NBQLtqk8zsyY4qTJs+NElI3aDFTcAo83JHvqD04EvB0= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240710121324-3ed288aa9b45/go.mod h1:LV0h7QBQUpoC2UUi6TcUvcIFm1xjP/DtEcqV8+qeLUs= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240718160222-2dc0c8136bfa h1:g75H8oh2ws52s8BekwvGQ9XvBVu3E7WM1rfiA0PN0zk= @@ -1405,12 +1407,12 @@ github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.202407 github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240709043547-03612098f799/go.mod h1:UVFRacRkP7O7TQAzFmR52v5mUlxf+G1ovMlCQAB/cHU= github.com/smartcontractkit/chainlink-testing-framework v1.34.12 h1:pI0ESAspOcEqQ1fm53+3o2laGNwP8wbQNAmrGp5Tw1A= github.com/smartcontractkit/chainlink-testing-framework v1.34.12/go.mod h1:ekYJbRAxXcs/YgOjHsY9/tlvDvXzv3lxcZK2eFUZduc= -github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240405215812-5a72bc9af239 h1:Kk5OVlx/5g9q3Z3lhxytZS4/f8ds1MiNM8yaHgK3Oe8= -github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240405215812-5a72bc9af239/go.mod h1:DC8sQMyTlI/44UCTL8QWFwb0bYNoXCfjwCv2hMivYZU= -github.com/smartcontractkit/chainlink-testing-framework/seth v1.2.1-0.20240827112945-bd8c580392d6 h1:ItZ75xmt+VHR/lw+GJwSWj9XICpgZ94dJ+I/5jdet7c= -github.com/smartcontractkit/chainlink-testing-framework/seth v1.2.1-0.20240827112945-bd8c580392d6/go.mod h1:afY3QmNgeR/VI1pRbGH8g3YXGy7C2RrFOwUzEFvL3L8= -github.com/smartcontractkit/chainlink-testing-framework/wasp v0.4.9 h1:zyp3Ic0lvseZEKh4/Afcsjk9RAnnxHEI6ajqNXWbRL0= -github.com/smartcontractkit/chainlink-testing-framework/wasp v0.4.9/go.mod h1:OMadmu2D8J0ju4XZ+tiTX3EOz0QBsfrw1zym+ZXuNVk= +github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.1 h1:1/r1wQZ4TOFpZ13w94r7amdF096Z96RuEnkOmrz1BGE= +github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.1/go.mod h1:DC8sQMyTlI/44UCTL8QWFwb0bYNoXCfjwCv2hMivYZU= +github.com/smartcontractkit/chainlink-testing-framework/seth v1.2.1 h1:GRAAvtn2+jhO/8Z3lig10eQXVcV4VuOI4UgCyoPdJBg= +github.com/smartcontractkit/chainlink-testing-framework/seth v1.2.1/go.mod h1:afY3QmNgeR/VI1pRbGH8g3YXGy7C2RrFOwUzEFvL3L8= +github.com/smartcontractkit/chainlink-testing-framework/wasp v0.4.10 h1:s7e9YPU/ECQ9xCyLc60ApFbf0blMjg9LWi31CAEjaZY= +github.com/smartcontractkit/chainlink-testing-framework/wasp v0.4.10/go.mod h1:E7x2ICsT8vzy0nL6wwBphoQMoNwOMl0L9voQpEl1FoM= github.com/smartcontractkit/go-plugin v0.0.0-20240208201424-b3b91517de16 h1:TFe+FvzxClblt6qRfqEhUfa4kFQx5UobuoFGO2W4mMo= github.com/smartcontractkit/go-plugin v0.0.0-20240208201424-b3b91517de16/go.mod h1:lBS5MtSSBZk0SHc66KACcjjlU6WzEVP/8pwz68aMkCI= github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f h1:hgJif132UCdjo8u43i7iPN1/MFnu49hv7lFGFftCHKU= @@ -1595,14 +1597,14 @@ go.dedis.ch/protobuf v1.0.5/go.mod h1:eIV4wicvi6JK0q/QnfIEGeSFNG0ZeB24kzut5+HaRL go.dedis.ch/protobuf v1.0.7/go.mod h1:pv5ysfkDX/EawiPqcW3ikOxsL5t+BqnV6xHSmE79KI4= go.dedis.ch/protobuf v1.0.11/go.mod h1:97QR256dnkimeNdfmURz0wAMNVbd1VmLXhG1CrTYrJ4= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/bbolt v1.3.8 h1:xs88BrvEv273UsB79e0hcVrlUWmS0a8upikMFhSyAtA= -go.etcd.io/bbolt v1.3.8/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= -go.etcd.io/etcd/api/v3 v3.5.12 h1:W4sw5ZoU2Juc9gBWuLk5U6fHfNVyY1WC5g9uiXZio/c= -go.etcd.io/etcd/api/v3 v3.5.12/go.mod h1:Ot+o0SWSyT6uHhA56al1oCED0JImsRiU9Dc26+C2a+4= -go.etcd.io/etcd/client/pkg/v3 v3.5.12 h1:EYDL6pWwyOsylrQyLp2w+HkQ46ATiOvoEdMarindU2A= -go.etcd.io/etcd/client/pkg/v3 v3.5.12/go.mod h1:seTzl2d9APP8R5Y2hFL3NVlD6qC/dOT+3kvrqPyTas4= -go.etcd.io/etcd/client/v3 v3.5.12 h1:v5lCPXn1pf1Uu3M4laUE2hp/geOTc5uPcYYsNe1lDxg= -go.etcd.io/etcd/client/v3 v3.5.12/go.mod h1:tSbBCakoWmmddL+BKVAJHa9km+O/E+bumDe9mSbPiqw= +go.etcd.io/bbolt v1.3.9 h1:8x7aARPEXiXbHmtUwAIv7eV2fQFHrLLavdiJ3uzJXoI= +go.etcd.io/bbolt v1.3.9/go.mod h1:zaO32+Ti0PK1ivdPtgMESzuzL2VPoIG1PCQNvOdo/dE= +go.etcd.io/etcd/api/v3 v3.5.14 h1:vHObSCxyB9zlF60w7qzAdTcGaglbJOpSj1Xj9+WGxq0= +go.etcd.io/etcd/api/v3 v3.5.14/go.mod h1:BmtWcRlQvwa1h3G2jvKYwIQy4PkHlDej5t7uLMUdJUU= +go.etcd.io/etcd/client/pkg/v3 v3.5.14 h1:SaNH6Y+rVEdxfpA2Jr5wkEvN6Zykme5+YnbCkxvuWxQ= +go.etcd.io/etcd/client/pkg/v3 v3.5.14/go.mod h1:8uMgAokyG1czCtIdsq+AGyYQMvpIKnSvPjFMunkgeZI= +go.etcd.io/etcd/client/v3 v3.5.14 h1:CWfRs4FDaDoSz81giL7zPpZH2Z35tbOrAJkkjMqOupg= +go.etcd.io/etcd/client/v3 v3.5.14/go.mod h1:k3XfdV/VIHy/97rqWjoUzrj9tk7GgJGH9J8L4dNXmAk= go.mongodb.org/mongo-driver v1.7.3/go.mod h1:NqaYOwnXWr5Pm7AOpO5QFxKJ503nbMse/R79oO62zWg= go.mongodb.org/mongo-driver v1.7.5/go.mod h1:VXEWRZ6URJIkUq2SCAyapmhH0ZLRBP+FT4xhp5Zvxng= go.mongodb.org/mongo-driver v1.10.0/go.mod h1:wsihk0Kdgv8Kqu1Anit4sfK+22vSFbUrAVEYRhCXrA8= @@ -1720,8 +1722,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8= -golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= +golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa h1:ELnwvuAXPNtPk1TJRuGkI9fDTwym6AYBu0qzT8AcHdI= +golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa/go.mod h1:akd2r19cwCdwSwWeIdzYQGa/EZZyqcOdwWiwj5L5eKQ= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -1746,8 +1748,8 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8= -golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0= +golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1803,8 +1805,8 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= -golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= -golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= +golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= +golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1812,8 +1814,8 @@ golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4Iltr golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I= -golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= -golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/oauth2 v0.22.0 h1:BzDx2FehcG7jJwgWLELCdmLuxk2i+x9UDpSiss2u0ZA= +golang.org/x/oauth2 v0.22.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1915,8 +1917,8 @@ golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM= -golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= +golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -2012,8 +2014,8 @@ golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg= -golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI= +golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24= +golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -2090,10 +2092,10 @@ google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20210401141331-865547bb08e2/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= google.golang.org/genproto v0.0.0-20240711142825-46eb208f015d h1:/hmn0Ku5kWij/kjGsrcJeC1T/MrJi2iNWwgAqrihFwc= google.golang.org/genproto v0.0.0-20240711142825-46eb208f015d/go.mod h1:FfBgJBJg9GcpPvKIuHSZ/aE1g2ecGL74upMzGZjiGEY= -google.golang.org/genproto/googleapis/api v0.0.0-20240711142825-46eb208f015d h1:kHjw/5UfflP/L5EbledDrcG4C2597RtymmGRZvHiCuY= -google.golang.org/genproto/googleapis/api v0.0.0-20240711142825-46eb208f015d/go.mod h1:mw8MG/Qz5wfgYr6VqVCiZcHe/GJEfI+oGGDCohaVgB0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240711142825-46eb208f015d h1:JU0iKnSg02Gmb5ZdV8nYsKEKsP6o/FGVWTrw4i1DA9A= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240711142825-46eb208f015d/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= +google.golang.org/genproto/googleapis/api v0.0.0-20240822170219-fc7c04adadcd h1:BBOTEWLuuEGQy9n1y9MhVJ9Qt0BDu21X8qZs71/uPZo= +google.golang.org/genproto/googleapis/api v0.0.0-20240822170219-fc7c04adadcd/go.mod h1:fO8wJzT2zbQbAjbIoos1285VfEIYKDDY+Dt+WpTkh6g= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240822170219-fc7c04adadcd h1:6TEm2ZxXoQmFWFlt1vNxvVOa1Q0dXFQD1m/rYjXmS0E= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240822170219-fc7c04adadcd/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= google.golang.org/grpc v1.12.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= @@ -2195,8 +2197,8 @@ k8s.io/kube-openapi v0.0.0-20240709000822-3c01b740850f h1:2sXuKesAYbRHxL3aE2PN6z k8s.io/kube-openapi v0.0.0-20240709000822-3c01b740850f/go.mod h1:UxDHUPsUwTOOxSU+oXURfFBcAS6JwiRXTYqYwfuGowc= k8s.io/kubectl v0.28.2 h1:fOWOtU6S0smdNjG1PB9WFbqEIMlkzU5ahyHkc7ESHgM= k8s.io/kubectl v0.28.2/go.mod h1:6EQWTPySF1fn7yKoQZHYf9TPwIl2AygHEcJoxFekr64= -k8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0 h1:jgGTlFYnhF1PM1Ax/lAlxUPE+KfCIXHaathvJg1C3ak= -k8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A= +k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= nhooyr.io/websocket v1.8.10 h1:mv4p+MnGrLDcPlBoWsvPP7XCzTYMXP9F9eIGoKbgx7Q= nhooyr.io/websocket v1.8.10/go.mod h1:rN9OFWIUwuxg4fR5tELlYC04bXYowCP9GX47ivo2l+c= nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50= From 66f42c9f6db88b2a531f8f742cd0102ae819dd13 Mon Sep 17 00:00:00 2001 From: "app-token-issuer-infra-releng[bot]" <120227048+app-token-issuer-infra-releng[bot]@users.noreply.github.com> Date: Mon, 2 Sep 2024 09:48:11 +0000 Subject: [PATCH 062/115] Update gethwrappers --- .../feeds_consumer/feeds_consumer.go | 28 +++++++++++++++++-- ...rapper-dependency-versions-do-not-edit.txt | 2 +- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/core/gethwrappers/keystone/generated/feeds_consumer/feeds_consumer.go b/core/gethwrappers/keystone/generated/feeds_consumer/feeds_consumer.go index f4d52eedb9..2951835c8d 100644 --- a/core/gethwrappers/keystone/generated/feeds_consumer/feeds_consumer.go +++ b/core/gethwrappers/keystone/generated/feeds_consumer/feeds_consumer.go @@ -31,8 +31,8 @@ var ( ) var KeystoneFeedsConsumerMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"UnauthorizedSender\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes10\",\"name\":\"workflowName\",\"type\":\"bytes10\"}],\"name\":\"UnauthorizedWorkflowName\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"}],\"name\":\"UnauthorizedWorkflowOwner\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"feedId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint224\",\"name\":\"price\",\"type\":\"uint224\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"name\":\"FeedReceived\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"feedId\",\"type\":\"bytes32\"}],\"name\":\"getPrice\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"rawReport\",\"type\":\"bytes\"}],\"name\":\"onReport\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_allowedSendersList\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"_allowedWorkflowOwnersList\",\"type\":\"address[]\"},{\"internalType\":\"bytes10[]\",\"name\":\"_allowedWorkflowNamesList\",\"type\":\"bytes10[]\"}],\"name\":\"setConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x608060405234801561001057600080fd5b5033806000816100675760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615610097576100978161009f565b505050610148565b336001600160a01b038216036100f75760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161005e565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6111cf806101576000396000f3fe608060405234801561001057600080fd5b50600436106100725760003560e01c80638da5cb5b116100505780638da5cb5b1461014e578063e340171114610176578063f2fde38b1461018957600080fd5b806331d98b3f1461007757806379ba509714610131578063805f21321461013b575b600080fd5b6100f3610085366004610d64565b6000908152600260209081526040918290208251808401909352547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff81168084527c010000000000000000000000000000000000000000000000000000000090910463ffffffff169290910182905291565b604080517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff909316835263ffffffff9091166020830152015b60405180910390f35b61013961019c565b005b610139610149366004610dc6565b61029e565b60005460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610128565b610139610184366004610e77565b61061d565b610139610197366004610f11565b610a5d565b60015473ffffffffffffffffffffffffffffffffffffffff163314610222576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b3360009081526004602052604090205460ff166102e9576040517f3fcc3f17000000000000000000000000000000000000000000000000000000008152336004820152602401610219565b60008061032b86868080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610a7192505050565b7fffffffffffffffffffff000000000000000000000000000000000000000000008216600090815260086020526040902054919350915060ff166103bf576040517f4b942f800000000000000000000000000000000000000000000000000000000081527fffffffffffffffffffff0000000000000000000000000000000000000000000083166004820152602401610219565b73ffffffffffffffffffffffffffffffffffffffff811660009081526006602052604090205460ff16610436576040517fbf24162300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152602401610219565b600061044484860186610ff5565b905060005b815181101561061357604051806040016040528083838151811061046f5761046f611107565b6020026020010151602001517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1681526020018383815181106104b0576104b0611107565b60200260200101516040015163ffffffff16815250600260008484815181106104db576104db611107565b602090810291909101810151518252818101929092526040016000208251929091015163ffffffff167c0100000000000000000000000000000000000000000000000000000000027bffffffffffffffffffffffffffffffffffffffffffffffffffffffff909216919091179055815182908290811061055d5761055d611107565b6020026020010151600001517f2c30f5cb3caf4239d0f994ce539d7ef24817fa550169c388e3a110f02e40197d83838151811061059c5761059c611107565b6020026020010151602001518484815181106105ba576105ba611107565b6020026020010151604001516040516106039291907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff92909216825263ffffffff16602082015260400190565b60405180910390a2600101610449565b5050505050505050565b610625610a87565b60005b60035463ffffffff821610156106c65760006004600060038463ffffffff168154811061065757610657611107565b60009182526020808320919091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169115159190911790556106bf81611136565b9050610628565b5060005b63ffffffff811686111561076e5760016004600089898563ffffffff168181106106f6576106f6611107565b905060200201602081019061070b9190610f11565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001691151591909117905561076781611136565b90506106ca565b5061077b60038787610bff565b5060005b60055463ffffffff8216101561081d5760006006600060058463ffffffff16815481106107ae576107ae611107565b60009182526020808320919091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001691151591909117905561081681611136565b905061077f565b5060005b63ffffffff81168411156108c55760016006600087878563ffffffff1681811061084d5761084d611107565b90506020020160208101906108629190610f11565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169115159190911790556108be81611136565b9050610821565b506108d260058585610bff565b5060005b60075463ffffffff821610156109935760006008600060078463ffffffff168154811061090557610905611107565b600091825260208083206003808404909101549206600a026101000a90910460b01b7fffffffffffffffffffff00000000000000000000000000000000000000000000168352820192909252604001902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001691151591909117905561098c81611136565b90506108d6565b5060005b63ffffffff8116821115610a475760016008600085858563ffffffff168181106109c3576109c3611107565b90506020020160208101906109d89190611180565b7fffffffffffffffffffff00000000000000000000000000000000000000000000168152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055610a4081611136565b9050610997565b50610a5460078383610c87565b50505050505050565b610a65610a87565b610a6e81610b0a565b50565b6040810151604a90910151909160609190911c90565b60005473ffffffffffffffffffffffffffffffffffffffff163314610b08576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610219565b565b3373ffffffffffffffffffffffffffffffffffffffff821603610b89576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610219565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b828054828255906000526020600020908101928215610c77579160200282015b82811115610c775781547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff843516178255602090920191600190910190610c1f565b50610c83929150610d4f565b5090565b82805482825590600052602060002090600201600390048101928215610c775791602002820160005b83821115610d1057833575ffffffffffffffffffffffffffffffffffffffffffff191683826101000a81548169ffffffffffffffffffff021916908360b01c02179055509260200192600a01602081600901049283019260010302610cb0565b8015610d465782816101000a81549069ffffffffffffffffffff0219169055600a01602081600901049283019260010302610d10565b5050610c839291505b5b80821115610c835760008155600101610d50565b600060208284031215610d7657600080fd5b5035919050565b60008083601f840112610d8f57600080fd5b50813567ffffffffffffffff811115610da757600080fd5b602083019150836020828501011115610dbf57600080fd5b9250929050565b60008060008060408587031215610ddc57600080fd5b843567ffffffffffffffff80821115610df457600080fd5b610e0088838901610d7d565b90965094506020870135915080821115610e1957600080fd5b50610e2687828801610d7d565b95989497509550505050565b60008083601f840112610e4457600080fd5b50813567ffffffffffffffff811115610e5c57600080fd5b6020830191508360208260051b8501011115610dbf57600080fd5b60008060008060008060608789031215610e9057600080fd5b863567ffffffffffffffff80821115610ea857600080fd5b610eb48a838b01610e32565b90985096506020890135915080821115610ecd57600080fd5b610ed98a838b01610e32565b90965094506040890135915080821115610ef257600080fd5b50610eff89828a01610e32565b979a9699509497509295939492505050565b600060208284031215610f2357600080fd5b813573ffffffffffffffffffffffffffffffffffffffff81168114610f4757600080fd5b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040516060810167ffffffffffffffff81118282101715610fa057610fa0610f4e565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715610fed57610fed610f4e565b604052919050565b6000602080838503121561100857600080fd5b823567ffffffffffffffff8082111561102057600080fd5b818501915085601f83011261103457600080fd5b81358181111561104657611046610f4e565b611054848260051b01610fa6565b8181528481019250606091820284018501918883111561107357600080fd5b938501935b828510156110fb5780858a0312156110905760008081fd5b611098610f7d565b85358152868601357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811681146110cb5760008081fd5b8188015260408681013563ffffffff811681146110e85760008081fd5b9082015284529384019392850192611078565b50979650505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600063ffffffff808316818103611176577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6001019392505050565b60006020828403121561119257600080fd5b81357fffffffffffffffffffff0000000000000000000000000000000000000000000081168114610f4757600080fdfea164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"UnauthorizedSender\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes10\",\"name\":\"workflowName\",\"type\":\"bytes10\"}],\"name\":\"UnauthorizedWorkflowName\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"}],\"name\":\"UnauthorizedWorkflowOwner\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"feedId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint224\",\"name\":\"price\",\"type\":\"uint224\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"name\":\"FeedReceived\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"feedId\",\"type\":\"bytes32\"}],\"name\":\"getPrice\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"rawReport\",\"type\":\"bytes\"}],\"name\":\"onReport\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_allowedSendersList\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"_allowedWorkflowOwnersList\",\"type\":\"address[]\"},{\"internalType\":\"bytes10[]\",\"name\":\"_allowedWorkflowNamesList\",\"type\":\"bytes10[]\"}],\"name\":\"setConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x608060405234801561001057600080fd5b5033806000816100675760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615610097576100978161009f565b505050610148565b336001600160a01b038216036100f75760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161005e565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b611281806101576000396000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c8063805f21321161005b578063805f2132146101ab5780638da5cb5b146101be578063e3401711146101e6578063f2fde38b146101f957600080fd5b806301ffc9a71461008257806331d98b3f146100ec57806379ba5097146101a1575b600080fd5b6100d7610090366004610dd4565b7fffffffff00000000000000000000000000000000000000000000000000000000167f805f2132000000000000000000000000000000000000000000000000000000001490565b60405190151581526020015b60405180910390f35b6101686100fa366004610e1d565b6000908152600260209081526040918290208251808401909352547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff81168084527c010000000000000000000000000000000000000000000000000000000090910463ffffffff169290910182905291565b604080517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff909316835263ffffffff9091166020830152016100e3565b6101a961020c565b005b6101a96101b9366004610e7f565b61030e565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100e3565b6101a96101f4366004610f30565b61068d565b6101a9610207366004610fca565b610acd565b60015473ffffffffffffffffffffffffffffffffffffffff163314610292576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b3360009081526004602052604090205460ff16610359576040517f3fcc3f17000000000000000000000000000000000000000000000000000000008152336004820152602401610289565b60008061039b86868080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610ae192505050565b7fffffffffffffffffffff000000000000000000000000000000000000000000008216600090815260086020526040902054919350915060ff1661042f576040517f4b942f800000000000000000000000000000000000000000000000000000000081527fffffffffffffffffffff0000000000000000000000000000000000000000000083166004820152602401610289565b73ffffffffffffffffffffffffffffffffffffffff811660009081526006602052604090205460ff166104a6576040517fbf24162300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152602401610289565b60006104b4848601866110a7565b905060005b81518110156106835760405180604001604052808383815181106104df576104df6111b9565b6020026020010151602001517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168152602001838381518110610520576105206111b9565b60200260200101516040015163ffffffff168152506002600084848151811061054b5761054b6111b9565b602090810291909101810151518252818101929092526040016000208251929091015163ffffffff167c0100000000000000000000000000000000000000000000000000000000027bffffffffffffffffffffffffffffffffffffffffffffffffffffffff90921691909117905581518290829081106105cd576105cd6111b9565b6020026020010151600001517f2c30f5cb3caf4239d0f994ce539d7ef24817fa550169c388e3a110f02e40197d83838151811061060c5761060c6111b9565b60200260200101516020015184848151811061062a5761062a6111b9565b6020026020010151604001516040516106739291907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff92909216825263ffffffff16602082015260400190565b60405180910390a26001016104b9565b5050505050505050565b610695610af7565b60005b60035463ffffffff821610156107365760006004600060038463ffffffff16815481106106c7576106c76111b9565b60009182526020808320919091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001691151591909117905561072f816111e8565b9050610698565b5060005b63ffffffff81168611156107de5760016004600089898563ffffffff16818110610766576107666111b9565b905060200201602081019061077b9190610fca565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169115159190911790556107d7816111e8565b905061073a565b506107eb60038787610c6f565b5060005b60055463ffffffff8216101561088d5760006006600060058463ffffffff168154811061081e5761081e6111b9565b60009182526020808320919091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055610886816111e8565b90506107ef565b5060005b63ffffffff81168411156109355760016006600087878563ffffffff168181106108bd576108bd6111b9565b90506020020160208101906108d29190610fca565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001691151591909117905561092e816111e8565b9050610891565b5061094260058585610c6f565b5060005b60075463ffffffff82161015610a035760006008600060078463ffffffff1681548110610975576109756111b9565b600091825260208083206003808404909101549206600a026101000a90910460b01b7fffffffffffffffffffff00000000000000000000000000000000000000000000168352820192909252604001902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169115159190911790556109fc816111e8565b9050610946565b5060005b63ffffffff8116821115610ab75760016008600085858563ffffffff16818110610a3357610a336111b9565b9050602002016020810190610a489190611232565b7fffffffffffffffffffff00000000000000000000000000000000000000000000168152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055610ab0816111e8565b9050610a07565b50610ac460078383610cf7565b50505050505050565b610ad5610af7565b610ade81610b7a565b50565b6040810151604a90910151909160609190911c90565b60005473ffffffffffffffffffffffffffffffffffffffff163314610b78576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610289565b565b3373ffffffffffffffffffffffffffffffffffffffff821603610bf9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610289565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b828054828255906000526020600020908101928215610ce7579160200282015b82811115610ce75781547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff843516178255602090920191600190910190610c8f565b50610cf3929150610dbf565b5090565b82805482825590600052602060002090600201600390048101928215610ce75791602002820160005b83821115610d8057833575ffffffffffffffffffffffffffffffffffffffffffff191683826101000a81548169ffffffffffffffffffff021916908360b01c02179055509260200192600a01602081600901049283019260010302610d20565b8015610db65782816101000a81549069ffffffffffffffffffff0219169055600a01602081600901049283019260010302610d80565b5050610cf39291505b5b80821115610cf35760008155600101610dc0565b600060208284031215610de657600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610e1657600080fd5b9392505050565b600060208284031215610e2f57600080fd5b5035919050565b60008083601f840112610e4857600080fd5b50813567ffffffffffffffff811115610e6057600080fd5b602083019150836020828501011115610e7857600080fd5b9250929050565b60008060008060408587031215610e9557600080fd5b843567ffffffffffffffff80821115610ead57600080fd5b610eb988838901610e36565b90965094506020870135915080821115610ed257600080fd5b50610edf87828801610e36565b95989497509550505050565b60008083601f840112610efd57600080fd5b50813567ffffffffffffffff811115610f1557600080fd5b6020830191508360208260051b8501011115610e7857600080fd5b60008060008060008060608789031215610f4957600080fd5b863567ffffffffffffffff80821115610f6157600080fd5b610f6d8a838b01610eeb565b90985096506020890135915080821115610f8657600080fd5b610f928a838b01610eeb565b90965094506040890135915080821115610fab57600080fd5b50610fb889828a01610eeb565b979a9699509497509295939492505050565b600060208284031215610fdc57600080fd5b813573ffffffffffffffffffffffffffffffffffffffff81168114610e1657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040516060810167ffffffffffffffff8111828210171561105257611052611000565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561109f5761109f611000565b604052919050565b600060208083850312156110ba57600080fd5b823567ffffffffffffffff808211156110d257600080fd5b818501915085601f8301126110e657600080fd5b8135818111156110f8576110f8611000565b611106848260051b01611058565b8181528481019250606091820284018501918883111561112557600080fd5b938501935b828510156111ad5780858a0312156111425760008081fd5b61114a61102f565b85358152868601357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116811461117d5760008081fd5b8188015260408681013563ffffffff8116811461119a5760008081fd5b908201528452938401939285019261112a565b50979650505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600063ffffffff808316818103611228577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6001019392505050565b60006020828403121561124457600080fd5b81357fffffffffffffffffffff0000000000000000000000000000000000000000000081168114610e1657600080fdfea164736f6c6343000818000a", } var KeystoneFeedsConsumerABI = KeystoneFeedsConsumerMetaData.ABI @@ -216,6 +216,28 @@ func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerCallerSession) Owner() (commo return _KeystoneFeedsConsumer.Contract.Owner(&_KeystoneFeedsConsumer.CallOpts) } +func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerCaller) SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) { + var out []interface{} + err := _KeystoneFeedsConsumer.contract.Call(opts, &out, "supportsInterface", interfaceId) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerSession) SupportsInterface(interfaceId [4]byte) (bool, error) { + return _KeystoneFeedsConsumer.Contract.SupportsInterface(&_KeystoneFeedsConsumer.CallOpts, interfaceId) +} + +func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerCallerSession) SupportsInterface(interfaceId [4]byte) (bool, error) { + return _KeystoneFeedsConsumer.Contract.SupportsInterface(&_KeystoneFeedsConsumer.CallOpts, interfaceId) +} + func (_KeystoneFeedsConsumer *KeystoneFeedsConsumerTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { return _KeystoneFeedsConsumer.contract.Transact(opts, "acceptOwnership") } @@ -700,6 +722,8 @@ type KeystoneFeedsConsumerInterface interface { Owner(opts *bind.CallOpts) (common.Address, error) + SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) + AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) OnReport(opts *bind.TransactOpts, metadata []byte, rawReport []byte) (*types.Transaction, error) diff --git a/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt index 7d25f651dd..40cf539277 100644 --- a/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -1,5 +1,5 @@ GETH_VERSION: 1.13.8 capabilities_registry: ../../../contracts/solc/v0.8.24/CapabilitiesRegistry/CapabilitiesRegistry.abi ../../../contracts/solc/v0.8.24/CapabilitiesRegistry/CapabilitiesRegistry.bin 6d2e3aa3a6f3aed2cf24b613743bb9ae4b9558f48a6864dc03b8b0ebb37235e3 -feeds_consumer: ../../../contracts/solc/v0.8.24/KeystoneFeedsConsumer/KeystoneFeedsConsumer.abi ../../../contracts/solc/v0.8.24/KeystoneFeedsConsumer/KeystoneFeedsConsumer.bin f098e25df6afc100425fcad7f5107aec0844cc98315117e49da139a179d0eead +feeds_consumer: ../../../contracts/solc/v0.8.24/KeystoneFeedsConsumer/KeystoneFeedsConsumer.abi ../../../contracts/solc/v0.8.24/KeystoneFeedsConsumer/KeystoneFeedsConsumer.bin 8c3a2b18a80be41e7c40d2bc3a4c8d1b5e18d55c1fd20ad5af68cebb66109fc5 forwarder: ../../../contracts/solc/v0.8.24/KeystoneForwarder/KeystoneForwarder.abi ../../../contracts/solc/v0.8.24/KeystoneForwarder/KeystoneForwarder.bin dc98a86a3775ead987b79d5b6079ee0e26f31c0626032bdd6508f986e2423227 ocr3_capability: ../../../contracts/solc/v0.8.24/OCR3Capability/OCR3Capability.abi ../../../contracts/solc/v0.8.24/OCR3Capability/OCR3Capability.bin 8bf0f53f222efce7143dea6134552eb26ea1eef845407b4475a0d79b7d7ba9f8 From 10ecf427758ee42e5545baf41d0c6bbaef589068 Mon Sep 17 00:00:00 2001 From: Mateusz Sekara Date: Mon, 2 Sep 2024 12:47:34 +0200 Subject: [PATCH 063/115] Adding missing prom reporter. Post merge fixes --- .mockery.yaml | 8 +- .../gas-snapshots/functions.gas-snapshot | 18 +- core/internal/cltest/cltest.go | 2 + core/internal/mocks/prometheus_backend.go | 204 ++++++++++++++++++ core/services/chainlink/application.go | 60 +++--- core/services/headreporter/head_reporter.go | 111 ---------- .../headreporter/head_reporter_mock.go | 130 ----------- .../headreporter/head_reporter_test.go | 51 ----- core/services/headreporter/helper_test.go | 5 - .../headreporter/prometheus_backend_mock.go | 204 ------------------ .../headreporter/telemetry_reporter.go | 69 ------ .../headreporter/telemetry_reporter_test.go | 108 ---------- .../ccip/testhelpers/integration/chainlink.go | 8 +- .../testhelpers_1_4_0/chainlink.go | 8 +- .../prom_reporter.go} | 168 +++++++++++---- .../prom_reporter_test.go} | 172 ++++++++------- core/web/testdata/body/health.html | 6 +- core/web/testdata/body/health.json | 18 +- core/web/testdata/body/health.txt | 2 +- integration-tests/go.mod | 1 - integration-tests/go.sum | 2 - integration-tests/load/go.mod | 21 +- integration-tests/load/go.sum | 42 +--- testdata/scripts/health/default.txtar | 20 +- testdata/scripts/health/multi-chain.txtar | 20 +- 25 files changed, 515 insertions(+), 943 deletions(-) create mode 100644 core/internal/mocks/prometheus_backend.go delete mode 100644 core/services/headreporter/head_reporter.go delete mode 100644 core/services/headreporter/head_reporter_mock.go delete mode 100644 core/services/headreporter/head_reporter_test.go delete mode 100644 core/services/headreporter/helper_test.go delete mode 100644 core/services/headreporter/prometheus_backend_mock.go delete mode 100644 core/services/headreporter/telemetry_reporter.go delete mode 100644 core/services/headreporter/telemetry_reporter_test.go rename core/services/{headreporter/prometheus_reporter.go => promreporter/prom_reporter.go} (63%) rename core/services/{headreporter/prometheus_reporter_test.go => promreporter/prom_reporter_test.go} (64%) diff --git a/.mockery.yaml b/.mockery.yaml index 6e56f27795..34b886d187 100644 --- a/.mockery.yaml +++ b/.mockery.yaml @@ -258,14 +258,10 @@ packages: ORM: Runner: PipelineParamUnmarshaler: - github.com/smartcontractkit/chainlink/v2/core/services/headreporter: + github.com/smartcontractkit/chainlink/v2/core/services/promreporter: config: - dir: "{{ .InterfaceDir }}" - filename: "{{ .InterfaceName | snakecase }}_mock.go" - inpackage: true - mockname: "Mock{{ .InterfaceName | camelcase }}" + dir: core/internal/mocks interfaces: - HeadReporter: PrometheusBackend: github.com/smartcontractkit/libocr/commontypes: config: diff --git a/contracts/gas-snapshots/functions.gas-snapshot b/contracts/gas-snapshots/functions.gas-snapshot index 44d557ebcf..69e0271684 100644 --- a/contracts/gas-snapshots/functions.gas-snapshot +++ b/contracts/gas-snapshots/functions.gas-snapshot @@ -45,7 +45,7 @@ FunctionsCoordinator_SetDONPublicKey:test_SetDONPublicKey_Success() (gas: 88970) FunctionsCoordinator_SetThresholdPublicKey:test_SetThresholdPublicKey_RevertNotOwner() (gas: 13915) FunctionsCoordinator_SetThresholdPublicKey:test_SetThresholdPublicKey_Success() (gas: 513165) FunctionsCoordinator_StartRequest:test_StartRequest_RevertIfNotRouter() (gas: 22802) -FunctionsCoordinator_StartRequest:test_StartRequest_Success() (gas: 150150) +FunctionsCoordinator_StartRequest:test_StartRequest_Success() (gas: 152650) FunctionsCoordinator__IsTransmitter:test__IsTransmitter_SuccessFound() (gas: 15106) FunctionsCoordinator__IsTransmitter:test__IsTransmitter_SuccessNotFound() (gas: 22916) FunctionsRequest_DEFAULT_BUFFER_SIZE:test_DEFAULT_BUFFER_SIZE() (gas: 3089) @@ -200,7 +200,7 @@ FunctionsTermsOfServiceAllowList_AcceptTermsOfService:test_AcceptTermsOfService_ FunctionsTermsOfServiceAllowList_AcceptTermsOfService:test_AcceptTermsOfService_RevertIfBlockedSender() (gas: 89013) FunctionsTermsOfServiceAllowList_AcceptTermsOfService:test_AcceptTermsOfService_RevertIfInvalidSigner() (gas: 23620) FunctionsTermsOfServiceAllowList_AcceptTermsOfService:test_AcceptTermsOfService_RevertIfRecipientContractIsNotSender() (gas: 1866619) -FunctionsTermsOfServiceAllowList_AcceptTermsOfService:test_AcceptTermsOfService_RevertIfRecipientIsNotSender() (gas: 26026) +FunctionsTermsOfServiceAllowList_AcceptTermsOfService:test_AcceptTermsOfService_RevertIfRecipientIsNotSender() (gas: 28526) FunctionsTermsOfServiceAllowList_AcceptTermsOfService:test_AcceptTermsOfService_SuccessIfAcceptingForContract() (gas: 1946966) FunctionsTermsOfServiceAllowList_AcceptTermsOfService:test_AcceptTermsOfService_SuccessIfAcceptingForSelf() (gas: 104555) FunctionsTermsOfServiceAllowList_BlockSender:test_BlockSender_RevertIfNotOwner() (gas: 15535) @@ -232,10 +232,10 @@ FunctionsTermsOfServiceAllowList_UpdateConfig:test_UpdateConfig_Success() (gas: Gas_AcceptTermsOfService:test_AcceptTermsOfService_Gas() (gas: 84725) Gas_AddConsumer:test_AddConsumer_Gas() (gas: 79140) Gas_CreateSubscription:test_CreateSubscription_Gas() (gas: 73419) -Gas_FulfillRequest_DuplicateRequestID:test_FulfillRequest_DuplicateRequestID_MaximumGas() (gas: 20717) -Gas_FulfillRequest_DuplicateRequestID:test_FulfillRequest_DuplicateRequestID_MinimumGas() (gas: 20157) -Gas_FulfillRequest_Success:test_FulfillRequest_Success_MaximumGas() (gas: 501339) -Gas_FulfillRequest_Success:test_FulfillRequest_Success_MinimumGas() (gas: 202509) -Gas_FundSubscription:test_FundSubscription_Gas() (gas: 38524) -Gas_SendRequest:test_SendRequest_MaximumGas() (gas: 988895) -Gas_SendRequest:test_SendRequest_MinimumGas() (gas: 181579) \ No newline at end of file +Gas_FulfillRequest_DuplicateRequestID:test_FulfillRequest_DuplicateRequestID_MaximumGas() (gas: 20562) +Gas_FulfillRequest_DuplicateRequestID:test_FulfillRequest_DuplicateRequestID_MinimumGas() (gas: 20024) +Gas_FulfillRequest_Success:test_FulfillRequest_Success_MaximumGas() (gas: 501184) +Gas_FulfillRequest_Success:test_FulfillRequest_Success_MinimumGas() (gas: 202376) +Gas_FundSubscription:test_FundSubscription_Gas() (gas: 38518) +Gas_SendRequest:test_SendRequest_MaximumGas() (gas: 984338) +Gas_SendRequest:test_SendRequest_MinimumGas() (gas: 181561) \ No newline at end of file diff --git a/core/internal/cltest/cltest.go b/core/internal/cltest/cltest.go index dc51ddd32f..12491300bf 100644 --- a/core/internal/cltest/cltest.go +++ b/core/internal/cltest/cltest.go @@ -461,6 +461,8 @@ func NewApplicationWithConfig(t testing.TB, cfg chainlink.GeneralConfig, flagsAn LoopRegistry: plugins.NewLoopRegistry(lggr, nil), MercuryPool: mercuryPool, CapabilitiesRegistry: capabilitiesRegistry, + CapabilitiesDispatcher: dispatcher, + CapabilitiesPeerWrapper: peerWrapper, }) require.NoError(t, err) diff --git a/core/internal/mocks/prometheus_backend.go b/core/internal/mocks/prometheus_backend.go new file mode 100644 index 0000000000..d02f7062cb --- /dev/null +++ b/core/internal/mocks/prometheus_backend.go @@ -0,0 +1,204 @@ +// Code generated by mockery v2.43.2. DO NOT EDIT. + +package mocks + +import ( + big "math/big" + + mock "github.com/stretchr/testify/mock" +) + +// PrometheusBackend is an autogenerated mock type for the PrometheusBackend type +type PrometheusBackend struct { + mock.Mock +} + +type PrometheusBackend_Expecter struct { + mock *mock.Mock +} + +func (_m *PrometheusBackend) EXPECT() *PrometheusBackend_Expecter { + return &PrometheusBackend_Expecter{mock: &_m.Mock} +} + +// SetMaxUnconfirmedAge provides a mock function with given fields: _a0, _a1 +func (_m *PrometheusBackend) SetMaxUnconfirmedAge(_a0 *big.Int, _a1 float64) { + _m.Called(_a0, _a1) +} + +// PrometheusBackend_SetMaxUnconfirmedAge_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetMaxUnconfirmedAge' +type PrometheusBackend_SetMaxUnconfirmedAge_Call struct { + *mock.Call +} + +// SetMaxUnconfirmedAge is a helper method to define mock.On call +// - _a0 *big.Int +// - _a1 float64 +func (_e *PrometheusBackend_Expecter) SetMaxUnconfirmedAge(_a0 interface{}, _a1 interface{}) *PrometheusBackend_SetMaxUnconfirmedAge_Call { + return &PrometheusBackend_SetMaxUnconfirmedAge_Call{Call: _e.mock.On("SetMaxUnconfirmedAge", _a0, _a1)} +} + +func (_c *PrometheusBackend_SetMaxUnconfirmedAge_Call) Run(run func(_a0 *big.Int, _a1 float64)) *PrometheusBackend_SetMaxUnconfirmedAge_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*big.Int), args[1].(float64)) + }) + return _c +} + +func (_c *PrometheusBackend_SetMaxUnconfirmedAge_Call) Return() *PrometheusBackend_SetMaxUnconfirmedAge_Call { + _c.Call.Return() + return _c +} + +func (_c *PrometheusBackend_SetMaxUnconfirmedAge_Call) RunAndReturn(run func(*big.Int, float64)) *PrometheusBackend_SetMaxUnconfirmedAge_Call { + _c.Call.Return(run) + return _c +} + +// SetMaxUnconfirmedBlocks provides a mock function with given fields: _a0, _a1 +func (_m *PrometheusBackend) SetMaxUnconfirmedBlocks(_a0 *big.Int, _a1 int64) { + _m.Called(_a0, _a1) +} + +// PrometheusBackend_SetMaxUnconfirmedBlocks_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetMaxUnconfirmedBlocks' +type PrometheusBackend_SetMaxUnconfirmedBlocks_Call struct { + *mock.Call +} + +// SetMaxUnconfirmedBlocks is a helper method to define mock.On call +// - _a0 *big.Int +// - _a1 int64 +func (_e *PrometheusBackend_Expecter) SetMaxUnconfirmedBlocks(_a0 interface{}, _a1 interface{}) *PrometheusBackend_SetMaxUnconfirmedBlocks_Call { + return &PrometheusBackend_SetMaxUnconfirmedBlocks_Call{Call: _e.mock.On("SetMaxUnconfirmedBlocks", _a0, _a1)} +} + +func (_c *PrometheusBackend_SetMaxUnconfirmedBlocks_Call) Run(run func(_a0 *big.Int, _a1 int64)) *PrometheusBackend_SetMaxUnconfirmedBlocks_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*big.Int), args[1].(int64)) + }) + return _c +} + +func (_c *PrometheusBackend_SetMaxUnconfirmedBlocks_Call) Return() *PrometheusBackend_SetMaxUnconfirmedBlocks_Call { + _c.Call.Return() + return _c +} + +func (_c *PrometheusBackend_SetMaxUnconfirmedBlocks_Call) RunAndReturn(run func(*big.Int, int64)) *PrometheusBackend_SetMaxUnconfirmedBlocks_Call { + _c.Call.Return(run) + return _c +} + +// SetPipelineRunsQueued provides a mock function with given fields: n +func (_m *PrometheusBackend) SetPipelineRunsQueued(n int) { + _m.Called(n) +} + +// PrometheusBackend_SetPipelineRunsQueued_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetPipelineRunsQueued' +type PrometheusBackend_SetPipelineRunsQueued_Call struct { + *mock.Call +} + +// SetPipelineRunsQueued is a helper method to define mock.On call +// - n int +func (_e *PrometheusBackend_Expecter) SetPipelineRunsQueued(n interface{}) *PrometheusBackend_SetPipelineRunsQueued_Call { + return &PrometheusBackend_SetPipelineRunsQueued_Call{Call: _e.mock.On("SetPipelineRunsQueued", n)} +} + +func (_c *PrometheusBackend_SetPipelineRunsQueued_Call) Run(run func(n int)) *PrometheusBackend_SetPipelineRunsQueued_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(int)) + }) + return _c +} + +func (_c *PrometheusBackend_SetPipelineRunsQueued_Call) Return() *PrometheusBackend_SetPipelineRunsQueued_Call { + _c.Call.Return() + return _c +} + +func (_c *PrometheusBackend_SetPipelineRunsQueued_Call) RunAndReturn(run func(int)) *PrometheusBackend_SetPipelineRunsQueued_Call { + _c.Call.Return(run) + return _c +} + +// SetPipelineTaskRunsQueued provides a mock function with given fields: n +func (_m *PrometheusBackend) SetPipelineTaskRunsQueued(n int) { + _m.Called(n) +} + +// PrometheusBackend_SetPipelineTaskRunsQueued_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetPipelineTaskRunsQueued' +type PrometheusBackend_SetPipelineTaskRunsQueued_Call struct { + *mock.Call +} + +// SetPipelineTaskRunsQueued is a helper method to define mock.On call +// - n int +func (_e *PrometheusBackend_Expecter) SetPipelineTaskRunsQueued(n interface{}) *PrometheusBackend_SetPipelineTaskRunsQueued_Call { + return &PrometheusBackend_SetPipelineTaskRunsQueued_Call{Call: _e.mock.On("SetPipelineTaskRunsQueued", n)} +} + +func (_c *PrometheusBackend_SetPipelineTaskRunsQueued_Call) Run(run func(n int)) *PrometheusBackend_SetPipelineTaskRunsQueued_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(int)) + }) + return _c +} + +func (_c *PrometheusBackend_SetPipelineTaskRunsQueued_Call) Return() *PrometheusBackend_SetPipelineTaskRunsQueued_Call { + _c.Call.Return() + return _c +} + +func (_c *PrometheusBackend_SetPipelineTaskRunsQueued_Call) RunAndReturn(run func(int)) *PrometheusBackend_SetPipelineTaskRunsQueued_Call { + _c.Call.Return(run) + return _c +} + +// SetUnconfirmedTransactions provides a mock function with given fields: _a0, _a1 +func (_m *PrometheusBackend) SetUnconfirmedTransactions(_a0 *big.Int, _a1 int64) { + _m.Called(_a0, _a1) +} + +// PrometheusBackend_SetUnconfirmedTransactions_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetUnconfirmedTransactions' +type PrometheusBackend_SetUnconfirmedTransactions_Call struct { + *mock.Call +} + +// SetUnconfirmedTransactions is a helper method to define mock.On call +// - _a0 *big.Int +// - _a1 int64 +func (_e *PrometheusBackend_Expecter) SetUnconfirmedTransactions(_a0 interface{}, _a1 interface{}) *PrometheusBackend_SetUnconfirmedTransactions_Call { + return &PrometheusBackend_SetUnconfirmedTransactions_Call{Call: _e.mock.On("SetUnconfirmedTransactions", _a0, _a1)} +} + +func (_c *PrometheusBackend_SetUnconfirmedTransactions_Call) Run(run func(_a0 *big.Int, _a1 int64)) *PrometheusBackend_SetUnconfirmedTransactions_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*big.Int), args[1].(int64)) + }) + return _c +} + +func (_c *PrometheusBackend_SetUnconfirmedTransactions_Call) Return() *PrometheusBackend_SetUnconfirmedTransactions_Call { + _c.Call.Return() + return _c +} + +func (_c *PrometheusBackend_SetUnconfirmedTransactions_Call) RunAndReturn(run func(*big.Int, int64)) *PrometheusBackend_SetUnconfirmedTransactions_Call { + _c.Call.Return(run) + return _c +} + +// NewPrometheusBackend creates a new instance of PrometheusBackend. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewPrometheusBackend(t interface { + mock.TestingT + Cleanup(func()) +}) *PrometheusBackend { + mock := &PrometheusBackend{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/core/services/chainlink/application.go b/core/services/chainlink/application.go index cc130d0283..e880ecfad2 100644 --- a/core/services/chainlink/application.go +++ b/core/services/chainlink/application.go @@ -25,10 +25,13 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" "github.com/smartcontractkit/chainlink/v2/core/capabilities" + remotetypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" "github.com/smartcontractkit/chainlink/v2/core/services/standardcapabilities" "github.com/smartcontractkit/chainlink/v2/core/static" + "github.com/smartcontractkit/chainlink/v2/core/services/promreporter" + "github.com/smartcontractkit/chainlink/v2/core/bridges" "github.com/smartcontractkit/chainlink/v2/core/build" "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote" @@ -46,7 +49,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/feeds" "github.com/smartcontractkit/chainlink/v2/core/services/fluxmonitorv2" "github.com/smartcontractkit/chainlink/v2/core/services/gateway" - "github.com/smartcontractkit/chainlink/v2/core/services/headreporter" "github.com/smartcontractkit/chainlink/v2/core/services/job" "github.com/smartcontractkit/chainlink/v2/core/services/keeper" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" @@ -180,6 +182,8 @@ type ApplicationOpts struct { GRPCOpts loop.GRPCOpts MercuryPool wsrpc.Pool CapabilitiesRegistry *capabilities.Registry + CapabilitiesDispatcher remotetypes.Dispatcher + CapabilitiesPeerWrapper p2ptypes.PeerWrapper } // NewApplication initializes a new store if one is not already @@ -199,20 +203,36 @@ func NewApplication(opts ApplicationOpts) (Application, error) { restrictedHTTPClient := opts.RestrictedHTTPClient unrestrictedHTTPClient := opts.UnrestrictedHTTPClient - if opts.CapabilitiesRegistry == nil { // for tests only, in prod Registry is always set at this point + if opts.CapabilitiesRegistry == nil { + // for tests only, in prod Registry should always be set at this point opts.CapabilitiesRegistry = capabilities.NewRegistry(globalLogger) } var externalPeerWrapper p2ptypes.PeerWrapper - var capabilityRegistrySyncer registrysyncer.Syncer + if cfg.Capabilities().Peering().Enabled() { + var dispatcher remotetypes.Dispatcher + if opts.CapabilitiesDispatcher == nil { + externalPeer := externalp2p.NewExternalPeerWrapper(keyStore.P2P(), cfg.Capabilities().Peering(), opts.DS, globalLogger) + signer := externalPeer + externalPeerWrapper = externalPeer + remoteDispatcher := remote.NewDispatcher(externalPeerWrapper, signer, opts.CapabilitiesRegistry, globalLogger) + srvcs = append(srvcs, remoteDispatcher) + + dispatcher = remoteDispatcher + } else { + dispatcher = opts.CapabilitiesDispatcher + externalPeerWrapper = opts.CapabilitiesPeerWrapper + } + + srvcs = append(srvcs, externalPeerWrapper) - if cfg.Capabilities().ExternalRegistry().Address() != "" { rid := cfg.Capabilities().ExternalRegistry().RelayID() registryAddress := cfg.Capabilities().ExternalRegistry().Address() relayer, err := relayerChainInterops.Get(rid) if err != nil { return nil, fmt.Errorf("could not fetch relayer %s configured for capabilities registry: %w", rid, err) } + registrySyncer, err := registrysyncer.New( globalLogger, externalPeerWrapper, @@ -223,31 +243,15 @@ func NewApplication(opts ApplicationOpts) (Application, error) { return nil, fmt.Errorf("could not configure syncer: %w", err) } - capabilityRegistrySyncer = registrySyncer - srvcs = append(srvcs, capabilityRegistrySyncer) - } - - if cfg.Capabilities().Peering().Enabled() { - if capabilityRegistrySyncer == nil { - return nil, errors.Errorf("peering enabled but no capability registry found") - } - externalPeer := externalp2p.NewExternalPeerWrapper(keyStore.P2P(), cfg.Capabilities().Peering(), opts.DS, globalLogger) - signer := externalPeer - externalPeerWrapper = externalPeer - - srvcs = append(srvcs, externalPeerWrapper) - - dispatcher := remote.NewDispatcher(externalPeerWrapper, signer, opts.CapabilitiesRegistry, globalLogger) - wfLauncher := capabilities.NewLauncher( globalLogger, externalPeerWrapper, dispatcher, opts.CapabilitiesRegistry, ) + registrySyncer.AddLauncher(wfLauncher) - capabilityRegistrySyncer.AddLauncher(wfLauncher) - srvcs = append(srvcs, dispatcher, wfLauncher) + srvcs = append(srvcs, dispatcher, wfLauncher, registrySyncer) } // LOOPs can be created as options, in the case of LOOP relayers, or @@ -320,6 +324,8 @@ func NewApplication(opts ApplicationOpts) (Application, error) { srvcs = append(srvcs, mailMon) srvcs = append(srvcs, relayerChainInterops.Services()...) + promReporter := promreporter.NewPromReporter(opts.DS, legacyEVMChains, globalLogger) + srvcs = append(srvcs, promReporter) // Initialize Local Users ORM and Authentication Provider specified in config // BasicAdminUsersORM is initialized and required regardless of separate Authentication Provider @@ -359,16 +365,8 @@ func NewApplication(opts ApplicationOpts) (Application, error) { workflowORM = workflowstore.NewDBStore(opts.DS, globalLogger, clockwork.NewRealClock()) ) - promReporter := headreporter.NewPrometheusReporter(opts.DS, legacyEVMChains) - chainIDs := make([]*big.Int, legacyEVMChains.Len()) - for i, chain := range legacyEVMChains.Slice() { - chainIDs[i] = chain.ID() - } - telemReporter := headreporter.NewTelemetryReporter(telemetryManager, globalLogger, chainIDs...) - headReporter := headreporter.NewHeadReporterService(opts.DS, globalLogger, promReporter, telemReporter) - srvcs = append(srvcs, headReporter) for _, chain := range legacyEVMChains.Slice() { - chain.HeadBroadcaster().Subscribe(headReporter) + chain.HeadBroadcaster().Subscribe(promReporter) chain.TxManager().RegisterResumeCallback(pipelineRunner.ResumeRun) } diff --git a/core/services/headreporter/head_reporter.go b/core/services/headreporter/head_reporter.go deleted file mode 100644 index 94de8ae2be..0000000000 --- a/core/services/headreporter/head_reporter.go +++ /dev/null @@ -1,111 +0,0 @@ -package headreporter - -import ( - "context" - "sync" - "time" - - "github.com/smartcontractkit/chainlink-common/pkg/services" - "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" - "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" - - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker/types" - evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" - "github.com/smartcontractkit/chainlink/v2/core/logger" -) - -type ( - HeadReporter interface { - ReportNewHead(ctx context.Context, head *evmtypes.Head) error - ReportPeriodic(ctx context.Context) error - } - - HeadReporterService struct { - services.StateMachine - ds sqlutil.DataSource - lggr logger.Logger - newHeads *mailbox.Mailbox[*evmtypes.Head] - chStop services.StopChan - wgDone sync.WaitGroup - reportPeriod time.Duration - reporters []HeadReporter - unsubscribeFns []func() - } -) - -func NewHeadReporterService(ds sqlutil.DataSource, lggr logger.Logger, reporters ...HeadReporter) *HeadReporterService { - return &HeadReporterService{ - ds: ds, - lggr: lggr.Named("HeadReporter"), - newHeads: mailbox.NewSingle[*evmtypes.Head](), - chStop: make(chan struct{}), - reporters: reporters, - reportPeriod: 15 * time.Second, - } -} - -func (hrd *HeadReporterService) Subscribe(subFn func(types.HeadTrackable) (evmtypes.Head, func())) { - _, unsubscribe := subFn(hrd) - hrd.unsubscribeFns = append(hrd.unsubscribeFns, unsubscribe) -} - -func (hrd *HeadReporterService) Start(context.Context) error { - return hrd.StartOnce(hrd.Name(), func() error { - hrd.wgDone.Add(1) - go hrd.eventLoop() - return nil - }) -} - -func (hrd *HeadReporterService) Close() error { - return hrd.StopOnce(hrd.Name(), func() error { - close(hrd.chStop) - hrd.wgDone.Wait() - return nil - }) -} - -func (hrd *HeadReporterService) Name() string { - return hrd.lggr.Name() -} - -func (hrd *HeadReporterService) HealthReport() map[string]error { - return map[string]error{hrd.Name(): hrd.Healthy()} -} - -func (hrd *HeadReporterService) OnNewLongestChain(ctx context.Context, head *evmtypes.Head) { - hrd.newHeads.Deliver(head) -} - -func (hrd *HeadReporterService) eventLoop() { - hrd.lggr.Debug("Starting event loop") - defer hrd.wgDone.Done() - ctx, cancel := hrd.chStop.NewCtx() - defer cancel() - after := time.After(hrd.reportPeriod) - for { - select { - case <-hrd.newHeads.Notify(): - head, exists := hrd.newHeads.Retrieve() - if !exists { - continue - } - for _, reporter := range hrd.reporters { - err := reporter.ReportNewHead(ctx, head) - if err != nil && ctx.Err() == nil { - hrd.lggr.Errorw("Error reporting new head", "err", err) - } - } - case <-after: - for _, reporter := range hrd.reporters { - err := reporter.ReportPeriodic(ctx) - if err != nil && ctx.Err() == nil { - hrd.lggr.Errorw("Error in periodic report", "err", err) - } - } - after = time.After(hrd.reportPeriod) - case <-hrd.chStop: - return - } - } -} diff --git a/core/services/headreporter/head_reporter_mock.go b/core/services/headreporter/head_reporter_mock.go deleted file mode 100644 index 21978abb86..0000000000 --- a/core/services/headreporter/head_reporter_mock.go +++ /dev/null @@ -1,130 +0,0 @@ -// Code generated by mockery v2.43.2. DO NOT EDIT. - -package headreporter - -import ( - context "context" - - types "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" - mock "github.com/stretchr/testify/mock" -) - -// MockHeadReporter is an autogenerated mock type for the HeadReporter type -type MockHeadReporter struct { - mock.Mock -} - -type MockHeadReporter_Expecter struct { - mock *mock.Mock -} - -func (_m *MockHeadReporter) EXPECT() *MockHeadReporter_Expecter { - return &MockHeadReporter_Expecter{mock: &_m.Mock} -} - -// ReportNewHead provides a mock function with given fields: ctx, head -func (_m *MockHeadReporter) ReportNewHead(ctx context.Context, head *types.Head) error { - ret := _m.Called(ctx, head) - - if len(ret) == 0 { - panic("no return value specified for ReportNewHead") - } - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, *types.Head) error); ok { - r0 = rf(ctx, head) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// MockHeadReporter_ReportNewHead_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ReportNewHead' -type MockHeadReporter_ReportNewHead_Call struct { - *mock.Call -} - -// ReportNewHead is a helper method to define mock.On call -// - ctx context.Context -// - head *types.Head -func (_e *MockHeadReporter_Expecter) ReportNewHead(ctx interface{}, head interface{}) *MockHeadReporter_ReportNewHead_Call { - return &MockHeadReporter_ReportNewHead_Call{Call: _e.mock.On("ReportNewHead", ctx, head)} -} - -func (_c *MockHeadReporter_ReportNewHead_Call) Run(run func(ctx context.Context, head *types.Head)) *MockHeadReporter_ReportNewHead_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context), args[1].(*types.Head)) - }) - return _c -} - -func (_c *MockHeadReporter_ReportNewHead_Call) Return(_a0 error) *MockHeadReporter_ReportNewHead_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *MockHeadReporter_ReportNewHead_Call) RunAndReturn(run func(context.Context, *types.Head) error) *MockHeadReporter_ReportNewHead_Call { - _c.Call.Return(run) - return _c -} - -// ReportPeriodic provides a mock function with given fields: ctx -func (_m *MockHeadReporter) ReportPeriodic(ctx context.Context) error { - ret := _m.Called(ctx) - - if len(ret) == 0 { - panic("no return value specified for ReportPeriodic") - } - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context) error); ok { - r0 = rf(ctx) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// MockHeadReporter_ReportPeriodic_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ReportPeriodic' -type MockHeadReporter_ReportPeriodic_Call struct { - *mock.Call -} - -// ReportPeriodic is a helper method to define mock.On call -// - ctx context.Context -func (_e *MockHeadReporter_Expecter) ReportPeriodic(ctx interface{}) *MockHeadReporter_ReportPeriodic_Call { - return &MockHeadReporter_ReportPeriodic_Call{Call: _e.mock.On("ReportPeriodic", ctx)} -} - -func (_c *MockHeadReporter_ReportPeriodic_Call) Run(run func(ctx context.Context)) *MockHeadReporter_ReportPeriodic_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(context.Context)) - }) - return _c -} - -func (_c *MockHeadReporter_ReportPeriodic_Call) Return(_a0 error) *MockHeadReporter_ReportPeriodic_Call { - _c.Call.Return(_a0) - return _c -} - -func (_c *MockHeadReporter_ReportPeriodic_Call) RunAndReturn(run func(context.Context) error) *MockHeadReporter_ReportPeriodic_Call { - _c.Call.Return(run) - return _c -} - -// NewMockHeadReporter creates a new instance of MockHeadReporter. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -// The first argument is typically a *testing.T value. -func NewMockHeadReporter(t interface { - mock.TestingT - Cleanup(func()) -}) *MockHeadReporter { - mock := &MockHeadReporter{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/core/services/headreporter/head_reporter_test.go b/core/services/headreporter/head_reporter_test.go deleted file mode 100644 index 304dd59a47..0000000000 --- a/core/services/headreporter/head_reporter_test.go +++ /dev/null @@ -1,51 +0,0 @@ -package headreporter - -import ( - "sync/atomic" - "testing" - "time" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/mock" - "github.com/stretchr/testify/require" - - evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" - ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" - - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" - "github.com/smartcontractkit/chainlink/v2/core/logger" -) - -func NewHead() evmtypes.Head { - return evmtypes.Head{Number: 42, EVMChainID: ubig.NewI(0)} -} - -func Test_HeadReporterService(t *testing.T) { - t.Run("report everything", func(t *testing.T) { - db := pgtest.NewSqlxDB(t) - - headReporter := NewMockHeadReporter(t) - service := NewHeadReporterService(db, logger.TestLogger(t), headReporter) - service.reportPeriod = time.Second - err := service.Start(testutils.Context(t)) - require.NoError(t, err) - - var reportCalls atomic.Int32 - head := NewHead() - headReporter.On("ReportNewHead", mock.Anything, &head).Run(func(args mock.Arguments) { - reportCalls.Add(1) - }).Return(nil) - headReporter.On("ReportPeriodic", mock.Anything).Run(func(args mock.Arguments) { - reportCalls.Add(1) - }).Return(nil) - service.OnNewLongestChain(testutils.Context(t), &head) - - require.Eventually(t, func() bool { return reportCalls.Load() == 2 }, 5*time.Second, 100*time.Millisecond) - }) - - t.Run("has default report period", func(t *testing.T) { - service := NewHeadReporterService(pgtest.NewSqlxDB(t), logger.TestLogger(t), NewMockHeadReporter(t)) - assert.Equal(t, service.reportPeriod, 15*time.Second) - }) -} diff --git a/core/services/headreporter/helper_test.go b/core/services/headreporter/helper_test.go deleted file mode 100644 index fa05182a85..0000000000 --- a/core/services/headreporter/helper_test.go +++ /dev/null @@ -1,5 +0,0 @@ -package headreporter - -func (p *prometheusReporter) SetBackend(b PrometheusBackend) { - p.backend = b -} diff --git a/core/services/headreporter/prometheus_backend_mock.go b/core/services/headreporter/prometheus_backend_mock.go deleted file mode 100644 index ca83f6c4fb..0000000000 --- a/core/services/headreporter/prometheus_backend_mock.go +++ /dev/null @@ -1,204 +0,0 @@ -// Code generated by mockery v2.43.2. DO NOT EDIT. - -package headreporter - -import ( - big "math/big" - - mock "github.com/stretchr/testify/mock" -) - -// MockPrometheusBackend is an autogenerated mock type for the PrometheusBackend type -type MockPrometheusBackend struct { - mock.Mock -} - -type MockPrometheusBackend_Expecter struct { - mock *mock.Mock -} - -func (_m *MockPrometheusBackend) EXPECT() *MockPrometheusBackend_Expecter { - return &MockPrometheusBackend_Expecter{mock: &_m.Mock} -} - -// SetMaxUnconfirmedAge provides a mock function with given fields: _a0, _a1 -func (_m *MockPrometheusBackend) SetMaxUnconfirmedAge(_a0 *big.Int, _a1 float64) { - _m.Called(_a0, _a1) -} - -// MockPrometheusBackend_SetMaxUnconfirmedAge_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetMaxUnconfirmedAge' -type MockPrometheusBackend_SetMaxUnconfirmedAge_Call struct { - *mock.Call -} - -// SetMaxUnconfirmedAge is a helper method to define mock.On call -// - _a0 *big.Int -// - _a1 float64 -func (_e *MockPrometheusBackend_Expecter) SetMaxUnconfirmedAge(_a0 interface{}, _a1 interface{}) *MockPrometheusBackend_SetMaxUnconfirmedAge_Call { - return &MockPrometheusBackend_SetMaxUnconfirmedAge_Call{Call: _e.mock.On("SetMaxUnconfirmedAge", _a0, _a1)} -} - -func (_c *MockPrometheusBackend_SetMaxUnconfirmedAge_Call) Run(run func(_a0 *big.Int, _a1 float64)) *MockPrometheusBackend_SetMaxUnconfirmedAge_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*big.Int), args[1].(float64)) - }) - return _c -} - -func (_c *MockPrometheusBackend_SetMaxUnconfirmedAge_Call) Return() *MockPrometheusBackend_SetMaxUnconfirmedAge_Call { - _c.Call.Return() - return _c -} - -func (_c *MockPrometheusBackend_SetMaxUnconfirmedAge_Call) RunAndReturn(run func(*big.Int, float64)) *MockPrometheusBackend_SetMaxUnconfirmedAge_Call { - _c.Call.Return(run) - return _c -} - -// SetMaxUnconfirmedBlocks provides a mock function with given fields: _a0, _a1 -func (_m *MockPrometheusBackend) SetMaxUnconfirmedBlocks(_a0 *big.Int, _a1 int64) { - _m.Called(_a0, _a1) -} - -// MockPrometheusBackend_SetMaxUnconfirmedBlocks_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetMaxUnconfirmedBlocks' -type MockPrometheusBackend_SetMaxUnconfirmedBlocks_Call struct { - *mock.Call -} - -// SetMaxUnconfirmedBlocks is a helper method to define mock.On call -// - _a0 *big.Int -// - _a1 int64 -func (_e *MockPrometheusBackend_Expecter) SetMaxUnconfirmedBlocks(_a0 interface{}, _a1 interface{}) *MockPrometheusBackend_SetMaxUnconfirmedBlocks_Call { - return &MockPrometheusBackend_SetMaxUnconfirmedBlocks_Call{Call: _e.mock.On("SetMaxUnconfirmedBlocks", _a0, _a1)} -} - -func (_c *MockPrometheusBackend_SetMaxUnconfirmedBlocks_Call) Run(run func(_a0 *big.Int, _a1 int64)) *MockPrometheusBackend_SetMaxUnconfirmedBlocks_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*big.Int), args[1].(int64)) - }) - return _c -} - -func (_c *MockPrometheusBackend_SetMaxUnconfirmedBlocks_Call) Return() *MockPrometheusBackend_SetMaxUnconfirmedBlocks_Call { - _c.Call.Return() - return _c -} - -func (_c *MockPrometheusBackend_SetMaxUnconfirmedBlocks_Call) RunAndReturn(run func(*big.Int, int64)) *MockPrometheusBackend_SetMaxUnconfirmedBlocks_Call { - _c.Call.Return(run) - return _c -} - -// SetPipelineRunsQueued provides a mock function with given fields: n -func (_m *MockPrometheusBackend) SetPipelineRunsQueued(n int) { - _m.Called(n) -} - -// MockPrometheusBackend_SetPipelineRunsQueued_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetPipelineRunsQueued' -type MockPrometheusBackend_SetPipelineRunsQueued_Call struct { - *mock.Call -} - -// SetPipelineRunsQueued is a helper method to define mock.On call -// - n int -func (_e *MockPrometheusBackend_Expecter) SetPipelineRunsQueued(n interface{}) *MockPrometheusBackend_SetPipelineRunsQueued_Call { - return &MockPrometheusBackend_SetPipelineRunsQueued_Call{Call: _e.mock.On("SetPipelineRunsQueued", n)} -} - -func (_c *MockPrometheusBackend_SetPipelineRunsQueued_Call) Run(run func(n int)) *MockPrometheusBackend_SetPipelineRunsQueued_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(int)) - }) - return _c -} - -func (_c *MockPrometheusBackend_SetPipelineRunsQueued_Call) Return() *MockPrometheusBackend_SetPipelineRunsQueued_Call { - _c.Call.Return() - return _c -} - -func (_c *MockPrometheusBackend_SetPipelineRunsQueued_Call) RunAndReturn(run func(int)) *MockPrometheusBackend_SetPipelineRunsQueued_Call { - _c.Call.Return(run) - return _c -} - -// SetPipelineTaskRunsQueued provides a mock function with given fields: n -func (_m *MockPrometheusBackend) SetPipelineTaskRunsQueued(n int) { - _m.Called(n) -} - -// MockPrometheusBackend_SetPipelineTaskRunsQueued_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetPipelineTaskRunsQueued' -type MockPrometheusBackend_SetPipelineTaskRunsQueued_Call struct { - *mock.Call -} - -// SetPipelineTaskRunsQueued is a helper method to define mock.On call -// - n int -func (_e *MockPrometheusBackend_Expecter) SetPipelineTaskRunsQueued(n interface{}) *MockPrometheusBackend_SetPipelineTaskRunsQueued_Call { - return &MockPrometheusBackend_SetPipelineTaskRunsQueued_Call{Call: _e.mock.On("SetPipelineTaskRunsQueued", n)} -} - -func (_c *MockPrometheusBackend_SetPipelineTaskRunsQueued_Call) Run(run func(n int)) *MockPrometheusBackend_SetPipelineTaskRunsQueued_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(int)) - }) - return _c -} - -func (_c *MockPrometheusBackend_SetPipelineTaskRunsQueued_Call) Return() *MockPrometheusBackend_SetPipelineTaskRunsQueued_Call { - _c.Call.Return() - return _c -} - -func (_c *MockPrometheusBackend_SetPipelineTaskRunsQueued_Call) RunAndReturn(run func(int)) *MockPrometheusBackend_SetPipelineTaskRunsQueued_Call { - _c.Call.Return(run) - return _c -} - -// SetUnconfirmedTransactions provides a mock function with given fields: _a0, _a1 -func (_m *MockPrometheusBackend) SetUnconfirmedTransactions(_a0 *big.Int, _a1 int64) { - _m.Called(_a0, _a1) -} - -// MockPrometheusBackend_SetUnconfirmedTransactions_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetUnconfirmedTransactions' -type MockPrometheusBackend_SetUnconfirmedTransactions_Call struct { - *mock.Call -} - -// SetUnconfirmedTransactions is a helper method to define mock.On call -// - _a0 *big.Int -// - _a1 int64 -func (_e *MockPrometheusBackend_Expecter) SetUnconfirmedTransactions(_a0 interface{}, _a1 interface{}) *MockPrometheusBackend_SetUnconfirmedTransactions_Call { - return &MockPrometheusBackend_SetUnconfirmedTransactions_Call{Call: _e.mock.On("SetUnconfirmedTransactions", _a0, _a1)} -} - -func (_c *MockPrometheusBackend_SetUnconfirmedTransactions_Call) Run(run func(_a0 *big.Int, _a1 int64)) *MockPrometheusBackend_SetUnconfirmedTransactions_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*big.Int), args[1].(int64)) - }) - return _c -} - -func (_c *MockPrometheusBackend_SetUnconfirmedTransactions_Call) Return() *MockPrometheusBackend_SetUnconfirmedTransactions_Call { - _c.Call.Return() - return _c -} - -func (_c *MockPrometheusBackend_SetUnconfirmedTransactions_Call) RunAndReturn(run func(*big.Int, int64)) *MockPrometheusBackend_SetUnconfirmedTransactions_Call { - _c.Call.Return(run) - return _c -} - -// NewMockPrometheusBackend creates a new instance of MockPrometheusBackend. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -// The first argument is typically a *testing.T value. -func NewMockPrometheusBackend(t interface { - mock.TestingT - Cleanup(func()) -}) *MockPrometheusBackend { - mock := &MockPrometheusBackend{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/core/services/headreporter/telemetry_reporter.go b/core/services/headreporter/telemetry_reporter.go deleted file mode 100644 index 0d93ca59a4..0000000000 --- a/core/services/headreporter/telemetry_reporter.go +++ /dev/null @@ -1,69 +0,0 @@ -package headreporter - -import ( - "context" - "math/big" - - "github.com/pkg/errors" - - "github.com/smartcontractkit/libocr/commontypes" - "google.golang.org/protobuf/proto" - - evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" - "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/synchronization" - "github.com/smartcontractkit/chainlink/v2/core/services/synchronization/telem" - "github.com/smartcontractkit/chainlink/v2/core/services/telemetry" -) - -type telemetryReporter struct { - lggr logger.Logger - endpoints map[uint64]commontypes.MonitoringEndpoint -} - -func NewTelemetryReporter(monitoringEndpointGen telemetry.MonitoringEndpointGenerator, lggr logger.Logger, chainIDs ...*big.Int) HeadReporter { - endpoints := make(map[uint64]commontypes.MonitoringEndpoint) - for _, chainID := range chainIDs { - endpoints[chainID.Uint64()] = monitoringEndpointGen.GenMonitoringEndpoint("EVM", chainID.String(), "", synchronization.HeadReport) - } - return &telemetryReporter{lggr: lggr.Named("TelemetryReporter"), endpoints: endpoints} -} - -func (t *telemetryReporter) ReportNewHead(ctx context.Context, head *evmtypes.Head) error { - monitoringEndpoint := t.endpoints[head.EVMChainID.ToInt().Uint64()] - if monitoringEndpoint == nil { - return errors.Errorf("No monitoring endpoint provided chain_id=%d", head.EVMChainID.Int64()) - } - var finalized *telem.Block - latestFinalizedHead := head.LatestFinalizedHead() - if latestFinalizedHead != nil { - finalized = &telem.Block{ - Timestamp: uint64(latestFinalizedHead.GetTimestamp().UTC().Unix()), - Number: uint64(latestFinalizedHead.BlockNumber()), - Hash: latestFinalizedHead.BlockHash().Hex(), - } - } - request := &telem.HeadReportRequest{ - ChainID: head.EVMChainID.String(), - Latest: &telem.Block{ - Timestamp: uint64(head.Timestamp.UTC().Unix()), - Number: uint64(head.Number), - Hash: head.Hash.Hex(), - }, - Finalized: finalized, - } - bytes, err := proto.Marshal(request) - if err != nil { - return errors.WithMessage(err, "telem.HeadReportRequest marshal error") - } - monitoringEndpoint.SendLog(bytes) - if finalized == nil { - t.lggr.Infow("No finalized block was found", "chainID", head.EVMChainID.Int64(), - "head.number", head.Number, "chainLength", head.ChainLength()) - } - return nil -} - -func (t *telemetryReporter) ReportPeriodic(ctx context.Context) error { - return nil -} diff --git a/core/services/headreporter/telemetry_reporter_test.go b/core/services/headreporter/telemetry_reporter_test.go deleted file mode 100644 index 85bfea5866..0000000000 --- a/core/services/headreporter/telemetry_reporter_test.go +++ /dev/null @@ -1,108 +0,0 @@ -package headreporter_test - -import ( - "math/big" - "testing" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/stretchr/testify/assert" - "google.golang.org/protobuf/proto" - - mocks2 "github.com/smartcontractkit/chainlink/v2/common/types/mocks" - evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" - ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/headreporter" - "github.com/smartcontractkit/chainlink/v2/core/services/synchronization" - "github.com/smartcontractkit/chainlink/v2/core/services/synchronization/telem" - "github.com/smartcontractkit/chainlink/v2/core/services/telemetry" -) - -func Test_TelemetryReporter_NewHead(t *testing.T) { - head := evmtypes.Head{ - Number: 42, - EVMChainID: ubig.NewI(100), - Hash: common.HexToHash("0x1010"), - Timestamp: time.UnixMilli(1000), - IsFinalized: false, - Parent: &evmtypes.Head{ - Number: 41, - Hash: common.HexToHash("0x1009"), - Timestamp: time.UnixMilli(999), - IsFinalized: true, - }, - } - requestBytes, err := proto.Marshal(&telem.HeadReportRequest{ - ChainID: "100", - Latest: &telem.Block{ - Timestamp: uint64(head.Timestamp.UTC().Unix()), - Number: 42, - Hash: head.Hash.Hex(), - }, - Finalized: &telem.Block{ - Timestamp: uint64(head.Parent.Timestamp.UTC().Unix()), - Number: 41, - Hash: head.Parent.Hash.Hex(), - }, - }) - assert.NoError(t, err) - - monitoringEndpoint := mocks2.NewMonitoringEndpoint(t) - monitoringEndpoint.On("SendLog", requestBytes).Return() - - monitoringEndpointGen := telemetry.NewMockMonitoringEndpointGenerator(t) - monitoringEndpointGen. - On("GenMonitoringEndpoint", "EVM", "100", "", synchronization.HeadReport). - Return(monitoringEndpoint) - reporter := headreporter.NewTelemetryReporter(monitoringEndpointGen, logger.TestLogger(t), big.NewInt(100)) - - err = reporter.ReportNewHead(testutils.Context(t), &head) - assert.NoError(t, err) -} - -func Test_TelemetryReporter_NewHeadMissingFinalized(t *testing.T) { - head := evmtypes.Head{ - Number: 42, - EVMChainID: ubig.NewI(100), - Hash: common.HexToHash("0x1010"), - Timestamp: time.UnixMilli(1000), - IsFinalized: false, - } - requestBytes, err := proto.Marshal(&telem.HeadReportRequest{ - ChainID: "100", - Latest: &telem.Block{ - Timestamp: uint64(head.Timestamp.UTC().Unix()), - Number: 42, - Hash: head.Hash.Hex(), - }, - }) - assert.NoError(t, err) - - monitoringEndpoint := mocks2.NewMonitoringEndpoint(t) - monitoringEndpoint.On("SendLog", requestBytes).Return() - - monitoringEndpointGen := telemetry.NewMockMonitoringEndpointGenerator(t) - monitoringEndpointGen. - On("GenMonitoringEndpoint", "EVM", "100", "", synchronization.HeadReport). - Return(monitoringEndpoint) - reporter := headreporter.NewTelemetryReporter(monitoringEndpointGen, logger.TestLogger(t), big.NewInt(100)) - - err = reporter.ReportNewHead(testutils.Context(t), &head) - assert.NoError(t, err) -} - -func Test_TelemetryReporter_NewHead_MissingEndpoint(t *testing.T) { - monitoringEndpointGen := telemetry.NewMockMonitoringEndpointGenerator(t) - monitoringEndpointGen. - On("GenMonitoringEndpoint", "EVM", "100", "", synchronization.HeadReport). - Return(nil) - - reporter := headreporter.NewTelemetryReporter(monitoringEndpointGen, logger.TestLogger(t), big.NewInt(100)) - - head := evmtypes.Head{Number: 42, EVMChainID: ubig.NewI(100)} - - err := reporter.ReportNewHead(testutils.Context(t), &head) - assert.Errorf(t, err, "No monitoring endpoint provided chain_id=100") -} diff --git a/core/services/ocr2/plugins/ccip/testhelpers/integration/chainlink.go b/core/services/ocr2/plugins/ccip/testhelpers/integration/chainlink.go index 73c5992470..bb2f6b0f7c 100644 --- a/core/services/ocr2/plugins/ccip/testhelpers/integration/chainlink.go +++ b/core/services/ocr2/plugins/ccip/testhelpers/integration/chainlink.go @@ -38,6 +38,7 @@ import ( cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" + evmcapabilities "github.com/smartcontractkit/chainlink/v2/core/capabilities" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" v2 "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" @@ -460,9 +461,10 @@ func setupNodeCCIP( } loopRegistry := plugins.NewLoopRegistry(lggr.Named("LoopRegistry"), config.Tracing()) relayerFactory := chainlink.RelayerFactory{ - Logger: lggr, - LoopRegistry: loopRegistry, - GRPCOpts: loop.GRPCOpts{}, + Logger: lggr, + LoopRegistry: loopRegistry, + GRPCOpts: loop.GRPCOpts{}, + CapabilitiesRegistry: evmcapabilities.NewRegistry(logger.TestLogger(t)), } testCtx := testutils.Context(t) // evm alway enabled for backward compatibility diff --git a/core/services/ocr2/plugins/ccip/testhelpers/testhelpers_1_4_0/chainlink.go b/core/services/ocr2/plugins/ccip/testhelpers/testhelpers_1_4_0/chainlink.go index 5099a4b57e..8d7a4551f1 100644 --- a/core/services/ocr2/plugins/ccip/testhelpers/testhelpers_1_4_0/chainlink.go +++ b/core/services/ocr2/plugins/ccip/testhelpers/testhelpers_1_4_0/chainlink.go @@ -37,6 +37,7 @@ import ( cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" + evmcapabilities "github.com/smartcontractkit/chainlink/v2/core/capabilities" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" v2 "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" @@ -457,9 +458,10 @@ func setupNodeCCIP( } loopRegistry := plugins.NewLoopRegistry(lggr.Named("LoopRegistry"), config.Tracing()) relayerFactory := chainlink.RelayerFactory{ - Logger: lggr, - LoopRegistry: loopRegistry, - GRPCOpts: loop.GRPCOpts{}, + Logger: lggr, + LoopRegistry: loopRegistry, + GRPCOpts: loop.GRPCOpts{}, + CapabilitiesRegistry: evmcapabilities.NewRegistry(lggr), } testCtx := testutils.Context(t) // evm alway enabled for backward compatibility diff --git a/core/services/headreporter/prometheus_reporter.go b/core/services/promreporter/prom_reporter.go similarity index 63% rename from core/services/headreporter/prometheus_reporter.go rename to core/services/promreporter/prom_reporter.go index 3e39c7aca4..31d5f1129e 100644 --- a/core/services/headreporter/prometheus_reporter.go +++ b/core/services/promreporter/prom_reporter.go @@ -1,28 +1,40 @@ -package headreporter +package promreporter import ( "context" "fmt" "math/big" + "sync" "time" + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" + txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" + "github.com/pkg/errors" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" "go.uber.org/multierr" - "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" - txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" + "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" + evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" + "github.com/smartcontractkit/chainlink/v2/core/logger" ) type ( - prometheusReporter struct { - ds sqlutil.DataSource - chains legacyevm.LegacyChainContainer - backend PrometheusBackend + promReporter struct { + services.StateMachine + ds sqlutil.DataSource + chains legacyevm.LegacyChainContainer + lggr logger.Logger + backend PrometheusBackend + newHeads *mailbox.Mailbox[*evmtypes.Head] + chStop services.StopChan + wgDone sync.WaitGroup + reportPeriod time.Duration } PrometheusBackend interface { @@ -59,15 +71,103 @@ var ( }) ) -func NewPrometheusReporter(ds sqlutil.DataSource, chainContainer legacyevm.LegacyChainContainer) *prometheusReporter { - return &prometheusReporter{ - ds: ds, - chains: chainContainer, - backend: defaultBackend{}, +func (defaultBackend) SetUnconfirmedTransactions(evmChainID *big.Int, n int64) { + promUnconfirmedTransactions.WithLabelValues(evmChainID.String()).Set(float64(n)) +} + +func (defaultBackend) SetMaxUnconfirmedAge(evmChainID *big.Int, s float64) { + promMaxUnconfirmedAge.WithLabelValues(evmChainID.String()).Set(s) +} + +func (defaultBackend) SetMaxUnconfirmedBlocks(evmChainID *big.Int, n int64) { + promMaxUnconfirmedBlocks.WithLabelValues(evmChainID.String()).Set(float64(n)) +} + +func (defaultBackend) SetPipelineRunsQueued(n int) { + promPipelineTaskRunsQueued.Set(float64(n)) +} + +func (defaultBackend) SetPipelineTaskRunsQueued(n int) { + promPipelineRunsQueued.Set(float64(n)) +} + +func NewPromReporter(ds sqlutil.DataSource, chainContainer legacyevm.LegacyChainContainer, lggr logger.Logger, opts ...interface{}) *promReporter { + var backend PrometheusBackend = defaultBackend{} + period := 15 * time.Second + for _, opt := range opts { + switch v := opt.(type) { + case time.Duration: + period = v + case PrometheusBackend: + backend = v + } + } + + chStop := make(chan struct{}) + return &promReporter{ + ds: ds, + chains: chainContainer, + lggr: lggr.Named("PromReporter"), + backend: backend, + newHeads: mailbox.NewSingle[*evmtypes.Head](), + chStop: chStop, + reportPeriod: period, } } -func (pr *prometheusReporter) getTxm(evmChainID *big.Int) (txmgr.TxManager, error) { +// Start starts PromReporter. +func (pr *promReporter) Start(context.Context) error { + return pr.StartOnce("PromReporter", func() error { + pr.wgDone.Add(1) + go pr.eventLoop() + return nil + }) +} + +func (pr *promReporter) Close() error { + return pr.StopOnce("PromReporter", func() error { + close(pr.chStop) + pr.wgDone.Wait() + return nil + }) +} +func (pr *promReporter) Name() string { + return pr.lggr.Name() +} + +func (pr *promReporter) HealthReport() map[string]error { + return map[string]error{pr.Name(): pr.Healthy()} +} + +func (pr *promReporter) OnNewLongestChain(ctx context.Context, head *evmtypes.Head) { + pr.newHeads.Deliver(head) +} + +func (pr *promReporter) eventLoop() { + pr.lggr.Debug("Starting event loop") + defer pr.wgDone.Done() + ctx, cancel := pr.chStop.NewCtx() + defer cancel() + for { + select { + case <-pr.newHeads.Notify(): + head, exists := pr.newHeads.Retrieve() + if !exists { + continue + } + pr.reportHeadMetrics(ctx, head) + case <-time.After(pr.reportPeriod): + if err := errors.Wrap(pr.reportPipelineRunStats(ctx), "reportPipelineRunStats failed"); err != nil { + pr.lggr.Errorw("Error reporting prometheus metrics", "err", err) + } + + case <-pr.chStop: + return + } + } +} + +func (pr *promReporter) getTxm(evmChainID *big.Int) (txmgr.TxManager, error) { chain, err := pr.chains.Get(evmChainID.String()) if err != nil { return nil, fmt.Errorf("failed to get chain: %w", err) @@ -75,16 +175,20 @@ func (pr *prometheusReporter) getTxm(evmChainID *big.Int) (txmgr.TxManager, erro return chain.TxManager(), nil } -func (pr *prometheusReporter) ReportNewHead(ctx context.Context, head *evmtypes.Head) error { +func (pr *promReporter) reportHeadMetrics(ctx context.Context, head *evmtypes.Head) { evmChainID := head.EVMChainID.ToInt() - return multierr.Combine( + err := multierr.Combine( errors.Wrap(pr.reportPendingEthTxes(ctx, evmChainID), "reportPendingEthTxes failed"), errors.Wrap(pr.reportMaxUnconfirmedAge(ctx, evmChainID), "reportMaxUnconfirmedAge failed"), errors.Wrap(pr.reportMaxUnconfirmedBlocks(ctx, head), "reportMaxUnconfirmedBlocks failed"), ) + + if err != nil && ctx.Err() == nil { + pr.lggr.Errorw("Error reporting prometheus metrics", "err", err) + } } -func (pr *prometheusReporter) reportPendingEthTxes(ctx context.Context, evmChainID *big.Int) (err error) { +func (pr *promReporter) reportPendingEthTxes(ctx context.Context, evmChainID *big.Int) (err error) { txm, err := pr.getTxm(evmChainID) if err != nil { return fmt.Errorf("failed to get txm: %w", err) @@ -98,7 +202,7 @@ func (pr *prometheusReporter) reportPendingEthTxes(ctx context.Context, evmChain return nil } -func (pr *prometheusReporter) reportMaxUnconfirmedAge(ctx context.Context, evmChainID *big.Int) (err error) { +func (pr *promReporter) reportMaxUnconfirmedAge(ctx context.Context, evmChainID *big.Int) (err error) { txm, err := pr.getTxm(evmChainID) if err != nil { return fmt.Errorf("failed to get txm: %w", err) @@ -117,7 +221,7 @@ func (pr *prometheusReporter) reportMaxUnconfirmedAge(ctx context.Context, evmCh return nil } -func (pr *prometheusReporter) reportMaxUnconfirmedBlocks(ctx context.Context, head *evmtypes.Head) (err error) { +func (pr *promReporter) reportMaxUnconfirmedBlocks(ctx context.Context, head *evmtypes.Head) (err error) { txm, err := pr.getTxm(head.EVMChainID.ToInt()) if err != nil { return fmt.Errorf("failed to get txm: %w", err) @@ -136,11 +240,7 @@ func (pr *prometheusReporter) reportMaxUnconfirmedBlocks(ctx context.Context, he return nil } -func (pr *prometheusReporter) ReportPeriodic(ctx context.Context) error { - return errors.Wrap(pr.reportPipelineRunStats(ctx), "reportPipelineRunStats failed") -} - -func (pr *prometheusReporter) reportPipelineRunStats(ctx context.Context) (err error) { +func (pr *promReporter) reportPipelineRunStats(ctx context.Context) (err error) { rows, err := pr.ds.QueryContext(ctx, ` SELECT pipeline_run_id FROM pipeline_task_runs WHERE finished_at IS NULL `) @@ -171,23 +271,3 @@ SELECT pipeline_run_id FROM pipeline_task_runs WHERE finished_at IS NULL return nil } - -func (defaultBackend) SetUnconfirmedTransactions(evmChainID *big.Int, n int64) { - promUnconfirmedTransactions.WithLabelValues(evmChainID.String()).Set(float64(n)) -} - -func (defaultBackend) SetMaxUnconfirmedAge(evmChainID *big.Int, s float64) { - promMaxUnconfirmedAge.WithLabelValues(evmChainID.String()).Set(s) -} - -func (defaultBackend) SetMaxUnconfirmedBlocks(evmChainID *big.Int, n int64) { - promMaxUnconfirmedBlocks.WithLabelValues(evmChainID.String()).Set(float64(n)) -} - -func (defaultBackend) SetPipelineRunsQueued(n int) { - promPipelineTaskRunsQueued.Set(float64(n)) -} - -func (defaultBackend) SetPipelineTaskRunsQueued(n int) { - promPipelineRunsQueued.Set(float64(n)) -} diff --git a/core/services/headreporter/prometheus_reporter_test.go b/core/services/promreporter/prom_reporter_test.go similarity index 64% rename from core/services/headreporter/prometheus_reporter_test.go rename to core/services/promreporter/prom_reporter_test.go index 32d2c09d0e..b61fa25bdc 100644 --- a/core/services/headreporter/prometheus_reporter_test.go +++ b/core/services/promreporter/prom_reporter_test.go @@ -1,7 +1,8 @@ -package headreporter_test +package promreporter_test import ( "math/big" + "sync/atomic" "testing" "time" @@ -9,40 +10,90 @@ import ( "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" + "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" + evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" + ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" + "github.com/smartcontractkit/chainlink/v2/core/internal/mocks" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/headreporter" + "github.com/smartcontractkit/chainlink/v2/core/services/promreporter" ) -func Test_PrometheusReporter(t *testing.T) { +func newHead() evmtypes.Head { + return evmtypes.Head{Number: 42, EVMChainID: ubig.NewI(0)} +} + +func newLegacyChainContainer(t *testing.T, db *sqlx.DB) legacyevm.LegacyChainContainer { + config, dbConfig, evmConfig := txmgr.MakeTestConfigs(t) + keyStore := cltest.NewKeyStore(t, db).Eth() + ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + estimator, err := gas.NewEstimator(logger.TestLogger(t), ethClient, config, evmConfig.GasEstimator()) + require.NoError(t, err) + lggr := logger.TestLogger(t) + lpOpts := logpoller.Opts{ + PollPeriod: 100 * time.Millisecond, + FinalityDepth: 2, + BackfillBatchSize: 3, + RpcBatchSize: 2, + KeepFinalizedBlocksDepth: 1000, + } + ht := headtracker.NewSimulatedHeadTracker(ethClient, lpOpts.UseFinalityTag, lpOpts.FinalityDepth) + lp := logpoller.NewLogPoller(logpoller.NewORM(testutils.FixtureChainID, db, lggr), ethClient, lggr, ht, lpOpts) + + txm, err := txmgr.NewTxm( + db, + evmConfig, + evmConfig.GasEstimator(), + evmConfig.Transactions(), + nil, + dbConfig, + dbConfig.Listener(), + ethClient, + lggr, + lp, + keyStore, + estimator) + require.NoError(t, err) + + cfg := configtest.NewGeneralConfig(t, nil) + return cltest.NewLegacyChainsWithMockChainAndTxManager(t, ethClient, cfg, txm) +} + +func Test_PromReporter_OnNewLongestChain(t *testing.T) { t.Run("with nothing in the database", func(t *testing.T) { db := pgtest.NewSqlxDB(t) - backend := headreporter.NewMockPrometheusBackend(t) + backend := mocks.NewPrometheusBackend(t) + reporter := promreporter.NewPromReporter(db, newLegacyChainContainer(t, db), logger.TestLogger(t), backend, 10*time.Millisecond) + + var subscribeCalls atomic.Int32 + backend.On("SetUnconfirmedTransactions", big.NewInt(0), int64(0)).Return() backend.On("SetMaxUnconfirmedAge", big.NewInt(0), float64(0)).Return() backend.On("SetMaxUnconfirmedBlocks", big.NewInt(0), int64(0)).Return() + backend.On("SetPipelineTaskRunsQueued", 0).Return() + backend.On("SetPipelineRunsQueued", 0). + Run(func(args mock.Arguments) { + subscribeCalls.Add(1) + }). + Return() - reporter := headreporter.NewPrometheusReporter(db, newLegacyChainContainer(t, db)) - reporter.SetBackend(backend) + servicetest.Run(t, reporter) - head := headreporter.NewHead() - err := reporter.ReportNewHead(testutils.Context(t), &head) - require.NoError(t, err) + head := newHead() + reporter.OnNewLongestChain(testutils.Context(t), &head) - backend.On("SetPipelineTaskRunsQueued", 0).Return() - backend.On("SetPipelineRunsQueued", 0).Return() - err = reporter.ReportPeriodic(testutils.Context(t)) - require.NoError(t, err) + require.Eventually(t, func() bool { return subscribeCalls.Load() >= 1 }, 12*time.Second, 100*time.Millisecond) }) t.Run("with unconfirmed evm.txes", func(t *testing.T) { @@ -51,92 +102,61 @@ func Test_PrometheusReporter(t *testing.T) { ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.MustInsertRandomKey(t, ethKeyStore) - etx := cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 0, fromAddress) - cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 1, fromAddress) - cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 2, fromAddress) - require.NoError(t, txStore.UpdateTxAttemptBroadcastBeforeBlockNum(testutils.Context(t), etx.ID, 7)) + var subscribeCalls atomic.Int32 - backend := headreporter.NewMockPrometheusBackend(t) + backend := mocks.NewPrometheusBackend(t) backend.On("SetUnconfirmedTransactions", big.NewInt(0), int64(3)).Return() backend.On("SetMaxUnconfirmedAge", big.NewInt(0), mock.MatchedBy(func(s float64) bool { return s > 0 })).Return() backend.On("SetMaxUnconfirmedBlocks", big.NewInt(0), int64(35)).Return() + backend.On("SetPipelineTaskRunsQueued", 0).Return() + backend.On("SetPipelineRunsQueued", 0). + Run(func(args mock.Arguments) { + subscribeCalls.Add(1) + }). + Return() + reporter := promreporter.NewPromReporter(db, newLegacyChainContainer(t, db), logger.TestLogger(t), backend, 10*time.Millisecond) + servicetest.Run(t, reporter) - reporter := headreporter.NewPrometheusReporter(db, newLegacyChainContainer(t, db)) - reporter.SetBackend(backend) - - head := headreporter.NewHead() - err := reporter.ReportNewHead(testutils.Context(t), &head) - require.NoError(t, err) + etx := cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 0, fromAddress) + cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 1, fromAddress) + cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 2, fromAddress) + require.NoError(t, txStore.UpdateTxAttemptBroadcastBeforeBlockNum(testutils.Context(t), etx.ID, 7)) - backend.On("SetPipelineTaskRunsQueued", 0).Return() - backend.On("SetPipelineRunsQueued", 0).Return() + head := newHead() + reporter.OnNewLongestChain(testutils.Context(t), &head) - err = reporter.ReportPeriodic(testutils.Context(t)) - require.NoError(t, err) + require.Eventually(t, func() bool { return subscribeCalls.Load() >= 1 }, 12*time.Second, 100*time.Millisecond) }) t.Run("with unfinished pipeline task runs", func(t *testing.T) { db := pgtest.NewSqlxDB(t) pgtest.MustExec(t, db, `SET CONSTRAINTS pipeline_task_runs_pipeline_run_id_fkey DEFERRED`) + backend := mocks.NewPrometheusBackend(t) + reporter := promreporter.NewPromReporter(db, newLegacyChainContainer(t, db), logger.TestLogger(t), backend, 10*time.Millisecond) + cltest.MustInsertUnfinishedPipelineTaskRun(t, db, 1) cltest.MustInsertUnfinishedPipelineTaskRun(t, db, 1) cltest.MustInsertUnfinishedPipelineTaskRun(t, db, 2) - backend := headreporter.NewMockPrometheusBackend(t) + var subscribeCalls atomic.Int32 + backend.On("SetUnconfirmedTransactions", big.NewInt(0), int64(0)).Return() backend.On("SetMaxUnconfirmedAge", big.NewInt(0), float64(0)).Return() backend.On("SetMaxUnconfirmedBlocks", big.NewInt(0), int64(0)).Return() - - reporter := headreporter.NewPrometheusReporter(db, newLegacyChainContainer(t, db)) - reporter.SetBackend(backend) - - head := headreporter.NewHead() - err := reporter.ReportNewHead(testutils.Context(t), &head) - require.NoError(t, err) - backend.On("SetPipelineTaskRunsQueued", 3).Return() - backend.On("SetPipelineRunsQueued", 2).Return() - - err = reporter.ReportPeriodic(testutils.Context(t)) - require.NoError(t, err) - }) -} - -func newLegacyChainContainer(t *testing.T, db *sqlx.DB) legacyevm.LegacyChainContainer { - config, dbConfig, evmConfig := txmgr.MakeTestConfigs(t) - keyStore := cltest.NewKeyStore(t, db).Eth() - ethClient := evmtest.NewEthClientMockWithDefaultChain(t) - estimator, err := gas.NewEstimator(logger.TestLogger(t), ethClient, config, evmConfig.GasEstimator()) - require.NoError(t, err) - lggr := logger.TestLogger(t) - lpOpts := logpoller.Opts{ - PollPeriod: 100 * time.Millisecond, - FinalityDepth: 2, - BackfillBatchSize: 3, - RpcBatchSize: 2, - KeepFinalizedBlocksDepth: 1000, - } - ht := headtracker.NewSimulatedHeadTracker(ethClient, lpOpts.UseFinalityTag, lpOpts.FinalityDepth) - lp := logpoller.NewLogPoller(logpoller.NewORM(testutils.FixtureChainID, db, lggr), ethClient, lggr, ht, lpOpts) + backend.On("SetPipelineRunsQueued", 2). + Run(func(args mock.Arguments) { + subscribeCalls.Add(1) + }). + Return() + servicetest.Run(t, reporter) - txm, err := txmgr.NewTxm( - db, - evmConfig, - evmConfig.GasEstimator(), - evmConfig.Transactions(), - nil, - dbConfig, - dbConfig.Listener(), - ethClient, - lggr, - lp, - keyStore, - estimator) - require.NoError(t, err) + head := newHead() + reporter.OnNewLongestChain(testutils.Context(t), &head) - cfg := configtest.NewGeneralConfig(t, nil) - return cltest.NewLegacyChainsWithMockChainAndTxManager(t, ethClient, cfg, txm) + require.Eventually(t, func() bool { return subscribeCalls.Load() >= 1 }, 12*time.Second, 100*time.Millisecond) + }) } diff --git a/core/web/testdata/body/health.html b/core/web/testdata/body/health.html index 4e244a9fe7..2a1b222753 100644 --- a/core/web/testdata/body/health.html +++ b/core/web/testdata/body/health.html @@ -69,9 +69,6 @@ -
- HeadReporter -
JobSpawner
@@ -99,6 +96,9 @@ BridgeCache +
+ PromReporter +
TelemetryManager
diff --git a/core/web/testdata/body/health.json b/core/web/testdata/body/health.json index 224a3534c9..10415c0abd 100644 --- a/core/web/testdata/body/health.json +++ b/core/web/testdata/body/health.json @@ -99,15 +99,6 @@ "output": "" } }, - { - "type": "checks", - "id": "HeadReporter", - "attributes": { - "name": "HeadReporter", - "status": "passing", - "output": "" - } - }, { "type": "checks", "id": "JobSpawner", @@ -171,6 +162,15 @@ "output": "" } }, + { + "type": "checks", + "id": "PromReporter", + "attributes": { + "name": "PromReporter", + "status": "passing", + "output": "" + } + }, { "type": "checks", "id": "TelemetryManager", diff --git a/core/web/testdata/body/health.txt b/core/web/testdata/body/health.txt index 0fbac846a6..09c8cff6c2 100644 --- a/core/web/testdata/body/health.txt +++ b/core/web/testdata/body/health.txt @@ -10,7 +10,6 @@ ok EVM.0.Txm.BlockHistoryEstimator ok EVM.0.Txm.Broadcaster ok EVM.0.Txm.Confirmer ok EVM.0.Txm.WrappedEvmEstimator -ok HeadReporter ok JobSpawner ok Mailbox.Monitor ok Mercury.WSRPCPool @@ -18,4 +17,5 @@ ok Mercury.WSRPCPool.CacheSet ok PipelineORM ok PipelineRunner ok PipelineRunner.BridgeCache +ok PromReporter ok TelemetryManager diff --git a/integration-tests/go.mod b/integration-tests/go.mod index 38bce599a7..bb07aca3ae 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -37,7 +37,6 @@ require ( github.com/smartcontractkit/chainlink-common v0.2.2-0.20240723123524-e407ecd120b1 github.com/smartcontractkit/chainlink-testing-framework v1.34.5 github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240405215812-5a72bc9af239 - github.com/smartcontractkit/chainlink-testing-framework/seth v1.2.1 github.com/smartcontractkit/chainlink/integration-tests v0.0.0-00010101000000-000000000000 github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000 github.com/smartcontractkit/havoc/k8schaos v0.0.0-20240409145249-e78d20847e37 diff --git a/integration-tests/go.sum b/integration-tests/go.sum index 3f6009ae72..7e5179b252 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1413,8 +1413,6 @@ github.com/smartcontractkit/chainlink-testing-framework v1.34.5 h1:6itLSDW4NHDDN github.com/smartcontractkit/chainlink-testing-framework v1.34.5/go.mod h1:hRZEDh2+afO8MSZb9qYNscmWb+3mHZf01J5ACZuIdTQ= github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240405215812-5a72bc9af239 h1:Kk5OVlx/5g9q3Z3lhxytZS4/f8ds1MiNM8yaHgK3Oe8= github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240405215812-5a72bc9af239/go.mod h1:DC8sQMyTlI/44UCTL8QWFwb0bYNoXCfjwCv2hMivYZU= -github.com/smartcontractkit/chainlink-testing-framework/seth v1.2.1 h1:GRAAvtn2+jhO/8Z3lig10eQXVcV4VuOI4UgCyoPdJBg= -github.com/smartcontractkit/chainlink-testing-framework/seth v1.2.1/go.mod h1:afY3QmNgeR/VI1pRbGH8g3YXGy7C2RrFOwUzEFvL3L8= github.com/smartcontractkit/go-plugin v0.0.0-20240208201424-b3b91517de16 h1:TFe+FvzxClblt6qRfqEhUfa4kFQx5UobuoFGO2W4mMo= github.com/smartcontractkit/go-plugin v0.0.0-20240208201424-b3b91517de16/go.mod h1:lBS5MtSSBZk0SHc66KACcjjlU6WzEVP/8pwz68aMkCI= github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f h1:hgJif132UCdjo8u43i7iPN1/MFnu49hv7lFGFftCHKU= diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index 4806e99bdd..eef855ef03 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -16,8 +16,8 @@ require ( github.com/rs/zerolog v1.33.0 github.com/slack-go/slack v0.12.2 github.com/smartcontractkit/chainlink-automation v1.0.4 - github.com/smartcontractkit/chainlink-common v0.2.2-0.20240829145110-4a45c426fbe8 - github.com/smartcontractkit/chainlink-testing-framework v1.34.12 + github.com/smartcontractkit/chainlink-common v0.2.2-0.20240723123524-e407ecd120b1 + github.com/smartcontractkit/chainlink-testing-framework v1.34.5 github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20240214231432-4ad5eb95178c github.com/smartcontractkit/chainlink/v2 v2.9.0-beta0.0.20240216210048-da02459ddad8 github.com/smartcontractkit/libocr v0.0.0-20240717100443-f6226e09bee7 @@ -36,30 +36,13 @@ require ( cosmossdk.io/errors v1.0.1 // indirect cosmossdk.io/math v1.3.0 // indirect github.com/awalterschulze/gographviz v2.0.3+incompatible // indirect - github.com/aws/aws-sdk-go-v2 v1.30.4 // indirect - github.com/aws/aws-sdk-go-v2/config v1.27.28 // indirect - github.com/aws/aws-sdk-go-v2/credentials v1.17.28 // indirect - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.12 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.16 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.16 // indirect - github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.4 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.18 // indirect - github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.32.5 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.22.5 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.5 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.30.4 // indirect - github.com/aws/smithy-go v1.20.4 // indirect github.com/containerd/errdefs v0.1.0 // indirect - github.com/go-viper/mapstructure/v2 v2.1.0 // indirect github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240710121324-3ed288aa9b45 // indirect - github.com/smartcontractkit/chainlink-testing-framework/seth v1.2.1 // indirect - github.com/smartcontractkit/chainlink-testing-framework/wasp v0.4.10 // indirect github.com/testcontainers/testcontainers-go v0.28.0 // indirect k8s.io/apimachinery v0.31.0 // indirect ) diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index da5b0c3cdf..86712da168 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -203,38 +203,10 @@ github.com/aws/aws-sdk-go v1.23.20/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpi github.com/aws/aws-sdk-go v1.38.35/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= github.com/aws/aws-sdk-go v1.45.25 h1:c4fLlh5sLdK2DCRTY1z0hyuJZU4ygxX8m1FswL6/nF4= github.com/aws/aws-sdk-go v1.45.25/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= -github.com/aws/aws-sdk-go-v2 v1.30.4 h1:frhcagrVNrzmT95RJImMHgabt99vkXGslubDaDagTk8= -github.com/aws/aws-sdk-go-v2 v1.30.4/go.mod h1:CT+ZPWXbYrci8chcARI3OmI/qgd+f6WtuLOoaIA8PR0= -github.com/aws/aws-sdk-go-v2/config v1.27.28 h1:OTxWGW/91C61QlneCtnD62NLb4W616/NM1jA8LhJqbg= -github.com/aws/aws-sdk-go-v2/config v1.27.28/go.mod h1:uzVRVtJSU5EFv6Fu82AoVFKozJi2ZCY6WRCXj06rbvs= -github.com/aws/aws-sdk-go-v2/credentials v1.17.28 h1:m8+AHY/ND8CMHJnPoH7PJIRakWGa4gbfbxuY9TGTUXM= -github.com/aws/aws-sdk-go-v2/credentials v1.17.28/go.mod h1:6TF7dSc78ehD1SL6KpRIPKMA1GyyWflIkjqg+qmf4+c= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.12 h1:yjwoSyDZF8Jth+mUk5lSPJCkMC0lMy6FaCD51jm6ayE= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.12/go.mod h1:fuR57fAgMk7ot3WcNQfb6rSEn+SUffl7ri+aa8uKysI= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.16 h1:TNyt/+X43KJ9IJJMjKfa3bNTiZbUP7DeCxfbTROESwY= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.16/go.mod h1:2DwJF39FlNAUiX5pAc0UNeiz16lK2t7IaFcm0LFHEgc= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.16 h1:jYfy8UPmd+6kJW5YhY0L1/KftReOGxI/4NtVSTh9O/I= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.16/go.mod h1:7ZfEPZxkW42Afq4uQB8H2E2e6ebh6mXTueEpYzjCzcs= -github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 h1:VaRN3TlFdd6KxX1x3ILT5ynH6HvKgqdiXoTxAF4HQcQ= -github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1/go.mod h1:FbtygfRFze9usAadmnGJNc8KsP346kEe+y2/oyhGAGc= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.4 h1:KypMCbLPPHEmf9DgMGw51jMj77VfGPAN2Kv4cfhlfgI= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.4/go.mod h1:Vz1JQXliGcQktFTN/LN6uGppAIRoLBR2bMvIMP0gOjc= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.18 h1:tJ5RnkHCiSH0jyd6gROjlJtNwov0eGYNz8s8nFcR0jQ= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.18/go.mod h1:++NHzT+nAF7ZPrHPsA+ENvsXkOO8wEu+C6RXltAG4/c= -github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.32.5 h1:UDXu9dqpCZYonj7poM4kFISjzTdWI0v3WUusM+w+Gfc= -github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.32.5/go.mod h1:5NPkI3RsTOhwz1CuG7VVSgJCm3CINKkoIaUbUZWQ67w= -github.com/aws/aws-sdk-go-v2/service/sso v1.22.5 h1:zCsFCKvbj25i7p1u94imVoO447I/sFv8qq+lGJhRN0c= -github.com/aws/aws-sdk-go-v2/service/sso v1.22.5/go.mod h1:ZeDX1SnKsVlejeuz41GiajjZpRSWR7/42q/EyA/QEiM= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.5 h1:SKvPgvdvmiTWoi0GAJ7AsJfOz3ngVkD/ERbs5pUnHNI= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.5/go.mod h1:20sz31hv/WsPa3HhU3hfrIet2kxM4Pe0r20eBZ20Tac= -github.com/aws/aws-sdk-go-v2/service/sts v1.30.4 h1:iAckBT2OeEK/kBDyN/jDtpEExhjeeA/Im2q4X0rJZT8= -github.com/aws/aws-sdk-go-v2/service/sts v1.30.4/go.mod h1:vmSqFK+BVIwVpDAGZB3CoCXHzurt4qBE8lf+I/kRTh0= github.com/aws/constructs-go/constructs/v10 v10.1.255 h1:5hARfEmhBqHSTQf/C3QLA3sWOxO2Dfja0iA1W7ZcI7g= github.com/aws/constructs-go/constructs/v10 v10.1.255/go.mod h1:DCdBSjN04Ck2pajCacTD4RKFqSA7Utya8d62XreYctI= github.com/aws/jsii-runtime-go v1.75.0 h1:NhpUfyiL7/wsRuUekFsz8FFBCYLfPD/l61kKg9kL/a4= github.com/aws/jsii-runtime-go v1.75.0/go.mod h1:TKCyrtM0pygEPo4rDZzbMSDNCDNTSYSN6/mGyHI6O3I= -github.com/aws/smithy-go v1.20.4 h1:2HK1zBdPgRbjFOHlfeQZfpC4r72MOb9bZkiFwggKO+4= -github.com/aws/smithy-go v1.20.4/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg= github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk= github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg= github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df h1:GSoSVRLoBaFpOOds6QyY1L8AX7uoY+Ln3BHc22W40X0= @@ -624,8 +596,6 @@ github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1v github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= github.com/go-test/deep v1.0.4 h1:u2CU3YKy9I2pmu9pX0eq50wCgjfGIt539SqR7FbHiho= github.com/go-test/deep v1.0.4/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= -github.com/go-viper/mapstructure/v2 v2.1.0 h1:gHnMa2Y/pIxElCH2GlZZ1lZSsn6XMtufpGyP1XxdC/w= -github.com/go-viper/mapstructure/v2 v2.1.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/go-webauthn/webauthn v0.9.4 h1:YxvHSqgUyc5AK2pZbqkWWR55qKeDPhP8zLDr6lpIc2g= github.com/go-webauthn/webauthn v0.9.4/go.mod h1:LqupCtzSef38FcxzaklmOn7AykGKhAhr9xlRbdbgnTw= github.com/go-webauthn/x v0.1.5 h1:V2TCzDU2TGLd0kSZOXdrqDVV5JB9ILnKxA9S53CSBw0= @@ -1393,8 +1363,8 @@ github.com/smartcontractkit/chain-selectors v1.0.23 h1:D2Eaex4Cw/O7Lg3tX6WklOqnj github.com/smartcontractkit/chain-selectors v1.0.23/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/smartcontractkit/chainlink-automation v1.0.4 h1:iyW181JjKHLNMnDleI8umfIfVVlwC7+n5izbLSFgjw8= github.com/smartcontractkit/chainlink-automation v1.0.4/go.mod h1:u4NbPZKJ5XiayfKHD/v3z3iflQWqvtdhj13jVZXj/cM= -github.com/smartcontractkit/chainlink-common v0.2.2-0.20240829145110-4a45c426fbe8 h1:MOFuL1J4/rRcR0x09qSlOsKIiq4I7YzbZcQ421KqUZA= -github.com/smartcontractkit/chainlink-common v0.2.2-0.20240829145110-4a45c426fbe8/go.mod h1:TJSY2ETKiXLRPvGHNO7Dp1tlpFIPSCWwN3iIdrsadIE= +github.com/smartcontractkit/chainlink-common v0.2.2-0.20240723123524-e407ecd120b1 h1:pdEpjgbZ5w/Sd5lzg/XiuC5gVyrmSovOo+3nUD46SP8= +github.com/smartcontractkit/chainlink-common v0.2.2-0.20240723123524-e407ecd120b1/go.mod h1:Jg1sCTsbxg76YByI8ifpFby3FvVqISStHT8ypy9ocmY= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240710121324-3ed288aa9b45 h1:NBQLtqk8zsyY4qTJs+NElI3aDFTcAo83JHvqD04EvB0= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240710121324-3ed288aa9b45/go.mod h1:LV0h7QBQUpoC2UUi6TcUvcIFm1xjP/DtEcqV8+qeLUs= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240718160222-2dc0c8136bfa h1:g75H8oh2ws52s8BekwvGQ9XvBVu3E7WM1rfiA0PN0zk= @@ -1405,14 +1375,10 @@ github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240712132946-267a37c5ac6 github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240712132946-267a37c5ac6e/go.mod h1:hsFhop+SlQHKD+DEFjZrMJmbauT1A/wvtZIeeo4PxFU= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240709043547-03612098f799 h1:HyLTySm7BR+oNfZqDTkVJ25wnmcTtxBBD31UkFL+kEM= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240709043547-03612098f799/go.mod h1:UVFRacRkP7O7TQAzFmR52v5mUlxf+G1ovMlCQAB/cHU= -github.com/smartcontractkit/chainlink-testing-framework v1.34.12 h1:pI0ESAspOcEqQ1fm53+3o2laGNwP8wbQNAmrGp5Tw1A= -github.com/smartcontractkit/chainlink-testing-framework v1.34.12/go.mod h1:ekYJbRAxXcs/YgOjHsY9/tlvDvXzv3lxcZK2eFUZduc= +github.com/smartcontractkit/chainlink-testing-framework v1.34.5 h1:6itLSDW4NHDDNR+Y+Z8YDzxxCN9SjdKb6SmLCl0vTFM= +github.com/smartcontractkit/chainlink-testing-framework v1.34.5/go.mod h1:hRZEDh2+afO8MSZb9qYNscmWb+3mHZf01J5ACZuIdTQ= github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.1 h1:1/r1wQZ4TOFpZ13w94r7amdF096Z96RuEnkOmrz1BGE= github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.1/go.mod h1:DC8sQMyTlI/44UCTL8QWFwb0bYNoXCfjwCv2hMivYZU= -github.com/smartcontractkit/chainlink-testing-framework/seth v1.2.1 h1:GRAAvtn2+jhO/8Z3lig10eQXVcV4VuOI4UgCyoPdJBg= -github.com/smartcontractkit/chainlink-testing-framework/seth v1.2.1/go.mod h1:afY3QmNgeR/VI1pRbGH8g3YXGy7C2RrFOwUzEFvL3L8= -github.com/smartcontractkit/chainlink-testing-framework/wasp v0.4.10 h1:s7e9YPU/ECQ9xCyLc60ApFbf0blMjg9LWi31CAEjaZY= -github.com/smartcontractkit/chainlink-testing-framework/wasp v0.4.10/go.mod h1:E7x2ICsT8vzy0nL6wwBphoQMoNwOMl0L9voQpEl1FoM= github.com/smartcontractkit/go-plugin v0.0.0-20240208201424-b3b91517de16 h1:TFe+FvzxClblt6qRfqEhUfa4kFQx5UobuoFGO2W4mMo= github.com/smartcontractkit/go-plugin v0.0.0-20240208201424-b3b91517de16/go.mod h1:lBS5MtSSBZk0SHc66KACcjjlU6WzEVP/8pwz68aMkCI= github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f h1:hgJif132UCdjo8u43i7iPN1/MFnu49hv7lFGFftCHKU= diff --git a/testdata/scripts/health/default.txtar b/testdata/scripts/health/default.txtar index 777d3e5e12..1dbf6b8eb9 100644 --- a/testdata/scripts/health/default.txtar +++ b/testdata/scripts/health/default.txtar @@ -31,7 +31,6 @@ fj293fbBnlQ!f9vNs HTTPPort = $PORT -- out.txt -- -ok HeadReporter ok JobSpawner ok Mailbox.Monitor ok Mercury.WSRPCPool @@ -39,20 +38,12 @@ ok Mercury.WSRPCPool.CacheSet ok PipelineORM ok PipelineRunner ok PipelineRunner.BridgeCache +ok PromReporter ok TelemetryManager -- out.json -- { "data": [ - { - "type": "checks", - "id": "HeadReporter", - "attributes": { - "name": "HeadReporter", - "status": "passing", - "output": "" - } - }, { "type": "checks", "id": "JobSpawner", @@ -116,6 +107,15 @@ ok TelemetryManager "output": "" } }, + { + "type": "checks", + "id": "PromReporter", + "attributes": { + "name": "PromReporter", + "status": "passing", + "output": "" + } + }, { "type": "checks", "id": "TelemetryManager", diff --git a/testdata/scripts/health/multi-chain.txtar b/testdata/scripts/health/multi-chain.txtar index 3bd15850af..8178f8e821 100644 --- a/testdata/scripts/health/multi-chain.txtar +++ b/testdata/scripts/health/multi-chain.txtar @@ -75,7 +75,6 @@ ok EVM.1.Txm.BlockHistoryEstimator ok EVM.1.Txm.Broadcaster ok EVM.1.Txm.Confirmer ok EVM.1.Txm.WrappedEvmEstimator -ok HeadReporter ok JobSpawner ok Mailbox.Monitor ok Mercury.WSRPCPool @@ -83,6 +82,7 @@ ok Mercury.WSRPCPool.CacheSet ok PipelineORM ok PipelineRunner ok PipelineRunner.BridgeCache +ok PromReporter ok Solana.Bar ok StarkNet.Baz ok TelemetryManager @@ -216,15 +216,6 @@ ok TelemetryManager "output": "" } }, - { - "type": "checks", - "id": "HeadReporter", - "attributes": { - "name": "HeadReporter", - "status": "passing", - "output": "" - } - }, { "type": "checks", "id": "JobSpawner", @@ -288,6 +279,15 @@ ok TelemetryManager "output": "" } }, + { + "type": "checks", + "id": "PromReporter", + "attributes": { + "name": "PromReporter", + "status": "passing", + "output": "" + } + }, { "type": "checks", "id": "Solana.Bar", From a7f496c379a76e616e0bc9a3c2e62a1bf347d203 Mon Sep 17 00:00:00 2001 From: Rens Rooimans Date: Tue, 3 Sep 2024 08:52:32 +0200 Subject: [PATCH 064/115] Misc golfs and fixes (#1402) Co-authored-by: app-token-issuer-infra-releng[bot] <120227048+app-token-issuer-infra-releng[bot]@users.noreply.github.com> --- contracts/gas-snapshots/ccip.gas-snapshot | 276 +++++++++--------- contracts/src/v0.8/ccip/FeeQuoter.sol | 6 +- .../src/v0.8/ccip/capability/CCIPConfig.sol | 30 +- contracts/src/v0.8/ccip/ocr/MultiOCR3Base.sol | 15 +- contracts/src/v0.8/ccip/offRamp/OffRamp.sol | 17 +- contracts/src/v0.8/ccip/onRamp/OnRamp.sol | 11 +- .../ccip/generated/ccip_config/ccip_config.go | 2 +- .../ccip/generated/fee_quoter/fee_quoter.go | 2 +- .../multi_ocr3_helper/multi_ocr3_helper.go | 2 +- .../ccip/generated/offramp/offramp.go | 2 +- .../ccip/generated/onramp/onramp.go | 2 +- ...rapper-dependency-versions-do-not-edit.txt | 10 +- 12 files changed, 181 insertions(+), 194 deletions(-) diff --git a/contracts/gas-snapshots/ccip.gas-snapshot b/contracts/gas-snapshots/ccip.gas-snapshot index 1658bd8dcb..60e1c8bf98 100644 --- a/contracts/gas-snapshots/ccip.gas-snapshot +++ b/contracts/gas-snapshots/ccip.gas-snapshot @@ -37,61 +37,61 @@ BurnWithFromMintTokenPool_lockOrBurn:test_Setup_Success() (gas: 23951) CCIPClientExample_sanity:test_ImmutableExamples_Success() (gas: 2132684) CCIPConfigSetup:test_getCapabilityConfiguration_Success() (gas: 9517) CCIPConfig_ConfigStateMachine:test__computeConfigDigest_Success() (gas: 70831) -CCIPConfig_ConfigStateMachine:test__computeNewConfigWithMeta_InitToRunning_Success() (gas: 363664) -CCIPConfig_ConfigStateMachine:test__computeNewConfigWithMeta_RunningToStaging_Success() (gas: 488826) -CCIPConfig_ConfigStateMachine:test__computeNewConfigWithMeta_StagingToRunning_Success() (gas: 453439) +CCIPConfig_ConfigStateMachine:test__computeNewConfigWithMeta_InitToRunning_Success() (gas: 363544) +CCIPConfig_ConfigStateMachine:test__computeNewConfigWithMeta_RunningToStaging_Success() (gas: 488615) +CCIPConfig_ConfigStateMachine:test__computeNewConfigWithMeta_StagingToRunning_Success() (gas: 453319) CCIPConfig_ConfigStateMachine:test__groupByPluginType_TooManyOCR3Configs_Reverts() (gas: 37049) CCIPConfig_ConfigStateMachine:test__groupByPluginType_threeCommitConfigs_Reverts() (gas: 61065) CCIPConfig_ConfigStateMachine:test__groupByPluginType_threeExecutionConfigs_Reverts() (gas: 60985) CCIPConfig_ConfigStateMachine:test__stateFromConfigLength_Success() (gas: 11635) CCIPConfig_ConfigStateMachine:test__validateConfigStateTransition_Success() (gas: 8831) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_InitToRunning_Success() (gas: 312055) +CCIPConfig_ConfigStateMachine:test__validateConfigTransition_InitToRunning_Success() (gas: 312026) CCIPConfig_ConfigStateMachine:test__validateConfigTransition_InitToRunning_WrongConfigCount_Reverts() (gas: 49727) CCIPConfig_ConfigStateMachine:test__validateConfigTransition_NonExistentConfigTransition_Reverts() (gas: 32320) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_RunningToStaging_Success() (gas: 376678) +CCIPConfig_ConfigStateMachine:test__validateConfigTransition_RunningToStaging_Success() (gas: 376649) CCIPConfig_ConfigStateMachine:test__validateConfigTransition_RunningToStaging_WrongConfigCount_Reverts() (gas: 121045) CCIPConfig_ConfigStateMachine:test__validateConfigTransition_RunningToStaging_WrongConfigDigestBlueGreen_Reverts() (gas: 157245) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_StagingToRunning_Success() (gas: 376454) +CCIPConfig_ConfigStateMachine:test__validateConfigTransition_StagingToRunning_Success() (gas: 376425) CCIPConfig_ConfigStateMachine:test__validateConfigTransition_StagingToRunning_WrongConfigDigest_Reverts() (gas: 157312) CCIPConfig_ConfigStateMachine:test_getCapabilityConfiguration_Success() (gas: 9605) -CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_CommitAndExecConfig_Success() (gas: 1851094) -CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_CommitConfigOnly_Success() (gas: 1068315) -CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_ExecConfigOnly_Success() (gas: 1068346) +CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_CommitAndExecConfig_Success() (gas: 1850870) +CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_CommitConfigOnly_Success() (gas: 1068182) +CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_ExecConfigOnly_Success() (gas: 1068213) CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_OnlyCapabilitiesRegistryCanCall_Reverts() (gas: 9599) -CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_ZeroLengthConfig_Success() (gas: 16070) +CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_ZeroLengthConfig_Success() (gas: 16057) CCIPConfig_beforeCapabilityConfigSet:test_getCapabilityConfiguration_Success() (gas: 9605) -CCIPConfig_chainConfig:test__applyChainConfigUpdates_FChainNotPositive_Reverts() (gas: 184703) -CCIPConfig_chainConfig:test_applyChainConfigUpdates_addChainConfigs_Success() (gas: 344881) -CCIPConfig_chainConfig:test_applyChainConfigUpdates_nodeNotInRegistry_Reverts() (gas: 20258) -CCIPConfig_chainConfig:test_applyChainConfigUpdates_removeChainConfigs_Success() (gas: 267558) +CCIPConfig_chainConfig:test__applyChainConfigUpdates_FChainNotPositive_Reverts() (gas: 184727) +CCIPConfig_chainConfig:test_applyChainConfigUpdates_addChainConfigs_Success() (gas: 344895) +CCIPConfig_chainConfig:test_applyChainConfigUpdates_nodeNotInRegistry_Reverts() (gas: 20329) +CCIPConfig_chainConfig:test_applyChainConfigUpdates_removeChainConfigs_Success() (gas: 267569) CCIPConfig_chainConfig:test_applyChainConfigUpdates_selectorNotFound_Reverts() (gas: 14829) CCIPConfig_chainConfig:test_getCapabilityConfiguration_Success() (gas: 9626) -CCIPConfig_chainConfig:test_getPaginatedCCIPConfigs_Success() (gas: 370235) -CCIPConfig_constructor:test_constructor_Success() (gas: 3612901) -CCIPConfig_constructor:test_constructor_ZeroAddressNotAllowed_Revert() (gas: 61777) -CCIPConfig_updatePluginConfig:test__updatePluginConfig_InitToRunning_Success() (gas: 1057368) +CCIPConfig_chainConfig:test_getPaginatedCCIPConfigs_Success() (gas: 370249) +CCIPConfig_constructor:test_constructor_Success() (gas: 3602871) +CCIPConfig_constructor:test_constructor_ZeroAddressNotAllowed_Revert() (gas: 61769) +CCIPConfig_updatePluginConfig:test__updatePluginConfig_InitToRunning_Success() (gas: 1057248) CCIPConfig_updatePluginConfig:test__updatePluginConfig_InvalidConfigLength_Reverts() (gas: 27561) CCIPConfig_updatePluginConfig:test__updatePluginConfig_InvalidConfigStateTransition_Reverts() (gas: 23127) -CCIPConfig_updatePluginConfig:test__updatePluginConfig_RunningToStaging_Success() (gas: 2009285) -CCIPConfig_updatePluginConfig:test__updatePluginConfig_StagingToRunning_Success() (gas: 2616133) +CCIPConfig_updatePluginConfig:test__updatePluginConfig_RunningToStaging_Success() (gas: 2009044) +CCIPConfig_updatePluginConfig:test__updatePluginConfig_StagingToRunning_Success() (gas: 2615819) CCIPConfig_updatePluginConfig:test_getCapabilityConfiguration_Success() (gas: 9605) -CCIPConfig_validateConfig:test__validateConfig_BootstrapP2PIdsHasDuplicates_Reverts() (gas: 294893) -CCIPConfig_validateConfig:test__validateConfig_BootstrapP2PIdsNotASubsetOfP2PIds_Reverts() (gas: 298325) -CCIPConfig_validateConfig:test__validateConfig_BootstrapP2PIdsNotSorted_Reverts() (gas: 295038) -CCIPConfig_validateConfig:test__validateConfig_ChainSelectorNotFound_Reverts() (gas: 294357) -CCIPConfig_validateConfig:test__validateConfig_ChainSelectorNotSet_Reverts() (gas: 291431) -CCIPConfig_validateConfig:test__validateConfig_FMustBePositive_Reverts() (gas: 292396) -CCIPConfig_validateConfig:test__validateConfig_FTooHigh_Reverts() (gas: 292540) -CCIPConfig_validateConfig:test__validateConfig_NodeNotInRegistry_Reverts() (gas: 299420) -CCIPConfig_validateConfig:test__validateConfig_NotEnoughTransmitters_Reverts() (gas: 1160094) -CCIPConfig_validateConfig:test__validateConfig_OfframpAddressCannotBeZero_Reverts() (gas: 291260) -CCIPConfig_validateConfig:test__validateConfig_P2PIdsHasDuplicates_Reverts() (gas: 295907) -CCIPConfig_validateConfig:test__validateConfig_P2PIdsLengthNotMatching_Reverts() (gas: 293229) -CCIPConfig_validateConfig:test__validateConfig_P2PIdsNotSorted_Reverts() (gas: 295623) -CCIPConfig_validateConfig:test__validateConfig_Success() (gas: 302186) -CCIPConfig_validateConfig:test__validateConfig_TooManyBootstrapP2PIds_Reverts() (gas: 294539) -CCIPConfig_validateConfig:test__validateConfig_TooManySigners_Reverts() (gas: 1215861) -CCIPConfig_validateConfig:test__validateConfig_TooManyTransmitters_Reverts() (gas: 1214264) +CCIPConfig_validateConfig:test__validateConfig_BootstrapP2PIdsHasDuplicates_Reverts() (gas: 294864) +CCIPConfig_validateConfig:test__validateConfig_BootstrapP2PIdsNotASubsetOfP2PIds_Reverts() (gas: 298296) +CCIPConfig_validateConfig:test__validateConfig_BootstrapP2PIdsNotSorted_Reverts() (gas: 295009) +CCIPConfig_validateConfig:test__validateConfig_ChainSelectorNotFound_Reverts() (gas: 294328) +CCIPConfig_validateConfig:test__validateConfig_ChainSelectorNotSet_Reverts() (gas: 291402) +CCIPConfig_validateConfig:test__validateConfig_FMustBePositive_Reverts() (gas: 292367) +CCIPConfig_validateConfig:test__validateConfig_FTooHigh_Reverts() (gas: 292511) +CCIPConfig_validateConfig:test__validateConfig_NodeNotInRegistry_Reverts() (gas: 299453) +CCIPConfig_validateConfig:test__validateConfig_NotEnoughTransmitters_Reverts() (gas: 1159741) +CCIPConfig_validateConfig:test__validateConfig_OfframpAddressCannotBeZero_Reverts() (gas: 291231) +CCIPConfig_validateConfig:test__validateConfig_P2PIdsHasDuplicates_Reverts() (gas: 295878) +CCIPConfig_validateConfig:test__validateConfig_P2PIdsLengthNotMatching_Reverts() (gas: 293200) +CCIPConfig_validateConfig:test__validateConfig_P2PIdsNotSorted_Reverts() (gas: 295594) +CCIPConfig_validateConfig:test__validateConfig_Success() (gas: 302066) +CCIPConfig_validateConfig:test__validateConfig_TooManyBootstrapP2PIds_Reverts() (gas: 294510) +CCIPConfig_validateConfig:test__validateConfig_TooManySigners_Reverts() (gas: 1215496) +CCIPConfig_validateConfig:test__validateConfig_TooManyTransmitters_Reverts() (gas: 1213899) CCIPConfig_validateConfig:test_getCapabilityConfiguration_Success() (gas: 9584) CommitStore_constructor:test_Constructor_Success() (gas: 3091326) CommitStore_isUnpausedAndRMNHealthy:test_RMN_Success() (gas: 73420) @@ -347,7 +347,7 @@ FeeQuoter_applyTokenTransferFeeConfigUpdates:test_OnlyCallableByOwnerOrAdmin_Rev FeeQuoter_constructor:test_InvalidLinkTokenEqZeroAddress_Revert() (gas: 107046) FeeQuoter_constructor:test_InvalidMaxFeeJuelsPerMsg_Revert() (gas: 111396) FeeQuoter_constructor:test_InvalidStalenessThreshold_Revert() (gas: 111449) -FeeQuoter_constructor:test_Setup_Success() (gas: 5358690) +FeeQuoter_constructor:test_Setup_Success() (gas: 5355882) FeeQuoter_convertTokenAmount:test_ConvertTokenAmount_Success() (gas: 72739) FeeQuoter_convertTokenAmount:test_LinkTokenNotSupported_Revert() (gas: 30963) FeeQuoter_getDataAvailabilityCost:test_EmptyMessageCalculatesDataAvailabilityCost_Success() (gas: 94303) @@ -369,17 +369,17 @@ FeeQuoter_getTokenTransferCost:test_ZeroAmountTokenTransferChargesMinFeeAndGas_S FeeQuoter_getTokenTransferCost:test_ZeroFeeConfigChargesMinFee_Success() (gas: 40013) FeeQuoter_getTokenTransferCost:test_getTokenTransferCost_selfServeUsesDefaults_Success() (gas: 29299) FeeQuoter_getValidatedFee:test_DestinationChainNotEnabled_Revert() (gas: 18180) -FeeQuoter_getValidatedFee:test_EmptyMessage_Success() (gas: 85936) -FeeQuoter_getValidatedFee:test_EnforceOutOfOrder_Revert() (gas: 56735) -FeeQuoter_getValidatedFee:test_HighGasMessage_Success() (gas: 242354) +FeeQuoter_getValidatedFee:test_EmptyMessage_Success() (gas: 85916) +FeeQuoter_getValidatedFee:test_EnforceOutOfOrder_Revert() (gas: 54345) +FeeQuoter_getValidatedFee:test_HighGasMessage_Success() (gas: 242334) FeeQuoter_getValidatedFee:test_InvalidEVMAddress_Revert() (gas: 22390) -FeeQuoter_getValidatedFee:test_MessageGasLimitTooHigh_Revert() (gas: 34187) +FeeQuoter_getValidatedFee:test_MessageGasLimitTooHigh_Revert() (gas: 31797) FeeQuoter_getValidatedFee:test_MessageTooLarge_Revert() (gas: 100133) -FeeQuoter_getValidatedFee:test_MessageWithDataAndTokenTransfer_Success() (gas: 147715) +FeeQuoter_getValidatedFee:test_MessageWithDataAndTokenTransfer_Success() (gas: 147677) FeeQuoter_getValidatedFee:test_NotAFeeToken_Revert() (gas: 21043) -FeeQuoter_getValidatedFee:test_SingleTokenMessage_Success() (gas: 116743) +FeeQuoter_getValidatedFee:test_SingleTokenMessage_Success() (gas: 116705) FeeQuoter_getValidatedFee:test_TooManyTokens_Revert() (gas: 22526) -FeeQuoter_getValidatedFee:test_ZeroDataAvailabilityMultiplier_Success() (gas: 64374) +FeeQuoter_getValidatedFee:test_ZeroDataAvailabilityMultiplier_Success() (gas: 64364) FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Above18Decimals_Success() (gas: 2094539) FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Below18Decimals_Success() (gas: 2094497) FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt0Decimals_Success() (gas: 2074616) @@ -536,37 +536,37 @@ MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokens_Remov MultiAggregateRateLimiter_updateRateLimitTokens:test_ZeroDestToken_Revert() (gas: 18287) MultiAggregateRateLimiter_updateRateLimitTokens:test_ZeroSourceToken_Revert() (gas: 18216) MultiOCR3Base_setOCR3Configs:test_FMustBePositive_Revert() (gas: 59331) -MultiOCR3Base_setOCR3Configs:test_FTooHigh_Revert() (gas: 44298) -MultiOCR3Base_setOCR3Configs:test_RepeatSignerAddress_Revert() (gas: 283711) -MultiOCR3Base_setOCR3Configs:test_RepeatTransmitterAddress_Revert() (gas: 422848) -MultiOCR3Base_setOCR3Configs:test_SetConfigIgnoreSigners_Success() (gas: 511694) -MultiOCR3Base_setOCR3Configs:test_SetConfigWithSigners_Success() (gas: 829593) -MultiOCR3Base_setOCR3Configs:test_SetConfigWithoutSigners_Success() (gas: 457446) +MultiOCR3Base_setOCR3Configs:test_FTooHigh_Revert() (gas: 44289) +MultiOCR3Base_setOCR3Configs:test_RepeatSignerAddress_Revert() (gas: 283606) +MultiOCR3Base_setOCR3Configs:test_RepeatTransmitterAddress_Revert() (gas: 422233) +MultiOCR3Base_setOCR3Configs:test_SetConfigIgnoreSigners_Success() (gas: 511089) +MultiOCR3Base_setOCR3Configs:test_SetConfigWithSigners_Success() (gas: 828394) +MultiOCR3Base_setOCR3Configs:test_SetConfigWithoutSigners_Success() (gas: 456841) MultiOCR3Base_setOCR3Configs:test_SetConfigsZeroInput_Success() (gas: 12376) -MultiOCR3Base_setOCR3Configs:test_SetMultipleConfigs_Success() (gas: 2143220) -MultiOCR3Base_setOCR3Configs:test_SignerCannotBeZeroAddress_Revert() (gas: 141744) -MultiOCR3Base_setOCR3Configs:test_StaticConfigChange_Revert() (gas: 808478) -MultiOCR3Base_setOCR3Configs:test_TooManySigners_Revert() (gas: 171331) -MultiOCR3Base_setOCR3Configs:test_TooManyTransmitters_Revert() (gas: 30298) -MultiOCR3Base_setOCR3Configs:test_TransmitterCannotBeZeroAddress_Revert() (gas: 254454) -MultiOCR3Base_setOCR3Configs:test_UpdateConfigSigners_Success() (gas: 861521) -MultiOCR3Base_setOCR3Configs:test_UpdateConfigTransmittersWithoutSigners_Success() (gas: 475825) +MultiOCR3Base_setOCR3Configs:test_SetMultipleConfigs_Success() (gas: 2140127) +MultiOCR3Base_setOCR3Configs:test_SignerCannotBeZeroAddress_Revert() (gas: 141723) +MultiOCR3Base_setOCR3Configs:test_StaticConfigChange_Revert() (gas: 807279) +MultiOCR3Base_setOCR3Configs:test_TooManySigners_Revert() (gas: 171322) +MultiOCR3Base_setOCR3Configs:test_TooManyTransmitters_Revert() (gas: 30289) +MultiOCR3Base_setOCR3Configs:test_TransmitterCannotBeZeroAddress_Revert() (gas: 254091) +MultiOCR3Base_setOCR3Configs:test_UpdateConfigSigners_Success() (gas: 860006) +MultiOCR3Base_setOCR3Configs:test_UpdateConfigTransmittersWithoutSigners_Success() (gas: 475059) MultiOCR3Base_transmit:test_ConfigDigestMismatch_Revert() (gas: 42837) MultiOCR3Base_transmit:test_ForkedChain_Revert() (gas: 48442) MultiOCR3Base_transmit:test_InsufficientSignatures_Revert() (gas: 76930) -MultiOCR3Base_transmit:test_NonUniqueSignature_Revert() (gas: 66127) +MultiOCR3Base_transmit:test_NonUniqueSignature_Revert() (gas: 65770) MultiOCR3Base_transmit:test_SignatureOutOfRegistration_Revert() (gas: 33419) MultiOCR3Base_transmit:test_TooManySignatures_Revert() (gas: 79521) -MultiOCR3Base_transmit:test_TransmitSigners_gas_Success() (gas: 34020) +MultiOCR3Base_transmit:test_TransmitSigners_gas_Success() (gas: 33633) MultiOCR3Base_transmit:test_TransmitWithExtraCalldataArgs_Revert() (gas: 47114) MultiOCR3Base_transmit:test_TransmitWithLessCalldataArgs_Revert() (gas: 25682) MultiOCR3Base_transmit:test_TransmitWithoutSignatureVerification_gas_Success() (gas: 18714) MultiOCR3Base_transmit:test_UnAuthorizedTransmitter_Revert() (gas: 24191) -MultiOCR3Base_transmit:test_UnauthorizedSigner_Revert() (gas: 61409) +MultiOCR3Base_transmit:test_UnauthorizedSigner_Revert() (gas: 61133) MultiOCR3Base_transmit:test_UnconfiguredPlugin_Revert() (gas: 39890) MultiOCR3Base_transmit:test_ZeroSignatures_Revert() (gas: 32973) -MultiOnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 414301) -MultiRampsE2E:test_E2E_3MessagesMMultiOffRampSuccess_gas() (gas: 1501445) +MultiOnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 413542) +MultiRampsE2E:test_E2E_3MessagesMMultiOffRampSuccess_gas() (gas: 1499109) NonceManager_NonceIncrementation:test_getIncrementedOutboundNonce_Success() (gas: 37907) NonceManager_NonceIncrementation:test_incrementInboundNonce_Skip() (gas: 23694) NonceManager_NonceIncrementation:test_incrementInboundNonce_Success() (gas: 38763) @@ -578,10 +578,10 @@ NonceManager_OffRampUpgrade:test_UpgradedOffRampNonceSkipsIfMsgInFlight_Success( NonceManager_OffRampUpgrade:test_UpgradedSenderNoncesReadsPreviousRampTransitive_Success() (gas: 244814) NonceManager_OffRampUpgrade:test_UpgradedSenderNoncesReadsPreviousRamp_Success() (gas: 233069) NonceManager_OffRampUpgrade:test_Upgraded_Success() (gas: 153186) -NonceManager_OnRampUpgrade:test_UpgradeNonceNewSenderStartsAtZero_Success() (gas: 168681) -NonceManager_OnRampUpgrade:test_UpgradeNonceStartsAtV1Nonce_Success() (gas: 220836) +NonceManager_OnRampUpgrade:test_UpgradeNonceNewSenderStartsAtZero_Success() (gas: 168317) +NonceManager_OnRampUpgrade:test_UpgradeNonceStartsAtV1Nonce_Success() (gas: 220108) NonceManager_OnRampUpgrade:test_UpgradeSenderNoncesReadsPreviousRamp_Success() (gas: 125070) -NonceManager_OnRampUpgrade:test_Upgrade_Success() (gas: 107910) +NonceManager_OnRampUpgrade:test_Upgrade_Success() (gas: 107546) NonceManager_applyPreviousRampsUpdates:test_MultipleRampsUpdates() (gas: 122943) NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySetOffRamp_Revert() (gas: 42959) NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySetOnRampAndOffRamp_Revert() (gas: 64282) @@ -629,50 +629,50 @@ OffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChain_Success() (gas: OffRamp_applySourceChainConfigUpdates:test_RouterAddress_Revert() (gas: 13263) OffRamp_applySourceChainConfigUpdates:test_ZeroOnRampAddress_Revert() (gas: 17988) OffRamp_applySourceChainConfigUpdates:test_ZeroSourceChainSelector_Revert() (gas: 15300) -OffRamp_batchExecute:test_MultipleReportsDifferentChains_Success() (gas: 322171) -OffRamp_batchExecute:test_MultipleReportsSameChain_Success() (gas: 263506) +OffRamp_batchExecute:test_MultipleReportsDifferentChains_Success() (gas: 321369) +OffRamp_batchExecute:test_MultipleReportsSameChain_Success() (gas: 262704) OffRamp_batchExecute:test_MultipleReportsSkipDuplicate_Success() (gas: 169162) -OffRamp_batchExecute:test_OutOfBoundsGasLimitsAccess_Revert() (gas: 188589) +OffRamp_batchExecute:test_OutOfBoundsGasLimitsAccess_Revert() (gas: 187787) OffRamp_batchExecute:test_SingleReport_Success() (gas: 156230) -OffRamp_batchExecute:test_Unhealthy_Revert() (gas: 533834) +OffRamp_batchExecute:test_Unhealthy_Revert() (gas: 533030) OffRamp_batchExecute:test_ZeroReports_Revert() (gas: 10461) OffRamp_ccipReceive:test_Reverts() (gas: 15773) OffRamp_commit:test_InvalidIntervalMinLargerThanMax_Revert() (gas: 67458) OffRamp_commit:test_InvalidInterval_Revert() (gas: 59778) OffRamp_commit:test_InvalidRootRevert() (gas: 58858) -OffRamp_commit:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6560573) -OffRamp_commit:test_NoConfig_Revert() (gas: 6143711) -OffRamp_commit:test_OnlyGasPriceUpdates_Success() (gas: 106317) -OffRamp_commit:test_OnlyPriceUpdateStaleReport_Revert() (gas: 116369) -OffRamp_commit:test_OnlyTokenPriceUpdates_Success() (gas: 106338) -OffRamp_commit:test_PriceSequenceNumberCleared_Success() (gas: 351652) -OffRamp_commit:test_ReportAndPriceUpdate_Success() (gas: 159342) -OffRamp_commit:test_ReportOnlyRootSuccess_gas() (gas: 136480) -OffRamp_commit:test_RootAlreadyCommitted_Revert() (gas: 136880) +OffRamp_commit:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6536301) +OffRamp_commit:test_NoConfig_Revert() (gas: 6120044) +OffRamp_commit:test_OnlyGasPriceUpdates_Success() (gas: 105929) +OffRamp_commit:test_OnlyPriceUpdateStaleReport_Revert() (gas: 115981) +OffRamp_commit:test_OnlyTokenPriceUpdates_Success() (gas: 105950) +OffRamp_commit:test_PriceSequenceNumberCleared_Success() (gas: 349072) +OffRamp_commit:test_ReportAndPriceUpdate_Success() (gas: 158960) +OffRamp_commit:test_ReportOnlyRootSuccess_gas() (gas: 136092) +OffRamp_commit:test_RootAlreadyCommitted_Revert() (gas: 136492) OffRamp_commit:test_SourceChainNotEnabled_Revert() (gas: 59126) -OffRamp_commit:test_StaleReportWithRoot_Success() (gas: 225582) +OffRamp_commit:test_StaleReportWithRoot_Success() (gas: 224806) OffRamp_commit:test_UnauthorizedTransmitter_Revert() (gas: 117632) OffRamp_commit:test_Unhealthy_Revert() (gas: 77674) -OffRamp_commit:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 205066) -OffRamp_commit:test_WrongConfigWithoutSigners_Revert() (gas: 6554962) +OffRamp_commit:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 204296) +OffRamp_commit:test_WrongConfigWithoutSigners_Revert() (gas: 6530690) OffRamp_commit:test_ZeroEpochAndRound_Revert() (gas: 47832) -OffRamp_constructor:test_Constructor_Success() (gas: 6147616) -OffRamp_constructor:test_SourceChainSelector_Revert() (gas: 137128) -OffRamp_constructor:test_ZeroChainSelector_Revert() (gas: 103845) -OffRamp_constructor:test_ZeroNonceManager_Revert() (gas: 101716) -OffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 139680) -OffRamp_constructor:test_ZeroRMNProxy_Revert() (gas: 101593) -OffRamp_constructor:test_ZeroTokenAdminRegistry_Revert() (gas: 101660) +OffRamp_constructor:test_Constructor_Success() (gas: 6123343) +OffRamp_constructor:test_SourceChainSelector_Revert() (gas: 137089) +OffRamp_constructor:test_ZeroChainSelector_Revert() (gas: 103806) +OffRamp_constructor:test_ZeroNonceManager_Revert() (gas: 101677) +OffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 139641) +OffRamp_constructor:test_ZeroRMNProxy_Revert() (gas: 101554) +OffRamp_constructor:test_ZeroTokenAdminRegistry_Revert() (gas: 101621) OffRamp_execute:test_IncorrectArrayType_Revert() (gas: 17305) -OffRamp_execute:test_LargeBatch_Success() (gas: 1828972) -OffRamp_execute:test_MultipleReportsWithPartialValidationFailures_Success() (gas: 358063) -OffRamp_execute:test_MultipleReports_Success() (gas: 285617) -OffRamp_execute:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6611685) -OffRamp_execute:test_NoConfig_Revert() (gas: 6194563) +OffRamp_execute:test_LargeBatch_Success() (gas: 1812704) +OffRamp_execute:test_MultipleReportsWithPartialValidationFailures_Success() (gas: 357260) +OffRamp_execute:test_MultipleReports_Success() (gas: 284815) +OffRamp_execute:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6587413) +OffRamp_execute:test_NoConfig_Revert() (gas: 6170896) OffRamp_execute:test_NonArray_Revert() (gas: 27809) OffRamp_execute:test_SingleReport_Success() (gas: 175620) OffRamp_execute:test_UnauthorizedTransmitter_Revert() (gas: 147848) -OffRamp_execute:test_WrongConfigWithSigners_Revert() (gas: 6973803) +OffRamp_execute:test_WrongConfigWithSigners_Revert() (gas: 6948937) OffRamp_execute:test_ZeroReports_Revert() (gas: 17225) OffRamp_executeSingleMessage:test_MessageSender_Revert() (gas: 18257) OffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 249037) @@ -685,11 +685,11 @@ OffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidation_Rev OffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens_Success() (gas: 280859) OffRamp_executeSingleMessage:test_executeSingleMessage_WithValidation_Success() (gas: 92437) OffRamp_executeSingleReport:test_DisabledSourceChain_Revert() (gas: 35104) -OffRamp_executeSingleReport:test_EmptyReport_Revert() (gas: 23923) -OffRamp_executeSingleReport:test_InvalidSourcePoolAddress_Success() (gas: 492333) +OffRamp_executeSingleReport:test_EmptyReport_Revert() (gas: 28724) +OffRamp_executeSingleReport:test_InvalidSourcePoolAddress_Success() (gas: 491530) OffRamp_executeSingleReport:test_ManualExecutionNotYetEnabled_Revert() (gas: 54457) -OffRamp_executeSingleReport:test_MismatchingDestChainSelector_Revert() (gas: 35927) -OffRamp_executeSingleReport:test_MismatchingOnRampRoot_Revert() (gas: 154493) +OffRamp_executeSingleReport:test_MismatchingDestChainSelector_Revert() (gas: 40728) +OffRamp_executeSingleReport:test_MismatchingOnRampRoot_Revert() (gas: 154111) OffRamp_executeSingleReport:test_NonExistingSourceChain_Revert() (gas: 35338) OffRamp_executeSingleReport:test_ReceiverError_Success() (gas: 187911) OffRamp_executeSingleReport:test_RetryFailedMessageWithoutManualExecution_Revert() (gas: 199215) @@ -700,15 +700,15 @@ OffRamp_executeSingleReport:test_SingleMessageNoTokensUnordered_Success() (gas: OffRamp_executeSingleReport:test_SingleMessageNoTokens_Success() (gas: 212938) OffRamp_executeSingleReport:test_SingleMessageToNonCCIPReceiver_Success() (gas: 266576) OffRamp_executeSingleReport:test_SingleMessagesNoTokensSuccess_gas() (gas: 141191) -OffRamp_executeSingleReport:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 423378) +OffRamp_executeSingleReport:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 422575) OffRamp_executeSingleReport:test_SkippedIncorrectNonce_Success() (gas: 65877) OffRamp_executeSingleReport:test_TokenDataMismatch_Revert() (gas: 80932) -OffRamp_executeSingleReport:test_TwoMessagesWithTokensAndGE_Success() (gas: 587410) -OffRamp_executeSingleReport:test_TwoMessagesWithTokensSuccess_gas() (gas: 535220) -OffRamp_executeSingleReport:test_UnexpectedTokenData_Revert() (gas: 35743) -OffRamp_executeSingleReport:test_UnhealthySingleChainCurse_Revert() (gas: 532474) -OffRamp_executeSingleReport:test_Unhealthy_Revert() (gas: 529798) -OffRamp_executeSingleReport:test_WithCurseOnAnotherSourceChain_Success() (gas: 495040) +OffRamp_executeSingleReport:test_TwoMessagesWithTokensAndGE_Success() (gas: 586607) +OffRamp_executeSingleReport:test_TwoMessagesWithTokensSuccess_gas() (gas: 534417) +OffRamp_executeSingleReport:test_UnexpectedTokenData_Revert() (gas: 40544) +OffRamp_executeSingleReport:test_UnhealthySingleChainCurse_Revert() (gas: 531671) +OffRamp_executeSingleReport:test_Unhealthy_Revert() (gas: 528995) +OffRamp_executeSingleReport:test_WithCurseOnAnotherSourceChain_Success() (gas: 494237) OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessageUnordered_Success() (gas: 136580) OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessage_Success() (gas: 165799) OffRamp_getExecutionState:test_FillExecutionState_Success() (gas: 3742124) @@ -724,8 +724,8 @@ OffRamp_manuallyExecute:test_manuallyExecute_LowGasLimit_Success() (gas: 524603) OffRamp_manuallyExecute:test_manuallyExecute_ReentrancyFails_Success() (gas: 2388943) OffRamp_manuallyExecute:test_manuallyExecute_Success() (gas: 208553) OffRamp_manuallyExecute:test_manuallyExecute_WithGasOverride_Success() (gas: 219343) -OffRamp_manuallyExecute:test_manuallyExecute_WithMultiReportGasOverride_Success() (gas: 663643) -OffRamp_manuallyExecute:test_manuallyExecute_WithPartialMessages_Success() (gas: 330148) +OffRamp_manuallyExecute:test_manuallyExecute_WithMultiReportGasOverride_Success() (gas: 658822) +OffRamp_manuallyExecute:test_manuallyExecute_WithPartialMessages_Success() (gas: 328543) OffRamp_releaseOrMintTokens:test_TokenHandlingError_Reverts() (gas: 165822) OffRamp_releaseOrMintTokens:test__releaseOrMintTokens_PoolIsNotAPool_Reverts() (gas: 24603) OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_InvalidDataLengthReturnData_Revert() (gas: 66285) @@ -734,7 +734,7 @@ OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_PoolDoesNotSupportDest_Reve OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_Success() (gas: 177934) OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals_Success() (gas: 191136) OffRamp_resetUnblessedRoots:test_OnlyOwner_Revert() (gas: 11423) -OffRamp_resetUnblessedRoots:test_ResetUnblessedRoots_Success() (gas: 215373) +OffRamp_resetUnblessedRoots:test_ResetUnblessedRoots_Success() (gas: 215009) OffRamp_setDynamicConfig:test_FeeQuoterZeroAddress_Revert() (gas: 11585) OffRamp_setDynamicConfig:test_NonOwner_Revert() (gas: 14152) OffRamp_setDynamicConfig:test_SetDynamicConfigWithValidator_Success() (gas: 49115) @@ -743,48 +743,48 @@ OffRamp_trialExecute:test_RateLimitError_Success() (gas: 225795) OffRamp_trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 234416) OffRamp_trialExecute:test_TokenPoolIsNotAContract_Success() (gas: 309206) OffRamp_trialExecute:test_trialExecute_Success() (gas: 283994) -OffRamp_verify:test_Blessed_Success() (gas: 176664) -OffRamp_verify:test_NotBlessedWrongChainSelector_Success() (gas: 178754) -OffRamp_verify:test_NotBlessed_Success() (gas: 141593) +OffRamp_verify:test_Blessed_Success() (gas: 176276) +OffRamp_verify:test_NotBlessedWrongChainSelector_Success() (gas: 178366) +OffRamp_verify:test_NotBlessed_Success() (gas: 141205) OffRamp_verify:test_TooManyLeaves_Revert() (gas: 51510) OnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 390336) OnRamp_allowListConfigUpdates:test_applyAllowList_Revert() (gas: 66509) OnRamp_allowListConfigUpdates:test_applyAllowList_Success() (gas: 323566) OnRamp_applyDestChainConfigUpdates:test_ApplyDestChainConfigUpdates_Success() (gas: 64501) OnRamp_applyDestChainConfigUpdates:test_ApplyDestChainConfigUpdates_WithInvalidChainSelector_Revert() (gas: 13242) -OnRamp_constructor:test_Constructor_InvalidConfigChainSelectorEqZero_Revert() (gas: 94878) -OnRamp_constructor:test_Constructor_InvalidConfigNonceManagerEqAddressZero_Revert() (gas: 92812) -OnRamp_constructor:test_Constructor_InvalidConfigRMNProxyEqAddressZero_Revert() (gas: 97827) -OnRamp_constructor:test_Constructor_InvalidConfigTokenAdminRegistryEqAddressZero_Revert() (gas: 92870) -OnRamp_constructor:test_Constructor_Success() (gas: 2866937) -OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() (gas: 115250) -OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2_Success() (gas: 146019) -OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessCustomExtraArgs() (gas: 145615) -OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessEmptyExtraArgs() (gas: 143816) -OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessLegacyExtraArgs() (gas: 145847) -OnRamp_forwardFromRouter:test_ForwardFromRouter_Success() (gas: 145216) -OnRamp_forwardFromRouter:test_ForwardFromRouter_Success_ConfigurableSourceRouter() (gas: 140359) +OnRamp_constructor:test_Constructor_InvalidConfigChainSelectorEqZero_Revert() (gas: 94862) +OnRamp_constructor:test_Constructor_InvalidConfigNonceManagerEqAddressZero_Revert() (gas: 92796) +OnRamp_constructor:test_Constructor_InvalidConfigRMNProxyEqAddressZero_Revert() (gas: 97811) +OnRamp_constructor:test_Constructor_InvalidConfigTokenAdminRegistryEqAddressZero_Revert() (gas: 92854) +OnRamp_constructor:test_Constructor_Success() (gas: 2852106) +OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() (gas: 114880) +OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2_Success() (gas: 145648) +OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessCustomExtraArgs() (gas: 145251) +OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessEmptyExtraArgs() (gas: 143464) +OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessLegacyExtraArgs() (gas: 145476) +OnRamp_forwardFromRouter:test_ForwardFromRouter_Success() (gas: 144852) +OnRamp_forwardFromRouter:test_ForwardFromRouter_Success_ConfigurableSourceRouter() (gas: 139995) OnRamp_forwardFromRouter:test_InvalidExtraArgsTag_Revert() (gas: 28810) OnRamp_forwardFromRouter:test_MessageValidationError_Revert() (gas: 138683) OnRamp_forwardFromRouter:test_MesssageFeeTooHigh_Revert() (gas: 26910) -OnRamp_forwardFromRouter:test_MultiCannotSendZeroTokens_Revert() (gas: 74456) +OnRamp_forwardFromRouter:test_MultiCannotSendZeroTokens_Revert() (gas: 74122) OnRamp_forwardFromRouter:test_OriginalSender_Revert() (gas: 12918) OnRamp_forwardFromRouter:test_Paused_Revert() (gas: 37224) OnRamp_forwardFromRouter:test_Permissions_Revert() (gas: 18179) -OnRamp_forwardFromRouter:test_ShouldIncrementNonceOnlyOnOrdered_Success() (gas: 185252) -OnRamp_forwardFromRouter:test_ShouldIncrementSeqNumAndNonce_Success() (gas: 211543) -OnRamp_forwardFromRouter:test_ShouldStoreLinkFees() (gas: 125128) -OnRamp_forwardFromRouter:test_ShouldStoreNonLinkFees() (gas: 146530) -OnRamp_forwardFromRouter:test_SourceTokenDataTooLarge_Revert() (gas: 3894232) +OnRamp_forwardFromRouter:test_ShouldIncrementNonceOnlyOnOrdered_Success() (gas: 184142) +OnRamp_forwardFromRouter:test_ShouldIncrementSeqNumAndNonce_Success() (gas: 210451) +OnRamp_forwardFromRouter:test_ShouldStoreLinkFees() (gas: 124764) +OnRamp_forwardFromRouter:test_ShouldStoreNonLinkFees() (gas: 146166) +OnRamp_forwardFromRouter:test_SourceTokenDataTooLarge_Revert() (gas: 3892469) OnRamp_forwardFromRouter:test_UnAllowedOriginalSender_Revert() (gas: 18609) -OnRamp_forwardFromRouter:test_UnsupportedToken_Revert() (gas: 111118) -OnRamp_forwardFromRouter:test_forwardFromRouter_UnsupportedToken_Revert() (gas: 76545) -OnRamp_forwardFromRouter:test_forwardFromRouter_WithValidation_Success() (gas: 281240) -OnRamp_getFee:test_EmptyMessage_Success() (gas: 110107) -OnRamp_getFee:test_EnforceOutOfOrder_Revert() (gas: 75610) -OnRamp_getFee:test_GetFeeOfZeroForTokenMessage_Success() (gas: 95456) +OnRamp_forwardFromRouter:test_UnsupportedToken_Revert() (gas: 110785) +OnRamp_forwardFromRouter:test_forwardFromRouter_UnsupportedToken_Revert() (gas: 76212) +OnRamp_forwardFromRouter:test_forwardFromRouter_WithValidation_Success() (gas: 280875) +OnRamp_getFee:test_EmptyMessage_Success() (gas: 110067) +OnRamp_getFee:test_EnforceOutOfOrder_Revert() (gas: 73220) +OnRamp_getFee:test_GetFeeOfZeroForTokenMessage_Success() (gas: 95436) OnRamp_getFee:test_NotAFeeTokenButPricedToken_Revert() (gas: 41814) -OnRamp_getFee:test_SingleTokenMessage_Success() (gas: 125476) +OnRamp_getFee:test_SingleTokenMessage_Success() (gas: 125400) OnRamp_getFee:test_Unhealthy_Revert() (gas: 43669) OnRamp_getSupportedTokens:test_GetSupportedTokens_Revert() (gas: 10438) OnRamp_getTokenPool:test_GetTokenPool_Success() (gas: 35204) diff --git a/contracts/src/v0.8/ccip/FeeQuoter.sol b/contracts/src/v0.8/ccip/FeeQuoter.sol index 970485e90f..957d146f45 100644 --- a/contracts/src/v0.8/ccip/FeeQuoter.sol +++ b/contracts/src/v0.8/ccip/FeeQuoter.sol @@ -467,8 +467,6 @@ contract FeeQuoter is AuthorizedCallers, IFeeQuoter, ITypeAndVersion, IReceiver, uint256 numberOfTokens = message.tokenAmounts.length; _validateMessage(destChainConfig, message.data.length, numberOfTokens, message.receiver); - uint64 premiumMultiplierWeiPerEth = s_premiumMultiplierWeiPerEth[message.feeToken]; - // The below call asserts that feeToken is a supported token (uint224 feeTokenPrice, uint224 packedGasPrice) = getTokenAndGasPrices(message.feeToken, destChainSelector); @@ -511,7 +509,6 @@ contract FeeQuoter is AuthorizedCallers, IFeeQuoter, ITypeAndVersion, IReceiver, // NOTE: when supporting non-EVM chains, revisit how generic this fee logic can be // NOTE: revisit parsing non-EVM args - uint256 executionCost = uint112(packedGasPrice) * ( destChainConfig.destGasOverhead + (message.data.length * destChainConfig.destGasPerPayloadByte) + tokenTransferGas @@ -521,7 +518,8 @@ contract FeeQuoter is AuthorizedCallers, IFeeQuoter, ITypeAndVersion, IReceiver, // Calculate number of fee tokens to charge. // Total USD fee is in 36 decimals, feeTokenPrice is in 18 decimals USD for 1e18 smallest token denominations. // Result of the division is the number of smallest token denominations. - return ((premiumFee * premiumMultiplierWeiPerEth) + executionCost + dataAvailabilityCost) / feeTokenPrice; + return ((premiumFee * s_premiumMultiplierWeiPerEth[message.feeToken]) + executionCost + dataAvailabilityCost) + / feeTokenPrice; } /// @notice Sets the fee configuration for a token. diff --git a/contracts/src/v0.8/ccip/capability/CCIPConfig.sol b/contracts/src/v0.8/ccip/capability/CCIPConfig.sol index ae1e4cc597..822b36fe8b 100644 --- a/contracts/src/v0.8/ccip/capability/CCIPConfig.sol +++ b/contracts/src/v0.8/ccip/capability/CCIPConfig.sol @@ -6,7 +6,6 @@ import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; import {ICapabilitiesRegistry} from "./interfaces/ICapabilitiesRegistry.sol"; import {OwnerIsCreator} from "../../shared/access/OwnerIsCreator.sol"; - import {SortedSetValidationUtil} from "../../shared/util/SortedSetValidationUtil.sol"; import {Internal} from "../libraries/Internal.sol"; import {CCIPConfigTypes} from "./libraries/CCIPConfigTypes.sol"; @@ -26,7 +25,6 @@ contract CCIPConfig is ITypeAndVersion, ICapabilityConfiguration, OwnerIsCreator /// @param chainSelector The chain selector. /// @param chainConfig The chain configuration. event ChainConfigSet(uint64 chainSelector, CCIPConfigTypes.ChainConfig chainConfig); - /// @notice Emitted when a chain's configuration is removed. /// @param chainSelector The chain selector. event ChainConfigRemoved(uint64 chainSelector); @@ -172,9 +170,8 @@ contract CCIPConfig is ITypeAndVersion, ICapabilityConfiguration, OwnerIsCreator revert OnlyCapabilitiesRegistryCanCall(); } - CCIPConfigTypes.OCR3Config[] memory ocr3Configs = abi.decode(config, (CCIPConfigTypes.OCR3Config[])); (CCIPConfigTypes.OCR3Config[] memory commitConfigs, CCIPConfigTypes.OCR3Config[] memory execConfigs) = - _groupByPluginType(ocr3Configs); + _groupByPluginType(abi.decode(config, (CCIPConfigTypes.OCR3Config[]))); if (commitConfigs.length > 0) { _updatePluginConfig(donId, Internal.OCRPluginType.Commit, commitConfigs); } @@ -363,8 +360,8 @@ contract CCIPConfig is ITypeAndVersion, ICapabilityConfiguration, OwnerIsCreator // access in the for loop below. commitConfigs = new CCIPConfigTypes.OCR3Config[](MAX_OCR3_CONFIGS_PER_PLUGIN); execConfigs = new CCIPConfigTypes.OCR3Config[](MAX_OCR3_CONFIGS_PER_PLUGIN); - uint256 commitCount; - uint256 execCount; + uint256 commitCount = 0; + uint256 execCount = 0; for (uint256 i = 0; i < ocr3Configs.length; ++i) { if (ocr3Configs[i].pluginType == Internal.OCRPluginType.Commit) { commitConfigs[commitCount] = ocr3Configs[i]; @@ -418,9 +415,7 @@ contract CCIPConfig is ITypeAndVersion, ICapabilityConfiguration, OwnerIsCreator SortedSetValidationUtil._checkIsValidUniqueSubset(cfg.bootstrapP2PIds, cfg.p2pIds); // Check that the readers are in the capabilities registry. - for (uint256 i = 0; i < cfg.signers.length; ++i) { - _ensureInRegistry(cfg.p2pIds[i]); - } + _ensureInRegistry(cfg.p2pIds); } /// @notice Computes the digest of the provided configuration. @@ -486,13 +481,10 @@ contract CCIPConfig is ITypeAndVersion, ICapabilityConfiguration, OwnerIsCreator // Process additions next. for (uint256 i = 0; i < chainConfigAdds.length; ++i) { CCIPConfigTypes.ChainConfig memory chainConfig = chainConfigAdds[i].chainConfig; - bytes32[] memory readers = chainConfig.readers; uint64 chainSelector = chainConfigAdds[i].chainSelector; // Verify that the provided readers are present in the capabilities registry. - for (uint256 j = 0; j < readers.length; j++) { - _ensureInRegistry(readers[j]); - } + _ensureInRegistry(chainConfig.readers); // Verify that fChain is positive. if (chainConfig.fChain == 0) { @@ -507,11 +499,13 @@ contract CCIPConfig is ITypeAndVersion, ICapabilityConfiguration, OwnerIsCreator } /// @notice Helper function to ensure that a node is in the capabilities registry. - /// @param p2pId The P2P ID of the node to check. - function _ensureInRegistry(bytes32 p2pId) internal view { - ICapabilitiesRegistry.NodeInfo memory node = ICapabilitiesRegistry(i_capabilitiesRegistry).getNode(p2pId); - if (node.p2pId == bytes32("")) { - revert NodeNotInRegistry(p2pId); + /// @param p2pIds The P2P IDs of the node to check. + function _ensureInRegistry(bytes32[] memory p2pIds) internal view { + for (uint256 i = 0; i < p2pIds.length; ++i) { + // TODO add a method that does the validation in the ICapabilitiesRegistry contract + if (ICapabilitiesRegistry(i_capabilitiesRegistry).getNode(p2pIds[i]).p2pId == bytes32("")) { + revert NodeNotInRegistry(p2pIds[i]); + } } } } diff --git a/contracts/src/v0.8/ccip/ocr/MultiOCR3Base.sol b/contracts/src/v0.8/ccip/ocr/MultiOCR3Base.sol index 0b90f88c11..0759127097 100644 --- a/contracts/src/v0.8/ccip/ocr/MultiOCR3Base.sol +++ b/contracts/src/v0.8/ccip/ocr/MultiOCR3Base.sol @@ -146,10 +146,7 @@ abstract contract MultiOCR3Base is ITypeAndVersion, OwnerIsCreator { } address[] memory transmitters = ocrConfigArgs.transmitters; - // Transmitters are expected to never exceed 255 (since this is bounded by MAX_NUM_ORACLES) - uint8 newTransmittersLength = uint8(transmitters.length); - - if (newTransmittersLength > MAX_NUM_ORACLES) revert InvalidConfig(InvalidConfigErrorType.TOO_MANY_TRANSMITTERS); + if (transmitters.length > MAX_NUM_ORACLES) revert InvalidConfig(InvalidConfigErrorType.TOO_MANY_TRANSMITTERS); _clearOracleRoles(ocrPluginType, ocrConfig.transmitters); @@ -198,13 +195,13 @@ abstract contract MultiOCR3Base is ITypeAndVersion, OwnerIsCreator { /// @param oracleAddresses Oracle addresses to assign roles to. /// @param role Role to assign. function _assignOracleRoles(uint8 ocrPluginType, address[] memory oracleAddresses, Role role) internal { - for (uint8 i = 0; i < oracleAddresses.length; ++i) { + for (uint256 i = 0; i < oracleAddresses.length; ++i) { address oracle = oracleAddresses[i]; if (s_oracles[ocrPluginType][oracle].role != Role.Unset) { revert InvalidConfig(InvalidConfigErrorType.REPEATED_ORACLE_ADDRESS); } if (oracle == address(0)) revert OracleCannotBeZeroAddress(); - s_oracles[ocrPluginType][oracle] = Oracle(i, role); + s_oracles[ocrPluginType][oracle] = Oracle(uint8(i), role); } } @@ -294,7 +291,7 @@ abstract contract MultiOCR3Base is ITypeAndVersion, OwnerIsCreator { bytes32 rawVs // signatures ) internal view { // Verify signatures attached to report - bool[MAX_NUM_ORACLES] memory signed; + uint256 signed = 0; uint256 numberOfSignatures = rs.length; for (uint256 i; i < numberOfSignatures; ++i) { @@ -304,8 +301,8 @@ abstract contract MultiOCR3Base is ITypeAndVersion, OwnerIsCreator { // never have a signer role. Oracle memory oracle = s_oracles[ocrPluginType][signer]; if (oracle.role != Role.Signer) revert UnauthorizedSigner(); - if (signed[oracle.index]) revert NonUniqueSignatures(); - signed[oracle.index] = true; + if (signed & (0x1 << oracle.index) != 0) revert NonUniqueSignatures(); + signed |= 0x1 << oracle.index; } } diff --git a/contracts/src/v0.8/ccip/offRamp/OffRamp.sol b/contracts/src/v0.8/ccip/offRamp/OffRamp.sol index d594597d18..3c709a88f6 100644 --- a/contracts/src/v0.8/ccip/offRamp/OffRamp.sol +++ b/contracts/src/v0.8/ccip/offRamp/OffRamp.sol @@ -3,7 +3,6 @@ pragma solidity 0.8.24; import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; import {IAny2EVMMessageReceiver} from "../interfaces/IAny2EVMMessageReceiver.sol"; - import {IFeeQuoter} from "../interfaces/IFeeQuoter.sol"; import {IMessageInterceptor} from "../interfaces/IMessageInterceptor.sol"; import {INonceManager} from "../interfaces/INonceManager.sol"; @@ -138,7 +137,8 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { MerkleRoot[] merkleRoots; // Collection of merkle roots per source chain to commit } - /// @dev Struct to hold a merkle root for a source chain so that an array of these can be passed in the resetUblessedRoots function. + /// @dev Struct to hold a merkle root for a source chain so that an array of these can be passed in the + /// resetUnblessedRoots function. struct UnblessedRoot { uint64 sourceChainSelector; // Remote source chain selector that the Merkle Root is scoped to bytes32 merkleRoot; // Merkle root of a single remote source chain @@ -344,7 +344,7 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { uint64 sourceChainSelector = report.sourceChainSelector; _whenNotCursed(sourceChainSelector); - SourceChainConfig storage sourceChainConfig = _getEnabledSourceChainConfig(sourceChainSelector); + bytes memory onRamp = _getEnabledSourceChainConfig(sourceChainSelector).onRamp; uint256 numMsgs = report.messages.length; if (numMsgs == 0) revert EmptyReport(); @@ -365,7 +365,7 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { // over the same data, which increases gas cost. // Hashing all of the message fields ensures that the message being executed is correct and not tampered with. // Including the known OnRamp ensures that the message originates from the correct on ramp version - hashedLeaves[i] = Internal._hash(message, sourceChainConfig.onRamp); + hashedLeaves[i] = Internal._hash(message, onRamp); } // SECURITY CRITICAL CHECK @@ -445,7 +445,6 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { } _setExecutionState(sourceChainSelector, message.header.sequenceNumber, Internal.MessageExecutionState.IN_PROGRESS); - (Internal.MessageExecutionState newState, bytes memory returnData) = _trialExecute(message, offchainTokenData); _setExecutionState(sourceChainSelector, message.header.sequenceNumber, newState); @@ -477,6 +476,8 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { hashedLeaves[i], newState, returnData, + // This emit covers not only the execution through the router, but also all of the overhead in executing the + // message. This gives the most accurate representation of the gas used in the execution. gasStart - gasleft() ); } @@ -586,12 +587,12 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { // Check if the report contains price updates if (commitReport.priceUpdates.tokenPriceUpdates.length > 0 || commitReport.priceUpdates.gasPriceUpdates.length > 0) { - uint64 sequenceNumber = uint64(uint256(reportContext[1])); + uint64 ocrSequenceNumber = uint64(uint256(reportContext[1])); // Check for price staleness based on the epoch and round - if (s_latestPriceSequenceNumber < sequenceNumber) { + if (s_latestPriceSequenceNumber < ocrSequenceNumber) { // If prices are not stale, update the latest epoch and round - s_latestPriceSequenceNumber = sequenceNumber; + s_latestPriceSequenceNumber = ocrSequenceNumber; // And update the prices in the fee quoter IFeeQuoter(s_dynamicConfig.feeQuoter).updatePrices(commitReport.priceUpdates); } else { diff --git a/contracts/src/v0.8/ccip/onRamp/OnRamp.sol b/contracts/src/v0.8/ccip/onRamp/OnRamp.sol index 3587854e90..21b2f8efb0 100644 --- a/contracts/src/v0.8/ccip/onRamp/OnRamp.sol +++ b/contracts/src/v0.8/ccip/onRamp/OnRamp.sol @@ -99,7 +99,7 @@ contract OnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCreator { //solhint-disable gas-struct-packing struct AllowListConfigArgs { uint64 destChainSelector; // ─────────────╮ Destination chain selector - // │ destChainSelector and allowListEnabled are packed in the same slot + // │ destChainSelector and allowListEnabled are packed in the same slot bool allowListEnabled; // ────────────────╯ boolean indicator to specify if allowList check is enabled. address[] addedAllowlistedSenders; // list of senders to be added to the allowedSendersList address[] removedAllowlistedSenders; // list of senders to be removed from the allowedSendersList @@ -208,7 +208,7 @@ contract OnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCreator { }), sender: originalSender, data: message.data, - extraArgs: message.extraArgs, + extraArgs: convertedExtraArgs, receiver: message.receiver, feeToken: message.feeToken, feeTokenAmount: feeTokenAmount, @@ -232,9 +232,6 @@ contract OnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCreator { newMessage.tokenAmounts[i].destExecData = destExecDataPerToken[i]; } - // Override extraArgs with latest version - newMessage.extraArgs = convertedExtraArgs; - // Hash only after all fields have been set newMessage.header.messageId = Internal._hash( newMessage, @@ -425,8 +422,8 @@ contract OnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCreator { } } - for (uint256 k = 0; k < allowListConfigArgs.removedAllowlistedSenders.length; ++k) { - destChainConfig.allowedSendersList.remove(allowListConfigArgs.removedAllowlistedSenders[k]); + for (uint256 j = 0; j < allowListConfigArgs.removedAllowlistedSenders.length; ++j) { + destChainConfig.allowedSendersList.remove(allowListConfigArgs.removedAllowlistedSenders[j]); } if (allowListConfigArgs.removedAllowlistedSenders.length > 0) { diff --git a/core/gethwrappers/ccip/generated/ccip_config/ccip_config.go b/core/gethwrappers/ccip/generated/ccip_config/ccip_config.go index 19588a8009..dbbd06ffb5 100644 --- a/core/gethwrappers/ccip/generated/ccip_config/ccip_config.go +++ b/core/gethwrappers/ccip/generated/ccip_config/ccip_config.go @@ -62,7 +62,7 @@ type CCIPConfigTypesOCR3ConfigWithMeta struct { var CCIPConfigMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"capabilitiesRegistry\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainSelectorNotFound\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ChainSelectorNotSet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptySet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FChainMustBePositive\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FMustBePositive\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FTooHigh\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"length\",\"type\":\"uint256\"}],\"name\":\"InvalidConfigLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enumCCIPConfigTypes.ConfigState\",\"name\":\"currentState\",\"type\":\"uint8\"},{\"internalType\":\"enumCCIPConfigTypes.ConfigState\",\"name\":\"proposedState\",\"type\":\"uint8\"}],\"name\":\"InvalidConfigStateTransition\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidPluginType\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"}],\"name\":\"NodeNotInRegistry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonExistentConfigTransition\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"set\",\"type\":\"bytes32[]\"}],\"name\":\"NotASortedSet\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"subset\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"superset\",\"type\":\"bytes32[]\"}],\"name\":\"NotASubset\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"got\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minimum\",\"type\":\"uint256\"}],\"name\":\"NotEnoughTransmitters\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OfframpAddressCannotBeZero\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCapabilitiesRegistryCanCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"p2pIdsLength\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"signersLength\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"transmittersLength\",\"type\":\"uint256\"}],\"name\":\"P2PIdsLengthNotMatching\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManyBootstrapP2PIds\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManyOCR3Configs\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManySigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManyTransmitters\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"got\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"expected\",\"type\":\"uint64\"}],\"name\":\"WrongConfigCount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"got\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"}],\"name\":\"WrongConfigDigest\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"got\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"}],\"name\":\"WrongConfigDigestBlueGreen\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"CapabilityConfigurationSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainConfigRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes32[]\",\"name\":\"readers\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint8\",\"name\":\"fChain\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"structCCIPConfigTypes.ChainConfig\",\"name\":\"chainConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"chainSelectorRemoves\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes32[]\",\"name\":\"readers\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint8\",\"name\":\"fChain\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPConfigTypes.ChainConfig\",\"name\":\"chainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structCCIPConfigTypes.ChainConfigInfo[]\",\"name\":\"chainConfigAdds\",\"type\":\"tuple[]\"}],\"name\":\"applyChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"}],\"name\":\"beforeCapabilityConfigSet\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"pageIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pageSize\",\"type\":\"uint256\"}],\"name\":\"getAllChainConfigs\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes32[]\",\"name\":\"readers\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint8\",\"name\":\"fChain\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPConfigTypes.ChainConfig\",\"name\":\"chainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structCCIPConfigTypes.ChainConfigInfo[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"name\":\"getCapabilityConfiguration\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"configuration\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCapabilityRegistry\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"}],\"name\":\"getOCRConfig\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offrampAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"bootstrapP2PIds\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"p2pIds\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes[]\",\"name\":\"signers\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes[]\",\"name\":\"transmitters\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPConfigTypes.OCR3Config\",\"name\":\"config\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"configCount\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"internalType\":\"structCCIPConfigTypes.OCR3ConfigWithMeta[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x60a06040523480156200001157600080fd5b50604051620044b7380380620044b78339810160408190526200003491620001a6565b33806000816200008b5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000be57620000be81620000fb565b5050506001600160a01b038116620000e9576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b0316608052620001d8565b336001600160a01b03821603620001555760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000082565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600060208284031215620001b957600080fd5b81516001600160a01b0381168114620001d157600080fd5b9392505050565b6080516142b6620002016000396000818160f801528181610f3001526111c501526142b66000f3fe608060405234801561001057600080fd5b50600436106100c95760003560e01c80638318ed5d11610081578063f2fde38b1161005b578063f2fde38b1461020f578063f442c89a14610222578063fba64a7c1461023557600080fd5b80638318ed5d146101b05780638da5cb5b146101d1578063b74b2356146101ef57600080fd5b8063181f5a77116100b2578063181f5a771461013d5780634bd0473f1461018657806379ba5097146101a657600080fd5b806301ffc9a7146100ce578063020330e6146100f6575b600080fd5b6100e16100dc366004613060565b610248565b60405190151581526020015b60405180910390f35b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100ed565b6101796040518060400160405280601481526020017f43434950436f6e66696720312e362e302d64657600000000000000000000000081525081565b6040516100ed9190613106565b61019961019436600461314a565b6102e1565b6040516100ed9190613269565b6101ae6107b1565b005b6101796101be366004613446565b5060408051602081019091526000815290565b60005473ffffffffffffffffffffffffffffffffffffffff16610118565b6102026101fd366004613463565b6108b3565b6040516100ed91906134c9565b6101ae61021d366004613559565b610b34565b6101ae6102303660046135db565b610b48565b6101ae61024336600461365f565b610f18565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f78bea7210000000000000000000000000000000000000000000000000000000014806102db57507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b63ffffffff8216600090815260056020526040812060609183600181111561030b5761030b61317f565b600181111561031c5761031c61317f565b8152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b828210156107a557600084815260209020604080516101a08101909152600984029091018054829060608201908390829060ff16600181111561038f5761038f61317f565b60018111156103a0576103a061317f565b8152815467ffffffffffffffff61010082048116602084015260ff690100000000000000000083041660408401526a01000000000000000000009091041660608201526001820180546080909201916103f89061371c565b80601f01602080910402602001604051908101604052809291908181526020018280546104249061371c565b80156104715780601f1061044657610100808354040283529160200191610471565b820191906000526020600020905b81548152906001019060200180831161045457829003601f168201915b50505050508152602001600282018054806020026020016040519081016040528092919081815260200182805480156104c957602002820191906000526020600020905b8154815260200190600101908083116104b5575b505050505081526020016003820180548060200260200160405190810160405280929190818152602001828054801561052157602002820191906000526020600020905b81548152602001906001019080831161050d575b5050505050815260200160048201805480602002602001604051908101604052809291908181526020016000905b828210156105fb57838290600052602060002001805461056e9061371c565b80601f016020809104026020016040519081016040528092919081815260200182805461059a9061371c565b80156105e75780601f106105bc576101008083540402835291602001916105e7565b820191906000526020600020905b8154815290600101906020018083116105ca57829003601f168201915b50505050508152602001906001019061054f565b50505050815260200160058201805480602002602001604051908101604052809291908181526020016000905b828210156106d45783829060005260206000200180546106479061371c565b80601f01602080910402602001604051908101604052809291908181526020018280546106739061371c565b80156106c05780601f10610695576101008083540402835291602001916106c0565b820191906000526020600020905b8154815290600101906020018083116106a357829003601f168201915b505050505081526020019060010190610628565b5050505081526020016006820180546106ec9061371c565b80601f01602080910402602001604051908101604052809291908181526020018280546107189061371c565b80156107655780601f1061073a57610100808354040283529160200191610765565b820191906000526020600020905b81548152906001019060200180831161074857829003601f168201915b505050919092525050508152600782015467ffffffffffffffff16602080830191909152600890920154604090910152908252600192909201910161034a565b50505050905092915050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610837576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b606060006108c16003610fd9565b905060006108cf848661379e565b90508315806108de5750818110155b1561091e576040805160008082526020820190925290610914565b610901612df1565b8152602001906001900390816108f95790505b50925050506102db565b600061092a85836137e4565b9050828111156109375750815b600061094383836137f7565b67ffffffffffffffff81111561095b5761095b6137b5565b60405190808252806020026020018201604052801561099457816020015b610981612df1565b8152602001906001900390816109795790505b50905060006109a36003610fe3565b9050835b83811015610b275760008282815181106109c3576109c361380a565b60209081029190910181015160408051808201825267ffffffffffffffff831680825260009081526002855282902082518154608081880283018101909552606082018181529597509295860194909391928492849190840182828015610a4957602002820191906000526020600020905b815481526020019060010190808311610a35575b5050509183525050600182015460ff166020820152600282018054604090920191610a739061371c565b80601f0160208091040260200160405190810160405280929190818152602001828054610a9f9061371c565b8015610aec5780601f10610ac157610100808354040283529160200191610aec565b820191906000526020600020905b815481529060010190602001808311610acf57829003601f168201915b50505091909252505050905284610b0388856137f7565b81518110610b1357610b1361380a565b6020908102919091010152506001016109a7565b5090979650505050505050565b610b3c610ff7565b610b458161107a565b50565b610b50610ff7565b60005b83811015610d3657610b97858583818110610b7057610b7061380a565b9050602002016020810190610b859190613839565b60039067ffffffffffffffff1661116f565b610c0157848482818110610bad57610bad61380a565b9050602002016020810190610bc29190613839565b6040517f1bd4d2d200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260240161082e565b60026000868684818110610c1757610c1761380a565b9050602002016020810190610c2c9190613839565b67ffffffffffffffff1681526020810191909152604001600090812090610c538282612e39565b6001820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055610c8b600283016000612e57565b5050610cc9858583818110610ca257610ca261380a565b9050602002016020810190610cb79190613839565b60039067ffffffffffffffff16611187565b507f2a680691fef3b2d105196805935232c661ce703e92d464ef0b94a7bc62d714f0858583818110610cfd57610cfd61380a565b9050602002016020810190610d129190613839565b60405167ffffffffffffffff909116815260200160405180910390a1600101610b53565b5060005b81811015610f11576000838383818110610d5657610d5661380a565b9050602002810190610d689190613854565b610d76906020810190613892565b610d7f90613a94565b80519091506000858585818110610d9857610d9861380a565b9050602002810190610daa9190613854565b610db8906020810190613839565b905060005b8251811015610df057610de8838281518110610ddb57610ddb61380a565b6020026020010151611193565b600101610dbd565b50826020015160ff16600003610e32576040517fa9b3766e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff81166000908152600260209081526040909120845180518693610e62928492910190612e91565b5060208201516001820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff90921691909117905560408201516002820190610eaf9082613b7b565b50610ec991506003905067ffffffffffffffff83166112ac565b507f05dd57854af2c291a94ea52e7c43d80bc3be7fa73022f98b735dea86642fa5e08184604051610efb929190613c95565b60405180910390a1505050806001019050610d3a565b5050505050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610f87576040517fac7a7efd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610f9584860186613d40565b9050600080610fa3836112b8565b8151919350915015610fbb57610fbb84600084611511565b805115610fce57610fce84600183611511565b505050505050505050565b60006102db825490565b60606000610ff083611cf2565b9392505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611078576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640161082e565b565b3373ffffffffffffffffffffffffffffffffffffffff8216036110f9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161082e565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60008181526001830160205260408120541515610ff0565b6000610ff08383611d4e565b6040517f50c946fe000000000000000000000000000000000000000000000000000000008152600481018290526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906350c946fe90602401600060405180830381865afa158015611221573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526112679190810190613fb1565b60808101519091506112a8576040517f8907a4fa0000000000000000000000000000000000000000000000000000000081526004810183905260240161082e565b5050565b6000610ff08383611e48565b606080600460ff16835111156112fa576040517f8854586400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160028082526060820190925290816020015b61137e6040805161014081019091528060008152602001600067ffffffffffffffff168152602001600060ff168152602001600067ffffffffffffffff1681526020016060815260200160608152602001606081526020016060815260200160608152602001606081525090565b81526020019060019003908161131057505060408051600280825260608201909252919350602082015b6114166040805161014081019091528060008152602001600067ffffffffffffffff168152602001600060ff168152602001600067ffffffffffffffff1681526020016060815260200160608152602001606081526020016060815260200160608152602001606081525090565b8152602001906001900390816113a857905050905060008060005b855181101561150457600086828151811061144e5761144e61380a565b602002602001015160000151600181111561146b5761146b61317f565b036114b8578581815181106114825761148261380a565b602002602001015185848151811061149c5761149c61380a565b6020026020010181905250826114b190614089565b92506114fc565b8581815181106114ca576114ca61380a565b60200260200101518483815181106114e4576114e461380a565b6020026020010181905250816114f990614089565b91505b600101611431565b5090835281529092909150565b63ffffffff83166000908152600560205260408120818460018111156115395761153961317f565b600181111561154a5761154a61317f565b8152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b828210156119d357600084815260209020604080516101a08101909152600984029091018054829060608201908390829060ff1660018111156115bd576115bd61317f565b60018111156115ce576115ce61317f565b8152815467ffffffffffffffff61010082048116602084015260ff690100000000000000000083041660408401526a01000000000000000000009091041660608201526001820180546080909201916116269061371c565b80601f01602080910402602001604051908101604052809291908181526020018280546116529061371c565b801561169f5780601f106116745761010080835404028352916020019161169f565b820191906000526020600020905b81548152906001019060200180831161168257829003601f168201915b50505050508152602001600282018054806020026020016040519081016040528092919081815260200182805480156116f757602002820191906000526020600020905b8154815260200190600101908083116116e3575b505050505081526020016003820180548060200260200160405190810160405280929190818152602001828054801561174f57602002820191906000526020600020905b81548152602001906001019080831161173b575b5050505050815260200160048201805480602002602001604051908101604052809291908181526020016000905b8282101561182957838290600052602060002001805461179c9061371c565b80601f01602080910402602001604051908101604052809291908181526020018280546117c89061371c565b80156118155780601f106117ea57610100808354040283529160200191611815565b820191906000526020600020905b8154815290600101906020018083116117f857829003601f168201915b50505050508152602001906001019061177d565b50505050815260200160058201805480602002602001604051908101604052809291908181526020016000905b828210156119025783829060005260206000200180546118759061371c565b80601f01602080910402602001604051908101604052809291908181526020018280546118a19061371c565b80156118ee5780601f106118c3576101008083540402835291602001916118ee565b820191906000526020600020905b8154815290600101906020018083116118d157829003601f168201915b505050505081526020019060010190611856565b50505050815260200160068201805461191a9061371c565b80601f01602080910402602001604051908101604052809291908181526020018280546119469061371c565b80156119935780601f1061196857610100808354040283529160200191611993565b820191906000526020600020905b81548152906001019060200180831161197657829003601f168201915b505050919092525050508152600782015467ffffffffffffffff166020808301919091526008909201546040909101529082526001929092019101611578565b50505050905060006119e58251611e97565b905060006119f38451611e97565b90506119ff8282611ee9565b6000611a0e8785878686611fa5565b9050611a1a8482612391565b63ffffffff8716600090815260056020526040812090876001811115611a4257611a4261317f565b6001811115611a5357611a5361317f565b81526020019081526020016000206000611a6d9190612edc565b60005b8151811015611ce85763ffffffff8816600090815260056020526040812090886001811115611aa157611aa161317f565b6001811115611ab257611ab261317f565b8152602001908152602001600020828281518110611ad257611ad261380a565b6020908102919091018101518254600181810185556000948552929093208151805160099095029091018054929490939192849283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016908381811115611b3c57611b3c61317f565b021790555060208201518154604084015160608501517fffffffffffffffffffffffffffffffffffffffffffff000000000000000000ff90921661010067ffffffffffffffff948516027fffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffff1617690100000000000000000060ff90921691909102177fffffffffffffffffffffffffffff0000000000000000ffffffffffffffffffff166a0100000000000000000000929091169190910217815560808201516001820190611c0b9082613b7b565b5060a08201518051611c27916002840191602090910190612e91565b5060c08201518051611c43916003840191602090910190612e91565b5060e08201518051611c5f916004840191602090910190612efd565b506101008201518051611c7c916005840191602090910190612efd565b506101208201516006820190611c929082613b7b565b50505060208201516007820180547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff909216919091179055604090910151600890910155600101611a70565b5050505050505050565b606081600001805480602002602001604051908101604052809291908181526020018280548015611d4257602002820191906000526020600020905b815481526020019060010190808311611d2e575b50505050509050919050565b60008181526001830160205260408120548015611e37576000611d726001836137f7565b8554909150600090611d86906001906137f7565b9050808214611deb576000866000018281548110611da657611da661380a565b9060005260206000200154905080876000018481548110611dc957611dc961380a565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080611dfc57611dfc6140c1565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506102db565b60009150506102db565b5092915050565b6000818152600183016020526040812054611e8f575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556102db565b5060006102db565b60006002821115611ed7576040517f3e4785260000000000000000000000000000000000000000000000000000000081526004810183905260240161082e565b8160028111156102db576102db61317f565b6000826002811115611efd57611efd61317f565b826002811115611f0f57611f0f61317f565b611f1991906140f0565b90508060011480611f655750807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff148015611f6557506002836002811115611f6357611f6361317f565b145b15611f6f57505050565b82826040517f0a6b675b00000000000000000000000000000000000000000000000000000000815260040161082e929190614120565b60606000845167ffffffffffffffff811115611fc357611fc36137b5565b604051908082528060200260200182016040528015611fec578160200160208202803683370190505b50905060008460028111156120035761200361317f565b1480156120215750600183600281111561201f5761201f61317f565b145b156120625760018160008151811061203b5761203b61380a565b602002602001019067ffffffffffffffff16908167ffffffffffffffff16815250506121ca565b60018460028111156120765761207661317f565b148015612094575060028360028111156120925761209261317f565b145b1561212b57856000815181106120ac576120ac61380a565b602002602001015160200151816000815181106120cb576120cb61380a565b602002602001019067ffffffffffffffff16908167ffffffffffffffff1681525050856000815181106121005761210061380a565b6020026020010151602001516001612118919061413b565b8160018151811061203b5761203b61380a565b600284600281111561213f5761213f61317f565b14801561215d5750600183600281111561215b5761215b61317f565b145b1561219457856001815181106121755761217561380a565b6020026020010151602001518160008151811061203b5761203b61380a565b83836040517f0a6b675b00000000000000000000000000000000000000000000000000000000815260040161082e929190614120565b6000855167ffffffffffffffff8111156121e6576121e66137b5565b60405190808252806020026020018201604052801561229c57816020015b604080516101a081018252600060608083018281526080840183905260a0840183905260c0840183905260e084018290526101008401829052610120840182905261014084018290526101608401829052610180840191909152825260208083018290529282015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816122045790505b50905060005b8251811015612385576122cd8782815181106122c0576122c061380a565b6020026020010151612710565b60405180606001604052808883815181106122ea576122ea61380a565b602002602001015181526020018483815181106123095761230961380a565b602002602001015167ffffffffffffffff16815260200161235d8b8685815181106123365761233661380a565b60200260200101518b86815181106123505761235061380a565b6020026020010151612b16565b8152508282815181106123725761237261380a565b60209081029190910101526001016122a2565b50979650505050505050565b81518151811580156123a35750806001145b1561244557826000815181106123bb576123bb61380a565b60200260200101516020015167ffffffffffffffff1660011461243f57826000815181106123eb576123eb61380a565b60209081029190910181015101516040517fc1658eb800000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526001602482015260440161082e565b50505050565b8160011480156124555750806002145b1561260b578360008151811061246d5761246d61380a565b6020026020010151604001518360008151811061248c5761248c61380a565b6020026020010151604001511461251857826000815181106124b0576124b061380a565b602002602001015160400151846000815181106124cf576124cf61380a565b6020026020010151604001516040517fc7ccdd7f00000000000000000000000000000000000000000000000000000000815260040161082e929190918252602082015260400190565b8360008151811061252b5761252b61380a565b6020026020010151602001516001612543919061413b565b67ffffffffffffffff16836001815181106125605761256061380a565b60200260200101516020015167ffffffffffffffff161461243f578260018151811061258e5761258e61380a565b602002602001015160200151846000815181106125ad576125ad61380a565b60200260200101516020015160016125c5919061413b565b6040517fc1658eb800000000000000000000000000000000000000000000000000000000815267ffffffffffffffff92831660048201529116602482015260440161082e565b81600214801561261b5750806001145b156126de57836001815181106126335761263361380a565b602002602001015160400151836000815181106126525761265261380a565b6020026020010151604001511461243f57826000815181106126765761267661380a565b602002602001015160400151846001815181106126955761269561380a565b6020026020010151604001516040517f9e97567000000000000000000000000000000000000000000000000000000000815260040161082e929190918252602082015260400190565b6040517f1f1b2bb600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806020015167ffffffffffffffff16600003612758576040517f698cf8e000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008151600181111561276d5761276d61317f565b1415801561278e575060018151600181111561278b5761278b61317f565b14155b156127c5576040517f3302dbd700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806080015151600003612804576040517f358c192700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602081015161281f9060039067ffffffffffffffff1661116f565b6128675760208101516040517f1bd4d2d200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260240161082e565b60e081015151601f10156128a7576040517f1b925da600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61010081015151601f10156128e8576040517f645960ff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208082015167ffffffffffffffff166000908152600290915260408120600101546129189060ff16600361415c565b612923906001614178565b60ff1690508082610100015151101561297a57610100820151516040517f548dd21f00000000000000000000000000000000000000000000000000000000815260048101919091526024810182905260440161082e565b816040015160ff166000036129bb576040517f39d1a4d000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408201516129cb90600361415c565b60ff168260e001515111612a0b576040517f4856694e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8160e00151518260c0015151141580612a2f5750816101000151518260c001515114155b15612a8a5760c08201515160e083015151610100840151516040517fba900f6d00000000000000000000000000000000000000000000000000000000815260048101939093526024830191909152604482015260640161082e565b8160c00151518260a00151511115612ace576040517f8473d80700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612ae08260a001518360c00151612beb565b60005b8260e0015151811015612b1157612b098360c001518281518110610ddb57610ddb61380a565b600101612ae3565b505050565b60008082602001518584600001518560800151878760a001518860c001518960e001518a61010001518b604001518c606001518d6101200151604051602001612b6a9c9b9a99989796959493929190614191565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e0a000000000000000000000000000000000000000000000000000000000000179150509392505050565b81511580612bf857508051155b15612c2f576040517fe249684100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612c3882612d66565b612c4181612d66565b6000805b835182108015612c555750825181105b15612d2757828181518110612c6c57612c6c61380a565b6020026020010151848381518110612c8657612c8661380a565b60200260200101511115612ca457612c9d81614089565b9050612c45565b828181518110612cb657612cb661380a565b6020026020010151848381518110612cd057612cd061380a565b602002602001015103612cf157612ce682614089565b9150612c9d81614089565b83836040517fd671700c00000000000000000000000000000000000000000000000000000000815260040161082e929190614271565b835182101561243f5783836040517fd671700c00000000000000000000000000000000000000000000000000000000815260040161082e929190614271565b60015b81518110156112a85781612d7e6001836137f7565b81518110612d8e57612d8e61380a565b6020026020010151828281518110612da857612da861380a565b602002602001015111612de957816040517f1bc41b4200000000000000000000000000000000000000000000000000000000815260040161082e9190614296565b600101612d69565b6040518060400160405280600067ffffffffffffffff168152602001612e34604051806060016040528060608152602001600060ff168152602001606081525090565b905290565b5080546000825590600052602060002090810190610b459190612f4f565b508054612e639061371c565b6000825580601f10612e73575050565b601f016020900490600052602060002090810190610b459190612f4f565b828054828255906000526020600020908101928215612ecc579160200282015b82811115612ecc578251825591602001919060010190612eb1565b50612ed8929150612f4f565b5090565b5080546000825560090290600052602060002090810190610b459190612f64565b828054828255906000526020600020908101928215612f43579160200282015b82811115612f435782518290612f339082613b7b565b5091602001919060010190612f1d565b50612ed8929150613025565b5b80821115612ed85760008155600101612f50565b80821115612ed85780547fffffffffffffffffffffffffffff00000000000000000000000000000000000016815560008181612fa36001830182612e57565b612fb1600283016000612e39565b612fbf600383016000612e39565b612fcd600483016000613042565b612fdb600583016000613042565b612fe9600683016000612e57565b5050506007810180547fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000016905560006008820155600901612f64565b80821115612ed85760006130398282612e57565b50600101613025565b5080546000825590600052602060002090810190610b459190613025565b60006020828403121561307257600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610ff057600080fd5b6000815180845260005b818110156130c8576020818501810151868301820152016130ac565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000610ff060208301846130a2565b63ffffffff81168114610b4557600080fd5b803561313681613119565b919050565b80356002811061313657600080fd5b6000806040838503121561315d57600080fd5b823561316881613119565b91506131766020840161313b565b90509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600281106131be576131be61317f565b9052565b60008151808452602080850194506020840160005b838110156131f3578151875295820195908201906001016131d7565b509495945050505050565b60008282518085526020808601955060208260051b8401016020860160005b84811015610b27577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08684030189526132578383516130a2565b9884019892509083019060010161321d565b600060208083018184528085518083526040925060408601915060408160051b87010184880160005b83811015613438577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08984030185528151606081518186526132d782870182516131ae565b8981015160806132f28189018367ffffffffffffffff169052565b8a830151915060a0613308818a018460ff169052565b938301519360c092506133268984018667ffffffffffffffff169052565b818401519450610140915060e082818b01526133466101a08b01876130a2565b95508185015191507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0610100818c890301818d015261338588856131c2565b97508587015195506101209350818c890301848d01526133a588876131c2565b9750828701519550818c890301858d01526133c088876131fe565b975080870151955050808b8803016101608c01526133de87866131fe565b9650828601519550808b8803016101808c0152505050505061340082826130a2565b9150508882015161341c8a87018267ffffffffffffffff169052565b5090870151938701939093529386019390860190600101613292565b509098975050505050505050565b60006020828403121561345857600080fd5b8135610ff081613119565b6000806040838503121561347657600080fd5b50508035926020909101359150565b600081516060845261349a60608501826131c2565b905060ff6020840151166020850152604083015184820360408601526134c082826130a2565b95945050505050565b600060208083018184528085518083526040925060408601915060408160051b87010184880160005b83811015613438578883037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00185528151805167ffffffffffffffff16845287015187840187905261354687850182613485565b95880195935050908601906001016134f2565b60006020828403121561356b57600080fd5b813573ffffffffffffffffffffffffffffffffffffffff81168114610ff057600080fd5b60008083601f8401126135a157600080fd5b50813567ffffffffffffffff8111156135b957600080fd5b6020830191508360208260051b85010111156135d457600080fd5b9250929050565b600080600080604085870312156135f157600080fd5b843567ffffffffffffffff8082111561360957600080fd5b6136158883890161358f565b9096509450602087013591508082111561362e57600080fd5b5061363b8782880161358f565b95989497509550505050565b803567ffffffffffffffff8116811461313657600080fd5b6000806000806000806080878903121561367857600080fd5b863567ffffffffffffffff8082111561369057600080fd5b61369c8a838b0161358f565b909850965060208901359150808211156136b557600080fd5b818901915089601f8301126136c957600080fd5b8135818111156136d857600080fd5b8a60208285010111156136ea57600080fd5b60208301965080955050505061370260408801613647565b91506137106060880161312b565b90509295509295509295565b600181811c9082168061373057607f821691505b602082108103613769577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80820281158282048414176102db576102db61376f565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b808201808211156102db576102db61376f565b818103818111156102db576102db61376f565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561384b57600080fd5b610ff082613647565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc183360301811261388857600080fd5b9190910192915050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa183360301811261388857600080fd5b604051610140810167ffffffffffffffff811182821017156138ea576138ea6137b5565b60405290565b60405160e0810167ffffffffffffffff811182821017156138ea576138ea6137b5565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561395a5761395a6137b5565b604052919050565b600067ffffffffffffffff82111561397c5761397c6137b5565b5060051b60200190565b600082601f83011261399757600080fd5b813560206139ac6139a783613962565b613913565b8083825260208201915060208460051b8701019350868411156139ce57600080fd5b602086015b848110156139ea57803583529183019183016139d3565b509695505050505050565b803560ff8116811461313657600080fd5b600082601f830112613a1757600080fd5b813567ffffffffffffffff811115613a3157613a316137b5565b613a6260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601613913565b818152846020838601011115613a7757600080fd5b816020850160208301376000918101602001919091529392505050565b600060608236031215613aa657600080fd5b6040516060810167ffffffffffffffff8282108183111715613aca57613aca6137b5565b816040528435915080821115613adf57600080fd5b613aeb36838701613986565b8352613af9602086016139f5565b60208401526040850135915080821115613b1257600080fd5b50613b1f36828601613a06565b60408301525092915050565b601f821115612b11576000816000526020600020601f850160051c81016020861015613b545750805b601f850160051c820191505b81811015613b7357828155600101613b60565b505050505050565b815167ffffffffffffffff811115613b9557613b956137b5565b613ba981613ba3845461371c565b84613b2b565b602080601f831160018114613bfc5760008415613bc65750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555613b73565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015613c4957888601518255948401946001909101908401613c2a565b5085821015613c8557878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b67ffffffffffffffff83168152604060208201526000613cb86040830184613485565b949350505050565b600082601f830112613cd157600080fd5b81356020613ce16139a783613962565b82815260059290921b84018101918181019086841115613d0057600080fd5b8286015b848110156139ea57803567ffffffffffffffff811115613d245760008081fd5b613d328986838b0101613a06565b845250918301918301613d04565b60006020808385031215613d5357600080fd5b823567ffffffffffffffff80821115613d6b57600080fd5b818501915085601f830112613d7f57600080fd5b8135613d8d6139a782613962565b81815260059190911b83018401908481019088831115613dac57600080fd5b8585015b83811015613f3a57803585811115613dc757600080fd5b8601610140818c037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0011215613dfc57600080fd5b613e046138c6565b613e0f89830161313b565b8152613e1d60408301613647565b89820152613e2d606083016139f5565b6040820152613e3e60808301613647565b606082015260a082013587811115613e5557600080fd5b613e638d8b83860101613a06565b60808301525060c082013587811115613e7b57600080fd5b613e898d8b83860101613986565b60a08301525060e082013587811115613ea157600080fd5b613eaf8d8b83860101613986565b60c0830152506101008083013588811115613ec957600080fd5b613ed78e8c83870101613cc0565b60e0840152506101208084013589811115613ef157600080fd5b613eff8f8d83880101613cc0565b8385015250610140840135915088821115613f1957600080fd5b613f278e8c84870101613a06565b9083015250845250918601918601613db0565b5098975050505050505050565b805161313681613119565b600082601f830112613f6357600080fd5b81516020613f736139a783613962565b8083825260208201915060208460051b870101935086841115613f9557600080fd5b602086015b848110156139ea5780518352918301918301613f9a565b600060208284031215613fc357600080fd5b815167ffffffffffffffff80821115613fdb57600080fd5b9083019060e08286031215613fef57600080fd5b613ff76138f0565b61400083613f47565b815261400e60208401613f47565b602082015261401f60408401613f47565b6040820152606083015160608201526080830151608082015260a08301518281111561404a57600080fd5b61405687828601613f52565b60a08301525060c08301518281111561406e57600080fd5b61407a87828601613f52565b60c08301525095945050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036140ba576140ba61376f565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b8181036000831280158383131683831282161715611e4157611e4161376f565b600381106131be576131be61317f565b6040810161412e8285614110565b610ff06020830184614110565b67ffffffffffffffff818116838216019080821115611e4157611e4161376f565b60ff8181168382160290811690818114611e4157611e4161376f565b60ff81811683821601908111156102db576102db61376f565b67ffffffffffffffff8d16815263ffffffff8c1660208201526141b7604082018c6131ae565b610180606082015260006141cf61018083018c6130a2565b67ffffffffffffffff8b16608084015282810360a08401526141f1818b6131c2565b905082810360c0840152614205818a6131c2565b905082810360e084015261421981896131fe565b905082810361010084015261422e81886131fe565b60ff8716610120850152905067ffffffffffffffff851661014084015282810361016084015261425e81856130a2565b9f9e505050505050505050505050505050565b60408152600061428460408301856131c2565b82810360208401526134c081856131c2565b602081526000610ff060208301846131c256fea164736f6c6343000818000a", + Bin: "0x60a06040523480156200001157600080fd5b5060405162004481380380620044818339810160408190526200003491620001a6565b33806000816200008b5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000be57620000be81620000fb565b5050506001600160a01b038116620000e9576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b0316608052620001d8565b336001600160a01b03821603620001555760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000082565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600060208284031215620001b957600080fd5b81516001600160a01b0381168114620001d157600080fd5b9392505050565b608051614280620002016000396000818160f801528181610eff015261116f01526142806000f3fe608060405234801561001057600080fd5b50600436106100c95760003560e01c80638318ed5d11610081578063f2fde38b1161005b578063f2fde38b1461020f578063f442c89a14610222578063fba64a7c1461023557600080fd5b80638318ed5d146101b05780638da5cb5b146101d1578063b74b2356146101ef57600080fd5b8063181f5a77116100b2578063181f5a771461013d5780634bd0473f1461018657806379ba5097146101a657600080fd5b806301ffc9a7146100ce578063020330e6146100f6575b600080fd5b6100e16100dc366004613029565b610248565b60405190151581526020015b60405180910390f35b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100ed565b6101796040518060400160405280601481526020017f43434950436f6e66696720312e362e302d64657600000000000000000000000081525081565b6040516100ed91906130cf565b610199610194366004613113565b6102e1565b6040516100ed9190613232565b6101ae6107b1565b005b6101796101be36600461340f565b5060408051602081019091526000815290565b60005473ffffffffffffffffffffffffffffffffffffffff16610118565b6102026101fd36600461342c565b6108b3565b6040516100ed9190613492565b6101ae61021d366004613522565b610b34565b6101ae6102303660046135a4565b610b48565b6101ae610243366004613628565b610ee7565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f78bea7210000000000000000000000000000000000000000000000000000000014806102db57507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b63ffffffff8216600090815260056020526040812060609183600181111561030b5761030b613148565b600181111561031c5761031c613148565b8152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b828210156107a557600084815260209020604080516101a08101909152600984029091018054829060608201908390829060ff16600181111561038f5761038f613148565b60018111156103a0576103a0613148565b8152815467ffffffffffffffff61010082048116602084015260ff690100000000000000000083041660408401526a01000000000000000000009091041660608201526001820180546080909201916103f8906136e5565b80601f0160208091040260200160405190810160405280929190818152602001828054610424906136e5565b80156104715780601f1061044657610100808354040283529160200191610471565b820191906000526020600020905b81548152906001019060200180831161045457829003601f168201915b50505050508152602001600282018054806020026020016040519081016040528092919081815260200182805480156104c957602002820191906000526020600020905b8154815260200190600101908083116104b5575b505050505081526020016003820180548060200260200160405190810160405280929190818152602001828054801561052157602002820191906000526020600020905b81548152602001906001019080831161050d575b5050505050815260200160048201805480602002602001604051908101604052809291908181526020016000905b828210156105fb57838290600052602060002001805461056e906136e5565b80601f016020809104026020016040519081016040528092919081815260200182805461059a906136e5565b80156105e75780601f106105bc576101008083540402835291602001916105e7565b820191906000526020600020905b8154815290600101906020018083116105ca57829003601f168201915b50505050508152602001906001019061054f565b50505050815260200160058201805480602002602001604051908101604052809291908181526020016000905b828210156106d4578382906000526020600020018054610647906136e5565b80601f0160208091040260200160405190810160405280929190818152602001828054610673906136e5565b80156106c05780601f10610695576101008083540402835291602001916106c0565b820191906000526020600020905b8154815290600101906020018083116106a357829003601f168201915b505050505081526020019060010190610628565b5050505081526020016006820180546106ec906136e5565b80601f0160208091040260200160405190810160405280929190818152602001828054610718906136e5565b80156107655780601f1061073a57610100808354040283529160200191610765565b820191906000526020600020905b81548152906001019060200180831161074857829003601f168201915b505050919092525050508152600782015467ffffffffffffffff16602080830191909152600890920154604090910152908252600192909201910161034a565b50505050905092915050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610837576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b606060006108c16003610fa2565b905060006108cf8486613767565b90508315806108de5750818110155b1561091e576040805160008082526020820190925290610914565b610901612dba565b8152602001906001900390816108f95790505b50925050506102db565b600061092a85836137ad565b9050828111156109375750815b600061094383836137c0565b67ffffffffffffffff81111561095b5761095b61377e565b60405190808252806020026020018201604052801561099457816020015b610981612dba565b8152602001906001900390816109795790505b50905060006109a36003610fac565b9050835b83811015610b275760008282815181106109c3576109c36137d3565b60209081029190910181015160408051808201825267ffffffffffffffff831680825260009081526002855282902082518154608081880283018101909552606082018181529597509295860194909391928492849190840182828015610a4957602002820191906000526020600020905b815481526020019060010190808311610a35575b5050509183525050600182015460ff166020820152600282018054604090920191610a73906136e5565b80601f0160208091040260200160405190810160405280929190818152602001828054610a9f906136e5565b8015610aec5780601f10610ac157610100808354040283529160200191610aec565b820191906000526020600020905b815481529060010190602001808311610acf57829003601f168201915b50505091909252505050905284610b0388856137c0565b81518110610b1357610b136137d3565b6020908102919091010152506001016109a7565b5090979650505050505050565b610b3c610fc0565b610b4581611043565b50565b610b50610fc0565b60005b83811015610d3657610b97858583818110610b7057610b706137d3565b9050602002016020810190610b859190613802565b60039067ffffffffffffffff16611138565b610c0157848482818110610bad57610bad6137d3565b9050602002016020810190610bc29190613802565b6040517f1bd4d2d200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260240161082e565b60026000868684818110610c1757610c176137d3565b9050602002016020810190610c2c9190613802565b67ffffffffffffffff1681526020810191909152604001600090812090610c538282612e02565b6001820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055610c8b600283016000612e20565b5050610cc9858583818110610ca257610ca26137d3565b9050602002016020810190610cb79190613802565b60039067ffffffffffffffff16611150565b507f2a680691fef3b2d105196805935232c661ce703e92d464ef0b94a7bc62d714f0858583818110610cfd57610cfd6137d3565b9050602002016020810190610d129190613802565b60405167ffffffffffffffff909116815260200160405180910390a1600101610b53565b5060005b81811015610ee0576000838383818110610d5657610d566137d3565b9050602002810190610d68919061381d565b610d7690602081019061385b565b610d7f90613a5d565b90506000848484818110610d9557610d956137d3565b9050602002810190610da7919061381d565b610db5906020810190613802565b9050610dc4826000015161115c565b816020015160ff16600003610e05576040517fa9b3766e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff81166000908152600260209081526040909120835180518593610e35928492910190612e5a565b5060208201516001820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff90921691909117905560408201516002820190610e829082613b45565b50610e9c91506003905067ffffffffffffffff83166112a8565b507f05dd57854af2c291a94ea52e7c43d80bc3be7fa73022f98b735dea86642fa5e08183604051610ece929190613c5f565b60405180910390a15050600101610d3a565b5050505050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610f56576040517fac7a7efd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080610f6d610f6886880188613d0a565b6112b4565b8151919350915015610f8557610f858360008461150d565b805115610f9857610f988360018361150d565b5050505050505050565b60006102db825490565b60606000610fb983611ce4565b9392505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611041576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640161082e565b565b3373ffffffffffffffffffffffffffffffffffffffff8216036110c2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161082e565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60008181526001830160205260408120541515610fb9565b6000610fb98383611d40565b60005b81518110156112a45760008019167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166350c946fe8484815181106111bb576111bb6137d3565b60200260200101516040518263ffffffff1660e01b81526004016111e191815260200190565b600060405180830381865afa1580156111fe573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526112449190810190613f7b565b608001510361129c5781818151811061125f5761125f6137d3565b60200260200101516040517f8907a4fa00000000000000000000000000000000000000000000000000000000815260040161082e91815260200190565b60010161115f565b5050565b6000610fb98383611e3a565b606080600460ff16835111156112f6576040517f8854586400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160028082526060820190925290816020015b61137a6040805161014081019091528060008152602001600067ffffffffffffffff168152602001600060ff168152602001600067ffffffffffffffff1681526020016060815260200160608152602001606081526020016060815260200160608152602001606081525090565b81526020019060019003908161130c57505060408051600280825260608201909252919350602082015b6114126040805161014081019091528060008152602001600067ffffffffffffffff168152602001600060ff168152602001600067ffffffffffffffff1681526020016060815260200160608152602001606081526020016060815260200160608152602001606081525090565b8152602001906001900390816113a457905050905060008060005b855181101561150057600086828151811061144a5761144a6137d3565b602002602001015160000151600181111561146757611467613148565b036114b45785818151811061147e5761147e6137d3565b6020026020010151858481518110611498576114986137d3565b6020026020010181905250826114ad90614053565b92506114f8565b8581815181106114c6576114c66137d3565b60200260200101518483815181106114e0576114e06137d3565b6020026020010181905250816114f590614053565b91505b60010161142d565b5090835281529092909150565b63ffffffff831660009081526005602052604081208184600181111561153557611535613148565b600181111561154657611546613148565b8152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b828210156119cf57600084815260209020604080516101a08101909152600984029091018054829060608201908390829060ff1660018111156115b9576115b9613148565b60018111156115ca576115ca613148565b8152815467ffffffffffffffff61010082048116602084015260ff690100000000000000000083041660408401526a0100000000000000000000909104166060820152600182018054608090920191611622906136e5565b80601f016020809104026020016040519081016040528092919081815260200182805461164e906136e5565b801561169b5780601f106116705761010080835404028352916020019161169b565b820191906000526020600020905b81548152906001019060200180831161167e57829003601f168201915b50505050508152602001600282018054806020026020016040519081016040528092919081815260200182805480156116f357602002820191906000526020600020905b8154815260200190600101908083116116df575b505050505081526020016003820180548060200260200160405190810160405280929190818152602001828054801561174b57602002820191906000526020600020905b815481526020019060010190808311611737575b5050505050815260200160048201805480602002602001604051908101604052809291908181526020016000905b82821015611825578382906000526020600020018054611798906136e5565b80601f01602080910402602001604051908101604052809291908181526020018280546117c4906136e5565b80156118115780601f106117e657610100808354040283529160200191611811565b820191906000526020600020905b8154815290600101906020018083116117f457829003601f168201915b505050505081526020019060010190611779565b50505050815260200160058201805480602002602001604051908101604052809291908181526020016000905b828210156118fe578382906000526020600020018054611871906136e5565b80601f016020809104026020016040519081016040528092919081815260200182805461189d906136e5565b80156118ea5780601f106118bf576101008083540402835291602001916118ea565b820191906000526020600020905b8154815290600101906020018083116118cd57829003601f168201915b505050505081526020019060010190611852565b505050508152602001600682018054611916906136e5565b80601f0160208091040260200160405190810160405280929190818152602001828054611942906136e5565b801561198f5780601f106119645761010080835404028352916020019161198f565b820191906000526020600020905b81548152906001019060200180831161197257829003601f168201915b505050919092525050508152600782015467ffffffffffffffff166020808301919091526008909201546040909101529082526001929092019101611574565b50505050905060006119e18251611e89565b905060006119ef8451611e89565b90506119fb8282611edb565b6000611a0a8785878686611f97565b9050611a168482612383565b63ffffffff8716600090815260056020526040812090876001811115611a3e57611a3e613148565b6001811115611a4f57611a4f613148565b81526020019081526020016000206000611a699190612ea5565b60005b8151811015610f985763ffffffff8816600090815260056020526040812090886001811115611a9d57611a9d613148565b6001811115611aae57611aae613148565b8152602001908152602001600020828281518110611ace57611ace6137d3565b6020908102919091018101518254600181810185556000948552929093208151805160099095029091018054929490939192849283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016908381811115611b3857611b38613148565b021790555060208201518154604084015160608501517fffffffffffffffffffffffffffffffffffffffffffff000000000000000000ff90921661010067ffffffffffffffff948516027fffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffff1617690100000000000000000060ff90921691909102177fffffffffffffffffffffffffffff0000000000000000ffffffffffffffffffff166a0100000000000000000000929091169190910217815560808201516001820190611c079082613b45565b5060a08201518051611c23916002840191602090910190612e5a565b5060c08201518051611c3f916003840191602090910190612e5a565b5060e08201518051611c5b916004840191602090910190612ec6565b506101008201518051611c78916005840191602090910190612ec6565b506101208201516006820190611c8e9082613b45565b50505060208201516007820180547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff909216919091179055604090910151600890910155600101611a6c565b606081600001805480602002602001604051908101604052809291908181526020018280548015611d3457602002820191906000526020600020905b815481526020019060010190808311611d20575b50505050509050919050565b60008181526001830160205260408120548015611e29576000611d646001836137c0565b8554909150600090611d78906001906137c0565b9050808214611ddd576000866000018281548110611d9857611d986137d3565b9060005260206000200154905080876000018481548110611dbb57611dbb6137d3565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080611dee57611dee61408b565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506102db565b60009150506102db565b5092915050565b6000818152600183016020526040812054611e81575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556102db565b5060006102db565b60006002821115611ec9576040517f3e4785260000000000000000000000000000000000000000000000000000000081526004810183905260240161082e565b8160028111156102db576102db613148565b6000826002811115611eef57611eef613148565b826002811115611f0157611f01613148565b611f0b91906140ba565b90508060011480611f575750807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff148015611f5757506002836002811115611f5557611f55613148565b145b15611f6157505050565b82826040517f0a6b675b00000000000000000000000000000000000000000000000000000000815260040161082e9291906140ea565b60606000845167ffffffffffffffff811115611fb557611fb561377e565b604051908082528060200260200182016040528015611fde578160200160208202803683370190505b5090506000846002811115611ff557611ff5613148565b1480156120135750600183600281111561201157612011613148565b145b156120545760018160008151811061202d5761202d6137d3565b602002602001019067ffffffffffffffff16908167ffffffffffffffff16815250506121bc565b600184600281111561206857612068613148565b1480156120865750600283600281111561208457612084613148565b145b1561211d578560008151811061209e5761209e6137d3565b602002602001015160200151816000815181106120bd576120bd6137d3565b602002602001019067ffffffffffffffff16908167ffffffffffffffff1681525050856000815181106120f2576120f26137d3565b602002602001015160200151600161210a9190614105565b8160018151811061202d5761202d6137d3565b600284600281111561213157612131613148565b14801561214f5750600183600281111561214d5761214d613148565b145b156121865785600181518110612167576121676137d3565b6020026020010151602001518160008151811061202d5761202d6137d3565b83836040517f0a6b675b00000000000000000000000000000000000000000000000000000000815260040161082e9291906140ea565b6000855167ffffffffffffffff8111156121d8576121d861377e565b60405190808252806020026020018201604052801561228e57816020015b604080516101a081018252600060608083018281526080840183905260a0840183905260c0840183905260e084018290526101008401829052610120840182905261014084018290526101608401829052610180840191909152825260208083018290529282015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816121f65790505b50905060005b8251811015612377576122bf8782815181106122b2576122b26137d3565b6020026020010151612702565b60405180606001604052808883815181106122dc576122dc6137d3565b602002602001015181526020018483815181106122fb576122fb6137d3565b602002602001015167ffffffffffffffff16815260200161234f8b868581518110612328576123286137d3565b60200260200101518b8681518110612342576123426137d3565b6020026020010151612adf565b815250828281518110612364576123646137d3565b6020908102919091010152600101612294565b50979650505050505050565b81518151811580156123955750806001145b1561243757826000815181106123ad576123ad6137d3565b60200260200101516020015167ffffffffffffffff1660011461243157826000815181106123dd576123dd6137d3565b60209081029190910181015101516040517fc1658eb800000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526001602482015260440161082e565b50505050565b8160011480156124475750806002145b156125fd578360008151811061245f5761245f6137d3565b6020026020010151604001518360008151811061247e5761247e6137d3565b6020026020010151604001511461250a57826000815181106124a2576124a26137d3565b602002602001015160400151846000815181106124c1576124c16137d3565b6020026020010151604001516040517fc7ccdd7f00000000000000000000000000000000000000000000000000000000815260040161082e929190918252602082015260400190565b8360008151811061251d5761251d6137d3565b60200260200101516020015160016125359190614105565b67ffffffffffffffff1683600181518110612552576125526137d3565b60200260200101516020015167ffffffffffffffff16146124315782600181518110612580576125806137d3565b6020026020010151602001518460008151811061259f5761259f6137d3565b60200260200101516020015160016125b79190614105565b6040517fc1658eb800000000000000000000000000000000000000000000000000000000815267ffffffffffffffff92831660048201529116602482015260440161082e565b81600214801561260d5750806001145b156126d05783600181518110612625576126256137d3565b60200260200101516040015183600081518110612644576126446137d3565b602002602001015160400151146124315782600081518110612668576126686137d3565b60200260200101516040015184600181518110612687576126876137d3565b6020026020010151604001516040517f9e97567000000000000000000000000000000000000000000000000000000000815260040161082e929190918252602082015260400190565b6040517f1f1b2bb600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806020015167ffffffffffffffff1660000361274a576040517f698cf8e000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008151600181111561275f5761275f613148565b14158015612780575060018151600181111561277d5761277d613148565b14155b156127b7576040517f3302dbd700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060800151516000036127f6576040517f358c192700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208101516128119060039067ffffffffffffffff16611138565b6128595760208101516040517f1bd4d2d200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260240161082e565b60e081015151601f1015612899576040517f1b925da600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61010081015151601f10156128da576040517f645960ff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208082015167ffffffffffffffff1660009081526002909152604081206001015461290a9060ff166003614126565b612915906001614142565b60ff1690508082610100015151101561296c57610100820151516040517f548dd21f00000000000000000000000000000000000000000000000000000000815260048101919091526024810182905260440161082e565b816040015160ff166000036129ad576040517f39d1a4d000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408201516129bd906003614126565b60ff168260e0015151116129fd576040517f4856694e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8160e00151518260c0015151141580612a215750816101000151518260c001515114155b15612a7c5760c08201515160e083015151610100840151516040517fba900f6d00000000000000000000000000000000000000000000000000000000815260048101939093526024830191909152604482015260640161082e565b8160c00151518260a00151511115612ac0576040517f8473d80700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612ad28260a001518360c00151612bb4565b6112a48260c0015161115c565b60008082602001518584600001518560800151878760a001518860c001518960e001518a61010001518b604001518c606001518d6101200151604051602001612b339c9b9a9998979695949392919061415b565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e0a000000000000000000000000000000000000000000000000000000000000179150509392505050565b81511580612bc157508051155b15612bf8576040517fe249684100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612c0182612d2f565b612c0a81612d2f565b6000805b835182108015612c1e5750825181105b15612cf057828181518110612c3557612c356137d3565b6020026020010151848381518110612c4f57612c4f6137d3565b60200260200101511115612c6d57612c6681614053565b9050612c0e565b828181518110612c7f57612c7f6137d3565b6020026020010151848381518110612c9957612c996137d3565b602002602001015103612cba57612caf82614053565b9150612c6681614053565b83836040517fd671700c00000000000000000000000000000000000000000000000000000000815260040161082e92919061423b565b83518210156124315783836040517fd671700c00000000000000000000000000000000000000000000000000000000815260040161082e92919061423b565b60015b81518110156112a45781612d476001836137c0565b81518110612d5757612d576137d3565b6020026020010151828281518110612d7157612d716137d3565b602002602001015111612db257816040517f1bc41b4200000000000000000000000000000000000000000000000000000000815260040161082e9190614260565b600101612d32565b6040518060400160405280600067ffffffffffffffff168152602001612dfd604051806060016040528060608152602001600060ff168152602001606081525090565b905290565b5080546000825590600052602060002090810190610b459190612f18565b508054612e2c906136e5565b6000825580601f10612e3c575050565b601f016020900490600052602060002090810190610b459190612f18565b828054828255906000526020600020908101928215612e95579160200282015b82811115612e95578251825591602001919060010190612e7a565b50612ea1929150612f18565b5090565b5080546000825560090290600052602060002090810190610b459190612f2d565b828054828255906000526020600020908101928215612f0c579160200282015b82811115612f0c5782518290612efc9082613b45565b5091602001919060010190612ee6565b50612ea1929150612fee565b5b80821115612ea15760008155600101612f19565b80821115612ea15780547fffffffffffffffffffffffffffff00000000000000000000000000000000000016815560008181612f6c6001830182612e20565b612f7a600283016000612e02565b612f88600383016000612e02565b612f9660048301600061300b565b612fa460058301600061300b565b612fb2600683016000612e20565b5050506007810180547fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000016905560006008820155600901612f2d565b80821115612ea15760006130028282612e20565b50600101612fee565b5080546000825590600052602060002090810190610b459190612fee565b60006020828403121561303b57600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610fb957600080fd5b6000815180845260005b8181101561309157602081850181015186830182015201613075565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000610fb9602083018461306b565b63ffffffff81168114610b4557600080fd5b80356130ff816130e2565b919050565b8035600281106130ff57600080fd5b6000806040838503121561312657600080fd5b8235613131816130e2565b915061313f60208401613104565b90509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6002811061318757613187613148565b9052565b60008151808452602080850194506020840160005b838110156131bc578151875295820195908201906001016131a0565b509495945050505050565b60008282518085526020808601955060208260051b8401016020860160005b84811015610b27577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe086840301895261322083835161306b565b988401989250908301906001016131e6565b600060208083018184528085518083526040925060408601915060408160051b87010184880160005b83811015613401577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08984030185528151606081518186526132a08287018251613177565b8981015160806132bb8189018367ffffffffffffffff169052565b8a830151915060a06132d1818a018460ff169052565b938301519360c092506132ef8984018667ffffffffffffffff169052565b818401519450610140915060e082818b015261330f6101a08b018761306b565b95508185015191507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0610100818c890301818d015261334e888561318b565b97508587015195506101209350818c890301848d015261336e888761318b565b9750828701519550818c890301858d015261338988876131c7565b975080870151955050808b8803016101608c01526133a787866131c7565b9650828601519550808b8803016101808c015250505050506133c9828261306b565b915050888201516133e58a87018267ffffffffffffffff169052565b509087015193870193909352938601939086019060010161325b565b509098975050505050505050565b60006020828403121561342157600080fd5b8135610fb9816130e2565b6000806040838503121561343f57600080fd5b50508035926020909101359150565b6000815160608452613463606085018261318b565b905060ff602084015116602085015260408301518482036040860152613489828261306b565b95945050505050565b600060208083018184528085518083526040925060408601915060408160051b87010184880160005b83811015613401578883037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00185528151805167ffffffffffffffff16845287015187840187905261350f8785018261344e565b95880195935050908601906001016134bb565b60006020828403121561353457600080fd5b813573ffffffffffffffffffffffffffffffffffffffff81168114610fb957600080fd5b60008083601f84011261356a57600080fd5b50813567ffffffffffffffff81111561358257600080fd5b6020830191508360208260051b850101111561359d57600080fd5b9250929050565b600080600080604085870312156135ba57600080fd5b843567ffffffffffffffff808211156135d257600080fd5b6135de88838901613558565b909650945060208701359150808211156135f757600080fd5b5061360487828801613558565b95989497509550505050565b803567ffffffffffffffff811681146130ff57600080fd5b6000806000806000806080878903121561364157600080fd5b863567ffffffffffffffff8082111561365957600080fd5b6136658a838b01613558565b9098509650602089013591508082111561367e57600080fd5b818901915089601f83011261369257600080fd5b8135818111156136a157600080fd5b8a60208285010111156136b357600080fd5b6020830196508095505050506136cb60408801613610565b91506136d9606088016130f4565b90509295509295509295565b600181811c908216806136f957607f821691505b602082108103613732577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80820281158282048414176102db576102db613738565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b808201808211156102db576102db613738565b818103818111156102db576102db613738565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561381457600080fd5b610fb982613610565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc183360301811261385157600080fd5b9190910192915050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa183360301811261385157600080fd5b604051610140810167ffffffffffffffff811182821017156138b3576138b361377e565b60405290565b60405160e0810167ffffffffffffffff811182821017156138b3576138b361377e565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156139235761392361377e565b604052919050565b600067ffffffffffffffff8211156139455761394561377e565b5060051b60200190565b600082601f83011261396057600080fd5b813560206139756139708361392b565b6138dc565b8083825260208201915060208460051b87010193508684111561399757600080fd5b602086015b848110156139b3578035835291830191830161399c565b509695505050505050565b803560ff811681146130ff57600080fd5b600082601f8301126139e057600080fd5b813567ffffffffffffffff8111156139fa576139fa61377e565b613a2b60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016138dc565b818152846020838601011115613a4057600080fd5b816020850160208301376000918101602001919091529392505050565b600060608236031215613a6f57600080fd5b6040516060810167ffffffffffffffff8282108183111715613a9357613a9361377e565b816040528435915080821115613aa857600080fd5b613ab43683870161394f565b8352613ac2602086016139be565b60208401526040850135915080821115613adb57600080fd5b50613ae8368286016139cf565b60408301525092915050565b601f821115613b40576000816000526020600020601f850160051c81016020861015613b1d5750805b601f850160051c820191505b81811015613b3c57828155600101613b29565b5050505b505050565b815167ffffffffffffffff811115613b5f57613b5f61377e565b613b7381613b6d84546136e5565b84613af4565b602080601f831160018114613bc65760008415613b905750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555613b3c565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015613c1357888601518255948401946001909101908401613bf4565b5085821015613c4f57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b67ffffffffffffffff83168152604060208201526000613c82604083018461344e565b949350505050565b600082601f830112613c9b57600080fd5b81356020613cab6139708361392b565b82815260059290921b84018101918181019086841115613cca57600080fd5b8286015b848110156139b357803567ffffffffffffffff811115613cee5760008081fd5b613cfc8986838b01016139cf565b845250918301918301613cce565b60006020808385031215613d1d57600080fd5b823567ffffffffffffffff80821115613d3557600080fd5b818501915085601f830112613d4957600080fd5b8135613d576139708261392b565b81815260059190911b83018401908481019088831115613d7657600080fd5b8585015b83811015613f0457803585811115613d9157600080fd5b8601610140818c037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0011215613dc657600080fd5b613dce61388f565b613dd9898301613104565b8152613de760408301613610565b89820152613df7606083016139be565b6040820152613e0860808301613610565b606082015260a082013587811115613e1f57600080fd5b613e2d8d8b838601016139cf565b60808301525060c082013587811115613e4557600080fd5b613e538d8b8386010161394f565b60a08301525060e082013587811115613e6b57600080fd5b613e798d8b8386010161394f565b60c0830152506101008083013588811115613e9357600080fd5b613ea18e8c83870101613c8a565b60e0840152506101208084013589811115613ebb57600080fd5b613ec98f8d83880101613c8a565b8385015250610140840135915088821115613ee357600080fd5b613ef18e8c848701016139cf565b9083015250845250918601918601613d7a565b5098975050505050505050565b80516130ff816130e2565b600082601f830112613f2d57600080fd5b81516020613f3d6139708361392b565b8083825260208201915060208460051b870101935086841115613f5f57600080fd5b602086015b848110156139b35780518352918301918301613f64565b600060208284031215613f8d57600080fd5b815167ffffffffffffffff80821115613fa557600080fd5b9083019060e08286031215613fb957600080fd5b613fc16138b9565b613fca83613f11565b8152613fd860208401613f11565b6020820152613fe960408401613f11565b6040820152606083015160608201526080830151608082015260a08301518281111561401457600080fd5b61402087828601613f1c565b60a08301525060c08301518281111561403857600080fd5b61404487828601613f1c565b60c08301525095945050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361408457614084613738565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b8181036000831280158383131683831282161715611e3357611e33613738565b6003811061318757613187613148565b604081016140f882856140da565b610fb960208301846140da565b67ffffffffffffffff818116838216019080821115611e3357611e33613738565b60ff8181168382160290811690818114611e3357611e33613738565b60ff81811683821601908111156102db576102db613738565b67ffffffffffffffff8d16815263ffffffff8c166020820152614181604082018c613177565b6101806060820152600061419961018083018c61306b565b67ffffffffffffffff8b16608084015282810360a08401526141bb818b61318b565b905082810360c08401526141cf818a61318b565b905082810360e08401526141e381896131c7565b90508281036101008401526141f881886131c7565b60ff8716610120850152905067ffffffffffffffff8516610140840152828103610160840152614228818561306b565b9f9e505050505050505050505050505050565b60408152600061424e604083018561318b565b8281036020840152613489818561318b565b602081526000610fb9602083018461318b56fea164736f6c6343000818000a", } var CCIPConfigABI = CCIPConfigMetaData.ABI diff --git a/core/gethwrappers/ccip/generated/fee_quoter/fee_quoter.go b/core/gethwrappers/ccip/generated/fee_quoter/fee_quoter.go index 807a932da6..d8f616053a 100644 --- a/core/gethwrappers/ccip/generated/fee_quoter/fee_quoter.go +++ b/core/gethwrappers/ccip/generated/fee_quoter/fee_quoter.go @@ -155,7 +155,7 @@ type KeystoneFeedsPermissionHandlerPermission struct { var FeeQuoterMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint96\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"linkToken\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"stalenessThreshold\",\"type\":\"uint32\"}],\"internalType\":\"structFeeQuoter.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"priceUpdaters\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"feeTokens\",\"type\":\"address[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"}],\"internalType\":\"structIFeeQuoter.TokenPriceFeedConfig\",\"name\":\"feedConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.TokenPriceFeedUpdate[]\",\"name\":\"tokenPriceFeeds\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigSingleTokenArgs[]\",\"name\":\"tokenTransferFeeConfigs\",\"type\":\"tuple[]\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigArgs[]\",\"name\":\"tokenTransferFeeConfigArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"internalType\":\"structFeeQuoter.PremiumMultiplierWeiPerEthArgs[]\",\"name\":\"premiumMultiplierWeiPerEthArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chain\",\"type\":\"uint64\"}],\"name\":\"ChainNotSupported\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DataFeedValueOutOfUint224Range\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"DestinationChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ExtraArgOutOfOrderExecutionMustBeTrue\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"FeeTokenNotSupported\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"}],\"name\":\"InvalidDestBytesOverhead\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidDestChainConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidEVMAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidExtraArgsTag\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidStaticConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"msgFeeJuels\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint256\"}],\"name\":\"MessageFeeTooHigh\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MessageGasLimitTooHigh\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"maxSize\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualSize\",\"type\":\"uint256\"}],\"name\":\"MessageTooLarge\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"internalType\":\"bytes10\",\"name\":\"workflowName\",\"type\":\"bytes10\"},{\"internalType\":\"bytes2\",\"name\":\"reportName\",\"type\":\"bytes2\"}],\"name\":\"ReportForwarderUnauthorized\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"SourceTokenDataTooLarge\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"threshold\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timePassed\",\"type\":\"uint256\"}],\"name\":\"StaleGasPrice\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feedTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"storedTimeStamp\",\"type\":\"uint256\"}],\"name\":\"StaleKeystoneUpdate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"TokenNotSupported\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"UnauthorizedCaller\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnsupportedNumberOfTokens\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"AuthorizedCallerAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"AuthorizedCallerRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"indexed\":false,\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"name\":\"DestChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"indexed\":false,\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"name\":\"DestChainConfigUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"}],\"name\":\"FeeTokenAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"}],\"name\":\"FeeTokenRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"name\":\"PremiumMultiplierWeiPerEthUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"}],\"indexed\":false,\"internalType\":\"structIFeeQuoter.TokenPriceFeedConfig\",\"name\":\"priceFeedConfig\",\"type\":\"tuple\"}],\"name\":\"PriceFeedPerTokenUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"reportId\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"},{\"internalType\":\"bytes10\",\"name\":\"workflowName\",\"type\":\"bytes10\"},{\"internalType\":\"bytes2\",\"name\":\"reportName\",\"type\":\"bytes2\"},{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isAllowed\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"structKeystoneFeedsPermissionHandler.Permission\",\"name\":\"permission\",\"type\":\"tuple\"}],\"name\":\"ReportPermissionSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"TokenTransferFeeConfigDeleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"name\":\"TokenTransferFeeConfigUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"UsdPerTokenUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChain\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"UsdPerUnitGasUpdated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address[]\",\"name\":\"addedCallers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"removedCallers\",\"type\":\"address[]\"}],\"internalType\":\"structAuthorizedCallers.AuthorizedCallerArgs\",\"name\":\"authorizedCallerArgs\",\"type\":\"tuple\"}],\"name\":\"applyAuthorizedCallerUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyDestChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"feeTokensToAdd\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"feeTokensToRemove\",\"type\":\"address[]\"}],\"name\":\"applyFeeTokensUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"internalType\":\"structFeeQuoter.PremiumMultiplierWeiPerEthArgs[]\",\"name\":\"premiumMultiplierWeiPerEthArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyPremiumMultiplierWeiPerEthUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigSingleTokenArgs[]\",\"name\":\"tokenTransferFeeConfigs\",\"type\":\"tuple[]\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigArgs[]\",\"name\":\"tokenTransferFeeConfigArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigRemoveArgs[]\",\"name\":\"tokensToUseDefaultFeeConfigs\",\"type\":\"tuple[]\"}],\"name\":\"applyTokenTransferFeeConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"fromToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fromTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"toToken\",\"type\":\"address\"}],\"name\":\"convertTokenAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllAuthorizedCallers\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getDestChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getDestinationChainGasPrice\",\"outputs\":[{\"components\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"internalType\":\"structInternal.TimestampedPackedUint224\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getFeeTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getPremiumMultiplierWeiPerEth\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint96\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"linkToken\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"stalenessThreshold\",\"type\":\"uint32\"}],\"internalType\":\"structFeeQuoter.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getTokenAndGasPrices\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"tokenPrice\",\"type\":\"uint224\"},{\"internalType\":\"uint224\",\"name\":\"gasPriceValue\",\"type\":\"uint224\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenPrice\",\"outputs\":[{\"components\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"internalType\":\"structInternal.TimestampedPackedUint224\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenPriceFeedConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"}],\"internalType\":\"structIFeeQuoter.TokenPriceFeedConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"tokens\",\"type\":\"address[]\"}],\"name\":\"getTokenPrices\",\"outputs\":[{\"components\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"internalType\":\"structInternal.TimestampedPackedUint224[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenTransferFeeConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"getValidatedFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getValidatedTokenPrice\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"\",\"type\":\"uint224\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"onReport\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"name\":\"processMessageArgs\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"msgFeeJuels\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isOutOfOrderExecution\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"convertedExtraArgs\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"rampTokenAmounts\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"sourceTokenAmounts\",\"type\":\"tuple[]\"}],\"name\":\"processPoolReturnData\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"destExecDataPerToken\",\"type\":\"bytes[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"},{\"internalType\":\"bytes10\",\"name\":\"workflowName\",\"type\":\"bytes10\"},{\"internalType\":\"bytes2\",\"name\":\"reportName\",\"type\":\"bytes2\"},{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isAllowed\",\"type\":\"bool\"}],\"internalType\":\"structKeystoneFeedsPermissionHandler.Permission[]\",\"name\":\"permissions\",\"type\":\"tuple[]\"}],\"name\":\"setReportPermissions\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"}],\"name\":\"updatePrices\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"}],\"internalType\":\"structIFeeQuoter.TokenPriceFeedConfig\",\"name\":\"feedConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.TokenPriceFeedUpdate[]\",\"name\":\"tokenPriceFeedUpdates\",\"type\":\"tuple[]\"}],\"name\":\"updateTokenPriceFeeds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x60e06040523480156200001157600080fd5b506040516200775238038062007752833981016040819052620000349162001834565b8533806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf8162000207565b5050604080518082018252838152815160008152602080820190935291810191909152620000ee9150620002b2565b5060208701516001600160a01b0316158062000112575086516001600160601b0316155b80620001265750604087015163ffffffff16155b15620001455760405163d794ef9560e01b815260040160405180910390fd5b6020878101516001600160a01b031660a05287516001600160601b031660805260408089015163ffffffff1660c05280516000815291820190526200018c90869062000401565b620001978462000549565b620001a2816200061a565b620001ad8262000a5a565b60408051600080825260208201909252620001fa91859190620001f3565b6040805180820190915260008082526020820152815260200190600190039081620001cb5790505b5062000b26565b5050505050505062001ae5565b336001600160a01b03821603620002615760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b602081015160005b815181101562000342576000828281518110620002db57620002db62001953565b60209081029190910101519050620002f560028262000e5f565b1562000338576040516001600160a01b03821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b50600101620002ba565b50815160005b8151811015620003fb57600082828151811062000369576200036962001953565b6020026020010151905060006001600160a01b0316816001600160a01b031603620003a7576040516342bcdf7f60e11b815260040160405180910390fd5b620003b460028262000e7f565b506040516001600160a01b03821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a15060010162000348565b50505050565b60005b8251811015620004a2576200044083828151811062000427576200042762001953565b6020026020010151600b62000e7f60201b90919060201c565b1562000499578281815181106200045b576200045b62001953565b60200260200101516001600160a01b03167fdf1b1bd32a69711488d71554706bb130b1fc63a5fa1a2cd85e8440f84065ba2360405160405180910390a25b60010162000404565b5060005b81518110156200054457620004e2828281518110620004c957620004c962001953565b6020026020010151600b62000e9660201b90919060201c565b156200053b57818181518110620004fd57620004fd62001953565b60200260200101516001600160a01b03167f1795838dc8ab2ffc5f431a1729a6afa0b587f982f7b2be0b9d7187a1ef547f9160405160405180910390a25b600101620004a6565b505050565b60005b8151811015620006165760008282815181106200056d576200056d62001953565b6020908102919091018101518051818301516001600160a01b0380831660008181526007875260409081902084518154868a018051929096166001600160a81b03199091168117600160a01b60ff9384160217909255825191825293519093169683019690965293955091939092917f08a5f7f5bb38a81d8e43aca13ecd76431dbf8816ae4699affff7b00b2fc1c464910160405180910390a25050508060010190506200054c565b5050565b60005b8151811015620006165760008282815181106200063e576200063e62001953565b6020026020010151905060008383815181106200065f576200065f62001953565b6020026020010151600001519050600082602001519050816001600160401b03166000148062000698575061016081015163ffffffff16155b80620006ba57506101e08101516001600160e01b031916630a04b54b60e21b14155b80620006da5750806060015163ffffffff1681610160015163ffffffff16115b15620007055760405163c35aa79d60e01b81526001600160401b038316600482015260240162000083565b6001600160401b038216600090815260096020526040812060010154600160881b900460e01b6001600160e01b03191690036200078557816001600160401b03167fd31c671936387b2f84ed402b553bd50c0e9c20408ea4e91a836d77b8180fb7248260405162000777919062001969565b60405180910390a2620007c9565b816001600160401b03167f1edd6f3553cfa16f10b95b195abae3a1cfca4783de4843f95d674b1e1df5ab2082604051620007c0919062001969565b60405180910390a25b8060096000846001600160401b03166001600160401b0316815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548161ffff021916908361ffff16021790555060408201518160000160036101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160076101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600b6101000a81548163ffffffff021916908363ffffffff16021790555060a082015181600001600f6101000a81548161ffff021916908361ffff16021790555060c08201518160000160116101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160000160156101000a81548161ffff021916908361ffff1602179055506101008201518160000160176101000a81548161ffff021916908361ffff1602179055506101208201518160000160196101000a81548161ffff021916908361ffff16021790555061014082015181600001601b6101000a81548163ffffffff021916908363ffffffff1602179055506101608201518160010160006101000a81548163ffffffff021916908363ffffffff1602179055506101808201518160010160046101000a8154816001600160401b0302191690836001600160401b031602179055506101a082015181600101600c6101000a81548163ffffffff021916908363ffffffff1602179055506101c08201518160010160106101000a81548160ff0219169083151502179055506101e08201518160010160116101000a81548163ffffffff021916908360e01c02179055509050505050508060010190506200061d565b60005b81518110156200061657600082828151811062000a7e5762000a7e62001953565b6020026020010151600001519050600083838151811062000aa35762000aa362001953565b6020908102919091018101518101516001600160a01b03841660008181526008845260409081902080546001600160401b0319166001600160401b0385169081179091559051908152919350917fbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d910160405180910390a2505060010162000a5d565b60005b825181101562000d9957600083828151811062000b4a5762000b4a62001953565b6020026020010151905060008160000151905060005b82602001515181101562000d8a5760008360200151828151811062000b895762000b8962001953565b602002602001015160200151905060008460200151838151811062000bb25762000bb262001953565b6020026020010151600001519050602063ffffffff16826080015163ffffffff16101562000c115760808201516040516312766e0160e11b81526001600160a01b038316600482015263ffffffff909116602482015260440162000083565b6001600160401b0384166000818152600a602090815260408083206001600160a01b0386168085529083529281902086518154938801518389015160608a015160808b015160a08c01511515600160901b0260ff60901b1963ffffffff928316600160701b021664ffffffffff60701b199383166a01000000000000000000000263ffffffff60501b1961ffff90961668010000000000000000029590951665ffffffffffff60401b19968416640100000000026001600160401b0319909b16939097169290921798909817939093169390931717919091161792909217909155519091907f94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b59062000d77908690600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60405180910390a3505060010162000b60565b50505080600101905062000b29565b5060005b81518110156200054457600082828151811062000dbe5762000dbe62001953565b6020026020010151600001519050600083838151811062000de35762000de362001953565b6020908102919091018101518101516001600160401b0384166000818152600a845260408082206001600160a01b038516808452955280822080546001600160981b03191690555192945090917f4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b9190a3505060010162000d9d565b600062000e76836001600160a01b03841662000ead565b90505b92915050565b600062000e76836001600160a01b03841662000fb1565b600062000e76836001600160a01b03841662001003565b6000818152600183016020526040812054801562000fa657600062000ed460018362001aad565b855490915060009062000eea9060019062001aad565b905081811462000f5657600086600001828154811062000f0e5762000f0e62001953565b906000526020600020015490508087600001848154811062000f345762000f3462001953565b6000918252602080832090910192909255918252600188019052604090208390555b855486908062000f6a5762000f6a62001acf565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505062000e79565b600091505062000e79565b600081815260018301602052604081205462000ffa5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000e79565b50600062000e79565b6000818152600183016020526040812054801562000fa65760006200102a60018362001aad565b8554909150600090620010409060019062001aad565b905080821462000f5657600086600001828154811062000f0e5762000f0e62001953565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b03811182821017156200109f576200109f62001064565b60405290565b60405160c081016001600160401b03811182821017156200109f576200109f62001064565b60405161020081016001600160401b03811182821017156200109f576200109f62001064565b604051601f8201601f191681016001600160401b03811182821017156200111b576200111b62001064565b604052919050565b80516001600160a01b03811681146200113b57600080fd5b919050565b805163ffffffff811681146200113b57600080fd5b6000606082840312156200116857600080fd5b604051606081016001600160401b03811182821017156200118d576200118d62001064565b604052825190915081906001600160601b0381168114620011ad57600080fd5b8152620011bd6020840162001123565b6020820152620011d06040840162001140565b60408201525092915050565b60006001600160401b03821115620011f857620011f862001064565b5060051b60200190565b600082601f8301126200121457600080fd5b815160206200122d6200122783620011dc565b620010f0565b8083825260208201915060208460051b8701019350868411156200125057600080fd5b602086015b848110156200127757620012698162001123565b835291830191830162001255565b509695505050505050565b600082601f8301126200129457600080fd5b81516020620012a76200122783620011dc565b82815260609283028501820192828201919087851115620012c757600080fd5b8387015b858110156200135a5780890382811215620012e65760008081fd5b620012f06200107a565b620012fb8362001123565b8152604080601f1984011215620013125760008081fd5b6200131c6200107a565b92506200132b88850162001123565b835283015160ff81168114620013415760008081fd5b82880152808701919091528452928401928101620012cb565b5090979650505050505050565b80516001600160401b03811681146200113b57600080fd5b805161ffff811681146200113b57600080fd5b805180151581146200113b57600080fd5b600082601f830112620013b557600080fd5b81516020620013c86200122783620011dc565b82815260059290921b84018101918181019086841115620013e857600080fd5b8286015b84811015620012775780516001600160401b03808211156200140d57600080fd5b908801906040601f19838c0381018213156200142857600080fd5b620014326200107a565b6200143f89860162001367565b815282850151848111156200145357600080fd5b8086019550508c603f8601126200146957600080fd5b8885015193506200147e6200122785620011dc565b84815260e09094028501830193898101908e8611156200149d57600080fd5b958401955b858710156200157657868f0360e0811215620014bd57600080fd5b620014c76200107a565b620014d28962001123565b815260c08683011215620014e557600080fd5b620014ef620010a5565b9150620014fe8d8a0162001140565b82526200150d878a0162001140565b8d8301526200151f60608a016200137f565b878301526200153160808a0162001140565b60608301526200154460a08a0162001140565b60808301526200155760c08a0162001392565b60a0830152808d0191909152825260e09690960195908a0190620014a2565b828b015250875250505092840192508301620013ec565b600082601f8301126200159f57600080fd5b81516020620015b26200122783620011dc565b82815260069290921b84018101918181019086841115620015d257600080fd5b8286015b84811015620012775760408189031215620015f15760008081fd5b620015fb6200107a565b620016068262001123565b81526200161585830162001367565b81860152835291830191604001620015d6565b80516001600160e01b0319811681146200113b57600080fd5b600082601f8301126200165357600080fd5b81516020620016666200122783620011dc565b82815261022092830285018201928282019190878511156200168757600080fd5b8387015b858110156200135a5780890382811215620016a65760008081fd5b620016b06200107a565b620016bb8362001367565b815261020080601f1984011215620016d35760008081fd5b620016dd620010ca565b9250620016ec88850162001392565b83526040620016fd8186016200137f565b8985015260606200171081870162001140565b82860152608091506200172582870162001140565b9085015260a06200173886820162001140565b8286015260c091506200174d8287016200137f565b9085015260e06200176086820162001140565b828601526101009150620017768287016200137f565b908501526101206200178a8682016200137f565b828601526101409150620017a08287016200137f565b90850152610160620017b486820162001140565b828601526101809150620017ca82870162001140565b908501526101a0620017de86820162001367565b828601526101c09150620017f482870162001140565b908501526101e06200180886820162001392565b828601526200181983870162001628565b9085015250508087019190915284529284019281016200168b565b6000806000806000806000610120888a0312156200185157600080fd5b6200185d898962001155565b60608901519097506001600160401b03808211156200187b57600080fd5b620018898b838c0162001202565b975060808a0151915080821115620018a057600080fd5b620018ae8b838c0162001202565b965060a08a0151915080821115620018c557600080fd5b620018d38b838c0162001282565b955060c08a0151915080821115620018ea57600080fd5b620018f88b838c01620013a3565b945060e08a01519150808211156200190f57600080fd5b6200191d8b838c016200158d565b93506101008a01519150808211156200193557600080fd5b50620019448a828b0162001641565b91505092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b815115158152610200810160208301516200198a602084018261ffff169052565b506040830151620019a3604084018263ffffffff169052565b506060830151620019bc606084018263ffffffff169052565b506080830151620019d5608084018263ffffffff169052565b5060a0830151620019ec60a084018261ffff169052565b5060c083015162001a0560c084018263ffffffff169052565b5060e083015162001a1c60e084018261ffff169052565b506101008381015161ffff9081169184019190915261012080850151909116908301526101408084015163ffffffff9081169184019190915261016080850151821690840152610180808501516001600160401b0316908401526101a080850151909116908301526101c0808401511515908301526101e0928301516001600160e01b031916929091019190915290565b8181038181111562000e7957634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b60805160a05160c051615c1362001b3f600039600081816102ef0152818161220b01526122740152600081816102b301528181611917015261197701526000818161027f015281816119a00152611a100152615c136000f3fe608060405234801561001057600080fd5b50600436106101ce5760003560e01c806379ba509711610104578063a69c64c0116100a2578063d02641a011610071578063d02641a014610a81578063d8694ccd14610a94578063f2fde38b14610aa7578063ffdb4b3714610aba57600080fd5b8063a69c64c014610997578063bf78e03f146109aa578063c4276bfc14610a57578063cdc73d5114610a7957600080fd5b806382b49eb0116100de57806382b49eb0146107d95780638da5cb5b1461094957806391a2749a146109715780639ea600261461098457600080fd5b806379ba5097146107ab5780637afac322146107b3578063805f2132146107c657600080fd5b8063407e1086116101715780634ab35b0b1161014b5780634ab35b0b14610441578063514e8cff146104815780636def4ce714610524578063770e2dc41461079857600080fd5b8063407e1086146103fb57806341ed29e71461040e57806345ac924d1461042157600080fd5b8063085318f8116101ad578063085318f814610368578063181f5a77146103885780632451a627146103d15780633937306f146103e657600080fd5b806241e5be146101d3578063061877e3146101f957806306285c6914610252575b600080fd5b6101e66101e13660046142ca565b610b02565b6040519081526020015b60405180910390f35b610239610207366004614306565b73ffffffffffffffffffffffffffffffffffffffff1660009081526008602052604090205467ffffffffffffffff1690565b60405167ffffffffffffffff90911681526020016101f0565b61031c604080516060810182526000808252602082018190529181019190915260405180606001604052807f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000063ffffffff16815250905090565b6040805182516bffffffffffffffffffffffff16815260208084015173ffffffffffffffffffffffffffffffffffffffff16908201529181015163ffffffff16908201526060016101f0565b61037b61037636600461437e565b610b70565b6040516101f09190614490565b6103c46040518060400160405280601381526020017f46656551756f74657220312e362e302d6465760000000000000000000000000081525081565b6040516101f09190614512565b6103d9610ee2565b6040516101f09190614525565b6103f96103f436600461457f565b610ef3565b005b6103f9610409366004614721565b6111a8565b6103f961041c366004614853565b6111bc565b61043461042f36600461498e565b6111fe565b6040516101f091906149d0565b61045461044f366004614306565b6112c9565b6040517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff90911681526020016101f0565b61051761048f366004614a4b565b60408051808201909152600080825260208201525067ffffffffffffffff166000908152600560209081526040918290208251808401909352547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811683527c0100000000000000000000000000000000000000000000000000000000900463ffffffff169082015290565b6040516101f09190614a66565b61078b610532366004614a4b565b6040805161020081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a081018290526101c081018290526101e08101919091525067ffffffffffffffff908116600090815260096020908152604091829020825161020081018452815460ff8082161515835261ffff61010080840482169685019690965263ffffffff630100000084048116978501979097526701000000000000008304871660608501526b0100000000000000000000008304871660808501526f010000000000000000000000000000008304811660a085015271010000000000000000000000000000000000808404881660c086015275010000000000000000000000000000000000000000008404821660e08087019190915277010000000000000000000000000000000000000000000000850483169786019790975279010000000000000000000000000000000000000000000000000084049091166101208501527b01000000000000000000000000000000000000000000000000000000909204861661014084015260019093015480861661016084015264010000000081049096166101808301526c0100000000000000000000000086049094166101a0820152700100000000000000000000000000000000850490911615156101c08201527fffffffff0000000000000000000000000000000000000000000000000000000092909304901b166101e082015290565b6040516101f09190614aa1565b6103f96107a6366004614cb8565b6112d4565b6103f96112e6565b6103f96107c1366004614fd2565b6113e3565b6103f96107d4366004615078565b6113f5565b6108e96107e73660046150e4565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101919091525067ffffffffffffffff919091166000908152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff94909416835292815290829020825160c081018452905463ffffffff8082168352640100000000820481169383019390935268010000000000000000810461ffff16938201939093526a01000000000000000000008304821660608201526e01000000000000000000000000000083049091166080820152720100000000000000000000000000000000000090910460ff16151560a082015290565b6040516101f09190600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101f0565b6103f961097f36600461510e565b6118dd565b6103f96109923660046151cf565b6118ee565b6103f96109a53660046153dc565b6118ff565b610a236109b8366004614306565b6040805180820182526000808252602091820181905273ffffffffffffffffffffffffffffffffffffffff93841681526007825282902082518084019093525492831682527401000000000000000000000000000000000000000090920460ff169181019190915290565b60408051825173ffffffffffffffffffffffffffffffffffffffff16815260209283015160ff1692810192909252016101f0565b610a6a610a653660046154a1565b611910565b6040516101f093929190615510565b6103d9611b06565b610517610a8f366004614306565b611b12565b6101e6610aa2366004615531565b611c0e565b6103f9610ab5366004614306565b612126565b610acd610ac8366004615586565b612137565b604080517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff9384168152929091166020830152016101f0565b6000610b0d826122c2565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16610b34856122c2565b610b5c907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16856155df565b610b6691906155f6565b90505b9392505050565b67ffffffffffffffff8086166000908152600960205260409020600101546060917101000000000000000000000000000000000090910460e01b908590811115610bbc57610bbc6145ba565b604051908082528060200260200182016040528015610bef57816020015b6060815260200190600190039081610bda5790505b50915060005b85811015610ed7576000858583818110610c1157610c11615631565b610c279260206040909202019081019150614306565b90506000888884818110610c3d57610c3d615631565b9050602002810190610c4f9190615660565b610c5d90604081019061569e565b9150506020811115610d125767ffffffffffffffff8a166000908152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff861684529091529020546e010000000000000000000000000000900463ffffffff16811115610d12576040517f36f536ca00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526024015b60405180910390fd5b610d82848a8a86818110610d2857610d28615631565b9050602002810190610d3a9190615660565b610d4890602081019061569e565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061235c92505050565b67ffffffffffffffff8a166000818152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684528252808320815160c081018352905463ffffffff8082168352640100000000820481168386015268010000000000000000820461ffff16838501526a01000000000000000000008204811660608401526e010000000000000000000000000000820481166080840152720100000000000000000000000000000000000090910460ff16151560a08301908152958552600990935290832054935190937b0100000000000000000000000000000000000000000000000000000090049091169190610e815781610e87565b82606001515b6040805163ffffffff8316602082015291925001604051602081830303815290604052888781518110610ebc57610ebc615631565b60200260200101819052505050505050806001019050610bf5565b505095945050505050565b6060610eee60026123b3565b905090565b610efb6123c0565b6000610f078280615703565b9050905060005b81811015611051576000610f228480615703565b83818110610f3257610f32615631565b905060400201803603810190610f489190615797565b604080518082018252602080840180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff908116845263ffffffff42818116858701908152885173ffffffffffffffffffffffffffffffffffffffff9081166000908152600690975295889020965190519092167c010000000000000000000000000000000000000000000000000000000002919092161790935584519051935194955016927f52f50aa6d1a95a4595361ecf953d095f125d442e4673716dede699e049de148a926110409290917bffffffffffffffffffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b60405180910390a250600101610f0e565b5060006110616020840184615703565b9050905060005b818110156111a257600061107f6020860186615703565b8381811061108f5761108f615631565b9050604002018036038101906110a591906157d4565b604080518082018252602080840180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff908116845263ffffffff42818116858701908152885167ffffffffffffffff9081166000908152600590975295889020965190519092167c010000000000000000000000000000000000000000000000000000000002919092161790935584519051935194955016927fdd84a3fa9ef9409f550d54d6affec7e9c480c878c6ab27b78912a03e1b371c6e926111919290917bffffffffffffffffffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b60405180910390a250600101611068565b50505050565b6111b0612405565b6111b981612486565b50565b6111c4612405565b60005b81518110156111fa576111f28282815181106111e5576111e5615631565b6020026020010151612584565b6001016111c7565b5050565b60608160008167ffffffffffffffff81111561121c5761121c6145ba565b60405190808252806020026020018201604052801561126157816020015b604080518082019091526000808252602082015281526020019060019003908161123a5790505b50905060005b828110156112be5761129986868381811061128457611284615631565b9050602002016020810190610a8f9190614306565b8282815181106112ab576112ab615631565b6020908102919091010152600101611267565b509150505b92915050565b60006112c3826122c2565b6112dc612405565b6111fa8282612756565b60015473ffffffffffffffffffffffffffffffffffffffff163314611367576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610d09565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6113eb612405565b6111fa8282612b63565b600080600061143987878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612caa92505050565b92509250925061144b33838584612cc5565b6000611459858701876157f7565b905060005b81518110156118d25760006007600084848151811061147f5761147f615631565b6020908102919091018101515173ffffffffffffffffffffffffffffffffffffffff16825281019190915260400160009081205474010000000000000000000000000000000000000000900460ff169150819003611540578282815181106114e9576114e9615631565b6020908102919091010151516040517f06439c6b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610d09565b600061158960128386868151811061155a5761155a615631565b6020026020010151602001517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16612e1d565b9050600660008585815181106115a1576115a1615631565b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001601c9054906101000a900463ffffffff1663ffffffff1684848151811061161357611613615631565b60200260200101516040015163ffffffff16101561171d5783838151811061163d5761163d615631565b60200260200101516000015184848151811061165b5761165b615631565b6020026020010151604001516006600087878151811061167d5761167d615631565b6020908102919091018101515173ffffffffffffffffffffffffffffffffffffffff90811683529082019290925260409081016000205490517f191ec70600000000000000000000000000000000000000000000000000000000815293909116600484015263ffffffff91821660248401527c01000000000000000000000000000000000000000000000000000000009004166044820152606401610d09565b6040518060400160405280827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16815260200185858151811061175e5761175e615631565b60200260200101516040015163ffffffff168152506006600086868151811061178957611789615631565b6020908102919091018101515173ffffffffffffffffffffffffffffffffffffffff168252818101929092526040016000208251929091015163ffffffff167c0100000000000000000000000000000000000000000000000000000000027bffffffffffffffffffffffffffffffffffffffffffffffffffffffff909216919091179055835184908490811061182157611821615631565b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff167f52f50aa6d1a95a4595361ecf953d095f125d442e4673716dede699e049de148a8286868151811061187757611877615631565b6020026020010151604001516040516118c09291907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff92909216825263ffffffff16602082015260400190565b60405180910390a2505060010161145e565b505050505050505050565b6118e5612405565b6111b981612ee3565b6118f6612405565b6111b98161306f565b611907612405565b6111b981613515565b60008060607f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff16036119705785925061199e565b61199b87877f0000000000000000000000000000000000000000000000000000000000000000610b02565b92505b7f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff16831115611a3d576040517f6a92a483000000000000000000000000000000000000000000000000000000008152600481018490526bffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166024820152604401610d09565b67ffffffffffffffff881660009081526009602052604081206001015463ffffffff1690611a6c8787846135ff565b9050806020015193508484611af3836040805182516024820152602092830151151560448083019190915282518083039091018152606490910190915290810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f181dcf100000000000000000000000000000000000000000000000000000000017905290565b9450945094505050955095509592505050565b6060610eee600b6123b3565b604080518082019091526000808252602082015273ffffffffffffffffffffffffffffffffffffffff8281166000908152600760209081526040918290208251808401909352549283168083527401000000000000000000000000000000000000000090930460ff169082015290611c0557505073ffffffffffffffffffffffffffffffffffffffff166000908152600660209081526040918290208251808401909352547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811683527c0100000000000000000000000000000000000000000000000000000000900463ffffffff169082015290565b610b69816137a8565b67ffffffffffffffff8083166000908152600960209081526040808320815161020081018352815460ff808216151580845261ffff61010080850482169886019890985263ffffffff630100000085048116978601979097526701000000000000008404871660608601526b0100000000000000000000008404871660808601526f010000000000000000000000000000008404811660a086015271010000000000000000000000000000000000808504881660c087015275010000000000000000000000000000000000000000008504821660e08088019190915277010000000000000000000000000000000000000000000000860483169987019990995279010000000000000000000000000000000000000000000000000085049091166101208601527b01000000000000000000000000000000000000000000000000000000909304861661014085015260019094015480861661016085015264010000000081049098166101808401526c0100000000000000000000000088049094166101a0830152700100000000000000000000000000000000870490931615156101c08201527fffffffff000000000000000000000000000000000000000000000000000000009290950490921b166101e0840152909190611e28576040517f99ac52f200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff85166004820152602401610d09565b611e43611e3b6080850160608601614306565b600b90613937565b611ea257611e576080840160608501614306565b6040517f2502348c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610d09565b6000611eb16040850185615703565b9150611f0d905082611ec6602087018761569e565b905083611ed3888061569e565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061396692505050565b6000600881611f226080880160608901614306565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160009081205467ffffffffffffffff16915080611f71611f6b6080890160608a01614306565b89612137565b9092509050600080808615611fb757611fab888c611f9560808e0160608f01614306565b888e8060400190611fa69190615703565b613a10565b91945092509050611fd7565b6101a0880151611fd49063ffffffff16662386f26fc100006155df565b92505b61010088015160009061ffff161561201b57612018896dffffffffffffffffffffffffffff607088901c1661200f60208f018f61569e565b90508b86613ce8565b90505b61018089015160009067ffffffffffffffff1661204461203e60808f018f61569e565b8d613d98565b600001518563ffffffff168c60a0015161ffff168f8060200190612068919061569e565b6120739291506155df565b8d6080015163ffffffff1661208891906158be565b61209291906158be565b61209c91906158be565b6120b6906dffffffffffffffffffffffffffff89166155df565b6120c091906155df565b90507bffffffffffffffffffffffffffffffffffffffffffffffffffffffff871682826120f767ffffffffffffffff8c16896155df565b61210191906158be565b61210b91906158be565b61211591906155f6565b9d9c50505050505050505050505050565b61212e612405565b6111b981613e59565b67ffffffffffffffff811660009081526005602090815260408083208151808301909252547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811682527c0100000000000000000000000000000000000000000000000000000000900463ffffffff16918101829052829182036121ef576040517f2e59db3a00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff85166004820152602401610d09565b6000816020015163ffffffff164261220791906158d1565b90507f000000000000000000000000000000000000000000000000000000000000000063ffffffff168111156122a8576040517ff08bcb3e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8616600482015263ffffffff7f000000000000000000000000000000000000000000000000000000000000000016602482015260448101829052606401610d09565b6122b1866122c2565b9151919350909150505b9250929050565b6000806122ce83611b12565b9050806020015163ffffffff1660001480612306575080517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16155b15612355576040517f06439c6b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152602401610d09565b5192915050565b7fd7ed2ad4000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316016111fa576123ae81613f4e565b505050565b60606000610b6983614001565b6123cb600233613937565b612403576040517fd86ad9cf000000000000000000000000000000000000000000000000000000008152336004820152602401610d09565b565b60005473ffffffffffffffffffffffffffffffffffffffff163314612403576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610d09565b60005b81518110156111fa5760008282815181106124a6576124a6615631565b60209081029190910181015180518183015173ffffffffffffffffffffffffffffffffffffffff80831660008181526007875260409081902084518154868a018051929096167fffffffffffffffffffffff00000000000000000000000000000000000000000090911681177401000000000000000000000000000000000000000060ff9384160217909255825191825293519093169683019690965293955091939092917f08a5f7f5bb38a81d8e43aca13ecd76431dbf8816ae4699affff7b00b2fc1c464910160405180910390a2505050806001019050612489565b600061263d82600001518360600151846020015185604001516040805173ffffffffffffffffffffffffffffffffffffffff80871660208301528516918101919091527fffffffffffffffffffff00000000000000000000000000000000000000000000831660608201527fffff0000000000000000000000000000000000000000000000000000000000008216608082015260009060a001604051602081830303815290604052805190602001209050949350505050565b60808301516000828152600460205260409081902080549215157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00909316929092179091555190915081907f32a4ba3fa3351b11ad555d4c8ec70a744e8705607077a946807030d64b6ab1a39061274a908590600060a08201905073ffffffffffffffffffffffffffffffffffffffff8084511683527fffffffffffffffffffff0000000000000000000000000000000000000000000060208501511660208401527fffff00000000000000000000000000000000000000000000000000000000000060408501511660408401528060608501511660608401525060808301511515608083015292915050565b60405180910390a25050565b60005b8251811015612a7f57600083828151811061277657612776615631565b6020026020010151905060008160000151905060005b826020015151811015612a71576000836020015182815181106127b1576127b1615631565b60200260200101516020015190506000846020015183815181106127d7576127d7615631565b6020026020010151600001519050602063ffffffff16826080015163ffffffff16101561285a5760808201516040517f24ecdc0200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8316600482015263ffffffff9091166024820152604401610d09565b67ffffffffffffffff84166000818152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff86168085529083529281902086518154938801518389015160608a015160808b015160a08c015115157201000000000000000000000000000000000000027fffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffff63ffffffff9283166e01000000000000000000000000000002167fffffffffffffffffffffffffff0000000000ffffffffffffffffffffffffffff9383166a0100000000000000000000027fffffffffffffffffffffffffffffffffffff00000000ffffffffffffffffffff61ffff9096166801000000000000000002959095167fffffffffffffffffffffffffffffffffffff000000000000ffffffffffffffff968416640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000909b16939097169290921798909817939093169390931717919091161792909217909155519091907f94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b590612a5f908690600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60405180910390a3505060010161278c565b505050806001019050612759565b5060005b81518110156123ae576000828281518110612aa057612aa0615631565b60200260200101516000015190506000838381518110612ac257612ac2615631565b60209081029190910181015181015167ffffffffffffffff84166000818152600a8452604080822073ffffffffffffffffffffffffffffffffffffffff8516808452955280822080547fffffffffffffffffffffffffff000000000000000000000000000000000000001690555192945090917f4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b9190a35050600101612a83565b60005b8251811015612c0657612b9c838281518110612b8457612b84615631565b6020026020010151600b61405d90919063ffffffff16565b15612bfe57828181518110612bb357612bb3615631565b602002602001015173ffffffffffffffffffffffffffffffffffffffff167fdf1b1bd32a69711488d71554706bb130b1fc63a5fa1a2cd85e8440f84065ba2360405160405180910390a25b600101612b66565b5060005b81518110156123ae57612c40828281518110612c2857612c28615631565b6020026020010151600b61407f90919063ffffffff16565b15612ca257818181518110612c5757612c57615631565b602002602001015173ffffffffffffffffffffffffffffffffffffffff167f1795838dc8ab2ffc5f431a1729a6afa0b587f982f7b2be0b9d7187a1ef547f9160405160405180910390a25b600101612c0a565b6040810151604a820151605e90920151909260609290921c91565b6040805173ffffffffffffffffffffffffffffffffffffffff868116602080840191909152908616828401527fffffffffffffffffffff00000000000000000000000000000000000000000000851660608301527fffff00000000000000000000000000000000000000000000000000000000000084166080808401919091528351808403909101815260a09092018352815191810191909120600081815260049092529190205460ff16612e16576040517f097e17ff00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8087166004830152851660248201527fffffffffffffffffffff00000000000000000000000000000000000000000000841660448201527fffff00000000000000000000000000000000000000000000000000000000000083166064820152608401610d09565b5050505050565b600080612e2a84866158e4565b9050600060248260ff161115612e6157612e456024836158fd565b612e5090600a615a36565b612e5a90856155f6565b9050612e84565b612e6c8260246158fd565b612e7790600a615a36565b612e8190856155df565b90505b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811115612eda576040517f10cb51d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b95945050505050565b602081015160005b8151811015612f7e576000828281518110612f0857612f08615631565b60200260200101519050612f268160026140a190919063ffffffff16565b15612f755760405173ffffffffffffffffffffffffffffffffffffffff821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b50600101612eeb565b50815160005b81518110156111a2576000828281518110612fa157612fa1615631565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603613011576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61301c60028261405d565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a150600101612f84565b60005b81518110156111fa57600082828151811061308f5761308f615631565b6020026020010151905060008383815181106130ad576130ad615631565b60200260200101516000015190506000826020015190508167ffffffffffffffff16600014806130e6575061016081015163ffffffff16155b8061313857506101e08101517fffffffff00000000000000000000000000000000000000000000000000000000167f2812d52c0000000000000000000000000000000000000000000000000000000014155b806131575750806060015163ffffffff1681610160015163ffffffff16115b1561319a576040517fc35aa79d00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff83166004820152602401610d09565b67ffffffffffffffff821660009081526009602052604081206001015471010000000000000000000000000000000000900460e01b7fffffffff0000000000000000000000000000000000000000000000000000000016900361323e578167ffffffffffffffff167fd31c671936387b2f84ed402b553bd50c0e9c20408ea4e91a836d77b8180fb724826040516132319190614aa1565b60405180910390a2613281565b8167ffffffffffffffff167f1edd6f3553cfa16f10b95b195abae3a1cfca4783de4843f95d674b1e1df5ab20826040516132789190614aa1565b60405180910390a25b80600960008467ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548161ffff021916908361ffff16021790555060408201518160000160036101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160076101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600b6101000a81548163ffffffff021916908363ffffffff16021790555060a082015181600001600f6101000a81548161ffff021916908361ffff16021790555060c08201518160000160116101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160000160156101000a81548161ffff021916908361ffff1602179055506101008201518160000160176101000a81548161ffff021916908361ffff1602179055506101208201518160000160196101000a81548161ffff021916908361ffff16021790555061014082015181600001601b6101000a81548163ffffffff021916908363ffffffff1602179055506101608201518160010160006101000a81548163ffffffff021916908363ffffffff1602179055506101808201518160010160046101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506101a082015181600101600c6101000a81548163ffffffff021916908363ffffffff1602179055506101c08201518160010160106101000a81548160ff0219169083151502179055506101e08201518160010160116101000a81548163ffffffff021916908360e01c0217905550905050505050806001019050613072565b60005b81518110156111fa57600082828151811061353557613535615631565b6020026020010151600001519050600083838151811061355757613557615631565b60209081029190910181015181015173ffffffffffffffffffffffffffffffffffffffff841660008181526008845260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff85169081179091559051908152919350917fbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d910160405180910390a25050600101613518565b6040805180820190915260008082526020820152600083900361364057506040805180820190915267ffffffffffffffff8216815260006020820152610b69565b600061364c8486615a45565b9050600061365d8560048189615a8b565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505050507fffffffff0000000000000000000000000000000000000000000000000000000082167fe7e230f000000000000000000000000000000000000000000000000000000000016136fa57808060200190518101906136f19190615ab5565b92505050610b69565b7f6859a837000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831601613776576040518060400160405280828060200190518101906137629190615ae1565b815260006020909101529250610b69915050565b6040517f5247fdce00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080518082019091526000808252602082015260008260000151905060008173ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015613812573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138369190615b14565b5050509150506000811215613877576040517f10cb51d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006138f68373ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156138c7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138eb9190615b64565b866020015184612e1d565b604080518082019091527bffffffffffffffffffffffffffffffffffffffffffffffffffffffff909116815263ffffffff4216602082015295945050505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515610b69565b836040015163ffffffff168311156139bf5760408085015190517f8693378900000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015260248101849052604401610d09565b836020015161ffff16821115613a01576040517f4c056b6a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6111a2846101e001518261235c565b6000808083815b81811015613cda576000878783818110613a3357613a33615631565b905060400201803603810190613a499190615b81565b67ffffffffffffffff8c166000908152600a60209081526040808320845173ffffffffffffffffffffffffffffffffffffffff168452825291829020825160c081018452905463ffffffff8082168352640100000000820481169383019390935268010000000000000000810461ffff16938201939093526a01000000000000000000008304821660608201526e01000000000000000000000000000083049091166080820152720100000000000000000000000000000000000090910460ff16151560a0820181905291925090613b69576101208d0151613b369061ffff16662386f26fc100006155df565b613b4090886158be565b96508c610140015186613b539190615bba565b9550613b60602086615bba565b94505050613cd2565b604081015160009061ffff1615613c225760008c73ffffffffffffffffffffffffffffffffffffffff16846000015173ffffffffffffffffffffffffffffffffffffffff1614613bc5578351613bbe906122c2565b9050613bc8565b508a5b620186a0836040015161ffff16613c0a8660200151847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166140c390919063ffffffff16565b613c1491906155df565b613c1e91906155f6565b9150505b6060820151613c319088615bba565b9650816080015186613c439190615bba565b8251909650600090613c629063ffffffff16662386f26fc100006155df565b905080821015613c8157613c76818a6158be565b985050505050613cd2565b6000836020015163ffffffff16662386f26fc10000613ca091906155df565b905080831115613cc057613cb4818b6158be565b99505050505050613cd2565b613cca838b6158be565b995050505050505b600101613a17565b505096509650969350505050565b60008063ffffffff8316613cfe610160866155df565b613d0a876101c06158be565b613d1491906158be565b613d1e91906158be565b905060008760c0015163ffffffff168860e0015161ffff1683613d4191906155df565b613d4b91906158be565b61010089015190915061ffff16613d726dffffffffffffffffffffffffffff8916836155df565b613d7c91906155df565b613d8c90655af3107a40006155df565b98975050505050505050565b60408051808201909152600080825260208201526000613dc4858585610160015163ffffffff166135ff565b9050826060015163ffffffff1681600001511115613e0e576040517f4c4fc93a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b826101c001518015613e2257508060200151155b15610b66576040517fee433e9900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff821603613ed8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610d09565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60008151602014613f8d57816040517f8d666f60000000000000000000000000000000000000000000000000000000008152600401610d099190614512565b600082806020019051810190613fa39190615ae1565b905073ffffffffffffffffffffffffffffffffffffffff811180613fc8575061040081105b156112c357826040517f8d666f60000000000000000000000000000000000000000000000000000000008152600401610d099190614512565b60608160000180548060200260200160405190810160405280929190818152602001828054801561405157602002820191906000526020600020905b81548152602001906001019080831161403d575b50505050509050919050565b6000610b698373ffffffffffffffffffffffffffffffffffffffff8416614100565b6000610b698373ffffffffffffffffffffffffffffffffffffffff841661414f565b6000610b698373ffffffffffffffffffffffffffffffffffffffff8416614249565b6000670de0b6b3a76400006140f6837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff86166155df565b610b6991906155f6565b6000818152600183016020526040812054614147575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556112c3565b5060006112c3565b600081815260018301602052604081205480156142385760006141736001836158d1565b8554909150600090614187906001906158d1565b90508082146141ec5760008660000182815481106141a7576141a7615631565b90600052602060002001549050808760000184815481106141ca576141ca615631565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806141fd576141fd615bd7565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506112c3565b60009150506112c3565b5092915050565b6000818152600183016020526040812054801561423857600061426d6001836158d1565b8554909150600090614281906001906158d1565b90508181146141ec5760008660000182815481106141a7576141a7615631565b803573ffffffffffffffffffffffffffffffffffffffff811681146142c557600080fd5b919050565b6000806000606084860312156142df57600080fd5b6142e8846142a1565b9250602084013591506142fd604085016142a1565b90509250925092565b60006020828403121561431857600080fd5b610b69826142a1565b803567ffffffffffffffff811681146142c557600080fd5b60008083601f84011261434b57600080fd5b50813567ffffffffffffffff81111561436357600080fd5b6020830191508360208260051b85010111156122bb57600080fd5b60008060008060006060868803121561439657600080fd5b61439f86614321565b9450602086013567ffffffffffffffff808211156143bc57600080fd5b6143c889838a01614339565b909650945060408801359150808211156143e157600080fd5b818801915088601f8301126143f557600080fd5b81358181111561440457600080fd5b8960208260061b850101111561441957600080fd5b9699959850939650602001949392505050565b6000815180845260005b8181101561445257602081850181015186830182015201614436565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b82811015614505577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526144f385835161442c565b945092850192908501906001016144b9565b5092979650505050505050565b602081526000610b69602083018461442c565b6020808252825182820181905260009190848201906040850190845b8181101561457357835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101614541565b50909695505050505050565b60006020828403121561459157600080fd5b813567ffffffffffffffff8111156145a857600080fd5b820160408185031215610b6957600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561460c5761460c6145ba565b60405290565b60405160a0810167ffffffffffffffff8111828210171561460c5761460c6145ba565b60405160c0810167ffffffffffffffff8111828210171561460c5761460c6145ba565b604051610200810167ffffffffffffffff8111828210171561460c5761460c6145ba565b6040516060810167ffffffffffffffff8111828210171561460c5761460c6145ba565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156146e6576146e66145ba565b604052919050565b600067ffffffffffffffff821115614708576147086145ba565b5060051b60200190565b60ff811681146111b957600080fd5b6000602080838503121561473457600080fd5b823567ffffffffffffffff81111561474b57600080fd5b8301601f8101851361475c57600080fd5b803561476f61476a826146ee565b61469f565b8181526060918202830184019184820191908884111561478e57600080fd5b938501935b8385101561482e57848903818112156147ac5760008081fd5b6147b46145e9565b6147bd876142a1565b81526040807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0840112156147f15760008081fd5b6147f96145e9565b92506148068989016142a1565b835287013561481481614712565b828901528088019190915283529384019391850191614793565b50979650505050505050565b80151581146111b957600080fd5b80356142c58161483a565b6000602080838503121561486657600080fd5b823567ffffffffffffffff81111561487d57600080fd5b8301601f8101851361488e57600080fd5b803561489c61476a826146ee565b81815260a091820283018401918482019190888411156148bb57600080fd5b938501935b8385101561482e5780858a0312156148d85760008081fd5b6148e0614612565b6148e9866142a1565b8152868601357fffffffffffffffffffff000000000000000000000000000000000000000000008116811461491e5760008081fd5b818801526040868101357fffff000000000000000000000000000000000000000000000000000000000000811681146149575760008081fd5b9082015260606149688782016142a1565b9082015260808681013561497b8161483a565b90820152835293840193918501916148c0565b600080602083850312156149a157600080fd5b823567ffffffffffffffff8111156149b857600080fd5b6149c485828601614339565b90969095509350505050565b602080825282518282018190526000919060409081850190868401855b82811015614a3e57614a2e84835180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16825260209081015163ffffffff16910152565b92840192908501906001016149ed565b5091979650505050505050565b600060208284031215614a5d57600080fd5b610b6982614321565b81517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16815260208083015163ffffffff1690820152604081016112c3565b81511515815261020081016020830151614ac1602084018261ffff169052565b506040830151614ad9604084018263ffffffff169052565b506060830151614af1606084018263ffffffff169052565b506080830151614b09608084018263ffffffff169052565b5060a0830151614b1f60a084018261ffff169052565b5060c0830151614b3760c084018263ffffffff169052565b5060e0830151614b4d60e084018261ffff169052565b506101008381015161ffff9081169184019190915261012080850151909116908301526101408084015163ffffffff90811691840191909152610160808501518216908401526101808085015167ffffffffffffffff16908401526101a080850151909116908301526101c0808401511515908301526101e0808401517fffffffff000000000000000000000000000000000000000000000000000000008116828501525b505092915050565b803563ffffffff811681146142c557600080fd5b803561ffff811681146142c557600080fd5b600082601f830112614c3157600080fd5b81356020614c4161476a836146ee565b82815260069290921b84018101918181019086841115614c6057600080fd5b8286015b84811015614cad5760408189031215614c7d5760008081fd5b614c856145e9565b614c8e82614321565b8152614c9b8583016142a1565b81860152835291830191604001614c64565b509695505050505050565b60008060408385031215614ccb57600080fd5b67ffffffffffffffff83351115614ce157600080fd5b83601f843585010112614cf357600080fd5b614d0361476a84358501356146ee565b8335840180358083526020808401939260059290921b90910101861015614d2957600080fd5b602085358601015b85358601803560051b01602001811015614f365767ffffffffffffffff81351115614d5b57600080fd5b8035863587010160407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0828a03011215614d9457600080fd5b614d9c6145e9565b614da860208301614321565b815267ffffffffffffffff60408301351115614dc357600080fd5b88603f604084013584010112614dd857600080fd5b614dee61476a60206040850135850101356146ee565b6020604084810135850182810135808552928401939260e00201018b1015614e1557600080fd5b6040808501358501015b6040858101358601602081013560e0020101811015614f175760e0818d031215614e4857600080fd5b614e506145e9565b614e59826142a1565b815260c07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0838f03011215614e8d57600080fd5b614e95614635565b614ea160208401614bfa565b8152614eaf60408401614bfa565b6020820152614ec060608401614c0e565b6040820152614ed160808401614bfa565b6060820152614ee260a08401614bfa565b6080820152614ef460c084013561483a565b60c083013560a0820152602082810191909152908452929092019160e001614e1f565b5080602084015250508085525050602083019250602081019050614d31565b5092505067ffffffffffffffff60208401351115614f5357600080fd5b614f638460208501358501614c20565b90509250929050565b600082601f830112614f7d57600080fd5b81356020614f8d61476a836146ee565b8083825260208201915060208460051b870101935086841115614faf57600080fd5b602086015b84811015614cad57614fc5816142a1565b8352918301918301614fb4565b60008060408385031215614fe557600080fd5b823567ffffffffffffffff80821115614ffd57600080fd5b61500986838701614f6c565b9350602085013591508082111561501f57600080fd5b5061502c85828601614f6c565b9150509250929050565b60008083601f84011261504857600080fd5b50813567ffffffffffffffff81111561506057600080fd5b6020830191508360208285010111156122bb57600080fd5b6000806000806040858703121561508e57600080fd5b843567ffffffffffffffff808211156150a657600080fd5b6150b288838901615036565b909650945060208701359150808211156150cb57600080fd5b506150d887828801615036565b95989497509550505050565b600080604083850312156150f757600080fd5b61510083614321565b9150614f63602084016142a1565b60006020828403121561512057600080fd5b813567ffffffffffffffff8082111561513857600080fd5b908301906040828603121561514c57600080fd5b6151546145e9565b82358281111561516357600080fd5b61516f87828601614f6c565b82525060208301358281111561518457600080fd5b61519087828601614f6c565b60208301525095945050505050565b80357fffffffff00000000000000000000000000000000000000000000000000000000811681146142c557600080fd5b600060208083850312156151e257600080fd5b823567ffffffffffffffff8111156151f957600080fd5b8301601f8101851361520a57600080fd5b803561521861476a826146ee565b818152610220918202830184019184820191908884111561523857600080fd5b938501935b8385101561482e57848903818112156152565760008081fd5b61525e6145e9565b61526787614321565b8152610200807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08401121561529c5760008081fd5b6152a4614658565b92506152b1898901614848565b835260406152c0818a01614c0e565b8a85015260606152d1818b01614bfa565b82860152608091506152e4828b01614bfa565b9085015260a06152f58a8201614bfa565b8286015260c09150615308828b01614c0e565b9085015260e06153198a8201614bfa565b82860152610100915061532d828b01614c0e565b9085015261012061533f8a8201614c0e565b828601526101409150615353828b01614c0e565b908501526101606153658a8201614bfa565b828601526101809150615379828b01614bfa565b908501526101a061538b8a8201614321565b828601526101c0915061539f828b01614bfa565b908501526101e06153b18a8201614848565b828601526153c0838b0161519f565b908501525050808801919091528352938401939185019161523d565b600060208083850312156153ef57600080fd5b823567ffffffffffffffff81111561540657600080fd5b8301601f8101851361541757600080fd5b803561542561476a826146ee565b81815260069190911b8201830190838101908783111561544457600080fd5b928401925b8284101561549657604084890312156154625760008081fd5b61546a6145e9565b615473856142a1565b8152615480868601614321565b8187015282526040939093019290840190615449565b979650505050505050565b6000806000806000608086880312156154b957600080fd5b6154c286614321565b94506154d0602087016142a1565b935060408601359250606086013567ffffffffffffffff8111156154f357600080fd5b6154ff88828901615036565b969995985093965092949392505050565b8381528215156020820152606060408201526000612eda606083018461442c565b6000806040838503121561554457600080fd5b61554d83614321565b9150602083013567ffffffffffffffff81111561556957600080fd5b830160a0818603121561557b57600080fd5b809150509250929050565b6000806040838503121561559957600080fd5b6155a2836142a1565b9150614f6360208401614321565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80820281158282048414176112c3576112c36155b0565b60008261562c577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6183360301811261569457600080fd5b9190910192915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126156d357600080fd5b83018035915067ffffffffffffffff8211156156ee57600080fd5b6020019150368190038213156122bb57600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261573857600080fd5b83018035915067ffffffffffffffff82111561575357600080fd5b6020019150600681901b36038213156122bb57600080fd5b80357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811681146142c557600080fd5b6000604082840312156157a957600080fd5b6157b16145e9565b6157ba836142a1565b81526157c86020840161576b565b60208201529392505050565b6000604082840312156157e657600080fd5b6157ee6145e9565b6157ba83614321565b6000602080838503121561580a57600080fd5b823567ffffffffffffffff81111561582157600080fd5b8301601f8101851361583257600080fd5b803561584061476a826146ee565b8181526060918202830184019184820191908884111561585f57600080fd5b938501935b8385101561482e5780858a03121561587c5760008081fd5b61588461467c565b61588d866142a1565b815261589a87870161576b565b8782015260406158ab818801614bfa565b9082015283529384019391850191615864565b808201808211156112c3576112c36155b0565b818103818111156112c3576112c36155b0565b60ff81811683821601908111156112c3576112c36155b0565b60ff82811682821603908111156112c3576112c36155b0565b600181815b8085111561596f57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115615955576159556155b0565b8085161561596257918102915b93841c939080029061591b565b509250929050565b600082615986575060016112c3565b81615993575060006112c3565b81600181146159a957600281146159b3576159cf565b60019150506112c3565b60ff8411156159c4576159c46155b0565b50506001821b6112c3565b5060208310610133831016604e8410600b84101617156159f2575081810a6112c3565b6159fc8383615916565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115615a2e57615a2e6155b0565b029392505050565b6000610b6960ff841683615977565b7fffffffff000000000000000000000000000000000000000000000000000000008135818116916004851015614bf25760049490940360031b84901b1690921692915050565b60008085851115615a9b57600080fd5b83861115615aa857600080fd5b5050820193919092039150565b600060408284031215615ac757600080fd5b615acf6145e9565b8251815260208301516157c88161483a565b600060208284031215615af357600080fd5b5051919050565b805169ffffffffffffffffffff811681146142c557600080fd5b600080600080600060a08688031215615b2c57600080fd5b615b3586615afa565b9450602086015193506040860151925060608601519150615b5860808701615afa565b90509295509295909350565b600060208284031215615b7657600080fd5b8151610b6981614712565b600060408284031215615b9357600080fd5b615b9b6145e9565b615ba4836142a1565b8152602083013560208201528091505092915050565b63ffffffff818116838216019080821115614242576142426155b0565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea164736f6c6343000818000a", + Bin: "0x60e06040523480156200001157600080fd5b506040516200774438038062007744833981016040819052620000349162001834565b8533806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf8162000207565b5050604080518082018252838152815160008152602080820190935291810191909152620000ee9150620002b2565b5060208701516001600160a01b0316158062000112575086516001600160601b0316155b80620001265750604087015163ffffffff16155b15620001455760405163d794ef9560e01b815260040160405180910390fd5b6020878101516001600160a01b031660a05287516001600160601b031660805260408089015163ffffffff1660c05280516000815291820190526200018c90869062000401565b620001978462000549565b620001a2816200061a565b620001ad8262000a5a565b60408051600080825260208201909252620001fa91859190620001f3565b6040805180820190915260008082526020820152815260200190600190039081620001cb5790505b5062000b26565b5050505050505062001ae5565b336001600160a01b03821603620002615760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b602081015160005b815181101562000342576000828281518110620002db57620002db62001953565b60209081029190910101519050620002f560028262000e5f565b1562000338576040516001600160a01b03821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b50600101620002ba565b50815160005b8151811015620003fb57600082828151811062000369576200036962001953565b6020026020010151905060006001600160a01b0316816001600160a01b031603620003a7576040516342bcdf7f60e11b815260040160405180910390fd5b620003b460028262000e7f565b506040516001600160a01b03821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a15060010162000348565b50505050565b60005b8251811015620004a2576200044083828151811062000427576200042762001953565b6020026020010151600b62000e7f60201b90919060201c565b1562000499578281815181106200045b576200045b62001953565b60200260200101516001600160a01b03167fdf1b1bd32a69711488d71554706bb130b1fc63a5fa1a2cd85e8440f84065ba2360405160405180910390a25b60010162000404565b5060005b81518110156200054457620004e2828281518110620004c957620004c962001953565b6020026020010151600b62000e9660201b90919060201c565b156200053b57818181518110620004fd57620004fd62001953565b60200260200101516001600160a01b03167f1795838dc8ab2ffc5f431a1729a6afa0b587f982f7b2be0b9d7187a1ef547f9160405160405180910390a25b600101620004a6565b505050565b60005b8151811015620006165760008282815181106200056d576200056d62001953565b6020908102919091018101518051818301516001600160a01b0380831660008181526007875260409081902084518154868a018051929096166001600160a81b03199091168117600160a01b60ff9384160217909255825191825293519093169683019690965293955091939092917f08a5f7f5bb38a81d8e43aca13ecd76431dbf8816ae4699affff7b00b2fc1c464910160405180910390a25050508060010190506200054c565b5050565b60005b8151811015620006165760008282815181106200063e576200063e62001953565b6020026020010151905060008383815181106200065f576200065f62001953565b6020026020010151600001519050600082602001519050816001600160401b03166000148062000698575061016081015163ffffffff16155b80620006ba57506101e08101516001600160e01b031916630a04b54b60e21b14155b80620006da5750806060015163ffffffff1681610160015163ffffffff16115b15620007055760405163c35aa79d60e01b81526001600160401b038316600482015260240162000083565b6001600160401b038216600090815260096020526040812060010154600160881b900460e01b6001600160e01b03191690036200078557816001600160401b03167fd31c671936387b2f84ed402b553bd50c0e9c20408ea4e91a836d77b8180fb7248260405162000777919062001969565b60405180910390a2620007c9565b816001600160401b03167f1edd6f3553cfa16f10b95b195abae3a1cfca4783de4843f95d674b1e1df5ab2082604051620007c0919062001969565b60405180910390a25b8060096000846001600160401b03166001600160401b0316815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548161ffff021916908361ffff16021790555060408201518160000160036101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160076101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600b6101000a81548163ffffffff021916908363ffffffff16021790555060a082015181600001600f6101000a81548161ffff021916908361ffff16021790555060c08201518160000160116101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160000160156101000a81548161ffff021916908361ffff1602179055506101008201518160000160176101000a81548161ffff021916908361ffff1602179055506101208201518160000160196101000a81548161ffff021916908361ffff16021790555061014082015181600001601b6101000a81548163ffffffff021916908363ffffffff1602179055506101608201518160010160006101000a81548163ffffffff021916908363ffffffff1602179055506101808201518160010160046101000a8154816001600160401b0302191690836001600160401b031602179055506101a082015181600101600c6101000a81548163ffffffff021916908363ffffffff1602179055506101c08201518160010160106101000a81548160ff0219169083151502179055506101e08201518160010160116101000a81548163ffffffff021916908360e01c02179055509050505050508060010190506200061d565b60005b81518110156200061657600082828151811062000a7e5762000a7e62001953565b6020026020010151600001519050600083838151811062000aa35762000aa362001953565b6020908102919091018101518101516001600160a01b03841660008181526008845260409081902080546001600160401b0319166001600160401b0385169081179091559051908152919350917fbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d910160405180910390a2505060010162000a5d565b60005b825181101562000d9957600083828151811062000b4a5762000b4a62001953565b6020026020010151905060008160000151905060005b82602001515181101562000d8a5760008360200151828151811062000b895762000b8962001953565b602002602001015160200151905060008460200151838151811062000bb25762000bb262001953565b6020026020010151600001519050602063ffffffff16826080015163ffffffff16101562000c115760808201516040516312766e0160e11b81526001600160a01b038316600482015263ffffffff909116602482015260440162000083565b6001600160401b0384166000818152600a602090815260408083206001600160a01b0386168085529083529281902086518154938801518389015160608a015160808b015160a08c01511515600160901b0260ff60901b1963ffffffff928316600160701b021664ffffffffff60701b199383166a01000000000000000000000263ffffffff60501b1961ffff90961668010000000000000000029590951665ffffffffffff60401b19968416640100000000026001600160401b0319909b16939097169290921798909817939093169390931717919091161792909217909155519091907f94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b59062000d77908690600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60405180910390a3505060010162000b60565b50505080600101905062000b29565b5060005b81518110156200054457600082828151811062000dbe5762000dbe62001953565b6020026020010151600001519050600083838151811062000de35762000de362001953565b6020908102919091018101518101516001600160401b0384166000818152600a845260408082206001600160a01b038516808452955280822080546001600160981b03191690555192945090917f4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b9190a3505060010162000d9d565b600062000e76836001600160a01b03841662000ead565b90505b92915050565b600062000e76836001600160a01b03841662000fb1565b600062000e76836001600160a01b03841662001003565b6000818152600183016020526040812054801562000fa657600062000ed460018362001aad565b855490915060009062000eea9060019062001aad565b905081811462000f5657600086600001828154811062000f0e5762000f0e62001953565b906000526020600020015490508087600001848154811062000f345762000f3462001953565b6000918252602080832090910192909255918252600188019052604090208390555b855486908062000f6a5762000f6a62001acf565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505062000e79565b600091505062000e79565b600081815260018301602052604081205462000ffa5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000e79565b50600062000e79565b6000818152600183016020526040812054801562000fa65760006200102a60018362001aad565b8554909150600090620010409060019062001aad565b905080821462000f5657600086600001828154811062000f0e5762000f0e62001953565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b03811182821017156200109f576200109f62001064565b60405290565b60405160c081016001600160401b03811182821017156200109f576200109f62001064565b60405161020081016001600160401b03811182821017156200109f576200109f62001064565b604051601f8201601f191681016001600160401b03811182821017156200111b576200111b62001064565b604052919050565b80516001600160a01b03811681146200113b57600080fd5b919050565b805163ffffffff811681146200113b57600080fd5b6000606082840312156200116857600080fd5b604051606081016001600160401b03811182821017156200118d576200118d62001064565b604052825190915081906001600160601b0381168114620011ad57600080fd5b8152620011bd6020840162001123565b6020820152620011d06040840162001140565b60408201525092915050565b60006001600160401b03821115620011f857620011f862001064565b5060051b60200190565b600082601f8301126200121457600080fd5b815160206200122d6200122783620011dc565b620010f0565b8083825260208201915060208460051b8701019350868411156200125057600080fd5b602086015b848110156200127757620012698162001123565b835291830191830162001255565b509695505050505050565b600082601f8301126200129457600080fd5b81516020620012a76200122783620011dc565b82815260609283028501820192828201919087851115620012c757600080fd5b8387015b858110156200135a5780890382811215620012e65760008081fd5b620012f06200107a565b620012fb8362001123565b8152604080601f1984011215620013125760008081fd5b6200131c6200107a565b92506200132b88850162001123565b835283015160ff81168114620013415760008081fd5b82880152808701919091528452928401928101620012cb565b5090979650505050505050565b80516001600160401b03811681146200113b57600080fd5b805161ffff811681146200113b57600080fd5b805180151581146200113b57600080fd5b600082601f830112620013b557600080fd5b81516020620013c86200122783620011dc565b82815260059290921b84018101918181019086841115620013e857600080fd5b8286015b84811015620012775780516001600160401b03808211156200140d57600080fd5b908801906040601f19838c0381018213156200142857600080fd5b620014326200107a565b6200143f89860162001367565b815282850151848111156200145357600080fd5b8086019550508c603f8601126200146957600080fd5b8885015193506200147e6200122785620011dc565b84815260e09094028501830193898101908e8611156200149d57600080fd5b958401955b858710156200157657868f0360e0811215620014bd57600080fd5b620014c76200107a565b620014d28962001123565b815260c08683011215620014e557600080fd5b620014ef620010a5565b9150620014fe8d8a0162001140565b82526200150d878a0162001140565b8d8301526200151f60608a016200137f565b878301526200153160808a0162001140565b60608301526200154460a08a0162001140565b60808301526200155760c08a0162001392565b60a0830152808d0191909152825260e09690960195908a0190620014a2565b828b015250875250505092840192508301620013ec565b600082601f8301126200159f57600080fd5b81516020620015b26200122783620011dc565b82815260069290921b84018101918181019086841115620015d257600080fd5b8286015b84811015620012775760408189031215620015f15760008081fd5b620015fb6200107a565b620016068262001123565b81526200161585830162001367565b81860152835291830191604001620015d6565b80516001600160e01b0319811681146200113b57600080fd5b600082601f8301126200165357600080fd5b81516020620016666200122783620011dc565b82815261022092830285018201928282019190878511156200168757600080fd5b8387015b858110156200135a5780890382811215620016a65760008081fd5b620016b06200107a565b620016bb8362001367565b815261020080601f1984011215620016d35760008081fd5b620016dd620010ca565b9250620016ec88850162001392565b83526040620016fd8186016200137f565b8985015260606200171081870162001140565b82860152608091506200172582870162001140565b9085015260a06200173886820162001140565b8286015260c091506200174d8287016200137f565b9085015260e06200176086820162001140565b828601526101009150620017768287016200137f565b908501526101206200178a8682016200137f565b828601526101409150620017a08287016200137f565b90850152610160620017b486820162001140565b828601526101809150620017ca82870162001140565b908501526101a0620017de86820162001367565b828601526101c09150620017f482870162001140565b908501526101e06200180886820162001392565b828601526200181983870162001628565b9085015250508087019190915284529284019281016200168b565b6000806000806000806000610120888a0312156200185157600080fd5b6200185d898962001155565b60608901519097506001600160401b03808211156200187b57600080fd5b620018898b838c0162001202565b975060808a0151915080821115620018a057600080fd5b620018ae8b838c0162001202565b965060a08a0151915080821115620018c557600080fd5b620018d38b838c0162001282565b955060c08a0151915080821115620018ea57600080fd5b620018f88b838c01620013a3565b945060e08a01519150808211156200190f57600080fd5b6200191d8b838c016200158d565b93506101008a01519150808211156200193557600080fd5b50620019448a828b0162001641565b91505092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b815115158152610200810160208301516200198a602084018261ffff169052565b506040830151620019a3604084018263ffffffff169052565b506060830151620019bc606084018263ffffffff169052565b506080830151620019d5608084018263ffffffff169052565b5060a0830151620019ec60a084018261ffff169052565b5060c083015162001a0560c084018263ffffffff169052565b5060e083015162001a1c60e084018261ffff169052565b506101008381015161ffff9081169184019190915261012080850151909116908301526101408084015163ffffffff9081169184019190915261016080850151821690840152610180808501516001600160401b0316908401526101a080850151909116908301526101c0808401511515908301526101e0928301516001600160e01b031916929091019190915290565b8181038181111562000e7957634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b60805160a05160c051615c0562001b3f600039600081816102ef015281816121fd01526122660152600081816102b301528181611917015261197701526000818161027f015281816119a00152611a100152615c056000f3fe608060405234801561001057600080fd5b50600436106101ce5760003560e01c806379ba509711610104578063a69c64c0116100a2578063d02641a011610071578063d02641a014610a81578063d8694ccd14610a94578063f2fde38b14610aa7578063ffdb4b3714610aba57600080fd5b8063a69c64c014610997578063bf78e03f146109aa578063c4276bfc14610a57578063cdc73d5114610a7957600080fd5b806382b49eb0116100de57806382b49eb0146107d95780638da5cb5b1461094957806391a2749a146109715780639ea600261461098457600080fd5b806379ba5097146107ab5780637afac322146107b3578063805f2132146107c657600080fd5b8063407e1086116101715780634ab35b0b1161014b5780634ab35b0b14610441578063514e8cff146104815780636def4ce714610524578063770e2dc41461079857600080fd5b8063407e1086146103fb57806341ed29e71461040e57806345ac924d1461042157600080fd5b8063085318f8116101ad578063085318f814610368578063181f5a77146103885780632451a627146103d15780633937306f146103e657600080fd5b806241e5be146101d3578063061877e3146101f957806306285c6914610252575b600080fd5b6101e66101e13660046142bc565b610b02565b6040519081526020015b60405180910390f35b6102396102073660046142f8565b73ffffffffffffffffffffffffffffffffffffffff1660009081526008602052604090205467ffffffffffffffff1690565b60405167ffffffffffffffff90911681526020016101f0565b61031c604080516060810182526000808252602082018190529181019190915260405180606001604052807f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000063ffffffff16815250905090565b6040805182516bffffffffffffffffffffffff16815260208084015173ffffffffffffffffffffffffffffffffffffffff16908201529181015163ffffffff16908201526060016101f0565b61037b610376366004614370565b610b70565b6040516101f09190614482565b6103c46040518060400160405280601381526020017f46656551756f74657220312e362e302d6465760000000000000000000000000081525081565b6040516101f09190614504565b6103d9610ee2565b6040516101f09190614517565b6103f96103f4366004614571565b610ef3565b005b6103f9610409366004614713565b6111a8565b6103f961041c366004614845565b6111bc565b61043461042f366004614980565b6111fe565b6040516101f091906149c2565b61045461044f3660046142f8565b6112c9565b6040517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff90911681526020016101f0565b61051761048f366004614a3d565b60408051808201909152600080825260208201525067ffffffffffffffff166000908152600560209081526040918290208251808401909352547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811683527c0100000000000000000000000000000000000000000000000000000000900463ffffffff169082015290565b6040516101f09190614a58565b61078b610532366004614a3d565b6040805161020081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a081018290526101c081018290526101e08101919091525067ffffffffffffffff908116600090815260096020908152604091829020825161020081018452815460ff8082161515835261ffff61010080840482169685019690965263ffffffff630100000084048116978501979097526701000000000000008304871660608501526b0100000000000000000000008304871660808501526f010000000000000000000000000000008304811660a085015271010000000000000000000000000000000000808404881660c086015275010000000000000000000000000000000000000000008404821660e08087019190915277010000000000000000000000000000000000000000000000850483169786019790975279010000000000000000000000000000000000000000000000000084049091166101208501527b01000000000000000000000000000000000000000000000000000000909204861661014084015260019093015480861661016084015264010000000081049096166101808301526c0100000000000000000000000086049094166101a0820152700100000000000000000000000000000000850490911615156101c08201527fffffffff0000000000000000000000000000000000000000000000000000000092909304901b166101e082015290565b6040516101f09190614a93565b6103f96107a6366004614caa565b6112d4565b6103f96112e6565b6103f96107c1366004614fc4565b6113e3565b6103f96107d436600461506a565b6113f5565b6108e96107e73660046150d6565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101919091525067ffffffffffffffff919091166000908152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff94909416835292815290829020825160c081018452905463ffffffff8082168352640100000000820481169383019390935268010000000000000000810461ffff16938201939093526a01000000000000000000008304821660608201526e01000000000000000000000000000083049091166080820152720100000000000000000000000000000000000090910460ff16151560a082015290565b6040516101f09190600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101f0565b6103f961097f366004615100565b6118dd565b6103f96109923660046151c1565b6118ee565b6103f96109a53660046153ce565b6118ff565b610a236109b83660046142f8565b6040805180820182526000808252602091820181905273ffffffffffffffffffffffffffffffffffffffff93841681526007825282902082518084019093525492831682527401000000000000000000000000000000000000000090920460ff169181019190915290565b60408051825173ffffffffffffffffffffffffffffffffffffffff16815260209283015160ff1692810192909252016101f0565b610a6a610a65366004615493565b611910565b6040516101f093929190615502565b6103d9611b06565b610517610a8f3660046142f8565b611b12565b6101e6610aa2366004615523565b611c0e565b6103f9610ab53660046142f8565b612118565b610acd610ac8366004615578565b612129565b604080517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff9384168152929091166020830152016101f0565b6000610b0d826122b4565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16610b34856122b4565b610b5c907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16856155d1565b610b6691906155e8565b90505b9392505050565b67ffffffffffffffff8086166000908152600960205260409020600101546060917101000000000000000000000000000000000090910460e01b908590811115610bbc57610bbc6145ac565b604051908082528060200260200182016040528015610bef57816020015b6060815260200190600190039081610bda5790505b50915060005b85811015610ed7576000858583818110610c1157610c11615623565b610c2792602060409092020190810191506142f8565b90506000888884818110610c3d57610c3d615623565b9050602002810190610c4f9190615652565b610c5d906040810190615690565b9150506020811115610d125767ffffffffffffffff8a166000908152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff861684529091529020546e010000000000000000000000000000900463ffffffff16811115610d12576040517f36f536ca00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526024015b60405180910390fd5b610d82848a8a86818110610d2857610d28615623565b9050602002810190610d3a9190615652565b610d48906020810190615690565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061234e92505050565b67ffffffffffffffff8a166000818152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684528252808320815160c081018352905463ffffffff8082168352640100000000820481168386015268010000000000000000820461ffff16838501526a01000000000000000000008204811660608401526e010000000000000000000000000000820481166080840152720100000000000000000000000000000000000090910460ff16151560a08301908152958552600990935290832054935190937b0100000000000000000000000000000000000000000000000000000090049091169190610e815781610e87565b82606001515b6040805163ffffffff8316602082015291925001604051602081830303815290604052888781518110610ebc57610ebc615623565b60200260200101819052505050505050806001019050610bf5565b505095945050505050565b6060610eee60026123a5565b905090565b610efb6123b2565b6000610f0782806156f5565b9050905060005b81811015611051576000610f2284806156f5565b83818110610f3257610f32615623565b905060400201803603810190610f489190615789565b604080518082018252602080840180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff908116845263ffffffff42818116858701908152885173ffffffffffffffffffffffffffffffffffffffff9081166000908152600690975295889020965190519092167c010000000000000000000000000000000000000000000000000000000002919092161790935584519051935194955016927f52f50aa6d1a95a4595361ecf953d095f125d442e4673716dede699e049de148a926110409290917bffffffffffffffffffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b60405180910390a250600101610f0e565b50600061106160208401846156f5565b9050905060005b818110156111a257600061107f60208601866156f5565b8381811061108f5761108f615623565b9050604002018036038101906110a591906157c6565b604080518082018252602080840180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff908116845263ffffffff42818116858701908152885167ffffffffffffffff9081166000908152600590975295889020965190519092167c010000000000000000000000000000000000000000000000000000000002919092161790935584519051935194955016927fdd84a3fa9ef9409f550d54d6affec7e9c480c878c6ab27b78912a03e1b371c6e926111919290917bffffffffffffffffffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b60405180910390a250600101611068565b50505050565b6111b06123f7565b6111b981612478565b50565b6111c46123f7565b60005b81518110156111fa576111f28282815181106111e5576111e5615623565b6020026020010151612576565b6001016111c7565b5050565b60608160008167ffffffffffffffff81111561121c5761121c6145ac565b60405190808252806020026020018201604052801561126157816020015b604080518082019091526000808252602082015281526020019060019003908161123a5790505b50905060005b828110156112be5761129986868381811061128457611284615623565b9050602002016020810190610a8f91906142f8565b8282815181106112ab576112ab615623565b6020908102919091010152600101611267565b509150505b92915050565b60006112c3826122b4565b6112dc6123f7565b6111fa8282612748565b60015473ffffffffffffffffffffffffffffffffffffffff163314611367576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610d09565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6113eb6123f7565b6111fa8282612b55565b600080600061143987878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612c9c92505050565b92509250925061144b33838584612cb7565b6000611459858701876157e9565b905060005b81518110156118d25760006007600084848151811061147f5761147f615623565b6020908102919091018101515173ffffffffffffffffffffffffffffffffffffffff16825281019190915260400160009081205474010000000000000000000000000000000000000000900460ff169150819003611540578282815181106114e9576114e9615623565b6020908102919091010151516040517f06439c6b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610d09565b600061158960128386868151811061155a5761155a615623565b6020026020010151602001517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16612e0f565b9050600660008585815181106115a1576115a1615623565b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001601c9054906101000a900463ffffffff1663ffffffff1684848151811061161357611613615623565b60200260200101516040015163ffffffff16101561171d5783838151811061163d5761163d615623565b60200260200101516000015184848151811061165b5761165b615623565b6020026020010151604001516006600087878151811061167d5761167d615623565b6020908102919091018101515173ffffffffffffffffffffffffffffffffffffffff90811683529082019290925260409081016000205490517f191ec70600000000000000000000000000000000000000000000000000000000815293909116600484015263ffffffff91821660248401527c01000000000000000000000000000000000000000000000000000000009004166044820152606401610d09565b6040518060400160405280827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16815260200185858151811061175e5761175e615623565b60200260200101516040015163ffffffff168152506006600086868151811061178957611789615623565b6020908102919091018101515173ffffffffffffffffffffffffffffffffffffffff168252818101929092526040016000208251929091015163ffffffff167c0100000000000000000000000000000000000000000000000000000000027bffffffffffffffffffffffffffffffffffffffffffffffffffffffff909216919091179055835184908490811061182157611821615623565b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff167f52f50aa6d1a95a4595361ecf953d095f125d442e4673716dede699e049de148a8286868151811061187757611877615623565b6020026020010151604001516040516118c09291907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff92909216825263ffffffff16602082015260400190565b60405180910390a2505060010161145e565b505050505050505050565b6118e56123f7565b6111b981612ed5565b6118f66123f7565b6111b981613061565b6119076123f7565b6111b981613507565b60008060607f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff16036119705785925061199e565b61199b87877f0000000000000000000000000000000000000000000000000000000000000000610b02565b92505b7f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff16831115611a3d576040517f6a92a483000000000000000000000000000000000000000000000000000000008152600481018490526bffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166024820152604401610d09565b67ffffffffffffffff881660009081526009602052604081206001015463ffffffff1690611a6c8787846135f1565b9050806020015193508484611af3836040805182516024820152602092830151151560448083019190915282518083039091018152606490910190915290810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f181dcf100000000000000000000000000000000000000000000000000000000017905290565b9450945094505050955095509592505050565b6060610eee600b6123a5565b604080518082019091526000808252602082015273ffffffffffffffffffffffffffffffffffffffff8281166000908152600760209081526040918290208251808401909352549283168083527401000000000000000000000000000000000000000090930460ff169082015290611c0557505073ffffffffffffffffffffffffffffffffffffffff166000908152600660209081526040918290208251808401909352547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811683527c0100000000000000000000000000000000000000000000000000000000900463ffffffff169082015290565b610b698161379a565b67ffffffffffffffff8083166000908152600960209081526040808320815161020081018352815460ff808216151580845261ffff61010080850482169886019890985263ffffffff630100000085048116978601979097526701000000000000008404871660608601526b0100000000000000000000008404871660808601526f010000000000000000000000000000008404811660a086015271010000000000000000000000000000000000808504881660c087015275010000000000000000000000000000000000000000008504821660e08088019190915277010000000000000000000000000000000000000000000000860483169987019990995279010000000000000000000000000000000000000000000000000085049091166101208601527b01000000000000000000000000000000000000000000000000000000909304861661014085015260019094015480861661016085015264010000000081049098166101808401526c0100000000000000000000000088049094166101a0830152700100000000000000000000000000000000870490931615156101c08201527fffffffff000000000000000000000000000000000000000000000000000000009290950490921b166101e0840152909190611e28576040517f99ac52f200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff85166004820152602401610d09565b611e43611e3b60808501606086016142f8565b600b90613929565b611ea257611e5760808401606085016142f8565b6040517f2502348c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610d09565b6000611eb160408501856156f5565b9150611f0d905082611ec66020870187615690565b905083611ed38880615690565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061395892505050565b600080611f29611f2360808801606089016142f8565b88612129565b9092509050600080808515611f6c57611f60878b611f4d60808d0160608e016142f8565b88611f5b60408f018f6156f5565b613a02565b91945092509050611f8c565b6101a0870151611f899063ffffffff16662386f26fc100006155d1565b92505b61010087015160009061ffff1615611fd057611fcd886dffffffffffffffffffffffffffff607088901c16611fc460208e018e615690565b90508a86613cda565b90505b61018088015160009067ffffffffffffffff16611ff9611ff360808e018e615690565b8c613d8a565b600001518563ffffffff168b60a0015161ffff168e806020019061201d9190615690565b6120289291506155d1565b8c6080015163ffffffff1661203d91906158b0565b61204791906158b0565b61205191906158b0565b61206b906dffffffffffffffffffffffffffff89166155d1565b61207591906155d1565b9050867bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168282600860008f60600160208101906120af91906142f8565b73ffffffffffffffffffffffffffffffffffffffff1681526020810191909152604001600020546120ea9067ffffffffffffffff16896155d1565b6120f491906158b0565b6120fe91906158b0565b61210891906155e8565b9c9b505050505050505050505050565b6121206123f7565b6111b981613e4b565b67ffffffffffffffff811660009081526005602090815260408083208151808301909252547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811682527c0100000000000000000000000000000000000000000000000000000000900463ffffffff16918101829052829182036121e1576040517f2e59db3a00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff85166004820152602401610d09565b6000816020015163ffffffff16426121f991906158c3565b90507f000000000000000000000000000000000000000000000000000000000000000063ffffffff1681111561229a576040517ff08bcb3e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8616600482015263ffffffff7f000000000000000000000000000000000000000000000000000000000000000016602482015260448101829052606401610d09565b6122a3866122b4565b9151919350909150505b9250929050565b6000806122c083611b12565b9050806020015163ffffffff16600014806122f8575080517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16155b15612347576040517f06439c6b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152602401610d09565b5192915050565b7fd7ed2ad4000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316016111fa576123a081613f40565b505050565b60606000610b6983613ff3565b6123bd600233613929565b6123f5576040517fd86ad9cf000000000000000000000000000000000000000000000000000000008152336004820152602401610d09565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633146123f5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610d09565b60005b81518110156111fa57600082828151811061249857612498615623565b60209081029190910181015180518183015173ffffffffffffffffffffffffffffffffffffffff80831660008181526007875260409081902084518154868a018051929096167fffffffffffffffffffffff00000000000000000000000000000000000000000090911681177401000000000000000000000000000000000000000060ff9384160217909255825191825293519093169683019690965293955091939092917f08a5f7f5bb38a81d8e43aca13ecd76431dbf8816ae4699affff7b00b2fc1c464910160405180910390a250505080600101905061247b565b600061262f82600001518360600151846020015185604001516040805173ffffffffffffffffffffffffffffffffffffffff80871660208301528516918101919091527fffffffffffffffffffff00000000000000000000000000000000000000000000831660608201527fffff0000000000000000000000000000000000000000000000000000000000008216608082015260009060a001604051602081830303815290604052805190602001209050949350505050565b60808301516000828152600460205260409081902080549215157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00909316929092179091555190915081907f32a4ba3fa3351b11ad555d4c8ec70a744e8705607077a946807030d64b6ab1a39061273c908590600060a08201905073ffffffffffffffffffffffffffffffffffffffff8084511683527fffffffffffffffffffff0000000000000000000000000000000000000000000060208501511660208401527fffff00000000000000000000000000000000000000000000000000000000000060408501511660408401528060608501511660608401525060808301511515608083015292915050565b60405180910390a25050565b60005b8251811015612a7157600083828151811061276857612768615623565b6020026020010151905060008160000151905060005b826020015151811015612a63576000836020015182815181106127a3576127a3615623565b60200260200101516020015190506000846020015183815181106127c9576127c9615623565b6020026020010151600001519050602063ffffffff16826080015163ffffffff16101561284c5760808201516040517f24ecdc0200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8316600482015263ffffffff9091166024820152604401610d09565b67ffffffffffffffff84166000818152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff86168085529083529281902086518154938801518389015160608a015160808b015160a08c015115157201000000000000000000000000000000000000027fffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffff63ffffffff9283166e01000000000000000000000000000002167fffffffffffffffffffffffffff0000000000ffffffffffffffffffffffffffff9383166a0100000000000000000000027fffffffffffffffffffffffffffffffffffff00000000ffffffffffffffffffff61ffff9096166801000000000000000002959095167fffffffffffffffffffffffffffffffffffff000000000000ffffffffffffffff968416640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000909b16939097169290921798909817939093169390931717919091161792909217909155519091907f94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b590612a51908690600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60405180910390a3505060010161277e565b50505080600101905061274b565b5060005b81518110156123a0576000828281518110612a9257612a92615623565b60200260200101516000015190506000838381518110612ab457612ab4615623565b60209081029190910181015181015167ffffffffffffffff84166000818152600a8452604080822073ffffffffffffffffffffffffffffffffffffffff8516808452955280822080547fffffffffffffffffffffffffff000000000000000000000000000000000000001690555192945090917f4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b9190a35050600101612a75565b60005b8251811015612bf857612b8e838281518110612b7657612b76615623565b6020026020010151600b61404f90919063ffffffff16565b15612bf057828181518110612ba557612ba5615623565b602002602001015173ffffffffffffffffffffffffffffffffffffffff167fdf1b1bd32a69711488d71554706bb130b1fc63a5fa1a2cd85e8440f84065ba2360405160405180910390a25b600101612b58565b5060005b81518110156123a057612c32828281518110612c1a57612c1a615623565b6020026020010151600b61407190919063ffffffff16565b15612c9457818181518110612c4957612c49615623565b602002602001015173ffffffffffffffffffffffffffffffffffffffff167f1795838dc8ab2ffc5f431a1729a6afa0b587f982f7b2be0b9d7187a1ef547f9160405160405180910390a25b600101612bfc565b6040810151604a820151605e90920151909260609290921c91565b6040805173ffffffffffffffffffffffffffffffffffffffff868116602080840191909152908616828401527fffffffffffffffffffff00000000000000000000000000000000000000000000851660608301527fffff00000000000000000000000000000000000000000000000000000000000084166080808401919091528351808403909101815260a09092018352815191810191909120600081815260049092529190205460ff16612e08576040517f097e17ff00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8087166004830152851660248201527fffffffffffffffffffff00000000000000000000000000000000000000000000841660448201527fffff00000000000000000000000000000000000000000000000000000000000083166064820152608401610d09565b5050505050565b600080612e1c84866158d6565b9050600060248260ff161115612e5357612e376024836158ef565b612e4290600a615a28565b612e4c90856155e8565b9050612e76565b612e5e8260246158ef565b612e6990600a615a28565b612e7390856155d1565b90505b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811115612ecc576040517f10cb51d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b95945050505050565b602081015160005b8151811015612f70576000828281518110612efa57612efa615623565b60200260200101519050612f1881600261409390919063ffffffff16565b15612f675760405173ffffffffffffffffffffffffffffffffffffffff821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b50600101612edd565b50815160005b81518110156111a2576000828281518110612f9357612f93615623565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603613003576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61300e60028261404f565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a150600101612f76565b60005b81518110156111fa57600082828151811061308157613081615623565b60200260200101519050600083838151811061309f5761309f615623565b60200260200101516000015190506000826020015190508167ffffffffffffffff16600014806130d8575061016081015163ffffffff16155b8061312a57506101e08101517fffffffff00000000000000000000000000000000000000000000000000000000167f2812d52c0000000000000000000000000000000000000000000000000000000014155b806131495750806060015163ffffffff1681610160015163ffffffff16115b1561318c576040517fc35aa79d00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff83166004820152602401610d09565b67ffffffffffffffff821660009081526009602052604081206001015471010000000000000000000000000000000000900460e01b7fffffffff00000000000000000000000000000000000000000000000000000000169003613230578167ffffffffffffffff167fd31c671936387b2f84ed402b553bd50c0e9c20408ea4e91a836d77b8180fb724826040516132239190614a93565b60405180910390a2613273565b8167ffffffffffffffff167f1edd6f3553cfa16f10b95b195abae3a1cfca4783de4843f95d674b1e1df5ab208260405161326a9190614a93565b60405180910390a25b80600960008467ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548161ffff021916908361ffff16021790555060408201518160000160036101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160076101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600b6101000a81548163ffffffff021916908363ffffffff16021790555060a082015181600001600f6101000a81548161ffff021916908361ffff16021790555060c08201518160000160116101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160000160156101000a81548161ffff021916908361ffff1602179055506101008201518160000160176101000a81548161ffff021916908361ffff1602179055506101208201518160000160196101000a81548161ffff021916908361ffff16021790555061014082015181600001601b6101000a81548163ffffffff021916908363ffffffff1602179055506101608201518160010160006101000a81548163ffffffff021916908363ffffffff1602179055506101808201518160010160046101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506101a082015181600101600c6101000a81548163ffffffff021916908363ffffffff1602179055506101c08201518160010160106101000a81548160ff0219169083151502179055506101e08201518160010160116101000a81548163ffffffff021916908360e01c0217905550905050505050806001019050613064565b60005b81518110156111fa57600082828151811061352757613527615623565b6020026020010151600001519050600083838151811061354957613549615623565b60209081029190910181015181015173ffffffffffffffffffffffffffffffffffffffff841660008181526008845260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff85169081179091559051908152919350917fbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d910160405180910390a2505060010161350a565b6040805180820190915260008082526020820152600083900361363257506040805180820190915267ffffffffffffffff8216815260006020820152610b69565b600061363e8486615a37565b9050600061364f8560048189615a7d565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505050507fffffffff0000000000000000000000000000000000000000000000000000000082167fe7e230f000000000000000000000000000000000000000000000000000000000016136ec57808060200190518101906136e39190615aa7565b92505050610b69565b7f6859a837000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831601613768576040518060400160405280828060200190518101906137549190615ad3565b815260006020909101529250610b69915050565b6040517f5247fdce00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080518082019091526000808252602082015260008260000151905060008173ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015613804573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138289190615b06565b5050509150506000811215613869576040517f10cb51d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006138e88373ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156138b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138dd9190615b56565b866020015184612e0f565b604080518082019091527bffffffffffffffffffffffffffffffffffffffffffffffffffffffff909116815263ffffffff4216602082015295945050505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515610b69565b836040015163ffffffff168311156139b15760408085015190517f8693378900000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015260248101849052604401610d09565b836020015161ffff168211156139f3576040517f4c056b6a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6111a2846101e001518261234e565b6000808083815b81811015613ccc576000878783818110613a2557613a25615623565b905060400201803603810190613a3b9190615b73565b67ffffffffffffffff8c166000908152600a60209081526040808320845173ffffffffffffffffffffffffffffffffffffffff168452825291829020825160c081018452905463ffffffff8082168352640100000000820481169383019390935268010000000000000000810461ffff16938201939093526a01000000000000000000008304821660608201526e01000000000000000000000000000083049091166080820152720100000000000000000000000000000000000090910460ff16151560a0820181905291925090613b5b576101208d0151613b289061ffff16662386f26fc100006155d1565b613b3290886158b0565b96508c610140015186613b459190615bac565b9550613b52602086615bac565b94505050613cc4565b604081015160009061ffff1615613c145760008c73ffffffffffffffffffffffffffffffffffffffff16846000015173ffffffffffffffffffffffffffffffffffffffff1614613bb7578351613bb0906122b4565b9050613bba565b508a5b620186a0836040015161ffff16613bfc8660200151847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166140b590919063ffffffff16565b613c0691906155d1565b613c1091906155e8565b9150505b6060820151613c239088615bac565b9650816080015186613c359190615bac565b8251909650600090613c549063ffffffff16662386f26fc100006155d1565b905080821015613c7357613c68818a6158b0565b985050505050613cc4565b6000836020015163ffffffff16662386f26fc10000613c9291906155d1565b905080831115613cb257613ca6818b6158b0565b99505050505050613cc4565b613cbc838b6158b0565b995050505050505b600101613a09565b505096509650969350505050565b60008063ffffffff8316613cf0610160866155d1565b613cfc876101c06158b0565b613d0691906158b0565b613d1091906158b0565b905060008760c0015163ffffffff168860e0015161ffff1683613d3391906155d1565b613d3d91906158b0565b61010089015190915061ffff16613d646dffffffffffffffffffffffffffff8916836155d1565b613d6e91906155d1565b613d7e90655af3107a40006155d1565b98975050505050505050565b60408051808201909152600080825260208201526000613db6858585610160015163ffffffff166135f1565b9050826060015163ffffffff1681600001511115613e00576040517f4c4fc93a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b826101c001518015613e1457508060200151155b15610b66576040517fee433e9900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff821603613eca576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610d09565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60008151602014613f7f57816040517f8d666f60000000000000000000000000000000000000000000000000000000008152600401610d099190614504565b600082806020019051810190613f959190615ad3565b905073ffffffffffffffffffffffffffffffffffffffff811180613fba575061040081105b156112c357826040517f8d666f60000000000000000000000000000000000000000000000000000000008152600401610d099190614504565b60608160000180548060200260200160405190810160405280929190818152602001828054801561404357602002820191906000526020600020905b81548152602001906001019080831161402f575b50505050509050919050565b6000610b698373ffffffffffffffffffffffffffffffffffffffff84166140f2565b6000610b698373ffffffffffffffffffffffffffffffffffffffff8416614141565b6000610b698373ffffffffffffffffffffffffffffffffffffffff841661423b565b6000670de0b6b3a76400006140e8837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff86166155d1565b610b6991906155e8565b6000818152600183016020526040812054614139575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556112c3565b5060006112c3565b6000818152600183016020526040812054801561422a5760006141656001836158c3565b8554909150600090614179906001906158c3565b90508082146141de57600086600001828154811061419957614199615623565b90600052602060002001549050808760000184815481106141bc576141bc615623565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806141ef576141ef615bc9565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506112c3565b60009150506112c3565b5092915050565b6000818152600183016020526040812054801561422a57600061425f6001836158c3565b8554909150600090614273906001906158c3565b90508181146141de57600086600001828154811061419957614199615623565b803573ffffffffffffffffffffffffffffffffffffffff811681146142b757600080fd5b919050565b6000806000606084860312156142d157600080fd5b6142da84614293565b9250602084013591506142ef60408501614293565b90509250925092565b60006020828403121561430a57600080fd5b610b6982614293565b803567ffffffffffffffff811681146142b757600080fd5b60008083601f84011261433d57600080fd5b50813567ffffffffffffffff81111561435557600080fd5b6020830191508360208260051b85010111156122ad57600080fd5b60008060008060006060868803121561438857600080fd5b61439186614313565b9450602086013567ffffffffffffffff808211156143ae57600080fd5b6143ba89838a0161432b565b909650945060408801359150808211156143d357600080fd5b818801915088601f8301126143e757600080fd5b8135818111156143f657600080fd5b8960208260061b850101111561440b57600080fd5b9699959850939650602001949392505050565b6000815180845260005b8181101561444457602081850181015186830182015201614428565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b828110156144f7577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526144e585835161441e565b945092850192908501906001016144ab565b5092979650505050505050565b602081526000610b69602083018461441e565b6020808252825182820181905260009190848201906040850190845b8181101561456557835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101614533565b50909695505050505050565b60006020828403121561458357600080fd5b813567ffffffffffffffff81111561459a57600080fd5b820160408185031215610b6957600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff811182821017156145fe576145fe6145ac565b60405290565b60405160a0810167ffffffffffffffff811182821017156145fe576145fe6145ac565b60405160c0810167ffffffffffffffff811182821017156145fe576145fe6145ac565b604051610200810167ffffffffffffffff811182821017156145fe576145fe6145ac565b6040516060810167ffffffffffffffff811182821017156145fe576145fe6145ac565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156146d8576146d86145ac565b604052919050565b600067ffffffffffffffff8211156146fa576146fa6145ac565b5060051b60200190565b60ff811681146111b957600080fd5b6000602080838503121561472657600080fd5b823567ffffffffffffffff81111561473d57600080fd5b8301601f8101851361474e57600080fd5b803561476161475c826146e0565b614691565b8181526060918202830184019184820191908884111561478057600080fd5b938501935b83851015614820578489038181121561479e5760008081fd5b6147a66145db565b6147af87614293565b81526040807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0840112156147e35760008081fd5b6147eb6145db565b92506147f8898901614293565b835287013561480681614704565b828901528088019190915283529384019391850191614785565b50979650505050505050565b80151581146111b957600080fd5b80356142b78161482c565b6000602080838503121561485857600080fd5b823567ffffffffffffffff81111561486f57600080fd5b8301601f8101851361488057600080fd5b803561488e61475c826146e0565b81815260a091820283018401918482019190888411156148ad57600080fd5b938501935b838510156148205780858a0312156148ca5760008081fd5b6148d2614604565b6148db86614293565b8152868601357fffffffffffffffffffff00000000000000000000000000000000000000000000811681146149105760008081fd5b818801526040868101357fffff000000000000000000000000000000000000000000000000000000000000811681146149495760008081fd5b90820152606061495a878201614293565b9082015260808681013561496d8161482c565b90820152835293840193918501916148b2565b6000806020838503121561499357600080fd5b823567ffffffffffffffff8111156149aa57600080fd5b6149b68582860161432b565b90969095509350505050565b602080825282518282018190526000919060409081850190868401855b82811015614a3057614a2084835180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16825260209081015163ffffffff16910152565b92840192908501906001016149df565b5091979650505050505050565b600060208284031215614a4f57600080fd5b610b6982614313565b81517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16815260208083015163ffffffff1690820152604081016112c3565b81511515815261020081016020830151614ab3602084018261ffff169052565b506040830151614acb604084018263ffffffff169052565b506060830151614ae3606084018263ffffffff169052565b506080830151614afb608084018263ffffffff169052565b5060a0830151614b1160a084018261ffff169052565b5060c0830151614b2960c084018263ffffffff169052565b5060e0830151614b3f60e084018261ffff169052565b506101008381015161ffff9081169184019190915261012080850151909116908301526101408084015163ffffffff90811691840191909152610160808501518216908401526101808085015167ffffffffffffffff16908401526101a080850151909116908301526101c0808401511515908301526101e0808401517fffffffff000000000000000000000000000000000000000000000000000000008116828501525b505092915050565b803563ffffffff811681146142b757600080fd5b803561ffff811681146142b757600080fd5b600082601f830112614c2357600080fd5b81356020614c3361475c836146e0565b82815260069290921b84018101918181019086841115614c5257600080fd5b8286015b84811015614c9f5760408189031215614c6f5760008081fd5b614c776145db565b614c8082614313565b8152614c8d858301614293565b81860152835291830191604001614c56565b509695505050505050565b60008060408385031215614cbd57600080fd5b67ffffffffffffffff83351115614cd357600080fd5b83601f843585010112614ce557600080fd5b614cf561475c84358501356146e0565b8335840180358083526020808401939260059290921b90910101861015614d1b57600080fd5b602085358601015b85358601803560051b01602001811015614f285767ffffffffffffffff81351115614d4d57600080fd5b8035863587010160407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0828a03011215614d8657600080fd5b614d8e6145db565b614d9a60208301614313565b815267ffffffffffffffff60408301351115614db557600080fd5b88603f604084013584010112614dca57600080fd5b614de061475c60206040850135850101356146e0565b6020604084810135850182810135808552928401939260e00201018b1015614e0757600080fd5b6040808501358501015b6040858101358601602081013560e0020101811015614f095760e0818d031215614e3a57600080fd5b614e426145db565b614e4b82614293565b815260c07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0838f03011215614e7f57600080fd5b614e87614627565b614e9360208401614bec565b8152614ea160408401614bec565b6020820152614eb260608401614c00565b6040820152614ec360808401614bec565b6060820152614ed460a08401614bec565b6080820152614ee660c084013561482c565b60c083013560a0820152602082810191909152908452929092019160e001614e11565b5080602084015250508085525050602083019250602081019050614d23565b5092505067ffffffffffffffff60208401351115614f4557600080fd5b614f558460208501358501614c12565b90509250929050565b600082601f830112614f6f57600080fd5b81356020614f7f61475c836146e0565b8083825260208201915060208460051b870101935086841115614fa157600080fd5b602086015b84811015614c9f57614fb781614293565b8352918301918301614fa6565b60008060408385031215614fd757600080fd5b823567ffffffffffffffff80821115614fef57600080fd5b614ffb86838701614f5e565b9350602085013591508082111561501157600080fd5b5061501e85828601614f5e565b9150509250929050565b60008083601f84011261503a57600080fd5b50813567ffffffffffffffff81111561505257600080fd5b6020830191508360208285010111156122ad57600080fd5b6000806000806040858703121561508057600080fd5b843567ffffffffffffffff8082111561509857600080fd5b6150a488838901615028565b909650945060208701359150808211156150bd57600080fd5b506150ca87828801615028565b95989497509550505050565b600080604083850312156150e957600080fd5b6150f283614313565b9150614f5560208401614293565b60006020828403121561511257600080fd5b813567ffffffffffffffff8082111561512a57600080fd5b908301906040828603121561513e57600080fd5b6151466145db565b82358281111561515557600080fd5b61516187828601614f5e565b82525060208301358281111561517657600080fd5b61518287828601614f5e565b60208301525095945050505050565b80357fffffffff00000000000000000000000000000000000000000000000000000000811681146142b757600080fd5b600060208083850312156151d457600080fd5b823567ffffffffffffffff8111156151eb57600080fd5b8301601f810185136151fc57600080fd5b803561520a61475c826146e0565b818152610220918202830184019184820191908884111561522a57600080fd5b938501935b8385101561482057848903818112156152485760008081fd5b6152506145db565b61525987614313565b8152610200807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08401121561528e5760008081fd5b61529661464a565b92506152a389890161483a565b835260406152b2818a01614c00565b8a85015260606152c3818b01614bec565b82860152608091506152d6828b01614bec565b9085015260a06152e78a8201614bec565b8286015260c091506152fa828b01614c00565b9085015260e061530b8a8201614bec565b82860152610100915061531f828b01614c00565b908501526101206153318a8201614c00565b828601526101409150615345828b01614c00565b908501526101606153578a8201614bec565b82860152610180915061536b828b01614bec565b908501526101a061537d8a8201614313565b828601526101c09150615391828b01614bec565b908501526101e06153a38a820161483a565b828601526153b2838b01615191565b908501525050808801919091528352938401939185019161522f565b600060208083850312156153e157600080fd5b823567ffffffffffffffff8111156153f857600080fd5b8301601f8101851361540957600080fd5b803561541761475c826146e0565b81815260069190911b8201830190838101908783111561543657600080fd5b928401925b8284101561548857604084890312156154545760008081fd5b61545c6145db565b61546585614293565b8152615472868601614313565b818701528252604093909301929084019061543b565b979650505050505050565b6000806000806000608086880312156154ab57600080fd5b6154b486614313565b94506154c260208701614293565b935060408601359250606086013567ffffffffffffffff8111156154e557600080fd5b6154f188828901615028565b969995985093965092949392505050565b8381528215156020820152606060408201526000612ecc606083018461441e565b6000806040838503121561553657600080fd5b61553f83614313565b9150602083013567ffffffffffffffff81111561555b57600080fd5b830160a0818603121561556d57600080fd5b809150509250929050565b6000806040838503121561558b57600080fd5b61559483614293565b9150614f5560208401614313565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80820281158282048414176112c3576112c36155a2565b60008261561e577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6183360301811261568657600080fd5b9190910192915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126156c557600080fd5b83018035915067ffffffffffffffff8211156156e057600080fd5b6020019150368190038213156122ad57600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261572a57600080fd5b83018035915067ffffffffffffffff82111561574557600080fd5b6020019150600681901b36038213156122ad57600080fd5b80357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811681146142b757600080fd5b60006040828403121561579b57600080fd5b6157a36145db565b6157ac83614293565b81526157ba6020840161575d565b60208201529392505050565b6000604082840312156157d857600080fd5b6157e06145db565b6157ac83614313565b600060208083850312156157fc57600080fd5b823567ffffffffffffffff81111561581357600080fd5b8301601f8101851361582457600080fd5b803561583261475c826146e0565b8181526060918202830184019184820191908884111561585157600080fd5b938501935b838510156148205780858a03121561586e5760008081fd5b61587661466e565b61587f86614293565b815261588c87870161575d565b87820152604061589d818801614bec565b9082015283529384019391850191615856565b808201808211156112c3576112c36155a2565b818103818111156112c3576112c36155a2565b60ff81811683821601908111156112c3576112c36155a2565b60ff82811682821603908111156112c3576112c36155a2565b600181815b8085111561596157817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115615947576159476155a2565b8085161561595457918102915b93841c939080029061590d565b509250929050565b600082615978575060016112c3565b81615985575060006112c3565b816001811461599b57600281146159a5576159c1565b60019150506112c3565b60ff8411156159b6576159b66155a2565b50506001821b6112c3565b5060208310610133831016604e8410600b84101617156159e4575081810a6112c3565b6159ee8383615908565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115615a2057615a206155a2565b029392505050565b6000610b6960ff841683615969565b7fffffffff000000000000000000000000000000000000000000000000000000008135818116916004851015614be45760049490940360031b84901b1690921692915050565b60008085851115615a8d57600080fd5b83861115615a9a57600080fd5b5050820193919092039150565b600060408284031215615ab957600080fd5b615ac16145db565b8251815260208301516157ba8161482c565b600060208284031215615ae557600080fd5b5051919050565b805169ffffffffffffffffffff811681146142b757600080fd5b600080600080600060a08688031215615b1e57600080fd5b615b2786615aec565b9450602086015193506040860151925060608601519150615b4a60808701615aec565b90509295509295909350565b600060208284031215615b6857600080fd5b8151610b6981614704565b600060408284031215615b8557600080fd5b615b8d6145db565b615b9683614293565b8152602083013560208201528091505092915050565b63ffffffff818116838216019080821115614234576142346155a2565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea164736f6c6343000818000a", } var FeeQuoterABI = FeeQuoterMetaData.ABI diff --git a/core/gethwrappers/ccip/generated/multi_ocr3_helper/multi_ocr3_helper.go b/core/gethwrappers/ccip/generated/multi_ocr3_helper/multi_ocr3_helper.go index d51e398b43..2f2dfbf821 100644 --- a/core/gethwrappers/ccip/generated/multi_ocr3_helper/multi_ocr3_helper.go +++ b/core/gethwrappers/ccip/generated/multi_ocr3_helper/multi_ocr3_helper.go @@ -59,7 +59,7 @@ type MultiOCR3BaseOracle struct { var MultiOCR3HelperMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"actual\",\"type\":\"bytes32\"}],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"ForkedChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enumMultiOCR3Base.InvalidConfigErrorType\",\"name\":\"errorType\",\"type\":\"uint8\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonUniqueSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OracleCannotBeZeroAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignaturesOutOfRegistration\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"StaticConfigCannotBeChanged\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedTransmitter\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"WrongMessageLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WrongNumberOfSignatures\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"AfterConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"oracleAddress\",\"type\":\"address\"}],\"name\":\"getOracle\",\"outputs\":[{\"components\":[{\"internalType\":\"uint8\",\"name\":\"index\",\"type\":\"uint8\"},{\"internalType\":\"enumMultiOCR3Base.Role\",\"name\":\"role\",\"type\":\"uint8\"}],\"internalType\":\"structMultiOCR3Base.Oracle\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"latestConfigDetails\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"n\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"}],\"internalType\":\"structMultiOCR3Base.ConfigInfo\",\"name\":\"configInfo\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfig\",\"name\":\"ocrConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfigArgs[]\",\"name\":\"ocrConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"setOCR3Configs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"setTransmitOcrPluginType\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"rawVs\",\"type\":\"bytes32\"}],\"name\":\"transmitWithSignatures\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"transmitWithoutSignatures\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]", - Bin: "0x60a06040523480156200001157600080fd5b503380600081620000695760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b03848116919091179091558116156200009c576200009c81620000a9565b5050466080525062000154565b336001600160a01b03821603620001035760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000060565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b608051611db66200017760003960008181610efc0152610f480152611db66000f3fe608060405234801561001057600080fd5b50600436106100be5760003560e01c80637ac0aa1a11610076578063c673e5841161005b578063c673e584146101c5578063f2fde38b146101e5578063f716f99f146101f857600080fd5b80637ac0aa1a1461015b5780638da5cb5b1461019d57600080fd5b806334a9c92e116100a757806334a9c92e1461012057806344e65e551461014057806379ba50971461015357600080fd5b8063181f5a77146100c357806326bf9d261461010b575b600080fd5b604080518082018252601981527f4d756c74694f4352334261736548656c70657220312e302e300000000000000060208201529051610102919061153c565b60405180910390f35b61011e610119366004611603565b61020b565b005b61013361012e366004611691565b61023a565b60405161010291906116f3565b61011e61014e366004611766565b6102ca565b61011e61034d565b61011e610169366004611819565b600480547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff92909216919091179055565b60005460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610102565b6101d86101d3366004611819565b61044f565b604051610102919061188d565b61011e6101f3366004611920565b6105c7565b61011e610206366004611a8c565b6105db565b604080516000808252602082019092526004549091506102349060ff168585858580600061061d565b50505050565b6040805180820182526000808252602080830182905260ff86811683526003825284832073ffffffffffffffffffffffffffffffffffffffff871684528252918490208451808601909552805480841686529394939092918401916101009091041660028111156102ad576102ad6116c4565b60028111156102be576102be6116c4565b90525090505b92915050565b60045460408051602080880282810182019093528782526103439360ff16928c928c928c928c918c91829185019084908082843760009201919091525050604080516020808d0282810182019093528c82529093508c92508b9182918501908490808284376000920191909152508a925061061d915050565b5050505050505050565b60015473ffffffffffffffffffffffffffffffffffffffff1633146103d3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6104926040805160e081019091526000606082018181526080830182905260a0830182905260c08301919091528190815260200160608152602001606081525090565b60ff808316600090815260026020818152604092839020835160e081018552815460608201908152600183015480881660808401526101008104881660a0840152620100009004909616151560c08201529485529182018054845181840281018401909552808552929385830193909283018282801561054857602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff16815260019091019060200180831161051d575b50505050508152602001600382018054806020026020016040519081016040528092919081815260200182805480156105b757602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff16815260019091019060200180831161058c575b5050505050815250509050919050565b6105cf6109a1565b6105d881610a24565b50565b6105e36109a1565b60005b81518110156106195761061182828151811061060457610604611bf5565b6020026020010151610b19565b6001016105e6565b5050565b60ff8781166000908152600260209081526040808320815160808101835281548152600190910154808616938201939093526101008304851691810191909152620100009091049092161515606083015287359061067c8760a4611c53565b90508260600151156106c4578451610695906020611c66565b86516106a2906020611c66565b6106ad9060a0611c53565b6106b79190611c53565b6106c19082611c53565b90505b368114610706576040517f8e1192e1000000000000000000000000000000000000000000000000000000008152600481018290523660248201526044016103ca565b508151811461074e5781516040517f93df584c0000000000000000000000000000000000000000000000000000000081526004810191909152602481018290526044016103ca565b610756610ef9565b60ff808a16600090815260036020908152604080832033845282528083208151808301909252805480861683529394919390928401916101009091041660028111156107a4576107a46116c4565b60028111156107b5576107b56116c4565b90525090506002816020015160028111156107d2576107d26116c4565b1480156108335750600260008b60ff1660ff168152602001908152602001600020600301816000015160ff168154811061080e5761080e611bf5565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1633145b610869576040517fda0f08e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5081606001511561094b576020820151610884906001611c7d565b60ff168551146108c0576040517f71253a2500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83518551146108fb576040517fa75d88af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000878760405161090d929190611c96565b604051908190038120610924918b90602001611ca6565b6040516020818303038152906040528051906020012090506109498a82888888610f7a565b505b6040805182815260208a81013567ffffffffffffffff169082015260ff8b16917f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef0910160405180910390a2505050505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610a22576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016103ca565b565b3373ffffffffffffffffffffffffffffffffffffffff821603610aa3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016103ca565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b806040015160ff16600003610b5d5760006040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016103ca9190611cba565b60208082015160ff80821660009081526002909352604083206001810154929390928392169003610bca57606084015160018201805491151562010000027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff909216919091179055610c1f565b6060840151600182015460ff6201000090910416151590151514610c1f576040517f87f6037c00000000000000000000000000000000000000000000000000000000815260ff841660048201526024016103ca565b60a08401518051601f60ff82161115610c675760016040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016103ca9190611cba565b610cda8585600301805480602002602001604051908101604052809291908181526020018280548015610cd057602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610ca5575b50505050506111b2565b856060015115610e4857610d558585600201805480602002602001604051908101604052809291908181526020018280548015610cd05760200282019190600052602060002090815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610ca55750505050506111b2565b60808601518051610d6f906002870190602084019061147e565b5080516001850180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1661010060ff841690810291909117909155601f1015610de85760026040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016103ca9190611cba565b6040880151610df8906003611cd4565b60ff168160ff1611610e395760036040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016103ca9190611cba565b610e458783600161124a565b50505b610e548583600261124a565b8151610e69906003860190602085019061147e565b506040868101516001850180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff8316179055875180865560a089015192517fab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f54793610ee0938a939260028b01929190611cf7565b60405180910390a1610ef185611445565b505050505050565b467f000000000000000000000000000000000000000000000000000000000000000014610a22576040517f0f01ce850000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060048201524660248201526044016103ca565b610f82611508565b835160005b81811015610343576000600188868460208110610fa657610fa6611bf5565b610fb391901a601b611c7d565b898581518110610fc557610fc5611bf5565b6020026020010151898681518110610fdf57610fdf611bf5565b60200260200101516040516000815260200160405260405161101d949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa15801561103f573d6000803e3d6000fd5b5050604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081015160ff808e1660009081526003602090815285822073ffffffffffffffffffffffffffffffffffffffff8516835281528582208587019096528554808416865293975090955092939284019161010090041660028111156110cb576110cb6116c4565b60028111156110dc576110dc6116c4565b90525090506001816020015160028111156110f9576110f96116c4565b14611130576040517fca31867a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051859060ff16601f811061114757611147611bf5565b602002015115611183576040517ff67bc7c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600185826000015160ff16601f811061119e5761119e611bf5565b911515602090920201525050600101610f87565b60005b81518110156112455760ff8316600090815260036020526040812083519091908490849081106111e7576111e7611bf5565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff16825281019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001690556001016111b5565b505050565b60005b82518160ff161015610234576000838260ff168151811061127057611270611bf5565b602002602001015190506000600281111561128d5761128d6116c4565b60ff808716600090815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915290205461010090041660028111156112d9576112d96116c4565b146113135760046040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016103ca9190611cba565b73ffffffffffffffffffffffffffffffffffffffff8116611360576040517fd6c62c9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052808360ff168152602001846002811115611386576113866116c4565b905260ff808716600090815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845282529091208351815493167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00841681178255918401519092909183917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000161761010083600281111561142b5761142b6116c4565b0217905550905050508061143e90611d8a565b905061124d565b60405160ff821681527f897ac1b2c12867721b284f3eb147bd4ab046d4eef1cf31c1d8988bfcfb962b539060200160405180910390a150565b8280548282559060005260206000209081019282156114f8579160200282015b828111156114f857825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff90911617825560209092019160019091019061149e565b50611504929150611527565b5090565b604051806103e00160405280601f906020820280368337509192915050565b5b808211156115045760008155600101611528565b60006020808352835180602085015260005b8181101561156a5785810183015185820160400152820161154e565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b80606081018310156102c457600080fd5b60008083601f8401126115cc57600080fd5b50813567ffffffffffffffff8111156115e457600080fd5b6020830191508360208285010111156115fc57600080fd5b9250929050565b60008060006080848603121561161857600080fd5b61162285856115a9565b9250606084013567ffffffffffffffff81111561163e57600080fd5b61164a868287016115ba565b9497909650939450505050565b803560ff8116811461166857600080fd5b919050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461166857600080fd5b600080604083850312156116a457600080fd5b6116ad83611657565b91506116bb6020840161166d565b90509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b815160ff1681526020820151604082019060038110611714576117146116c4565b8060208401525092915050565b60008083601f84011261173357600080fd5b50813567ffffffffffffffff81111561174b57600080fd5b6020830191508360208260051b85010111156115fc57600080fd5b60008060008060008060008060e0898b03121561178257600080fd5b61178c8a8a6115a9565b9750606089013567ffffffffffffffff808211156117a957600080fd5b6117b58c838d016115ba565b909950975060808b01359150808211156117ce57600080fd5b6117da8c838d01611721565b909750955060a08b01359150808211156117f357600080fd5b506118008b828c01611721565b999c989b50969995989497949560c00135949350505050565b60006020828403121561182b57600080fd5b61183482611657565b9392505050565b60008151808452602080850194506020840160005b8381101561188257815173ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101611850565b509495945050505050565b60208152600082518051602084015260ff602082015116604084015260ff604082015116606084015260608101511515608084015250602083015160c060a08401526118dc60e084018261183b565b905060408401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08483030160c0850152611917828261183b565b95945050505050565b60006020828403121561193257600080fd5b6118348261166d565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160c0810167ffffffffffffffff8111828210171561198d5761198d61193b565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156119da576119da61193b565b604052919050565b600067ffffffffffffffff8211156119fc576119fc61193b565b5060051b60200190565b8035801515811461166857600080fd5b600082601f830112611a2757600080fd5b81356020611a3c611a37836119e2565b611993565b8083825260208201915060208460051b870101935086841115611a5e57600080fd5b602086015b84811015611a8157611a748161166d565b8352918301918301611a63565b509695505050505050565b60006020808385031215611a9f57600080fd5b823567ffffffffffffffff80821115611ab757600080fd5b818501915085601f830112611acb57600080fd5b8135611ad9611a37826119e2565b81815260059190911b83018401908481019088831115611af857600080fd5b8585015b83811015611be857803585811115611b1357600080fd5b860160c0818c037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0011215611b485760008081fd5b611b5061196a565b8882013581526040611b63818401611657565b8a8301526060611b74818501611657565b8284015260809150611b87828501611a06565b9083015260a08381013589811115611b9f5760008081fd5b611bad8f8d83880101611a16565b838501525060c0840135915088821115611bc75760008081fd5b611bd58e8c84870101611a16565b9083015250845250918601918601611afc565b5098975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156102c4576102c4611c24565b80820281158282048414176102c4576102c4611c24565b60ff81811683821601908111156102c4576102c4611c24565b8183823760009101908152919050565b828152606082602083013760800192915050565b6020810160058310611cce57611cce6116c4565b91905290565b60ff8181168382160290811690818114611cf057611cf0611c24565b5092915050565b600060a0820160ff88168352602087602085015260a0604085015281875480845260c086019150886000526020600020935060005b81811015611d5e57845473ffffffffffffffffffffffffffffffffffffffff1683526001948501949284019201611d2c565b50508481036060860152611d72818861183b565b935050505060ff831660808301529695505050505050565b600060ff821660ff8103611da057611da0611c24565b6001019291505056fea164736f6c6343000818000a", + Bin: "0x60a06040523480156200001157600080fd5b503380600081620000695760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b03848116919091179091558116156200009c576200009c81620000a9565b5050466080525062000154565b336001600160a01b03821603620001035760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000060565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b608051611d3f6200017760003960008181610ef70152610f430152611d3f6000f3fe608060405234801561001057600080fd5b50600436106100be5760003560e01c80637ac0aa1a11610076578063c673e5841161005b578063c673e584146101c5578063f2fde38b146101e5578063f716f99f146101f857600080fd5b80637ac0aa1a1461015b5780638da5cb5b1461019d57600080fd5b806334a9c92e116100a757806334a9c92e1461012057806344e65e551461014057806379ba50971461015357600080fd5b8063181f5a77146100c357806326bf9d261461010b575b600080fd5b604080518082018252601981527f4d756c74694f4352334261736548656c70657220312e302e30000000000000006020820152905161010291906114e4565b60405180910390f35b61011e6101193660046115ab565b61020b565b005b61013361012e366004611639565b61023a565b604051610102919061169b565b61011e61014e36600461170e565b6102ca565b61011e61034d565b61011e6101693660046117c1565b600480547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff92909216919091179055565b60005460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610102565b6101d86101d33660046117c1565b61044f565b6040516101029190611835565b61011e6101f33660046118c8565b6105c7565b61011e610206366004611a34565b6105db565b604080516000808252602082019092526004549091506102349060ff168585858580600061061d565b50505050565b6040805180820182526000808252602080830182905260ff86811683526003825284832073ffffffffffffffffffffffffffffffffffffffff871684528252918490208451808601909552805480841686529394939092918401916101009091041660028111156102ad576102ad61166c565b60028111156102be576102be61166c565b90525090505b92915050565b60045460408051602080880282810182019093528782526103439360ff16928c928c928c928c918c91829185019084908082843760009201919091525050604080516020808d0282810182019093528c82529093508c92508b9182918501908490808284376000920191909152508a925061061d915050565b5050505050505050565b60015473ffffffffffffffffffffffffffffffffffffffff1633146103d3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6104926040805160e081019091526000606082018181526080830182905260a0830182905260c08301919091528190815260200160608152602001606081525090565b60ff808316600090815260026020818152604092839020835160e081018552815460608201908152600183015480881660808401526101008104881660a0840152620100009004909616151560c08201529485529182018054845181840281018401909552808552929385830193909283018282801561054857602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff16815260019091019060200180831161051d575b50505050508152602001600382018054806020026020016040519081016040528092919081815260200182805480156105b757602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff16815260019091019060200180831161058c575b5050505050815250509050919050565b6105cf6109a1565b6105d881610a24565b50565b6105e36109a1565b60005b81518110156106195761061182828151811061060457610604611b9d565b6020026020010151610b19565b6001016105e6565b5050565b60ff8781166000908152600260209081526040808320815160808101835281548152600190910154808616938201939093526101008304851691810191909152620100009091049092161515606083015287359061067c8760a4611bfb565b90508260600151156106c4578451610695906020611c0e565b86516106a2906020611c0e565b6106ad9060a0611bfb565b6106b79190611bfb565b6106c19082611bfb565b90505b368114610706576040517f8e1192e1000000000000000000000000000000000000000000000000000000008152600481018290523660248201526044016103ca565b508151811461074e5781516040517f93df584c0000000000000000000000000000000000000000000000000000000081526004810191909152602481018290526044016103ca565b610756610ef4565b60ff808a16600090815260036020908152604080832033845282528083208151808301909252805480861683529394919390928401916101009091041660028111156107a4576107a461166c565b60028111156107b5576107b561166c565b90525090506002816020015160028111156107d2576107d261166c565b1480156108335750600260008b60ff1660ff168152602001908152602001600020600301816000015160ff168154811061080e5761080e611b9d565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1633145b610869576040517fda0f08e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5081606001511561094b576020820151610884906001611c25565b60ff168551146108c0576040517f71253a2500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83518551146108fb576040517fa75d88af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000878760405161090d929190611c3e565b604051908190038120610924918b90602001611c4e565b6040516020818303038152906040528051906020012090506109498a82888888610f75565b505b6040805182815260208a81013567ffffffffffffffff169082015260ff8b16917f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef0910160405180910390a2505050505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610a22576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016103ca565b565b3373ffffffffffffffffffffffffffffffffffffffff821603610aa3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016103ca565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b806040015160ff16600003610b5d5760006040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016103ca9190611c62565b60208082015160ff80821660009081526002909352604083206001810154929390928392169003610bca57606084015160018201805491151562010000027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff909216919091179055610c1f565b6060840151600182015460ff6201000090910416151590151514610c1f576040517f87f6037c00000000000000000000000000000000000000000000000000000000815260ff841660048201526024016103ca565b60a08401518051601f1015610c635760016040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016103ca9190611c62565b610cd68484600301805480602002602001604051908101604052809291908181526020018280548015610ccc57602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610ca1575b5050505050611185565b846060015115610e4457610d518484600201805480602002602001604051908101604052809291908181526020018280548015610ccc5760200282019190600052602060002090815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610ca1575050505050611185565b60808501518051610d6b9060028601906020840190611445565b5080516001840180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1661010060ff841690810291909117909155601f1015610de45760026040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016103ca9190611c62565b6040870151610df4906003611c7c565b60ff168160ff1611610e355760036040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016103ca9190611c62565b610e418683600161121d565b50505b610e508482600261121d565b8051610e659060038501906020840190611445565b506040858101516001840180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff8316179055865180855560a088015192517fab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f54793610edc9389939260028a01929190611c9f565b60405180910390a1610eed8461140c565b5050505050565b467f000000000000000000000000000000000000000000000000000000000000000014610a22576040517f0f01ce850000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060048201524660248201526044016103ca565b8251600090815b81811015610343576000600188868460208110610f9b57610f9b611b9d565b610fa891901a601b611c25565b898581518110610fba57610fba611b9d565b6020026020010151898681518110610fd457610fd4611b9d565b602002602001015160405160008152602001604052604051611012949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015611034573d6000803e3d6000fd5b5050604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081015160ff808e1660009081526003602090815285822073ffffffffffffffffffffffffffffffffffffffff8516835281528582208587019096528554808416865293975090955092939284019161010090041660028111156110c0576110c061166c565b60028111156110d1576110d161166c565b90525090506001816020015160028111156110ee576110ee61166c565b14611125576040517fca31867a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051600160ff9091161b851615611168576040517ff67bc7c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806000015160ff166001901b851794505050806001019050610f7c565b60005b81518110156112185760ff8316600090815260036020526040812083519091908490849081106111ba576111ba611b9d565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff16825281019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000169055600101611188565b505050565b60005b825181101561023457600083828151811061123d5761123d611b9d565b602002602001015190506000600281111561125a5761125a61166c565b60ff808716600090815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915290205461010090041660028111156112a6576112a661166c565b146112e05760046040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016103ca9190611c62565b73ffffffffffffffffffffffffffffffffffffffff811661132d576040517fd6c62c9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052808360ff1681526020018460028111156113535761135361166c565b905260ff808716600090815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845282529091208351815493167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00841681178255918401519092909183917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000016176101008360028111156113f8576113f861166c565b021790555090505050806001019050611220565b60405160ff821681527f897ac1b2c12867721b284f3eb147bd4ab046d4eef1cf31c1d8988bfcfb962b539060200160405180910390a150565b8280548282559060005260206000209081019282156114bf579160200282015b828111156114bf57825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909116178255602090920191600190910190611465565b506114cb9291506114cf565b5090565b5b808211156114cb57600081556001016114d0565b60006020808352835180602085015260005b81811015611512578581018301518582016040015282016114f6565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b80606081018310156102c457600080fd5b60008083601f84011261157457600080fd5b50813567ffffffffffffffff81111561158c57600080fd5b6020830191508360208285010111156115a457600080fd5b9250929050565b6000806000608084860312156115c057600080fd5b6115ca8585611551565b9250606084013567ffffffffffffffff8111156115e657600080fd5b6115f286828701611562565b9497909650939450505050565b803560ff8116811461161057600080fd5b919050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461161057600080fd5b6000806040838503121561164c57600080fd5b611655836115ff565b915061166360208401611615565b90509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b815160ff16815260208201516040820190600381106116bc576116bc61166c565b8060208401525092915050565b60008083601f8401126116db57600080fd5b50813567ffffffffffffffff8111156116f357600080fd5b6020830191508360208260051b85010111156115a457600080fd5b60008060008060008060008060e0898b03121561172a57600080fd5b6117348a8a611551565b9750606089013567ffffffffffffffff8082111561175157600080fd5b61175d8c838d01611562565b909950975060808b013591508082111561177657600080fd5b6117828c838d016116c9565b909750955060a08b013591508082111561179b57600080fd5b506117a88b828c016116c9565b999c989b50969995989497949560c00135949350505050565b6000602082840312156117d357600080fd5b6117dc826115ff565b9392505050565b60008151808452602080850194506020840160005b8381101561182a57815173ffffffffffffffffffffffffffffffffffffffff16875295820195908201906001016117f8565b509495945050505050565b60208152600082518051602084015260ff602082015116604084015260ff604082015116606084015260608101511515608084015250602083015160c060a084015261188460e08401826117e3565b905060408401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08483030160c08501526118bf82826117e3565b95945050505050565b6000602082840312156118da57600080fd5b6117dc82611615565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160c0810167ffffffffffffffff81118282101715611935576119356118e3565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611982576119826118e3565b604052919050565b600067ffffffffffffffff8211156119a4576119a46118e3565b5060051b60200190565b8035801515811461161057600080fd5b600082601f8301126119cf57600080fd5b813560206119e46119df8361198a565b61193b565b8083825260208201915060208460051b870101935086841115611a0657600080fd5b602086015b84811015611a2957611a1c81611615565b8352918301918301611a0b565b509695505050505050565b60006020808385031215611a4757600080fd5b823567ffffffffffffffff80821115611a5f57600080fd5b818501915085601f830112611a7357600080fd5b8135611a816119df8261198a565b81815260059190911b83018401908481019088831115611aa057600080fd5b8585015b83811015611b9057803585811115611abb57600080fd5b860160c0818c037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0011215611af05760008081fd5b611af8611912565b8882013581526040611b0b8184016115ff565b8a8301526060611b1c8185016115ff565b8284015260809150611b2f8285016119ae565b9083015260a08381013589811115611b475760008081fd5b611b558f8d838801016119be565b838501525060c0840135915088821115611b6f5760008081fd5b611b7d8e8c848701016119be565b9083015250845250918601918601611aa4565b5098975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156102c4576102c4611bcc565b80820281158282048414176102c4576102c4611bcc565b60ff81811683821601908111156102c4576102c4611bcc565b8183823760009101908152919050565b828152606082602083013760800192915050565b6020810160058310611c7657611c7661166c565b91905290565b60ff8181168382160290811690818114611c9857611c98611bcc565b5092915050565b600060a0820160ff88168352602087602085015260a0604085015281875480845260c086019150886000526020600020935060005b81811015611d0657845473ffffffffffffffffffffffffffffffffffffffff1683526001948501949284019201611cd4565b50508481036060860152611d1a81886117e3565b935050505060ff83166080830152969550505050505056fea164736f6c6343000818000a", } var MultiOCR3HelperABI = MultiOCR3HelperMetaData.ABI diff --git a/core/gethwrappers/ccip/generated/offramp/offramp.go b/core/gethwrappers/ccip/generated/offramp/offramp.go index 65795e0626..6f2ba32ec6 100644 --- a/core/gethwrappers/ccip/generated/offramp/offramp.go +++ b/core/gethwrappers/ccip/generated/offramp/offramp.go @@ -165,7 +165,7 @@ type OffRampUnblessedRoot struct { var OffRampMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CanOnlySelfCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"actual\",\"type\":\"bytes32\"}],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ExecutionError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"ForkedChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enumMultiOCR3Base.InvalidConfigErrorType\",\"name\":\"errorType\",\"type\":\"uint8\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"got\",\"type\":\"uint256\"}],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidEVMAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"internalType\":\"structOffRamp.Interval\",\"name\":\"interval\",\"type\":\"tuple\"}],\"name\":\"InvalidInterval\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"newLimit\",\"type\":\"uint256\"}],\"name\":\"InvalidManualExecutionGasLimit\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"messageDestChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidMessageDestChainSelector\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"newState\",\"type\":\"uint8\"}],\"name\":\"InvalidNewState\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRoot\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidStaticConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LeavesCannotBeEmpty\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ManualExecutionGasLimitMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"ManualExecutionNotYetEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"errorReason\",\"type\":\"bytes\"}],\"name\":\"MessageValidationError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonUniqueSignatures\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"notPool\",\"type\":\"address\"}],\"name\":\"NotACompatiblePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OracleCannotBeZeroAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ReceiverError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountReleased\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePre\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePost\",\"type\":\"uint256\"}],\"name\":\"ReleaseOrMintBalanceMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"name\":\"RootAlreadyCommitted\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"RootNotCommitted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignaturesOutOfRegistration\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"StaleCommitReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"StaticConfigCannotBeChanged\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"TokenDataMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"TokenHandlingError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnexpectedTokenData\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"WrongMessageLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WrongNumberOfSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroChainSelectorNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"AlreadyAttempted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"internalType\":\"structOffRamp.Interval\",\"name\":\"interval\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structOffRamp.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"report\",\"type\":\"tuple\"}],\"name\":\"CommitReportAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"DynamicConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"messageHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"name\":\"ExecutionStateChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"RootRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"SkippedAlreadyExecutedMessage\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"sourceConfig\",\"type\":\"tuple\"}],\"name\":\"SourceChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainSelectorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"}],\"name\":\"StaticConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigUpdates\",\"type\":\"tuple[]\"}],\"name\":\"applySourceChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"destTokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structClient.Any2EVMMessage\",\"name\":\"\",\"type\":\"tuple\"}],\"name\":\"ccipReceive\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"rawVs\",\"type\":\"bytes32\"}],\"name\":\"commit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"execute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"bytes[]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[]\"}],\"name\":\"executeSingleMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"getExecutionState\",\"outputs\":[{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLatestPriceSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"getMerkleRoot\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"getSourceChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"isBlessed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"latestConfigDetails\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"n\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"}],\"internalType\":\"structMultiOCR3Base.ConfigInfo\",\"name\":\"configInfo\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfig\",\"name\":\"ocrConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage[]\",\"name\":\"messages\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[][]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[][]\"},{\"internalType\":\"bytes32[]\",\"name\":\"proofs\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"proofFlagBits\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.ExecutionReportSingleChain[]\",\"name\":\"reports\",\"type\":\"tuple[]\"},{\"internalType\":\"uint256[][]\",\"name\":\"gasLimitOverrides\",\"type\":\"uint256[][]\"}],\"name\":\"manuallyExecute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structOffRamp.UnblessedRoot[]\",\"name\":\"rootToReset\",\"type\":\"tuple[]\"}],\"name\":\"resetUnblessedRoots\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"setDynamicConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfigArgs[]\",\"name\":\"ocrConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"setOCR3Configs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x6101206040523480156200001257600080fd5b5060405162006c4a38038062006c4a8339810160408190526200003591620008c7565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf81620001fa565b5050466080525060208301516001600160a01b03161580620000ec575060408301516001600160a01b0316155b8062000103575060608301516001600160a01b0316155b1562000122576040516342bcdf7f60e11b815260040160405180910390fd5b82516001600160401b03166000036200014e5760405163c656089560e01b815260040160405180910390fd5b82516001600160401b0390811660a052602080850180516001600160a01b0390811660c05260408088018051831660e0526060808a01805185166101005283518b519098168852945184169587019590955251821690850152905116908201527f683eb52ee924eb817377cfa8f41f238f4bb7a877da5267869dfffbad85f564d89060800160405180910390a1620001e682620002a5565b620001f181620003c1565b50505062000c67565b336001600160a01b03821603620002545760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b0316620002ce576040516342bcdf7f60e11b815260040160405180910390fd5b80516004805460208085018051604080880180516060808b0180516001600160a01b039b8c166001600160c01b0319909a168a17600160a01b63ffffffff98891602176001600160c01b0316600160c01b948816949094026001600160e01b031693909317600160e01b93871693909302929092179098556080808b018051600580546001600160a01b031916918d169190911790558451988952955185169688019690965290518316918601919091525116938301939093529151909216908201527fa55bd56595c45f517e5967a3067f3dca684445a3080e7c04a4e0d5a40cda627d9060a00160405180910390a150565b60005b815181101562000666576000828281518110620003e557620003e562000a1d565b60200260200101519050600081602001519050806001600160401b0316600003620004235760405163c656089560e01b815260040160405180910390fd5b81516001600160a01b03166200044c576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160401b0381166000908152600660205260408120600181018054919291620004789062000a33565b80601f0160208091040260200160405190810160405280929190818152602001828054620004a69062000a33565b8015620004f75780601f10620004cb57610100808354040283529160200191620004f7565b820191906000526020600020905b815481529060010190602001808311620004d957829003601f168201915b5050505050905060008460600151905081516000036200059e57805160000362000534576040516342bcdf7f60e11b815260040160405180910390fd5b6001830162000544828262000ac4565b508254600160a81b600160e81b031916600160a81b1783556040516001600160401b03851681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1620005d9565b8080519060200120828051906020012014620005d95760405163c39a620560e01b81526001600160401b038516600482015260240162000083565b604080860151845487516001600160a01b03166001600160a01b0319921515600160a01b02929092166001600160a81b031990911617178455516001600160401b038516907f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b906200064d90869062000b90565b60405180910390a25050505050806001019050620003c4565b5050565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b0381118282101715620006a557620006a56200066a565b60405290565b604051601f8201601f191681016001600160401b0381118282101715620006d657620006d66200066a565b604052919050565b80516001600160401b0381168114620006f657600080fd5b919050565b6001600160a01b03811681146200071157600080fd5b50565b805163ffffffff81168114620006f657600080fd5b6000601f83601f8401126200073d57600080fd5b825160206001600160401b03808311156200075c576200075c6200066a565b8260051b6200076d838201620006ab565b93845286810183019383810190898611156200078857600080fd5b84890192505b85831015620008ba57825184811115620007a85760008081fd5b89016080601f19828d038101821315620007c25760008081fd5b620007cc62000680565b88840151620007db81620006fb565b81526040620007ec858201620006de565b8a8301526060808601518015158114620008065760008081fd5b838301529385015193898511156200081e5760008081fd5b84860195508f603f8701126200083657600094508485fd5b8a8601519450898511156200084f576200084f6200066a565b620008608b858f88011601620006ab565b93508484528f82868801011115620008785760008081fd5b60005b8581101562000898578681018301518582018d01528b016200087b565b5060009484018b0194909452509182015283525091840191908401906200078e565b9998505050505050505050565b6000806000838503610140811215620008df57600080fd5b6080811215620008ee57600080fd5b620008f862000680565b6200090386620006de565b815260208601516200091581620006fb565b602082015260408601516200092a81620006fb565b604082015260608601516200093f81620006fb565b6060820152935060a0607f19820112156200095957600080fd5b5060405160a081016001600160401b0380821183831017156200098057620009806200066a565b81604052608087015191506200099682620006fb565b818352620009a760a0880162000714565b6020840152620009ba60c0880162000714565b6040840152620009cd60e0880162000714565b60608401526101008701519150620009e582620006fb565b608083018290526101208701519294508083111562000a0357600080fd5b505062000a138682870162000729565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b600181811c9082168062000a4857607f821691505b60208210810362000a6957634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111562000abf576000816000526020600020601f850160051c8101602086101562000a9a5750805b601f850160051c820191505b8181101562000abb5782815560010162000aa6565b5050505b505050565b81516001600160401b0381111562000ae05762000ae06200066a565b62000af88162000af1845462000a33565b8462000a6f565b602080601f83116001811462000b30576000841562000b175750858301515b600019600386901b1c1916600185901b17855562000abb565b600085815260208120601f198616915b8281101562000b615788860151825594840194600190910190840162000b40565b508582101562000b805787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b602080825282546001600160a01b0381168383015260a081901c60ff161515604084015260a81c6001600160401b0316606083015260808083015260018084018054600093929190849062000be58162000a33565b8060a089015260c0600183166000811462000c09576001811462000c265762000c58565b60ff19841660c08b015260c083151560051b8b0101945062000c58565b85600052602060002060005b8481101562000c4f5781548c820185015290880190890162000c32565b8b0160c0019550505b50929998505050505050505050565b60805160a05160c05160e05161010051615f7462000cd6600039600081816102660152612a010152600081816102370152612f1d0152600081816102080152818161142b015261196d0152600081816101d801526125f00152600081816117f3015261183f0152615f746000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806385572ffb116100d8578063ccd37ba31161008c578063f2fde38b11610066578063f2fde38b14610583578063f716f99f14610596578063ff888fb1146105a957600080fd5b8063ccd37ba31461050b578063d2a15d3514610550578063e9d68a8e1461056357600080fd5b8063991a5018116100bd578063991a5018146104c5578063a80036b4146104d8578063c673e584146104eb57600080fd5b806385572ffb1461049c5780638da5cb5b146104aa57600080fd5b8063311cd5131161012f5780635e36480c116101145780635e36480c146103785780637437ff9f1461039857806379ba50971461049457600080fd5b8063311cd513146103495780633f4b04aa1461035c57600080fd5b806306285c691161016057806306285c69146101a4578063181f5a77146102ed5780632d04ab761461033657600080fd5b806304666f9c1461017c57806305d938b514610191575b600080fd5b61018f61018a3660046140d8565b6105cc565b005b61018f61019f366004614764565b6105e0565b61029660408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316815250905090565b6040516102e49190815167ffffffffffffffff1681526020808301516001600160a01b0390811691830191909152604080840151821690830152606092830151169181019190915260800190565b60405180910390f35b6103296040518060400160405280601181526020017f4f666652616d7020312e362e302d64657600000000000000000000000000000081525081565b6040516102e491906148df565b61018f61034436600461498a565b610785565b61018f610357366004614a3d565b610b5c565b60095460405167ffffffffffffffff90911681526020016102e4565b61038b610386366004614a91565b610bc5565b6040516102e49190614aee565b6104376040805160a081018252600080825260208201819052918101829052606081018290526080810191909152506040805160a0810182526004546001600160a01b03808216835263ffffffff600160a01b83048116602085015278010000000000000000000000000000000000000000000000008304811694840194909452600160e01b9091049092166060820152600554909116608082015290565b6040516102e49190600060a0820190506001600160a01b03808451168352602084015163ffffffff808216602086015280604087015116604086015280606087015116606086015250508060808501511660808401525092915050565b61018f610c1b565b61018f610177366004614afc565b6000546040516001600160a01b0390911681526020016102e4565b61018f6104d3366004614b4b565b610cd9565b61018f6104e6366004614bbf565b610cea565b6104fe6104f9366004614c2c565b61105d565b6040516102e49190614c8c565b610542610519366004614d01565b67ffffffffffffffff919091166000908152600860209081526040808320938352929052205490565b6040519081526020016102e4565b61018f61055e366004614d2b565b6111bb565b610576610571366004614da0565b611275565b6040516102e49190614dbb565b61018f610591366004614e09565b611382565b61018f6105a4366004614e8e565b611393565b6105bc6105b7366004614fcc565b6113d5565b60405190151581526020016102e4565b6105d4611496565b6105dd816114f2565b50565b6105e86117f0565b815181518114610624576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8181101561077557600084828151811061064357610643614fe5565b6020026020010151905060008160200151519050600085848151811061066b5761066b614fe5565b60200260200101519050805182146106af576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b828110156107665760008282815181106106ce576106ce614fe5565b602002602001015190508060001461075d57846020015182815181106106f6576106f6614fe5565b60200260200101516080015181101561075d5784516040517fc8e9605100000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260248101839052604481018290526064015b60405180910390fd5b506001016106b2565b50505050806001019050610627565b506107808383611871565b505050565b60006107938789018961516b565b805151519091501515806107ac57508051602001515115155b156108ac5760095460208a01359067ffffffffffffffff8083169116101561086b576009805467ffffffffffffffff191667ffffffffffffffff83161790556004805483516040517f3937306f0000000000000000000000000000000000000000000000000000000081526001600160a01b0390921692633937306f92610834929101615393565b600060405180830381600087803b15801561084e57600080fd5b505af1158015610862573d6000803e3d6000fd5b505050506108aa565b8160200151516000036108aa576040517f2261116700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b60005b816020015151811015610aa5576000826020015182815181106108d4576108d4614fe5565b602002602001015190506000816000015190506108f081611921565b60006108fb82611a23565b602084015151815491925067ffffffffffffffff908116600160a81b9092041614158061093f575060208084015190810151905167ffffffffffffffff9182169116115b1561097f57825160208401516040517feefb0cac0000000000000000000000000000000000000000000000000000000081526107549291906004016153a6565b6040830151806109bb576040517f504570e300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b835167ffffffffffffffff16600090815260086020908152604080832084845290915290205415610a2e5783516040517f32cf0cbf00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260248101829052604401610754565b6020808501510151610a419060016153f1565b82547fffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffff16600160a81b67ffffffffffffffff9283160217909255925116600090815260086020908152604080832094835293905291909120429055506001016108af565b507f3a3950e13dd607cc37980db0ef14266c40d2bba9c01b2e44bfe549808883095d81604051610ad59190615419565b60405180910390a1610b5160008a8a8a8a8a8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808e0282810182019093528d82529093508d92508c9182918501908490808284376000920191909152508b9250611a8a915050565b505050505050505050565b610b9c610b6b828401846154b6565b6040805160008082526020820190925290610b96565b6060815260200190600190039081610b815790505b50611871565b604080516000808252602082019092529050610bbf600185858585866000611a8a565b50505050565b6000610bd3600160046154eb565b6002610be0608085615514565b67ffffffffffffffff16610bf4919061553b565b610bfe8585611e01565b901c166003811115610c1257610c12614ac4565b90505b92915050565b6001546001600160a01b03163314610c755760405162461bcd60e51b815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610754565b600080543373ffffffffffffffffffffffffffffffffffffffff19808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610ce1611496565b6105dd81611e48565b333014610d23576040517f371a732800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160008082526020820190925281610d60565b6040805180820190915260008082526020820152815260200190600190039081610d395790505b5060a08501515190915015610d9457610d918460a00151856020015186606001518760000151602001518787611fae565b90505b6040805160a0810182528551518152855160209081015167ffffffffffffffff1681830152808701518351600094840192610dd09291016148df565b60408051601f19818403018152918152908252878101516020830152018390526005549091506001600160a01b03168015610edd576040517f08d450a10000000000000000000000000000000000000000000000000000000081526001600160a01b038216906308d450a190610e4a9085906004016155f4565b600060405180830381600087803b158015610e6457600080fd5b505af1925050508015610e75575060015b610edd573d808015610ea3576040519150601f19603f3d011682016040523d82523d6000602084013e610ea8565b606091505b50806040517f09c2532500000000000000000000000000000000000000000000000000000000815260040161075491906148df565b604086015151158015610ef257506080860151155b80610f09575060608601516001600160a01b03163b155b80610f4957506060860151610f47906001600160a01b03167f85572ffb000000000000000000000000000000000000000000000000000000006120cd565b155b15610f5657505050505050565b855160209081015167ffffffffffffffff1660009081526006909152604080822054608089015160608a015192517f3cf9798300000000000000000000000000000000000000000000000000000000815284936001600160a01b0390931692633cf9798392610fce9289926113889291600401615607565b6000604051808303816000875af1158015610fed573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526110159190810190615643565b50915091508161105357806040517f0a8d6e8c00000000000000000000000000000000000000000000000000000000815260040161075491906148df565b5050505050505050565b6110a06040805160e081019091526000606082018181526080830182905260a0830182905260c08301919091528190815260200160608152602001606081525090565b60ff808316600090815260026020818152604092839020835160e081018552815460608201908152600183015480881660808401526101008104881660a0840152620100009004909616151560c08201529485529182018054845181840281018401909552808552929385830193909283018282801561114957602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161112b575b50505050508152602001600382018054806020026020016040519081016040528092919081815260200182805480156111ab57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161118d575b5050505050815250509050919050565b6111c3611496565b60005b818110156107805760008383838181106111e2576111e2614fe5565b9050604002018036038101906111f891906156d9565b905061120781602001516113d5565b61126c57805167ffffffffffffffff1660009081526008602090815260408083208285018051855290835281842093909355915191519182527f202f1139a3e334b6056064c0e9b19fd07e44a88d8f6e5ded571b24cf8c371f12910160405180910390a15b506001016111c6565b604080516080808201835260008083526020808401829052838501829052606080850181905267ffffffffffffffff878116845260068352928690208651948501875280546001600160a01b0381168652600160a01b810460ff16151593860193909352600160a81b90920490921694830194909452600184018054939492939184019161130290615712565b80601f016020809104026020016040519081016040528092919081815260200182805461132e90615712565b80156111ab5780601f10611350576101008083540402835291602001916111ab565b820191906000526020600020905b81548152906001019060200180831161135e57505050919092525091949350505050565b61138a611496565b6105dd816120e9565b61139b611496565b60005b81518110156113d1576113c98282815181106113bc576113bc614fe5565b602002602001015161219f565b60010161139e565b5050565b6040805180820182523081526020810183815291517f4d61677100000000000000000000000000000000000000000000000000000000815290516001600160a01b039081166004830152915160248201526000917f00000000000000000000000000000000000000000000000000000000000000001690634d61677190604401602060405180830381865afa158015611472573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c15919061574c565b6000546001600160a01b031633146114f05760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610754565b565b60005b81518110156113d157600082828151811061151257611512614fe5565b602002602001015190506000816020015190508067ffffffffffffffff16600003611569576040517fc656089500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81516001600160a01b0316611591576040516342bcdf7f60e11b815260040160405180910390fd5b67ffffffffffffffff811660009081526006602052604081206001810180549192916115bc90615712565b80601f01602080910402602001604051908101604052809291908181526020018280546115e890615712565b80156116355780601f1061160a57610100808354040283529160200191611635565b820191906000526020600020905b81548152906001019060200180831161161857829003601f168201915b5050505050905060008460600151905081516000036116ed578051600003611670576040516342bcdf7f60e11b815260040160405180910390fd5b6001830161167e82826157b1565b5082547fffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffff16600160a81b17835560405167ffffffffffffffff851681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1611740565b8080519060200120828051906020012014611740576040517fc39a620500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff85166004820152602401610754565b604080860151845487516001600160a01b031673ffffffffffffffffffffffffffffffffffffffff19921515600160a01b02929092167fffffffffffffffffffffff000000000000000000000000000000000000000000909116171784555167ffffffffffffffff8516907f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b906117d8908690615871565b60405180910390a250505050508060010190506114f5565b467f0000000000000000000000000000000000000000000000000000000000000000146114f0576040517f0f01ce850000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000006004820152466024820152604401610754565b81516000036118ab576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160408051600080825260208201909252911591905b845181101561191a576119128582815181106118e0576118e0614fe5565b60200260200101518461190c578583815181106118ff576118ff614fe5565b60200260200101516124e3565b836124e3565b6001016118c2565b5050505050565b6040517f2cbc26bb000000000000000000000000000000000000000000000000000000008152608082901b77ffffffffffffffff000000000000000000000000000000001660048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632cbc26bb90602401602060405180830381865afa1580156119bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119e0919061574c565b156105dd576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610754565b67ffffffffffffffff811660009081526006602052604081208054600160a01b900460ff16610c15576040517fed053c5900000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610754565b60ff87811660009081526002602090815260408083208151608081018352815481526001909101548086169382019390935261010083048516918101919091526201000090910490921615156060830152873590611ae98760a461593f565b9050826060015115611b31578451611b0290602061553b565b8651611b0f90602061553b565b611b1a9060a061593f565b611b24919061593f565b611b2e908261593f565b90505b368114611b73576040517f8e1192e100000000000000000000000000000000000000000000000000000000815260048101829052366024820152604401610754565b5081518114611bbb5781516040517f93df584c000000000000000000000000000000000000000000000000000000008152600481019190915260248101829052604401610754565b611bc36117f0565b60ff808a1660009081526003602090815260408083203384528252808320815180830190925280548086168352939491939092840191610100909104166002811115611c1157611c11614ac4565b6002811115611c2257611c22614ac4565b9052509050600281602001516002811115611c3f57611c3f614ac4565b148015611c935750600260008b60ff1660ff168152602001908152602001600020600301816000015160ff1681548110611c7b57611c7b614fe5565b6000918252602090912001546001600160a01b031633145b611cc9576040517fda0f08e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50816060015115611dab576020820151611ce4906001615952565b60ff16855114611d20576040517f71253a2500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8351855114611d5b576040517fa75d88af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008787604051611d6d92919061596b565b604051908190038120611d84918b9060200161597b565b604051602081830303815290604052805190602001209050611da98a82888888612caf565b505b6040805182815260208a81013567ffffffffffffffff169082015260ff8b16917f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef0910160405180910390a2505050505050505050565b67ffffffffffffffff8216600090815260076020526040812081611e2660808561598f565b67ffffffffffffffff1681526020810191909152604001600020549392505050565b80516001600160a01b0316611e70576040516342bcdf7f60e11b815260040160405180910390fd5b80516004805460208085018051604080880180516060808b0180516001600160a01b039b8c167fffffffffffffffff000000000000000000000000000000000000000000000000909a168a17600160a01b63ffffffff988916021777ffffffffffffffffffffffffffffffffffffffffffffffff167801000000000000000000000000000000000000000000000000948816949094026001600160e01b031693909317600160e01b93871693909302929092179098556080808b0180516005805473ffffffffffffffffffffffffffffffffffffffff1916918d169190911790558451988952955185169688019690965290518316918601919091525116938301939093529151909216908201527fa55bd56595c45f517e5967a3067f3dca684445a3080e7c04a4e0d5a40cda627d9060a00160405180910390a150565b6060865167ffffffffffffffff811115611fca57611fca613eef565b60405190808252806020026020018201604052801561200f57816020015b6040805180820190915260008082526020820152815260200190600190039081611fe85790505b50905060005b87518110156120c15761209c88828151811061203357612033614fe5565b602002602001015188888888888781811061205057612050614fe5565b905060200281019061206291906159b6565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612ebc92505050565b8282815181106120ae576120ae614fe5565b6020908102919091010152600101612015565b505b9695505050505050565b60006120d883613261565b8015610c125750610c1283836132c5565b336001600160a01b038216036121415760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610754565b6001805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b806040015160ff166000036121ca576000604051631b3fab5160e11b81526004016107549190615a1b565b60208082015160ff8082166000908152600290935260408320600181015492939092839216900361223757606084015160018201805491151562010000027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff90921691909117905561228c565b6060840151600182015460ff620100009091041615159015151461228c576040517f87f6037c00000000000000000000000000000000000000000000000000000000815260ff84166004820152602401610754565b60a08401518051601f60ff821611156122bb576001604051631b3fab5160e11b81526004016107549190615a1b565b612321858560030180548060200260200160405190810160405280929190818152602001828054801561231757602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116122f9575b5050505050613380565b8560600151156124505761238f8585600201805480602002602001604051908101604052809291908181526020018280548015612317576020028201919060005260206000209081546001600160a01b031681526001909101906020018083116122f9575050505050613380565b608086015180516123a99060028701906020840190613e49565b5080516001850180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1661010060ff841690810291909117909155601f1015612409576002604051631b3fab5160e11b81526004016107549190615a1b565b6040880151612419906003615a35565b60ff168160ff1611612441576003604051631b3fab5160e11b81526004016107549190615a1b565b61244d878360016133e9565b50505b61245c858360026133e9565b81516124719060038601906020850190613e49565b5060408681015160018501805460ff191660ff8316179055875180865560a089015192517fab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f547936124ca938a939260028b01929190615a51565b60405180910390a16124db85613569565b505050505050565b81516124ee81611921565b60006124f982611a23565b602085015151909150600081900361253c576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b846040015151811461257a576040517f57e0e08300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008167ffffffffffffffff81111561259557612595613eef565b6040519080825280602002602001820160405280156125be578160200160208202803683370190505b50905060005b82811015612733576000876020015182815181106125e4576125e4614fe5565b602002602001015190507f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681600001516040015167ffffffffffffffff161461267757805160409081015190517f38432a2200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610754565b61270d8186600101805461268a90615712565b80601f01602080910402602001604051908101604052809291908181526020018280546126b690615712565b80156127035780601f106126d857610100808354040283529160200191612703565b820191906000526020600020905b8154815290600101906020018083116126e657829003601f168201915b5050505050613585565b83838151811061271f5761271f614fe5565b6020908102919091010152506001016125c4565b50600061274a858389606001518a608001516136a7565b905080600003612792576040517f7dd17a7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff86166004820152602401610754565b8551151560005b84811015610b515760005a905060008a6020015183815181106127be576127be614fe5565b6020026020010151905060006127dc8a836000015160600151610bc5565b905060008160038111156127f2576127f2614ac4565b148061280f5750600381600381111561280d5761280d614ac4565b145b612867578151606001516040805167ffffffffffffffff808e16825290921660208301527f3b575419319662b2a6f5e2467d84521517a3382b908eb3d557bb3fdb0c50e23c91015b60405180910390a1505050612ca7565b841561293757600454600090600160a01b900463ffffffff1661288a88426154eb565b11905080806128aa575060038260038111156128a8576128a8614ac4565b145b6128ec576040517fa9cfc86200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8c166004820152602401610754565b8b85815181106128fe576128fe614fe5565b6020026020010151600014612931578b858151811061291f5761291f614fe5565b60200260200101518360800181815250505b50612998565b600081600381111561294b5761294b614ac4565b14612998578151606001516040805167ffffffffffffffff808e16825290921660208301527f3ef2a99c550a751d4b0b261268f05a803dfb049ab43616a1ffb388f61fe651209101612857565b81516080015167ffffffffffffffff1615612a875760008160038111156129c1576129c1614ac4565b03612a875781516080015160208301516040517fe0e03cae0000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169263e0e03cae92612a38928f929190600401615afd565b6020604051808303816000875af1158015612a57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a7b919061574c565b612a8757505050612ca7565b60008c604001518581518110612a9f57612a9f614fe5565b6020026020010151905080518360a001515114612b03578251606001516040517f1cfe6d8b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808e1660048301529091166024820152604401610754565b612b178b84600001516060015160016136fd565b600080612b2485846137a5565b91509150612b3b8d866000015160600151846136fd565b8715612bab576003826003811115612b5557612b55614ac4565b03612bab576000846003811115612b6e57612b6e614ac4565b14612bab578451516040517f2b11b8d900000000000000000000000000000000000000000000000000000000815261075491908390600401615b2a565b6002826003811115612bbf57612bbf614ac4565b14612c19576003826003811115612bd857612bd8614ac4565b14612c19578451606001516040517f926c5a3e000000000000000000000000000000000000000000000000000000008152610754918f918590600401615b43565b84600001516000015185600001516060015167ffffffffffffffff168e67ffffffffffffffff167f05665fe9ad095383d018353f4cbcba77e84db27dd215081bbf7cdf9ae6fbe48b8d8b81518110612c7357612c73614fe5565b602002602001015186865a612c88908e6154eb565b604051612c989493929190615b69565b60405180910390a45050505050505b600101612799565b612cb7613ebb565b835160005b81811015611053576000600188868460208110612cdb57612cdb614fe5565b612ce891901a601b615952565b898581518110612cfa57612cfa614fe5565b6020026020010151898681518110612d1457612d14614fe5565b602002602001015160405160008152602001604052604051612d52949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015612d74573d6000803e3d6000fd5b505060408051601f1981015160ff808e166000908152600360209081528582206001600160a01b03851683528152858220858701909652855480841686529397509095509293928401916101009004166002811115612dd557612dd5614ac4565b6002811115612de657612de6614ac4565b9052509050600181602001516002811115612e0357612e03614ac4565b14612e3a576040517fca31867a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051859060ff16601f8110612e5157612e51614fe5565b602002015115612e8d576040517ff67bc7c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600185826000015160ff16601f8110612ea857612ea8614fe5565b911515602090920201525050600101612cbc565b60408051808201909152600080825260208201526000612edf876020015161386f565b6040517fbbe4f6db0000000000000000000000000000000000000000000000000000000081526001600160a01b0380831660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063bbe4f6db90602401602060405180830381865afa158015612f64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f889190615ba0565b90506001600160a01b0381161580612fd05750612fce6001600160a01b0382167faff2afbf000000000000000000000000000000000000000000000000000000006120cd565b155b15613012576040517fae9b4ce90000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152602401610754565b60045460009081906130349089908690600160e01b900463ffffffff16613915565b9150915060008060006131016040518061010001604052808e81526020018c67ffffffffffffffff1681526020018d6001600160a01b031681526020018f606001518152602001896001600160a01b031681526020018f6000015181526020018f6040015181526020018b8152506040516024016130b29190615bbd565b60408051601f198184030181529190526020810180516001600160e01b03167f390775370000000000000000000000000000000000000000000000000000000017905287866113886084613a43565b9250925092508261314057816040517fe1cd550900000000000000000000000000000000000000000000000000000000815260040161075491906148df565b81516020146131885781516040517f78ef8024000000000000000000000000000000000000000000000000000000008152602060048201526024810191909152604401610754565b60008280602001905181019061319e9190615c8a565b9050866001600160a01b03168c6001600160a01b0316146132335760006131cf8d8a6131ca868a6154eb565b613915565b509050868110806131e95750816131e688836154eb565b14155b15613231576040517fa966e21f000000000000000000000000000000000000000000000000000000008152600481018390526024810188905260448101829052606401610754565b505b604080518082019091526001600160a01b039098168852602088015250949550505050505095945050505050565b600061328d827f01ffc9a7000000000000000000000000000000000000000000000000000000006132c5565b8015610c1557506132be827fffffffff000000000000000000000000000000000000000000000000000000006132c5565b1592915050565b6040517fffffffff0000000000000000000000000000000000000000000000000000000082166024820152600090819060440160408051601f19818403018152919052602080820180516001600160e01b03167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825192935060009283928392909183918a617530fa92503d91506000519050828015613369575060208210155b80156133755750600081115b979650505050505050565b60005b81518110156107805760ff8316600090815260036020526040812083519091908490849081106133b5576133b5614fe5565b6020908102919091018101516001600160a01b03168252810191909152604001600020805461ffff19169055600101613383565b60005b82518160ff161015610bbf576000838260ff168151811061340f5761340f614fe5565b602002602001015190506000600281111561342c5761342c614ac4565b60ff80871660009081526003602090815260408083206001600160a01b0387168452909152902054610100900416600281111561346b5761346b614ac4565b1461348c576004604051631b3fab5160e11b81526004016107549190615a1b565b6001600160a01b0381166134cc576040517fd6c62c9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052808360ff1681526020018460028111156134f2576134f2614ac4565b905260ff80871660009081526003602090815260408083206001600160a01b0387168452825290912083518154931660ff198416811782559184015190929091839161ffff19161761010083600281111561354f5761354f614ac4565b0217905550905050508061356290615ca3565b90506133ec565b60ff81166105dd576009805467ffffffffffffffff1916905550565b8151602080820151604092830151925160009384936135cb937f2425b0b9f9054c76ff151b0a175b18f37a4a4e82013a72e9f15c9caa095ed21f93909291889101615cc2565b60408051601f1981840301815290829052805160209182012086518051888401516060808b0151908401516080808d015195015195976136149794969395929491939101615cf5565b604051602081830303815290604052805190602001208560400151805190602001208660a0015160405160200161364b9190615e07565b60408051601f198184030181528282528051602091820120908301969096528101939093526060830191909152608082015260a081019190915260c0015b60405160208183030381529060405280519060200120905092915050565b6000806136b5858585613b69565b90506136c0816113d5565b6136ce5760009150506136f5565b67ffffffffffffffff86166000908152600860209081526040808320938352929052205490505b949350505050565b6000600261370c608085615514565b67ffffffffffffffff16613720919061553b565b9050600061372e8585611e01565b90508161373d600160046154eb565b901b19168183600381111561375457613754614ac4565b67ffffffffffffffff871660009081526007602052604081209190921b9290921791829161378360808861598f565b67ffffffffffffffff1681526020810191909152604001600020555050505050565b6040517fa80036b4000000000000000000000000000000000000000000000000000000008152600090606090309063a80036b4906137e99087908790600401615e67565b600060405180830381600087803b15801561380357600080fd5b505af1925050508015613814575060015b613853573d808015613842576040519150601f19603f3d011682016040523d82523d6000602084013e613847565b606091505b50600392509050613868565b50506040805160208101909152600081526002905b9250929050565b600081516020146138ae57816040517f8d666f6000000000000000000000000000000000000000000000000000000000815260040161075491906148df565b6000828060200190518101906138c49190615c8a565b90506001600160a01b038111806138dc575061040081105b15610c1557826040517f8d666f6000000000000000000000000000000000000000000000000000000000815260040161075491906148df565b600080600080600061398f8860405160240161394091906001600160a01b0391909116815260200190565b60408051601f198184030181529190526020810180516001600160e01b03167f70a082310000000000000000000000000000000000000000000000000000000017905288886113886084613a43565b925092509250826139ce57816040517fe1cd550900000000000000000000000000000000000000000000000000000000815260040161075491906148df565b6020825114613a165781516040517f78ef8024000000000000000000000000000000000000000000000000000000008152602060048201526024810191909152604401610754565b81806020019051810190613a2a9190615c8a565b613a3482886154eb565b94509450505050935093915050565b6000606060008361ffff1667ffffffffffffffff811115613a6657613a66613eef565b6040519080825280601f01601f191660200182016040528015613a90576020820181803683370190505b509150863b613ac3577f0c3b563c0000000000000000000000000000000000000000000000000000000060005260046000fd5b5a85811015613af6577fafa32a2c0000000000000000000000000000000000000000000000000000000060005260046000fd5b8590036040810481038710613b2f577f37c3be290000000000000000000000000000000000000000000000000000000060005260046000fd5b505a6000808a5160208c0160008c8cf193505a900390503d84811115613b525750835b808352806000602085013e50955095509592505050565b8251825160009190818303613baa576040517f11a6b26400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6101018211801590613bbe57506101018111155b613bdb576040516309bde33960e01b815260040160405180910390fd5b60001982820101610100811115613c05576040516309bde33960e01b815260040160405180910390fd5b80600003613c325786600081518110613c2057613c20614fe5565b60200260200101519350505050613e01565b60008167ffffffffffffffff811115613c4d57613c4d613eef565b604051908082528060200260200182016040528015613c76578160200160208202803683370190505b50905060008080805b85811015613da05760006001821b8b811603613cda5788851015613cc3578c5160018601958e918110613cb457613cb4614fe5565b60200260200101519050613cfc565b8551600185019487918110613cb457613cb4614fe5565b8b5160018401938d918110613cf157613cf1614fe5565b602002602001015190505b600089861015613d2c578d5160018701968f918110613d1d57613d1d614fe5565b60200260200101519050613d4e565b8651600186019588918110613d4357613d43614fe5565b602002602001015190505b82851115613d6f576040516309bde33960e01b815260040160405180910390fd5b613d798282613e08565b878481518110613d8b57613d8b614fe5565b60209081029190910101525050600101613c7f565b506001850382148015613db257508683145b8015613dbd57508581145b613dda576040516309bde33960e01b815260040160405180910390fd5b836001860381518110613def57613def614fe5565b60200260200101519750505050505050505b9392505050565b6000818310613e2057613e1b8284613e26565b610c12565b610c1283835b604080516001602082015290810183905260608101829052600090608001613689565b828054828255906000526020600020908101928215613eab579160200282015b82811115613eab578251825473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03909116178255602090920191600190910190613e69565b50613eb7929150613eda565b5090565b604051806103e00160405280601f906020820280368337509192915050565b5b80821115613eb75760008155600101613edb565b634e487b7160e01b600052604160045260246000fd5b6040516080810167ffffffffffffffff81118282101715613f2857613f28613eef565b60405290565b60405160a0810167ffffffffffffffff81118282101715613f2857613f28613eef565b60405160c0810167ffffffffffffffff81118282101715613f2857613f28613eef565b6040805190810167ffffffffffffffff81118282101715613f2857613f28613eef565b6040516060810167ffffffffffffffff81118282101715613f2857613f28613eef565b604051601f8201601f1916810167ffffffffffffffff81118282101715613fe357613fe3613eef565b604052919050565b600067ffffffffffffffff82111561400557614005613eef565b5060051b60200190565b6001600160a01b03811681146105dd57600080fd5b803567ffffffffffffffff8116811461403c57600080fd5b919050565b80151581146105dd57600080fd5b803561403c81614041565b600067ffffffffffffffff82111561407457614074613eef565b50601f01601f191660200190565b600082601f83011261409357600080fd5b81356140a66140a18261405a565b613fba565b8181528460208386010111156140bb57600080fd5b816020850160208301376000918101602001919091529392505050565b600060208083850312156140eb57600080fd5b823567ffffffffffffffff8082111561410357600080fd5b818501915085601f83011261411757600080fd5b81356141256140a182613feb565b81815260059190911b8301840190848101908883111561414457600080fd5b8585015b838110156141ea578035858111156141605760008081fd5b86016080818c03601f19018113156141785760008081fd5b614180613f05565b8983013561418d8161400f565b8152604061419c848201614024565b8b8301526060808501356141af81614041565b838301529284013592898411156141c857600091508182fd5b6141d68f8d86880101614082565b908301525085525050918601918601614148565b5098975050505050505050565b600060a0828403121561420957600080fd5b614211613f2e565b90508135815261422360208301614024565b602082015261423460408301614024565b604082015261424560608301614024565b606082015261425660808301614024565b608082015292915050565b803561403c8161400f565b600082601f83011261427d57600080fd5b8135602061428d6140a183613feb565b82815260059290921b840181019181810190868411156142ac57600080fd5b8286015b848110156120c157803567ffffffffffffffff808211156142d15760008081fd5b818901915060a080601f19848d030112156142ec5760008081fd5b6142f4613f2e565b87840135838111156143065760008081fd5b6143148d8a83880101614082565b8252506040808501358481111561432b5760008081fd5b6143398e8b83890101614082565b8a84015250606080860135858111156143525760008081fd5b6143608f8c838a0101614082565b838501525060809150818601358184015250828501359250838311156143865760008081fd5b6143948d8a85880101614082565b9082015286525050509183019183016142b0565b600061014082840312156143bb57600080fd5b6143c3613f51565b90506143cf83836141f7565b815260a082013567ffffffffffffffff808211156143ec57600080fd5b6143f885838601614082565b602084015260c084013591508082111561441157600080fd5b61441d85838601614082565b604084015261442e60e08501614261565b6060840152610100840135608084015261012084013591508082111561445357600080fd5b506144608482850161426c565b60a08301525092915050565b600082601f83011261447d57600080fd5b8135602061448d6140a183613feb565b82815260059290921b840181019181810190868411156144ac57600080fd5b8286015b848110156120c157803567ffffffffffffffff8111156144d05760008081fd5b6144de8986838b01016143a8565b8452509183019183016144b0565b600082601f8301126144fd57600080fd5b8135602061450d6140a183613feb565b82815260059290921b8401810191818101908684111561452c57600080fd5b8286015b848110156120c157803567ffffffffffffffff8082111561455057600080fd5b818901915089603f83011261456457600080fd5b858201356145746140a182613feb565b81815260059190911b830160400190878101908c83111561459457600080fd5b604085015b838110156145cd578035858111156145b057600080fd5b6145bf8f6040838a0101614082565b845250918901918901614599565b50875250505092840192508301614530565b600082601f8301126145f057600080fd5b813560206146006140a183613feb565b8083825260208201915060208460051b87010193508684111561462257600080fd5b602086015b848110156120c15780358352918301918301614627565b600082601f83011261464f57600080fd5b8135602061465f6140a183613feb565b82815260059290921b8401810191818101908684111561467e57600080fd5b8286015b848110156120c157803567ffffffffffffffff808211156146a35760008081fd5b818901915060a080601f19848d030112156146be5760008081fd5b6146c6613f2e565b6146d1888501614024565b8152604080850135848111156146e75760008081fd5b6146f58e8b8389010161446c565b8a840152506060808601358581111561470e5760008081fd5b61471c8f8c838a01016144ec565b83850152506080915081860135858111156147375760008081fd5b6147458f8c838a01016145df565b9184019190915250919093013590830152508352918301918301614682565b600080604080848603121561477857600080fd5b833567ffffffffffffffff8082111561479057600080fd5b61479c8783880161463e565b94506020915081860135818111156147b357600080fd5b8601601f810188136147c457600080fd5b80356147d26140a182613feb565b81815260059190911b8201840190848101908a8311156147f157600080fd5b8584015b8381101561487d5780358681111561480d5760008081fd5b8501603f81018d1361481f5760008081fd5b8781013561482f6140a182613feb565b81815260059190911b82018a0190898101908f83111561484f5760008081fd5b928b01925b8284101561486d5783358252928a0192908a0190614854565b86525050509186019186016147f5565b50809750505050505050509250929050565b60005b838110156148aa578181015183820152602001614892565b50506000910152565b600081518084526148cb81602086016020860161488f565b601f01601f19169290920160200192915050565b602081526000610c1260208301846148b3565b8060608101831015610c1557600080fd5b60008083601f84011261491557600080fd5b50813567ffffffffffffffff81111561492d57600080fd5b60208301915083602082850101111561386857600080fd5b60008083601f84011261495757600080fd5b50813567ffffffffffffffff81111561496f57600080fd5b6020830191508360208260051b850101111561386857600080fd5b60008060008060008060008060e0898b0312156149a657600080fd5b6149b08a8a6148f2565b9750606089013567ffffffffffffffff808211156149cd57600080fd5b6149d98c838d01614903565b909950975060808b01359150808211156149f257600080fd5b6149fe8c838d01614945565b909750955060a08b0135915080821115614a1757600080fd5b50614a248b828c01614945565b999c989b50969995989497949560c00135949350505050565b600080600060808486031215614a5257600080fd5b614a5c85856148f2565b9250606084013567ffffffffffffffff811115614a7857600080fd5b614a8486828701614903565b9497909650939450505050565b60008060408385031215614aa457600080fd5b614aad83614024565b9150614abb60208401614024565b90509250929050565b634e487b7160e01b600052602160045260246000fd5b60048110614aea57614aea614ac4565b9052565b60208101610c158284614ada565b600060208284031215614b0e57600080fd5b813567ffffffffffffffff811115614b2557600080fd5b820160a08185031215613e0157600080fd5b803563ffffffff8116811461403c57600080fd5b600060a08284031215614b5d57600080fd5b614b65613f2e565b8235614b708161400f565b8152614b7e60208401614b37565b6020820152614b8f60408401614b37565b6040820152614ba060608401614b37565b60608201526080830135614bb38161400f565b60808201529392505050565b600080600060408486031215614bd457600080fd5b833567ffffffffffffffff80821115614bec57600080fd5b614bf8878388016143a8565b94506020860135915080821115614c0e57600080fd5b50614a8486828701614945565b803560ff8116811461403c57600080fd5b600060208284031215614c3e57600080fd5b610c1282614c1b565b60008151808452602080850194506020840160005b83811015614c815781516001600160a01b031687529582019590820190600101614c5c565b509495945050505050565b60208152600082518051602084015260ff602082015116604084015260ff604082015116606084015260608101511515608084015250602083015160c060a0840152614cdb60e0840182614c47565b90506040840151601f198483030160c0850152614cf88282614c47565b95945050505050565b60008060408385031215614d1457600080fd5b614d1d83614024565b946020939093013593505050565b60008060208385031215614d3e57600080fd5b823567ffffffffffffffff80821115614d5657600080fd5b818501915085601f830112614d6a57600080fd5b813581811115614d7957600080fd5b8660208260061b8501011115614d8e57600080fd5b60209290920196919550909350505050565b600060208284031215614db257600080fd5b610c1282614024565b602081526001600160a01b03825116602082015260208201511515604082015267ffffffffffffffff6040830151166060820152600060608301516080808401526136f560a08401826148b3565b600060208284031215614e1b57600080fd5b8135613e018161400f565b600082601f830112614e3757600080fd5b81356020614e476140a183613feb565b8083825260208201915060208460051b870101935086841115614e6957600080fd5b602086015b848110156120c1578035614e818161400f565b8352918301918301614e6e565b60006020808385031215614ea157600080fd5b823567ffffffffffffffff80821115614eb957600080fd5b818501915085601f830112614ecd57600080fd5b8135614edb6140a182613feb565b81815260059190911b83018401908481019088831115614efa57600080fd5b8585015b838110156141ea57803585811115614f1557600080fd5b860160c0818c03601f19011215614f2c5760008081fd5b614f34613f51565b8882013581526040614f47818401614c1b565b8a8301526060614f58818501614c1b565b8284015260809150614f6b82850161404f565b9083015260a08381013589811115614f835760008081fd5b614f918f8d83880101614e26565b838501525060c0840135915088821115614fab5760008081fd5b614fb98e8c84870101614e26565b9083015250845250918601918601614efe565b600060208284031215614fde57600080fd5b5035919050565b634e487b7160e01b600052603260045260246000fd5b80356001600160e01b038116811461403c57600080fd5b600082601f83011261502357600080fd5b813560206150336140a183613feb565b82815260069290921b8401810191818101908684111561505257600080fd5b8286015b848110156120c1576040818903121561506f5760008081fd5b615077613f74565b61508082614024565b815261508d858301614ffb565b81860152835291830191604001615056565b600082601f8301126150b057600080fd5b813560206150c06140a183613feb565b82815260079290921b840181019181810190868411156150df57600080fd5b8286015b848110156120c15780880360808112156150fd5760008081fd5b615105613f97565b61510e83614024565b8152604080601f19840112156151245760008081fd5b61512c613f74565b9250615139878501614024565b8352615146818501614024565b83880152818701929092526060830135918101919091528352918301916080016150e3565b6000602080838503121561517e57600080fd5b823567ffffffffffffffff8082111561519657600080fd5b818501915060408083880312156151ac57600080fd5b6151b4613f74565b8335838111156151c357600080fd5b84016040818a0312156151d557600080fd5b6151dd613f74565b8135858111156151ec57600080fd5b8201601f81018b136151fd57600080fd5b803561520b6140a182613feb565b81815260069190911b8201890190898101908d83111561522a57600080fd5b928a01925b8284101561527a5787848f0312156152475760008081fd5b61524f613f74565b843561525a8161400f565b8152615267858d01614ffb565b818d0152825292870192908a019061522f565b84525050508187013593508484111561529257600080fd5b61529e8a858401615012565b81880152825250838501359150828211156152b857600080fd5b6152c48883860161509f565b85820152809550505050505092915050565b805160408084528151848201819052600092602091908201906060870190855b8181101561532d57835180516001600160a01b031684528501516001600160e01b03168584015292840192918501916001016152f6565b50508583015187820388850152805180835290840192506000918401905b80831015615387578351805167ffffffffffffffff1683528501516001600160e01b03168583015292840192600192909201919085019061534b565b50979650505050505050565b602081526000610c1260208301846152d6565b67ffffffffffffffff8316815260608101613e016020830184805167ffffffffffffffff908116835260209182015116910152565b634e487b7160e01b600052601160045260246000fd5b67ffffffffffffffff818116838216019080821115615412576154126153db565b5092915050565b60006020808352606084516040808487015261543860608701836152d6565b87850151878203601f19016040890152805180835290860193506000918601905b808310156141ea57845167ffffffffffffffff81511683528781015161549889850182805167ffffffffffffffff908116835260209182015116910152565b50840151828701529386019360019290920191608090910190615459565b6000602082840312156154c857600080fd5b813567ffffffffffffffff8111156154df57600080fd5b6136f58482850161463e565b81810381811115610c1557610c156153db565b634e487b7160e01b600052601260045260246000fd5b600067ffffffffffffffff8084168061552f5761552f6154fe565b92169190910692915050565b8082028115828204841417610c1557610c156153db565b805182526000602067ffffffffffffffff81840151168185015260408084015160a0604087015261558660a08701826148b3565b90506060850151868203606088015261559f82826148b3565b608087810151898303918a01919091528051808352908601935060009250908501905b8083101561538757835180516001600160a01b03168352860151868301529285019260019290920191908401906155c2565b602081526000610c126020830184615552565b60808152600061561a6080830187615552565b61ffff9590951660208301525060408101929092526001600160a01b0316606090910152919050565b60008060006060848603121561565857600080fd5b835161566381614041565b602085015190935067ffffffffffffffff81111561568057600080fd5b8401601f8101861361569157600080fd5b805161569f6140a18261405a565b8181528760208385010111156156b457600080fd5b6156c582602083016020860161488f565b809450505050604084015190509250925092565b6000604082840312156156eb57600080fd5b6156f3613f74565b6156fc83614024565b8152602083013560208201528091505092915050565b600181811c9082168061572657607f821691505b60208210810361574657634e487b7160e01b600052602260045260246000fd5b50919050565b60006020828403121561575e57600080fd5b8151613e0181614041565b601f821115610780576000816000526020600020601f850160051c810160208610156157925750805b601f850160051c820191505b818110156124db5782815560010161579e565b815167ffffffffffffffff8111156157cb576157cb613eef565b6157df816157d98454615712565b84615769565b602080601f83116001811461581457600084156157fc5750858301515b600019600386901b1c1916600185901b1785556124db565b600085815260208120601f198616915b8281101561584357888601518255948401946001909101908401615824565b50858210156158615787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6000602080835283546001600160a01b038116602085015260ff8160a01c161515604085015267ffffffffffffffff8160a81c166060850152506001808501608080860152600081546158c381615712565b8060a089015260c060018316600081146158e4576001811461590057615930565b60ff19841660c08b015260c083151560051b8b01019450615930565b85600052602060002060005b848110156159275781548c820185015290880190890161590c565b8b0160c0019550505b50929998505050505050505050565b80820180821115610c1557610c156153db565b60ff8181168382160190811115610c1557610c156153db565b8183823760009101908152919050565b828152606082602083013760800192915050565b600067ffffffffffffffff808416806159aa576159aa6154fe565b92169190910492915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126159eb57600080fd5b83018035915067ffffffffffffffff821115615a0657600080fd5b60200191503681900382131561386857600080fd5b6020810160058310615a2f57615a2f614ac4565b91905290565b60ff8181168382160290811690818114615412576154126153db565b600060a0820160ff881683526020878185015260a0604085015281875480845260c0860191508860005282600020935060005b81811015615aa95784546001600160a01b031683526001948501949284019201615a84565b50508481036060860152865180825290820192508187019060005b81811015615ae95782516001600160a01b031685529383019391830191600101615ac4565b50505060ff851660808501525090506120c3565b600067ffffffffffffffff808616835280851660208401525060606040830152614cf860608301846148b3565b8281526040602082015260006136f560408301846148b3565b67ffffffffffffffff848116825283166020820152606081016136f56040830184614ada565b848152615b796020820185614ada565b608060408201526000615b8f60808301856148b3565b905082606083015295945050505050565b600060208284031215615bb257600080fd5b8151613e018161400f565b6020815260008251610100806020850152615bdc6101208501836148b3565b91506020850151615bf9604086018267ffffffffffffffff169052565b5060408501516001600160a01b038116606086015250606085015160808501526080850151615c3360a08601826001600160a01b03169052565b5060a0850151601f19808685030160c0870152615c5084836148b3565b935060c08701519150808685030160e0870152615c6d84836148b3565b935060e08701519150808685030183870152506120c383826148b3565b600060208284031215615c9c57600080fd5b5051919050565b600060ff821660ff8103615cb957615cb96153db565b60010192915050565b848152600067ffffffffffffffff8086166020840152808516604084015250608060608301526120c360808301846148b3565b86815260c060208201526000615d0e60c08301886148b3565b6001600160a01b039690961660408301525067ffffffffffffffff9384166060820152608081019290925290911660a09091015292915050565b600082825180855260208086019550808260051b84010181860160005b84811015615dfa57601f19868403018952815160a08151818652615d8b828701826148b3565b9150508582015185820387870152615da382826148b3565b91505060408083015186830382880152615dbd83826148b3565b92505050606080830151818701525060808083015192508582038187015250615de681836148b3565b9a86019a9450505090830190600101615d65565b5090979650505050505050565b602081526000610c126020830184615d48565b60008282518085526020808601955060208260051b8401016020860160005b84811015615dfa57601f19868403018952615e558383516148b3565b98840198925090830190600101615e39565b604081526000835180516040840152602081015167ffffffffffffffff80821660608601528060408401511660808601528060608401511660a08601528060808401511660c086015250505060208401516101408060e0850152615ecf6101808501836148b3565b915060408601517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08086850301610100870152615f0c84836148b3565b935060608801519150615f2b6101208701836001600160a01b03169052565b60808801518387015260a0880151925080868503016101608701525050615f528282615d48565b9150508281036020840152614cf88185615e1a56fea164736f6c6343000818000a", + Bin: "0x6101206040523480156200001257600080fd5b5060405162006bd438038062006bd48339810160408190526200003591620008c7565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf81620001fa565b5050466080525060208301516001600160a01b03161580620000ec575060408301516001600160a01b0316155b8062000103575060608301516001600160a01b0316155b1562000122576040516342bcdf7f60e11b815260040160405180910390fd5b82516001600160401b03166000036200014e5760405163c656089560e01b815260040160405180910390fd5b82516001600160401b0390811660a052602080850180516001600160a01b0390811660c05260408088018051831660e0526060808a01805185166101005283518b519098168852945184169587019590955251821690850152905116908201527f683eb52ee924eb817377cfa8f41f238f4bb7a877da5267869dfffbad85f564d89060800160405180910390a1620001e682620002a5565b620001f181620003c1565b50505062000c67565b336001600160a01b03821603620002545760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b0316620002ce576040516342bcdf7f60e11b815260040160405180910390fd5b80516004805460208085018051604080880180516060808b0180516001600160a01b039b8c166001600160c01b0319909a168a17600160a01b63ffffffff98891602176001600160c01b0316600160c01b948816949094026001600160e01b031693909317600160e01b93871693909302929092179098556080808b018051600580546001600160a01b031916918d169190911790558451988952955185169688019690965290518316918601919091525116938301939093529151909216908201527fa55bd56595c45f517e5967a3067f3dca684445a3080e7c04a4e0d5a40cda627d9060a00160405180910390a150565b60005b815181101562000666576000828281518110620003e557620003e562000a1d565b60200260200101519050600081602001519050806001600160401b0316600003620004235760405163c656089560e01b815260040160405180910390fd5b81516001600160a01b03166200044c576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160401b0381166000908152600660205260408120600181018054919291620004789062000a33565b80601f0160208091040260200160405190810160405280929190818152602001828054620004a69062000a33565b8015620004f75780601f10620004cb57610100808354040283529160200191620004f7565b820191906000526020600020905b815481529060010190602001808311620004d957829003601f168201915b5050505050905060008460600151905081516000036200059e57805160000362000534576040516342bcdf7f60e11b815260040160405180910390fd5b6001830162000544828262000ac4565b508254600160a81b600160e81b031916600160a81b1783556040516001600160401b03851681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1620005d9565b8080519060200120828051906020012014620005d95760405163c39a620560e01b81526001600160401b038516600482015260240162000083565b604080860151845487516001600160a01b03166001600160a01b0319921515600160a01b02929092166001600160a81b031990911617178455516001600160401b038516907f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b906200064d90869062000b90565b60405180910390a25050505050806001019050620003c4565b5050565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b0381118282101715620006a557620006a56200066a565b60405290565b604051601f8201601f191681016001600160401b0381118282101715620006d657620006d66200066a565b604052919050565b80516001600160401b0381168114620006f657600080fd5b919050565b6001600160a01b03811681146200071157600080fd5b50565b805163ffffffff81168114620006f657600080fd5b6000601f83601f8401126200073d57600080fd5b825160206001600160401b03808311156200075c576200075c6200066a565b8260051b6200076d838201620006ab565b93845286810183019383810190898611156200078857600080fd5b84890192505b85831015620008ba57825184811115620007a85760008081fd5b89016080601f19828d038101821315620007c25760008081fd5b620007cc62000680565b88840151620007db81620006fb565b81526040620007ec858201620006de565b8a8301526060808601518015158114620008065760008081fd5b838301529385015193898511156200081e5760008081fd5b84860195508f603f8701126200083657600094508485fd5b8a8601519450898511156200084f576200084f6200066a565b620008608b858f88011601620006ab565b93508484528f82868801011115620008785760008081fd5b60005b8581101562000898578681018301518582018d01528b016200087b565b5060009484018b0194909452509182015283525091840191908401906200078e565b9998505050505050505050565b6000806000838503610140811215620008df57600080fd5b6080811215620008ee57600080fd5b620008f862000680565b6200090386620006de565b815260208601516200091581620006fb565b602082015260408601516200092a81620006fb565b604082015260608601516200093f81620006fb565b6060820152935060a0607f19820112156200095957600080fd5b5060405160a081016001600160401b0380821183831017156200098057620009806200066a565b81604052608087015191506200099682620006fb565b818352620009a760a0880162000714565b6020840152620009ba60c0880162000714565b6040840152620009cd60e0880162000714565b60608401526101008701519150620009e582620006fb565b608083018290526101208701519294508083111562000a0357600080fd5b505062000a138682870162000729565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b600181811c9082168062000a4857607f821691505b60208210810362000a6957634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111562000abf576000816000526020600020601f850160051c8101602086101562000a9a5750805b601f850160051c820191505b8181101562000abb5782815560010162000aa6565b5050505b505050565b81516001600160401b0381111562000ae05762000ae06200066a565b62000af88162000af1845462000a33565b8462000a6f565b602080601f83116001811462000b30576000841562000b175750858301515b600019600386901b1c1916600185901b17855562000abb565b600085815260208120601f198616915b8281101562000b615788860151825594840194600190910190840162000b40565b508582101562000b805787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b602080825282546001600160a01b0381168383015260a081901c60ff161515604084015260a81c6001600160401b0316606083015260808083015260018084018054600093929190849062000be58162000a33565b8060a089015260c0600183166000811462000c09576001811462000c265762000c58565b60ff19841660c08b015260c083151560051b8b0101945062000c58565b85600052602060002060005b8481101562000c4f5781548c820185015290880190890162000c32565b8b0160c0019550505b50929998505050505050505050565b60805160a05160c05160e05161010051615efe62000cd66000396000818161026601526129f50152600081816102370152612ee90152600081816102080152818161142b015261196d0152600081816101d801526126700152600081816117f3015261183f0152615efe6000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806385572ffb116100d8578063ccd37ba31161008c578063f2fde38b11610066578063f2fde38b14610583578063f716f99f14610596578063ff888fb1146105a957600080fd5b8063ccd37ba31461050b578063d2a15d3514610550578063e9d68a8e1461056357600080fd5b8063991a5018116100bd578063991a5018146104c5578063a80036b4146104d8578063c673e584146104eb57600080fd5b806385572ffb1461049c5780638da5cb5b146104aa57600080fd5b8063311cd5131161012f5780635e36480c116101145780635e36480c146103785780637437ff9f1461039857806379ba50971461049457600080fd5b8063311cd513146103495780633f4b04aa1461035c57600080fd5b806306285c691161016057806306285c69146101a4578063181f5a77146102ed5780632d04ab761461033657600080fd5b806304666f9c1461017c57806305d938b514610191575b600080fd5b61018f61018a366004614079565b6105cc565b005b61018f61019f366004614705565b6105e0565b61029660408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316815250905090565b6040516102e49190815167ffffffffffffffff1681526020808301516001600160a01b0390811691830191909152604080840151821690830152606092830151169181019190915260800190565b60405180910390f35b6103296040518060400160405280601181526020017f4f666652616d7020312e362e302d64657600000000000000000000000000000081525081565b6040516102e49190614880565b61018f61034436600461492b565b610785565b61018f6103573660046149de565b610b5c565b60095460405167ffffffffffffffff90911681526020016102e4565b61038b610386366004614a32565b610bc5565b6040516102e49190614a8f565b6104376040805160a081018252600080825260208201819052918101829052606081018290526080810191909152506040805160a0810182526004546001600160a01b03808216835263ffffffff600160a01b83048116602085015278010000000000000000000000000000000000000000000000008304811694840194909452600160e01b9091049092166060820152600554909116608082015290565b6040516102e49190600060a0820190506001600160a01b03808451168352602084015163ffffffff808216602086015280604087015116604086015280606087015116606086015250508060808501511660808401525092915050565b61018f610c1b565b61018f610177366004614a9d565b6000546040516001600160a01b0390911681526020016102e4565b61018f6104d3366004614aec565b610cd9565b61018f6104e6366004614b60565b610cea565b6104fe6104f9366004614bcd565b61105d565b6040516102e49190614c2d565b610542610519366004614ca2565b67ffffffffffffffff919091166000908152600860209081526040808320938352929052205490565b6040519081526020016102e4565b61018f61055e366004614ccc565b6111bb565b610576610571366004614d41565b611275565b6040516102e49190614d5c565b61018f610591366004614daa565b611382565b61018f6105a4366004614e2f565b611393565b6105bc6105b7366004614f6d565b6113d5565b60405190151581526020016102e4565b6105d4611496565b6105dd816114f2565b50565b6105e86117f0565b815181518114610624576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8181101561077557600084828151811061064357610643614f86565b6020026020010151905060008160200151519050600085848151811061066b5761066b614f86565b60200260200101519050805182146106af576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b828110156107665760008282815181106106ce576106ce614f86565b602002602001015190508060001461075d57846020015182815181106106f6576106f6614f86565b60200260200101516080015181101561075d5784516040517fc8e9605100000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260248101839052604481018290526064015b60405180910390fd5b506001016106b2565b50505050806001019050610627565b506107808383611871565b505050565b60006107938789018961510c565b805151519091501515806107ac57508051602001515115155b156108ac5760095460208a01359067ffffffffffffffff8083169116101561086b576009805467ffffffffffffffff191667ffffffffffffffff83161790556004805483516040517f3937306f0000000000000000000000000000000000000000000000000000000081526001600160a01b0390921692633937306f92610834929101615334565b600060405180830381600087803b15801561084e57600080fd5b505af1158015610862573d6000803e3d6000fd5b505050506108aa565b8160200151516000036108aa576040517f2261116700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b60005b816020015151811015610aa5576000826020015182815181106108d4576108d4614f86565b602002602001015190506000816000015190506108f081611921565b60006108fb82611a23565b602084015151815491925067ffffffffffffffff908116600160a81b9092041614158061093f575060208084015190810151905167ffffffffffffffff9182169116115b1561097f57825160208401516040517feefb0cac000000000000000000000000000000000000000000000000000000008152610754929190600401615347565b6040830151806109bb576040517f504570e300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b835167ffffffffffffffff16600090815260086020908152604080832084845290915290205415610a2e5783516040517f32cf0cbf00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260248101829052604401610754565b6020808501510151610a41906001615392565b82547fffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffff16600160a81b67ffffffffffffffff9283160217909255925116600090815260086020908152604080832094835293905291909120429055506001016108af565b507f3a3950e13dd607cc37980db0ef14266c40d2bba9c01b2e44bfe549808883095d81604051610ad591906153ba565b60405180910390a1610b5160008a8a8a8a8a8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808e0282810182019093528d82529093508d92508c9182918501908490808284376000920191909152508b9250611a8a915050565b505050505050505050565b610b9c610b6b82840184615457565b6040805160008082526020820190925290610b96565b6060815260200190600190039081610b815790505b50611871565b604080516000808252602082019092529050610bbf600185858585866000611a8a565b50505050565b6000610bd36001600461548c565b6002610be06080856154b5565b67ffffffffffffffff16610bf491906154dc565b610bfe8585611e01565b901c166003811115610c1257610c12614a65565b90505b92915050565b6001546001600160a01b03163314610c755760405162461bcd60e51b815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610754565b600080543373ffffffffffffffffffffffffffffffffffffffff19808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610ce1611496565b6105dd81611e48565b333014610d23576040517f371a732800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160008082526020820190925281610d60565b6040805180820190915260008082526020820152815260200190600190039081610d395790505b5060a08501515190915015610d9457610d918460a00151856020015186606001518760000151602001518787611fae565b90505b6040805160a0810182528551518152855160209081015167ffffffffffffffff1681830152808701518351600094840192610dd0929101614880565b60408051601f19818403018152918152908252878101516020830152018390526005549091506001600160a01b03168015610edd576040517f08d450a10000000000000000000000000000000000000000000000000000000081526001600160a01b038216906308d450a190610e4a908590600401615595565b600060405180830381600087803b158015610e6457600080fd5b505af1925050508015610e75575060015b610edd573d808015610ea3576040519150601f19603f3d011682016040523d82523d6000602084013e610ea8565b606091505b50806040517f09c253250000000000000000000000000000000000000000000000000000000081526004016107549190614880565b604086015151158015610ef257506080860151155b80610f09575060608601516001600160a01b03163b155b80610f4957506060860151610f47906001600160a01b03167f85572ffb000000000000000000000000000000000000000000000000000000006120cd565b155b15610f5657505050505050565b855160209081015167ffffffffffffffff1660009081526006909152604080822054608089015160608a015192517f3cf9798300000000000000000000000000000000000000000000000000000000815284936001600160a01b0390931692633cf9798392610fce92899261138892916004016155a8565b6000604051808303816000875af1158015610fed573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261101591908101906155e4565b50915091508161105357806040517f0a8d6e8c0000000000000000000000000000000000000000000000000000000081526004016107549190614880565b5050505050505050565b6110a06040805160e081019091526000606082018181526080830182905260a0830182905260c08301919091528190815260200160608152602001606081525090565b60ff808316600090815260026020818152604092839020835160e081018552815460608201908152600183015480881660808401526101008104881660a0840152620100009004909616151560c08201529485529182018054845181840281018401909552808552929385830193909283018282801561114957602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161112b575b50505050508152602001600382018054806020026020016040519081016040528092919081815260200182805480156111ab57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161118d575b5050505050815250509050919050565b6111c3611496565b60005b818110156107805760008383838181106111e2576111e2614f86565b9050604002018036038101906111f8919061567a565b905061120781602001516113d5565b61126c57805167ffffffffffffffff1660009081526008602090815260408083208285018051855290835281842093909355915191519182527f202f1139a3e334b6056064c0e9b19fd07e44a88d8f6e5ded571b24cf8c371f12910160405180910390a15b506001016111c6565b604080516080808201835260008083526020808401829052838501829052606080850181905267ffffffffffffffff878116845260068352928690208651948501875280546001600160a01b0381168652600160a01b810460ff16151593860193909352600160a81b909204909216948301949094526001840180549394929391840191611302906156b3565b80601f016020809104026020016040519081016040528092919081815260200182805461132e906156b3565b80156111ab5780601f10611350576101008083540402835291602001916111ab565b820191906000526020600020905b81548152906001019060200180831161135e57505050919092525091949350505050565b61138a611496565b6105dd816120e9565b61139b611496565b60005b81518110156113d1576113c98282815181106113bc576113bc614f86565b602002602001015161219f565b60010161139e565b5050565b6040805180820182523081526020810183815291517f4d61677100000000000000000000000000000000000000000000000000000000815290516001600160a01b039081166004830152915160248201526000917f00000000000000000000000000000000000000000000000000000000000000001690634d61677190604401602060405180830381865afa158015611472573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c1591906156ed565b6000546001600160a01b031633146114f05760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610754565b565b60005b81518110156113d157600082828151811061151257611512614f86565b602002602001015190506000816020015190508067ffffffffffffffff16600003611569576040517fc656089500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81516001600160a01b0316611591576040516342bcdf7f60e11b815260040160405180910390fd5b67ffffffffffffffff811660009081526006602052604081206001810180549192916115bc906156b3565b80601f01602080910402602001604051908101604052809291908181526020018280546115e8906156b3565b80156116355780601f1061160a57610100808354040283529160200191611635565b820191906000526020600020905b81548152906001019060200180831161161857829003601f168201915b5050505050905060008460600151905081516000036116ed578051600003611670576040516342bcdf7f60e11b815260040160405180910390fd5b6001830161167e828261575a565b5082547fffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffff16600160a81b17835560405167ffffffffffffffff851681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1611740565b8080519060200120828051906020012014611740576040517fc39a620500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff85166004820152602401610754565b604080860151845487516001600160a01b031673ffffffffffffffffffffffffffffffffffffffff19921515600160a01b02929092167fffffffffffffffffffffff000000000000000000000000000000000000000000909116171784555167ffffffffffffffff8516907f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b906117d890869061581a565b60405180910390a250505050508060010190506114f5565b467f0000000000000000000000000000000000000000000000000000000000000000146114f0576040517f0f01ce850000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000006004820152466024820152604401610754565b81516000036118ab576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160408051600080825260208201909252911591905b845181101561191a576119128582815181106118e0576118e0614f86565b60200260200101518461190c578583815181106118ff576118ff614f86565b60200260200101516124d7565b836124d7565b6001016118c2565b5050505050565b6040517f2cbc26bb000000000000000000000000000000000000000000000000000000008152608082901b77ffffffffffffffff000000000000000000000000000000001660048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632cbc26bb90602401602060405180830381865afa1580156119bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119e091906156ed565b156105dd576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610754565b67ffffffffffffffff811660009081526006602052604081208054600160a01b900460ff16610c15576040517fed053c5900000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610754565b60ff87811660009081526002602090815260408083208151608081018352815481526001909101548086169382019390935261010083048516918101919091526201000090910490921615156060830152873590611ae98760a46158e8565b9050826060015115611b31578451611b029060206154dc565b8651611b0f9060206154dc565b611b1a9060a06158e8565b611b2491906158e8565b611b2e90826158e8565b90505b368114611b73576040517f8e1192e100000000000000000000000000000000000000000000000000000000815260048101829052366024820152604401610754565b5081518114611bbb5781516040517f93df584c000000000000000000000000000000000000000000000000000000008152600481019190915260248101829052604401610754565b611bc36117f0565b60ff808a1660009081526003602090815260408083203384528252808320815180830190925280548086168352939491939092840191610100909104166002811115611c1157611c11614a65565b6002811115611c2257611c22614a65565b9052509050600281602001516002811115611c3f57611c3f614a65565b148015611c935750600260008b60ff1660ff168152602001908152602001600020600301816000015160ff1681548110611c7b57611c7b614f86565b6000918252602090912001546001600160a01b031633145b611cc9576040517fda0f08e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50816060015115611dab576020820151611ce49060016158fb565b60ff16855114611d20576040517f71253a2500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8351855114611d5b576040517fa75d88af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008787604051611d6d929190615914565b604051908190038120611d84918b90602001615924565b604051602081830303815290604052805190602001209050611da98a82888888612ca3565b505b6040805182815260208a81013567ffffffffffffffff169082015260ff8b16917f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef0910160405180910390a2505050505050505050565b67ffffffffffffffff8216600090815260076020526040812081611e26608085615938565b67ffffffffffffffff1681526020810191909152604001600020549392505050565b80516001600160a01b0316611e70576040516342bcdf7f60e11b815260040160405180910390fd5b80516004805460208085018051604080880180516060808b0180516001600160a01b039b8c167fffffffffffffffff000000000000000000000000000000000000000000000000909a168a17600160a01b63ffffffff988916021777ffffffffffffffffffffffffffffffffffffffffffffffff167801000000000000000000000000000000000000000000000000948816949094026001600160e01b031693909317600160e01b93871693909302929092179098556080808b0180516005805473ffffffffffffffffffffffffffffffffffffffff1916918d169190911790558451988952955185169688019690965290518316918601919091525116938301939093529151909216908201527fa55bd56595c45f517e5967a3067f3dca684445a3080e7c04a4e0d5a40cda627d9060a00160405180910390a150565b6060865167ffffffffffffffff811115611fca57611fca613e90565b60405190808252806020026020018201604052801561200f57816020015b6040805180820190915260008082526020820152815260200190600190039081611fe85790505b50905060005b87518110156120c15761209c88828151811061203357612033614f86565b602002602001015188888888888781811061205057612050614f86565b9050602002810190612062919061595f565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612e8892505050565b8282815181106120ae576120ae614f86565b6020908102919091010152600101612015565b505b9695505050505050565b60006120d88361322d565b8015610c125750610c128383613291565b336001600160a01b038216036121415760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610754565b6001805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b806040015160ff166000036121ca576000604051631b3fab5160e11b815260040161075491906159c4565b60208082015160ff8082166000908152600290935260408320600181015492939092839216900361223757606084015160018201805491151562010000027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff90921691909117905561228c565b6060840151600182015460ff620100009091041615159015151461228c576040517f87f6037c00000000000000000000000000000000000000000000000000000000815260ff84166004820152602401610754565b60a08401518051601f10156122b7576001604051631b3fab5160e11b815260040161075491906159c4565b61231d848460030180548060200260200160405190810160405280929190818152602001828054801561231357602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116122f5575b505050505061334c565b84606001511561244c5761238b8484600201805480602002602001604051908101604052809291908181526020018280548015612313576020028201919060005260206000209081546001600160a01b031681526001909101906020018083116122f557505050505061334c565b608085015180516123a59060028601906020840190613e09565b5080516001840180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1661010060ff841690810291909117909155601f1015612405576002604051631b3fab5160e11b815260040161075491906159c4565b60408701516124159060036159de565b60ff168160ff161161243d576003604051631b3fab5160e11b815260040161075491906159c4565b612449868360016133b5565b50505b612458848260026133b5565b805161246d9060038501906020840190613e09565b5060408581015160018401805460ff191660ff8316179055865180855560a088015192517fab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f547936124c69389939260028a019291906159fa565b60405180910390a161191a84613529565b81516124e281611921565b60006124ed82611a23565b60010180546124fb906156b3565b80601f0160208091040260200160405190810160405280929190818152602001828054612527906156b3565b80156125745780601f1061254957610100808354040283529160200191612574565b820191906000526020600020905b81548152906001019060200180831161255757829003601f168201915b505050602087015151929350505060008190036125bc576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84604001515181146125fa576040517f57e0e08300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008167ffffffffffffffff81111561261557612615613e90565b60405190808252806020026020018201604052801561263e578160200160208202803683370190505b50905060005b828110156127275760008760200151828151811061266457612664614f86565b602002602001015190507f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681600001516040015167ffffffffffffffff16146126f757805160409081015190517f38432a2200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610754565b6127018186613545565b83838151811061271357612713614f86565b602090810291909101015250600101612644565b50600061273e858389606001518a60800151613667565b905080600003612786576040517f7dd17a7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff86166004820152602401610754565b8551151560005b84811015610b515760005a905060008a6020015183815181106127b2576127b2614f86565b6020026020010151905060006127d08a836000015160600151610bc5565b905060008160038111156127e6576127e6614a65565b14806128035750600381600381111561280157612801614a65565b145b61285b578151606001516040805167ffffffffffffffff808e16825290921660208301527f3b575419319662b2a6f5e2467d84521517a3382b908eb3d557bb3fdb0c50e23c91015b60405180910390a1505050612c9b565b841561292b57600454600090600160a01b900463ffffffff1661287e884261548c565b119050808061289e5750600382600381111561289c5761289c614a65565b145b6128e0576040517fa9cfc86200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8c166004820152602401610754565b8b85815181106128f2576128f2614f86565b6020026020010151600014612925578b858151811061291357612913614f86565b60200260200101518360800181815250505b5061298c565b600081600381111561293f5761293f614a65565b1461298c578151606001516040805167ffffffffffffffff808e16825290921660208301527f3ef2a99c550a751d4b0b261268f05a803dfb049ab43616a1ffb388f61fe65120910161284b565b81516080015167ffffffffffffffff1615612a7b5760008160038111156129b5576129b5614a65565b03612a7b5781516080015160208301516040517fe0e03cae0000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169263e0e03cae92612a2c928f929190600401615aa6565b6020604051808303816000875af1158015612a4b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a6f91906156ed565b612a7b57505050612c9b565b60008c604001518581518110612a9357612a93614f86565b6020026020010151905080518360a001515114612af7578251606001516040517f1cfe6d8b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808e1660048301529091166024820152604401610754565b612b0b8b84600001516060015160016136bd565b600080612b188584613765565b91509150612b2f8d866000015160600151846136bd565b8715612b9f576003826003811115612b4957612b49614a65565b03612b9f576000846003811115612b6257612b62614a65565b14612b9f578451516040517f2b11b8d900000000000000000000000000000000000000000000000000000000815261075491908390600401615ad3565b6002826003811115612bb357612bb3614a65565b14612c0d576003826003811115612bcc57612bcc614a65565b14612c0d578451606001516040517f926c5a3e000000000000000000000000000000000000000000000000000000008152610754918f918590600401615aec565b84600001516000015185600001516060015167ffffffffffffffff168e67ffffffffffffffff167f05665fe9ad095383d018353f4cbcba77e84db27dd215081bbf7cdf9ae6fbe48b8d8b81518110612c6757612c67614f86565b602002602001015186865a612c7c908e61548c565b604051612c8c9493929190615b12565b60405180910390a45050505050505b60010161278d565b8251600090815b81811015611053576000600188868460208110612cc957612cc9614f86565b612cd691901a601b6158fb565b898581518110612ce857612ce8614f86565b6020026020010151898681518110612d0257612d02614f86565b602002602001015160405160008152602001604052604051612d40949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015612d62573d6000803e3d6000fd5b505060408051601f1981015160ff808e166000908152600360209081528582206001600160a01b03851683528152858220858701909652855480841686529397509095509293928401916101009004166002811115612dc357612dc3614a65565b6002811115612dd457612dd4614a65565b9052509050600181602001516002811115612df157612df1614a65565b14612e28576040517fca31867a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051600160ff9091161b851615612e6b576040517ff67bc7c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806000015160ff166001901b851794505050806001019050612caa565b60408051808201909152600080825260208201526000612eab876020015161382f565b6040517fbbe4f6db0000000000000000000000000000000000000000000000000000000081526001600160a01b0380831660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063bbe4f6db90602401602060405180830381865afa158015612f30573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f549190615b49565b90506001600160a01b0381161580612f9c5750612f9a6001600160a01b0382167faff2afbf000000000000000000000000000000000000000000000000000000006120cd565b155b15612fde576040517fae9b4ce90000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152602401610754565b60045460009081906130009089908690600160e01b900463ffffffff166138d5565b9150915060008060006130cd6040518061010001604052808e81526020018c67ffffffffffffffff1681526020018d6001600160a01b031681526020018f606001518152602001896001600160a01b031681526020018f6000015181526020018f6040015181526020018b81525060405160240161307e9190615b66565b60408051601f198184030181529190526020810180516001600160e01b03167f390775370000000000000000000000000000000000000000000000000000000017905287866113886084613a03565b9250925092508261310c57816040517fe1cd55090000000000000000000000000000000000000000000000000000000081526004016107549190614880565b81516020146131545781516040517f78ef8024000000000000000000000000000000000000000000000000000000008152602060048201526024810191909152604401610754565b60008280602001905181019061316a9190615c33565b9050866001600160a01b03168c6001600160a01b0316146131ff57600061319b8d8a613196868a61548c565b6138d5565b509050868110806131b55750816131b2888361548c565b14155b156131fd576040517fa966e21f000000000000000000000000000000000000000000000000000000008152600481018390526024810188905260448101829052606401610754565b505b604080518082019091526001600160a01b039098168852602088015250949550505050505095945050505050565b6000613259827f01ffc9a700000000000000000000000000000000000000000000000000000000613291565b8015610c15575061328a827fffffffff00000000000000000000000000000000000000000000000000000000613291565b1592915050565b6040517fffffffff0000000000000000000000000000000000000000000000000000000082166024820152600090819060440160408051601f19818403018152919052602080820180516001600160e01b03167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825192935060009283928392909183918a617530fa92503d91506000519050828015613335575060208210155b80156133415750600081115b979650505050505050565b60005b81518110156107805760ff83166000908152600360205260408120835190919084908490811061338157613381614f86565b6020908102919091018101516001600160a01b03168252810191909152604001600020805461ffff1916905560010161334f565b60005b8251811015610bbf5760008382815181106133d5576133d5614f86565b60200260200101519050600060028111156133f2576133f2614a65565b60ff80871660009081526003602090815260408083206001600160a01b0387168452909152902054610100900416600281111561343157613431614a65565b14613452576004604051631b3fab5160e11b815260040161075491906159c4565b6001600160a01b038116613492576040517fd6c62c9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052808360ff1681526020018460028111156134b8576134b8614a65565b905260ff80871660009081526003602090815260408083206001600160a01b0387168452825290912083518154931660ff198416811782559184015190929091839161ffff19161761010083600281111561351557613515614a65565b0217905550905050508060010190506133b8565b60ff81166105dd576009805467ffffffffffffffff1916905550565b81516020808201516040928301519251600093849361358b937f2425b0b9f9054c76ff151b0a175b18f37a4a4e82013a72e9f15c9caa095ed21f93909291889101615c4c565b60408051601f1981840301815290829052805160209182012086518051888401516060808b0151908401516080808d015195015195976135d49794969395929491939101615c7f565b604051602081830303815290604052805190602001208560400151805190602001208660a0015160405160200161360b9190615d91565b60408051601f198184030181528282528051602091820120908301969096528101939093526060830191909152608082015260a081019190915260c0015b60405160208183030381529060405280519060200120905092915050565b600080613675858585613b29565b9050613680816113d5565b61368e5760009150506136b5565b67ffffffffffffffff86166000908152600860209081526040808320938352929052205490505b949350505050565b600060026136cc6080856154b5565b67ffffffffffffffff166136e091906154dc565b905060006136ee8585611e01565b9050816136fd6001600461548c565b901b19168183600381111561371457613714614a65565b67ffffffffffffffff871660009081526007602052604081209190921b92909217918291613743608088615938565b67ffffffffffffffff1681526020810191909152604001600020555050505050565b6040517fa80036b4000000000000000000000000000000000000000000000000000000008152600090606090309063a80036b4906137a99087908790600401615df1565b600060405180830381600087803b1580156137c357600080fd5b505af19250505080156137d4575060015b613813573d808015613802576040519150601f19603f3d011682016040523d82523d6000602084013e613807565b606091505b50600392509050613828565b50506040805160208101909152600081526002905b9250929050565b6000815160201461386e57816040517f8d666f600000000000000000000000000000000000000000000000000000000081526004016107549190614880565b6000828060200190518101906138849190615c33565b90506001600160a01b0381118061389c575061040081105b15610c1557826040517f8d666f600000000000000000000000000000000000000000000000000000000081526004016107549190614880565b600080600080600061394f8860405160240161390091906001600160a01b0391909116815260200190565b60408051601f198184030181529190526020810180516001600160e01b03167f70a082310000000000000000000000000000000000000000000000000000000017905288886113886084613a03565b9250925092508261398e57816040517fe1cd55090000000000000000000000000000000000000000000000000000000081526004016107549190614880565b60208251146139d65781516040517f78ef8024000000000000000000000000000000000000000000000000000000008152602060048201526024810191909152604401610754565b818060200190518101906139ea9190615c33565b6139f4828861548c565b94509450505050935093915050565b6000606060008361ffff1667ffffffffffffffff811115613a2657613a26613e90565b6040519080825280601f01601f191660200182016040528015613a50576020820181803683370190505b509150863b613a83577f0c3b563c0000000000000000000000000000000000000000000000000000000060005260046000fd5b5a85811015613ab6577fafa32a2c0000000000000000000000000000000000000000000000000000000060005260046000fd5b8590036040810481038710613aef577f37c3be290000000000000000000000000000000000000000000000000000000060005260046000fd5b505a6000808a5160208c0160008c8cf193505a900390503d84811115613b125750835b808352806000602085013e50955095509592505050565b8251825160009190818303613b6a576040517f11a6b26400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6101018211801590613b7e57506101018111155b613b9b576040516309bde33960e01b815260040160405180910390fd5b60001982820101610100811115613bc5576040516309bde33960e01b815260040160405180910390fd5b80600003613bf25786600081518110613be057613be0614f86565b60200260200101519350505050613dc1565b60008167ffffffffffffffff811115613c0d57613c0d613e90565b604051908082528060200260200182016040528015613c36578160200160208202803683370190505b50905060008080805b85811015613d605760006001821b8b811603613c9a5788851015613c83578c5160018601958e918110613c7457613c74614f86565b60200260200101519050613cbc565b8551600185019487918110613c7457613c74614f86565b8b5160018401938d918110613cb157613cb1614f86565b602002602001015190505b600089861015613cec578d5160018701968f918110613cdd57613cdd614f86565b60200260200101519050613d0e565b8651600186019588918110613d0357613d03614f86565b602002602001015190505b82851115613d2f576040516309bde33960e01b815260040160405180910390fd5b613d398282613dc8565b878481518110613d4b57613d4b614f86565b60209081029190910101525050600101613c3f565b506001850382148015613d7257508683145b8015613d7d57508581145b613d9a576040516309bde33960e01b815260040160405180910390fd5b836001860381518110613daf57613daf614f86565b60200260200101519750505050505050505b9392505050565b6000818310613de057613ddb8284613de6565b610c12565b610c1283835b604080516001602082015290810183905260608101829052600090608001613649565b828054828255906000526020600020908101928215613e6b579160200282015b82811115613e6b578251825473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03909116178255602090920191600190910190613e29565b50613e77929150613e7b565b5090565b5b80821115613e775760008155600101613e7c565b634e487b7160e01b600052604160045260246000fd5b6040516080810167ffffffffffffffff81118282101715613ec957613ec9613e90565b60405290565b60405160a0810167ffffffffffffffff81118282101715613ec957613ec9613e90565b60405160c0810167ffffffffffffffff81118282101715613ec957613ec9613e90565b6040805190810167ffffffffffffffff81118282101715613ec957613ec9613e90565b6040516060810167ffffffffffffffff81118282101715613ec957613ec9613e90565b604051601f8201601f1916810167ffffffffffffffff81118282101715613f8457613f84613e90565b604052919050565b600067ffffffffffffffff821115613fa657613fa6613e90565b5060051b60200190565b6001600160a01b03811681146105dd57600080fd5b803567ffffffffffffffff81168114613fdd57600080fd5b919050565b80151581146105dd57600080fd5b8035613fdd81613fe2565b600067ffffffffffffffff82111561401557614015613e90565b50601f01601f191660200190565b600082601f83011261403457600080fd5b813561404761404282613ffb565b613f5b565b81815284602083860101111561405c57600080fd5b816020850160208301376000918101602001919091529392505050565b6000602080838503121561408c57600080fd5b823567ffffffffffffffff808211156140a457600080fd5b818501915085601f8301126140b857600080fd5b81356140c661404282613f8c565b81815260059190911b830184019084810190888311156140e557600080fd5b8585015b8381101561418b578035858111156141015760008081fd5b86016080818c03601f19018113156141195760008081fd5b614121613ea6565b8983013561412e81613fb0565b8152604061413d848201613fc5565b8b83015260608085013561415081613fe2565b8383015292840135928984111561416957600091508182fd5b6141778f8d86880101614023565b9083015250855250509186019186016140e9565b5098975050505050505050565b600060a082840312156141aa57600080fd5b6141b2613ecf565b9050813581526141c460208301613fc5565b60208201526141d560408301613fc5565b60408201526141e660608301613fc5565b60608201526141f760808301613fc5565b608082015292915050565b8035613fdd81613fb0565b600082601f83011261421e57600080fd5b8135602061422e61404283613f8c565b82815260059290921b8401810191818101908684111561424d57600080fd5b8286015b848110156120c157803567ffffffffffffffff808211156142725760008081fd5b818901915060a080601f19848d0301121561428d5760008081fd5b614295613ecf565b87840135838111156142a75760008081fd5b6142b58d8a83880101614023565b825250604080850135848111156142cc5760008081fd5b6142da8e8b83890101614023565b8a84015250606080860135858111156142f35760008081fd5b6143018f8c838a0101614023565b838501525060809150818601358184015250828501359250838311156143275760008081fd5b6143358d8a85880101614023565b908201528652505050918301918301614251565b6000610140828403121561435c57600080fd5b614364613ef2565b90506143708383614198565b815260a082013567ffffffffffffffff8082111561438d57600080fd5b61439985838601614023565b602084015260c08401359150808211156143b257600080fd5b6143be85838601614023565b60408401526143cf60e08501614202565b606084015261010084013560808401526101208401359150808211156143f457600080fd5b506144018482850161420d565b60a08301525092915050565b600082601f83011261441e57600080fd5b8135602061442e61404283613f8c565b82815260059290921b8401810191818101908684111561444d57600080fd5b8286015b848110156120c157803567ffffffffffffffff8111156144715760008081fd5b61447f8986838b0101614349565b845250918301918301614451565b600082601f83011261449e57600080fd5b813560206144ae61404283613f8c565b82815260059290921b840181019181810190868411156144cd57600080fd5b8286015b848110156120c157803567ffffffffffffffff808211156144f157600080fd5b818901915089603f83011261450557600080fd5b8582013561451561404282613f8c565b81815260059190911b830160400190878101908c83111561453557600080fd5b604085015b8381101561456e5780358581111561455157600080fd5b6145608f6040838a0101614023565b84525091890191890161453a565b508752505050928401925083016144d1565b600082601f83011261459157600080fd5b813560206145a161404283613f8c565b8083825260208201915060208460051b8701019350868411156145c357600080fd5b602086015b848110156120c157803583529183019183016145c8565b600082601f8301126145f057600080fd5b8135602061460061404283613f8c565b82815260059290921b8401810191818101908684111561461f57600080fd5b8286015b848110156120c157803567ffffffffffffffff808211156146445760008081fd5b818901915060a080601f19848d0301121561465f5760008081fd5b614667613ecf565b614672888501613fc5565b8152604080850135848111156146885760008081fd5b6146968e8b8389010161440d565b8a84015250606080860135858111156146af5760008081fd5b6146bd8f8c838a010161448d565b83850152506080915081860135858111156146d85760008081fd5b6146e68f8c838a0101614580565b9184019190915250919093013590830152508352918301918301614623565b600080604080848603121561471957600080fd5b833567ffffffffffffffff8082111561473157600080fd5b61473d878388016145df565b945060209150818601358181111561475457600080fd5b8601601f8101881361476557600080fd5b803561477361404282613f8c565b81815260059190911b8201840190848101908a83111561479257600080fd5b8584015b8381101561481e578035868111156147ae5760008081fd5b8501603f81018d136147c05760008081fd5b878101356147d061404282613f8c565b81815260059190911b82018a0190898101908f8311156147f05760008081fd5b928b01925b8284101561480e5783358252928a0192908a01906147f5565b8652505050918601918601614796565b50809750505050505050509250929050565b60005b8381101561484b578181015183820152602001614833565b50506000910152565b6000815180845261486c816020860160208601614830565b601f01601f19169290920160200192915050565b602081526000610c126020830184614854565b8060608101831015610c1557600080fd5b60008083601f8401126148b657600080fd5b50813567ffffffffffffffff8111156148ce57600080fd5b60208301915083602082850101111561382857600080fd5b60008083601f8401126148f857600080fd5b50813567ffffffffffffffff81111561491057600080fd5b6020830191508360208260051b850101111561382857600080fd5b60008060008060008060008060e0898b03121561494757600080fd5b6149518a8a614893565b9750606089013567ffffffffffffffff8082111561496e57600080fd5b61497a8c838d016148a4565b909950975060808b013591508082111561499357600080fd5b61499f8c838d016148e6565b909750955060a08b01359150808211156149b857600080fd5b506149c58b828c016148e6565b999c989b50969995989497949560c00135949350505050565b6000806000608084860312156149f357600080fd5b6149fd8585614893565b9250606084013567ffffffffffffffff811115614a1957600080fd5b614a25868287016148a4565b9497909650939450505050565b60008060408385031215614a4557600080fd5b614a4e83613fc5565b9150614a5c60208401613fc5565b90509250929050565b634e487b7160e01b600052602160045260246000fd5b60048110614a8b57614a8b614a65565b9052565b60208101610c158284614a7b565b600060208284031215614aaf57600080fd5b813567ffffffffffffffff811115614ac657600080fd5b820160a08185031215613dc157600080fd5b803563ffffffff81168114613fdd57600080fd5b600060a08284031215614afe57600080fd5b614b06613ecf565b8235614b1181613fb0565b8152614b1f60208401614ad8565b6020820152614b3060408401614ad8565b6040820152614b4160608401614ad8565b60608201526080830135614b5481613fb0565b60808201529392505050565b600080600060408486031215614b7557600080fd5b833567ffffffffffffffff80821115614b8d57600080fd5b614b9987838801614349565b94506020860135915080821115614baf57600080fd5b50614a25868287016148e6565b803560ff81168114613fdd57600080fd5b600060208284031215614bdf57600080fd5b610c1282614bbc565b60008151808452602080850194506020840160005b83811015614c225781516001600160a01b031687529582019590820190600101614bfd565b509495945050505050565b60208152600082518051602084015260ff602082015116604084015260ff604082015116606084015260608101511515608084015250602083015160c060a0840152614c7c60e0840182614be8565b90506040840151601f198483030160c0850152614c998282614be8565b95945050505050565b60008060408385031215614cb557600080fd5b614cbe83613fc5565b946020939093013593505050565b60008060208385031215614cdf57600080fd5b823567ffffffffffffffff80821115614cf757600080fd5b818501915085601f830112614d0b57600080fd5b813581811115614d1a57600080fd5b8660208260061b8501011115614d2f57600080fd5b60209290920196919550909350505050565b600060208284031215614d5357600080fd5b610c1282613fc5565b602081526001600160a01b03825116602082015260208201511515604082015267ffffffffffffffff6040830151166060820152600060608301516080808401526136b560a0840182614854565b600060208284031215614dbc57600080fd5b8135613dc181613fb0565b600082601f830112614dd857600080fd5b81356020614de861404283613f8c565b8083825260208201915060208460051b870101935086841115614e0a57600080fd5b602086015b848110156120c1578035614e2281613fb0565b8352918301918301614e0f565b60006020808385031215614e4257600080fd5b823567ffffffffffffffff80821115614e5a57600080fd5b818501915085601f830112614e6e57600080fd5b8135614e7c61404282613f8c565b81815260059190911b83018401908481019088831115614e9b57600080fd5b8585015b8381101561418b57803585811115614eb657600080fd5b860160c0818c03601f19011215614ecd5760008081fd5b614ed5613ef2565b8882013581526040614ee8818401614bbc565b8a8301526060614ef9818501614bbc565b8284015260809150614f0c828501613ff0565b9083015260a08381013589811115614f245760008081fd5b614f328f8d83880101614dc7565b838501525060c0840135915088821115614f4c5760008081fd5b614f5a8e8c84870101614dc7565b9083015250845250918601918601614e9f565b600060208284031215614f7f57600080fd5b5035919050565b634e487b7160e01b600052603260045260246000fd5b80356001600160e01b0381168114613fdd57600080fd5b600082601f830112614fc457600080fd5b81356020614fd461404283613f8c565b82815260069290921b84018101918181019086841115614ff357600080fd5b8286015b848110156120c157604081890312156150105760008081fd5b615018613f15565b61502182613fc5565b815261502e858301614f9c565b81860152835291830191604001614ff7565b600082601f83011261505157600080fd5b8135602061506161404283613f8c565b82815260079290921b8401810191818101908684111561508057600080fd5b8286015b848110156120c157808803608081121561509e5760008081fd5b6150a6613f38565b6150af83613fc5565b8152604080601f19840112156150c55760008081fd5b6150cd613f15565b92506150da878501613fc5565b83526150e7818501613fc5565b8388015281870192909252606083013591810191909152835291830191608001615084565b6000602080838503121561511f57600080fd5b823567ffffffffffffffff8082111561513757600080fd5b8185019150604080838803121561514d57600080fd5b615155613f15565b83358381111561516457600080fd5b84016040818a03121561517657600080fd5b61517e613f15565b81358581111561518d57600080fd5b8201601f81018b1361519e57600080fd5b80356151ac61404282613f8c565b81815260069190911b8201890190898101908d8311156151cb57600080fd5b928a01925b8284101561521b5787848f0312156151e85760008081fd5b6151f0613f15565b84356151fb81613fb0565b8152615208858d01614f9c565b818d0152825292870192908a01906151d0565b84525050508187013593508484111561523357600080fd5b61523f8a858401614fb3565b818801528252508385013591508282111561525957600080fd5b61526588838601615040565b85820152809550505050505092915050565b805160408084528151848201819052600092602091908201906060870190855b818110156152ce57835180516001600160a01b031684528501516001600160e01b0316858401529284019291850191600101615297565b50508583015187820388850152805180835290840192506000918401905b80831015615328578351805167ffffffffffffffff1683528501516001600160e01b0316858301529284019260019290920191908501906152ec565b50979650505050505050565b602081526000610c126020830184615277565b67ffffffffffffffff8316815260608101613dc16020830184805167ffffffffffffffff908116835260209182015116910152565b634e487b7160e01b600052601160045260246000fd5b67ffffffffffffffff8181168382160190808211156153b3576153b361537c565b5092915050565b6000602080835260608451604080848701526153d96060870183615277565b87850151878203601f19016040890152805180835290860193506000918601905b8083101561418b57845167ffffffffffffffff81511683528781015161543989850182805167ffffffffffffffff908116835260209182015116910152565b508401518287015293860193600192909201916080909101906153fa565b60006020828403121561546957600080fd5b813567ffffffffffffffff81111561548057600080fd5b6136b5848285016145df565b81810381811115610c1557610c1561537c565b634e487b7160e01b600052601260045260246000fd5b600067ffffffffffffffff808416806154d0576154d061549f565b92169190910692915050565b8082028115828204841417610c1557610c1561537c565b805182526000602067ffffffffffffffff81840151168185015260408084015160a0604087015261552760a0870182614854565b9050606085015186820360608801526155408282614854565b608087810151898303918a01919091528051808352908601935060009250908501905b8083101561532857835180516001600160a01b0316835286015186830152928501926001929092019190840190615563565b602081526000610c1260208301846154f3565b6080815260006155bb60808301876154f3565b61ffff9590951660208301525060408101929092526001600160a01b0316606090910152919050565b6000806000606084860312156155f957600080fd5b835161560481613fe2565b602085015190935067ffffffffffffffff81111561562157600080fd5b8401601f8101861361563257600080fd5b805161564061404282613ffb565b81815287602083850101111561565557600080fd5b615666826020830160208601614830565b809450505050604084015190509250925092565b60006040828403121561568c57600080fd5b615694613f15565b61569d83613fc5565b8152602083013560208201528091505092915050565b600181811c908216806156c757607f821691505b6020821081036156e757634e487b7160e01b600052602260045260246000fd5b50919050565b6000602082840312156156ff57600080fd5b8151613dc181613fe2565b601f821115610780576000816000526020600020601f850160051c810160208610156157335750805b601f850160051c820191505b818110156157525782815560010161573f565b505050505050565b815167ffffffffffffffff81111561577457615774613e90565b6157888161578284546156b3565b8461570a565b602080601f8311600181146157bd57600084156157a55750858301515b600019600386901b1c1916600185901b178555615752565b600085815260208120601f198616915b828110156157ec578886015182559484019460019091019084016157cd565b508582101561580a5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6000602080835283546001600160a01b038116602085015260ff8160a01c161515604085015267ffffffffffffffff8160a81c1660608501525060018085016080808601526000815461586c816156b3565b8060a089015260c0600183166000811461588d57600181146158a9576158d9565b60ff19841660c08b015260c083151560051b8b010194506158d9565b85600052602060002060005b848110156158d05781548c82018501529088019089016158b5565b8b0160c0019550505b50929998505050505050505050565b80820180821115610c1557610c1561537c565b60ff8181168382160190811115610c1557610c1561537c565b8183823760009101908152919050565b828152606082602083013760800192915050565b600067ffffffffffffffff808416806159535761595361549f565b92169190910492915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261599457600080fd5b83018035915067ffffffffffffffff8211156159af57600080fd5b60200191503681900382131561382857600080fd5b60208101600583106159d8576159d8614a65565b91905290565b60ff81811683821602908116908181146153b3576153b361537c565b600060a0820160ff881683526020878185015260a0604085015281875480845260c0860191508860005282600020935060005b81811015615a525784546001600160a01b031683526001948501949284019201615a2d565b50508481036060860152865180825290820192508187019060005b81811015615a925782516001600160a01b031685529383019391830191600101615a6d565b50505060ff851660808501525090506120c3565b600067ffffffffffffffff808616835280851660208401525060606040830152614c996060830184614854565b8281526040602082015260006136b56040830184614854565b67ffffffffffffffff848116825283166020820152606081016136b56040830184614a7b565b848152615b226020820185614a7b565b608060408201526000615b386080830185614854565b905082606083015295945050505050565b600060208284031215615b5b57600080fd5b8151613dc181613fb0565b6020815260008251610100806020850152615b85610120850183614854565b91506020850151615ba2604086018267ffffffffffffffff169052565b5060408501516001600160a01b038116606086015250606085015160808501526080850151615bdc60a08601826001600160a01b03169052565b5060a0850151601f19808685030160c0870152615bf98483614854565b935060c08701519150808685030160e0870152615c168483614854565b935060e08701519150808685030183870152506120c38382614854565b600060208284031215615c4557600080fd5b5051919050565b848152600067ffffffffffffffff8086166020840152808516604084015250608060608301526120c36080830184614854565b86815260c060208201526000615c9860c0830188614854565b6001600160a01b039690961660408301525067ffffffffffffffff9384166060820152608081019290925290911660a09091015292915050565b600082825180855260208086019550808260051b84010181860160005b84811015615d8457601f19868403018952815160a08151818652615d1582870182614854565b9150508582015185820387870152615d2d8282614854565b91505060408083015186830382880152615d478382614854565b92505050606080830151818701525060808083015192508582038187015250615d708183614854565b9a86019a9450505090830190600101615cef565b5090979650505050505050565b602081526000610c126020830184615cd2565b60008282518085526020808601955060208260051b8401016020860160005b84811015615d8457601f19868403018952615ddf838351614854565b98840198925090830190600101615dc3565b604081526000835180516040840152602081015167ffffffffffffffff80821660608601528060408401511660808601528060608401511660a08601528060808401511660c086015250505060208401516101408060e0850152615e59610180850183614854565b915060408601517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08086850301610100870152615e968483614854565b935060608801519150615eb56101208701836001600160a01b03169052565b60808801518387015260a0880151925080868503016101608701525050615edc8282615cd2565b9150508281036020840152614c998185615da456fea164736f6c6343000818000a", } var OffRampABI = OffRampMetaData.ABI diff --git a/core/gethwrappers/ccip/generated/onramp/onramp.go b/core/gethwrappers/ccip/generated/onramp/onramp.go index dd2428a143..bd07c18f3a 100644 --- a/core/gethwrappers/ccip/generated/onramp/onramp.go +++ b/core/gethwrappers/ccip/generated/onramp/onramp.go @@ -98,7 +98,7 @@ type OnRampStaticConfig struct { var OnRampMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CannotSendZeroTokens\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GetSupportedTokensFunctionalityRemovedCheckAdminRegistry\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidAllowListRequest\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidDestChainConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeCalledByRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrAllowlistAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RouterMustSetOriginalSender\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"UnsupportedToken\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"name\":\"AllowListAdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"senders\",\"type\":\"address[]\"}],\"name\":\"AllowListSendersAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"senders\",\"type\":\"address[]\"}],\"name\":\"AllowListSendersRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"CCIPSendRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOnRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"allowListEnabled\",\"type\":\"bool\"}],\"name\":\"DestChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"feeValueJuels\",\"type\":\"uint256\"}],\"name\":\"FeePaid\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeeTokenWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"allowListEnabled\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"addedAllowlistedSenders\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"removedAllowlistedSenders\",\"type\":\"address[]\"}],\"internalType\":\"structOnRamp.AllowListConfigArgs[]\",\"name\":\"allowListConfigArgsItems\",\"type\":\"tuple[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyDestChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"}],\"name\":\"forwardFromRouter\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getAllowedSendersList\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getDestChainConfig\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"allowListEnabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getExpectedNextSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"getFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"},{\"internalType\":\"contractIERC20\",\"name\":\"sourceToken\",\"type\":\"address\"}],\"name\":\"getPoolBySourceToken\",\"outputs\":[{\"internalType\":\"contractIPoolV1\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"contractIRouter\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"name\":\"getSupportedTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"setDynamicConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"withdrawFeeTokens\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x6101006040523480156200001257600080fd5b506040516200407338038062004073833981016040819052620000359162000665565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf8162000186565b505083516001600160401b031615905080620000e6575060208301516001600160a01b0316155b80620000fd575060408301516001600160a01b0316155b8062000114575060608301516001600160a01b0316155b1562000133576040516306b7c75960e31b815260040160405180910390fd5b82516001600160401b031660805260208301516001600160a01b0390811660a0526040840151811660c05260608401511660e052620001728262000231565b6200017d8162000390565b5050506200079f565b336001600160a01b03821603620001e05760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b0316158062000254575060408101516001600160a01b0316155b1562000273576040516306b7c75960e31b815260040160405180910390fd5b8051600280546001600160a01b03199081166001600160a01b0393841617909155602080840180516003805485169186169190911790556040808601805160048054871691881691909117905560608088018051600580549098169089161790965582516080808201855280516001600160401b031680835260a080518b16848a0190815260c080518d16868a0190815260e080518f169789019788528a5195865292518e169b85019b909b5299518c169783019790975292518a169381019390935289518916908301529351871693810193909352518516928201929092529151909216918101919091527f23a1adf8ad7fad6091a4803227af2cee848c01a7c812404cade7c25636925e32906101000160405180910390a150565b60005b8151811015620004cf576000828281518110620003b457620003b462000789565b602002602001015190506000838381518110620003d557620003d562000789565b6020026020010151600001519050806001600160401b03166000036200041a5760405163c35aa79d60e01b81526001600160401b038216600482015260240162000083565b6001600160401b03818116600081815260066020908152604091829020868201518154600160481b600160e81b0319811669010000000000000000006001600160a01b03909316928302908117808555865192891691909816178152928301526801000000000000000090940460ff161515918101919091527fd5ad72bc37dc7a80a8b9b9df20500046fd7341adb1be2258a540466fdd7dcef59060600160405180910390a250505080600101905062000393565b5050565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b03811182821017156200050e576200050e620004d3565b60405290565b604080519081016001600160401b03811182821017156200050e576200050e620004d3565b604051601f8201601f191681016001600160401b0381118282101715620005645762000564620004d3565b604052919050565b80516001600160401b03811681146200058457600080fd5b919050565b6001600160a01b03811681146200059f57600080fd5b50565b600082601f830112620005b457600080fd5b815160206001600160401b03821115620005d257620005d2620004d3565b620005e2818360051b0162000539565b82815260069290921b840181019181810190868411156200060257600080fd5b8286015b848110156200065a5760408189031215620006215760008081fd5b6200062b62000514565b62000636826200056c565b815284820151620006478162000589565b8186015283529183019160400162000606565b509695505050505050565b60008060008385036101208112156200067d57600080fd5b60808112156200068c57600080fd5b62000696620004e9565b620006a1866200056c565b81526020860151620006b38162000589565b60208201526040860151620006c88162000589565b60408201526060860151620006dd8162000589565b606082015293506080607f1982011215620006f757600080fd5b5062000702620004e9565b6080850151620007128162000589565b815260a0850151620007248162000589565b602082015260c0850151620007398162000589565b604082015260e08501516200074e8162000589565b60608201526101008501519092506001600160401b038111156200077157600080fd5b6200077f86828701620005a2565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b60805160a05160c05160e05161385b620008186000396000818161022c01528181610c790152611beb0152600081816101f0015281816112480152611bc40152600081816101b4015281816105de0152611b9a0152600081816101840152818161116e015281816116930152611b6d015261385b6000f3fe608060405234801561001057600080fd5b50600436106101365760003560e01c806379ba5097116100b2578063a6f3ab6c11610081578063df0aa9e911610066578063df0aa9e91461052d578063f2fde38b14610540578063fbca3b741461055357600080fd5b8063a6f3ab6c146104cd578063d77d5ed0146104e057600080fd5b806379ba50971461045b5780638da5cb5b146104635780639041be3d14610481578063972b4612146104ad57600080fd5b806334adf4941161010957806348a98aa4116100ee57806348a98aa4146103045780636def4ce71461033c5780637437ff9f146103db57600080fd5b806334adf494146102e95780633a019940146102fc57600080fd5b80630242cf601461013b57806306285c6914610150578063181f5a771461027f57806320487ded146102c8575b600080fd5b61014e6101493660046126e0565b610566565b005b61026960408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16815250905090565b60405161027691906127a3565b60405180910390f35b6102bb6040518060400160405280601081526020017f4f6e52616d7020312e362e302d6465760000000000000000000000000000000081525081565b6040516102769190612868565b6102db6102d6366004612893565b61057a565b604051908152602001610276565b61014e6102f73660046128e3565b610733565b61014e610a06565b610317610312366004612958565b610c31565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610276565b61039f61034a366004612991565b67ffffffffffffffff9081166000908152600660205260409020549081169168010000000000000000820460ff16916901000000000000000000900473ffffffffffffffffffffffffffffffffffffffff1690565b6040805167ffffffffffffffff9094168452911515602084015273ffffffffffffffffffffffffffffffffffffffff1690820152606001610276565b61044e604080516080810182526000808252602082018190529181018290526060810191909152506040805160808101825260025473ffffffffffffffffffffffffffffffffffffffff908116825260035481166020830152600454811692820192909252600554909116606082015290565b60405161027691906129ae565b61014e610ce6565b60005473ffffffffffffffffffffffffffffffffffffffff16610317565b61049461048f366004612991565b610de3565b60405167ffffffffffffffff9091168152602001610276565b6104c06104bb366004612991565b610e0c565b60405161027691906129f7565b61014e6104db366004612a61565b610e34565b6103176104ee366004612991565b67ffffffffffffffff166000908152600660205260409020546901000000000000000000900473ffffffffffffffffffffffffffffffffffffffff1690565b6102db61053b366004612ac8565b610e45565b61014e61054e366004612b34565b611748565b6104c0610561366004612991565b611759565b61056e61178d565b61057781611810565b50565b6040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815277ffffffffffffffff00000000000000000000000000000000608084901b16600482015260009073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690632cbc26bb90602401602060405180830381865afa158015610625573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106499190612b5f565b15610691576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024015b60405180910390fd5b6002546040517fd8694ccd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063d8694ccd906106e99086908690600401612c90565b602060405180830381865afa158015610706573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061072a9190612dd9565b90505b92915050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146107a35760055473ffffffffffffffffffffffffffffffffffffffff1633146107a3576040517f905d7d9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015610a015760008383838181106107c2576107c2612df2565b90506020028101906107d49190612e21565b6107dd90612ed2565b805167ffffffffffffffff1660009081526006602090815260409091209082015181547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff16680100000000000000009115801592909202178255919250906109545760005b8260400151518110156108fd5760008360400151828151811061086757610867612df2565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036108e65783516040517f463258ff00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610688565b6108f36001840182611987565b5050600101610842565b506040820151511561095457816000015167ffffffffffffffff167f330939f6eafe8bb516716892fe962ff19770570838686e6579dbc1cc51fc3281836040015160405161094b91906129f7565b60405180910390a25b60005b8260600151518110156109a0576109978360600151828151811061097d5761097d612df2565b6020026020010151836001016119a990919063ffffffff16565b50600101610957565b50606082015151156109f757816000015167ffffffffffffffff167fc237ec1921f855ccd5e9a5af9733f2d58943a5a8501ec5988e305d7a4d42158683606001516040516109ee91906129f7565b60405180910390a25b50506001016107a6565b505050565b600254604080517fcdc73d51000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163cdc73d5191600480830192869291908290030181865afa158015610a75573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610abb9190810190612f65565b60045490915073ffffffffffffffffffffffffffffffffffffffff1660005b8251811015610a01576000838281518110610af757610af7612df2565b60209081029190910101516040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915060009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa158015610b72573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b969190612dd9565b90508015610c2757610bbf73ffffffffffffffffffffffffffffffffffffffff831685836119cb565b8173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f508d7d183612c18fc339b42618912b9fa3239f631dd7ec0671f950200a0fa66e83604051610c1e91815260200190565b60405180910390a35b5050600101610ada565b6040517fbbe4f6db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063bbe4f6db90602401602060405180830381865afa158015610cc2573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061072a9190612ff4565b60015473ffffffffffffffffffffffffffffffffffffffff163314610d67576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610688565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b67ffffffffffffffff808216600090815260066020526040812054909161072d91166001613040565b67ffffffffffffffff8116600090815260066020526040902060609061072d90600101611a58565b610e3c61178d565b61057781611a6c565b67ffffffffffffffff8416600090815260066020526040812073ffffffffffffffffffffffffffffffffffffffff8316610eab576040517fa4ec747900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805468010000000000000000900460ff1615610f1c57610ece6001820184611c4e565b610f1c576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152602401610688565b80546901000000000000000000900473ffffffffffffffffffffffffffffffffffffffff163314610f79576040517f1c0a352900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60035473ffffffffffffffffffffffffffffffffffffffff16801561101f576040517fe0a0e50600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82169063e0a0e50690610fec908a908a90600401612c90565b600060405180830381600087803b15801561100657600080fd5b505af115801561101a573d6000803e3d6000fd5b505050505b506002546000908190819073ffffffffffffffffffffffffffffffffffffffff1663c4276bfc8a61105660808c0160608d01612b34565b8a61106460808e018e613061565b6040518663ffffffff1660e01b81526004016110849594939291906130c6565b600060405180830381865afa1580156110a1573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526110e7919081019061318e565b919450925090506110fe6080890160608a01612b34565b73ffffffffffffffffffffffffffffffffffffffff167f075a2720282fdf622141dae0b048ef90a21a7e57c134c76912d19d006b3b3f6f8460405161114591815260200190565b60405180910390a2604080516101a081019091526000610100820181815267ffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000081166101208501528c811661014085015287549293928392916101608401918a9187916111ba91166131e8565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905567ffffffffffffffff168152602001866112ba576040517fea458c0c00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8f16600482015273ffffffffffffffffffffffffffffffffffffffff8c811660248301527f0000000000000000000000000000000000000000000000000000000000000000169063ea458c0c906044016020604051808303816000875af1158015611291573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112b5919061320f565b6112bd565b60005b67ffffffffffffffff1681525081526020018873ffffffffffffffffffffffffffffffffffffffff1681526020018a80602001906112fb9190613061565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050509082525060200161133f8b80613061565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050509082525060200161138660808c018c613061565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050908252506020016113d060808c0160608d01612b34565b73ffffffffffffffffffffffffffffffffffffffff1681526020018981526020018a8060400190611401919061322c565b905067ffffffffffffffff81111561141b5761141b6125ba565b60405190808252806020026020018201604052801561147e57816020015b61146b6040518060a0016040528060608152602001606081526020016060815260200160008152602001606081525090565b8152602001906001900390816114395790505b509052905060005b61149360408b018b61322c565b9050811015611542576115196114ac60408c018c61322c565b838181106114bc576114bc612df2565b9050604002018036038101906114d29190613294565b8c6114dd8d80613061565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508e9250611c7d915050565b8260e00151828151811061152f5761152f612df2565b6020908102919091010152600101611486565b5060025460e082015160009173ffffffffffffffffffffffffffffffffffffffff169063085318f8908d9061157a60408f018f61322c565b6040518563ffffffff1660e01b815260040161159994939291906133ab565b600060405180830381865afa1580156115b6573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526115fc91908101906133e1565b905060005b8260e00151518110156116555781818151811061162057611620612df2565b60200260200101518360e00151828151811061163e5761163e612df2565b602090810291909101015160800152600101611601565b506080808301849052604080517f130ac867e79e2789f923760a88743d292acdf7002139a588206e2260f73f7321602082015267ffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811692820192909252908d16606082015230918101919091526116ef90839060a00160405160208183030381529060405280519060200120611fa3565b82515260405167ffffffffffffffff8c16907fcae3d9f68a9ed33d0a770e9bcc6fc25d4041dd6391e6cd8015546547a3c931409061172e908590613492565b60405180910390a25051519450505050505b949350505050565b61175061178d565b610577816120a3565b60606040517f9e7177c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005473ffffffffffffffffffffffffffffffffffffffff16331461180e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610688565b565b60005b815181101561198357600082828151811061183057611830612df2565b60200260200101519050600083838151811061184e5761184e612df2565b60200260200101516000015190508067ffffffffffffffff166000036118ac576040517fc35aa79d00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610688565b67ffffffffffffffff8181166000818152600660209081526040918290208682015181547fffffff0000000000000000000000000000000000000000ffffffffffffffffff8116690100000000000000000073ffffffffffffffffffffffffffffffffffffffff909316928302908117808555865192891691909816178152928301526801000000000000000090940460ff161515918101919091527fd5ad72bc37dc7a80a8b9b9df20500046fd7341adb1be2258a540466fdd7dcef59060600160405180910390a2505050806001019050611813565b5050565b600061072a8373ffffffffffffffffffffffffffffffffffffffff8416612198565b600061072a8373ffffffffffffffffffffffffffffffffffffffff84166121e7565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052610a019084906122e1565b60606000611a65836123ed565b9392505050565b805173ffffffffffffffffffffffffffffffffffffffff161580611aa85750604081015173ffffffffffffffffffffffffffffffffffffffff16155b15611adf576040517f35be3ac800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051600280547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff93841617909155602080840151600380548416918516919091179055604080850151600480548516918616919091179055606080860151600580549095169086161790935580516080810182527f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681527f00000000000000000000000000000000000000000000000000000000000000008516928101929092527f00000000000000000000000000000000000000000000000000000000000000008416828201527f00000000000000000000000000000000000000000000000000000000000000009093169181019190915290517f23a1adf8ad7fad6091a4803227af2cee848c01a7c812404cade7c25636925e3291611c439184906135e0565b60405180910390a150565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600183016020526040812054151561072a565b611caf6040518060a0016040528060608152602001606081526020016060815260200160008152602001606081525090565b8460200151600003611ced576040517f5cf0444900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611cfd858760000151610c31565b905073ffffffffffffffffffffffffffffffffffffffff81161580611dcd57506040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527faff2afbf00000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff8216906301ffc9a790602401602060405180830381865afa158015611da7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dcb9190612b5f565b155b15611e1f5785516040517fbf16aab600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610688565b60008173ffffffffffffffffffffffffffffffffffffffff16639a4575b96040518060a001604052808881526020018967ffffffffffffffff1681526020018773ffffffffffffffffffffffffffffffffffffffff1681526020018a6020015181526020018a6000015173ffffffffffffffffffffffffffffffffffffffff168152506040518263ffffffff1660e01b8152600401611ebe919061367f565b6000604051808303816000875af1158015611edd573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611f2391908101906136f5565b6040805160a0810190915273ffffffffffffffffffffffffffffffffffffffff841660c08201529091508060e0810160405160208183030381529060405281526020018260000151815260200182602001518152602001886020015181526020016040518060200160405280600081525081525092505050949350505050565b60008060001b82846020015185606001518660000151606001518760000151608001518860a001518960c00151604051602001611fe596959493929190613786565b604051602081830303815290604052805190602001208560400151805190602001208660e0015160405160200161201c91906137e7565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201206080808c0151805190840120928501989098529183019590955260608201939093529384015260a083015260c082015260e00160405160208183030381529060405280519060200120905092915050565b3373ffffffffffffffffffffffffffffffffffffffff821603612122576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610688565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60008181526001830160205260408120546121df5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561072d565b50600061072d565b600081815260018301602052604081205480156122d057600061220b6001836137fa565b855490915060009061221f906001906137fa565b905080821461228457600086600001828154811061223f5761223f612df2565b906000526020600020015490508087600001848154811061226257612262612df2565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806122955761229561380d565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061072d565b600091505061072d565b5092915050565b6000612343826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166124499092919063ffffffff16565b805190915015610a0157808060200190518101906123619190612b5f565b610a01576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610688565b60608160000180548060200260200160405190810160405280929190818152602001828054801561243d57602002820191906000526020600020905b815481526020019060010190808311612429575b50505050509050919050565b60606117408484600085856000808673ffffffffffffffffffffffffffffffffffffffff16858760405161247d919061383c565b60006040518083038185875af1925050503d80600081146124ba576040519150601f19603f3d011682016040523d82523d6000602084013e6124bf565b606091505b50915091506124d0878383876124db565b979650505050505050565b6060831561257157825160000361256a5773ffffffffffffffffffffffffffffffffffffffff85163b61256a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610688565b5081611740565b61174083838151156125865781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106889190612868565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561260c5761260c6125ba565b60405290565b6040516080810167ffffffffffffffff8111828210171561260c5761260c6125ba565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561267c5761267c6125ba565b604052919050565b600067ffffffffffffffff82111561269e5761269e6125ba565b5060051b60200190565b67ffffffffffffffff8116811461057757600080fd5b73ffffffffffffffffffffffffffffffffffffffff8116811461057757600080fd5b600060208083850312156126f357600080fd5b823567ffffffffffffffff81111561270a57600080fd5b8301601f8101851361271b57600080fd5b803561272e61272982612684565b612635565b81815260069190911b8201830190838101908783111561274d57600080fd5b928401925b828410156124d0576040848903121561276b5760008081fd5b6127736125e9565b843561277e816126a8565b81528486013561278d816126be565b8187015282526040939093019290840190612752565b6080810161072d828467ffffffffffffffff8151168252602081015173ffffffffffffffffffffffffffffffffffffffff808216602085015280604084015116604085015280606084015116606085015250505050565b60005b838110156128155781810151838201526020016127fd565b50506000910152565b600081518084526128368160208601602086016127fa565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061072a602083018461281e565b600060a0828403121561288d57600080fd5b50919050565b600080604083850312156128a657600080fd5b82356128b1816126a8565b9150602083013567ffffffffffffffff8111156128cd57600080fd5b6128d98582860161287b565b9150509250929050565b600080602083850312156128f657600080fd5b823567ffffffffffffffff8082111561290e57600080fd5b818501915085601f83011261292257600080fd5b81358181111561293157600080fd5b8660208260051b850101111561294657600080fd5b60209290920196919550909350505050565b6000806040838503121561296b57600080fd5b8235612976816126a8565b91506020830135612986816126be565b809150509250929050565b6000602082840312156129a357600080fd5b8135611a65816126a8565b6080810161072d8284805173ffffffffffffffffffffffffffffffffffffffff908116835260208083015182169084015260408083015182169084015260609182015116910152565b6020808252825182820181905260009190848201906040850190845b81811015612a4557835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101612a13565b50909695505050505050565b8035612a5c816126be565b919050565b600060808284031215612a7357600080fd5b612a7b612612565b8235612a86816126be565b81526020830135612a96816126be565b60208201526040830135612aa9816126be565b60408201526060830135612abc816126be565b60608201529392505050565b60008060008060808587031215612ade57600080fd5b8435612ae9816126a8565b9350602085013567ffffffffffffffff811115612b0557600080fd5b612b118782880161287b565b935050604085013591506060850135612b29816126be565b939692955090935050565b600060208284031215612b4657600080fd5b8135611a65816126be565b801515811461057757600080fd5b600060208284031215612b7157600080fd5b8151611a6581612b51565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112612bb157600080fd5b830160208101925035905067ffffffffffffffff811115612bd157600080fd5b803603821315612be057600080fd5b9250929050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b8183526000602080850194508260005b85811015612c85578135612c53816126be565b73ffffffffffffffffffffffffffffffffffffffff168752818301358388015260409687019690910190600101612c40565b509495945050505050565b600067ffffffffffffffff808516835260406020840152612cb18485612b7c565b60a06040860152612cc660e086018284612be7565b915050612cd66020860186612b7c565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc080878503016060880152612d0c848385612be7565b9350604088013592507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1883603018312612d4557600080fd5b60209288019283019235915084821115612d5e57600080fd5b8160061b3603831315612d7057600080fd5b80878503016080880152612d85848385612c30565b9450612d9360608901612a51565b73ffffffffffffffffffffffffffffffffffffffff811660a08901529350612dbe6080890189612b7c565b94509250808786030160c088015250506124d0838383612be7565b600060208284031215612deb57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81833603018112612e5557600080fd5b9190910192915050565b600082601f830112612e7057600080fd5b81356020612e8061272983612684565b8083825260208201915060208460051b870101935086841115612ea257600080fd5b602086015b84811015612ec7578035612eba816126be565b8352918301918301612ea7565b509695505050505050565b600060808236031215612ee457600080fd5b612eec612612565b8235612ef7816126a8565b81526020830135612f0781612b51565b6020820152604083013567ffffffffffffffff80821115612f2757600080fd5b612f3336838701612e5f565b60408401526060850135915080821115612f4c57600080fd5b50612f5936828601612e5f565b60608301525092915050565b60006020808385031215612f7857600080fd5b825167ffffffffffffffff811115612f8f57600080fd5b8301601f81018513612fa057600080fd5b8051612fae61272982612684565b81815260059190911b82018301908381019087831115612fcd57600080fd5b928401925b828410156124d0578351612fe5816126be565b82529284019290840190612fd2565b60006020828403121561300657600080fd5b8151611a65816126be565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b67ffffffffffffffff8181168382160190808211156122da576122da613011565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261309657600080fd5b83018035915067ffffffffffffffff8211156130b157600080fd5b602001915036819003821315612be057600080fd5b67ffffffffffffffff8616815273ffffffffffffffffffffffffffffffffffffffff851660208201528360408201526080606082015260006124d0608083018486612be7565b600082601f83011261311d57600080fd5b815167ffffffffffffffff811115613137576131376125ba565b61316860207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601612635565b81815284602083860101111561317d57600080fd5b6117408260208301602087016127fa565b6000806000606084860312156131a357600080fd5b8351925060208401516131b581612b51565b604085015190925067ffffffffffffffff8111156131d257600080fd5b6131de8682870161310c565b9150509250925092565b600067ffffffffffffffff80831681810361320557613205613011565b6001019392505050565b60006020828403121561322157600080fd5b8151611a65816126a8565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261326157600080fd5b83018035915067ffffffffffffffff82111561327c57600080fd5b6020019150600681901b3603821315612be057600080fd5b6000604082840312156132a657600080fd5b6132ae6125e9565b82356132b9816126be565b81526020928301359281019290925250919050565b600082825180855260208086019550808260051b84010181860160005b8481101561339e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018952815160a0815181865261332f8287018261281e565b9150508582015185820387870152613347828261281e565b91505060408083015186830382880152613361838261281e565b9250505060608083015181870152506080808301519250858203818701525061338a818361281e565b9a86019a94505050908301906001016132eb565b5090979650505050505050565b67ffffffffffffffff851681526060602082015260006133ce60608301866132ce565b82810360408401526124d0818587612c30565b600060208083850312156133f457600080fd5b825167ffffffffffffffff8082111561340c57600080fd5b818501915085601f83011261342057600080fd5b815161342e61272982612684565b81815260059190911b8301840190848101908883111561344d57600080fd5b8585015b83811015613485578051858111156134695760008081fd5b6134778b89838a010161310c565b845250918601918601613451565b5098975050505050505050565b602081526134e360208201835180518252602081015167ffffffffffffffff808216602085015280604084015116604085015280606084015116606085015280608084015116608085015250505050565b6000602083015161350c60c084018273ffffffffffffffffffffffffffffffffffffffff169052565b5060408301516101808060e08501526135296101a085018361281e565b915060608501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08086850301610100870152613566848361281e565b9350608087015191508086850301610120870152613584848361281e565b935060a087015191506135b061014087018373ffffffffffffffffffffffffffffffffffffffff169052565b60c087015161016087015260e08701519150808685030183870152506135d683826132ce565b9695505050505050565b6101008101613638828567ffffffffffffffff8151168252602081015173ffffffffffffffffffffffffffffffffffffffff808216602085015280604084015116604085015280606084015116606085015250505050565b825173ffffffffffffffffffffffffffffffffffffffff90811660808401526020840151811660a08401526040840151811660c084015260608401511660e0830152611a65565b602081526000825160a0602084015261369b60c084018261281e565b905067ffffffffffffffff6020850151166040840152604084015173ffffffffffffffffffffffffffffffffffffffff8082166060860152606086015160808601528060808701511660a086015250508091505092915050565b60006020828403121561370757600080fd5b815167ffffffffffffffff8082111561371f57600080fd5b908301906040828603121561373357600080fd5b61373b6125e9565b82518281111561374a57600080fd5b6137568782860161310c565b82525060208301518281111561376b57600080fd5b6137778782860161310c565b60208301525095945050505050565b600073ffffffffffffffffffffffffffffffffffffffff808916835260c060208401526137b660c084018961281e565b67ffffffffffffffff97881660408501529590961660608301525091909316608082015260a0019190915292915050565b60208152600061072a60208301846132ce565b8181038181111561072d5761072d613011565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b60008251612e558184602087016127fa56fea164736f6c6343000818000a", + Bin: "0x6101006040523480156200001257600080fd5b506040516200402938038062004029833981016040819052620000359162000665565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf8162000186565b505083516001600160401b031615905080620000e6575060208301516001600160a01b0316155b80620000fd575060408301516001600160a01b0316155b8062000114575060608301516001600160a01b0316155b1562000133576040516306b7c75960e31b815260040160405180910390fd5b82516001600160401b031660805260208301516001600160a01b0390811660a0526040840151811660c05260608401511660e052620001728262000231565b6200017d8162000390565b5050506200079f565b336001600160a01b03821603620001e05760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b0316158062000254575060408101516001600160a01b0316155b1562000273576040516306b7c75960e31b815260040160405180910390fd5b8051600280546001600160a01b03199081166001600160a01b0393841617909155602080840180516003805485169186169190911790556040808601805160048054871691881691909117905560608088018051600580549098169089161790965582516080808201855280516001600160401b031680835260a080518b16848a0190815260c080518d16868a0190815260e080518f169789019788528a5195865292518e169b85019b909b5299518c169783019790975292518a169381019390935289518916908301529351871693810193909352518516928201929092529151909216918101919091527f23a1adf8ad7fad6091a4803227af2cee848c01a7c812404cade7c25636925e32906101000160405180910390a150565b60005b8151811015620004cf576000828281518110620003b457620003b462000789565b602002602001015190506000838381518110620003d557620003d562000789565b6020026020010151600001519050806001600160401b03166000036200041a5760405163c35aa79d60e01b81526001600160401b038216600482015260240162000083565b6001600160401b03818116600081815260066020908152604091829020868201518154600160481b600160e81b0319811669010000000000000000006001600160a01b03909316928302908117808555865192891691909816178152928301526801000000000000000090940460ff161515918101919091527fd5ad72bc37dc7a80a8b9b9df20500046fd7341adb1be2258a540466fdd7dcef59060600160405180910390a250505080600101905062000393565b5050565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b03811182821017156200050e576200050e620004d3565b60405290565b604080519081016001600160401b03811182821017156200050e576200050e620004d3565b604051601f8201601f191681016001600160401b0381118282101715620005645762000564620004d3565b604052919050565b80516001600160401b03811681146200058457600080fd5b919050565b6001600160a01b03811681146200059f57600080fd5b50565b600082601f830112620005b457600080fd5b815160206001600160401b03821115620005d257620005d2620004d3565b620005e2818360051b0162000539565b82815260069290921b840181019181810190868411156200060257600080fd5b8286015b848110156200065a5760408189031215620006215760008081fd5b6200062b62000514565b62000636826200056c565b815284820151620006478162000589565b8186015283529183019160400162000606565b509695505050505050565b60008060008385036101208112156200067d57600080fd5b60808112156200068c57600080fd5b62000696620004e9565b620006a1866200056c565b81526020860151620006b38162000589565b60208201526040860151620006c88162000589565b60408201526060860151620006dd8162000589565b606082015293506080607f1982011215620006f757600080fd5b5062000702620004e9565b6080850151620007128162000589565b815260a0850151620007248162000589565b602082015260c0850151620007398162000589565b604082015260e08501516200074e8162000589565b60608201526101008501519092506001600160401b038111156200077157600080fd5b6200077f86828701620005a2565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b60805160a05160c05160e051613811620008186000396000818161022c01528181610c790152611ba10152600081816101f0015281816112480152611b7a0152600081816101b4015281816105de0152611b500152600081816101840152818161116e0152818161164b0152611b2301526138116000f3fe608060405234801561001057600080fd5b50600436106101365760003560e01c806379ba5097116100b2578063a6f3ab6c11610081578063df0aa9e911610066578063df0aa9e91461052d578063f2fde38b14610540578063fbca3b741461055357600080fd5b8063a6f3ab6c146104cd578063d77d5ed0146104e057600080fd5b806379ba50971461045b5780638da5cb5b146104635780639041be3d14610481578063972b4612146104ad57600080fd5b806334adf4941161010957806348a98aa4116100ee57806348a98aa4146103045780636def4ce71461033c5780637437ff9f146103db57600080fd5b806334adf494146102e95780633a019940146102fc57600080fd5b80630242cf601461013b57806306285c6914610150578063181f5a771461027f57806320487ded146102c8575b600080fd5b61014e610149366004612696565b610566565b005b61026960408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16815250905090565b6040516102769190612759565b60405180910390f35b6102bb6040518060400160405280601081526020017f4f6e52616d7020312e362e302d6465760000000000000000000000000000000081525081565b604051610276919061281e565b6102db6102d6366004612849565b61057a565b604051908152602001610276565b61014e6102f7366004612899565b610733565b61014e610a06565b61031761031236600461290e565b610c31565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610276565b61039f61034a366004612947565b67ffffffffffffffff9081166000908152600660205260409020549081169168010000000000000000820460ff16916901000000000000000000900473ffffffffffffffffffffffffffffffffffffffff1690565b6040805167ffffffffffffffff9094168452911515602084015273ffffffffffffffffffffffffffffffffffffffff1690820152606001610276565b61044e604080516080810182526000808252602082018190529181018290526060810191909152506040805160808101825260025473ffffffffffffffffffffffffffffffffffffffff908116825260035481166020830152600454811692820192909252600554909116606082015290565b6040516102769190612964565b61014e610ce6565b60005473ffffffffffffffffffffffffffffffffffffffff16610317565b61049461048f366004612947565b610de3565b60405167ffffffffffffffff9091168152602001610276565b6104c06104bb366004612947565b610e0c565b60405161027691906129ad565b61014e6104db366004612a17565b610e34565b6103176104ee366004612947565b67ffffffffffffffff166000908152600660205260409020546901000000000000000000900473ffffffffffffffffffffffffffffffffffffffff1690565b6102db61053b366004612a7e565b610e45565b61014e61054e366004612aea565b6116fe565b6104c0610561366004612947565b61170f565b61056e611743565b610577816117c6565b50565b6040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815277ffffffffffffffff00000000000000000000000000000000608084901b16600482015260009073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690632cbc26bb90602401602060405180830381865afa158015610625573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106499190612b15565b15610691576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024015b60405180910390fd5b6002546040517fd8694ccd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063d8694ccd906106e99086908690600401612c46565b602060405180830381865afa158015610706573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061072a9190612d8f565b90505b92915050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146107a35760055473ffffffffffffffffffffffffffffffffffffffff1633146107a3576040517f905d7d9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015610a015760008383838181106107c2576107c2612da8565b90506020028101906107d49190612dd7565b6107dd90612e88565b805167ffffffffffffffff1660009081526006602090815260409091209082015181547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff16680100000000000000009115801592909202178255919250906109545760005b8260400151518110156108fd5760008360400151828151811061086757610867612da8565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036108e65783516040517f463258ff00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610688565b6108f3600184018261193d565b5050600101610842565b506040820151511561095457816000015167ffffffffffffffff167f330939f6eafe8bb516716892fe962ff19770570838686e6579dbc1cc51fc3281836040015160405161094b91906129ad565b60405180910390a25b60005b8260600151518110156109a0576109978360600151828151811061097d5761097d612da8565b60200260200101518360010161195f90919063ffffffff16565b50600101610957565b50606082015151156109f757816000015167ffffffffffffffff167fc237ec1921f855ccd5e9a5af9733f2d58943a5a8501ec5988e305d7a4d42158683606001516040516109ee91906129ad565b60405180910390a25b50506001016107a6565b505050565b600254604080517fcdc73d51000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163cdc73d5191600480830192869291908290030181865afa158015610a75573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610abb9190810190612f1b565b60045490915073ffffffffffffffffffffffffffffffffffffffff1660005b8251811015610a01576000838281518110610af757610af7612da8565b60209081029190910101516040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915060009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa158015610b72573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b969190612d8f565b90508015610c2757610bbf73ffffffffffffffffffffffffffffffffffffffff83168583611981565b8173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f508d7d183612c18fc339b42618912b9fa3239f631dd7ec0671f950200a0fa66e83604051610c1e91815260200190565b60405180910390a35b5050600101610ada565b6040517fbbe4f6db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063bbe4f6db90602401602060405180830381865afa158015610cc2573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061072a9190612faa565b60015473ffffffffffffffffffffffffffffffffffffffff163314610d67576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610688565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b67ffffffffffffffff808216600090815260066020526040812054909161072d91166001612ff6565b67ffffffffffffffff8116600090815260066020526040902060609061072d90600101611a0e565b610e3c611743565b61057781611a22565b67ffffffffffffffff8416600090815260066020526040812073ffffffffffffffffffffffffffffffffffffffff8316610eab576040517fa4ec747900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805468010000000000000000900460ff1615610f1c57610ece6001820184611c04565b610f1c576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152602401610688565b80546901000000000000000000900473ffffffffffffffffffffffffffffffffffffffff163314610f79576040517f1c0a352900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60035473ffffffffffffffffffffffffffffffffffffffff16801561101f576040517fe0a0e50600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82169063e0a0e50690610fec908a908a90600401612c46565b600060405180830381600087803b15801561100657600080fd5b505af115801561101a573d6000803e3d6000fd5b505050505b506002546000908190819073ffffffffffffffffffffffffffffffffffffffff1663c4276bfc8a61105660808c0160608d01612aea565b8a61106460808e018e613017565b6040518663ffffffff1660e01b815260040161108495949392919061307c565b600060405180830381865afa1580156110a1573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526110e79190810190613144565b919450925090506110fe6080890160608a01612aea565b73ffffffffffffffffffffffffffffffffffffffff167f075a2720282fdf622141dae0b048ef90a21a7e57c134c76912d19d006b3b3f6f8460405161114591815260200190565b60405180910390a2604080516101a081019091526000610100820181815267ffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000081166101208501528c811661014085015287549293928392916101608401918a9187916111ba911661319e565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905567ffffffffffffffff168152602001866112ba576040517fea458c0c00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8f16600482015273ffffffffffffffffffffffffffffffffffffffff8c811660248301527f0000000000000000000000000000000000000000000000000000000000000000169063ea458c0c906044016020604051808303816000875af1158015611291573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112b591906131c5565b6112bd565b60005b67ffffffffffffffff1681525081526020018873ffffffffffffffffffffffffffffffffffffffff1681526020018a80602001906112fb9190613017565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050509082525060200161133f8b80613017565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050908252506020810184905260400161139060808c0160608d01612aea565b73ffffffffffffffffffffffffffffffffffffffff1681526020018981526020018a80604001906113c191906131e2565b905067ffffffffffffffff8111156113db576113db612570565b60405190808252806020026020018201604052801561143e57816020015b61142b6040518060a0016040528060608152602001606081526020016060815260200160008152602001606081525090565b8152602001906001900390816113f95790505b509052905060005b61145360408b018b6131e2565b9050811015611502576114d961146c60408c018c6131e2565b8381811061147c5761147c612da8565b905060400201803603810190611492919061324a565b8c61149d8d80613017565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508e9250611c33915050565b8260e0015182815181106114ef576114ef612da8565b6020908102919091010152600101611446565b5060025460e082015160009173ffffffffffffffffffffffffffffffffffffffff169063085318f8908d9061153a60408f018f6131e2565b6040518563ffffffff1660e01b81526004016115599493929190613361565b600060405180830381865afa158015611576573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526115bc9190810190613397565b905060005b8260e0015151811015611615578181815181106115e0576115e0612da8565b60200260200101518360e0015182815181106115fe576115fe612da8565b6020908102919091010151608001526001016115c1565b50604080517f130ac867e79e2789f923760a88743d292acdf7002139a588206e2260f73f7321602082015267ffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811692820192909252908c1660608201523060808201526116a590839060a00160405160208183030381529060405280519060200120611f59565b82515260405167ffffffffffffffff8c16907fcae3d9f68a9ed33d0a770e9bcc6fc25d4041dd6391e6cd8015546547a3c93140906116e4908590613448565b60405180910390a25051519450505050505b949350505050565b611706611743565b61057781612059565b60606040517f9e7177c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005473ffffffffffffffffffffffffffffffffffffffff1633146117c4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610688565b565b60005b81518110156119395760008282815181106117e6576117e6612da8565b60200260200101519050600083838151811061180457611804612da8565b60200260200101516000015190508067ffffffffffffffff16600003611862576040517fc35aa79d00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610688565b67ffffffffffffffff8181166000818152600660209081526040918290208682015181547fffffff0000000000000000000000000000000000000000ffffffffffffffffff8116690100000000000000000073ffffffffffffffffffffffffffffffffffffffff909316928302908117808555865192891691909816178152928301526801000000000000000090940460ff161515918101919091527fd5ad72bc37dc7a80a8b9b9df20500046fd7341adb1be2258a540466fdd7dcef59060600160405180910390a25050508060010190506117c9565b5050565b600061072a8373ffffffffffffffffffffffffffffffffffffffff841661214e565b600061072a8373ffffffffffffffffffffffffffffffffffffffff841661219d565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052610a01908490612297565b60606000611a1b836123a3565b9392505050565b805173ffffffffffffffffffffffffffffffffffffffff161580611a5e5750604081015173ffffffffffffffffffffffffffffffffffffffff16155b15611a95576040517f35be3ac800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051600280547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff93841617909155602080840151600380548416918516919091179055604080850151600480548516918616919091179055606080860151600580549095169086161790935580516080810182527f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681527f00000000000000000000000000000000000000000000000000000000000000008516928101929092527f00000000000000000000000000000000000000000000000000000000000000008416828201527f00000000000000000000000000000000000000000000000000000000000000009093169181019190915290517f23a1adf8ad7fad6091a4803227af2cee848c01a7c812404cade7c25636925e3291611bf9918490613596565b60405180910390a150565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600183016020526040812054151561072a565b611c656040518060a0016040528060608152602001606081526020016060815260200160008152602001606081525090565b8460200151600003611ca3576040517f5cf0444900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611cb3858760000151610c31565b905073ffffffffffffffffffffffffffffffffffffffff81161580611d8357506040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527faff2afbf00000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff8216906301ffc9a790602401602060405180830381865afa158015611d5d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d819190612b15565b155b15611dd55785516040517fbf16aab600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610688565b60008173ffffffffffffffffffffffffffffffffffffffff16639a4575b96040518060a001604052808881526020018967ffffffffffffffff1681526020018773ffffffffffffffffffffffffffffffffffffffff1681526020018a6020015181526020018a6000015173ffffffffffffffffffffffffffffffffffffffff168152506040518263ffffffff1660e01b8152600401611e749190613635565b6000604051808303816000875af1158015611e93573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611ed991908101906136ab565b6040805160a0810190915273ffffffffffffffffffffffffffffffffffffffff841660c08201529091508060e0810160405160208183030381529060405281526020018260000151815260200182602001518152602001886020015181526020016040518060200160405280600081525081525092505050949350505050565b60008060001b82846020015185606001518660000151606001518760000151608001518860a001518960c00151604051602001611f9b9695949392919061373c565b604051602081830303815290604052805190602001208560400151805190602001208660e00151604051602001611fd2919061379d565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201206080808c0151805190840120928501989098529183019590955260608201939093529384015260a083015260c082015260e00160405160208183030381529060405280519060200120905092915050565b3373ffffffffffffffffffffffffffffffffffffffff8216036120d8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610688565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60008181526001830160205260408120546121955750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561072d565b50600061072d565b600081815260018301602052604081205480156122865760006121c16001836137b0565b85549091506000906121d5906001906137b0565b905080821461223a5760008660000182815481106121f5576121f5612da8565b906000526020600020015490508087600001848154811061221857612218612da8565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061224b5761224b6137c3565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061072d565b600091505061072d565b5092915050565b60006122f9826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166123ff9092919063ffffffff16565b805190915015610a0157808060200190518101906123179190612b15565b610a01576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610688565b6060816000018054806020026020016040519081016040528092919081815260200182805480156123f357602002820191906000526020600020905b8154815260200190600101908083116123df575b50505050509050919050565b60606116f68484600085856000808673ffffffffffffffffffffffffffffffffffffffff16858760405161243391906137f2565b60006040518083038185875af1925050503d8060008114612470576040519150601f19603f3d011682016040523d82523d6000602084013e612475565b606091505b509150915061248687838387612491565b979650505050505050565b606083156125275782516000036125205773ffffffffffffffffffffffffffffffffffffffff85163b612520576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610688565b50816116f6565b6116f6838381511561253c5781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610688919061281e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff811182821017156125c2576125c2612570565b60405290565b6040516080810167ffffffffffffffff811182821017156125c2576125c2612570565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561263257612632612570565b604052919050565b600067ffffffffffffffff82111561265457612654612570565b5060051b60200190565b67ffffffffffffffff8116811461057757600080fd5b73ffffffffffffffffffffffffffffffffffffffff8116811461057757600080fd5b600060208083850312156126a957600080fd5b823567ffffffffffffffff8111156126c057600080fd5b8301601f810185136126d157600080fd5b80356126e46126df8261263a565b6125eb565b81815260069190911b8201830190838101908783111561270357600080fd5b928401925b8284101561248657604084890312156127215760008081fd5b61272961259f565b84356127348161265e565b81528486013561274381612674565b8187015282526040939093019290840190612708565b6080810161072d828467ffffffffffffffff8151168252602081015173ffffffffffffffffffffffffffffffffffffffff808216602085015280604084015116604085015280606084015116606085015250505050565b60005b838110156127cb5781810151838201526020016127b3565b50506000910152565b600081518084526127ec8160208601602086016127b0565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061072a60208301846127d4565b600060a0828403121561284357600080fd5b50919050565b6000806040838503121561285c57600080fd5b82356128678161265e565b9150602083013567ffffffffffffffff81111561288357600080fd5b61288f85828601612831565b9150509250929050565b600080602083850312156128ac57600080fd5b823567ffffffffffffffff808211156128c457600080fd5b818501915085601f8301126128d857600080fd5b8135818111156128e757600080fd5b8660208260051b85010111156128fc57600080fd5b60209290920196919550909350505050565b6000806040838503121561292157600080fd5b823561292c8161265e565b9150602083013561293c81612674565b809150509250929050565b60006020828403121561295957600080fd5b8135611a1b8161265e565b6080810161072d8284805173ffffffffffffffffffffffffffffffffffffffff908116835260208083015182169084015260408083015182169084015260609182015116910152565b6020808252825182820181905260009190848201906040850190845b818110156129fb57835173ffffffffffffffffffffffffffffffffffffffff16835292840192918401916001016129c9565b50909695505050505050565b8035612a1281612674565b919050565b600060808284031215612a2957600080fd5b612a316125c8565b8235612a3c81612674565b81526020830135612a4c81612674565b60208201526040830135612a5f81612674565b60408201526060830135612a7281612674565b60608201529392505050565b60008060008060808587031215612a9457600080fd5b8435612a9f8161265e565b9350602085013567ffffffffffffffff811115612abb57600080fd5b612ac787828801612831565b935050604085013591506060850135612adf81612674565b939692955090935050565b600060208284031215612afc57600080fd5b8135611a1b81612674565b801515811461057757600080fd5b600060208284031215612b2757600080fd5b8151611a1b81612b07565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112612b6757600080fd5b830160208101925035905067ffffffffffffffff811115612b8757600080fd5b803603821315612b9657600080fd5b9250929050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b8183526000602080850194508260005b85811015612c3b578135612c0981612674565b73ffffffffffffffffffffffffffffffffffffffff168752818301358388015260409687019690910190600101612bf6565b509495945050505050565b600067ffffffffffffffff808516835260406020840152612c678485612b32565b60a06040860152612c7c60e086018284612b9d565b915050612c8c6020860186612b32565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc080878503016060880152612cc2848385612b9d565b9350604088013592507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1883603018312612cfb57600080fd5b60209288019283019235915084821115612d1457600080fd5b8160061b3603831315612d2657600080fd5b80878503016080880152612d3b848385612be6565b9450612d4960608901612a07565b73ffffffffffffffffffffffffffffffffffffffff811660a08901529350612d746080890189612b32565b94509250808786030160c08801525050612486838383612b9d565b600060208284031215612da157600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81833603018112612e0b57600080fd5b9190910192915050565b600082601f830112612e2657600080fd5b81356020612e366126df8361263a565b8083825260208201915060208460051b870101935086841115612e5857600080fd5b602086015b84811015612e7d578035612e7081612674565b8352918301918301612e5d565b509695505050505050565b600060808236031215612e9a57600080fd5b612ea26125c8565b8235612ead8161265e565b81526020830135612ebd81612b07565b6020820152604083013567ffffffffffffffff80821115612edd57600080fd5b612ee936838701612e15565b60408401526060850135915080821115612f0257600080fd5b50612f0f36828601612e15565b60608301525092915050565b60006020808385031215612f2e57600080fd5b825167ffffffffffffffff811115612f4557600080fd5b8301601f81018513612f5657600080fd5b8051612f646126df8261263a565b81815260059190911b82018301908381019087831115612f8357600080fd5b928401925b82841015612486578351612f9b81612674565b82529284019290840190612f88565b600060208284031215612fbc57600080fd5b8151611a1b81612674565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b67ffffffffffffffff81811683821601908082111561229057612290612fc7565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261304c57600080fd5b83018035915067ffffffffffffffff82111561306757600080fd5b602001915036819003821315612b9657600080fd5b67ffffffffffffffff8616815273ffffffffffffffffffffffffffffffffffffffff85166020820152836040820152608060608201526000612486608083018486612b9d565b600082601f8301126130d357600080fd5b815167ffffffffffffffff8111156130ed576130ed612570565b61311e60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016125eb565b81815284602083860101111561313357600080fd5b6116f68260208301602087016127b0565b60008060006060848603121561315957600080fd5b83519250602084015161316b81612b07565b604085015190925067ffffffffffffffff81111561318857600080fd5b613194868287016130c2565b9150509250925092565b600067ffffffffffffffff8083168181036131bb576131bb612fc7565b6001019392505050565b6000602082840312156131d757600080fd5b8151611a1b8161265e565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261321757600080fd5b83018035915067ffffffffffffffff82111561323257600080fd5b6020019150600681901b3603821315612b9657600080fd5b60006040828403121561325c57600080fd5b61326461259f565b823561326f81612674565b81526020928301359281019290925250919050565b600082825180855260208086019550808260051b84010181860160005b84811015613354577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018952815160a081518186526132e5828701826127d4565b91505085820151858203878701526132fd82826127d4565b9150506040808301518683038288015261331783826127d4565b9250505060608083015181870152506080808301519250858203818701525061334081836127d4565b9a86019a94505050908301906001016132a1565b5090979650505050505050565b67ffffffffffffffff851681526060602082015260006133846060830186613284565b8281036040840152612486818587612be6565b600060208083850312156133aa57600080fd5b825167ffffffffffffffff808211156133c257600080fd5b818501915085601f8301126133d657600080fd5b81516133e46126df8261263a565b81815260059190911b8301840190848101908883111561340357600080fd5b8585015b8381101561343b5780518581111561341f5760008081fd5b61342d8b89838a01016130c2565b845250918601918601613407565b5098975050505050505050565b6020815261349960208201835180518252602081015167ffffffffffffffff808216602085015280604084015116604085015280606084015116606085015280608084015116608085015250505050565b600060208301516134c260c084018273ffffffffffffffffffffffffffffffffffffffff169052565b5060408301516101808060e08501526134df6101a08501836127d4565b915060608501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0808685030161010087015261351c84836127d4565b935060808701519150808685030161012087015261353a84836127d4565b935060a0870151915061356661014087018373ffffffffffffffffffffffffffffffffffffffff169052565b60c087015161016087015260e087015191508086850301838701525061358c8382613284565b9695505050505050565b61010081016135ee828567ffffffffffffffff8151168252602081015173ffffffffffffffffffffffffffffffffffffffff808216602085015280604084015116604085015280606084015116606085015250505050565b825173ffffffffffffffffffffffffffffffffffffffff90811660808401526020840151811660a08401526040840151811660c084015260608401511660e0830152611a1b565b602081526000825160a0602084015261365160c08401826127d4565b905067ffffffffffffffff6020850151166040840152604084015173ffffffffffffffffffffffffffffffffffffffff8082166060860152606086015160808601528060808701511660a086015250508091505092915050565b6000602082840312156136bd57600080fd5b815167ffffffffffffffff808211156136d557600080fd5b90830190604082860312156136e957600080fd5b6136f161259f565b82518281111561370057600080fd5b61370c878286016130c2565b82525060208301518281111561372157600080fd5b61372d878286016130c2565b60208301525095945050505050565b600073ffffffffffffffffffffffffffffffffffffffff808916835260c0602084015261376c60c08401896127d4565b67ffffffffffffffff97881660408501529590961660608301525091909316608082015260a0019190915292915050565b60208152600061072a6020830184613284565b8181038181111561072d5761072d612fc7565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b60008251612e0b8184602087016127b056fea164736f6c6343000818000a", } var OnRampABI = OnRampMetaData.ABI diff --git a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt index afbdd51c79..35daa791c3 100644 --- a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -4,14 +4,14 @@ burn_mint_token_pool: ../../../contracts/solc/v0.8.24/BurnMintTokenPool/BurnMint burn_mint_token_pool_and_proxy: ../../../contracts/solc/v0.8.24/BurnMintTokenPoolAndProxy/BurnMintTokenPoolAndProxy.abi ../../../contracts/solc/v0.8.24/BurnMintTokenPoolAndProxy/BurnMintTokenPoolAndProxy.bin 717c079d5d13300cf3c3ee871c6e5bf9af904411f204fb081a9f3b263cca1391 burn_with_from_mint_token_pool: ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.abi ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.bin 6333d0314d0bd29e75ea5e05fe62a4516ade0c6db91c30b6f93645035db52ed8 burn_with_from_mint_token_pool_and_proxy: ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPoolAndProxy/BurnWithFromMintTokenPoolAndProxy.abi ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPoolAndProxy/BurnWithFromMintTokenPoolAndProxy.bin 08ed1235dda921ce8841b26aa18d0c0f36db4884779dd7670857159801b6d597 -ccip_config: ../../../contracts/solc/v0.8.24/CCIPConfig/CCIPConfig.abi ../../../contracts/solc/v0.8.24/CCIPConfig/CCIPConfig.bin 213d4adc8634671aea16fb4207989375b1aac919b04d608f4767c29592affbf5 +ccip_config: ../../../contracts/solc/v0.8.24/CCIPConfig/CCIPConfig.abi ../../../contracts/solc/v0.8.24/CCIPConfig/CCIPConfig.bin 3b89dd119dc7a0719bf70339e80e820a8c0d615e7b257631ed12e2e6a95ea19c ccip_reader_tester: ../../../contracts/solc/v0.8.24/CCIPReaderTester/CCIPReaderTester.abi ../../../contracts/solc/v0.8.24/CCIPReaderTester/CCIPReaderTester.bin d8d70fe111bacc7702c7c263f8c4733dcb2fff77e52c9f60c30d303731bc97c1 commit_store: ../../../contracts/solc/v0.8.24/CommitStore/CommitStore.abi ../../../contracts/solc/v0.8.24/CommitStore/CommitStore.bin 274d87db70b643e00ab0a7e7845bb4b791f3b613bfc87708d33fc5a8369e2a41 commit_store_helper: ../../../contracts/solc/v0.8.24/CommitStoreHelper/CommitStoreHelper.abi ../../../contracts/solc/v0.8.24/CommitStoreHelper/CommitStoreHelper.bin f7128dcc2ee6dbcbc976288abcc16970ffb19b59412c5202ef6b259d2007f801 ether_sender_receiver: ../../../contracts/solc/v0.8.24/EtherSenderReceiver/EtherSenderReceiver.abi ../../../contracts/solc/v0.8.24/EtherSenderReceiver/EtherSenderReceiver.bin 09510a3f773f108a3c231e8d202835c845ded862d071ec54c4f89c12d868b8de evm_2_evm_offramp: ../../../contracts/solc/v0.8.24/EVM2EVMOffRamp/EVM2EVMOffRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMOffRamp/EVM2EVMOffRamp.bin b0d77babbe635cd6ba04c2af049badc9e9d28a4b6ed6bb75f830ad902a618beb evm_2_evm_onramp: ../../../contracts/solc/v0.8.24/EVM2EVMOnRamp/EVM2EVMOnRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMOnRamp/EVM2EVMOnRamp.bin 5c02c2b167946b3467636ff2bb58594cb4652fc63d8bdfee2488ed562e2a3e50 -fee_quoter: ../../../contracts/solc/v0.8.24/FeeQuoter/FeeQuoter.abi ../../../contracts/solc/v0.8.24/FeeQuoter/FeeQuoter.bin 920b7a293165fe8306fbed0cafd866bafc5943e8759486f7803bfbbd40309b6b +fee_quoter: ../../../contracts/solc/v0.8.24/FeeQuoter/FeeQuoter.abi ../../../contracts/solc/v0.8.24/FeeQuoter/FeeQuoter.bin 7fcb78bfc6f050c9d3bd3396a29fa58c6eceec3be6f9f6e807212e816f881a4c lock_release_token_pool: ../../../contracts/solc/v0.8.24/LockReleaseTokenPool/LockReleaseTokenPool.abi ../../../contracts/solc/v0.8.24/LockReleaseTokenPool/LockReleaseTokenPool.bin e6a8ec9e8faccb1da7d90e0f702ed72975964f97dc3222b54cfcca0a0ba3fea2 lock_release_token_pool_and_proxy: ../../../contracts/solc/v0.8.24/LockReleaseTokenPoolAndProxy/LockReleaseTokenPoolAndProxy.abi ../../../contracts/solc/v0.8.24/LockReleaseTokenPoolAndProxy/LockReleaseTokenPoolAndProxy.bin e632b08be0fbd1d013e8b3a9d75293d0d532b83071c531ff2be1deec1fa48ec1 maybe_revert_message_receiver: ../../../contracts/solc/v0.8.24/MaybeRevertMessageReceiver/MaybeRevertMessageReceiver.abi ../../../contracts/solc/v0.8.24/MaybeRevertMessageReceiver/MaybeRevertMessageReceiver.bin d73956c26232ebcc4a5444429fa99cbefed960e323be9b5a24925885c2e477d5 @@ -20,11 +20,11 @@ mock_usdc_token_messenger: ../../../contracts/solc/v0.8.24/MockE2EUSDCTokenMesse mock_usdc_token_transmitter: ../../../contracts/solc/v0.8.24/MockE2EUSDCTransmitter/MockE2EUSDCTransmitter.abi ../../../contracts/solc/v0.8.24/MockE2EUSDCTransmitter/MockE2EUSDCTransmitter.bin be0dbc3e475741ea0b7a54ec2b935a321b428baa9f4ce18180a87fb38bb87de2 mock_v3_aggregator_contract: ../../../contracts/solc/v0.8.24/MockV3Aggregator/MockV3Aggregator.abi ../../../contracts/solc/v0.8.24/MockV3Aggregator/MockV3Aggregator.bin 518e19efa2ff52b0fefd8e597b05765317ee7638189bfe34ca43de2f6599faf4 multi_aggregate_rate_limiter: ../../../contracts/solc/v0.8.24/MultiAggregateRateLimiter/MultiAggregateRateLimiter.abi ../../../contracts/solc/v0.8.24/MultiAggregateRateLimiter/MultiAggregateRateLimiter.bin 0b541232e49727e947dc164eadf35963c66e67576f21baa0ecaa06a8833148ed -multi_ocr3_helper: ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Helper.abi ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Helper.bin aa299e0c2659d53aad4eace4d66be0e734b1366008593669cf30361ff529da6a +multi_ocr3_helper: ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Helper.abi ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Helper.bin a0b23ebb141fa05e59f84bb8a8abd5eb804b94ddad6dc9f4beda5cc6995cb0f5 nonce_manager: ../../../contracts/solc/v0.8.24/NonceManager/NonceManager.abi ../../../contracts/solc/v0.8.24/NonceManager/NonceManager.bin 6f64e1083b356c06ee66b9138e398b9c97a4cd3e8c9ec38cf3010cebc79af536 ocr3_config_encoder: ../../../contracts/solc/v0.8.24/IOCR3ConfigEncoder/IOCR3ConfigEncoder.abi ../../../contracts/solc/v0.8.24/IOCR3ConfigEncoder/IOCR3ConfigEncoder.bin e21180898e1ad54a045ee20add85a2793c681425ea06f66d1a9e5cab128b6487 -offramp: ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.abi ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.bin a3b8a9644f0d450dbf53d3371555dcc4084fb2eaf138a3797ef5cf73ed665bae -onramp: ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.abi ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.bin 1ae9e3ebefc56d0382308c67c4ec066cdf3fa3eed2d31af8015d5d8db67f9c90 +offramp: ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.abi ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.bin e6344e0f3a65ff8122b41eb071cde5641a666c14ced5d72a04d65efb9ef538a5 +onramp: ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.abi ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.bin 93ad9efaf8789baf7133a5db803b20d05b4771bf25f57a438cb7e5a8111fb472 ping_pong_demo: ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.abi ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.bin c1c2f8a65c7ffd971899cae7fe62f2da57d09e936151e2b92163c4bebe699d6b price_registry: ../../../contracts/solc/v0.8.24/PriceRegistry/PriceRegistry.abi ../../../contracts/solc/v0.8.24/PriceRegistry/PriceRegistry.bin e7781d600c1bb7aa4620106af7f6e146a109b97f4cb6a7d06c9e15773340ecb2 registry_module_owner_custom: ../../../contracts/solc/v0.8.24/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.abi ../../../contracts/solc/v0.8.24/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.bin 75be86323c227917a9bbc3f799d7ed02f92db546653a36db30ed0ebe64461353 From 554f7c7ef7dc943f6cf7cc1be55a487084fb9187 Mon Sep 17 00:00:00 2001 From: Mateusz Sekara Date: Tue, 3 Sep 2024 11:53:45 +0200 Subject: [PATCH 065/115] Removing .swp file, probably accidentally committed --- .swp | Bin 61440 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .swp diff --git a/.swp b/.swp deleted file mode 100644 index e2293baeb2c82c5dda684b915378632a283c71fb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 61440 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 HJo5hlrWzqI From 3c694cb54f0a81d1bc1fd784b5f955324732f108 Mon Sep 17 00:00:00 2001 From: Anirudh Warrier <12178754+anirudhwarrier@users.noreply.github.com> Date: Tue, 3 Sep 2024 15:08:24 +0400 Subject: [PATCH 066/115] bump CTF to v1.34.10 (#1406) ## Motivation ## Solution --- integration-tests/actions/actions.go | 3 +- .../actions/automation_ocr_helpers.go | 3 +- .../actions/automationv2/actions.go | 3 +- integration-tests/actions/keeper_helpers.go | 3 +- integration-tests/actions/ocr_helpers.go | 3 +- integration-tests/actions/refund.go | 3 +- .../actions/vrf/common/actions.go | 3 +- .../actions/vrf/vrfv1/actions.go | 2 +- .../actions/vrf/vrfv2/contract_steps.go | 2 +- .../actions/vrf/vrfv2/setup_steps.go | 2 +- .../actions/vrf/vrfv2plus/contract_steps.go | 3 +- .../actions/vrf/vrfv2plus/setup_steps.go | 2 +- .../ccip-tests/testconfig/global.go | 3 +- .../contracts/contract_vrf_models.go | 2 +- .../contracts/ethereum_contracts.go | 3 +- .../contracts/ethereum_contracts_atlas.go | 3 +- .../ethereum_contracts_automation.go | 3 +- .../contracts/ethereum_vrf_contracts.go | 2 +- .../contracts/ethereum_vrfv2_contracts.go | 2 +- .../contracts/ethereum_vrfv2plus_contracts.go | 2 +- integration-tests/contracts/multicall.go | 3 +- integration-tests/contracts/test_contracts.go | 3 +- integration-tests/crib/connect.go | 3 +- integration-tests/go.mod | 19 +++++++++- integration-tests/go.sum | 38 +++++++++++++++++-- integration-tests/load/automationv2_1/gun.go | 3 +- .../load/automationv2_1/helpers.go | 3 +- integration-tests/load/functions/setup.go | 3 +- integration-tests/load/go.mod | 19 +++++++++- integration-tests/load/go.sum | 38 +++++++++++++++++-- integration-tests/load/ocr/gun.go | 3 +- integration-tests/load/ocr/vu.go | 2 +- integration-tests/load/vrfv2/gun.go | 3 +- integration-tests/load/vrfv2/vrfv2_test.go | 2 +- integration-tests/load/vrfv2plus/gun.go | 3 +- .../load/vrfv2plus/vrfv2plus_test.go | 2 +- .../reorg/automation_reorg_test.go | 2 +- integration-tests/smoke/keeper_test.go | 3 +- integration-tests/smoke/log_poller_test.go | 2 +- integration-tests/smoke/ocr2_test.go | 3 +- integration-tests/smoke/ocr_test.go | 3 +- .../smoke/reorg_above_finality_test.go | 2 +- integration-tests/smoke/vrf_test.go | 3 +- integration-tests/smoke/vrfv2_test.go | 2 +- integration-tests/smoke/vrfv2plus_test.go | 2 +- integration-tests/testconfig/testconfig.go | 2 +- .../testsetups/keeper_benchmark.go | 3 +- integration-tests/testsetups/ocr.go | 9 +++-- .../universal/log_poller/helpers.go | 3 +- integration-tests/wrappers/contract_caller.go | 3 +- 50 files changed, 180 insertions(+), 61 deletions(-) diff --git a/integration-tests/actions/actions.go b/integration-tests/actions/actions.go index 9cad5f79de..73365da443 100644 --- a/integration-tests/actions/actions.go +++ b/integration-tests/actions/actions.go @@ -40,7 +40,8 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/google/uuid" - "github.com/smartcontractkit/seth" + + "github.com/smartcontractkit/chainlink-testing-framework/seth" gethtypes "github.com/ethereum/go-ethereum/core/types" "github.com/pkg/errors" diff --git a/integration-tests/actions/automation_ocr_helpers.go b/integration-tests/actions/automation_ocr_helpers.go index 05c4501fbe..866d1078a6 100644 --- a/integration-tests/actions/automation_ocr_helpers.go +++ b/integration-tests/actions/automation_ocr_helpers.go @@ -10,7 +10,8 @@ import ( "time" "github.com/pkg/errors" - "github.com/smartcontractkit/seth" + + "github.com/smartcontractkit/chainlink-testing-framework/seth" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_automation_registry_master_wrapper_2_3" diff --git a/integration-tests/actions/automationv2/actions.go b/integration-tests/actions/automationv2/actions.go index 40caf15917..c0d751b96c 100644 --- a/integration-tests/actions/automationv2/actions.go +++ b/integration-tests/actions/automationv2/actions.go @@ -20,11 +20,12 @@ import ( ocr2 "github.com/smartcontractkit/libocr/offchainreporting2plus/confighelper" ocr3 "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3confighelper" "github.com/smartcontractkit/libocr/offchainreporting2plus/types" - "github.com/smartcontractkit/seth" "github.com/stretchr/testify/require" "golang.org/x/sync/errgroup" "gopkg.in/guregu/null.v4" + "github.com/smartcontractkit/chainlink-testing-framework/seth" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_automation_registry_master_wrapper_2_3" ocr2keepers20config "github.com/smartcontractkit/chainlink-automation/pkg/v2/config" diff --git a/integration-tests/actions/keeper_helpers.go b/integration-tests/actions/keeper_helpers.go index ee1662cc18..84353ff9b2 100644 --- a/integration-tests/actions/keeper_helpers.go +++ b/integration-tests/actions/keeper_helpers.go @@ -11,7 +11,8 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/google/uuid" "github.com/pkg/errors" - "github.com/smartcontractkit/seth" + + "github.com/smartcontractkit/chainlink-testing-framework/seth" ctf_concurrency "github.com/smartcontractkit/chainlink-testing-framework/concurrency" "github.com/smartcontractkit/chainlink-testing-framework/logging" diff --git a/integration-tests/actions/ocr_helpers.go b/integration-tests/actions/ocr_helpers.go index 0622167c99..b0292dc518 100644 --- a/integration-tests/actions/ocr_helpers.go +++ b/integration-tests/actions/ocr_helpers.go @@ -10,7 +10,8 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/rs/zerolog" - "github.com/smartcontractkit/seth" + + "github.com/smartcontractkit/chainlink-testing-framework/seth" "github.com/google/uuid" "github.com/stretchr/testify/require" diff --git a/integration-tests/actions/refund.go b/integration-tests/actions/refund.go index 38c4dfad3b..d49b74c699 100644 --- a/integration-tests/actions/refund.go +++ b/integration-tests/actions/refund.go @@ -16,7 +16,8 @@ import ( "github.com/ethereum/go-ethereum/crypto" "github.com/pkg/errors" "github.com/rs/zerolog" - "github.com/smartcontractkit/seth" + + "github.com/smartcontractkit/chainlink-testing-framework/seth" "github.com/smartcontractkit/chainlink-testing-framework/blockchain" diff --git a/integration-tests/actions/vrf/common/actions.go b/integration-tests/actions/vrf/common/actions.go index e599c705ef..1fcba02fa7 100644 --- a/integration-tests/actions/vrf/common/actions.go +++ b/integration-tests/actions/vrf/common/actions.go @@ -15,7 +15,8 @@ import ( "github.com/go-resty/resty/v2" "github.com/google/uuid" "github.com/rs/zerolog" - "github.com/smartcontractkit/seth" + + "github.com/smartcontractkit/chainlink-testing-framework/seth" ctf_test_env "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env" "github.com/smartcontractkit/chainlink-testing-framework/utils/conversions" diff --git a/integration-tests/actions/vrf/vrfv1/actions.go b/integration-tests/actions/vrf/vrfv1/actions.go index 67110c543e..f5fae76a39 100644 --- a/integration-tests/actions/vrf/vrfv1/actions.go +++ b/integration-tests/actions/vrf/vrfv1/actions.go @@ -3,7 +3,7 @@ package vrfv1 import ( "fmt" - "github.com/smartcontractkit/seth" + "github.com/smartcontractkit/chainlink-testing-framework/seth" "github.com/smartcontractkit/chainlink/integration-tests/contracts" ) diff --git a/integration-tests/actions/vrf/vrfv2/contract_steps.go b/integration-tests/actions/vrf/vrfv2/contract_steps.go index 324b65b5d6..053b06758d 100644 --- a/integration-tests/actions/vrf/vrfv2/contract_steps.go +++ b/integration-tests/actions/vrf/vrfv2/contract_steps.go @@ -11,7 +11,7 @@ import ( "github.com/rs/zerolog" "github.com/shopspring/decimal" - "github.com/smartcontractkit/seth" + "github.com/smartcontractkit/chainlink-testing-framework/seth" "github.com/smartcontractkit/chainlink-testing-framework/utils/conversions" "github.com/smartcontractkit/chainlink/integration-tests/actions" diff --git a/integration-tests/actions/vrf/vrfv2/setup_steps.go b/integration-tests/actions/vrf/vrfv2/setup_steps.go index c13aed807a..25b1f4c077 100644 --- a/integration-tests/actions/vrf/vrfv2/setup_steps.go +++ b/integration-tests/actions/vrf/vrfv2/setup_steps.go @@ -6,7 +6,7 @@ import ( "math/big" "testing" - "github.com/smartcontractkit/seth" + "github.com/smartcontractkit/chainlink-testing-framework/seth" seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" diff --git a/integration-tests/actions/vrf/vrfv2plus/contract_steps.go b/integration-tests/actions/vrf/vrfv2plus/contract_steps.go index 479b00d952..882bd97792 100644 --- a/integration-tests/actions/vrf/vrfv2plus/contract_steps.go +++ b/integration-tests/actions/vrf/vrfv2plus/contract_steps.go @@ -10,7 +10,8 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/rs/zerolog" "github.com/shopspring/decimal" - "github.com/smartcontractkit/seth" + + "github.com/smartcontractkit/chainlink-testing-framework/seth" "github.com/smartcontractkit/chainlink-testing-framework/utils/conversions" "github.com/smartcontractkit/chainlink/integration-tests/actions" diff --git a/integration-tests/actions/vrf/vrfv2plus/setup_steps.go b/integration-tests/actions/vrf/vrfv2plus/setup_steps.go index f3c7d53d6e..b7698e6429 100644 --- a/integration-tests/actions/vrf/vrfv2plus/setup_steps.go +++ b/integration-tests/actions/vrf/vrfv2plus/setup_steps.go @@ -6,7 +6,7 @@ import ( "math/big" "testing" - "github.com/smartcontractkit/seth" + "github.com/smartcontractkit/chainlink-testing-framework/seth" seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" diff --git a/integration-tests/ccip-tests/testconfig/global.go b/integration-tests/ccip-tests/testconfig/global.go index a1658a4841..e8d955fae9 100644 --- a/integration-tests/ccip-tests/testconfig/global.go +++ b/integration-tests/ccip-tests/testconfig/global.go @@ -12,7 +12,8 @@ import ( "github.com/pelletier/go-toml/v2" "github.com/pkg/errors" "github.com/rs/zerolog/log" - "github.com/smartcontractkit/seth" + + "github.com/smartcontractkit/chainlink-testing-framework/seth" "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env" "github.com/smartcontractkit/chainlink-testing-framework/logging" diff --git a/integration-tests/contracts/contract_vrf_models.go b/integration-tests/contracts/contract_vrf_models.go index 45825a18ff..3aca32a66f 100644 --- a/integration-tests/contracts/contract_vrf_models.go +++ b/integration-tests/contracts/contract_vrf_models.go @@ -9,7 +9,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" - "github.com/smartcontractkit/seth" + "github.com/smartcontractkit/chainlink-testing-framework/seth" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_coordinator_v2" diff --git a/integration-tests/contracts/ethereum_contracts.go b/integration-tests/contracts/ethereum_contracts.go index 2db6aeb463..9ce118b556 100644 --- a/integration-tests/contracts/ethereum_contracts.go +++ b/integration-tests/contracts/ethereum_contracts.go @@ -18,7 +18,8 @@ import ( "github.com/smartcontractkit/libocr/gethwrappers2/ocr2aggregator" ocrConfigHelper "github.com/smartcontractkit/libocr/offchainreporting/confighelper" ocrTypes "github.com/smartcontractkit/libocr/offchainreporting/types" - "github.com/smartcontractkit/seth" + + "github.com/smartcontractkit/chainlink-testing-framework/seth" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/counter" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/i_automation_registry_master_wrapper_2_3" diff --git a/integration-tests/contracts/ethereum_contracts_atlas.go b/integration-tests/contracts/ethereum_contracts_atlas.go index c28e519868..4636a92a19 100644 --- a/integration-tests/contracts/ethereum_contracts_atlas.go +++ b/integration-tests/contracts/ethereum_contracts_atlas.go @@ -5,7 +5,8 @@ import ( "math/big" "github.com/ethereum/go-ethereum/common" - "github.com/smartcontractkit/seth" + + "github.com/smartcontractkit/chainlink-testing-framework/seth" eth_contracts "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" "github.com/smartcontractkit/chainlink/integration-tests/wrappers" diff --git a/integration-tests/contracts/ethereum_contracts_automation.go b/integration-tests/contracts/ethereum_contracts_automation.go index bd0e1aafc8..b15cb6c172 100644 --- a/integration-tests/contracts/ethereum_contracts_automation.go +++ b/integration-tests/contracts/ethereum_contracts_automation.go @@ -14,7 +14,8 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/rs/zerolog" - "github.com/smartcontractkit/seth" + + "github.com/smartcontractkit/chainlink-testing-framework/seth" cltypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" registrylogicc23 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_registry_logic_c_wrapper_2_3" diff --git a/integration-tests/contracts/ethereum_vrf_contracts.go b/integration-tests/contracts/ethereum_vrf_contracts.go index e4dbb87d0b..8fcd6c7bfa 100644 --- a/integration-tests/contracts/ethereum_vrf_contracts.go +++ b/integration-tests/contracts/ethereum_vrf_contracts.go @@ -15,7 +15,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrfv2plus_wrapper" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrfv2plus_wrapper_optimism" - "github.com/smartcontractkit/seth" + "github.com/smartcontractkit/chainlink-testing-framework/seth" "github.com/smartcontractkit/chainlink-testing-framework/blockchain" "github.com/smartcontractkit/chainlink/integration-tests/wrappers" diff --git a/integration-tests/contracts/ethereum_vrfv2_contracts.go b/integration-tests/contracts/ethereum_vrfv2_contracts.go index a9d1a93769..aa9237ea7c 100644 --- a/integration-tests/contracts/ethereum_vrfv2_contracts.go +++ b/integration-tests/contracts/ethereum_vrfv2_contracts.go @@ -13,7 +13,7 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/rs/zerolog/log" - "github.com/smartcontractkit/seth" + "github.com/smartcontractkit/chainlink-testing-framework/seth" "github.com/smartcontractkit/chainlink/integration-tests/wrappers" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated" diff --git a/integration-tests/contracts/ethereum_vrfv2plus_contracts.go b/integration-tests/contracts/ethereum_vrfv2plus_contracts.go index 8e099b4f6b..58044b36c6 100644 --- a/integration-tests/contracts/ethereum_vrfv2plus_contracts.go +++ b/integration-tests/contracts/ethereum_vrfv2plus_contracts.go @@ -11,7 +11,7 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/montanaflynn/stats" - "github.com/smartcontractkit/seth" + "github.com/smartcontractkit/chainlink-testing-framework/seth" "github.com/smartcontractkit/chainlink/integration-tests/wrappers" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/batch_blockhash_store" diff --git a/integration-tests/contracts/multicall.go b/integration-tests/contracts/multicall.go index 6b73aed084..cd7134a8d8 100644 --- a/integration-tests/contracts/multicall.go +++ b/integration-tests/contracts/multicall.go @@ -8,7 +8,8 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" - "github.com/smartcontractkit/seth" + + "github.com/smartcontractkit/chainlink-testing-framework/seth" "github.com/smartcontractkit/chainlink/integration-tests/wrappers" ) diff --git a/integration-tests/contracts/test_contracts.go b/integration-tests/contracts/test_contracts.go index 85e76054c7..f8674e2136 100644 --- a/integration-tests/contracts/test_contracts.go +++ b/integration-tests/contracts/test_contracts.go @@ -7,7 +7,8 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/rs/zerolog" - "github.com/smartcontractkit/seth" + + "github.com/smartcontractkit/chainlink-testing-framework/seth" "github.com/smartcontractkit/chainlink/integration-tests/wrappers" le "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/log_emitter" diff --git a/integration-tests/crib/connect.go b/integration-tests/crib/connect.go index 91d7d8ee1a..f8ab8db282 100644 --- a/integration-tests/crib/connect.go +++ b/integration-tests/crib/connect.go @@ -7,7 +7,8 @@ import ( "time" "github.com/pkg/errors" - "github.com/smartcontractkit/seth" + + "github.com/smartcontractkit/chainlink-testing-framework/seth" "github.com/smartcontractkit/chainlink-testing-framework/utils/ptr" seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" diff --git a/integration-tests/go.mod b/integration-tests/go.mod index bb07aca3ae..20f43c4b7b 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -35,13 +35,13 @@ require ( github.com/smartcontractkit/chain-selectors v1.0.23 github.com/smartcontractkit/chainlink-automation v1.0.4 github.com/smartcontractkit/chainlink-common v0.2.2-0.20240723123524-e407ecd120b1 - github.com/smartcontractkit/chainlink-testing-framework v1.34.5 + github.com/smartcontractkit/chainlink-testing-framework v1.34.10 github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240405215812-5a72bc9af239 + github.com/smartcontractkit/chainlink-testing-framework/seth v1.2.1-0.20240827112945-bd8c580392d6 github.com/smartcontractkit/chainlink/integration-tests v0.0.0-00010101000000-000000000000 github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000 github.com/smartcontractkit/havoc/k8schaos v0.0.0-20240409145249-e78d20847e37 github.com/smartcontractkit/libocr v0.0.0-20240717100443-f6226e09bee7 - github.com/smartcontractkit/seth v1.2.1-0.20240827060008-860f949fcb26 github.com/smartcontractkit/wasp v0.4.5 github.com/spf13/cobra v1.8.1 github.com/stretchr/testify v1.9.0 @@ -104,8 +104,22 @@ require ( github.com/avast/retry-go v3.0.0+incompatible // indirect github.com/awalterschulze/gographviz v2.0.3+incompatible // indirect github.com/aws/aws-sdk-go v1.45.25 // indirect + github.com/aws/aws-sdk-go-v2 v1.30.4 // indirect + github.com/aws/aws-sdk-go-v2/config v1.27.28 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.17.28 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.12 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.16 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.16 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.4 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.18 // indirect + github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.32.5 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.22.5 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.5 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.30.4 // indirect github.com/aws/constructs-go/constructs/v10 v10.1.255 // indirect github.com/aws/jsii-runtime-go v1.75.0 // indirect + github.com/aws/smithy-go v1.20.4 // indirect github.com/bahlo/generic-list-go v0.2.0 // indirect github.com/benbjohnson/clock v1.3.5 // indirect github.com/beorn7/perks v1.0.1 // indirect @@ -395,6 +409,7 @@ require ( github.com/smartcontractkit/chainlink-feeds v0.0.0-20240710170203-5b41615da827 // indirect github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240712132946-267a37c5ac6e // indirect github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240709043547-03612098f799 // indirect + github.com/smartcontractkit/chainlink-testing-framework/wasp v0.4.9 // indirect github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 // indirect github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1 // indirect github.com/smartcontractkit/wsrpc v0.8.1 // indirect diff --git a/integration-tests/go.sum b/integration-tests/go.sum index 7e5179b252..5e6f9b279d 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -215,10 +215,38 @@ github.com/aws/aws-sdk-go v1.23.20/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpi github.com/aws/aws-sdk-go v1.38.35/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= github.com/aws/aws-sdk-go v1.45.25 h1:c4fLlh5sLdK2DCRTY1z0hyuJZU4ygxX8m1FswL6/nF4= github.com/aws/aws-sdk-go v1.45.25/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= +github.com/aws/aws-sdk-go-v2 v1.30.4 h1:frhcagrVNrzmT95RJImMHgabt99vkXGslubDaDagTk8= +github.com/aws/aws-sdk-go-v2 v1.30.4/go.mod h1:CT+ZPWXbYrci8chcARI3OmI/qgd+f6WtuLOoaIA8PR0= +github.com/aws/aws-sdk-go-v2/config v1.27.28 h1:OTxWGW/91C61QlneCtnD62NLb4W616/NM1jA8LhJqbg= +github.com/aws/aws-sdk-go-v2/config v1.27.28/go.mod h1:uzVRVtJSU5EFv6Fu82AoVFKozJi2ZCY6WRCXj06rbvs= +github.com/aws/aws-sdk-go-v2/credentials v1.17.28 h1:m8+AHY/ND8CMHJnPoH7PJIRakWGa4gbfbxuY9TGTUXM= +github.com/aws/aws-sdk-go-v2/credentials v1.17.28/go.mod h1:6TF7dSc78ehD1SL6KpRIPKMA1GyyWflIkjqg+qmf4+c= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.12 h1:yjwoSyDZF8Jth+mUk5lSPJCkMC0lMy6FaCD51jm6ayE= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.12/go.mod h1:fuR57fAgMk7ot3WcNQfb6rSEn+SUffl7ri+aa8uKysI= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.16 h1:TNyt/+X43KJ9IJJMjKfa3bNTiZbUP7DeCxfbTROESwY= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.16/go.mod h1:2DwJF39FlNAUiX5pAc0UNeiz16lK2t7IaFcm0LFHEgc= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.16 h1:jYfy8UPmd+6kJW5YhY0L1/KftReOGxI/4NtVSTh9O/I= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.16/go.mod h1:7ZfEPZxkW42Afq4uQB8H2E2e6ebh6mXTueEpYzjCzcs= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 h1:VaRN3TlFdd6KxX1x3ILT5ynH6HvKgqdiXoTxAF4HQcQ= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1/go.mod h1:FbtygfRFze9usAadmnGJNc8KsP346kEe+y2/oyhGAGc= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.4 h1:KypMCbLPPHEmf9DgMGw51jMj77VfGPAN2Kv4cfhlfgI= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.4/go.mod h1:Vz1JQXliGcQktFTN/LN6uGppAIRoLBR2bMvIMP0gOjc= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.18 h1:tJ5RnkHCiSH0jyd6gROjlJtNwov0eGYNz8s8nFcR0jQ= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.18/go.mod h1:++NHzT+nAF7ZPrHPsA+ENvsXkOO8wEu+C6RXltAG4/c= +github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.32.5 h1:UDXu9dqpCZYonj7poM4kFISjzTdWI0v3WUusM+w+Gfc= +github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.32.5/go.mod h1:5NPkI3RsTOhwz1CuG7VVSgJCm3CINKkoIaUbUZWQ67w= +github.com/aws/aws-sdk-go-v2/service/sso v1.22.5 h1:zCsFCKvbj25i7p1u94imVoO447I/sFv8qq+lGJhRN0c= +github.com/aws/aws-sdk-go-v2/service/sso v1.22.5/go.mod h1:ZeDX1SnKsVlejeuz41GiajjZpRSWR7/42q/EyA/QEiM= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.5 h1:SKvPgvdvmiTWoi0GAJ7AsJfOz3ngVkD/ERbs5pUnHNI= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.5/go.mod h1:20sz31hv/WsPa3HhU3hfrIet2kxM4Pe0r20eBZ20Tac= +github.com/aws/aws-sdk-go-v2/service/sts v1.30.4 h1:iAckBT2OeEK/kBDyN/jDtpEExhjeeA/Im2q4X0rJZT8= +github.com/aws/aws-sdk-go-v2/service/sts v1.30.4/go.mod h1:vmSqFK+BVIwVpDAGZB3CoCXHzurt4qBE8lf+I/kRTh0= github.com/aws/constructs-go/constructs/v10 v10.1.255 h1:5hARfEmhBqHSTQf/C3QLA3sWOxO2Dfja0iA1W7ZcI7g= github.com/aws/constructs-go/constructs/v10 v10.1.255/go.mod h1:DCdBSjN04Ck2pajCacTD4RKFqSA7Utya8d62XreYctI= github.com/aws/jsii-runtime-go v1.75.0 h1:NhpUfyiL7/wsRuUekFsz8FFBCYLfPD/l61kKg9kL/a4= github.com/aws/jsii-runtime-go v1.75.0/go.mod h1:TKCyrtM0pygEPo4rDZzbMSDNCDNTSYSN6/mGyHI6O3I= +github.com/aws/smithy-go v1.20.4 h1:2HK1zBdPgRbjFOHlfeQZfpC4r72MOb9bZkiFwggKO+4= +github.com/aws/smithy-go v1.20.4/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg= github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk= github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg= github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df h1:GSoSVRLoBaFpOOds6QyY1L8AX7uoY+Ln3BHc22W40X0= @@ -1409,10 +1437,14 @@ github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240712132946-267a37c5ac6 github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240712132946-267a37c5ac6e/go.mod h1:hsFhop+SlQHKD+DEFjZrMJmbauT1A/wvtZIeeo4PxFU= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240709043547-03612098f799 h1:HyLTySm7BR+oNfZqDTkVJ25wnmcTtxBBD31UkFL+kEM= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240709043547-03612098f799/go.mod h1:UVFRacRkP7O7TQAzFmR52v5mUlxf+G1ovMlCQAB/cHU= -github.com/smartcontractkit/chainlink-testing-framework v1.34.5 h1:6itLSDW4NHDDNR+Y+Z8YDzxxCN9SjdKb6SmLCl0vTFM= -github.com/smartcontractkit/chainlink-testing-framework v1.34.5/go.mod h1:hRZEDh2+afO8MSZb9qYNscmWb+3mHZf01J5ACZuIdTQ= +github.com/smartcontractkit/chainlink-testing-framework v1.34.10 h1:7boGJr/wkX5TF6TBb4wRnP6t1IFL6RD98+fZBJBZyCY= +github.com/smartcontractkit/chainlink-testing-framework v1.34.10/go.mod h1:ekYJbRAxXcs/YgOjHsY9/tlvDvXzv3lxcZK2eFUZduc= github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240405215812-5a72bc9af239 h1:Kk5OVlx/5g9q3Z3lhxytZS4/f8ds1MiNM8yaHgK3Oe8= github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240405215812-5a72bc9af239/go.mod h1:DC8sQMyTlI/44UCTL8QWFwb0bYNoXCfjwCv2hMivYZU= +github.com/smartcontractkit/chainlink-testing-framework/seth v1.2.1-0.20240827112945-bd8c580392d6 h1:ItZ75xmt+VHR/lw+GJwSWj9XICpgZ94dJ+I/5jdet7c= +github.com/smartcontractkit/chainlink-testing-framework/seth v1.2.1-0.20240827112945-bd8c580392d6/go.mod h1:afY3QmNgeR/VI1pRbGH8g3YXGy7C2RrFOwUzEFvL3L8= +github.com/smartcontractkit/chainlink-testing-framework/wasp v0.4.9 h1:zyp3Ic0lvseZEKh4/Afcsjk9RAnnxHEI6ajqNXWbRL0= +github.com/smartcontractkit/chainlink-testing-framework/wasp v0.4.9/go.mod h1:OMadmu2D8J0ju4XZ+tiTX3EOz0QBsfrw1zym+ZXuNVk= github.com/smartcontractkit/go-plugin v0.0.0-20240208201424-b3b91517de16 h1:TFe+FvzxClblt6qRfqEhUfa4kFQx5UobuoFGO2W4mMo= github.com/smartcontractkit/go-plugin v0.0.0-20240208201424-b3b91517de16/go.mod h1:lBS5MtSSBZk0SHc66KACcjjlU6WzEVP/8pwz68aMkCI= github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f h1:hgJif132UCdjo8u43i7iPN1/MFnu49hv7lFGFftCHKU= @@ -1421,8 +1453,6 @@ github.com/smartcontractkit/havoc/k8schaos v0.0.0-20240409145249-e78d20847e37 h1 github.com/smartcontractkit/havoc/k8schaos v0.0.0-20240409145249-e78d20847e37/go.mod h1:/kFr0D7SI/vueXl1N03uzOun4nViGPFRyA5X6eL3jXw= github.com/smartcontractkit/libocr v0.0.0-20240717100443-f6226e09bee7 h1:e38V5FYE7DA1JfKXeD5Buo/7lczALuVXlJ8YNTAUxcw= github.com/smartcontractkit/libocr v0.0.0-20240717100443-f6226e09bee7/go.mod h1:fb1ZDVXACvu4frX3APHZaEBp0xi1DIm34DcA0CwTsZM= -github.com/smartcontractkit/seth v1.2.1-0.20240827060008-860f949fcb26 h1:9c3dbd38M8T/Hkc9LKOSRf3wxfXAFNJcLnEPOBOctNk= -github.com/smartcontractkit/seth v1.2.1-0.20240827060008-860f949fcb26/go.mod h1:KrhtzffZ+Pp5vyTkYErnnwjfjrGl8F9y3pxrbuZlVr0= github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 h1:yiKnypAqP8l0OX0P3klzZ7SCcBUxy5KqTAKZmQOvSQE= github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1/go.mod h1:q6f4fe39oZPdsh1i57WznEZgxd8siidMaSFq3wdPmVg= github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1 h1:Dai1bn+Q5cpeGMQwRdjOdVjG8mmFFROVkSKuUgBErRQ= diff --git a/integration-tests/load/automationv2_1/gun.go b/integration-tests/load/automationv2_1/gun.go index 162aca251f..a5fd52c40c 100644 --- a/integration-tests/load/automationv2_1/gun.go +++ b/integration-tests/load/automationv2_1/gun.go @@ -5,9 +5,10 @@ import ( "sync" "github.com/rs/zerolog" - "github.com/smartcontractkit/seth" "github.com/smartcontractkit/wasp" + "github.com/smartcontractkit/chainlink-testing-framework/seth" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/log_emitter" "github.com/smartcontractkit/chainlink/integration-tests/contracts" diff --git a/integration-tests/load/automationv2_1/helpers.go b/integration-tests/load/automationv2_1/helpers.go index 30559743e1..f770ba7573 100644 --- a/integration-tests/load/automationv2_1/helpers.go +++ b/integration-tests/load/automationv2_1/helpers.go @@ -8,7 +8,8 @@ import ( "github.com/pkg/errors" "github.com/rs/zerolog" "github.com/slack-go/slack" - "github.com/smartcontractkit/seth" + + "github.com/smartcontractkit/chainlink-testing-framework/seth" ctf_concurrency "github.com/smartcontractkit/chainlink-testing-framework/concurrency" reportModel "github.com/smartcontractkit/chainlink-testing-framework/testreporters" diff --git a/integration-tests/load/functions/setup.go b/integration-tests/load/functions/setup.go index 5519c90846..8151342021 100644 --- a/integration-tests/load/functions/setup.go +++ b/integration-tests/load/functions/setup.go @@ -13,9 +13,10 @@ import ( "github.com/ethereum/go-ethereum/crypto" "github.com/go-resty/resty/v2" "github.com/rs/zerolog/log" - "github.com/smartcontractkit/seth" "github.com/smartcontractkit/tdh2/go/tdh2/tdh2easy" + "github.com/smartcontractkit/chainlink-testing-framework/seth" + chainlinkutils "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" ctf_config "github.com/smartcontractkit/chainlink-testing-framework/config" diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index eef855ef03..6ce1049562 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -17,11 +17,11 @@ require ( github.com/slack-go/slack v0.12.2 github.com/smartcontractkit/chainlink-automation v1.0.4 github.com/smartcontractkit/chainlink-common v0.2.2-0.20240723123524-e407ecd120b1 - github.com/smartcontractkit/chainlink-testing-framework v1.34.5 + github.com/smartcontractkit/chainlink-testing-framework v1.34.10 + github.com/smartcontractkit/chainlink-testing-framework/seth v1.2.1-0.20240827112945-bd8c580392d6 github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20240214231432-4ad5eb95178c github.com/smartcontractkit/chainlink/v2 v2.9.0-beta0.0.20240216210048-da02459ddad8 github.com/smartcontractkit/libocr v0.0.0-20240717100443-f6226e09bee7 - github.com/smartcontractkit/seth v1.2.1-0.20240827060008-860f949fcb26 github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1 github.com/smartcontractkit/wasp v0.4.7 github.com/stretchr/testify v1.9.0 @@ -36,6 +36,20 @@ require ( cosmossdk.io/errors v1.0.1 // indirect cosmossdk.io/math v1.3.0 // indirect github.com/awalterschulze/gographviz v2.0.3+incompatible // indirect + github.com/aws/aws-sdk-go-v2 v1.30.4 // indirect + github.com/aws/aws-sdk-go-v2/config v1.27.28 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.17.28 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.12 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.16 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.16 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.4 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.18 // indirect + github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.32.5 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.22.5 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.5 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.30.4 // indirect + github.com/aws/smithy-go v1.20.4 // indirect github.com/containerd/errdefs v0.1.0 // indirect github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect @@ -43,6 +57,7 @@ require ( github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240710121324-3ed288aa9b45 // indirect + github.com/smartcontractkit/chainlink-testing-framework/wasp v0.4.9 // indirect github.com/testcontainers/testcontainers-go v0.28.0 // indirect k8s.io/apimachinery v0.31.0 // indirect ) diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index 86712da168..760e624daf 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -203,10 +203,38 @@ github.com/aws/aws-sdk-go v1.23.20/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpi github.com/aws/aws-sdk-go v1.38.35/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= github.com/aws/aws-sdk-go v1.45.25 h1:c4fLlh5sLdK2DCRTY1z0hyuJZU4ygxX8m1FswL6/nF4= github.com/aws/aws-sdk-go v1.45.25/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= +github.com/aws/aws-sdk-go-v2 v1.30.4 h1:frhcagrVNrzmT95RJImMHgabt99vkXGslubDaDagTk8= +github.com/aws/aws-sdk-go-v2 v1.30.4/go.mod h1:CT+ZPWXbYrci8chcARI3OmI/qgd+f6WtuLOoaIA8PR0= +github.com/aws/aws-sdk-go-v2/config v1.27.28 h1:OTxWGW/91C61QlneCtnD62NLb4W616/NM1jA8LhJqbg= +github.com/aws/aws-sdk-go-v2/config v1.27.28/go.mod h1:uzVRVtJSU5EFv6Fu82AoVFKozJi2ZCY6WRCXj06rbvs= +github.com/aws/aws-sdk-go-v2/credentials v1.17.28 h1:m8+AHY/ND8CMHJnPoH7PJIRakWGa4gbfbxuY9TGTUXM= +github.com/aws/aws-sdk-go-v2/credentials v1.17.28/go.mod h1:6TF7dSc78ehD1SL6KpRIPKMA1GyyWflIkjqg+qmf4+c= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.12 h1:yjwoSyDZF8Jth+mUk5lSPJCkMC0lMy6FaCD51jm6ayE= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.12/go.mod h1:fuR57fAgMk7ot3WcNQfb6rSEn+SUffl7ri+aa8uKysI= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.16 h1:TNyt/+X43KJ9IJJMjKfa3bNTiZbUP7DeCxfbTROESwY= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.16/go.mod h1:2DwJF39FlNAUiX5pAc0UNeiz16lK2t7IaFcm0LFHEgc= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.16 h1:jYfy8UPmd+6kJW5YhY0L1/KftReOGxI/4NtVSTh9O/I= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.16/go.mod h1:7ZfEPZxkW42Afq4uQB8H2E2e6ebh6mXTueEpYzjCzcs= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 h1:VaRN3TlFdd6KxX1x3ILT5ynH6HvKgqdiXoTxAF4HQcQ= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1/go.mod h1:FbtygfRFze9usAadmnGJNc8KsP346kEe+y2/oyhGAGc= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.4 h1:KypMCbLPPHEmf9DgMGw51jMj77VfGPAN2Kv4cfhlfgI= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.4/go.mod h1:Vz1JQXliGcQktFTN/LN6uGppAIRoLBR2bMvIMP0gOjc= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.18 h1:tJ5RnkHCiSH0jyd6gROjlJtNwov0eGYNz8s8nFcR0jQ= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.18/go.mod h1:++NHzT+nAF7ZPrHPsA+ENvsXkOO8wEu+C6RXltAG4/c= +github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.32.5 h1:UDXu9dqpCZYonj7poM4kFISjzTdWI0v3WUusM+w+Gfc= +github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.32.5/go.mod h1:5NPkI3RsTOhwz1CuG7VVSgJCm3CINKkoIaUbUZWQ67w= +github.com/aws/aws-sdk-go-v2/service/sso v1.22.5 h1:zCsFCKvbj25i7p1u94imVoO447I/sFv8qq+lGJhRN0c= +github.com/aws/aws-sdk-go-v2/service/sso v1.22.5/go.mod h1:ZeDX1SnKsVlejeuz41GiajjZpRSWR7/42q/EyA/QEiM= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.5 h1:SKvPgvdvmiTWoi0GAJ7AsJfOz3ngVkD/ERbs5pUnHNI= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.5/go.mod h1:20sz31hv/WsPa3HhU3hfrIet2kxM4Pe0r20eBZ20Tac= +github.com/aws/aws-sdk-go-v2/service/sts v1.30.4 h1:iAckBT2OeEK/kBDyN/jDtpEExhjeeA/Im2q4X0rJZT8= +github.com/aws/aws-sdk-go-v2/service/sts v1.30.4/go.mod h1:vmSqFK+BVIwVpDAGZB3CoCXHzurt4qBE8lf+I/kRTh0= github.com/aws/constructs-go/constructs/v10 v10.1.255 h1:5hARfEmhBqHSTQf/C3QLA3sWOxO2Dfja0iA1W7ZcI7g= github.com/aws/constructs-go/constructs/v10 v10.1.255/go.mod h1:DCdBSjN04Ck2pajCacTD4RKFqSA7Utya8d62XreYctI= github.com/aws/jsii-runtime-go v1.75.0 h1:NhpUfyiL7/wsRuUekFsz8FFBCYLfPD/l61kKg9kL/a4= github.com/aws/jsii-runtime-go v1.75.0/go.mod h1:TKCyrtM0pygEPo4rDZzbMSDNCDNTSYSN6/mGyHI6O3I= +github.com/aws/smithy-go v1.20.4 h1:2HK1zBdPgRbjFOHlfeQZfpC4r72MOb9bZkiFwggKO+4= +github.com/aws/smithy-go v1.20.4/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg= github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk= github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg= github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df h1:GSoSVRLoBaFpOOds6QyY1L8AX7uoY+Ln3BHc22W40X0= @@ -1375,10 +1403,14 @@ github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240712132946-267a37c5ac6 github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240712132946-267a37c5ac6e/go.mod h1:hsFhop+SlQHKD+DEFjZrMJmbauT1A/wvtZIeeo4PxFU= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240709043547-03612098f799 h1:HyLTySm7BR+oNfZqDTkVJ25wnmcTtxBBD31UkFL+kEM= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240709043547-03612098f799/go.mod h1:UVFRacRkP7O7TQAzFmR52v5mUlxf+G1ovMlCQAB/cHU= -github.com/smartcontractkit/chainlink-testing-framework v1.34.5 h1:6itLSDW4NHDDNR+Y+Z8YDzxxCN9SjdKb6SmLCl0vTFM= -github.com/smartcontractkit/chainlink-testing-framework v1.34.5/go.mod h1:hRZEDh2+afO8MSZb9qYNscmWb+3mHZf01J5ACZuIdTQ= +github.com/smartcontractkit/chainlink-testing-framework v1.34.10 h1:7boGJr/wkX5TF6TBb4wRnP6t1IFL6RD98+fZBJBZyCY= +github.com/smartcontractkit/chainlink-testing-framework v1.34.10/go.mod h1:ekYJbRAxXcs/YgOjHsY9/tlvDvXzv3lxcZK2eFUZduc= github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.1 h1:1/r1wQZ4TOFpZ13w94r7amdF096Z96RuEnkOmrz1BGE= github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.1/go.mod h1:DC8sQMyTlI/44UCTL8QWFwb0bYNoXCfjwCv2hMivYZU= +github.com/smartcontractkit/chainlink-testing-framework/seth v1.2.1-0.20240827112945-bd8c580392d6 h1:ItZ75xmt+VHR/lw+GJwSWj9XICpgZ94dJ+I/5jdet7c= +github.com/smartcontractkit/chainlink-testing-framework/seth v1.2.1-0.20240827112945-bd8c580392d6/go.mod h1:afY3QmNgeR/VI1pRbGH8g3YXGy7C2RrFOwUzEFvL3L8= +github.com/smartcontractkit/chainlink-testing-framework/wasp v0.4.9 h1:zyp3Ic0lvseZEKh4/Afcsjk9RAnnxHEI6ajqNXWbRL0= +github.com/smartcontractkit/chainlink-testing-framework/wasp v0.4.9/go.mod h1:OMadmu2D8J0ju4XZ+tiTX3EOz0QBsfrw1zym+ZXuNVk= github.com/smartcontractkit/go-plugin v0.0.0-20240208201424-b3b91517de16 h1:TFe+FvzxClblt6qRfqEhUfa4kFQx5UobuoFGO2W4mMo= github.com/smartcontractkit/go-plugin v0.0.0-20240208201424-b3b91517de16/go.mod h1:lBS5MtSSBZk0SHc66KACcjjlU6WzEVP/8pwz68aMkCI= github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f h1:hgJif132UCdjo8u43i7iPN1/MFnu49hv7lFGFftCHKU= @@ -1387,8 +1419,6 @@ github.com/smartcontractkit/havoc/k8schaos v0.0.0-20240409145249-e78d20847e37 h1 github.com/smartcontractkit/havoc/k8schaos v0.0.0-20240409145249-e78d20847e37/go.mod h1:/kFr0D7SI/vueXl1N03uzOun4nViGPFRyA5X6eL3jXw= github.com/smartcontractkit/libocr v0.0.0-20240717100443-f6226e09bee7 h1:e38V5FYE7DA1JfKXeD5Buo/7lczALuVXlJ8YNTAUxcw= github.com/smartcontractkit/libocr v0.0.0-20240717100443-f6226e09bee7/go.mod h1:fb1ZDVXACvu4frX3APHZaEBp0xi1DIm34DcA0CwTsZM= -github.com/smartcontractkit/seth v1.2.1-0.20240827060008-860f949fcb26 h1:9c3dbd38M8T/Hkc9LKOSRf3wxfXAFNJcLnEPOBOctNk= -github.com/smartcontractkit/seth v1.2.1-0.20240827060008-860f949fcb26/go.mod h1:KrhtzffZ+Pp5vyTkYErnnwjfjrGl8F9y3pxrbuZlVr0= github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 h1:yiKnypAqP8l0OX0P3klzZ7SCcBUxy5KqTAKZmQOvSQE= github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1/go.mod h1:q6f4fe39oZPdsh1i57WznEZgxd8siidMaSFq3wdPmVg= github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1 h1:Dai1bn+Q5cpeGMQwRdjOdVjG8mmFFROVkSKuUgBErRQ= diff --git a/integration-tests/load/ocr/gun.go b/integration-tests/load/ocr/gun.go index c4b79ceaf4..5ed71f1672 100644 --- a/integration-tests/load/ocr/gun.go +++ b/integration-tests/load/ocr/gun.go @@ -6,9 +6,10 @@ import ( "time" "github.com/rs/zerolog" - "github.com/smartcontractkit/seth" "github.com/smartcontractkit/wasp" + "github.com/smartcontractkit/chainlink-testing-framework/seth" + "github.com/smartcontractkit/chainlink/integration-tests/contracts" ) diff --git a/integration-tests/load/ocr/vu.go b/integration-tests/load/ocr/vu.go index 88f186c5ee..a50b52c690 100644 --- a/integration-tests/load/ocr/vu.go +++ b/integration-tests/load/ocr/vu.go @@ -9,7 +9,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/rs/zerolog" - "github.com/smartcontractkit/seth" + "github.com/smartcontractkit/chainlink-testing-framework/seth" "github.com/smartcontractkit/wasp" "go.uber.org/ratelimit" diff --git a/integration-tests/load/vrfv2/gun.go b/integration-tests/load/vrfv2/gun.go index bf7449a247..0eef5b1481 100644 --- a/integration-tests/load/vrfv2/gun.go +++ b/integration-tests/load/vrfv2/gun.go @@ -4,9 +4,10 @@ import ( "math/rand" "github.com/rs/zerolog" - "github.com/smartcontractkit/seth" "github.com/smartcontractkit/wasp" + "github.com/smartcontractkit/chainlink-testing-framework/seth" + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" vrfcommon "github.com/smartcontractkit/chainlink/integration-tests/actions/vrf/common" diff --git a/integration-tests/load/vrfv2/vrfv2_test.go b/integration-tests/load/vrfv2/vrfv2_test.go index 31d6c27e51..6d3c199d7e 100644 --- a/integration-tests/load/vrfv2/vrfv2_test.go +++ b/integration-tests/load/vrfv2/vrfv2_test.go @@ -7,7 +7,7 @@ import ( "testing" "time" - "github.com/smartcontractkit/seth" + "github.com/smartcontractkit/chainlink-testing-framework/seth" "github.com/rs/zerolog/log" "github.com/smartcontractkit/wasp" diff --git a/integration-tests/load/vrfv2plus/gun.go b/integration-tests/load/vrfv2plus/gun.go index 430e9f5ff1..8d4162ab88 100644 --- a/integration-tests/load/vrfv2plus/gun.go +++ b/integration-tests/load/vrfv2plus/gun.go @@ -5,9 +5,10 @@ import ( "math/rand" "github.com/rs/zerolog" - "github.com/smartcontractkit/seth" "github.com/smartcontractkit/wasp" + "github.com/smartcontractkit/chainlink-testing-framework/seth" + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" "github.com/smartcontractkit/chainlink/integration-tests/actions" diff --git a/integration-tests/load/vrfv2plus/vrfv2plus_test.go b/integration-tests/load/vrfv2plus/vrfv2plus_test.go index 7eb55d0f43..98a9375389 100644 --- a/integration-tests/load/vrfv2plus/vrfv2plus_test.go +++ b/integration-tests/load/vrfv2plus/vrfv2plus_test.go @@ -6,7 +6,7 @@ import ( "testing" "time" - "github.com/smartcontractkit/seth" + "github.com/smartcontractkit/chainlink-testing-framework/seth" "github.com/rs/zerolog/log" "github.com/smartcontractkit/wasp" diff --git a/integration-tests/reorg/automation_reorg_test.go b/integration-tests/reorg/automation_reorg_test.go index 1b9cf5819b..fbfac20d40 100644 --- a/integration-tests/reorg/automation_reorg_test.go +++ b/integration-tests/reorg/automation_reorg_test.go @@ -132,7 +132,7 @@ func TestAutomationReorg(t *testing.T) { err = actions.FundChainlinkNodesFromRootAddress(l, sethClient, contracts.ChainlinkClientToChainlinkNodeWithKeysAndAddress(env.ClCluster.NodeAPIs()), big.NewFloat(*config.GetCommonConfig().ChainlinkNodeFunding)) require.NoError(t, err, "Failed to fund the nodes") - gethRPCClient := ctfClient.NewRPCClient(evmNetwork.HTTPURLs[0]) + gethRPCClient := ctfClient.NewRPCClient(evmNetwork.HTTPURLs[0], nil) registryConfig := actions.AutomationDefaultRegistryConfig(config) registryConfig.RegistryVersion = registryVersion diff --git a/integration-tests/smoke/keeper_test.go b/integration-tests/smoke/keeper_test.go index 4ff1c90bd1..9e979dd0ff 100644 --- a/integration-tests/smoke/keeper_test.go +++ b/integration-tests/smoke/keeper_test.go @@ -13,9 +13,10 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/onsi/gomega" "github.com/rs/zerolog" - "github.com/smartcontractkit/seth" "github.com/stretchr/testify/require" + "github.com/smartcontractkit/chainlink-testing-framework/seth" + "github.com/smartcontractkit/chainlink-testing-framework/logging" "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" diff --git a/integration-tests/smoke/log_poller_test.go b/integration-tests/smoke/log_poller_test.go index f1a257552a..18862e13b7 100644 --- a/integration-tests/smoke/log_poller_test.go +++ b/integration-tests/smoke/log_poller_test.go @@ -7,7 +7,7 @@ import ( "testing" "time" - "github.com/smartcontractkit/seth" + "github.com/smartcontractkit/chainlink-testing-framework/seth" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/onsi/gomega" diff --git a/integration-tests/smoke/ocr2_test.go b/integration-tests/smoke/ocr2_test.go index 56a95c50bd..05f3dfa05c 100644 --- a/integration-tests/smoke/ocr2_test.go +++ b/integration-tests/smoke/ocr2_test.go @@ -12,9 +12,10 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/rs/zerolog" - "github.com/smartcontractkit/seth" "github.com/stretchr/testify/require" + "github.com/smartcontractkit/chainlink-testing-framework/seth" + "github.com/smartcontractkit/chainlink-testing-framework/logging" "github.com/smartcontractkit/chainlink-testing-framework/logstream" "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" diff --git a/integration-tests/smoke/ocr_test.go b/integration-tests/smoke/ocr_test.go index 0b4ac3de30..3d0ec83174 100644 --- a/integration-tests/smoke/ocr_test.go +++ b/integration-tests/smoke/ocr_test.go @@ -9,9 +9,10 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/rs/zerolog" - "github.com/smartcontractkit/seth" "github.com/stretchr/testify/require" + "github.com/smartcontractkit/chainlink-testing-framework/seth" + "github.com/smartcontractkit/chainlink-testing-framework/logging" "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" diff --git a/integration-tests/smoke/reorg_above_finality_test.go b/integration-tests/smoke/reorg_above_finality_test.go index e7b9e4a218..78132848e5 100644 --- a/integration-tests/smoke/reorg_above_finality_test.go +++ b/integration-tests/smoke/reorg_above_finality_test.go @@ -53,7 +53,7 @@ func TestReorgAboveFinality_FinalityTagDisabled(t *testing.T) { evmNetwork, err := testEnv.GetFirstEvmNetwork() require.NoError(t, err, "Error getting first evm network") - client := ctf_client.NewRPCClient(evmNetwork.HTTPURLs[0]) + client := ctf_client.NewRPCClient(evmNetwork.HTTPURLs[0], nil) // Wait for chain to progress require.Eventually(t, func() bool { diff --git a/integration-tests/smoke/vrf_test.go b/integration-tests/smoke/vrf_test.go index 04e760796d..ac22270216 100644 --- a/integration-tests/smoke/vrf_test.go +++ b/integration-tests/smoke/vrf_test.go @@ -9,9 +9,10 @@ import ( "github.com/google/uuid" "github.com/onsi/gomega" "github.com/rs/zerolog" - "github.com/smartcontractkit/seth" "github.com/stretchr/testify/require" + "github.com/smartcontractkit/chainlink-testing-framework/seth" + "github.com/smartcontractkit/chainlink-testing-framework/logging" seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" diff --git a/integration-tests/smoke/vrfv2_test.go b/integration-tests/smoke/vrfv2_test.go index aad2a6d577..73e3d9054b 100644 --- a/integration-tests/smoke/vrfv2_test.go +++ b/integration-tests/smoke/vrfv2_test.go @@ -10,7 +10,7 @@ import ( "testing" "time" - "github.com/smartcontractkit/seth" + "github.com/smartcontractkit/chainlink-testing-framework/seth" "github.com/ethereum/go-ethereum/common" "github.com/google/go-cmp/cmp" diff --git a/integration-tests/smoke/vrfv2plus_test.go b/integration-tests/smoke/vrfv2plus_test.go index 00bd2a101a..2d95074ef0 100644 --- a/integration-tests/smoke/vrfv2plus_test.go +++ b/integration-tests/smoke/vrfv2plus_test.go @@ -9,7 +9,7 @@ import ( "testing" "time" - "github.com/smartcontractkit/seth" + "github.com/smartcontractkit/chainlink-testing-framework/seth" "github.com/ethereum/go-ethereum/common" "github.com/google/go-cmp/cmp" diff --git a/integration-tests/testconfig/testconfig.go b/integration-tests/testconfig/testconfig.go index 718a72c4e7..11f73a6ab0 100644 --- a/integration-tests/testconfig/testconfig.go +++ b/integration-tests/testconfig/testconfig.go @@ -17,7 +17,7 @@ import ( "golang.org/x/text/cases" "golang.org/x/text/language" - "github.com/smartcontractkit/seth" + "github.com/smartcontractkit/chainlink-testing-framework/seth" ctf_config "github.com/smartcontractkit/chainlink-testing-framework/config" k8s_config "github.com/smartcontractkit/chainlink-testing-framework/k8s/config" diff --git a/integration-tests/testsetups/keeper_benchmark.go b/integration-tests/testsetups/keeper_benchmark.go index 4803a5249f..f6bb041de8 100644 --- a/integration-tests/testsetups/keeper_benchmark.go +++ b/integration-tests/testsetups/keeper_benchmark.go @@ -21,10 +21,11 @@ import ( "github.com/rs/zerolog" "github.com/rs/zerolog/log" "github.com/slack-go/slack" - "github.com/smartcontractkit/seth" "github.com/stretchr/testify/require" "golang.org/x/sync/errgroup" + "github.com/smartcontractkit/chainlink-testing-framework/seth" + "github.com/smartcontractkit/chainlink-testing-framework/blockchain" "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment" "github.com/smartcontractkit/chainlink-testing-framework/logging" diff --git a/integration-tests/testsetups/ocr.go b/integration-tests/testsetups/ocr.go index 30b0a6fcb1..858f6d08a5 100644 --- a/integration-tests/testsetups/ocr.go +++ b/integration-tests/testsetups/ocr.go @@ -23,9 +23,10 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/pelletier/go-toml/v2" "github.com/rs/zerolog" - "github.com/smartcontractkit/seth" "github.com/stretchr/testify/require" + "github.com/smartcontractkit/chainlink-testing-framework/seth" + "github.com/smartcontractkit/libocr/gethwrappers/offchainaggregator" "github.com/smartcontractkit/libocr/gethwrappers2/ocr2aggregator" @@ -740,7 +741,7 @@ func (o *OCRSoakTest) complete() { } func (o *OCRSoakTest) startGethBlockchainReorg(network blockchain.EVMNetwork, conf ctf_config.ReorgConfig) { - client := ctf_client.NewRPCClient(network.HTTPURLs[0]) + client := ctf_client.NewRPCClient(network.HTTPURLs[0], nil) o.log.Info(). Str("URL", client.URL). Int("Depth", conf.Depth). @@ -752,7 +753,7 @@ func (o *OCRSoakTest) startGethBlockchainReorg(network blockchain.EVMNetwork, co } func (o *OCRSoakTest) startAnvilGasSpikeSimulation(network blockchain.EVMNetwork, conf ctf_config.GasSpikeSimulationConfig) { - client := ctf_client.NewRPCClient(network.HTTPURLs[0]) + client := ctf_client.NewRPCClient(network.HTTPURLs[0], nil) o.log.Info(). Str("URL", client.URL). Any("GasSpikeSimulationConfig", conf). @@ -765,7 +766,7 @@ func (o *OCRSoakTest) startAnvilGasSpikeSimulation(network blockchain.EVMNetwork } func (o *OCRSoakTest) startAnvilGasLimitSimulation(network blockchain.EVMNetwork, conf ctf_config.GasLimitSimulationConfig) { - client := ctf_client.NewRPCClient(network.HTTPURLs[0]) + client := ctf_client.NewRPCClient(network.HTTPURLs[0], nil) latestBlock, err := o.seth.Client.BlockByNumber(context.Background(), nil) require.NoError(o.t, err) newGasLimit := int64(math.Ceil(float64(latestBlock.GasUsed()) * conf.NextGasLimitPercentage)) diff --git a/integration-tests/universal/log_poller/helpers.go b/integration-tests/universal/log_poller/helpers.go index daa4784ec1..ce352440ac 100644 --- a/integration-tests/universal/log_poller/helpers.go +++ b/integration-tests/universal/log_poller/helpers.go @@ -14,9 +14,10 @@ import ( "time" "github.com/jmoiron/sqlx" - "github.com/smartcontractkit/seth" "github.com/smartcontractkit/wasp" + "github.com/smartcontractkit/chainlink-testing-framework/seth" + geth "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" diff --git a/integration-tests/wrappers/contract_caller.go b/integration-tests/wrappers/contract_caller.go index 0eea760e02..31672cb915 100644 --- a/integration-tests/wrappers/contract_caller.go +++ b/integration-tests/wrappers/contract_caller.go @@ -16,7 +16,8 @@ import ( "github.com/ethereum/go-ethereum/rpc" "github.com/pkg/errors" "github.com/rs/zerolog" - "github.com/smartcontractkit/seth" + + "github.com/smartcontractkit/chainlink-testing-framework/seth" "github.com/smartcontractkit/chainlink-testing-framework/blockchain" From e1577f60b7c653d6ea976d669f569527405e9bc3 Mon Sep 17 00:00:00 2001 From: Mateusz Sekara Date: Tue, 3 Sep 2024 13:47:35 +0200 Subject: [PATCH 067/115] Adding comment to the Observation structs (#1349) --- core/services/ocr2/plugins/ccip/observations.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/core/services/ocr2/plugins/ccip/observations.go b/core/services/ocr2/plugins/ccip/observations.go index f79d667a55..29fa85021f 100644 --- a/core/services/ocr2/plugins/ccip/observations.go +++ b/core/services/ocr2/plugins/ccip/observations.go @@ -19,6 +19,10 @@ import ( // Note if a breaking change is introduced to this struct nodes running different versions // will not be able to unmarshal each other's observations. Do not modify unless you // know what you are doing. +// +// IMPORTANT: Both CommitObservation and ExecutionObservation are streamed and processed by Atlas. +// Any change to that struct must be reflected in the Atlas codebase. +// Additionally, you must test if OTI telemetry ingestion works with the new struct on staging environment. type CommitObservation struct { Interval cciptypes.CommitStoreInterval `json:"interval"` TokenPricesUSD map[cciptypes.Address]*big.Int `json:"tokensPerFeeCoin"` @@ -47,6 +51,10 @@ func (o CommitObservation) Marshal() ([]byte, error) { // Note if a breaking change is introduced to this struct nodes running different versions // will not be able to unmarshal each other's observations. Do not modify unless you // know what you are doing. +// +// IMPORTANT: Both CommitObservation and ExecutionObservation are streamed and processed by Atlas. +// Any change to that struct must be reflected in the Atlas codebase. +// Additionally, you must test if OTI telemetry ingestion works with the new struct on staging environment. type ExecutionObservation struct { Messages map[uint64]MsgData `json:"messages"` } From 62ba1f047c80cab5725df25fcb48089407a6f495 Mon Sep 17 00:00:00 2001 From: Rens Rooimans Date: Tue, 3 Sep 2024 17:43:31 +0200 Subject: [PATCH 068/115] Increase max signers (#1405) Improve tests and error checks --------- Co-authored-by: app-token-issuer-infra-releng[bot] <120227048+app-token-issuer-infra-releng[bot]@users.noreply.github.com> --- contracts/gas-snapshots/ccip.gas-snapshot | 94 ++--- .../src/v0.8/ccip/capability/CCIPConfig.sol | 37 +- contracts/src/v0.8/ccip/ocr/MultiOCR3Base.sol | 18 +- .../ccip/test/capability/CCIPConfig.t.sol | 349 ++++-------------- .../v0.8/ccip/test/ocr/MultiOCR3Base.t.sol | 4 +- .../ccip/generated/ccip_config/ccip_config.go | 4 +- .../multi_ocr3_helper/multi_ocr3_helper.go | 2 +- .../ccip/generated/offramp/offramp.go | 2 +- ...rapper-dependency-versions-do-not-edit.txt | 6 +- 9 files changed, 154 insertions(+), 362 deletions(-) diff --git a/contracts/gas-snapshots/ccip.gas-snapshot b/contracts/gas-snapshots/ccip.gas-snapshot index 60e1c8bf98..6153b0a079 100644 --- a/contracts/gas-snapshots/ccip.gas-snapshot +++ b/contracts/gas-snapshots/ccip.gas-snapshot @@ -37,9 +37,9 @@ BurnWithFromMintTokenPool_lockOrBurn:test_Setup_Success() (gas: 23951) CCIPClientExample_sanity:test_ImmutableExamples_Success() (gas: 2132684) CCIPConfigSetup:test_getCapabilityConfiguration_Success() (gas: 9517) CCIPConfig_ConfigStateMachine:test__computeConfigDigest_Success() (gas: 70831) -CCIPConfig_ConfigStateMachine:test__computeNewConfigWithMeta_InitToRunning_Success() (gas: 363544) -CCIPConfig_ConfigStateMachine:test__computeNewConfigWithMeta_RunningToStaging_Success() (gas: 488615) -CCIPConfig_ConfigStateMachine:test__computeNewConfigWithMeta_StagingToRunning_Success() (gas: 453319) +CCIPConfig_ConfigStateMachine:test__computeNewConfigWithMeta_InitToRunning_Success() (gas: 363682) +CCIPConfig_ConfigStateMachine:test__computeNewConfigWithMeta_RunningToStaging_Success() (gas: 488896) +CCIPConfig_ConfigStateMachine:test__computeNewConfigWithMeta_StagingToRunning_Success() (gas: 453458) CCIPConfig_ConfigStateMachine:test__groupByPluginType_TooManyOCR3Configs_Reverts() (gas: 37049) CCIPConfig_ConfigStateMachine:test__groupByPluginType_threeCommitConfigs_Reverts() (gas: 61065) CCIPConfig_ConfigStateMachine:test__groupByPluginType_threeExecutionConfigs_Reverts() (gas: 60985) @@ -54,9 +54,9 @@ CCIPConfig_ConfigStateMachine:test__validateConfigTransition_RunningToStaging_Wr CCIPConfig_ConfigStateMachine:test__validateConfigTransition_StagingToRunning_Success() (gas: 376425) CCIPConfig_ConfigStateMachine:test__validateConfigTransition_StagingToRunning_WrongConfigDigest_Reverts() (gas: 157312) CCIPConfig_ConfigStateMachine:test_getCapabilityConfiguration_Success() (gas: 9605) -CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_CommitAndExecConfig_Success() (gas: 1850870) -CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_CommitConfigOnly_Success() (gas: 1068182) -CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_ExecConfigOnly_Success() (gas: 1068213) +CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_CommitAndExecConfig_Success() (gas: 1851149) +CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_CommitConfigOnly_Success() (gas: 1068320) +CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_ExecConfigOnly_Success() (gas: 1068351) CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_OnlyCapabilitiesRegistryCanCall_Reverts() (gas: 9599) CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_ZeroLengthConfig_Success() (gas: 16057) CCIPConfig_beforeCapabilityConfigSet:test_getCapabilityConfiguration_Success() (gas: 9605) @@ -67,31 +67,31 @@ CCIPConfig_chainConfig:test_applyChainConfigUpdates_removeChainConfigs_Success() CCIPConfig_chainConfig:test_applyChainConfigUpdates_selectorNotFound_Reverts() (gas: 14829) CCIPConfig_chainConfig:test_getCapabilityConfiguration_Success() (gas: 9626) CCIPConfig_chainConfig:test_getPaginatedCCIPConfigs_Success() (gas: 370249) -CCIPConfig_constructor:test_constructor_Success() (gas: 3602871) -CCIPConfig_constructor:test_constructor_ZeroAddressNotAllowed_Revert() (gas: 61769) -CCIPConfig_updatePluginConfig:test__updatePluginConfig_InitToRunning_Success() (gas: 1057248) +CCIPConfig_constructor:test_constructor_Success() (gas: 3597863) +CCIPConfig_constructor:test_constructor_ZeroAddressNotAllowed_Revert() (gas: 61761) +CCIPConfig_updatePluginConfig:test__updatePluginConfig_InitToRunning_Success() (gas: 1057386) CCIPConfig_updatePluginConfig:test__updatePluginConfig_InvalidConfigLength_Reverts() (gas: 27561) CCIPConfig_updatePluginConfig:test__updatePluginConfig_InvalidConfigStateTransition_Reverts() (gas: 23127) -CCIPConfig_updatePluginConfig:test__updatePluginConfig_RunningToStaging_Success() (gas: 2009044) -CCIPConfig_updatePluginConfig:test__updatePluginConfig_StagingToRunning_Success() (gas: 2615819) +CCIPConfig_updatePluginConfig:test__updatePluginConfig_RunningToStaging_Success() (gas: 2009377) +CCIPConfig_updatePluginConfig:test__updatePluginConfig_StagingToRunning_Success() (gas: 2616263) CCIPConfig_updatePluginConfig:test_getCapabilityConfiguration_Success() (gas: 9605) -CCIPConfig_validateConfig:test__validateConfig_BootstrapP2PIdsHasDuplicates_Reverts() (gas: 294864) -CCIPConfig_validateConfig:test__validateConfig_BootstrapP2PIdsNotASubsetOfP2PIds_Reverts() (gas: 298296) -CCIPConfig_validateConfig:test__validateConfig_BootstrapP2PIdsNotSorted_Reverts() (gas: 295009) -CCIPConfig_validateConfig:test__validateConfig_ChainSelectorNotFound_Reverts() (gas: 294328) -CCIPConfig_validateConfig:test__validateConfig_ChainSelectorNotSet_Reverts() (gas: 291402) -CCIPConfig_validateConfig:test__validateConfig_FMustBePositive_Reverts() (gas: 292367) -CCIPConfig_validateConfig:test__validateConfig_FTooHigh_Reverts() (gas: 292511) -CCIPConfig_validateConfig:test__validateConfig_NodeNotInRegistry_Reverts() (gas: 299453) -CCIPConfig_validateConfig:test__validateConfig_NotEnoughTransmitters_Reverts() (gas: 1159741) -CCIPConfig_validateConfig:test__validateConfig_OfframpAddressCannotBeZero_Reverts() (gas: 291231) -CCIPConfig_validateConfig:test__validateConfig_P2PIdsHasDuplicates_Reverts() (gas: 295878) -CCIPConfig_validateConfig:test__validateConfig_P2PIdsLengthNotMatching_Reverts() (gas: 293200) -CCIPConfig_validateConfig:test__validateConfig_P2PIdsNotSorted_Reverts() (gas: 295594) -CCIPConfig_validateConfig:test__validateConfig_Success() (gas: 302066) -CCIPConfig_validateConfig:test__validateConfig_TooManyBootstrapP2PIds_Reverts() (gas: 294510) -CCIPConfig_validateConfig:test__validateConfig_TooManySigners_Reverts() (gas: 1215496) -CCIPConfig_validateConfig:test__validateConfig_TooManyTransmitters_Reverts() (gas: 1213899) +CCIPConfig_validateConfig:test__validateConfig_ABIEncodedAddress_OfframpAddressCannotBeZero_Reverts() (gas: 292159) +CCIPConfig_validateConfig:test__validateConfig_BootstrapP2PIdsHasDuplicates_Reverts() (gas: 295946) +CCIPConfig_validateConfig:test__validateConfig_BootstrapP2PIdsNotASubsetOfP2PIds_Reverts() (gas: 299396) +CCIPConfig_validateConfig:test__validateConfig_BootstrapP2PIdsNotSorted_Reverts() (gas: 296081) +CCIPConfig_validateConfig:test__validateConfig_ChainSelectorNotFound_Reverts() (gas: 294926) +CCIPConfig_validateConfig:test__validateConfig_ChainSelectorNotSet_Reverts() (gas: 291771) +CCIPConfig_validateConfig:test__validateConfig_FMustBePositive_Reverts() (gas: 292999) +CCIPConfig_validateConfig:test__validateConfig_FTooHigh_Reverts() (gas: 293164) +CCIPConfig_validateConfig:test__validateConfig_NodeNotInRegistry_Reverts() (gas: 348310) +CCIPConfig_validateConfig:test__validateConfig_NotEnoughTransmitters_Reverts() (gas: 1209654) +CCIPConfig_validateConfig:test__validateConfig_OfframpAddressCannotBeZero_Reverts() (gas: 291876) +CCIPConfig_validateConfig:test__validateConfig_P2PIdsHasDuplicates_Reverts() (gas: 295780) +CCIPConfig_validateConfig:test__validateConfig_P2PIdsLengthNotMatching_Reverts() (gas: 293785) +CCIPConfig_validateConfig:test__validateConfig_P2PIdsNotSorted_Reverts() (gas: 296150) +CCIPConfig_validateConfig:test__validateConfig_Success() (gas: 302468) +CCIPConfig_validateConfig:test__validateConfig_TooManyBootstrapP2PIds_Reverts() (gas: 295556) +CCIPConfig_validateConfig:test__validateConfig_TooManySigners_Reverts() (gas: 494442) CCIPConfig_validateConfig:test_getCapabilityConfiguration_Success() (gas: 9584) CommitStore_constructor:test_Constructor_Success() (gas: 3091326) CommitStore_isUnpausedAndRMNHealthy:test_RMN_Success() (gas: 73420) @@ -536,20 +536,20 @@ MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokens_Remov MultiAggregateRateLimiter_updateRateLimitTokens:test_ZeroDestToken_Revert() (gas: 18287) MultiAggregateRateLimiter_updateRateLimitTokens:test_ZeroSourceToken_Revert() (gas: 18216) MultiOCR3Base_setOCR3Configs:test_FMustBePositive_Revert() (gas: 59331) -MultiOCR3Base_setOCR3Configs:test_FTooHigh_Revert() (gas: 44289) -MultiOCR3Base_setOCR3Configs:test_RepeatSignerAddress_Revert() (gas: 283606) -MultiOCR3Base_setOCR3Configs:test_RepeatTransmitterAddress_Revert() (gas: 422233) +MultiOCR3Base_setOCR3Configs:test_FTooHigh_Revert() (gas: 43602) +MultiOCR3Base_setOCR3Configs:test_RepeatSignerAddress_Revert() (gas: 283585) +MultiOCR3Base_setOCR3Configs:test_RepeatTransmitterAddress_Revert() (gas: 422210) MultiOCR3Base_setOCR3Configs:test_SetConfigIgnoreSigners_Success() (gas: 511089) -MultiOCR3Base_setOCR3Configs:test_SetConfigWithSigners_Success() (gas: 828394) +MultiOCR3Base_setOCR3Configs:test_SetConfigWithSigners_Success() (gas: 828371) MultiOCR3Base_setOCR3Configs:test_SetConfigWithoutSigners_Success() (gas: 456841) MultiOCR3Base_setOCR3Configs:test_SetConfigsZeroInput_Success() (gas: 12376) -MultiOCR3Base_setOCR3Configs:test_SetMultipleConfigs_Success() (gas: 2140127) -MultiOCR3Base_setOCR3Configs:test_SignerCannotBeZeroAddress_Revert() (gas: 141723) -MultiOCR3Base_setOCR3Configs:test_StaticConfigChange_Revert() (gas: 807279) -MultiOCR3Base_setOCR3Configs:test_TooManySigners_Revert() (gas: 171322) -MultiOCR3Base_setOCR3Configs:test_TooManyTransmitters_Revert() (gas: 30289) -MultiOCR3Base_setOCR3Configs:test_TransmitterCannotBeZeroAddress_Revert() (gas: 254091) -MultiOCR3Base_setOCR3Configs:test_UpdateConfigSigners_Success() (gas: 860006) +MultiOCR3Base_setOCR3Configs:test_SetMultipleConfigs_Success() (gas: 2140058) +MultiOCR3Base_setOCR3Configs:test_SignerCannotBeZeroAddress_Revert() (gas: 141702) +MultiOCR3Base_setOCR3Configs:test_StaticConfigChange_Revert() (gas: 807256) +MultiOCR3Base_setOCR3Configs:test_TooManySigners_Revert() (gas: 158772) +MultiOCR3Base_setOCR3Configs:test_TooManyTransmitters_Revert() (gas: 112266) +MultiOCR3Base_setOCR3Configs:test_TransmitterCannotBeZeroAddress_Revert() (gas: 254068) +MultiOCR3Base_setOCR3Configs:test_UpdateConfigSigners_Success() (gas: 859969) MultiOCR3Base_setOCR3Configs:test_UpdateConfigTransmittersWithoutSigners_Success() (gas: 475059) MultiOCR3Base_transmit:test_ConfigDigestMismatch_Revert() (gas: 42837) MultiOCR3Base_transmit:test_ForkedChain_Revert() (gas: 48442) @@ -640,12 +640,12 @@ OffRamp_ccipReceive:test_Reverts() (gas: 15773) OffRamp_commit:test_InvalidIntervalMinLargerThanMax_Revert() (gas: 67458) OffRamp_commit:test_InvalidInterval_Revert() (gas: 59778) OffRamp_commit:test_InvalidRootRevert() (gas: 58858) -OffRamp_commit:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6536301) -OffRamp_commit:test_NoConfig_Revert() (gas: 6120044) +OffRamp_commit:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6534892) +OffRamp_commit:test_NoConfig_Revert() (gas: 6118635) OffRamp_commit:test_OnlyGasPriceUpdates_Success() (gas: 105929) OffRamp_commit:test_OnlyPriceUpdateStaleReport_Revert() (gas: 115981) OffRamp_commit:test_OnlyTokenPriceUpdates_Success() (gas: 105950) -OffRamp_commit:test_PriceSequenceNumberCleared_Success() (gas: 349072) +OffRamp_commit:test_PriceSequenceNumberCleared_Success() (gas: 349049) OffRamp_commit:test_ReportAndPriceUpdate_Success() (gas: 158960) OffRamp_commit:test_ReportOnlyRootSuccess_gas() (gas: 136092) OffRamp_commit:test_RootAlreadyCommitted_Revert() (gas: 136492) @@ -654,9 +654,9 @@ OffRamp_commit:test_StaleReportWithRoot_Success() (gas: 224806) OffRamp_commit:test_UnauthorizedTransmitter_Revert() (gas: 117632) OffRamp_commit:test_Unhealthy_Revert() (gas: 77674) OffRamp_commit:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 204296) -OffRamp_commit:test_WrongConfigWithoutSigners_Revert() (gas: 6530690) +OffRamp_commit:test_WrongConfigWithoutSigners_Revert() (gas: 6529281) OffRamp_commit:test_ZeroEpochAndRound_Revert() (gas: 47832) -OffRamp_constructor:test_Constructor_Success() (gas: 6123343) +OffRamp_constructor:test_Constructor_Success() (gas: 6121934) OffRamp_constructor:test_SourceChainSelector_Revert() (gas: 137089) OffRamp_constructor:test_ZeroChainSelector_Revert() (gas: 103806) OffRamp_constructor:test_ZeroNonceManager_Revert() (gas: 101677) @@ -667,12 +667,12 @@ OffRamp_execute:test_IncorrectArrayType_Revert() (gas: 17305) OffRamp_execute:test_LargeBatch_Success() (gas: 1812704) OffRamp_execute:test_MultipleReportsWithPartialValidationFailures_Success() (gas: 357260) OffRamp_execute:test_MultipleReports_Success() (gas: 284815) -OffRamp_execute:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6587413) -OffRamp_execute:test_NoConfig_Revert() (gas: 6170896) +OffRamp_execute:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6586004) +OffRamp_execute:test_NoConfig_Revert() (gas: 6169487) OffRamp_execute:test_NonArray_Revert() (gas: 27809) OffRamp_execute:test_SingleReport_Success() (gas: 175620) OffRamp_execute:test_UnauthorizedTransmitter_Revert() (gas: 147848) -OffRamp_execute:test_WrongConfigWithSigners_Revert() (gas: 6948937) +OffRamp_execute:test_WrongConfigWithSigners_Revert() (gas: 6947505) OffRamp_execute:test_ZeroReports_Revert() (gas: 17225) OffRamp_executeSingleMessage:test_MessageSender_Revert() (gas: 18257) OffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 249037) diff --git a/contracts/src/v0.8/ccip/capability/CCIPConfig.sol b/contracts/src/v0.8/ccip/capability/CCIPConfig.sol index 822b36fe8b..5f863ed7ae 100644 --- a/contracts/src/v0.8/ccip/capability/CCIPConfig.sol +++ b/contracts/src/v0.8/ccip/capability/CCIPConfig.sol @@ -35,7 +35,6 @@ contract CCIPConfig is ITypeAndVersion, ICapabilityConfiguration, OwnerIsCreator error ChainSelectorNotSet(); error TooManyOCR3Configs(); error TooManySigners(); - error TooManyTransmitters(); error TooManyBootstrapP2PIds(); error P2PIdsLengthNotMatching(uint256 p2pIdsLength, uint256 signersLength, uint256 transmittersLength); error NotEnoughTransmitters(uint256 got, uint256 minimum); @@ -60,6 +59,15 @@ contract CCIPConfig is ITypeAndVersion, ICapabilityConfiguration, OwnerIsCreator /// @notice The canonical capabilities registry address. address internal immutable i_capabilitiesRegistry; + uint8 internal constant MAX_OCR3_CONFIGS_PER_PLUGIN = 2; + uint8 internal constant MAX_OCR3_CONFIGS_PER_DON = 4; + uint256 internal constant CONFIG_DIGEST_PREFIX_MASK = type(uint256).max << (256 - 16); // 0xFFFF00..0 + /// @dev must be equal to libocr multi role: https://github.com/smartcontractkit/libocr/blob/ae747ca5b81236ffdbf1714318c652e923a5ff4d/offchainreporting2plus/types/config_digest.go#L28 + uint256 internal constant CONFIG_DIGEST_PREFIX = 0x000a << (256 - 16); // 0x000a00..00 + bytes32 internal constant EMPTY_ENCODED_ADDRESS_HASH = keccak256(abi.encode(address(0))); + /// @dev 256 is the hard limit due to the bit encoding of their indexes into a uint256. + uint256 internal constant MAX_NUM_ORACLES = 256; + /// @notice chain configuration for each chain that CCIP is deployed on. mapping(uint64 chainSelector => CCIPConfigTypes.ChainConfig chainConfig) internal s_chainConfigurations; @@ -73,13 +81,6 @@ contract CCIPConfig is ITypeAndVersion, ICapabilityConfiguration, OwnerIsCreator uint32 donId => mapping(Internal.OCRPluginType pluginType => CCIPConfigTypes.OCR3ConfigWithMeta[] ocr3Configs) ) internal s_ocr3Configs; - uint8 internal constant MAX_OCR3_CONFIGS_PER_PLUGIN = 2; - uint8 internal constant MAX_OCR3_CONFIGS_PER_DON = 4; - uint8 internal constant MAX_NUM_ORACLES = 31; - uint256 internal constant CONFIG_DIGEST_PREFIX_MASK = type(uint256).max << (256 - 16); // 0xFFFF00..0 - /// @dev must be equal to libocr multi role: https://github.com/smartcontractkit/libocr/blob/ae747ca5b81236ffdbf1714318c652e923a5ff4d/offchainreporting2plus/types/config_digest.go#L28 - uint256 internal constant CONFIG_DIGEST_PREFIX = 0x000a << (256 - 16); // 0x000a00..00 - /// @param capabilitiesRegistry the canonical capabilities registry address. constructor(address capabilitiesRegistry) { if (capabilitiesRegistry == address(0)) { @@ -388,26 +389,24 @@ contract CCIPConfig is ITypeAndVersion, ICapabilityConfiguration, OwnerIsCreator if (cfg.pluginType != Internal.OCRPluginType.Commit && cfg.pluginType != Internal.OCRPluginType.Execution) { revert InvalidPluginType(); } - // TODO: can we do more sophisticated validation than this? - if (cfg.offrampAddress.length == 0) revert OfframpAddressCannotBeZero(); + if (cfg.offrampAddress.length == 0 || keccak256(cfg.offrampAddress) == EMPTY_ENCODED_ADDRESS_HASH) { + revert OfframpAddressCannotBeZero(); + } if (!s_remoteChainSelectors.contains(cfg.chainSelector)) revert ChainSelectorNotFound(cfg.chainSelector); - // Some of these checks below are done in OCR2/3Base config validation, so we do them again here. - // Role DON OCR configs will have all the Role DON signers but only a subset of transmitters. - if (cfg.signers.length > MAX_NUM_ORACLES) revert TooManySigners(); - if (cfg.transmitters.length > MAX_NUM_ORACLES) revert TooManyTransmitters(); - // We check for chain config presence above, so fChain here must be non-zero. uint256 minTransmittersLength = 3 * s_chainConfigurations[cfg.chainSelector].fChain + 1; if (cfg.transmitters.length < minTransmittersLength) { revert NotEnoughTransmitters(cfg.transmitters.length, minTransmittersLength); } - if (cfg.F == 0) revert FMustBePositive(); - if (cfg.signers.length <= 3 * cfg.F) revert FTooHigh(); - - if (cfg.p2pIds.length != cfg.signers.length || cfg.p2pIds.length != cfg.transmitters.length) { + uint256 numberOfSigners = cfg.signers.length; + if (numberOfSigners > MAX_NUM_ORACLES) revert TooManySigners(); + if (numberOfSigners != cfg.p2pIds.length || numberOfSigners != cfg.transmitters.length) { revert P2PIdsLengthNotMatching(cfg.p2pIds.length, cfg.signers.length, cfg.transmitters.length); } + if (cfg.F == 0) revert FMustBePositive(); + if (numberOfSigners <= 3 * cfg.F) revert FTooHigh(); + if (cfg.bootstrapP2PIds.length > cfg.p2pIds.length) revert TooManyBootstrapP2PIds(); // check for duplicate p2p ids and bootstrapP2PIds. diff --git a/contracts/src/v0.8/ccip/ocr/MultiOCR3Base.sol b/contracts/src/v0.8/ccip/ocr/MultiOCR3Base.sol index 0759127097..c9fff4d624 100644 --- a/contracts/src/v0.8/ccip/ocr/MultiOCR3Base.sol +++ b/contracts/src/v0.8/ccip/ocr/MultiOCR3Base.sol @@ -8,7 +8,7 @@ import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; /// with multiple OCR plugin support. abstract contract MultiOCR3Base is ITypeAndVersion, OwnerIsCreator { // Maximum number of oracles the offchain reporting protocol is designed for - uint256 internal constant MAX_NUM_ORACLES = 31; + uint256 internal constant MAX_NUM_ORACLES = 256; /// @notice Triggers a new run of the offchain reporting protocol /// @param ocrPluginType OCR plugin type for which the config was set @@ -154,13 +154,12 @@ abstract contract MultiOCR3Base is ITypeAndVersion, OwnerIsCreator { _clearOracleRoles(ocrPluginType, ocrConfig.signers); address[] memory signers = ocrConfigArgs.signers; - ocrConfig.signers = signers; - uint8 signersLength = uint8(signers.length); - configInfo.n = signersLength; + if (signers.length > MAX_NUM_ORACLES) revert InvalidConfig(InvalidConfigErrorType.TOO_MANY_SIGNERS); + if (signers.length <= 3 * ocrConfigArgs.F) revert InvalidConfig(InvalidConfigErrorType.F_TOO_HIGH); - if (signersLength > MAX_NUM_ORACLES) revert InvalidConfig(InvalidConfigErrorType.TOO_MANY_SIGNERS); - if (signersLength <= 3 * ocrConfigArgs.F) revert InvalidConfig(InvalidConfigErrorType.F_TOO_HIGH); + configInfo.n = uint8(signers.length); + ocrConfig.signers = signers; _assignOracleRoles(ocrPluginType, signers, Role.Signer); } @@ -288,17 +287,16 @@ abstract contract MultiOCR3Base is ITypeAndVersion, OwnerIsCreator { bytes32 hashedReport, bytes32[] memory rs, bytes32[] memory ss, - bytes32 rawVs // signatures + bytes32 rawVs ) internal view { - // Verify signatures attached to report + // Verify signatures attached to report. Using a uint256 means we can only verify up to 256 oracles. uint256 signed = 0; uint256 numberOfSignatures = rs.length; for (uint256 i; i < numberOfSignatures; ++i) { // Safe from ECDSA malleability here since we check for duplicate signers. address signer = ecrecover(hashedReport, uint8(rawVs[i]) + 27, rs[i], ss[i]); - // Since we disallow address(0) as a valid signer address, it can - // never have a signer role. + // Since we disallow address(0) as a valid signer address, it can never have a signer role. Oracle memory oracle = s_oracles[ocrPluginType][signer]; if (oracle.role != Role.Signer) revert UnauthorizedSigner(); if (signed & (0x1 << oracle.index) != 0) revert NonUniqueSignatures(); diff --git a/contracts/src/v0.8/ccip/test/capability/CCIPConfig.t.sol b/contracts/src/v0.8/ccip/test/capability/CCIPConfig.t.sol index ca7f2114a6..d252698e62 100644 --- a/contracts/src/v0.8/ccip/test/capability/CCIPConfig.t.sol +++ b/contracts/src/v0.8/ccip/test/capability/CCIPConfig.t.sol @@ -334,13 +334,10 @@ contract CCIPConfig_chainConfig is CCIPConfigSetup { } contract CCIPConfig_validateConfig is CCIPConfigSetup { - // Successes. - - function test__validateConfig_Success() public { + function _getCorrectOCR3Config() internal returns (CCIPConfigTypes.OCR3Config memory) { (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); - // Config is for 4 nodes, so f == 1. - CCIPConfigTypes.OCR3Config memory config = CCIPConfigTypes.OCR3Config({ + return CCIPConfigTypes.OCR3Config({ pluginType: Internal.OCRPluginType.Commit, offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), chainSelector: 1, @@ -352,239 +349,118 @@ contract CCIPConfig_validateConfig is CCIPConfigSetup { offchainConfigVersion: 30, offchainConfig: bytes("offchainConfig") }); - s_ccipCC.validateConfig(config); + } + + // Successes. + + function test__validateConfig_Success() public { + s_ccipCC.validateConfig(_getCorrectOCR3Config()); } // Reverts. function test__validateConfig_ChainSelectorNotSet_Reverts() public { - (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); - - // Config is for 4 nodes, so f == 1. - CCIPConfigTypes.OCR3Config memory config = CCIPConfigTypes.OCR3Config({ - pluginType: Internal.OCRPluginType.Commit, - offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), - chainSelector: 0, // invalid - bootstrapP2PIds: _subset(p2pIds, 0, 1), - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, - offchainConfigVersion: 30, - offchainConfig: bytes("offchainConfig") - }); + CCIPConfigTypes.OCR3Config memory config = _getCorrectOCR3Config(); + config.chainSelector = 0; // invalid vm.expectRevert(CCIPConfig.ChainSelectorNotSet.selector); s_ccipCC.validateConfig(config); } function test__validateConfig_OfframpAddressCannotBeZero_Reverts() public { - (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); - - // Config is for 4 nodes, so f == 1. - CCIPConfigTypes.OCR3Config memory config = CCIPConfigTypes.OCR3Config({ - pluginType: Internal.OCRPluginType.Commit, - offrampAddress: bytes(""), // invalid - chainSelector: 1, - bootstrapP2PIds: _subset(p2pIds, 0, 1), - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, - offchainConfigVersion: 30, - offchainConfig: bytes("offchainConfig") - }); + CCIPConfigTypes.OCR3Config memory config = _getCorrectOCR3Config(); + config.offrampAddress = ""; // invalid vm.expectRevert(CCIPConfig.OfframpAddressCannotBeZero.selector); s_ccipCC.validateConfig(config); } - function test__validateConfig_ChainSelectorNotFound_Reverts() public { - (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); - - // Config is for 4 nodes, so f == 1. - CCIPConfigTypes.OCR3Config memory config = CCIPConfigTypes.OCR3Config({ - pluginType: Internal.OCRPluginType.Commit, - offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), - chainSelector: 2, // not set - bootstrapP2PIds: _subset(p2pIds, 0, 1), - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, - offchainConfigVersion: 30, - offchainConfig: bytes("offchainConfig") - }); - - vm.expectRevert(abi.encodeWithSelector(CCIPConfig.ChainSelectorNotFound.selector, 2)); - s_ccipCC.validateConfig(config); - } - - function test__validateConfig_TooManySigners_Reverts() public { - // 32 > 31 (max num oracles) - (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(32); - - CCIPConfigTypes.OCR3Config memory config = CCIPConfigTypes.OCR3Config({ - pluginType: Internal.OCRPluginType.Commit, - offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), - chainSelector: 1, - bootstrapP2PIds: _subset(p2pIds, 0, 1), - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, - offchainConfigVersion: 30, - offchainConfig: bytes("offchainConfig") - }); + function test__validateConfig_ABIEncodedAddress_OfframpAddressCannotBeZero_Reverts() public { + CCIPConfigTypes.OCR3Config memory config = _getCorrectOCR3Config(); + config.offrampAddress = abi.encode(address(0)); // invalid - vm.expectRevert(CCIPConfig.TooManySigners.selector); + vm.expectRevert(CCIPConfig.OfframpAddressCannotBeZero.selector); s_ccipCC.validateConfig(config); } - function test__validateConfig_TooManyTransmitters_Reverts() public { - // 32 > 31 (max num oracles) - (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(32); - - // truncate signers but keep transmitters > 31 - assembly { - mstore(signers, 30) - } - - CCIPConfigTypes.OCR3Config memory config = CCIPConfigTypes.OCR3Config({ - pluginType: Internal.OCRPluginType.Commit, - offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), - chainSelector: 1, - bootstrapP2PIds: _subset(p2pIds, 0, 1), - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, - offchainConfigVersion: 30, - offchainConfig: bytes("offchainConfig") - }); + function test__validateConfig_ChainSelectorNotFound_Reverts() public { + CCIPConfigTypes.OCR3Config memory config = _getCorrectOCR3Config(); + config.chainSelector = 2; // not set - vm.expectRevert(CCIPConfig.TooManyTransmitters.selector); + vm.expectRevert(abi.encodeWithSelector(CCIPConfig.ChainSelectorNotFound.selector, 2)); s_ccipCC.validateConfig(config); } function test__validateConfig_NotEnoughTransmitters_Reverts() public { + CCIPConfigTypes.OCR3Config memory config = _getCorrectOCR3Config(); + uint256 numberOfTransmitters = 3; + // 32 > 31 (max num oracles) (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(31); // truncate transmitters to < 3 * fChain + 1 // since fChain is 1 in this case, we need to truncate to 3 transmitters. assembly { - mstore(transmitters, 3) + mstore(transmitters, numberOfTransmitters) } - CCIPConfigTypes.OCR3Config memory config = CCIPConfigTypes.OCR3Config({ - pluginType: Internal.OCRPluginType.Commit, - offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), - chainSelector: 1, - bootstrapP2PIds: _subset(p2pIds, 0, 1), - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, - offchainConfigVersion: 30, - offchainConfig: bytes("offchainConfig") - }); + config.transmitters = transmitters; + config.p2pIds = p2pIds; + config.signers = signers; - vm.expectRevert(abi.encodeWithSelector(CCIPConfig.NotEnoughTransmitters.selector, 3, 4)); + vm.expectRevert(abi.encodeWithSelector(CCIPConfig.NotEnoughTransmitters.selector, numberOfTransmitters, 4)); s_ccipCC.validateConfig(config); } - function test__validateConfig_FMustBePositive_Reverts() public { - (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); + function test__validateConfig_TooManySigners_Reverts() public { + CCIPConfigTypes.OCR3Config memory config = _getCorrectOCR3Config(); + config.signers = new bytes[](257); - // Config is for 4 nodes, so f == 1. - CCIPConfigTypes.OCR3Config memory config = CCIPConfigTypes.OCR3Config({ - pluginType: Internal.OCRPluginType.Commit, - offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), - chainSelector: 1, - bootstrapP2PIds: _subset(p2pIds, 0, 1), - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 0, - offchainConfigVersion: 30, - offchainConfig: bytes("offchainConfig") - }); + vm.expectRevert(CCIPConfig.TooManySigners.selector); + s_ccipCC.validateConfig(config); + } + + function test__validateConfig_FMustBePositive_Reverts() public { + CCIPConfigTypes.OCR3Config memory config = _getCorrectOCR3Config(); + config.F = 0; // not positive vm.expectRevert(CCIPConfig.FMustBePositive.selector); s_ccipCC.validateConfig(config); } function test__validateConfig_FTooHigh_Reverts() public { - (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); - - CCIPConfigTypes.OCR3Config memory config = CCIPConfigTypes.OCR3Config({ - pluginType: Internal.OCRPluginType.Commit, - offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), - chainSelector: 1, - bootstrapP2PIds: _subset(p2pIds, 0, 1), - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 2, - offchainConfigVersion: 30, - offchainConfig: bytes("offchainConfig") - }); + CCIPConfigTypes.OCR3Config memory config = _getCorrectOCR3Config(); + config.F = 2; // too high vm.expectRevert(CCIPConfig.FTooHigh.selector); s_ccipCC.validateConfig(config); } function test__validateConfig_P2PIdsLengthNotMatching_Reverts() public { - (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); - // truncate the p2pIds length - assembly { - mstore(p2pIds, 3) - } + CCIPConfigTypes.OCR3Config memory config = _getCorrectOCR3Config(); - // Config is for 4 nodes, so f == 1. - CCIPConfigTypes.OCR3Config memory config = CCIPConfigTypes.OCR3Config({ - pluginType: Internal.OCRPluginType.Commit, - offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), - chainSelector: 1, - bootstrapP2PIds: _subset(p2pIds, 0, 1), - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, - offchainConfigVersion: 30, - offchainConfig: bytes("offchainConfig") - }); + uint256 expectedNumberOfP2pIds = config.signers.length; + uint256 wrongNumberOfP2pIds = expectedNumberOfP2pIds - 1; + config.p2pIds = new bytes32[](wrongNumberOfP2pIds); // Not enough vm.expectRevert( - abi.encodeWithSelector(CCIPConfig.P2PIdsLengthNotMatching.selector, uint256(3), uint256(4), uint256(4)) + abi.encodeWithSelector( + CCIPConfig.P2PIdsLengthNotMatching.selector, wrongNumberOfP2pIds, expectedNumberOfP2pIds, expectedNumberOfP2pIds + ) ); s_ccipCC.validateConfig(config); } function test__validateConfig_TooManyBootstrapP2PIds_Reverts() public { - (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); - - // Config is for 4 nodes, so f == 1. - CCIPConfigTypes.OCR3Config memory config = CCIPConfigTypes.OCR3Config({ - pluginType: Internal.OCRPluginType.Commit, - offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), - chainSelector: 1, - bootstrapP2PIds: _makeBytes32Array(5, 0), // too many bootstrap p2pIds, 5 > 4 - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, - offchainConfigVersion: 30, - offchainConfig: bytes("offchainConfig") - }); + CCIPConfigTypes.OCR3Config memory config = _getCorrectOCR3Config(); + config.bootstrapP2PIds = _makeBytes32Array(5, 0); // too many bootstrap p2pIds, 5 > 4 vm.expectRevert(CCIPConfig.TooManyBootstrapP2PIds.selector); s_ccipCC.validateConfig(config); } function test__validateConfig_NodeNotInRegistry_Reverts() public { - (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); + (bytes32[] memory p2pIds,,) = _addChainConfig(4); bytes32 nonExistentP2PId = keccak256("notInRegistry"); p2pIds[0] = nonExistentP2PId; @@ -603,146 +479,65 @@ contract CCIPConfig_validateConfig is CCIPConfigSetup { }) ) ); - - // Config is for 4 nodes, so f == 1. - CCIPConfigTypes.OCR3Config memory config = CCIPConfigTypes.OCR3Config({ - pluginType: Internal.OCRPluginType.Commit, - offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), - chainSelector: 1, - bootstrapP2PIds: _subset(p2pIds, 0, 1), - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, - offchainConfigVersion: 30, - offchainConfig: bytes("offchainConfig") - }); + CCIPConfigTypes.OCR3Config memory config = _getCorrectOCR3Config(); + config.p2pIds = p2pIds; + config.bootstrapP2PIds = _subset(p2pIds, 0, 1); vm.expectRevert(abi.encodeWithSelector(CCIPConfig.NodeNotInRegistry.selector, nonExistentP2PId)); s_ccipCC.validateConfig(config); } function test__validateConfig_P2PIdsNotSorted_Reverts() public { - (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); - // Config is for 4 nodes, so f == 1. + CCIPConfigTypes.OCR3Config memory config = _getCorrectOCR3Config(); //swapping two adjacent p2pIds to make it unsorted - (p2pIds[2], p2pIds[3]) = (p2pIds[3], p2pIds[2]); + (config.p2pIds[2], config.p2pIds[3]) = (config.p2pIds[3], config.p2pIds[2]); - CCIPConfigTypes.OCR3Config memory config = CCIPConfigTypes.OCR3Config({ - pluginType: Internal.OCRPluginType.Commit, - offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), - chainSelector: 1, - bootstrapP2PIds: _subset(p2pIds, 0, 1), - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, - offchainConfigVersion: 30, - offchainConfig: bytes("offchainConfig") - }); - - vm.expectRevert(abi.encodeWithSelector(SortedSetValidationUtil.NotASortedSet.selector, p2pIds)); + vm.expectRevert(abi.encodeWithSelector(SortedSetValidationUtil.NotASortedSet.selector, config.p2pIds)); s_ccipCC.validateConfig(config); } function test__validateConfig_BootstrapP2PIdsNotSorted_Reverts() public { - (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); - // Config is for 4 nodes, so f == 1. - - bytes32[] memory bootstrapP2PIds = _subset(p2pIds, 0, 2); + CCIPConfigTypes.OCR3Config memory config = _getCorrectOCR3Config(); + bytes32[] memory bootstrapP2PIds = _subset(config.p2pIds, 0, 2); //swapping bootstrapP2PIds to make it unsorted (bootstrapP2PIds[0], bootstrapP2PIds[1]) = (bootstrapP2PIds[1], bootstrapP2PIds[0]); - CCIPConfigTypes.OCR3Config memory config = CCIPConfigTypes.OCR3Config({ - pluginType: Internal.OCRPluginType.Commit, - offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), - chainSelector: 1, - bootstrapP2PIds: bootstrapP2PIds, - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, - offchainConfigVersion: 30, - offchainConfig: bytes("offchainConfig") - }); + config.bootstrapP2PIds = bootstrapP2PIds; vm.expectRevert(abi.encodeWithSelector(SortedSetValidationUtil.NotASortedSet.selector, bootstrapP2PIds)); s_ccipCC.validateConfig(config); } function test__validateConfig_P2PIdsHasDuplicates_Reverts() public { - (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); - // Config is for 4 nodes, so f == 1. - + CCIPConfigTypes.OCR3Config memory config = _getCorrectOCR3Config(); //forcing duplicate p2pIds - p2pIds[1] = p2pIds[2]; - - CCIPConfigTypes.OCR3Config memory config = CCIPConfigTypes.OCR3Config({ - pluginType: Internal.OCRPluginType.Commit, - offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), - chainSelector: 1, - bootstrapP2PIds: _subset(p2pIds, 0, 2), - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, - offchainConfigVersion: 30, - offchainConfig: bytes("offchainConfig") - }); + config.p2pIds[1] = config.p2pIds[2]; - vm.expectRevert(abi.encodeWithSelector(SortedSetValidationUtil.NotASortedSet.selector, p2pIds)); + vm.expectRevert(abi.encodeWithSelector(SortedSetValidationUtil.NotASortedSet.selector, config.p2pIds)); s_ccipCC.validateConfig(config); } function test__validateConfig_BootstrapP2PIdsHasDuplicates_Reverts() public { - (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); - // Config is for 4 nodes, so f == 1. - - bytes32[] memory bootstrapP2PIds = _subset(p2pIds, 0, 2); + CCIPConfigTypes.OCR3Config memory config = _getCorrectOCR3Config(); //forcing duplicate bootstrapP2PIds - bootstrapP2PIds[1] = bootstrapP2PIds[0]; - - CCIPConfigTypes.OCR3Config memory config = CCIPConfigTypes.OCR3Config({ - pluginType: Internal.OCRPluginType.Commit, - offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), - chainSelector: 1, - bootstrapP2PIds: bootstrapP2PIds, - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, - offchainConfigVersion: 30, - offchainConfig: bytes("offchainConfig") - }); + config.bootstrapP2PIds = _subset(config.p2pIds, 0, 2); + config.bootstrapP2PIds[1] = config.bootstrapP2PIds[0]; - vm.expectRevert(abi.encodeWithSelector(SortedSetValidationUtil.NotASortedSet.selector, bootstrapP2PIds)); + vm.expectRevert(abi.encodeWithSelector(SortedSetValidationUtil.NotASortedSet.selector, config.bootstrapP2PIds)); s_ccipCC.validateConfig(config); } function test__validateConfig_BootstrapP2PIdsNotASubsetOfP2PIds_Reverts() public { - (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); - // Config is for 4 nodes, so f == 1. - - //forcing invalid bootstrapP2PIds where the bootstrapP2PIds is sorted, but one of the element is not in the p2pIdsSet - bytes32[] memory bootstrapP2PIds = _subset(p2pIds, 0, 2); - p2pIds[1] = bytes32(uint256(p2pIds[0]) + 100); + CCIPConfigTypes.OCR3Config memory config = _getCorrectOCR3Config(); + config.bootstrapP2PIds = _subset(config.p2pIds, 0, 2); + config.p2pIds[1] = bytes32(uint256(config.p2pIds[0]) + 100); - CCIPConfigTypes.OCR3Config memory config = CCIPConfigTypes.OCR3Config({ - pluginType: Internal.OCRPluginType.Commit, - offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), - chainSelector: 1, - bootstrapP2PIds: bootstrapP2PIds, - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, - offchainConfigVersion: 30, - offchainConfig: bytes("offchainConfig") - }); + vm.expectRevert( + abi.encodeWithSelector(SortedSetValidationUtil.NotASubset.selector, config.bootstrapP2PIds, config.p2pIds) + ); - vm.expectRevert(abi.encodeWithSelector(SortedSetValidationUtil.NotASubset.selector, bootstrapP2PIds, p2pIds)); s_ccipCC.validateConfig(config); } } diff --git a/contracts/src/v0.8/ccip/test/ocr/MultiOCR3Base.t.sol b/contracts/src/v0.8/ccip/test/ocr/MultiOCR3Base.t.sol index 5b784bf721..8867d1b127 100644 --- a/contracts/src/v0.8/ccip/test/ocr/MultiOCR3Base.t.sol +++ b/contracts/src/v0.8/ccip/test/ocr/MultiOCR3Base.t.sol @@ -878,7 +878,7 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { function test_TooManyTransmitters_Revert() public { address[] memory signers = new address[](0); - address[] memory transmitters = new address[](32); + address[] memory transmitters = new address[](257); MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ @@ -899,7 +899,7 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { } function test_TooManySigners_Revert() public { - address[] memory signers = new address[](32); + address[] memory signers = new address[](257); MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ diff --git a/core/gethwrappers/ccip/generated/ccip_config/ccip_config.go b/core/gethwrappers/ccip/generated/ccip_config/ccip_config.go index dbbd06ffb5..565e0bff3a 100644 --- a/core/gethwrappers/ccip/generated/ccip_config/ccip_config.go +++ b/core/gethwrappers/ccip/generated/ccip_config/ccip_config.go @@ -61,8 +61,8 @@ type CCIPConfigTypesOCR3ConfigWithMeta struct { } var CCIPConfigMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"capabilitiesRegistry\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainSelectorNotFound\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ChainSelectorNotSet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptySet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FChainMustBePositive\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FMustBePositive\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FTooHigh\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"length\",\"type\":\"uint256\"}],\"name\":\"InvalidConfigLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enumCCIPConfigTypes.ConfigState\",\"name\":\"currentState\",\"type\":\"uint8\"},{\"internalType\":\"enumCCIPConfigTypes.ConfigState\",\"name\":\"proposedState\",\"type\":\"uint8\"}],\"name\":\"InvalidConfigStateTransition\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidPluginType\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"}],\"name\":\"NodeNotInRegistry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonExistentConfigTransition\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"set\",\"type\":\"bytes32[]\"}],\"name\":\"NotASortedSet\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"subset\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"superset\",\"type\":\"bytes32[]\"}],\"name\":\"NotASubset\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"got\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minimum\",\"type\":\"uint256\"}],\"name\":\"NotEnoughTransmitters\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OfframpAddressCannotBeZero\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCapabilitiesRegistryCanCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"p2pIdsLength\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"signersLength\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"transmittersLength\",\"type\":\"uint256\"}],\"name\":\"P2PIdsLengthNotMatching\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManyBootstrapP2PIds\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManyOCR3Configs\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManySigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManyTransmitters\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"got\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"expected\",\"type\":\"uint64\"}],\"name\":\"WrongConfigCount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"got\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"}],\"name\":\"WrongConfigDigest\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"got\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"}],\"name\":\"WrongConfigDigestBlueGreen\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"CapabilityConfigurationSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainConfigRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes32[]\",\"name\":\"readers\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint8\",\"name\":\"fChain\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"structCCIPConfigTypes.ChainConfig\",\"name\":\"chainConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"chainSelectorRemoves\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes32[]\",\"name\":\"readers\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint8\",\"name\":\"fChain\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPConfigTypes.ChainConfig\",\"name\":\"chainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structCCIPConfigTypes.ChainConfigInfo[]\",\"name\":\"chainConfigAdds\",\"type\":\"tuple[]\"}],\"name\":\"applyChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"}],\"name\":\"beforeCapabilityConfigSet\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"pageIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pageSize\",\"type\":\"uint256\"}],\"name\":\"getAllChainConfigs\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes32[]\",\"name\":\"readers\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint8\",\"name\":\"fChain\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPConfigTypes.ChainConfig\",\"name\":\"chainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structCCIPConfigTypes.ChainConfigInfo[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"name\":\"getCapabilityConfiguration\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"configuration\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCapabilityRegistry\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"}],\"name\":\"getOCRConfig\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offrampAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"bootstrapP2PIds\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"p2pIds\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes[]\",\"name\":\"signers\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes[]\",\"name\":\"transmitters\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPConfigTypes.OCR3Config\",\"name\":\"config\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"configCount\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"internalType\":\"structCCIPConfigTypes.OCR3ConfigWithMeta[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x60a06040523480156200001157600080fd5b5060405162004481380380620044818339810160408190526200003491620001a6565b33806000816200008b5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000be57620000be81620000fb565b5050506001600160a01b038116620000e9576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b0316608052620001d8565b336001600160a01b03821603620001555760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000082565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600060208284031215620001b957600080fd5b81516001600160a01b0381168114620001d157600080fd5b9392505050565b608051614280620002016000396000818160f801528181610eff015261116f01526142806000f3fe608060405234801561001057600080fd5b50600436106100c95760003560e01c80638318ed5d11610081578063f2fde38b1161005b578063f2fde38b1461020f578063f442c89a14610222578063fba64a7c1461023557600080fd5b80638318ed5d146101b05780638da5cb5b146101d1578063b74b2356146101ef57600080fd5b8063181f5a77116100b2578063181f5a771461013d5780634bd0473f1461018657806379ba5097146101a657600080fd5b806301ffc9a7146100ce578063020330e6146100f6575b600080fd5b6100e16100dc366004613029565b610248565b60405190151581526020015b60405180910390f35b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100ed565b6101796040518060400160405280601481526020017f43434950436f6e66696720312e362e302d64657600000000000000000000000081525081565b6040516100ed91906130cf565b610199610194366004613113565b6102e1565b6040516100ed9190613232565b6101ae6107b1565b005b6101796101be36600461340f565b5060408051602081019091526000815290565b60005473ffffffffffffffffffffffffffffffffffffffff16610118565b6102026101fd36600461342c565b6108b3565b6040516100ed9190613492565b6101ae61021d366004613522565b610b34565b6101ae6102303660046135a4565b610b48565b6101ae610243366004613628565b610ee7565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f78bea7210000000000000000000000000000000000000000000000000000000014806102db57507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b63ffffffff8216600090815260056020526040812060609183600181111561030b5761030b613148565b600181111561031c5761031c613148565b8152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b828210156107a557600084815260209020604080516101a08101909152600984029091018054829060608201908390829060ff16600181111561038f5761038f613148565b60018111156103a0576103a0613148565b8152815467ffffffffffffffff61010082048116602084015260ff690100000000000000000083041660408401526a01000000000000000000009091041660608201526001820180546080909201916103f8906136e5565b80601f0160208091040260200160405190810160405280929190818152602001828054610424906136e5565b80156104715780601f1061044657610100808354040283529160200191610471565b820191906000526020600020905b81548152906001019060200180831161045457829003601f168201915b50505050508152602001600282018054806020026020016040519081016040528092919081815260200182805480156104c957602002820191906000526020600020905b8154815260200190600101908083116104b5575b505050505081526020016003820180548060200260200160405190810160405280929190818152602001828054801561052157602002820191906000526020600020905b81548152602001906001019080831161050d575b5050505050815260200160048201805480602002602001604051908101604052809291908181526020016000905b828210156105fb57838290600052602060002001805461056e906136e5565b80601f016020809104026020016040519081016040528092919081815260200182805461059a906136e5565b80156105e75780601f106105bc576101008083540402835291602001916105e7565b820191906000526020600020905b8154815290600101906020018083116105ca57829003601f168201915b50505050508152602001906001019061054f565b50505050815260200160058201805480602002602001604051908101604052809291908181526020016000905b828210156106d4578382906000526020600020018054610647906136e5565b80601f0160208091040260200160405190810160405280929190818152602001828054610673906136e5565b80156106c05780601f10610695576101008083540402835291602001916106c0565b820191906000526020600020905b8154815290600101906020018083116106a357829003601f168201915b505050505081526020019060010190610628565b5050505081526020016006820180546106ec906136e5565b80601f0160208091040260200160405190810160405280929190818152602001828054610718906136e5565b80156107655780601f1061073a57610100808354040283529160200191610765565b820191906000526020600020905b81548152906001019060200180831161074857829003601f168201915b505050919092525050508152600782015467ffffffffffffffff16602080830191909152600890920154604090910152908252600192909201910161034a565b50505050905092915050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610837576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b606060006108c16003610fa2565b905060006108cf8486613767565b90508315806108de5750818110155b1561091e576040805160008082526020820190925290610914565b610901612dba565b8152602001906001900390816108f95790505b50925050506102db565b600061092a85836137ad565b9050828111156109375750815b600061094383836137c0565b67ffffffffffffffff81111561095b5761095b61377e565b60405190808252806020026020018201604052801561099457816020015b610981612dba565b8152602001906001900390816109795790505b50905060006109a36003610fac565b9050835b83811015610b275760008282815181106109c3576109c36137d3565b60209081029190910181015160408051808201825267ffffffffffffffff831680825260009081526002855282902082518154608081880283018101909552606082018181529597509295860194909391928492849190840182828015610a4957602002820191906000526020600020905b815481526020019060010190808311610a35575b5050509183525050600182015460ff166020820152600282018054604090920191610a73906136e5565b80601f0160208091040260200160405190810160405280929190818152602001828054610a9f906136e5565b8015610aec5780601f10610ac157610100808354040283529160200191610aec565b820191906000526020600020905b815481529060010190602001808311610acf57829003601f168201915b50505091909252505050905284610b0388856137c0565b81518110610b1357610b136137d3565b6020908102919091010152506001016109a7565b5090979650505050505050565b610b3c610fc0565b610b4581611043565b50565b610b50610fc0565b60005b83811015610d3657610b97858583818110610b7057610b706137d3565b9050602002016020810190610b859190613802565b60039067ffffffffffffffff16611138565b610c0157848482818110610bad57610bad6137d3565b9050602002016020810190610bc29190613802565b6040517f1bd4d2d200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260240161082e565b60026000868684818110610c1757610c176137d3565b9050602002016020810190610c2c9190613802565b67ffffffffffffffff1681526020810191909152604001600090812090610c538282612e02565b6001820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055610c8b600283016000612e20565b5050610cc9858583818110610ca257610ca26137d3565b9050602002016020810190610cb79190613802565b60039067ffffffffffffffff16611150565b507f2a680691fef3b2d105196805935232c661ce703e92d464ef0b94a7bc62d714f0858583818110610cfd57610cfd6137d3565b9050602002016020810190610d129190613802565b60405167ffffffffffffffff909116815260200160405180910390a1600101610b53565b5060005b81811015610ee0576000838383818110610d5657610d566137d3565b9050602002810190610d68919061381d565b610d7690602081019061385b565b610d7f90613a5d565b90506000848484818110610d9557610d956137d3565b9050602002810190610da7919061381d565b610db5906020810190613802565b9050610dc4826000015161115c565b816020015160ff16600003610e05576040517fa9b3766e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff81166000908152600260209081526040909120835180518593610e35928492910190612e5a565b5060208201516001820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff90921691909117905560408201516002820190610e829082613b45565b50610e9c91506003905067ffffffffffffffff83166112a8565b507f05dd57854af2c291a94ea52e7c43d80bc3be7fa73022f98b735dea86642fa5e08183604051610ece929190613c5f565b60405180910390a15050600101610d3a565b5050505050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610f56576040517fac7a7efd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080610f6d610f6886880188613d0a565b6112b4565b8151919350915015610f8557610f858360008461150d565b805115610f9857610f988360018361150d565b5050505050505050565b60006102db825490565b60606000610fb983611ce4565b9392505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611041576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640161082e565b565b3373ffffffffffffffffffffffffffffffffffffffff8216036110c2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161082e565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60008181526001830160205260408120541515610fb9565b6000610fb98383611d40565b60005b81518110156112a45760008019167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166350c946fe8484815181106111bb576111bb6137d3565b60200260200101516040518263ffffffff1660e01b81526004016111e191815260200190565b600060405180830381865afa1580156111fe573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526112449190810190613f7b565b608001510361129c5781818151811061125f5761125f6137d3565b60200260200101516040517f8907a4fa00000000000000000000000000000000000000000000000000000000815260040161082e91815260200190565b60010161115f565b5050565b6000610fb98383611e3a565b606080600460ff16835111156112f6576040517f8854586400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160028082526060820190925290816020015b61137a6040805161014081019091528060008152602001600067ffffffffffffffff168152602001600060ff168152602001600067ffffffffffffffff1681526020016060815260200160608152602001606081526020016060815260200160608152602001606081525090565b81526020019060019003908161130c57505060408051600280825260608201909252919350602082015b6114126040805161014081019091528060008152602001600067ffffffffffffffff168152602001600060ff168152602001600067ffffffffffffffff1681526020016060815260200160608152602001606081526020016060815260200160608152602001606081525090565b8152602001906001900390816113a457905050905060008060005b855181101561150057600086828151811061144a5761144a6137d3565b602002602001015160000151600181111561146757611467613148565b036114b45785818151811061147e5761147e6137d3565b6020026020010151858481518110611498576114986137d3565b6020026020010181905250826114ad90614053565b92506114f8565b8581815181106114c6576114c66137d3565b60200260200101518483815181106114e0576114e06137d3565b6020026020010181905250816114f590614053565b91505b60010161142d565b5090835281529092909150565b63ffffffff831660009081526005602052604081208184600181111561153557611535613148565b600181111561154657611546613148565b8152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b828210156119cf57600084815260209020604080516101a08101909152600984029091018054829060608201908390829060ff1660018111156115b9576115b9613148565b60018111156115ca576115ca613148565b8152815467ffffffffffffffff61010082048116602084015260ff690100000000000000000083041660408401526a0100000000000000000000909104166060820152600182018054608090920191611622906136e5565b80601f016020809104026020016040519081016040528092919081815260200182805461164e906136e5565b801561169b5780601f106116705761010080835404028352916020019161169b565b820191906000526020600020905b81548152906001019060200180831161167e57829003601f168201915b50505050508152602001600282018054806020026020016040519081016040528092919081815260200182805480156116f357602002820191906000526020600020905b8154815260200190600101908083116116df575b505050505081526020016003820180548060200260200160405190810160405280929190818152602001828054801561174b57602002820191906000526020600020905b815481526020019060010190808311611737575b5050505050815260200160048201805480602002602001604051908101604052809291908181526020016000905b82821015611825578382906000526020600020018054611798906136e5565b80601f01602080910402602001604051908101604052809291908181526020018280546117c4906136e5565b80156118115780601f106117e657610100808354040283529160200191611811565b820191906000526020600020905b8154815290600101906020018083116117f457829003601f168201915b505050505081526020019060010190611779565b50505050815260200160058201805480602002602001604051908101604052809291908181526020016000905b828210156118fe578382906000526020600020018054611871906136e5565b80601f016020809104026020016040519081016040528092919081815260200182805461189d906136e5565b80156118ea5780601f106118bf576101008083540402835291602001916118ea565b820191906000526020600020905b8154815290600101906020018083116118cd57829003601f168201915b505050505081526020019060010190611852565b505050508152602001600682018054611916906136e5565b80601f0160208091040260200160405190810160405280929190818152602001828054611942906136e5565b801561198f5780601f106119645761010080835404028352916020019161198f565b820191906000526020600020905b81548152906001019060200180831161197257829003601f168201915b505050919092525050508152600782015467ffffffffffffffff166020808301919091526008909201546040909101529082526001929092019101611574565b50505050905060006119e18251611e89565b905060006119ef8451611e89565b90506119fb8282611edb565b6000611a0a8785878686611f97565b9050611a168482612383565b63ffffffff8716600090815260056020526040812090876001811115611a3e57611a3e613148565b6001811115611a4f57611a4f613148565b81526020019081526020016000206000611a699190612ea5565b60005b8151811015610f985763ffffffff8816600090815260056020526040812090886001811115611a9d57611a9d613148565b6001811115611aae57611aae613148565b8152602001908152602001600020828281518110611ace57611ace6137d3565b6020908102919091018101518254600181810185556000948552929093208151805160099095029091018054929490939192849283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016908381811115611b3857611b38613148565b021790555060208201518154604084015160608501517fffffffffffffffffffffffffffffffffffffffffffff000000000000000000ff90921661010067ffffffffffffffff948516027fffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffff1617690100000000000000000060ff90921691909102177fffffffffffffffffffffffffffff0000000000000000ffffffffffffffffffff166a0100000000000000000000929091169190910217815560808201516001820190611c079082613b45565b5060a08201518051611c23916002840191602090910190612e5a565b5060c08201518051611c3f916003840191602090910190612e5a565b5060e08201518051611c5b916004840191602090910190612ec6565b506101008201518051611c78916005840191602090910190612ec6565b506101208201516006820190611c8e9082613b45565b50505060208201516007820180547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff909216919091179055604090910151600890910155600101611a6c565b606081600001805480602002602001604051908101604052809291908181526020018280548015611d3457602002820191906000526020600020905b815481526020019060010190808311611d20575b50505050509050919050565b60008181526001830160205260408120548015611e29576000611d646001836137c0565b8554909150600090611d78906001906137c0565b9050808214611ddd576000866000018281548110611d9857611d986137d3565b9060005260206000200154905080876000018481548110611dbb57611dbb6137d3565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080611dee57611dee61408b565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506102db565b60009150506102db565b5092915050565b6000818152600183016020526040812054611e81575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556102db565b5060006102db565b60006002821115611ec9576040517f3e4785260000000000000000000000000000000000000000000000000000000081526004810183905260240161082e565b8160028111156102db576102db613148565b6000826002811115611eef57611eef613148565b826002811115611f0157611f01613148565b611f0b91906140ba565b90508060011480611f575750807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff148015611f5757506002836002811115611f5557611f55613148565b145b15611f6157505050565b82826040517f0a6b675b00000000000000000000000000000000000000000000000000000000815260040161082e9291906140ea565b60606000845167ffffffffffffffff811115611fb557611fb561377e565b604051908082528060200260200182016040528015611fde578160200160208202803683370190505b5090506000846002811115611ff557611ff5613148565b1480156120135750600183600281111561201157612011613148565b145b156120545760018160008151811061202d5761202d6137d3565b602002602001019067ffffffffffffffff16908167ffffffffffffffff16815250506121bc565b600184600281111561206857612068613148565b1480156120865750600283600281111561208457612084613148565b145b1561211d578560008151811061209e5761209e6137d3565b602002602001015160200151816000815181106120bd576120bd6137d3565b602002602001019067ffffffffffffffff16908167ffffffffffffffff1681525050856000815181106120f2576120f26137d3565b602002602001015160200151600161210a9190614105565b8160018151811061202d5761202d6137d3565b600284600281111561213157612131613148565b14801561214f5750600183600281111561214d5761214d613148565b145b156121865785600181518110612167576121676137d3565b6020026020010151602001518160008151811061202d5761202d6137d3565b83836040517f0a6b675b00000000000000000000000000000000000000000000000000000000815260040161082e9291906140ea565b6000855167ffffffffffffffff8111156121d8576121d861377e565b60405190808252806020026020018201604052801561228e57816020015b604080516101a081018252600060608083018281526080840183905260a0840183905260c0840183905260e084018290526101008401829052610120840182905261014084018290526101608401829052610180840191909152825260208083018290529282015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816121f65790505b50905060005b8251811015612377576122bf8782815181106122b2576122b26137d3565b6020026020010151612702565b60405180606001604052808883815181106122dc576122dc6137d3565b602002602001015181526020018483815181106122fb576122fb6137d3565b602002602001015167ffffffffffffffff16815260200161234f8b868581518110612328576123286137d3565b60200260200101518b8681518110612342576123426137d3565b6020026020010151612adf565b815250828281518110612364576123646137d3565b6020908102919091010152600101612294565b50979650505050505050565b81518151811580156123955750806001145b1561243757826000815181106123ad576123ad6137d3565b60200260200101516020015167ffffffffffffffff1660011461243157826000815181106123dd576123dd6137d3565b60209081029190910181015101516040517fc1658eb800000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526001602482015260440161082e565b50505050565b8160011480156124475750806002145b156125fd578360008151811061245f5761245f6137d3565b6020026020010151604001518360008151811061247e5761247e6137d3565b6020026020010151604001511461250a57826000815181106124a2576124a26137d3565b602002602001015160400151846000815181106124c1576124c16137d3565b6020026020010151604001516040517fc7ccdd7f00000000000000000000000000000000000000000000000000000000815260040161082e929190918252602082015260400190565b8360008151811061251d5761251d6137d3565b60200260200101516020015160016125359190614105565b67ffffffffffffffff1683600181518110612552576125526137d3565b60200260200101516020015167ffffffffffffffff16146124315782600181518110612580576125806137d3565b6020026020010151602001518460008151811061259f5761259f6137d3565b60200260200101516020015160016125b79190614105565b6040517fc1658eb800000000000000000000000000000000000000000000000000000000815267ffffffffffffffff92831660048201529116602482015260440161082e565b81600214801561260d5750806001145b156126d05783600181518110612625576126256137d3565b60200260200101516040015183600081518110612644576126446137d3565b602002602001015160400151146124315782600081518110612668576126686137d3565b60200260200101516040015184600181518110612687576126876137d3565b6020026020010151604001516040517f9e97567000000000000000000000000000000000000000000000000000000000815260040161082e929190918252602082015260400190565b6040517f1f1b2bb600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806020015167ffffffffffffffff1660000361274a576040517f698cf8e000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008151600181111561275f5761275f613148565b14158015612780575060018151600181111561277d5761277d613148565b14155b156127b7576040517f3302dbd700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8060800151516000036127f6576040517f358c192700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208101516128119060039067ffffffffffffffff16611138565b6128595760208101516040517f1bd4d2d200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260240161082e565b60e081015151601f1015612899576040517f1b925da600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61010081015151601f10156128da576040517f645960ff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208082015167ffffffffffffffff1660009081526002909152604081206001015461290a9060ff166003614126565b612915906001614142565b60ff1690508082610100015151101561296c57610100820151516040517f548dd21f00000000000000000000000000000000000000000000000000000000815260048101919091526024810182905260440161082e565b816040015160ff166000036129ad576040517f39d1a4d000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408201516129bd906003614126565b60ff168260e0015151116129fd576040517f4856694e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8160e00151518260c0015151141580612a215750816101000151518260c001515114155b15612a7c5760c08201515160e083015151610100840151516040517fba900f6d00000000000000000000000000000000000000000000000000000000815260048101939093526024830191909152604482015260640161082e565b8160c00151518260a00151511115612ac0576040517f8473d80700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612ad28260a001518360c00151612bb4565b6112a48260c0015161115c565b60008082602001518584600001518560800151878760a001518860c001518960e001518a61010001518b604001518c606001518d6101200151604051602001612b339c9b9a9998979695949392919061415b565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e0a000000000000000000000000000000000000000000000000000000000000179150509392505050565b81511580612bc157508051155b15612bf8576040517fe249684100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612c0182612d2f565b612c0a81612d2f565b6000805b835182108015612c1e5750825181105b15612cf057828181518110612c3557612c356137d3565b6020026020010151848381518110612c4f57612c4f6137d3565b60200260200101511115612c6d57612c6681614053565b9050612c0e565b828181518110612c7f57612c7f6137d3565b6020026020010151848381518110612c9957612c996137d3565b602002602001015103612cba57612caf82614053565b9150612c6681614053565b83836040517fd671700c00000000000000000000000000000000000000000000000000000000815260040161082e92919061423b565b83518210156124315783836040517fd671700c00000000000000000000000000000000000000000000000000000000815260040161082e92919061423b565b60015b81518110156112a45781612d476001836137c0565b81518110612d5757612d576137d3565b6020026020010151828281518110612d7157612d716137d3565b602002602001015111612db257816040517f1bc41b4200000000000000000000000000000000000000000000000000000000815260040161082e9190614260565b600101612d32565b6040518060400160405280600067ffffffffffffffff168152602001612dfd604051806060016040528060608152602001600060ff168152602001606081525090565b905290565b5080546000825590600052602060002090810190610b459190612f18565b508054612e2c906136e5565b6000825580601f10612e3c575050565b601f016020900490600052602060002090810190610b459190612f18565b828054828255906000526020600020908101928215612e95579160200282015b82811115612e95578251825591602001919060010190612e7a565b50612ea1929150612f18565b5090565b5080546000825560090290600052602060002090810190610b459190612f2d565b828054828255906000526020600020908101928215612f0c579160200282015b82811115612f0c5782518290612efc9082613b45565b5091602001919060010190612ee6565b50612ea1929150612fee565b5b80821115612ea15760008155600101612f19565b80821115612ea15780547fffffffffffffffffffffffffffff00000000000000000000000000000000000016815560008181612f6c6001830182612e20565b612f7a600283016000612e02565b612f88600383016000612e02565b612f9660048301600061300b565b612fa460058301600061300b565b612fb2600683016000612e20565b5050506007810180547fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000016905560006008820155600901612f2d565b80821115612ea15760006130028282612e20565b50600101612fee565b5080546000825590600052602060002090810190610b459190612fee565b60006020828403121561303b57600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610fb957600080fd5b6000815180845260005b8181101561309157602081850181015186830182015201613075565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000610fb9602083018461306b565b63ffffffff81168114610b4557600080fd5b80356130ff816130e2565b919050565b8035600281106130ff57600080fd5b6000806040838503121561312657600080fd5b8235613131816130e2565b915061313f60208401613104565b90509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6002811061318757613187613148565b9052565b60008151808452602080850194506020840160005b838110156131bc578151875295820195908201906001016131a0565b509495945050505050565b60008282518085526020808601955060208260051b8401016020860160005b84811015610b27577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe086840301895261322083835161306b565b988401989250908301906001016131e6565b600060208083018184528085518083526040925060408601915060408160051b87010184880160005b83811015613401577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08984030185528151606081518186526132a08287018251613177565b8981015160806132bb8189018367ffffffffffffffff169052565b8a830151915060a06132d1818a018460ff169052565b938301519360c092506132ef8984018667ffffffffffffffff169052565b818401519450610140915060e082818b015261330f6101a08b018761306b565b95508185015191507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0610100818c890301818d015261334e888561318b565b97508587015195506101209350818c890301848d015261336e888761318b565b9750828701519550818c890301858d015261338988876131c7565b975080870151955050808b8803016101608c01526133a787866131c7565b9650828601519550808b8803016101808c015250505050506133c9828261306b565b915050888201516133e58a87018267ffffffffffffffff169052565b509087015193870193909352938601939086019060010161325b565b509098975050505050505050565b60006020828403121561342157600080fd5b8135610fb9816130e2565b6000806040838503121561343f57600080fd5b50508035926020909101359150565b6000815160608452613463606085018261318b565b905060ff602084015116602085015260408301518482036040860152613489828261306b565b95945050505050565b600060208083018184528085518083526040925060408601915060408160051b87010184880160005b83811015613401578883037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00185528151805167ffffffffffffffff16845287015187840187905261350f8785018261344e565b95880195935050908601906001016134bb565b60006020828403121561353457600080fd5b813573ffffffffffffffffffffffffffffffffffffffff81168114610fb957600080fd5b60008083601f84011261356a57600080fd5b50813567ffffffffffffffff81111561358257600080fd5b6020830191508360208260051b850101111561359d57600080fd5b9250929050565b600080600080604085870312156135ba57600080fd5b843567ffffffffffffffff808211156135d257600080fd5b6135de88838901613558565b909650945060208701359150808211156135f757600080fd5b5061360487828801613558565b95989497509550505050565b803567ffffffffffffffff811681146130ff57600080fd5b6000806000806000806080878903121561364157600080fd5b863567ffffffffffffffff8082111561365957600080fd5b6136658a838b01613558565b9098509650602089013591508082111561367e57600080fd5b818901915089601f83011261369257600080fd5b8135818111156136a157600080fd5b8a60208285010111156136b357600080fd5b6020830196508095505050506136cb60408801613610565b91506136d9606088016130f4565b90509295509295509295565b600181811c908216806136f957607f821691505b602082108103613732577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80820281158282048414176102db576102db613738565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b808201808211156102db576102db613738565b818103818111156102db576102db613738565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561381457600080fd5b610fb982613610565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc183360301811261385157600080fd5b9190910192915050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa183360301811261385157600080fd5b604051610140810167ffffffffffffffff811182821017156138b3576138b361377e565b60405290565b60405160e0810167ffffffffffffffff811182821017156138b3576138b361377e565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156139235761392361377e565b604052919050565b600067ffffffffffffffff8211156139455761394561377e565b5060051b60200190565b600082601f83011261396057600080fd5b813560206139756139708361392b565b6138dc565b8083825260208201915060208460051b87010193508684111561399757600080fd5b602086015b848110156139b3578035835291830191830161399c565b509695505050505050565b803560ff811681146130ff57600080fd5b600082601f8301126139e057600080fd5b813567ffffffffffffffff8111156139fa576139fa61377e565b613a2b60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016138dc565b818152846020838601011115613a4057600080fd5b816020850160208301376000918101602001919091529392505050565b600060608236031215613a6f57600080fd5b6040516060810167ffffffffffffffff8282108183111715613a9357613a9361377e565b816040528435915080821115613aa857600080fd5b613ab43683870161394f565b8352613ac2602086016139be565b60208401526040850135915080821115613adb57600080fd5b50613ae8368286016139cf565b60408301525092915050565b601f821115613b40576000816000526020600020601f850160051c81016020861015613b1d5750805b601f850160051c820191505b81811015613b3c57828155600101613b29565b5050505b505050565b815167ffffffffffffffff811115613b5f57613b5f61377e565b613b7381613b6d84546136e5565b84613af4565b602080601f831160018114613bc65760008415613b905750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555613b3c565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015613c1357888601518255948401946001909101908401613bf4565b5085821015613c4f57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b67ffffffffffffffff83168152604060208201526000613c82604083018461344e565b949350505050565b600082601f830112613c9b57600080fd5b81356020613cab6139708361392b565b82815260059290921b84018101918181019086841115613cca57600080fd5b8286015b848110156139b357803567ffffffffffffffff811115613cee5760008081fd5b613cfc8986838b01016139cf565b845250918301918301613cce565b60006020808385031215613d1d57600080fd5b823567ffffffffffffffff80821115613d3557600080fd5b818501915085601f830112613d4957600080fd5b8135613d576139708261392b565b81815260059190911b83018401908481019088831115613d7657600080fd5b8585015b83811015613f0457803585811115613d9157600080fd5b8601610140818c037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0011215613dc657600080fd5b613dce61388f565b613dd9898301613104565b8152613de760408301613610565b89820152613df7606083016139be565b6040820152613e0860808301613610565b606082015260a082013587811115613e1f57600080fd5b613e2d8d8b838601016139cf565b60808301525060c082013587811115613e4557600080fd5b613e538d8b8386010161394f565b60a08301525060e082013587811115613e6b57600080fd5b613e798d8b8386010161394f565b60c0830152506101008083013588811115613e9357600080fd5b613ea18e8c83870101613c8a565b60e0840152506101208084013589811115613ebb57600080fd5b613ec98f8d83880101613c8a565b8385015250610140840135915088821115613ee357600080fd5b613ef18e8c848701016139cf565b9083015250845250918601918601613d7a565b5098975050505050505050565b80516130ff816130e2565b600082601f830112613f2d57600080fd5b81516020613f3d6139708361392b565b8083825260208201915060208460051b870101935086841115613f5f57600080fd5b602086015b848110156139b35780518352918301918301613f64565b600060208284031215613f8d57600080fd5b815167ffffffffffffffff80821115613fa557600080fd5b9083019060e08286031215613fb957600080fd5b613fc16138b9565b613fca83613f11565b8152613fd860208401613f11565b6020820152613fe960408401613f11565b6040820152606083015160608201526080830151608082015260a08301518281111561401457600080fd5b61402087828601613f1c565b60a08301525060c08301518281111561403857600080fd5b61404487828601613f1c565b60c08301525095945050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361408457614084613738565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b8181036000831280158383131683831282161715611e3357611e33613738565b6003811061318757613187613148565b604081016140f882856140da565b610fb960208301846140da565b67ffffffffffffffff818116838216019080821115611e3357611e33613738565b60ff8181168382160290811690818114611e3357611e33613738565b60ff81811683821601908111156102db576102db613738565b67ffffffffffffffff8d16815263ffffffff8c166020820152614181604082018c613177565b6101806060820152600061419961018083018c61306b565b67ffffffffffffffff8b16608084015282810360a08401526141bb818b61318b565b905082810360c08401526141cf818a61318b565b905082810360e08401526141e381896131c7565b90508281036101008401526141f881886131c7565b60ff8716610120850152905067ffffffffffffffff8516610140840152828103610160840152614228818561306b565b9f9e505050505050505050505050505050565b60408152600061424e604083018561318b565b8281036020840152613489818561318b565b602081526000610fb9602083018461318b56fea164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"capabilitiesRegistry\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainSelectorNotFound\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ChainSelectorNotSet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptySet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FChainMustBePositive\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FMustBePositive\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FTooHigh\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"length\",\"type\":\"uint256\"}],\"name\":\"InvalidConfigLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enumCCIPConfigTypes.ConfigState\",\"name\":\"currentState\",\"type\":\"uint8\"},{\"internalType\":\"enumCCIPConfigTypes.ConfigState\",\"name\":\"proposedState\",\"type\":\"uint8\"}],\"name\":\"InvalidConfigStateTransition\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidPluginType\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"}],\"name\":\"NodeNotInRegistry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonExistentConfigTransition\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"set\",\"type\":\"bytes32[]\"}],\"name\":\"NotASortedSet\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"subset\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"superset\",\"type\":\"bytes32[]\"}],\"name\":\"NotASubset\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"got\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minimum\",\"type\":\"uint256\"}],\"name\":\"NotEnoughTransmitters\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OfframpAddressCannotBeZero\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCapabilitiesRegistryCanCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"p2pIdsLength\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"signersLength\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"transmittersLength\",\"type\":\"uint256\"}],\"name\":\"P2PIdsLengthNotMatching\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManyBootstrapP2PIds\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManyOCR3Configs\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManySigners\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"got\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"expected\",\"type\":\"uint64\"}],\"name\":\"WrongConfigCount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"got\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"}],\"name\":\"WrongConfigDigest\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"got\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"}],\"name\":\"WrongConfigDigestBlueGreen\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"CapabilityConfigurationSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainConfigRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes32[]\",\"name\":\"readers\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint8\",\"name\":\"fChain\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"structCCIPConfigTypes.ChainConfig\",\"name\":\"chainConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"chainSelectorRemoves\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes32[]\",\"name\":\"readers\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint8\",\"name\":\"fChain\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPConfigTypes.ChainConfig\",\"name\":\"chainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structCCIPConfigTypes.ChainConfigInfo[]\",\"name\":\"chainConfigAdds\",\"type\":\"tuple[]\"}],\"name\":\"applyChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"}],\"name\":\"beforeCapabilityConfigSet\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"pageIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pageSize\",\"type\":\"uint256\"}],\"name\":\"getAllChainConfigs\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes32[]\",\"name\":\"readers\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint8\",\"name\":\"fChain\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPConfigTypes.ChainConfig\",\"name\":\"chainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structCCIPConfigTypes.ChainConfigInfo[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"name\":\"getCapabilityConfiguration\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"configuration\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCapabilityRegistry\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"}],\"name\":\"getOCRConfig\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offrampAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"bootstrapP2PIds\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"p2pIds\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes[]\",\"name\":\"signers\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes[]\",\"name\":\"transmitters\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPConfigTypes.OCR3Config\",\"name\":\"config\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"configCount\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"internalType\":\"structCCIPConfigTypes.OCR3ConfigWithMeta[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x60a06040523480156200001157600080fd5b506040516200446c3803806200446c8339810160408190526200003491620001a6565b33806000816200008b5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000be57620000be81620000fb565b5050506001600160a01b038116620000e9576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b0316608052620001d8565b336001600160a01b03821603620001555760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000082565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600060208284031215620001b957600080fd5b81516001600160a01b0381168114620001d157600080fd5b9392505050565b60805161426b620002016000396000818160f801528181610eff015261116f015261426b6000f3fe608060405234801561001057600080fd5b50600436106100c95760003560e01c80638318ed5d11610081578063f2fde38b1161005b578063f2fde38b1461020f578063f442c89a14610222578063fba64a7c1461023557600080fd5b80638318ed5d146101b05780638da5cb5b146101d1578063b74b2356146101ef57600080fd5b8063181f5a77116100b2578063181f5a771461013d5780634bd0473f1461018657806379ba5097146101a657600080fd5b806301ffc9a7146100ce578063020330e6146100f6575b600080fd5b6100e16100dc366004613015565b610248565b60405190151581526020015b60405180910390f35b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100ed565b6101796040518060400160405280601481526020017f43434950436f6e66696720312e362e302d64657600000000000000000000000081525081565b6040516100ed91906130bb565b6101996101943660046130ff565b6102e1565b6040516100ed919061321e565b6101ae6107b1565b005b6101796101be3660046133fb565b5060408051602081019091526000815290565b60005473ffffffffffffffffffffffffffffffffffffffff16610118565b6102026101fd366004613418565b6108b3565b6040516100ed919061347e565b6101ae61021d36600461350e565b610b34565b6101ae610230366004613590565b610b48565b6101ae610243366004613614565b610ee7565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f78bea7210000000000000000000000000000000000000000000000000000000014806102db57507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b63ffffffff8216600090815260056020526040812060609183600181111561030b5761030b613134565b600181111561031c5761031c613134565b8152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b828210156107a557600084815260209020604080516101a08101909152600984029091018054829060608201908390829060ff16600181111561038f5761038f613134565b60018111156103a0576103a0613134565b8152815467ffffffffffffffff61010082048116602084015260ff690100000000000000000083041660408401526a01000000000000000000009091041660608201526001820180546080909201916103f8906136d1565b80601f0160208091040260200160405190810160405280929190818152602001828054610424906136d1565b80156104715780601f1061044657610100808354040283529160200191610471565b820191906000526020600020905b81548152906001019060200180831161045457829003601f168201915b50505050508152602001600282018054806020026020016040519081016040528092919081815260200182805480156104c957602002820191906000526020600020905b8154815260200190600101908083116104b5575b505050505081526020016003820180548060200260200160405190810160405280929190818152602001828054801561052157602002820191906000526020600020905b81548152602001906001019080831161050d575b5050505050815260200160048201805480602002602001604051908101604052809291908181526020016000905b828210156105fb57838290600052602060002001805461056e906136d1565b80601f016020809104026020016040519081016040528092919081815260200182805461059a906136d1565b80156105e75780601f106105bc576101008083540402835291602001916105e7565b820191906000526020600020905b8154815290600101906020018083116105ca57829003601f168201915b50505050508152602001906001019061054f565b50505050815260200160058201805480602002602001604051908101604052809291908181526020016000905b828210156106d4578382906000526020600020018054610647906136d1565b80601f0160208091040260200160405190810160405280929190818152602001828054610673906136d1565b80156106c05780601f10610695576101008083540402835291602001916106c0565b820191906000526020600020905b8154815290600101906020018083116106a357829003601f168201915b505050505081526020019060010190610628565b5050505081526020016006820180546106ec906136d1565b80601f0160208091040260200160405190810160405280929190818152602001828054610718906136d1565b80156107655780601f1061073a57610100808354040283529160200191610765565b820191906000526020600020905b81548152906001019060200180831161074857829003601f168201915b505050919092525050508152600782015467ffffffffffffffff16602080830191909152600890920154604090910152908252600192909201910161034a565b50505050905092915050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610837576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b606060006108c16003610fa2565b905060006108cf8486613753565b90508315806108de5750818110155b1561091e576040805160008082526020820190925290610914565b610901612da6565b8152602001906001900390816108f95790505b50925050506102db565b600061092a8583613799565b9050828111156109375750815b600061094383836137ac565b67ffffffffffffffff81111561095b5761095b61376a565b60405190808252806020026020018201604052801561099457816020015b610981612da6565b8152602001906001900390816109795790505b50905060006109a36003610fac565b9050835b83811015610b275760008282815181106109c3576109c36137bf565b60209081029190910181015160408051808201825267ffffffffffffffff831680825260009081526002855282902082518154608081880283018101909552606082018181529597509295860194909391928492849190840182828015610a4957602002820191906000526020600020905b815481526020019060010190808311610a35575b5050509183525050600182015460ff166020820152600282018054604090920191610a73906136d1565b80601f0160208091040260200160405190810160405280929190818152602001828054610a9f906136d1565b8015610aec5780601f10610ac157610100808354040283529160200191610aec565b820191906000526020600020905b815481529060010190602001808311610acf57829003601f168201915b50505091909252505050905284610b0388856137ac565b81518110610b1357610b136137bf565b6020908102919091010152506001016109a7565b5090979650505050505050565b610b3c610fc0565b610b4581611043565b50565b610b50610fc0565b60005b83811015610d3657610b97858583818110610b7057610b706137bf565b9050602002016020810190610b8591906137ee565b60039067ffffffffffffffff16611138565b610c0157848482818110610bad57610bad6137bf565b9050602002016020810190610bc291906137ee565b6040517f1bd4d2d200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260240161082e565b60026000868684818110610c1757610c176137bf565b9050602002016020810190610c2c91906137ee565b67ffffffffffffffff1681526020810191909152604001600090812090610c538282612dee565b6001820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055610c8b600283016000612e0c565b5050610cc9858583818110610ca257610ca26137bf565b9050602002016020810190610cb791906137ee565b60039067ffffffffffffffff16611150565b507f2a680691fef3b2d105196805935232c661ce703e92d464ef0b94a7bc62d714f0858583818110610cfd57610cfd6137bf565b9050602002016020810190610d1291906137ee565b60405167ffffffffffffffff909116815260200160405180910390a1600101610b53565b5060005b81811015610ee0576000838383818110610d5657610d566137bf565b9050602002810190610d689190613809565b610d76906020810190613847565b610d7f90613a49565b90506000848484818110610d9557610d956137bf565b9050602002810190610da79190613809565b610db59060208101906137ee565b9050610dc4826000015161115c565b816020015160ff16600003610e05576040517fa9b3766e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff81166000908152600260209081526040909120835180518593610e35928492910190612e46565b5060208201516001820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff90921691909117905560408201516002820190610e829082613b30565b50610e9c91506003905067ffffffffffffffff83166112a8565b507f05dd57854af2c291a94ea52e7c43d80bc3be7fa73022f98b735dea86642fa5e08183604051610ece929190613c4a565b60405180910390a15050600101610d3a565b5050505050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610f56576040517fac7a7efd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080610f6d610f6886880188613cf5565b6112b4565b8151919350915015610f8557610f858360008461150d565b805115610f9857610f988360018361150d565b5050505050505050565b60006102db825490565b60606000610fb983611ce4565b9392505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611041576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640161082e565b565b3373ffffffffffffffffffffffffffffffffffffffff8216036110c2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161082e565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60008181526001830160205260408120541515610fb9565b6000610fb98383611d40565b60005b81518110156112a45760008019167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166350c946fe8484815181106111bb576111bb6137bf565b60200260200101516040518263ffffffff1660e01b81526004016111e191815260200190565b600060405180830381865afa1580156111fe573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526112449190810190613f66565b608001510361129c5781818151811061125f5761125f6137bf565b60200260200101516040517f8907a4fa00000000000000000000000000000000000000000000000000000000815260040161082e91815260200190565b60010161115f565b5050565b6000610fb98383611e3a565b606080600460ff16835111156112f6576040517f8854586400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160028082526060820190925290816020015b61137a6040805161014081019091528060008152602001600067ffffffffffffffff168152602001600060ff168152602001600067ffffffffffffffff1681526020016060815260200160608152602001606081526020016060815260200160608152602001606081525090565b81526020019060019003908161130c57505060408051600280825260608201909252919350602082015b6114126040805161014081019091528060008152602001600067ffffffffffffffff168152602001600060ff168152602001600067ffffffffffffffff1681526020016060815260200160608152602001606081526020016060815260200160608152602001606081525090565b8152602001906001900390816113a457905050905060008060005b855181101561150057600086828151811061144a5761144a6137bf565b602002602001015160000151600181111561146757611467613134565b036114b45785818151811061147e5761147e6137bf565b6020026020010151858481518110611498576114986137bf565b6020026020010181905250826114ad9061403e565b92506114f8565b8581815181106114c6576114c66137bf565b60200260200101518483815181106114e0576114e06137bf565b6020026020010181905250816114f59061403e565b91505b60010161142d565b5090835281529092909150565b63ffffffff831660009081526005602052604081208184600181111561153557611535613134565b600181111561154657611546613134565b8152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b828210156119cf57600084815260209020604080516101a08101909152600984029091018054829060608201908390829060ff1660018111156115b9576115b9613134565b60018111156115ca576115ca613134565b8152815467ffffffffffffffff61010082048116602084015260ff690100000000000000000083041660408401526a0100000000000000000000909104166060820152600182018054608090920191611622906136d1565b80601f016020809104026020016040519081016040528092919081815260200182805461164e906136d1565b801561169b5780601f106116705761010080835404028352916020019161169b565b820191906000526020600020905b81548152906001019060200180831161167e57829003601f168201915b50505050508152602001600282018054806020026020016040519081016040528092919081815260200182805480156116f357602002820191906000526020600020905b8154815260200190600101908083116116df575b505050505081526020016003820180548060200260200160405190810160405280929190818152602001828054801561174b57602002820191906000526020600020905b815481526020019060010190808311611737575b5050505050815260200160048201805480602002602001604051908101604052809291908181526020016000905b82821015611825578382906000526020600020018054611798906136d1565b80601f01602080910402602001604051908101604052809291908181526020018280546117c4906136d1565b80156118115780601f106117e657610100808354040283529160200191611811565b820191906000526020600020905b8154815290600101906020018083116117f457829003601f168201915b505050505081526020019060010190611779565b50505050815260200160058201805480602002602001604051908101604052809291908181526020016000905b828210156118fe578382906000526020600020018054611871906136d1565b80601f016020809104026020016040519081016040528092919081815260200182805461189d906136d1565b80156118ea5780601f106118bf576101008083540402835291602001916118ea565b820191906000526020600020905b8154815290600101906020018083116118cd57829003601f168201915b505050505081526020019060010190611852565b505050508152602001600682018054611916906136d1565b80601f0160208091040260200160405190810160405280929190818152602001828054611942906136d1565b801561198f5780601f106119645761010080835404028352916020019161198f565b820191906000526020600020905b81548152906001019060200180831161197257829003601f168201915b505050919092525050508152600782015467ffffffffffffffff166020808301919091526008909201546040909101529082526001929092019101611574565b50505050905060006119e18251611e89565b905060006119ef8451611e89565b90506119fb8282611edb565b6000611a0a8785878686611f97565b9050611a168482612383565b63ffffffff8716600090815260056020526040812090876001811115611a3e57611a3e613134565b6001811115611a4f57611a4f613134565b81526020019081526020016000206000611a699190612e91565b60005b8151811015610f985763ffffffff8816600090815260056020526040812090886001811115611a9d57611a9d613134565b6001811115611aae57611aae613134565b8152602001908152602001600020828281518110611ace57611ace6137bf565b6020908102919091018101518254600181810185556000948552929093208151805160099095029091018054929490939192849283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016908381811115611b3857611b38613134565b021790555060208201518154604084015160608501517fffffffffffffffffffffffffffffffffffffffffffff000000000000000000ff90921661010067ffffffffffffffff948516027fffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffff1617690100000000000000000060ff90921691909102177fffffffffffffffffffffffffffff0000000000000000ffffffffffffffffffff166a0100000000000000000000929091169190910217815560808201516001820190611c079082613b30565b5060a08201518051611c23916002840191602090910190612e46565b5060c08201518051611c3f916003840191602090910190612e46565b5060e08201518051611c5b916004840191602090910190612eb2565b506101008201518051611c78916005840191602090910190612eb2565b506101208201516006820190611c8e9082613b30565b50505060208201516007820180547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff909216919091179055604090910151600890910155600101611a6c565b606081600001805480602002602001604051908101604052809291908181526020018280548015611d3457602002820191906000526020600020905b815481526020019060010190808311611d20575b50505050509050919050565b60008181526001830160205260408120548015611e29576000611d646001836137ac565b8554909150600090611d78906001906137ac565b9050808214611ddd576000866000018281548110611d9857611d986137bf565b9060005260206000200154905080876000018481548110611dbb57611dbb6137bf565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080611dee57611dee614076565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506102db565b60009150506102db565b5092915050565b6000818152600183016020526040812054611e81575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556102db565b5060006102db565b60006002821115611ec9576040517f3e4785260000000000000000000000000000000000000000000000000000000081526004810183905260240161082e565b8160028111156102db576102db613134565b6000826002811115611eef57611eef613134565b826002811115611f0157611f01613134565b611f0b91906140a5565b90508060011480611f575750807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff148015611f5757506002836002811115611f5557611f55613134565b145b15611f6157505050565b82826040517f0a6b675b00000000000000000000000000000000000000000000000000000000815260040161082e9291906140d5565b60606000845167ffffffffffffffff811115611fb557611fb561376a565b604051908082528060200260200182016040528015611fde578160200160208202803683370190505b5090506000846002811115611ff557611ff5613134565b1480156120135750600183600281111561201157612011613134565b145b156120545760018160008151811061202d5761202d6137bf565b602002602001019067ffffffffffffffff16908167ffffffffffffffff16815250506121bc565b600184600281111561206857612068613134565b1480156120865750600283600281111561208457612084613134565b145b1561211d578560008151811061209e5761209e6137bf565b602002602001015160200151816000815181106120bd576120bd6137bf565b602002602001019067ffffffffffffffff16908167ffffffffffffffff1681525050856000815181106120f2576120f26137bf565b602002602001015160200151600161210a91906140f0565b8160018151811061202d5761202d6137bf565b600284600281111561213157612131613134565b14801561214f5750600183600281111561214d5761214d613134565b145b156121865785600181518110612167576121676137bf565b6020026020010151602001518160008151811061202d5761202d6137bf565b83836040517f0a6b675b00000000000000000000000000000000000000000000000000000000815260040161082e9291906140d5565b6000855167ffffffffffffffff8111156121d8576121d861376a565b60405190808252806020026020018201604052801561228e57816020015b604080516101a081018252600060608083018281526080840183905260a0840183905260c0840183905260e084018290526101008401829052610120840182905261014084018290526101608401829052610180840191909152825260208083018290529282015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816121f65790505b50905060005b8251811015612377576122bf8782815181106122b2576122b26137bf565b6020026020010151612702565b60405180606001604052808883815181106122dc576122dc6137bf565b602002602001015181526020018483815181106122fb576122fb6137bf565b602002602001015167ffffffffffffffff16815260200161234f8b868581518110612328576123286137bf565b60200260200101518b8681518110612342576123426137bf565b6020026020010151612acb565b815250828281518110612364576123646137bf565b6020908102919091010152600101612294565b50979650505050505050565b81518151811580156123955750806001145b1561243757826000815181106123ad576123ad6137bf565b60200260200101516020015167ffffffffffffffff1660011461243157826000815181106123dd576123dd6137bf565b60209081029190910181015101516040517fc1658eb800000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526001602482015260440161082e565b50505050565b8160011480156124475750806002145b156125fd578360008151811061245f5761245f6137bf565b6020026020010151604001518360008151811061247e5761247e6137bf565b6020026020010151604001511461250a57826000815181106124a2576124a26137bf565b602002602001015160400151846000815181106124c1576124c16137bf565b6020026020010151604001516040517fc7ccdd7f00000000000000000000000000000000000000000000000000000000815260040161082e929190918252602082015260400190565b8360008151811061251d5761251d6137bf565b602002602001015160200151600161253591906140f0565b67ffffffffffffffff1683600181518110612552576125526137bf565b60200260200101516020015167ffffffffffffffff16146124315782600181518110612580576125806137bf565b6020026020010151602001518460008151811061259f5761259f6137bf565b60200260200101516020015160016125b791906140f0565b6040517fc1658eb800000000000000000000000000000000000000000000000000000000815267ffffffffffffffff92831660048201529116602482015260440161082e565b81600214801561260d5750806001145b156126d05783600181518110612625576126256137bf565b60200260200101516040015183600081518110612644576126446137bf565b602002602001015160400151146124315782600081518110612668576126686137bf565b60200260200101516040015184600181518110612687576126876137bf565b6020026020010151604001516040517f9e97567000000000000000000000000000000000000000000000000000000000815260040161082e929190918252602082015260400190565b6040517f1f1b2bb600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806020015167ffffffffffffffff1660000361274a576040517f698cf8e000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008151600181111561275f5761275f613134565b14158015612780575060018151600181111561277d5761277d613134565b14155b156127b7576040517f3302dbd700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60808101515115806127f4575060408051600060208201520160405160208183030381529060405280519060200120816080015180519060200120145b1561282b576040517f358c192700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208101516128469060039067ffffffffffffffff16611138565b61288e5760208101516040517f1bd4d2d200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260240161082e565b60208082015167ffffffffffffffff166000908152600290915260408120600101546128be9060ff166003614111565b6128c990600161412d565b60ff1690508082610100015151101561292057610100820151516040517f548dd21f00000000000000000000000000000000000000000000000000000000815260048101919091526024810182905260440161082e565b60e082015151610100811115612962576040517f1b925da600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8260c00151518114158061297c5750826101000151518114155b156129d75760c08301515160e084015151610100850151516040517fba900f6d00000000000000000000000000000000000000000000000000000000815260048101939093526024830191909152604482015260640161082e565b826040015160ff16600003612a18576040517f39d1a4d000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040830151612a28906003614111565b60ff168111612a63576040517f4856694e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8260c00151518360a00151511115612aa7576040517f8473d80700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612ab98360a001518460c00151612ba0565b612ac68360c0015161115c565b505050565b60008082602001518584600001518560800151878760a001518860c001518960e001518a61010001518b604001518c606001518d6101200151604051602001612b1f9c9b9a99989796959493929190614146565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e0a000000000000000000000000000000000000000000000000000000000000179150509392505050565b81511580612bad57508051155b15612be4576040517fe249684100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612bed82612d1b565b612bf681612d1b565b6000805b835182108015612c0a5750825181105b15612cdc57828181518110612c2157612c216137bf565b6020026020010151848381518110612c3b57612c3b6137bf565b60200260200101511115612c5957612c528161403e565b9050612bfa565b828181518110612c6b57612c6b6137bf565b6020026020010151848381518110612c8557612c856137bf565b602002602001015103612ca657612c9b8261403e565b9150612c528161403e565b83836040517fd671700c00000000000000000000000000000000000000000000000000000000815260040161082e929190614226565b83518210156124315783836040517fd671700c00000000000000000000000000000000000000000000000000000000815260040161082e929190614226565b60015b81518110156112a45781612d336001836137ac565b81518110612d4357612d436137bf565b6020026020010151828281518110612d5d57612d5d6137bf565b602002602001015111612d9e57816040517f1bc41b4200000000000000000000000000000000000000000000000000000000815260040161082e919061424b565b600101612d1e565b6040518060400160405280600067ffffffffffffffff168152602001612de9604051806060016040528060608152602001600060ff168152602001606081525090565b905290565b5080546000825590600052602060002090810190610b459190612f04565b508054612e18906136d1565b6000825580601f10612e28575050565b601f016020900490600052602060002090810190610b459190612f04565b828054828255906000526020600020908101928215612e81579160200282015b82811115612e81578251825591602001919060010190612e66565b50612e8d929150612f04565b5090565b5080546000825560090290600052602060002090810190610b459190612f19565b828054828255906000526020600020908101928215612ef8579160200282015b82811115612ef85782518290612ee89082613b30565b5091602001919060010190612ed2565b50612e8d929150612fda565b5b80821115612e8d5760008155600101612f05565b80821115612e8d5780547fffffffffffffffffffffffffffff00000000000000000000000000000000000016815560008181612f586001830182612e0c565b612f66600283016000612dee565b612f74600383016000612dee565b612f82600483016000612ff7565b612f90600583016000612ff7565b612f9e600683016000612e0c565b5050506007810180547fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000016905560006008820155600901612f19565b80821115612e8d576000612fee8282612e0c565b50600101612fda565b5080546000825590600052602060002090810190610b459190612fda565b60006020828403121561302757600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610fb957600080fd5b6000815180845260005b8181101561307d57602081850181015186830182015201613061565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000610fb96020830184613057565b63ffffffff81168114610b4557600080fd5b80356130eb816130ce565b919050565b8035600281106130eb57600080fd5b6000806040838503121561311257600080fd5b823561311d816130ce565b915061312b602084016130f0565b90509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6002811061317357613173613134565b9052565b60008151808452602080850194506020840160005b838110156131a85781518752958201959082019060010161318c565b509495945050505050565b60008282518085526020808601955060208260051b8401016020860160005b84811015610b27577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe086840301895261320c838351613057565b988401989250908301906001016131d2565b600060208083018184528085518083526040925060408601915060408160051b87010184880160005b838110156133ed577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc089840301855281516060815181865261328c8287018251613163565b8981015160806132a78189018367ffffffffffffffff169052565b8a830151915060a06132bd818a018460ff169052565b938301519360c092506132db8984018667ffffffffffffffff169052565b818401519450610140915060e082818b01526132fb6101a08b0187613057565b95508185015191507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0610100818c890301818d015261333a8885613177565b97508587015195506101209350818c890301848d015261335a8887613177565b9750828701519550818c890301858d015261337588876131b3565b975080870151955050808b8803016101608c015261339387866131b3565b9650828601519550808b8803016101808c015250505050506133b58282613057565b915050888201516133d18a87018267ffffffffffffffff169052565b5090870151938701939093529386019390860190600101613247565b509098975050505050505050565b60006020828403121561340d57600080fd5b8135610fb9816130ce565b6000806040838503121561342b57600080fd5b50508035926020909101359150565b600081516060845261344f6060850182613177565b905060ff6020840151166020850152604083015184820360408601526134758282613057565b95945050505050565b600060208083018184528085518083526040925060408601915060408160051b87010184880160005b838110156133ed578883037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00185528151805167ffffffffffffffff1684528701518784018790526134fb8785018261343a565b95880195935050908601906001016134a7565b60006020828403121561352057600080fd5b813573ffffffffffffffffffffffffffffffffffffffff81168114610fb957600080fd5b60008083601f84011261355657600080fd5b50813567ffffffffffffffff81111561356e57600080fd5b6020830191508360208260051b850101111561358957600080fd5b9250929050565b600080600080604085870312156135a657600080fd5b843567ffffffffffffffff808211156135be57600080fd5b6135ca88838901613544565b909650945060208701359150808211156135e357600080fd5b506135f087828801613544565b95989497509550505050565b803567ffffffffffffffff811681146130eb57600080fd5b6000806000806000806080878903121561362d57600080fd5b863567ffffffffffffffff8082111561364557600080fd5b6136518a838b01613544565b9098509650602089013591508082111561366a57600080fd5b818901915089601f83011261367e57600080fd5b81358181111561368d57600080fd5b8a602082850101111561369f57600080fd5b6020830196508095505050506136b7604088016135fc565b91506136c5606088016130e0565b90509295509295509295565b600181811c908216806136e557607f821691505b60208210810361371e577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80820281158282048414176102db576102db613724565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b808201808211156102db576102db613724565b818103818111156102db576102db613724565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561380057600080fd5b610fb9826135fc565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc183360301811261383d57600080fd5b9190910192915050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa183360301811261383d57600080fd5b604051610140810167ffffffffffffffff8111828210171561389f5761389f61376a565b60405290565b60405160e0810167ffffffffffffffff8111828210171561389f5761389f61376a565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561390f5761390f61376a565b604052919050565b600067ffffffffffffffff8211156139315761393161376a565b5060051b60200190565b600082601f83011261394c57600080fd5b8135602061396161395c83613917565b6138c8565b8083825260208201915060208460051b87010193508684111561398357600080fd5b602086015b8481101561399f5780358352918301918301613988565b509695505050505050565b803560ff811681146130eb57600080fd5b600082601f8301126139cc57600080fd5b813567ffffffffffffffff8111156139e6576139e661376a565b613a1760207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016138c8565b818152846020838601011115613a2c57600080fd5b816020850160208301376000918101602001919091529392505050565b600060608236031215613a5b57600080fd5b6040516060810167ffffffffffffffff8282108183111715613a7f57613a7f61376a565b816040528435915080821115613a9457600080fd5b613aa03683870161393b565b8352613aae602086016139aa565b60208401526040850135915080821115613ac757600080fd5b50613ad4368286016139bb565b60408301525092915050565b601f821115612ac6576000816000526020600020601f850160051c81016020861015613b095750805b601f850160051c820191505b81811015613b2857828155600101613b15565b505050505050565b815167ffffffffffffffff811115613b4a57613b4a61376a565b613b5e81613b5884546136d1565b84613ae0565b602080601f831160018114613bb15760008415613b7b5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555613b28565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015613bfe57888601518255948401946001909101908401613bdf565b5085821015613c3a57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b67ffffffffffffffff83168152604060208201526000613c6d604083018461343a565b949350505050565b600082601f830112613c8657600080fd5b81356020613c9661395c83613917565b82815260059290921b84018101918181019086841115613cb557600080fd5b8286015b8481101561399f57803567ffffffffffffffff811115613cd95760008081fd5b613ce78986838b01016139bb565b845250918301918301613cb9565b60006020808385031215613d0857600080fd5b823567ffffffffffffffff80821115613d2057600080fd5b818501915085601f830112613d3457600080fd5b8135613d4261395c82613917565b81815260059190911b83018401908481019088831115613d6157600080fd5b8585015b83811015613eef57803585811115613d7c57600080fd5b8601610140818c037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0011215613db157600080fd5b613db961387b565b613dc48983016130f0565b8152613dd2604083016135fc565b89820152613de2606083016139aa565b6040820152613df3608083016135fc565b606082015260a082013587811115613e0a57600080fd5b613e188d8b838601016139bb565b60808301525060c082013587811115613e3057600080fd5b613e3e8d8b8386010161393b565b60a08301525060e082013587811115613e5657600080fd5b613e648d8b8386010161393b565b60c0830152506101008083013588811115613e7e57600080fd5b613e8c8e8c83870101613c75565b60e0840152506101208084013589811115613ea657600080fd5b613eb48f8d83880101613c75565b8385015250610140840135915088821115613ece57600080fd5b613edc8e8c848701016139bb565b9083015250845250918601918601613d65565b5098975050505050505050565b80516130eb816130ce565b600082601f830112613f1857600080fd5b81516020613f2861395c83613917565b8083825260208201915060208460051b870101935086841115613f4a57600080fd5b602086015b8481101561399f5780518352918301918301613f4f565b600060208284031215613f7857600080fd5b815167ffffffffffffffff80821115613f9057600080fd5b9083019060e08286031215613fa457600080fd5b613fac6138a5565b613fb583613efc565b8152613fc360208401613efc565b6020820152613fd460408401613efc565b6040820152606083015160608201526080830151608082015260a083015182811115613fff57600080fd5b61400b87828601613f07565b60a08301525060c08301518281111561402357600080fd5b61402f87828601613f07565b60c08301525095945050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361406f5761406f613724565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b8181036000831280158383131683831282161715611e3357611e33613724565b6003811061317357613173613134565b604081016140e382856140c5565b610fb960208301846140c5565b67ffffffffffffffff818116838216019080821115611e3357611e33613724565b60ff8181168382160290811690818114611e3357611e33613724565b60ff81811683821601908111156102db576102db613724565b67ffffffffffffffff8d16815263ffffffff8c16602082015261416c604082018c613163565b6101806060820152600061418461018083018c613057565b67ffffffffffffffff8b16608084015282810360a08401526141a6818b613177565b905082810360c08401526141ba818a613177565b905082810360e08401526141ce81896131b3565b90508281036101008401526141e381886131b3565b60ff8716610120850152905067ffffffffffffffff85166101408401528281036101608401526142138185613057565b9f9e505050505050505050505050505050565b6040815260006142396040830185613177565b82810360208401526134758185613177565b602081526000610fb9602083018461317756fea164736f6c6343000818000a", } var CCIPConfigABI = CCIPConfigMetaData.ABI diff --git a/core/gethwrappers/ccip/generated/multi_ocr3_helper/multi_ocr3_helper.go b/core/gethwrappers/ccip/generated/multi_ocr3_helper/multi_ocr3_helper.go index 2f2dfbf821..285aaaa338 100644 --- a/core/gethwrappers/ccip/generated/multi_ocr3_helper/multi_ocr3_helper.go +++ b/core/gethwrappers/ccip/generated/multi_ocr3_helper/multi_ocr3_helper.go @@ -59,7 +59,7 @@ type MultiOCR3BaseOracle struct { var MultiOCR3HelperMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"actual\",\"type\":\"bytes32\"}],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"ForkedChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enumMultiOCR3Base.InvalidConfigErrorType\",\"name\":\"errorType\",\"type\":\"uint8\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonUniqueSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OracleCannotBeZeroAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignaturesOutOfRegistration\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"StaticConfigCannotBeChanged\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedTransmitter\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"WrongMessageLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WrongNumberOfSignatures\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"AfterConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"oracleAddress\",\"type\":\"address\"}],\"name\":\"getOracle\",\"outputs\":[{\"components\":[{\"internalType\":\"uint8\",\"name\":\"index\",\"type\":\"uint8\"},{\"internalType\":\"enumMultiOCR3Base.Role\",\"name\":\"role\",\"type\":\"uint8\"}],\"internalType\":\"structMultiOCR3Base.Oracle\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"latestConfigDetails\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"n\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"}],\"internalType\":\"structMultiOCR3Base.ConfigInfo\",\"name\":\"configInfo\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfig\",\"name\":\"ocrConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfigArgs[]\",\"name\":\"ocrConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"setOCR3Configs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"setTransmitOcrPluginType\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"rawVs\",\"type\":\"bytes32\"}],\"name\":\"transmitWithSignatures\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"transmitWithoutSignatures\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]", - Bin: "0x60a06040523480156200001157600080fd5b503380600081620000695760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b03848116919091179091558116156200009c576200009c81620000a9565b5050466080525062000154565b336001600160a01b03821603620001035760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000060565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b608051611d3f6200017760003960008181610ef70152610f430152611d3f6000f3fe608060405234801561001057600080fd5b50600436106100be5760003560e01c80637ac0aa1a11610076578063c673e5841161005b578063c673e584146101c5578063f2fde38b146101e5578063f716f99f146101f857600080fd5b80637ac0aa1a1461015b5780638da5cb5b1461019d57600080fd5b806334a9c92e116100a757806334a9c92e1461012057806344e65e551461014057806379ba50971461015357600080fd5b8063181f5a77146100c357806326bf9d261461010b575b600080fd5b604080518082018252601981527f4d756c74694f4352334261736548656c70657220312e302e30000000000000006020820152905161010291906114e4565b60405180910390f35b61011e6101193660046115ab565b61020b565b005b61013361012e366004611639565b61023a565b604051610102919061169b565b61011e61014e36600461170e565b6102ca565b61011e61034d565b61011e6101693660046117c1565b600480547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff92909216919091179055565b60005460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610102565b6101d86101d33660046117c1565b61044f565b6040516101029190611835565b61011e6101f33660046118c8565b6105c7565b61011e610206366004611a34565b6105db565b604080516000808252602082019092526004549091506102349060ff168585858580600061061d565b50505050565b6040805180820182526000808252602080830182905260ff86811683526003825284832073ffffffffffffffffffffffffffffffffffffffff871684528252918490208451808601909552805480841686529394939092918401916101009091041660028111156102ad576102ad61166c565b60028111156102be576102be61166c565b90525090505b92915050565b60045460408051602080880282810182019093528782526103439360ff16928c928c928c928c918c91829185019084908082843760009201919091525050604080516020808d0282810182019093528c82529093508c92508b9182918501908490808284376000920191909152508a925061061d915050565b5050505050505050565b60015473ffffffffffffffffffffffffffffffffffffffff1633146103d3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6104926040805160e081019091526000606082018181526080830182905260a0830182905260c08301919091528190815260200160608152602001606081525090565b60ff808316600090815260026020818152604092839020835160e081018552815460608201908152600183015480881660808401526101008104881660a0840152620100009004909616151560c08201529485529182018054845181840281018401909552808552929385830193909283018282801561054857602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff16815260019091019060200180831161051d575b50505050508152602001600382018054806020026020016040519081016040528092919081815260200182805480156105b757602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff16815260019091019060200180831161058c575b5050505050815250509050919050565b6105cf6109a1565b6105d881610a24565b50565b6105e36109a1565b60005b81518110156106195761061182828151811061060457610604611b9d565b6020026020010151610b19565b6001016105e6565b5050565b60ff8781166000908152600260209081526040808320815160808101835281548152600190910154808616938201939093526101008304851691810191909152620100009091049092161515606083015287359061067c8760a4611bfb565b90508260600151156106c4578451610695906020611c0e565b86516106a2906020611c0e565b6106ad9060a0611bfb565b6106b79190611bfb565b6106c19082611bfb565b90505b368114610706576040517f8e1192e1000000000000000000000000000000000000000000000000000000008152600481018290523660248201526044016103ca565b508151811461074e5781516040517f93df584c0000000000000000000000000000000000000000000000000000000081526004810191909152602481018290526044016103ca565b610756610ef4565b60ff808a16600090815260036020908152604080832033845282528083208151808301909252805480861683529394919390928401916101009091041660028111156107a4576107a461166c565b60028111156107b5576107b561166c565b90525090506002816020015160028111156107d2576107d261166c565b1480156108335750600260008b60ff1660ff168152602001908152602001600020600301816000015160ff168154811061080e5761080e611b9d565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1633145b610869576040517fda0f08e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5081606001511561094b576020820151610884906001611c25565b60ff168551146108c0576040517f71253a2500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83518551146108fb576040517fa75d88af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000878760405161090d929190611c3e565b604051908190038120610924918b90602001611c4e565b6040516020818303038152906040528051906020012090506109498a82888888610f75565b505b6040805182815260208a81013567ffffffffffffffff169082015260ff8b16917f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef0910160405180910390a2505050505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610a22576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016103ca565b565b3373ffffffffffffffffffffffffffffffffffffffff821603610aa3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016103ca565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b806040015160ff16600003610b5d5760006040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016103ca9190611c62565b60208082015160ff80821660009081526002909352604083206001810154929390928392169003610bca57606084015160018201805491151562010000027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff909216919091179055610c1f565b6060840151600182015460ff6201000090910416151590151514610c1f576040517f87f6037c00000000000000000000000000000000000000000000000000000000815260ff841660048201526024016103ca565b60a08401518051601f1015610c635760016040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016103ca9190611c62565b610cd68484600301805480602002602001604051908101604052809291908181526020018280548015610ccc57602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610ca1575b5050505050611185565b846060015115610e4457610d518484600201805480602002602001604051908101604052809291908181526020018280548015610ccc5760200282019190600052602060002090815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610ca1575050505050611185565b60808501518051610d6b9060028601906020840190611445565b5080516001840180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1661010060ff841690810291909117909155601f1015610de45760026040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016103ca9190611c62565b6040870151610df4906003611c7c565b60ff168160ff1611610e355760036040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016103ca9190611c62565b610e418683600161121d565b50505b610e508482600261121d565b8051610e659060038501906020840190611445565b506040858101516001840180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff8316179055865180855560a088015192517fab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f54793610edc9389939260028a01929190611c9f565b60405180910390a1610eed8461140c565b5050505050565b467f000000000000000000000000000000000000000000000000000000000000000014610a22576040517f0f01ce850000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060048201524660248201526044016103ca565b8251600090815b81811015610343576000600188868460208110610f9b57610f9b611b9d565b610fa891901a601b611c25565b898581518110610fba57610fba611b9d565b6020026020010151898681518110610fd457610fd4611b9d565b602002602001015160405160008152602001604052604051611012949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015611034573d6000803e3d6000fd5b5050604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081015160ff808e1660009081526003602090815285822073ffffffffffffffffffffffffffffffffffffffff8516835281528582208587019096528554808416865293975090955092939284019161010090041660028111156110c0576110c061166c565b60028111156110d1576110d161166c565b90525090506001816020015160028111156110ee576110ee61166c565b14611125576040517fca31867a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051600160ff9091161b851615611168576040517ff67bc7c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806000015160ff166001901b851794505050806001019050610f7c565b60005b81518110156112185760ff8316600090815260036020526040812083519091908490849081106111ba576111ba611b9d565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff16825281019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000169055600101611188565b505050565b60005b825181101561023457600083828151811061123d5761123d611b9d565b602002602001015190506000600281111561125a5761125a61166c565b60ff808716600090815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915290205461010090041660028111156112a6576112a661166c565b146112e05760046040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016103ca9190611c62565b73ffffffffffffffffffffffffffffffffffffffff811661132d576040517fd6c62c9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052808360ff1681526020018460028111156113535761135361166c565b905260ff808716600090815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845282529091208351815493167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00841681178255918401519092909183917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000016176101008360028111156113f8576113f861166c565b021790555090505050806001019050611220565b60405160ff821681527f897ac1b2c12867721b284f3eb147bd4ab046d4eef1cf31c1d8988bfcfb962b539060200160405180910390a150565b8280548282559060005260206000209081019282156114bf579160200282015b828111156114bf57825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909116178255602090920191600190910190611465565b506114cb9291506114cf565b5090565b5b808211156114cb57600081556001016114d0565b60006020808352835180602085015260005b81811015611512578581018301518582016040015282016114f6565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b80606081018310156102c457600080fd5b60008083601f84011261157457600080fd5b50813567ffffffffffffffff81111561158c57600080fd5b6020830191508360208285010111156115a457600080fd5b9250929050565b6000806000608084860312156115c057600080fd5b6115ca8585611551565b9250606084013567ffffffffffffffff8111156115e657600080fd5b6115f286828701611562565b9497909650939450505050565b803560ff8116811461161057600080fd5b919050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461161057600080fd5b6000806040838503121561164c57600080fd5b611655836115ff565b915061166360208401611615565b90509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b815160ff16815260208201516040820190600381106116bc576116bc61166c565b8060208401525092915050565b60008083601f8401126116db57600080fd5b50813567ffffffffffffffff8111156116f357600080fd5b6020830191508360208260051b85010111156115a457600080fd5b60008060008060008060008060e0898b03121561172a57600080fd5b6117348a8a611551565b9750606089013567ffffffffffffffff8082111561175157600080fd5b61175d8c838d01611562565b909950975060808b013591508082111561177657600080fd5b6117828c838d016116c9565b909750955060a08b013591508082111561179b57600080fd5b506117a88b828c016116c9565b999c989b50969995989497949560c00135949350505050565b6000602082840312156117d357600080fd5b6117dc826115ff565b9392505050565b60008151808452602080850194506020840160005b8381101561182a57815173ffffffffffffffffffffffffffffffffffffffff16875295820195908201906001016117f8565b509495945050505050565b60208152600082518051602084015260ff602082015116604084015260ff604082015116606084015260608101511515608084015250602083015160c060a084015261188460e08401826117e3565b905060408401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08483030160c08501526118bf82826117e3565b95945050505050565b6000602082840312156118da57600080fd5b6117dc82611615565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160c0810167ffffffffffffffff81118282101715611935576119356118e3565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611982576119826118e3565b604052919050565b600067ffffffffffffffff8211156119a4576119a46118e3565b5060051b60200190565b8035801515811461161057600080fd5b600082601f8301126119cf57600080fd5b813560206119e46119df8361198a565b61193b565b8083825260208201915060208460051b870101935086841115611a0657600080fd5b602086015b84811015611a2957611a1c81611615565b8352918301918301611a0b565b509695505050505050565b60006020808385031215611a4757600080fd5b823567ffffffffffffffff80821115611a5f57600080fd5b818501915085601f830112611a7357600080fd5b8135611a816119df8261198a565b81815260059190911b83018401908481019088831115611aa057600080fd5b8585015b83811015611b9057803585811115611abb57600080fd5b860160c0818c037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0011215611af05760008081fd5b611af8611912565b8882013581526040611b0b8184016115ff565b8a8301526060611b1c8185016115ff565b8284015260809150611b2f8285016119ae565b9083015260a08381013589811115611b475760008081fd5b611b558f8d838801016119be565b838501525060c0840135915088821115611b6f5760008081fd5b611b7d8e8c848701016119be565b9083015250845250918601918601611aa4565b5098975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156102c4576102c4611bcc565b80820281158282048414176102c4576102c4611bcc565b60ff81811683821601908111156102c4576102c4611bcc565b8183823760009101908152919050565b828152606082602083013760800192915050565b6020810160058310611c7657611c7661166c565b91905290565b60ff8181168382160290811690818114611c9857611c98611bcc565b5092915050565b600060a0820160ff88168352602087602085015260a0604085015281875480845260c086019150886000526020600020935060005b81811015611d0657845473ffffffffffffffffffffffffffffffffffffffff1683526001948501949284019201611cd4565b50508481036060860152611d1a81886117e3565b935050505060ff83166080830152969550505050505056fea164736f6c6343000818000a", + Bin: "0x60a06040523480156200001157600080fd5b503380600081620000695760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b03848116919091179091558116156200009c576200009c81620000a9565b5050466080525062000154565b336001600160a01b03821603620001035760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000060565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b608051611d386200017760003960008181610ef00152610f3c0152611d386000f3fe608060405234801561001057600080fd5b50600436106100be5760003560e01c80637ac0aa1a11610076578063c673e5841161005b578063c673e584146101c5578063f2fde38b146101e5578063f716f99f146101f857600080fd5b80637ac0aa1a1461015b5780638da5cb5b1461019d57600080fd5b806334a9c92e116100a757806334a9c92e1461012057806344e65e551461014057806379ba50971461015357600080fd5b8063181f5a77146100c357806326bf9d261461010b575b600080fd5b604080518082018252601981527f4d756c74694f4352334261736548656c70657220312e302e30000000000000006020820152905161010291906114dd565b60405180910390f35b61011e6101193660046115a4565b61020b565b005b61013361012e366004611632565b61023a565b6040516101029190611694565b61011e61014e366004611707565b6102ca565b61011e61034d565b61011e6101693660046117ba565b600480547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff92909216919091179055565b60005460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610102565b6101d86101d33660046117ba565b61044f565b604051610102919061182e565b61011e6101f33660046118c1565b6105c7565b61011e610206366004611a2d565b6105db565b604080516000808252602082019092526004549091506102349060ff168585858580600061061d565b50505050565b6040805180820182526000808252602080830182905260ff86811683526003825284832073ffffffffffffffffffffffffffffffffffffffff871684528252918490208451808601909552805480841686529394939092918401916101009091041660028111156102ad576102ad611665565b60028111156102be576102be611665565b90525090505b92915050565b60045460408051602080880282810182019093528782526103439360ff16928c928c928c928c918c91829185019084908082843760009201919091525050604080516020808d0282810182019093528c82529093508c92508b9182918501908490808284376000920191909152508a925061061d915050565b5050505050505050565b60015473ffffffffffffffffffffffffffffffffffffffff1633146103d3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6104926040805160e081019091526000606082018181526080830182905260a0830182905260c08301919091528190815260200160608152602001606081525090565b60ff808316600090815260026020818152604092839020835160e081018552815460608201908152600183015480881660808401526101008104881660a0840152620100009004909616151560c08201529485529182018054845181840281018401909552808552929385830193909283018282801561054857602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff16815260019091019060200180831161051d575b50505050508152602001600382018054806020026020016040519081016040528092919081815260200182805480156105b757602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff16815260019091019060200180831161058c575b5050505050815250509050919050565b6105cf6109a1565b6105d881610a24565b50565b6105e36109a1565b60005b81518110156106195761061182828151811061060457610604611b96565b6020026020010151610b19565b6001016105e6565b5050565b60ff8781166000908152600260209081526040808320815160808101835281548152600190910154808616938201939093526101008304851691810191909152620100009091049092161515606083015287359061067c8760a4611bf4565b90508260600151156106c4578451610695906020611c07565b86516106a2906020611c07565b6106ad9060a0611bf4565b6106b79190611bf4565b6106c19082611bf4565b90505b368114610706576040517f8e1192e1000000000000000000000000000000000000000000000000000000008152600481018290523660248201526044016103ca565b508151811461074e5781516040517f93df584c0000000000000000000000000000000000000000000000000000000081526004810191909152602481018290526044016103ca565b610756610eed565b60ff808a16600090815260036020908152604080832033845282528083208151808301909252805480861683529394919390928401916101009091041660028111156107a4576107a4611665565b60028111156107b5576107b5611665565b90525090506002816020015160028111156107d2576107d2611665565b1480156108335750600260008b60ff1660ff168152602001908152602001600020600301816000015160ff168154811061080e5761080e611b96565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1633145b610869576040517fda0f08e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5081606001511561094b576020820151610884906001611c1e565b60ff168551146108c0576040517f71253a2500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83518551146108fb576040517fa75d88af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000878760405161090d929190611c37565b604051908190038120610924918b90602001611c47565b6040516020818303038152906040528051906020012090506109498a82888888610f6e565b505b6040805182815260208a81013567ffffffffffffffff169082015260ff8b16917f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef0910160405180910390a2505050505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610a22576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016103ca565b565b3373ffffffffffffffffffffffffffffffffffffffff821603610aa3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016103ca565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b806040015160ff16600003610b5d5760006040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016103ca9190611c5b565b60208082015160ff80821660009081526002909352604083206001810154929390928392169003610bca57606084015160018201805491151562010000027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff909216919091179055610c1f565b6060840151600182015460ff6201000090910416151590151514610c1f576040517f87f6037c00000000000000000000000000000000000000000000000000000000815260ff841660048201526024016103ca565b60a084015180516101001015610c645760016040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016103ca9190611c5b565b610cd78484600301805480602002602001604051908101604052809291908181526020018280548015610ccd57602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610ca2575b505050505061117e565b846060015115610e3d57610d528484600201805480602002602001604051908101604052809291908181526020018280548015610ccd5760200282019190600052602060002090815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610ca257505050505061117e565b608085015180516101001015610d975760026040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016103ca9190611c5b565b6040860151610da7906003611c75565b60ff16815111610de65760036040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016103ca9190611c5b565b80516001840180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1661010060ff841602179055610e2e906002860190602084019061143e565b50610e3b85826001611216565b505b610e4984826002611216565b8051610e5e906003850190602084019061143e565b506040858101516001840180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff8316179055865180855560a088015192517fab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f54793610ed59389939260028a01929190611c98565b60405180910390a1610ee684611405565b5050505050565b467f000000000000000000000000000000000000000000000000000000000000000014610a22576040517f0f01ce850000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060048201524660248201526044016103ca565b8251600090815b81811015610343576000600188868460208110610f9457610f94611b96565b610fa191901a601b611c1e565b898581518110610fb357610fb3611b96565b6020026020010151898681518110610fcd57610fcd611b96565b60200260200101516040516000815260200160405260405161100b949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa15801561102d573d6000803e3d6000fd5b5050604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081015160ff808e1660009081526003602090815285822073ffffffffffffffffffffffffffffffffffffffff8516835281528582208587019096528554808416865293975090955092939284019161010090041660028111156110b9576110b9611665565b60028111156110ca576110ca611665565b90525090506001816020015160028111156110e7576110e7611665565b1461111e576040517fca31867a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051600160ff9091161b851615611161576040517ff67bc7c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806000015160ff166001901b851794505050806001019050610f75565b60005b81518110156112115760ff8316600090815260036020526040812083519091908490849081106111b3576111b3611b96565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff16825281019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000169055600101611181565b505050565b60005b825181101561023457600083828151811061123657611236611b96565b602002602001015190506000600281111561125357611253611665565b60ff808716600090815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff87168452909152902054610100900416600281111561129f5761129f611665565b146112d95760046040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016103ca9190611c5b565b73ffffffffffffffffffffffffffffffffffffffff8116611326576040517fd6c62c9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052808360ff16815260200184600281111561134c5761134c611665565b905260ff808716600090815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845282529091208351815493167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00841681178255918401519092909183917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000016176101008360028111156113f1576113f1611665565b021790555090505050806001019050611219565b60405160ff821681527f897ac1b2c12867721b284f3eb147bd4ab046d4eef1cf31c1d8988bfcfb962b539060200160405180910390a150565b8280548282559060005260206000209081019282156114b8579160200282015b828111156114b857825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff90911617825560209092019160019091019061145e565b506114c49291506114c8565b5090565b5b808211156114c457600081556001016114c9565b60006020808352835180602085015260005b8181101561150b578581018301518582016040015282016114ef565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b80606081018310156102c457600080fd5b60008083601f84011261156d57600080fd5b50813567ffffffffffffffff81111561158557600080fd5b60208301915083602082850101111561159d57600080fd5b9250929050565b6000806000608084860312156115b957600080fd5b6115c3858561154a565b9250606084013567ffffffffffffffff8111156115df57600080fd5b6115eb8682870161155b565b9497909650939450505050565b803560ff8116811461160957600080fd5b919050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461160957600080fd5b6000806040838503121561164557600080fd5b61164e836115f8565b915061165c6020840161160e565b90509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b815160ff16815260208201516040820190600381106116b5576116b5611665565b8060208401525092915050565b60008083601f8401126116d457600080fd5b50813567ffffffffffffffff8111156116ec57600080fd5b6020830191508360208260051b850101111561159d57600080fd5b60008060008060008060008060e0898b03121561172357600080fd5b61172d8a8a61154a565b9750606089013567ffffffffffffffff8082111561174a57600080fd5b6117568c838d0161155b565b909950975060808b013591508082111561176f57600080fd5b61177b8c838d016116c2565b909750955060a08b013591508082111561179457600080fd5b506117a18b828c016116c2565b999c989b50969995989497949560c00135949350505050565b6000602082840312156117cc57600080fd5b6117d5826115f8565b9392505050565b60008151808452602080850194506020840160005b8381101561182357815173ffffffffffffffffffffffffffffffffffffffff16875295820195908201906001016117f1565b509495945050505050565b60208152600082518051602084015260ff602082015116604084015260ff604082015116606084015260608101511515608084015250602083015160c060a084015261187d60e08401826117dc565b905060408401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08483030160c08501526118b882826117dc565b95945050505050565b6000602082840312156118d357600080fd5b6117d58261160e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160c0810167ffffffffffffffff8111828210171561192e5761192e6118dc565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561197b5761197b6118dc565b604052919050565b600067ffffffffffffffff82111561199d5761199d6118dc565b5060051b60200190565b8035801515811461160957600080fd5b600082601f8301126119c857600080fd5b813560206119dd6119d883611983565b611934565b8083825260208201915060208460051b8701019350868411156119ff57600080fd5b602086015b84811015611a2257611a158161160e565b8352918301918301611a04565b509695505050505050565b60006020808385031215611a4057600080fd5b823567ffffffffffffffff80821115611a5857600080fd5b818501915085601f830112611a6c57600080fd5b8135611a7a6119d882611983565b81815260059190911b83018401908481019088831115611a9957600080fd5b8585015b83811015611b8957803585811115611ab457600080fd5b860160c0818c037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0011215611ae95760008081fd5b611af161190b565b8882013581526040611b048184016115f8565b8a8301526060611b158185016115f8565b8284015260809150611b288285016119a7565b9083015260a08381013589811115611b405760008081fd5b611b4e8f8d838801016119b7565b838501525060c0840135915088821115611b685760008081fd5b611b768e8c848701016119b7565b9083015250845250918601918601611a9d565b5098975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156102c4576102c4611bc5565b80820281158282048414176102c4576102c4611bc5565b60ff81811683821601908111156102c4576102c4611bc5565b8183823760009101908152919050565b828152606082602083013760800192915050565b6020810160058310611c6f57611c6f611665565b91905290565b60ff8181168382160290811690818114611c9157611c91611bc5565b5092915050565b600060a0820160ff88168352602087602085015260a0604085015281875480845260c086019150886000526020600020935060005b81811015611cff57845473ffffffffffffffffffffffffffffffffffffffff1683526001948501949284019201611ccd565b50508481036060860152611d1381886117dc565b935050505060ff83166080830152969550505050505056fea164736f6c6343000818000a", } var MultiOCR3HelperABI = MultiOCR3HelperMetaData.ABI diff --git a/core/gethwrappers/ccip/generated/offramp/offramp.go b/core/gethwrappers/ccip/generated/offramp/offramp.go index 6f2ba32ec6..b491a4f39d 100644 --- a/core/gethwrappers/ccip/generated/offramp/offramp.go +++ b/core/gethwrappers/ccip/generated/offramp/offramp.go @@ -165,7 +165,7 @@ type OffRampUnblessedRoot struct { var OffRampMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CanOnlySelfCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"actual\",\"type\":\"bytes32\"}],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ExecutionError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"ForkedChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enumMultiOCR3Base.InvalidConfigErrorType\",\"name\":\"errorType\",\"type\":\"uint8\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"got\",\"type\":\"uint256\"}],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidEVMAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"internalType\":\"structOffRamp.Interval\",\"name\":\"interval\",\"type\":\"tuple\"}],\"name\":\"InvalidInterval\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"newLimit\",\"type\":\"uint256\"}],\"name\":\"InvalidManualExecutionGasLimit\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"messageDestChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidMessageDestChainSelector\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"newState\",\"type\":\"uint8\"}],\"name\":\"InvalidNewState\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRoot\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidStaticConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LeavesCannotBeEmpty\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ManualExecutionGasLimitMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"ManualExecutionNotYetEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"errorReason\",\"type\":\"bytes\"}],\"name\":\"MessageValidationError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonUniqueSignatures\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"notPool\",\"type\":\"address\"}],\"name\":\"NotACompatiblePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OracleCannotBeZeroAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ReceiverError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountReleased\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePre\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePost\",\"type\":\"uint256\"}],\"name\":\"ReleaseOrMintBalanceMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"name\":\"RootAlreadyCommitted\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"RootNotCommitted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignaturesOutOfRegistration\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"StaleCommitReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"StaticConfigCannotBeChanged\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"TokenDataMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"TokenHandlingError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnexpectedTokenData\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"WrongMessageLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WrongNumberOfSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroChainSelectorNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"AlreadyAttempted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"internalType\":\"structOffRamp.Interval\",\"name\":\"interval\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structOffRamp.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"report\",\"type\":\"tuple\"}],\"name\":\"CommitReportAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"DynamicConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"messageHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"name\":\"ExecutionStateChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"RootRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"SkippedAlreadyExecutedMessage\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"sourceConfig\",\"type\":\"tuple\"}],\"name\":\"SourceChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainSelectorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"}],\"name\":\"StaticConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigUpdates\",\"type\":\"tuple[]\"}],\"name\":\"applySourceChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"destTokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structClient.Any2EVMMessage\",\"name\":\"\",\"type\":\"tuple\"}],\"name\":\"ccipReceive\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"rawVs\",\"type\":\"bytes32\"}],\"name\":\"commit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"execute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"bytes[]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[]\"}],\"name\":\"executeSingleMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"getExecutionState\",\"outputs\":[{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLatestPriceSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"getMerkleRoot\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"getSourceChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"isBlessed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"latestConfigDetails\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"n\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"}],\"internalType\":\"structMultiOCR3Base.ConfigInfo\",\"name\":\"configInfo\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfig\",\"name\":\"ocrConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage[]\",\"name\":\"messages\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[][]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[][]\"},{\"internalType\":\"bytes32[]\",\"name\":\"proofs\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"proofFlagBits\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.ExecutionReportSingleChain[]\",\"name\":\"reports\",\"type\":\"tuple[]\"},{\"internalType\":\"uint256[][]\",\"name\":\"gasLimitOverrides\",\"type\":\"uint256[][]\"}],\"name\":\"manuallyExecute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structOffRamp.UnblessedRoot[]\",\"name\":\"rootToReset\",\"type\":\"tuple[]\"}],\"name\":\"resetUnblessedRoots\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"setDynamicConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfigArgs[]\",\"name\":\"ocrConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"setOCR3Configs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x6101206040523480156200001257600080fd5b5060405162006bd438038062006bd48339810160408190526200003591620008c7565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf81620001fa565b5050466080525060208301516001600160a01b03161580620000ec575060408301516001600160a01b0316155b8062000103575060608301516001600160a01b0316155b1562000122576040516342bcdf7f60e11b815260040160405180910390fd5b82516001600160401b03166000036200014e5760405163c656089560e01b815260040160405180910390fd5b82516001600160401b0390811660a052602080850180516001600160a01b0390811660c05260408088018051831660e0526060808a01805185166101005283518b519098168852945184169587019590955251821690850152905116908201527f683eb52ee924eb817377cfa8f41f238f4bb7a877da5267869dfffbad85f564d89060800160405180910390a1620001e682620002a5565b620001f181620003c1565b50505062000c67565b336001600160a01b03821603620002545760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b0316620002ce576040516342bcdf7f60e11b815260040160405180910390fd5b80516004805460208085018051604080880180516060808b0180516001600160a01b039b8c166001600160c01b0319909a168a17600160a01b63ffffffff98891602176001600160c01b0316600160c01b948816949094026001600160e01b031693909317600160e01b93871693909302929092179098556080808b018051600580546001600160a01b031916918d169190911790558451988952955185169688019690965290518316918601919091525116938301939093529151909216908201527fa55bd56595c45f517e5967a3067f3dca684445a3080e7c04a4e0d5a40cda627d9060a00160405180910390a150565b60005b815181101562000666576000828281518110620003e557620003e562000a1d565b60200260200101519050600081602001519050806001600160401b0316600003620004235760405163c656089560e01b815260040160405180910390fd5b81516001600160a01b03166200044c576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160401b0381166000908152600660205260408120600181018054919291620004789062000a33565b80601f0160208091040260200160405190810160405280929190818152602001828054620004a69062000a33565b8015620004f75780601f10620004cb57610100808354040283529160200191620004f7565b820191906000526020600020905b815481529060010190602001808311620004d957829003601f168201915b5050505050905060008460600151905081516000036200059e57805160000362000534576040516342bcdf7f60e11b815260040160405180910390fd5b6001830162000544828262000ac4565b508254600160a81b600160e81b031916600160a81b1783556040516001600160401b03851681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1620005d9565b8080519060200120828051906020012014620005d95760405163c39a620560e01b81526001600160401b038516600482015260240162000083565b604080860151845487516001600160a01b03166001600160a01b0319921515600160a01b02929092166001600160a81b031990911617178455516001600160401b038516907f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b906200064d90869062000b90565b60405180910390a25050505050806001019050620003c4565b5050565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b0381118282101715620006a557620006a56200066a565b60405290565b604051601f8201601f191681016001600160401b0381118282101715620006d657620006d66200066a565b604052919050565b80516001600160401b0381168114620006f657600080fd5b919050565b6001600160a01b03811681146200071157600080fd5b50565b805163ffffffff81168114620006f657600080fd5b6000601f83601f8401126200073d57600080fd5b825160206001600160401b03808311156200075c576200075c6200066a565b8260051b6200076d838201620006ab565b93845286810183019383810190898611156200078857600080fd5b84890192505b85831015620008ba57825184811115620007a85760008081fd5b89016080601f19828d038101821315620007c25760008081fd5b620007cc62000680565b88840151620007db81620006fb565b81526040620007ec858201620006de565b8a8301526060808601518015158114620008065760008081fd5b838301529385015193898511156200081e5760008081fd5b84860195508f603f8701126200083657600094508485fd5b8a8601519450898511156200084f576200084f6200066a565b620008608b858f88011601620006ab565b93508484528f82868801011115620008785760008081fd5b60005b8581101562000898578681018301518582018d01528b016200087b565b5060009484018b0194909452509182015283525091840191908401906200078e565b9998505050505050505050565b6000806000838503610140811215620008df57600080fd5b6080811215620008ee57600080fd5b620008f862000680565b6200090386620006de565b815260208601516200091581620006fb565b602082015260408601516200092a81620006fb565b604082015260608601516200093f81620006fb565b6060820152935060a0607f19820112156200095957600080fd5b5060405160a081016001600160401b0380821183831017156200098057620009806200066a565b81604052608087015191506200099682620006fb565b818352620009a760a0880162000714565b6020840152620009ba60c0880162000714565b6040840152620009cd60e0880162000714565b60608401526101008701519150620009e582620006fb565b608083018290526101208701519294508083111562000a0357600080fd5b505062000a138682870162000729565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b600181811c9082168062000a4857607f821691505b60208210810362000a6957634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111562000abf576000816000526020600020601f850160051c8101602086101562000a9a5750805b601f850160051c820191505b8181101562000abb5782815560010162000aa6565b5050505b505050565b81516001600160401b0381111562000ae05762000ae06200066a565b62000af88162000af1845462000a33565b8462000a6f565b602080601f83116001811462000b30576000841562000b175750858301515b600019600386901b1c1916600185901b17855562000abb565b600085815260208120601f198616915b8281101562000b615788860151825594840194600190910190840162000b40565b508582101562000b805787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b602080825282546001600160a01b0381168383015260a081901c60ff161515604084015260a81c6001600160401b0316606083015260808083015260018084018054600093929190849062000be58162000a33565b8060a089015260c0600183166000811462000c09576001811462000c265762000c58565b60ff19841660c08b015260c083151560051b8b0101945062000c58565b85600052602060002060005b8481101562000c4f5781548c820185015290880190890162000c32565b8b0160c0019550505b50929998505050505050505050565b60805160a05160c05160e05161010051615efe62000cd66000396000818161026601526129f50152600081816102370152612ee90152600081816102080152818161142b015261196d0152600081816101d801526126700152600081816117f3015261183f0152615efe6000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806385572ffb116100d8578063ccd37ba31161008c578063f2fde38b11610066578063f2fde38b14610583578063f716f99f14610596578063ff888fb1146105a957600080fd5b8063ccd37ba31461050b578063d2a15d3514610550578063e9d68a8e1461056357600080fd5b8063991a5018116100bd578063991a5018146104c5578063a80036b4146104d8578063c673e584146104eb57600080fd5b806385572ffb1461049c5780638da5cb5b146104aa57600080fd5b8063311cd5131161012f5780635e36480c116101145780635e36480c146103785780637437ff9f1461039857806379ba50971461049457600080fd5b8063311cd513146103495780633f4b04aa1461035c57600080fd5b806306285c691161016057806306285c69146101a4578063181f5a77146102ed5780632d04ab761461033657600080fd5b806304666f9c1461017c57806305d938b514610191575b600080fd5b61018f61018a366004614079565b6105cc565b005b61018f61019f366004614705565b6105e0565b61029660408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316815250905090565b6040516102e49190815167ffffffffffffffff1681526020808301516001600160a01b0390811691830191909152604080840151821690830152606092830151169181019190915260800190565b60405180910390f35b6103296040518060400160405280601181526020017f4f666652616d7020312e362e302d64657600000000000000000000000000000081525081565b6040516102e49190614880565b61018f61034436600461492b565b610785565b61018f6103573660046149de565b610b5c565b60095460405167ffffffffffffffff90911681526020016102e4565b61038b610386366004614a32565b610bc5565b6040516102e49190614a8f565b6104376040805160a081018252600080825260208201819052918101829052606081018290526080810191909152506040805160a0810182526004546001600160a01b03808216835263ffffffff600160a01b83048116602085015278010000000000000000000000000000000000000000000000008304811694840194909452600160e01b9091049092166060820152600554909116608082015290565b6040516102e49190600060a0820190506001600160a01b03808451168352602084015163ffffffff808216602086015280604087015116604086015280606087015116606086015250508060808501511660808401525092915050565b61018f610c1b565b61018f610177366004614a9d565b6000546040516001600160a01b0390911681526020016102e4565b61018f6104d3366004614aec565b610cd9565b61018f6104e6366004614b60565b610cea565b6104fe6104f9366004614bcd565b61105d565b6040516102e49190614c2d565b610542610519366004614ca2565b67ffffffffffffffff919091166000908152600860209081526040808320938352929052205490565b6040519081526020016102e4565b61018f61055e366004614ccc565b6111bb565b610576610571366004614d41565b611275565b6040516102e49190614d5c565b61018f610591366004614daa565b611382565b61018f6105a4366004614e2f565b611393565b6105bc6105b7366004614f6d565b6113d5565b60405190151581526020016102e4565b6105d4611496565b6105dd816114f2565b50565b6105e86117f0565b815181518114610624576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8181101561077557600084828151811061064357610643614f86565b6020026020010151905060008160200151519050600085848151811061066b5761066b614f86565b60200260200101519050805182146106af576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b828110156107665760008282815181106106ce576106ce614f86565b602002602001015190508060001461075d57846020015182815181106106f6576106f6614f86565b60200260200101516080015181101561075d5784516040517fc8e9605100000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260248101839052604481018290526064015b60405180910390fd5b506001016106b2565b50505050806001019050610627565b506107808383611871565b505050565b60006107938789018961510c565b805151519091501515806107ac57508051602001515115155b156108ac5760095460208a01359067ffffffffffffffff8083169116101561086b576009805467ffffffffffffffff191667ffffffffffffffff83161790556004805483516040517f3937306f0000000000000000000000000000000000000000000000000000000081526001600160a01b0390921692633937306f92610834929101615334565b600060405180830381600087803b15801561084e57600080fd5b505af1158015610862573d6000803e3d6000fd5b505050506108aa565b8160200151516000036108aa576040517f2261116700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b60005b816020015151811015610aa5576000826020015182815181106108d4576108d4614f86565b602002602001015190506000816000015190506108f081611921565b60006108fb82611a23565b602084015151815491925067ffffffffffffffff908116600160a81b9092041614158061093f575060208084015190810151905167ffffffffffffffff9182169116115b1561097f57825160208401516040517feefb0cac000000000000000000000000000000000000000000000000000000008152610754929190600401615347565b6040830151806109bb576040517f504570e300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b835167ffffffffffffffff16600090815260086020908152604080832084845290915290205415610a2e5783516040517f32cf0cbf00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260248101829052604401610754565b6020808501510151610a41906001615392565b82547fffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffff16600160a81b67ffffffffffffffff9283160217909255925116600090815260086020908152604080832094835293905291909120429055506001016108af565b507f3a3950e13dd607cc37980db0ef14266c40d2bba9c01b2e44bfe549808883095d81604051610ad591906153ba565b60405180910390a1610b5160008a8a8a8a8a8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808e0282810182019093528d82529093508d92508c9182918501908490808284376000920191909152508b9250611a8a915050565b505050505050505050565b610b9c610b6b82840184615457565b6040805160008082526020820190925290610b96565b6060815260200190600190039081610b815790505b50611871565b604080516000808252602082019092529050610bbf600185858585866000611a8a565b50505050565b6000610bd36001600461548c565b6002610be06080856154b5565b67ffffffffffffffff16610bf491906154dc565b610bfe8585611e01565b901c166003811115610c1257610c12614a65565b90505b92915050565b6001546001600160a01b03163314610c755760405162461bcd60e51b815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610754565b600080543373ffffffffffffffffffffffffffffffffffffffff19808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610ce1611496565b6105dd81611e48565b333014610d23576040517f371a732800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160008082526020820190925281610d60565b6040805180820190915260008082526020820152815260200190600190039081610d395790505b5060a08501515190915015610d9457610d918460a00151856020015186606001518760000151602001518787611fae565b90505b6040805160a0810182528551518152855160209081015167ffffffffffffffff1681830152808701518351600094840192610dd0929101614880565b60408051601f19818403018152918152908252878101516020830152018390526005549091506001600160a01b03168015610edd576040517f08d450a10000000000000000000000000000000000000000000000000000000081526001600160a01b038216906308d450a190610e4a908590600401615595565b600060405180830381600087803b158015610e6457600080fd5b505af1925050508015610e75575060015b610edd573d808015610ea3576040519150601f19603f3d011682016040523d82523d6000602084013e610ea8565b606091505b50806040517f09c253250000000000000000000000000000000000000000000000000000000081526004016107549190614880565b604086015151158015610ef257506080860151155b80610f09575060608601516001600160a01b03163b155b80610f4957506060860151610f47906001600160a01b03167f85572ffb000000000000000000000000000000000000000000000000000000006120cd565b155b15610f5657505050505050565b855160209081015167ffffffffffffffff1660009081526006909152604080822054608089015160608a015192517f3cf9798300000000000000000000000000000000000000000000000000000000815284936001600160a01b0390931692633cf9798392610fce92899261138892916004016155a8565b6000604051808303816000875af1158015610fed573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261101591908101906155e4565b50915091508161105357806040517f0a8d6e8c0000000000000000000000000000000000000000000000000000000081526004016107549190614880565b5050505050505050565b6110a06040805160e081019091526000606082018181526080830182905260a0830182905260c08301919091528190815260200160608152602001606081525090565b60ff808316600090815260026020818152604092839020835160e081018552815460608201908152600183015480881660808401526101008104881660a0840152620100009004909616151560c08201529485529182018054845181840281018401909552808552929385830193909283018282801561114957602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161112b575b50505050508152602001600382018054806020026020016040519081016040528092919081815260200182805480156111ab57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161118d575b5050505050815250509050919050565b6111c3611496565b60005b818110156107805760008383838181106111e2576111e2614f86565b9050604002018036038101906111f8919061567a565b905061120781602001516113d5565b61126c57805167ffffffffffffffff1660009081526008602090815260408083208285018051855290835281842093909355915191519182527f202f1139a3e334b6056064c0e9b19fd07e44a88d8f6e5ded571b24cf8c371f12910160405180910390a15b506001016111c6565b604080516080808201835260008083526020808401829052838501829052606080850181905267ffffffffffffffff878116845260068352928690208651948501875280546001600160a01b0381168652600160a01b810460ff16151593860193909352600160a81b909204909216948301949094526001840180549394929391840191611302906156b3565b80601f016020809104026020016040519081016040528092919081815260200182805461132e906156b3565b80156111ab5780601f10611350576101008083540402835291602001916111ab565b820191906000526020600020905b81548152906001019060200180831161135e57505050919092525091949350505050565b61138a611496565b6105dd816120e9565b61139b611496565b60005b81518110156113d1576113c98282815181106113bc576113bc614f86565b602002602001015161219f565b60010161139e565b5050565b6040805180820182523081526020810183815291517f4d61677100000000000000000000000000000000000000000000000000000000815290516001600160a01b039081166004830152915160248201526000917f00000000000000000000000000000000000000000000000000000000000000001690634d61677190604401602060405180830381865afa158015611472573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c1591906156ed565b6000546001600160a01b031633146114f05760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610754565b565b60005b81518110156113d157600082828151811061151257611512614f86565b602002602001015190506000816020015190508067ffffffffffffffff16600003611569576040517fc656089500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81516001600160a01b0316611591576040516342bcdf7f60e11b815260040160405180910390fd5b67ffffffffffffffff811660009081526006602052604081206001810180549192916115bc906156b3565b80601f01602080910402602001604051908101604052809291908181526020018280546115e8906156b3565b80156116355780601f1061160a57610100808354040283529160200191611635565b820191906000526020600020905b81548152906001019060200180831161161857829003601f168201915b5050505050905060008460600151905081516000036116ed578051600003611670576040516342bcdf7f60e11b815260040160405180910390fd5b6001830161167e828261575a565b5082547fffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffff16600160a81b17835560405167ffffffffffffffff851681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1611740565b8080519060200120828051906020012014611740576040517fc39a620500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff85166004820152602401610754565b604080860151845487516001600160a01b031673ffffffffffffffffffffffffffffffffffffffff19921515600160a01b02929092167fffffffffffffffffffffff000000000000000000000000000000000000000000909116171784555167ffffffffffffffff8516907f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b906117d890869061581a565b60405180910390a250505050508060010190506114f5565b467f0000000000000000000000000000000000000000000000000000000000000000146114f0576040517f0f01ce850000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000006004820152466024820152604401610754565b81516000036118ab576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160408051600080825260208201909252911591905b845181101561191a576119128582815181106118e0576118e0614f86565b60200260200101518461190c578583815181106118ff576118ff614f86565b60200260200101516124d7565b836124d7565b6001016118c2565b5050505050565b6040517f2cbc26bb000000000000000000000000000000000000000000000000000000008152608082901b77ffffffffffffffff000000000000000000000000000000001660048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632cbc26bb90602401602060405180830381865afa1580156119bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119e091906156ed565b156105dd576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610754565b67ffffffffffffffff811660009081526006602052604081208054600160a01b900460ff16610c15576040517fed053c5900000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610754565b60ff87811660009081526002602090815260408083208151608081018352815481526001909101548086169382019390935261010083048516918101919091526201000090910490921615156060830152873590611ae98760a46158e8565b9050826060015115611b31578451611b029060206154dc565b8651611b0f9060206154dc565b611b1a9060a06158e8565b611b2491906158e8565b611b2e90826158e8565b90505b368114611b73576040517f8e1192e100000000000000000000000000000000000000000000000000000000815260048101829052366024820152604401610754565b5081518114611bbb5781516040517f93df584c000000000000000000000000000000000000000000000000000000008152600481019190915260248101829052604401610754565b611bc36117f0565b60ff808a1660009081526003602090815260408083203384528252808320815180830190925280548086168352939491939092840191610100909104166002811115611c1157611c11614a65565b6002811115611c2257611c22614a65565b9052509050600281602001516002811115611c3f57611c3f614a65565b148015611c935750600260008b60ff1660ff168152602001908152602001600020600301816000015160ff1681548110611c7b57611c7b614f86565b6000918252602090912001546001600160a01b031633145b611cc9576040517fda0f08e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50816060015115611dab576020820151611ce49060016158fb565b60ff16855114611d20576040517f71253a2500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8351855114611d5b576040517fa75d88af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008787604051611d6d929190615914565b604051908190038120611d84918b90602001615924565b604051602081830303815290604052805190602001209050611da98a82888888612ca3565b505b6040805182815260208a81013567ffffffffffffffff169082015260ff8b16917f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef0910160405180910390a2505050505050505050565b67ffffffffffffffff8216600090815260076020526040812081611e26608085615938565b67ffffffffffffffff1681526020810191909152604001600020549392505050565b80516001600160a01b0316611e70576040516342bcdf7f60e11b815260040160405180910390fd5b80516004805460208085018051604080880180516060808b0180516001600160a01b039b8c167fffffffffffffffff000000000000000000000000000000000000000000000000909a168a17600160a01b63ffffffff988916021777ffffffffffffffffffffffffffffffffffffffffffffffff167801000000000000000000000000000000000000000000000000948816949094026001600160e01b031693909317600160e01b93871693909302929092179098556080808b0180516005805473ffffffffffffffffffffffffffffffffffffffff1916918d169190911790558451988952955185169688019690965290518316918601919091525116938301939093529151909216908201527fa55bd56595c45f517e5967a3067f3dca684445a3080e7c04a4e0d5a40cda627d9060a00160405180910390a150565b6060865167ffffffffffffffff811115611fca57611fca613e90565b60405190808252806020026020018201604052801561200f57816020015b6040805180820190915260008082526020820152815260200190600190039081611fe85790505b50905060005b87518110156120c15761209c88828151811061203357612033614f86565b602002602001015188888888888781811061205057612050614f86565b9050602002810190612062919061595f565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612e8892505050565b8282815181106120ae576120ae614f86565b6020908102919091010152600101612015565b505b9695505050505050565b60006120d88361322d565b8015610c125750610c128383613291565b336001600160a01b038216036121415760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610754565b6001805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b806040015160ff166000036121ca576000604051631b3fab5160e11b815260040161075491906159c4565b60208082015160ff8082166000908152600290935260408320600181015492939092839216900361223757606084015160018201805491151562010000027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff90921691909117905561228c565b6060840151600182015460ff620100009091041615159015151461228c576040517f87f6037c00000000000000000000000000000000000000000000000000000000815260ff84166004820152602401610754565b60a08401518051601f10156122b7576001604051631b3fab5160e11b815260040161075491906159c4565b61231d848460030180548060200260200160405190810160405280929190818152602001828054801561231357602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116122f5575b505050505061334c565b84606001511561244c5761238b8484600201805480602002602001604051908101604052809291908181526020018280548015612313576020028201919060005260206000209081546001600160a01b031681526001909101906020018083116122f557505050505061334c565b608085015180516123a59060028601906020840190613e09565b5080516001840180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1661010060ff841690810291909117909155601f1015612405576002604051631b3fab5160e11b815260040161075491906159c4565b60408701516124159060036159de565b60ff168160ff161161243d576003604051631b3fab5160e11b815260040161075491906159c4565b612449868360016133b5565b50505b612458848260026133b5565b805161246d9060038501906020840190613e09565b5060408581015160018401805460ff191660ff8316179055865180855560a088015192517fab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f547936124c69389939260028a019291906159fa565b60405180910390a161191a84613529565b81516124e281611921565b60006124ed82611a23565b60010180546124fb906156b3565b80601f0160208091040260200160405190810160405280929190818152602001828054612527906156b3565b80156125745780601f1061254957610100808354040283529160200191612574565b820191906000526020600020905b81548152906001019060200180831161255757829003601f168201915b505050602087015151929350505060008190036125bc576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84604001515181146125fa576040517f57e0e08300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008167ffffffffffffffff81111561261557612615613e90565b60405190808252806020026020018201604052801561263e578160200160208202803683370190505b50905060005b828110156127275760008760200151828151811061266457612664614f86565b602002602001015190507f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681600001516040015167ffffffffffffffff16146126f757805160409081015190517f38432a2200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610754565b6127018186613545565b83838151811061271357612713614f86565b602090810291909101015250600101612644565b50600061273e858389606001518a60800151613667565b905080600003612786576040517f7dd17a7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff86166004820152602401610754565b8551151560005b84811015610b515760005a905060008a6020015183815181106127b2576127b2614f86565b6020026020010151905060006127d08a836000015160600151610bc5565b905060008160038111156127e6576127e6614a65565b14806128035750600381600381111561280157612801614a65565b145b61285b578151606001516040805167ffffffffffffffff808e16825290921660208301527f3b575419319662b2a6f5e2467d84521517a3382b908eb3d557bb3fdb0c50e23c91015b60405180910390a1505050612c9b565b841561292b57600454600090600160a01b900463ffffffff1661287e884261548c565b119050808061289e5750600382600381111561289c5761289c614a65565b145b6128e0576040517fa9cfc86200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8c166004820152602401610754565b8b85815181106128f2576128f2614f86565b6020026020010151600014612925578b858151811061291357612913614f86565b60200260200101518360800181815250505b5061298c565b600081600381111561293f5761293f614a65565b1461298c578151606001516040805167ffffffffffffffff808e16825290921660208301527f3ef2a99c550a751d4b0b261268f05a803dfb049ab43616a1ffb388f61fe65120910161284b565b81516080015167ffffffffffffffff1615612a7b5760008160038111156129b5576129b5614a65565b03612a7b5781516080015160208301516040517fe0e03cae0000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169263e0e03cae92612a2c928f929190600401615aa6565b6020604051808303816000875af1158015612a4b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a6f91906156ed565b612a7b57505050612c9b565b60008c604001518581518110612a9357612a93614f86565b6020026020010151905080518360a001515114612af7578251606001516040517f1cfe6d8b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808e1660048301529091166024820152604401610754565b612b0b8b84600001516060015160016136bd565b600080612b188584613765565b91509150612b2f8d866000015160600151846136bd565b8715612b9f576003826003811115612b4957612b49614a65565b03612b9f576000846003811115612b6257612b62614a65565b14612b9f578451516040517f2b11b8d900000000000000000000000000000000000000000000000000000000815261075491908390600401615ad3565b6002826003811115612bb357612bb3614a65565b14612c0d576003826003811115612bcc57612bcc614a65565b14612c0d578451606001516040517f926c5a3e000000000000000000000000000000000000000000000000000000008152610754918f918590600401615aec565b84600001516000015185600001516060015167ffffffffffffffff168e67ffffffffffffffff167f05665fe9ad095383d018353f4cbcba77e84db27dd215081bbf7cdf9ae6fbe48b8d8b81518110612c6757612c67614f86565b602002602001015186865a612c7c908e61548c565b604051612c8c9493929190615b12565b60405180910390a45050505050505b60010161278d565b8251600090815b81811015611053576000600188868460208110612cc957612cc9614f86565b612cd691901a601b6158fb565b898581518110612ce857612ce8614f86565b6020026020010151898681518110612d0257612d02614f86565b602002602001015160405160008152602001604052604051612d40949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015612d62573d6000803e3d6000fd5b505060408051601f1981015160ff808e166000908152600360209081528582206001600160a01b03851683528152858220858701909652855480841686529397509095509293928401916101009004166002811115612dc357612dc3614a65565b6002811115612dd457612dd4614a65565b9052509050600181602001516002811115612df157612df1614a65565b14612e28576040517fca31867a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051600160ff9091161b851615612e6b576040517ff67bc7c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806000015160ff166001901b851794505050806001019050612caa565b60408051808201909152600080825260208201526000612eab876020015161382f565b6040517fbbe4f6db0000000000000000000000000000000000000000000000000000000081526001600160a01b0380831660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063bbe4f6db90602401602060405180830381865afa158015612f30573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f549190615b49565b90506001600160a01b0381161580612f9c5750612f9a6001600160a01b0382167faff2afbf000000000000000000000000000000000000000000000000000000006120cd565b155b15612fde576040517fae9b4ce90000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152602401610754565b60045460009081906130009089908690600160e01b900463ffffffff166138d5565b9150915060008060006130cd6040518061010001604052808e81526020018c67ffffffffffffffff1681526020018d6001600160a01b031681526020018f606001518152602001896001600160a01b031681526020018f6000015181526020018f6040015181526020018b81525060405160240161307e9190615b66565b60408051601f198184030181529190526020810180516001600160e01b03167f390775370000000000000000000000000000000000000000000000000000000017905287866113886084613a03565b9250925092508261310c57816040517fe1cd55090000000000000000000000000000000000000000000000000000000081526004016107549190614880565b81516020146131545781516040517f78ef8024000000000000000000000000000000000000000000000000000000008152602060048201526024810191909152604401610754565b60008280602001905181019061316a9190615c33565b9050866001600160a01b03168c6001600160a01b0316146131ff57600061319b8d8a613196868a61548c565b6138d5565b509050868110806131b55750816131b2888361548c565b14155b156131fd576040517fa966e21f000000000000000000000000000000000000000000000000000000008152600481018390526024810188905260448101829052606401610754565b505b604080518082019091526001600160a01b039098168852602088015250949550505050505095945050505050565b6000613259827f01ffc9a700000000000000000000000000000000000000000000000000000000613291565b8015610c15575061328a827fffffffff00000000000000000000000000000000000000000000000000000000613291565b1592915050565b6040517fffffffff0000000000000000000000000000000000000000000000000000000082166024820152600090819060440160408051601f19818403018152919052602080820180516001600160e01b03167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825192935060009283928392909183918a617530fa92503d91506000519050828015613335575060208210155b80156133415750600081115b979650505050505050565b60005b81518110156107805760ff83166000908152600360205260408120835190919084908490811061338157613381614f86565b6020908102919091018101516001600160a01b03168252810191909152604001600020805461ffff1916905560010161334f565b60005b8251811015610bbf5760008382815181106133d5576133d5614f86565b60200260200101519050600060028111156133f2576133f2614a65565b60ff80871660009081526003602090815260408083206001600160a01b0387168452909152902054610100900416600281111561343157613431614a65565b14613452576004604051631b3fab5160e11b815260040161075491906159c4565b6001600160a01b038116613492576040517fd6c62c9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052808360ff1681526020018460028111156134b8576134b8614a65565b905260ff80871660009081526003602090815260408083206001600160a01b0387168452825290912083518154931660ff198416811782559184015190929091839161ffff19161761010083600281111561351557613515614a65565b0217905550905050508060010190506133b8565b60ff81166105dd576009805467ffffffffffffffff1916905550565b81516020808201516040928301519251600093849361358b937f2425b0b9f9054c76ff151b0a175b18f37a4a4e82013a72e9f15c9caa095ed21f93909291889101615c4c565b60408051601f1981840301815290829052805160209182012086518051888401516060808b0151908401516080808d015195015195976135d49794969395929491939101615c7f565b604051602081830303815290604052805190602001208560400151805190602001208660a0015160405160200161360b9190615d91565b60408051601f198184030181528282528051602091820120908301969096528101939093526060830191909152608082015260a081019190915260c0015b60405160208183030381529060405280519060200120905092915050565b600080613675858585613b29565b9050613680816113d5565b61368e5760009150506136b5565b67ffffffffffffffff86166000908152600860209081526040808320938352929052205490505b949350505050565b600060026136cc6080856154b5565b67ffffffffffffffff166136e091906154dc565b905060006136ee8585611e01565b9050816136fd6001600461548c565b901b19168183600381111561371457613714614a65565b67ffffffffffffffff871660009081526007602052604081209190921b92909217918291613743608088615938565b67ffffffffffffffff1681526020810191909152604001600020555050505050565b6040517fa80036b4000000000000000000000000000000000000000000000000000000008152600090606090309063a80036b4906137a99087908790600401615df1565b600060405180830381600087803b1580156137c357600080fd5b505af19250505080156137d4575060015b613813573d808015613802576040519150601f19603f3d011682016040523d82523d6000602084013e613807565b606091505b50600392509050613828565b50506040805160208101909152600081526002905b9250929050565b6000815160201461386e57816040517f8d666f600000000000000000000000000000000000000000000000000000000081526004016107549190614880565b6000828060200190518101906138849190615c33565b90506001600160a01b0381118061389c575061040081105b15610c1557826040517f8d666f600000000000000000000000000000000000000000000000000000000081526004016107549190614880565b600080600080600061394f8860405160240161390091906001600160a01b0391909116815260200190565b60408051601f198184030181529190526020810180516001600160e01b03167f70a082310000000000000000000000000000000000000000000000000000000017905288886113886084613a03565b9250925092508261398e57816040517fe1cd55090000000000000000000000000000000000000000000000000000000081526004016107549190614880565b60208251146139d65781516040517f78ef8024000000000000000000000000000000000000000000000000000000008152602060048201526024810191909152604401610754565b818060200190518101906139ea9190615c33565b6139f4828861548c565b94509450505050935093915050565b6000606060008361ffff1667ffffffffffffffff811115613a2657613a26613e90565b6040519080825280601f01601f191660200182016040528015613a50576020820181803683370190505b509150863b613a83577f0c3b563c0000000000000000000000000000000000000000000000000000000060005260046000fd5b5a85811015613ab6577fafa32a2c0000000000000000000000000000000000000000000000000000000060005260046000fd5b8590036040810481038710613aef577f37c3be290000000000000000000000000000000000000000000000000000000060005260046000fd5b505a6000808a5160208c0160008c8cf193505a900390503d84811115613b125750835b808352806000602085013e50955095509592505050565b8251825160009190818303613b6a576040517f11a6b26400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6101018211801590613b7e57506101018111155b613b9b576040516309bde33960e01b815260040160405180910390fd5b60001982820101610100811115613bc5576040516309bde33960e01b815260040160405180910390fd5b80600003613bf25786600081518110613be057613be0614f86565b60200260200101519350505050613dc1565b60008167ffffffffffffffff811115613c0d57613c0d613e90565b604051908082528060200260200182016040528015613c36578160200160208202803683370190505b50905060008080805b85811015613d605760006001821b8b811603613c9a5788851015613c83578c5160018601958e918110613c7457613c74614f86565b60200260200101519050613cbc565b8551600185019487918110613c7457613c74614f86565b8b5160018401938d918110613cb157613cb1614f86565b602002602001015190505b600089861015613cec578d5160018701968f918110613cdd57613cdd614f86565b60200260200101519050613d0e565b8651600186019588918110613d0357613d03614f86565b602002602001015190505b82851115613d2f576040516309bde33960e01b815260040160405180910390fd5b613d398282613dc8565b878481518110613d4b57613d4b614f86565b60209081029190910101525050600101613c3f565b506001850382148015613d7257508683145b8015613d7d57508581145b613d9a576040516309bde33960e01b815260040160405180910390fd5b836001860381518110613daf57613daf614f86565b60200260200101519750505050505050505b9392505050565b6000818310613de057613ddb8284613de6565b610c12565b610c1283835b604080516001602082015290810183905260608101829052600090608001613649565b828054828255906000526020600020908101928215613e6b579160200282015b82811115613e6b578251825473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03909116178255602090920191600190910190613e29565b50613e77929150613e7b565b5090565b5b80821115613e775760008155600101613e7c565b634e487b7160e01b600052604160045260246000fd5b6040516080810167ffffffffffffffff81118282101715613ec957613ec9613e90565b60405290565b60405160a0810167ffffffffffffffff81118282101715613ec957613ec9613e90565b60405160c0810167ffffffffffffffff81118282101715613ec957613ec9613e90565b6040805190810167ffffffffffffffff81118282101715613ec957613ec9613e90565b6040516060810167ffffffffffffffff81118282101715613ec957613ec9613e90565b604051601f8201601f1916810167ffffffffffffffff81118282101715613f8457613f84613e90565b604052919050565b600067ffffffffffffffff821115613fa657613fa6613e90565b5060051b60200190565b6001600160a01b03811681146105dd57600080fd5b803567ffffffffffffffff81168114613fdd57600080fd5b919050565b80151581146105dd57600080fd5b8035613fdd81613fe2565b600067ffffffffffffffff82111561401557614015613e90565b50601f01601f191660200190565b600082601f83011261403457600080fd5b813561404761404282613ffb565b613f5b565b81815284602083860101111561405c57600080fd5b816020850160208301376000918101602001919091529392505050565b6000602080838503121561408c57600080fd5b823567ffffffffffffffff808211156140a457600080fd5b818501915085601f8301126140b857600080fd5b81356140c661404282613f8c565b81815260059190911b830184019084810190888311156140e557600080fd5b8585015b8381101561418b578035858111156141015760008081fd5b86016080818c03601f19018113156141195760008081fd5b614121613ea6565b8983013561412e81613fb0565b8152604061413d848201613fc5565b8b83015260608085013561415081613fe2565b8383015292840135928984111561416957600091508182fd5b6141778f8d86880101614023565b9083015250855250509186019186016140e9565b5098975050505050505050565b600060a082840312156141aa57600080fd5b6141b2613ecf565b9050813581526141c460208301613fc5565b60208201526141d560408301613fc5565b60408201526141e660608301613fc5565b60608201526141f760808301613fc5565b608082015292915050565b8035613fdd81613fb0565b600082601f83011261421e57600080fd5b8135602061422e61404283613f8c565b82815260059290921b8401810191818101908684111561424d57600080fd5b8286015b848110156120c157803567ffffffffffffffff808211156142725760008081fd5b818901915060a080601f19848d0301121561428d5760008081fd5b614295613ecf565b87840135838111156142a75760008081fd5b6142b58d8a83880101614023565b825250604080850135848111156142cc5760008081fd5b6142da8e8b83890101614023565b8a84015250606080860135858111156142f35760008081fd5b6143018f8c838a0101614023565b838501525060809150818601358184015250828501359250838311156143275760008081fd5b6143358d8a85880101614023565b908201528652505050918301918301614251565b6000610140828403121561435c57600080fd5b614364613ef2565b90506143708383614198565b815260a082013567ffffffffffffffff8082111561438d57600080fd5b61439985838601614023565b602084015260c08401359150808211156143b257600080fd5b6143be85838601614023565b60408401526143cf60e08501614202565b606084015261010084013560808401526101208401359150808211156143f457600080fd5b506144018482850161420d565b60a08301525092915050565b600082601f83011261441e57600080fd5b8135602061442e61404283613f8c565b82815260059290921b8401810191818101908684111561444d57600080fd5b8286015b848110156120c157803567ffffffffffffffff8111156144715760008081fd5b61447f8986838b0101614349565b845250918301918301614451565b600082601f83011261449e57600080fd5b813560206144ae61404283613f8c565b82815260059290921b840181019181810190868411156144cd57600080fd5b8286015b848110156120c157803567ffffffffffffffff808211156144f157600080fd5b818901915089603f83011261450557600080fd5b8582013561451561404282613f8c565b81815260059190911b830160400190878101908c83111561453557600080fd5b604085015b8381101561456e5780358581111561455157600080fd5b6145608f6040838a0101614023565b84525091890191890161453a565b508752505050928401925083016144d1565b600082601f83011261459157600080fd5b813560206145a161404283613f8c565b8083825260208201915060208460051b8701019350868411156145c357600080fd5b602086015b848110156120c157803583529183019183016145c8565b600082601f8301126145f057600080fd5b8135602061460061404283613f8c565b82815260059290921b8401810191818101908684111561461f57600080fd5b8286015b848110156120c157803567ffffffffffffffff808211156146445760008081fd5b818901915060a080601f19848d0301121561465f5760008081fd5b614667613ecf565b614672888501613fc5565b8152604080850135848111156146885760008081fd5b6146968e8b8389010161440d565b8a84015250606080860135858111156146af5760008081fd5b6146bd8f8c838a010161448d565b83850152506080915081860135858111156146d85760008081fd5b6146e68f8c838a0101614580565b9184019190915250919093013590830152508352918301918301614623565b600080604080848603121561471957600080fd5b833567ffffffffffffffff8082111561473157600080fd5b61473d878388016145df565b945060209150818601358181111561475457600080fd5b8601601f8101881361476557600080fd5b803561477361404282613f8c565b81815260059190911b8201840190848101908a83111561479257600080fd5b8584015b8381101561481e578035868111156147ae5760008081fd5b8501603f81018d136147c05760008081fd5b878101356147d061404282613f8c565b81815260059190911b82018a0190898101908f8311156147f05760008081fd5b928b01925b8284101561480e5783358252928a0192908a01906147f5565b8652505050918601918601614796565b50809750505050505050509250929050565b60005b8381101561484b578181015183820152602001614833565b50506000910152565b6000815180845261486c816020860160208601614830565b601f01601f19169290920160200192915050565b602081526000610c126020830184614854565b8060608101831015610c1557600080fd5b60008083601f8401126148b657600080fd5b50813567ffffffffffffffff8111156148ce57600080fd5b60208301915083602082850101111561382857600080fd5b60008083601f8401126148f857600080fd5b50813567ffffffffffffffff81111561491057600080fd5b6020830191508360208260051b850101111561382857600080fd5b60008060008060008060008060e0898b03121561494757600080fd5b6149518a8a614893565b9750606089013567ffffffffffffffff8082111561496e57600080fd5b61497a8c838d016148a4565b909950975060808b013591508082111561499357600080fd5b61499f8c838d016148e6565b909750955060a08b01359150808211156149b857600080fd5b506149c58b828c016148e6565b999c989b50969995989497949560c00135949350505050565b6000806000608084860312156149f357600080fd5b6149fd8585614893565b9250606084013567ffffffffffffffff811115614a1957600080fd5b614a25868287016148a4565b9497909650939450505050565b60008060408385031215614a4557600080fd5b614a4e83613fc5565b9150614a5c60208401613fc5565b90509250929050565b634e487b7160e01b600052602160045260246000fd5b60048110614a8b57614a8b614a65565b9052565b60208101610c158284614a7b565b600060208284031215614aaf57600080fd5b813567ffffffffffffffff811115614ac657600080fd5b820160a08185031215613dc157600080fd5b803563ffffffff81168114613fdd57600080fd5b600060a08284031215614afe57600080fd5b614b06613ecf565b8235614b1181613fb0565b8152614b1f60208401614ad8565b6020820152614b3060408401614ad8565b6040820152614b4160608401614ad8565b60608201526080830135614b5481613fb0565b60808201529392505050565b600080600060408486031215614b7557600080fd5b833567ffffffffffffffff80821115614b8d57600080fd5b614b9987838801614349565b94506020860135915080821115614baf57600080fd5b50614a25868287016148e6565b803560ff81168114613fdd57600080fd5b600060208284031215614bdf57600080fd5b610c1282614bbc565b60008151808452602080850194506020840160005b83811015614c225781516001600160a01b031687529582019590820190600101614bfd565b509495945050505050565b60208152600082518051602084015260ff602082015116604084015260ff604082015116606084015260608101511515608084015250602083015160c060a0840152614c7c60e0840182614be8565b90506040840151601f198483030160c0850152614c998282614be8565b95945050505050565b60008060408385031215614cb557600080fd5b614cbe83613fc5565b946020939093013593505050565b60008060208385031215614cdf57600080fd5b823567ffffffffffffffff80821115614cf757600080fd5b818501915085601f830112614d0b57600080fd5b813581811115614d1a57600080fd5b8660208260061b8501011115614d2f57600080fd5b60209290920196919550909350505050565b600060208284031215614d5357600080fd5b610c1282613fc5565b602081526001600160a01b03825116602082015260208201511515604082015267ffffffffffffffff6040830151166060820152600060608301516080808401526136b560a0840182614854565b600060208284031215614dbc57600080fd5b8135613dc181613fb0565b600082601f830112614dd857600080fd5b81356020614de861404283613f8c565b8083825260208201915060208460051b870101935086841115614e0a57600080fd5b602086015b848110156120c1578035614e2281613fb0565b8352918301918301614e0f565b60006020808385031215614e4257600080fd5b823567ffffffffffffffff80821115614e5a57600080fd5b818501915085601f830112614e6e57600080fd5b8135614e7c61404282613f8c565b81815260059190911b83018401908481019088831115614e9b57600080fd5b8585015b8381101561418b57803585811115614eb657600080fd5b860160c0818c03601f19011215614ecd5760008081fd5b614ed5613ef2565b8882013581526040614ee8818401614bbc565b8a8301526060614ef9818501614bbc565b8284015260809150614f0c828501613ff0565b9083015260a08381013589811115614f245760008081fd5b614f328f8d83880101614dc7565b838501525060c0840135915088821115614f4c5760008081fd5b614f5a8e8c84870101614dc7565b9083015250845250918601918601614e9f565b600060208284031215614f7f57600080fd5b5035919050565b634e487b7160e01b600052603260045260246000fd5b80356001600160e01b0381168114613fdd57600080fd5b600082601f830112614fc457600080fd5b81356020614fd461404283613f8c565b82815260069290921b84018101918181019086841115614ff357600080fd5b8286015b848110156120c157604081890312156150105760008081fd5b615018613f15565b61502182613fc5565b815261502e858301614f9c565b81860152835291830191604001614ff7565b600082601f83011261505157600080fd5b8135602061506161404283613f8c565b82815260079290921b8401810191818101908684111561508057600080fd5b8286015b848110156120c157808803608081121561509e5760008081fd5b6150a6613f38565b6150af83613fc5565b8152604080601f19840112156150c55760008081fd5b6150cd613f15565b92506150da878501613fc5565b83526150e7818501613fc5565b8388015281870192909252606083013591810191909152835291830191608001615084565b6000602080838503121561511f57600080fd5b823567ffffffffffffffff8082111561513757600080fd5b8185019150604080838803121561514d57600080fd5b615155613f15565b83358381111561516457600080fd5b84016040818a03121561517657600080fd5b61517e613f15565b81358581111561518d57600080fd5b8201601f81018b1361519e57600080fd5b80356151ac61404282613f8c565b81815260069190911b8201890190898101908d8311156151cb57600080fd5b928a01925b8284101561521b5787848f0312156151e85760008081fd5b6151f0613f15565b84356151fb81613fb0565b8152615208858d01614f9c565b818d0152825292870192908a01906151d0565b84525050508187013593508484111561523357600080fd5b61523f8a858401614fb3565b818801528252508385013591508282111561525957600080fd5b61526588838601615040565b85820152809550505050505092915050565b805160408084528151848201819052600092602091908201906060870190855b818110156152ce57835180516001600160a01b031684528501516001600160e01b0316858401529284019291850191600101615297565b50508583015187820388850152805180835290840192506000918401905b80831015615328578351805167ffffffffffffffff1683528501516001600160e01b0316858301529284019260019290920191908501906152ec565b50979650505050505050565b602081526000610c126020830184615277565b67ffffffffffffffff8316815260608101613dc16020830184805167ffffffffffffffff908116835260209182015116910152565b634e487b7160e01b600052601160045260246000fd5b67ffffffffffffffff8181168382160190808211156153b3576153b361537c565b5092915050565b6000602080835260608451604080848701526153d96060870183615277565b87850151878203601f19016040890152805180835290860193506000918601905b8083101561418b57845167ffffffffffffffff81511683528781015161543989850182805167ffffffffffffffff908116835260209182015116910152565b508401518287015293860193600192909201916080909101906153fa565b60006020828403121561546957600080fd5b813567ffffffffffffffff81111561548057600080fd5b6136b5848285016145df565b81810381811115610c1557610c1561537c565b634e487b7160e01b600052601260045260246000fd5b600067ffffffffffffffff808416806154d0576154d061549f565b92169190910692915050565b8082028115828204841417610c1557610c1561537c565b805182526000602067ffffffffffffffff81840151168185015260408084015160a0604087015261552760a0870182614854565b9050606085015186820360608801526155408282614854565b608087810151898303918a01919091528051808352908601935060009250908501905b8083101561532857835180516001600160a01b0316835286015186830152928501926001929092019190840190615563565b602081526000610c1260208301846154f3565b6080815260006155bb60808301876154f3565b61ffff9590951660208301525060408101929092526001600160a01b0316606090910152919050565b6000806000606084860312156155f957600080fd5b835161560481613fe2565b602085015190935067ffffffffffffffff81111561562157600080fd5b8401601f8101861361563257600080fd5b805161564061404282613ffb565b81815287602083850101111561565557600080fd5b615666826020830160208601614830565b809450505050604084015190509250925092565b60006040828403121561568c57600080fd5b615694613f15565b61569d83613fc5565b8152602083013560208201528091505092915050565b600181811c908216806156c757607f821691505b6020821081036156e757634e487b7160e01b600052602260045260246000fd5b50919050565b6000602082840312156156ff57600080fd5b8151613dc181613fe2565b601f821115610780576000816000526020600020601f850160051c810160208610156157335750805b601f850160051c820191505b818110156157525782815560010161573f565b505050505050565b815167ffffffffffffffff81111561577457615774613e90565b6157888161578284546156b3565b8461570a565b602080601f8311600181146157bd57600084156157a55750858301515b600019600386901b1c1916600185901b178555615752565b600085815260208120601f198616915b828110156157ec578886015182559484019460019091019084016157cd565b508582101561580a5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6000602080835283546001600160a01b038116602085015260ff8160a01c161515604085015267ffffffffffffffff8160a81c1660608501525060018085016080808601526000815461586c816156b3565b8060a089015260c0600183166000811461588d57600181146158a9576158d9565b60ff19841660c08b015260c083151560051b8b010194506158d9565b85600052602060002060005b848110156158d05781548c82018501529088019089016158b5565b8b0160c0019550505b50929998505050505050505050565b80820180821115610c1557610c1561537c565b60ff8181168382160190811115610c1557610c1561537c565b8183823760009101908152919050565b828152606082602083013760800192915050565b600067ffffffffffffffff808416806159535761595361549f565b92169190910492915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261599457600080fd5b83018035915067ffffffffffffffff8211156159af57600080fd5b60200191503681900382131561382857600080fd5b60208101600583106159d8576159d8614a65565b91905290565b60ff81811683821602908116908181146153b3576153b361537c565b600060a0820160ff881683526020878185015260a0604085015281875480845260c0860191508860005282600020935060005b81811015615a525784546001600160a01b031683526001948501949284019201615a2d565b50508481036060860152865180825290820192508187019060005b81811015615a925782516001600160a01b031685529383019391830191600101615a6d565b50505060ff851660808501525090506120c3565b600067ffffffffffffffff808616835280851660208401525060606040830152614c996060830184614854565b8281526040602082015260006136b56040830184614854565b67ffffffffffffffff848116825283166020820152606081016136b56040830184614a7b565b848152615b226020820185614a7b565b608060408201526000615b386080830185614854565b905082606083015295945050505050565b600060208284031215615b5b57600080fd5b8151613dc181613fb0565b6020815260008251610100806020850152615b85610120850183614854565b91506020850151615ba2604086018267ffffffffffffffff169052565b5060408501516001600160a01b038116606086015250606085015160808501526080850151615bdc60a08601826001600160a01b03169052565b5060a0850151601f19808685030160c0870152615bf98483614854565b935060c08701519150808685030160e0870152615c168483614854565b935060e08701519150808685030183870152506120c38382614854565b600060208284031215615c4557600080fd5b5051919050565b848152600067ffffffffffffffff8086166020840152808516604084015250608060608301526120c36080830184614854565b86815260c060208201526000615c9860c0830188614854565b6001600160a01b039690961660408301525067ffffffffffffffff9384166060820152608081019290925290911660a09091015292915050565b600082825180855260208086019550808260051b84010181860160005b84811015615d8457601f19868403018952815160a08151818652615d1582870182614854565b9150508582015185820387870152615d2d8282614854565b91505060408083015186830382880152615d478382614854565b92505050606080830151818701525060808083015192508582038187015250615d708183614854565b9a86019a9450505090830190600101615cef565b5090979650505050505050565b602081526000610c126020830184615cd2565b60008282518085526020808601955060208260051b8401016020860160005b84811015615d8457601f19868403018952615ddf838351614854565b98840198925090830190600101615dc3565b604081526000835180516040840152602081015167ffffffffffffffff80821660608601528060408401511660808601528060608401511660a08601528060808401511660c086015250505060208401516101408060e0850152615e59610180850183614854565b915060408601517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08086850301610100870152615e968483614854565b935060608801519150615eb56101208701836001600160a01b03169052565b60808801518387015260a0880151925080868503016101608701525050615edc8282615cd2565b9150508281036020840152614c998185615da456fea164736f6c6343000818000a", + Bin: "0x6101206040523480156200001257600080fd5b5060405162006bcd38038062006bcd8339810160408190526200003591620008c7565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf81620001fa565b5050466080525060208301516001600160a01b03161580620000ec575060408301516001600160a01b0316155b8062000103575060608301516001600160a01b0316155b1562000122576040516342bcdf7f60e11b815260040160405180910390fd5b82516001600160401b03166000036200014e5760405163c656089560e01b815260040160405180910390fd5b82516001600160401b0390811660a052602080850180516001600160a01b0390811660c05260408088018051831660e0526060808a01805185166101005283518b519098168852945184169587019590955251821690850152905116908201527f683eb52ee924eb817377cfa8f41f238f4bb7a877da5267869dfffbad85f564d89060800160405180910390a1620001e682620002a5565b620001f181620003c1565b50505062000c67565b336001600160a01b03821603620002545760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b0316620002ce576040516342bcdf7f60e11b815260040160405180910390fd5b80516004805460208085018051604080880180516060808b0180516001600160a01b039b8c166001600160c01b0319909a168a17600160a01b63ffffffff98891602176001600160c01b0316600160c01b948816949094026001600160e01b031693909317600160e01b93871693909302929092179098556080808b018051600580546001600160a01b031916918d169190911790558451988952955185169688019690965290518316918601919091525116938301939093529151909216908201527fa55bd56595c45f517e5967a3067f3dca684445a3080e7c04a4e0d5a40cda627d9060a00160405180910390a150565b60005b815181101562000666576000828281518110620003e557620003e562000a1d565b60200260200101519050600081602001519050806001600160401b0316600003620004235760405163c656089560e01b815260040160405180910390fd5b81516001600160a01b03166200044c576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160401b0381166000908152600660205260408120600181018054919291620004789062000a33565b80601f0160208091040260200160405190810160405280929190818152602001828054620004a69062000a33565b8015620004f75780601f10620004cb57610100808354040283529160200191620004f7565b820191906000526020600020905b815481529060010190602001808311620004d957829003601f168201915b5050505050905060008460600151905081516000036200059e57805160000362000534576040516342bcdf7f60e11b815260040160405180910390fd5b6001830162000544828262000ac4565b508254600160a81b600160e81b031916600160a81b1783556040516001600160401b03851681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1620005d9565b8080519060200120828051906020012014620005d95760405163c39a620560e01b81526001600160401b038516600482015260240162000083565b604080860151845487516001600160a01b03166001600160a01b0319921515600160a01b02929092166001600160a81b031990911617178455516001600160401b038516907f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b906200064d90869062000b90565b60405180910390a25050505050806001019050620003c4565b5050565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b0381118282101715620006a557620006a56200066a565b60405290565b604051601f8201601f191681016001600160401b0381118282101715620006d657620006d66200066a565b604052919050565b80516001600160401b0381168114620006f657600080fd5b919050565b6001600160a01b03811681146200071157600080fd5b50565b805163ffffffff81168114620006f657600080fd5b6000601f83601f8401126200073d57600080fd5b825160206001600160401b03808311156200075c576200075c6200066a565b8260051b6200076d838201620006ab565b93845286810183019383810190898611156200078857600080fd5b84890192505b85831015620008ba57825184811115620007a85760008081fd5b89016080601f19828d038101821315620007c25760008081fd5b620007cc62000680565b88840151620007db81620006fb565b81526040620007ec858201620006de565b8a8301526060808601518015158114620008065760008081fd5b838301529385015193898511156200081e5760008081fd5b84860195508f603f8701126200083657600094508485fd5b8a8601519450898511156200084f576200084f6200066a565b620008608b858f88011601620006ab565b93508484528f82868801011115620008785760008081fd5b60005b8581101562000898578681018301518582018d01528b016200087b565b5060009484018b0194909452509182015283525091840191908401906200078e565b9998505050505050505050565b6000806000838503610140811215620008df57600080fd5b6080811215620008ee57600080fd5b620008f862000680565b6200090386620006de565b815260208601516200091581620006fb565b602082015260408601516200092a81620006fb565b604082015260608601516200093f81620006fb565b6060820152935060a0607f19820112156200095957600080fd5b5060405160a081016001600160401b0380821183831017156200098057620009806200066a565b81604052608087015191506200099682620006fb565b818352620009a760a0880162000714565b6020840152620009ba60c0880162000714565b6040840152620009cd60e0880162000714565b60608401526101008701519150620009e582620006fb565b608083018290526101208701519294508083111562000a0357600080fd5b505062000a138682870162000729565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b600181811c9082168062000a4857607f821691505b60208210810362000a6957634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111562000abf576000816000526020600020601f850160051c8101602086101562000a9a5750805b601f850160051c820191505b8181101562000abb5782815560010162000aa6565b5050505b505050565b81516001600160401b0381111562000ae05762000ae06200066a565b62000af88162000af1845462000a33565b8462000a6f565b602080601f83116001811462000b30576000841562000b175750858301515b600019600386901b1c1916600185901b17855562000abb565b600085815260208120601f198616915b8281101562000b615788860151825594840194600190910190840162000b40565b508582101562000b805787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b602080825282546001600160a01b0381168383015260a081901c60ff161515604084015260a81c6001600160401b0316606083015260808083015260018084018054600093929190849062000be58162000a33565b8060a089015260c0600183166000811462000c09576001811462000c265762000c58565b60ff19841660c08b015260c083151560051b8b0101945062000c58565b85600052602060002060005b8481101562000c4f5781548c820185015290880190890162000c32565b8b0160c0019550505b50929998505050505050505050565b60805160a05160c05160e05161010051615ef762000cd66000396000818161026601526129ee0152600081816102370152612ee20152600081816102080152818161142b015261196d0152600081816101d801526126690152600081816117f3015261183f0152615ef76000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806385572ffb116100d8578063ccd37ba31161008c578063f2fde38b11610066578063f2fde38b14610583578063f716f99f14610596578063ff888fb1146105a957600080fd5b8063ccd37ba31461050b578063d2a15d3514610550578063e9d68a8e1461056357600080fd5b8063991a5018116100bd578063991a5018146104c5578063a80036b4146104d8578063c673e584146104eb57600080fd5b806385572ffb1461049c5780638da5cb5b146104aa57600080fd5b8063311cd5131161012f5780635e36480c116101145780635e36480c146103785780637437ff9f1461039857806379ba50971461049457600080fd5b8063311cd513146103495780633f4b04aa1461035c57600080fd5b806306285c691161016057806306285c69146101a4578063181f5a77146102ed5780632d04ab761461033657600080fd5b806304666f9c1461017c57806305d938b514610191575b600080fd5b61018f61018a366004614072565b6105cc565b005b61018f61019f3660046146fe565b6105e0565b61029660408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316815250905090565b6040516102e49190815167ffffffffffffffff1681526020808301516001600160a01b0390811691830191909152604080840151821690830152606092830151169181019190915260800190565b60405180910390f35b6103296040518060400160405280601181526020017f4f666652616d7020312e362e302d64657600000000000000000000000000000081525081565b6040516102e49190614879565b61018f610344366004614924565b610785565b61018f6103573660046149d7565b610b5c565b60095460405167ffffffffffffffff90911681526020016102e4565b61038b610386366004614a2b565b610bc5565b6040516102e49190614a88565b6104376040805160a081018252600080825260208201819052918101829052606081018290526080810191909152506040805160a0810182526004546001600160a01b03808216835263ffffffff600160a01b83048116602085015278010000000000000000000000000000000000000000000000008304811694840194909452600160e01b9091049092166060820152600554909116608082015290565b6040516102e49190600060a0820190506001600160a01b03808451168352602084015163ffffffff808216602086015280604087015116604086015280606087015116606086015250508060808501511660808401525092915050565b61018f610c1b565b61018f610177366004614a96565b6000546040516001600160a01b0390911681526020016102e4565b61018f6104d3366004614ae5565b610cd9565b61018f6104e6366004614b59565b610cea565b6104fe6104f9366004614bc6565b61105d565b6040516102e49190614c26565b610542610519366004614c9b565b67ffffffffffffffff919091166000908152600860209081526040808320938352929052205490565b6040519081526020016102e4565b61018f61055e366004614cc5565b6111bb565b610576610571366004614d3a565b611275565b6040516102e49190614d55565b61018f610591366004614da3565b611382565b61018f6105a4366004614e28565b611393565b6105bc6105b7366004614f66565b6113d5565b60405190151581526020016102e4565b6105d4611496565b6105dd816114f2565b50565b6105e86117f0565b815181518114610624576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8181101561077557600084828151811061064357610643614f7f565b6020026020010151905060008160200151519050600085848151811061066b5761066b614f7f565b60200260200101519050805182146106af576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b828110156107665760008282815181106106ce576106ce614f7f565b602002602001015190508060001461075d57846020015182815181106106f6576106f6614f7f565b60200260200101516080015181101561075d5784516040517fc8e9605100000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260248101839052604481018290526064015b60405180910390fd5b506001016106b2565b50505050806001019050610627565b506107808383611871565b505050565b600061079387890189615105565b805151519091501515806107ac57508051602001515115155b156108ac5760095460208a01359067ffffffffffffffff8083169116101561086b576009805467ffffffffffffffff191667ffffffffffffffff83161790556004805483516040517f3937306f0000000000000000000000000000000000000000000000000000000081526001600160a01b0390921692633937306f9261083492910161532d565b600060405180830381600087803b15801561084e57600080fd5b505af1158015610862573d6000803e3d6000fd5b505050506108aa565b8160200151516000036108aa576040517f2261116700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b60005b816020015151811015610aa5576000826020015182815181106108d4576108d4614f7f565b602002602001015190506000816000015190506108f081611921565b60006108fb82611a23565b602084015151815491925067ffffffffffffffff908116600160a81b9092041614158061093f575060208084015190810151905167ffffffffffffffff9182169116115b1561097f57825160208401516040517feefb0cac000000000000000000000000000000000000000000000000000000008152610754929190600401615340565b6040830151806109bb576040517f504570e300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b835167ffffffffffffffff16600090815260086020908152604080832084845290915290205415610a2e5783516040517f32cf0cbf00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260248101829052604401610754565b6020808501510151610a4190600161538b565b82547fffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffff16600160a81b67ffffffffffffffff9283160217909255925116600090815260086020908152604080832094835293905291909120429055506001016108af565b507f3a3950e13dd607cc37980db0ef14266c40d2bba9c01b2e44bfe549808883095d81604051610ad591906153b3565b60405180910390a1610b5160008a8a8a8a8a8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808e0282810182019093528d82529093508d92508c9182918501908490808284376000920191909152508b9250611a8a915050565b505050505050505050565b610b9c610b6b82840184615450565b6040805160008082526020820190925290610b96565b6060815260200190600190039081610b815790505b50611871565b604080516000808252602082019092529050610bbf600185858585866000611a8a565b50505050565b6000610bd360016004615485565b6002610be06080856154ae565b67ffffffffffffffff16610bf491906154d5565b610bfe8585611e01565b901c166003811115610c1257610c12614a5e565b90505b92915050565b6001546001600160a01b03163314610c755760405162461bcd60e51b815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610754565b600080543373ffffffffffffffffffffffffffffffffffffffff19808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610ce1611496565b6105dd81611e48565b333014610d23576040517f371a732800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160008082526020820190925281610d60565b6040805180820190915260008082526020820152815260200190600190039081610d395790505b5060a08501515190915015610d9457610d918460a00151856020015186606001518760000151602001518787611fae565b90505b6040805160a0810182528551518152855160209081015167ffffffffffffffff1681830152808701518351600094840192610dd0929101614879565b60408051601f19818403018152918152908252878101516020830152018390526005549091506001600160a01b03168015610edd576040517f08d450a10000000000000000000000000000000000000000000000000000000081526001600160a01b038216906308d450a190610e4a90859060040161558e565b600060405180830381600087803b158015610e6457600080fd5b505af1925050508015610e75575060015b610edd573d808015610ea3576040519150601f19603f3d011682016040523d82523d6000602084013e610ea8565b606091505b50806040517f09c253250000000000000000000000000000000000000000000000000000000081526004016107549190614879565b604086015151158015610ef257506080860151155b80610f09575060608601516001600160a01b03163b155b80610f4957506060860151610f47906001600160a01b03167f85572ffb000000000000000000000000000000000000000000000000000000006120cd565b155b15610f5657505050505050565b855160209081015167ffffffffffffffff1660009081526006909152604080822054608089015160608a015192517f3cf9798300000000000000000000000000000000000000000000000000000000815284936001600160a01b0390931692633cf9798392610fce92899261138892916004016155a1565b6000604051808303816000875af1158015610fed573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261101591908101906155dd565b50915091508161105357806040517f0a8d6e8c0000000000000000000000000000000000000000000000000000000081526004016107549190614879565b5050505050505050565b6110a06040805160e081019091526000606082018181526080830182905260a0830182905260c08301919091528190815260200160608152602001606081525090565b60ff808316600090815260026020818152604092839020835160e081018552815460608201908152600183015480881660808401526101008104881660a0840152620100009004909616151560c08201529485529182018054845181840281018401909552808552929385830193909283018282801561114957602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161112b575b50505050508152602001600382018054806020026020016040519081016040528092919081815260200182805480156111ab57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161118d575b5050505050815250509050919050565b6111c3611496565b60005b818110156107805760008383838181106111e2576111e2614f7f565b9050604002018036038101906111f89190615673565b905061120781602001516113d5565b61126c57805167ffffffffffffffff1660009081526008602090815260408083208285018051855290835281842093909355915191519182527f202f1139a3e334b6056064c0e9b19fd07e44a88d8f6e5ded571b24cf8c371f12910160405180910390a15b506001016111c6565b604080516080808201835260008083526020808401829052838501829052606080850181905267ffffffffffffffff878116845260068352928690208651948501875280546001600160a01b0381168652600160a01b810460ff16151593860193909352600160a81b909204909216948301949094526001840180549394929391840191611302906156ac565b80601f016020809104026020016040519081016040528092919081815260200182805461132e906156ac565b80156111ab5780601f10611350576101008083540402835291602001916111ab565b820191906000526020600020905b81548152906001019060200180831161135e57505050919092525091949350505050565b61138a611496565b6105dd816120e9565b61139b611496565b60005b81518110156113d1576113c98282815181106113bc576113bc614f7f565b602002602001015161219f565b60010161139e565b5050565b6040805180820182523081526020810183815291517f4d61677100000000000000000000000000000000000000000000000000000000815290516001600160a01b039081166004830152915160248201526000917f00000000000000000000000000000000000000000000000000000000000000001690634d61677190604401602060405180830381865afa158015611472573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c1591906156e6565b6000546001600160a01b031633146114f05760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610754565b565b60005b81518110156113d157600082828151811061151257611512614f7f565b602002602001015190506000816020015190508067ffffffffffffffff16600003611569576040517fc656089500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81516001600160a01b0316611591576040516342bcdf7f60e11b815260040160405180910390fd5b67ffffffffffffffff811660009081526006602052604081206001810180549192916115bc906156ac565b80601f01602080910402602001604051908101604052809291908181526020018280546115e8906156ac565b80156116355780601f1061160a57610100808354040283529160200191611635565b820191906000526020600020905b81548152906001019060200180831161161857829003601f168201915b5050505050905060008460600151905081516000036116ed578051600003611670576040516342bcdf7f60e11b815260040160405180910390fd5b6001830161167e8282615753565b5082547fffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffff16600160a81b17835560405167ffffffffffffffff851681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1611740565b8080519060200120828051906020012014611740576040517fc39a620500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff85166004820152602401610754565b604080860151845487516001600160a01b031673ffffffffffffffffffffffffffffffffffffffff19921515600160a01b02929092167fffffffffffffffffffffff000000000000000000000000000000000000000000909116171784555167ffffffffffffffff8516907f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b906117d8908690615813565b60405180910390a250505050508060010190506114f5565b467f0000000000000000000000000000000000000000000000000000000000000000146114f0576040517f0f01ce850000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000006004820152466024820152604401610754565b81516000036118ab576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160408051600080825260208201909252911591905b845181101561191a576119128582815181106118e0576118e0614f7f565b60200260200101518461190c578583815181106118ff576118ff614f7f565b60200260200101516124d0565b836124d0565b6001016118c2565b5050505050565b6040517f2cbc26bb000000000000000000000000000000000000000000000000000000008152608082901b77ffffffffffffffff000000000000000000000000000000001660048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632cbc26bb90602401602060405180830381865afa1580156119bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119e091906156e6565b156105dd576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610754565b67ffffffffffffffff811660009081526006602052604081208054600160a01b900460ff16610c15576040517fed053c5900000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610754565b60ff87811660009081526002602090815260408083208151608081018352815481526001909101548086169382019390935261010083048516918101919091526201000090910490921615156060830152873590611ae98760a46158e1565b9050826060015115611b31578451611b029060206154d5565b8651611b0f9060206154d5565b611b1a9060a06158e1565b611b2491906158e1565b611b2e90826158e1565b90505b368114611b73576040517f8e1192e100000000000000000000000000000000000000000000000000000000815260048101829052366024820152604401610754565b5081518114611bbb5781516040517f93df584c000000000000000000000000000000000000000000000000000000008152600481019190915260248101829052604401610754565b611bc36117f0565b60ff808a1660009081526003602090815260408083203384528252808320815180830190925280548086168352939491939092840191610100909104166002811115611c1157611c11614a5e565b6002811115611c2257611c22614a5e565b9052509050600281602001516002811115611c3f57611c3f614a5e565b148015611c935750600260008b60ff1660ff168152602001908152602001600020600301816000015160ff1681548110611c7b57611c7b614f7f565b6000918252602090912001546001600160a01b031633145b611cc9576040517fda0f08e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50816060015115611dab576020820151611ce49060016158f4565b60ff16855114611d20576040517f71253a2500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8351855114611d5b576040517fa75d88af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008787604051611d6d92919061590d565b604051908190038120611d84918b9060200161591d565b604051602081830303815290604052805190602001209050611da98a82888888612c9c565b505b6040805182815260208a81013567ffffffffffffffff169082015260ff8b16917f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef0910160405180910390a2505050505050505050565b67ffffffffffffffff8216600090815260076020526040812081611e26608085615931565b67ffffffffffffffff1681526020810191909152604001600020549392505050565b80516001600160a01b0316611e70576040516342bcdf7f60e11b815260040160405180910390fd5b80516004805460208085018051604080880180516060808b0180516001600160a01b039b8c167fffffffffffffffff000000000000000000000000000000000000000000000000909a168a17600160a01b63ffffffff988916021777ffffffffffffffffffffffffffffffffffffffffffffffff167801000000000000000000000000000000000000000000000000948816949094026001600160e01b031693909317600160e01b93871693909302929092179098556080808b0180516005805473ffffffffffffffffffffffffffffffffffffffff1916918d169190911790558451988952955185169688019690965290518316918601919091525116938301939093529151909216908201527fa55bd56595c45f517e5967a3067f3dca684445a3080e7c04a4e0d5a40cda627d9060a00160405180910390a150565b6060865167ffffffffffffffff811115611fca57611fca613e89565b60405190808252806020026020018201604052801561200f57816020015b6040805180820190915260008082526020820152815260200190600190039081611fe85790505b50905060005b87518110156120c15761209c88828151811061203357612033614f7f565b602002602001015188888888888781811061205057612050614f7f565b90506020028101906120629190615958565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612e8192505050565b8282815181106120ae576120ae614f7f565b6020908102919091010152600101612015565b505b9695505050505050565b60006120d883613226565b8015610c125750610c12838361328a565b336001600160a01b038216036121415760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610754565b6001805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b806040015160ff166000036121ca576000604051631b3fab5160e11b815260040161075491906159bd565b60208082015160ff8082166000908152600290935260408320600181015492939092839216900361223757606084015160018201805491151562010000027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff90921691909117905561228c565b6060840151600182015460ff620100009091041615159015151461228c576040517f87f6037c00000000000000000000000000000000000000000000000000000000815260ff84166004820152602401610754565b60a0840151805161010010156122b8576001604051631b3fab5160e11b815260040161075491906159bd565b61231e848460030180548060200260200160405190810160405280929190818152602001828054801561231457602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116122f6575b5050505050613345565b8460600151156124455761238c8484600201805480602002602001604051908101604052809291908181526020018280548015612314576020028201919060005260206000209081546001600160a01b031681526001909101906020018083116122f6575050505050613345565b6080850151805161010010156123b8576002604051631b3fab5160e11b815260040161075491906159bd565b60408601516123c89060036159d7565b60ff168151116123ee576003604051631b3fab5160e11b815260040161075491906159bd565b80516001840180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1661010060ff8416021790556124369060028601906020840190613e02565b50612443858260016133ae565b505b612451848260026133ae565b80516124669060038501906020840190613e02565b5060408581015160018401805460ff191660ff8316179055865180855560a088015192517fab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f547936124bf9389939260028a019291906159f3565b60405180910390a161191a84613522565b81516124db81611921565b60006124e682611a23565b60010180546124f4906156ac565b80601f0160208091040260200160405190810160405280929190818152602001828054612520906156ac565b801561256d5780601f106125425761010080835404028352916020019161256d565b820191906000526020600020905b81548152906001019060200180831161255057829003601f168201915b505050602087015151929350505060008190036125b5576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84604001515181146125f3576040517f57e0e08300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008167ffffffffffffffff81111561260e5761260e613e89565b604051908082528060200260200182016040528015612637578160200160208202803683370190505b50905060005b828110156127205760008760200151828151811061265d5761265d614f7f565b602002602001015190507f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681600001516040015167ffffffffffffffff16146126f057805160409081015190517f38432a2200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610754565b6126fa818661353e565b83838151811061270c5761270c614f7f565b60209081029190910101525060010161263d565b506000612737858389606001518a60800151613660565b90508060000361277f576040517f7dd17a7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff86166004820152602401610754565b8551151560005b84811015610b515760005a905060008a6020015183815181106127ab576127ab614f7f565b6020026020010151905060006127c98a836000015160600151610bc5565b905060008160038111156127df576127df614a5e565b14806127fc575060038160038111156127fa576127fa614a5e565b145b612854578151606001516040805167ffffffffffffffff808e16825290921660208301527f3b575419319662b2a6f5e2467d84521517a3382b908eb3d557bb3fdb0c50e23c91015b60405180910390a1505050612c94565b841561292457600454600090600160a01b900463ffffffff166128778842615485565b11905080806128975750600382600381111561289557612895614a5e565b145b6128d9576040517fa9cfc86200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8c166004820152602401610754565b8b85815181106128eb576128eb614f7f565b602002602001015160001461291e578b858151811061290c5761290c614f7f565b60200260200101518360800181815250505b50612985565b600081600381111561293857612938614a5e565b14612985578151606001516040805167ffffffffffffffff808e16825290921660208301527f3ef2a99c550a751d4b0b261268f05a803dfb049ab43616a1ffb388f61fe651209101612844565b81516080015167ffffffffffffffff1615612a745760008160038111156129ae576129ae614a5e565b03612a745781516080015160208301516040517fe0e03cae0000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169263e0e03cae92612a25928f929190600401615a9f565b6020604051808303816000875af1158015612a44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a6891906156e6565b612a7457505050612c94565b60008c604001518581518110612a8c57612a8c614f7f565b6020026020010151905080518360a001515114612af0578251606001516040517f1cfe6d8b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808e1660048301529091166024820152604401610754565b612b048b84600001516060015160016136b6565b600080612b11858461375e565b91509150612b288d866000015160600151846136b6565b8715612b98576003826003811115612b4257612b42614a5e565b03612b98576000846003811115612b5b57612b5b614a5e565b14612b98578451516040517f2b11b8d900000000000000000000000000000000000000000000000000000000815261075491908390600401615acc565b6002826003811115612bac57612bac614a5e565b14612c06576003826003811115612bc557612bc5614a5e565b14612c06578451606001516040517f926c5a3e000000000000000000000000000000000000000000000000000000008152610754918f918590600401615ae5565b84600001516000015185600001516060015167ffffffffffffffff168e67ffffffffffffffff167f05665fe9ad095383d018353f4cbcba77e84db27dd215081bbf7cdf9ae6fbe48b8d8b81518110612c6057612c60614f7f565b602002602001015186865a612c75908e615485565b604051612c859493929190615b0b565b60405180910390a45050505050505b600101612786565b8251600090815b81811015611053576000600188868460208110612cc257612cc2614f7f565b612ccf91901a601b6158f4565b898581518110612ce157612ce1614f7f565b6020026020010151898681518110612cfb57612cfb614f7f565b602002602001015160405160008152602001604052604051612d39949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015612d5b573d6000803e3d6000fd5b505060408051601f1981015160ff808e166000908152600360209081528582206001600160a01b03851683528152858220858701909652855480841686529397509095509293928401916101009004166002811115612dbc57612dbc614a5e565b6002811115612dcd57612dcd614a5e565b9052509050600181602001516002811115612dea57612dea614a5e565b14612e21576040517fca31867a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051600160ff9091161b851615612e64576040517ff67bc7c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806000015160ff166001901b851794505050806001019050612ca3565b60408051808201909152600080825260208201526000612ea48760200151613828565b6040517fbbe4f6db0000000000000000000000000000000000000000000000000000000081526001600160a01b0380831660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063bbe4f6db90602401602060405180830381865afa158015612f29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f4d9190615b42565b90506001600160a01b0381161580612f955750612f936001600160a01b0382167faff2afbf000000000000000000000000000000000000000000000000000000006120cd565b155b15612fd7576040517fae9b4ce90000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152602401610754565b6004546000908190612ff99089908690600160e01b900463ffffffff166138ce565b9150915060008060006130c66040518061010001604052808e81526020018c67ffffffffffffffff1681526020018d6001600160a01b031681526020018f606001518152602001896001600160a01b031681526020018f6000015181526020018f6040015181526020018b8152506040516024016130779190615b5f565b60408051601f198184030181529190526020810180516001600160e01b03167f3907753700000000000000000000000000000000000000000000000000000000179052878661138860846139fc565b9250925092508261310557816040517fe1cd55090000000000000000000000000000000000000000000000000000000081526004016107549190614879565b815160201461314d5781516040517f78ef8024000000000000000000000000000000000000000000000000000000008152602060048201526024810191909152604401610754565b6000828060200190518101906131639190615c2c565b9050866001600160a01b03168c6001600160a01b0316146131f85760006131948d8a61318f868a615485565b6138ce565b509050868110806131ae5750816131ab8883615485565b14155b156131f6576040517fa966e21f000000000000000000000000000000000000000000000000000000008152600481018390526024810188905260448101829052606401610754565b505b604080518082019091526001600160a01b039098168852602088015250949550505050505095945050505050565b6000613252827f01ffc9a70000000000000000000000000000000000000000000000000000000061328a565b8015610c155750613283827fffffffff0000000000000000000000000000000000000000000000000000000061328a565b1592915050565b6040517fffffffff0000000000000000000000000000000000000000000000000000000082166024820152600090819060440160408051601f19818403018152919052602080820180516001600160e01b03167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825192935060009283928392909183918a617530fa92503d9150600051905082801561332e575060208210155b801561333a5750600081115b979650505050505050565b60005b81518110156107805760ff83166000908152600360205260408120835190919084908490811061337a5761337a614f7f565b6020908102919091018101516001600160a01b03168252810191909152604001600020805461ffff19169055600101613348565b60005b8251811015610bbf5760008382815181106133ce576133ce614f7f565b60200260200101519050600060028111156133eb576133eb614a5e565b60ff80871660009081526003602090815260408083206001600160a01b0387168452909152902054610100900416600281111561342a5761342a614a5e565b1461344b576004604051631b3fab5160e11b815260040161075491906159bd565b6001600160a01b03811661348b576040517fd6c62c9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052808360ff1681526020018460028111156134b1576134b1614a5e565b905260ff80871660009081526003602090815260408083206001600160a01b0387168452825290912083518154931660ff198416811782559184015190929091839161ffff19161761010083600281111561350e5761350e614a5e565b0217905550905050508060010190506133b1565b60ff81166105dd576009805467ffffffffffffffff1916905550565b815160208082015160409283015192516000938493613584937f2425b0b9f9054c76ff151b0a175b18f37a4a4e82013a72e9f15c9caa095ed21f93909291889101615c45565b60408051601f1981840301815290829052805160209182012086518051888401516060808b0151908401516080808d015195015195976135cd9794969395929491939101615c78565b604051602081830303815290604052805190602001208560400151805190602001208660a001516040516020016136049190615d8a565b60408051601f198184030181528282528051602091820120908301969096528101939093526060830191909152608082015260a081019190915260c0015b60405160208183030381529060405280519060200120905092915050565b60008061366e858585613b22565b9050613679816113d5565b6136875760009150506136ae565b67ffffffffffffffff86166000908152600860209081526040808320938352929052205490505b949350505050565b600060026136c56080856154ae565b67ffffffffffffffff166136d991906154d5565b905060006136e78585611e01565b9050816136f660016004615485565b901b19168183600381111561370d5761370d614a5e565b67ffffffffffffffff871660009081526007602052604081209190921b9290921791829161373c608088615931565b67ffffffffffffffff1681526020810191909152604001600020555050505050565b6040517fa80036b4000000000000000000000000000000000000000000000000000000008152600090606090309063a80036b4906137a29087908790600401615dea565b600060405180830381600087803b1580156137bc57600080fd5b505af19250505080156137cd575060015b61380c573d8080156137fb576040519150601f19603f3d011682016040523d82523d6000602084013e613800565b606091505b50600392509050613821565b50506040805160208101909152600081526002905b9250929050565b6000815160201461386757816040517f8d666f600000000000000000000000000000000000000000000000000000000081526004016107549190614879565b60008280602001905181019061387d9190615c2c565b90506001600160a01b03811180613895575061040081105b15610c1557826040517f8d666f600000000000000000000000000000000000000000000000000000000081526004016107549190614879565b6000806000806000613948886040516024016138f991906001600160a01b0391909116815260200190565b60408051601f198184030181529190526020810180516001600160e01b03167f70a0823100000000000000000000000000000000000000000000000000000000179052888861138860846139fc565b9250925092508261398757816040517fe1cd55090000000000000000000000000000000000000000000000000000000081526004016107549190614879565b60208251146139cf5781516040517f78ef8024000000000000000000000000000000000000000000000000000000008152602060048201526024810191909152604401610754565b818060200190518101906139e39190615c2c565b6139ed8288615485565b94509450505050935093915050565b6000606060008361ffff1667ffffffffffffffff811115613a1f57613a1f613e89565b6040519080825280601f01601f191660200182016040528015613a49576020820181803683370190505b509150863b613a7c577f0c3b563c0000000000000000000000000000000000000000000000000000000060005260046000fd5b5a85811015613aaf577fafa32a2c0000000000000000000000000000000000000000000000000000000060005260046000fd5b8590036040810481038710613ae8577f37c3be290000000000000000000000000000000000000000000000000000000060005260046000fd5b505a6000808a5160208c0160008c8cf193505a900390503d84811115613b0b5750835b808352806000602085013e50955095509592505050565b8251825160009190818303613b63576040517f11a6b26400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6101018211801590613b7757506101018111155b613b94576040516309bde33960e01b815260040160405180910390fd5b60001982820101610100811115613bbe576040516309bde33960e01b815260040160405180910390fd5b80600003613beb5786600081518110613bd957613bd9614f7f565b60200260200101519350505050613dba565b60008167ffffffffffffffff811115613c0657613c06613e89565b604051908082528060200260200182016040528015613c2f578160200160208202803683370190505b50905060008080805b85811015613d595760006001821b8b811603613c935788851015613c7c578c5160018601958e918110613c6d57613c6d614f7f565b60200260200101519050613cb5565b8551600185019487918110613c6d57613c6d614f7f565b8b5160018401938d918110613caa57613caa614f7f565b602002602001015190505b600089861015613ce5578d5160018701968f918110613cd657613cd6614f7f565b60200260200101519050613d07565b8651600186019588918110613cfc57613cfc614f7f565b602002602001015190505b82851115613d28576040516309bde33960e01b815260040160405180910390fd5b613d328282613dc1565b878481518110613d4457613d44614f7f565b60209081029190910101525050600101613c38565b506001850382148015613d6b57508683145b8015613d7657508581145b613d93576040516309bde33960e01b815260040160405180910390fd5b836001860381518110613da857613da8614f7f565b60200260200101519750505050505050505b9392505050565b6000818310613dd957613dd48284613ddf565b610c12565b610c1283835b604080516001602082015290810183905260608101829052600090608001613642565b828054828255906000526020600020908101928215613e64579160200282015b82811115613e64578251825473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03909116178255602090920191600190910190613e22565b50613e70929150613e74565b5090565b5b80821115613e705760008155600101613e75565b634e487b7160e01b600052604160045260246000fd5b6040516080810167ffffffffffffffff81118282101715613ec257613ec2613e89565b60405290565b60405160a0810167ffffffffffffffff81118282101715613ec257613ec2613e89565b60405160c0810167ffffffffffffffff81118282101715613ec257613ec2613e89565b6040805190810167ffffffffffffffff81118282101715613ec257613ec2613e89565b6040516060810167ffffffffffffffff81118282101715613ec257613ec2613e89565b604051601f8201601f1916810167ffffffffffffffff81118282101715613f7d57613f7d613e89565b604052919050565b600067ffffffffffffffff821115613f9f57613f9f613e89565b5060051b60200190565b6001600160a01b03811681146105dd57600080fd5b803567ffffffffffffffff81168114613fd657600080fd5b919050565b80151581146105dd57600080fd5b8035613fd681613fdb565b600067ffffffffffffffff82111561400e5761400e613e89565b50601f01601f191660200190565b600082601f83011261402d57600080fd5b813561404061403b82613ff4565b613f54565b81815284602083860101111561405557600080fd5b816020850160208301376000918101602001919091529392505050565b6000602080838503121561408557600080fd5b823567ffffffffffffffff8082111561409d57600080fd5b818501915085601f8301126140b157600080fd5b81356140bf61403b82613f85565b81815260059190911b830184019084810190888311156140de57600080fd5b8585015b83811015614184578035858111156140fa5760008081fd5b86016080818c03601f19018113156141125760008081fd5b61411a613e9f565b8983013561412781613fa9565b81526040614136848201613fbe565b8b83015260608085013561414981613fdb565b8383015292840135928984111561416257600091508182fd5b6141708f8d8688010161401c565b9083015250855250509186019186016140e2565b5098975050505050505050565b600060a082840312156141a357600080fd5b6141ab613ec8565b9050813581526141bd60208301613fbe565b60208201526141ce60408301613fbe565b60408201526141df60608301613fbe565b60608201526141f060808301613fbe565b608082015292915050565b8035613fd681613fa9565b600082601f83011261421757600080fd5b8135602061422761403b83613f85565b82815260059290921b8401810191818101908684111561424657600080fd5b8286015b848110156120c157803567ffffffffffffffff8082111561426b5760008081fd5b818901915060a080601f19848d030112156142865760008081fd5b61428e613ec8565b87840135838111156142a05760008081fd5b6142ae8d8a8388010161401c565b825250604080850135848111156142c55760008081fd5b6142d38e8b8389010161401c565b8a84015250606080860135858111156142ec5760008081fd5b6142fa8f8c838a010161401c565b838501525060809150818601358184015250828501359250838311156143205760008081fd5b61432e8d8a8588010161401c565b90820152865250505091830191830161424a565b6000610140828403121561435557600080fd5b61435d613eeb565b90506143698383614191565b815260a082013567ffffffffffffffff8082111561438657600080fd5b6143928583860161401c565b602084015260c08401359150808211156143ab57600080fd5b6143b78583860161401c565b60408401526143c860e085016141fb565b606084015261010084013560808401526101208401359150808211156143ed57600080fd5b506143fa84828501614206565b60a08301525092915050565b600082601f83011261441757600080fd5b8135602061442761403b83613f85565b82815260059290921b8401810191818101908684111561444657600080fd5b8286015b848110156120c157803567ffffffffffffffff81111561446a5760008081fd5b6144788986838b0101614342565b84525091830191830161444a565b600082601f83011261449757600080fd5b813560206144a761403b83613f85565b82815260059290921b840181019181810190868411156144c657600080fd5b8286015b848110156120c157803567ffffffffffffffff808211156144ea57600080fd5b818901915089603f8301126144fe57600080fd5b8582013561450e61403b82613f85565b81815260059190911b830160400190878101908c83111561452e57600080fd5b604085015b838110156145675780358581111561454a57600080fd5b6145598f6040838a010161401c565b845250918901918901614533565b508752505050928401925083016144ca565b600082601f83011261458a57600080fd5b8135602061459a61403b83613f85565b8083825260208201915060208460051b8701019350868411156145bc57600080fd5b602086015b848110156120c157803583529183019183016145c1565b600082601f8301126145e957600080fd5b813560206145f961403b83613f85565b82815260059290921b8401810191818101908684111561461857600080fd5b8286015b848110156120c157803567ffffffffffffffff8082111561463d5760008081fd5b818901915060a080601f19848d030112156146585760008081fd5b614660613ec8565b61466b888501613fbe565b8152604080850135848111156146815760008081fd5b61468f8e8b83890101614406565b8a84015250606080860135858111156146a85760008081fd5b6146b68f8c838a0101614486565b83850152506080915081860135858111156146d15760008081fd5b6146df8f8c838a0101614579565b918401919091525091909301359083015250835291830191830161461c565b600080604080848603121561471257600080fd5b833567ffffffffffffffff8082111561472a57600080fd5b614736878388016145d8565b945060209150818601358181111561474d57600080fd5b8601601f8101881361475e57600080fd5b803561476c61403b82613f85565b81815260059190911b8201840190848101908a83111561478b57600080fd5b8584015b83811015614817578035868111156147a75760008081fd5b8501603f81018d136147b95760008081fd5b878101356147c961403b82613f85565b81815260059190911b82018a0190898101908f8311156147e95760008081fd5b928b01925b828410156148075783358252928a0192908a01906147ee565b865250505091860191860161478f565b50809750505050505050509250929050565b60005b8381101561484457818101518382015260200161482c565b50506000910152565b60008151808452614865816020860160208601614829565b601f01601f19169290920160200192915050565b602081526000610c12602083018461484d565b8060608101831015610c1557600080fd5b60008083601f8401126148af57600080fd5b50813567ffffffffffffffff8111156148c757600080fd5b60208301915083602082850101111561382157600080fd5b60008083601f8401126148f157600080fd5b50813567ffffffffffffffff81111561490957600080fd5b6020830191508360208260051b850101111561382157600080fd5b60008060008060008060008060e0898b03121561494057600080fd5b61494a8a8a61488c565b9750606089013567ffffffffffffffff8082111561496757600080fd5b6149738c838d0161489d565b909950975060808b013591508082111561498c57600080fd5b6149988c838d016148df565b909750955060a08b01359150808211156149b157600080fd5b506149be8b828c016148df565b999c989b50969995989497949560c00135949350505050565b6000806000608084860312156149ec57600080fd5b6149f6858561488c565b9250606084013567ffffffffffffffff811115614a1257600080fd5b614a1e8682870161489d565b9497909650939450505050565b60008060408385031215614a3e57600080fd5b614a4783613fbe565b9150614a5560208401613fbe565b90509250929050565b634e487b7160e01b600052602160045260246000fd5b60048110614a8457614a84614a5e565b9052565b60208101610c158284614a74565b600060208284031215614aa857600080fd5b813567ffffffffffffffff811115614abf57600080fd5b820160a08185031215613dba57600080fd5b803563ffffffff81168114613fd657600080fd5b600060a08284031215614af757600080fd5b614aff613ec8565b8235614b0a81613fa9565b8152614b1860208401614ad1565b6020820152614b2960408401614ad1565b6040820152614b3a60608401614ad1565b60608201526080830135614b4d81613fa9565b60808201529392505050565b600080600060408486031215614b6e57600080fd5b833567ffffffffffffffff80821115614b8657600080fd5b614b9287838801614342565b94506020860135915080821115614ba857600080fd5b50614a1e868287016148df565b803560ff81168114613fd657600080fd5b600060208284031215614bd857600080fd5b610c1282614bb5565b60008151808452602080850194506020840160005b83811015614c1b5781516001600160a01b031687529582019590820190600101614bf6565b509495945050505050565b60208152600082518051602084015260ff602082015116604084015260ff604082015116606084015260608101511515608084015250602083015160c060a0840152614c7560e0840182614be1565b90506040840151601f198483030160c0850152614c928282614be1565b95945050505050565b60008060408385031215614cae57600080fd5b614cb783613fbe565b946020939093013593505050565b60008060208385031215614cd857600080fd5b823567ffffffffffffffff80821115614cf057600080fd5b818501915085601f830112614d0457600080fd5b813581811115614d1357600080fd5b8660208260061b8501011115614d2857600080fd5b60209290920196919550909350505050565b600060208284031215614d4c57600080fd5b610c1282613fbe565b602081526001600160a01b03825116602082015260208201511515604082015267ffffffffffffffff6040830151166060820152600060608301516080808401526136ae60a084018261484d565b600060208284031215614db557600080fd5b8135613dba81613fa9565b600082601f830112614dd157600080fd5b81356020614de161403b83613f85565b8083825260208201915060208460051b870101935086841115614e0357600080fd5b602086015b848110156120c1578035614e1b81613fa9565b8352918301918301614e08565b60006020808385031215614e3b57600080fd5b823567ffffffffffffffff80821115614e5357600080fd5b818501915085601f830112614e6757600080fd5b8135614e7561403b82613f85565b81815260059190911b83018401908481019088831115614e9457600080fd5b8585015b8381101561418457803585811115614eaf57600080fd5b860160c0818c03601f19011215614ec65760008081fd5b614ece613eeb565b8882013581526040614ee1818401614bb5565b8a8301526060614ef2818501614bb5565b8284015260809150614f05828501613fe9565b9083015260a08381013589811115614f1d5760008081fd5b614f2b8f8d83880101614dc0565b838501525060c0840135915088821115614f455760008081fd5b614f538e8c84870101614dc0565b9083015250845250918601918601614e98565b600060208284031215614f7857600080fd5b5035919050565b634e487b7160e01b600052603260045260246000fd5b80356001600160e01b0381168114613fd657600080fd5b600082601f830112614fbd57600080fd5b81356020614fcd61403b83613f85565b82815260069290921b84018101918181019086841115614fec57600080fd5b8286015b848110156120c157604081890312156150095760008081fd5b615011613f0e565b61501a82613fbe565b8152615027858301614f95565b81860152835291830191604001614ff0565b600082601f83011261504a57600080fd5b8135602061505a61403b83613f85565b82815260079290921b8401810191818101908684111561507957600080fd5b8286015b848110156120c15780880360808112156150975760008081fd5b61509f613f31565b6150a883613fbe565b8152604080601f19840112156150be5760008081fd5b6150c6613f0e565b92506150d3878501613fbe565b83526150e0818501613fbe565b838801528187019290925260608301359181019190915283529183019160800161507d565b6000602080838503121561511857600080fd5b823567ffffffffffffffff8082111561513057600080fd5b8185019150604080838803121561514657600080fd5b61514e613f0e565b83358381111561515d57600080fd5b84016040818a03121561516f57600080fd5b615177613f0e565b81358581111561518657600080fd5b8201601f81018b1361519757600080fd5b80356151a561403b82613f85565b81815260069190911b8201890190898101908d8311156151c457600080fd5b928a01925b828410156152145787848f0312156151e15760008081fd5b6151e9613f0e565b84356151f481613fa9565b8152615201858d01614f95565b818d0152825292870192908a01906151c9565b84525050508187013593508484111561522c57600080fd5b6152388a858401614fac565b818801528252508385013591508282111561525257600080fd5b61525e88838601615039565b85820152809550505050505092915050565b805160408084528151848201819052600092602091908201906060870190855b818110156152c757835180516001600160a01b031684528501516001600160e01b0316858401529284019291850191600101615290565b50508583015187820388850152805180835290840192506000918401905b80831015615321578351805167ffffffffffffffff1683528501516001600160e01b0316858301529284019260019290920191908501906152e5565b50979650505050505050565b602081526000610c126020830184615270565b67ffffffffffffffff8316815260608101613dba6020830184805167ffffffffffffffff908116835260209182015116910152565b634e487b7160e01b600052601160045260246000fd5b67ffffffffffffffff8181168382160190808211156153ac576153ac615375565b5092915050565b6000602080835260608451604080848701526153d26060870183615270565b87850151878203601f19016040890152805180835290860193506000918601905b8083101561418457845167ffffffffffffffff81511683528781015161543289850182805167ffffffffffffffff908116835260209182015116910152565b508401518287015293860193600192909201916080909101906153f3565b60006020828403121561546257600080fd5b813567ffffffffffffffff81111561547957600080fd5b6136ae848285016145d8565b81810381811115610c1557610c15615375565b634e487b7160e01b600052601260045260246000fd5b600067ffffffffffffffff808416806154c9576154c9615498565b92169190910692915050565b8082028115828204841417610c1557610c15615375565b805182526000602067ffffffffffffffff81840151168185015260408084015160a0604087015261552060a087018261484d565b905060608501518682036060880152615539828261484d565b608087810151898303918a01919091528051808352908601935060009250908501905b8083101561532157835180516001600160a01b031683528601518683015292850192600192909201919084019061555c565b602081526000610c1260208301846154ec565b6080815260006155b460808301876154ec565b61ffff9590951660208301525060408101929092526001600160a01b0316606090910152919050565b6000806000606084860312156155f257600080fd5b83516155fd81613fdb565b602085015190935067ffffffffffffffff81111561561a57600080fd5b8401601f8101861361562b57600080fd5b805161563961403b82613ff4565b81815287602083850101111561564e57600080fd5b61565f826020830160208601614829565b809450505050604084015190509250925092565b60006040828403121561568557600080fd5b61568d613f0e565b61569683613fbe565b8152602083013560208201528091505092915050565b600181811c908216806156c057607f821691505b6020821081036156e057634e487b7160e01b600052602260045260246000fd5b50919050565b6000602082840312156156f857600080fd5b8151613dba81613fdb565b601f821115610780576000816000526020600020601f850160051c8101602086101561572c5750805b601f850160051c820191505b8181101561574b57828155600101615738565b505050505050565b815167ffffffffffffffff81111561576d5761576d613e89565b6157818161577b84546156ac565b84615703565b602080601f8311600181146157b6576000841561579e5750858301515b600019600386901b1c1916600185901b17855561574b565b600085815260208120601f198616915b828110156157e5578886015182559484019460019091019084016157c6565b50858210156158035787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6000602080835283546001600160a01b038116602085015260ff8160a01c161515604085015267ffffffffffffffff8160a81c16606085015250600180850160808086015260008154615865816156ac565b8060a089015260c0600183166000811461588657600181146158a2576158d2565b60ff19841660c08b015260c083151560051b8b010194506158d2565b85600052602060002060005b848110156158c95781548c82018501529088019089016158ae565b8b0160c0019550505b50929998505050505050505050565b80820180821115610c1557610c15615375565b60ff8181168382160190811115610c1557610c15615375565b8183823760009101908152919050565b828152606082602083013760800192915050565b600067ffffffffffffffff8084168061594c5761594c615498565b92169190910492915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261598d57600080fd5b83018035915067ffffffffffffffff8211156159a857600080fd5b60200191503681900382131561382157600080fd5b60208101600583106159d1576159d1614a5e565b91905290565b60ff81811683821602908116908181146153ac576153ac615375565b600060a0820160ff881683526020878185015260a0604085015281875480845260c0860191508860005282600020935060005b81811015615a4b5784546001600160a01b031683526001948501949284019201615a26565b50508481036060860152865180825290820192508187019060005b81811015615a8b5782516001600160a01b031685529383019391830191600101615a66565b50505060ff851660808501525090506120c3565b600067ffffffffffffffff808616835280851660208401525060606040830152614c92606083018461484d565b8281526040602082015260006136ae604083018461484d565b67ffffffffffffffff848116825283166020820152606081016136ae6040830184614a74565b848152615b1b6020820185614a74565b608060408201526000615b31608083018561484d565b905082606083015295945050505050565b600060208284031215615b5457600080fd5b8151613dba81613fa9565b6020815260008251610100806020850152615b7e61012085018361484d565b91506020850151615b9b604086018267ffffffffffffffff169052565b5060408501516001600160a01b038116606086015250606085015160808501526080850151615bd560a08601826001600160a01b03169052565b5060a0850151601f19808685030160c0870152615bf2848361484d565b935060c08701519150808685030160e0870152615c0f848361484d565b935060e08701519150808685030183870152506120c3838261484d565b600060208284031215615c3e57600080fd5b5051919050565b848152600067ffffffffffffffff8086166020840152808516604084015250608060608301526120c3608083018461484d565b86815260c060208201526000615c9160c083018861484d565b6001600160a01b039690961660408301525067ffffffffffffffff9384166060820152608081019290925290911660a09091015292915050565b600082825180855260208086019550808260051b84010181860160005b84811015615d7d57601f19868403018952815160a08151818652615d0e8287018261484d565b9150508582015185820387870152615d26828261484d565b91505060408083015186830382880152615d40838261484d565b92505050606080830151818701525060808083015192508582038187015250615d69818361484d565b9a86019a9450505090830190600101615ce8565b5090979650505050505050565b602081526000610c126020830184615ccb565b60008282518085526020808601955060208260051b8401016020860160005b84811015615d7d57601f19868403018952615dd883835161484d565b98840198925090830190600101615dbc565b604081526000835180516040840152602081015167ffffffffffffffff80821660608601528060408401511660808601528060608401511660a08601528060808401511660c086015250505060208401516101408060e0850152615e5261018085018361484d565b915060408601517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08086850301610100870152615e8f848361484d565b935060608801519150615eae6101208701836001600160a01b03169052565b60808801518387015260a0880151925080868503016101608701525050615ed58282615ccb565b9150508281036020840152614c928185615d9d56fea164736f6c6343000818000a", } var OffRampABI = OffRampMetaData.ABI diff --git a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt index 35daa791c3..fa4edfd3dd 100644 --- a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -4,7 +4,7 @@ burn_mint_token_pool: ../../../contracts/solc/v0.8.24/BurnMintTokenPool/BurnMint burn_mint_token_pool_and_proxy: ../../../contracts/solc/v0.8.24/BurnMintTokenPoolAndProxy/BurnMintTokenPoolAndProxy.abi ../../../contracts/solc/v0.8.24/BurnMintTokenPoolAndProxy/BurnMintTokenPoolAndProxy.bin 717c079d5d13300cf3c3ee871c6e5bf9af904411f204fb081a9f3b263cca1391 burn_with_from_mint_token_pool: ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.abi ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.bin 6333d0314d0bd29e75ea5e05fe62a4516ade0c6db91c30b6f93645035db52ed8 burn_with_from_mint_token_pool_and_proxy: ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPoolAndProxy/BurnWithFromMintTokenPoolAndProxy.abi ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPoolAndProxy/BurnWithFromMintTokenPoolAndProxy.bin 08ed1235dda921ce8841b26aa18d0c0f36db4884779dd7670857159801b6d597 -ccip_config: ../../../contracts/solc/v0.8.24/CCIPConfig/CCIPConfig.abi ../../../contracts/solc/v0.8.24/CCIPConfig/CCIPConfig.bin 3b89dd119dc7a0719bf70339e80e820a8c0d615e7b257631ed12e2e6a95ea19c +ccip_config: ../../../contracts/solc/v0.8.24/CCIPConfig/CCIPConfig.abi ../../../contracts/solc/v0.8.24/CCIPConfig/CCIPConfig.bin 02da0d657b0835cf89f39ba790a96cab4595d27e16ebb7242a40dcec67e9da56 ccip_reader_tester: ../../../contracts/solc/v0.8.24/CCIPReaderTester/CCIPReaderTester.abi ../../../contracts/solc/v0.8.24/CCIPReaderTester/CCIPReaderTester.bin d8d70fe111bacc7702c7c263f8c4733dcb2fff77e52c9f60c30d303731bc97c1 commit_store: ../../../contracts/solc/v0.8.24/CommitStore/CommitStore.abi ../../../contracts/solc/v0.8.24/CommitStore/CommitStore.bin 274d87db70b643e00ab0a7e7845bb4b791f3b613bfc87708d33fc5a8369e2a41 commit_store_helper: ../../../contracts/solc/v0.8.24/CommitStoreHelper/CommitStoreHelper.abi ../../../contracts/solc/v0.8.24/CommitStoreHelper/CommitStoreHelper.bin f7128dcc2ee6dbcbc976288abcc16970ffb19b59412c5202ef6b259d2007f801 @@ -20,10 +20,10 @@ mock_usdc_token_messenger: ../../../contracts/solc/v0.8.24/MockE2EUSDCTokenMesse mock_usdc_token_transmitter: ../../../contracts/solc/v0.8.24/MockE2EUSDCTransmitter/MockE2EUSDCTransmitter.abi ../../../contracts/solc/v0.8.24/MockE2EUSDCTransmitter/MockE2EUSDCTransmitter.bin be0dbc3e475741ea0b7a54ec2b935a321b428baa9f4ce18180a87fb38bb87de2 mock_v3_aggregator_contract: ../../../contracts/solc/v0.8.24/MockV3Aggregator/MockV3Aggregator.abi ../../../contracts/solc/v0.8.24/MockV3Aggregator/MockV3Aggregator.bin 518e19efa2ff52b0fefd8e597b05765317ee7638189bfe34ca43de2f6599faf4 multi_aggregate_rate_limiter: ../../../contracts/solc/v0.8.24/MultiAggregateRateLimiter/MultiAggregateRateLimiter.abi ../../../contracts/solc/v0.8.24/MultiAggregateRateLimiter/MultiAggregateRateLimiter.bin 0b541232e49727e947dc164eadf35963c66e67576f21baa0ecaa06a8833148ed -multi_ocr3_helper: ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Helper.abi ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Helper.bin a0b23ebb141fa05e59f84bb8a8abd5eb804b94ddad6dc9f4beda5cc6995cb0f5 +multi_ocr3_helper: ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Helper.abi ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Helper.bin 6b56e0114a4d50797d30a34aecc2641ef340451d0c3fcb9d729bba4df2435122 nonce_manager: ../../../contracts/solc/v0.8.24/NonceManager/NonceManager.abi ../../../contracts/solc/v0.8.24/NonceManager/NonceManager.bin 6f64e1083b356c06ee66b9138e398b9c97a4cd3e8c9ec38cf3010cebc79af536 ocr3_config_encoder: ../../../contracts/solc/v0.8.24/IOCR3ConfigEncoder/IOCR3ConfigEncoder.abi ../../../contracts/solc/v0.8.24/IOCR3ConfigEncoder/IOCR3ConfigEncoder.bin e21180898e1ad54a045ee20add85a2793c681425ea06f66d1a9e5cab128b6487 -offramp: ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.abi ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.bin e6344e0f3a65ff8122b41eb071cde5641a666c14ced5d72a04d65efb9ef538a5 +offramp: ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.abi ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.bin 263df151d037af19cc412a051efb82993b0ccdde0184c598e3669f1326ab4ce9 onramp: ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.abi ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.bin 93ad9efaf8789baf7133a5db803b20d05b4771bf25f57a438cb7e5a8111fb472 ping_pong_demo: ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.abi ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.bin c1c2f8a65c7ffd971899cae7fe62f2da57d09e936151e2b92163c4bebe699d6b price_registry: ../../../contracts/solc/v0.8.24/PriceRegistry/PriceRegistry.abi ../../../contracts/solc/v0.8.24/PriceRegistry/PriceRegistry.bin e7781d600c1bb7aa4620106af7f6e146a109b97f4cb6a7d06c9e15773340ecb2 From 6ffa59d2853e45e2e11d2bb7e3feeec33718bd3b Mon Sep 17 00:00:00 2001 From: Suryansh <39276431+0xsuryansh@users.noreply.github.com> Date: Wed, 4 Sep 2024 14:50:25 +0530 Subject: [PATCH 069/115] rename CCIPSendRequested to CCIPMessageSent (#1409) --- contracts/src/v0.8/ccip/onRamp/OnRamp.sol | 4 +- .../src/v0.8/ccip/test/NonceManager.t.sol | 8 +-- .../MultiOnRampTokenPoolReentrancy.t.sol | 4 +- .../v0.8/ccip/test/e2e/MultiRampsEnd2End.sol | 2 +- .../src/v0.8/ccip/test/onRamp/OnRamp.t.sol | 20 +++---- .../ccip/generated/onramp/onramp.go | 54 +++++++++---------- ...rapper-dependency-versions-do-not-edit.txt | 2 +- 7 files changed, 47 insertions(+), 47 deletions(-) diff --git a/contracts/src/v0.8/ccip/onRamp/OnRamp.sol b/contracts/src/v0.8/ccip/onRamp/OnRamp.sol index 21b2f8efb0..677ec1a191 100644 --- a/contracts/src/v0.8/ccip/onRamp/OnRamp.sol +++ b/contracts/src/v0.8/ccip/onRamp/OnRamp.sol @@ -48,7 +48,7 @@ contract OnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCreator { event FeePaid(address indexed feeToken, uint256 feeValueJuels); event FeeTokenWithdrawn(address indexed feeAggregator, address indexed feeToken, uint256 amount); /// RMN depends on this event, if changing, please notify the RMN maintainers. - event CCIPSendRequested(uint64 indexed destChainSelector, Internal.EVM2AnyRampMessage message); + event CCIPMessageSent(uint64 indexed destChainSelector, Internal.EVM2AnyRampMessage message); event AllowListAdminSet(address indexed allowListAdmin); event AllowListSendersAdded(uint64 indexed destChainSelector, address[] senders); event AllowListSendersRemoved(uint64 indexed destChainSelector, address[] senders); @@ -243,7 +243,7 @@ contract OnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCreator { // Emit message request // This must happen after any pool events as some tokens (e.g. USDC) emit events that we expect to precede this // event in the offchain code. - emit CCIPSendRequested(destChainSelector, newMessage); + emit CCIPMessageSent(destChainSelector, newMessage); return newMessage.header.messageId; } diff --git a/contracts/src/v0.8/ccip/test/NonceManager.t.sol b/contracts/src/v0.8/ccip/test/NonceManager.t.sol index 69afc7104e..8c61ba5d21 100644 --- a/contracts/src/v0.8/ccip/test/NonceManager.t.sol +++ b/contracts/src/v0.8/ccip/test/NonceManager.t.sol @@ -265,7 +265,7 @@ contract NonceManager_OnRampUpgrade is OnRampSetup { Client.EVM2AnyMessage memory message = _generateEmptyMessage(); vm.expectEmit(); - emit OnRamp.CCIPSendRequested(DEST_CHAIN_SELECTOR, _messageToEvent(message, 1, 1, FEE_AMOUNT, OWNER)); + emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, _messageToEvent(message, 1, 1, FEE_AMOUNT, OWNER)); s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, FEE_AMOUNT, OWNER); } @@ -292,14 +292,14 @@ contract NonceManager_OnRampUpgrade is OnRampSetup { // new onramp nonce should start from 2, while sequence number start from 1 vm.expectEmit(); - emit OnRamp.CCIPSendRequested(DEST_CHAIN_SELECTOR, _messageToEvent(message, 1, startNonce + 2, FEE_AMOUNT, OWNER)); + emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, _messageToEvent(message, 1, startNonce + 2, FEE_AMOUNT, OWNER)); s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, FEE_AMOUNT, OWNER); assertEq(startNonce + 2, s_outboundNonceManager.getOutboundNonce(DEST_CHAIN_SELECTOR, OWNER)); // after another send, nonce should be 3, and sequence number be 2 vm.expectEmit(); - emit OnRamp.CCIPSendRequested(DEST_CHAIN_SELECTOR, _messageToEvent(message, 2, startNonce + 3, FEE_AMOUNT, OWNER)); + emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, _messageToEvent(message, 2, startNonce + 3, FEE_AMOUNT, OWNER)); s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, FEE_AMOUNT, OWNER); assertEq(startNonce + 3, s_outboundNonceManager.getOutboundNonce(DEST_CHAIN_SELECTOR, OWNER)); @@ -314,7 +314,7 @@ contract NonceManager_OnRampUpgrade is OnRampSetup { address newSender = address(1234567); // new onramp nonce should start from 1 for new sender vm.expectEmit(); - emit OnRamp.CCIPSendRequested(DEST_CHAIN_SELECTOR, _messageToEvent(message, 1, 1, FEE_AMOUNT, newSender)); + emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, _messageToEvent(message, 1, 1, FEE_AMOUNT, newSender)); s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, FEE_AMOUNT, newSender); } } diff --git a/contracts/src/v0.8/ccip/test/attacks/onRamp/MultiOnRampTokenPoolReentrancy.t.sol b/contracts/src/v0.8/ccip/test/attacks/onRamp/MultiOnRampTokenPoolReentrancy.t.sol index 0eea71eacc..5161aba883 100644 --- a/contracts/src/v0.8/ccip/test/attacks/onRamp/MultiOnRampTokenPoolReentrancy.t.sol +++ b/contracts/src/v0.8/ccip/test/attacks/onRamp/MultiOnRampTokenPoolReentrancy.t.sol @@ -107,9 +107,9 @@ contract MultiOnRampTokenPoolReentrancy is OnRampSetup { Internal.EVM2AnyRampMessage memory msgEvent2 = _messageToEvent(message2, 2, 2, expectedFee, address(s_facadeClient)); vm.expectEmit(); - emit OnRamp.CCIPSendRequested(DEST_CHAIN_SELECTOR, msgEvent2); + emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, msgEvent2); vm.expectEmit(); - emit OnRamp.CCIPSendRequested(DEST_CHAIN_SELECTOR, msgEvent1); + emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, msgEvent1); s_facadeClient.send(amount); } diff --git a/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.sol b/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.sol index b22e4db9d4..c3c1b311ee 100644 --- a/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.sol +++ b/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.sol @@ -251,7 +251,7 @@ contract MultiRampsE2E is OnRampSetup, OffRampSetup { ); vm.expectEmit(); - emit OnRamp.CCIPSendRequested(DEST_CHAIN_SELECTOR, msgEvent); + emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, msgEvent); vm.resumeGasMetering(); router.ccipSend(DEST_CHAIN_SELECTOR, message); diff --git a/contracts/src/v0.8/ccip/test/onRamp/OnRamp.t.sol b/contracts/src/v0.8/ccip/test/onRamp/OnRamp.t.sol index a6f4205ee1..f49a196603 100644 --- a/contracts/src/v0.8/ccip/test/onRamp/OnRamp.t.sol +++ b/contracts/src/v0.8/ccip/test/onRamp/OnRamp.t.sol @@ -144,7 +144,7 @@ contract OnRamp_forwardFromRouter is OnRampSetup { IERC20(s_sourceFeeToken).transferFrom(OWNER, address(s_onRamp), feeAmount); vm.expectEmit(); - emit OnRamp.CCIPSendRequested(DEST_CHAIN_SELECTOR, _messageToEvent(message, 1, 1, feeAmount, OWNER)); + emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, _messageToEvent(message, 1, 1, feeAmount, OWNER)); s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); } @@ -180,7 +180,7 @@ contract OnRamp_forwardFromRouter is OnRampSetup { vm.expectEmit(); // We expect the message to be emitted with strict = false. - emit OnRamp.CCIPSendRequested(DEST_CHAIN_SELECTOR, _messageToEvent(message, 1, 1, feeAmount, OWNER)); + emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, _messageToEvent(message, 1, 1, feeAmount, OWNER)); s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); } @@ -193,7 +193,7 @@ contract OnRamp_forwardFromRouter is OnRampSetup { vm.expectEmit(); // We expect the message to be emitted with strict = false. - emit OnRamp.CCIPSendRequested(DEST_CHAIN_SELECTOR, _messageToEvent(message, 1, 1, feeAmount, OWNER)); + emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, _messageToEvent(message, 1, 1, feeAmount, OWNER)); s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); } @@ -205,7 +205,7 @@ contract OnRamp_forwardFromRouter is OnRampSetup { IERC20(s_sourceFeeToken).transferFrom(OWNER, address(s_onRamp), feeAmount); vm.expectEmit(); - emit OnRamp.CCIPSendRequested(DEST_CHAIN_SELECTOR, _messageToEvent(message, 1, 1, feeAmount, OWNER)); + emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, _messageToEvent(message, 1, 1, feeAmount, OWNER)); s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); } @@ -219,7 +219,7 @@ contract OnRamp_forwardFromRouter is OnRampSetup { IERC20(s_sourceFeeToken).transferFrom(OWNER, address(s_onRamp), feeAmount); vm.expectEmit(); - emit OnRamp.CCIPSendRequested(DEST_CHAIN_SELECTOR, _messageToEvent(message, 1, 1, feeAmount, OWNER)); + emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, _messageToEvent(message, 1, 1, feeAmount, OWNER)); s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); } @@ -233,7 +233,7 @@ contract OnRamp_forwardFromRouter is OnRampSetup { IERC20(s_sourceFeeToken).transferFrom(OWNER, address(s_onRamp), feeAmount); vm.expectEmit(); - emit OnRamp.CCIPSendRequested(DEST_CHAIN_SELECTOR, _messageToEvent(message, 1, 1, feeAmount, OWNER)); + emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, _messageToEvent(message, 1, 1, feeAmount, OWNER)); s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); } @@ -246,7 +246,7 @@ contract OnRamp_forwardFromRouter is OnRampSetup { uint64 sequenceNumberBefore = s_onRamp.getExpectedNextSequenceNumber(DEST_CHAIN_SELECTOR) - 1; vm.expectEmit(); - emit OnRamp.CCIPSendRequested(DEST_CHAIN_SELECTOR, _messageToEvent(message, i, i, 0, OWNER)); + emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, _messageToEvent(message, i, i, 0, OWNER)); s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); @@ -268,7 +268,7 @@ contract OnRamp_forwardFromRouter is OnRampSetup { uint64 sequenceNumberBefore = s_onRamp.getExpectedNextSequenceNumber(DEST_CHAIN_SELECTOR) - 1; vm.expectEmit(); - emit OnRamp.CCIPSendRequested(DEST_CHAIN_SELECTOR, _messageToEvent(message, i, i, 0, OWNER)); + emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, _messageToEvent(message, i, i, 0, OWNER)); s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, 0, OWNER); @@ -353,7 +353,7 @@ contract OnRamp_forwardFromRouter is OnRampSetup { vm.expectEmit(); emit OnRamp.FeePaid(s_sourceFeeToken, feeTokenAmount); vm.expectEmit(false, false, false, true); - emit OnRamp.CCIPSendRequested(DEST_CHAIN_SELECTOR, expectedEvent); + emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, expectedEvent); // Assert the message Id is correct assertEq( @@ -375,7 +375,7 @@ contract OnRamp_forwardFromRouter is OnRampSetup { s_outboundMessageValidator.setMessageIdValidationState(keccak256(abi.encode(message)), false); vm.expectEmit(); - emit OnRamp.CCIPSendRequested(DEST_CHAIN_SELECTOR, _messageToEvent(message, 1, 1, feeAmount, OWNER)); + emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, _messageToEvent(message, 1, 1, feeAmount, OWNER)); s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); } diff --git a/core/gethwrappers/ccip/generated/onramp/onramp.go b/core/gethwrappers/ccip/generated/onramp/onramp.go index bd07c18f3a..61c35f6c4d 100644 --- a/core/gethwrappers/ccip/generated/onramp/onramp.go +++ b/core/gethwrappers/ccip/generated/onramp/onramp.go @@ -97,8 +97,8 @@ type OnRampStaticConfig struct { } var OnRampMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CannotSendZeroTokens\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GetSupportedTokensFunctionalityRemovedCheckAdminRegistry\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidAllowListRequest\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidDestChainConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeCalledByRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrAllowlistAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RouterMustSetOriginalSender\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"UnsupportedToken\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"name\":\"AllowListAdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"senders\",\"type\":\"address[]\"}],\"name\":\"AllowListSendersAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"senders\",\"type\":\"address[]\"}],\"name\":\"AllowListSendersRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"CCIPSendRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOnRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"allowListEnabled\",\"type\":\"bool\"}],\"name\":\"DestChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"feeValueJuels\",\"type\":\"uint256\"}],\"name\":\"FeePaid\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeeTokenWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"allowListEnabled\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"addedAllowlistedSenders\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"removedAllowlistedSenders\",\"type\":\"address[]\"}],\"internalType\":\"structOnRamp.AllowListConfigArgs[]\",\"name\":\"allowListConfigArgsItems\",\"type\":\"tuple[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyDestChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"}],\"name\":\"forwardFromRouter\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getAllowedSendersList\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getDestChainConfig\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"allowListEnabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getExpectedNextSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"getFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"},{\"internalType\":\"contractIERC20\",\"name\":\"sourceToken\",\"type\":\"address\"}],\"name\":\"getPoolBySourceToken\",\"outputs\":[{\"internalType\":\"contractIPoolV1\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"contractIRouter\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"name\":\"getSupportedTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"setDynamicConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"withdrawFeeTokens\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x6101006040523480156200001257600080fd5b506040516200402938038062004029833981016040819052620000359162000665565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf8162000186565b505083516001600160401b031615905080620000e6575060208301516001600160a01b0316155b80620000fd575060408301516001600160a01b0316155b8062000114575060608301516001600160a01b0316155b1562000133576040516306b7c75960e31b815260040160405180910390fd5b82516001600160401b031660805260208301516001600160a01b0390811660a0526040840151811660c05260608401511660e052620001728262000231565b6200017d8162000390565b5050506200079f565b336001600160a01b03821603620001e05760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b0316158062000254575060408101516001600160a01b0316155b1562000273576040516306b7c75960e31b815260040160405180910390fd5b8051600280546001600160a01b03199081166001600160a01b0393841617909155602080840180516003805485169186169190911790556040808601805160048054871691881691909117905560608088018051600580549098169089161790965582516080808201855280516001600160401b031680835260a080518b16848a0190815260c080518d16868a0190815260e080518f169789019788528a5195865292518e169b85019b909b5299518c169783019790975292518a169381019390935289518916908301529351871693810193909352518516928201929092529151909216918101919091527f23a1adf8ad7fad6091a4803227af2cee848c01a7c812404cade7c25636925e32906101000160405180910390a150565b60005b8151811015620004cf576000828281518110620003b457620003b462000789565b602002602001015190506000838381518110620003d557620003d562000789565b6020026020010151600001519050806001600160401b03166000036200041a5760405163c35aa79d60e01b81526001600160401b038216600482015260240162000083565b6001600160401b03818116600081815260066020908152604091829020868201518154600160481b600160e81b0319811669010000000000000000006001600160a01b03909316928302908117808555865192891691909816178152928301526801000000000000000090940460ff161515918101919091527fd5ad72bc37dc7a80a8b9b9df20500046fd7341adb1be2258a540466fdd7dcef59060600160405180910390a250505080600101905062000393565b5050565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b03811182821017156200050e576200050e620004d3565b60405290565b604080519081016001600160401b03811182821017156200050e576200050e620004d3565b604051601f8201601f191681016001600160401b0381118282101715620005645762000564620004d3565b604052919050565b80516001600160401b03811681146200058457600080fd5b919050565b6001600160a01b03811681146200059f57600080fd5b50565b600082601f830112620005b457600080fd5b815160206001600160401b03821115620005d257620005d2620004d3565b620005e2818360051b0162000539565b82815260069290921b840181019181810190868411156200060257600080fd5b8286015b848110156200065a5760408189031215620006215760008081fd5b6200062b62000514565b62000636826200056c565b815284820151620006478162000589565b8186015283529183019160400162000606565b509695505050505050565b60008060008385036101208112156200067d57600080fd5b60808112156200068c57600080fd5b62000696620004e9565b620006a1866200056c565b81526020860151620006b38162000589565b60208201526040860151620006c88162000589565b60408201526060860151620006dd8162000589565b606082015293506080607f1982011215620006f757600080fd5b5062000702620004e9565b6080850151620007128162000589565b815260a0850151620007248162000589565b602082015260c0850151620007398162000589565b604082015260e08501516200074e8162000589565b60608201526101008501519092506001600160401b038111156200077157600080fd5b6200077f86828701620005a2565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b60805160a05160c05160e051613811620008186000396000818161022c01528181610c790152611ba10152600081816101f0015281816112480152611b7a0152600081816101b4015281816105de0152611b500152600081816101840152818161116e0152818161164b0152611b2301526138116000f3fe608060405234801561001057600080fd5b50600436106101365760003560e01c806379ba5097116100b2578063a6f3ab6c11610081578063df0aa9e911610066578063df0aa9e91461052d578063f2fde38b14610540578063fbca3b741461055357600080fd5b8063a6f3ab6c146104cd578063d77d5ed0146104e057600080fd5b806379ba50971461045b5780638da5cb5b146104635780639041be3d14610481578063972b4612146104ad57600080fd5b806334adf4941161010957806348a98aa4116100ee57806348a98aa4146103045780636def4ce71461033c5780637437ff9f146103db57600080fd5b806334adf494146102e95780633a019940146102fc57600080fd5b80630242cf601461013b57806306285c6914610150578063181f5a771461027f57806320487ded146102c8575b600080fd5b61014e610149366004612696565b610566565b005b61026960408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16815250905090565b6040516102769190612759565b60405180910390f35b6102bb6040518060400160405280601081526020017f4f6e52616d7020312e362e302d6465760000000000000000000000000000000081525081565b604051610276919061281e565b6102db6102d6366004612849565b61057a565b604051908152602001610276565b61014e6102f7366004612899565b610733565b61014e610a06565b61031761031236600461290e565b610c31565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610276565b61039f61034a366004612947565b67ffffffffffffffff9081166000908152600660205260409020549081169168010000000000000000820460ff16916901000000000000000000900473ffffffffffffffffffffffffffffffffffffffff1690565b6040805167ffffffffffffffff9094168452911515602084015273ffffffffffffffffffffffffffffffffffffffff1690820152606001610276565b61044e604080516080810182526000808252602082018190529181018290526060810191909152506040805160808101825260025473ffffffffffffffffffffffffffffffffffffffff908116825260035481166020830152600454811692820192909252600554909116606082015290565b6040516102769190612964565b61014e610ce6565b60005473ffffffffffffffffffffffffffffffffffffffff16610317565b61049461048f366004612947565b610de3565b60405167ffffffffffffffff9091168152602001610276565b6104c06104bb366004612947565b610e0c565b60405161027691906129ad565b61014e6104db366004612a17565b610e34565b6103176104ee366004612947565b67ffffffffffffffff166000908152600660205260409020546901000000000000000000900473ffffffffffffffffffffffffffffffffffffffff1690565b6102db61053b366004612a7e565b610e45565b61014e61054e366004612aea565b6116fe565b6104c0610561366004612947565b61170f565b61056e611743565b610577816117c6565b50565b6040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815277ffffffffffffffff00000000000000000000000000000000608084901b16600482015260009073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690632cbc26bb90602401602060405180830381865afa158015610625573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106499190612b15565b15610691576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024015b60405180910390fd5b6002546040517fd8694ccd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063d8694ccd906106e99086908690600401612c46565b602060405180830381865afa158015610706573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061072a9190612d8f565b90505b92915050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146107a35760055473ffffffffffffffffffffffffffffffffffffffff1633146107a3576040517f905d7d9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015610a015760008383838181106107c2576107c2612da8565b90506020028101906107d49190612dd7565b6107dd90612e88565b805167ffffffffffffffff1660009081526006602090815260409091209082015181547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff16680100000000000000009115801592909202178255919250906109545760005b8260400151518110156108fd5760008360400151828151811061086757610867612da8565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036108e65783516040517f463258ff00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610688565b6108f3600184018261193d565b5050600101610842565b506040820151511561095457816000015167ffffffffffffffff167f330939f6eafe8bb516716892fe962ff19770570838686e6579dbc1cc51fc3281836040015160405161094b91906129ad565b60405180910390a25b60005b8260600151518110156109a0576109978360600151828151811061097d5761097d612da8565b60200260200101518360010161195f90919063ffffffff16565b50600101610957565b50606082015151156109f757816000015167ffffffffffffffff167fc237ec1921f855ccd5e9a5af9733f2d58943a5a8501ec5988e305d7a4d42158683606001516040516109ee91906129ad565b60405180910390a25b50506001016107a6565b505050565b600254604080517fcdc73d51000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163cdc73d5191600480830192869291908290030181865afa158015610a75573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610abb9190810190612f1b565b60045490915073ffffffffffffffffffffffffffffffffffffffff1660005b8251811015610a01576000838281518110610af757610af7612da8565b60209081029190910101516040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915060009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa158015610b72573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b969190612d8f565b90508015610c2757610bbf73ffffffffffffffffffffffffffffffffffffffff83168583611981565b8173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f508d7d183612c18fc339b42618912b9fa3239f631dd7ec0671f950200a0fa66e83604051610c1e91815260200190565b60405180910390a35b5050600101610ada565b6040517fbbe4f6db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063bbe4f6db90602401602060405180830381865afa158015610cc2573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061072a9190612faa565b60015473ffffffffffffffffffffffffffffffffffffffff163314610d67576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610688565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b67ffffffffffffffff808216600090815260066020526040812054909161072d91166001612ff6565b67ffffffffffffffff8116600090815260066020526040902060609061072d90600101611a0e565b610e3c611743565b61057781611a22565b67ffffffffffffffff8416600090815260066020526040812073ffffffffffffffffffffffffffffffffffffffff8316610eab576040517fa4ec747900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805468010000000000000000900460ff1615610f1c57610ece6001820184611c04565b610f1c576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152602401610688565b80546901000000000000000000900473ffffffffffffffffffffffffffffffffffffffff163314610f79576040517f1c0a352900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60035473ffffffffffffffffffffffffffffffffffffffff16801561101f576040517fe0a0e50600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82169063e0a0e50690610fec908a908a90600401612c46565b600060405180830381600087803b15801561100657600080fd5b505af115801561101a573d6000803e3d6000fd5b505050505b506002546000908190819073ffffffffffffffffffffffffffffffffffffffff1663c4276bfc8a61105660808c0160608d01612aea565b8a61106460808e018e613017565b6040518663ffffffff1660e01b815260040161108495949392919061307c565b600060405180830381865afa1580156110a1573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526110e79190810190613144565b919450925090506110fe6080890160608a01612aea565b73ffffffffffffffffffffffffffffffffffffffff167f075a2720282fdf622141dae0b048ef90a21a7e57c134c76912d19d006b3b3f6f8460405161114591815260200190565b60405180910390a2604080516101a081019091526000610100820181815267ffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000081166101208501528c811661014085015287549293928392916101608401918a9187916111ba911661319e565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905567ffffffffffffffff168152602001866112ba576040517fea458c0c00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8f16600482015273ffffffffffffffffffffffffffffffffffffffff8c811660248301527f0000000000000000000000000000000000000000000000000000000000000000169063ea458c0c906044016020604051808303816000875af1158015611291573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112b591906131c5565b6112bd565b60005b67ffffffffffffffff1681525081526020018873ffffffffffffffffffffffffffffffffffffffff1681526020018a80602001906112fb9190613017565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050509082525060200161133f8b80613017565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050908252506020810184905260400161139060808c0160608d01612aea565b73ffffffffffffffffffffffffffffffffffffffff1681526020018981526020018a80604001906113c191906131e2565b905067ffffffffffffffff8111156113db576113db612570565b60405190808252806020026020018201604052801561143e57816020015b61142b6040518060a0016040528060608152602001606081526020016060815260200160008152602001606081525090565b8152602001906001900390816113f95790505b509052905060005b61145360408b018b6131e2565b9050811015611502576114d961146c60408c018c6131e2565b8381811061147c5761147c612da8565b905060400201803603810190611492919061324a565b8c61149d8d80613017565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508e9250611c33915050565b8260e0015182815181106114ef576114ef612da8565b6020908102919091010152600101611446565b5060025460e082015160009173ffffffffffffffffffffffffffffffffffffffff169063085318f8908d9061153a60408f018f6131e2565b6040518563ffffffff1660e01b81526004016115599493929190613361565b600060405180830381865afa158015611576573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526115bc9190810190613397565b905060005b8260e0015151811015611615578181815181106115e0576115e0612da8565b60200260200101518360e0015182815181106115fe576115fe612da8565b6020908102919091010151608001526001016115c1565b50604080517f130ac867e79e2789f923760a88743d292acdf7002139a588206e2260f73f7321602082015267ffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811692820192909252908c1660608201523060808201526116a590839060a00160405160208183030381529060405280519060200120611f59565b82515260405167ffffffffffffffff8c16907fcae3d9f68a9ed33d0a770e9bcc6fc25d4041dd6391e6cd8015546547a3c93140906116e4908590613448565b60405180910390a25051519450505050505b949350505050565b611706611743565b61057781612059565b60606040517f9e7177c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005473ffffffffffffffffffffffffffffffffffffffff1633146117c4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610688565b565b60005b81518110156119395760008282815181106117e6576117e6612da8565b60200260200101519050600083838151811061180457611804612da8565b60200260200101516000015190508067ffffffffffffffff16600003611862576040517fc35aa79d00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610688565b67ffffffffffffffff8181166000818152600660209081526040918290208682015181547fffffff0000000000000000000000000000000000000000ffffffffffffffffff8116690100000000000000000073ffffffffffffffffffffffffffffffffffffffff909316928302908117808555865192891691909816178152928301526801000000000000000090940460ff161515918101919091527fd5ad72bc37dc7a80a8b9b9df20500046fd7341adb1be2258a540466fdd7dcef59060600160405180910390a25050508060010190506117c9565b5050565b600061072a8373ffffffffffffffffffffffffffffffffffffffff841661214e565b600061072a8373ffffffffffffffffffffffffffffffffffffffff841661219d565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052610a01908490612297565b60606000611a1b836123a3565b9392505050565b805173ffffffffffffffffffffffffffffffffffffffff161580611a5e5750604081015173ffffffffffffffffffffffffffffffffffffffff16155b15611a95576040517f35be3ac800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051600280547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff93841617909155602080840151600380548416918516919091179055604080850151600480548516918616919091179055606080860151600580549095169086161790935580516080810182527f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681527f00000000000000000000000000000000000000000000000000000000000000008516928101929092527f00000000000000000000000000000000000000000000000000000000000000008416828201527f00000000000000000000000000000000000000000000000000000000000000009093169181019190915290517f23a1adf8ad7fad6091a4803227af2cee848c01a7c812404cade7c25636925e3291611bf9918490613596565b60405180910390a150565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600183016020526040812054151561072a565b611c656040518060a0016040528060608152602001606081526020016060815260200160008152602001606081525090565b8460200151600003611ca3576040517f5cf0444900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611cb3858760000151610c31565b905073ffffffffffffffffffffffffffffffffffffffff81161580611d8357506040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527faff2afbf00000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff8216906301ffc9a790602401602060405180830381865afa158015611d5d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d819190612b15565b155b15611dd55785516040517fbf16aab600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610688565b60008173ffffffffffffffffffffffffffffffffffffffff16639a4575b96040518060a001604052808881526020018967ffffffffffffffff1681526020018773ffffffffffffffffffffffffffffffffffffffff1681526020018a6020015181526020018a6000015173ffffffffffffffffffffffffffffffffffffffff168152506040518263ffffffff1660e01b8152600401611e749190613635565b6000604051808303816000875af1158015611e93573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611ed991908101906136ab565b6040805160a0810190915273ffffffffffffffffffffffffffffffffffffffff841660c08201529091508060e0810160405160208183030381529060405281526020018260000151815260200182602001518152602001886020015181526020016040518060200160405280600081525081525092505050949350505050565b60008060001b82846020015185606001518660000151606001518760000151608001518860a001518960c00151604051602001611f9b9695949392919061373c565b604051602081830303815290604052805190602001208560400151805190602001208660e00151604051602001611fd2919061379d565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201206080808c0151805190840120928501989098529183019590955260608201939093529384015260a083015260c082015260e00160405160208183030381529060405280519060200120905092915050565b3373ffffffffffffffffffffffffffffffffffffffff8216036120d8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610688565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60008181526001830160205260408120546121955750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561072d565b50600061072d565b600081815260018301602052604081205480156122865760006121c16001836137b0565b85549091506000906121d5906001906137b0565b905080821461223a5760008660000182815481106121f5576121f5612da8565b906000526020600020015490508087600001848154811061221857612218612da8565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061224b5761224b6137c3565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061072d565b600091505061072d565b5092915050565b60006122f9826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166123ff9092919063ffffffff16565b805190915015610a0157808060200190518101906123179190612b15565b610a01576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610688565b6060816000018054806020026020016040519081016040528092919081815260200182805480156123f357602002820191906000526020600020905b8154815260200190600101908083116123df575b50505050509050919050565b60606116f68484600085856000808673ffffffffffffffffffffffffffffffffffffffff16858760405161243391906137f2565b60006040518083038185875af1925050503d8060008114612470576040519150601f19603f3d011682016040523d82523d6000602084013e612475565b606091505b509150915061248687838387612491565b979650505050505050565b606083156125275782516000036125205773ffffffffffffffffffffffffffffffffffffffff85163b612520576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610688565b50816116f6565b6116f6838381511561253c5781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610688919061281e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff811182821017156125c2576125c2612570565b60405290565b6040516080810167ffffffffffffffff811182821017156125c2576125c2612570565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561263257612632612570565b604052919050565b600067ffffffffffffffff82111561265457612654612570565b5060051b60200190565b67ffffffffffffffff8116811461057757600080fd5b73ffffffffffffffffffffffffffffffffffffffff8116811461057757600080fd5b600060208083850312156126a957600080fd5b823567ffffffffffffffff8111156126c057600080fd5b8301601f810185136126d157600080fd5b80356126e46126df8261263a565b6125eb565b81815260069190911b8201830190838101908783111561270357600080fd5b928401925b8284101561248657604084890312156127215760008081fd5b61272961259f565b84356127348161265e565b81528486013561274381612674565b8187015282526040939093019290840190612708565b6080810161072d828467ffffffffffffffff8151168252602081015173ffffffffffffffffffffffffffffffffffffffff808216602085015280604084015116604085015280606084015116606085015250505050565b60005b838110156127cb5781810151838201526020016127b3565b50506000910152565b600081518084526127ec8160208601602086016127b0565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061072a60208301846127d4565b600060a0828403121561284357600080fd5b50919050565b6000806040838503121561285c57600080fd5b82356128678161265e565b9150602083013567ffffffffffffffff81111561288357600080fd5b61288f85828601612831565b9150509250929050565b600080602083850312156128ac57600080fd5b823567ffffffffffffffff808211156128c457600080fd5b818501915085601f8301126128d857600080fd5b8135818111156128e757600080fd5b8660208260051b85010111156128fc57600080fd5b60209290920196919550909350505050565b6000806040838503121561292157600080fd5b823561292c8161265e565b9150602083013561293c81612674565b809150509250929050565b60006020828403121561295957600080fd5b8135611a1b8161265e565b6080810161072d8284805173ffffffffffffffffffffffffffffffffffffffff908116835260208083015182169084015260408083015182169084015260609182015116910152565b6020808252825182820181905260009190848201906040850190845b818110156129fb57835173ffffffffffffffffffffffffffffffffffffffff16835292840192918401916001016129c9565b50909695505050505050565b8035612a1281612674565b919050565b600060808284031215612a2957600080fd5b612a316125c8565b8235612a3c81612674565b81526020830135612a4c81612674565b60208201526040830135612a5f81612674565b60408201526060830135612a7281612674565b60608201529392505050565b60008060008060808587031215612a9457600080fd5b8435612a9f8161265e565b9350602085013567ffffffffffffffff811115612abb57600080fd5b612ac787828801612831565b935050604085013591506060850135612adf81612674565b939692955090935050565b600060208284031215612afc57600080fd5b8135611a1b81612674565b801515811461057757600080fd5b600060208284031215612b2757600080fd5b8151611a1b81612b07565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112612b6757600080fd5b830160208101925035905067ffffffffffffffff811115612b8757600080fd5b803603821315612b9657600080fd5b9250929050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b8183526000602080850194508260005b85811015612c3b578135612c0981612674565b73ffffffffffffffffffffffffffffffffffffffff168752818301358388015260409687019690910190600101612bf6565b509495945050505050565b600067ffffffffffffffff808516835260406020840152612c678485612b32565b60a06040860152612c7c60e086018284612b9d565b915050612c8c6020860186612b32565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc080878503016060880152612cc2848385612b9d565b9350604088013592507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1883603018312612cfb57600080fd5b60209288019283019235915084821115612d1457600080fd5b8160061b3603831315612d2657600080fd5b80878503016080880152612d3b848385612be6565b9450612d4960608901612a07565b73ffffffffffffffffffffffffffffffffffffffff811660a08901529350612d746080890189612b32565b94509250808786030160c08801525050612486838383612b9d565b600060208284031215612da157600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81833603018112612e0b57600080fd5b9190910192915050565b600082601f830112612e2657600080fd5b81356020612e366126df8361263a565b8083825260208201915060208460051b870101935086841115612e5857600080fd5b602086015b84811015612e7d578035612e7081612674565b8352918301918301612e5d565b509695505050505050565b600060808236031215612e9a57600080fd5b612ea26125c8565b8235612ead8161265e565b81526020830135612ebd81612b07565b6020820152604083013567ffffffffffffffff80821115612edd57600080fd5b612ee936838701612e15565b60408401526060850135915080821115612f0257600080fd5b50612f0f36828601612e15565b60608301525092915050565b60006020808385031215612f2e57600080fd5b825167ffffffffffffffff811115612f4557600080fd5b8301601f81018513612f5657600080fd5b8051612f646126df8261263a565b81815260059190911b82018301908381019087831115612f8357600080fd5b928401925b82841015612486578351612f9b81612674565b82529284019290840190612f88565b600060208284031215612fbc57600080fd5b8151611a1b81612674565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b67ffffffffffffffff81811683821601908082111561229057612290612fc7565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261304c57600080fd5b83018035915067ffffffffffffffff82111561306757600080fd5b602001915036819003821315612b9657600080fd5b67ffffffffffffffff8616815273ffffffffffffffffffffffffffffffffffffffff85166020820152836040820152608060608201526000612486608083018486612b9d565b600082601f8301126130d357600080fd5b815167ffffffffffffffff8111156130ed576130ed612570565b61311e60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016125eb565b81815284602083860101111561313357600080fd5b6116f68260208301602087016127b0565b60008060006060848603121561315957600080fd5b83519250602084015161316b81612b07565b604085015190925067ffffffffffffffff81111561318857600080fd5b613194868287016130c2565b9150509250925092565b600067ffffffffffffffff8083168181036131bb576131bb612fc7565b6001019392505050565b6000602082840312156131d757600080fd5b8151611a1b8161265e565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261321757600080fd5b83018035915067ffffffffffffffff82111561323257600080fd5b6020019150600681901b3603821315612b9657600080fd5b60006040828403121561325c57600080fd5b61326461259f565b823561326f81612674565b81526020928301359281019290925250919050565b600082825180855260208086019550808260051b84010181860160005b84811015613354577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018952815160a081518186526132e5828701826127d4565b91505085820151858203878701526132fd82826127d4565b9150506040808301518683038288015261331783826127d4565b9250505060608083015181870152506080808301519250858203818701525061334081836127d4565b9a86019a94505050908301906001016132a1565b5090979650505050505050565b67ffffffffffffffff851681526060602082015260006133846060830186613284565b8281036040840152612486818587612be6565b600060208083850312156133aa57600080fd5b825167ffffffffffffffff808211156133c257600080fd5b818501915085601f8301126133d657600080fd5b81516133e46126df8261263a565b81815260059190911b8301840190848101908883111561340357600080fd5b8585015b8381101561343b5780518581111561341f5760008081fd5b61342d8b89838a01016130c2565b845250918601918601613407565b5098975050505050505050565b6020815261349960208201835180518252602081015167ffffffffffffffff808216602085015280604084015116604085015280606084015116606085015280608084015116608085015250505050565b600060208301516134c260c084018273ffffffffffffffffffffffffffffffffffffffff169052565b5060408301516101808060e08501526134df6101a08501836127d4565b915060608501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0808685030161010087015261351c84836127d4565b935060808701519150808685030161012087015261353a84836127d4565b935060a0870151915061356661014087018373ffffffffffffffffffffffffffffffffffffffff169052565b60c087015161016087015260e087015191508086850301838701525061358c8382613284565b9695505050505050565b61010081016135ee828567ffffffffffffffff8151168252602081015173ffffffffffffffffffffffffffffffffffffffff808216602085015280604084015116604085015280606084015116606085015250505050565b825173ffffffffffffffffffffffffffffffffffffffff90811660808401526020840151811660a08401526040840151811660c084015260608401511660e0830152611a1b565b602081526000825160a0602084015261365160c08401826127d4565b905067ffffffffffffffff6020850151166040840152604084015173ffffffffffffffffffffffffffffffffffffffff8082166060860152606086015160808601528060808701511660a086015250508091505092915050565b6000602082840312156136bd57600080fd5b815167ffffffffffffffff808211156136d557600080fd5b90830190604082860312156136e957600080fd5b6136f161259f565b82518281111561370057600080fd5b61370c878286016130c2565b82525060208301518281111561372157600080fd5b61372d878286016130c2565b60208301525095945050505050565b600073ffffffffffffffffffffffffffffffffffffffff808916835260c0602084015261376c60c08401896127d4565b67ffffffffffffffff97881660408501529590961660608301525091909316608082015260a0019190915292915050565b60208152600061072a6020830184613284565b8181038181111561072d5761072d612fc7565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b60008251612e0b8184602087016127b056fea164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CannotSendZeroTokens\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GetSupportedTokensFunctionalityRemovedCheckAdminRegistry\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidAllowListRequest\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidDestChainConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeCalledByRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrAllowlistAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RouterMustSetOriginalSender\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"UnsupportedToken\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"name\":\"AllowListAdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"senders\",\"type\":\"address[]\"}],\"name\":\"AllowListSendersAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"senders\",\"type\":\"address[]\"}],\"name\":\"AllowListSendersRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"CCIPMessageSent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOnRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"allowListEnabled\",\"type\":\"bool\"}],\"name\":\"DestChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"feeValueJuels\",\"type\":\"uint256\"}],\"name\":\"FeePaid\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeeTokenWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"allowListEnabled\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"addedAllowlistedSenders\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"removedAllowlistedSenders\",\"type\":\"address[]\"}],\"internalType\":\"structOnRamp.AllowListConfigArgs[]\",\"name\":\"allowListConfigArgsItems\",\"type\":\"tuple[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyDestChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"}],\"name\":\"forwardFromRouter\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getAllowedSendersList\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getDestChainConfig\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"allowListEnabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getExpectedNextSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"getFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"},{\"internalType\":\"contractIERC20\",\"name\":\"sourceToken\",\"type\":\"address\"}],\"name\":\"getPoolBySourceToken\",\"outputs\":[{\"internalType\":\"contractIPoolV1\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"contractIRouter\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"name\":\"getSupportedTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"setDynamicConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"withdrawFeeTokens\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x6101006040523480156200001257600080fd5b506040516200402938038062004029833981016040819052620000359162000665565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf8162000186565b505083516001600160401b031615905080620000e6575060208301516001600160a01b0316155b80620000fd575060408301516001600160a01b0316155b8062000114575060608301516001600160a01b0316155b1562000133576040516306b7c75960e31b815260040160405180910390fd5b82516001600160401b031660805260208301516001600160a01b0390811660a0526040840151811660c05260608401511660e052620001728262000231565b6200017d8162000390565b5050506200079f565b336001600160a01b03821603620001e05760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b0316158062000254575060408101516001600160a01b0316155b1562000273576040516306b7c75960e31b815260040160405180910390fd5b8051600280546001600160a01b03199081166001600160a01b0393841617909155602080840180516003805485169186169190911790556040808601805160048054871691881691909117905560608088018051600580549098169089161790965582516080808201855280516001600160401b031680835260a080518b16848a0190815260c080518d16868a0190815260e080518f169789019788528a5195865292518e169b85019b909b5299518c169783019790975292518a169381019390935289518916908301529351871693810193909352518516928201929092529151909216918101919091527f23a1adf8ad7fad6091a4803227af2cee848c01a7c812404cade7c25636925e32906101000160405180910390a150565b60005b8151811015620004cf576000828281518110620003b457620003b462000789565b602002602001015190506000838381518110620003d557620003d562000789565b6020026020010151600001519050806001600160401b03166000036200041a5760405163c35aa79d60e01b81526001600160401b038216600482015260240162000083565b6001600160401b03818116600081815260066020908152604091829020868201518154600160481b600160e81b0319811669010000000000000000006001600160a01b03909316928302908117808555865192891691909816178152928301526801000000000000000090940460ff161515918101919091527fd5ad72bc37dc7a80a8b9b9df20500046fd7341adb1be2258a540466fdd7dcef59060600160405180910390a250505080600101905062000393565b5050565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b03811182821017156200050e576200050e620004d3565b60405290565b604080519081016001600160401b03811182821017156200050e576200050e620004d3565b604051601f8201601f191681016001600160401b0381118282101715620005645762000564620004d3565b604052919050565b80516001600160401b03811681146200058457600080fd5b919050565b6001600160a01b03811681146200059f57600080fd5b50565b600082601f830112620005b457600080fd5b815160206001600160401b03821115620005d257620005d2620004d3565b620005e2818360051b0162000539565b82815260069290921b840181019181810190868411156200060257600080fd5b8286015b848110156200065a5760408189031215620006215760008081fd5b6200062b62000514565b62000636826200056c565b815284820151620006478162000589565b8186015283529183019160400162000606565b509695505050505050565b60008060008385036101208112156200067d57600080fd5b60808112156200068c57600080fd5b62000696620004e9565b620006a1866200056c565b81526020860151620006b38162000589565b60208201526040860151620006c88162000589565b60408201526060860151620006dd8162000589565b606082015293506080607f1982011215620006f757600080fd5b5062000702620004e9565b6080850151620007128162000589565b815260a0850151620007248162000589565b602082015260c0850151620007398162000589565b604082015260e08501516200074e8162000589565b60608201526101008501519092506001600160401b038111156200077157600080fd5b6200077f86828701620005a2565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b60805160a05160c05160e051613811620008186000396000818161022c01528181610c790152611ba10152600081816101f0015281816112480152611b7a0152600081816101b4015281816105de0152611b500152600081816101840152818161116e0152818161164b0152611b2301526138116000f3fe608060405234801561001057600080fd5b50600436106101365760003560e01c806379ba5097116100b2578063a6f3ab6c11610081578063df0aa9e911610066578063df0aa9e91461052d578063f2fde38b14610540578063fbca3b741461055357600080fd5b8063a6f3ab6c146104cd578063d77d5ed0146104e057600080fd5b806379ba50971461045b5780638da5cb5b146104635780639041be3d14610481578063972b4612146104ad57600080fd5b806334adf4941161010957806348a98aa4116100ee57806348a98aa4146103045780636def4ce71461033c5780637437ff9f146103db57600080fd5b806334adf494146102e95780633a019940146102fc57600080fd5b80630242cf601461013b57806306285c6914610150578063181f5a771461027f57806320487ded146102c8575b600080fd5b61014e610149366004612696565b610566565b005b61026960408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16815250905090565b6040516102769190612759565b60405180910390f35b6102bb6040518060400160405280601081526020017f4f6e52616d7020312e362e302d6465760000000000000000000000000000000081525081565b604051610276919061281e565b6102db6102d6366004612849565b61057a565b604051908152602001610276565b61014e6102f7366004612899565b610733565b61014e610a06565b61031761031236600461290e565b610c31565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610276565b61039f61034a366004612947565b67ffffffffffffffff9081166000908152600660205260409020549081169168010000000000000000820460ff16916901000000000000000000900473ffffffffffffffffffffffffffffffffffffffff1690565b6040805167ffffffffffffffff9094168452911515602084015273ffffffffffffffffffffffffffffffffffffffff1690820152606001610276565b61044e604080516080810182526000808252602082018190529181018290526060810191909152506040805160808101825260025473ffffffffffffffffffffffffffffffffffffffff908116825260035481166020830152600454811692820192909252600554909116606082015290565b6040516102769190612964565b61014e610ce6565b60005473ffffffffffffffffffffffffffffffffffffffff16610317565b61049461048f366004612947565b610de3565b60405167ffffffffffffffff9091168152602001610276565b6104c06104bb366004612947565b610e0c565b60405161027691906129ad565b61014e6104db366004612a17565b610e34565b6103176104ee366004612947565b67ffffffffffffffff166000908152600660205260409020546901000000000000000000900473ffffffffffffffffffffffffffffffffffffffff1690565b6102db61053b366004612a7e565b610e45565b61014e61054e366004612aea565b6116fe565b6104c0610561366004612947565b61170f565b61056e611743565b610577816117c6565b50565b6040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815277ffffffffffffffff00000000000000000000000000000000608084901b16600482015260009073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690632cbc26bb90602401602060405180830381865afa158015610625573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106499190612b15565b15610691576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024015b60405180910390fd5b6002546040517fd8694ccd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063d8694ccd906106e99086908690600401612c46565b602060405180830381865afa158015610706573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061072a9190612d8f565b90505b92915050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146107a35760055473ffffffffffffffffffffffffffffffffffffffff1633146107a3576040517f905d7d9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015610a015760008383838181106107c2576107c2612da8565b90506020028101906107d49190612dd7565b6107dd90612e88565b805167ffffffffffffffff1660009081526006602090815260409091209082015181547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff16680100000000000000009115801592909202178255919250906109545760005b8260400151518110156108fd5760008360400151828151811061086757610867612da8565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036108e65783516040517f463258ff00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610688565b6108f3600184018261193d565b5050600101610842565b506040820151511561095457816000015167ffffffffffffffff167f330939f6eafe8bb516716892fe962ff19770570838686e6579dbc1cc51fc3281836040015160405161094b91906129ad565b60405180910390a25b60005b8260600151518110156109a0576109978360600151828151811061097d5761097d612da8565b60200260200101518360010161195f90919063ffffffff16565b50600101610957565b50606082015151156109f757816000015167ffffffffffffffff167fc237ec1921f855ccd5e9a5af9733f2d58943a5a8501ec5988e305d7a4d42158683606001516040516109ee91906129ad565b60405180910390a25b50506001016107a6565b505050565b600254604080517fcdc73d51000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163cdc73d5191600480830192869291908290030181865afa158015610a75573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610abb9190810190612f1b565b60045490915073ffffffffffffffffffffffffffffffffffffffff1660005b8251811015610a01576000838281518110610af757610af7612da8565b60209081029190910101516040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915060009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa158015610b72573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b969190612d8f565b90508015610c2757610bbf73ffffffffffffffffffffffffffffffffffffffff83168583611981565b8173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f508d7d183612c18fc339b42618912b9fa3239f631dd7ec0671f950200a0fa66e83604051610c1e91815260200190565b60405180910390a35b5050600101610ada565b6040517fbbe4f6db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063bbe4f6db90602401602060405180830381865afa158015610cc2573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061072a9190612faa565b60015473ffffffffffffffffffffffffffffffffffffffff163314610d67576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610688565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b67ffffffffffffffff808216600090815260066020526040812054909161072d91166001612ff6565b67ffffffffffffffff8116600090815260066020526040902060609061072d90600101611a0e565b610e3c611743565b61057781611a22565b67ffffffffffffffff8416600090815260066020526040812073ffffffffffffffffffffffffffffffffffffffff8316610eab576040517fa4ec747900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805468010000000000000000900460ff1615610f1c57610ece6001820184611c04565b610f1c576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152602401610688565b80546901000000000000000000900473ffffffffffffffffffffffffffffffffffffffff163314610f79576040517f1c0a352900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60035473ffffffffffffffffffffffffffffffffffffffff16801561101f576040517fe0a0e50600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82169063e0a0e50690610fec908a908a90600401612c46565b600060405180830381600087803b15801561100657600080fd5b505af115801561101a573d6000803e3d6000fd5b505050505b506002546000908190819073ffffffffffffffffffffffffffffffffffffffff1663c4276bfc8a61105660808c0160608d01612aea565b8a61106460808e018e613017565b6040518663ffffffff1660e01b815260040161108495949392919061307c565b600060405180830381865afa1580156110a1573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526110e79190810190613144565b919450925090506110fe6080890160608a01612aea565b73ffffffffffffffffffffffffffffffffffffffff167f075a2720282fdf622141dae0b048ef90a21a7e57c134c76912d19d006b3b3f6f8460405161114591815260200190565b60405180910390a2604080516101a081019091526000610100820181815267ffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000081166101208501528c811661014085015287549293928392916101608401918a9187916111ba911661319e565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905567ffffffffffffffff168152602001866112ba576040517fea458c0c00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8f16600482015273ffffffffffffffffffffffffffffffffffffffff8c811660248301527f0000000000000000000000000000000000000000000000000000000000000000169063ea458c0c906044016020604051808303816000875af1158015611291573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112b591906131c5565b6112bd565b60005b67ffffffffffffffff1681525081526020018873ffffffffffffffffffffffffffffffffffffffff1681526020018a80602001906112fb9190613017565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050509082525060200161133f8b80613017565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050908252506020810184905260400161139060808c0160608d01612aea565b73ffffffffffffffffffffffffffffffffffffffff1681526020018981526020018a80604001906113c191906131e2565b905067ffffffffffffffff8111156113db576113db612570565b60405190808252806020026020018201604052801561143e57816020015b61142b6040518060a0016040528060608152602001606081526020016060815260200160008152602001606081525090565b8152602001906001900390816113f95790505b509052905060005b61145360408b018b6131e2565b9050811015611502576114d961146c60408c018c6131e2565b8381811061147c5761147c612da8565b905060400201803603810190611492919061324a565b8c61149d8d80613017565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508e9250611c33915050565b8260e0015182815181106114ef576114ef612da8565b6020908102919091010152600101611446565b5060025460e082015160009173ffffffffffffffffffffffffffffffffffffffff169063085318f8908d9061153a60408f018f6131e2565b6040518563ffffffff1660e01b81526004016115599493929190613361565b600060405180830381865afa158015611576573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526115bc9190810190613397565b905060005b8260e0015151811015611615578181815181106115e0576115e0612da8565b60200260200101518360e0015182815181106115fe576115fe612da8565b6020908102919091010151608001526001016115c1565b50604080517f130ac867e79e2789f923760a88743d292acdf7002139a588206e2260f73f7321602082015267ffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811692820192909252908c1660608201523060808201526116a590839060a00160405160208183030381529060405280519060200120611f59565b82515260405167ffffffffffffffff8c16907ff6e86ef8896c7a0d629406168f396e883280680c99e649b9e2d36466fbc9f9e5906116e4908590613448565b60405180910390a25051519450505050505b949350505050565b611706611743565b61057781612059565b60606040517f9e7177c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005473ffffffffffffffffffffffffffffffffffffffff1633146117c4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610688565b565b60005b81518110156119395760008282815181106117e6576117e6612da8565b60200260200101519050600083838151811061180457611804612da8565b60200260200101516000015190508067ffffffffffffffff16600003611862576040517fc35aa79d00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610688565b67ffffffffffffffff8181166000818152600660209081526040918290208682015181547fffffff0000000000000000000000000000000000000000ffffffffffffffffff8116690100000000000000000073ffffffffffffffffffffffffffffffffffffffff909316928302908117808555865192891691909816178152928301526801000000000000000090940460ff161515918101919091527fd5ad72bc37dc7a80a8b9b9df20500046fd7341adb1be2258a540466fdd7dcef59060600160405180910390a25050508060010190506117c9565b5050565b600061072a8373ffffffffffffffffffffffffffffffffffffffff841661214e565b600061072a8373ffffffffffffffffffffffffffffffffffffffff841661219d565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052610a01908490612297565b60606000611a1b836123a3565b9392505050565b805173ffffffffffffffffffffffffffffffffffffffff161580611a5e5750604081015173ffffffffffffffffffffffffffffffffffffffff16155b15611a95576040517f35be3ac800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051600280547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff93841617909155602080840151600380548416918516919091179055604080850151600480548516918616919091179055606080860151600580549095169086161790935580516080810182527f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681527f00000000000000000000000000000000000000000000000000000000000000008516928101929092527f00000000000000000000000000000000000000000000000000000000000000008416828201527f00000000000000000000000000000000000000000000000000000000000000009093169181019190915290517f23a1adf8ad7fad6091a4803227af2cee848c01a7c812404cade7c25636925e3291611bf9918490613596565b60405180910390a150565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600183016020526040812054151561072a565b611c656040518060a0016040528060608152602001606081526020016060815260200160008152602001606081525090565b8460200151600003611ca3576040517f5cf0444900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611cb3858760000151610c31565b905073ffffffffffffffffffffffffffffffffffffffff81161580611d8357506040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527faff2afbf00000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff8216906301ffc9a790602401602060405180830381865afa158015611d5d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d819190612b15565b155b15611dd55785516040517fbf16aab600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610688565b60008173ffffffffffffffffffffffffffffffffffffffff16639a4575b96040518060a001604052808881526020018967ffffffffffffffff1681526020018773ffffffffffffffffffffffffffffffffffffffff1681526020018a6020015181526020018a6000015173ffffffffffffffffffffffffffffffffffffffff168152506040518263ffffffff1660e01b8152600401611e749190613635565b6000604051808303816000875af1158015611e93573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611ed991908101906136ab565b6040805160a0810190915273ffffffffffffffffffffffffffffffffffffffff841660c08201529091508060e0810160405160208183030381529060405281526020018260000151815260200182602001518152602001886020015181526020016040518060200160405280600081525081525092505050949350505050565b60008060001b82846020015185606001518660000151606001518760000151608001518860a001518960c00151604051602001611f9b9695949392919061373c565b604051602081830303815290604052805190602001208560400151805190602001208660e00151604051602001611fd2919061379d565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201206080808c0151805190840120928501989098529183019590955260608201939093529384015260a083015260c082015260e00160405160208183030381529060405280519060200120905092915050565b3373ffffffffffffffffffffffffffffffffffffffff8216036120d8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610688565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60008181526001830160205260408120546121955750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561072d565b50600061072d565b600081815260018301602052604081205480156122865760006121c16001836137b0565b85549091506000906121d5906001906137b0565b905080821461223a5760008660000182815481106121f5576121f5612da8565b906000526020600020015490508087600001848154811061221857612218612da8565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061224b5761224b6137c3565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061072d565b600091505061072d565b5092915050565b60006122f9826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166123ff9092919063ffffffff16565b805190915015610a0157808060200190518101906123179190612b15565b610a01576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610688565b6060816000018054806020026020016040519081016040528092919081815260200182805480156123f357602002820191906000526020600020905b8154815260200190600101908083116123df575b50505050509050919050565b60606116f68484600085856000808673ffffffffffffffffffffffffffffffffffffffff16858760405161243391906137f2565b60006040518083038185875af1925050503d8060008114612470576040519150601f19603f3d011682016040523d82523d6000602084013e612475565b606091505b509150915061248687838387612491565b979650505050505050565b606083156125275782516000036125205773ffffffffffffffffffffffffffffffffffffffff85163b612520576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610688565b50816116f6565b6116f6838381511561253c5781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610688919061281e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff811182821017156125c2576125c2612570565b60405290565b6040516080810167ffffffffffffffff811182821017156125c2576125c2612570565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561263257612632612570565b604052919050565b600067ffffffffffffffff82111561265457612654612570565b5060051b60200190565b67ffffffffffffffff8116811461057757600080fd5b73ffffffffffffffffffffffffffffffffffffffff8116811461057757600080fd5b600060208083850312156126a957600080fd5b823567ffffffffffffffff8111156126c057600080fd5b8301601f810185136126d157600080fd5b80356126e46126df8261263a565b6125eb565b81815260069190911b8201830190838101908783111561270357600080fd5b928401925b8284101561248657604084890312156127215760008081fd5b61272961259f565b84356127348161265e565b81528486013561274381612674565b8187015282526040939093019290840190612708565b6080810161072d828467ffffffffffffffff8151168252602081015173ffffffffffffffffffffffffffffffffffffffff808216602085015280604084015116604085015280606084015116606085015250505050565b60005b838110156127cb5781810151838201526020016127b3565b50506000910152565b600081518084526127ec8160208601602086016127b0565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061072a60208301846127d4565b600060a0828403121561284357600080fd5b50919050565b6000806040838503121561285c57600080fd5b82356128678161265e565b9150602083013567ffffffffffffffff81111561288357600080fd5b61288f85828601612831565b9150509250929050565b600080602083850312156128ac57600080fd5b823567ffffffffffffffff808211156128c457600080fd5b818501915085601f8301126128d857600080fd5b8135818111156128e757600080fd5b8660208260051b85010111156128fc57600080fd5b60209290920196919550909350505050565b6000806040838503121561292157600080fd5b823561292c8161265e565b9150602083013561293c81612674565b809150509250929050565b60006020828403121561295957600080fd5b8135611a1b8161265e565b6080810161072d8284805173ffffffffffffffffffffffffffffffffffffffff908116835260208083015182169084015260408083015182169084015260609182015116910152565b6020808252825182820181905260009190848201906040850190845b818110156129fb57835173ffffffffffffffffffffffffffffffffffffffff16835292840192918401916001016129c9565b50909695505050505050565b8035612a1281612674565b919050565b600060808284031215612a2957600080fd5b612a316125c8565b8235612a3c81612674565b81526020830135612a4c81612674565b60208201526040830135612a5f81612674565b60408201526060830135612a7281612674565b60608201529392505050565b60008060008060808587031215612a9457600080fd5b8435612a9f8161265e565b9350602085013567ffffffffffffffff811115612abb57600080fd5b612ac787828801612831565b935050604085013591506060850135612adf81612674565b939692955090935050565b600060208284031215612afc57600080fd5b8135611a1b81612674565b801515811461057757600080fd5b600060208284031215612b2757600080fd5b8151611a1b81612b07565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112612b6757600080fd5b830160208101925035905067ffffffffffffffff811115612b8757600080fd5b803603821315612b9657600080fd5b9250929050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b8183526000602080850194508260005b85811015612c3b578135612c0981612674565b73ffffffffffffffffffffffffffffffffffffffff168752818301358388015260409687019690910190600101612bf6565b509495945050505050565b600067ffffffffffffffff808516835260406020840152612c678485612b32565b60a06040860152612c7c60e086018284612b9d565b915050612c8c6020860186612b32565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc080878503016060880152612cc2848385612b9d565b9350604088013592507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1883603018312612cfb57600080fd5b60209288019283019235915084821115612d1457600080fd5b8160061b3603831315612d2657600080fd5b80878503016080880152612d3b848385612be6565b9450612d4960608901612a07565b73ffffffffffffffffffffffffffffffffffffffff811660a08901529350612d746080890189612b32565b94509250808786030160c08801525050612486838383612b9d565b600060208284031215612da157600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81833603018112612e0b57600080fd5b9190910192915050565b600082601f830112612e2657600080fd5b81356020612e366126df8361263a565b8083825260208201915060208460051b870101935086841115612e5857600080fd5b602086015b84811015612e7d578035612e7081612674565b8352918301918301612e5d565b509695505050505050565b600060808236031215612e9a57600080fd5b612ea26125c8565b8235612ead8161265e565b81526020830135612ebd81612b07565b6020820152604083013567ffffffffffffffff80821115612edd57600080fd5b612ee936838701612e15565b60408401526060850135915080821115612f0257600080fd5b50612f0f36828601612e15565b60608301525092915050565b60006020808385031215612f2e57600080fd5b825167ffffffffffffffff811115612f4557600080fd5b8301601f81018513612f5657600080fd5b8051612f646126df8261263a565b81815260059190911b82018301908381019087831115612f8357600080fd5b928401925b82841015612486578351612f9b81612674565b82529284019290840190612f88565b600060208284031215612fbc57600080fd5b8151611a1b81612674565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b67ffffffffffffffff81811683821601908082111561229057612290612fc7565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261304c57600080fd5b83018035915067ffffffffffffffff82111561306757600080fd5b602001915036819003821315612b9657600080fd5b67ffffffffffffffff8616815273ffffffffffffffffffffffffffffffffffffffff85166020820152836040820152608060608201526000612486608083018486612b9d565b600082601f8301126130d357600080fd5b815167ffffffffffffffff8111156130ed576130ed612570565b61311e60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016125eb565b81815284602083860101111561313357600080fd5b6116f68260208301602087016127b0565b60008060006060848603121561315957600080fd5b83519250602084015161316b81612b07565b604085015190925067ffffffffffffffff81111561318857600080fd5b613194868287016130c2565b9150509250925092565b600067ffffffffffffffff8083168181036131bb576131bb612fc7565b6001019392505050565b6000602082840312156131d757600080fd5b8151611a1b8161265e565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261321757600080fd5b83018035915067ffffffffffffffff82111561323257600080fd5b6020019150600681901b3603821315612b9657600080fd5b60006040828403121561325c57600080fd5b61326461259f565b823561326f81612674565b81526020928301359281019290925250919050565b600082825180855260208086019550808260051b84010181860160005b84811015613354577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018952815160a081518186526132e5828701826127d4565b91505085820151858203878701526132fd82826127d4565b9150506040808301518683038288015261331783826127d4565b9250505060608083015181870152506080808301519250858203818701525061334081836127d4565b9a86019a94505050908301906001016132a1565b5090979650505050505050565b67ffffffffffffffff851681526060602082015260006133846060830186613284565b8281036040840152612486818587612be6565b600060208083850312156133aa57600080fd5b825167ffffffffffffffff808211156133c257600080fd5b818501915085601f8301126133d657600080fd5b81516133e46126df8261263a565b81815260059190911b8301840190848101908883111561340357600080fd5b8585015b8381101561343b5780518581111561341f5760008081fd5b61342d8b89838a01016130c2565b845250918601918601613407565b5098975050505050505050565b6020815261349960208201835180518252602081015167ffffffffffffffff808216602085015280604084015116604085015280606084015116606085015280608084015116608085015250505050565b600060208301516134c260c084018273ffffffffffffffffffffffffffffffffffffffff169052565b5060408301516101808060e08501526134df6101a08501836127d4565b915060608501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0808685030161010087015261351c84836127d4565b935060808701519150808685030161012087015261353a84836127d4565b935060a0870151915061356661014087018373ffffffffffffffffffffffffffffffffffffffff169052565b60c087015161016087015260e087015191508086850301838701525061358c8382613284565b9695505050505050565b61010081016135ee828567ffffffffffffffff8151168252602081015173ffffffffffffffffffffffffffffffffffffffff808216602085015280604084015116604085015280606084015116606085015250505050565b825173ffffffffffffffffffffffffffffffffffffffff90811660808401526020840151811660a08401526040840151811660c084015260608401511660e0830152611a1b565b602081526000825160a0602084015261365160c08401826127d4565b905067ffffffffffffffff6020850151166040840152604084015173ffffffffffffffffffffffffffffffffffffffff8082166060860152606086015160808601528060808701511660a086015250508091505092915050565b6000602082840312156136bd57600080fd5b815167ffffffffffffffff808211156136d557600080fd5b90830190604082860312156136e957600080fd5b6136f161259f565b82518281111561370057600080fd5b61370c878286016130c2565b82525060208301518281111561372157600080fd5b61372d878286016130c2565b60208301525095945050505050565b600073ffffffffffffffffffffffffffffffffffffffff808916835260c0602084015261376c60c08401896127d4565b67ffffffffffffffff97881660408501529590961660608301525091909316608082015260a0019190915292915050565b60208152600061072a6020830184613284565b8181038181111561072d5761072d612fc7565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b60008251612e0b8184602087016127b056fea164736f6c6343000818000a", } var OnRampABI = OnRampMetaData.ABI @@ -955,8 +955,8 @@ func (_OnRamp *OnRampFilterer) ParseAllowListSendersRemoved(log types.Log) (*OnR return event, nil } -type OnRampCCIPSendRequestedIterator struct { - Event *OnRampCCIPSendRequested +type OnRampCCIPMessageSentIterator struct { + Event *OnRampCCIPMessageSent contract *bind.BoundContract event string @@ -967,7 +967,7 @@ type OnRampCCIPSendRequestedIterator struct { fail error } -func (it *OnRampCCIPSendRequestedIterator) Next() bool { +func (it *OnRampCCIPMessageSentIterator) Next() bool { if it.fail != nil { return false @@ -976,7 +976,7 @@ func (it *OnRampCCIPSendRequestedIterator) Next() bool { if it.done { select { case log := <-it.logs: - it.Event = new(OnRampCCIPSendRequested) + it.Event = new(OnRampCCIPMessageSent) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -991,7 +991,7 @@ func (it *OnRampCCIPSendRequestedIterator) Next() bool { select { case log := <-it.logs: - it.Event = new(OnRampCCIPSendRequested) + it.Event = new(OnRampCCIPMessageSent) if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { it.fail = err return false @@ -1006,43 +1006,43 @@ func (it *OnRampCCIPSendRequestedIterator) Next() bool { } } -func (it *OnRampCCIPSendRequestedIterator) Error() error { +func (it *OnRampCCIPMessageSentIterator) Error() error { return it.fail } -func (it *OnRampCCIPSendRequestedIterator) Close() error { +func (it *OnRampCCIPMessageSentIterator) Close() error { it.sub.Unsubscribe() return nil } -type OnRampCCIPSendRequested struct { +type OnRampCCIPMessageSent struct { DestChainSelector uint64 Message InternalEVM2AnyRampMessage Raw types.Log } -func (_OnRamp *OnRampFilterer) FilterCCIPSendRequested(opts *bind.FilterOpts, destChainSelector []uint64) (*OnRampCCIPSendRequestedIterator, error) { +func (_OnRamp *OnRampFilterer) FilterCCIPMessageSent(opts *bind.FilterOpts, destChainSelector []uint64) (*OnRampCCIPMessageSentIterator, error) { var destChainSelectorRule []interface{} for _, destChainSelectorItem := range destChainSelector { destChainSelectorRule = append(destChainSelectorRule, destChainSelectorItem) } - logs, sub, err := _OnRamp.contract.FilterLogs(opts, "CCIPSendRequested", destChainSelectorRule) + logs, sub, err := _OnRamp.contract.FilterLogs(opts, "CCIPMessageSent", destChainSelectorRule) if err != nil { return nil, err } - return &OnRampCCIPSendRequestedIterator{contract: _OnRamp.contract, event: "CCIPSendRequested", logs: logs, sub: sub}, nil + return &OnRampCCIPMessageSentIterator{contract: _OnRamp.contract, event: "CCIPMessageSent", logs: logs, sub: sub}, nil } -func (_OnRamp *OnRampFilterer) WatchCCIPSendRequested(opts *bind.WatchOpts, sink chan<- *OnRampCCIPSendRequested, destChainSelector []uint64) (event.Subscription, error) { +func (_OnRamp *OnRampFilterer) WatchCCIPMessageSent(opts *bind.WatchOpts, sink chan<- *OnRampCCIPMessageSent, destChainSelector []uint64) (event.Subscription, error) { var destChainSelectorRule []interface{} for _, destChainSelectorItem := range destChainSelector { destChainSelectorRule = append(destChainSelectorRule, destChainSelectorItem) } - logs, sub, err := _OnRamp.contract.WatchLogs(opts, "CCIPSendRequested", destChainSelectorRule) + logs, sub, err := _OnRamp.contract.WatchLogs(opts, "CCIPMessageSent", destChainSelectorRule) if err != nil { return nil, err } @@ -1052,8 +1052,8 @@ func (_OnRamp *OnRampFilterer) WatchCCIPSendRequested(opts *bind.WatchOpts, sink select { case log := <-logs: - event := new(OnRampCCIPSendRequested) - if err := _OnRamp.contract.UnpackLog(event, "CCIPSendRequested", log); err != nil { + event := new(OnRampCCIPMessageSent) + if err := _OnRamp.contract.UnpackLog(event, "CCIPMessageSent", log); err != nil { return err } event.Raw = log @@ -1074,9 +1074,9 @@ func (_OnRamp *OnRampFilterer) WatchCCIPSendRequested(opts *bind.WatchOpts, sink }), nil } -func (_OnRamp *OnRampFilterer) ParseCCIPSendRequested(log types.Log) (*OnRampCCIPSendRequested, error) { - event := new(OnRampCCIPSendRequested) - if err := _OnRamp.contract.UnpackLog(event, "CCIPSendRequested", log); err != nil { +func (_OnRamp *OnRampFilterer) ParseCCIPMessageSent(log types.Log) (*OnRampCCIPMessageSent, error) { + event := new(OnRampCCIPMessageSent) + if err := _OnRamp.contract.UnpackLog(event, "CCIPMessageSent", log); err != nil { return nil, err } event.Raw = log @@ -1882,8 +1882,8 @@ func (_OnRamp *OnRamp) ParseLog(log types.Log) (generated.AbigenLog, error) { return _OnRamp.ParseAllowListSendersAdded(log) case _OnRamp.abi.Events["AllowListSendersRemoved"].ID: return _OnRamp.ParseAllowListSendersRemoved(log) - case _OnRamp.abi.Events["CCIPSendRequested"].ID: - return _OnRamp.ParseCCIPSendRequested(log) + case _OnRamp.abi.Events["CCIPMessageSent"].ID: + return _OnRamp.ParseCCIPMessageSent(log) case _OnRamp.abi.Events["ConfigSet"].ID: return _OnRamp.ParseConfigSet(log) case _OnRamp.abi.Events["DestChainConfigSet"].ID: @@ -1914,8 +1914,8 @@ func (OnRampAllowListSendersRemoved) Topic() common.Hash { return common.HexToHash("0xc237ec1921f855ccd5e9a5af9733f2d58943a5a8501ec5988e305d7a4d421586") } -func (OnRampCCIPSendRequested) Topic() common.Hash { - return common.HexToHash("0xcae3d9f68a9ed33d0a770e9bcc6fc25d4041dd6391e6cd8015546547a3c93140") +func (OnRampCCIPMessageSent) Topic() common.Hash { + return common.HexToHash("0xf6e86ef8896c7a0d629406168f396e883280680c99e649b9e2d36466fbc9f9e5") } func (OnRampConfigSet) Topic() common.Hash { @@ -2003,11 +2003,11 @@ type OnRampInterface interface { ParseAllowListSendersRemoved(log types.Log) (*OnRampAllowListSendersRemoved, error) - FilterCCIPSendRequested(opts *bind.FilterOpts, destChainSelector []uint64) (*OnRampCCIPSendRequestedIterator, error) + FilterCCIPMessageSent(opts *bind.FilterOpts, destChainSelector []uint64) (*OnRampCCIPMessageSentIterator, error) - WatchCCIPSendRequested(opts *bind.WatchOpts, sink chan<- *OnRampCCIPSendRequested, destChainSelector []uint64) (event.Subscription, error) + WatchCCIPMessageSent(opts *bind.WatchOpts, sink chan<- *OnRampCCIPMessageSent, destChainSelector []uint64) (event.Subscription, error) - ParseCCIPSendRequested(log types.Log) (*OnRampCCIPSendRequested, error) + ParseCCIPMessageSent(log types.Log) (*OnRampCCIPMessageSent, error) FilterConfigSet(opts *bind.FilterOpts) (*OnRampConfigSetIterator, error) diff --git a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt index fa4edfd3dd..d0be78aeaa 100644 --- a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -24,7 +24,7 @@ multi_ocr3_helper: ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Help nonce_manager: ../../../contracts/solc/v0.8.24/NonceManager/NonceManager.abi ../../../contracts/solc/v0.8.24/NonceManager/NonceManager.bin 6f64e1083b356c06ee66b9138e398b9c97a4cd3e8c9ec38cf3010cebc79af536 ocr3_config_encoder: ../../../contracts/solc/v0.8.24/IOCR3ConfigEncoder/IOCR3ConfigEncoder.abi ../../../contracts/solc/v0.8.24/IOCR3ConfigEncoder/IOCR3ConfigEncoder.bin e21180898e1ad54a045ee20add85a2793c681425ea06f66d1a9e5cab128b6487 offramp: ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.abi ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.bin 263df151d037af19cc412a051efb82993b0ccdde0184c598e3669f1326ab4ce9 -onramp: ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.abi ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.bin 93ad9efaf8789baf7133a5db803b20d05b4771bf25f57a438cb7e5a8111fb472 +onramp: ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.abi ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.bin c3b345930e1a553b18553e18a5c0ff8df3c372118fdf78a176aaccb1891664bb ping_pong_demo: ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.abi ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.bin c1c2f8a65c7ffd971899cae7fe62f2da57d09e936151e2b92163c4bebe699d6b price_registry: ../../../contracts/solc/v0.8.24/PriceRegistry/PriceRegistry.abi ../../../contracts/solc/v0.8.24/PriceRegistry/PriceRegistry.bin e7781d600c1bb7aa4620106af7f6e146a109b97f4cb6a7d06c9e15773340ecb2 registry_module_owner_custom: ../../../contracts/solc/v0.8.24/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.abi ../../../contracts/solc/v0.8.24/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.bin 75be86323c227917a9bbc3f799d7ed02f92db546653a36db30ed0ebe64461353 From 17ce920e09c9f0d64aa1545cfbed737af1b5358b Mon Sep 17 00:00:00 2001 From: Ryan <80392855+RayXpub@users.noreply.github.com> Date: Wed, 4 Sep 2024 16:06:51 +0400 Subject: [PATCH 070/115] Skip report execution on curse (#1408) ## Motivation The goal of this PR is to remove reverts on lane cursing for DON execution transactions. If a lane is cursed, reverting will cause the whole execution transaction to fail so any execution reports for other lanes will be blocked. ## Solution For DON execution transactions the behavior is now to skip the report and emit a `SkippedReportExecution`. For manual execution we still revert, otherwise the transaction will silently fail for the users. --------- Co-authored-by: app-token-issuer-infra-releng[bot] <120227048+app-token-issuer-infra-releng[bot]@users.noreply.github.com> --- contracts/gas-snapshots/ccip.gas-snapshot | 194 ++++++++--------- contracts/src/v0.8/ccip/offRamp/OffRamp.sol | 26 ++- .../src/v0.8/ccip/test/offRamp/OffRamp.t.sol | 198 +++++++++++++++--- .../v0.8/ccip/test/offRamp/OffRampSetup.t.sol | 40 +++- .../ccip/generated/offramp/offramp.go | 133 +++++++++++- ...rapper-dependency-versions-do-not-edit.txt | 2 +- 6 files changed, 448 insertions(+), 145 deletions(-) diff --git a/contracts/gas-snapshots/ccip.gas-snapshot b/contracts/gas-snapshots/ccip.gas-snapshot index 6153b0a079..bf3f7a9f72 100644 --- a/contracts/gas-snapshots/ccip.gas-snapshot +++ b/contracts/gas-snapshots/ccip.gas-snapshot @@ -566,18 +566,18 @@ MultiOCR3Base_transmit:test_UnauthorizedSigner_Revert() (gas: 61133) MultiOCR3Base_transmit:test_UnconfiguredPlugin_Revert() (gas: 39890) MultiOCR3Base_transmit:test_ZeroSignatures_Revert() (gas: 32973) MultiOnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 413542) -MultiRampsE2E:test_E2E_3MessagesMMultiOffRampSuccess_gas() (gas: 1499109) +MultiRampsE2E:test_E2E_3MessagesMMultiOffRampSuccess_gas() (gas: 1499013) NonceManager_NonceIncrementation:test_getIncrementedOutboundNonce_Success() (gas: 37907) NonceManager_NonceIncrementation:test_incrementInboundNonce_Skip() (gas: 23694) NonceManager_NonceIncrementation:test_incrementInboundNonce_Success() (gas: 38763) NonceManager_NonceIncrementation:test_incrementNoncesInboundAndOutbound_Success() (gas: 71847) -NonceManager_OffRampUpgrade:test_NoPrevOffRampForChain_Success() (gas: 260262) -NonceManager_OffRampUpgrade:test_UpgradedNonceNewSenderStartsAtZero_Success() (gas: 262359) -NonceManager_OffRampUpgrade:test_UpgradedNonceStartsAtV1Nonce_Success() (gas: 326051) -NonceManager_OffRampUpgrade:test_UpgradedOffRampNonceSkipsIfMsgInFlight_Success() (gas: 298263) -NonceManager_OffRampUpgrade:test_UpgradedSenderNoncesReadsPreviousRampTransitive_Success() (gas: 244814) -NonceManager_OffRampUpgrade:test_UpgradedSenderNoncesReadsPreviousRamp_Success() (gas: 233069) -NonceManager_OffRampUpgrade:test_Upgraded_Success() (gas: 153186) +NonceManager_OffRampUpgrade:test_NoPrevOffRampForChain_Success() (gas: 260206) +NonceManager_OffRampUpgrade:test_UpgradedNonceNewSenderStartsAtZero_Success() (gas: 262348) +NonceManager_OffRampUpgrade:test_UpgradedNonceStartsAtV1Nonce_Success() (gas: 325972) +NonceManager_OffRampUpgrade:test_UpgradedOffRampNonceSkipsIfMsgInFlight_Success() (gas: 298151) +NonceManager_OffRampUpgrade:test_UpgradedSenderNoncesReadsPreviousRampTransitive_Success() (gas: 244682) +NonceManager_OffRampUpgrade:test_UpgradedSenderNoncesReadsPreviousRamp_Success() (gas: 232980) +NonceManager_OffRampUpgrade:test_Upgraded_Success() (gas: 153163) NonceManager_OnRampUpgrade:test_UpgradeNonceNewSenderStartsAtZero_Success() (gas: 168317) NonceManager_OnRampUpgrade:test_UpgradeNonceStartsAtV1Nonce_Success() (gas: 220108) NonceManager_OnRampUpgrade:test_UpgradeSenderNoncesReadsPreviousRamp_Success() (gas: 125070) @@ -614,118 +614,120 @@ OCR2Base_transmit:test_Transmit2SignersSuccess_gas() (gas: 51674) OCR2Base_transmit:test_UnAuthorizedTransmitter_Revert() (gas: 23484) OCR2Base_transmit:test_UnauthorizedSigner_Revert() (gas: 39665) OCR2Base_transmit:test_WrongNumberOfSignatures_Revert() (gas: 20557) -OffRamp__releaseOrMintSingleToken:test__releaseOrMintSingleToken_NotACompatiblePool_Revert() (gas: 40149) -OffRamp__releaseOrMintSingleToken:test__releaseOrMintSingleToken_Success() (gas: 107130) +OffRamp__releaseOrMintSingleToken:test__releaseOrMintSingleToken_NotACompatiblePool_Revert() (gas: 40127) +OffRamp__releaseOrMintSingleToken:test__releaseOrMintSingleToken_Success() (gas: 107108) OffRamp__releaseOrMintSingleToken:test__releaseOrMintSingleToken_TokenHandlingError_transfer_Revert() (gas: 88331) OffRamp__releaseOrMintSingleToken:test_releaseOrMintToken_InvalidDataLength_Revert() (gas: 39848) -OffRamp__releaseOrMintSingleToken:test_releaseOrMintToken_ReleaseOrMintBalanceMismatch_Revert() (gas: 97399) +OffRamp__releaseOrMintSingleToken:test_releaseOrMintToken_ReleaseOrMintBalanceMismatch_Revert() (gas: 97377) OffRamp__releaseOrMintSingleToken:test_releaseOrMintToken_TokenHandlingError_BalanceOf_Revert() (gas: 42843) OffRamp__releaseOrMintSingleToken:test_releaseOrMintToken_skip_ReleaseOrMintBalanceMismatch_if_pool_Revert() (gas: 89579) OffRamp_applySourceChainConfigUpdates:test_AddMultipleChains_Success() (gas: 467917) -OffRamp_applySourceChainConfigUpdates:test_AddNewChain_Success() (gas: 99183) +OffRamp_applySourceChainConfigUpdates:test_AddNewChain_Success() (gas: 99161) OffRamp_applySourceChainConfigUpdates:test_ApplyZeroUpdates_Success() (gas: 12395) OffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChainOnRamp_Revert() (gas: 93181) -OffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChain_Success() (gas: 109824) +OffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChain_Success() (gas: 109869) OffRamp_applySourceChainConfigUpdates:test_RouterAddress_Revert() (gas: 13263) OffRamp_applySourceChainConfigUpdates:test_ZeroOnRampAddress_Revert() (gas: 17988) -OffRamp_applySourceChainConfigUpdates:test_ZeroSourceChainSelector_Revert() (gas: 15300) -OffRamp_batchExecute:test_MultipleReportsDifferentChains_Success() (gas: 321369) -OffRamp_batchExecute:test_MultipleReportsSameChain_Success() (gas: 262704) -OffRamp_batchExecute:test_MultipleReportsSkipDuplicate_Success() (gas: 169162) -OffRamp_batchExecute:test_OutOfBoundsGasLimitsAccess_Revert() (gas: 187787) -OffRamp_batchExecute:test_SingleReport_Success() (gas: 156230) -OffRamp_batchExecute:test_Unhealthy_Revert() (gas: 533030) -OffRamp_batchExecute:test_ZeroReports_Revert() (gas: 10461) +OffRamp_applySourceChainConfigUpdates:test_ZeroSourceChainSelector_Revert() (gas: 15343) +OffRamp_batchExecute:test_MultipleReportsDifferentChainsSkipCursedChain_Success() (gas: 202302) +OffRamp_batchExecute:test_MultipleReportsDifferentChains_Success() (gas: 335775) +OffRamp_batchExecute:test_MultipleReportsSameChain_Success() (gas: 277143) +OffRamp_batchExecute:test_MultipleReportsSkipDuplicate_Success() (gas: 169155) +OffRamp_batchExecute:test_OutOfBoundsGasLimitsAccess_Revert() (gas: 187792) +OffRamp_batchExecute:test_SingleReport_Success() (gas: 156254) +OffRamp_batchExecute:test_Unhealthy_Success() (gas: 573431) +OffRamp_batchExecute:test_ZeroReports_Revert() (gas: 10421) OffRamp_ccipReceive:test_Reverts() (gas: 15773) -OffRamp_commit:test_InvalidIntervalMinLargerThanMax_Revert() (gas: 67458) -OffRamp_commit:test_InvalidInterval_Revert() (gas: 59778) -OffRamp_commit:test_InvalidRootRevert() (gas: 58858) -OffRamp_commit:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6534892) -OffRamp_commit:test_NoConfig_Revert() (gas: 6118635) +OffRamp_commit:test_InvalidIntervalMinLargerThanMax_Revert() (gas: 67433) +OffRamp_commit:test_InvalidInterval_Revert() (gas: 59753) +OffRamp_commit:test_InvalidRootRevert() (gas: 58833) +OffRamp_commit:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6597673) +OffRamp_commit:test_NoConfig_Revert() (gas: 6181416) OffRamp_commit:test_OnlyGasPriceUpdates_Success() (gas: 105929) OffRamp_commit:test_OnlyPriceUpdateStaleReport_Revert() (gas: 115981) OffRamp_commit:test_OnlyTokenPriceUpdates_Success() (gas: 105950) OffRamp_commit:test_PriceSequenceNumberCleared_Success() (gas: 349049) -OffRamp_commit:test_ReportAndPriceUpdate_Success() (gas: 158960) -OffRamp_commit:test_ReportOnlyRootSuccess_gas() (gas: 136092) -OffRamp_commit:test_RootAlreadyCommitted_Revert() (gas: 136492) -OffRamp_commit:test_SourceChainNotEnabled_Revert() (gas: 59126) -OffRamp_commit:test_StaleReportWithRoot_Success() (gas: 224806) -OffRamp_commit:test_UnauthorizedTransmitter_Revert() (gas: 117632) -OffRamp_commit:test_Unhealthy_Revert() (gas: 77674) -OffRamp_commit:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 204296) -OffRamp_commit:test_WrongConfigWithoutSigners_Revert() (gas: 6529281) +OffRamp_commit:test_ReportAndPriceUpdate_Success() (gas: 159000) +OffRamp_commit:test_ReportOnlyRootSuccess_gas() (gas: 136067) +OffRamp_commit:test_RootAlreadyCommitted_Revert() (gas: 136442) +OffRamp_commit:test_SourceChainNotEnabled_Revert() (gas: 59101) +OffRamp_commit:test_StaleReportWithRoot_Success() (gas: 224756) +OffRamp_commit:test_UnauthorizedTransmitter_Revert() (gas: 117607) +OffRamp_commit:test_Unhealthy_Revert() (gas: 77660) +OffRamp_commit:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 204271) +OffRamp_commit:test_WrongConfigWithoutSigners_Revert() (gas: 6592062) OffRamp_commit:test_ZeroEpochAndRound_Revert() (gas: 47832) -OffRamp_constructor:test_Constructor_Success() (gas: 6121934) -OffRamp_constructor:test_SourceChainSelector_Revert() (gas: 137089) -OffRamp_constructor:test_ZeroChainSelector_Revert() (gas: 103806) -OffRamp_constructor:test_ZeroNonceManager_Revert() (gas: 101677) -OffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 139641) -OffRamp_constructor:test_ZeroRMNProxy_Revert() (gas: 101554) -OffRamp_constructor:test_ZeroTokenAdminRegistry_Revert() (gas: 101621) -OffRamp_execute:test_IncorrectArrayType_Revert() (gas: 17305) -OffRamp_execute:test_LargeBatch_Success() (gas: 1812704) -OffRamp_execute:test_MultipleReportsWithPartialValidationFailures_Success() (gas: 357260) -OffRamp_execute:test_MultipleReports_Success() (gas: 284815) -OffRamp_execute:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6586004) -OffRamp_execute:test_NoConfig_Revert() (gas: 6169487) -OffRamp_execute:test_NonArray_Revert() (gas: 27809) -OffRamp_execute:test_SingleReport_Success() (gas: 175620) -OffRamp_execute:test_UnauthorizedTransmitter_Revert() (gas: 147848) -OffRamp_execute:test_WrongConfigWithSigners_Revert() (gas: 6947505) +OffRamp_constructor:test_Constructor_Success() (gas: 6184742) +OffRamp_constructor:test_SourceChainSelector_Revert() (gas: 137165) +OffRamp_constructor:test_ZeroChainSelector_Revert() (gas: 103904) +OffRamp_constructor:test_ZeroNonceManager_Revert() (gas: 101775) +OffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 139740) +OffRamp_constructor:test_ZeroRMNProxy_Revert() (gas: 101652) +OffRamp_constructor:test_ZeroTokenAdminRegistry_Revert() (gas: 101719) +OffRamp_execute:test_IncorrectArrayType_Revert() (gas: 17350) +OffRamp_execute:test_LargeBatch_Success() (gas: 3384707) +OffRamp_execute:test_MultipleReportsWithPartialValidationFailures_Success() (gas: 373627) +OffRamp_execute:test_MultipleReports_Success() (gas: 299546) +OffRamp_execute:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6648787) +OffRamp_execute:test_NoConfig_Revert() (gas: 6232270) +OffRamp_execute:test_NonArray_Revert() (gas: 27787) +OffRamp_execute:test_SingleReport_Success() (gas: 175597) +OffRamp_execute:test_UnauthorizedTransmitter_Revert() (gas: 147825) +OffRamp_execute:test_WrongConfigWithSigners_Revert() (gas: 7010288) OffRamp_execute:test_ZeroReports_Revert() (gas: 17225) OffRamp_executeSingleMessage:test_MessageSender_Revert() (gas: 18257) OffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 249037) -OffRamp_executeSingleMessage:test_NonContract_Success() (gas: 20517) +OffRamp_executeSingleMessage:test_NonContract_Success() (gas: 20539) OffRamp_executeSingleMessage:test_TokenHandlingError_Revert() (gas: 210176) OffRamp_executeSingleMessage:test_ZeroGasDONExecution_Revert() (gas: 48779) -OffRamp_executeSingleMessage:test_executeSingleMessage_NoTokens_Success() (gas: 48302) +OffRamp_executeSingleMessage:test_executeSingleMessage_NoTokens_Success() (gas: 48257) OffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidationNoRouterCall_Revert() (gas: 229565) OffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidation_Revert() (gas: 86203) OffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens_Success() (gas: 280859) OffRamp_executeSingleMessage:test_executeSingleMessage_WithValidation_Success() (gas: 92437) -OffRamp_executeSingleReport:test_DisabledSourceChain_Revert() (gas: 35104) -OffRamp_executeSingleReport:test_EmptyReport_Revert() (gas: 28724) -OffRamp_executeSingleReport:test_InvalidSourcePoolAddress_Success() (gas: 491530) -OffRamp_executeSingleReport:test_ManualExecutionNotYetEnabled_Revert() (gas: 54457) -OffRamp_executeSingleReport:test_MismatchingDestChainSelector_Revert() (gas: 40728) -OffRamp_executeSingleReport:test_MismatchingOnRampRoot_Revert() (gas: 154111) -OffRamp_executeSingleReport:test_NonExistingSourceChain_Revert() (gas: 35338) -OffRamp_executeSingleReport:test_ReceiverError_Success() (gas: 187911) -OffRamp_executeSingleReport:test_RetryFailedMessageWithoutManualExecution_Revert() (gas: 199215) -OffRamp_executeSingleReport:test_RootNotCommitted_Revert() (gas: 48096) -OffRamp_executeSingleReport:test_RouterYULCall_Revert() (gas: 447759) -OffRamp_executeSingleReport:test_SingleMessageNoTokensOtherChain_Success() (gas: 251078) -OffRamp_executeSingleReport:test_SingleMessageNoTokensUnordered_Success() (gas: 193345) -OffRamp_executeSingleReport:test_SingleMessageNoTokens_Success() (gas: 212938) -OffRamp_executeSingleReport:test_SingleMessageToNonCCIPReceiver_Success() (gas: 266576) -OffRamp_executeSingleReport:test_SingleMessagesNoTokensSuccess_gas() (gas: 141191) -OffRamp_executeSingleReport:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 422575) -OffRamp_executeSingleReport:test_SkippedIncorrectNonce_Success() (gas: 65877) -OffRamp_executeSingleReport:test_TokenDataMismatch_Revert() (gas: 80932) -OffRamp_executeSingleReport:test_TwoMessagesWithTokensAndGE_Success() (gas: 586607) -OffRamp_executeSingleReport:test_TwoMessagesWithTokensSuccess_gas() (gas: 534417) -OffRamp_executeSingleReport:test_UnexpectedTokenData_Revert() (gas: 40544) -OffRamp_executeSingleReport:test_UnhealthySingleChainCurse_Revert() (gas: 531671) -OffRamp_executeSingleReport:test_Unhealthy_Revert() (gas: 528995) -OffRamp_executeSingleReport:test_WithCurseOnAnotherSourceChain_Success() (gas: 494237) -OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessageUnordered_Success() (gas: 136580) -OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessage_Success() (gas: 165799) +OffRamp_executeSingleReport:test_DisabledSourceChain_Revert() (gas: 35087) +OffRamp_executeSingleReport:test_EmptyReport_Revert() (gas: 28713) +OffRamp_executeSingleReport:test_InvalidSourcePoolAddress_Success() (gas: 491507) +OffRamp_executeSingleReport:test_ManualExecutionNotYetEnabled_Revert() (gas: 54434) +OffRamp_executeSingleReport:test_MismatchingDestChainSelector_Revert() (gas: 40717) +OffRamp_executeSingleReport:test_MismatchingOnRampRoot_Revert() (gas: 154069) +OffRamp_executeSingleReport:test_NonExistingSourceChain_Revert() (gas: 35321) +OffRamp_executeSingleReport:test_ReceiverError_Success() (gas: 187888) +OffRamp_executeSingleReport:test_RetryFailedMessageWithoutManualExecution_Revert() (gas: 199169) +OffRamp_executeSingleReport:test_RootNotCommitted_Revert() (gas: 48085) +OffRamp_executeSingleReport:test_RouterYULCall_Revert() (gas: 447736) +OffRamp_executeSingleReport:test_SingleMessageNoTokensOtherChain_Success() (gas: 251032) +OffRamp_executeSingleReport:test_SingleMessageNoTokensUnordered_Success() (gas: 193299) +OffRamp_executeSingleReport:test_SingleMessageNoTokens_Success() (gas: 212892) +OffRamp_executeSingleReport:test_SingleMessageToNonCCIPReceiver_Success() (gas: 266553) +OffRamp_executeSingleReport:test_SingleMessagesNoTokensSuccess_gas() (gas: 141168) +OffRamp_executeSingleReport:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 422552) +OffRamp_executeSingleReport:test_SkippedIncorrectNonce_Success() (gas: 65854) +OffRamp_executeSingleReport:test_TokenDataMismatch_Revert() (gas: 80909) +OffRamp_executeSingleReport:test_TwoMessagesWithTokensAndGE_Success() (gas: 594246) +OffRamp_executeSingleReport:test_TwoMessagesWithTokensSuccess_gas() (gas: 542093) +OffRamp_executeSingleReport:test_UnexpectedTokenData_Revert() (gas: 40533) +OffRamp_executeSingleReport:test_UnhealthySingleChainCurse_Revert() (gas: 569984) +OffRamp_executeSingleReport:test_Unhealthy_Success() (gas: 569363) +OffRamp_executeSingleReport:test_WithCurseOnAnotherSourceChain_Success() (gas: 494202) +OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessageUnordered_Success() (gas: 136534) +OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessage_Success() (gas: 165753) OffRamp_getExecutionState:test_FillExecutionState_Success() (gas: 3742124) OffRamp_getExecutionState:test_GetDifferentChainExecutionState_Success() (gas: 118836) OffRamp_getExecutionState:test_GetExecutionState_Success() (gas: 88048) OffRamp_manuallyExecute:test_ManualExecGasLimitMismatchSingleReport_Revert() (gas: 75551) OffRamp_manuallyExecute:test_ManualExecInvalidGasLimit_Revert() (gas: 26439) -OffRamp_manuallyExecute:test_manuallyExecute_DoesNotRevertIfUntouched_Success() (gas: 171639) -OffRamp_manuallyExecute:test_manuallyExecute_FailedTx_Revert() (gas: 205796) +OffRamp_manuallyExecute:test_manuallyExecute_DoesNotRevertIfUntouched_Success() (gas: 171604) +OffRamp_manuallyExecute:test_manuallyExecute_FailedTx_Revert() (gas: 205795) OffRamp_manuallyExecute:test_manuallyExecute_ForkedChain_Revert() (gas: 25993) -OffRamp_manuallyExecute:test_manuallyExecute_GasLimitMismatchMultipleReports_Revert() (gas: 152822) -OffRamp_manuallyExecute:test_manuallyExecute_LowGasLimit_Success() (gas: 524603) -OffRamp_manuallyExecute:test_manuallyExecute_ReentrancyFails_Success() (gas: 2388943) -OffRamp_manuallyExecute:test_manuallyExecute_Success() (gas: 208553) -OffRamp_manuallyExecute:test_manuallyExecute_WithGasOverride_Success() (gas: 219343) -OffRamp_manuallyExecute:test_manuallyExecute_WithMultiReportGasOverride_Success() (gas: 658822) -OffRamp_manuallyExecute:test_manuallyExecute_WithPartialMessages_Success() (gas: 328543) +OffRamp_manuallyExecute:test_manuallyExecute_GasLimitMismatchMultipleReports_Revert() (gas: 152834) +OffRamp_manuallyExecute:test_manuallyExecute_LowGasLimit_Success() (gas: 524524) +OffRamp_manuallyExecute:test_manuallyExecute_MultipleReportsWithSingleCursedLane_Revert() (gas: 322692) +OffRamp_manuallyExecute:test_manuallyExecute_ReentrancyFails_Success() (gas: 2388897) +OffRamp_manuallyExecute:test_manuallyExecute_Success() (gas: 218722) +OffRamp_manuallyExecute:test_manuallyExecute_WithGasOverride_Success() (gas: 219297) +OffRamp_manuallyExecute:test_manuallyExecute_WithMultiReportGasOverride_Success() (gas: 740091) +OffRamp_manuallyExecute:test_manuallyExecute_WithPartialMessages_Success() (gas: 344193) OffRamp_releaseOrMintTokens:test_TokenHandlingError_Reverts() (gas: 165822) OffRamp_releaseOrMintTokens:test__releaseOrMintTokens_PoolIsNotAPool_Reverts() (gas: 24603) OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_InvalidDataLengthReturnData_Revert() (gas: 66285) @@ -733,19 +735,19 @@ OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_InvalidEVMAddress_Revert() OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_PoolDoesNotSupportDest_Reverts() (gas: 83291) OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_Success() (gas: 177934) OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals_Success() (gas: 191136) -OffRamp_resetUnblessedRoots:test_OnlyOwner_Revert() (gas: 11423) -OffRamp_resetUnblessedRoots:test_ResetUnblessedRoots_Success() (gas: 215009) +OffRamp_resetUnblessedRoots:test_OnlyOwner_Revert() (gas: 11379) +OffRamp_resetUnblessedRoots:test_ResetUnblessedRoots_Success() (gas: 214934) OffRamp_setDynamicConfig:test_FeeQuoterZeroAddress_Revert() (gas: 11585) OffRamp_setDynamicConfig:test_NonOwner_Revert() (gas: 14152) OffRamp_setDynamicConfig:test_SetDynamicConfigWithValidator_Success() (gas: 49115) -OffRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 27037) +OffRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 27060) OffRamp_trialExecute:test_RateLimitError_Success() (gas: 225795) OffRamp_trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 234416) OffRamp_trialExecute:test_TokenPoolIsNotAContract_Success() (gas: 309206) OffRamp_trialExecute:test_trialExecute_Success() (gas: 283994) -OffRamp_verify:test_Blessed_Success() (gas: 176276) -OffRamp_verify:test_NotBlessedWrongChainSelector_Success() (gas: 178366) -OffRamp_verify:test_NotBlessed_Success() (gas: 141205) +OffRamp_verify:test_Blessed_Success() (gas: 176251) +OffRamp_verify:test_NotBlessedWrongChainSelector_Success() (gas: 178341) +OffRamp_verify:test_NotBlessed_Success() (gas: 141180) OffRamp_verify:test_TooManyLeaves_Revert() (gas: 51510) OnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 390336) OnRamp_allowListConfigUpdates:test_applyAllowList_Revert() (gas: 66509) diff --git a/contracts/src/v0.8/ccip/offRamp/OffRamp.sol b/contracts/src/v0.8/ccip/offRamp/OffRamp.sol index 3c709a88f6..d15881a229 100644 --- a/contracts/src/v0.8/ccip/offRamp/OffRamp.sol +++ b/contracts/src/v0.8/ccip/offRamp/OffRamp.sol @@ -79,6 +79,7 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { /// @dev RMN depends on this event, if changing, please notify the RMN maintainers. event CommitReportAccepted(CommitReport report); event RootRemoved(bytes32 root); + event SkippedReportExecution(uint64 sourceChainSelector); /// @notice Struct that contains the static configuration /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers. @@ -342,7 +343,16 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { uint256[] memory manualExecGasLimits ) internal { uint64 sourceChainSelector = report.sourceChainSelector; - _whenNotCursed(sourceChainSelector); + bool manualExecution = manualExecGasLimits.length != 0; + if (IRMN(i_rmnProxy).isCursed(bytes16(uint128(sourceChainSelector)))) { + if (manualExecution) { + // For manual execution we don't want to silently fail so we revert + revert CursedByRMN(sourceChainSelector); + } + // For DON execution we do not revert as a single lane curse can revert the entire batch + emit SkippedReportExecution(sourceChainSelector); + return; + } bytes memory onRamp = _getEnabledSourceChainConfig(sourceChainSelector).onRamp; @@ -374,7 +384,6 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { if (timestampCommitted == 0) revert RootNotCommitted(sourceChainSelector); // Execute messages - bool manualExecution = manualExecGasLimits.length != 0; for (uint256 i = 0; i < numMsgs; ++i) { uint256 gasStart = gasleft(); Internal.Any2EVMRampMessage memory message = report.messages[i]; @@ -607,7 +616,10 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { MerkleRoot memory root = commitReport.merkleRoots[i]; uint64 sourceChainSelector = root.sourceChainSelector; - _whenNotCursed(sourceChainSelector); + if (IRMN(i_rmnProxy).isCursed(bytes16(uint128(sourceChainSelector)))) { + revert CursedByRMN(sourceChainSelector); + } + SourceChainConfig storage sourceChainConfig = _getEnabledSourceChainConfig(sourceChainSelector); if (sourceChainConfig.minSeqNr != root.interval.min || root.interval.min > root.interval.max) { @@ -959,12 +971,4 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { // solhint-disable-next-line revert(); } - - /// @notice Validates that the source chain -> this chain lane, and reverts if it is cursed - /// @param sourceChainSelector Source chain selector to check for cursing - function _whenNotCursed(uint64 sourceChainSelector) internal view { - if (IRMN(i_rmnProxy).isCursed(bytes16(uint128(sourceChainSelector)))) { - revert CursedByRMN(sourceChainSelector); - } - } } diff --git a/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol index ec8ac65008..1a0b67891d 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol @@ -604,7 +604,11 @@ contract OffRamp_executeSingleReport is OffRampSetup { vm.resumeGasMetering(); vm.recordLogs(); s_offRamp.executeSingleReport(report, new uint256[](0)); + + Vm.Log[] memory logs = vm.getRecordedLogs(); + assertExecutionStateChangedEventLogs( + logs, SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber, messages[0].header.messageId, @@ -614,6 +618,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { ); assertExecutionStateChangedEventLogs( + logs, SOURCE_CHAIN_SELECTOR_1, messages[1].header.sequenceNumber, messages[1].header.messageId, @@ -636,7 +641,11 @@ contract OffRamp_executeSingleReport is OffRampSetup { s_offRamp.executeSingleReport( _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), _getGasLimitsFromMessages(messages) ); + + Vm.Log[] memory logs = vm.getRecordedLogs(); + assertExecutionStateChangedEventLogs( + logs, SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber, messages[0].header.messageId, @@ -645,6 +654,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { "" ); assertExecutionStateChangedEventLogs( + logs, SOURCE_CHAIN_SELECTOR_1, messages[1].header.sequenceNumber, messages[1].header.messageId, @@ -679,6 +689,9 @@ contract OffRamp_executeSingleReport is OffRampSetup { s_offRamp.executeSingleReport( _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), _getGasLimitsFromMessages(messages) ); + + Vm.Log[] memory logs = vm.getRecordedLogs(); + // all executions should succeed. for (uint256 i = 0; i < orderings.length; ++i) { assertEq( @@ -687,6 +700,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { ); assertExecutionStateChangedEventLogs( + logs, SOURCE_CHAIN_SELECTOR_1, messages[i].header.sequenceNumber, messages[i].header.messageId, @@ -736,6 +750,29 @@ contract OffRamp_executeSingleReport is OffRampSetup { ); } + function test_Unhealthy_Success() public { + s_mockRMN.setGlobalCursed(true); + vm.expectEmit(); + emit OffRamp.SkippedReportExecution(SOURCE_CHAIN_SELECTOR_1); + s_offRamp.executeSingleReport( + _generateReportFromMessages( + SOURCE_CHAIN_SELECTOR_1, _generateMessagesWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1) + ), + new uint256[](0) + ); + + s_mockRMN.setGlobalCursed(false); + vm.recordLogs(); + s_offRamp.executeSingleReport( + _generateReportFromMessages( + SOURCE_CHAIN_SELECTOR_1, _generateMessagesWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1) + ), + new uint256[](0) + ); + + _assertNoEmit(OffRamp.SkippedReportExecution.selector); + } + // Reverts function test_MismatchingDestChainSelector_Revert() public { @@ -770,34 +807,17 @@ contract OffRamp_executeSingleReport is OffRampSetup { s_offRamp.executeSingleReport(executionReport, new uint256[](0)); } - function test_Unhealthy_Revert() public { - s_mockRMN.setGlobalCursed(true); - vm.expectRevert(abi.encodeWithSelector(OffRamp.CursedByRMN.selector, SOURCE_CHAIN_SELECTOR_1)); - s_offRamp.executeSingleReport( - _generateReportFromMessages( - SOURCE_CHAIN_SELECTOR_1, _generateMessagesWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1) - ), - new uint256[](0) - ); - // Uncurse should succeed - s_mockRMN.setGlobalCursed(false); - s_offRamp.executeSingleReport( - _generateReportFromMessages( - SOURCE_CHAIN_SELECTOR_1, _generateMessagesWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1) - ), - new uint256[](0) - ); - } - function test_UnhealthySingleChainCurse_Revert() public { s_mockRMN.setChainCursed(SOURCE_CHAIN_SELECTOR_1, true); - vm.expectRevert(abi.encodeWithSelector(OffRamp.CursedByRMN.selector, SOURCE_CHAIN_SELECTOR_1)); + vm.expectEmit(); + emit OffRamp.SkippedReportExecution(SOURCE_CHAIN_SELECTOR_1); s_offRamp.executeSingleReport( _generateReportFromMessages( SOURCE_CHAIN_SELECTOR_1, _generateMessagesWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1) ), new uint256[](0) ); + vm.recordLogs(); // Uncurse should succeed s_mockRMN.setChainCursed(SOURCE_CHAIN_SELECTOR_1, false); s_offRamp.executeSingleReport( @@ -806,6 +826,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { ), new uint256[](0) ); + _assertNoEmit(OffRamp.SkippedReportExecution.selector); } function test_UnexpectedTokenData_Revert() public { @@ -1149,7 +1170,11 @@ contract OffRamp_batchExecute is OffRampSetup { uint64 nonceBefore = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages1[0].sender); vm.recordLogs(); s_offRamp.batchExecute(reports, new uint256[][](2)); + + Vm.Log[] memory logs = vm.getRecordedLogs(); + assertExecutionStateChangedEventLogs( + logs, messages1[0].header.sourceChainSelector, messages1[0].header.sequenceNumber, messages1[0].header.messageId, @@ -1159,6 +1184,7 @@ contract OffRamp_batchExecute is OffRampSetup { ); assertExecutionStateChangedEventLogs( + logs, messages1[1].header.sourceChainSelector, messages1[1].header.sequenceNumber, messages1[1].header.messageId, @@ -1168,6 +1194,7 @@ contract OffRamp_batchExecute is OffRampSetup { ); assertExecutionStateChangedEventLogs( + logs, messages2[0].header.sourceChainSelector, messages2[0].header.sequenceNumber, messages2[0].header.messageId, @@ -1195,7 +1222,10 @@ contract OffRamp_batchExecute is OffRampSetup { s_offRamp.batchExecute(reports, new uint256[][](2)); + Vm.Log[] memory logs = vm.getRecordedLogs(); + assertExecutionStateChangedEventLogs( + logs, messages1[0].header.sourceChainSelector, messages1[0].header.sequenceNumber, messages1[0].header.messageId, @@ -1205,6 +1235,7 @@ contract OffRamp_batchExecute is OffRampSetup { ); assertExecutionStateChangedEventLogs( + logs, messages1[1].header.sourceChainSelector, messages1[1].header.sequenceNumber, messages1[1].header.messageId, @@ -1214,10 +1245,11 @@ contract OffRamp_batchExecute is OffRampSetup { ); assertExecutionStateChangedEventLogs( + logs, messages2[0].header.sourceChainSelector, messages2[0].header.sequenceNumber, messages2[0].header.messageId, - Internal._hash(messages2[0], ON_RAMP_ADDRESS_1), + Internal._hash(messages2[0], ON_RAMP_ADDRESS_3), Internal.MessageExecutionState.SUCCESS, "" ); @@ -1230,6 +1262,45 @@ contract OffRamp_batchExecute is OffRampSetup { assertGt(nonceChain3, 0); } + function test_MultipleReportsDifferentChainsSkipCursedChain_Success() public { + s_mockRMN.setChainCursed(SOURCE_CHAIN_SELECTOR_1, true); + + Internal.Any2EVMRampMessage[] memory messages1 = new Internal.Any2EVMRampMessage[](2); + Internal.Any2EVMRampMessage[] memory messages2 = new Internal.Any2EVMRampMessage[](1); + + messages1[0] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); + messages1[1] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 2); + messages2[0] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_3, ON_RAMP_ADDRESS_3, 1); + + Internal.ExecutionReportSingleChain[] memory reports = new Internal.ExecutionReportSingleChain[](2); + reports[0] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages1); + reports[1] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_3, messages2); + + vm.recordLogs(); + + vm.expectEmit(); + emit OffRamp.SkippedReportExecution(SOURCE_CHAIN_SELECTOR_1); + + s_offRamp.batchExecute(reports, new uint256[][](2)); + + Vm.Log[] memory logs = vm.getRecordedLogs(); + + for (uint256 i = 0; i < logs.length; ++i) { + if (logs[i].topics[0] == OffRamp.ExecutionStateChanged.selector) { + uint64 logSourceChainSelector = uint64(uint256(logs[i].topics[1])); + uint64 logSequenceNumber = uint64(uint256(logs[i].topics[2])); + bytes32 logMessageId = bytes32(logs[i].topics[3]); + (bytes32 logMessageHash, uint8 logState,,) = abi.decode(logs[i].data, (bytes32, uint8, bytes, uint256)); + assertEq(logMessageId, messages2[0].header.messageId); + assertEq(logSourceChainSelector, messages2[0].header.sourceChainSelector); + assertEq(logSequenceNumber, messages2[0].header.sequenceNumber); + assertEq(logMessageId, messages2[0].header.messageId); + assertEq(logMessageHash, Internal._hash(messages2[0], ON_RAMP_ADDRESS_3)); + assertEq(logState, uint8(Internal.MessageExecutionState.SUCCESS)); + } + } + } + function test_MultipleReportsSkipDuplicate_Success() public { Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); @@ -1253,29 +1324,34 @@ contract OffRamp_batchExecute is OffRampSetup { ); } - // Reverts - function test_ZeroReports_Revert() public { - vm.expectRevert(OffRamp.EmptyReport.selector); - s_offRamp.batchExecute(new Internal.ExecutionReportSingleChain[](0), new uint256[][](1)); - } - - function test_Unhealthy_Revert() public { + function test_Unhealthy_Success() public { s_mockRMN.setGlobalCursed(true); - vm.expectRevert(abi.encodeWithSelector(OffRamp.CursedByRMN.selector, SOURCE_CHAIN_SELECTOR_1)); + vm.expectEmit(); + emit OffRamp.SkippedReportExecution(SOURCE_CHAIN_SELECTOR_1); s_offRamp.batchExecute( _generateBatchReportFromMessages( SOURCE_CHAIN_SELECTOR_1, _generateMessagesWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1) ), new uint256[][](1) ); - // Uncurse should succeed + s_mockRMN.setGlobalCursed(false); + + vm.recordLogs(); s_offRamp.batchExecute( _generateBatchReportFromMessages( SOURCE_CHAIN_SELECTOR_1, _generateMessagesWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1) ), new uint256[][](1) ); + + _assertNoEmit(OffRamp.SkippedReportExecution.selector); + } + + // Reverts + function test_ZeroReports_Revert() public { + vm.expectRevert(OffRamp.EmptyReport.selector); + s_offRamp.batchExecute(new Internal.ExecutionReportSingleChain[](0), new uint256[][](1)); } function test_OutOfBoundsGasLimitsAccess_Revert() public { @@ -1315,6 +1391,8 @@ contract OffRamp_manuallyExecute is OffRampSetup { uint256[][] memory gasLimitOverrides = new uint256[][](1); gasLimitOverrides[0] = new uint256[](messages.length); + + vm.recordLogs(); s_offRamp.manuallyExecute(_generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), gasLimitOverrides); assertExecutionStateChangedEventLogs( SOURCE_CHAIN_SELECTOR_1, @@ -1419,10 +1497,14 @@ contract OffRamp_manuallyExecute is OffRampSetup { gasLimitOverrides[1][i] += 1; } + vm.recordLogs(); s_offRamp.manuallyExecute(reports, gasLimitOverrides); + Vm.Log[] memory logs = vm.getRecordedLogs(); + for (uint256 j = 0; j < 3; ++j) { assertExecutionStateChangedEventLogs( + logs, SOURCE_CHAIN_SELECTOR_1, messages1[j].header.sequenceNumber, messages1[j].header.messageId, @@ -1434,10 +1516,11 @@ contract OffRamp_manuallyExecute is OffRampSetup { for (uint256 k = 0; k < 2; ++k) { assertExecutionStateChangedEventLogs( - SOURCE_CHAIN_SELECTOR_1, + logs, + SOURCE_CHAIN_SELECTOR_3, messages2[k].header.sequenceNumber, messages2[k].header.messageId, - Internal._hash(messages2[k], ON_RAMP_ADDRESS_1), + Internal._hash(messages2[k], ON_RAMP_ADDRESS_3), Internal.MessageExecutionState.SUCCESS, "" ); @@ -1457,7 +1540,10 @@ contract OffRamp_manuallyExecute is OffRampSetup { vm.recordLogs(); s_offRamp.batchExecute(_generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[][](1)); + Vm.Log[] memory logs = vm.getRecordedLogs(); + assertExecutionStateChangedEventLogs( + logs, SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber, messages[0].header.messageId, @@ -1467,6 +1553,7 @@ contract OffRamp_manuallyExecute is OffRampSetup { ); assertExecutionStateChangedEventLogs( + logs, SOURCE_CHAIN_SELECTOR_1, messages[1].header.sequenceNumber, messages[1].header.messageId, @@ -1479,6 +1566,7 @@ contract OffRamp_manuallyExecute is OffRampSetup { ); assertExecutionStateChangedEventLogs( + logs, SOURCE_CHAIN_SELECTOR_1, messages[2].header.sequenceNumber, messages[2].header.messageId, @@ -1738,6 +1826,37 @@ contract OffRamp_manuallyExecute is OffRampSetup { // Since the tx failed we don't release the tokens assertEq(tokenToAbuse.balanceOf(address(receiver)), balancePre + tokenAmount); } + + function test_manuallyExecute_MultipleReportsWithSingleCursedLane_Revert() public { + Internal.Any2EVMRampMessage[] memory messages1 = new Internal.Any2EVMRampMessage[](3); + Internal.Any2EVMRampMessage[] memory messages2 = new Internal.Any2EVMRampMessage[](2); + + for (uint64 i = 0; i < 3; ++i) { + messages1[i] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, i + 1); + messages1[i].receiver = address(s_reverting_receiver); + messages1[i].header.messageId = Internal._hash(messages1[i], ON_RAMP_ADDRESS_1); + } + + for (uint64 i = 0; i < 2; ++i) { + messages2[i] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_3, ON_RAMP_ADDRESS_3, i + 1); + messages2[i].receiver = address(s_reverting_receiver); + messages2[i].header.messageId = Internal._hash(messages2[i], ON_RAMP_ADDRESS_3); + } + + Internal.ExecutionReportSingleChain[] memory reports = new Internal.ExecutionReportSingleChain[](2); + reports[0] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages1); + reports[1] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_3, messages2); + + uint256[][] memory gasLimitOverrides = new uint256[][](2); + gasLimitOverrides[0] = _getGasLimitsFromMessages(messages1); + gasLimitOverrides[1] = _getGasLimitsFromMessages(messages2); + + s_mockRMN.setChainCursed(SOURCE_CHAIN_SELECTOR_3, true); + + vm.expectRevert(abi.encodeWithSelector(OffRamp.CursedByRMN.selector, SOURCE_CHAIN_SELECTOR_3)); + + s_offRamp.manuallyExecute(reports, gasLimitOverrides); + } } contract OffRamp_execute is OffRampSetup { @@ -1792,7 +1911,11 @@ contract OffRamp_execute is OffRampSetup { vm.recordLogs(); _execute(reports); + + Vm.Log[] memory logs = vm.getRecordedLogs(); + assertExecutionStateChangedEventLogs( + logs, messages1[0].header.sourceChainSelector, messages1[0].header.sequenceNumber, messages1[0].header.messageId, @@ -1802,6 +1925,7 @@ contract OffRamp_execute is OffRampSetup { ); assertExecutionStateChangedEventLogs( + logs, messages1[1].header.sourceChainSelector, messages1[1].header.sequenceNumber, messages1[1].header.messageId, @@ -1811,6 +1935,7 @@ contract OffRamp_execute is OffRampSetup { ); assertExecutionStateChangedEventLogs( + logs, messages2[0].header.sourceChainSelector, messages2[0].header.sequenceNumber, messages2[0].header.messageId, @@ -1839,9 +1964,12 @@ contract OffRamp_execute is OffRampSetup { vm.recordLogs(); _execute(reports); + Vm.Log[] memory logs = vm.getRecordedLogs(); + for (uint64 i = 0; i < reports.length; ++i) { for (uint64 j = 0; j < reports[i].messages.length; ++j) { assertExecutionStateChangedEventLogs( + logs, reports[i].messages[j].header.sourceChainSelector, reports[i].messages[j].header.sequenceNumber, reports[i].messages[j].header.messageId, @@ -1877,7 +2005,11 @@ contract OffRamp_execute is OffRampSetup { vm.recordLogs(); _execute(reports); + + Vm.Log[] memory logs = vm.getRecordedLogs(); + assertExecutionStateChangedEventLogs( + logs, messages1[0].header.sourceChainSelector, messages1[0].header.sequenceNumber, messages1[0].header.messageId, @@ -1890,6 +2022,7 @@ contract OffRamp_execute is OffRampSetup { ); assertExecutionStateChangedEventLogs( + logs, messages1[1].header.sourceChainSelector, messages1[1].header.sequenceNumber, messages1[1].header.messageId, @@ -1899,6 +2032,7 @@ contract OffRamp_execute is OffRampSetup { ); assertExecutionStateChangedEventLogs( + logs, messages2[0].header.sourceChainSelector, messages2[0].header.sequenceNumber, messages2[0].header.messageId, diff --git a/contracts/src/v0.8/ccip/test/offRamp/OffRampSetup.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRampSetup.t.sol index ae9fc044ac..79599fb98b 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/OffRampSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRampSetup.t.sol @@ -29,8 +29,6 @@ contract OffRampSetup is FeeQuoterSetup, MultiOCR3BaseSetup { uint64 internal constant SOURCE_CHAIN_SELECTOR_1 = SOURCE_CHAIN_SELECTOR; uint64 internal constant SOURCE_CHAIN_SELECTOR_2 = 6433500567565415381; uint64 internal constant SOURCE_CHAIN_SELECTOR_3 = 4051577828743386545; - bytes32 internal constant EXECUTION_STATE_CHANGE_TOPIC_HASH = - keccak256("ExecutionStateChanged(uint64,uint64,bytes32,bytes32,uint8,bytes,uint256)"); bytes internal constant ON_RAMP_ADDRESS_1 = abi.encode(ON_RAMP_ADDRESS); bytes internal constant ON_RAMP_ADDRESS_2 = abi.encode(0xaA3f843Cf8E33B1F02dd28303b6bD87B1aBF8AE4); @@ -484,7 +482,7 @@ contract OffRampSetup is FeeQuoterSetup, MultiOCR3BaseSetup { ) public { Vm.Log[] memory logs = vm.getRecordedLogs(); for (uint256 i = 0; i < logs.length; ++i) { - if (logs[i].topics[0] == EXECUTION_STATE_CHANGE_TOPIC_HASH) { + if (logs[i].topics[0] == OffRamp.ExecutionStateChanged.selector) { uint64 logSourceChainSelector = uint64(uint256(logs[i].topics[1])); uint64 logSequenceNumber = uint64(uint256(logs[i].topics[2])); bytes32 logMessageId = bytes32(logs[i].topics[3]); @@ -501,4 +499,40 @@ contract OffRampSetup is FeeQuoterSetup, MultiOCR3BaseSetup { } } } + + function assertExecutionStateChangedEventLogs( + Vm.Log[] memory logs, + uint64 sourceChainSelector, + uint64 sequenceNumber, + bytes32 messageId, + bytes32 messageHash, + Internal.MessageExecutionState state, + bytes memory returnData + ) public pure { + for (uint256 i = 0; i < logs.length; ++i) { + if (logs[i].topics[0] == OffRamp.ExecutionStateChanged.selector) { + uint64 logSourceChainSelector = uint64(uint256(logs[i].topics[1])); + uint64 logSequenceNumber = uint64(uint256(logs[i].topics[2])); + bytes32 logMessageId = bytes32(logs[i].topics[3]); + (bytes32 logMessageHash, uint8 logState, bytes memory logReturnData,) = + abi.decode(logs[i].data, (bytes32, uint8, bytes, uint256)); + if (logMessageId == messageId) { + assertEq(logSourceChainSelector, sourceChainSelector); + assertEq(logSequenceNumber, sequenceNumber); + assertEq(logMessageId, messageId); + assertEq(logMessageHash, messageHash); + assertEq(logState, uint8(state)); + assertEq(logReturnData, returnData); + } + } + } + } + + function _assertNoEmit(bytes32 eventSelector) internal { + Vm.Log[] memory logs = vm.getRecordedLogs(); + + for (uint256 i = 0; i < logs.length; i++) { + assertTrue(logs[i].topics[0] != eventSelector); + } + } } diff --git a/core/gethwrappers/ccip/generated/offramp/offramp.go b/core/gethwrappers/ccip/generated/offramp/offramp.go index b491a4f39d..6357a0c15f 100644 --- a/core/gethwrappers/ccip/generated/offramp/offramp.go +++ b/core/gethwrappers/ccip/generated/offramp/offramp.go @@ -164,8 +164,8 @@ type OffRampUnblessedRoot struct { } var OffRampMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CanOnlySelfCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"actual\",\"type\":\"bytes32\"}],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ExecutionError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"ForkedChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enumMultiOCR3Base.InvalidConfigErrorType\",\"name\":\"errorType\",\"type\":\"uint8\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"got\",\"type\":\"uint256\"}],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidEVMAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"internalType\":\"structOffRamp.Interval\",\"name\":\"interval\",\"type\":\"tuple\"}],\"name\":\"InvalidInterval\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"newLimit\",\"type\":\"uint256\"}],\"name\":\"InvalidManualExecutionGasLimit\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"messageDestChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidMessageDestChainSelector\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"newState\",\"type\":\"uint8\"}],\"name\":\"InvalidNewState\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRoot\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidStaticConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LeavesCannotBeEmpty\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ManualExecutionGasLimitMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"ManualExecutionNotYetEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"errorReason\",\"type\":\"bytes\"}],\"name\":\"MessageValidationError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonUniqueSignatures\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"notPool\",\"type\":\"address\"}],\"name\":\"NotACompatiblePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OracleCannotBeZeroAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ReceiverError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountReleased\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePre\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePost\",\"type\":\"uint256\"}],\"name\":\"ReleaseOrMintBalanceMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"name\":\"RootAlreadyCommitted\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"RootNotCommitted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignaturesOutOfRegistration\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"StaleCommitReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"StaticConfigCannotBeChanged\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"TokenDataMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"TokenHandlingError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnexpectedTokenData\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"WrongMessageLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WrongNumberOfSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroChainSelectorNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"AlreadyAttempted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"internalType\":\"structOffRamp.Interval\",\"name\":\"interval\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structOffRamp.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"report\",\"type\":\"tuple\"}],\"name\":\"CommitReportAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"DynamicConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"messageHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"name\":\"ExecutionStateChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"RootRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"SkippedAlreadyExecutedMessage\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"sourceConfig\",\"type\":\"tuple\"}],\"name\":\"SourceChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainSelectorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"}],\"name\":\"StaticConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigUpdates\",\"type\":\"tuple[]\"}],\"name\":\"applySourceChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"destTokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structClient.Any2EVMMessage\",\"name\":\"\",\"type\":\"tuple\"}],\"name\":\"ccipReceive\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"rawVs\",\"type\":\"bytes32\"}],\"name\":\"commit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"execute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"bytes[]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[]\"}],\"name\":\"executeSingleMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"getExecutionState\",\"outputs\":[{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLatestPriceSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"getMerkleRoot\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"getSourceChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"isBlessed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"latestConfigDetails\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"n\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"}],\"internalType\":\"structMultiOCR3Base.ConfigInfo\",\"name\":\"configInfo\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfig\",\"name\":\"ocrConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage[]\",\"name\":\"messages\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[][]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[][]\"},{\"internalType\":\"bytes32[]\",\"name\":\"proofs\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"proofFlagBits\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.ExecutionReportSingleChain[]\",\"name\":\"reports\",\"type\":\"tuple[]\"},{\"internalType\":\"uint256[][]\",\"name\":\"gasLimitOverrides\",\"type\":\"uint256[][]\"}],\"name\":\"manuallyExecute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structOffRamp.UnblessedRoot[]\",\"name\":\"rootToReset\",\"type\":\"tuple[]\"}],\"name\":\"resetUnblessedRoots\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"setDynamicConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfigArgs[]\",\"name\":\"ocrConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"setOCR3Configs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x6101206040523480156200001257600080fd5b5060405162006bcd38038062006bcd8339810160408190526200003591620008c7565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf81620001fa565b5050466080525060208301516001600160a01b03161580620000ec575060408301516001600160a01b0316155b8062000103575060608301516001600160a01b0316155b1562000122576040516342bcdf7f60e11b815260040160405180910390fd5b82516001600160401b03166000036200014e5760405163c656089560e01b815260040160405180910390fd5b82516001600160401b0390811660a052602080850180516001600160a01b0390811660c05260408088018051831660e0526060808a01805185166101005283518b519098168852945184169587019590955251821690850152905116908201527f683eb52ee924eb817377cfa8f41f238f4bb7a877da5267869dfffbad85f564d89060800160405180910390a1620001e682620002a5565b620001f181620003c1565b50505062000c67565b336001600160a01b03821603620002545760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b0316620002ce576040516342bcdf7f60e11b815260040160405180910390fd5b80516004805460208085018051604080880180516060808b0180516001600160a01b039b8c166001600160c01b0319909a168a17600160a01b63ffffffff98891602176001600160c01b0316600160c01b948816949094026001600160e01b031693909317600160e01b93871693909302929092179098556080808b018051600580546001600160a01b031916918d169190911790558451988952955185169688019690965290518316918601919091525116938301939093529151909216908201527fa55bd56595c45f517e5967a3067f3dca684445a3080e7c04a4e0d5a40cda627d9060a00160405180910390a150565b60005b815181101562000666576000828281518110620003e557620003e562000a1d565b60200260200101519050600081602001519050806001600160401b0316600003620004235760405163c656089560e01b815260040160405180910390fd5b81516001600160a01b03166200044c576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160401b0381166000908152600660205260408120600181018054919291620004789062000a33565b80601f0160208091040260200160405190810160405280929190818152602001828054620004a69062000a33565b8015620004f75780601f10620004cb57610100808354040283529160200191620004f7565b820191906000526020600020905b815481529060010190602001808311620004d957829003601f168201915b5050505050905060008460600151905081516000036200059e57805160000362000534576040516342bcdf7f60e11b815260040160405180910390fd5b6001830162000544828262000ac4565b508254600160a81b600160e81b031916600160a81b1783556040516001600160401b03851681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1620005d9565b8080519060200120828051906020012014620005d95760405163c39a620560e01b81526001600160401b038516600482015260240162000083565b604080860151845487516001600160a01b03166001600160a01b0319921515600160a01b02929092166001600160a81b031990911617178455516001600160401b038516907f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b906200064d90869062000b90565b60405180910390a25050505050806001019050620003c4565b5050565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b0381118282101715620006a557620006a56200066a565b60405290565b604051601f8201601f191681016001600160401b0381118282101715620006d657620006d66200066a565b604052919050565b80516001600160401b0381168114620006f657600080fd5b919050565b6001600160a01b03811681146200071157600080fd5b50565b805163ffffffff81168114620006f657600080fd5b6000601f83601f8401126200073d57600080fd5b825160206001600160401b03808311156200075c576200075c6200066a565b8260051b6200076d838201620006ab565b93845286810183019383810190898611156200078857600080fd5b84890192505b85831015620008ba57825184811115620007a85760008081fd5b89016080601f19828d038101821315620007c25760008081fd5b620007cc62000680565b88840151620007db81620006fb565b81526040620007ec858201620006de565b8a8301526060808601518015158114620008065760008081fd5b838301529385015193898511156200081e5760008081fd5b84860195508f603f8701126200083657600094508485fd5b8a8601519450898511156200084f576200084f6200066a565b620008608b858f88011601620006ab565b93508484528f82868801011115620008785760008081fd5b60005b8581101562000898578681018301518582018d01528b016200087b565b5060009484018b0194909452509182015283525091840191908401906200078e565b9998505050505050505050565b6000806000838503610140811215620008df57600080fd5b6080811215620008ee57600080fd5b620008f862000680565b6200090386620006de565b815260208601516200091581620006fb565b602082015260408601516200092a81620006fb565b604082015260608601516200093f81620006fb565b6060820152935060a0607f19820112156200095957600080fd5b5060405160a081016001600160401b0380821183831017156200098057620009806200066a565b81604052608087015191506200099682620006fb565b818352620009a760a0880162000714565b6020840152620009ba60c0880162000714565b6040840152620009cd60e0880162000714565b60608401526101008701519150620009e582620006fb565b608083018290526101208701519294508083111562000a0357600080fd5b505062000a138682870162000729565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b600181811c9082168062000a4857607f821691505b60208210810362000a6957634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111562000abf576000816000526020600020601f850160051c8101602086101562000a9a5750805b601f850160051c820191505b8181101562000abb5782815560010162000aa6565b5050505b505050565b81516001600160401b0381111562000ae05762000ae06200066a565b62000af88162000af1845462000a33565b8462000a6f565b602080601f83116001811462000b30576000841562000b175750858301515b600019600386901b1c1916600185901b17855562000abb565b600085815260208120601f198616915b8281101562000b615788860151825594840194600190910190840162000b40565b508582101562000b805787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b602080825282546001600160a01b0381168383015260a081901c60ff161515604084015260a81c6001600160401b0316606083015260808083015260018084018054600093929190849062000be58162000a33565b8060a089015260c0600183166000811462000c09576001811462000c265762000c58565b60ff19841660c08b015260c083151560051b8b0101945062000c58565b85600052602060002060005b8481101562000c4f5781548c820185015290880190890162000c32565b8b0160c0019550505b50929998505050505050505050565b60805160a05160c05160e05161010051615ef762000cd66000396000818161026601526129ee0152600081816102370152612ee20152600081816102080152818161142b015261196d0152600081816101d801526126690152600081816117f3015261183f0152615ef76000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806385572ffb116100d8578063ccd37ba31161008c578063f2fde38b11610066578063f2fde38b14610583578063f716f99f14610596578063ff888fb1146105a957600080fd5b8063ccd37ba31461050b578063d2a15d3514610550578063e9d68a8e1461056357600080fd5b8063991a5018116100bd578063991a5018146104c5578063a80036b4146104d8578063c673e584146104eb57600080fd5b806385572ffb1461049c5780638da5cb5b146104aa57600080fd5b8063311cd5131161012f5780635e36480c116101145780635e36480c146103785780637437ff9f1461039857806379ba50971461049457600080fd5b8063311cd513146103495780633f4b04aa1461035c57600080fd5b806306285c691161016057806306285c69146101a4578063181f5a77146102ed5780632d04ab761461033657600080fd5b806304666f9c1461017c57806305d938b514610191575b600080fd5b61018f61018a366004614072565b6105cc565b005b61018f61019f3660046146fe565b6105e0565b61029660408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316815250905090565b6040516102e49190815167ffffffffffffffff1681526020808301516001600160a01b0390811691830191909152604080840151821690830152606092830151169181019190915260800190565b60405180910390f35b6103296040518060400160405280601181526020017f4f666652616d7020312e362e302d64657600000000000000000000000000000081525081565b6040516102e49190614879565b61018f610344366004614924565b610785565b61018f6103573660046149d7565b610b5c565b60095460405167ffffffffffffffff90911681526020016102e4565b61038b610386366004614a2b565b610bc5565b6040516102e49190614a88565b6104376040805160a081018252600080825260208201819052918101829052606081018290526080810191909152506040805160a0810182526004546001600160a01b03808216835263ffffffff600160a01b83048116602085015278010000000000000000000000000000000000000000000000008304811694840194909452600160e01b9091049092166060820152600554909116608082015290565b6040516102e49190600060a0820190506001600160a01b03808451168352602084015163ffffffff808216602086015280604087015116604086015280606087015116606086015250508060808501511660808401525092915050565b61018f610c1b565b61018f610177366004614a96565b6000546040516001600160a01b0390911681526020016102e4565b61018f6104d3366004614ae5565b610cd9565b61018f6104e6366004614b59565b610cea565b6104fe6104f9366004614bc6565b61105d565b6040516102e49190614c26565b610542610519366004614c9b565b67ffffffffffffffff919091166000908152600860209081526040808320938352929052205490565b6040519081526020016102e4565b61018f61055e366004614cc5565b6111bb565b610576610571366004614d3a565b611275565b6040516102e49190614d55565b61018f610591366004614da3565b611382565b61018f6105a4366004614e28565b611393565b6105bc6105b7366004614f66565b6113d5565b60405190151581526020016102e4565b6105d4611496565b6105dd816114f2565b50565b6105e86117f0565b815181518114610624576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8181101561077557600084828151811061064357610643614f7f565b6020026020010151905060008160200151519050600085848151811061066b5761066b614f7f565b60200260200101519050805182146106af576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b828110156107665760008282815181106106ce576106ce614f7f565b602002602001015190508060001461075d57846020015182815181106106f6576106f6614f7f565b60200260200101516080015181101561075d5784516040517fc8e9605100000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260248101839052604481018290526064015b60405180910390fd5b506001016106b2565b50505050806001019050610627565b506107808383611871565b505050565b600061079387890189615105565b805151519091501515806107ac57508051602001515115155b156108ac5760095460208a01359067ffffffffffffffff8083169116101561086b576009805467ffffffffffffffff191667ffffffffffffffff83161790556004805483516040517f3937306f0000000000000000000000000000000000000000000000000000000081526001600160a01b0390921692633937306f9261083492910161532d565b600060405180830381600087803b15801561084e57600080fd5b505af1158015610862573d6000803e3d6000fd5b505050506108aa565b8160200151516000036108aa576040517f2261116700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b60005b816020015151811015610aa5576000826020015182815181106108d4576108d4614f7f565b602002602001015190506000816000015190506108f081611921565b60006108fb82611a23565b602084015151815491925067ffffffffffffffff908116600160a81b9092041614158061093f575060208084015190810151905167ffffffffffffffff9182169116115b1561097f57825160208401516040517feefb0cac000000000000000000000000000000000000000000000000000000008152610754929190600401615340565b6040830151806109bb576040517f504570e300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b835167ffffffffffffffff16600090815260086020908152604080832084845290915290205415610a2e5783516040517f32cf0cbf00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260248101829052604401610754565b6020808501510151610a4190600161538b565b82547fffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffff16600160a81b67ffffffffffffffff9283160217909255925116600090815260086020908152604080832094835293905291909120429055506001016108af565b507f3a3950e13dd607cc37980db0ef14266c40d2bba9c01b2e44bfe549808883095d81604051610ad591906153b3565b60405180910390a1610b5160008a8a8a8a8a8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808e0282810182019093528d82529093508d92508c9182918501908490808284376000920191909152508b9250611a8a915050565b505050505050505050565b610b9c610b6b82840184615450565b6040805160008082526020820190925290610b96565b6060815260200190600190039081610b815790505b50611871565b604080516000808252602082019092529050610bbf600185858585866000611a8a565b50505050565b6000610bd360016004615485565b6002610be06080856154ae565b67ffffffffffffffff16610bf491906154d5565b610bfe8585611e01565b901c166003811115610c1257610c12614a5e565b90505b92915050565b6001546001600160a01b03163314610c755760405162461bcd60e51b815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610754565b600080543373ffffffffffffffffffffffffffffffffffffffff19808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610ce1611496565b6105dd81611e48565b333014610d23576040517f371a732800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160008082526020820190925281610d60565b6040805180820190915260008082526020820152815260200190600190039081610d395790505b5060a08501515190915015610d9457610d918460a00151856020015186606001518760000151602001518787611fae565b90505b6040805160a0810182528551518152855160209081015167ffffffffffffffff1681830152808701518351600094840192610dd0929101614879565b60408051601f19818403018152918152908252878101516020830152018390526005549091506001600160a01b03168015610edd576040517f08d450a10000000000000000000000000000000000000000000000000000000081526001600160a01b038216906308d450a190610e4a90859060040161558e565b600060405180830381600087803b158015610e6457600080fd5b505af1925050508015610e75575060015b610edd573d808015610ea3576040519150601f19603f3d011682016040523d82523d6000602084013e610ea8565b606091505b50806040517f09c253250000000000000000000000000000000000000000000000000000000081526004016107549190614879565b604086015151158015610ef257506080860151155b80610f09575060608601516001600160a01b03163b155b80610f4957506060860151610f47906001600160a01b03167f85572ffb000000000000000000000000000000000000000000000000000000006120cd565b155b15610f5657505050505050565b855160209081015167ffffffffffffffff1660009081526006909152604080822054608089015160608a015192517f3cf9798300000000000000000000000000000000000000000000000000000000815284936001600160a01b0390931692633cf9798392610fce92899261138892916004016155a1565b6000604051808303816000875af1158015610fed573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261101591908101906155dd565b50915091508161105357806040517f0a8d6e8c0000000000000000000000000000000000000000000000000000000081526004016107549190614879565b5050505050505050565b6110a06040805160e081019091526000606082018181526080830182905260a0830182905260c08301919091528190815260200160608152602001606081525090565b60ff808316600090815260026020818152604092839020835160e081018552815460608201908152600183015480881660808401526101008104881660a0840152620100009004909616151560c08201529485529182018054845181840281018401909552808552929385830193909283018282801561114957602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161112b575b50505050508152602001600382018054806020026020016040519081016040528092919081815260200182805480156111ab57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161118d575b5050505050815250509050919050565b6111c3611496565b60005b818110156107805760008383838181106111e2576111e2614f7f565b9050604002018036038101906111f89190615673565b905061120781602001516113d5565b61126c57805167ffffffffffffffff1660009081526008602090815260408083208285018051855290835281842093909355915191519182527f202f1139a3e334b6056064c0e9b19fd07e44a88d8f6e5ded571b24cf8c371f12910160405180910390a15b506001016111c6565b604080516080808201835260008083526020808401829052838501829052606080850181905267ffffffffffffffff878116845260068352928690208651948501875280546001600160a01b0381168652600160a01b810460ff16151593860193909352600160a81b909204909216948301949094526001840180549394929391840191611302906156ac565b80601f016020809104026020016040519081016040528092919081815260200182805461132e906156ac565b80156111ab5780601f10611350576101008083540402835291602001916111ab565b820191906000526020600020905b81548152906001019060200180831161135e57505050919092525091949350505050565b61138a611496565b6105dd816120e9565b61139b611496565b60005b81518110156113d1576113c98282815181106113bc576113bc614f7f565b602002602001015161219f565b60010161139e565b5050565b6040805180820182523081526020810183815291517f4d61677100000000000000000000000000000000000000000000000000000000815290516001600160a01b039081166004830152915160248201526000917f00000000000000000000000000000000000000000000000000000000000000001690634d61677190604401602060405180830381865afa158015611472573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c1591906156e6565b6000546001600160a01b031633146114f05760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610754565b565b60005b81518110156113d157600082828151811061151257611512614f7f565b602002602001015190506000816020015190508067ffffffffffffffff16600003611569576040517fc656089500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81516001600160a01b0316611591576040516342bcdf7f60e11b815260040160405180910390fd5b67ffffffffffffffff811660009081526006602052604081206001810180549192916115bc906156ac565b80601f01602080910402602001604051908101604052809291908181526020018280546115e8906156ac565b80156116355780601f1061160a57610100808354040283529160200191611635565b820191906000526020600020905b81548152906001019060200180831161161857829003601f168201915b5050505050905060008460600151905081516000036116ed578051600003611670576040516342bcdf7f60e11b815260040160405180910390fd5b6001830161167e8282615753565b5082547fffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffff16600160a81b17835560405167ffffffffffffffff851681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1611740565b8080519060200120828051906020012014611740576040517fc39a620500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff85166004820152602401610754565b604080860151845487516001600160a01b031673ffffffffffffffffffffffffffffffffffffffff19921515600160a01b02929092167fffffffffffffffffffffff000000000000000000000000000000000000000000909116171784555167ffffffffffffffff8516907f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b906117d8908690615813565b60405180910390a250505050508060010190506114f5565b467f0000000000000000000000000000000000000000000000000000000000000000146114f0576040517f0f01ce850000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000006004820152466024820152604401610754565b81516000036118ab576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160408051600080825260208201909252911591905b845181101561191a576119128582815181106118e0576118e0614f7f565b60200260200101518461190c578583815181106118ff576118ff614f7f565b60200260200101516124d0565b836124d0565b6001016118c2565b5050505050565b6040517f2cbc26bb000000000000000000000000000000000000000000000000000000008152608082901b77ffffffffffffffff000000000000000000000000000000001660048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632cbc26bb90602401602060405180830381865afa1580156119bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119e091906156e6565b156105dd576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610754565b67ffffffffffffffff811660009081526006602052604081208054600160a01b900460ff16610c15576040517fed053c5900000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610754565b60ff87811660009081526002602090815260408083208151608081018352815481526001909101548086169382019390935261010083048516918101919091526201000090910490921615156060830152873590611ae98760a46158e1565b9050826060015115611b31578451611b029060206154d5565b8651611b0f9060206154d5565b611b1a9060a06158e1565b611b2491906158e1565b611b2e90826158e1565b90505b368114611b73576040517f8e1192e100000000000000000000000000000000000000000000000000000000815260048101829052366024820152604401610754565b5081518114611bbb5781516040517f93df584c000000000000000000000000000000000000000000000000000000008152600481019190915260248101829052604401610754565b611bc36117f0565b60ff808a1660009081526003602090815260408083203384528252808320815180830190925280548086168352939491939092840191610100909104166002811115611c1157611c11614a5e565b6002811115611c2257611c22614a5e565b9052509050600281602001516002811115611c3f57611c3f614a5e565b148015611c935750600260008b60ff1660ff168152602001908152602001600020600301816000015160ff1681548110611c7b57611c7b614f7f565b6000918252602090912001546001600160a01b031633145b611cc9576040517fda0f08e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50816060015115611dab576020820151611ce49060016158f4565b60ff16855114611d20576040517f71253a2500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8351855114611d5b576040517fa75d88af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008787604051611d6d92919061590d565b604051908190038120611d84918b9060200161591d565b604051602081830303815290604052805190602001209050611da98a82888888612c9c565b505b6040805182815260208a81013567ffffffffffffffff169082015260ff8b16917f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef0910160405180910390a2505050505050505050565b67ffffffffffffffff8216600090815260076020526040812081611e26608085615931565b67ffffffffffffffff1681526020810191909152604001600020549392505050565b80516001600160a01b0316611e70576040516342bcdf7f60e11b815260040160405180910390fd5b80516004805460208085018051604080880180516060808b0180516001600160a01b039b8c167fffffffffffffffff000000000000000000000000000000000000000000000000909a168a17600160a01b63ffffffff988916021777ffffffffffffffffffffffffffffffffffffffffffffffff167801000000000000000000000000000000000000000000000000948816949094026001600160e01b031693909317600160e01b93871693909302929092179098556080808b0180516005805473ffffffffffffffffffffffffffffffffffffffff1916918d169190911790558451988952955185169688019690965290518316918601919091525116938301939093529151909216908201527fa55bd56595c45f517e5967a3067f3dca684445a3080e7c04a4e0d5a40cda627d9060a00160405180910390a150565b6060865167ffffffffffffffff811115611fca57611fca613e89565b60405190808252806020026020018201604052801561200f57816020015b6040805180820190915260008082526020820152815260200190600190039081611fe85790505b50905060005b87518110156120c15761209c88828151811061203357612033614f7f565b602002602001015188888888888781811061205057612050614f7f565b90506020028101906120629190615958565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612e8192505050565b8282815181106120ae576120ae614f7f565b6020908102919091010152600101612015565b505b9695505050505050565b60006120d883613226565b8015610c125750610c12838361328a565b336001600160a01b038216036121415760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610754565b6001805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b806040015160ff166000036121ca576000604051631b3fab5160e11b815260040161075491906159bd565b60208082015160ff8082166000908152600290935260408320600181015492939092839216900361223757606084015160018201805491151562010000027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff90921691909117905561228c565b6060840151600182015460ff620100009091041615159015151461228c576040517f87f6037c00000000000000000000000000000000000000000000000000000000815260ff84166004820152602401610754565b60a0840151805161010010156122b8576001604051631b3fab5160e11b815260040161075491906159bd565b61231e848460030180548060200260200160405190810160405280929190818152602001828054801561231457602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116122f6575b5050505050613345565b8460600151156124455761238c8484600201805480602002602001604051908101604052809291908181526020018280548015612314576020028201919060005260206000209081546001600160a01b031681526001909101906020018083116122f6575050505050613345565b6080850151805161010010156123b8576002604051631b3fab5160e11b815260040161075491906159bd565b60408601516123c89060036159d7565b60ff168151116123ee576003604051631b3fab5160e11b815260040161075491906159bd565b80516001840180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1661010060ff8416021790556124369060028601906020840190613e02565b50612443858260016133ae565b505b612451848260026133ae565b80516124669060038501906020840190613e02565b5060408581015160018401805460ff191660ff8316179055865180855560a088015192517fab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f547936124bf9389939260028a019291906159f3565b60405180910390a161191a84613522565b81516124db81611921565b60006124e682611a23565b60010180546124f4906156ac565b80601f0160208091040260200160405190810160405280929190818152602001828054612520906156ac565b801561256d5780601f106125425761010080835404028352916020019161256d565b820191906000526020600020905b81548152906001019060200180831161255057829003601f168201915b505050602087015151929350505060008190036125b5576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84604001515181146125f3576040517f57e0e08300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008167ffffffffffffffff81111561260e5761260e613e89565b604051908082528060200260200182016040528015612637578160200160208202803683370190505b50905060005b828110156127205760008760200151828151811061265d5761265d614f7f565b602002602001015190507f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681600001516040015167ffffffffffffffff16146126f057805160409081015190517f38432a2200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610754565b6126fa818661353e565b83838151811061270c5761270c614f7f565b60209081029190910101525060010161263d565b506000612737858389606001518a60800151613660565b90508060000361277f576040517f7dd17a7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff86166004820152602401610754565b8551151560005b84811015610b515760005a905060008a6020015183815181106127ab576127ab614f7f565b6020026020010151905060006127c98a836000015160600151610bc5565b905060008160038111156127df576127df614a5e565b14806127fc575060038160038111156127fa576127fa614a5e565b145b612854578151606001516040805167ffffffffffffffff808e16825290921660208301527f3b575419319662b2a6f5e2467d84521517a3382b908eb3d557bb3fdb0c50e23c91015b60405180910390a1505050612c94565b841561292457600454600090600160a01b900463ffffffff166128778842615485565b11905080806128975750600382600381111561289557612895614a5e565b145b6128d9576040517fa9cfc86200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8c166004820152602401610754565b8b85815181106128eb576128eb614f7f565b602002602001015160001461291e578b858151811061290c5761290c614f7f565b60200260200101518360800181815250505b50612985565b600081600381111561293857612938614a5e565b14612985578151606001516040805167ffffffffffffffff808e16825290921660208301527f3ef2a99c550a751d4b0b261268f05a803dfb049ab43616a1ffb388f61fe651209101612844565b81516080015167ffffffffffffffff1615612a745760008160038111156129ae576129ae614a5e565b03612a745781516080015160208301516040517fe0e03cae0000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169263e0e03cae92612a25928f929190600401615a9f565b6020604051808303816000875af1158015612a44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a6891906156e6565b612a7457505050612c94565b60008c604001518581518110612a8c57612a8c614f7f565b6020026020010151905080518360a001515114612af0578251606001516040517f1cfe6d8b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808e1660048301529091166024820152604401610754565b612b048b84600001516060015160016136b6565b600080612b11858461375e565b91509150612b288d866000015160600151846136b6565b8715612b98576003826003811115612b4257612b42614a5e565b03612b98576000846003811115612b5b57612b5b614a5e565b14612b98578451516040517f2b11b8d900000000000000000000000000000000000000000000000000000000815261075491908390600401615acc565b6002826003811115612bac57612bac614a5e565b14612c06576003826003811115612bc557612bc5614a5e565b14612c06578451606001516040517f926c5a3e000000000000000000000000000000000000000000000000000000008152610754918f918590600401615ae5565b84600001516000015185600001516060015167ffffffffffffffff168e67ffffffffffffffff167f05665fe9ad095383d018353f4cbcba77e84db27dd215081bbf7cdf9ae6fbe48b8d8b81518110612c6057612c60614f7f565b602002602001015186865a612c75908e615485565b604051612c859493929190615b0b565b60405180910390a45050505050505b600101612786565b8251600090815b81811015611053576000600188868460208110612cc257612cc2614f7f565b612ccf91901a601b6158f4565b898581518110612ce157612ce1614f7f565b6020026020010151898681518110612cfb57612cfb614f7f565b602002602001015160405160008152602001604052604051612d39949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015612d5b573d6000803e3d6000fd5b505060408051601f1981015160ff808e166000908152600360209081528582206001600160a01b03851683528152858220858701909652855480841686529397509095509293928401916101009004166002811115612dbc57612dbc614a5e565b6002811115612dcd57612dcd614a5e565b9052509050600181602001516002811115612dea57612dea614a5e565b14612e21576040517fca31867a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051600160ff9091161b851615612e64576040517ff67bc7c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806000015160ff166001901b851794505050806001019050612ca3565b60408051808201909152600080825260208201526000612ea48760200151613828565b6040517fbbe4f6db0000000000000000000000000000000000000000000000000000000081526001600160a01b0380831660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063bbe4f6db90602401602060405180830381865afa158015612f29573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f4d9190615b42565b90506001600160a01b0381161580612f955750612f936001600160a01b0382167faff2afbf000000000000000000000000000000000000000000000000000000006120cd565b155b15612fd7576040517fae9b4ce90000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152602401610754565b6004546000908190612ff99089908690600160e01b900463ffffffff166138ce565b9150915060008060006130c66040518061010001604052808e81526020018c67ffffffffffffffff1681526020018d6001600160a01b031681526020018f606001518152602001896001600160a01b031681526020018f6000015181526020018f6040015181526020018b8152506040516024016130779190615b5f565b60408051601f198184030181529190526020810180516001600160e01b03167f3907753700000000000000000000000000000000000000000000000000000000179052878661138860846139fc565b9250925092508261310557816040517fe1cd55090000000000000000000000000000000000000000000000000000000081526004016107549190614879565b815160201461314d5781516040517f78ef8024000000000000000000000000000000000000000000000000000000008152602060048201526024810191909152604401610754565b6000828060200190518101906131639190615c2c565b9050866001600160a01b03168c6001600160a01b0316146131f85760006131948d8a61318f868a615485565b6138ce565b509050868110806131ae5750816131ab8883615485565b14155b156131f6576040517fa966e21f000000000000000000000000000000000000000000000000000000008152600481018390526024810188905260448101829052606401610754565b505b604080518082019091526001600160a01b039098168852602088015250949550505050505095945050505050565b6000613252827f01ffc9a70000000000000000000000000000000000000000000000000000000061328a565b8015610c155750613283827fffffffff0000000000000000000000000000000000000000000000000000000061328a565b1592915050565b6040517fffffffff0000000000000000000000000000000000000000000000000000000082166024820152600090819060440160408051601f19818403018152919052602080820180516001600160e01b03167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825192935060009283928392909183918a617530fa92503d9150600051905082801561332e575060208210155b801561333a5750600081115b979650505050505050565b60005b81518110156107805760ff83166000908152600360205260408120835190919084908490811061337a5761337a614f7f565b6020908102919091018101516001600160a01b03168252810191909152604001600020805461ffff19169055600101613348565b60005b8251811015610bbf5760008382815181106133ce576133ce614f7f565b60200260200101519050600060028111156133eb576133eb614a5e565b60ff80871660009081526003602090815260408083206001600160a01b0387168452909152902054610100900416600281111561342a5761342a614a5e565b1461344b576004604051631b3fab5160e11b815260040161075491906159bd565b6001600160a01b03811661348b576040517fd6c62c9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052808360ff1681526020018460028111156134b1576134b1614a5e565b905260ff80871660009081526003602090815260408083206001600160a01b0387168452825290912083518154931660ff198416811782559184015190929091839161ffff19161761010083600281111561350e5761350e614a5e565b0217905550905050508060010190506133b1565b60ff81166105dd576009805467ffffffffffffffff1916905550565b815160208082015160409283015192516000938493613584937f2425b0b9f9054c76ff151b0a175b18f37a4a4e82013a72e9f15c9caa095ed21f93909291889101615c45565b60408051601f1981840301815290829052805160209182012086518051888401516060808b0151908401516080808d015195015195976135cd9794969395929491939101615c78565b604051602081830303815290604052805190602001208560400151805190602001208660a001516040516020016136049190615d8a565b60408051601f198184030181528282528051602091820120908301969096528101939093526060830191909152608082015260a081019190915260c0015b60405160208183030381529060405280519060200120905092915050565b60008061366e858585613b22565b9050613679816113d5565b6136875760009150506136ae565b67ffffffffffffffff86166000908152600860209081526040808320938352929052205490505b949350505050565b600060026136c56080856154ae565b67ffffffffffffffff166136d991906154d5565b905060006136e78585611e01565b9050816136f660016004615485565b901b19168183600381111561370d5761370d614a5e565b67ffffffffffffffff871660009081526007602052604081209190921b9290921791829161373c608088615931565b67ffffffffffffffff1681526020810191909152604001600020555050505050565b6040517fa80036b4000000000000000000000000000000000000000000000000000000008152600090606090309063a80036b4906137a29087908790600401615dea565b600060405180830381600087803b1580156137bc57600080fd5b505af19250505080156137cd575060015b61380c573d8080156137fb576040519150601f19603f3d011682016040523d82523d6000602084013e613800565b606091505b50600392509050613821565b50506040805160208101909152600081526002905b9250929050565b6000815160201461386757816040517f8d666f600000000000000000000000000000000000000000000000000000000081526004016107549190614879565b60008280602001905181019061387d9190615c2c565b90506001600160a01b03811180613895575061040081105b15610c1557826040517f8d666f600000000000000000000000000000000000000000000000000000000081526004016107549190614879565b6000806000806000613948886040516024016138f991906001600160a01b0391909116815260200190565b60408051601f198184030181529190526020810180516001600160e01b03167f70a0823100000000000000000000000000000000000000000000000000000000179052888861138860846139fc565b9250925092508261398757816040517fe1cd55090000000000000000000000000000000000000000000000000000000081526004016107549190614879565b60208251146139cf5781516040517f78ef8024000000000000000000000000000000000000000000000000000000008152602060048201526024810191909152604401610754565b818060200190518101906139e39190615c2c565b6139ed8288615485565b94509450505050935093915050565b6000606060008361ffff1667ffffffffffffffff811115613a1f57613a1f613e89565b6040519080825280601f01601f191660200182016040528015613a49576020820181803683370190505b509150863b613a7c577f0c3b563c0000000000000000000000000000000000000000000000000000000060005260046000fd5b5a85811015613aaf577fafa32a2c0000000000000000000000000000000000000000000000000000000060005260046000fd5b8590036040810481038710613ae8577f37c3be290000000000000000000000000000000000000000000000000000000060005260046000fd5b505a6000808a5160208c0160008c8cf193505a900390503d84811115613b0b5750835b808352806000602085013e50955095509592505050565b8251825160009190818303613b63576040517f11a6b26400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6101018211801590613b7757506101018111155b613b94576040516309bde33960e01b815260040160405180910390fd5b60001982820101610100811115613bbe576040516309bde33960e01b815260040160405180910390fd5b80600003613beb5786600081518110613bd957613bd9614f7f565b60200260200101519350505050613dba565b60008167ffffffffffffffff811115613c0657613c06613e89565b604051908082528060200260200182016040528015613c2f578160200160208202803683370190505b50905060008080805b85811015613d595760006001821b8b811603613c935788851015613c7c578c5160018601958e918110613c6d57613c6d614f7f565b60200260200101519050613cb5565b8551600185019487918110613c6d57613c6d614f7f565b8b5160018401938d918110613caa57613caa614f7f565b602002602001015190505b600089861015613ce5578d5160018701968f918110613cd657613cd6614f7f565b60200260200101519050613d07565b8651600186019588918110613cfc57613cfc614f7f565b602002602001015190505b82851115613d28576040516309bde33960e01b815260040160405180910390fd5b613d328282613dc1565b878481518110613d4457613d44614f7f565b60209081029190910101525050600101613c38565b506001850382148015613d6b57508683145b8015613d7657508581145b613d93576040516309bde33960e01b815260040160405180910390fd5b836001860381518110613da857613da8614f7f565b60200260200101519750505050505050505b9392505050565b6000818310613dd957613dd48284613ddf565b610c12565b610c1283835b604080516001602082015290810183905260608101829052600090608001613642565b828054828255906000526020600020908101928215613e64579160200282015b82811115613e64578251825473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03909116178255602090920191600190910190613e22565b50613e70929150613e74565b5090565b5b80821115613e705760008155600101613e75565b634e487b7160e01b600052604160045260246000fd5b6040516080810167ffffffffffffffff81118282101715613ec257613ec2613e89565b60405290565b60405160a0810167ffffffffffffffff81118282101715613ec257613ec2613e89565b60405160c0810167ffffffffffffffff81118282101715613ec257613ec2613e89565b6040805190810167ffffffffffffffff81118282101715613ec257613ec2613e89565b6040516060810167ffffffffffffffff81118282101715613ec257613ec2613e89565b604051601f8201601f1916810167ffffffffffffffff81118282101715613f7d57613f7d613e89565b604052919050565b600067ffffffffffffffff821115613f9f57613f9f613e89565b5060051b60200190565b6001600160a01b03811681146105dd57600080fd5b803567ffffffffffffffff81168114613fd657600080fd5b919050565b80151581146105dd57600080fd5b8035613fd681613fdb565b600067ffffffffffffffff82111561400e5761400e613e89565b50601f01601f191660200190565b600082601f83011261402d57600080fd5b813561404061403b82613ff4565b613f54565b81815284602083860101111561405557600080fd5b816020850160208301376000918101602001919091529392505050565b6000602080838503121561408557600080fd5b823567ffffffffffffffff8082111561409d57600080fd5b818501915085601f8301126140b157600080fd5b81356140bf61403b82613f85565b81815260059190911b830184019084810190888311156140de57600080fd5b8585015b83811015614184578035858111156140fa5760008081fd5b86016080818c03601f19018113156141125760008081fd5b61411a613e9f565b8983013561412781613fa9565b81526040614136848201613fbe565b8b83015260608085013561414981613fdb565b8383015292840135928984111561416257600091508182fd5b6141708f8d8688010161401c565b9083015250855250509186019186016140e2565b5098975050505050505050565b600060a082840312156141a357600080fd5b6141ab613ec8565b9050813581526141bd60208301613fbe565b60208201526141ce60408301613fbe565b60408201526141df60608301613fbe565b60608201526141f060808301613fbe565b608082015292915050565b8035613fd681613fa9565b600082601f83011261421757600080fd5b8135602061422761403b83613f85565b82815260059290921b8401810191818101908684111561424657600080fd5b8286015b848110156120c157803567ffffffffffffffff8082111561426b5760008081fd5b818901915060a080601f19848d030112156142865760008081fd5b61428e613ec8565b87840135838111156142a05760008081fd5b6142ae8d8a8388010161401c565b825250604080850135848111156142c55760008081fd5b6142d38e8b8389010161401c565b8a84015250606080860135858111156142ec5760008081fd5b6142fa8f8c838a010161401c565b838501525060809150818601358184015250828501359250838311156143205760008081fd5b61432e8d8a8588010161401c565b90820152865250505091830191830161424a565b6000610140828403121561435557600080fd5b61435d613eeb565b90506143698383614191565b815260a082013567ffffffffffffffff8082111561438657600080fd5b6143928583860161401c565b602084015260c08401359150808211156143ab57600080fd5b6143b78583860161401c565b60408401526143c860e085016141fb565b606084015261010084013560808401526101208401359150808211156143ed57600080fd5b506143fa84828501614206565b60a08301525092915050565b600082601f83011261441757600080fd5b8135602061442761403b83613f85565b82815260059290921b8401810191818101908684111561444657600080fd5b8286015b848110156120c157803567ffffffffffffffff81111561446a5760008081fd5b6144788986838b0101614342565b84525091830191830161444a565b600082601f83011261449757600080fd5b813560206144a761403b83613f85565b82815260059290921b840181019181810190868411156144c657600080fd5b8286015b848110156120c157803567ffffffffffffffff808211156144ea57600080fd5b818901915089603f8301126144fe57600080fd5b8582013561450e61403b82613f85565b81815260059190911b830160400190878101908c83111561452e57600080fd5b604085015b838110156145675780358581111561454a57600080fd5b6145598f6040838a010161401c565b845250918901918901614533565b508752505050928401925083016144ca565b600082601f83011261458a57600080fd5b8135602061459a61403b83613f85565b8083825260208201915060208460051b8701019350868411156145bc57600080fd5b602086015b848110156120c157803583529183019183016145c1565b600082601f8301126145e957600080fd5b813560206145f961403b83613f85565b82815260059290921b8401810191818101908684111561461857600080fd5b8286015b848110156120c157803567ffffffffffffffff8082111561463d5760008081fd5b818901915060a080601f19848d030112156146585760008081fd5b614660613ec8565b61466b888501613fbe565b8152604080850135848111156146815760008081fd5b61468f8e8b83890101614406565b8a84015250606080860135858111156146a85760008081fd5b6146b68f8c838a0101614486565b83850152506080915081860135858111156146d15760008081fd5b6146df8f8c838a0101614579565b918401919091525091909301359083015250835291830191830161461c565b600080604080848603121561471257600080fd5b833567ffffffffffffffff8082111561472a57600080fd5b614736878388016145d8565b945060209150818601358181111561474d57600080fd5b8601601f8101881361475e57600080fd5b803561476c61403b82613f85565b81815260059190911b8201840190848101908a83111561478b57600080fd5b8584015b83811015614817578035868111156147a75760008081fd5b8501603f81018d136147b95760008081fd5b878101356147c961403b82613f85565b81815260059190911b82018a0190898101908f8311156147e95760008081fd5b928b01925b828410156148075783358252928a0192908a01906147ee565b865250505091860191860161478f565b50809750505050505050509250929050565b60005b8381101561484457818101518382015260200161482c565b50506000910152565b60008151808452614865816020860160208601614829565b601f01601f19169290920160200192915050565b602081526000610c12602083018461484d565b8060608101831015610c1557600080fd5b60008083601f8401126148af57600080fd5b50813567ffffffffffffffff8111156148c757600080fd5b60208301915083602082850101111561382157600080fd5b60008083601f8401126148f157600080fd5b50813567ffffffffffffffff81111561490957600080fd5b6020830191508360208260051b850101111561382157600080fd5b60008060008060008060008060e0898b03121561494057600080fd5b61494a8a8a61488c565b9750606089013567ffffffffffffffff8082111561496757600080fd5b6149738c838d0161489d565b909950975060808b013591508082111561498c57600080fd5b6149988c838d016148df565b909750955060a08b01359150808211156149b157600080fd5b506149be8b828c016148df565b999c989b50969995989497949560c00135949350505050565b6000806000608084860312156149ec57600080fd5b6149f6858561488c565b9250606084013567ffffffffffffffff811115614a1257600080fd5b614a1e8682870161489d565b9497909650939450505050565b60008060408385031215614a3e57600080fd5b614a4783613fbe565b9150614a5560208401613fbe565b90509250929050565b634e487b7160e01b600052602160045260246000fd5b60048110614a8457614a84614a5e565b9052565b60208101610c158284614a74565b600060208284031215614aa857600080fd5b813567ffffffffffffffff811115614abf57600080fd5b820160a08185031215613dba57600080fd5b803563ffffffff81168114613fd657600080fd5b600060a08284031215614af757600080fd5b614aff613ec8565b8235614b0a81613fa9565b8152614b1860208401614ad1565b6020820152614b2960408401614ad1565b6040820152614b3a60608401614ad1565b60608201526080830135614b4d81613fa9565b60808201529392505050565b600080600060408486031215614b6e57600080fd5b833567ffffffffffffffff80821115614b8657600080fd5b614b9287838801614342565b94506020860135915080821115614ba857600080fd5b50614a1e868287016148df565b803560ff81168114613fd657600080fd5b600060208284031215614bd857600080fd5b610c1282614bb5565b60008151808452602080850194506020840160005b83811015614c1b5781516001600160a01b031687529582019590820190600101614bf6565b509495945050505050565b60208152600082518051602084015260ff602082015116604084015260ff604082015116606084015260608101511515608084015250602083015160c060a0840152614c7560e0840182614be1565b90506040840151601f198483030160c0850152614c928282614be1565b95945050505050565b60008060408385031215614cae57600080fd5b614cb783613fbe565b946020939093013593505050565b60008060208385031215614cd857600080fd5b823567ffffffffffffffff80821115614cf057600080fd5b818501915085601f830112614d0457600080fd5b813581811115614d1357600080fd5b8660208260061b8501011115614d2857600080fd5b60209290920196919550909350505050565b600060208284031215614d4c57600080fd5b610c1282613fbe565b602081526001600160a01b03825116602082015260208201511515604082015267ffffffffffffffff6040830151166060820152600060608301516080808401526136ae60a084018261484d565b600060208284031215614db557600080fd5b8135613dba81613fa9565b600082601f830112614dd157600080fd5b81356020614de161403b83613f85565b8083825260208201915060208460051b870101935086841115614e0357600080fd5b602086015b848110156120c1578035614e1b81613fa9565b8352918301918301614e08565b60006020808385031215614e3b57600080fd5b823567ffffffffffffffff80821115614e5357600080fd5b818501915085601f830112614e6757600080fd5b8135614e7561403b82613f85565b81815260059190911b83018401908481019088831115614e9457600080fd5b8585015b8381101561418457803585811115614eaf57600080fd5b860160c0818c03601f19011215614ec65760008081fd5b614ece613eeb565b8882013581526040614ee1818401614bb5565b8a8301526060614ef2818501614bb5565b8284015260809150614f05828501613fe9565b9083015260a08381013589811115614f1d5760008081fd5b614f2b8f8d83880101614dc0565b838501525060c0840135915088821115614f455760008081fd5b614f538e8c84870101614dc0565b9083015250845250918601918601614e98565b600060208284031215614f7857600080fd5b5035919050565b634e487b7160e01b600052603260045260246000fd5b80356001600160e01b0381168114613fd657600080fd5b600082601f830112614fbd57600080fd5b81356020614fcd61403b83613f85565b82815260069290921b84018101918181019086841115614fec57600080fd5b8286015b848110156120c157604081890312156150095760008081fd5b615011613f0e565b61501a82613fbe565b8152615027858301614f95565b81860152835291830191604001614ff0565b600082601f83011261504a57600080fd5b8135602061505a61403b83613f85565b82815260079290921b8401810191818101908684111561507957600080fd5b8286015b848110156120c15780880360808112156150975760008081fd5b61509f613f31565b6150a883613fbe565b8152604080601f19840112156150be5760008081fd5b6150c6613f0e565b92506150d3878501613fbe565b83526150e0818501613fbe565b838801528187019290925260608301359181019190915283529183019160800161507d565b6000602080838503121561511857600080fd5b823567ffffffffffffffff8082111561513057600080fd5b8185019150604080838803121561514657600080fd5b61514e613f0e565b83358381111561515d57600080fd5b84016040818a03121561516f57600080fd5b615177613f0e565b81358581111561518657600080fd5b8201601f81018b1361519757600080fd5b80356151a561403b82613f85565b81815260069190911b8201890190898101908d8311156151c457600080fd5b928a01925b828410156152145787848f0312156151e15760008081fd5b6151e9613f0e565b84356151f481613fa9565b8152615201858d01614f95565b818d0152825292870192908a01906151c9565b84525050508187013593508484111561522c57600080fd5b6152388a858401614fac565b818801528252508385013591508282111561525257600080fd5b61525e88838601615039565b85820152809550505050505092915050565b805160408084528151848201819052600092602091908201906060870190855b818110156152c757835180516001600160a01b031684528501516001600160e01b0316858401529284019291850191600101615290565b50508583015187820388850152805180835290840192506000918401905b80831015615321578351805167ffffffffffffffff1683528501516001600160e01b0316858301529284019260019290920191908501906152e5565b50979650505050505050565b602081526000610c126020830184615270565b67ffffffffffffffff8316815260608101613dba6020830184805167ffffffffffffffff908116835260209182015116910152565b634e487b7160e01b600052601160045260246000fd5b67ffffffffffffffff8181168382160190808211156153ac576153ac615375565b5092915050565b6000602080835260608451604080848701526153d26060870183615270565b87850151878203601f19016040890152805180835290860193506000918601905b8083101561418457845167ffffffffffffffff81511683528781015161543289850182805167ffffffffffffffff908116835260209182015116910152565b508401518287015293860193600192909201916080909101906153f3565b60006020828403121561546257600080fd5b813567ffffffffffffffff81111561547957600080fd5b6136ae848285016145d8565b81810381811115610c1557610c15615375565b634e487b7160e01b600052601260045260246000fd5b600067ffffffffffffffff808416806154c9576154c9615498565b92169190910692915050565b8082028115828204841417610c1557610c15615375565b805182526000602067ffffffffffffffff81840151168185015260408084015160a0604087015261552060a087018261484d565b905060608501518682036060880152615539828261484d565b608087810151898303918a01919091528051808352908601935060009250908501905b8083101561532157835180516001600160a01b031683528601518683015292850192600192909201919084019061555c565b602081526000610c1260208301846154ec565b6080815260006155b460808301876154ec565b61ffff9590951660208301525060408101929092526001600160a01b0316606090910152919050565b6000806000606084860312156155f257600080fd5b83516155fd81613fdb565b602085015190935067ffffffffffffffff81111561561a57600080fd5b8401601f8101861361562b57600080fd5b805161563961403b82613ff4565b81815287602083850101111561564e57600080fd5b61565f826020830160208601614829565b809450505050604084015190509250925092565b60006040828403121561568557600080fd5b61568d613f0e565b61569683613fbe565b8152602083013560208201528091505092915050565b600181811c908216806156c057607f821691505b6020821081036156e057634e487b7160e01b600052602260045260246000fd5b50919050565b6000602082840312156156f857600080fd5b8151613dba81613fdb565b601f821115610780576000816000526020600020601f850160051c8101602086101561572c5750805b601f850160051c820191505b8181101561574b57828155600101615738565b505050505050565b815167ffffffffffffffff81111561576d5761576d613e89565b6157818161577b84546156ac565b84615703565b602080601f8311600181146157b6576000841561579e5750858301515b600019600386901b1c1916600185901b17855561574b565b600085815260208120601f198616915b828110156157e5578886015182559484019460019091019084016157c6565b50858210156158035787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6000602080835283546001600160a01b038116602085015260ff8160a01c161515604085015267ffffffffffffffff8160a81c16606085015250600180850160808086015260008154615865816156ac565b8060a089015260c0600183166000811461588657600181146158a2576158d2565b60ff19841660c08b015260c083151560051b8b010194506158d2565b85600052602060002060005b848110156158c95781548c82018501529088019089016158ae565b8b0160c0019550505b50929998505050505050505050565b80820180821115610c1557610c15615375565b60ff8181168382160190811115610c1557610c15615375565b8183823760009101908152919050565b828152606082602083013760800192915050565b600067ffffffffffffffff8084168061594c5761594c615498565b92169190910492915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261598d57600080fd5b83018035915067ffffffffffffffff8211156159a857600080fd5b60200191503681900382131561382157600080fd5b60208101600583106159d1576159d1614a5e565b91905290565b60ff81811683821602908116908181146153ac576153ac615375565b600060a0820160ff881683526020878185015260a0604085015281875480845260c0860191508860005282600020935060005b81811015615a4b5784546001600160a01b031683526001948501949284019201615a26565b50508481036060860152865180825290820192508187019060005b81811015615a8b5782516001600160a01b031685529383019391830191600101615a66565b50505060ff851660808501525090506120c3565b600067ffffffffffffffff808616835280851660208401525060606040830152614c92606083018461484d565b8281526040602082015260006136ae604083018461484d565b67ffffffffffffffff848116825283166020820152606081016136ae6040830184614a74565b848152615b1b6020820185614a74565b608060408201526000615b31608083018561484d565b905082606083015295945050505050565b600060208284031215615b5457600080fd5b8151613dba81613fa9565b6020815260008251610100806020850152615b7e61012085018361484d565b91506020850151615b9b604086018267ffffffffffffffff169052565b5060408501516001600160a01b038116606086015250606085015160808501526080850151615bd560a08601826001600160a01b03169052565b5060a0850151601f19808685030160c0870152615bf2848361484d565b935060c08701519150808685030160e0870152615c0f848361484d565b935060e08701519150808685030183870152506120c3838261484d565b600060208284031215615c3e57600080fd5b5051919050565b848152600067ffffffffffffffff8086166020840152808516604084015250608060608301526120c3608083018461484d565b86815260c060208201526000615c9160c083018861484d565b6001600160a01b039690961660408301525067ffffffffffffffff9384166060820152608081019290925290911660a09091015292915050565b600082825180855260208086019550808260051b84010181860160005b84811015615d7d57601f19868403018952815160a08151818652615d0e8287018261484d565b9150508582015185820387870152615d26828261484d565b91505060408083015186830382880152615d40838261484d565b92505050606080830151818701525060808083015192508582038187015250615d69818361484d565b9a86019a9450505090830190600101615ce8565b5090979650505050505050565b602081526000610c126020830184615ccb565b60008282518085526020808601955060208260051b8401016020860160005b84811015615d7d57601f19868403018952615dd883835161484d565b98840198925090830190600101615dbc565b604081526000835180516040840152602081015167ffffffffffffffff80821660608601528060408401511660808601528060608401511660a08601528060808401511660c086015250505060208401516101408060e0850152615e5261018085018361484d565b915060408601517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08086850301610100870152615e8f848361484d565b935060608801519150615eae6101208701836001600160a01b03169052565b60808801518387015260a0880151925080868503016101608701525050615ed58282615ccb565b9150508281036020840152614c928185615d9d56fea164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CanOnlySelfCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"actual\",\"type\":\"bytes32\"}],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ExecutionError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"ForkedChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enumMultiOCR3Base.InvalidConfigErrorType\",\"name\":\"errorType\",\"type\":\"uint8\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"got\",\"type\":\"uint256\"}],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidEVMAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"internalType\":\"structOffRamp.Interval\",\"name\":\"interval\",\"type\":\"tuple\"}],\"name\":\"InvalidInterval\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"newLimit\",\"type\":\"uint256\"}],\"name\":\"InvalidManualExecutionGasLimit\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"messageDestChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidMessageDestChainSelector\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"newState\",\"type\":\"uint8\"}],\"name\":\"InvalidNewState\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRoot\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidStaticConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LeavesCannotBeEmpty\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ManualExecutionGasLimitMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"ManualExecutionNotYetEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"errorReason\",\"type\":\"bytes\"}],\"name\":\"MessageValidationError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonUniqueSignatures\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"notPool\",\"type\":\"address\"}],\"name\":\"NotACompatiblePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OracleCannotBeZeroAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ReceiverError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountReleased\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePre\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePost\",\"type\":\"uint256\"}],\"name\":\"ReleaseOrMintBalanceMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"name\":\"RootAlreadyCommitted\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"RootNotCommitted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignaturesOutOfRegistration\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"StaleCommitReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"StaticConfigCannotBeChanged\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"TokenDataMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"TokenHandlingError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnexpectedTokenData\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"WrongMessageLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WrongNumberOfSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroChainSelectorNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"AlreadyAttempted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"internalType\":\"structOffRamp.Interval\",\"name\":\"interval\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structOffRamp.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"report\",\"type\":\"tuple\"}],\"name\":\"CommitReportAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"DynamicConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"messageHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"name\":\"ExecutionStateChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"RootRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"SkippedAlreadyExecutedMessage\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SkippedReportExecution\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"sourceConfig\",\"type\":\"tuple\"}],\"name\":\"SourceChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainSelectorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"}],\"name\":\"StaticConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigUpdates\",\"type\":\"tuple[]\"}],\"name\":\"applySourceChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"destTokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structClient.Any2EVMMessage\",\"name\":\"\",\"type\":\"tuple\"}],\"name\":\"ccipReceive\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"rawVs\",\"type\":\"bytes32\"}],\"name\":\"commit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"execute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"bytes[]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[]\"}],\"name\":\"executeSingleMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"getExecutionState\",\"outputs\":[{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLatestPriceSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"getMerkleRoot\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"getSourceChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"isBlessed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"latestConfigDetails\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"n\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"}],\"internalType\":\"structMultiOCR3Base.ConfigInfo\",\"name\":\"configInfo\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfig\",\"name\":\"ocrConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage[]\",\"name\":\"messages\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[][]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[][]\"},{\"internalType\":\"bytes32[]\",\"name\":\"proofs\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"proofFlagBits\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.ExecutionReportSingleChain[]\",\"name\":\"reports\",\"type\":\"tuple[]\"},{\"internalType\":\"uint256[][]\",\"name\":\"gasLimitOverrides\",\"type\":\"uint256[][]\"}],\"name\":\"manuallyExecute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structOffRamp.UnblessedRoot[]\",\"name\":\"rootToReset\",\"type\":\"tuple[]\"}],\"name\":\"resetUnblessedRoots\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"setDynamicConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfigArgs[]\",\"name\":\"ocrConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"setOCR3Configs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x6101206040523480156200001257600080fd5b5060405162006d0d38038062006d0d8339810160408190526200003591620008c7565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf81620001fa565b5050466080525060208301516001600160a01b03161580620000ec575060408301516001600160a01b0316155b8062000103575060608301516001600160a01b0316155b1562000122576040516342bcdf7f60e11b815260040160405180910390fd5b82516001600160401b03166000036200014e5760405163c656089560e01b815260040160405180910390fd5b82516001600160401b0390811660a052602080850180516001600160a01b0390811660c05260408088018051831660e0526060808a01805185166101005283518b519098168852945184169587019590955251821690850152905116908201527f683eb52ee924eb817377cfa8f41f238f4bb7a877da5267869dfffbad85f564d89060800160405180910390a1620001e682620002a5565b620001f181620003c1565b50505062000c67565b336001600160a01b03821603620002545760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b0316620002ce576040516342bcdf7f60e11b815260040160405180910390fd5b80516004805460208085018051604080880180516060808b0180516001600160a01b039b8c166001600160c01b0319909a168a17600160a01b63ffffffff98891602176001600160c01b0316600160c01b948816949094026001600160e01b031693909317600160e01b93871693909302929092179098556080808b018051600580546001600160a01b031916918d169190911790558451988952955185169688019690965290518316918601919091525116938301939093529151909216908201527fa55bd56595c45f517e5967a3067f3dca684445a3080e7c04a4e0d5a40cda627d9060a00160405180910390a150565b60005b815181101562000666576000828281518110620003e557620003e562000a1d565b60200260200101519050600081602001519050806001600160401b0316600003620004235760405163c656089560e01b815260040160405180910390fd5b81516001600160a01b03166200044c576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160401b0381166000908152600660205260408120600181018054919291620004789062000a33565b80601f0160208091040260200160405190810160405280929190818152602001828054620004a69062000a33565b8015620004f75780601f10620004cb57610100808354040283529160200191620004f7565b820191906000526020600020905b815481529060010190602001808311620004d957829003601f168201915b5050505050905060008460600151905081516000036200059e57805160000362000534576040516342bcdf7f60e11b815260040160405180910390fd5b6001830162000544828262000ac4565b508254600160a81b600160e81b031916600160a81b1783556040516001600160401b03851681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1620005d9565b8080519060200120828051906020012014620005d95760405163c39a620560e01b81526001600160401b038516600482015260240162000083565b604080860151845487516001600160a01b03166001600160a01b0319921515600160a01b02929092166001600160a81b031990911617178455516001600160401b038516907f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b906200064d90869062000b90565b60405180910390a25050505050806001019050620003c4565b5050565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b0381118282101715620006a557620006a56200066a565b60405290565b604051601f8201601f191681016001600160401b0381118282101715620006d657620006d66200066a565b604052919050565b80516001600160401b0381168114620006f657600080fd5b919050565b6001600160a01b03811681146200071157600080fd5b50565b805163ffffffff81168114620006f657600080fd5b6000601f83601f8401126200073d57600080fd5b825160206001600160401b03808311156200075c576200075c6200066a565b8260051b6200076d838201620006ab565b93845286810183019383810190898611156200078857600080fd5b84890192505b85831015620008ba57825184811115620007a85760008081fd5b89016080601f19828d038101821315620007c25760008081fd5b620007cc62000680565b88840151620007db81620006fb565b81526040620007ec858201620006de565b8a8301526060808601518015158114620008065760008081fd5b838301529385015193898511156200081e5760008081fd5b84860195508f603f8701126200083657600094508485fd5b8a8601519450898511156200084f576200084f6200066a565b620008608b858f88011601620006ab565b93508484528f82868801011115620008785760008081fd5b60005b8581101562000898578681018301518582018d01528b016200087b565b5060009484018b0194909452509182015283525091840191908401906200078e565b9998505050505050505050565b6000806000838503610140811215620008df57600080fd5b6080811215620008ee57600080fd5b620008f862000680565b6200090386620006de565b815260208601516200091581620006fb565b602082015260408601516200092a81620006fb565b604082015260608601516200093f81620006fb565b6060820152935060a0607f19820112156200095957600080fd5b5060405160a081016001600160401b0380821183831017156200098057620009806200066a565b81604052608087015191506200099682620006fb565b818352620009a760a0880162000714565b6020840152620009ba60c0880162000714565b6040840152620009cd60e0880162000714565b60608401526101008701519150620009e582620006fb565b608083018290526101208701519294508083111562000a0357600080fd5b505062000a138682870162000729565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b600181811c9082168062000a4857607f821691505b60208210810362000a6957634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111562000abf576000816000526020600020601f850160051c8101602086101562000a9a5750805b601f850160051c820191505b8181101562000abb5782815560010162000aa6565b5050505b505050565b81516001600160401b0381111562000ae05762000ae06200066a565b62000af88162000af1845462000a33565b8462000a6f565b602080601f83116001811462000b30576000841562000b175750858301515b600019600386901b1c1916600185901b17855562000abb565b600085815260208120601f198616915b8281101562000b615788860151825594840194600190910190840162000b40565b508582101562000b805787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b602080825282546001600160a01b0381168383015260a081901c60ff161515604084015260a81c6001600160401b0316606083015260808083015260018084018054600093929190849062000be58162000a33565b8060a089015260c0600183166000811462000c09576001811462000c265762000c58565b60ff19841660c08b015260c083151560051b8b0101945062000c58565b85600052602060002060005b8481101562000c4f5781548c820185015290880190890162000c32565b8b0160c0019550505b50929998505050505050505050565b60805160a05160c05160e0516101005161603062000cdd600039600081816102660152612b27015260008181610237015261301b015260008181610208015281816109390152818161152201526125190152600081816101d801526127a60152600081816118ea015261193601526160306000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806385572ffb116100d8578063ccd37ba31161008c578063f2fde38b11610066578063f2fde38b14610583578063f716f99f14610596578063ff888fb1146105a957600080fd5b8063ccd37ba31461050b578063d2a15d3514610550578063e9d68a8e1461056357600080fd5b8063991a5018116100bd578063991a5018146104c5578063a80036b4146104d8578063c673e584146104eb57600080fd5b806385572ffb1461049c5780638da5cb5b146104aa57600080fd5b8063311cd5131161012f5780635e36480c116101145780635e36480c146103785780637437ff9f1461039857806379ba50971461049457600080fd5b8063311cd513146103495780633f4b04aa1461035c57600080fd5b806306285c691161016057806306285c69146101a4578063181f5a77146102ed5780632d04ab761461033657600080fd5b806304666f9c1461017c57806305d938b514610191575b600080fd5b61018f61018a3660046141ab565b6105cc565b005b61018f61019f366004614837565b6105e0565b61029660408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316815250905090565b6040516102e49190815167ffffffffffffffff1681526020808301516001600160a01b0390811691830191909152604080840151821690830152606092830151169181019190915260800190565b60405180910390f35b6103296040518060400160405280601181526020017f4f666652616d7020312e362e302d64657600000000000000000000000000000081525081565b6040516102e491906149b2565b61018f610344366004614a5d565b610785565b61018f610357366004614b10565b610c53565b60095460405167ffffffffffffffff90911681526020016102e4565b61038b610386366004614b64565b610cbc565b6040516102e49190614bc1565b6104376040805160a081018252600080825260208201819052918101829052606081018290526080810191909152506040805160a0810182526004546001600160a01b03808216835263ffffffff600160a01b83048116602085015278010000000000000000000000000000000000000000000000008304811694840194909452600160e01b9091049092166060820152600554909116608082015290565b6040516102e49190600060a0820190506001600160a01b03808451168352602084015163ffffffff808216602086015280604087015116604086015280606087015116606086015250508060808501511660808401525092915050565b61018f610d12565b61018f610177366004614bcf565b6000546040516001600160a01b0390911681526020016102e4565b61018f6104d3366004614c1e565b610dd0565b61018f6104e6366004614c92565b610de1565b6104fe6104f9366004614cff565b611154565b6040516102e49190614d5f565b610542610519366004614dd4565b67ffffffffffffffff919091166000908152600860209081526040808320938352929052205490565b6040519081526020016102e4565b61018f61055e366004614dfe565b6112b2565b610576610571366004614e73565b61136c565b6040516102e49190614e8e565b61018f610591366004614edc565b611479565b61018f6105a4366004614f61565b61148a565b6105bc6105b736600461509f565b6114cc565b60405190151581526020016102e4565b6105d461158d565b6105dd816115e9565b50565b6105e86118e7565b815181518114610624576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015610775576000848281518110610643576106436150b8565b6020026020010151905060008160200151519050600085848151811061066b5761066b6150b8565b60200260200101519050805182146106af576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b828110156107665760008282815181106106ce576106ce6150b8565b602002602001015190508060001461075d57846020015182815181106106f6576106f66150b8565b60200260200101516080015181101561075d5784516040517fc8e9605100000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260248101839052604481018290526064015b60405180910390fd5b506001016106b2565b50505050806001019050610627565b506107808383611968565b505050565b60006107938789018961523e565b805151519091501515806107ac57508051602001515115155b156108ac5760095460208a01359067ffffffffffffffff8083169116101561086b576009805467ffffffffffffffff191667ffffffffffffffff83161790556004805483516040517f3937306f0000000000000000000000000000000000000000000000000000000081526001600160a01b0390921692633937306f92610834929101615466565b600060405180830381600087803b15801561084e57600080fd5b505af1158015610862573d6000803e3d6000fd5b505050506108aa565b8160200151516000036108aa576040517f2261116700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b60005b816020015151811015610b9c576000826020015182815181106108d4576108d46150b8565b602090810291909101015180516040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815277ffffffffffffffff00000000000000000000000000000000608083901b166004820152919250906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632cbc26bb90602401602060405180830381865afa158015610980573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109a49190615479565b156109e7576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610754565b60006109f282611a18565b602084015151815491925067ffffffffffffffff908116600160a81b90920416141580610a36575060208084015190810151905167ffffffffffffffff9182169116115b15610a7657825160208401516040517feefb0cac000000000000000000000000000000000000000000000000000000008152610754929190600401615496565b604083015180610ab2576040517f504570e300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b835167ffffffffffffffff16600090815260086020908152604080832084845290915290205415610b255783516040517f32cf0cbf00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260248101829052604401610754565b6020808501510151610b389060016154e1565b82547fffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffff16600160a81b67ffffffffffffffff9283160217909255925116600090815260086020908152604080832094835293905291909120429055506001016108af565b507f3a3950e13dd607cc37980db0ef14266c40d2bba9c01b2e44bfe549808883095d81604051610bcc9190615509565b60405180910390a1610c4860008a8a8a8a8a8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808e0282810182019093528d82529093508d92508c9182918501908490808284376000920191909152508b9250611a7f915050565b505050505050505050565b610c93610c62828401846155a6565b6040805160008082526020820190925290610c8d565b6060815260200190600190039081610c785790505b50611968565b604080516000808252602082019092529050610cb6600185858585866000611a7f565b50505050565b6000610cca600160046155db565b6002610cd7608085615604565b67ffffffffffffffff16610ceb919061562b565b610cf58585611df6565b901c166003811115610d0957610d09614b97565b90505b92915050565b6001546001600160a01b03163314610d6c5760405162461bcd60e51b815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610754565b600080543373ffffffffffffffffffffffffffffffffffffffff19808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610dd861158d565b6105dd81611e3d565b333014610e1a576040517f371a732800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160008082526020820190925281610e57565b6040805180820190915260008082526020820152815260200190600190039081610e305790505b5060a08501515190915015610e8b57610e888460a00151856020015186606001518760000151602001518787611fa3565b90505b6040805160a0810182528551518152855160209081015167ffffffffffffffff1681830152808701518351600094840192610ec79291016149b2565b60408051601f19818403018152918152908252878101516020830152018390526005549091506001600160a01b03168015610fd4576040517f08d450a10000000000000000000000000000000000000000000000000000000081526001600160a01b038216906308d450a190610f419085906004016156e4565b600060405180830381600087803b158015610f5b57600080fd5b505af1925050508015610f6c575060015b610fd4573d808015610f9a576040519150601f19603f3d011682016040523d82523d6000602084013e610f9f565b606091505b50806040517f09c2532500000000000000000000000000000000000000000000000000000000815260040161075491906149b2565b604086015151158015610fe957506080860151155b80611000575060608601516001600160a01b03163b155b806110405750606086015161103e906001600160a01b03167f85572ffb000000000000000000000000000000000000000000000000000000006120c2565b155b1561104d57505050505050565b855160209081015167ffffffffffffffff1660009081526006909152604080822054608089015160608a015192517f3cf9798300000000000000000000000000000000000000000000000000000000815284936001600160a01b0390931692633cf97983926110c592899261138892916004016156f7565b6000604051808303816000875af11580156110e4573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261110c9190810190615733565b50915091508161114a57806040517f0a8d6e8c00000000000000000000000000000000000000000000000000000000815260040161075491906149b2565b5050505050505050565b6111976040805160e081019091526000606082018181526080830182905260a0830182905260c08301919091528190815260200160608152602001606081525090565b60ff808316600090815260026020818152604092839020835160e081018552815460608201908152600183015480881660808401526101008104881660a0840152620100009004909616151560c08201529485529182018054845181840281018401909552808552929385830193909283018282801561124057602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611222575b50505050508152602001600382018054806020026020016040519081016040528092919081815260200182805480156112a257602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611284575b5050505050815250509050919050565b6112ba61158d565b60005b818110156107805760008383838181106112d9576112d96150b8565b9050604002018036038101906112ef91906157c9565b90506112fe81602001516114cc565b61136357805167ffffffffffffffff1660009081526008602090815260408083208285018051855290835281842093909355915191519182527f202f1139a3e334b6056064c0e9b19fd07e44a88d8f6e5ded571b24cf8c371f12910160405180910390a15b506001016112bd565b604080516080808201835260008083526020808401829052838501829052606080850181905267ffffffffffffffff878116845260068352928690208651948501875280546001600160a01b0381168652600160a01b810460ff16151593860193909352600160a81b9092049092169483019490945260018401805493949293918401916113f990615802565b80601f016020809104026020016040519081016040528092919081815260200182805461142590615802565b80156112a25780601f10611447576101008083540402835291602001916112a2565b820191906000526020600020905b81548152906001019060200180831161145557505050919092525091949350505050565b61148161158d565b6105dd816120de565b61149261158d565b60005b81518110156114c8576114c08282815181106114b3576114b36150b8565b6020026020010151612194565b600101611495565b5050565b6040805180820182523081526020810183815291517f4d61677100000000000000000000000000000000000000000000000000000000815290516001600160a01b039081166004830152915160248201526000917f00000000000000000000000000000000000000000000000000000000000000001690634d61677190604401602060405180830381865afa158015611569573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d0c9190615479565b6000546001600160a01b031633146115e75760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610754565b565b60005b81518110156114c8576000828281518110611609576116096150b8565b602002602001015190506000816020015190508067ffffffffffffffff16600003611660576040517fc656089500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81516001600160a01b0316611688576040516342bcdf7f60e11b815260040160405180910390fd5b67ffffffffffffffff811660009081526006602052604081206001810180549192916116b390615802565b80601f01602080910402602001604051908101604052809291908181526020018280546116df90615802565b801561172c5780601f106117015761010080835404028352916020019161172c565b820191906000526020600020905b81548152906001019060200180831161170f57829003601f168201915b5050505050905060008460600151905081516000036117e4578051600003611767576040516342bcdf7f60e11b815260040160405180910390fd5b60018301611775828261588c565b5082547fffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffff16600160a81b17835560405167ffffffffffffffff851681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1611837565b8080519060200120828051906020012014611837576040517fc39a620500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff85166004820152602401610754565b604080860151845487516001600160a01b031673ffffffffffffffffffffffffffffffffffffffff19921515600160a01b02929092167fffffffffffffffffffffff000000000000000000000000000000000000000000909116171784555167ffffffffffffffff8516907f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b906118cf90869061594c565b60405180910390a250505050508060010190506115ec565b467f0000000000000000000000000000000000000000000000000000000000000000146115e7576040517f0f01ce850000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000006004820152466024820152604401610754565b81516000036119a2576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160408051600080825260208201909252911591905b8451811015611a1157611a098582815181106119d7576119d76150b8565b602002602001015184611a03578583815181106119f6576119f66150b8565b60200260200101516124c5565b836124c5565b6001016119b9565b5050505050565b67ffffffffffffffff811660009081526006602052604081208054600160a01b900460ff16610d0c576040517fed053c5900000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610754565b60ff87811660009081526002602090815260408083208151608081018352815481526001909101548086169382019390935261010083048516918101919091526201000090910490921615156060830152873590611ade8760a4615a1a565b9050826060015115611b26578451611af790602061562b565b8651611b0490602061562b565b611b0f9060a0615a1a565b611b199190615a1a565b611b239082615a1a565b90505b368114611b68576040517f8e1192e100000000000000000000000000000000000000000000000000000000815260048101829052366024820152604401610754565b5081518114611bb05781516040517f93df584c000000000000000000000000000000000000000000000000000000008152600481019190915260248101829052604401610754565b611bb86118e7565b60ff808a1660009081526003602090815260408083203384528252808320815180830190925280548086168352939491939092840191610100909104166002811115611c0657611c06614b97565b6002811115611c1757611c17614b97565b9052509050600281602001516002811115611c3457611c34614b97565b148015611c885750600260008b60ff1660ff168152602001908152602001600020600301816000015160ff1681548110611c7057611c706150b8565b6000918252602090912001546001600160a01b031633145b611cbe576040517fda0f08e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50816060015115611da0576020820151611cd9906001615a2d565b60ff16855114611d15576040517f71253a2500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8351855114611d50576040517fa75d88af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008787604051611d62929190615a46565b604051908190038120611d79918b90602001615a56565b604051602081830303815290604052805190602001209050611d9e8a82888888612dd5565b505b6040805182815260208a81013567ffffffffffffffff169082015260ff8b16917f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef0910160405180910390a2505050505050505050565b67ffffffffffffffff8216600090815260076020526040812081611e1b608085615a6a565b67ffffffffffffffff1681526020810191909152604001600020549392505050565b80516001600160a01b0316611e65576040516342bcdf7f60e11b815260040160405180910390fd5b80516004805460208085018051604080880180516060808b0180516001600160a01b039b8c167fffffffffffffffff000000000000000000000000000000000000000000000000909a168a17600160a01b63ffffffff988916021777ffffffffffffffffffffffffffffffffffffffffffffffff167801000000000000000000000000000000000000000000000000948816949094026001600160e01b031693909317600160e01b93871693909302929092179098556080808b0180516005805473ffffffffffffffffffffffffffffffffffffffff1916918d169190911790558451988952955185169688019690965290518316918601919091525116938301939093529151909216908201527fa55bd56595c45f517e5967a3067f3dca684445a3080e7c04a4e0d5a40cda627d9060a00160405180910390a150565b6060865167ffffffffffffffff811115611fbf57611fbf613fc2565b60405190808252806020026020018201604052801561200457816020015b6040805180820190915260008082526020820152815260200190600190039081611fdd5790505b50905060005b87518110156120b657612091888281518110612028576120286150b8565b6020026020010151888888888887818110612045576120456150b8565b90506020028101906120579190615a91565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612fba92505050565b8282815181106120a3576120a36150b8565b602090810291909101015260010161200a565b505b9695505050505050565b60006120cd8361335f565b8015610d095750610d0983836133c3565b336001600160a01b038216036121365760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610754565b6001805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b806040015160ff166000036121bf576000604051631b3fab5160e11b81526004016107549190615af6565b60208082015160ff8082166000908152600290935260408320600181015492939092839216900361222c57606084015160018201805491151562010000027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff909216919091179055612281565b6060840151600182015460ff6201000090910416151590151514612281576040517f87f6037c00000000000000000000000000000000000000000000000000000000815260ff84166004820152602401610754565b60a0840151805161010010156122ad576001604051631b3fab5160e11b81526004016107549190615af6565b612313848460030180548060200260200160405190810160405280929190818152602001828054801561230957602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116122eb575b505050505061347e565b84606001511561243a576123818484600201805480602002602001604051908101604052809291908181526020018280548015612309576020028201919060005260206000209081546001600160a01b031681526001909101906020018083116122eb57505050505061347e565b6080850151805161010010156123ad576002604051631b3fab5160e11b81526004016107549190615af6565b60408601516123bd906003615b10565b60ff168151116123e3576003604051631b3fab5160e11b81526004016107549190615af6565b80516001840180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1661010060ff84160217905561242b9060028601906020840190613f3b565b50612438858260016134e7565b505b612446848260026134e7565b805161245b9060038501906020840190613f3b565b5060408581015160018401805460ff191660ff8316179055865180855560a088015192517fab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f547936124b49389939260028a01929190615b2c565b60405180910390a1611a118461365b565b815181516040517f2cbc26bb000000000000000000000000000000000000000000000000000000008152608083901b77ffffffffffffffff00000000000000000000000000000000166004820152901515907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632cbc26bb90602401602060405180830381865afa158015612568573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061258c9190615479565b156126185780156125d5576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff83166004820152602401610754565b60405167ffffffffffffffff831681527faab522ed53d887e56ed53dd37398a01aeef6a58e0fa77c2173beb9512d8949339060200160405180910390a150505050565b600061262383611a18565b600101805461263190615802565b80601f016020809104026020016040519081016040528092919081815260200182805461265d90615802565b80156126aa5780601f1061267f576101008083540402835291602001916126aa565b820191906000526020600020905b81548152906001019060200180831161268d57829003601f168201915b505050602088015151929350505060008190036126f2576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8560400151518114612730576040517f57e0e08300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008167ffffffffffffffff81111561274b5761274b613fc2565b604051908082528060200260200182016040528015612774578160200160208202803683370190505b50905060005b8281101561285d5760008860200151828151811061279a5761279a6150b8565b602002602001015190507f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681600001516040015167ffffffffffffffff161461282d57805160409081015190517f38432a2200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610754565b6128378186613677565b838381518110612849576128496150b8565b60209081029190910101525060010161277a565b50600061287486838a606001518b60800151613799565b9050806000036128bc576040517f7dd17a7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff87166004820152602401610754565b60005b83811015610c485760005a905060008a6020015183815181106128e4576128e46150b8565b6020026020010151905060006129028a836000015160600151610cbc565b9050600081600381111561291857612918614b97565b14806129355750600381600381111561293357612933614b97565b145b61298d578151606001516040805167ffffffffffffffff808e16825290921660208301527f3b575419319662b2a6f5e2467d84521517a3382b908eb3d557bb3fdb0c50e23c91015b60405180910390a1505050612dcd565b8815612a5d57600454600090600160a01b900463ffffffff166129b087426155db565b11905080806129d0575060038260038111156129ce576129ce614b97565b145b612a12576040517fa9cfc86200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8c166004820152602401610754565b8b8581518110612a2457612a246150b8565b6020026020010151600014612a57578b8581518110612a4557612a456150b8565b60200260200101518360800181815250505b50612abe565b6000816003811115612a7157612a71614b97565b14612abe578151606001516040805167ffffffffffffffff808e16825290921660208301527f3ef2a99c550a751d4b0b261268f05a803dfb049ab43616a1ffb388f61fe65120910161297d565b81516080015167ffffffffffffffff1615612bad576000816003811115612ae757612ae7614b97565b03612bad5781516080015160208301516040517fe0e03cae0000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169263e0e03cae92612b5e928f929190600401615bd8565b6020604051808303816000875af1158015612b7d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ba19190615479565b612bad57505050612dcd565b60008c604001518581518110612bc557612bc56150b8565b6020026020010151905080518360a001515114612c29578251606001516040517f1cfe6d8b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808e1660048301529091166024820152604401610754565b612c3d8b84600001516060015160016137ef565b600080612c4a8584613897565b91509150612c618d866000015160600151846137ef565b8b15612cd1576003826003811115612c7b57612c7b614b97565b03612cd1576000846003811115612c9457612c94614b97565b14612cd1578451516040517f2b11b8d900000000000000000000000000000000000000000000000000000000815261075491908390600401615c05565b6002826003811115612ce557612ce5614b97565b14612d3f576003826003811115612cfe57612cfe614b97565b14612d3f578451606001516040517f926c5a3e000000000000000000000000000000000000000000000000000000008152610754918f918590600401615c1e565b84600001516000015185600001516060015167ffffffffffffffff168e67ffffffffffffffff167f05665fe9ad095383d018353f4cbcba77e84db27dd215081bbf7cdf9ae6fbe48b8c8b81518110612d9957612d996150b8565b602002602001015186865a612dae908e6155db565b604051612dbe9493929190615c44565b60405180910390a45050505050505b6001016128bf565b8251600090815b8181101561114a576000600188868460208110612dfb57612dfb6150b8565b612e0891901a601b615a2d565b898581518110612e1a57612e1a6150b8565b6020026020010151898681518110612e3457612e346150b8565b602002602001015160405160008152602001604052604051612e72949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015612e94573d6000803e3d6000fd5b505060408051601f1981015160ff808e166000908152600360209081528582206001600160a01b03851683528152858220858701909652855480841686529397509095509293928401916101009004166002811115612ef557612ef5614b97565b6002811115612f0657612f06614b97565b9052509050600181602001516002811115612f2357612f23614b97565b14612f5a576040517fca31867a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051600160ff9091161b851615612f9d576040517ff67bc7c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806000015160ff166001901b851794505050806001019050612ddc565b60408051808201909152600080825260208201526000612fdd8760200151613961565b6040517fbbe4f6db0000000000000000000000000000000000000000000000000000000081526001600160a01b0380831660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063bbe4f6db90602401602060405180830381865afa158015613062573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130869190615c7b565b90506001600160a01b03811615806130ce57506130cc6001600160a01b0382167faff2afbf000000000000000000000000000000000000000000000000000000006120c2565b155b15613110576040517fae9b4ce90000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152602401610754565b60045460009081906131329089908690600160e01b900463ffffffff16613a07565b9150915060008060006131ff6040518061010001604052808e81526020018c67ffffffffffffffff1681526020018d6001600160a01b031681526020018f606001518152602001896001600160a01b031681526020018f6000015181526020018f6040015181526020018b8152506040516024016131b09190615c98565b60408051601f198184030181529190526020810180516001600160e01b03167f390775370000000000000000000000000000000000000000000000000000000017905287866113886084613b35565b9250925092508261323e57816040517fe1cd550900000000000000000000000000000000000000000000000000000000815260040161075491906149b2565b81516020146132865781516040517f78ef8024000000000000000000000000000000000000000000000000000000008152602060048201526024810191909152604401610754565b60008280602001905181019061329c9190615d65565b9050866001600160a01b03168c6001600160a01b0316146133315760006132cd8d8a6132c8868a6155db565b613a07565b509050868110806132e75750816132e488836155db565b14155b1561332f576040517fa966e21f000000000000000000000000000000000000000000000000000000008152600481018390526024810188905260448101829052606401610754565b505b604080518082019091526001600160a01b039098168852602088015250949550505050505095945050505050565b600061338b827f01ffc9a7000000000000000000000000000000000000000000000000000000006133c3565b8015610d0c57506133bc827fffffffff000000000000000000000000000000000000000000000000000000006133c3565b1592915050565b6040517fffffffff0000000000000000000000000000000000000000000000000000000082166024820152600090819060440160408051601f19818403018152919052602080820180516001600160e01b03167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825192935060009283928392909183918a617530fa92503d91506000519050828015613467575060208210155b80156134735750600081115b979650505050505050565b60005b81518110156107805760ff8316600090815260036020526040812083519091908490849081106134b3576134b36150b8565b6020908102919091018101516001600160a01b03168252810191909152604001600020805461ffff19169055600101613481565b60005b8251811015610cb6576000838281518110613507576135076150b8565b602002602001015190506000600281111561352457613524614b97565b60ff80871660009081526003602090815260408083206001600160a01b0387168452909152902054610100900416600281111561356357613563614b97565b14613584576004604051631b3fab5160e11b81526004016107549190615af6565b6001600160a01b0381166135c4576040517fd6c62c9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052808360ff1681526020018460028111156135ea576135ea614b97565b905260ff80871660009081526003602090815260408083206001600160a01b0387168452825290912083518154931660ff198416811782559184015190929091839161ffff19161761010083600281111561364757613647614b97565b0217905550905050508060010190506134ea565b60ff81166105dd576009805467ffffffffffffffff1916905550565b8151602080820151604092830151925160009384936136bd937f2425b0b9f9054c76ff151b0a175b18f37a4a4e82013a72e9f15c9caa095ed21f93909291889101615d7e565b60408051601f1981840301815290829052805160209182012086518051888401516060808b0151908401516080808d015195015195976137069794969395929491939101615db1565b604051602081830303815290604052805190602001208560400151805190602001208660a0015160405160200161373d9190615ec3565b60408051601f198184030181528282528051602091820120908301969096528101939093526060830191909152608082015260a081019190915260c0015b60405160208183030381529060405280519060200120905092915050565b6000806137a7858585613c5b565b90506137b2816114cc565b6137c05760009150506137e7565b67ffffffffffffffff86166000908152600860209081526040808320938352929052205490505b949350505050565b600060026137fe608085615604565b67ffffffffffffffff16613812919061562b565b905060006138208585611df6565b90508161382f600160046155db565b901b19168183600381111561384657613846614b97565b67ffffffffffffffff871660009081526007602052604081209190921b92909217918291613875608088615a6a565b67ffffffffffffffff1681526020810191909152604001600020555050505050565b6040517fa80036b4000000000000000000000000000000000000000000000000000000008152600090606090309063a80036b4906138db9087908790600401615f23565b600060405180830381600087803b1580156138f557600080fd5b505af1925050508015613906575060015b613945573d808015613934576040519150601f19603f3d011682016040523d82523d6000602084013e613939565b606091505b5060039250905061395a565b50506040805160208101909152600081526002905b9250929050565b600081516020146139a057816040517f8d666f6000000000000000000000000000000000000000000000000000000000815260040161075491906149b2565b6000828060200190518101906139b69190615d65565b90506001600160a01b038111806139ce575061040081105b15610d0c57826040517f8d666f6000000000000000000000000000000000000000000000000000000000815260040161075491906149b2565b6000806000806000613a8188604051602401613a3291906001600160a01b0391909116815260200190565b60408051601f198184030181529190526020810180516001600160e01b03167f70a082310000000000000000000000000000000000000000000000000000000017905288886113886084613b35565b92509250925082613ac057816040517fe1cd550900000000000000000000000000000000000000000000000000000000815260040161075491906149b2565b6020825114613b085781516040517f78ef8024000000000000000000000000000000000000000000000000000000008152602060048201526024810191909152604401610754565b81806020019051810190613b1c9190615d65565b613b2682886155db565b94509450505050935093915050565b6000606060008361ffff1667ffffffffffffffff811115613b5857613b58613fc2565b6040519080825280601f01601f191660200182016040528015613b82576020820181803683370190505b509150863b613bb5577f0c3b563c0000000000000000000000000000000000000000000000000000000060005260046000fd5b5a85811015613be8577fafa32a2c0000000000000000000000000000000000000000000000000000000060005260046000fd5b8590036040810481038710613c21577f37c3be290000000000000000000000000000000000000000000000000000000060005260046000fd5b505a6000808a5160208c0160008c8cf193505a900390503d84811115613c445750835b808352806000602085013e50955095509592505050565b8251825160009190818303613c9c576040517f11a6b26400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6101018211801590613cb057506101018111155b613ccd576040516309bde33960e01b815260040160405180910390fd5b60001982820101610100811115613cf7576040516309bde33960e01b815260040160405180910390fd5b80600003613d245786600081518110613d1257613d126150b8565b60200260200101519350505050613ef3565b60008167ffffffffffffffff811115613d3f57613d3f613fc2565b604051908082528060200260200182016040528015613d68578160200160208202803683370190505b50905060008080805b85811015613e925760006001821b8b811603613dcc5788851015613db5578c5160018601958e918110613da657613da66150b8565b60200260200101519050613dee565b8551600185019487918110613da657613da66150b8565b8b5160018401938d918110613de357613de36150b8565b602002602001015190505b600089861015613e1e578d5160018701968f918110613e0f57613e0f6150b8565b60200260200101519050613e40565b8651600186019588918110613e3557613e356150b8565b602002602001015190505b82851115613e61576040516309bde33960e01b815260040160405180910390fd5b613e6b8282613efa565b878481518110613e7d57613e7d6150b8565b60209081029190910101525050600101613d71565b506001850382148015613ea457508683145b8015613eaf57508581145b613ecc576040516309bde33960e01b815260040160405180910390fd5b836001860381518110613ee157613ee16150b8565b60200260200101519750505050505050505b9392505050565b6000818310613f1257613f0d8284613f18565b610d09565b610d0983835b60408051600160208201529081018390526060810182905260009060800161377b565b828054828255906000526020600020908101928215613f9d579160200282015b82811115613f9d578251825473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03909116178255602090920191600190910190613f5b565b50613fa9929150613fad565b5090565b5b80821115613fa95760008155600101613fae565b634e487b7160e01b600052604160045260246000fd5b6040516080810167ffffffffffffffff81118282101715613ffb57613ffb613fc2565b60405290565b60405160a0810167ffffffffffffffff81118282101715613ffb57613ffb613fc2565b60405160c0810167ffffffffffffffff81118282101715613ffb57613ffb613fc2565b6040805190810167ffffffffffffffff81118282101715613ffb57613ffb613fc2565b6040516060810167ffffffffffffffff81118282101715613ffb57613ffb613fc2565b604051601f8201601f1916810167ffffffffffffffff811182821017156140b6576140b6613fc2565b604052919050565b600067ffffffffffffffff8211156140d8576140d8613fc2565b5060051b60200190565b6001600160a01b03811681146105dd57600080fd5b803567ffffffffffffffff8116811461410f57600080fd5b919050565b80151581146105dd57600080fd5b803561410f81614114565b600067ffffffffffffffff82111561414757614147613fc2565b50601f01601f191660200190565b600082601f83011261416657600080fd5b81356141796141748261412d565b61408d565b81815284602083860101111561418e57600080fd5b816020850160208301376000918101602001919091529392505050565b600060208083850312156141be57600080fd5b823567ffffffffffffffff808211156141d657600080fd5b818501915085601f8301126141ea57600080fd5b81356141f8614174826140be565b81815260059190911b8301840190848101908883111561421757600080fd5b8585015b838110156142bd578035858111156142335760008081fd5b86016080818c03601f190181131561424b5760008081fd5b614253613fd8565b89830135614260816140e2565b8152604061426f8482016140f7565b8b83015260608085013561428281614114565b8383015292840135928984111561429b57600091508182fd5b6142a98f8d86880101614155565b90830152508552505091860191860161421b565b5098975050505050505050565b600060a082840312156142dc57600080fd5b6142e4614001565b9050813581526142f6602083016140f7565b6020820152614307604083016140f7565b6040820152614318606083016140f7565b6060820152614329608083016140f7565b608082015292915050565b803561410f816140e2565b600082601f83011261435057600080fd5b81356020614360614174836140be565b82815260059290921b8401810191818101908684111561437f57600080fd5b8286015b848110156120b657803567ffffffffffffffff808211156143a45760008081fd5b818901915060a080601f19848d030112156143bf5760008081fd5b6143c7614001565b87840135838111156143d95760008081fd5b6143e78d8a83880101614155565b825250604080850135848111156143fe5760008081fd5b61440c8e8b83890101614155565b8a84015250606080860135858111156144255760008081fd5b6144338f8c838a0101614155565b838501525060809150818601358184015250828501359250838311156144595760008081fd5b6144678d8a85880101614155565b908201528652505050918301918301614383565b6000610140828403121561448e57600080fd5b614496614024565b90506144a283836142ca565b815260a082013567ffffffffffffffff808211156144bf57600080fd5b6144cb85838601614155565b602084015260c08401359150808211156144e457600080fd5b6144f085838601614155565b604084015261450160e08501614334565b6060840152610100840135608084015261012084013591508082111561452657600080fd5b506145338482850161433f565b60a08301525092915050565b600082601f83011261455057600080fd5b81356020614560614174836140be565b82815260059290921b8401810191818101908684111561457f57600080fd5b8286015b848110156120b657803567ffffffffffffffff8111156145a35760008081fd5b6145b18986838b010161447b565b845250918301918301614583565b600082601f8301126145d057600080fd5b813560206145e0614174836140be565b82815260059290921b840181019181810190868411156145ff57600080fd5b8286015b848110156120b657803567ffffffffffffffff8082111561462357600080fd5b818901915089603f83011261463757600080fd5b85820135614647614174826140be565b81815260059190911b830160400190878101908c83111561466757600080fd5b604085015b838110156146a05780358581111561468357600080fd5b6146928f6040838a0101614155565b84525091890191890161466c565b50875250505092840192508301614603565b600082601f8301126146c357600080fd5b813560206146d3614174836140be565b8083825260208201915060208460051b8701019350868411156146f557600080fd5b602086015b848110156120b657803583529183019183016146fa565b600082601f83011261472257600080fd5b81356020614732614174836140be565b82815260059290921b8401810191818101908684111561475157600080fd5b8286015b848110156120b657803567ffffffffffffffff808211156147765760008081fd5b818901915060a080601f19848d030112156147915760008081fd5b614799614001565b6147a48885016140f7565b8152604080850135848111156147ba5760008081fd5b6147c88e8b8389010161453f565b8a84015250606080860135858111156147e15760008081fd5b6147ef8f8c838a01016145bf565b838501525060809150818601358581111561480a5760008081fd5b6148188f8c838a01016146b2565b9184019190915250919093013590830152508352918301918301614755565b600080604080848603121561484b57600080fd5b833567ffffffffffffffff8082111561486357600080fd5b61486f87838801614711565b945060209150818601358181111561488657600080fd5b8601601f8101881361489757600080fd5b80356148a5614174826140be565b81815260059190911b8201840190848101908a8311156148c457600080fd5b8584015b83811015614950578035868111156148e05760008081fd5b8501603f81018d136148f25760008081fd5b87810135614902614174826140be565b81815260059190911b82018a0190898101908f8311156149225760008081fd5b928b01925b828410156149405783358252928a0192908a0190614927565b86525050509186019186016148c8565b50809750505050505050509250929050565b60005b8381101561497d578181015183820152602001614965565b50506000910152565b6000815180845261499e816020860160208601614962565b601f01601f19169290920160200192915050565b602081526000610d096020830184614986565b8060608101831015610d0c57600080fd5b60008083601f8401126149e857600080fd5b50813567ffffffffffffffff811115614a0057600080fd5b60208301915083602082850101111561395a57600080fd5b60008083601f840112614a2a57600080fd5b50813567ffffffffffffffff811115614a4257600080fd5b6020830191508360208260051b850101111561395a57600080fd5b60008060008060008060008060e0898b031215614a7957600080fd5b614a838a8a6149c5565b9750606089013567ffffffffffffffff80821115614aa057600080fd5b614aac8c838d016149d6565b909950975060808b0135915080821115614ac557600080fd5b614ad18c838d01614a18565b909750955060a08b0135915080821115614aea57600080fd5b50614af78b828c01614a18565b999c989b50969995989497949560c00135949350505050565b600080600060808486031215614b2557600080fd5b614b2f85856149c5565b9250606084013567ffffffffffffffff811115614b4b57600080fd5b614b57868287016149d6565b9497909650939450505050565b60008060408385031215614b7757600080fd5b614b80836140f7565b9150614b8e602084016140f7565b90509250929050565b634e487b7160e01b600052602160045260246000fd5b60048110614bbd57614bbd614b97565b9052565b60208101610d0c8284614bad565b600060208284031215614be157600080fd5b813567ffffffffffffffff811115614bf857600080fd5b820160a08185031215613ef357600080fd5b803563ffffffff8116811461410f57600080fd5b600060a08284031215614c3057600080fd5b614c38614001565b8235614c43816140e2565b8152614c5160208401614c0a565b6020820152614c6260408401614c0a565b6040820152614c7360608401614c0a565b60608201526080830135614c86816140e2565b60808201529392505050565b600080600060408486031215614ca757600080fd5b833567ffffffffffffffff80821115614cbf57600080fd5b614ccb8783880161447b565b94506020860135915080821115614ce157600080fd5b50614b5786828701614a18565b803560ff8116811461410f57600080fd5b600060208284031215614d1157600080fd5b610d0982614cee565b60008151808452602080850194506020840160005b83811015614d545781516001600160a01b031687529582019590820190600101614d2f565b509495945050505050565b60208152600082518051602084015260ff602082015116604084015260ff604082015116606084015260608101511515608084015250602083015160c060a0840152614dae60e0840182614d1a565b90506040840151601f198483030160c0850152614dcb8282614d1a565b95945050505050565b60008060408385031215614de757600080fd5b614df0836140f7565b946020939093013593505050565b60008060208385031215614e1157600080fd5b823567ffffffffffffffff80821115614e2957600080fd5b818501915085601f830112614e3d57600080fd5b813581811115614e4c57600080fd5b8660208260061b8501011115614e6157600080fd5b60209290920196919550909350505050565b600060208284031215614e8557600080fd5b610d09826140f7565b602081526001600160a01b03825116602082015260208201511515604082015267ffffffffffffffff6040830151166060820152600060608301516080808401526137e760a0840182614986565b600060208284031215614eee57600080fd5b8135613ef3816140e2565b600082601f830112614f0a57600080fd5b81356020614f1a614174836140be565b8083825260208201915060208460051b870101935086841115614f3c57600080fd5b602086015b848110156120b6578035614f54816140e2565b8352918301918301614f41565b60006020808385031215614f7457600080fd5b823567ffffffffffffffff80821115614f8c57600080fd5b818501915085601f830112614fa057600080fd5b8135614fae614174826140be565b81815260059190911b83018401908481019088831115614fcd57600080fd5b8585015b838110156142bd57803585811115614fe857600080fd5b860160c0818c03601f19011215614fff5760008081fd5b615007614024565b888201358152604061501a818401614cee565b8a830152606061502b818501614cee565b828401526080915061503e828501614122565b9083015260a083810135898111156150565760008081fd5b6150648f8d83880101614ef9565b838501525060c084013591508882111561507e5760008081fd5b61508c8e8c84870101614ef9565b9083015250845250918601918601614fd1565b6000602082840312156150b157600080fd5b5035919050565b634e487b7160e01b600052603260045260246000fd5b80356001600160e01b038116811461410f57600080fd5b600082601f8301126150f657600080fd5b81356020615106614174836140be565b82815260069290921b8401810191818101908684111561512557600080fd5b8286015b848110156120b657604081890312156151425760008081fd5b61514a614047565b615153826140f7565b81526151608583016150ce565b81860152835291830191604001615129565b600082601f83011261518357600080fd5b81356020615193614174836140be565b82815260079290921b840181019181810190868411156151b257600080fd5b8286015b848110156120b65780880360808112156151d05760008081fd5b6151d861406a565b6151e1836140f7565b8152604080601f19840112156151f75760008081fd5b6151ff614047565b925061520c8785016140f7565b83526152198185016140f7565b83880152818701929092526060830135918101919091528352918301916080016151b6565b6000602080838503121561525157600080fd5b823567ffffffffffffffff8082111561526957600080fd5b8185019150604080838803121561527f57600080fd5b615287614047565b83358381111561529657600080fd5b84016040818a0312156152a857600080fd5b6152b0614047565b8135858111156152bf57600080fd5b8201601f81018b136152d057600080fd5b80356152de614174826140be565b81815260069190911b8201890190898101908d8311156152fd57600080fd5b928a01925b8284101561534d5787848f03121561531a5760008081fd5b615322614047565b843561532d816140e2565b815261533a858d016150ce565b818d0152825292870192908a0190615302565b84525050508187013593508484111561536557600080fd5b6153718a8584016150e5565b818801528252508385013591508282111561538b57600080fd5b61539788838601615172565b85820152809550505050505092915050565b805160408084528151848201819052600092602091908201906060870190855b8181101561540057835180516001600160a01b031684528501516001600160e01b03168584015292840192918501916001016153c9565b50508583015187820388850152805180835290840192506000918401905b8083101561545a578351805167ffffffffffffffff1683528501516001600160e01b03168583015292840192600192909201919085019061541e565b50979650505050505050565b602081526000610d0960208301846153a9565b60006020828403121561548b57600080fd5b8151613ef381614114565b67ffffffffffffffff8316815260608101613ef36020830184805167ffffffffffffffff908116835260209182015116910152565b634e487b7160e01b600052601160045260246000fd5b67ffffffffffffffff818116838216019080821115615502576155026154cb565b5092915050565b60006020808352606084516040808487015261552860608701836153a9565b87850151878203601f19016040890152805180835290860193506000918601905b808310156142bd57845167ffffffffffffffff81511683528781015161558889850182805167ffffffffffffffff908116835260209182015116910152565b50840151828701529386019360019290920191608090910190615549565b6000602082840312156155b857600080fd5b813567ffffffffffffffff8111156155cf57600080fd5b6137e784828501614711565b81810381811115610d0c57610d0c6154cb565b634e487b7160e01b600052601260045260246000fd5b600067ffffffffffffffff8084168061561f5761561f6155ee565b92169190910692915050565b8082028115828204841417610d0c57610d0c6154cb565b805182526000602067ffffffffffffffff81840151168185015260408084015160a0604087015261567660a0870182614986565b90506060850151868203606088015261568f8282614986565b608087810151898303918a01919091528051808352908601935060009250908501905b8083101561545a57835180516001600160a01b03168352860151868301529285019260019290920191908401906156b2565b602081526000610d096020830184615642565b60808152600061570a6080830187615642565b61ffff9590951660208301525060408101929092526001600160a01b0316606090910152919050565b60008060006060848603121561574857600080fd5b835161575381614114565b602085015190935067ffffffffffffffff81111561577057600080fd5b8401601f8101861361578157600080fd5b805161578f6141748261412d565b8181528760208385010111156157a457600080fd5b6157b5826020830160208601614962565b809450505050604084015190509250925092565b6000604082840312156157db57600080fd5b6157e3614047565b6157ec836140f7565b8152602083013560208201528091505092915050565b600181811c9082168061581657607f821691505b60208210810361583657634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115610780576000816000526020600020601f850160051c810160208610156158655750805b601f850160051c820191505b8181101561588457828155600101615871565b505050505050565b815167ffffffffffffffff8111156158a6576158a6613fc2565b6158ba816158b48454615802565b8461583c565b602080601f8311600181146158ef57600084156158d75750858301515b600019600386901b1c1916600185901b178555615884565b600085815260208120601f198616915b8281101561591e578886015182559484019460019091019084016158ff565b508582101561593c5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6000602080835283546001600160a01b038116602085015260ff8160a01c161515604085015267ffffffffffffffff8160a81c1660608501525060018085016080808601526000815461599e81615802565b8060a089015260c060018316600081146159bf57600181146159db57615a0b565b60ff19841660c08b015260c083151560051b8b01019450615a0b565b85600052602060002060005b84811015615a025781548c82018501529088019089016159e7565b8b0160c0019550505b50929998505050505050505050565b80820180821115610d0c57610d0c6154cb565b60ff8181168382160190811115610d0c57610d0c6154cb565b8183823760009101908152919050565b828152606082602083013760800192915050565b600067ffffffffffffffff80841680615a8557615a856155ee565b92169190910492915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112615ac657600080fd5b83018035915067ffffffffffffffff821115615ae157600080fd5b60200191503681900382131561395a57600080fd5b6020810160058310615b0a57615b0a614b97565b91905290565b60ff8181168382160290811690818114615502576155026154cb565b600060a0820160ff881683526020878185015260a0604085015281875480845260c0860191508860005282600020935060005b81811015615b845784546001600160a01b031683526001948501949284019201615b5f565b50508481036060860152865180825290820192508187019060005b81811015615bc45782516001600160a01b031685529383019391830191600101615b9f565b50505060ff851660808501525090506120b8565b600067ffffffffffffffff808616835280851660208401525060606040830152614dcb6060830184614986565b8281526040602082015260006137e76040830184614986565b67ffffffffffffffff848116825283166020820152606081016137e76040830184614bad565b848152615c546020820185614bad565b608060408201526000615c6a6080830185614986565b905082606083015295945050505050565b600060208284031215615c8d57600080fd5b8151613ef3816140e2565b6020815260008251610100806020850152615cb7610120850183614986565b91506020850151615cd4604086018267ffffffffffffffff169052565b5060408501516001600160a01b038116606086015250606085015160808501526080850151615d0e60a08601826001600160a01b03169052565b5060a0850151601f19808685030160c0870152615d2b8483614986565b935060c08701519150808685030160e0870152615d488483614986565b935060e08701519150808685030183870152506120b88382614986565b600060208284031215615d7757600080fd5b5051919050565b848152600067ffffffffffffffff8086166020840152808516604084015250608060608301526120b86080830184614986565b86815260c060208201526000615dca60c0830188614986565b6001600160a01b039690961660408301525067ffffffffffffffff9384166060820152608081019290925290911660a09091015292915050565b600082825180855260208086019550808260051b84010181860160005b84811015615eb657601f19868403018952815160a08151818652615e4782870182614986565b9150508582015185820387870152615e5f8282614986565b91505060408083015186830382880152615e798382614986565b92505050606080830151818701525060808083015192508582038187015250615ea28183614986565b9a86019a9450505090830190600101615e21565b5090979650505050505050565b602081526000610d096020830184615e04565b60008282518085526020808601955060208260051b8401016020860160005b84811015615eb657601f19868403018952615f11838351614986565b98840198925090830190600101615ef5565b604081526000835180516040840152602081015167ffffffffffffffff80821660608601528060408401511660808601528060608401511660a08601528060808401511660c086015250505060208401516101408060e0850152615f8b610180850183614986565b915060408601517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08086850301610100870152615fc88483614986565b935060608801519150615fe76101208701836001600160a01b03169052565b60808801518387015260a088015192508086850301610160870152505061600e8282615e04565b9150508281036020840152614dcb8185615ed656fea164736f6c6343000818000a", } var OffRampABI = OffRampMetaData.ABI @@ -1793,6 +1793,123 @@ func (_OffRamp *OffRampFilterer) ParseSkippedAlreadyExecutedMessage(log types.Lo return event, nil } +type OffRampSkippedReportExecutionIterator struct { + Event *OffRampSkippedReportExecution + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *OffRampSkippedReportExecutionIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(OffRampSkippedReportExecution) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(OffRampSkippedReportExecution) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *OffRampSkippedReportExecutionIterator) Error() error { + return it.fail +} + +func (it *OffRampSkippedReportExecutionIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type OffRampSkippedReportExecution struct { + SourceChainSelector uint64 + Raw types.Log +} + +func (_OffRamp *OffRampFilterer) FilterSkippedReportExecution(opts *bind.FilterOpts) (*OffRampSkippedReportExecutionIterator, error) { + + logs, sub, err := _OffRamp.contract.FilterLogs(opts, "SkippedReportExecution") + if err != nil { + return nil, err + } + return &OffRampSkippedReportExecutionIterator{contract: _OffRamp.contract, event: "SkippedReportExecution", logs: logs, sub: sub}, nil +} + +func (_OffRamp *OffRampFilterer) WatchSkippedReportExecution(opts *bind.WatchOpts, sink chan<- *OffRampSkippedReportExecution) (event.Subscription, error) { + + logs, sub, err := _OffRamp.contract.WatchLogs(opts, "SkippedReportExecution") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(OffRampSkippedReportExecution) + if err := _OffRamp.contract.UnpackLog(event, "SkippedReportExecution", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_OffRamp *OffRampFilterer) ParseSkippedReportExecution(log types.Log) (*OffRampSkippedReportExecution, error) { + event := new(OffRampSkippedReportExecution) + if err := _OffRamp.contract.UnpackLog(event, "SkippedReportExecution", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + type OffRampSourceChainConfigSetIterator struct { Event *OffRampSourceChainConfigSet @@ -2304,6 +2421,8 @@ func (_OffRamp *OffRamp) ParseLog(log types.Log) (generated.AbigenLog, error) { return _OffRamp.ParseRootRemoved(log) case _OffRamp.abi.Events["SkippedAlreadyExecutedMessage"].ID: return _OffRamp.ParseSkippedAlreadyExecutedMessage(log) + case _OffRamp.abi.Events["SkippedReportExecution"].ID: + return _OffRamp.ParseSkippedReportExecution(log) case _OffRamp.abi.Events["SourceChainConfigSet"].ID: return _OffRamp.ParseSourceChainConfigSet(log) case _OffRamp.abi.Events["SourceChainSelectorAdded"].ID: @@ -2354,6 +2473,10 @@ func (OffRampSkippedAlreadyExecutedMessage) Topic() common.Hash { return common.HexToHash("0x3b575419319662b2a6f5e2467d84521517a3382b908eb3d557bb3fdb0c50e23c") } +func (OffRampSkippedReportExecution) Topic() common.Hash { + return common.HexToHash("0xaab522ed53d887e56ed53dd37398a01aeef6a58e0fa77c2173beb9512d894933") +} + func (OffRampSourceChainConfigSet) Topic() common.Hash { return common.HexToHash("0x49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b") } @@ -2471,6 +2594,12 @@ type OffRampInterface interface { ParseSkippedAlreadyExecutedMessage(log types.Log) (*OffRampSkippedAlreadyExecutedMessage, error) + FilterSkippedReportExecution(opts *bind.FilterOpts) (*OffRampSkippedReportExecutionIterator, error) + + WatchSkippedReportExecution(opts *bind.WatchOpts, sink chan<- *OffRampSkippedReportExecution) (event.Subscription, error) + + ParseSkippedReportExecution(log types.Log) (*OffRampSkippedReportExecution, error) + FilterSourceChainConfigSet(opts *bind.FilterOpts, sourceChainSelector []uint64) (*OffRampSourceChainConfigSetIterator, error) WatchSourceChainConfigSet(opts *bind.WatchOpts, sink chan<- *OffRampSourceChainConfigSet, sourceChainSelector []uint64) (event.Subscription, error) diff --git a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt index d0be78aeaa..77f04c61c6 100644 --- a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -23,7 +23,7 @@ multi_aggregate_rate_limiter: ../../../contracts/solc/v0.8.24/MultiAggregateRate multi_ocr3_helper: ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Helper.abi ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Helper.bin 6b56e0114a4d50797d30a34aecc2641ef340451d0c3fcb9d729bba4df2435122 nonce_manager: ../../../contracts/solc/v0.8.24/NonceManager/NonceManager.abi ../../../contracts/solc/v0.8.24/NonceManager/NonceManager.bin 6f64e1083b356c06ee66b9138e398b9c97a4cd3e8c9ec38cf3010cebc79af536 ocr3_config_encoder: ../../../contracts/solc/v0.8.24/IOCR3ConfigEncoder/IOCR3ConfigEncoder.abi ../../../contracts/solc/v0.8.24/IOCR3ConfigEncoder/IOCR3ConfigEncoder.bin e21180898e1ad54a045ee20add85a2793c681425ea06f66d1a9e5cab128b6487 -offramp: ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.abi ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.bin 263df151d037af19cc412a051efb82993b0ccdde0184c598e3669f1326ab4ce9 +offramp: ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.abi ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.bin 136ae93018723f03d695f60348231d58cacf53e4de2016fa6e638eba7bd64af7 onramp: ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.abi ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.bin c3b345930e1a553b18553e18a5c0ff8df3c372118fdf78a176aaccb1891664bb ping_pong_demo: ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.abi ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.bin c1c2f8a65c7ffd971899cae7fe62f2da57d09e936151e2b92163c4bebe699d6b price_registry: ../../../contracts/solc/v0.8.24/PriceRegistry/PriceRegistry.abi ../../../contracts/solc/v0.8.24/PriceRegistry/PriceRegistry.bin e7781d600c1bb7aa4620106af7f6e146a109b97f4cb6a7d06c9e15773340ecb2 From 137712f1f38f81429d53a19d2b66d6ca9dfe0357 Mon Sep 17 00:00:00 2001 From: Makram Date: Wed, 4 Sep 2024 20:06:34 +0300 Subject: [PATCH 071/115] remove bootstrapP2PIds (#1388) ## Motivation Bootstrap P2P IDs are no longer needed in the OCR config in CCIPConfig. See #1348's description for more details. ## Solution Remove bootstrap P2P IDs from the OCR config in CCIPConfig. ## Related PRs https://github.com/smartcontractkit/chainlink-ccip/pull/89 --- contracts/gas-snapshots/ccip.gas-snapshot | 108 +++++++++--------- .../src/v0.8/ccip/capability/CCIPConfig.sol | 9 -- .../capability/libraries/CCIPConfigTypes.sol | 2 - .../ccip/test/capability/CCIPConfig.t.sol | 95 --------------- .../ccip/generated/ccip_config/ccip_config.go | 5 +- .../ocr3_config_encoder.go | 3 +- ...rapper-dependency-versions-do-not-edit.txt | 4 +- 7 files changed, 56 insertions(+), 170 deletions(-) diff --git a/contracts/gas-snapshots/ccip.gas-snapshot b/contracts/gas-snapshots/ccip.gas-snapshot index bf3f7a9f72..62deac1cb9 100644 --- a/contracts/gas-snapshots/ccip.gas-snapshot +++ b/contracts/gas-snapshots/ccip.gas-snapshot @@ -35,64 +35,58 @@ BurnWithFromMintTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas BurnWithFromMintTokenPool_lockOrBurn:test_PoolBurn_Success() (gas: 243517) BurnWithFromMintTokenPool_lockOrBurn:test_Setup_Success() (gas: 23951) CCIPClientExample_sanity:test_ImmutableExamples_Success() (gas: 2132684) -CCIPConfigSetup:test_getCapabilityConfiguration_Success() (gas: 9517) -CCIPConfig_ConfigStateMachine:test__computeConfigDigest_Success() (gas: 70831) -CCIPConfig_ConfigStateMachine:test__computeNewConfigWithMeta_InitToRunning_Success() (gas: 363682) -CCIPConfig_ConfigStateMachine:test__computeNewConfigWithMeta_RunningToStaging_Success() (gas: 488896) -CCIPConfig_ConfigStateMachine:test__computeNewConfigWithMeta_StagingToRunning_Success() (gas: 453458) -CCIPConfig_ConfigStateMachine:test__groupByPluginType_TooManyOCR3Configs_Reverts() (gas: 37049) -CCIPConfig_ConfigStateMachine:test__groupByPluginType_threeCommitConfigs_Reverts() (gas: 61065) -CCIPConfig_ConfigStateMachine:test__groupByPluginType_threeExecutionConfigs_Reverts() (gas: 60985) -CCIPConfig_ConfigStateMachine:test__stateFromConfigLength_Success() (gas: 11635) -CCIPConfig_ConfigStateMachine:test__validateConfigStateTransition_Success() (gas: 8831) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_InitToRunning_Success() (gas: 312026) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_InitToRunning_WrongConfigCount_Reverts() (gas: 49727) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_NonExistentConfigTransition_Reverts() (gas: 32320) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_RunningToStaging_Success() (gas: 376649) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_RunningToStaging_WrongConfigCount_Reverts() (gas: 121045) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_RunningToStaging_WrongConfigDigestBlueGreen_Reverts() (gas: 157245) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_StagingToRunning_Success() (gas: 376425) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_StagingToRunning_WrongConfigDigest_Reverts() (gas: 157312) -CCIPConfig_ConfigStateMachine:test_getCapabilityConfiguration_Success() (gas: 9605) -CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_CommitAndExecConfig_Success() (gas: 1851149) -CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_CommitConfigOnly_Success() (gas: 1068320) -CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_ExecConfigOnly_Success() (gas: 1068351) +CCIPConfigSetup:test_getCapabilityConfiguration_Success() (gas: 9539) +CCIPConfig_ConfigStateMachine:test__computeConfigDigest_Success() (gas: 66088) +CCIPConfig_ConfigStateMachine:test__computeNewConfigWithMeta_InitToRunning_Success() (gas: 357846) +CCIPConfig_ConfigStateMachine:test__computeNewConfigWithMeta_RunningToStaging_Success() (gas: 474512) +CCIPConfig_ConfigStateMachine:test__computeNewConfigWithMeta_StagingToRunning_Success() (gas: 441765) +CCIPConfig_ConfigStateMachine:test__groupByPluginType_TooManyOCR3Configs_Reverts() (gas: 33798) +CCIPConfig_ConfigStateMachine:test__groupByPluginType_threeCommitConfigs_Reverts() (gas: 56870) +CCIPConfig_ConfigStateMachine:test__groupByPluginType_threeExecutionConfigs_Reverts() (gas: 56790) +CCIPConfig_ConfigStateMachine:test__stateFromConfigLength_Success() (gas: 11701) +CCIPConfig_ConfigStateMachine:test__validateConfigStateTransition_Success() (gas: 8762) +CCIPConfig_ConfigStateMachine:test__validateConfigTransition_InitToRunning_Success() (gas: 309581) +CCIPConfig_ConfigStateMachine:test__validateConfigTransition_InitToRunning_WrongConfigCount_Reverts() (gas: 45877) +CCIPConfig_ConfigStateMachine:test__validateConfigTransition_NonExistentConfigTransition_Reverts() (gas: 29698) +CCIPConfig_ConfigStateMachine:test__validateConfigTransition_RunningToStaging_Success() (gas: 369916) +CCIPConfig_ConfigStateMachine:test__validateConfigTransition_RunningToStaging_WrongConfigCount_Reverts() (gas: 111436) +CCIPConfig_ConfigStateMachine:test__validateConfigTransition_RunningToStaging_WrongConfigDigestBlueGreen_Reverts() (gas: 145550) +CCIPConfig_ConfigStateMachine:test__validateConfigTransition_StagingToRunning_Success() (gas: 369692) +CCIPConfig_ConfigStateMachine:test__validateConfigTransition_StagingToRunning_WrongConfigDigest_Reverts() (gas: 145617) +CCIPConfig_ConfigStateMachine:test_getCapabilityConfiguration_Success() (gas: 9627) +CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_CommitAndExecConfig_Success() (gas: 1752378) +CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_CommitConfigOnly_Success() (gas: 1018901) +CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_ExecConfigOnly_Success() (gas: 1018932) CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_OnlyCapabilitiesRegistryCanCall_Reverts() (gas: 9599) -CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_ZeroLengthConfig_Success() (gas: 16057) -CCIPConfig_beforeCapabilityConfigSet:test_getCapabilityConfiguration_Success() (gas: 9605) -CCIPConfig_chainConfig:test__applyChainConfigUpdates_FChainNotPositive_Reverts() (gas: 184727) -CCIPConfig_chainConfig:test_applyChainConfigUpdates_addChainConfigs_Success() (gas: 344895) -CCIPConfig_chainConfig:test_applyChainConfigUpdates_nodeNotInRegistry_Reverts() (gas: 20329) -CCIPConfig_chainConfig:test_applyChainConfigUpdates_removeChainConfigs_Success() (gas: 267569) -CCIPConfig_chainConfig:test_applyChainConfigUpdates_selectorNotFound_Reverts() (gas: 14829) -CCIPConfig_chainConfig:test_getCapabilityConfiguration_Success() (gas: 9626) -CCIPConfig_chainConfig:test_getPaginatedCCIPConfigs_Success() (gas: 370249) -CCIPConfig_constructor:test_constructor_Success() (gas: 3597863) -CCIPConfig_constructor:test_constructor_ZeroAddressNotAllowed_Revert() (gas: 61761) -CCIPConfig_updatePluginConfig:test__updatePluginConfig_InitToRunning_Success() (gas: 1057386) -CCIPConfig_updatePluginConfig:test__updatePluginConfig_InvalidConfigLength_Reverts() (gas: 27561) -CCIPConfig_updatePluginConfig:test__updatePluginConfig_InvalidConfigStateTransition_Reverts() (gas: 23127) -CCIPConfig_updatePluginConfig:test__updatePluginConfig_RunningToStaging_Success() (gas: 2009377) -CCIPConfig_updatePluginConfig:test__updatePluginConfig_StagingToRunning_Success() (gas: 2616263) -CCIPConfig_updatePluginConfig:test_getCapabilityConfiguration_Success() (gas: 9605) -CCIPConfig_validateConfig:test__validateConfig_ABIEncodedAddress_OfframpAddressCannotBeZero_Reverts() (gas: 292159) -CCIPConfig_validateConfig:test__validateConfig_BootstrapP2PIdsHasDuplicates_Reverts() (gas: 295946) -CCIPConfig_validateConfig:test__validateConfig_BootstrapP2PIdsNotASubsetOfP2PIds_Reverts() (gas: 299396) -CCIPConfig_validateConfig:test__validateConfig_BootstrapP2PIdsNotSorted_Reverts() (gas: 296081) -CCIPConfig_validateConfig:test__validateConfig_ChainSelectorNotFound_Reverts() (gas: 294926) -CCIPConfig_validateConfig:test__validateConfig_ChainSelectorNotSet_Reverts() (gas: 291771) -CCIPConfig_validateConfig:test__validateConfig_FMustBePositive_Reverts() (gas: 292999) -CCIPConfig_validateConfig:test__validateConfig_FTooHigh_Reverts() (gas: 293164) -CCIPConfig_validateConfig:test__validateConfig_NodeNotInRegistry_Reverts() (gas: 348310) -CCIPConfig_validateConfig:test__validateConfig_NotEnoughTransmitters_Reverts() (gas: 1209654) -CCIPConfig_validateConfig:test__validateConfig_OfframpAddressCannotBeZero_Reverts() (gas: 291876) -CCIPConfig_validateConfig:test__validateConfig_P2PIdsHasDuplicates_Reverts() (gas: 295780) -CCIPConfig_validateConfig:test__validateConfig_P2PIdsLengthNotMatching_Reverts() (gas: 293785) -CCIPConfig_validateConfig:test__validateConfig_P2PIdsNotSorted_Reverts() (gas: 296150) -CCIPConfig_validateConfig:test__validateConfig_Success() (gas: 302468) -CCIPConfig_validateConfig:test__validateConfig_TooManyBootstrapP2PIds_Reverts() (gas: 295556) -CCIPConfig_validateConfig:test__validateConfig_TooManySigners_Reverts() (gas: 494442) -CCIPConfig_validateConfig:test_getCapabilityConfiguration_Success() (gas: 9584) +CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_ZeroLengthConfig_Success() (gas: 15984) +CCIPConfig_beforeCapabilityConfigSet:test_getCapabilityConfiguration_Success() (gas: 9627) +CCIPConfig_chainConfig:test__applyChainConfigUpdates_FChainNotPositive_Reverts() (gas: 184705) +CCIPConfig_chainConfig:test_applyChainConfigUpdates_addChainConfigs_Success() (gas: 344873) +CCIPConfig_chainConfig:test_applyChainConfigUpdates_nodeNotInRegistry_Reverts() (gas: 20307) +CCIPConfig_chainConfig:test_applyChainConfigUpdates_removeChainConfigs_Success() (gas: 267534) +CCIPConfig_chainConfig:test_applyChainConfigUpdates_selectorNotFound_Reverts() (gas: 14807) +CCIPConfig_chainConfig:test_getCapabilityConfiguration_Success() (gas: 9648) +CCIPConfig_chainConfig:test_getPaginatedCCIPConfigs_Success() (gas: 370227) +CCIPConfig_constructor:test_constructor_Success() (gas: 3397350) +CCIPConfig_constructor:test_constructor_ZeroAddressNotAllowed_Revert() (gas: 61507) +CCIPConfig_updatePluginConfig:test__updatePluginConfig_InitToRunning_Success() (gas: 1008218) +CCIPConfig_updatePluginConfig:test__updatePluginConfig_InvalidConfigLength_Reverts() (gas: 25563) +CCIPConfig_updatePluginConfig:test__updatePluginConfig_InvalidConfigStateTransition_Reverts() (gas: 21781) +CCIPConfig_updatePluginConfig:test__updatePluginConfig_RunningToStaging_Success() (gas: 1895343) +CCIPConfig_updatePluginConfig:test__updatePluginConfig_StagingToRunning_Success() (gas: 2464900) +CCIPConfig_updatePluginConfig:test_getCapabilityConfiguration_Success() (gas: 9627) +CCIPConfig_validateConfig:test__validateConfig_ABIEncodedAddress_OfframpAddressCannotBeZero_Reverts() (gas: 290657) +CCIPConfig_validateConfig:test__validateConfig_ChainSelectorNotFound_Reverts() (gas: 293370) +CCIPConfig_validateConfig:test__validateConfig_ChainSelectorNotSet_Reverts() (gas: 290290) +CCIPConfig_validateConfig:test__validateConfig_FMustBePositive_Reverts() (gas: 291497) +CCIPConfig_validateConfig:test__validateConfig_FTooHigh_Reverts() (gas: 291595) +CCIPConfig_validateConfig:test__validateConfig_NodeNotInRegistry_Reverts() (gas: 344569) +CCIPConfig_validateConfig:test__validateConfig_NotEnoughTransmitters_Reverts() (gas: 1207267) +CCIPConfig_validateConfig:test__validateConfig_OfframpAddressCannotBeZero_Reverts() (gas: 290373) +CCIPConfig_validateConfig:test__validateConfig_P2PIdsLengthNotMatching_Reverts() (gas: 292270) +CCIPConfig_validateConfig:test__validateConfig_Success() (gas: 299419) +CCIPConfig_validateConfig:test__validateConfig_TooManySigners_Reverts() (gas: 492913) +CCIPConfig_validateConfig:test_getCapabilityConfiguration_Success() (gas: 9606) CommitStore_constructor:test_Constructor_Success() (gas: 3091326) CommitStore_isUnpausedAndRMNHealthy:test_RMN_Success() (gas: 73420) CommitStore_report:test_InvalidIntervalMinLargerThanMax_Revert() (gas: 28670) diff --git a/contracts/src/v0.8/ccip/capability/CCIPConfig.sol b/contracts/src/v0.8/ccip/capability/CCIPConfig.sol index 5f863ed7ae..463a710335 100644 --- a/contracts/src/v0.8/ccip/capability/CCIPConfig.sol +++ b/contracts/src/v0.8/ccip/capability/CCIPConfig.sol @@ -6,7 +6,6 @@ import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; import {ICapabilitiesRegistry} from "./interfaces/ICapabilitiesRegistry.sol"; import {OwnerIsCreator} from "../../shared/access/OwnerIsCreator.sol"; -import {SortedSetValidationUtil} from "../../shared/util/SortedSetValidationUtil.sol"; import {Internal} from "../libraries/Internal.sol"; import {CCIPConfigTypes} from "./libraries/CCIPConfigTypes.sol"; @@ -35,7 +34,6 @@ contract CCIPConfig is ITypeAndVersion, ICapabilityConfiguration, OwnerIsCreator error ChainSelectorNotSet(); error TooManyOCR3Configs(); error TooManySigners(); - error TooManyBootstrapP2PIds(); error P2PIdsLengthNotMatching(uint256 p2pIdsLength, uint256 signersLength, uint256 transmittersLength); error NotEnoughTransmitters(uint256 got, uint256 minimum); error FMustBePositive(); @@ -407,12 +405,6 @@ contract CCIPConfig is ITypeAndVersion, ICapabilityConfiguration, OwnerIsCreator if (cfg.F == 0) revert FMustBePositive(); if (numberOfSigners <= 3 * cfg.F) revert FTooHigh(); - if (cfg.bootstrapP2PIds.length > cfg.p2pIds.length) revert TooManyBootstrapP2PIds(); - - // check for duplicate p2p ids and bootstrapP2PIds. - // check that p2p ids in cfg.bootstrapP2PIds are included in cfg.p2pIds. - SortedSetValidationUtil._checkIsValidUniqueSubset(cfg.bootstrapP2PIds, cfg.p2pIds); - // Check that the readers are in the capabilities registry. _ensureInRegistry(cfg.p2pIds); } @@ -439,7 +431,6 @@ contract CCIPConfig is ITypeAndVersion, ICapabilityConfiguration, OwnerIsCreator ocr3Config.pluginType, ocr3Config.offrampAddress, configCount, - ocr3Config.bootstrapP2PIds, ocr3Config.p2pIds, ocr3Config.signers, ocr3Config.transmitters, diff --git a/contracts/src/v0.8/ccip/capability/libraries/CCIPConfigTypes.sol b/contracts/src/v0.8/ccip/capability/libraries/CCIPConfigTypes.sol index 99adef84b1..2148f991c8 100644 --- a/contracts/src/v0.8/ccip/capability/libraries/CCIPConfigTypes.sol +++ b/contracts/src/v0.8/ccip/capability/libraries/CCIPConfigTypes.sol @@ -37,8 +37,6 @@ library CCIPConfigTypes { uint8 F; // | The "big F" parameter for the role DON. uint64 offchainConfigVersion; // ─────────────╯ The version of the offchain configuration. bytes offrampAddress; // The remote chain offramp address. - // NOTE: bootstrapP2PIds and p2pIds should be sent as sorted sets - bytes32[] bootstrapP2PIds; // The bootstrap P2P IDs of the oracles that are part of the role DON. // len(p2pIds) == len(signers) == len(transmitters) == 3 * F + 1 // NOTE: indexes matter here! The p2p ID at index i corresponds to the signer at index i and the transmitter at index i. // This is crucial in order to build the oracle ID <-> peer ID mapping offchain. diff --git a/contracts/src/v0.8/ccip/test/capability/CCIPConfig.t.sol b/contracts/src/v0.8/ccip/test/capability/CCIPConfig.t.sol index d252698e62..721f5d3463 100644 --- a/contracts/src/v0.8/ccip/test/capability/CCIPConfig.t.sol +++ b/contracts/src/v0.8/ccip/test/capability/CCIPConfig.t.sol @@ -341,7 +341,6 @@ contract CCIPConfig_validateConfig is CCIPConfigSetup { pluginType: Internal.OCRPluginType.Commit, offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), chainSelector: 1, - bootstrapP2PIds: _subset(p2pIds, 0, 1), p2pIds: p2pIds, signers: signers, transmitters: transmitters, @@ -451,14 +450,6 @@ contract CCIPConfig_validateConfig is CCIPConfigSetup { s_ccipCC.validateConfig(config); } - function test__validateConfig_TooManyBootstrapP2PIds_Reverts() public { - CCIPConfigTypes.OCR3Config memory config = _getCorrectOCR3Config(); - config.bootstrapP2PIds = _makeBytes32Array(5, 0); // too many bootstrap p2pIds, 5 > 4 - - vm.expectRevert(CCIPConfig.TooManyBootstrapP2PIds.selector); - s_ccipCC.validateConfig(config); - } - function test__validateConfig_NodeNotInRegistry_Reverts() public { (bytes32[] memory p2pIds,,) = _addChainConfig(4); bytes32 nonExistentP2PId = keccak256("notInRegistry"); @@ -481,65 +472,10 @@ contract CCIPConfig_validateConfig is CCIPConfigSetup { ); CCIPConfigTypes.OCR3Config memory config = _getCorrectOCR3Config(); config.p2pIds = p2pIds; - config.bootstrapP2PIds = _subset(p2pIds, 0, 1); vm.expectRevert(abi.encodeWithSelector(CCIPConfig.NodeNotInRegistry.selector, nonExistentP2PId)); s_ccipCC.validateConfig(config); } - - function test__validateConfig_P2PIdsNotSorted_Reverts() public { - CCIPConfigTypes.OCR3Config memory config = _getCorrectOCR3Config(); - - //swapping two adjacent p2pIds to make it unsorted - (config.p2pIds[2], config.p2pIds[3]) = (config.p2pIds[3], config.p2pIds[2]); - - vm.expectRevert(abi.encodeWithSelector(SortedSetValidationUtil.NotASortedSet.selector, config.p2pIds)); - s_ccipCC.validateConfig(config); - } - - function test__validateConfig_BootstrapP2PIdsNotSorted_Reverts() public { - CCIPConfigTypes.OCR3Config memory config = _getCorrectOCR3Config(); - bytes32[] memory bootstrapP2PIds = _subset(config.p2pIds, 0, 2); - - //swapping bootstrapP2PIds to make it unsorted - (bootstrapP2PIds[0], bootstrapP2PIds[1]) = (bootstrapP2PIds[1], bootstrapP2PIds[0]); - - config.bootstrapP2PIds = bootstrapP2PIds; - - vm.expectRevert(abi.encodeWithSelector(SortedSetValidationUtil.NotASortedSet.selector, bootstrapP2PIds)); - s_ccipCC.validateConfig(config); - } - - function test__validateConfig_P2PIdsHasDuplicates_Reverts() public { - CCIPConfigTypes.OCR3Config memory config = _getCorrectOCR3Config(); - //forcing duplicate p2pIds - config.p2pIds[1] = config.p2pIds[2]; - - vm.expectRevert(abi.encodeWithSelector(SortedSetValidationUtil.NotASortedSet.selector, config.p2pIds)); - s_ccipCC.validateConfig(config); - } - - function test__validateConfig_BootstrapP2PIdsHasDuplicates_Reverts() public { - CCIPConfigTypes.OCR3Config memory config = _getCorrectOCR3Config(); - //forcing duplicate bootstrapP2PIds - config.bootstrapP2PIds = _subset(config.p2pIds, 0, 2); - config.bootstrapP2PIds[1] = config.bootstrapP2PIds[0]; - - vm.expectRevert(abi.encodeWithSelector(SortedSetValidationUtil.NotASortedSet.selector, config.bootstrapP2PIds)); - s_ccipCC.validateConfig(config); - } - - function test__validateConfig_BootstrapP2PIdsNotASubsetOfP2PIds_Reverts() public { - CCIPConfigTypes.OCR3Config memory config = _getCorrectOCR3Config(); - config.bootstrapP2PIds = _subset(config.p2pIds, 0, 2); - config.p2pIds[1] = bytes32(uint256(config.p2pIds[0]) + 100); - - vm.expectRevert( - abi.encodeWithSelector(SortedSetValidationUtil.NotASubset.selector, config.bootstrapP2PIds, config.p2pIds) - ); - - s_ccipCC.validateConfig(config); - } } contract CCIPConfig_ConfigStateMachine is CCIPConfigSetup { @@ -579,7 +515,6 @@ contract CCIPConfig_ConfigStateMachine is CCIPConfigSetup { pluginType: Internal.OCRPluginType.Commit, offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), chainSelector: 1, - bootstrapP2PIds: _subset(p2pIds, 0, 1), p2pIds: p2pIds, signers: signers, transmitters: transmitters, @@ -624,7 +559,6 @@ contract CCIPConfig_ConfigStateMachine is CCIPConfigSetup { pluginType: Internal.OCRPluginType.Commit, offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), chainSelector: 1, - bootstrapP2PIds: _subset(p2pIds, 0, 1), p2pIds: p2pIds, signers: signers, transmitters: transmitters, @@ -638,7 +572,6 @@ contract CCIPConfig_ConfigStateMachine is CCIPConfigSetup { pluginType: Internal.OCRPluginType.Execution, offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), chainSelector: 1, - bootstrapP2PIds: _subset(p2pIds, 0, 1), p2pIds: p2pIds, signers: signers, transmitters: transmitters, @@ -671,7 +604,6 @@ contract CCIPConfig_ConfigStateMachine is CCIPConfigSetup { pluginType: Internal.OCRPluginType.Commit, offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), chainSelector: 1, - bootstrapP2PIds: _subset(p2pIds, 0, 1), p2pIds: p2pIds, signers: signers, transmitters: transmitters, @@ -704,7 +636,6 @@ contract CCIPConfig_ConfigStateMachine is CCIPConfigSetup { pluginType: Internal.OCRPluginType.Commit, offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), chainSelector: 1, - bootstrapP2PIds: _subset(p2pIds, 0, 1), p2pIds: p2pIds, signers: signers, transmitters: transmitters, @@ -716,7 +647,6 @@ contract CCIPConfig_ConfigStateMachine is CCIPConfigSetup { pluginType: Internal.OCRPluginType.Commit, offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), chainSelector: 1, - bootstrapP2PIds: _subset(p2pIds, 0, 1), p2pIds: p2pIds, signers: signers, transmitters: transmitters, @@ -782,7 +712,6 @@ contract CCIPConfig_ConfigStateMachine is CCIPConfigSetup { pluginType: Internal.OCRPluginType.Commit, offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), chainSelector: 1, - bootstrapP2PIds: _subset(p2pIds, 0, 1), p2pIds: p2pIds, signers: signers, transmitters: transmitters, @@ -794,7 +723,6 @@ contract CCIPConfig_ConfigStateMachine is CCIPConfigSetup { pluginType: Internal.OCRPluginType.Commit, offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), chainSelector: 1, - bootstrapP2PIds: _subset(p2pIds, 0, 1), p2pIds: p2pIds, signers: signers, transmitters: transmitters, @@ -842,7 +770,6 @@ contract CCIPConfig_ConfigStateMachine is CCIPConfigSetup { pluginType: Internal.OCRPluginType.Commit, offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), chainSelector: 1, - bootstrapP2PIds: _subset(p2pIds, 0, 1), p2pIds: p2pIds, signers: signers, transmitters: transmitters, @@ -869,7 +796,6 @@ contract CCIPConfig_ConfigStateMachine is CCIPConfigSetup { pluginType: Internal.OCRPluginType.Commit, offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), chainSelector: 1, - bootstrapP2PIds: _subset(p2pIds, 0, 1), p2pIds: p2pIds, signers: signers, transmitters: transmitters, @@ -881,7 +807,6 @@ contract CCIPConfig_ConfigStateMachine is CCIPConfigSetup { pluginType: Internal.OCRPluginType.Commit, offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), chainSelector: 1, - bootstrapP2PIds: _subset(p2pIds, 0, 1), p2pIds: p2pIds, signers: signers, transmitters: transmitters, @@ -919,7 +844,6 @@ contract CCIPConfig_ConfigStateMachine is CCIPConfigSetup { pluginType: Internal.OCRPluginType.Commit, offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), chainSelector: 1, - bootstrapP2PIds: _subset(p2pIds, 0, 1), p2pIds: p2pIds, signers: signers, transmitters: transmitters, @@ -931,7 +855,6 @@ contract CCIPConfig_ConfigStateMachine is CCIPConfigSetup { pluginType: Internal.OCRPluginType.Commit, offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), chainSelector: 1, - bootstrapP2PIds: _subset(p2pIds, 0, 1), p2pIds: p2pIds, signers: signers, transmitters: transmitters, @@ -980,7 +903,6 @@ contract CCIPConfig_ConfigStateMachine is CCIPConfigSetup { pluginType: Internal.OCRPluginType.Commit, offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), chainSelector: 1, - bootstrapP2PIds: _subset(p2pIds, 0, 1), p2pIds: p2pIds, signers: signers, transmitters: transmitters, @@ -1003,7 +925,6 @@ contract CCIPConfig_ConfigStateMachine is CCIPConfigSetup { pluginType: Internal.OCRPluginType.Execution, offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), chainSelector: 1, - bootstrapP2PIds: _subset(p2pIds, 0, 1), p2pIds: p2pIds, signers: signers, transmitters: transmitters, @@ -1028,7 +949,6 @@ contract CCIPConfig_ConfigStateMachine is CCIPConfigSetup { pluginType: Internal.OCRPluginType.Commit, offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), chainSelector: 1, - bootstrapP2PIds: _subset(_makeBytes32Array(4, 0), 0, 1), p2pIds: _makeBytes32Array(4, 0), signers: _makeBytesArray(4, 10), transmitters: _makeBytesArray(4, 20), @@ -1055,7 +975,6 @@ contract CCIPConfig_ConfigStateMachine is CCIPConfigSetup { pluginType: Internal.OCRPluginType.Commit, offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), chainSelector: 1, - bootstrapP2PIds: _subset(_makeBytes32Array(4, 0), 0, 1), p2pIds: _makeBytes32Array(4, 0), signers: _makeBytesArray(4, 10), transmitters: _makeBytesArray(4, 20), @@ -1067,7 +986,6 @@ contract CCIPConfig_ConfigStateMachine is CCIPConfigSetup { pluginType: Internal.OCRPluginType.Commit, offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), chainSelector: 1, - bootstrapP2PIds: _subset(_makeBytes32Array(4, 0), 0, 1), p2pIds: _makeBytes32Array(4, 0), signers: _makeBytesArray(4, 10), transmitters: _makeBytesArray(4, 20), @@ -1111,7 +1029,6 @@ contract CCIPConfig_ConfigStateMachine is CCIPConfigSetup { pluginType: Internal.OCRPluginType.Commit, offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), chainSelector: 1, - bootstrapP2PIds: _subset(_makeBytes32Array(4, 0), 0, 1), p2pIds: _makeBytes32Array(4, 0), signers: _makeBytesArray(4, 10), transmitters: _makeBytesArray(4, 20), @@ -1123,7 +1040,6 @@ contract CCIPConfig_ConfigStateMachine is CCIPConfigSetup { pluginType: Internal.OCRPluginType.Commit, offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), chainSelector: 1, - bootstrapP2PIds: _subset(_makeBytes32Array(4, 0), 0, 1), p2pIds: _makeBytes32Array(4, 0), signers: _makeBytesArray(4, 10), transmitters: _makeBytesArray(4, 20), @@ -1161,7 +1077,6 @@ contract CCIPConfig_ConfigStateMachine is CCIPConfigSetup { pluginType: Internal.OCRPluginType.Commit, offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), chainSelector: 1, - bootstrapP2PIds: _subset(_makeBytes32Array(4, 0), 0, 1), p2pIds: _makeBytes32Array(4, 0), signers: _makeBytesArray(4, 10), transmitters: _makeBytesArray(4, 20), @@ -1173,7 +1088,6 @@ contract CCIPConfig_ConfigStateMachine is CCIPConfigSetup { pluginType: Internal.OCRPluginType.Commit, offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), chainSelector: 1, - bootstrapP2PIds: _subset(_makeBytes32Array(4, 0), 0, 1), p2pIds: _makeBytes32Array(4, 0), signers: _makeBytesArray(4, 10), transmitters: _makeBytesArray(4, 20), @@ -1229,7 +1143,6 @@ contract CCIPConfig_updatePluginConfig is CCIPConfigSetup { pluginType: Internal.OCRPluginType.Commit, offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), chainSelector: 1, - bootstrapP2PIds: _subset(p2pIds, 0, 1), p2pIds: p2pIds, signers: signers, transmitters: transmitters, @@ -1258,7 +1171,6 @@ contract CCIPConfig_updatePluginConfig is CCIPConfigSetup { pluginType: Internal.OCRPluginType.Commit, offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), chainSelector: 1, - bootstrapP2PIds: _subset(p2pIds, 0, 1), p2pIds: p2pIds, signers: signers, transmitters: transmitters, @@ -1275,7 +1187,6 @@ contract CCIPConfig_updatePluginConfig is CCIPConfigSetup { pluginType: Internal.OCRPluginType.Commit, offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), chainSelector: 1, - bootstrapP2PIds: _subset(p2pIds, 0, 1), p2pIds: p2pIds, signers: signers, transmitters: transmitters, @@ -1313,7 +1224,6 @@ contract CCIPConfig_updatePluginConfig is CCIPConfigSetup { pluginType: Internal.OCRPluginType.Commit, offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), chainSelector: 1, - bootstrapP2PIds: _subset(p2pIds, 0, 1), p2pIds: p2pIds, signers: signers, transmitters: transmitters, @@ -1330,7 +1240,6 @@ contract CCIPConfig_updatePluginConfig is CCIPConfigSetup { pluginType: Internal.OCRPluginType.Commit, offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), chainSelector: 1, - bootstrapP2PIds: _subset(p2pIds, 0, 1), p2pIds: p2pIds, signers: signers, transmitters: transmitters, @@ -1411,7 +1320,6 @@ contract CCIPConfig_beforeCapabilityConfigSet is CCIPConfigSetup { pluginType: Internal.OCRPluginType.Commit, offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), chainSelector: 1, - bootstrapP2PIds: _subset(p2pIds, 0, 1), p2pIds: p2pIds, signers: signers, transmitters: transmitters, @@ -1443,7 +1351,6 @@ contract CCIPConfig_beforeCapabilityConfigSet is CCIPConfigSetup { pluginType: Internal.OCRPluginType.Execution, offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), chainSelector: 1, - bootstrapP2PIds: _subset(p2pIds, 0, 1), p2pIds: p2pIds, signers: signers, transmitters: transmitters, @@ -1477,7 +1384,6 @@ contract CCIPConfig_beforeCapabilityConfigSet is CCIPConfigSetup { pluginType: Internal.OCRPluginType.Commit, offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), chainSelector: 1, - bootstrapP2PIds: _subset(p2pIds, 0, 1), p2pIds: p2pIds, signers: signers, transmitters: transmitters, @@ -1489,7 +1395,6 @@ contract CCIPConfig_beforeCapabilityConfigSet is CCIPConfigSetup { pluginType: Internal.OCRPluginType.Execution, offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), chainSelector: 1, - bootstrapP2PIds: _subset(p2pIds, 0, 1), p2pIds: p2pIds, signers: signers, transmitters: transmitters, diff --git a/core/gethwrappers/ccip/generated/ccip_config/ccip_config.go b/core/gethwrappers/ccip/generated/ccip_config/ccip_config.go index 565e0bff3a..3c2d44cd30 100644 --- a/core/gethwrappers/ccip/generated/ccip_config/ccip_config.go +++ b/core/gethwrappers/ccip/generated/ccip_config/ccip_config.go @@ -47,7 +47,6 @@ type CCIPConfigTypesOCR3Config struct { F uint8 OffchainConfigVersion uint64 OfframpAddress []byte - BootstrapP2PIds [][32]byte P2pIds [][32]byte Signers [][]byte Transmitters [][]byte @@ -61,8 +60,8 @@ type CCIPConfigTypesOCR3ConfigWithMeta struct { } var CCIPConfigMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"capabilitiesRegistry\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainSelectorNotFound\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ChainSelectorNotSet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptySet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FChainMustBePositive\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FMustBePositive\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FTooHigh\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"length\",\"type\":\"uint256\"}],\"name\":\"InvalidConfigLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enumCCIPConfigTypes.ConfigState\",\"name\":\"currentState\",\"type\":\"uint8\"},{\"internalType\":\"enumCCIPConfigTypes.ConfigState\",\"name\":\"proposedState\",\"type\":\"uint8\"}],\"name\":\"InvalidConfigStateTransition\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidPluginType\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"}],\"name\":\"NodeNotInRegistry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonExistentConfigTransition\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"set\",\"type\":\"bytes32[]\"}],\"name\":\"NotASortedSet\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"subset\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"superset\",\"type\":\"bytes32[]\"}],\"name\":\"NotASubset\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"got\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minimum\",\"type\":\"uint256\"}],\"name\":\"NotEnoughTransmitters\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OfframpAddressCannotBeZero\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCapabilitiesRegistryCanCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"p2pIdsLength\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"signersLength\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"transmittersLength\",\"type\":\"uint256\"}],\"name\":\"P2PIdsLengthNotMatching\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManyBootstrapP2PIds\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManyOCR3Configs\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManySigners\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"got\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"expected\",\"type\":\"uint64\"}],\"name\":\"WrongConfigCount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"got\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"}],\"name\":\"WrongConfigDigest\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"got\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"}],\"name\":\"WrongConfigDigestBlueGreen\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"CapabilityConfigurationSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainConfigRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes32[]\",\"name\":\"readers\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint8\",\"name\":\"fChain\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"structCCIPConfigTypes.ChainConfig\",\"name\":\"chainConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"chainSelectorRemoves\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes32[]\",\"name\":\"readers\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint8\",\"name\":\"fChain\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPConfigTypes.ChainConfig\",\"name\":\"chainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structCCIPConfigTypes.ChainConfigInfo[]\",\"name\":\"chainConfigAdds\",\"type\":\"tuple[]\"}],\"name\":\"applyChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"}],\"name\":\"beforeCapabilityConfigSet\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"pageIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pageSize\",\"type\":\"uint256\"}],\"name\":\"getAllChainConfigs\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes32[]\",\"name\":\"readers\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint8\",\"name\":\"fChain\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPConfigTypes.ChainConfig\",\"name\":\"chainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structCCIPConfigTypes.ChainConfigInfo[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"name\":\"getCapabilityConfiguration\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"configuration\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCapabilityRegistry\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"}],\"name\":\"getOCRConfig\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offrampAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"bootstrapP2PIds\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"p2pIds\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes[]\",\"name\":\"signers\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes[]\",\"name\":\"transmitters\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPConfigTypes.OCR3Config\",\"name\":\"config\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"configCount\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"internalType\":\"structCCIPConfigTypes.OCR3ConfigWithMeta[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x60a06040523480156200001157600080fd5b506040516200446c3803806200446c8339810160408190526200003491620001a6565b33806000816200008b5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000be57620000be81620000fb565b5050506001600160a01b038116620000e9576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b0316608052620001d8565b336001600160a01b03821603620001555760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000082565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600060208284031215620001b957600080fd5b81516001600160a01b0381168114620001d157600080fd5b9392505050565b60805161426b620002016000396000818160f801528181610eff015261116f015261426b6000f3fe608060405234801561001057600080fd5b50600436106100c95760003560e01c80638318ed5d11610081578063f2fde38b1161005b578063f2fde38b1461020f578063f442c89a14610222578063fba64a7c1461023557600080fd5b80638318ed5d146101b05780638da5cb5b146101d1578063b74b2356146101ef57600080fd5b8063181f5a77116100b2578063181f5a771461013d5780634bd0473f1461018657806379ba5097146101a657600080fd5b806301ffc9a7146100ce578063020330e6146100f6575b600080fd5b6100e16100dc366004613015565b610248565b60405190151581526020015b60405180910390f35b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100ed565b6101796040518060400160405280601481526020017f43434950436f6e66696720312e362e302d64657600000000000000000000000081525081565b6040516100ed91906130bb565b6101996101943660046130ff565b6102e1565b6040516100ed919061321e565b6101ae6107b1565b005b6101796101be3660046133fb565b5060408051602081019091526000815290565b60005473ffffffffffffffffffffffffffffffffffffffff16610118565b6102026101fd366004613418565b6108b3565b6040516100ed919061347e565b6101ae61021d36600461350e565b610b34565b6101ae610230366004613590565b610b48565b6101ae610243366004613614565b610ee7565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f78bea7210000000000000000000000000000000000000000000000000000000014806102db57507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b63ffffffff8216600090815260056020526040812060609183600181111561030b5761030b613134565b600181111561031c5761031c613134565b8152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b828210156107a557600084815260209020604080516101a08101909152600984029091018054829060608201908390829060ff16600181111561038f5761038f613134565b60018111156103a0576103a0613134565b8152815467ffffffffffffffff61010082048116602084015260ff690100000000000000000083041660408401526a01000000000000000000009091041660608201526001820180546080909201916103f8906136d1565b80601f0160208091040260200160405190810160405280929190818152602001828054610424906136d1565b80156104715780601f1061044657610100808354040283529160200191610471565b820191906000526020600020905b81548152906001019060200180831161045457829003601f168201915b50505050508152602001600282018054806020026020016040519081016040528092919081815260200182805480156104c957602002820191906000526020600020905b8154815260200190600101908083116104b5575b505050505081526020016003820180548060200260200160405190810160405280929190818152602001828054801561052157602002820191906000526020600020905b81548152602001906001019080831161050d575b5050505050815260200160048201805480602002602001604051908101604052809291908181526020016000905b828210156105fb57838290600052602060002001805461056e906136d1565b80601f016020809104026020016040519081016040528092919081815260200182805461059a906136d1565b80156105e75780601f106105bc576101008083540402835291602001916105e7565b820191906000526020600020905b8154815290600101906020018083116105ca57829003601f168201915b50505050508152602001906001019061054f565b50505050815260200160058201805480602002602001604051908101604052809291908181526020016000905b828210156106d4578382906000526020600020018054610647906136d1565b80601f0160208091040260200160405190810160405280929190818152602001828054610673906136d1565b80156106c05780601f10610695576101008083540402835291602001916106c0565b820191906000526020600020905b8154815290600101906020018083116106a357829003601f168201915b505050505081526020019060010190610628565b5050505081526020016006820180546106ec906136d1565b80601f0160208091040260200160405190810160405280929190818152602001828054610718906136d1565b80156107655780601f1061073a57610100808354040283529160200191610765565b820191906000526020600020905b81548152906001019060200180831161074857829003601f168201915b505050919092525050508152600782015467ffffffffffffffff16602080830191909152600890920154604090910152908252600192909201910161034a565b50505050905092915050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610837576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b606060006108c16003610fa2565b905060006108cf8486613753565b90508315806108de5750818110155b1561091e576040805160008082526020820190925290610914565b610901612da6565b8152602001906001900390816108f95790505b50925050506102db565b600061092a8583613799565b9050828111156109375750815b600061094383836137ac565b67ffffffffffffffff81111561095b5761095b61376a565b60405190808252806020026020018201604052801561099457816020015b610981612da6565b8152602001906001900390816109795790505b50905060006109a36003610fac565b9050835b83811015610b275760008282815181106109c3576109c36137bf565b60209081029190910181015160408051808201825267ffffffffffffffff831680825260009081526002855282902082518154608081880283018101909552606082018181529597509295860194909391928492849190840182828015610a4957602002820191906000526020600020905b815481526020019060010190808311610a35575b5050509183525050600182015460ff166020820152600282018054604090920191610a73906136d1565b80601f0160208091040260200160405190810160405280929190818152602001828054610a9f906136d1565b8015610aec5780601f10610ac157610100808354040283529160200191610aec565b820191906000526020600020905b815481529060010190602001808311610acf57829003601f168201915b50505091909252505050905284610b0388856137ac565b81518110610b1357610b136137bf565b6020908102919091010152506001016109a7565b5090979650505050505050565b610b3c610fc0565b610b4581611043565b50565b610b50610fc0565b60005b83811015610d3657610b97858583818110610b7057610b706137bf565b9050602002016020810190610b8591906137ee565b60039067ffffffffffffffff16611138565b610c0157848482818110610bad57610bad6137bf565b9050602002016020810190610bc291906137ee565b6040517f1bd4d2d200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260240161082e565b60026000868684818110610c1757610c176137bf565b9050602002016020810190610c2c91906137ee565b67ffffffffffffffff1681526020810191909152604001600090812090610c538282612dee565b6001820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055610c8b600283016000612e0c565b5050610cc9858583818110610ca257610ca26137bf565b9050602002016020810190610cb791906137ee565b60039067ffffffffffffffff16611150565b507f2a680691fef3b2d105196805935232c661ce703e92d464ef0b94a7bc62d714f0858583818110610cfd57610cfd6137bf565b9050602002016020810190610d1291906137ee565b60405167ffffffffffffffff909116815260200160405180910390a1600101610b53565b5060005b81811015610ee0576000838383818110610d5657610d566137bf565b9050602002810190610d689190613809565b610d76906020810190613847565b610d7f90613a49565b90506000848484818110610d9557610d956137bf565b9050602002810190610da79190613809565b610db59060208101906137ee565b9050610dc4826000015161115c565b816020015160ff16600003610e05576040517fa9b3766e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff81166000908152600260209081526040909120835180518593610e35928492910190612e46565b5060208201516001820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff90921691909117905560408201516002820190610e829082613b30565b50610e9c91506003905067ffffffffffffffff83166112a8565b507f05dd57854af2c291a94ea52e7c43d80bc3be7fa73022f98b735dea86642fa5e08183604051610ece929190613c4a565b60405180910390a15050600101610d3a565b5050505050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610f56576040517fac7a7efd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080610f6d610f6886880188613cf5565b6112b4565b8151919350915015610f8557610f858360008461150d565b805115610f9857610f988360018361150d565b5050505050505050565b60006102db825490565b60606000610fb983611ce4565b9392505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314611041576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640161082e565b565b3373ffffffffffffffffffffffffffffffffffffffff8216036110c2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161082e565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60008181526001830160205260408120541515610fb9565b6000610fb98383611d40565b60005b81518110156112a45760008019167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166350c946fe8484815181106111bb576111bb6137bf565b60200260200101516040518263ffffffff1660e01b81526004016111e191815260200190565b600060405180830381865afa1580156111fe573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526112449190810190613f66565b608001510361129c5781818151811061125f5761125f6137bf565b60200260200101516040517f8907a4fa00000000000000000000000000000000000000000000000000000000815260040161082e91815260200190565b60010161115f565b5050565b6000610fb98383611e3a565b606080600460ff16835111156112f6576040517f8854586400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160028082526060820190925290816020015b61137a6040805161014081019091528060008152602001600067ffffffffffffffff168152602001600060ff168152602001600067ffffffffffffffff1681526020016060815260200160608152602001606081526020016060815260200160608152602001606081525090565b81526020019060019003908161130c57505060408051600280825260608201909252919350602082015b6114126040805161014081019091528060008152602001600067ffffffffffffffff168152602001600060ff168152602001600067ffffffffffffffff1681526020016060815260200160608152602001606081526020016060815260200160608152602001606081525090565b8152602001906001900390816113a457905050905060008060005b855181101561150057600086828151811061144a5761144a6137bf565b602002602001015160000151600181111561146757611467613134565b036114b45785818151811061147e5761147e6137bf565b6020026020010151858481518110611498576114986137bf565b6020026020010181905250826114ad9061403e565b92506114f8565b8581815181106114c6576114c66137bf565b60200260200101518483815181106114e0576114e06137bf565b6020026020010181905250816114f59061403e565b91505b60010161142d565b5090835281529092909150565b63ffffffff831660009081526005602052604081208184600181111561153557611535613134565b600181111561154657611546613134565b8152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b828210156119cf57600084815260209020604080516101a08101909152600984029091018054829060608201908390829060ff1660018111156115b9576115b9613134565b60018111156115ca576115ca613134565b8152815467ffffffffffffffff61010082048116602084015260ff690100000000000000000083041660408401526a0100000000000000000000909104166060820152600182018054608090920191611622906136d1565b80601f016020809104026020016040519081016040528092919081815260200182805461164e906136d1565b801561169b5780601f106116705761010080835404028352916020019161169b565b820191906000526020600020905b81548152906001019060200180831161167e57829003601f168201915b50505050508152602001600282018054806020026020016040519081016040528092919081815260200182805480156116f357602002820191906000526020600020905b8154815260200190600101908083116116df575b505050505081526020016003820180548060200260200160405190810160405280929190818152602001828054801561174b57602002820191906000526020600020905b815481526020019060010190808311611737575b5050505050815260200160048201805480602002602001604051908101604052809291908181526020016000905b82821015611825578382906000526020600020018054611798906136d1565b80601f01602080910402602001604051908101604052809291908181526020018280546117c4906136d1565b80156118115780601f106117e657610100808354040283529160200191611811565b820191906000526020600020905b8154815290600101906020018083116117f457829003601f168201915b505050505081526020019060010190611779565b50505050815260200160058201805480602002602001604051908101604052809291908181526020016000905b828210156118fe578382906000526020600020018054611871906136d1565b80601f016020809104026020016040519081016040528092919081815260200182805461189d906136d1565b80156118ea5780601f106118bf576101008083540402835291602001916118ea565b820191906000526020600020905b8154815290600101906020018083116118cd57829003601f168201915b505050505081526020019060010190611852565b505050508152602001600682018054611916906136d1565b80601f0160208091040260200160405190810160405280929190818152602001828054611942906136d1565b801561198f5780601f106119645761010080835404028352916020019161198f565b820191906000526020600020905b81548152906001019060200180831161197257829003601f168201915b505050919092525050508152600782015467ffffffffffffffff166020808301919091526008909201546040909101529082526001929092019101611574565b50505050905060006119e18251611e89565b905060006119ef8451611e89565b90506119fb8282611edb565b6000611a0a8785878686611f97565b9050611a168482612383565b63ffffffff8716600090815260056020526040812090876001811115611a3e57611a3e613134565b6001811115611a4f57611a4f613134565b81526020019081526020016000206000611a699190612e91565b60005b8151811015610f985763ffffffff8816600090815260056020526040812090886001811115611a9d57611a9d613134565b6001811115611aae57611aae613134565b8152602001908152602001600020828281518110611ace57611ace6137bf565b6020908102919091018101518254600181810185556000948552929093208151805160099095029091018054929490939192849283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016908381811115611b3857611b38613134565b021790555060208201518154604084015160608501517fffffffffffffffffffffffffffffffffffffffffffff000000000000000000ff90921661010067ffffffffffffffff948516027fffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffff1617690100000000000000000060ff90921691909102177fffffffffffffffffffffffffffff0000000000000000ffffffffffffffffffff166a0100000000000000000000929091169190910217815560808201516001820190611c079082613b30565b5060a08201518051611c23916002840191602090910190612e46565b5060c08201518051611c3f916003840191602090910190612e46565b5060e08201518051611c5b916004840191602090910190612eb2565b506101008201518051611c78916005840191602090910190612eb2565b506101208201516006820190611c8e9082613b30565b50505060208201516007820180547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff909216919091179055604090910151600890910155600101611a6c565b606081600001805480602002602001604051908101604052809291908181526020018280548015611d3457602002820191906000526020600020905b815481526020019060010190808311611d20575b50505050509050919050565b60008181526001830160205260408120548015611e29576000611d646001836137ac565b8554909150600090611d78906001906137ac565b9050808214611ddd576000866000018281548110611d9857611d986137bf565b9060005260206000200154905080876000018481548110611dbb57611dbb6137bf565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080611dee57611dee614076565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506102db565b60009150506102db565b5092915050565b6000818152600183016020526040812054611e81575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556102db565b5060006102db565b60006002821115611ec9576040517f3e4785260000000000000000000000000000000000000000000000000000000081526004810183905260240161082e565b8160028111156102db576102db613134565b6000826002811115611eef57611eef613134565b826002811115611f0157611f01613134565b611f0b91906140a5565b90508060011480611f575750807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff148015611f5757506002836002811115611f5557611f55613134565b145b15611f6157505050565b82826040517f0a6b675b00000000000000000000000000000000000000000000000000000000815260040161082e9291906140d5565b60606000845167ffffffffffffffff811115611fb557611fb561376a565b604051908082528060200260200182016040528015611fde578160200160208202803683370190505b5090506000846002811115611ff557611ff5613134565b1480156120135750600183600281111561201157612011613134565b145b156120545760018160008151811061202d5761202d6137bf565b602002602001019067ffffffffffffffff16908167ffffffffffffffff16815250506121bc565b600184600281111561206857612068613134565b1480156120865750600283600281111561208457612084613134565b145b1561211d578560008151811061209e5761209e6137bf565b602002602001015160200151816000815181106120bd576120bd6137bf565b602002602001019067ffffffffffffffff16908167ffffffffffffffff1681525050856000815181106120f2576120f26137bf565b602002602001015160200151600161210a91906140f0565b8160018151811061202d5761202d6137bf565b600284600281111561213157612131613134565b14801561214f5750600183600281111561214d5761214d613134565b145b156121865785600181518110612167576121676137bf565b6020026020010151602001518160008151811061202d5761202d6137bf565b83836040517f0a6b675b00000000000000000000000000000000000000000000000000000000815260040161082e9291906140d5565b6000855167ffffffffffffffff8111156121d8576121d861376a565b60405190808252806020026020018201604052801561228e57816020015b604080516101a081018252600060608083018281526080840183905260a0840183905260c0840183905260e084018290526101008401829052610120840182905261014084018290526101608401829052610180840191909152825260208083018290529282015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816121f65790505b50905060005b8251811015612377576122bf8782815181106122b2576122b26137bf565b6020026020010151612702565b60405180606001604052808883815181106122dc576122dc6137bf565b602002602001015181526020018483815181106122fb576122fb6137bf565b602002602001015167ffffffffffffffff16815260200161234f8b868581518110612328576123286137bf565b60200260200101518b8681518110612342576123426137bf565b6020026020010151612acb565b815250828281518110612364576123646137bf565b6020908102919091010152600101612294565b50979650505050505050565b81518151811580156123955750806001145b1561243757826000815181106123ad576123ad6137bf565b60200260200101516020015167ffffffffffffffff1660011461243157826000815181106123dd576123dd6137bf565b60209081029190910181015101516040517fc1658eb800000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526001602482015260440161082e565b50505050565b8160011480156124475750806002145b156125fd578360008151811061245f5761245f6137bf565b6020026020010151604001518360008151811061247e5761247e6137bf565b6020026020010151604001511461250a57826000815181106124a2576124a26137bf565b602002602001015160400151846000815181106124c1576124c16137bf565b6020026020010151604001516040517fc7ccdd7f00000000000000000000000000000000000000000000000000000000815260040161082e929190918252602082015260400190565b8360008151811061251d5761251d6137bf565b602002602001015160200151600161253591906140f0565b67ffffffffffffffff1683600181518110612552576125526137bf565b60200260200101516020015167ffffffffffffffff16146124315782600181518110612580576125806137bf565b6020026020010151602001518460008151811061259f5761259f6137bf565b60200260200101516020015160016125b791906140f0565b6040517fc1658eb800000000000000000000000000000000000000000000000000000000815267ffffffffffffffff92831660048201529116602482015260440161082e565b81600214801561260d5750806001145b156126d05783600181518110612625576126256137bf565b60200260200101516040015183600081518110612644576126446137bf565b602002602001015160400151146124315782600081518110612668576126686137bf565b60200260200101516040015184600181518110612687576126876137bf565b6020026020010151604001516040517f9e97567000000000000000000000000000000000000000000000000000000000815260040161082e929190918252602082015260400190565b6040517f1f1b2bb600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806020015167ffffffffffffffff1660000361274a576040517f698cf8e000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008151600181111561275f5761275f613134565b14158015612780575060018151600181111561277d5761277d613134565b14155b156127b7576040517f3302dbd700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60808101515115806127f4575060408051600060208201520160405160208183030381529060405280519060200120816080015180519060200120145b1561282b576040517f358c192700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208101516128469060039067ffffffffffffffff16611138565b61288e5760208101516040517f1bd4d2d200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260240161082e565b60208082015167ffffffffffffffff166000908152600290915260408120600101546128be9060ff166003614111565b6128c990600161412d565b60ff1690508082610100015151101561292057610100820151516040517f548dd21f00000000000000000000000000000000000000000000000000000000815260048101919091526024810182905260440161082e565b60e082015151610100811115612962576040517f1b925da600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8260c00151518114158061297c5750826101000151518114155b156129d75760c08301515160e084015151610100850151516040517fba900f6d00000000000000000000000000000000000000000000000000000000815260048101939093526024830191909152604482015260640161082e565b826040015160ff16600003612a18576040517f39d1a4d000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040830151612a28906003614111565b60ff168111612a63576040517f4856694e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8260c00151518360a00151511115612aa7576040517f8473d80700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612ab98360a001518460c00151612ba0565b612ac68360c0015161115c565b505050565b60008082602001518584600001518560800151878760a001518860c001518960e001518a61010001518b604001518c606001518d6101200151604051602001612b1f9c9b9a99989796959493929190614146565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e0a000000000000000000000000000000000000000000000000000000000000179150509392505050565b81511580612bad57508051155b15612be4576040517fe249684100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612bed82612d1b565b612bf681612d1b565b6000805b835182108015612c0a5750825181105b15612cdc57828181518110612c2157612c216137bf565b6020026020010151848381518110612c3b57612c3b6137bf565b60200260200101511115612c5957612c528161403e565b9050612bfa565b828181518110612c6b57612c6b6137bf565b6020026020010151848381518110612c8557612c856137bf565b602002602001015103612ca657612c9b8261403e565b9150612c528161403e565b83836040517fd671700c00000000000000000000000000000000000000000000000000000000815260040161082e929190614226565b83518210156124315783836040517fd671700c00000000000000000000000000000000000000000000000000000000815260040161082e929190614226565b60015b81518110156112a45781612d336001836137ac565b81518110612d4357612d436137bf565b6020026020010151828281518110612d5d57612d5d6137bf565b602002602001015111612d9e57816040517f1bc41b4200000000000000000000000000000000000000000000000000000000815260040161082e919061424b565b600101612d1e565b6040518060400160405280600067ffffffffffffffff168152602001612de9604051806060016040528060608152602001600060ff168152602001606081525090565b905290565b5080546000825590600052602060002090810190610b459190612f04565b508054612e18906136d1565b6000825580601f10612e28575050565b601f016020900490600052602060002090810190610b459190612f04565b828054828255906000526020600020908101928215612e81579160200282015b82811115612e81578251825591602001919060010190612e66565b50612e8d929150612f04565b5090565b5080546000825560090290600052602060002090810190610b459190612f19565b828054828255906000526020600020908101928215612ef8579160200282015b82811115612ef85782518290612ee89082613b30565b5091602001919060010190612ed2565b50612e8d929150612fda565b5b80821115612e8d5760008155600101612f05565b80821115612e8d5780547fffffffffffffffffffffffffffff00000000000000000000000000000000000016815560008181612f586001830182612e0c565b612f66600283016000612dee565b612f74600383016000612dee565b612f82600483016000612ff7565b612f90600583016000612ff7565b612f9e600683016000612e0c565b5050506007810180547fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000016905560006008820155600901612f19565b80821115612e8d576000612fee8282612e0c565b50600101612fda565b5080546000825590600052602060002090810190610b459190612fda565b60006020828403121561302757600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610fb957600080fd5b6000815180845260005b8181101561307d57602081850181015186830182015201613061565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000610fb96020830184613057565b63ffffffff81168114610b4557600080fd5b80356130eb816130ce565b919050565b8035600281106130eb57600080fd5b6000806040838503121561311257600080fd5b823561311d816130ce565b915061312b602084016130f0565b90509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6002811061317357613173613134565b9052565b60008151808452602080850194506020840160005b838110156131a85781518752958201959082019060010161318c565b509495945050505050565b60008282518085526020808601955060208260051b8401016020860160005b84811015610b27577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe086840301895261320c838351613057565b988401989250908301906001016131d2565b600060208083018184528085518083526040925060408601915060408160051b87010184880160005b838110156133ed577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc089840301855281516060815181865261328c8287018251613163565b8981015160806132a78189018367ffffffffffffffff169052565b8a830151915060a06132bd818a018460ff169052565b938301519360c092506132db8984018667ffffffffffffffff169052565b818401519450610140915060e082818b01526132fb6101a08b0187613057565b95508185015191507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0610100818c890301818d015261333a8885613177565b97508587015195506101209350818c890301848d015261335a8887613177565b9750828701519550818c890301858d015261337588876131b3565b975080870151955050808b8803016101608c015261339387866131b3565b9650828601519550808b8803016101808c015250505050506133b58282613057565b915050888201516133d18a87018267ffffffffffffffff169052565b5090870151938701939093529386019390860190600101613247565b509098975050505050505050565b60006020828403121561340d57600080fd5b8135610fb9816130ce565b6000806040838503121561342b57600080fd5b50508035926020909101359150565b600081516060845261344f6060850182613177565b905060ff6020840151166020850152604083015184820360408601526134758282613057565b95945050505050565b600060208083018184528085518083526040925060408601915060408160051b87010184880160005b838110156133ed578883037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00185528151805167ffffffffffffffff1684528701518784018790526134fb8785018261343a565b95880195935050908601906001016134a7565b60006020828403121561352057600080fd5b813573ffffffffffffffffffffffffffffffffffffffff81168114610fb957600080fd5b60008083601f84011261355657600080fd5b50813567ffffffffffffffff81111561356e57600080fd5b6020830191508360208260051b850101111561358957600080fd5b9250929050565b600080600080604085870312156135a657600080fd5b843567ffffffffffffffff808211156135be57600080fd5b6135ca88838901613544565b909650945060208701359150808211156135e357600080fd5b506135f087828801613544565b95989497509550505050565b803567ffffffffffffffff811681146130eb57600080fd5b6000806000806000806080878903121561362d57600080fd5b863567ffffffffffffffff8082111561364557600080fd5b6136518a838b01613544565b9098509650602089013591508082111561366a57600080fd5b818901915089601f83011261367e57600080fd5b81358181111561368d57600080fd5b8a602082850101111561369f57600080fd5b6020830196508095505050506136b7604088016135fc565b91506136c5606088016130e0565b90509295509295509295565b600181811c908216806136e557607f821691505b60208210810361371e577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80820281158282048414176102db576102db613724565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b808201808211156102db576102db613724565b818103818111156102db576102db613724565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561380057600080fd5b610fb9826135fc565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc183360301811261383d57600080fd5b9190910192915050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa183360301811261383d57600080fd5b604051610140810167ffffffffffffffff8111828210171561389f5761389f61376a565b60405290565b60405160e0810167ffffffffffffffff8111828210171561389f5761389f61376a565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561390f5761390f61376a565b604052919050565b600067ffffffffffffffff8211156139315761393161376a565b5060051b60200190565b600082601f83011261394c57600080fd5b8135602061396161395c83613917565b6138c8565b8083825260208201915060208460051b87010193508684111561398357600080fd5b602086015b8481101561399f5780358352918301918301613988565b509695505050505050565b803560ff811681146130eb57600080fd5b600082601f8301126139cc57600080fd5b813567ffffffffffffffff8111156139e6576139e661376a565b613a1760207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016138c8565b818152846020838601011115613a2c57600080fd5b816020850160208301376000918101602001919091529392505050565b600060608236031215613a5b57600080fd5b6040516060810167ffffffffffffffff8282108183111715613a7f57613a7f61376a565b816040528435915080821115613a9457600080fd5b613aa03683870161393b565b8352613aae602086016139aa565b60208401526040850135915080821115613ac757600080fd5b50613ad4368286016139bb565b60408301525092915050565b601f821115612ac6576000816000526020600020601f850160051c81016020861015613b095750805b601f850160051c820191505b81811015613b2857828155600101613b15565b505050505050565b815167ffffffffffffffff811115613b4a57613b4a61376a565b613b5e81613b5884546136d1565b84613ae0565b602080601f831160018114613bb15760008415613b7b5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555613b28565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015613bfe57888601518255948401946001909101908401613bdf565b5085821015613c3a57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b67ffffffffffffffff83168152604060208201526000613c6d604083018461343a565b949350505050565b600082601f830112613c8657600080fd5b81356020613c9661395c83613917565b82815260059290921b84018101918181019086841115613cb557600080fd5b8286015b8481101561399f57803567ffffffffffffffff811115613cd95760008081fd5b613ce78986838b01016139bb565b845250918301918301613cb9565b60006020808385031215613d0857600080fd5b823567ffffffffffffffff80821115613d2057600080fd5b818501915085601f830112613d3457600080fd5b8135613d4261395c82613917565b81815260059190911b83018401908481019088831115613d6157600080fd5b8585015b83811015613eef57803585811115613d7c57600080fd5b8601610140818c037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0011215613db157600080fd5b613db961387b565b613dc48983016130f0565b8152613dd2604083016135fc565b89820152613de2606083016139aa565b6040820152613df3608083016135fc565b606082015260a082013587811115613e0a57600080fd5b613e188d8b838601016139bb565b60808301525060c082013587811115613e3057600080fd5b613e3e8d8b8386010161393b565b60a08301525060e082013587811115613e5657600080fd5b613e648d8b8386010161393b565b60c0830152506101008083013588811115613e7e57600080fd5b613e8c8e8c83870101613c75565b60e0840152506101208084013589811115613ea657600080fd5b613eb48f8d83880101613c75565b8385015250610140840135915088821115613ece57600080fd5b613edc8e8c848701016139bb565b9083015250845250918601918601613d65565b5098975050505050505050565b80516130eb816130ce565b600082601f830112613f1857600080fd5b81516020613f2861395c83613917565b8083825260208201915060208460051b870101935086841115613f4a57600080fd5b602086015b8481101561399f5780518352918301918301613f4f565b600060208284031215613f7857600080fd5b815167ffffffffffffffff80821115613f9057600080fd5b9083019060e08286031215613fa457600080fd5b613fac6138a5565b613fb583613efc565b8152613fc360208401613efc565b6020820152613fd460408401613efc565b6040820152606083015160608201526080830151608082015260a083015182811115613fff57600080fd5b61400b87828601613f07565b60a08301525060c08301518281111561402357600080fd5b61402f87828601613f07565b60c08301525095945050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361406f5761406f613724565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b8181036000831280158383131683831282161715611e3357611e33613724565b6003811061317357613173613134565b604081016140e382856140c5565b610fb960208301846140c5565b67ffffffffffffffff818116838216019080821115611e3357611e33613724565b60ff8181168382160290811690818114611e3357611e33613724565b60ff81811683821601908111156102db576102db613724565b67ffffffffffffffff8d16815263ffffffff8c16602082015261416c604082018c613163565b6101806060820152600061418461018083018c613057565b67ffffffffffffffff8b16608084015282810360a08401526141a6818b613177565b905082810360c08401526141ba818a613177565b905082810360e08401526141ce81896131b3565b90508281036101008401526141e381886131b3565b60ff8716610120850152905067ffffffffffffffff85166101408401528281036101608401526142138185613057565b9f9e505050505050505050505050505050565b6040815260006142396040830185613177565b82810360208401526134758185613177565b602081526000610fb9602083018461317756fea164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"capabilitiesRegistry\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainSelectorNotFound\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ChainSelectorNotSet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FChainMustBePositive\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FMustBePositive\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FTooHigh\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"length\",\"type\":\"uint256\"}],\"name\":\"InvalidConfigLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enumCCIPConfigTypes.ConfigState\",\"name\":\"currentState\",\"type\":\"uint8\"},{\"internalType\":\"enumCCIPConfigTypes.ConfigState\",\"name\":\"proposedState\",\"type\":\"uint8\"}],\"name\":\"InvalidConfigStateTransition\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidPluginType\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"}],\"name\":\"NodeNotInRegistry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonExistentConfigTransition\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"got\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minimum\",\"type\":\"uint256\"}],\"name\":\"NotEnoughTransmitters\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OfframpAddressCannotBeZero\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCapabilitiesRegistryCanCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"p2pIdsLength\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"signersLength\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"transmittersLength\",\"type\":\"uint256\"}],\"name\":\"P2PIdsLengthNotMatching\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManyOCR3Configs\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManySigners\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"got\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"expected\",\"type\":\"uint64\"}],\"name\":\"WrongConfigCount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"got\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"}],\"name\":\"WrongConfigDigest\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"got\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"}],\"name\":\"WrongConfigDigestBlueGreen\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"CapabilityConfigurationSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainConfigRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes32[]\",\"name\":\"readers\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint8\",\"name\":\"fChain\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"structCCIPConfigTypes.ChainConfig\",\"name\":\"chainConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"chainSelectorRemoves\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes32[]\",\"name\":\"readers\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint8\",\"name\":\"fChain\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPConfigTypes.ChainConfig\",\"name\":\"chainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structCCIPConfigTypes.ChainConfigInfo[]\",\"name\":\"chainConfigAdds\",\"type\":\"tuple[]\"}],\"name\":\"applyChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"}],\"name\":\"beforeCapabilityConfigSet\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"pageIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pageSize\",\"type\":\"uint256\"}],\"name\":\"getAllChainConfigs\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes32[]\",\"name\":\"readers\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint8\",\"name\":\"fChain\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPConfigTypes.ChainConfig\",\"name\":\"chainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structCCIPConfigTypes.ChainConfigInfo[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"name\":\"getCapabilityConfiguration\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"configuration\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCapabilityRegistry\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"}],\"name\":\"getOCRConfig\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offrampAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"p2pIds\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes[]\",\"name\":\"signers\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes[]\",\"name\":\"transmitters\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPConfigTypes.OCR3Config\",\"name\":\"config\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"configCount\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"internalType\":\"structCCIPConfigTypes.OCR3ConfigWithMeta[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x60a06040523480156200001157600080fd5b5060405162004080380380620040808339810160408190526200003491620001a6565b33806000816200008b5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000be57620000be81620000fb565b5050506001600160a01b038116620000e9576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b0316608052620001d8565b336001600160a01b03821603620001555760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000082565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600060208284031215620001b957600080fd5b81516001600160a01b0381168114620001d157600080fd5b9392505050565b608051613e7f620002016000396000818160f801528181610ea701526111170152613e7f6000f3fe608060405234801561001057600080fd5b50600436106100c95760003560e01c80638318ed5d11610081578063f2fde38b1161005b578063f2fde38b1461020f578063f442c89a14610222578063fba64a7c1461023557600080fd5b80638318ed5d146101b05780638da5cb5b146101d1578063b74b2356146101ef57600080fd5b8063181f5a77116100b2578063181f5a771461013d5780634bd0473f1461018657806379ba5097146101a657600080fd5b806301ffc9a7146100ce578063020330e6146100f6575b600080fd5b6100e16100dc366004612cbd565b610248565b60405190151581526020015b60405180910390f35b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100ed565b6101796040518060400160405280601481526020017f43434950436f6e66696720312e362e302d64657600000000000000000000000081525081565b6040516100ed9190612d63565b610199610194366004612da7565b6102e1565b6040516100ed9190612ec6565b6101ae610759565b005b6101796101be366004613082565b5060408051602081019091526000815290565b60005473ffffffffffffffffffffffffffffffffffffffff16610118565b6102026101fd36600461309f565b61085b565b6040516100ed9190613105565b6101ae61021d366004613195565b610adc565b6101ae610230366004613217565b610af0565b6101ae61024336600461329b565b610e8f565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f78bea7210000000000000000000000000000000000000000000000000000000014806102db57507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b63ffffffff8216600090815260056020526040812060609183600181111561030b5761030b612ddc565b600181111561031c5761031c612ddc565b8152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b8282101561074d57600084815260209020604080516101808101909152600884029091018054829060608201908390829060ff16600181111561038f5761038f612ddc565b60018111156103a0576103a0612ddc565b8152815467ffffffffffffffff61010082048116602084015260ff690100000000000000000083041660408401526a01000000000000000000009091041660608201526001820180546080909201916103f890613358565b80601f016020809104026020016040519081016040528092919081815260200182805461042490613358565b80156104715780601f1061044657610100808354040283529160200191610471565b820191906000526020600020905b81548152906001019060200180831161045457829003601f168201915b50505050508152602001600282018054806020026020016040519081016040528092919081815260200182805480156104c957602002820191906000526020600020905b8154815260200190600101908083116104b5575b5050505050815260200160038201805480602002602001604051908101604052809291908181526020016000905b828210156105a357838290600052602060002001805461051690613358565b80601f016020809104026020016040519081016040528092919081815260200182805461054290613358565b801561058f5780601f106105645761010080835404028352916020019161058f565b820191906000526020600020905b81548152906001019060200180831161057257829003601f168201915b5050505050815260200190600101906104f7565b50505050815260200160048201805480602002602001604051908101604052809291908181526020016000905b8282101561067c5783829060005260206000200180546105ef90613358565b80601f016020809104026020016040519081016040528092919081815260200182805461061b90613358565b80156106685780601f1061063d57610100808354040283529160200191610668565b820191906000526020600020905b81548152906001019060200180831161064b57829003601f168201915b5050505050815260200190600101906105d0565b50505050815260200160058201805461069490613358565b80601f01602080910402602001604051908101604052809291908181526020018280546106c090613358565b801561070d5780601f106106e25761010080835404028352916020019161070d565b820191906000526020600020905b8154815290600101906020018083116106f057829003601f168201915b505050919092525050508152600682015467ffffffffffffffff16602080830191909152600790920154604090910152908252600192909201910161034a565b50505050905092915050565b60015473ffffffffffffffffffffffffffffffffffffffff1633146107df576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b606060006108696003610f4a565b9050600061087784866133da565b90508315806108865750818110155b156108c65760408051600080825260208201909252906108bc565b6108a9612a5c565b8152602001906001900390816108a15790505b50925050506102db565b60006108d28583613420565b9050828111156108df5750815b60006108eb8383613433565b67ffffffffffffffff811115610903576109036133f1565b60405190808252806020026020018201604052801561093c57816020015b610929612a5c565b8152602001906001900390816109215790505b509050600061094b6003610f54565b9050835b83811015610acf57600082828151811061096b5761096b613446565b60209081029190910181015160408051808201825267ffffffffffffffff8316808252600090815260028552829020825181546080818802830181019095526060820181815295975092958601949093919284928491908401828280156109f157602002820191906000526020600020905b8154815260200190600101908083116109dd575b5050509183525050600182015460ff166020820152600282018054604090920191610a1b90613358565b80601f0160208091040260200160405190810160405280929190818152602001828054610a4790613358565b8015610a945780601f10610a6957610100808354040283529160200191610a94565b820191906000526020600020905b815481529060010190602001808311610a7757829003601f168201915b50505091909252505050905284610aab8885613433565b81518110610abb57610abb613446565b60209081029190910101525060010161094f565b5090979650505050505050565b610ae4610f68565b610aed81610feb565b50565b610af8610f68565b60005b83811015610cde57610b3f858583818110610b1857610b18613446565b9050602002016020810190610b2d9190613475565b60039067ffffffffffffffff166110e0565b610ba957848482818110610b5557610b55613446565b9050602002016020810190610b6a9190613475565b6040517f1bd4d2d200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016107d6565b60026000868684818110610bbf57610bbf613446565b9050602002016020810190610bd49190613475565b67ffffffffffffffff1681526020810191909152604001600090812090610bfb8282612aa4565b6001820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055610c33600283016000612ac2565b5050610c71858583818110610c4a57610c4a613446565b9050602002016020810190610c5f9190613475565b60039067ffffffffffffffff166110f8565b507f2a680691fef3b2d105196805935232c661ce703e92d464ef0b94a7bc62d714f0858583818110610ca557610ca5613446565b9050602002016020810190610cba9190613475565b60405167ffffffffffffffff909116815260200160405180910390a1600101610afb565b5060005b81811015610e88576000838383818110610cfe57610cfe613446565b9050602002810190610d109190613490565b610d1e9060208101906134ce565b610d27906136d0565b90506000848484818110610d3d57610d3d613446565b9050602002810190610d4f9190613490565b610d5d906020810190613475565b9050610d6c8260000151611104565b816020015160ff16600003610dad576040517fa9b3766e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff81166000908152600260209081526040909120835180518593610ddd928492910190612afc565b5060208201516001820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff90921691909117905560408201516002820190610e2a90826137b7565b50610e4491506003905067ffffffffffffffff8316611250565b507f05dd57854af2c291a94ea52e7c43d80bc3be7fa73022f98b735dea86642fa5e08183604051610e769291906138d1565b60405180910390a15050600101610ce2565b5050505050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610efe576040517fac7a7efd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080610f15610f108688018861397c565b61125c565b8151919350915015610f2d57610f2d836000846114a7565b805115610f4057610f40836001836114a7565b5050505050505050565b60006102db825490565b60606000610f6183611c09565b9392505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610fe9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016107d6565b565b3373ffffffffffffffffffffffffffffffffffffffff82160361106a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016107d6565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60008181526001830160205260408120541515610f61565b6000610f618383611c65565b60005b815181101561124c5760008019167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166350c946fe84848151811061116357611163613446565b60200260200101516040518263ffffffff1660e01b815260040161118991815260200190565b600060405180830381865afa1580156111a6573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526111ec9190810190613bc7565b60800151036112445781818151811061120757611207613446565b60200260200101516040517f8907a4fa0000000000000000000000000000000000000000000000000000000081526004016107d691815260200190565b600101611107565b5050565b6000610f618383611d5f565b606080600460ff168351111561129e576040517f8854586400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160028082526060820190925290816020015b61131b6040805161012081019091528060008152602001600067ffffffffffffffff168152602001600060ff168152602001600067ffffffffffffffff16815260200160608152602001606081526020016060815260200160608152602001606081525090565b8152602001906001900390816112b457505060408051600280825260608201909252919350602082015b6113ac6040805161012081019091528060008152602001600067ffffffffffffffff168152602001600060ff168152602001600067ffffffffffffffff16815260200160608152602001606081526020016060815260200160608152602001606081525090565b81526020019060019003908161134557905050905060008060005b855181101561149a5760008682815181106113e4576113e4613446565b602002602001015160000151600181111561140157611401612ddc565b0361144e5785818151811061141857611418613446565b602002602001015185848151811061143257611432613446565b60200260200101819052508261144790613c9f565b9250611492565b85818151811061146057611460613446565b602002602001015184838151811061147a5761147a613446565b60200260200101819052508161148f90613c9f565b91505b6001016113c7565b5090835281529092909150565b63ffffffff83166000908152600560205260408120818460018111156114cf576114cf612ddc565b60018111156114e0576114e0612ddc565b8152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b8282101561191157600084815260209020604080516101808101909152600884029091018054829060608201908390829060ff16600181111561155357611553612ddc565b600181111561156457611564612ddc565b8152815467ffffffffffffffff61010082048116602084015260ff690100000000000000000083041660408401526a01000000000000000000009091041660608201526001820180546080909201916115bc90613358565b80601f01602080910402602001604051908101604052809291908181526020018280546115e890613358565b80156116355780601f1061160a57610100808354040283529160200191611635565b820191906000526020600020905b81548152906001019060200180831161161857829003601f168201915b505050505081526020016002820180548060200260200160405190810160405280929190818152602001828054801561168d57602002820191906000526020600020905b815481526020019060010190808311611679575b5050505050815260200160038201805480602002602001604051908101604052809291908181526020016000905b828210156117675783829060005260206000200180546116da90613358565b80601f016020809104026020016040519081016040528092919081815260200182805461170690613358565b80156117535780601f1061172857610100808354040283529160200191611753565b820191906000526020600020905b81548152906001019060200180831161173657829003601f168201915b5050505050815260200190600101906116bb565b50505050815260200160048201805480602002602001604051908101604052809291908181526020016000905b828210156118405783829060005260206000200180546117b390613358565b80601f01602080910402602001604051908101604052809291908181526020018280546117df90613358565b801561182c5780601f106118015761010080835404028352916020019161182c565b820191906000526020600020905b81548152906001019060200180831161180f57829003601f168201915b505050505081526020019060010190611794565b50505050815260200160058201805461185890613358565b80601f016020809104026020016040519081016040528092919081815260200182805461188490613358565b80156118d15780601f106118a6576101008083540402835291602001916118d1565b820191906000526020600020905b8154815290600101906020018083116118b457829003601f168201915b505050919092525050508152600682015467ffffffffffffffff16602080830191909152600790920154604090910152908252600192909201910161150e565b50505050905060006119238251611dae565b905060006119318451611dae565b905061193d8282611e00565b600061194c8785878686611ebc565b905061195884826122a0565b63ffffffff871660009081526005602052604081209087600181111561198057611980612ddc565b600181111561199157611991612ddc565b815260200190815260200160002060006119ab9190612b47565b60005b8151811015610f405763ffffffff88166000908152600560205260408120908860018111156119df576119df612ddc565b60018111156119f0576119f0612ddc565b8152602001908152602001600020828281518110611a1057611a10613446565b6020908102919091018101518254600181810185556000948552929093208151805160089095029091018054929490939192849283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016908381811115611a7a57611a7a612ddc565b021790555060208201518154604084015160608501517fffffffffffffffffffffffffffffffffffffffffffff000000000000000000ff90921661010067ffffffffffffffff948516027fffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffff1617690100000000000000000060ff90921691909102177fffffffffffffffffffffffffffff0000000000000000ffffffffffffffffffff166a0100000000000000000000929091169190910217815560808201516001820190611b4990826137b7565b5060a08201518051611b65916002840191602090910190612afc565b5060c08201518051611b81916003840191602090910190612b68565b5060e08201518051611b9d916004840191602090910190612b68565b506101008201516005820190611bb390826137b7565b50505060208201516006820180547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff9092169190911790556040909101516007909101556001016119ae565b606081600001805480602002602001604051908101604052809291908181526020018280548015611c5957602002820191906000526020600020905b815481526020019060010190808311611c45575b50505050509050919050565b60008181526001830160205260408120548015611d4e576000611c89600183613433565b8554909150600090611c9d90600190613433565b9050808214611d02576000866000018281548110611cbd57611cbd613446565b9060005260206000200154905080876000018481548110611ce057611ce0613446565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080611d1357611d13613cd7565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506102db565b60009150506102db565b5092915050565b6000818152600183016020526040812054611da6575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556102db565b5060006102db565b60006002821115611dee576040517f3e478526000000000000000000000000000000000000000000000000000000008152600481018390526024016107d6565b8160028111156102db576102db612ddc565b6000826002811115611e1457611e14612ddc565b826002811115611e2657611e26612ddc565b611e309190613d06565b90508060011480611e7c5750807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff148015611e7c57506002836002811115611e7a57611e7a612ddc565b145b15611e8657505050565b82826040517f0a6b675b0000000000000000000000000000000000000000000000000000000081526004016107d6929190613d36565b60606000845167ffffffffffffffff811115611eda57611eda6133f1565b604051908082528060200260200182016040528015611f03578160200160208202803683370190505b5090506000846002811115611f1a57611f1a612ddc565b148015611f3857506001836002811115611f3657611f36612ddc565b145b15611f7957600181600081518110611f5257611f52613446565b602002602001019067ffffffffffffffff16908167ffffffffffffffff16815250506120e1565b6001846002811115611f8d57611f8d612ddc565b148015611fab57506002836002811115611fa957611fa9612ddc565b145b156120425785600081518110611fc357611fc3613446565b60200260200101516020015181600081518110611fe257611fe2613446565b602002602001019067ffffffffffffffff16908167ffffffffffffffff16815250508560008151811061201757612017613446565b602002602001015160200151600161202f9190613d51565b81600181518110611f5257611f52613446565b600284600281111561205657612056612ddc565b1480156120745750600183600281111561207257612072612ddc565b145b156120ab578560018151811061208c5761208c613446565b60200260200101516020015181600081518110611f5257611f52613446565b83836040517f0a6b675b0000000000000000000000000000000000000000000000000000000081526004016107d6929190613d36565b6000855167ffffffffffffffff8111156120fd576120fd6133f1565b6040519080825280602002602001820160405280156121ab57816020015b6040805161018081018252600060608083018281526080840183905260a0840183905260c0840183905260e08401829052610100840182905261012084018290526101408401829052610160840191909152825260208083018290529282015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90920191018161211b5790505b50905060005b8251811015612294576121dc8782815181106121cf576121cf613446565b602002602001015161261f565b60405180606001604052808883815181106121f9576121f9613446565b6020026020010151815260200184838151811061221857612218613446565b602002602001015167ffffffffffffffff16815260200161226c8b86858151811061224557612245613446565b60200260200101518b868151811061225f5761225f613446565b602002602001015161298e565b81525082828151811061228157612281613446565b60209081029190910101526001016121b1565b50979650505050505050565b81518151811580156122b25750806001145b1561235457826000815181106122ca576122ca613446565b60200260200101516020015167ffffffffffffffff1660011461234e57826000815181106122fa576122fa613446565b60209081029190910181015101516040517fc1658eb800000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152600160248201526044016107d6565b50505050565b8160011480156123645750806002145b1561251a578360008151811061237c5761237c613446565b6020026020010151604001518360008151811061239b5761239b613446565b6020026020010151604001511461242757826000815181106123bf576123bf613446565b602002602001015160400151846000815181106123de576123de613446565b6020026020010151604001516040517fc7ccdd7f0000000000000000000000000000000000000000000000000000000081526004016107d6929190918252602082015260400190565b8360008151811061243a5761243a613446565b60200260200101516020015160016124529190613d51565b67ffffffffffffffff168360018151811061246f5761246f613446565b60200260200101516020015167ffffffffffffffff161461234e578260018151811061249d5761249d613446565b602002602001015160200151846000815181106124bc576124bc613446565b60200260200101516020015160016124d49190613d51565b6040517fc1658eb800000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9283166004820152911660248201526044016107d6565b81600214801561252a5750806001145b156125ed578360018151811061254257612542613446565b6020026020010151604001518360008151811061256157612561613446565b6020026020010151604001511461234e578260008151811061258557612585613446565b602002602001015160400151846001815181106125a4576125a4613446565b6020026020010151604001516040517f9e9756700000000000000000000000000000000000000000000000000000000081526004016107d6929190918252602082015260400190565b6040517f1f1b2bb600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806020015167ffffffffffffffff16600003612667576040517f698cf8e000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008151600181111561267c5761267c612ddc565b1415801561269d575060018151600181111561269a5761269a612ddc565b14155b156126d4576040517f3302dbd700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6080810151511580612711575060408051600060208201520160405160208183030381529060405280519060200120816080015180519060200120145b15612748576040517f358c192700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208101516127639060039067ffffffffffffffff166110e0565b6127ab5760208101516040517f1bd4d2d200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016107d6565b60208082015167ffffffffffffffff166000908152600290915260408120600101546127db9060ff166003613d72565b6127e6906001613d8e565b60ff169050808260e0015151101561283b5760e0820151516040517f548dd21f0000000000000000000000000000000000000000000000000000000081526004810191909152602481018290526044016107d6565b60c08201515161010081111561287d576040517f1b925da600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8260a00151518114158061289657508260e00151518114155b156128f05760a08301515160c08401515160e0850151516040517fba900f6d0000000000000000000000000000000000000000000000000000000081526004810193909352602483019190915260448201526064016107d6565b826040015160ff16600003612931576040517f39d1a4d000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040830151612941906003613d72565b60ff16811161297c576040517f4856694e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6129898360a00151611104565b505050565b60008082602001518584600001518560800151878760a001518860c001518960e001518a604001518b606001518c61010001516040516020016129db9b9a99989796959493929190613da7565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e0a000000000000000000000000000000000000000000000000000000000000179150509392505050565b6040518060400160405280600067ffffffffffffffff168152602001612a9f604051806060016040528060608152602001600060ff168152602001606081525090565b905290565b5080546000825590600052602060002090810190610aed9190612bba565b508054612ace90613358565b6000825580601f10612ade575050565b601f016020900490600052602060002090810190610aed9190612bba565b828054828255906000526020600020908101928215612b37579160200282015b82811115612b37578251825591602001919060010190612b1c565b50612b43929150612bba565b5090565b5080546000825560080290600052602060002090810190610aed9190612bcf565b828054828255906000526020600020908101928215612bae579160200282015b82811115612bae5782518290612b9e90826137b7565b5091602001919060010190612b88565b50612b43929150612c82565b5b80821115612b435760008155600101612bbb565b80821115612b435780547fffffffffffffffffffffffffffff00000000000000000000000000000000000016815560008181612c0e6001830182612ac2565b612c1c600283016000612aa4565b612c2a600383016000612c9f565b612c38600483016000612c9f565b612c46600583016000612ac2565b5050506006810180547fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000016905560006007820155600801612bcf565b80821115612b43576000612c968282612ac2565b50600101612c82565b5080546000825590600052602060002090810190610aed9190612c82565b600060208284031215612ccf57600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610f6157600080fd5b6000815180845260005b81811015612d2557602081850181015186830182015201612d09565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000610f616020830184612cff565b63ffffffff81168114610aed57600080fd5b8035612d9381612d76565b919050565b803560028110612d9357600080fd5b60008060408385031215612dba57600080fd5b8235612dc581612d76565b9150612dd360208401612d98565b90509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60028110612e1b57612e1b612ddc565b9052565b60008151808452602080850194506020840160005b83811015612e5057815187529582019590820190600101612e34565b509495945050505050565b60008282518085526020808601955060208260051b8401016020860160005b84811015610acf577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018952612eb4838351612cff565b98840198925090830190600101612e7a565b600060208083018184528085518083526040925060408601915060408160051b87010184880160005b83811015613074577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0898403018552815160608151818652612f348287018251612e0b565b898101516080612f4f8189018367ffffffffffffffff169052565b8a830151915060a0612f65818a018460ff169052565b938301519360c09250612f838984018667ffffffffffffffff169052565b818401519450610120915060e082818b0152612fa36101808b0187612cff565b95508185015191507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0610100818c890301818d0152612fe28885612e1f565b958701518c87038301868e0152959750612ffc8887612e5b565b9750828701519550818c8903016101408d01526130198887612e5b565b975080870151965050808b8803016101608c0152505050505061303c8282612cff565b915050888201516130588a87018267ffffffffffffffff169052565b5090870151938701939093529386019390860190600101612eef565b509098975050505050505050565b60006020828403121561309457600080fd5b8135610f6181612d76565b600080604083850312156130b257600080fd5b50508035926020909101359150565b60008151606084526130d66060850182612e1f565b905060ff6020840151166020850152604083015184820360408601526130fc8282612cff565b95945050505050565b600060208083018184528085518083526040925060408601915060408160051b87010184880160005b83811015613074578883037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00185528151805167ffffffffffffffff168452870151878401879052613182878501826130c1565b958801959350509086019060010161312e565b6000602082840312156131a757600080fd5b813573ffffffffffffffffffffffffffffffffffffffff81168114610f6157600080fd5b60008083601f8401126131dd57600080fd5b50813567ffffffffffffffff8111156131f557600080fd5b6020830191508360208260051b850101111561321057600080fd5b9250929050565b6000806000806040858703121561322d57600080fd5b843567ffffffffffffffff8082111561324557600080fd5b613251888389016131cb565b9096509450602087013591508082111561326a57600080fd5b50613277878288016131cb565b95989497509550505050565b803567ffffffffffffffff81168114612d9357600080fd5b600080600080600080608087890312156132b457600080fd5b863567ffffffffffffffff808211156132cc57600080fd5b6132d88a838b016131cb565b909850965060208901359150808211156132f157600080fd5b818901915089601f83011261330557600080fd5b81358181111561331457600080fd5b8a602082850101111561332657600080fd5b60208301965080955050505061333e60408801613283565b915061334c60608801612d88565b90509295509295509295565b600181811c9082168061336c57607f821691505b6020821081036133a5577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80820281158282048414176102db576102db6133ab565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b808201808211156102db576102db6133ab565b818103818111156102db576102db6133ab565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561348757600080fd5b610f6182613283565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc18336030181126134c457600080fd5b9190910192915050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa18336030181126134c457600080fd5b604051610120810167ffffffffffffffff81118282101715613526576135266133f1565b60405290565b60405160e0810167ffffffffffffffff81118282101715613526576135266133f1565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613596576135966133f1565b604052919050565b600067ffffffffffffffff8211156135b8576135b86133f1565b5060051b60200190565b600082601f8301126135d357600080fd5b813560206135e86135e38361359e565b61354f565b8083825260208201915060208460051b87010193508684111561360a57600080fd5b602086015b84811015613626578035835291830191830161360f565b509695505050505050565b803560ff81168114612d9357600080fd5b600082601f83011261365357600080fd5b813567ffffffffffffffff81111561366d5761366d6133f1565b61369e60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160161354f565b8181528460208386010111156136b357600080fd5b816020850160208301376000918101602001919091529392505050565b6000606082360312156136e257600080fd5b6040516060810167ffffffffffffffff8282108183111715613706576137066133f1565b81604052843591508082111561371b57600080fd5b613727368387016135c2565b835261373560208601613631565b6020840152604085013591508082111561374e57600080fd5b5061375b36828601613642565b60408301525092915050565b601f821115612989576000816000526020600020601f850160051c810160208610156137905750805b601f850160051c820191505b818110156137af5782815560010161379c565b505050505050565b815167ffffffffffffffff8111156137d1576137d16133f1565b6137e5816137df8454613358565b84613767565b602080601f83116001811461383857600084156138025750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556137af565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b8281101561388557888601518255948401946001909101908401613866565b50858210156138c157878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b67ffffffffffffffff831681526040602082015260006138f460408301846130c1565b949350505050565b600082601f83011261390d57600080fd5b8135602061391d6135e38361359e565b82815260059290921b8401810191818101908684111561393c57600080fd5b8286015b8481101561362657803567ffffffffffffffff8111156139605760008081fd5b61396e8986838b0101613642565b845250918301918301613940565b6000602080838503121561398f57600080fd5b823567ffffffffffffffff808211156139a757600080fd5b818501915085601f8301126139bb57600080fd5b81356139c96135e38261359e565b81815260059190911b830184019084810190888311156139e857600080fd5b8585015b83811015613b5057803585811115613a0357600080fd5b8601610120818c037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001811315613a3957600080fd5b613a41613502565b613a4c8a8401612d98565b8152613a5a60408401613283565b8a820152613a6a60608401613631565b6040820152613a7b60808401613283565b606082015260a083013588811115613a9257600080fd5b613aa08e8c83870101613642565b60808301525060c083013588811115613ab857600080fd5b613ac68e8c838701016135c2565b60a08301525060e083013588811115613adf5760008081fd5b613aed8e8c838701016138fc565b60c0830152506101008084013589811115613b085760008081fd5b613b168f8d838801016138fc565b60e084015250918301359188831115613b2f5760008081fd5b613b3d8e8c85870101613642565b90820152855250509186019186016139ec565b5098975050505050505050565b8051612d9381612d76565b600082601f830112613b7957600080fd5b81516020613b896135e38361359e565b8083825260208201915060208460051b870101935086841115613bab57600080fd5b602086015b848110156136265780518352918301918301613bb0565b600060208284031215613bd957600080fd5b815167ffffffffffffffff80821115613bf157600080fd5b9083019060e08286031215613c0557600080fd5b613c0d61352c565b613c1683613b5d565b8152613c2460208401613b5d565b6020820152613c3560408401613b5d565b6040820152606083015160608201526080830151608082015260a083015182811115613c6057600080fd5b613c6c87828601613b68565b60a08301525060c083015182811115613c8457600080fd5b613c9087828601613b68565b60c08301525095945050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613cd057613cd06133ab565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b8181036000831280158383131683831282161715611d5857611d586133ab565b60038110612e1b57612e1b612ddc565b60408101613d448285613d26565b610f616020830184613d26565b67ffffffffffffffff818116838216019080821115611d5857611d586133ab565b60ff8181168382160290811690818114611d5857611d586133ab565b60ff81811683821601908111156102db576102db6133ab565b600061016067ffffffffffffffff8e16835263ffffffff8d166020840152613dd2604084018d612e0b565b806060840152613de48184018c612cff565b67ffffffffffffffff8b166080850152905082810360a0840152613e08818a612e1f565b905082810360c0840152613e1c8189612e5b565b905082810360e0840152613e308188612e5b565b60ff8716610100850152905067ffffffffffffffff8516610120840152828103610140840152613e608185612cff565b9e9d505050505050505050505050505056fea164736f6c6343000818000a", } var CCIPConfigABI = CCIPConfigMetaData.ABI diff --git a/core/gethwrappers/ccip/generated/ocr3_config_encoder/ocr3_config_encoder.go b/core/gethwrappers/ccip/generated/ocr3_config_encoder/ocr3_config_encoder.go index 399ae5dbd6..737a768dbe 100644 --- a/core/gethwrappers/ccip/generated/ocr3_config_encoder/ocr3_config_encoder.go +++ b/core/gethwrappers/ccip/generated/ocr3_config_encoder/ocr3_config_encoder.go @@ -34,7 +34,6 @@ type CCIPConfigTypesOCR3Config struct { F uint8 OffchainConfigVersion uint64 OfframpAddress []byte - BootstrapP2PIds [][32]byte P2pIds [][32]byte Signers [][]byte Transmitters [][]byte @@ -42,7 +41,7 @@ type CCIPConfigTypesOCR3Config struct { } var IOCR3ConfigEncoderMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offrampAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"bootstrapP2PIds\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"p2pIds\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes[]\",\"name\":\"signers\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes[]\",\"name\":\"transmitters\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPConfigTypes.OCR3Config[]\",\"name\":\"config\",\"type\":\"tuple[]\"}],\"name\":\"exposeOCR3Config\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offrampAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"p2pIds\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes[]\",\"name\":\"signers\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes[]\",\"name\":\"transmitters\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPConfigTypes.OCR3Config[]\",\"name\":\"config\",\"type\":\"tuple[]\"}],\"name\":\"exposeOCR3Config\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", } var IOCR3ConfigEncoderABI = IOCR3ConfigEncoderMetaData.ABI diff --git a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt index 77f04c61c6..055c0874ba 100644 --- a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -4,7 +4,7 @@ burn_mint_token_pool: ../../../contracts/solc/v0.8.24/BurnMintTokenPool/BurnMint burn_mint_token_pool_and_proxy: ../../../contracts/solc/v0.8.24/BurnMintTokenPoolAndProxy/BurnMintTokenPoolAndProxy.abi ../../../contracts/solc/v0.8.24/BurnMintTokenPoolAndProxy/BurnMintTokenPoolAndProxy.bin 717c079d5d13300cf3c3ee871c6e5bf9af904411f204fb081a9f3b263cca1391 burn_with_from_mint_token_pool: ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.abi ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.bin 6333d0314d0bd29e75ea5e05fe62a4516ade0c6db91c30b6f93645035db52ed8 burn_with_from_mint_token_pool_and_proxy: ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPoolAndProxy/BurnWithFromMintTokenPoolAndProxy.abi ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPoolAndProxy/BurnWithFromMintTokenPoolAndProxy.bin 08ed1235dda921ce8841b26aa18d0c0f36db4884779dd7670857159801b6d597 -ccip_config: ../../../contracts/solc/v0.8.24/CCIPConfig/CCIPConfig.abi ../../../contracts/solc/v0.8.24/CCIPConfig/CCIPConfig.bin 02da0d657b0835cf89f39ba790a96cab4595d27e16ebb7242a40dcec67e9da56 +ccip_config: ../../../contracts/solc/v0.8.24/CCIPConfig/CCIPConfig.abi ../../../contracts/solc/v0.8.24/CCIPConfig/CCIPConfig.bin 75955a3dcfd66b308be07eda54d6036cc79e87d3cdcf3c5c3115813c55912af8 ccip_reader_tester: ../../../contracts/solc/v0.8.24/CCIPReaderTester/CCIPReaderTester.abi ../../../contracts/solc/v0.8.24/CCIPReaderTester/CCIPReaderTester.bin d8d70fe111bacc7702c7c263f8c4733dcb2fff77e52c9f60c30d303731bc97c1 commit_store: ../../../contracts/solc/v0.8.24/CommitStore/CommitStore.abi ../../../contracts/solc/v0.8.24/CommitStore/CommitStore.bin 274d87db70b643e00ab0a7e7845bb4b791f3b613bfc87708d33fc5a8369e2a41 commit_store_helper: ../../../contracts/solc/v0.8.24/CommitStoreHelper/CommitStoreHelper.abi ../../../contracts/solc/v0.8.24/CommitStoreHelper/CommitStoreHelper.bin f7128dcc2ee6dbcbc976288abcc16970ffb19b59412c5202ef6b259d2007f801 @@ -22,7 +22,7 @@ mock_v3_aggregator_contract: ../../../contracts/solc/v0.8.24/MockV3Aggregator/Mo multi_aggregate_rate_limiter: ../../../contracts/solc/v0.8.24/MultiAggregateRateLimiter/MultiAggregateRateLimiter.abi ../../../contracts/solc/v0.8.24/MultiAggregateRateLimiter/MultiAggregateRateLimiter.bin 0b541232e49727e947dc164eadf35963c66e67576f21baa0ecaa06a8833148ed multi_ocr3_helper: ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Helper.abi ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Helper.bin 6b56e0114a4d50797d30a34aecc2641ef340451d0c3fcb9d729bba4df2435122 nonce_manager: ../../../contracts/solc/v0.8.24/NonceManager/NonceManager.abi ../../../contracts/solc/v0.8.24/NonceManager/NonceManager.bin 6f64e1083b356c06ee66b9138e398b9c97a4cd3e8c9ec38cf3010cebc79af536 -ocr3_config_encoder: ../../../contracts/solc/v0.8.24/IOCR3ConfigEncoder/IOCR3ConfigEncoder.abi ../../../contracts/solc/v0.8.24/IOCR3ConfigEncoder/IOCR3ConfigEncoder.bin e21180898e1ad54a045ee20add85a2793c681425ea06f66d1a9e5cab128b6487 +ocr3_config_encoder: ../../../contracts/solc/v0.8.24/IOCR3ConfigEncoder/IOCR3ConfigEncoder.abi ../../../contracts/solc/v0.8.24/IOCR3ConfigEncoder/IOCR3ConfigEncoder.bin 9254b35a86f00fde7b7193a033ca58f6521a66e87b9cf9da6ce5660082e79f5d offramp: ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.abi ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.bin 136ae93018723f03d695f60348231d58cacf53e4de2016fa6e638eba7bd64af7 onramp: ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.abi ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.bin c3b345930e1a553b18553e18a5c0ff8df3c372118fdf78a176aaccb1891664bb ping_pong_demo: ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.abi ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.bin c1c2f8a65c7ffd971899cae7fe62f2da57d09e936151e2b92163c4bebe699d6b From d2c51be5ad875d935c79d9743631f8e29ef81ac7 Mon Sep 17 00:00:00 2001 From: Ryan Hall Date: Wed, 4 Sep 2024 16:35:49 -0400 Subject: [PATCH 072/115] Integrate RMNRemote and OffRamp (#1360) ## Motivation Remove the requirement for self-transmitted RMN blessings ## Solution Allow the commit DON to include RMN blessings at commitment time This PR has a dependency on changes to [chainlink-ccip](https://github.com/smartcontractkit/chainlink-ccip/pull/84) --------- Co-authored-by: Makram --- contracts/.solhintignore | 3 +- contracts/gas-snapshots/ccip.gas-snapshot | 659 +++++++------- contracts/package.json | 2 +- contracts/pnpm-lock.yaml | 22 +- .../scripts/native_solc_compile_all_ccip | 1 + contracts/src/v0.8/ccip/interfaces/IRMNV2.sol | 22 + .../src/v0.8/ccip/libraries/Internal.sol | 10 + contracts/src/v0.8/ccip/offRamp/OffRamp.sol | 87 +- contracts/src/v0.8/ccip/onRamp/OnRamp.sol | 20 +- contracts/src/v0.8/ccip/{ => rmn}/RMNHome.sol | 2 +- .../src/v0.8/ccip/{ => rmn}/RMNRemote.sol | 41 +- contracts/src/v0.8/ccip/test/BaseTest.t.sol | 21 + .../v0.8/ccip/test/e2e/MultiRampsEnd2End.sol | 26 +- .../src/v0.8/ccip/test/offRamp/OffRamp.t.sol | 418 ++++----- .../v0.8/ccip/test/offRamp/OffRampSetup.t.sol | 11 +- .../src/v0.8/ccip/test/onRamp/OnRamp.t.sol | 15 +- .../v0.8/ccip/test/onRamp/OnRampSetup.t.sol | 4 +- .../ccip_reader_tester/ccip_reader_tester.go | 35 +- .../ccip/generated/offramp/offramp.go | 80 +- .../ccip/generated/onramp/onramp.go | 4 +- .../generated/report_codec/report_codec.go | 35 +- .../ccip/generated/rmn_remote/rmn_remote.go | 842 ++++++++++++++++++ ...rapper-dependency-versions-do-not-edit.txt | 9 +- core/gethwrappers/ccip/go_generate.go | 1 + 24 files changed, 1568 insertions(+), 802 deletions(-) create mode 100644 contracts/src/v0.8/ccip/interfaces/IRMNV2.sol rename contracts/src/v0.8/ccip/{ => rmn}/RMNHome.sol (98%) rename contracts/src/v0.8/ccip/{ => rmn}/RMNRemote.sol (79%) create mode 100644 core/gethwrappers/ccip/generated/rmn_remote/rmn_remote.go diff --git a/contracts/.solhintignore b/contracts/.solhintignore index 446f91f84f..5ae38e28d9 100644 --- a/contracts/.solhintignore +++ b/contracts/.solhintignore @@ -43,5 +43,4 @@ ./node_modules/ # Ignore RMN contracts temporarily -./src/v0.8/ccip/RMNRemote.sol -./src/v0.8/ccip/RMNHome.sol \ No newline at end of file +./src/v0.8/ccip/rmn \ No newline at end of file diff --git a/contracts/gas-snapshots/ccip.gas-snapshot b/contracts/gas-snapshots/ccip.gas-snapshot index 62deac1cb9..d684185072 100644 --- a/contracts/gas-snapshots/ccip.gas-snapshot +++ b/contracts/gas-snapshots/ccip.gas-snapshot @@ -14,27 +14,27 @@ AggregateTokenLimiter_getTokenValue:test_GetTokenValue_Success() (gas: 19668) AggregateTokenLimiter_getTokenValue:test_NoTokenPrice_Reverts() (gas: 21253) AggregateTokenLimiter_rateLimitValue:test_AggregateValueMaxCapacityExceeded_Revert() (gas: 16418) AggregateTokenLimiter_rateLimitValue:test_RateLimitValueSuccess_gas() (gas: 18306) -AggregateTokenLimiter_setAdmin:test_OnlyOwnerOrAdmin_Revert() (gas: 13047) +AggregateTokenLimiter_setAdmin:test_OnlyOwnerOrAdmin_Revert() (gas: 13048) AggregateTokenLimiter_setAdmin:test_Owner_Success() (gas: 18989) -AggregateTokenLimiter_setRateLimiterConfig:test_OnlyOnlyCallableByAdminOrOwner_Revert() (gas: 17479) +AggregateTokenLimiter_setRateLimiterConfig:test_OnlyOnlyCallableByAdminOrOwner_Revert() (gas: 17480) AggregateTokenLimiter_setRateLimiterConfig:test_Owner_Success() (gas: 30062) AggregateTokenLimiter_setRateLimiterConfig:test_TokenLimitAdmin_Success() (gas: 32071) -BurnFromMintTokenPool_lockOrBurn:test_ChainNotAllowed_Revert() (gas: 28761) +BurnFromMintTokenPool_lockOrBurn:test_ChainNotAllowed_Revert() (gas: 28773) BurnFromMintTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 55115) -BurnFromMintTokenPool_lockOrBurn:test_PoolBurn_Success() (gas: 243491) +BurnFromMintTokenPool_lockOrBurn:test_PoolBurn_Success() (gas: 243529) BurnFromMintTokenPool_lockOrBurn:test_Setup_Success() (gas: 23947) -BurnMintTokenPool_lockOrBurn:test_ChainNotAllowed_Revert() (gas: 27522) +BurnMintTokenPool_lockOrBurn:test_ChainNotAllowed_Revert() (gas: 27534) BurnMintTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 55115) -BurnMintTokenPool_lockOrBurn:test_PoolBurn_Success() (gas: 241381) +BurnMintTokenPool_lockOrBurn:test_PoolBurn_Success() (gas: 241420) BurnMintTokenPool_lockOrBurn:test_Setup_Success() (gas: 17677) BurnMintTokenPool_releaseOrMint:test_ChainNotAllowed_Revert() (gas: 28757) BurnMintTokenPool_releaseOrMint:test_PoolMintNotHealthy_Revert() (gas: 56190) BurnMintTokenPool_releaseOrMint:test_PoolMint_Success() (gas: 112319) -BurnWithFromMintTokenPool_lockOrBurn:test_ChainNotAllowed_Revert() (gas: 28761) +BurnWithFromMintTokenPool_lockOrBurn:test_ChainNotAllowed_Revert() (gas: 28773) BurnWithFromMintTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 55115) -BurnWithFromMintTokenPool_lockOrBurn:test_PoolBurn_Success() (gas: 243517) +BurnWithFromMintTokenPool_lockOrBurn:test_PoolBurn_Success() (gas: 243556) BurnWithFromMintTokenPool_lockOrBurn:test_Setup_Success() (gas: 23951) -CCIPClientExample_sanity:test_ImmutableExamples_Success() (gas: 2132684) +CCIPClientExample_sanity:test_ImmutableExamples_Success() (gas: 2132690) CCIPConfigSetup:test_getCapabilityConfiguration_Success() (gas: 9539) CCIPConfig_ConfigStateMachine:test__computeConfigDigest_Success() (gas: 66088) CCIPConfig_ConfigStateMachine:test__computeNewConfigWithMeta_InitToRunning_Success() (gas: 357846) @@ -108,9 +108,9 @@ CommitStore_resetUnblessedRoots:test_ResetUnblessedRoots_Success() (gas: 143718) CommitStore_setDynamicConfig:test_InvalidCommitStoreConfig_Revert() (gas: 37263) CommitStore_setDynamicConfig:test_OnlyOwner_Revert() (gas: 37399) CommitStore_setDynamicConfig:test_PriceEpochCleared_Success() (gas: 129098) -CommitStore_setLatestPriceEpochAndRound:test_OnlyOwner_Revert() (gas: 11047) +CommitStore_setLatestPriceEpochAndRound:test_OnlyOwner_Revert() (gas: 11048) CommitStore_setLatestPriceEpochAndRound:test_SetLatestPriceEpochAndRound_Success() (gas: 20642) -CommitStore_setMinSeqNr:test_OnlyOwner_Revert() (gas: 11046) +CommitStore_setMinSeqNr:test_OnlyOwner_Revert() (gas: 11047) CommitStore_verify:test_Blessed_Success() (gas: 96389) CommitStore_verify:test_NotBlessed_Success() (gas: 61374) CommitStore_verify:test_Paused_Revert() (gas: 18496) @@ -118,73 +118,73 @@ CommitStore_verify:test_TooManyLeaves_Revert() (gas: 36785) DefensiveExampleTest:test_HappyPath_Success() (gas: 200018) DefensiveExampleTest:test_Recovery() (gas: 424256) E2E:test_E2E_3MessagesSuccess_gas() (gas: 1100023) -EVM2EVMOffRamp__releaseOrMintToken:test__releaseOrMintToken_NotACompatiblePool_Revert() (gas: 37797) -EVM2EVMOffRamp__releaseOrMintToken:test__releaseOrMintToken_Success() (gas: 103733) -EVM2EVMOffRamp__releaseOrMintToken:test__releaseOrMintToken_TokenHandlingError_transfer_Revert() (gas: 85258) -EVM2EVMOffRamp__releaseOrMintToken:test_releaseOrMintToken_InvalidDataLength_Revert() (gas: 36786) -EVM2EVMOffRamp__releaseOrMintToken:test_releaseOrMintToken_ReleaseOrMintBalanceMismatch_Revert() (gas: 94302) -EVM2EVMOffRamp__releaseOrMintToken:test_releaseOrMintToken_TokenHandlingError_BalanceOf_Revert() (gas: 39768) +EVM2EVMOffRamp__releaseOrMintToken:test__releaseOrMintToken_NotACompatiblePool_Revert() (gas: 37782) +EVM2EVMOffRamp__releaseOrMintToken:test__releaseOrMintToken_Success() (gas: 103730) +EVM2EVMOffRamp__releaseOrMintToken:test__releaseOrMintToken_TokenHandlingError_transfer_Revert() (gas: 85255) +EVM2EVMOffRamp__releaseOrMintToken:test_releaseOrMintToken_InvalidDataLength_Revert() (gas: 36789) +EVM2EVMOffRamp__releaseOrMintToken:test_releaseOrMintToken_ReleaseOrMintBalanceMismatch_Revert() (gas: 94299) +EVM2EVMOffRamp__releaseOrMintToken:test_releaseOrMintToken_TokenHandlingError_BalanceOf_Revert() (gas: 39765) EVM2EVMOffRamp__releaseOrMintToken:test_releaseOrMintToken_skip_ReleaseOrMintBalanceMismatch_if_pool_Revert() (gas: 86559) EVM2EVMOffRamp__releaseOrMintTokens:test_OverValueWithARLOff_Success() (gas: 385246) -EVM2EVMOffRamp__releaseOrMintTokens:test_PriceNotFoundForToken_Reverts() (gas: 141896) +EVM2EVMOffRamp__releaseOrMintTokens:test_PriceNotFoundForToken_Reverts() (gas: 141905) EVM2EVMOffRamp__releaseOrMintTokens:test_RateLimitErrors_Reverts() (gas: 803071) EVM2EVMOffRamp__releaseOrMintTokens:test_TokenHandlingError_Reverts() (gas: 179244) -EVM2EVMOffRamp__releaseOrMintTokens:test__releaseOrMintTokens_NotACompatiblePool_Reverts() (gas: 29240) +EVM2EVMOffRamp__releaseOrMintTokens:test__releaseOrMintTokens_NotACompatiblePool_Reverts() (gas: 29243) EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_InvalidDataLengthReturnData_Revert() (gas: 66444) EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_InvalidEVMAddress_Revert() (gas: 43320) EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_Success() (gas: 210968) EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals_Success() (gas: 222232) -EVM2EVMOffRamp__report:test_Report_Success() (gas: 126637) +EVM2EVMOffRamp__report:test_Report_Success() (gas: 126640) EVM2EVMOffRamp__trialExecute:test_RateLimitError_Success() (gas: 237791) EVM2EVMOffRamp__trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 246391) EVM2EVMOffRamp__trialExecute:test_TokenPoolIsNotAContract_Success() (gas: 329828) EVM2EVMOffRamp__trialExecute:test_trialExecute_Success() (gas: 312265) -EVM2EVMOffRamp_ccipReceive:test_Reverts() (gas: 17030) +EVM2EVMOffRamp_ccipReceive:test_Reverts() (gas: 17033) EVM2EVMOffRamp_constructor:test_CommitStoreAlreadyInUse_Revert() (gas: 153727) -EVM2EVMOffRamp_constructor:test_Constructor_Success() (gas: 5665947) +EVM2EVMOffRamp_constructor:test_Constructor_Success() (gas: 5665956) EVM2EVMOffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 144461) -EVM2EVMOffRamp_execute:test_EmptyReport_Revert() (gas: 21318) -EVM2EVMOffRamp_execute:test_InvalidMessageId_Revert() (gas: 36432) +EVM2EVMOffRamp_execute:test_EmptyReport_Revert() (gas: 21315) +EVM2EVMOffRamp_execute:test_InvalidMessageId_Revert() (gas: 36429) EVM2EVMOffRamp_execute:test_InvalidSourceChain_Revert() (gas: 51598) EVM2EVMOffRamp_execute:test_InvalidSourcePoolAddress_Success() (gas: 473329) EVM2EVMOffRamp_execute:test_ManualExecutionNotYetEnabled_Revert() (gas: 47668) -EVM2EVMOffRamp_execute:test_MessageTooLarge_Revert() (gas: 152359) +EVM2EVMOffRamp_execute:test_MessageTooLarge_Revert() (gas: 152356) EVM2EVMOffRamp_execute:test_Paused_Revert() (gas: 102842) -EVM2EVMOffRamp_execute:test_ReceiverError_Success() (gas: 163804) +EVM2EVMOffRamp_execute:test_ReceiverError_Success() (gas: 163810) EVM2EVMOffRamp_execute:test_RetryFailedMessageWithoutManualExecution_Success() (gas: 178205) EVM2EVMOffRamp_execute:test_RootNotCommitted_Revert() (gas: 42539) EVM2EVMOffRamp_execute:test_SingleMessageNoTokensUnordered_Success() (gas: 157347) EVM2EVMOffRamp_execute:test_SingleMessageNoTokens_Success() (gas: 172692) EVM2EVMOffRamp_execute:test_SingleMessageToNonCCIPReceiver_Success() (gas: 247069) -EVM2EVMOffRamp_execute:test_SingleMessagesNoTokensSuccess_gas() (gas: 113842) +EVM2EVMOffRamp_execute:test_SingleMessagesNoTokensSuccess_gas() (gas: 113839) EVM2EVMOffRamp_execute:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 407451) EVM2EVMOffRamp_execute:test_SkippedIncorrectNonce_Success() (gas: 54096) -EVM2EVMOffRamp_execute:test_StrictUntouchedToSuccess_Success() (gas: 131047) -EVM2EVMOffRamp_execute:test_TokenDataMismatch_Revert() (gas: 52090) -EVM2EVMOffRamp_execute:test_TwoMessagesWithTokensAndGE_Success() (gas: 563385) -EVM2EVMOffRamp_execute:test_TwoMessagesWithTokensSuccess_gas() (gas: 494182) -EVM2EVMOffRamp_execute:test_UnexpectedTokenData_Revert() (gas: 35383) +EVM2EVMOffRamp_execute:test_StrictUntouchedToSuccess_Success() (gas: 131053) +EVM2EVMOffRamp_execute:test_TokenDataMismatch_Revert() (gas: 52087) +EVM2EVMOffRamp_execute:test_TwoMessagesWithTokensAndGE_Success() (gas: 563391) +EVM2EVMOffRamp_execute:test_TwoMessagesWithTokensSuccess_gas() (gas: 494179) +EVM2EVMOffRamp_execute:test_UnexpectedTokenData_Revert() (gas: 35380) EVM2EVMOffRamp_execute:test_Unhealthy_Revert() (gas: 544641) -EVM2EVMOffRamp_execute:test_UnsupportedNumberOfTokens_Revert() (gas: 64326) +EVM2EVMOffRamp_execute:test_UnsupportedNumberOfTokens_Revert() (gas: 64323) EVM2EVMOffRamp_execute:test__execute_SkippedAlreadyExecutedMessageUnordered_Success() (gas: 122322) EVM2EVMOffRamp_execute:test__execute_SkippedAlreadyExecutedMessage_Success() (gas: 142532) -EVM2EVMOffRamp_execute:test_execute_RouterYULCall_Success() (gas: 427337) +EVM2EVMOffRamp_execute:test_execute_RouterYULCall_Success() (gas: 427328) EVM2EVMOffRamp_executeSingleMessage:test_MessageSender_Revert() (gas: 18502) -EVM2EVMOffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 278097) -EVM2EVMOffRamp_executeSingleMessage:test_NonContract_Success() (gas: 18659) +EVM2EVMOffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 278106) +EVM2EVMOffRamp_executeSingleMessage:test_NonContract_Success() (gas: 18668) EVM2EVMOffRamp_executeSingleMessage:test_TokenHandlingError_Revert() (gas: 223921) EVM2EVMOffRamp_executeSingleMessage:test_ZeroGasDONExecution_Revert() (gas: 47881) EVM2EVMOffRamp_executeSingleMessage:test_executeSingleMessage_NoTokens_Success() (gas: 47352) EVM2EVMOffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens_Success() (gas: 313917) EVM2EVMOffRamp_executeSingleMessage:test_executeSingleMessage_ZeroGasZeroData_Success() (gas: 70008) -EVM2EVMOffRamp_execute_upgrade:test_V2NonceNewSenderStartsAtZero_Success() (gas: 229319) +EVM2EVMOffRamp_execute_upgrade:test_V2NonceNewSenderStartsAtZero_Success() (gas: 229325) EVM2EVMOffRamp_execute_upgrade:test_V2NonceStartsAtV1Nonce_Success() (gas: 276790) EVM2EVMOffRamp_execute_upgrade:test_V2OffRampNonceSkipsIfMsgInFlight_Success() (gas: 258696) EVM2EVMOffRamp_execute_upgrade:test_V2SenderNoncesReadsPreviousRamp_Success() (gas: 226253) EVM2EVMOffRamp_execute_upgrade:test_V2_Success() (gas: 130745) EVM2EVMOffRamp_getAllRateLimitTokens:test_GetAllRateLimitTokens_Success() (gas: 38446) -EVM2EVMOffRamp_getExecutionState:test_FillExecutionState_Success() (gas: 3247348) -EVM2EVMOffRamp_getExecutionState:test_GetExecutionState_Success() (gas: 83333) +EVM2EVMOffRamp_getExecutionState:test_FillExecutionState_Success() (gas: 3251974) +EVM2EVMOffRamp_getExecutionState:test_GetExecutionState_Success() (gas: 83387) EVM2EVMOffRamp_manuallyExecute:test_ManualExecFailedTx_Revert() (gas: 185829) EVM2EVMOffRamp_manuallyExecute:test_ManualExecForkedChain_Revert() (gas: 27049) EVM2EVMOffRamp_manuallyExecute:test_ManualExecGasLimitMismatch_Revert() (gas: 45155) @@ -192,29 +192,29 @@ EVM2EVMOffRamp_manuallyExecute:test_ManualExecInvalidGasLimit_Revert() (gas: 274 EVM2EVMOffRamp_manuallyExecute:test_ManualExecWithMultipleMessagesAndSourceTokens_Success() (gas: 530151) EVM2EVMOffRamp_manuallyExecute:test_ManualExecWithSourceTokens_Success() (gas: 345758) EVM2EVMOffRamp_manuallyExecute:test_ManualExec_Success() (gas: 187324) -EVM2EVMOffRamp_manuallyExecute:test_ReentrancyManualExecuteFails_Success() (gas: 2321906) +EVM2EVMOffRamp_manuallyExecute:test_ReentrancyManualExecuteFails_Success() (gas: 2321912) EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_DestinationGasAmountCountMismatch_Revert() (gas: 362965) EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_DoesNotRevertIfUntouched_Success() (gas: 143900) EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_InvalidTokenGasOverride_Revert() (gas: 366104) -EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_LowGasLimitManualExec_Success() (gas: 482691) +EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_LowGasLimitManualExec_Success() (gas: 482682) EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_WithGasOverride_Success() (gas: 189727) EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_WithInvalidReceiverExecutionGasOverride_Revert() (gas: 153641) EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_WithInvalidSourceTokenDataCount_Revert() (gas: 59894) -EVM2EVMOffRamp_metadataHash:test_MetadataHash_Success() (gas: 8838) -EVM2EVMOffRamp_setDynamicConfig:test_NonOwner_Revert() (gas: 40153) -EVM2EVMOffRamp_setDynamicConfig:test_RouterZeroAddress_Revert() (gas: 38236) -EVM2EVMOffRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 141962) -EVM2EVMOffRamp_updateRateLimitTokens:test_updateRateLimitTokens_AddsAndRemoves_Success() (gas: 162525) -EVM2EVMOffRamp_updateRateLimitTokens:test_updateRateLimitTokens_NonOwner_Revert() (gas: 16690) -EVM2EVMOffRamp_updateRateLimitTokens:test_updateRateLimitTokens_Success() (gas: 197721) -EVM2EVMOnRamp_constructor:test_Constructor_Success() (gas: 5579769) +EVM2EVMOffRamp_metadataHash:test_MetadataHash_Success() (gas: 8865) +EVM2EVMOffRamp_setDynamicConfig:test_NonOwner_Revert() (gas: 40156) +EVM2EVMOffRamp_setDynamicConfig:test_RouterZeroAddress_Revert() (gas: 38239) +EVM2EVMOffRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 141923) +EVM2EVMOffRamp_updateRateLimitTokens:test_updateRateLimitTokens_AddsAndRemoves_Success() (gas: 162528) +EVM2EVMOffRamp_updateRateLimitTokens:test_updateRateLimitTokens_NonOwner_Revert() (gas: 16693) +EVM2EVMOffRamp_updateRateLimitTokens:test_updateRateLimitTokens_Success() (gas: 197728) +EVM2EVMOnRamp_constructor:test_Constructor_Success() (gas: 5579757) EVM2EVMOnRamp_forwardFromRouter:test_CannotSendZeroTokens_Revert() (gas: 35778) -EVM2EVMOnRamp_forwardFromRouter:test_EnforceOutOfOrder_Revert() (gas: 98428) -EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() (gas: 114198) -EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2_Success() (gas: 114240) -EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterSuccessCustomExtraArgs() (gas: 130207) -EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterSuccessLegacyExtraArgs() (gas: 138653) -EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouter_Success() (gas: 129829) +EVM2EVMOnRamp_forwardFromRouter:test_EnforceOutOfOrder_Revert() (gas: 98446) +EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() (gas: 114204) +EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2_Success() (gas: 114246) +EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterSuccessCustomExtraArgs() (gas: 130213) +EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterSuccessLegacyExtraArgs() (gas: 138659) +EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouter_Success() (gas: 129838) EVM2EVMOnRamp_forwardFromRouter:test_InvalidAddressEncodePacked_Revert() (gas: 38257) EVM2EVMOnRamp_forwardFromRouter:test_InvalidAddress_Revert() (gas: 38440) EVM2EVMOnRamp_forwardFromRouter:test_InvalidChainSelector_Revert() (gas: 25489) @@ -236,7 +236,7 @@ EVM2EVMOnRamp_forwardFromRouter:test_TooManyTokens_Revert() (gas: 30187) EVM2EVMOnRamp_forwardFromRouter:test_Unhealthy_Revert() (gas: 43300) EVM2EVMOnRamp_forwardFromRouter:test_UnsupportedToken_Revert() (gas: 109305) EVM2EVMOnRamp_forwardFromRouter:test_ZeroAddressReceiver_Revert() (gas: 312579) -EVM2EVMOnRamp_forwardFromRouter:test_forwardFromRouter_ShouldStoreLinkFees_Success() (gas: 112322) +EVM2EVMOnRamp_forwardFromRouter:test_forwardFromRouter_ShouldStoreLinkFees_Success() (gas: 112331) EVM2EVMOnRamp_forwardFromRouter:test_forwardFromRouter_UnsupportedToken_Revert() (gas: 72206) EVM2EVMOnRamp_forwardFromRouter:test_forwardFromRouter_correctSourceTokenData_Success() (gas: 712975) EVM2EVMOnRamp_forwardFromRouter_upgrade:test_V2NonceNewSenderStartsAtZero_Success() (gas: 147664) @@ -245,14 +245,14 @@ EVM2EVMOnRamp_forwardFromRouter_upgrade:test_V2SenderNoncesReadsPreviousRamp_Suc EVM2EVMOnRamp_forwardFromRouter_upgrade:test_V2_Success() (gas: 95349) EVM2EVMOnRamp_getDataAvailabilityCost:test_EmptyMessageCalculatesDataAvailabilityCost_Success() (gas: 20544) EVM2EVMOnRamp_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCost_Success() (gas: 20912) -EVM2EVMOnRamp_getFee:test_EmptyMessage_Success() (gas: 78230) +EVM2EVMOnRamp_getFee:test_EmptyMessage_Success() (gas: 78233) EVM2EVMOnRamp_getFee:test_GetFeeOfZeroForTokenMessage_Success() (gas: 81762) -EVM2EVMOnRamp_getFee:test_HighGasMessage_Success() (gas: 234078) +EVM2EVMOnRamp_getFee:test_HighGasMessage_Success() (gas: 234081) EVM2EVMOnRamp_getFee:test_MessageGasLimitTooHigh_Revert() (gas: 16715) EVM2EVMOnRamp_getFee:test_MessageTooLarge_Revert() (gas: 95271) -EVM2EVMOnRamp_getFee:test_MessageWithDataAndTokenTransfer_Success() (gas: 159436) +EVM2EVMOnRamp_getFee:test_MessageWithDataAndTokenTransfer_Success() (gas: 159439) EVM2EVMOnRamp_getFee:test_NotAFeeToken_Revert() (gas: 24089) -EVM2EVMOnRamp_getFee:test_SingleTokenMessage_Success() (gas: 117922) +EVM2EVMOnRamp_getFee:test_SingleTokenMessage_Success() (gas: 117925) EVM2EVMOnRamp_getFee:test_TooManyTokens_Revert() (gas: 19902) EVM2EVMOnRamp_getFee:test_ZeroDataAvailabilityMultiplier_Success() (gas: 64648) EVM2EVMOnRamp_getSupportedTokens:test_GetSupportedTokens_Revert() (gas: 10460) @@ -275,7 +275,7 @@ EVM2EVMOnRamp_payNops:test_NoFeesToPay_Revert() (gas: 127367) EVM2EVMOnRamp_payNops:test_NoNopsToPay_Revert() (gas: 133251) EVM2EVMOnRamp_payNops:test_NopPayNops_Success() (gas: 146446) EVM2EVMOnRamp_payNops:test_OwnerPayNops_Success() (gas: 141021) -EVM2EVMOnRamp_payNops:test_PayNopsSuccessAfterSetNops() (gas: 297510) +EVM2EVMOnRamp_payNops:test_PayNopsSuccessAfterSetNops() (gas: 297519) EVM2EVMOnRamp_payNops:test_WrongPermissions_Revert() (gas: 15294) EVM2EVMOnRamp_setDynamicConfig:test_SetConfigInvalidConfig_Revert() (gas: 42365) EVM2EVMOnRamp_setDynamicConfig:test_SetConfigOnlyOwner_Revert() (gas: 21246) @@ -347,10 +347,10 @@ FeeQuoter_convertTokenAmount:test_LinkTokenNotSupported_Revert() (gas: 30963) FeeQuoter_getDataAvailabilityCost:test_EmptyMessageCalculatesDataAvailabilityCost_Success() (gas: 94303) FeeQuoter_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCostUnsupportedDestChainSelector_Success() (gas: 14614) FeeQuoter_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCost_Success() (gas: 20410) -FeeQuoter_getTokenAndGasPrices:test_GetFeeTokenAndGasPrices_Success() (gas: 70443) +FeeQuoter_getTokenAndGasPrices:test_GetFeeTokenAndGasPrices_Success() (gas: 70458) FeeQuoter_getTokenAndGasPrices:test_StaleGasPrice_Revert() (gas: 16838) FeeQuoter_getTokenAndGasPrices:test_UnsupportedChain_Revert() (gas: 16140) -FeeQuoter_getTokenAndGasPrices:test_ZeroGasPrice_Success() (gas: 45750) +FeeQuoter_getTokenAndGasPrices:test_ZeroGasPrice_Success() (gas: 45765) FeeQuoter_getTokenPrice:test_GetTokenPriceFromFeed_Success() (gas: 62252) FeeQuoter_getTokenPrices:test_GetTokenPrices_Success() (gas: 84800) FeeQuoter_getTokenTransferCost:test_CustomTokenBpsFee_Success() (gas: 41227) @@ -363,15 +363,15 @@ FeeQuoter_getTokenTransferCost:test_ZeroAmountTokenTransferChargesMinFeeAndGas_S FeeQuoter_getTokenTransferCost:test_ZeroFeeConfigChargesMinFee_Success() (gas: 40013) FeeQuoter_getTokenTransferCost:test_getTokenTransferCost_selfServeUsesDefaults_Success() (gas: 29299) FeeQuoter_getValidatedFee:test_DestinationChainNotEnabled_Revert() (gas: 18180) -FeeQuoter_getValidatedFee:test_EmptyMessage_Success() (gas: 85916) +FeeQuoter_getValidatedFee:test_EmptyMessage_Success() (gas: 85919) FeeQuoter_getValidatedFee:test_EnforceOutOfOrder_Revert() (gas: 54345) -FeeQuoter_getValidatedFee:test_HighGasMessage_Success() (gas: 242334) +FeeQuoter_getValidatedFee:test_HighGasMessage_Success() (gas: 242337) FeeQuoter_getValidatedFee:test_InvalidEVMAddress_Revert() (gas: 22390) FeeQuoter_getValidatedFee:test_MessageGasLimitTooHigh_Revert() (gas: 31797) FeeQuoter_getValidatedFee:test_MessageTooLarge_Revert() (gas: 100133) -FeeQuoter_getValidatedFee:test_MessageWithDataAndTokenTransfer_Success() (gas: 147677) +FeeQuoter_getValidatedFee:test_MessageWithDataAndTokenTransfer_Success() (gas: 147680) FeeQuoter_getValidatedFee:test_NotAFeeToken_Revert() (gas: 21043) -FeeQuoter_getValidatedFee:test_SingleTokenMessage_Success() (gas: 116705) +FeeQuoter_getValidatedFee:test_SingleTokenMessage_Success() (gas: 116708) FeeQuoter_getValidatedFee:test_TooManyTokens_Revert() (gas: 22526) FeeQuoter_getValidatedFee:test_ZeroDataAvailabilityMultiplier_Success() (gas: 64364) FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Above18Decimals_Success() (gas: 2094539) @@ -426,53 +426,53 @@ FeeQuoter_validatePoolReturnData:test_InvalidEVMAddressDestToken_Revert() (gas: FeeQuoter_validatePoolReturnData:test_ProcessPoolReturnData_Success() (gas: 73252) FeeQuoter_validatePoolReturnData:test_SourceTokenDataTooLarge_Revert() (gas: 107744) FeeQuoter_validatePoolReturnData:test_TokenAmountArraysMismatching_Revert() (gas: 40091) -HybridUSDCTokenPoolMigrationTests:test_LockOrBurn_LocKReleaseMechanism_then_switchToPrimary_Success() (gas: 208137) -HybridUSDCTokenPoolMigrationTests:test_LockOrBurn_PrimaryMechanism_Success() (gas: 135392) -HybridUSDCTokenPoolMigrationTests:test_LockOrBurn_WhileMigrationPause_Revert() (gas: 106624) -HybridUSDCTokenPoolMigrationTests:test_LockOrBurn_onLockReleaseMechanism_Success() (gas: 143884) -HybridUSDCTokenPoolMigrationTests:test_MintOrRelease_OnLockReleaseMechanism_Success() (gas: 230399) -HybridUSDCTokenPoolMigrationTests:test_MintOrRelease_OnLockReleaseMechanism_then_switchToPrimary_Success() (gas: 438259) -HybridUSDCTokenPoolMigrationTests:test_MintOrRelease_incomingMessageWithPrimaryMechanism() (gas: 269968) +HybridUSDCTokenPoolMigrationTests:test_LockOrBurn_LocKReleaseMechanism_then_switchToPrimary_Success() (gas: 208156) +HybridUSDCTokenPoolMigrationTests:test_LockOrBurn_PrimaryMechanism_Success() (gas: 135401) +HybridUSDCTokenPoolMigrationTests:test_LockOrBurn_WhileMigrationPause_Revert() (gas: 106633) +HybridUSDCTokenPoolMigrationTests:test_LockOrBurn_onLockReleaseMechanism_Success() (gas: 143893) +HybridUSDCTokenPoolMigrationTests:test_MintOrRelease_OnLockReleaseMechanism_Success() (gas: 230396) +HybridUSDCTokenPoolMigrationTests:test_MintOrRelease_OnLockReleaseMechanism_then_switchToPrimary_Success() (gas: 438277) +HybridUSDCTokenPoolMigrationTests:test_MintOrRelease_incomingMessageWithPrimaryMechanism() (gas: 269985) HybridUSDCTokenPoolMigrationTests:test_burnLockedUSDC_invalidPermissions_Revert() (gas: 39124) HybridUSDCTokenPoolMigrationTests:test_cancelExistingCCTPMigrationProposal() (gas: 31124) HybridUSDCTokenPoolMigrationTests:test_cannotCancelANonExistentMigrationProposal() (gas: 12628) -HybridUSDCTokenPoolMigrationTests:test_cannotModifyLiquidityWithoutPermissions_Revert() (gas: 17133) -HybridUSDCTokenPoolMigrationTests:test_lockOrBurn_then_BurnInCCTPMigration_Success() (gas: 252432) +HybridUSDCTokenPoolMigrationTests:test_cannotModifyLiquidityWithoutPermissions_Revert() (gas: 17134) +HybridUSDCTokenPoolMigrationTests:test_lockOrBurn_then_BurnInCCTPMigration_Success() (gas: 252452) HybridUSDCTokenPoolMigrationTests:test_transferLiquidity_Success() (gas: 157049) HybridUSDCTokenPoolMigrationTests:test_withdrawLiquidity_Success() (gas: 140780) -HybridUSDCTokenPoolTests:test_LockOrBurn_LocKReleaseMechanism_then_switchToPrimary_Success() (gas: 208102) -HybridUSDCTokenPoolTests:test_LockOrBurn_PrimaryMechanism_Success() (gas: 135365) -HybridUSDCTokenPoolTests:test_LockOrBurn_WhileMigrationPause_Revert() (gas: 106589) -HybridUSDCTokenPoolTests:test_LockOrBurn_onLockReleaseMechanism_Success() (gas: 143832) -HybridUSDCTokenPoolTests:test_MintOrRelease_OnLockReleaseMechanism_Success() (gas: 230365) -HybridUSDCTokenPoolTests:test_MintOrRelease_OnLockReleaseMechanism_then_switchToPrimary_Success() (gas: 438171) -HybridUSDCTokenPoolTests:test_MintOrRelease_incomingMessageWithPrimaryMechanism() (gas: 269912) +HybridUSDCTokenPoolTests:test_LockOrBurn_LocKReleaseMechanism_then_switchToPrimary_Success() (gas: 208121) +HybridUSDCTokenPoolTests:test_LockOrBurn_PrimaryMechanism_Success() (gas: 135375) +HybridUSDCTokenPoolTests:test_LockOrBurn_WhileMigrationPause_Revert() (gas: 106610) +HybridUSDCTokenPoolTests:test_LockOrBurn_onLockReleaseMechanism_Success() (gas: 143841) +HybridUSDCTokenPoolTests:test_MintOrRelease_OnLockReleaseMechanism_Success() (gas: 230362) +HybridUSDCTokenPoolTests:test_MintOrRelease_OnLockReleaseMechanism_then_switchToPrimary_Success() (gas: 438237) +HybridUSDCTokenPoolTests:test_MintOrRelease_incomingMessageWithPrimaryMechanism() (gas: 269968) HybridUSDCTokenPoolTests:test_withdrawLiquidity_Success() (gas: 140774) -LockReleaseTokenPoolAndProxy_setRebalancer:test_SetRebalancer_Revert() (gas: 10970) +LockReleaseTokenPoolAndProxy_setRebalancer:test_SetRebalancer_Revert() (gas: 10971) LockReleaseTokenPoolAndProxy_setRebalancer:test_SetRebalancer_Success() (gas: 17992) -LockReleaseTokenPoolPoolAndProxy_canAcceptLiquidity:test_CanAcceptLiquidity_Success() (gas: 3368110) -LockReleaseTokenPoolPoolAndProxy_provideLiquidity:test_LiquidityNotAccepted_Revert() (gas: 3364509) -LockReleaseTokenPoolPoolAndProxy_provideLiquidity:test_Unauthorized_Revert() (gas: 11380) +LockReleaseTokenPoolPoolAndProxy_canAcceptLiquidity:test_CanAcceptLiquidity_Success() (gas: 3368113) +LockReleaseTokenPoolPoolAndProxy_provideLiquidity:test_LiquidityNotAccepted_Revert() (gas: 3364513) +LockReleaseTokenPoolPoolAndProxy_provideLiquidity:test_Unauthorized_Revert() (gas: 11381) LockReleaseTokenPoolPoolAndProxy_supportsInterface:test_SupportsInterface_Success() (gas: 9977) LockReleaseTokenPoolPoolAndProxy_withdrawalLiquidity:test_InsufficientLiquidity_Revert() (gas: 60043) -LockReleaseTokenPoolPoolAndProxy_withdrawalLiquidity:test_Unauthorized_Revert() (gas: 11355) -LockReleaseTokenPool_canAcceptLiquidity:test_CanAcceptLiquidity_Success() (gas: 3124819) -LockReleaseTokenPool_lockOrBurn:test_LockOrBurnWithAllowList_Revert() (gas: 29942) +LockReleaseTokenPoolPoolAndProxy_withdrawalLiquidity:test_Unauthorized_Revert() (gas: 11356) +LockReleaseTokenPool_canAcceptLiquidity:test_CanAcceptLiquidity_Success() (gas: 3124822) +LockReleaseTokenPool_lockOrBurn:test_LockOrBurnWithAllowList_Revert() (gas: 29954) LockReleaseTokenPool_lockOrBurn:test_LockOrBurnWithAllowList_Success() (gas: 79844) LockReleaseTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 59464) -LockReleaseTokenPool_provideLiquidity:test_LiquidityNotAccepted_Revert() (gas: 3121261) -LockReleaseTokenPool_provideLiquidity:test_Unauthorized_Revert() (gas: 11380) -LockReleaseTokenPool_releaseOrMint:test_ChainNotAllowed_Revert() (gas: 72644) +LockReleaseTokenPool_provideLiquidity:test_LiquidityNotAccepted_Revert() (gas: 3121265) +LockReleaseTokenPool_provideLiquidity:test_Unauthorized_Revert() (gas: 11381) +LockReleaseTokenPool_releaseOrMint:test_ChainNotAllowed_Revert() (gas: 72654) LockReleaseTokenPool_releaseOrMint:test_PoolMintNotHealthy_Revert() (gas: 56196) -LockReleaseTokenPool_releaseOrMint:test_ReleaseOrMint_Success() (gas: 225108) -LockReleaseTokenPool_setRebalancer:test_SetRebalancer_Revert() (gas: 10992) +LockReleaseTokenPool_releaseOrMint:test_ReleaseOrMint_Success() (gas: 225137) +LockReleaseTokenPool_setRebalancer:test_SetRebalancer_Revert() (gas: 10993) LockReleaseTokenPool_setRebalancer:test_SetRebalancer_Success() (gas: 18058) LockReleaseTokenPool_supportsInterface:test_SupportsInterface_Success() (gas: 9977) LockReleaseTokenPool_transferLiquidity:test_transferLiquidity_Success() (gas: 83171) LockReleaseTokenPool_transferLiquidity:test_transferLiquidity_transferTooMuch_Revert() (gas: 55878) LockReleaseTokenPool_withdrawalLiquidity:test_InsufficientLiquidity_Revert() (gas: 60043) -LockReleaseTokenPool_withdrawalLiquidity:test_Unauthorized_Revert() (gas: 11355) -LockRelease_setRateLimitAdmin:test_SetRateLimitAdmin_Revert() (gas: 11029) +LockReleaseTokenPool_withdrawalLiquidity:test_Unauthorized_Revert() (gas: 11356) +LockRelease_setRateLimitAdmin:test_SetRateLimitAdmin_Revert() (gas: 11030) LockRelease_setRateLimitAdmin:test_SetRateLimitAdmin_Success() (gas: 35030) MerkleMultiProofTest:test_CVE_2023_34459() (gas: 5451) MerkleMultiProofTest:test_EmptyLeaf_Revert() (gas: 3552) @@ -481,7 +481,7 @@ MerkleMultiProofTest:test_MerkleRootSingleLeaf_Success() (gas: 3649) MerkleMultiProofTest:test_SpecSync_gas() (gas: 34123) MockRouterTest:test_ccipSendWithInsufficientNativeTokens_Revert() (gas: 33965) MockRouterTest:test_ccipSendWithInvalidMsgValue_Revert() (gas: 60758) -MockRouterTest:test_ccipSendWithLinkFeeTokenAndValidMsgValue_Success() (gas: 126294) +MockRouterTest:test_ccipSendWithLinkFeeTokenAndValidMsgValue_Success() (gas: 126306) MockRouterTest:test_ccipSendWithLinkFeeTokenbutInsufficientAllowance_Revert() (gas: 63302) MockRouterTest:test_ccipSendWithSufficientNativeFeeTokens_Success() (gas: 43853) MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_MultipleConfigsBothLanes_Success() (gas: 132031) @@ -529,7 +529,7 @@ MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokens_AddsA MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokens_RemoveNonExistentToken_Success() (gas: 28703) MultiAggregateRateLimiter_updateRateLimitTokens:test_ZeroDestToken_Revert() (gas: 18287) MultiAggregateRateLimiter_updateRateLimitTokens:test_ZeroSourceToken_Revert() (gas: 18216) -MultiOCR3Base_setOCR3Configs:test_FMustBePositive_Revert() (gas: 59331) +MultiOCR3Base_setOCR3Configs:test_FMustBePositive_Revert() (gas: 59228) MultiOCR3Base_setOCR3Configs:test_FTooHigh_Revert() (gas: 43602) MultiOCR3Base_setOCR3Configs:test_RepeatSignerAddress_Revert() (gas: 283585) MultiOCR3Base_setOCR3Configs:test_RepeatTransmitterAddress_Revert() (gas: 422210) @@ -537,7 +537,7 @@ MultiOCR3Base_setOCR3Configs:test_SetConfigIgnoreSigners_Success() (gas: 511089) MultiOCR3Base_setOCR3Configs:test_SetConfigWithSigners_Success() (gas: 828371) MultiOCR3Base_setOCR3Configs:test_SetConfigWithoutSigners_Success() (gas: 456841) MultiOCR3Base_setOCR3Configs:test_SetConfigsZeroInput_Success() (gas: 12376) -MultiOCR3Base_setOCR3Configs:test_SetMultipleConfigs_Success() (gas: 2140058) +MultiOCR3Base_setOCR3Configs:test_SetMultipleConfigs_Success() (gas: 2139958) MultiOCR3Base_setOCR3Configs:test_SignerCannotBeZeroAddress_Revert() (gas: 141702) MultiOCR3Base_setOCR3Configs:test_StaticConfigChange_Revert() (gas: 807256) MultiOCR3Base_setOCR3Configs:test_TooManySigners_Revert() (gas: 158772) @@ -545,36 +545,36 @@ MultiOCR3Base_setOCR3Configs:test_TooManyTransmitters_Revert() (gas: 112266) MultiOCR3Base_setOCR3Configs:test_TransmitterCannotBeZeroAddress_Revert() (gas: 254068) MultiOCR3Base_setOCR3Configs:test_UpdateConfigSigners_Success() (gas: 859969) MultiOCR3Base_setOCR3Configs:test_UpdateConfigTransmittersWithoutSigners_Success() (gas: 475059) -MultiOCR3Base_transmit:test_ConfigDigestMismatch_Revert() (gas: 42837) -MultiOCR3Base_transmit:test_ForkedChain_Revert() (gas: 48442) -MultiOCR3Base_transmit:test_InsufficientSignatures_Revert() (gas: 76930) -MultiOCR3Base_transmit:test_NonUniqueSignature_Revert() (gas: 65770) -MultiOCR3Base_transmit:test_SignatureOutOfRegistration_Revert() (gas: 33419) -MultiOCR3Base_transmit:test_TooManySignatures_Revert() (gas: 79521) -MultiOCR3Base_transmit:test_TransmitSigners_gas_Success() (gas: 33633) -MultiOCR3Base_transmit:test_TransmitWithExtraCalldataArgs_Revert() (gas: 47114) -MultiOCR3Base_transmit:test_TransmitWithLessCalldataArgs_Revert() (gas: 25682) -MultiOCR3Base_transmit:test_TransmitWithoutSignatureVerification_gas_Success() (gas: 18714) -MultiOCR3Base_transmit:test_UnAuthorizedTransmitter_Revert() (gas: 24191) -MultiOCR3Base_transmit:test_UnauthorizedSigner_Revert() (gas: 61133) -MultiOCR3Base_transmit:test_UnconfiguredPlugin_Revert() (gas: 39890) -MultiOCR3Base_transmit:test_ZeroSignatures_Revert() (gas: 32973) -MultiOnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 413542) -MultiRampsE2E:test_E2E_3MessagesMMultiOffRampSuccess_gas() (gas: 1499013) +MultiOCR3Base_transmit:test_ConfigDigestMismatch_Revert() (gas: 42833) +MultiOCR3Base_transmit:test_ForkedChain_Revert() (gas: 48438) +MultiOCR3Base_transmit:test_InsufficientSignatures_Revert() (gas: 76928) +MultiOCR3Base_transmit:test_NonUniqueSignature_Revert() (gas: 65768) +MultiOCR3Base_transmit:test_SignatureOutOfRegistration_Revert() (gas: 33417) +MultiOCR3Base_transmit:test_TooManySignatures_Revert() (gas: 79519) +MultiOCR3Base_transmit:test_TransmitSigners_gas_Success() (gas: 33631) +MultiOCR3Base_transmit:test_TransmitWithExtraCalldataArgs_Revert() (gas: 47110) +MultiOCR3Base_transmit:test_TransmitWithLessCalldataArgs_Revert() (gas: 25678) +MultiOCR3Base_transmit:test_TransmitWithoutSignatureVerification_gas_Success() (gas: 18712) +MultiOCR3Base_transmit:test_UnAuthorizedTransmitter_Revert() (gas: 24189) +MultiOCR3Base_transmit:test_UnauthorizedSigner_Revert() (gas: 61131) +MultiOCR3Base_transmit:test_UnconfiguredPlugin_Revert() (gas: 39888) +MultiOCR3Base_transmit:test_ZeroSignatures_Revert() (gas: 32971) +MultiOnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 411393) +MultiRampsE2E:test_E2E_3MessagesMMultiOffRampSuccess_gas() (gas: 1526613) NonceManager_NonceIncrementation:test_getIncrementedOutboundNonce_Success() (gas: 37907) -NonceManager_NonceIncrementation:test_incrementInboundNonce_Skip() (gas: 23694) -NonceManager_NonceIncrementation:test_incrementInboundNonce_Success() (gas: 38763) -NonceManager_NonceIncrementation:test_incrementNoncesInboundAndOutbound_Success() (gas: 71847) -NonceManager_OffRampUpgrade:test_NoPrevOffRampForChain_Success() (gas: 260206) -NonceManager_OffRampUpgrade:test_UpgradedNonceNewSenderStartsAtZero_Success() (gas: 262348) -NonceManager_OffRampUpgrade:test_UpgradedNonceStartsAtV1Nonce_Success() (gas: 325972) -NonceManager_OffRampUpgrade:test_UpgradedOffRampNonceSkipsIfMsgInFlight_Success() (gas: 298151) +NonceManager_NonceIncrementation:test_incrementInboundNonce_Skip() (gas: 23703) +NonceManager_NonceIncrementation:test_incrementInboundNonce_Success() (gas: 38790) +NonceManager_NonceIncrementation:test_incrementNoncesInboundAndOutbound_Success() (gas: 71874) +NonceManager_OffRampUpgrade:test_NoPrevOffRampForChain_Success() (gas: 259788) +NonceManager_OffRampUpgrade:test_UpgradedNonceNewSenderStartsAtZero_Success() (gas: 263930) +NonceManager_OffRampUpgrade:test_UpgradedNonceStartsAtV1Nonce_Success() (gas: 326647) +NonceManager_OffRampUpgrade:test_UpgradedOffRampNonceSkipsIfMsgInFlight_Success() (gas: 298821) NonceManager_OffRampUpgrade:test_UpgradedSenderNoncesReadsPreviousRampTransitive_Success() (gas: 244682) -NonceManager_OffRampUpgrade:test_UpgradedSenderNoncesReadsPreviousRamp_Success() (gas: 232980) -NonceManager_OffRampUpgrade:test_Upgraded_Success() (gas: 153163) -NonceManager_OnRampUpgrade:test_UpgradeNonceNewSenderStartsAtZero_Success() (gas: 168317) -NonceManager_OnRampUpgrade:test_UpgradeNonceStartsAtV1Nonce_Success() (gas: 220108) -NonceManager_OnRampUpgrade:test_UpgradeSenderNoncesReadsPreviousRamp_Success() (gas: 125070) +NonceManager_OffRampUpgrade:test_UpgradedSenderNoncesReadsPreviousRamp_Success() (gas: 232797) +NonceManager_OffRampUpgrade:test_Upgraded_Success() (gas: 152756) +NonceManager_OnRampUpgrade:test_UpgradeNonceNewSenderStartsAtZero_Success() (gas: 168320) +NonceManager_OnRampUpgrade:test_UpgradeNonceStartsAtV1Nonce_Success() (gas: 220111) +NonceManager_OnRampUpgrade:test_UpgradeSenderNoncesReadsPreviousRamp_Success() (gas: 125079) NonceManager_OnRampUpgrade:test_Upgrade_Success() (gas: 107546) NonceManager_applyPreviousRampsUpdates:test_MultipleRampsUpdates() (gas: 122943) NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySetOffRamp_Revert() (gas: 42959) @@ -608,160 +608,155 @@ OCR2Base_transmit:test_Transmit2SignersSuccess_gas() (gas: 51674) OCR2Base_transmit:test_UnAuthorizedTransmitter_Revert() (gas: 23484) OCR2Base_transmit:test_UnauthorizedSigner_Revert() (gas: 39665) OCR2Base_transmit:test_WrongNumberOfSignatures_Revert() (gas: 20557) -OffRamp__releaseOrMintSingleToken:test__releaseOrMintSingleToken_NotACompatiblePool_Revert() (gas: 40127) -OffRamp__releaseOrMintSingleToken:test__releaseOrMintSingleToken_Success() (gas: 107108) -OffRamp__releaseOrMintSingleToken:test__releaseOrMintSingleToken_TokenHandlingError_transfer_Revert() (gas: 88331) -OffRamp__releaseOrMintSingleToken:test_releaseOrMintToken_InvalidDataLength_Revert() (gas: 39848) -OffRamp__releaseOrMintSingleToken:test_releaseOrMintToken_ReleaseOrMintBalanceMismatch_Revert() (gas: 97377) -OffRamp__releaseOrMintSingleToken:test_releaseOrMintToken_TokenHandlingError_BalanceOf_Revert() (gas: 42843) -OffRamp__releaseOrMintSingleToken:test_releaseOrMintToken_skip_ReleaseOrMintBalanceMismatch_if_pool_Revert() (gas: 89579) -OffRamp_applySourceChainConfigUpdates:test_AddMultipleChains_Success() (gas: 467917) -OffRamp_applySourceChainConfigUpdates:test_AddNewChain_Success() (gas: 99161) -OffRamp_applySourceChainConfigUpdates:test_ApplyZeroUpdates_Success() (gas: 12395) -OffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChainOnRamp_Revert() (gas: 93181) -OffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChain_Success() (gas: 109869) -OffRamp_applySourceChainConfigUpdates:test_RouterAddress_Revert() (gas: 13263) -OffRamp_applySourceChainConfigUpdates:test_ZeroOnRampAddress_Revert() (gas: 17988) -OffRamp_applySourceChainConfigUpdates:test_ZeroSourceChainSelector_Revert() (gas: 15343) -OffRamp_batchExecute:test_MultipleReportsDifferentChainsSkipCursedChain_Success() (gas: 202302) -OffRamp_batchExecute:test_MultipleReportsDifferentChains_Success() (gas: 335775) -OffRamp_batchExecute:test_MultipleReportsSameChain_Success() (gas: 277143) -OffRamp_batchExecute:test_MultipleReportsSkipDuplicate_Success() (gas: 169155) -OffRamp_batchExecute:test_OutOfBoundsGasLimitsAccess_Revert() (gas: 187792) -OffRamp_batchExecute:test_SingleReport_Success() (gas: 156254) -OffRamp_batchExecute:test_Unhealthy_Success() (gas: 573431) -OffRamp_batchExecute:test_ZeroReports_Revert() (gas: 10421) -OffRamp_ccipReceive:test_Reverts() (gas: 15773) -OffRamp_commit:test_InvalidIntervalMinLargerThanMax_Revert() (gas: 67433) -OffRamp_commit:test_InvalidInterval_Revert() (gas: 59753) -OffRamp_commit:test_InvalidRootRevert() (gas: 58833) -OffRamp_commit:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6597673) -OffRamp_commit:test_NoConfig_Revert() (gas: 6181416) -OffRamp_commit:test_OnlyGasPriceUpdates_Success() (gas: 105929) -OffRamp_commit:test_OnlyPriceUpdateStaleReport_Revert() (gas: 115981) -OffRamp_commit:test_OnlyTokenPriceUpdates_Success() (gas: 105950) -OffRamp_commit:test_PriceSequenceNumberCleared_Success() (gas: 349049) -OffRamp_commit:test_ReportAndPriceUpdate_Success() (gas: 159000) -OffRamp_commit:test_ReportOnlyRootSuccess_gas() (gas: 136067) -OffRamp_commit:test_RootAlreadyCommitted_Revert() (gas: 136442) -OffRamp_commit:test_SourceChainNotEnabled_Revert() (gas: 59101) -OffRamp_commit:test_StaleReportWithRoot_Success() (gas: 224756) -OffRamp_commit:test_UnauthorizedTransmitter_Revert() (gas: 117607) -OffRamp_commit:test_Unhealthy_Revert() (gas: 77660) -OffRamp_commit:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 204271) -OffRamp_commit:test_WrongConfigWithoutSigners_Revert() (gas: 6592062) -OffRamp_commit:test_ZeroEpochAndRound_Revert() (gas: 47832) -OffRamp_constructor:test_Constructor_Success() (gas: 6184742) -OffRamp_constructor:test_SourceChainSelector_Revert() (gas: 137165) -OffRamp_constructor:test_ZeroChainSelector_Revert() (gas: 103904) -OffRamp_constructor:test_ZeroNonceManager_Revert() (gas: 101775) -OffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 139740) -OffRamp_constructor:test_ZeroRMNProxy_Revert() (gas: 101652) -OffRamp_constructor:test_ZeroTokenAdminRegistry_Revert() (gas: 101719) -OffRamp_execute:test_IncorrectArrayType_Revert() (gas: 17350) -OffRamp_execute:test_LargeBatch_Success() (gas: 3384707) -OffRamp_execute:test_MultipleReportsWithPartialValidationFailures_Success() (gas: 373627) -OffRamp_execute:test_MultipleReports_Success() (gas: 299546) -OffRamp_execute:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6648787) -OffRamp_execute:test_NoConfig_Revert() (gas: 6232270) -OffRamp_execute:test_NonArray_Revert() (gas: 27787) -OffRamp_execute:test_SingleReport_Success() (gas: 175597) -OffRamp_execute:test_UnauthorizedTransmitter_Revert() (gas: 147825) -OffRamp_execute:test_WrongConfigWithSigners_Revert() (gas: 7010288) -OffRamp_execute:test_ZeroReports_Revert() (gas: 17225) -OffRamp_executeSingleMessage:test_MessageSender_Revert() (gas: 18257) -OffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 249037) -OffRamp_executeSingleMessage:test_NonContract_Success() (gas: 20539) -OffRamp_executeSingleMessage:test_TokenHandlingError_Revert() (gas: 210176) -OffRamp_executeSingleMessage:test_ZeroGasDONExecution_Revert() (gas: 48779) -OffRamp_executeSingleMessage:test_executeSingleMessage_NoTokens_Success() (gas: 48257) -OffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidationNoRouterCall_Revert() (gas: 229565) -OffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidation_Revert() (gas: 86203) -OffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens_Success() (gas: 280859) -OffRamp_executeSingleMessage:test_executeSingleMessage_WithValidation_Success() (gas: 92437) -OffRamp_executeSingleReport:test_DisabledSourceChain_Revert() (gas: 35087) -OffRamp_executeSingleReport:test_EmptyReport_Revert() (gas: 28713) -OffRamp_executeSingleReport:test_InvalidSourcePoolAddress_Success() (gas: 491507) -OffRamp_executeSingleReport:test_ManualExecutionNotYetEnabled_Revert() (gas: 54434) -OffRamp_executeSingleReport:test_MismatchingDestChainSelector_Revert() (gas: 40717) -OffRamp_executeSingleReport:test_MismatchingOnRampRoot_Revert() (gas: 154069) -OffRamp_executeSingleReport:test_NonExistingSourceChain_Revert() (gas: 35321) -OffRamp_executeSingleReport:test_ReceiverError_Success() (gas: 187888) -OffRamp_executeSingleReport:test_RetryFailedMessageWithoutManualExecution_Revert() (gas: 199169) -OffRamp_executeSingleReport:test_RootNotCommitted_Revert() (gas: 48085) -OffRamp_executeSingleReport:test_RouterYULCall_Revert() (gas: 447736) -OffRamp_executeSingleReport:test_SingleMessageNoTokensOtherChain_Success() (gas: 251032) -OffRamp_executeSingleReport:test_SingleMessageNoTokensUnordered_Success() (gas: 193299) -OffRamp_executeSingleReport:test_SingleMessageNoTokens_Success() (gas: 212892) -OffRamp_executeSingleReport:test_SingleMessageToNonCCIPReceiver_Success() (gas: 266553) -OffRamp_executeSingleReport:test_SingleMessagesNoTokensSuccess_gas() (gas: 141168) -OffRamp_executeSingleReport:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 422552) -OffRamp_executeSingleReport:test_SkippedIncorrectNonce_Success() (gas: 65854) -OffRamp_executeSingleReport:test_TokenDataMismatch_Revert() (gas: 80909) -OffRamp_executeSingleReport:test_TwoMessagesWithTokensAndGE_Success() (gas: 594246) -OffRamp_executeSingleReport:test_TwoMessagesWithTokensSuccess_gas() (gas: 542093) -OffRamp_executeSingleReport:test_UnexpectedTokenData_Revert() (gas: 40533) -OffRamp_executeSingleReport:test_UnhealthySingleChainCurse_Revert() (gas: 569984) -OffRamp_executeSingleReport:test_Unhealthy_Success() (gas: 569363) -OffRamp_executeSingleReport:test_WithCurseOnAnotherSourceChain_Success() (gas: 494202) -OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessageUnordered_Success() (gas: 136534) -OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessage_Success() (gas: 165753) -OffRamp_getExecutionState:test_FillExecutionState_Success() (gas: 3742124) -OffRamp_getExecutionState:test_GetDifferentChainExecutionState_Success() (gas: 118836) -OffRamp_getExecutionState:test_GetExecutionState_Success() (gas: 88048) -OffRamp_manuallyExecute:test_ManualExecGasLimitMismatchSingleReport_Revert() (gas: 75551) +OffRamp__releaseOrMintSingleToken:test__releaseOrMintSingleToken_NotACompatiblePool_Revert() (gas: 40170) +OffRamp__releaseOrMintSingleToken:test__releaseOrMintSingleToken_Success() (gas: 107133) +OffRamp__releaseOrMintSingleToken:test__releaseOrMintSingleToken_TokenHandlingError_transfer_Revert() (gas: 88356) +OffRamp__releaseOrMintSingleToken:test_releaseOrMintToken_InvalidDataLength_Revert() (gas: 39873) +OffRamp__releaseOrMintSingleToken:test_releaseOrMintToken_ReleaseOrMintBalanceMismatch_Revert() (gas: 97399) +OffRamp__releaseOrMintSingleToken:test_releaseOrMintToken_TokenHandlingError_BalanceOf_Revert() (gas: 42865) +OffRamp__releaseOrMintSingleToken:test_releaseOrMintToken_skip_ReleaseOrMintBalanceMismatch_if_pool_Revert() (gas: 89601) +OffRamp_applySourceChainConfigUpdates:test_AddMultipleChains_Success() (gas: 467980) +OffRamp_applySourceChainConfigUpdates:test_AddNewChain_Success() (gas: 99186) +OffRamp_applySourceChainConfigUpdates:test_ApplyZeroUpdates_Success() (gas: 12392) +OffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChainOnRamp_Revert() (gas: 93184) +OffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChain_Success() (gas: 109891) +OffRamp_applySourceChainConfigUpdates:test_RouterAddress_Revert() (gas: 13260) +OffRamp_applySourceChainConfigUpdates:test_ZeroOnRampAddress_Revert() (gas: 17994) +OffRamp_applySourceChainConfigUpdates:test_ZeroSourceChainSelector_Revert() (gas: 15349) +OffRamp_batchExecute:test_MultipleReportsDifferentChainsSkipCursedChain_Success() (gas: 176779) +OffRamp_batchExecute:test_MultipleReportsDifferentChains_Success() (gas: 332397) +OffRamp_batchExecute:test_MultipleReportsSameChain_Success() (gas: 275765) +OffRamp_batchExecute:test_MultipleReportsSkipDuplicate_Success() (gas: 167867) +OffRamp_batchExecute:test_OutOfBoundsGasLimitsAccess_Revert() (gas: 187343) +OffRamp_batchExecute:test_SingleReport_Success() (gas: 155847) +OffRamp_batchExecute:test_Unhealthy_Success() (gas: 572707) +OffRamp_batchExecute:test_ZeroReports_Revert() (gas: 10440) +OffRamp_ccipReceive:test_Reverts() (gas: 15705) +OffRamp_commit:test_FailedRMNVerification_Reverts() (gas: 64218) +OffRamp_commit:test_InvalidIntervalMinLargerThanMax_Revert() (gas: 67373) +OffRamp_commit:test_InvalidInterval_Revert() (gas: 59676) +OffRamp_commit:test_InvalidRootRevert() (gas: 58728) +OffRamp_commit:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6572843) +OffRamp_commit:test_NoConfig_Revert() (gas: 6156722) +OffRamp_commit:test_OnlyGasPriceUpdates_Success() (gas: 113211) +OffRamp_commit:test_OnlyPriceUpdateStaleReport_Revert() (gas: 121156) +OffRamp_commit:test_OnlyTokenPriceUpdates_Success() (gas: 113232) +OffRamp_commit:test_PriceSequenceNumberCleared_Success() (gas: 354911) +OffRamp_commit:test_ReportAndPriceUpdate_Success() (gas: 166399) +OffRamp_commit:test_ReportOnlyRootSuccess_gas() (gas: 141496) +OffRamp_commit:test_RootAlreadyCommitted_Revert() (gas: 142440) +OffRamp_commit:test_SourceChainNotEnabled_Revert() (gas: 59004) +OffRamp_commit:test_StaleReportWithRoot_Success() (gas: 239068) +OffRamp_commit:test_UnauthorizedTransmitter_Revert() (gas: 122234) +OffRamp_commit:test_Unhealthy_Revert() (gas: 57761) +OffRamp_commit:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 211577) +OffRamp_commit:test_WrongConfigWithoutSigners_Revert() (gas: 6569232) +OffRamp_commit:test_ZeroEpochAndRound_Revert() (gas: 51147) +OffRamp_constructor:test_Constructor_Success() (gas: 6157449) +OffRamp_constructor:test_SourceChainSelector_Revert() (gas: 137102) +OffRamp_constructor:test_ZeroChainSelector_Revert() (gas: 103831) +OffRamp_constructor:test_ZeroNonceManager_Revert() (gas: 101702) +OffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 139743) +OffRamp_constructor:test_ZeroRMNRemote_Revert() (gas: 101631) +OffRamp_constructor:test_ZeroTokenAdminRegistry_Revert() (gas: 101646) +OffRamp_execute:test_IncorrectArrayType_Revert() (gas: 17281) +OffRamp_execute:test_LargeBatch_Success() (gas: 3374948) +OffRamp_execute:test_MultipleReportsWithPartialValidationFailures_Success() (gas: 372169) +OffRamp_execute:test_MultipleReports_Success() (gas: 298074) +OffRamp_execute:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6620946) +OffRamp_execute:test_NoConfig_Revert() (gas: 6204499) +OffRamp_execute:test_NonArray_Revert() (gas: 27718) +OffRamp_execute:test_SingleReport_Success() (gas: 175099) +OffRamp_execute:test_UnauthorizedTransmitter_Revert() (gas: 147327) +OffRamp_execute:test_WrongConfigWithSigners_Revert() (gas: 6982447) +OffRamp_execute:test_ZeroReports_Revert() (gas: 17156) +OffRamp_executeSingleMessage:test_MessageSender_Revert() (gas: 18212) +OffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 248992) +OffRamp_executeSingleMessage:test_NonContract_Success() (gas: 20494) +OffRamp_executeSingleMessage:test_TokenHandlingError_Revert() (gas: 210134) +OffRamp_executeSingleMessage:test_ZeroGasDONExecution_Revert() (gas: 48734) +OffRamp_executeSingleMessage:test_executeSingleMessage_NoTokens_Success() (gas: 48212) +OffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidationNoRouterCall_Revert() (gas: 229531) +OffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidation_Revert() (gas: 86169) +OffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens_Success() (gas: 280811) +OffRamp_executeSingleMessage:test_executeSingleMessage_WithValidation_Success() (gas: 92403) +OffRamp_executeSingleReport:test_DisabledSourceChain_Revert() (gas: 28225) +OffRamp_executeSingleReport:test_EmptyReport_Revert() (gas: 21854) +OffRamp_executeSingleReport:test_InvalidSourcePoolAddress_Success() (gas: 501555) +OffRamp_executeSingleReport:test_ManualExecutionNotYetEnabled_Revert() (gas: 47569) +OffRamp_executeSingleReport:test_MismatchingDestChainSelector_Revert() (gas: 33855) +OffRamp_executeSingleReport:test_MismatchingOnRampRoot_Revert() (gas: 154807) +OffRamp_executeSingleReport:test_NonExistingSourceChain_Revert() (gas: 28459) +OffRamp_executeSingleReport:test_ReceiverError_Success() (gas: 187481) +OffRamp_executeSingleReport:test_RetryFailedMessageWithoutManualExecution_Revert() (gas: 197900) +OffRamp_executeSingleReport:test_RootNotCommitted_Revert() (gas: 40076) +OffRamp_executeSingleReport:test_RouterYULCall_Revert() (gas: 447326) +OffRamp_executeSingleReport:test_SingleMessageNoTokensOtherChain_Success() (gas: 247718) +OffRamp_executeSingleReport:test_SingleMessageNoTokensUnordered_Success() (gas: 191985) +OffRamp_executeSingleReport:test_SingleMessageNoTokens_Success() (gas: 211578) +OffRamp_executeSingleReport:test_SingleMessageToNonCCIPReceiver_Success() (gas: 259646) +OffRamp_executeSingleReport:test_SingleMessagesNoTokensSuccess_gas() (gas: 140761) +OffRamp_executeSingleReport:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 424145) +OffRamp_executeSingleReport:test_SkippedIncorrectNonce_Success() (gas: 58992) +OffRamp_executeSingleReport:test_TokenDataMismatch_Revert() (gas: 74047) +OffRamp_executeSingleReport:test_TwoMessagesWithTokensAndGE_Success() (gas: 595794) +OffRamp_executeSingleReport:test_TwoMessagesWithTokensSuccess_gas() (gas: 543647) +OffRamp_executeSingleReport:test_UnexpectedTokenData_Revert() (gas: 33671) +OffRamp_executeSingleReport:test_UnhealthySingleChainCurse_Revert() (gas: 568625) +OffRamp_executeSingleReport:test_Unhealthy_Success() (gas: 568639) +OffRamp_executeSingleReport:test_WithCurseOnAnotherSourceChain_Success() (gas: 474070) +OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessageUnordered_Success() (gas: 135265) +OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessage_Success() (gas: 164484) +OffRamp_getExecutionState:test_FillExecutionState_Success() (gas: 3635486) +OffRamp_getExecutionState:test_GetDifferentChainExecutionState_Success() (gas: 118398) +OffRamp_getExecutionState:test_GetExecutionState_Success() (gas: 87417) +OffRamp_manuallyExecute:test_ManualExecGasLimitMismatchSingleReport_Revert() (gas: 75545) OffRamp_manuallyExecute:test_ManualExecInvalidGasLimit_Revert() (gas: 26439) -OffRamp_manuallyExecute:test_manuallyExecute_DoesNotRevertIfUntouched_Success() (gas: 171604) -OffRamp_manuallyExecute:test_manuallyExecute_FailedTx_Revert() (gas: 205795) -OffRamp_manuallyExecute:test_manuallyExecute_ForkedChain_Revert() (gas: 25993) -OffRamp_manuallyExecute:test_manuallyExecute_GasLimitMismatchMultipleReports_Revert() (gas: 152834) -OffRamp_manuallyExecute:test_manuallyExecute_LowGasLimit_Success() (gas: 524524) -OffRamp_manuallyExecute:test_manuallyExecute_MultipleReportsWithSingleCursedLane_Revert() (gas: 322692) -OffRamp_manuallyExecute:test_manuallyExecute_ReentrancyFails_Success() (gas: 2388897) -OffRamp_manuallyExecute:test_manuallyExecute_Success() (gas: 218722) -OffRamp_manuallyExecute:test_manuallyExecute_WithGasOverride_Success() (gas: 219297) -OffRamp_manuallyExecute:test_manuallyExecute_WithMultiReportGasOverride_Success() (gas: 740091) -OffRamp_manuallyExecute:test_manuallyExecute_WithPartialMessages_Success() (gas: 344193) -OffRamp_releaseOrMintTokens:test_TokenHandlingError_Reverts() (gas: 165822) -OffRamp_releaseOrMintTokens:test__releaseOrMintTokens_PoolIsNotAPool_Reverts() (gas: 24603) -OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_InvalidDataLengthReturnData_Revert() (gas: 66285) -OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_InvalidEVMAddress_Revert() (gas: 41316) -OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_PoolDoesNotSupportDest_Reverts() (gas: 83291) -OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_Success() (gas: 177934) -OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals_Success() (gas: 191136) -OffRamp_resetUnblessedRoots:test_OnlyOwner_Revert() (gas: 11379) -OffRamp_resetUnblessedRoots:test_ResetUnblessedRoots_Success() (gas: 214934) -OffRamp_setDynamicConfig:test_FeeQuoterZeroAddress_Revert() (gas: 11585) -OffRamp_setDynamicConfig:test_NonOwner_Revert() (gas: 14152) -OffRamp_setDynamicConfig:test_SetDynamicConfigWithValidator_Success() (gas: 49115) -OffRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 27060) -OffRamp_trialExecute:test_RateLimitError_Success() (gas: 225795) -OffRamp_trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 234416) -OffRamp_trialExecute:test_TokenPoolIsNotAContract_Success() (gas: 309206) -OffRamp_trialExecute:test_trialExecute_Success() (gas: 283994) -OffRamp_verify:test_Blessed_Success() (gas: 176251) -OffRamp_verify:test_NotBlessedWrongChainSelector_Success() (gas: 178341) -OffRamp_verify:test_NotBlessed_Success() (gas: 141180) -OffRamp_verify:test_TooManyLeaves_Revert() (gas: 51510) +OffRamp_manuallyExecute:test_manuallyExecute_DoesNotRevertIfUntouched_Success() (gas: 171175) +OffRamp_manuallyExecute:test_manuallyExecute_FailedTx_Revert() (gas: 210959) +OffRamp_manuallyExecute:test_manuallyExecute_ForkedChain_Revert() (gas: 25990) +OffRamp_manuallyExecute:test_manuallyExecute_GasLimitMismatchMultipleReports_Revert() (gas: 152828) +OffRamp_manuallyExecute:test_manuallyExecute_LowGasLimit_Success() (gas: 529679) +OffRamp_manuallyExecute:test_manuallyExecute_MultipleReportsWithSingleCursedLane_Revert() (gas: 310107) +OffRamp_manuallyExecute:test_manuallyExecute_ReentrancyFails_Success() (gas: 2389581) +OffRamp_manuallyExecute:test_manuallyExecute_Success() (gas: 223886) +OffRamp_manuallyExecute:test_manuallyExecute_WithGasOverride_Success() (gas: 224461) +OffRamp_manuallyExecute:test_manuallyExecute_WithMultiReportGasOverride_Success() (gas: 767127) +OffRamp_manuallyExecute:test_manuallyExecute_WithPartialMessages_Success() (gas: 342767) +OffRamp_releaseOrMintTokens:test_TokenHandlingError_Reverts() (gas: 165844) +OffRamp_releaseOrMintTokens:test__releaseOrMintTokens_PoolIsNotAPool_Reverts() (gas: 24622) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_InvalidDataLengthReturnData_Revert() (gas: 66304) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_InvalidEVMAddress_Revert() (gas: 41335) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_PoolDoesNotSupportDest_Reverts() (gas: 83310) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_Success() (gas: 177953) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals_Success() (gas: 191164) +OffRamp_setDynamicConfig:test_FeeQuoterZeroAddress_Revert() (gas: 11604) +OffRamp_setDynamicConfig:test_NonOwner_Revert() (gas: 14171) +OffRamp_setDynamicConfig:test_SetDynamicConfigWithValidator_Success() (gas: 49156) +OffRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 27101) +OffRamp_trialExecute:test_RateLimitError_Success() (gas: 225708) +OffRamp_trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 234329) +OffRamp_trialExecute:test_TokenPoolIsNotAContract_Success() (gas: 308936) +OffRamp_trialExecute:test_trialExecute_Success() (gas: 283904) OnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 390336) -OnRamp_allowListConfigUpdates:test_applyAllowList_Revert() (gas: 66509) -OnRamp_allowListConfigUpdates:test_applyAllowList_Success() (gas: 323566) -OnRamp_applyDestChainConfigUpdates:test_ApplyDestChainConfigUpdates_Success() (gas: 64501) +OnRamp_allowListConfigUpdates:test_applyAllowList_Revert() (gas: 66512) +OnRamp_allowListConfigUpdates:test_applyAllowList_Success() (gas: 323568) +OnRamp_applyDestChainConfigUpdates:test_ApplyDestChainConfigUpdates_Success() (gas: 64504) OnRamp_applyDestChainConfigUpdates:test_ApplyDestChainConfigUpdates_WithInvalidChainSelector_Revert() (gas: 13242) -OnRamp_constructor:test_Constructor_InvalidConfigChainSelectorEqZero_Revert() (gas: 94862) -OnRamp_constructor:test_Constructor_InvalidConfigNonceManagerEqAddressZero_Revert() (gas: 92796) +OnRamp_constructor:test_Constructor_InvalidConfigChainSelectorEqZero_Revert() (gas: 94851) +OnRamp_constructor:test_Constructor_InvalidConfigNonceManagerEqAddressZero_Revert() (gas: 92785) OnRamp_constructor:test_Constructor_InvalidConfigRMNProxyEqAddressZero_Revert() (gas: 97811) -OnRamp_constructor:test_Constructor_InvalidConfigTokenAdminRegistryEqAddressZero_Revert() (gas: 92854) -OnRamp_constructor:test_Constructor_Success() (gas: 2852106) -OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() (gas: 114880) -OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2_Success() (gas: 145648) -OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessCustomExtraArgs() (gas: 145251) -OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessEmptyExtraArgs() (gas: 143464) -OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessLegacyExtraArgs() (gas: 145476) -OnRamp_forwardFromRouter:test_ForwardFromRouter_Success() (gas: 144852) -OnRamp_forwardFromRouter:test_ForwardFromRouter_Success_ConfigurableSourceRouter() (gas: 139995) +OnRamp_constructor:test_Constructor_InvalidConfigTokenAdminRegistryEqAddressZero_Revert() (gas: 92843) +OnRamp_constructor:test_Constructor_Success() (gas: 2852084) +OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() (gas: 114886) +OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2_Success() (gas: 145654) +OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessCustomExtraArgs() (gas: 145257) +OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessEmptyExtraArgs() (gas: 143482) +OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessLegacyExtraArgs() (gas: 145482) +OnRamp_forwardFromRouter:test_ForwardFromRouter_Success() (gas: 144861) +OnRamp_forwardFromRouter:test_ForwardFromRouter_Success_ConfigurableSourceRouter() (gas: 140001) OnRamp_forwardFromRouter:test_InvalidExtraArgsTag_Revert() (gas: 28810) -OnRamp_forwardFromRouter:test_MessageValidationError_Revert() (gas: 138683) +OnRamp_forwardFromRouter:test_MessageValidationError_Revert() (gas: 138698) OnRamp_forwardFromRouter:test_MesssageFeeTooHigh_Revert() (gas: 26910) OnRamp_forwardFromRouter:test_MultiCannotSendZeroTokens_Revert() (gas: 74122) OnRamp_forwardFromRouter:test_OriginalSender_Revert() (gas: 12918) @@ -769,19 +764,19 @@ OnRamp_forwardFromRouter:test_Paused_Revert() (gas: 37224) OnRamp_forwardFromRouter:test_Permissions_Revert() (gas: 18179) OnRamp_forwardFromRouter:test_ShouldIncrementNonceOnlyOnOrdered_Success() (gas: 184142) OnRamp_forwardFromRouter:test_ShouldIncrementSeqNumAndNonce_Success() (gas: 210451) -OnRamp_forwardFromRouter:test_ShouldStoreLinkFees() (gas: 124764) +OnRamp_forwardFromRouter:test_ShouldStoreLinkFees() (gas: 124773) OnRamp_forwardFromRouter:test_ShouldStoreNonLinkFees() (gas: 146166) -OnRamp_forwardFromRouter:test_SourceTokenDataTooLarge_Revert() (gas: 3892469) +OnRamp_forwardFromRouter:test_SourceTokenDataTooLarge_Revert() (gas: 3882038) OnRamp_forwardFromRouter:test_UnAllowedOriginalSender_Revert() (gas: 18609) OnRamp_forwardFromRouter:test_UnsupportedToken_Revert() (gas: 110785) OnRamp_forwardFromRouter:test_forwardFromRouter_UnsupportedToken_Revert() (gas: 76212) -OnRamp_forwardFromRouter:test_forwardFromRouter_WithValidation_Success() (gas: 280875) -OnRamp_getFee:test_EmptyMessage_Success() (gas: 110067) -OnRamp_getFee:test_EnforceOutOfOrder_Revert() (gas: 73220) -OnRamp_getFee:test_GetFeeOfZeroForTokenMessage_Success() (gas: 95436) -OnRamp_getFee:test_NotAFeeTokenButPricedToken_Revert() (gas: 41814) -OnRamp_getFee:test_SingleTokenMessage_Success() (gas: 125400) -OnRamp_getFee:test_Unhealthy_Revert() (gas: 43669) +OnRamp_forwardFromRouter:test_forwardFromRouter_WithValidation_Success() (gas: 280890) +OnRamp_getFee:test_EmptyMessage_Success() (gas: 102302) +OnRamp_getFee:test_EnforceOutOfOrder_Revert() (gas: 66336) +OnRamp_getFee:test_GetFeeOfZeroForTokenMessage_Success() (gas: 87668) +OnRamp_getFee:test_NotAFeeTokenButPricedToken_Revert() (gas: 34930) +OnRamp_getFee:test_SingleTokenMessage_Success() (gas: 117635) +OnRamp_getFee:test_Unhealthy_Revert() (gas: 17009) OnRamp_getSupportedTokens:test_GetSupportedTokens_Revert() (gas: 10438) OnRamp_getTokenPool:test_GetTokenPool_Success() (gas: 35204) OnRamp_setDynamicConfig:test_SetConfigInvalidConfigFeeAggregatorEqAddressZero_Revert() (gas: 11402) @@ -789,7 +784,7 @@ OnRamp_setDynamicConfig:test_SetConfigInvalidConfigFeeQuoterEqAddressZero_Revert OnRamp_setDynamicConfig:test_SetConfigInvalidConfig_Revert() (gas: 11359) OnRamp_setDynamicConfig:test_SetConfigOnlyOwner_Revert() (gas: 16385) OnRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 55321) -OnRamp_withdrawFeeTokens:test_WithdrawFeeTokens_Success() (gas: 97107) +OnRamp_withdrawFeeTokens:test_WithdrawFeeTokens_Success() (gas: 97095) PingPong_ccipReceive:test_CcipReceive_Success() (gas: 152669) PingPong_plumbing:test_OutOfOrderExecution_Success() (gas: 20277) PingPong_plumbing:test_Pausing_Success() (gas: 17777) @@ -873,24 +868,24 @@ RegistryModuleOwnerCustom_registerAdminViaOwner:test_registerAdminViaOwner_Rever RegistryModuleOwnerCustom_registerAdminViaOwner:test_registerAdminViaOwner_Success() (gas: 129731) Router_applyRampUpdates:test_OffRampMismatch_Revert() (gas: 89288) Router_applyRampUpdates:test_OffRampUpdatesWithRouting() (gas: 10642128) -Router_applyRampUpdates:test_OnRampDisable() (gas: 55913) +Router_applyRampUpdates:test_OnRampDisable() (gas: 55935) Router_applyRampUpdates:test_OnlyOwner_Revert() (gas: 12311) Router_ccipSend:test_CCIPSendLinkFeeNoTokenSuccess_gas() (gas: 113880) Router_ccipSend:test_CCIPSendLinkFeeOneTokenSuccess_gas() (gas: 201336) Router_ccipSend:test_CCIPSendNativeFeeNoTokenSuccess_gas() (gas: 128515) Router_ccipSend:test_CCIPSendNativeFeeOneTokenSuccess_gas() (gas: 215973) -Router_ccipSend:test_FeeTokenAmountTooLow_Revert() (gas: 66269) +Router_ccipSend:test_FeeTokenAmountTooLow_Revert() (gas: 66281) Router_ccipSend:test_InvalidMsgValue() (gas: 31963) -Router_ccipSend:test_NativeFeeTokenInsufficientValue() (gas: 68740) +Router_ccipSend:test_NativeFeeTokenInsufficientValue() (gas: 68737) Router_ccipSend:test_NativeFeeTokenOverpay_Success() (gas: 173606) Router_ccipSend:test_NativeFeeTokenZeroValue() (gas: 56031) Router_ccipSend:test_NativeFeeToken_Success() (gas: 172200) -Router_ccipSend:test_NonLinkFeeToken_Success() (gas: 242714) +Router_ccipSend:test_NonLinkFeeToken_Success() (gas: 242717) Router_ccipSend:test_UnsupportedDestinationChain_Revert() (gas: 24749) Router_ccipSend:test_WhenNotHealthy_Revert() (gas: 44724) -Router_ccipSend:test_WrappedNativeFeeToken_Success() (gas: 174416) +Router_ccipSend:test_WrappedNativeFeeToken_Success() (gas: 174386) Router_ccipSend:test_ZeroFeeAndGasPrice_Success() (gas: 244854) -Router_constructor:test_Constructor_Success() (gas: 13074) +Router_constructor:test_Constructor_Success() (gas: 13070) Router_getArmProxy:test_getArmProxy() (gas: 10561) Router_getFee:test_GetFeeSupportedChain_Success() (gas: 46458) Router_getFee:test_UnsupportedDestinationChain_Revert() (gas: 17138) @@ -901,11 +896,11 @@ Router_recoverTokens:test_RecoverTokensNonOwner_Revert() (gas: 11159) Router_recoverTokens:test_RecoverTokensValueReceiver_Revert() (gas: 422138) Router_recoverTokens:test_RecoverTokens_Success() (gas: 52437) Router_routeMessage:test_AutoExec_Success() (gas: 42684) -Router_routeMessage:test_ExecutionEvent_Success() (gas: 157980) +Router_routeMessage:test_ExecutionEvent_Success() (gas: 157989) Router_routeMessage:test_ManualExec_Success() (gas: 35381) Router_routeMessage:test_OnlyOffRamp_Revert() (gas: 25116) Router_routeMessage:test_WhenNotHealthy_Revert() (gas: 44724) -Router_setWrappedNative:test_OnlyOwner_Revert() (gas: 10985) +Router_setWrappedNative:test_OnlyOwner_Revert() (gas: 10986) SelfFundedPingPong_ccipReceive:test_FundingIfNotANop_Revert() (gas: 55531) SelfFundedPingPong_ccipReceive:test_Funding_Success() (gas: 419466) SelfFundedPingPong_setCountIncrBeforeFunding:test_setCountIncrBeforeFunding() (gas: 20151) @@ -917,33 +912,33 @@ TokenAdminRegistry_getAllConfiguredTokens:test_getAllConfiguredTokens_outOfBound TokenAdminRegistry_getPool:test_getPool_Success() (gas: 17581) TokenAdminRegistry_getPools:test_getPools_Success() (gas: 39902) TokenAdminRegistry_isAdministrator:test_isAdministrator_Success() (gas: 105922) -TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_AlreadyRegistered_Revert() (gas: 104001) -TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_OnlyRegistryModule_Revert() (gas: 15481) -TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_ZeroAddress_Revert() (gas: 15026) -TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_module_Success() (gas: 112536) -TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_owner_Success() (gas: 107656) -TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_reRegisterWhileUnclaimed_Success() (gas: 115686) +TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_AlreadyRegistered_Revert() (gas: 104037) +TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_OnlyRegistryModule_Revert() (gas: 15493) +TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_ZeroAddress_Revert() (gas: 15038) +TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_module_Success() (gas: 112548) +TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_owner_Success() (gas: 107668) +TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_reRegisterWhileUnclaimed_Success() (gas: 115698) TokenAdminRegistry_removeRegistryModule:test_removeRegistryModule_OnlyOwner_Revert() (gas: 12585) TokenAdminRegistry_removeRegistryModule:test_removeRegistryModule_Success() (gas: 54473) -TokenAdminRegistry_setPool:test_setPool_InvalidTokenPoolToken_Revert() (gas: 19148) +TokenAdminRegistry_setPool:test_setPool_InvalidTokenPoolToken_Revert() (gas: 19154) TokenAdminRegistry_setPool:test_setPool_OnlyAdministrator_Revert() (gas: 18020) -TokenAdminRegistry_setPool:test_setPool_Success() (gas: 35943) -TokenAdminRegistry_setPool:test_setPool_ZeroAddressRemovesPool_Success() (gas: 30617) +TokenAdminRegistry_setPool:test_setPool_Success() (gas: 35949) +TokenAdminRegistry_setPool:test_setPool_ZeroAddressRemovesPool_Success() (gas: 30623) TokenAdminRegistry_transferAdminRole:test_transferAdminRole_OnlyAdministrator_Revert() (gas: 18043) TokenAdminRegistry_transferAdminRole:test_transferAdminRole_Success() (gas: 49390) -TokenPoolAndProxy:test_lockOrBurn_burnMint_Success() (gas: 6070353) -TokenPoolAndProxy:test_lockOrBurn_burnWithFromMint_Success() (gas: 6101826) -TokenPoolAndProxy:test_lockOrBurn_lockRelease_Success() (gas: 6319594) +TokenPoolAndProxy:test_lockOrBurn_burnMint_Success() (gas: 6070356) +TokenPoolAndProxy:test_lockOrBurn_burnWithFromMint_Success() (gas: 6101829) +TokenPoolAndProxy:test_lockOrBurn_lockRelease_Success() (gas: 6319597) TokenPoolAndProxy:test_setPreviousPool_Success() (gas: 3387124) -TokenPoolAndProxyMigration:test_tokenPoolMigration_Success_1_2() (gas: 6916278) -TokenPoolAndProxyMigration:test_tokenPoolMigration_Success_1_4() (gas: 7100303) -TokenPoolWithAllowList_applyAllowListUpdates:test_AllowListNotEnabled_Revert() (gas: 2209837) +TokenPoolAndProxyMigration:test_tokenPoolMigration_Success_1_2() (gas: 6916281) +TokenPoolAndProxyMigration:test_tokenPoolMigration_Success_1_4() (gas: 7100309) +TokenPoolWithAllowList_applyAllowListUpdates:test_AllowListNotEnabled_Revert() (gas: 2209840) TokenPoolWithAllowList_applyAllowListUpdates:test_OnlyOwner_Revert() (gas: 12089) -TokenPoolWithAllowList_applyAllowListUpdates:test_SetAllowListSkipsZero_Success() (gas: 23324) -TokenPoolWithAllowList_applyAllowListUpdates:test_SetAllowList_Success() (gas: 177568) -TokenPoolWithAllowList_getAllowList:test_GetAllowList_Success() (gas: 23670) +TokenPoolWithAllowList_applyAllowListUpdates:test_SetAllowListSkipsZero_Success() (gas: 23464) +TokenPoolWithAllowList_applyAllowListUpdates:test_SetAllowList_Success() (gas: 177792) +TokenPoolWithAllowList_getAllowList:test_GetAllowList_Success() (gas: 23740) TokenPoolWithAllowList_getAllowListEnabled:test_GetAllowListEnabled_Success() (gas: 8363) -TokenPoolWithAllowList_setRouter:test_SetRouter_Success() (gas: 24831) +TokenPoolWithAllowList_setRouter:test_SetRouter_Success() (gas: 24843) TokenPool_applyChainUpdates:test_applyChainUpdates_DisabledNonZeroRateLimit_Revert() (gas: 271305) TokenPool_applyChainUpdates:test_applyChainUpdates_InvalidRateLimitRate_Revert() (gas: 541162) TokenPool_applyChainUpdates:test_applyChainUpdates_NonExistentChain_Revert() (gas: 18344) @@ -953,14 +948,14 @@ TokenPool_applyChainUpdates:test_applyChainUpdates_ZeroAddressNotAllowed_Revert( TokenPool_constructor:test_ZeroAddressNotAllowed_Revert() (gas: 70721) TokenPool_constructor:test_immutableFields_Success() (gas: 20544) TokenPool_getRemotePool:test_getRemotePool_Success() (gas: 273962) -TokenPool_onlyOffRamp:test_CallerIsNotARampOnRouter_Revert() (gas: 276909) -TokenPool_onlyOffRamp:test_ChainNotAllowed_Revert() (gas: 289406) -TokenPool_onlyOffRamp:test_onlyOffRamp_Success() (gas: 349720) -TokenPool_onlyOnRamp:test_CallerIsNotARampOnRouter_Revert() (gas: 276643) -TokenPool_onlyOnRamp:test_ChainNotAllowed_Revert() (gas: 253432) -TokenPool_onlyOnRamp:test_onlyOnRamp_Success() (gas: 304761) -TokenPool_setChainRateLimiterConfig:test_NonExistentChain_Revert() (gas: 17061) -TokenPool_setChainRateLimiterConfig:test_OnlyOwnerOrRateLimitAdmin_Revert() (gas: 15062) +TokenPool_onlyOffRamp:test_CallerIsNotARampOnRouter_Revert() (gas: 276921) +TokenPool_onlyOffRamp:test_ChainNotAllowed_Revert() (gas: 289432) +TokenPool_onlyOffRamp:test_onlyOffRamp_Success() (gas: 349729) +TokenPool_onlyOnRamp:test_CallerIsNotARampOnRouter_Revert() (gas: 276655) +TokenPool_onlyOnRamp:test_ChainNotAllowed_Revert() (gas: 253458) +TokenPool_onlyOnRamp:test_onlyOnRamp_Success() (gas: 304770) +TokenPool_setChainRateLimiterConfig:test_NonExistentChain_Revert() (gas: 17073) +TokenPool_setChainRateLimiterConfig:test_OnlyOwnerOrRateLimitAdmin_Revert() (gas: 15074) TokenPool_setRemotePool:test_setRemotePool_NonExistentChain_Reverts() (gas: 15620) TokenPool_setRemotePool:test_setRemotePool_OnlyOwner_Reverts() (gas: 13195) TokenPool_setRemotePool:test_setRemotePool_Success() (gas: 281912) @@ -973,16 +968,16 @@ TokenProxy_ccipSend:test_CcipSend_Success() (gas: 261558) TokenProxy_constructor:test_Constructor() (gas: 13812) TokenProxy_getFee:test_GetFeeGasShouldBeZero_Revert() (gas: 16827) TokenProxy_getFee:test_GetFeeInvalidToken_Revert() (gas: 12658) -TokenProxy_getFee:test_GetFeeNoDataAllowed_Revert() (gas: 15849) +TokenProxy_getFee:test_GetFeeNoDataAllowed_Revert() (gas: 15852) TokenProxy_getFee:test_GetFee_Success() (gas: 86690) -USDCTokenPool__validateMessage:test_ValidateInvalidMessage_Revert() (gas: 25290) -USDCTokenPool_lockOrBurn:test_CallerIsNotARampOnRouter_Revert() (gas: 35322) -USDCTokenPool_lockOrBurn:test_LockOrBurnWithAllowList_Revert() (gas: 30073) -USDCTokenPool_lockOrBurn:test_LockOrBurn_Success() (gas: 133102) -USDCTokenPool_lockOrBurn:test_UnknownDomain_Revert() (gas: 477183) -USDCTokenPool_releaseOrMint:test_ReleaseOrMintRealTx_Success() (gas: 268111) -USDCTokenPool_releaseOrMint:test_TokenMaxCapacityExceeded_Revert() (gas: 50676) -USDCTokenPool_releaseOrMint:test_UnlockingUSDCFailed_Revert() (gas: 98591) -USDCTokenPool_setDomains:test_InvalidDomain_Revert() (gas: 66150) +USDCTokenPool__validateMessage:test_ValidateInvalidMessage_Revert() (gas: 25338) +USDCTokenPool_lockOrBurn:test_CallerIsNotARampOnRouter_Revert() (gas: 35352) +USDCTokenPool_lockOrBurn:test_LockOrBurnWithAllowList_Revert() (gas: 30094) +USDCTokenPool_lockOrBurn:test_LockOrBurn_Success() (gas: 133112) +USDCTokenPool_lockOrBurn:test_UnknownDomain_Revert() (gas: 477240) +USDCTokenPool_releaseOrMint:test_ReleaseOrMintRealTx_Success() (gas: 268166) +USDCTokenPool_releaseOrMint:test_TokenMaxCapacityExceeded_Revert() (gas: 50700) +USDCTokenPool_releaseOrMint:test_UnlockingUSDCFailed_Revert() (gas: 98609) +USDCTokenPool_setDomains:test_InvalidDomain_Revert() (gas: 66174) USDCTokenPool_setDomains:test_OnlyOwner_Revert() (gas: 11333) USDCTokenPool_supportsInterface:test_SupportsInterface_Success() (gas: 9876) \ No newline at end of file diff --git a/contracts/package.json b/contracts/package.json index f8cc3a505e..b173fc8603 100644 --- a/contracts/package.json +++ b/contracts/package.json @@ -108,7 +108,7 @@ "moment": "^2.30.1", "prettier": "^3.3.3", "prettier-plugin-solidity": "^1.3.1", - "solhint": "^5.0.3", + "solhint": "^5.0.1", "solhint-plugin-chainlink-solidity": "git+https://github.com/smartcontractkit/chainlink-solhint-rules.git#v1.2.1", "solhint-plugin-prettier": "^0.1.0", "ts-node": "^10.9.2", diff --git a/contracts/pnpm-lock.yaml b/contracts/pnpm-lock.yaml index e2a4f29137..6731f62ae7 100644 --- a/contracts/pnpm-lock.yaml +++ b/contracts/pnpm-lock.yaml @@ -148,8 +148,8 @@ importers: specifier: ^1.3.1 version: 1.3.1(prettier@3.3.3) solhint: - specifier: ^5.0.3 - version: 5.0.3 + specifier: ^5.0.1 + version: 5.0.1 solhint-plugin-chainlink-solidity: specifier: git+https://github.com/smartcontractkit/chainlink-solhint-rules.git#v1.2.1 version: '@chainlink/solhint-plugin-chainlink-solidity@https://codeload.github.com/smartcontractkit/chainlink-solhint-rules/tar.gz/1b4c0c2663fcd983589d4f33a2e73908624ed43c' @@ -1760,7 +1760,6 @@ packages: glob@8.1.0: resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} engines: {node: '>=12'} - deprecated: Glob versions prior to v9 are no longer supported globals@13.24.0: resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} @@ -2152,6 +2151,9 @@ packages: resolution: {integrity: sha512-PyKKjkH53wDMLGrvmRGSNWgmSxZOUqbnXwKL9tmgbFYA1iAYqW21kfR7mZXV0MlESiefxQQE9X9fTa3X+2MPDQ==} engines: {node: '>=10.0.0'} + keyv@4.5.0: + resolution: {integrity: sha512-2YvuMsA+jnFGtBareKqgANOEKe1mk3HKiXu2fRmAfyxG0MJAywNhi5ttWA3PMjl4NmpyjZNbFifR2vNjW1znfA==} + keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} @@ -2900,8 +2902,8 @@ packages: prettier: ^3.0.0 prettier-plugin-solidity: ^1.0.0 - solhint@5.0.3: - resolution: {integrity: sha512-OLCH6qm/mZTCpplTXzXTJGId1zrtNuDYP5c2e6snIv/hdRVxPfBBz/bAlL91bY/Accavkayp2Zp2BaDSrLVXTQ==} + solhint@5.0.1: + resolution: {integrity: sha512-QeQLS9HGCnIiibt+xiOa/+MuP7BWz9N7C5+Mj9pLHshdkNhuo3AzCpWmjfWVZBUuwIUO3YyCRVIcYLR3YOKGfg==} hasBin: true solidity-ast@0.4.56: @@ -4801,7 +4803,7 @@ snapshots: clone-response: 1.0.2 get-stream: 5.1.0 http-cache-semantics: 4.0.3 - keyv: 4.5.4 + keyv: 4.5.0 lowercase-keys: 2.0.0 normalize-url: 6.1.0 responselike: 2.0.1 @@ -6208,6 +6210,10 @@ snapshots: node-gyp-build: 4.5.0 readable-stream: 3.6.0 + keyv@4.5.0: + dependencies: + json-buffer: 3.0.1 + keyv@4.5.4: dependencies: json-buffer: 3.0.1 @@ -6987,7 +6993,7 @@ snapshots: prettier-linter-helpers: 1.0.0 prettier-plugin-solidity: 1.3.1(prettier@3.3.3) - solhint@5.0.3: + solhint@5.0.1: dependencies: '@solidity-parser/parser': 0.18.0 ajv: 6.12.6 @@ -6998,7 +7004,7 @@ snapshots: cosmiconfig: 8.2.0 fast-diff: 1.2.0 glob: 8.1.0 - ignore: 5.3.1 + ignore: 5.2.4 js-yaml: 4.1.0 latest-version: 7.0.0 lodash: 4.17.21 diff --git a/contracts/scripts/native_solc_compile_all_ccip b/contracts/scripts/native_solc_compile_all_ccip index 7b2c580b3c..2e72a72a22 100755 --- a/contracts/scripts/native_solc_compile_all_ccip +++ b/contracts/scripts/native_solc_compile_all_ccip @@ -59,6 +59,7 @@ compileContract () { # Contracts should be ordered in reverse-import-complexity-order to minimize overwrite risks. compileContract ccip/offRamp/EVM2EVMOffRamp.sol compileContract ccip/offRamp/OffRamp.sol +compileContract ccip/rmn/RMNRemote.sol compileContract ccip/applications/PingPongDemo.sol compileContract ccip/applications/SelfFundedPingPong.sol compileContract ccip/applications/EtherSenderReceiver.sol diff --git a/contracts/src/v0.8/ccip/interfaces/IRMNV2.sol b/contracts/src/v0.8/ccip/interfaces/IRMNV2.sol new file mode 100644 index 0000000000..9af3de6cab --- /dev/null +++ b/contracts/src/v0.8/ccip/interfaces/IRMNV2.sol @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {Internal} from "../libraries/Internal.sol"; + +/// @notice This interface contains the only RMN-related functions that might be used on-chain by other CCIP contracts. +interface IRMNV2 { + /// @notice signature components from RMN nodes + struct Signature { + bytes32 r; + bytes32 s; + } + + function verify(Internal.MerkleRoot[] memory merkleRoots, Signature[] memory signatures) external view; + + /// @notice If there is an active global or legacy curse, this function returns true. + function isCursed() external view returns (bool); + + /// @notice If there is an active global curse, or an active curse for `subject`, this function returns true. + /// @param subject To check whether a particular chain is cursed, set to bytes16(uint128(chainSelector)). + function isCursed(bytes16 subject) external view returns (bool); +} diff --git a/contracts/src/v0.8/ccip/libraries/Internal.sol b/contracts/src/v0.8/ccip/libraries/Internal.sol index 9b251eedcf..58ae6279b8 100644 --- a/contracts/src/v0.8/ccip/libraries/Internal.sol +++ b/contracts/src/v0.8/ccip/libraries/Internal.sol @@ -338,4 +338,14 @@ library Internal { // bytes4(keccak256("CCIP ChainFamilySelector EVM")) bytes4 public constant CHAIN_FAMILY_SELECTOR_EVM = 0x2812d52c; + + /// @dev Struct to hold a merkle root and an interval for a source chain so that an array of these can be passed in the CommitReport. + /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers. + struct MerkleRoot { + uint64 sourceChainSelector; // ──╮ Remote source chain selector that the Merkle Root is scoped to + uint64 minSeqNr; // | Minimum sequence number, inclusive + uint64 maxSeqNr; // ─────────────╯ Maximum sequence number, inclusive + bytes32 merkleRoot; // Merkle root covering the interval & source chain messages + bytes onRampAddress; // Generic onramp address, to support arbitrary sources; for EVM, use abi.encode + } } diff --git a/contracts/src/v0.8/ccip/offRamp/OffRamp.sol b/contracts/src/v0.8/ccip/offRamp/OffRamp.sol index d15881a229..10bde4c251 100644 --- a/contracts/src/v0.8/ccip/offRamp/OffRamp.sol +++ b/contracts/src/v0.8/ccip/offRamp/OffRamp.sol @@ -7,7 +7,7 @@ import {IFeeQuoter} from "../interfaces/IFeeQuoter.sol"; import {IMessageInterceptor} from "../interfaces/IMessageInterceptor.sol"; import {INonceManager} from "../interfaces/INonceManager.sol"; import {IPoolV1} from "../interfaces/IPool.sol"; -import {IRMN} from "../interfaces/IRMN.sol"; +import {IRMNV2} from "../interfaces/IRMNV2.sol"; import {IRouter} from "../interfaces/IRouter.sol"; import {ITokenAdminRegistry} from "../interfaces/ITokenAdminRegistry.sol"; @@ -55,7 +55,7 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { error InvalidNewState(uint64 sourceChainSelector, uint64 sequenceNumber, Internal.MessageExecutionState newState); error InvalidStaticConfig(uint64 sourceChainSelector); error StaleCommitReport(); - error InvalidInterval(uint64 sourceChainSelector, Interval interval); + error InvalidInterval(uint64 sourceChainSelector, uint64 min, uint64 max); error ZeroAddressNotAllowed(); error InvalidMessageDestChainSelector(uint64 messageDestChainSelector); @@ -83,9 +83,12 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { /// @notice Struct that contains the static configuration /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers. + /// @dev not sure why solhint complains about this, seems like a buggy detector + /// https://github.com/protofire/solhint/issues/597 + // solhint-disable-next-line gas-struct-packing struct StaticConfig { uint64 chainSelector; // ───╮ Destination chainSelector - address rmnProxy; // ───────╯ RMN proxy address + IRMNV2 rmn; // ─────────────╯ RMN Verification Contract address tokenAdminRegistry; // Token admin registry address address nonceManager; // Nonce manager address } @@ -117,40 +120,20 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { address messageValidator; // Optional message validator to validate incoming messages (zero address = no validator) } - /// @notice a sequenceNumber interval - /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers. - struct Interval { - uint64 min; // ───╮ Minimum sequence number, inclusive - uint64 max; // ───╯ Maximum sequence number, inclusive - } - - /// @dev Struct to hold a merkle root and an interval for a source chain so that an array of these can be passed in the CommitReport. - struct MerkleRoot { - uint64 sourceChainSelector; // Remote source chain selector that the Merkle Root is scoped to - Interval interval; // Report interval of the merkle root - bytes32 merkleRoot; // Merkle root covering the interval & source chain messages - } - /// @notice Report that is committed by the observing DON at the committing phase /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers. struct CommitReport { Internal.PriceUpdates priceUpdates; // Collection of gas and price updates to commit - MerkleRoot[] merkleRoots; // Collection of merkle roots per source chain to commit - } - - /// @dev Struct to hold a merkle root for a source chain so that an array of these can be passed in the - /// resetUnblessedRoots function. - struct UnblessedRoot { - uint64 sourceChainSelector; // Remote source chain selector that the Merkle Root is scoped to - bytes32 merkleRoot; // Merkle root of a single remote source chain + Internal.MerkleRoot[] merkleRoots; // Collection of merkle roots per source chain to commit + IRMNV2.Signature[] rmnSignatures; // RMN signatures on the merkle roots } // STATIC CONFIG string public constant override typeAndVersion = "OffRamp 1.6.0-dev"; /// @dev ChainSelector of this chain uint64 internal immutable i_chainSelector; - /// @dev The address of the RMN proxy - address internal immutable i_rmnProxy; + /// @dev The RMN verification contract + IRMNV2 internal immutable i_rmn; /// @dev The address of the token admin registry address internal immutable i_tokenAdminRegistry; /// @dev The address of the nonce manager @@ -181,7 +164,7 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { SourceChainConfigArgs[] memory sourceChainConfigs ) MultiOCR3Base() { if ( - staticConfig.rmnProxy == address(0) || staticConfig.tokenAdminRegistry == address(0) + address(staticConfig.rmn) == address(0) || staticConfig.tokenAdminRegistry == address(0) || staticConfig.nonceManager == address(0) ) { revert ZeroAddressNotAllowed(); @@ -192,7 +175,7 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { } i_chainSelector = staticConfig.chainSelector; - i_rmnProxy = staticConfig.rmnProxy; + i_rmn = staticConfig.rmn; i_tokenAdminRegistry = staticConfig.tokenAdminRegistry; i_nonceManager = staticConfig.nonceManager; emit StaticConfigSet(staticConfig); @@ -344,7 +327,7 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { ) internal { uint64 sourceChainSelector = report.sourceChainSelector; bool manualExecution = manualExecGasLimits.length != 0; - if (IRMN(i_rmnProxy).isCursed(bytes16(uint128(sourceChainSelector)))) { + if (i_rmn.isCursed(bytes16(uint128(sourceChainSelector)))) { if (manualExecution) { // For manual execution we don't want to silently fail so we revert revert CursedByRMN(sourceChainSelector); @@ -593,6 +576,11 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { ) external { CommitReport memory commitReport = abi.decode(report, (CommitReport)); + // Verify RMN signatures + if (commitReport.merkleRoots.length > 0) { + i_rmn.verify(commitReport.merkleRoots, commitReport.rmnSignatures); + } + // Check if the report contains price updates if (commitReport.priceUpdates.tokenPriceUpdates.length > 0 || commitReport.priceUpdates.gasPriceUpdates.length > 0) { @@ -613,20 +601,19 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { } for (uint256 i = 0; i < commitReport.merkleRoots.length; ++i) { - MerkleRoot memory root = commitReport.merkleRoots[i]; + Internal.MerkleRoot memory root = commitReport.merkleRoots[i]; uint64 sourceChainSelector = root.sourceChainSelector; - if (IRMN(i_rmnProxy).isCursed(bytes16(uint128(sourceChainSelector)))) { + if (i_rmn.isCursed(bytes16(uint128(sourceChainSelector)))) { revert CursedByRMN(sourceChainSelector); } SourceChainConfig storage sourceChainConfig = _getEnabledSourceChainConfig(sourceChainSelector); - if (sourceChainConfig.minSeqNr != root.interval.min || root.interval.min > root.interval.max) { - revert InvalidInterval(root.sourceChainSelector, root.interval); + if (sourceChainConfig.minSeqNr != root.minSeqNr || root.minSeqNr > root.maxSeqNr) { + revert InvalidInterval(root.sourceChainSelector, root.minSeqNr, root.maxSeqNr); } - // TODO: confirm how RMN offchain blessing impacts commit report bytes32 merkleRoot = root.merkleRoot; if (merkleRoot == bytes32(0)) revert InvalidRoot(); // If we reached this section, the report should contain a valid root @@ -636,7 +623,7 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { revert RootAlreadyCommitted(root.sourceChainSelector, merkleRoot); } - sourceChainConfig.minSeqNr = root.interval.max + 1; + sourceChainConfig.minSeqNr = root.maxSeqNr + 1; s_roots[root.sourceChainSelector][merkleRoot] = block.timestamp; } @@ -661,28 +648,6 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { return s_roots[sourceChainSelector][root]; } - /// @notice Returns if a root is blessed or not. - /// @param root The merkle root to check the blessing status for. - /// @return blessed Whether the root is blessed or not. - function isBlessed(bytes32 root) public view returns (bool) { - // TODO: update RMN to also consider the source chain selector for blessing - return IRMN(i_rmnProxy).isBlessed(IRMN.TaggedRoot({commitStore: address(this), root: root})); - } - - /// @notice Used by the owner in case an invalid sequence of roots has been - /// posted and needs to be removed. The interval in the report is trusted. - /// @param rootToReset The roots that will be reset. This function will only - /// reset roots that are not blessed. - function resetUnblessedRoots(UnblessedRoot[] calldata rootToReset) external onlyOwner { - for (uint256 i = 0; i < rootToReset.length; ++i) { - UnblessedRoot memory root = rootToReset[i]; - if (!isBlessed(root.merkleRoot)) { - delete s_roots[root.sourceChainSelector][root.merkleRoot]; - emit RootRemoved(root.merkleRoot); - } - } - } - /// @notice Returns timestamp of when root was accepted or 0 if verification fails. /// @dev This method uses a merkle tree within a merkle tree, with the hashedLeaves, /// proofs and proofFlagBits being used to get the root of the inner tree. @@ -695,10 +660,6 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { uint256 proofFlagBits ) internal view virtual returns (uint256 timestamp) { bytes32 root = MerkleMultiProof.merkleRoot(hashedLeaves, proofs, proofFlagBits); - // Only return non-zero if present and blessed. - if (!isBlessed(root)) { - return 0; - } return s_roots[sourceChainSelector][root]; } @@ -724,7 +685,7 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { function getStaticConfig() external view returns (StaticConfig memory) { return StaticConfig({ chainSelector: i_chainSelector, - rmnProxy: i_rmnProxy, + rmn: i_rmn, tokenAdminRegistry: i_tokenAdminRegistry, nonceManager: i_nonceManager }); diff --git a/contracts/src/v0.8/ccip/onRamp/OnRamp.sol b/contracts/src/v0.8/ccip/onRamp/OnRamp.sol index 677ec1a191..cc449feaed 100644 --- a/contracts/src/v0.8/ccip/onRamp/OnRamp.sol +++ b/contracts/src/v0.8/ccip/onRamp/OnRamp.sol @@ -7,7 +7,7 @@ import {IFeeQuoter} from "../interfaces/IFeeQuoter.sol"; import {IMessageInterceptor} from "../interfaces/IMessageInterceptor.sol"; import {INonceManager} from "../interfaces/INonceManager.sol"; import {IPoolV1} from "../interfaces/IPool.sol"; -import {IRMN} from "../interfaces/IRMN.sol"; +import {IRMNV2} from "../interfaces/IRMNV2.sol"; import {IRouter} from "../interfaces/IRouter.sol"; import {ITokenAdminRegistry} from "../interfaces/ITokenAdminRegistry.sol"; @@ -58,7 +58,7 @@ contract OnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCreator { // solhint-disable-next-line gas-struct-packing struct StaticConfig { uint64 chainSelector; // ─────╮ Source chain selector - address rmnProxy; // ─────────╯ RMN proxy address + IRMNV2 rmn; // ───────────────╯ RMN remote address address nonceManager; // Nonce manager address address tokenAdminRegistry; // Token admin registry address } @@ -109,8 +109,8 @@ contract OnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCreator { string public constant override typeAndVersion = "OnRamp 1.6.0-dev"; /// @dev The chain ID of the source chain that this contract is deployed to uint64 internal immutable i_chainSelector; - /// @dev The address of the rmn proxy - address internal immutable i_rmnProxy; + /// @dev The rmn contract + IRMNV2 internal immutable i_rmn; /// @dev The address of the nonce manager address internal immutable i_nonceManager; /// @dev The address of the token admin registry @@ -129,14 +129,14 @@ contract OnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCreator { DestChainConfigArgs[] memory destChainConfigArgs ) { if ( - staticConfig.chainSelector == 0 || staticConfig.rmnProxy == address(0) || staticConfig.nonceManager == address(0) - || staticConfig.tokenAdminRegistry == address(0) + staticConfig.chainSelector == 0 || address(staticConfig.rmn) == address(0) + || staticConfig.nonceManager == address(0) || staticConfig.tokenAdminRegistry == address(0) ) { revert InvalidConfig(); } i_chainSelector = staticConfig.chainSelector; - i_rmnProxy = staticConfig.rmnProxy; + i_rmn = staticConfig.rmn; i_nonceManager = staticConfig.nonceManager; i_tokenAdminRegistry = staticConfig.tokenAdminRegistry; @@ -299,7 +299,7 @@ contract OnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCreator { function getStaticConfig() external view returns (StaticConfig memory) { return StaticConfig({ chainSelector: i_chainSelector, - rmnProxy: i_rmnProxy, + rmn: i_rmn, nonceManager: i_nonceManager, tokenAdminRegistry: i_tokenAdminRegistry }); @@ -333,7 +333,7 @@ contract OnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCreator { emit ConfigSet( StaticConfig({ chainSelector: i_chainSelector, - rmnProxy: i_rmnProxy, + rmn: i_rmn, nonceManager: i_nonceManager, tokenAdminRegistry: i_tokenAdminRegistry }), @@ -461,7 +461,7 @@ contract OnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCreator { uint64 destChainSelector, Client.EVM2AnyMessage calldata message ) external view returns (uint256 feeTokenAmount) { - if (IRMN(i_rmnProxy).isCursed(bytes16(uint128(destChainSelector)))) revert CursedByRMN(destChainSelector); + if (i_rmn.isCursed(bytes16(uint128(destChainSelector)))) revert CursedByRMN(destChainSelector); return IFeeQuoter(s_dynamicConfig.feeQuoter).getValidatedFee(destChainSelector, message); } diff --git a/contracts/src/v0.8/ccip/RMNHome.sol b/contracts/src/v0.8/ccip/rmn/RMNHome.sol similarity index 98% rename from contracts/src/v0.8/ccip/RMNHome.sol rename to contracts/src/v0.8/ccip/rmn/RMNHome.sol index f28a5da95b..0d3d7d9803 100644 --- a/contracts/src/v0.8/ccip/RMNHome.sol +++ b/contracts/src/v0.8/ccip/rmn/RMNHome.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.24; import "@openzeppelin/contracts/access/Ownable2Step.sol"; -import {ITypeAndVersion} from "../shared/interfaces/ITypeAndVersion.sol"; +import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; /// @notice Stores the home configuration for RMN, that is referenced by CCIP oracles, RMN nodes, and the RMNRemote /// contracts. diff --git a/contracts/src/v0.8/ccip/RMNRemote.sol b/contracts/src/v0.8/ccip/rmn/RMNRemote.sol similarity index 79% rename from contracts/src/v0.8/ccip/RMNRemote.sol rename to contracts/src/v0.8/ccip/rmn/RMNRemote.sol index 19b7f89e1b..3ebbf4af80 100644 --- a/contracts/src/v0.8/ccip/RMNRemote.sol +++ b/contracts/src/v0.8/ccip/rmn/RMNRemote.sol @@ -1,14 +1,16 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.24; -import "@openzeppelin/contracts/access/Ownable2Step.sol"; - -import {ITypeAndVersion} from "../shared/interfaces/ITypeAndVersion.sol"; +import {OwnerIsCreator} from "../../shared/access/OwnerIsCreator.sol"; +import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; +import {IRMNV2} from "../interfaces/IRMNV2.sol"; +import {Internal} from "../libraries/Internal.sol"; bytes32 constant RMN_V1_6_ANY2EVM_REPORT = keccak256("RMN_V1_6_ANY2EVM_REPORT"); +/// @dev XXX DO NOT USE THIS CONTRACT, NOT PRODUCTION READY XXX /// @notice This contract supports verification of RMN reports for any Any2EVM OffRamp. -contract RMNRemote is Ownable2Step, ITypeAndVersion { +contract RMNRemote is OwnerIsCreator, ITypeAndVersion, IRMNV2 { /// @dev temp placeholder to exclude this contract from coverage function test() public {} @@ -85,27 +87,13 @@ contract RMNRemote is Ownable2Step, ITypeAndVersion { return VersionedConfig({version: s_configCount, config: s_config}); } - /// @notice The part of the LaneUpdate for a fixed destination chain and OffRamp, to avoid verbosity in Report - struct DestLaneUpdate { - uint64 sourceChainSelector; - bytes onrampAddress; // generic, to support arbitrary sources; for EVM2EVM, use abi.encodePacked - uint64 minMsgNr; - uint64 maxMsgNr; - bytes32 root; - } - struct Report { uint256 destChainId; // to guard against chain selector misconfiguration uint64 destChainSelector; address rmnRemoteContractAddress; address offrampAddress; bytes32 rmnHomeContractConfigDigest; - DestLaneUpdate[] destLaneUpdates; - } - - struct Signature { - bytes32 r; - bytes32 s; + Internal.MerkleRoot[] destLaneUpdates; } /// @notice Verifies signatures of RMN nodes, on dest lane updates as provided in the CommitReport @@ -113,7 +101,9 @@ contract RMNRemote is Ownable2Step, ITypeAndVersion { /// @param signatures must be sorted in ascending order by signer address /// @dev Will revert if verification fails. Needs to be called by the OffRamp for which the signatures are produced, /// otherwise verification will fail. - function verify(DestLaneUpdate[] memory destLaneUpdates, Signature[] memory signatures) external view { + function verify(Internal.MerkleRoot[] memory destLaneUpdates, Signature[] memory signatures) external view { + return; // XXX temporary workaround to fix integration tests while we wait to productionize this contract + if (s_configCount == 0) { revert ConfigNotSet(); } @@ -146,6 +136,17 @@ contract RMNRemote is Ownable2Step, ITypeAndVersion { if (numSigners < s_config.minSigners) revert ThresholdNotMet(); } + /// @notice If there is an active global or legacy curse, this function returns true. + function isCursed() external view returns (bool) { + return false; // XXX temporary workaround + } + + /// @notice If there is an active global curse, or an active curse for `subject`, this function returns true. + /// @param subject To check whether a particular chain is cursed, set to bytes16(uint128(chainSelector)). + function isCursed(bytes16 subject) external view returns (bool) { + return false; // XXX temporary workaround + } + /// /// Events /// diff --git a/contracts/src/v0.8/ccip/test/BaseTest.t.sol b/contracts/src/v0.8/ccip/test/BaseTest.t.sol index 2eb44ec485..e8003cab15 100644 --- a/contracts/src/v0.8/ccip/test/BaseTest.t.sol +++ b/contracts/src/v0.8/ccip/test/BaseTest.t.sol @@ -3,6 +3,8 @@ pragma solidity 0.8.24; // Imports to any non-library are not allowed due to the significant cascading // compile time increase they cause when imported into this base test. + +import {IRMNV2} from "../interfaces/IRMNV2.sol"; import {Internal} from "../libraries/Internal.sol"; import {RateLimiter} from "../libraries/RateLimiter.sol"; import {MockRMN} from "./mocks/MockRMN.sol"; @@ -69,6 +71,7 @@ contract BaseTest is Test { address internal constant ADMIN = 0x11118e64e1FB0c487f25dD6D3601FF6aF8d32E4e; MockRMN internal s_mockRMN; + IRMNV2 internal s_mockRMNRemote; function setUp() public virtual { // BaseTest.setUp is often called multiple times from tests' setUp due to inheritance. @@ -84,7 +87,25 @@ contract BaseTest is Test { // Set the block time to a constant known value vm.warp(BLOCK_TIME); + // setup mock RMN & RMNRemote s_mockRMN = new MockRMN(); + s_mockRMNRemote = IRMNV2(makeAddr("MOCK RMN REMOTE")); + vm.etch(address(s_mockRMNRemote), bytes("fake bytecode")); + vm.mockCall(address(s_mockRMNRemote), abi.encodeWithSelector(IRMNV2.verify.selector), bytes("")); + _setMockRMNGlobalCurse(false); + vm.mockCall(address(s_mockRMNRemote), abi.encodeWithSignature("isCursed(bytes16)"), abi.encode(false)); // no curses by defaule + } + + function _setMockRMNGlobalCurse(bool isCursed) internal { + vm.mockCall(address(s_mockRMNRemote), abi.encodeWithSignature("isCursed()"), abi.encode(isCursed)); + } + + function _setMockRMNChainCurse(uint64 chainSelector, bool isCursed) internal { + vm.mockCall( + address(s_mockRMNRemote), + abi.encodeWithSignature("isCursed(bytes16)", bytes16(uint128(chainSelector))), + abi.encode(isCursed) + ); } function _getOutboundRateLimiterConfig() internal pure returns (RateLimiter.Config memory) { diff --git a/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.sol b/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.sol index c3c1b311ee..39a80808a3 100644 --- a/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.sol +++ b/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.sol @@ -3,6 +3,7 @@ pragma solidity 0.8.24; import {AuthorizedCallers} from "../../../shared/access/AuthorizedCallers.sol"; import {NonceManager} from "../../NonceManager.sol"; +import {IRMNV2} from "../../interfaces/IRMNV2.sol"; import {LockReleaseTokenPool} from "../../pools/LockReleaseTokenPool.sol"; import {TokenAdminRegistry} from "../../tokenAdminRegistry/TokenAdminRegistry.sol"; import "../helpers/MerkleHelper.sol"; @@ -82,7 +83,7 @@ contract MultiRampsE2E is OnRampSetup, OffRampSetup { s_sourceRouter2.applyRampUpdates(onRampUpdates, new Router.OffRamp[](0), new Router.OffRamp[](0)); // Deploy offramp - _deployOffRamp(s_mockRMN, s_inboundNonceManager); + _deployOffRamp(s_mockRMNRemote, s_inboundNonceManager); // Enable source chains on offramp OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](2); @@ -146,20 +147,27 @@ contract MultiRampsE2E is OnRampSetup, OffRampSetup { merkleRoots[0] = MerkleHelper.getMerkleRoot(hashedMessages1); merkleRoots[1] = MerkleHelper.getMerkleRoot(hashedMessages2); - OffRamp.MerkleRoot[] memory roots = new OffRamp.MerkleRoot[](2); - roots[0] = OffRamp.MerkleRoot({ + // TODO make these real sigs :) + IRMNV2.Signature[] memory rmnSignatures = new IRMNV2.Signature[](0); + + Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](2); + roots[0] = Internal.MerkleRoot({ sourceChainSelector: SOURCE_CHAIN_SELECTOR, - interval: OffRamp.Interval(messages1[0].header.sequenceNumber, messages1[1].header.sequenceNumber), - merkleRoot: merkleRoots[0] + minSeqNr: messages1[0].header.sequenceNumber, + maxSeqNr: messages1[1].header.sequenceNumber, + merkleRoot: merkleRoots[0], + onRampAddress: abi.encode(address(s_onRamp)) }); - roots[1] = OffRamp.MerkleRoot({ + roots[1] = Internal.MerkleRoot({ sourceChainSelector: SOURCE_CHAIN_SELECTOR + 1, - interval: OffRamp.Interval(messages2[0].header.sequenceNumber, messages2[0].header.sequenceNumber), - merkleRoot: merkleRoots[1] + minSeqNr: messages2[0].header.sequenceNumber, + maxSeqNr: messages2[0].header.sequenceNumber, + merkleRoot: merkleRoots[1], + onRampAddress: abi.encode(address(s_onRamp)) }); OffRamp.CommitReport memory report = - OffRamp.CommitReport({priceUpdates: _getEmptyPriceUpdates(), merkleRoots: roots}); + OffRamp.CommitReport({priceUpdates: _getEmptyPriceUpdates(), merkleRoots: roots, rmnSignatures: rmnSignatures}); vm.resumeGasMetering(); _commit(report, ++s_latestSequenceNumber); diff --git a/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol index 1a0b67891d..8db8be3d11 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol @@ -3,7 +3,8 @@ pragma solidity 0.8.24; import {IFeeQuoter} from "../../interfaces/IFeeQuoter.sol"; import {IMessageInterceptor} from "../../interfaces/IMessageInterceptor.sol"; -import {IRMN} from "../../interfaces/IRMN.sol"; +import {IPriceRegistry} from "../../interfaces/IPriceRegistry.sol"; +import {IRMNV2} from "../../interfaces/IRMNV2.sol"; import {IRouter} from "../../interfaces/IRouter.sol"; import {ITokenAdminRegistry} from "../../interfaces/ITokenAdminRegistry.sol"; @@ -34,7 +35,7 @@ contract OffRamp_constructor is OffRampSetup { function test_Constructor_Success() public { OffRamp.StaticConfig memory staticConfig = OffRamp.StaticConfig({ chainSelector: DEST_CHAIN_SELECTOR, - rmnProxy: address(s_mockRMN), + rmn: s_mockRMNRemote, tokenAdminRegistry: address(s_tokenAdminRegistry), nonceManager: address(s_inboundNonceManager) }); @@ -103,7 +104,7 @@ contract OffRamp_constructor is OffRampSetup { // Static config OffRamp.StaticConfig memory gotStaticConfig = s_offRamp.getStaticConfig(); assertEq(staticConfig.chainSelector, gotStaticConfig.chainSelector); - assertEq(staticConfig.rmnProxy, gotStaticConfig.rmnProxy); + assertEq(address(staticConfig.rmn), address(gotStaticConfig.rmn)); assertEq(staticConfig.tokenAdminRegistry, gotStaticConfig.tokenAdminRegistry); // Dynamic config @@ -155,7 +156,7 @@ contract OffRamp_constructor is OffRampSetup { s_offRamp = new OffRampHelper( OffRamp.StaticConfig({ chainSelector: DEST_CHAIN_SELECTOR, - rmnProxy: address(s_mockRMN), + rmn: s_mockRMNRemote, tokenAdminRegistry: address(s_tokenAdminRegistry), nonceManager: address(s_inboundNonceManager) }), @@ -181,7 +182,7 @@ contract OffRamp_constructor is OffRampSetup { s_offRamp = new OffRampHelper( OffRamp.StaticConfig({ chainSelector: DEST_CHAIN_SELECTOR, - rmnProxy: address(s_mockRMN), + rmn: s_mockRMNRemote, tokenAdminRegistry: address(s_tokenAdminRegistry), nonceManager: address(s_inboundNonceManager) }), @@ -190,7 +191,7 @@ contract OffRamp_constructor is OffRampSetup { ); } - function test_ZeroRMNProxy_Revert() public { + function test_ZeroRMNRemote_Revert() public { uint64[] memory sourceChainSelectors = new uint64[](1); sourceChainSelectors[0] = SOURCE_CHAIN_SELECTOR_1; @@ -201,7 +202,7 @@ contract OffRamp_constructor is OffRampSetup { s_offRamp = new OffRampHelper( OffRamp.StaticConfig({ chainSelector: DEST_CHAIN_SELECTOR, - rmnProxy: ZERO_ADDRESS, + rmn: IRMNV2(ZERO_ADDRESS), tokenAdminRegistry: address(s_tokenAdminRegistry), nonceManager: address(s_inboundNonceManager) }), @@ -221,7 +222,7 @@ contract OffRamp_constructor is OffRampSetup { s_offRamp = new OffRampHelper( OffRamp.StaticConfig({ chainSelector: 0, - rmnProxy: address(s_mockRMN), + rmn: s_mockRMNRemote, tokenAdminRegistry: address(s_tokenAdminRegistry), nonceManager: address(s_inboundNonceManager) }), @@ -241,7 +242,7 @@ contract OffRamp_constructor is OffRampSetup { s_offRamp = new OffRampHelper( OffRamp.StaticConfig({ chainSelector: DEST_CHAIN_SELECTOR, - rmnProxy: address(s_mockRMN), + rmn: s_mockRMNRemote, tokenAdminRegistry: ZERO_ADDRESS, nonceManager: address(s_inboundNonceManager) }), @@ -261,7 +262,7 @@ contract OffRamp_constructor is OffRampSetup { s_offRamp = new OffRampHelper( OffRamp.StaticConfig({ chainSelector: DEST_CHAIN_SELECTOR, - rmnProxy: address(s_mockRMN), + rmn: s_mockRMNRemote, tokenAdminRegistry: address(s_tokenAdminRegistry), nonceManager: ZERO_ADDRESS }), @@ -741,7 +742,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { } function test_WithCurseOnAnotherSourceChain_Success() public { - s_mockRMN.setChainCursed(SOURCE_CHAIN_SELECTOR_2, true); + _setMockRMNChainCurse(SOURCE_CHAIN_SELECTOR_2, true); s_offRamp.executeSingleReport( _generateReportFromMessages( SOURCE_CHAIN_SELECTOR_1, _generateMessagesWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1) @@ -751,7 +752,8 @@ contract OffRamp_executeSingleReport is OffRampSetup { } function test_Unhealthy_Success() public { - s_mockRMN.setGlobalCursed(true); + _setMockRMNChainCurse(SOURCE_CHAIN_SELECTOR_1, true); + vm.expectEmit(); emit OffRamp.SkippedReportExecution(SOURCE_CHAIN_SELECTOR_1); s_offRamp.executeSingleReport( @@ -761,7 +763,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { new uint256[](0) ); - s_mockRMN.setGlobalCursed(false); + _setMockRMNChainCurse(SOURCE_CHAIN_SELECTOR_1, false); vm.recordLogs(); s_offRamp.executeSingleReport( _generateReportFromMessages( @@ -808,7 +810,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { } function test_UnhealthySingleChainCurse_Revert() public { - s_mockRMN.setChainCursed(SOURCE_CHAIN_SELECTOR_1, true); + _setMockRMNChainCurse(SOURCE_CHAIN_SELECTOR_1, true); vm.expectEmit(); emit OffRamp.SkippedReportExecution(SOURCE_CHAIN_SELECTOR_1); s_offRamp.executeSingleReport( @@ -819,7 +821,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { ); vm.recordLogs(); // Uncurse should succeed - s_mockRMN.setChainCursed(SOURCE_CHAIN_SELECTOR_1, false); + _setMockRMNChainCurse(SOURCE_CHAIN_SELECTOR_1, false); s_offRamp.executeSingleReport( _generateReportFromMessages( SOURCE_CHAIN_SELECTOR_1, _generateMessagesWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1) @@ -968,15 +970,20 @@ contract OffRamp_executeSingleReport is OffRampSetup { } function _constructCommitReport(bytes32 merkleRoot) internal view returns (OffRamp.CommitReport memory) { - OffRamp.MerkleRoot[] memory roots = new OffRamp.MerkleRoot[](1); - roots[0] = OffRamp.MerkleRoot({ + Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](1); + roots[0] = Internal.MerkleRoot({ sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, - interval: OffRamp.Interval(1, 2), - merkleRoot: merkleRoot + minSeqNr: 1, + maxSeqNr: 2, + merkleRoot: merkleRoot, + onRampAddress: abi.encode(ON_RAMP_ADDRESS_1) }); - return - OffRamp.CommitReport({priceUpdates: _getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), merkleRoots: roots}); + return OffRamp.CommitReport({ + priceUpdates: _getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), + merkleRoots: roots, + rmnSignatures: s_rmnSignatures + }); } } @@ -1263,7 +1270,7 @@ contract OffRamp_batchExecute is OffRampSetup { } function test_MultipleReportsDifferentChainsSkipCursedChain_Success() public { - s_mockRMN.setChainCursed(SOURCE_CHAIN_SELECTOR_1, true); + _setMockRMNChainCurse(SOURCE_CHAIN_SELECTOR_1, true); Internal.Any2EVMRampMessage[] memory messages1 = new Internal.Any2EVMRampMessage[](2); Internal.Any2EVMRampMessage[] memory messages2 = new Internal.Any2EVMRampMessage[](1); @@ -1325,7 +1332,7 @@ contract OffRamp_batchExecute is OffRampSetup { } function test_Unhealthy_Success() public { - s_mockRMN.setGlobalCursed(true); + _setMockRMNChainCurse(SOURCE_CHAIN_SELECTOR_1, true); vm.expectEmit(); emit OffRamp.SkippedReportExecution(SOURCE_CHAIN_SELECTOR_1); s_offRamp.batchExecute( @@ -1335,7 +1342,7 @@ contract OffRamp_batchExecute is OffRampSetup { new uint256[][](1) ); - s_mockRMN.setGlobalCursed(false); + _setMockRMNChainCurse(SOURCE_CHAIN_SELECTOR_1, false); vm.recordLogs(); s_offRamp.batchExecute( @@ -1851,7 +1858,7 @@ contract OffRamp_manuallyExecute is OffRampSetup { gasLimitOverrides[0] = _getGasLimitsFromMessages(messages1); gasLimitOverrides[1] = _getGasLimitsFromMessages(messages2); - s_mockRMN.setChainCursed(SOURCE_CHAIN_SELECTOR_3, true); + _setMockRMNChainCurse(SOURCE_CHAIN_SELECTOR_3, true); vm.expectRevert(abi.encodeWithSelector(OffRamp.CursedByRMN.selector, SOURCE_CHAIN_SELECTOR_3)); @@ -3108,15 +3115,17 @@ contract OffRamp_commit is OffRampSetup { uint64 max1 = 931; bytes32 root = "Only a single root"; - OffRamp.MerkleRoot[] memory roots = new OffRamp.MerkleRoot[](1); - roots[0] = OffRamp.MerkleRoot({ + Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](1); + roots[0] = Internal.MerkleRoot({ sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, - interval: OffRamp.Interval(1, max1), - merkleRoot: root + minSeqNr: 1, + maxSeqNr: max1, + merkleRoot: root, + onRampAddress: abi.encode(ON_RAMP_ADDRESS_1) }); OffRamp.CommitReport memory commitReport = - OffRamp.CommitReport({priceUpdates: _getEmptyPriceUpdates(), merkleRoots: roots}); + OffRamp.CommitReport({priceUpdates: _getEmptyPriceUpdates(), merkleRoots: roots, rmnSignatures: s_rmnSignatures}); vm.expectEmit(); emit OffRamp.CommitReportAccepted(commitReport); @@ -3135,14 +3144,16 @@ contract OffRamp_commit is OffRampSetup { uint64 maxSeq = 12; uint224 tokenStartPrice = IFeeQuoter(s_offRamp.getDynamicConfig().feeQuoter).getTokenPrice(s_sourceFeeToken).value; - OffRamp.MerkleRoot[] memory roots = new OffRamp.MerkleRoot[](1); - roots[0] = OffRamp.MerkleRoot({ + Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](1); + roots[0] = Internal.MerkleRoot({ sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, - interval: OffRamp.Interval(1, maxSeq), - merkleRoot: "stale report 1" + minSeqNr: 1, + maxSeqNr: maxSeq, + merkleRoot: "stale report 1", + onRampAddress: abi.encode(ON_RAMP_ADDRESS_1) }); OffRamp.CommitReport memory commitReport = - OffRamp.CommitReport({priceUpdates: _getEmptyPriceUpdates(), merkleRoots: roots}); + OffRamp.CommitReport({priceUpdates: _getEmptyPriceUpdates(), merkleRoots: roots, rmnSignatures: s_rmnSignatures}); vm.expectEmit(); emit OffRamp.CommitReportAccepted(commitReport); @@ -3155,7 +3166,8 @@ contract OffRamp_commit is OffRampSetup { assertEq(maxSeq + 1, s_offRamp.getSourceChainConfig(SOURCE_CHAIN_SELECTOR).minSeqNr); assertEq(0, s_offRamp.getLatestPriceSequenceNumber()); - commitReport.merkleRoots[0].interval = OffRamp.Interval(maxSeq + 1, maxSeq * 2); + commitReport.merkleRoots[0].minSeqNr = maxSeq + 1; + commitReport.merkleRoots[0].maxSeqNr = maxSeq * 2; commitReport.merkleRoots[0].merkleRoot = "stale report 2"; vm.expectEmit(); @@ -3172,9 +3184,15 @@ contract OffRamp_commit is OffRampSetup { } function test_OnlyTokenPriceUpdates_Success() public { - OffRamp.MerkleRoot[] memory roots = new OffRamp.MerkleRoot[](0); - OffRamp.CommitReport memory commitReport = - OffRamp.CommitReport({priceUpdates: _getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), merkleRoots: roots}); + // force RMN verification to fail + vm.mockCallRevert(address(s_mockRMNRemote), abi.encodeWithSelector(IRMNV2.verify.selector), bytes("")); + + Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](0); + OffRamp.CommitReport memory commitReport = OffRamp.CommitReport({ + priceUpdates: _getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), + merkleRoots: roots, + rmnSignatures: s_rmnSignatures + }); vm.expectEmit(); emit FeeQuoter.UsdPerTokenUpdated(s_sourceFeeToken, 4e18, block.timestamp); @@ -3188,9 +3206,15 @@ contract OffRamp_commit is OffRampSetup { } function test_OnlyGasPriceUpdates_Success() public { - OffRamp.MerkleRoot[] memory roots = new OffRamp.MerkleRoot[](0); - OffRamp.CommitReport memory commitReport = - OffRamp.CommitReport({priceUpdates: _getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), merkleRoots: roots}); + // force RMN verification to fail + vm.mockCallRevert(address(s_mockRMNRemote), abi.encodeWithSelector(IRMNV2.verify.selector), bytes("")); + + Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](0); + OffRamp.CommitReport memory commitReport = OffRamp.CommitReport({ + priceUpdates: _getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), + merkleRoots: roots, + rmnSignatures: s_rmnSignatures + }); vm.expectEmit(); emit FeeQuoter.UsdPerTokenUpdated(s_sourceFeeToken, 4e18, block.timestamp); @@ -3203,9 +3227,12 @@ contract OffRamp_commit is OffRampSetup { } function test_PriceSequenceNumberCleared_Success() public { - OffRamp.MerkleRoot[] memory roots = new OffRamp.MerkleRoot[](0); - OffRamp.CommitReport memory commitReport = - OffRamp.CommitReport({priceUpdates: _getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), merkleRoots: roots}); + Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](0); + OffRamp.CommitReport memory commitReport = OffRamp.CommitReport({ + priceUpdates: _getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), + merkleRoots: roots, + rmnSignatures: s_rmnSignatures + }); vm.expectEmit(); emit FeeQuoter.UsdPerTokenUpdated(s_sourceFeeToken, 4e18, block.timestamp); @@ -3252,10 +3279,11 @@ contract OffRamp_commit is OffRampSetup { uint64 maxSeq = 12; uint224 tokenPrice1 = 4e18; uint224 tokenPrice2 = 5e18; - OffRamp.MerkleRoot[] memory roots = new OffRamp.MerkleRoot[](0); + Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](0); OffRamp.CommitReport memory commitReport = OffRamp.CommitReport({ priceUpdates: _getSingleTokenPriceUpdateStruct(s_sourceFeeToken, tokenPrice1), - merkleRoots: roots + merkleRoots: roots, + rmnSignatures: s_rmnSignatures }); vm.expectEmit(); @@ -3267,11 +3295,13 @@ contract OffRamp_commit is OffRampSetup { _commit(commitReport, s_latestSequenceNumber); assertEq(s_latestSequenceNumber, s_offRamp.getLatestPriceSequenceNumber()); - roots = new OffRamp.MerkleRoot[](1); - roots[0] = OffRamp.MerkleRoot({ + roots = new Internal.MerkleRoot[](1); + roots[0] = Internal.MerkleRoot({ sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, - interval: OffRamp.Interval(1, maxSeq), - merkleRoot: "stale report" + minSeqNr: 1, + maxSeqNr: maxSeq, + merkleRoot: "stale report", + onRampAddress: abi.encode(ON_RAMP_ADDRESS_1) }); commitReport.priceUpdates = _getSingleTokenPriceUpdateStruct(s_sourceFeeToken, tokenPrice2); commitReport.merkleRoots = roots; @@ -3363,74 +3393,109 @@ contract OffRamp_commit is OffRampSetup { _commit(commitReport, s_latestSequenceNumber); } + function test_FailedRMNVerification_Reverts() public { + // force RMN verification to fail + vm.mockCallRevert(address(s_mockRMNRemote), abi.encodeWithSelector(IRMNV2.verify.selector), bytes("")); + + OffRamp.CommitReport memory commitReport = _constructCommitReport(); + vm.expectRevert(); + _commit(commitReport, s_latestSequenceNumber); + } + function test_Unhealthy_Revert() public { - s_mockRMN.setGlobalCursed(true); - OffRamp.MerkleRoot[] memory roots = new OffRamp.MerkleRoot[](1); - roots[0] = OffRamp.MerkleRoot({ + _setMockRMNChainCurse(SOURCE_CHAIN_SELECTOR_1, true); + Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](1); + roots[0] = Internal.MerkleRoot({ sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, - interval: OffRamp.Interval(1, 2), - merkleRoot: "Only a single root" + minSeqNr: 1, + maxSeqNr: 2, + merkleRoot: "Only a single root", + onRampAddress: abi.encode(ON_RAMP_ADDRESS_1) }); OffRamp.CommitReport memory commitReport = - OffRamp.CommitReport({priceUpdates: _getEmptyPriceUpdates(), merkleRoots: roots}); + OffRamp.CommitReport({priceUpdates: _getEmptyPriceUpdates(), merkleRoots: roots, rmnSignatures: s_rmnSignatures}); vm.expectRevert(abi.encodeWithSelector(OffRamp.CursedByRMN.selector, roots[0].sourceChainSelector)); _commit(commitReport, s_latestSequenceNumber); } function test_InvalidRootRevert() public { - OffRamp.MerkleRoot[] memory roots = new OffRamp.MerkleRoot[](1); - roots[0] = OffRamp.MerkleRoot({ + Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](1); + roots[0] = Internal.MerkleRoot({ sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, - interval: OffRamp.Interval(1, 4), - merkleRoot: bytes32(0) + minSeqNr: 1, + maxSeqNr: 4, + merkleRoot: bytes32(0), + onRampAddress: abi.encode(ON_RAMP_ADDRESS_1) }); OffRamp.CommitReport memory commitReport = - OffRamp.CommitReport({priceUpdates: _getEmptyPriceUpdates(), merkleRoots: roots}); + OffRamp.CommitReport({priceUpdates: _getEmptyPriceUpdates(), merkleRoots: roots, rmnSignatures: s_rmnSignatures}); vm.expectRevert(OffRamp.InvalidRoot.selector); _commit(commitReport, s_latestSequenceNumber); } function test_InvalidInterval_Revert() public { - OffRamp.Interval memory interval = OffRamp.Interval(2, 2); - OffRamp.MerkleRoot[] memory roots = new OffRamp.MerkleRoot[](1); - roots[0] = - OffRamp.MerkleRoot({sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, interval: interval, merkleRoot: bytes32(0)}); + Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](1); + roots[0] = Internal.MerkleRoot({ + sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, + minSeqNr: 2, + maxSeqNr: 2, + merkleRoot: bytes32(0), + onRampAddress: abi.encode(ON_RAMP_ADDRESS_1) + }); OffRamp.CommitReport memory commitReport = - OffRamp.CommitReport({priceUpdates: _getEmptyPriceUpdates(), merkleRoots: roots}); + OffRamp.CommitReport({priceUpdates: _getEmptyPriceUpdates(), merkleRoots: roots, rmnSignatures: s_rmnSignatures}); - vm.expectRevert(abi.encodeWithSelector(OffRamp.InvalidInterval.selector, roots[0].sourceChainSelector, interval)); + vm.expectRevert( + abi.encodeWithSelector( + OffRamp.InvalidInterval.selector, roots[0].sourceChainSelector, roots[0].minSeqNr, roots[0].maxSeqNr + ) + ); _commit(commitReport, s_latestSequenceNumber); } function test_InvalidIntervalMinLargerThanMax_Revert() public { s_offRamp.getSourceChainConfig(SOURCE_CHAIN_SELECTOR); - OffRamp.Interval memory interval = OffRamp.Interval(1, 0); - OffRamp.MerkleRoot[] memory roots = new OffRamp.MerkleRoot[](1); - roots[0] = - OffRamp.MerkleRoot({sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, interval: interval, merkleRoot: bytes32(0)}); + Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](1); + roots[0] = Internal.MerkleRoot({ + sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, + minSeqNr: 1, + maxSeqNr: 0, + merkleRoot: bytes32(0), + onRampAddress: abi.encode(ON_RAMP_ADDRESS_1) + }); OffRamp.CommitReport memory commitReport = - OffRamp.CommitReport({priceUpdates: _getEmptyPriceUpdates(), merkleRoots: roots}); + OffRamp.CommitReport({priceUpdates: _getEmptyPriceUpdates(), merkleRoots: roots, rmnSignatures: s_rmnSignatures}); - vm.expectRevert(abi.encodeWithSelector(OffRamp.InvalidInterval.selector, roots[0].sourceChainSelector, interval)); + vm.expectRevert( + abi.encodeWithSelector( + OffRamp.InvalidInterval.selector, roots[0].sourceChainSelector, roots[0].minSeqNr, roots[0].maxSeqNr + ) + ); _commit(commitReport, s_latestSequenceNumber); } function test_ZeroEpochAndRound_Revert() public { - OffRamp.MerkleRoot[] memory roots = new OffRamp.MerkleRoot[](0); - OffRamp.CommitReport memory commitReport = - OffRamp.CommitReport({priceUpdates: _getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), merkleRoots: roots}); + Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](0); + OffRamp.CommitReport memory commitReport = OffRamp.CommitReport({ + priceUpdates: _getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), + merkleRoots: roots, + rmnSignatures: s_rmnSignatures + }); vm.expectRevert(OffRamp.StaleCommitReport.selector); _commit(commitReport, 0); } function test_OnlyPriceUpdateStaleReport_Revert() public { - OffRamp.MerkleRoot[] memory roots = new OffRamp.MerkleRoot[](0); - OffRamp.CommitReport memory commitReport = - OffRamp.CommitReport({priceUpdates: _getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), merkleRoots: roots}); + Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](0); + OffRamp.CommitReport memory commitReport = OffRamp.CommitReport({ + priceUpdates: _getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), + merkleRoots: roots, + rmnSignatures: s_rmnSignatures + }); vm.expectEmit(); emit FeeQuoter.UsdPerTokenUpdated(s_sourceFeeToken, 4e18, block.timestamp); @@ -3441,29 +3506,37 @@ contract OffRamp_commit is OffRampSetup { } function test_SourceChainNotEnabled_Revert() public { - OffRamp.MerkleRoot[] memory roots = new OffRamp.MerkleRoot[](1); - roots[0] = - OffRamp.MerkleRoot({sourceChainSelector: 0, interval: OffRamp.Interval(1, 2), merkleRoot: "Only a single root"}); + Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](1); + roots[0] = Internal.MerkleRoot({ + sourceChainSelector: 0, + minSeqNr: 1, + maxSeqNr: 2, + merkleRoot: "Only a single root", + onRampAddress: abi.encode(ON_RAMP_ADDRESS_1) + }); OffRamp.CommitReport memory commitReport = - OffRamp.CommitReport({priceUpdates: _getEmptyPriceUpdates(), merkleRoots: roots}); + OffRamp.CommitReport({priceUpdates: _getEmptyPriceUpdates(), merkleRoots: roots, rmnSignatures: s_rmnSignatures}); vm.expectRevert(abi.encodeWithSelector(OffRamp.SourceChainNotEnabled.selector, 0)); _commit(commitReport, s_latestSequenceNumber); } function test_RootAlreadyCommitted_Revert() public { - OffRamp.MerkleRoot[] memory roots = new OffRamp.MerkleRoot[](1); - roots[0] = OffRamp.MerkleRoot({ + Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](1); + roots[0] = Internal.MerkleRoot({ sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, - interval: OffRamp.Interval(1, 2), - merkleRoot: "Only a single root" + minSeqNr: 1, + maxSeqNr: 2, + merkleRoot: "Only a single root", + onRampAddress: abi.encode(ON_RAMP_ADDRESS_1) }); OffRamp.CommitReport memory commitReport = - OffRamp.CommitReport({priceUpdates: _getEmptyPriceUpdates(), merkleRoots: roots}); + OffRamp.CommitReport({priceUpdates: _getEmptyPriceUpdates(), merkleRoots: roots, rmnSignatures: s_rmnSignatures}); _commit(commitReport, s_latestSequenceNumber); - commitReport.merkleRoots[0].interval = OffRamp.Interval(3, 3); + commitReport.merkleRoots[0].minSeqNr = 3; + commitReport.merkleRoots[0].maxSeqNr = 3; vm.expectRevert( abi.encodeWithSelector(OffRamp.RootAlreadyCommitted.selector, roots[0].sourceChainSelector, roots[0].merkleRoot) @@ -3472,164 +3545,19 @@ contract OffRamp_commit is OffRampSetup { } function _constructCommitReport() internal view returns (OffRamp.CommitReport memory) { - OffRamp.MerkleRoot[] memory roots = new OffRamp.MerkleRoot[](1); - roots[0] = OffRamp.MerkleRoot({ + Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](1); + roots[0] = Internal.MerkleRoot({ sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, - interval: OffRamp.Interval(1, s_maxInterval), - merkleRoot: "test #2" + minSeqNr: 1, + maxSeqNr: s_maxInterval, + merkleRoot: "test #2", + onRampAddress: abi.encode(ON_RAMP_ADDRESS_1) }); - return - OffRamp.CommitReport({priceUpdates: _getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), merkleRoots: roots}); - } -} - -contract OffRamp_resetUnblessedRoots is OffRampSetup { - function setUp() public virtual override { - super.setUp(); - _setupRealRMN(); - _deployOffRamp(s_realRMN, s_inboundNonceManager); - _setupMultipleOffRamps(); - } - - function test_ResetUnblessedRoots_Success() public { - OffRamp.UnblessedRoot[] memory rootsToReset = new OffRamp.UnblessedRoot[](3); - rootsToReset[0] = OffRamp.UnblessedRoot({sourceChainSelector: SOURCE_CHAIN_SELECTOR, merkleRoot: "1"}); - rootsToReset[1] = OffRamp.UnblessedRoot({sourceChainSelector: SOURCE_CHAIN_SELECTOR, merkleRoot: "2"}); - rootsToReset[2] = OffRamp.UnblessedRoot({sourceChainSelector: SOURCE_CHAIN_SELECTOR, merkleRoot: "3"}); - - OffRamp.MerkleRoot[] memory roots = new OffRamp.MerkleRoot[](3); - roots[0] = OffRamp.MerkleRoot({ - sourceChainSelector: SOURCE_CHAIN_SELECTOR, - interval: OffRamp.Interval(1, 2), - merkleRoot: rootsToReset[0].merkleRoot - }); - roots[1] = OffRamp.MerkleRoot({ - sourceChainSelector: SOURCE_CHAIN_SELECTOR, - interval: OffRamp.Interval(3, 4), - merkleRoot: rootsToReset[1].merkleRoot + return OffRamp.CommitReport({ + priceUpdates: _getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), + merkleRoots: roots, + rmnSignatures: s_rmnSignatures }); - roots[2] = OffRamp.MerkleRoot({ - sourceChainSelector: SOURCE_CHAIN_SELECTOR, - interval: OffRamp.Interval(5, 5), - merkleRoot: rootsToReset[2].merkleRoot - }); - - OffRamp.CommitReport memory report = - OffRamp.CommitReport({priceUpdates: _getEmptyPriceUpdates(), merkleRoots: roots}); - - _commit(report, ++s_latestSequenceNumber); - - IRMN.TaggedRoot[] memory blessedTaggedRoots = new IRMN.TaggedRoot[](1); - blessedTaggedRoots[0] = IRMN.TaggedRoot({commitStore: address(s_offRamp), root: rootsToReset[1].merkleRoot}); - - vm.startPrank(BLESS_VOTE_ADDR); - s_realRMN.voteToBless(blessedTaggedRoots); - - vm.expectEmit(false, false, false, true); - emit OffRamp.RootRemoved(rootsToReset[0].merkleRoot); - - vm.expectEmit(false, false, false, true); - emit OffRamp.RootRemoved(rootsToReset[2].merkleRoot); - - vm.startPrank(OWNER); - s_offRamp.resetUnblessedRoots(rootsToReset); - - assertEq(0, s_offRamp.getMerkleRoot(SOURCE_CHAIN_SELECTOR, rootsToReset[0].merkleRoot)); - assertEq(BLOCK_TIME, s_offRamp.getMerkleRoot(SOURCE_CHAIN_SELECTOR, rootsToReset[1].merkleRoot)); - assertEq(0, s_offRamp.getMerkleRoot(SOURCE_CHAIN_SELECTOR, rootsToReset[2].merkleRoot)); - } - - // Reverts - - function test_OnlyOwner_Revert() public { - vm.stopPrank(); - vm.expectRevert("Only callable by owner"); - OffRamp.UnblessedRoot[] memory rootsToReset = new OffRamp.UnblessedRoot[](0); - s_offRamp.resetUnblessedRoots(rootsToReset); - } -} - -contract OffRamp_verify is OffRampSetup { - function setUp() public virtual override { - super.setUp(); - _setupRealRMN(); - _deployOffRamp(s_realRMN, s_inboundNonceManager); - _setupMultipleOffRamps(); - } - - function test_NotBlessed_Success() public { - bytes32[] memory leaves = new bytes32[](1); - leaves[0] = "root"; - - OffRamp.MerkleRoot[] memory roots = new OffRamp.MerkleRoot[](1); - roots[0] = OffRamp.MerkleRoot({ - sourceChainSelector: SOURCE_CHAIN_SELECTOR, - interval: OffRamp.Interval(1, 2), - merkleRoot: leaves[0] - }); - OffRamp.CommitReport memory report = - OffRamp.CommitReport({priceUpdates: _getEmptyPriceUpdates(), merkleRoots: roots}); - _commit(report, ++s_latestSequenceNumber); - bytes32[] memory proofs = new bytes32[](0); - // We have not blessed this root, should return 0. - uint256 timestamp = s_offRamp.verify(SOURCE_CHAIN_SELECTOR, leaves, proofs, 0); - assertEq(uint256(0), timestamp); - } - - function test_Blessed_Success() public { - bytes32[] memory leaves = new bytes32[](1); - leaves[0] = "root"; - OffRamp.MerkleRoot[] memory roots = new OffRamp.MerkleRoot[](1); - roots[0] = OffRamp.MerkleRoot({ - sourceChainSelector: SOURCE_CHAIN_SELECTOR, - interval: OffRamp.Interval(1, 2), - merkleRoot: leaves[0] - }); - OffRamp.CommitReport memory report = - OffRamp.CommitReport({priceUpdates: _getEmptyPriceUpdates(), merkleRoots: roots}); - _commit(report, ++s_latestSequenceNumber); - // Bless that root. - IRMN.TaggedRoot[] memory taggedRoots = new IRMN.TaggedRoot[](1); - taggedRoots[0] = IRMN.TaggedRoot({commitStore: address(s_offRamp), root: leaves[0]}); - vm.startPrank(BLESS_VOTE_ADDR); - s_realRMN.voteToBless(taggedRoots); - bytes32[] memory proofs = new bytes32[](0); - uint256 timestamp = s_offRamp.verify(SOURCE_CHAIN_SELECTOR, leaves, proofs, 0); - assertEq(BLOCK_TIME, timestamp); - } - - function test_NotBlessedWrongChainSelector_Success() public { - bytes32[] memory leaves = new bytes32[](1); - leaves[0] = "root"; - OffRamp.MerkleRoot[] memory roots = new OffRamp.MerkleRoot[](1); - roots[0] = OffRamp.MerkleRoot({ - sourceChainSelector: SOURCE_CHAIN_SELECTOR, - interval: OffRamp.Interval(1, 2), - merkleRoot: leaves[0] - }); - - OffRamp.CommitReport memory report = - OffRamp.CommitReport({priceUpdates: _getEmptyPriceUpdates(), merkleRoots: roots}); - _commit(report, ++s_latestSequenceNumber); - - // Bless that root. - IRMN.TaggedRoot[] memory taggedRoots = new IRMN.TaggedRoot[](1); - taggedRoots[0] = IRMN.TaggedRoot({commitStore: address(s_offRamp), root: leaves[0]}); - vm.startPrank(BLESS_VOTE_ADDR); - s_realRMN.voteToBless(taggedRoots); - - bytes32[] memory proofs = new bytes32[](0); - uint256 timestamp = s_offRamp.verify(SOURCE_CHAIN_SELECTOR + 1, leaves, proofs, 0); - assertEq(uint256(0), timestamp); - } - - // Reverts - - function test_TooManyLeaves_Revert() public { - bytes32[] memory leaves = new bytes32[](258); - bytes32[] memory proofs = new bytes32[](0); - vm.expectRevert(MerkleMultiProof.InvalidProof.selector); - s_offRamp.verify(SOURCE_CHAIN_SELECTOR, leaves, proofs, 0); } } diff --git a/contracts/src/v0.8/ccip/test/offRamp/OffRampSetup.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRampSetup.t.sol index 79599fb98b..2d65ee735c 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/OffRampSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRampSetup.t.sol @@ -4,6 +4,7 @@ pragma solidity 0.8.24; import {IAny2EVMMessageReceiver} from "../../interfaces/IAny2EVMMessageReceiver.sol"; import {ICommitStore} from "../../interfaces/ICommitStore.sol"; import {IRMN} from "../../interfaces/IRMN.sol"; +import {IRMNV2} from "../../interfaces/IRMNV2.sol"; import {AuthorizedCallers} from "../../../shared/access/AuthorizedCallers.sol"; import {NonceManager} from "../../NonceManager.sol"; @@ -55,6 +56,8 @@ contract OffRampSetup is FeeQuoterSetup, MultiOCR3BaseSetup { uint64 internal s_latestSequenceNumber; + IRMNV2.Signature[] internal s_rmnSignatures; + function setUp() public virtual override(FeeQuoterSetup, MultiOCR3BaseSetup) { FeeQuoterSetup.setUp(); MultiOCR3BaseSetup.setUp(); @@ -67,16 +70,16 @@ contract OffRampSetup is FeeQuoterSetup, MultiOCR3BaseSetup { s_maybeRevertingPool = MaybeRevertingBurnMintTokenPool(s_destPoolByToken[s_destTokens[1]]); s_inboundNonceManager = new NonceManager(new address[](0)); - _deployOffRamp(s_mockRMN, s_inboundNonceManager); + _deployOffRamp(s_mockRMNRemote, s_inboundNonceManager); } - function _deployOffRamp(IRMN rmnProxy, NonceManager nonceManager) internal { + function _deployOffRamp(IRMNV2 rmn, NonceManager nonceManager) internal { OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](0); s_offRamp = new OffRampHelper( OffRamp.StaticConfig({ chainSelector: DEST_CHAIN_SELECTOR, - rmnProxy: address(rmnProxy), + rmn: rmn, tokenAdminRegistry: address(s_tokenAdminRegistry), nonceManager: address(nonceManager) }), @@ -425,7 +428,7 @@ contract OffRampSetup is FeeQuoterSetup, MultiOCR3BaseSetup { s_offRamp = new OffRampHelper( OffRamp.StaticConfig({ chainSelector: DEST_CHAIN_SELECTOR, - rmnProxy: address(s_mockRMN), + rmn: s_mockRMNRemote, tokenAdminRegistry: address(s_tokenAdminRegistry), nonceManager: address(s_inboundNonceManager) }), diff --git a/contracts/src/v0.8/ccip/test/onRamp/OnRamp.t.sol b/contracts/src/v0.8/ccip/test/onRamp/OnRamp.t.sol index f49a196603..d989c15651 100644 --- a/contracts/src/v0.8/ccip/test/onRamp/OnRamp.t.sol +++ b/contracts/src/v0.8/ccip/test/onRamp/OnRamp.t.sol @@ -2,6 +2,7 @@ pragma solidity 0.8.24; import {IMessageInterceptor} from "../../interfaces/IMessageInterceptor.sol"; +import {IRMNV2} from "../../interfaces/IRMNV2.sol"; import {IRouter} from "../../interfaces/IRouter.sol"; import {BurnMintERC677} from "../../../shared/token/ERC677/BurnMintERC677.sol"; @@ -21,7 +22,7 @@ contract OnRamp_constructor is OnRampSetup { function test_Constructor_Success() public { OnRamp.StaticConfig memory staticConfig = OnRamp.StaticConfig({ chainSelector: SOURCE_CHAIN_SELECTOR, - rmnProxy: address(s_mockRMN), + rmn: s_mockRMNRemote, nonceManager: address(s_outboundNonceManager), tokenAdminRegistry: address(s_tokenAdminRegistry) }); @@ -52,7 +53,7 @@ contract OnRamp_constructor is OnRampSetup { new OnRampHelper( OnRamp.StaticConfig({ chainSelector: 0, - rmnProxy: address(s_mockRMN), + rmn: s_mockRMNRemote, nonceManager: address(s_outboundNonceManager), tokenAdminRegistry: address(s_tokenAdminRegistry) }), @@ -66,7 +67,7 @@ contract OnRamp_constructor is OnRampSetup { s_onRamp = new OnRampHelper( OnRamp.StaticConfig({ chainSelector: SOURCE_CHAIN_SELECTOR, - rmnProxy: address(0), + rmn: IRMNV2(address(0)), nonceManager: address(s_outboundNonceManager), tokenAdminRegistry: address(s_tokenAdminRegistry) }), @@ -80,7 +81,7 @@ contract OnRamp_constructor is OnRampSetup { new OnRampHelper( OnRamp.StaticConfig({ chainSelector: SOURCE_CHAIN_SELECTOR, - rmnProxy: address(s_mockRMN), + rmn: s_mockRMNRemote, nonceManager: address(0), tokenAdminRegistry: address(s_tokenAdminRegistry) }), @@ -94,7 +95,7 @@ contract OnRamp_constructor is OnRampSetup { new OnRampHelper( OnRamp.StaticConfig({ chainSelector: SOURCE_CHAIN_SELECTOR, - rmnProxy: address(s_mockRMN), + rmn: s_mockRMNRemote, nonceManager: address(s_outboundNonceManager), tokenAdminRegistry: address(0) }), @@ -497,7 +498,7 @@ contract OnRamp_forwardFromRouter is OnRampSetup { vm.startPrank(OWNER); MaybeRevertingBurnMintTokenPool newPool = new MaybeRevertingBurnMintTokenPool( - BurnMintERC677(sourceETH), new address[](0), address(s_mockRMN), address(s_sourceRouter) + BurnMintERC677(sourceETH), new address[](0), address(s_mockRMNRemote), address(s_sourceRouter) ); BurnMintERC677(sourceETH).grantMintAndBurnRoles(address(newPool)); deal(address(sourceETH), address(newPool), type(uint256).max); @@ -632,7 +633,7 @@ contract OnRamp_getFee is OnRampSetup { // Reverts function test_Unhealthy_Revert() public { - s_mockRMN.setGlobalCursed(true); + _setMockRMNChainCurse(DEST_CHAIN_SELECTOR, true); vm.expectRevert(abi.encodeWithSelector(OnRamp.CursedByRMN.selector, DEST_CHAIN_SELECTOR)); s_onRamp.getFee(DEST_CHAIN_SELECTOR, _generateEmptyMessage()); } diff --git a/contracts/src/v0.8/ccip/test/onRamp/OnRampSetup.t.sol b/contracts/src/v0.8/ccip/test/onRamp/OnRampSetup.t.sol index f43bce6a99..4c43c16f59 100644 --- a/contracts/src/v0.8/ccip/test/onRamp/OnRampSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/onRamp/OnRampSetup.t.sol @@ -117,7 +117,7 @@ contract OnRampSetup is FeeQuoterFeeSetup { OnRampHelper onRamp = new OnRampHelper( OnRamp.StaticConfig({ chainSelector: sourceChainSelector, - rmnProxy: address(s_mockRMN), + rmn: s_mockRMNRemote, nonceManager: nonceManager, tokenAdminRegistry: tokenAdminRegistry }), @@ -161,7 +161,7 @@ contract OnRampSetup is FeeQuoterFeeSetup { function _assertStaticConfigsEqual(OnRamp.StaticConfig memory a, OnRamp.StaticConfig memory b) internal pure { assertEq(a.chainSelector, b.chainSelector); - assertEq(a.rmnProxy, b.rmnProxy); + assertEq(address(a.rmn), address(b.rmn)); assertEq(a.tokenAdminRegistry, b.tokenAdminRegistry); } diff --git a/core/gethwrappers/ccip/generated/ccip_reader_tester/ccip_reader_tester.go b/core/gethwrappers/ccip/generated/ccip_reader_tester/ccip_reader_tester.go index cce56e0d80..1c19bd60bd 100644 --- a/core/gethwrappers/ccip/generated/ccip_reader_tester/ccip_reader_tester.go +++ b/core/gethwrappers/ccip/generated/ccip_reader_tester/ccip_reader_tester.go @@ -30,6 +30,11 @@ var ( _ = abi.ConvertType ) +type IRMNV2Signature struct { + R [32]byte + S [32]byte +} + type InternalEVM2AnyRampMessage struct { Header InternalRampMessageHeader Sender common.Address @@ -46,6 +51,14 @@ type InternalGasPriceUpdate struct { UsdPerUnitGas *big.Int } +type InternalMerkleRoot struct { + SourceChainSelector uint64 + MinSeqNr uint64 + MaxSeqNr uint64 + MerkleRoot [32]byte + OnRampAddress []byte +} + type InternalPriceUpdates struct { TokenPriceUpdates []InternalTokenPriceUpdate GasPriceUpdates []InternalGasPriceUpdate @@ -73,19 +86,9 @@ type InternalTokenPriceUpdate struct { } type OffRampCommitReport struct { - PriceUpdates InternalPriceUpdates - MerkleRoots []OffRampMerkleRoot -} - -type OffRampInterval struct { - Min uint64 - Max uint64 -} - -type OffRampMerkleRoot struct { - SourceChainSelector uint64 - Interval OffRampInterval - MerkleRoot [32]byte + PriceUpdates InternalPriceUpdates + MerkleRoots []InternalMerkleRoot + RmnSignatures []IRMNV2Signature } type OffRampSourceChainConfig struct { @@ -96,8 +99,8 @@ type OffRampSourceChainConfig struct { } var CCIPReaderTesterMetaData = &bind.MetaData{ - ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"CCIPSendRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"internalType\":\"structOffRamp.Interval\",\"name\":\"interval\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structOffRamp.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"report\",\"type\":\"tuple\"}],\"name\":\"CommitReportAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"name\":\"ExecutionStateChanged\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"emitCCIPSendRequested\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"internalType\":\"structOffRamp.Interval\",\"name\":\"interval\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structOffRamp.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"}],\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"report\",\"type\":\"tuple\"}],\"name\":\"emitCommitReportAccepted\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"name\":\"emitExecutionStateChanged\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getExpectedNextSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"getSourceChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"setDestChainSeqNr\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"sourceChainConfig\",\"type\":\"tuple\"}],\"name\":\"setSourceChainConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x608060405234801561001057600080fd5b5061129d806100206000396000f3fe608060405234801561001057600080fd5b506004361061006d5760003560e01c80634cf66e361461007257806385096da9146100875780639041be3d1461009a578063c1a5a355146100ca578063e44302b714610106578063e83eabba14610119578063e9d68a8e1461012c575b600080fd5b610085610080366004610571565b61014c565b005b6100856100953660046107e9565b6101a1565b6100ad6100a8366004610917565b6101e6565b6040516001600160401b0390911681526020015b60405180910390f35b6100856100d8366004610939565b6001600160401b03918216600090815260016020526040902080546001600160401b03191691909216179055565b610085610114366004610adc565b610215565b610085610127366004610c46565b61024f565b61013f61013a366004610917565b6102db565b6040516100c19190610d47565b82846001600160401b0316866001600160401b03167f8c324ce1367b83031769f6a813e3bb4c117aba2185789d66b98b791405be6df28585604051610192929190610d9f565b60405180910390a45050505050565b816001600160401b03167fcae3d9f68a9ed33d0a770e9bcc6fc25d4041dd6391e6cd8015546547a3c93140826040516101da9190610ea2565b60405180910390a25050565b6001600160401b038082166000908152600160208190526040822054919261020f921690610fa4565b92915050565b7f3a3950e13dd607cc37980db0ef14266c40d2bba9c01b2e44bfe549808883095d816040516102449190611091565b60405180910390a150565b6001600160401b0380831660009081526020818152604091829020845181549286015193860151909416600160a81b02600160a81b600160e81b0319931515600160a01b026001600160a81b03199093166001600160a01b03909516949094179190911791909116919091178155606082015182919060018201906102d490826111d1565b5050505050565b60408051608080820183526000808352602080840182905283850182905260608085018190526001600160401b038781168452838352928690208651948501875280546001600160a01b0381168652600160a01b810460ff16151593860193909352600160a81b90920490921694830194909452600184018054939492939184019161036690611146565b80601f016020809104026020016040519081016040528092919081815260200182805461039290611146565b80156103df5780601f106103b4576101008083540402835291602001916103df565b820191906000526020600020905b8154815290600101906020018083116103c257829003601f168201915b5050505050815250509050919050565b80356001600160401b038116811461040657600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60405160a081016001600160401b03811182821017156104435761044361040b565b60405290565b60405161010081016001600160401b03811182821017156104435761044361040b565b604080519081016001600160401b03811182821017156104435761044361040b565b604051606081016001600160401b03811182821017156104435761044361040b565b604051608081016001600160401b03811182821017156104435761044361040b565b604051601f8201601f191681016001600160401b03811182821017156104fa576104fa61040b565b604052919050565b600082601f83011261051357600080fd5b81356001600160401b0381111561052c5761052c61040b565b61053f601f8201601f19166020016104d2565b81815284602083860101111561055457600080fd5b816020850160208301376000918101602001919091529392505050565b600080600080600060a0868803121561058957600080fd5b610592866103ef565b94506105a0602087016103ef565b9350604086013592506060860135600481106105bb57600080fd5b915060808601356001600160401b038111156105d657600080fd5b6105e288828901610502565b9150509295509295909350565b600060a0828403121561060157600080fd5b610609610421565b90508135815261061b602083016103ef565b602082015261062c604083016103ef565b604082015261063d606083016103ef565b606082015261064e608083016103ef565b608082015292915050565b6001600160a01b038116811461066e57600080fd5b50565b803561040681610659565b60006001600160401b038211156106955761069561040b565b5060051b60200190565b600082601f8301126106b057600080fd5b813560206106c56106c08361067c565b6104d2565b82815260059290921b840181019181810190868411156106e457600080fd5b8286015b848110156107de5780356001600160401b03808211156107085760008081fd5b9088019060a0828b03601f19018113156107225760008081fd5b61072a610421565b878401358381111561073c5760008081fd5b61074a8d8a83880101610502565b825250604080850135848111156107615760008081fd5b61076f8e8b83890101610502565b8a84015250606080860135858111156107885760008081fd5b6107968f8c838a0101610502565b838501525060809150818601358184015250828501359250838311156107bc5760008081fd5b6107ca8d8a85880101610502565b9082015286525050509183019183016106e8565b509695505050505050565b600080604083850312156107fc57600080fd5b610805836103ef565b915060208301356001600160401b038082111561082157600080fd5b90840190610180828703121561083657600080fd5b61083e610449565b61084887846105ef565b815261085660a08401610671565b602082015260c08301358281111561086d57600080fd5b61087988828601610502565b60408301525060e08301358281111561089157600080fd5b61089d88828601610502565b606083015250610100830135828111156108b657600080fd5b6108c288828601610502565b6080830152506108d56101208401610671565b60a082015261014083013560c0820152610160830135828111156108f857600080fd5b6109048882860161069f565b60e0830152508093505050509250929050565b60006020828403121561092957600080fd5b610932826103ef565b9392505050565b6000806040838503121561094c57600080fd5b610955836103ef565b9150610963602084016103ef565b90509250929050565b80356001600160e01b038116811461040657600080fd5b600082601f83011261099457600080fd5b813560206109a46106c08361067c565b82815260069290921b840181019181810190868411156109c357600080fd5b8286015b848110156107de57604081890312156109e05760008081fd5b6109e861046c565b6109f1826103ef565b81526109fe85830161096c565b818601528352918301916040016109c7565b600082601f830112610a2157600080fd5b81356020610a316106c08361067c565b82815260079290921b84018101918181019086841115610a5057600080fd5b8286015b848110156107de578088036080811215610a6e5760008081fd5b610a7661048e565b610a7f836103ef565b8152604080601f1984011215610a955760008081fd5b610a9d61046c565b9250610aaa8785016103ef565b8352610ab78185016103ef565b8388015281870192909252606083013591810191909152835291830191608001610a54565b60006020808385031215610aef57600080fd5b82356001600160401b0380821115610b0657600080fd5b81850191506040808388031215610b1c57600080fd5b610b2461046c565b833583811115610b3357600080fd5b84016040818a031215610b4557600080fd5b610b4d61046c565b813585811115610b5c57600080fd5b8201601f81018b13610b6d57600080fd5b8035610b7b6106c08261067c565b81815260069190911b8201890190898101908d831115610b9a57600080fd5b928a01925b82841015610bea5787848f031215610bb75760008081fd5b610bbf61046c565b8435610bca81610659565b8152610bd7858d0161096c565b818d0152825292870192908a0190610b9f565b845250505081870135935084841115610c0257600080fd5b610c0e8a858401610983565b8188015282525083850135915082821115610c2857600080fd5b610c3488838601610a10565b85820152809550505050505092915050565b60008060408385031215610c5957600080fd5b610c62836103ef565b915060208301356001600160401b0380821115610c7e57600080fd5b9084019060808287031215610c9257600080fd5b610c9a6104b0565b8235610ca581610659565b815260208301358015158114610cba57600080fd5b6020820152610ccb604084016103ef565b6040820152606083013582811115610ce257600080fd5b610cee88828601610502565b6060830152508093505050509250929050565b6000815180845260005b81811015610d2757602081850181015186830182015201610d0b565b506000602082860101526020601f19601f83011685010191505092915050565b602080825282516001600160a01b03168282015282015115156040808301919091528201516001600160401b0316606080830191909152820151608080830152600090610d9760a0840182610d01565b949350505050565b600060048410610dbf57634e487b7160e01b600052602160045260246000fd5b83825260406020830152610d976040830184610d01565b6001600160a01b03169052565b600082825180855260208086019550808260051b84010181860160005b84811015610e9557601f19868403018952815160a08151818652610e2682870182610d01565b9150508582015185820387870152610e3e8282610d01565b91505060408083015186830382880152610e588382610d01565b92505050606080830151818701525060808083015192508582038187015250610e818183610d01565b9a86019a9450505090830190600101610e00565b5090979650505050505050565b60208152610eef602082018351805182526020808201516001600160401b039081169184019190915260408083015182169084015260608083015182169084015260809182015116910152565b60006020830151610f0360c0840182610dd6565b5060408301516101808060e0850152610f206101a0850183610d01565b91506060850151601f198086850301610100870152610f3f8483610d01565b9350608087015191508086850301610120870152610f5d8483610d01565b935060a08701519150610f74610140870183610dd6565b60c087015161016087015260e0870151915080868503018387015250610f9a8382610de3565b9695505050505050565b6001600160401b03818116838216019080821115610fd257634e487b7160e01b600052601160045260246000fd5b5092915050565b60008151808452602080850194506020840160005b8381101561102757815180516001600160401b031688528301516001600160e01b03168388015260409096019590820190600101610fee565b509495945050505050565b600081518084526020808501945080840160005b8381101561102757815180516001600160401b0390811689528482015180518216868b0152850151166040898101919091520151606088015260809096019590820190600101611046565b6000602080835283516040808386015260a0850182516040606088015281815180845260c0890191508683019350600092505b808310156110ff57835180516001600160a01b031683528701516001600160e01b0316878301529286019260019290920191908401906110c4565b5093850151878503605f190160808901529361111b8186610fd9565b945050505050818501519150601f1984820301604085015261113d8183611032565b95945050505050565b600181811c9082168061115a57607f821691505b60208210810361117a57634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156111cc576000816000526020600020601f850160051c810160208610156111a95750805b601f850160051c820191505b818110156111c8578281556001016111b5565b5050505b505050565b81516001600160401b038111156111ea576111ea61040b565b6111fe816111f88454611146565b84611180565b602080601f831160018114611233576000841561121b5750858301515b600019600386901b1c1916600185901b1785556111c8565b600085815260208120601f198616915b8281101561126257888601518255948401946001909101908401611243565b50858210156112805787850151600019600388901b60f8161c191681555b5050505050600190811b0190555056fea164736f6c6343000818000a", + ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"CCIPSendRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"structIRMNV2.Signature[]\",\"name\":\"rmnSignatures\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"report\",\"type\":\"tuple\"}],\"name\":\"CommitReportAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"name\":\"ExecutionStateChanged\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"emitCCIPSendRequested\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"structIRMNV2.Signature[]\",\"name\":\"rmnSignatures\",\"type\":\"tuple[]\"}],\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"report\",\"type\":\"tuple\"}],\"name\":\"emitCommitReportAccepted\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"name\":\"emitExecutionStateChanged\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getExpectedNextSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"getSourceChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"setDestChainSeqNr\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"sourceChainConfig\",\"type\":\"tuple\"}],\"name\":\"setSourceChainConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x608060405234801561001057600080fd5b506113f1806100206000396000f3fe608060405234801561001057600080fd5b506004361061006d5760003560e01c806344f38be5146100725780634cf66e361461008757806385096da91461009a5780639041be3d146100ad578063c1a5a355146100dd578063e83eabba14610119578063e9d68a8e1461012c575b600080fd5b6100856100803660046107e2565b61014c565b005b61008561009536600461096c565b610186565b6100856100a8366004610b8e565b6101db565b6100c06100bb366004610cbc565b610220565b6040516001600160401b0390911681526020015b60405180910390f35b6100856100eb366004610cde565b6001600160401b03918216600090815260016020526040902080546001600160401b03191691909216179055565b610085610127366004610d11565b61024f565b61013f61013a366004610cbc565b6102db565b6040516100d49190610e12565b7fd7868a16facbdde7b5c020620136316b3c266fffcb4e1e41cb6a662fe14ba3e18160405161017b9190610fa8565b60405180910390a150565b82846001600160401b0316866001600160401b03167f8c324ce1367b83031769f6a813e3bb4c117aba2185789d66b98b791405be6df285856040516101cc92919061107a565b60405180910390a45050505050565b816001600160401b03167fcae3d9f68a9ed33d0a770e9bcc6fc25d4041dd6391e6cd8015546547a3c93140826040516102149190611163565b60405180910390a25050565b6001600160401b0380821660009081526001602081905260408220549192610249921690611265565b92915050565b6001600160401b0380831660009081526020818152604091829020845181549286015193860151909416600160a81b02600160a81b600160e81b0319931515600160a01b026001600160a81b03199093166001600160a01b03909516949094179190911791909116919091178155606082015182919060018201906102d49082611325565b5050505050565b60408051608080820183526000808352602080840182905283850182905260608085018190526001600160401b038781168452838352928690208651948501875280546001600160a01b0381168652600160a01b810460ff16151593860193909352600160a81b9092049092169483019490945260018401805493949293918401916103669061129a565b80601f01602080910402602001604051908101604052809291908181526020018280546103929061129a565b80156103df5780601f106103b4576101008083540402835291602001916103df565b820191906000526020600020905b8154815290600101906020018083116103c257829003601f168201915b5050505050815250509050919050565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b0381118282101715610427576104276103ef565b60405290565b60405160a081016001600160401b0381118282101715610427576104276103ef565b604051606081016001600160401b0381118282101715610427576104276103ef565b60405161010081016001600160401b0381118282101715610427576104276103ef565b604051608081016001600160401b0381118282101715610427576104276103ef565b604051601f8201601f191681016001600160401b03811182821017156104de576104de6103ef565b604052919050565b60006001600160401b038211156104ff576104ff6103ef565b5060051b60200190565b6001600160a01b038116811461051e57600080fd5b50565b803561052c81610509565b919050565b80356001600160e01b038116811461052c57600080fd5b80356001600160401b038116811461052c57600080fd5b600082601f83011261057057600080fd5b81356020610585610580836104e6565b6104b6565b82815260069290921b840181019181810190868411156105a457600080fd5b8286015b848110156105f157604081890312156105c15760008081fd5b6105c9610405565b6105d282610548565b81526105df858301610531565b818601528352918301916040016105a8565b509695505050505050565b600082601f83011261060d57600080fd5b81356001600160401b03811115610626576106266103ef565b610639601f8201601f19166020016104b6565b81815284602083860101111561064e57600080fd5b816020850160208301376000918101602001919091529392505050565b600082601f83011261067c57600080fd5b8135602061068c610580836104e6565b82815260059290921b840181019181810190868411156106ab57600080fd5b8286015b848110156105f15780356001600160401b03808211156106cf5760008081fd5b9088019060a0828b03601f19018113156106e95760008081fd5b6106f161042d565b6106fc888501610548565b8152604061070b818601610548565b89830152606061071c818701610548565b8284015260809150818601358184015250828501359250838311156107415760008081fd5b61074f8d8a858801016105fc565b9082015286525050509183019183016106af565b600082601f83011261077457600080fd5b81356020610784610580836104e6565b82815260069290921b840181019181810190868411156107a357600080fd5b8286015b848110156105f157604081890312156107c05760008081fd5b6107c8610405565b8135815284820135858201528352918301916040016107a7565b600060208083850312156107f557600080fd5b82356001600160401b038082111561080c57600080fd5b908401906060828703121561082057600080fd5b61082861044f565b82358281111561083757600080fd5b8301604081890381131561084a57600080fd5b610852610405565b82358581111561086157600080fd5b8301601f81018b1361087257600080fd5b8035610880610580826104e6565b81815260069190911b8201890190898101908d83111561089f57600080fd5b928a01925b828410156108ef5785848f0312156108bc5760008081fd5b6108c4610405565b84356108cf81610509565b81526108dc858d01610531565b818d0152825292850192908a01906108a4565b84525050508287013591508482111561090757600080fd5b6109138a83850161055f565b8188015283525050828401358281111561092c57600080fd5b6109388882860161066b565b8583015250604083013593508184111561095157600080fd5b61095d87858501610763565b60408201529695505050505050565b600080600080600060a0868803121561098457600080fd5b61098d86610548565b945061099b60208701610548565b9350604086013592506060860135600481106109b657600080fd5b915060808601356001600160401b038111156109d157600080fd5b6109dd888289016105fc565b9150509295509295909350565b600060a082840312156109fc57600080fd5b610a0461042d565b905081358152610a1660208301610548565b6020820152610a2760408301610548565b6040820152610a3860608301610548565b6060820152610a4960808301610548565b608082015292915050565b600082601f830112610a6557600080fd5b81356020610a75610580836104e6565b82815260059290921b84018101918181019086841115610a9457600080fd5b8286015b848110156105f15780356001600160401b0380821115610ab85760008081fd5b9088019060a0828b03601f1901811315610ad25760008081fd5b610ada61042d565b8784013583811115610aec5760008081fd5b610afa8d8a838801016105fc565b82525060408085013584811115610b115760008081fd5b610b1f8e8b838901016105fc565b8a8401525060608086013585811115610b385760008081fd5b610b468f8c838a01016105fc565b83850152506080915081860135818401525082850135925083831115610b6c5760008081fd5b610b7a8d8a858801016105fc565b908201528652505050918301918301610a98565b60008060408385031215610ba157600080fd5b610baa83610548565b915060208301356001600160401b0380821115610bc657600080fd5b908401906101808287031215610bdb57600080fd5b610be3610471565b610bed87846109ea565b8152610bfb60a08401610521565b602082015260c083013582811115610c1257600080fd5b610c1e888286016105fc565b60408301525060e083013582811115610c3657600080fd5b610c42888286016105fc565b60608301525061010083013582811115610c5b57600080fd5b610c67888286016105fc565b608083015250610c7a6101208401610521565b60a082015261014083013560c082015261016083013582811115610c9d57600080fd5b610ca988828601610a54565b60e0830152508093505050509250929050565b600060208284031215610cce57600080fd5b610cd782610548565b9392505050565b60008060408385031215610cf157600080fd5b610cfa83610548565b9150610d0860208401610548565b90509250929050565b60008060408385031215610d2457600080fd5b610d2d83610548565b915060208301356001600160401b0380821115610d4957600080fd5b9084019060808287031215610d5d57600080fd5b610d65610494565b8235610d7081610509565b815260208301358015158114610d8557600080fd5b6020820152610d9660408401610548565b6040820152606083013582811115610dad57600080fd5b610db9888286016105fc565b6060830152508093505050509250929050565b6000815180845260005b81811015610df257602081850181015186830182015201610dd6565b506000602082860101526020601f19601f83011685010191505092915050565b602080825282516001600160a01b03168282015282015115156040808301919091528201516001600160401b0316606080830191909152820151608080830152600090610e6260a0840182610dcc565b949350505050565b6001600160a01b03169052565b60008151808452602080850194506020840160005b83811015610ec557815180516001600160401b031688528301516001600160e01b03168388015260409096019590820190600101610e8c565b509495945050505050565b600082825180855260208086019550808260051b84010181860160005b84811015610f5f57858303601f19018952815180516001600160401b03908116855285820151811686860152604080830151909116908501526060808201519085015260809081015160a091850182905290610f4b81860183610dcc565b9a86019a9450505090830190600101610eed565b5090979650505050505050565b60008151808452602080850194506020840160005b83811015610ec5578151805188528301518388015260409096019590820190600101610f81565b602080825282516060838301528051604060808501819052815160c086018190526000949392840191859160e08801905b8084101561101457845180516001600160a01b031683528701516001600160e01b031687830152938601936001939093019290820190610fd9565b5093850151878503607f190160a0890152936110308186610e77565b945050505050818501519150601f19808583030160408601526110538284610ed0565b92506040860151915080858403016060860152506110718282610f6c565b95945050505050565b60006004841061109a57634e487b7160e01b600052602160045260246000fd5b83825260406020830152610e626040830184610dcc565b600082825180855260208086019550808260051b84010181860160005b84811015610f5f57601f19868403018952815160a081518186526110f482870182610dcc565b915050858201518582038787015261110c8282610dcc565b915050604080830151868303828801526111268382610dcc565b9250505060608083015181870152506080808301519250858203818701525061114f8183610dcc565b9a86019a94505050908301906001016110ce565b602081526111b0602082018351805182526020808201516001600160401b039081169184019190915260408083015182169084015260608083015182169084015260809182015116910152565b600060208301516111c460c0840182610e6a565b5060408301516101808060e08501526111e16101a0850183610dcc565b91506060850151601f1980868503016101008701526112008483610dcc565b935060808701519150808685030161012087015261121e8483610dcc565b935060a08701519150611235610140870183610e6a565b60c087015161016087015260e087015191508086850301838701525061125b83826110b1565b9695505050505050565b6001600160401b0381811683821601908082111561129357634e487b7160e01b600052601160045260246000fd5b5092915050565b600181811c908216806112ae57607f821691505b6020821081036112ce57634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115611320576000816000526020600020601f850160051c810160208610156112fd5750805b601f850160051c820191505b8181101561131c57828155600101611309565b5050505b505050565b81516001600160401b0381111561133e5761133e6103ef565b6113528161134c845461129a565b846112d4565b602080601f831160018114611387576000841561136f5750858301515b600019600386901b1c1916600185901b17855561131c565b600085815260208120601f198616915b828110156113b657888601518255948401946001909101908401611397565b50858210156113d45787850151600019600388901b60f8161c191681555b5050505050600190811b0190555056fea164736f6c6343000818000a", } var CCIPReaderTesterABI = CCIPReaderTesterMetaData.ABI @@ -751,7 +754,7 @@ func (CCIPReaderTesterCCIPSendRequested) Topic() common.Hash { } func (CCIPReaderTesterCommitReportAccepted) Topic() common.Hash { - return common.HexToHash("0x3a3950e13dd607cc37980db0ef14266c40d2bba9c01b2e44bfe549808883095d") + return common.HexToHash("0xd7868a16facbdde7b5c020620136316b3c266fffcb4e1e41cb6a662fe14ba3e1") } func (CCIPReaderTesterExecutionStateChanged) Topic() common.Hash { diff --git a/core/gethwrappers/ccip/generated/offramp/offramp.go b/core/gethwrappers/ccip/generated/offramp/offramp.go index 6357a0c15f..df4d1124d8 100644 --- a/core/gethwrappers/ccip/generated/offramp/offramp.go +++ b/core/gethwrappers/ccip/generated/offramp/offramp.go @@ -43,6 +43,11 @@ type ClientEVMTokenAmount struct { Amount *big.Int } +type IRMNV2Signature struct { + R [32]byte + S [32]byte +} + type InternalAny2EVMRampMessage struct { Header InternalRampMessageHeader Sender []byte @@ -65,6 +70,14 @@ type InternalGasPriceUpdate struct { UsdPerUnitGas *big.Int } +type InternalMerkleRoot struct { + SourceChainSelector uint64 + MinSeqNr uint64 + MaxSeqNr uint64 + MerkleRoot [32]byte + OnRampAddress []byte +} + type InternalPriceUpdates struct { TokenPriceUpdates []InternalTokenPriceUpdate GasPriceUpdates []InternalGasPriceUpdate @@ -114,8 +127,9 @@ type MultiOCR3BaseOCRConfigArgs struct { } type OffRampCommitReport struct { - PriceUpdates InternalPriceUpdates - MerkleRoots []OffRampMerkleRoot + PriceUpdates InternalPriceUpdates + MerkleRoots []InternalMerkleRoot + RmnSignatures []IRMNV2Signature } type OffRampDynamicConfig struct { @@ -126,17 +140,6 @@ type OffRampDynamicConfig struct { MessageValidator common.Address } -type OffRampInterval struct { - Min uint64 - Max uint64 -} - -type OffRampMerkleRoot struct { - SourceChainSelector uint64 - Interval OffRampInterval - MerkleRoot [32]byte -} - type OffRampSourceChainConfig struct { Router common.Address IsEnabled bool @@ -153,19 +156,14 @@ type OffRampSourceChainConfigArgs struct { type OffRampStaticConfig struct { ChainSelector uint64 - RmnProxy common.Address + Rmn common.Address TokenAdminRegistry common.Address NonceManager common.Address } -type OffRampUnblessedRoot struct { - SourceChainSelector uint64 - MerkleRoot [32]byte -} - var OffRampMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CanOnlySelfCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"actual\",\"type\":\"bytes32\"}],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ExecutionError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"ForkedChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enumMultiOCR3Base.InvalidConfigErrorType\",\"name\":\"errorType\",\"type\":\"uint8\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"got\",\"type\":\"uint256\"}],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidEVMAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"internalType\":\"structOffRamp.Interval\",\"name\":\"interval\",\"type\":\"tuple\"}],\"name\":\"InvalidInterval\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"newLimit\",\"type\":\"uint256\"}],\"name\":\"InvalidManualExecutionGasLimit\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"messageDestChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidMessageDestChainSelector\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"newState\",\"type\":\"uint8\"}],\"name\":\"InvalidNewState\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRoot\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidStaticConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LeavesCannotBeEmpty\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ManualExecutionGasLimitMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"ManualExecutionNotYetEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"errorReason\",\"type\":\"bytes\"}],\"name\":\"MessageValidationError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonUniqueSignatures\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"notPool\",\"type\":\"address\"}],\"name\":\"NotACompatiblePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OracleCannotBeZeroAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ReceiverError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountReleased\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePre\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePost\",\"type\":\"uint256\"}],\"name\":\"ReleaseOrMintBalanceMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"name\":\"RootAlreadyCommitted\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"RootNotCommitted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignaturesOutOfRegistration\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"StaleCommitReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"StaticConfigCannotBeChanged\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"TokenDataMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"TokenHandlingError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnexpectedTokenData\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"WrongMessageLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WrongNumberOfSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroChainSelectorNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"AlreadyAttempted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"internalType\":\"structOffRamp.Interval\",\"name\":\"interval\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structOffRamp.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"report\",\"type\":\"tuple\"}],\"name\":\"CommitReportAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"DynamicConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"messageHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"name\":\"ExecutionStateChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"RootRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"SkippedAlreadyExecutedMessage\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SkippedReportExecution\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"sourceConfig\",\"type\":\"tuple\"}],\"name\":\"SourceChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainSelectorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"}],\"name\":\"StaticConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigUpdates\",\"type\":\"tuple[]\"}],\"name\":\"applySourceChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"destTokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structClient.Any2EVMMessage\",\"name\":\"\",\"type\":\"tuple\"}],\"name\":\"ccipReceive\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"rawVs\",\"type\":\"bytes32\"}],\"name\":\"commit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"execute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"bytes[]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[]\"}],\"name\":\"executeSingleMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"getExecutionState\",\"outputs\":[{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLatestPriceSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"getMerkleRoot\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"getSourceChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"isBlessed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"latestConfigDetails\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"n\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"}],\"internalType\":\"structMultiOCR3Base.ConfigInfo\",\"name\":\"configInfo\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfig\",\"name\":\"ocrConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage[]\",\"name\":\"messages\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[][]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[][]\"},{\"internalType\":\"bytes32[]\",\"name\":\"proofs\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"proofFlagBits\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.ExecutionReportSingleChain[]\",\"name\":\"reports\",\"type\":\"tuple[]\"},{\"internalType\":\"uint256[][]\",\"name\":\"gasLimitOverrides\",\"type\":\"uint256[][]\"}],\"name\":\"manuallyExecute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structOffRamp.UnblessedRoot[]\",\"name\":\"rootToReset\",\"type\":\"tuple[]\"}],\"name\":\"resetUnblessedRoots\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"setDynamicConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfigArgs[]\",\"name\":\"ocrConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"setOCR3Configs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x6101206040523480156200001257600080fd5b5060405162006d0d38038062006d0d8339810160408190526200003591620008c7565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf81620001fa565b5050466080525060208301516001600160a01b03161580620000ec575060408301516001600160a01b0316155b8062000103575060608301516001600160a01b0316155b1562000122576040516342bcdf7f60e11b815260040160405180910390fd5b82516001600160401b03166000036200014e5760405163c656089560e01b815260040160405180910390fd5b82516001600160401b0390811660a052602080850180516001600160a01b0390811660c05260408088018051831660e0526060808a01805185166101005283518b519098168852945184169587019590955251821690850152905116908201527f683eb52ee924eb817377cfa8f41f238f4bb7a877da5267869dfffbad85f564d89060800160405180910390a1620001e682620002a5565b620001f181620003c1565b50505062000c67565b336001600160a01b03821603620002545760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b0316620002ce576040516342bcdf7f60e11b815260040160405180910390fd5b80516004805460208085018051604080880180516060808b0180516001600160a01b039b8c166001600160c01b0319909a168a17600160a01b63ffffffff98891602176001600160c01b0316600160c01b948816949094026001600160e01b031693909317600160e01b93871693909302929092179098556080808b018051600580546001600160a01b031916918d169190911790558451988952955185169688019690965290518316918601919091525116938301939093529151909216908201527fa55bd56595c45f517e5967a3067f3dca684445a3080e7c04a4e0d5a40cda627d9060a00160405180910390a150565b60005b815181101562000666576000828281518110620003e557620003e562000a1d565b60200260200101519050600081602001519050806001600160401b0316600003620004235760405163c656089560e01b815260040160405180910390fd5b81516001600160a01b03166200044c576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160401b0381166000908152600660205260408120600181018054919291620004789062000a33565b80601f0160208091040260200160405190810160405280929190818152602001828054620004a69062000a33565b8015620004f75780601f10620004cb57610100808354040283529160200191620004f7565b820191906000526020600020905b815481529060010190602001808311620004d957829003601f168201915b5050505050905060008460600151905081516000036200059e57805160000362000534576040516342bcdf7f60e11b815260040160405180910390fd5b6001830162000544828262000ac4565b508254600160a81b600160e81b031916600160a81b1783556040516001600160401b03851681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1620005d9565b8080519060200120828051906020012014620005d95760405163c39a620560e01b81526001600160401b038516600482015260240162000083565b604080860151845487516001600160a01b03166001600160a01b0319921515600160a01b02929092166001600160a81b031990911617178455516001600160401b038516907f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b906200064d90869062000b90565b60405180910390a25050505050806001019050620003c4565b5050565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b0381118282101715620006a557620006a56200066a565b60405290565b604051601f8201601f191681016001600160401b0381118282101715620006d657620006d66200066a565b604052919050565b80516001600160401b0381168114620006f657600080fd5b919050565b6001600160a01b03811681146200071157600080fd5b50565b805163ffffffff81168114620006f657600080fd5b6000601f83601f8401126200073d57600080fd5b825160206001600160401b03808311156200075c576200075c6200066a565b8260051b6200076d838201620006ab565b93845286810183019383810190898611156200078857600080fd5b84890192505b85831015620008ba57825184811115620007a85760008081fd5b89016080601f19828d038101821315620007c25760008081fd5b620007cc62000680565b88840151620007db81620006fb565b81526040620007ec858201620006de565b8a8301526060808601518015158114620008065760008081fd5b838301529385015193898511156200081e5760008081fd5b84860195508f603f8701126200083657600094508485fd5b8a8601519450898511156200084f576200084f6200066a565b620008608b858f88011601620006ab565b93508484528f82868801011115620008785760008081fd5b60005b8581101562000898578681018301518582018d01528b016200087b565b5060009484018b0194909452509182015283525091840191908401906200078e565b9998505050505050505050565b6000806000838503610140811215620008df57600080fd5b6080811215620008ee57600080fd5b620008f862000680565b6200090386620006de565b815260208601516200091581620006fb565b602082015260408601516200092a81620006fb565b604082015260608601516200093f81620006fb565b6060820152935060a0607f19820112156200095957600080fd5b5060405160a081016001600160401b0380821183831017156200098057620009806200066a565b81604052608087015191506200099682620006fb565b818352620009a760a0880162000714565b6020840152620009ba60c0880162000714565b6040840152620009cd60e0880162000714565b60608401526101008701519150620009e582620006fb565b608083018290526101208701519294508083111562000a0357600080fd5b505062000a138682870162000729565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b600181811c9082168062000a4857607f821691505b60208210810362000a6957634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111562000abf576000816000526020600020601f850160051c8101602086101562000a9a5750805b601f850160051c820191505b8181101562000abb5782815560010162000aa6565b5050505b505050565b81516001600160401b0381111562000ae05762000ae06200066a565b62000af88162000af1845462000a33565b8462000a6f565b602080601f83116001811462000b30576000841562000b175750858301515b600019600386901b1c1916600185901b17855562000abb565b600085815260208120601f198616915b8281101562000b615788860151825594840194600190910190840162000b40565b508582101562000b805787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b602080825282546001600160a01b0381168383015260a081901c60ff161515604084015260a81c6001600160401b0316606083015260808083015260018084018054600093929190849062000be58162000a33565b8060a089015260c0600183166000811462000c09576001811462000c265762000c58565b60ff19841660c08b015260c083151560051b8b0101945062000c58565b85600052602060002060005b8481101562000c4f5781548c820185015290880190890162000c32565b8b0160c0019550505b50929998505050505050505050565b60805160a05160c05160e0516101005161603062000cdd600039600081816102660152612b27015260008181610237015261301b015260008181610208015281816109390152818161152201526125190152600081816101d801526127a60152600081816118ea015261193601526160306000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c806385572ffb116100d8578063ccd37ba31161008c578063f2fde38b11610066578063f2fde38b14610583578063f716f99f14610596578063ff888fb1146105a957600080fd5b8063ccd37ba31461050b578063d2a15d3514610550578063e9d68a8e1461056357600080fd5b8063991a5018116100bd578063991a5018146104c5578063a80036b4146104d8578063c673e584146104eb57600080fd5b806385572ffb1461049c5780638da5cb5b146104aa57600080fd5b8063311cd5131161012f5780635e36480c116101145780635e36480c146103785780637437ff9f1461039857806379ba50971461049457600080fd5b8063311cd513146103495780633f4b04aa1461035c57600080fd5b806306285c691161016057806306285c69146101a4578063181f5a77146102ed5780632d04ab761461033657600080fd5b806304666f9c1461017c57806305d938b514610191575b600080fd5b61018f61018a3660046141ab565b6105cc565b005b61018f61019f366004614837565b6105e0565b61029660408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316815250905090565b6040516102e49190815167ffffffffffffffff1681526020808301516001600160a01b0390811691830191909152604080840151821690830152606092830151169181019190915260800190565b60405180910390f35b6103296040518060400160405280601181526020017f4f666652616d7020312e362e302d64657600000000000000000000000000000081525081565b6040516102e491906149b2565b61018f610344366004614a5d565b610785565b61018f610357366004614b10565b610c53565b60095460405167ffffffffffffffff90911681526020016102e4565b61038b610386366004614b64565b610cbc565b6040516102e49190614bc1565b6104376040805160a081018252600080825260208201819052918101829052606081018290526080810191909152506040805160a0810182526004546001600160a01b03808216835263ffffffff600160a01b83048116602085015278010000000000000000000000000000000000000000000000008304811694840194909452600160e01b9091049092166060820152600554909116608082015290565b6040516102e49190600060a0820190506001600160a01b03808451168352602084015163ffffffff808216602086015280604087015116604086015280606087015116606086015250508060808501511660808401525092915050565b61018f610d12565b61018f610177366004614bcf565b6000546040516001600160a01b0390911681526020016102e4565b61018f6104d3366004614c1e565b610dd0565b61018f6104e6366004614c92565b610de1565b6104fe6104f9366004614cff565b611154565b6040516102e49190614d5f565b610542610519366004614dd4565b67ffffffffffffffff919091166000908152600860209081526040808320938352929052205490565b6040519081526020016102e4565b61018f61055e366004614dfe565b6112b2565b610576610571366004614e73565b61136c565b6040516102e49190614e8e565b61018f610591366004614edc565b611479565b61018f6105a4366004614f61565b61148a565b6105bc6105b736600461509f565b6114cc565b60405190151581526020016102e4565b6105d461158d565b6105dd816115e9565b50565b6105e86118e7565b815181518114610624576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015610775576000848281518110610643576106436150b8565b6020026020010151905060008160200151519050600085848151811061066b5761066b6150b8565b60200260200101519050805182146106af576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b828110156107665760008282815181106106ce576106ce6150b8565b602002602001015190508060001461075d57846020015182815181106106f6576106f66150b8565b60200260200101516080015181101561075d5784516040517fc8e9605100000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260248101839052604481018290526064015b60405180910390fd5b506001016106b2565b50505050806001019050610627565b506107808383611968565b505050565b60006107938789018961523e565b805151519091501515806107ac57508051602001515115155b156108ac5760095460208a01359067ffffffffffffffff8083169116101561086b576009805467ffffffffffffffff191667ffffffffffffffff83161790556004805483516040517f3937306f0000000000000000000000000000000000000000000000000000000081526001600160a01b0390921692633937306f92610834929101615466565b600060405180830381600087803b15801561084e57600080fd5b505af1158015610862573d6000803e3d6000fd5b505050506108aa565b8160200151516000036108aa576040517f2261116700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b60005b816020015151811015610b9c576000826020015182815181106108d4576108d46150b8565b602090810291909101015180516040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815277ffffffffffffffff00000000000000000000000000000000608083901b166004820152919250906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632cbc26bb90602401602060405180830381865afa158015610980573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109a49190615479565b156109e7576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610754565b60006109f282611a18565b602084015151815491925067ffffffffffffffff908116600160a81b90920416141580610a36575060208084015190810151905167ffffffffffffffff9182169116115b15610a7657825160208401516040517feefb0cac000000000000000000000000000000000000000000000000000000008152610754929190600401615496565b604083015180610ab2576040517f504570e300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b835167ffffffffffffffff16600090815260086020908152604080832084845290915290205415610b255783516040517f32cf0cbf00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260248101829052604401610754565b6020808501510151610b389060016154e1565b82547fffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffff16600160a81b67ffffffffffffffff9283160217909255925116600090815260086020908152604080832094835293905291909120429055506001016108af565b507f3a3950e13dd607cc37980db0ef14266c40d2bba9c01b2e44bfe549808883095d81604051610bcc9190615509565b60405180910390a1610c4860008a8a8a8a8a8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808e0282810182019093528d82529093508d92508c9182918501908490808284376000920191909152508b9250611a7f915050565b505050505050505050565b610c93610c62828401846155a6565b6040805160008082526020820190925290610c8d565b6060815260200190600190039081610c785790505b50611968565b604080516000808252602082019092529050610cb6600185858585866000611a7f565b50505050565b6000610cca600160046155db565b6002610cd7608085615604565b67ffffffffffffffff16610ceb919061562b565b610cf58585611df6565b901c166003811115610d0957610d09614b97565b90505b92915050565b6001546001600160a01b03163314610d6c5760405162461bcd60e51b815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610754565b600080543373ffffffffffffffffffffffffffffffffffffffff19808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610dd861158d565b6105dd81611e3d565b333014610e1a576040517f371a732800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160008082526020820190925281610e57565b6040805180820190915260008082526020820152815260200190600190039081610e305790505b5060a08501515190915015610e8b57610e888460a00151856020015186606001518760000151602001518787611fa3565b90505b6040805160a0810182528551518152855160209081015167ffffffffffffffff1681830152808701518351600094840192610ec79291016149b2565b60408051601f19818403018152918152908252878101516020830152018390526005549091506001600160a01b03168015610fd4576040517f08d450a10000000000000000000000000000000000000000000000000000000081526001600160a01b038216906308d450a190610f419085906004016156e4565b600060405180830381600087803b158015610f5b57600080fd5b505af1925050508015610f6c575060015b610fd4573d808015610f9a576040519150601f19603f3d011682016040523d82523d6000602084013e610f9f565b606091505b50806040517f09c2532500000000000000000000000000000000000000000000000000000000815260040161075491906149b2565b604086015151158015610fe957506080860151155b80611000575060608601516001600160a01b03163b155b806110405750606086015161103e906001600160a01b03167f85572ffb000000000000000000000000000000000000000000000000000000006120c2565b155b1561104d57505050505050565b855160209081015167ffffffffffffffff1660009081526006909152604080822054608089015160608a015192517f3cf9798300000000000000000000000000000000000000000000000000000000815284936001600160a01b0390931692633cf97983926110c592899261138892916004016156f7565b6000604051808303816000875af11580156110e4573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261110c9190810190615733565b50915091508161114a57806040517f0a8d6e8c00000000000000000000000000000000000000000000000000000000815260040161075491906149b2565b5050505050505050565b6111976040805160e081019091526000606082018181526080830182905260a0830182905260c08301919091528190815260200160608152602001606081525090565b60ff808316600090815260026020818152604092839020835160e081018552815460608201908152600183015480881660808401526101008104881660a0840152620100009004909616151560c08201529485529182018054845181840281018401909552808552929385830193909283018282801561124057602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611222575b50505050508152602001600382018054806020026020016040519081016040528092919081815260200182805480156112a257602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611284575b5050505050815250509050919050565b6112ba61158d565b60005b818110156107805760008383838181106112d9576112d96150b8565b9050604002018036038101906112ef91906157c9565b90506112fe81602001516114cc565b61136357805167ffffffffffffffff1660009081526008602090815260408083208285018051855290835281842093909355915191519182527f202f1139a3e334b6056064c0e9b19fd07e44a88d8f6e5ded571b24cf8c371f12910160405180910390a15b506001016112bd565b604080516080808201835260008083526020808401829052838501829052606080850181905267ffffffffffffffff878116845260068352928690208651948501875280546001600160a01b0381168652600160a01b810460ff16151593860193909352600160a81b9092049092169483019490945260018401805493949293918401916113f990615802565b80601f016020809104026020016040519081016040528092919081815260200182805461142590615802565b80156112a25780601f10611447576101008083540402835291602001916112a2565b820191906000526020600020905b81548152906001019060200180831161145557505050919092525091949350505050565b61148161158d565b6105dd816120de565b61149261158d565b60005b81518110156114c8576114c08282815181106114b3576114b36150b8565b6020026020010151612194565b600101611495565b5050565b6040805180820182523081526020810183815291517f4d61677100000000000000000000000000000000000000000000000000000000815290516001600160a01b039081166004830152915160248201526000917f00000000000000000000000000000000000000000000000000000000000000001690634d61677190604401602060405180830381865afa158015611569573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d0c9190615479565b6000546001600160a01b031633146115e75760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610754565b565b60005b81518110156114c8576000828281518110611609576116096150b8565b602002602001015190506000816020015190508067ffffffffffffffff16600003611660576040517fc656089500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81516001600160a01b0316611688576040516342bcdf7f60e11b815260040160405180910390fd5b67ffffffffffffffff811660009081526006602052604081206001810180549192916116b390615802565b80601f01602080910402602001604051908101604052809291908181526020018280546116df90615802565b801561172c5780601f106117015761010080835404028352916020019161172c565b820191906000526020600020905b81548152906001019060200180831161170f57829003601f168201915b5050505050905060008460600151905081516000036117e4578051600003611767576040516342bcdf7f60e11b815260040160405180910390fd5b60018301611775828261588c565b5082547fffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffff16600160a81b17835560405167ffffffffffffffff851681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1611837565b8080519060200120828051906020012014611837576040517fc39a620500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff85166004820152602401610754565b604080860151845487516001600160a01b031673ffffffffffffffffffffffffffffffffffffffff19921515600160a01b02929092167fffffffffffffffffffffff000000000000000000000000000000000000000000909116171784555167ffffffffffffffff8516907f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b906118cf90869061594c565b60405180910390a250505050508060010190506115ec565b467f0000000000000000000000000000000000000000000000000000000000000000146115e7576040517f0f01ce850000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000006004820152466024820152604401610754565b81516000036119a2576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160408051600080825260208201909252911591905b8451811015611a1157611a098582815181106119d7576119d76150b8565b602002602001015184611a03578583815181106119f6576119f66150b8565b60200260200101516124c5565b836124c5565b6001016119b9565b5050505050565b67ffffffffffffffff811660009081526006602052604081208054600160a01b900460ff16610d0c576040517fed053c5900000000000000000000000000000000000000000000000000000000815267ffffffffffffffff84166004820152602401610754565b60ff87811660009081526002602090815260408083208151608081018352815481526001909101548086169382019390935261010083048516918101919091526201000090910490921615156060830152873590611ade8760a4615a1a565b9050826060015115611b26578451611af790602061562b565b8651611b0490602061562b565b611b0f9060a0615a1a565b611b199190615a1a565b611b239082615a1a565b90505b368114611b68576040517f8e1192e100000000000000000000000000000000000000000000000000000000815260048101829052366024820152604401610754565b5081518114611bb05781516040517f93df584c000000000000000000000000000000000000000000000000000000008152600481019190915260248101829052604401610754565b611bb86118e7565b60ff808a1660009081526003602090815260408083203384528252808320815180830190925280548086168352939491939092840191610100909104166002811115611c0657611c06614b97565b6002811115611c1757611c17614b97565b9052509050600281602001516002811115611c3457611c34614b97565b148015611c885750600260008b60ff1660ff168152602001908152602001600020600301816000015160ff1681548110611c7057611c706150b8565b6000918252602090912001546001600160a01b031633145b611cbe576040517fda0f08e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50816060015115611da0576020820151611cd9906001615a2d565b60ff16855114611d15576040517f71253a2500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8351855114611d50576040517fa75d88af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008787604051611d62929190615a46565b604051908190038120611d79918b90602001615a56565b604051602081830303815290604052805190602001209050611d9e8a82888888612dd5565b505b6040805182815260208a81013567ffffffffffffffff169082015260ff8b16917f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef0910160405180910390a2505050505050505050565b67ffffffffffffffff8216600090815260076020526040812081611e1b608085615a6a565b67ffffffffffffffff1681526020810191909152604001600020549392505050565b80516001600160a01b0316611e65576040516342bcdf7f60e11b815260040160405180910390fd5b80516004805460208085018051604080880180516060808b0180516001600160a01b039b8c167fffffffffffffffff000000000000000000000000000000000000000000000000909a168a17600160a01b63ffffffff988916021777ffffffffffffffffffffffffffffffffffffffffffffffff167801000000000000000000000000000000000000000000000000948816949094026001600160e01b031693909317600160e01b93871693909302929092179098556080808b0180516005805473ffffffffffffffffffffffffffffffffffffffff1916918d169190911790558451988952955185169688019690965290518316918601919091525116938301939093529151909216908201527fa55bd56595c45f517e5967a3067f3dca684445a3080e7c04a4e0d5a40cda627d9060a00160405180910390a150565b6060865167ffffffffffffffff811115611fbf57611fbf613fc2565b60405190808252806020026020018201604052801561200457816020015b6040805180820190915260008082526020820152815260200190600190039081611fdd5790505b50905060005b87518110156120b657612091888281518110612028576120286150b8565b6020026020010151888888888887818110612045576120456150b8565b90506020028101906120579190615a91565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612fba92505050565b8282815181106120a3576120a36150b8565b602090810291909101015260010161200a565b505b9695505050505050565b60006120cd8361335f565b8015610d095750610d0983836133c3565b336001600160a01b038216036121365760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610754565b6001805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b806040015160ff166000036121bf576000604051631b3fab5160e11b81526004016107549190615af6565b60208082015160ff8082166000908152600290935260408320600181015492939092839216900361222c57606084015160018201805491151562010000027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff909216919091179055612281565b6060840151600182015460ff6201000090910416151590151514612281576040517f87f6037c00000000000000000000000000000000000000000000000000000000815260ff84166004820152602401610754565b60a0840151805161010010156122ad576001604051631b3fab5160e11b81526004016107549190615af6565b612313848460030180548060200260200160405190810160405280929190818152602001828054801561230957602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116122eb575b505050505061347e565b84606001511561243a576123818484600201805480602002602001604051908101604052809291908181526020018280548015612309576020028201919060005260206000209081546001600160a01b031681526001909101906020018083116122eb57505050505061347e565b6080850151805161010010156123ad576002604051631b3fab5160e11b81526004016107549190615af6565b60408601516123bd906003615b10565b60ff168151116123e3576003604051631b3fab5160e11b81526004016107549190615af6565b80516001840180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1661010060ff84160217905561242b9060028601906020840190613f3b565b50612438858260016134e7565b505b612446848260026134e7565b805161245b9060038501906020840190613f3b565b5060408581015160018401805460ff191660ff8316179055865180855560a088015192517fab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f547936124b49389939260028a01929190615b2c565b60405180910390a1611a118461365b565b815181516040517f2cbc26bb000000000000000000000000000000000000000000000000000000008152608083901b77ffffffffffffffff00000000000000000000000000000000166004820152901515907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632cbc26bb90602401602060405180830381865afa158015612568573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061258c9190615479565b156126185780156125d5576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff83166004820152602401610754565b60405167ffffffffffffffff831681527faab522ed53d887e56ed53dd37398a01aeef6a58e0fa77c2173beb9512d8949339060200160405180910390a150505050565b600061262383611a18565b600101805461263190615802565b80601f016020809104026020016040519081016040528092919081815260200182805461265d90615802565b80156126aa5780601f1061267f576101008083540402835291602001916126aa565b820191906000526020600020905b81548152906001019060200180831161268d57829003601f168201915b505050602088015151929350505060008190036126f2576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8560400151518114612730576040517f57e0e08300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008167ffffffffffffffff81111561274b5761274b613fc2565b604051908082528060200260200182016040528015612774578160200160208202803683370190505b50905060005b8281101561285d5760008860200151828151811061279a5761279a6150b8565b602002602001015190507f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681600001516040015167ffffffffffffffff161461282d57805160409081015190517f38432a2200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610754565b6128378186613677565b838381518110612849576128496150b8565b60209081029190910101525060010161277a565b50600061287486838a606001518b60800151613799565b9050806000036128bc576040517f7dd17a7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff87166004820152602401610754565b60005b83811015610c485760005a905060008a6020015183815181106128e4576128e46150b8565b6020026020010151905060006129028a836000015160600151610cbc565b9050600081600381111561291857612918614b97565b14806129355750600381600381111561293357612933614b97565b145b61298d578151606001516040805167ffffffffffffffff808e16825290921660208301527f3b575419319662b2a6f5e2467d84521517a3382b908eb3d557bb3fdb0c50e23c91015b60405180910390a1505050612dcd565b8815612a5d57600454600090600160a01b900463ffffffff166129b087426155db565b11905080806129d0575060038260038111156129ce576129ce614b97565b145b612a12576040517fa9cfc86200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8c166004820152602401610754565b8b8581518110612a2457612a246150b8565b6020026020010151600014612a57578b8581518110612a4557612a456150b8565b60200260200101518360800181815250505b50612abe565b6000816003811115612a7157612a71614b97565b14612abe578151606001516040805167ffffffffffffffff808e16825290921660208301527f3ef2a99c550a751d4b0b261268f05a803dfb049ab43616a1ffb388f61fe65120910161297d565b81516080015167ffffffffffffffff1615612bad576000816003811115612ae757612ae7614b97565b03612bad5781516080015160208301516040517fe0e03cae0000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169263e0e03cae92612b5e928f929190600401615bd8565b6020604051808303816000875af1158015612b7d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ba19190615479565b612bad57505050612dcd565b60008c604001518581518110612bc557612bc56150b8565b6020026020010151905080518360a001515114612c29578251606001516040517f1cfe6d8b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808e1660048301529091166024820152604401610754565b612c3d8b84600001516060015160016137ef565b600080612c4a8584613897565b91509150612c618d866000015160600151846137ef565b8b15612cd1576003826003811115612c7b57612c7b614b97565b03612cd1576000846003811115612c9457612c94614b97565b14612cd1578451516040517f2b11b8d900000000000000000000000000000000000000000000000000000000815261075491908390600401615c05565b6002826003811115612ce557612ce5614b97565b14612d3f576003826003811115612cfe57612cfe614b97565b14612d3f578451606001516040517f926c5a3e000000000000000000000000000000000000000000000000000000008152610754918f918590600401615c1e565b84600001516000015185600001516060015167ffffffffffffffff168e67ffffffffffffffff167f05665fe9ad095383d018353f4cbcba77e84db27dd215081bbf7cdf9ae6fbe48b8c8b81518110612d9957612d996150b8565b602002602001015186865a612dae908e6155db565b604051612dbe9493929190615c44565b60405180910390a45050505050505b6001016128bf565b8251600090815b8181101561114a576000600188868460208110612dfb57612dfb6150b8565b612e0891901a601b615a2d565b898581518110612e1a57612e1a6150b8565b6020026020010151898681518110612e3457612e346150b8565b602002602001015160405160008152602001604052604051612e72949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015612e94573d6000803e3d6000fd5b505060408051601f1981015160ff808e166000908152600360209081528582206001600160a01b03851683528152858220858701909652855480841686529397509095509293928401916101009004166002811115612ef557612ef5614b97565b6002811115612f0657612f06614b97565b9052509050600181602001516002811115612f2357612f23614b97565b14612f5a576040517fca31867a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051600160ff9091161b851615612f9d576040517ff67bc7c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806000015160ff166001901b851794505050806001019050612ddc565b60408051808201909152600080825260208201526000612fdd8760200151613961565b6040517fbbe4f6db0000000000000000000000000000000000000000000000000000000081526001600160a01b0380831660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063bbe4f6db90602401602060405180830381865afa158015613062573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130869190615c7b565b90506001600160a01b03811615806130ce57506130cc6001600160a01b0382167faff2afbf000000000000000000000000000000000000000000000000000000006120c2565b155b15613110576040517fae9b4ce90000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152602401610754565b60045460009081906131329089908690600160e01b900463ffffffff16613a07565b9150915060008060006131ff6040518061010001604052808e81526020018c67ffffffffffffffff1681526020018d6001600160a01b031681526020018f606001518152602001896001600160a01b031681526020018f6000015181526020018f6040015181526020018b8152506040516024016131b09190615c98565b60408051601f198184030181529190526020810180516001600160e01b03167f390775370000000000000000000000000000000000000000000000000000000017905287866113886084613b35565b9250925092508261323e57816040517fe1cd550900000000000000000000000000000000000000000000000000000000815260040161075491906149b2565b81516020146132865781516040517f78ef8024000000000000000000000000000000000000000000000000000000008152602060048201526024810191909152604401610754565b60008280602001905181019061329c9190615d65565b9050866001600160a01b03168c6001600160a01b0316146133315760006132cd8d8a6132c8868a6155db565b613a07565b509050868110806132e75750816132e488836155db565b14155b1561332f576040517fa966e21f000000000000000000000000000000000000000000000000000000008152600481018390526024810188905260448101829052606401610754565b505b604080518082019091526001600160a01b039098168852602088015250949550505050505095945050505050565b600061338b827f01ffc9a7000000000000000000000000000000000000000000000000000000006133c3565b8015610d0c57506133bc827fffffffff000000000000000000000000000000000000000000000000000000006133c3565b1592915050565b6040517fffffffff0000000000000000000000000000000000000000000000000000000082166024820152600090819060440160408051601f19818403018152919052602080820180516001600160e01b03167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825192935060009283928392909183918a617530fa92503d91506000519050828015613467575060208210155b80156134735750600081115b979650505050505050565b60005b81518110156107805760ff8316600090815260036020526040812083519091908490849081106134b3576134b36150b8565b6020908102919091018101516001600160a01b03168252810191909152604001600020805461ffff19169055600101613481565b60005b8251811015610cb6576000838281518110613507576135076150b8565b602002602001015190506000600281111561352457613524614b97565b60ff80871660009081526003602090815260408083206001600160a01b0387168452909152902054610100900416600281111561356357613563614b97565b14613584576004604051631b3fab5160e11b81526004016107549190615af6565b6001600160a01b0381166135c4576040517fd6c62c9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052808360ff1681526020018460028111156135ea576135ea614b97565b905260ff80871660009081526003602090815260408083206001600160a01b0387168452825290912083518154931660ff198416811782559184015190929091839161ffff19161761010083600281111561364757613647614b97565b0217905550905050508060010190506134ea565b60ff81166105dd576009805467ffffffffffffffff1916905550565b8151602080820151604092830151925160009384936136bd937f2425b0b9f9054c76ff151b0a175b18f37a4a4e82013a72e9f15c9caa095ed21f93909291889101615d7e565b60408051601f1981840301815290829052805160209182012086518051888401516060808b0151908401516080808d015195015195976137069794969395929491939101615db1565b604051602081830303815290604052805190602001208560400151805190602001208660a0015160405160200161373d9190615ec3565b60408051601f198184030181528282528051602091820120908301969096528101939093526060830191909152608082015260a081019190915260c0015b60405160208183030381529060405280519060200120905092915050565b6000806137a7858585613c5b565b90506137b2816114cc565b6137c05760009150506137e7565b67ffffffffffffffff86166000908152600860209081526040808320938352929052205490505b949350505050565b600060026137fe608085615604565b67ffffffffffffffff16613812919061562b565b905060006138208585611df6565b90508161382f600160046155db565b901b19168183600381111561384657613846614b97565b67ffffffffffffffff871660009081526007602052604081209190921b92909217918291613875608088615a6a565b67ffffffffffffffff1681526020810191909152604001600020555050505050565b6040517fa80036b4000000000000000000000000000000000000000000000000000000008152600090606090309063a80036b4906138db9087908790600401615f23565b600060405180830381600087803b1580156138f557600080fd5b505af1925050508015613906575060015b613945573d808015613934576040519150601f19603f3d011682016040523d82523d6000602084013e613939565b606091505b5060039250905061395a565b50506040805160208101909152600081526002905b9250929050565b600081516020146139a057816040517f8d666f6000000000000000000000000000000000000000000000000000000000815260040161075491906149b2565b6000828060200190518101906139b69190615d65565b90506001600160a01b038111806139ce575061040081105b15610d0c57826040517f8d666f6000000000000000000000000000000000000000000000000000000000815260040161075491906149b2565b6000806000806000613a8188604051602401613a3291906001600160a01b0391909116815260200190565b60408051601f198184030181529190526020810180516001600160e01b03167f70a082310000000000000000000000000000000000000000000000000000000017905288886113886084613b35565b92509250925082613ac057816040517fe1cd550900000000000000000000000000000000000000000000000000000000815260040161075491906149b2565b6020825114613b085781516040517f78ef8024000000000000000000000000000000000000000000000000000000008152602060048201526024810191909152604401610754565b81806020019051810190613b1c9190615d65565b613b2682886155db565b94509450505050935093915050565b6000606060008361ffff1667ffffffffffffffff811115613b5857613b58613fc2565b6040519080825280601f01601f191660200182016040528015613b82576020820181803683370190505b509150863b613bb5577f0c3b563c0000000000000000000000000000000000000000000000000000000060005260046000fd5b5a85811015613be8577fafa32a2c0000000000000000000000000000000000000000000000000000000060005260046000fd5b8590036040810481038710613c21577f37c3be290000000000000000000000000000000000000000000000000000000060005260046000fd5b505a6000808a5160208c0160008c8cf193505a900390503d84811115613c445750835b808352806000602085013e50955095509592505050565b8251825160009190818303613c9c576040517f11a6b26400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6101018211801590613cb057506101018111155b613ccd576040516309bde33960e01b815260040160405180910390fd5b60001982820101610100811115613cf7576040516309bde33960e01b815260040160405180910390fd5b80600003613d245786600081518110613d1257613d126150b8565b60200260200101519350505050613ef3565b60008167ffffffffffffffff811115613d3f57613d3f613fc2565b604051908082528060200260200182016040528015613d68578160200160208202803683370190505b50905060008080805b85811015613e925760006001821b8b811603613dcc5788851015613db5578c5160018601958e918110613da657613da66150b8565b60200260200101519050613dee565b8551600185019487918110613da657613da66150b8565b8b5160018401938d918110613de357613de36150b8565b602002602001015190505b600089861015613e1e578d5160018701968f918110613e0f57613e0f6150b8565b60200260200101519050613e40565b8651600186019588918110613e3557613e356150b8565b602002602001015190505b82851115613e61576040516309bde33960e01b815260040160405180910390fd5b613e6b8282613efa565b878481518110613e7d57613e7d6150b8565b60209081029190910101525050600101613d71565b506001850382148015613ea457508683145b8015613eaf57508581145b613ecc576040516309bde33960e01b815260040160405180910390fd5b836001860381518110613ee157613ee16150b8565b60200260200101519750505050505050505b9392505050565b6000818310613f1257613f0d8284613f18565b610d09565b610d0983835b60408051600160208201529081018390526060810182905260009060800161377b565b828054828255906000526020600020908101928215613f9d579160200282015b82811115613f9d578251825473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03909116178255602090920191600190910190613f5b565b50613fa9929150613fad565b5090565b5b80821115613fa95760008155600101613fae565b634e487b7160e01b600052604160045260246000fd5b6040516080810167ffffffffffffffff81118282101715613ffb57613ffb613fc2565b60405290565b60405160a0810167ffffffffffffffff81118282101715613ffb57613ffb613fc2565b60405160c0810167ffffffffffffffff81118282101715613ffb57613ffb613fc2565b6040805190810167ffffffffffffffff81118282101715613ffb57613ffb613fc2565b6040516060810167ffffffffffffffff81118282101715613ffb57613ffb613fc2565b604051601f8201601f1916810167ffffffffffffffff811182821017156140b6576140b6613fc2565b604052919050565b600067ffffffffffffffff8211156140d8576140d8613fc2565b5060051b60200190565b6001600160a01b03811681146105dd57600080fd5b803567ffffffffffffffff8116811461410f57600080fd5b919050565b80151581146105dd57600080fd5b803561410f81614114565b600067ffffffffffffffff82111561414757614147613fc2565b50601f01601f191660200190565b600082601f83011261416657600080fd5b81356141796141748261412d565b61408d565b81815284602083860101111561418e57600080fd5b816020850160208301376000918101602001919091529392505050565b600060208083850312156141be57600080fd5b823567ffffffffffffffff808211156141d657600080fd5b818501915085601f8301126141ea57600080fd5b81356141f8614174826140be565b81815260059190911b8301840190848101908883111561421757600080fd5b8585015b838110156142bd578035858111156142335760008081fd5b86016080818c03601f190181131561424b5760008081fd5b614253613fd8565b89830135614260816140e2565b8152604061426f8482016140f7565b8b83015260608085013561428281614114565b8383015292840135928984111561429b57600091508182fd5b6142a98f8d86880101614155565b90830152508552505091860191860161421b565b5098975050505050505050565b600060a082840312156142dc57600080fd5b6142e4614001565b9050813581526142f6602083016140f7565b6020820152614307604083016140f7565b6040820152614318606083016140f7565b6060820152614329608083016140f7565b608082015292915050565b803561410f816140e2565b600082601f83011261435057600080fd5b81356020614360614174836140be565b82815260059290921b8401810191818101908684111561437f57600080fd5b8286015b848110156120b657803567ffffffffffffffff808211156143a45760008081fd5b818901915060a080601f19848d030112156143bf5760008081fd5b6143c7614001565b87840135838111156143d95760008081fd5b6143e78d8a83880101614155565b825250604080850135848111156143fe5760008081fd5b61440c8e8b83890101614155565b8a84015250606080860135858111156144255760008081fd5b6144338f8c838a0101614155565b838501525060809150818601358184015250828501359250838311156144595760008081fd5b6144678d8a85880101614155565b908201528652505050918301918301614383565b6000610140828403121561448e57600080fd5b614496614024565b90506144a283836142ca565b815260a082013567ffffffffffffffff808211156144bf57600080fd5b6144cb85838601614155565b602084015260c08401359150808211156144e457600080fd5b6144f085838601614155565b604084015261450160e08501614334565b6060840152610100840135608084015261012084013591508082111561452657600080fd5b506145338482850161433f565b60a08301525092915050565b600082601f83011261455057600080fd5b81356020614560614174836140be565b82815260059290921b8401810191818101908684111561457f57600080fd5b8286015b848110156120b657803567ffffffffffffffff8111156145a35760008081fd5b6145b18986838b010161447b565b845250918301918301614583565b600082601f8301126145d057600080fd5b813560206145e0614174836140be565b82815260059290921b840181019181810190868411156145ff57600080fd5b8286015b848110156120b657803567ffffffffffffffff8082111561462357600080fd5b818901915089603f83011261463757600080fd5b85820135614647614174826140be565b81815260059190911b830160400190878101908c83111561466757600080fd5b604085015b838110156146a05780358581111561468357600080fd5b6146928f6040838a0101614155565b84525091890191890161466c565b50875250505092840192508301614603565b600082601f8301126146c357600080fd5b813560206146d3614174836140be565b8083825260208201915060208460051b8701019350868411156146f557600080fd5b602086015b848110156120b657803583529183019183016146fa565b600082601f83011261472257600080fd5b81356020614732614174836140be565b82815260059290921b8401810191818101908684111561475157600080fd5b8286015b848110156120b657803567ffffffffffffffff808211156147765760008081fd5b818901915060a080601f19848d030112156147915760008081fd5b614799614001565b6147a48885016140f7565b8152604080850135848111156147ba5760008081fd5b6147c88e8b8389010161453f565b8a84015250606080860135858111156147e15760008081fd5b6147ef8f8c838a01016145bf565b838501525060809150818601358581111561480a5760008081fd5b6148188f8c838a01016146b2565b9184019190915250919093013590830152508352918301918301614755565b600080604080848603121561484b57600080fd5b833567ffffffffffffffff8082111561486357600080fd5b61486f87838801614711565b945060209150818601358181111561488657600080fd5b8601601f8101881361489757600080fd5b80356148a5614174826140be565b81815260059190911b8201840190848101908a8311156148c457600080fd5b8584015b83811015614950578035868111156148e05760008081fd5b8501603f81018d136148f25760008081fd5b87810135614902614174826140be565b81815260059190911b82018a0190898101908f8311156149225760008081fd5b928b01925b828410156149405783358252928a0192908a0190614927565b86525050509186019186016148c8565b50809750505050505050509250929050565b60005b8381101561497d578181015183820152602001614965565b50506000910152565b6000815180845261499e816020860160208601614962565b601f01601f19169290920160200192915050565b602081526000610d096020830184614986565b8060608101831015610d0c57600080fd5b60008083601f8401126149e857600080fd5b50813567ffffffffffffffff811115614a0057600080fd5b60208301915083602082850101111561395a57600080fd5b60008083601f840112614a2a57600080fd5b50813567ffffffffffffffff811115614a4257600080fd5b6020830191508360208260051b850101111561395a57600080fd5b60008060008060008060008060e0898b031215614a7957600080fd5b614a838a8a6149c5565b9750606089013567ffffffffffffffff80821115614aa057600080fd5b614aac8c838d016149d6565b909950975060808b0135915080821115614ac557600080fd5b614ad18c838d01614a18565b909750955060a08b0135915080821115614aea57600080fd5b50614af78b828c01614a18565b999c989b50969995989497949560c00135949350505050565b600080600060808486031215614b2557600080fd5b614b2f85856149c5565b9250606084013567ffffffffffffffff811115614b4b57600080fd5b614b57868287016149d6565b9497909650939450505050565b60008060408385031215614b7757600080fd5b614b80836140f7565b9150614b8e602084016140f7565b90509250929050565b634e487b7160e01b600052602160045260246000fd5b60048110614bbd57614bbd614b97565b9052565b60208101610d0c8284614bad565b600060208284031215614be157600080fd5b813567ffffffffffffffff811115614bf857600080fd5b820160a08185031215613ef357600080fd5b803563ffffffff8116811461410f57600080fd5b600060a08284031215614c3057600080fd5b614c38614001565b8235614c43816140e2565b8152614c5160208401614c0a565b6020820152614c6260408401614c0a565b6040820152614c7360608401614c0a565b60608201526080830135614c86816140e2565b60808201529392505050565b600080600060408486031215614ca757600080fd5b833567ffffffffffffffff80821115614cbf57600080fd5b614ccb8783880161447b565b94506020860135915080821115614ce157600080fd5b50614b5786828701614a18565b803560ff8116811461410f57600080fd5b600060208284031215614d1157600080fd5b610d0982614cee565b60008151808452602080850194506020840160005b83811015614d545781516001600160a01b031687529582019590820190600101614d2f565b509495945050505050565b60208152600082518051602084015260ff602082015116604084015260ff604082015116606084015260608101511515608084015250602083015160c060a0840152614dae60e0840182614d1a565b90506040840151601f198483030160c0850152614dcb8282614d1a565b95945050505050565b60008060408385031215614de757600080fd5b614df0836140f7565b946020939093013593505050565b60008060208385031215614e1157600080fd5b823567ffffffffffffffff80821115614e2957600080fd5b818501915085601f830112614e3d57600080fd5b813581811115614e4c57600080fd5b8660208260061b8501011115614e6157600080fd5b60209290920196919550909350505050565b600060208284031215614e8557600080fd5b610d09826140f7565b602081526001600160a01b03825116602082015260208201511515604082015267ffffffffffffffff6040830151166060820152600060608301516080808401526137e760a0840182614986565b600060208284031215614eee57600080fd5b8135613ef3816140e2565b600082601f830112614f0a57600080fd5b81356020614f1a614174836140be565b8083825260208201915060208460051b870101935086841115614f3c57600080fd5b602086015b848110156120b6578035614f54816140e2565b8352918301918301614f41565b60006020808385031215614f7457600080fd5b823567ffffffffffffffff80821115614f8c57600080fd5b818501915085601f830112614fa057600080fd5b8135614fae614174826140be565b81815260059190911b83018401908481019088831115614fcd57600080fd5b8585015b838110156142bd57803585811115614fe857600080fd5b860160c0818c03601f19011215614fff5760008081fd5b615007614024565b888201358152604061501a818401614cee565b8a830152606061502b818501614cee565b828401526080915061503e828501614122565b9083015260a083810135898111156150565760008081fd5b6150648f8d83880101614ef9565b838501525060c084013591508882111561507e5760008081fd5b61508c8e8c84870101614ef9565b9083015250845250918601918601614fd1565b6000602082840312156150b157600080fd5b5035919050565b634e487b7160e01b600052603260045260246000fd5b80356001600160e01b038116811461410f57600080fd5b600082601f8301126150f657600080fd5b81356020615106614174836140be565b82815260069290921b8401810191818101908684111561512557600080fd5b8286015b848110156120b657604081890312156151425760008081fd5b61514a614047565b615153826140f7565b81526151608583016150ce565b81860152835291830191604001615129565b600082601f83011261518357600080fd5b81356020615193614174836140be565b82815260079290921b840181019181810190868411156151b257600080fd5b8286015b848110156120b65780880360808112156151d05760008081fd5b6151d861406a565b6151e1836140f7565b8152604080601f19840112156151f75760008081fd5b6151ff614047565b925061520c8785016140f7565b83526152198185016140f7565b83880152818701929092526060830135918101919091528352918301916080016151b6565b6000602080838503121561525157600080fd5b823567ffffffffffffffff8082111561526957600080fd5b8185019150604080838803121561527f57600080fd5b615287614047565b83358381111561529657600080fd5b84016040818a0312156152a857600080fd5b6152b0614047565b8135858111156152bf57600080fd5b8201601f81018b136152d057600080fd5b80356152de614174826140be565b81815260069190911b8201890190898101908d8311156152fd57600080fd5b928a01925b8284101561534d5787848f03121561531a5760008081fd5b615322614047565b843561532d816140e2565b815261533a858d016150ce565b818d0152825292870192908a0190615302565b84525050508187013593508484111561536557600080fd5b6153718a8584016150e5565b818801528252508385013591508282111561538b57600080fd5b61539788838601615172565b85820152809550505050505092915050565b805160408084528151848201819052600092602091908201906060870190855b8181101561540057835180516001600160a01b031684528501516001600160e01b03168584015292840192918501916001016153c9565b50508583015187820388850152805180835290840192506000918401905b8083101561545a578351805167ffffffffffffffff1683528501516001600160e01b03168583015292840192600192909201919085019061541e565b50979650505050505050565b602081526000610d0960208301846153a9565b60006020828403121561548b57600080fd5b8151613ef381614114565b67ffffffffffffffff8316815260608101613ef36020830184805167ffffffffffffffff908116835260209182015116910152565b634e487b7160e01b600052601160045260246000fd5b67ffffffffffffffff818116838216019080821115615502576155026154cb565b5092915050565b60006020808352606084516040808487015261552860608701836153a9565b87850151878203601f19016040890152805180835290860193506000918601905b808310156142bd57845167ffffffffffffffff81511683528781015161558889850182805167ffffffffffffffff908116835260209182015116910152565b50840151828701529386019360019290920191608090910190615549565b6000602082840312156155b857600080fd5b813567ffffffffffffffff8111156155cf57600080fd5b6137e784828501614711565b81810381811115610d0c57610d0c6154cb565b634e487b7160e01b600052601260045260246000fd5b600067ffffffffffffffff8084168061561f5761561f6155ee565b92169190910692915050565b8082028115828204841417610d0c57610d0c6154cb565b805182526000602067ffffffffffffffff81840151168185015260408084015160a0604087015261567660a0870182614986565b90506060850151868203606088015261568f8282614986565b608087810151898303918a01919091528051808352908601935060009250908501905b8083101561545a57835180516001600160a01b03168352860151868301529285019260019290920191908401906156b2565b602081526000610d096020830184615642565b60808152600061570a6080830187615642565b61ffff9590951660208301525060408101929092526001600160a01b0316606090910152919050565b60008060006060848603121561574857600080fd5b835161575381614114565b602085015190935067ffffffffffffffff81111561577057600080fd5b8401601f8101861361578157600080fd5b805161578f6141748261412d565b8181528760208385010111156157a457600080fd5b6157b5826020830160208601614962565b809450505050604084015190509250925092565b6000604082840312156157db57600080fd5b6157e3614047565b6157ec836140f7565b8152602083013560208201528091505092915050565b600181811c9082168061581657607f821691505b60208210810361583657634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115610780576000816000526020600020601f850160051c810160208610156158655750805b601f850160051c820191505b8181101561588457828155600101615871565b505050505050565b815167ffffffffffffffff8111156158a6576158a6613fc2565b6158ba816158b48454615802565b8461583c565b602080601f8311600181146158ef57600084156158d75750858301515b600019600386901b1c1916600185901b178555615884565b600085815260208120601f198616915b8281101561591e578886015182559484019460019091019084016158ff565b508582101561593c5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6000602080835283546001600160a01b038116602085015260ff8160a01c161515604085015267ffffffffffffffff8160a81c1660608501525060018085016080808601526000815461599e81615802565b8060a089015260c060018316600081146159bf57600181146159db57615a0b565b60ff19841660c08b015260c083151560051b8b01019450615a0b565b85600052602060002060005b84811015615a025781548c82018501529088019089016159e7565b8b0160c0019550505b50929998505050505050505050565b80820180821115610d0c57610d0c6154cb565b60ff8181168382160190811115610d0c57610d0c6154cb565b8183823760009101908152919050565b828152606082602083013760800192915050565b600067ffffffffffffffff80841680615a8557615a856155ee565b92169190910492915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112615ac657600080fd5b83018035915067ffffffffffffffff821115615ae157600080fd5b60200191503681900382131561395a57600080fd5b6020810160058310615b0a57615b0a614b97565b91905290565b60ff8181168382160290811690818114615502576155026154cb565b600060a0820160ff881683526020878185015260a0604085015281875480845260c0860191508860005282600020935060005b81811015615b845784546001600160a01b031683526001948501949284019201615b5f565b50508481036060860152865180825290820192508187019060005b81811015615bc45782516001600160a01b031685529383019391830191600101615b9f565b50505060ff851660808501525090506120b8565b600067ffffffffffffffff808616835280851660208401525060606040830152614dcb6060830184614986565b8281526040602082015260006137e76040830184614986565b67ffffffffffffffff848116825283166020820152606081016137e76040830184614bad565b848152615c546020820185614bad565b608060408201526000615c6a6080830185614986565b905082606083015295945050505050565b600060208284031215615c8d57600080fd5b8151613ef3816140e2565b6020815260008251610100806020850152615cb7610120850183614986565b91506020850151615cd4604086018267ffffffffffffffff169052565b5060408501516001600160a01b038116606086015250606085015160808501526080850151615d0e60a08601826001600160a01b03169052565b5060a0850151601f19808685030160c0870152615d2b8483614986565b935060c08701519150808685030160e0870152615d488483614986565b935060e08701519150808685030183870152506120b88382614986565b600060208284031215615d7757600080fd5b5051919050565b848152600067ffffffffffffffff8086166020840152808516604084015250608060608301526120b86080830184614986565b86815260c060208201526000615dca60c0830188614986565b6001600160a01b039690961660408301525067ffffffffffffffff9384166060820152608081019290925290911660a09091015292915050565b600082825180855260208086019550808260051b84010181860160005b84811015615eb657601f19868403018952815160a08151818652615e4782870182614986565b9150508582015185820387870152615e5f8282614986565b91505060408083015186830382880152615e798382614986565b92505050606080830151818701525060808083015192508582038187015250615ea28183614986565b9a86019a9450505090830190600101615e21565b5090979650505050505050565b602081526000610d096020830184615e04565b60008282518085526020808601955060208260051b8401016020860160005b84811015615eb657601f19868403018952615f11838351614986565b98840198925090830190600101615ef5565b604081526000835180516040840152602081015167ffffffffffffffff80821660608601528060408401511660808601528060608401511660a08601528060808401511660c086015250505060208401516101408060e0850152615f8b610180850183614986565b915060408601517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08086850301610100870152615fc88483614986565b935060608801519150615fe76101208701836001600160a01b03169052565b60808801518387015260a088015192508086850301610160870152505061600e8282615e04565b9150508281036020840152614dcb8185615ed656fea164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CanOnlySelfCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"actual\",\"type\":\"bytes32\"}],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ExecutionError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"ForkedChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enumMultiOCR3Base.InvalidConfigErrorType\",\"name\":\"errorType\",\"type\":\"uint8\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"got\",\"type\":\"uint256\"}],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidEVMAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"name\":\"InvalidInterval\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"newLimit\",\"type\":\"uint256\"}],\"name\":\"InvalidManualExecutionGasLimit\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"messageDestChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidMessageDestChainSelector\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"newState\",\"type\":\"uint8\"}],\"name\":\"InvalidNewState\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRoot\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidStaticConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LeavesCannotBeEmpty\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ManualExecutionGasLimitMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"ManualExecutionNotYetEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"errorReason\",\"type\":\"bytes\"}],\"name\":\"MessageValidationError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonUniqueSignatures\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"notPool\",\"type\":\"address\"}],\"name\":\"NotACompatiblePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OracleCannotBeZeroAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ReceiverError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountReleased\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePre\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePost\",\"type\":\"uint256\"}],\"name\":\"ReleaseOrMintBalanceMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"name\":\"RootAlreadyCommitted\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"RootNotCommitted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignaturesOutOfRegistration\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"StaleCommitReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"StaticConfigCannotBeChanged\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"TokenDataMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"TokenHandlingError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnexpectedTokenData\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"WrongMessageLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WrongNumberOfSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroChainSelectorNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"AlreadyAttempted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"structIRMNV2.Signature[]\",\"name\":\"rmnSignatures\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"report\",\"type\":\"tuple\"}],\"name\":\"CommitReportAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"DynamicConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"messageHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"name\":\"ExecutionStateChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"RootRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"SkippedAlreadyExecutedMessage\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SkippedReportExecution\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"sourceConfig\",\"type\":\"tuple\"}],\"name\":\"SourceChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainSelectorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"}],\"name\":\"StaticConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigUpdates\",\"type\":\"tuple[]\"}],\"name\":\"applySourceChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"destTokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structClient.Any2EVMMessage\",\"name\":\"\",\"type\":\"tuple\"}],\"name\":\"ccipReceive\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"rawVs\",\"type\":\"bytes32\"}],\"name\":\"commit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"execute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"bytes[]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[]\"}],\"name\":\"executeSingleMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"getExecutionState\",\"outputs\":[{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLatestPriceSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"getMerkleRoot\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"getSourceChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"latestConfigDetails\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"n\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"}],\"internalType\":\"structMultiOCR3Base.ConfigInfo\",\"name\":\"configInfo\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfig\",\"name\":\"ocrConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage[]\",\"name\":\"messages\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[][]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[][]\"},{\"internalType\":\"bytes32[]\",\"name\":\"proofs\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"proofFlagBits\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.ExecutionReportSingleChain[]\",\"name\":\"reports\",\"type\":\"tuple[]\"},{\"internalType\":\"uint256[][]\",\"name\":\"gasLimitOverrides\",\"type\":\"uint256[][]\"}],\"name\":\"manuallyExecute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"setDynamicConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfigArgs[]\",\"name\":\"ocrConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"setOCR3Configs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x6101206040523480156200001257600080fd5b5060405162006c6538038062006c658339810160408190526200003591620008c7565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf81620001fa565b5050466080525060208301516001600160a01b03161580620000ec575060408301516001600160a01b0316155b8062000103575060608301516001600160a01b0316155b1562000122576040516342bcdf7f60e11b815260040160405180910390fd5b82516001600160401b03166000036200014e5760405163c656089560e01b815260040160405180910390fd5b82516001600160401b0390811660a052602080850180516001600160a01b0390811660c05260408088018051831660e0526060808a01805185166101005283518b519098168852945184169587019590955251821690850152905116908201527f683eb52ee924eb817377cfa8f41f238f4bb7a877da5267869dfffbad85f564d89060800160405180910390a1620001e682620002a5565b620001f181620003c1565b50505062000c67565b336001600160a01b03821603620002545760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b0316620002ce576040516342bcdf7f60e11b815260040160405180910390fd5b80516004805460208085018051604080880180516060808b0180516001600160a01b039b8c166001600160c01b0319909a168a17600160a01b63ffffffff98891602176001600160c01b0316600160c01b948816949094026001600160e01b031693909317600160e01b93871693909302929092179098556080808b018051600580546001600160a01b031916918d169190911790558451988952955185169688019690965290518316918601919091525116938301939093529151909216908201527fa55bd56595c45f517e5967a3067f3dca684445a3080e7c04a4e0d5a40cda627d9060a00160405180910390a150565b60005b815181101562000666576000828281518110620003e557620003e562000a1d565b60200260200101519050600081602001519050806001600160401b0316600003620004235760405163c656089560e01b815260040160405180910390fd5b81516001600160a01b03166200044c576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160401b0381166000908152600660205260408120600181018054919291620004789062000a33565b80601f0160208091040260200160405190810160405280929190818152602001828054620004a69062000a33565b8015620004f75780601f10620004cb57610100808354040283529160200191620004f7565b820191906000526020600020905b815481529060010190602001808311620004d957829003601f168201915b5050505050905060008460600151905081516000036200059e57805160000362000534576040516342bcdf7f60e11b815260040160405180910390fd5b6001830162000544828262000ac4565b508254600160a81b600160e81b031916600160a81b1783556040516001600160401b03851681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1620005d9565b8080519060200120828051906020012014620005d95760405163c39a620560e01b81526001600160401b038516600482015260240162000083565b604080860151845487516001600160a01b03166001600160a01b0319921515600160a01b02929092166001600160a81b031990911617178455516001600160401b038516907f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b906200064d90869062000b90565b60405180910390a25050505050806001019050620003c4565b5050565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b0381118282101715620006a557620006a56200066a565b60405290565b604051601f8201601f191681016001600160401b0381118282101715620006d657620006d66200066a565b604052919050565b80516001600160401b0381168114620006f657600080fd5b919050565b6001600160a01b03811681146200071157600080fd5b50565b805163ffffffff81168114620006f657600080fd5b6000601f83601f8401126200073d57600080fd5b825160206001600160401b03808311156200075c576200075c6200066a565b8260051b6200076d838201620006ab565b93845286810183019383810190898611156200078857600080fd5b84890192505b85831015620008ba57825184811115620007a85760008081fd5b89016080601f19828d038101821315620007c25760008081fd5b620007cc62000680565b88840151620007db81620006fb565b81526040620007ec858201620006de565b8a8301526060808601518015158114620008065760008081fd5b838301529385015193898511156200081e5760008081fd5b84860195508f603f8701126200083657600094508485fd5b8a8601519450898511156200084f576200084f6200066a565b620008608b858f88011601620006ab565b93508484528f82868801011115620008785760008081fd5b60005b8581101562000898578681018301518582018d01528b016200087b565b5060009484018b0194909452509182015283525091840191908401906200078e565b9998505050505050505050565b6000806000838503610140811215620008df57600080fd5b6080811215620008ee57600080fd5b620008f862000680565b6200090386620006de565b815260208601516200091581620006fb565b602082015260408601516200092a81620006fb565b604082015260608601516200093f81620006fb565b6060820152935060a0607f19820112156200095957600080fd5b5060405160a081016001600160401b0380821183831017156200098057620009806200066a565b81604052608087015191506200099682620006fb565b818352620009a760a0880162000714565b6020840152620009ba60c0880162000714565b6040840152620009cd60e0880162000714565b60608401526101008701519150620009e582620006fb565b608083018290526101208701519294508083111562000a0357600080fd5b505062000a138682870162000729565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b600181811c9082168062000a4857607f821691505b60208210810362000a6957634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111562000abf576000816000526020600020601f850160051c8101602086101562000a9a5750805b601f850160051c820191505b8181101562000abb5782815560010162000aa6565b5050505b505050565b81516001600160401b0381111562000ae05762000ae06200066a565b62000af88162000af1845462000a33565b8462000a6f565b602080601f83116001811462000b30576000841562000b175750858301515b600019600386901b1c1916600185901b17855562000abb565b600085815260208120601f198616915b8281101562000b615788860151825594840194600190910190840162000b40565b508582101562000b805787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b602080825282546001600160a01b0381168383015260a081901c60ff161515604084015260a81c6001600160401b0316606083015260808083015260018084018054600093929190849062000be58162000a33565b8060a089015260c0600183166000811462000c09576001811462000c265762000c58565b60ff19841660c08b015260c083151560051b8b0101945062000c58565b85600052602060002060005b8481101562000c4f5781548c820185015290880190890162000c32565b8b0160c0019550505b50929998505050505050505050565b60805160a05160c05160e05161010051615f8862000cdd600039600081816102400152612a1a0152600081816102110152612f0e0152600081816101e20152818161077f01528181610986015261240c0152600081816101b201526126990152600081816117dd01526118290152615f886000f3fe608060405234801561001057600080fd5b50600436106101515760003560e01c806379ba5097116100cd578063c673e58411610081578063e9d68a8e11610066578063e9d68a8e1461052a578063f2fde38b1461054a578063f716f99f1461055d57600080fd5b8063c673e584146104c5578063ccd37ba3146104e557600080fd5b80638da5cb5b116100b25780638da5cb5b14610484578063991a50181461049f578063a80036b4146104b257600080fd5b806379ba50971461046e57806385572ffb1461047657600080fd5b80632d04ab76116101245780633f4b04aa116101095780633f4b04aa146103365780635e36480c146103525780637437ff9f1461037257600080fd5b80632d04ab7614610310578063311cd5131461032357600080fd5b806304666f9c1461015657806305d938b51461016b57806306285c691461017e578063181f5a77146102c7575b600080fd5b610169610164366004614086565b610570565b005b610169610179366004614712565b610584565b61027060408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316815250905090565b6040516102be9190815167ffffffffffffffff1681526020808301516001600160a01b0390811691830191909152604080840151821690830152606092830151169181019190915260800190565b60405180910390f35b6103036040518060400160405280601181526020017f4f666652616d7020312e362e302d64657600000000000000000000000000000081525081565b6040516102be919061488d565b61016961031e366004614938565b610729565b6101696103313660046149eb565b610cc1565b60095460405167ffffffffffffffff90911681526020016102be565b610365610360366004614a3f565b610d2a565b6040516102be9190614a9c565b6104116040805160a081018252600080825260208201819052918101829052606081018290526080810191909152506040805160a0810182526004546001600160a01b03808216835263ffffffff600160a01b83048116602085015278010000000000000000000000000000000000000000000000008304811694840194909452600160e01b9091049092166060820152600554909116608082015290565b6040516102be9190600060a0820190506001600160a01b03808451168352602084015163ffffffff808216602086015280604087015116604086015280606087015116606086015250508060808501511660808401525092915050565b610169610d80565b610169610151366004614aaa565b6000546040516001600160a01b0390911681526020016102be565b6101696104ad366004614af9565b610e3e565b6101696104c0366004614b6d565b610e4f565b6104d86104d3366004614bda565b6111c2565b6040516102be9190614c3a565b61051c6104f3366004614caf565b67ffffffffffffffff919091166000908152600860209081526040808320938352929052205490565b6040519081526020016102be565b61053d610538366004614cd9565b611320565b6040516102be9190614cf4565b610169610558366004614d42565b61142d565b61016961056b366004614dc7565b61143e565b610578611480565b610581816114dc565b50565b61058c6117da565b8151815181146105c8576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b818110156107195760008482815181106105e7576105e7614f05565b6020026020010151905060008160200151519050600085848151811061060f5761060f614f05565b6020026020010151905080518214610653576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8281101561070a57600082828151811061067257610672614f05565b6020026020010151905080600014610701578460200151828151811061069a5761069a614f05565b6020026020010151608001518110156107015784516040517fc8e9605100000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260248101839052604481018290526064015b60405180910390fd5b50600101610656565b505050508060010190506105cb565b50610724838361185b565b505050565b600061073787890189615138565b602081015151909150156107e357602081015160408083015190517f30dfc3080000000000000000000000000000000000000000000000000000000081526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016926330dfc308926107b29260040161539c565b60006040518083038186803b1580156107ca57600080fd5b505afa1580156107de573d6000803e3d6000fd5b505050505b805151511515806107f957508051602001515115155b156108f95760095460208a01359067ffffffffffffffff808316911610156108b8576009805467ffffffffffffffff191667ffffffffffffffff83161790556004805483516040517f3937306f0000000000000000000000000000000000000000000000000000000081526001600160a01b0390921692633937306f9261088192910161547e565b600060405180830381600087803b15801561089b57600080fd5b505af11580156108af573d6000803e3d6000fd5b505050506108f7565b8160200151516000036108f7576040517f2261116700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b60005b816020015151811015610c0a5760008260200151828151811061092157610921614f05565b602090810291909101015180516040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815277ffffffffffffffff00000000000000000000000000000000608083901b166004820152919250906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632cbc26bb90602401602060405180830381865afa1580156109cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109f19190615491565b15610a34576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff821660048201526024016106f8565b6000610a3f8261190b565b6020840151815491925067ffffffffffffffff908116600160a81b90920416141580610a865750826040015167ffffffffffffffff16836020015167ffffffffffffffff16115b15610ae7578251602084015160408086015190517fd5e0f0d600000000000000000000000000000000000000000000000000000000815267ffffffffffffffff938416600482015291831660248301529190911660448201526064016106f8565b606083015180610b23576040517f504570e300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b835167ffffffffffffffff16600090815260086020908152604080832084845290915290205415610b965783516040517f32cf0cbf00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602481018290526044016106f8565b6040840151610ba69060016154c4565b82547fffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffff16600160a81b67ffffffffffffffff9283160217909255925116600090815260086020908152604080832094835293905291909120429055506001016108fc565b507fd7868a16facbdde7b5c020620136316b3c266fffcb4e1e41cb6a662fe14ba3e181604051610c3a91906154ec565b60405180910390a1610cb660008a8a8a8a8a8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808e0282810182019093528d82529093508d92508c9182918501908490808284376000920191909152508b9250611972915050565b505050505050505050565b610d01610cd082840184615544565b6040805160008082526020820190925290610cfb565b6060815260200190600190039081610ce65790505b5061185b565b604080516000808252602082019092529050610d24600185858585866000611972565b50505050565b6000610d3860016004615579565b6002610d456080856155a2565b67ffffffffffffffff16610d5991906155c9565b610d638585611ce9565b901c166003811115610d7757610d77614a72565b90505b92915050565b6001546001600160a01b03163314610dda5760405162461bcd60e51b815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064016106f8565b600080543373ffffffffffffffffffffffffffffffffffffffff19808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610e46611480565b61058181611d30565b333014610e88576040517f371a732800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160008082526020820190925281610ec5565b6040805180820190915260008082526020820152815260200190600190039081610e9e5790505b5060a08501515190915015610ef957610ef68460a00151856020015186606001518760000151602001518787611e96565b90505b6040805160a0810182528551518152855160209081015167ffffffffffffffff1681830152808701518351600094840192610f3592910161488d565b60408051601f19818403018152918152908252878101516020830152018390526005549091506001600160a01b03168015611042576040517f08d450a10000000000000000000000000000000000000000000000000000000081526001600160a01b038216906308d450a190610faf908590600401615682565b600060405180830381600087803b158015610fc957600080fd5b505af1925050508015610fda575060015b611042573d808015611008576040519150601f19603f3d011682016040523d82523d6000602084013e61100d565b606091505b50806040517f09c253250000000000000000000000000000000000000000000000000000000081526004016106f8919061488d565b60408601515115801561105757506080860151155b8061106e575060608601516001600160a01b03163b155b806110ae575060608601516110ac906001600160a01b03167f85572ffb00000000000000000000000000000000000000000000000000000000611fb5565b155b156110bb57505050505050565b855160209081015167ffffffffffffffff1660009081526006909152604080822054608089015160608a015192517f3cf9798300000000000000000000000000000000000000000000000000000000815284936001600160a01b0390931692633cf97983926111339289926113889291600401615695565b6000604051808303816000875af1158015611152573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261117a91908101906156d1565b5091509150816111b857806040517f0a8d6e8c0000000000000000000000000000000000000000000000000000000081526004016106f8919061488d565b5050505050505050565b6112056040805160e081019091526000606082018181526080830182905260a0830182905260c08301919091528190815260200160608152602001606081525090565b60ff808316600090815260026020818152604092839020835160e081018552815460608201908152600183015480881660808401526101008104881660a0840152620100009004909616151560c0820152948552918201805484518184028101840190955280855292938583019390928301828280156112ae57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611290575b505050505081526020016003820180548060200260200160405190810160405280929190818152602001828054801561131057602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116112f2575b5050505050815250509050919050565b604080516080808201835260008083526020808401829052838501829052606080850181905267ffffffffffffffff878116845260068352928690208651948501875280546001600160a01b0381168652600160a01b810460ff16151593860193909352600160a81b9092049092169483019490945260018401805493949293918401916113ad90615767565b80601f01602080910402602001604051908101604052809291908181526020018280546113d990615767565b80156113105780601f106113fb57610100808354040283529160200191611310565b820191906000526020600020905b81548152906001019060200180831161140957505050919092525091949350505050565b611435611480565b61058181611fd1565b611446611480565b60005b815181101561147c5761147482828151811061146757611467614f05565b6020026020010151612087565b600101611449565b5050565b6000546001600160a01b031633146114da5760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016106f8565b565b60005b815181101561147c5760008282815181106114fc576114fc614f05565b602002602001015190506000816020015190508067ffffffffffffffff16600003611553576040517fc656089500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81516001600160a01b031661157b576040516342bcdf7f60e11b815260040160405180910390fd5b67ffffffffffffffff811660009081526006602052604081206001810180549192916115a690615767565b80601f01602080910402602001604051908101604052809291908181526020018280546115d290615767565b801561161f5780601f106115f45761010080835404028352916020019161161f565b820191906000526020600020905b81548152906001019060200180831161160257829003601f168201915b5050505050905060008460600151905081516000036116d757805160000361165a576040516342bcdf7f60e11b815260040160405180910390fd5b6001830161166882826157f1565b5082547fffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffff16600160a81b17835560405167ffffffffffffffff851681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a161172a565b808051906020012082805190602001201461172a576040517fc39a620500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff851660048201526024016106f8565b604080860151845487516001600160a01b031673ffffffffffffffffffffffffffffffffffffffff19921515600160a01b02929092167fffffffffffffffffffffff000000000000000000000000000000000000000000909116171784555167ffffffffffffffff8516907f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b906117c29086906158b1565b60405180910390a250505050508060010190506114df565b467f0000000000000000000000000000000000000000000000000000000000000000146114da576040517f0f01ce850000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060048201524660248201526044016106f8565b8151600003611895576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160408051600080825260208201909252911591905b8451811015611904576118fc8582815181106118ca576118ca614f05565b6020026020010151846118f6578583815181106118e9576118e9614f05565b60200260200101516123b8565b836123b8565b6001016118ac565b5050505050565b67ffffffffffffffff811660009081526006602052604081208054600160a01b900460ff16610d7a576040517fed053c5900000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024016106f8565b60ff878116600090815260026020908152604080832081516080810183528154815260019091015480861693820193909352610100830485169181019190915262010000909104909216151560608301528735906119d18760a461597f565b9050826060015115611a195784516119ea9060206155c9565b86516119f79060206155c9565b611a029060a061597f565b611a0c919061597f565b611a16908261597f565b90505b368114611a5b576040517f8e1192e1000000000000000000000000000000000000000000000000000000008152600481018290523660248201526044016106f8565b5081518114611aa35781516040517f93df584c0000000000000000000000000000000000000000000000000000000081526004810191909152602481018290526044016106f8565b611aab6117da565b60ff808a1660009081526003602090815260408083203384528252808320815180830190925280548086168352939491939092840191610100909104166002811115611af957611af9614a72565b6002811115611b0a57611b0a614a72565b9052509050600281602001516002811115611b2757611b27614a72565b148015611b7b5750600260008b60ff1660ff168152602001908152602001600020600301816000015160ff1681548110611b6357611b63614f05565b6000918252602090912001546001600160a01b031633145b611bb1576040517fda0f08e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50816060015115611c93576020820151611bcc906001615992565b60ff16855114611c08576040517f71253a2500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8351855114611c43576040517fa75d88af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008787604051611c559291906159ab565b604051908190038120611c6c918b906020016159bb565b604051602081830303815290604052805190602001209050611c918a82888888612cc8565b505b6040805182815260208a81013567ffffffffffffffff169082015260ff8b16917f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef0910160405180910390a2505050505050505050565b67ffffffffffffffff8216600090815260076020526040812081611d0e6080856159cf565b67ffffffffffffffff1681526020810191909152604001600020549392505050565b80516001600160a01b0316611d58576040516342bcdf7f60e11b815260040160405180910390fd5b80516004805460208085018051604080880180516060808b0180516001600160a01b039b8c167fffffffffffffffff000000000000000000000000000000000000000000000000909a168a17600160a01b63ffffffff988916021777ffffffffffffffffffffffffffffffffffffffffffffffff167801000000000000000000000000000000000000000000000000948816949094026001600160e01b031693909317600160e01b93871693909302929092179098556080808b0180516005805473ffffffffffffffffffffffffffffffffffffffff1916918d169190911790558451988952955185169688019690965290518316918601919091525116938301939093529151909216908201527fa55bd56595c45f517e5967a3067f3dca684445a3080e7c04a4e0d5a40cda627d9060a00160405180910390a150565b6060865167ffffffffffffffff811115611eb257611eb2613e9d565b604051908082528060200260200182016040528015611ef757816020015b6040805180820190915260008082526020820152815260200190600190039081611ed05790505b50905060005b8751811015611fa957611f84888281518110611f1b57611f1b614f05565b6020026020010151888888888887818110611f3857611f38614f05565b9050602002810190611f4a91906159f6565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612ead92505050565b828281518110611f9657611f96614f05565b6020908102919091010152600101611efd565b505b9695505050505050565b6000611fc083613252565b8015610d775750610d7783836132b6565b336001600160a01b038216036120295760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016106f8565b6001805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b806040015160ff166000036120b2576000604051631b3fab5160e11b81526004016106f89190615a5b565b60208082015160ff8082166000908152600290935260408320600181015492939092839216900361211f57606084015160018201805491151562010000027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff909216919091179055612174565b6060840151600182015460ff6201000090910416151590151514612174576040517f87f6037c00000000000000000000000000000000000000000000000000000000815260ff841660048201526024016106f8565b60a0840151805161010010156121a0576001604051631b3fab5160e11b81526004016106f89190615a5b565b61220684846003018054806020026020016040519081016040528092919081815260200182805480156121fc57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116121de575b5050505050613371565b84606001511561232d5761227484846002018054806020026020016040519081016040528092919081815260200182805480156121fc576020028201919060005260206000209081546001600160a01b031681526001909101906020018083116121de575050505050613371565b6080850151805161010010156122a0576002604051631b3fab5160e11b81526004016106f89190615a5b565b60408601516122b0906003615a75565b60ff168151116122d6576003604051631b3fab5160e11b81526004016106f89190615a5b565b80516001840180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1661010060ff84160217905561231e9060028601906020840190613e16565b5061232b858260016133da565b505b612339848260026133da565b805161234e9060038501906020840190613e16565b5060408581015160018401805460ff191660ff8316179055865180855560a088015192517fab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f547936123a79389939260028a01929190615a91565b60405180910390a16119048461354e565b815181516040517f2cbc26bb000000000000000000000000000000000000000000000000000000008152608083901b77ffffffffffffffff00000000000000000000000000000000166004820152901515907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632cbc26bb90602401602060405180830381865afa15801561245b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061247f9190615491565b1561250b5780156124c8576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff831660048201526024016106f8565b60405167ffffffffffffffff831681527faab522ed53d887e56ed53dd37398a01aeef6a58e0fa77c2173beb9512d8949339060200160405180910390a150505050565b60006125168361190b565b600101805461252490615767565b80601f016020809104026020016040519081016040528092919081815260200182805461255090615767565b801561259d5780601f106125725761010080835404028352916020019161259d565b820191906000526020600020905b81548152906001019060200180831161258057829003601f168201915b505050602088015151929350505060008190036125e5576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8560400151518114612623576040517f57e0e08300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008167ffffffffffffffff81111561263e5761263e613e9d565b604051908082528060200260200182016040528015612667578160200160208202803683370190505b50905060005b828110156127505760008860200151828151811061268d5761268d614f05565b602002602001015190507f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681600001516040015167ffffffffffffffff161461272057805160409081015190517f38432a2200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016106f8565b61272a818661356a565b83838151811061273c5761273c614f05565b60209081029190910101525060010161266d565b50600061276786838a606001518b6080015161368c565b9050806000036127af576040517f7dd17a7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff871660048201526024016106f8565b60005b83811015610cb65760005a905060008a6020015183815181106127d7576127d7614f05565b6020026020010151905060006127f58a836000015160600151610d2a565b9050600081600381111561280b5761280b614a72565b14806128285750600381600381111561282657612826614a72565b145b612880578151606001516040805167ffffffffffffffff808e16825290921660208301527f3b575419319662b2a6f5e2467d84521517a3382b908eb3d557bb3fdb0c50e23c91015b60405180910390a1505050612cc0565b881561295057600454600090600160a01b900463ffffffff166128a38742615579565b11905080806128c3575060038260038111156128c1576128c1614a72565b145b612905576040517fa9cfc86200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8c1660048201526024016106f8565b8b858151811061291757612917614f05565b602002602001015160001461294a578b858151811061293857612938614f05565b60200260200101518360800181815250505b506129b1565b600081600381111561296457612964614a72565b146129b1578151606001516040805167ffffffffffffffff808e16825290921660208301527f3ef2a99c550a751d4b0b261268f05a803dfb049ab43616a1ffb388f61fe651209101612870565b81516080015167ffffffffffffffff1615612aa05760008160038111156129da576129da614a72565b03612aa05781516080015160208301516040517fe0e03cae0000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169263e0e03cae92612a51928f929190600401615b3d565b6020604051808303816000875af1158015612a70573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a949190615491565b612aa057505050612cc0565b60008c604001518581518110612ab857612ab8614f05565b6020026020010151905080518360a001515114612b1c578251606001516040517f1cfe6d8b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808e16600483015290911660248201526044016106f8565b612b308b84600001516060015160016136ca565b600080612b3d8584613772565b91509150612b548d866000015160600151846136ca565b8b15612bc4576003826003811115612b6e57612b6e614a72565b03612bc4576000846003811115612b8757612b87614a72565b14612bc4578451516040517f2b11b8d90000000000000000000000000000000000000000000000000000000081526106f891908390600401615b6a565b6002826003811115612bd857612bd8614a72565b14612c32576003826003811115612bf157612bf1614a72565b14612c32578451606001516040517f926c5a3e0000000000000000000000000000000000000000000000000000000081526106f8918f918590600401615b83565b84600001516000015185600001516060015167ffffffffffffffff168e67ffffffffffffffff167f05665fe9ad095383d018353f4cbcba77e84db27dd215081bbf7cdf9ae6fbe48b8c8b81518110612c8c57612c8c614f05565b602002602001015186865a612ca1908e615579565b604051612cb19493929190615ba9565b60405180910390a45050505050505b6001016127b2565b8251600090815b818110156111b8576000600188868460208110612cee57612cee614f05565b612cfb91901a601b615992565b898581518110612d0d57612d0d614f05565b6020026020010151898681518110612d2757612d27614f05565b602002602001015160405160008152602001604052604051612d65949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015612d87573d6000803e3d6000fd5b505060408051601f1981015160ff808e166000908152600360209081528582206001600160a01b03851683528152858220858701909652855480841686529397509095509293928401916101009004166002811115612de857612de8614a72565b6002811115612df957612df9614a72565b9052509050600181602001516002811115612e1657612e16614a72565b14612e4d576040517fca31867a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051600160ff9091161b851615612e90576040517ff67bc7c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806000015160ff166001901b851794505050806001019050612ccf565b60408051808201909152600080825260208201526000612ed0876020015161383c565b6040517fbbe4f6db0000000000000000000000000000000000000000000000000000000081526001600160a01b0380831660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063bbe4f6db90602401602060405180830381865afa158015612f55573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f799190615be0565b90506001600160a01b0381161580612fc15750612fbf6001600160a01b0382167faff2afbf00000000000000000000000000000000000000000000000000000000611fb5565b155b15613003576040517fae9b4ce90000000000000000000000000000000000000000000000000000000081526001600160a01b03821660048201526024016106f8565b60045460009081906130259089908690600160e01b900463ffffffff166138e2565b9150915060008060006130f26040518061010001604052808e81526020018c67ffffffffffffffff1681526020018d6001600160a01b031681526020018f606001518152602001896001600160a01b031681526020018f6000015181526020018f6040015181526020018b8152506040516024016130a39190615bfd565b60408051601f198184030181529190526020810180516001600160e01b03167f390775370000000000000000000000000000000000000000000000000000000017905287866113886084613a10565b9250925092508261313157816040517fe1cd55090000000000000000000000000000000000000000000000000000000081526004016106f8919061488d565b81516020146131795781516040517f78ef80240000000000000000000000000000000000000000000000000000000081526020600482015260248101919091526044016106f8565b60008280602001905181019061318f9190615cca565b9050866001600160a01b03168c6001600160a01b0316146132245760006131c08d8a6131bb868a615579565b6138e2565b509050868110806131da5750816131d78883615579565b14155b15613222576040517fa966e21f0000000000000000000000000000000000000000000000000000000081526004810183905260248101889052604481018290526064016106f8565b505b604080518082019091526001600160a01b039098168852602088015250949550505050505095945050505050565b600061327e827f01ffc9a7000000000000000000000000000000000000000000000000000000006132b6565b8015610d7a57506132af827fffffffff000000000000000000000000000000000000000000000000000000006132b6565b1592915050565b6040517fffffffff0000000000000000000000000000000000000000000000000000000082166024820152600090819060440160408051601f19818403018152919052602080820180516001600160e01b03167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825192935060009283928392909183918a617530fa92503d9150600051905082801561335a575060208210155b80156133665750600081115b979650505050505050565b60005b81518110156107245760ff8316600090815260036020526040812083519091908490849081106133a6576133a6614f05565b6020908102919091018101516001600160a01b03168252810191909152604001600020805461ffff19169055600101613374565b60005b8251811015610d245760008382815181106133fa576133fa614f05565b602002602001015190506000600281111561341757613417614a72565b60ff80871660009081526003602090815260408083206001600160a01b0387168452909152902054610100900416600281111561345657613456614a72565b14613477576004604051631b3fab5160e11b81526004016106f89190615a5b565b6001600160a01b0381166134b7576040517fd6c62c9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052808360ff1681526020018460028111156134dd576134dd614a72565b905260ff80871660009081526003602090815260408083206001600160a01b0387168452825290912083518154931660ff198416811782559184015190929091839161ffff19161761010083600281111561353a5761353a614a72565b0217905550905050508060010190506133dd565b60ff8116610581576009805467ffffffffffffffff1916905550565b8151602080820151604092830151925160009384936135b0937f2425b0b9f9054c76ff151b0a175b18f37a4a4e82013a72e9f15c9caa095ed21f93909291889101615ce3565b60408051601f1981840301815290829052805160209182012086518051888401516060808b0151908401516080808d015195015195976135f99794969395929491939101615d16565b604051602081830303815290604052805190602001208560400151805190602001208660a001516040516020016136309190615e1b565b60408051601f198184030181528282528051602091820120908301969096528101939093526060830191909152608082015260a081019190915260c0015b60405160208183030381529060405280519060200120905092915050565b60008061369a858585613b36565b67ffffffffffffffff8716600090815260086020908152604080832093835292905220549150505b949350505050565b600060026136d96080856155a2565b67ffffffffffffffff166136ed91906155c9565b905060006136fb8585611ce9565b90508161370a60016004615579565b901b19168183600381111561372157613721614a72565b67ffffffffffffffff871660009081526007602052604081209190921b929092179182916137506080886159cf565b67ffffffffffffffff1681526020810191909152604001600020555050505050565b6040517fa80036b4000000000000000000000000000000000000000000000000000000008152600090606090309063a80036b4906137b69087908790600401615e7b565b600060405180830381600087803b1580156137d057600080fd5b505af19250505080156137e1575060015b613820573d80801561380f576040519150601f19603f3d011682016040523d82523d6000602084013e613814565b606091505b50600392509050613835565b50506040805160208101909152600081526002905b9250929050565b6000815160201461387b57816040517f8d666f600000000000000000000000000000000000000000000000000000000081526004016106f8919061488d565b6000828060200190518101906138919190615cca565b90506001600160a01b038111806138a9575061040081105b15610d7a57826040517f8d666f600000000000000000000000000000000000000000000000000000000081526004016106f8919061488d565b600080600080600061395c8860405160240161390d91906001600160a01b0391909116815260200190565b60408051601f198184030181529190526020810180516001600160e01b03167f70a082310000000000000000000000000000000000000000000000000000000017905288886113886084613a10565b9250925092508261399b57816040517fe1cd55090000000000000000000000000000000000000000000000000000000081526004016106f8919061488d565b60208251146139e35781516040517f78ef80240000000000000000000000000000000000000000000000000000000081526020600482015260248101919091526044016106f8565b818060200190518101906139f79190615cca565b613a018288615579565b94509450505050935093915050565b6000606060008361ffff1667ffffffffffffffff811115613a3357613a33613e9d565b6040519080825280601f01601f191660200182016040528015613a5d576020820181803683370190505b509150863b613a90577f0c3b563c0000000000000000000000000000000000000000000000000000000060005260046000fd5b5a85811015613ac3577fafa32a2c0000000000000000000000000000000000000000000000000000000060005260046000fd5b8590036040810481038710613afc577f37c3be290000000000000000000000000000000000000000000000000000000060005260046000fd5b505a6000808a5160208c0160008c8cf193505a900390503d84811115613b1f5750835b808352806000602085013e50955095509592505050565b8251825160009190818303613b77576040517f11a6b26400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6101018211801590613b8b57506101018111155b613ba8576040516309bde33960e01b815260040160405180910390fd5b60001982820101610100811115613bd2576040516309bde33960e01b815260040160405180910390fd5b80600003613bff5786600081518110613bed57613bed614f05565b60200260200101519350505050613dce565b60008167ffffffffffffffff811115613c1a57613c1a613e9d565b604051908082528060200260200182016040528015613c43578160200160208202803683370190505b50905060008080805b85811015613d6d5760006001821b8b811603613ca75788851015613c90578c5160018601958e918110613c8157613c81614f05565b60200260200101519050613cc9565b8551600185019487918110613c8157613c81614f05565b8b5160018401938d918110613cbe57613cbe614f05565b602002602001015190505b600089861015613cf9578d5160018701968f918110613cea57613cea614f05565b60200260200101519050613d1b565b8651600186019588918110613d1057613d10614f05565b602002602001015190505b82851115613d3c576040516309bde33960e01b815260040160405180910390fd5b613d468282613dd5565b878481518110613d5857613d58614f05565b60209081029190910101525050600101613c4c565b506001850382148015613d7f57508683145b8015613d8a57508581145b613da7576040516309bde33960e01b815260040160405180910390fd5b836001860381518110613dbc57613dbc614f05565b60200260200101519750505050505050505b9392505050565b6000818310613ded57613de88284613df3565b610d77565b610d7783835b60408051600160208201529081018390526060810182905260009060800161366e565b828054828255906000526020600020908101928215613e78579160200282015b82811115613e78578251825473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03909116178255602090920191600190910190613e36565b50613e84929150613e88565b5090565b5b80821115613e845760008155600101613e89565b634e487b7160e01b600052604160045260246000fd5b6040516080810167ffffffffffffffff81118282101715613ed657613ed6613e9d565b60405290565b60405160a0810167ffffffffffffffff81118282101715613ed657613ed6613e9d565b60405160c0810167ffffffffffffffff81118282101715613ed657613ed6613e9d565b6040805190810167ffffffffffffffff81118282101715613ed657613ed6613e9d565b6040516060810167ffffffffffffffff81118282101715613ed657613ed6613e9d565b604051601f8201601f1916810167ffffffffffffffff81118282101715613f9157613f91613e9d565b604052919050565b600067ffffffffffffffff821115613fb357613fb3613e9d565b5060051b60200190565b6001600160a01b038116811461058157600080fd5b803567ffffffffffffffff81168114613fea57600080fd5b919050565b801515811461058157600080fd5b8035613fea81613fef565b600067ffffffffffffffff82111561402257614022613e9d565b50601f01601f191660200190565b600082601f83011261404157600080fd5b813561405461404f82614008565b613f68565b81815284602083860101111561406957600080fd5b816020850160208301376000918101602001919091529392505050565b6000602080838503121561409957600080fd5b823567ffffffffffffffff808211156140b157600080fd5b818501915085601f8301126140c557600080fd5b81356140d361404f82613f99565b81815260059190911b830184019084810190888311156140f257600080fd5b8585015b838110156141985780358581111561410e5760008081fd5b86016080818c03601f19018113156141265760008081fd5b61412e613eb3565b8983013561413b81613fbd565b8152604061414a848201613fd2565b8b83015260608085013561415d81613fef565b8383015292840135928984111561417657600091508182fd5b6141848f8d86880101614030565b9083015250855250509186019186016140f6565b5098975050505050505050565b600060a082840312156141b757600080fd5b6141bf613edc565b9050813581526141d160208301613fd2565b60208201526141e260408301613fd2565b60408201526141f360608301613fd2565b606082015261420460808301613fd2565b608082015292915050565b8035613fea81613fbd565b600082601f83011261422b57600080fd5b8135602061423b61404f83613f99565b82815260059290921b8401810191818101908684111561425a57600080fd5b8286015b84811015611fa957803567ffffffffffffffff8082111561427f5760008081fd5b818901915060a080601f19848d0301121561429a5760008081fd5b6142a2613edc565b87840135838111156142b45760008081fd5b6142c28d8a83880101614030565b825250604080850135848111156142d95760008081fd5b6142e78e8b83890101614030565b8a84015250606080860135858111156143005760008081fd5b61430e8f8c838a0101614030565b838501525060809150818601358184015250828501359250838311156143345760008081fd5b6143428d8a85880101614030565b90820152865250505091830191830161425e565b6000610140828403121561436957600080fd5b614371613eff565b905061437d83836141a5565b815260a082013567ffffffffffffffff8082111561439a57600080fd5b6143a685838601614030565b602084015260c08401359150808211156143bf57600080fd5b6143cb85838601614030565b60408401526143dc60e0850161420f565b6060840152610100840135608084015261012084013591508082111561440157600080fd5b5061440e8482850161421a565b60a08301525092915050565b600082601f83011261442b57600080fd5b8135602061443b61404f83613f99565b82815260059290921b8401810191818101908684111561445a57600080fd5b8286015b84811015611fa957803567ffffffffffffffff81111561447e5760008081fd5b61448c8986838b0101614356565b84525091830191830161445e565b600082601f8301126144ab57600080fd5b813560206144bb61404f83613f99565b82815260059290921b840181019181810190868411156144da57600080fd5b8286015b84811015611fa957803567ffffffffffffffff808211156144fe57600080fd5b818901915089603f83011261451257600080fd5b8582013561452261404f82613f99565b81815260059190911b830160400190878101908c83111561454257600080fd5b604085015b8381101561457b5780358581111561455e57600080fd5b61456d8f6040838a0101614030565b845250918901918901614547565b508752505050928401925083016144de565b600082601f83011261459e57600080fd5b813560206145ae61404f83613f99565b8083825260208201915060208460051b8701019350868411156145d057600080fd5b602086015b84811015611fa957803583529183019183016145d5565b600082601f8301126145fd57600080fd5b8135602061460d61404f83613f99565b82815260059290921b8401810191818101908684111561462c57600080fd5b8286015b84811015611fa957803567ffffffffffffffff808211156146515760008081fd5b818901915060a080601f19848d0301121561466c5760008081fd5b614674613edc565b61467f888501613fd2565b8152604080850135848111156146955760008081fd5b6146a38e8b8389010161441a565b8a84015250606080860135858111156146bc5760008081fd5b6146ca8f8c838a010161449a565b83850152506080915081860135858111156146e55760008081fd5b6146f38f8c838a010161458d565b9184019190915250919093013590830152508352918301918301614630565b600080604080848603121561472657600080fd5b833567ffffffffffffffff8082111561473e57600080fd5b61474a878388016145ec565b945060209150818601358181111561476157600080fd5b8601601f8101881361477257600080fd5b803561478061404f82613f99565b81815260059190911b8201840190848101908a83111561479f57600080fd5b8584015b8381101561482b578035868111156147bb5760008081fd5b8501603f81018d136147cd5760008081fd5b878101356147dd61404f82613f99565b81815260059190911b82018a0190898101908f8311156147fd5760008081fd5b928b01925b8284101561481b5783358252928a0192908a0190614802565b86525050509186019186016147a3565b50809750505050505050509250929050565b60005b83811015614858578181015183820152602001614840565b50506000910152565b6000815180845261487981602086016020860161483d565b601f01601f19169290920160200192915050565b602081526000610d776020830184614861565b8060608101831015610d7a57600080fd5b60008083601f8401126148c357600080fd5b50813567ffffffffffffffff8111156148db57600080fd5b60208301915083602082850101111561383557600080fd5b60008083601f84011261490557600080fd5b50813567ffffffffffffffff81111561491d57600080fd5b6020830191508360208260051b850101111561383557600080fd5b60008060008060008060008060e0898b03121561495457600080fd5b61495e8a8a6148a0565b9750606089013567ffffffffffffffff8082111561497b57600080fd5b6149878c838d016148b1565b909950975060808b01359150808211156149a057600080fd5b6149ac8c838d016148f3565b909750955060a08b01359150808211156149c557600080fd5b506149d28b828c016148f3565b999c989b50969995989497949560c00135949350505050565b600080600060808486031215614a0057600080fd5b614a0a85856148a0565b9250606084013567ffffffffffffffff811115614a2657600080fd5b614a32868287016148b1565b9497909650939450505050565b60008060408385031215614a5257600080fd5b614a5b83613fd2565b9150614a6960208401613fd2565b90509250929050565b634e487b7160e01b600052602160045260246000fd5b60048110614a9857614a98614a72565b9052565b60208101610d7a8284614a88565b600060208284031215614abc57600080fd5b813567ffffffffffffffff811115614ad357600080fd5b820160a08185031215613dce57600080fd5b803563ffffffff81168114613fea57600080fd5b600060a08284031215614b0b57600080fd5b614b13613edc565b8235614b1e81613fbd565b8152614b2c60208401614ae5565b6020820152614b3d60408401614ae5565b6040820152614b4e60608401614ae5565b60608201526080830135614b6181613fbd565b60808201529392505050565b600080600060408486031215614b8257600080fd5b833567ffffffffffffffff80821115614b9a57600080fd5b614ba687838801614356565b94506020860135915080821115614bbc57600080fd5b50614a32868287016148f3565b803560ff81168114613fea57600080fd5b600060208284031215614bec57600080fd5b610d7782614bc9565b60008151808452602080850194506020840160005b83811015614c2f5781516001600160a01b031687529582019590820190600101614c0a565b509495945050505050565b60208152600082518051602084015260ff602082015116604084015260ff604082015116606084015260608101511515608084015250602083015160c060a0840152614c8960e0840182614bf5565b90506040840151601f198483030160c0850152614ca68282614bf5565b95945050505050565b60008060408385031215614cc257600080fd5b614ccb83613fd2565b946020939093013593505050565b600060208284031215614ceb57600080fd5b610d7782613fd2565b602081526001600160a01b03825116602082015260208201511515604082015267ffffffffffffffff6040830151166060820152600060608301516080808401526136c260a0840182614861565b600060208284031215614d5457600080fd5b8135613dce81613fbd565b600082601f830112614d7057600080fd5b81356020614d8061404f83613f99565b8083825260208201915060208460051b870101935086841115614da257600080fd5b602086015b84811015611fa9578035614dba81613fbd565b8352918301918301614da7565b60006020808385031215614dda57600080fd5b823567ffffffffffffffff80821115614df257600080fd5b818501915085601f830112614e0657600080fd5b8135614e1461404f82613f99565b81815260059190911b83018401908481019088831115614e3357600080fd5b8585015b8381101561419857803585811115614e4e57600080fd5b860160c0818c03601f19011215614e655760008081fd5b614e6d613eff565b8882013581526040614e80818401614bc9565b8a8301526060614e91818501614bc9565b8284015260809150614ea4828501613ffd565b9083015260a08381013589811115614ebc5760008081fd5b614eca8f8d83880101614d5f565b838501525060c0840135915088821115614ee45760008081fd5b614ef28e8c84870101614d5f565b9083015250845250918601918601614e37565b634e487b7160e01b600052603260045260246000fd5b80356001600160e01b0381168114613fea57600080fd5b600082601f830112614f4357600080fd5b81356020614f5361404f83613f99565b82815260069290921b84018101918181019086841115614f7257600080fd5b8286015b84811015611fa95760408189031215614f8f5760008081fd5b614f97613f22565b614fa082613fd2565b8152614fad858301614f1b565b81860152835291830191604001614f76565b600082601f830112614fd057600080fd5b81356020614fe061404f83613f99565b82815260059290921b84018101918181019086841115614fff57600080fd5b8286015b84811015611fa957803567ffffffffffffffff808211156150245760008081fd5b818901915060a080601f19848d0301121561503f5760008081fd5b615047613edc565b615052888501613fd2565b81526040615061818601613fd2565b898301526060615072818701613fd2565b8284015260809150818601358184015250828501359250838311156150975760008081fd5b6150a58d8a85880101614030565b908201528652505050918301918301615003565b600082601f8301126150ca57600080fd5b813560206150da61404f83613f99565b82815260069290921b840181019181810190868411156150f957600080fd5b8286015b84811015611fa957604081890312156151165760008081fd5b61511e613f22565b8135815284820135858201528352918301916040016150fd565b6000602080838503121561514b57600080fd5b823567ffffffffffffffff8082111561516357600080fd5b908401906060828703121561517757600080fd5b61517f613f45565b82358281111561518e57600080fd5b830160408189038113156151a157600080fd5b6151a9613f22565b8235858111156151b857600080fd5b8301601f81018b136151c957600080fd5b80356151d761404f82613f99565b81815260069190911b8201890190898101908d8311156151f657600080fd5b928a01925b828410156152465785848f0312156152135760008081fd5b61521b613f22565b843561522681613fbd565b8152615233858d01614f1b565b818d0152825292850192908a01906151fb565b84525050508287013591508482111561525e57600080fd5b61526a8a838501614f32565b8188015283525050828401358281111561528357600080fd5b61528f88828601614fbf565b858301525060408301359350818411156152a857600080fd5b6152b4878585016150b9565b60408201529695505050505050565b600082825180855260208086019550808260051b84010181860160005b8481101561535357858303601f190189528151805167ffffffffffffffff908116855285820151811686860152604080830151909116908501526060808201519085015260809081015160a09185018290529061533f81860183614861565b9a86019a94505050908301906001016152e0565b5090979650505050505050565b60008151808452602080850194506020840160005b83811015614c2f578151805188528301518388015260409096019590820190600101615375565b6040815260006153af60408301856152c3565b8281036020840152614ca68185615360565b805160408084528151848201819052600092602091908201906060870190855b8181101561541857835180516001600160a01b031684528501516001600160e01b03168584015292840192918501916001016153e1565b50508583015187820388850152805180835290840192506000918401905b80831015615472578351805167ffffffffffffffff1683528501516001600160e01b031685830152928401926001929092019190850190615436565b50979650505050505050565b602081526000610d7760208301846153c1565b6000602082840312156154a357600080fd5b8151613dce81613fef565b634e487b7160e01b600052601160045260246000fd5b67ffffffffffffffff8181168382160190808211156154e5576154e56154ae565b5092915050565b60208152600082516060602084015261550860808401826153c1565b90506020840151601f198085840301604086015261552683836152c3565b9250604086015191508085840301606086015250614ca68282615360565b60006020828403121561555657600080fd5b813567ffffffffffffffff81111561556d57600080fd5b6136c2848285016145ec565b81810381811115610d7a57610d7a6154ae565b634e487b7160e01b600052601260045260246000fd5b600067ffffffffffffffff808416806155bd576155bd61558c565b92169190910692915050565b8082028115828204841417610d7a57610d7a6154ae565b805182526000602067ffffffffffffffff81840151168185015260408084015160a0604087015261561460a0870182614861565b90506060850151868203606088015261562d8282614861565b608087810151898303918a01919091528051808352908601935060009250908501905b8083101561547257835180516001600160a01b0316835286015186830152928501926001929092019190840190615650565b602081526000610d7760208301846155e0565b6080815260006156a860808301876155e0565b61ffff9590951660208301525060408101929092526001600160a01b0316606090910152919050565b6000806000606084860312156156e657600080fd5b83516156f181613fef565b602085015190935067ffffffffffffffff81111561570e57600080fd5b8401601f8101861361571f57600080fd5b805161572d61404f82614008565b81815287602083850101111561574257600080fd5b61575382602083016020860161483d565b809450505050604084015190509250925092565b600181811c9082168061577b57607f821691505b60208210810361579b57634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115610724576000816000526020600020601f850160051c810160208610156157ca5750805b601f850160051c820191505b818110156157e9578281556001016157d6565b505050505050565b815167ffffffffffffffff81111561580b5761580b613e9d565b61581f816158198454615767565b846157a1565b602080601f831160018114615854576000841561583c5750858301515b600019600386901b1c1916600185901b1785556157e9565b600085815260208120601f198616915b8281101561588357888601518255948401946001909101908401615864565b50858210156158a15787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6000602080835283546001600160a01b038116602085015260ff8160a01c161515604085015267ffffffffffffffff8160a81c1660608501525060018085016080808601526000815461590381615767565b8060a089015260c06001831660008114615924576001811461594057615970565b60ff19841660c08b015260c083151560051b8b01019450615970565b85600052602060002060005b848110156159675781548c820185015290880190890161594c565b8b0160c0019550505b50929998505050505050505050565b80820180821115610d7a57610d7a6154ae565b60ff8181168382160190811115610d7a57610d7a6154ae565b8183823760009101908152919050565b828152606082602083013760800192915050565b600067ffffffffffffffff808416806159ea576159ea61558c565b92169190910492915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112615a2b57600080fd5b83018035915067ffffffffffffffff821115615a4657600080fd5b60200191503681900382131561383557600080fd5b6020810160058310615a6f57615a6f614a72565b91905290565b60ff81811683821602908116908181146154e5576154e56154ae565b600060a0820160ff881683526020878185015260a0604085015281875480845260c0860191508860005282600020935060005b81811015615ae95784546001600160a01b031683526001948501949284019201615ac4565b50508481036060860152865180825290820192508187019060005b81811015615b295782516001600160a01b031685529383019391830191600101615b04565b50505060ff85166080850152509050611fab565b600067ffffffffffffffff808616835280851660208401525060606040830152614ca66060830184614861565b8281526040602082015260006136c26040830184614861565b67ffffffffffffffff848116825283166020820152606081016136c26040830184614a88565b848152615bb96020820185614a88565b608060408201526000615bcf6080830185614861565b905082606083015295945050505050565b600060208284031215615bf257600080fd5b8151613dce81613fbd565b6020815260008251610100806020850152615c1c610120850183614861565b91506020850151615c39604086018267ffffffffffffffff169052565b5060408501516001600160a01b038116606086015250606085015160808501526080850151615c7360a08601826001600160a01b03169052565b5060a0850151601f19808685030160c0870152615c908483614861565b935060c08701519150808685030160e0870152615cad8483614861565b935060e0870151915080868503018387015250611fab8382614861565b600060208284031215615cdc57600080fd5b5051919050565b848152600067ffffffffffffffff808616602084015280851660408401525060806060830152611fab6080830184614861565b86815260c060208201526000615d2f60c0830188614861565b6001600160a01b039690961660408301525067ffffffffffffffff9384166060820152608081019290925290911660a09091015292915050565b600082825180855260208086019550808260051b84010181860160005b8481101561535357601f19868403018952815160a08151818652615dac82870182614861565b9150508582015185820387870152615dc48282614861565b91505060408083015186830382880152615dde8382614861565b92505050606080830151818701525060808083015192508582038187015250615e078183614861565b9a86019a9450505090830190600101615d86565b602081526000610d776020830184615d69565b60008282518085526020808601955060208260051b8401016020860160005b8481101561535357601f19868403018952615e69838351614861565b98840198925090830190600101615e4d565b604081526000835180516040840152602081015167ffffffffffffffff80821660608601528060408401511660808601528060608401511660a08601528060808401511660c086015250505060208401516101408060e0850152615ee3610180850183614861565b915060408601517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08086850301610100870152615f208483614861565b935060608801519150615f3f6101208701836001600160a01b03169052565b60808801518387015260a0880151925080868503016101608701525050615f668282615d69565b9150508281036020840152614ca68185615e2e56fea164736f6c6343000818000a", } var OffRampABI = OffRampMetaData.ABI @@ -456,28 +454,6 @@ func (_OffRamp *OffRampCallerSession) GetStaticConfig() (OffRampStaticConfig, er return _OffRamp.Contract.GetStaticConfig(&_OffRamp.CallOpts) } -func (_OffRamp *OffRampCaller) IsBlessed(opts *bind.CallOpts, root [32]byte) (bool, error) { - var out []interface{} - err := _OffRamp.contract.Call(opts, &out, "isBlessed", root) - - if err != nil { - return *new(bool), err - } - - out0 := *abi.ConvertType(out[0], new(bool)).(*bool) - - return out0, err - -} - -func (_OffRamp *OffRampSession) IsBlessed(root [32]byte) (bool, error) { - return _OffRamp.Contract.IsBlessed(&_OffRamp.CallOpts, root) -} - -func (_OffRamp *OffRampCallerSession) IsBlessed(root [32]byte) (bool, error) { - return _OffRamp.Contract.IsBlessed(&_OffRamp.CallOpts, root) -} - func (_OffRamp *OffRampCaller) LatestConfigDetails(opts *bind.CallOpts, ocrPluginType uint8) (MultiOCR3BaseOCRConfig, error) { var out []interface{} err := _OffRamp.contract.Call(opts, &out, "latestConfigDetails", ocrPluginType) @@ -616,18 +592,6 @@ func (_OffRamp *OffRampTransactorSession) ManuallyExecute(reports []InternalExec return _OffRamp.Contract.ManuallyExecute(&_OffRamp.TransactOpts, reports, gasLimitOverrides) } -func (_OffRamp *OffRampTransactor) ResetUnblessedRoots(opts *bind.TransactOpts, rootToReset []OffRampUnblessedRoot) (*types.Transaction, error) { - return _OffRamp.contract.Transact(opts, "resetUnblessedRoots", rootToReset) -} - -func (_OffRamp *OffRampSession) ResetUnblessedRoots(rootToReset []OffRampUnblessedRoot) (*types.Transaction, error) { - return _OffRamp.Contract.ResetUnblessedRoots(&_OffRamp.TransactOpts, rootToReset) -} - -func (_OffRamp *OffRampTransactorSession) ResetUnblessedRoots(rootToReset []OffRampUnblessedRoot) (*types.Transaction, error) { - return _OffRamp.Contract.ResetUnblessedRoots(&_OffRamp.TransactOpts, rootToReset) -} - func (_OffRamp *OffRampTransactor) SetDynamicConfig(opts *bind.TransactOpts, dynamicConfig OffRampDynamicConfig) (*types.Transaction, error) { return _OffRamp.contract.Transact(opts, "setDynamicConfig", dynamicConfig) } @@ -2442,7 +2406,7 @@ func (OffRampAlreadyAttempted) Topic() common.Hash { } func (OffRampCommitReportAccepted) Topic() common.Hash { - return common.HexToHash("0x3a3950e13dd607cc37980db0ef14266c40d2bba9c01b2e44bfe549808883095d") + return common.HexToHash("0xd7868a16facbdde7b5c020620136316b3c266fffcb4e1e41cb6a662fe14ba3e1") } func (OffRampConfigSet) Topic() common.Hash { @@ -2512,8 +2476,6 @@ type OffRampInterface interface { GetStaticConfig(opts *bind.CallOpts) (OffRampStaticConfig, error) - IsBlessed(opts *bind.CallOpts, root [32]byte) (bool, error) - LatestConfigDetails(opts *bind.CallOpts, ocrPluginType uint8) (MultiOCR3BaseOCRConfig, error) Owner(opts *bind.CallOpts) (common.Address, error) @@ -2532,8 +2494,6 @@ type OffRampInterface interface { ManuallyExecute(opts *bind.TransactOpts, reports []InternalExecutionReportSingleChain, gasLimitOverrides [][]*big.Int) (*types.Transaction, error) - ResetUnblessedRoots(opts *bind.TransactOpts, rootToReset []OffRampUnblessedRoot) (*types.Transaction, error) - SetDynamicConfig(opts *bind.TransactOpts, dynamicConfig OffRampDynamicConfig) (*types.Transaction, error) SetOCR3Configs(opts *bind.TransactOpts, ocrConfigArgs []MultiOCR3BaseOCRConfigArgs) (*types.Transaction, error) diff --git a/core/gethwrappers/ccip/generated/onramp/onramp.go b/core/gethwrappers/ccip/generated/onramp/onramp.go index 61c35f6c4d..776f945650 100644 --- a/core/gethwrappers/ccip/generated/onramp/onramp.go +++ b/core/gethwrappers/ccip/generated/onramp/onramp.go @@ -91,13 +91,13 @@ type OnRampDynamicConfig struct { type OnRampStaticConfig struct { ChainSelector uint64 - RmnProxy common.Address + Rmn common.Address NonceManager common.Address TokenAdminRegistry common.Address } var OnRampMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CannotSendZeroTokens\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GetSupportedTokensFunctionalityRemovedCheckAdminRegistry\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidAllowListRequest\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidDestChainConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeCalledByRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrAllowlistAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RouterMustSetOriginalSender\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"UnsupportedToken\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"name\":\"AllowListAdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"senders\",\"type\":\"address[]\"}],\"name\":\"AllowListSendersAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"senders\",\"type\":\"address[]\"}],\"name\":\"AllowListSendersRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"CCIPMessageSent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOnRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"allowListEnabled\",\"type\":\"bool\"}],\"name\":\"DestChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"feeValueJuels\",\"type\":\"uint256\"}],\"name\":\"FeePaid\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeeTokenWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"allowListEnabled\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"addedAllowlistedSenders\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"removedAllowlistedSenders\",\"type\":\"address[]\"}],\"internalType\":\"structOnRamp.AllowListConfigArgs[]\",\"name\":\"allowListConfigArgsItems\",\"type\":\"tuple[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyDestChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"}],\"name\":\"forwardFromRouter\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getAllowedSendersList\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getDestChainConfig\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"allowListEnabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getExpectedNextSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"getFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"},{\"internalType\":\"contractIERC20\",\"name\":\"sourceToken\",\"type\":\"address\"}],\"name\":\"getPoolBySourceToken\",\"outputs\":[{\"internalType\":\"contractIPoolV1\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"contractIRouter\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnProxy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"name\":\"getSupportedTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"setDynamicConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"withdrawFeeTokens\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CannotSendZeroTokens\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GetSupportedTokensFunctionalityRemovedCheckAdminRegistry\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidAllowListRequest\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidDestChainConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeCalledByRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrAllowlistAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RouterMustSetOriginalSender\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"UnsupportedToken\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"name\":\"AllowListAdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"senders\",\"type\":\"address[]\"}],\"name\":\"AllowListSendersAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"senders\",\"type\":\"address[]\"}],\"name\":\"AllowListSendersRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"CCIPMessageSent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOnRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"allowListEnabled\",\"type\":\"bool\"}],\"name\":\"DestChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"feeValueJuels\",\"type\":\"uint256\"}],\"name\":\"FeePaid\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeeTokenWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"allowListEnabled\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"addedAllowlistedSenders\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"removedAllowlistedSenders\",\"type\":\"address[]\"}],\"internalType\":\"structOnRamp.AllowListConfigArgs[]\",\"name\":\"allowListConfigArgsItems\",\"type\":\"tuple[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyDestChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"}],\"name\":\"forwardFromRouter\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getAllowedSendersList\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getDestChainConfig\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"allowListEnabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getExpectedNextSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"getFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"},{\"internalType\":\"contractIERC20\",\"name\":\"sourceToken\",\"type\":\"address\"}],\"name\":\"getPoolBySourceToken\",\"outputs\":[{\"internalType\":\"contractIPoolV1\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"contractIRouter\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"name\":\"getSupportedTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"setDynamicConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"withdrawFeeTokens\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", Bin: "0x6101006040523480156200001257600080fd5b506040516200402938038062004029833981016040819052620000359162000665565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf8162000186565b505083516001600160401b031615905080620000e6575060208301516001600160a01b0316155b80620000fd575060408301516001600160a01b0316155b8062000114575060608301516001600160a01b0316155b1562000133576040516306b7c75960e31b815260040160405180910390fd5b82516001600160401b031660805260208301516001600160a01b0390811660a0526040840151811660c05260608401511660e052620001728262000231565b6200017d8162000390565b5050506200079f565b336001600160a01b03821603620001e05760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b0316158062000254575060408101516001600160a01b0316155b1562000273576040516306b7c75960e31b815260040160405180910390fd5b8051600280546001600160a01b03199081166001600160a01b0393841617909155602080840180516003805485169186169190911790556040808601805160048054871691881691909117905560608088018051600580549098169089161790965582516080808201855280516001600160401b031680835260a080518b16848a0190815260c080518d16868a0190815260e080518f169789019788528a5195865292518e169b85019b909b5299518c169783019790975292518a169381019390935289518916908301529351871693810193909352518516928201929092529151909216918101919091527f23a1adf8ad7fad6091a4803227af2cee848c01a7c812404cade7c25636925e32906101000160405180910390a150565b60005b8151811015620004cf576000828281518110620003b457620003b462000789565b602002602001015190506000838381518110620003d557620003d562000789565b6020026020010151600001519050806001600160401b03166000036200041a5760405163c35aa79d60e01b81526001600160401b038216600482015260240162000083565b6001600160401b03818116600081815260066020908152604091829020868201518154600160481b600160e81b0319811669010000000000000000006001600160a01b03909316928302908117808555865192891691909816178152928301526801000000000000000090940460ff161515918101919091527fd5ad72bc37dc7a80a8b9b9df20500046fd7341adb1be2258a540466fdd7dcef59060600160405180910390a250505080600101905062000393565b5050565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b03811182821017156200050e576200050e620004d3565b60405290565b604080519081016001600160401b03811182821017156200050e576200050e620004d3565b604051601f8201601f191681016001600160401b0381118282101715620005645762000564620004d3565b604052919050565b80516001600160401b03811681146200058457600080fd5b919050565b6001600160a01b03811681146200059f57600080fd5b50565b600082601f830112620005b457600080fd5b815160206001600160401b03821115620005d257620005d2620004d3565b620005e2818360051b0162000539565b82815260069290921b840181019181810190868411156200060257600080fd5b8286015b848110156200065a5760408189031215620006215760008081fd5b6200062b62000514565b62000636826200056c565b815284820151620006478162000589565b8186015283529183019160400162000606565b509695505050505050565b60008060008385036101208112156200067d57600080fd5b60808112156200068c57600080fd5b62000696620004e9565b620006a1866200056c565b81526020860151620006b38162000589565b60208201526040860151620006c88162000589565b60408201526060860151620006dd8162000589565b606082015293506080607f1982011215620006f757600080fd5b5062000702620004e9565b6080850151620007128162000589565b815260a0850151620007248162000589565b602082015260c0850151620007398162000589565b604082015260e08501516200074e8162000589565b60608201526101008501519092506001600160401b038111156200077157600080fd5b6200077f86828701620005a2565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b60805160a05160c05160e051613811620008186000396000818161022c01528181610c790152611ba10152600081816101f0015281816112480152611b7a0152600081816101b4015281816105de0152611b500152600081816101840152818161116e0152818161164b0152611b2301526138116000f3fe608060405234801561001057600080fd5b50600436106101365760003560e01c806379ba5097116100b2578063a6f3ab6c11610081578063df0aa9e911610066578063df0aa9e91461052d578063f2fde38b14610540578063fbca3b741461055357600080fd5b8063a6f3ab6c146104cd578063d77d5ed0146104e057600080fd5b806379ba50971461045b5780638da5cb5b146104635780639041be3d14610481578063972b4612146104ad57600080fd5b806334adf4941161010957806348a98aa4116100ee57806348a98aa4146103045780636def4ce71461033c5780637437ff9f146103db57600080fd5b806334adf494146102e95780633a019940146102fc57600080fd5b80630242cf601461013b57806306285c6914610150578063181f5a771461027f57806320487ded146102c8575b600080fd5b61014e610149366004612696565b610566565b005b61026960408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16815250905090565b6040516102769190612759565b60405180910390f35b6102bb6040518060400160405280601081526020017f4f6e52616d7020312e362e302d6465760000000000000000000000000000000081525081565b604051610276919061281e565b6102db6102d6366004612849565b61057a565b604051908152602001610276565b61014e6102f7366004612899565b610733565b61014e610a06565b61031761031236600461290e565b610c31565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610276565b61039f61034a366004612947565b67ffffffffffffffff9081166000908152600660205260409020549081169168010000000000000000820460ff16916901000000000000000000900473ffffffffffffffffffffffffffffffffffffffff1690565b6040805167ffffffffffffffff9094168452911515602084015273ffffffffffffffffffffffffffffffffffffffff1690820152606001610276565b61044e604080516080810182526000808252602082018190529181018290526060810191909152506040805160808101825260025473ffffffffffffffffffffffffffffffffffffffff908116825260035481166020830152600454811692820192909252600554909116606082015290565b6040516102769190612964565b61014e610ce6565b60005473ffffffffffffffffffffffffffffffffffffffff16610317565b61049461048f366004612947565b610de3565b60405167ffffffffffffffff9091168152602001610276565b6104c06104bb366004612947565b610e0c565b60405161027691906129ad565b61014e6104db366004612a17565b610e34565b6103176104ee366004612947565b67ffffffffffffffff166000908152600660205260409020546901000000000000000000900473ffffffffffffffffffffffffffffffffffffffff1690565b6102db61053b366004612a7e565b610e45565b61014e61054e366004612aea565b6116fe565b6104c0610561366004612947565b61170f565b61056e611743565b610577816117c6565b50565b6040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815277ffffffffffffffff00000000000000000000000000000000608084901b16600482015260009073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690632cbc26bb90602401602060405180830381865afa158015610625573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106499190612b15565b15610691576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024015b60405180910390fd5b6002546040517fd8694ccd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063d8694ccd906106e99086908690600401612c46565b602060405180830381865afa158015610706573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061072a9190612d8f565b90505b92915050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146107a35760055473ffffffffffffffffffffffffffffffffffffffff1633146107a3576040517f905d7d9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015610a015760008383838181106107c2576107c2612da8565b90506020028101906107d49190612dd7565b6107dd90612e88565b805167ffffffffffffffff1660009081526006602090815260409091209082015181547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff16680100000000000000009115801592909202178255919250906109545760005b8260400151518110156108fd5760008360400151828151811061086757610867612da8565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036108e65783516040517f463258ff00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610688565b6108f3600184018261193d565b5050600101610842565b506040820151511561095457816000015167ffffffffffffffff167f330939f6eafe8bb516716892fe962ff19770570838686e6579dbc1cc51fc3281836040015160405161094b91906129ad565b60405180910390a25b60005b8260600151518110156109a0576109978360600151828151811061097d5761097d612da8565b60200260200101518360010161195f90919063ffffffff16565b50600101610957565b50606082015151156109f757816000015167ffffffffffffffff167fc237ec1921f855ccd5e9a5af9733f2d58943a5a8501ec5988e305d7a4d42158683606001516040516109ee91906129ad565b60405180910390a25b50506001016107a6565b505050565b600254604080517fcdc73d51000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163cdc73d5191600480830192869291908290030181865afa158015610a75573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610abb9190810190612f1b565b60045490915073ffffffffffffffffffffffffffffffffffffffff1660005b8251811015610a01576000838281518110610af757610af7612da8565b60209081029190910101516040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915060009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa158015610b72573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b969190612d8f565b90508015610c2757610bbf73ffffffffffffffffffffffffffffffffffffffff83168583611981565b8173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f508d7d183612c18fc339b42618912b9fa3239f631dd7ec0671f950200a0fa66e83604051610c1e91815260200190565b60405180910390a35b5050600101610ada565b6040517fbbe4f6db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063bbe4f6db90602401602060405180830381865afa158015610cc2573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061072a9190612faa565b60015473ffffffffffffffffffffffffffffffffffffffff163314610d67576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610688565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b67ffffffffffffffff808216600090815260066020526040812054909161072d91166001612ff6565b67ffffffffffffffff8116600090815260066020526040902060609061072d90600101611a0e565b610e3c611743565b61057781611a22565b67ffffffffffffffff8416600090815260066020526040812073ffffffffffffffffffffffffffffffffffffffff8316610eab576040517fa4ec747900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805468010000000000000000900460ff1615610f1c57610ece6001820184611c04565b610f1c576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152602401610688565b80546901000000000000000000900473ffffffffffffffffffffffffffffffffffffffff163314610f79576040517f1c0a352900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60035473ffffffffffffffffffffffffffffffffffffffff16801561101f576040517fe0a0e50600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82169063e0a0e50690610fec908a908a90600401612c46565b600060405180830381600087803b15801561100657600080fd5b505af115801561101a573d6000803e3d6000fd5b505050505b506002546000908190819073ffffffffffffffffffffffffffffffffffffffff1663c4276bfc8a61105660808c0160608d01612aea565b8a61106460808e018e613017565b6040518663ffffffff1660e01b815260040161108495949392919061307c565b600060405180830381865afa1580156110a1573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526110e79190810190613144565b919450925090506110fe6080890160608a01612aea565b73ffffffffffffffffffffffffffffffffffffffff167f075a2720282fdf622141dae0b048ef90a21a7e57c134c76912d19d006b3b3f6f8460405161114591815260200190565b60405180910390a2604080516101a081019091526000610100820181815267ffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000081166101208501528c811661014085015287549293928392916101608401918a9187916111ba911661319e565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905567ffffffffffffffff168152602001866112ba576040517fea458c0c00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8f16600482015273ffffffffffffffffffffffffffffffffffffffff8c811660248301527f0000000000000000000000000000000000000000000000000000000000000000169063ea458c0c906044016020604051808303816000875af1158015611291573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112b591906131c5565b6112bd565b60005b67ffffffffffffffff1681525081526020018873ffffffffffffffffffffffffffffffffffffffff1681526020018a80602001906112fb9190613017565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050509082525060200161133f8b80613017565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050908252506020810184905260400161139060808c0160608d01612aea565b73ffffffffffffffffffffffffffffffffffffffff1681526020018981526020018a80604001906113c191906131e2565b905067ffffffffffffffff8111156113db576113db612570565b60405190808252806020026020018201604052801561143e57816020015b61142b6040518060a0016040528060608152602001606081526020016060815260200160008152602001606081525090565b8152602001906001900390816113f95790505b509052905060005b61145360408b018b6131e2565b9050811015611502576114d961146c60408c018c6131e2565b8381811061147c5761147c612da8565b905060400201803603810190611492919061324a565b8c61149d8d80613017565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508e9250611c33915050565b8260e0015182815181106114ef576114ef612da8565b6020908102919091010152600101611446565b5060025460e082015160009173ffffffffffffffffffffffffffffffffffffffff169063085318f8908d9061153a60408f018f6131e2565b6040518563ffffffff1660e01b81526004016115599493929190613361565b600060405180830381865afa158015611576573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526115bc9190810190613397565b905060005b8260e0015151811015611615578181815181106115e0576115e0612da8565b60200260200101518360e0015182815181106115fe576115fe612da8565b6020908102919091010151608001526001016115c1565b50604080517f130ac867e79e2789f923760a88743d292acdf7002139a588206e2260f73f7321602082015267ffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811692820192909252908c1660608201523060808201526116a590839060a00160405160208183030381529060405280519060200120611f59565b82515260405167ffffffffffffffff8c16907ff6e86ef8896c7a0d629406168f396e883280680c99e649b9e2d36466fbc9f9e5906116e4908590613448565b60405180910390a25051519450505050505b949350505050565b611706611743565b61057781612059565b60606040517f9e7177c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005473ffffffffffffffffffffffffffffffffffffffff1633146117c4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610688565b565b60005b81518110156119395760008282815181106117e6576117e6612da8565b60200260200101519050600083838151811061180457611804612da8565b60200260200101516000015190508067ffffffffffffffff16600003611862576040517fc35aa79d00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610688565b67ffffffffffffffff8181166000818152600660209081526040918290208682015181547fffffff0000000000000000000000000000000000000000ffffffffffffffffff8116690100000000000000000073ffffffffffffffffffffffffffffffffffffffff909316928302908117808555865192891691909816178152928301526801000000000000000090940460ff161515918101919091527fd5ad72bc37dc7a80a8b9b9df20500046fd7341adb1be2258a540466fdd7dcef59060600160405180910390a25050508060010190506117c9565b5050565b600061072a8373ffffffffffffffffffffffffffffffffffffffff841661214e565b600061072a8373ffffffffffffffffffffffffffffffffffffffff841661219d565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052610a01908490612297565b60606000611a1b836123a3565b9392505050565b805173ffffffffffffffffffffffffffffffffffffffff161580611a5e5750604081015173ffffffffffffffffffffffffffffffffffffffff16155b15611a95576040517f35be3ac800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051600280547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff93841617909155602080840151600380548416918516919091179055604080850151600480548516918616919091179055606080860151600580549095169086161790935580516080810182527f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681527f00000000000000000000000000000000000000000000000000000000000000008516928101929092527f00000000000000000000000000000000000000000000000000000000000000008416828201527f00000000000000000000000000000000000000000000000000000000000000009093169181019190915290517f23a1adf8ad7fad6091a4803227af2cee848c01a7c812404cade7c25636925e3291611bf9918490613596565b60405180910390a150565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600183016020526040812054151561072a565b611c656040518060a0016040528060608152602001606081526020016060815260200160008152602001606081525090565b8460200151600003611ca3576040517f5cf0444900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611cb3858760000151610c31565b905073ffffffffffffffffffffffffffffffffffffffff81161580611d8357506040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527faff2afbf00000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff8216906301ffc9a790602401602060405180830381865afa158015611d5d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d819190612b15565b155b15611dd55785516040517fbf16aab600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610688565b60008173ffffffffffffffffffffffffffffffffffffffff16639a4575b96040518060a001604052808881526020018967ffffffffffffffff1681526020018773ffffffffffffffffffffffffffffffffffffffff1681526020018a6020015181526020018a6000015173ffffffffffffffffffffffffffffffffffffffff168152506040518263ffffffff1660e01b8152600401611e749190613635565b6000604051808303816000875af1158015611e93573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611ed991908101906136ab565b6040805160a0810190915273ffffffffffffffffffffffffffffffffffffffff841660c08201529091508060e0810160405160208183030381529060405281526020018260000151815260200182602001518152602001886020015181526020016040518060200160405280600081525081525092505050949350505050565b60008060001b82846020015185606001518660000151606001518760000151608001518860a001518960c00151604051602001611f9b9695949392919061373c565b604051602081830303815290604052805190602001208560400151805190602001208660e00151604051602001611fd2919061379d565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201206080808c0151805190840120928501989098529183019590955260608201939093529384015260a083015260c082015260e00160405160208183030381529060405280519060200120905092915050565b3373ffffffffffffffffffffffffffffffffffffffff8216036120d8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610688565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60008181526001830160205260408120546121955750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561072d565b50600061072d565b600081815260018301602052604081205480156122865760006121c16001836137b0565b85549091506000906121d5906001906137b0565b905080821461223a5760008660000182815481106121f5576121f5612da8565b906000526020600020015490508087600001848154811061221857612218612da8565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061224b5761224b6137c3565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061072d565b600091505061072d565b5092915050565b60006122f9826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166123ff9092919063ffffffff16565b805190915015610a0157808060200190518101906123179190612b15565b610a01576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610688565b6060816000018054806020026020016040519081016040528092919081815260200182805480156123f357602002820191906000526020600020905b8154815260200190600101908083116123df575b50505050509050919050565b60606116f68484600085856000808673ffffffffffffffffffffffffffffffffffffffff16858760405161243391906137f2565b60006040518083038185875af1925050503d8060008114612470576040519150601f19603f3d011682016040523d82523d6000602084013e612475565b606091505b509150915061248687838387612491565b979650505050505050565b606083156125275782516000036125205773ffffffffffffffffffffffffffffffffffffffff85163b612520576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610688565b50816116f6565b6116f6838381511561253c5781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610688919061281e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff811182821017156125c2576125c2612570565b60405290565b6040516080810167ffffffffffffffff811182821017156125c2576125c2612570565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561263257612632612570565b604052919050565b600067ffffffffffffffff82111561265457612654612570565b5060051b60200190565b67ffffffffffffffff8116811461057757600080fd5b73ffffffffffffffffffffffffffffffffffffffff8116811461057757600080fd5b600060208083850312156126a957600080fd5b823567ffffffffffffffff8111156126c057600080fd5b8301601f810185136126d157600080fd5b80356126e46126df8261263a565b6125eb565b81815260069190911b8201830190838101908783111561270357600080fd5b928401925b8284101561248657604084890312156127215760008081fd5b61272961259f565b84356127348161265e565b81528486013561274381612674565b8187015282526040939093019290840190612708565b6080810161072d828467ffffffffffffffff8151168252602081015173ffffffffffffffffffffffffffffffffffffffff808216602085015280604084015116604085015280606084015116606085015250505050565b60005b838110156127cb5781810151838201526020016127b3565b50506000910152565b600081518084526127ec8160208601602086016127b0565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061072a60208301846127d4565b600060a0828403121561284357600080fd5b50919050565b6000806040838503121561285c57600080fd5b82356128678161265e565b9150602083013567ffffffffffffffff81111561288357600080fd5b61288f85828601612831565b9150509250929050565b600080602083850312156128ac57600080fd5b823567ffffffffffffffff808211156128c457600080fd5b818501915085601f8301126128d857600080fd5b8135818111156128e757600080fd5b8660208260051b85010111156128fc57600080fd5b60209290920196919550909350505050565b6000806040838503121561292157600080fd5b823561292c8161265e565b9150602083013561293c81612674565b809150509250929050565b60006020828403121561295957600080fd5b8135611a1b8161265e565b6080810161072d8284805173ffffffffffffffffffffffffffffffffffffffff908116835260208083015182169084015260408083015182169084015260609182015116910152565b6020808252825182820181905260009190848201906040850190845b818110156129fb57835173ffffffffffffffffffffffffffffffffffffffff16835292840192918401916001016129c9565b50909695505050505050565b8035612a1281612674565b919050565b600060808284031215612a2957600080fd5b612a316125c8565b8235612a3c81612674565b81526020830135612a4c81612674565b60208201526040830135612a5f81612674565b60408201526060830135612a7281612674565b60608201529392505050565b60008060008060808587031215612a9457600080fd5b8435612a9f8161265e565b9350602085013567ffffffffffffffff811115612abb57600080fd5b612ac787828801612831565b935050604085013591506060850135612adf81612674565b939692955090935050565b600060208284031215612afc57600080fd5b8135611a1b81612674565b801515811461057757600080fd5b600060208284031215612b2757600080fd5b8151611a1b81612b07565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112612b6757600080fd5b830160208101925035905067ffffffffffffffff811115612b8757600080fd5b803603821315612b9657600080fd5b9250929050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b8183526000602080850194508260005b85811015612c3b578135612c0981612674565b73ffffffffffffffffffffffffffffffffffffffff168752818301358388015260409687019690910190600101612bf6565b509495945050505050565b600067ffffffffffffffff808516835260406020840152612c678485612b32565b60a06040860152612c7c60e086018284612b9d565b915050612c8c6020860186612b32565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc080878503016060880152612cc2848385612b9d565b9350604088013592507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1883603018312612cfb57600080fd5b60209288019283019235915084821115612d1457600080fd5b8160061b3603831315612d2657600080fd5b80878503016080880152612d3b848385612be6565b9450612d4960608901612a07565b73ffffffffffffffffffffffffffffffffffffffff811660a08901529350612d746080890189612b32565b94509250808786030160c08801525050612486838383612b9d565b600060208284031215612da157600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81833603018112612e0b57600080fd5b9190910192915050565b600082601f830112612e2657600080fd5b81356020612e366126df8361263a565b8083825260208201915060208460051b870101935086841115612e5857600080fd5b602086015b84811015612e7d578035612e7081612674565b8352918301918301612e5d565b509695505050505050565b600060808236031215612e9a57600080fd5b612ea26125c8565b8235612ead8161265e565b81526020830135612ebd81612b07565b6020820152604083013567ffffffffffffffff80821115612edd57600080fd5b612ee936838701612e15565b60408401526060850135915080821115612f0257600080fd5b50612f0f36828601612e15565b60608301525092915050565b60006020808385031215612f2e57600080fd5b825167ffffffffffffffff811115612f4557600080fd5b8301601f81018513612f5657600080fd5b8051612f646126df8261263a565b81815260059190911b82018301908381019087831115612f8357600080fd5b928401925b82841015612486578351612f9b81612674565b82529284019290840190612f88565b600060208284031215612fbc57600080fd5b8151611a1b81612674565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b67ffffffffffffffff81811683821601908082111561229057612290612fc7565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261304c57600080fd5b83018035915067ffffffffffffffff82111561306757600080fd5b602001915036819003821315612b9657600080fd5b67ffffffffffffffff8616815273ffffffffffffffffffffffffffffffffffffffff85166020820152836040820152608060608201526000612486608083018486612b9d565b600082601f8301126130d357600080fd5b815167ffffffffffffffff8111156130ed576130ed612570565b61311e60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016125eb565b81815284602083860101111561313357600080fd5b6116f68260208301602087016127b0565b60008060006060848603121561315957600080fd5b83519250602084015161316b81612b07565b604085015190925067ffffffffffffffff81111561318857600080fd5b613194868287016130c2565b9150509250925092565b600067ffffffffffffffff8083168181036131bb576131bb612fc7565b6001019392505050565b6000602082840312156131d757600080fd5b8151611a1b8161265e565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261321757600080fd5b83018035915067ffffffffffffffff82111561323257600080fd5b6020019150600681901b3603821315612b9657600080fd5b60006040828403121561325c57600080fd5b61326461259f565b823561326f81612674565b81526020928301359281019290925250919050565b600082825180855260208086019550808260051b84010181860160005b84811015613354577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018952815160a081518186526132e5828701826127d4565b91505085820151858203878701526132fd82826127d4565b9150506040808301518683038288015261331783826127d4565b9250505060608083015181870152506080808301519250858203818701525061334081836127d4565b9a86019a94505050908301906001016132a1565b5090979650505050505050565b67ffffffffffffffff851681526060602082015260006133846060830186613284565b8281036040840152612486818587612be6565b600060208083850312156133aa57600080fd5b825167ffffffffffffffff808211156133c257600080fd5b818501915085601f8301126133d657600080fd5b81516133e46126df8261263a565b81815260059190911b8301840190848101908883111561340357600080fd5b8585015b8381101561343b5780518581111561341f5760008081fd5b61342d8b89838a01016130c2565b845250918601918601613407565b5098975050505050505050565b6020815261349960208201835180518252602081015167ffffffffffffffff808216602085015280604084015116604085015280606084015116606085015280608084015116608085015250505050565b600060208301516134c260c084018273ffffffffffffffffffffffffffffffffffffffff169052565b5060408301516101808060e08501526134df6101a08501836127d4565b915060608501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0808685030161010087015261351c84836127d4565b935060808701519150808685030161012087015261353a84836127d4565b935060a0870151915061356661014087018373ffffffffffffffffffffffffffffffffffffffff169052565b60c087015161016087015260e087015191508086850301838701525061358c8382613284565b9695505050505050565b61010081016135ee828567ffffffffffffffff8151168252602081015173ffffffffffffffffffffffffffffffffffffffff808216602085015280604084015116604085015280606084015116606085015250505050565b825173ffffffffffffffffffffffffffffffffffffffff90811660808401526020840151811660a08401526040840151811660c084015260608401511660e0830152611a1b565b602081526000825160a0602084015261365160c08401826127d4565b905067ffffffffffffffff6020850151166040840152604084015173ffffffffffffffffffffffffffffffffffffffff8082166060860152606086015160808601528060808701511660a086015250508091505092915050565b6000602082840312156136bd57600080fd5b815167ffffffffffffffff808211156136d557600080fd5b90830190604082860312156136e957600080fd5b6136f161259f565b82518281111561370057600080fd5b61370c878286016130c2565b82525060208301518281111561372157600080fd5b61372d878286016130c2565b60208301525095945050505050565b600073ffffffffffffffffffffffffffffffffffffffff808916835260c0602084015261376c60c08401896127d4565b67ffffffffffffffff97881660408501529590961660608301525091909316608082015260a0019190915292915050565b60208152600061072a6020830184613284565b8181038181111561072d5761072d612fc7565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b60008251612e0b8184602087016127b056fea164736f6c6343000818000a", } diff --git a/core/gethwrappers/ccip/generated/report_codec/report_codec.go b/core/gethwrappers/ccip/generated/report_codec/report_codec.go index 0080cfc419..29333984cc 100644 --- a/core/gethwrappers/ccip/generated/report_codec/report_codec.go +++ b/core/gethwrappers/ccip/generated/report_codec/report_codec.go @@ -30,6 +30,11 @@ var ( _ = abi.ConvertType ) +type IRMNV2Signature struct { + R [32]byte + S [32]byte +} + type InternalAny2EVMRampMessage struct { Header InternalRampMessageHeader Sender []byte @@ -52,6 +57,14 @@ type InternalGasPriceUpdate struct { UsdPerUnitGas *big.Int } +type InternalMerkleRoot struct { + SourceChainSelector uint64 + MinSeqNr uint64 + MaxSeqNr uint64 + MerkleRoot [32]byte + OnRampAddress []byte +} + type InternalPriceUpdates struct { TokenPriceUpdates []InternalTokenPriceUpdate GasPriceUpdates []InternalGasPriceUpdate @@ -79,24 +92,14 @@ type InternalTokenPriceUpdate struct { } type OffRampCommitReport struct { - PriceUpdates InternalPriceUpdates - MerkleRoots []OffRampMerkleRoot -} - -type OffRampInterval struct { - Min uint64 - Max uint64 -} - -type OffRampMerkleRoot struct { - SourceChainSelector uint64 - Interval OffRampInterval - MerkleRoot [32]byte + PriceUpdates InternalPriceUpdates + MerkleRoots []InternalMerkleRoot + RmnSignatures []IRMNV2Signature } var ReportCodecMetaData = &bind.MetaData{ - ABI: "[{\"anonymous\":false,\"inputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"internalType\":\"structOffRamp.Interval\",\"name\":\"interval\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structOffRamp.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"report\",\"type\":\"tuple\"}],\"name\":\"CommitReportDecoded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage[]\",\"name\":\"messages\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[][]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[][]\"},{\"internalType\":\"bytes32[]\",\"name\":\"proofs\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"proofFlagBits\",\"type\":\"uint256\"}],\"indexed\":false,\"internalType\":\"structInternal.ExecutionReportSingleChain[]\",\"name\":\"report\",\"type\":\"tuple[]\"}],\"name\":\"ExecuteReportDecoded\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"decodeCommitReport\",\"outputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"internalType\":\"structOffRamp.Interval\",\"name\":\"interval\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structOffRamp.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"}],\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"decodeExecuteReport\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage[]\",\"name\":\"messages\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[][]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[][]\"},{\"internalType\":\"bytes32[]\",\"name\":\"proofs\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"proofFlagBits\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.ExecutionReportSingleChain[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]", - Bin: "0x608060405234801561001057600080fd5b5061126d806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80636fb349561461003b578063f816ec6014610064575b600080fd5b61004e61004936600461022c565b610084565b60405161005b91906104ed565b60405180910390f35b61007761007236600461022c565b6100a0565b60405161005b91906107a6565b60608180602001905181019061009a9190610de1565b92915050565b604080516080810182526060918101828152828201839052815260208101919091528180602001905181019061009a91906110f7565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff81118282101715610128576101286100d6565b60405290565b60405160c0810167ffffffffffffffff81118282101715610128576101286100d6565b6040805190810167ffffffffffffffff81118282101715610128576101286100d6565b6040516060810167ffffffffffffffff81118282101715610128576101286100d6565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156101de576101de6100d6565b604052919050565b600067ffffffffffffffff821115610200576102006100d6565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b60006020828403121561023e57600080fd5b813567ffffffffffffffff81111561025557600080fd5b8201601f8101841361026657600080fd5b8035610279610274826101e6565b610197565b81815285602083850101111561028e57600080fd5b81602084016020830137600091810160200191909152949350505050565b60005b838110156102c75781810151838201526020016102af565b50506000910152565b600081518084526102e88160208601602086016102ac565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b600082825180855260208086019550808260051b84010181860160005b848110156103ea577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018952815160a0815181865261037b828701826102d0565b915050858201518582038787015261039382826102d0565b915050604080830151868303828801526103ad83826102d0565b925050506060808301518187015250608080830151925085820381870152506103d681836102d0565b9a86019a9450505090830190600101610337565b5090979650505050505050565b6000828251808552602080860195506005818360051b8501018287016000805b868110156104a2577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe088850381018c5283518051808752908801908887019080891b88018a01865b8281101561048b57858a83030184526104798286516102d0565b948c0194938c0193915060010161045f565b509e8a019e97505050938701935050600101610417565b50919998505050505050505050565b60008151808452602080850194506020840160005b838110156104e2578151875295820195908201906001016104c6565b509495945050505050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b828110156106d5577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0888603018452815160a0860167ffffffffffffffff8083511688528883015160a08a8a015282815180855260c08b01915060c08160051b8c010194508b8301925060005b8181101561067e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff408c87030183528351805180518852868f820151168f890152866040820151166040890152866060820151166060890152866080820151166080890152508d81015161014060a08901526106016101408901826102d0565b9050604082015188820360c08a015261061a82826102d0565b915050606082015161064460e08a018273ffffffffffffffffffffffffffffffffffffffff169052565b50608082015161010089015260a0820151915087810361012089015261066a818361031a565b97505050928c0192918c0191600101610581565b50505050506040820151878203604089015261069a82826103f7565b915050606082015187820360608901526106b482826104b1565b60809384015198909301979097525094509285019290850190600101610514565b5092979650505050505050565b60008151808452602080850194506020840160005b838110156104e2578151805167ffffffffffffffff1688528301517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1683880152604090960195908201906001016106f7565b600081518084526020808501945080840160005b838110156104e2578151805167ffffffffffffffff90811689528482015180518216868b0152850151166040808a0191909152015160608801526080909601959082019060010161075a565b6000602080835283516040808386015260a0850182516040606088015281815180845260c0890191508683019350600092505b80831015610836578351805173ffffffffffffffffffffffffffffffffffffffff1683528701517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16878301529286019260019290920191908401906107d9565b50938501518785037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa00160808901529361087081866106e2565b9450505050508185015191507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08482030160408501526108b08183610746565b95945050505050565b600067ffffffffffffffff8211156108d3576108d36100d6565b5060051b60200190565b805167ffffffffffffffff811681146108f557600080fd5b919050565b600060a0828403121561090c57600080fd5b610914610105565b905081518152610926602083016108dd565b6020820152610937604083016108dd565b6040820152610948606083016108dd565b6060820152610959608083016108dd565b608082015292915050565b600082601f83011261097557600080fd5b8151610983610274826101e6565b81815284602083860101111561099857600080fd5b6109a98260208301602087016102ac565b949350505050565b805173ffffffffffffffffffffffffffffffffffffffff811681146108f557600080fd5b600082601f8301126109e657600080fd5b815160206109f6610274836108b9565b82815260059290921b84018101918181019086841115610a1557600080fd5b8286015b84811015610b2f57805167ffffffffffffffff80821115610a3a5760008081fd5b818901915060a0807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848d03011215610a735760008081fd5b610a7b610105565b8784015183811115610a8d5760008081fd5b610a9b8d8a83880101610964565b82525060408085015184811115610ab25760008081fd5b610ac08e8b83890101610964565b8a8401525060608086015185811115610ad95760008081fd5b610ae78f8c838a0101610964565b83850152506080915081860151818401525082850151925083831115610b0d5760008081fd5b610b1b8d8a85880101610964565b908201528652505050918301918301610a19565b509695505050505050565b600082601f830112610b4b57600080fd5b81516020610b5b610274836108b9565b82815260059290921b84018101918181019086841115610b7a57600080fd5b8286015b84811015610b2f57805167ffffffffffffffff80821115610b9f5760008081fd5b8189019150610140807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848d03011215610bd95760008081fd5b610be161012e565b610bed8c8986016108fa565b815260c084015183811115610c025760008081fd5b610c108d8a83880101610964565b898301525060e084015183811115610c285760008081fd5b610c368d8a83880101610964565b604083015250610c4961010085016109b1565b60608201526101208401516080820152908301519082821115610c6c5760008081fd5b610c7a8c89848701016109d5565b60a08201528652505050918301918301610b7e565b600082601f830112610ca057600080fd5b81516020610cb0610274836108b9565b82815260059290921b84018101918181019086841115610ccf57600080fd5b8286015b84811015610b2f57805167ffffffffffffffff80821115610cf357600080fd5b818901915089603f830112610d0757600080fd5b85820151610d17610274826108b9565b81815260059190911b830160400190878101908c831115610d3757600080fd5b604085015b83811015610d7057805185811115610d5357600080fd5b610d628f6040838a0101610964565b845250918901918901610d3c565b50875250505092840192508301610cd3565b600082601f830112610d9357600080fd5b81516020610da3610274836108b9565b8083825260208201915060208460051b870101935086841115610dc557600080fd5b602086015b84811015610b2f5780518352918301918301610dca565b60006020808385031215610df457600080fd5b825167ffffffffffffffff80821115610e0c57600080fd5b818501915085601f830112610e2057600080fd5b8151610e2e610274826108b9565b81815260059190911b83018401908481019088831115610e4d57600080fd5b8585015b83811015610f4757805185811115610e6857600080fd5b860160a0818c037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0011215610e9d5760008081fd5b610ea5610105565b610eb08983016108dd565b815260408083015188811115610ec65760008081fd5b610ed48e8c83870101610b3a565b8b8401525060608084015189811115610eed5760008081fd5b610efb8f8d83880101610c8f565b8385015250608091508184015189811115610f165760008081fd5b610f248f8d83880101610d82565b918401919091525060a09290920151918101919091528352918601918601610e51565b5098975050505050505050565b80517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811681146108f557600080fd5b600082601f830112610f9157600080fd5b81516020610fa1610274836108b9565b82815260069290921b84018101918181019086841115610fc057600080fd5b8286015b84811015610b2f5760408189031215610fdd5760008081fd5b610fe5610151565b610fee826108dd565b8152610ffb858301610f54565b81860152835291830191604001610fc4565b600082601f83011261101e57600080fd5b8151602061102e610274836108b9565b82815260079290921b8401810191818101908684111561104d57600080fd5b8286015b84811015610b2f57808803608081121561106b5760008081fd5b611073610174565b61107c836108dd565b81526040807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0840112156110b05760008081fd5b6110b8610151565b92506110c58785016108dd565b83526110d28185016108dd565b8388015281870192909252606083015191810191909152835291830191608001611051565b6000602080838503121561110a57600080fd5b825167ffffffffffffffff8082111561112257600080fd5b8185019150604080838803121561113857600080fd5b611140610151565b83518381111561114f57600080fd5b84016040818a03121561116157600080fd5b611169610151565b81518581111561117857600080fd5b8201601f81018b1361118957600080fd5b8051611197610274826108b9565b81815260069190911b8201890190898101908d8311156111b657600080fd5b928a01925b828410156112045787848f0312156111d35760008081fd5b6111db610151565b6111e4856109b1565b81526111f18c8601610f54565b818d0152825292870192908a01906111bb565b84525050508187015193508484111561121c57600080fd5b6112288a858401610f80565b818801528252508385015191508282111561124257600080fd5b61124e8883860161100d565b8582015280955050505050509291505056fea164736f6c6343000818000a", + ABI: "[{\"anonymous\":false,\"inputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"structIRMNV2.Signature[]\",\"name\":\"rmnSignatures\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"report\",\"type\":\"tuple\"}],\"name\":\"CommitReportDecoded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage[]\",\"name\":\"messages\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[][]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[][]\"},{\"internalType\":\"bytes32[]\",\"name\":\"proofs\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"proofFlagBits\",\"type\":\"uint256\"}],\"indexed\":false,\"internalType\":\"structInternal.ExecutionReportSingleChain[]\",\"name\":\"report\",\"type\":\"tuple[]\"}],\"name\":\"ExecuteReportDecoded\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"decodeCommitReport\",\"outputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"structIRMNV2.Signature[]\",\"name\":\"rmnSignatures\",\"type\":\"tuple[]\"}],\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"decodeExecuteReport\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage[]\",\"name\":\"messages\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[][]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[][]\"},{\"internalType\":\"bytes32[]\",\"name\":\"proofs\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"proofFlagBits\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.ExecutionReportSingleChain[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]", + Bin: "0x608060405234801561001057600080fd5b506113e6806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80636fb349561461003b578063f816ec6014610064575b600080fd5b61004e610049366004610231565b610084565b60405161005b91906104f2565b60405180910390f35b610077610072366004610231565b6100a0565b60405161005b9190610835565b60608180602001905181019061009a9190610e8d565b92915050565b6040805160a08101825260608082018181526080830182905282526020808301829052928201528251909161009a9184018101908401611250565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff8111828210171561012d5761012d6100db565b60405290565b60405160c0810167ffffffffffffffff8111828210171561012d5761012d6100db565b6040805190810167ffffffffffffffff8111828210171561012d5761012d6100db565b6040516060810167ffffffffffffffff8111828210171561012d5761012d6100db565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156101e3576101e36100db565b604052919050565b600067ffffffffffffffff821115610205576102056100db565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b60006020828403121561024357600080fd5b813567ffffffffffffffff81111561025a57600080fd5b8201601f8101841361026b57600080fd5b803561027e610279826101eb565b61019c565b81815285602083850101111561029357600080fd5b81602084016020830137600091810160200191909152949350505050565b60005b838110156102cc5781810151838201526020016102b4565b50506000910152565b600081518084526102ed8160208601602086016102b1565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b600082825180855260208086019550808260051b84010181860160005b848110156103ef577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018952815160a08151818652610380828701826102d5565b915050858201518582038787015261039882826102d5565b915050604080830151868303828801526103b283826102d5565b925050506060808301518187015250608080830151925085820381870152506103db81836102d5565b9a86019a945050509083019060010161033c565b5090979650505050505050565b6000828251808552602080860195506005818360051b8501018287016000805b868110156104a7577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe088850381018c5283518051808752908801908887019080891b88018a01865b8281101561049057858a830301845261047e8286516102d5565b948c0194938c01939150600101610464565b509e8a019e9750505093870193505060010161041c565b50919998505050505050505050565b60008151808452602080850194506020840160005b838110156104e7578151875295820195908201906001016104cb565b509495945050505050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b828110156106da577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0888603018452815160a0860167ffffffffffffffff8083511688528883015160a08a8a015282815180855260c08b01915060c08160051b8c010194508b8301925060005b81811015610683577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff408c87030183528351805180518852868f820151168f890152866040820151166040890152866060820151166060890152866080820151166080890152508d81015161014060a08901526106066101408901826102d5565b9050604082015188820360c08a015261061f82826102d5565b915050606082015161064960e08a018273ffffffffffffffffffffffffffffffffffffffff169052565b50608082015161010089015260a0820151915087810361012089015261066f818361031f565b97505050928c0192918c0191600101610586565b50505050506040820151878203604089015261069f82826103fc565b915050606082015187820360608901526106b982826104b6565b60809384015198909301979097525094509285019290850190600101610519565b5092979650505050505050565b60008151808452602080850194506020840160005b838110156104e7578151805167ffffffffffffffff1688528301517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1683880152604090960195908201906001016106fc565b600082825180855260208086019550808260051b84010181860160005b848110156103ef578583037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00189528151805167ffffffffffffffff908116855285820151811686860152604080830151909116908501526060808201519085015260809081015160a0918501829052906107e5818601836102d5565b9a86019a9450505090830190600101610768565b60008151808452602080850194506020840160005b838110156104e757815180518852830151838801526040909601959082019060010161080e565b602080825282516060838301528051604060808501819052815160c086018190526000949392840191859160e08801905b808410156108c3578451805173ffffffffffffffffffffffffffffffffffffffff1683528701517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1687830152938601936001939093019290820190610866565b50938501518785037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff800160a0890152936108fd81866106e7565b9450505050508185015191507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08085830301604086015261093e828461074b565b925060408601519150808584030160608601525061095c82826107f9565b95945050505050565b600067ffffffffffffffff82111561097f5761097f6100db565b5060051b60200190565b805167ffffffffffffffff811681146109a157600080fd5b919050565b600060a082840312156109b857600080fd5b6109c061010a565b9050815181526109d260208301610989565b60208201526109e360408301610989565b60408201526109f460608301610989565b6060820152610a0560808301610989565b608082015292915050565b600082601f830112610a2157600080fd5b8151610a2f610279826101eb565b818152846020838601011115610a4457600080fd5b610a558260208301602087016102b1565b949350505050565b805173ffffffffffffffffffffffffffffffffffffffff811681146109a157600080fd5b600082601f830112610a9257600080fd5b81516020610aa261027983610965565b82815260059290921b84018101918181019086841115610ac157600080fd5b8286015b84811015610bdb57805167ffffffffffffffff80821115610ae65760008081fd5b818901915060a0807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848d03011215610b1f5760008081fd5b610b2761010a565b8784015183811115610b395760008081fd5b610b478d8a83880101610a10565b82525060408085015184811115610b5e5760008081fd5b610b6c8e8b83890101610a10565b8a8401525060608086015185811115610b855760008081fd5b610b938f8c838a0101610a10565b83850152506080915081860151818401525082850151925083831115610bb95760008081fd5b610bc78d8a85880101610a10565b908201528652505050918301918301610ac5565b509695505050505050565b600082601f830112610bf757600080fd5b81516020610c0761027983610965565b82815260059290921b84018101918181019086841115610c2657600080fd5b8286015b84811015610bdb57805167ffffffffffffffff80821115610c4b5760008081fd5b8189019150610140807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848d03011215610c855760008081fd5b610c8d610133565b610c998c8986016109a6565b815260c084015183811115610cae5760008081fd5b610cbc8d8a83880101610a10565b898301525060e084015183811115610cd45760008081fd5b610ce28d8a83880101610a10565b604083015250610cf56101008501610a5d565b60608201526101208401516080820152908301519082821115610d185760008081fd5b610d268c8984870101610a81565b60a08201528652505050918301918301610c2a565b600082601f830112610d4c57600080fd5b81516020610d5c61027983610965565b82815260059290921b84018101918181019086841115610d7b57600080fd5b8286015b84811015610bdb57805167ffffffffffffffff80821115610d9f57600080fd5b818901915089603f830112610db357600080fd5b85820151610dc361027982610965565b81815260059190911b830160400190878101908c831115610de357600080fd5b604085015b83811015610e1c57805185811115610dff57600080fd5b610e0e8f6040838a0101610a10565b845250918901918901610de8565b50875250505092840192508301610d7f565b600082601f830112610e3f57600080fd5b81516020610e4f61027983610965565b8083825260208201915060208460051b870101935086841115610e7157600080fd5b602086015b84811015610bdb5780518352918301918301610e76565b60006020808385031215610ea057600080fd5b825167ffffffffffffffff80821115610eb857600080fd5b818501915085601f830112610ecc57600080fd5b8151610eda61027982610965565b81815260059190911b83018401908481019088831115610ef957600080fd5b8585015b83811015610ff357805185811115610f1457600080fd5b860160a0818c037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0011215610f495760008081fd5b610f5161010a565b610f5c898301610989565b815260408083015188811115610f725760008081fd5b610f808e8c83870101610be6565b8b8401525060608084015189811115610f995760008081fd5b610fa78f8d83880101610d3b565b8385015250608091508184015189811115610fc25760008081fd5b610fd08f8d83880101610e2e565b918401919091525060a09290920151918101919091528352918601918601610efd565b5098975050505050505050565b80517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811681146109a157600080fd5b600082601f83011261103d57600080fd5b8151602061104d61027983610965565b82815260069290921b8401810191818101908684111561106c57600080fd5b8286015b84811015610bdb57604081890312156110895760008081fd5b611091610156565b61109a82610989565b81526110a7858301611000565b81860152835291830191604001611070565b600082601f8301126110ca57600080fd5b815160206110da61027983610965565b82815260059290921b840181019181810190868411156110f957600080fd5b8286015b84811015610bdb57805167ffffffffffffffff8082111561111e5760008081fd5b818901915060a0807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848d030112156111575760008081fd5b61115f61010a565b61116a888501610989565b81526040611179818601610989565b89830152606061118a818701610989565b8284015260809150818601518184015250828501519250838311156111af5760008081fd5b6111bd8d8a85880101610a10565b9082015286525050509183019183016110fd565b600082601f8301126111e257600080fd5b815160206111f261027983610965565b82815260069290921b8401810191818101908684111561121157600080fd5b8286015b84811015610bdb576040818903121561122e5760008081fd5b611236610156565b815181528482015185820152835291830191604001611215565b6000602080838503121561126357600080fd5b825167ffffffffffffffff8082111561127b57600080fd5b908401906060828703121561128f57600080fd5b611297610179565b8251828111156112a657600080fd5b830160408189038113156112b957600080fd5b6112c1610156565b8251858111156112d057600080fd5b8301601f81018b136112e157600080fd5b80516112ef61027982610965565b81815260069190911b8201890190898101908d83111561130e57600080fd5b928a01925b8284101561135c5785848f03121561132b5760008081fd5b611333610156565b61133c85610a5d565b81526113498c8601611000565b818d0152825292850192908a0190611313565b84525050508287015191508482111561137457600080fd5b6113808a83850161102c565b8188015283525050828401518281111561139957600080fd5b6113a5888286016110b9565b858301525060408301519350818411156113be57600080fd5b6113ca878585016111d1565b6040820152969550505050505056fea164736f6c6343000818000a", } var ReportCodecABI = ReportCodecMetaData.ABI @@ -526,7 +529,7 @@ func (_ReportCodec *ReportCodec) ParseLog(log types.Log) (generated.AbigenLog, e } func (ReportCodecCommitReportDecoded) Topic() common.Hash { - return common.HexToHash("0x1b2cb5e9d31bdaabb2ae07532436ae669406f84003ca27179b4dfb72f127f7dc") + return common.HexToHash("0x83099d210b303f78572f4da1af1d1777cbf80cae42cdb9381f310dbdf21e8f89") } func (ReportCodecExecuteReportDecoded) Topic() common.Hash { diff --git a/core/gethwrappers/ccip/generated/rmn_remote/rmn_remote.go b/core/gethwrappers/ccip/generated/rmn_remote/rmn_remote.go new file mode 100644 index 0000000000..a380d77e10 --- /dev/null +++ b/core/gethwrappers/ccip/generated/rmn_remote/rmn_remote.go @@ -0,0 +1,842 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package rmn_remote + +import ( + "errors" + "fmt" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated" +) + +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +type IRMNV2Signature struct { + R [32]byte + S [32]byte +} + +type InternalMerkleRoot struct { + SourceChainSelector uint64 + MinSeqNr uint64 + MaxSeqNr uint64 + MerkleRoot [32]byte + OnRampAddress []byte +} + +type RMNRemoteConfig struct { + RmnHomeContractConfigDigest [32]byte + Signers []RMNRemoteSigner + MinSigners uint64 +} + +type RMNRemoteSigner struct { + OnchainPublicKey common.Address + NodeIndex uint64 +} + +type RMNRemoteVersionedConfig struct { + Version uint32 + Config RMNRemoteConfig +} + +var RMNRemoteMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"ConfigNotSet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateOnchainPublicKey\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSignature\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSignerOrder\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MinSignersTooHigh\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OutOfOrderSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ThresholdNotMet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnexpectedSigner\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"rmnHomeContractConfigDigest\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"onchainPublicKey\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"nodeIndex\",\"type\":\"uint64\"}],\"internalType\":\"structRMNRemote.Signer[]\",\"name\":\"signers\",\"type\":\"tuple[]\"},{\"internalType\":\"uint64\",\"name\":\"minSigners\",\"type\":\"uint64\"}],\"internalType\":\"structRMNRemote.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"indexed\":false,\"internalType\":\"structRMNRemote.VersionedConfig\",\"name\":\"versionedConfig\",\"type\":\"tuple\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getVersionedConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"rmnHomeContractConfigDigest\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"onchainPublicKey\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"nodeIndex\",\"type\":\"uint64\"}],\"internalType\":\"structRMNRemote.Signer[]\",\"name\":\"signers\",\"type\":\"tuple[]\"},{\"internalType\":\"uint64\",\"name\":\"minSigners\",\"type\":\"uint64\"}],\"internalType\":\"structRMNRemote.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"internalType\":\"structRMNRemote.VersionedConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes16\",\"name\":\"subject\",\"type\":\"bytes16\"}],\"name\":\"isCursed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isCursed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"rmnHomeContractConfigDigest\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"onchainPublicKey\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"nodeIndex\",\"type\":\"uint64\"}],\"internalType\":\"structRMNRemote.Signer[]\",\"name\":\"signers\",\"type\":\"tuple[]\"},{\"internalType\":\"uint64\",\"name\":\"minSigners\",\"type\":\"uint64\"}],\"internalType\":\"structRMNRemote.Config\",\"name\":\"newConfig\",\"type\":\"tuple\"}],\"name\":\"setConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"test\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"destLaneUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"structIRMNV2.Signature[]\",\"name\":\"signatures\",\"type\":\"tuple[]\"}],\"name\":\"verify\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x60a06040523480156200001157600080fd5b506040516200182d3803806200182d83398101604081905262000034916200017e565b33806000816200008b5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000be57620000be81620000d3565b5050506001600160401b0316608052620001b0565b336001600160a01b038216036200012d5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000082565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000602082840312156200019157600080fd5b81516001600160401b0381168114620001a957600080fd5b9392505050565b608051611664620001c9600039600050506116646000f3fe608060405234801561001057600080fd5b50600436106100be5760003560e01c8063397796f7116100765780638da5cb5b1161005b5780638da5cb5b14610184578063f2fde38b146101ac578063f8a8fd6d1461012857600080fd5b8063397796f71461017557806379ba50971461017c57600080fd5b80631add205f116100a75780631add205f1461012a5780632cbc26bb1461013f57806330dfc3081461016357600080fd5b8063181f5a77146100c3578063198f0f7714610115575b600080fd5b6100ff6040518060400160405280601381526020017f524d4e52656d6f746520312e362e302d6465760000000000000000000000000081525081565b60405161010c9190610c4b565b60405180910390f35b610128610123366004610c65565b6101bf565b005b6101326105f0565b60405161010c9190610ca0565b61015361014d366004610d58565b50600090565b604051901515815260200161010c565b610128610171366004610f60565b5050565b6000610153565b61012861090b565b60005460405173ffffffffffffffffffffffffffffffffffffffff909116815260200161010c565b6101286101ba36600461113d565b610a0d565b6101c7610a23565b60015b6101d7602083018361115a565b90508110156102a7576101ed602083018361115a565b828181106101fd576101fd6111c9565b905060400201602001602081019061021591906111f8565b67ffffffffffffffff1661022c602084018461115a565b610237600185611244565b818110610246576102466111c9565b905060400201602001602081019061025e91906111f8565b67ffffffffffffffff161061029f576040517f4485151700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001016101ca565b506102b5602082018261115a565b90506102c760608301604084016111f8565b67ffffffffffffffff161115610309576040517ffba0d9e600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60025b60018101541561040557600180820180546006926000929161032e9190611244565b8154811061033e5761033e6111c9565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055600181018054806103a8576103a861125d565b60008281526020902081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffff0000000000000000000000000000000000000000000000000000000016905501905561030c565b5060005b610416602083018361115a565b905081101561054b5760066000610430602085018561115a565b84818110610440576104406111c9565b610456926020604090920201908101915061113d565b73ffffffffffffffffffffffffffffffffffffffff16815260208101919091526040016000205460ff16156104b7576040517f28cae27d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600660006104ca602086018661115a565b858181106104da576104da6111c9565b6104f0926020604090920201908101915061113d565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055600101610409565b508060026105598282611345565b5050600580546000919082906105749063ffffffff16611480565b91906101000a81548163ffffffff021916908363ffffffff160217905590507f6cc65868ae41a007e6c3ed18ce591c123dd4e5864b421888c68ce92dae98cea460405180604001604052808363ffffffff168152602001846105d5906114a3565b90526040516105e49190610ca0565b60405180910390a15050565b6105f8610b99565b60408051808201825260055463ffffffff1681528151606081018352600280548252600380548551602082810282018101909752818152949580870195858201939092909160009084015b828210156106b1576000848152602090819020604080518082019091529084015473ffffffffffffffffffffffffffffffffffffffff8116825274010000000000000000000000000000000000000000900467ffffffffffffffff1681830152825260019092019101610643565b505050908252506002919091015467ffffffffffffffff166020909101529052919050565b84518110156108bd5760008582815181106106f3576106f36111c9565b602002602001015190506000600186601b8460000151856020015160405160008152602001604052604051610744949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015610766573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff81166107de576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1610610843576040517fbbe15e7f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff811660009081526006602052604090205460ff166108a2576040517faaaa914100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b9250826108ae8561161f565b945050508060010190506106d6565b5060045467ffffffffffffffff16821015610904576040517f59fa4a9300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610991576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610a15610a23565b610a1e81610aa4565b50565b565b60005473ffffffffffffffffffffffffffffffffffffffff163314610a21576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610988565b3373ffffffffffffffffffffffffffffffffffffffff821603610b23576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610988565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6040518060400160405280600063ffffffff168152602001610be260405180606001604052806000801916815260200160608152602001600067ffffffffffffffff1681525090565b905290565b6000815180845260005b81811015610c0d57602081850181015186830182015201610bf1565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000610c5e6020830184610be7565b9392505050565b600060208284031215610c7757600080fd5b813567ffffffffffffffff811115610c8e57600080fd5b820160608185031215610c5e57600080fd5b6000602080835263ffffffff8451168184015280840151604080604086015260c0850182516060870152838301516060608088015281815180845260e0890191508683019350600092505b80831015610d34578351805173ffffffffffffffffffffffffffffffffffffffff16835287015167ffffffffffffffff1687830152928601926001929092019190840190610ceb565b50604085015167ffffffffffffffff811660a08a0152955098975050505050505050565b600060208284031215610d6a57600080fd5b81357fffffffffffffffffffffffffffffffff0000000000000000000000000000000081168114610c5e57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715610dec57610dec610d9a565b60405290565b60405160a0810167ffffffffffffffff81118282101715610dec57610dec610d9a565b6040516060810167ffffffffffffffff81118282101715610dec57610dec610d9a565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715610e7f57610e7f610d9a565b604052919050565b600067ffffffffffffffff821115610ea157610ea1610d9a565b5060051b60200190565b67ffffffffffffffff81168114610a1e57600080fd5b8035610ecc81610eab565b919050565b600082601f830112610ee257600080fd5b81356020610ef7610ef283610e87565b610e38565b82815260069290921b84018101918181019086841115610f1657600080fd5b8286015b84811015610f555760408189031215610f335760008081fd5b610f3b610dc9565b813581528482013585820152835291830191604001610f1a565b509695505050505050565b60008060408385031215610f7357600080fd5b823567ffffffffffffffff80821115610f8b57600080fd5b818501915085601f830112610f9f57600080fd5b81356020610faf610ef283610e87565b82815260059290921b84018101918181019089841115610fce57600080fd5b8286015b848110156110ed57803586811115610fe957600080fd5b87017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe060a0828e038201121561101e57600080fd5b611026610df2565b8683013561103381610eab565b8152604083013561104381610eab565b81880152606083013561105581610eab565b60408201526080830135606082015260a08301358981111561107657600080fd5b8084019350508d603f84011261108b57600080fd5b868301358981111561109f5761109f610d9a565b6110af8884601f84011601610e38565b92508083528e60408286010111156110c657600080fd5b80604085018985013760009083018801526080810191909152845250918301918301610fd2565b509650508601359250508082111561110457600080fd5b5061111185828601610ed1565b9150509250929050565b73ffffffffffffffffffffffffffffffffffffffff81168114610a1e57600080fd5b60006020828403121561114f57600080fd5b8135610c5e8161111b565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261118f57600080fd5b83018035915067ffffffffffffffff8211156111aa57600080fd5b6020019150600681901b36038213156111c257600080fd5b9250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561120a57600080fd5b8135610c5e81610eab565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8181038181111561125757611257611215565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b6000813561125781610eab565b81356112a48161111b565b73ffffffffffffffffffffffffffffffffffffffff811690508154817fffffffffffffffffffffffff0000000000000000000000000000000000000000821617835560208401356112f481610eab565b7bffffffffffffffff00000000000000000000000000000000000000008160a01b16837fffffffff000000000000000000000000000000000000000000000000000000008416171784555050505050565b81358155600180820160208401357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe185360301811261138357600080fd5b8401803567ffffffffffffffff81111561139c57600080fd5b6020820191508060061b36038213156113b457600080fd5b680100000000000000008111156113cd576113cd610d9a565b825481845580821015611402576000848152602081208381019083015b808210156113fe57828255908701906113ea565b5050505b50600092835260208320925b81811015611432576114208385611299565b9284019260409290920191840161140e565b50505050506101716114466040840161128c565b6002830167ffffffffffffffff82167fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000008254161781555050565b600063ffffffff80831681810361149957611499611215565b6001019392505050565b6000606082360312156114b557600080fd5b6114bd610e15565b8235815260208084013567ffffffffffffffff8111156114dc57600080fd5b840136601f8201126114ed57600080fd5b80356114fb610ef282610e87565b81815260069190911b8201830190838101903683111561151a57600080fd5b928401925b8284101561157057604084360312156115385760008081fd5b611540610dc9565b843561154b8161111b565b81528486013561155a81610eab565b818701528252604093909301929084019061151f565b8085870152505050505061158660408401610ec1565b604082015292915050565b8181101561160c578c89037ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee00184528751805187168a528a81015187168b8b01528b81015187168c8b015287810151888b0152850151858a018490526115f9848b0182610be7565b9950509689019692890192600101611591565b50969d9c50505050505050505050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361165057611650611215565b506001019056fea164736f6c6343000818000a", +} + +var RMNRemoteABI = RMNRemoteMetaData.ABI + +var RMNRemoteBin = RMNRemoteMetaData.Bin + +func DeployRMNRemote(auth *bind.TransactOpts, backend bind.ContractBackend, chainSelector uint64) (common.Address, *types.Transaction, *RMNRemote, error) { + parsed, err := RMNRemoteMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(RMNRemoteBin), backend, chainSelector) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &RMNRemote{address: address, abi: *parsed, RMNRemoteCaller: RMNRemoteCaller{contract: contract}, RMNRemoteTransactor: RMNRemoteTransactor{contract: contract}, RMNRemoteFilterer: RMNRemoteFilterer{contract: contract}}, nil +} + +type RMNRemote struct { + address common.Address + abi abi.ABI + RMNRemoteCaller + RMNRemoteTransactor + RMNRemoteFilterer +} + +type RMNRemoteCaller struct { + contract *bind.BoundContract +} + +type RMNRemoteTransactor struct { + contract *bind.BoundContract +} + +type RMNRemoteFilterer struct { + contract *bind.BoundContract +} + +type RMNRemoteSession struct { + Contract *RMNRemote + CallOpts bind.CallOpts + TransactOpts bind.TransactOpts +} + +type RMNRemoteCallerSession struct { + Contract *RMNRemoteCaller + CallOpts bind.CallOpts +} + +type RMNRemoteTransactorSession struct { + Contract *RMNRemoteTransactor + TransactOpts bind.TransactOpts +} + +type RMNRemoteRaw struct { + Contract *RMNRemote +} + +type RMNRemoteCallerRaw struct { + Contract *RMNRemoteCaller +} + +type RMNRemoteTransactorRaw struct { + Contract *RMNRemoteTransactor +} + +func NewRMNRemote(address common.Address, backend bind.ContractBackend) (*RMNRemote, error) { + abi, err := abi.JSON(strings.NewReader(RMNRemoteABI)) + if err != nil { + return nil, err + } + contract, err := bindRMNRemote(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &RMNRemote{address: address, abi: abi, RMNRemoteCaller: RMNRemoteCaller{contract: contract}, RMNRemoteTransactor: RMNRemoteTransactor{contract: contract}, RMNRemoteFilterer: RMNRemoteFilterer{contract: contract}}, nil +} + +func NewRMNRemoteCaller(address common.Address, caller bind.ContractCaller) (*RMNRemoteCaller, error) { + contract, err := bindRMNRemote(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &RMNRemoteCaller{contract: contract}, nil +} + +func NewRMNRemoteTransactor(address common.Address, transactor bind.ContractTransactor) (*RMNRemoteTransactor, error) { + contract, err := bindRMNRemote(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &RMNRemoteTransactor{contract: contract}, nil +} + +func NewRMNRemoteFilterer(address common.Address, filterer bind.ContractFilterer) (*RMNRemoteFilterer, error) { + contract, err := bindRMNRemote(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &RMNRemoteFilterer{contract: contract}, nil +} + +func bindRMNRemote(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := RMNRemoteMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +func (_RMNRemote *RMNRemoteRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _RMNRemote.Contract.RMNRemoteCaller.contract.Call(opts, result, method, params...) +} + +func (_RMNRemote *RMNRemoteRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _RMNRemote.Contract.RMNRemoteTransactor.contract.Transfer(opts) +} + +func (_RMNRemote *RMNRemoteRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _RMNRemote.Contract.RMNRemoteTransactor.contract.Transact(opts, method, params...) +} + +func (_RMNRemote *RMNRemoteCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _RMNRemote.Contract.contract.Call(opts, result, method, params...) +} + +func (_RMNRemote *RMNRemoteTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _RMNRemote.Contract.contract.Transfer(opts) +} + +func (_RMNRemote *RMNRemoteTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _RMNRemote.Contract.contract.Transact(opts, method, params...) +} + +func (_RMNRemote *RMNRemoteCaller) GetVersionedConfig(opts *bind.CallOpts) (RMNRemoteVersionedConfig, error) { + var out []interface{} + err := _RMNRemote.contract.Call(opts, &out, "getVersionedConfig") + + if err != nil { + return *new(RMNRemoteVersionedConfig), err + } + + out0 := *abi.ConvertType(out[0], new(RMNRemoteVersionedConfig)).(*RMNRemoteVersionedConfig) + + return out0, err + +} + +func (_RMNRemote *RMNRemoteSession) GetVersionedConfig() (RMNRemoteVersionedConfig, error) { + return _RMNRemote.Contract.GetVersionedConfig(&_RMNRemote.CallOpts) +} + +func (_RMNRemote *RMNRemoteCallerSession) GetVersionedConfig() (RMNRemoteVersionedConfig, error) { + return _RMNRemote.Contract.GetVersionedConfig(&_RMNRemote.CallOpts) +} + +func (_RMNRemote *RMNRemoteCaller) IsCursed(opts *bind.CallOpts, subject [16]byte) (bool, error) { + var out []interface{} + err := _RMNRemote.contract.Call(opts, &out, "isCursed", subject) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +func (_RMNRemote *RMNRemoteSession) IsCursed(subject [16]byte) (bool, error) { + return _RMNRemote.Contract.IsCursed(&_RMNRemote.CallOpts, subject) +} + +func (_RMNRemote *RMNRemoteCallerSession) IsCursed(subject [16]byte) (bool, error) { + return _RMNRemote.Contract.IsCursed(&_RMNRemote.CallOpts, subject) +} + +func (_RMNRemote *RMNRemoteCaller) IsCursed0(opts *bind.CallOpts) (bool, error) { + var out []interface{} + err := _RMNRemote.contract.Call(opts, &out, "isCursed0") + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +func (_RMNRemote *RMNRemoteSession) IsCursed0() (bool, error) { + return _RMNRemote.Contract.IsCursed0(&_RMNRemote.CallOpts) +} + +func (_RMNRemote *RMNRemoteCallerSession) IsCursed0() (bool, error) { + return _RMNRemote.Contract.IsCursed0(&_RMNRemote.CallOpts) +} + +func (_RMNRemote *RMNRemoteCaller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _RMNRemote.contract.Call(opts, &out, "owner") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_RMNRemote *RMNRemoteSession) Owner() (common.Address, error) { + return _RMNRemote.Contract.Owner(&_RMNRemote.CallOpts) +} + +func (_RMNRemote *RMNRemoteCallerSession) Owner() (common.Address, error) { + return _RMNRemote.Contract.Owner(&_RMNRemote.CallOpts) +} + +func (_RMNRemote *RMNRemoteCaller) TypeAndVersion(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _RMNRemote.contract.Call(opts, &out, "typeAndVersion") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +func (_RMNRemote *RMNRemoteSession) TypeAndVersion() (string, error) { + return _RMNRemote.Contract.TypeAndVersion(&_RMNRemote.CallOpts) +} + +func (_RMNRemote *RMNRemoteCallerSession) TypeAndVersion() (string, error) { + return _RMNRemote.Contract.TypeAndVersion(&_RMNRemote.CallOpts) +} + +func (_RMNRemote *RMNRemoteCaller) Verify(opts *bind.CallOpts, destLaneUpdates []InternalMerkleRoot, signatures []IRMNV2Signature) error { + var out []interface{} + err := _RMNRemote.contract.Call(opts, &out, "verify", destLaneUpdates, signatures) + + if err != nil { + return err + } + + return err + +} + +func (_RMNRemote *RMNRemoteSession) Verify(destLaneUpdates []InternalMerkleRoot, signatures []IRMNV2Signature) error { + return _RMNRemote.Contract.Verify(&_RMNRemote.CallOpts, destLaneUpdates, signatures) +} + +func (_RMNRemote *RMNRemoteCallerSession) Verify(destLaneUpdates []InternalMerkleRoot, signatures []IRMNV2Signature) error { + return _RMNRemote.Contract.Verify(&_RMNRemote.CallOpts, destLaneUpdates, signatures) +} + +func (_RMNRemote *RMNRemoteTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _RMNRemote.contract.Transact(opts, "acceptOwnership") +} + +func (_RMNRemote *RMNRemoteSession) AcceptOwnership() (*types.Transaction, error) { + return _RMNRemote.Contract.AcceptOwnership(&_RMNRemote.TransactOpts) +} + +func (_RMNRemote *RMNRemoteTransactorSession) AcceptOwnership() (*types.Transaction, error) { + return _RMNRemote.Contract.AcceptOwnership(&_RMNRemote.TransactOpts) +} + +func (_RMNRemote *RMNRemoteTransactor) SetConfig(opts *bind.TransactOpts, newConfig RMNRemoteConfig) (*types.Transaction, error) { + return _RMNRemote.contract.Transact(opts, "setConfig", newConfig) +} + +func (_RMNRemote *RMNRemoteSession) SetConfig(newConfig RMNRemoteConfig) (*types.Transaction, error) { + return _RMNRemote.Contract.SetConfig(&_RMNRemote.TransactOpts, newConfig) +} + +func (_RMNRemote *RMNRemoteTransactorSession) SetConfig(newConfig RMNRemoteConfig) (*types.Transaction, error) { + return _RMNRemote.Contract.SetConfig(&_RMNRemote.TransactOpts, newConfig) +} + +func (_RMNRemote *RMNRemoteTransactor) Test(opts *bind.TransactOpts) (*types.Transaction, error) { + return _RMNRemote.contract.Transact(opts, "test") +} + +func (_RMNRemote *RMNRemoteSession) Test() (*types.Transaction, error) { + return _RMNRemote.Contract.Test(&_RMNRemote.TransactOpts) +} + +func (_RMNRemote *RMNRemoteTransactorSession) Test() (*types.Transaction, error) { + return _RMNRemote.Contract.Test(&_RMNRemote.TransactOpts) +} + +func (_RMNRemote *RMNRemoteTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { + return _RMNRemote.contract.Transact(opts, "transferOwnership", to) +} + +func (_RMNRemote *RMNRemoteSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _RMNRemote.Contract.TransferOwnership(&_RMNRemote.TransactOpts, to) +} + +func (_RMNRemote *RMNRemoteTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _RMNRemote.Contract.TransferOwnership(&_RMNRemote.TransactOpts, to) +} + +type RMNRemoteConfigSetIterator struct { + Event *RMNRemoteConfigSet + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *RMNRemoteConfigSetIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(RMNRemoteConfigSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(RMNRemoteConfigSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *RMNRemoteConfigSetIterator) Error() error { + return it.fail +} + +func (it *RMNRemoteConfigSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type RMNRemoteConfigSet struct { + VersionedConfig RMNRemoteVersionedConfig + Raw types.Log +} + +func (_RMNRemote *RMNRemoteFilterer) FilterConfigSet(opts *bind.FilterOpts) (*RMNRemoteConfigSetIterator, error) { + + logs, sub, err := _RMNRemote.contract.FilterLogs(opts, "ConfigSet") + if err != nil { + return nil, err + } + return &RMNRemoteConfigSetIterator{contract: _RMNRemote.contract, event: "ConfigSet", logs: logs, sub: sub}, nil +} + +func (_RMNRemote *RMNRemoteFilterer) WatchConfigSet(opts *bind.WatchOpts, sink chan<- *RMNRemoteConfigSet) (event.Subscription, error) { + + logs, sub, err := _RMNRemote.contract.WatchLogs(opts, "ConfigSet") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(RMNRemoteConfigSet) + if err := _RMNRemote.contract.UnpackLog(event, "ConfigSet", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_RMNRemote *RMNRemoteFilterer) ParseConfigSet(log types.Log) (*RMNRemoteConfigSet, error) { + event := new(RMNRemoteConfigSet) + if err := _RMNRemote.contract.UnpackLog(event, "ConfigSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type RMNRemoteOwnershipTransferRequestedIterator struct { + Event *RMNRemoteOwnershipTransferRequested + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *RMNRemoteOwnershipTransferRequestedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(RMNRemoteOwnershipTransferRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(RMNRemoteOwnershipTransferRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *RMNRemoteOwnershipTransferRequestedIterator) Error() error { + return it.fail +} + +func (it *RMNRemoteOwnershipTransferRequestedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type RMNRemoteOwnershipTransferRequested struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_RMNRemote *RMNRemoteFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*RMNRemoteOwnershipTransferRequestedIterator, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _RMNRemote.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + if err != nil { + return nil, err + } + return &RMNRemoteOwnershipTransferRequestedIterator{contract: _RMNRemote.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil +} + +func (_RMNRemote *RMNRemoteFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *RMNRemoteOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _RMNRemote.contract.WatchLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(RMNRemoteOwnershipTransferRequested) + if err := _RMNRemote.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_RMNRemote *RMNRemoteFilterer) ParseOwnershipTransferRequested(log types.Log) (*RMNRemoteOwnershipTransferRequested, error) { + event := new(RMNRemoteOwnershipTransferRequested) + if err := _RMNRemote.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type RMNRemoteOwnershipTransferredIterator struct { + Event *RMNRemoteOwnershipTransferred + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *RMNRemoteOwnershipTransferredIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(RMNRemoteOwnershipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(RMNRemoteOwnershipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *RMNRemoteOwnershipTransferredIterator) Error() error { + return it.fail +} + +func (it *RMNRemoteOwnershipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type RMNRemoteOwnershipTransferred struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_RMNRemote *RMNRemoteFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*RMNRemoteOwnershipTransferredIterator, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _RMNRemote.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) + if err != nil { + return nil, err + } + return &RMNRemoteOwnershipTransferredIterator{contract: _RMNRemote.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil +} + +func (_RMNRemote *RMNRemoteFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *RMNRemoteOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _RMNRemote.contract.WatchLogs(opts, "OwnershipTransferred", fromRule, toRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(RMNRemoteOwnershipTransferred) + if err := _RMNRemote.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_RMNRemote *RMNRemoteFilterer) ParseOwnershipTransferred(log types.Log) (*RMNRemoteOwnershipTransferred, error) { + event := new(RMNRemoteOwnershipTransferred) + if err := _RMNRemote.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +func (_RMNRemote *RMNRemote) ParseLog(log types.Log) (generated.AbigenLog, error) { + switch log.Topics[0] { + case _RMNRemote.abi.Events["ConfigSet"].ID: + return _RMNRemote.ParseConfigSet(log) + case _RMNRemote.abi.Events["OwnershipTransferRequested"].ID: + return _RMNRemote.ParseOwnershipTransferRequested(log) + case _RMNRemote.abi.Events["OwnershipTransferred"].ID: + return _RMNRemote.ParseOwnershipTransferred(log) + + default: + return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) + } +} + +func (RMNRemoteConfigSet) Topic() common.Hash { + return common.HexToHash("0x6cc65868ae41a007e6c3ed18ce591c123dd4e5864b421888c68ce92dae98cea4") +} + +func (RMNRemoteOwnershipTransferRequested) Topic() common.Hash { + return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") +} + +func (RMNRemoteOwnershipTransferred) Topic() common.Hash { + return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") +} + +func (_RMNRemote *RMNRemote) Address() common.Address { + return _RMNRemote.address +} + +type RMNRemoteInterface interface { + GetVersionedConfig(opts *bind.CallOpts) (RMNRemoteVersionedConfig, error) + + IsCursed(opts *bind.CallOpts, subject [16]byte) (bool, error) + + IsCursed0(opts *bind.CallOpts) (bool, error) + + Owner(opts *bind.CallOpts) (common.Address, error) + + TypeAndVersion(opts *bind.CallOpts) (string, error) + + Verify(opts *bind.CallOpts, destLaneUpdates []InternalMerkleRoot, signatures []IRMNV2Signature) error + + AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) + + SetConfig(opts *bind.TransactOpts, newConfig RMNRemoteConfig) (*types.Transaction, error) + + Test(opts *bind.TransactOpts) (*types.Transaction, error) + + TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) + + FilterConfigSet(opts *bind.FilterOpts) (*RMNRemoteConfigSetIterator, error) + + WatchConfigSet(opts *bind.WatchOpts, sink chan<- *RMNRemoteConfigSet) (event.Subscription, error) + + ParseConfigSet(log types.Log) (*RMNRemoteConfigSet, error) + + FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*RMNRemoteOwnershipTransferRequestedIterator, error) + + WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *RMNRemoteOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferRequested(log types.Log) (*RMNRemoteOwnershipTransferRequested, error) + + FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*RMNRemoteOwnershipTransferredIterator, error) + + WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *RMNRemoteOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferred(log types.Log) (*RMNRemoteOwnershipTransferred, error) + + ParseLog(log types.Log) (generated.AbigenLog, error) + + Address() common.Address +} diff --git a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt index 055c0874ba..e64f3f38f8 100644 --- a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -5,7 +5,7 @@ burn_mint_token_pool_and_proxy: ../../../contracts/solc/v0.8.24/BurnMintTokenPoo burn_with_from_mint_token_pool: ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.abi ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.bin 6333d0314d0bd29e75ea5e05fe62a4516ade0c6db91c30b6f93645035db52ed8 burn_with_from_mint_token_pool_and_proxy: ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPoolAndProxy/BurnWithFromMintTokenPoolAndProxy.abi ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPoolAndProxy/BurnWithFromMintTokenPoolAndProxy.bin 08ed1235dda921ce8841b26aa18d0c0f36db4884779dd7670857159801b6d597 ccip_config: ../../../contracts/solc/v0.8.24/CCIPConfig/CCIPConfig.abi ../../../contracts/solc/v0.8.24/CCIPConfig/CCIPConfig.bin 75955a3dcfd66b308be07eda54d6036cc79e87d3cdcf3c5c3115813c55912af8 -ccip_reader_tester: ../../../contracts/solc/v0.8.24/CCIPReaderTester/CCIPReaderTester.abi ../../../contracts/solc/v0.8.24/CCIPReaderTester/CCIPReaderTester.bin d8d70fe111bacc7702c7c263f8c4733dcb2fff77e52c9f60c30d303731bc97c1 +ccip_reader_tester: ../../../contracts/solc/v0.8.24/CCIPReaderTester/CCIPReaderTester.abi ../../../contracts/solc/v0.8.24/CCIPReaderTester/CCIPReaderTester.bin 9e21d63b5a3ea8776dbfa068effcb70e77d3fcc44bc6af3a6a6870f5c4bfe212 commit_store: ../../../contracts/solc/v0.8.24/CommitStore/CommitStore.abi ../../../contracts/solc/v0.8.24/CommitStore/CommitStore.bin 274d87db70b643e00ab0a7e7845bb4b791f3b613bfc87708d33fc5a8369e2a41 commit_store_helper: ../../../contracts/solc/v0.8.24/CommitStoreHelper/CommitStoreHelper.abi ../../../contracts/solc/v0.8.24/CommitStoreHelper/CommitStoreHelper.bin f7128dcc2ee6dbcbc976288abcc16970ffb19b59412c5202ef6b259d2007f801 ether_sender_receiver: ../../../contracts/solc/v0.8.24/EtherSenderReceiver/EtherSenderReceiver.abi ../../../contracts/solc/v0.8.24/EtherSenderReceiver/EtherSenderReceiver.bin 09510a3f773f108a3c231e8d202835c845ded862d071ec54c4f89c12d868b8de @@ -23,14 +23,15 @@ multi_aggregate_rate_limiter: ../../../contracts/solc/v0.8.24/MultiAggregateRate multi_ocr3_helper: ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Helper.abi ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Helper.bin 6b56e0114a4d50797d30a34aecc2641ef340451d0c3fcb9d729bba4df2435122 nonce_manager: ../../../contracts/solc/v0.8.24/NonceManager/NonceManager.abi ../../../contracts/solc/v0.8.24/NonceManager/NonceManager.bin 6f64e1083b356c06ee66b9138e398b9c97a4cd3e8c9ec38cf3010cebc79af536 ocr3_config_encoder: ../../../contracts/solc/v0.8.24/IOCR3ConfigEncoder/IOCR3ConfigEncoder.abi ../../../contracts/solc/v0.8.24/IOCR3ConfigEncoder/IOCR3ConfigEncoder.bin 9254b35a86f00fde7b7193a033ca58f6521a66e87b9cf9da6ce5660082e79f5d -offramp: ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.abi ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.bin 136ae93018723f03d695f60348231d58cacf53e4de2016fa6e638eba7bd64af7 -onramp: ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.abi ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.bin c3b345930e1a553b18553e18a5c0ff8df3c372118fdf78a176aaccb1891664bb +offramp: ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.abi ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.bin a97246b6e73f0ac7bea5677b8bb536a085280effc3c110cd4859a93ceed474af +onramp: ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.abi ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.bin c37096aaa0369ad988e94c300ba62917e17fcc71a3c1aa3e9b8420f21c0591d2 ping_pong_demo: ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.abi ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.bin c1c2f8a65c7ffd971899cae7fe62f2da57d09e936151e2b92163c4bebe699d6b price_registry: ../../../contracts/solc/v0.8.24/PriceRegistry/PriceRegistry.abi ../../../contracts/solc/v0.8.24/PriceRegistry/PriceRegistry.bin e7781d600c1bb7aa4620106af7f6e146a109b97f4cb6a7d06c9e15773340ecb2 registry_module_owner_custom: ../../../contracts/solc/v0.8.24/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.abi ../../../contracts/solc/v0.8.24/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.bin 75be86323c227917a9bbc3f799d7ed02f92db546653a36db30ed0ebe64461353 -report_codec: ../../../contracts/solc/v0.8.24/ReportCodec/ReportCodec.abi ../../../contracts/solc/v0.8.24/ReportCodec/ReportCodec.bin 3d7ebd8d4563b63cec83b141fe9f9ef5d8ab12a7c23ccd5e7e3434aba3cab66a +report_codec: ../../../contracts/solc/v0.8.24/ReportCodec/ReportCodec.abi ../../../contracts/solc/v0.8.24/ReportCodec/ReportCodec.bin 4b9252c443c87ceb7f5ac3b9d100e572fead010f7c39543315052677a3a2c597 rmn_contract: ../../../contracts/solc/v0.8.24/RMN/RMN.abi ../../../contracts/solc/v0.8.24/RMN/RMN.bin 8b45b0fb08631c6b582fd3c0b4052a79cc2b4e091e6286af1ab131bef63661f9 rmn_proxy_contract: ../../../contracts/solc/v0.8.24/ARMProxy/ARMProxy.abi ../../../contracts/solc/v0.8.24/ARMProxy/ARMProxy.bin b048d8e752e3c41113ebb305c1efa06737ad36b4907b93e627fb0a3113023454 +rmn_remote: ../../../contracts/solc/v0.8.24/RMNRemote/RMNRemote.abi ../../../contracts/solc/v0.8.24/RMNRemote/RMNRemote.bin be6840d9646195c37f6fa3f95e1cb67218d04d2cebf72e698377b0a7b9cd76f4 router: ../../../contracts/solc/v0.8.24/Router/Router.abi ../../../contracts/solc/v0.8.24/Router/Router.bin 2e4f0a7826c8abb49d882bb49fc5ff20a186dbd3137624b9097ffed903ae4888 self_funded_ping_pong: ../../../contracts/solc/v0.8.24/SelfFundedPingPong/SelfFundedPingPong.abi ../../../contracts/solc/v0.8.24/SelfFundedPingPong/SelfFundedPingPong.bin 8ea5d75dbc3f8afd90d22c4a665a94e02892259cd16520c1c6b4cf0dc80c9148 token_admin_registry: ../../../contracts/solc/v0.8.24/TokenAdminRegistry/TokenAdminRegistry.abi ../../../contracts/solc/v0.8.24/TokenAdminRegistry/TokenAdminRegistry.bin 942be7d1681ac102e0615bee13f76838ebb0b261697cf1270d2bf82c12e57aeb diff --git a/core/gethwrappers/ccip/go_generate.go b/core/gethwrappers/ccip/go_generate.go index 5c316af1ac..ba51fe13fc 100644 --- a/core/gethwrappers/ccip/go_generate.go +++ b/core/gethwrappers/ccip/go_generate.go @@ -12,6 +12,7 @@ package ccip //go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.abi ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.bin OnRamp onramp //go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/EVM2EVMOffRamp/EVM2EVMOffRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMOffRamp/EVM2EVMOffRamp.bin EVM2EVMOffRamp evm_2_evm_offramp //go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.abi ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.bin OffRamp offramp +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/RMNRemote/RMNRemote.abi ../../../contracts/solc/v0.8.24/RMNRemote/RMNRemote.bin RMNRemote rmn_remote //go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/MultiAggregateRateLimiter/MultiAggregateRateLimiter.abi ../../../contracts/solc/v0.8.24/MultiAggregateRateLimiter/MultiAggregateRateLimiter.bin MultiAggregateRateLimiter multi_aggregate_rate_limiter //go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/Router/Router.abi ../../../contracts/solc/v0.8.24/Router/Router.bin Router router //go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/FeeQuoter/FeeQuoter.abi ../../../contracts/solc/v0.8.24/FeeQuoter/FeeQuoter.bin FeeQuoter fee_quoter From 53057b1e96d14011003c51bb1f1a54dc1fe0e7db Mon Sep 17 00:00:00 2001 From: Makram Date: Thu, 5 Sep 2024 14:21:02 +0300 Subject: [PATCH 073/115] contracts/scripts: reduce offramp optimizations (#1414) ## Motivation The offramp was failing to deploy due to too many optimizations causing a max code size exceeded error. ## Solution Reduce the number of optimizations by 1. Also, add a test that deploys v1.6 contracts and ensures that they are deployable on the simulated backend. --- .../scripts/native_solc_compile_all_ccip | 2 +- .../ccip/deployment_test/deployment_test.go | 97 +++++++++++++++++++ .../ccip/generated/offramp/offramp.go | 2 +- ...rapper-dependency-versions-do-not-edit.txt | 2 +- 4 files changed, 100 insertions(+), 3 deletions(-) create mode 100644 core/gethwrappers/ccip/deployment_test/deployment_test.go diff --git a/contracts/scripts/native_solc_compile_all_ccip b/contracts/scripts/native_solc_compile_all_ccip index 2e72a72a22..64fcd9f435 100755 --- a/contracts/scripts/native_solc_compile_all_ccip +++ b/contracts/scripts/native_solc_compile_all_ccip @@ -10,7 +10,7 @@ SOLC_VERSION="0.8.24" OPTIMIZE_RUNS=26000 OPTIMIZE_RUNS_OFFRAMP=18000 OPTIMIZE_RUNS_ONRAMP=4100 -OPTIMIZE_RUNS_MULTI_OFFRAMP=2000 +OPTIMIZE_RUNS_MULTI_OFFRAMP=1999 SCRIPTPATH="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" diff --git a/core/gethwrappers/ccip/deployment_test/deployment_test.go b/core/gethwrappers/ccip/deployment_test/deployment_test.go new file mode 100644 index 0000000000..c89ca23917 --- /dev/null +++ b/core/gethwrappers/ccip/deployment_test/deployment_test.go @@ -0,0 +1,97 @@ +package deploymenttest + +import ( + "math/big" + "testing" + "time" + + "github.com/ethereum/go-ethereum/accounts/abi/bind/backends" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/fee_quoter" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/nonce_manager" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/offramp" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/onramp" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/token_admin_registry" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" +) + +// This tests ensures that all of the compiled contracts can be +// deployed to an actual blockchain (i.e no "max code size exceeded" errors). +// It does not attempt to correctly set up the contracts, so bogus inputs are used. +func TestDeployAllV1_6(t *testing.T) { + owner := testutils.MustNewSimTransactor(t) + chain := backends.NewSimulatedBackend(core.GenesisAlloc{ + owner.From: {Balance: assets.Ether(100).ToInt()}, + }, 30e6) + + // router + _, _, _, err := router.DeployRouter(owner, chain, common.HexToAddress("0x1"), common.HexToAddress("0x2")) + require.NoError(t, err) + chain.Commit() + + // nonce manager + _, _, _, err = nonce_manager.DeployNonceManager(owner, chain, []common.Address{common.HexToAddress("0x1")}) + require.NoError(t, err) + chain.Commit() + + // offramp + _, _, _, err = offramp.DeployOffRamp(owner, chain, offramp.OffRampStaticConfig{ + ChainSelector: 1, + Rmn: common.HexToAddress("0x1"), + TokenAdminRegistry: common.HexToAddress("0x2"), + NonceManager: common.HexToAddress("0x3"), + }, offramp.OffRampDynamicConfig{ + FeeQuoter: common.HexToAddress("0x4"), + PermissionLessExecutionThresholdSeconds: uint32((8 * time.Hour).Seconds()), + MaxTokenTransferGas: 50_000, + MaxPoolReleaseOrMintGas: 50_000, + MessageValidator: common.HexToAddress("0x5"), + }, nil) + require.NoError(t, err) + chain.Commit() + + // onramp + _, _, _, err = onramp.DeployOnRamp(owner, chain, onramp.OnRampStaticConfig{ + ChainSelector: 1, + Rmn: common.HexToAddress("0x1"), + NonceManager: common.HexToAddress("0x2"), + TokenAdminRegistry: common.HexToAddress("0x3"), + }, onramp.OnRampDynamicConfig{ + FeeQuoter: common.HexToAddress("0x4"), + MessageValidator: common.HexToAddress("0x5"), + FeeAggregator: common.HexToAddress("0x6"), + AllowListAdmin: common.HexToAddress("0x7"), + }, nil) + require.NoError(t, err) + chain.Commit() + + // fee quoter + _, _, _, err = fee_quoter.DeployFeeQuoter( + owner, + chain, + fee_quoter.FeeQuoterStaticConfig{ + MaxFeeJuelsPerMsg: big.NewInt(1e18), + LinkToken: common.HexToAddress("0x1"), + StalenessThreshold: 10, + }, + []common.Address{common.HexToAddress("0x1")}, + []common.Address{common.HexToAddress("0x2")}, + []fee_quoter.FeeQuoterTokenPriceFeedUpdate{}, + []fee_quoter.FeeQuoterTokenTransferFeeConfigArgs{}, + []fee_quoter.FeeQuoterPremiumMultiplierWeiPerEthArgs{}, + []fee_quoter.FeeQuoterDestChainConfigArgs{}) + require.NoError(t, err) + chain.Commit() + + // token admin registry + _, _, _, err = token_admin_registry.DeployTokenAdminRegistry(owner, chain) + require.NoError(t, err) + chain.Commit() + + // TODO: add rmn home and rmn remote +} diff --git a/core/gethwrappers/ccip/generated/offramp/offramp.go b/core/gethwrappers/ccip/generated/offramp/offramp.go index df4d1124d8..51edddf954 100644 --- a/core/gethwrappers/ccip/generated/offramp/offramp.go +++ b/core/gethwrappers/ccip/generated/offramp/offramp.go @@ -163,7 +163,7 @@ type OffRampStaticConfig struct { var OffRampMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CanOnlySelfCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"actual\",\"type\":\"bytes32\"}],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ExecutionError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"ForkedChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enumMultiOCR3Base.InvalidConfigErrorType\",\"name\":\"errorType\",\"type\":\"uint8\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"got\",\"type\":\"uint256\"}],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidEVMAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"name\":\"InvalidInterval\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"newLimit\",\"type\":\"uint256\"}],\"name\":\"InvalidManualExecutionGasLimit\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"messageDestChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidMessageDestChainSelector\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"newState\",\"type\":\"uint8\"}],\"name\":\"InvalidNewState\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRoot\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidStaticConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LeavesCannotBeEmpty\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ManualExecutionGasLimitMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"ManualExecutionNotYetEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"errorReason\",\"type\":\"bytes\"}],\"name\":\"MessageValidationError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonUniqueSignatures\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"notPool\",\"type\":\"address\"}],\"name\":\"NotACompatiblePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OracleCannotBeZeroAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ReceiverError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountReleased\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePre\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePost\",\"type\":\"uint256\"}],\"name\":\"ReleaseOrMintBalanceMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"name\":\"RootAlreadyCommitted\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"RootNotCommitted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignaturesOutOfRegistration\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"StaleCommitReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"StaticConfigCannotBeChanged\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"TokenDataMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"TokenHandlingError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnexpectedTokenData\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"WrongMessageLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WrongNumberOfSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroChainSelectorNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"AlreadyAttempted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"structIRMNV2.Signature[]\",\"name\":\"rmnSignatures\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"report\",\"type\":\"tuple\"}],\"name\":\"CommitReportAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"DynamicConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"messageHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"name\":\"ExecutionStateChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"RootRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"SkippedAlreadyExecutedMessage\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SkippedReportExecution\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"sourceConfig\",\"type\":\"tuple\"}],\"name\":\"SourceChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainSelectorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"}],\"name\":\"StaticConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigUpdates\",\"type\":\"tuple[]\"}],\"name\":\"applySourceChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"destTokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structClient.Any2EVMMessage\",\"name\":\"\",\"type\":\"tuple\"}],\"name\":\"ccipReceive\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"rawVs\",\"type\":\"bytes32\"}],\"name\":\"commit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"execute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"bytes[]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[]\"}],\"name\":\"executeSingleMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"getExecutionState\",\"outputs\":[{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLatestPriceSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"getMerkleRoot\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"getSourceChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"latestConfigDetails\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"n\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"}],\"internalType\":\"structMultiOCR3Base.ConfigInfo\",\"name\":\"configInfo\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfig\",\"name\":\"ocrConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage[]\",\"name\":\"messages\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[][]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[][]\"},{\"internalType\":\"bytes32[]\",\"name\":\"proofs\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"proofFlagBits\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.ExecutionReportSingleChain[]\",\"name\":\"reports\",\"type\":\"tuple[]\"},{\"internalType\":\"uint256[][]\",\"name\":\"gasLimitOverrides\",\"type\":\"uint256[][]\"}],\"name\":\"manuallyExecute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"setDynamicConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfigArgs[]\",\"name\":\"ocrConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"setOCR3Configs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x6101206040523480156200001257600080fd5b5060405162006c6538038062006c658339810160408190526200003591620008c7565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf81620001fa565b5050466080525060208301516001600160a01b03161580620000ec575060408301516001600160a01b0316155b8062000103575060608301516001600160a01b0316155b1562000122576040516342bcdf7f60e11b815260040160405180910390fd5b82516001600160401b03166000036200014e5760405163c656089560e01b815260040160405180910390fd5b82516001600160401b0390811660a052602080850180516001600160a01b0390811660c05260408088018051831660e0526060808a01805185166101005283518b519098168852945184169587019590955251821690850152905116908201527f683eb52ee924eb817377cfa8f41f238f4bb7a877da5267869dfffbad85f564d89060800160405180910390a1620001e682620002a5565b620001f181620003c1565b50505062000c67565b336001600160a01b03821603620002545760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b0316620002ce576040516342bcdf7f60e11b815260040160405180910390fd5b80516004805460208085018051604080880180516060808b0180516001600160a01b039b8c166001600160c01b0319909a168a17600160a01b63ffffffff98891602176001600160c01b0316600160c01b948816949094026001600160e01b031693909317600160e01b93871693909302929092179098556080808b018051600580546001600160a01b031916918d169190911790558451988952955185169688019690965290518316918601919091525116938301939093529151909216908201527fa55bd56595c45f517e5967a3067f3dca684445a3080e7c04a4e0d5a40cda627d9060a00160405180910390a150565b60005b815181101562000666576000828281518110620003e557620003e562000a1d565b60200260200101519050600081602001519050806001600160401b0316600003620004235760405163c656089560e01b815260040160405180910390fd5b81516001600160a01b03166200044c576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160401b0381166000908152600660205260408120600181018054919291620004789062000a33565b80601f0160208091040260200160405190810160405280929190818152602001828054620004a69062000a33565b8015620004f75780601f10620004cb57610100808354040283529160200191620004f7565b820191906000526020600020905b815481529060010190602001808311620004d957829003601f168201915b5050505050905060008460600151905081516000036200059e57805160000362000534576040516342bcdf7f60e11b815260040160405180910390fd5b6001830162000544828262000ac4565b508254600160a81b600160e81b031916600160a81b1783556040516001600160401b03851681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1620005d9565b8080519060200120828051906020012014620005d95760405163c39a620560e01b81526001600160401b038516600482015260240162000083565b604080860151845487516001600160a01b03166001600160a01b0319921515600160a01b02929092166001600160a81b031990911617178455516001600160401b038516907f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b906200064d90869062000b90565b60405180910390a25050505050806001019050620003c4565b5050565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b0381118282101715620006a557620006a56200066a565b60405290565b604051601f8201601f191681016001600160401b0381118282101715620006d657620006d66200066a565b604052919050565b80516001600160401b0381168114620006f657600080fd5b919050565b6001600160a01b03811681146200071157600080fd5b50565b805163ffffffff81168114620006f657600080fd5b6000601f83601f8401126200073d57600080fd5b825160206001600160401b03808311156200075c576200075c6200066a565b8260051b6200076d838201620006ab565b93845286810183019383810190898611156200078857600080fd5b84890192505b85831015620008ba57825184811115620007a85760008081fd5b89016080601f19828d038101821315620007c25760008081fd5b620007cc62000680565b88840151620007db81620006fb565b81526040620007ec858201620006de565b8a8301526060808601518015158114620008065760008081fd5b838301529385015193898511156200081e5760008081fd5b84860195508f603f8701126200083657600094508485fd5b8a8601519450898511156200084f576200084f6200066a565b620008608b858f88011601620006ab565b93508484528f82868801011115620008785760008081fd5b60005b8581101562000898578681018301518582018d01528b016200087b565b5060009484018b0194909452509182015283525091840191908401906200078e565b9998505050505050505050565b6000806000838503610140811215620008df57600080fd5b6080811215620008ee57600080fd5b620008f862000680565b6200090386620006de565b815260208601516200091581620006fb565b602082015260408601516200092a81620006fb565b604082015260608601516200093f81620006fb565b6060820152935060a0607f19820112156200095957600080fd5b5060405160a081016001600160401b0380821183831017156200098057620009806200066a565b81604052608087015191506200099682620006fb565b818352620009a760a0880162000714565b6020840152620009ba60c0880162000714565b6040840152620009cd60e0880162000714565b60608401526101008701519150620009e582620006fb565b608083018290526101208701519294508083111562000a0357600080fd5b505062000a138682870162000729565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b600181811c9082168062000a4857607f821691505b60208210810362000a6957634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111562000abf576000816000526020600020601f850160051c8101602086101562000a9a5750805b601f850160051c820191505b8181101562000abb5782815560010162000aa6565b5050505b505050565b81516001600160401b0381111562000ae05762000ae06200066a565b62000af88162000af1845462000a33565b8462000a6f565b602080601f83116001811462000b30576000841562000b175750858301515b600019600386901b1c1916600185901b17855562000abb565b600085815260208120601f198616915b8281101562000b615788860151825594840194600190910190840162000b40565b508582101562000b805787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b602080825282546001600160a01b0381168383015260a081901c60ff161515604084015260a81c6001600160401b0316606083015260808083015260018084018054600093929190849062000be58162000a33565b8060a089015260c0600183166000811462000c09576001811462000c265762000c58565b60ff19841660c08b015260c083151560051b8b0101945062000c58565b85600052602060002060005b8481101562000c4f5781548c820185015290880190890162000c32565b8b0160c0019550505b50929998505050505050505050565b60805160a05160c05160e05161010051615f8862000cdd600039600081816102400152612a1a0152600081816102110152612f0e0152600081816101e20152818161077f01528181610986015261240c0152600081816101b201526126990152600081816117dd01526118290152615f886000f3fe608060405234801561001057600080fd5b50600436106101515760003560e01c806379ba5097116100cd578063c673e58411610081578063e9d68a8e11610066578063e9d68a8e1461052a578063f2fde38b1461054a578063f716f99f1461055d57600080fd5b8063c673e584146104c5578063ccd37ba3146104e557600080fd5b80638da5cb5b116100b25780638da5cb5b14610484578063991a50181461049f578063a80036b4146104b257600080fd5b806379ba50971461046e57806385572ffb1461047657600080fd5b80632d04ab76116101245780633f4b04aa116101095780633f4b04aa146103365780635e36480c146103525780637437ff9f1461037257600080fd5b80632d04ab7614610310578063311cd5131461032357600080fd5b806304666f9c1461015657806305d938b51461016b57806306285c691461017e578063181f5a77146102c7575b600080fd5b610169610164366004614086565b610570565b005b610169610179366004614712565b610584565b61027060408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316815250905090565b6040516102be9190815167ffffffffffffffff1681526020808301516001600160a01b0390811691830191909152604080840151821690830152606092830151169181019190915260800190565b60405180910390f35b6103036040518060400160405280601181526020017f4f666652616d7020312e362e302d64657600000000000000000000000000000081525081565b6040516102be919061488d565b61016961031e366004614938565b610729565b6101696103313660046149eb565b610cc1565b60095460405167ffffffffffffffff90911681526020016102be565b610365610360366004614a3f565b610d2a565b6040516102be9190614a9c565b6104116040805160a081018252600080825260208201819052918101829052606081018290526080810191909152506040805160a0810182526004546001600160a01b03808216835263ffffffff600160a01b83048116602085015278010000000000000000000000000000000000000000000000008304811694840194909452600160e01b9091049092166060820152600554909116608082015290565b6040516102be9190600060a0820190506001600160a01b03808451168352602084015163ffffffff808216602086015280604087015116604086015280606087015116606086015250508060808501511660808401525092915050565b610169610d80565b610169610151366004614aaa565b6000546040516001600160a01b0390911681526020016102be565b6101696104ad366004614af9565b610e3e565b6101696104c0366004614b6d565b610e4f565b6104d86104d3366004614bda565b6111c2565b6040516102be9190614c3a565b61051c6104f3366004614caf565b67ffffffffffffffff919091166000908152600860209081526040808320938352929052205490565b6040519081526020016102be565b61053d610538366004614cd9565b611320565b6040516102be9190614cf4565b610169610558366004614d42565b61142d565b61016961056b366004614dc7565b61143e565b610578611480565b610581816114dc565b50565b61058c6117da565b8151815181146105c8576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b818110156107195760008482815181106105e7576105e7614f05565b6020026020010151905060008160200151519050600085848151811061060f5761060f614f05565b6020026020010151905080518214610653576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8281101561070a57600082828151811061067257610672614f05565b6020026020010151905080600014610701578460200151828151811061069a5761069a614f05565b6020026020010151608001518110156107015784516040517fc8e9605100000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260248101839052604481018290526064015b60405180910390fd5b50600101610656565b505050508060010190506105cb565b50610724838361185b565b505050565b600061073787890189615138565b602081015151909150156107e357602081015160408083015190517f30dfc3080000000000000000000000000000000000000000000000000000000081526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016926330dfc308926107b29260040161539c565b60006040518083038186803b1580156107ca57600080fd5b505afa1580156107de573d6000803e3d6000fd5b505050505b805151511515806107f957508051602001515115155b156108f95760095460208a01359067ffffffffffffffff808316911610156108b8576009805467ffffffffffffffff191667ffffffffffffffff83161790556004805483516040517f3937306f0000000000000000000000000000000000000000000000000000000081526001600160a01b0390921692633937306f9261088192910161547e565b600060405180830381600087803b15801561089b57600080fd5b505af11580156108af573d6000803e3d6000fd5b505050506108f7565b8160200151516000036108f7576040517f2261116700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b60005b816020015151811015610c0a5760008260200151828151811061092157610921614f05565b602090810291909101015180516040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815277ffffffffffffffff00000000000000000000000000000000608083901b166004820152919250906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632cbc26bb90602401602060405180830381865afa1580156109cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109f19190615491565b15610a34576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff821660048201526024016106f8565b6000610a3f8261190b565b6020840151815491925067ffffffffffffffff908116600160a81b90920416141580610a865750826040015167ffffffffffffffff16836020015167ffffffffffffffff16115b15610ae7578251602084015160408086015190517fd5e0f0d600000000000000000000000000000000000000000000000000000000815267ffffffffffffffff938416600482015291831660248301529190911660448201526064016106f8565b606083015180610b23576040517f504570e300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b835167ffffffffffffffff16600090815260086020908152604080832084845290915290205415610b965783516040517f32cf0cbf00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602481018290526044016106f8565b6040840151610ba69060016154c4565b82547fffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffff16600160a81b67ffffffffffffffff9283160217909255925116600090815260086020908152604080832094835293905291909120429055506001016108fc565b507fd7868a16facbdde7b5c020620136316b3c266fffcb4e1e41cb6a662fe14ba3e181604051610c3a91906154ec565b60405180910390a1610cb660008a8a8a8a8a8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808e0282810182019093528d82529093508d92508c9182918501908490808284376000920191909152508b9250611972915050565b505050505050505050565b610d01610cd082840184615544565b6040805160008082526020820190925290610cfb565b6060815260200190600190039081610ce65790505b5061185b565b604080516000808252602082019092529050610d24600185858585866000611972565b50505050565b6000610d3860016004615579565b6002610d456080856155a2565b67ffffffffffffffff16610d5991906155c9565b610d638585611ce9565b901c166003811115610d7757610d77614a72565b90505b92915050565b6001546001600160a01b03163314610dda5760405162461bcd60e51b815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064016106f8565b600080543373ffffffffffffffffffffffffffffffffffffffff19808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610e46611480565b61058181611d30565b333014610e88576040517f371a732800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160008082526020820190925281610ec5565b6040805180820190915260008082526020820152815260200190600190039081610e9e5790505b5060a08501515190915015610ef957610ef68460a00151856020015186606001518760000151602001518787611e96565b90505b6040805160a0810182528551518152855160209081015167ffffffffffffffff1681830152808701518351600094840192610f3592910161488d565b60408051601f19818403018152918152908252878101516020830152018390526005549091506001600160a01b03168015611042576040517f08d450a10000000000000000000000000000000000000000000000000000000081526001600160a01b038216906308d450a190610faf908590600401615682565b600060405180830381600087803b158015610fc957600080fd5b505af1925050508015610fda575060015b611042573d808015611008576040519150601f19603f3d011682016040523d82523d6000602084013e61100d565b606091505b50806040517f09c253250000000000000000000000000000000000000000000000000000000081526004016106f8919061488d565b60408601515115801561105757506080860151155b8061106e575060608601516001600160a01b03163b155b806110ae575060608601516110ac906001600160a01b03167f85572ffb00000000000000000000000000000000000000000000000000000000611fb5565b155b156110bb57505050505050565b855160209081015167ffffffffffffffff1660009081526006909152604080822054608089015160608a015192517f3cf9798300000000000000000000000000000000000000000000000000000000815284936001600160a01b0390931692633cf97983926111339289926113889291600401615695565b6000604051808303816000875af1158015611152573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261117a91908101906156d1565b5091509150816111b857806040517f0a8d6e8c0000000000000000000000000000000000000000000000000000000081526004016106f8919061488d565b5050505050505050565b6112056040805160e081019091526000606082018181526080830182905260a0830182905260c08301919091528190815260200160608152602001606081525090565b60ff808316600090815260026020818152604092839020835160e081018552815460608201908152600183015480881660808401526101008104881660a0840152620100009004909616151560c0820152948552918201805484518184028101840190955280855292938583019390928301828280156112ae57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611290575b505050505081526020016003820180548060200260200160405190810160405280929190818152602001828054801561131057602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116112f2575b5050505050815250509050919050565b604080516080808201835260008083526020808401829052838501829052606080850181905267ffffffffffffffff878116845260068352928690208651948501875280546001600160a01b0381168652600160a01b810460ff16151593860193909352600160a81b9092049092169483019490945260018401805493949293918401916113ad90615767565b80601f01602080910402602001604051908101604052809291908181526020018280546113d990615767565b80156113105780601f106113fb57610100808354040283529160200191611310565b820191906000526020600020905b81548152906001019060200180831161140957505050919092525091949350505050565b611435611480565b61058181611fd1565b611446611480565b60005b815181101561147c5761147482828151811061146757611467614f05565b6020026020010151612087565b600101611449565b5050565b6000546001600160a01b031633146114da5760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016106f8565b565b60005b815181101561147c5760008282815181106114fc576114fc614f05565b602002602001015190506000816020015190508067ffffffffffffffff16600003611553576040517fc656089500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81516001600160a01b031661157b576040516342bcdf7f60e11b815260040160405180910390fd5b67ffffffffffffffff811660009081526006602052604081206001810180549192916115a690615767565b80601f01602080910402602001604051908101604052809291908181526020018280546115d290615767565b801561161f5780601f106115f45761010080835404028352916020019161161f565b820191906000526020600020905b81548152906001019060200180831161160257829003601f168201915b5050505050905060008460600151905081516000036116d757805160000361165a576040516342bcdf7f60e11b815260040160405180910390fd5b6001830161166882826157f1565b5082547fffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffff16600160a81b17835560405167ffffffffffffffff851681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a161172a565b808051906020012082805190602001201461172a576040517fc39a620500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff851660048201526024016106f8565b604080860151845487516001600160a01b031673ffffffffffffffffffffffffffffffffffffffff19921515600160a01b02929092167fffffffffffffffffffffff000000000000000000000000000000000000000000909116171784555167ffffffffffffffff8516907f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b906117c29086906158b1565b60405180910390a250505050508060010190506114df565b467f0000000000000000000000000000000000000000000000000000000000000000146114da576040517f0f01ce850000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060048201524660248201526044016106f8565b8151600003611895576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160408051600080825260208201909252911591905b8451811015611904576118fc8582815181106118ca576118ca614f05565b6020026020010151846118f6578583815181106118e9576118e9614f05565b60200260200101516123b8565b836123b8565b6001016118ac565b5050505050565b67ffffffffffffffff811660009081526006602052604081208054600160a01b900460ff16610d7a576040517fed053c5900000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024016106f8565b60ff878116600090815260026020908152604080832081516080810183528154815260019091015480861693820193909352610100830485169181019190915262010000909104909216151560608301528735906119d18760a461597f565b9050826060015115611a195784516119ea9060206155c9565b86516119f79060206155c9565b611a029060a061597f565b611a0c919061597f565b611a16908261597f565b90505b368114611a5b576040517f8e1192e1000000000000000000000000000000000000000000000000000000008152600481018290523660248201526044016106f8565b5081518114611aa35781516040517f93df584c0000000000000000000000000000000000000000000000000000000081526004810191909152602481018290526044016106f8565b611aab6117da565b60ff808a1660009081526003602090815260408083203384528252808320815180830190925280548086168352939491939092840191610100909104166002811115611af957611af9614a72565b6002811115611b0a57611b0a614a72565b9052509050600281602001516002811115611b2757611b27614a72565b148015611b7b5750600260008b60ff1660ff168152602001908152602001600020600301816000015160ff1681548110611b6357611b63614f05565b6000918252602090912001546001600160a01b031633145b611bb1576040517fda0f08e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50816060015115611c93576020820151611bcc906001615992565b60ff16855114611c08576040517f71253a2500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8351855114611c43576040517fa75d88af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008787604051611c559291906159ab565b604051908190038120611c6c918b906020016159bb565b604051602081830303815290604052805190602001209050611c918a82888888612cc8565b505b6040805182815260208a81013567ffffffffffffffff169082015260ff8b16917f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef0910160405180910390a2505050505050505050565b67ffffffffffffffff8216600090815260076020526040812081611d0e6080856159cf565b67ffffffffffffffff1681526020810191909152604001600020549392505050565b80516001600160a01b0316611d58576040516342bcdf7f60e11b815260040160405180910390fd5b80516004805460208085018051604080880180516060808b0180516001600160a01b039b8c167fffffffffffffffff000000000000000000000000000000000000000000000000909a168a17600160a01b63ffffffff988916021777ffffffffffffffffffffffffffffffffffffffffffffffff167801000000000000000000000000000000000000000000000000948816949094026001600160e01b031693909317600160e01b93871693909302929092179098556080808b0180516005805473ffffffffffffffffffffffffffffffffffffffff1916918d169190911790558451988952955185169688019690965290518316918601919091525116938301939093529151909216908201527fa55bd56595c45f517e5967a3067f3dca684445a3080e7c04a4e0d5a40cda627d9060a00160405180910390a150565b6060865167ffffffffffffffff811115611eb257611eb2613e9d565b604051908082528060200260200182016040528015611ef757816020015b6040805180820190915260008082526020820152815260200190600190039081611ed05790505b50905060005b8751811015611fa957611f84888281518110611f1b57611f1b614f05565b6020026020010151888888888887818110611f3857611f38614f05565b9050602002810190611f4a91906159f6565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612ead92505050565b828281518110611f9657611f96614f05565b6020908102919091010152600101611efd565b505b9695505050505050565b6000611fc083613252565b8015610d775750610d7783836132b6565b336001600160a01b038216036120295760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016106f8565b6001805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b806040015160ff166000036120b2576000604051631b3fab5160e11b81526004016106f89190615a5b565b60208082015160ff8082166000908152600290935260408320600181015492939092839216900361211f57606084015160018201805491151562010000027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff909216919091179055612174565b6060840151600182015460ff6201000090910416151590151514612174576040517f87f6037c00000000000000000000000000000000000000000000000000000000815260ff841660048201526024016106f8565b60a0840151805161010010156121a0576001604051631b3fab5160e11b81526004016106f89190615a5b565b61220684846003018054806020026020016040519081016040528092919081815260200182805480156121fc57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116121de575b5050505050613371565b84606001511561232d5761227484846002018054806020026020016040519081016040528092919081815260200182805480156121fc576020028201919060005260206000209081546001600160a01b031681526001909101906020018083116121de575050505050613371565b6080850151805161010010156122a0576002604051631b3fab5160e11b81526004016106f89190615a5b565b60408601516122b0906003615a75565b60ff168151116122d6576003604051631b3fab5160e11b81526004016106f89190615a5b565b80516001840180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1661010060ff84160217905561231e9060028601906020840190613e16565b5061232b858260016133da565b505b612339848260026133da565b805161234e9060038501906020840190613e16565b5060408581015160018401805460ff191660ff8316179055865180855560a088015192517fab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f547936123a79389939260028a01929190615a91565b60405180910390a16119048461354e565b815181516040517f2cbc26bb000000000000000000000000000000000000000000000000000000008152608083901b77ffffffffffffffff00000000000000000000000000000000166004820152901515907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632cbc26bb90602401602060405180830381865afa15801561245b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061247f9190615491565b1561250b5780156124c8576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff831660048201526024016106f8565b60405167ffffffffffffffff831681527faab522ed53d887e56ed53dd37398a01aeef6a58e0fa77c2173beb9512d8949339060200160405180910390a150505050565b60006125168361190b565b600101805461252490615767565b80601f016020809104026020016040519081016040528092919081815260200182805461255090615767565b801561259d5780601f106125725761010080835404028352916020019161259d565b820191906000526020600020905b81548152906001019060200180831161258057829003601f168201915b505050602088015151929350505060008190036125e5576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8560400151518114612623576040517f57e0e08300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008167ffffffffffffffff81111561263e5761263e613e9d565b604051908082528060200260200182016040528015612667578160200160208202803683370190505b50905060005b828110156127505760008860200151828151811061268d5761268d614f05565b602002602001015190507f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681600001516040015167ffffffffffffffff161461272057805160409081015190517f38432a2200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016106f8565b61272a818661356a565b83838151811061273c5761273c614f05565b60209081029190910101525060010161266d565b50600061276786838a606001518b6080015161368c565b9050806000036127af576040517f7dd17a7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff871660048201526024016106f8565b60005b83811015610cb65760005a905060008a6020015183815181106127d7576127d7614f05565b6020026020010151905060006127f58a836000015160600151610d2a565b9050600081600381111561280b5761280b614a72565b14806128285750600381600381111561282657612826614a72565b145b612880578151606001516040805167ffffffffffffffff808e16825290921660208301527f3b575419319662b2a6f5e2467d84521517a3382b908eb3d557bb3fdb0c50e23c91015b60405180910390a1505050612cc0565b881561295057600454600090600160a01b900463ffffffff166128a38742615579565b11905080806128c3575060038260038111156128c1576128c1614a72565b145b612905576040517fa9cfc86200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8c1660048201526024016106f8565b8b858151811061291757612917614f05565b602002602001015160001461294a578b858151811061293857612938614f05565b60200260200101518360800181815250505b506129b1565b600081600381111561296457612964614a72565b146129b1578151606001516040805167ffffffffffffffff808e16825290921660208301527f3ef2a99c550a751d4b0b261268f05a803dfb049ab43616a1ffb388f61fe651209101612870565b81516080015167ffffffffffffffff1615612aa05760008160038111156129da576129da614a72565b03612aa05781516080015160208301516040517fe0e03cae0000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169263e0e03cae92612a51928f929190600401615b3d565b6020604051808303816000875af1158015612a70573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a949190615491565b612aa057505050612cc0565b60008c604001518581518110612ab857612ab8614f05565b6020026020010151905080518360a001515114612b1c578251606001516040517f1cfe6d8b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808e16600483015290911660248201526044016106f8565b612b308b84600001516060015160016136ca565b600080612b3d8584613772565b91509150612b548d866000015160600151846136ca565b8b15612bc4576003826003811115612b6e57612b6e614a72565b03612bc4576000846003811115612b8757612b87614a72565b14612bc4578451516040517f2b11b8d90000000000000000000000000000000000000000000000000000000081526106f891908390600401615b6a565b6002826003811115612bd857612bd8614a72565b14612c32576003826003811115612bf157612bf1614a72565b14612c32578451606001516040517f926c5a3e0000000000000000000000000000000000000000000000000000000081526106f8918f918590600401615b83565b84600001516000015185600001516060015167ffffffffffffffff168e67ffffffffffffffff167f05665fe9ad095383d018353f4cbcba77e84db27dd215081bbf7cdf9ae6fbe48b8c8b81518110612c8c57612c8c614f05565b602002602001015186865a612ca1908e615579565b604051612cb19493929190615ba9565b60405180910390a45050505050505b6001016127b2565b8251600090815b818110156111b8576000600188868460208110612cee57612cee614f05565b612cfb91901a601b615992565b898581518110612d0d57612d0d614f05565b6020026020010151898681518110612d2757612d27614f05565b602002602001015160405160008152602001604052604051612d65949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015612d87573d6000803e3d6000fd5b505060408051601f1981015160ff808e166000908152600360209081528582206001600160a01b03851683528152858220858701909652855480841686529397509095509293928401916101009004166002811115612de857612de8614a72565b6002811115612df957612df9614a72565b9052509050600181602001516002811115612e1657612e16614a72565b14612e4d576040517fca31867a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051600160ff9091161b851615612e90576040517ff67bc7c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806000015160ff166001901b851794505050806001019050612ccf565b60408051808201909152600080825260208201526000612ed0876020015161383c565b6040517fbbe4f6db0000000000000000000000000000000000000000000000000000000081526001600160a01b0380831660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063bbe4f6db90602401602060405180830381865afa158015612f55573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f799190615be0565b90506001600160a01b0381161580612fc15750612fbf6001600160a01b0382167faff2afbf00000000000000000000000000000000000000000000000000000000611fb5565b155b15613003576040517fae9b4ce90000000000000000000000000000000000000000000000000000000081526001600160a01b03821660048201526024016106f8565b60045460009081906130259089908690600160e01b900463ffffffff166138e2565b9150915060008060006130f26040518061010001604052808e81526020018c67ffffffffffffffff1681526020018d6001600160a01b031681526020018f606001518152602001896001600160a01b031681526020018f6000015181526020018f6040015181526020018b8152506040516024016130a39190615bfd565b60408051601f198184030181529190526020810180516001600160e01b03167f390775370000000000000000000000000000000000000000000000000000000017905287866113886084613a10565b9250925092508261313157816040517fe1cd55090000000000000000000000000000000000000000000000000000000081526004016106f8919061488d565b81516020146131795781516040517f78ef80240000000000000000000000000000000000000000000000000000000081526020600482015260248101919091526044016106f8565b60008280602001905181019061318f9190615cca565b9050866001600160a01b03168c6001600160a01b0316146132245760006131c08d8a6131bb868a615579565b6138e2565b509050868110806131da5750816131d78883615579565b14155b15613222576040517fa966e21f0000000000000000000000000000000000000000000000000000000081526004810183905260248101889052604481018290526064016106f8565b505b604080518082019091526001600160a01b039098168852602088015250949550505050505095945050505050565b600061327e827f01ffc9a7000000000000000000000000000000000000000000000000000000006132b6565b8015610d7a57506132af827fffffffff000000000000000000000000000000000000000000000000000000006132b6565b1592915050565b6040517fffffffff0000000000000000000000000000000000000000000000000000000082166024820152600090819060440160408051601f19818403018152919052602080820180516001600160e01b03167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825192935060009283928392909183918a617530fa92503d9150600051905082801561335a575060208210155b80156133665750600081115b979650505050505050565b60005b81518110156107245760ff8316600090815260036020526040812083519091908490849081106133a6576133a6614f05565b6020908102919091018101516001600160a01b03168252810191909152604001600020805461ffff19169055600101613374565b60005b8251811015610d245760008382815181106133fa576133fa614f05565b602002602001015190506000600281111561341757613417614a72565b60ff80871660009081526003602090815260408083206001600160a01b0387168452909152902054610100900416600281111561345657613456614a72565b14613477576004604051631b3fab5160e11b81526004016106f89190615a5b565b6001600160a01b0381166134b7576040517fd6c62c9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052808360ff1681526020018460028111156134dd576134dd614a72565b905260ff80871660009081526003602090815260408083206001600160a01b0387168452825290912083518154931660ff198416811782559184015190929091839161ffff19161761010083600281111561353a5761353a614a72565b0217905550905050508060010190506133dd565b60ff8116610581576009805467ffffffffffffffff1916905550565b8151602080820151604092830151925160009384936135b0937f2425b0b9f9054c76ff151b0a175b18f37a4a4e82013a72e9f15c9caa095ed21f93909291889101615ce3565b60408051601f1981840301815290829052805160209182012086518051888401516060808b0151908401516080808d015195015195976135f99794969395929491939101615d16565b604051602081830303815290604052805190602001208560400151805190602001208660a001516040516020016136309190615e1b565b60408051601f198184030181528282528051602091820120908301969096528101939093526060830191909152608082015260a081019190915260c0015b60405160208183030381529060405280519060200120905092915050565b60008061369a858585613b36565b67ffffffffffffffff8716600090815260086020908152604080832093835292905220549150505b949350505050565b600060026136d96080856155a2565b67ffffffffffffffff166136ed91906155c9565b905060006136fb8585611ce9565b90508161370a60016004615579565b901b19168183600381111561372157613721614a72565b67ffffffffffffffff871660009081526007602052604081209190921b929092179182916137506080886159cf565b67ffffffffffffffff1681526020810191909152604001600020555050505050565b6040517fa80036b4000000000000000000000000000000000000000000000000000000008152600090606090309063a80036b4906137b69087908790600401615e7b565b600060405180830381600087803b1580156137d057600080fd5b505af19250505080156137e1575060015b613820573d80801561380f576040519150601f19603f3d011682016040523d82523d6000602084013e613814565b606091505b50600392509050613835565b50506040805160208101909152600081526002905b9250929050565b6000815160201461387b57816040517f8d666f600000000000000000000000000000000000000000000000000000000081526004016106f8919061488d565b6000828060200190518101906138919190615cca565b90506001600160a01b038111806138a9575061040081105b15610d7a57826040517f8d666f600000000000000000000000000000000000000000000000000000000081526004016106f8919061488d565b600080600080600061395c8860405160240161390d91906001600160a01b0391909116815260200190565b60408051601f198184030181529190526020810180516001600160e01b03167f70a082310000000000000000000000000000000000000000000000000000000017905288886113886084613a10565b9250925092508261399b57816040517fe1cd55090000000000000000000000000000000000000000000000000000000081526004016106f8919061488d565b60208251146139e35781516040517f78ef80240000000000000000000000000000000000000000000000000000000081526020600482015260248101919091526044016106f8565b818060200190518101906139f79190615cca565b613a018288615579565b94509450505050935093915050565b6000606060008361ffff1667ffffffffffffffff811115613a3357613a33613e9d565b6040519080825280601f01601f191660200182016040528015613a5d576020820181803683370190505b509150863b613a90577f0c3b563c0000000000000000000000000000000000000000000000000000000060005260046000fd5b5a85811015613ac3577fafa32a2c0000000000000000000000000000000000000000000000000000000060005260046000fd5b8590036040810481038710613afc577f37c3be290000000000000000000000000000000000000000000000000000000060005260046000fd5b505a6000808a5160208c0160008c8cf193505a900390503d84811115613b1f5750835b808352806000602085013e50955095509592505050565b8251825160009190818303613b77576040517f11a6b26400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6101018211801590613b8b57506101018111155b613ba8576040516309bde33960e01b815260040160405180910390fd5b60001982820101610100811115613bd2576040516309bde33960e01b815260040160405180910390fd5b80600003613bff5786600081518110613bed57613bed614f05565b60200260200101519350505050613dce565b60008167ffffffffffffffff811115613c1a57613c1a613e9d565b604051908082528060200260200182016040528015613c43578160200160208202803683370190505b50905060008080805b85811015613d6d5760006001821b8b811603613ca75788851015613c90578c5160018601958e918110613c8157613c81614f05565b60200260200101519050613cc9565b8551600185019487918110613c8157613c81614f05565b8b5160018401938d918110613cbe57613cbe614f05565b602002602001015190505b600089861015613cf9578d5160018701968f918110613cea57613cea614f05565b60200260200101519050613d1b565b8651600186019588918110613d1057613d10614f05565b602002602001015190505b82851115613d3c576040516309bde33960e01b815260040160405180910390fd5b613d468282613dd5565b878481518110613d5857613d58614f05565b60209081029190910101525050600101613c4c565b506001850382148015613d7f57508683145b8015613d8a57508581145b613da7576040516309bde33960e01b815260040160405180910390fd5b836001860381518110613dbc57613dbc614f05565b60200260200101519750505050505050505b9392505050565b6000818310613ded57613de88284613df3565b610d77565b610d7783835b60408051600160208201529081018390526060810182905260009060800161366e565b828054828255906000526020600020908101928215613e78579160200282015b82811115613e78578251825473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03909116178255602090920191600190910190613e36565b50613e84929150613e88565b5090565b5b80821115613e845760008155600101613e89565b634e487b7160e01b600052604160045260246000fd5b6040516080810167ffffffffffffffff81118282101715613ed657613ed6613e9d565b60405290565b60405160a0810167ffffffffffffffff81118282101715613ed657613ed6613e9d565b60405160c0810167ffffffffffffffff81118282101715613ed657613ed6613e9d565b6040805190810167ffffffffffffffff81118282101715613ed657613ed6613e9d565b6040516060810167ffffffffffffffff81118282101715613ed657613ed6613e9d565b604051601f8201601f1916810167ffffffffffffffff81118282101715613f9157613f91613e9d565b604052919050565b600067ffffffffffffffff821115613fb357613fb3613e9d565b5060051b60200190565b6001600160a01b038116811461058157600080fd5b803567ffffffffffffffff81168114613fea57600080fd5b919050565b801515811461058157600080fd5b8035613fea81613fef565b600067ffffffffffffffff82111561402257614022613e9d565b50601f01601f191660200190565b600082601f83011261404157600080fd5b813561405461404f82614008565b613f68565b81815284602083860101111561406957600080fd5b816020850160208301376000918101602001919091529392505050565b6000602080838503121561409957600080fd5b823567ffffffffffffffff808211156140b157600080fd5b818501915085601f8301126140c557600080fd5b81356140d361404f82613f99565b81815260059190911b830184019084810190888311156140f257600080fd5b8585015b838110156141985780358581111561410e5760008081fd5b86016080818c03601f19018113156141265760008081fd5b61412e613eb3565b8983013561413b81613fbd565b8152604061414a848201613fd2565b8b83015260608085013561415d81613fef565b8383015292840135928984111561417657600091508182fd5b6141848f8d86880101614030565b9083015250855250509186019186016140f6565b5098975050505050505050565b600060a082840312156141b757600080fd5b6141bf613edc565b9050813581526141d160208301613fd2565b60208201526141e260408301613fd2565b60408201526141f360608301613fd2565b606082015261420460808301613fd2565b608082015292915050565b8035613fea81613fbd565b600082601f83011261422b57600080fd5b8135602061423b61404f83613f99565b82815260059290921b8401810191818101908684111561425a57600080fd5b8286015b84811015611fa957803567ffffffffffffffff8082111561427f5760008081fd5b818901915060a080601f19848d0301121561429a5760008081fd5b6142a2613edc565b87840135838111156142b45760008081fd5b6142c28d8a83880101614030565b825250604080850135848111156142d95760008081fd5b6142e78e8b83890101614030565b8a84015250606080860135858111156143005760008081fd5b61430e8f8c838a0101614030565b838501525060809150818601358184015250828501359250838311156143345760008081fd5b6143428d8a85880101614030565b90820152865250505091830191830161425e565b6000610140828403121561436957600080fd5b614371613eff565b905061437d83836141a5565b815260a082013567ffffffffffffffff8082111561439a57600080fd5b6143a685838601614030565b602084015260c08401359150808211156143bf57600080fd5b6143cb85838601614030565b60408401526143dc60e0850161420f565b6060840152610100840135608084015261012084013591508082111561440157600080fd5b5061440e8482850161421a565b60a08301525092915050565b600082601f83011261442b57600080fd5b8135602061443b61404f83613f99565b82815260059290921b8401810191818101908684111561445a57600080fd5b8286015b84811015611fa957803567ffffffffffffffff81111561447e5760008081fd5b61448c8986838b0101614356565b84525091830191830161445e565b600082601f8301126144ab57600080fd5b813560206144bb61404f83613f99565b82815260059290921b840181019181810190868411156144da57600080fd5b8286015b84811015611fa957803567ffffffffffffffff808211156144fe57600080fd5b818901915089603f83011261451257600080fd5b8582013561452261404f82613f99565b81815260059190911b830160400190878101908c83111561454257600080fd5b604085015b8381101561457b5780358581111561455e57600080fd5b61456d8f6040838a0101614030565b845250918901918901614547565b508752505050928401925083016144de565b600082601f83011261459e57600080fd5b813560206145ae61404f83613f99565b8083825260208201915060208460051b8701019350868411156145d057600080fd5b602086015b84811015611fa957803583529183019183016145d5565b600082601f8301126145fd57600080fd5b8135602061460d61404f83613f99565b82815260059290921b8401810191818101908684111561462c57600080fd5b8286015b84811015611fa957803567ffffffffffffffff808211156146515760008081fd5b818901915060a080601f19848d0301121561466c5760008081fd5b614674613edc565b61467f888501613fd2565b8152604080850135848111156146955760008081fd5b6146a38e8b8389010161441a565b8a84015250606080860135858111156146bc5760008081fd5b6146ca8f8c838a010161449a565b83850152506080915081860135858111156146e55760008081fd5b6146f38f8c838a010161458d565b9184019190915250919093013590830152508352918301918301614630565b600080604080848603121561472657600080fd5b833567ffffffffffffffff8082111561473e57600080fd5b61474a878388016145ec565b945060209150818601358181111561476157600080fd5b8601601f8101881361477257600080fd5b803561478061404f82613f99565b81815260059190911b8201840190848101908a83111561479f57600080fd5b8584015b8381101561482b578035868111156147bb5760008081fd5b8501603f81018d136147cd5760008081fd5b878101356147dd61404f82613f99565b81815260059190911b82018a0190898101908f8311156147fd5760008081fd5b928b01925b8284101561481b5783358252928a0192908a0190614802565b86525050509186019186016147a3565b50809750505050505050509250929050565b60005b83811015614858578181015183820152602001614840565b50506000910152565b6000815180845261487981602086016020860161483d565b601f01601f19169290920160200192915050565b602081526000610d776020830184614861565b8060608101831015610d7a57600080fd5b60008083601f8401126148c357600080fd5b50813567ffffffffffffffff8111156148db57600080fd5b60208301915083602082850101111561383557600080fd5b60008083601f84011261490557600080fd5b50813567ffffffffffffffff81111561491d57600080fd5b6020830191508360208260051b850101111561383557600080fd5b60008060008060008060008060e0898b03121561495457600080fd5b61495e8a8a6148a0565b9750606089013567ffffffffffffffff8082111561497b57600080fd5b6149878c838d016148b1565b909950975060808b01359150808211156149a057600080fd5b6149ac8c838d016148f3565b909750955060a08b01359150808211156149c557600080fd5b506149d28b828c016148f3565b999c989b50969995989497949560c00135949350505050565b600080600060808486031215614a0057600080fd5b614a0a85856148a0565b9250606084013567ffffffffffffffff811115614a2657600080fd5b614a32868287016148b1565b9497909650939450505050565b60008060408385031215614a5257600080fd5b614a5b83613fd2565b9150614a6960208401613fd2565b90509250929050565b634e487b7160e01b600052602160045260246000fd5b60048110614a9857614a98614a72565b9052565b60208101610d7a8284614a88565b600060208284031215614abc57600080fd5b813567ffffffffffffffff811115614ad357600080fd5b820160a08185031215613dce57600080fd5b803563ffffffff81168114613fea57600080fd5b600060a08284031215614b0b57600080fd5b614b13613edc565b8235614b1e81613fbd565b8152614b2c60208401614ae5565b6020820152614b3d60408401614ae5565b6040820152614b4e60608401614ae5565b60608201526080830135614b6181613fbd565b60808201529392505050565b600080600060408486031215614b8257600080fd5b833567ffffffffffffffff80821115614b9a57600080fd5b614ba687838801614356565b94506020860135915080821115614bbc57600080fd5b50614a32868287016148f3565b803560ff81168114613fea57600080fd5b600060208284031215614bec57600080fd5b610d7782614bc9565b60008151808452602080850194506020840160005b83811015614c2f5781516001600160a01b031687529582019590820190600101614c0a565b509495945050505050565b60208152600082518051602084015260ff602082015116604084015260ff604082015116606084015260608101511515608084015250602083015160c060a0840152614c8960e0840182614bf5565b90506040840151601f198483030160c0850152614ca68282614bf5565b95945050505050565b60008060408385031215614cc257600080fd5b614ccb83613fd2565b946020939093013593505050565b600060208284031215614ceb57600080fd5b610d7782613fd2565b602081526001600160a01b03825116602082015260208201511515604082015267ffffffffffffffff6040830151166060820152600060608301516080808401526136c260a0840182614861565b600060208284031215614d5457600080fd5b8135613dce81613fbd565b600082601f830112614d7057600080fd5b81356020614d8061404f83613f99565b8083825260208201915060208460051b870101935086841115614da257600080fd5b602086015b84811015611fa9578035614dba81613fbd565b8352918301918301614da7565b60006020808385031215614dda57600080fd5b823567ffffffffffffffff80821115614df257600080fd5b818501915085601f830112614e0657600080fd5b8135614e1461404f82613f99565b81815260059190911b83018401908481019088831115614e3357600080fd5b8585015b8381101561419857803585811115614e4e57600080fd5b860160c0818c03601f19011215614e655760008081fd5b614e6d613eff565b8882013581526040614e80818401614bc9565b8a8301526060614e91818501614bc9565b8284015260809150614ea4828501613ffd565b9083015260a08381013589811115614ebc5760008081fd5b614eca8f8d83880101614d5f565b838501525060c0840135915088821115614ee45760008081fd5b614ef28e8c84870101614d5f565b9083015250845250918601918601614e37565b634e487b7160e01b600052603260045260246000fd5b80356001600160e01b0381168114613fea57600080fd5b600082601f830112614f4357600080fd5b81356020614f5361404f83613f99565b82815260069290921b84018101918181019086841115614f7257600080fd5b8286015b84811015611fa95760408189031215614f8f5760008081fd5b614f97613f22565b614fa082613fd2565b8152614fad858301614f1b565b81860152835291830191604001614f76565b600082601f830112614fd057600080fd5b81356020614fe061404f83613f99565b82815260059290921b84018101918181019086841115614fff57600080fd5b8286015b84811015611fa957803567ffffffffffffffff808211156150245760008081fd5b818901915060a080601f19848d0301121561503f5760008081fd5b615047613edc565b615052888501613fd2565b81526040615061818601613fd2565b898301526060615072818701613fd2565b8284015260809150818601358184015250828501359250838311156150975760008081fd5b6150a58d8a85880101614030565b908201528652505050918301918301615003565b600082601f8301126150ca57600080fd5b813560206150da61404f83613f99565b82815260069290921b840181019181810190868411156150f957600080fd5b8286015b84811015611fa957604081890312156151165760008081fd5b61511e613f22565b8135815284820135858201528352918301916040016150fd565b6000602080838503121561514b57600080fd5b823567ffffffffffffffff8082111561516357600080fd5b908401906060828703121561517757600080fd5b61517f613f45565b82358281111561518e57600080fd5b830160408189038113156151a157600080fd5b6151a9613f22565b8235858111156151b857600080fd5b8301601f81018b136151c957600080fd5b80356151d761404f82613f99565b81815260069190911b8201890190898101908d8311156151f657600080fd5b928a01925b828410156152465785848f0312156152135760008081fd5b61521b613f22565b843561522681613fbd565b8152615233858d01614f1b565b818d0152825292850192908a01906151fb565b84525050508287013591508482111561525e57600080fd5b61526a8a838501614f32565b8188015283525050828401358281111561528357600080fd5b61528f88828601614fbf565b858301525060408301359350818411156152a857600080fd5b6152b4878585016150b9565b60408201529695505050505050565b600082825180855260208086019550808260051b84010181860160005b8481101561535357858303601f190189528151805167ffffffffffffffff908116855285820151811686860152604080830151909116908501526060808201519085015260809081015160a09185018290529061533f81860183614861565b9a86019a94505050908301906001016152e0565b5090979650505050505050565b60008151808452602080850194506020840160005b83811015614c2f578151805188528301518388015260409096019590820190600101615375565b6040815260006153af60408301856152c3565b8281036020840152614ca68185615360565b805160408084528151848201819052600092602091908201906060870190855b8181101561541857835180516001600160a01b031684528501516001600160e01b03168584015292840192918501916001016153e1565b50508583015187820388850152805180835290840192506000918401905b80831015615472578351805167ffffffffffffffff1683528501516001600160e01b031685830152928401926001929092019190850190615436565b50979650505050505050565b602081526000610d7760208301846153c1565b6000602082840312156154a357600080fd5b8151613dce81613fef565b634e487b7160e01b600052601160045260246000fd5b67ffffffffffffffff8181168382160190808211156154e5576154e56154ae565b5092915050565b60208152600082516060602084015261550860808401826153c1565b90506020840151601f198085840301604086015261552683836152c3565b9250604086015191508085840301606086015250614ca68282615360565b60006020828403121561555657600080fd5b813567ffffffffffffffff81111561556d57600080fd5b6136c2848285016145ec565b81810381811115610d7a57610d7a6154ae565b634e487b7160e01b600052601260045260246000fd5b600067ffffffffffffffff808416806155bd576155bd61558c565b92169190910692915050565b8082028115828204841417610d7a57610d7a6154ae565b805182526000602067ffffffffffffffff81840151168185015260408084015160a0604087015261561460a0870182614861565b90506060850151868203606088015261562d8282614861565b608087810151898303918a01919091528051808352908601935060009250908501905b8083101561547257835180516001600160a01b0316835286015186830152928501926001929092019190840190615650565b602081526000610d7760208301846155e0565b6080815260006156a860808301876155e0565b61ffff9590951660208301525060408101929092526001600160a01b0316606090910152919050565b6000806000606084860312156156e657600080fd5b83516156f181613fef565b602085015190935067ffffffffffffffff81111561570e57600080fd5b8401601f8101861361571f57600080fd5b805161572d61404f82614008565b81815287602083850101111561574257600080fd5b61575382602083016020860161483d565b809450505050604084015190509250925092565b600181811c9082168061577b57607f821691505b60208210810361579b57634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115610724576000816000526020600020601f850160051c810160208610156157ca5750805b601f850160051c820191505b818110156157e9578281556001016157d6565b505050505050565b815167ffffffffffffffff81111561580b5761580b613e9d565b61581f816158198454615767565b846157a1565b602080601f831160018114615854576000841561583c5750858301515b600019600386901b1c1916600185901b1785556157e9565b600085815260208120601f198616915b8281101561588357888601518255948401946001909101908401615864565b50858210156158a15787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6000602080835283546001600160a01b038116602085015260ff8160a01c161515604085015267ffffffffffffffff8160a81c1660608501525060018085016080808601526000815461590381615767565b8060a089015260c06001831660008114615924576001811461594057615970565b60ff19841660c08b015260c083151560051b8b01019450615970565b85600052602060002060005b848110156159675781548c820185015290880190890161594c565b8b0160c0019550505b50929998505050505050505050565b80820180821115610d7a57610d7a6154ae565b60ff8181168382160190811115610d7a57610d7a6154ae565b8183823760009101908152919050565b828152606082602083013760800192915050565b600067ffffffffffffffff808416806159ea576159ea61558c565b92169190910492915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112615a2b57600080fd5b83018035915067ffffffffffffffff821115615a4657600080fd5b60200191503681900382131561383557600080fd5b6020810160058310615a6f57615a6f614a72565b91905290565b60ff81811683821602908116908181146154e5576154e56154ae565b600060a0820160ff881683526020878185015260a0604085015281875480845260c0860191508860005282600020935060005b81811015615ae95784546001600160a01b031683526001948501949284019201615ac4565b50508481036060860152865180825290820192508187019060005b81811015615b295782516001600160a01b031685529383019391830191600101615b04565b50505060ff85166080850152509050611fab565b600067ffffffffffffffff808616835280851660208401525060606040830152614ca66060830184614861565b8281526040602082015260006136c26040830184614861565b67ffffffffffffffff848116825283166020820152606081016136c26040830184614a88565b848152615bb96020820185614a88565b608060408201526000615bcf6080830185614861565b905082606083015295945050505050565b600060208284031215615bf257600080fd5b8151613dce81613fbd565b6020815260008251610100806020850152615c1c610120850183614861565b91506020850151615c39604086018267ffffffffffffffff169052565b5060408501516001600160a01b038116606086015250606085015160808501526080850151615c7360a08601826001600160a01b03169052565b5060a0850151601f19808685030160c0870152615c908483614861565b935060c08701519150808685030160e0870152615cad8483614861565b935060e0870151915080868503018387015250611fab8382614861565b600060208284031215615cdc57600080fd5b5051919050565b848152600067ffffffffffffffff808616602084015280851660408401525060806060830152611fab6080830184614861565b86815260c060208201526000615d2f60c0830188614861565b6001600160a01b039690961660408301525067ffffffffffffffff9384166060820152608081019290925290911660a09091015292915050565b600082825180855260208086019550808260051b84010181860160005b8481101561535357601f19868403018952815160a08151818652615dac82870182614861565b9150508582015185820387870152615dc48282614861565b91505060408083015186830382880152615dde8382614861565b92505050606080830151818701525060808083015192508582038187015250615e078183614861565b9a86019a9450505090830190600101615d86565b602081526000610d776020830184615d69565b60008282518085526020808601955060208260051b8401016020860160005b8481101561535357601f19868403018952615e69838351614861565b98840198925090830190600101615e4d565b604081526000835180516040840152602081015167ffffffffffffffff80821660608601528060408401511660808601528060608401511660a08601528060808401511660c086015250505060208401516101408060e0850152615ee3610180850183614861565b915060408601517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08086850301610100870152615f208483614861565b935060608801519150615f3f6101208701836001600160a01b03169052565b60808801518387015260a0880151925080868503016101608701525050615f668282615d69565b9150508281036020840152614ca68185615e2e56fea164736f6c6343000818000a", + Bin: "0x6101206040523480156200001257600080fd5b5060405162006c2638038062006c268339810160408190526200003591620008c7565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf81620001fa565b5050466080525060208301516001600160a01b03161580620000ec575060408301516001600160a01b0316155b8062000103575060608301516001600160a01b0316155b1562000122576040516342bcdf7f60e11b815260040160405180910390fd5b82516001600160401b03166000036200014e5760405163c656089560e01b815260040160405180910390fd5b82516001600160401b0390811660a052602080850180516001600160a01b0390811660c05260408088018051831660e0526060808a01805185166101005283518b519098168852945184169587019590955251821690850152905116908201527f683eb52ee924eb817377cfa8f41f238f4bb7a877da5267869dfffbad85f564d89060800160405180910390a1620001e682620002a5565b620001f181620003c1565b50505062000c67565b336001600160a01b03821603620002545760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b0316620002ce576040516342bcdf7f60e11b815260040160405180910390fd5b80516004805460208085018051604080880180516060808b0180516001600160a01b039b8c166001600160c01b0319909a168a17600160a01b63ffffffff98891602176001600160c01b0316600160c01b948816949094026001600160e01b031693909317600160e01b93871693909302929092179098556080808b018051600580546001600160a01b031916918d169190911790558451988952955185169688019690965290518316918601919091525116938301939093529151909216908201527fa55bd56595c45f517e5967a3067f3dca684445a3080e7c04a4e0d5a40cda627d9060a00160405180910390a150565b60005b815181101562000666576000828281518110620003e557620003e562000a1d565b60200260200101519050600081602001519050806001600160401b0316600003620004235760405163c656089560e01b815260040160405180910390fd5b81516001600160a01b03166200044c576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160401b0381166000908152600660205260408120600181018054919291620004789062000a33565b80601f0160208091040260200160405190810160405280929190818152602001828054620004a69062000a33565b8015620004f75780601f10620004cb57610100808354040283529160200191620004f7565b820191906000526020600020905b815481529060010190602001808311620004d957829003601f168201915b5050505050905060008460600151905081516000036200059e57805160000362000534576040516342bcdf7f60e11b815260040160405180910390fd5b6001830162000544828262000ac4565b508254600160a81b600160e81b031916600160a81b1783556040516001600160401b03851681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1620005d9565b8080519060200120828051906020012014620005d95760405163c39a620560e01b81526001600160401b038516600482015260240162000083565b604080860151845487516001600160a01b03166001600160a01b0319921515600160a01b02929092166001600160a81b031990911617178455516001600160401b038516907f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b906200064d90869062000b90565b60405180910390a25050505050806001019050620003c4565b5050565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b0381118282101715620006a557620006a56200066a565b60405290565b604051601f8201601f191681016001600160401b0381118282101715620006d657620006d66200066a565b604052919050565b80516001600160401b0381168114620006f657600080fd5b919050565b6001600160a01b03811681146200071157600080fd5b50565b805163ffffffff81168114620006f657600080fd5b6000601f83601f8401126200073d57600080fd5b825160206001600160401b03808311156200075c576200075c6200066a565b8260051b6200076d838201620006ab565b93845286810183019383810190898611156200078857600080fd5b84890192505b85831015620008ba57825184811115620007a85760008081fd5b89016080601f19828d038101821315620007c25760008081fd5b620007cc62000680565b88840151620007db81620006fb565b81526040620007ec858201620006de565b8a8301526060808601518015158114620008065760008081fd5b838301529385015193898511156200081e5760008081fd5b84860195508f603f8701126200083657600094508485fd5b8a8601519450898511156200084f576200084f6200066a565b620008608b858f88011601620006ab565b93508484528f82868801011115620008785760008081fd5b60005b8581101562000898578681018301518582018d01528b016200087b565b5060009484018b0194909452509182015283525091840191908401906200078e565b9998505050505050505050565b6000806000838503610140811215620008df57600080fd5b6080811215620008ee57600080fd5b620008f862000680565b6200090386620006de565b815260208601516200091581620006fb565b602082015260408601516200092a81620006fb565b604082015260608601516200093f81620006fb565b6060820152935060a0607f19820112156200095957600080fd5b5060405160a081016001600160401b0380821183831017156200098057620009806200066a565b81604052608087015191506200099682620006fb565b818352620009a760a0880162000714565b6020840152620009ba60c0880162000714565b6040840152620009cd60e0880162000714565b60608401526101008701519150620009e582620006fb565b608083018290526101208701519294508083111562000a0357600080fd5b505062000a138682870162000729565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b600181811c9082168062000a4857607f821691505b60208210810362000a6957634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111562000abf576000816000526020600020601f850160051c8101602086101562000a9a5750805b601f850160051c820191505b8181101562000abb5782815560010162000aa6565b5050505b505050565b81516001600160401b0381111562000ae05762000ae06200066a565b62000af88162000af1845462000a33565b8462000a6f565b602080601f83116001811462000b30576000841562000b175750858301515b600019600386901b1c1916600185901b17855562000abb565b600085815260208120601f198616915b8281101562000b615788860151825594840194600190910190840162000b40565b508582101562000b805787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b602080825282546001600160a01b0381168383015260a081901c60ff161515604084015260a81c6001600160401b0316606083015260808083015260018084018054600093929190849062000be58162000a33565b8060a089015260c0600183166000811462000c09576001811462000c265762000c58565b60ff19841660c08b015260c083151560051b8b0101945062000c58565b85600052602060002060005b8481101562000c4f5781548c820185015290880190890162000c32565b8b0160c0019550505b50929998505050505050505050565b60805160a05160c05160e05161010051615f4962000cdd600039600081816102400152612a1a0152600081816102110152612f0e0152600081816101e20152818161077f01528181610986015261240c0152600081816101b201526126990152600081816117dd01526118290152615f496000f3fe608060405234801561001057600080fd5b50600436106101515760003560e01c806379ba5097116100cd578063c673e58411610081578063e9d68a8e11610066578063e9d68a8e1461052a578063f2fde38b1461054a578063f716f99f1461055d57600080fd5b8063c673e584146104c5578063ccd37ba3146104e557600080fd5b80638da5cb5b116100b25780638da5cb5b14610484578063991a50181461049f578063a80036b4146104b257600080fd5b806379ba50971461046e57806385572ffb1461047657600080fd5b80632d04ab76116101245780633f4b04aa116101095780633f4b04aa146103365780635e36480c146103525780637437ff9f1461037257600080fd5b80632d04ab7614610310578063311cd5131461032357600080fd5b806304666f9c1461015657806305d938b51461016b57806306285c691461017e578063181f5a77146102c7575b600080fd5b610169610164366004614086565b610570565b005b610169610179366004614710565b610584565b61027060408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316815250905090565b6040516102be9190815167ffffffffffffffff1681526020808301516001600160a01b0390811691830191909152604080840151821690830152606092830151169181019190915260800190565b60405180910390f35b6103036040518060400160405280601181526020017f4f666652616d7020312e362e302d64657600000000000000000000000000000081525081565b6040516102be919061488b565b61016961031e366004614936565b610729565b6101696103313660046149e9565b610cc1565b60095460405167ffffffffffffffff90911681526020016102be565b610365610360366004614a3d565b610d2a565b6040516102be9190614a9a565b6104116040805160a081018252600080825260208201819052918101829052606081018290526080810191909152506040805160a0810182526004546001600160a01b03808216835263ffffffff600160a01b83048116602085015278010000000000000000000000000000000000000000000000008304811694840194909452600160e01b9091049092166060820152600554909116608082015290565b6040516102be9190600060a0820190506001600160a01b03808451168352602084015163ffffffff808216602086015280604087015116604086015280606087015116606086015250508060808501511660808401525092915050565b610169610d80565b610169610151366004614aa8565b6000546040516001600160a01b0390911681526020016102be565b6101696104ad366004614af7565b610e3e565b6101696104c0366004614b6b565b610e4f565b6104d86104d3366004614bd8565b6111c2565b6040516102be9190614c38565b61051c6104f3366004614cad565b67ffffffffffffffff919091166000908152600860209081526040808320938352929052205490565b6040519081526020016102be565b61053d610538366004614cd7565b611320565b6040516102be9190614cf2565b610169610558366004614d40565b61142d565b61016961056b366004614dc5565b61143e565b610578611480565b610581816114dc565b50565b61058c6117da565b8151815181146105c8576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b818110156107195760008482815181106105e7576105e7614f03565b6020026020010151905060008160200151519050600085848151811061060f5761060f614f03565b6020026020010151905080518214610653576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8281101561070a57600082828151811061067257610672614f03565b6020026020010151905080600014610701578460200151828151811061069a5761069a614f03565b6020026020010151608001518110156107015784516040517fc8e9605100000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260248101839052604481018290526064015b60405180910390fd5b50600101610656565b505050508060010190506105cb565b50610724838361185b565b505050565b600061073787890189615135565b602081015151909150156107e357602081015160408083015190517f30dfc3080000000000000000000000000000000000000000000000000000000081526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016926330dfc308926107b292600401615399565b60006040518083038186803b1580156107ca57600080fd5b505afa1580156107de573d6000803e3d6000fd5b505050505b805151511515806107f957508051602001515115155b156108f95760095460208a01359067ffffffffffffffff808316911610156108b8576009805467ffffffffffffffff191667ffffffffffffffff83161790556004805483516040517f3937306f0000000000000000000000000000000000000000000000000000000081526001600160a01b0390921692633937306f9261088192910161547b565b600060405180830381600087803b15801561089b57600080fd5b505af11580156108af573d6000803e3d6000fd5b505050506108f7565b8160200151516000036108f7576040517f2261116700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b60005b816020015151811015610c0a5760008260200151828151811061092157610921614f03565b602090810291909101015180516040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815277ffffffffffffffff00000000000000000000000000000000608083901b166004820152919250906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632cbc26bb90602401602060405180830381865afa1580156109cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109f1919061548e565b15610a34576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff821660048201526024016106f8565b6000610a3f8261190b565b6020840151815491925067ffffffffffffffff908116600160a81b90920416141580610a865750826040015167ffffffffffffffff16836020015167ffffffffffffffff16115b15610ae7578251602084015160408086015190517fd5e0f0d600000000000000000000000000000000000000000000000000000000815267ffffffffffffffff938416600482015291831660248301529190911660448201526064016106f8565b606083015180610b23576040517f504570e300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b835167ffffffffffffffff16600090815260086020908152604080832084845290915290205415610b965783516040517f32cf0cbf00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602481018290526044016106f8565b6040840151610ba69060016154c1565b82547fffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffff16600160a81b67ffffffffffffffff9283160217909255925116600090815260086020908152604080832094835293905291909120429055506001016108fc565b507fd7868a16facbdde7b5c020620136316b3c266fffcb4e1e41cb6a662fe14ba3e181604051610c3a91906154e9565b60405180910390a1610cb660008a8a8a8a8a8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808e0282810182019093528d82529093508d92508c9182918501908490808284376000920191909152508b9250611972915050565b505050505050505050565b610d01610cd082840184615541565b6040805160008082526020820190925290610cfb565b6060815260200190600190039081610ce65790505b5061185b565b604080516000808252602082019092529050610d24600185858585866000611972565b50505050565b6000610d3860016004615576565b6002610d4560808561559f565b67ffffffffffffffff16610d5991906155c6565b610d638585611ce9565b901c166003811115610d7757610d77614a70565b90505b92915050565b6001546001600160a01b03163314610dda5760405162461bcd60e51b815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064016106f8565b600080543373ffffffffffffffffffffffffffffffffffffffff19808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610e46611480565b61058181611d30565b333014610e88576040517f371a732800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160008082526020820190925281610ec5565b6040805180820190915260008082526020820152815260200190600190039081610e9e5790505b5060a08501515190915015610ef957610ef68460a00151856020015186606001518760000151602001518787611e96565b90505b6040805160a0810182528551518152855160209081015167ffffffffffffffff1681830152808701518351600094840192610f3592910161488b565b60408051601f19818403018152918152908252878101516020830152018390526005549091506001600160a01b03168015611042576040517f08d450a10000000000000000000000000000000000000000000000000000000081526001600160a01b038216906308d450a190610faf90859060040161567f565b600060405180830381600087803b158015610fc957600080fd5b505af1925050508015610fda575060015b611042573d808015611008576040519150601f19603f3d011682016040523d82523d6000602084013e61100d565b606091505b50806040517f09c253250000000000000000000000000000000000000000000000000000000081526004016106f8919061488b565b60408601515115801561105757506080860151155b8061106e575060608601516001600160a01b03163b155b806110ae575060608601516110ac906001600160a01b03167f85572ffb00000000000000000000000000000000000000000000000000000000611fb5565b155b156110bb57505050505050565b855160209081015167ffffffffffffffff1660009081526006909152604080822054608089015160608a015192517f3cf9798300000000000000000000000000000000000000000000000000000000815284936001600160a01b0390931692633cf97983926111339289926113889291600401615692565b6000604051808303816000875af1158015611152573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261117a91908101906156ce565b5091509150816111b857806040517f0a8d6e8c0000000000000000000000000000000000000000000000000000000081526004016106f8919061488b565b5050505050505050565b6112056040805160e081019091526000606082018181526080830182905260a0830182905260c08301919091528190815260200160608152602001606081525090565b60ff808316600090815260026020818152604092839020835160e081018552815460608201908152600183015480881660808401526101008104881660a0840152620100009004909616151560c0820152948552918201805484518184028101840190955280855292938583019390928301828280156112ae57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611290575b505050505081526020016003820180548060200260200160405190810160405280929190818152602001828054801561131057602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116112f2575b5050505050815250509050919050565b604080516080808201835260008083526020808401829052838501829052606080850181905267ffffffffffffffff878116845260068352928690208651948501875280546001600160a01b0381168652600160a01b810460ff16151593860193909352600160a81b9092049092169483019490945260018401805493949293918401916113ad90615764565b80601f01602080910402602001604051908101604052809291908181526020018280546113d990615764565b80156113105780601f106113fb57610100808354040283529160200191611310565b820191906000526020600020905b81548152906001019060200180831161140957505050919092525091949350505050565b611435611480565b61058181611fd1565b611446611480565b60005b815181101561147c5761147482828151811061146757611467614f03565b6020026020010151612087565b600101611449565b5050565b6000546001600160a01b031633146114da5760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016106f8565b565b60005b815181101561147c5760008282815181106114fc576114fc614f03565b602002602001015190506000816020015190508067ffffffffffffffff16600003611553576040517fc656089500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81516001600160a01b031661157b576040516342bcdf7f60e11b815260040160405180910390fd5b67ffffffffffffffff811660009081526006602052604081206001810180549192916115a690615764565b80601f01602080910402602001604051908101604052809291908181526020018280546115d290615764565b801561161f5780601f106115f45761010080835404028352916020019161161f565b820191906000526020600020905b81548152906001019060200180831161160257829003601f168201915b5050505050905060008460600151905081516000036116d757805160000361165a576040516342bcdf7f60e11b815260040160405180910390fd5b6001830161166882826157ee565b5082547fffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffff16600160a81b17835560405167ffffffffffffffff851681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a161172a565b808051906020012082805190602001201461172a576040517fc39a620500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff851660048201526024016106f8565b604080860151845487516001600160a01b031673ffffffffffffffffffffffffffffffffffffffff19921515600160a01b02929092167fffffffffffffffffffffff000000000000000000000000000000000000000000909116171784555167ffffffffffffffff8516907f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b906117c29086906158ae565b60405180910390a250505050508060010190506114df565b467f0000000000000000000000000000000000000000000000000000000000000000146114da576040517f0f01ce850000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060048201524660248201526044016106f8565b8151600003611895576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160408051600080825260208201909252911591905b8451811015611904576118fc8582815181106118ca576118ca614f03565b6020026020010151846118f6578583815181106118e9576118e9614f03565b60200260200101516123b8565b836123b8565b6001016118ac565b5050505050565b67ffffffffffffffff811660009081526006602052604081208054600160a01b900460ff16610d7a576040517fed053c5900000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024016106f8565b60ff878116600090815260026020908152604080832081516080810183528154815260019091015480861693820193909352610100830485169181019190915262010000909104909216151560608301528735906119d18760a461597c565b9050826060015115611a195784516119ea9060206155c6565b86516119f79060206155c6565b611a029060a061597c565b611a0c919061597c565b611a16908261597c565b90505b368114611a5b576040517f8e1192e1000000000000000000000000000000000000000000000000000000008152600481018290523660248201526044016106f8565b5081518114611aa35781516040517f93df584c0000000000000000000000000000000000000000000000000000000081526004810191909152602481018290526044016106f8565b611aab6117da565b60ff808a1660009081526003602090815260408083203384528252808320815180830190925280548086168352939491939092840191610100909104166002811115611af957611af9614a70565b6002811115611b0a57611b0a614a70565b9052509050600281602001516002811115611b2757611b27614a70565b148015611b7b5750600260008b60ff1660ff168152602001908152602001600020600301816000015160ff1681548110611b6357611b63614f03565b6000918252602090912001546001600160a01b031633145b611bb1576040517fda0f08e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50816060015115611c93576020820151611bcc90600161598f565b60ff16855114611c08576040517f71253a2500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8351855114611c43576040517fa75d88af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008787604051611c559291906159a8565b604051908190038120611c6c918b906020016159b8565b604051602081830303815290604052805190602001209050611c918a82888888612cc8565b505b6040805182815260208a81013567ffffffffffffffff169082015260ff8b16917f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef0910160405180910390a2505050505050505050565b67ffffffffffffffff8216600090815260076020526040812081611d0e6080856159cc565b67ffffffffffffffff1681526020810191909152604001600020549392505050565b80516001600160a01b0316611d58576040516342bcdf7f60e11b815260040160405180910390fd5b80516004805460208085018051604080880180516060808b0180516001600160a01b039b8c167fffffffffffffffff000000000000000000000000000000000000000000000000909a168a17600160a01b63ffffffff988916021777ffffffffffffffffffffffffffffffffffffffffffffffff167801000000000000000000000000000000000000000000000000948816949094026001600160e01b031693909317600160e01b93871693909302929092179098556080808b0180516005805473ffffffffffffffffffffffffffffffffffffffff1916918d169190911790558451988952955185169688019690965290518316918601919091525116938301939093529151909216908201527fa55bd56595c45f517e5967a3067f3dca684445a3080e7c04a4e0d5a40cda627d9060a00160405180910390a150565b6060865167ffffffffffffffff811115611eb257611eb2613e9d565b604051908082528060200260200182016040528015611ef757816020015b6040805180820190915260008082526020820152815260200190600190039081611ed05790505b50905060005b8751811015611fa957611f84888281518110611f1b57611f1b614f03565b6020026020010151888888888887818110611f3857611f38614f03565b9050602002810190611f4a91906159f3565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612ead92505050565b828281518110611f9657611f96614f03565b6020908102919091010152600101611efd565b505b9695505050505050565b6000611fc083613252565b8015610d775750610d7783836132b6565b336001600160a01b038216036120295760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016106f8565b6001805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b806040015160ff166000036120b2576000604051631b3fab5160e11b81526004016106f89190615a3a565b60208082015160ff8082166000908152600290935260408320600181015492939092839216900361211f57606084015160018201805491151562010000027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff909216919091179055612174565b6060840151600182015460ff6201000090910416151590151514612174576040517f87f6037c00000000000000000000000000000000000000000000000000000000815260ff841660048201526024016106f8565b60a0840151805161010010156121a0576001604051631b3fab5160e11b81526004016106f89190615a3a565b61220684846003018054806020026020016040519081016040528092919081815260200182805480156121fc57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116121de575b5050505050613371565b84606001511561232d5761227484846002018054806020026020016040519081016040528092919081815260200182805480156121fc576020028201919060005260206000209081546001600160a01b031681526001909101906020018083116121de575050505050613371565b6080850151805161010010156122a0576002604051631b3fab5160e11b81526004016106f89190615a3a565b60408601516122b0906003615a54565b60ff168151116122d6576003604051631b3fab5160e11b81526004016106f89190615a3a565b80516001840180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1661010060ff84160217905561231e9060028601906020840190613e16565b5061232b858260016133da565b505b612339848260026133da565b805161234e9060038501906020840190613e16565b5060408581015160018401805460ff191660ff8316179055865180855560a088015192517fab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f547936123a79389939260028a01929190615a70565b60405180910390a16119048461354e565b815181516040517f2cbc26bb000000000000000000000000000000000000000000000000000000008152608083901b77ffffffffffffffff00000000000000000000000000000000166004820152901515907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632cbc26bb90602401602060405180830381865afa15801561245b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061247f919061548e565b1561250b5780156124c8576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff831660048201526024016106f8565b60405167ffffffffffffffff831681527faab522ed53d887e56ed53dd37398a01aeef6a58e0fa77c2173beb9512d8949339060200160405180910390a150505050565b60006125168361190b565b600101805461252490615764565b80601f016020809104026020016040519081016040528092919081815260200182805461255090615764565b801561259d5780601f106125725761010080835404028352916020019161259d565b820191906000526020600020905b81548152906001019060200180831161258057829003601f168201915b505050602088015151929350505060008190036125e5576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8560400151518114612623576040517f57e0e08300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008167ffffffffffffffff81111561263e5761263e613e9d565b604051908082528060200260200182016040528015612667578160200160208202803683370190505b50905060005b828110156127505760008860200151828151811061268d5761268d614f03565b602002602001015190507f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681600001516040015167ffffffffffffffff161461272057805160409081015190517f38432a2200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016106f8565b61272a818661356a565b83838151811061273c5761273c614f03565b60209081029190910101525060010161266d565b50600061276786838a606001518b6080015161368c565b9050806000036127af576040517f7dd17a7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff871660048201526024016106f8565b60005b83811015610cb65760005a905060008a6020015183815181106127d7576127d7614f03565b6020026020010151905060006127f58a836000015160600151610d2a565b9050600081600381111561280b5761280b614a70565b14806128285750600381600381111561282657612826614a70565b145b612880578151606001516040805167ffffffffffffffff808e16825290921660208301527f3b575419319662b2a6f5e2467d84521517a3382b908eb3d557bb3fdb0c50e23c91015b60405180910390a1505050612cc0565b881561295057600454600090600160a01b900463ffffffff166128a38742615576565b11905080806128c3575060038260038111156128c1576128c1614a70565b145b612905576040517fa9cfc86200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8c1660048201526024016106f8565b8b858151811061291757612917614f03565b602002602001015160001461294a578b858151811061293857612938614f03565b60200260200101518360800181815250505b506129b1565b600081600381111561296457612964614a70565b146129b1578151606001516040805167ffffffffffffffff808e16825290921660208301527f3ef2a99c550a751d4b0b261268f05a803dfb049ab43616a1ffb388f61fe651209101612870565b81516080015167ffffffffffffffff1615612aa05760008160038111156129da576129da614a70565b03612aa05781516080015160208301516040517fe0e03cae0000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169263e0e03cae92612a51928f929190600401615b1c565b6020604051808303816000875af1158015612a70573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a94919061548e565b612aa057505050612cc0565b60008c604001518581518110612ab857612ab8614f03565b6020026020010151905080518360a001515114612b1c578251606001516040517f1cfe6d8b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808e16600483015290911660248201526044016106f8565b612b308b84600001516060015160016136ca565b600080612b3d8584613772565b91509150612b548d866000015160600151846136ca565b8b15612bc4576003826003811115612b6e57612b6e614a70565b03612bc4576000846003811115612b8757612b87614a70565b14612bc4578451516040517f2b11b8d90000000000000000000000000000000000000000000000000000000081526106f891908390600401615b49565b6002826003811115612bd857612bd8614a70565b14612c32576003826003811115612bf157612bf1614a70565b14612c32578451606001516040517f926c5a3e0000000000000000000000000000000000000000000000000000000081526106f8918f918590600401615b62565b84600001516000015185600001516060015167ffffffffffffffff168e67ffffffffffffffff167f05665fe9ad095383d018353f4cbcba77e84db27dd215081bbf7cdf9ae6fbe48b8c8b81518110612c8c57612c8c614f03565b602002602001015186865a612ca1908e615576565b604051612cb19493929190615b88565b60405180910390a45050505050505b6001016127b2565b8251600090815b818110156111b8576000600188868460208110612cee57612cee614f03565b612cfb91901a601b61598f565b898581518110612d0d57612d0d614f03565b6020026020010151898681518110612d2757612d27614f03565b602002602001015160405160008152602001604052604051612d65949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015612d87573d6000803e3d6000fd5b505060408051601f1981015160ff808e166000908152600360209081528582206001600160a01b03851683528152858220858701909652855480841686529397509095509293928401916101009004166002811115612de857612de8614a70565b6002811115612df957612df9614a70565b9052509050600181602001516002811115612e1657612e16614a70565b14612e4d576040517fca31867a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051600160ff9091161b851615612e90576040517ff67bc7c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806000015160ff166001901b851794505050806001019050612ccf565b60408051808201909152600080825260208201526000612ed0876020015161383c565b6040517fbbe4f6db0000000000000000000000000000000000000000000000000000000081526001600160a01b0380831660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063bbe4f6db90602401602060405180830381865afa158015612f55573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f799190615bbf565b90506001600160a01b0381161580612fc15750612fbf6001600160a01b0382167faff2afbf00000000000000000000000000000000000000000000000000000000611fb5565b155b15613003576040517fae9b4ce90000000000000000000000000000000000000000000000000000000081526001600160a01b03821660048201526024016106f8565b60045460009081906130259089908690600160e01b900463ffffffff166138e2565b9150915060008060006130f26040518061010001604052808e81526020018c67ffffffffffffffff1681526020018d6001600160a01b031681526020018f606001518152602001896001600160a01b031681526020018f6000015181526020018f6040015181526020018b8152506040516024016130a39190615bdc565b60408051601f198184030181529190526020810180516001600160e01b03167f390775370000000000000000000000000000000000000000000000000000000017905287866113886084613a10565b9250925092508261313157816040517fe1cd55090000000000000000000000000000000000000000000000000000000081526004016106f8919061488b565b81516020146131795781516040517f78ef80240000000000000000000000000000000000000000000000000000000081526020600482015260248101919091526044016106f8565b60008280602001905181019061318f9190615ca9565b9050866001600160a01b03168c6001600160a01b0316146132245760006131c08d8a6131bb868a615576565b6138e2565b509050868110806131da5750816131d78883615576565b14155b15613222576040517fa966e21f0000000000000000000000000000000000000000000000000000000081526004810183905260248101889052604481018290526064016106f8565b505b604080518082019091526001600160a01b039098168852602088015250949550505050505095945050505050565b600061327e827f01ffc9a7000000000000000000000000000000000000000000000000000000006132b6565b8015610d7a57506132af827fffffffff000000000000000000000000000000000000000000000000000000006132b6565b1592915050565b6040517fffffffff0000000000000000000000000000000000000000000000000000000082166024820152600090819060440160408051601f19818403018152919052602080820180516001600160e01b03167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825192935060009283928392909183918a617530fa92503d9150600051905082801561335a575060208210155b80156133665750600081115b979650505050505050565b60005b81518110156107245760ff8316600090815260036020526040812083519091908490849081106133a6576133a6614f03565b6020908102919091018101516001600160a01b03168252810191909152604001600020805461ffff19169055600101613374565b60005b8251811015610d245760008382815181106133fa576133fa614f03565b602002602001015190506000600281111561341757613417614a70565b60ff80871660009081526003602090815260408083206001600160a01b0387168452909152902054610100900416600281111561345657613456614a70565b14613477576004604051631b3fab5160e11b81526004016106f89190615a3a565b6001600160a01b0381166134b7576040517fd6c62c9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052808360ff1681526020018460028111156134dd576134dd614a70565b905260ff80871660009081526003602090815260408083206001600160a01b0387168452825290912083518154931660ff198416811782559184015190929091839161ffff19161761010083600281111561353a5761353a614a70565b0217905550905050508060010190506133dd565b60ff8116610581576009805467ffffffffffffffff1916905550565b8151602080820151604092830151925160009384936135b0937f2425b0b9f9054c76ff151b0a175b18f37a4a4e82013a72e9f15c9caa095ed21f93909291889101615cc2565b60408051601f1981840301815290829052805160209182012086518051888401516060808b0151908401516080808d015195015195976135f99794969395929491939101615cf5565b604051602081830303815290604052805190602001208560400151805190602001208660a001516040516020016136309190615dfa565b60408051601f198184030181528282528051602091820120908301969096528101939093526060830191909152608082015260a081019190915260c0015b60405160208183030381529060405280519060200120905092915050565b60008061369a858585613b36565b67ffffffffffffffff8716600090815260086020908152604080832093835292905220549150505b949350505050565b600060026136d960808561559f565b67ffffffffffffffff166136ed91906155c6565b905060006136fb8585611ce9565b90508161370a60016004615576565b901b19168183600381111561372157613721614a70565b67ffffffffffffffff871660009081526007602052604081209190921b929092179182916137506080886159cc565b67ffffffffffffffff1681526020810191909152604001600020555050505050565b6040517fa80036b4000000000000000000000000000000000000000000000000000000008152600090606090309063a80036b4906137b69087908790600401615e5a565b600060405180830381600087803b1580156137d057600080fd5b505af19250505080156137e1575060015b613820573d80801561380f576040519150601f19603f3d011682016040523d82523d6000602084013e613814565b606091505b50600392509050613835565b50506040805160208101909152600081526002905b9250929050565b6000815160201461387b57816040517f8d666f600000000000000000000000000000000000000000000000000000000081526004016106f8919061488b565b6000828060200190518101906138919190615ca9565b90506001600160a01b038111806138a9575061040081105b15610d7a57826040517f8d666f600000000000000000000000000000000000000000000000000000000081526004016106f8919061488b565b600080600080600061395c8860405160240161390d91906001600160a01b0391909116815260200190565b60408051601f198184030181529190526020810180516001600160e01b03167f70a082310000000000000000000000000000000000000000000000000000000017905288886113886084613a10565b9250925092508261399b57816040517fe1cd55090000000000000000000000000000000000000000000000000000000081526004016106f8919061488b565b60208251146139e35781516040517f78ef80240000000000000000000000000000000000000000000000000000000081526020600482015260248101919091526044016106f8565b818060200190518101906139f79190615ca9565b613a018288615576565b94509450505050935093915050565b6000606060008361ffff1667ffffffffffffffff811115613a3357613a33613e9d565b6040519080825280601f01601f191660200182016040528015613a5d576020820181803683370190505b509150863b613a90577f0c3b563c0000000000000000000000000000000000000000000000000000000060005260046000fd5b5a85811015613ac3577fafa32a2c0000000000000000000000000000000000000000000000000000000060005260046000fd5b8590036040810481038710613afc577f37c3be290000000000000000000000000000000000000000000000000000000060005260046000fd5b505a6000808a5160208c0160008c8cf193505a900390503d84811115613b1f5750835b808352806000602085013e50955095509592505050565b8251825160009190818303613b77576040517f11a6b26400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6101018211801590613b8b57506101018111155b613ba8576040516309bde33960e01b815260040160405180910390fd5b60001982820101610100811115613bd2576040516309bde33960e01b815260040160405180910390fd5b80600003613bff5786600081518110613bed57613bed614f03565b60200260200101519350505050613dce565b60008167ffffffffffffffff811115613c1a57613c1a613e9d565b604051908082528060200260200182016040528015613c43578160200160208202803683370190505b50905060008080805b85811015613d6d5760006001821b8b811603613ca75788851015613c90578c5160018601958e918110613c8157613c81614f03565b60200260200101519050613cc9565b8551600185019487918110613c8157613c81614f03565b8b5160018401938d918110613cbe57613cbe614f03565b602002602001015190505b600089861015613cf9578d5160018701968f918110613cea57613cea614f03565b60200260200101519050613d1b565b8651600186019588918110613d1057613d10614f03565b602002602001015190505b82851115613d3c576040516309bde33960e01b815260040160405180910390fd5b613d468282613dd5565b878481518110613d5857613d58614f03565b60209081029190910101525050600101613c4c565b506001850382148015613d7f57508683145b8015613d8a57508581145b613da7576040516309bde33960e01b815260040160405180910390fd5b836001860381518110613dbc57613dbc614f03565b60200260200101519750505050505050505b9392505050565b6000818310613ded57613de88284613df3565b610d77565b610d7783835b60408051600160208201529081018390526060810182905260009060800161366e565b828054828255906000526020600020908101928215613e78579160200282015b82811115613e78578251825473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03909116178255602090920191600190910190613e36565b50613e84929150613e88565b5090565b5b80821115613e845760008155600101613e89565b634e487b7160e01b600052604160045260246000fd5b6040516080810167ffffffffffffffff81118282101715613ed657613ed6613e9d565b60405290565b60405160a0810167ffffffffffffffff81118282101715613ed657613ed6613e9d565b60405160c0810167ffffffffffffffff81118282101715613ed657613ed6613e9d565b6040805190810167ffffffffffffffff81118282101715613ed657613ed6613e9d565b6040516060810167ffffffffffffffff81118282101715613ed657613ed6613e9d565b604051601f8201601f1916810167ffffffffffffffff81118282101715613f9157613f91613e9d565b604052919050565b600067ffffffffffffffff821115613fb357613fb3613e9d565b5060051b60200190565b6001600160a01b038116811461058157600080fd5b803567ffffffffffffffff81168114613fea57600080fd5b919050565b801515811461058157600080fd5b8035613fea81613fef565b600067ffffffffffffffff82111561402257614022613e9d565b50601f01601f191660200190565b600082601f83011261404157600080fd5b813561405461404f82614008565b613f68565b81815284602083860101111561406957600080fd5b816020850160208301376000918101602001919091529392505050565b6000602080838503121561409957600080fd5b823567ffffffffffffffff808211156140b157600080fd5b818501915085601f8301126140c557600080fd5b81356140d361404f82613f99565b81815260059190911b830184019084810190888311156140f257600080fd5b8585015b838110156141985780358581111561410e5760008081fd5b86016080818c03601f19018113156141265760008081fd5b61412e613eb3565b8983013561413b81613fbd565b8152604061414a848201613fd2565b8b83015260608085013561415d81613fef565b8383015292840135928984111561417657600091508182fd5b6141848f8d86880101614030565b9083015250855250509186019186016140f6565b5098975050505050505050565b600060a082840312156141b757600080fd5b6141bf613edc565b9050813581526141d160208301613fd2565b60208201526141e260408301613fd2565b60408201526141f360608301613fd2565b606082015261420460808301613fd2565b608082015292915050565b8035613fea81613fbd565b600082601f83011261422b57600080fd5b8135602061423b61404f83613f99565b82815260059290921b8401810191818101908684111561425a57600080fd5b8286015b84811015611fa957803567ffffffffffffffff8082111561427f5760008081fd5b9088019060a0828b03601f19018113156142995760008081fd5b6142a1613edc565b87840135838111156142b35760008081fd5b6142c18d8a83880101614030565b825250604080850135848111156142d85760008081fd5b6142e68e8b83890101614030565b8a84015250606080860135858111156142ff5760008081fd5b61430d8f8c838a0101614030565b838501525060809150818601358184015250828501359250838311156143335760008081fd5b6143418d8a85880101614030565b90820152865250505091830191830161425e565b6000610140828403121561436857600080fd5b614370613eff565b905061437c83836141a5565b815260a082013567ffffffffffffffff8082111561439957600080fd5b6143a585838601614030565b602084015260c08401359150808211156143be57600080fd5b6143ca85838601614030565b60408401526143db60e0850161420f565b6060840152610100840135608084015261012084013591508082111561440057600080fd5b5061440d8482850161421a565b60a08301525092915050565b600082601f83011261442a57600080fd5b8135602061443a61404f83613f99565b82815260059290921b8401810191818101908684111561445957600080fd5b8286015b84811015611fa957803567ffffffffffffffff81111561447d5760008081fd5b61448b8986838b0101614355565b84525091830191830161445d565b600082601f8301126144aa57600080fd5b813560206144ba61404f83613f99565b82815260059290921b840181019181810190868411156144d957600080fd5b8286015b84811015611fa957803567ffffffffffffffff808211156144fd57600080fd5b818901915089603f83011261451157600080fd5b8582013561452161404f82613f99565b81815260059190911b830160400190878101908c83111561454157600080fd5b604085015b8381101561457a5780358581111561455d57600080fd5b61456c8f6040838a0101614030565b845250918901918901614546565b508752505050928401925083016144dd565b600082601f83011261459d57600080fd5b813560206145ad61404f83613f99565b8083825260208201915060208460051b8701019350868411156145cf57600080fd5b602086015b84811015611fa957803583529183019183016145d4565b600082601f8301126145fc57600080fd5b8135602061460c61404f83613f99565b82815260059290921b8401810191818101908684111561462b57600080fd5b8286015b84811015611fa957803567ffffffffffffffff808211156146505760008081fd5b9088019060a0828b03601f190181131561466a5760008081fd5b614672613edc565b61467d888501613fd2565b8152604080850135848111156146935760008081fd5b6146a18e8b83890101614419565b8a84015250606080860135858111156146ba5760008081fd5b6146c88f8c838a0101614499565b83850152506080915081860135858111156146e35760008081fd5b6146f18f8c838a010161458c565b918401919091525091909301359083015250835291830191830161462f565b600080604080848603121561472457600080fd5b833567ffffffffffffffff8082111561473c57600080fd5b614748878388016145eb565b945060209150818601358181111561475f57600080fd5b8601601f8101881361477057600080fd5b803561477e61404f82613f99565b81815260059190911b8201840190848101908a83111561479d57600080fd5b8584015b83811015614829578035868111156147b95760008081fd5b8501603f81018d136147cb5760008081fd5b878101356147db61404f82613f99565b81815260059190911b82018a0190898101908f8311156147fb5760008081fd5b928b01925b828410156148195783358252928a0192908a0190614800565b86525050509186019186016147a1565b50809750505050505050509250929050565b60005b8381101561485657818101518382015260200161483e565b50506000910152565b6000815180845261487781602086016020860161483b565b601f01601f19169290920160200192915050565b602081526000610d77602083018461485f565b8060608101831015610d7a57600080fd5b60008083601f8401126148c157600080fd5b50813567ffffffffffffffff8111156148d957600080fd5b60208301915083602082850101111561383557600080fd5b60008083601f84011261490357600080fd5b50813567ffffffffffffffff81111561491b57600080fd5b6020830191508360208260051b850101111561383557600080fd5b60008060008060008060008060e0898b03121561495257600080fd5b61495c8a8a61489e565b9750606089013567ffffffffffffffff8082111561497957600080fd5b6149858c838d016148af565b909950975060808b013591508082111561499e57600080fd5b6149aa8c838d016148f1565b909750955060a08b01359150808211156149c357600080fd5b506149d08b828c016148f1565b999c989b50969995989497949560c00135949350505050565b6000806000608084860312156149fe57600080fd5b614a08858561489e565b9250606084013567ffffffffffffffff811115614a2457600080fd5b614a30868287016148af565b9497909650939450505050565b60008060408385031215614a5057600080fd5b614a5983613fd2565b9150614a6760208401613fd2565b90509250929050565b634e487b7160e01b600052602160045260246000fd5b60048110614a9657614a96614a70565b9052565b60208101610d7a8284614a86565b600060208284031215614aba57600080fd5b813567ffffffffffffffff811115614ad157600080fd5b820160a08185031215613dce57600080fd5b803563ffffffff81168114613fea57600080fd5b600060a08284031215614b0957600080fd5b614b11613edc565b8235614b1c81613fbd565b8152614b2a60208401614ae3565b6020820152614b3b60408401614ae3565b6040820152614b4c60608401614ae3565b60608201526080830135614b5f81613fbd565b60808201529392505050565b600080600060408486031215614b8057600080fd5b833567ffffffffffffffff80821115614b9857600080fd5b614ba487838801614355565b94506020860135915080821115614bba57600080fd5b50614a30868287016148f1565b803560ff81168114613fea57600080fd5b600060208284031215614bea57600080fd5b610d7782614bc7565b60008151808452602080850194506020840160005b83811015614c2d5781516001600160a01b031687529582019590820190600101614c08565b509495945050505050565b60208152600082518051602084015260ff602082015116604084015260ff604082015116606084015260608101511515608084015250602083015160c060a0840152614c8760e0840182614bf3565b90506040840151601f198483030160c0850152614ca48282614bf3565b95945050505050565b60008060408385031215614cc057600080fd5b614cc983613fd2565b946020939093013593505050565b600060208284031215614ce957600080fd5b610d7782613fd2565b602081526001600160a01b03825116602082015260208201511515604082015267ffffffffffffffff6040830151166060820152600060608301516080808401526136c260a084018261485f565b600060208284031215614d5257600080fd5b8135613dce81613fbd565b600082601f830112614d6e57600080fd5b81356020614d7e61404f83613f99565b8083825260208201915060208460051b870101935086841115614da057600080fd5b602086015b84811015611fa9578035614db881613fbd565b8352918301918301614da5565b60006020808385031215614dd857600080fd5b823567ffffffffffffffff80821115614df057600080fd5b818501915085601f830112614e0457600080fd5b8135614e1261404f82613f99565b81815260059190911b83018401908481019088831115614e3157600080fd5b8585015b8381101561419857803585811115614e4c57600080fd5b860160c0818c03601f19011215614e635760008081fd5b614e6b613eff565b8882013581526040614e7e818401614bc7565b8a8301526060614e8f818501614bc7565b8284015260809150614ea2828501613ffd565b9083015260a08381013589811115614eba5760008081fd5b614ec88f8d83880101614d5d565b838501525060c0840135915088821115614ee25760008081fd5b614ef08e8c84870101614d5d565b9083015250845250918601918601614e35565b634e487b7160e01b600052603260045260246000fd5b80356001600160e01b0381168114613fea57600080fd5b600082601f830112614f4157600080fd5b81356020614f5161404f83613f99565b82815260069290921b84018101918181019086841115614f7057600080fd5b8286015b84811015611fa95760408189031215614f8d5760008081fd5b614f95613f22565b614f9e82613fd2565b8152614fab858301614f19565b81860152835291830191604001614f74565b600082601f830112614fce57600080fd5b81356020614fde61404f83613f99565b82815260059290921b84018101918181019086841115614ffd57600080fd5b8286015b84811015611fa957803567ffffffffffffffff808211156150225760008081fd5b9088019060a0828b03601f190181131561503c5760008081fd5b615044613edc565b61504f888501613fd2565b8152604061505e818601613fd2565b89830152606061506f818701613fd2565b8284015260809150818601358184015250828501359250838311156150945760008081fd5b6150a28d8a85880101614030565b908201528652505050918301918301615001565b600082601f8301126150c757600080fd5b813560206150d761404f83613f99565b82815260069290921b840181019181810190868411156150f657600080fd5b8286015b84811015611fa957604081890312156151135760008081fd5b61511b613f22565b8135815284820135858201528352918301916040016150fa565b6000602080838503121561514857600080fd5b823567ffffffffffffffff8082111561516057600080fd5b908401906060828703121561517457600080fd5b61517c613f45565b82358281111561518b57600080fd5b8301604081890381131561519e57600080fd5b6151a6613f22565b8235858111156151b557600080fd5b8301601f81018b136151c657600080fd5b80356151d461404f82613f99565b81815260069190911b8201890190898101908d8311156151f357600080fd5b928a01925b828410156152435785848f0312156152105760008081fd5b615218613f22565b843561522381613fbd565b8152615230858d01614f19565b818d0152825292850192908a01906151f8565b84525050508287013591508482111561525b57600080fd5b6152678a838501614f30565b8188015283525050828401358281111561528057600080fd5b61528c88828601614fbd565b858301525060408301359350818411156152a557600080fd5b6152b1878585016150b6565b60408201529695505050505050565b600082825180855260208086019550808260051b84010181860160005b8481101561535057858303601f190189528151805167ffffffffffffffff908116855285820151811686860152604080830151909116908501526060808201519085015260809081015160a09185018290529061533c8186018361485f565b9a86019a94505050908301906001016152dd565b5090979650505050505050565b60008151808452602080850194506020840160005b83811015614c2d578151805188528301518388015260409096019590820190600101615372565b6040815260006153ac60408301856152c0565b8281036020840152614ca4818561535d565b805160408084528151848201819052600092602091908201906060870190855b8181101561541557835180516001600160a01b031684528501516001600160e01b03168584015292840192918501916001016153de565b50508583015187820388850152805180835290840192506000918401905b8083101561546f578351805167ffffffffffffffff1683528501516001600160e01b031685830152928401926001929092019190850190615433565b50979650505050505050565b602081526000610d7760208301846153be565b6000602082840312156154a057600080fd5b8151613dce81613fef565b634e487b7160e01b600052601160045260246000fd5b67ffffffffffffffff8181168382160190808211156154e2576154e26154ab565b5092915050565b60208152600082516060602084015261550560808401826153be565b90506020840151601f198085840301604086015261552383836152c0565b9250604086015191508085840301606086015250614ca4828261535d565b60006020828403121561555357600080fd5b813567ffffffffffffffff81111561556a57600080fd5b6136c2848285016145eb565b81810381811115610d7a57610d7a6154ab565b634e487b7160e01b600052601260045260246000fd5b600067ffffffffffffffff808416806155ba576155ba615589565b92169190910692915050565b8082028115828204841417610d7a57610d7a6154ab565b805182526000602067ffffffffffffffff81840151168185015260408084015160a0604087015261561160a087018261485f565b90506060850151868203606088015261562a828261485f565b608087810151898303918a01919091528051808352908601935060009250908501905b8083101561546f57835180516001600160a01b031683528601518683015292850192600192909201919084019061564d565b602081526000610d7760208301846155dd565b6080815260006156a560808301876155dd565b61ffff9590951660208301525060408101929092526001600160a01b0316606090910152919050565b6000806000606084860312156156e357600080fd5b83516156ee81613fef565b602085015190935067ffffffffffffffff81111561570b57600080fd5b8401601f8101861361571c57600080fd5b805161572a61404f82614008565b81815287602083850101111561573f57600080fd5b61575082602083016020860161483b565b809450505050604084015190509250925092565b600181811c9082168061577857607f821691505b60208210810361579857634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115610724576000816000526020600020601f850160051c810160208610156157c75750805b601f850160051c820191505b818110156157e6578281556001016157d3565b505050505050565b815167ffffffffffffffff81111561580857615808613e9d565b61581c816158168454615764565b8461579e565b602080601f83116001811461585157600084156158395750858301515b600019600386901b1c1916600185901b1785556157e6565b600085815260208120601f198616915b8281101561588057888601518255948401946001909101908401615861565b508582101561589e5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6000602080835283546001600160a01b038116602085015260ff8160a01c161515604085015267ffffffffffffffff8160a81c1660608501525060018085016080808601526000815461590081615764565b8060a089015260c06001831660008114615921576001811461593d5761596d565b60ff19841660c08b015260c083151560051b8b0101945061596d565b85600052602060002060005b848110156159645781548c8201850152908801908901615949565b8b0160c0019550505b50929998505050505050505050565b80820180821115610d7a57610d7a6154ab565b60ff8181168382160190811115610d7a57610d7a6154ab565b8183823760009101908152919050565b828152606082602083013760800192915050565b600067ffffffffffffffff808416806159e7576159e7615589565b92169190910492915050565b6000808335601e19843603018112615a0a57600080fd5b83018035915067ffffffffffffffff821115615a2557600080fd5b60200191503681900382131561383557600080fd5b6020810160058310615a4e57615a4e614a70565b91905290565b60ff81811683821602908116908181146154e2576154e26154ab565b600060a0820160ff881683526020878185015260a0604085015281875480845260c0860191508860005282600020935060005b81811015615ac85784546001600160a01b031683526001948501949284019201615aa3565b50508481036060860152865180825290820192508187019060005b81811015615b085782516001600160a01b031685529383019391830191600101615ae3565b50505060ff85166080850152509050611fab565b600067ffffffffffffffff808616835280851660208401525060606040830152614ca4606083018461485f565b8281526040602082015260006136c2604083018461485f565b67ffffffffffffffff848116825283166020820152606081016136c26040830184614a86565b848152615b986020820185614a86565b608060408201526000615bae608083018561485f565b905082606083015295945050505050565b600060208284031215615bd157600080fd5b8151613dce81613fbd565b6020815260008251610100806020850152615bfb61012085018361485f565b91506020850151615c18604086018267ffffffffffffffff169052565b5060408501516001600160a01b038116606086015250606085015160808501526080850151615c5260a08601826001600160a01b03169052565b5060a0850151601f19808685030160c0870152615c6f848361485f565b935060c08701519150808685030160e0870152615c8c848361485f565b935060e0870151915080868503018387015250611fab838261485f565b600060208284031215615cbb57600080fd5b5051919050565b848152600067ffffffffffffffff808616602084015280851660408401525060806060830152611fab608083018461485f565b86815260c060208201526000615d0e60c083018861485f565b6001600160a01b039690961660408301525067ffffffffffffffff9384166060820152608081019290925290911660a09091015292915050565b600082825180855260208086019550808260051b84010181860160005b8481101561535057601f19868403018952815160a08151818652615d8b8287018261485f565b9150508582015185820387870152615da3828261485f565b91505060408083015186830382880152615dbd838261485f565b92505050606080830151818701525060808083015192508582038187015250615de6818361485f565b9a86019a9450505090830190600101615d65565b602081526000610d776020830184615d48565b60008282518085526020808601955060208260051b8401016020860160005b8481101561535057601f19868403018952615e4883835161485f565b98840198925090830190600101615e2c565b604081526000835180516040840152602081015167ffffffffffffffff80821660608601528060408401511660808601528060608401511660a08601528060808401511660c086015250505060208401516101408060e0850152615ec261018085018361485f565b91506040860151603f198086850301610100870152615ee1848361485f565b935060608801519150615f006101208701836001600160a01b03169052565b60808801518387015260a0880151925080868503016101608701525050615f278282615d48565b9150508281036020840152614ca48185615e0d56fea164736f6c6343000818000a", } var OffRampABI = OffRampMetaData.ABI diff --git a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt index e64f3f38f8..659e8ac648 100644 --- a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -23,7 +23,7 @@ multi_aggregate_rate_limiter: ../../../contracts/solc/v0.8.24/MultiAggregateRate multi_ocr3_helper: ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Helper.abi ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Helper.bin 6b56e0114a4d50797d30a34aecc2641ef340451d0c3fcb9d729bba4df2435122 nonce_manager: ../../../contracts/solc/v0.8.24/NonceManager/NonceManager.abi ../../../contracts/solc/v0.8.24/NonceManager/NonceManager.bin 6f64e1083b356c06ee66b9138e398b9c97a4cd3e8c9ec38cf3010cebc79af536 ocr3_config_encoder: ../../../contracts/solc/v0.8.24/IOCR3ConfigEncoder/IOCR3ConfigEncoder.abi ../../../contracts/solc/v0.8.24/IOCR3ConfigEncoder/IOCR3ConfigEncoder.bin 9254b35a86f00fde7b7193a033ca58f6521a66e87b9cf9da6ce5660082e79f5d -offramp: ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.abi ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.bin a97246b6e73f0ac7bea5677b8bb536a085280effc3c110cd4859a93ceed474af +offramp: ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.abi ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.bin e6827d4a39ed916c3ffa5a7d08b6bfa03cf101bee7207e5c96723b6a9fc761b0 onramp: ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.abi ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.bin c37096aaa0369ad988e94c300ba62917e17fcc71a3c1aa3e9b8420f21c0591d2 ping_pong_demo: ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.abi ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.bin c1c2f8a65c7ffd971899cae7fe62f2da57d09e936151e2b92163c4bebe699d6b price_registry: ../../../contracts/solc/v0.8.24/PriceRegistry/PriceRegistry.abi ../../../contracts/solc/v0.8.24/PriceRegistry/PriceRegistry.bin e7781d600c1bb7aa4620106af7f6e146a109b97f4cb6a7d06c9e15773340ecb2 From 01c503fdc9b06896ef3356782d6059e8bbd328cd Mon Sep 17 00:00:00 2001 From: Ryan <80392855+RayXpub@users.noreply.github.com> Date: Thu, 5 Sep 2024 16:19:55 +0400 Subject: [PATCH 074/115] Add report vs message source chain selector check (#1413) ## Motivation The goal of this PR is to add an extra check in the execute function to enforce that the report source chain selector matches its messages source chain selector. Extra gas cost is about 50 gas per message. ## Solution Revert when `report.sourceChainSelector != (message.header.sourceChainSelector` --- contracts/gas-snapshots/ccip.gas-snapshot | 129 +++++++++--------- contracts/src/v0.8/ccip/offRamp/OffRamp.sol | 7 + .../src/v0.8/ccip/test/offRamp/OffRamp.t.sol | 22 +++ .../ccip/generated/offramp/offramp.go | 4 +- ...rapper-dependency-versions-do-not-edit.txt | 2 +- 5 files changed, 97 insertions(+), 67 deletions(-) diff --git a/contracts/gas-snapshots/ccip.gas-snapshot b/contracts/gas-snapshots/ccip.gas-snapshot index d684185072..0f352370f8 100644 --- a/contracts/gas-snapshots/ccip.gas-snapshot +++ b/contracts/gas-snapshots/ccip.gas-snapshot @@ -560,18 +560,18 @@ MultiOCR3Base_transmit:test_UnauthorizedSigner_Revert() (gas: 61131) MultiOCR3Base_transmit:test_UnconfiguredPlugin_Revert() (gas: 39888) MultiOCR3Base_transmit:test_ZeroSignatures_Revert() (gas: 32971) MultiOnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 411393) -MultiRampsE2E:test_E2E_3MessagesMMultiOffRampSuccess_gas() (gas: 1526613) +MultiRampsE2E:test_E2E_3MessagesMMultiOffRampSuccess_gas() (gas: 1526772) NonceManager_NonceIncrementation:test_getIncrementedOutboundNonce_Success() (gas: 37907) NonceManager_NonceIncrementation:test_incrementInboundNonce_Skip() (gas: 23703) NonceManager_NonceIncrementation:test_incrementInboundNonce_Success() (gas: 38790) NonceManager_NonceIncrementation:test_incrementNoncesInboundAndOutbound_Success() (gas: 71874) -NonceManager_OffRampUpgrade:test_NoPrevOffRampForChain_Success() (gas: 259788) -NonceManager_OffRampUpgrade:test_UpgradedNonceNewSenderStartsAtZero_Success() (gas: 263930) -NonceManager_OffRampUpgrade:test_UpgradedNonceStartsAtV1Nonce_Success() (gas: 326647) -NonceManager_OffRampUpgrade:test_UpgradedOffRampNonceSkipsIfMsgInFlight_Success() (gas: 298821) +NonceManager_OffRampUpgrade:test_NoPrevOffRampForChain_Success() (gas: 259841) +NonceManager_OffRampUpgrade:test_UpgradedNonceNewSenderStartsAtZero_Success() (gas: 263983) +NonceManager_OffRampUpgrade:test_UpgradedNonceStartsAtV1Nonce_Success() (gas: 326753) +NonceManager_OffRampUpgrade:test_UpgradedOffRampNonceSkipsIfMsgInFlight_Success() (gas: 298927) NonceManager_OffRampUpgrade:test_UpgradedSenderNoncesReadsPreviousRampTransitive_Success() (gas: 244682) NonceManager_OffRampUpgrade:test_UpgradedSenderNoncesReadsPreviousRamp_Success() (gas: 232797) -NonceManager_OffRampUpgrade:test_Upgraded_Success() (gas: 152756) +NonceManager_OffRampUpgrade:test_Upgraded_Success() (gas: 152809) NonceManager_OnRampUpgrade:test_UpgradeNonceNewSenderStartsAtZero_Success() (gas: 168320) NonceManager_OnRampUpgrade:test_UpgradeNonceStartsAtV1Nonce_Success() (gas: 220111) NonceManager_OnRampUpgrade:test_UpgradeSenderNoncesReadsPreviousRamp_Success() (gas: 125079) @@ -623,21 +623,21 @@ OffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChain_Success() (gas: OffRamp_applySourceChainConfigUpdates:test_RouterAddress_Revert() (gas: 13260) OffRamp_applySourceChainConfigUpdates:test_ZeroOnRampAddress_Revert() (gas: 17994) OffRamp_applySourceChainConfigUpdates:test_ZeroSourceChainSelector_Revert() (gas: 15349) -OffRamp_batchExecute:test_MultipleReportsDifferentChainsSkipCursedChain_Success() (gas: 176779) -OffRamp_batchExecute:test_MultipleReportsDifferentChains_Success() (gas: 332397) -OffRamp_batchExecute:test_MultipleReportsSameChain_Success() (gas: 275765) -OffRamp_batchExecute:test_MultipleReportsSkipDuplicate_Success() (gas: 167867) -OffRamp_batchExecute:test_OutOfBoundsGasLimitsAccess_Revert() (gas: 187343) -OffRamp_batchExecute:test_SingleReport_Success() (gas: 155847) -OffRamp_batchExecute:test_Unhealthy_Success() (gas: 572707) +OffRamp_batchExecute:test_MultipleReportsDifferentChainsSkipCursedChain_Success() (gas: 176832) +OffRamp_batchExecute:test_MultipleReportsDifferentChains_Success() (gas: 332556) +OffRamp_batchExecute:test_MultipleReportsSameChain_Success() (gas: 275924) +OffRamp_batchExecute:test_MultipleReportsSkipDuplicate_Success() (gas: 167973) +OffRamp_batchExecute:test_OutOfBoundsGasLimitsAccess_Revert() (gas: 187449) +OffRamp_batchExecute:test_SingleReport_Success() (gas: 155900) +OffRamp_batchExecute:test_Unhealthy_Success() (gas: 572813) OffRamp_batchExecute:test_ZeroReports_Revert() (gas: 10440) OffRamp_ccipReceive:test_Reverts() (gas: 15705) OffRamp_commit:test_FailedRMNVerification_Reverts() (gas: 64218) OffRamp_commit:test_InvalidIntervalMinLargerThanMax_Revert() (gas: 67373) OffRamp_commit:test_InvalidInterval_Revert() (gas: 59676) OffRamp_commit:test_InvalidRootRevert() (gas: 58728) -OffRamp_commit:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6572843) -OffRamp_commit:test_NoConfig_Revert() (gas: 6156722) +OffRamp_commit:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6595300) +OffRamp_commit:test_NoConfig_Revert() (gas: 6179179) OffRamp_commit:test_OnlyGasPriceUpdates_Success() (gas: 113211) OffRamp_commit:test_OnlyPriceUpdateStaleReport_Revert() (gas: 121156) OffRamp_commit:test_OnlyTokenPriceUpdates_Success() (gas: 113232) @@ -650,25 +650,25 @@ OffRamp_commit:test_StaleReportWithRoot_Success() (gas: 239068) OffRamp_commit:test_UnauthorizedTransmitter_Revert() (gas: 122234) OffRamp_commit:test_Unhealthy_Revert() (gas: 57761) OffRamp_commit:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 211577) -OffRamp_commit:test_WrongConfigWithoutSigners_Revert() (gas: 6569232) +OffRamp_commit:test_WrongConfigWithoutSigners_Revert() (gas: 6591689) OffRamp_commit:test_ZeroEpochAndRound_Revert() (gas: 51147) -OffRamp_constructor:test_Constructor_Success() (gas: 6157449) -OffRamp_constructor:test_SourceChainSelector_Revert() (gas: 137102) -OffRamp_constructor:test_ZeroChainSelector_Revert() (gas: 103831) -OffRamp_constructor:test_ZeroNonceManager_Revert() (gas: 101702) -OffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 139743) -OffRamp_constructor:test_ZeroRMNRemote_Revert() (gas: 101631) -OffRamp_constructor:test_ZeroTokenAdminRegistry_Revert() (gas: 101646) +OffRamp_constructor:test_Constructor_Success() (gas: 6179907) +OffRamp_constructor:test_SourceChainSelector_Revert() (gas: 137132) +OffRamp_constructor:test_ZeroChainSelector_Revert() (gas: 103861) +OffRamp_constructor:test_ZeroNonceManager_Revert() (gas: 101732) +OffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 139773) +OffRamp_constructor:test_ZeroRMNRemote_Revert() (gas: 101661) +OffRamp_constructor:test_ZeroTokenAdminRegistry_Revert() (gas: 101676) OffRamp_execute:test_IncorrectArrayType_Revert() (gas: 17281) -OffRamp_execute:test_LargeBatch_Success() (gas: 3374948) -OffRamp_execute:test_MultipleReportsWithPartialValidationFailures_Success() (gas: 372169) -OffRamp_execute:test_MultipleReports_Success() (gas: 298074) -OffRamp_execute:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6620946) -OffRamp_execute:test_NoConfig_Revert() (gas: 6204499) +OffRamp_execute:test_LargeBatch_Success() (gas: 3376538) +OffRamp_execute:test_MultipleReportsWithPartialValidationFailures_Success() (gas: 372328) +OffRamp_execute:test_MultipleReports_Success() (gas: 298233) +OffRamp_execute:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6643456) +OffRamp_execute:test_NoConfig_Revert() (gas: 6227009) OffRamp_execute:test_NonArray_Revert() (gas: 27718) -OffRamp_execute:test_SingleReport_Success() (gas: 175099) -OffRamp_execute:test_UnauthorizedTransmitter_Revert() (gas: 147327) -OffRamp_execute:test_WrongConfigWithSigners_Revert() (gas: 6982447) +OffRamp_execute:test_SingleReport_Success() (gas: 175152) +OffRamp_execute:test_UnauthorizedTransmitter_Revert() (gas: 147380) +OffRamp_execute:test_WrongConfigWithSigners_Revert() (gas: 7004957) OffRamp_execute:test_ZeroReports_Revert() (gas: 17156) OffRamp_executeSingleMessage:test_MessageSender_Revert() (gas: 18212) OffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 248992) @@ -682,47 +682,48 @@ OffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens_Success() (gas OffRamp_executeSingleMessage:test_executeSingleMessage_WithValidation_Success() (gas: 92403) OffRamp_executeSingleReport:test_DisabledSourceChain_Revert() (gas: 28225) OffRamp_executeSingleReport:test_EmptyReport_Revert() (gas: 21854) -OffRamp_executeSingleReport:test_InvalidSourcePoolAddress_Success() (gas: 501555) -OffRamp_executeSingleReport:test_ManualExecutionNotYetEnabled_Revert() (gas: 47569) +OffRamp_executeSingleReport:test_InvalidSourcePoolAddress_Success() (gas: 501661) +OffRamp_executeSingleReport:test_ManualExecutionNotYetEnabled_Revert() (gas: 47622) OffRamp_executeSingleReport:test_MismatchingDestChainSelector_Revert() (gas: 33855) -OffRamp_executeSingleReport:test_MismatchingOnRampRoot_Revert() (gas: 154807) +OffRamp_executeSingleReport:test_MismatchingOnRampRoot_Revert() (gas: 154860) OffRamp_executeSingleReport:test_NonExistingSourceChain_Revert() (gas: 28459) -OffRamp_executeSingleReport:test_ReceiverError_Success() (gas: 187481) -OffRamp_executeSingleReport:test_RetryFailedMessageWithoutManualExecution_Revert() (gas: 197900) -OffRamp_executeSingleReport:test_RootNotCommitted_Revert() (gas: 40076) -OffRamp_executeSingleReport:test_RouterYULCall_Revert() (gas: 447326) -OffRamp_executeSingleReport:test_SingleMessageNoTokensOtherChain_Success() (gas: 247718) -OffRamp_executeSingleReport:test_SingleMessageNoTokensUnordered_Success() (gas: 191985) -OffRamp_executeSingleReport:test_SingleMessageNoTokens_Success() (gas: 211578) -OffRamp_executeSingleReport:test_SingleMessageToNonCCIPReceiver_Success() (gas: 259646) -OffRamp_executeSingleReport:test_SingleMessagesNoTokensSuccess_gas() (gas: 140761) -OffRamp_executeSingleReport:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 424145) -OffRamp_executeSingleReport:test_SkippedIncorrectNonce_Success() (gas: 58992) -OffRamp_executeSingleReport:test_TokenDataMismatch_Revert() (gas: 74047) -OffRamp_executeSingleReport:test_TwoMessagesWithTokensAndGE_Success() (gas: 595794) -OffRamp_executeSingleReport:test_TwoMessagesWithTokensSuccess_gas() (gas: 543647) +OffRamp_executeSingleReport:test_ReceiverError_Success() (gas: 187534) +OffRamp_executeSingleReport:test_RetryFailedMessageWithoutManualExecution_Revert() (gas: 198006) +OffRamp_executeSingleReport:test_RootNotCommitted_Revert() (gas: 40129) +OffRamp_executeSingleReport:test_RouterYULCall_Revert() (gas: 447379) +OffRamp_executeSingleReport:test_SingleMessageNoTokensOtherChain_Success() (gas: 247824) +OffRamp_executeSingleReport:test_SingleMessageNoTokensUnordered_Success() (gas: 192091) +OffRamp_executeSingleReport:test_SingleMessageNoTokens_Success() (gas: 211684) +OffRamp_executeSingleReport:test_SingleMessageToNonCCIPReceiver_Success() (gas: 259699) +OffRamp_executeSingleReport:test_SingleMessagesNoTokensSuccess_gas() (gas: 140814) +OffRamp_executeSingleReport:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 424251) +OffRamp_executeSingleReport:test_SkippedIncorrectNonce_Success() (gas: 59045) +OffRamp_executeSingleReport:test_TokenDataMismatch_Revert() (gas: 74100) +OffRamp_executeSingleReport:test_TwoMessagesWithTokensAndGE_Success() (gas: 595900) +OffRamp_executeSingleReport:test_TwoMessagesWithTokensSuccess_gas() (gas: 543753) OffRamp_executeSingleReport:test_UnexpectedTokenData_Revert() (gas: 33671) -OffRamp_executeSingleReport:test_UnhealthySingleChainCurse_Revert() (gas: 568625) -OffRamp_executeSingleReport:test_Unhealthy_Success() (gas: 568639) -OffRamp_executeSingleReport:test_WithCurseOnAnotherSourceChain_Success() (gas: 474070) -OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessageUnordered_Success() (gas: 135265) -OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessage_Success() (gas: 164484) +OffRamp_executeSingleReport:test_UnhealthySingleChainCurse_Revert() (gas: 568731) +OffRamp_executeSingleReport:test_Unhealthy_Success() (gas: 568745) +OffRamp_executeSingleReport:test_WithCurseOnAnotherSourceChain_Success() (gas: 474176) +OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessageUnordered_Success() (gas: 135371) +OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessage_Success() (gas: 164590) OffRamp_getExecutionState:test_FillExecutionState_Success() (gas: 3635486) OffRamp_getExecutionState:test_GetDifferentChainExecutionState_Success() (gas: 118398) OffRamp_getExecutionState:test_GetExecutionState_Success() (gas: 87417) OffRamp_manuallyExecute:test_ManualExecGasLimitMismatchSingleReport_Revert() (gas: 75545) OffRamp_manuallyExecute:test_ManualExecInvalidGasLimit_Revert() (gas: 26439) -OffRamp_manuallyExecute:test_manuallyExecute_DoesNotRevertIfUntouched_Success() (gas: 171175) -OffRamp_manuallyExecute:test_manuallyExecute_FailedTx_Revert() (gas: 210959) -OffRamp_manuallyExecute:test_manuallyExecute_ForkedChain_Revert() (gas: 25990) -OffRamp_manuallyExecute:test_manuallyExecute_GasLimitMismatchMultipleReports_Revert() (gas: 152828) -OffRamp_manuallyExecute:test_manuallyExecute_LowGasLimit_Success() (gas: 529679) -OffRamp_manuallyExecute:test_manuallyExecute_MultipleReportsWithSingleCursedLane_Revert() (gas: 310107) -OffRamp_manuallyExecute:test_manuallyExecute_ReentrancyFails_Success() (gas: 2389581) -OffRamp_manuallyExecute:test_manuallyExecute_Success() (gas: 223886) -OffRamp_manuallyExecute:test_manuallyExecute_WithGasOverride_Success() (gas: 224461) -OffRamp_manuallyExecute:test_manuallyExecute_WithMultiReportGasOverride_Success() (gas: 767127) -OffRamp_manuallyExecute:test_manuallyExecute_WithPartialMessages_Success() (gas: 342767) +OffRamp_manuallyExecute:test_manuallyExecute_DoesNotRevertIfUntouched_Success() (gas: 171228) +OffRamp_manuallyExecute:test_manuallyExecute_FailedTx_Revert() (gas: 211065) +OffRamp_manuallyExecute:test_manuallyExecute_ForkedChain_Revert() (gas: 26057) +OffRamp_manuallyExecute:test_manuallyExecute_GasLimitMismatchMultipleReports_Revert() (gas: 152806) +OffRamp_manuallyExecute:test_manuallyExecute_LowGasLimit_Success() (gas: 529785) +OffRamp_manuallyExecute:test_manuallyExecute_MultipleReportsWithSingleCursedLane_Revert() (gas: 310294) +OffRamp_manuallyExecute:test_manuallyExecute_ReentrancyFails_Success() (gas: 2389687) +OffRamp_manuallyExecute:test_manuallyExecute_SourceChainSelectorMismatch_Revert() (gas: 162168) +OffRamp_manuallyExecute:test_manuallyExecute_Success() (gas: 223992) +OffRamp_manuallyExecute:test_manuallyExecute_WithGasOverride_Success() (gas: 224567) +OffRamp_manuallyExecute:test_manuallyExecute_WithMultiReportGasOverride_Success() (gas: 767657) +OffRamp_manuallyExecute:test_manuallyExecute_WithPartialMessages_Success() (gas: 342979) OffRamp_releaseOrMintTokens:test_TokenHandlingError_Reverts() (gas: 165844) OffRamp_releaseOrMintTokens:test__releaseOrMintTokens_PoolIsNotAPool_Reverts() (gas: 24622) OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_InvalidDataLengthReturnData_Revert() (gas: 66304) diff --git a/contracts/src/v0.8/ccip/offRamp/OffRamp.sol b/contracts/src/v0.8/ccip/offRamp/OffRamp.sol index 10bde4c251..6753e260cd 100644 --- a/contracts/src/v0.8/ccip/offRamp/OffRamp.sol +++ b/contracts/src/v0.8/ccip/offRamp/OffRamp.sol @@ -58,6 +58,7 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { error InvalidInterval(uint64 sourceChainSelector, uint64 min, uint64 max); error ZeroAddressNotAllowed(); error InvalidMessageDestChainSelector(uint64 messageDestChainSelector); + error SourceChainSelectorMismatch(uint64 reportSourceChainSelector, uint64 messageSourceChainSelector); /// @dev Atlas depends on this event, if changing, please notify Atlas. event StaticConfigSet(StaticConfig staticConfig); @@ -353,6 +354,12 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { if (message.header.destChainSelector != i_chainSelector) { revert InvalidMessageDestChainSelector(message.header.destChainSelector); } + // If the message source chain selector does not match the report's source chain selector and + // the root has not been committed for the report source chain selector, this will be caught by the root verification. + // This acts as an extra check. + if (message.header.sourceChainSelector != sourceChainSelector) { + revert SourceChainSelectorMismatch(sourceChainSelector, message.header.sourceChainSelector); + } // We do this hash here instead of in _verify to avoid two separate loops // over the same data, which increases gas cost. diff --git a/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol index 8db8be3d11..83da20eb6f 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol @@ -1864,6 +1864,28 @@ contract OffRamp_manuallyExecute is OffRampSetup { s_offRamp.manuallyExecute(reports, gasLimitOverrides); } + + function test_manuallyExecute_SourceChainSelectorMismatch_Revert() public { + Internal.Any2EVMRampMessage[] memory messages1 = new Internal.Any2EVMRampMessage[](1); + Internal.Any2EVMRampMessage[] memory messages2 = new Internal.Any2EVMRampMessage[](1); + messages1[0] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); + messages2[0] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); + + Internal.ExecutionReportSingleChain[] memory reports = new Internal.ExecutionReportSingleChain[](2); + reports[0] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages1); + reports[1] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_3, messages2); + + uint256[][] memory gasLimitOverrides = new uint256[][](2); + gasLimitOverrides[0] = _getGasLimitsFromMessages(messages1); + gasLimitOverrides[1] = _getGasLimitsFromMessages(messages2); + + vm.expectRevert( + abi.encodeWithSelector( + OffRamp.SourceChainSelectorMismatch.selector, SOURCE_CHAIN_SELECTOR_3, SOURCE_CHAIN_SELECTOR_1 + ) + ); + s_offRamp.manuallyExecute(reports, gasLimitOverrides); + } } contract OffRamp_execute is OffRampSetup { diff --git a/core/gethwrappers/ccip/generated/offramp/offramp.go b/core/gethwrappers/ccip/generated/offramp/offramp.go index 51edddf954..3204871921 100644 --- a/core/gethwrappers/ccip/generated/offramp/offramp.go +++ b/core/gethwrappers/ccip/generated/offramp/offramp.go @@ -162,8 +162,8 @@ type OffRampStaticConfig struct { } var OffRampMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CanOnlySelfCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"actual\",\"type\":\"bytes32\"}],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ExecutionError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"ForkedChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enumMultiOCR3Base.InvalidConfigErrorType\",\"name\":\"errorType\",\"type\":\"uint8\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"got\",\"type\":\"uint256\"}],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidEVMAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"name\":\"InvalidInterval\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"newLimit\",\"type\":\"uint256\"}],\"name\":\"InvalidManualExecutionGasLimit\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"messageDestChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidMessageDestChainSelector\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"newState\",\"type\":\"uint8\"}],\"name\":\"InvalidNewState\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRoot\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidStaticConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LeavesCannotBeEmpty\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ManualExecutionGasLimitMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"ManualExecutionNotYetEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"errorReason\",\"type\":\"bytes\"}],\"name\":\"MessageValidationError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonUniqueSignatures\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"notPool\",\"type\":\"address\"}],\"name\":\"NotACompatiblePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OracleCannotBeZeroAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ReceiverError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountReleased\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePre\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePost\",\"type\":\"uint256\"}],\"name\":\"ReleaseOrMintBalanceMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"name\":\"RootAlreadyCommitted\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"RootNotCommitted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignaturesOutOfRegistration\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"StaleCommitReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"StaticConfigCannotBeChanged\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"TokenDataMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"TokenHandlingError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnexpectedTokenData\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"WrongMessageLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WrongNumberOfSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroChainSelectorNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"AlreadyAttempted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"structIRMNV2.Signature[]\",\"name\":\"rmnSignatures\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"report\",\"type\":\"tuple\"}],\"name\":\"CommitReportAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"DynamicConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"messageHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"name\":\"ExecutionStateChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"RootRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"SkippedAlreadyExecutedMessage\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SkippedReportExecution\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"sourceConfig\",\"type\":\"tuple\"}],\"name\":\"SourceChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainSelectorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"}],\"name\":\"StaticConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigUpdates\",\"type\":\"tuple[]\"}],\"name\":\"applySourceChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"destTokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structClient.Any2EVMMessage\",\"name\":\"\",\"type\":\"tuple\"}],\"name\":\"ccipReceive\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"rawVs\",\"type\":\"bytes32\"}],\"name\":\"commit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"execute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"bytes[]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[]\"}],\"name\":\"executeSingleMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"getExecutionState\",\"outputs\":[{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLatestPriceSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"getMerkleRoot\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"getSourceChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"latestConfigDetails\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"n\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"}],\"internalType\":\"structMultiOCR3Base.ConfigInfo\",\"name\":\"configInfo\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfig\",\"name\":\"ocrConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage[]\",\"name\":\"messages\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[][]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[][]\"},{\"internalType\":\"bytes32[]\",\"name\":\"proofs\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"proofFlagBits\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.ExecutionReportSingleChain[]\",\"name\":\"reports\",\"type\":\"tuple[]\"},{\"internalType\":\"uint256[][]\",\"name\":\"gasLimitOverrides\",\"type\":\"uint256[][]\"}],\"name\":\"manuallyExecute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"setDynamicConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfigArgs[]\",\"name\":\"ocrConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"setOCR3Configs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x6101206040523480156200001257600080fd5b5060405162006c2638038062006c268339810160408190526200003591620008c7565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf81620001fa565b5050466080525060208301516001600160a01b03161580620000ec575060408301516001600160a01b0316155b8062000103575060608301516001600160a01b0316155b1562000122576040516342bcdf7f60e11b815260040160405180910390fd5b82516001600160401b03166000036200014e5760405163c656089560e01b815260040160405180910390fd5b82516001600160401b0390811660a052602080850180516001600160a01b0390811660c05260408088018051831660e0526060808a01805185166101005283518b519098168852945184169587019590955251821690850152905116908201527f683eb52ee924eb817377cfa8f41f238f4bb7a877da5267869dfffbad85f564d89060800160405180910390a1620001e682620002a5565b620001f181620003c1565b50505062000c67565b336001600160a01b03821603620002545760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b0316620002ce576040516342bcdf7f60e11b815260040160405180910390fd5b80516004805460208085018051604080880180516060808b0180516001600160a01b039b8c166001600160c01b0319909a168a17600160a01b63ffffffff98891602176001600160c01b0316600160c01b948816949094026001600160e01b031693909317600160e01b93871693909302929092179098556080808b018051600580546001600160a01b031916918d169190911790558451988952955185169688019690965290518316918601919091525116938301939093529151909216908201527fa55bd56595c45f517e5967a3067f3dca684445a3080e7c04a4e0d5a40cda627d9060a00160405180910390a150565b60005b815181101562000666576000828281518110620003e557620003e562000a1d565b60200260200101519050600081602001519050806001600160401b0316600003620004235760405163c656089560e01b815260040160405180910390fd5b81516001600160a01b03166200044c576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160401b0381166000908152600660205260408120600181018054919291620004789062000a33565b80601f0160208091040260200160405190810160405280929190818152602001828054620004a69062000a33565b8015620004f75780601f10620004cb57610100808354040283529160200191620004f7565b820191906000526020600020905b815481529060010190602001808311620004d957829003601f168201915b5050505050905060008460600151905081516000036200059e57805160000362000534576040516342bcdf7f60e11b815260040160405180910390fd5b6001830162000544828262000ac4565b508254600160a81b600160e81b031916600160a81b1783556040516001600160401b03851681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1620005d9565b8080519060200120828051906020012014620005d95760405163c39a620560e01b81526001600160401b038516600482015260240162000083565b604080860151845487516001600160a01b03166001600160a01b0319921515600160a01b02929092166001600160a81b031990911617178455516001600160401b038516907f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b906200064d90869062000b90565b60405180910390a25050505050806001019050620003c4565b5050565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b0381118282101715620006a557620006a56200066a565b60405290565b604051601f8201601f191681016001600160401b0381118282101715620006d657620006d66200066a565b604052919050565b80516001600160401b0381168114620006f657600080fd5b919050565b6001600160a01b03811681146200071157600080fd5b50565b805163ffffffff81168114620006f657600080fd5b6000601f83601f8401126200073d57600080fd5b825160206001600160401b03808311156200075c576200075c6200066a565b8260051b6200076d838201620006ab565b93845286810183019383810190898611156200078857600080fd5b84890192505b85831015620008ba57825184811115620007a85760008081fd5b89016080601f19828d038101821315620007c25760008081fd5b620007cc62000680565b88840151620007db81620006fb565b81526040620007ec858201620006de565b8a8301526060808601518015158114620008065760008081fd5b838301529385015193898511156200081e5760008081fd5b84860195508f603f8701126200083657600094508485fd5b8a8601519450898511156200084f576200084f6200066a565b620008608b858f88011601620006ab565b93508484528f82868801011115620008785760008081fd5b60005b8581101562000898578681018301518582018d01528b016200087b565b5060009484018b0194909452509182015283525091840191908401906200078e565b9998505050505050505050565b6000806000838503610140811215620008df57600080fd5b6080811215620008ee57600080fd5b620008f862000680565b6200090386620006de565b815260208601516200091581620006fb565b602082015260408601516200092a81620006fb565b604082015260608601516200093f81620006fb565b6060820152935060a0607f19820112156200095957600080fd5b5060405160a081016001600160401b0380821183831017156200098057620009806200066a565b81604052608087015191506200099682620006fb565b818352620009a760a0880162000714565b6020840152620009ba60c0880162000714565b6040840152620009cd60e0880162000714565b60608401526101008701519150620009e582620006fb565b608083018290526101208701519294508083111562000a0357600080fd5b505062000a138682870162000729565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b600181811c9082168062000a4857607f821691505b60208210810362000a6957634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111562000abf576000816000526020600020601f850160051c8101602086101562000a9a5750805b601f850160051c820191505b8181101562000abb5782815560010162000aa6565b5050505b505050565b81516001600160401b0381111562000ae05762000ae06200066a565b62000af88162000af1845462000a33565b8462000a6f565b602080601f83116001811462000b30576000841562000b175750858301515b600019600386901b1c1916600185901b17855562000abb565b600085815260208120601f198616915b8281101562000b615788860151825594840194600190910190840162000b40565b508582101562000b805787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b602080825282546001600160a01b0381168383015260a081901c60ff161515604084015260a81c6001600160401b0316606083015260808083015260018084018054600093929190849062000be58162000a33565b8060a089015260c0600183166000811462000c09576001811462000c265762000c58565b60ff19841660c08b015260c083151560051b8b0101945062000c58565b85600052602060002060005b8481101562000c4f5781548c820185015290880190890162000c32565b8b0160c0019550505b50929998505050505050505050565b60805160a05160c05160e05161010051615f4962000cdd600039600081816102400152612a1a0152600081816102110152612f0e0152600081816101e20152818161077f01528181610986015261240c0152600081816101b201526126990152600081816117dd01526118290152615f496000f3fe608060405234801561001057600080fd5b50600436106101515760003560e01c806379ba5097116100cd578063c673e58411610081578063e9d68a8e11610066578063e9d68a8e1461052a578063f2fde38b1461054a578063f716f99f1461055d57600080fd5b8063c673e584146104c5578063ccd37ba3146104e557600080fd5b80638da5cb5b116100b25780638da5cb5b14610484578063991a50181461049f578063a80036b4146104b257600080fd5b806379ba50971461046e57806385572ffb1461047657600080fd5b80632d04ab76116101245780633f4b04aa116101095780633f4b04aa146103365780635e36480c146103525780637437ff9f1461037257600080fd5b80632d04ab7614610310578063311cd5131461032357600080fd5b806304666f9c1461015657806305d938b51461016b57806306285c691461017e578063181f5a77146102c7575b600080fd5b610169610164366004614086565b610570565b005b610169610179366004614710565b610584565b61027060408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316815250905090565b6040516102be9190815167ffffffffffffffff1681526020808301516001600160a01b0390811691830191909152604080840151821690830152606092830151169181019190915260800190565b60405180910390f35b6103036040518060400160405280601181526020017f4f666652616d7020312e362e302d64657600000000000000000000000000000081525081565b6040516102be919061488b565b61016961031e366004614936565b610729565b6101696103313660046149e9565b610cc1565b60095460405167ffffffffffffffff90911681526020016102be565b610365610360366004614a3d565b610d2a565b6040516102be9190614a9a565b6104116040805160a081018252600080825260208201819052918101829052606081018290526080810191909152506040805160a0810182526004546001600160a01b03808216835263ffffffff600160a01b83048116602085015278010000000000000000000000000000000000000000000000008304811694840194909452600160e01b9091049092166060820152600554909116608082015290565b6040516102be9190600060a0820190506001600160a01b03808451168352602084015163ffffffff808216602086015280604087015116604086015280606087015116606086015250508060808501511660808401525092915050565b610169610d80565b610169610151366004614aa8565b6000546040516001600160a01b0390911681526020016102be565b6101696104ad366004614af7565b610e3e565b6101696104c0366004614b6b565b610e4f565b6104d86104d3366004614bd8565b6111c2565b6040516102be9190614c38565b61051c6104f3366004614cad565b67ffffffffffffffff919091166000908152600860209081526040808320938352929052205490565b6040519081526020016102be565b61053d610538366004614cd7565b611320565b6040516102be9190614cf2565b610169610558366004614d40565b61142d565b61016961056b366004614dc5565b61143e565b610578611480565b610581816114dc565b50565b61058c6117da565b8151815181146105c8576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b818110156107195760008482815181106105e7576105e7614f03565b6020026020010151905060008160200151519050600085848151811061060f5761060f614f03565b6020026020010151905080518214610653576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8281101561070a57600082828151811061067257610672614f03565b6020026020010151905080600014610701578460200151828151811061069a5761069a614f03565b6020026020010151608001518110156107015784516040517fc8e9605100000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260248101839052604481018290526064015b60405180910390fd5b50600101610656565b505050508060010190506105cb565b50610724838361185b565b505050565b600061073787890189615135565b602081015151909150156107e357602081015160408083015190517f30dfc3080000000000000000000000000000000000000000000000000000000081526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016926330dfc308926107b292600401615399565b60006040518083038186803b1580156107ca57600080fd5b505afa1580156107de573d6000803e3d6000fd5b505050505b805151511515806107f957508051602001515115155b156108f95760095460208a01359067ffffffffffffffff808316911610156108b8576009805467ffffffffffffffff191667ffffffffffffffff83161790556004805483516040517f3937306f0000000000000000000000000000000000000000000000000000000081526001600160a01b0390921692633937306f9261088192910161547b565b600060405180830381600087803b15801561089b57600080fd5b505af11580156108af573d6000803e3d6000fd5b505050506108f7565b8160200151516000036108f7576040517f2261116700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b60005b816020015151811015610c0a5760008260200151828151811061092157610921614f03565b602090810291909101015180516040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815277ffffffffffffffff00000000000000000000000000000000608083901b166004820152919250906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632cbc26bb90602401602060405180830381865afa1580156109cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109f1919061548e565b15610a34576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff821660048201526024016106f8565b6000610a3f8261190b565b6020840151815491925067ffffffffffffffff908116600160a81b90920416141580610a865750826040015167ffffffffffffffff16836020015167ffffffffffffffff16115b15610ae7578251602084015160408086015190517fd5e0f0d600000000000000000000000000000000000000000000000000000000815267ffffffffffffffff938416600482015291831660248301529190911660448201526064016106f8565b606083015180610b23576040517f504570e300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b835167ffffffffffffffff16600090815260086020908152604080832084845290915290205415610b965783516040517f32cf0cbf00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602481018290526044016106f8565b6040840151610ba69060016154c1565b82547fffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffff16600160a81b67ffffffffffffffff9283160217909255925116600090815260086020908152604080832094835293905291909120429055506001016108fc565b507fd7868a16facbdde7b5c020620136316b3c266fffcb4e1e41cb6a662fe14ba3e181604051610c3a91906154e9565b60405180910390a1610cb660008a8a8a8a8a8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808e0282810182019093528d82529093508d92508c9182918501908490808284376000920191909152508b9250611972915050565b505050505050505050565b610d01610cd082840184615541565b6040805160008082526020820190925290610cfb565b6060815260200190600190039081610ce65790505b5061185b565b604080516000808252602082019092529050610d24600185858585866000611972565b50505050565b6000610d3860016004615576565b6002610d4560808561559f565b67ffffffffffffffff16610d5991906155c6565b610d638585611ce9565b901c166003811115610d7757610d77614a70565b90505b92915050565b6001546001600160a01b03163314610dda5760405162461bcd60e51b815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064016106f8565b600080543373ffffffffffffffffffffffffffffffffffffffff19808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610e46611480565b61058181611d30565b333014610e88576040517f371a732800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160008082526020820190925281610ec5565b6040805180820190915260008082526020820152815260200190600190039081610e9e5790505b5060a08501515190915015610ef957610ef68460a00151856020015186606001518760000151602001518787611e96565b90505b6040805160a0810182528551518152855160209081015167ffffffffffffffff1681830152808701518351600094840192610f3592910161488b565b60408051601f19818403018152918152908252878101516020830152018390526005549091506001600160a01b03168015611042576040517f08d450a10000000000000000000000000000000000000000000000000000000081526001600160a01b038216906308d450a190610faf90859060040161567f565b600060405180830381600087803b158015610fc957600080fd5b505af1925050508015610fda575060015b611042573d808015611008576040519150601f19603f3d011682016040523d82523d6000602084013e61100d565b606091505b50806040517f09c253250000000000000000000000000000000000000000000000000000000081526004016106f8919061488b565b60408601515115801561105757506080860151155b8061106e575060608601516001600160a01b03163b155b806110ae575060608601516110ac906001600160a01b03167f85572ffb00000000000000000000000000000000000000000000000000000000611fb5565b155b156110bb57505050505050565b855160209081015167ffffffffffffffff1660009081526006909152604080822054608089015160608a015192517f3cf9798300000000000000000000000000000000000000000000000000000000815284936001600160a01b0390931692633cf97983926111339289926113889291600401615692565b6000604051808303816000875af1158015611152573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261117a91908101906156ce565b5091509150816111b857806040517f0a8d6e8c0000000000000000000000000000000000000000000000000000000081526004016106f8919061488b565b5050505050505050565b6112056040805160e081019091526000606082018181526080830182905260a0830182905260c08301919091528190815260200160608152602001606081525090565b60ff808316600090815260026020818152604092839020835160e081018552815460608201908152600183015480881660808401526101008104881660a0840152620100009004909616151560c0820152948552918201805484518184028101840190955280855292938583019390928301828280156112ae57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611290575b505050505081526020016003820180548060200260200160405190810160405280929190818152602001828054801561131057602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116112f2575b5050505050815250509050919050565b604080516080808201835260008083526020808401829052838501829052606080850181905267ffffffffffffffff878116845260068352928690208651948501875280546001600160a01b0381168652600160a01b810460ff16151593860193909352600160a81b9092049092169483019490945260018401805493949293918401916113ad90615764565b80601f01602080910402602001604051908101604052809291908181526020018280546113d990615764565b80156113105780601f106113fb57610100808354040283529160200191611310565b820191906000526020600020905b81548152906001019060200180831161140957505050919092525091949350505050565b611435611480565b61058181611fd1565b611446611480565b60005b815181101561147c5761147482828151811061146757611467614f03565b6020026020010151612087565b600101611449565b5050565b6000546001600160a01b031633146114da5760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016106f8565b565b60005b815181101561147c5760008282815181106114fc576114fc614f03565b602002602001015190506000816020015190508067ffffffffffffffff16600003611553576040517fc656089500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81516001600160a01b031661157b576040516342bcdf7f60e11b815260040160405180910390fd5b67ffffffffffffffff811660009081526006602052604081206001810180549192916115a690615764565b80601f01602080910402602001604051908101604052809291908181526020018280546115d290615764565b801561161f5780601f106115f45761010080835404028352916020019161161f565b820191906000526020600020905b81548152906001019060200180831161160257829003601f168201915b5050505050905060008460600151905081516000036116d757805160000361165a576040516342bcdf7f60e11b815260040160405180910390fd5b6001830161166882826157ee565b5082547fffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffff16600160a81b17835560405167ffffffffffffffff851681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a161172a565b808051906020012082805190602001201461172a576040517fc39a620500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff851660048201526024016106f8565b604080860151845487516001600160a01b031673ffffffffffffffffffffffffffffffffffffffff19921515600160a01b02929092167fffffffffffffffffffffff000000000000000000000000000000000000000000909116171784555167ffffffffffffffff8516907f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b906117c29086906158ae565b60405180910390a250505050508060010190506114df565b467f0000000000000000000000000000000000000000000000000000000000000000146114da576040517f0f01ce850000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060048201524660248201526044016106f8565b8151600003611895576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160408051600080825260208201909252911591905b8451811015611904576118fc8582815181106118ca576118ca614f03565b6020026020010151846118f6578583815181106118e9576118e9614f03565b60200260200101516123b8565b836123b8565b6001016118ac565b5050505050565b67ffffffffffffffff811660009081526006602052604081208054600160a01b900460ff16610d7a576040517fed053c5900000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024016106f8565b60ff878116600090815260026020908152604080832081516080810183528154815260019091015480861693820193909352610100830485169181019190915262010000909104909216151560608301528735906119d18760a461597c565b9050826060015115611a195784516119ea9060206155c6565b86516119f79060206155c6565b611a029060a061597c565b611a0c919061597c565b611a16908261597c565b90505b368114611a5b576040517f8e1192e1000000000000000000000000000000000000000000000000000000008152600481018290523660248201526044016106f8565b5081518114611aa35781516040517f93df584c0000000000000000000000000000000000000000000000000000000081526004810191909152602481018290526044016106f8565b611aab6117da565b60ff808a1660009081526003602090815260408083203384528252808320815180830190925280548086168352939491939092840191610100909104166002811115611af957611af9614a70565b6002811115611b0a57611b0a614a70565b9052509050600281602001516002811115611b2757611b27614a70565b148015611b7b5750600260008b60ff1660ff168152602001908152602001600020600301816000015160ff1681548110611b6357611b63614f03565b6000918252602090912001546001600160a01b031633145b611bb1576040517fda0f08e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50816060015115611c93576020820151611bcc90600161598f565b60ff16855114611c08576040517f71253a2500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8351855114611c43576040517fa75d88af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008787604051611c559291906159a8565b604051908190038120611c6c918b906020016159b8565b604051602081830303815290604052805190602001209050611c918a82888888612cc8565b505b6040805182815260208a81013567ffffffffffffffff169082015260ff8b16917f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef0910160405180910390a2505050505050505050565b67ffffffffffffffff8216600090815260076020526040812081611d0e6080856159cc565b67ffffffffffffffff1681526020810191909152604001600020549392505050565b80516001600160a01b0316611d58576040516342bcdf7f60e11b815260040160405180910390fd5b80516004805460208085018051604080880180516060808b0180516001600160a01b039b8c167fffffffffffffffff000000000000000000000000000000000000000000000000909a168a17600160a01b63ffffffff988916021777ffffffffffffffffffffffffffffffffffffffffffffffff167801000000000000000000000000000000000000000000000000948816949094026001600160e01b031693909317600160e01b93871693909302929092179098556080808b0180516005805473ffffffffffffffffffffffffffffffffffffffff1916918d169190911790558451988952955185169688019690965290518316918601919091525116938301939093529151909216908201527fa55bd56595c45f517e5967a3067f3dca684445a3080e7c04a4e0d5a40cda627d9060a00160405180910390a150565b6060865167ffffffffffffffff811115611eb257611eb2613e9d565b604051908082528060200260200182016040528015611ef757816020015b6040805180820190915260008082526020820152815260200190600190039081611ed05790505b50905060005b8751811015611fa957611f84888281518110611f1b57611f1b614f03565b6020026020010151888888888887818110611f3857611f38614f03565b9050602002810190611f4a91906159f3565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612ead92505050565b828281518110611f9657611f96614f03565b6020908102919091010152600101611efd565b505b9695505050505050565b6000611fc083613252565b8015610d775750610d7783836132b6565b336001600160a01b038216036120295760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016106f8565b6001805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b806040015160ff166000036120b2576000604051631b3fab5160e11b81526004016106f89190615a3a565b60208082015160ff8082166000908152600290935260408320600181015492939092839216900361211f57606084015160018201805491151562010000027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff909216919091179055612174565b6060840151600182015460ff6201000090910416151590151514612174576040517f87f6037c00000000000000000000000000000000000000000000000000000000815260ff841660048201526024016106f8565b60a0840151805161010010156121a0576001604051631b3fab5160e11b81526004016106f89190615a3a565b61220684846003018054806020026020016040519081016040528092919081815260200182805480156121fc57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116121de575b5050505050613371565b84606001511561232d5761227484846002018054806020026020016040519081016040528092919081815260200182805480156121fc576020028201919060005260206000209081546001600160a01b031681526001909101906020018083116121de575050505050613371565b6080850151805161010010156122a0576002604051631b3fab5160e11b81526004016106f89190615a3a565b60408601516122b0906003615a54565b60ff168151116122d6576003604051631b3fab5160e11b81526004016106f89190615a3a565b80516001840180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1661010060ff84160217905561231e9060028601906020840190613e16565b5061232b858260016133da565b505b612339848260026133da565b805161234e9060038501906020840190613e16565b5060408581015160018401805460ff191660ff8316179055865180855560a088015192517fab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f547936123a79389939260028a01929190615a70565b60405180910390a16119048461354e565b815181516040517f2cbc26bb000000000000000000000000000000000000000000000000000000008152608083901b77ffffffffffffffff00000000000000000000000000000000166004820152901515907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632cbc26bb90602401602060405180830381865afa15801561245b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061247f919061548e565b1561250b5780156124c8576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff831660048201526024016106f8565b60405167ffffffffffffffff831681527faab522ed53d887e56ed53dd37398a01aeef6a58e0fa77c2173beb9512d8949339060200160405180910390a150505050565b60006125168361190b565b600101805461252490615764565b80601f016020809104026020016040519081016040528092919081815260200182805461255090615764565b801561259d5780601f106125725761010080835404028352916020019161259d565b820191906000526020600020905b81548152906001019060200180831161258057829003601f168201915b505050602088015151929350505060008190036125e5576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8560400151518114612623576040517f57e0e08300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008167ffffffffffffffff81111561263e5761263e613e9d565b604051908082528060200260200182016040528015612667578160200160208202803683370190505b50905060005b828110156127505760008860200151828151811061268d5761268d614f03565b602002602001015190507f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681600001516040015167ffffffffffffffff161461272057805160409081015190517f38432a2200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016106f8565b61272a818661356a565b83838151811061273c5761273c614f03565b60209081029190910101525060010161266d565b50600061276786838a606001518b6080015161368c565b9050806000036127af576040517f7dd17a7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff871660048201526024016106f8565b60005b83811015610cb65760005a905060008a6020015183815181106127d7576127d7614f03565b6020026020010151905060006127f58a836000015160600151610d2a565b9050600081600381111561280b5761280b614a70565b14806128285750600381600381111561282657612826614a70565b145b612880578151606001516040805167ffffffffffffffff808e16825290921660208301527f3b575419319662b2a6f5e2467d84521517a3382b908eb3d557bb3fdb0c50e23c91015b60405180910390a1505050612cc0565b881561295057600454600090600160a01b900463ffffffff166128a38742615576565b11905080806128c3575060038260038111156128c1576128c1614a70565b145b612905576040517fa9cfc86200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8c1660048201526024016106f8565b8b858151811061291757612917614f03565b602002602001015160001461294a578b858151811061293857612938614f03565b60200260200101518360800181815250505b506129b1565b600081600381111561296457612964614a70565b146129b1578151606001516040805167ffffffffffffffff808e16825290921660208301527f3ef2a99c550a751d4b0b261268f05a803dfb049ab43616a1ffb388f61fe651209101612870565b81516080015167ffffffffffffffff1615612aa05760008160038111156129da576129da614a70565b03612aa05781516080015160208301516040517fe0e03cae0000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169263e0e03cae92612a51928f929190600401615b1c565b6020604051808303816000875af1158015612a70573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a94919061548e565b612aa057505050612cc0565b60008c604001518581518110612ab857612ab8614f03565b6020026020010151905080518360a001515114612b1c578251606001516040517f1cfe6d8b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808e16600483015290911660248201526044016106f8565b612b308b84600001516060015160016136ca565b600080612b3d8584613772565b91509150612b548d866000015160600151846136ca565b8b15612bc4576003826003811115612b6e57612b6e614a70565b03612bc4576000846003811115612b8757612b87614a70565b14612bc4578451516040517f2b11b8d90000000000000000000000000000000000000000000000000000000081526106f891908390600401615b49565b6002826003811115612bd857612bd8614a70565b14612c32576003826003811115612bf157612bf1614a70565b14612c32578451606001516040517f926c5a3e0000000000000000000000000000000000000000000000000000000081526106f8918f918590600401615b62565b84600001516000015185600001516060015167ffffffffffffffff168e67ffffffffffffffff167f05665fe9ad095383d018353f4cbcba77e84db27dd215081bbf7cdf9ae6fbe48b8c8b81518110612c8c57612c8c614f03565b602002602001015186865a612ca1908e615576565b604051612cb19493929190615b88565b60405180910390a45050505050505b6001016127b2565b8251600090815b818110156111b8576000600188868460208110612cee57612cee614f03565b612cfb91901a601b61598f565b898581518110612d0d57612d0d614f03565b6020026020010151898681518110612d2757612d27614f03565b602002602001015160405160008152602001604052604051612d65949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015612d87573d6000803e3d6000fd5b505060408051601f1981015160ff808e166000908152600360209081528582206001600160a01b03851683528152858220858701909652855480841686529397509095509293928401916101009004166002811115612de857612de8614a70565b6002811115612df957612df9614a70565b9052509050600181602001516002811115612e1657612e16614a70565b14612e4d576040517fca31867a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051600160ff9091161b851615612e90576040517ff67bc7c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806000015160ff166001901b851794505050806001019050612ccf565b60408051808201909152600080825260208201526000612ed0876020015161383c565b6040517fbbe4f6db0000000000000000000000000000000000000000000000000000000081526001600160a01b0380831660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063bbe4f6db90602401602060405180830381865afa158015612f55573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f799190615bbf565b90506001600160a01b0381161580612fc15750612fbf6001600160a01b0382167faff2afbf00000000000000000000000000000000000000000000000000000000611fb5565b155b15613003576040517fae9b4ce90000000000000000000000000000000000000000000000000000000081526001600160a01b03821660048201526024016106f8565b60045460009081906130259089908690600160e01b900463ffffffff166138e2565b9150915060008060006130f26040518061010001604052808e81526020018c67ffffffffffffffff1681526020018d6001600160a01b031681526020018f606001518152602001896001600160a01b031681526020018f6000015181526020018f6040015181526020018b8152506040516024016130a39190615bdc565b60408051601f198184030181529190526020810180516001600160e01b03167f390775370000000000000000000000000000000000000000000000000000000017905287866113886084613a10565b9250925092508261313157816040517fe1cd55090000000000000000000000000000000000000000000000000000000081526004016106f8919061488b565b81516020146131795781516040517f78ef80240000000000000000000000000000000000000000000000000000000081526020600482015260248101919091526044016106f8565b60008280602001905181019061318f9190615ca9565b9050866001600160a01b03168c6001600160a01b0316146132245760006131c08d8a6131bb868a615576565b6138e2565b509050868110806131da5750816131d78883615576565b14155b15613222576040517fa966e21f0000000000000000000000000000000000000000000000000000000081526004810183905260248101889052604481018290526064016106f8565b505b604080518082019091526001600160a01b039098168852602088015250949550505050505095945050505050565b600061327e827f01ffc9a7000000000000000000000000000000000000000000000000000000006132b6565b8015610d7a57506132af827fffffffff000000000000000000000000000000000000000000000000000000006132b6565b1592915050565b6040517fffffffff0000000000000000000000000000000000000000000000000000000082166024820152600090819060440160408051601f19818403018152919052602080820180516001600160e01b03167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825192935060009283928392909183918a617530fa92503d9150600051905082801561335a575060208210155b80156133665750600081115b979650505050505050565b60005b81518110156107245760ff8316600090815260036020526040812083519091908490849081106133a6576133a6614f03565b6020908102919091018101516001600160a01b03168252810191909152604001600020805461ffff19169055600101613374565b60005b8251811015610d245760008382815181106133fa576133fa614f03565b602002602001015190506000600281111561341757613417614a70565b60ff80871660009081526003602090815260408083206001600160a01b0387168452909152902054610100900416600281111561345657613456614a70565b14613477576004604051631b3fab5160e11b81526004016106f89190615a3a565b6001600160a01b0381166134b7576040517fd6c62c9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052808360ff1681526020018460028111156134dd576134dd614a70565b905260ff80871660009081526003602090815260408083206001600160a01b0387168452825290912083518154931660ff198416811782559184015190929091839161ffff19161761010083600281111561353a5761353a614a70565b0217905550905050508060010190506133dd565b60ff8116610581576009805467ffffffffffffffff1916905550565b8151602080820151604092830151925160009384936135b0937f2425b0b9f9054c76ff151b0a175b18f37a4a4e82013a72e9f15c9caa095ed21f93909291889101615cc2565b60408051601f1981840301815290829052805160209182012086518051888401516060808b0151908401516080808d015195015195976135f99794969395929491939101615cf5565b604051602081830303815290604052805190602001208560400151805190602001208660a001516040516020016136309190615dfa565b60408051601f198184030181528282528051602091820120908301969096528101939093526060830191909152608082015260a081019190915260c0015b60405160208183030381529060405280519060200120905092915050565b60008061369a858585613b36565b67ffffffffffffffff8716600090815260086020908152604080832093835292905220549150505b949350505050565b600060026136d960808561559f565b67ffffffffffffffff166136ed91906155c6565b905060006136fb8585611ce9565b90508161370a60016004615576565b901b19168183600381111561372157613721614a70565b67ffffffffffffffff871660009081526007602052604081209190921b929092179182916137506080886159cc565b67ffffffffffffffff1681526020810191909152604001600020555050505050565b6040517fa80036b4000000000000000000000000000000000000000000000000000000008152600090606090309063a80036b4906137b69087908790600401615e5a565b600060405180830381600087803b1580156137d057600080fd5b505af19250505080156137e1575060015b613820573d80801561380f576040519150601f19603f3d011682016040523d82523d6000602084013e613814565b606091505b50600392509050613835565b50506040805160208101909152600081526002905b9250929050565b6000815160201461387b57816040517f8d666f600000000000000000000000000000000000000000000000000000000081526004016106f8919061488b565b6000828060200190518101906138919190615ca9565b90506001600160a01b038111806138a9575061040081105b15610d7a57826040517f8d666f600000000000000000000000000000000000000000000000000000000081526004016106f8919061488b565b600080600080600061395c8860405160240161390d91906001600160a01b0391909116815260200190565b60408051601f198184030181529190526020810180516001600160e01b03167f70a082310000000000000000000000000000000000000000000000000000000017905288886113886084613a10565b9250925092508261399b57816040517fe1cd55090000000000000000000000000000000000000000000000000000000081526004016106f8919061488b565b60208251146139e35781516040517f78ef80240000000000000000000000000000000000000000000000000000000081526020600482015260248101919091526044016106f8565b818060200190518101906139f79190615ca9565b613a018288615576565b94509450505050935093915050565b6000606060008361ffff1667ffffffffffffffff811115613a3357613a33613e9d565b6040519080825280601f01601f191660200182016040528015613a5d576020820181803683370190505b509150863b613a90577f0c3b563c0000000000000000000000000000000000000000000000000000000060005260046000fd5b5a85811015613ac3577fafa32a2c0000000000000000000000000000000000000000000000000000000060005260046000fd5b8590036040810481038710613afc577f37c3be290000000000000000000000000000000000000000000000000000000060005260046000fd5b505a6000808a5160208c0160008c8cf193505a900390503d84811115613b1f5750835b808352806000602085013e50955095509592505050565b8251825160009190818303613b77576040517f11a6b26400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6101018211801590613b8b57506101018111155b613ba8576040516309bde33960e01b815260040160405180910390fd5b60001982820101610100811115613bd2576040516309bde33960e01b815260040160405180910390fd5b80600003613bff5786600081518110613bed57613bed614f03565b60200260200101519350505050613dce565b60008167ffffffffffffffff811115613c1a57613c1a613e9d565b604051908082528060200260200182016040528015613c43578160200160208202803683370190505b50905060008080805b85811015613d6d5760006001821b8b811603613ca75788851015613c90578c5160018601958e918110613c8157613c81614f03565b60200260200101519050613cc9565b8551600185019487918110613c8157613c81614f03565b8b5160018401938d918110613cbe57613cbe614f03565b602002602001015190505b600089861015613cf9578d5160018701968f918110613cea57613cea614f03565b60200260200101519050613d1b565b8651600186019588918110613d1057613d10614f03565b602002602001015190505b82851115613d3c576040516309bde33960e01b815260040160405180910390fd5b613d468282613dd5565b878481518110613d5857613d58614f03565b60209081029190910101525050600101613c4c565b506001850382148015613d7f57508683145b8015613d8a57508581145b613da7576040516309bde33960e01b815260040160405180910390fd5b836001860381518110613dbc57613dbc614f03565b60200260200101519750505050505050505b9392505050565b6000818310613ded57613de88284613df3565b610d77565b610d7783835b60408051600160208201529081018390526060810182905260009060800161366e565b828054828255906000526020600020908101928215613e78579160200282015b82811115613e78578251825473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03909116178255602090920191600190910190613e36565b50613e84929150613e88565b5090565b5b80821115613e845760008155600101613e89565b634e487b7160e01b600052604160045260246000fd5b6040516080810167ffffffffffffffff81118282101715613ed657613ed6613e9d565b60405290565b60405160a0810167ffffffffffffffff81118282101715613ed657613ed6613e9d565b60405160c0810167ffffffffffffffff81118282101715613ed657613ed6613e9d565b6040805190810167ffffffffffffffff81118282101715613ed657613ed6613e9d565b6040516060810167ffffffffffffffff81118282101715613ed657613ed6613e9d565b604051601f8201601f1916810167ffffffffffffffff81118282101715613f9157613f91613e9d565b604052919050565b600067ffffffffffffffff821115613fb357613fb3613e9d565b5060051b60200190565b6001600160a01b038116811461058157600080fd5b803567ffffffffffffffff81168114613fea57600080fd5b919050565b801515811461058157600080fd5b8035613fea81613fef565b600067ffffffffffffffff82111561402257614022613e9d565b50601f01601f191660200190565b600082601f83011261404157600080fd5b813561405461404f82614008565b613f68565b81815284602083860101111561406957600080fd5b816020850160208301376000918101602001919091529392505050565b6000602080838503121561409957600080fd5b823567ffffffffffffffff808211156140b157600080fd5b818501915085601f8301126140c557600080fd5b81356140d361404f82613f99565b81815260059190911b830184019084810190888311156140f257600080fd5b8585015b838110156141985780358581111561410e5760008081fd5b86016080818c03601f19018113156141265760008081fd5b61412e613eb3565b8983013561413b81613fbd565b8152604061414a848201613fd2565b8b83015260608085013561415d81613fef565b8383015292840135928984111561417657600091508182fd5b6141848f8d86880101614030565b9083015250855250509186019186016140f6565b5098975050505050505050565b600060a082840312156141b757600080fd5b6141bf613edc565b9050813581526141d160208301613fd2565b60208201526141e260408301613fd2565b60408201526141f360608301613fd2565b606082015261420460808301613fd2565b608082015292915050565b8035613fea81613fbd565b600082601f83011261422b57600080fd5b8135602061423b61404f83613f99565b82815260059290921b8401810191818101908684111561425a57600080fd5b8286015b84811015611fa957803567ffffffffffffffff8082111561427f5760008081fd5b9088019060a0828b03601f19018113156142995760008081fd5b6142a1613edc565b87840135838111156142b35760008081fd5b6142c18d8a83880101614030565b825250604080850135848111156142d85760008081fd5b6142e68e8b83890101614030565b8a84015250606080860135858111156142ff5760008081fd5b61430d8f8c838a0101614030565b838501525060809150818601358184015250828501359250838311156143335760008081fd5b6143418d8a85880101614030565b90820152865250505091830191830161425e565b6000610140828403121561436857600080fd5b614370613eff565b905061437c83836141a5565b815260a082013567ffffffffffffffff8082111561439957600080fd5b6143a585838601614030565b602084015260c08401359150808211156143be57600080fd5b6143ca85838601614030565b60408401526143db60e0850161420f565b6060840152610100840135608084015261012084013591508082111561440057600080fd5b5061440d8482850161421a565b60a08301525092915050565b600082601f83011261442a57600080fd5b8135602061443a61404f83613f99565b82815260059290921b8401810191818101908684111561445957600080fd5b8286015b84811015611fa957803567ffffffffffffffff81111561447d5760008081fd5b61448b8986838b0101614355565b84525091830191830161445d565b600082601f8301126144aa57600080fd5b813560206144ba61404f83613f99565b82815260059290921b840181019181810190868411156144d957600080fd5b8286015b84811015611fa957803567ffffffffffffffff808211156144fd57600080fd5b818901915089603f83011261451157600080fd5b8582013561452161404f82613f99565b81815260059190911b830160400190878101908c83111561454157600080fd5b604085015b8381101561457a5780358581111561455d57600080fd5b61456c8f6040838a0101614030565b845250918901918901614546565b508752505050928401925083016144dd565b600082601f83011261459d57600080fd5b813560206145ad61404f83613f99565b8083825260208201915060208460051b8701019350868411156145cf57600080fd5b602086015b84811015611fa957803583529183019183016145d4565b600082601f8301126145fc57600080fd5b8135602061460c61404f83613f99565b82815260059290921b8401810191818101908684111561462b57600080fd5b8286015b84811015611fa957803567ffffffffffffffff808211156146505760008081fd5b9088019060a0828b03601f190181131561466a5760008081fd5b614672613edc565b61467d888501613fd2565b8152604080850135848111156146935760008081fd5b6146a18e8b83890101614419565b8a84015250606080860135858111156146ba5760008081fd5b6146c88f8c838a0101614499565b83850152506080915081860135858111156146e35760008081fd5b6146f18f8c838a010161458c565b918401919091525091909301359083015250835291830191830161462f565b600080604080848603121561472457600080fd5b833567ffffffffffffffff8082111561473c57600080fd5b614748878388016145eb565b945060209150818601358181111561475f57600080fd5b8601601f8101881361477057600080fd5b803561477e61404f82613f99565b81815260059190911b8201840190848101908a83111561479d57600080fd5b8584015b83811015614829578035868111156147b95760008081fd5b8501603f81018d136147cb5760008081fd5b878101356147db61404f82613f99565b81815260059190911b82018a0190898101908f8311156147fb5760008081fd5b928b01925b828410156148195783358252928a0192908a0190614800565b86525050509186019186016147a1565b50809750505050505050509250929050565b60005b8381101561485657818101518382015260200161483e565b50506000910152565b6000815180845261487781602086016020860161483b565b601f01601f19169290920160200192915050565b602081526000610d77602083018461485f565b8060608101831015610d7a57600080fd5b60008083601f8401126148c157600080fd5b50813567ffffffffffffffff8111156148d957600080fd5b60208301915083602082850101111561383557600080fd5b60008083601f84011261490357600080fd5b50813567ffffffffffffffff81111561491b57600080fd5b6020830191508360208260051b850101111561383557600080fd5b60008060008060008060008060e0898b03121561495257600080fd5b61495c8a8a61489e565b9750606089013567ffffffffffffffff8082111561497957600080fd5b6149858c838d016148af565b909950975060808b013591508082111561499e57600080fd5b6149aa8c838d016148f1565b909750955060a08b01359150808211156149c357600080fd5b506149d08b828c016148f1565b999c989b50969995989497949560c00135949350505050565b6000806000608084860312156149fe57600080fd5b614a08858561489e565b9250606084013567ffffffffffffffff811115614a2457600080fd5b614a30868287016148af565b9497909650939450505050565b60008060408385031215614a5057600080fd5b614a5983613fd2565b9150614a6760208401613fd2565b90509250929050565b634e487b7160e01b600052602160045260246000fd5b60048110614a9657614a96614a70565b9052565b60208101610d7a8284614a86565b600060208284031215614aba57600080fd5b813567ffffffffffffffff811115614ad157600080fd5b820160a08185031215613dce57600080fd5b803563ffffffff81168114613fea57600080fd5b600060a08284031215614b0957600080fd5b614b11613edc565b8235614b1c81613fbd565b8152614b2a60208401614ae3565b6020820152614b3b60408401614ae3565b6040820152614b4c60608401614ae3565b60608201526080830135614b5f81613fbd565b60808201529392505050565b600080600060408486031215614b8057600080fd5b833567ffffffffffffffff80821115614b9857600080fd5b614ba487838801614355565b94506020860135915080821115614bba57600080fd5b50614a30868287016148f1565b803560ff81168114613fea57600080fd5b600060208284031215614bea57600080fd5b610d7782614bc7565b60008151808452602080850194506020840160005b83811015614c2d5781516001600160a01b031687529582019590820190600101614c08565b509495945050505050565b60208152600082518051602084015260ff602082015116604084015260ff604082015116606084015260608101511515608084015250602083015160c060a0840152614c8760e0840182614bf3565b90506040840151601f198483030160c0850152614ca48282614bf3565b95945050505050565b60008060408385031215614cc057600080fd5b614cc983613fd2565b946020939093013593505050565b600060208284031215614ce957600080fd5b610d7782613fd2565b602081526001600160a01b03825116602082015260208201511515604082015267ffffffffffffffff6040830151166060820152600060608301516080808401526136c260a084018261485f565b600060208284031215614d5257600080fd5b8135613dce81613fbd565b600082601f830112614d6e57600080fd5b81356020614d7e61404f83613f99565b8083825260208201915060208460051b870101935086841115614da057600080fd5b602086015b84811015611fa9578035614db881613fbd565b8352918301918301614da5565b60006020808385031215614dd857600080fd5b823567ffffffffffffffff80821115614df057600080fd5b818501915085601f830112614e0457600080fd5b8135614e1261404f82613f99565b81815260059190911b83018401908481019088831115614e3157600080fd5b8585015b8381101561419857803585811115614e4c57600080fd5b860160c0818c03601f19011215614e635760008081fd5b614e6b613eff565b8882013581526040614e7e818401614bc7565b8a8301526060614e8f818501614bc7565b8284015260809150614ea2828501613ffd565b9083015260a08381013589811115614eba5760008081fd5b614ec88f8d83880101614d5d565b838501525060c0840135915088821115614ee25760008081fd5b614ef08e8c84870101614d5d565b9083015250845250918601918601614e35565b634e487b7160e01b600052603260045260246000fd5b80356001600160e01b0381168114613fea57600080fd5b600082601f830112614f4157600080fd5b81356020614f5161404f83613f99565b82815260069290921b84018101918181019086841115614f7057600080fd5b8286015b84811015611fa95760408189031215614f8d5760008081fd5b614f95613f22565b614f9e82613fd2565b8152614fab858301614f19565b81860152835291830191604001614f74565b600082601f830112614fce57600080fd5b81356020614fde61404f83613f99565b82815260059290921b84018101918181019086841115614ffd57600080fd5b8286015b84811015611fa957803567ffffffffffffffff808211156150225760008081fd5b9088019060a0828b03601f190181131561503c5760008081fd5b615044613edc565b61504f888501613fd2565b8152604061505e818601613fd2565b89830152606061506f818701613fd2565b8284015260809150818601358184015250828501359250838311156150945760008081fd5b6150a28d8a85880101614030565b908201528652505050918301918301615001565b600082601f8301126150c757600080fd5b813560206150d761404f83613f99565b82815260069290921b840181019181810190868411156150f657600080fd5b8286015b84811015611fa957604081890312156151135760008081fd5b61511b613f22565b8135815284820135858201528352918301916040016150fa565b6000602080838503121561514857600080fd5b823567ffffffffffffffff8082111561516057600080fd5b908401906060828703121561517457600080fd5b61517c613f45565b82358281111561518b57600080fd5b8301604081890381131561519e57600080fd5b6151a6613f22565b8235858111156151b557600080fd5b8301601f81018b136151c657600080fd5b80356151d461404f82613f99565b81815260069190911b8201890190898101908d8311156151f357600080fd5b928a01925b828410156152435785848f0312156152105760008081fd5b615218613f22565b843561522381613fbd565b8152615230858d01614f19565b818d0152825292850192908a01906151f8565b84525050508287013591508482111561525b57600080fd5b6152678a838501614f30565b8188015283525050828401358281111561528057600080fd5b61528c88828601614fbd565b858301525060408301359350818411156152a557600080fd5b6152b1878585016150b6565b60408201529695505050505050565b600082825180855260208086019550808260051b84010181860160005b8481101561535057858303601f190189528151805167ffffffffffffffff908116855285820151811686860152604080830151909116908501526060808201519085015260809081015160a09185018290529061533c8186018361485f565b9a86019a94505050908301906001016152dd565b5090979650505050505050565b60008151808452602080850194506020840160005b83811015614c2d578151805188528301518388015260409096019590820190600101615372565b6040815260006153ac60408301856152c0565b8281036020840152614ca4818561535d565b805160408084528151848201819052600092602091908201906060870190855b8181101561541557835180516001600160a01b031684528501516001600160e01b03168584015292840192918501916001016153de565b50508583015187820388850152805180835290840192506000918401905b8083101561546f578351805167ffffffffffffffff1683528501516001600160e01b031685830152928401926001929092019190850190615433565b50979650505050505050565b602081526000610d7760208301846153be565b6000602082840312156154a057600080fd5b8151613dce81613fef565b634e487b7160e01b600052601160045260246000fd5b67ffffffffffffffff8181168382160190808211156154e2576154e26154ab565b5092915050565b60208152600082516060602084015261550560808401826153be565b90506020840151601f198085840301604086015261552383836152c0565b9250604086015191508085840301606086015250614ca4828261535d565b60006020828403121561555357600080fd5b813567ffffffffffffffff81111561556a57600080fd5b6136c2848285016145eb565b81810381811115610d7a57610d7a6154ab565b634e487b7160e01b600052601260045260246000fd5b600067ffffffffffffffff808416806155ba576155ba615589565b92169190910692915050565b8082028115828204841417610d7a57610d7a6154ab565b805182526000602067ffffffffffffffff81840151168185015260408084015160a0604087015261561160a087018261485f565b90506060850151868203606088015261562a828261485f565b608087810151898303918a01919091528051808352908601935060009250908501905b8083101561546f57835180516001600160a01b031683528601518683015292850192600192909201919084019061564d565b602081526000610d7760208301846155dd565b6080815260006156a560808301876155dd565b61ffff9590951660208301525060408101929092526001600160a01b0316606090910152919050565b6000806000606084860312156156e357600080fd5b83516156ee81613fef565b602085015190935067ffffffffffffffff81111561570b57600080fd5b8401601f8101861361571c57600080fd5b805161572a61404f82614008565b81815287602083850101111561573f57600080fd5b61575082602083016020860161483b565b809450505050604084015190509250925092565b600181811c9082168061577857607f821691505b60208210810361579857634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115610724576000816000526020600020601f850160051c810160208610156157c75750805b601f850160051c820191505b818110156157e6578281556001016157d3565b505050505050565b815167ffffffffffffffff81111561580857615808613e9d565b61581c816158168454615764565b8461579e565b602080601f83116001811461585157600084156158395750858301515b600019600386901b1c1916600185901b1785556157e6565b600085815260208120601f198616915b8281101561588057888601518255948401946001909101908401615861565b508582101561589e5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6000602080835283546001600160a01b038116602085015260ff8160a01c161515604085015267ffffffffffffffff8160a81c1660608501525060018085016080808601526000815461590081615764565b8060a089015260c06001831660008114615921576001811461593d5761596d565b60ff19841660c08b015260c083151560051b8b0101945061596d565b85600052602060002060005b848110156159645781548c8201850152908801908901615949565b8b0160c0019550505b50929998505050505050505050565b80820180821115610d7a57610d7a6154ab565b60ff8181168382160190811115610d7a57610d7a6154ab565b8183823760009101908152919050565b828152606082602083013760800192915050565b600067ffffffffffffffff808416806159e7576159e7615589565b92169190910492915050565b6000808335601e19843603018112615a0a57600080fd5b83018035915067ffffffffffffffff821115615a2557600080fd5b60200191503681900382131561383557600080fd5b6020810160058310615a4e57615a4e614a70565b91905290565b60ff81811683821602908116908181146154e2576154e26154ab565b600060a0820160ff881683526020878185015260a0604085015281875480845260c0860191508860005282600020935060005b81811015615ac85784546001600160a01b031683526001948501949284019201615aa3565b50508481036060860152865180825290820192508187019060005b81811015615b085782516001600160a01b031685529383019391830191600101615ae3565b50505060ff85166080850152509050611fab565b600067ffffffffffffffff808616835280851660208401525060606040830152614ca4606083018461485f565b8281526040602082015260006136c2604083018461485f565b67ffffffffffffffff848116825283166020820152606081016136c26040830184614a86565b848152615b986020820185614a86565b608060408201526000615bae608083018561485f565b905082606083015295945050505050565b600060208284031215615bd157600080fd5b8151613dce81613fbd565b6020815260008251610100806020850152615bfb61012085018361485f565b91506020850151615c18604086018267ffffffffffffffff169052565b5060408501516001600160a01b038116606086015250606085015160808501526080850151615c5260a08601826001600160a01b03169052565b5060a0850151601f19808685030160c0870152615c6f848361485f565b935060c08701519150808685030160e0870152615c8c848361485f565b935060e0870151915080868503018387015250611fab838261485f565b600060208284031215615cbb57600080fd5b5051919050565b848152600067ffffffffffffffff808616602084015280851660408401525060806060830152611fab608083018461485f565b86815260c060208201526000615d0e60c083018861485f565b6001600160a01b039690961660408301525067ffffffffffffffff9384166060820152608081019290925290911660a09091015292915050565b600082825180855260208086019550808260051b84010181860160005b8481101561535057601f19868403018952815160a08151818652615d8b8287018261485f565b9150508582015185820387870152615da3828261485f565b91505060408083015186830382880152615dbd838261485f565b92505050606080830151818701525060808083015192508582038187015250615de6818361485f565b9a86019a9450505090830190600101615d65565b602081526000610d776020830184615d48565b60008282518085526020808601955060208260051b8401016020860160005b8481101561535057601f19868403018952615e4883835161485f565b98840198925090830190600101615e2c565b604081526000835180516040840152602081015167ffffffffffffffff80821660608601528060408401511660808601528060608401511660a08601528060808401511660c086015250505060208401516101408060e0850152615ec261018085018361485f565b91506040860151603f198086850301610100870152615ee1848361485f565b935060608801519150615f006101208701836001600160a01b03169052565b60808801518387015260a0880151925080868503016101608701525050615f278282615d48565b9150508281036020840152614ca48185615e0d56fea164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CanOnlySelfCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"actual\",\"type\":\"bytes32\"}],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ExecutionError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"ForkedChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enumMultiOCR3Base.InvalidConfigErrorType\",\"name\":\"errorType\",\"type\":\"uint8\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"got\",\"type\":\"uint256\"}],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidEVMAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"name\":\"InvalidInterval\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"newLimit\",\"type\":\"uint256\"}],\"name\":\"InvalidManualExecutionGasLimit\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"messageDestChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidMessageDestChainSelector\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"newState\",\"type\":\"uint8\"}],\"name\":\"InvalidNewState\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRoot\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidStaticConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LeavesCannotBeEmpty\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ManualExecutionGasLimitMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"ManualExecutionNotYetEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"errorReason\",\"type\":\"bytes\"}],\"name\":\"MessageValidationError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonUniqueSignatures\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"notPool\",\"type\":\"address\"}],\"name\":\"NotACompatiblePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OracleCannotBeZeroAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ReceiverError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountReleased\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePre\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePost\",\"type\":\"uint256\"}],\"name\":\"ReleaseOrMintBalanceMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"name\":\"RootAlreadyCommitted\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"RootNotCommitted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignaturesOutOfRegistration\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"reportSourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"messageSourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainSelectorMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"StaleCommitReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"StaticConfigCannotBeChanged\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"TokenDataMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"TokenHandlingError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnexpectedTokenData\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"WrongMessageLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WrongNumberOfSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroChainSelectorNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"AlreadyAttempted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"structIRMNV2.Signature[]\",\"name\":\"rmnSignatures\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"report\",\"type\":\"tuple\"}],\"name\":\"CommitReportAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"DynamicConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"messageHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"name\":\"ExecutionStateChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"RootRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"SkippedAlreadyExecutedMessage\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SkippedReportExecution\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"sourceConfig\",\"type\":\"tuple\"}],\"name\":\"SourceChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainSelectorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"}],\"name\":\"StaticConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigUpdates\",\"type\":\"tuple[]\"}],\"name\":\"applySourceChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"destTokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structClient.Any2EVMMessage\",\"name\":\"\",\"type\":\"tuple\"}],\"name\":\"ccipReceive\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"rawVs\",\"type\":\"bytes32\"}],\"name\":\"commit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"execute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"bytes[]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[]\"}],\"name\":\"executeSingleMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"getExecutionState\",\"outputs\":[{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLatestPriceSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"getMerkleRoot\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"getSourceChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"latestConfigDetails\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"n\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"}],\"internalType\":\"structMultiOCR3Base.ConfigInfo\",\"name\":\"configInfo\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfig\",\"name\":\"ocrConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage[]\",\"name\":\"messages\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[][]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[][]\"},{\"internalType\":\"bytes32[]\",\"name\":\"proofs\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"proofFlagBits\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.ExecutionReportSingleChain[]\",\"name\":\"reports\",\"type\":\"tuple[]\"},{\"internalType\":\"uint256[][]\",\"name\":\"gasLimitOverrides\",\"type\":\"uint256[][]\"}],\"name\":\"manuallyExecute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"setDynamicConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfigArgs[]\",\"name\":\"ocrConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"setOCR3Configs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x6101206040523480156200001257600080fd5b5060405162006c9638038062006c968339810160408190526200003591620008c7565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf81620001fa565b5050466080525060208301516001600160a01b03161580620000ec575060408301516001600160a01b0316155b8062000103575060608301516001600160a01b0316155b1562000122576040516342bcdf7f60e11b815260040160405180910390fd5b82516001600160401b03166000036200014e5760405163c656089560e01b815260040160405180910390fd5b82516001600160401b0390811660a052602080850180516001600160a01b0390811660c05260408088018051831660e0526060808a01805185166101005283518b519098168852945184169587019590955251821690850152905116908201527f683eb52ee924eb817377cfa8f41f238f4bb7a877da5267869dfffbad85f564d89060800160405180910390a1620001e682620002a5565b620001f181620003c1565b50505062000c67565b336001600160a01b03821603620002545760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b0316620002ce576040516342bcdf7f60e11b815260040160405180910390fd5b80516004805460208085018051604080880180516060808b0180516001600160a01b039b8c166001600160c01b0319909a168a17600160a01b63ffffffff98891602176001600160c01b0316600160c01b948816949094026001600160e01b031693909317600160e01b93871693909302929092179098556080808b018051600580546001600160a01b031916918d169190911790558451988952955185169688019690965290518316918601919091525116938301939093529151909216908201527fa55bd56595c45f517e5967a3067f3dca684445a3080e7c04a4e0d5a40cda627d9060a00160405180910390a150565b60005b815181101562000666576000828281518110620003e557620003e562000a1d565b60200260200101519050600081602001519050806001600160401b0316600003620004235760405163c656089560e01b815260040160405180910390fd5b81516001600160a01b03166200044c576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160401b0381166000908152600660205260408120600181018054919291620004789062000a33565b80601f0160208091040260200160405190810160405280929190818152602001828054620004a69062000a33565b8015620004f75780601f10620004cb57610100808354040283529160200191620004f7565b820191906000526020600020905b815481529060010190602001808311620004d957829003601f168201915b5050505050905060008460600151905081516000036200059e57805160000362000534576040516342bcdf7f60e11b815260040160405180910390fd5b6001830162000544828262000ac4565b508254600160a81b600160e81b031916600160a81b1783556040516001600160401b03851681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1620005d9565b8080519060200120828051906020012014620005d95760405163c39a620560e01b81526001600160401b038516600482015260240162000083565b604080860151845487516001600160a01b03166001600160a01b0319921515600160a01b02929092166001600160a81b031990911617178455516001600160401b038516907f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b906200064d90869062000b90565b60405180910390a25050505050806001019050620003c4565b5050565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b0381118282101715620006a557620006a56200066a565b60405290565b604051601f8201601f191681016001600160401b0381118282101715620006d657620006d66200066a565b604052919050565b80516001600160401b0381168114620006f657600080fd5b919050565b6001600160a01b03811681146200071157600080fd5b50565b805163ffffffff81168114620006f657600080fd5b6000601f83601f8401126200073d57600080fd5b825160206001600160401b03808311156200075c576200075c6200066a565b8260051b6200076d838201620006ab565b93845286810183019383810190898611156200078857600080fd5b84890192505b85831015620008ba57825184811115620007a85760008081fd5b89016080601f19828d038101821315620007c25760008081fd5b620007cc62000680565b88840151620007db81620006fb565b81526040620007ec858201620006de565b8a8301526060808601518015158114620008065760008081fd5b838301529385015193898511156200081e5760008081fd5b84860195508f603f8701126200083657600094508485fd5b8a8601519450898511156200084f576200084f6200066a565b620008608b858f88011601620006ab565b93508484528f82868801011115620008785760008081fd5b60005b8581101562000898578681018301518582018d01528b016200087b565b5060009484018b0194909452509182015283525091840191908401906200078e565b9998505050505050505050565b6000806000838503610140811215620008df57600080fd5b6080811215620008ee57600080fd5b620008f862000680565b6200090386620006de565b815260208601516200091581620006fb565b602082015260408601516200092a81620006fb565b604082015260608601516200093f81620006fb565b6060820152935060a0607f19820112156200095957600080fd5b5060405160a081016001600160401b0380821183831017156200098057620009806200066a565b81604052608087015191506200099682620006fb565b818352620009a760a0880162000714565b6020840152620009ba60c0880162000714565b6040840152620009cd60e0880162000714565b60608401526101008701519150620009e582620006fb565b608083018290526101208701519294508083111562000a0357600080fd5b505062000a138682870162000729565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b600181811c9082168062000a4857607f821691505b60208210810362000a6957634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111562000abf576000816000526020600020601f850160051c8101602086101562000a9a5750805b601f850160051c820191505b8181101562000abb5782815560010162000aa6565b5050505b505050565b81516001600160401b0381111562000ae05762000ae06200066a565b62000af88162000af1845462000a33565b8462000a6f565b602080601f83116001811462000b30576000841562000b175750858301515b600019600386901b1c1916600185901b17855562000abb565b600085815260208120601f198616915b8281101562000b615788860151825594840194600190910190840162000b40565b508582101562000b805787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b602080825282546001600160a01b0381168383015260a081901c60ff161515604084015260a81c6001600160401b0316606083015260808083015260018084018054600093929190849062000be58162000a33565b8060a089015260c0600183166000811462000c09576001811462000c265762000c58565b60ff19841660c08b015260c083151560051b8b0101945062000c58565b85600052602060002060005b8481101562000c4f5781548c820185015290880190890162000c32565b8b0160c0019550505b50929998505050505050505050565b60805160a05160c05160e05161010051615fb962000cdd600039600081816102400152612a8a0152600081816102110152612f7e0152600081816101e20152818161077f01528181610986015261240c0152600081816101b201526126990152600081816117dd01526118290152615fb96000f3fe608060405234801561001057600080fd5b50600436106101515760003560e01c806379ba5097116100cd578063c673e58411610081578063e9d68a8e11610066578063e9d68a8e1461052a578063f2fde38b1461054a578063f716f99f1461055d57600080fd5b8063c673e584146104c5578063ccd37ba3146104e557600080fd5b80638da5cb5b116100b25780638da5cb5b14610484578063991a50181461049f578063a80036b4146104b257600080fd5b806379ba50971461046e57806385572ffb1461047657600080fd5b80632d04ab76116101245780633f4b04aa116101095780633f4b04aa146103365780635e36480c146103525780637437ff9f1461037257600080fd5b80632d04ab7614610310578063311cd5131461032357600080fd5b806304666f9c1461015657806305d938b51461016b57806306285c691461017e578063181f5a77146102c7575b600080fd5b6101696101643660046140f6565b610570565b005b610169610179366004614780565b610584565b61027060408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316815250905090565b6040516102be9190815167ffffffffffffffff1681526020808301516001600160a01b0390811691830191909152604080840151821690830152606092830151169181019190915260800190565b60405180910390f35b6103036040518060400160405280601181526020017f4f666652616d7020312e362e302d64657600000000000000000000000000000081525081565b6040516102be91906148fb565b61016961031e3660046149a6565b610729565b610169610331366004614a59565b610cc1565b60095460405167ffffffffffffffff90911681526020016102be565b610365610360366004614aad565b610d2a565b6040516102be9190614b0a565b6104116040805160a081018252600080825260208201819052918101829052606081018290526080810191909152506040805160a0810182526004546001600160a01b03808216835263ffffffff600160a01b83048116602085015278010000000000000000000000000000000000000000000000008304811694840194909452600160e01b9091049092166060820152600554909116608082015290565b6040516102be9190600060a0820190506001600160a01b03808451168352602084015163ffffffff808216602086015280604087015116604086015280606087015116606086015250508060808501511660808401525092915050565b610169610d80565b610169610151366004614b18565b6000546040516001600160a01b0390911681526020016102be565b6101696104ad366004614b67565b610e3e565b6101696104c0366004614bdb565b610e4f565b6104d86104d3366004614c48565b6111c2565b6040516102be9190614ca8565b61051c6104f3366004614d1d565b67ffffffffffffffff919091166000908152600860209081526040808320938352929052205490565b6040519081526020016102be565b61053d610538366004614d47565b611320565b6040516102be9190614d62565b610169610558366004614db0565b61142d565b61016961056b366004614e35565b61143e565b610578611480565b610581816114dc565b50565b61058c6117da565b8151815181146105c8576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b818110156107195760008482815181106105e7576105e7614f73565b6020026020010151905060008160200151519050600085848151811061060f5761060f614f73565b6020026020010151905080518214610653576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8281101561070a57600082828151811061067257610672614f73565b6020026020010151905080600014610701578460200151828151811061069a5761069a614f73565b6020026020010151608001518110156107015784516040517fc8e9605100000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260248101839052604481018290526064015b60405180910390fd5b50600101610656565b505050508060010190506105cb565b50610724838361185b565b505050565b6000610737878901896151a5565b602081015151909150156107e357602081015160408083015190517f30dfc3080000000000000000000000000000000000000000000000000000000081526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016926330dfc308926107b292600401615409565b60006040518083038186803b1580156107ca57600080fd5b505afa1580156107de573d6000803e3d6000fd5b505050505b805151511515806107f957508051602001515115155b156108f95760095460208a01359067ffffffffffffffff808316911610156108b8576009805467ffffffffffffffff191667ffffffffffffffff83161790556004805483516040517f3937306f0000000000000000000000000000000000000000000000000000000081526001600160a01b0390921692633937306f926108819291016154eb565b600060405180830381600087803b15801561089b57600080fd5b505af11580156108af573d6000803e3d6000fd5b505050506108f7565b8160200151516000036108f7576040517f2261116700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b60005b816020015151811015610c0a5760008260200151828151811061092157610921614f73565b602090810291909101015180516040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815277ffffffffffffffff00000000000000000000000000000000608083901b166004820152919250906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632cbc26bb90602401602060405180830381865afa1580156109cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109f191906154fe565b15610a34576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff821660048201526024016106f8565b6000610a3f8261190b565b6020840151815491925067ffffffffffffffff908116600160a81b90920416141580610a865750826040015167ffffffffffffffff16836020015167ffffffffffffffff16115b15610ae7578251602084015160408086015190517fd5e0f0d600000000000000000000000000000000000000000000000000000000815267ffffffffffffffff938416600482015291831660248301529190911660448201526064016106f8565b606083015180610b23576040517f504570e300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b835167ffffffffffffffff16600090815260086020908152604080832084845290915290205415610b965783516040517f32cf0cbf00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602481018290526044016106f8565b6040840151610ba6906001615531565b82547fffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffff16600160a81b67ffffffffffffffff9283160217909255925116600090815260086020908152604080832094835293905291909120429055506001016108fc565b507fd7868a16facbdde7b5c020620136316b3c266fffcb4e1e41cb6a662fe14ba3e181604051610c3a9190615559565b60405180910390a1610cb660008a8a8a8a8a8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808e0282810182019093528d82529093508d92508c9182918501908490808284376000920191909152508b9250611972915050565b505050505050505050565b610d01610cd0828401846155b1565b6040805160008082526020820190925290610cfb565b6060815260200190600190039081610ce65790505b5061185b565b604080516000808252602082019092529050610d24600185858585866000611972565b50505050565b6000610d38600160046155e6565b6002610d4560808561560f565b67ffffffffffffffff16610d599190615636565b610d638585611ce9565b901c166003811115610d7757610d77614ae0565b90505b92915050565b6001546001600160a01b03163314610dda5760405162461bcd60e51b815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064016106f8565b600080543373ffffffffffffffffffffffffffffffffffffffff19808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610e46611480565b61058181611d30565b333014610e88576040517f371a732800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160008082526020820190925281610ec5565b6040805180820190915260008082526020820152815260200190600190039081610e9e5790505b5060a08501515190915015610ef957610ef68460a00151856020015186606001518760000151602001518787611e96565b90505b6040805160a0810182528551518152855160209081015167ffffffffffffffff1681830152808701518351600094840192610f359291016148fb565b60408051601f19818403018152918152908252878101516020830152018390526005549091506001600160a01b03168015611042576040517f08d450a10000000000000000000000000000000000000000000000000000000081526001600160a01b038216906308d450a190610faf9085906004016156ef565b600060405180830381600087803b158015610fc957600080fd5b505af1925050508015610fda575060015b611042573d808015611008576040519150601f19603f3d011682016040523d82523d6000602084013e61100d565b606091505b50806040517f09c253250000000000000000000000000000000000000000000000000000000081526004016106f891906148fb565b60408601515115801561105757506080860151155b8061106e575060608601516001600160a01b03163b155b806110ae575060608601516110ac906001600160a01b03167f85572ffb00000000000000000000000000000000000000000000000000000000611fb5565b155b156110bb57505050505050565b855160209081015167ffffffffffffffff1660009081526006909152604080822054608089015160608a015192517f3cf9798300000000000000000000000000000000000000000000000000000000815284936001600160a01b0390931692633cf97983926111339289926113889291600401615702565b6000604051808303816000875af1158015611152573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261117a919081019061573e565b5091509150816111b857806040517f0a8d6e8c0000000000000000000000000000000000000000000000000000000081526004016106f891906148fb565b5050505050505050565b6112056040805160e081019091526000606082018181526080830182905260a0830182905260c08301919091528190815260200160608152602001606081525090565b60ff808316600090815260026020818152604092839020835160e081018552815460608201908152600183015480881660808401526101008104881660a0840152620100009004909616151560c0820152948552918201805484518184028101840190955280855292938583019390928301828280156112ae57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611290575b505050505081526020016003820180548060200260200160405190810160405280929190818152602001828054801561131057602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116112f2575b5050505050815250509050919050565b604080516080808201835260008083526020808401829052838501829052606080850181905267ffffffffffffffff878116845260068352928690208651948501875280546001600160a01b0381168652600160a01b810460ff16151593860193909352600160a81b9092049092169483019490945260018401805493949293918401916113ad906157d4565b80601f01602080910402602001604051908101604052809291908181526020018280546113d9906157d4565b80156113105780601f106113fb57610100808354040283529160200191611310565b820191906000526020600020905b81548152906001019060200180831161140957505050919092525091949350505050565b611435611480565b61058181611fd1565b611446611480565b60005b815181101561147c5761147482828151811061146757611467614f73565b6020026020010151612087565b600101611449565b5050565b6000546001600160a01b031633146114da5760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016106f8565b565b60005b815181101561147c5760008282815181106114fc576114fc614f73565b602002602001015190506000816020015190508067ffffffffffffffff16600003611553576040517fc656089500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81516001600160a01b031661157b576040516342bcdf7f60e11b815260040160405180910390fd5b67ffffffffffffffff811660009081526006602052604081206001810180549192916115a6906157d4565b80601f01602080910402602001604051908101604052809291908181526020018280546115d2906157d4565b801561161f5780601f106115f45761010080835404028352916020019161161f565b820191906000526020600020905b81548152906001019060200180831161160257829003601f168201915b5050505050905060008460600151905081516000036116d757805160000361165a576040516342bcdf7f60e11b815260040160405180910390fd5b60018301611668828261585e565b5082547fffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffff16600160a81b17835560405167ffffffffffffffff851681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a161172a565b808051906020012082805190602001201461172a576040517fc39a620500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff851660048201526024016106f8565b604080860151845487516001600160a01b031673ffffffffffffffffffffffffffffffffffffffff19921515600160a01b02929092167fffffffffffffffffffffff000000000000000000000000000000000000000000909116171784555167ffffffffffffffff8516907f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b906117c290869061591e565b60405180910390a250505050508060010190506114df565b467f0000000000000000000000000000000000000000000000000000000000000000146114da576040517f0f01ce850000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060048201524660248201526044016106f8565b8151600003611895576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160408051600080825260208201909252911591905b8451811015611904576118fc8582815181106118ca576118ca614f73565b6020026020010151846118f6578583815181106118e9576118e9614f73565b60200260200101516123b8565b836123b8565b6001016118ac565b5050505050565b67ffffffffffffffff811660009081526006602052604081208054600160a01b900460ff16610d7a576040517fed053c5900000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024016106f8565b60ff878116600090815260026020908152604080832081516080810183528154815260019091015480861693820193909352610100830485169181019190915262010000909104909216151560608301528735906119d18760a46159ec565b9050826060015115611a195784516119ea906020615636565b86516119f7906020615636565b611a029060a06159ec565b611a0c91906159ec565b611a1690826159ec565b90505b368114611a5b576040517f8e1192e1000000000000000000000000000000000000000000000000000000008152600481018290523660248201526044016106f8565b5081518114611aa35781516040517f93df584c0000000000000000000000000000000000000000000000000000000081526004810191909152602481018290526044016106f8565b611aab6117da565b60ff808a1660009081526003602090815260408083203384528252808320815180830190925280548086168352939491939092840191610100909104166002811115611af957611af9614ae0565b6002811115611b0a57611b0a614ae0565b9052509050600281602001516002811115611b2757611b27614ae0565b148015611b7b5750600260008b60ff1660ff168152602001908152602001600020600301816000015160ff1681548110611b6357611b63614f73565b6000918252602090912001546001600160a01b031633145b611bb1576040517fda0f08e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50816060015115611c93576020820151611bcc9060016159ff565b60ff16855114611c08576040517f71253a2500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8351855114611c43576040517fa75d88af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008787604051611c55929190615a18565b604051908190038120611c6c918b90602001615a28565b604051602081830303815290604052805190602001209050611c918a82888888612d38565b505b6040805182815260208a81013567ffffffffffffffff169082015260ff8b16917f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef0910160405180910390a2505050505050505050565b67ffffffffffffffff8216600090815260076020526040812081611d0e608085615a3c565b67ffffffffffffffff1681526020810191909152604001600020549392505050565b80516001600160a01b0316611d58576040516342bcdf7f60e11b815260040160405180910390fd5b80516004805460208085018051604080880180516060808b0180516001600160a01b039b8c167fffffffffffffffff000000000000000000000000000000000000000000000000909a168a17600160a01b63ffffffff988916021777ffffffffffffffffffffffffffffffffffffffffffffffff167801000000000000000000000000000000000000000000000000948816949094026001600160e01b031693909317600160e01b93871693909302929092179098556080808b0180516005805473ffffffffffffffffffffffffffffffffffffffff1916918d169190911790558451988952955185169688019690965290518316918601919091525116938301939093529151909216908201527fa55bd56595c45f517e5967a3067f3dca684445a3080e7c04a4e0d5a40cda627d9060a00160405180910390a150565b6060865167ffffffffffffffff811115611eb257611eb2613f0d565b604051908082528060200260200182016040528015611ef757816020015b6040805180820190915260008082526020820152815260200190600190039081611ed05790505b50905060005b8751811015611fa957611f84888281518110611f1b57611f1b614f73565b6020026020010151888888888887818110611f3857611f38614f73565b9050602002810190611f4a9190615a63565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612f1d92505050565b828281518110611f9657611f96614f73565b6020908102919091010152600101611efd565b505b9695505050505050565b6000611fc0836132c2565b8015610d775750610d778383613326565b336001600160a01b038216036120295760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016106f8565b6001805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b806040015160ff166000036120b2576000604051631b3fab5160e11b81526004016106f89190615aaa565b60208082015160ff8082166000908152600290935260408320600181015492939092839216900361211f57606084015160018201805491151562010000027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff909216919091179055612174565b6060840151600182015460ff6201000090910416151590151514612174576040517f87f6037c00000000000000000000000000000000000000000000000000000000815260ff841660048201526024016106f8565b60a0840151805161010010156121a0576001604051631b3fab5160e11b81526004016106f89190615aaa565b61220684846003018054806020026020016040519081016040528092919081815260200182805480156121fc57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116121de575b50505050506133e1565b84606001511561232d5761227484846002018054806020026020016040519081016040528092919081815260200182805480156121fc576020028201919060005260206000209081546001600160a01b031681526001909101906020018083116121de5750505050506133e1565b6080850151805161010010156122a0576002604051631b3fab5160e11b81526004016106f89190615aaa565b60408601516122b0906003615ac4565b60ff168151116122d6576003604051631b3fab5160e11b81526004016106f89190615aaa565b80516001840180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1661010060ff84160217905561231e9060028601906020840190613e86565b5061232b8582600161344a565b505b6123398482600261344a565b805161234e9060038501906020840190613e86565b5060408581015160018401805460ff191660ff8316179055865180855560a088015192517fab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f547936123a79389939260028a01929190615ae0565b60405180910390a1611904846135be565b815181516040517f2cbc26bb000000000000000000000000000000000000000000000000000000008152608083901b77ffffffffffffffff00000000000000000000000000000000166004820152901515907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632cbc26bb90602401602060405180830381865afa15801561245b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061247f91906154fe565b1561250b5780156124c8576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff831660048201526024016106f8565b60405167ffffffffffffffff831681527faab522ed53d887e56ed53dd37398a01aeef6a58e0fa77c2173beb9512d8949339060200160405180910390a150505050565b60006125168361190b565b6001018054612524906157d4565b80601f0160208091040260200160405190810160405280929190818152602001828054612550906157d4565b801561259d5780601f106125725761010080835404028352916020019161259d565b820191906000526020600020905b81548152906001019060200180831161258057829003601f168201915b505050602088015151929350505060008190036125e5576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8560400151518114612623576040517f57e0e08300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008167ffffffffffffffff81111561263e5761263e613f0d565b604051908082528060200260200182016040528015612667578160200160208202803683370190505b50905060005b828110156127c05760008860200151828151811061268d5761268d614f73565b602002602001015190507f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681600001516040015167ffffffffffffffff161461272057805160409081015190517f38432a2200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016106f8565b8667ffffffffffffffff1681600001516020015167ffffffffffffffff1614612790578051602001516040517f6c95f1eb00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808a16600483015290911660248201526044016106f8565b61279a81866135da565b8383815181106127ac576127ac614f73565b60209081029190910101525060010161266d565b5060006127d786838a606001518b608001516136fc565b90508060000361281f576040517f7dd17a7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff871660048201526024016106f8565b60005b83811015610cb65760005a905060008a60200151838151811061284757612847614f73565b6020026020010151905060006128658a836000015160600151610d2a565b9050600081600381111561287b5761287b614ae0565b14806128985750600381600381111561289657612896614ae0565b145b6128f0578151606001516040805167ffffffffffffffff808e16825290921660208301527f3b575419319662b2a6f5e2467d84521517a3382b908eb3d557bb3fdb0c50e23c91015b60405180910390a1505050612d30565b88156129c057600454600090600160a01b900463ffffffff1661291387426155e6565b11905080806129335750600382600381111561293157612931614ae0565b145b612975576040517fa9cfc86200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8c1660048201526024016106f8565b8b858151811061298757612987614f73565b60200260200101516000146129ba578b85815181106129a8576129a8614f73565b60200260200101518360800181815250505b50612a21565b60008160038111156129d4576129d4614ae0565b14612a21578151606001516040805167ffffffffffffffff808e16825290921660208301527f3ef2a99c550a751d4b0b261268f05a803dfb049ab43616a1ffb388f61fe6512091016128e0565b81516080015167ffffffffffffffff1615612b10576000816003811115612a4a57612a4a614ae0565b03612b105781516080015160208301516040517fe0e03cae0000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169263e0e03cae92612ac1928f929190600401615b8c565b6020604051808303816000875af1158015612ae0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b0491906154fe565b612b1057505050612d30565b60008c604001518581518110612b2857612b28614f73565b6020026020010151905080518360a001515114612b8c578251606001516040517f1cfe6d8b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808e16600483015290911660248201526044016106f8565b612ba08b846000015160600151600161373a565b600080612bad85846137e2565b91509150612bc48d8660000151606001518461373a565b8b15612c34576003826003811115612bde57612bde614ae0565b03612c34576000846003811115612bf757612bf7614ae0565b14612c34578451516040517f2b11b8d90000000000000000000000000000000000000000000000000000000081526106f891908390600401615bb9565b6002826003811115612c4857612c48614ae0565b14612ca2576003826003811115612c6157612c61614ae0565b14612ca2578451606001516040517f926c5a3e0000000000000000000000000000000000000000000000000000000081526106f8918f918590600401615bd2565b84600001516000015185600001516060015167ffffffffffffffff168e67ffffffffffffffff167f05665fe9ad095383d018353f4cbcba77e84db27dd215081bbf7cdf9ae6fbe48b8c8b81518110612cfc57612cfc614f73565b602002602001015186865a612d11908e6155e6565b604051612d219493929190615bf8565b60405180910390a45050505050505b600101612822565b8251600090815b818110156111b8576000600188868460208110612d5e57612d5e614f73565b612d6b91901a601b6159ff565b898581518110612d7d57612d7d614f73565b6020026020010151898681518110612d9757612d97614f73565b602002602001015160405160008152602001604052604051612dd5949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015612df7573d6000803e3d6000fd5b505060408051601f1981015160ff808e166000908152600360209081528582206001600160a01b03851683528152858220858701909652855480841686529397509095509293928401916101009004166002811115612e5857612e58614ae0565b6002811115612e6957612e69614ae0565b9052509050600181602001516002811115612e8657612e86614ae0565b14612ebd576040517fca31867a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051600160ff9091161b851615612f00576040517ff67bc7c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806000015160ff166001901b851794505050806001019050612d3f565b60408051808201909152600080825260208201526000612f4087602001516138ac565b6040517fbbe4f6db0000000000000000000000000000000000000000000000000000000081526001600160a01b0380831660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063bbe4f6db90602401602060405180830381865afa158015612fc5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fe99190615c2f565b90506001600160a01b0381161580613031575061302f6001600160a01b0382167faff2afbf00000000000000000000000000000000000000000000000000000000611fb5565b155b15613073576040517fae9b4ce90000000000000000000000000000000000000000000000000000000081526001600160a01b03821660048201526024016106f8565b60045460009081906130959089908690600160e01b900463ffffffff16613952565b9150915060008060006131626040518061010001604052808e81526020018c67ffffffffffffffff1681526020018d6001600160a01b031681526020018f606001518152602001896001600160a01b031681526020018f6000015181526020018f6040015181526020018b8152506040516024016131139190615c4c565b60408051601f198184030181529190526020810180516001600160e01b03167f390775370000000000000000000000000000000000000000000000000000000017905287866113886084613a80565b925092509250826131a157816040517fe1cd55090000000000000000000000000000000000000000000000000000000081526004016106f891906148fb565b81516020146131e95781516040517f78ef80240000000000000000000000000000000000000000000000000000000081526020600482015260248101919091526044016106f8565b6000828060200190518101906131ff9190615d19565b9050866001600160a01b03168c6001600160a01b0316146132945760006132308d8a61322b868a6155e6565b613952565b5090508681108061324a57508161324788836155e6565b14155b15613292576040517fa966e21f0000000000000000000000000000000000000000000000000000000081526004810183905260248101889052604481018290526064016106f8565b505b604080518082019091526001600160a01b039098168852602088015250949550505050505095945050505050565b60006132ee827f01ffc9a700000000000000000000000000000000000000000000000000000000613326565b8015610d7a575061331f827fffffffff00000000000000000000000000000000000000000000000000000000613326565b1592915050565b6040517fffffffff0000000000000000000000000000000000000000000000000000000082166024820152600090819060440160408051601f19818403018152919052602080820180516001600160e01b03167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825192935060009283928392909183918a617530fa92503d915060005190508280156133ca575060208210155b80156133d65750600081115b979650505050505050565b60005b81518110156107245760ff83166000908152600360205260408120835190919084908490811061341657613416614f73565b6020908102919091018101516001600160a01b03168252810191909152604001600020805461ffff191690556001016133e4565b60005b8251811015610d2457600083828151811061346a5761346a614f73565b602002602001015190506000600281111561348757613487614ae0565b60ff80871660009081526003602090815260408083206001600160a01b038716845290915290205461010090041660028111156134c6576134c6614ae0565b146134e7576004604051631b3fab5160e11b81526004016106f89190615aaa565b6001600160a01b038116613527576040517fd6c62c9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052808360ff16815260200184600281111561354d5761354d614ae0565b905260ff80871660009081526003602090815260408083206001600160a01b0387168452825290912083518154931660ff198416811782559184015190929091839161ffff1916176101008360028111156135aa576135aa614ae0565b02179055509050505080600101905061344d565b60ff8116610581576009805467ffffffffffffffff1916905550565b815160208082015160409283015192516000938493613620937f2425b0b9f9054c76ff151b0a175b18f37a4a4e82013a72e9f15c9caa095ed21f93909291889101615d32565b60408051601f1981840301815290829052805160209182012086518051888401516060808b0151908401516080808d015195015195976136699794969395929491939101615d65565b604051602081830303815290604052805190602001208560400151805190602001208660a001516040516020016136a09190615e6a565b60408051601f198184030181528282528051602091820120908301969096528101939093526060830191909152608082015260a081019190915260c0015b60405160208183030381529060405280519060200120905092915050565b60008061370a858585613ba6565b67ffffffffffffffff8716600090815260086020908152604080832093835292905220549150505b949350505050565b6000600261374960808561560f565b67ffffffffffffffff1661375d9190615636565b9050600061376b8585611ce9565b90508161377a600160046155e6565b901b19168183600381111561379157613791614ae0565b67ffffffffffffffff871660009081526007602052604081209190921b929092179182916137c0608088615a3c565b67ffffffffffffffff1681526020810191909152604001600020555050505050565b6040517fa80036b4000000000000000000000000000000000000000000000000000000008152600090606090309063a80036b4906138269087908790600401615eca565b600060405180830381600087803b15801561384057600080fd5b505af1925050508015613851575060015b613890573d80801561387f576040519150601f19603f3d011682016040523d82523d6000602084013e613884565b606091505b506003925090506138a5565b50506040805160208101909152600081526002905b9250929050565b600081516020146138eb57816040517f8d666f600000000000000000000000000000000000000000000000000000000081526004016106f891906148fb565b6000828060200190518101906139019190615d19565b90506001600160a01b03811180613919575061040081105b15610d7a57826040517f8d666f600000000000000000000000000000000000000000000000000000000081526004016106f891906148fb565b60008060008060006139cc8860405160240161397d91906001600160a01b0391909116815260200190565b60408051601f198184030181529190526020810180516001600160e01b03167f70a082310000000000000000000000000000000000000000000000000000000017905288886113886084613a80565b92509250925082613a0b57816040517fe1cd55090000000000000000000000000000000000000000000000000000000081526004016106f891906148fb565b6020825114613a535781516040517f78ef80240000000000000000000000000000000000000000000000000000000081526020600482015260248101919091526044016106f8565b81806020019051810190613a679190615d19565b613a7182886155e6565b94509450505050935093915050565b6000606060008361ffff1667ffffffffffffffff811115613aa357613aa3613f0d565b6040519080825280601f01601f191660200182016040528015613acd576020820181803683370190505b509150863b613b00577f0c3b563c0000000000000000000000000000000000000000000000000000000060005260046000fd5b5a85811015613b33577fafa32a2c0000000000000000000000000000000000000000000000000000000060005260046000fd5b8590036040810481038710613b6c577f37c3be290000000000000000000000000000000000000000000000000000000060005260046000fd5b505a6000808a5160208c0160008c8cf193505a900390503d84811115613b8f5750835b808352806000602085013e50955095509592505050565b8251825160009190818303613be7576040517f11a6b26400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6101018211801590613bfb57506101018111155b613c18576040516309bde33960e01b815260040160405180910390fd5b60001982820101610100811115613c42576040516309bde33960e01b815260040160405180910390fd5b80600003613c6f5786600081518110613c5d57613c5d614f73565b60200260200101519350505050613e3e565b60008167ffffffffffffffff811115613c8a57613c8a613f0d565b604051908082528060200260200182016040528015613cb3578160200160208202803683370190505b50905060008080805b85811015613ddd5760006001821b8b811603613d175788851015613d00578c5160018601958e918110613cf157613cf1614f73565b60200260200101519050613d39565b8551600185019487918110613cf157613cf1614f73565b8b5160018401938d918110613d2e57613d2e614f73565b602002602001015190505b600089861015613d69578d5160018701968f918110613d5a57613d5a614f73565b60200260200101519050613d8b565b8651600186019588918110613d8057613d80614f73565b602002602001015190505b82851115613dac576040516309bde33960e01b815260040160405180910390fd5b613db68282613e45565b878481518110613dc857613dc8614f73565b60209081029190910101525050600101613cbc565b506001850382148015613def57508683145b8015613dfa57508581145b613e17576040516309bde33960e01b815260040160405180910390fd5b836001860381518110613e2c57613e2c614f73565b60200260200101519750505050505050505b9392505050565b6000818310613e5d57613e588284613e63565b610d77565b610d7783835b6040805160016020820152908101839052606081018290526000906080016136de565b828054828255906000526020600020908101928215613ee8579160200282015b82811115613ee8578251825473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03909116178255602090920191600190910190613ea6565b50613ef4929150613ef8565b5090565b5b80821115613ef45760008155600101613ef9565b634e487b7160e01b600052604160045260246000fd5b6040516080810167ffffffffffffffff81118282101715613f4657613f46613f0d565b60405290565b60405160a0810167ffffffffffffffff81118282101715613f4657613f46613f0d565b60405160c0810167ffffffffffffffff81118282101715613f4657613f46613f0d565b6040805190810167ffffffffffffffff81118282101715613f4657613f46613f0d565b6040516060810167ffffffffffffffff81118282101715613f4657613f46613f0d565b604051601f8201601f1916810167ffffffffffffffff8111828210171561400157614001613f0d565b604052919050565b600067ffffffffffffffff82111561402357614023613f0d565b5060051b60200190565b6001600160a01b038116811461058157600080fd5b803567ffffffffffffffff8116811461405a57600080fd5b919050565b801515811461058157600080fd5b803561405a8161405f565b600067ffffffffffffffff82111561409257614092613f0d565b50601f01601f191660200190565b600082601f8301126140b157600080fd5b81356140c46140bf82614078565b613fd8565b8181528460208386010111156140d957600080fd5b816020850160208301376000918101602001919091529392505050565b6000602080838503121561410957600080fd5b823567ffffffffffffffff8082111561412157600080fd5b818501915085601f83011261413557600080fd5b81356141436140bf82614009565b81815260059190911b8301840190848101908883111561416257600080fd5b8585015b838110156142085780358581111561417e5760008081fd5b86016080818c03601f19018113156141965760008081fd5b61419e613f23565b898301356141ab8161402d565b815260406141ba848201614042565b8b8301526060808501356141cd8161405f565b838301529284013592898411156141e657600091508182fd5b6141f48f8d868801016140a0565b908301525085525050918601918601614166565b5098975050505050505050565b600060a0828403121561422757600080fd5b61422f613f4c565b90508135815261424160208301614042565b602082015261425260408301614042565b604082015261426360608301614042565b606082015261427460808301614042565b608082015292915050565b803561405a8161402d565b600082601f83011261429b57600080fd5b813560206142ab6140bf83614009565b82815260059290921b840181019181810190868411156142ca57600080fd5b8286015b84811015611fa957803567ffffffffffffffff808211156142ef5760008081fd5b9088019060a0828b03601f19018113156143095760008081fd5b614311613f4c565b87840135838111156143235760008081fd5b6143318d8a838801016140a0565b825250604080850135848111156143485760008081fd5b6143568e8b838901016140a0565b8a840152506060808601358581111561436f5760008081fd5b61437d8f8c838a01016140a0565b838501525060809150818601358184015250828501359250838311156143a35760008081fd5b6143b18d8a858801016140a0565b9082015286525050509183019183016142ce565b600061014082840312156143d857600080fd5b6143e0613f6f565b90506143ec8383614215565b815260a082013567ffffffffffffffff8082111561440957600080fd5b614415858386016140a0565b602084015260c084013591508082111561442e57600080fd5b61443a858386016140a0565b604084015261444b60e0850161427f565b6060840152610100840135608084015261012084013591508082111561447057600080fd5b5061447d8482850161428a565b60a08301525092915050565b600082601f83011261449a57600080fd5b813560206144aa6140bf83614009565b82815260059290921b840181019181810190868411156144c957600080fd5b8286015b84811015611fa957803567ffffffffffffffff8111156144ed5760008081fd5b6144fb8986838b01016143c5565b8452509183019183016144cd565b600082601f83011261451a57600080fd5b8135602061452a6140bf83614009565b82815260059290921b8401810191818101908684111561454957600080fd5b8286015b84811015611fa957803567ffffffffffffffff8082111561456d57600080fd5b818901915089603f83011261458157600080fd5b858201356145916140bf82614009565b81815260059190911b830160400190878101908c8311156145b157600080fd5b604085015b838110156145ea578035858111156145cd57600080fd5b6145dc8f6040838a01016140a0565b8452509189019189016145b6565b5087525050509284019250830161454d565b600082601f83011261460d57600080fd5b8135602061461d6140bf83614009565b8083825260208201915060208460051b87010193508684111561463f57600080fd5b602086015b84811015611fa95780358352918301918301614644565b600082601f83011261466c57600080fd5b8135602061467c6140bf83614009565b82815260059290921b8401810191818101908684111561469b57600080fd5b8286015b84811015611fa957803567ffffffffffffffff808211156146c05760008081fd5b9088019060a0828b03601f19018113156146da5760008081fd5b6146e2613f4c565b6146ed888501614042565b8152604080850135848111156147035760008081fd5b6147118e8b83890101614489565b8a840152506060808601358581111561472a5760008081fd5b6147388f8c838a0101614509565b83850152506080915081860135858111156147535760008081fd5b6147618f8c838a01016145fc565b918401919091525091909301359083015250835291830191830161469f565b600080604080848603121561479457600080fd5b833567ffffffffffffffff808211156147ac57600080fd5b6147b88783880161465b565b94506020915081860135818111156147cf57600080fd5b8601601f810188136147e057600080fd5b80356147ee6140bf82614009565b81815260059190911b8201840190848101908a83111561480d57600080fd5b8584015b83811015614899578035868111156148295760008081fd5b8501603f81018d1361483b5760008081fd5b8781013561484b6140bf82614009565b81815260059190911b82018a0190898101908f83111561486b5760008081fd5b928b01925b828410156148895783358252928a0192908a0190614870565b8652505050918601918601614811565b50809750505050505050509250929050565b60005b838110156148c65781810151838201526020016148ae565b50506000910152565b600081518084526148e78160208601602086016148ab565b601f01601f19169290920160200192915050565b602081526000610d7760208301846148cf565b8060608101831015610d7a57600080fd5b60008083601f84011261493157600080fd5b50813567ffffffffffffffff81111561494957600080fd5b6020830191508360208285010111156138a557600080fd5b60008083601f84011261497357600080fd5b50813567ffffffffffffffff81111561498b57600080fd5b6020830191508360208260051b85010111156138a557600080fd5b60008060008060008060008060e0898b0312156149c257600080fd5b6149cc8a8a61490e565b9750606089013567ffffffffffffffff808211156149e957600080fd5b6149f58c838d0161491f565b909950975060808b0135915080821115614a0e57600080fd5b614a1a8c838d01614961565b909750955060a08b0135915080821115614a3357600080fd5b50614a408b828c01614961565b999c989b50969995989497949560c00135949350505050565b600080600060808486031215614a6e57600080fd5b614a78858561490e565b9250606084013567ffffffffffffffff811115614a9457600080fd5b614aa08682870161491f565b9497909650939450505050565b60008060408385031215614ac057600080fd5b614ac983614042565b9150614ad760208401614042565b90509250929050565b634e487b7160e01b600052602160045260246000fd5b60048110614b0657614b06614ae0565b9052565b60208101610d7a8284614af6565b600060208284031215614b2a57600080fd5b813567ffffffffffffffff811115614b4157600080fd5b820160a08185031215613e3e57600080fd5b803563ffffffff8116811461405a57600080fd5b600060a08284031215614b7957600080fd5b614b81613f4c565b8235614b8c8161402d565b8152614b9a60208401614b53565b6020820152614bab60408401614b53565b6040820152614bbc60608401614b53565b60608201526080830135614bcf8161402d565b60808201529392505050565b600080600060408486031215614bf057600080fd5b833567ffffffffffffffff80821115614c0857600080fd5b614c14878388016143c5565b94506020860135915080821115614c2a57600080fd5b50614aa086828701614961565b803560ff8116811461405a57600080fd5b600060208284031215614c5a57600080fd5b610d7782614c37565b60008151808452602080850194506020840160005b83811015614c9d5781516001600160a01b031687529582019590820190600101614c78565b509495945050505050565b60208152600082518051602084015260ff602082015116604084015260ff604082015116606084015260608101511515608084015250602083015160c060a0840152614cf760e0840182614c63565b90506040840151601f198483030160c0850152614d148282614c63565b95945050505050565b60008060408385031215614d3057600080fd5b614d3983614042565b946020939093013593505050565b600060208284031215614d5957600080fd5b610d7782614042565b602081526001600160a01b03825116602082015260208201511515604082015267ffffffffffffffff60408301511660608201526000606083015160808084015261373260a08401826148cf565b600060208284031215614dc257600080fd5b8135613e3e8161402d565b600082601f830112614dde57600080fd5b81356020614dee6140bf83614009565b8083825260208201915060208460051b870101935086841115614e1057600080fd5b602086015b84811015611fa9578035614e288161402d565b8352918301918301614e15565b60006020808385031215614e4857600080fd5b823567ffffffffffffffff80821115614e6057600080fd5b818501915085601f830112614e7457600080fd5b8135614e826140bf82614009565b81815260059190911b83018401908481019088831115614ea157600080fd5b8585015b8381101561420857803585811115614ebc57600080fd5b860160c0818c03601f19011215614ed35760008081fd5b614edb613f6f565b8882013581526040614eee818401614c37565b8a8301526060614eff818501614c37565b8284015260809150614f1282850161406d565b9083015260a08381013589811115614f2a5760008081fd5b614f388f8d83880101614dcd565b838501525060c0840135915088821115614f525760008081fd5b614f608e8c84870101614dcd565b9083015250845250918601918601614ea5565b634e487b7160e01b600052603260045260246000fd5b80356001600160e01b038116811461405a57600080fd5b600082601f830112614fb157600080fd5b81356020614fc16140bf83614009565b82815260069290921b84018101918181019086841115614fe057600080fd5b8286015b84811015611fa95760408189031215614ffd5760008081fd5b615005613f92565b61500e82614042565b815261501b858301614f89565b81860152835291830191604001614fe4565b600082601f83011261503e57600080fd5b8135602061504e6140bf83614009565b82815260059290921b8401810191818101908684111561506d57600080fd5b8286015b84811015611fa957803567ffffffffffffffff808211156150925760008081fd5b9088019060a0828b03601f19018113156150ac5760008081fd5b6150b4613f4c565b6150bf888501614042565b815260406150ce818601614042565b8983015260606150df818701614042565b8284015260809150818601358184015250828501359250838311156151045760008081fd5b6151128d8a858801016140a0565b908201528652505050918301918301615071565b600082601f83011261513757600080fd5b813560206151476140bf83614009565b82815260069290921b8401810191818101908684111561516657600080fd5b8286015b84811015611fa957604081890312156151835760008081fd5b61518b613f92565b81358152848201358582015283529183019160400161516a565b600060208083850312156151b857600080fd5b823567ffffffffffffffff808211156151d057600080fd5b90840190606082870312156151e457600080fd5b6151ec613fb5565b8235828111156151fb57600080fd5b8301604081890381131561520e57600080fd5b615216613f92565b82358581111561522557600080fd5b8301601f81018b1361523657600080fd5b80356152446140bf82614009565b81815260069190911b8201890190898101908d83111561526357600080fd5b928a01925b828410156152b35785848f0312156152805760008081fd5b615288613f92565b84356152938161402d565b81526152a0858d01614f89565b818d0152825292850192908a0190615268565b8452505050828701359150848211156152cb57600080fd5b6152d78a838501614fa0565b818801528352505082840135828111156152f057600080fd5b6152fc8882860161502d565b8583015250604083013593508184111561531557600080fd5b61532187858501615126565b60408201529695505050505050565b600082825180855260208086019550808260051b84010181860160005b848110156153c057858303601f190189528151805167ffffffffffffffff908116855285820151811686860152604080830151909116908501526060808201519085015260809081015160a0918501829052906153ac818601836148cf565b9a86019a945050509083019060010161534d565b5090979650505050505050565b60008151808452602080850194506020840160005b83811015614c9d5781518051885283015183880152604090960195908201906001016153e2565b60408152600061541c6040830185615330565b8281036020840152614d1481856153cd565b805160408084528151848201819052600092602091908201906060870190855b8181101561548557835180516001600160a01b031684528501516001600160e01b031685840152928401929185019160010161544e565b50508583015187820388850152805180835290840192506000918401905b808310156154df578351805167ffffffffffffffff1683528501516001600160e01b0316858301529284019260019290920191908501906154a3565b50979650505050505050565b602081526000610d77602083018461542e565b60006020828403121561551057600080fd5b8151613e3e8161405f565b634e487b7160e01b600052601160045260246000fd5b67ffffffffffffffff8181168382160190808211156155525761555261551b565b5092915050565b602081526000825160606020840152615575608084018261542e565b90506020840151601f19808584030160408601526155938383615330565b9250604086015191508085840301606086015250614d1482826153cd565b6000602082840312156155c357600080fd5b813567ffffffffffffffff8111156155da57600080fd5b6137328482850161465b565b81810381811115610d7a57610d7a61551b565b634e487b7160e01b600052601260045260246000fd5b600067ffffffffffffffff8084168061562a5761562a6155f9565b92169190910692915050565b8082028115828204841417610d7a57610d7a61551b565b805182526000602067ffffffffffffffff81840151168185015260408084015160a0604087015261568160a08701826148cf565b90506060850151868203606088015261569a82826148cf565b608087810151898303918a01919091528051808352908601935060009250908501905b808310156154df57835180516001600160a01b03168352860151868301529285019260019290920191908401906156bd565b602081526000610d77602083018461564d565b608081526000615715608083018761564d565b61ffff9590951660208301525060408101929092526001600160a01b0316606090910152919050565b60008060006060848603121561575357600080fd5b835161575e8161405f565b602085015190935067ffffffffffffffff81111561577b57600080fd5b8401601f8101861361578c57600080fd5b805161579a6140bf82614078565b8181528760208385010111156157af57600080fd5b6157c08260208301602086016148ab565b809450505050604084015190509250925092565b600181811c908216806157e857607f821691505b60208210810361580857634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115610724576000816000526020600020601f850160051c810160208610156158375750805b601f850160051c820191505b8181101561585657828155600101615843565b505050505050565b815167ffffffffffffffff81111561587857615878613f0d565b61588c8161588684546157d4565b8461580e565b602080601f8311600181146158c157600084156158a95750858301515b600019600386901b1c1916600185901b178555615856565b600085815260208120601f198616915b828110156158f0578886015182559484019460019091019084016158d1565b508582101561590e5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6000602080835283546001600160a01b038116602085015260ff8160a01c161515604085015267ffffffffffffffff8160a81c16606085015250600180850160808086015260008154615970816157d4565b8060a089015260c0600183166000811461599157600181146159ad576159dd565b60ff19841660c08b015260c083151560051b8b010194506159dd565b85600052602060002060005b848110156159d45781548c82018501529088019089016159b9565b8b0160c0019550505b50929998505050505050505050565b80820180821115610d7a57610d7a61551b565b60ff8181168382160190811115610d7a57610d7a61551b565b8183823760009101908152919050565b828152606082602083013760800192915050565b600067ffffffffffffffff80841680615a5757615a576155f9565b92169190910492915050565b6000808335601e19843603018112615a7a57600080fd5b83018035915067ffffffffffffffff821115615a9557600080fd5b6020019150368190038213156138a557600080fd5b6020810160058310615abe57615abe614ae0565b91905290565b60ff81811683821602908116908181146155525761555261551b565b600060a0820160ff881683526020878185015260a0604085015281875480845260c0860191508860005282600020935060005b81811015615b385784546001600160a01b031683526001948501949284019201615b13565b50508481036060860152865180825290820192508187019060005b81811015615b785782516001600160a01b031685529383019391830191600101615b53565b50505060ff85166080850152509050611fab565b600067ffffffffffffffff808616835280851660208401525060606040830152614d1460608301846148cf565b82815260406020820152600061373260408301846148cf565b67ffffffffffffffff848116825283166020820152606081016137326040830184614af6565b848152615c086020820185614af6565b608060408201526000615c1e60808301856148cf565b905082606083015295945050505050565b600060208284031215615c4157600080fd5b8151613e3e8161402d565b6020815260008251610100806020850152615c6b6101208501836148cf565b91506020850151615c88604086018267ffffffffffffffff169052565b5060408501516001600160a01b038116606086015250606085015160808501526080850151615cc260a08601826001600160a01b03169052565b5060a0850151601f19808685030160c0870152615cdf84836148cf565b935060c08701519150808685030160e0870152615cfc84836148cf565b935060e0870151915080868503018387015250611fab83826148cf565b600060208284031215615d2b57600080fd5b5051919050565b848152600067ffffffffffffffff808616602084015280851660408401525060806060830152611fab60808301846148cf565b86815260c060208201526000615d7e60c08301886148cf565b6001600160a01b039690961660408301525067ffffffffffffffff9384166060820152608081019290925290911660a09091015292915050565b600082825180855260208086019550808260051b84010181860160005b848110156153c057601f19868403018952815160a08151818652615dfb828701826148cf565b9150508582015185820387870152615e1382826148cf565b91505060408083015186830382880152615e2d83826148cf565b92505050606080830151818701525060808083015192508582038187015250615e5681836148cf565b9a86019a9450505090830190600101615dd5565b602081526000610d776020830184615db8565b60008282518085526020808601955060208260051b8401016020860160005b848110156153c057601f19868403018952615eb88383516148cf565b98840198925090830190600101615e9c565b604081526000835180516040840152602081015167ffffffffffffffff80821660608601528060408401511660808601528060608401511660a08601528060808401511660c086015250505060208401516101408060e0850152615f326101808501836148cf565b91506040860151603f198086850301610100870152615f5184836148cf565b935060608801519150615f706101208701836001600160a01b03169052565b60808801518387015260a0880151925080868503016101608701525050615f978282615db8565b9150508281036020840152614d148185615e7d56fea164736f6c6343000818000a", } var OffRampABI = OffRampMetaData.ABI diff --git a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt index 659e8ac648..6396cf5cea 100644 --- a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -23,7 +23,7 @@ multi_aggregate_rate_limiter: ../../../contracts/solc/v0.8.24/MultiAggregateRate multi_ocr3_helper: ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Helper.abi ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Helper.bin 6b56e0114a4d50797d30a34aecc2641ef340451d0c3fcb9d729bba4df2435122 nonce_manager: ../../../contracts/solc/v0.8.24/NonceManager/NonceManager.abi ../../../contracts/solc/v0.8.24/NonceManager/NonceManager.bin 6f64e1083b356c06ee66b9138e398b9c97a4cd3e8c9ec38cf3010cebc79af536 ocr3_config_encoder: ../../../contracts/solc/v0.8.24/IOCR3ConfigEncoder/IOCR3ConfigEncoder.abi ../../../contracts/solc/v0.8.24/IOCR3ConfigEncoder/IOCR3ConfigEncoder.bin 9254b35a86f00fde7b7193a033ca58f6521a66e87b9cf9da6ce5660082e79f5d -offramp: ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.abi ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.bin e6827d4a39ed916c3ffa5a7d08b6bfa03cf101bee7207e5c96723b6a9fc761b0 +offramp: ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.abi ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.bin 2d1cdfd810e2fde409610f4d188889e62a41c8baceb8948849c9a78623a252b6 onramp: ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.abi ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.bin c37096aaa0369ad988e94c300ba62917e17fcc71a3c1aa3e9b8420f21c0591d2 ping_pong_demo: ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.abi ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.bin c1c2f8a65c7ffd971899cae7fe62f2da57d09e936151e2b92163c4bebe699d6b price_registry: ../../../contracts/solc/v0.8.24/PriceRegistry/PriceRegistry.abi ../../../contracts/solc/v0.8.24/PriceRegistry/PriceRegistry.bin e7781d600c1bb7aa4620106af7f6e146a109b97f4cb6a7d06c9e15773340ecb2 From d389c1d3a13c6e4d3c39e731b852874a809a5da2 Mon Sep 17 00:00:00 2001 From: Balamurali Gopalswami <167726375+b-gopalswami@users.noreply.github.com> Date: Thu, 5 Sep 2024 11:26:35 -0400 Subject: [PATCH 075/115] Update prod testnet config with 1.5 RMN contract (#1412) ## Motivation RMN contract details needs to be updated in prod tesnet config to make test assertions work. https://smartcontract-it.atlassian.net/browse/CCIP-3164 ## Solution Update latest 1.5 RMN contract details in the prod testnet config and cleanup unwanted network details. --- .../tomls/ccip1.4-stress/prod-testnet.toml | 795 +----------------- 1 file changed, 33 insertions(+), 762 deletions(-) diff --git a/integration-tests/ccip-tests/testconfig/tomls/ccip1.4-stress/prod-testnet.toml b/integration-tests/ccip-tests/testconfig/tomls/ccip1.4-stress/prod-testnet.toml index 917a739b18..c4aadb998d 100644 --- a/integration-tests/ccip-tests/testconfig/tomls/ccip1.4-stress/prod-testnet.toml +++ b/integration-tests/ccip-tests/testconfig/tomls/ccip1.4-stress/prod-testnet.toml @@ -11,888 +11,159 @@ CommitStore = '1.2.0' Data = """ { "lane_configs": { - "Arbitrum Sepolia": { - "is_native_fee_token": true, - "fee_token": "0xb1D4538B4571d411F07960EF2838Ce337FE1E80E", - "bridge_tokens": [ - ], - "bridge_tokens_pools": [ - ], - "price_aggregators": null, - "arm": "0x5EF7a726Fd21Fd9D77D34E3C56cfDD8691F7F0ac", - "router": "0x2a9C5afB0d0e4BAb2BCdaE109EC4b0c4Be15a165", - "price_registry": "0x89D5b13908b9063abCC6791dc724bF7B7c93634C", - "wrapped_native": "0xE591bf0A0CF924A0674d7792db046B23CEbF5f34", - "src_contracts": { - "Avalanche Fuji": { - "on_ramp": "0x1Cb56374296ED19E86F68fA437ee679FD7798DaA", - "deployed_at": 33999325 - }, - "Base Sepolia": { - "on_ramp": "0x7854E73C73e7F9bb5b0D5B4861E997f4C6E8dcC6", - "deployed_at": 9199926 - }, - "Gnosis Chiado": { - "on_ramp": "0x973CbE752258D32AE82b60CD1CB656Eebb588dF0", - "deployed_at": 42809650 - }, - "Optimism Sepolia": { - "on_ramp": "0x701Fe16916dd21EFE2f535CA59611D818B017877", - "deployed_at": 35180131 - }, - "Sepolia Testnet": { - "on_ramp": "0x4205E1Ca0202A248A5D42F5975A8FE56F3E302e9", - "deployed_at": 35180131 - }, - "WeMix Testnet": { - "on_ramp": "0xBD4106fBE4699FE212A34Cc21b10BFf22b02d959", - "deployed_at": 18816676 - } - }, - "dest_contracts": { - "Avalanche Fuji": { - "off_ramp": "0xcab0EF91Bee323d1A617c0a027eE753aFd6997E4", - "commit_store": "0x0d90b9b96cBFa0D01635ce12982ccE1b70827c7a", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Base Sepolia": { - "off_ramp": "0xc1982985720B959E66c19b64F783361Eb9B60F26", - "commit_store": "0x28F66bB336f6db713d6ad2a3bd1B7a531282A159", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Gnosis Chiado": { - "off_ramp": "0x935C26F9a9122E5F9a27f2d3803e74c75B94f5a3", - "commit_store": "0xEdb963Ec5c2E5AbdFdCF137eF44A445a7fa4787A", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Optimism Sepolia": { - "off_ramp": "0xfD404A89e1d195F0c65be1A9042C77745197659e", - "commit_store": "0x84B7B012c95f8A152B44Ab3e952f2dEE424fA8e1", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Sepolia Testnet": { - "off_ramp": "0x1c71f141b4630EBE52d6aF4894812960abE207eB", - "commit_store": "0xaB0c8Ba51E7Fa3E5693a4Fbb39473520FD85d173", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "WeMix Testnet": { - "off_ramp": "0x262e16C8D42aa07bE13e58F81e7D9F62F6DE2830", - "commit_store": "0xc132eFAf929299E5ee704Fa6D9796CFa23Bb8b2C", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - } - } - }, "Avalanche Fuji": { - "fee_token": "0x0b9d5D9136855f6FEc3c0993feE6E9CE8a297846", - "bridge_tokens": [ - ], - "bridge_tokens_pools": [ - ], - "price_aggregators": null, - "arm": "0x0ea0D7B2b78DD3A926fC76d6875a287F0AEB158F", + "is_native_fee_token": true, + "fee_token": "0xd00ae08403B9bbb9124bB305C09058E32C39A48c", + "arm": "0x7e28DD790214139798446A121cFe950B51304684", "router": "0xF694E193200268f9a4868e4Aa017A0118C9a8177", "price_registry": "0x19e157E5fb1DAec1aE4BaB113fdf077F980704AA", "wrapped_native": "0xd00ae08403B9bbb9124bB305C09058E32C39A48c", "src_contracts": { - "Arbitrum Sepolia": { - "on_ramp": "0x8bB16BEDbFd62D1f905ACe8DBBF2954c8EEB4f66", - "deployed_at": 31888860 - }, - "BSC Testnet": { - "on_ramp": "0xF25ECF1Aad9B2E43EDc2960cF66f325783245535", - "deployed_at": 33214865 - }, "Base Sepolia": { "on_ramp": "0x1A674645f3EB4147543FCA7d40C5719cbd997362", - "deployed_at": 31235262 - }, - "Gnosis Chiado": { - "on_ramp": "0x1532e5b204ee2b2244170c78E743CB9c168F4DF9", - "deployed_at": 32817266 + "deployed_at": 0 }, "Optimism Sepolia": { "on_ramp": "0xC334DE5b020e056d0fE766dE46e8d9f306Ffa1E2", - "deployed_at": 30396804 - }, - "Polygon Amoy": { - "on_ramp": "0x610F76A35E17DA4542518D85FfEa12645eF111Fc", - "deployed_at": 31982368 + "deployed_at": 0 }, "Sepolia Testnet": { "on_ramp": "0x5724B4Cc39a9690135F7273b44Dfd3BA6c0c69aD", - "deployed_at": 33214865 - }, - "WeMix Testnet": { - "on_ramp": "0x677B5ab5C8522d929166c064d5700F147b15fa33", - "deployed_at": 30436465 + "deployed_at": 0 } }, "dest_contracts": { - "Arbitrum Sepolia": { - "off_ramp": "0x90A74072e7B0c2d59e13aB4d8f93c8198c413194", - "commit_store": "0xf3458CFd2fdf4a6CF0Ce296d520DD21eB194828b", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "BSC Testnet": { - "off_ramp": "0x10b28009E5D776F1f5AAA73941CE8953B8f42d26", - "commit_store": "0xacDD582F271eCF22FAd6764cCDe1c4a534b732A8", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, "Base Sepolia": { "off_ramp": "0xdBdE8510226d1E060A3bf982b67705C67f5697e2", "commit_store": "0x8Ee73BC9492b4182D289E5C1e66e40CD876CC00F", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Gnosis Chiado": { - "off_ramp": "0x56dF55aF5F0A4689f3364230587a68eD6A314fAd", - "commit_store": "0xabA7ff98094c4cc7A075812EefF2CD21f6400235", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Optimism Sepolia": { "off_ramp": "0x3d7CbC95DCC33257F14D6Eb780c88Bd56C6335BB", "commit_store": "0x1fcDC02edDfb405f378ba53cF9E6104feBcB7542", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Polygon Amoy": { - "off_ramp": "0x3e33290B90fD0FF30a3FA138934DF028E4eCA348", - "commit_store": "0xCFe3556Aa42d40be09BD23aa80448a19443BE5B1", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Sepolia Testnet": { "off_ramp": "0x9e5e4324F8608D54A50a317832d456a392E4F8C2", "commit_store": "0x92A51eD3F041B39EbD1e464C1f7cb1e8f8A8c63f", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "WeMix Testnet": { - "off_ramp": "0xD0D338318bC6837b091FC7AB5F2a94B7783507d5", - "commit_store": "0xd9D479208235c7355848ff4aF26eB5aacfDC30c6", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - } - } - }, - "BSC Testnet": { - "is_native_fee_token": true, - "fee_token": "0x84b9B910527Ad5C03A9Ca831909E21e236EA7b06", - "bridge_tokens": [ - ], - "bridge_tokens_pools": [ - ], - "price_aggregators": null, - "arm": "0xF9a21B587111e7E8745Fb8b13750014f19DB0014", - "router": "0xE1053aE1857476f36A3C62580FF9b016E8EE8F6f", - "price_registry": "0xCCDf022c9d31DC26Ebab4FB92432724a5b79809a", - "wrapped_native": "0xae13d989daC2f0dEbFf460aC112a837C89BAa7cd", - "src_contracts": { - "Avalanche Fuji": { - "on_ramp": "0xa2515683E99F50ADbE177519A46bb20FfdBaA5de", - "deployed_at": 40500000 - }, - "Base Sepolia": { - "on_ramp": "0x3E807220Ca84b997c0d1928162227b46C618e0c5", - "deployed_at": 37115558 - }, - "Gnosis Chiado": { - "on_ramp": "0x8735f991d41eA9cA9D2CC75cD201e4B7C866E63e", - "deployed_at": 40228352 - }, - "Polygon Amoy": { - "on_ramp": "0xf37CcbfC04adc1B56a46B36F811D52C744a1AF78", - "deployed_at": 39572254 - }, - "Sepolia Testnet": { - "on_ramp": "0xB1DE44B04C00eaFe9915a3C07a0CaeA4410537dF", - "deployed_at": 38150066 - }, - "WeMix Testnet": { - "on_ramp": "0x89268Afc1BEA0782a27ba84124E3F42b196af927", - "deployed_at": 38184995 - } - }, - "dest_contracts": { - "Avalanche Fuji": { - "off_ramp": "0x6e6fFCb6B4BED91ff0CC8C2e57EC029dA7DB80C2", - "commit_store": "0x38Bc38Bd824b6eE87571f9D3CFbe6D6E28E3Dc62", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Base Sepolia": { - "off_ramp": "0x2C61FD7E93Dc79422861282145c59B56dFbc3a8c", - "commit_store": "0x42fAe5B3605804CF6d08632d7A25864e24F792Ae", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Gnosis Chiado": { - "off_ramp": "0x71a44a60832B0F8B63232C9516e7E6aEc3A373Dc", - "commit_store": "0xAC24299a91b72d1Cb5B31147e3CF54964D896974", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Polygon Amoy": { - "off_ramp": "0x63440C7747d37bc6154b5538AE32b54FE0965AfA", - "commit_store": "0xAD22fA198CECfC534927aE1D480c460d5bB3460F", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Sepolia Testnet": { - "off_ramp": "0xf1c128Fe52Ea78CcAAB407509292E61ce38C1523", - "commit_store": "0x59dFD870dC4bd76A7B879A4f705Fdcd2595f85f9", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "WeMix Testnet": { - "off_ramp": "0xfd9B19c3725da5B517aA705B848ff3f21F98280e", - "commit_store": "0x3c1F1412563188aBc8FE3fd53E8F1Cb601CaB4f9", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" } } }, "Base Sepolia": { "is_native_fee_token": true, - "fee_token": "0xE4aB69C077896252FAFBD49EFD26B5D171A32410", - "bridge_tokens": [ - ], - "bridge_tokens_pools": [ - ], - "price_aggregators": null, - "arm": "0x5aA82cA372782d6CC33AA4C830Df2a91017A7e1b", + "fee_token": "0x4200000000000000000000000000000000000006", + "arm": "0x7827dD0481EE18DB646bD250d20A8eA43da52146", "router": "0xD3b06cEbF099CE7DA4AcCf578aaebFDBd6e88a93", "price_registry": "0x4D20536e60832bE579Cd38E89Dc03d11E1741FbA", "wrapped_native": "0x4200000000000000000000000000000000000006", "src_contracts": { - "Arbitrum Sepolia": { - "on_ramp": "0x58622a80c6DdDc072F2b527a99BE1D0934eb2b50", - "deployed_at": 5146539 - }, "Avalanche Fuji": { "on_ramp": "0xAbA09a1b7b9f13E05A6241292a66793Ec7d43357", - "deployed_at": 7810235 - }, - "BSC Testnet": { - "on_ramp": "0xD806966beAB5A3C75E5B90CDA4a6922C6A9F0c9d", - "deployed_at": 5144127 - }, - "Gnosis Chiado": { - "on_ramp": "0x2Eff2d1BF5C557d6289D208a7a43608f5E3FeCc2", - "deployed_at": 9817141 + "deployed_at": 0 }, "Optimism Sepolia": { "on_ramp": "0x3b39Cd9599137f892Ad57A4f54158198D445D147", - "deployed_at": 5147649 + "deployed_at": 0 }, "Sepolia Testnet": { "on_ramp": "0x6486906bB2d85A6c0cCEf2A2831C11A2059ebfea", - "deployed_at": 7810235 - }, - "ethereum-testnet-sepolia-mode-1": { - "on_ramp": "0x3d0115386C01436870a2c47e6297962284E70BA6", - "deployed_at": 10409731 + "deployed_at": 0 } }, "dest_contracts": { - "Arbitrum Sepolia": { - "off_ramp": "0xd364C06ac99a82a00d3eFF9F2F78E4Abe4b9baAA", - "commit_store": "0xdE8d0f47a71eA3fDFBD3162271652f2847939097", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, "Avalanche Fuji": { "off_ramp": "0xAd91214efFee446500940c764DF77AF18427294F", "commit_store": "0x1242b6c5e0e349b8d4BCf0938f961C4B4f7EA3Fa", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "BSC Testnet": { - "off_ramp": "0xd5E9508921434e8758f4540D55c1c066b7cc1598", - "commit_store": "0x1a86b29364D1B3fA3386329A361aA98A104b2742", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Gnosis Chiado": { - "off_ramp": "0x9Bb7e398ef9Acfe9cA584C39B1E233Cba62BB9f7", - "commit_store": "0x1F4B82cDebaC5e3a0Dd53183D47e51808B4a64cB", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Optimism Sepolia": { "off_ramp": "0x86a3910908eCaAA31Fcd9F0fC8841D8E98f1511d", "commit_store": "0xE99a87C9b5ed4D2b6060195DEea5106ffF655736", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Sepolia Testnet": { "off_ramp": "0x189F61D9B886Dd2975D5Abc893c8Cf5f5effda71", "commit_store": "0xEE7e27346DCD1e711348D0F7f7ECB53a9a3a08a7", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "ethereum-testnet-sepolia-mode-1": { - "off_ramp": "0xB26647A23e8b4284375e5C74b77c9557aE709D03", - "commit_store": "0x4b4fEB401d3E613e1D6242E155C83A80BF9ac2C9", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - } - } - }, - "Gnosis Chiado": { - "is_native_fee_token": true, - "fee_token": "0xDCA67FD8324990792C0bfaE95903B8A64097754F", - "bridge_tokens": [ - ], - "bridge_tokens_pools": [ - ], - "price_aggregators": null, - "arm": "0xb6f1Fe2CDE891eFd5Efd2A563C4C2F2549163718", - "router": "0x19b1bac554111517831ACadc0FD119D23Bb14391", - "price_registry": "0x2F4ACd1f8986c6B1788159C4c9a5fC3fceCCE363", - "wrapped_native": "0x18c8a7ec7897177E4529065a7E7B0878358B3BfF", - "src_contracts": { - "Arbitrum Sepolia": { - "on_ramp": "0x473b49fb592B54a4BfCD55d40E048431982879C9", - "deployed_at": 9718588 - }, - "Avalanche Fuji": { - "on_ramp": "0x610F76A35E17DA4542518D85FfEa12645eF111Fc", - "deployed_at": 9718676 - }, - "BSC Testnet": { - "on_ramp": "0xE48E6AA1fc7D0411acEA95F8C6CaD972A37721D4", - "deployed_at": 9718302 - }, - "Base Sepolia": { - "on_ramp": "0x41b4A51cAfb699D9504E89d19D71F92E886028a8", - "deployed_at": 9718513 - }, - "Optimism Sepolia": { - "on_ramp": "0xAae733212981e06D9C978Eb5148F8af03F54b6EF", - "deployed_at": 9718420 - }, - "Polygon Amoy": { - "on_ramp": "0x01800fCDd892e37f7829937271840A6F041bE62E", - "deployed_at": 9718194 - }, - "Sepolia Testnet": { - "on_ramp": "0x4ac7FBEc2A7298AbDf0E0F4fDC45015836C4bAFe", - "deployed_at": 8487681 - } - }, - "dest_contracts": { - "Arbitrum Sepolia": { - "off_ramp": "0x9aA82DBB53bf02096B771D40e9432A323a78fB26", - "commit_store": "0x5CdbA91aBC0cD81FC56bc10Ad1835C9E5fB38e5F", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Avalanche Fuji": { - "off_ramp": "0x3e33290B90fD0FF30a3FA138934DF028E4eCA348", - "commit_store": "0xCFe3556Aa42d40be09BD23aa80448a19443BE5B1", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "BSC Testnet": { - "off_ramp": "0xbc4AD54e91b213D4279af92c0C5518c0b96cf62D", - "commit_store": "0xff84e8Dd4Fd17eaBb23b6AeA6e1981830e54389C", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Base Sepolia": { - "off_ramp": "0x4117953A5ceeF12f5B8C1E973b470ab83a8CebA6", - "commit_store": "0x94ad41296186E81f31e1ed0B1BcF5fa9e1721C27", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Optimism Sepolia": { - "off_ramp": "0x33d2898F8fb7714FD1661791766f40754982a343", - "commit_store": "0x55d6Df194472f02CD481e506A277c4A29D0D1bCc", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Polygon Amoy": { - "off_ramp": "0x450543b1d85ca79885851D7b74dc982981b78229", - "commit_store": "0x23B79d940A769FE31b4C867A8BAE80117f24Ca81", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Sepolia Testnet": { - "off_ramp": "0xbf9036529123DE264bFA0FC7362fE25B650D4B16", - "commit_store": "0x5f7F1abD5c5EdaF2636D58B980e85355AF0Ef80d", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - } - } - }, - "Kroma Sepolia": { - "is_native_fee_token": true, - "fee_token": "0xa75cCA5b404ec6F4BB6EC4853D177FE7057085c8", - "bridge_tokens": [ - ], - "bridge_tokens_pools": [ - ], - "price_aggregators": null, - "arm": "0x1E4e4e0d6f6631A45C616F71a1A5cF208DB9eCDe", - "router": "0xA8C0c11bf64AF62CDCA6f93D3769B88BdD7cb93D", - "price_registry": "0xa1ed3A3aA29166C9c8448654A8cA6b7916BC8379", - "wrapped_native": "0x4200000000000000000000000000000000000001", - "src_contracts": { - "WeMix Testnet": { - "on_ramp": "0x6ea155Fc77566D9dcE01B8aa5D7968665dc4f0C5", - "deployed_at": 10290904 - } - }, - "dest_contracts": { - "WeMix Testnet": { - "off_ramp": "0xB602B6E5Caf08ac0C920EAE585aed100a8cF6f3B", - "commit_store": "0x89D5b13908b9063abCC6791dc724bF7B7c93634C", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" } } }, "Optimism Sepolia": { "is_native_fee_token": true, - "fee_token": "0xE4aB69C077896252FAFBD49EFD26B5D171A32410", - "bridge_tokens": [ - ], - "bridge_tokens_pools": [ - ], - "price_aggregators": null, - "arm": "0xf06Ff5D2084295909119ca541E93635E7D582FFc", + "fee_token": "0x4200000000000000000000000000000000000006", + "arm": "0xF51366F72184E22cF4a7a8362508DB0d3370392d", "router": "0x114A20A10b43D4115e5aeef7345a1A71d2a60C57", "price_registry": "0x782a7Ba95215f2F7c3dD4C153cbB2Ae3Ec2d3215", "wrapped_native": "0x4200000000000000000000000000000000000006", "src_contracts": { - "Arbitrum Sepolia": { - "on_ramp": "0x1a86b29364D1B3fA3386329A361aA98A104b2742", - "deployed_at": 10841494 - }, "Avalanche Fuji": { "on_ramp": "0x6b38CC6Fa938D5AB09Bdf0CFe580E226fDD793cE", - "deployed_at": 8677537 + "deployed_at": 0 }, "Base Sepolia": { "on_ramp": "0xe284D2315a28c4d62C419e8474dC457b219DB969", - "deployed_at": 7130524 - }, - "Gnosis Chiado": { - "on_ramp": "0x835a5b8e6CA17c2bB5A336c93a4E22478E6F1C8A", - "deployed_at": 11799783 - }, - "Polygon Amoy": { - "on_ramp": "0x2Cf26fb01E9ccDb831414B766287c0A9e4551089", - "deployed_at": 10813146 + "deployed_at": 0 }, "Sepolia Testnet": { "on_ramp": "0xC8b93b46BF682c39B3F65Aa1c135bC8A95A5E43a", - "deployed_at": 12165583 - }, - "WeMix Testnet": { - "on_ramp": "0xc7E53f6aB982af7A7C3e470c8cCa283d3399BDAd", - "deployed_at": 8733017 + "deployed_at": 0 } }, "dest_contracts": { - "Arbitrum Sepolia": { - "off_ramp": "0xDc2c7A3d8068C6F09F0F3648d24C84e372F6014d", - "commit_store": "0xb1aFb5cbE3c29b5Db71F21442BA9EfD450BC23C3", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, "Avalanche Fuji": { "off_ramp": "0x1F350718e015EB20E5065C09F4A7a3f66888aEeD", "commit_store": "0x98650A8EB59f75D93563aB34FcF603b1A30e4CBF", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Base Sepolia": { "off_ramp": "0x0a750ca77369e03613d7640548F4b2b1c695c3Bb", "commit_store": "0x8fEBC74C26129C8d7E60288C6dCCc75eb494aA3C", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Gnosis Chiado": { - "off_ramp": "0xCE2CE7F940B7c839384e5D7e079A6aE80e8AD6dB", - "commit_store": "0x1b9D78Ec1CEEC439F0b7eA6C428A1a607D9FA7e4", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Polygon Amoy": { - "off_ramp": "0xD667b5706592D0b040C78fEe5EE17D243b7dCB41", - "commit_store": "0x96101BA5250EE9295c193693C1e08A55bC593664", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Sepolia Testnet": { "off_ramp": "0x260AF9b83e0d2Bb6C9015fC9f0BfF8858A0CCE68", "commit_store": "0x7a0bB92Bc8663abe6296d0162A9b41a2Cb2E0358", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "WeMix Testnet": { - "off_ramp": "0x9C08B7712af0344188aa5087D9e6aD0f47191037", - "commit_store": "0x4BE6DB0B884169a6A207fe5cad01eB4C025a13dB", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - } - } - }, - "Polygon Amoy": { - "is_native_fee_token": true, - "fee_token": "0x0Fd9e8d3aF1aaee056EB9e802c3A762a667b1904", - "bridge_tokens": [ - ], - "bridge_tokens_pools": [ - ], - "price_aggregators": null, - "arm": "0x50b023c5b33AEe5Adef15C2E95C2fEC690a52fa1", - "router": "0x9C32fCB86BF0f4a1A8921a9Fe46de3198bb884B2", - "price_registry": "0xfb2f2A207dC428da81fbAFfDDe121761f8Be1194", - "wrapped_native": "0x360ad4f9a9A8EFe9A8DCB5f461c4Cc1047E1Dcf9", - "src_contracts": { - "Avalanche Fuji": { - "on_ramp": "0x8Fb98b3837578aceEA32b454f3221FE18D7Ce903", - "deployed_at": 6004551 - }, - "BSC Testnet": { - "on_ramp": "0xC6683ac4a0F62803Bec89a5355B36495ddF2C38b", - "deployed_at": 6005330 - }, - "Gnosis Chiado": { - "on_ramp": "0x2331F6D614C9Fd613Ff59a1aB727f1EDf6c37A68", - "deployed_at": 6897885 - }, - "Optimism Sepolia": { - "on_ramp": "0xA52cDAeb43803A80B3c0C2296f5cFe57e695BE11", - "deployed_at": 6004902 - }, - "Sepolia Testnet": { - "on_ramp": "0x35347A2fC1f2a4c5Eae03339040d0b83b09e6FDA", - "deployed_at": 6004056 - }, - "WeMix Testnet": { - "on_ramp": "0x26546096F64B5eF9A1DcDAe70Df6F4f8c2E10C61", - "deployed_at": 6005611 - } - }, - "dest_contracts": { - "Avalanche Fuji": { - "off_ramp": "0xa733ce82a84335b2E9D864312225B0F3D5d80600", - "commit_store": "0x09B0F93fC2111aE439e853884173AC5b2F809885", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "BSC Testnet": { - "off_ramp": "0x948dfaa4842fc23e0e362Fe8D4396AaE4E6DF7EA", - "commit_store": "0x7F4e739D40E58BBd59dAD388171d18e37B26326f", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Gnosis Chiado": { - "off_ramp": "0x17c542a28e08AEF5697251601C7b2B621d153D42", - "commit_store": "0x811250c20fAB9a1b7ca245453aC214ba637fBEB5", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Optimism Sepolia": { - "off_ramp": "0xfFdE9E8c34A27BEBeaCcAcB7b3044A0A364455C9", - "commit_store": "0x74ED442ad211050e9C05Dc9A267E037E3d74A03B", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Sepolia Testnet": { - "off_ramp": "0xFb04129aD1EEDB741CC705ebC1978a7aB63e51f6", - "commit_store": "0x63f875240149d29136053C954Ca164a9BfA81F77", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "WeMix Testnet": { - "off_ramp": "0xdE8451E952Eb43350614839cCAA84f7C8701a09C", - "commit_store": "0xaCdaBa07ECad81dc634458b98673931DD9d3Bc14", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" } } }, "Sepolia Testnet": { "is_native_fee_token": true, - "fee_token": "0x779877A7B0D9E8603169DdbD7836e478b4624789", - "bridge_tokens": [ - ], - "bridge_tokens_pools": [ - ], - "price_aggregators": null, - "arm": "0xB4d360459F32Dd641Ef5A6985fFbAC5c4e5521aA", + "fee_token": "0x097D90c9d3E0B50Ca60e1ae45F6A81010f9FB534", + "arm": "0x27Da8735d8d1402cEc072C234759fbbB4dABBC4A", "router": "0x0BF3dE8c5D3e8A2B34D2BEeB17ABfCeBaf363A59", "price_registry": "0x9EF7D57a4ea30b9e37794E55b0C75F2A70275dCc", "wrapped_native": "0x097D90c9d3E0B50Ca60e1ae45F6A81010f9FB534", "src_contracts": { - "Arbitrum Sepolia": { - "on_ramp": "0xe4Dd3B16E09c016402585a8aDFdB4A18f772a07e", - "deployed_at": 5737506 - }, "Avalanche Fuji": { "on_ramp": "0x0477cA0a35eE05D3f9f424d88bC0977ceCf339D4", - "deployed_at": 5944649 - }, - "BSC Testnet": { - "on_ramp": "0xD990f8aFA5BCB02f95eEd88ecB7C68f5998bD618", - "deployed_at": 5383500 + "deployed_at": 0 }, "Base Sepolia": { "on_ramp": "0x2B70a05320cB069e0fB55084D402343F832556E7", - "deployed_at": 5619657 - }, - "Gnosis Chiado": { - "on_ramp": "0x3E842E3A79A00AFdd03B52390B1caC6306Ea257E", - "deployed_at": 5386355 + "deployed_at": 0 }, "Optimism Sepolia": { "on_ramp": "0x69CaB5A0a08a12BaFD8f5B195989D709E396Ed4d", - "deployed_at": 5937506 - }, - "Polygon Amoy": { - "on_ramp": "0x9f656e0361Fb5Df2ac446102c8aB31855B591692", - "deployed_at": 5723315 - }, - "WeMix Testnet": { - "on_ramp": "0xedFc22336Eb0B9B11Ff37C07777db27BCcDe3C65", - "deployed_at": 5393931 - }, - "celo-testnet-alfajores": { - "on_ramp": "0x3C86d16F52C10B2ff6696a0e1b8E0BcfCC085948", - "deployed_at": 5704643 - }, - "ethereum-testnet-sepolia-blast-1": { - "on_ramp": "0xDB75E9D9ca7577CcBd7232741be954cf26194a66", - "deployed_at": 6040848 - }, - "ethereum-testnet-sepolia-metis-1": { - "on_ramp": "0x1C4640914cd57c5f02a68048A0fbb0E12d904223", - "deployed_at": 6002793 - }, - "ethereum-testnet-sepolia-mode-1": { - "on_ramp": "0xc630fbD4D0F6AEB00aD0793FB827b54fBB78e981", - "deployed_at": 5970819 + "deployed_at": 0 } }, "dest_contracts": { - "Arbitrum Sepolia": { - "off_ramp": "0xF18896AB20a09A29e64fdEbA99FDb8EC328f43b1", - "commit_store": "0x93Ff9Dd39Dc01eac1fc4d2c9211D95Ee458CAB94", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, "Avalanche Fuji": { "off_ramp": "0x000b26f604eAadC3D874a4404bde6D64a97d95ca", "commit_store": "0x2dD9273F8208B8393350508131270A6574A69784", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "BSC Testnet": { - "off_ramp": "0xdE2d8E126e08d675fCD7fFa5a6CE49925f3Dc692", - "commit_store": "0x0050ac355a82caB31194507f94174297bf0655A7", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Base Sepolia": { "off_ramp": "0x31c0B81832B333419f0DfD36A69F502cF9094aed", "commit_store": "0xDFcde9d698a2B32DB2537DC9B752Cadd1D846a52", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Gnosis Chiado": { - "off_ramp": "0x7db0115A0b3AAb01d30bf81123c5DD7B0C41Add5", - "commit_store": "0x6640723Ea801178c4383FA016b9781e7ef1016EF", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" }, "Optimism Sepolia": { "off_ramp": "0xD50590D4438411EDe47029b0FD7901A7145E5Df6", "commit_store": "0xe85EEE9Fd434A7b8a586Ee086E828abF41839479", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Polygon Amoy": { - "off_ramp": "0x5032cbC0C4aEeD25bb6E45D8B3fAF05DB0688C5d", - "commit_store": "0xe6201C9996Cc7B6E828E10CbE937E693d577D318", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "WeMix Testnet": { - "off_ramp": "0x46b639a3C1a4CBfD326b94a2dB7415c27157282f", - "commit_store": "0x7b74554678816b045c1e7409327E086bD436aa46", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "celo-testnet-alfajores": { - "off_ramp": "0xB435E0f73c18C5a12C324CA1d02F81F2C3e6e761", - "commit_store": "0xbc5d74957F171e75F92c8F0E1C317A25a56a416D", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "ethereum-testnet-sepolia-blast-1": { - "off_ramp": "0x4e897e5cF3aC307F0541B2151A88bCD781c153a3", - "commit_store": "0xB656652841F347178e193951C4663652aCe36B74", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "ethereum-testnet-sepolia-metis-1": { - "off_ramp": "0x4DB693A93E9d5196ECD42EC56CDEAe99dFC652ED", - "commit_store": "0xBfACd78F1412B6f93Ac23409bf456aFec1ABd845", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "ethereum-testnet-sepolia-mode-1": { - "off_ramp": "0xbEfd8D65F6643De54F0b1268A3bf4618ff85dcB4", - "commit_store": "0x0C161D3470b45Cc677661654C30ce4AdE6aCD288", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - } - } - }, - "WeMix Testnet": { - "is_native_fee_token": true, - "fee_token": "0x3580c7A817cCD41f7e02143BFa411D4EeAE78093", - "bridge_tokens": [ - ], - "bridge_tokens_pools": [ - ], - "price_aggregators": null, - "arm": "0x46fF31494651593973D9b38a872ED5B06f45A693", - "router": "0xA8C0c11bf64AF62CDCA6f93D3769B88BdD7cb93D", - "price_registry": "0x89D17571DB7C9540eeB36760E3c749C8fb984569", - "wrapped_native": "0xbE3686643c05f00eC46e73da594c78098F7a9Ae7", - "src_contracts": { - "Arbitrum Sepolia": { - "on_ramp": "0xA9DE3F7A617D67bC50c56baaCb9E0373C15EbfC6", - "deployed_at": 51216113 - }, - "Avalanche Fuji": { - "on_ramp": "0xC4aC84da458ba8e40210D2dF94C76E9a41f70069", - "deployed_at": 51214769 - }, - "BSC Testnet": { - "on_ramp": "0x5AD6eed6Be0ffaDCA4105050CF0E584D87E0c2F1", - "deployed_at": 51213771 - }, - "Kroma Sepolia": { - "on_ramp": "0x428C4dc89b6Bf908B82d77C9CBceA786ea8cc7D0", - "deployed_at": 51239062 - }, - "Optimism Sepolia": { - "on_ramp": "0x1961a7De751451F410391c251D4D4F98D71B767D", - "deployed_at": 51216748 - }, - "Polygon Amoy": { - "on_ramp": "0xd55148e841e76265B484d399eC71b7076ecB1216", - "deployed_at": 55378685 - }, - "Sepolia Testnet": { - "on_ramp": "0x4d57C6d8037C65fa66D6231844785a428310a735", - "deployed_at": 51239309 - } - }, - "dest_contracts": { - "Arbitrum Sepolia": { - "off_ramp": "0xeB1dFaB2464Bf0574D43e764E0c758f92e7ecAFb", - "commit_store": "0xcEaCa2B7890065c485f3E58657358a185Ad33791", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Avalanche Fuji": { - "off_ramp": "0x98e811Df9D2512f1aaf58D534607F583D6c54A4F", - "commit_store": "0x8e538351F6E5B2daF3c90C565C3738bca69a2716", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "BSC Testnet": { - "off_ramp": "0xB0e7f0fCcD3c961C473E7c44D939C1cDb4Cec1cB", - "commit_store": "0x4B56D8d53f1A6e0117B09700067De99581aA5542", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Kroma Sepolia": { - "off_ramp": "0xD685D2d224dd6D0Db2D56497db6270D77D9a7966", - "commit_store": "0x7e062D6880779a0347e7742058C1b1Ee4AA0B137", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Optimism Sepolia": { - "off_ramp": "0xA5f97Bc69Bf06e7C37B93265c5457420A92c5F4b", - "commit_store": "0xd48b9213583074f518D8f4336FDf35370D450132", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Polygon Amoy": { - "off_ramp": "0x6c8f5999B06FDE17B11E4e3C1062b761766F960f", - "commit_store": "0x957c3c2056192e58A8485eF31165fC490d474239", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Sepolia Testnet": { - "off_ramp": "0x8AB103843ED9D28D2C5DAf5FdB9c3e1CE2B6c876", - "commit_store": "0x7d5297c5506ee2A7Ef121Da9bE02b6a6AD30b392", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - } - } - }, - "celo-testnet-alfajores": { - "is_native_fee_token": true, - "fee_token": "0x32E08557B14FaD8908025619797221281D439071", - "bridge_tokens": [ - ], - "bridge_tokens_pools": [ - ], - "price_aggregators": null, - "arm": "0xbE8FD4b84ca8CC2cFAeeEf8dc1388E44860eeEeb", - "router": "0xb00E95b773528E2Ea724DB06B75113F239D15Dca", - "price_registry": "0x8F048206D11B2c69b8963E2EBd5968D141e022f4", - "wrapped_native": "0x99604d0e2EfE7ABFb58BdE565b5330Bb46Ab3Dca", - "src_contracts": { - "Sepolia Testnet": { - "on_ramp": "0x16a020c4bbdE363FaB8481262D30516AdbcfcFc8", - "deployed_at": 23561364 - } - }, - "dest_contracts": { - "Sepolia Testnet": { - "off_ramp": "0xa1b97F92D806BA040daf419AFC2765DC723683a4", - "commit_store": "0xcd92C0599Ac515e7588865cC45Eee21A74816aFc", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - } - } - }, - "ethereum-testnet-sepolia-blast-1": { - "is_native_fee_token": true, - "fee_token": "0x02c359ebf98fc8BF793F970F9B8302bb373BdF32", - "bridge_tokens": [ - ], - "bridge_tokens_pools": [ - ], - "price_aggregators": null, - "arm": "0x9C32fCB86BF0f4a1A8921a9Fe46de3198bb884B2", - "router": "0xfb2f2A207dC428da81fbAFfDDe121761f8Be1194", - "price_registry": "0xc8acE9dF450FaD007755C6C9AB4f0e9c8626E29C", - "wrapped_native": "0x4200000000000000000000000000000000000023", - "src_contracts": { - "Sepolia Testnet": { - "on_ramp": "0x85Ef19FC4C63c70744995DC38CAAEC185E0c619f", - "deployed_at": 6429339 - } - }, - "dest_contracts": { - "Sepolia Testnet": { - "off_ramp": "0x92cD24C278D34C726f377703E50875d8f9535dC2", - "commit_store": "0xcE1b4D50CeD56850182Bd58Ace91171cB249B873", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - } - } - }, - "ethereum-testnet-sepolia-metis-1": { - "is_native_fee_token": true, - "fee_token": "0x9870D6a0e05F867EAAe696e106741843F7fD116D", - "bridge_tokens": [ - ], - "bridge_tokens_pools": [ - ], - "price_aggregators": null, - "arm": "0x26546096F64B5eF9A1DcDAe70Df6F4f8c2E10C61", - "router": "0xaCdaBa07ECad81dc634458b98673931DD9d3Bc14", - "price_registry": "0x5DCE866b3ae6E0Ed153f0e149D7203A1B266cdF5", - "wrapped_native": "0x5c48e07062aC4E2Cf4b9A768a711Aef18e8fbdA0", - "src_contracts": { - "Sepolia Testnet": { - "on_ramp": "0x2Eff2d1BF5C557d6289D208a7a43608f5E3FeCc2", - "deployed_at": 858864 - } - }, - "dest_contracts": { - "Sepolia Testnet": { - "off_ramp": "0x9Bb7e398ef9Acfe9cA584C39B1E233Cba62BB9f7", - "commit_store": "0x1F4B82cDebaC5e3a0Dd53183D47e51808B4a64cB", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - } - } - }, - "ethereum-testnet-sepolia-mode-1": { - "is_native_fee_token": true, - "fee_token": "0x925a4bfE64AE2bFAC8a02b35F78e60C29743755d", - "bridge_tokens": [ - ], - "bridge_tokens_pools": [ - ], - "price_aggregators": null, - "arm": "0x11545812A8d64e4A3A0Ec36b6F70D87b42Ce4a01", - "router": "0xc49ec0eB4beb48B8Da4cceC51AA9A5bD0D0A4c43", - "price_registry": "0xa733ce82a84335b2E9D864312225B0F3D5d80600", - "wrapped_native": "0x4200000000000000000000000000000000000006", - "src_contracts": { - "Base Sepolia": { - "on_ramp": "0x73f7E074bd7291706a0C5412f51DB46441B1aDCB", - "deployed_at": 14359909 - }, - "Sepolia Testnet": { - "on_ramp": "0xfFdE9E8c34A27BEBeaCcAcB7b3044A0A364455C9", - "deployed_at": 14359680 - } - }, - "dest_contracts": { - "Base Sepolia": { - "off_ramp": "0x137a38c6b1Ad20101F93516aB2159Df525309168", - "commit_store": "0x8F43d867969F14619895d71E0A5b89E0bb20bF70", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Sepolia Testnet": { - "off_ramp": "0xcD44cec849B6a8eBd5551D6DFeEcA452257Dfe4d", - "commit_store": "0xbA66f08733E6715D33edDfb5a5947676bb45d0e0", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" } } } From 95ffd86c84773069654251ee17999eff5fa13e5f Mon Sep 17 00:00:00 2001 From: Anindita Ghosh <88458927+AnieeG@users.noreply.github.com> Date: Thu, 5 Sep 2024 12:55:00 -0700 Subject: [PATCH 076/115] CCIP-3007 : Add script for zksync compile contract (#1276) --- contracts/.gitignore | 2 + contracts/hardhat.ccip.zksync.config.ts | 116 ++ contracts/package.json | 5 + contracts/pnpm-lock.yaml | 1095 ++++++++++++----- contracts/scripts/zksyncverify/README.md | 35 + contracts/scripts/zksyncverify/main.go | 100 ++ .../scripts/zksyncverify/zksync-verify.ts | 28 + go.mod | 1 + 8 files changed, 1086 insertions(+), 296 deletions(-) create mode 100644 contracts/hardhat.ccip.zksync.config.ts create mode 100644 contracts/scripts/zksyncverify/README.md create mode 100644 contracts/scripts/zksyncverify/main.go create mode 100644 contracts/scripts/zksyncverify/zksync-verify.ts diff --git a/contracts/.gitignore b/contracts/.gitignore index ddfd43837d..b5e053e940 100644 --- a/contracts/.gitignore +++ b/contracts/.gitignore @@ -11,5 +11,7 @@ typechain # Foundry foundry-cache foundry-artifacts +artifacts-zk +cache-zk .openzeppelin \ No newline at end of file diff --git a/contracts/hardhat.ccip.zksync.config.ts b/contracts/hardhat.ccip.zksync.config.ts new file mode 100644 index 0000000000..b8f2e1d154 --- /dev/null +++ b/contracts/hardhat.ccip.zksync.config.ts @@ -0,0 +1,116 @@ +import '@nomicfoundation/hardhat-ethers' +import '@nomicfoundation/hardhat-verify' +import '@nomicfoundation/hardhat-chai-matchers' +import '@matterlabs/hardhat-zksync-solc' +import '@typechain/hardhat' +import 'hardhat-abi-exporter' +import { subtask } from 'hardhat/config' +import { TASK_COMPILE_SOLIDITY_GET_SOURCE_PATHS } from 'hardhat/builtin-tasks/task-names' +import '@matterlabs/hardhat-zksync-verify' + +const COMPILER_SETTINGS = { + optimizer: { + enabled: true, + runs: 1000000, + }, + metadata: { + bytecodeHash: 'none', + }, +} + +// prune forge style tests from hardhat paths +subtask(TASK_COMPILE_SOLIDITY_GET_SOURCE_PATHS).setAction( + async (_, __, runSuper) => { + const paths = await runSuper() + const noTests = paths.filter((p: string) => !p.endsWith('.t.sol')) + const noCCIPTests = noTests.filter( + (p: string) => !p.includes('/v0.8/ccip/test'), + ) + return noCCIPTests.filter( + (p: string) => !p.includes('src/v0.8/vendor/forge-std'), + ) + }, +) + +/** + * @type import('hardhat/config').HardhatUserConfig + */ +let config = { + abiExporter: { + path: './abi', + runOnCompile: true, + }, + paths: { + artifacts: './artifacts', + cache: './cache', + sources: './src/v0.8/ccip', + tests: './test/v0.8/ccip, ./src/v0.8/ccip/test', + }, + typechain: { + outDir: './typechain', + target: 'ethers-v5', + }, + defaultNetwork: 'zkSync', + networks: { + env: { + url: process.env.NODE_HTTP_URL || '', + }, + hardhat: { + allowUnlimitedContractSize: Boolean( + process.env.ALLOW_UNLIMITED_CONTRACT_SIZE, + ), + hardfork: 'merge', + }, + zkSyncSepolia: { + url: 'https://sepolia.era.zksync.dev', + ethNetwork: 'sepolia', + zksync: true, // enables zksolc compiler + verifyURL: + 'https://explorer.sepolia.era.zksync.dev/contract_verification', + }, + zkSync: { + url: 'https://mainnet.era.zksync.io', // The testnet RPC URL of ZKsync Era network. + ethNetwork: 'mainnet', // The Ethereum Web3 RPC URL, or the identifier of the network (e.g. `mainnet` or `sepolia`) + zksync: true, + // Verification endpoint for Sepolia + verifyURL: + 'https://zksync2-mainnet-explorer.zksync.io/contract_verification', + }, + }, + solidity: { + compilers: [ + { + version: '0.8.24', + settings: { + ...COMPILER_SETTINGS, + evmVersion: 'paris', + }, + }, + ], + }, + zksolc: { + settings: { + compilerPath: 'zksolc', + version: 'v1.5.3', + optimizer: { + enabled: true, + mode: '3', + fallback_to_optimizing_for_size: false, + }, + experimental: { + dockerImage: '', + tag: '', + }, + // contractsToCompile: ['RMN', 'ARMProxy'], // uncomment this to compile only specific contracts + }, + }, + warnings: !process.env.HIDE_WARNINGS, +} + +if (process.env.NETWORK_NAME && process.env.EXPLORER_API_KEY) { + config = { + ...config, + } +} + +export default config diff --git a/contracts/package.json b/contracts/package.json index b173fc8603..8afd81e3a4 100644 --- a/contracts/package.json +++ b/contracts/package.json @@ -14,6 +14,9 @@ "clean": "hardhat clean", "compile:native": "./scripts/native_solc_compile_all", "compile": "hardhat compile --no-typechain", + "zksync:compile": "npx hardhat compile --config ./hardhat.ccip.zksync.config.ts --no-typechain", + "zksync:verify:sepolia": "npx hardhat run scripts/zksyncverify/zksync-verify.ts --network zkSyncSepolia --config ./hardhat.ccip.zksync.config.ts", + "zksync:verify": "npx hardhat run scripts/zksyncverify/zksync-verify.ts --network zkSync --config ./hardhat.ccip.zksync.config.ts", "coverage": "hardhat coverage", "prepare": "chmod +x .husky/prepare.sh && ./.husky/prepare.sh", "prepublishOnly": "pnpm compile && ./scripts/prepublish_generate_abi_folder", @@ -77,6 +80,7 @@ "@ethersproject/bignumber": "~5.7.0", "@ethersproject/contracts": "~5.7.0", "@ethersproject/providers": "~5.7.2", + "@matterlabs/hardhat-zksync-solc": "^1.2.1", "@nomicfoundation/hardhat-chai-matchers": "^1.0.6", "@nomicfoundation/hardhat-ethers": "^3.0.6", "@nomicfoundation/hardhat-network-helpers": "^1.0.11", @@ -121,6 +125,7 @@ "@changesets/changelog-github": "^0.5.0", "@changesets/cli": "~2.27.7", "@eth-optimism/contracts": "0.6.0", + "@matterlabs/hardhat-zksync-verify": "^1.6.0", "@openzeppelin/contracts": "4.9.3", "@openzeppelin/contracts-upgradeable": "4.9.3", "@scroll-tech/contracts": "0.1.0", diff --git a/contracts/pnpm-lock.yaml b/contracts/pnpm-lock.yaml index 6731f62ae7..225a0ec34c 100644 --- a/contracts/pnpm-lock.yaml +++ b/contracts/pnpm-lock.yaml @@ -22,10 +22,13 @@ importers: version: 0.5.0 '@changesets/cli': specifier: ~2.27.7 - version: 2.27.7 + version: 2.27.8 '@eth-optimism/contracts': specifier: 0.6.0 version: 0.6.0(ethers@5.7.2) + '@matterlabs/hardhat-zksync-verify': + specifier: ^1.6.0 + version: 1.6.0(@nomicfoundation/hardhat-verify@2.0.10(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.16.4)(typescript@5.5.4))(typescript@5.5.4)))(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.16.4)(typescript@5.5.4))(typescript@5.5.4)) '@openzeppelin/contracts': specifier: 4.9.3 version: 4.9.3 @@ -54,30 +57,33 @@ importers: '@ethersproject/providers': specifier: ~5.7.2 version: 5.7.2 + '@matterlabs/hardhat-zksync-solc': + specifier: ^1.2.1 + version: 1.2.3(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.16.4)(typescript@5.5.4))(typescript@5.5.4)) '@nomicfoundation/hardhat-chai-matchers': specifier: ^1.0.6 - version: 1.0.6(@nomiclabs/hardhat-ethers@2.2.3(ethers@5.7.2)(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.14.15)(typescript@5.5.4))(typescript@5.5.4)))(chai@4.5.0)(ethers@5.7.2)(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.14.15)(typescript@5.5.4))(typescript@5.5.4)) + version: 1.0.6(@nomiclabs/hardhat-ethers@2.2.3(ethers@5.7.2)(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.16.4)(typescript@5.5.4))(typescript@5.5.4)))(chai@4.5.0)(ethers@5.7.2)(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.16.4)(typescript@5.5.4))(typescript@5.5.4)) '@nomicfoundation/hardhat-ethers': specifier: ^3.0.6 - version: 3.0.6(ethers@5.7.2)(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.14.15)(typescript@5.5.4))(typescript@5.5.4)) + version: 3.0.6(ethers@5.7.2)(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.16.4)(typescript@5.5.4))(typescript@5.5.4)) '@nomicfoundation/hardhat-network-helpers': specifier: ^1.0.11 - version: 1.0.11(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.14.15)(typescript@5.5.4))(typescript@5.5.4)) + version: 1.0.11(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.16.4)(typescript@5.5.4))(typescript@5.5.4)) '@nomicfoundation/hardhat-verify': specifier: ^2.0.9 - version: 2.0.9(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.14.15)(typescript@5.5.4))(typescript@5.5.4)) + version: 2.0.10(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.16.4)(typescript@5.5.4))(typescript@5.5.4)) '@typechain/ethers-v5': specifier: ^7.2.0 version: 7.2.0(@ethersproject/abi@5.7.0)(@ethersproject/bytes@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.2(typescript@5.5.4))(typescript@5.5.4) '@typechain/hardhat': specifier: ^7.0.0 - version: 7.0.0(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(@typechain/ethers-v5@7.2.0(@ethersproject/abi@5.7.0)(@ethersproject/bytes@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.2(typescript@5.5.4))(typescript@5.5.4))(ethers@5.7.2)(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.14.15)(typescript@5.5.4))(typescript@5.5.4))(typechain@8.3.2(typescript@5.5.4)) + version: 7.0.0(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(@typechain/ethers-v5@7.2.0(@ethersproject/abi@5.7.0)(@ethersproject/bytes@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.2(typescript@5.5.4))(typescript@5.5.4))(ethers@5.7.2)(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.16.4)(typescript@5.5.4))(typescript@5.5.4))(typechain@8.3.2(typescript@5.5.4)) '@types/cbor': specifier: ~5.0.1 version: 5.0.1 '@types/chai': specifier: ^4.3.17 - version: 4.3.17 + version: 4.3.19 '@types/debug': specifier: ^4.1.12 version: 4.1.12 @@ -89,7 +95,7 @@ importers: version: 10.0.7 '@types/node': specifier: ^20.14.15 - version: 20.14.15 + version: 20.16.4 '@typescript-eslint/eslint-plugin': specifier: ^7.18.0 version: 7.18.0(@typescript-eslint/parser@7.18.0(eslint@8.57.0)(typescript@5.5.4))(eslint@8.57.0)(typescript@5.5.4) @@ -125,19 +131,19 @@ importers: version: 5.7.2 hardhat: specifier: ~2.20.1 - version: 2.20.1(ts-node@10.9.2(@types/node@20.14.15)(typescript@5.5.4))(typescript@5.5.4) + version: 2.20.1(ts-node@10.9.2(@types/node@20.16.4)(typescript@5.5.4))(typescript@5.5.4) hardhat-abi-exporter: specifier: ^2.10.1 - version: 2.10.1(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.14.15)(typescript@5.5.4))(typescript@5.5.4)) + version: 2.10.1(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.16.4)(typescript@5.5.4))(typescript@5.5.4)) hardhat-ignore-warnings: specifier: ^0.2.6 version: 0.2.11 husky: specifier: ^9.0.11 - version: 9.1.5 + version: 9.0.11 lint-staged: specifier: ^15.2.2 - version: 15.2.9 + version: 15.2.2 moment: specifier: ^2.30.1 version: 2.30.1 @@ -158,7 +164,7 @@ importers: version: 0.1.0(prettier-plugin-solidity@1.3.1(prettier@3.3.3))(prettier@3.3.3) ts-node: specifier: ^10.9.2 - version: 10.9.2(@types/node@20.14.15)(typescript@5.5.4) + version: 10.9.2(@types/node@20.16.4)(typescript@5.5.4) typechain: specifier: ^8.2.1 version: 8.3.2(typescript@5.5.4) @@ -194,15 +200,18 @@ packages: resolution: {integrity: sha512-Chk32uHMg6TnQdvw2e9IlqPpFX/6NLuK0Ys2PqLb7/gL5uFn9mXvK715FGLlOLQrcO4qIkNHkvPGktzzXexsFw==} engines: {node: '>=6.9.0'} + '@balena/dockerignore@1.0.2': + resolution: {integrity: sha512-wMue2Sy4GAVTk6Ic4tJVcnfdau+gx2EnG7S+uAEe+TWJFqE4YoWN4/H8MSLj4eYJKxGg26lZwboEniNiNwZQ6Q==} + '@chainlink/solhint-plugin-chainlink-solidity@https://codeload.github.com/smartcontractkit/chainlink-solhint-rules/tar.gz/1b4c0c2663fcd983589d4f33a2e73908624ed43c': resolution: {tarball: https://codeload.github.com/smartcontractkit/chainlink-solhint-rules/tar.gz/1b4c0c2663fcd983589d4f33a2e73908624ed43c} version: 1.2.0 - '@changesets/apply-release-plan@7.0.4': - resolution: {integrity: sha512-HLFwhKWayKinWAul0Vj+76jVx1Pc2v55MGPVjZ924Y/ROeSsBMFutv9heHmCUj48lJyRfOTJG5+ar+29FUky/A==} + '@changesets/apply-release-plan@7.0.5': + resolution: {integrity: sha512-1cWCk+ZshEkSVEZrm2fSj1Gz8sYvxgUL4Q78+1ZZqeqfuevPTPk033/yUZ3df8BKMohkqqHfzj0HOOrG0KtXTw==} - '@changesets/assemble-release-plan@6.0.3': - resolution: {integrity: sha512-bLNh9/Lgl1VwkjWZTq8JmRqH+hj7/Yzfz0jsQ/zJJ+FTmVqmqPj3szeKOri8O/hEM8JmHW019vh2gTO9iq5Cuw==} + '@changesets/assemble-release-plan@6.0.4': + resolution: {integrity: sha512-nqICnvmrwWj4w2x0fOhVj2QEGdlUuwVAwESrUo5HLzWMI1rE5SWfsr9ln+rDqWB6RQ2ZyaMZHUcU7/IRaUJS+Q==} '@changesets/changelog-git@0.2.0': resolution: {integrity: sha512-bHOx97iFI4OClIT35Lok3sJAwM31VbUM++gnMBV16fdbtBhgYu4dxsphBF/0AZZsyAHMrnM0yFcj5gZM1py6uQ==} @@ -210,45 +219,45 @@ packages: '@changesets/changelog-github@0.5.0': resolution: {integrity: sha512-zoeq2LJJVcPJcIotHRJEEA2qCqX0AQIeFE+L21L8sRLPVqDhSXY8ZWAt2sohtBpFZkBwu+LUwMSKRr2lMy3LJA==} - '@changesets/cli@2.27.7': - resolution: {integrity: sha512-6lr8JltiiXPIjDeYg4iM2MeePP6VN/JkmqBsVA5XRiy01hGS3y629LtSDvKcycj/w/5Eur1rEwby/MjcYS+e2A==} + '@changesets/cli@2.27.8': + resolution: {integrity: sha512-gZNyh+LdSsI82wBSHLQ3QN5J30P4uHKJ4fXgoGwQxfXwYFTJzDdvIJasZn8rYQtmKhyQuiBj4SSnLuKlxKWq4w==} hasBin: true - '@changesets/config@3.0.2': - resolution: {integrity: sha512-cdEhS4t8woKCX2M8AotcV2BOWnBp09sqICxKapgLHf9m5KdENpWjyrFNMjkLqGJtUys9U+w93OxWT0czorVDfw==} + '@changesets/config@3.0.3': + resolution: {integrity: sha512-vqgQZMyIcuIpw9nqFIpTSNyc/wgm/Lu1zKN5vECy74u95Qx/Wa9g27HdgO4NkVAaq+BGA8wUc/qvbvVNs93n6A==} '@changesets/errors@0.2.0': resolution: {integrity: sha512-6BLOQUscTpZeGljvyQXlWOItQyU71kCdGz7Pi8H8zdw6BI0g3m43iL4xKUVPWtG+qrrL9DTjpdn8eYuCQSRpow==} - '@changesets/get-dependents-graph@2.1.1': - resolution: {integrity: sha512-LRFjjvigBSzfnPU2n/AhFsuWR5DK++1x47aq6qZ8dzYsPtS/I5mNhIGAS68IAxh1xjO9BTtz55FwefhANZ+FCA==} + '@changesets/get-dependents-graph@2.1.2': + resolution: {integrity: sha512-sgcHRkiBY9i4zWYBwlVyAjEM9sAzs4wYVwJUdnbDLnVG3QwAaia1Mk5P8M7kraTOZN+vBET7n8KyB0YXCbFRLQ==} '@changesets/get-github-info@0.6.0': resolution: {integrity: sha512-v/TSnFVXI8vzX9/w3DU2Ol+UlTZcu3m0kXTjTT4KlAdwSvwutcByYwyYn9hwerPWfPkT2JfpoX0KgvCEi8Q/SA==} - '@changesets/get-release-plan@4.0.3': - resolution: {integrity: sha512-6PLgvOIwTSdJPTtpdcr3sLtGatT+Jr22+cQwEBJBy6wP0rjB4yJ9lv583J9fVpn1bfQlBkDa8JxbS2g/n9lIyA==} + '@changesets/get-release-plan@4.0.4': + resolution: {integrity: sha512-SicG/S67JmPTrdcc9Vpu0wSQt7IiuN0dc8iR5VScnnTVPfIaLvKmEGRvIaF0kcn8u5ZqLbormZNTO77bCEvyWw==} '@changesets/get-version-range-type@0.4.0': resolution: {integrity: sha512-hwawtob9DryoGTpixy1D3ZXbGgJu1Rhr+ySH2PvTLHvkZuQ7sRT4oQwMh0hbqZH1weAooedEjRsbrWcGLCeyVQ==} - '@changesets/git@3.0.0': - resolution: {integrity: sha512-vvhnZDHe2eiBNRFHEgMiGd2CT+164dfYyrJDhwwxTVD/OW0FUD6G7+4DIx1dNwkwjHyzisxGAU96q0sVNBns0w==} + '@changesets/git@3.0.1': + resolution: {integrity: sha512-pdgHcYBLCPcLd82aRcuO0kxCDbw/yISlOtkmwmE8Odo1L6hSiZrBOsRl84eYG7DRCab/iHnOkWqExqc4wxk2LQ==} - '@changesets/logger@0.1.0': - resolution: {integrity: sha512-pBrJm4CQm9VqFVwWnSqKEfsS2ESnwqwH+xR7jETxIErZcfd1u2zBSqrHbRHR7xjhSgep9x2PSKFKY//FAshA3g==} + '@changesets/logger@0.1.1': + resolution: {integrity: sha512-OQtR36ZlnuTxKqoW4Sv6x5YIhOmClRd5pWsjZsddYxpWs517R0HkyiefQPIytCVh4ZcC5x9XaG8KTdd5iRQUfg==} '@changesets/parse@0.4.0': resolution: {integrity: sha512-TS/9KG2CdGXS27S+QxbZXgr8uPsP4yNJYb4BC2/NeFUj80Rni3TeD2qwWmabymxmrLo7JEsytXH1FbpKTbvivw==} - '@changesets/pre@2.0.0': - resolution: {integrity: sha512-HLTNYX/A4jZxc+Sq8D1AMBsv+1qD6rmmJtjsCJa/9MSRybdxh0mjbTvE6JYZQ/ZiQ0mMlDOlGPXTm9KLTU3jyw==} + '@changesets/pre@2.0.1': + resolution: {integrity: sha512-vvBJ/If4jKM4tPz9JdY2kGOgWmCowUYOi5Ycv8dyLnEE8FgpYYUo1mgJZxcdtGGP3aG8rAQulGLyyXGSLkIMTQ==} - '@changesets/read@0.6.0': - resolution: {integrity: sha512-ZypqX8+/im1Fm98K4YcZtmLKgjs1kDQ5zHpc2U1qdtNBmZZfo/IBiG162RoP0CUF05tvp2y4IspH11PLnPxuuw==} + '@changesets/read@0.6.1': + resolution: {integrity: sha512-jYMbyXQk3nwP25nRzQQGa1nKLY0KfoOV7VLgwucI0bUO8t8ZLCr6LZmgjXsiKuRDc+5A6doKPr9w2d+FEJ55zQ==} - '@changesets/should-skip-package@0.1.0': - resolution: {integrity: sha512-FxG6Mhjw7yFStlSM7Z0Gmg3RiyQ98d/9VpQAZ3Fzr59dCOM9G6ZdYbjiSAt0XtFr9JR5U2tBaJWPjrkGGc618g==} + '@changesets/should-skip-package@0.1.1': + resolution: {integrity: sha512-H9LjLbF6mMHLtJIc/eHR9Na+MifJ3VxtgP/Y+XLn4BF7tDTEN1HNYtH6QMcjP1uxp9sjaFYmW8xqloaCi/ckTg==} '@changesets/types@4.1.0': resolution: {integrity: sha512-LDQvVDv5Kb50ny2s25Fhm3d9QSZimsoUGBsUioj6MC3qbMUCuC8GPIvk/M6IvXx3lYhAs0lwWUQLb+VIEUCECw==} @@ -256,8 +265,8 @@ packages: '@changesets/types@6.0.0': resolution: {integrity: sha512-b1UkfNulgKoWfqyHtzKS5fOZYSJO+77adgL7DLRDr+/7jhChN+QcHnbjiQVOz/U+Ts3PGNySq7diAItzDgugfQ==} - '@changesets/write@0.3.1': - resolution: {integrity: sha512-SyGtMXzH3qFqlHKcvFY2eX+6b0NGiFcNav8AFsYwy5l8hejOeoeTDemu5Yjmke2V5jpzY+pBvM0vCCQ3gdZpfw==} + '@changesets/write@0.3.2': + resolution: {integrity: sha512-kDxDrPNpUgsjDbWBvUo27PzKX4gqeKOlhibaOXDJA6kuBisGqNHv/HwGJrAu8U/dSf8ZEFIeHIPtvSlZI1kULw==} '@cspotcode/source-map-support@0.8.1': resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} @@ -414,6 +423,17 @@ packages: '@manypkg/get-packages@1.1.3': resolution: {integrity: sha512-fo+QhuU3qE/2TQMQmbVMqaQ6EWbMhi4ABWP+O4AM1NqPBuy0OrApV5LO6BrrgnhtAHS2NH6RrVk9OL181tTi8A==} + '@matterlabs/hardhat-zksync-solc@1.2.3': + resolution: {integrity: sha512-vRvA89DEV49vBcm1/lZVVp+k3OHjuFzhGnzzgwk9zmV9rr4onRDtTShPbu7fP6MdJOTZQ0F3f82rYKsh0ERqNA==} + peerDependencies: + hardhat: ^2.22.5 + + '@matterlabs/hardhat-zksync-verify@1.6.0': + resolution: {integrity: sha512-RsWlQbI23BDXMsxTtvHXpzx1dBotI2p2trvdG+r1uN/KAmMJBOKIqxce2UNXl8skd5Gtysa4GPjXEp4yaf2KrA==} + peerDependencies: + '@nomicfoundation/hardhat-verify': ^2.0.8 + hardhat: ^2.22.5 + '@metamask/eth-sig-util@4.0.1': resolution: {integrity: sha512-tghyZKLHZjcdlDqCA3gNZmLeR0XvOE9U1qoQO9ohyAZT6Pya+H9vkBPcsyXytmYLNgVoin7CKCmweo/R43V+tQ==} engines: {node: '>=12.0.0'} @@ -517,10 +537,10 @@ packages: peerDependencies: hardhat: ^2.9.5 - '@nomicfoundation/hardhat-verify@2.0.9': - resolution: {integrity: sha512-7kD8hu1+zlnX87gC+UN4S0HTKBnIsDfXZ/pproq1gYsK94hgCk+exvzXbwR0X2giiY/RZPkqY9oKRi0Uev91hQ==} + '@nomicfoundation/hardhat-verify@2.0.10': + resolution: {integrity: sha512-3zoTZGQhpeOm6piJDdsGb6euzZAd7N5Tk0zPQvGnfKQ0+AoxKz/7i4if12goi8IDTuUGElAUuZyQB8PMQoXA5g==} peerDependencies: - hardhat: ^2.22.72.0.4 + hardhat: ^2.0.4 '@nomicfoundation/solidity-analyzer-darwin-arm64@0.1.0': resolution: {integrity: sha512-vEF3yKuuzfMHsZecHQcnkUrqm8mnTWfJeEVFHpg+cO+le96xQA4lAJYdUan8pXZohQxv1fSReQsn4QGNuBNuCw==} @@ -586,6 +606,9 @@ packages: resolution: {integrity: sha512-xGWAiVCGOycvGiP/qrlf9f9eOn7fpNbyJygcB0P21a1MDuVPlKt0Srp7rvtBEutYQ48ouYnRXm33zlRnlTOPHg==} engines: {node: '>= 12'} + '@nomiclabs/hardhat-docker@2.0.2': + resolution: {integrity: sha512-XgGEpRT3wlA1VslyB57zyAHV+oll8KnV1TjwnxxC1tpAL04/lbdwpdO5KxInVN8irMSepqFpsiSkqlcnvbE7Ng==} + '@nomiclabs/hardhat-ethers@2.2.3': resolution: {integrity: sha512-YhzPdzb612X591FOe68q+qXVXGG2ANZRvDo0RRUtimev85rCrAlv/TLMEZw5c+kq9AbzocLTVX/h2jVIFPL9Xg==} peerDependencies: @@ -619,8 +642,8 @@ packages: '@openzeppelin/contracts@4.9.3': resolution: {integrity: sha512-He3LieZ1pP2TNt5JbkPA4PNT9WC3gOTOlDcFGJW4Le4QKqwmiNJCRt44APfxMxvq7OugU/cqYuPcSBzOw38DAg==} - '@openzeppelin/upgrades-core@1.34.4': - resolution: {integrity: sha512-iGN3StqYHYVqqSKs8hWY+Gz6VkiEqOkQccBhHl7lHLGBJF91QUZ8wNMZ59SA5Usg1Fstu/HurvZTCEshPJAZ8w==} + '@openzeppelin/upgrades-core@1.32.5': + resolution: {integrity: sha512-R0wprsyJ4xWiRW05kaTfZZkRVpG2g0af3/hpjE7t2mX0Eb2n40MQLokTwqIk4LDzpp910JfLSpB0vBuZ6WNPog==} hasBin: true '@pkgr/core@0.1.1': @@ -688,6 +711,21 @@ packages: resolution: {integrity: sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==} engines: {node: '>=10'} + '@sinonjs/commons@2.0.0': + resolution: {integrity: sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==} + + '@sinonjs/commons@3.0.1': + resolution: {integrity: sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==} + + '@sinonjs/fake-timers@11.3.1': + resolution: {integrity: sha512-EVJO7nW5M/F5Tur0Rf2z/QoMo+1Ia963RiMtapiQrEWvY0iBUvADo8Beegwjpnle5BHkyHuoxSTW3jF43H1XRA==} + + '@sinonjs/samsam@8.0.0': + resolution: {integrity: sha512-Bp8KUVlLp8ibJZrnvq2foVhP0IVX2CIprMJPK0vqGqgrDa0OHVKeZyBykqskkrdxV6yKBPmGasO8LVjAKR3Gew==} + + '@sinonjs/text-encoding@0.7.3': + resolution: {integrity: sha512-DE427ROAphMQzU4ENbliGYrBSYPXF+TtLg9S8vzeA+OF4ZKzoDdzfL8sxuMUGS/lgRhM6j1URSk9ghf7Xo1tyA==} + '@solidity-parser/parser@0.17.0': resolution: {integrity: sha512-Nko8R0/kUo391jsEHHxrGM07QFdnPGvlmox4rmH0kNiNAashItAilhy4Mv4pK5gQmW5f4sXAF58fwJbmlkGcVw==} @@ -751,8 +789,8 @@ packages: '@types/chai-as-promised@7.1.8': resolution: {integrity: sha512-ThlRVIJhr69FLlh6IctTXFkmhtP3NpMZ2QGq69StYLyKZFp/HOp1VdKZj7RvfNWYYcJ1xlbLGLLWj1UvP5u/Gw==} - '@types/chai@4.3.17': - resolution: {integrity: sha512-zmZ21EWzR71B4Sscphjief5djsLre50M6lI622OSySTmn9DB3j+C3kWroHfBQWXbOBwbgg/M8CG/hUxDLIloow==} + '@types/chai@4.3.19': + resolution: {integrity: sha512-2hHHvQBVE2FiSK4eN0Br6snX9MtolHaTo/batnLjlGRhoQzlCL61iVpxoqO7SfFyOw+P/pwv+0zNHzKoGWz9Cw==} '@types/debug@4.1.12': resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==} @@ -778,8 +816,8 @@ packages: '@types/node@12.19.16': resolution: {integrity: sha512-7xHmXm/QJ7cbK2laF+YYD7gb5MggHIIQwqyjin3bpEGiSuvScMQ5JZZXPvRipi1MwckTQbJZROMns/JxdnIL1Q==} - '@types/node@20.14.15': - resolution: {integrity: sha512-Fz1xDMCF/B00/tYSVMlmK7hVeLh7jE5f3B7X1/hmV0MJBwE27KlS7EvD/Yp+z1lm8mVhwV5w+n8jOZG8AfTlKw==} + '@types/node@20.16.4': + resolution: {integrity: sha512-ioyQ1zK9aGEomJ45zz8S8IdzElyxhvP1RVWnPrXDf6wFaUb+kk1tEcVVJkF7RPGM0VWI7cp5U57oCPIn5iN1qg==} '@types/pbkdf2@3.1.0': resolution: {integrity: sha512-Cf63Rv7jCQ0LaL8tNXmEyqTHuIJxRdlS5vMh1mj5voN4+QFhVZnlZruezqpWYDiJ8UTzhP0VmeLXCmBk66YrMQ==} @@ -863,6 +901,10 @@ packages: '@yarnpkg/lockfile@1.1.0': resolution: {integrity: sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==} + JSONStream@1.3.2: + resolution: {integrity: sha512-mn0KSip7N4e0UDPZHnqDsHECo5uGQrixQKnAskOM1BIB8hd7QKbd6il8IPRPudPHOeHiECoCFqhyMaRO9+nWyA==} + hasBin: true + abi-to-sol@0.6.6: resolution: {integrity: sha512-PRn81rSpv6NXFPYQSw7ujruqIP6UkwZ/XoFldtiqCX8+2kHVc73xVaUVvdbro06vvBVZiwnxhEIGdI4BRMwGHw==} hasBin: true @@ -922,9 +964,9 @@ packages: resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} engines: {node: '>=8'} - ansi-escapes@7.0.0: - resolution: {integrity: sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==} - engines: {node: '>=18'} + ansi-escapes@6.2.1: + resolution: {integrity: sha512-4nJ3yixlEthEJ9Rk4vPcdBRkZvQZlYyu8j4/Mqz5sgIkddmEnH2Yj2ZrnP9S3tQOvSNRUIgVNF/1yPpRAGNRig==} + engines: {node: '>=14.16'} ansi-regex@2.1.1: resolution: {integrity: sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==} @@ -998,6 +1040,9 @@ packages: resolution: {integrity: sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==} engines: {node: '>= 0.4'} + asn1@0.2.6: + resolution: {integrity: sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==} + assertion-error@1.1.0: resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} @@ -1008,6 +1053,9 @@ packages: resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} engines: {node: '>=8'} + asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + at-least-node@1.0.0: resolution: {integrity: sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==} engines: {node: '>= 4.0.0'} @@ -1020,12 +1068,21 @@ packages: resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} engines: {node: '>= 0.4'} + axios@1.7.7: + resolution: {integrity: sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==} + balanced-match@1.0.0: resolution: {integrity: sha512-9Y0g0Q8rmSt+H33DfKv7FOc3v+iRI+o1lbzt8jGcIosYW37IIW/2XVYq5NPdmaD5NQ59Nk26Kl/vZbwW9Fr8vg==} base-x@3.0.9: resolution: {integrity: sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==} + base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + + bcrypt-pbkdf@1.0.2: + resolution: {integrity: sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==} + bech32@1.1.4: resolution: {integrity: sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==} @@ -1049,6 +1106,12 @@ packages: resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} engines: {node: '>=8'} + bl@1.2.3: + resolution: {integrity: sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww==} + + bl@4.1.0: + resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} + blakejs@1.2.1: resolution: {integrity: sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ==} @@ -1075,10 +1138,6 @@ packages: resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} engines: {node: '>=8'} - braces@3.0.3: - resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} - engines: {node: '>=8'} - brorand@1.1.0: resolution: {integrity: sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==} @@ -1094,16 +1153,32 @@ packages: bs58check@2.1.2: resolution: {integrity: sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==} + buffer-alloc-unsafe@1.1.0: + resolution: {integrity: sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==} + + buffer-alloc@1.2.0: + resolution: {integrity: sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==} + + buffer-fill@1.0.0: + resolution: {integrity: sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ==} + buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} buffer-xor@1.0.3: resolution: {integrity: sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==} + buffer@5.7.1: + resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} + bufio@1.0.7: resolution: {integrity: sha512-bd1dDQhiC+bEbEfg56IdBv7faWa6OipMs/AFFFvtFnB3wAYjlwQpQRZ0pm6ZkgtfL0pILRXhKxOiQj6UzoMR7A==} engines: {node: '>=8.0.0'} + buildcheck@0.0.6: + resolution: {integrity: sha512-8f9ZJCUXyT1M35Jx7MkBgmBMo3oHTTBIPLiY9xyL0pl3T5RwcPEY8cUHr5LBNfu/fk6c2T4DJZuVM/8ZZT2D2A==} + engines: {node: '>=10.0.0'} + bytes@3.1.2: resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} engines: {node: '>= 0.8'} @@ -1180,6 +1255,9 @@ packages: resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} engines: {node: '>= 8.10.0'} + chownr@1.1.4: + resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==} + ci-info@2.0.0: resolution: {integrity: sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==} @@ -1198,9 +1276,9 @@ packages: resolution: {integrity: sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==} engines: {node: '>=6'} - cli-cursor@5.0.0: - resolution: {integrity: sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==} - engines: {node: '>=18'} + cli-cursor@4.0.0: + resolution: {integrity: sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} cli-truncate@4.0.0: resolution: {integrity: sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==} @@ -1232,6 +1310,10 @@ packages: colorette@2.0.20: resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} + combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + command-exists@1.2.9: resolution: {integrity: sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==} @@ -1247,19 +1329,23 @@ packages: resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==} engines: {node: '>=14'} - commander@12.1.0: - resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==} - engines: {node: '>=18'} + commander@11.1.0: + resolution: {integrity: sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==} + engines: {node: '>=16'} commander@3.0.2: resolution: {integrity: sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow==} - compare-versions@6.1.1: - resolution: {integrity: sha512-4hm4VPpIecmlg59CHXnRDnqGplJFrbLG4aFEl5vl6cK1u76ws3LLvX7ikFnTDl5vo39sjWD6AaDPYodJp/NNHg==} + compare-versions@6.1.0: + resolution: {integrity: sha512-LNZQXhqUvqUTotpZ00qLSaify3b4VFD588aRr8MKFw4CMUr98ytzCW5wDH5qx/DEY5kCDXcbcRuCqL0szEf2tg==} concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + concat-stream@1.6.2: + resolution: {integrity: sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==} + engines: {'0': node >= 0.8} + config-chain@1.1.13: resolution: {integrity: sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==} @@ -1273,10 +1359,17 @@ packages: core-js@3.30.1: resolution: {integrity: sha512-ZNS5nbiSwDTq4hFosEDqm65izl2CWmLz0hARJMyNQBgkUZMIF51cQiMvIQKA6hvuaeWxQDP3hEedM1JZIgTldQ==} + core-util-is@1.0.3: + resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} + cosmiconfig@8.2.0: resolution: {integrity: sha512-3rTMnFJA1tCOPwRxtgF4wd7Ab2qvDbL8jX+3smjIbS4HlZBagTlpERbdN7iAbWlrfxE3M8c27kTwTawQ7st+OQ==} engines: {node: '>=14'} + cpu-features@0.0.10: + resolution: {integrity: sha512-9IkYqtX3YHPCzoVg1Py+o9057a3i0fp7S530UWokCSaFVTc7CwXPRiOjRjBQQ18ZCNafx78YfnG+HALxtVmOGA==} + engines: {node: '>=10.0.0'} + create-hash@1.2.0: resolution: {integrity: sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==} @@ -1312,6 +1405,14 @@ packages: dataloader@1.4.0: resolution: {integrity: sha512-68s5jYdlvasItOJnCuI2Q9s4q98g0pCyL3HrcKJu8KNugUl8ahgmZYg38ysLTgQjjXX3H8CJLkAvWrclWfcalw==} + debug@3.2.7: + resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + debug@4.3.4: resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} engines: {node: '>=6.0'} @@ -1368,6 +1469,10 @@ packages: resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} engines: {node: '>= 0.4'} + delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + delete-empty@3.0.0: resolution: {integrity: sha512-ZUyiwo76W+DYnKsL3Kim6M/UOavPdBJgDYWOmuQhYaZvJH0AXAHbUNyEDtRbBra8wqqr686+63/0azfEk1ebUQ==} engines: {node: '>=10'} @@ -1389,10 +1494,30 @@ packages: resolution: {integrity: sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==} engines: {node: '>=0.3.1'} + diff@5.2.0: + resolution: {integrity: sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==} + engines: {node: '>=0.3.1'} + dir-glob@3.0.1: resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} engines: {node: '>=8'} + docker-modem@1.0.9: + resolution: {integrity: sha512-lVjqCSCIAUDZPAZIeyM125HXfNvOmYYInciphNrLrylUtKyW66meAjSPXWchKVzoIYZx69TPnAepVSSkeawoIw==} + engines: {node: '>= 0.8'} + + docker-modem@5.0.3: + resolution: {integrity: sha512-89zhop5YVhcPEt5FpUFGr3cDyceGhq/F9J+ZndQ4KfqNvfbJpPMfgeixFgUj5OjCYAboElqODxY5Z1EBsSa6sg==} + engines: {node: '>= 8.0'} + + dockerode@2.5.8: + resolution: {integrity: sha512-+7iOUYBeDTScmOmQqpUYQaE7F4vvIt6+gIZNHWhqAQEI887tiPFB9OvXI/HzQYqfUNvukMK+9myLW63oTJPZpw==} + engines: {node: '>= 0.8'} + + dockerode@4.0.2: + resolution: {integrity: sha512-9wM1BVpVMFr2Pw3eJNXrYYt6DT9k0xMcsSCjtPvyQ+xa1iPg/Mo3T/gUcwI0B2cczqCeCYRPF8yFYDwtFXT0+w==} + engines: {node: '>= 8.0'} + doctrine@3.0.0: resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} engines: {node: '>=6.0.0'} @@ -1407,8 +1532,8 @@ packages: elliptic@6.5.4: resolution: {integrity: sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==} - emoji-regex@10.4.0: - resolution: {integrity: sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==} + emoji-regex@10.3.0: + resolution: {integrity: sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==} emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} @@ -1424,10 +1549,6 @@ packages: resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} engines: {node: '>=6'} - environment@1.1.0: - resolution: {integrity: sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==} - engines: {node: '>=18'} - error-ex@1.3.2: resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} @@ -1614,10 +1735,6 @@ packages: resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} engines: {node: '>=8'} - fill-range@7.1.1: - resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} - engines: {node: '>=8'} - find-replace@3.0.0: resolution: {integrity: sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==} engines: {node: '>=4.0.0'} @@ -1634,9 +1751,6 @@ packages: resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} engines: {node: '>=10'} - find-yarn-workspace-root2@1.2.16: - resolution: {integrity: sha512-hr6hb1w8ePMpPVUK39S4RlwJzi+xPLuVuG8XlwXU3KD5Yn3qgBWVfy3AzNlDhWvE1EORCE65/Qm26rFQt3VLVA==} - find-yarn-workspace-root@2.0.0: resolution: {integrity: sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ==} @@ -1666,12 +1780,23 @@ packages: form-data-encoder@1.7.1: resolution: {integrity: sha512-EFRDrsMm/kyqbTQocNvRXMLjc7Es2Vk+IQFx/YW7hkUH1eBl4J1fqiP34l74Yt0pFLCNpc06fkbVk00008mzjg==} + form-data@4.0.0: + resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} + engines: {node: '>= 6'} + fp-ts@1.19.3: resolution: {integrity: sha512-H5KQDspykdHuztLTg+ajGN0Z2qUjcEf3Ybxc6hLt0k7/zPkn29XnKnxlBPyW2XIddWrGaJBzBl4VLYOtk39yZg==} + fs-constants@1.0.0: + resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} + fs-extra@0.30.0: resolution: {integrity: sha512-UvSPKyhMn6LEd/WpUaV9C9t3zATuqoqfWc3QdPhPLb58prN9tqYPlPWi8Krxi44loBoUzlobqZ3+8tGpxxSzwA==} + fs-extra@11.2.0: + resolution: {integrity: sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==} + engines: {node: '>=14.14'} + fs-extra@7.0.1: resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==} engines: {node: '>=6 <7 || >=8'} @@ -1894,8 +2019,8 @@ packages: resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} engines: {node: '>=16.17.0'} - husky@9.1.5: - resolution: {integrity: sha512-rowAVRUBfI0b4+niA4SJMhfQwc107VLkBUgEYYAOQAbqDCnra1nYh83hF/MDmhYs9t9n1E3DuKOrs2LYNC+0Ag==} + husky@9.0.11: + resolution: {integrity: sha512-AB6lFlbwwyIqMdHYhwPe+kjOC3Oc5P3nThEoW/AaO2BX3vJDjWPFxYLxokUZOo6RNX20He3AaT8sESs9NJcmEw==} engines: {node: '>=18'} hasBin: true @@ -1903,6 +2028,9 @@ packages: resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} engines: {node: '>=0.10.0'} + ieee754@1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + ignore@5.2.4: resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==} engines: {node: '>= 4'} @@ -2092,6 +2220,12 @@ packages: resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} engines: {node: '>=8'} + isarray@0.0.1: + resolution: {integrity: sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==} + + isarray@1.0.0: + resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} + isarray@2.0.5: resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} @@ -2143,10 +2277,17 @@ packages: jsonfile@6.1.0: resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} + jsonparse@1.3.1: + resolution: {integrity: sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==} + engines: {'0': node >= 0.2.0} + jsonpointer@5.0.1: resolution: {integrity: sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==} engines: {node: '>=0.10.0'} + just-extend@6.2.0: + resolution: {integrity: sha512-cYofQu2Xpom82S6qD778jBDpwvvy39s1l/hrYij2u9AMdQcGRpaBu6kY4mVhuno5kJVi1DAz4aiphA2WI1/OAw==} + keccak@3.0.2: resolution: {integrity: sha512-PyKKjkH53wDMLGrvmRGSNWgmSxZOUqbnXwKL9tmgbFYA1iAYqW21kfR7mZXV0MlESiefxQQE9X9fTa3X+2MPDQ==} engines: {node: '>=10.0.0'} @@ -2175,26 +2316,22 @@ packages: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} - lilconfig@3.1.2: - resolution: {integrity: sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==} + lilconfig@3.0.0: + resolution: {integrity: sha512-K2U4W2Ff5ibV7j7ydLr+zLAkIg5JJ4lPn1Ltsdt+Tz/IjQ8buJ55pZAxoP34lqIiwtF9iAvtLv3JGv7CAyAg+g==} engines: {node: '>=14'} lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - lint-staged@15.2.9: - resolution: {integrity: sha512-BZAt8Lk3sEnxw7tfxM7jeZlPRuT4M68O0/CwZhhaw6eeWu0Lz5eERE3m386InivXB64fp/mDID452h48tvKlRQ==} + lint-staged@15.2.2: + resolution: {integrity: sha512-TiTt93OPh1OZOsb5B7k96A/ATl2AjIZo+vnzFZ6oHK5FuTk63ByDtxGQpHm+kFETjEWqgkF95M8FRXKR/LEBcw==} engines: {node: '>=18.12.0'} hasBin: true - listr2@8.2.4: - resolution: {integrity: sha512-opevsywziHd3zHCVQGAj8zu+Z3yHNkkoYhWIGnq54RrCVwLz0MozotJEDnKsIBLvkfLGN6BLOyAeRrYI0pKA4g==} + listr2@8.0.1: + resolution: {integrity: sha512-ovJXBXkKGfq+CwmKTjluEqFi3p4h8xvkxGQQAQan22YCgef4KZ1mKGjzfGh6PL6AW5Csw0QiQPNuQyH+6Xk3hA==} engines: {node: '>=18.0.0'} - load-yaml-file@0.2.0: - resolution: {integrity: sha512-OfCBkGEw4nN6JLtgRidPX6QxjBQGQf72q3si2uvqyFEMbycSFFHwAZeXx6cJgFM9wmLrf9zBwCP3Ivqa+LLZPw==} - engines: {node: '>=6'} - locate-path@2.0.0: resolution: {integrity: sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==} engines: {node: '>=4'} @@ -2213,6 +2350,9 @@ packages: lodash.clonedeep@4.5.0: resolution: {integrity: sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==} + lodash.get@4.4.2: + resolution: {integrity: sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==} + lodash.isequal@4.5.0: resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==} @@ -2235,8 +2375,8 @@ packages: resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} engines: {node: '>=10'} - log-update@6.1.0: - resolution: {integrity: sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==} + log-update@6.0.0: + resolution: {integrity: sha512-niTvB4gqvtof056rRIrTZvjNYE4rCUzO6X/X+kYjd7WFxXeJ0NwEFnRxX6ehkvv3jTwrXnNdtAak5XYZuIyPFw==} engines: {node: '>=18'} loupe@2.3.7: @@ -2287,18 +2427,22 @@ packages: resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} engines: {node: '>=8.6'} - micromatch@4.0.8: - resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} - engines: {node: '>=8.6'} + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + + mimic-fn@2.1.0: + resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} + engines: {node: '>=6'} mimic-fn@4.0.0: resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} engines: {node: '>=12'} - mimic-function@5.0.1: - resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==} - engines: {node: '>=18'} - mimic-response@1.0.1: resolution: {integrity: sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==} engines: {node: '>=4'} @@ -2331,6 +2475,13 @@ packages: minimist@1.2.8: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + mkdirp-classic@0.5.3: + resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==} + + mkdirp@0.5.6: + resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} + hasBin: true + mkdirp@1.0.4: resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} engines: {node: '>=10'} @@ -2357,6 +2508,9 @@ packages: ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + nan@2.20.0: + resolution: {integrity: sha512-bk3gXBZDGILuuo/6sKtr0DQmSThYHLtNCdSdXk9YkxD/jK6X2vmCyyXBBxyqZ4XcnzTyYEAThfX3DCEnLf6igw==} + nanoid@3.3.3: resolution: {integrity: sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} @@ -2371,6 +2525,9 @@ packages: nice-try@1.0.5: resolution: {integrity: sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==} + nise@6.0.0: + resolution: {integrity: sha512-K8ePqo9BFvN31HXwEtTNGzgrPpmvgciDsFz8aztFjt4LqKO/JeFD8tBOeuDiCMXrIl/m1YvfH8auSpxfaD09wg==} + no-case@2.3.2: resolution: {integrity: sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==} @@ -2439,14 +2596,14 @@ packages: once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + onetime@5.1.2: + resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} + engines: {node: '>=6'} + onetime@6.0.0: resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} engines: {node: '>=12'} - onetime@7.0.0: - resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==} - engines: {node: '>=18'} - open@7.4.2: resolution: {integrity: sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==} engines: {node: '>=8'} @@ -2517,6 +2674,9 @@ packages: resolution: {integrity: sha512-cbH9IAIJHNj9uXi196JVsRlt7cHKak6u/e6AkL/bkRelZ7rlL3X1YKxsZwa36xipOEKAsdtmaG6aAJoM1fx2zA==} engines: {node: '>=14.16'} + package-manager-detector@0.2.0: + resolution: {integrity: sha512-E385OSk9qDcXhcM9LNSe4sdhx8a9mAPrZ4sMLW+tmxl5ZuGtPUcdFu+MPP2jbgiWAZ6Pfe5soGFMd+0Db5Vrog==} + param-case@2.1.1: resolution: {integrity: sha512-eQE845L6ot89sk2N8liD8HAuH4ca6Vvr7VWAWwt7+kvvG5aBcPmmphQ68JsEG2qa9n1TykS2DLeMt363AAH8/w==} @@ -2570,6 +2730,9 @@ packages: resolution: {integrity: sha512-wZ3AeiRBRlNwkdUxvBANh0+esnt38DLffHDujZyRHkqkaKHTglnY2EP5UX3b8rdeiSutgO4y9NEJwXezNP5vHg==} engines: {node: '>=8'} + path-to-regexp@6.2.2: + resolution: {integrity: sha512-GQX3SSMokngb36+whdpRXE+3f9V8UzyAorlYvOGx87ufGHehNTn5lCxrKtLyZ4Yl/wEKnNnr98ZzOwwDZV5ogw==} + path-type@4.0.0: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} @@ -2581,6 +2744,9 @@ packages: resolution: {integrity: sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==} engines: {node: '>=0.12'} + picocolors@1.1.0: + resolution: {integrity: sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==} + picomatch@2.3.1: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} @@ -2594,10 +2760,6 @@ packages: resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} engines: {node: '>=6'} - pkg-dir@4.2.0: - resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} - engines: {node: '>=8'} - pluralize@8.0.0: resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} engines: {node: '>=4'} @@ -2606,10 +2768,6 @@ packages: resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==} engines: {node: '>= 0.4'} - preferred-pm@3.1.3: - resolution: {integrity: sha512-MkXsENfftWSRpzCzImcp4FRsCc3y1opwB73CfCNWyzMqArju2CrlMHlqB7VexKiPEOjGMbttv1r9fSCn5S610w==} - engines: {node: '>=10'} - prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} @@ -2634,15 +2792,24 @@ packages: engines: {node: '>=14'} hasBin: true + process-nextick-args@2.0.1: + resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} + proper-lockfile@4.1.2: resolution: {integrity: sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==} proto-list@1.2.4: resolution: {integrity: sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==} + proxy-from-env@1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + pseudomap@1.0.2: resolution: {integrity: sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==} + pump@1.0.3: + resolution: {integrity: sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw==} + pump@3.0.0: resolution: {integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==} @@ -2672,6 +2839,12 @@ packages: resolution: {integrity: sha512-VIMnQi/Z4HT2Fxuwg5KrY174U1VdUIASQVWXXyqtNRtxSr9IYkn1rsI6Tb6HsrHCmB7gVpNwX6JxPTHcH6IoTA==} engines: {node: '>=6'} + readable-stream@1.0.34: + resolution: {integrity: sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg==} + + readable-stream@2.3.8: + resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} + readable-stream@3.6.0: resolution: {integrity: sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==} engines: {node: '>= 6'} @@ -2728,9 +2901,9 @@ packages: responselike@2.0.1: resolution: {integrity: sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==} - restore-cursor@5.1.0: - resolution: {integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==} - engines: {node: '>=18'} + restore-cursor@4.0.0: + resolution: {integrity: sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} retry@0.12.0: resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==} @@ -2740,8 +2913,8 @@ packages: resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - rfdc@1.4.1: - resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} + rfdc@1.3.1: + resolution: {integrity: sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg==} rimraf@2.7.1: resolution: {integrity: sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==} @@ -2868,6 +3041,15 @@ packages: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} + sinon-chai@3.7.0: + resolution: {integrity: sha512-mf5NURdUaSdnatJx3uhoBOrY9dtL19fiOtAdT1Azxg3+lNJFiuN0uzaU3xX1LeAfL17kHQhTAJgpsfhbMJMY2g==} + peerDependencies: + chai: ^4.0.0 + sinon: '>=4.0.0' + + sinon@18.0.0: + resolution: {integrity: sha512-+dXDXzD1sBO6HlmZDd7mXZCR/y5ECiEiGCBSGuFD/kZ0bDTofPYc6JaeGmPSF+1j1MejGUWkORbYOLDyvqCWpA==} + slash@2.0.0: resolution: {integrity: sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==} engines: {node: '>=6'} @@ -2989,9 +3171,16 @@ packages: spawndamnit@2.0.0: resolution: {integrity: sha512-j4JKEcncSjFlqIwU5L/rp2N5SIPsdxaRsIv678+TZxZ0SRDJTm8JrxJMjE/XuiEZNEir3S8l0Fa3Ke339WI4qA==} + split-ca@1.0.1: + resolution: {integrity: sha512-Q5thBSxp5t8WPTTJQS59LrGqOZqOsrhDGDVm8azCqIBjSBd7nd9o2PM+mDulQQkh8h//4U6hFZnc/mul8t5pWQ==} + sprintf-js@1.0.3: resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + ssh2@1.15.0: + resolution: {integrity: sha512-C0PHgX4h6lBxYx7hcXwu3QWdh4tg6tZZsTfXcdvc5caW/EMxaB4H9dWsl7qk+F7LAW762hp8VbXOX7x4xUYvEw==} + engines: {node: '>=10.16.0'} + stacktrace-parser@0.1.10: resolution: {integrity: sha512-KJP1OCML99+8fhOHxwwzyWrlUuVX5GQ0ZpJTd1DFXhdkrvg1szxfHhawXUZ3g9TkXORQd4/WG68jMlQZ2p8wlg==} engines: {node: '>=6'} @@ -3011,8 +3200,8 @@ packages: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} - string-width@7.2.0: - resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} + string-width@7.1.0: + resolution: {integrity: sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==} engines: {node: '>=18'} string.prototype.trim@1.2.8: @@ -3036,6 +3225,12 @@ packages: resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} engines: {node: '>= 0.4'} + string_decoder@0.10.31: + resolution: {integrity: sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==} + + string_decoder@1.1.1: + resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} + string_decoder@1.3.0: resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} @@ -3094,6 +3289,20 @@ packages: resolution: {integrity: sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA==} engines: {node: '>=10.0.0'} + tar-fs@1.16.3: + resolution: {integrity: sha512-NvCeXpYx7OsmOh8zIOP/ebG55zZmxLE0etfWRbWok+q2Qo8x/vOR/IJT1taADXPe+jsiu9axDb3X4B+iIgNlKw==} + + tar-fs@2.0.1: + resolution: {integrity: sha512-6tzWDMeroL87uF/+lin46k+Q+46rAJ0SyPGz7OW7wTgblI273hsBqk2C1j0/xNadNLKDTUL9BukSjB7cwgmlPA==} + + tar-stream@1.6.2: + resolution: {integrity: sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==} + engines: {node: '>= 0.8.0'} + + tar-stream@2.2.0: + resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} + engines: {node: '>=6'} + term-size@2.2.1: resolution: {integrity: sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==} engines: {node: '>=8'} @@ -3101,6 +3310,9 @@ packages: text-table@0.2.0: resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} + through@2.3.8: + resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} + title-case@2.1.1: resolution: {integrity: sha512-EkJoZ2O3zdCz3zJsYCsxyq2OC5hrxR9mfdd5I+w8h/tmFfeOxJ+vvkxsKxdmN0WtS9zLdHEgfgVOiMVgv+Po4Q==} @@ -3108,6 +3320,9 @@ packages: resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} engines: {node: '>=0.6.0'} + to-buffer@1.1.1: + resolution: {integrity: sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==} + to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} @@ -3160,6 +3375,9 @@ packages: tweetnacl-util@0.15.1: resolution: {integrity: sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw==} + tweetnacl@0.14.5: + resolution: {integrity: sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==} + tweetnacl@1.0.3: resolution: {integrity: sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==} @@ -3224,6 +3442,9 @@ packages: resolution: {integrity: sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==} engines: {node: '>= 0.4'} + typedarray@0.0.6: + resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==} + typescript@5.5.4: resolution: {integrity: sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==} engines: {node: '>=14.17'} @@ -3240,13 +3461,17 @@ packages: unbox-primitive@1.0.2: resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} - undici-types@5.26.5: - resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + undici-types@6.19.8: + resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} undici@5.28.4: resolution: {integrity: sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==} engines: {node: '>=14.0'} + undici@6.19.8: + resolution: {integrity: sha512-U8uCCl2x9TK3WANvmBavymRzxbfFYG+tAu+fgx3zxQy3qdagQqBLwJVrdyO1TBfUXvfKveMKJZhpvUYoOjM+4g==} + engines: {node: '>=18.17'} + universalify@0.1.2: resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} engines: {node: '>= 4.0.0'} @@ -3294,10 +3519,6 @@ packages: which-boxed-primitive@1.0.2: resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} - which-pm@2.0.0: - resolution: {integrity: sha512-Lhs9Pmyph0p5n5Z3mVnN0yWcbQYUAD7rbQUiMsQxOJ3T57k7RFe35SUwWMf7dsbDZks1uOmw4AecB/JMDj3v/w==} - engines: {node: '>=8.15'} - which-typed-array@1.1.13: resolution: {integrity: sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==} engines: {node: '>= 0.4'} @@ -3361,6 +3582,10 @@ packages: utf-8-validate: optional: true + xtend@4.0.2: + resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} + engines: {node: '>=0.4'} + y18n@5.0.8: resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} engines: {node: '>=10'} @@ -3372,10 +3597,9 @@ packages: resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==} engines: {node: '>= 6'} - yaml@2.5.0: - resolution: {integrity: sha512-2wWLbGbYDiSqqIKoPjar3MPgB94ErzCtrNE1FdqGuaO0pi2JGjmE8aW8TDZwzU7vuxcGRdL/4gPQwQ7hD5AMSw==} + yaml@2.3.4: + resolution: {integrity: sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==} engines: {node: '>= 14'} - hasBin: true yargs-parser@20.2.4: resolution: {integrity: sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==} @@ -3415,7 +3639,7 @@ snapshots: '@openzeppelin/contracts': 4.8.3 '@openzeppelin/contracts-upgradeable': 4.8.3 optionalDependencies: - '@openzeppelin/upgrades-core': 1.34.4 + '@openzeppelin/upgrades-core': 1.32.5 transitivePeerDependencies: - supports-color @@ -3435,15 +3659,16 @@ snapshots: dependencies: regenerator-runtime: 0.14.1 + '@balena/dockerignore@1.0.2': {} + '@chainlink/solhint-plugin-chainlink-solidity@https://codeload.github.com/smartcontractkit/chainlink-solhint-rules/tar.gz/1b4c0c2663fcd983589d4f33a2e73908624ed43c': {} - '@changesets/apply-release-plan@7.0.4': + '@changesets/apply-release-plan@7.0.5': dependencies: - '@babel/runtime': 7.24.0 - '@changesets/config': 3.0.2 + '@changesets/config': 3.0.3 '@changesets/get-version-range-type': 0.4.0 - '@changesets/git': 3.0.0 - '@changesets/should-skip-package': 0.1.0 + '@changesets/git': 3.0.1 + '@changesets/should-skip-package': 0.1.1 '@changesets/types': 6.0.0 '@manypkg/get-packages': 1.1.3 detect-indent: 6.1.0 @@ -3454,12 +3679,11 @@ snapshots: resolve-from: 5.0.0 semver: 7.6.3 - '@changesets/assemble-release-plan@6.0.3': + '@changesets/assemble-release-plan@6.0.4': dependencies: - '@babel/runtime': 7.24.0 '@changesets/errors': 0.2.0 - '@changesets/get-dependents-graph': 2.1.1 - '@changesets/should-skip-package': 0.1.0 + '@changesets/get-dependents-graph': 2.1.2 + '@changesets/should-skip-package': 0.1.1 '@changesets/types': 6.0.0 '@manypkg/get-packages': 1.1.3 semver: 7.6.3 @@ -3476,46 +3700,44 @@ snapshots: transitivePeerDependencies: - encoding - '@changesets/cli@2.27.7': + '@changesets/cli@2.27.8': dependencies: - '@babel/runtime': 7.24.0 - '@changesets/apply-release-plan': 7.0.4 - '@changesets/assemble-release-plan': 6.0.3 + '@changesets/apply-release-plan': 7.0.5 + '@changesets/assemble-release-plan': 6.0.4 '@changesets/changelog-git': 0.2.0 - '@changesets/config': 3.0.2 + '@changesets/config': 3.0.3 '@changesets/errors': 0.2.0 - '@changesets/get-dependents-graph': 2.1.1 - '@changesets/get-release-plan': 4.0.3 - '@changesets/git': 3.0.0 - '@changesets/logger': 0.1.0 - '@changesets/pre': 2.0.0 - '@changesets/read': 0.6.0 - '@changesets/should-skip-package': 0.1.0 + '@changesets/get-dependents-graph': 2.1.2 + '@changesets/get-release-plan': 4.0.4 + '@changesets/git': 3.0.1 + '@changesets/logger': 0.1.1 + '@changesets/pre': 2.0.1 + '@changesets/read': 0.6.1 + '@changesets/should-skip-package': 0.1.1 '@changesets/types': 6.0.0 - '@changesets/write': 0.3.1 + '@changesets/write': 0.3.2 '@manypkg/get-packages': 1.1.3 '@types/semver': 7.5.0 ansi-colors: 4.1.3 - chalk: 2.4.2 ci-info: 3.9.0 enquirer: 2.3.6 external-editor: 3.1.0 fs-extra: 7.0.1 - human-id: 1.0.2 mri: 1.2.0 outdent: 0.5.0 p-limit: 2.3.0 - preferred-pm: 3.1.3 + package-manager-detector: 0.2.0 + picocolors: 1.1.0 resolve-from: 5.0.0 semver: 7.6.3 spawndamnit: 2.0.0 term-size: 2.2.1 - '@changesets/config@3.0.2': + '@changesets/config@3.0.3': dependencies: '@changesets/errors': 0.2.0 - '@changesets/get-dependents-graph': 2.1.1 - '@changesets/logger': 0.1.0 + '@changesets/get-dependents-graph': 2.1.2 + '@changesets/logger': 0.1.1 '@changesets/types': 6.0.0 '@manypkg/get-packages': 1.1.3 fs-extra: 7.0.1 @@ -3525,12 +3747,11 @@ snapshots: dependencies: extendable-error: 0.1.7 - '@changesets/get-dependents-graph@2.1.1': + '@changesets/get-dependents-graph@2.1.2': dependencies: '@changesets/types': 6.0.0 '@manypkg/get-packages': 1.1.3 - chalk: 2.4.2 - fs-extra: 7.0.1 + picocolors: 1.1.0 semver: 7.6.3 '@changesets/get-github-info@0.6.0': @@ -3540,59 +3761,53 @@ snapshots: transitivePeerDependencies: - encoding - '@changesets/get-release-plan@4.0.3': + '@changesets/get-release-plan@4.0.4': dependencies: - '@babel/runtime': 7.24.0 - '@changesets/assemble-release-plan': 6.0.3 - '@changesets/config': 3.0.2 - '@changesets/pre': 2.0.0 - '@changesets/read': 0.6.0 + '@changesets/assemble-release-plan': 6.0.4 + '@changesets/config': 3.0.3 + '@changesets/pre': 2.0.1 + '@changesets/read': 0.6.1 '@changesets/types': 6.0.0 '@manypkg/get-packages': 1.1.3 '@changesets/get-version-range-type@0.4.0': {} - '@changesets/git@3.0.0': + '@changesets/git@3.0.1': dependencies: - '@babel/runtime': 7.24.0 '@changesets/errors': 0.2.0 - '@changesets/types': 6.0.0 '@manypkg/get-packages': 1.1.3 is-subdir: 1.2.0 micromatch: 4.0.5 spawndamnit: 2.0.0 - '@changesets/logger@0.1.0': + '@changesets/logger@0.1.1': dependencies: - chalk: 2.4.2 + picocolors: 1.1.0 '@changesets/parse@0.4.0': dependencies: '@changesets/types': 6.0.0 js-yaml: 3.14.1 - '@changesets/pre@2.0.0': + '@changesets/pre@2.0.1': dependencies: - '@babel/runtime': 7.24.0 '@changesets/errors': 0.2.0 '@changesets/types': 6.0.0 '@manypkg/get-packages': 1.1.3 fs-extra: 7.0.1 - '@changesets/read@0.6.0': + '@changesets/read@0.6.1': dependencies: - '@babel/runtime': 7.24.0 - '@changesets/git': 3.0.0 - '@changesets/logger': 0.1.0 + '@changesets/git': 3.0.1 + '@changesets/logger': 0.1.1 '@changesets/parse': 0.4.0 '@changesets/types': 6.0.0 - chalk: 2.4.2 fs-extra: 7.0.1 p-filter: 2.1.0 + picocolors: 1.1.0 - '@changesets/should-skip-package@0.1.0': + '@changesets/should-skip-package@0.1.1': dependencies: - '@babel/runtime': 7.24.0 '@changesets/types': 6.0.0 '@manypkg/get-packages': 1.1.3 @@ -3600,9 +3815,8 @@ snapshots: '@changesets/types@6.0.0': {} - '@changesets/write@0.3.1': + '@changesets/write@0.3.2': dependencies: - '@babel/runtime': 7.24.0 '@changesets/types': 6.0.0 fs-extra: 7.0.1 human-id: 1.0.2 @@ -3969,6 +4183,43 @@ snapshots: globby: 11.1.0 read-yaml-file: 1.1.0 + '@matterlabs/hardhat-zksync-solc@1.2.3(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.16.4)(typescript@5.5.4))(typescript@5.5.4))': + dependencies: + '@nomiclabs/hardhat-docker': 2.0.2 + chai: 4.5.0 + chalk: 4.1.2 + debug: 4.3.6 + dockerode: 4.0.2 + fs-extra: 11.2.0 + hardhat: 2.20.1(ts-node@10.9.2(@types/node@20.16.4)(typescript@5.5.4))(typescript@5.5.4) + proper-lockfile: 4.1.2 + semver: 7.6.3 + sinon: 18.0.0 + sinon-chai: 3.7.0(chai@4.5.0)(sinon@18.0.0) + undici: 6.19.8 + transitivePeerDependencies: + - encoding + - supports-color + + '@matterlabs/hardhat-zksync-verify@1.6.0(@nomicfoundation/hardhat-verify@2.0.10(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.16.4)(typescript@5.5.4))(typescript@5.5.4)))(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.16.4)(typescript@5.5.4))(typescript@5.5.4))': + dependencies: + '@ethersproject/abi': 5.7.0 + '@ethersproject/address': 5.7.0 + '@matterlabs/hardhat-zksync-solc': 1.2.3(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.16.4)(typescript@5.5.4))(typescript@5.5.4)) + '@nomicfoundation/hardhat-verify': 2.0.10(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.16.4)(typescript@5.5.4))(typescript@5.5.4)) + axios: 1.7.7(debug@4.3.6) + cbor: 9.0.2 + chai: 4.5.0 + chalk: 4.1.2 + debug: 4.3.6 + hardhat: 2.20.1(ts-node@10.9.2(@types/node@20.16.4)(typescript@5.5.4))(typescript@5.5.4) + semver: 7.6.3 + sinon: 18.0.0 + sinon-chai: 3.7.0(chai@4.5.0)(sinon@18.0.0) + transitivePeerDependencies: + - encoding + - supports-color + '@metamask/eth-sig-util@4.0.1': dependencies: ethereumjs-abi: 0.6.8 @@ -4119,40 +4370,40 @@ snapshots: - c-kzg - supports-color - '@nomicfoundation/hardhat-chai-matchers@1.0.6(@nomiclabs/hardhat-ethers@2.2.3(ethers@5.7.2)(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.14.15)(typescript@5.5.4))(typescript@5.5.4)))(chai@4.5.0)(ethers@5.7.2)(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.14.15)(typescript@5.5.4))(typescript@5.5.4))': + '@nomicfoundation/hardhat-chai-matchers@1.0.6(@nomiclabs/hardhat-ethers@2.2.3(ethers@5.7.2)(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.16.4)(typescript@5.5.4))(typescript@5.5.4)))(chai@4.5.0)(ethers@5.7.2)(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.16.4)(typescript@5.5.4))(typescript@5.5.4))': dependencies: '@ethersproject/abi': 5.7.0 - '@nomiclabs/hardhat-ethers': 2.2.3(ethers@5.7.2)(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.14.15)(typescript@5.5.4))(typescript@5.5.4)) + '@nomiclabs/hardhat-ethers': 2.2.3(ethers@5.7.2)(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.16.4)(typescript@5.5.4))(typescript@5.5.4)) '@types/chai-as-promised': 7.1.8 chai: 4.5.0 chai-as-promised: 7.1.1(chai@4.5.0) deep-eql: 4.1.3 ethers: 5.7.2 - hardhat: 2.20.1(ts-node@10.9.2(@types/node@20.14.15)(typescript@5.5.4))(typescript@5.5.4) + hardhat: 2.20.1(ts-node@10.9.2(@types/node@20.16.4)(typescript@5.5.4))(typescript@5.5.4) ordinal: 1.0.3 - '@nomicfoundation/hardhat-ethers@3.0.6(ethers@5.7.2)(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.14.15)(typescript@5.5.4))(typescript@5.5.4))': + '@nomicfoundation/hardhat-ethers@3.0.6(ethers@5.7.2)(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.16.4)(typescript@5.5.4))(typescript@5.5.4))': dependencies: debug: 4.3.6 ethers: 5.7.2 - hardhat: 2.20.1(ts-node@10.9.2(@types/node@20.14.15)(typescript@5.5.4))(typescript@5.5.4) + hardhat: 2.20.1(ts-node@10.9.2(@types/node@20.16.4)(typescript@5.5.4))(typescript@5.5.4) lodash.isequal: 4.5.0 transitivePeerDependencies: - supports-color - '@nomicfoundation/hardhat-network-helpers@1.0.11(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.14.15)(typescript@5.5.4))(typescript@5.5.4))': + '@nomicfoundation/hardhat-network-helpers@1.0.11(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.16.4)(typescript@5.5.4))(typescript@5.5.4))': dependencies: ethereumjs-util: 7.1.5 - hardhat: 2.20.1(ts-node@10.9.2(@types/node@20.14.15)(typescript@5.5.4))(typescript@5.5.4) + hardhat: 2.20.1(ts-node@10.9.2(@types/node@20.16.4)(typescript@5.5.4))(typescript@5.5.4) - '@nomicfoundation/hardhat-verify@2.0.9(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.14.15)(typescript@5.5.4))(typescript@5.5.4))': + '@nomicfoundation/hardhat-verify@2.0.10(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.16.4)(typescript@5.5.4))(typescript@5.5.4))': dependencies: '@ethersproject/abi': 5.7.0 '@ethersproject/address': 5.7.0 cbor: 8.1.0 chalk: 2.4.2 debug: 4.3.6 - hardhat: 2.20.1(ts-node@10.9.2(@types/node@20.14.15)(typescript@5.5.4))(typescript@5.5.4) + hardhat: 2.20.1(ts-node@10.9.2(@types/node@20.16.4)(typescript@5.5.4))(typescript@5.5.4) lodash.clonedeep: 4.5.0 semver: 6.3.0 table: 6.8.1 @@ -4203,10 +4454,19 @@ snapshots: '@nomicfoundation/solidity-analyzer-win32-ia32-msvc': 0.1.0 '@nomicfoundation/solidity-analyzer-win32-x64-msvc': 0.1.0 - '@nomiclabs/hardhat-ethers@2.2.3(ethers@5.7.2)(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.14.15)(typescript@5.5.4))(typescript@5.5.4))': + '@nomiclabs/hardhat-docker@2.0.2': + dependencies: + dockerode: 2.5.8 + fs-extra: 7.0.1 + node-fetch: 2.6.7 + transitivePeerDependencies: + - encoding + - supports-color + + '@nomiclabs/hardhat-ethers@2.2.3(ethers@5.7.2)(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.16.4)(typescript@5.5.4))(typescript@5.5.4))': dependencies: ethers: 5.7.2 - hardhat: 2.20.1(ts-node@10.9.2(@types/node@20.14.15)(typescript@5.5.4))(typescript@5.5.4) + hardhat: 2.20.1(ts-node@10.9.2(@types/node@20.16.4)(typescript@5.5.4))(typescript@5.5.4) '@offchainlabs/upgrade-executor@1.1.0-beta.0': dependencies: @@ -4229,11 +4489,11 @@ snapshots: '@openzeppelin/contracts@4.9.3': {} - '@openzeppelin/upgrades-core@1.34.4': + '@openzeppelin/upgrades-core@1.32.5': dependencies: cbor: 9.0.2 chalk: 4.1.2 - compare-versions: 6.1.1 + compare-versions: 6.1.0 debug: 4.3.6 ethereumjs-util: 7.1.5 minimist: 1.2.8 @@ -4327,6 +4587,26 @@ snapshots: '@sindresorhus/is@4.6.0': {} + '@sinonjs/commons@2.0.0': + dependencies: + type-detect: 4.0.8 + + '@sinonjs/commons@3.0.1': + dependencies: + type-detect: 4.0.8 + + '@sinonjs/fake-timers@11.3.1': + dependencies: + '@sinonjs/commons': 3.0.1 + + '@sinonjs/samsam@8.0.0': + dependencies: + '@sinonjs/commons': 2.0.0 + lodash.get: 4.4.2 + type-detect: 4.0.8 + + '@sinonjs/text-encoding@0.7.3': {} + '@solidity-parser/parser@0.17.0': {} '@solidity-parser/parser@0.18.0': {} @@ -4367,40 +4647,40 @@ snapshots: typechain: 8.3.2(typescript@5.5.4) typescript: 5.5.4 - '@typechain/hardhat@7.0.0(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(@typechain/ethers-v5@7.2.0(@ethersproject/abi@5.7.0)(@ethersproject/bytes@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.2(typescript@5.5.4))(typescript@5.5.4))(ethers@5.7.2)(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.14.15)(typescript@5.5.4))(typescript@5.5.4))(typechain@8.3.2(typescript@5.5.4))': + '@typechain/hardhat@7.0.0(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2)(@typechain/ethers-v5@7.2.0(@ethersproject/abi@5.7.0)(@ethersproject/bytes@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.2(typescript@5.5.4))(typescript@5.5.4))(ethers@5.7.2)(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.16.4)(typescript@5.5.4))(typescript@5.5.4))(typechain@8.3.2(typescript@5.5.4))': dependencies: '@ethersproject/abi': 5.7.0 '@ethersproject/providers': 5.7.2 '@typechain/ethers-v5': 7.2.0(@ethersproject/abi@5.7.0)(@ethersproject/bytes@5.7.0)(@ethersproject/providers@5.7.2)(ethers@5.7.2)(typechain@8.3.2(typescript@5.5.4))(typescript@5.5.4) ethers: 5.7.2 fs-extra: 9.1.0 - hardhat: 2.20.1(ts-node@10.9.2(@types/node@20.14.15)(typescript@5.5.4))(typescript@5.5.4) + hardhat: 2.20.1(ts-node@10.9.2(@types/node@20.16.4)(typescript@5.5.4))(typescript@5.5.4) typechain: 8.3.2(typescript@5.5.4) '@types/bn.js@4.11.6': dependencies: - '@types/node': 20.14.15 + '@types/node': 20.16.4 '@types/bn.js@5.1.1': dependencies: - '@types/node': 20.14.15 + '@types/node': 20.16.4 '@types/cacheable-request@6.0.2': dependencies: '@types/http-cache-semantics': 4.0.1 '@types/keyv': 3.1.4 - '@types/node': 20.14.15 + '@types/node': 20.16.4 '@types/responselike': 1.0.0 '@types/cbor@5.0.1': dependencies: - '@types/node': 20.14.15 + '@types/node': 20.16.4 '@types/chai-as-promised@7.1.8': dependencies: - '@types/chai': 4.3.17 + '@types/chai': 4.3.19 - '@types/chai@4.3.17': {} + '@types/chai@4.3.19': {} '@types/debug@4.1.12': dependencies: @@ -4412,7 +4692,7 @@ snapshots: '@types/keyv@3.1.4': dependencies: - '@types/node': 20.14.15 + '@types/node': 20.16.4 '@types/lru-cache@5.1.1': {} @@ -4422,28 +4702,28 @@ snapshots: '@types/node@12.19.16': {} - '@types/node@20.14.15': + '@types/node@20.16.4': dependencies: - undici-types: 5.26.5 + undici-types: 6.19.8 '@types/pbkdf2@3.1.0': dependencies: - '@types/node': 20.14.15 + '@types/node': 20.16.4 '@types/prettier@2.7.1': {} '@types/readable-stream@2.3.15': dependencies: - '@types/node': 20.14.15 + '@types/node': 20.16.4 safe-buffer: 5.1.2 '@types/responselike@1.0.0': dependencies: - '@types/node': 20.14.15 + '@types/node': 20.16.4 '@types/secp256k1@4.0.3': dependencies: - '@types/node': 20.14.15 + '@types/node': 20.16.4 '@types/semver@7.5.0': {} @@ -4532,6 +4812,11 @@ snapshots: '@yarnpkg/lockfile@1.1.0': {} + JSONStream@1.3.2: + dependencies: + jsonparse: 1.3.1 + through: 2.3.8 + abi-to-sol@0.6.6: dependencies: '@truffle/abi-utils': 0.3.2 @@ -4598,9 +4883,7 @@ snapshots: dependencies: type-fest: 0.21.3 - ansi-escapes@7.0.0: - dependencies: - environment: 1.1.0 + ansi-escapes@6.2.1: {} ansi-regex@2.1.1: {} @@ -4684,12 +4967,18 @@ snapshots: is-shared-array-buffer: 1.0.3 optional: true + asn1@0.2.6: + dependencies: + safer-buffer: 2.1.2 + assertion-error@1.1.0: {} ast-parents@0.0.1: {} astral-regex@2.0.0: {} + asynckit@0.4.0: {} + at-least-node@1.0.0: {} available-typed-arrays@1.0.5: @@ -4700,12 +4989,26 @@ snapshots: possible-typed-array-names: 1.0.0 optional: true + axios@1.7.7(debug@4.3.6): + dependencies: + follow-redirects: 1.15.6(debug@4.3.6) + form-data: 4.0.0 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + balanced-match@1.0.0: {} base-x@3.0.9: dependencies: safe-buffer: 5.2.1 + base64-js@1.5.1: {} + + bcrypt-pbkdf@1.0.2: + dependencies: + tweetnacl: 0.14.5 + bech32@1.1.4: {} better-ajv-errors@0.8.2(ajv@6.12.6): @@ -4729,6 +5032,17 @@ snapshots: binary-extensions@2.2.0: {} + bl@1.2.3: + dependencies: + readable-stream: 2.3.8 + safe-buffer: 5.2.1 + + bl@4.1.0: + dependencies: + buffer: 5.7.1 + inherits: 2.0.4 + readable-stream: 3.6.0 + blakejs@1.2.1: {} bn.js@4.11.6: {} @@ -4761,10 +5075,6 @@ snapshots: dependencies: fill-range: 7.0.1 - braces@3.0.3: - dependencies: - fill-range: 7.1.1 - brorand@1.1.0: {} browser-stdout@1.3.1: {} @@ -4788,12 +5098,29 @@ snapshots: create-hash: 1.2.0 safe-buffer: 5.2.1 + buffer-alloc-unsafe@1.1.0: {} + + buffer-alloc@1.2.0: + dependencies: + buffer-alloc-unsafe: 1.1.0 + buffer-fill: 1.0.0 + + buffer-fill@1.0.0: {} + buffer-from@1.1.2: {} buffer-xor@1.0.3: {} + buffer@5.7.1: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + bufio@1.0.7: {} + buildcheck@0.0.6: + optional: true + bytes@3.1.2: {} cacheable-lookup@6.1.0: {} @@ -4845,7 +5172,6 @@ snapshots: cbor@9.0.2: dependencies: nofilter: 3.1.0 - optional: true chai-as-promised@7.1.1(chai@4.5.0): dependencies: @@ -4914,6 +5240,8 @@ snapshots: optionalDependencies: fsevents: 2.3.2 + chownr@1.1.4: {} + ci-info@2.0.0: {} ci-info@3.9.0: {} @@ -4927,14 +5255,14 @@ snapshots: cli-boxes@2.2.1: {} - cli-cursor@5.0.0: + cli-cursor@4.0.0: dependencies: - restore-cursor: 5.1.0 + restore-cursor: 4.0.0 cli-truncate@4.0.0: dependencies: slice-ansi: 5.0.0 - string-width: 7.2.0 + string-width: 7.1.0 cliui@7.0.4: dependencies: @@ -4962,6 +5290,10 @@ snapshots: colorette@2.0.20: {} + combined-stream@1.0.8: + dependencies: + delayed-stream: 1.0.0 + command-exists@1.2.9: {} command-line-args@5.2.1: @@ -4980,15 +5312,22 @@ snapshots: commander@10.0.1: {} - commander@12.1.0: {} + commander@11.1.0: {} commander@3.0.2: {} - compare-versions@6.1.1: + compare-versions@6.1.0: optional: true concat-map@0.0.1: {} + concat-stream@1.6.2: + dependencies: + buffer-from: 1.1.2 + inherits: 2.0.4 + readable-stream: 2.3.8 + typedarray: 0.0.6 + config-chain@1.1.13: dependencies: ini: 1.3.8 @@ -5003,6 +5342,8 @@ snapshots: core-js@3.30.1: {} + core-util-is@1.0.3: {} + cosmiconfig@8.2.0: dependencies: import-fresh: 3.3.0 @@ -5010,6 +5351,12 @@ snapshots: parse-json: 5.2.0 path-type: 4.0.0 + cpu-features@0.0.10: + dependencies: + buildcheck: 0.0.6 + nan: 2.20.0 + optional: true + create-hash@1.2.0: dependencies: cipher-base: 1.0.4 @@ -5072,6 +5419,10 @@ snapshots: dataloader@1.4.0: {} + debug@3.2.7: + dependencies: + ms: 2.1.3 + debug@4.3.4(supports-color@8.1.1): dependencies: ms: 2.1.2 @@ -5124,6 +5475,8 @@ snapshots: object-keys: 1.1.1 optional: true + delayed-stream@1.0.0: {} + delete-empty@3.0.0: dependencies: ansi-colors: 4.1.3 @@ -5139,10 +5492,46 @@ snapshots: diff@5.0.0: {} + diff@5.2.0: {} + dir-glob@3.0.1: dependencies: path-type: 4.0.0 + docker-modem@1.0.9: + dependencies: + JSONStream: 1.3.2 + debug: 3.2.7 + readable-stream: 1.0.34 + split-ca: 1.0.1 + transitivePeerDependencies: + - supports-color + + docker-modem@5.0.3: + dependencies: + debug: 4.3.6 + readable-stream: 3.6.0 + split-ca: 1.0.1 + ssh2: 1.15.0 + transitivePeerDependencies: + - supports-color + + dockerode@2.5.8: + dependencies: + concat-stream: 1.6.2 + docker-modem: 1.0.9 + tar-fs: 1.16.3 + transitivePeerDependencies: + - supports-color + + dockerode@4.0.2: + dependencies: + '@balena/dockerignore': 1.0.2 + docker-modem: 5.0.3 + tar-fs: 2.0.1 + transitivePeerDependencies: + - supports-color + doctrine@3.0.0: dependencies: esutils: 2.0.3 @@ -5163,7 +5552,7 @@ snapshots: minimalistic-assert: 1.0.1 minimalistic-crypto-utils: 1.0.1 - emoji-regex@10.4.0: {} + emoji-regex@10.3.0: {} emoji-regex@8.0.0: {} @@ -5177,8 +5566,6 @@ snapshots: env-paths@2.2.1: {} - environment@1.1.0: {} - error-ex@1.3.2: dependencies: is-arrayish: 0.2.1 @@ -5561,10 +5948,6 @@ snapshots: dependencies: to-regex-range: 5.0.1 - fill-range@7.1.1: - dependencies: - to-regex-range: 5.0.1 - find-replace@3.0.0: dependencies: array-back: 3.1.0 @@ -5583,11 +5966,6 @@ snapshots: locate-path: 6.0.0 path-exists: 4.0.0 - find-yarn-workspace-root2@1.2.16: - dependencies: - micromatch: 4.0.5 - pkg-dir: 4.2.0 - find-yarn-workspace-root@2.0.0: dependencies: micromatch: 4.0.5 @@ -5613,8 +5991,16 @@ snapshots: form-data-encoder@1.7.1: {} + form-data@4.0.0: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + mime-types: 2.1.35 + fp-ts@1.19.3: {} + fs-constants@1.0.0: {} + fs-extra@0.30.0: dependencies: graceful-fs: 4.2.10 @@ -5623,6 +6009,12 @@ snapshots: path-is-absolute: 1.0.1 rimraf: 2.7.1 + fs-extra@11.2.0: + dependencies: + graceful-fs: 4.2.10 + jsonfile: 6.1.0 + universalify: 2.0.0 + fs-extra@7.0.1: dependencies: graceful-fs: 4.2.10 @@ -5762,7 +6154,7 @@ snapshots: array-union: 2.1.0 dir-glob: 3.0.1 fast-glob: 3.3.1 - ignore: 5.2.4 + ignore: 5.3.1 merge2: 1.4.1 slash: 3.0.0 @@ -5793,11 +6185,11 @@ snapshots: graphemer@1.4.0: {} - hardhat-abi-exporter@2.10.1(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.14.15)(typescript@5.5.4))(typescript@5.5.4)): + hardhat-abi-exporter@2.10.1(hardhat@2.20.1(ts-node@10.9.2(@types/node@20.16.4)(typescript@5.5.4))(typescript@5.5.4)): dependencies: '@ethersproject/abi': 5.7.0 delete-empty: 3.0.0 - hardhat: 2.20.1(ts-node@10.9.2(@types/node@20.14.15)(typescript@5.5.4))(typescript@5.5.4) + hardhat: 2.20.1(ts-node@10.9.2(@types/node@20.16.4)(typescript@5.5.4))(typescript@5.5.4) hardhat-ignore-warnings@0.2.11: dependencies: @@ -5805,7 +6197,7 @@ snapshots: node-interval-tree: 2.1.2 solidity-comments: 0.0.2 - hardhat@2.20.1(ts-node@10.9.2(@types/node@20.14.15)(typescript@5.5.4))(typescript@5.5.4): + hardhat@2.20.1(ts-node@10.9.2(@types/node@20.16.4)(typescript@5.5.4))(typescript@5.5.4): dependencies: '@ethersproject/abi': 5.7.0 '@metamask/eth-sig-util': 4.0.1 @@ -5858,7 +6250,7 @@ snapshots: uuid: 8.3.2 ws: 7.5.9 optionalDependencies: - ts-node: 10.9.2(@types/node@20.14.15)(typescript@5.5.4) + ts-node: 10.9.2(@types/node@20.16.4)(typescript@5.5.4) typescript: 5.5.4 transitivePeerDependencies: - bufferutil @@ -5962,12 +6354,14 @@ snapshots: human-signals@5.0.0: {} - husky@9.1.5: {} + husky@9.0.11: {} iconv-lite@0.4.24: dependencies: safer-buffer: 2.1.2 + ieee754@1.2.1: {} + ignore@5.2.4: {} ignore@5.3.1: {} @@ -6153,6 +6547,10 @@ snapshots: dependencies: is-docker: 2.2.1 + isarray@0.0.1: {} + + isarray@1.0.0: {} + isarray@2.0.5: optional: true @@ -6202,8 +6600,12 @@ snapshots: optionalDependencies: graceful-fs: 4.2.10 + jsonparse@1.3.1: {} + jsonpointer@5.0.1: {} + just-extend@6.2.0: {} + keccak@3.0.2: dependencies: node-addon-api: 2.0.2 @@ -6237,41 +6639,34 @@ snapshots: prelude-ls: 1.2.1 type-check: 0.4.0 - lilconfig@3.1.2: {} + lilconfig@3.0.0: {} lines-and-columns@1.2.4: {} - lint-staged@15.2.9: + lint-staged@15.2.2: dependencies: chalk: 5.3.0 - commander: 12.1.0 - debug: 4.3.6 + commander: 11.1.0 + debug: 4.3.4(supports-color@8.1.1) execa: 8.0.1 - lilconfig: 3.1.2 - listr2: 8.2.4 - micromatch: 4.0.8 + lilconfig: 3.0.0 + listr2: 8.0.1 + micromatch: 4.0.5 pidtree: 0.6.0 string-argv: 0.3.2 - yaml: 2.5.0 + yaml: 2.3.4 transitivePeerDependencies: - supports-color - listr2@8.2.4: + listr2@8.0.1: dependencies: cli-truncate: 4.0.0 colorette: 2.0.20 eventemitter3: 5.0.1 - log-update: 6.1.0 - rfdc: 1.4.1 + log-update: 6.0.0 + rfdc: 1.3.1 wrap-ansi: 9.0.0 - load-yaml-file@0.2.0: - dependencies: - graceful-fs: 4.2.10 - js-yaml: 3.14.1 - pify: 4.0.1 - strip-bom: 3.0.0 - locate-path@2.0.0: dependencies: p-locate: 2.0.0 @@ -6289,6 +6684,8 @@ snapshots: lodash.clonedeep@4.5.0: {} + lodash.get@4.4.2: {} + lodash.isequal@4.5.0: {} lodash.mapvalues@4.6.0: {} @@ -6306,10 +6703,10 @@ snapshots: chalk: 4.1.2 is-unicode-supported: 0.1.0 - log-update@6.1.0: + log-update@6.0.0: dependencies: - ansi-escapes: 7.0.0 - cli-cursor: 5.0.0 + ansi-escapes: 6.2.1 + cli-cursor: 4.0.0 slice-ansi: 7.1.0 strip-ansi: 7.1.0 wrap-ansi: 9.0.0 @@ -6356,14 +6753,15 @@ snapshots: braces: 3.0.2 picomatch: 2.3.1 - micromatch@4.0.8: + mime-db@1.52.0: {} + + mime-types@2.1.35: dependencies: - braces: 3.0.3 - picomatch: 2.3.1 + mime-db: 1.52.0 - mimic-fn@4.0.0: {} + mimic-fn@2.1.0: {} - mimic-function@5.0.1: {} + mimic-fn@4.0.0: {} mimic-response@1.0.1: {} @@ -6391,6 +6789,12 @@ snapshots: minimist@1.2.8: {} + mkdirp-classic@0.5.3: {} + + mkdirp@0.5.6: + dependencies: + minimist: 1.2.8 + mkdirp@1.0.4: {} mnemonist@0.38.5: @@ -6429,6 +6833,9 @@ snapshots: ms@2.1.3: {} + nan@2.20.0: + optional: true + nanoid@3.3.3: {} natural-compare@1.4.0: {} @@ -6439,6 +6846,14 @@ snapshots: nice-try@1.0.5: {} + nise@6.0.0: + dependencies: + '@sinonjs/commons': 3.0.1 + '@sinonjs/fake-timers': 11.3.1 + '@sinonjs/text-encoding': 0.7.3 + just-extend: 6.2.0 + path-to-regexp: 6.2.2 + no-case@2.3.2: dependencies: lower-case: 1.1.4 @@ -6500,13 +6915,13 @@ snapshots: dependencies: wrappy: 1.0.2 - onetime@6.0.0: + onetime@5.1.2: dependencies: - mimic-fn: 4.0.0 + mimic-fn: 2.1.0 - onetime@7.0.0: + onetime@6.0.0: dependencies: - mimic-function: 5.0.1 + mimic-fn: 4.0.0 open@7.4.2: dependencies: @@ -6575,6 +6990,8 @@ snapshots: registry-url: 6.0.1 semver: 7.6.3 + package-manager-detector@0.2.0: {} + param-case@2.1.1: dependencies: no-case: 2.3.2 @@ -6632,6 +7049,8 @@ snapshots: path-starts-with@2.0.1: {} + path-to-regexp@6.2.2: {} + path-type@4.0.0: {} pathval@1.1.1: {} @@ -6644,28 +7063,19 @@ snapshots: safe-buffer: 5.2.1 sha.js: 2.4.11 + picocolors@1.1.0: {} + picomatch@2.3.1: {} pidtree@0.6.0: {} pify@4.0.1: {} - pkg-dir@4.2.0: - dependencies: - find-up: 4.1.0 - pluralize@8.0.0: {} possible-typed-array-names@1.0.0: optional: true - preferred-pm@3.1.3: - dependencies: - find-up: 5.0.0 - find-yarn-workspace-root2: 1.2.16 - path-exists: 4.0.0 - which-pm: 2.0.0 - prelude-ls@1.2.1: {} prettier-linter-helpers@1.0.0: @@ -6691,17 +7101,25 @@ snapshots: prettier@3.3.3: {} + process-nextick-args@2.0.1: {} + proper-lockfile@4.1.2: dependencies: graceful-fs: 4.2.10 retry: 0.12.0 signal-exit: 3.0.7 - optional: true proto-list@1.2.4: {} + proxy-from-env@1.1.0: {} + pseudomap@1.0.2: {} + pump@1.0.3: + dependencies: + end-of-stream: 1.4.4 + once: 1.4.0 + pump@3.0.0: dependencies: end-of-stream: 1.4.4 @@ -6738,6 +7156,23 @@ snapshots: pify: 4.0.1 strip-bom: 3.0.0 + readable-stream@1.0.34: + dependencies: + core-util-is: 1.0.3 + inherits: 2.0.4 + isarray: 0.0.1 + string_decoder: 0.10.31 + + readable-stream@2.3.8: + dependencies: + core-util-is: 1.0.3 + inherits: 2.0.4 + isarray: 1.0.0 + process-nextick-args: 2.0.1 + safe-buffer: 5.1.2 + string_decoder: 1.1.1 + util-deprecate: 1.0.2 + readable-stream@3.6.0: dependencies: inherits: 2.0.4 @@ -6793,17 +7228,16 @@ snapshots: dependencies: lowercase-keys: 2.0.0 - restore-cursor@5.1.0: + restore-cursor@4.0.0: dependencies: - onetime: 7.0.0 - signal-exit: 4.1.0 + onetime: 5.1.2 + signal-exit: 3.0.7 - retry@0.12.0: - optional: true + retry@0.12.0: {} reusify@1.0.4: {} - rfdc@1.4.1: {} + rfdc@1.3.1: {} rimraf@2.7.1: dependencies: @@ -6948,6 +7382,20 @@ snapshots: signal-exit@4.1.0: {} + sinon-chai@3.7.0(chai@4.5.0)(sinon@18.0.0): + dependencies: + chai: 4.5.0 + sinon: 18.0.0 + + sinon@18.0.0: + dependencies: + '@sinonjs/commons': 3.0.1 + '@sinonjs/fake-timers': 11.3.1 + '@sinonjs/samsam': 8.0.0 + diff: 5.2.0 + nise: 6.0.0 + supports-color: 7.2.0 + slash@2.0.0: {} slash@3.0.0: {} @@ -7082,8 +7530,18 @@ snapshots: cross-spawn: 5.1.0 signal-exit: 3.0.7 + split-ca@1.0.1: {} + sprintf-js@1.0.3: {} + ssh2@1.15.0: + dependencies: + asn1: 0.2.6 + bcrypt-pbkdf: 1.0.2 + optionalDependencies: + cpu-features: 0.0.10 + nan: 2.20.0 + stacktrace-parser@0.1.10: dependencies: type-fest: 0.7.1 @@ -7100,9 +7558,9 @@ snapshots: is-fullwidth-code-point: 3.0.0 strip-ansi: 6.0.1 - string-width@7.2.0: + string-width@7.1.0: dependencies: - emoji-regex: 10.4.0 + emoji-regex: 10.3.0 get-east-asian-width: 1.2.0 strip-ansi: 7.1.0 @@ -7149,6 +7607,12 @@ snapshots: es-object-atoms: 1.0.0 optional: true + string_decoder@0.10.31: {} + + string_decoder@1.1.1: + dependencies: + safe-buffer: 5.1.2 + string_decoder@1.3.0: dependencies: safe-buffer: 5.2.1 @@ -7210,10 +7674,44 @@ snapshots: string-width: 4.2.3 strip-ansi: 6.0.1 + tar-fs@1.16.3: + dependencies: + chownr: 1.1.4 + mkdirp: 0.5.6 + pump: 1.0.3 + tar-stream: 1.6.2 + + tar-fs@2.0.1: + dependencies: + chownr: 1.1.4 + mkdirp-classic: 0.5.3 + pump: 3.0.0 + tar-stream: 2.2.0 + + tar-stream@1.6.2: + dependencies: + bl: 1.2.3 + buffer-alloc: 1.2.0 + end-of-stream: 1.4.4 + fs-constants: 1.0.0 + readable-stream: 2.3.8 + to-buffer: 1.1.1 + xtend: 4.0.2 + + tar-stream@2.2.0: + dependencies: + bl: 4.1.0 + end-of-stream: 1.4.4 + fs-constants: 1.0.0 + inherits: 2.0.4 + readable-stream: 3.6.0 + term-size@2.2.1: {} text-table@0.2.0: {} + through@2.3.8: {} + title-case@2.1.1: dependencies: no-case: 2.3.2 @@ -7223,6 +7721,8 @@ snapshots: dependencies: os-tmpdir: 1.0.2 + to-buffer@1.1.1: {} + to-regex-range@5.0.1: dependencies: is-number: 7.0.0 @@ -7246,14 +7746,14 @@ snapshots: dependencies: typescript: 5.5.4 - ts-node@10.9.2(@types/node@20.14.15)(typescript@5.5.4): + ts-node@10.9.2(@types/node@20.16.4)(typescript@5.5.4): dependencies: '@cspotcode/source-map-support': 0.8.1 '@tsconfig/node10': 1.0.9 '@tsconfig/node12': 1.0.11 '@tsconfig/node14': 1.0.3 '@tsconfig/node16': 1.0.3 - '@types/node': 20.14.15 + '@types/node': 20.16.4 acorn: 8.10.0 acorn-walk: 8.2.0 arg: 4.1.3 @@ -7272,6 +7772,8 @@ snapshots: tweetnacl-util@0.15.1: {} + tweetnacl@0.14.5: {} + tweetnacl@1.0.3: {} type-check@0.4.0: @@ -7371,6 +7873,8 @@ snapshots: possible-typed-array-names: 1.0.0 optional: true + typedarray@0.0.6: {} + typescript@5.5.4: {} typical@4.0.0: {} @@ -7385,12 +7889,14 @@ snapshots: which-boxed-primitive: 1.0.2 optional: true - undici-types@5.26.5: {} + undici-types@6.19.8: {} undici@5.28.4: dependencies: '@fastify/busboy': 2.1.1 + undici@6.19.8: {} + universalify@0.1.2: {} universalify@2.0.0: {} @@ -7441,11 +7947,6 @@ snapshots: is-symbol: 1.0.3 optional: true - which-pm@2.0.0: - dependencies: - load-yaml-file: 0.2.0 - path-exists: 4.0.0 - which-typed-array@1.1.13: dependencies: available-typed-arrays: 1.0.5 @@ -7492,7 +7993,7 @@ snapshots: wrap-ansi@9.0.0: dependencies: ansi-styles: 6.2.1 - string-width: 7.2.0 + string-width: 7.1.0 strip-ansi: 7.1.0 wrappy@1.0.2: {} @@ -7501,13 +8002,15 @@ snapshots: ws@7.5.9: {} + xtend@4.0.2: {} + y18n@5.0.8: {} yallist@2.1.2: {} yaml@1.10.2: {} - yaml@2.5.0: {} + yaml@2.3.4: {} yargs-parser@20.2.4: {} diff --git a/contracts/scripts/zksyncverify/README.md b/contracts/scripts/zksyncverify/README.md new file mode 100644 index 0000000000..97158f660b --- /dev/null +++ b/contracts/scripts/zksyncverify/README.md @@ -0,0 +1,35 @@ +# Verify ZkSync Contracts For CCIP + +Pre-requisites: +- `pnpm install` at contracts directory +- `pnpm run zksync:compile `>> for compiling the contracts, you can uncomment `contractsToCompile` in [hardhat.ccip.zksync.config.ts](../../hardhat.ccip.zksync.config.ts) to compile only the contracts you need + +Now that you have compiled the contracts, you can verify them : + +You will need - +`abiFilePath`: Absolute file path to the compiled json file. You can find the compiled json files in the `artifacts-zk` directory under [contracts](../../) folder. Example: contracts/artifacts-zk/src/v0.8/ccip/PriceRegistry.sol/PriceRegistry.json +`encodedConstructorArgs`: The encoded constructor arguments for the contract. You can find the encoded constructor arguments in the `Input Data` field of the deployment transaction on etherscan. +If you cannot find the encoded constructor arguments, you can pass the following argument for the script to fetch the encoded constructor arguments: +`deploymentTx` - The transaction hash of the contract deployment transaction. Example: 0x801901aea0714fff8f26997bd148c744b6494865b01e83dfa15f571df7af531c +`rpcURL` - The RPC URL of the network you want to verify the contract on. Example: https://mainnet.infura.io/v3/your-infura-project-id + +Once you have the above you can run the following command to generate the constructor arguments for verification script: + +```bash +go run scripts/zksyncverify/main.go --abiFilePath= --deploymentTx= --rpcURL= + +Or + +go run scripts/zksyncverify/main.go --abiFilePath= --encodedConstructorArgs= +``` + +This will generate the constructor arguments which you can use to in [zksync-verify.ts](zksync-verify.ts) script. +Replace the constructor arguments and contract address in the script and run the following command from [contracts](../../) dir to verify the contract: +Please note : the generated constructor arguments may not be in the right order, Cross-check the order of the constructor arguments, structs & its fields against the constructor in the respective solidity file. + +```bash +pnpm run zksync:verify + +For Testnet: +pnpm run zksync:verify:sepolia +``` \ No newline at end of file diff --git a/contracts/scripts/zksyncverify/main.go b/contracts/scripts/zksyncverify/main.go new file mode 100644 index 0000000000..99a7ef4a9e --- /dev/null +++ b/contracts/scripts/zksyncverify/main.go @@ -0,0 +1,100 @@ +package main + +import ( + "context" + "encoding/hex" + "encoding/json" + "flag" + "fmt" + "log" + "os" + "path/filepath" + "strings" + + "github.com/AlekSi/pointer" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethclient" +) + +// This script decodes the constructor arguments of a contract from a hex string +func main() { + abiFilePath := flag.String("abiPath", "", "Absolute Path to the compiled contract ABI JSON file") + encodedConstructorArgs := flag.String("encodedConstructorArgs", "", "Hex encoded constructor arguments") + deploymentTx := flag.String("deploymentTx", "", "Contract Deployment transaction hash") + rpcURL := flag.String("rpcURL", "", "RPC URL for the chain") + flag.Parse() + if pointer.GetString(encodedConstructorArgs) == "" && (pointer.GetString(deploymentTx) == "" || pointer.GetString(rpcURL) == "") { + log.Fatalf("Encoded constructor arguments or deploymentTx and rpcURL must be provided") + } + + if !filepath.IsAbs(pointer.GetString(abiFilePath)) { + log.Fatalf("Abi file path must be absolute") + } + var params string + if pointer.GetString(encodedConstructorArgs) == "" { + // Get the contract deployment transaction receipt + client, err := ethclient.Dial(pointer.GetString(rpcURL)) + if err != nil { + log.Fatalf("Failed to connect to the rpc client: %v", err) + } + tx, _, err := client.TransactionByHash(context.Background(), common.HexToHash(pointer.GetString(deploymentTx))) + if err != nil { + log.Fatalf("Failed to get transaction receipt: %v", err) + } + params = string(tx.Data()) + } else { + params = pointer.GetString(encodedConstructorArgs) + } + // Read the ABI JSON file + abiFileContent, err := os.ReadFile(pointer.GetString(abiFilePath)) + if err != nil { + log.Fatalf("Failed to read ABI file: %v", err) + } + + // Parse the JSON content to extract the ABI and deployed bytecode + var compiledFile struct { + ABI json.RawMessage `json:"abi"` + DeployedBytecode string `json:"deployedBytecode"` + } + if err = json.Unmarshal(abiFileContent, &compiledFile); err != nil { + log.Fatalf("Failed to unmarshal ABI file content: %v", err) + } + + // Parse the ABI + parsedABI, err := abi.JSON(strings.NewReader(string(compiledFile.ABI))) + if err != nil { + log.Fatalf("Failed to parse ABI: %v", err) + } + + // Decode the constructor arguments from the input hex + encodedParamsBytes, err := hex.DecodeString(params) + if err != nil { + log.Fatalf("Failed to decode hex string: %v", err) + } + + // fmt.Println(hex.EncodeToString(encodedParamsBytes[0 : 4+(4*32)])) + encodedParamsBytes = encodedParamsBytes[4+(4*32):] + + // Use the constructor arguments to unpack the values + decodedArgs, err := parsedABI.Constructor.Inputs.Unpack(encodedParamsBytes) + if err != nil { + log.Fatalf("Failed to unpack constructor arguments: %v", err) + } + + // Create a map to hold the named constructor arguments + constructorArgsMap := make(map[string]interface{}) + for i, arg := range parsedABI.Constructor.Inputs { + fmt.Println(arg.Name) + constructorArgsMap[arg.Name] = decodedArgs[i] + } + + // Convert decoded arguments to JSON + decodedArgsJSON, err := json.MarshalIndent(constructorArgsMap, "", " ") + if err != nil { + log.Fatalf("Failed to marshal decoded arguments to JSON: %v", err) + } + + fmt.Println("Decoded Constructor Arguments in JSON Format:") + fmt.Println(string(decodedArgsJSON)) +} diff --git a/contracts/scripts/zksyncverify/zksync-verify.ts b/contracts/scripts/zksyncverify/zksync-verify.ts new file mode 100644 index 0000000000..b5f430f5b2 --- /dev/null +++ b/contracts/scripts/zksyncverify/zksync-verify.ts @@ -0,0 +1,28 @@ +import hre from 'hardhat' +//import big from 'ethers' +// pass in the correct constrcutor arguments for the contract & +// run with `npx hardhat run zksync-verify.ts --config ./hardhat.ccip.zksync.config.ts` & remember to change the appropriate `default network` in the config file or pass as argument +async function main() { + await hre.run('verify:verify', { + address: '0xb575772CD01478477eA649b82C30FD63295D7A4d', + constructorArguments: [ + { + voters: [ + { + blessVoteAddr: '0x94e46574182e03cab3557ecb780643b66946970a', + curseVoteAddr: '0x3e09450412c5765b0b91e3c7b15dd523e460aeae', + blessWeight: 1, + curseWeight: 1, + }, + ], + blessWeightThreshold: 1, + curseWeightThreshold: 1, + }, + ], + }) +} + +main().catch((error) => { + console.error(error) + process.exitCode = 1 +}) diff --git a/go.mod b/go.mod index fdebb10181..64c460303b 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module github.com/smartcontractkit/chainlink/v2 go 1.22.5 require ( + github.com/AlekSi/pointer v1.1.0 github.com/Depado/ginprom v1.8.0 github.com/Masterminds/semver/v3 v3.2.1 github.com/Masterminds/sprig/v3 v3.2.3 From 53a84916e1fc28ee59370ee04d891205fcae7cb3 Mon Sep 17 00:00:00 2001 From: Ryan <80392855+RayXpub@users.noreply.github.com> Date: Mon, 9 Sep 2024 09:17:25 +0400 Subject: [PATCH 077/115] Enforce signature verification for commit plugin in `OffRamp` (#1416) ## Motivation The goal of this PR is to implement a check to ensure that the OCR3 signature verification is enabled for the commit plugin on config. This reduces misconfig risks and impact because previously an accidental setting of `isSignatureVerificationEnabled=false` for the commit plugin in the `OffRamp` would have required a redeploy to be fixed. ## Solution Add a check enforcing `isSignatureVerificationEnabled=false` for the commit plugin in `_afterOC3Config`. --- contracts/foundry.toml | 2 +- contracts/gas-snapshots/ccip.gas-snapshot | 1758 ++++++++--------- .../scripts/native_solc_compile_all_ccip | 2 +- contracts/src/v0.8/ccip/offRamp/OffRamp.sol | 5 + .../v0.8/ccip/test/e2e/MultiRampsEnd2End.sol | 2 + .../src/v0.8/ccip/test/offRamp/OffRamp.t.sol | 56 +- .../v0.8/ccip/test/offRamp/OffRampSetup.t.sol | 2 - .../ccip/generated/offramp/offramp.go | 4 +- ...rapper-dependency-versions-do-not-edit.txt | 2 +- 9 files changed, 922 insertions(+), 911 deletions(-) diff --git a/contracts/foundry.toml b/contracts/foundry.toml index c755ba6437..c7c34e49d5 100644 --- a/contracts/foundry.toml +++ b/contracts/foundry.toml @@ -26,7 +26,7 @@ single_line_statement_blocks = "preserve" solc_version = '0.8.24' src = 'src/v0.8/ccip' test = 'src/v0.8/ccip/test' -optimizer_runs = 3_600 +optimizer_runs = 1_925 evm_version = 'paris' [profile.functions] diff --git a/contracts/gas-snapshots/ccip.gas-snapshot b/contracts/gas-snapshots/ccip.gas-snapshot index 0f352370f8..2ecd600642 100644 --- a/contracts/gas-snapshots/ccip.gas-snapshot +++ b/contracts/gas-snapshots/ccip.gas-snapshot @@ -1,984 +1,984 @@ -ARMProxyStandaloneTest:test_ARMCallEmptyContractRevert() (gas: 19600) -ARMProxyStandaloneTest:test_Constructor() (gas: 374544) -ARMProxyStandaloneTest:test_SetARM() (gas: 16494) -ARMProxyStandaloneTest:test_SetARMzero() (gas: 11216) -ARMProxyTest:test_ARMCallRevertReasonForwarded() (gas: 47793) -ARMProxyTest:test_ARMIsBlessed_Success() (gas: 36269) -ARMProxyTest:test_ARMIsCursed_Success() (gas: 49740) -AggregateTokenLimiter_constructor:test_Constructor_Success() (gas: 26920) -AggregateTokenLimiter_getTokenBucket:test_GetTokenBucket_Success() (gas: 19691) -AggregateTokenLimiter_getTokenBucket:test_Refill_Success() (gas: 40911) -AggregateTokenLimiter_getTokenBucket:test_TimeUnderflow_Revert() (gas: 15368) +ARMProxyStandaloneTest:test_ARMCallEmptyContractRevert() (gas: 19675) +ARMProxyStandaloneTest:test_Constructor() (gas: 315049) +ARMProxyStandaloneTest:test_SetARM() (gas: 16581) +ARMProxyStandaloneTest:test_SetARMzero() (gas: 11267) +ARMProxyTest:test_ARMCallRevertReasonForwarded() (gas: 47868) +ARMProxyTest:test_ARMIsBlessed_Success() (gas: 36334) +ARMProxyTest:test_ARMIsCursed_Success() (gas: 49833) +AggregateTokenLimiter_constructor:test_Constructor_Success() (gas: 26992) +AggregateTokenLimiter_getTokenBucket:test_GetTokenBucket_Success() (gas: 19835) +AggregateTokenLimiter_getTokenBucket:test_Refill_Success() (gas: 41499) +AggregateTokenLimiter_getTokenBucket:test_TimeUnderflow_Revert() (gas: 15446) AggregateTokenLimiter_getTokenLimitAdmin:test_GetTokenLimitAdmin_Success() (gas: 10531) -AggregateTokenLimiter_getTokenValue:test_GetTokenValue_Success() (gas: 19668) -AggregateTokenLimiter_getTokenValue:test_NoTokenPrice_Reverts() (gas: 21253) -AggregateTokenLimiter_rateLimitValue:test_AggregateValueMaxCapacityExceeded_Revert() (gas: 16418) -AggregateTokenLimiter_rateLimitValue:test_RateLimitValueSuccess_gas() (gas: 18306) -AggregateTokenLimiter_setAdmin:test_OnlyOwnerOrAdmin_Revert() (gas: 13048) -AggregateTokenLimiter_setAdmin:test_Owner_Success() (gas: 18989) -AggregateTokenLimiter_setRateLimiterConfig:test_OnlyOnlyCallableByAdminOrOwner_Revert() (gas: 17480) -AggregateTokenLimiter_setRateLimiterConfig:test_Owner_Success() (gas: 30062) -AggregateTokenLimiter_setRateLimiterConfig:test_TokenLimitAdmin_Success() (gas: 32071) -BurnFromMintTokenPool_lockOrBurn:test_ChainNotAllowed_Revert() (gas: 28773) -BurnFromMintTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 55115) -BurnFromMintTokenPool_lockOrBurn:test_PoolBurn_Success() (gas: 243529) +AggregateTokenLimiter_getTokenValue:test_GetTokenValue_Success() (gas: 19674) +AggregateTokenLimiter_getTokenValue:test_NoTokenPrice_Reverts() (gas: 21259) +AggregateTokenLimiter_rateLimitValue:test_AggregateValueMaxCapacityExceeded_Revert() (gas: 16508) +AggregateTokenLimiter_rateLimitValue:test_RateLimitValueSuccess_gas() (gas: 18348) +AggregateTokenLimiter_setAdmin:test_OnlyOwnerOrAdmin_Revert() (gas: 13054) +AggregateTokenLimiter_setAdmin:test_Owner_Success() (gas: 18998) +AggregateTokenLimiter_setRateLimiterConfig:test_OnlyOnlyCallableByAdminOrOwner_Revert() (gas: 17510) +AggregateTokenLimiter_setRateLimiterConfig:test_Owner_Success() (gas: 30230) +AggregateTokenLimiter_setRateLimiterConfig:test_TokenLimitAdmin_Success() (gas: 32244) +BurnFromMintTokenPool_lockOrBurn:test_ChainNotAllowed_Revert() (gas: 28779) +BurnFromMintTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 55124) +BurnFromMintTokenPool_lockOrBurn:test_PoolBurn_Success() (gas: 243680) BurnFromMintTokenPool_lockOrBurn:test_Setup_Success() (gas: 23947) -BurnMintTokenPool_lockOrBurn:test_ChainNotAllowed_Revert() (gas: 27534) -BurnMintTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 55115) -BurnMintTokenPool_lockOrBurn:test_PoolBurn_Success() (gas: 241420) +BurnMintTokenPool_lockOrBurn:test_ChainNotAllowed_Revert() (gas: 27546) +BurnMintTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 55130) +BurnMintTokenPool_lockOrBurn:test_PoolBurn_Success() (gas: 241573) BurnMintTokenPool_lockOrBurn:test_Setup_Success() (gas: 17677) -BurnMintTokenPool_releaseOrMint:test_ChainNotAllowed_Revert() (gas: 28757) -BurnMintTokenPool_releaseOrMint:test_PoolMintNotHealthy_Revert() (gas: 56190) -BurnMintTokenPool_releaseOrMint:test_PoolMint_Success() (gas: 112319) -BurnWithFromMintTokenPool_lockOrBurn:test_ChainNotAllowed_Revert() (gas: 28773) -BurnWithFromMintTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 55115) -BurnWithFromMintTokenPool_lockOrBurn:test_PoolBurn_Success() (gas: 243556) +BurnMintTokenPool_releaseOrMint:test_ChainNotAllowed_Revert() (gas: 28775) +BurnMintTokenPool_releaseOrMint:test_PoolMintNotHealthy_Revert() (gas: 56211) +BurnMintTokenPool_releaseOrMint:test_PoolMint_Success() (gas: 112343) +BurnWithFromMintTokenPool_lockOrBurn:test_ChainNotAllowed_Revert() (gas: 28779) +BurnWithFromMintTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 55124) +BurnWithFromMintTokenPool_lockOrBurn:test_PoolBurn_Success() (gas: 243707) BurnWithFromMintTokenPool_lockOrBurn:test_Setup_Success() (gas: 23951) -CCIPClientExample_sanity:test_ImmutableExamples_Success() (gas: 2132690) +CCIPClientExample_sanity:test_ImmutableExamples_Success() (gas: 2096747) CCIPConfigSetup:test_getCapabilityConfiguration_Success() (gas: 9539) CCIPConfig_ConfigStateMachine:test__computeConfigDigest_Success() (gas: 66088) -CCIPConfig_ConfigStateMachine:test__computeNewConfigWithMeta_InitToRunning_Success() (gas: 357846) -CCIPConfig_ConfigStateMachine:test__computeNewConfigWithMeta_RunningToStaging_Success() (gas: 474512) -CCIPConfig_ConfigStateMachine:test__computeNewConfigWithMeta_StagingToRunning_Success() (gas: 441765) -CCIPConfig_ConfigStateMachine:test__groupByPluginType_TooManyOCR3Configs_Reverts() (gas: 33798) +CCIPConfig_ConfigStateMachine:test__computeNewConfigWithMeta_InitToRunning_Success() (gas: 358063) +CCIPConfig_ConfigStateMachine:test__computeNewConfigWithMeta_RunningToStaging_Success() (gas: 474771) +CCIPConfig_ConfigStateMachine:test__computeNewConfigWithMeta_StagingToRunning_Success() (gas: 441974) +CCIPConfig_ConfigStateMachine:test__groupByPluginType_TooManyOCR3Configs_Reverts() (gas: 33804) CCIPConfig_ConfigStateMachine:test__groupByPluginType_threeCommitConfigs_Reverts() (gas: 56870) -CCIPConfig_ConfigStateMachine:test__groupByPluginType_threeExecutionConfigs_Reverts() (gas: 56790) -CCIPConfig_ConfigStateMachine:test__stateFromConfigLength_Success() (gas: 11701) -CCIPConfig_ConfigStateMachine:test__validateConfigStateTransition_Success() (gas: 8762) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_InitToRunning_Success() (gas: 309581) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_InitToRunning_WrongConfigCount_Reverts() (gas: 45877) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_NonExistentConfigTransition_Reverts() (gas: 29698) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_RunningToStaging_Success() (gas: 369916) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_RunningToStaging_WrongConfigCount_Reverts() (gas: 111436) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_RunningToStaging_WrongConfigDigestBlueGreen_Reverts() (gas: 145550) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_StagingToRunning_Success() (gas: 369692) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_StagingToRunning_WrongConfigDigest_Reverts() (gas: 145617) +CCIPConfig_ConfigStateMachine:test__groupByPluginType_threeExecutionConfigs_Reverts() (gas: 56808) +CCIPConfig_ConfigStateMachine:test__stateFromConfigLength_Success() (gas: 11719) +CCIPConfig_ConfigStateMachine:test__validateConfigStateTransition_Success() (gas: 8780) +CCIPConfig_ConfigStateMachine:test__validateConfigTransition_InitToRunning_Success() (gas: 309744) +CCIPConfig_ConfigStateMachine:test__validateConfigTransition_InitToRunning_WrongConfigCount_Reverts() (gas: 45887) +CCIPConfig_ConfigStateMachine:test__validateConfigTransition_NonExistentConfigTransition_Reverts() (gas: 29690) +CCIPConfig_ConfigStateMachine:test__validateConfigTransition_RunningToStaging_Success() (gas: 370075) +CCIPConfig_ConfigStateMachine:test__validateConfigTransition_RunningToStaging_WrongConfigCount_Reverts() (gas: 111442) +CCIPConfig_ConfigStateMachine:test__validateConfigTransition_RunningToStaging_WrongConfigDigestBlueGreen_Reverts() (gas: 145556) +CCIPConfig_ConfigStateMachine:test__validateConfigTransition_StagingToRunning_Success() (gas: 369851) +CCIPConfig_ConfigStateMachine:test__validateConfigTransition_StagingToRunning_WrongConfigDigest_Reverts() (gas: 145623) CCIPConfig_ConfigStateMachine:test_getCapabilityConfiguration_Success() (gas: 9627) -CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_CommitAndExecConfig_Success() (gas: 1752378) -CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_CommitConfigOnly_Success() (gas: 1018901) -CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_ExecConfigOnly_Success() (gas: 1018932) -CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_OnlyCapabilitiesRegistryCanCall_Reverts() (gas: 9599) -CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_ZeroLengthConfig_Success() (gas: 15984) +CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_CommitAndExecConfig_Success() (gas: 1752579) +CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_CommitConfigOnly_Success() (gas: 1019042) +CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_ExecConfigOnly_Success() (gas: 1019073) +CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_OnlyCapabilitiesRegistryCanCall_Reverts() (gas: 9611) +CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_ZeroLengthConfig_Success() (gas: 15996) CCIPConfig_beforeCapabilityConfigSet:test_getCapabilityConfiguration_Success() (gas: 9627) -CCIPConfig_chainConfig:test__applyChainConfigUpdates_FChainNotPositive_Reverts() (gas: 184705) -CCIPConfig_chainConfig:test_applyChainConfigUpdates_addChainConfigs_Success() (gas: 344873) -CCIPConfig_chainConfig:test_applyChainConfigUpdates_nodeNotInRegistry_Reverts() (gas: 20307) -CCIPConfig_chainConfig:test_applyChainConfigUpdates_removeChainConfigs_Success() (gas: 267534) -CCIPConfig_chainConfig:test_applyChainConfigUpdates_selectorNotFound_Reverts() (gas: 14807) +CCIPConfig_chainConfig:test__applyChainConfigUpdates_FChainNotPositive_Reverts() (gas: 184771) +CCIPConfig_chainConfig:test_applyChainConfigUpdates_addChainConfigs_Success() (gas: 344939) +CCIPConfig_chainConfig:test_applyChainConfigUpdates_nodeNotInRegistry_Reverts() (gas: 20340) +CCIPConfig_chainConfig:test_applyChainConfigUpdates_removeChainConfigs_Success() (gas: 267596) +CCIPConfig_chainConfig:test_applyChainConfigUpdates_selectorNotFound_Reverts() (gas: 14819) CCIPConfig_chainConfig:test_getCapabilityConfiguration_Success() (gas: 9648) -CCIPConfig_chainConfig:test_getPaginatedCCIPConfigs_Success() (gas: 370227) -CCIPConfig_constructor:test_constructor_Success() (gas: 3397350) -CCIPConfig_constructor:test_constructor_ZeroAddressNotAllowed_Revert() (gas: 61507) -CCIPConfig_updatePluginConfig:test__updatePluginConfig_InitToRunning_Success() (gas: 1008218) -CCIPConfig_updatePluginConfig:test__updatePluginConfig_InvalidConfigLength_Reverts() (gas: 25563) -CCIPConfig_updatePluginConfig:test__updatePluginConfig_InvalidConfigStateTransition_Reverts() (gas: 21781) -CCIPConfig_updatePluginConfig:test__updatePluginConfig_RunningToStaging_Success() (gas: 1895343) -CCIPConfig_updatePluginConfig:test__updatePluginConfig_StagingToRunning_Success() (gas: 2464900) +CCIPConfig_chainConfig:test_getPaginatedCCIPConfigs_Success() (gas: 370293) +CCIPConfig_constructor:test_constructor_Success() (gas: 3334093) +CCIPConfig_constructor:test_constructor_ZeroAddressNotAllowed_Revert() (gas: 61438) +CCIPConfig_updatePluginConfig:test__updatePluginConfig_InitToRunning_Success() (gas: 1008449) +CCIPConfig_updatePluginConfig:test__updatePluginConfig_InvalidConfigLength_Reverts() (gas: 25584) +CCIPConfig_updatePluginConfig:test__updatePluginConfig_InvalidConfigStateTransition_Reverts() (gas: 21799) +CCIPConfig_updatePluginConfig:test__updatePluginConfig_RunningToStaging_Success() (gas: 1895621) +CCIPConfig_updatePluginConfig:test__updatePluginConfig_StagingToRunning_Success() (gas: 2465231) CCIPConfig_updatePluginConfig:test_getCapabilityConfiguration_Success() (gas: 9627) -CCIPConfig_validateConfig:test__validateConfig_ABIEncodedAddress_OfframpAddressCannotBeZero_Reverts() (gas: 290657) -CCIPConfig_validateConfig:test__validateConfig_ChainSelectorNotFound_Reverts() (gas: 293370) -CCIPConfig_validateConfig:test__validateConfig_ChainSelectorNotSet_Reverts() (gas: 290290) -CCIPConfig_validateConfig:test__validateConfig_FMustBePositive_Reverts() (gas: 291497) -CCIPConfig_validateConfig:test__validateConfig_FTooHigh_Reverts() (gas: 291595) -CCIPConfig_validateConfig:test__validateConfig_NodeNotInRegistry_Reverts() (gas: 344569) -CCIPConfig_validateConfig:test__validateConfig_NotEnoughTransmitters_Reverts() (gas: 1207267) -CCIPConfig_validateConfig:test__validateConfig_OfframpAddressCannotBeZero_Reverts() (gas: 290373) -CCIPConfig_validateConfig:test__validateConfig_P2PIdsLengthNotMatching_Reverts() (gas: 292270) -CCIPConfig_validateConfig:test__validateConfig_Success() (gas: 299419) -CCIPConfig_validateConfig:test__validateConfig_TooManySigners_Reverts() (gas: 492913) +CCIPConfig_validateConfig:test__validateConfig_ABIEncodedAddress_OfframpAddressCannotBeZero_Reverts() (gas: 290828) +CCIPConfig_validateConfig:test__validateConfig_ChainSelectorNotFound_Reverts() (gas: 293559) +CCIPConfig_validateConfig:test__validateConfig_ChainSelectorNotSet_Reverts() (gas: 290461) +CCIPConfig_validateConfig:test__validateConfig_FMustBePositive_Reverts() (gas: 291668) +CCIPConfig_validateConfig:test__validateConfig_FTooHigh_Reverts() (gas: 291766) +CCIPConfig_validateConfig:test__validateConfig_NodeNotInRegistry_Reverts() (gas: 344947) +CCIPConfig_validateConfig:test__validateConfig_NotEnoughTransmitters_Reverts() (gas: 1208593) +CCIPConfig_validateConfig:test__validateConfig_OfframpAddressCannotBeZero_Reverts() (gas: 290544) +CCIPConfig_validateConfig:test__validateConfig_P2PIdsLengthNotMatching_Reverts() (gas: 292459) +CCIPConfig_validateConfig:test__validateConfig_Success() (gas: 299632) +CCIPConfig_validateConfig:test__validateConfig_TooManySigners_Reverts() (gas: 493084) CCIPConfig_validateConfig:test_getCapabilityConfiguration_Success() (gas: 9606) -CommitStore_constructor:test_Constructor_Success() (gas: 3091326) -CommitStore_isUnpausedAndRMNHealthy:test_RMN_Success() (gas: 73420) -CommitStore_report:test_InvalidIntervalMinLargerThanMax_Revert() (gas: 28670) -CommitStore_report:test_InvalidInterval_Revert() (gas: 28610) -CommitStore_report:test_InvalidRootRevert() (gas: 27843) -CommitStore_report:test_OnlyGasPriceUpdates_Success() (gas: 53275) -CommitStore_report:test_OnlyPriceUpdateStaleReport_Revert() (gas: 59071) -CommitStore_report:test_OnlyTokenPriceUpdates_Success() (gas: 53273) -CommitStore_report:test_Paused_Revert() (gas: 21259) -CommitStore_report:test_ReportAndPriceUpdate_Success() (gas: 84264) -CommitStore_report:test_ReportOnlyRootSuccess_gas() (gas: 56249) -CommitStore_report:test_RootAlreadyCommitted_Revert() (gas: 63969) -CommitStore_report:test_StaleReportWithRoot_Success() (gas: 119364) -CommitStore_report:test_Unhealthy_Revert() (gas: 44751) -CommitStore_report:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 100752) -CommitStore_report:test_ZeroEpochAndRound_Revert() (gas: 27626) -CommitStore_resetUnblessedRoots:test_OnlyOwner_Revert() (gas: 11325) -CommitStore_resetUnblessedRoots:test_ResetUnblessedRoots_Success() (gas: 143718) +CommitStore_constructor:test_Constructor_Success() (gas: 3013980) +CommitStore_isUnpausedAndRMNHealthy:test_RMN_Success() (gas: 73477) +CommitStore_report:test_InvalidIntervalMinLargerThanMax_Revert() (gas: 28676) +CommitStore_report:test_InvalidInterval_Revert() (gas: 28616) +CommitStore_report:test_InvalidRootRevert() (gas: 27849) +CommitStore_report:test_OnlyGasPriceUpdates_Success() (gas: 53290) +CommitStore_report:test_OnlyPriceUpdateStaleReport_Revert() (gas: 59092) +CommitStore_report:test_OnlyTokenPriceUpdates_Success() (gas: 53288) +CommitStore_report:test_Paused_Revert() (gas: 21262) +CommitStore_report:test_ReportAndPriceUpdate_Success() (gas: 84276) +CommitStore_report:test_ReportOnlyRootSuccess_gas() (gas: 56258) +CommitStore_report:test_RootAlreadyCommitted_Revert() (gas: 63984) +CommitStore_report:test_StaleReportWithRoot_Success() (gas: 119394) +CommitStore_report:test_Unhealthy_Revert() (gas: 44754) +CommitStore_report:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 100782) +CommitStore_report:test_ZeroEpochAndRound_Revert() (gas: 27632) +CommitStore_resetUnblessedRoots:test_OnlyOwner_Revert() (gas: 11331) +CommitStore_resetUnblessedRoots:test_ResetUnblessedRoots_Success() (gas: 143814) CommitStore_setDynamicConfig:test_InvalidCommitStoreConfig_Revert() (gas: 37263) -CommitStore_setDynamicConfig:test_OnlyOwner_Revert() (gas: 37399) -CommitStore_setDynamicConfig:test_PriceEpochCleared_Success() (gas: 129098) -CommitStore_setLatestPriceEpochAndRound:test_OnlyOwner_Revert() (gas: 11048) -CommitStore_setLatestPriceEpochAndRound:test_SetLatestPriceEpochAndRound_Success() (gas: 20642) -CommitStore_setMinSeqNr:test_OnlyOwner_Revert() (gas: 11047) -CommitStore_verify:test_Blessed_Success() (gas: 96389) -CommitStore_verify:test_NotBlessed_Success() (gas: 61374) -CommitStore_verify:test_Paused_Revert() (gas: 18496) -CommitStore_verify:test_TooManyLeaves_Revert() (gas: 36785) -DefensiveExampleTest:test_HappyPath_Success() (gas: 200018) -DefensiveExampleTest:test_Recovery() (gas: 424256) -E2E:test_E2E_3MessagesSuccess_gas() (gas: 1100023) -EVM2EVMOffRamp__releaseOrMintToken:test__releaseOrMintToken_NotACompatiblePool_Revert() (gas: 37782) -EVM2EVMOffRamp__releaseOrMintToken:test__releaseOrMintToken_Success() (gas: 103730) -EVM2EVMOffRamp__releaseOrMintToken:test__releaseOrMintToken_TokenHandlingError_transfer_Revert() (gas: 85255) -EVM2EVMOffRamp__releaseOrMintToken:test_releaseOrMintToken_InvalidDataLength_Revert() (gas: 36789) -EVM2EVMOffRamp__releaseOrMintToken:test_releaseOrMintToken_ReleaseOrMintBalanceMismatch_Revert() (gas: 94299) -EVM2EVMOffRamp__releaseOrMintToken:test_releaseOrMintToken_TokenHandlingError_BalanceOf_Revert() (gas: 39765) -EVM2EVMOffRamp__releaseOrMintToken:test_releaseOrMintToken_skip_ReleaseOrMintBalanceMismatch_if_pool_Revert() (gas: 86559) -EVM2EVMOffRamp__releaseOrMintTokens:test_OverValueWithARLOff_Success() (gas: 385246) -EVM2EVMOffRamp__releaseOrMintTokens:test_PriceNotFoundForToken_Reverts() (gas: 141905) -EVM2EVMOffRamp__releaseOrMintTokens:test_RateLimitErrors_Reverts() (gas: 803071) -EVM2EVMOffRamp__releaseOrMintTokens:test_TokenHandlingError_Reverts() (gas: 179244) +CommitStore_setDynamicConfig:test_OnlyOwner_Revert() (gas: 37405) +CommitStore_setDynamicConfig:test_PriceEpochCleared_Success() (gas: 129131) +CommitStore_setLatestPriceEpochAndRound:test_OnlyOwner_Revert() (gas: 11054) +CommitStore_setLatestPriceEpochAndRound:test_SetLatestPriceEpochAndRound_Success() (gas: 20645) +CommitStore_setMinSeqNr:test_OnlyOwner_Revert() (gas: 11053) +CommitStore_verify:test_Blessed_Success() (gas: 96452) +CommitStore_verify:test_NotBlessed_Success() (gas: 61398) +CommitStore_verify:test_Paused_Revert() (gas: 18505) +CommitStore_verify:test_TooManyLeaves_Revert() (gas: 36797) +DefensiveExampleTest:test_HappyPath_Success() (gas: 200047) +DefensiveExampleTest:test_Recovery() (gas: 424294) +E2E:test_E2E_3MessagesSuccess_gas() (gas: 1101943) +EVM2EVMOffRamp__releaseOrMintToken:test__releaseOrMintToken_NotACompatiblePool_Revert() (gas: 37818) +EVM2EVMOffRamp__releaseOrMintToken:test__releaseOrMintToken_Success() (gas: 103820) +EVM2EVMOffRamp__releaseOrMintToken:test__releaseOrMintToken_TokenHandlingError_transfer_Revert() (gas: 85333) +EVM2EVMOffRamp__releaseOrMintToken:test_releaseOrMintToken_InvalidDataLength_Revert() (gas: 36843) +EVM2EVMOffRamp__releaseOrMintToken:test_releaseOrMintToken_ReleaseOrMintBalanceMismatch_Revert() (gas: 94389) +EVM2EVMOffRamp__releaseOrMintToken:test_releaseOrMintToken_TokenHandlingError_BalanceOf_Revert() (gas: 39813) +EVM2EVMOffRamp__releaseOrMintToken:test_releaseOrMintToken_skip_ReleaseOrMintBalanceMismatch_if_pool_Revert() (gas: 86631) +EVM2EVMOffRamp__releaseOrMintTokens:test_OverValueWithARLOff_Success() (gas: 385756) +EVM2EVMOffRamp__releaseOrMintTokens:test_PriceNotFoundForToken_Reverts() (gas: 142019) +EVM2EVMOffRamp__releaseOrMintTokens:test_RateLimitErrors_Reverts() (gas: 804151) +EVM2EVMOffRamp__releaseOrMintTokens:test_TokenHandlingError_Reverts() (gas: 179460) EVM2EVMOffRamp__releaseOrMintTokens:test__releaseOrMintTokens_NotACompatiblePool_Reverts() (gas: 29243) -EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_InvalidDataLengthReturnData_Revert() (gas: 66444) +EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_InvalidDataLengthReturnData_Revert() (gas: 66504) EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_InvalidEVMAddress_Revert() (gas: 43320) -EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_Success() (gas: 210968) -EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals_Success() (gas: 222232) -EVM2EVMOffRamp__report:test_Report_Success() (gas: 126640) -EVM2EVMOffRamp__trialExecute:test_RateLimitError_Success() (gas: 237791) -EVM2EVMOffRamp__trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 246391) -EVM2EVMOffRamp__trialExecute:test_TokenPoolIsNotAContract_Success() (gas: 329828) -EVM2EVMOffRamp__trialExecute:test_trialExecute_Success() (gas: 312265) +EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_Success() (gas: 211280) +EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals_Success() (gas: 222532) +EVM2EVMOffRamp__report:test_Report_Success() (gas: 126703) +EVM2EVMOffRamp__trialExecute:test_RateLimitError_Success() (gas: 238004) +EVM2EVMOffRamp__trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 246604) +EVM2EVMOffRamp__trialExecute:test_TokenPoolIsNotAContract_Success() (gas: 330188) +EVM2EVMOffRamp__trialExecute:test_trialExecute_Success() (gas: 312619) EVM2EVMOffRamp_ccipReceive:test_Reverts() (gas: 17033) -EVM2EVMOffRamp_constructor:test_CommitStoreAlreadyInUse_Revert() (gas: 153727) -EVM2EVMOffRamp_constructor:test_Constructor_Success() (gas: 5665956) -EVM2EVMOffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 144461) -EVM2EVMOffRamp_execute:test_EmptyReport_Revert() (gas: 21315) -EVM2EVMOffRamp_execute:test_InvalidMessageId_Revert() (gas: 36429) -EVM2EVMOffRamp_execute:test_InvalidSourceChain_Revert() (gas: 51598) -EVM2EVMOffRamp_execute:test_InvalidSourcePoolAddress_Success() (gas: 473329) -EVM2EVMOffRamp_execute:test_ManualExecutionNotYetEnabled_Revert() (gas: 47668) -EVM2EVMOffRamp_execute:test_MessageTooLarge_Revert() (gas: 152356) -EVM2EVMOffRamp_execute:test_Paused_Revert() (gas: 102842) -EVM2EVMOffRamp_execute:test_ReceiverError_Success() (gas: 163810) -EVM2EVMOffRamp_execute:test_RetryFailedMessageWithoutManualExecution_Success() (gas: 178205) -EVM2EVMOffRamp_execute:test_RootNotCommitted_Revert() (gas: 42539) -EVM2EVMOffRamp_execute:test_SingleMessageNoTokensUnordered_Success() (gas: 157347) -EVM2EVMOffRamp_execute:test_SingleMessageNoTokens_Success() (gas: 172692) -EVM2EVMOffRamp_execute:test_SingleMessageToNonCCIPReceiver_Success() (gas: 247069) -EVM2EVMOffRamp_execute:test_SingleMessagesNoTokensSuccess_gas() (gas: 113839) -EVM2EVMOffRamp_execute:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 407451) -EVM2EVMOffRamp_execute:test_SkippedIncorrectNonce_Success() (gas: 54096) -EVM2EVMOffRamp_execute:test_StrictUntouchedToSuccess_Success() (gas: 131053) -EVM2EVMOffRamp_execute:test_TokenDataMismatch_Revert() (gas: 52087) -EVM2EVMOffRamp_execute:test_TwoMessagesWithTokensAndGE_Success() (gas: 563391) -EVM2EVMOffRamp_execute:test_TwoMessagesWithTokensSuccess_gas() (gas: 494179) -EVM2EVMOffRamp_execute:test_UnexpectedTokenData_Revert() (gas: 35380) -EVM2EVMOffRamp_execute:test_Unhealthy_Revert() (gas: 544641) -EVM2EVMOffRamp_execute:test_UnsupportedNumberOfTokens_Revert() (gas: 64323) -EVM2EVMOffRamp_execute:test__execute_SkippedAlreadyExecutedMessageUnordered_Success() (gas: 122322) -EVM2EVMOffRamp_execute:test__execute_SkippedAlreadyExecutedMessage_Success() (gas: 142532) -EVM2EVMOffRamp_execute:test_execute_RouterYULCall_Success() (gas: 427328) +EVM2EVMOffRamp_constructor:test_CommitStoreAlreadyInUse_Revert() (gas: 153548) +EVM2EVMOffRamp_constructor:test_Constructor_Success() (gas: 5549627) +EVM2EVMOffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 144282) +EVM2EVMOffRamp_execute:test_EmptyReport_Revert() (gas: 21321) +EVM2EVMOffRamp_execute:test_InvalidMessageId_Revert() (gas: 36558) +EVM2EVMOffRamp_execute:test_InvalidSourceChain_Revert() (gas: 51775) +EVM2EVMOffRamp_execute:test_InvalidSourcePoolAddress_Success() (gas: 474025) +EVM2EVMOffRamp_execute:test_ManualExecutionNotYetEnabled_Revert() (gas: 47830) +EVM2EVMOffRamp_execute:test_MessageTooLarge_Revert() (gas: 152518) +EVM2EVMOffRamp_execute:test_Paused_Revert() (gas: 103046) +EVM2EVMOffRamp_execute:test_ReceiverError_Success() (gas: 164107) +EVM2EVMOffRamp_execute:test_RetryFailedMessageWithoutManualExecution_Success() (gas: 178568) +EVM2EVMOffRamp_execute:test_RootNotCommitted_Revert() (gas: 42701) +EVM2EVMOffRamp_execute:test_SingleMessageNoTokensUnordered_Success() (gas: 157899) +EVM2EVMOffRamp_execute:test_SingleMessageNoTokens_Success() (gas: 173184) +EVM2EVMOffRamp_execute:test_SingleMessageToNonCCIPReceiver_Success() (gas: 247246) +EVM2EVMOffRamp_execute:test_SingleMessagesNoTokensSuccess_gas() (gas: 113971) +EVM2EVMOffRamp_execute:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 408147) +EVM2EVMOffRamp_execute:test_SkippedIncorrectNonce_Success() (gas: 54294) +EVM2EVMOffRamp_execute:test_StrictUntouchedToSuccess_Success() (gas: 131317) +EVM2EVMOffRamp_execute:test_TokenDataMismatch_Revert() (gas: 52249) +EVM2EVMOffRamp_execute:test_TwoMessagesWithTokensAndGE_Success() (gas: 564489) +EVM2EVMOffRamp_execute:test_TwoMessagesWithTokensSuccess_gas() (gas: 495004) +EVM2EVMOffRamp_execute:test_UnexpectedTokenData_Revert() (gas: 35497) +EVM2EVMOffRamp_execute:test_Unhealthy_Revert() (gas: 545754) +EVM2EVMOffRamp_execute:test_UnsupportedNumberOfTokens_Revert() (gas: 64497) +EVM2EVMOffRamp_execute:test__execute_SkippedAlreadyExecutedMessageUnordered_Success() (gas: 122676) +EVM2EVMOffRamp_execute:test__execute_SkippedAlreadyExecutedMessage_Success() (gas: 142850) +EVM2EVMOffRamp_execute:test_execute_RouterYULCall_Success() (gas: 427538) EVM2EVMOffRamp_executeSingleMessage:test_MessageSender_Revert() (gas: 18502) -EVM2EVMOffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 278106) +EVM2EVMOffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 278406) EVM2EVMOffRamp_executeSingleMessage:test_NonContract_Success() (gas: 18668) -EVM2EVMOffRamp_executeSingleMessage:test_TokenHandlingError_Revert() (gas: 223921) -EVM2EVMOffRamp_executeSingleMessage:test_ZeroGasDONExecution_Revert() (gas: 47881) -EVM2EVMOffRamp_executeSingleMessage:test_executeSingleMessage_NoTokens_Success() (gas: 47352) -EVM2EVMOffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens_Success() (gas: 313917) -EVM2EVMOffRamp_executeSingleMessage:test_executeSingleMessage_ZeroGasZeroData_Success() (gas: 70008) -EVM2EVMOffRamp_execute_upgrade:test_V2NonceNewSenderStartsAtZero_Success() (gas: 229325) -EVM2EVMOffRamp_execute_upgrade:test_V2NonceStartsAtV1Nonce_Success() (gas: 276790) -EVM2EVMOffRamp_execute_upgrade:test_V2OffRampNonceSkipsIfMsgInFlight_Success() (gas: 258696) -EVM2EVMOffRamp_execute_upgrade:test_V2SenderNoncesReadsPreviousRamp_Success() (gas: 226253) -EVM2EVMOffRamp_execute_upgrade:test_V2_Success() (gas: 130745) +EVM2EVMOffRamp_executeSingleMessage:test_TokenHandlingError_Revert() (gas: 224131) +EVM2EVMOffRamp_executeSingleMessage:test_ZeroGasDONExecution_Revert() (gas: 47926) +EVM2EVMOffRamp_executeSingleMessage:test_executeSingleMessage_NoTokens_Success() (gas: 47403) +EVM2EVMOffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens_Success() (gas: 314268) +EVM2EVMOffRamp_executeSingleMessage:test_executeSingleMessage_ZeroGasZeroData_Success() (gas: 70065) +EVM2EVMOffRamp_execute_upgrade:test_V2NonceNewSenderStartsAtZero_Success() (gas: 229454) +EVM2EVMOffRamp_execute_upgrade:test_V2NonceStartsAtV1Nonce_Success() (gas: 276982) +EVM2EVMOffRamp_execute_upgrade:test_V2OffRampNonceSkipsIfMsgInFlight_Success() (gas: 258834) +EVM2EVMOffRamp_execute_upgrade:test_V2SenderNoncesReadsPreviousRamp_Success() (gas: 226442) +EVM2EVMOffRamp_execute_upgrade:test_V2_Success() (gas: 130811) EVM2EVMOffRamp_getAllRateLimitTokens:test_GetAllRateLimitTokens_Success() (gas: 38446) EVM2EVMOffRamp_getExecutionState:test_FillExecutionState_Success() (gas: 3251974) EVM2EVMOffRamp_getExecutionState:test_GetExecutionState_Success() (gas: 83387) -EVM2EVMOffRamp_manuallyExecute:test_ManualExecFailedTx_Revert() (gas: 185829) -EVM2EVMOffRamp_manuallyExecute:test_ManualExecForkedChain_Revert() (gas: 27049) -EVM2EVMOffRamp_manuallyExecute:test_ManualExecGasLimitMismatch_Revert() (gas: 45155) -EVM2EVMOffRamp_manuallyExecute:test_ManualExecInvalidGasLimit_Revert() (gas: 27468) -EVM2EVMOffRamp_manuallyExecute:test_ManualExecWithMultipleMessagesAndSourceTokens_Success() (gas: 530151) -EVM2EVMOffRamp_manuallyExecute:test_ManualExecWithSourceTokens_Success() (gas: 345758) -EVM2EVMOffRamp_manuallyExecute:test_ManualExec_Success() (gas: 187324) -EVM2EVMOffRamp_manuallyExecute:test_ReentrancyManualExecuteFails_Success() (gas: 2321912) -EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_DestinationGasAmountCountMismatch_Revert() (gas: 362965) -EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_DoesNotRevertIfUntouched_Success() (gas: 143900) -EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_InvalidTokenGasOverride_Revert() (gas: 366104) -EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_LowGasLimitManualExec_Success() (gas: 482682) -EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_WithGasOverride_Success() (gas: 189727) -EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_WithInvalidReceiverExecutionGasOverride_Revert() (gas: 153641) -EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_WithInvalidSourceTokenDataCount_Revert() (gas: 59894) +EVM2EVMOffRamp_manuallyExecute:test_ManualExecFailedTx_Revert() (gas: 185967) +EVM2EVMOffRamp_manuallyExecute:test_ManualExecForkedChain_Revert() (gas: 27052) +EVM2EVMOffRamp_manuallyExecute:test_ManualExecGasLimitMismatch_Revert() (gas: 45200) +EVM2EVMOffRamp_manuallyExecute:test_ManualExecInvalidGasLimit_Revert() (gas: 27471) +EVM2EVMOffRamp_manuallyExecute:test_ManualExecWithMultipleMessagesAndSourceTokens_Success() (gas: 530877) +EVM2EVMOffRamp_manuallyExecute:test_ManualExecWithSourceTokens_Success() (gas: 346127) +EVM2EVMOffRamp_manuallyExecute:test_ManualExec_Success() (gas: 187459) +EVM2EVMOffRamp_manuallyExecute:test_ReentrancyManualExecuteFails_Success() (gas: 2258388) +EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_DestinationGasAmountCountMismatch_Revert() (gas: 363340) +EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_DoesNotRevertIfUntouched_Success() (gas: 143972) +EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_InvalidTokenGasOverride_Revert() (gas: 366479) +EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_LowGasLimitManualExec_Success() (gas: 482796) +EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_WithGasOverride_Success() (gas: 189862) +EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_WithInvalidReceiverExecutionGasOverride_Revert() (gas: 153716) +EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_WithInvalidSourceTokenDataCount_Revert() (gas: 59897) EVM2EVMOffRamp_metadataHash:test_MetadataHash_Success() (gas: 8865) -EVM2EVMOffRamp_setDynamicConfig:test_NonOwner_Revert() (gas: 40156) +EVM2EVMOffRamp_setDynamicConfig:test_NonOwner_Revert() (gas: 40162) EVM2EVMOffRamp_setDynamicConfig:test_RouterZeroAddress_Revert() (gas: 38239) -EVM2EVMOffRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 141923) +EVM2EVMOffRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 141938) EVM2EVMOffRamp_updateRateLimitTokens:test_updateRateLimitTokens_AddsAndRemoves_Success() (gas: 162528) -EVM2EVMOffRamp_updateRateLimitTokens:test_updateRateLimitTokens_NonOwner_Revert() (gas: 16693) +EVM2EVMOffRamp_updateRateLimitTokens:test_updateRateLimitTokens_NonOwner_Revert() (gas: 16699) EVM2EVMOffRamp_updateRateLimitTokens:test_updateRateLimitTokens_Success() (gas: 197728) -EVM2EVMOnRamp_constructor:test_Constructor_Success() (gas: 5579757) -EVM2EVMOnRamp_forwardFromRouter:test_CannotSendZeroTokens_Revert() (gas: 35778) -EVM2EVMOnRamp_forwardFromRouter:test_EnforceOutOfOrder_Revert() (gas: 98446) -EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() (gas: 114204) -EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2_Success() (gas: 114246) -EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterSuccessCustomExtraArgs() (gas: 130213) -EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterSuccessLegacyExtraArgs() (gas: 138659) -EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouter_Success() (gas: 129838) -EVM2EVMOnRamp_forwardFromRouter:test_InvalidAddressEncodePacked_Revert() (gas: 38257) -EVM2EVMOnRamp_forwardFromRouter:test_InvalidAddress_Revert() (gas: 38440) -EVM2EVMOnRamp_forwardFromRouter:test_InvalidChainSelector_Revert() (gas: 25489) -EVM2EVMOnRamp_forwardFromRouter:test_InvalidExtraArgsTag_Revert() (gas: 25275) -EVM2EVMOnRamp_forwardFromRouter:test_MaxCapacityExceeded_Revert() (gas: 86013) -EVM2EVMOnRamp_forwardFromRouter:test_MaxFeeBalanceReached_Revert() (gas: 36457) -EVM2EVMOnRamp_forwardFromRouter:test_MessageGasLimitTooHigh_Revert() (gas: 29015) -EVM2EVMOnRamp_forwardFromRouter:test_MessageTooLarge_Revert() (gas: 107571) -EVM2EVMOnRamp_forwardFromRouter:test_OriginalSender_Revert() (gas: 22679) -EVM2EVMOnRamp_forwardFromRouter:test_OverValueWithARLOff_Success() (gas: 227119) -EVM2EVMOnRamp_forwardFromRouter:test_Paused_Revert() (gas: 53072) -EVM2EVMOnRamp_forwardFromRouter:test_Permissions_Revert() (gas: 25481) -EVM2EVMOnRamp_forwardFromRouter:test_PriceNotFoundForToken_Revert() (gas: 59341) -EVM2EVMOnRamp_forwardFromRouter:test_ShouldIncrementNonceOnlyOnOrdered_Success() (gas: 179148) -EVM2EVMOnRamp_forwardFromRouter:test_ShouldIncrementSeqNumAndNonce_Success() (gas: 177430) -EVM2EVMOnRamp_forwardFromRouter:test_ShouldStoreNonLinkFees() (gas: 137254) -EVM2EVMOnRamp_forwardFromRouter:test_SourceTokenDataTooLarge_Revert() (gas: 3825327) -EVM2EVMOnRamp_forwardFromRouter:test_TooManyTokens_Revert() (gas: 30187) -EVM2EVMOnRamp_forwardFromRouter:test_Unhealthy_Revert() (gas: 43300) -EVM2EVMOnRamp_forwardFromRouter:test_UnsupportedToken_Revert() (gas: 109305) -EVM2EVMOnRamp_forwardFromRouter:test_ZeroAddressReceiver_Revert() (gas: 312579) -EVM2EVMOnRamp_forwardFromRouter:test_forwardFromRouter_ShouldStoreLinkFees_Success() (gas: 112331) -EVM2EVMOnRamp_forwardFromRouter:test_forwardFromRouter_UnsupportedToken_Revert() (gas: 72206) -EVM2EVMOnRamp_forwardFromRouter:test_forwardFromRouter_correctSourceTokenData_Success() (gas: 712975) -EVM2EVMOnRamp_forwardFromRouter_upgrade:test_V2NonceNewSenderStartsAtZero_Success() (gas: 147664) -EVM2EVMOnRamp_forwardFromRouter_upgrade:test_V2NonceStartsAtV1Nonce_Success() (gas: 190529) -EVM2EVMOnRamp_forwardFromRouter_upgrade:test_V2SenderNoncesReadsPreviousRamp_Success() (gas: 121320) -EVM2EVMOnRamp_forwardFromRouter_upgrade:test_V2_Success() (gas: 95349) -EVM2EVMOnRamp_getDataAvailabilityCost:test_EmptyMessageCalculatesDataAvailabilityCost_Success() (gas: 20544) -EVM2EVMOnRamp_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCost_Success() (gas: 20912) -EVM2EVMOnRamp_getFee:test_EmptyMessage_Success() (gas: 78233) -EVM2EVMOnRamp_getFee:test_GetFeeOfZeroForTokenMessage_Success() (gas: 81762) -EVM2EVMOnRamp_getFee:test_HighGasMessage_Success() (gas: 234081) -EVM2EVMOnRamp_getFee:test_MessageGasLimitTooHigh_Revert() (gas: 16715) -EVM2EVMOnRamp_getFee:test_MessageTooLarge_Revert() (gas: 95271) -EVM2EVMOnRamp_getFee:test_MessageWithDataAndTokenTransfer_Success() (gas: 159439) -EVM2EVMOnRamp_getFee:test_NotAFeeToken_Revert() (gas: 24089) -EVM2EVMOnRamp_getFee:test_SingleTokenMessage_Success() (gas: 117925) -EVM2EVMOnRamp_getFee:test_TooManyTokens_Revert() (gas: 19902) -EVM2EVMOnRamp_getFee:test_ZeroDataAvailabilityMultiplier_Success() (gas: 64648) +EVM2EVMOnRamp_constructor:test_Constructor_Success() (gas: 5431520) +EVM2EVMOnRamp_forwardFromRouter:test_CannotSendZeroTokens_Revert() (gas: 35835) +EVM2EVMOnRamp_forwardFromRouter:test_EnforceOutOfOrder_Revert() (gas: 98584) +EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() (gas: 114231) +EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2_Success() (gas: 114273) +EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterSuccessCustomExtraArgs() (gas: 130246) +EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterSuccessLegacyExtraArgs() (gas: 138686) +EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouter_Success() (gas: 129865) +EVM2EVMOnRamp_forwardFromRouter:test_InvalidAddressEncodePacked_Revert() (gas: 38314) +EVM2EVMOnRamp_forwardFromRouter:test_InvalidAddress_Revert() (gas: 38497) +EVM2EVMOnRamp_forwardFromRouter:test_InvalidChainSelector_Revert() (gas: 25534) +EVM2EVMOnRamp_forwardFromRouter:test_InvalidExtraArgsTag_Revert() (gas: 25320) +EVM2EVMOnRamp_forwardFromRouter:test_MaxCapacityExceeded_Revert() (gas: 86160) +EVM2EVMOnRamp_forwardFromRouter:test_MaxFeeBalanceReached_Revert() (gas: 36514) +EVM2EVMOnRamp_forwardFromRouter:test_MessageGasLimitTooHigh_Revert() (gas: 29078) +EVM2EVMOnRamp_forwardFromRouter:test_MessageTooLarge_Revert() (gas: 107622) +EVM2EVMOnRamp_forwardFromRouter:test_OriginalSender_Revert() (gas: 22724) +EVM2EVMOnRamp_forwardFromRouter:test_OverValueWithARLOff_Success() (gas: 227461) +EVM2EVMOnRamp_forwardFromRouter:test_Paused_Revert() (gas: 53150) +EVM2EVMOnRamp_forwardFromRouter:test_Permissions_Revert() (gas: 25559) +EVM2EVMOnRamp_forwardFromRouter:test_PriceNotFoundForToken_Revert() (gas: 59500) +EVM2EVMOnRamp_forwardFromRouter:test_ShouldIncrementNonceOnlyOnOrdered_Success() (gas: 179442) +EVM2EVMOnRamp_forwardFromRouter:test_ShouldIncrementSeqNumAndNonce_Success() (gas: 177724) +EVM2EVMOnRamp_forwardFromRouter:test_ShouldStoreNonLinkFees() (gas: 137377) +EVM2EVMOnRamp_forwardFromRouter:test_SourceTokenDataTooLarge_Revert() (gas: 3772676) +EVM2EVMOnRamp_forwardFromRouter:test_TooManyTokens_Revert() (gas: 30244) +EVM2EVMOnRamp_forwardFromRouter:test_Unhealthy_Revert() (gas: 43342) +EVM2EVMOnRamp_forwardFromRouter:test_UnsupportedToken_Revert() (gas: 109440) +EVM2EVMOnRamp_forwardFromRouter:test_ZeroAddressReceiver_Revert() (gas: 313095) +EVM2EVMOnRamp_forwardFromRouter:test_forwardFromRouter_ShouldStoreLinkFees_Success() (gas: 112430) +EVM2EVMOnRamp_forwardFromRouter:test_forwardFromRouter_UnsupportedToken_Revert() (gas: 72269) +EVM2EVMOnRamp_forwardFromRouter:test_forwardFromRouter_correctSourceTokenData_Success() (gas: 713890) +EVM2EVMOnRamp_forwardFromRouter_upgrade:test_V2NonceNewSenderStartsAtZero_Success() (gas: 147709) +EVM2EVMOnRamp_forwardFromRouter_upgrade:test_V2NonceStartsAtV1Nonce_Success() (gas: 190616) +EVM2EVMOnRamp_forwardFromRouter_upgrade:test_V2SenderNoncesReadsPreviousRamp_Success() (gas: 121404) +EVM2EVMOnRamp_forwardFromRouter_upgrade:test_V2_Success() (gas: 95376) +EVM2EVMOnRamp_getDataAvailabilityCost:test_EmptyMessageCalculatesDataAvailabilityCost_Success() (gas: 20568) +EVM2EVMOnRamp_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCost_Success() (gas: 20936) +EVM2EVMOnRamp_getFee:test_EmptyMessage_Success() (gas: 78401) +EVM2EVMOnRamp_getFee:test_GetFeeOfZeroForTokenMessage_Success() (gas: 81897) +EVM2EVMOnRamp_getFee:test_HighGasMessage_Success() (gas: 234249) +EVM2EVMOnRamp_getFee:test_MessageGasLimitTooHigh_Revert() (gas: 16733) +EVM2EVMOnRamp_getFee:test_MessageTooLarge_Revert() (gas: 95283) +EVM2EVMOnRamp_getFee:test_MessageWithDataAndTokenTransfer_Success() (gas: 160123) +EVM2EVMOnRamp_getFee:test_NotAFeeToken_Revert() (gas: 24113) +EVM2EVMOnRamp_getFee:test_SingleTokenMessage_Success() (gas: 118345) +EVM2EVMOnRamp_getFee:test_TooManyTokens_Revert() (gas: 19914) +EVM2EVMOnRamp_getFee:test_ZeroDataAvailabilityMultiplier_Success() (gas: 64726) EVM2EVMOnRamp_getSupportedTokens:test_GetSupportedTokens_Revert() (gas: 10460) EVM2EVMOnRamp_getTokenPool:test_GetTokenPool_Success() (gas: 35195) -EVM2EVMOnRamp_getTokenTransferCost:test_CustomTokenBpsFee_Success() (gas: 45120) -EVM2EVMOnRamp_getTokenTransferCost:test_FeeTokenBpsFee_Success() (gas: 33019) -EVM2EVMOnRamp_getTokenTransferCost:test_LargeTokenTransferChargesMaxFeeAndGas_Success() (gas: 28296) -EVM2EVMOnRamp_getTokenTransferCost:test_MixedTokenTransferFee_Success() (gas: 126453) -EVM2EVMOnRamp_getTokenTransferCost:test_NoTokenTransferChargesZeroFee_Success() (gas: 15238) -EVM2EVMOnRamp_getTokenTransferCost:test_SmallTokenTransferChargesMinFeeAndGas_Success() (gas: 28104) -EVM2EVMOnRamp_getTokenTransferCost:test_UnsupportedToken_Revert() (gas: 21248) -EVM2EVMOnRamp_getTokenTransferCost:test_ZeroAmountTokenTransferChargesMinFeeAndGas_Success() (gas: 28127) -EVM2EVMOnRamp_getTokenTransferCost:test_ZeroFeeConfigChargesMinFee_Success() (gas: 38599) -EVM2EVMOnRamp_getTokenTransferCost:test__getTokenTransferCost_selfServeUsesDefaults_Success() (gas: 29404) -EVM2EVMOnRamp_linkAvailableForPayment:test_InsufficientLinkBalance_Success() (gas: 32615) -EVM2EVMOnRamp_linkAvailableForPayment:test_LinkAvailableForPayment_Success() (gas: 134833) -EVM2EVMOnRamp_payNops:test_AdminPayNops_Success() (gas: 143159) -EVM2EVMOnRamp_payNops:test_InsufficientBalance_Revert() (gas: 29043) -EVM2EVMOnRamp_payNops:test_NoFeesToPay_Revert() (gas: 127367) -EVM2EVMOnRamp_payNops:test_NoNopsToPay_Revert() (gas: 133251) -EVM2EVMOnRamp_payNops:test_NopPayNops_Success() (gas: 146446) -EVM2EVMOnRamp_payNops:test_OwnerPayNops_Success() (gas: 141021) -EVM2EVMOnRamp_payNops:test_PayNopsSuccessAfterSetNops() (gas: 297519) -EVM2EVMOnRamp_payNops:test_WrongPermissions_Revert() (gas: 15294) -EVM2EVMOnRamp_setDynamicConfig:test_SetConfigInvalidConfig_Revert() (gas: 42365) -EVM2EVMOnRamp_setDynamicConfig:test_SetConfigOnlyOwner_Revert() (gas: 21246) -EVM2EVMOnRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 53764) -EVM2EVMOnRamp_setFeeTokenConfig:test_OnlyCallableByOwnerOrAdmin_Revert() (gas: 13464) -EVM2EVMOnRamp_setFeeTokenConfig:test_SetFeeTokenConfigByAdmin_Success() (gas: 16449) +EVM2EVMOnRamp_getTokenTransferCost:test_CustomTokenBpsFee_Success() (gas: 45198) +EVM2EVMOnRamp_getTokenTransferCost:test_FeeTokenBpsFee_Success() (gas: 33079) +EVM2EVMOnRamp_getTokenTransferCost:test_LargeTokenTransferChargesMaxFeeAndGas_Success() (gas: 28356) +EVM2EVMOnRamp_getTokenTransferCost:test_MixedTokenTransferFee_Success() (gas: 126939) +EVM2EVMOnRamp_getTokenTransferCost:test_NoTokenTransferChargesZeroFee_Success() (gas: 15250) +EVM2EVMOnRamp_getTokenTransferCost:test_SmallTokenTransferChargesMinFeeAndGas_Success() (gas: 28164) +EVM2EVMOnRamp_getTokenTransferCost:test_UnsupportedToken_Revert() (gas: 21260) +EVM2EVMOnRamp_getTokenTransferCost:test_ZeroAmountTokenTransferChargesMinFeeAndGas_Success() (gas: 28187) +EVM2EVMOnRamp_getTokenTransferCost:test_ZeroFeeConfigChargesMinFee_Success() (gas: 38638) +EVM2EVMOnRamp_getTokenTransferCost:test__getTokenTransferCost_selfServeUsesDefaults_Success() (gas: 29440) +EVM2EVMOnRamp_linkAvailableForPayment:test_InsufficientLinkBalance_Success() (gas: 32621) +EVM2EVMOnRamp_linkAvailableForPayment:test_LinkAvailableForPayment_Success() (gas: 134884) +EVM2EVMOnRamp_payNops:test_AdminPayNops_Success() (gas: 143210) +EVM2EVMOnRamp_payNops:test_InsufficientBalance_Revert() (gas: 29055) +EVM2EVMOnRamp_payNops:test_NoFeesToPay_Revert() (gas: 127424) +EVM2EVMOnRamp_payNops:test_NoNopsToPay_Revert() (gas: 133318) +EVM2EVMOnRamp_payNops:test_NopPayNops_Success() (gas: 146497) +EVM2EVMOnRamp_payNops:test_OwnerPayNops_Success() (gas: 141072) +EVM2EVMOnRamp_payNops:test_PayNopsSuccessAfterSetNops() (gas: 297651) +EVM2EVMOnRamp_payNops:test_WrongPermissions_Revert() (gas: 15300) +EVM2EVMOnRamp_setDynamicConfig:test_SetConfigInvalidConfig_Revert() (gas: 42377) +EVM2EVMOnRamp_setDynamicConfig:test_SetConfigOnlyOwner_Revert() (gas: 21258) +EVM2EVMOnRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 53782) +EVM2EVMOnRamp_setFeeTokenConfig:test_OnlyCallableByOwnerOrAdmin_Revert() (gas: 13470) +EVM2EVMOnRamp_setFeeTokenConfig:test_SetFeeTokenConfigByAdmin_Success() (gas: 16455) EVM2EVMOnRamp_setFeeTokenConfig:test_SetFeeTokenConfig_Success() (gas: 13994) -EVM2EVMOnRamp_setNops:test_AdminCanSetNops_Success() (gas: 61759) -EVM2EVMOnRamp_setNops:test_IncludesPayment_Success() (gas: 469227) -EVM2EVMOnRamp_setNops:test_LinkTokenCannotBeNop_Revert() (gas: 57255) -EVM2EVMOnRamp_setNops:test_NonOwnerOrAdmin_Revert() (gas: 14665) -EVM2EVMOnRamp_setNops:test_NotEnoughFundsForPayout_Revert() (gas: 84480) -EVM2EVMOnRamp_setNops:test_SetNopsRemovesOldNopsCompletely_Success() (gas: 60637) -EVM2EVMOnRamp_setNops:test_SetNops_Success() (gas: 173782) -EVM2EVMOnRamp_setNops:test_TooManyNops_Revert() (gas: 190338) -EVM2EVMOnRamp_setNops:test_ZeroAddressCannotBeNop_Revert() (gas: 53596) +EVM2EVMOnRamp_setNops:test_AdminCanSetNops_Success() (gas: 61785) +EVM2EVMOnRamp_setNops:test_IncludesPayment_Success() (gas: 469353) +EVM2EVMOnRamp_setNops:test_LinkTokenCannotBeNop_Revert() (gas: 57276) +EVM2EVMOnRamp_setNops:test_NonOwnerOrAdmin_Revert() (gas: 14677) +EVM2EVMOnRamp_setNops:test_NotEnoughFundsForPayout_Revert() (gas: 84528) +EVM2EVMOnRamp_setNops:test_SetNopsRemovesOldNopsCompletely_Success() (gas: 60673) +EVM2EVMOnRamp_setNops:test_SetNops_Success() (gas: 173821) +EVM2EVMOnRamp_setNops:test_TooManyNops_Revert() (gas: 190350) +EVM2EVMOnRamp_setNops:test_ZeroAddressCannotBeNop_Revert() (gas: 53617) EVM2EVMOnRamp_setTokenTransferFeeConfig:test__setTokenTransferFeeConfig_InvalidDestBytesOverhead_Revert() (gas: 14499) -EVM2EVMOnRamp_setTokenTransferFeeConfig:test__setTokenTransferFeeConfig_OnlyCallableByOwnerOrAdmin_Revert() (gas: 14277) -EVM2EVMOnRamp_setTokenTransferFeeConfig:test__setTokenTransferFeeConfig_Success() (gas: 84029) -EVM2EVMOnRamp_setTokenTransferFeeConfig:test__setTokenTransferFeeConfig_byAdmin_Success() (gas: 17369) -EVM2EVMOnRamp_withdrawNonLinkFees:test_LinkBalanceNotSettled_Revert() (gas: 83005) +EVM2EVMOnRamp_setTokenTransferFeeConfig:test__setTokenTransferFeeConfig_OnlyCallableByOwnerOrAdmin_Revert() (gas: 14283) +EVM2EVMOnRamp_setTokenTransferFeeConfig:test__setTokenTransferFeeConfig_Success() (gas: 84107) +EVM2EVMOnRamp_setTokenTransferFeeConfig:test__setTokenTransferFeeConfig_byAdmin_Success() (gas: 17375) +EVM2EVMOnRamp_withdrawNonLinkFees:test_LinkBalanceNotSettled_Revert() (gas: 83035) EVM2EVMOnRamp_withdrawNonLinkFees:test_NonOwnerOrAdmin_Revert() (gas: 15275) -EVM2EVMOnRamp_withdrawNonLinkFees:test_SettlingBalance_Success() (gas: 272035) -EVM2EVMOnRamp_withdrawNonLinkFees:test_WithdrawNonLinkFees_Success() (gas: 53446) +EVM2EVMOnRamp_withdrawNonLinkFees:test_SettlingBalance_Success() (gas: 272083) +EVM2EVMOnRamp_withdrawNonLinkFees:test_WithdrawNonLinkFees_Success() (gas: 53458) EVM2EVMOnRamp_withdrawNonLinkFees:test_WithdrawToZeroAddress_Revert() (gas: 12830) -EtherSenderReceiverTest_ccipReceive:test_ccipReceive_fallbackToWethTransfer() (gas: 96729) -EtherSenderReceiverTest_ccipReceive:test_ccipReceive_happyPath() (gas: 49688) -EtherSenderReceiverTest_ccipReceive:test_ccipReceive_wrongToken() (gas: 17384) -EtherSenderReceiverTest_ccipReceive:test_ccipReceive_wrongTokenAmount() (gas: 15677) -EtherSenderReceiverTest_ccipSend:test_ccipSend_reverts_insufficientFee_feeToken() (gas: 99741) -EtherSenderReceiverTest_ccipSend:test_ccipSend_reverts_insufficientFee_native() (gas: 76096) -EtherSenderReceiverTest_ccipSend:test_ccipSend_reverts_insufficientFee_weth() (gas: 99748) -EtherSenderReceiverTest_ccipSend:test_ccipSend_success_feeToken() (gas: 144569) -EtherSenderReceiverTest_ccipSend:test_ccipSend_success_native() (gas: 80259) -EtherSenderReceiverTest_ccipSend:test_ccipSend_success_nativeExcess() (gas: 80446) -EtherSenderReceiverTest_ccipSend:test_ccipSend_success_weth() (gas: 95713) -EtherSenderReceiverTest_constructor:test_constructor() (gas: 17511) -EtherSenderReceiverTest_getFee:test_getFee() (gas: 27289) -EtherSenderReceiverTest_validateFeeToken:test_validateFeeToken_reverts_feeToken_tokenAmountNotEqualToMsgValue() (gas: 20333) -EtherSenderReceiverTest_validateFeeToken:test_validateFeeToken_valid_feeToken() (gas: 16715) -EtherSenderReceiverTest_validateFeeToken:test_validateFeeToken_valid_native() (gas: 16654) +EtherSenderReceiverTest_ccipReceive:test_ccipReceive_fallbackToWethTransfer() (gas: 96892) +EtherSenderReceiverTest_ccipReceive:test_ccipReceive_happyPath() (gas: 49770) +EtherSenderReceiverTest_ccipReceive:test_ccipReceive_wrongToken() (gas: 17423) +EtherSenderReceiverTest_ccipReceive:test_ccipReceive_wrongTokenAmount() (gas: 15716) +EtherSenderReceiverTest_ccipSend:test_ccipSend_reverts_insufficientFee_feeToken() (gas: 99831) +EtherSenderReceiverTest_ccipSend:test_ccipSend_reverts_insufficientFee_native() (gas: 76099) +EtherSenderReceiverTest_ccipSend:test_ccipSend_reverts_insufficientFee_weth() (gas: 99853) +EtherSenderReceiverTest_ccipSend:test_ccipSend_success_feeToken() (gas: 144833) +EtherSenderReceiverTest_ccipSend:test_ccipSend_success_native() (gas: 80262) +EtherSenderReceiverTest_ccipSend:test_ccipSend_success_nativeExcess() (gas: 80449) +EtherSenderReceiverTest_ccipSend:test_ccipSend_success_weth() (gas: 95902) +EtherSenderReceiverTest_constructor:test_constructor() (gas: 17535) +EtherSenderReceiverTest_getFee:test_getFee() (gas: 27316) +EtherSenderReceiverTest_validateFeeToken:test_validateFeeToken_reverts_feeToken_tokenAmountNotEqualToMsgValue() (gas: 20363) +EtherSenderReceiverTest_validateFeeToken:test_validateFeeToken_valid_feeToken() (gas: 16718) +EtherSenderReceiverTest_validateFeeToken:test_validateFeeToken_valid_native() (gas: 16657) EtherSenderReceiverTest_validatedMessage:test_validatedMessage_dataOverwrittenToMsgSender() (gas: 25415) EtherSenderReceiverTest_validatedMessage:test_validatedMessage_emptyDataOverwrittenToMsgSender() (gas: 25265) -EtherSenderReceiverTest_validatedMessage:test_validatedMessage_invalidTokenAmounts() (gas: 17895) +EtherSenderReceiverTest_validatedMessage:test_validatedMessage_invalidTokenAmounts() (gas: 17907) EtherSenderReceiverTest_validatedMessage:test_validatedMessage_tokenOverwrittenToWeth() (gas: 25287) -EtherSenderReceiverTest_validatedMessage:test_validatedMessage_validMessage_extraArgs() (gas: 26292) -FeeQuoter_applyDestChainConfigUpdates:test_InvalidChainFamilySelector_Revert() (gas: 16503) -FeeQuoter_applyDestChainConfigUpdates:test_InvalidDestChainConfigDestChainSelectorEqZero_Revert() (gas: 16417) -FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesDefaultTxGasLimitEqZero_Revert() (gas: 16459) -FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesDefaultTxGasLimitGtMaxPerMessageGasLimit_Revert() (gas: 39957) +EtherSenderReceiverTest_validatedMessage:test_validatedMessage_validMessage_extraArgs() (gas: 26316) +FeeQuoter_applyDestChainConfigUpdates:test_InvalidChainFamilySelector_Revert() (gas: 16509) +FeeQuoter_applyDestChainConfigUpdates:test_InvalidDestChainConfigDestChainSelectorEqZero_Revert() (gas: 16423) +FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesDefaultTxGasLimitEqZero_Revert() (gas: 16465) +FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesDefaultTxGasLimitGtMaxPerMessageGasLimit_Revert() (gas: 39969) FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesZeroIntput_Success() (gas: 12342) -FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdates_Success() (gas: 135870) -FeeQuoter_applyFeeTokensUpdates:test_ApplyFeeTokensUpdates_Success() (gas: 79896) -FeeQuoter_applyFeeTokensUpdates:test_OnlyCallableByOwner_Revert() (gas: 12603) -FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_OnlyCallableByOwnerOrAdmin_Revert() (gas: 11421) -FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesMultipleTokens_Success() (gas: 54105) -FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesSingleToken_Success() (gas: 44791) +FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdates_Success() (gas: 135942) +FeeQuoter_applyFeeTokensUpdates:test_ApplyFeeTokensUpdates_Success() (gas: 79906) +FeeQuoter_applyFeeTokensUpdates:test_OnlyCallableByOwner_Revert() (gas: 12615) +FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_OnlyCallableByOwnerOrAdmin_Revert() (gas: 11433) +FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesMultipleTokens_Success() (gas: 54213) +FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesSingleToken_Success() (gas: 44857) FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesZeroInput() (gas: 12257) -FeeQuoter_applyTokenTransferFeeConfigUpdates:test_ApplyTokenTransferFeeConfig_Success() (gas: 86926) +FeeQuoter_applyTokenTransferFeeConfigUpdates:test_ApplyTokenTransferFeeConfig_Success() (gas: 86968) FeeQuoter_applyTokenTransferFeeConfigUpdates:test_ApplyTokenTransferFeeZeroInput() (gas: 13089) FeeQuoter_applyTokenTransferFeeConfigUpdates:test_InvalidDestBytesOverhead_Revert() (gas: 17071) -FeeQuoter_applyTokenTransferFeeConfigUpdates:test_OnlyCallableByOwnerOrAdmin_Revert() (gas: 12240) -FeeQuoter_constructor:test_InvalidLinkTokenEqZeroAddress_Revert() (gas: 107046) -FeeQuoter_constructor:test_InvalidMaxFeeJuelsPerMsg_Revert() (gas: 111396) -FeeQuoter_constructor:test_InvalidStalenessThreshold_Revert() (gas: 111449) -FeeQuoter_constructor:test_Setup_Success() (gas: 5355882) -FeeQuoter_convertTokenAmount:test_ConvertTokenAmount_Success() (gas: 72739) -FeeQuoter_convertTokenAmount:test_LinkTokenNotSupported_Revert() (gas: 30963) -FeeQuoter_getDataAvailabilityCost:test_EmptyMessageCalculatesDataAvailabilityCost_Success() (gas: 94303) -FeeQuoter_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCostUnsupportedDestChainSelector_Success() (gas: 14614) -FeeQuoter_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCost_Success() (gas: 20410) -FeeQuoter_getTokenAndGasPrices:test_GetFeeTokenAndGasPrices_Success() (gas: 70458) +FeeQuoter_applyTokenTransferFeeConfigUpdates:test_OnlyCallableByOwnerOrAdmin_Revert() (gas: 12246) +FeeQuoter_constructor:test_InvalidLinkTokenEqZeroAddress_Revert() (gas: 106810) +FeeQuoter_constructor:test_InvalidMaxFeeJuelsPerMsg_Revert() (gas: 111160) +FeeQuoter_constructor:test_InvalidStalenessThreshold_Revert() (gas: 111213) +FeeQuoter_constructor:test_Setup_Success() (gas: 5195512) +FeeQuoter_convertTokenAmount:test_ConvertTokenAmount_Success() (gas: 72751) +FeeQuoter_convertTokenAmount:test_LinkTokenNotSupported_Revert() (gas: 30981) +FeeQuoter_getDataAvailabilityCost:test_EmptyMessageCalculatesDataAvailabilityCost_Success() (gas: 94441) +FeeQuoter_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCostUnsupportedDestChainSelector_Success() (gas: 14650) +FeeQuoter_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCost_Success() (gas: 20482) +FeeQuoter_getTokenAndGasPrices:test_GetFeeTokenAndGasPrices_Success() (gas: 70464) FeeQuoter_getTokenAndGasPrices:test_StaleGasPrice_Revert() (gas: 16838) FeeQuoter_getTokenAndGasPrices:test_UnsupportedChain_Revert() (gas: 16140) -FeeQuoter_getTokenAndGasPrices:test_ZeroGasPrice_Success() (gas: 45765) -FeeQuoter_getTokenPrice:test_GetTokenPriceFromFeed_Success() (gas: 62252) -FeeQuoter_getTokenPrices:test_GetTokenPrices_Success() (gas: 84800) -FeeQuoter_getTokenTransferCost:test_CustomTokenBpsFee_Success() (gas: 41227) -FeeQuoter_getTokenTransferCost:test_FeeTokenBpsFee_Success() (gas: 34682) -FeeQuoter_getTokenTransferCost:test_LargeTokenTransferChargesMaxFeeAndGas_Success() (gas: 27756) -FeeQuoter_getTokenTransferCost:test_MixedTokenTransferFee_Success() (gas: 101624) -FeeQuoter_getTokenTransferCost:test_NoTokenTransferChargesZeroFee_Success() (gas: 20354) -FeeQuoter_getTokenTransferCost:test_SmallTokenTransferChargesMinFeeAndGas_Success() (gas: 27631) -FeeQuoter_getTokenTransferCost:test_ZeroAmountTokenTransferChargesMinFeeAndGas_Success() (gas: 27587) -FeeQuoter_getTokenTransferCost:test_ZeroFeeConfigChargesMinFee_Success() (gas: 40013) -FeeQuoter_getTokenTransferCost:test_getTokenTransferCost_selfServeUsesDefaults_Success() (gas: 29299) -FeeQuoter_getValidatedFee:test_DestinationChainNotEnabled_Revert() (gas: 18180) -FeeQuoter_getValidatedFee:test_EmptyMessage_Success() (gas: 85919) -FeeQuoter_getValidatedFee:test_EnforceOutOfOrder_Revert() (gas: 54345) -FeeQuoter_getValidatedFee:test_HighGasMessage_Success() (gas: 242337) -FeeQuoter_getValidatedFee:test_InvalidEVMAddress_Revert() (gas: 22390) -FeeQuoter_getValidatedFee:test_MessageGasLimitTooHigh_Revert() (gas: 31797) -FeeQuoter_getValidatedFee:test_MessageTooLarge_Revert() (gas: 100133) -FeeQuoter_getValidatedFee:test_MessageWithDataAndTokenTransfer_Success() (gas: 147680) -FeeQuoter_getValidatedFee:test_NotAFeeToken_Revert() (gas: 21043) -FeeQuoter_getValidatedFee:test_SingleTokenMessage_Success() (gas: 116708) -FeeQuoter_getValidatedFee:test_TooManyTokens_Revert() (gas: 22526) -FeeQuoter_getValidatedFee:test_ZeroDataAvailabilityMultiplier_Success() (gas: 64364) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Above18Decimals_Success() (gas: 2094539) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Below18Decimals_Success() (gas: 2094497) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt0Decimals_Success() (gas: 2074616) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt18Decimals_Success() (gas: 2094271) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFlippedDecimals_Success() (gas: 2094475) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedMaxInt224Value_Success() (gas: 2094287) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedOverStalenessPeriod_Success() (gas: 62004) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeed_Success() (gas: 61884) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPrice_Success() (gas: 61036) -FeeQuoter_getValidatedTokenPrice:test_OverflowFeedPrice_Revert() (gas: 2093974) -FeeQuoter_getValidatedTokenPrice:test_StaleFeeToken_Success() (gas: 61563) -FeeQuoter_getValidatedTokenPrice:test_TokenNotSupportedFeed_Revert() (gas: 109120) -FeeQuoter_getValidatedTokenPrice:test_TokenNotSupported_Revert() (gas: 13857) -FeeQuoter_getValidatedTokenPrice:test_UnderflowFeedPrice_Revert() (gas: 2092636) -FeeQuoter_onReport:test_OnReport_StaleUpdate_Revert() (gas: 43334) -FeeQuoter_onReport:test_onReport_InvalidForwarder_Reverts() (gas: 23294) -FeeQuoter_onReport:test_onReport_Success() (gas: 80639) -FeeQuoter_onReport:test_onReport_UnsupportedToken_Reverts() (gas: 26677) -FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsDefault_Success() (gas: 17185) -FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsEnforceOutOfOrder_Revert() (gas: 21290) -FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsGasLimitTooHigh_Revert() (gas: 18387) -FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsInvalidExtraArgsTag_Revert() (gas: 17911) -FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsV1_Success() (gas: 18285) -FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsV2_Success() (gas: 18401) +FeeQuoter_getTokenAndGasPrices:test_ZeroGasPrice_Success() (gas: 45771) +FeeQuoter_getTokenPrice:test_GetTokenPriceFromFeed_Success() (gas: 62264) +FeeQuoter_getTokenPrices:test_GetTokenPrices_Success() (gas: 84818) +FeeQuoter_getTokenTransferCost:test_CustomTokenBpsFee_Success() (gas: 41281) +FeeQuoter_getTokenTransferCost:test_FeeTokenBpsFee_Success() (gas: 34730) +FeeQuoter_getTokenTransferCost:test_LargeTokenTransferChargesMaxFeeAndGas_Success() (gas: 27804) +FeeQuoter_getTokenTransferCost:test_MixedTokenTransferFee_Success() (gas: 101864) +FeeQuoter_getTokenTransferCost:test_NoTokenTransferChargesZeroFee_Success() (gas: 20390) +FeeQuoter_getTokenTransferCost:test_SmallTokenTransferChargesMinFeeAndGas_Success() (gas: 27679) +FeeQuoter_getTokenTransferCost:test_ZeroAmountTokenTransferChargesMinFeeAndGas_Success() (gas: 27635) +FeeQuoter_getTokenTransferCost:test_ZeroFeeConfigChargesMinFee_Success() (gas: 40064) +FeeQuoter_getTokenTransferCost:test_getTokenTransferCost_selfServeUsesDefaults_Success() (gas: 29347) +FeeQuoter_getValidatedFee:test_DestinationChainNotEnabled_Revert() (gas: 18210) +FeeQuoter_getValidatedFee:test_EmptyMessage_Success() (gas: 86123) +FeeQuoter_getValidatedFee:test_EnforceOutOfOrder_Revert() (gas: 54405) +FeeQuoter_getValidatedFee:test_HighGasMessage_Success() (gas: 242541) +FeeQuoter_getValidatedFee:test_InvalidEVMAddress_Revert() (gas: 22420) +FeeQuoter_getValidatedFee:test_MessageGasLimitTooHigh_Revert() (gas: 31833) +FeeQuoter_getValidatedFee:test_MessageTooLarge_Revert() (gas: 100163) +FeeQuoter_getValidatedFee:test_MessageWithDataAndTokenTransfer_Success() (gas: 148076) +FeeQuoter_getValidatedFee:test_NotAFeeToken_Revert() (gas: 21073) +FeeQuoter_getValidatedFee:test_SingleTokenMessage_Success() (gas: 117032) +FeeQuoter_getValidatedFee:test_TooManyTokens_Revert() (gas: 22562) +FeeQuoter_getValidatedFee:test_ZeroDataAvailabilityMultiplier_Success() (gas: 64442) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Above18Decimals_Success() (gas: 2076337) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Below18Decimals_Success() (gas: 2076295) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt0Decimals_Success() (gas: 2056414) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt18Decimals_Success() (gas: 2076069) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFlippedDecimals_Success() (gas: 2076273) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedMaxInt224Value_Success() (gas: 2076085) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedOverStalenessPeriod_Success() (gas: 62016) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeed_Success() (gas: 61896) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPrice_Success() (gas: 61042) +FeeQuoter_getValidatedTokenPrice:test_OverflowFeedPrice_Revert() (gas: 2075772) +FeeQuoter_getValidatedTokenPrice:test_StaleFeeToken_Success() (gas: 61569) +FeeQuoter_getValidatedTokenPrice:test_TokenNotSupportedFeed_Revert() (gas: 109132) +FeeQuoter_getValidatedTokenPrice:test_TokenNotSupported_Revert() (gas: 13863) +FeeQuoter_getValidatedTokenPrice:test_UnderflowFeedPrice_Revert() (gas: 2074434) +FeeQuoter_onReport:test_OnReport_StaleUpdate_Revert() (gas: 43358) +FeeQuoter_onReport:test_onReport_InvalidForwarder_Reverts() (gas: 23306) +FeeQuoter_onReport:test_onReport_Success() (gas: 80684) +FeeQuoter_onReport:test_onReport_UnsupportedToken_Reverts() (gas: 26692) +FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsDefault_Success() (gas: 17191) +FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsEnforceOutOfOrder_Revert() (gas: 21302) +FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsGasLimitTooHigh_Revert() (gas: 18399) +FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsInvalidExtraArgsTag_Revert() (gas: 17923) +FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsV1_Success() (gas: 18291) +FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsV2_Success() (gas: 18407) FeeQuoter_processMessageArgs:test_InvalidExtraArgs_Revert() (gas: 18361) FeeQuoter_processMessageArgs:test_MalformedEVMExtraArgs_Revert() (gas: 18907) FeeQuoter_processMessageArgs:test_MessageFeeTooHigh_Revert() (gas: 16426) -FeeQuoter_processMessageArgs:test_WitEVMExtraArgsV2_Success() (gas: 26269) -FeeQuoter_processMessageArgs:test_WithConvertedTokenAmount_Success() (gas: 32441) -FeeQuoter_processMessageArgs:test_WithEVMExtraArgsV1_Success() (gas: 25881) -FeeQuoter_processMessageArgs:test_WithEmptyEVMExtraArgs_Success() (gas: 23696) +FeeQuoter_processMessageArgs:test_WitEVMExtraArgsV2_Success() (gas: 26299) +FeeQuoter_processMessageArgs:test_WithConvertedTokenAmount_Success() (gas: 32465) +FeeQuoter_processMessageArgs:test_WithEVMExtraArgsV1_Success() (gas: 25911) +FeeQuoter_processMessageArgs:test_WithEmptyEVMExtraArgs_Success() (gas: 23726) FeeQuoter_processMessageArgs:test_WithLinkTokenAmount_Success() (gas: 17375) -FeeQuoter_updatePrices:test_OnlyCallableByUpdater_Revert() (gas: 12102) +FeeQuoter_updatePrices:test_OnlyCallableByUpdater_Revert() (gas: 12114) FeeQuoter_updatePrices:test_OnlyGasPrice_Success() (gas: 23599) -FeeQuoter_updatePrices:test_OnlyTokenPrice_Success() (gas: 30631) -FeeQuoter_updatePrices:test_UpdatableByAuthorizedCaller_Success() (gas: 76003) -FeeQuoter_updatePrices:test_UpdateMultiplePrices_Success() (gas: 151393) -FeeQuoter_updateTokenPriceFeeds:test_FeedNotUpdated() (gas: 50527) -FeeQuoter_updateTokenPriceFeeds:test_FeedUnset_Success() (gas: 63626) -FeeQuoter_updateTokenPriceFeeds:test_FeedUpdatedByNonOwner_Revert() (gas: 19932) -FeeQuoter_updateTokenPriceFeeds:test_MultipleFeedUpdate_Success() (gas: 88972) -FeeQuoter_updateTokenPriceFeeds:test_SingleFeedUpdate_Success() (gas: 50821) +FeeQuoter_updatePrices:test_OnlyTokenPrice_Success() (gas: 30637) +FeeQuoter_updatePrices:test_UpdatableByAuthorizedCaller_Success() (gas: 76027) +FeeQuoter_updatePrices:test_UpdateMultiplePrices_Success() (gas: 151411) +FeeQuoter_updateTokenPriceFeeds:test_FeedNotUpdated() (gas: 50545) +FeeQuoter_updateTokenPriceFeeds:test_FeedUnset_Success() (gas: 63662) +FeeQuoter_updateTokenPriceFeeds:test_FeedUpdatedByNonOwner_Revert() (gas: 19938) +FeeQuoter_updateTokenPriceFeeds:test_MultipleFeedUpdate_Success() (gas: 89008) +FeeQuoter_updateTokenPriceFeeds:test_SingleFeedUpdate_Success() (gas: 50839) FeeQuoter_updateTokenPriceFeeds:test_ZeroFeeds_Success() (gas: 12296) -FeeQuoter_validateDestFamilyAddress:test_InvalidEVMAddressEncodePacked_Revert() (gas: 10616) -FeeQuoter_validateDestFamilyAddress:test_InvalidEVMAddressPrecompiles_Revert() (gas: 3961646) -FeeQuoter_validateDestFamilyAddress:test_InvalidEVMAddress_Revert() (gas: 10800) -FeeQuoter_validateDestFamilyAddress:test_ValidEVMAddress_Success() (gas: 6704) +FeeQuoter_validateDestFamilyAddress:test_InvalidEVMAddressEncodePacked_Revert() (gas: 10622) +FeeQuoter_validateDestFamilyAddress:test_InvalidEVMAddressPrecompiles_Revert() (gas: 3967790) +FeeQuoter_validateDestFamilyAddress:test_InvalidEVMAddress_Revert() (gas: 10806) +FeeQuoter_validateDestFamilyAddress:test_ValidEVMAddress_Success() (gas: 6710) FeeQuoter_validateDestFamilyAddress:test_ValidNonEVMAddress_Success() (gas: 6484) -FeeQuoter_validatePoolReturnData:test_InvalidEVMAddressDestToken_Revert() (gas: 42748) -FeeQuoter_validatePoolReturnData:test_ProcessPoolReturnData_Success() (gas: 73252) -FeeQuoter_validatePoolReturnData:test_SourceTokenDataTooLarge_Revert() (gas: 107744) -FeeQuoter_validatePoolReturnData:test_TokenAmountArraysMismatching_Revert() (gas: 40091) -HybridUSDCTokenPoolMigrationTests:test_LockOrBurn_LocKReleaseMechanism_then_switchToPrimary_Success() (gas: 208156) -HybridUSDCTokenPoolMigrationTests:test_LockOrBurn_PrimaryMechanism_Success() (gas: 135401) -HybridUSDCTokenPoolMigrationTests:test_LockOrBurn_WhileMigrationPause_Revert() (gas: 106633) -HybridUSDCTokenPoolMigrationTests:test_LockOrBurn_onLockReleaseMechanism_Success() (gas: 143893) -HybridUSDCTokenPoolMigrationTests:test_MintOrRelease_OnLockReleaseMechanism_Success() (gas: 230396) -HybridUSDCTokenPoolMigrationTests:test_MintOrRelease_OnLockReleaseMechanism_then_switchToPrimary_Success() (gas: 438277) -HybridUSDCTokenPoolMigrationTests:test_MintOrRelease_incomingMessageWithPrimaryMechanism() (gas: 269985) -HybridUSDCTokenPoolMigrationTests:test_burnLockedUSDC_invalidPermissions_Revert() (gas: 39124) -HybridUSDCTokenPoolMigrationTests:test_cancelExistingCCTPMigrationProposal() (gas: 31124) +FeeQuoter_validatePoolReturnData:test_InvalidEVMAddressDestToken_Revert() (gas: 42769) +FeeQuoter_validatePoolReturnData:test_ProcessPoolReturnData_Success() (gas: 73306) +FeeQuoter_validatePoolReturnData:test_SourceTokenDataTooLarge_Revert() (gas: 107855) +FeeQuoter_validatePoolReturnData:test_TokenAmountArraysMismatching_Revert() (gas: 40106) +HybridUSDCTokenPoolMigrationTests:test_LockOrBurn_LocKReleaseMechanism_then_switchToPrimary_Success() (gas: 208384) +HybridUSDCTokenPoolMigrationTests:test_LockOrBurn_PrimaryMechanism_Success() (gas: 135502) +HybridUSDCTokenPoolMigrationTests:test_LockOrBurn_WhileMigrationPause_Revert() (gas: 106651) +HybridUSDCTokenPoolMigrationTests:test_LockOrBurn_onLockReleaseMechanism_Success() (gas: 143944) +HybridUSDCTokenPoolMigrationTests:test_MintOrRelease_OnLockReleaseMechanism_Success() (gas: 230450) +HybridUSDCTokenPoolMigrationTests:test_MintOrRelease_OnLockReleaseMechanism_then_switchToPrimary_Success() (gas: 438517) +HybridUSDCTokenPoolMigrationTests:test_MintOrRelease_incomingMessageWithPrimaryMechanism() (gas: 270081) +HybridUSDCTokenPoolMigrationTests:test_burnLockedUSDC_invalidPermissions_Revert() (gas: 39130) +HybridUSDCTokenPoolMigrationTests:test_cancelExistingCCTPMigrationProposal() (gas: 31181) HybridUSDCTokenPoolMigrationTests:test_cannotCancelANonExistentMigrationProposal() (gas: 12628) -HybridUSDCTokenPoolMigrationTests:test_cannotModifyLiquidityWithoutPermissions_Revert() (gas: 17134) -HybridUSDCTokenPoolMigrationTests:test_lockOrBurn_then_BurnInCCTPMigration_Success() (gas: 252452) -HybridUSDCTokenPoolMigrationTests:test_transferLiquidity_Success() (gas: 157049) -HybridUSDCTokenPoolMigrationTests:test_withdrawLiquidity_Success() (gas: 140780) -HybridUSDCTokenPoolTests:test_LockOrBurn_LocKReleaseMechanism_then_switchToPrimary_Success() (gas: 208121) -HybridUSDCTokenPoolTests:test_LockOrBurn_PrimaryMechanism_Success() (gas: 135375) -HybridUSDCTokenPoolTests:test_LockOrBurn_WhileMigrationPause_Revert() (gas: 106610) -HybridUSDCTokenPoolTests:test_LockOrBurn_onLockReleaseMechanism_Success() (gas: 143841) -HybridUSDCTokenPoolTests:test_MintOrRelease_OnLockReleaseMechanism_Success() (gas: 230362) -HybridUSDCTokenPoolTests:test_MintOrRelease_OnLockReleaseMechanism_then_switchToPrimary_Success() (gas: 438237) -HybridUSDCTokenPoolTests:test_MintOrRelease_incomingMessageWithPrimaryMechanism() (gas: 269968) -HybridUSDCTokenPoolTests:test_withdrawLiquidity_Success() (gas: 140774) -LockReleaseTokenPoolAndProxy_setRebalancer:test_SetRebalancer_Revert() (gas: 10971) -LockReleaseTokenPoolAndProxy_setRebalancer:test_SetRebalancer_Success() (gas: 17992) -LockReleaseTokenPoolPoolAndProxy_canAcceptLiquidity:test_CanAcceptLiquidity_Success() (gas: 3368113) -LockReleaseTokenPoolPoolAndProxy_provideLiquidity:test_LiquidityNotAccepted_Revert() (gas: 3364513) -LockReleaseTokenPoolPoolAndProxy_provideLiquidity:test_Unauthorized_Revert() (gas: 11381) +HybridUSDCTokenPoolMigrationTests:test_cannotModifyLiquidityWithoutPermissions_Revert() (gas: 17158) +HybridUSDCTokenPoolMigrationTests:test_lockOrBurn_then_BurnInCCTPMigration_Success() (gas: 252682) +HybridUSDCTokenPoolMigrationTests:test_transferLiquidity_Success() (gas: 157130) +HybridUSDCTokenPoolMigrationTests:test_withdrawLiquidity_Success() (gas: 140828) +HybridUSDCTokenPoolTests:test_LockOrBurn_LocKReleaseMechanism_then_switchToPrimary_Success() (gas: 208164) +HybridUSDCTokenPoolTests:test_LockOrBurn_PrimaryMechanism_Success() (gas: 135396) +HybridUSDCTokenPoolTests:test_LockOrBurn_WhileMigrationPause_Revert() (gas: 106628) +HybridUSDCTokenPoolTests:test_LockOrBurn_onLockReleaseMechanism_Success() (gas: 143865) +HybridUSDCTokenPoolTests:test_MintOrRelease_OnLockReleaseMechanism_Success() (gas: 230383) +HybridUSDCTokenPoolTests:test_MintOrRelease_OnLockReleaseMechanism_then_switchToPrimary_Success() (gas: 438318) +HybridUSDCTokenPoolTests:test_MintOrRelease_incomingMessageWithPrimaryMechanism() (gas: 270011) +HybridUSDCTokenPoolTests:test_withdrawLiquidity_Success() (gas: 140783) +LockReleaseTokenPoolAndProxy_setRebalancer:test_SetRebalancer_Revert() (gas: 10977) +LockReleaseTokenPoolAndProxy_setRebalancer:test_SetRebalancer_Success() (gas: 17998) +LockReleaseTokenPoolPoolAndProxy_canAcceptLiquidity:test_CanAcceptLiquidity_Success() (gas: 3315195) +LockReleaseTokenPoolPoolAndProxy_provideLiquidity:test_LiquidityNotAccepted_Revert() (gas: 3311601) +LockReleaseTokenPoolPoolAndProxy_provideLiquidity:test_Unauthorized_Revert() (gas: 11405) LockReleaseTokenPoolPoolAndProxy_supportsInterface:test_SupportsInterface_Success() (gas: 9977) -LockReleaseTokenPoolPoolAndProxy_withdrawalLiquidity:test_InsufficientLiquidity_Revert() (gas: 60043) -LockReleaseTokenPoolPoolAndProxy_withdrawalLiquidity:test_Unauthorized_Revert() (gas: 11356) -LockReleaseTokenPool_canAcceptLiquidity:test_CanAcceptLiquidity_Success() (gas: 3124822) -LockReleaseTokenPool_lockOrBurn:test_LockOrBurnWithAllowList_Revert() (gas: 29954) -LockReleaseTokenPool_lockOrBurn:test_LockOrBurnWithAllowList_Success() (gas: 79844) -LockReleaseTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 59464) -LockReleaseTokenPool_provideLiquidity:test_LiquidityNotAccepted_Revert() (gas: 3121265) -LockReleaseTokenPool_provideLiquidity:test_Unauthorized_Revert() (gas: 11381) -LockReleaseTokenPool_releaseOrMint:test_ChainNotAllowed_Revert() (gas: 72654) -LockReleaseTokenPool_releaseOrMint:test_PoolMintNotHealthy_Revert() (gas: 56196) -LockReleaseTokenPool_releaseOrMint:test_ReleaseOrMint_Success() (gas: 225137) -LockReleaseTokenPool_setRebalancer:test_SetRebalancer_Revert() (gas: 10993) -LockReleaseTokenPool_setRebalancer:test_SetRebalancer_Success() (gas: 18058) +LockReleaseTokenPoolPoolAndProxy_withdrawalLiquidity:test_InsufficientLiquidity_Revert() (gas: 60060) +LockReleaseTokenPoolPoolAndProxy_withdrawalLiquidity:test_Unauthorized_Revert() (gas: 11386) +LockReleaseTokenPool_canAcceptLiquidity:test_CanAcceptLiquidity_Success() (gas: 3071906) +LockReleaseTokenPool_lockOrBurn:test_LockOrBurnWithAllowList_Revert() (gas: 29960) +LockReleaseTokenPool_lockOrBurn:test_LockOrBurnWithAllowList_Success() (gas: 79868) +LockReleaseTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 59479) +LockReleaseTokenPool_provideLiquidity:test_LiquidityNotAccepted_Revert() (gas: 3068356) +LockReleaseTokenPool_provideLiquidity:test_Unauthorized_Revert() (gas: 11405) +LockReleaseTokenPool_releaseOrMint:test_ChainNotAllowed_Revert() (gas: 72666) +LockReleaseTokenPool_releaseOrMint:test_PoolMintNotHealthy_Revert() (gas: 56211) +LockReleaseTokenPool_releaseOrMint:test_ReleaseOrMint_Success() (gas: 225296) +LockReleaseTokenPool_setRebalancer:test_SetRebalancer_Revert() (gas: 10999) +LockReleaseTokenPool_setRebalancer:test_SetRebalancer_Success() (gas: 18064) LockReleaseTokenPool_supportsInterface:test_SupportsInterface_Success() (gas: 9977) -LockReleaseTokenPool_transferLiquidity:test_transferLiquidity_Success() (gas: 83171) -LockReleaseTokenPool_transferLiquidity:test_transferLiquidity_transferTooMuch_Revert() (gas: 55878) -LockReleaseTokenPool_withdrawalLiquidity:test_InsufficientLiquidity_Revert() (gas: 60043) -LockReleaseTokenPool_withdrawalLiquidity:test_Unauthorized_Revert() (gas: 11356) -LockRelease_setRateLimitAdmin:test_SetRateLimitAdmin_Revert() (gas: 11030) +LockReleaseTokenPool_transferLiquidity:test_transferLiquidity_Success() (gas: 83177) +LockReleaseTokenPool_transferLiquidity:test_transferLiquidity_transferTooMuch_Revert() (gas: 55899) +LockReleaseTokenPool_withdrawalLiquidity:test_InsufficientLiquidity_Revert() (gas: 60060) +LockReleaseTokenPool_withdrawalLiquidity:test_Unauthorized_Revert() (gas: 11386) +LockRelease_setRateLimitAdmin:test_SetRateLimitAdmin_Revert() (gas: 11036) LockRelease_setRateLimitAdmin:test_SetRateLimitAdmin_Success() (gas: 35030) -MerkleMultiProofTest:test_CVE_2023_34459() (gas: 5451) -MerkleMultiProofTest:test_EmptyLeaf_Revert() (gas: 3552) -MerkleMultiProofTest:test_MerkleRoot256() (gas: 394876) +MerkleMultiProofTest:test_CVE_2023_34459() (gas: 5454) +MerkleMultiProofTest:test_EmptyLeaf_Revert() (gas: 3555) +MerkleMultiProofTest:test_MerkleRoot256() (gas: 394879) MerkleMultiProofTest:test_MerkleRootSingleLeaf_Success() (gas: 3649) MerkleMultiProofTest:test_SpecSync_gas() (gas: 34123) -MockRouterTest:test_ccipSendWithInsufficientNativeTokens_Revert() (gas: 33965) -MockRouterTest:test_ccipSendWithInvalidMsgValue_Revert() (gas: 60758) -MockRouterTest:test_ccipSendWithLinkFeeTokenAndValidMsgValue_Success() (gas: 126306) -MockRouterTest:test_ccipSendWithLinkFeeTokenbutInsufficientAllowance_Revert() (gas: 63302) -MockRouterTest:test_ccipSendWithSufficientNativeFeeTokens_Success() (gas: 43853) -MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_MultipleConfigsBothLanes_Success() (gas: 132031) -MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_MultipleConfigs_Success() (gas: 312057) -MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_OnlyCallableByOwner_Revert() (gas: 17717) -MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_SingleConfigOutbound_Success() (gas: 75784) -MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_SingleConfig_Success() (gas: 75700) -MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_UpdateExistingConfigWithNoDifference_Success() (gas: 38133) -MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_UpdateExistingConfig_Success() (gas: 53092) -MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_ZeroChainSelector_Revert() (gas: 17019) -MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_ZeroConfigs_Success() (gas: 12295) -MultiAggregateRateLimiter_constructor:test_ConstructorNoAuthorizedCallers_Success() (gas: 2149547) -MultiAggregateRateLimiter_constructor:test_Constructor_Success() (gas: 2265849) -MultiAggregateRateLimiter_getTokenBucket:test_GetTokenBucket_Success() (gas: 30248) -MultiAggregateRateLimiter_getTokenBucket:test_Refill_Success() (gas: 47358) -MultiAggregateRateLimiter_getTokenBucket:test_TimeUnderflow_Revert() (gas: 15821) -MultiAggregateRateLimiter_getTokenValue:test_GetTokenValue_Success() (gas: 19662) -MultiAggregateRateLimiter_getTokenValue:test_NoTokenPrice_Reverts() (gas: 21247) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageFromUnauthorizedCaller_Revert() (gas: 14527) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithDifferentTokensOnDifferentChains_Success() (gas: 213638) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithDisabledRateLimitToken_Success() (gas: 60437) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithNoTokens_Success() (gas: 17593) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitDisabled_Success() (gas: 44895) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitExceeded_Revert() (gas: 50542) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitReset_Success() (gas: 78668) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithTokensOnDifferentChains_Success() (gas: 311927) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithTokens_Success() (gas: 54728) -MultiAggregateRateLimiter_onOutboundMessage:test_RateLimitValueDifferentLanes_Success() (gas: 1073667529) -MultiAggregateRateLimiter_onOutboundMessage:test_ValidateMessageWithNoTokens_Success() (gas: 19149) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageFromUnauthorizedCaller_Revert() (gas: 15823) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithDifferentTokensOnDifferentChains_Success() (gas: 213716) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithDisabledRateLimitToken_Success() (gas: 62217) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitDisabled_Success() (gas: 46728) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitExceeded_Revert() (gas: 52360) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitReset_Success() (gas: 79913) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithTokensOnDifferentChains_Success() (gas: 312231) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithTokens_Success() (gas: 56530) -MultiAggregateRateLimiter_setFeeQuoter:test_OnlyOwner_Revert() (gas: 11313) -MultiAggregateRateLimiter_setFeeQuoter:test_Owner_Success() (gas: 19066) -MultiAggregateRateLimiter_setFeeQuoter:test_ZeroAddress_Revert() (gas: 10585) -MultiAggregateRateLimiter_updateRateLimitTokens:test_NonOwner_Revert() (gas: 18850) -MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokensMultipleChains_Success() (gas: 279972) -MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokensSingleChain_Success() (gas: 254523) -MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokens_AddsAndRemoves_Success() (gas: 204488) +MockRouterTest:test_ccipSendWithInsufficientNativeTokens_Revert() (gas: 34019) +MockRouterTest:test_ccipSendWithInvalidMsgValue_Revert() (gas: 60812) +MockRouterTest:test_ccipSendWithLinkFeeTokenAndValidMsgValue_Success() (gas: 126480) +MockRouterTest:test_ccipSendWithLinkFeeTokenbutInsufficientAllowance_Revert() (gas: 63419) +MockRouterTest:test_ccipSendWithSufficientNativeFeeTokens_Success() (gas: 43952) +MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_MultipleConfigsBothLanes_Success() (gas: 132457) +MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_MultipleConfigs_Success() (gas: 313023) +MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_OnlyCallableByOwner_Revert() (gas: 17750) +MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_SingleConfigOutbound_Success() (gas: 76030) +MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_SingleConfig_Success() (gas: 75946) +MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_UpdateExistingConfigWithNoDifference_Success() (gas: 38436) +MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_UpdateExistingConfig_Success() (gas: 53473) +MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_ZeroChainSelector_Revert() (gas: 17046) +MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_ZeroConfigs_Success() (gas: 12361) +MultiAggregateRateLimiter_constructor:test_ConstructorNoAuthorizedCallers_Success() (gas: 2050112) +MultiAggregateRateLimiter_constructor:test_Constructor_Success() (gas: 2166413) +MultiAggregateRateLimiter_getTokenBucket:test_GetTokenBucket_Success() (gas: 30404) +MultiAggregateRateLimiter_getTokenBucket:test_Refill_Success() (gas: 47673) +MultiAggregateRateLimiter_getTokenBucket:test_TimeUnderflow_Revert() (gas: 15863) +MultiAggregateRateLimiter_getTokenValue:test_GetTokenValue_Success() (gas: 19668) +MultiAggregateRateLimiter_getTokenValue:test_NoTokenPrice_Reverts() (gas: 21253) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageFromUnauthorizedCaller_Revert() (gas: 14533) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithDifferentTokensOnDifferentChains_Success() (gas: 214266) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithDisabledRateLimitToken_Success() (gas: 60479) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithNoTokens_Success() (gas: 17599) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitDisabled_Success() (gas: 45006) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitExceeded_Revert() (gas: 50584) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitReset_Success() (gas: 78872) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithTokensOnDifferentChains_Success() (gas: 312547) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithTokens_Success() (gas: 54776) +MultiAggregateRateLimiter_onOutboundMessage:test_RateLimitValueDifferentLanes_Success() (gas: 1073667418) +MultiAggregateRateLimiter_onOutboundMessage:test_ValidateMessageWithNoTokens_Success() (gas: 19158) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageFromUnauthorizedCaller_Revert() (gas: 15829) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithDifferentTokensOnDifferentChains_Success() (gas: 214110) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithDisabledRateLimitToken_Success() (gas: 62262) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitDisabled_Success() (gas: 46818) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitExceeded_Revert() (gas: 52405) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitReset_Success() (gas: 80129) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithTokensOnDifferentChains_Success() (gas: 312617) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithTokens_Success() (gas: 56581) +MultiAggregateRateLimiter_setFeeQuoter:test_OnlyOwner_Revert() (gas: 11325) +MultiAggregateRateLimiter_setFeeQuoter:test_Owner_Success() (gas: 19072) +MultiAggregateRateLimiter_setFeeQuoter:test_ZeroAddress_Revert() (gas: 10597) +MultiAggregateRateLimiter_updateRateLimitTokens:test_NonOwner_Revert() (gas: 18800) +MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokensMultipleChains_Success() (gas: 279944) +MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokensSingleChain_Success() (gas: 254495) +MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokens_AddsAndRemoves_Success() (gas: 204465) MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokens_RemoveNonExistentToken_Success() (gas: 28703) -MultiAggregateRateLimiter_updateRateLimitTokens:test_ZeroDestToken_Revert() (gas: 18287) -MultiAggregateRateLimiter_updateRateLimitTokens:test_ZeroSourceToken_Revert() (gas: 18216) -MultiOCR3Base_setOCR3Configs:test_FMustBePositive_Revert() (gas: 59228) -MultiOCR3Base_setOCR3Configs:test_FTooHigh_Revert() (gas: 43602) -MultiOCR3Base_setOCR3Configs:test_RepeatSignerAddress_Revert() (gas: 283585) -MultiOCR3Base_setOCR3Configs:test_RepeatTransmitterAddress_Revert() (gas: 422210) -MultiOCR3Base_setOCR3Configs:test_SetConfigIgnoreSigners_Success() (gas: 511089) -MultiOCR3Base_setOCR3Configs:test_SetConfigWithSigners_Success() (gas: 828371) -MultiOCR3Base_setOCR3Configs:test_SetConfigWithoutSigners_Success() (gas: 456841) -MultiOCR3Base_setOCR3Configs:test_SetConfigsZeroInput_Success() (gas: 12376) -MultiOCR3Base_setOCR3Configs:test_SetMultipleConfigs_Success() (gas: 2139958) -MultiOCR3Base_setOCR3Configs:test_SignerCannotBeZeroAddress_Revert() (gas: 141702) -MultiOCR3Base_setOCR3Configs:test_StaticConfigChange_Revert() (gas: 807256) -MultiOCR3Base_setOCR3Configs:test_TooManySigners_Revert() (gas: 158772) -MultiOCR3Base_setOCR3Configs:test_TooManyTransmitters_Revert() (gas: 112266) -MultiOCR3Base_setOCR3Configs:test_TransmitterCannotBeZeroAddress_Revert() (gas: 254068) -MultiOCR3Base_setOCR3Configs:test_UpdateConfigSigners_Success() (gas: 859969) -MultiOCR3Base_setOCR3Configs:test_UpdateConfigTransmittersWithoutSigners_Success() (gas: 475059) -MultiOCR3Base_transmit:test_ConfigDigestMismatch_Revert() (gas: 42833) -MultiOCR3Base_transmit:test_ForkedChain_Revert() (gas: 48438) +MultiAggregateRateLimiter_updateRateLimitTokens:test_ZeroDestToken_Revert() (gas: 18279) +MultiAggregateRateLimiter_updateRateLimitTokens:test_ZeroSourceToken_Revert() (gas: 18208) +MultiOCR3Base_setOCR3Configs:test_FMustBePositive_Revert() (gas: 59255) +MultiOCR3Base_setOCR3Configs:test_FTooHigh_Revert() (gas: 43629) +MultiOCR3Base_setOCR3Configs:test_RepeatSignerAddress_Revert() (gas: 283636) +MultiOCR3Base_setOCR3Configs:test_RepeatTransmitterAddress_Revert() (gas: 422261) +MultiOCR3Base_setOCR3Configs:test_SetConfigIgnoreSigners_Success() (gas: 511281) +MultiOCR3Base_setOCR3Configs:test_SetConfigWithSigners_Success() (gas: 828440) +MultiOCR3Base_setOCR3Configs:test_SetConfigWithoutSigners_Success() (gas: 456886) +MultiOCR3Base_setOCR3Configs:test_SetConfigsZeroInput_Success() (gas: 12382) +MultiOCR3Base_setOCR3Configs:test_SetMultipleConfigs_Success() (gas: 2140159) +MultiOCR3Base_setOCR3Configs:test_SignerCannotBeZeroAddress_Revert() (gas: 141717) +MultiOCR3Base_setOCR3Configs:test_StaticConfigChange_Revert() (gas: 807340) +MultiOCR3Base_setOCR3Configs:test_TooManySigners_Revert() (gas: 158799) +MultiOCR3Base_setOCR3Configs:test_TooManyTransmitters_Revert() (gas: 112293) +MultiOCR3Base_setOCR3Configs:test_TransmitterCannotBeZeroAddress_Revert() (gas: 254083) +MultiOCR3Base_setOCR3Configs:test_UpdateConfigSigners_Success() (gas: 860224) +MultiOCR3Base_setOCR3Configs:test_UpdateConfigTransmittersWithoutSigners_Success() (gas: 475193) +MultiOCR3Base_transmit:test_ConfigDigestMismatch_Revert() (gas: 42845) +MultiOCR3Base_transmit:test_ForkedChain_Revert() (gas: 48450) MultiOCR3Base_transmit:test_InsufficientSignatures_Revert() (gas: 76928) MultiOCR3Base_transmit:test_NonUniqueSignature_Revert() (gas: 65768) MultiOCR3Base_transmit:test_SignatureOutOfRegistration_Revert() (gas: 33417) MultiOCR3Base_transmit:test_TooManySignatures_Revert() (gas: 79519) MultiOCR3Base_transmit:test_TransmitSigners_gas_Success() (gas: 33631) -MultiOCR3Base_transmit:test_TransmitWithExtraCalldataArgs_Revert() (gas: 47110) -MultiOCR3Base_transmit:test_TransmitWithLessCalldataArgs_Revert() (gas: 25678) +MultiOCR3Base_transmit:test_TransmitWithExtraCalldataArgs_Revert() (gas: 47122) +MultiOCR3Base_transmit:test_TransmitWithLessCalldataArgs_Revert() (gas: 25690) MultiOCR3Base_transmit:test_TransmitWithoutSignatureVerification_gas_Success() (gas: 18712) MultiOCR3Base_transmit:test_UnAuthorizedTransmitter_Revert() (gas: 24189) MultiOCR3Base_transmit:test_UnauthorizedSigner_Revert() (gas: 61131) MultiOCR3Base_transmit:test_UnconfiguredPlugin_Revert() (gas: 39888) MultiOCR3Base_transmit:test_ZeroSignatures_Revert() (gas: 32971) -MultiOnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 411393) -MultiRampsE2E:test_E2E_3MessagesMMultiOffRampSuccess_gas() (gas: 1526772) -NonceManager_NonceIncrementation:test_getIncrementedOutboundNonce_Success() (gas: 37907) -NonceManager_NonceIncrementation:test_incrementInboundNonce_Skip() (gas: 23703) -NonceManager_NonceIncrementation:test_incrementInboundNonce_Success() (gas: 38790) -NonceManager_NonceIncrementation:test_incrementNoncesInboundAndOutbound_Success() (gas: 71874) -NonceManager_OffRampUpgrade:test_NoPrevOffRampForChain_Success() (gas: 259841) -NonceManager_OffRampUpgrade:test_UpgradedNonceNewSenderStartsAtZero_Success() (gas: 263983) -NonceManager_OffRampUpgrade:test_UpgradedNonceStartsAtV1Nonce_Success() (gas: 326753) -NonceManager_OffRampUpgrade:test_UpgradedOffRampNonceSkipsIfMsgInFlight_Success() (gas: 298927) -NonceManager_OffRampUpgrade:test_UpgradedSenderNoncesReadsPreviousRampTransitive_Success() (gas: 244682) -NonceManager_OffRampUpgrade:test_UpgradedSenderNoncesReadsPreviousRamp_Success() (gas: 232797) -NonceManager_OffRampUpgrade:test_Upgraded_Success() (gas: 152809) -NonceManager_OnRampUpgrade:test_UpgradeNonceNewSenderStartsAtZero_Success() (gas: 168320) -NonceManager_OnRampUpgrade:test_UpgradeNonceStartsAtV1Nonce_Success() (gas: 220111) -NonceManager_OnRampUpgrade:test_UpgradeSenderNoncesReadsPreviousRamp_Success() (gas: 125079) -NonceManager_OnRampUpgrade:test_Upgrade_Success() (gas: 107546) -NonceManager_applyPreviousRampsUpdates:test_MultipleRampsUpdates() (gas: 122943) -NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySetOffRamp_Revert() (gas: 42959) -NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySetOnRampAndOffRamp_Revert() (gas: 64282) -NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySetOnRamp_Revert() (gas: 42823) -NonceManager_applyPreviousRampsUpdates:test_SingleRampUpdate() (gas: 66570) +MultiOnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 411753) +MultiRampsE2E:test_E2E_3MessagesMMultiOffRampSuccess_gas() (gas: 1527968) +NonceManager_NonceIncrementation:test_getIncrementedOutboundNonce_Success() (gas: 37916) +NonceManager_NonceIncrementation:test_incrementInboundNonce_Skip() (gas: 23709) +NonceManager_NonceIncrementation:test_incrementInboundNonce_Success() (gas: 38799) +NonceManager_NonceIncrementation:test_incrementNoncesInboundAndOutbound_Success() (gas: 71898) +NonceManager_OffRampUpgrade:test_NoPrevOffRampForChain_Success() (gas: 259965) +NonceManager_OffRampUpgrade:test_UpgradedNonceNewSenderStartsAtZero_Success() (gas: 264107) +NonceManager_OffRampUpgrade:test_UpgradedNonceStartsAtV1Nonce_Success() (gas: 326950) +NonceManager_OffRampUpgrade:test_UpgradedOffRampNonceSkipsIfMsgInFlight_Success() (gas: 299064) +NonceManager_OffRampUpgrade:test_UpgradedSenderNoncesReadsPreviousRampTransitive_Success() (gas: 244871) +NonceManager_OffRampUpgrade:test_UpgradedSenderNoncesReadsPreviousRamp_Success() (gas: 232986) +NonceManager_OffRampUpgrade:test_Upgraded_Success() (gas: 152870) +NonceManager_OnRampUpgrade:test_UpgradeNonceNewSenderStartsAtZero_Success() (gas: 168380) +NonceManager_OnRampUpgrade:test_UpgradeNonceStartsAtV1Nonce_Success() (gas: 220237) +NonceManager_OnRampUpgrade:test_UpgradeSenderNoncesReadsPreviousRamp_Success() (gas: 125157) +NonceManager_OnRampUpgrade:test_Upgrade_Success() (gas: 107588) +NonceManager_applyPreviousRampsUpdates:test_MultipleRampsUpdates() (gas: 122955) +NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySetOffRamp_Revert() (gas: 42965) +NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySetOnRampAndOffRamp_Revert() (gas: 64288) +NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySetOnRamp_Revert() (gas: 42829) +NonceManager_applyPreviousRampsUpdates:test_SingleRampUpdate() (gas: 66576) NonceManager_applyPreviousRampsUpdates:test_ZeroInput() (gas: 12025) -NonceManager_typeAndVersion:test_typeAndVersion() (gas: 9675) -OCR2BaseNoChecks_setOCR2Config:test_FMustBePositive_Revert() (gas: 12171) -OCR2BaseNoChecks_setOCR2Config:test_RepeatAddress_Revert() (gas: 42233) -OCR2BaseNoChecks_setOCR2Config:test_SetConfigSuccess_gas() (gas: 84124) -OCR2BaseNoChecks_setOCR2Config:test_TooManyTransmitter_Revert() (gas: 36938) -OCR2BaseNoChecks_setOCR2Config:test_TransmitterCannotBeZeroAddress_Revert() (gas: 24158) -OCR2BaseNoChecks_transmit:test_ConfigDigestMismatch_Revert() (gas: 17448) -OCR2BaseNoChecks_transmit:test_ForkedChain_Revert() (gas: 26726) -OCR2BaseNoChecks_transmit:test_TransmitSuccess_gas() (gas: 27466) -OCR2BaseNoChecks_transmit:test_UnAuthorizedTransmitter_Revert() (gas: 21296) -OCR2Base_setOCR2Config:test_FMustBePositive_Revert() (gas: 12189) -OCR2Base_setOCR2Config:test_FTooHigh_Revert() (gas: 12345) -OCR2Base_setOCR2Config:test_OracleOutOfRegister_Revert() (gas: 14892) -OCR2Base_setOCR2Config:test_RepeatAddress_Revert() (gas: 45442) -OCR2Base_setOCR2Config:test_SetConfigSuccess_gas() (gas: 155192) +NonceManager_typeAndVersion:test_typeAndVersion() (gas: 9699) +OCR2BaseNoChecks_setOCR2Config:test_FMustBePositive_Revert() (gas: 12183) +OCR2BaseNoChecks_setOCR2Config:test_RepeatAddress_Revert() (gas: 42404) +OCR2BaseNoChecks_setOCR2Config:test_SetConfigSuccess_gas() (gas: 84585) +OCR2BaseNoChecks_setOCR2Config:test_TooManyTransmitter_Revert() (gas: 38150) +OCR2BaseNoChecks_setOCR2Config:test_TransmitterCannotBeZeroAddress_Revert() (gas: 24290) +OCR2BaseNoChecks_transmit:test_ConfigDigestMismatch_Revert() (gas: 17469) +OCR2BaseNoChecks_transmit:test_ForkedChain_Revert() (gas: 26762) +OCR2BaseNoChecks_transmit:test_TransmitSuccess_gas() (gas: 27499) +OCR2BaseNoChecks_transmit:test_UnAuthorizedTransmitter_Revert() (gas: 21317) +OCR2Base_setOCR2Config:test_FMustBePositive_Revert() (gas: 12201) +OCR2Base_setOCR2Config:test_FTooHigh_Revert() (gas: 12357) +OCR2Base_setOCR2Config:test_OracleOutOfRegister_Revert() (gas: 14904) +OCR2Base_setOCR2Config:test_RepeatAddress_Revert() (gas: 45454) +OCR2Base_setOCR2Config:test_SetConfigSuccess_gas() (gas: 155211) OCR2Base_setOCR2Config:test_SingerCannotBeZeroAddress_Revert() (gas: 24407) -OCR2Base_setOCR2Config:test_TooManySigners_Revert() (gas: 20508) +OCR2Base_setOCR2Config:test_TooManySigners_Revert() (gas: 20520) OCR2Base_setOCR2Config:test_TransmitterCannotBeZeroAddress_Revert() (gas: 47298) -OCR2Base_transmit:test_ConfigDigestMismatch_Revert() (gas: 19623) -OCR2Base_transmit:test_ForkedChain_Revert() (gas: 37683) -OCR2Base_transmit:test_NonUniqueSignature_Revert() (gas: 55309) -OCR2Base_transmit:test_SignatureOutOfRegistration_Revert() (gas: 20962) -OCR2Base_transmit:test_Transmit2SignersSuccess_gas() (gas: 51674) -OCR2Base_transmit:test_UnAuthorizedTransmitter_Revert() (gas: 23484) -OCR2Base_transmit:test_UnauthorizedSigner_Revert() (gas: 39665) -OCR2Base_transmit:test_WrongNumberOfSignatures_Revert() (gas: 20557) -OffRamp__releaseOrMintSingleToken:test__releaseOrMintSingleToken_NotACompatiblePool_Revert() (gas: 40170) -OffRamp__releaseOrMintSingleToken:test__releaseOrMintSingleToken_Success() (gas: 107133) -OffRamp__releaseOrMintSingleToken:test__releaseOrMintSingleToken_TokenHandlingError_transfer_Revert() (gas: 88356) -OffRamp__releaseOrMintSingleToken:test_releaseOrMintToken_InvalidDataLength_Revert() (gas: 39873) -OffRamp__releaseOrMintSingleToken:test_releaseOrMintToken_ReleaseOrMintBalanceMismatch_Revert() (gas: 97399) -OffRamp__releaseOrMintSingleToken:test_releaseOrMintToken_TokenHandlingError_BalanceOf_Revert() (gas: 42865) -OffRamp__releaseOrMintSingleToken:test_releaseOrMintToken_skip_ReleaseOrMintBalanceMismatch_if_pool_Revert() (gas: 89601) -OffRamp_applySourceChainConfigUpdates:test_AddMultipleChains_Success() (gas: 467980) -OffRamp_applySourceChainConfigUpdates:test_AddNewChain_Success() (gas: 99186) +OCR2Base_transmit:test_ConfigDigestMismatch_Revert() (gas: 19638) +OCR2Base_transmit:test_ForkedChain_Revert() (gas: 37713) +OCR2Base_transmit:test_NonUniqueSignature_Revert() (gas: 55324) +OCR2Base_transmit:test_SignatureOutOfRegistration_Revert() (gas: 20977) +OCR2Base_transmit:test_Transmit2SignersSuccess_gas() (gas: 51689) +OCR2Base_transmit:test_UnAuthorizedTransmitter_Revert() (gas: 23499) +OCR2Base_transmit:test_UnauthorizedSigner_Revert() (gas: 39695) +OCR2Base_transmit:test_WrongNumberOfSignatures_Revert() (gas: 20572) +OffRamp_afterOC3ConfigSet:test_afterOCR3ConfigSet_SignatureVerificationDisabled_Revert() (gas: 5850100) +OffRamp_applySourceChainConfigUpdates:test_AddMultipleChains_Success() (gas: 468052) +OffRamp_applySourceChainConfigUpdates:test_AddNewChain_Success() (gas: 99216) OffRamp_applySourceChainConfigUpdates:test_ApplyZeroUpdates_Success() (gas: 12392) -OffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChainOnRamp_Revert() (gas: 93184) -OffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChain_Success() (gas: 109891) -OffRamp_applySourceChainConfigUpdates:test_RouterAddress_Revert() (gas: 13260) -OffRamp_applySourceChainConfigUpdates:test_ZeroOnRampAddress_Revert() (gas: 17994) +OffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChainOnRamp_Revert() (gas: 93196) +OffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChain_Success() (gas: 109927) +OffRamp_applySourceChainConfigUpdates:test_RouterAddress_Revert() (gas: 13266) +OffRamp_applySourceChainConfigUpdates:test_ZeroOnRampAddress_Revert() (gas: 18000) OffRamp_applySourceChainConfigUpdates:test_ZeroSourceChainSelector_Revert() (gas: 15349) -OffRamp_batchExecute:test_MultipleReportsDifferentChainsSkipCursedChain_Success() (gas: 176832) -OffRamp_batchExecute:test_MultipleReportsDifferentChains_Success() (gas: 332556) -OffRamp_batchExecute:test_MultipleReportsSameChain_Success() (gas: 275924) -OffRamp_batchExecute:test_MultipleReportsSkipDuplicate_Success() (gas: 167973) -OffRamp_batchExecute:test_OutOfBoundsGasLimitsAccess_Revert() (gas: 187449) -OffRamp_batchExecute:test_SingleReport_Success() (gas: 155900) -OffRamp_batchExecute:test_Unhealthy_Success() (gas: 572813) +OffRamp_batchExecute:test_MultipleReportsDifferentChainsSkipCursedChain_Success() (gas: 176901) +OffRamp_batchExecute:test_MultipleReportsDifferentChains_Success() (gas: 332739) +OffRamp_batchExecute:test_MultipleReportsSameChain_Success() (gas: 276107) +OffRamp_batchExecute:test_MultipleReportsSkipDuplicate_Success() (gas: 168045) +OffRamp_batchExecute:test_OutOfBoundsGasLimitsAccess_Revert() (gas: 187572) +OffRamp_batchExecute:test_SingleReport_Success() (gas: 155963) +OffRamp_batchExecute:test_Unhealthy_Success() (gas: 573311) OffRamp_batchExecute:test_ZeroReports_Revert() (gas: 10440) OffRamp_ccipReceive:test_Reverts() (gas: 15705) -OffRamp_commit:test_FailedRMNVerification_Reverts() (gas: 64218) -OffRamp_commit:test_InvalidIntervalMinLargerThanMax_Revert() (gas: 67373) -OffRamp_commit:test_InvalidInterval_Revert() (gas: 59676) -OffRamp_commit:test_InvalidRootRevert() (gas: 58728) -OffRamp_commit:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6595300) -OffRamp_commit:test_NoConfig_Revert() (gas: 6179179) -OffRamp_commit:test_OnlyGasPriceUpdates_Success() (gas: 113211) -OffRamp_commit:test_OnlyPriceUpdateStaleReport_Revert() (gas: 121156) -OffRamp_commit:test_OnlyTokenPriceUpdates_Success() (gas: 113232) -OffRamp_commit:test_PriceSequenceNumberCleared_Success() (gas: 354911) -OffRamp_commit:test_ReportAndPriceUpdate_Success() (gas: 166399) -OffRamp_commit:test_ReportOnlyRootSuccess_gas() (gas: 141496) -OffRamp_commit:test_RootAlreadyCommitted_Revert() (gas: 142440) -OffRamp_commit:test_SourceChainNotEnabled_Revert() (gas: 59004) -OffRamp_commit:test_StaleReportWithRoot_Success() (gas: 239068) -OffRamp_commit:test_UnauthorizedTransmitter_Revert() (gas: 122234) -OffRamp_commit:test_Unhealthy_Revert() (gas: 57761) -OffRamp_commit:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 211577) -OffRamp_commit:test_WrongConfigWithoutSigners_Revert() (gas: 6591689) -OffRamp_commit:test_ZeroEpochAndRound_Revert() (gas: 51147) -OffRamp_constructor:test_Constructor_Success() (gas: 6179907) -OffRamp_constructor:test_SourceChainSelector_Revert() (gas: 137132) -OffRamp_constructor:test_ZeroChainSelector_Revert() (gas: 103861) -OffRamp_constructor:test_ZeroNonceManager_Revert() (gas: 101732) -OffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 139773) -OffRamp_constructor:test_ZeroRMNRemote_Revert() (gas: 101661) -OffRamp_constructor:test_ZeroTokenAdminRegistry_Revert() (gas: 101676) +OffRamp_commit:test_FailedRMNVerification_Reverts() (gas: 64343) +OffRamp_commit:test_InvalidIntervalMinLargerThanMax_Revert() (gas: 67494) +OffRamp_commit:test_InvalidInterval_Revert() (gas: 59807) +OffRamp_commit:test_InvalidRootRevert() (gas: 58865) +OffRamp_commit:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6454926) +OffRamp_commit:test_NoConfig_Revert() (gas: 6038739) +OffRamp_commit:test_OnlyGasPriceUpdates_Success() (gas: 113421) +OffRamp_commit:test_OnlyPriceUpdateStaleReport_Revert() (gas: 121444) +OffRamp_commit:test_OnlyTokenPriceUpdates_Success() (gas: 113442) +OffRamp_commit:test_PriceSequenceNumberCleared_Success() (gas: 355496) +OffRamp_commit:test_ReportAndPriceUpdate_Success() (gas: 166631) +OffRamp_commit:test_ReportOnlyRootSuccess_gas() (gas: 141711) +OffRamp_commit:test_RootAlreadyCommitted_Revert() (gas: 142664) +OffRamp_commit:test_SourceChainNotEnabled_Revert() (gas: 59129) +OffRamp_commit:test_StaleReportWithRoot_Success() (gas: 239467) +OffRamp_commit:test_UnauthorizedTransmitter_Revert() (gas: 122361) +OffRamp_commit:test_Unhealthy_Revert() (gas: 57858) +OffRamp_commit:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 211983) +OffRamp_commit:test_ZeroEpochAndRound_Revert() (gas: 51264) +OffRamp_constructor:test_Constructor_Success() (gas: 6039389) +OffRamp_constructor:test_SourceChainSelector_Revert() (gas: 136917) +OffRamp_constructor:test_ZeroChainSelector_Revert() (gas: 103646) +OffRamp_constructor:test_ZeroNonceManager_Revert() (gas: 101523) +OffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 139565) +OffRamp_constructor:test_ZeroRMNRemote_Revert() (gas: 101452) +OffRamp_constructor:test_ZeroTokenAdminRegistry_Revert() (gas: 101467) OffRamp_execute:test_IncorrectArrayType_Revert() (gas: 17281) -OffRamp_execute:test_LargeBatch_Success() (gas: 3376538) -OffRamp_execute:test_MultipleReportsWithPartialValidationFailures_Success() (gas: 372328) -OffRamp_execute:test_MultipleReports_Success() (gas: 298233) -OffRamp_execute:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6643456) -OffRamp_execute:test_NoConfig_Revert() (gas: 6227009) -OffRamp_execute:test_NonArray_Revert() (gas: 27718) -OffRamp_execute:test_SingleReport_Success() (gas: 175152) -OffRamp_execute:test_UnauthorizedTransmitter_Revert() (gas: 147380) -OffRamp_execute:test_WrongConfigWithSigners_Revert() (gas: 7004957) -OffRamp_execute:test_ZeroReports_Revert() (gas: 17156) +OffRamp_execute:test_LargeBatch_Success() (gas: 3378308) +OffRamp_execute:test_MultipleReportsWithPartialValidationFailures_Success() (gas: 372457) +OffRamp_execute:test_MultipleReports_Success() (gas: 298416) +OffRamp_execute:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6861731) +OffRamp_execute:test_NoConfig_Revert() (gas: 6086529) +OffRamp_execute:test_NonArray_Revert() (gas: 27721) +OffRamp_execute:test_SingleReport_Success() (gas: 175215) +OffRamp_execute:test_UnauthorizedTransmitter_Revert() (gas: 147455) +OffRamp_execute:test_WrongConfigWithSigners_Revert() (gas: 6864474) +OffRamp_execute:test_ZeroReports_Revert() (gas: 17162) OffRamp_executeSingleMessage:test_MessageSender_Revert() (gas: 18212) -OffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 248992) +OffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 249178) OffRamp_executeSingleMessage:test_NonContract_Success() (gas: 20494) -OffRamp_executeSingleMessage:test_TokenHandlingError_Revert() (gas: 210134) -OffRamp_executeSingleMessage:test_ZeroGasDONExecution_Revert() (gas: 48734) -OffRamp_executeSingleMessage:test_executeSingleMessage_NoTokens_Success() (gas: 48212) -OffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidationNoRouterCall_Revert() (gas: 229531) -OffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidation_Revert() (gas: 86169) -OffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens_Success() (gas: 280811) -OffRamp_executeSingleMessage:test_executeSingleMessage_WithValidation_Success() (gas: 92403) -OffRamp_executeSingleReport:test_DisabledSourceChain_Revert() (gas: 28225) -OffRamp_executeSingleReport:test_EmptyReport_Revert() (gas: 21854) -OffRamp_executeSingleReport:test_InvalidSourcePoolAddress_Success() (gas: 501661) -OffRamp_executeSingleReport:test_ManualExecutionNotYetEnabled_Revert() (gas: 47622) -OffRamp_executeSingleReport:test_MismatchingDestChainSelector_Revert() (gas: 33855) -OffRamp_executeSingleReport:test_MismatchingOnRampRoot_Revert() (gas: 154860) -OffRamp_executeSingleReport:test_NonExistingSourceChain_Revert() (gas: 28459) -OffRamp_executeSingleReport:test_ReceiverError_Success() (gas: 187534) -OffRamp_executeSingleReport:test_RetryFailedMessageWithoutManualExecution_Revert() (gas: 198006) -OffRamp_executeSingleReport:test_RootNotCommitted_Revert() (gas: 40129) -OffRamp_executeSingleReport:test_RouterYULCall_Revert() (gas: 447379) -OffRamp_executeSingleReport:test_SingleMessageNoTokensOtherChain_Success() (gas: 247824) -OffRamp_executeSingleReport:test_SingleMessageNoTokensUnordered_Success() (gas: 192091) -OffRamp_executeSingleReport:test_SingleMessageNoTokens_Success() (gas: 211684) -OffRamp_executeSingleReport:test_SingleMessageToNonCCIPReceiver_Success() (gas: 259699) -OffRamp_executeSingleReport:test_SingleMessagesNoTokensSuccess_gas() (gas: 140814) -OffRamp_executeSingleReport:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 424251) -OffRamp_executeSingleReport:test_SkippedIncorrectNonce_Success() (gas: 59045) -OffRamp_executeSingleReport:test_TokenDataMismatch_Revert() (gas: 74100) -OffRamp_executeSingleReport:test_TwoMessagesWithTokensAndGE_Success() (gas: 595900) -OffRamp_executeSingleReport:test_TwoMessagesWithTokensSuccess_gas() (gas: 543753) -OffRamp_executeSingleReport:test_UnexpectedTokenData_Revert() (gas: 33671) -OffRamp_executeSingleReport:test_UnhealthySingleChainCurse_Revert() (gas: 568731) -OffRamp_executeSingleReport:test_Unhealthy_Success() (gas: 568745) -OffRamp_executeSingleReport:test_WithCurseOnAnotherSourceChain_Success() (gas: 474176) -OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessageUnordered_Success() (gas: 135371) -OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessage_Success() (gas: 164590) +OffRamp_executeSingleMessage:test_TokenHandlingError_Revert() (gas: 210308) +OffRamp_executeSingleMessage:test_ZeroGasDONExecution_Revert() (gas: 48776) +OffRamp_executeSingleMessage:test_executeSingleMessage_NoTokens_Success() (gas: 48260) +OffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidationNoRouterCall_Revert() (gas: 229570) +OffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidation_Revert() (gas: 86208) +OffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens_Success() (gas: 281045) +OffRamp_executeSingleMessage:test_executeSingleMessage_WithValidation_Success() (gas: 92487) +OffRamp_executeSingleReport:test_DisabledSourceChain_Revert() (gas: 28238) +OffRamp_executeSingleReport:test_EmptyReport_Revert() (gas: 21860) +OffRamp_executeSingleReport:test_InvalidSourcePoolAddress_Success() (gas: 502029) +OffRamp_executeSingleReport:test_ManualExecutionNotYetEnabled_Revert() (gas: 47635) +OffRamp_executeSingleReport:test_MismatchingDestChainSelector_Revert() (gas: 33895) +OffRamp_executeSingleReport:test_MismatchingOnRampRoot_Revert() (gas: 155036) +OffRamp_executeSingleReport:test_NonExistingSourceChain_Revert() (gas: 28472) +OffRamp_executeSingleReport:test_ReceiverError_Success() (gas: 187688) +OffRamp_executeSingleReport:test_RetryFailedMessageWithoutManualExecution_Revert() (gas: 198173) +OffRamp_executeSingleReport:test_RootNotCommitted_Revert() (gas: 40136) +OffRamp_executeSingleReport:test_RouterYULCall_Revert() (gas: 447500) +OffRamp_executeSingleReport:test_SingleMessageNoTokensOtherChain_Success() (gas: 247946) +OffRamp_executeSingleReport:test_SingleMessageNoTokensUnordered_Success() (gas: 192339) +OffRamp_executeSingleReport:test_SingleMessageNoTokens_Success() (gas: 211938) +OffRamp_executeSingleReport:test_SingleMessageToNonCCIPReceiver_Success() (gas: 259763) +OffRamp_executeSingleReport:test_SingleMessagesNoTokensSuccess_gas() (gas: 140974) +OffRamp_executeSingleReport:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 424565) +OffRamp_executeSingleReport:test_SkippedIncorrectNonce_Success() (gas: 59052) +OffRamp_executeSingleReport:test_TokenDataMismatch_Revert() (gas: 74143) +OffRamp_executeSingleReport:test_TwoMessagesWithTokensAndGE_Success() (gas: 596466) +OffRamp_executeSingleReport:test_TwoMessagesWithTokensSuccess_gas() (gas: 544340) +OffRamp_executeSingleReport:test_UnexpectedTokenData_Revert() (gas: 33678) +OffRamp_executeSingleReport:test_UnhealthySingleChainCurse_Revert() (gas: 569320) +OffRamp_executeSingleReport:test_Unhealthy_Success() (gas: 569334) +OffRamp_executeSingleReport:test_WithCurseOnAnotherSourceChain_Success() (gas: 474664) +OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessageUnordered_Success() (gas: 135508) +OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessage_Success() (gas: 164757) OffRamp_getExecutionState:test_FillExecutionState_Success() (gas: 3635486) OffRamp_getExecutionState:test_GetDifferentChainExecutionState_Success() (gas: 118398) OffRamp_getExecutionState:test_GetExecutionState_Success() (gas: 87417) -OffRamp_manuallyExecute:test_ManualExecGasLimitMismatchSingleReport_Revert() (gas: 75545) -OffRamp_manuallyExecute:test_ManualExecInvalidGasLimit_Revert() (gas: 26439) -OffRamp_manuallyExecute:test_manuallyExecute_DoesNotRevertIfUntouched_Success() (gas: 171228) -OffRamp_manuallyExecute:test_manuallyExecute_FailedTx_Revert() (gas: 211065) -OffRamp_manuallyExecute:test_manuallyExecute_ForkedChain_Revert() (gas: 26057) -OffRamp_manuallyExecute:test_manuallyExecute_GasLimitMismatchMultipleReports_Revert() (gas: 152806) -OffRamp_manuallyExecute:test_manuallyExecute_LowGasLimit_Success() (gas: 529785) -OffRamp_manuallyExecute:test_manuallyExecute_MultipleReportsWithSingleCursedLane_Revert() (gas: 310294) -OffRamp_manuallyExecute:test_manuallyExecute_ReentrancyFails_Success() (gas: 2389687) -OffRamp_manuallyExecute:test_manuallyExecute_SourceChainSelectorMismatch_Revert() (gas: 162168) -OffRamp_manuallyExecute:test_manuallyExecute_Success() (gas: 223992) -OffRamp_manuallyExecute:test_manuallyExecute_WithGasOverride_Success() (gas: 224567) -OffRamp_manuallyExecute:test_manuallyExecute_WithMultiReportGasOverride_Success() (gas: 767657) -OffRamp_manuallyExecute:test_manuallyExecute_WithPartialMessages_Success() (gas: 342979) -OffRamp_releaseOrMintTokens:test_TokenHandlingError_Reverts() (gas: 165844) -OffRamp_releaseOrMintTokens:test__releaseOrMintTokens_PoolIsNotAPool_Reverts() (gas: 24622) -OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_InvalidDataLengthReturnData_Revert() (gas: 66304) -OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_InvalidEVMAddress_Revert() (gas: 41335) -OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_PoolDoesNotSupportDest_Reverts() (gas: 83310) -OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_Success() (gas: 177953) -OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals_Success() (gas: 191164) -OffRamp_setDynamicConfig:test_FeeQuoterZeroAddress_Revert() (gas: 11604) -OffRamp_setDynamicConfig:test_NonOwner_Revert() (gas: 14171) -OffRamp_setDynamicConfig:test_SetDynamicConfigWithValidator_Success() (gas: 49156) -OffRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 27101) -OffRamp_trialExecute:test_RateLimitError_Success() (gas: 225708) -OffRamp_trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 234329) -OffRamp_trialExecute:test_TokenPoolIsNotAContract_Success() (gas: 308936) -OffRamp_trialExecute:test_trialExecute_Success() (gas: 283904) -OnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 390336) -OnRamp_allowListConfigUpdates:test_applyAllowList_Revert() (gas: 66512) -OnRamp_allowListConfigUpdates:test_applyAllowList_Success() (gas: 323568) -OnRamp_applyDestChainConfigUpdates:test_ApplyDestChainConfigUpdates_Success() (gas: 64504) -OnRamp_applyDestChainConfigUpdates:test_ApplyDestChainConfigUpdates_WithInvalidChainSelector_Revert() (gas: 13242) -OnRamp_constructor:test_Constructor_InvalidConfigChainSelectorEqZero_Revert() (gas: 94851) -OnRamp_constructor:test_Constructor_InvalidConfigNonceManagerEqAddressZero_Revert() (gas: 92785) -OnRamp_constructor:test_Constructor_InvalidConfigRMNProxyEqAddressZero_Revert() (gas: 97811) -OnRamp_constructor:test_Constructor_InvalidConfigTokenAdminRegistryEqAddressZero_Revert() (gas: 92843) -OnRamp_constructor:test_Constructor_Success() (gas: 2852084) -OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() (gas: 114886) -OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2_Success() (gas: 145654) -OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessCustomExtraArgs() (gas: 145257) -OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessEmptyExtraArgs() (gas: 143482) -OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessLegacyExtraArgs() (gas: 145482) -OnRamp_forwardFromRouter:test_ForwardFromRouter_Success() (gas: 144861) -OnRamp_forwardFromRouter:test_ForwardFromRouter_Success_ConfigurableSourceRouter() (gas: 140001) -OnRamp_forwardFromRouter:test_InvalidExtraArgsTag_Revert() (gas: 28810) -OnRamp_forwardFromRouter:test_MessageValidationError_Revert() (gas: 138698) -OnRamp_forwardFromRouter:test_MesssageFeeTooHigh_Revert() (gas: 26910) -OnRamp_forwardFromRouter:test_MultiCannotSendZeroTokens_Revert() (gas: 74122) -OnRamp_forwardFromRouter:test_OriginalSender_Revert() (gas: 12918) -OnRamp_forwardFromRouter:test_Paused_Revert() (gas: 37224) -OnRamp_forwardFromRouter:test_Permissions_Revert() (gas: 18179) -OnRamp_forwardFromRouter:test_ShouldIncrementNonceOnlyOnOrdered_Success() (gas: 184142) -OnRamp_forwardFromRouter:test_ShouldIncrementSeqNumAndNonce_Success() (gas: 210451) -OnRamp_forwardFromRouter:test_ShouldStoreLinkFees() (gas: 124773) -OnRamp_forwardFromRouter:test_ShouldStoreNonLinkFees() (gas: 146166) -OnRamp_forwardFromRouter:test_SourceTokenDataTooLarge_Revert() (gas: 3882038) -OnRamp_forwardFromRouter:test_UnAllowedOriginalSender_Revert() (gas: 18609) -OnRamp_forwardFromRouter:test_UnsupportedToken_Revert() (gas: 110785) -OnRamp_forwardFromRouter:test_forwardFromRouter_UnsupportedToken_Revert() (gas: 76212) -OnRamp_forwardFromRouter:test_forwardFromRouter_WithValidation_Success() (gas: 280890) -OnRamp_getFee:test_EmptyMessage_Success() (gas: 102302) -OnRamp_getFee:test_EnforceOutOfOrder_Revert() (gas: 66336) -OnRamp_getFee:test_GetFeeOfZeroForTokenMessage_Success() (gas: 87668) -OnRamp_getFee:test_NotAFeeTokenButPricedToken_Revert() (gas: 34930) -OnRamp_getFee:test_SingleTokenMessage_Success() (gas: 117635) +OffRamp_manuallyExecute:test_ManualExecGasLimitMismatchSingleReport_Revert() (gas: 75569) +OffRamp_manuallyExecute:test_ManualExecInvalidGasLimit_Revert() (gas: 26442) +OffRamp_manuallyExecute:test_manuallyExecute_DoesNotRevertIfUntouched_Success() (gas: 171318) +OffRamp_manuallyExecute:test_manuallyExecute_FailedTx_Revert() (gas: 211218) +OffRamp_manuallyExecute:test_manuallyExecute_ForkedChain_Revert() (gas: 26060) +OffRamp_manuallyExecute:test_manuallyExecute_GasLimitMismatchMultipleReports_Revert() (gas: 152860) +OffRamp_manuallyExecute:test_manuallyExecute_LowGasLimit_Success() (gas: 529914) +OffRamp_manuallyExecute:test_manuallyExecute_MultipleReportsWithSingleCursedLane_Revert() (gas: 310504) +OffRamp_manuallyExecute:test_manuallyExecute_ReentrancyFails_Success() (gas: 2327501) +OffRamp_manuallyExecute:test_manuallyExecute_SourceChainSelectorMismatch_Revert() (gas: 162246) +OffRamp_manuallyExecute:test_manuallyExecute_Success() (gas: 224130) +OffRamp_manuallyExecute:test_manuallyExecute_WithGasOverride_Success() (gas: 224711) +OffRamp_manuallyExecute:test_manuallyExecute_WithMultiReportGasOverride_Success() (gas: 768287) +OffRamp_manuallyExecute:test_manuallyExecute_WithPartialMessages_Success() (gas: 343255) +OffRamp_releaseOrMintSingleToken:test__releaseOrMintSingleToken_NotACompatiblePool_Revert() (gas: 40194) +OffRamp_releaseOrMintSingleToken:test__releaseOrMintSingleToken_Success() (gas: 107223) +OffRamp_releaseOrMintSingleToken:test__releaseOrMintSingleToken_TokenHandlingError_transfer_Revert() (gas: 88434) +OffRamp_releaseOrMintSingleToken:test_releaseOrMintToken_InvalidDataLength_Revert() (gas: 39933) +OffRamp_releaseOrMintSingleToken:test_releaseOrMintToken_ReleaseOrMintBalanceMismatch_Revert() (gas: 97495) +OffRamp_releaseOrMintSingleToken:test_releaseOrMintToken_TokenHandlingError_BalanceOf_Revert() (gas: 42919) +OffRamp_releaseOrMintSingleToken:test_releaseOrMintToken_skip_ReleaseOrMintBalanceMismatch_if_pool_Revert() (gas: 89679) +OffRamp_releaseOrMintTokens:test_TokenHandlingError_Reverts() (gas: 166024) +OffRamp_releaseOrMintTokens:test__releaseOrMintTokens_PoolIsNotAPool_Reverts() (gas: 24628) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_InvalidDataLengthReturnData_Revert() (gas: 66391) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_InvalidEVMAddress_Revert() (gas: 41350) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_PoolDoesNotSupportDest_Reverts() (gas: 83403) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_Success() (gas: 178169) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals_Success() (gas: 191356) +OffRamp_setDynamicConfig:test_FeeQuoterZeroAddress_Revert() (gas: 11610) +OffRamp_setDynamicConfig:test_NonOwner_Revert() (gas: 14177) +OffRamp_setDynamicConfig:test_SetDynamicConfigWithValidator_Success() (gas: 49192) +OffRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 27137) +OffRamp_trialExecute:test_RateLimitError_Success() (gas: 225885) +OffRamp_trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 234506) +OffRamp_trialExecute:test_TokenPoolIsNotAContract_Success() (gas: 309185) +OffRamp_trialExecute:test_trialExecute_Success() (gas: 284141) +OnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 390954) +OnRamp_allowListConfigUpdates:test_applyAllowList_Revert() (gas: 66515) +OnRamp_allowListConfigUpdates:test_applyAllowList_Success() (gas: 323595) +OnRamp_applyDestChainConfigUpdates:test_ApplyDestChainConfigUpdates_Success() (gas: 64546) +OnRamp_applyDestChainConfigUpdates:test_ApplyDestChainConfigUpdates_WithInvalidChainSelector_Revert() (gas: 13254) +OnRamp_constructor:test_Constructor_InvalidConfigChainSelectorEqZero_Revert() (gas: 94815) +OnRamp_constructor:test_Constructor_InvalidConfigNonceManagerEqAddressZero_Revert() (gas: 92749) +OnRamp_constructor:test_Constructor_InvalidConfigRMNProxyEqAddressZero_Revert() (gas: 97775) +OnRamp_constructor:test_Constructor_InvalidConfigTokenAdminRegistryEqAddressZero_Revert() (gas: 92807) +OnRamp_constructor:test_Constructor_Success() (gas: 2812991) +OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() (gas: 114961) +OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2_Success() (gas: 145732) +OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessCustomExtraArgs() (gas: 145335) +OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessEmptyExtraArgs() (gas: 143560) +OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessLegacyExtraArgs() (gas: 145560) +OnRamp_forwardFromRouter:test_ForwardFromRouter_Success() (gas: 144939) +OnRamp_forwardFromRouter:test_ForwardFromRouter_Success_ConfigurableSourceRouter() (gas: 140265) +OnRamp_forwardFromRouter:test_InvalidExtraArgsTag_Revert() (gas: 28846) +OnRamp_forwardFromRouter:test_MessageValidationError_Revert() (gas: 138926) +OnRamp_forwardFromRouter:test_MesssageFeeTooHigh_Revert() (gas: 26946) +OnRamp_forwardFromRouter:test_MultiCannotSendZeroTokens_Revert() (gas: 74161) +OnRamp_forwardFromRouter:test_OriginalSender_Revert() (gas: 12951) +OnRamp_forwardFromRouter:test_Paused_Revert() (gas: 37326) +OnRamp_forwardFromRouter:test_Permissions_Revert() (gas: 18278) +OnRamp_forwardFromRouter:test_ShouldIncrementNonceOnlyOnOrdered_Success() (gas: 184628) +OnRamp_forwardFromRouter:test_ShouldIncrementSeqNumAndNonce_Success() (gas: 210946) +OnRamp_forwardFromRouter:test_ShouldStoreLinkFees() (gas: 124860) +OnRamp_forwardFromRouter:test_ShouldStoreNonLinkFees() (gas: 146277) +OnRamp_forwardFromRouter:test_SourceTokenDataTooLarge_Revert() (gas: 3829399) +OnRamp_forwardFromRouter:test_UnAllowedOriginalSender_Revert() (gas: 18714) +OnRamp_forwardFromRouter:test_UnsupportedToken_Revert() (gas: 110929) +OnRamp_forwardFromRouter:test_forwardFromRouter_UnsupportedToken_Revert() (gas: 76251) +OnRamp_forwardFromRouter:test_forwardFromRouter_WithValidation_Success() (gas: 281193) +OnRamp_getFee:test_EmptyMessage_Success() (gas: 102470) +OnRamp_getFee:test_EnforceOutOfOrder_Revert() (gas: 66390) +OnRamp_getFee:test_GetFeeOfZeroForTokenMessage_Success() (gas: 87773) +OnRamp_getFee:test_NotAFeeTokenButPricedToken_Revert() (gas: 34972) +OnRamp_getFee:test_SingleTokenMessage_Success() (gas: 117839) OnRamp_getFee:test_Unhealthy_Revert() (gas: 17009) OnRamp_getSupportedTokens:test_GetSupportedTokens_Revert() (gas: 10438) OnRamp_getTokenPool:test_GetTokenPool_Success() (gas: 35204) -OnRamp_setDynamicConfig:test_SetConfigInvalidConfigFeeAggregatorEqAddressZero_Revert() (gas: 11402) -OnRamp_setDynamicConfig:test_SetConfigInvalidConfigFeeQuoterEqAddressZero_Revert() (gas: 13001) -OnRamp_setDynamicConfig:test_SetConfigInvalidConfig_Revert() (gas: 11359) -OnRamp_setDynamicConfig:test_SetConfigOnlyOwner_Revert() (gas: 16385) -OnRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 55321) -OnRamp_withdrawFeeTokens:test_WithdrawFeeTokens_Success() (gas: 97095) -PingPong_ccipReceive:test_CcipReceive_Success() (gas: 152669) -PingPong_plumbing:test_OutOfOrderExecution_Success() (gas: 20277) -PingPong_plumbing:test_Pausing_Success() (gas: 17777) -PingPong_startPingPong:test_StartPingPong_With_OOO_Success() (gas: 163187) -PingPong_startPingPong:test_StartPingPong_With_Sequenced_Ordered_Success() (gas: 182599) +OnRamp_setDynamicConfig:test_SetConfigInvalidConfigFeeAggregatorEqAddressZero_Revert() (gas: 11420) +OnRamp_setDynamicConfig:test_SetConfigInvalidConfigFeeQuoterEqAddressZero_Revert() (gas: 13019) +OnRamp_setDynamicConfig:test_SetConfigInvalidConfig_Revert() (gas: 11377) +OnRamp_setDynamicConfig:test_SetConfigOnlyOwner_Revert() (gas: 16409) +OnRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 55330) +OnRamp_withdrawFeeTokens:test_WithdrawFeeTokens_Success() (gas: 97191) +PingPong_ccipReceive:test_CcipReceive_Success() (gas: 152765) +PingPong_plumbing:test_OutOfOrderExecution_Success() (gas: 20280) +PingPong_plumbing:test_Pausing_Success() (gas: 17780) +PingPong_startPingPong:test_StartPingPong_With_OOO_Success() (gas: 163361) +PingPong_startPingPong:test_StartPingPong_With_Sequenced_Ordered_Success() (gas: 182770) RMNHome:test() (gas: 186) -RMN_constructor:test_Constructor_Success() (gas: 48838) -RMN_getRecordedCurseRelatedOps:test_OpsPostDeployment() (gas: 19666) -RMN_lazyVoteToCurseUpdate_Benchmark:test_VoteToCurseLazilyRetain3VotersUponConfigChange_gas() (gas: 152152) -RMN_ownerUnbless:test_Unbless_Success() (gas: 74699) -RMN_ownerUnvoteToCurse:test_CanBlessAndCurseAfterGlobalCurseIsLifted() (gas: 470965) -RMN_ownerUnvoteToCurse:test_IsIdempotent() (gas: 397532) -RMN_ownerUnvoteToCurse:test_NonOwner_Revert() (gas: 18591) -RMN_ownerUnvoteToCurse:test_OwnerUnvoteToCurseSuccess_gas() (gas: 357400) -RMN_ownerUnvoteToCurse:test_UnknownVoter_Revert() (gas: 32980) -RMN_ownerUnvoteToCurse_Benchmark:test_OwnerUnvoteToCurse_1Voter_LiftsCurse_gas() (gas: 261985) -RMN_permaBlessing:test_PermaBlessing() (gas: 202686) +RMN_constructor:test_Constructor_Success() (gas: 48874) +RMN_getRecordedCurseRelatedOps:test_OpsPostDeployment() (gas: 19690) +RMN_lazyVoteToCurseUpdate_Benchmark:test_VoteToCurseLazilyRetain3VotersUponConfigChange_gas() (gas: 152263) +RMN_ownerUnbless:test_Unbless_Success() (gas: 74882) +RMN_ownerUnvoteToCurse:test_CanBlessAndCurseAfterGlobalCurseIsLifted() (gas: 471457) +RMN_ownerUnvoteToCurse:test_IsIdempotent() (gas: 398096) +RMN_ownerUnvoteToCurse:test_NonOwner_Revert() (gas: 18669) +RMN_ownerUnvoteToCurse:test_OwnerUnvoteToCurseSuccess_gas() (gas: 357751) +RMN_ownerUnvoteToCurse:test_UnknownVoter_Revert() (gas: 33034) +RMN_ownerUnvoteToCurse_Benchmark:test_OwnerUnvoteToCurse_1Voter_LiftsCurse_gas() (gas: 262211) +RMN_permaBlessing:test_PermaBlessing() (gas: 202691) RMN_setConfig:test_BlessVoterIsZeroAddress_Revert() (gas: 15494) RMN_setConfig:test_EitherThresholdIsZero_Revert() (gas: 21095) -RMN_setConfig:test_NonOwner_Revert() (gas: 14713) +RMN_setConfig:test_NonOwner_Revert() (gas: 14719) RMN_setConfig:test_RepeatedAddress_Revert() (gas: 18213) -RMN_setConfig:test_SetConfigSuccess_gas() (gas: 104022) +RMN_setConfig:test_SetConfigSuccess_gas() (gas: 104080) RMN_setConfig:test_TotalWeightsSmallerThanEachThreshold_Revert() (gas: 30173) -RMN_setConfig:test_VoteToBlessByEjectedVoter_Revert() (gas: 130303) +RMN_setConfig:test_VoteToBlessByEjectedVoter_Revert() (gas: 130363) RMN_setConfig:test_VotersLengthIsZero_Revert() (gas: 12128) RMN_setConfig:test_WeightIsZeroAddress_Revert() (gas: 15734) -RMN_setConfig_Benchmark_1:test_SetConfig_7Voters_gas() (gas: 659123) -RMN_setConfig_Benchmark_2:test_ResetConfig_7Voters_gas() (gas: 212156) -RMN_unvoteToCurse:test_InvalidCursesHash() (gas: 26364) -RMN_unvoteToCurse:test_OwnerSkips() (gas: 33753) -RMN_unvoteToCurse:test_OwnerSucceeds() (gas: 63909) -RMN_unvoteToCurse:test_UnauthorizedVoter() (gas: 47478) -RMN_unvoteToCurse:test_ValidCursesHash() (gas: 61067) -RMN_unvoteToCurse:test_VotersCantLiftCurseButOwnerCan() (gas: 627750) -RMN_voteToBless:test_Curse_Revert() (gas: 472823) -RMN_voteToBless:test_IsAlreadyBlessed_Revert() (gas: 114829) -RMN_voteToBless:test_RootSuccess() (gas: 555559) -RMN_voteToBless:test_SenderAlreadyVoted_Revert() (gas: 96730) -RMN_voteToBless:test_UnauthorizedVoter_Revert() (gas: 17087) -RMN_voteToBless_Benchmark:test_1RootSuccess_gas() (gas: 44667) -RMN_voteToBless_Benchmark:test_3RootSuccess_gas() (gas: 98565) -RMN_voteToBless_Benchmark:test_5RootSuccess_gas() (gas: 152401) -RMN_voteToBless_Blessed_Benchmark:test_1RootSuccessBecameBlessed_gas() (gas: 29619) -RMN_voteToBless_Blessed_Benchmark:test_1RootSuccess_gas() (gas: 27565) -RMN_voteToBless_Blessed_Benchmark:test_3RootSuccess_gas() (gas: 81485) -RMN_voteToBless_Blessed_Benchmark:test_5RootSuccess_gas() (gas: 135299) -RMN_voteToCurse:test_CurseOnlyWhenThresholdReached_Success() (gas: 1648701) -RMN_voteToCurse:test_EmptySubjects_Revert() (gas: 14019) -RMN_voteToCurse:test_EvenIfAlreadyCursed_Success() (gas: 534332) -RMN_voteToCurse:test_OwnerCanCurseAndUncurse() (gas: 399001) -RMN_voteToCurse:test_RepeatedSubject_Revert() (gas: 144225) -RMN_voteToCurse:test_ReusedCurseId_Revert() (gas: 146738) -RMN_voteToCurse:test_UnauthorizedVoter_Revert() (gas: 12600) -RMN_voteToCurse:test_VoteToCurse_NoCurse_Success() (gas: 187244) -RMN_voteToCurse:test_VoteToCurse_YesCurse_Success() (gas: 472452) -RMN_voteToCurse_2:test_VotesAreDroppedIfSubjectIsNotCursedDuringConfigChange() (gas: 370468) -RMN_voteToCurse_2:test_VotesAreRetainedIfSubjectIsCursedDuringConfigChange() (gas: 1151909) -RMN_voteToCurse_Benchmark_1:test_VoteToCurse_NewSubject_NewVoter_NoCurse_gas() (gas: 140968) -RMN_voteToCurse_Benchmark_1:test_VoteToCurse_NewSubject_NewVoter_YesCurse_gas() (gas: 165087) -RMN_voteToCurse_Benchmark_2:test_VoteToCurse_OldSubject_NewVoter_NoCurse_gas() (gas: 121305) -RMN_voteToCurse_Benchmark_2:test_VoteToCurse_OldSubject_OldVoter_NoCurse_gas() (gas: 98247) -RMN_voteToCurse_Benchmark_3:test_VoteToCurse_OldSubject_NewVoter_YesCurse_gas() (gas: 145631) -RateLimiter_constructor:test_Constructor_Success() (gas: 19650) -RateLimiter_consume:test_AggregateValueMaxCapacityExceeded_Revert() (gas: 15916) -RateLimiter_consume:test_AggregateValueRateLimitReached_Revert() (gas: 22222) -RateLimiter_consume:test_ConsumeAggregateValue_Success() (gas: 31353) -RateLimiter_consume:test_ConsumeTokens_Success() (gas: 20336) -RateLimiter_consume:test_ConsumeUnlimited_Success() (gas: 40285) -RateLimiter_consume:test_ConsumingMoreThanUint128_Revert() (gas: 15720) -RateLimiter_consume:test_RateLimitReachedOverConsecutiveBlocks_Revert() (gas: 25594) -RateLimiter_consume:test_Refill_Success() (gas: 37222) -RateLimiter_consume:test_TokenMaxCapacityExceeded_Revert() (gas: 18250) -RateLimiter_consume:test_TokenRateLimitReached_Revert() (gas: 24706) -RateLimiter_currentTokenBucketState:test_CurrentTokenBucketState_Success() (gas: 38647) -RateLimiter_currentTokenBucketState:test_Refill_Success() (gas: 46384) -RateLimiter_setTokenBucketConfig:test_SetRateLimiterConfig_Success() (gas: 38017) -RegistryModuleOwnerCustom_constructor:test_constructor_Revert() (gas: 36028) -RegistryModuleOwnerCustom_registerAdminViaGetCCIPAdmin:test_registerAdminViaGetCCIPAdmin_Revert() (gas: 19637) -RegistryModuleOwnerCustom_registerAdminViaGetCCIPAdmin:test_registerAdminViaGetCCIPAdmin_Success() (gas: 129918) -RegistryModuleOwnerCustom_registerAdminViaOwner:test_registerAdminViaOwner_Revert() (gas: 19451) -RegistryModuleOwnerCustom_registerAdminViaOwner:test_registerAdminViaOwner_Success() (gas: 129731) -Router_applyRampUpdates:test_OffRampMismatch_Revert() (gas: 89288) -Router_applyRampUpdates:test_OffRampUpdatesWithRouting() (gas: 10642128) -Router_applyRampUpdates:test_OnRampDisable() (gas: 55935) -Router_applyRampUpdates:test_OnlyOwner_Revert() (gas: 12311) -Router_ccipSend:test_CCIPSendLinkFeeNoTokenSuccess_gas() (gas: 113880) -Router_ccipSend:test_CCIPSendLinkFeeOneTokenSuccess_gas() (gas: 201336) -Router_ccipSend:test_CCIPSendNativeFeeNoTokenSuccess_gas() (gas: 128515) -Router_ccipSend:test_CCIPSendNativeFeeOneTokenSuccess_gas() (gas: 215973) -Router_ccipSend:test_FeeTokenAmountTooLow_Revert() (gas: 66281) -Router_ccipSend:test_InvalidMsgValue() (gas: 31963) -Router_ccipSend:test_NativeFeeTokenInsufficientValue() (gas: 68737) -Router_ccipSend:test_NativeFeeTokenOverpay_Success() (gas: 173606) -Router_ccipSend:test_NativeFeeTokenZeroValue() (gas: 56031) -Router_ccipSend:test_NativeFeeToken_Success() (gas: 172200) -Router_ccipSend:test_NonLinkFeeToken_Success() (gas: 242717) -Router_ccipSend:test_UnsupportedDestinationChain_Revert() (gas: 24749) -Router_ccipSend:test_WhenNotHealthy_Revert() (gas: 44724) -Router_ccipSend:test_WrappedNativeFeeToken_Success() (gas: 174386) -Router_ccipSend:test_ZeroFeeAndGasPrice_Success() (gas: 244854) +RMN_setConfig_Benchmark_1:test_SetConfig_7Voters_gas() (gas: 659462) +RMN_setConfig_Benchmark_2:test_ResetConfig_7Voters_gas() (gas: 212484) +RMN_unvoteToCurse:test_InvalidCursesHash() (gas: 26412) +RMN_unvoteToCurse:test_OwnerSkips() (gas: 33813) +RMN_unvoteToCurse:test_OwnerSucceeds() (gas: 63981) +RMN_unvoteToCurse:test_UnauthorizedVoter() (gas: 47598) +RMN_unvoteToCurse:test_ValidCursesHash() (gas: 61127) +RMN_unvoteToCurse:test_VotersCantLiftCurseButOwnerCan() (gas: 628641) +RMN_voteToBless:test_Curse_Revert() (gas: 473252) +RMN_voteToBless:test_IsAlreadyBlessed_Revert() (gas: 115312) +RMN_voteToBless:test_RootSuccess() (gas: 558319) +RMN_voteToBless:test_SenderAlreadyVoted_Revert() (gas: 97177) +RMN_voteToBless:test_UnauthorizedVoter_Revert() (gas: 17096) +RMN_voteToBless_Benchmark:test_1RootSuccess_gas() (gas: 44703) +RMN_voteToBless_Benchmark:test_3RootSuccess_gas() (gas: 98673) +RMN_voteToBless_Benchmark:test_5RootSuccess_gas() (gas: 152581) +RMN_voteToBless_Blessed_Benchmark:test_1RootSuccessBecameBlessed_gas() (gas: 29673) +RMN_voteToBless_Blessed_Benchmark:test_1RootSuccess_gas() (gas: 27619) +RMN_voteToBless_Blessed_Benchmark:test_3RootSuccess_gas() (gas: 81611) +RMN_voteToBless_Blessed_Benchmark:test_5RootSuccess_gas() (gas: 135497) +RMN_voteToCurse:test_CurseOnlyWhenThresholdReached_Success() (gas: 1650405) +RMN_voteToCurse:test_EmptySubjects_Revert() (gas: 14031) +RMN_voteToCurse:test_EvenIfAlreadyCursed_Success() (gas: 534854) +RMN_voteToCurse:test_OwnerCanCurseAndUncurse() (gas: 399532) +RMN_voteToCurse:test_RepeatedSubject_Revert() (gas: 144336) +RMN_voteToCurse:test_ReusedCurseId_Revert() (gas: 146885) +RMN_voteToCurse:test_UnauthorizedVoter_Revert() (gas: 12630) +RMN_voteToCurse:test_VoteToCurse_NoCurse_Success() (gas: 187388) +RMN_voteToCurse:test_VoteToCurse_YesCurse_Success() (gas: 472854) +RMN_voteToCurse_2:test_VotesAreDroppedIfSubjectIsNotCursedDuringConfigChange() (gas: 370837) +RMN_voteToCurse_2:test_VotesAreRetainedIfSubjectIsCursedDuringConfigChange() (gas: 1153282) +RMN_voteToCurse_Benchmark_1:test_VoteToCurse_NewSubject_NewVoter_NoCurse_gas() (gas: 141079) +RMN_voteToCurse_Benchmark_1:test_VoteToCurse_NewSubject_NewVoter_YesCurse_gas() (gas: 165213) +RMN_voteToCurse_Benchmark_2:test_VoteToCurse_OldSubject_NewVoter_NoCurse_gas() (gas: 121413) +RMN_voteToCurse_Benchmark_2:test_VoteToCurse_OldSubject_OldVoter_NoCurse_gas() (gas: 98355) +RMN_voteToCurse_Benchmark_3:test_VoteToCurse_OldSubject_NewVoter_YesCurse_gas() (gas: 145748) +RateLimiter_constructor:test_Constructor_Success() (gas: 19704) +RateLimiter_consume:test_AggregateValueMaxCapacityExceeded_Revert() (gas: 16006) +RateLimiter_consume:test_AggregateValueRateLimitReached_Revert() (gas: 22345) +RateLimiter_consume:test_ConsumeAggregateValue_Success() (gas: 31443) +RateLimiter_consume:test_ConsumeTokens_Success() (gas: 20366) +RateLimiter_consume:test_ConsumeUnlimited_Success() (gas: 40573) +RateLimiter_consume:test_ConsumingMoreThanUint128_Revert() (gas: 15786) +RateLimiter_consume:test_RateLimitReachedOverConsecutiveBlocks_Revert() (gas: 25747) +RateLimiter_consume:test_Refill_Success() (gas: 37354) +RateLimiter_consume:test_TokenMaxCapacityExceeded_Revert() (gas: 18340) +RateLimiter_consume:test_TokenRateLimitReached_Revert() (gas: 24823) +RateLimiter_currentTokenBucketState:test_CurrentTokenBucketState_Success() (gas: 38875) +RateLimiter_currentTokenBucketState:test_Refill_Success() (gas: 46768) +RateLimiter_setTokenBucketConfig:test_SetRateLimiterConfig_Success() (gas: 38446) +RegistryModuleOwnerCustom_constructor:test_constructor_Revert() (gas: 36037) +RegistryModuleOwnerCustom_registerAdminViaGetCCIPAdmin:test_registerAdminViaGetCCIPAdmin_Revert() (gas: 19643) +RegistryModuleOwnerCustom_registerAdminViaGetCCIPAdmin:test_registerAdminViaGetCCIPAdmin_Success() (gas: 129930) +RegistryModuleOwnerCustom_registerAdminViaOwner:test_registerAdminViaOwner_Revert() (gas: 19457) +RegistryModuleOwnerCustom_registerAdminViaOwner:test_registerAdminViaOwner_Success() (gas: 129743) +Router_applyRampUpdates:test_OffRampMismatch_Revert() (gas: 89306) +Router_applyRampUpdates:test_OffRampUpdatesWithRouting() (gas: 10648972) +Router_applyRampUpdates:test_OnRampDisable() (gas: 55971) +Router_applyRampUpdates:test_OnlyOwner_Revert() (gas: 12317) +Router_ccipSend:test_CCIPSendLinkFeeNoTokenSuccess_gas() (gas: 114039) +Router_ccipSend:test_CCIPSendLinkFeeOneTokenSuccess_gas() (gas: 201534) +Router_ccipSend:test_CCIPSendNativeFeeNoTokenSuccess_gas() (gas: 128767) +Router_ccipSend:test_CCIPSendNativeFeeOneTokenSuccess_gas() (gas: 216264) +Router_ccipSend:test_FeeTokenAmountTooLow_Revert() (gas: 66368) +Router_ccipSend:test_InvalidMsgValue() (gas: 32008) +Router_ccipSend:test_NativeFeeTokenInsufficientValue() (gas: 68827) +Router_ccipSend:test_NativeFeeTokenOverpay_Success() (gas: 173903) +Router_ccipSend:test_NativeFeeTokenZeroValue() (gas: 56109) +Router_ccipSend:test_NativeFeeToken_Success() (gas: 172497) +Router_ccipSend:test_NonLinkFeeToken_Success() (gas: 242837) +Router_ccipSend:test_UnsupportedDestinationChain_Revert() (gas: 24761) +Router_ccipSend:test_WhenNotHealthy_Revert() (gas: 44736) +Router_ccipSend:test_WrappedNativeFeeToken_Success() (gas: 174755) +Router_ccipSend:test_ZeroFeeAndGasPrice_Success() (gas: 245046) Router_constructor:test_Constructor_Success() (gas: 13070) Router_getArmProxy:test_getArmProxy() (gas: 10561) -Router_getFee:test_GetFeeSupportedChain_Success() (gas: 46458) -Router_getFee:test_UnsupportedDestinationChain_Revert() (gas: 17138) +Router_getFee:test_GetFeeSupportedChain_Success() (gas: 46536) +Router_getFee:test_UnsupportedDestinationChain_Revert() (gas: 17144) Router_getSupportedTokens:test_GetSupportedTokens_Revert() (gas: 10460) Router_recoverTokens:test_RecoverTokensInvalidRecipient_Revert() (gas: 11316) Router_recoverTokens:test_RecoverTokensNoFunds_Revert() (gas: 20261) Router_recoverTokens:test_RecoverTokensNonOwner_Revert() (gas: 11159) -Router_recoverTokens:test_RecoverTokensValueReceiver_Revert() (gas: 422138) +Router_recoverTokens:test_RecoverTokensValueReceiver_Revert() (gas: 402507) Router_recoverTokens:test_RecoverTokens_Success() (gas: 52437) -Router_routeMessage:test_AutoExec_Success() (gas: 42684) -Router_routeMessage:test_ExecutionEvent_Success() (gas: 157989) -Router_routeMessage:test_ManualExec_Success() (gas: 35381) -Router_routeMessage:test_OnlyOffRamp_Revert() (gas: 25116) -Router_routeMessage:test_WhenNotHealthy_Revert() (gas: 44724) +Router_routeMessage:test_AutoExec_Success() (gas: 42738) +Router_routeMessage:test_ExecutionEvent_Success() (gas: 158166) +Router_routeMessage:test_ManualExec_Success() (gas: 35429) +Router_routeMessage:test_OnlyOffRamp_Revert() (gas: 25140) +Router_routeMessage:test_WhenNotHealthy_Revert() (gas: 44742) Router_setWrappedNative:test_OnlyOwner_Revert() (gas: 10986) -SelfFundedPingPong_ccipReceive:test_FundingIfNotANop_Revert() (gas: 55531) -SelfFundedPingPong_ccipReceive:test_Funding_Success() (gas: 419466) -SelfFundedPingPong_setCountIncrBeforeFunding:test_setCountIncrBeforeFunding() (gas: 20151) -TokenAdminRegistry_acceptAdminRole:test_acceptAdminRole_OnlyPendingAdministrator_Revert() (gas: 51085) -TokenAdminRegistry_acceptAdminRole:test_acceptAdminRole_Success() (gas: 43947) -TokenAdminRegistry_addRegistryModule:test_addRegistryModule_OnlyOwner_Revert() (gas: 12629) -TokenAdminRegistry_addRegistryModule:test_addRegistryModule_Success() (gas: 67011) +SelfFundedPingPong_ccipReceive:test_FundingIfNotANop_Revert() (gas: 55572) +SelfFundedPingPong_ccipReceive:test_Funding_Success() (gas: 420162) +SelfFundedPingPong_setCountIncrBeforeFunding:test_setCountIncrBeforeFunding() (gas: 20169) +TokenAdminRegistry_acceptAdminRole:test_acceptAdminRole_OnlyPendingAdministrator_Revert() (gas: 51109) +TokenAdminRegistry_acceptAdminRole:test_acceptAdminRole_Success() (gas: 43956) +TokenAdminRegistry_addRegistryModule:test_addRegistryModule_OnlyOwner_Revert() (gas: 12641) +TokenAdminRegistry_addRegistryModule:test_addRegistryModule_Success() (gas: 67038) TokenAdminRegistry_getAllConfiguredTokens:test_getAllConfiguredTokens_outOfBounds_Success() (gas: 11350) -TokenAdminRegistry_getPool:test_getPool_Success() (gas: 17581) -TokenAdminRegistry_getPools:test_getPools_Success() (gas: 39902) -TokenAdminRegistry_isAdministrator:test_isAdministrator_Success() (gas: 105922) -TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_AlreadyRegistered_Revert() (gas: 104037) -TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_OnlyRegistryModule_Revert() (gas: 15493) -TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_ZeroAddress_Revert() (gas: 15038) -TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_module_Success() (gas: 112548) -TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_owner_Success() (gas: 107668) -TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_reRegisterWhileUnclaimed_Success() (gas: 115698) -TokenAdminRegistry_removeRegistryModule:test_removeRegistryModule_OnlyOwner_Revert() (gas: 12585) -TokenAdminRegistry_removeRegistryModule:test_removeRegistryModule_Success() (gas: 54473) -TokenAdminRegistry_setPool:test_setPool_InvalidTokenPoolToken_Revert() (gas: 19154) -TokenAdminRegistry_setPool:test_setPool_OnlyAdministrator_Revert() (gas: 18020) -TokenAdminRegistry_setPool:test_setPool_Success() (gas: 35949) -TokenAdminRegistry_setPool:test_setPool_ZeroAddressRemovesPool_Success() (gas: 30623) -TokenAdminRegistry_transferAdminRole:test_transferAdminRole_OnlyAdministrator_Revert() (gas: 18043) +TokenAdminRegistry_getPool:test_getPool_Success() (gas: 17596) +TokenAdminRegistry_getPools:test_getPools_Success() (gas: 39920) +TokenAdminRegistry_isAdministrator:test_isAdministrator_Success() (gas: 105946) +TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_AlreadyRegistered_Revert() (gas: 104067) +TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_OnlyRegistryModule_Revert() (gas: 15499) +TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_ZeroAddress_Revert() (gas: 15044) +TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_module_Success() (gas: 112572) +TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_owner_Success() (gas: 107686) +TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_reRegisterWhileUnclaimed_Success() (gas: 115710) +TokenAdminRegistry_removeRegistryModule:test_removeRegistryModule_OnlyOwner_Revert() (gas: 12597) +TokenAdminRegistry_removeRegistryModule:test_removeRegistryModule_Success() (gas: 54495) +TokenAdminRegistry_setPool:test_setPool_InvalidTokenPoolToken_Revert() (gas: 19166) +TokenAdminRegistry_setPool:test_setPool_OnlyAdministrator_Revert() (gas: 18026) +TokenAdminRegistry_setPool:test_setPool_Success() (gas: 35961) +TokenAdminRegistry_setPool:test_setPool_ZeroAddressRemovesPool_Success() (gas: 30635) +TokenAdminRegistry_transferAdminRole:test_transferAdminRole_OnlyAdministrator_Revert() (gas: 18085) TokenAdminRegistry_transferAdminRole:test_transferAdminRole_Success() (gas: 49390) -TokenPoolAndProxy:test_lockOrBurn_burnMint_Success() (gas: 6070356) -TokenPoolAndProxy:test_lockOrBurn_burnWithFromMint_Success() (gas: 6101829) -TokenPoolAndProxy:test_lockOrBurn_lockRelease_Success() (gas: 6319597) -TokenPoolAndProxy:test_setPreviousPool_Success() (gas: 3387124) -TokenPoolAndProxyMigration:test_tokenPoolMigration_Success_1_2() (gas: 6916281) -TokenPoolAndProxyMigration:test_tokenPoolMigration_Success_1_4() (gas: 7100309) -TokenPoolWithAllowList_applyAllowListUpdates:test_AllowListNotEnabled_Revert() (gas: 2209840) -TokenPoolWithAllowList_applyAllowListUpdates:test_OnlyOwner_Revert() (gas: 12089) +TokenPoolAndProxy:test_lockOrBurn_burnMint_Success() (gas: 5945631) +TokenPoolAndProxy:test_lockOrBurn_burnWithFromMint_Success() (gas: 5977107) +TokenPoolAndProxy:test_lockOrBurn_lockRelease_Success() (gas: 6179838) +TokenPoolAndProxy:test_setPreviousPool_Success() (gas: 3334200) +TokenPoolAndProxyMigration:test_tokenPoolMigration_Success_1_2() (gas: 6792268) +TokenPoolAndProxyMigration:test_tokenPoolMigration_Success_1_4() (gas: 7024950) +TokenPoolWithAllowList_applyAllowListUpdates:test_AllowListNotEnabled_Revert() (gas: 2100002) +TokenPoolWithAllowList_applyAllowListUpdates:test_OnlyOwner_Revert() (gas: 12101) TokenPoolWithAllowList_applyAllowListUpdates:test_SetAllowListSkipsZero_Success() (gas: 23464) -TokenPoolWithAllowList_applyAllowListUpdates:test_SetAllowList_Success() (gas: 177792) +TokenPoolWithAllowList_applyAllowListUpdates:test_SetAllowList_Success() (gas: 177802) TokenPoolWithAllowList_getAllowList:test_GetAllowList_Success() (gas: 23740) TokenPoolWithAllowList_getAllowListEnabled:test_GetAllowListEnabled_Success() (gas: 8363) TokenPoolWithAllowList_setRouter:test_SetRouter_Success() (gas: 24843) -TokenPool_applyChainUpdates:test_applyChainUpdates_DisabledNonZeroRateLimit_Revert() (gas: 271305) -TokenPool_applyChainUpdates:test_applyChainUpdates_InvalidRateLimitRate_Revert() (gas: 541162) -TokenPool_applyChainUpdates:test_applyChainUpdates_NonExistentChain_Revert() (gas: 18344) -TokenPool_applyChainUpdates:test_applyChainUpdates_OnlyCallableByOwner_Revert() (gas: 11385) -TokenPool_applyChainUpdates:test_applyChainUpdates_Success() (gas: 476468) -TokenPool_applyChainUpdates:test_applyChainUpdates_ZeroAddressNotAllowed_Revert() (gas: 157074) -TokenPool_constructor:test_ZeroAddressNotAllowed_Revert() (gas: 70721) +TokenPool_applyChainUpdates:test_applyChainUpdates_DisabledNonZeroRateLimit_Revert() (gas: 271551) +TokenPool_applyChainUpdates:test_applyChainUpdates_InvalidRateLimitRate_Revert() (gas: 542134) +TokenPool_applyChainUpdates:test_applyChainUpdates_NonExistentChain_Revert() (gas: 18449) +TokenPool_applyChainUpdates:test_applyChainUpdates_OnlyCallableByOwner_Revert() (gas: 11391) +TokenPool_applyChainUpdates:test_applyChainUpdates_Success() (gas: 477675) +TokenPool_applyChainUpdates:test_applyChainUpdates_ZeroAddressNotAllowed_Revert() (gas: 157320) +TokenPool_constructor:test_ZeroAddressNotAllowed_Revert() (gas: 70594) TokenPool_constructor:test_immutableFields_Success() (gas: 20544) -TokenPool_getRemotePool:test_getRemotePool_Success() (gas: 273962) -TokenPool_onlyOffRamp:test_CallerIsNotARampOnRouter_Revert() (gas: 276921) -TokenPool_onlyOffRamp:test_ChainNotAllowed_Revert() (gas: 289432) -TokenPool_onlyOffRamp:test_onlyOffRamp_Success() (gas: 349729) -TokenPool_onlyOnRamp:test_CallerIsNotARampOnRouter_Revert() (gas: 276655) -TokenPool_onlyOnRamp:test_ChainNotAllowed_Revert() (gas: 253458) -TokenPool_onlyOnRamp:test_onlyOnRamp_Success() (gas: 304770) -TokenPool_setChainRateLimiterConfig:test_NonExistentChain_Revert() (gas: 17073) -TokenPool_setChainRateLimiterConfig:test_OnlyOwnerOrRateLimitAdmin_Revert() (gas: 15074) -TokenPool_setRemotePool:test_setRemotePool_NonExistentChain_Reverts() (gas: 15620) -TokenPool_setRemotePool:test_setRemotePool_OnlyOwner_Reverts() (gas: 13195) -TokenPool_setRemotePool:test_setRemotePool_Success() (gas: 281912) -TokenProxy_ccipSend:test_CcipSendGasShouldBeZero_Revert() (gas: 17109) -TokenProxy_ccipSend:test_CcipSendInsufficientAllowance_Revert() (gas: 136222) -TokenProxy_ccipSend:test_CcipSendInvalidToken_Revert() (gas: 15919) -TokenProxy_ccipSend:test_CcipSendNative_Success() (gas: 245173) -TokenProxy_ccipSend:test_CcipSendNoDataAllowed_Revert() (gas: 16303) -TokenProxy_ccipSend:test_CcipSend_Success() (gas: 261558) +TokenPool_getRemotePool:test_getRemotePool_Success() (gas: 274133) +TokenPool_onlyOffRamp:test_CallerIsNotARampOnRouter_Revert() (gas: 277110) +TokenPool_onlyOffRamp:test_ChainNotAllowed_Revert() (gas: 289682) +TokenPool_onlyOffRamp:test_onlyOffRamp_Success() (gas: 349912) +TokenPool_onlyOnRamp:test_CallerIsNotARampOnRouter_Revert() (gas: 276850) +TokenPool_onlyOnRamp:test_ChainNotAllowed_Revert() (gas: 253710) +TokenPool_onlyOnRamp:test_onlyOnRamp_Success() (gas: 304962) +TokenPool_setChainRateLimiterConfig:test_NonExistentChain_Revert() (gas: 17142) +TokenPool_setChainRateLimiterConfig:test_OnlyOwnerOrRateLimitAdmin_Revert() (gas: 15137) +TokenPool_setRemotePool:test_setRemotePool_NonExistentChain_Reverts() (gas: 15653) +TokenPool_setRemotePool:test_setRemotePool_OnlyOwner_Reverts() (gas: 13201) +TokenPool_setRemotePool:test_setRemotePool_Success() (gas: 282083) +TokenProxy_ccipSend:test_CcipSendGasShouldBeZero_Revert() (gas: 17121) +TokenProxy_ccipSend:test_CcipSendInsufficientAllowance_Revert() (gas: 136330) +TokenProxy_ccipSend:test_CcipSendInvalidToken_Revert() (gas: 15931) +TokenProxy_ccipSend:test_CcipSendNative_Success() (gas: 245419) +TokenProxy_ccipSend:test_CcipSendNoDataAllowed_Revert() (gas: 16315) +TokenProxy_ccipSend:test_CcipSend_Success() (gas: 261760) TokenProxy_constructor:test_Constructor() (gas: 13812) -TokenProxy_getFee:test_GetFeeGasShouldBeZero_Revert() (gas: 16827) -TokenProxy_getFee:test_GetFeeInvalidToken_Revert() (gas: 12658) -TokenProxy_getFee:test_GetFeeNoDataAllowed_Revert() (gas: 15852) -TokenProxy_getFee:test_GetFee_Success() (gas: 86690) -USDCTokenPool__validateMessage:test_ValidateInvalidMessage_Revert() (gas: 25338) -USDCTokenPool_lockOrBurn:test_CallerIsNotARampOnRouter_Revert() (gas: 35352) -USDCTokenPool_lockOrBurn:test_LockOrBurnWithAllowList_Revert() (gas: 30094) -USDCTokenPool_lockOrBurn:test_LockOrBurn_Success() (gas: 133112) -USDCTokenPool_lockOrBurn:test_UnknownDomain_Revert() (gas: 477240) -USDCTokenPool_releaseOrMint:test_ReleaseOrMintRealTx_Success() (gas: 268166) -USDCTokenPool_releaseOrMint:test_TokenMaxCapacityExceeded_Revert() (gas: 50700) -USDCTokenPool_releaseOrMint:test_UnlockingUSDCFailed_Revert() (gas: 98609) +TokenProxy_getFee:test_GetFeeGasShouldBeZero_Revert() (gas: 16839) +TokenProxy_getFee:test_GetFeeInvalidToken_Revert() (gas: 12670) +TokenProxy_getFee:test_GetFeeNoDataAllowed_Revert() (gas: 15864) +TokenProxy_getFee:test_GetFee_Success() (gas: 86882) +USDCTokenPool__validateMessage:test_ValidateInvalidMessage_Revert() (gas: 25407) +USDCTokenPool_lockOrBurn:test_CallerIsNotARampOnRouter_Revert() (gas: 35364) +USDCTokenPool_lockOrBurn:test_LockOrBurnWithAllowList_Revert() (gas: 30106) +USDCTokenPool_lockOrBurn:test_LockOrBurn_Success() (gas: 133143) +USDCTokenPool_lockOrBurn:test_UnknownDomain_Revert() (gas: 477468) +USDCTokenPool_releaseOrMint:test_ReleaseOrMintRealTx_Success() (gas: 268219) +USDCTokenPool_releaseOrMint:test_TokenMaxCapacityExceeded_Revert() (gas: 50718) +USDCTokenPool_releaseOrMint:test_UnlockingUSDCFailed_Revert() (gas: 98636) USDCTokenPool_setDomains:test_InvalidDomain_Revert() (gas: 66174) -USDCTokenPool_setDomains:test_OnlyOwner_Revert() (gas: 11333) +USDCTokenPool_setDomains:test_OnlyOwner_Revert() (gas: 11339) USDCTokenPool_supportsInterface:test_SupportsInterface_Success() (gas: 9876) \ No newline at end of file diff --git a/contracts/scripts/native_solc_compile_all_ccip b/contracts/scripts/native_solc_compile_all_ccip index 64fcd9f435..7c4ff56bd8 100755 --- a/contracts/scripts/native_solc_compile_all_ccip +++ b/contracts/scripts/native_solc_compile_all_ccip @@ -10,7 +10,7 @@ SOLC_VERSION="0.8.24" OPTIMIZE_RUNS=26000 OPTIMIZE_RUNS_OFFRAMP=18000 OPTIMIZE_RUNS_ONRAMP=4100 -OPTIMIZE_RUNS_MULTI_OFFRAMP=1999 +OPTIMIZE_RUNS_MULTI_OFFRAMP=1925 SCRIPTPATH="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" diff --git a/contracts/src/v0.8/ccip/offRamp/OffRamp.sol b/contracts/src/v0.8/ccip/offRamp/OffRamp.sol index 6753e260cd..6897ba5751 100644 --- a/contracts/src/v0.8/ccip/offRamp/OffRamp.sol +++ b/contracts/src/v0.8/ccip/offRamp/OffRamp.sol @@ -59,6 +59,7 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { error ZeroAddressNotAllowed(); error InvalidMessageDestChainSelector(uint64 messageDestChainSelector); error SourceChainSelectorMismatch(uint64 reportSourceChainSelector, uint64 messageSourceChainSelector); + error SignatureVerificationDisabled(); /// @dev Atlas depends on this event, if changing, please notify Atlas. event StaticConfigSet(StaticConfig staticConfig); @@ -673,6 +674,10 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { /// @inheritdoc MultiOCR3Base function _afterOCR3ConfigSet(uint8 ocrPluginType) internal override { if (ocrPluginType == uint8(Internal.OCRPluginType.Commit)) { + // Signature verification must be enabled for commit plugin + if (!s_ocrConfigs[ocrPluginType].configInfo.isSignatureVerificationEnabled) { + revert SignatureVerificationDisabled(); + } // When the OCR config changes, we reset the sequence number // since it is scoped per config digest. // Note that s_minSeqNr/roots do not need to be reset as the roots persist diff --git a/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.sol b/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.sol index 39a80808a3..79999fa5b4 100644 --- a/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.sol +++ b/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.sol @@ -1,6 +1,8 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.24; +import {IRMN} from "../../interfaces/IRMN.sol"; + import {AuthorizedCallers} from "../../../shared/access/AuthorizedCallers.sol"; import {NonceManager} from "../../NonceManager.sol"; import {IRMNV2} from "../../interfaces/IRMNV2.sol"; diff --git a/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol index 83da20eb6f..e720b1ddb1 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol @@ -3,7 +3,6 @@ pragma solidity 0.8.24; import {IFeeQuoter} from "../../interfaces/IFeeQuoter.sol"; import {IMessageInterceptor} from "../../interfaces/IMessageInterceptor.sol"; -import {IPriceRegistry} from "../../interfaces/IPriceRegistry.sol"; import {IRMNV2} from "../../interfaces/IRMNV2.sol"; import {IRouter} from "../../interfaces/IRouter.sol"; import {ITokenAdminRegistry} from "../../interfaces/ITokenAdminRegistry.sol"; @@ -13,7 +12,6 @@ import {FeeQuoter} from "../../FeeQuoter.sol"; import {NonceManager} from "../../NonceManager.sol"; import {Client} from "../../libraries/Client.sol"; import {Internal} from "../../libraries/Internal.sol"; -import {MerkleMultiProof} from "../../libraries/MerkleMultiProof.sol"; import {Pool} from "../../libraries/Pool.sol"; import {RateLimiter} from "../../libraries/RateLimiter.sol"; import {MultiOCR3Base} from "../../ocr/MultiOCR3Base.sol"; @@ -2113,8 +2111,8 @@ contract OffRamp_execute is OffRampSetup { ocrPluginType: uint8(Internal.OCRPluginType.Commit), configDigest: s_configDigestCommit, F: s_F, - isSignatureVerificationEnabled: false, - signers: s_emptySigners, + isSignatureVerificationEnabled: true, + signers: s_validSigners, transmitters: s_validTransmitters }); s_offRamp.setOCR3Configs(ocrConfigs); @@ -2457,7 +2455,7 @@ contract OffRamp_trialExecute is OffRampSetup { } } -contract OffRamp__releaseOrMintSingleToken is OffRampSetup { +contract OffRamp_releaseOrMintSingleToken is OffRampSetup { function setUp() public virtual override { super.setUp(); _setupMultipleOffRamps(); @@ -3395,26 +3393,6 @@ contract OffRamp_commit is OffRampSetup { s_offRamp.commit(reportContext, abi.encode(commitReport), rs, ss, rawVs); } - function test_WrongConfigWithoutSigners_Revert() public { - _redeployOffRampWithNoOCRConfigs(); - - OffRamp.CommitReport memory commitReport = _constructCommitReport(); - - MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); - ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ - ocrPluginType: uint8(Internal.OCRPluginType.Commit), - configDigest: s_configDigestCommit, - F: s_F, - isSignatureVerificationEnabled: false, - signers: s_emptySigners, - transmitters: s_validTransmitters - }); - s_offRamp.setOCR3Configs(ocrConfigs); - - vm.expectRevert(); - _commit(commitReport, s_latestSequenceNumber); - } - function test_FailedRMNVerification_Reverts() public { // force RMN verification to fail vm.mockCallRevert(address(s_mockRMNRemote), abi.encodeWithSelector(IRMNV2.verify.selector), bytes("")); @@ -3583,3 +3561,31 @@ contract OffRamp_commit is OffRampSetup { }); } } + +contract OffRamp_afterOC3ConfigSet is OffRampSetup { + function test_afterOCR3ConfigSet_SignatureVerificationDisabled_Revert() public { + s_offRamp = new OffRampHelper( + OffRamp.StaticConfig({ + chainSelector: DEST_CHAIN_SELECTOR, + rmn: s_mockRMNRemote, + tokenAdminRegistry: address(s_tokenAdminRegistry), + nonceManager: address(s_inboundNonceManager) + }), + _generateDynamicOffRampConfig(address(s_feeQuoter)), + new OffRamp.SourceChainConfigArgs[](0) + ); + + MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); + ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ + ocrPluginType: uint8(Internal.OCRPluginType.Commit), + configDigest: s_configDigestCommit, + F: s_F, + isSignatureVerificationEnabled: false, + signers: s_validSigners, + transmitters: s_validTransmitters + }); + + vm.expectRevert(OffRamp.SignatureVerificationDisabled.selector); + s_offRamp.setOCR3Configs(ocrConfigs); + } +} diff --git a/contracts/src/v0.8/ccip/test/offRamp/OffRampSetup.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRampSetup.t.sol index 2d65ee735c..bb890ef1b8 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/OffRampSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRampSetup.t.sol @@ -3,7 +3,6 @@ pragma solidity 0.8.24; import {IAny2EVMMessageReceiver} from "../../interfaces/IAny2EVMMessageReceiver.sol"; import {ICommitStore} from "../../interfaces/ICommitStore.sol"; -import {IRMN} from "../../interfaces/IRMN.sol"; import {IRMNV2} from "../../interfaces/IRMNV2.sol"; import {AuthorizedCallers} from "../../../shared/access/AuthorizedCallers.sol"; @@ -16,7 +15,6 @@ import {MultiOCR3Base} from "../../ocr/MultiOCR3Base.sol"; import {EVM2EVMOffRamp} from "../../offRamp/EVM2EVMOffRamp.sol"; import {OffRamp} from "../../offRamp/OffRamp.sol"; import {TokenPool} from "../../pools/TokenPool.sol"; - import {FeeQuoterSetup} from "../feeQuoter/FeeQuoterSetup.t.sol"; import {EVM2EVMOffRampHelper} from "../helpers/EVM2EVMOffRampHelper.sol"; import {MaybeRevertingBurnMintTokenPool} from "../helpers/MaybeRevertingBurnMintTokenPool.sol"; diff --git a/core/gethwrappers/ccip/generated/offramp/offramp.go b/core/gethwrappers/ccip/generated/offramp/offramp.go index 3204871921..f7de788882 100644 --- a/core/gethwrappers/ccip/generated/offramp/offramp.go +++ b/core/gethwrappers/ccip/generated/offramp/offramp.go @@ -162,8 +162,8 @@ type OffRampStaticConfig struct { } var OffRampMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CanOnlySelfCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"actual\",\"type\":\"bytes32\"}],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ExecutionError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"ForkedChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enumMultiOCR3Base.InvalidConfigErrorType\",\"name\":\"errorType\",\"type\":\"uint8\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"got\",\"type\":\"uint256\"}],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidEVMAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"name\":\"InvalidInterval\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"newLimit\",\"type\":\"uint256\"}],\"name\":\"InvalidManualExecutionGasLimit\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"messageDestChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidMessageDestChainSelector\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"newState\",\"type\":\"uint8\"}],\"name\":\"InvalidNewState\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRoot\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidStaticConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LeavesCannotBeEmpty\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ManualExecutionGasLimitMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"ManualExecutionNotYetEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"errorReason\",\"type\":\"bytes\"}],\"name\":\"MessageValidationError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonUniqueSignatures\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"notPool\",\"type\":\"address\"}],\"name\":\"NotACompatiblePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OracleCannotBeZeroAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ReceiverError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountReleased\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePre\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePost\",\"type\":\"uint256\"}],\"name\":\"ReleaseOrMintBalanceMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"name\":\"RootAlreadyCommitted\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"RootNotCommitted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignaturesOutOfRegistration\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"reportSourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"messageSourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainSelectorMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"StaleCommitReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"StaticConfigCannotBeChanged\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"TokenDataMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"TokenHandlingError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnexpectedTokenData\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"WrongMessageLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WrongNumberOfSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroChainSelectorNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"AlreadyAttempted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"structIRMNV2.Signature[]\",\"name\":\"rmnSignatures\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"report\",\"type\":\"tuple\"}],\"name\":\"CommitReportAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"DynamicConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"messageHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"name\":\"ExecutionStateChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"RootRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"SkippedAlreadyExecutedMessage\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SkippedReportExecution\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"sourceConfig\",\"type\":\"tuple\"}],\"name\":\"SourceChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainSelectorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"}],\"name\":\"StaticConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigUpdates\",\"type\":\"tuple[]\"}],\"name\":\"applySourceChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"destTokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structClient.Any2EVMMessage\",\"name\":\"\",\"type\":\"tuple\"}],\"name\":\"ccipReceive\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"rawVs\",\"type\":\"bytes32\"}],\"name\":\"commit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"execute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"bytes[]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[]\"}],\"name\":\"executeSingleMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"getExecutionState\",\"outputs\":[{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLatestPriceSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"getMerkleRoot\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"getSourceChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"latestConfigDetails\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"n\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"}],\"internalType\":\"structMultiOCR3Base.ConfigInfo\",\"name\":\"configInfo\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfig\",\"name\":\"ocrConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage[]\",\"name\":\"messages\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[][]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[][]\"},{\"internalType\":\"bytes32[]\",\"name\":\"proofs\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"proofFlagBits\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.ExecutionReportSingleChain[]\",\"name\":\"reports\",\"type\":\"tuple[]\"},{\"internalType\":\"uint256[][]\",\"name\":\"gasLimitOverrides\",\"type\":\"uint256[][]\"}],\"name\":\"manuallyExecute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"setDynamicConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfigArgs[]\",\"name\":\"ocrConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"setOCR3Configs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x6101206040523480156200001257600080fd5b5060405162006c9638038062006c968339810160408190526200003591620008c7565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf81620001fa565b5050466080525060208301516001600160a01b03161580620000ec575060408301516001600160a01b0316155b8062000103575060608301516001600160a01b0316155b1562000122576040516342bcdf7f60e11b815260040160405180910390fd5b82516001600160401b03166000036200014e5760405163c656089560e01b815260040160405180910390fd5b82516001600160401b0390811660a052602080850180516001600160a01b0390811660c05260408088018051831660e0526060808a01805185166101005283518b519098168852945184169587019590955251821690850152905116908201527f683eb52ee924eb817377cfa8f41f238f4bb7a877da5267869dfffbad85f564d89060800160405180910390a1620001e682620002a5565b620001f181620003c1565b50505062000c67565b336001600160a01b03821603620002545760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b0316620002ce576040516342bcdf7f60e11b815260040160405180910390fd5b80516004805460208085018051604080880180516060808b0180516001600160a01b039b8c166001600160c01b0319909a168a17600160a01b63ffffffff98891602176001600160c01b0316600160c01b948816949094026001600160e01b031693909317600160e01b93871693909302929092179098556080808b018051600580546001600160a01b031916918d169190911790558451988952955185169688019690965290518316918601919091525116938301939093529151909216908201527fa55bd56595c45f517e5967a3067f3dca684445a3080e7c04a4e0d5a40cda627d9060a00160405180910390a150565b60005b815181101562000666576000828281518110620003e557620003e562000a1d565b60200260200101519050600081602001519050806001600160401b0316600003620004235760405163c656089560e01b815260040160405180910390fd5b81516001600160a01b03166200044c576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160401b0381166000908152600660205260408120600181018054919291620004789062000a33565b80601f0160208091040260200160405190810160405280929190818152602001828054620004a69062000a33565b8015620004f75780601f10620004cb57610100808354040283529160200191620004f7565b820191906000526020600020905b815481529060010190602001808311620004d957829003601f168201915b5050505050905060008460600151905081516000036200059e57805160000362000534576040516342bcdf7f60e11b815260040160405180910390fd5b6001830162000544828262000ac4565b508254600160a81b600160e81b031916600160a81b1783556040516001600160401b03851681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1620005d9565b8080519060200120828051906020012014620005d95760405163c39a620560e01b81526001600160401b038516600482015260240162000083565b604080860151845487516001600160a01b03166001600160a01b0319921515600160a01b02929092166001600160a81b031990911617178455516001600160401b038516907f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b906200064d90869062000b90565b60405180910390a25050505050806001019050620003c4565b5050565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b0381118282101715620006a557620006a56200066a565b60405290565b604051601f8201601f191681016001600160401b0381118282101715620006d657620006d66200066a565b604052919050565b80516001600160401b0381168114620006f657600080fd5b919050565b6001600160a01b03811681146200071157600080fd5b50565b805163ffffffff81168114620006f657600080fd5b6000601f83601f8401126200073d57600080fd5b825160206001600160401b03808311156200075c576200075c6200066a565b8260051b6200076d838201620006ab565b93845286810183019383810190898611156200078857600080fd5b84890192505b85831015620008ba57825184811115620007a85760008081fd5b89016080601f19828d038101821315620007c25760008081fd5b620007cc62000680565b88840151620007db81620006fb565b81526040620007ec858201620006de565b8a8301526060808601518015158114620008065760008081fd5b838301529385015193898511156200081e5760008081fd5b84860195508f603f8701126200083657600094508485fd5b8a8601519450898511156200084f576200084f6200066a565b620008608b858f88011601620006ab565b93508484528f82868801011115620008785760008081fd5b60005b8581101562000898578681018301518582018d01528b016200087b565b5060009484018b0194909452509182015283525091840191908401906200078e565b9998505050505050505050565b6000806000838503610140811215620008df57600080fd5b6080811215620008ee57600080fd5b620008f862000680565b6200090386620006de565b815260208601516200091581620006fb565b602082015260408601516200092a81620006fb565b604082015260608601516200093f81620006fb565b6060820152935060a0607f19820112156200095957600080fd5b5060405160a081016001600160401b0380821183831017156200098057620009806200066a565b81604052608087015191506200099682620006fb565b818352620009a760a0880162000714565b6020840152620009ba60c0880162000714565b6040840152620009cd60e0880162000714565b60608401526101008701519150620009e582620006fb565b608083018290526101208701519294508083111562000a0357600080fd5b505062000a138682870162000729565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b600181811c9082168062000a4857607f821691505b60208210810362000a6957634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111562000abf576000816000526020600020601f850160051c8101602086101562000a9a5750805b601f850160051c820191505b8181101562000abb5782815560010162000aa6565b5050505b505050565b81516001600160401b0381111562000ae05762000ae06200066a565b62000af88162000af1845462000a33565b8462000a6f565b602080601f83116001811462000b30576000841562000b175750858301515b600019600386901b1c1916600185901b17855562000abb565b600085815260208120601f198616915b8281101562000b615788860151825594840194600190910190840162000b40565b508582101562000b805787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b602080825282546001600160a01b0381168383015260a081901c60ff161515604084015260a81c6001600160401b0316606083015260808083015260018084018054600093929190849062000be58162000a33565b8060a089015260c0600183166000811462000c09576001811462000c265762000c58565b60ff19841660c08b015260c083151560051b8b0101945062000c58565b85600052602060002060005b8481101562000c4f5781548c820185015290880190890162000c32565b8b0160c0019550505b50929998505050505050505050565b60805160a05160c05160e05161010051615fb962000cdd600039600081816102400152612a8a0152600081816102110152612f7e0152600081816101e20152818161077f01528181610986015261240c0152600081816101b201526126990152600081816117dd01526118290152615fb96000f3fe608060405234801561001057600080fd5b50600436106101515760003560e01c806379ba5097116100cd578063c673e58411610081578063e9d68a8e11610066578063e9d68a8e1461052a578063f2fde38b1461054a578063f716f99f1461055d57600080fd5b8063c673e584146104c5578063ccd37ba3146104e557600080fd5b80638da5cb5b116100b25780638da5cb5b14610484578063991a50181461049f578063a80036b4146104b257600080fd5b806379ba50971461046e57806385572ffb1461047657600080fd5b80632d04ab76116101245780633f4b04aa116101095780633f4b04aa146103365780635e36480c146103525780637437ff9f1461037257600080fd5b80632d04ab7614610310578063311cd5131461032357600080fd5b806304666f9c1461015657806305d938b51461016b57806306285c691461017e578063181f5a77146102c7575b600080fd5b6101696101643660046140f6565b610570565b005b610169610179366004614780565b610584565b61027060408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316815250905090565b6040516102be9190815167ffffffffffffffff1681526020808301516001600160a01b0390811691830191909152604080840151821690830152606092830151169181019190915260800190565b60405180910390f35b6103036040518060400160405280601181526020017f4f666652616d7020312e362e302d64657600000000000000000000000000000081525081565b6040516102be91906148fb565b61016961031e3660046149a6565b610729565b610169610331366004614a59565b610cc1565b60095460405167ffffffffffffffff90911681526020016102be565b610365610360366004614aad565b610d2a565b6040516102be9190614b0a565b6104116040805160a081018252600080825260208201819052918101829052606081018290526080810191909152506040805160a0810182526004546001600160a01b03808216835263ffffffff600160a01b83048116602085015278010000000000000000000000000000000000000000000000008304811694840194909452600160e01b9091049092166060820152600554909116608082015290565b6040516102be9190600060a0820190506001600160a01b03808451168352602084015163ffffffff808216602086015280604087015116604086015280606087015116606086015250508060808501511660808401525092915050565b610169610d80565b610169610151366004614b18565b6000546040516001600160a01b0390911681526020016102be565b6101696104ad366004614b67565b610e3e565b6101696104c0366004614bdb565b610e4f565b6104d86104d3366004614c48565b6111c2565b6040516102be9190614ca8565b61051c6104f3366004614d1d565b67ffffffffffffffff919091166000908152600860209081526040808320938352929052205490565b6040519081526020016102be565b61053d610538366004614d47565b611320565b6040516102be9190614d62565b610169610558366004614db0565b61142d565b61016961056b366004614e35565b61143e565b610578611480565b610581816114dc565b50565b61058c6117da565b8151815181146105c8576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b818110156107195760008482815181106105e7576105e7614f73565b6020026020010151905060008160200151519050600085848151811061060f5761060f614f73565b6020026020010151905080518214610653576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8281101561070a57600082828151811061067257610672614f73565b6020026020010151905080600014610701578460200151828151811061069a5761069a614f73565b6020026020010151608001518110156107015784516040517fc8e9605100000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260248101839052604481018290526064015b60405180910390fd5b50600101610656565b505050508060010190506105cb565b50610724838361185b565b505050565b6000610737878901896151a5565b602081015151909150156107e357602081015160408083015190517f30dfc3080000000000000000000000000000000000000000000000000000000081526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016926330dfc308926107b292600401615409565b60006040518083038186803b1580156107ca57600080fd5b505afa1580156107de573d6000803e3d6000fd5b505050505b805151511515806107f957508051602001515115155b156108f95760095460208a01359067ffffffffffffffff808316911610156108b8576009805467ffffffffffffffff191667ffffffffffffffff83161790556004805483516040517f3937306f0000000000000000000000000000000000000000000000000000000081526001600160a01b0390921692633937306f926108819291016154eb565b600060405180830381600087803b15801561089b57600080fd5b505af11580156108af573d6000803e3d6000fd5b505050506108f7565b8160200151516000036108f7576040517f2261116700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b60005b816020015151811015610c0a5760008260200151828151811061092157610921614f73565b602090810291909101015180516040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815277ffffffffffffffff00000000000000000000000000000000608083901b166004820152919250906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632cbc26bb90602401602060405180830381865afa1580156109cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109f191906154fe565b15610a34576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff821660048201526024016106f8565b6000610a3f8261190b565b6020840151815491925067ffffffffffffffff908116600160a81b90920416141580610a865750826040015167ffffffffffffffff16836020015167ffffffffffffffff16115b15610ae7578251602084015160408086015190517fd5e0f0d600000000000000000000000000000000000000000000000000000000815267ffffffffffffffff938416600482015291831660248301529190911660448201526064016106f8565b606083015180610b23576040517f504570e300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b835167ffffffffffffffff16600090815260086020908152604080832084845290915290205415610b965783516040517f32cf0cbf00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602481018290526044016106f8565b6040840151610ba6906001615531565b82547fffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffff16600160a81b67ffffffffffffffff9283160217909255925116600090815260086020908152604080832094835293905291909120429055506001016108fc565b507fd7868a16facbdde7b5c020620136316b3c266fffcb4e1e41cb6a662fe14ba3e181604051610c3a9190615559565b60405180910390a1610cb660008a8a8a8a8a8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808e0282810182019093528d82529093508d92508c9182918501908490808284376000920191909152508b9250611972915050565b505050505050505050565b610d01610cd0828401846155b1565b6040805160008082526020820190925290610cfb565b6060815260200190600190039081610ce65790505b5061185b565b604080516000808252602082019092529050610d24600185858585866000611972565b50505050565b6000610d38600160046155e6565b6002610d4560808561560f565b67ffffffffffffffff16610d599190615636565b610d638585611ce9565b901c166003811115610d7757610d77614ae0565b90505b92915050565b6001546001600160a01b03163314610dda5760405162461bcd60e51b815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064016106f8565b600080543373ffffffffffffffffffffffffffffffffffffffff19808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610e46611480565b61058181611d30565b333014610e88576040517f371a732800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160008082526020820190925281610ec5565b6040805180820190915260008082526020820152815260200190600190039081610e9e5790505b5060a08501515190915015610ef957610ef68460a00151856020015186606001518760000151602001518787611e96565b90505b6040805160a0810182528551518152855160209081015167ffffffffffffffff1681830152808701518351600094840192610f359291016148fb565b60408051601f19818403018152918152908252878101516020830152018390526005549091506001600160a01b03168015611042576040517f08d450a10000000000000000000000000000000000000000000000000000000081526001600160a01b038216906308d450a190610faf9085906004016156ef565b600060405180830381600087803b158015610fc957600080fd5b505af1925050508015610fda575060015b611042573d808015611008576040519150601f19603f3d011682016040523d82523d6000602084013e61100d565b606091505b50806040517f09c253250000000000000000000000000000000000000000000000000000000081526004016106f891906148fb565b60408601515115801561105757506080860151155b8061106e575060608601516001600160a01b03163b155b806110ae575060608601516110ac906001600160a01b03167f85572ffb00000000000000000000000000000000000000000000000000000000611fb5565b155b156110bb57505050505050565b855160209081015167ffffffffffffffff1660009081526006909152604080822054608089015160608a015192517f3cf9798300000000000000000000000000000000000000000000000000000000815284936001600160a01b0390931692633cf97983926111339289926113889291600401615702565b6000604051808303816000875af1158015611152573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261117a919081019061573e565b5091509150816111b857806040517f0a8d6e8c0000000000000000000000000000000000000000000000000000000081526004016106f891906148fb565b5050505050505050565b6112056040805160e081019091526000606082018181526080830182905260a0830182905260c08301919091528190815260200160608152602001606081525090565b60ff808316600090815260026020818152604092839020835160e081018552815460608201908152600183015480881660808401526101008104881660a0840152620100009004909616151560c0820152948552918201805484518184028101840190955280855292938583019390928301828280156112ae57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611290575b505050505081526020016003820180548060200260200160405190810160405280929190818152602001828054801561131057602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116112f2575b5050505050815250509050919050565b604080516080808201835260008083526020808401829052838501829052606080850181905267ffffffffffffffff878116845260068352928690208651948501875280546001600160a01b0381168652600160a01b810460ff16151593860193909352600160a81b9092049092169483019490945260018401805493949293918401916113ad906157d4565b80601f01602080910402602001604051908101604052809291908181526020018280546113d9906157d4565b80156113105780601f106113fb57610100808354040283529160200191611310565b820191906000526020600020905b81548152906001019060200180831161140957505050919092525091949350505050565b611435611480565b61058181611fd1565b611446611480565b60005b815181101561147c5761147482828151811061146757611467614f73565b6020026020010151612087565b600101611449565b5050565b6000546001600160a01b031633146114da5760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016106f8565b565b60005b815181101561147c5760008282815181106114fc576114fc614f73565b602002602001015190506000816020015190508067ffffffffffffffff16600003611553576040517fc656089500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81516001600160a01b031661157b576040516342bcdf7f60e11b815260040160405180910390fd5b67ffffffffffffffff811660009081526006602052604081206001810180549192916115a6906157d4565b80601f01602080910402602001604051908101604052809291908181526020018280546115d2906157d4565b801561161f5780601f106115f45761010080835404028352916020019161161f565b820191906000526020600020905b81548152906001019060200180831161160257829003601f168201915b5050505050905060008460600151905081516000036116d757805160000361165a576040516342bcdf7f60e11b815260040160405180910390fd5b60018301611668828261585e565b5082547fffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffff16600160a81b17835560405167ffffffffffffffff851681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a161172a565b808051906020012082805190602001201461172a576040517fc39a620500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff851660048201526024016106f8565b604080860151845487516001600160a01b031673ffffffffffffffffffffffffffffffffffffffff19921515600160a01b02929092167fffffffffffffffffffffff000000000000000000000000000000000000000000909116171784555167ffffffffffffffff8516907f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b906117c290869061591e565b60405180910390a250505050508060010190506114df565b467f0000000000000000000000000000000000000000000000000000000000000000146114da576040517f0f01ce850000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060048201524660248201526044016106f8565b8151600003611895576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160408051600080825260208201909252911591905b8451811015611904576118fc8582815181106118ca576118ca614f73565b6020026020010151846118f6578583815181106118e9576118e9614f73565b60200260200101516123b8565b836123b8565b6001016118ac565b5050505050565b67ffffffffffffffff811660009081526006602052604081208054600160a01b900460ff16610d7a576040517fed053c5900000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024016106f8565b60ff878116600090815260026020908152604080832081516080810183528154815260019091015480861693820193909352610100830485169181019190915262010000909104909216151560608301528735906119d18760a46159ec565b9050826060015115611a195784516119ea906020615636565b86516119f7906020615636565b611a029060a06159ec565b611a0c91906159ec565b611a1690826159ec565b90505b368114611a5b576040517f8e1192e1000000000000000000000000000000000000000000000000000000008152600481018290523660248201526044016106f8565b5081518114611aa35781516040517f93df584c0000000000000000000000000000000000000000000000000000000081526004810191909152602481018290526044016106f8565b611aab6117da565b60ff808a1660009081526003602090815260408083203384528252808320815180830190925280548086168352939491939092840191610100909104166002811115611af957611af9614ae0565b6002811115611b0a57611b0a614ae0565b9052509050600281602001516002811115611b2757611b27614ae0565b148015611b7b5750600260008b60ff1660ff168152602001908152602001600020600301816000015160ff1681548110611b6357611b63614f73565b6000918252602090912001546001600160a01b031633145b611bb1576040517fda0f08e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50816060015115611c93576020820151611bcc9060016159ff565b60ff16855114611c08576040517f71253a2500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8351855114611c43576040517fa75d88af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008787604051611c55929190615a18565b604051908190038120611c6c918b90602001615a28565b604051602081830303815290604052805190602001209050611c918a82888888612d38565b505b6040805182815260208a81013567ffffffffffffffff169082015260ff8b16917f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef0910160405180910390a2505050505050505050565b67ffffffffffffffff8216600090815260076020526040812081611d0e608085615a3c565b67ffffffffffffffff1681526020810191909152604001600020549392505050565b80516001600160a01b0316611d58576040516342bcdf7f60e11b815260040160405180910390fd5b80516004805460208085018051604080880180516060808b0180516001600160a01b039b8c167fffffffffffffffff000000000000000000000000000000000000000000000000909a168a17600160a01b63ffffffff988916021777ffffffffffffffffffffffffffffffffffffffffffffffff167801000000000000000000000000000000000000000000000000948816949094026001600160e01b031693909317600160e01b93871693909302929092179098556080808b0180516005805473ffffffffffffffffffffffffffffffffffffffff1916918d169190911790558451988952955185169688019690965290518316918601919091525116938301939093529151909216908201527fa55bd56595c45f517e5967a3067f3dca684445a3080e7c04a4e0d5a40cda627d9060a00160405180910390a150565b6060865167ffffffffffffffff811115611eb257611eb2613f0d565b604051908082528060200260200182016040528015611ef757816020015b6040805180820190915260008082526020820152815260200190600190039081611ed05790505b50905060005b8751811015611fa957611f84888281518110611f1b57611f1b614f73565b6020026020010151888888888887818110611f3857611f38614f73565b9050602002810190611f4a9190615a63565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612f1d92505050565b828281518110611f9657611f96614f73565b6020908102919091010152600101611efd565b505b9695505050505050565b6000611fc0836132c2565b8015610d775750610d778383613326565b336001600160a01b038216036120295760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016106f8565b6001805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b806040015160ff166000036120b2576000604051631b3fab5160e11b81526004016106f89190615aaa565b60208082015160ff8082166000908152600290935260408320600181015492939092839216900361211f57606084015160018201805491151562010000027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff909216919091179055612174565b6060840151600182015460ff6201000090910416151590151514612174576040517f87f6037c00000000000000000000000000000000000000000000000000000000815260ff841660048201526024016106f8565b60a0840151805161010010156121a0576001604051631b3fab5160e11b81526004016106f89190615aaa565b61220684846003018054806020026020016040519081016040528092919081815260200182805480156121fc57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116121de575b50505050506133e1565b84606001511561232d5761227484846002018054806020026020016040519081016040528092919081815260200182805480156121fc576020028201919060005260206000209081546001600160a01b031681526001909101906020018083116121de5750505050506133e1565b6080850151805161010010156122a0576002604051631b3fab5160e11b81526004016106f89190615aaa565b60408601516122b0906003615ac4565b60ff168151116122d6576003604051631b3fab5160e11b81526004016106f89190615aaa565b80516001840180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1661010060ff84160217905561231e9060028601906020840190613e86565b5061232b8582600161344a565b505b6123398482600261344a565b805161234e9060038501906020840190613e86565b5060408581015160018401805460ff191660ff8316179055865180855560a088015192517fab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f547936123a79389939260028a01929190615ae0565b60405180910390a1611904846135be565b815181516040517f2cbc26bb000000000000000000000000000000000000000000000000000000008152608083901b77ffffffffffffffff00000000000000000000000000000000166004820152901515907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632cbc26bb90602401602060405180830381865afa15801561245b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061247f91906154fe565b1561250b5780156124c8576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff831660048201526024016106f8565b60405167ffffffffffffffff831681527faab522ed53d887e56ed53dd37398a01aeef6a58e0fa77c2173beb9512d8949339060200160405180910390a150505050565b60006125168361190b565b6001018054612524906157d4565b80601f0160208091040260200160405190810160405280929190818152602001828054612550906157d4565b801561259d5780601f106125725761010080835404028352916020019161259d565b820191906000526020600020905b81548152906001019060200180831161258057829003601f168201915b505050602088015151929350505060008190036125e5576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8560400151518114612623576040517f57e0e08300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008167ffffffffffffffff81111561263e5761263e613f0d565b604051908082528060200260200182016040528015612667578160200160208202803683370190505b50905060005b828110156127c05760008860200151828151811061268d5761268d614f73565b602002602001015190507f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681600001516040015167ffffffffffffffff161461272057805160409081015190517f38432a2200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016106f8565b8667ffffffffffffffff1681600001516020015167ffffffffffffffff1614612790578051602001516040517f6c95f1eb00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808a16600483015290911660248201526044016106f8565b61279a81866135da565b8383815181106127ac576127ac614f73565b60209081029190910101525060010161266d565b5060006127d786838a606001518b608001516136fc565b90508060000361281f576040517f7dd17a7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff871660048201526024016106f8565b60005b83811015610cb65760005a905060008a60200151838151811061284757612847614f73565b6020026020010151905060006128658a836000015160600151610d2a565b9050600081600381111561287b5761287b614ae0565b14806128985750600381600381111561289657612896614ae0565b145b6128f0578151606001516040805167ffffffffffffffff808e16825290921660208301527f3b575419319662b2a6f5e2467d84521517a3382b908eb3d557bb3fdb0c50e23c91015b60405180910390a1505050612d30565b88156129c057600454600090600160a01b900463ffffffff1661291387426155e6565b11905080806129335750600382600381111561293157612931614ae0565b145b612975576040517fa9cfc86200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8c1660048201526024016106f8565b8b858151811061298757612987614f73565b60200260200101516000146129ba578b85815181106129a8576129a8614f73565b60200260200101518360800181815250505b50612a21565b60008160038111156129d4576129d4614ae0565b14612a21578151606001516040805167ffffffffffffffff808e16825290921660208301527f3ef2a99c550a751d4b0b261268f05a803dfb049ab43616a1ffb388f61fe6512091016128e0565b81516080015167ffffffffffffffff1615612b10576000816003811115612a4a57612a4a614ae0565b03612b105781516080015160208301516040517fe0e03cae0000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169263e0e03cae92612ac1928f929190600401615b8c565b6020604051808303816000875af1158015612ae0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b0491906154fe565b612b1057505050612d30565b60008c604001518581518110612b2857612b28614f73565b6020026020010151905080518360a001515114612b8c578251606001516040517f1cfe6d8b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808e16600483015290911660248201526044016106f8565b612ba08b846000015160600151600161373a565b600080612bad85846137e2565b91509150612bc48d8660000151606001518461373a565b8b15612c34576003826003811115612bde57612bde614ae0565b03612c34576000846003811115612bf757612bf7614ae0565b14612c34578451516040517f2b11b8d90000000000000000000000000000000000000000000000000000000081526106f891908390600401615bb9565b6002826003811115612c4857612c48614ae0565b14612ca2576003826003811115612c6157612c61614ae0565b14612ca2578451606001516040517f926c5a3e0000000000000000000000000000000000000000000000000000000081526106f8918f918590600401615bd2565b84600001516000015185600001516060015167ffffffffffffffff168e67ffffffffffffffff167f05665fe9ad095383d018353f4cbcba77e84db27dd215081bbf7cdf9ae6fbe48b8c8b81518110612cfc57612cfc614f73565b602002602001015186865a612d11908e6155e6565b604051612d219493929190615bf8565b60405180910390a45050505050505b600101612822565b8251600090815b818110156111b8576000600188868460208110612d5e57612d5e614f73565b612d6b91901a601b6159ff565b898581518110612d7d57612d7d614f73565b6020026020010151898681518110612d9757612d97614f73565b602002602001015160405160008152602001604052604051612dd5949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015612df7573d6000803e3d6000fd5b505060408051601f1981015160ff808e166000908152600360209081528582206001600160a01b03851683528152858220858701909652855480841686529397509095509293928401916101009004166002811115612e5857612e58614ae0565b6002811115612e6957612e69614ae0565b9052509050600181602001516002811115612e8657612e86614ae0565b14612ebd576040517fca31867a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051600160ff9091161b851615612f00576040517ff67bc7c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806000015160ff166001901b851794505050806001019050612d3f565b60408051808201909152600080825260208201526000612f4087602001516138ac565b6040517fbbe4f6db0000000000000000000000000000000000000000000000000000000081526001600160a01b0380831660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063bbe4f6db90602401602060405180830381865afa158015612fc5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fe99190615c2f565b90506001600160a01b0381161580613031575061302f6001600160a01b0382167faff2afbf00000000000000000000000000000000000000000000000000000000611fb5565b155b15613073576040517fae9b4ce90000000000000000000000000000000000000000000000000000000081526001600160a01b03821660048201526024016106f8565b60045460009081906130959089908690600160e01b900463ffffffff16613952565b9150915060008060006131626040518061010001604052808e81526020018c67ffffffffffffffff1681526020018d6001600160a01b031681526020018f606001518152602001896001600160a01b031681526020018f6000015181526020018f6040015181526020018b8152506040516024016131139190615c4c565b60408051601f198184030181529190526020810180516001600160e01b03167f390775370000000000000000000000000000000000000000000000000000000017905287866113886084613a80565b925092509250826131a157816040517fe1cd55090000000000000000000000000000000000000000000000000000000081526004016106f891906148fb565b81516020146131e95781516040517f78ef80240000000000000000000000000000000000000000000000000000000081526020600482015260248101919091526044016106f8565b6000828060200190518101906131ff9190615d19565b9050866001600160a01b03168c6001600160a01b0316146132945760006132308d8a61322b868a6155e6565b613952565b5090508681108061324a57508161324788836155e6565b14155b15613292576040517fa966e21f0000000000000000000000000000000000000000000000000000000081526004810183905260248101889052604481018290526064016106f8565b505b604080518082019091526001600160a01b039098168852602088015250949550505050505095945050505050565b60006132ee827f01ffc9a700000000000000000000000000000000000000000000000000000000613326565b8015610d7a575061331f827fffffffff00000000000000000000000000000000000000000000000000000000613326565b1592915050565b6040517fffffffff0000000000000000000000000000000000000000000000000000000082166024820152600090819060440160408051601f19818403018152919052602080820180516001600160e01b03167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825192935060009283928392909183918a617530fa92503d915060005190508280156133ca575060208210155b80156133d65750600081115b979650505050505050565b60005b81518110156107245760ff83166000908152600360205260408120835190919084908490811061341657613416614f73565b6020908102919091018101516001600160a01b03168252810191909152604001600020805461ffff191690556001016133e4565b60005b8251811015610d2457600083828151811061346a5761346a614f73565b602002602001015190506000600281111561348757613487614ae0565b60ff80871660009081526003602090815260408083206001600160a01b038716845290915290205461010090041660028111156134c6576134c6614ae0565b146134e7576004604051631b3fab5160e11b81526004016106f89190615aaa565b6001600160a01b038116613527576040517fd6c62c9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052808360ff16815260200184600281111561354d5761354d614ae0565b905260ff80871660009081526003602090815260408083206001600160a01b0387168452825290912083518154931660ff198416811782559184015190929091839161ffff1916176101008360028111156135aa576135aa614ae0565b02179055509050505080600101905061344d565b60ff8116610581576009805467ffffffffffffffff1916905550565b815160208082015160409283015192516000938493613620937f2425b0b9f9054c76ff151b0a175b18f37a4a4e82013a72e9f15c9caa095ed21f93909291889101615d32565b60408051601f1981840301815290829052805160209182012086518051888401516060808b0151908401516080808d015195015195976136699794969395929491939101615d65565b604051602081830303815290604052805190602001208560400151805190602001208660a001516040516020016136a09190615e6a565b60408051601f198184030181528282528051602091820120908301969096528101939093526060830191909152608082015260a081019190915260c0015b60405160208183030381529060405280519060200120905092915050565b60008061370a858585613ba6565b67ffffffffffffffff8716600090815260086020908152604080832093835292905220549150505b949350505050565b6000600261374960808561560f565b67ffffffffffffffff1661375d9190615636565b9050600061376b8585611ce9565b90508161377a600160046155e6565b901b19168183600381111561379157613791614ae0565b67ffffffffffffffff871660009081526007602052604081209190921b929092179182916137c0608088615a3c565b67ffffffffffffffff1681526020810191909152604001600020555050505050565b6040517fa80036b4000000000000000000000000000000000000000000000000000000008152600090606090309063a80036b4906138269087908790600401615eca565b600060405180830381600087803b15801561384057600080fd5b505af1925050508015613851575060015b613890573d80801561387f576040519150601f19603f3d011682016040523d82523d6000602084013e613884565b606091505b506003925090506138a5565b50506040805160208101909152600081526002905b9250929050565b600081516020146138eb57816040517f8d666f600000000000000000000000000000000000000000000000000000000081526004016106f891906148fb565b6000828060200190518101906139019190615d19565b90506001600160a01b03811180613919575061040081105b15610d7a57826040517f8d666f600000000000000000000000000000000000000000000000000000000081526004016106f891906148fb565b60008060008060006139cc8860405160240161397d91906001600160a01b0391909116815260200190565b60408051601f198184030181529190526020810180516001600160e01b03167f70a082310000000000000000000000000000000000000000000000000000000017905288886113886084613a80565b92509250925082613a0b57816040517fe1cd55090000000000000000000000000000000000000000000000000000000081526004016106f891906148fb565b6020825114613a535781516040517f78ef80240000000000000000000000000000000000000000000000000000000081526020600482015260248101919091526044016106f8565b81806020019051810190613a679190615d19565b613a7182886155e6565b94509450505050935093915050565b6000606060008361ffff1667ffffffffffffffff811115613aa357613aa3613f0d565b6040519080825280601f01601f191660200182016040528015613acd576020820181803683370190505b509150863b613b00577f0c3b563c0000000000000000000000000000000000000000000000000000000060005260046000fd5b5a85811015613b33577fafa32a2c0000000000000000000000000000000000000000000000000000000060005260046000fd5b8590036040810481038710613b6c577f37c3be290000000000000000000000000000000000000000000000000000000060005260046000fd5b505a6000808a5160208c0160008c8cf193505a900390503d84811115613b8f5750835b808352806000602085013e50955095509592505050565b8251825160009190818303613be7576040517f11a6b26400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6101018211801590613bfb57506101018111155b613c18576040516309bde33960e01b815260040160405180910390fd5b60001982820101610100811115613c42576040516309bde33960e01b815260040160405180910390fd5b80600003613c6f5786600081518110613c5d57613c5d614f73565b60200260200101519350505050613e3e565b60008167ffffffffffffffff811115613c8a57613c8a613f0d565b604051908082528060200260200182016040528015613cb3578160200160208202803683370190505b50905060008080805b85811015613ddd5760006001821b8b811603613d175788851015613d00578c5160018601958e918110613cf157613cf1614f73565b60200260200101519050613d39565b8551600185019487918110613cf157613cf1614f73565b8b5160018401938d918110613d2e57613d2e614f73565b602002602001015190505b600089861015613d69578d5160018701968f918110613d5a57613d5a614f73565b60200260200101519050613d8b565b8651600186019588918110613d8057613d80614f73565b602002602001015190505b82851115613dac576040516309bde33960e01b815260040160405180910390fd5b613db68282613e45565b878481518110613dc857613dc8614f73565b60209081029190910101525050600101613cbc565b506001850382148015613def57508683145b8015613dfa57508581145b613e17576040516309bde33960e01b815260040160405180910390fd5b836001860381518110613e2c57613e2c614f73565b60200260200101519750505050505050505b9392505050565b6000818310613e5d57613e588284613e63565b610d77565b610d7783835b6040805160016020820152908101839052606081018290526000906080016136de565b828054828255906000526020600020908101928215613ee8579160200282015b82811115613ee8578251825473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03909116178255602090920191600190910190613ea6565b50613ef4929150613ef8565b5090565b5b80821115613ef45760008155600101613ef9565b634e487b7160e01b600052604160045260246000fd5b6040516080810167ffffffffffffffff81118282101715613f4657613f46613f0d565b60405290565b60405160a0810167ffffffffffffffff81118282101715613f4657613f46613f0d565b60405160c0810167ffffffffffffffff81118282101715613f4657613f46613f0d565b6040805190810167ffffffffffffffff81118282101715613f4657613f46613f0d565b6040516060810167ffffffffffffffff81118282101715613f4657613f46613f0d565b604051601f8201601f1916810167ffffffffffffffff8111828210171561400157614001613f0d565b604052919050565b600067ffffffffffffffff82111561402357614023613f0d565b5060051b60200190565b6001600160a01b038116811461058157600080fd5b803567ffffffffffffffff8116811461405a57600080fd5b919050565b801515811461058157600080fd5b803561405a8161405f565b600067ffffffffffffffff82111561409257614092613f0d565b50601f01601f191660200190565b600082601f8301126140b157600080fd5b81356140c46140bf82614078565b613fd8565b8181528460208386010111156140d957600080fd5b816020850160208301376000918101602001919091529392505050565b6000602080838503121561410957600080fd5b823567ffffffffffffffff8082111561412157600080fd5b818501915085601f83011261413557600080fd5b81356141436140bf82614009565b81815260059190911b8301840190848101908883111561416257600080fd5b8585015b838110156142085780358581111561417e5760008081fd5b86016080818c03601f19018113156141965760008081fd5b61419e613f23565b898301356141ab8161402d565b815260406141ba848201614042565b8b8301526060808501356141cd8161405f565b838301529284013592898411156141e657600091508182fd5b6141f48f8d868801016140a0565b908301525085525050918601918601614166565b5098975050505050505050565b600060a0828403121561422757600080fd5b61422f613f4c565b90508135815261424160208301614042565b602082015261425260408301614042565b604082015261426360608301614042565b606082015261427460808301614042565b608082015292915050565b803561405a8161402d565b600082601f83011261429b57600080fd5b813560206142ab6140bf83614009565b82815260059290921b840181019181810190868411156142ca57600080fd5b8286015b84811015611fa957803567ffffffffffffffff808211156142ef5760008081fd5b9088019060a0828b03601f19018113156143095760008081fd5b614311613f4c565b87840135838111156143235760008081fd5b6143318d8a838801016140a0565b825250604080850135848111156143485760008081fd5b6143568e8b838901016140a0565b8a840152506060808601358581111561436f5760008081fd5b61437d8f8c838a01016140a0565b838501525060809150818601358184015250828501359250838311156143a35760008081fd5b6143b18d8a858801016140a0565b9082015286525050509183019183016142ce565b600061014082840312156143d857600080fd5b6143e0613f6f565b90506143ec8383614215565b815260a082013567ffffffffffffffff8082111561440957600080fd5b614415858386016140a0565b602084015260c084013591508082111561442e57600080fd5b61443a858386016140a0565b604084015261444b60e0850161427f565b6060840152610100840135608084015261012084013591508082111561447057600080fd5b5061447d8482850161428a565b60a08301525092915050565b600082601f83011261449a57600080fd5b813560206144aa6140bf83614009565b82815260059290921b840181019181810190868411156144c957600080fd5b8286015b84811015611fa957803567ffffffffffffffff8111156144ed5760008081fd5b6144fb8986838b01016143c5565b8452509183019183016144cd565b600082601f83011261451a57600080fd5b8135602061452a6140bf83614009565b82815260059290921b8401810191818101908684111561454957600080fd5b8286015b84811015611fa957803567ffffffffffffffff8082111561456d57600080fd5b818901915089603f83011261458157600080fd5b858201356145916140bf82614009565b81815260059190911b830160400190878101908c8311156145b157600080fd5b604085015b838110156145ea578035858111156145cd57600080fd5b6145dc8f6040838a01016140a0565b8452509189019189016145b6565b5087525050509284019250830161454d565b600082601f83011261460d57600080fd5b8135602061461d6140bf83614009565b8083825260208201915060208460051b87010193508684111561463f57600080fd5b602086015b84811015611fa95780358352918301918301614644565b600082601f83011261466c57600080fd5b8135602061467c6140bf83614009565b82815260059290921b8401810191818101908684111561469b57600080fd5b8286015b84811015611fa957803567ffffffffffffffff808211156146c05760008081fd5b9088019060a0828b03601f19018113156146da5760008081fd5b6146e2613f4c565b6146ed888501614042565b8152604080850135848111156147035760008081fd5b6147118e8b83890101614489565b8a840152506060808601358581111561472a5760008081fd5b6147388f8c838a0101614509565b83850152506080915081860135858111156147535760008081fd5b6147618f8c838a01016145fc565b918401919091525091909301359083015250835291830191830161469f565b600080604080848603121561479457600080fd5b833567ffffffffffffffff808211156147ac57600080fd5b6147b88783880161465b565b94506020915081860135818111156147cf57600080fd5b8601601f810188136147e057600080fd5b80356147ee6140bf82614009565b81815260059190911b8201840190848101908a83111561480d57600080fd5b8584015b83811015614899578035868111156148295760008081fd5b8501603f81018d1361483b5760008081fd5b8781013561484b6140bf82614009565b81815260059190911b82018a0190898101908f83111561486b5760008081fd5b928b01925b828410156148895783358252928a0192908a0190614870565b8652505050918601918601614811565b50809750505050505050509250929050565b60005b838110156148c65781810151838201526020016148ae565b50506000910152565b600081518084526148e78160208601602086016148ab565b601f01601f19169290920160200192915050565b602081526000610d7760208301846148cf565b8060608101831015610d7a57600080fd5b60008083601f84011261493157600080fd5b50813567ffffffffffffffff81111561494957600080fd5b6020830191508360208285010111156138a557600080fd5b60008083601f84011261497357600080fd5b50813567ffffffffffffffff81111561498b57600080fd5b6020830191508360208260051b85010111156138a557600080fd5b60008060008060008060008060e0898b0312156149c257600080fd5b6149cc8a8a61490e565b9750606089013567ffffffffffffffff808211156149e957600080fd5b6149f58c838d0161491f565b909950975060808b0135915080821115614a0e57600080fd5b614a1a8c838d01614961565b909750955060a08b0135915080821115614a3357600080fd5b50614a408b828c01614961565b999c989b50969995989497949560c00135949350505050565b600080600060808486031215614a6e57600080fd5b614a78858561490e565b9250606084013567ffffffffffffffff811115614a9457600080fd5b614aa08682870161491f565b9497909650939450505050565b60008060408385031215614ac057600080fd5b614ac983614042565b9150614ad760208401614042565b90509250929050565b634e487b7160e01b600052602160045260246000fd5b60048110614b0657614b06614ae0565b9052565b60208101610d7a8284614af6565b600060208284031215614b2a57600080fd5b813567ffffffffffffffff811115614b4157600080fd5b820160a08185031215613e3e57600080fd5b803563ffffffff8116811461405a57600080fd5b600060a08284031215614b7957600080fd5b614b81613f4c565b8235614b8c8161402d565b8152614b9a60208401614b53565b6020820152614bab60408401614b53565b6040820152614bbc60608401614b53565b60608201526080830135614bcf8161402d565b60808201529392505050565b600080600060408486031215614bf057600080fd5b833567ffffffffffffffff80821115614c0857600080fd5b614c14878388016143c5565b94506020860135915080821115614c2a57600080fd5b50614aa086828701614961565b803560ff8116811461405a57600080fd5b600060208284031215614c5a57600080fd5b610d7782614c37565b60008151808452602080850194506020840160005b83811015614c9d5781516001600160a01b031687529582019590820190600101614c78565b509495945050505050565b60208152600082518051602084015260ff602082015116604084015260ff604082015116606084015260608101511515608084015250602083015160c060a0840152614cf760e0840182614c63565b90506040840151601f198483030160c0850152614d148282614c63565b95945050505050565b60008060408385031215614d3057600080fd5b614d3983614042565b946020939093013593505050565b600060208284031215614d5957600080fd5b610d7782614042565b602081526001600160a01b03825116602082015260208201511515604082015267ffffffffffffffff60408301511660608201526000606083015160808084015261373260a08401826148cf565b600060208284031215614dc257600080fd5b8135613e3e8161402d565b600082601f830112614dde57600080fd5b81356020614dee6140bf83614009565b8083825260208201915060208460051b870101935086841115614e1057600080fd5b602086015b84811015611fa9578035614e288161402d565b8352918301918301614e15565b60006020808385031215614e4857600080fd5b823567ffffffffffffffff80821115614e6057600080fd5b818501915085601f830112614e7457600080fd5b8135614e826140bf82614009565b81815260059190911b83018401908481019088831115614ea157600080fd5b8585015b8381101561420857803585811115614ebc57600080fd5b860160c0818c03601f19011215614ed35760008081fd5b614edb613f6f565b8882013581526040614eee818401614c37565b8a8301526060614eff818501614c37565b8284015260809150614f1282850161406d565b9083015260a08381013589811115614f2a5760008081fd5b614f388f8d83880101614dcd565b838501525060c0840135915088821115614f525760008081fd5b614f608e8c84870101614dcd565b9083015250845250918601918601614ea5565b634e487b7160e01b600052603260045260246000fd5b80356001600160e01b038116811461405a57600080fd5b600082601f830112614fb157600080fd5b81356020614fc16140bf83614009565b82815260069290921b84018101918181019086841115614fe057600080fd5b8286015b84811015611fa95760408189031215614ffd5760008081fd5b615005613f92565b61500e82614042565b815261501b858301614f89565b81860152835291830191604001614fe4565b600082601f83011261503e57600080fd5b8135602061504e6140bf83614009565b82815260059290921b8401810191818101908684111561506d57600080fd5b8286015b84811015611fa957803567ffffffffffffffff808211156150925760008081fd5b9088019060a0828b03601f19018113156150ac5760008081fd5b6150b4613f4c565b6150bf888501614042565b815260406150ce818601614042565b8983015260606150df818701614042565b8284015260809150818601358184015250828501359250838311156151045760008081fd5b6151128d8a858801016140a0565b908201528652505050918301918301615071565b600082601f83011261513757600080fd5b813560206151476140bf83614009565b82815260069290921b8401810191818101908684111561516657600080fd5b8286015b84811015611fa957604081890312156151835760008081fd5b61518b613f92565b81358152848201358582015283529183019160400161516a565b600060208083850312156151b857600080fd5b823567ffffffffffffffff808211156151d057600080fd5b90840190606082870312156151e457600080fd5b6151ec613fb5565b8235828111156151fb57600080fd5b8301604081890381131561520e57600080fd5b615216613f92565b82358581111561522557600080fd5b8301601f81018b1361523657600080fd5b80356152446140bf82614009565b81815260069190911b8201890190898101908d83111561526357600080fd5b928a01925b828410156152b35785848f0312156152805760008081fd5b615288613f92565b84356152938161402d565b81526152a0858d01614f89565b818d0152825292850192908a0190615268565b8452505050828701359150848211156152cb57600080fd5b6152d78a838501614fa0565b818801528352505082840135828111156152f057600080fd5b6152fc8882860161502d565b8583015250604083013593508184111561531557600080fd5b61532187858501615126565b60408201529695505050505050565b600082825180855260208086019550808260051b84010181860160005b848110156153c057858303601f190189528151805167ffffffffffffffff908116855285820151811686860152604080830151909116908501526060808201519085015260809081015160a0918501829052906153ac818601836148cf565b9a86019a945050509083019060010161534d565b5090979650505050505050565b60008151808452602080850194506020840160005b83811015614c9d5781518051885283015183880152604090960195908201906001016153e2565b60408152600061541c6040830185615330565b8281036020840152614d1481856153cd565b805160408084528151848201819052600092602091908201906060870190855b8181101561548557835180516001600160a01b031684528501516001600160e01b031685840152928401929185019160010161544e565b50508583015187820388850152805180835290840192506000918401905b808310156154df578351805167ffffffffffffffff1683528501516001600160e01b0316858301529284019260019290920191908501906154a3565b50979650505050505050565b602081526000610d77602083018461542e565b60006020828403121561551057600080fd5b8151613e3e8161405f565b634e487b7160e01b600052601160045260246000fd5b67ffffffffffffffff8181168382160190808211156155525761555261551b565b5092915050565b602081526000825160606020840152615575608084018261542e565b90506020840151601f19808584030160408601526155938383615330565b9250604086015191508085840301606086015250614d1482826153cd565b6000602082840312156155c357600080fd5b813567ffffffffffffffff8111156155da57600080fd5b6137328482850161465b565b81810381811115610d7a57610d7a61551b565b634e487b7160e01b600052601260045260246000fd5b600067ffffffffffffffff8084168061562a5761562a6155f9565b92169190910692915050565b8082028115828204841417610d7a57610d7a61551b565b805182526000602067ffffffffffffffff81840151168185015260408084015160a0604087015261568160a08701826148cf565b90506060850151868203606088015261569a82826148cf565b608087810151898303918a01919091528051808352908601935060009250908501905b808310156154df57835180516001600160a01b03168352860151868301529285019260019290920191908401906156bd565b602081526000610d77602083018461564d565b608081526000615715608083018761564d565b61ffff9590951660208301525060408101929092526001600160a01b0316606090910152919050565b60008060006060848603121561575357600080fd5b835161575e8161405f565b602085015190935067ffffffffffffffff81111561577b57600080fd5b8401601f8101861361578c57600080fd5b805161579a6140bf82614078565b8181528760208385010111156157af57600080fd5b6157c08260208301602086016148ab565b809450505050604084015190509250925092565b600181811c908216806157e857607f821691505b60208210810361580857634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115610724576000816000526020600020601f850160051c810160208610156158375750805b601f850160051c820191505b8181101561585657828155600101615843565b505050505050565b815167ffffffffffffffff81111561587857615878613f0d565b61588c8161588684546157d4565b8461580e565b602080601f8311600181146158c157600084156158a95750858301515b600019600386901b1c1916600185901b178555615856565b600085815260208120601f198616915b828110156158f0578886015182559484019460019091019084016158d1565b508582101561590e5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6000602080835283546001600160a01b038116602085015260ff8160a01c161515604085015267ffffffffffffffff8160a81c16606085015250600180850160808086015260008154615970816157d4565b8060a089015260c0600183166000811461599157600181146159ad576159dd565b60ff19841660c08b015260c083151560051b8b010194506159dd565b85600052602060002060005b848110156159d45781548c82018501529088019089016159b9565b8b0160c0019550505b50929998505050505050505050565b80820180821115610d7a57610d7a61551b565b60ff8181168382160190811115610d7a57610d7a61551b565b8183823760009101908152919050565b828152606082602083013760800192915050565b600067ffffffffffffffff80841680615a5757615a576155f9565b92169190910492915050565b6000808335601e19843603018112615a7a57600080fd5b83018035915067ffffffffffffffff821115615a9557600080fd5b6020019150368190038213156138a557600080fd5b6020810160058310615abe57615abe614ae0565b91905290565b60ff81811683821602908116908181146155525761555261551b565b600060a0820160ff881683526020878185015260a0604085015281875480845260c0860191508860005282600020935060005b81811015615b385784546001600160a01b031683526001948501949284019201615b13565b50508481036060860152865180825290820192508187019060005b81811015615b785782516001600160a01b031685529383019391830191600101615b53565b50505060ff85166080850152509050611fab565b600067ffffffffffffffff808616835280851660208401525060606040830152614d1460608301846148cf565b82815260406020820152600061373260408301846148cf565b67ffffffffffffffff848116825283166020820152606081016137326040830184614af6565b848152615c086020820185614af6565b608060408201526000615c1e60808301856148cf565b905082606083015295945050505050565b600060208284031215615c4157600080fd5b8151613e3e8161402d565b6020815260008251610100806020850152615c6b6101208501836148cf565b91506020850151615c88604086018267ffffffffffffffff169052565b5060408501516001600160a01b038116606086015250606085015160808501526080850151615cc260a08601826001600160a01b03169052565b5060a0850151601f19808685030160c0870152615cdf84836148cf565b935060c08701519150808685030160e0870152615cfc84836148cf565b935060e0870151915080868503018387015250611fab83826148cf565b600060208284031215615d2b57600080fd5b5051919050565b848152600067ffffffffffffffff808616602084015280851660408401525060806060830152611fab60808301846148cf565b86815260c060208201526000615d7e60c08301886148cf565b6001600160a01b039690961660408301525067ffffffffffffffff9384166060820152608081019290925290911660a09091015292915050565b600082825180855260208086019550808260051b84010181860160005b848110156153c057601f19868403018952815160a08151818652615dfb828701826148cf565b9150508582015185820387870152615e1382826148cf565b91505060408083015186830382880152615e2d83826148cf565b92505050606080830151818701525060808083015192508582038187015250615e5681836148cf565b9a86019a9450505090830190600101615dd5565b602081526000610d776020830184615db8565b60008282518085526020808601955060208260051b8401016020860160005b848110156153c057601f19868403018952615eb88383516148cf565b98840198925090830190600101615e9c565b604081526000835180516040840152602081015167ffffffffffffffff80821660608601528060408401511660808601528060608401511660a08601528060808401511660c086015250505060208401516101408060e0850152615f326101808501836148cf565b91506040860151603f198086850301610100870152615f5184836148cf565b935060608801519150615f706101208701836001600160a01b03169052565b60808801518387015260a0880151925080868503016101608701525050615f978282615db8565b9150508281036020840152614d148185615e7d56fea164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CanOnlySelfCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"actual\",\"type\":\"bytes32\"}],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ExecutionError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"ForkedChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enumMultiOCR3Base.InvalidConfigErrorType\",\"name\":\"errorType\",\"type\":\"uint8\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"got\",\"type\":\"uint256\"}],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidEVMAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"name\":\"InvalidInterval\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"newLimit\",\"type\":\"uint256\"}],\"name\":\"InvalidManualExecutionGasLimit\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"messageDestChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidMessageDestChainSelector\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"newState\",\"type\":\"uint8\"}],\"name\":\"InvalidNewState\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRoot\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidStaticConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LeavesCannotBeEmpty\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ManualExecutionGasLimitMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"ManualExecutionNotYetEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"errorReason\",\"type\":\"bytes\"}],\"name\":\"MessageValidationError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonUniqueSignatures\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"notPool\",\"type\":\"address\"}],\"name\":\"NotACompatiblePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OracleCannotBeZeroAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ReceiverError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountReleased\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePre\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePost\",\"type\":\"uint256\"}],\"name\":\"ReleaseOrMintBalanceMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"name\":\"RootAlreadyCommitted\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"RootNotCommitted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignatureVerificationDisabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignaturesOutOfRegistration\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"reportSourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"messageSourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainSelectorMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"StaleCommitReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"StaticConfigCannotBeChanged\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"TokenDataMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"TokenHandlingError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnexpectedTokenData\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"WrongMessageLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WrongNumberOfSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroChainSelectorNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"AlreadyAttempted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"structIRMNV2.Signature[]\",\"name\":\"rmnSignatures\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"report\",\"type\":\"tuple\"}],\"name\":\"CommitReportAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"DynamicConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"messageHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"name\":\"ExecutionStateChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"RootRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"SkippedAlreadyExecutedMessage\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SkippedReportExecution\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"sourceConfig\",\"type\":\"tuple\"}],\"name\":\"SourceChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainSelectorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"}],\"name\":\"StaticConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigUpdates\",\"type\":\"tuple[]\"}],\"name\":\"applySourceChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"destTokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structClient.Any2EVMMessage\",\"name\":\"\",\"type\":\"tuple\"}],\"name\":\"ccipReceive\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"rawVs\",\"type\":\"bytes32\"}],\"name\":\"commit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"execute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"bytes[]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[]\"}],\"name\":\"executeSingleMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"getExecutionState\",\"outputs\":[{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLatestPriceSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"getMerkleRoot\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"getSourceChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"latestConfigDetails\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"n\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"}],\"internalType\":\"structMultiOCR3Base.ConfigInfo\",\"name\":\"configInfo\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfig\",\"name\":\"ocrConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage[]\",\"name\":\"messages\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[][]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[][]\"},{\"internalType\":\"bytes32[]\",\"name\":\"proofs\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"proofFlagBits\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.ExecutionReportSingleChain[]\",\"name\":\"reports\",\"type\":\"tuple[]\"},{\"internalType\":\"uint256[][]\",\"name\":\"gasLimitOverrides\",\"type\":\"uint256[][]\"}],\"name\":\"manuallyExecute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"setDynamicConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfigArgs[]\",\"name\":\"ocrConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"setOCR3Configs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x6101206040523480156200001257600080fd5b5060405162006ccd38038062006ccd8339810160408190526200003591620008c7565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf81620001fa565b5050466080525060208301516001600160a01b03161580620000ec575060408301516001600160a01b0316155b8062000103575060608301516001600160a01b0316155b1562000122576040516342bcdf7f60e11b815260040160405180910390fd5b82516001600160401b03166000036200014e5760405163c656089560e01b815260040160405180910390fd5b82516001600160401b0390811660a052602080850180516001600160a01b0390811660c05260408088018051831660e0526060808a01805185166101005283518b519098168852945184169587019590955251821690850152905116908201527f683eb52ee924eb817377cfa8f41f238f4bb7a877da5267869dfffbad85f564d89060800160405180910390a1620001e682620002a5565b620001f181620003c1565b50505062000c67565b336001600160a01b03821603620002545760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b0316620002ce576040516342bcdf7f60e11b815260040160405180910390fd5b80516004805460208085018051604080880180516060808b0180516001600160a01b039b8c166001600160c01b0319909a168a17600160a01b63ffffffff98891602176001600160c01b0316600160c01b948816949094026001600160e01b031693909317600160e01b93871693909302929092179098556080808b018051600580546001600160a01b031916918d169190911790558451988952955185169688019690965290518316918601919091525116938301939093529151909216908201527fa55bd56595c45f517e5967a3067f3dca684445a3080e7c04a4e0d5a40cda627d9060a00160405180910390a150565b60005b815181101562000666576000828281518110620003e557620003e562000a1d565b60200260200101519050600081602001519050806001600160401b0316600003620004235760405163c656089560e01b815260040160405180910390fd5b81516001600160a01b03166200044c576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160401b0381166000908152600660205260408120600181018054919291620004789062000a33565b80601f0160208091040260200160405190810160405280929190818152602001828054620004a69062000a33565b8015620004f75780601f10620004cb57610100808354040283529160200191620004f7565b820191906000526020600020905b815481529060010190602001808311620004d957829003601f168201915b5050505050905060008460600151905081516000036200059e57805160000362000534576040516342bcdf7f60e11b815260040160405180910390fd5b6001830162000544828262000ac4565b508254600160a81b600160e81b031916600160a81b1783556040516001600160401b03851681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1620005d9565b8080519060200120828051906020012014620005d95760405163c39a620560e01b81526001600160401b038516600482015260240162000083565b604080860151845487516001600160a01b03166001600160a01b0319921515600160a01b02929092166001600160a81b031990911617178455516001600160401b038516907f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b906200064d90869062000b90565b60405180910390a25050505050806001019050620003c4565b5050565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b0381118282101715620006a557620006a56200066a565b60405290565b604051601f8201601f191681016001600160401b0381118282101715620006d657620006d66200066a565b604052919050565b80516001600160401b0381168114620006f657600080fd5b919050565b6001600160a01b03811681146200071157600080fd5b50565b805163ffffffff81168114620006f657600080fd5b6000601f83601f8401126200073d57600080fd5b825160206001600160401b03808311156200075c576200075c6200066a565b8260051b6200076d838201620006ab565b93845286810183019383810190898611156200078857600080fd5b84890192505b85831015620008ba57825184811115620007a85760008081fd5b89016080601f19828d038101821315620007c25760008081fd5b620007cc62000680565b88840151620007db81620006fb565b81526040620007ec858201620006de565b8a8301526060808601518015158114620008065760008081fd5b838301529385015193898511156200081e5760008081fd5b84860195508f603f8701126200083657600094508485fd5b8a8601519450898511156200084f576200084f6200066a565b620008608b858f88011601620006ab565b93508484528f82868801011115620008785760008081fd5b60005b8581101562000898578681018301518582018d01528b016200087b565b5060009484018b0194909452509182015283525091840191908401906200078e565b9998505050505050505050565b6000806000838503610140811215620008df57600080fd5b6080811215620008ee57600080fd5b620008f862000680565b6200090386620006de565b815260208601516200091581620006fb565b602082015260408601516200092a81620006fb565b604082015260608601516200093f81620006fb565b6060820152935060a0607f19820112156200095957600080fd5b5060405160a081016001600160401b0380821183831017156200098057620009806200066a565b81604052608087015191506200099682620006fb565b818352620009a760a0880162000714565b6020840152620009ba60c0880162000714565b6040840152620009cd60e0880162000714565b60608401526101008701519150620009e582620006fb565b608083018290526101208701519294508083111562000a0357600080fd5b505062000a138682870162000729565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b600181811c9082168062000a4857607f821691505b60208210810362000a6957634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111562000abf576000816000526020600020601f850160051c8101602086101562000a9a5750805b601f850160051c820191505b8181101562000abb5782815560010162000aa6565b5050505b505050565b81516001600160401b0381111562000ae05762000ae06200066a565b62000af88162000af1845462000a33565b8462000a6f565b602080601f83116001811462000b30576000841562000b175750858301515b600019600386901b1c1916600185901b17855562000abb565b600085815260208120601f198616915b8281101562000b615788860151825594840194600190910190840162000b40565b508582101562000b805787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b602080825282546001600160a01b0381168383015260a081901c60ff161515604084015260a81c6001600160401b0316606083015260808083015260018084018054600093929190849062000be58162000a33565b8060a089015260c0600183166000811462000c09576001811462000c265762000c58565b60ff19841660c08b015260c083151560051b8b0101945062000c58565b85600052602060002060005b8481101562000c4f5781548c820185015290880190890162000c32565b8b0160c0019550505b50929998505050505050505050565b60805160a05160c05160e05161010051615ff062000cdd600039600081816102400152612a6d0152600081816102110152612f610152600081816101e20152818161077f0152818161098601526123ef0152600081816101b2015261267c0152600081816117dd01526118290152615ff06000f3fe608060405234801561001057600080fd5b50600436106101515760003560e01c806379ba5097116100cd578063c673e58411610081578063e9d68a8e11610066578063e9d68a8e1461052a578063f2fde38b1461054a578063f716f99f1461055d57600080fd5b8063c673e584146104c5578063ccd37ba3146104e557600080fd5b80638da5cb5b116100b25780638da5cb5b14610484578063991a50181461049f578063a80036b4146104b257600080fd5b806379ba50971461046e57806385572ffb1461047657600080fd5b80632d04ab76116101245780633f4b04aa116101095780633f4b04aa146103365780635e36480c146103525780637437ff9f1461037257600080fd5b80632d04ab7614610310578063311cd5131461032357600080fd5b806304666f9c1461015657806305d938b51461016b57806306285c691461017e578063181f5a77146102c7575b600080fd5b61016961016436600461412d565b610570565b005b6101696101793660046147b7565b610584565b61027060408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316815250905090565b6040516102be9190815167ffffffffffffffff1681526020808301516001600160a01b0390811691830191909152604080840151821690830152606092830151169181019190915260800190565b60405180910390f35b6103036040518060400160405280601181526020017f4f666652616d7020312e362e302d64657600000000000000000000000000000081525081565b6040516102be9190614932565b61016961031e3660046149dd565b610729565b610169610331366004614a90565b610cc1565b60095460405167ffffffffffffffff90911681526020016102be565b610365610360366004614ae4565b610d2a565b6040516102be9190614b41565b6104116040805160a081018252600080825260208201819052918101829052606081018290526080810191909152506040805160a0810182526004546001600160a01b03808216835263ffffffff600160a01b83048116602085015278010000000000000000000000000000000000000000000000008304811694840194909452600160e01b9091049092166060820152600554909116608082015290565b6040516102be9190600060a0820190506001600160a01b03808451168352602084015163ffffffff808216602086015280604087015116604086015280606087015116606086015250508060808501511660808401525092915050565b610169610d80565b610169610151366004614b4f565b6000546040516001600160a01b0390911681526020016102be565b6101696104ad366004614b9e565b610e3e565b6101696104c0366004614c12565b610e4f565b6104d86104d3366004614c7f565b6111c2565b6040516102be9190614cdf565b61051c6104f3366004614d54565b67ffffffffffffffff919091166000908152600860209081526040808320938352929052205490565b6040519081526020016102be565b61053d610538366004614d7e565b611320565b6040516102be9190614d99565b610169610558366004614de7565b61142d565b61016961056b366004614e6c565b61143e565b610578611480565b610581816114dc565b50565b61058c6117da565b8151815181146105c8576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b818110156107195760008482815181106105e7576105e7614faa565b6020026020010151905060008160200151519050600085848151811061060f5761060f614faa565b6020026020010151905080518214610653576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8281101561070a57600082828151811061067257610672614faa565b6020026020010151905080600014610701578460200151828151811061069a5761069a614faa565b6020026020010151608001518110156107015784516040517fc8e9605100000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260248101839052604481018290526064015b60405180910390fd5b50600101610656565b505050508060010190506105cb565b50610724838361185b565b505050565b6000610737878901896151dc565b602081015151909150156107e357602081015160408083015190517f30dfc3080000000000000000000000000000000000000000000000000000000081526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016926330dfc308926107b292600401615440565b60006040518083038186803b1580156107ca57600080fd5b505afa1580156107de573d6000803e3d6000fd5b505050505b805151511515806107f957508051602001515115155b156108f95760095460208a01359067ffffffffffffffff808316911610156108b8576009805467ffffffffffffffff191667ffffffffffffffff83161790556004805483516040517f3937306f0000000000000000000000000000000000000000000000000000000081526001600160a01b0390921692633937306f92610881929101615522565b600060405180830381600087803b15801561089b57600080fd5b505af11580156108af573d6000803e3d6000fd5b505050506108f7565b8160200151516000036108f7576040517f2261116700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b60005b816020015151811015610c0a5760008260200151828151811061092157610921614faa565b602090810291909101015180516040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815277ffffffffffffffff00000000000000000000000000000000608083901b166004820152919250906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632cbc26bb90602401602060405180830381865afa1580156109cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109f19190615535565b15610a34576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff821660048201526024016106f8565b6000610a3f8261190b565b6020840151815491925067ffffffffffffffff908116600160a81b90920416141580610a865750826040015167ffffffffffffffff16836020015167ffffffffffffffff16115b15610ae7578251602084015160408086015190517fd5e0f0d600000000000000000000000000000000000000000000000000000000815267ffffffffffffffff938416600482015291831660248301529190911660448201526064016106f8565b606083015180610b23576040517f504570e300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b835167ffffffffffffffff16600090815260086020908152604080832084845290915290205415610b965783516040517f32cf0cbf00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602481018290526044016106f8565b6040840151610ba6906001615568565b82547fffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffff16600160a81b67ffffffffffffffff9283160217909255925116600090815260086020908152604080832094835293905291909120429055506001016108fc565b507fd7868a16facbdde7b5c020620136316b3c266fffcb4e1e41cb6a662fe14ba3e181604051610c3a9190615590565b60405180910390a1610cb660008a8a8a8a8a8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808e0282810182019093528d82529093508d92508c9182918501908490808284376000920191909152508b9250611972915050565b505050505050505050565b610d01610cd0828401846155e8565b6040805160008082526020820190925290610cfb565b6060815260200190600190039081610ce65790505b5061185b565b604080516000808252602082019092529050610d24600185858585866000611972565b50505050565b6000610d386001600461561d565b6002610d45608085615646565b67ffffffffffffffff16610d59919061566d565b610d638585611ce9565b901c166003811115610d7757610d77614b17565b90505b92915050565b6001546001600160a01b03163314610dda5760405162461bcd60e51b815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064016106f8565b600080543373ffffffffffffffffffffffffffffffffffffffff19808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610e46611480565b61058181611d30565b333014610e88576040517f371a732800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160008082526020820190925281610ec5565b6040805180820190915260008082526020820152815260200190600190039081610e9e5790505b5060a08501515190915015610ef957610ef68460a00151856020015186606001518760000151602001518787611e96565b90505b6040805160a0810182528551518152855160209081015167ffffffffffffffff1681830152808701518351600094840192610f35929101614932565b60408051601f19818403018152918152908252878101516020830152018390526005549091506001600160a01b03168015611042576040517f08d450a10000000000000000000000000000000000000000000000000000000081526001600160a01b038216906308d450a190610faf908590600401615726565b600060405180830381600087803b158015610fc957600080fd5b505af1925050508015610fda575060015b611042573d808015611008576040519150601f19603f3d011682016040523d82523d6000602084013e61100d565b606091505b50806040517f09c253250000000000000000000000000000000000000000000000000000000081526004016106f89190614932565b60408601515115801561105757506080860151155b8061106e575060608601516001600160a01b03163b155b806110ae575060608601516110ac906001600160a01b03167f85572ffb00000000000000000000000000000000000000000000000000000000611fb5565b155b156110bb57505050505050565b855160209081015167ffffffffffffffff1660009081526006909152604080822054608089015160608a015192517f3cf9798300000000000000000000000000000000000000000000000000000000815284936001600160a01b0390931692633cf97983926111339289926113889291600401615739565b6000604051808303816000875af1158015611152573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261117a9190810190615775565b5091509150816111b857806040517f0a8d6e8c0000000000000000000000000000000000000000000000000000000081526004016106f89190614932565b5050505050505050565b6112056040805160e081019091526000606082018181526080830182905260a0830182905260c08301919091528190815260200160608152602001606081525090565b60ff808316600090815260026020818152604092839020835160e081018552815460608201908152600183015480881660808401526101008104881660a0840152620100009004909616151560c0820152948552918201805484518184028101840190955280855292938583019390928301828280156112ae57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611290575b505050505081526020016003820180548060200260200160405190810160405280929190818152602001828054801561131057602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116112f2575b5050505050815250509050919050565b604080516080808201835260008083526020808401829052838501829052606080850181905267ffffffffffffffff878116845260068352928690208651948501875280546001600160a01b0381168652600160a01b810460ff16151593860193909352600160a81b9092049092169483019490945260018401805493949293918401916113ad9061580b565b80601f01602080910402602001604051908101604052809291908181526020018280546113d99061580b565b80156113105780601f106113fb57610100808354040283529160200191611310565b820191906000526020600020905b81548152906001019060200180831161140957505050919092525091949350505050565b611435611480565b61058181611fd1565b611446611480565b60005b815181101561147c5761147482828151811061146757611467614faa565b6020026020010151612087565b600101611449565b5050565b6000546001600160a01b031633146114da5760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016106f8565b565b60005b815181101561147c5760008282815181106114fc576114fc614faa565b602002602001015190506000816020015190508067ffffffffffffffff16600003611553576040517fc656089500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81516001600160a01b031661157b576040516342bcdf7f60e11b815260040160405180910390fd5b67ffffffffffffffff811660009081526006602052604081206001810180549192916115a69061580b565b80601f01602080910402602001604051908101604052809291908181526020018280546115d29061580b565b801561161f5780601f106115f45761010080835404028352916020019161161f565b820191906000526020600020905b81548152906001019060200180831161160257829003601f168201915b5050505050905060008460600151905081516000036116d757805160000361165a576040516342bcdf7f60e11b815260040160405180910390fd5b600183016116688282615895565b5082547fffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffff16600160a81b17835560405167ffffffffffffffff851681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a161172a565b808051906020012082805190602001201461172a576040517fc39a620500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff851660048201526024016106f8565b604080860151845487516001600160a01b031673ffffffffffffffffffffffffffffffffffffffff19921515600160a01b02929092167fffffffffffffffffffffff000000000000000000000000000000000000000000909116171784555167ffffffffffffffff8516907f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b906117c2908690615955565b60405180910390a250505050508060010190506114df565b467f0000000000000000000000000000000000000000000000000000000000000000146114da576040517f0f01ce850000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060048201524660248201526044016106f8565b8151600003611895576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160408051600080825260208201909252911591905b8451811015611904576118fc8582815181106118ca576118ca614faa565b6020026020010151846118f6578583815181106118e9576118e9614faa565b602002602001015161239b565b8361239b565b6001016118ac565b5050505050565b67ffffffffffffffff811660009081526006602052604081208054600160a01b900460ff16610d7a576040517fed053c5900000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024016106f8565b60ff878116600090815260026020908152604080832081516080810183528154815260019091015480861693820193909352610100830485169181019190915262010000909104909216151560608301528735906119d18760a4615a23565b9050826060015115611a195784516119ea90602061566d565b86516119f790602061566d565b611a029060a0615a23565b611a0c9190615a23565b611a169082615a23565b90505b368114611a5b576040517f8e1192e1000000000000000000000000000000000000000000000000000000008152600481018290523660248201526044016106f8565b5081518114611aa35781516040517f93df584c0000000000000000000000000000000000000000000000000000000081526004810191909152602481018290526044016106f8565b611aab6117da565b60ff808a1660009081526003602090815260408083203384528252808320815180830190925280548086168352939491939092840191610100909104166002811115611af957611af9614b17565b6002811115611b0a57611b0a614b17565b9052509050600281602001516002811115611b2757611b27614b17565b148015611b7b5750600260008b60ff1660ff168152602001908152602001600020600301816000015160ff1681548110611b6357611b63614faa565b6000918252602090912001546001600160a01b031633145b611bb1576040517fda0f08e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50816060015115611c93576020820151611bcc906001615a36565b60ff16855114611c08576040517f71253a2500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8351855114611c43576040517fa75d88af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008787604051611c55929190615a4f565b604051908190038120611c6c918b90602001615a5f565b604051602081830303815290604052805190602001209050611c918a82888888612d1b565b505b6040805182815260208a81013567ffffffffffffffff169082015260ff8b16917f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef0910160405180910390a2505050505050505050565b67ffffffffffffffff8216600090815260076020526040812081611d0e608085615a73565b67ffffffffffffffff1681526020810191909152604001600020549392505050565b80516001600160a01b0316611d58576040516342bcdf7f60e11b815260040160405180910390fd5b80516004805460208085018051604080880180516060808b0180516001600160a01b039b8c167fffffffffffffffff000000000000000000000000000000000000000000000000909a168a17600160a01b63ffffffff988916021777ffffffffffffffffffffffffffffffffffffffffffffffff167801000000000000000000000000000000000000000000000000948816949094026001600160e01b031693909317600160e01b93871693909302929092179098556080808b0180516005805473ffffffffffffffffffffffffffffffffffffffff1916918d169190911790558451988952955185169688019690965290518316918601919091525116938301939093529151909216908201527fa55bd56595c45f517e5967a3067f3dca684445a3080e7c04a4e0d5a40cda627d9060a00160405180910390a150565b6060865167ffffffffffffffff811115611eb257611eb2613f44565b604051908082528060200260200182016040528015611ef757816020015b6040805180820190915260008082526020820152815260200190600190039081611ed05790505b50905060005b8751811015611fa957611f84888281518110611f1b57611f1b614faa565b6020026020010151888888888887818110611f3857611f38614faa565b9050602002810190611f4a9190615a9a565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612f0092505050565b828281518110611f9657611f96614faa565b6020908102919091010152600101611efd565b505b9695505050505050565b6000611fc0836132a5565b8015610d775750610d778383613309565b336001600160a01b038216036120295760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016106f8565b6001805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b806040015160ff166000036120b2576000604051631b3fab5160e11b81526004016106f89190615ae1565b60208082015160ff8082166000908152600290935260408320600181015492939092839216900361211f57606084015160018201805491151562010000027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff909216919091179055612174565b6060840151600182015460ff6201000090910416151590151514612174576040517f87f6037c00000000000000000000000000000000000000000000000000000000815260ff841660048201526024016106f8565b60a0840151805161010010156121a0576001604051631b3fab5160e11b81526004016106f89190615ae1565b61220684846003018054806020026020016040519081016040528092919081815260200182805480156121fc57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116121de575b50505050506133c4565b8460600151156123105761227484846002018054806020026020016040519081016040528092919081815260200182805480156121fc576020028201919060005260206000209081546001600160a01b031681526001909101906020018083116121de5750505050506133c4565b6080850151805161010010156122a0576002604051631b3fab5160e11b81526004016106f89190615ae1565b60408601516122b0906003615afb565b60ff168151116122d6576003604051631b3fab5160e11b81526004016106f89190615ae1565b805160018401805461ff00191661010060ff8416021790556123019060028601906020840190613ebd565b5061230e8582600161342d565b505b61231c8482600261342d565b80516123319060038501906020840190613ebd565b5060408581015160018401805460ff191660ff8316179055865180855560a088015192517fab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f5479361238a9389939260028a01929190615b17565b60405180910390a1611904846135a1565b815181516040517f2cbc26bb000000000000000000000000000000000000000000000000000000008152608083901b77ffffffffffffffff00000000000000000000000000000000166004820152901515907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632cbc26bb90602401602060405180830381865afa15801561243e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124629190615535565b156124ee5780156124ab576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff831660048201526024016106f8565b60405167ffffffffffffffff831681527faab522ed53d887e56ed53dd37398a01aeef6a58e0fa77c2173beb9512d8949339060200160405180910390a150505050565b60006124f98361190b565b60010180546125079061580b565b80601f01602080910402602001604051908101604052809291908181526020018280546125339061580b565b80156125805780601f1061255557610100808354040283529160200191612580565b820191906000526020600020905b81548152906001019060200180831161256357829003601f168201915b505050602088015151929350505060008190036125c8576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8560400151518114612606576040517f57e0e08300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008167ffffffffffffffff81111561262157612621613f44565b60405190808252806020026020018201604052801561264a578160200160208202803683370190505b50905060005b828110156127a35760008860200151828151811061267057612670614faa565b602002602001015190507f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681600001516040015167ffffffffffffffff161461270357805160409081015190517f38432a2200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016106f8565b8667ffffffffffffffff1681600001516020015167ffffffffffffffff1614612773578051602001516040517f6c95f1eb00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808a16600483015290911660248201526044016106f8565b61277d8186613611565b83838151811061278f5761278f614faa565b602090810291909101015250600101612650565b5060006127ba86838a606001518b60800151613733565b905080600003612802576040517f7dd17a7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff871660048201526024016106f8565b60005b83811015610cb65760005a905060008a60200151838151811061282a5761282a614faa565b6020026020010151905060006128488a836000015160600151610d2a565b9050600081600381111561285e5761285e614b17565b148061287b5750600381600381111561287957612879614b17565b145b6128d3578151606001516040805167ffffffffffffffff808e16825290921660208301527f3b575419319662b2a6f5e2467d84521517a3382b908eb3d557bb3fdb0c50e23c91015b60405180910390a1505050612d13565b88156129a357600454600090600160a01b900463ffffffff166128f6874261561d565b11905080806129165750600382600381111561291457612914614b17565b145b612958576040517fa9cfc86200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8c1660048201526024016106f8565b8b858151811061296a5761296a614faa565b602002602001015160001461299d578b858151811061298b5761298b614faa565b60200260200101518360800181815250505b50612a04565b60008160038111156129b7576129b7614b17565b14612a04578151606001516040805167ffffffffffffffff808e16825290921660208301527f3ef2a99c550a751d4b0b261268f05a803dfb049ab43616a1ffb388f61fe6512091016128c3565b81516080015167ffffffffffffffff1615612af3576000816003811115612a2d57612a2d614b17565b03612af35781516080015160208301516040517fe0e03cae0000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169263e0e03cae92612aa4928f929190600401615bc3565b6020604051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190615535565b612af357505050612d13565b60008c604001518581518110612b0b57612b0b614faa565b6020026020010151905080518360a001515114612b6f578251606001516040517f1cfe6d8b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808e16600483015290911660248201526044016106f8565b612b838b8460000151606001516001613771565b600080612b908584613819565b91509150612ba78d86600001516060015184613771565b8b15612c17576003826003811115612bc157612bc1614b17565b03612c17576000846003811115612bda57612bda614b17565b14612c17578451516040517f2b11b8d90000000000000000000000000000000000000000000000000000000081526106f891908390600401615bf0565b6002826003811115612c2b57612c2b614b17565b14612c85576003826003811115612c4457612c44614b17565b14612c85578451606001516040517f926c5a3e0000000000000000000000000000000000000000000000000000000081526106f8918f918590600401615c09565b84600001516000015185600001516060015167ffffffffffffffff168e67ffffffffffffffff167f05665fe9ad095383d018353f4cbcba77e84db27dd215081bbf7cdf9ae6fbe48b8c8b81518110612cdf57612cdf614faa565b602002602001015186865a612cf4908e61561d565b604051612d049493929190615c2f565b60405180910390a45050505050505b600101612805565b8251600090815b818110156111b8576000600188868460208110612d4157612d41614faa565b612d4e91901a601b615a36565b898581518110612d6057612d60614faa565b6020026020010151898681518110612d7a57612d7a614faa565b602002602001015160405160008152602001604052604051612db8949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015612dda573d6000803e3d6000fd5b505060408051601f1981015160ff808e166000908152600360209081528582206001600160a01b03851683528152858220858701909652855480841686529397509095509293928401916101009004166002811115612e3b57612e3b614b17565b6002811115612e4c57612e4c614b17565b9052509050600181602001516002811115612e6957612e69614b17565b14612ea0576040517fca31867a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051600160ff9091161b851615612ee3576040517ff67bc7c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806000015160ff166001901b851794505050806001019050612d22565b60408051808201909152600080825260208201526000612f2387602001516138e3565b6040517fbbe4f6db0000000000000000000000000000000000000000000000000000000081526001600160a01b0380831660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063bbe4f6db90602401602060405180830381865afa158015612fa8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fcc9190615c66565b90506001600160a01b038116158061301457506130126001600160a01b0382167faff2afbf00000000000000000000000000000000000000000000000000000000611fb5565b155b15613056576040517fae9b4ce90000000000000000000000000000000000000000000000000000000081526001600160a01b03821660048201526024016106f8565b60045460009081906130789089908690600160e01b900463ffffffff16613989565b9150915060008060006131456040518061010001604052808e81526020018c67ffffffffffffffff1681526020018d6001600160a01b031681526020018f606001518152602001896001600160a01b031681526020018f6000015181526020018f6040015181526020018b8152506040516024016130f69190615c83565b60408051601f198184030181529190526020810180516001600160e01b03167f390775370000000000000000000000000000000000000000000000000000000017905287866113886084613ab7565b9250925092508261318457816040517fe1cd55090000000000000000000000000000000000000000000000000000000081526004016106f89190614932565b81516020146131cc5781516040517f78ef80240000000000000000000000000000000000000000000000000000000081526020600482015260248101919091526044016106f8565b6000828060200190518101906131e29190615d50565b9050866001600160a01b03168c6001600160a01b0316146132775760006132138d8a61320e868a61561d565b613989565b5090508681108061322d57508161322a888361561d565b14155b15613275576040517fa966e21f0000000000000000000000000000000000000000000000000000000081526004810183905260248101889052604481018290526064016106f8565b505b604080518082019091526001600160a01b039098168852602088015250949550505050505095945050505050565b60006132d1827f01ffc9a700000000000000000000000000000000000000000000000000000000613309565b8015610d7a5750613302827fffffffff00000000000000000000000000000000000000000000000000000000613309565b1592915050565b6040517fffffffff0000000000000000000000000000000000000000000000000000000082166024820152600090819060440160408051601f19818403018152919052602080820180516001600160e01b03167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825192935060009283928392909183918a617530fa92503d915060005190508280156133ad575060208210155b80156133b95750600081115b979650505050505050565b60005b81518110156107245760ff8316600090815260036020526040812083519091908490849081106133f9576133f9614faa565b6020908102919091018101516001600160a01b03168252810191909152604001600020805461ffff191690556001016133c7565b60005b8251811015610d2457600083828151811061344d5761344d614faa565b602002602001015190506000600281111561346a5761346a614b17565b60ff80871660009081526003602090815260408083206001600160a01b038716845290915290205461010090041660028111156134a9576134a9614b17565b146134ca576004604051631b3fab5160e11b81526004016106f89190615ae1565b6001600160a01b03811661350a576040517fd6c62c9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052808360ff16815260200184600281111561353057613530614b17565b905260ff80871660009081526003602090815260408083206001600160a01b0387168452825290912083518154931660ff198416811782559184015190929091839161ffff19161761010083600281111561358d5761358d614b17565b021790555090505050806001019050613430565b60ff81166105815760ff808216600090815260026020526040902060010154620100009004166135fd576040517f7a3b4c9400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6009805467ffffffffffffffff1916905550565b815160208082015160409283015192516000938493613657937f2425b0b9f9054c76ff151b0a175b18f37a4a4e82013a72e9f15c9caa095ed21f93909291889101615d69565b60408051601f1981840301815290829052805160209182012086518051888401516060808b0151908401516080808d015195015195976136a09794969395929491939101615d9c565b604051602081830303815290604052805190602001208560400151805190602001208660a001516040516020016136d79190615ea1565b60408051601f198184030181528282528051602091820120908301969096528101939093526060830191909152608082015260a081019190915260c0015b60405160208183030381529060405280519060200120905092915050565b600080613741858585613bdd565b67ffffffffffffffff8716600090815260086020908152604080832093835292905220549150505b949350505050565b60006002613780608085615646565b67ffffffffffffffff16613794919061566d565b905060006137a28585611ce9565b9050816137b16001600461561d565b901b1916818360038111156137c8576137c8614b17565b67ffffffffffffffff871660009081526007602052604081209190921b929092179182916137f7608088615a73565b67ffffffffffffffff1681526020810191909152604001600020555050505050565b6040517fa80036b4000000000000000000000000000000000000000000000000000000008152600090606090309063a80036b49061385d9087908790600401615f01565b600060405180830381600087803b15801561387757600080fd5b505af1925050508015613888575060015b6138c7573d8080156138b6576040519150601f19603f3d011682016040523d82523d6000602084013e6138bb565b606091505b506003925090506138dc565b50506040805160208101909152600081526002905b9250929050565b6000815160201461392257816040517f8d666f600000000000000000000000000000000000000000000000000000000081526004016106f89190614932565b6000828060200190518101906139389190615d50565b90506001600160a01b03811180613950575061040081105b15610d7a57826040517f8d666f600000000000000000000000000000000000000000000000000000000081526004016106f89190614932565b6000806000806000613a03886040516024016139b491906001600160a01b0391909116815260200190565b60408051601f198184030181529190526020810180516001600160e01b03167f70a082310000000000000000000000000000000000000000000000000000000017905288886113886084613ab7565b92509250925082613a4257816040517fe1cd55090000000000000000000000000000000000000000000000000000000081526004016106f89190614932565b6020825114613a8a5781516040517f78ef80240000000000000000000000000000000000000000000000000000000081526020600482015260248101919091526044016106f8565b81806020019051810190613a9e9190615d50565b613aa8828861561d565b94509450505050935093915050565b6000606060008361ffff1667ffffffffffffffff811115613ada57613ada613f44565b6040519080825280601f01601f191660200182016040528015613b04576020820181803683370190505b509150863b613b37577f0c3b563c0000000000000000000000000000000000000000000000000000000060005260046000fd5b5a85811015613b6a577fafa32a2c0000000000000000000000000000000000000000000000000000000060005260046000fd5b8590036040810481038710613ba3577f37c3be290000000000000000000000000000000000000000000000000000000060005260046000fd5b505a6000808a5160208c0160008c8cf193505a900390503d84811115613bc65750835b808352806000602085013e50955095509592505050565b8251825160009190818303613c1e576040517f11a6b26400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6101018211801590613c3257506101018111155b613c4f576040516309bde33960e01b815260040160405180910390fd5b60001982820101610100811115613c79576040516309bde33960e01b815260040160405180910390fd5b80600003613ca65786600081518110613c9457613c94614faa565b60200260200101519350505050613e75565b60008167ffffffffffffffff811115613cc157613cc1613f44565b604051908082528060200260200182016040528015613cea578160200160208202803683370190505b50905060008080805b85811015613e145760006001821b8b811603613d4e5788851015613d37578c5160018601958e918110613d2857613d28614faa565b60200260200101519050613d70565b8551600185019487918110613d2857613d28614faa565b8b5160018401938d918110613d6557613d65614faa565b602002602001015190505b600089861015613da0578d5160018701968f918110613d9157613d91614faa565b60200260200101519050613dc2565b8651600186019588918110613db757613db7614faa565b602002602001015190505b82851115613de3576040516309bde33960e01b815260040160405180910390fd5b613ded8282613e7c565b878481518110613dff57613dff614faa565b60209081029190910101525050600101613cf3565b506001850382148015613e2657508683145b8015613e3157508581145b613e4e576040516309bde33960e01b815260040160405180910390fd5b836001860381518110613e6357613e63614faa565b60200260200101519750505050505050505b9392505050565b6000818310613e9457613e8f8284613e9a565b610d77565b610d7783835b604080516001602082015290810183905260608101829052600090608001613715565b828054828255906000526020600020908101928215613f1f579160200282015b82811115613f1f578251825473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03909116178255602090920191600190910190613edd565b50613f2b929150613f2f565b5090565b5b80821115613f2b5760008155600101613f30565b634e487b7160e01b600052604160045260246000fd5b6040516080810167ffffffffffffffff81118282101715613f7d57613f7d613f44565b60405290565b60405160a0810167ffffffffffffffff81118282101715613f7d57613f7d613f44565b60405160c0810167ffffffffffffffff81118282101715613f7d57613f7d613f44565b6040805190810167ffffffffffffffff81118282101715613f7d57613f7d613f44565b6040516060810167ffffffffffffffff81118282101715613f7d57613f7d613f44565b604051601f8201601f1916810167ffffffffffffffff8111828210171561403857614038613f44565b604052919050565b600067ffffffffffffffff82111561405a5761405a613f44565b5060051b60200190565b6001600160a01b038116811461058157600080fd5b803567ffffffffffffffff8116811461409157600080fd5b919050565b801515811461058157600080fd5b803561409181614096565b600067ffffffffffffffff8211156140c9576140c9613f44565b50601f01601f191660200190565b600082601f8301126140e857600080fd5b81356140fb6140f6826140af565b61400f565b81815284602083860101111561411057600080fd5b816020850160208301376000918101602001919091529392505050565b6000602080838503121561414057600080fd5b823567ffffffffffffffff8082111561415857600080fd5b818501915085601f83011261416c57600080fd5b813561417a6140f682614040565b81815260059190911b8301840190848101908883111561419957600080fd5b8585015b8381101561423f578035858111156141b55760008081fd5b86016080818c03601f19018113156141cd5760008081fd5b6141d5613f5a565b898301356141e281614064565b815260406141f1848201614079565b8b83015260608085013561420481614096565b8383015292840135928984111561421d57600091508182fd5b61422b8f8d868801016140d7565b90830152508552505091860191860161419d565b5098975050505050505050565b600060a0828403121561425e57600080fd5b614266613f83565b90508135815261427860208301614079565b602082015261428960408301614079565b604082015261429a60608301614079565b60608201526142ab60808301614079565b608082015292915050565b803561409181614064565b600082601f8301126142d257600080fd5b813560206142e26140f683614040565b82815260059290921b8401810191818101908684111561430157600080fd5b8286015b84811015611fa957803567ffffffffffffffff808211156143265760008081fd5b9088019060a0828b03601f19018113156143405760008081fd5b614348613f83565b878401358381111561435a5760008081fd5b6143688d8a838801016140d7565b8252506040808501358481111561437f5760008081fd5b61438d8e8b838901016140d7565b8a84015250606080860135858111156143a65760008081fd5b6143b48f8c838a01016140d7565b838501525060809150818601358184015250828501359250838311156143da5760008081fd5b6143e88d8a858801016140d7565b908201528652505050918301918301614305565b6000610140828403121561440f57600080fd5b614417613fa6565b9050614423838361424c565b815260a082013567ffffffffffffffff8082111561444057600080fd5b61444c858386016140d7565b602084015260c084013591508082111561446557600080fd5b614471858386016140d7565b604084015261448260e085016142b6565b606084015261010084013560808401526101208401359150808211156144a757600080fd5b506144b4848285016142c1565b60a08301525092915050565b600082601f8301126144d157600080fd5b813560206144e16140f683614040565b82815260059290921b8401810191818101908684111561450057600080fd5b8286015b84811015611fa957803567ffffffffffffffff8111156145245760008081fd5b6145328986838b01016143fc565b845250918301918301614504565b600082601f83011261455157600080fd5b813560206145616140f683614040565b82815260059290921b8401810191818101908684111561458057600080fd5b8286015b84811015611fa957803567ffffffffffffffff808211156145a457600080fd5b818901915089603f8301126145b857600080fd5b858201356145c86140f682614040565b81815260059190911b830160400190878101908c8311156145e857600080fd5b604085015b838110156146215780358581111561460457600080fd5b6146138f6040838a01016140d7565b8452509189019189016145ed565b50875250505092840192508301614584565b600082601f83011261464457600080fd5b813560206146546140f683614040565b8083825260208201915060208460051b87010193508684111561467657600080fd5b602086015b84811015611fa9578035835291830191830161467b565b600082601f8301126146a357600080fd5b813560206146b36140f683614040565b82815260059290921b840181019181810190868411156146d257600080fd5b8286015b84811015611fa957803567ffffffffffffffff808211156146f75760008081fd5b9088019060a0828b03601f19018113156147115760008081fd5b614719613f83565b614724888501614079565b81526040808501358481111561473a5760008081fd5b6147488e8b838901016144c0565b8a84015250606080860135858111156147615760008081fd5b61476f8f8c838a0101614540565b838501525060809150818601358581111561478a5760008081fd5b6147988f8c838a0101614633565b91840191909152509190930135908301525083529183019183016146d6565b60008060408084860312156147cb57600080fd5b833567ffffffffffffffff808211156147e357600080fd5b6147ef87838801614692565b945060209150818601358181111561480657600080fd5b8601601f8101881361481757600080fd5b80356148256140f682614040565b81815260059190911b8201840190848101908a83111561484457600080fd5b8584015b838110156148d0578035868111156148605760008081fd5b8501603f81018d136148725760008081fd5b878101356148826140f682614040565b81815260059190911b82018a0190898101908f8311156148a25760008081fd5b928b01925b828410156148c05783358252928a0192908a01906148a7565b8652505050918601918601614848565b50809750505050505050509250929050565b60005b838110156148fd5781810151838201526020016148e5565b50506000910152565b6000815180845261491e8160208601602086016148e2565b601f01601f19169290920160200192915050565b602081526000610d776020830184614906565b8060608101831015610d7a57600080fd5b60008083601f84011261496857600080fd5b50813567ffffffffffffffff81111561498057600080fd5b6020830191508360208285010111156138dc57600080fd5b60008083601f8401126149aa57600080fd5b50813567ffffffffffffffff8111156149c257600080fd5b6020830191508360208260051b85010111156138dc57600080fd5b60008060008060008060008060e0898b0312156149f957600080fd5b614a038a8a614945565b9750606089013567ffffffffffffffff80821115614a2057600080fd5b614a2c8c838d01614956565b909950975060808b0135915080821115614a4557600080fd5b614a518c838d01614998565b909750955060a08b0135915080821115614a6a57600080fd5b50614a778b828c01614998565b999c989b50969995989497949560c00135949350505050565b600080600060808486031215614aa557600080fd5b614aaf8585614945565b9250606084013567ffffffffffffffff811115614acb57600080fd5b614ad786828701614956565b9497909650939450505050565b60008060408385031215614af757600080fd5b614b0083614079565b9150614b0e60208401614079565b90509250929050565b634e487b7160e01b600052602160045260246000fd5b60048110614b3d57614b3d614b17565b9052565b60208101610d7a8284614b2d565b600060208284031215614b6157600080fd5b813567ffffffffffffffff811115614b7857600080fd5b820160a08185031215613e7557600080fd5b803563ffffffff8116811461409157600080fd5b600060a08284031215614bb057600080fd5b614bb8613f83565b8235614bc381614064565b8152614bd160208401614b8a565b6020820152614be260408401614b8a565b6040820152614bf360608401614b8a565b60608201526080830135614c0681614064565b60808201529392505050565b600080600060408486031215614c2757600080fd5b833567ffffffffffffffff80821115614c3f57600080fd5b614c4b878388016143fc565b94506020860135915080821115614c6157600080fd5b50614ad786828701614998565b803560ff8116811461409157600080fd5b600060208284031215614c9157600080fd5b610d7782614c6e565b60008151808452602080850194506020840160005b83811015614cd45781516001600160a01b031687529582019590820190600101614caf565b509495945050505050565b60208152600082518051602084015260ff602082015116604084015260ff604082015116606084015260608101511515608084015250602083015160c060a0840152614d2e60e0840182614c9a565b90506040840151601f198483030160c0850152614d4b8282614c9a565b95945050505050565b60008060408385031215614d6757600080fd5b614d7083614079565b946020939093013593505050565b600060208284031215614d9057600080fd5b610d7782614079565b602081526001600160a01b03825116602082015260208201511515604082015267ffffffffffffffff60408301511660608201526000606083015160808084015261376960a0840182614906565b600060208284031215614df957600080fd5b8135613e7581614064565b600082601f830112614e1557600080fd5b81356020614e256140f683614040565b8083825260208201915060208460051b870101935086841115614e4757600080fd5b602086015b84811015611fa9578035614e5f81614064565b8352918301918301614e4c565b60006020808385031215614e7f57600080fd5b823567ffffffffffffffff80821115614e9757600080fd5b818501915085601f830112614eab57600080fd5b8135614eb96140f682614040565b81815260059190911b83018401908481019088831115614ed857600080fd5b8585015b8381101561423f57803585811115614ef357600080fd5b860160c0818c03601f19011215614f0a5760008081fd5b614f12613fa6565b8882013581526040614f25818401614c6e565b8a8301526060614f36818501614c6e565b8284015260809150614f498285016140a4565b9083015260a08381013589811115614f615760008081fd5b614f6f8f8d83880101614e04565b838501525060c0840135915088821115614f895760008081fd5b614f978e8c84870101614e04565b9083015250845250918601918601614edc565b634e487b7160e01b600052603260045260246000fd5b80356001600160e01b038116811461409157600080fd5b600082601f830112614fe857600080fd5b81356020614ff86140f683614040565b82815260069290921b8401810191818101908684111561501757600080fd5b8286015b84811015611fa957604081890312156150345760008081fd5b61503c613fc9565b61504582614079565b8152615052858301614fc0565b8186015283529183019160400161501b565b600082601f83011261507557600080fd5b813560206150856140f683614040565b82815260059290921b840181019181810190868411156150a457600080fd5b8286015b84811015611fa957803567ffffffffffffffff808211156150c95760008081fd5b9088019060a0828b03601f19018113156150e35760008081fd5b6150eb613f83565b6150f6888501614079565b81526040615105818601614079565b898301526060615116818701614079565b82840152608091508186013581840152508285013592508383111561513b5760008081fd5b6151498d8a858801016140d7565b9082015286525050509183019183016150a8565b600082601f83011261516e57600080fd5b8135602061517e6140f683614040565b82815260069290921b8401810191818101908684111561519d57600080fd5b8286015b84811015611fa957604081890312156151ba5760008081fd5b6151c2613fc9565b8135815284820135858201528352918301916040016151a1565b600060208083850312156151ef57600080fd5b823567ffffffffffffffff8082111561520757600080fd5b908401906060828703121561521b57600080fd5b615223613fec565b82358281111561523257600080fd5b8301604081890381131561524557600080fd5b61524d613fc9565b82358581111561525c57600080fd5b8301601f81018b1361526d57600080fd5b803561527b6140f682614040565b81815260069190911b8201890190898101908d83111561529a57600080fd5b928a01925b828410156152ea5785848f0312156152b75760008081fd5b6152bf613fc9565b84356152ca81614064565b81526152d7858d01614fc0565b818d0152825292850192908a019061529f565b84525050508287013591508482111561530257600080fd5b61530e8a838501614fd7565b8188015283525050828401358281111561532757600080fd5b61533388828601615064565b8583015250604083013593508184111561534c57600080fd5b6153588785850161515d565b60408201529695505050505050565b600082825180855260208086019550808260051b84010181860160005b848110156153f757858303601f190189528151805167ffffffffffffffff908116855285820151811686860152604080830151909116908501526060808201519085015260809081015160a0918501829052906153e381860183614906565b9a86019a9450505090830190600101615384565b5090979650505050505050565b60008151808452602080850194506020840160005b83811015614cd4578151805188528301518388015260409096019590820190600101615419565b6040815260006154536040830185615367565b8281036020840152614d4b8185615404565b805160408084528151848201819052600092602091908201906060870190855b818110156154bc57835180516001600160a01b031684528501516001600160e01b0316858401529284019291850191600101615485565b50508583015187820388850152805180835290840192506000918401905b80831015615516578351805167ffffffffffffffff1683528501516001600160e01b0316858301529284019260019290920191908501906154da565b50979650505050505050565b602081526000610d776020830184615465565b60006020828403121561554757600080fd5b8151613e7581614096565b634e487b7160e01b600052601160045260246000fd5b67ffffffffffffffff81811683821601908082111561558957615589615552565b5092915050565b6020815260008251606060208401526155ac6080840182615465565b90506020840151601f19808584030160408601526155ca8383615367565b9250604086015191508085840301606086015250614d4b8282615404565b6000602082840312156155fa57600080fd5b813567ffffffffffffffff81111561561157600080fd5b61376984828501614692565b81810381811115610d7a57610d7a615552565b634e487b7160e01b600052601260045260246000fd5b600067ffffffffffffffff8084168061566157615661615630565b92169190910692915050565b8082028115828204841417610d7a57610d7a615552565b805182526000602067ffffffffffffffff81840151168185015260408084015160a060408701526156b860a0870182614906565b9050606085015186820360608801526156d18282614906565b608087810151898303918a01919091528051808352908601935060009250908501905b8083101561551657835180516001600160a01b03168352860151868301529285019260019290920191908401906156f4565b602081526000610d776020830184615684565b60808152600061574c6080830187615684565b61ffff9590951660208301525060408101929092526001600160a01b0316606090910152919050565b60008060006060848603121561578a57600080fd5b835161579581614096565b602085015190935067ffffffffffffffff8111156157b257600080fd5b8401601f810186136157c357600080fd5b80516157d16140f6826140af565b8181528760208385010111156157e657600080fd5b6157f78260208301602086016148e2565b809450505050604084015190509250925092565b600181811c9082168061581f57607f821691505b60208210810361583f57634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115610724576000816000526020600020601f850160051c8101602086101561586e5750805b601f850160051c820191505b8181101561588d5782815560010161587a565b505050505050565b815167ffffffffffffffff8111156158af576158af613f44565b6158c3816158bd845461580b565b84615845565b602080601f8311600181146158f857600084156158e05750858301515b600019600386901b1c1916600185901b17855561588d565b600085815260208120601f198616915b8281101561592757888601518255948401946001909101908401615908565b50858210156159455787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6000602080835283546001600160a01b038116602085015260ff8160a01c161515604085015267ffffffffffffffff8160a81c166060850152506001808501608080860152600081546159a78161580b565b8060a089015260c060018316600081146159c857600181146159e457615a14565b60ff19841660c08b015260c083151560051b8b01019450615a14565b85600052602060002060005b84811015615a0b5781548c82018501529088019089016159f0565b8b0160c0019550505b50929998505050505050505050565b80820180821115610d7a57610d7a615552565b60ff8181168382160190811115610d7a57610d7a615552565b8183823760009101908152919050565b828152606082602083013760800192915050565b600067ffffffffffffffff80841680615a8e57615a8e615630565b92169190910492915050565b6000808335601e19843603018112615ab157600080fd5b83018035915067ffffffffffffffff821115615acc57600080fd5b6020019150368190038213156138dc57600080fd5b6020810160058310615af557615af5614b17565b91905290565b60ff818116838216029081169081811461558957615589615552565b600060a0820160ff881683526020878185015260a0604085015281875480845260c0860191508860005282600020935060005b81811015615b6f5784546001600160a01b031683526001948501949284019201615b4a565b50508481036060860152865180825290820192508187019060005b81811015615baf5782516001600160a01b031685529383019391830191600101615b8a565b50505060ff85166080850152509050611fab565b600067ffffffffffffffff808616835280851660208401525060606040830152614d4b6060830184614906565b8281526040602082015260006137696040830184614906565b67ffffffffffffffff848116825283166020820152606081016137696040830184614b2d565b848152615c3f6020820185614b2d565b608060408201526000615c556080830185614906565b905082606083015295945050505050565b600060208284031215615c7857600080fd5b8151613e7581614064565b6020815260008251610100806020850152615ca2610120850183614906565b91506020850151615cbf604086018267ffffffffffffffff169052565b5060408501516001600160a01b038116606086015250606085015160808501526080850151615cf960a08601826001600160a01b03169052565b5060a0850151601f19808685030160c0870152615d168483614906565b935060c08701519150808685030160e0870152615d338483614906565b935060e0870151915080868503018387015250611fab8382614906565b600060208284031215615d6257600080fd5b5051919050565b848152600067ffffffffffffffff808616602084015280851660408401525060806060830152611fab6080830184614906565b86815260c060208201526000615db560c0830188614906565b6001600160a01b039690961660408301525067ffffffffffffffff9384166060820152608081019290925290911660a09091015292915050565b600082825180855260208086019550808260051b84010181860160005b848110156153f757601f19868403018952815160a08151818652615e3282870182614906565b9150508582015185820387870152615e4a8282614906565b91505060408083015186830382880152615e648382614906565b92505050606080830151818701525060808083015192508582038187015250615e8d8183614906565b9a86019a9450505090830190600101615e0c565b602081526000610d776020830184615def565b60008282518085526020808601955060208260051b8401016020860160005b848110156153f757601f19868403018952615eef838351614906565b98840198925090830190600101615ed3565b604081526000835180516040840152602081015167ffffffffffffffff80821660608601528060408401511660808601528060608401511660a08601528060808401511660c086015250505060208401516101408060e0850152615f69610180850183614906565b91506040860151603f198086850301610100870152615f888483614906565b935060608801519150615fa76101208701836001600160a01b03169052565b60808801518387015260a0880151925080868503016101608701525050615fce8282615def565b9150508281036020840152614d4b8185615eb456fea164736f6c6343000818000a", } var OffRampABI = OffRampMetaData.ABI diff --git a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt index 6396cf5cea..7bf6d2a158 100644 --- a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -23,7 +23,7 @@ multi_aggregate_rate_limiter: ../../../contracts/solc/v0.8.24/MultiAggregateRate multi_ocr3_helper: ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Helper.abi ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Helper.bin 6b56e0114a4d50797d30a34aecc2641ef340451d0c3fcb9d729bba4df2435122 nonce_manager: ../../../contracts/solc/v0.8.24/NonceManager/NonceManager.abi ../../../contracts/solc/v0.8.24/NonceManager/NonceManager.bin 6f64e1083b356c06ee66b9138e398b9c97a4cd3e8c9ec38cf3010cebc79af536 ocr3_config_encoder: ../../../contracts/solc/v0.8.24/IOCR3ConfigEncoder/IOCR3ConfigEncoder.abi ../../../contracts/solc/v0.8.24/IOCR3ConfigEncoder/IOCR3ConfigEncoder.bin 9254b35a86f00fde7b7193a033ca58f6521a66e87b9cf9da6ce5660082e79f5d -offramp: ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.abi ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.bin 2d1cdfd810e2fde409610f4d188889e62a41c8baceb8948849c9a78623a252b6 +offramp: ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.abi ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.bin f8b00a000ceaadcd9d0c2a9d78f6d2aedbff1e3dcdb66e4fd23333ed6daf26e7 onramp: ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.abi ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.bin c37096aaa0369ad988e94c300ba62917e17fcc71a3c1aa3e9b8420f21c0591d2 ping_pong_demo: ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.abi ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.bin c1c2f8a65c7ffd971899cae7fe62f2da57d09e936151e2b92163c4bebe699d6b price_registry: ../../../contracts/solc/v0.8.24/PriceRegistry/PriceRegistry.abi ../../../contracts/solc/v0.8.24/PriceRegistry/PriceRegistry.bin e7781d600c1bb7aa4620106af7f6e146a109b97f4cb6a7d06c9e15773340ecb2 From 8e883b08ae483bee91f37a6b9ad0407da4ebde17 Mon Sep 17 00:00:00 2001 From: Ryan Hall Date: Mon, 9 Sep 2024 13:41:31 -0400 Subject: [PATCH 078/115] Revert "reorder fields in MerkleRoot struct" (#1417) ## Motivation Avoid forcing breaking changes on RMN nodes ## Solution This reverts commit da570c5. --- contracts/gas-snapshots/ccip.gas-snapshot | 52 +++++++++---------- .../src/v0.8/ccip/libraries/Internal.sol | 8 +-- .../v0.8/ccip/test/e2e/MultiRampsEnd2End.sol | 8 +-- .../src/v0.8/ccip/test/offRamp/OffRamp.t.sol | 40 +++++++------- .../ccip_reader_tester/ccip_reader_tester.go | 8 +-- .../ccip/generated/offramp/offramp.go | 8 +-- .../generated/report_codec/report_codec.go | 8 +-- .../ccip/generated/rmn_remote/rmn_remote.go | 6 +-- ...rapper-dependency-versions-do-not-edit.txt | 8 +-- 9 files changed, 74 insertions(+), 72 deletions(-) diff --git a/contracts/gas-snapshots/ccip.gas-snapshot b/contracts/gas-snapshots/ccip.gas-snapshot index 2ecd600642..8d215c59b5 100644 --- a/contracts/gas-snapshots/ccip.gas-snapshot +++ b/contracts/gas-snapshots/ccip.gas-snapshot @@ -560,7 +560,7 @@ MultiOCR3Base_transmit:test_UnauthorizedSigner_Revert() (gas: 61131) MultiOCR3Base_transmit:test_UnconfiguredPlugin_Revert() (gas: 39888) MultiOCR3Base_transmit:test_ZeroSignatures_Revert() (gas: 32971) MultiOnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 411753) -MultiRampsE2E:test_E2E_3MessagesMMultiOffRampSuccess_gas() (gas: 1527968) +MultiRampsE2E:test_E2E_3MessagesMMultiOffRampSuccess_gas() (gas: 1528026) NonceManager_NonceIncrementation:test_getIncrementedOutboundNonce_Success() (gas: 37916) NonceManager_NonceIncrementation:test_incrementInboundNonce_Skip() (gas: 23709) NonceManager_NonceIncrementation:test_incrementInboundNonce_Success() (gas: 38799) @@ -608,7 +608,7 @@ OCR2Base_transmit:test_Transmit2SignersSuccess_gas() (gas: 51689) OCR2Base_transmit:test_UnAuthorizedTransmitter_Revert() (gas: 23499) OCR2Base_transmit:test_UnauthorizedSigner_Revert() (gas: 39695) OCR2Base_transmit:test_WrongNumberOfSignatures_Revert() (gas: 20572) -OffRamp_afterOC3ConfigSet:test_afterOCR3ConfigSet_SignatureVerificationDisabled_Revert() (gas: 5850100) +OffRamp_afterOC3ConfigSet:test_afterOCR3ConfigSet_SignatureVerificationDisabled_Revert() (gas: 5849491) OffRamp_applySourceChainConfigUpdates:test_AddMultipleChains_Success() (gas: 468052) OffRamp_applySourceChainConfigUpdates:test_AddNewChain_Success() (gas: 99216) OffRamp_applySourceChainConfigUpdates:test_ApplyZeroUpdates_Success() (gas: 12392) @@ -626,26 +626,26 @@ OffRamp_batchExecute:test_SingleReport_Success() (gas: 155963) OffRamp_batchExecute:test_Unhealthy_Success() (gas: 573311) OffRamp_batchExecute:test_ZeroReports_Revert() (gas: 10440) OffRamp_ccipReceive:test_Reverts() (gas: 15705) -OffRamp_commit:test_FailedRMNVerification_Reverts() (gas: 64343) -OffRamp_commit:test_InvalidIntervalMinLargerThanMax_Revert() (gas: 67494) -OffRamp_commit:test_InvalidInterval_Revert() (gas: 59807) -OffRamp_commit:test_InvalidRootRevert() (gas: 58865) -OffRamp_commit:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6454926) -OffRamp_commit:test_NoConfig_Revert() (gas: 6038739) -OffRamp_commit:test_OnlyGasPriceUpdates_Success() (gas: 113421) -OffRamp_commit:test_OnlyPriceUpdateStaleReport_Revert() (gas: 121444) -OffRamp_commit:test_OnlyTokenPriceUpdates_Success() (gas: 113442) -OffRamp_commit:test_PriceSequenceNumberCleared_Success() (gas: 355496) -OffRamp_commit:test_ReportAndPriceUpdate_Success() (gas: 166631) -OffRamp_commit:test_ReportOnlyRootSuccess_gas() (gas: 141711) -OffRamp_commit:test_RootAlreadyCommitted_Revert() (gas: 142664) -OffRamp_commit:test_SourceChainNotEnabled_Revert() (gas: 59129) -OffRamp_commit:test_StaleReportWithRoot_Success() (gas: 239467) -OffRamp_commit:test_UnauthorizedTransmitter_Revert() (gas: 122361) -OffRamp_commit:test_Unhealthy_Revert() (gas: 57858) -OffRamp_commit:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 211983) -OffRamp_commit:test_ZeroEpochAndRound_Revert() (gas: 51264) -OffRamp_constructor:test_Constructor_Success() (gas: 6039389) +OffRamp_commit:test_FailedRMNVerification_Reverts() (gas: 64462) +OffRamp_commit:test_InvalidIntervalMinLargerThanMax_Revert() (gas: 67674) +OffRamp_commit:test_InvalidInterval_Revert() (gas: 59928) +OffRamp_commit:test_InvalidRootRevert() (gas: 58963) +OffRamp_commit:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6454659) +OffRamp_commit:test_NoConfig_Revert() (gas: 6038472) +OffRamp_commit:test_OnlyGasPriceUpdates_Success() (gas: 113541) +OffRamp_commit:test_OnlyPriceUpdateStaleReport_Revert() (gas: 121576) +OffRamp_commit:test_OnlyTokenPriceUpdates_Success() (gas: 113562) +OffRamp_commit:test_PriceSequenceNumberCleared_Success() (gas: 355724) +OffRamp_commit:test_ReportAndPriceUpdate_Success() (gas: 166923) +OffRamp_commit:test_ReportOnlyRootSuccess_gas() (gas: 141978) +OffRamp_commit:test_RootAlreadyCommitted_Revert() (gas: 142982) +OffRamp_commit:test_SourceChainNotEnabled_Revert() (gas: 59250) +OffRamp_commit:test_StaleReportWithRoot_Success() (gas: 240109) +OffRamp_commit:test_UnauthorizedTransmitter_Revert() (gas: 122475) +OffRamp_commit:test_Unhealthy_Revert() (gas: 57991) +OffRamp_commit:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 212415) +OffRamp_commit:test_ZeroEpochAndRound_Revert() (gas: 51324) +OffRamp_constructor:test_Constructor_Success() (gas: 6038780) OffRamp_constructor:test_SourceChainSelector_Revert() (gas: 136917) OffRamp_constructor:test_ZeroChainSelector_Revert() (gas: 103646) OffRamp_constructor:test_ZeroNonceManager_Revert() (gas: 101523) @@ -656,12 +656,12 @@ OffRamp_execute:test_IncorrectArrayType_Revert() (gas: 17281) OffRamp_execute:test_LargeBatch_Success() (gas: 3378308) OffRamp_execute:test_MultipleReportsWithPartialValidationFailures_Success() (gas: 372457) OffRamp_execute:test_MultipleReports_Success() (gas: 298416) -OffRamp_execute:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6861731) -OffRamp_execute:test_NoConfig_Revert() (gas: 6086529) +OffRamp_execute:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6861122) +OffRamp_execute:test_NoConfig_Revert() (gas: 6085920) OffRamp_execute:test_NonArray_Revert() (gas: 27721) OffRamp_execute:test_SingleReport_Success() (gas: 175215) OffRamp_execute:test_UnauthorizedTransmitter_Revert() (gas: 147455) -OffRamp_execute:test_WrongConfigWithSigners_Revert() (gas: 6864474) +OffRamp_execute:test_WrongConfigWithSigners_Revert() (gas: 6863865) OffRamp_execute:test_ZeroReports_Revert() (gas: 17162) OffRamp_executeSingleMessage:test_MessageSender_Revert() (gas: 18212) OffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 249178) @@ -678,7 +678,7 @@ OffRamp_executeSingleReport:test_EmptyReport_Revert() (gas: 21860) OffRamp_executeSingleReport:test_InvalidSourcePoolAddress_Success() (gas: 502029) OffRamp_executeSingleReport:test_ManualExecutionNotYetEnabled_Revert() (gas: 47635) OffRamp_executeSingleReport:test_MismatchingDestChainSelector_Revert() (gas: 33895) -OffRamp_executeSingleReport:test_MismatchingOnRampRoot_Revert() (gas: 155036) +OffRamp_executeSingleReport:test_MismatchingOnRampRoot_Revert() (gas: 155054) OffRamp_executeSingleReport:test_NonExistingSourceChain_Revert() (gas: 28472) OffRamp_executeSingleReport:test_ReceiverError_Success() (gas: 187688) OffRamp_executeSingleReport:test_RetryFailedMessageWithoutManualExecution_Revert() (gas: 198173) diff --git a/contracts/src/v0.8/ccip/libraries/Internal.sol b/contracts/src/v0.8/ccip/libraries/Internal.sol index 58ae6279b8..5d91219e04 100644 --- a/contracts/src/v0.8/ccip/libraries/Internal.sol +++ b/contracts/src/v0.8/ccip/libraries/Internal.sol @@ -341,11 +341,13 @@ library Internal { /// @dev Struct to hold a merkle root and an interval for a source chain so that an array of these can be passed in the CommitReport. /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers. + /// @dev ineffiecient struct packing intentionally chosen to maintain order of specificity. Not a storage struct so impact is minimal. + // solhint-disable-next-line gas-struct-packing struct MerkleRoot { - uint64 sourceChainSelector; // ──╮ Remote source chain selector that the Merkle Root is scoped to - uint64 minSeqNr; // | Minimum sequence number, inclusive + uint64 sourceChainSelector; // Remote source chain selector that the Merkle Root is scoped to + bytes onRampAddress; // Generic onramp address, to support arbitrary sources; for EVM, use abi.encode + uint64 minSeqNr; // ─────────────╮ Minimum sequence number, inclusive uint64 maxSeqNr; // ─────────────╯ Maximum sequence number, inclusive bytes32 merkleRoot; // Merkle root covering the interval & source chain messages - bytes onRampAddress; // Generic onramp address, to support arbitrary sources; for EVM, use abi.encode } } diff --git a/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.sol b/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.sol index 79999fa5b4..446dcfc344 100644 --- a/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.sol +++ b/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.sol @@ -155,17 +155,17 @@ contract MultiRampsE2E is OnRampSetup, OffRampSetup { Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](2); roots[0] = Internal.MerkleRoot({ sourceChainSelector: SOURCE_CHAIN_SELECTOR, + onRampAddress: abi.encode(address(s_onRamp)), minSeqNr: messages1[0].header.sequenceNumber, maxSeqNr: messages1[1].header.sequenceNumber, - merkleRoot: merkleRoots[0], - onRampAddress: abi.encode(address(s_onRamp)) + merkleRoot: merkleRoots[0] }); roots[1] = Internal.MerkleRoot({ sourceChainSelector: SOURCE_CHAIN_SELECTOR + 1, + onRampAddress: abi.encode(address(s_onRamp)), minSeqNr: messages2[0].header.sequenceNumber, maxSeqNr: messages2[0].header.sequenceNumber, - merkleRoot: merkleRoots[1], - onRampAddress: abi.encode(address(s_onRamp)) + merkleRoot: merkleRoots[1] }); OffRamp.CommitReport memory report = diff --git a/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol index e720b1ddb1..cce4a19105 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol @@ -971,10 +971,10 @@ contract OffRamp_executeSingleReport is OffRampSetup { Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](1); roots[0] = Internal.MerkleRoot({ sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, + onRampAddress: abi.encode(ON_RAMP_ADDRESS_1), minSeqNr: 1, maxSeqNr: 2, - merkleRoot: merkleRoot, - onRampAddress: abi.encode(ON_RAMP_ADDRESS_1) + merkleRoot: merkleRoot }); return OffRamp.CommitReport({ @@ -3138,10 +3138,10 @@ contract OffRamp_commit is OffRampSetup { Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](1); roots[0] = Internal.MerkleRoot({ sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, + onRampAddress: abi.encode(ON_RAMP_ADDRESS_1), minSeqNr: 1, maxSeqNr: max1, - merkleRoot: root, - onRampAddress: abi.encode(ON_RAMP_ADDRESS_1) + merkleRoot: root }); OffRamp.CommitReport memory commitReport = @@ -3167,10 +3167,10 @@ contract OffRamp_commit is OffRampSetup { Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](1); roots[0] = Internal.MerkleRoot({ sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, + onRampAddress: abi.encode(ON_RAMP_ADDRESS_1), minSeqNr: 1, maxSeqNr: maxSeq, - merkleRoot: "stale report 1", - onRampAddress: abi.encode(ON_RAMP_ADDRESS_1) + merkleRoot: "stale report 1" }); OffRamp.CommitReport memory commitReport = OffRamp.CommitReport({priceUpdates: _getEmptyPriceUpdates(), merkleRoots: roots, rmnSignatures: s_rmnSignatures}); @@ -3318,10 +3318,10 @@ contract OffRamp_commit is OffRampSetup { roots = new Internal.MerkleRoot[](1); roots[0] = Internal.MerkleRoot({ sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, + onRampAddress: abi.encode(ON_RAMP_ADDRESS_1), minSeqNr: 1, maxSeqNr: maxSeq, - merkleRoot: "stale report", - onRampAddress: abi.encode(ON_RAMP_ADDRESS_1) + merkleRoot: "stale report" }); commitReport.priceUpdates = _getSingleTokenPriceUpdateStruct(s_sourceFeeToken, tokenPrice2); commitReport.merkleRoots = roots; @@ -3424,10 +3424,10 @@ contract OffRamp_commit is OffRampSetup { Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](1); roots[0] = Internal.MerkleRoot({ sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, + onRampAddress: abi.encode(ON_RAMP_ADDRESS_1), minSeqNr: 1, maxSeqNr: 4, - merkleRoot: bytes32(0), - onRampAddress: abi.encode(ON_RAMP_ADDRESS_1) + merkleRoot: bytes32(0) }); OffRamp.CommitReport memory commitReport = OffRamp.CommitReport({priceUpdates: _getEmptyPriceUpdates(), merkleRoots: roots, rmnSignatures: s_rmnSignatures}); @@ -3440,10 +3440,10 @@ contract OffRamp_commit is OffRampSetup { Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](1); roots[0] = Internal.MerkleRoot({ sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, + onRampAddress: abi.encode(ON_RAMP_ADDRESS_1), minSeqNr: 2, maxSeqNr: 2, - merkleRoot: bytes32(0), - onRampAddress: abi.encode(ON_RAMP_ADDRESS_1) + merkleRoot: bytes32(0) }); OffRamp.CommitReport memory commitReport = OffRamp.CommitReport({priceUpdates: _getEmptyPriceUpdates(), merkleRoots: roots, rmnSignatures: s_rmnSignatures}); @@ -3461,10 +3461,10 @@ contract OffRamp_commit is OffRampSetup { Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](1); roots[0] = Internal.MerkleRoot({ sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, + onRampAddress: abi.encode(ON_RAMP_ADDRESS_1), minSeqNr: 1, maxSeqNr: 0, - merkleRoot: bytes32(0), - onRampAddress: abi.encode(ON_RAMP_ADDRESS_1) + merkleRoot: bytes32(0) }); OffRamp.CommitReport memory commitReport = OffRamp.CommitReport({priceUpdates: _getEmptyPriceUpdates(), merkleRoots: roots, rmnSignatures: s_rmnSignatures}); @@ -3509,10 +3509,10 @@ contract OffRamp_commit is OffRampSetup { Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](1); roots[0] = Internal.MerkleRoot({ sourceChainSelector: 0, + onRampAddress: abi.encode(ON_RAMP_ADDRESS_1), minSeqNr: 1, maxSeqNr: 2, - merkleRoot: "Only a single root", - onRampAddress: abi.encode(ON_RAMP_ADDRESS_1) + merkleRoot: "Only a single root" }); OffRamp.CommitReport memory commitReport = @@ -3526,10 +3526,10 @@ contract OffRamp_commit is OffRampSetup { Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](1); roots[0] = Internal.MerkleRoot({ sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, + onRampAddress: abi.encode(ON_RAMP_ADDRESS_1), minSeqNr: 1, maxSeqNr: 2, - merkleRoot: "Only a single root", - onRampAddress: abi.encode(ON_RAMP_ADDRESS_1) + merkleRoot: "Only a single root" }); OffRamp.CommitReport memory commitReport = OffRamp.CommitReport({priceUpdates: _getEmptyPriceUpdates(), merkleRoots: roots, rmnSignatures: s_rmnSignatures}); @@ -3548,10 +3548,10 @@ contract OffRamp_commit is OffRampSetup { Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](1); roots[0] = Internal.MerkleRoot({ sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, + onRampAddress: abi.encode(ON_RAMP_ADDRESS_1), minSeqNr: 1, maxSeqNr: s_maxInterval, - merkleRoot: "test #2", - onRampAddress: abi.encode(ON_RAMP_ADDRESS_1) + merkleRoot: "test #2" }); return OffRamp.CommitReport({ diff --git a/core/gethwrappers/ccip/generated/ccip_reader_tester/ccip_reader_tester.go b/core/gethwrappers/ccip/generated/ccip_reader_tester/ccip_reader_tester.go index 1c19bd60bd..fa9224ef21 100644 --- a/core/gethwrappers/ccip/generated/ccip_reader_tester/ccip_reader_tester.go +++ b/core/gethwrappers/ccip/generated/ccip_reader_tester/ccip_reader_tester.go @@ -53,10 +53,10 @@ type InternalGasPriceUpdate struct { type InternalMerkleRoot struct { SourceChainSelector uint64 + OnRampAddress []byte MinSeqNr uint64 MaxSeqNr uint64 MerkleRoot [32]byte - OnRampAddress []byte } type InternalPriceUpdates struct { @@ -99,8 +99,8 @@ type OffRampSourceChainConfig struct { } var CCIPReaderTesterMetaData = &bind.MetaData{ - ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"CCIPSendRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"structIRMNV2.Signature[]\",\"name\":\"rmnSignatures\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"report\",\"type\":\"tuple\"}],\"name\":\"CommitReportAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"name\":\"ExecutionStateChanged\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"emitCCIPSendRequested\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"structIRMNV2.Signature[]\",\"name\":\"rmnSignatures\",\"type\":\"tuple[]\"}],\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"report\",\"type\":\"tuple\"}],\"name\":\"emitCommitReportAccepted\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"name\":\"emitExecutionStateChanged\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getExpectedNextSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"getSourceChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"setDestChainSeqNr\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"sourceChainConfig\",\"type\":\"tuple\"}],\"name\":\"setSourceChainConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x608060405234801561001057600080fd5b506113f1806100206000396000f3fe608060405234801561001057600080fd5b506004361061006d5760003560e01c806344f38be5146100725780634cf66e361461008757806385096da91461009a5780639041be3d146100ad578063c1a5a355146100dd578063e83eabba14610119578063e9d68a8e1461012c575b600080fd5b6100856100803660046107e2565b61014c565b005b61008561009536600461096c565b610186565b6100856100a8366004610b8e565b6101db565b6100c06100bb366004610cbc565b610220565b6040516001600160401b0390911681526020015b60405180910390f35b6100856100eb366004610cde565b6001600160401b03918216600090815260016020526040902080546001600160401b03191691909216179055565b610085610127366004610d11565b61024f565b61013f61013a366004610cbc565b6102db565b6040516100d49190610e12565b7fd7868a16facbdde7b5c020620136316b3c266fffcb4e1e41cb6a662fe14ba3e18160405161017b9190610fa8565b60405180910390a150565b82846001600160401b0316866001600160401b03167f8c324ce1367b83031769f6a813e3bb4c117aba2185789d66b98b791405be6df285856040516101cc92919061107a565b60405180910390a45050505050565b816001600160401b03167fcae3d9f68a9ed33d0a770e9bcc6fc25d4041dd6391e6cd8015546547a3c93140826040516102149190611163565b60405180910390a25050565b6001600160401b0380821660009081526001602081905260408220549192610249921690611265565b92915050565b6001600160401b0380831660009081526020818152604091829020845181549286015193860151909416600160a81b02600160a81b600160e81b0319931515600160a01b026001600160a81b03199093166001600160a01b03909516949094179190911791909116919091178155606082015182919060018201906102d49082611325565b5050505050565b60408051608080820183526000808352602080840182905283850182905260608085018190526001600160401b038781168452838352928690208651948501875280546001600160a01b0381168652600160a01b810460ff16151593860193909352600160a81b9092049092169483019490945260018401805493949293918401916103669061129a565b80601f01602080910402602001604051908101604052809291908181526020018280546103929061129a565b80156103df5780601f106103b4576101008083540402835291602001916103df565b820191906000526020600020905b8154815290600101906020018083116103c257829003601f168201915b5050505050815250509050919050565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b0381118282101715610427576104276103ef565b60405290565b60405160a081016001600160401b0381118282101715610427576104276103ef565b604051606081016001600160401b0381118282101715610427576104276103ef565b60405161010081016001600160401b0381118282101715610427576104276103ef565b604051608081016001600160401b0381118282101715610427576104276103ef565b604051601f8201601f191681016001600160401b03811182821017156104de576104de6103ef565b604052919050565b60006001600160401b038211156104ff576104ff6103ef565b5060051b60200190565b6001600160a01b038116811461051e57600080fd5b50565b803561052c81610509565b919050565b80356001600160e01b038116811461052c57600080fd5b80356001600160401b038116811461052c57600080fd5b600082601f83011261057057600080fd5b81356020610585610580836104e6565b6104b6565b82815260069290921b840181019181810190868411156105a457600080fd5b8286015b848110156105f157604081890312156105c15760008081fd5b6105c9610405565b6105d282610548565b81526105df858301610531565b818601528352918301916040016105a8565b509695505050505050565b600082601f83011261060d57600080fd5b81356001600160401b03811115610626576106266103ef565b610639601f8201601f19166020016104b6565b81815284602083860101111561064e57600080fd5b816020850160208301376000918101602001919091529392505050565b600082601f83011261067c57600080fd5b8135602061068c610580836104e6565b82815260059290921b840181019181810190868411156106ab57600080fd5b8286015b848110156105f15780356001600160401b03808211156106cf5760008081fd5b9088019060a0828b03601f19018113156106e95760008081fd5b6106f161042d565b6106fc888501610548565b8152604061070b818601610548565b89830152606061071c818701610548565b8284015260809150818601358184015250828501359250838311156107415760008081fd5b61074f8d8a858801016105fc565b9082015286525050509183019183016106af565b600082601f83011261077457600080fd5b81356020610784610580836104e6565b82815260069290921b840181019181810190868411156107a357600080fd5b8286015b848110156105f157604081890312156107c05760008081fd5b6107c8610405565b8135815284820135858201528352918301916040016107a7565b600060208083850312156107f557600080fd5b82356001600160401b038082111561080c57600080fd5b908401906060828703121561082057600080fd5b61082861044f565b82358281111561083757600080fd5b8301604081890381131561084a57600080fd5b610852610405565b82358581111561086157600080fd5b8301601f81018b1361087257600080fd5b8035610880610580826104e6565b81815260069190911b8201890190898101908d83111561089f57600080fd5b928a01925b828410156108ef5785848f0312156108bc5760008081fd5b6108c4610405565b84356108cf81610509565b81526108dc858d01610531565b818d0152825292850192908a01906108a4565b84525050508287013591508482111561090757600080fd5b6109138a83850161055f565b8188015283525050828401358281111561092c57600080fd5b6109388882860161066b565b8583015250604083013593508184111561095157600080fd5b61095d87858501610763565b60408201529695505050505050565b600080600080600060a0868803121561098457600080fd5b61098d86610548565b945061099b60208701610548565b9350604086013592506060860135600481106109b657600080fd5b915060808601356001600160401b038111156109d157600080fd5b6109dd888289016105fc565b9150509295509295909350565b600060a082840312156109fc57600080fd5b610a0461042d565b905081358152610a1660208301610548565b6020820152610a2760408301610548565b6040820152610a3860608301610548565b6060820152610a4960808301610548565b608082015292915050565b600082601f830112610a6557600080fd5b81356020610a75610580836104e6565b82815260059290921b84018101918181019086841115610a9457600080fd5b8286015b848110156105f15780356001600160401b0380821115610ab85760008081fd5b9088019060a0828b03601f1901811315610ad25760008081fd5b610ada61042d565b8784013583811115610aec5760008081fd5b610afa8d8a838801016105fc565b82525060408085013584811115610b115760008081fd5b610b1f8e8b838901016105fc565b8a8401525060608086013585811115610b385760008081fd5b610b468f8c838a01016105fc565b83850152506080915081860135818401525082850135925083831115610b6c5760008081fd5b610b7a8d8a858801016105fc565b908201528652505050918301918301610a98565b60008060408385031215610ba157600080fd5b610baa83610548565b915060208301356001600160401b0380821115610bc657600080fd5b908401906101808287031215610bdb57600080fd5b610be3610471565b610bed87846109ea565b8152610bfb60a08401610521565b602082015260c083013582811115610c1257600080fd5b610c1e888286016105fc565b60408301525060e083013582811115610c3657600080fd5b610c42888286016105fc565b60608301525061010083013582811115610c5b57600080fd5b610c67888286016105fc565b608083015250610c7a6101208401610521565b60a082015261014083013560c082015261016083013582811115610c9d57600080fd5b610ca988828601610a54565b60e0830152508093505050509250929050565b600060208284031215610cce57600080fd5b610cd782610548565b9392505050565b60008060408385031215610cf157600080fd5b610cfa83610548565b9150610d0860208401610548565b90509250929050565b60008060408385031215610d2457600080fd5b610d2d83610548565b915060208301356001600160401b0380821115610d4957600080fd5b9084019060808287031215610d5d57600080fd5b610d65610494565b8235610d7081610509565b815260208301358015158114610d8557600080fd5b6020820152610d9660408401610548565b6040820152606083013582811115610dad57600080fd5b610db9888286016105fc565b6060830152508093505050509250929050565b6000815180845260005b81811015610df257602081850181015186830182015201610dd6565b506000602082860101526020601f19601f83011685010191505092915050565b602080825282516001600160a01b03168282015282015115156040808301919091528201516001600160401b0316606080830191909152820151608080830152600090610e6260a0840182610dcc565b949350505050565b6001600160a01b03169052565b60008151808452602080850194506020840160005b83811015610ec557815180516001600160401b031688528301516001600160e01b03168388015260409096019590820190600101610e8c565b509495945050505050565b600082825180855260208086019550808260051b84010181860160005b84811015610f5f57858303601f19018952815180516001600160401b03908116855285820151811686860152604080830151909116908501526060808201519085015260809081015160a091850182905290610f4b81860183610dcc565b9a86019a9450505090830190600101610eed565b5090979650505050505050565b60008151808452602080850194506020840160005b83811015610ec5578151805188528301518388015260409096019590820190600101610f81565b602080825282516060838301528051604060808501819052815160c086018190526000949392840191859160e08801905b8084101561101457845180516001600160a01b031683528701516001600160e01b031687830152938601936001939093019290820190610fd9565b5093850151878503607f190160a0890152936110308186610e77565b945050505050818501519150601f19808583030160408601526110538284610ed0565b92506040860151915080858403016060860152506110718282610f6c565b95945050505050565b60006004841061109a57634e487b7160e01b600052602160045260246000fd5b83825260406020830152610e626040830184610dcc565b600082825180855260208086019550808260051b84010181860160005b84811015610f5f57601f19868403018952815160a081518186526110f482870182610dcc565b915050858201518582038787015261110c8282610dcc565b915050604080830151868303828801526111268382610dcc565b9250505060608083015181870152506080808301519250858203818701525061114f8183610dcc565b9a86019a94505050908301906001016110ce565b602081526111b0602082018351805182526020808201516001600160401b039081169184019190915260408083015182169084015260608083015182169084015260809182015116910152565b600060208301516111c460c0840182610e6a565b5060408301516101808060e08501526111e16101a0850183610dcc565b91506060850151601f1980868503016101008701526112008483610dcc565b935060808701519150808685030161012087015261121e8483610dcc565b935060a08701519150611235610140870183610e6a565b60c087015161016087015260e087015191508086850301838701525061125b83826110b1565b9695505050505050565b6001600160401b0381811683821601908082111561129357634e487b7160e01b600052601160045260246000fd5b5092915050565b600181811c908216806112ae57607f821691505b6020821081036112ce57634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115611320576000816000526020600020601f850160051c810160208610156112fd5750805b601f850160051c820191505b8181101561131c57828155600101611309565b5050505b505050565b81516001600160401b0381111561133e5761133e6103ef565b6113528161134c845461129a565b846112d4565b602080601f831160018114611387576000841561136f5750858301515b600019600386901b1c1916600185901b17855561131c565b600085815260208120601f198616915b828110156113b657888601518255948401946001909101908401611397565b50858210156113d45787850151600019600388901b60f8161c191681555b5050505050600190811b0190555056fea164736f6c6343000818000a", + ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"CCIPSendRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"structIRMNV2.Signature[]\",\"name\":\"rmnSignatures\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"report\",\"type\":\"tuple\"}],\"name\":\"CommitReportAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"name\":\"ExecutionStateChanged\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"emitCCIPSendRequested\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"structIRMNV2.Signature[]\",\"name\":\"rmnSignatures\",\"type\":\"tuple[]\"}],\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"report\",\"type\":\"tuple\"}],\"name\":\"emitCommitReportAccepted\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"name\":\"emitExecutionStateChanged\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getExpectedNextSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"getSourceChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"setDestChainSeqNr\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"sourceChainConfig\",\"type\":\"tuple\"}],\"name\":\"setSourceChainConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x608060405234801561001057600080fd5b506113f4806100206000396000f3fe608060405234801561001057600080fd5b506004361061006d5760003560e01c80634cf66e361461007257806385096da9146100875780639041be3d1461009a578063bfc9b789146100ca578063c1a5a355146100dd578063e83eabba14610119578063e9d68a8e1461012c575b600080fd5b610085610080366004610571565b61014c565b005b6100856100953660046107e9565b6101a1565b6100ad6100a8366004610917565b6101e6565b6040516001600160401b0390911681526020015b60405180910390f35b6100856100d8366004610b51565b610215565b6100856100eb366004610cdb565b6001600160401b03918216600090815260016020526040902080546001600160401b03191691909216179055565b610085610127366004610d0e565b61024f565b61013f61013a366004610917565b6102db565b6040516100c19190610e0f565b82846001600160401b0316866001600160401b03167f8c324ce1367b83031769f6a813e3bb4c117aba2185789d66b98b791405be6df28585604051610192929190610e67565b60405180910390a45050505050565b816001600160401b03167fcae3d9f68a9ed33d0a770e9bcc6fc25d4041dd6391e6cd8015546547a3c93140826040516101da9190610f6a565b60405180910390a25050565b6001600160401b038082166000908152600160208190526040822054919261020f92169061106c565b92915050565b7f23bc80217a08968cec0790cd045b396fa7eea0a21af469e603329940b883d86d8160405161024491906111cb565b60405180910390a150565b6001600160401b0380831660009081526020818152604091829020845181549286015193860151909416600160a81b02600160a81b600160e81b0319931515600160a01b026001600160a81b03199093166001600160a01b03909516949094179190911791909116919091178155606082015182919060018201906102d49082611328565b5050505050565b60408051608080820183526000808352602080840182905283850182905260608085018190526001600160401b038781168452838352928690208651948501875280546001600160a01b0381168652600160a01b810460ff16151593860193909352600160a81b9092049092169483019490945260018401805493949293918401916103669061129d565b80601f01602080910402602001604051908101604052809291908181526020018280546103929061129d565b80156103df5780601f106103b4576101008083540402835291602001916103df565b820191906000526020600020905b8154815290600101906020018083116103c257829003601f168201915b5050505050815250509050919050565b80356001600160401b038116811461040657600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60405160a081016001600160401b03811182821017156104435761044361040b565b60405290565b60405161010081016001600160401b03811182821017156104435761044361040b565b604080519081016001600160401b03811182821017156104435761044361040b565b604051606081016001600160401b03811182821017156104435761044361040b565b604051608081016001600160401b03811182821017156104435761044361040b565b604051601f8201601f191681016001600160401b03811182821017156104fa576104fa61040b565b604052919050565b600082601f83011261051357600080fd5b81356001600160401b0381111561052c5761052c61040b565b61053f601f8201601f19166020016104d2565b81815284602083860101111561055457600080fd5b816020850160208301376000918101602001919091529392505050565b600080600080600060a0868803121561058957600080fd5b610592866103ef565b94506105a0602087016103ef565b9350604086013592506060860135600481106105bb57600080fd5b915060808601356001600160401b038111156105d657600080fd5b6105e288828901610502565b9150509295509295909350565b600060a0828403121561060157600080fd5b610609610421565b90508135815261061b602083016103ef565b602082015261062c604083016103ef565b604082015261063d606083016103ef565b606082015261064e608083016103ef565b608082015292915050565b6001600160a01b038116811461066e57600080fd5b50565b803561040681610659565b60006001600160401b038211156106955761069561040b565b5060051b60200190565b600082601f8301126106b057600080fd5b813560206106c56106c08361067c565b6104d2565b82815260059290921b840181019181810190868411156106e457600080fd5b8286015b848110156107de5780356001600160401b03808211156107085760008081fd5b9088019060a0828b03601f19018113156107225760008081fd5b61072a610421565b878401358381111561073c5760008081fd5b61074a8d8a83880101610502565b825250604080850135848111156107615760008081fd5b61076f8e8b83890101610502565b8a84015250606080860135858111156107885760008081fd5b6107968f8c838a0101610502565b838501525060809150818601358184015250828501359250838311156107bc5760008081fd5b6107ca8d8a85880101610502565b9082015286525050509183019183016106e8565b509695505050505050565b600080604083850312156107fc57600080fd5b610805836103ef565b915060208301356001600160401b038082111561082157600080fd5b90840190610180828703121561083657600080fd5b61083e610449565b61084887846105ef565b815261085660a08401610671565b602082015260c08301358281111561086d57600080fd5b61087988828601610502565b60408301525060e08301358281111561089157600080fd5b61089d88828601610502565b606083015250610100830135828111156108b657600080fd5b6108c288828601610502565b6080830152506108d56101208401610671565b60a082015261014083013560c0820152610160830135828111156108f857600080fd5b6109048882860161069f565b60e0830152508093505050509250929050565b60006020828403121561092957600080fd5b610932826103ef565b9392505050565b80356001600160e01b038116811461040657600080fd5b600082601f83011261096157600080fd5b813560206109716106c08361067c565b82815260069290921b8401810191818101908684111561099057600080fd5b8286015b848110156107de57604081890312156109ad5760008081fd5b6109b561046c565b6109be826103ef565b81526109cb858301610939565b81860152835291830191604001610994565b600082601f8301126109ee57600080fd5b813560206109fe6106c08361067c565b82815260059290921b84018101918181019086841115610a1d57600080fd5b8286015b848110156107de5780356001600160401b0380821115610a415760008081fd5b9088019060a0828b03601f1901811315610a5b5760008081fd5b610a63610421565b610a6e8885016103ef565b815260408085013584811115610a845760008081fd5b610a928e8b83890101610502565b8a8401525060609350610aa68486016103ef565b908201526080610ab78582016103ef565b93820193909352920135908201528352918301918301610a21565b600082601f830112610ae357600080fd5b81356020610af36106c08361067c565b82815260069290921b84018101918181019086841115610b1257600080fd5b8286015b848110156107de5760408189031215610b2f5760008081fd5b610b3761046c565b813581528482013585820152835291830191604001610b16565b60006020808385031215610b6457600080fd5b82356001600160401b0380821115610b7b57600080fd5b9084019060608287031215610b8f57600080fd5b610b9761048e565b823582811115610ba657600080fd5b83016040818903811315610bb957600080fd5b610bc161046c565b823585811115610bd057600080fd5b8301601f81018b13610be157600080fd5b8035610bef6106c08261067c565b81815260069190911b8201890190898101908d831115610c0e57600080fd5b928a01925b82841015610c5e5785848f031215610c2b5760008081fd5b610c3361046c565b8435610c3e81610659565b8152610c4b858d01610939565b818d0152825292850192908a0190610c13565b845250505082870135915084821115610c7657600080fd5b610c828a838501610950565b81880152835250508284013582811115610c9b57600080fd5b610ca7888286016109dd565b85830152506040830135935081841115610cc057600080fd5b610ccc87858501610ad2565b60408201529695505050505050565b60008060408385031215610cee57600080fd5b610cf7836103ef565b9150610d05602084016103ef565b90509250929050565b60008060408385031215610d2157600080fd5b610d2a836103ef565b915060208301356001600160401b0380821115610d4657600080fd5b9084019060808287031215610d5a57600080fd5b610d626104b0565b8235610d6d81610659565b815260208301358015158114610d8257600080fd5b6020820152610d93604084016103ef565b6040820152606083013582811115610daa57600080fd5b610db688828601610502565b6060830152508093505050509250929050565b6000815180845260005b81811015610def57602081850181015186830182015201610dd3565b506000602082860101526020601f19601f83011685010191505092915050565b602080825282516001600160a01b03168282015282015115156040808301919091528201516001600160401b0316606080830191909152820151608080830152600090610e5f60a0840182610dc9565b949350505050565b600060048410610e8757634e487b7160e01b600052602160045260246000fd5b83825260406020830152610e5f6040830184610dc9565b6001600160a01b03169052565b600082825180855260208086019550808260051b84010181860160005b84811015610f5d57601f19868403018952815160a08151818652610eee82870182610dc9565b9150508582015185820387870152610f068282610dc9565b91505060408083015186830382880152610f208382610dc9565b92505050606080830151818701525060808083015192508582038187015250610f498183610dc9565b9a86019a9450505090830190600101610ec8565b5090979650505050505050565b60208152610fb7602082018351805182526020808201516001600160401b039081169184019190915260408083015182169084015260608083015182169084015260809182015116910152565b60006020830151610fcb60c0840182610e9e565b5060408301516101808060e0850152610fe86101a0850183610dc9565b91506060850151601f1980868503016101008701526110078483610dc9565b93506080870151915080868503016101208701526110258483610dc9565b935060a0870151915061103c610140870183610e9e565b60c087015161016087015260e08701519150808685030183870152506110628382610eab565b9695505050505050565b6001600160401b0381811683821601908082111561109a57634e487b7160e01b600052601160045260246000fd5b5092915050565b60008151808452602080850194506020840160005b838110156110ef57815180516001600160401b031688528301516001600160e01b031683880152604090960195908201906001016110b6565b509495945050505050565b600082825180855260208086019550808260051b84010181860160005b84811015610f5d57858303601f19018952815180516001600160401b0390811685528582015160a0878701819052919061115383880182610dc9565b60408581015184169089015260608086015190931692880192909252506080928301519290950191909152509783019790830190600101611117565b60008151808452602080850194506020840160005b838110156110ef5781518051885283015183880152604090960195908201906001016111a4565b602080825282516060838301528051604060808501819052815160c086018190526000949392840191859160e08801905b8084101561123757845180516001600160a01b031683528701516001600160e01b0316878301529386019360019390930192908201906111fc565b5093850151878503607f190160a08901529361125381866110a1565b945050505050818501519150601f198085830301604086015261127682846110fa565b9250604086015191508085840301606086015250611294828261118f565b95945050505050565b600181811c908216806112b157607f821691505b6020821081036112d157634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115611323576000816000526020600020601f850160051c810160208610156113005750805b601f850160051c820191505b8181101561131f5782815560010161130c565b5050505b505050565b81516001600160401b038111156113415761134161040b565b6113558161134f845461129d565b846112d7565b602080601f83116001811461138a57600084156113725750858301515b600019600386901b1c1916600185901b17855561131f565b600085815260208120601f198616915b828110156113b95788860151825594840194600190910190840161139a565b50858210156113d75787850151600019600388901b60f8161c191681555b5050505050600190811b0190555056fea164736f6c6343000818000a", } var CCIPReaderTesterABI = CCIPReaderTesterMetaData.ABI @@ -754,7 +754,7 @@ func (CCIPReaderTesterCCIPSendRequested) Topic() common.Hash { } func (CCIPReaderTesterCommitReportAccepted) Topic() common.Hash { - return common.HexToHash("0xd7868a16facbdde7b5c020620136316b3c266fffcb4e1e41cb6a662fe14ba3e1") + return common.HexToHash("0x23bc80217a08968cec0790cd045b396fa7eea0a21af469e603329940b883d86d") } func (CCIPReaderTesterExecutionStateChanged) Topic() common.Hash { diff --git a/core/gethwrappers/ccip/generated/offramp/offramp.go b/core/gethwrappers/ccip/generated/offramp/offramp.go index f7de788882..60c42366cb 100644 --- a/core/gethwrappers/ccip/generated/offramp/offramp.go +++ b/core/gethwrappers/ccip/generated/offramp/offramp.go @@ -72,10 +72,10 @@ type InternalGasPriceUpdate struct { type InternalMerkleRoot struct { SourceChainSelector uint64 + OnRampAddress []byte MinSeqNr uint64 MaxSeqNr uint64 MerkleRoot [32]byte - OnRampAddress []byte } type InternalPriceUpdates struct { @@ -162,8 +162,8 @@ type OffRampStaticConfig struct { } var OffRampMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CanOnlySelfCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"actual\",\"type\":\"bytes32\"}],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ExecutionError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"ForkedChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enumMultiOCR3Base.InvalidConfigErrorType\",\"name\":\"errorType\",\"type\":\"uint8\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"got\",\"type\":\"uint256\"}],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidEVMAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"name\":\"InvalidInterval\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"newLimit\",\"type\":\"uint256\"}],\"name\":\"InvalidManualExecutionGasLimit\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"messageDestChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidMessageDestChainSelector\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"newState\",\"type\":\"uint8\"}],\"name\":\"InvalidNewState\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRoot\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidStaticConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LeavesCannotBeEmpty\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ManualExecutionGasLimitMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"ManualExecutionNotYetEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"errorReason\",\"type\":\"bytes\"}],\"name\":\"MessageValidationError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonUniqueSignatures\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"notPool\",\"type\":\"address\"}],\"name\":\"NotACompatiblePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OracleCannotBeZeroAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ReceiverError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountReleased\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePre\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePost\",\"type\":\"uint256\"}],\"name\":\"ReleaseOrMintBalanceMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"name\":\"RootAlreadyCommitted\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"RootNotCommitted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignatureVerificationDisabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignaturesOutOfRegistration\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"reportSourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"messageSourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainSelectorMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"StaleCommitReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"StaticConfigCannotBeChanged\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"TokenDataMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"TokenHandlingError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnexpectedTokenData\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"WrongMessageLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WrongNumberOfSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroChainSelectorNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"AlreadyAttempted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"structIRMNV2.Signature[]\",\"name\":\"rmnSignatures\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"report\",\"type\":\"tuple\"}],\"name\":\"CommitReportAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"DynamicConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"messageHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"name\":\"ExecutionStateChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"RootRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"SkippedAlreadyExecutedMessage\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SkippedReportExecution\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"sourceConfig\",\"type\":\"tuple\"}],\"name\":\"SourceChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainSelectorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"}],\"name\":\"StaticConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigUpdates\",\"type\":\"tuple[]\"}],\"name\":\"applySourceChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"destTokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structClient.Any2EVMMessage\",\"name\":\"\",\"type\":\"tuple\"}],\"name\":\"ccipReceive\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"rawVs\",\"type\":\"bytes32\"}],\"name\":\"commit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"execute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"bytes[]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[]\"}],\"name\":\"executeSingleMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"getExecutionState\",\"outputs\":[{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLatestPriceSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"getMerkleRoot\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"getSourceChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"latestConfigDetails\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"n\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"}],\"internalType\":\"structMultiOCR3Base.ConfigInfo\",\"name\":\"configInfo\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfig\",\"name\":\"ocrConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage[]\",\"name\":\"messages\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[][]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[][]\"},{\"internalType\":\"bytes32[]\",\"name\":\"proofs\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"proofFlagBits\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.ExecutionReportSingleChain[]\",\"name\":\"reports\",\"type\":\"tuple[]\"},{\"internalType\":\"uint256[][]\",\"name\":\"gasLimitOverrides\",\"type\":\"uint256[][]\"}],\"name\":\"manuallyExecute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"setDynamicConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfigArgs[]\",\"name\":\"ocrConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"setOCR3Configs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x6101206040523480156200001257600080fd5b5060405162006ccd38038062006ccd8339810160408190526200003591620008c7565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf81620001fa565b5050466080525060208301516001600160a01b03161580620000ec575060408301516001600160a01b0316155b8062000103575060608301516001600160a01b0316155b1562000122576040516342bcdf7f60e11b815260040160405180910390fd5b82516001600160401b03166000036200014e5760405163c656089560e01b815260040160405180910390fd5b82516001600160401b0390811660a052602080850180516001600160a01b0390811660c05260408088018051831660e0526060808a01805185166101005283518b519098168852945184169587019590955251821690850152905116908201527f683eb52ee924eb817377cfa8f41f238f4bb7a877da5267869dfffbad85f564d89060800160405180910390a1620001e682620002a5565b620001f181620003c1565b50505062000c67565b336001600160a01b03821603620002545760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b0316620002ce576040516342bcdf7f60e11b815260040160405180910390fd5b80516004805460208085018051604080880180516060808b0180516001600160a01b039b8c166001600160c01b0319909a168a17600160a01b63ffffffff98891602176001600160c01b0316600160c01b948816949094026001600160e01b031693909317600160e01b93871693909302929092179098556080808b018051600580546001600160a01b031916918d169190911790558451988952955185169688019690965290518316918601919091525116938301939093529151909216908201527fa55bd56595c45f517e5967a3067f3dca684445a3080e7c04a4e0d5a40cda627d9060a00160405180910390a150565b60005b815181101562000666576000828281518110620003e557620003e562000a1d565b60200260200101519050600081602001519050806001600160401b0316600003620004235760405163c656089560e01b815260040160405180910390fd5b81516001600160a01b03166200044c576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160401b0381166000908152600660205260408120600181018054919291620004789062000a33565b80601f0160208091040260200160405190810160405280929190818152602001828054620004a69062000a33565b8015620004f75780601f10620004cb57610100808354040283529160200191620004f7565b820191906000526020600020905b815481529060010190602001808311620004d957829003601f168201915b5050505050905060008460600151905081516000036200059e57805160000362000534576040516342bcdf7f60e11b815260040160405180910390fd5b6001830162000544828262000ac4565b508254600160a81b600160e81b031916600160a81b1783556040516001600160401b03851681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1620005d9565b8080519060200120828051906020012014620005d95760405163c39a620560e01b81526001600160401b038516600482015260240162000083565b604080860151845487516001600160a01b03166001600160a01b0319921515600160a01b02929092166001600160a81b031990911617178455516001600160401b038516907f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b906200064d90869062000b90565b60405180910390a25050505050806001019050620003c4565b5050565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b0381118282101715620006a557620006a56200066a565b60405290565b604051601f8201601f191681016001600160401b0381118282101715620006d657620006d66200066a565b604052919050565b80516001600160401b0381168114620006f657600080fd5b919050565b6001600160a01b03811681146200071157600080fd5b50565b805163ffffffff81168114620006f657600080fd5b6000601f83601f8401126200073d57600080fd5b825160206001600160401b03808311156200075c576200075c6200066a565b8260051b6200076d838201620006ab565b93845286810183019383810190898611156200078857600080fd5b84890192505b85831015620008ba57825184811115620007a85760008081fd5b89016080601f19828d038101821315620007c25760008081fd5b620007cc62000680565b88840151620007db81620006fb565b81526040620007ec858201620006de565b8a8301526060808601518015158114620008065760008081fd5b838301529385015193898511156200081e5760008081fd5b84860195508f603f8701126200083657600094508485fd5b8a8601519450898511156200084f576200084f6200066a565b620008608b858f88011601620006ab565b93508484528f82868801011115620008785760008081fd5b60005b8581101562000898578681018301518582018d01528b016200087b565b5060009484018b0194909452509182015283525091840191908401906200078e565b9998505050505050505050565b6000806000838503610140811215620008df57600080fd5b6080811215620008ee57600080fd5b620008f862000680565b6200090386620006de565b815260208601516200091581620006fb565b602082015260408601516200092a81620006fb565b604082015260608601516200093f81620006fb565b6060820152935060a0607f19820112156200095957600080fd5b5060405160a081016001600160401b0380821183831017156200098057620009806200066a565b81604052608087015191506200099682620006fb565b818352620009a760a0880162000714565b6020840152620009ba60c0880162000714565b6040840152620009cd60e0880162000714565b60608401526101008701519150620009e582620006fb565b608083018290526101208701519294508083111562000a0357600080fd5b505062000a138682870162000729565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b600181811c9082168062000a4857607f821691505b60208210810362000a6957634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111562000abf576000816000526020600020601f850160051c8101602086101562000a9a5750805b601f850160051c820191505b8181101562000abb5782815560010162000aa6565b5050505b505050565b81516001600160401b0381111562000ae05762000ae06200066a565b62000af88162000af1845462000a33565b8462000a6f565b602080601f83116001811462000b30576000841562000b175750858301515b600019600386901b1c1916600185901b17855562000abb565b600085815260208120601f198616915b8281101562000b615788860151825594840194600190910190840162000b40565b508582101562000b805787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b602080825282546001600160a01b0381168383015260a081901c60ff161515604084015260a81c6001600160401b0316606083015260808083015260018084018054600093929190849062000be58162000a33565b8060a089015260c0600183166000811462000c09576001811462000c265762000c58565b60ff19841660c08b015260c083151560051b8b0101945062000c58565b85600052602060002060005b8481101562000c4f5781548c820185015290880190890162000c32565b8b0160c0019550505b50929998505050505050505050565b60805160a05160c05160e05161010051615ff062000cdd600039600081816102400152612a6d0152600081816102110152612f610152600081816101e20152818161077f0152818161098601526123ef0152600081816101b2015261267c0152600081816117dd01526118290152615ff06000f3fe608060405234801561001057600080fd5b50600436106101515760003560e01c806379ba5097116100cd578063c673e58411610081578063e9d68a8e11610066578063e9d68a8e1461052a578063f2fde38b1461054a578063f716f99f1461055d57600080fd5b8063c673e584146104c5578063ccd37ba3146104e557600080fd5b80638da5cb5b116100b25780638da5cb5b14610484578063991a50181461049f578063a80036b4146104b257600080fd5b806379ba50971461046e57806385572ffb1461047657600080fd5b80632d04ab76116101245780633f4b04aa116101095780633f4b04aa146103365780635e36480c146103525780637437ff9f1461037257600080fd5b80632d04ab7614610310578063311cd5131461032357600080fd5b806304666f9c1461015657806305d938b51461016b57806306285c691461017e578063181f5a77146102c7575b600080fd5b61016961016436600461412d565b610570565b005b6101696101793660046147b7565b610584565b61027060408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316815250905090565b6040516102be9190815167ffffffffffffffff1681526020808301516001600160a01b0390811691830191909152604080840151821690830152606092830151169181019190915260800190565b60405180910390f35b6103036040518060400160405280601181526020017f4f666652616d7020312e362e302d64657600000000000000000000000000000081525081565b6040516102be9190614932565b61016961031e3660046149dd565b610729565b610169610331366004614a90565b610cc1565b60095460405167ffffffffffffffff90911681526020016102be565b610365610360366004614ae4565b610d2a565b6040516102be9190614b41565b6104116040805160a081018252600080825260208201819052918101829052606081018290526080810191909152506040805160a0810182526004546001600160a01b03808216835263ffffffff600160a01b83048116602085015278010000000000000000000000000000000000000000000000008304811694840194909452600160e01b9091049092166060820152600554909116608082015290565b6040516102be9190600060a0820190506001600160a01b03808451168352602084015163ffffffff808216602086015280604087015116604086015280606087015116606086015250508060808501511660808401525092915050565b610169610d80565b610169610151366004614b4f565b6000546040516001600160a01b0390911681526020016102be565b6101696104ad366004614b9e565b610e3e565b6101696104c0366004614c12565b610e4f565b6104d86104d3366004614c7f565b6111c2565b6040516102be9190614cdf565b61051c6104f3366004614d54565b67ffffffffffffffff919091166000908152600860209081526040808320938352929052205490565b6040519081526020016102be565b61053d610538366004614d7e565b611320565b6040516102be9190614d99565b610169610558366004614de7565b61142d565b61016961056b366004614e6c565b61143e565b610578611480565b610581816114dc565b50565b61058c6117da565b8151815181146105c8576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b818110156107195760008482815181106105e7576105e7614faa565b6020026020010151905060008160200151519050600085848151811061060f5761060f614faa565b6020026020010151905080518214610653576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8281101561070a57600082828151811061067257610672614faa565b6020026020010151905080600014610701578460200151828151811061069a5761069a614faa565b6020026020010151608001518110156107015784516040517fc8e9605100000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260248101839052604481018290526064015b60405180910390fd5b50600101610656565b505050508060010190506105cb565b50610724838361185b565b505050565b6000610737878901896151dc565b602081015151909150156107e357602081015160408083015190517f30dfc3080000000000000000000000000000000000000000000000000000000081526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016926330dfc308926107b292600401615440565b60006040518083038186803b1580156107ca57600080fd5b505afa1580156107de573d6000803e3d6000fd5b505050505b805151511515806107f957508051602001515115155b156108f95760095460208a01359067ffffffffffffffff808316911610156108b8576009805467ffffffffffffffff191667ffffffffffffffff83161790556004805483516040517f3937306f0000000000000000000000000000000000000000000000000000000081526001600160a01b0390921692633937306f92610881929101615522565b600060405180830381600087803b15801561089b57600080fd5b505af11580156108af573d6000803e3d6000fd5b505050506108f7565b8160200151516000036108f7576040517f2261116700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b60005b816020015151811015610c0a5760008260200151828151811061092157610921614faa565b602090810291909101015180516040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815277ffffffffffffffff00000000000000000000000000000000608083901b166004820152919250906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632cbc26bb90602401602060405180830381865afa1580156109cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109f19190615535565b15610a34576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff821660048201526024016106f8565b6000610a3f8261190b565b6020840151815491925067ffffffffffffffff908116600160a81b90920416141580610a865750826040015167ffffffffffffffff16836020015167ffffffffffffffff16115b15610ae7578251602084015160408086015190517fd5e0f0d600000000000000000000000000000000000000000000000000000000815267ffffffffffffffff938416600482015291831660248301529190911660448201526064016106f8565b606083015180610b23576040517f504570e300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b835167ffffffffffffffff16600090815260086020908152604080832084845290915290205415610b965783516040517f32cf0cbf00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602481018290526044016106f8565b6040840151610ba6906001615568565b82547fffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffff16600160a81b67ffffffffffffffff9283160217909255925116600090815260086020908152604080832094835293905291909120429055506001016108fc565b507fd7868a16facbdde7b5c020620136316b3c266fffcb4e1e41cb6a662fe14ba3e181604051610c3a9190615590565b60405180910390a1610cb660008a8a8a8a8a8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808e0282810182019093528d82529093508d92508c9182918501908490808284376000920191909152508b9250611972915050565b505050505050505050565b610d01610cd0828401846155e8565b6040805160008082526020820190925290610cfb565b6060815260200190600190039081610ce65790505b5061185b565b604080516000808252602082019092529050610d24600185858585866000611972565b50505050565b6000610d386001600461561d565b6002610d45608085615646565b67ffffffffffffffff16610d59919061566d565b610d638585611ce9565b901c166003811115610d7757610d77614b17565b90505b92915050565b6001546001600160a01b03163314610dda5760405162461bcd60e51b815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064016106f8565b600080543373ffffffffffffffffffffffffffffffffffffffff19808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610e46611480565b61058181611d30565b333014610e88576040517f371a732800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160008082526020820190925281610ec5565b6040805180820190915260008082526020820152815260200190600190039081610e9e5790505b5060a08501515190915015610ef957610ef68460a00151856020015186606001518760000151602001518787611e96565b90505b6040805160a0810182528551518152855160209081015167ffffffffffffffff1681830152808701518351600094840192610f35929101614932565b60408051601f19818403018152918152908252878101516020830152018390526005549091506001600160a01b03168015611042576040517f08d450a10000000000000000000000000000000000000000000000000000000081526001600160a01b038216906308d450a190610faf908590600401615726565b600060405180830381600087803b158015610fc957600080fd5b505af1925050508015610fda575060015b611042573d808015611008576040519150601f19603f3d011682016040523d82523d6000602084013e61100d565b606091505b50806040517f09c253250000000000000000000000000000000000000000000000000000000081526004016106f89190614932565b60408601515115801561105757506080860151155b8061106e575060608601516001600160a01b03163b155b806110ae575060608601516110ac906001600160a01b03167f85572ffb00000000000000000000000000000000000000000000000000000000611fb5565b155b156110bb57505050505050565b855160209081015167ffffffffffffffff1660009081526006909152604080822054608089015160608a015192517f3cf9798300000000000000000000000000000000000000000000000000000000815284936001600160a01b0390931692633cf97983926111339289926113889291600401615739565b6000604051808303816000875af1158015611152573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261117a9190810190615775565b5091509150816111b857806040517f0a8d6e8c0000000000000000000000000000000000000000000000000000000081526004016106f89190614932565b5050505050505050565b6112056040805160e081019091526000606082018181526080830182905260a0830182905260c08301919091528190815260200160608152602001606081525090565b60ff808316600090815260026020818152604092839020835160e081018552815460608201908152600183015480881660808401526101008104881660a0840152620100009004909616151560c0820152948552918201805484518184028101840190955280855292938583019390928301828280156112ae57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611290575b505050505081526020016003820180548060200260200160405190810160405280929190818152602001828054801561131057602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116112f2575b5050505050815250509050919050565b604080516080808201835260008083526020808401829052838501829052606080850181905267ffffffffffffffff878116845260068352928690208651948501875280546001600160a01b0381168652600160a01b810460ff16151593860193909352600160a81b9092049092169483019490945260018401805493949293918401916113ad9061580b565b80601f01602080910402602001604051908101604052809291908181526020018280546113d99061580b565b80156113105780601f106113fb57610100808354040283529160200191611310565b820191906000526020600020905b81548152906001019060200180831161140957505050919092525091949350505050565b611435611480565b61058181611fd1565b611446611480565b60005b815181101561147c5761147482828151811061146757611467614faa565b6020026020010151612087565b600101611449565b5050565b6000546001600160a01b031633146114da5760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016106f8565b565b60005b815181101561147c5760008282815181106114fc576114fc614faa565b602002602001015190506000816020015190508067ffffffffffffffff16600003611553576040517fc656089500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81516001600160a01b031661157b576040516342bcdf7f60e11b815260040160405180910390fd5b67ffffffffffffffff811660009081526006602052604081206001810180549192916115a69061580b565b80601f01602080910402602001604051908101604052809291908181526020018280546115d29061580b565b801561161f5780601f106115f45761010080835404028352916020019161161f565b820191906000526020600020905b81548152906001019060200180831161160257829003601f168201915b5050505050905060008460600151905081516000036116d757805160000361165a576040516342bcdf7f60e11b815260040160405180910390fd5b600183016116688282615895565b5082547fffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffff16600160a81b17835560405167ffffffffffffffff851681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a161172a565b808051906020012082805190602001201461172a576040517fc39a620500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff851660048201526024016106f8565b604080860151845487516001600160a01b031673ffffffffffffffffffffffffffffffffffffffff19921515600160a01b02929092167fffffffffffffffffffffff000000000000000000000000000000000000000000909116171784555167ffffffffffffffff8516907f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b906117c2908690615955565b60405180910390a250505050508060010190506114df565b467f0000000000000000000000000000000000000000000000000000000000000000146114da576040517f0f01ce850000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060048201524660248201526044016106f8565b8151600003611895576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160408051600080825260208201909252911591905b8451811015611904576118fc8582815181106118ca576118ca614faa565b6020026020010151846118f6578583815181106118e9576118e9614faa565b602002602001015161239b565b8361239b565b6001016118ac565b5050505050565b67ffffffffffffffff811660009081526006602052604081208054600160a01b900460ff16610d7a576040517fed053c5900000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024016106f8565b60ff878116600090815260026020908152604080832081516080810183528154815260019091015480861693820193909352610100830485169181019190915262010000909104909216151560608301528735906119d18760a4615a23565b9050826060015115611a195784516119ea90602061566d565b86516119f790602061566d565b611a029060a0615a23565b611a0c9190615a23565b611a169082615a23565b90505b368114611a5b576040517f8e1192e1000000000000000000000000000000000000000000000000000000008152600481018290523660248201526044016106f8565b5081518114611aa35781516040517f93df584c0000000000000000000000000000000000000000000000000000000081526004810191909152602481018290526044016106f8565b611aab6117da565b60ff808a1660009081526003602090815260408083203384528252808320815180830190925280548086168352939491939092840191610100909104166002811115611af957611af9614b17565b6002811115611b0a57611b0a614b17565b9052509050600281602001516002811115611b2757611b27614b17565b148015611b7b5750600260008b60ff1660ff168152602001908152602001600020600301816000015160ff1681548110611b6357611b63614faa565b6000918252602090912001546001600160a01b031633145b611bb1576040517fda0f08e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50816060015115611c93576020820151611bcc906001615a36565b60ff16855114611c08576040517f71253a2500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8351855114611c43576040517fa75d88af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008787604051611c55929190615a4f565b604051908190038120611c6c918b90602001615a5f565b604051602081830303815290604052805190602001209050611c918a82888888612d1b565b505b6040805182815260208a81013567ffffffffffffffff169082015260ff8b16917f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef0910160405180910390a2505050505050505050565b67ffffffffffffffff8216600090815260076020526040812081611d0e608085615a73565b67ffffffffffffffff1681526020810191909152604001600020549392505050565b80516001600160a01b0316611d58576040516342bcdf7f60e11b815260040160405180910390fd5b80516004805460208085018051604080880180516060808b0180516001600160a01b039b8c167fffffffffffffffff000000000000000000000000000000000000000000000000909a168a17600160a01b63ffffffff988916021777ffffffffffffffffffffffffffffffffffffffffffffffff167801000000000000000000000000000000000000000000000000948816949094026001600160e01b031693909317600160e01b93871693909302929092179098556080808b0180516005805473ffffffffffffffffffffffffffffffffffffffff1916918d169190911790558451988952955185169688019690965290518316918601919091525116938301939093529151909216908201527fa55bd56595c45f517e5967a3067f3dca684445a3080e7c04a4e0d5a40cda627d9060a00160405180910390a150565b6060865167ffffffffffffffff811115611eb257611eb2613f44565b604051908082528060200260200182016040528015611ef757816020015b6040805180820190915260008082526020820152815260200190600190039081611ed05790505b50905060005b8751811015611fa957611f84888281518110611f1b57611f1b614faa565b6020026020010151888888888887818110611f3857611f38614faa565b9050602002810190611f4a9190615a9a565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612f0092505050565b828281518110611f9657611f96614faa565b6020908102919091010152600101611efd565b505b9695505050505050565b6000611fc0836132a5565b8015610d775750610d778383613309565b336001600160a01b038216036120295760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016106f8565b6001805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b806040015160ff166000036120b2576000604051631b3fab5160e11b81526004016106f89190615ae1565b60208082015160ff8082166000908152600290935260408320600181015492939092839216900361211f57606084015160018201805491151562010000027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff909216919091179055612174565b6060840151600182015460ff6201000090910416151590151514612174576040517f87f6037c00000000000000000000000000000000000000000000000000000000815260ff841660048201526024016106f8565b60a0840151805161010010156121a0576001604051631b3fab5160e11b81526004016106f89190615ae1565b61220684846003018054806020026020016040519081016040528092919081815260200182805480156121fc57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116121de575b50505050506133c4565b8460600151156123105761227484846002018054806020026020016040519081016040528092919081815260200182805480156121fc576020028201919060005260206000209081546001600160a01b031681526001909101906020018083116121de5750505050506133c4565b6080850151805161010010156122a0576002604051631b3fab5160e11b81526004016106f89190615ae1565b60408601516122b0906003615afb565b60ff168151116122d6576003604051631b3fab5160e11b81526004016106f89190615ae1565b805160018401805461ff00191661010060ff8416021790556123019060028601906020840190613ebd565b5061230e8582600161342d565b505b61231c8482600261342d565b80516123319060038501906020840190613ebd565b5060408581015160018401805460ff191660ff8316179055865180855560a088015192517fab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f5479361238a9389939260028a01929190615b17565b60405180910390a1611904846135a1565b815181516040517f2cbc26bb000000000000000000000000000000000000000000000000000000008152608083901b77ffffffffffffffff00000000000000000000000000000000166004820152901515907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632cbc26bb90602401602060405180830381865afa15801561243e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124629190615535565b156124ee5780156124ab576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff831660048201526024016106f8565b60405167ffffffffffffffff831681527faab522ed53d887e56ed53dd37398a01aeef6a58e0fa77c2173beb9512d8949339060200160405180910390a150505050565b60006124f98361190b565b60010180546125079061580b565b80601f01602080910402602001604051908101604052809291908181526020018280546125339061580b565b80156125805780601f1061255557610100808354040283529160200191612580565b820191906000526020600020905b81548152906001019060200180831161256357829003601f168201915b505050602088015151929350505060008190036125c8576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8560400151518114612606576040517f57e0e08300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008167ffffffffffffffff81111561262157612621613f44565b60405190808252806020026020018201604052801561264a578160200160208202803683370190505b50905060005b828110156127a35760008860200151828151811061267057612670614faa565b602002602001015190507f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681600001516040015167ffffffffffffffff161461270357805160409081015190517f38432a2200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016106f8565b8667ffffffffffffffff1681600001516020015167ffffffffffffffff1614612773578051602001516040517f6c95f1eb00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808a16600483015290911660248201526044016106f8565b61277d8186613611565b83838151811061278f5761278f614faa565b602090810291909101015250600101612650565b5060006127ba86838a606001518b60800151613733565b905080600003612802576040517f7dd17a7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff871660048201526024016106f8565b60005b83811015610cb65760005a905060008a60200151838151811061282a5761282a614faa565b6020026020010151905060006128488a836000015160600151610d2a565b9050600081600381111561285e5761285e614b17565b148061287b5750600381600381111561287957612879614b17565b145b6128d3578151606001516040805167ffffffffffffffff808e16825290921660208301527f3b575419319662b2a6f5e2467d84521517a3382b908eb3d557bb3fdb0c50e23c91015b60405180910390a1505050612d13565b88156129a357600454600090600160a01b900463ffffffff166128f6874261561d565b11905080806129165750600382600381111561291457612914614b17565b145b612958576040517fa9cfc86200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8c1660048201526024016106f8565b8b858151811061296a5761296a614faa565b602002602001015160001461299d578b858151811061298b5761298b614faa565b60200260200101518360800181815250505b50612a04565b60008160038111156129b7576129b7614b17565b14612a04578151606001516040805167ffffffffffffffff808e16825290921660208301527f3ef2a99c550a751d4b0b261268f05a803dfb049ab43616a1ffb388f61fe6512091016128c3565b81516080015167ffffffffffffffff1615612af3576000816003811115612a2d57612a2d614b17565b03612af35781516080015160208301516040517fe0e03cae0000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169263e0e03cae92612aa4928f929190600401615bc3565b6020604051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190615535565b612af357505050612d13565b60008c604001518581518110612b0b57612b0b614faa565b6020026020010151905080518360a001515114612b6f578251606001516040517f1cfe6d8b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808e16600483015290911660248201526044016106f8565b612b838b8460000151606001516001613771565b600080612b908584613819565b91509150612ba78d86600001516060015184613771565b8b15612c17576003826003811115612bc157612bc1614b17565b03612c17576000846003811115612bda57612bda614b17565b14612c17578451516040517f2b11b8d90000000000000000000000000000000000000000000000000000000081526106f891908390600401615bf0565b6002826003811115612c2b57612c2b614b17565b14612c85576003826003811115612c4457612c44614b17565b14612c85578451606001516040517f926c5a3e0000000000000000000000000000000000000000000000000000000081526106f8918f918590600401615c09565b84600001516000015185600001516060015167ffffffffffffffff168e67ffffffffffffffff167f05665fe9ad095383d018353f4cbcba77e84db27dd215081bbf7cdf9ae6fbe48b8c8b81518110612cdf57612cdf614faa565b602002602001015186865a612cf4908e61561d565b604051612d049493929190615c2f565b60405180910390a45050505050505b600101612805565b8251600090815b818110156111b8576000600188868460208110612d4157612d41614faa565b612d4e91901a601b615a36565b898581518110612d6057612d60614faa565b6020026020010151898681518110612d7a57612d7a614faa565b602002602001015160405160008152602001604052604051612db8949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015612dda573d6000803e3d6000fd5b505060408051601f1981015160ff808e166000908152600360209081528582206001600160a01b03851683528152858220858701909652855480841686529397509095509293928401916101009004166002811115612e3b57612e3b614b17565b6002811115612e4c57612e4c614b17565b9052509050600181602001516002811115612e6957612e69614b17565b14612ea0576040517fca31867a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051600160ff9091161b851615612ee3576040517ff67bc7c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806000015160ff166001901b851794505050806001019050612d22565b60408051808201909152600080825260208201526000612f2387602001516138e3565b6040517fbbe4f6db0000000000000000000000000000000000000000000000000000000081526001600160a01b0380831660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063bbe4f6db90602401602060405180830381865afa158015612fa8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fcc9190615c66565b90506001600160a01b038116158061301457506130126001600160a01b0382167faff2afbf00000000000000000000000000000000000000000000000000000000611fb5565b155b15613056576040517fae9b4ce90000000000000000000000000000000000000000000000000000000081526001600160a01b03821660048201526024016106f8565b60045460009081906130789089908690600160e01b900463ffffffff16613989565b9150915060008060006131456040518061010001604052808e81526020018c67ffffffffffffffff1681526020018d6001600160a01b031681526020018f606001518152602001896001600160a01b031681526020018f6000015181526020018f6040015181526020018b8152506040516024016130f69190615c83565b60408051601f198184030181529190526020810180516001600160e01b03167f390775370000000000000000000000000000000000000000000000000000000017905287866113886084613ab7565b9250925092508261318457816040517fe1cd55090000000000000000000000000000000000000000000000000000000081526004016106f89190614932565b81516020146131cc5781516040517f78ef80240000000000000000000000000000000000000000000000000000000081526020600482015260248101919091526044016106f8565b6000828060200190518101906131e29190615d50565b9050866001600160a01b03168c6001600160a01b0316146132775760006132138d8a61320e868a61561d565b613989565b5090508681108061322d57508161322a888361561d565b14155b15613275576040517fa966e21f0000000000000000000000000000000000000000000000000000000081526004810183905260248101889052604481018290526064016106f8565b505b604080518082019091526001600160a01b039098168852602088015250949550505050505095945050505050565b60006132d1827f01ffc9a700000000000000000000000000000000000000000000000000000000613309565b8015610d7a5750613302827fffffffff00000000000000000000000000000000000000000000000000000000613309565b1592915050565b6040517fffffffff0000000000000000000000000000000000000000000000000000000082166024820152600090819060440160408051601f19818403018152919052602080820180516001600160e01b03167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825192935060009283928392909183918a617530fa92503d915060005190508280156133ad575060208210155b80156133b95750600081115b979650505050505050565b60005b81518110156107245760ff8316600090815260036020526040812083519091908490849081106133f9576133f9614faa565b6020908102919091018101516001600160a01b03168252810191909152604001600020805461ffff191690556001016133c7565b60005b8251811015610d2457600083828151811061344d5761344d614faa565b602002602001015190506000600281111561346a5761346a614b17565b60ff80871660009081526003602090815260408083206001600160a01b038716845290915290205461010090041660028111156134a9576134a9614b17565b146134ca576004604051631b3fab5160e11b81526004016106f89190615ae1565b6001600160a01b03811661350a576040517fd6c62c9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052808360ff16815260200184600281111561353057613530614b17565b905260ff80871660009081526003602090815260408083206001600160a01b0387168452825290912083518154931660ff198416811782559184015190929091839161ffff19161761010083600281111561358d5761358d614b17565b021790555090505050806001019050613430565b60ff81166105815760ff808216600090815260026020526040902060010154620100009004166135fd576040517f7a3b4c9400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6009805467ffffffffffffffff1916905550565b815160208082015160409283015192516000938493613657937f2425b0b9f9054c76ff151b0a175b18f37a4a4e82013a72e9f15c9caa095ed21f93909291889101615d69565b60408051601f1981840301815290829052805160209182012086518051888401516060808b0151908401516080808d015195015195976136a09794969395929491939101615d9c565b604051602081830303815290604052805190602001208560400151805190602001208660a001516040516020016136d79190615ea1565b60408051601f198184030181528282528051602091820120908301969096528101939093526060830191909152608082015260a081019190915260c0015b60405160208183030381529060405280519060200120905092915050565b600080613741858585613bdd565b67ffffffffffffffff8716600090815260086020908152604080832093835292905220549150505b949350505050565b60006002613780608085615646565b67ffffffffffffffff16613794919061566d565b905060006137a28585611ce9565b9050816137b16001600461561d565b901b1916818360038111156137c8576137c8614b17565b67ffffffffffffffff871660009081526007602052604081209190921b929092179182916137f7608088615a73565b67ffffffffffffffff1681526020810191909152604001600020555050505050565b6040517fa80036b4000000000000000000000000000000000000000000000000000000008152600090606090309063a80036b49061385d9087908790600401615f01565b600060405180830381600087803b15801561387757600080fd5b505af1925050508015613888575060015b6138c7573d8080156138b6576040519150601f19603f3d011682016040523d82523d6000602084013e6138bb565b606091505b506003925090506138dc565b50506040805160208101909152600081526002905b9250929050565b6000815160201461392257816040517f8d666f600000000000000000000000000000000000000000000000000000000081526004016106f89190614932565b6000828060200190518101906139389190615d50565b90506001600160a01b03811180613950575061040081105b15610d7a57826040517f8d666f600000000000000000000000000000000000000000000000000000000081526004016106f89190614932565b6000806000806000613a03886040516024016139b491906001600160a01b0391909116815260200190565b60408051601f198184030181529190526020810180516001600160e01b03167f70a082310000000000000000000000000000000000000000000000000000000017905288886113886084613ab7565b92509250925082613a4257816040517fe1cd55090000000000000000000000000000000000000000000000000000000081526004016106f89190614932565b6020825114613a8a5781516040517f78ef80240000000000000000000000000000000000000000000000000000000081526020600482015260248101919091526044016106f8565b81806020019051810190613a9e9190615d50565b613aa8828861561d565b94509450505050935093915050565b6000606060008361ffff1667ffffffffffffffff811115613ada57613ada613f44565b6040519080825280601f01601f191660200182016040528015613b04576020820181803683370190505b509150863b613b37577f0c3b563c0000000000000000000000000000000000000000000000000000000060005260046000fd5b5a85811015613b6a577fafa32a2c0000000000000000000000000000000000000000000000000000000060005260046000fd5b8590036040810481038710613ba3577f37c3be290000000000000000000000000000000000000000000000000000000060005260046000fd5b505a6000808a5160208c0160008c8cf193505a900390503d84811115613bc65750835b808352806000602085013e50955095509592505050565b8251825160009190818303613c1e576040517f11a6b26400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6101018211801590613c3257506101018111155b613c4f576040516309bde33960e01b815260040160405180910390fd5b60001982820101610100811115613c79576040516309bde33960e01b815260040160405180910390fd5b80600003613ca65786600081518110613c9457613c94614faa565b60200260200101519350505050613e75565b60008167ffffffffffffffff811115613cc157613cc1613f44565b604051908082528060200260200182016040528015613cea578160200160208202803683370190505b50905060008080805b85811015613e145760006001821b8b811603613d4e5788851015613d37578c5160018601958e918110613d2857613d28614faa565b60200260200101519050613d70565b8551600185019487918110613d2857613d28614faa565b8b5160018401938d918110613d6557613d65614faa565b602002602001015190505b600089861015613da0578d5160018701968f918110613d9157613d91614faa565b60200260200101519050613dc2565b8651600186019588918110613db757613db7614faa565b602002602001015190505b82851115613de3576040516309bde33960e01b815260040160405180910390fd5b613ded8282613e7c565b878481518110613dff57613dff614faa565b60209081029190910101525050600101613cf3565b506001850382148015613e2657508683145b8015613e3157508581145b613e4e576040516309bde33960e01b815260040160405180910390fd5b836001860381518110613e6357613e63614faa565b60200260200101519750505050505050505b9392505050565b6000818310613e9457613e8f8284613e9a565b610d77565b610d7783835b604080516001602082015290810183905260608101829052600090608001613715565b828054828255906000526020600020908101928215613f1f579160200282015b82811115613f1f578251825473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03909116178255602090920191600190910190613edd565b50613f2b929150613f2f565b5090565b5b80821115613f2b5760008155600101613f30565b634e487b7160e01b600052604160045260246000fd5b6040516080810167ffffffffffffffff81118282101715613f7d57613f7d613f44565b60405290565b60405160a0810167ffffffffffffffff81118282101715613f7d57613f7d613f44565b60405160c0810167ffffffffffffffff81118282101715613f7d57613f7d613f44565b6040805190810167ffffffffffffffff81118282101715613f7d57613f7d613f44565b6040516060810167ffffffffffffffff81118282101715613f7d57613f7d613f44565b604051601f8201601f1916810167ffffffffffffffff8111828210171561403857614038613f44565b604052919050565b600067ffffffffffffffff82111561405a5761405a613f44565b5060051b60200190565b6001600160a01b038116811461058157600080fd5b803567ffffffffffffffff8116811461409157600080fd5b919050565b801515811461058157600080fd5b803561409181614096565b600067ffffffffffffffff8211156140c9576140c9613f44565b50601f01601f191660200190565b600082601f8301126140e857600080fd5b81356140fb6140f6826140af565b61400f565b81815284602083860101111561411057600080fd5b816020850160208301376000918101602001919091529392505050565b6000602080838503121561414057600080fd5b823567ffffffffffffffff8082111561415857600080fd5b818501915085601f83011261416c57600080fd5b813561417a6140f682614040565b81815260059190911b8301840190848101908883111561419957600080fd5b8585015b8381101561423f578035858111156141b55760008081fd5b86016080818c03601f19018113156141cd5760008081fd5b6141d5613f5a565b898301356141e281614064565b815260406141f1848201614079565b8b83015260608085013561420481614096565b8383015292840135928984111561421d57600091508182fd5b61422b8f8d868801016140d7565b90830152508552505091860191860161419d565b5098975050505050505050565b600060a0828403121561425e57600080fd5b614266613f83565b90508135815261427860208301614079565b602082015261428960408301614079565b604082015261429a60608301614079565b60608201526142ab60808301614079565b608082015292915050565b803561409181614064565b600082601f8301126142d257600080fd5b813560206142e26140f683614040565b82815260059290921b8401810191818101908684111561430157600080fd5b8286015b84811015611fa957803567ffffffffffffffff808211156143265760008081fd5b9088019060a0828b03601f19018113156143405760008081fd5b614348613f83565b878401358381111561435a5760008081fd5b6143688d8a838801016140d7565b8252506040808501358481111561437f5760008081fd5b61438d8e8b838901016140d7565b8a84015250606080860135858111156143a65760008081fd5b6143b48f8c838a01016140d7565b838501525060809150818601358184015250828501359250838311156143da5760008081fd5b6143e88d8a858801016140d7565b908201528652505050918301918301614305565b6000610140828403121561440f57600080fd5b614417613fa6565b9050614423838361424c565b815260a082013567ffffffffffffffff8082111561444057600080fd5b61444c858386016140d7565b602084015260c084013591508082111561446557600080fd5b614471858386016140d7565b604084015261448260e085016142b6565b606084015261010084013560808401526101208401359150808211156144a757600080fd5b506144b4848285016142c1565b60a08301525092915050565b600082601f8301126144d157600080fd5b813560206144e16140f683614040565b82815260059290921b8401810191818101908684111561450057600080fd5b8286015b84811015611fa957803567ffffffffffffffff8111156145245760008081fd5b6145328986838b01016143fc565b845250918301918301614504565b600082601f83011261455157600080fd5b813560206145616140f683614040565b82815260059290921b8401810191818101908684111561458057600080fd5b8286015b84811015611fa957803567ffffffffffffffff808211156145a457600080fd5b818901915089603f8301126145b857600080fd5b858201356145c86140f682614040565b81815260059190911b830160400190878101908c8311156145e857600080fd5b604085015b838110156146215780358581111561460457600080fd5b6146138f6040838a01016140d7565b8452509189019189016145ed565b50875250505092840192508301614584565b600082601f83011261464457600080fd5b813560206146546140f683614040565b8083825260208201915060208460051b87010193508684111561467657600080fd5b602086015b84811015611fa9578035835291830191830161467b565b600082601f8301126146a357600080fd5b813560206146b36140f683614040565b82815260059290921b840181019181810190868411156146d257600080fd5b8286015b84811015611fa957803567ffffffffffffffff808211156146f75760008081fd5b9088019060a0828b03601f19018113156147115760008081fd5b614719613f83565b614724888501614079565b81526040808501358481111561473a5760008081fd5b6147488e8b838901016144c0565b8a84015250606080860135858111156147615760008081fd5b61476f8f8c838a0101614540565b838501525060809150818601358581111561478a5760008081fd5b6147988f8c838a0101614633565b91840191909152509190930135908301525083529183019183016146d6565b60008060408084860312156147cb57600080fd5b833567ffffffffffffffff808211156147e357600080fd5b6147ef87838801614692565b945060209150818601358181111561480657600080fd5b8601601f8101881361481757600080fd5b80356148256140f682614040565b81815260059190911b8201840190848101908a83111561484457600080fd5b8584015b838110156148d0578035868111156148605760008081fd5b8501603f81018d136148725760008081fd5b878101356148826140f682614040565b81815260059190911b82018a0190898101908f8311156148a25760008081fd5b928b01925b828410156148c05783358252928a0192908a01906148a7565b8652505050918601918601614848565b50809750505050505050509250929050565b60005b838110156148fd5781810151838201526020016148e5565b50506000910152565b6000815180845261491e8160208601602086016148e2565b601f01601f19169290920160200192915050565b602081526000610d776020830184614906565b8060608101831015610d7a57600080fd5b60008083601f84011261496857600080fd5b50813567ffffffffffffffff81111561498057600080fd5b6020830191508360208285010111156138dc57600080fd5b60008083601f8401126149aa57600080fd5b50813567ffffffffffffffff8111156149c257600080fd5b6020830191508360208260051b85010111156138dc57600080fd5b60008060008060008060008060e0898b0312156149f957600080fd5b614a038a8a614945565b9750606089013567ffffffffffffffff80821115614a2057600080fd5b614a2c8c838d01614956565b909950975060808b0135915080821115614a4557600080fd5b614a518c838d01614998565b909750955060a08b0135915080821115614a6a57600080fd5b50614a778b828c01614998565b999c989b50969995989497949560c00135949350505050565b600080600060808486031215614aa557600080fd5b614aaf8585614945565b9250606084013567ffffffffffffffff811115614acb57600080fd5b614ad786828701614956565b9497909650939450505050565b60008060408385031215614af757600080fd5b614b0083614079565b9150614b0e60208401614079565b90509250929050565b634e487b7160e01b600052602160045260246000fd5b60048110614b3d57614b3d614b17565b9052565b60208101610d7a8284614b2d565b600060208284031215614b6157600080fd5b813567ffffffffffffffff811115614b7857600080fd5b820160a08185031215613e7557600080fd5b803563ffffffff8116811461409157600080fd5b600060a08284031215614bb057600080fd5b614bb8613f83565b8235614bc381614064565b8152614bd160208401614b8a565b6020820152614be260408401614b8a565b6040820152614bf360608401614b8a565b60608201526080830135614c0681614064565b60808201529392505050565b600080600060408486031215614c2757600080fd5b833567ffffffffffffffff80821115614c3f57600080fd5b614c4b878388016143fc565b94506020860135915080821115614c6157600080fd5b50614ad786828701614998565b803560ff8116811461409157600080fd5b600060208284031215614c9157600080fd5b610d7782614c6e565b60008151808452602080850194506020840160005b83811015614cd45781516001600160a01b031687529582019590820190600101614caf565b509495945050505050565b60208152600082518051602084015260ff602082015116604084015260ff604082015116606084015260608101511515608084015250602083015160c060a0840152614d2e60e0840182614c9a565b90506040840151601f198483030160c0850152614d4b8282614c9a565b95945050505050565b60008060408385031215614d6757600080fd5b614d7083614079565b946020939093013593505050565b600060208284031215614d9057600080fd5b610d7782614079565b602081526001600160a01b03825116602082015260208201511515604082015267ffffffffffffffff60408301511660608201526000606083015160808084015261376960a0840182614906565b600060208284031215614df957600080fd5b8135613e7581614064565b600082601f830112614e1557600080fd5b81356020614e256140f683614040565b8083825260208201915060208460051b870101935086841115614e4757600080fd5b602086015b84811015611fa9578035614e5f81614064565b8352918301918301614e4c565b60006020808385031215614e7f57600080fd5b823567ffffffffffffffff80821115614e9757600080fd5b818501915085601f830112614eab57600080fd5b8135614eb96140f682614040565b81815260059190911b83018401908481019088831115614ed857600080fd5b8585015b8381101561423f57803585811115614ef357600080fd5b860160c0818c03601f19011215614f0a5760008081fd5b614f12613fa6565b8882013581526040614f25818401614c6e565b8a8301526060614f36818501614c6e565b8284015260809150614f498285016140a4565b9083015260a08381013589811115614f615760008081fd5b614f6f8f8d83880101614e04565b838501525060c0840135915088821115614f895760008081fd5b614f978e8c84870101614e04565b9083015250845250918601918601614edc565b634e487b7160e01b600052603260045260246000fd5b80356001600160e01b038116811461409157600080fd5b600082601f830112614fe857600080fd5b81356020614ff86140f683614040565b82815260069290921b8401810191818101908684111561501757600080fd5b8286015b84811015611fa957604081890312156150345760008081fd5b61503c613fc9565b61504582614079565b8152615052858301614fc0565b8186015283529183019160400161501b565b600082601f83011261507557600080fd5b813560206150856140f683614040565b82815260059290921b840181019181810190868411156150a457600080fd5b8286015b84811015611fa957803567ffffffffffffffff808211156150c95760008081fd5b9088019060a0828b03601f19018113156150e35760008081fd5b6150eb613f83565b6150f6888501614079565b81526040615105818601614079565b898301526060615116818701614079565b82840152608091508186013581840152508285013592508383111561513b5760008081fd5b6151498d8a858801016140d7565b9082015286525050509183019183016150a8565b600082601f83011261516e57600080fd5b8135602061517e6140f683614040565b82815260069290921b8401810191818101908684111561519d57600080fd5b8286015b84811015611fa957604081890312156151ba5760008081fd5b6151c2613fc9565b8135815284820135858201528352918301916040016151a1565b600060208083850312156151ef57600080fd5b823567ffffffffffffffff8082111561520757600080fd5b908401906060828703121561521b57600080fd5b615223613fec565b82358281111561523257600080fd5b8301604081890381131561524557600080fd5b61524d613fc9565b82358581111561525c57600080fd5b8301601f81018b1361526d57600080fd5b803561527b6140f682614040565b81815260069190911b8201890190898101908d83111561529a57600080fd5b928a01925b828410156152ea5785848f0312156152b75760008081fd5b6152bf613fc9565b84356152ca81614064565b81526152d7858d01614fc0565b818d0152825292850192908a019061529f565b84525050508287013591508482111561530257600080fd5b61530e8a838501614fd7565b8188015283525050828401358281111561532757600080fd5b61533388828601615064565b8583015250604083013593508184111561534c57600080fd5b6153588785850161515d565b60408201529695505050505050565b600082825180855260208086019550808260051b84010181860160005b848110156153f757858303601f190189528151805167ffffffffffffffff908116855285820151811686860152604080830151909116908501526060808201519085015260809081015160a0918501829052906153e381860183614906565b9a86019a9450505090830190600101615384565b5090979650505050505050565b60008151808452602080850194506020840160005b83811015614cd4578151805188528301518388015260409096019590820190600101615419565b6040815260006154536040830185615367565b8281036020840152614d4b8185615404565b805160408084528151848201819052600092602091908201906060870190855b818110156154bc57835180516001600160a01b031684528501516001600160e01b0316858401529284019291850191600101615485565b50508583015187820388850152805180835290840192506000918401905b80831015615516578351805167ffffffffffffffff1683528501516001600160e01b0316858301529284019260019290920191908501906154da565b50979650505050505050565b602081526000610d776020830184615465565b60006020828403121561554757600080fd5b8151613e7581614096565b634e487b7160e01b600052601160045260246000fd5b67ffffffffffffffff81811683821601908082111561558957615589615552565b5092915050565b6020815260008251606060208401526155ac6080840182615465565b90506020840151601f19808584030160408601526155ca8383615367565b9250604086015191508085840301606086015250614d4b8282615404565b6000602082840312156155fa57600080fd5b813567ffffffffffffffff81111561561157600080fd5b61376984828501614692565b81810381811115610d7a57610d7a615552565b634e487b7160e01b600052601260045260246000fd5b600067ffffffffffffffff8084168061566157615661615630565b92169190910692915050565b8082028115828204841417610d7a57610d7a615552565b805182526000602067ffffffffffffffff81840151168185015260408084015160a060408701526156b860a0870182614906565b9050606085015186820360608801526156d18282614906565b608087810151898303918a01919091528051808352908601935060009250908501905b8083101561551657835180516001600160a01b03168352860151868301529285019260019290920191908401906156f4565b602081526000610d776020830184615684565b60808152600061574c6080830187615684565b61ffff9590951660208301525060408101929092526001600160a01b0316606090910152919050565b60008060006060848603121561578a57600080fd5b835161579581614096565b602085015190935067ffffffffffffffff8111156157b257600080fd5b8401601f810186136157c357600080fd5b80516157d16140f6826140af565b8181528760208385010111156157e657600080fd5b6157f78260208301602086016148e2565b809450505050604084015190509250925092565b600181811c9082168061581f57607f821691505b60208210810361583f57634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115610724576000816000526020600020601f850160051c8101602086101561586e5750805b601f850160051c820191505b8181101561588d5782815560010161587a565b505050505050565b815167ffffffffffffffff8111156158af576158af613f44565b6158c3816158bd845461580b565b84615845565b602080601f8311600181146158f857600084156158e05750858301515b600019600386901b1c1916600185901b17855561588d565b600085815260208120601f198616915b8281101561592757888601518255948401946001909101908401615908565b50858210156159455787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6000602080835283546001600160a01b038116602085015260ff8160a01c161515604085015267ffffffffffffffff8160a81c166060850152506001808501608080860152600081546159a78161580b565b8060a089015260c060018316600081146159c857600181146159e457615a14565b60ff19841660c08b015260c083151560051b8b01019450615a14565b85600052602060002060005b84811015615a0b5781548c82018501529088019089016159f0565b8b0160c0019550505b50929998505050505050505050565b80820180821115610d7a57610d7a615552565b60ff8181168382160190811115610d7a57610d7a615552565b8183823760009101908152919050565b828152606082602083013760800192915050565b600067ffffffffffffffff80841680615a8e57615a8e615630565b92169190910492915050565b6000808335601e19843603018112615ab157600080fd5b83018035915067ffffffffffffffff821115615acc57600080fd5b6020019150368190038213156138dc57600080fd5b6020810160058310615af557615af5614b17565b91905290565b60ff818116838216029081169081811461558957615589615552565b600060a0820160ff881683526020878185015260a0604085015281875480845260c0860191508860005282600020935060005b81811015615b6f5784546001600160a01b031683526001948501949284019201615b4a565b50508481036060860152865180825290820192508187019060005b81811015615baf5782516001600160a01b031685529383019391830191600101615b8a565b50505060ff85166080850152509050611fab565b600067ffffffffffffffff808616835280851660208401525060606040830152614d4b6060830184614906565b8281526040602082015260006137696040830184614906565b67ffffffffffffffff848116825283166020820152606081016137696040830184614b2d565b848152615c3f6020820185614b2d565b608060408201526000615c556080830185614906565b905082606083015295945050505050565b600060208284031215615c7857600080fd5b8151613e7581614064565b6020815260008251610100806020850152615ca2610120850183614906565b91506020850151615cbf604086018267ffffffffffffffff169052565b5060408501516001600160a01b038116606086015250606085015160808501526080850151615cf960a08601826001600160a01b03169052565b5060a0850151601f19808685030160c0870152615d168483614906565b935060c08701519150808685030160e0870152615d338483614906565b935060e0870151915080868503018387015250611fab8382614906565b600060208284031215615d6257600080fd5b5051919050565b848152600067ffffffffffffffff808616602084015280851660408401525060806060830152611fab6080830184614906565b86815260c060208201526000615db560c0830188614906565b6001600160a01b039690961660408301525067ffffffffffffffff9384166060820152608081019290925290911660a09091015292915050565b600082825180855260208086019550808260051b84010181860160005b848110156153f757601f19868403018952815160a08151818652615e3282870182614906565b9150508582015185820387870152615e4a8282614906565b91505060408083015186830382880152615e648382614906565b92505050606080830151818701525060808083015192508582038187015250615e8d8183614906565b9a86019a9450505090830190600101615e0c565b602081526000610d776020830184615def565b60008282518085526020808601955060208260051b8401016020860160005b848110156153f757601f19868403018952615eef838351614906565b98840198925090830190600101615ed3565b604081526000835180516040840152602081015167ffffffffffffffff80821660608601528060408401511660808601528060608401511660a08601528060808401511660c086015250505060208401516101408060e0850152615f69610180850183614906565b91506040860151603f198086850301610100870152615f888483614906565b935060608801519150615fa76101208701836001600160a01b03169052565b60808801518387015260a0880151925080868503016101608701525050615fce8282615def565b9150508281036020840152614d4b8185615eb456fea164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CanOnlySelfCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"actual\",\"type\":\"bytes32\"}],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ExecutionError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"ForkedChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enumMultiOCR3Base.InvalidConfigErrorType\",\"name\":\"errorType\",\"type\":\"uint8\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"got\",\"type\":\"uint256\"}],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidEVMAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"name\":\"InvalidInterval\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"newLimit\",\"type\":\"uint256\"}],\"name\":\"InvalidManualExecutionGasLimit\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"messageDestChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidMessageDestChainSelector\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"newState\",\"type\":\"uint8\"}],\"name\":\"InvalidNewState\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRoot\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidStaticConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LeavesCannotBeEmpty\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ManualExecutionGasLimitMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"ManualExecutionNotYetEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"errorReason\",\"type\":\"bytes\"}],\"name\":\"MessageValidationError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonUniqueSignatures\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"notPool\",\"type\":\"address\"}],\"name\":\"NotACompatiblePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OracleCannotBeZeroAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ReceiverError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountReleased\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePre\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePost\",\"type\":\"uint256\"}],\"name\":\"ReleaseOrMintBalanceMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"name\":\"RootAlreadyCommitted\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"RootNotCommitted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignatureVerificationDisabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignaturesOutOfRegistration\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"reportSourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"messageSourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainSelectorMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"StaleCommitReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"StaticConfigCannotBeChanged\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"TokenDataMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"TokenHandlingError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnexpectedTokenData\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"WrongMessageLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WrongNumberOfSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroChainSelectorNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"AlreadyAttempted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"structIRMNV2.Signature[]\",\"name\":\"rmnSignatures\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"report\",\"type\":\"tuple\"}],\"name\":\"CommitReportAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"DynamicConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"messageHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"name\":\"ExecutionStateChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"RootRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"SkippedAlreadyExecutedMessage\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SkippedReportExecution\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"sourceConfig\",\"type\":\"tuple\"}],\"name\":\"SourceChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainSelectorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"}],\"name\":\"StaticConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigUpdates\",\"type\":\"tuple[]\"}],\"name\":\"applySourceChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"destTokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structClient.Any2EVMMessage\",\"name\":\"\",\"type\":\"tuple\"}],\"name\":\"ccipReceive\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"rawVs\",\"type\":\"bytes32\"}],\"name\":\"commit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"execute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"bytes[]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[]\"}],\"name\":\"executeSingleMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"getExecutionState\",\"outputs\":[{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLatestPriceSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"getMerkleRoot\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"getSourceChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"latestConfigDetails\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"n\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"}],\"internalType\":\"structMultiOCR3Base.ConfigInfo\",\"name\":\"configInfo\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfig\",\"name\":\"ocrConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage[]\",\"name\":\"messages\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[][]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[][]\"},{\"internalType\":\"bytes32[]\",\"name\":\"proofs\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"proofFlagBits\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.ExecutionReportSingleChain[]\",\"name\":\"reports\",\"type\":\"tuple[]\"},{\"internalType\":\"uint256[][]\",\"name\":\"gasLimitOverrides\",\"type\":\"uint256[][]\"}],\"name\":\"manuallyExecute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"setDynamicConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfigArgs[]\",\"name\":\"ocrConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"setOCR3Configs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x6101206040523480156200001257600080fd5b5060405162006cca38038062006cca8339810160408190526200003591620008c7565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf81620001fa565b5050466080525060208301516001600160a01b03161580620000ec575060408301516001600160a01b0316155b8062000103575060608301516001600160a01b0316155b1562000122576040516342bcdf7f60e11b815260040160405180910390fd5b82516001600160401b03166000036200014e5760405163c656089560e01b815260040160405180910390fd5b82516001600160401b0390811660a052602080850180516001600160a01b0390811660c05260408088018051831660e0526060808a01805185166101005283518b519098168852945184169587019590955251821690850152905116908201527f683eb52ee924eb817377cfa8f41f238f4bb7a877da5267869dfffbad85f564d89060800160405180910390a1620001e682620002a5565b620001f181620003c1565b50505062000c67565b336001600160a01b03821603620002545760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b0316620002ce576040516342bcdf7f60e11b815260040160405180910390fd5b80516004805460208085018051604080880180516060808b0180516001600160a01b039b8c166001600160c01b0319909a168a17600160a01b63ffffffff98891602176001600160c01b0316600160c01b948816949094026001600160e01b031693909317600160e01b93871693909302929092179098556080808b018051600580546001600160a01b031916918d169190911790558451988952955185169688019690965290518316918601919091525116938301939093529151909216908201527fa55bd56595c45f517e5967a3067f3dca684445a3080e7c04a4e0d5a40cda627d9060a00160405180910390a150565b60005b815181101562000666576000828281518110620003e557620003e562000a1d565b60200260200101519050600081602001519050806001600160401b0316600003620004235760405163c656089560e01b815260040160405180910390fd5b81516001600160a01b03166200044c576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160401b0381166000908152600660205260408120600181018054919291620004789062000a33565b80601f0160208091040260200160405190810160405280929190818152602001828054620004a69062000a33565b8015620004f75780601f10620004cb57610100808354040283529160200191620004f7565b820191906000526020600020905b815481529060010190602001808311620004d957829003601f168201915b5050505050905060008460600151905081516000036200059e57805160000362000534576040516342bcdf7f60e11b815260040160405180910390fd5b6001830162000544828262000ac4565b508254600160a81b600160e81b031916600160a81b1783556040516001600160401b03851681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1620005d9565b8080519060200120828051906020012014620005d95760405163c39a620560e01b81526001600160401b038516600482015260240162000083565b604080860151845487516001600160a01b03166001600160a01b0319921515600160a01b02929092166001600160a81b031990911617178455516001600160401b038516907f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b906200064d90869062000b90565b60405180910390a25050505050806001019050620003c4565b5050565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b0381118282101715620006a557620006a56200066a565b60405290565b604051601f8201601f191681016001600160401b0381118282101715620006d657620006d66200066a565b604052919050565b80516001600160401b0381168114620006f657600080fd5b919050565b6001600160a01b03811681146200071157600080fd5b50565b805163ffffffff81168114620006f657600080fd5b6000601f83601f8401126200073d57600080fd5b825160206001600160401b03808311156200075c576200075c6200066a565b8260051b6200076d838201620006ab565b93845286810183019383810190898611156200078857600080fd5b84890192505b85831015620008ba57825184811115620007a85760008081fd5b89016080601f19828d038101821315620007c25760008081fd5b620007cc62000680565b88840151620007db81620006fb565b81526040620007ec858201620006de565b8a8301526060808601518015158114620008065760008081fd5b838301529385015193898511156200081e5760008081fd5b84860195508f603f8701126200083657600094508485fd5b8a8601519450898511156200084f576200084f6200066a565b620008608b858f88011601620006ab565b93508484528f82868801011115620008785760008081fd5b60005b8581101562000898578681018301518582018d01528b016200087b565b5060009484018b0194909452509182015283525091840191908401906200078e565b9998505050505050505050565b6000806000838503610140811215620008df57600080fd5b6080811215620008ee57600080fd5b620008f862000680565b6200090386620006de565b815260208601516200091581620006fb565b602082015260408601516200092a81620006fb565b604082015260608601516200093f81620006fb565b6060820152935060a0607f19820112156200095957600080fd5b5060405160a081016001600160401b0380821183831017156200098057620009806200066a565b81604052608087015191506200099682620006fb565b818352620009a760a0880162000714565b6020840152620009ba60c0880162000714565b6040840152620009cd60e0880162000714565b60608401526101008701519150620009e582620006fb565b608083018290526101208701519294508083111562000a0357600080fd5b505062000a138682870162000729565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b600181811c9082168062000a4857607f821691505b60208210810362000a6957634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111562000abf576000816000526020600020601f850160051c8101602086101562000a9a5750805b601f850160051c820191505b8181101562000abb5782815560010162000aa6565b5050505b505050565b81516001600160401b0381111562000ae05762000ae06200066a565b62000af88162000af1845462000a33565b8462000a6f565b602080601f83116001811462000b30576000841562000b175750858301515b600019600386901b1c1916600185901b17855562000abb565b600085815260208120601f198616915b8281101562000b615788860151825594840194600190910190840162000b40565b508582101562000b805787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b602080825282546001600160a01b0381168383015260a081901c60ff161515604084015260a81c6001600160401b0316606083015260808083015260018084018054600093929190849062000be58162000a33565b8060a089015260c0600183166000811462000c09576001811462000c265762000c58565b60ff19841660c08b015260c083151560051b8b0101945062000c58565b85600052602060002060005b8481101562000c4f5781548c820185015290880190890162000c32565b8b0160c0019550505b50929998505050505050505050565b60805160a05160c05160e05161010051615fed62000cdd600039600081816102400152612a6b0152600081816102110152612f5f0152600081816101e20152818161077f0152818161098601526123ed0152600081816101b2015261267a0152600081816117db01526118270152615fed6000f3fe608060405234801561001057600080fd5b50600436106101515760003560e01c806379ba5097116100cd578063c673e58411610081578063e9d68a8e11610066578063e9d68a8e1461052a578063f2fde38b1461054a578063f716f99f1461055d57600080fd5b8063c673e584146104c5578063ccd37ba3146104e557600080fd5b80638da5cb5b116100b25780638da5cb5b14610484578063991a50181461049f578063a80036b4146104b257600080fd5b806379ba50971461046e57806385572ffb1461047657600080fd5b80632d04ab76116101245780633f4b04aa116101095780633f4b04aa146103365780635e36480c146103525780637437ff9f1461037257600080fd5b80632d04ab7614610310578063311cd5131461032357600080fd5b806304666f9c1461015657806305d938b51461016b57806306285c691461017e578063181f5a77146102c7575b600080fd5b61016961016436600461412b565b610570565b005b6101696101793660046147b5565b610584565b61027060408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316815250905090565b6040516102be9190815167ffffffffffffffff1681526020808301516001600160a01b0390811691830191909152604080840151821690830152606092830151169181019190915260800190565b60405180910390f35b6103036040518060400160405280601181526020017f4f666652616d7020312e362e302d64657600000000000000000000000000000081525081565b6040516102be9190614930565b61016961031e3660046149db565b610729565b610169610331366004614a8e565b610cbf565b60095460405167ffffffffffffffff90911681526020016102be565b610365610360366004614ae2565b610d28565b6040516102be9190614b3f565b6104116040805160a081018252600080825260208201819052918101829052606081018290526080810191909152506040805160a0810182526004546001600160a01b03808216835263ffffffff600160a01b83048116602085015278010000000000000000000000000000000000000000000000008304811694840194909452600160e01b9091049092166060820152600554909116608082015290565b6040516102be9190600060a0820190506001600160a01b03808451168352602084015163ffffffff808216602086015280604087015116604086015280606087015116606086015250508060808501511660808401525092915050565b610169610d7e565b610169610151366004614b4d565b6000546040516001600160a01b0390911681526020016102be565b6101696104ad366004614b9c565b610e3c565b6101696104c0366004614c10565b610e4d565b6104d86104d3366004614c7d565b6111c0565b6040516102be9190614cdd565b61051c6104f3366004614d52565b67ffffffffffffffff919091166000908152600860209081526040808320938352929052205490565b6040519081526020016102be565b61053d610538366004614d7c565b61131e565b6040516102be9190614d97565b610169610558366004614de5565b61142b565b61016961056b366004614e6a565b61143c565b61057861147e565b610581816114da565b50565b61058c6117d8565b8151815181146105c8576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b818110156107195760008482815181106105e7576105e7614fa8565b6020026020010151905060008160200151519050600085848151811061060f5761060f614fa8565b6020026020010151905080518214610653576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8281101561070a57600082828151811061067257610672614fa8565b6020026020010151905080600014610701578460200151828151811061069a5761069a614fa8565b6020026020010151608001518110156107015784516040517fc8e9605100000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260248101839052604481018290526064015b60405180910390fd5b50600101610656565b505050508060010190506105cb565b506107248383611859565b505050565b6000610737878901896151d7565b602081015151909150156107e357602081015160408083015190517fccd5af000000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169263ccd5af00926107b29260040161543d565b60006040518083038186803b1580156107ca57600080fd5b505afa1580156107de573d6000803e3d6000fd5b505050505b805151511515806107f957508051602001515115155b156108f95760095460208a01359067ffffffffffffffff808316911610156108b8576009805467ffffffffffffffff191667ffffffffffffffff83161790556004805483516040517f3937306f0000000000000000000000000000000000000000000000000000000081526001600160a01b0390921692633937306f9261088192910161551f565b600060405180830381600087803b15801561089b57600080fd5b505af11580156108af573d6000803e3d6000fd5b505050506108f7565b8160200151516000036108f7576040517f2261116700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b60005b816020015151811015610c085760008260200151828151811061092157610921614fa8565b602090810291909101015180516040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815277ffffffffffffffff00000000000000000000000000000000608083901b166004820152919250906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632cbc26bb90602401602060405180830381865afa1580156109cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109f19190615532565b15610a34576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff821660048201526024016106f8565b6000610a3f82611909565b6040840151815491925067ffffffffffffffff908116600160a81b90920416141580610a865750826060015167ffffffffffffffff16836040015167ffffffffffffffff16115b15610ae5578251604080850151606086015191517fd5e0f0d600000000000000000000000000000000000000000000000000000000815267ffffffffffffffff93841660048201529083166024820152911660448201526064016106f8565b608083015180610b21576040517f504570e300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b835167ffffffffffffffff16600090815260086020908152604080832084845290915290205415610b945783516040517f32cf0cbf00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602481018290526044016106f8565b6060840151610ba4906001615565565b82547fffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffff16600160a81b67ffffffffffffffff9283160217909255925116600090815260086020908152604080832094835293905291909120429055506001016108fc565b507f23bc80217a08968cec0790cd045b396fa7eea0a21af469e603329940b883d86d81604051610c38919061558d565b60405180910390a1610cb460008a8a8a8a8a8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808e0282810182019093528d82529093508d92508c9182918501908490808284376000920191909152508b9250611970915050565b505050505050505050565b610cff610cce828401846155e5565b6040805160008082526020820190925290610cf9565b6060815260200190600190039081610ce45790505b50611859565b604080516000808252602082019092529050610d22600185858585866000611970565b50505050565b6000610d366001600461561a565b6002610d43608085615643565b67ffffffffffffffff16610d57919061566a565b610d618585611ce7565b901c166003811115610d7557610d75614b15565b90505b92915050565b6001546001600160a01b03163314610dd85760405162461bcd60e51b815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064016106f8565b600080543373ffffffffffffffffffffffffffffffffffffffff19808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610e4461147e565b61058181611d2e565b333014610e86576040517f371a732800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160008082526020820190925281610ec3565b6040805180820190915260008082526020820152815260200190600190039081610e9c5790505b5060a08501515190915015610ef757610ef48460a00151856020015186606001518760000151602001518787611e94565b90505b6040805160a0810182528551518152855160209081015167ffffffffffffffff1681830152808701518351600094840192610f33929101614930565b60408051601f19818403018152918152908252878101516020830152018390526005549091506001600160a01b03168015611040576040517f08d450a10000000000000000000000000000000000000000000000000000000081526001600160a01b038216906308d450a190610fad908590600401615723565b600060405180830381600087803b158015610fc757600080fd5b505af1925050508015610fd8575060015b611040573d808015611006576040519150601f19603f3d011682016040523d82523d6000602084013e61100b565b606091505b50806040517f09c253250000000000000000000000000000000000000000000000000000000081526004016106f89190614930565b60408601515115801561105557506080860151155b8061106c575060608601516001600160a01b03163b155b806110ac575060608601516110aa906001600160a01b03167f85572ffb00000000000000000000000000000000000000000000000000000000611fb3565b155b156110b957505050505050565b855160209081015167ffffffffffffffff1660009081526006909152604080822054608089015160608a015192517f3cf9798300000000000000000000000000000000000000000000000000000000815284936001600160a01b0390931692633cf97983926111319289926113889291600401615736565b6000604051808303816000875af1158015611150573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526111789190810190615772565b5091509150816111b657806040517f0a8d6e8c0000000000000000000000000000000000000000000000000000000081526004016106f89190614930565b5050505050505050565b6112036040805160e081019091526000606082018181526080830182905260a0830182905260c08301919091528190815260200160608152602001606081525090565b60ff808316600090815260026020818152604092839020835160e081018552815460608201908152600183015480881660808401526101008104881660a0840152620100009004909616151560c0820152948552918201805484518184028101840190955280855292938583019390928301828280156112ac57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161128e575b505050505081526020016003820180548060200260200160405190810160405280929190818152602001828054801561130e57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116112f0575b5050505050815250509050919050565b604080516080808201835260008083526020808401829052838501829052606080850181905267ffffffffffffffff878116845260068352928690208651948501875280546001600160a01b0381168652600160a01b810460ff16151593860193909352600160a81b9092049092169483019490945260018401805493949293918401916113ab90615808565b80601f01602080910402602001604051908101604052809291908181526020018280546113d790615808565b801561130e5780601f106113f95761010080835404028352916020019161130e565b820191906000526020600020905b81548152906001019060200180831161140757505050919092525091949350505050565b61143361147e565b61058181611fcf565b61144461147e565b60005b815181101561147a5761147282828151811061146557611465614fa8565b6020026020010151612085565b600101611447565b5050565b6000546001600160a01b031633146114d85760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016106f8565b565b60005b815181101561147a5760008282815181106114fa576114fa614fa8565b602002602001015190506000816020015190508067ffffffffffffffff16600003611551576040517fc656089500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81516001600160a01b0316611579576040516342bcdf7f60e11b815260040160405180910390fd5b67ffffffffffffffff811660009081526006602052604081206001810180549192916115a490615808565b80601f01602080910402602001604051908101604052809291908181526020018280546115d090615808565b801561161d5780601f106115f25761010080835404028352916020019161161d565b820191906000526020600020905b81548152906001019060200180831161160057829003601f168201915b5050505050905060008460600151905081516000036116d5578051600003611658576040516342bcdf7f60e11b815260040160405180910390fd5b600183016116668282615892565b5082547fffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffff16600160a81b17835560405167ffffffffffffffff851681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1611728565b8080519060200120828051906020012014611728576040517fc39a620500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff851660048201526024016106f8565b604080860151845487516001600160a01b031673ffffffffffffffffffffffffffffffffffffffff19921515600160a01b02929092167fffffffffffffffffffffff000000000000000000000000000000000000000000909116171784555167ffffffffffffffff8516907f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b906117c0908690615952565b60405180910390a250505050508060010190506114dd565b467f0000000000000000000000000000000000000000000000000000000000000000146114d8576040517f0f01ce850000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060048201524660248201526044016106f8565b8151600003611893576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160408051600080825260208201909252911591905b8451811015611902576118fa8582815181106118c8576118c8614fa8565b6020026020010151846118f4578583815181106118e7576118e7614fa8565b6020026020010151612399565b83612399565b6001016118aa565b5050505050565b67ffffffffffffffff811660009081526006602052604081208054600160a01b900460ff16610d78576040517fed053c5900000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024016106f8565b60ff878116600090815260026020908152604080832081516080810183528154815260019091015480861693820193909352610100830485169181019190915262010000909104909216151560608301528735906119cf8760a4615a20565b9050826060015115611a175784516119e890602061566a565b86516119f590602061566a565b611a009060a0615a20565b611a0a9190615a20565b611a149082615a20565b90505b368114611a59576040517f8e1192e1000000000000000000000000000000000000000000000000000000008152600481018290523660248201526044016106f8565b5081518114611aa15781516040517f93df584c0000000000000000000000000000000000000000000000000000000081526004810191909152602481018290526044016106f8565b611aa96117d8565b60ff808a1660009081526003602090815260408083203384528252808320815180830190925280548086168352939491939092840191610100909104166002811115611af757611af7614b15565b6002811115611b0857611b08614b15565b9052509050600281602001516002811115611b2557611b25614b15565b148015611b795750600260008b60ff1660ff168152602001908152602001600020600301816000015160ff1681548110611b6157611b61614fa8565b6000918252602090912001546001600160a01b031633145b611baf576040517fda0f08e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50816060015115611c91576020820151611bca906001615a33565b60ff16855114611c06576040517f71253a2500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8351855114611c41576040517fa75d88af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008787604051611c53929190615a4c565b604051908190038120611c6a918b90602001615a5c565b604051602081830303815290604052805190602001209050611c8f8a82888888612d19565b505b6040805182815260208a81013567ffffffffffffffff169082015260ff8b16917f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef0910160405180910390a2505050505050505050565b67ffffffffffffffff8216600090815260076020526040812081611d0c608085615a70565b67ffffffffffffffff1681526020810191909152604001600020549392505050565b80516001600160a01b0316611d56576040516342bcdf7f60e11b815260040160405180910390fd5b80516004805460208085018051604080880180516060808b0180516001600160a01b039b8c167fffffffffffffffff000000000000000000000000000000000000000000000000909a168a17600160a01b63ffffffff988916021777ffffffffffffffffffffffffffffffffffffffffffffffff167801000000000000000000000000000000000000000000000000948816949094026001600160e01b031693909317600160e01b93871693909302929092179098556080808b0180516005805473ffffffffffffffffffffffffffffffffffffffff1916918d169190911790558451988952955185169688019690965290518316918601919091525116938301939093529151909216908201527fa55bd56595c45f517e5967a3067f3dca684445a3080e7c04a4e0d5a40cda627d9060a00160405180910390a150565b6060865167ffffffffffffffff811115611eb057611eb0613f42565b604051908082528060200260200182016040528015611ef557816020015b6040805180820190915260008082526020820152815260200190600190039081611ece5790505b50905060005b8751811015611fa757611f82888281518110611f1957611f19614fa8565b6020026020010151888888888887818110611f3657611f36614fa8565b9050602002810190611f489190615a97565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612efe92505050565b828281518110611f9457611f94614fa8565b6020908102919091010152600101611efb565b505b9695505050505050565b6000611fbe836132a3565b8015610d755750610d758383613307565b336001600160a01b038216036120275760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016106f8565b6001805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b806040015160ff166000036120b0576000604051631b3fab5160e11b81526004016106f89190615ade565b60208082015160ff8082166000908152600290935260408320600181015492939092839216900361211d57606084015160018201805491151562010000027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff909216919091179055612172565b6060840151600182015460ff6201000090910416151590151514612172576040517f87f6037c00000000000000000000000000000000000000000000000000000000815260ff841660048201526024016106f8565b60a08401518051610100101561219e576001604051631b3fab5160e11b81526004016106f89190615ade565b61220484846003018054806020026020016040519081016040528092919081815260200182805480156121fa57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116121dc575b50505050506133c2565b84606001511561230e5761227284846002018054806020026020016040519081016040528092919081815260200182805480156121fa576020028201919060005260206000209081546001600160a01b031681526001909101906020018083116121dc5750505050506133c2565b60808501518051610100101561229e576002604051631b3fab5160e11b81526004016106f89190615ade565b60408601516122ae906003615af8565b60ff168151116122d4576003604051631b3fab5160e11b81526004016106f89190615ade565b805160018401805461ff00191661010060ff8416021790556122ff9060028601906020840190613ebb565b5061230c8582600161342b565b505b61231a8482600261342b565b805161232f9060038501906020840190613ebb565b5060408581015160018401805460ff191660ff8316179055865180855560a088015192517fab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f547936123889389939260028a01929190615b14565b60405180910390a16119028461359f565b815181516040517f2cbc26bb000000000000000000000000000000000000000000000000000000008152608083901b77ffffffffffffffff00000000000000000000000000000000166004820152901515907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632cbc26bb90602401602060405180830381865afa15801561243c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124609190615532565b156124ec5780156124a9576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff831660048201526024016106f8565b60405167ffffffffffffffff831681527faab522ed53d887e56ed53dd37398a01aeef6a58e0fa77c2173beb9512d8949339060200160405180910390a150505050565b60006124f783611909565b600101805461250590615808565b80601f016020809104026020016040519081016040528092919081815260200182805461253190615808565b801561257e5780601f106125535761010080835404028352916020019161257e565b820191906000526020600020905b81548152906001019060200180831161256157829003601f168201915b505050602088015151929350505060008190036125c6576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8560400151518114612604576040517f57e0e08300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008167ffffffffffffffff81111561261f5761261f613f42565b604051908082528060200260200182016040528015612648578160200160208202803683370190505b50905060005b828110156127a15760008860200151828151811061266e5761266e614fa8565b602002602001015190507f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681600001516040015167ffffffffffffffff161461270157805160409081015190517f38432a2200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016106f8565b8667ffffffffffffffff1681600001516020015167ffffffffffffffff1614612771578051602001516040517f6c95f1eb00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808a16600483015290911660248201526044016106f8565b61277b818661360f565b83838151811061278d5761278d614fa8565b60209081029190910101525060010161264e565b5060006127b886838a606001518b60800151613731565b905080600003612800576040517f7dd17a7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff871660048201526024016106f8565b60005b83811015610cb45760005a905060008a60200151838151811061282857612828614fa8565b6020026020010151905060006128468a836000015160600151610d28565b9050600081600381111561285c5761285c614b15565b14806128795750600381600381111561287757612877614b15565b145b6128d1578151606001516040805167ffffffffffffffff808e16825290921660208301527f3b575419319662b2a6f5e2467d84521517a3382b908eb3d557bb3fdb0c50e23c91015b60405180910390a1505050612d11565b88156129a157600454600090600160a01b900463ffffffff166128f4874261561a565b11905080806129145750600382600381111561291257612912614b15565b145b612956576040517fa9cfc86200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8c1660048201526024016106f8565b8b858151811061296857612968614fa8565b602002602001015160001461299b578b858151811061298957612989614fa8565b60200260200101518360800181815250505b50612a02565b60008160038111156129b5576129b5614b15565b14612a02578151606001516040805167ffffffffffffffff808e16825290921660208301527f3ef2a99c550a751d4b0b261268f05a803dfb049ab43616a1ffb388f61fe6512091016128c1565b81516080015167ffffffffffffffff1615612af1576000816003811115612a2b57612a2b614b15565b03612af15781516080015160208301516040517fe0e03cae0000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169263e0e03cae92612aa2928f929190600401615bc0565b6020604051808303816000875af1158015612ac1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae59190615532565b612af157505050612d11565b60008c604001518581518110612b0957612b09614fa8565b6020026020010151905080518360a001515114612b6d578251606001516040517f1cfe6d8b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808e16600483015290911660248201526044016106f8565b612b818b846000015160600151600161376f565b600080612b8e8584613817565b91509150612ba58d8660000151606001518461376f565b8b15612c15576003826003811115612bbf57612bbf614b15565b03612c15576000846003811115612bd857612bd8614b15565b14612c15578451516040517f2b11b8d90000000000000000000000000000000000000000000000000000000081526106f891908390600401615bed565b6002826003811115612c2957612c29614b15565b14612c83576003826003811115612c4257612c42614b15565b14612c83578451606001516040517f926c5a3e0000000000000000000000000000000000000000000000000000000081526106f8918f918590600401615c06565b84600001516000015185600001516060015167ffffffffffffffff168e67ffffffffffffffff167f05665fe9ad095383d018353f4cbcba77e84db27dd215081bbf7cdf9ae6fbe48b8c8b81518110612cdd57612cdd614fa8565b602002602001015186865a612cf2908e61561a565b604051612d029493929190615c2c565b60405180910390a45050505050505b600101612803565b8251600090815b818110156111b6576000600188868460208110612d3f57612d3f614fa8565b612d4c91901a601b615a33565b898581518110612d5e57612d5e614fa8565b6020026020010151898681518110612d7857612d78614fa8565b602002602001015160405160008152602001604052604051612db6949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015612dd8573d6000803e3d6000fd5b505060408051601f1981015160ff808e166000908152600360209081528582206001600160a01b03851683528152858220858701909652855480841686529397509095509293928401916101009004166002811115612e3957612e39614b15565b6002811115612e4a57612e4a614b15565b9052509050600181602001516002811115612e6757612e67614b15565b14612e9e576040517fca31867a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051600160ff9091161b851615612ee1576040517ff67bc7c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806000015160ff166001901b851794505050806001019050612d20565b60408051808201909152600080825260208201526000612f2187602001516138e1565b6040517fbbe4f6db0000000000000000000000000000000000000000000000000000000081526001600160a01b0380831660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063bbe4f6db90602401602060405180830381865afa158015612fa6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fca9190615c63565b90506001600160a01b038116158061301257506130106001600160a01b0382167faff2afbf00000000000000000000000000000000000000000000000000000000611fb3565b155b15613054576040517fae9b4ce90000000000000000000000000000000000000000000000000000000081526001600160a01b03821660048201526024016106f8565b60045460009081906130769089908690600160e01b900463ffffffff16613987565b9150915060008060006131436040518061010001604052808e81526020018c67ffffffffffffffff1681526020018d6001600160a01b031681526020018f606001518152602001896001600160a01b031681526020018f6000015181526020018f6040015181526020018b8152506040516024016130f49190615c80565b60408051601f198184030181529190526020810180516001600160e01b03167f390775370000000000000000000000000000000000000000000000000000000017905287866113886084613ab5565b9250925092508261318257816040517fe1cd55090000000000000000000000000000000000000000000000000000000081526004016106f89190614930565b81516020146131ca5781516040517f78ef80240000000000000000000000000000000000000000000000000000000081526020600482015260248101919091526044016106f8565b6000828060200190518101906131e09190615d4d565b9050866001600160a01b03168c6001600160a01b0316146132755760006132118d8a61320c868a61561a565b613987565b5090508681108061322b575081613228888361561a565b14155b15613273576040517fa966e21f0000000000000000000000000000000000000000000000000000000081526004810183905260248101889052604481018290526064016106f8565b505b604080518082019091526001600160a01b039098168852602088015250949550505050505095945050505050565b60006132cf827f01ffc9a700000000000000000000000000000000000000000000000000000000613307565b8015610d785750613300827fffffffff00000000000000000000000000000000000000000000000000000000613307565b1592915050565b6040517fffffffff0000000000000000000000000000000000000000000000000000000082166024820152600090819060440160408051601f19818403018152919052602080820180516001600160e01b03167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825192935060009283928392909183918a617530fa92503d915060005190508280156133ab575060208210155b80156133b75750600081115b979650505050505050565b60005b81518110156107245760ff8316600090815260036020526040812083519091908490849081106133f7576133f7614fa8565b6020908102919091018101516001600160a01b03168252810191909152604001600020805461ffff191690556001016133c5565b60005b8251811015610d2257600083828151811061344b5761344b614fa8565b602002602001015190506000600281111561346857613468614b15565b60ff80871660009081526003602090815260408083206001600160a01b038716845290915290205461010090041660028111156134a7576134a7614b15565b146134c8576004604051631b3fab5160e11b81526004016106f89190615ade565b6001600160a01b038116613508576040517fd6c62c9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052808360ff16815260200184600281111561352e5761352e614b15565b905260ff80871660009081526003602090815260408083206001600160a01b0387168452825290912083518154931660ff198416811782559184015190929091839161ffff19161761010083600281111561358b5761358b614b15565b02179055509050505080600101905061342e565b60ff81166105815760ff808216600090815260026020526040902060010154620100009004166135fb576040517f7a3b4c9400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6009805467ffffffffffffffff1916905550565b815160208082015160409283015192516000938493613655937f2425b0b9f9054c76ff151b0a175b18f37a4a4e82013a72e9f15c9caa095ed21f93909291889101615d66565b60408051601f1981840301815290829052805160209182012086518051888401516060808b0151908401516080808d0151950151959761369e9794969395929491939101615d99565b604051602081830303815290604052805190602001208560400151805190602001208660a001516040516020016136d59190615e9e565b60408051601f198184030181528282528051602091820120908301969096528101939093526060830191909152608082015260a081019190915260c0015b60405160208183030381529060405280519060200120905092915050565b60008061373f858585613bdb565b67ffffffffffffffff8716600090815260086020908152604080832093835292905220549150505b949350505050565b6000600261377e608085615643565b67ffffffffffffffff16613792919061566a565b905060006137a08585611ce7565b9050816137af6001600461561a565b901b1916818360038111156137c6576137c6614b15565b67ffffffffffffffff871660009081526007602052604081209190921b929092179182916137f5608088615a70565b67ffffffffffffffff1681526020810191909152604001600020555050505050565b6040517fa80036b4000000000000000000000000000000000000000000000000000000008152600090606090309063a80036b49061385b9087908790600401615efe565b600060405180830381600087803b15801561387557600080fd5b505af1925050508015613886575060015b6138c5573d8080156138b4576040519150601f19603f3d011682016040523d82523d6000602084013e6138b9565b606091505b506003925090506138da565b50506040805160208101909152600081526002905b9250929050565b6000815160201461392057816040517f8d666f600000000000000000000000000000000000000000000000000000000081526004016106f89190614930565b6000828060200190518101906139369190615d4d565b90506001600160a01b0381118061394e575061040081105b15610d7857826040517f8d666f600000000000000000000000000000000000000000000000000000000081526004016106f89190614930565b6000806000806000613a01886040516024016139b291906001600160a01b0391909116815260200190565b60408051601f198184030181529190526020810180516001600160e01b03167f70a082310000000000000000000000000000000000000000000000000000000017905288886113886084613ab5565b92509250925082613a4057816040517fe1cd55090000000000000000000000000000000000000000000000000000000081526004016106f89190614930565b6020825114613a885781516040517f78ef80240000000000000000000000000000000000000000000000000000000081526020600482015260248101919091526044016106f8565b81806020019051810190613a9c9190615d4d565b613aa6828861561a565b94509450505050935093915050565b6000606060008361ffff1667ffffffffffffffff811115613ad857613ad8613f42565b6040519080825280601f01601f191660200182016040528015613b02576020820181803683370190505b509150863b613b35577f0c3b563c0000000000000000000000000000000000000000000000000000000060005260046000fd5b5a85811015613b68577fafa32a2c0000000000000000000000000000000000000000000000000000000060005260046000fd5b8590036040810481038710613ba1577f37c3be290000000000000000000000000000000000000000000000000000000060005260046000fd5b505a6000808a5160208c0160008c8cf193505a900390503d84811115613bc45750835b808352806000602085013e50955095509592505050565b8251825160009190818303613c1c576040517f11a6b26400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6101018211801590613c3057506101018111155b613c4d576040516309bde33960e01b815260040160405180910390fd5b60001982820101610100811115613c77576040516309bde33960e01b815260040160405180910390fd5b80600003613ca45786600081518110613c9257613c92614fa8565b60200260200101519350505050613e73565b60008167ffffffffffffffff811115613cbf57613cbf613f42565b604051908082528060200260200182016040528015613ce8578160200160208202803683370190505b50905060008080805b85811015613e125760006001821b8b811603613d4c5788851015613d35578c5160018601958e918110613d2657613d26614fa8565b60200260200101519050613d6e565b8551600185019487918110613d2657613d26614fa8565b8b5160018401938d918110613d6357613d63614fa8565b602002602001015190505b600089861015613d9e578d5160018701968f918110613d8f57613d8f614fa8565b60200260200101519050613dc0565b8651600186019588918110613db557613db5614fa8565b602002602001015190505b82851115613de1576040516309bde33960e01b815260040160405180910390fd5b613deb8282613e7a565b878481518110613dfd57613dfd614fa8565b60209081029190910101525050600101613cf1565b506001850382148015613e2457508683145b8015613e2f57508581145b613e4c576040516309bde33960e01b815260040160405180910390fd5b836001860381518110613e6157613e61614fa8565b60200260200101519750505050505050505b9392505050565b6000818310613e9257613e8d8284613e98565b610d75565b610d7583835b604080516001602082015290810183905260608101829052600090608001613713565b828054828255906000526020600020908101928215613f1d579160200282015b82811115613f1d578251825473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03909116178255602090920191600190910190613edb565b50613f29929150613f2d565b5090565b5b80821115613f295760008155600101613f2e565b634e487b7160e01b600052604160045260246000fd5b6040516080810167ffffffffffffffff81118282101715613f7b57613f7b613f42565b60405290565b60405160a0810167ffffffffffffffff81118282101715613f7b57613f7b613f42565b60405160c0810167ffffffffffffffff81118282101715613f7b57613f7b613f42565b6040805190810167ffffffffffffffff81118282101715613f7b57613f7b613f42565b6040516060810167ffffffffffffffff81118282101715613f7b57613f7b613f42565b604051601f8201601f1916810167ffffffffffffffff8111828210171561403657614036613f42565b604052919050565b600067ffffffffffffffff82111561405857614058613f42565b5060051b60200190565b6001600160a01b038116811461058157600080fd5b803567ffffffffffffffff8116811461408f57600080fd5b919050565b801515811461058157600080fd5b803561408f81614094565b600067ffffffffffffffff8211156140c7576140c7613f42565b50601f01601f191660200190565b600082601f8301126140e657600080fd5b81356140f96140f4826140ad565b61400d565b81815284602083860101111561410e57600080fd5b816020850160208301376000918101602001919091529392505050565b6000602080838503121561413e57600080fd5b823567ffffffffffffffff8082111561415657600080fd5b818501915085601f83011261416a57600080fd5b81356141786140f48261403e565b81815260059190911b8301840190848101908883111561419757600080fd5b8585015b8381101561423d578035858111156141b35760008081fd5b86016080818c03601f19018113156141cb5760008081fd5b6141d3613f58565b898301356141e081614062565b815260406141ef848201614077565b8b83015260608085013561420281614094565b8383015292840135928984111561421b57600091508182fd5b6142298f8d868801016140d5565b90830152508552505091860191860161419b565b5098975050505050505050565b600060a0828403121561425c57600080fd5b614264613f81565b90508135815261427660208301614077565b602082015261428760408301614077565b604082015261429860608301614077565b60608201526142a960808301614077565b608082015292915050565b803561408f81614062565b600082601f8301126142d057600080fd5b813560206142e06140f48361403e565b82815260059290921b840181019181810190868411156142ff57600080fd5b8286015b84811015611fa757803567ffffffffffffffff808211156143245760008081fd5b9088019060a0828b03601f190181131561433e5760008081fd5b614346613f81565b87840135838111156143585760008081fd5b6143668d8a838801016140d5565b8252506040808501358481111561437d5760008081fd5b61438b8e8b838901016140d5565b8a84015250606080860135858111156143a45760008081fd5b6143b28f8c838a01016140d5565b838501525060809150818601358184015250828501359250838311156143d85760008081fd5b6143e68d8a858801016140d5565b908201528652505050918301918301614303565b6000610140828403121561440d57600080fd5b614415613fa4565b9050614421838361424a565b815260a082013567ffffffffffffffff8082111561443e57600080fd5b61444a858386016140d5565b602084015260c084013591508082111561446357600080fd5b61446f858386016140d5565b604084015261448060e085016142b4565b606084015261010084013560808401526101208401359150808211156144a557600080fd5b506144b2848285016142bf565b60a08301525092915050565b600082601f8301126144cf57600080fd5b813560206144df6140f48361403e565b82815260059290921b840181019181810190868411156144fe57600080fd5b8286015b84811015611fa757803567ffffffffffffffff8111156145225760008081fd5b6145308986838b01016143fa565b845250918301918301614502565b600082601f83011261454f57600080fd5b8135602061455f6140f48361403e565b82815260059290921b8401810191818101908684111561457e57600080fd5b8286015b84811015611fa757803567ffffffffffffffff808211156145a257600080fd5b818901915089603f8301126145b657600080fd5b858201356145c66140f48261403e565b81815260059190911b830160400190878101908c8311156145e657600080fd5b604085015b8381101561461f5780358581111561460257600080fd5b6146118f6040838a01016140d5565b8452509189019189016145eb565b50875250505092840192508301614582565b600082601f83011261464257600080fd5b813560206146526140f48361403e565b8083825260208201915060208460051b87010193508684111561467457600080fd5b602086015b84811015611fa75780358352918301918301614679565b600082601f8301126146a157600080fd5b813560206146b16140f48361403e565b82815260059290921b840181019181810190868411156146d057600080fd5b8286015b84811015611fa757803567ffffffffffffffff808211156146f55760008081fd5b9088019060a0828b03601f190181131561470f5760008081fd5b614717613f81565b614722888501614077565b8152604080850135848111156147385760008081fd5b6147468e8b838901016144be565b8a840152506060808601358581111561475f5760008081fd5b61476d8f8c838a010161453e565b83850152506080915081860135858111156147885760008081fd5b6147968f8c838a0101614631565b91840191909152509190930135908301525083529183019183016146d4565b60008060408084860312156147c957600080fd5b833567ffffffffffffffff808211156147e157600080fd5b6147ed87838801614690565b945060209150818601358181111561480457600080fd5b8601601f8101881361481557600080fd5b80356148236140f48261403e565b81815260059190911b8201840190848101908a83111561484257600080fd5b8584015b838110156148ce5780358681111561485e5760008081fd5b8501603f81018d136148705760008081fd5b878101356148806140f48261403e565b81815260059190911b82018a0190898101908f8311156148a05760008081fd5b928b01925b828410156148be5783358252928a0192908a01906148a5565b8652505050918601918601614846565b50809750505050505050509250929050565b60005b838110156148fb5781810151838201526020016148e3565b50506000910152565b6000815180845261491c8160208601602086016148e0565b601f01601f19169290920160200192915050565b602081526000610d756020830184614904565b8060608101831015610d7857600080fd5b60008083601f84011261496657600080fd5b50813567ffffffffffffffff81111561497e57600080fd5b6020830191508360208285010111156138da57600080fd5b60008083601f8401126149a857600080fd5b50813567ffffffffffffffff8111156149c057600080fd5b6020830191508360208260051b85010111156138da57600080fd5b60008060008060008060008060e0898b0312156149f757600080fd5b614a018a8a614943565b9750606089013567ffffffffffffffff80821115614a1e57600080fd5b614a2a8c838d01614954565b909950975060808b0135915080821115614a4357600080fd5b614a4f8c838d01614996565b909750955060a08b0135915080821115614a6857600080fd5b50614a758b828c01614996565b999c989b50969995989497949560c00135949350505050565b600080600060808486031215614aa357600080fd5b614aad8585614943565b9250606084013567ffffffffffffffff811115614ac957600080fd5b614ad586828701614954565b9497909650939450505050565b60008060408385031215614af557600080fd5b614afe83614077565b9150614b0c60208401614077565b90509250929050565b634e487b7160e01b600052602160045260246000fd5b60048110614b3b57614b3b614b15565b9052565b60208101610d788284614b2b565b600060208284031215614b5f57600080fd5b813567ffffffffffffffff811115614b7657600080fd5b820160a08185031215613e7357600080fd5b803563ffffffff8116811461408f57600080fd5b600060a08284031215614bae57600080fd5b614bb6613f81565b8235614bc181614062565b8152614bcf60208401614b88565b6020820152614be060408401614b88565b6040820152614bf160608401614b88565b60608201526080830135614c0481614062565b60808201529392505050565b600080600060408486031215614c2557600080fd5b833567ffffffffffffffff80821115614c3d57600080fd5b614c49878388016143fa565b94506020860135915080821115614c5f57600080fd5b50614ad586828701614996565b803560ff8116811461408f57600080fd5b600060208284031215614c8f57600080fd5b610d7582614c6c565b60008151808452602080850194506020840160005b83811015614cd25781516001600160a01b031687529582019590820190600101614cad565b509495945050505050565b60208152600082518051602084015260ff602082015116604084015260ff604082015116606084015260608101511515608084015250602083015160c060a0840152614d2c60e0840182614c98565b90506040840151601f198483030160c0850152614d498282614c98565b95945050505050565b60008060408385031215614d6557600080fd5b614d6e83614077565b946020939093013593505050565b600060208284031215614d8e57600080fd5b610d7582614077565b602081526001600160a01b03825116602082015260208201511515604082015267ffffffffffffffff60408301511660608201526000606083015160808084015261376760a0840182614904565b600060208284031215614df757600080fd5b8135613e7381614062565b600082601f830112614e1357600080fd5b81356020614e236140f48361403e565b8083825260208201915060208460051b870101935086841115614e4557600080fd5b602086015b84811015611fa7578035614e5d81614062565b8352918301918301614e4a565b60006020808385031215614e7d57600080fd5b823567ffffffffffffffff80821115614e9557600080fd5b818501915085601f830112614ea957600080fd5b8135614eb76140f48261403e565b81815260059190911b83018401908481019088831115614ed657600080fd5b8585015b8381101561423d57803585811115614ef157600080fd5b860160c0818c03601f19011215614f085760008081fd5b614f10613fa4565b8882013581526040614f23818401614c6c565b8a8301526060614f34818501614c6c565b8284015260809150614f478285016140a2565b9083015260a08381013589811115614f5f5760008081fd5b614f6d8f8d83880101614e02565b838501525060c0840135915088821115614f875760008081fd5b614f958e8c84870101614e02565b9083015250845250918601918601614eda565b634e487b7160e01b600052603260045260246000fd5b80356001600160e01b038116811461408f57600080fd5b600082601f830112614fe657600080fd5b81356020614ff66140f48361403e565b82815260069290921b8401810191818101908684111561501557600080fd5b8286015b84811015611fa757604081890312156150325760008081fd5b61503a613fc7565b61504382614077565b8152615050858301614fbe565b81860152835291830191604001615019565b600082601f83011261507357600080fd5b813560206150836140f48361403e565b82815260059290921b840181019181810190868411156150a257600080fd5b8286015b84811015611fa757803567ffffffffffffffff808211156150c75760008081fd5b9088019060a0828b03601f19018113156150e15760008081fd5b6150e9613f81565b6150f4888501614077565b81526040808501358481111561510a5760008081fd5b6151188e8b838901016140d5565b8a840152506060935061512c848601614077565b90820152608061513d858201614077565b938201939093529201359082015283529183019183016150a6565b600082601f83011261516957600080fd5b813560206151796140f48361403e565b82815260069290921b8401810191818101908684111561519857600080fd5b8286015b84811015611fa757604081890312156151b55760008081fd5b6151bd613fc7565b81358152848201358582015283529183019160400161519c565b600060208083850312156151ea57600080fd5b823567ffffffffffffffff8082111561520257600080fd5b908401906060828703121561521657600080fd5b61521e613fea565b82358281111561522d57600080fd5b8301604081890381131561524057600080fd5b615248613fc7565b82358581111561525757600080fd5b8301601f81018b1361526857600080fd5b80356152766140f48261403e565b81815260069190911b8201890190898101908d83111561529557600080fd5b928a01925b828410156152e55785848f0312156152b25760008081fd5b6152ba613fc7565b84356152c581614062565b81526152d2858d01614fbe565b818d0152825292850192908a019061529a565b8452505050828701359150848211156152fd57600080fd5b6153098a838501614fd5565b8188015283525050828401358281111561532257600080fd5b61532e88828601615062565b8583015250604083013593508184111561534757600080fd5b61535387858501615158565b60408201529695505050505050565b600082825180855260208086019550808260051b84010181860160005b848110156153f457601f19868403018952815160a067ffffffffffffffff8083511686528683015182888801526153b883880182614904565b6040858101518416908901526060808601519093169288019290925250608092830151929095019190915250978301979083019060010161537f565b5090979650505050505050565b60008151808452602080850194506020840160005b83811015614cd2578151805188528301518388015260409096019590820190600101615416565b6040815260006154506040830185615362565b8281036020840152614d498185615401565b805160408084528151848201819052600092602091908201906060870190855b818110156154b957835180516001600160a01b031684528501516001600160e01b0316858401529284019291850191600101615482565b50508583015187820388850152805180835290840192506000918401905b80831015615513578351805167ffffffffffffffff1683528501516001600160e01b0316858301529284019260019290920191908501906154d7565b50979650505050505050565b602081526000610d756020830184615462565b60006020828403121561554457600080fd5b8151613e7381614094565b634e487b7160e01b600052601160045260246000fd5b67ffffffffffffffff8181168382160190808211156155865761558661554f565b5092915050565b6020815260008251606060208401526155a96080840182615462565b90506020840151601f19808584030160408601526155c78383615362565b9250604086015191508085840301606086015250614d498282615401565b6000602082840312156155f757600080fd5b813567ffffffffffffffff81111561560e57600080fd5b61376784828501614690565b81810381811115610d7857610d7861554f565b634e487b7160e01b600052601260045260246000fd5b600067ffffffffffffffff8084168061565e5761565e61562d565b92169190910692915050565b8082028115828204841417610d7857610d7861554f565b805182526000602067ffffffffffffffff81840151168185015260408084015160a060408701526156b560a0870182614904565b9050606085015186820360608801526156ce8282614904565b608087810151898303918a01919091528051808352908601935060009250908501905b8083101561551357835180516001600160a01b03168352860151868301529285019260019290920191908401906156f1565b602081526000610d756020830184615681565b6080815260006157496080830187615681565b61ffff9590951660208301525060408101929092526001600160a01b0316606090910152919050565b60008060006060848603121561578757600080fd5b835161579281614094565b602085015190935067ffffffffffffffff8111156157af57600080fd5b8401601f810186136157c057600080fd5b80516157ce6140f4826140ad565b8181528760208385010111156157e357600080fd5b6157f48260208301602086016148e0565b809450505050604084015190509250925092565b600181811c9082168061581c57607f821691505b60208210810361583c57634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115610724576000816000526020600020601f850160051c8101602086101561586b5750805b601f850160051c820191505b8181101561588a57828155600101615877565b505050505050565b815167ffffffffffffffff8111156158ac576158ac613f42565b6158c0816158ba8454615808565b84615842565b602080601f8311600181146158f557600084156158dd5750858301515b600019600386901b1c1916600185901b17855561588a565b600085815260208120601f198616915b8281101561592457888601518255948401946001909101908401615905565b50858210156159425787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6000602080835283546001600160a01b038116602085015260ff8160a01c161515604085015267ffffffffffffffff8160a81c166060850152506001808501608080860152600081546159a481615808565b8060a089015260c060018316600081146159c557600181146159e157615a11565b60ff19841660c08b015260c083151560051b8b01019450615a11565b85600052602060002060005b84811015615a085781548c82018501529088019089016159ed565b8b0160c0019550505b50929998505050505050505050565b80820180821115610d7857610d7861554f565b60ff8181168382160190811115610d7857610d7861554f565b8183823760009101908152919050565b828152606082602083013760800192915050565b600067ffffffffffffffff80841680615a8b57615a8b61562d565b92169190910492915050565b6000808335601e19843603018112615aae57600080fd5b83018035915067ffffffffffffffff821115615ac957600080fd5b6020019150368190038213156138da57600080fd5b6020810160058310615af257615af2614b15565b91905290565b60ff81811683821602908116908181146155865761558661554f565b600060a0820160ff881683526020878185015260a0604085015281875480845260c0860191508860005282600020935060005b81811015615b6c5784546001600160a01b031683526001948501949284019201615b47565b50508481036060860152865180825290820192508187019060005b81811015615bac5782516001600160a01b031685529383019391830191600101615b87565b50505060ff85166080850152509050611fa9565b600067ffffffffffffffff808616835280851660208401525060606040830152614d496060830184614904565b8281526040602082015260006137676040830184614904565b67ffffffffffffffff848116825283166020820152606081016137676040830184614b2b565b848152615c3c6020820185614b2b565b608060408201526000615c526080830185614904565b905082606083015295945050505050565b600060208284031215615c7557600080fd5b8151613e7381614062565b6020815260008251610100806020850152615c9f610120850183614904565b91506020850151615cbc604086018267ffffffffffffffff169052565b5060408501516001600160a01b038116606086015250606085015160808501526080850151615cf660a08601826001600160a01b03169052565b5060a0850151601f19808685030160c0870152615d138483614904565b935060c08701519150808685030160e0870152615d308483614904565b935060e0870151915080868503018387015250611fa98382614904565b600060208284031215615d5f57600080fd5b5051919050565b848152600067ffffffffffffffff808616602084015280851660408401525060806060830152611fa96080830184614904565b86815260c060208201526000615db260c0830188614904565b6001600160a01b039690961660408301525067ffffffffffffffff9384166060820152608081019290925290911660a09091015292915050565b600082825180855260208086019550808260051b84010181860160005b848110156153f457601f19868403018952815160a08151818652615e2f82870182614904565b9150508582015185820387870152615e478282614904565b91505060408083015186830382880152615e618382614904565b92505050606080830151818701525060808083015192508582038187015250615e8a8183614904565b9a86019a9450505090830190600101615e09565b602081526000610d756020830184615dec565b60008282518085526020808601955060208260051b8401016020860160005b848110156153f457601f19868403018952615eec838351614904565b98840198925090830190600101615ed0565b604081526000835180516040840152602081015167ffffffffffffffff80821660608601528060408401511660808601528060608401511660a08601528060808401511660c086015250505060208401516101408060e0850152615f66610180850183614904565b91506040860151603f198086850301610100870152615f858483614904565b935060608801519150615fa46101208701836001600160a01b03169052565b60808801518387015260a0880151925080868503016101608701525050615fcb8282615dec565b9150508281036020840152614d498185615eb156fea164736f6c6343000818000a", } var OffRampABI = OffRampMetaData.ABI @@ -2406,7 +2406,7 @@ func (OffRampAlreadyAttempted) Topic() common.Hash { } func (OffRampCommitReportAccepted) Topic() common.Hash { - return common.HexToHash("0xd7868a16facbdde7b5c020620136316b3c266fffcb4e1e41cb6a662fe14ba3e1") + return common.HexToHash("0x23bc80217a08968cec0790cd045b396fa7eea0a21af469e603329940b883d86d") } func (OffRampConfigSet) Topic() common.Hash { diff --git a/core/gethwrappers/ccip/generated/report_codec/report_codec.go b/core/gethwrappers/ccip/generated/report_codec/report_codec.go index 29333984cc..03c190690f 100644 --- a/core/gethwrappers/ccip/generated/report_codec/report_codec.go +++ b/core/gethwrappers/ccip/generated/report_codec/report_codec.go @@ -59,10 +59,10 @@ type InternalGasPriceUpdate struct { type InternalMerkleRoot struct { SourceChainSelector uint64 + OnRampAddress []byte MinSeqNr uint64 MaxSeqNr uint64 MerkleRoot [32]byte - OnRampAddress []byte } type InternalPriceUpdates struct { @@ -98,8 +98,8 @@ type OffRampCommitReport struct { } var ReportCodecMetaData = &bind.MetaData{ - ABI: "[{\"anonymous\":false,\"inputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"structIRMNV2.Signature[]\",\"name\":\"rmnSignatures\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"report\",\"type\":\"tuple\"}],\"name\":\"CommitReportDecoded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage[]\",\"name\":\"messages\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[][]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[][]\"},{\"internalType\":\"bytes32[]\",\"name\":\"proofs\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"proofFlagBits\",\"type\":\"uint256\"}],\"indexed\":false,\"internalType\":\"structInternal.ExecutionReportSingleChain[]\",\"name\":\"report\",\"type\":\"tuple[]\"}],\"name\":\"ExecuteReportDecoded\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"decodeCommitReport\",\"outputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"structIRMNV2.Signature[]\",\"name\":\"rmnSignatures\",\"type\":\"tuple[]\"}],\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"decodeExecuteReport\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage[]\",\"name\":\"messages\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[][]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[][]\"},{\"internalType\":\"bytes32[]\",\"name\":\"proofs\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"proofFlagBits\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.ExecutionReportSingleChain[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]", - Bin: "0x608060405234801561001057600080fd5b506113e6806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80636fb349561461003b578063f816ec6014610064575b600080fd5b61004e610049366004610231565b610084565b60405161005b91906104f2565b60405180910390f35b610077610072366004610231565b6100a0565b60405161005b9190610835565b60608180602001905181019061009a9190610e8d565b92915050565b6040805160a08101825260608082018181526080830182905282526020808301829052928201528251909161009a9184018101908401611250565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff8111828210171561012d5761012d6100db565b60405290565b60405160c0810167ffffffffffffffff8111828210171561012d5761012d6100db565b6040805190810167ffffffffffffffff8111828210171561012d5761012d6100db565b6040516060810167ffffffffffffffff8111828210171561012d5761012d6100db565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156101e3576101e36100db565b604052919050565b600067ffffffffffffffff821115610205576102056100db565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b60006020828403121561024357600080fd5b813567ffffffffffffffff81111561025a57600080fd5b8201601f8101841361026b57600080fd5b803561027e610279826101eb565b61019c565b81815285602083850101111561029357600080fd5b81602084016020830137600091810160200191909152949350505050565b60005b838110156102cc5781810151838201526020016102b4565b50506000910152565b600081518084526102ed8160208601602086016102b1565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b600082825180855260208086019550808260051b84010181860160005b848110156103ef577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018952815160a08151818652610380828701826102d5565b915050858201518582038787015261039882826102d5565b915050604080830151868303828801526103b283826102d5565b925050506060808301518187015250608080830151925085820381870152506103db81836102d5565b9a86019a945050509083019060010161033c565b5090979650505050505050565b6000828251808552602080860195506005818360051b8501018287016000805b868110156104a7577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe088850381018c5283518051808752908801908887019080891b88018a01865b8281101561049057858a830301845261047e8286516102d5565b948c0194938c01939150600101610464565b509e8a019e9750505093870193505060010161041c565b50919998505050505050505050565b60008151808452602080850194506020840160005b838110156104e7578151875295820195908201906001016104cb565b509495945050505050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b828110156106da577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0888603018452815160a0860167ffffffffffffffff8083511688528883015160a08a8a015282815180855260c08b01915060c08160051b8c010194508b8301925060005b81811015610683577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff408c87030183528351805180518852868f820151168f890152866040820151166040890152866060820151166060890152866080820151166080890152508d81015161014060a08901526106066101408901826102d5565b9050604082015188820360c08a015261061f82826102d5565b915050606082015161064960e08a018273ffffffffffffffffffffffffffffffffffffffff169052565b50608082015161010089015260a0820151915087810361012089015261066f818361031f565b97505050928c0192918c0191600101610586565b50505050506040820151878203604089015261069f82826103fc565b915050606082015187820360608901526106b982826104b6565b60809384015198909301979097525094509285019290850190600101610519565b5092979650505050505050565b60008151808452602080850194506020840160005b838110156104e7578151805167ffffffffffffffff1688528301517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1683880152604090960195908201906001016106fc565b600082825180855260208086019550808260051b84010181860160005b848110156103ef578583037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00189528151805167ffffffffffffffff908116855285820151811686860152604080830151909116908501526060808201519085015260809081015160a0918501829052906107e5818601836102d5565b9a86019a9450505090830190600101610768565b60008151808452602080850194506020840160005b838110156104e757815180518852830151838801526040909601959082019060010161080e565b602080825282516060838301528051604060808501819052815160c086018190526000949392840191859160e08801905b808410156108c3578451805173ffffffffffffffffffffffffffffffffffffffff1683528701517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1687830152938601936001939093019290820190610866565b50938501518785037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff800160a0890152936108fd81866106e7565b9450505050508185015191507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08085830301604086015261093e828461074b565b925060408601519150808584030160608601525061095c82826107f9565b95945050505050565b600067ffffffffffffffff82111561097f5761097f6100db565b5060051b60200190565b805167ffffffffffffffff811681146109a157600080fd5b919050565b600060a082840312156109b857600080fd5b6109c061010a565b9050815181526109d260208301610989565b60208201526109e360408301610989565b60408201526109f460608301610989565b6060820152610a0560808301610989565b608082015292915050565b600082601f830112610a2157600080fd5b8151610a2f610279826101eb565b818152846020838601011115610a4457600080fd5b610a558260208301602087016102b1565b949350505050565b805173ffffffffffffffffffffffffffffffffffffffff811681146109a157600080fd5b600082601f830112610a9257600080fd5b81516020610aa261027983610965565b82815260059290921b84018101918181019086841115610ac157600080fd5b8286015b84811015610bdb57805167ffffffffffffffff80821115610ae65760008081fd5b818901915060a0807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848d03011215610b1f5760008081fd5b610b2761010a565b8784015183811115610b395760008081fd5b610b478d8a83880101610a10565b82525060408085015184811115610b5e5760008081fd5b610b6c8e8b83890101610a10565b8a8401525060608086015185811115610b855760008081fd5b610b938f8c838a0101610a10565b83850152506080915081860151818401525082850151925083831115610bb95760008081fd5b610bc78d8a85880101610a10565b908201528652505050918301918301610ac5565b509695505050505050565b600082601f830112610bf757600080fd5b81516020610c0761027983610965565b82815260059290921b84018101918181019086841115610c2657600080fd5b8286015b84811015610bdb57805167ffffffffffffffff80821115610c4b5760008081fd5b8189019150610140807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848d03011215610c855760008081fd5b610c8d610133565b610c998c8986016109a6565b815260c084015183811115610cae5760008081fd5b610cbc8d8a83880101610a10565b898301525060e084015183811115610cd45760008081fd5b610ce28d8a83880101610a10565b604083015250610cf56101008501610a5d565b60608201526101208401516080820152908301519082821115610d185760008081fd5b610d268c8984870101610a81565b60a08201528652505050918301918301610c2a565b600082601f830112610d4c57600080fd5b81516020610d5c61027983610965565b82815260059290921b84018101918181019086841115610d7b57600080fd5b8286015b84811015610bdb57805167ffffffffffffffff80821115610d9f57600080fd5b818901915089603f830112610db357600080fd5b85820151610dc361027982610965565b81815260059190911b830160400190878101908c831115610de357600080fd5b604085015b83811015610e1c57805185811115610dff57600080fd5b610e0e8f6040838a0101610a10565b845250918901918901610de8565b50875250505092840192508301610d7f565b600082601f830112610e3f57600080fd5b81516020610e4f61027983610965565b8083825260208201915060208460051b870101935086841115610e7157600080fd5b602086015b84811015610bdb5780518352918301918301610e76565b60006020808385031215610ea057600080fd5b825167ffffffffffffffff80821115610eb857600080fd5b818501915085601f830112610ecc57600080fd5b8151610eda61027982610965565b81815260059190911b83018401908481019088831115610ef957600080fd5b8585015b83811015610ff357805185811115610f1457600080fd5b860160a0818c037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0011215610f495760008081fd5b610f5161010a565b610f5c898301610989565b815260408083015188811115610f725760008081fd5b610f808e8c83870101610be6565b8b8401525060608084015189811115610f995760008081fd5b610fa78f8d83880101610d3b565b8385015250608091508184015189811115610fc25760008081fd5b610fd08f8d83880101610e2e565b918401919091525060a09290920151918101919091528352918601918601610efd565b5098975050505050505050565b80517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811681146109a157600080fd5b600082601f83011261103d57600080fd5b8151602061104d61027983610965565b82815260069290921b8401810191818101908684111561106c57600080fd5b8286015b84811015610bdb57604081890312156110895760008081fd5b611091610156565b61109a82610989565b81526110a7858301611000565b81860152835291830191604001611070565b600082601f8301126110ca57600080fd5b815160206110da61027983610965565b82815260059290921b840181019181810190868411156110f957600080fd5b8286015b84811015610bdb57805167ffffffffffffffff8082111561111e5760008081fd5b818901915060a0807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848d030112156111575760008081fd5b61115f61010a565b61116a888501610989565b81526040611179818601610989565b89830152606061118a818701610989565b8284015260809150818601518184015250828501519250838311156111af5760008081fd5b6111bd8d8a85880101610a10565b9082015286525050509183019183016110fd565b600082601f8301126111e257600080fd5b815160206111f261027983610965565b82815260069290921b8401810191818101908684111561121157600080fd5b8286015b84811015610bdb576040818903121561122e5760008081fd5b611236610156565b815181528482015185820152835291830191604001611215565b6000602080838503121561126357600080fd5b825167ffffffffffffffff8082111561127b57600080fd5b908401906060828703121561128f57600080fd5b611297610179565b8251828111156112a657600080fd5b830160408189038113156112b957600080fd5b6112c1610156565b8251858111156112d057600080fd5b8301601f81018b136112e157600080fd5b80516112ef61027982610965565b81815260069190911b8201890190898101908d83111561130e57600080fd5b928a01925b8284101561135c5785848f03121561132b5760008081fd5b611333610156565b61133c85610a5d565b81526113498c8601611000565b818d0152825292850192908a0190611313565b84525050508287015191508482111561137457600080fd5b6113808a83850161102c565b8188015283525050828401518281111561139957600080fd5b6113a5888286016110b9565b858301525060408301519350818411156113be57600080fd5b6113ca878585016111d1565b6040820152969550505050505056fea164736f6c6343000818000a", + ABI: "[{\"anonymous\":false,\"inputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"structIRMNV2.Signature[]\",\"name\":\"rmnSignatures\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"report\",\"type\":\"tuple\"}],\"name\":\"CommitReportDecoded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage[]\",\"name\":\"messages\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[][]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[][]\"},{\"internalType\":\"bytes32[]\",\"name\":\"proofs\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"proofFlagBits\",\"type\":\"uint256\"}],\"indexed\":false,\"internalType\":\"structInternal.ExecutionReportSingleChain[]\",\"name\":\"report\",\"type\":\"tuple[]\"}],\"name\":\"ExecuteReportDecoded\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"decodeCommitReport\",\"outputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"structIRMNV2.Signature[]\",\"name\":\"rmnSignatures\",\"type\":\"tuple[]\"}],\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"decodeExecuteReport\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage[]\",\"name\":\"messages\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[][]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[][]\"},{\"internalType\":\"bytes32[]\",\"name\":\"proofs\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"proofFlagBits\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.ExecutionReportSingleChain[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]", + Bin: "0x608060405234801561001057600080fd5b506113e5806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80636fb349561461003b578063f816ec6014610064575b600080fd5b61004e610049366004610231565b610084565b60405161005b91906104f2565b60405180910390f35b610077610072366004610231565b6100a0565b60405161005b9190610837565b60608180602001905181019061009a9190610e8f565b92915050565b6040805160a08101825260608082018181526080830182905282526020808301829052928201528251909161009a918401810190840161124f565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff8111828210171561012d5761012d6100db565b60405290565b60405160c0810167ffffffffffffffff8111828210171561012d5761012d6100db565b6040805190810167ffffffffffffffff8111828210171561012d5761012d6100db565b6040516060810167ffffffffffffffff8111828210171561012d5761012d6100db565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156101e3576101e36100db565b604052919050565b600067ffffffffffffffff821115610205576102056100db565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b60006020828403121561024357600080fd5b813567ffffffffffffffff81111561025a57600080fd5b8201601f8101841361026b57600080fd5b803561027e610279826101eb565b61019c565b81815285602083850101111561029357600080fd5b81602084016020830137600091810160200191909152949350505050565b60005b838110156102cc5781810151838201526020016102b4565b50506000910152565b600081518084526102ed8160208601602086016102b1565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b600082825180855260208086019550808260051b84010181860160005b848110156103ef577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018952815160a08151818652610380828701826102d5565b915050858201518582038787015261039882826102d5565b915050604080830151868303828801526103b283826102d5565b925050506060808301518187015250608080830151925085820381870152506103db81836102d5565b9a86019a945050509083019060010161033c565b5090979650505050505050565b6000828251808552602080860195506005818360051b8501018287016000805b868110156104a7577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe088850381018c5283518051808752908801908887019080891b88018a01865b8281101561049057858a830301845261047e8286516102d5565b948c0194938c01939150600101610464565b509e8a019e9750505093870193505060010161041c565b50919998505050505050505050565b60008151808452602080850194506020840160005b838110156104e7578151875295820195908201906001016104cb565b509495945050505050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b828110156106da577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0888603018452815160a0860167ffffffffffffffff8083511688528883015160a08a8a015282815180855260c08b01915060c08160051b8c010194508b8301925060005b81811015610683577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff408c87030183528351805180518852868f820151168f890152866040820151166040890152866060820151166060890152866080820151166080890152508d81015161014060a08901526106066101408901826102d5565b9050604082015188820360c08a015261061f82826102d5565b915050606082015161064960e08a018273ffffffffffffffffffffffffffffffffffffffff169052565b50608082015161010089015260a0820151915087810361012089015261066f818361031f565b97505050928c0192918c0191600101610586565b50505050506040820151878203604089015261069f82826103fc565b915050606082015187820360608901526106b982826104b6565b60809384015198909301979097525094509285019290850190600101610519565b5092979650505050505050565b60008151808452602080850194506020840160005b838110156104e7578151805167ffffffffffffffff1688528301517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1683880152604090960195908201906001016106fc565b600082825180855260208086019550808260051b84010181860160005b848110156103ef577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018952815160a067ffffffffffffffff8083511686528683015182888801526107bf838801826102d5565b60408581015184169089015260608086015190931692880192909252506080928301519290950191909152509783019790830190600101610768565b60008151808452602080850194506020840160005b838110156104e7578151805188528301518388015260409096019590820190600101610810565b602080825282516060838301528051604060808501819052815160c086018190526000949392840191859160e08801905b808410156108c5578451805173ffffffffffffffffffffffffffffffffffffffff1683528701517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1687830152938601936001939093019290820190610868565b50938501518785037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff800160a0890152936108ff81866106e7565b9450505050508185015191507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe080858303016040860152610940828461074b565b925060408601519150808584030160608601525061095e82826107fb565b95945050505050565b600067ffffffffffffffff821115610981576109816100db565b5060051b60200190565b805167ffffffffffffffff811681146109a357600080fd5b919050565b600060a082840312156109ba57600080fd5b6109c261010a565b9050815181526109d46020830161098b565b60208201526109e56040830161098b565b60408201526109f66060830161098b565b6060820152610a076080830161098b565b608082015292915050565b600082601f830112610a2357600080fd5b8151610a31610279826101eb565b818152846020838601011115610a4657600080fd5b610a578260208301602087016102b1565b949350505050565b805173ffffffffffffffffffffffffffffffffffffffff811681146109a357600080fd5b600082601f830112610a9457600080fd5b81516020610aa461027983610967565b82815260059290921b84018101918181019086841115610ac357600080fd5b8286015b84811015610bdd57805167ffffffffffffffff80821115610ae85760008081fd5b818901915060a0807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848d03011215610b215760008081fd5b610b2961010a565b8784015183811115610b3b5760008081fd5b610b498d8a83880101610a12565b82525060408085015184811115610b605760008081fd5b610b6e8e8b83890101610a12565b8a8401525060608086015185811115610b875760008081fd5b610b958f8c838a0101610a12565b83850152506080915081860151818401525082850151925083831115610bbb5760008081fd5b610bc98d8a85880101610a12565b908201528652505050918301918301610ac7565b509695505050505050565b600082601f830112610bf957600080fd5b81516020610c0961027983610967565b82815260059290921b84018101918181019086841115610c2857600080fd5b8286015b84811015610bdd57805167ffffffffffffffff80821115610c4d5760008081fd5b8189019150610140807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848d03011215610c875760008081fd5b610c8f610133565b610c9b8c8986016109a8565b815260c084015183811115610cb05760008081fd5b610cbe8d8a83880101610a12565b898301525060e084015183811115610cd65760008081fd5b610ce48d8a83880101610a12565b604083015250610cf76101008501610a5f565b60608201526101208401516080820152908301519082821115610d1a5760008081fd5b610d288c8984870101610a83565b60a08201528652505050918301918301610c2c565b600082601f830112610d4e57600080fd5b81516020610d5e61027983610967565b82815260059290921b84018101918181019086841115610d7d57600080fd5b8286015b84811015610bdd57805167ffffffffffffffff80821115610da157600080fd5b818901915089603f830112610db557600080fd5b85820151610dc561027982610967565b81815260059190911b830160400190878101908c831115610de557600080fd5b604085015b83811015610e1e57805185811115610e0157600080fd5b610e108f6040838a0101610a12565b845250918901918901610dea565b50875250505092840192508301610d81565b600082601f830112610e4157600080fd5b81516020610e5161027983610967565b8083825260208201915060208460051b870101935086841115610e7357600080fd5b602086015b84811015610bdd5780518352918301918301610e78565b60006020808385031215610ea257600080fd5b825167ffffffffffffffff80821115610eba57600080fd5b818501915085601f830112610ece57600080fd5b8151610edc61027982610967565b81815260059190911b83018401908481019088831115610efb57600080fd5b8585015b83811015610ff557805185811115610f1657600080fd5b860160a0818c037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0011215610f4b5760008081fd5b610f5361010a565b610f5e89830161098b565b815260408083015188811115610f745760008081fd5b610f828e8c83870101610be8565b8b8401525060608084015189811115610f9b5760008081fd5b610fa98f8d83880101610d3d565b8385015250608091508184015189811115610fc45760008081fd5b610fd28f8d83880101610e30565b918401919091525060a09290920151918101919091528352918601918601610eff565b5098975050505050505050565b80517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811681146109a357600080fd5b600082601f83011261103f57600080fd5b8151602061104f61027983610967565b82815260069290921b8401810191818101908684111561106e57600080fd5b8286015b84811015610bdd576040818903121561108b5760008081fd5b611093610156565b61109c8261098b565b81526110a9858301611002565b81860152835291830191604001611072565b600082601f8301126110cc57600080fd5b815160206110dc61027983610967565b82815260059290921b840181019181810190868411156110fb57600080fd5b8286015b84811015610bdd57805167ffffffffffffffff808211156111205760008081fd5b818901915060a0807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848d030112156111595760008081fd5b61116161010a565b61116c88850161098b565b8152604080850151848111156111825760008081fd5b6111908e8b83890101610a12565b8a84015250606093506111a484860161098b565b9082015260806111b585820161098b565b938201939093529201519082015283529183019183016110ff565b600082601f8301126111e157600080fd5b815160206111f161027983610967565b82815260069290921b8401810191818101908684111561121057600080fd5b8286015b84811015610bdd576040818903121561122d5760008081fd5b611235610156565b815181528482015185820152835291830191604001611214565b6000602080838503121561126257600080fd5b825167ffffffffffffffff8082111561127a57600080fd5b908401906060828703121561128e57600080fd5b611296610179565b8251828111156112a557600080fd5b830160408189038113156112b857600080fd5b6112c0610156565b8251858111156112cf57600080fd5b8301601f81018b136112e057600080fd5b80516112ee61027982610967565b81815260069190911b8201890190898101908d83111561130d57600080fd5b928a01925b8284101561135b5785848f03121561132a5760008081fd5b611332610156565b61133b85610a5f565b81526113488c8601611002565b818d0152825292850192908a0190611312565b84525050508287015191508482111561137357600080fd5b61137f8a83850161102e565b8188015283525050828401518281111561139857600080fd5b6113a4888286016110bb565b858301525060408301519350818411156113bd57600080fd5b6113c9878585016111d0565b6040820152969550505050505056fea164736f6c6343000818000a", } var ReportCodecABI = ReportCodecMetaData.ABI @@ -529,7 +529,7 @@ func (_ReportCodec *ReportCodec) ParseLog(log types.Log) (generated.AbigenLog, e } func (ReportCodecCommitReportDecoded) Topic() common.Hash { - return common.HexToHash("0x83099d210b303f78572f4da1af1d1777cbf80cae42cdb9381f310dbdf21e8f89") + return common.HexToHash("0x31a4e1cb25733cdb9679561cd59cdc238d70a7d486f8bfc1f13242efd60fc29d") } func (ReportCodecExecuteReportDecoded) Topic() common.Hash { diff --git a/core/gethwrappers/ccip/generated/rmn_remote/rmn_remote.go b/core/gethwrappers/ccip/generated/rmn_remote/rmn_remote.go index a380d77e10..bf210e2eb1 100644 --- a/core/gethwrappers/ccip/generated/rmn_remote/rmn_remote.go +++ b/core/gethwrappers/ccip/generated/rmn_remote/rmn_remote.go @@ -37,10 +37,10 @@ type IRMNV2Signature struct { type InternalMerkleRoot struct { SourceChainSelector uint64 + OnRampAddress []byte MinSeqNr uint64 MaxSeqNr uint64 MerkleRoot [32]byte - OnRampAddress []byte } type RMNRemoteConfig struct { @@ -60,8 +60,8 @@ type RMNRemoteVersionedConfig struct { } var RMNRemoteMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"ConfigNotSet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateOnchainPublicKey\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSignature\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSignerOrder\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MinSignersTooHigh\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OutOfOrderSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ThresholdNotMet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnexpectedSigner\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"rmnHomeContractConfigDigest\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"onchainPublicKey\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"nodeIndex\",\"type\":\"uint64\"}],\"internalType\":\"structRMNRemote.Signer[]\",\"name\":\"signers\",\"type\":\"tuple[]\"},{\"internalType\":\"uint64\",\"name\":\"minSigners\",\"type\":\"uint64\"}],\"internalType\":\"structRMNRemote.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"indexed\":false,\"internalType\":\"structRMNRemote.VersionedConfig\",\"name\":\"versionedConfig\",\"type\":\"tuple\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getVersionedConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"rmnHomeContractConfigDigest\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"onchainPublicKey\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"nodeIndex\",\"type\":\"uint64\"}],\"internalType\":\"structRMNRemote.Signer[]\",\"name\":\"signers\",\"type\":\"tuple[]\"},{\"internalType\":\"uint64\",\"name\":\"minSigners\",\"type\":\"uint64\"}],\"internalType\":\"structRMNRemote.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"internalType\":\"structRMNRemote.VersionedConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes16\",\"name\":\"subject\",\"type\":\"bytes16\"}],\"name\":\"isCursed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isCursed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"rmnHomeContractConfigDigest\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"onchainPublicKey\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"nodeIndex\",\"type\":\"uint64\"}],\"internalType\":\"structRMNRemote.Signer[]\",\"name\":\"signers\",\"type\":\"tuple[]\"},{\"internalType\":\"uint64\",\"name\":\"minSigners\",\"type\":\"uint64\"}],\"internalType\":\"structRMNRemote.Config\",\"name\":\"newConfig\",\"type\":\"tuple\"}],\"name\":\"setConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"test\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"destLaneUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"structIRMNV2.Signature[]\",\"name\":\"signatures\",\"type\":\"tuple[]\"}],\"name\":\"verify\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x60a06040523480156200001157600080fd5b506040516200182d3803806200182d83398101604081905262000034916200017e565b33806000816200008b5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000be57620000be81620000d3565b5050506001600160401b0316608052620001b0565b336001600160a01b038216036200012d5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000082565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000602082840312156200019157600080fd5b81516001600160401b0381168114620001a957600080fd5b9392505050565b608051611664620001c9600039600050506116646000f3fe608060405234801561001057600080fd5b50600436106100be5760003560e01c8063397796f7116100765780638da5cb5b1161005b5780638da5cb5b14610184578063f2fde38b146101ac578063f8a8fd6d1461012857600080fd5b8063397796f71461017557806379ba50971461017c57600080fd5b80631add205f116100a75780631add205f1461012a5780632cbc26bb1461013f57806330dfc3081461016357600080fd5b8063181f5a77146100c3578063198f0f7714610115575b600080fd5b6100ff6040518060400160405280601381526020017f524d4e52656d6f746520312e362e302d6465760000000000000000000000000081525081565b60405161010c9190610c4b565b60405180910390f35b610128610123366004610c65565b6101bf565b005b6101326105f0565b60405161010c9190610ca0565b61015361014d366004610d58565b50600090565b604051901515815260200161010c565b610128610171366004610f60565b5050565b6000610153565b61012861090b565b60005460405173ffffffffffffffffffffffffffffffffffffffff909116815260200161010c565b6101286101ba36600461113d565b610a0d565b6101c7610a23565b60015b6101d7602083018361115a565b90508110156102a7576101ed602083018361115a565b828181106101fd576101fd6111c9565b905060400201602001602081019061021591906111f8565b67ffffffffffffffff1661022c602084018461115a565b610237600185611244565b818110610246576102466111c9565b905060400201602001602081019061025e91906111f8565b67ffffffffffffffff161061029f576040517f4485151700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001016101ca565b506102b5602082018261115a565b90506102c760608301604084016111f8565b67ffffffffffffffff161115610309576040517ffba0d9e600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60025b60018101541561040557600180820180546006926000929161032e9190611244565b8154811061033e5761033e6111c9565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055600181018054806103a8576103a861125d565b60008281526020902081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffff0000000000000000000000000000000000000000000000000000000016905501905561030c565b5060005b610416602083018361115a565b905081101561054b5760066000610430602085018561115a565b84818110610440576104406111c9565b610456926020604090920201908101915061113d565b73ffffffffffffffffffffffffffffffffffffffff16815260208101919091526040016000205460ff16156104b7576040517f28cae27d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600660006104ca602086018661115a565b858181106104da576104da6111c9565b6104f0926020604090920201908101915061113d565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055600101610409565b508060026105598282611345565b5050600580546000919082906105749063ffffffff16611480565b91906101000a81548163ffffffff021916908363ffffffff160217905590507f6cc65868ae41a007e6c3ed18ce591c123dd4e5864b421888c68ce92dae98cea460405180604001604052808363ffffffff168152602001846105d5906114a3565b90526040516105e49190610ca0565b60405180910390a15050565b6105f8610b99565b60408051808201825260055463ffffffff1681528151606081018352600280548252600380548551602082810282018101909752818152949580870195858201939092909160009084015b828210156106b1576000848152602090819020604080518082019091529084015473ffffffffffffffffffffffffffffffffffffffff8116825274010000000000000000000000000000000000000000900467ffffffffffffffff1681830152825260019092019101610643565b505050908252506002919091015467ffffffffffffffff166020909101529052919050565b84518110156108bd5760008582815181106106f3576106f36111c9565b602002602001015190506000600186601b8460000151856020015160405160008152602001604052604051610744949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015610766573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff81166107de576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1610610843576040517fbbe15e7f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff811660009081526006602052604090205460ff166108a2576040517faaaa914100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b9250826108ae8561161f565b945050508060010190506106d6565b5060045467ffffffffffffffff16821015610904576040517f59fa4a9300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610991576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610a15610a23565b610a1e81610aa4565b50565b565b60005473ffffffffffffffffffffffffffffffffffffffff163314610a21576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610988565b3373ffffffffffffffffffffffffffffffffffffffff821603610b23576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610988565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6040518060400160405280600063ffffffff168152602001610be260405180606001604052806000801916815260200160608152602001600067ffffffffffffffff1681525090565b905290565b6000815180845260005b81811015610c0d57602081850181015186830182015201610bf1565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000610c5e6020830184610be7565b9392505050565b600060208284031215610c7757600080fd5b813567ffffffffffffffff811115610c8e57600080fd5b820160608185031215610c5e57600080fd5b6000602080835263ffffffff8451168184015280840151604080604086015260c0850182516060870152838301516060608088015281815180845260e0890191508683019350600092505b80831015610d34578351805173ffffffffffffffffffffffffffffffffffffffff16835287015167ffffffffffffffff1687830152928601926001929092019190840190610ceb565b50604085015167ffffffffffffffff811660a08a0152955098975050505050505050565b600060208284031215610d6a57600080fd5b81357fffffffffffffffffffffffffffffffff0000000000000000000000000000000081168114610c5e57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715610dec57610dec610d9a565b60405290565b60405160a0810167ffffffffffffffff81118282101715610dec57610dec610d9a565b6040516060810167ffffffffffffffff81118282101715610dec57610dec610d9a565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715610e7f57610e7f610d9a565b604052919050565b600067ffffffffffffffff821115610ea157610ea1610d9a565b5060051b60200190565b67ffffffffffffffff81168114610a1e57600080fd5b8035610ecc81610eab565b919050565b600082601f830112610ee257600080fd5b81356020610ef7610ef283610e87565b610e38565b82815260069290921b84018101918181019086841115610f1657600080fd5b8286015b84811015610f555760408189031215610f335760008081fd5b610f3b610dc9565b813581528482013585820152835291830191604001610f1a565b509695505050505050565b60008060408385031215610f7357600080fd5b823567ffffffffffffffff80821115610f8b57600080fd5b818501915085601f830112610f9f57600080fd5b81356020610faf610ef283610e87565b82815260059290921b84018101918181019089841115610fce57600080fd5b8286015b848110156110ed57803586811115610fe957600080fd5b87017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe060a0828e038201121561101e57600080fd5b611026610df2565b8683013561103381610eab565b8152604083013561104381610eab565b81880152606083013561105581610eab565b60408201526080830135606082015260a08301358981111561107657600080fd5b8084019350508d603f84011261108b57600080fd5b868301358981111561109f5761109f610d9a565b6110af8884601f84011601610e38565b92508083528e60408286010111156110c657600080fd5b80604085018985013760009083018801526080810191909152845250918301918301610fd2565b509650508601359250508082111561110457600080fd5b5061111185828601610ed1565b9150509250929050565b73ffffffffffffffffffffffffffffffffffffffff81168114610a1e57600080fd5b60006020828403121561114f57600080fd5b8135610c5e8161111b565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261118f57600080fd5b83018035915067ffffffffffffffff8211156111aa57600080fd5b6020019150600681901b36038213156111c257600080fd5b9250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561120a57600080fd5b8135610c5e81610eab565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8181038181111561125757611257611215565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b6000813561125781610eab565b81356112a48161111b565b73ffffffffffffffffffffffffffffffffffffffff811690508154817fffffffffffffffffffffffff0000000000000000000000000000000000000000821617835560208401356112f481610eab565b7bffffffffffffffff00000000000000000000000000000000000000008160a01b16837fffffffff000000000000000000000000000000000000000000000000000000008416171784555050505050565b81358155600180820160208401357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe185360301811261138357600080fd5b8401803567ffffffffffffffff81111561139c57600080fd5b6020820191508060061b36038213156113b457600080fd5b680100000000000000008111156113cd576113cd610d9a565b825481845580821015611402576000848152602081208381019083015b808210156113fe57828255908701906113ea565b5050505b50600092835260208320925b81811015611432576114208385611299565b9284019260409290920191840161140e565b50505050506101716114466040840161128c565b6002830167ffffffffffffffff82167fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000008254161781555050565b600063ffffffff80831681810361149957611499611215565b6001019392505050565b6000606082360312156114b557600080fd5b6114bd610e15565b8235815260208084013567ffffffffffffffff8111156114dc57600080fd5b840136601f8201126114ed57600080fd5b80356114fb610ef282610e87565b81815260069190911b8201830190838101903683111561151a57600080fd5b928401925b8284101561157057604084360312156115385760008081fd5b611540610dc9565b843561154b8161111b565b81528486013561155a81610eab565b818701528252604093909301929084019061151f565b8085870152505050505061158660408401610ec1565b604082015292915050565b8181101561160c578c89037ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee00184528751805187168a528a81015187168b8b01528b81015187168c8b015287810151888b0152850151858a018490526115f9848b0182610be7565b9950509689019692890192600101611591565b50969d9c50505050505050505050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361165057611650611215565b506001019056fea164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"ConfigNotSet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateOnchainPublicKey\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSignature\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSignerOrder\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MinSignersTooHigh\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OutOfOrderSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ThresholdNotMet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnexpectedSigner\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"rmnHomeContractConfigDigest\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"onchainPublicKey\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"nodeIndex\",\"type\":\"uint64\"}],\"internalType\":\"structRMNRemote.Signer[]\",\"name\":\"signers\",\"type\":\"tuple[]\"},{\"internalType\":\"uint64\",\"name\":\"minSigners\",\"type\":\"uint64\"}],\"internalType\":\"structRMNRemote.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"indexed\":false,\"internalType\":\"structRMNRemote.VersionedConfig\",\"name\":\"versionedConfig\",\"type\":\"tuple\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getVersionedConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"rmnHomeContractConfigDigest\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"onchainPublicKey\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"nodeIndex\",\"type\":\"uint64\"}],\"internalType\":\"structRMNRemote.Signer[]\",\"name\":\"signers\",\"type\":\"tuple[]\"},{\"internalType\":\"uint64\",\"name\":\"minSigners\",\"type\":\"uint64\"}],\"internalType\":\"structRMNRemote.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"internalType\":\"structRMNRemote.VersionedConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes16\",\"name\":\"subject\",\"type\":\"bytes16\"}],\"name\":\"isCursed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isCursed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"rmnHomeContractConfigDigest\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"onchainPublicKey\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"nodeIndex\",\"type\":\"uint64\"}],\"internalType\":\"structRMNRemote.Signer[]\",\"name\":\"signers\",\"type\":\"tuple[]\"},{\"internalType\":\"uint64\",\"name\":\"minSigners\",\"type\":\"uint64\"}],\"internalType\":\"structRMNRemote.Config\",\"name\":\"newConfig\",\"type\":\"tuple\"}],\"name\":\"setConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"test\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"destLaneUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"structIRMNV2.Signature[]\",\"name\":\"signatures\",\"type\":\"tuple[]\"}],\"name\":\"verify\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x60a06040523480156200001157600080fd5b50604051620018293803806200182983398101604081905262000034916200017e565b33806000816200008b5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000be57620000be81620000d3565b5050506001600160401b0316608052620001b0565b336001600160a01b038216036200012d5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000082565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000602082840312156200019157600080fd5b81516001600160401b0381168114620001a957600080fd5b9392505050565b608051611660620001c9600039600050506116606000f3fe608060405234801561001057600080fd5b50600436106100be5760003560e01c806379ba509711610076578063ccd5af001161005b578063ccd5af001461019a578063f2fde38b146101ac578063f8a8fd6d1461012857600080fd5b806379ba50971461016a5780638da5cb5b1461017257600080fd5b80631add205f116100a75780631add205f1461012a5780632cbc26bb1461013f578063397796f71461016357600080fd5b8063181f5a77146100c3578063198f0f7714610115575b600080fd5b6100ff6040518060400160405280601381526020017f524d4e52656d6f746520312e362e302d6465760000000000000000000000000081525081565b60405161010c9190610c4b565b60405180910390f35b610128610123366004610c65565b6101bf565b005b6101326105f0565b60405161010c9190610ca0565b61015361014d366004610d58565b50600090565b604051901515815260200161010c565b6000610153565b6101286106d6565b60005460405173ffffffffffffffffffffffffffffffffffffffff909116815260200161010c565b6101286101a8366004610f60565b5050565b6101286101ba366004611137565b610a0d565b6101c7610a23565b60015b6101d76020830183611154565b90508110156102a7576101ed6020830183611154565b828181106101fd576101fd6111c3565b905060400201602001602081019061021591906111f2565b67ffffffffffffffff1661022c6020840184611154565b61023760018561123e565b818110610246576102466111c3565b905060400201602001602081019061025e91906111f2565b67ffffffffffffffff161061029f576040517f4485151700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001016101ca565b506102b56020820182611154565b90506102c760608301604084016111f2565b67ffffffffffffffff161115610309576040517ffba0d9e600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60025b60018101541561040557600180820180546006926000929161032e919061123e565b8154811061033e5761033e6111c3565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055600181018054806103a8576103a8611257565b60008281526020902081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffff0000000000000000000000000000000000000000000000000000000016905501905561030c565b5060005b6104166020830183611154565b905081101561054b57600660006104306020850185611154565b84818110610440576104406111c3565b6104569260206040909202019081019150611137565b73ffffffffffffffffffffffffffffffffffffffff16815260208101919091526040016000205460ff16156104b7576040517f28cae27d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600660006104ca6020860186611154565b858181106104da576104da6111c3565b6104f09260206040909202019081019150611137565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055600101610409565b50806002610559828261133f565b5050600580546000919082906105749063ffffffff1661147a565b91906101000a81548163ffffffff021916908363ffffffff160217905590507f6cc65868ae41a007e6c3ed18ce591c123dd4e5864b421888c68ce92dae98cea460405180604001604052808363ffffffff168152602001846105d59061149d565b90526040516105e49190610ca0565b60405180910390a15050565b6105f8610b99565b60408051808201825260055463ffffffff1681528151606081018352600280548252600380548551602082810282018101909752818152949580870195858201939092909160009084015b828210156106b1576000848152602090819020604080518082019091529084015473ffffffffffffffffffffffffffffffffffffffff8116825274010000000000000000000000000000000000000000900467ffffffffffffffff1681830152825260019092019101610643565b505050908252506002919091015467ffffffffffffffff166020909101529052919050565b60015473ffffffffffffffffffffffffffffffffffffffff16331461075c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b84518110156109bf5760008582815181106107f5576107f56111c3565b602002602001015190506000600186601b8460000151856020015160405160008152602001604052604051610846949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015610868573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff81166108e0576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1610610945576040517fbbe15e7f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff811660009081526006602052604090205460ff166109a4576040517faaaa914100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b9250826109b08561161b565b945050508060010190506107d8565b5060045467ffffffffffffffff16821015610a06576040517f59fa4a9300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050565b610a15610a23565b610a1e81610aa4565b50565b565b60005473ffffffffffffffffffffffffffffffffffffffff163314610a21576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610753565b3373ffffffffffffffffffffffffffffffffffffffff821603610b23576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610753565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6040518060400160405280600063ffffffff168152602001610be260405180606001604052806000801916815260200160608152602001600067ffffffffffffffff1681525090565b905290565b6000815180845260005b81811015610c0d57602081850181015186830182015201610bf1565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000610c5e6020830184610be7565b9392505050565b600060208284031215610c7757600080fd5b813567ffffffffffffffff811115610c8e57600080fd5b820160608185031215610c5e57600080fd5b6000602080835263ffffffff8451168184015280840151604080604086015260c0850182516060870152838301516060608088015281815180845260e0890191508683019350600092505b80831015610d34578351805173ffffffffffffffffffffffffffffffffffffffff16835287015167ffffffffffffffff1687830152928601926001929092019190840190610ceb565b50604085015167ffffffffffffffff811660a08a0152955098975050505050505050565b600060208284031215610d6a57600080fd5b81357fffffffffffffffffffffffffffffffff0000000000000000000000000000000081168114610c5e57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715610dec57610dec610d9a565b60405290565b60405160a0810167ffffffffffffffff81118282101715610dec57610dec610d9a565b6040516060810167ffffffffffffffff81118282101715610dec57610dec610d9a565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715610e7f57610e7f610d9a565b604052919050565b600067ffffffffffffffff821115610ea157610ea1610d9a565b5060051b60200190565b67ffffffffffffffff81168114610a1e57600080fd5b8035610ecc81610eab565b919050565b600082601f830112610ee257600080fd5b81356020610ef7610ef283610e87565b610e38565b82815260069290921b84018101918181019086841115610f1657600080fd5b8286015b84811015610f555760408189031215610f335760008081fd5b610f3b610dc9565b813581528482013585820152835291830191604001610f1a565b509695505050505050565b60008060408385031215610f7357600080fd5b823567ffffffffffffffff80821115610f8b57600080fd5b818501915085601f830112610f9f57600080fd5b81356020610faf610ef283610e87565b82815260059290921b84018101918181019089841115610fce57600080fd5b8286015b848110156110e757803586811115610fe957600080fd5b87017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe060a0828e038201121561101e57600080fd5b611026610df2565b8683013561103381610eab565b815260408301358981111561104757600080fd5b8301603f81018f1361105857600080fd5b878101358a81111561106c5761106c610d9a565b61107c8985601f84011601610e38565b93508084528f604082840101111561109357600080fd5b80604083018a8601376000898286010152505081878201526110b760608401610ec1565b60408201526110c860808401610ec1565b606082015260a092909201356080830152508352918301918301610fd2565b50965050860135925050808211156110fe57600080fd5b5061110b85828601610ed1565b9150509250929050565b73ffffffffffffffffffffffffffffffffffffffff81168114610a1e57600080fd5b60006020828403121561114957600080fd5b8135610c5e81611115565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261118957600080fd5b83018035915067ffffffffffffffff8211156111a457600080fd5b6020019150600681901b36038213156111bc57600080fd5b9250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561120457600080fd5b8135610c5e81610eab565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818103818111156112515761125161120f565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b6000813561125181610eab565b813561129e81611115565b73ffffffffffffffffffffffffffffffffffffffff811690508154817fffffffffffffffffffffffff0000000000000000000000000000000000000000821617835560208401356112ee81610eab565b7bffffffffffffffff00000000000000000000000000000000000000008160a01b16837fffffffff000000000000000000000000000000000000000000000000000000008416171784555050505050565b81358155600180820160208401357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe185360301811261137d57600080fd5b8401803567ffffffffffffffff81111561139657600080fd5b6020820191508060061b36038213156113ae57600080fd5b680100000000000000008111156113c7576113c7610d9a565b8254818455808210156113fc576000848152602081208381019083015b808210156113f857828255908701906113e4565b5050505b50600092835260208320925b8181101561142c5761141a8385611293565b92840192604092909201918401611408565b50505050506101a861144060408401611286565b6002830167ffffffffffffffff82167fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000008254161781555050565b600063ffffffff8083168181036114935761149361120f565b6001019392505050565b6000606082360312156114af57600080fd5b6114b7610e15565b8235815260208084013567ffffffffffffffff8111156114d657600080fd5b840136601f8201126114e757600080fd5b80356114f5610ef282610e87565b81815260069190911b8201830190838101903683111561151457600080fd5b928401925b8284101561156a57604084360312156115325760008081fd5b61153a610dc9565b843561154581611115565b81528486013561155481610eab565b8187015282526040939093019290840190611519565b8085870152505050505061158060408401610ec1565b604082015292915050565b81811015611608577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee08d8a030184528751868151168a528a810151848c8c01526115d7858c0182610be7565b828e015189168c8f01528983015189168a8d0152918701519a87019a909a529850968901969289019260010161158b565b50969d9c50505050505050505050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361164c5761164c61120f565b506001019056fea164736f6c6343000818000a", } var RMNRemoteABI = RMNRemoteMetaData.ABI diff --git a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt index 7bf6d2a158..28ee860683 100644 --- a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -5,7 +5,7 @@ burn_mint_token_pool_and_proxy: ../../../contracts/solc/v0.8.24/BurnMintTokenPoo burn_with_from_mint_token_pool: ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.abi ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.bin 6333d0314d0bd29e75ea5e05fe62a4516ade0c6db91c30b6f93645035db52ed8 burn_with_from_mint_token_pool_and_proxy: ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPoolAndProxy/BurnWithFromMintTokenPoolAndProxy.abi ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPoolAndProxy/BurnWithFromMintTokenPoolAndProxy.bin 08ed1235dda921ce8841b26aa18d0c0f36db4884779dd7670857159801b6d597 ccip_config: ../../../contracts/solc/v0.8.24/CCIPConfig/CCIPConfig.abi ../../../contracts/solc/v0.8.24/CCIPConfig/CCIPConfig.bin 75955a3dcfd66b308be07eda54d6036cc79e87d3cdcf3c5c3115813c55912af8 -ccip_reader_tester: ../../../contracts/solc/v0.8.24/CCIPReaderTester/CCIPReaderTester.abi ../../../contracts/solc/v0.8.24/CCIPReaderTester/CCIPReaderTester.bin 9e21d63b5a3ea8776dbfa068effcb70e77d3fcc44bc6af3a6a6870f5c4bfe212 +ccip_reader_tester: ../../../contracts/solc/v0.8.24/CCIPReaderTester/CCIPReaderTester.abi ../../../contracts/solc/v0.8.24/CCIPReaderTester/CCIPReaderTester.bin 481d461f14c98308cd788b64be1151e92bac6f95ddd55eefc926296454316f13 commit_store: ../../../contracts/solc/v0.8.24/CommitStore/CommitStore.abi ../../../contracts/solc/v0.8.24/CommitStore/CommitStore.bin 274d87db70b643e00ab0a7e7845bb4b791f3b613bfc87708d33fc5a8369e2a41 commit_store_helper: ../../../contracts/solc/v0.8.24/CommitStoreHelper/CommitStoreHelper.abi ../../../contracts/solc/v0.8.24/CommitStoreHelper/CommitStoreHelper.bin f7128dcc2ee6dbcbc976288abcc16970ffb19b59412c5202ef6b259d2007f801 ether_sender_receiver: ../../../contracts/solc/v0.8.24/EtherSenderReceiver/EtherSenderReceiver.abi ../../../contracts/solc/v0.8.24/EtherSenderReceiver/EtherSenderReceiver.bin 09510a3f773f108a3c231e8d202835c845ded862d071ec54c4f89c12d868b8de @@ -23,15 +23,15 @@ multi_aggregate_rate_limiter: ../../../contracts/solc/v0.8.24/MultiAggregateRate multi_ocr3_helper: ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Helper.abi ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Helper.bin 6b56e0114a4d50797d30a34aecc2641ef340451d0c3fcb9d729bba4df2435122 nonce_manager: ../../../contracts/solc/v0.8.24/NonceManager/NonceManager.abi ../../../contracts/solc/v0.8.24/NonceManager/NonceManager.bin 6f64e1083b356c06ee66b9138e398b9c97a4cd3e8c9ec38cf3010cebc79af536 ocr3_config_encoder: ../../../contracts/solc/v0.8.24/IOCR3ConfigEncoder/IOCR3ConfigEncoder.abi ../../../contracts/solc/v0.8.24/IOCR3ConfigEncoder/IOCR3ConfigEncoder.bin 9254b35a86f00fde7b7193a033ca58f6521a66e87b9cf9da6ce5660082e79f5d -offramp: ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.abi ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.bin f8b00a000ceaadcd9d0c2a9d78f6d2aedbff1e3dcdb66e4fd23333ed6daf26e7 +offramp: ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.abi ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.bin 741b4b66670c06c1b09408ec6706656c46e4c98b227111d99f80940cc5faad42 onramp: ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.abi ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.bin c37096aaa0369ad988e94c300ba62917e17fcc71a3c1aa3e9b8420f21c0591d2 ping_pong_demo: ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.abi ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.bin c1c2f8a65c7ffd971899cae7fe62f2da57d09e936151e2b92163c4bebe699d6b price_registry: ../../../contracts/solc/v0.8.24/PriceRegistry/PriceRegistry.abi ../../../contracts/solc/v0.8.24/PriceRegistry/PriceRegistry.bin e7781d600c1bb7aa4620106af7f6e146a109b97f4cb6a7d06c9e15773340ecb2 registry_module_owner_custom: ../../../contracts/solc/v0.8.24/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.abi ../../../contracts/solc/v0.8.24/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.bin 75be86323c227917a9bbc3f799d7ed02f92db546653a36db30ed0ebe64461353 -report_codec: ../../../contracts/solc/v0.8.24/ReportCodec/ReportCodec.abi ../../../contracts/solc/v0.8.24/ReportCodec/ReportCodec.bin 4b9252c443c87ceb7f5ac3b9d100e572fead010f7c39543315052677a3a2c597 +report_codec: ../../../contracts/solc/v0.8.24/ReportCodec/ReportCodec.abi ../../../contracts/solc/v0.8.24/ReportCodec/ReportCodec.bin cb9183d8d8ebbc1e64bc0d4c9525264e8b71de3e8d3622962dbada53970ecfc8 rmn_contract: ../../../contracts/solc/v0.8.24/RMN/RMN.abi ../../../contracts/solc/v0.8.24/RMN/RMN.bin 8b45b0fb08631c6b582fd3c0b4052a79cc2b4e091e6286af1ab131bef63661f9 rmn_proxy_contract: ../../../contracts/solc/v0.8.24/ARMProxy/ARMProxy.abi ../../../contracts/solc/v0.8.24/ARMProxy/ARMProxy.bin b048d8e752e3c41113ebb305c1efa06737ad36b4907b93e627fb0a3113023454 -rmn_remote: ../../../contracts/solc/v0.8.24/RMNRemote/RMNRemote.abi ../../../contracts/solc/v0.8.24/RMNRemote/RMNRemote.bin be6840d9646195c37f6fa3f95e1cb67218d04d2cebf72e698377b0a7b9cd76f4 +rmn_remote: ../../../contracts/solc/v0.8.24/RMNRemote/RMNRemote.abi ../../../contracts/solc/v0.8.24/RMNRemote/RMNRemote.bin c58cc9f0102413373f45882e87d69b4bf9a4f4516ecfa866584618a1384a8416 router: ../../../contracts/solc/v0.8.24/Router/Router.abi ../../../contracts/solc/v0.8.24/Router/Router.bin 2e4f0a7826c8abb49d882bb49fc5ff20a186dbd3137624b9097ffed903ae4888 self_funded_ping_pong: ../../../contracts/solc/v0.8.24/SelfFundedPingPong/SelfFundedPingPong.abi ../../../contracts/solc/v0.8.24/SelfFundedPingPong/SelfFundedPingPong.bin 8ea5d75dbc3f8afd90d22c4a665a94e02892259cd16520c1c6b4cf0dc80c9148 token_admin_registry: ../../../contracts/solc/v0.8.24/TokenAdminRegistry/TokenAdminRegistry.abi ../../../contracts/solc/v0.8.24/TokenAdminRegistry/TokenAdminRegistry.bin 942be7d1681ac102e0615bee13f76838ebb0b261697cf1270d2bf82c12e57aeb From d48e3c07510cf50faaba4712134c2400c635a8ed Mon Sep 17 00:00:00 2001 From: Balamurali Gopalswami <167726375+b-gopalswami@users.noreply.github.com> Date: Mon, 9 Sep 2024 16:50:50 -0400 Subject: [PATCH 079/115] CCIP-2824: Adding reorg test (#1379) ## Motivation Test around reorg is not available in CCIP which let the bug (caching the block timestamp which got reorged) in mainnet. ## Solution Add unit level test which can identify the caching problem. Add E2E test to assess CCIP behaviour when above and below finality reorg happens. --------- Co-authored-by: Mateusz Sekara --- .github/workflows/integration-tests.yml | 25 ++- .../plugins/ccip/clo_ccip_integration_test.go | 22 ++- .../ocr2/plugins/ccip/integration_test.go | 82 ++++++++- .../ccip/testhelpers/ccip_contracts.go | 6 +- .../ccip/testhelpers/integration/chainlink.go | 19 ++- core/services/ocr2/plugins/ccip/vars.go | 10 +- .../ccip-tests/actions/ccip_helpers.go | 30 +++- .../ccip-tests/actions/reorg_helpers.go | 86 ++++++++++ .../ccip-tests/smoke/ccip_test.go | 160 +++++++++++++++++- integration-tests/ccip-tests/smoke/lm_test.go | 1 - .../ccip-tests/testconfig/ccip.go | 15 ++ .../testconfig/tomls/ccip-reorg.toml | 64 +++++++ 12 files changed, 498 insertions(+), 22 deletions(-) create mode 100644 integration-tests/ccip-tests/actions/reorg_helpers.go create mode 100644 integration-tests/ccip-tests/testconfig/tomls/ccip-reorg.toml diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index dba8aadec6..b03f30c979 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -373,6 +373,27 @@ jobs: file: ccip run: -run ^TestSmokeCCIPForBidirectionalLane$ config_path: ./integration-tests/ccip-tests/testconfig/tomls/leader-lane.toml + - name: ccip-smoke-reorg + nodes: 1 + dir: ccip-tests/smoke + os: ubuntu-latest + file: ccip + run: -run ^TestSmokeCCIPReorgBelowFinality$ -v + config_path: ./integration-tests/ccip-tests/testconfig/tomls/ccip-reorg.toml + - name: ccip-smoke-reorg + nodes: 1 + dir: ccip-tests/smoke + os: ubuntu-latest + file: ccip + run: -run ^TestSmokeCCIPReorgAboveFinalityAtDestination$ -v + config_path: ./integration-tests/ccip-tests/testconfig/tomls/ccip-reorg.toml + - name: ccip-smoke-reorg + nodes: 1 + dir: ccip-tests/smoke + os: ubuntu-latest + file: ccip + run: -run ^TestSmokeCCIPReorgAboveFinalityAtSource$ -v + config_path: ./integration-tests/ccip-tests/testconfig/tomls/ccip-reorg.toml - name: runlog id: runlog nodes: 2 @@ -569,8 +590,8 @@ jobs: if: needs.changes.outputs.src == 'true' || github.event_name == 'workflow_dispatch' uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@aa8eea635029ab8d95abd3c206f56dae1e22e623 # v2.3.28 env: - BASE64_CCIP_CONFIG_OVERRIDE: ${{ steps.set_override_config.outputs.base_64_override }},${{ steps.setup_create_base64_config_ccip.outputs.base64_config }} - TEST_BASE64_CCIP_CONFIG_OVERRIDE: ${{ steps.set_override_config.outputs.base_64_override }},${{ steps.setup_create_base64_config_ccip.outputs.base64_config }} + BASE64_CCIP_CONFIG_OVERRIDE: ${{ steps.setup_create_base64_config_ccip.outputs.base64_config }},${{ steps.set_override_config.outputs.base_64_override }} + TEST_BASE64_CCIP_CONFIG_OVERRIDE: ${{ steps.setup_create_base64_config_ccip.outputs.base64_config }},${{ steps.set_override_config.outputs.base_64_override }} DEBUG_RESTY: false with: test_command_to_run: cd ./integration-tests && go test -timeout 30m -count=1 -json -test.parallel=${{ matrix.product.nodes }} ${{ steps.build-go-test-command.outputs.run_command }} 2>&1 | tee /tmp/gotest.log | gotestloghelper -ci -singlepackage -hidepassingtests=false -hidepassinglogs diff --git a/core/services/ocr2/plugins/ccip/clo_ccip_integration_test.go b/core/services/ocr2/plugins/ccip/clo_ccip_integration_test.go index 2fddd58ac8..0a7594324b 100644 --- a/core/services/ocr2/plugins/ccip/clo_ccip_integration_test.go +++ b/core/services/ocr2/plugins/ccip/clo_ccip_integration_test.go @@ -6,6 +6,8 @@ import ( "math/big" "testing" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/assert" @@ -20,7 +22,15 @@ import ( ) func Test_CLOSpecApprovalFlow_pipeline(t *testing.T) { - ccipTH := integrationtesthelpers.SetupCCIPIntegrationTH(t, testhelpers.SourceChainID, testhelpers.SourceChainSelector, testhelpers.DestChainID, testhelpers.DestChainSelector) + ccipTH := integrationtesthelpers.SetupCCIPIntegrationTH( + t, + testhelpers.SourceChainID, + testhelpers.SourceChainSelector, + testhelpers.DestChainID, + testhelpers.DestChainSelector, + ccip.DefaultSourceFinalityDepth, + ccip.DefaultDestFinalityDepth, + ) tokenPricesUSDPipeline, linkUSD, ethUSD := ccipTH.CreatePricesPipeline(t) defer linkUSD.Close() @@ -30,7 +40,15 @@ func Test_CLOSpecApprovalFlow_pipeline(t *testing.T) { } func Test_CLOSpecApprovalFlow_dynamicPriceGetter(t *testing.T) { - ccipTH := integrationtesthelpers.SetupCCIPIntegrationTH(t, testhelpers.SourceChainID, testhelpers.SourceChainSelector, testhelpers.DestChainID, testhelpers.DestChainSelector) + ccipTH := integrationtesthelpers.SetupCCIPIntegrationTH( + t, + testhelpers.SourceChainID, + testhelpers.SourceChainSelector, + testhelpers.DestChainID, + testhelpers.DestChainSelector, + ccip.DefaultSourceFinalityDepth, + ccip.DefaultDestFinalityDepth, + ) //Set up the aggregators here to avoid modifying ccipTH. dstLinkAddr := ccipTH.Dest.LinkToken.Address() diff --git a/core/services/ocr2/plugins/ccip/integration_test.go b/core/services/ocr2/plugins/ccip/integration_test.go index bfd270fb66..21227f6dcf 100644 --- a/core/services/ocr2/plugins/ccip/integration_test.go +++ b/core/services/ocr2/plugins/ccip/integration_test.go @@ -9,6 +9,8 @@ import ( "testing" "time" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip" + "github.com/ethereum/go-ethereum/common" gethtypes "github.com/ethereum/go-ethereum/core/types" "github.com/stretchr/testify/assert" @@ -17,6 +19,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_onramp" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/mock_v3_aggregator_contract" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/config" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/v1_5_0" @@ -46,7 +49,15 @@ func TestIntegration_CCIP(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - ccipTH := integrationtesthelpers.SetupCCIPIntegrationTH(t, testhelpers.SourceChainID, testhelpers.SourceChainSelector, testhelpers.DestChainID, testhelpers.DestChainSelector) + ccipTH := integrationtesthelpers.SetupCCIPIntegrationTH( + t, + testhelpers.SourceChainID, + testhelpers.SourceChainSelector, + testhelpers.DestChainID, + testhelpers.DestChainSelector, + ccip.DefaultSourceFinalityDepth, + ccip.DefaultDestFinalityDepth, + ) tokenPricesUSDPipeline := "" priceGetterConfigJson := "" @@ -94,7 +105,6 @@ func TestIntegration_CCIP(t *testing.T) { require.NoError(t, err) priceGetterConfigJson = string(priceGetterConfigBytes) } - jobParams := ccipTH.SetUpNodesAndJobs(t, tokenPricesUSDPipeline, priceGetterConfigJson, "") // track sequence number and nonce separately since nonce doesn't bump for messages with allowOutOfOrderExecution == true, @@ -629,3 +639,71 @@ func TestIntegration_CCIP(t *testing.T) { }) } } + +// TestReorg ensures that CCIP works even when a below finality depth reorg happens +func TestReorg(t *testing.T) { + // We need higher finality depth on the destination to perform reorg deep enough to revert commit and execution reports + destinationFinalityDepth := uint32(50) + ccipTH := integrationtesthelpers.SetupCCIPIntegrationTH( + t, + testhelpers.SourceChainID, + testhelpers.SourceChainSelector, + testhelpers.DestChainID, + testhelpers.DestChainSelector, + ccip.DefaultSourceFinalityDepth, + destinationFinalityDepth, + ) + testPricePipeline, linkUSD, ethUSD := ccipTH.CreatePricesPipeline(t) + defer linkUSD.Close() + defer ethUSD.Close() + ccipTH.SetUpNodesAndJobs(t, testPricePipeline, "", "") + + gasLimit := big.NewInt(200_00) + tokenAmount := big.NewInt(1) + + forkBlock, err := ccipTH.Dest.Chain.BlockByNumber(context.Background(), nil) + require.NoError(t, err, "Error while fetching the destination chain current block number") + + // Adjust time to start next blocks with timestamps two hours after the fork block. + // This is critical to have two forks with different block_timestamps. + err = ccipTH.Dest.Chain.AdjustTime(2 * time.Hour) + require.NoError(t, err, "Error while adjusting the destination chain time") + ccipTH.Dest.Chain.Commit() + + // Send request for the first time and make sure it's executed on the destination + ccipTH.SendMessage(t, gasLimit, tokenAmount, ccipTH.Dest.Receivers[0].Receiver.Address()) + ccipTH.Dest.User.GasLimit = 100000 + ccipTH.EventuallySendRequested(t, uint64(1)) + ccipTH.EventuallyReportCommitted(t, 1) + executionLog := ccipTH.AllNodesHaveExecutedSeqNums(t, 1, 1) + ccipTH.AssertExecState(t, executionLog[0], testhelpers.ExecutionStateSuccess) + + currentBlock, err := ccipTH.Dest.Chain.BlockByNumber(context.Background(), nil) + require.NoError(t, err, "Error while fetching the current block number of destination chain") + + // Reorg back to the `forkBlock`. Next blocks in the fork will have block_timestamps right after the fork, + // but before the 2 hours interval defined above for the canonical chain + require.NoError(t, ccipTH.Dest.Chain.Fork(testutils.Context(t), forkBlock.Hash()), + "Error while forking the chain") + // Make sure that fork is longer than the canonical chain to enforce switch + noOfBlocks := int(currentBlock.NumberU64() - forkBlock.NumberU64()) + for i := 0; i < noOfBlocks+1; i++ { + ccipTH.Dest.Chain.Commit() + } + + // State of the chain (block_timestamps) after reorg: + // / --> block1 (02:01) --> block2 (02:02) --> commit report (02:03) --> ... + // forkBlock (00:00) --> block1' (00:01) --> block2' (00:02) --> commit report' (00:03) --> ... + + // CCIP should commit and executed messages that was reorged away + ccipTH.EventuallyReportCommitted(t, 1) + executionLog = ccipTH.AllNodesHaveExecutedSeqNums(t, 1, 1) + ccipTH.AssertExecState(t, executionLog[0], testhelpers.ExecutionStateSuccess) + + // Sending another message and make sure it's executed on the destination + ccipTH.SendMessage(t, gasLimit, tokenAmount, ccipTH.Dest.Receivers[0].Receiver.Address()) + ccipTH.EventuallySendRequested(t, uint64(2)) + ccipTH.EventuallyReportCommitted(t, 2) + executionLog = ccipTH.AllNodesHaveExecutedSeqNums(t, 1, 2) + ccipTH.AssertExecState(t, executionLog[0], testhelpers.ExecutionStateSuccess) +} diff --git a/core/services/ocr2/plugins/ccip/testhelpers/ccip_contracts.go b/core/services/ocr2/plugins/ccip/testhelpers/ccip_contracts.go index e1aed59053..7b3351ce06 100644 --- a/core/services/ocr2/plugins/ccip/testhelpers/ccip_contracts.go +++ b/core/services/ocr2/plugins/ccip/testhelpers/ccip_contracts.go @@ -179,6 +179,7 @@ type Common struct { ARMProxy *rmn_proxy_contract.RMNProxyContract PriceRegistry *price_registry_1_2_0.PriceRegistry TokenAdminRegistry *token_admin_registry.TokenAdminRegistry + FinalityDepth uint32 } type SourceChain struct { @@ -652,7 +653,8 @@ func SetAdminAndRegisterPool(t *testing.T, chain.Commit() } -func SetupCCIPContracts(t *testing.T, sourceChainID, sourceChainSelector, destChainID, destChainSelector uint64) CCIPContracts { +func SetupCCIPContracts(t *testing.T, sourceChainID, sourceChainSelector, destChainID, destChainSelector uint64, + sourceFinalityDepth, destFinalityDepth uint32) CCIPContracts { sourceChain, sourceUser := SetupChain(t) destChain, destUser := SetupChain(t) @@ -1177,6 +1179,7 @@ func SetupCCIPContracts(t *testing.T, sourceChainID, sourceChainSelector, destCh WrappedNative: sourceWrapped, WrappedNativePool: sourceWeth9Pool, TokenAdminRegistry: sourceTokenAdminRegistry, + FinalityDepth: sourceFinalityDepth, }, Router: sourceRouter, OnRamp: onRamp, @@ -1196,6 +1199,7 @@ func SetupCCIPContracts(t *testing.T, sourceChainID, sourceChainSelector, destCh WrappedNative: destWrapped, WrappedNativePool: destWrappedPool, TokenAdminRegistry: destTokenAdminRegistry, + FinalityDepth: destFinalityDepth, }, CommitStoreHelper: commitStoreHelper, CommitStore: commitStore, diff --git a/core/services/ocr2/plugins/ccip/testhelpers/integration/chainlink.go b/core/services/ocr2/plugins/ccip/testhelpers/integration/chainlink.go index bb2f6b0f7c..04d6663959 100644 --- a/core/services/ocr2/plugins/ccip/testhelpers/integration/chainlink.go +++ b/core/services/ocr2/plugins/ccip/testhelpers/integration/chainlink.go @@ -371,6 +371,7 @@ func setupNodeCCIP( sourceChainID *big.Int, destChainID *big.Int, bootstrapPeerID string, bootstrapPort int64, + sourceFinalityDepth, destFinalityDepth uint32, ) (chainlink.Application, string, common.Address, ocr2key.KeyBundle) { trueRef, falseRef := true, false @@ -405,7 +406,7 @@ func setupNodeCCIP( c.P2P.V2.ListenAddresses = &p2pAddresses c.P2P.V2.AnnounceAddresses = &p2pAddresses - c.EVM = []*v2.EVMConfig{createConfigV2Chain(sourceChainID), createConfigV2Chain(destChainID)} + c.EVM = []*v2.EVMConfig{createConfigV2Chain(sourceChainID, sourceFinalityDepth), createConfigV2Chain(destChainID, destFinalityDepth)} if bootstrapPeerID != "" { // Supply the bootstrap IP and port as a V2 peer address @@ -527,7 +528,7 @@ func setupNodeCCIP( return app, peerID.Raw(), transmitter, kb } -func createConfigV2Chain(chainId *big.Int) *v2.EVMConfig { +func createConfigV2Chain(chainId *big.Int, finalityDepth uint32) *v2.EVMConfig { // NOTE: For the executor jobs, the default of 500k is insufficient for a 3 message batch defaultGasLimit := uint64(5000000) tr := true @@ -538,8 +539,7 @@ func createConfigV2Chain(chainId *big.Int) *v2.EVMConfig { sourceC.GasEstimator.Mode = &fixedPrice d, _ := config.NewDuration(100 * time.Millisecond) sourceC.LogPollInterval = &d - fd := uint32(2) - sourceC.FinalityDepth = &fd + sourceC.FinalityDepth = &finalityDepth return &v2.EVMConfig{ ChainID: (*evmUtils.Big)(chainId), Enabled: &tr, @@ -554,9 +554,11 @@ type CCIPIntegrationTestHarness struct { Bootstrap Node } -func SetupCCIPIntegrationTH(t *testing.T, sourceChainID, sourceChainSelector, destChainId, destChainSelector uint64) CCIPIntegrationTestHarness { +func SetupCCIPIntegrationTH(t *testing.T, sourceChainID, sourceChainSelector, destChainId, destChainSelector uint64, + sourceFinalityDepth, destFinalityDepth uint32) CCIPIntegrationTestHarness { return CCIPIntegrationTestHarness{ - CCIPContracts: testhelpers.SetupCCIPContracts(t, sourceChainID, sourceChainSelector, destChainId, destChainSelector), + CCIPContracts: testhelpers.SetupCCIPContracts(t, sourceChainID, sourceChainSelector, destChainId, + destChainSelector, sourceFinalityDepth, destFinalityDepth), } } @@ -929,7 +931,8 @@ func (c *CCIPIntegrationTestHarness) ConsistentlyReportNotCommitted(t *testing.T func (c *CCIPIntegrationTestHarness) SetupAndStartNodes(ctx context.Context, t *testing.T, bootstrapNodePort int64) (Node, []Node, int64) { appBootstrap, bootstrapPeerID, bootstrapTransmitter, bootstrapKb := setupNodeCCIP(t, c.Dest.User, bootstrapNodePort, "bootstrap_ccip", c.Source.Chain, c.Dest.Chain, big.NewInt(0).SetUint64(c.Source.ChainID), - big.NewInt(0).SetUint64(c.Dest.ChainID), "", 0) + big.NewInt(0).SetUint64(c.Dest.ChainID), "", 0, c.Source.FinalityDepth, + c.Dest.FinalityDepth) var ( oracles []confighelper.OracleIdentityExtra nodes []Node @@ -957,6 +960,8 @@ func (c *CCIPIntegrationTestHarness) SetupAndStartNodes(ctx context.Context, t * big.NewInt(0).SetUint64(c.Dest.ChainID), bootstrapPeerID, bootstrapNodePort, + c.Source.FinalityDepth, + c.Dest.FinalityDepth, ) nodes = append(nodes, Node{ App: app, diff --git a/core/services/ocr2/plugins/ccip/vars.go b/core/services/ocr2/plugins/ccip/vars.go index a44f5e41d6..82309ef783 100644 --- a/core/services/ocr2/plugins/ccip/vars.go +++ b/core/services/ocr2/plugins/ccip/vars.go @@ -5,10 +5,12 @@ import ( ) const ( - MaxQueryLength = 0 // empty for both plugins - MaxObservationLength = 250_000 // plugins's Observation should make sure to cap to this limit - CommitPluginLabel = "commit" - ExecPluginLabel = "exec" + MaxQueryLength = 0 // empty for both plugins + MaxObservationLength = 250_000 // plugins's Observation should make sure to cap to this limit + CommitPluginLabel = "commit" + ExecPluginLabel = "exec" + DefaultSourceFinalityDepth = uint32(2) + DefaultDestFinalityDepth = uint32(2) ) var ErrChainIsNotHealthy = errors.New("lane processing is stopped because of healthcheck failure, please see crit logs") diff --git a/integration-tests/ccip-tests/actions/ccip_helpers.go b/integration-tests/ccip-tests/actions/ccip_helpers.go index e878233d53..e07a97dbf2 100644 --- a/integration-tests/ccip-tests/actions/ccip_helpers.go +++ b/integration-tests/ccip-tests/actions/ccip_helpers.go @@ -3046,6 +3046,7 @@ func (lane *CCIPLane) ExecuteManually(options ...ManualExecutionOption) error { // validationOptions are used in the ValidateRequests function to specify which phase is expected to fail and how type validationOptions struct { + expectAnyPhaseToFail bool phaseExpectedToFail testreporters.Phase // the phase expected to fail expectedErrorMessage string // if provided, we're looking for a specific error message timeout time.Duration // timeout for the validation @@ -3087,6 +3088,18 @@ func ExpectPhaseToFail(phase testreporters.Phase, phaseSpecificOptions ...PhaseS } } +// ExpectAnyPhaseToFail expects any phase in CCIP transaction to fail. +func ExpectAnyPhaseToFail(phaseSpecificOptions ...PhaseSpecificValidationOptionFunc) ValidationOptionFunc { + return func(opts *validationOptions) { + opts.expectAnyPhaseToFail = true + for _, f := range phaseSpecificOptions { + if f != nil { + f(opts) + } + } + } +} + // ValidateRequests validates all sent request events. // If you expect a specific phase to fail, you can pass a validationOptionFunc to specify exactly which one. // If not, just pass in nil. @@ -3132,7 +3145,7 @@ func (lane *CCIPLane) ValidateRequestByTxHash(txHash common.Hash, opts validatio reqStats = append(reqStats, req.RequestStat) } - if opts.phaseExpectedToFail == testreporters.CCIPSendRe && opts.timeout != 0 { + if (opts.phaseExpectedToFail == testreporters.CCIPSendRe || opts.expectAnyPhaseToFail) && opts.timeout != 0 { timeout = opts.timeout } msgLogs, ccipSendReqGenAt, err := lane.Source.AssertEventCCIPSendRequested( @@ -3160,6 +3173,10 @@ func (lane *CCIPLane) ValidateRequestByTxHash(txHash common.Hash, opts validatio return fmt.Errorf("could not find request stat for seq number %d", seqNumber) } + if opts.expectAnyPhaseToFail && opts.timeout != 0 { + timeout = opts.timeout + } + if opts.phaseExpectedToFail == testreporters.Commit && opts.timeout != 0 { timeout = opts.timeout } @@ -3199,6 +3216,9 @@ func (lane *CCIPLane) ValidateRequestByTxHash(txHash common.Hash, opts validatio return phaseErr } } + if opts.expectAnyPhaseToFail { + return fmt.Errorf("expected at least any one phase to fail but no phase got failed") + } return nil } @@ -3210,6 +3230,11 @@ func isPhaseValid( opts validationOptions, err error, ) (shouldComplete bool, validationError error) { + if opts.expectAnyPhaseToFail && err != nil { + logmsg := logger.Info().Str("Failed with Error", err.Error()).Str("Phase", string(currentPhase)) + logmsg.Msg("Phase failed, as expected") + return true, nil + } // If no phase is expected to fail or the current phase is not the one expected to fail, we just return what we were given if opts.phaseExpectedToFail == "" || currentPhase != opts.phaseExpectedToFail { return err != nil, err @@ -3218,13 +3243,14 @@ func isPhaseValid( return true, fmt.Errorf("expected phase '%s' to fail, but it passed", opts.phaseExpectedToFail) } logmsg := logger.Info().Str("Failed with Error", err.Error()).Str("Phase", string(currentPhase)) + if opts.expectedErrorMessage != "" { if !strings.Contains(err.Error(), opts.expectedErrorMessage) { return true, fmt.Errorf("expected phase '%s' to fail with error message '%s' but got error '%s'", currentPhase, opts.expectedErrorMessage, err.Error()) } logmsg.Str("Expected Error Message", opts.expectedErrorMessage) } - logmsg.Msg("Expected phase to fail and it did") + logmsg.Msg("Phase failed, as expected") return true, nil } diff --git a/integration-tests/ccip-tests/actions/reorg_helpers.go b/integration-tests/ccip-tests/actions/reorg_helpers.go new file mode 100644 index 0000000000..eb7751b822 --- /dev/null +++ b/integration-tests/ccip-tests/actions/reorg_helpers.go @@ -0,0 +1,86 @@ +package actions + +import ( + "fmt" + "testing" + "time" + + "github.com/rs/zerolog" + "github.com/stretchr/testify/assert" + + "github.com/smartcontractkit/chainlink-testing-framework/client" +) + +// ReorgSuite is a test suite that generates reorgs on source/dest chains +type ReorgSuite struct { + t *testing.T + Cfg *ReorgConfig + Logger *zerolog.Logger + SrcClient *client.RPCClient + DstClient *client.RPCClient +} + +// ReorgConfig is a configuration for reorg tests +type ReorgConfig struct { + // SrcGethHTTPURL source chain Geth HTTP URL + SrcGethHTTPURL string + // DstGethHTTPURL dest chain Geth HTTP URL + DstGethHTTPURL string + // SrcFinalityDepth source chain finality depth + SrcFinalityDepth uint64 + // DstGethHTTPURL dest chain finality depth + DstFinalityDepth uint64 + // FinalityDelta blocks to rewind below or above finality + FinalityDelta int +} + +// Validate validates ReorgConfig params +func (rc *ReorgConfig) Validate() error { + if rc.FinalityDelta >= int(rc.SrcFinalityDepth) || rc.FinalityDelta >= int(rc.DstFinalityDepth) { + return fmt.Errorf( + "finality delta can't be higher than source or dest chain finality, delta: %d, src: %d, dst: %d", + rc.FinalityDelta, rc.SrcFinalityDepth, rc.DstFinalityDepth, + ) + } + return nil +} + +// NewReorgSuite creates new reorg suite with source/dest RPC clients, works only with Geth +func NewReorgSuite(t *testing.T, lggr *zerolog.Logger, cfg *ReorgConfig) (*ReorgSuite, error) { + if err := cfg.Validate(); err != nil { + return nil, err + } + return &ReorgSuite{ + t: t, + Cfg: cfg, + Logger: lggr, + SrcClient: client.NewRPCClient(cfg.SrcGethHTTPURL, nil), + DstClient: client.NewRPCClient(cfg.DstGethHTTPURL, nil), + }, nil +} + +// RunReorg rollbacks given chain, for N blocks back +func (r *ReorgSuite) RunReorg(client *client.RPCClient, blocksBack int, network string, startDelay time.Duration) { + go func() { + time.Sleep(startDelay) + r.Logger.Info(). + Str("Network", network). + Str("URL", client.URL). + Int("BlocksBack", blocksBack). + Msg(fmt.Sprintf("Rewinding blocks on %s chain", network)) + blockNumber, err := client.BlockNumber() + assert.NoError(r.t, err, "error getting block number") + r.Logger.Info(). + Int64("Number", blockNumber). + Str("Network", network). + Msg("Block number before rewinding") + err = client.GethSetHead(blocksBack) + assert.NoError(r.t, err, "error setting block head") + blockNumber, err = client.BlockNumber() + assert.NoError(r.t, err, "error getting block number") + r.Logger.Info(). + Int64("Number", blockNumber). + Str("Network", network). + Msg("Block number after rewinding") + }() +} diff --git a/integration-tests/ccip-tests/smoke/ccip_test.go b/integration-tests/ccip-tests/smoke/ccip_test.go index 9a34044a5d..37cc4ea394 100644 --- a/integration-tests/ccip-tests/smoke/ccip_test.go +++ b/integration-tests/ccip-tests/smoke/ccip_test.go @@ -7,6 +7,8 @@ import ( "time" "github.com/AlekSi/pointer" + "github.com/rs/zerolog" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink-testing-framework/logging" @@ -32,7 +34,6 @@ func TestSmokeCCIPForBidirectionalLane(t *testing.T) { t.Parallel() log := logging.GetTestLogger(t) TestCfg := testsetups.NewCCIPTestConfig(t, log, testconfig.Smoke) - require.NotNil(t, TestCfg.TestGroupInput.MsgDetails.DestGasLimit) gasLimit := big.NewInt(*TestCfg.TestGroupInput.MsgDetails.DestGasLimit) setUpOutput := testsetups.CCIPDefaultTestSetUp(t, &log, "smoke-ccip", nil, TestCfg) if len(setUpOutput.Lanes) == 0 { @@ -855,6 +856,130 @@ func TestSmokeCCIPManuallyExecuteAfterExecutionFailingDueToInsufficientGas(t *te } } +// Test expects to generate below finality reorg in both source and destination and +// expect CCIP transactions to go through successful. +func TestSmokeCCIPReorgBelowFinality(t *testing.T) { + t.Parallel() + log := logging.GetTestLogger(t) + TestCfg := testsetups.NewCCIPTestConfig(t, log, testconfig.Smoke) + gasLimit := big.NewInt(*TestCfg.TestGroupInput.MsgDetails.DestGasLimit) + setUpOutput := testsetups.CCIPDefaultTestSetUp(t, &log, "smoke-ccip", nil, TestCfg) + require.False(t, len(setUpOutput.Lanes) == 0, "No lanes found.") + t.Cleanup(func() { + require.NoError(t, setUpOutput.TearDown()) + }) + + lane := setUpOutput.Lanes[0].ForwardLane + log.Info(). + Str("Source", lane.SourceNetworkName). + Str("Destination", lane.DestNetworkName). + Msg("Starting CCIP reorg test") + t.Run(fmt.Sprintf("CCIP reorg below finality test from network %s to network %s", + lane.SourceNetworkName, lane.DestNetworkName), func(t *testing.T) { + t.Parallel() + lane.Test = t + lane.RecordStateBeforeTransfer() + // sending multiple request and expect all should go through though there is below finality reorg + err := lane.SendRequests(5, gasLimit) + require.NoError(t, err, "Send requests failed") + rs := SetupReorgSuite(t, &log, setUpOutput) + // run below finality reorg in both source and destination chain + blocksBackSrc := int(rs.Cfg.SrcFinalityDepth) - rs.Cfg.FinalityDelta + blocksBackDst := int(rs.Cfg.DstFinalityDepth) - rs.Cfg.FinalityDelta + rs.RunReorg(rs.DstClient, blocksBackSrc, "Source", 2*time.Second) + rs.RunReorg(rs.DstClient, blocksBackDst, "Destination", 2*time.Second) + time.Sleep(1 * time.Minute) + lane.ValidateRequests() + }) +} + +// Test creates above finality reorg at destination and +// expects ccip transactions in-flight and the one initiated after reorg +// doesn't go through and verifies every node is able to detect reorg. +// Note: LogPollInterval interval is set as 1s to detect the reorg immediately +func TestSmokeCCIPReorgAboveFinalityAtDestination(t *testing.T) { + t.Parallel() + t.Run("Above finality reorg in destination chain", func(t *testing.T) { + performAboveFinalityReorgAndValidate(t, "Destination") + }) +} + +// Test creates above finality reorg at destination and +// expects ccip transactions in-flight doesn't go through, the transaction initiated after reorg +// shouldn't even get initiated and verifies every node is able to detect reorg. +// Note: LogPollInterval interval is set as 1s to detect the reorg immediately +func TestSmokeCCIPReorgAboveFinalityAtSource(t *testing.T) { + t.Parallel() + t.Run("Above finality reorg in source chain", func(t *testing.T) { + performAboveFinalityReorgAndValidate(t, "Source") + }) +} + +// performAboveFinalityReorgAndValidate is to perform the above finality reorg test +func performAboveFinalityReorgAndValidate(t *testing.T, network string) { + t.Helper() + + log := logging.GetTestLogger(t) + TestCfg := testsetups.NewCCIPTestConfig(t, log, testconfig.Smoke) + gasLimit := big.NewInt(*TestCfg.TestGroupInput.MsgDetails.DestGasLimit) + setUpOutput := testsetups.CCIPDefaultTestSetUp(t, &log, "smoke-ccip", nil, TestCfg) + require.False(t, len(setUpOutput.Lanes) == 0, "No lanes found.") + t.Cleanup(func() { + require.NoError(t, setUpOutput.TearDown()) + }) + rs := SetupReorgSuite(t, &log, setUpOutput) + lane := setUpOutput.Lanes[0].ForwardLane + log.Info(). + Str("Source", lane.SourceNetworkName). + Str("Destination", lane.DestNetworkName). + Msg("Starting ccip reorg test") + lane.Test = t + lane.RecordStateBeforeTransfer() + err := lane.SendRequests(1, gasLimit) + require.NoError(t, err, "Send requests failed") + logPollerName := "" + if network == "Destination" { + logPollerName = fmt.Sprintf("EVM.%d.LogPoller", lane.DestChain.GetChainID()) + rs.RunReorg(rs.DstClient, int(rs.Cfg.DstFinalityDepth)+rs.Cfg.FinalityDelta, network, 2*time.Second) + } else { + logPollerName = fmt.Sprintf("EVM.%d.LogPoller", lane.SourceChain.GetChainID()) + rs.RunReorg(rs.SrcClient, int(rs.Cfg.SrcFinalityDepth)+rs.Cfg.FinalityDelta, network, 2*time.Second) + } + clNodes := setUpOutput.Env.CLNodes + // assert every node is detecting the reorg (LogPollInterval is set as 1s for faster detection) + nodesDetectedViolation := make(map[string]bool) + assert.Eventually(t, func() bool { + for _, node := range clNodes { + if _, ok := nodesDetectedViolation[node.ChainlinkClient.URL()]; ok { + continue + } + resp, _, err := node.Health() + require.NoError(t, err) + for _, d := range resp.Data { + if d.Attributes.Name == logPollerName && d.Attributes.Output == "finality violated" && d.Attributes.Status == "failing" { + log.Debug().Str("Node", node.ChainlinkClient.URL()).Msg("Finality violated is detected by node") + nodesDetectedViolation[node.ChainlinkClient.URL()] = true + } + } + } + return len(nodesDetectedViolation) == len(clNodes) + }, 5*time.Minute, 5*time.Second, "Reorg above finality depth is not detected by every node") + log.Debug().Interface("Nodes", nodesDetectedViolation).Msg("Violation detection details") + // send another request and verify it fails + err = lane.SendRequests(1, gasLimit) + if network == "Source" { + // if it is source chain reorg, the transaction will not even be initiated + require.Error(t, err, + "CCIP send transaction shouldn't be initiated as there is above finality depth reorg in source chain") + } else { + // if it is destination chain reorg, the transaction will be initiated and will fail in the process + require.NoError(t, err, + "CCIP send transaction should be initiated even when there above finality reorg in dest chain") + } + + lane.ValidateRequests(actions.ExpectAnyPhaseToFail(actions.WithTimeout(time.Minute))) +} + // add liquidity to pools on both networks func addLiquidity(t *testing.T, ccipCommon *actions.CCIPCommon, amount *big.Int) { t.Helper() @@ -1006,3 +1131,36 @@ func testOffRampRateLimits(t *testing.T, rateLimiterConfig contracts.RateLimiter } } + +// SetupReorgSuite defines the setup required to perform re-org step +func SetupReorgSuite(t *testing.T, lggr *zerolog.Logger, setupOutput *testsetups.CCIPTestSetUpOutputs) *actions.ReorgSuite { + var finalitySrc uint64 + var finalityDst uint64 + if setupOutput.Cfg.SelectedNetworks[0].FinalityTag { + finalitySrc = 10 + } else { + finalitySrc = setupOutput.Cfg.SelectedNetworks[0].FinalityDepth + } + if setupOutput.Cfg.SelectedNetworks[1].FinalityTag { + finalityDst = 10 + } else { + finalityDst = setupOutput.Cfg.SelectedNetworks[1].FinalityDepth + } + var srcGethHTTPURL, dstGethHTTPURL string + if setupOutput.Env.LocalCluster != nil { + srcGethHTTPURL = setupOutput.Env.LocalCluster.EVMNetworks[0].HTTPURLs[0] + dstGethHTTPURL = setupOutput.Env.LocalCluster.EVMNetworks[1].HTTPURLs[0] + } else { + srcGethHTTPURL = setupOutput.Env.K8Env.URLs["source-chain_http"][0] + dstGethHTTPURL = setupOutput.Env.K8Env.URLs["dest-chain_http"][0] + } + rs, err := actions.NewReorgSuite(t, lggr, &actions.ReorgConfig{ + SrcGethHTTPURL: srcGethHTTPURL, + DstGethHTTPURL: dstGethHTTPURL, + SrcFinalityDepth: finalitySrc, + DstFinalityDepth: finalityDst, + FinalityDelta: setupOutput.Cfg.TestGroupInput.ReorgProfile.FinalityDelta, + }) + require.NoError(t, err) + return rs +} diff --git a/integration-tests/ccip-tests/smoke/lm_test.go b/integration-tests/ccip-tests/smoke/lm_test.go index 8b2625ac11..9ac55b1612 100644 --- a/integration-tests/ccip-tests/smoke/lm_test.go +++ b/integration-tests/ccip-tests/smoke/lm_test.go @@ -16,7 +16,6 @@ func TestLmBasic(t *testing.T) { t.Parallel() log := logging.GetTestLogger(t) TestCfg := testsetups.NewCCIPTestConfig(t, log, testconfig.Smoke) - require.NotNil(t, TestCfg.TestGroupInput.MsgDetails.DestGasLimit) //gasLimit := big.NewInt(*TestCfg.TestGroupInput.MsgDetails.DestGasLimit) lmTestSetup := testsetups.LMDefaultTestSetup(t, &log, "smoke-lm", TestCfg) diff --git a/integration-tests/ccip-tests/testconfig/ccip.go b/integration-tests/ccip-tests/testconfig/ccip.go index 7d9419828e..9dc416da56 100644 --- a/integration-tests/ccip-tests/testconfig/ccip.go +++ b/integration-tests/ccip-tests/testconfig/ccip.go @@ -251,6 +251,15 @@ func (l *LoadProfile) SetTestRunName(name string) { } } +type ReorgProfile struct { + FinalityDelta int `toml:",omitempty"` +} + +func (gp *ReorgProfile) Validate() error { + // FinalityDelta can be validated only relatively to CL nodes settings, see setupReorgSuite method + return nil +} + // CCIPTestGroupConfig defines configuration input to change how a particular CCIP test group should run type CCIPTestGroupConfig struct { Type string `toml:",omitempty"` @@ -280,6 +289,7 @@ type CCIPTestGroupConfig struct { CommitInflightExpiry *config.Duration `toml:",omitempty"` StoreLaneConfig *bool `toml:",omitempty"` LoadProfile *LoadProfile `toml:",omitempty"` + ReorgProfile *ReorgProfile `toml:",omitempty"` } func (c *CCIPTestGroupConfig) Validate() error { @@ -296,6 +306,11 @@ func (c *CCIPTestGroupConfig) Validate() error { return fmt.Errorf("test run name should be set if existing deployment is true and test is running in k8s") } } + if c.ReorgProfile != nil { + if err := c.ReorgProfile.Validate(); err != nil { + return err + } + } } err := c.MsgDetails.Validate() if err != nil { diff --git a/integration-tests/ccip-tests/testconfig/tomls/ccip-reorg.toml b/integration-tests/ccip-tests/testconfig/tomls/ccip-reorg.toml new file mode 100644 index 0000000000..afcba2247f --- /dev/null +++ b/integration-tests/ccip-tests/testconfig/tomls/ccip-reorg.toml @@ -0,0 +1,64 @@ +[CCIP] +[CCIP.Env] +Mockserver = 'http://mockserver:1080' +[CCIP.Env.Network] +selected_networks= ['SIMULATED_1', 'SIMULATED_2'] + +[CCIP.Env.Network.EVMNetworks.SIMULATED_1] +evm_name = 'source-chain' +evm_chain_id = 1337 +evm_keys = ['59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d', '7c852118294e51e653712a81e05800f419141751be58f605c371e15141b007a6'] +evm_simulated = true +client_implementation = 'Ethereum' +evm_chainlink_transaction_limit = 5000 +evm_transaction_timeout = '3m' +evm_minimum_confirmations = 1 +evm_gas_estimation_buffer = 1000 +evm_supports_eip1559 = true +evm_default_gas_limit = 6000000 +evm_finality_depth = 10 + +[CCIP.Env.Network.EVMNetworks.SIMULATED_2] +evm_name = 'dest-chain' +evm_chain_id = 2337 +evm_keys = ['ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80', '7c852118294e51e653712a81e05800f419141751be58f605c371e15141b007a6'] +evm_simulated = true +client_implementation = 'Ethereum' +evm_chainlink_transaction_limit = 5000 +evm_transaction_timeout = '3m' +evm_minimum_confirmations = 1 +evm_gas_estimation_buffer = 1000 +evm_supports_eip1559 = true +evm_default_gas_limit = 6000000 +evm_finality_depth = 10 + +[CCIP.Env.NewCLCluster] +NoOfNodes = 6 +NodeMemory = '4Gi' +NodeCPU = '2' +DBMemory = '4Gi' +DBCPU = '2' +DBCapacity = '10Gi' +IsStateful = true +DBArgs = ['shared_buffers=1536MB', 'effective_cache_size=4096MB', 'work_mem=64MB'] + +[CCIP.Env.NewCLCluster.Common] +CommonChainConfigTOML = """ +LogPollInterval = '1s' +[HeadTracker] +HistoryDepth = 30 + +[GasEstimator] +PriceMax = '200 gwei' +LimitDefault = 6000000 +FeeCapDefault = '200 gwei' +""" + +[CCIP.Groups.smoke] +PhaseTimeout = '3m' # Duration to wait for the each phase validation(SendRequested, Commit, RMN Blessing, Execution) to time-out. +LocalCluster = true + +[CCIP.Groups.smoke.ReorgProfile] +FinalityDelta = 5 + + From 31a15dd6217ce341320a5479990852598992eeaa Mon Sep 17 00:00:00 2001 From: Ryan <80392855+RayXpub@users.noreply.github.com> Date: Tue, 10 Sep 2024 12:55:01 +0400 Subject: [PATCH 080/115] Implement getTotalChainConfigurations (#1419) ## Motivation The goal of this PR is to add a getter function to the `CCIPConfig` contract to fetch the total number of chains configured. This value is necessary to correctly call `getAllChainConfigs` and previously, the only way to access it was through events. ## Solution Implement `getTotalChainConfigurations`. --- contracts/gas-snapshots/ccip.gas-snapshot | 50 +++++++++---------- .../src/v0.8/ccip/capability/CCIPConfig.sol | 6 +++ .../ccip/test/capability/CCIPConfig.t.sol | 6 ++- .../ccip/generated/ccip_config/ccip_config.go | 28 ++++++++++- ...rapper-dependency-versions-do-not-edit.txt | 2 +- 5 files changed, 63 insertions(+), 29 deletions(-) diff --git a/contracts/gas-snapshots/ccip.gas-snapshot b/contracts/gas-snapshots/ccip.gas-snapshot index 8d215c59b5..180da04db6 100644 --- a/contracts/gas-snapshots/ccip.gas-snapshot +++ b/contracts/gas-snapshots/ccip.gas-snapshot @@ -36,44 +36,44 @@ BurnWithFromMintTokenPool_lockOrBurn:test_PoolBurn_Success() (gas: 243707) BurnWithFromMintTokenPool_lockOrBurn:test_Setup_Success() (gas: 23951) CCIPClientExample_sanity:test_ImmutableExamples_Success() (gas: 2096747) CCIPConfigSetup:test_getCapabilityConfiguration_Success() (gas: 9539) -CCIPConfig_ConfigStateMachine:test__computeConfigDigest_Success() (gas: 66088) -CCIPConfig_ConfigStateMachine:test__computeNewConfigWithMeta_InitToRunning_Success() (gas: 358063) -CCIPConfig_ConfigStateMachine:test__computeNewConfigWithMeta_RunningToStaging_Success() (gas: 474771) -CCIPConfig_ConfigStateMachine:test__computeNewConfigWithMeta_StagingToRunning_Success() (gas: 441974) -CCIPConfig_ConfigStateMachine:test__groupByPluginType_TooManyOCR3Configs_Reverts() (gas: 33804) -CCIPConfig_ConfigStateMachine:test__groupByPluginType_threeCommitConfigs_Reverts() (gas: 56870) -CCIPConfig_ConfigStateMachine:test__groupByPluginType_threeExecutionConfigs_Reverts() (gas: 56808) +CCIPConfig_ConfigStateMachine:test__computeConfigDigest_Success() (gas: 66000) +CCIPConfig_ConfigStateMachine:test__computeNewConfigWithMeta_InitToRunning_Success() (gas: 358041) +CCIPConfig_ConfigStateMachine:test__computeNewConfigWithMeta_RunningToStaging_Success() (gas: 474705) +CCIPConfig_ConfigStateMachine:test__computeNewConfigWithMeta_StagingToRunning_Success() (gas: 441908) +CCIPConfig_ConfigStateMachine:test__groupByPluginType_TooManyOCR3Configs_Reverts() (gas: 33848) +CCIPConfig_ConfigStateMachine:test__groupByPluginType_threeCommitConfigs_Reverts() (gas: 56914) +CCIPConfig_ConfigStateMachine:test__groupByPluginType_threeExecutionConfigs_Reverts() (gas: 56852) CCIPConfig_ConfigStateMachine:test__stateFromConfigLength_Success() (gas: 11719) -CCIPConfig_ConfigStateMachine:test__validateConfigStateTransition_Success() (gas: 8780) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_InitToRunning_Success() (gas: 309744) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_InitToRunning_WrongConfigCount_Reverts() (gas: 45887) +CCIPConfig_ConfigStateMachine:test__validateConfigStateTransition_Success() (gas: 8849) +CCIPConfig_ConfigStateMachine:test__validateConfigTransition_InitToRunning_Success() (gas: 309722) +CCIPConfig_ConfigStateMachine:test__validateConfigTransition_InitToRunning_WrongConfigCount_Reverts() (gas: 45865) CCIPConfig_ConfigStateMachine:test__validateConfigTransition_NonExistentConfigTransition_Reverts() (gas: 29690) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_RunningToStaging_Success() (gas: 370075) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_RunningToStaging_WrongConfigCount_Reverts() (gas: 111442) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_RunningToStaging_WrongConfigDigestBlueGreen_Reverts() (gas: 145556) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_StagingToRunning_Success() (gas: 369851) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_StagingToRunning_WrongConfigDigest_Reverts() (gas: 145623) +CCIPConfig_ConfigStateMachine:test__validateConfigTransition_RunningToStaging_Success() (gas: 370009) +CCIPConfig_ConfigStateMachine:test__validateConfigTransition_RunningToStaging_WrongConfigCount_Reverts() (gas: 111376) +CCIPConfig_ConfigStateMachine:test__validateConfigTransition_RunningToStaging_WrongConfigDigestBlueGreen_Reverts() (gas: 145446) +CCIPConfig_ConfigStateMachine:test__validateConfigTransition_StagingToRunning_Success() (gas: 369785) +CCIPConfig_ConfigStateMachine:test__validateConfigTransition_StagingToRunning_WrongConfigDigest_Reverts() (gas: 145513) CCIPConfig_ConfigStateMachine:test_getCapabilityConfiguration_Success() (gas: 9627) -CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_CommitAndExecConfig_Success() (gas: 1752579) -CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_CommitConfigOnly_Success() (gas: 1019042) -CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_ExecConfigOnly_Success() (gas: 1019073) +CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_CommitAndExecConfig_Success() (gas: 1752535) +CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_CommitConfigOnly_Success() (gas: 1019020) +CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_ExecConfigOnly_Success() (gas: 1019051) CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_OnlyCapabilitiesRegistryCanCall_Reverts() (gas: 9611) CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_ZeroLengthConfig_Success() (gas: 15996) CCIPConfig_beforeCapabilityConfigSet:test_getCapabilityConfiguration_Success() (gas: 9627) CCIPConfig_chainConfig:test__applyChainConfigUpdates_FChainNotPositive_Reverts() (gas: 184771) -CCIPConfig_chainConfig:test_applyChainConfigUpdates_addChainConfigs_Success() (gas: 344939) +CCIPConfig_chainConfig:test_applyChainConfigUpdates_addChainConfigs_Success() (gas: 346687) CCIPConfig_chainConfig:test_applyChainConfigUpdates_nodeNotInRegistry_Reverts() (gas: 20340) -CCIPConfig_chainConfig:test_applyChainConfigUpdates_removeChainConfigs_Success() (gas: 267596) +CCIPConfig_chainConfig:test_applyChainConfigUpdates_removeChainConfigs_Success() (gas: 270334) CCIPConfig_chainConfig:test_applyChainConfigUpdates_selectorNotFound_Reverts() (gas: 14819) CCIPConfig_chainConfig:test_getCapabilityConfiguration_Success() (gas: 9648) CCIPConfig_chainConfig:test_getPaginatedCCIPConfigs_Success() (gas: 370293) -CCIPConfig_constructor:test_constructor_Success() (gas: 3334093) -CCIPConfig_constructor:test_constructor_ZeroAddressNotAllowed_Revert() (gas: 61438) -CCIPConfig_updatePluginConfig:test__updatePluginConfig_InitToRunning_Success() (gas: 1008449) +CCIPConfig_constructor:test_constructor_Success() (gas: 3344515) +CCIPConfig_constructor:test_constructor_ZeroAddressNotAllowed_Revert() (gas: 61446) +CCIPConfig_updatePluginConfig:test__updatePluginConfig_InitToRunning_Success() (gas: 1008427) CCIPConfig_updatePluginConfig:test__updatePluginConfig_InvalidConfigLength_Reverts() (gas: 25584) CCIPConfig_updatePluginConfig:test__updatePluginConfig_InvalidConfigStateTransition_Reverts() (gas: 21799) -CCIPConfig_updatePluginConfig:test__updatePluginConfig_RunningToStaging_Success() (gas: 1895621) -CCIPConfig_updatePluginConfig:test__updatePluginConfig_StagingToRunning_Success() (gas: 2465231) +CCIPConfig_updatePluginConfig:test__updatePluginConfig_RunningToStaging_Success() (gas: 1895604) +CCIPConfig_updatePluginConfig:test__updatePluginConfig_StagingToRunning_Success() (gas: 2465196) CCIPConfig_updatePluginConfig:test_getCapabilityConfiguration_Success() (gas: 9627) CCIPConfig_validateConfig:test__validateConfig_ABIEncodedAddress_OfframpAddressCannotBeZero_Reverts() (gas: 290828) CCIPConfig_validateConfig:test__validateConfig_ChainSelectorNotFound_Reverts() (gas: 293559) diff --git a/contracts/src/v0.8/ccip/capability/CCIPConfig.sol b/contracts/src/v0.8/ccip/capability/CCIPConfig.sol index 463a710335..84feb2a061 100644 --- a/contracts/src/v0.8/ccip/capability/CCIPConfig.sol +++ b/contracts/src/v0.8/ccip/capability/CCIPConfig.sol @@ -101,6 +101,12 @@ contract CCIPConfig is ITypeAndVersion, ICapabilityConfiguration, OwnerIsCreator return i_capabilitiesRegistry; } + /// @notice Returns the total number of chains configured. + /// @return The total number of chains configured. + function getNumChainConfigurations() external view returns (uint256) { + return s_remoteChainSelectors.length(); + } + /// @notice Returns all the chain configurations. /// @param pageIndex The page index. /// @param pageSize The page size. diff --git a/contracts/src/v0.8/ccip/test/capability/CCIPConfig.t.sol b/contracts/src/v0.8/ccip/test/capability/CCIPConfig.t.sol index 721f5d3463..0ec50914bf 100644 --- a/contracts/src/v0.8/ccip/test/capability/CCIPConfig.t.sol +++ b/contracts/src/v0.8/ccip/test/capability/CCIPConfig.t.sol @@ -1,7 +1,6 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.24; -import {SortedSetValidationUtil} from "../../../shared/util/SortedSetValidationUtil.sol"; import {CCIPConfig} from "../../capability/CCIPConfig.sol"; import {ICapabilitiesRegistry} from "../../capability/interfaces/ICapabilitiesRegistry.sol"; import {CCIPConfigTypes} from "../../capability/libraries/CCIPConfigTypes.sol"; @@ -164,6 +163,7 @@ contract CCIPConfig_chainConfig is CCIPConfigSetup { assertEq(configs.length, 2, "chain configs length must be 2"); assertEq(configs[0].chainSelector, 1, "chain selector must match"); assertEq(configs[1].chainSelector, 2, "chain selector must match"); + assertEq(s_ccipCC.getNumChainConfigurations(), 2, "total chain configs must be 2"); } function test_getPaginatedCCIPConfigs_Success() public { @@ -252,12 +252,16 @@ contract CCIPConfig_chainConfig is CCIPConfigSetup { emit CCIPConfig.ChainConfigSet(2, adds[1].chainConfig); s_ccipCC.applyChainConfigUpdates(new uint64[](0), adds); + assertEq(s_ccipCC.getNumChainConfigurations(), 2, "total chain configs must be 2"); + uint64[] memory removes = new uint64[](1); removes[0] = uint64(1); vm.expectEmit(); emit CCIPConfig.ChainConfigRemoved(1); s_ccipCC.applyChainConfigUpdates(removes, new CCIPConfigTypes.ChainConfigInfo[](0)); + + assertEq(s_ccipCC.getNumChainConfigurations(), 1, "total chain configs must be 1"); } // Reverts. diff --git a/core/gethwrappers/ccip/generated/ccip_config/ccip_config.go b/core/gethwrappers/ccip/generated/ccip_config/ccip_config.go index 3c2d44cd30..dd61552789 100644 --- a/core/gethwrappers/ccip/generated/ccip_config/ccip_config.go +++ b/core/gethwrappers/ccip/generated/ccip_config/ccip_config.go @@ -60,8 +60,8 @@ type CCIPConfigTypesOCR3ConfigWithMeta struct { } var CCIPConfigMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"capabilitiesRegistry\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainSelectorNotFound\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ChainSelectorNotSet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FChainMustBePositive\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FMustBePositive\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FTooHigh\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"length\",\"type\":\"uint256\"}],\"name\":\"InvalidConfigLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enumCCIPConfigTypes.ConfigState\",\"name\":\"currentState\",\"type\":\"uint8\"},{\"internalType\":\"enumCCIPConfigTypes.ConfigState\",\"name\":\"proposedState\",\"type\":\"uint8\"}],\"name\":\"InvalidConfigStateTransition\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidPluginType\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"}],\"name\":\"NodeNotInRegistry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonExistentConfigTransition\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"got\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minimum\",\"type\":\"uint256\"}],\"name\":\"NotEnoughTransmitters\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OfframpAddressCannotBeZero\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCapabilitiesRegistryCanCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"p2pIdsLength\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"signersLength\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"transmittersLength\",\"type\":\"uint256\"}],\"name\":\"P2PIdsLengthNotMatching\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManyOCR3Configs\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManySigners\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"got\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"expected\",\"type\":\"uint64\"}],\"name\":\"WrongConfigCount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"got\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"}],\"name\":\"WrongConfigDigest\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"got\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"}],\"name\":\"WrongConfigDigestBlueGreen\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"CapabilityConfigurationSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainConfigRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes32[]\",\"name\":\"readers\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint8\",\"name\":\"fChain\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"structCCIPConfigTypes.ChainConfig\",\"name\":\"chainConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"chainSelectorRemoves\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes32[]\",\"name\":\"readers\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint8\",\"name\":\"fChain\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPConfigTypes.ChainConfig\",\"name\":\"chainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structCCIPConfigTypes.ChainConfigInfo[]\",\"name\":\"chainConfigAdds\",\"type\":\"tuple[]\"}],\"name\":\"applyChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"}],\"name\":\"beforeCapabilityConfigSet\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"pageIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pageSize\",\"type\":\"uint256\"}],\"name\":\"getAllChainConfigs\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes32[]\",\"name\":\"readers\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint8\",\"name\":\"fChain\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPConfigTypes.ChainConfig\",\"name\":\"chainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structCCIPConfigTypes.ChainConfigInfo[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"name\":\"getCapabilityConfiguration\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"configuration\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCapabilityRegistry\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"}],\"name\":\"getOCRConfig\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offrampAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"p2pIds\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes[]\",\"name\":\"signers\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes[]\",\"name\":\"transmitters\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPConfigTypes.OCR3Config\",\"name\":\"config\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"configCount\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"internalType\":\"structCCIPConfigTypes.OCR3ConfigWithMeta[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x60a06040523480156200001157600080fd5b5060405162004080380380620040808339810160408190526200003491620001a6565b33806000816200008b5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000be57620000be81620000fb565b5050506001600160a01b038116620000e9576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b0316608052620001d8565b336001600160a01b03821603620001555760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000082565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600060208284031215620001b957600080fd5b81516001600160a01b0381168114620001d157600080fd5b9392505050565b608051613e7f620002016000396000818160f801528181610ea701526111170152613e7f6000f3fe608060405234801561001057600080fd5b50600436106100c95760003560e01c80638318ed5d11610081578063f2fde38b1161005b578063f2fde38b1461020f578063f442c89a14610222578063fba64a7c1461023557600080fd5b80638318ed5d146101b05780638da5cb5b146101d1578063b74b2356146101ef57600080fd5b8063181f5a77116100b2578063181f5a771461013d5780634bd0473f1461018657806379ba5097146101a657600080fd5b806301ffc9a7146100ce578063020330e6146100f6575b600080fd5b6100e16100dc366004612cbd565b610248565b60405190151581526020015b60405180910390f35b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100ed565b6101796040518060400160405280601481526020017f43434950436f6e66696720312e362e302d64657600000000000000000000000081525081565b6040516100ed9190612d63565b610199610194366004612da7565b6102e1565b6040516100ed9190612ec6565b6101ae610759565b005b6101796101be366004613082565b5060408051602081019091526000815290565b60005473ffffffffffffffffffffffffffffffffffffffff16610118565b6102026101fd36600461309f565b61085b565b6040516100ed9190613105565b6101ae61021d366004613195565b610adc565b6101ae610230366004613217565b610af0565b6101ae61024336600461329b565b610e8f565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f78bea7210000000000000000000000000000000000000000000000000000000014806102db57507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b63ffffffff8216600090815260056020526040812060609183600181111561030b5761030b612ddc565b600181111561031c5761031c612ddc565b8152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b8282101561074d57600084815260209020604080516101808101909152600884029091018054829060608201908390829060ff16600181111561038f5761038f612ddc565b60018111156103a0576103a0612ddc565b8152815467ffffffffffffffff61010082048116602084015260ff690100000000000000000083041660408401526a01000000000000000000009091041660608201526001820180546080909201916103f890613358565b80601f016020809104026020016040519081016040528092919081815260200182805461042490613358565b80156104715780601f1061044657610100808354040283529160200191610471565b820191906000526020600020905b81548152906001019060200180831161045457829003601f168201915b50505050508152602001600282018054806020026020016040519081016040528092919081815260200182805480156104c957602002820191906000526020600020905b8154815260200190600101908083116104b5575b5050505050815260200160038201805480602002602001604051908101604052809291908181526020016000905b828210156105a357838290600052602060002001805461051690613358565b80601f016020809104026020016040519081016040528092919081815260200182805461054290613358565b801561058f5780601f106105645761010080835404028352916020019161058f565b820191906000526020600020905b81548152906001019060200180831161057257829003601f168201915b5050505050815260200190600101906104f7565b50505050815260200160048201805480602002602001604051908101604052809291908181526020016000905b8282101561067c5783829060005260206000200180546105ef90613358565b80601f016020809104026020016040519081016040528092919081815260200182805461061b90613358565b80156106685780601f1061063d57610100808354040283529160200191610668565b820191906000526020600020905b81548152906001019060200180831161064b57829003601f168201915b5050505050815260200190600101906105d0565b50505050815260200160058201805461069490613358565b80601f01602080910402602001604051908101604052809291908181526020018280546106c090613358565b801561070d5780601f106106e25761010080835404028352916020019161070d565b820191906000526020600020905b8154815290600101906020018083116106f057829003601f168201915b505050919092525050508152600682015467ffffffffffffffff16602080830191909152600790920154604090910152908252600192909201910161034a565b50505050905092915050565b60015473ffffffffffffffffffffffffffffffffffffffff1633146107df576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b606060006108696003610f4a565b9050600061087784866133da565b90508315806108865750818110155b156108c65760408051600080825260208201909252906108bc565b6108a9612a5c565b8152602001906001900390816108a15790505b50925050506102db565b60006108d28583613420565b9050828111156108df5750815b60006108eb8383613433565b67ffffffffffffffff811115610903576109036133f1565b60405190808252806020026020018201604052801561093c57816020015b610929612a5c565b8152602001906001900390816109215790505b509050600061094b6003610f54565b9050835b83811015610acf57600082828151811061096b5761096b613446565b60209081029190910181015160408051808201825267ffffffffffffffff8316808252600090815260028552829020825181546080818802830181019095526060820181815295975092958601949093919284928491908401828280156109f157602002820191906000526020600020905b8154815260200190600101908083116109dd575b5050509183525050600182015460ff166020820152600282018054604090920191610a1b90613358565b80601f0160208091040260200160405190810160405280929190818152602001828054610a4790613358565b8015610a945780601f10610a6957610100808354040283529160200191610a94565b820191906000526020600020905b815481529060010190602001808311610a7757829003601f168201915b50505091909252505050905284610aab8885613433565b81518110610abb57610abb613446565b60209081029190910101525060010161094f565b5090979650505050505050565b610ae4610f68565b610aed81610feb565b50565b610af8610f68565b60005b83811015610cde57610b3f858583818110610b1857610b18613446565b9050602002016020810190610b2d9190613475565b60039067ffffffffffffffff166110e0565b610ba957848482818110610b5557610b55613446565b9050602002016020810190610b6a9190613475565b6040517f1bd4d2d200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016107d6565b60026000868684818110610bbf57610bbf613446565b9050602002016020810190610bd49190613475565b67ffffffffffffffff1681526020810191909152604001600090812090610bfb8282612aa4565b6001820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055610c33600283016000612ac2565b5050610c71858583818110610c4a57610c4a613446565b9050602002016020810190610c5f9190613475565b60039067ffffffffffffffff166110f8565b507f2a680691fef3b2d105196805935232c661ce703e92d464ef0b94a7bc62d714f0858583818110610ca557610ca5613446565b9050602002016020810190610cba9190613475565b60405167ffffffffffffffff909116815260200160405180910390a1600101610afb565b5060005b81811015610e88576000838383818110610cfe57610cfe613446565b9050602002810190610d109190613490565b610d1e9060208101906134ce565b610d27906136d0565b90506000848484818110610d3d57610d3d613446565b9050602002810190610d4f9190613490565b610d5d906020810190613475565b9050610d6c8260000151611104565b816020015160ff16600003610dad576040517fa9b3766e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff81166000908152600260209081526040909120835180518593610ddd928492910190612afc565b5060208201516001820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff90921691909117905560408201516002820190610e2a90826137b7565b50610e4491506003905067ffffffffffffffff8316611250565b507f05dd57854af2c291a94ea52e7c43d80bc3be7fa73022f98b735dea86642fa5e08183604051610e769291906138d1565b60405180910390a15050600101610ce2565b5050505050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610efe576040517fac7a7efd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080610f15610f108688018861397c565b61125c565b8151919350915015610f2d57610f2d836000846114a7565b805115610f4057610f40836001836114a7565b5050505050505050565b60006102db825490565b60606000610f6183611c09565b9392505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610fe9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016107d6565b565b3373ffffffffffffffffffffffffffffffffffffffff82160361106a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016107d6565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60008181526001830160205260408120541515610f61565b6000610f618383611c65565b60005b815181101561124c5760008019167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166350c946fe84848151811061116357611163613446565b60200260200101516040518263ffffffff1660e01b815260040161118991815260200190565b600060405180830381865afa1580156111a6573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526111ec9190810190613bc7565b60800151036112445781818151811061120757611207613446565b60200260200101516040517f8907a4fa0000000000000000000000000000000000000000000000000000000081526004016107d691815260200190565b600101611107565b5050565b6000610f618383611d5f565b606080600460ff168351111561129e576040517f8854586400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160028082526060820190925290816020015b61131b6040805161012081019091528060008152602001600067ffffffffffffffff168152602001600060ff168152602001600067ffffffffffffffff16815260200160608152602001606081526020016060815260200160608152602001606081525090565b8152602001906001900390816112b457505060408051600280825260608201909252919350602082015b6113ac6040805161012081019091528060008152602001600067ffffffffffffffff168152602001600060ff168152602001600067ffffffffffffffff16815260200160608152602001606081526020016060815260200160608152602001606081525090565b81526020019060019003908161134557905050905060008060005b855181101561149a5760008682815181106113e4576113e4613446565b602002602001015160000151600181111561140157611401612ddc565b0361144e5785818151811061141857611418613446565b602002602001015185848151811061143257611432613446565b60200260200101819052508261144790613c9f565b9250611492565b85818151811061146057611460613446565b602002602001015184838151811061147a5761147a613446565b60200260200101819052508161148f90613c9f565b91505b6001016113c7565b5090835281529092909150565b63ffffffff83166000908152600560205260408120818460018111156114cf576114cf612ddc565b60018111156114e0576114e0612ddc565b8152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b8282101561191157600084815260209020604080516101808101909152600884029091018054829060608201908390829060ff16600181111561155357611553612ddc565b600181111561156457611564612ddc565b8152815467ffffffffffffffff61010082048116602084015260ff690100000000000000000083041660408401526a01000000000000000000009091041660608201526001820180546080909201916115bc90613358565b80601f01602080910402602001604051908101604052809291908181526020018280546115e890613358565b80156116355780601f1061160a57610100808354040283529160200191611635565b820191906000526020600020905b81548152906001019060200180831161161857829003601f168201915b505050505081526020016002820180548060200260200160405190810160405280929190818152602001828054801561168d57602002820191906000526020600020905b815481526020019060010190808311611679575b5050505050815260200160038201805480602002602001604051908101604052809291908181526020016000905b828210156117675783829060005260206000200180546116da90613358565b80601f016020809104026020016040519081016040528092919081815260200182805461170690613358565b80156117535780601f1061172857610100808354040283529160200191611753565b820191906000526020600020905b81548152906001019060200180831161173657829003601f168201915b5050505050815260200190600101906116bb565b50505050815260200160048201805480602002602001604051908101604052809291908181526020016000905b828210156118405783829060005260206000200180546117b390613358565b80601f01602080910402602001604051908101604052809291908181526020018280546117df90613358565b801561182c5780601f106118015761010080835404028352916020019161182c565b820191906000526020600020905b81548152906001019060200180831161180f57829003601f168201915b505050505081526020019060010190611794565b50505050815260200160058201805461185890613358565b80601f016020809104026020016040519081016040528092919081815260200182805461188490613358565b80156118d15780601f106118a6576101008083540402835291602001916118d1565b820191906000526020600020905b8154815290600101906020018083116118b457829003601f168201915b505050919092525050508152600682015467ffffffffffffffff16602080830191909152600790920154604090910152908252600192909201910161150e565b50505050905060006119238251611dae565b905060006119318451611dae565b905061193d8282611e00565b600061194c8785878686611ebc565b905061195884826122a0565b63ffffffff871660009081526005602052604081209087600181111561198057611980612ddc565b600181111561199157611991612ddc565b815260200190815260200160002060006119ab9190612b47565b60005b8151811015610f405763ffffffff88166000908152600560205260408120908860018111156119df576119df612ddc565b60018111156119f0576119f0612ddc565b8152602001908152602001600020828281518110611a1057611a10613446565b6020908102919091018101518254600181810185556000948552929093208151805160089095029091018054929490939192849283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016908381811115611a7a57611a7a612ddc565b021790555060208201518154604084015160608501517fffffffffffffffffffffffffffffffffffffffffffff000000000000000000ff90921661010067ffffffffffffffff948516027fffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffff1617690100000000000000000060ff90921691909102177fffffffffffffffffffffffffffff0000000000000000ffffffffffffffffffff166a0100000000000000000000929091169190910217815560808201516001820190611b4990826137b7565b5060a08201518051611b65916002840191602090910190612afc565b5060c08201518051611b81916003840191602090910190612b68565b5060e08201518051611b9d916004840191602090910190612b68565b506101008201516005820190611bb390826137b7565b50505060208201516006820180547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff9092169190911790556040909101516007909101556001016119ae565b606081600001805480602002602001604051908101604052809291908181526020018280548015611c5957602002820191906000526020600020905b815481526020019060010190808311611c45575b50505050509050919050565b60008181526001830160205260408120548015611d4e576000611c89600183613433565b8554909150600090611c9d90600190613433565b9050808214611d02576000866000018281548110611cbd57611cbd613446565b9060005260206000200154905080876000018481548110611ce057611ce0613446565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080611d1357611d13613cd7565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506102db565b60009150506102db565b5092915050565b6000818152600183016020526040812054611da6575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556102db565b5060006102db565b60006002821115611dee576040517f3e478526000000000000000000000000000000000000000000000000000000008152600481018390526024016107d6565b8160028111156102db576102db612ddc565b6000826002811115611e1457611e14612ddc565b826002811115611e2657611e26612ddc565b611e309190613d06565b90508060011480611e7c5750807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff148015611e7c57506002836002811115611e7a57611e7a612ddc565b145b15611e8657505050565b82826040517f0a6b675b0000000000000000000000000000000000000000000000000000000081526004016107d6929190613d36565b60606000845167ffffffffffffffff811115611eda57611eda6133f1565b604051908082528060200260200182016040528015611f03578160200160208202803683370190505b5090506000846002811115611f1a57611f1a612ddc565b148015611f3857506001836002811115611f3657611f36612ddc565b145b15611f7957600181600081518110611f5257611f52613446565b602002602001019067ffffffffffffffff16908167ffffffffffffffff16815250506120e1565b6001846002811115611f8d57611f8d612ddc565b148015611fab57506002836002811115611fa957611fa9612ddc565b145b156120425785600081518110611fc357611fc3613446565b60200260200101516020015181600081518110611fe257611fe2613446565b602002602001019067ffffffffffffffff16908167ffffffffffffffff16815250508560008151811061201757612017613446565b602002602001015160200151600161202f9190613d51565b81600181518110611f5257611f52613446565b600284600281111561205657612056612ddc565b1480156120745750600183600281111561207257612072612ddc565b145b156120ab578560018151811061208c5761208c613446565b60200260200101516020015181600081518110611f5257611f52613446565b83836040517f0a6b675b0000000000000000000000000000000000000000000000000000000081526004016107d6929190613d36565b6000855167ffffffffffffffff8111156120fd576120fd6133f1565b6040519080825280602002602001820160405280156121ab57816020015b6040805161018081018252600060608083018281526080840183905260a0840183905260c0840183905260e08401829052610100840182905261012084018290526101408401829052610160840191909152825260208083018290529282015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90920191018161211b5790505b50905060005b8251811015612294576121dc8782815181106121cf576121cf613446565b602002602001015161261f565b60405180606001604052808883815181106121f9576121f9613446565b6020026020010151815260200184838151811061221857612218613446565b602002602001015167ffffffffffffffff16815260200161226c8b86858151811061224557612245613446565b60200260200101518b868151811061225f5761225f613446565b602002602001015161298e565b81525082828151811061228157612281613446565b60209081029190910101526001016121b1565b50979650505050505050565b81518151811580156122b25750806001145b1561235457826000815181106122ca576122ca613446565b60200260200101516020015167ffffffffffffffff1660011461234e57826000815181106122fa576122fa613446565b60209081029190910181015101516040517fc1658eb800000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152600160248201526044016107d6565b50505050565b8160011480156123645750806002145b1561251a578360008151811061237c5761237c613446565b6020026020010151604001518360008151811061239b5761239b613446565b6020026020010151604001511461242757826000815181106123bf576123bf613446565b602002602001015160400151846000815181106123de576123de613446565b6020026020010151604001516040517fc7ccdd7f0000000000000000000000000000000000000000000000000000000081526004016107d6929190918252602082015260400190565b8360008151811061243a5761243a613446565b60200260200101516020015160016124529190613d51565b67ffffffffffffffff168360018151811061246f5761246f613446565b60200260200101516020015167ffffffffffffffff161461234e578260018151811061249d5761249d613446565b602002602001015160200151846000815181106124bc576124bc613446565b60200260200101516020015160016124d49190613d51565b6040517fc1658eb800000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9283166004820152911660248201526044016107d6565b81600214801561252a5750806001145b156125ed578360018151811061254257612542613446565b6020026020010151604001518360008151811061256157612561613446565b6020026020010151604001511461234e578260008151811061258557612585613446565b602002602001015160400151846001815181106125a4576125a4613446565b6020026020010151604001516040517f9e9756700000000000000000000000000000000000000000000000000000000081526004016107d6929190918252602082015260400190565b6040517f1f1b2bb600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806020015167ffffffffffffffff16600003612667576040517f698cf8e000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008151600181111561267c5761267c612ddc565b1415801561269d575060018151600181111561269a5761269a612ddc565b14155b156126d4576040517f3302dbd700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6080810151511580612711575060408051600060208201520160405160208183030381529060405280519060200120816080015180519060200120145b15612748576040517f358c192700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208101516127639060039067ffffffffffffffff166110e0565b6127ab5760208101516040517f1bd4d2d200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016107d6565b60208082015167ffffffffffffffff166000908152600290915260408120600101546127db9060ff166003613d72565b6127e6906001613d8e565b60ff169050808260e0015151101561283b5760e0820151516040517f548dd21f0000000000000000000000000000000000000000000000000000000081526004810191909152602481018290526044016107d6565b60c08201515161010081111561287d576040517f1b925da600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8260a00151518114158061289657508260e00151518114155b156128f05760a08301515160c08401515160e0850151516040517fba900f6d0000000000000000000000000000000000000000000000000000000081526004810193909352602483019190915260448201526064016107d6565b826040015160ff16600003612931576040517f39d1a4d000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040830151612941906003613d72565b60ff16811161297c576040517f4856694e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6129898360a00151611104565b505050565b60008082602001518584600001518560800151878760a001518860c001518960e001518a604001518b606001518c61010001516040516020016129db9b9a99989796959493929190613da7565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e0a000000000000000000000000000000000000000000000000000000000000179150509392505050565b6040518060400160405280600067ffffffffffffffff168152602001612a9f604051806060016040528060608152602001600060ff168152602001606081525090565b905290565b5080546000825590600052602060002090810190610aed9190612bba565b508054612ace90613358565b6000825580601f10612ade575050565b601f016020900490600052602060002090810190610aed9190612bba565b828054828255906000526020600020908101928215612b37579160200282015b82811115612b37578251825591602001919060010190612b1c565b50612b43929150612bba565b5090565b5080546000825560080290600052602060002090810190610aed9190612bcf565b828054828255906000526020600020908101928215612bae579160200282015b82811115612bae5782518290612b9e90826137b7565b5091602001919060010190612b88565b50612b43929150612c82565b5b80821115612b435760008155600101612bbb565b80821115612b435780547fffffffffffffffffffffffffffff00000000000000000000000000000000000016815560008181612c0e6001830182612ac2565b612c1c600283016000612aa4565b612c2a600383016000612c9f565b612c38600483016000612c9f565b612c46600583016000612ac2565b5050506006810180547fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000016905560006007820155600801612bcf565b80821115612b43576000612c968282612ac2565b50600101612c82565b5080546000825590600052602060002090810190610aed9190612c82565b600060208284031215612ccf57600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610f6157600080fd5b6000815180845260005b81811015612d2557602081850181015186830182015201612d09565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000610f616020830184612cff565b63ffffffff81168114610aed57600080fd5b8035612d9381612d76565b919050565b803560028110612d9357600080fd5b60008060408385031215612dba57600080fd5b8235612dc581612d76565b9150612dd360208401612d98565b90509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60028110612e1b57612e1b612ddc565b9052565b60008151808452602080850194506020840160005b83811015612e5057815187529582019590820190600101612e34565b509495945050505050565b60008282518085526020808601955060208260051b8401016020860160005b84811015610acf577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018952612eb4838351612cff565b98840198925090830190600101612e7a565b600060208083018184528085518083526040925060408601915060408160051b87010184880160005b83811015613074577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0898403018552815160608151818652612f348287018251612e0b565b898101516080612f4f8189018367ffffffffffffffff169052565b8a830151915060a0612f65818a018460ff169052565b938301519360c09250612f838984018667ffffffffffffffff169052565b818401519450610120915060e082818b0152612fa36101808b0187612cff565b95508185015191507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0610100818c890301818d0152612fe28885612e1f565b958701518c87038301868e0152959750612ffc8887612e5b565b9750828701519550818c8903016101408d01526130198887612e5b565b975080870151965050808b8803016101608c0152505050505061303c8282612cff565b915050888201516130588a87018267ffffffffffffffff169052565b5090870151938701939093529386019390860190600101612eef565b509098975050505050505050565b60006020828403121561309457600080fd5b8135610f6181612d76565b600080604083850312156130b257600080fd5b50508035926020909101359150565b60008151606084526130d66060850182612e1f565b905060ff6020840151166020850152604083015184820360408601526130fc8282612cff565b95945050505050565b600060208083018184528085518083526040925060408601915060408160051b87010184880160005b83811015613074578883037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00185528151805167ffffffffffffffff168452870151878401879052613182878501826130c1565b958801959350509086019060010161312e565b6000602082840312156131a757600080fd5b813573ffffffffffffffffffffffffffffffffffffffff81168114610f6157600080fd5b60008083601f8401126131dd57600080fd5b50813567ffffffffffffffff8111156131f557600080fd5b6020830191508360208260051b850101111561321057600080fd5b9250929050565b6000806000806040858703121561322d57600080fd5b843567ffffffffffffffff8082111561324557600080fd5b613251888389016131cb565b9096509450602087013591508082111561326a57600080fd5b50613277878288016131cb565b95989497509550505050565b803567ffffffffffffffff81168114612d9357600080fd5b600080600080600080608087890312156132b457600080fd5b863567ffffffffffffffff808211156132cc57600080fd5b6132d88a838b016131cb565b909850965060208901359150808211156132f157600080fd5b818901915089601f83011261330557600080fd5b81358181111561331457600080fd5b8a602082850101111561332657600080fd5b60208301965080955050505061333e60408801613283565b915061334c60608801612d88565b90509295509295509295565b600181811c9082168061336c57607f821691505b6020821081036133a5577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80820281158282048414176102db576102db6133ab565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b808201808211156102db576102db6133ab565b818103818111156102db576102db6133ab565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561348757600080fd5b610f6182613283565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc18336030181126134c457600080fd5b9190910192915050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa18336030181126134c457600080fd5b604051610120810167ffffffffffffffff81118282101715613526576135266133f1565b60405290565b60405160e0810167ffffffffffffffff81118282101715613526576135266133f1565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715613596576135966133f1565b604052919050565b600067ffffffffffffffff8211156135b8576135b86133f1565b5060051b60200190565b600082601f8301126135d357600080fd5b813560206135e86135e38361359e565b61354f565b8083825260208201915060208460051b87010193508684111561360a57600080fd5b602086015b84811015613626578035835291830191830161360f565b509695505050505050565b803560ff81168114612d9357600080fd5b600082601f83011261365357600080fd5b813567ffffffffffffffff81111561366d5761366d6133f1565b61369e60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160161354f565b8181528460208386010111156136b357600080fd5b816020850160208301376000918101602001919091529392505050565b6000606082360312156136e257600080fd5b6040516060810167ffffffffffffffff8282108183111715613706576137066133f1565b81604052843591508082111561371b57600080fd5b613727368387016135c2565b835261373560208601613631565b6020840152604085013591508082111561374e57600080fd5b5061375b36828601613642565b60408301525092915050565b601f821115612989576000816000526020600020601f850160051c810160208610156137905750805b601f850160051c820191505b818110156137af5782815560010161379c565b505050505050565b815167ffffffffffffffff8111156137d1576137d16133f1565b6137e5816137df8454613358565b84613767565b602080601f83116001811461383857600084156138025750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556137af565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b8281101561388557888601518255948401946001909101908401613866565b50858210156138c157878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b67ffffffffffffffff831681526040602082015260006138f460408301846130c1565b949350505050565b600082601f83011261390d57600080fd5b8135602061391d6135e38361359e565b82815260059290921b8401810191818101908684111561393c57600080fd5b8286015b8481101561362657803567ffffffffffffffff8111156139605760008081fd5b61396e8986838b0101613642565b845250918301918301613940565b6000602080838503121561398f57600080fd5b823567ffffffffffffffff808211156139a757600080fd5b818501915085601f8301126139bb57600080fd5b81356139c96135e38261359e565b81815260059190911b830184019084810190888311156139e857600080fd5b8585015b83811015613b5057803585811115613a0357600080fd5b8601610120818c037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001811315613a3957600080fd5b613a41613502565b613a4c8a8401612d98565b8152613a5a60408401613283565b8a820152613a6a60608401613631565b6040820152613a7b60808401613283565b606082015260a083013588811115613a9257600080fd5b613aa08e8c83870101613642565b60808301525060c083013588811115613ab857600080fd5b613ac68e8c838701016135c2565b60a08301525060e083013588811115613adf5760008081fd5b613aed8e8c838701016138fc565b60c0830152506101008084013589811115613b085760008081fd5b613b168f8d838801016138fc565b60e084015250918301359188831115613b2f5760008081fd5b613b3d8e8c85870101613642565b90820152855250509186019186016139ec565b5098975050505050505050565b8051612d9381612d76565b600082601f830112613b7957600080fd5b81516020613b896135e38361359e565b8083825260208201915060208460051b870101935086841115613bab57600080fd5b602086015b848110156136265780518352918301918301613bb0565b600060208284031215613bd957600080fd5b815167ffffffffffffffff80821115613bf157600080fd5b9083019060e08286031215613c0557600080fd5b613c0d61352c565b613c1683613b5d565b8152613c2460208401613b5d565b6020820152613c3560408401613b5d565b6040820152606083015160608201526080830151608082015260a083015182811115613c6057600080fd5b613c6c87828601613b68565b60a08301525060c083015182811115613c8457600080fd5b613c9087828601613b68565b60c08301525095945050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613cd057613cd06133ab565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b8181036000831280158383131683831282161715611d5857611d586133ab565b60038110612e1b57612e1b612ddc565b60408101613d448285613d26565b610f616020830184613d26565b67ffffffffffffffff818116838216019080821115611d5857611d586133ab565b60ff8181168382160290811690818114611d5857611d586133ab565b60ff81811683821601908111156102db576102db6133ab565b600061016067ffffffffffffffff8e16835263ffffffff8d166020840152613dd2604084018d612e0b565b806060840152613de48184018c612cff565b67ffffffffffffffff8b166080850152905082810360a0840152613e08818a612e1f565b905082810360c0840152613e1c8189612e5b565b905082810360e0840152613e308188612e5b565b60ff8716610100850152905067ffffffffffffffff8516610120840152828103610140840152613e608185612cff565b9e9d505050505050505050505050505056fea164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"capabilitiesRegistry\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainSelectorNotFound\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ChainSelectorNotSet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FChainMustBePositive\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FMustBePositive\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FTooHigh\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"length\",\"type\":\"uint256\"}],\"name\":\"InvalidConfigLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enumCCIPConfigTypes.ConfigState\",\"name\":\"currentState\",\"type\":\"uint8\"},{\"internalType\":\"enumCCIPConfigTypes.ConfigState\",\"name\":\"proposedState\",\"type\":\"uint8\"}],\"name\":\"InvalidConfigStateTransition\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidPluginType\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"}],\"name\":\"NodeNotInRegistry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonExistentConfigTransition\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"got\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minimum\",\"type\":\"uint256\"}],\"name\":\"NotEnoughTransmitters\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OfframpAddressCannotBeZero\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCapabilitiesRegistryCanCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"p2pIdsLength\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"signersLength\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"transmittersLength\",\"type\":\"uint256\"}],\"name\":\"P2PIdsLengthNotMatching\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManyOCR3Configs\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManySigners\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"got\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"expected\",\"type\":\"uint64\"}],\"name\":\"WrongConfigCount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"got\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"}],\"name\":\"WrongConfigDigest\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"got\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"}],\"name\":\"WrongConfigDigestBlueGreen\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"CapabilityConfigurationSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainConfigRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes32[]\",\"name\":\"readers\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint8\",\"name\":\"fChain\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"structCCIPConfigTypes.ChainConfig\",\"name\":\"chainConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"chainSelectorRemoves\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes32[]\",\"name\":\"readers\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint8\",\"name\":\"fChain\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPConfigTypes.ChainConfig\",\"name\":\"chainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structCCIPConfigTypes.ChainConfigInfo[]\",\"name\":\"chainConfigAdds\",\"type\":\"tuple[]\"}],\"name\":\"applyChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"}],\"name\":\"beforeCapabilityConfigSet\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"pageIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pageSize\",\"type\":\"uint256\"}],\"name\":\"getAllChainConfigs\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes32[]\",\"name\":\"readers\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint8\",\"name\":\"fChain\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPConfigTypes.ChainConfig\",\"name\":\"chainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structCCIPConfigTypes.ChainConfigInfo[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"name\":\"getCapabilityConfiguration\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"configuration\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCapabilityRegistry\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNumChainConfigurations\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"}],\"name\":\"getOCRConfig\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offrampAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"p2pIds\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes[]\",\"name\":\"signers\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes[]\",\"name\":\"transmitters\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPConfigTypes.OCR3Config\",\"name\":\"config\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"configCount\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"internalType\":\"structCCIPConfigTypes.OCR3ConfigWithMeta[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x60a06040523480156200001157600080fd5b50604051620040b3380380620040b38339810160408190526200003491620001a6565b33806000816200008b5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000be57620000be81620000fb565b5050506001600160a01b038116620000e9576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b0316608052620001d8565b336001600160a01b03821603620001555760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000082565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600060208284031215620001b957600080fd5b81516001600160a01b0381168114620001d157600080fd5b9392505050565b608051613eb1620002026000396000818161010301528181610ed901526111490152613eb16000f3fe608060405234801561001057600080fd5b50600436106100d45760003560e01c80638318ed5d11610081578063f2fde38b1161005b578063f2fde38b14610230578063f442c89a14610243578063fba64a7c1461025657600080fd5b80638318ed5d146101d15780638da5cb5b146101f2578063b74b23561461021057600080fd5b80634bd0473f116100b25780634bd0473f1461019157806379ba5097146101b15780637ac0d41e146101bb57600080fd5b806301ffc9a7146100d9578063020330e614610101578063181f5a7714610148575b600080fd5b6100ec6100e7366004612cef565b610269565b60405190151581526020015b60405180910390f35b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100f8565b6101846040518060400160405280601481526020017f43434950436f6e66696720312e362e302d64657600000000000000000000000081525081565b6040516100f89190612d95565b6101a461019f366004612dd9565b610302565b6040516100f89190612ef8565b6101b961077a565b005b6101c361087c565b6040519081526020016100f8565b6101846101df3660046130b4565b5060408051602081019091526000815290565b60005473ffffffffffffffffffffffffffffffffffffffff16610123565b61022361021e3660046130d1565b61088d565b6040516100f89190613137565b6101b961023e3660046131c7565b610b0e565b6101b9610251366004613249565b610b22565b6101b96102643660046132cd565b610ec1565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f78bea7210000000000000000000000000000000000000000000000000000000014806102fc57507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b63ffffffff8216600090815260056020526040812060609183600181111561032c5761032c612e0e565b600181111561033d5761033d612e0e565b8152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b8282101561076e57600084815260209020604080516101808101909152600884029091018054829060608201908390829060ff1660018111156103b0576103b0612e0e565b60018111156103c1576103c1612e0e565b8152815467ffffffffffffffff61010082048116602084015260ff690100000000000000000083041660408401526a01000000000000000000009091041660608201526001820180546080909201916104199061338a565b80601f01602080910402602001604051908101604052809291908181526020018280546104459061338a565b80156104925780601f1061046757610100808354040283529160200191610492565b820191906000526020600020905b81548152906001019060200180831161047557829003601f168201915b50505050508152602001600282018054806020026020016040519081016040528092919081815260200182805480156104ea57602002820191906000526020600020905b8154815260200190600101908083116104d6575b5050505050815260200160038201805480602002602001604051908101604052809291908181526020016000905b828210156105c45783829060005260206000200180546105379061338a565b80601f01602080910402602001604051908101604052809291908181526020018280546105639061338a565b80156105b05780601f10610585576101008083540402835291602001916105b0565b820191906000526020600020905b81548152906001019060200180831161059357829003601f168201915b505050505081526020019060010190610518565b50505050815260200160048201805480602002602001604051908101604052809291908181526020016000905b8282101561069d5783829060005260206000200180546106109061338a565b80601f016020809104026020016040519081016040528092919081815260200182805461063c9061338a565b80156106895780601f1061065e57610100808354040283529160200191610689565b820191906000526020600020905b81548152906001019060200180831161066c57829003601f168201915b5050505050815260200190600101906105f1565b5050505081526020016005820180546106b59061338a565b80601f01602080910402602001604051908101604052809291908181526020018280546106e19061338a565b801561072e5780601f106107035761010080835404028352916020019161072e565b820191906000526020600020905b81548152906001019060200180831161071157829003601f168201915b505050919092525050508152600682015467ffffffffffffffff16602080830191909152600790920154604090910152908252600192909201910161036b565b50505050905092915050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610800576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b60006108886003610f7c565b905090565b6060600061089b6003610f7c565b905060006108a9848661340c565b90508315806108b85750818110155b156108f85760408051600080825260208201909252906108ee565b6108db612a8e565b8152602001906001900390816108d35790505b50925050506102fc565b60006109048583613452565b9050828111156109115750815b600061091d8383613465565b67ffffffffffffffff81111561093557610935613423565b60405190808252806020026020018201604052801561096e57816020015b61095b612a8e565b8152602001906001900390816109535790505b509050600061097d6003610f86565b9050835b83811015610b0157600082828151811061099d5761099d613478565b60209081029190910181015160408051808201825267ffffffffffffffff831680825260009081526002855282902082518154608081880283018101909552606082018181529597509295860194909391928492849190840182828015610a2357602002820191906000526020600020905b815481526020019060010190808311610a0f575b5050509183525050600182015460ff166020820152600282018054604090920191610a4d9061338a565b80601f0160208091040260200160405190810160405280929190818152602001828054610a799061338a565b8015610ac65780601f10610a9b57610100808354040283529160200191610ac6565b820191906000526020600020905b815481529060010190602001808311610aa957829003601f168201915b50505091909252505050905284610add8885613465565b81518110610aed57610aed613478565b602090810291909101015250600101610981565b5090979650505050505050565b610b16610f9a565b610b1f8161101d565b50565b610b2a610f9a565b60005b83811015610d1057610b71858583818110610b4a57610b4a613478565b9050602002016020810190610b5f91906134a7565b60039067ffffffffffffffff16611112565b610bdb57848482818110610b8757610b87613478565b9050602002016020810190610b9c91906134a7565b6040517f1bd4d2d200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016107f7565b60026000868684818110610bf157610bf1613478565b9050602002016020810190610c0691906134a7565b67ffffffffffffffff1681526020810191909152604001600090812090610c2d8282612ad6565b6001820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055610c65600283016000612af4565b5050610ca3858583818110610c7c57610c7c613478565b9050602002016020810190610c9191906134a7565b60039067ffffffffffffffff1661112a565b507f2a680691fef3b2d105196805935232c661ce703e92d464ef0b94a7bc62d714f0858583818110610cd757610cd7613478565b9050602002016020810190610cec91906134a7565b60405167ffffffffffffffff909116815260200160405180910390a1600101610b2d565b5060005b81811015610eba576000838383818110610d3057610d30613478565b9050602002810190610d4291906134c2565b610d50906020810190613500565b610d5990613702565b90506000848484818110610d6f57610d6f613478565b9050602002810190610d8191906134c2565b610d8f9060208101906134a7565b9050610d9e8260000151611136565b816020015160ff16600003610ddf576040517fa9b3766e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff81166000908152600260209081526040909120835180518593610e0f928492910190612b2e565b5060208201516001820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff90921691909117905560408201516002820190610e5c90826137e9565b50610e7691506003905067ffffffffffffffff8316611282565b507f05dd57854af2c291a94ea52e7c43d80bc3be7fa73022f98b735dea86642fa5e08183604051610ea8929190613903565b60405180910390a15050600101610d14565b5050505050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610f30576040517fac7a7efd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080610f47610f42868801886139ae565b61128e565b8151919350915015610f5f57610f5f836000846114d9565b805115610f7257610f72836001836114d9565b5050505050505050565b60006102fc825490565b60606000610f9383611c3b565b9392505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461101b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016107f7565b565b3373ffffffffffffffffffffffffffffffffffffffff82160361109c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016107f7565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60008181526001830160205260408120541515610f93565b6000610f938383611c97565b60005b815181101561127e5760008019167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166350c946fe84848151811061119557611195613478565b60200260200101516040518263ffffffff1660e01b81526004016111bb91815260200190565b600060405180830381865afa1580156111d8573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261121e9190810190613bf9565b60800151036112765781818151811061123957611239613478565b60200260200101516040517f8907a4fa0000000000000000000000000000000000000000000000000000000081526004016107f791815260200190565b600101611139565b5050565b6000610f938383611d91565b606080600460ff16835111156112d0576040517f8854586400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160028082526060820190925290816020015b61134d6040805161012081019091528060008152602001600067ffffffffffffffff168152602001600060ff168152602001600067ffffffffffffffff16815260200160608152602001606081526020016060815260200160608152602001606081525090565b8152602001906001900390816112e657505060408051600280825260608201909252919350602082015b6113de6040805161012081019091528060008152602001600067ffffffffffffffff168152602001600060ff168152602001600067ffffffffffffffff16815260200160608152602001606081526020016060815260200160608152602001606081525090565b81526020019060019003908161137757905050905060008060005b85518110156114cc57600086828151811061141657611416613478565b602002602001015160000151600181111561143357611433612e0e565b036114805785818151811061144a5761144a613478565b602002602001015185848151811061146457611464613478565b60200260200101819052508261147990613cd1565b92506114c4565b85818151811061149257611492613478565b60200260200101518483815181106114ac576114ac613478565b6020026020010181905250816114c190613cd1565b91505b6001016113f9565b5090835281529092909150565b63ffffffff831660009081526005602052604081208184600181111561150157611501612e0e565b600181111561151257611512612e0e565b8152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b8282101561194357600084815260209020604080516101808101909152600884029091018054829060608201908390829060ff16600181111561158557611585612e0e565b600181111561159657611596612e0e565b8152815467ffffffffffffffff61010082048116602084015260ff690100000000000000000083041660408401526a01000000000000000000009091041660608201526001820180546080909201916115ee9061338a565b80601f016020809104026020016040519081016040528092919081815260200182805461161a9061338a565b80156116675780601f1061163c57610100808354040283529160200191611667565b820191906000526020600020905b81548152906001019060200180831161164a57829003601f168201915b50505050508152602001600282018054806020026020016040519081016040528092919081815260200182805480156116bf57602002820191906000526020600020905b8154815260200190600101908083116116ab575b5050505050815260200160038201805480602002602001604051908101604052809291908181526020016000905b8282101561179957838290600052602060002001805461170c9061338a565b80601f01602080910402602001604051908101604052809291908181526020018280546117389061338a565b80156117855780601f1061175a57610100808354040283529160200191611785565b820191906000526020600020905b81548152906001019060200180831161176857829003601f168201915b5050505050815260200190600101906116ed565b50505050815260200160048201805480602002602001604051908101604052809291908181526020016000905b828210156118725783829060005260206000200180546117e59061338a565b80601f01602080910402602001604051908101604052809291908181526020018280546118119061338a565b801561185e5780601f106118335761010080835404028352916020019161185e565b820191906000526020600020905b81548152906001019060200180831161184157829003601f168201915b5050505050815260200190600101906117c6565b50505050815260200160058201805461188a9061338a565b80601f01602080910402602001604051908101604052809291908181526020018280546118b69061338a565b80156119035780601f106118d857610100808354040283529160200191611903565b820191906000526020600020905b8154815290600101906020018083116118e657829003601f168201915b505050919092525050508152600682015467ffffffffffffffff166020808301919091526007909201546040909101529082526001929092019101611540565b50505050905060006119558251611de0565b905060006119638451611de0565b905061196f8282611e32565b600061197e8785878686611eee565b905061198a84826122d2565b63ffffffff87166000908152600560205260408120908760018111156119b2576119b2612e0e565b60018111156119c3576119c3612e0e565b815260200190815260200160002060006119dd9190612b79565b60005b8151811015610f725763ffffffff8816600090815260056020526040812090886001811115611a1157611a11612e0e565b6001811115611a2257611a22612e0e565b8152602001908152602001600020828281518110611a4257611a42613478565b6020908102919091018101518254600181810185556000948552929093208151805160089095029091018054929490939192849283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016908381811115611aac57611aac612e0e565b021790555060208201518154604084015160608501517fffffffffffffffffffffffffffffffffffffffffffff000000000000000000ff90921661010067ffffffffffffffff948516027fffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffff1617690100000000000000000060ff90921691909102177fffffffffffffffffffffffffffff0000000000000000ffffffffffffffffffff166a0100000000000000000000929091169190910217815560808201516001820190611b7b90826137e9565b5060a08201518051611b97916002840191602090910190612b2e565b5060c08201518051611bb3916003840191602090910190612b9a565b5060e08201518051611bcf916004840191602090910190612b9a565b506101008201516005820190611be590826137e9565b50505060208201516006820180547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff9092169190911790556040909101516007909101556001016119e0565b606081600001805480602002602001604051908101604052809291908181526020018280548015611c8b57602002820191906000526020600020905b815481526020019060010190808311611c77575b50505050509050919050565b60008181526001830160205260408120548015611d80576000611cbb600183613465565b8554909150600090611ccf90600190613465565b9050808214611d34576000866000018281548110611cef57611cef613478565b9060005260206000200154905080876000018481548110611d1257611d12613478565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080611d4557611d45613d09565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506102fc565b60009150506102fc565b5092915050565b6000818152600183016020526040812054611dd8575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556102fc565b5060006102fc565b60006002821115611e20576040517f3e478526000000000000000000000000000000000000000000000000000000008152600481018390526024016107f7565b8160028111156102fc576102fc612e0e565b6000826002811115611e4657611e46612e0e565b826002811115611e5857611e58612e0e565b611e629190613d38565b90508060011480611eae5750807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff148015611eae57506002836002811115611eac57611eac612e0e565b145b15611eb857505050565b82826040517f0a6b675b0000000000000000000000000000000000000000000000000000000081526004016107f7929190613d68565b60606000845167ffffffffffffffff811115611f0c57611f0c613423565b604051908082528060200260200182016040528015611f35578160200160208202803683370190505b5090506000846002811115611f4c57611f4c612e0e565b148015611f6a57506001836002811115611f6857611f68612e0e565b145b15611fab57600181600081518110611f8457611f84613478565b602002602001019067ffffffffffffffff16908167ffffffffffffffff1681525050612113565b6001846002811115611fbf57611fbf612e0e565b148015611fdd57506002836002811115611fdb57611fdb612e0e565b145b156120745785600081518110611ff557611ff5613478565b6020026020010151602001518160008151811061201457612014613478565b602002602001019067ffffffffffffffff16908167ffffffffffffffff16815250508560008151811061204957612049613478565b60200260200101516020015160016120619190613d83565b81600181518110611f8457611f84613478565b600284600281111561208857612088612e0e565b1480156120a6575060018360028111156120a4576120a4612e0e565b145b156120dd57856001815181106120be576120be613478565b60200260200101516020015181600081518110611f8457611f84613478565b83836040517f0a6b675b0000000000000000000000000000000000000000000000000000000081526004016107f7929190613d68565b6000855167ffffffffffffffff81111561212f5761212f613423565b6040519080825280602002602001820160405280156121dd57816020015b6040805161018081018252600060608083018281526080840183905260a0840183905260c0840183905260e08401829052610100840182905261012084018290526101408401829052610160840191909152825260208083018290529282015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90920191018161214d5790505b50905060005b82518110156122c65761220e87828151811061220157612201613478565b6020026020010151612651565b604051806060016040528088838151811061222b5761222b613478565b6020026020010151815260200184838151811061224a5761224a613478565b602002602001015167ffffffffffffffff16815260200161229e8b86858151811061227757612277613478565b60200260200101518b868151811061229157612291613478565b60200260200101516129c0565b8152508282815181106122b3576122b3613478565b60209081029190910101526001016121e3565b50979650505050505050565b81518151811580156122e45750806001145b1561238657826000815181106122fc576122fc613478565b60200260200101516020015167ffffffffffffffff16600114612380578260008151811061232c5761232c613478565b60209081029190910181015101516040517fc1658eb800000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152600160248201526044016107f7565b50505050565b8160011480156123965750806002145b1561254c57836000815181106123ae576123ae613478565b602002602001015160400151836000815181106123cd576123cd613478565b6020026020010151604001511461245957826000815181106123f1576123f1613478565b6020026020010151604001518460008151811061241057612410613478565b6020026020010151604001516040517fc7ccdd7f0000000000000000000000000000000000000000000000000000000081526004016107f7929190918252602082015260400190565b8360008151811061246c5761246c613478565b60200260200101516020015160016124849190613d83565b67ffffffffffffffff16836001815181106124a1576124a1613478565b60200260200101516020015167ffffffffffffffff161461238057826001815181106124cf576124cf613478565b602002602001015160200151846000815181106124ee576124ee613478565b60200260200101516020015160016125069190613d83565b6040517fc1658eb800000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9283166004820152911660248201526044016107f7565b81600214801561255c5750806001145b1561261f578360018151811061257457612574613478565b6020026020010151604001518360008151811061259357612593613478565b6020026020010151604001511461238057826000815181106125b7576125b7613478565b602002602001015160400151846001815181106125d6576125d6613478565b6020026020010151604001516040517f9e9756700000000000000000000000000000000000000000000000000000000081526004016107f7929190918252602082015260400190565b6040517f1f1b2bb600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806020015167ffffffffffffffff16600003612699576040517f698cf8e000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000815160018111156126ae576126ae612e0e565b141580156126cf57506001815160018111156126cc576126cc612e0e565b14155b15612706576040517f3302dbd700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6080810151511580612743575060408051600060208201520160405160208183030381529060405280519060200120816080015180519060200120145b1561277a576040517f358c192700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208101516127959060039067ffffffffffffffff16611112565b6127dd5760208101516040517f1bd4d2d200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016107f7565b60208082015167ffffffffffffffff1660009081526002909152604081206001015461280d9060ff166003613da4565b612818906001613dc0565b60ff169050808260e0015151101561286d5760e0820151516040517f548dd21f0000000000000000000000000000000000000000000000000000000081526004810191909152602481018290526044016107f7565b60c0820151516101008111156128af576040517f1b925da600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8260a0015151811415806128c857508260e00151518114155b156129225760a08301515160c08401515160e0850151516040517fba900f6d0000000000000000000000000000000000000000000000000000000081526004810193909352602483019190915260448201526064016107f7565b826040015160ff16600003612963576040517f39d1a4d000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040830151612973906003613da4565b60ff1681116129ae576040517f4856694e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6129bb8360a00151611136565b505050565b60008082602001518584600001518560800151878760a001518860c001518960e001518a604001518b606001518c6101000151604051602001612a0d9b9a99989796959493929190613dd9565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e0a000000000000000000000000000000000000000000000000000000000000179150509392505050565b6040518060400160405280600067ffffffffffffffff168152602001612ad1604051806060016040528060608152602001600060ff168152602001606081525090565b905290565b5080546000825590600052602060002090810190610b1f9190612bec565b508054612b009061338a565b6000825580601f10612b10575050565b601f016020900490600052602060002090810190610b1f9190612bec565b828054828255906000526020600020908101928215612b69579160200282015b82811115612b69578251825591602001919060010190612b4e565b50612b75929150612bec565b5090565b5080546000825560080290600052602060002090810190610b1f9190612c01565b828054828255906000526020600020908101928215612be0579160200282015b82811115612be05782518290612bd090826137e9565b5091602001919060010190612bba565b50612b75929150612cb4565b5b80821115612b755760008155600101612bed565b80821115612b755780547fffffffffffffffffffffffffffff00000000000000000000000000000000000016815560008181612c406001830182612af4565b612c4e600283016000612ad6565b612c5c600383016000612cd1565b612c6a600483016000612cd1565b612c78600583016000612af4565b5050506006810180547fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000016905560006007820155600801612c01565b80821115612b75576000612cc88282612af4565b50600101612cb4565b5080546000825590600052602060002090810190610b1f9190612cb4565b600060208284031215612d0157600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610f9357600080fd5b6000815180845260005b81811015612d5757602081850181015186830182015201612d3b565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000610f936020830184612d31565b63ffffffff81168114610b1f57600080fd5b8035612dc581612da8565b919050565b803560028110612dc557600080fd5b60008060408385031215612dec57600080fd5b8235612df781612da8565b9150612e0560208401612dca565b90509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60028110612e4d57612e4d612e0e565b9052565b60008151808452602080850194506020840160005b83811015612e8257815187529582019590820190600101612e66565b509495945050505050565b60008282518085526020808601955060208260051b8401016020860160005b84811015610b01577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018952612ee6838351612d31565b98840198925090830190600101612eac565b600060208083018184528085518083526040925060408601915060408160051b87010184880160005b838110156130a6577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0898403018552815160608151818652612f668287018251612e3d565b898101516080612f818189018367ffffffffffffffff169052565b8a830151915060a0612f97818a018460ff169052565b938301519360c09250612fb58984018667ffffffffffffffff169052565b818401519450610120915060e082818b0152612fd56101808b0187612d31565b95508185015191507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0610100818c890301818d01526130148885612e51565b958701518c87038301868e015295975061302e8887612e8d565b9750828701519550818c8903016101408d015261304b8887612e8d565b975080870151965050808b8803016101608c0152505050505061306e8282612d31565b9150508882015161308a8a87018267ffffffffffffffff169052565b5090870151938701939093529386019390860190600101612f21565b509098975050505050505050565b6000602082840312156130c657600080fd5b8135610f9381612da8565b600080604083850312156130e457600080fd5b50508035926020909101359150565b60008151606084526131086060850182612e51565b905060ff60208401511660208501526040830151848203604086015261312e8282612d31565b95945050505050565b600060208083018184528085518083526040925060408601915060408160051b87010184880160005b838110156130a6578883037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00185528151805167ffffffffffffffff1684528701518784018790526131b4878501826130f3565b9588019593505090860190600101613160565b6000602082840312156131d957600080fd5b813573ffffffffffffffffffffffffffffffffffffffff81168114610f9357600080fd5b60008083601f84011261320f57600080fd5b50813567ffffffffffffffff81111561322757600080fd5b6020830191508360208260051b850101111561324257600080fd5b9250929050565b6000806000806040858703121561325f57600080fd5b843567ffffffffffffffff8082111561327757600080fd5b613283888389016131fd565b9096509450602087013591508082111561329c57600080fd5b506132a9878288016131fd565b95989497509550505050565b803567ffffffffffffffff81168114612dc557600080fd5b600080600080600080608087890312156132e657600080fd5b863567ffffffffffffffff808211156132fe57600080fd5b61330a8a838b016131fd565b9098509650602089013591508082111561332357600080fd5b818901915089601f83011261333757600080fd5b81358181111561334657600080fd5b8a602082850101111561335857600080fd5b602083019650809550505050613370604088016132b5565b915061337e60608801612dba565b90509295509295509295565b600181811c9082168061339e57607f821691505b6020821081036133d7577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80820281158282048414176102fc576102fc6133dd565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b808201808211156102fc576102fc6133dd565b818103818111156102fc576102fc6133dd565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000602082840312156134b957600080fd5b610f93826132b5565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc18336030181126134f657600080fd5b9190910192915050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa18336030181126134f657600080fd5b604051610120810167ffffffffffffffff8111828210171561355857613558613423565b60405290565b60405160e0810167ffffffffffffffff8111828210171561355857613558613423565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156135c8576135c8613423565b604052919050565b600067ffffffffffffffff8211156135ea576135ea613423565b5060051b60200190565b600082601f83011261360557600080fd5b8135602061361a613615836135d0565b613581565b8083825260208201915060208460051b87010193508684111561363c57600080fd5b602086015b848110156136585780358352918301918301613641565b509695505050505050565b803560ff81168114612dc557600080fd5b600082601f83011261368557600080fd5b813567ffffffffffffffff81111561369f5761369f613423565b6136d060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601613581565b8181528460208386010111156136e557600080fd5b816020850160208301376000918101602001919091529392505050565b60006060823603121561371457600080fd5b6040516060810167ffffffffffffffff828210818311171561373857613738613423565b81604052843591508082111561374d57600080fd5b613759368387016135f4565b835261376760208601613663565b6020840152604085013591508082111561378057600080fd5b5061378d36828601613674565b60408301525092915050565b601f8211156129bb576000816000526020600020601f850160051c810160208610156137c25750805b601f850160051c820191505b818110156137e1578281556001016137ce565b505050505050565b815167ffffffffffffffff81111561380357613803613423565b61381781613811845461338a565b84613799565b602080601f83116001811461386a57600084156138345750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556137e1565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b828110156138b757888601518255948401946001909101908401613898565b50858210156138f357878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b67ffffffffffffffff8316815260406020820152600061392660408301846130f3565b949350505050565b600082601f83011261393f57600080fd5b8135602061394f613615836135d0565b82815260059290921b8401810191818101908684111561396e57600080fd5b8286015b8481101561365857803567ffffffffffffffff8111156139925760008081fd5b6139a08986838b0101613674565b845250918301918301613972565b600060208083850312156139c157600080fd5b823567ffffffffffffffff808211156139d957600080fd5b818501915085601f8301126139ed57600080fd5b81356139fb613615826135d0565b81815260059190911b83018401908481019088831115613a1a57600080fd5b8585015b83811015613b8257803585811115613a3557600080fd5b8601610120818c037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001811315613a6b57600080fd5b613a73613534565b613a7e8a8401612dca565b8152613a8c604084016132b5565b8a820152613a9c60608401613663565b6040820152613aad608084016132b5565b606082015260a083013588811115613ac457600080fd5b613ad28e8c83870101613674565b60808301525060c083013588811115613aea57600080fd5b613af88e8c838701016135f4565b60a08301525060e083013588811115613b115760008081fd5b613b1f8e8c8387010161392e565b60c0830152506101008084013589811115613b3a5760008081fd5b613b488f8d8388010161392e565b60e084015250918301359188831115613b615760008081fd5b613b6f8e8c85870101613674565b9082015285525050918601918601613a1e565b5098975050505050505050565b8051612dc581612da8565b600082601f830112613bab57600080fd5b81516020613bbb613615836135d0565b8083825260208201915060208460051b870101935086841115613bdd57600080fd5b602086015b848110156136585780518352918301918301613be2565b600060208284031215613c0b57600080fd5b815167ffffffffffffffff80821115613c2357600080fd5b9083019060e08286031215613c3757600080fd5b613c3f61355e565b613c4883613b8f565b8152613c5660208401613b8f565b6020820152613c6760408401613b8f565b6040820152606083015160608201526080830151608082015260a083015182811115613c9257600080fd5b613c9e87828601613b9a565b60a08301525060c083015182811115613cb657600080fd5b613cc287828601613b9a565b60c08301525095945050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613d0257613d026133dd565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b8181036000831280158383131683831282161715611d8a57611d8a6133dd565b60038110612e4d57612e4d612e0e565b60408101613d768285613d58565b610f936020830184613d58565b67ffffffffffffffff818116838216019080821115611d8a57611d8a6133dd565b60ff8181168382160290811690818114611d8a57611d8a6133dd565b60ff81811683821601908111156102fc576102fc6133dd565b600061016067ffffffffffffffff8e16835263ffffffff8d166020840152613e04604084018d612e3d565b806060840152613e168184018c612d31565b67ffffffffffffffff8b166080850152905082810360a0840152613e3a818a612e51565b905082810360c0840152613e4e8189612e8d565b905082810360e0840152613e628188612e8d565b60ff8716610100850152905067ffffffffffffffff8516610120840152828103610140840152613e928185612d31565b9e9d505050505050505050505050505056fea164736f6c6343000818000a", } var CCIPConfigABI = CCIPConfigMetaData.ABI @@ -266,6 +266,28 @@ func (_CCIPConfig *CCIPConfigCallerSession) GetCapabilityRegistry() (common.Addr return _CCIPConfig.Contract.GetCapabilityRegistry(&_CCIPConfig.CallOpts) } +func (_CCIPConfig *CCIPConfigCaller) GetNumChainConfigurations(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _CCIPConfig.contract.Call(opts, &out, "getNumChainConfigurations") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_CCIPConfig *CCIPConfigSession) GetNumChainConfigurations() (*big.Int, error) { + return _CCIPConfig.Contract.GetNumChainConfigurations(&_CCIPConfig.CallOpts) +} + +func (_CCIPConfig *CCIPConfigCallerSession) GetNumChainConfigurations() (*big.Int, error) { + return _CCIPConfig.Contract.GetNumChainConfigurations(&_CCIPConfig.CallOpts) +} + func (_CCIPConfig *CCIPConfigCaller) GetOCRConfig(opts *bind.CallOpts, donId uint32, pluginType uint8) ([]CCIPConfigTypesOCR3ConfigWithMeta, error) { var out []interface{} err := _CCIPConfig.contract.Call(opts, &out, "getOCRConfig", donId, pluginType) @@ -1074,6 +1096,8 @@ type CCIPConfigInterface interface { GetCapabilityRegistry(opts *bind.CallOpts) (common.Address, error) + GetNumChainConfigurations(opts *bind.CallOpts) (*big.Int, error) + GetOCRConfig(opts *bind.CallOpts, donId uint32, pluginType uint8) ([]CCIPConfigTypesOCR3ConfigWithMeta, error) Owner(opts *bind.CallOpts) (common.Address, error) diff --git a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt index 28ee860683..743083f50a 100644 --- a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -4,7 +4,7 @@ burn_mint_token_pool: ../../../contracts/solc/v0.8.24/BurnMintTokenPool/BurnMint burn_mint_token_pool_and_proxy: ../../../contracts/solc/v0.8.24/BurnMintTokenPoolAndProxy/BurnMintTokenPoolAndProxy.abi ../../../contracts/solc/v0.8.24/BurnMintTokenPoolAndProxy/BurnMintTokenPoolAndProxy.bin 717c079d5d13300cf3c3ee871c6e5bf9af904411f204fb081a9f3b263cca1391 burn_with_from_mint_token_pool: ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.abi ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.bin 6333d0314d0bd29e75ea5e05fe62a4516ade0c6db91c30b6f93645035db52ed8 burn_with_from_mint_token_pool_and_proxy: ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPoolAndProxy/BurnWithFromMintTokenPoolAndProxy.abi ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPoolAndProxy/BurnWithFromMintTokenPoolAndProxy.bin 08ed1235dda921ce8841b26aa18d0c0f36db4884779dd7670857159801b6d597 -ccip_config: ../../../contracts/solc/v0.8.24/CCIPConfig/CCIPConfig.abi ../../../contracts/solc/v0.8.24/CCIPConfig/CCIPConfig.bin 75955a3dcfd66b308be07eda54d6036cc79e87d3cdcf3c5c3115813c55912af8 +ccip_config: ../../../contracts/solc/v0.8.24/CCIPConfig/CCIPConfig.abi ../../../contracts/solc/v0.8.24/CCIPConfig/CCIPConfig.bin b64994e8719f666101322b32c87d7d569b865be30bc6966aa8751ecb9249bcf4 ccip_reader_tester: ../../../contracts/solc/v0.8.24/CCIPReaderTester/CCIPReaderTester.abi ../../../contracts/solc/v0.8.24/CCIPReaderTester/CCIPReaderTester.bin 481d461f14c98308cd788b64be1151e92bac6f95ddd55eefc926296454316f13 commit_store: ../../../contracts/solc/v0.8.24/CommitStore/CommitStore.abi ../../../contracts/solc/v0.8.24/CommitStore/CommitStore.bin 274d87db70b643e00ab0a7e7845bb4b791f3b613bfc87708d33fc5a8369e2a41 commit_store_helper: ../../../contracts/solc/v0.8.24/CommitStoreHelper/CommitStoreHelper.abi ../../../contracts/solc/v0.8.24/CommitStoreHelper/CommitStoreHelper.bin f7128dcc2ee6dbcbc976288abcc16970ffb19b59412c5202ef6b259d2007f801 From 884e5b64b7989bb0a9303a61d81620254dfc7324 Mon Sep 17 00:00:00 2001 From: Ryan <80392855+RayXpub@users.noreply.github.com> Date: Tue, 10 Sep 2024 22:38:23 +0400 Subject: [PATCH 081/115] Add sanity check in applyAllowListUpdates (#1420) ## Motivation Currently, in the event of a misconfig where a destination chain's `AllowListConfigArgs` `allowListEnabled` is set to false while providing addresses to add to the allow list, the config will silently be skipped. ## Solution Add a sanity check to detect `!allowListConfigArgs.allowListEnabled && `allowListConfigArgs.addedAllowlistedSenders.length > 0` --- contracts/gas-snapshots/ccip.gas-snapshot | 15 ++++++----- contracts/src/v0.8/ccip/onRamp/OnRamp.sol | 18 +++++++------ .../src/v0.8/ccip/test/onRamp/OnRamp.t.sol | 26 ++++++++++++++++--- .../ccip/generated/onramp/onramp.go | 2 +- ...rapper-dependency-versions-do-not-edit.txt | 2 +- 5 files changed, 43 insertions(+), 20 deletions(-) diff --git a/contracts/gas-snapshots/ccip.gas-snapshot b/contracts/gas-snapshots/ccip.gas-snapshot index 180da04db6..018caf5293 100644 --- a/contracts/gas-snapshots/ccip.gas-snapshot +++ b/contracts/gas-snapshots/ccip.gas-snapshot @@ -740,15 +740,16 @@ OffRamp_trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 234506) OffRamp_trialExecute:test_TokenPoolIsNotAContract_Success() (gas: 309185) OffRamp_trialExecute:test_trialExecute_Success() (gas: 284141) OnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 390954) -OnRamp_allowListConfigUpdates:test_applyAllowList_Revert() (gas: 66515) -OnRamp_allowListConfigUpdates:test_applyAllowList_Success() (gas: 323595) +OnRamp_applyAllowListUpdates:test_applyAllowListUpdates_InvalidAllowListRequestDisabledAllowListWithAdds() (gas: 17746) +OnRamp_applyAllowListUpdates:test_applyAllowListUpdates_Revert() (gas: 66535) +OnRamp_applyAllowListUpdates:test_applyAllowListUpdates_Success() (gas: 323600) OnRamp_applyDestChainConfigUpdates:test_ApplyDestChainConfigUpdates_Success() (gas: 64546) OnRamp_applyDestChainConfigUpdates:test_ApplyDestChainConfigUpdates_WithInvalidChainSelector_Revert() (gas: 13254) -OnRamp_constructor:test_Constructor_InvalidConfigChainSelectorEqZero_Revert() (gas: 94815) -OnRamp_constructor:test_Constructor_InvalidConfigNonceManagerEqAddressZero_Revert() (gas: 92749) -OnRamp_constructor:test_Constructor_InvalidConfigRMNProxyEqAddressZero_Revert() (gas: 97775) -OnRamp_constructor:test_Constructor_InvalidConfigTokenAdminRegistryEqAddressZero_Revert() (gas: 92807) -OnRamp_constructor:test_Constructor_Success() (gas: 2812991) +OnRamp_constructor:test_Constructor_InvalidConfigChainSelectorEqZero_Revert() (gas: 94831) +OnRamp_constructor:test_Constructor_InvalidConfigNonceManagerEqAddressZero_Revert() (gas: 92765) +OnRamp_constructor:test_Constructor_InvalidConfigRMNProxyEqAddressZero_Revert() (gas: 97791) +OnRamp_constructor:test_Constructor_InvalidConfigTokenAdminRegistryEqAddressZero_Revert() (gas: 92823) +OnRamp_constructor:test_Constructor_Success() (gas: 2827622) OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() (gas: 114961) OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2_Success() (gas: 145732) OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessCustomExtraArgs() (gas: 145335) diff --git a/contracts/src/v0.8/ccip/onRamp/OnRamp.sol b/contracts/src/v0.8/ccip/onRamp/OnRamp.sol index cc449feaed..10036557ef 100644 --- a/contracts/src/v0.8/ccip/onRamp/OnRamp.sol +++ b/contracts/src/v0.8/ccip/onRamp/OnRamp.sol @@ -408,17 +408,19 @@ contract OnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCreator { DestChainConfig storage destChainConfig = s_destChainConfigs[allowListConfigArgs.destChainSelector]; destChainConfig.allowListEnabled = allowListConfigArgs.allowListEnabled; - if (allowListConfigArgs.allowListEnabled) { - for (uint256 j = 0; j < allowListConfigArgs.addedAllowlistedSenders.length; ++j) { - address toAdd = allowListConfigArgs.addedAllowlistedSenders[j]; - if (toAdd == address(0)) { - revert InvalidAllowListRequest(allowListConfigArgs.destChainSelector); + if (allowListConfigArgs.addedAllowlistedSenders.length > 0) { + if (allowListConfigArgs.allowListEnabled) { + for (uint256 j = 0; j < allowListConfigArgs.addedAllowlistedSenders.length; ++j) { + address toAdd = allowListConfigArgs.addedAllowlistedSenders[j]; + if (toAdd == address(0)) { + revert InvalidAllowListRequest(allowListConfigArgs.destChainSelector); + } + destChainConfig.allowedSendersList.add(toAdd); } - destChainConfig.allowedSendersList.add(toAdd); - } - if (allowListConfigArgs.addedAllowlistedSenders.length > 0) { emit AllowListSendersAdded(allowListConfigArgs.destChainSelector, allowListConfigArgs.addedAllowlistedSenders); + } else { + revert InvalidAllowListRequest(allowListConfigArgs.destChainSelector); } } diff --git a/contracts/src/v0.8/ccip/test/onRamp/OnRamp.t.sol b/contracts/src/v0.8/ccip/test/onRamp/OnRamp.t.sol index d989c15651..11b15048c1 100644 --- a/contracts/src/v0.8/ccip/test/onRamp/OnRamp.t.sol +++ b/contracts/src/v0.8/ccip/test/onRamp/OnRamp.t.sol @@ -854,8 +854,8 @@ contract OnRamp_applyDestChainConfigUpdates is OnRampSetup { } } -contract OnRamp_allowListConfigUpdates is OnRampSetup { - function test_applyAllowList_Success() public { +contract OnRamp_applyAllowListUpdates is OnRampSetup { + function test_applyAllowListUpdates_Success() public { vm.stopPrank(); vm.startPrank(OWNER); @@ -946,7 +946,7 @@ contract OnRamp_allowListConfigUpdates is OnRampSetup { assertEq(3, s_onRamp.getAllowedSendersList(DEST_CHAIN_SELECTOR).length); } - function test_applyAllowList_Revert() public { + function test_applyAllowListUpdates_Revert() public { vm.stopPrank(); vm.startPrank(OWNER); @@ -990,4 +990,24 @@ contract OnRamp_allowListConfigUpdates is OnRampSetup { s_onRamp.applyAllowListUpdates(applyAllowListConfigArgsItems); vm.stopPrank(); } + + function test_applyAllowListUpdates_InvalidAllowListRequestDisabledAllowListWithAdds() public { + vm.stopPrank(); + vm.startPrank(OWNER); + + address[] memory addedAllowlistedSenders = new address[](1); + addedAllowlistedSenders[0] = vm.addr(1); + + OnRamp.AllowListConfigArgs memory allowListConfigArgs = OnRamp.AllowListConfigArgs({ + allowListEnabled: false, + destChainSelector: DEST_CHAIN_SELECTOR, + addedAllowlistedSenders: addedAllowlistedSenders, + removedAllowlistedSenders: new address[](0) + }); + OnRamp.AllowListConfigArgs[] memory applyAllowListConfigArgsItems = new OnRamp.AllowListConfigArgs[](1); + applyAllowListConfigArgsItems[0] = allowListConfigArgs; + + vm.expectRevert(abi.encodeWithSelector(OnRamp.InvalidAllowListRequest.selector, DEST_CHAIN_SELECTOR)); + s_onRamp.applyAllowListUpdates(applyAllowListConfigArgsItems); + } } diff --git a/core/gethwrappers/ccip/generated/onramp/onramp.go b/core/gethwrappers/ccip/generated/onramp/onramp.go index 776f945650..16e352909e 100644 --- a/core/gethwrappers/ccip/generated/onramp/onramp.go +++ b/core/gethwrappers/ccip/generated/onramp/onramp.go @@ -98,7 +98,7 @@ type OnRampStaticConfig struct { var OnRampMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CannotSendZeroTokens\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GetSupportedTokensFunctionalityRemovedCheckAdminRegistry\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidAllowListRequest\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidDestChainConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeCalledByRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrAllowlistAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RouterMustSetOriginalSender\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"UnsupportedToken\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"name\":\"AllowListAdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"senders\",\"type\":\"address[]\"}],\"name\":\"AllowListSendersAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"senders\",\"type\":\"address[]\"}],\"name\":\"AllowListSendersRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"CCIPMessageSent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOnRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"allowListEnabled\",\"type\":\"bool\"}],\"name\":\"DestChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"feeValueJuels\",\"type\":\"uint256\"}],\"name\":\"FeePaid\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeeTokenWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"allowListEnabled\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"addedAllowlistedSenders\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"removedAllowlistedSenders\",\"type\":\"address[]\"}],\"internalType\":\"structOnRamp.AllowListConfigArgs[]\",\"name\":\"allowListConfigArgsItems\",\"type\":\"tuple[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyDestChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"}],\"name\":\"forwardFromRouter\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getAllowedSendersList\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getDestChainConfig\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"allowListEnabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getExpectedNextSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"getFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"},{\"internalType\":\"contractIERC20\",\"name\":\"sourceToken\",\"type\":\"address\"}],\"name\":\"getPoolBySourceToken\",\"outputs\":[{\"internalType\":\"contractIPoolV1\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"contractIRouter\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"name\":\"getSupportedTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"setDynamicConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"withdrawFeeTokens\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x6101006040523480156200001257600080fd5b506040516200402938038062004029833981016040819052620000359162000665565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf8162000186565b505083516001600160401b031615905080620000e6575060208301516001600160a01b0316155b80620000fd575060408301516001600160a01b0316155b8062000114575060608301516001600160a01b0316155b1562000133576040516306b7c75960e31b815260040160405180910390fd5b82516001600160401b031660805260208301516001600160a01b0390811660a0526040840151811660c05260608401511660e052620001728262000231565b6200017d8162000390565b5050506200079f565b336001600160a01b03821603620001e05760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b0316158062000254575060408101516001600160a01b0316155b1562000273576040516306b7c75960e31b815260040160405180910390fd5b8051600280546001600160a01b03199081166001600160a01b0393841617909155602080840180516003805485169186169190911790556040808601805160048054871691881691909117905560608088018051600580549098169089161790965582516080808201855280516001600160401b031680835260a080518b16848a0190815260c080518d16868a0190815260e080518f169789019788528a5195865292518e169b85019b909b5299518c169783019790975292518a169381019390935289518916908301529351871693810193909352518516928201929092529151909216918101919091527f23a1adf8ad7fad6091a4803227af2cee848c01a7c812404cade7c25636925e32906101000160405180910390a150565b60005b8151811015620004cf576000828281518110620003b457620003b462000789565b602002602001015190506000838381518110620003d557620003d562000789565b6020026020010151600001519050806001600160401b03166000036200041a5760405163c35aa79d60e01b81526001600160401b038216600482015260240162000083565b6001600160401b03818116600081815260066020908152604091829020868201518154600160481b600160e81b0319811669010000000000000000006001600160a01b03909316928302908117808555865192891691909816178152928301526801000000000000000090940460ff161515918101919091527fd5ad72bc37dc7a80a8b9b9df20500046fd7341adb1be2258a540466fdd7dcef59060600160405180910390a250505080600101905062000393565b5050565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b03811182821017156200050e576200050e620004d3565b60405290565b604080519081016001600160401b03811182821017156200050e576200050e620004d3565b604051601f8201601f191681016001600160401b0381118282101715620005645762000564620004d3565b604052919050565b80516001600160401b03811681146200058457600080fd5b919050565b6001600160a01b03811681146200059f57600080fd5b50565b600082601f830112620005b457600080fd5b815160206001600160401b03821115620005d257620005d2620004d3565b620005e2818360051b0162000539565b82815260069290921b840181019181810190868411156200060257600080fd5b8286015b848110156200065a5760408189031215620006215760008081fd5b6200062b62000514565b62000636826200056c565b815284820151620006478162000589565b8186015283529183019160400162000606565b509695505050505050565b60008060008385036101208112156200067d57600080fd5b60808112156200068c57600080fd5b62000696620004e9565b620006a1866200056c565b81526020860151620006b38162000589565b60208201526040860151620006c88162000589565b60408201526060860151620006dd8162000589565b606082015293506080607f1982011215620006f757600080fd5b5062000702620004e9565b6080850151620007128162000589565b815260a0850151620007248162000589565b602082015260c0850151620007398162000589565b604082015260e08501516200074e8162000589565b60608201526101008501519092506001600160401b038111156200077157600080fd5b6200077f86828701620005a2565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b60805160a05160c05160e051613811620008186000396000818161022c01528181610c790152611ba10152600081816101f0015281816112480152611b7a0152600081816101b4015281816105de0152611b500152600081816101840152818161116e0152818161164b0152611b2301526138116000f3fe608060405234801561001057600080fd5b50600436106101365760003560e01c806379ba5097116100b2578063a6f3ab6c11610081578063df0aa9e911610066578063df0aa9e91461052d578063f2fde38b14610540578063fbca3b741461055357600080fd5b8063a6f3ab6c146104cd578063d77d5ed0146104e057600080fd5b806379ba50971461045b5780638da5cb5b146104635780639041be3d14610481578063972b4612146104ad57600080fd5b806334adf4941161010957806348a98aa4116100ee57806348a98aa4146103045780636def4ce71461033c5780637437ff9f146103db57600080fd5b806334adf494146102e95780633a019940146102fc57600080fd5b80630242cf601461013b57806306285c6914610150578063181f5a771461027f57806320487ded146102c8575b600080fd5b61014e610149366004612696565b610566565b005b61026960408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16815250905090565b6040516102769190612759565b60405180910390f35b6102bb6040518060400160405280601081526020017f4f6e52616d7020312e362e302d6465760000000000000000000000000000000081525081565b604051610276919061281e565b6102db6102d6366004612849565b61057a565b604051908152602001610276565b61014e6102f7366004612899565b610733565b61014e610a06565b61031761031236600461290e565b610c31565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610276565b61039f61034a366004612947565b67ffffffffffffffff9081166000908152600660205260409020549081169168010000000000000000820460ff16916901000000000000000000900473ffffffffffffffffffffffffffffffffffffffff1690565b6040805167ffffffffffffffff9094168452911515602084015273ffffffffffffffffffffffffffffffffffffffff1690820152606001610276565b61044e604080516080810182526000808252602082018190529181018290526060810191909152506040805160808101825260025473ffffffffffffffffffffffffffffffffffffffff908116825260035481166020830152600454811692820192909252600554909116606082015290565b6040516102769190612964565b61014e610ce6565b60005473ffffffffffffffffffffffffffffffffffffffff16610317565b61049461048f366004612947565b610de3565b60405167ffffffffffffffff9091168152602001610276565b6104c06104bb366004612947565b610e0c565b60405161027691906129ad565b61014e6104db366004612a17565b610e34565b6103176104ee366004612947565b67ffffffffffffffff166000908152600660205260409020546901000000000000000000900473ffffffffffffffffffffffffffffffffffffffff1690565b6102db61053b366004612a7e565b610e45565b61014e61054e366004612aea565b6116fe565b6104c0610561366004612947565b61170f565b61056e611743565b610577816117c6565b50565b6040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815277ffffffffffffffff00000000000000000000000000000000608084901b16600482015260009073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690632cbc26bb90602401602060405180830381865afa158015610625573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106499190612b15565b15610691576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024015b60405180910390fd5b6002546040517fd8694ccd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063d8694ccd906106e99086908690600401612c46565b602060405180830381865afa158015610706573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061072a9190612d8f565b90505b92915050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146107a35760055473ffffffffffffffffffffffffffffffffffffffff1633146107a3576040517f905d7d9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015610a015760008383838181106107c2576107c2612da8565b90506020028101906107d49190612dd7565b6107dd90612e88565b805167ffffffffffffffff1660009081526006602090815260409091209082015181547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff16680100000000000000009115801592909202178255919250906109545760005b8260400151518110156108fd5760008360400151828151811061086757610867612da8565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036108e65783516040517f463258ff00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610688565b6108f3600184018261193d565b5050600101610842565b506040820151511561095457816000015167ffffffffffffffff167f330939f6eafe8bb516716892fe962ff19770570838686e6579dbc1cc51fc3281836040015160405161094b91906129ad565b60405180910390a25b60005b8260600151518110156109a0576109978360600151828151811061097d5761097d612da8565b60200260200101518360010161195f90919063ffffffff16565b50600101610957565b50606082015151156109f757816000015167ffffffffffffffff167fc237ec1921f855ccd5e9a5af9733f2d58943a5a8501ec5988e305d7a4d42158683606001516040516109ee91906129ad565b60405180910390a25b50506001016107a6565b505050565b600254604080517fcdc73d51000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163cdc73d5191600480830192869291908290030181865afa158015610a75573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610abb9190810190612f1b565b60045490915073ffffffffffffffffffffffffffffffffffffffff1660005b8251811015610a01576000838281518110610af757610af7612da8565b60209081029190910101516040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915060009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa158015610b72573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b969190612d8f565b90508015610c2757610bbf73ffffffffffffffffffffffffffffffffffffffff83168583611981565b8173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f508d7d183612c18fc339b42618912b9fa3239f631dd7ec0671f950200a0fa66e83604051610c1e91815260200190565b60405180910390a35b5050600101610ada565b6040517fbbe4f6db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063bbe4f6db90602401602060405180830381865afa158015610cc2573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061072a9190612faa565b60015473ffffffffffffffffffffffffffffffffffffffff163314610d67576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610688565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b67ffffffffffffffff808216600090815260066020526040812054909161072d91166001612ff6565b67ffffffffffffffff8116600090815260066020526040902060609061072d90600101611a0e565b610e3c611743565b61057781611a22565b67ffffffffffffffff8416600090815260066020526040812073ffffffffffffffffffffffffffffffffffffffff8316610eab576040517fa4ec747900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805468010000000000000000900460ff1615610f1c57610ece6001820184611c04565b610f1c576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152602401610688565b80546901000000000000000000900473ffffffffffffffffffffffffffffffffffffffff163314610f79576040517f1c0a352900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60035473ffffffffffffffffffffffffffffffffffffffff16801561101f576040517fe0a0e50600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82169063e0a0e50690610fec908a908a90600401612c46565b600060405180830381600087803b15801561100657600080fd5b505af115801561101a573d6000803e3d6000fd5b505050505b506002546000908190819073ffffffffffffffffffffffffffffffffffffffff1663c4276bfc8a61105660808c0160608d01612aea565b8a61106460808e018e613017565b6040518663ffffffff1660e01b815260040161108495949392919061307c565b600060405180830381865afa1580156110a1573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526110e79190810190613144565b919450925090506110fe6080890160608a01612aea565b73ffffffffffffffffffffffffffffffffffffffff167f075a2720282fdf622141dae0b048ef90a21a7e57c134c76912d19d006b3b3f6f8460405161114591815260200190565b60405180910390a2604080516101a081019091526000610100820181815267ffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000081166101208501528c811661014085015287549293928392916101608401918a9187916111ba911661319e565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905567ffffffffffffffff168152602001866112ba576040517fea458c0c00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8f16600482015273ffffffffffffffffffffffffffffffffffffffff8c811660248301527f0000000000000000000000000000000000000000000000000000000000000000169063ea458c0c906044016020604051808303816000875af1158015611291573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112b591906131c5565b6112bd565b60005b67ffffffffffffffff1681525081526020018873ffffffffffffffffffffffffffffffffffffffff1681526020018a80602001906112fb9190613017565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050509082525060200161133f8b80613017565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050908252506020810184905260400161139060808c0160608d01612aea565b73ffffffffffffffffffffffffffffffffffffffff1681526020018981526020018a80604001906113c191906131e2565b905067ffffffffffffffff8111156113db576113db612570565b60405190808252806020026020018201604052801561143e57816020015b61142b6040518060a0016040528060608152602001606081526020016060815260200160008152602001606081525090565b8152602001906001900390816113f95790505b509052905060005b61145360408b018b6131e2565b9050811015611502576114d961146c60408c018c6131e2565b8381811061147c5761147c612da8565b905060400201803603810190611492919061324a565b8c61149d8d80613017565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508e9250611c33915050565b8260e0015182815181106114ef576114ef612da8565b6020908102919091010152600101611446565b5060025460e082015160009173ffffffffffffffffffffffffffffffffffffffff169063085318f8908d9061153a60408f018f6131e2565b6040518563ffffffff1660e01b81526004016115599493929190613361565b600060405180830381865afa158015611576573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526115bc9190810190613397565b905060005b8260e0015151811015611615578181815181106115e0576115e0612da8565b60200260200101518360e0015182815181106115fe576115fe612da8565b6020908102919091010151608001526001016115c1565b50604080517f130ac867e79e2789f923760a88743d292acdf7002139a588206e2260f73f7321602082015267ffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811692820192909252908c1660608201523060808201526116a590839060a00160405160208183030381529060405280519060200120611f59565b82515260405167ffffffffffffffff8c16907ff6e86ef8896c7a0d629406168f396e883280680c99e649b9e2d36466fbc9f9e5906116e4908590613448565b60405180910390a25051519450505050505b949350505050565b611706611743565b61057781612059565b60606040517f9e7177c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005473ffffffffffffffffffffffffffffffffffffffff1633146117c4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610688565b565b60005b81518110156119395760008282815181106117e6576117e6612da8565b60200260200101519050600083838151811061180457611804612da8565b60200260200101516000015190508067ffffffffffffffff16600003611862576040517fc35aa79d00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610688565b67ffffffffffffffff8181166000818152600660209081526040918290208682015181547fffffff0000000000000000000000000000000000000000ffffffffffffffffff8116690100000000000000000073ffffffffffffffffffffffffffffffffffffffff909316928302908117808555865192891691909816178152928301526801000000000000000090940460ff161515918101919091527fd5ad72bc37dc7a80a8b9b9df20500046fd7341adb1be2258a540466fdd7dcef59060600160405180910390a25050508060010190506117c9565b5050565b600061072a8373ffffffffffffffffffffffffffffffffffffffff841661214e565b600061072a8373ffffffffffffffffffffffffffffffffffffffff841661219d565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052610a01908490612297565b60606000611a1b836123a3565b9392505050565b805173ffffffffffffffffffffffffffffffffffffffff161580611a5e5750604081015173ffffffffffffffffffffffffffffffffffffffff16155b15611a95576040517f35be3ac800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051600280547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff93841617909155602080840151600380548416918516919091179055604080850151600480548516918616919091179055606080860151600580549095169086161790935580516080810182527f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681527f00000000000000000000000000000000000000000000000000000000000000008516928101929092527f00000000000000000000000000000000000000000000000000000000000000008416828201527f00000000000000000000000000000000000000000000000000000000000000009093169181019190915290517f23a1adf8ad7fad6091a4803227af2cee848c01a7c812404cade7c25636925e3291611bf9918490613596565b60405180910390a150565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600183016020526040812054151561072a565b611c656040518060a0016040528060608152602001606081526020016060815260200160008152602001606081525090565b8460200151600003611ca3576040517f5cf0444900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611cb3858760000151610c31565b905073ffffffffffffffffffffffffffffffffffffffff81161580611d8357506040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527faff2afbf00000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff8216906301ffc9a790602401602060405180830381865afa158015611d5d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d819190612b15565b155b15611dd55785516040517fbf16aab600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610688565b60008173ffffffffffffffffffffffffffffffffffffffff16639a4575b96040518060a001604052808881526020018967ffffffffffffffff1681526020018773ffffffffffffffffffffffffffffffffffffffff1681526020018a6020015181526020018a6000015173ffffffffffffffffffffffffffffffffffffffff168152506040518263ffffffff1660e01b8152600401611e749190613635565b6000604051808303816000875af1158015611e93573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611ed991908101906136ab565b6040805160a0810190915273ffffffffffffffffffffffffffffffffffffffff841660c08201529091508060e0810160405160208183030381529060405281526020018260000151815260200182602001518152602001886020015181526020016040518060200160405280600081525081525092505050949350505050565b60008060001b82846020015185606001518660000151606001518760000151608001518860a001518960c00151604051602001611f9b9695949392919061373c565b604051602081830303815290604052805190602001208560400151805190602001208660e00151604051602001611fd2919061379d565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201206080808c0151805190840120928501989098529183019590955260608201939093529384015260a083015260c082015260e00160405160208183030381529060405280519060200120905092915050565b3373ffffffffffffffffffffffffffffffffffffffff8216036120d8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610688565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60008181526001830160205260408120546121955750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561072d565b50600061072d565b600081815260018301602052604081205480156122865760006121c16001836137b0565b85549091506000906121d5906001906137b0565b905080821461223a5760008660000182815481106121f5576121f5612da8565b906000526020600020015490508087600001848154811061221857612218612da8565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061224b5761224b6137c3565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061072d565b600091505061072d565b5092915050565b60006122f9826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166123ff9092919063ffffffff16565b805190915015610a0157808060200190518101906123179190612b15565b610a01576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610688565b6060816000018054806020026020016040519081016040528092919081815260200182805480156123f357602002820191906000526020600020905b8154815260200190600101908083116123df575b50505050509050919050565b60606116f68484600085856000808673ffffffffffffffffffffffffffffffffffffffff16858760405161243391906137f2565b60006040518083038185875af1925050503d8060008114612470576040519150601f19603f3d011682016040523d82523d6000602084013e612475565b606091505b509150915061248687838387612491565b979650505050505050565b606083156125275782516000036125205773ffffffffffffffffffffffffffffffffffffffff85163b612520576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610688565b50816116f6565b6116f6838381511561253c5781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610688919061281e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff811182821017156125c2576125c2612570565b60405290565b6040516080810167ffffffffffffffff811182821017156125c2576125c2612570565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561263257612632612570565b604052919050565b600067ffffffffffffffff82111561265457612654612570565b5060051b60200190565b67ffffffffffffffff8116811461057757600080fd5b73ffffffffffffffffffffffffffffffffffffffff8116811461057757600080fd5b600060208083850312156126a957600080fd5b823567ffffffffffffffff8111156126c057600080fd5b8301601f810185136126d157600080fd5b80356126e46126df8261263a565b6125eb565b81815260069190911b8201830190838101908783111561270357600080fd5b928401925b8284101561248657604084890312156127215760008081fd5b61272961259f565b84356127348161265e565b81528486013561274381612674565b8187015282526040939093019290840190612708565b6080810161072d828467ffffffffffffffff8151168252602081015173ffffffffffffffffffffffffffffffffffffffff808216602085015280604084015116604085015280606084015116606085015250505050565b60005b838110156127cb5781810151838201526020016127b3565b50506000910152565b600081518084526127ec8160208601602086016127b0565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061072a60208301846127d4565b600060a0828403121561284357600080fd5b50919050565b6000806040838503121561285c57600080fd5b82356128678161265e565b9150602083013567ffffffffffffffff81111561288357600080fd5b61288f85828601612831565b9150509250929050565b600080602083850312156128ac57600080fd5b823567ffffffffffffffff808211156128c457600080fd5b818501915085601f8301126128d857600080fd5b8135818111156128e757600080fd5b8660208260051b85010111156128fc57600080fd5b60209290920196919550909350505050565b6000806040838503121561292157600080fd5b823561292c8161265e565b9150602083013561293c81612674565b809150509250929050565b60006020828403121561295957600080fd5b8135611a1b8161265e565b6080810161072d8284805173ffffffffffffffffffffffffffffffffffffffff908116835260208083015182169084015260408083015182169084015260609182015116910152565b6020808252825182820181905260009190848201906040850190845b818110156129fb57835173ffffffffffffffffffffffffffffffffffffffff16835292840192918401916001016129c9565b50909695505050505050565b8035612a1281612674565b919050565b600060808284031215612a2957600080fd5b612a316125c8565b8235612a3c81612674565b81526020830135612a4c81612674565b60208201526040830135612a5f81612674565b60408201526060830135612a7281612674565b60608201529392505050565b60008060008060808587031215612a9457600080fd5b8435612a9f8161265e565b9350602085013567ffffffffffffffff811115612abb57600080fd5b612ac787828801612831565b935050604085013591506060850135612adf81612674565b939692955090935050565b600060208284031215612afc57600080fd5b8135611a1b81612674565b801515811461057757600080fd5b600060208284031215612b2757600080fd5b8151611a1b81612b07565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112612b6757600080fd5b830160208101925035905067ffffffffffffffff811115612b8757600080fd5b803603821315612b9657600080fd5b9250929050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b8183526000602080850194508260005b85811015612c3b578135612c0981612674565b73ffffffffffffffffffffffffffffffffffffffff168752818301358388015260409687019690910190600101612bf6565b509495945050505050565b600067ffffffffffffffff808516835260406020840152612c678485612b32565b60a06040860152612c7c60e086018284612b9d565b915050612c8c6020860186612b32565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc080878503016060880152612cc2848385612b9d565b9350604088013592507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1883603018312612cfb57600080fd5b60209288019283019235915084821115612d1457600080fd5b8160061b3603831315612d2657600080fd5b80878503016080880152612d3b848385612be6565b9450612d4960608901612a07565b73ffffffffffffffffffffffffffffffffffffffff811660a08901529350612d746080890189612b32565b94509250808786030160c08801525050612486838383612b9d565b600060208284031215612da157600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81833603018112612e0b57600080fd5b9190910192915050565b600082601f830112612e2657600080fd5b81356020612e366126df8361263a565b8083825260208201915060208460051b870101935086841115612e5857600080fd5b602086015b84811015612e7d578035612e7081612674565b8352918301918301612e5d565b509695505050505050565b600060808236031215612e9a57600080fd5b612ea26125c8565b8235612ead8161265e565b81526020830135612ebd81612b07565b6020820152604083013567ffffffffffffffff80821115612edd57600080fd5b612ee936838701612e15565b60408401526060850135915080821115612f0257600080fd5b50612f0f36828601612e15565b60608301525092915050565b60006020808385031215612f2e57600080fd5b825167ffffffffffffffff811115612f4557600080fd5b8301601f81018513612f5657600080fd5b8051612f646126df8261263a565b81815260059190911b82018301908381019087831115612f8357600080fd5b928401925b82841015612486578351612f9b81612674565b82529284019290840190612f88565b600060208284031215612fbc57600080fd5b8151611a1b81612674565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b67ffffffffffffffff81811683821601908082111561229057612290612fc7565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261304c57600080fd5b83018035915067ffffffffffffffff82111561306757600080fd5b602001915036819003821315612b9657600080fd5b67ffffffffffffffff8616815273ffffffffffffffffffffffffffffffffffffffff85166020820152836040820152608060608201526000612486608083018486612b9d565b600082601f8301126130d357600080fd5b815167ffffffffffffffff8111156130ed576130ed612570565b61311e60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016125eb565b81815284602083860101111561313357600080fd5b6116f68260208301602087016127b0565b60008060006060848603121561315957600080fd5b83519250602084015161316b81612b07565b604085015190925067ffffffffffffffff81111561318857600080fd5b613194868287016130c2565b9150509250925092565b600067ffffffffffffffff8083168181036131bb576131bb612fc7565b6001019392505050565b6000602082840312156131d757600080fd5b8151611a1b8161265e565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261321757600080fd5b83018035915067ffffffffffffffff82111561323257600080fd5b6020019150600681901b3603821315612b9657600080fd5b60006040828403121561325c57600080fd5b61326461259f565b823561326f81612674565b81526020928301359281019290925250919050565b600082825180855260208086019550808260051b84010181860160005b84811015613354577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018952815160a081518186526132e5828701826127d4565b91505085820151858203878701526132fd82826127d4565b9150506040808301518683038288015261331783826127d4565b9250505060608083015181870152506080808301519250858203818701525061334081836127d4565b9a86019a94505050908301906001016132a1565b5090979650505050505050565b67ffffffffffffffff851681526060602082015260006133846060830186613284565b8281036040840152612486818587612be6565b600060208083850312156133aa57600080fd5b825167ffffffffffffffff808211156133c257600080fd5b818501915085601f8301126133d657600080fd5b81516133e46126df8261263a565b81815260059190911b8301840190848101908883111561340357600080fd5b8585015b8381101561343b5780518581111561341f5760008081fd5b61342d8b89838a01016130c2565b845250918601918601613407565b5098975050505050505050565b6020815261349960208201835180518252602081015167ffffffffffffffff808216602085015280604084015116604085015280606084015116606085015280608084015116608085015250505050565b600060208301516134c260c084018273ffffffffffffffffffffffffffffffffffffffff169052565b5060408301516101808060e08501526134df6101a08501836127d4565b915060608501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0808685030161010087015261351c84836127d4565b935060808701519150808685030161012087015261353a84836127d4565b935060a0870151915061356661014087018373ffffffffffffffffffffffffffffffffffffffff169052565b60c087015161016087015260e087015191508086850301838701525061358c8382613284565b9695505050505050565b61010081016135ee828567ffffffffffffffff8151168252602081015173ffffffffffffffffffffffffffffffffffffffff808216602085015280604084015116604085015280606084015116606085015250505050565b825173ffffffffffffffffffffffffffffffffffffffff90811660808401526020840151811660a08401526040840151811660c084015260608401511660e0830152611a1b565b602081526000825160a0602084015261365160c08401826127d4565b905067ffffffffffffffff6020850151166040840152604084015173ffffffffffffffffffffffffffffffffffffffff8082166060860152606086015160808601528060808701511660a086015250508091505092915050565b6000602082840312156136bd57600080fd5b815167ffffffffffffffff808211156136d557600080fd5b90830190604082860312156136e957600080fd5b6136f161259f565b82518281111561370057600080fd5b61370c878286016130c2565b82525060208301518281111561372157600080fd5b61372d878286016130c2565b60208301525095945050505050565b600073ffffffffffffffffffffffffffffffffffffffff808916835260c0602084015261376c60c08401896127d4565b67ffffffffffffffff97881660408501529590961660608301525091909316608082015260a0019190915292915050565b60208152600061072a6020830184613284565b8181038181111561072d5761072d612fc7565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b60008251612e0b8184602087016127b056fea164736f6c6343000818000a", + Bin: "0x6101006040523480156200001257600080fd5b506040516200407238038062004072833981016040819052620000359162000665565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf8162000186565b505083516001600160401b031615905080620000e6575060208301516001600160a01b0316155b80620000fd575060408301516001600160a01b0316155b8062000114575060608301516001600160a01b0316155b1562000133576040516306b7c75960e31b815260040160405180910390fd5b82516001600160401b031660805260208301516001600160a01b0390811660a0526040840151811660c05260608401511660e052620001728262000231565b6200017d8162000390565b5050506200079f565b336001600160a01b03821603620001e05760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b0316158062000254575060408101516001600160a01b0316155b1562000273576040516306b7c75960e31b815260040160405180910390fd5b8051600280546001600160a01b03199081166001600160a01b0393841617909155602080840180516003805485169186169190911790556040808601805160048054871691881691909117905560608088018051600580549098169089161790965582516080808201855280516001600160401b031680835260a080518b16848a0190815260c080518d16868a0190815260e080518f169789019788528a5195865292518e169b85019b909b5299518c169783019790975292518a169381019390935289518916908301529351871693810193909352518516928201929092529151909216918101919091527f23a1adf8ad7fad6091a4803227af2cee848c01a7c812404cade7c25636925e32906101000160405180910390a150565b60005b8151811015620004cf576000828281518110620003b457620003b462000789565b602002602001015190506000838381518110620003d557620003d562000789565b6020026020010151600001519050806001600160401b03166000036200041a5760405163c35aa79d60e01b81526001600160401b038216600482015260240162000083565b6001600160401b03818116600081815260066020908152604091829020868201518154600160481b600160e81b0319811669010000000000000000006001600160a01b03909316928302908117808555865192891691909816178152928301526801000000000000000090940460ff161515918101919091527fd5ad72bc37dc7a80a8b9b9df20500046fd7341adb1be2258a540466fdd7dcef59060600160405180910390a250505080600101905062000393565b5050565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b03811182821017156200050e576200050e620004d3565b60405290565b604080519081016001600160401b03811182821017156200050e576200050e620004d3565b604051601f8201601f191681016001600160401b0381118282101715620005645762000564620004d3565b604052919050565b80516001600160401b03811681146200058457600080fd5b919050565b6001600160a01b03811681146200059f57600080fd5b50565b600082601f830112620005b457600080fd5b815160206001600160401b03821115620005d257620005d2620004d3565b620005e2818360051b0162000539565b82815260069290921b840181019181810190868411156200060257600080fd5b8286015b848110156200065a5760408189031215620006215760008081fd5b6200062b62000514565b62000636826200056c565b815284820151620006478162000589565b8186015283529183019160400162000606565b509695505050505050565b60008060008385036101208112156200067d57600080fd5b60808112156200068c57600080fd5b62000696620004e9565b620006a1866200056c565b81526020860151620006b38162000589565b60208201526040860151620006c88162000589565b60408201526060860151620006dd8162000589565b606082015293506080607f1982011215620006f757600080fd5b5062000702620004e9565b6080850151620007128162000589565b815260a0850151620007248162000589565b602082015260c0850151620007398162000589565b604082015260e08501516200074e8162000589565b60608201526101008501519092506001600160401b038111156200077157600080fd5b6200077f86828701620005a2565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b60805160a05160c05160e05161385a620008186000396000818161022c01528181610cc20152611bea0152600081816101f0015281816112910152611bc30152600081816101b4015281816105de0152611b99015260008181610184015281816111b7015281816116940152611b6c015261385a6000f3fe608060405234801561001057600080fd5b50600436106101365760003560e01c806379ba5097116100b2578063a6f3ab6c11610081578063df0aa9e911610066578063df0aa9e91461052d578063f2fde38b14610540578063fbca3b741461055357600080fd5b8063a6f3ab6c146104cd578063d77d5ed0146104e057600080fd5b806379ba50971461045b5780638da5cb5b146104635780639041be3d14610481578063972b4612146104ad57600080fd5b806334adf4941161010957806348a98aa4116100ee57806348a98aa4146103045780636def4ce71461033c5780637437ff9f146103db57600080fd5b806334adf494146102e95780633a019940146102fc57600080fd5b80630242cf601461013b57806306285c6914610150578063181f5a771461027f57806320487ded146102c8575b600080fd5b61014e6101493660046126df565b610566565b005b61026960408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16815250905090565b60405161027691906127a2565b60405180910390f35b6102bb6040518060400160405280601081526020017f4f6e52616d7020312e362e302d6465760000000000000000000000000000000081525081565b6040516102769190612867565b6102db6102d6366004612892565b61057a565b604051908152602001610276565b61014e6102f73660046128e2565b610733565b61014e610a4f565b610317610312366004612957565b610c7a565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610276565b61039f61034a366004612990565b67ffffffffffffffff9081166000908152600660205260409020549081169168010000000000000000820460ff16916901000000000000000000900473ffffffffffffffffffffffffffffffffffffffff1690565b6040805167ffffffffffffffff9094168452911515602084015273ffffffffffffffffffffffffffffffffffffffff1690820152606001610276565b61044e604080516080810182526000808252602082018190529181018290526060810191909152506040805160808101825260025473ffffffffffffffffffffffffffffffffffffffff908116825260035481166020830152600454811692820192909252600554909116606082015290565b60405161027691906129ad565b61014e610d2f565b60005473ffffffffffffffffffffffffffffffffffffffff16610317565b61049461048f366004612990565b610e2c565b60405167ffffffffffffffff9091168152602001610276565b6104c06104bb366004612990565b610e55565b60405161027691906129f6565b61014e6104db366004612a60565b610e7d565b6103176104ee366004612990565b67ffffffffffffffff166000908152600660205260409020546901000000000000000000900473ffffffffffffffffffffffffffffffffffffffff1690565b6102db61053b366004612ac7565b610e8e565b61014e61054e366004612b33565b611747565b6104c0610561366004612990565b611758565b61056e61178c565b6105778161180f565b50565b6040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815277ffffffffffffffff00000000000000000000000000000000608084901b16600482015260009073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690632cbc26bb90602401602060405180830381865afa158015610625573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106499190612b5e565b15610691576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024015b60405180910390fd5b6002546040517fd8694ccd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063d8694ccd906106e99086908690600401612c8f565b602060405180830381865afa158015610706573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061072a9190612dd8565b90505b92915050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146107a35760055473ffffffffffffffffffffffffffffffffffffffff1633146107a3576040517f905d7d9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015610a4a5760008383838181106107c2576107c2612df1565b90506020028101906107d49190612e20565b6107dd90612ed1565b805167ffffffffffffffff1660009081526006602090815260409182902090830151815490151568010000000000000000027fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff9091161781559082015151919250901561099d5781602001511561095c5760005b82604001515181101561090c5760008360400151828151811061087657610876612df1565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036108f55783516040517f463258ff00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610688565b6109026001840182611986565b5050600101610851565b50816000015167ffffffffffffffff167f330939f6eafe8bb516716892fe962ff19770570838686e6579dbc1cc51fc3281836040015160405161094f91906129f6565b60405180910390a261099d565b81516040517f463258ff00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610688565b60005b8260600151518110156109e9576109e0836060015182815181106109c6576109c6612df1565b6020026020010151836001016119a890919063ffffffff16565b506001016109a0565b5060608201515115610a4057816000015167ffffffffffffffff167fc237ec1921f855ccd5e9a5af9733f2d58943a5a8501ec5988e305d7a4d4215868360600151604051610a3791906129f6565b60405180910390a25b50506001016107a6565b505050565b600254604080517fcdc73d51000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163cdc73d5191600480830192869291908290030181865afa158015610abe573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610b049190810190612f64565b60045490915073ffffffffffffffffffffffffffffffffffffffff1660005b8251811015610a4a576000838281518110610b4057610b40612df1565b60209081029190910101516040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915060009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa158015610bbb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bdf9190612dd8565b90508015610c7057610c0873ffffffffffffffffffffffffffffffffffffffff831685836119ca565b8173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f508d7d183612c18fc339b42618912b9fa3239f631dd7ec0671f950200a0fa66e83604051610c6791815260200190565b60405180910390a35b5050600101610b23565b6040517fbbe4f6db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063bbe4f6db90602401602060405180830381865afa158015610d0b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061072a9190612ff3565b60015473ffffffffffffffffffffffffffffffffffffffff163314610db0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610688565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b67ffffffffffffffff808216600090815260066020526040812054909161072d9116600161303f565b67ffffffffffffffff8116600090815260066020526040902060609061072d90600101611a57565b610e8561178c565b61057781611a6b565b67ffffffffffffffff8416600090815260066020526040812073ffffffffffffffffffffffffffffffffffffffff8316610ef4576040517fa4ec747900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805468010000000000000000900460ff1615610f6557610f176001820184611c4d565b610f65576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152602401610688565b80546901000000000000000000900473ffffffffffffffffffffffffffffffffffffffff163314610fc2576040517f1c0a352900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60035473ffffffffffffffffffffffffffffffffffffffff168015611068576040517fe0a0e50600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82169063e0a0e50690611035908a908a90600401612c8f565b600060405180830381600087803b15801561104f57600080fd5b505af1158015611063573d6000803e3d6000fd5b505050505b506002546000908190819073ffffffffffffffffffffffffffffffffffffffff1663c4276bfc8a61109f60808c0160608d01612b33565b8a6110ad60808e018e613060565b6040518663ffffffff1660e01b81526004016110cd9594939291906130c5565b600060405180830381865afa1580156110ea573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611130919081019061318d565b919450925090506111476080890160608a01612b33565b73ffffffffffffffffffffffffffffffffffffffff167f075a2720282fdf622141dae0b048ef90a21a7e57c134c76912d19d006b3b3f6f8460405161118e91815260200190565b60405180910390a2604080516101a081019091526000610100820181815267ffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000081166101208501528c811661014085015287549293928392916101608401918a91879161120391166131e7565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905567ffffffffffffffff16815260200186611303576040517fea458c0c00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8f16600482015273ffffffffffffffffffffffffffffffffffffffff8c811660248301527f0000000000000000000000000000000000000000000000000000000000000000169063ea458c0c906044016020604051808303816000875af11580156112da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112fe919061320e565b611306565b60005b67ffffffffffffffff1681525081526020018873ffffffffffffffffffffffffffffffffffffffff1681526020018a80602001906113449190613060565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050908252506020016113888b80613060565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250505090825250602081018490526040016113d960808c0160608d01612b33565b73ffffffffffffffffffffffffffffffffffffffff1681526020018981526020018a806040019061140a919061322b565b905067ffffffffffffffff811115611424576114246125b9565b60405190808252806020026020018201604052801561148757816020015b6114746040518060a0016040528060608152602001606081526020016060815260200160008152602001606081525090565b8152602001906001900390816114425790505b509052905060005b61149c60408b018b61322b565b905081101561154b576115226114b560408c018c61322b565b838181106114c5576114c5612df1565b9050604002018036038101906114db9190613293565b8c6114e68d80613060565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508e9250611c7c915050565b8260e00151828151811061153857611538612df1565b602090810291909101015260010161148f565b5060025460e082015160009173ffffffffffffffffffffffffffffffffffffffff169063085318f8908d9061158360408f018f61322b565b6040518563ffffffff1660e01b81526004016115a294939291906133aa565b600060405180830381865afa1580156115bf573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261160591908101906133e0565b905060005b8260e001515181101561165e5781818151811061162957611629612df1565b60200260200101518360e00151828151811061164757611647612df1565b60209081029190910101516080015260010161160a565b50604080517f130ac867e79e2789f923760a88743d292acdf7002139a588206e2260f73f7321602082015267ffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811692820192909252908c1660608201523060808201526116ee90839060a00160405160208183030381529060405280519060200120611fa2565b82515260405167ffffffffffffffff8c16907ff6e86ef8896c7a0d629406168f396e883280680c99e649b9e2d36466fbc9f9e59061172d908590613491565b60405180910390a25051519450505050505b949350505050565b61174f61178c565b610577816120a2565b60606040517f9e7177c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005473ffffffffffffffffffffffffffffffffffffffff16331461180d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610688565b565b60005b815181101561198257600082828151811061182f5761182f612df1565b60200260200101519050600083838151811061184d5761184d612df1565b60200260200101516000015190508067ffffffffffffffff166000036118ab576040517fc35aa79d00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610688565b67ffffffffffffffff8181166000818152600660209081526040918290208682015181547fffffff0000000000000000000000000000000000000000ffffffffffffffffff8116690100000000000000000073ffffffffffffffffffffffffffffffffffffffff909316928302908117808555865192891691909816178152928301526801000000000000000090940460ff161515918101919091527fd5ad72bc37dc7a80a8b9b9df20500046fd7341adb1be2258a540466fdd7dcef59060600160405180910390a2505050806001019050611812565b5050565b600061072a8373ffffffffffffffffffffffffffffffffffffffff8416612197565b600061072a8373ffffffffffffffffffffffffffffffffffffffff84166121e6565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052610a4a9084906122e0565b60606000611a64836123ec565b9392505050565b805173ffffffffffffffffffffffffffffffffffffffff161580611aa75750604081015173ffffffffffffffffffffffffffffffffffffffff16155b15611ade576040517f35be3ac800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051600280547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff93841617909155602080840151600380548416918516919091179055604080850151600480548516918616919091179055606080860151600580549095169086161790935580516080810182527f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681527f00000000000000000000000000000000000000000000000000000000000000008516928101929092527f00000000000000000000000000000000000000000000000000000000000000008416828201527f00000000000000000000000000000000000000000000000000000000000000009093169181019190915290517f23a1adf8ad7fad6091a4803227af2cee848c01a7c812404cade7c25636925e3291611c429184906135df565b60405180910390a150565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600183016020526040812054151561072a565b611cae6040518060a0016040528060608152602001606081526020016060815260200160008152602001606081525090565b8460200151600003611cec576040517f5cf0444900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611cfc858760000151610c7a565b905073ffffffffffffffffffffffffffffffffffffffff81161580611dcc57506040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527faff2afbf00000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff8216906301ffc9a790602401602060405180830381865afa158015611da6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dca9190612b5e565b155b15611e1e5785516040517fbf16aab600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610688565b60008173ffffffffffffffffffffffffffffffffffffffff16639a4575b96040518060a001604052808881526020018967ffffffffffffffff1681526020018773ffffffffffffffffffffffffffffffffffffffff1681526020018a6020015181526020018a6000015173ffffffffffffffffffffffffffffffffffffffff168152506040518263ffffffff1660e01b8152600401611ebd919061367e565b6000604051808303816000875af1158015611edc573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611f2291908101906136f4565b6040805160a0810190915273ffffffffffffffffffffffffffffffffffffffff841660c08201529091508060e0810160405160208183030381529060405281526020018260000151815260200182602001518152602001886020015181526020016040518060200160405280600081525081525092505050949350505050565b60008060001b82846020015185606001518660000151606001518760000151608001518860a001518960c00151604051602001611fe496959493929190613785565b604051602081830303815290604052805190602001208560400151805190602001208660e0015160405160200161201b91906137e6565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201206080808c0151805190840120928501989098529183019590955260608201939093529384015260a083015260c082015260e00160405160208183030381529060405280519060200120905092915050565b3373ffffffffffffffffffffffffffffffffffffffff821603612121576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610688565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60008181526001830160205260408120546121de5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561072d565b50600061072d565b600081815260018301602052604081205480156122cf57600061220a6001836137f9565b855490915060009061221e906001906137f9565b905080821461228357600086600001828154811061223e5761223e612df1565b906000526020600020015490508087600001848154811061226157612261612df1565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806122945761229461380c565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061072d565b600091505061072d565b5092915050565b6000612342826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166124489092919063ffffffff16565b805190915015610a4a57808060200190518101906123609190612b5e565b610a4a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610688565b60608160000180548060200260200160405190810160405280929190818152602001828054801561243c57602002820191906000526020600020905b815481526020019060010190808311612428575b50505050509050919050565b606061173f8484600085856000808673ffffffffffffffffffffffffffffffffffffffff16858760405161247c919061383b565b60006040518083038185875af1925050503d80600081146124b9576040519150601f19603f3d011682016040523d82523d6000602084013e6124be565b606091505b50915091506124cf878383876124da565b979650505050505050565b606083156125705782516000036125695773ffffffffffffffffffffffffffffffffffffffff85163b612569576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610688565b508161173f565b61173f83838151156125855781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106889190612867565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561260b5761260b6125b9565b60405290565b6040516080810167ffffffffffffffff8111828210171561260b5761260b6125b9565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561267b5761267b6125b9565b604052919050565b600067ffffffffffffffff82111561269d5761269d6125b9565b5060051b60200190565b67ffffffffffffffff8116811461057757600080fd5b73ffffffffffffffffffffffffffffffffffffffff8116811461057757600080fd5b600060208083850312156126f257600080fd5b823567ffffffffffffffff81111561270957600080fd5b8301601f8101851361271a57600080fd5b803561272d61272882612683565b612634565b81815260069190911b8201830190838101908783111561274c57600080fd5b928401925b828410156124cf576040848903121561276a5760008081fd5b6127726125e8565b843561277d816126a7565b81528486013561278c816126bd565b8187015282526040939093019290840190612751565b6080810161072d828467ffffffffffffffff8151168252602081015173ffffffffffffffffffffffffffffffffffffffff808216602085015280604084015116604085015280606084015116606085015250505050565b60005b838110156128145781810151838201526020016127fc565b50506000910152565b600081518084526128358160208601602086016127f9565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061072a602083018461281d565b600060a0828403121561288c57600080fd5b50919050565b600080604083850312156128a557600080fd5b82356128b0816126a7565b9150602083013567ffffffffffffffff8111156128cc57600080fd5b6128d88582860161287a565b9150509250929050565b600080602083850312156128f557600080fd5b823567ffffffffffffffff8082111561290d57600080fd5b818501915085601f83011261292157600080fd5b81358181111561293057600080fd5b8660208260051b850101111561294557600080fd5b60209290920196919550909350505050565b6000806040838503121561296a57600080fd5b8235612975816126a7565b91506020830135612985816126bd565b809150509250929050565b6000602082840312156129a257600080fd5b8135611a64816126a7565b6080810161072d8284805173ffffffffffffffffffffffffffffffffffffffff908116835260208083015182169084015260408083015182169084015260609182015116910152565b6020808252825182820181905260009190848201906040850190845b81811015612a4457835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101612a12565b50909695505050505050565b8035612a5b816126bd565b919050565b600060808284031215612a7257600080fd5b612a7a612611565b8235612a85816126bd565b81526020830135612a95816126bd565b60208201526040830135612aa8816126bd565b60408201526060830135612abb816126bd565b60608201529392505050565b60008060008060808587031215612add57600080fd5b8435612ae8816126a7565b9350602085013567ffffffffffffffff811115612b0457600080fd5b612b108782880161287a565b935050604085013591506060850135612b28816126bd565b939692955090935050565b600060208284031215612b4557600080fd5b8135611a64816126bd565b801515811461057757600080fd5b600060208284031215612b7057600080fd5b8151611a6481612b50565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112612bb057600080fd5b830160208101925035905067ffffffffffffffff811115612bd057600080fd5b803603821315612bdf57600080fd5b9250929050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b8183526000602080850194508260005b85811015612c84578135612c52816126bd565b73ffffffffffffffffffffffffffffffffffffffff168752818301358388015260409687019690910190600101612c3f565b509495945050505050565b600067ffffffffffffffff808516835260406020840152612cb08485612b7b565b60a06040860152612cc560e086018284612be6565b915050612cd56020860186612b7b565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc080878503016060880152612d0b848385612be6565b9350604088013592507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1883603018312612d4457600080fd5b60209288019283019235915084821115612d5d57600080fd5b8160061b3603831315612d6f57600080fd5b80878503016080880152612d84848385612c2f565b9450612d9260608901612a50565b73ffffffffffffffffffffffffffffffffffffffff811660a08901529350612dbd6080890189612b7b565b94509250808786030160c088015250506124cf838383612be6565b600060208284031215612dea57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81833603018112612e5457600080fd5b9190910192915050565b600082601f830112612e6f57600080fd5b81356020612e7f61272883612683565b8083825260208201915060208460051b870101935086841115612ea157600080fd5b602086015b84811015612ec6578035612eb9816126bd565b8352918301918301612ea6565b509695505050505050565b600060808236031215612ee357600080fd5b612eeb612611565b8235612ef6816126a7565b81526020830135612f0681612b50565b6020820152604083013567ffffffffffffffff80821115612f2657600080fd5b612f3236838701612e5e565b60408401526060850135915080821115612f4b57600080fd5b50612f5836828601612e5e565b60608301525092915050565b60006020808385031215612f7757600080fd5b825167ffffffffffffffff811115612f8e57600080fd5b8301601f81018513612f9f57600080fd5b8051612fad61272882612683565b81815260059190911b82018301908381019087831115612fcc57600080fd5b928401925b828410156124cf578351612fe4816126bd565b82529284019290840190612fd1565b60006020828403121561300557600080fd5b8151611a64816126bd565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b67ffffffffffffffff8181168382160190808211156122d9576122d9613010565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261309557600080fd5b83018035915067ffffffffffffffff8211156130b057600080fd5b602001915036819003821315612bdf57600080fd5b67ffffffffffffffff8616815273ffffffffffffffffffffffffffffffffffffffff851660208201528360408201526080606082015260006124cf608083018486612be6565b600082601f83011261311c57600080fd5b815167ffffffffffffffff811115613136576131366125b9565b61316760207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601612634565b81815284602083860101111561317c57600080fd5b61173f8260208301602087016127f9565b6000806000606084860312156131a257600080fd5b8351925060208401516131b481612b50565b604085015190925067ffffffffffffffff8111156131d157600080fd5b6131dd8682870161310b565b9150509250925092565b600067ffffffffffffffff80831681810361320457613204613010565b6001019392505050565b60006020828403121561322057600080fd5b8151611a64816126a7565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261326057600080fd5b83018035915067ffffffffffffffff82111561327b57600080fd5b6020019150600681901b3603821315612bdf57600080fd5b6000604082840312156132a557600080fd5b6132ad6125e8565b82356132b8816126bd565b81526020928301359281019290925250919050565b600082825180855260208086019550808260051b84010181860160005b8481101561339d577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018952815160a0815181865261332e8287018261281d565b9150508582015185820387870152613346828261281d565b91505060408083015186830382880152613360838261281d565b92505050606080830151818701525060808083015192508582038187015250613389818361281d565b9a86019a94505050908301906001016132ea565b5090979650505050505050565b67ffffffffffffffff851681526060602082015260006133cd60608301866132cd565b82810360408401526124cf818587612c2f565b600060208083850312156133f357600080fd5b825167ffffffffffffffff8082111561340b57600080fd5b818501915085601f83011261341f57600080fd5b815161342d61272882612683565b81815260059190911b8301840190848101908883111561344c57600080fd5b8585015b83811015613484578051858111156134685760008081fd5b6134768b89838a010161310b565b845250918601918601613450565b5098975050505050505050565b602081526134e260208201835180518252602081015167ffffffffffffffff808216602085015280604084015116604085015280606084015116606085015280608084015116608085015250505050565b6000602083015161350b60c084018273ffffffffffffffffffffffffffffffffffffffff169052565b5060408301516101808060e08501526135286101a085018361281d565b915060608501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08086850301610100870152613565848361281d565b9350608087015191508086850301610120870152613583848361281d565b935060a087015191506135af61014087018373ffffffffffffffffffffffffffffffffffffffff169052565b60c087015161016087015260e08701519150808685030183870152506135d583826132cd565b9695505050505050565b6101008101613637828567ffffffffffffffff8151168252602081015173ffffffffffffffffffffffffffffffffffffffff808216602085015280604084015116604085015280606084015116606085015250505050565b825173ffffffffffffffffffffffffffffffffffffffff90811660808401526020840151811660a08401526040840151811660c084015260608401511660e0830152611a64565b602081526000825160a0602084015261369a60c084018261281d565b905067ffffffffffffffff6020850151166040840152604084015173ffffffffffffffffffffffffffffffffffffffff8082166060860152606086015160808601528060808701511660a086015250508091505092915050565b60006020828403121561370657600080fd5b815167ffffffffffffffff8082111561371e57600080fd5b908301906040828603121561373257600080fd5b61373a6125e8565b82518281111561374957600080fd5b6137558782860161310b565b82525060208301518281111561376a57600080fd5b6137768782860161310b565b60208301525095945050505050565b600073ffffffffffffffffffffffffffffffffffffffff808916835260c060208401526137b560c084018961281d565b67ffffffffffffffff97881660408501529590961660608301525091909316608082015260a0019190915292915050565b60208152600061072a60208301846132cd565b8181038181111561072d5761072d613010565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b60008251612e548184602087016127f956fea164736f6c6343000818000a", } var OnRampABI = OnRampMetaData.ABI diff --git a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt index 743083f50a..d050e401b9 100644 --- a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -24,7 +24,7 @@ multi_ocr3_helper: ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Help nonce_manager: ../../../contracts/solc/v0.8.24/NonceManager/NonceManager.abi ../../../contracts/solc/v0.8.24/NonceManager/NonceManager.bin 6f64e1083b356c06ee66b9138e398b9c97a4cd3e8c9ec38cf3010cebc79af536 ocr3_config_encoder: ../../../contracts/solc/v0.8.24/IOCR3ConfigEncoder/IOCR3ConfigEncoder.abi ../../../contracts/solc/v0.8.24/IOCR3ConfigEncoder/IOCR3ConfigEncoder.bin 9254b35a86f00fde7b7193a033ca58f6521a66e87b9cf9da6ce5660082e79f5d offramp: ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.abi ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.bin 741b4b66670c06c1b09408ec6706656c46e4c98b227111d99f80940cc5faad42 -onramp: ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.abi ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.bin c37096aaa0369ad988e94c300ba62917e17fcc71a3c1aa3e9b8420f21c0591d2 +onramp: ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.abi ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.bin 594439983f963f4158f9c5009dee7cba4ee56be61900bb1d5b9108eaeac3d6a6 ping_pong_demo: ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.abi ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.bin c1c2f8a65c7ffd971899cae7fe62f2da57d09e936151e2b92163c4bebe699d6b price_registry: ../../../contracts/solc/v0.8.24/PriceRegistry/PriceRegistry.abi ../../../contracts/solc/v0.8.24/PriceRegistry/PriceRegistry.bin e7781d600c1bb7aa4620106af7f6e146a109b97f4cb6a7d06c9e15773340ecb2 registry_module_owner_custom: ../../../contracts/solc/v0.8.24/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.abi ../../../contracts/solc/v0.8.24/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.bin 75be86323c227917a9bbc3f799d7ed02f92db546653a36db30ed0ebe64461353 From f550bb4ab931f11452b67adaf438e235a03595e9 Mon Sep 17 00:00:00 2001 From: Ryan <80392855+RayXpub@users.noreply.github.com> Date: Wed, 11 Sep 2024 10:08:09 +0400 Subject: [PATCH 082/115] Miscellaneous fixes and cleanups (#1421) ## Motivation The goal of this PR is to fix several miscellaneous items. ## Solution - Replaces some magic numbers with constants - Default to `private` visibility for state variables that are not used in test helpers - Standardizes some natspec tags (consistent use of `@dev` instead of `@notice` for state variables) - Add a `ConfigSet` event in `CCIPConfig` - Asserts full equality of `OCRConfigWithMeta[]` in `CCIPConfigTests` - Add clarifying comments in `NonceManager` `applyPreviousRampsUpdates` --- contracts/gas-snapshots/ccip.gas-snapshot | 248 +++++++++--------- contracts/src/v0.8/ccip/FeeQuoter.sol | 21 +- .../v0.8/ccip/MultiAggregateRateLimiter.sol | 4 +- contracts/src/v0.8/ccip/NonceManager.sol | 4 +- .../src/v0.8/ccip/capability/CCIPConfig.sol | 20 +- .../src/v0.8/ccip/interfaces/IFeeQuoter.sol | 2 +- contracts/src/v0.8/ccip/offRamp/OffRamp.sol | 12 +- contracts/src/v0.8/ccip/onRamp/OnRamp.sol | 12 +- .../ccip/test/capability/CCIPConfig.t.sol | 124 ++++++--- .../ccip/generated/ccip_config/ccip_config.go | 153 ++++++++++- .../ccip/generated/fee_quoter/fee_quoter.go | 52 +++- ...rapper-dependency-versions-do-not-edit.txt | 4 +- .../ccip/mocks/fee_quoter_interface.go | 116 ++++++++ 13 files changed, 568 insertions(+), 204 deletions(-) diff --git a/contracts/gas-snapshots/ccip.gas-snapshot b/contracts/gas-snapshots/ccip.gas-snapshot index 018caf5293..7a3587415c 100644 --- a/contracts/gas-snapshots/ccip.gas-snapshot +++ b/contracts/gas-snapshots/ccip.gas-snapshot @@ -10,8 +10,8 @@ AggregateTokenLimiter_getTokenBucket:test_GetTokenBucket_Success() (gas: 19835) AggregateTokenLimiter_getTokenBucket:test_Refill_Success() (gas: 41499) AggregateTokenLimiter_getTokenBucket:test_TimeUnderflow_Revert() (gas: 15446) AggregateTokenLimiter_getTokenLimitAdmin:test_GetTokenLimitAdmin_Success() (gas: 10531) -AggregateTokenLimiter_getTokenValue:test_GetTokenValue_Success() (gas: 19674) -AggregateTokenLimiter_getTokenValue:test_NoTokenPrice_Reverts() (gas: 21259) +AggregateTokenLimiter_getTokenValue:test_GetTokenValue_Success() (gas: 19652) +AggregateTokenLimiter_getTokenValue:test_NoTokenPrice_Reverts() (gas: 21237) AggregateTokenLimiter_rateLimitValue:test_AggregateValueMaxCapacityExceeded_Revert() (gas: 16508) AggregateTokenLimiter_rateLimitValue:test_RateLimitValueSuccess_gas() (gas: 18348) AggregateTokenLimiter_setAdmin:test_OnlyOwnerOrAdmin_Revert() (gas: 13054) @@ -54,9 +54,9 @@ CCIPConfig_ConfigStateMachine:test__validateConfigTransition_RunningToStaging_Wr CCIPConfig_ConfigStateMachine:test__validateConfigTransition_StagingToRunning_Success() (gas: 369785) CCIPConfig_ConfigStateMachine:test__validateConfigTransition_StagingToRunning_WrongConfigDigest_Reverts() (gas: 145513) CCIPConfig_ConfigStateMachine:test_getCapabilityConfiguration_Success() (gas: 9627) -CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_CommitAndExecConfig_Success() (gas: 1752535) -CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_CommitConfigOnly_Success() (gas: 1019020) -CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_ExecConfigOnly_Success() (gas: 1019051) +CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_CommitAndExecConfig_Success() (gas: 1790808) +CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_CommitConfigOnly_Success() (gas: 1038239) +CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_ExecConfigOnly_Success() (gas: 1038270) CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_OnlyCapabilitiesRegistryCanCall_Reverts() (gas: 9611) CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_ZeroLengthConfig_Success() (gas: 15996) CCIPConfig_beforeCapabilityConfigSet:test_getCapabilityConfiguration_Success() (gas: 9627) @@ -67,14 +67,14 @@ CCIPConfig_chainConfig:test_applyChainConfigUpdates_removeChainConfigs_Success() CCIPConfig_chainConfig:test_applyChainConfigUpdates_selectorNotFound_Reverts() (gas: 14819) CCIPConfig_chainConfig:test_getCapabilityConfiguration_Success() (gas: 9648) CCIPConfig_chainConfig:test_getPaginatedCCIPConfigs_Success() (gas: 370293) -CCIPConfig_constructor:test_constructor_Success() (gas: 3344515) -CCIPConfig_constructor:test_constructor_ZeroAddressNotAllowed_Revert() (gas: 61446) -CCIPConfig_updatePluginConfig:test__updatePluginConfig_InitToRunning_Success() (gas: 1008427) -CCIPConfig_updatePluginConfig:test__updatePluginConfig_InvalidConfigLength_Reverts() (gas: 25584) -CCIPConfig_updatePluginConfig:test__updatePluginConfig_InvalidConfigStateTransition_Reverts() (gas: 21799) -CCIPConfig_updatePluginConfig:test__updatePluginConfig_RunningToStaging_Success() (gas: 1895604) -CCIPConfig_updatePluginConfig:test__updatePluginConfig_StagingToRunning_Success() (gas: 2465196) -CCIPConfig_updatePluginConfig:test_getCapabilityConfiguration_Success() (gas: 9627) +CCIPConfig_constructor:test_constructor_Success() (gas: 3363163) +CCIPConfig_constructor:test_constructor_ZeroAddressNotAllowed_Revert() (gas: 61471) +CCIPConfig_updatePluginConfig:test__updatePluginConfig_InvalidConfigLength_Reverts() (gas: 25819) +CCIPConfig_updatePluginConfig:test__updatePluginConfig_InvalidConfigStateTransition_Reverts() (gas: 21913) +CCIPConfig_updatePluginConfig:test_getCapabilityConfiguration_Success() (gas: 9649) +CCIPConfig_updatePluginConfig:test_updatePluginConfig_InitToRunning_Success() (gas: 1087677) +CCIPConfig_updatePluginConfig:test_updatePluginConfig_RunningToStaging_Success() (gas: 2032286) +CCIPConfig_updatePluginConfig:test_updatePluginConfig_StagingToRunning_Success() (gas: 2032320) CCIPConfig_validateConfig:test__validateConfig_ABIEncodedAddress_OfframpAddressCannotBeZero_Reverts() (gas: 290828) CCIPConfig_validateConfig:test__validateConfig_ChainSelectorNotFound_Reverts() (gas: 293559) CCIPConfig_validateConfig:test__validateConfig_ChainSelectorNotSet_Reverts() (gas: 290461) @@ -99,9 +99,9 @@ CommitStore_report:test_Paused_Revert() (gas: 21262) CommitStore_report:test_ReportAndPriceUpdate_Success() (gas: 84276) CommitStore_report:test_ReportOnlyRootSuccess_gas() (gas: 56258) CommitStore_report:test_RootAlreadyCommitted_Revert() (gas: 63984) -CommitStore_report:test_StaleReportWithRoot_Success() (gas: 119394) +CommitStore_report:test_StaleReportWithRoot_Success() (gas: 119350) CommitStore_report:test_Unhealthy_Revert() (gas: 44754) -CommitStore_report:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 100782) +CommitStore_report:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 100760) CommitStore_report:test_ZeroEpochAndRound_Revert() (gas: 27632) CommitStore_resetUnblessedRoots:test_OnlyOwner_Revert() (gas: 11331) CommitStore_resetUnblessedRoots:test_ResetUnblessedRoots_Success() (gas: 143814) @@ -117,7 +117,7 @@ CommitStore_verify:test_Paused_Revert() (gas: 18505) CommitStore_verify:test_TooManyLeaves_Revert() (gas: 36797) DefensiveExampleTest:test_HappyPath_Success() (gas: 200047) DefensiveExampleTest:test_Recovery() (gas: 424294) -E2E:test_E2E_3MessagesSuccess_gas() (gas: 1101943) +E2E:test_E2E_3MessagesSuccess_gas() (gas: 1101745) EVM2EVMOffRamp__releaseOrMintToken:test__releaseOrMintToken_NotACompatiblePool_Revert() (gas: 37818) EVM2EVMOffRamp__releaseOrMintToken:test__releaseOrMintToken_Success() (gas: 103820) EVM2EVMOffRamp__releaseOrMintToken:test__releaseOrMintToken_TokenHandlingError_transfer_Revert() (gas: 85333) @@ -125,20 +125,20 @@ EVM2EVMOffRamp__releaseOrMintToken:test_releaseOrMintToken_InvalidDataLength_Rev EVM2EVMOffRamp__releaseOrMintToken:test_releaseOrMintToken_ReleaseOrMintBalanceMismatch_Revert() (gas: 94389) EVM2EVMOffRamp__releaseOrMintToken:test_releaseOrMintToken_TokenHandlingError_BalanceOf_Revert() (gas: 39813) EVM2EVMOffRamp__releaseOrMintToken:test_releaseOrMintToken_skip_ReleaseOrMintBalanceMismatch_if_pool_Revert() (gas: 86631) -EVM2EVMOffRamp__releaseOrMintTokens:test_OverValueWithARLOff_Success() (gas: 385756) -EVM2EVMOffRamp__releaseOrMintTokens:test_PriceNotFoundForToken_Reverts() (gas: 142019) -EVM2EVMOffRamp__releaseOrMintTokens:test_RateLimitErrors_Reverts() (gas: 804151) -EVM2EVMOffRamp__releaseOrMintTokens:test_TokenHandlingError_Reverts() (gas: 179460) +EVM2EVMOffRamp__releaseOrMintTokens:test_OverValueWithARLOff_Success() (gas: 385690) +EVM2EVMOffRamp__releaseOrMintTokens:test_PriceNotFoundForToken_Reverts() (gas: 141997) +EVM2EVMOffRamp__releaseOrMintTokens:test_RateLimitErrors_Reverts() (gas: 804041) +EVM2EVMOffRamp__releaseOrMintTokens:test_TokenHandlingError_Reverts() (gas: 179438) EVM2EVMOffRamp__releaseOrMintTokens:test__releaseOrMintTokens_NotACompatiblePool_Reverts() (gas: 29243) EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_InvalidDataLengthReturnData_Revert() (gas: 66504) EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_InvalidEVMAddress_Revert() (gas: 43320) -EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_Success() (gas: 211280) -EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals_Success() (gas: 222532) +EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_Success() (gas: 211236) +EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals_Success() (gas: 222488) EVM2EVMOffRamp__report:test_Report_Success() (gas: 126703) -EVM2EVMOffRamp__trialExecute:test_RateLimitError_Success() (gas: 238004) -EVM2EVMOffRamp__trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 246604) -EVM2EVMOffRamp__trialExecute:test_TokenPoolIsNotAContract_Success() (gas: 330188) -EVM2EVMOffRamp__trialExecute:test_trialExecute_Success() (gas: 312619) +EVM2EVMOffRamp__trialExecute:test_RateLimitError_Success() (gas: 237982) +EVM2EVMOffRamp__trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 246582) +EVM2EVMOffRamp__trialExecute:test_TokenPoolIsNotAContract_Success() (gas: 330144) +EVM2EVMOffRamp__trialExecute:test_trialExecute_Success() (gas: 312575) EVM2EVMOffRamp_ccipReceive:test_Reverts() (gas: 17033) EVM2EVMOffRamp_constructor:test_CommitStoreAlreadyInUse_Revert() (gas: 153548) EVM2EVMOffRamp_constructor:test_Constructor_Success() (gas: 5549627) @@ -146,7 +146,7 @@ EVM2EVMOffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 144282) EVM2EVMOffRamp_execute:test_EmptyReport_Revert() (gas: 21321) EVM2EVMOffRamp_execute:test_InvalidMessageId_Revert() (gas: 36558) EVM2EVMOffRamp_execute:test_InvalidSourceChain_Revert() (gas: 51775) -EVM2EVMOffRamp_execute:test_InvalidSourcePoolAddress_Success() (gas: 474025) +EVM2EVMOffRamp_execute:test_InvalidSourcePoolAddress_Success() (gas: 473981) EVM2EVMOffRamp_execute:test_ManualExecutionNotYetEnabled_Revert() (gas: 47830) EVM2EVMOffRamp_execute:test_MessageTooLarge_Revert() (gas: 152518) EVM2EVMOffRamp_execute:test_Paused_Revert() (gas: 103046) @@ -157,25 +157,25 @@ EVM2EVMOffRamp_execute:test_SingleMessageNoTokensUnordered_Success() (gas: 15789 EVM2EVMOffRamp_execute:test_SingleMessageNoTokens_Success() (gas: 173184) EVM2EVMOffRamp_execute:test_SingleMessageToNonCCIPReceiver_Success() (gas: 247246) EVM2EVMOffRamp_execute:test_SingleMessagesNoTokensSuccess_gas() (gas: 113971) -EVM2EVMOffRamp_execute:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 408147) +EVM2EVMOffRamp_execute:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 408103) EVM2EVMOffRamp_execute:test_SkippedIncorrectNonce_Success() (gas: 54294) EVM2EVMOffRamp_execute:test_StrictUntouchedToSuccess_Success() (gas: 131317) EVM2EVMOffRamp_execute:test_TokenDataMismatch_Revert() (gas: 52249) -EVM2EVMOffRamp_execute:test_TwoMessagesWithTokensAndGE_Success() (gas: 564489) -EVM2EVMOffRamp_execute:test_TwoMessagesWithTokensSuccess_gas() (gas: 495004) +EVM2EVMOffRamp_execute:test_TwoMessagesWithTokensAndGE_Success() (gas: 564401) +EVM2EVMOffRamp_execute:test_TwoMessagesWithTokensSuccess_gas() (gas: 494916) EVM2EVMOffRamp_execute:test_UnexpectedTokenData_Revert() (gas: 35497) -EVM2EVMOffRamp_execute:test_Unhealthy_Revert() (gas: 545754) +EVM2EVMOffRamp_execute:test_Unhealthy_Revert() (gas: 545666) EVM2EVMOffRamp_execute:test_UnsupportedNumberOfTokens_Revert() (gas: 64497) EVM2EVMOffRamp_execute:test__execute_SkippedAlreadyExecutedMessageUnordered_Success() (gas: 122676) EVM2EVMOffRamp_execute:test__execute_SkippedAlreadyExecutedMessage_Success() (gas: 142850) EVM2EVMOffRamp_execute:test_execute_RouterYULCall_Success() (gas: 427538) EVM2EVMOffRamp_executeSingleMessage:test_MessageSender_Revert() (gas: 18502) -EVM2EVMOffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 278406) +EVM2EVMOffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 278362) EVM2EVMOffRamp_executeSingleMessage:test_NonContract_Success() (gas: 18668) -EVM2EVMOffRamp_executeSingleMessage:test_TokenHandlingError_Revert() (gas: 224131) +EVM2EVMOffRamp_executeSingleMessage:test_TokenHandlingError_Revert() (gas: 224109) EVM2EVMOffRamp_executeSingleMessage:test_ZeroGasDONExecution_Revert() (gas: 47926) EVM2EVMOffRamp_executeSingleMessage:test_executeSingleMessage_NoTokens_Success() (gas: 47403) -EVM2EVMOffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens_Success() (gas: 314268) +EVM2EVMOffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens_Success() (gas: 314224) EVM2EVMOffRamp_executeSingleMessage:test_executeSingleMessage_ZeroGasZeroData_Success() (gas: 70065) EVM2EVMOffRamp_execute_upgrade:test_V2NonceNewSenderStartsAtZero_Success() (gas: 229454) EVM2EVMOffRamp_execute_upgrade:test_V2NonceStartsAtV1Nonce_Success() (gas: 276982) @@ -189,13 +189,13 @@ EVM2EVMOffRamp_manuallyExecute:test_ManualExecFailedTx_Revert() (gas: 185967) EVM2EVMOffRamp_manuallyExecute:test_ManualExecForkedChain_Revert() (gas: 27052) EVM2EVMOffRamp_manuallyExecute:test_ManualExecGasLimitMismatch_Revert() (gas: 45200) EVM2EVMOffRamp_manuallyExecute:test_ManualExecInvalidGasLimit_Revert() (gas: 27471) -EVM2EVMOffRamp_manuallyExecute:test_ManualExecWithMultipleMessagesAndSourceTokens_Success() (gas: 530877) -EVM2EVMOffRamp_manuallyExecute:test_ManualExecWithSourceTokens_Success() (gas: 346127) +EVM2EVMOffRamp_manuallyExecute:test_ManualExecWithMultipleMessagesAndSourceTokens_Success() (gas: 530789) +EVM2EVMOffRamp_manuallyExecute:test_ManualExecWithSourceTokens_Success() (gas: 346083) EVM2EVMOffRamp_manuallyExecute:test_ManualExec_Success() (gas: 187459) -EVM2EVMOffRamp_manuallyExecute:test_ReentrancyManualExecuteFails_Success() (gas: 2258388) -EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_DestinationGasAmountCountMismatch_Revert() (gas: 363340) +EVM2EVMOffRamp_manuallyExecute:test_ReentrancyManualExecuteFails_Success() (gas: 2258366) +EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_DestinationGasAmountCountMismatch_Revert() (gas: 363296) EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_DoesNotRevertIfUntouched_Success() (gas: 143972) -EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_InvalidTokenGasOverride_Revert() (gas: 366479) +EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_InvalidTokenGasOverride_Revert() (gas: 366435) EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_LowGasLimitManualExec_Success() (gas: 482796) EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_WithGasOverride_Success() (gas: 189862) EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_WithInvalidReceiverExecutionGasOverride_Revert() (gas: 153716) @@ -219,18 +219,18 @@ EVM2EVMOnRamp_forwardFromRouter:test_InvalidAddressEncodePacked_Revert() (gas: 3 EVM2EVMOnRamp_forwardFromRouter:test_InvalidAddress_Revert() (gas: 38497) EVM2EVMOnRamp_forwardFromRouter:test_InvalidChainSelector_Revert() (gas: 25534) EVM2EVMOnRamp_forwardFromRouter:test_InvalidExtraArgsTag_Revert() (gas: 25320) -EVM2EVMOnRamp_forwardFromRouter:test_MaxCapacityExceeded_Revert() (gas: 86160) +EVM2EVMOnRamp_forwardFromRouter:test_MaxCapacityExceeded_Revert() (gas: 86138) EVM2EVMOnRamp_forwardFromRouter:test_MaxFeeBalanceReached_Revert() (gas: 36514) EVM2EVMOnRamp_forwardFromRouter:test_MessageGasLimitTooHigh_Revert() (gas: 29078) EVM2EVMOnRamp_forwardFromRouter:test_MessageTooLarge_Revert() (gas: 107622) EVM2EVMOnRamp_forwardFromRouter:test_OriginalSender_Revert() (gas: 22724) -EVM2EVMOnRamp_forwardFromRouter:test_OverValueWithARLOff_Success() (gas: 227461) +EVM2EVMOnRamp_forwardFromRouter:test_OverValueWithARLOff_Success() (gas: 227439) EVM2EVMOnRamp_forwardFromRouter:test_Paused_Revert() (gas: 53150) EVM2EVMOnRamp_forwardFromRouter:test_Permissions_Revert() (gas: 25559) -EVM2EVMOnRamp_forwardFromRouter:test_PriceNotFoundForToken_Revert() (gas: 59500) +EVM2EVMOnRamp_forwardFromRouter:test_PriceNotFoundForToken_Revert() (gas: 59478) EVM2EVMOnRamp_forwardFromRouter:test_ShouldIncrementNonceOnlyOnOrdered_Success() (gas: 179442) EVM2EVMOnRamp_forwardFromRouter:test_ShouldIncrementSeqNumAndNonce_Success() (gas: 177724) -EVM2EVMOnRamp_forwardFromRouter:test_ShouldStoreNonLinkFees() (gas: 137377) +EVM2EVMOnRamp_forwardFromRouter:test_ShouldStoreNonLinkFees() (gas: 137333) EVM2EVMOnRamp_forwardFromRouter:test_SourceTokenDataTooLarge_Revert() (gas: 3772676) EVM2EVMOnRamp_forwardFromRouter:test_TooManyTokens_Revert() (gas: 30244) EVM2EVMOnRamp_forwardFromRouter:test_Unhealthy_Revert() (gas: 43342) @@ -238,7 +238,7 @@ EVM2EVMOnRamp_forwardFromRouter:test_UnsupportedToken_Revert() (gas: 109440) EVM2EVMOnRamp_forwardFromRouter:test_ZeroAddressReceiver_Revert() (gas: 313095) EVM2EVMOnRamp_forwardFromRouter:test_forwardFromRouter_ShouldStoreLinkFees_Success() (gas: 112430) EVM2EVMOnRamp_forwardFromRouter:test_forwardFromRouter_UnsupportedToken_Revert() (gas: 72269) -EVM2EVMOnRamp_forwardFromRouter:test_forwardFromRouter_correctSourceTokenData_Success() (gas: 713890) +EVM2EVMOnRamp_forwardFromRouter:test_forwardFromRouter_correctSourceTokenData_Success() (gas: 713846) EVM2EVMOnRamp_forwardFromRouter_upgrade:test_V2NonceNewSenderStartsAtZero_Success() (gas: 147709) EVM2EVMOnRamp_forwardFromRouter_upgrade:test_V2NonceStartsAtV1Nonce_Success() (gas: 190616) EVM2EVMOnRamp_forwardFromRouter_upgrade:test_V2SenderNoncesReadsPreviousRamp_Success() (gas: 121404) @@ -328,20 +328,20 @@ FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesDefaultTxG FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesDefaultTxGasLimitGtMaxPerMessageGasLimit_Revert() (gas: 39969) FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesZeroIntput_Success() (gas: 12342) FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdates_Success() (gas: 135942) -FeeQuoter_applyFeeTokensUpdates:test_ApplyFeeTokensUpdates_Success() (gas: 79906) +FeeQuoter_applyFeeTokensUpdates:test_ApplyFeeTokensUpdates_Success() (gas: 80117) FeeQuoter_applyFeeTokensUpdates:test_OnlyCallableByOwner_Revert() (gas: 12615) -FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_OnlyCallableByOwnerOrAdmin_Revert() (gas: 11433) -FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesMultipleTokens_Success() (gas: 54213) -FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesSingleToken_Success() (gas: 44857) -FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesZeroInput() (gas: 12257) +FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_OnlyCallableByOwnerOrAdmin_Revert() (gas: 11456) +FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesMultipleTokens_Success() (gas: 54236) +FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesSingleToken_Success() (gas: 44880) +FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesZeroInput() (gas: 12280) FeeQuoter_applyTokenTransferFeeConfigUpdates:test_ApplyTokenTransferFeeConfig_Success() (gas: 86968) FeeQuoter_applyTokenTransferFeeConfigUpdates:test_ApplyTokenTransferFeeZeroInput() (gas: 13089) FeeQuoter_applyTokenTransferFeeConfigUpdates:test_InvalidDestBytesOverhead_Revert() (gas: 17071) FeeQuoter_applyTokenTransferFeeConfigUpdates:test_OnlyCallableByOwnerOrAdmin_Revert() (gas: 12246) -FeeQuoter_constructor:test_InvalidLinkTokenEqZeroAddress_Revert() (gas: 106810) -FeeQuoter_constructor:test_InvalidMaxFeeJuelsPerMsg_Revert() (gas: 111160) -FeeQuoter_constructor:test_InvalidStalenessThreshold_Revert() (gas: 111213) -FeeQuoter_constructor:test_Setup_Success() (gas: 5195512) +FeeQuoter_constructor:test_InvalidLinkTokenEqZeroAddress_Revert() (gas: 106820) +FeeQuoter_constructor:test_InvalidMaxFeeJuelsPerMsg_Revert() (gas: 111170) +FeeQuoter_constructor:test_InvalidStalenessThreshold_Revert() (gas: 111223) +FeeQuoter_constructor:test_Setup_Success() (gas: 5205186) FeeQuoter_convertTokenAmount:test_ConvertTokenAmount_Success() (gas: 72751) FeeQuoter_convertTokenAmount:test_LinkTokenNotSupported_Revert() (gas: 30981) FeeQuoter_getDataAvailabilityCost:test_EmptyMessageCalculatesDataAvailabilityCost_Success() (gas: 94441) @@ -351,7 +351,7 @@ FeeQuoter_getTokenAndGasPrices:test_GetFeeTokenAndGasPrices_Success() (gas: 7046 FeeQuoter_getTokenAndGasPrices:test_StaleGasPrice_Revert() (gas: 16838) FeeQuoter_getTokenAndGasPrices:test_UnsupportedChain_Revert() (gas: 16140) FeeQuoter_getTokenAndGasPrices:test_ZeroGasPrice_Success() (gas: 45771) -FeeQuoter_getTokenPrice:test_GetTokenPriceFromFeed_Success() (gas: 62264) +FeeQuoter_getTokenPrice:test_GetTokenPriceFromFeed_Success() (gas: 62227) FeeQuoter_getTokenPrices:test_GetTokenPrices_Success() (gas: 84818) FeeQuoter_getTokenTransferCost:test_CustomTokenBpsFee_Success() (gas: 41281) FeeQuoter_getTokenTransferCost:test_FeeTokenBpsFee_Success() (gas: 34730) @@ -374,23 +374,23 @@ FeeQuoter_getValidatedFee:test_NotAFeeToken_Revert() (gas: 21073) FeeQuoter_getValidatedFee:test_SingleTokenMessage_Success() (gas: 117032) FeeQuoter_getValidatedFee:test_TooManyTokens_Revert() (gas: 22562) FeeQuoter_getValidatedFee:test_ZeroDataAvailabilityMultiplier_Success() (gas: 64442) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Above18Decimals_Success() (gas: 2076337) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Below18Decimals_Success() (gas: 2076295) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt0Decimals_Success() (gas: 2056414) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt18Decimals_Success() (gas: 2076069) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFlippedDecimals_Success() (gas: 2076273) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedMaxInt224Value_Success() (gas: 2076085) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedOverStalenessPeriod_Success() (gas: 62016) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeed_Success() (gas: 61896) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Above18Decimals_Success() (gas: 2076322) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Below18Decimals_Success() (gas: 2076280) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt0Decimals_Success() (gas: 2056399) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt18Decimals_Success() (gas: 2076054) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFlippedDecimals_Success() (gas: 2076258) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedMaxInt224Value_Success() (gas: 2076070) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedOverStalenessPeriod_Success() (gas: 62001) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeed_Success() (gas: 61881) FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPrice_Success() (gas: 61042) -FeeQuoter_getValidatedTokenPrice:test_OverflowFeedPrice_Revert() (gas: 2075772) +FeeQuoter_getValidatedTokenPrice:test_OverflowFeedPrice_Revert() (gas: 2075757) FeeQuoter_getValidatedTokenPrice:test_StaleFeeToken_Success() (gas: 61569) -FeeQuoter_getValidatedTokenPrice:test_TokenNotSupportedFeed_Revert() (gas: 109132) +FeeQuoter_getValidatedTokenPrice:test_TokenNotSupportedFeed_Revert() (gas: 109117) FeeQuoter_getValidatedTokenPrice:test_TokenNotSupported_Revert() (gas: 13863) FeeQuoter_getValidatedTokenPrice:test_UnderflowFeedPrice_Revert() (gas: 2074434) -FeeQuoter_onReport:test_OnReport_StaleUpdate_Revert() (gas: 43358) +FeeQuoter_onReport:test_OnReport_StaleUpdate_Revert() (gas: 43336) FeeQuoter_onReport:test_onReport_InvalidForwarder_Reverts() (gas: 23306) -FeeQuoter_onReport:test_onReport_Success() (gas: 80684) +FeeQuoter_onReport:test_onReport_Success() (gas: 80582) FeeQuoter_onReport:test_onReport_UnsupportedToken_Reverts() (gas: 26692) FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsDefault_Success() (gas: 17191) FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsEnforceOutOfOrder_Revert() (gas: 21302) @@ -398,24 +398,24 @@ FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsGasLimitTooHigh_Revert() ( FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsInvalidExtraArgsTag_Revert() (gas: 17923) FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsV1_Success() (gas: 18291) FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsV2_Success() (gas: 18407) -FeeQuoter_processMessageArgs:test_InvalidExtraArgs_Revert() (gas: 18361) -FeeQuoter_processMessageArgs:test_MalformedEVMExtraArgs_Revert() (gas: 18907) -FeeQuoter_processMessageArgs:test_MessageFeeTooHigh_Revert() (gas: 16426) -FeeQuoter_processMessageArgs:test_WitEVMExtraArgsV2_Success() (gas: 26299) -FeeQuoter_processMessageArgs:test_WithConvertedTokenAmount_Success() (gas: 32465) -FeeQuoter_processMessageArgs:test_WithEVMExtraArgsV1_Success() (gas: 25911) -FeeQuoter_processMessageArgs:test_WithEmptyEVMExtraArgs_Success() (gas: 23726) -FeeQuoter_processMessageArgs:test_WithLinkTokenAmount_Success() (gas: 17375) +FeeQuoter_processMessageArgs:test_InvalidExtraArgs_Revert() (gas: 18339) +FeeQuoter_processMessageArgs:test_MalformedEVMExtraArgs_Revert() (gas: 18885) +FeeQuoter_processMessageArgs:test_MessageFeeTooHigh_Revert() (gas: 16404) +FeeQuoter_processMessageArgs:test_WitEVMExtraArgsV2_Success() (gas: 26277) +FeeQuoter_processMessageArgs:test_WithConvertedTokenAmount_Success() (gas: 32443) +FeeQuoter_processMessageArgs:test_WithEVMExtraArgsV1_Success() (gas: 25889) +FeeQuoter_processMessageArgs:test_WithEmptyEVMExtraArgs_Success() (gas: 23704) +FeeQuoter_processMessageArgs:test_WithLinkTokenAmount_Success() (gas: 17353) FeeQuoter_updatePrices:test_OnlyCallableByUpdater_Revert() (gas: 12114) FeeQuoter_updatePrices:test_OnlyGasPrice_Success() (gas: 23599) -FeeQuoter_updatePrices:test_OnlyTokenPrice_Success() (gas: 30637) -FeeQuoter_updatePrices:test_UpdatableByAuthorizedCaller_Success() (gas: 76027) -FeeQuoter_updatePrices:test_UpdateMultiplePrices_Success() (gas: 151411) -FeeQuoter_updateTokenPriceFeeds:test_FeedNotUpdated() (gas: 50545) -FeeQuoter_updateTokenPriceFeeds:test_FeedUnset_Success() (gas: 63662) +FeeQuoter_updatePrices:test_OnlyTokenPrice_Success() (gas: 30615) +FeeQuoter_updatePrices:test_UpdatableByAuthorizedCaller_Success() (gas: 76009) +FeeQuoter_updatePrices:test_UpdateMultiplePrices_Success() (gas: 151345) +FeeQuoter_updateTokenPriceFeeds:test_FeedNotUpdated() (gas: 50523) +FeeQuoter_updateTokenPriceFeeds:test_FeedUnset_Success() (gas: 63574) FeeQuoter_updateTokenPriceFeeds:test_FeedUpdatedByNonOwner_Revert() (gas: 19938) -FeeQuoter_updateTokenPriceFeeds:test_MultipleFeedUpdate_Success() (gas: 89008) -FeeQuoter_updateTokenPriceFeeds:test_SingleFeedUpdate_Success() (gas: 50839) +FeeQuoter_updateTokenPriceFeeds:test_MultipleFeedUpdate_Success() (gas: 88920) +FeeQuoter_updateTokenPriceFeeds:test_SingleFeedUpdate_Success() (gas: 50795) FeeQuoter_updateTokenPriceFeeds:test_ZeroFeeds_Success() (gas: 12296) FeeQuoter_validateDestFamilyAddress:test_InvalidEVMAddressEncodePacked_Revert() (gas: 10622) FeeQuoter_validateDestFamilyAddress:test_InvalidEVMAddressPrecompiles_Revert() (gas: 3967790) @@ -498,27 +498,27 @@ MultiAggregateRateLimiter_constructor:test_Constructor_Success() (gas: 2166413) MultiAggregateRateLimiter_getTokenBucket:test_GetTokenBucket_Success() (gas: 30404) MultiAggregateRateLimiter_getTokenBucket:test_Refill_Success() (gas: 47673) MultiAggregateRateLimiter_getTokenBucket:test_TimeUnderflow_Revert() (gas: 15863) -MultiAggregateRateLimiter_getTokenValue:test_GetTokenValue_Success() (gas: 19668) -MultiAggregateRateLimiter_getTokenValue:test_NoTokenPrice_Reverts() (gas: 21253) +MultiAggregateRateLimiter_getTokenValue:test_GetTokenValue_Success() (gas: 19646) +MultiAggregateRateLimiter_getTokenValue:test_NoTokenPrice_Reverts() (gas: 21231) MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageFromUnauthorizedCaller_Revert() (gas: 14533) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithDifferentTokensOnDifferentChains_Success() (gas: 214266) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithDisabledRateLimitToken_Success() (gas: 60479) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithDifferentTokensOnDifferentChains_Success() (gas: 214200) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithDisabledRateLimitToken_Success() (gas: 60457) MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithNoTokens_Success() (gas: 17599) MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitDisabled_Success() (gas: 45006) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitExceeded_Revert() (gas: 50584) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitReset_Success() (gas: 78872) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithTokensOnDifferentChains_Success() (gas: 312547) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithTokens_Success() (gas: 54776) -MultiAggregateRateLimiter_onOutboundMessage:test_RateLimitValueDifferentLanes_Success() (gas: 1073667418) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitExceeded_Revert() (gas: 50540) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitReset_Success() (gas: 78784) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithTokensOnDifferentChains_Success() (gas: 312459) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithTokens_Success() (gas: 54732) +MultiAggregateRateLimiter_onOutboundMessage:test_RateLimitValueDifferentLanes_Success() (gas: 1073667462) MultiAggregateRateLimiter_onOutboundMessage:test_ValidateMessageWithNoTokens_Success() (gas: 19158) MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageFromUnauthorizedCaller_Revert() (gas: 15829) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithDifferentTokensOnDifferentChains_Success() (gas: 214110) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithDisabledRateLimitToken_Success() (gas: 62262) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithDifferentTokensOnDifferentChains_Success() (gas: 214044) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithDisabledRateLimitToken_Success() (gas: 62240) MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitDisabled_Success() (gas: 46818) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitExceeded_Revert() (gas: 52405) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitReset_Success() (gas: 80129) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithTokensOnDifferentChains_Success() (gas: 312617) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithTokens_Success() (gas: 56581) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitExceeded_Revert() (gas: 52361) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitReset_Success() (gas: 80041) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithTokensOnDifferentChains_Success() (gas: 312529) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithTokens_Success() (gas: 56537) MultiAggregateRateLimiter_setFeeQuoter:test_OnlyOwner_Revert() (gas: 11325) MultiAggregateRateLimiter_setFeeQuoter:test_Owner_Success() (gas: 19072) MultiAggregateRateLimiter_setFeeQuoter:test_ZeroAddress_Revert() (gas: 10597) @@ -559,8 +559,8 @@ MultiOCR3Base_transmit:test_UnAuthorizedTransmitter_Revert() (gas: 24189) MultiOCR3Base_transmit:test_UnauthorizedSigner_Revert() (gas: 61131) MultiOCR3Base_transmit:test_UnconfiguredPlugin_Revert() (gas: 39888) MultiOCR3Base_transmit:test_ZeroSignatures_Revert() (gas: 32971) -MultiOnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 411753) -MultiRampsE2E:test_E2E_3MessagesMMultiOffRampSuccess_gas() (gas: 1528026) +MultiOnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 411709) +MultiRampsE2E:test_E2E_3MessagesMMultiOffRampSuccess_gas() (gas: 1527960) NonceManager_NonceIncrementation:test_getIncrementedOutboundNonce_Success() (gas: 37916) NonceManager_NonceIncrementation:test_incrementInboundNonce_Skip() (gas: 23709) NonceManager_NonceIncrementation:test_incrementInboundNonce_Success() (gas: 38799) @@ -572,10 +572,10 @@ NonceManager_OffRampUpgrade:test_UpgradedOffRampNonceSkipsIfMsgInFlight_Success( NonceManager_OffRampUpgrade:test_UpgradedSenderNoncesReadsPreviousRampTransitive_Success() (gas: 244871) NonceManager_OffRampUpgrade:test_UpgradedSenderNoncesReadsPreviousRamp_Success() (gas: 232986) NonceManager_OffRampUpgrade:test_Upgraded_Success() (gas: 152870) -NonceManager_OnRampUpgrade:test_UpgradeNonceNewSenderStartsAtZero_Success() (gas: 168380) -NonceManager_OnRampUpgrade:test_UpgradeNonceStartsAtV1Nonce_Success() (gas: 220237) +NonceManager_OnRampUpgrade:test_UpgradeNonceNewSenderStartsAtZero_Success() (gas: 168358) +NonceManager_OnRampUpgrade:test_UpgradeNonceStartsAtV1Nonce_Success() (gas: 220193) NonceManager_OnRampUpgrade:test_UpgradeSenderNoncesReadsPreviousRamp_Success() (gas: 125157) -NonceManager_OnRampUpgrade:test_Upgrade_Success() (gas: 107588) +NonceManager_OnRampUpgrade:test_Upgrade_Success() (gas: 107566) NonceManager_applyPreviousRampsUpdates:test_MultipleRampsUpdates() (gas: 122955) NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySetOffRamp_Revert() (gas: 42965) NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySetOnRampAndOffRamp_Revert() (gas: 64288) @@ -640,10 +640,10 @@ OffRamp_commit:test_ReportAndPriceUpdate_Success() (gas: 166923) OffRamp_commit:test_ReportOnlyRootSuccess_gas() (gas: 141978) OffRamp_commit:test_RootAlreadyCommitted_Revert() (gas: 142982) OffRamp_commit:test_SourceChainNotEnabled_Revert() (gas: 59250) -OffRamp_commit:test_StaleReportWithRoot_Success() (gas: 240109) +OffRamp_commit:test_StaleReportWithRoot_Success() (gas: 240065) OffRamp_commit:test_UnauthorizedTransmitter_Revert() (gas: 122475) OffRamp_commit:test_Unhealthy_Revert() (gas: 57991) -OffRamp_commit:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 212415) +OffRamp_commit:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 212393) OffRamp_commit:test_ZeroEpochAndRound_Revert() (gas: 51324) OffRamp_constructor:test_Constructor_Success() (gas: 6038780) OffRamp_constructor:test_SourceChainSelector_Revert() (gas: 136917) @@ -739,7 +739,7 @@ OffRamp_trialExecute:test_RateLimitError_Success() (gas: 225885) OffRamp_trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 234506) OffRamp_trialExecute:test_TokenPoolIsNotAContract_Success() (gas: 309185) OffRamp_trialExecute:test_trialExecute_Success() (gas: 284141) -OnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 390954) +OnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 390910) OnRamp_applyAllowListUpdates:test_applyAllowListUpdates_InvalidAllowListRequestDisabledAllowListWithAdds() (gas: 17746) OnRamp_applyAllowListUpdates:test_applyAllowListUpdates_Revert() (gas: 66535) OnRamp_applyAllowListUpdates:test_applyAllowListUpdates_Success() (gas: 323600) @@ -750,32 +750,32 @@ OnRamp_constructor:test_Constructor_InvalidConfigNonceManagerEqAddressZero_Rever OnRamp_constructor:test_Constructor_InvalidConfigRMNProxyEqAddressZero_Revert() (gas: 97791) OnRamp_constructor:test_Constructor_InvalidConfigTokenAdminRegistryEqAddressZero_Revert() (gas: 92823) OnRamp_constructor:test_Constructor_Success() (gas: 2827622) -OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() (gas: 114961) -OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2_Success() (gas: 145732) -OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessCustomExtraArgs() (gas: 145335) -OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessEmptyExtraArgs() (gas: 143560) -OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessLegacyExtraArgs() (gas: 145560) -OnRamp_forwardFromRouter:test_ForwardFromRouter_Success() (gas: 144939) -OnRamp_forwardFromRouter:test_ForwardFromRouter_Success_ConfigurableSourceRouter() (gas: 140265) -OnRamp_forwardFromRouter:test_InvalidExtraArgsTag_Revert() (gas: 28846) +OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() (gas: 114939) +OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2_Success() (gas: 145710) +OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessCustomExtraArgs() (gas: 145313) +OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessEmptyExtraArgs() (gas: 143538) +OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessLegacyExtraArgs() (gas: 145538) +OnRamp_forwardFromRouter:test_ForwardFromRouter_Success() (gas: 144917) +OnRamp_forwardFromRouter:test_ForwardFromRouter_Success_ConfigurableSourceRouter() (gas: 140243) +OnRamp_forwardFromRouter:test_InvalidExtraArgsTag_Revert() (gas: 28824) OnRamp_forwardFromRouter:test_MessageValidationError_Revert() (gas: 138926) -OnRamp_forwardFromRouter:test_MesssageFeeTooHigh_Revert() (gas: 26946) -OnRamp_forwardFromRouter:test_MultiCannotSendZeroTokens_Revert() (gas: 74161) +OnRamp_forwardFromRouter:test_MesssageFeeTooHigh_Revert() (gas: 26924) +OnRamp_forwardFromRouter:test_MultiCannotSendZeroTokens_Revert() (gas: 74139) OnRamp_forwardFromRouter:test_OriginalSender_Revert() (gas: 12951) OnRamp_forwardFromRouter:test_Paused_Revert() (gas: 37326) OnRamp_forwardFromRouter:test_Permissions_Revert() (gas: 18278) -OnRamp_forwardFromRouter:test_ShouldIncrementNonceOnlyOnOrdered_Success() (gas: 184628) -OnRamp_forwardFromRouter:test_ShouldIncrementSeqNumAndNonce_Success() (gas: 210946) -OnRamp_forwardFromRouter:test_ShouldStoreLinkFees() (gas: 124860) -OnRamp_forwardFromRouter:test_ShouldStoreNonLinkFees() (gas: 146277) -OnRamp_forwardFromRouter:test_SourceTokenDataTooLarge_Revert() (gas: 3829399) +OnRamp_forwardFromRouter:test_ShouldIncrementNonceOnlyOnOrdered_Success() (gas: 184562) +OnRamp_forwardFromRouter:test_ShouldIncrementSeqNumAndNonce_Success() (gas: 210880) +OnRamp_forwardFromRouter:test_ShouldStoreLinkFees() (gas: 124838) +OnRamp_forwardFromRouter:test_ShouldStoreNonLinkFees() (gas: 146211) +OnRamp_forwardFromRouter:test_SourceTokenDataTooLarge_Revert() (gas: 3829289) OnRamp_forwardFromRouter:test_UnAllowedOriginalSender_Revert() (gas: 18714) -OnRamp_forwardFromRouter:test_UnsupportedToken_Revert() (gas: 110929) -OnRamp_forwardFromRouter:test_forwardFromRouter_UnsupportedToken_Revert() (gas: 76251) -OnRamp_forwardFromRouter:test_forwardFromRouter_WithValidation_Success() (gas: 281193) +OnRamp_forwardFromRouter:test_UnsupportedToken_Revert() (gas: 110907) +OnRamp_forwardFromRouter:test_forwardFromRouter_UnsupportedToken_Revert() (gas: 76229) +OnRamp_forwardFromRouter:test_forwardFromRouter_WithValidation_Success() (gas: 281171) OnRamp_getFee:test_EmptyMessage_Success() (gas: 102470) OnRamp_getFee:test_EnforceOutOfOrder_Revert() (gas: 66390) -OnRamp_getFee:test_GetFeeOfZeroForTokenMessage_Success() (gas: 87773) +OnRamp_getFee:test_GetFeeOfZeroForTokenMessage_Success() (gas: 87796) OnRamp_getFee:test_NotAFeeTokenButPricedToken_Revert() (gas: 34972) OnRamp_getFee:test_SingleTokenMessage_Success() (gas: 117839) OnRamp_getFee:test_Unhealthy_Revert() (gas: 17009) @@ -786,7 +786,7 @@ OnRamp_setDynamicConfig:test_SetConfigInvalidConfigFeeQuoterEqAddressZero_Revert OnRamp_setDynamicConfig:test_SetConfigInvalidConfig_Revert() (gas: 11377) OnRamp_setDynamicConfig:test_SetConfigOnlyOwner_Revert() (gas: 16409) OnRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 55330) -OnRamp_withdrawFeeTokens:test_WithdrawFeeTokens_Success() (gas: 97191) +OnRamp_withdrawFeeTokens:test_WithdrawFeeTokens_Success() (gas: 97235) PingPong_ccipReceive:test_CcipReceive_Success() (gas: 152765) PingPong_plumbing:test_OutOfOrderExecution_Success() (gas: 20280) PingPong_plumbing:test_Pausing_Success() (gas: 17780) diff --git a/contracts/src/v0.8/ccip/FeeQuoter.sol b/contracts/src/v0.8/ccip/FeeQuoter.sol index 957d146f45..aa6399d544 100644 --- a/contracts/src/v0.8/ccip/FeeQuoter.sol +++ b/contracts/src/v0.8/ccip/FeeQuoter.sol @@ -58,7 +58,7 @@ contract FeeQuoter is AuthorizedCallers, IFeeQuoter, ITypeAndVersion, IReceiver, event DestChainConfigUpdated(uint64 indexed destChainSelector, DestChainConfig destChainConfig); event DestChainAdded(uint64 indexed destChainSelector, DestChainConfig destChainConfig); - /// @notice Token price data feed update + /// @dev Token price data feed update struct TokenPriceFeedUpdate { address sourceToken; // Source token to update feed for IFeeQuoter.TokenPriceFeedConfig feedConfig; // Feed config update data @@ -73,7 +73,7 @@ contract FeeQuoter is AuthorizedCallers, IFeeQuoter, ITypeAndVersion, IReceiver, uint32 stalenessThreshold; // The amount of time a gas price can be stale before it is considered invalid. } - /// @notice The struct representing the received CCIP feed report from keystone IReceiver.onReport() + /// @dev The struct representing the received CCIP feed report from keystone IReceiver.onReport() struct ReceivedCCIPFeedReport { address token; // Token address uint224 price; // ─────────╮ Price of the token in USD with 18 decimals @@ -151,6 +151,11 @@ contract FeeQuoter is AuthorizedCallers, IFeeQuoter, ITypeAndVersion, IReceiver, uint64 premiumMultiplierWeiPerEth; // ──╯ Multiplier for destination chain specific premiums. } + /// @dev The base decimals for cost calculations + uint256 public constant FEE_BASE_DECIMALS = 36; + /// @dev The decimals that Keystone reports prices in + uint256 public constant KEYSTONE_PRICE_DECIMALS = 18; + string public constant override typeAndVersion = "FeeQuoter 1.6.0-dev"; /// @dev The gas price per unit of gas for a given destination chain, in USD with 18 decimals. @@ -175,13 +180,13 @@ contract FeeQuoter is AuthorizedCallers, IFeeQuoter, ITypeAndVersion, IReceiver, mapping(address token => IFeeQuoter.TokenPriceFeedConfig dataFeedAddress) private s_usdPriceFeedsPerToken; /// @dev The multiplier for destination chain specific premiums that can be set by the owner or fee admin - mapping(address token => uint64 premiumMultiplierWeiPerEth) internal s_premiumMultiplierWeiPerEth; + mapping(address token => uint64 premiumMultiplierWeiPerEth) private s_premiumMultiplierWeiPerEth; /// @dev The destination chain specific fee configs mapping(uint64 destChainSelector => DestChainConfig destChainConfig) internal s_destChainConfigs; /// @dev The token transfer fee config that can be set by the owner or fee admin - mapping(uint64 destChainSelector => mapping(address token => TokenTransferFeeConfig tranferFeeConfig)) internal + mapping(uint64 destChainSelector => mapping(address token => TokenTransferFeeConfig tranferFeeConfig)) private s_tokenTransferFeeConfig; /// @dev Maximum fee that can be charged for a message. This is a guard to prevent massively overcharging due to misconfiguation. @@ -530,7 +535,7 @@ contract FeeQuoter is AuthorizedCallers, IFeeQuoter, ITypeAndVersion, IReceiver, _applyPremiumMultiplierWeiPerEthUpdates(premiumMultiplierWeiPerEthArgs); } - /// @dev Set the fee config. + /// @dev Sets the fee config. /// @param premiumMultiplierWeiPerEthArgs The multiplier for destination chain specific premiums. function _applyPremiumMultiplierWeiPerEthUpdates( PremiumMultiplierWeiPerEthArgs[] memory premiumMultiplierWeiPerEthArgs @@ -646,10 +651,10 @@ contract FeeQuoter is AuthorizedCallers, IFeeQuoter, ITypeAndVersion, IReceiver, uint8 excessDecimals = dataFeedDecimal + tokenDecimal; uint256 rebasedVal; - if (excessDecimals > 36) { - rebasedVal = feedValue / (10 ** (excessDecimals - 36)); + if (excessDecimals > FEE_BASE_DECIMALS) { + rebasedVal = feedValue / (10 ** (excessDecimals - FEE_BASE_DECIMALS)); } else { - rebasedVal = feedValue * (10 ** (36 - excessDecimals)); + rebasedVal = feedValue * (10 ** (FEE_BASE_DECIMALS - excessDecimals)); } if (rebasedVal > type(uint224).max) { diff --git a/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol b/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol index 1fbfd22d1c..3935d6fab9 100644 --- a/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol +++ b/contracts/src/v0.8/ccip/MultiAggregateRateLimiter.sol @@ -59,14 +59,14 @@ contract MultiAggregateRateLimiter is IMessageInterceptor, AuthorizedCallers, IT /// @dev Tokens that should be included in Aggregate Rate Limiting (from local chain (this chain) -> remote), /// grouped per-remote chain. - mapping(uint64 remoteChainSelector => EnumerableMapAddresses.AddressToBytesMap tokensLocalToRemote) internal + mapping(uint64 remoteChainSelector => EnumerableMapAddresses.AddressToBytesMap tokensLocalToRemote) private s_rateLimitedTokensLocalToRemote; /// @notice The address of the FeeQuoter used to query token values for ratelimiting. address internal s_feeQuoter; /// @notice Rate limiter token bucket states per chain, with separate buckets for inbound and outbound lanes. - mapping(uint64 remoteChainSelector => RateLimiterBuckets buckets) internal s_rateLimitersByChainSelector; + mapping(uint64 remoteChainSelector => RateLimiterBuckets buckets) private s_rateLimitersByChainSelector; /// @param feeQuoter the fee quoter to set. /// @param authorizedCallers the authorized callers to set. diff --git a/contracts/src/v0.8/ccip/NonceManager.sol b/contracts/src/v0.8/ccip/NonceManager.sol index 38212e1d5f..5932e88b9c 100644 --- a/contracts/src/v0.8/ccip/NonceManager.sol +++ b/contracts/src/v0.8/ccip/NonceManager.sol @@ -129,7 +129,9 @@ contract NonceManager is INonceManager, AuthorizedCallers, ITypeAndVersion { PreviousRamps storage prevRamps = s_previousRamps[previousRampsArg.remoteChainSelector]; - // If the previous ramps are already set then they should not be updated + // If the previous ramps are already set then they should not be updated. + // In versions prior to the introduction of the NonceManager contract, nonces were tracked in the on/off ramps. + // This config does a 1-time migration to move the nonce from on/off ramps into NonceManager if (prevRamps.prevOnRamp != address(0) || prevRamps.prevOffRamp != address(0)) { revert PreviousRampAlreadySet(); } diff --git a/contracts/src/v0.8/ccip/capability/CCIPConfig.sol b/contracts/src/v0.8/ccip/capability/CCIPConfig.sol index 84feb2a061..10f5e6706f 100644 --- a/contracts/src/v0.8/ccip/capability/CCIPConfig.sol +++ b/contracts/src/v0.8/ccip/capability/CCIPConfig.sol @@ -51,10 +51,12 @@ contract CCIPConfig is ITypeAndVersion, ICapabilityConfiguration, OwnerIsCreator error WrongConfigDigestBlueGreen(bytes32 got, bytes32 expected); error ZeroAddressNotAllowed(); - /// @notice Type and version override. + event ConfigSet(uint32 indexed donId, uint8 indexed pluginType, CCIPConfigTypes.OCR3ConfigWithMeta[] config); + + /// @dev Type and version override. string public constant override typeAndVersion = "CCIPConfig 1.6.0-dev"; - /// @notice The canonical capabilities registry address. + /// @dev The canonical capabilities registry address. address internal immutable i_capabilitiesRegistry; uint8 internal constant MAX_OCR3_CONFIGS_PER_PLUGIN = 2; @@ -66,18 +68,18 @@ contract CCIPConfig is ITypeAndVersion, ICapabilityConfiguration, OwnerIsCreator /// @dev 256 is the hard limit due to the bit encoding of their indexes into a uint256. uint256 internal constant MAX_NUM_ORACLES = 256; - /// @notice chain configuration for each chain that CCIP is deployed on. - mapping(uint64 chainSelector => CCIPConfigTypes.ChainConfig chainConfig) internal s_chainConfigurations; + /// @dev chain configuration for each chain that CCIP is deployed on. + mapping(uint64 chainSelector => CCIPConfigTypes.ChainConfig chainConfig) private s_chainConfigurations; - /// @notice All chains that are configured. - EnumerableSet.UintSet internal s_remoteChainSelectors; + /// @dev All chains that are configured. + EnumerableSet.UintSet private s_remoteChainSelectors; - /// @notice OCR3 configurations for each DON. + /// @dev OCR3 configurations for each DON. /// Each CR DON will have a commit and execution configuration. /// This means that a DON can have up to 4 configurations, since we are implementing blue/green deployments. mapping( uint32 donId => mapping(Internal.OCRPluginType pluginType => CCIPConfigTypes.OCR3ConfigWithMeta[] ocr3Configs) - ) internal s_ocr3Configs; + ) private s_ocr3Configs; /// @param capabilitiesRegistry the canonical capabilities registry address. constructor(address capabilitiesRegistry) { @@ -213,6 +215,8 @@ contract CCIPConfig is ITypeAndVersion, ICapabilityConfiguration, OwnerIsCreator for (uint256 i = 0; i < newConfigWithMeta.length; ++i) { s_ocr3Configs[donId][pluginType].push(newConfigWithMeta[i]); } + + emit ConfigSet(donId, uint8(pluginType), newConfigWithMeta); } // ================================================================ diff --git a/contracts/src/v0.8/ccip/interfaces/IFeeQuoter.sol b/contracts/src/v0.8/ccip/interfaces/IFeeQuoter.sol index fdea4538b6..f8fb1969de 100644 --- a/contracts/src/v0.8/ccip/interfaces/IFeeQuoter.sol +++ b/contracts/src/v0.8/ccip/interfaces/IFeeQuoter.sol @@ -6,7 +6,7 @@ import {Internal} from "../libraries/Internal.sol"; import {IPriceRegistry} from "./IPriceRegistry.sol"; interface IFeeQuoter is IPriceRegistry { - /// @notice Token price data feed configuration + /// @dev Token price data feed configuration struct TokenPriceFeedConfig { address dataFeedAddress; // ──╮ AggregatorV3Interface contract (0 - feed is unset) uint8 tokenDecimals; // ──────╯ Decimals of the token that the feed represents diff --git a/contracts/src/v0.8/ccip/offRamp/OffRamp.sol b/contracts/src/v0.8/ccip/offRamp/OffRamp.sol index 6897ba5751..9270214727 100644 --- a/contracts/src/v0.8/ccip/offRamp/OffRamp.sol +++ b/contracts/src/v0.8/ccip/offRamp/OffRamp.sol @@ -83,7 +83,7 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { event RootRemoved(bytes32 root); event SkippedReportExecution(uint64 sourceChainSelector); - /// @notice Struct that contains the static configuration + /// @dev Struct that contains the static configuration /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers. /// @dev not sure why solhint complains about this, seems like a buggy detector /// https://github.com/protofire/solhint/issues/597 @@ -95,7 +95,7 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { address nonceManager; // Nonce manager address } - /// @notice Per-chain source config (defining a lane from a Source Chain -> Dest OffRamp) + /// @dev Per-chain source config (defining a lane from a Source Chain -> Dest OffRamp) struct SourceChainConfig { IRouter router; // ──────────╮ Local router to use for messages coming from this source chain bool isEnabled; // | Flag whether the source chain is enabled or not @@ -103,7 +103,7 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { bytes onRamp; // OnRamp address on the source chain } - /// @notice Same as SourceChainConfig but with source chain selector so that an array of these + /// @dev Same as SourceChainConfig but with source chain selector so that an array of these /// can be passed in the constructor and the applySourceChainConfigUpdates function. struct SourceChainConfigArgs { IRouter router; // ────────────────╮ Local router to use for messages coming from this source chain @@ -112,7 +112,7 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { bytes onRamp; // OnRamp address on the source chain } - /// @notice Dynamic offRamp config + /// @dev Dynamic offRamp config /// @dev Since DynamicConfig is part of DynamicConfigSet event, if changing it, we should update the ABI on Atlas struct DynamicConfig { address feeQuoter; // ──────────────────────────────╮ FeeQuoter address on the local chain @@ -122,7 +122,7 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { address messageValidator; // Optional message validator to validate incoming messages (zero address = no validator) } - /// @notice Report that is committed by the observing DON at the committing phase + /// @dev Report that is committed by the observing DON at the committing phase /// @dev RMN depends on this struct, if changing, please notify the RMN maintainers. struct CommitReport { Internal.PriceUpdates priceUpdates; // Collection of gas and price updates to commit @@ -146,7 +146,7 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { /// @notice SourceChainConfig per chain /// (forms lane configurations from sourceChainSelector => StaticConfig.chainSelector) - mapping(uint64 sourceChainSelector => SourceChainConfig sourceChainConfig) internal s_sourceChainConfigs; + mapping(uint64 sourceChainSelector => SourceChainConfig sourceChainConfig) private s_sourceChainConfigs; // STATE /// @dev A mapping of sequence numbers (per source chain) to execution state using a bitmap with each execution diff --git a/contracts/src/v0.8/ccip/onRamp/OnRamp.sol b/contracts/src/v0.8/ccip/onRamp/OnRamp.sol index 10036557ef..a454293eb6 100644 --- a/contracts/src/v0.8/ccip/onRamp/OnRamp.sol +++ b/contracts/src/v0.8/ccip/onRamp/OnRamp.sol @@ -108,20 +108,20 @@ contract OnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCreator { // STATIC CONFIG string public constant override typeAndVersion = "OnRamp 1.6.0-dev"; /// @dev The chain ID of the source chain that this contract is deployed to - uint64 internal immutable i_chainSelector; + uint64 private immutable i_chainSelector; /// @dev The rmn contract - IRMNV2 internal immutable i_rmn; + IRMNV2 private immutable i_rmn; /// @dev The address of the nonce manager - address internal immutable i_nonceManager; + address private immutable i_nonceManager; /// @dev The address of the token admin registry - address internal immutable i_tokenAdminRegistry; + address private immutable i_tokenAdminRegistry; // DYNAMIC CONFIG /// @dev The dynamic config for the onRamp - DynamicConfig internal s_dynamicConfig; + DynamicConfig private s_dynamicConfig; /// @dev The destination chain specific configs - mapping(uint64 destChainSelector => DestChainConfig destChainConfig) internal s_destChainConfigs; + mapping(uint64 destChainSelector => DestChainConfig destChainConfig) private s_destChainConfigs; constructor( StaticConfig memory staticConfig, diff --git a/contracts/src/v0.8/ccip/test/capability/CCIPConfig.t.sol b/contracts/src/v0.8/ccip/test/capability/CCIPConfig.t.sol index 0ec50914bf..384528eeeb 100644 --- a/contracts/src/v0.8/ccip/test/capability/CCIPConfig.t.sol +++ b/contracts/src/v0.8/ccip/test/capability/CCIPConfig.t.sol @@ -100,6 +100,41 @@ contract CCIPConfigSetup is Test { return (p2pIds, signers, transmitters); } + function _assertOCR3ConfigWithMetaEqual( + CCIPConfigTypes.OCR3ConfigWithMeta[] memory a, + CCIPConfigTypes.OCR3ConfigWithMeta[] memory b + ) internal pure { + assertEq(a.length, b.length, "OCR3ConfigWithMeta lengths do no match"); + for (uint256 i = 0; i < a.length; ++i) { + _assertOCR3ConfigEqual(a[i].config, b[i].config); + assertEq(a[i].configCount, b[i].configCount, "configCount must match"); + assertEq(a[i].configDigest, b[i].configDigest, "configDigest must match"); + } + } + + function _assertOCR3ConfigEqual( + CCIPConfigTypes.OCR3Config memory a, + CCIPConfigTypes.OCR3Config memory b + ) internal pure { + assertEq(uint8(a.pluginType), uint8(b.pluginType), "pluginType must match"); + assertEq(a.chainSelector, b.chainSelector, "chainSelector must match"); + assertEq(a.F, b.F, "F must match"); + assertEq(a.offchainConfigVersion, b.offchainConfigVersion, "offchainConfigVersion must match"); + assertEq(a.offrampAddress, b.offrampAddress, "offrampAddress must match"); + assertEq(a.p2pIds.length, b.p2pIds.length, "p2pIds length must match"); + assertEq(a.offchainConfig, b.offchainConfig, "offchainConfig must match"); + + for (uint256 i = 0; i < a.p2pIds.length; ++i) { + assertEq(a.p2pIds[i], b.p2pIds[i], "p2pId must match"); + } + for (uint256 i = 0; i < a.signers.length; ++i) { + assertEq(a.signers[i], b.signers[i], "signer must match"); + } + for (uint256 i = 0; i < a.transmitters.length; ++i) { + assertEq(a.transmitters[i], b.transmitters[i], "transmitter must match"); + } + } + function test_getCapabilityConfiguration_Success() public view { bytes memory capConfig = s_ccipCC.getCapabilityConfiguration(42 /* doesn't matter, not used */ ); assertEq(capConfig.length, 0, "capability config length must be 0"); @@ -1140,7 +1175,7 @@ contract CCIPConfig_ConfigStateMachine is CCIPConfigSetup { contract CCIPConfig_updatePluginConfig is CCIPConfigSetup { // Successes. - function test__updatePluginConfig_InitToRunning_Success() public { + function test_updatePluginConfig_InitToRunning_Success() public { (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); uint32 donId = 1; CCIPConfigTypes.OCR3Config memory blueConfig = CCIPConfigTypes.OCR3Config({ @@ -1157,17 +1192,25 @@ contract CCIPConfig_updatePluginConfig is CCIPConfigSetup { CCIPConfigTypes.OCR3Config[] memory configs = new CCIPConfigTypes.OCR3Config[](1); configs[0] = blueConfig; + CCIPConfigTypes.OCR3ConfigWithMeta[] memory expectedConfig = new CCIPConfigTypes.OCR3ConfigWithMeta[](1); + expectedConfig[0] = CCIPConfigTypes.OCR3ConfigWithMeta({ + config: blueConfig, + configCount: 1, + configDigest: s_ccipCC.computeConfigDigest(donId, 1, blueConfig) + }); + + vm.expectEmit(); + emit CCIPConfig.ConfigSet(donId, uint8(Internal.OCRPluginType.Commit), expectedConfig); s_ccipCC.updatePluginConfig(donId, Internal.OCRPluginType.Commit, configs); // should see the updated config in the contract state. CCIPConfigTypes.OCR3ConfigWithMeta[] memory storedConfig = s_ccipCC.getOCRConfig(donId, Internal.OCRPluginType.Commit); - assertEq(storedConfig.length, 1, "don config length must be 1"); - assertEq(storedConfig[0].configCount, uint64(1), "config count must be 1"); - assertEq(uint256(storedConfig[0].config.pluginType), uint256(blueConfig.pluginType), "plugin type must match"); + + _assertOCR3ConfigWithMetaEqual(storedConfig, expectedConfig); } - function test__updatePluginConfig_RunningToStaging_Success() public { + function test_updatePluginConfig_RunningToStaging_Success() public { (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); // add blue config. uint32 donId = 1; @@ -1202,25 +1245,31 @@ contract CCIPConfig_updatePluginConfig is CCIPConfigSetup { blueAndGreen[0] = blueConfig; blueAndGreen[1] = greenConfig; + CCIPConfigTypes.OCR3ConfigWithMeta[] memory expectedConfig = new CCIPConfigTypes.OCR3ConfigWithMeta[](2); + expectedConfig[0] = CCIPConfigTypes.OCR3ConfigWithMeta({ + config: blueConfig, + configCount: 1, + configDigest: s_ccipCC.computeConfigDigest(donId, 1, blueConfig) + }); + expectedConfig[1] = CCIPConfigTypes.OCR3ConfigWithMeta({ + config: greenConfig, + configCount: 2, + configDigest: s_ccipCC.computeConfigDigest(donId, 2, greenConfig) + }); + + vm.expectEmit(); + emit CCIPConfig.ConfigSet(donId, uint8(Internal.OCRPluginType.Commit), expectedConfig); + s_ccipCC.updatePluginConfig(donId, Internal.OCRPluginType.Commit, blueAndGreen); // should see the updated config in the contract state. CCIPConfigTypes.OCR3ConfigWithMeta[] memory storedConfig = s_ccipCC.getOCRConfig(donId, Internal.OCRPluginType.Commit); - assertEq(storedConfig.length, 2, "don config length must be 2"); - // 0 index is blue config, 1 index is green config. - assertEq(storedConfig[1].configCount, uint64(2), "config count must be 2"); - assertEq( - uint256(storedConfig[0].config.pluginType), uint256(Internal.OCRPluginType.Commit), "plugin type must match" - ); - assertEq( - uint256(storedConfig[1].config.pluginType), uint256(Internal.OCRPluginType.Commit), "plugin type must match" - ); - assertEq(storedConfig[0].config.offchainConfig, bytes("commit"), "blue offchain config must match"); - assertEq(storedConfig[1].config.offchainConfig, bytes("commit-new"), "green offchain config must match"); + + _assertOCR3ConfigWithMetaEqual(storedConfig, expectedConfig); } - function test__updatePluginConfig_StagingToRunning_Success() public { + function test_updatePluginConfig_StagingToRunning_Success() public { (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); // add blue config. uint32 donId = 1; @@ -1255,37 +1304,28 @@ contract CCIPConfig_updatePluginConfig is CCIPConfigSetup { blueAndGreen[0] = blueConfig; blueAndGreen[1] = greenConfig; + CCIPConfigTypes.OCR3ConfigWithMeta[] memory expectedConfig = new CCIPConfigTypes.OCR3ConfigWithMeta[](2); + expectedConfig[0] = CCIPConfigTypes.OCR3ConfigWithMeta({ + config: blueConfig, + configCount: 1, + configDigest: s_ccipCC.computeConfigDigest(donId, 1, blueConfig) + }); + expectedConfig[1] = CCIPConfigTypes.OCR3ConfigWithMeta({ + config: greenConfig, + configCount: 2, + configDigest: s_ccipCC.computeConfigDigest(donId, 2, greenConfig) + }); + + vm.expectEmit(); + emit CCIPConfig.ConfigSet(donId, uint8(Internal.OCRPluginType.Commit), expectedConfig); + s_ccipCC.updatePluginConfig(donId, Internal.OCRPluginType.Commit, blueAndGreen); // should see the updated config in the contract state. CCIPConfigTypes.OCR3ConfigWithMeta[] memory storedConfig = s_ccipCC.getOCRConfig(donId, Internal.OCRPluginType.Commit); - assertEq(storedConfig.length, 2, "don config length must be 2"); - // 0 index is blue config, 1 index is green config. - assertEq(storedConfig[1].configCount, uint64(2), "config count must be 2"); - assertEq( - uint256(storedConfig[0].config.pluginType), uint256(Internal.OCRPluginType.Commit), "plugin type must match" - ); - assertEq( - uint256(storedConfig[1].config.pluginType), uint256(Internal.OCRPluginType.Commit), "plugin type must match" - ); - assertEq(storedConfig[0].config.offchainConfig, bytes("commit"), "blue offchain config must match"); - assertEq(storedConfig[1].config.offchainConfig, bytes("commit-new"), "green offchain config must match"); - - // promote green to blue. - CCIPConfigTypes.OCR3Config[] memory promote = new CCIPConfigTypes.OCR3Config[](1); - promote[0] = greenConfig; - - s_ccipCC.updatePluginConfig(donId, Internal.OCRPluginType.Commit, promote); - // should see the updated config in the contract state. - storedConfig = s_ccipCC.getOCRConfig(donId, Internal.OCRPluginType.Commit); - assertEq(storedConfig.length, 1, "don config length must be 1"); - assertEq(storedConfig[0].configCount, uint64(2), "config count must be 2"); - assertEq( - uint256(storedConfig[0].config.pluginType), uint256(Internal.OCRPluginType.Commit), "plugin type must match" - ); - assertEq(storedConfig[0].config.offchainConfig, bytes("commit-new"), "green offchain config must match"); + _assertOCR3ConfigWithMetaEqual(storedConfig, expectedConfig); } // Reverts. diff --git a/core/gethwrappers/ccip/generated/ccip_config/ccip_config.go b/core/gethwrappers/ccip/generated/ccip_config/ccip_config.go index dd61552789..380819d6ac 100644 --- a/core/gethwrappers/ccip/generated/ccip_config/ccip_config.go +++ b/core/gethwrappers/ccip/generated/ccip_config/ccip_config.go @@ -60,8 +60,8 @@ type CCIPConfigTypesOCR3ConfigWithMeta struct { } var CCIPConfigMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"capabilitiesRegistry\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainSelectorNotFound\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ChainSelectorNotSet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FChainMustBePositive\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FMustBePositive\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FTooHigh\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"length\",\"type\":\"uint256\"}],\"name\":\"InvalidConfigLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enumCCIPConfigTypes.ConfigState\",\"name\":\"currentState\",\"type\":\"uint8\"},{\"internalType\":\"enumCCIPConfigTypes.ConfigState\",\"name\":\"proposedState\",\"type\":\"uint8\"}],\"name\":\"InvalidConfigStateTransition\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidPluginType\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"}],\"name\":\"NodeNotInRegistry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonExistentConfigTransition\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"got\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minimum\",\"type\":\"uint256\"}],\"name\":\"NotEnoughTransmitters\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OfframpAddressCannotBeZero\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCapabilitiesRegistryCanCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"p2pIdsLength\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"signersLength\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"transmittersLength\",\"type\":\"uint256\"}],\"name\":\"P2PIdsLengthNotMatching\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManyOCR3Configs\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManySigners\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"got\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"expected\",\"type\":\"uint64\"}],\"name\":\"WrongConfigCount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"got\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"}],\"name\":\"WrongConfigDigest\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"got\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"}],\"name\":\"WrongConfigDigestBlueGreen\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"CapabilityConfigurationSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainConfigRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes32[]\",\"name\":\"readers\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint8\",\"name\":\"fChain\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"structCCIPConfigTypes.ChainConfig\",\"name\":\"chainConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"chainSelectorRemoves\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes32[]\",\"name\":\"readers\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint8\",\"name\":\"fChain\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPConfigTypes.ChainConfig\",\"name\":\"chainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structCCIPConfigTypes.ChainConfigInfo[]\",\"name\":\"chainConfigAdds\",\"type\":\"tuple[]\"}],\"name\":\"applyChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"}],\"name\":\"beforeCapabilityConfigSet\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"pageIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pageSize\",\"type\":\"uint256\"}],\"name\":\"getAllChainConfigs\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes32[]\",\"name\":\"readers\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint8\",\"name\":\"fChain\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPConfigTypes.ChainConfig\",\"name\":\"chainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structCCIPConfigTypes.ChainConfigInfo[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"name\":\"getCapabilityConfiguration\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"configuration\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCapabilityRegistry\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNumChainConfigurations\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"}],\"name\":\"getOCRConfig\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offrampAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"p2pIds\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes[]\",\"name\":\"signers\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes[]\",\"name\":\"transmitters\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPConfigTypes.OCR3Config\",\"name\":\"config\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"configCount\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"internalType\":\"structCCIPConfigTypes.OCR3ConfigWithMeta[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x60a06040523480156200001157600080fd5b50604051620040b3380380620040b38339810160408190526200003491620001a6565b33806000816200008b5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000be57620000be81620000fb565b5050506001600160a01b038116620000e9576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b0316608052620001d8565b336001600160a01b03821603620001555760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000082565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600060208284031215620001b957600080fd5b81516001600160a01b0381168114620001d157600080fd5b9392505050565b608051613eb1620002026000396000818161010301528181610ed901526111490152613eb16000f3fe608060405234801561001057600080fd5b50600436106100d45760003560e01c80638318ed5d11610081578063f2fde38b1161005b578063f2fde38b14610230578063f442c89a14610243578063fba64a7c1461025657600080fd5b80638318ed5d146101d15780638da5cb5b146101f2578063b74b23561461021057600080fd5b80634bd0473f116100b25780634bd0473f1461019157806379ba5097146101b15780637ac0d41e146101bb57600080fd5b806301ffc9a7146100d9578063020330e614610101578063181f5a7714610148575b600080fd5b6100ec6100e7366004612cef565b610269565b60405190151581526020015b60405180910390f35b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100f8565b6101846040518060400160405280601481526020017f43434950436f6e66696720312e362e302d64657600000000000000000000000081525081565b6040516100f89190612d95565b6101a461019f366004612dd9565b610302565b6040516100f89190612ef8565b6101b961077a565b005b6101c361087c565b6040519081526020016100f8565b6101846101df3660046130b4565b5060408051602081019091526000815290565b60005473ffffffffffffffffffffffffffffffffffffffff16610123565b61022361021e3660046130d1565b61088d565b6040516100f89190613137565b6101b961023e3660046131c7565b610b0e565b6101b9610251366004613249565b610b22565b6101b96102643660046132cd565b610ec1565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f78bea7210000000000000000000000000000000000000000000000000000000014806102fc57507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b63ffffffff8216600090815260056020526040812060609183600181111561032c5761032c612e0e565b600181111561033d5761033d612e0e565b8152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b8282101561076e57600084815260209020604080516101808101909152600884029091018054829060608201908390829060ff1660018111156103b0576103b0612e0e565b60018111156103c1576103c1612e0e565b8152815467ffffffffffffffff61010082048116602084015260ff690100000000000000000083041660408401526a01000000000000000000009091041660608201526001820180546080909201916104199061338a565b80601f01602080910402602001604051908101604052809291908181526020018280546104459061338a565b80156104925780601f1061046757610100808354040283529160200191610492565b820191906000526020600020905b81548152906001019060200180831161047557829003601f168201915b50505050508152602001600282018054806020026020016040519081016040528092919081815260200182805480156104ea57602002820191906000526020600020905b8154815260200190600101908083116104d6575b5050505050815260200160038201805480602002602001604051908101604052809291908181526020016000905b828210156105c45783829060005260206000200180546105379061338a565b80601f01602080910402602001604051908101604052809291908181526020018280546105639061338a565b80156105b05780601f10610585576101008083540402835291602001916105b0565b820191906000526020600020905b81548152906001019060200180831161059357829003601f168201915b505050505081526020019060010190610518565b50505050815260200160048201805480602002602001604051908101604052809291908181526020016000905b8282101561069d5783829060005260206000200180546106109061338a565b80601f016020809104026020016040519081016040528092919081815260200182805461063c9061338a565b80156106895780601f1061065e57610100808354040283529160200191610689565b820191906000526020600020905b81548152906001019060200180831161066c57829003601f168201915b5050505050815260200190600101906105f1565b5050505081526020016005820180546106b59061338a565b80601f01602080910402602001604051908101604052809291908181526020018280546106e19061338a565b801561072e5780601f106107035761010080835404028352916020019161072e565b820191906000526020600020905b81548152906001019060200180831161071157829003601f168201915b505050919092525050508152600682015467ffffffffffffffff16602080830191909152600790920154604090910152908252600192909201910161036b565b50505050905092915050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610800576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b60006108886003610f7c565b905090565b6060600061089b6003610f7c565b905060006108a9848661340c565b90508315806108b85750818110155b156108f85760408051600080825260208201909252906108ee565b6108db612a8e565b8152602001906001900390816108d35790505b50925050506102fc565b60006109048583613452565b9050828111156109115750815b600061091d8383613465565b67ffffffffffffffff81111561093557610935613423565b60405190808252806020026020018201604052801561096e57816020015b61095b612a8e565b8152602001906001900390816109535790505b509050600061097d6003610f86565b9050835b83811015610b0157600082828151811061099d5761099d613478565b60209081029190910181015160408051808201825267ffffffffffffffff831680825260009081526002855282902082518154608081880283018101909552606082018181529597509295860194909391928492849190840182828015610a2357602002820191906000526020600020905b815481526020019060010190808311610a0f575b5050509183525050600182015460ff166020820152600282018054604090920191610a4d9061338a565b80601f0160208091040260200160405190810160405280929190818152602001828054610a799061338a565b8015610ac65780601f10610a9b57610100808354040283529160200191610ac6565b820191906000526020600020905b815481529060010190602001808311610aa957829003601f168201915b50505091909252505050905284610add8885613465565b81518110610aed57610aed613478565b602090810291909101015250600101610981565b5090979650505050505050565b610b16610f9a565b610b1f8161101d565b50565b610b2a610f9a565b60005b83811015610d1057610b71858583818110610b4a57610b4a613478565b9050602002016020810190610b5f91906134a7565b60039067ffffffffffffffff16611112565b610bdb57848482818110610b8757610b87613478565b9050602002016020810190610b9c91906134a7565b6040517f1bd4d2d200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016107f7565b60026000868684818110610bf157610bf1613478565b9050602002016020810190610c0691906134a7565b67ffffffffffffffff1681526020810191909152604001600090812090610c2d8282612ad6565b6001820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055610c65600283016000612af4565b5050610ca3858583818110610c7c57610c7c613478565b9050602002016020810190610c9191906134a7565b60039067ffffffffffffffff1661112a565b507f2a680691fef3b2d105196805935232c661ce703e92d464ef0b94a7bc62d714f0858583818110610cd757610cd7613478565b9050602002016020810190610cec91906134a7565b60405167ffffffffffffffff909116815260200160405180910390a1600101610b2d565b5060005b81811015610eba576000838383818110610d3057610d30613478565b9050602002810190610d4291906134c2565b610d50906020810190613500565b610d5990613702565b90506000848484818110610d6f57610d6f613478565b9050602002810190610d8191906134c2565b610d8f9060208101906134a7565b9050610d9e8260000151611136565b816020015160ff16600003610ddf576040517fa9b3766e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff81166000908152600260209081526040909120835180518593610e0f928492910190612b2e565b5060208201516001820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff90921691909117905560408201516002820190610e5c90826137e9565b50610e7691506003905067ffffffffffffffff8316611282565b507f05dd57854af2c291a94ea52e7c43d80bc3be7fa73022f98b735dea86642fa5e08183604051610ea8929190613903565b60405180910390a15050600101610d14565b5050505050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610f30576040517fac7a7efd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080610f47610f42868801886139ae565b61128e565b8151919350915015610f5f57610f5f836000846114d9565b805115610f7257610f72836001836114d9565b5050505050505050565b60006102fc825490565b60606000610f9383611c3b565b9392505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461101b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016107f7565b565b3373ffffffffffffffffffffffffffffffffffffffff82160361109c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016107f7565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60008181526001830160205260408120541515610f93565b6000610f938383611c97565b60005b815181101561127e5760008019167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166350c946fe84848151811061119557611195613478565b60200260200101516040518263ffffffff1660e01b81526004016111bb91815260200190565b600060405180830381865afa1580156111d8573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261121e9190810190613bf9565b60800151036112765781818151811061123957611239613478565b60200260200101516040517f8907a4fa0000000000000000000000000000000000000000000000000000000081526004016107f791815260200190565b600101611139565b5050565b6000610f938383611d91565b606080600460ff16835111156112d0576040517f8854586400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160028082526060820190925290816020015b61134d6040805161012081019091528060008152602001600067ffffffffffffffff168152602001600060ff168152602001600067ffffffffffffffff16815260200160608152602001606081526020016060815260200160608152602001606081525090565b8152602001906001900390816112e657505060408051600280825260608201909252919350602082015b6113de6040805161012081019091528060008152602001600067ffffffffffffffff168152602001600060ff168152602001600067ffffffffffffffff16815260200160608152602001606081526020016060815260200160608152602001606081525090565b81526020019060019003908161137757905050905060008060005b85518110156114cc57600086828151811061141657611416613478565b602002602001015160000151600181111561143357611433612e0e565b036114805785818151811061144a5761144a613478565b602002602001015185848151811061146457611464613478565b60200260200101819052508261147990613cd1565b92506114c4565b85818151811061149257611492613478565b60200260200101518483815181106114ac576114ac613478565b6020026020010181905250816114c190613cd1565b91505b6001016113f9565b5090835281529092909150565b63ffffffff831660009081526005602052604081208184600181111561150157611501612e0e565b600181111561151257611512612e0e565b8152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b8282101561194357600084815260209020604080516101808101909152600884029091018054829060608201908390829060ff16600181111561158557611585612e0e565b600181111561159657611596612e0e565b8152815467ffffffffffffffff61010082048116602084015260ff690100000000000000000083041660408401526a01000000000000000000009091041660608201526001820180546080909201916115ee9061338a565b80601f016020809104026020016040519081016040528092919081815260200182805461161a9061338a565b80156116675780601f1061163c57610100808354040283529160200191611667565b820191906000526020600020905b81548152906001019060200180831161164a57829003601f168201915b50505050508152602001600282018054806020026020016040519081016040528092919081815260200182805480156116bf57602002820191906000526020600020905b8154815260200190600101908083116116ab575b5050505050815260200160038201805480602002602001604051908101604052809291908181526020016000905b8282101561179957838290600052602060002001805461170c9061338a565b80601f01602080910402602001604051908101604052809291908181526020018280546117389061338a565b80156117855780601f1061175a57610100808354040283529160200191611785565b820191906000526020600020905b81548152906001019060200180831161176857829003601f168201915b5050505050815260200190600101906116ed565b50505050815260200160048201805480602002602001604051908101604052809291908181526020016000905b828210156118725783829060005260206000200180546117e59061338a565b80601f01602080910402602001604051908101604052809291908181526020018280546118119061338a565b801561185e5780601f106118335761010080835404028352916020019161185e565b820191906000526020600020905b81548152906001019060200180831161184157829003601f168201915b5050505050815260200190600101906117c6565b50505050815260200160058201805461188a9061338a565b80601f01602080910402602001604051908101604052809291908181526020018280546118b69061338a565b80156119035780601f106118d857610100808354040283529160200191611903565b820191906000526020600020905b8154815290600101906020018083116118e657829003601f168201915b505050919092525050508152600682015467ffffffffffffffff166020808301919091526007909201546040909101529082526001929092019101611540565b50505050905060006119558251611de0565b905060006119638451611de0565b905061196f8282611e32565b600061197e8785878686611eee565b905061198a84826122d2565b63ffffffff87166000908152600560205260408120908760018111156119b2576119b2612e0e565b60018111156119c3576119c3612e0e565b815260200190815260200160002060006119dd9190612b79565b60005b8151811015610f725763ffffffff8816600090815260056020526040812090886001811115611a1157611a11612e0e565b6001811115611a2257611a22612e0e565b8152602001908152602001600020828281518110611a4257611a42613478565b6020908102919091018101518254600181810185556000948552929093208151805160089095029091018054929490939192849283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016908381811115611aac57611aac612e0e565b021790555060208201518154604084015160608501517fffffffffffffffffffffffffffffffffffffffffffff000000000000000000ff90921661010067ffffffffffffffff948516027fffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffff1617690100000000000000000060ff90921691909102177fffffffffffffffffffffffffffff0000000000000000ffffffffffffffffffff166a0100000000000000000000929091169190910217815560808201516001820190611b7b90826137e9565b5060a08201518051611b97916002840191602090910190612b2e565b5060c08201518051611bb3916003840191602090910190612b9a565b5060e08201518051611bcf916004840191602090910190612b9a565b506101008201516005820190611be590826137e9565b50505060208201516006820180547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff9092169190911790556040909101516007909101556001016119e0565b606081600001805480602002602001604051908101604052809291908181526020018280548015611c8b57602002820191906000526020600020905b815481526020019060010190808311611c77575b50505050509050919050565b60008181526001830160205260408120548015611d80576000611cbb600183613465565b8554909150600090611ccf90600190613465565b9050808214611d34576000866000018281548110611cef57611cef613478565b9060005260206000200154905080876000018481548110611d1257611d12613478565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080611d4557611d45613d09565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506102fc565b60009150506102fc565b5092915050565b6000818152600183016020526040812054611dd8575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556102fc565b5060006102fc565b60006002821115611e20576040517f3e478526000000000000000000000000000000000000000000000000000000008152600481018390526024016107f7565b8160028111156102fc576102fc612e0e565b6000826002811115611e4657611e46612e0e565b826002811115611e5857611e58612e0e565b611e629190613d38565b90508060011480611eae5750807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff148015611eae57506002836002811115611eac57611eac612e0e565b145b15611eb857505050565b82826040517f0a6b675b0000000000000000000000000000000000000000000000000000000081526004016107f7929190613d68565b60606000845167ffffffffffffffff811115611f0c57611f0c613423565b604051908082528060200260200182016040528015611f35578160200160208202803683370190505b5090506000846002811115611f4c57611f4c612e0e565b148015611f6a57506001836002811115611f6857611f68612e0e565b145b15611fab57600181600081518110611f8457611f84613478565b602002602001019067ffffffffffffffff16908167ffffffffffffffff1681525050612113565b6001846002811115611fbf57611fbf612e0e565b148015611fdd57506002836002811115611fdb57611fdb612e0e565b145b156120745785600081518110611ff557611ff5613478565b6020026020010151602001518160008151811061201457612014613478565b602002602001019067ffffffffffffffff16908167ffffffffffffffff16815250508560008151811061204957612049613478565b60200260200101516020015160016120619190613d83565b81600181518110611f8457611f84613478565b600284600281111561208857612088612e0e565b1480156120a6575060018360028111156120a4576120a4612e0e565b145b156120dd57856001815181106120be576120be613478565b60200260200101516020015181600081518110611f8457611f84613478565b83836040517f0a6b675b0000000000000000000000000000000000000000000000000000000081526004016107f7929190613d68565b6000855167ffffffffffffffff81111561212f5761212f613423565b6040519080825280602002602001820160405280156121dd57816020015b6040805161018081018252600060608083018281526080840183905260a0840183905260c0840183905260e08401829052610100840182905261012084018290526101408401829052610160840191909152825260208083018290529282015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90920191018161214d5790505b50905060005b82518110156122c65761220e87828151811061220157612201613478565b6020026020010151612651565b604051806060016040528088838151811061222b5761222b613478565b6020026020010151815260200184838151811061224a5761224a613478565b602002602001015167ffffffffffffffff16815260200161229e8b86858151811061227757612277613478565b60200260200101518b868151811061229157612291613478565b60200260200101516129c0565b8152508282815181106122b3576122b3613478565b60209081029190910101526001016121e3565b50979650505050505050565b81518151811580156122e45750806001145b1561238657826000815181106122fc576122fc613478565b60200260200101516020015167ffffffffffffffff16600114612380578260008151811061232c5761232c613478565b60209081029190910181015101516040517fc1658eb800000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152600160248201526044016107f7565b50505050565b8160011480156123965750806002145b1561254c57836000815181106123ae576123ae613478565b602002602001015160400151836000815181106123cd576123cd613478565b6020026020010151604001511461245957826000815181106123f1576123f1613478565b6020026020010151604001518460008151811061241057612410613478565b6020026020010151604001516040517fc7ccdd7f0000000000000000000000000000000000000000000000000000000081526004016107f7929190918252602082015260400190565b8360008151811061246c5761246c613478565b60200260200101516020015160016124849190613d83565b67ffffffffffffffff16836001815181106124a1576124a1613478565b60200260200101516020015167ffffffffffffffff161461238057826001815181106124cf576124cf613478565b602002602001015160200151846000815181106124ee576124ee613478565b60200260200101516020015160016125069190613d83565b6040517fc1658eb800000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9283166004820152911660248201526044016107f7565b81600214801561255c5750806001145b1561261f578360018151811061257457612574613478565b6020026020010151604001518360008151811061259357612593613478565b6020026020010151604001511461238057826000815181106125b7576125b7613478565b602002602001015160400151846001815181106125d6576125d6613478565b6020026020010151604001516040517f9e9756700000000000000000000000000000000000000000000000000000000081526004016107f7929190918252602082015260400190565b6040517f1f1b2bb600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806020015167ffffffffffffffff16600003612699576040517f698cf8e000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000815160018111156126ae576126ae612e0e565b141580156126cf57506001815160018111156126cc576126cc612e0e565b14155b15612706576040517f3302dbd700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6080810151511580612743575060408051600060208201520160405160208183030381529060405280519060200120816080015180519060200120145b1561277a576040517f358c192700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208101516127959060039067ffffffffffffffff16611112565b6127dd5760208101516040517f1bd4d2d200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016107f7565b60208082015167ffffffffffffffff1660009081526002909152604081206001015461280d9060ff166003613da4565b612818906001613dc0565b60ff169050808260e0015151101561286d5760e0820151516040517f548dd21f0000000000000000000000000000000000000000000000000000000081526004810191909152602481018290526044016107f7565b60c0820151516101008111156128af576040517f1b925da600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8260a0015151811415806128c857508260e00151518114155b156129225760a08301515160c08401515160e0850151516040517fba900f6d0000000000000000000000000000000000000000000000000000000081526004810193909352602483019190915260448201526064016107f7565b826040015160ff16600003612963576040517f39d1a4d000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040830151612973906003613da4565b60ff1681116129ae576040517f4856694e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6129bb8360a00151611136565b505050565b60008082602001518584600001518560800151878760a001518860c001518960e001518a604001518b606001518c6101000151604051602001612a0d9b9a99989796959493929190613dd9565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e0a000000000000000000000000000000000000000000000000000000000000179150509392505050565b6040518060400160405280600067ffffffffffffffff168152602001612ad1604051806060016040528060608152602001600060ff168152602001606081525090565b905290565b5080546000825590600052602060002090810190610b1f9190612bec565b508054612b009061338a565b6000825580601f10612b10575050565b601f016020900490600052602060002090810190610b1f9190612bec565b828054828255906000526020600020908101928215612b69579160200282015b82811115612b69578251825591602001919060010190612b4e565b50612b75929150612bec565b5090565b5080546000825560080290600052602060002090810190610b1f9190612c01565b828054828255906000526020600020908101928215612be0579160200282015b82811115612be05782518290612bd090826137e9565b5091602001919060010190612bba565b50612b75929150612cb4565b5b80821115612b755760008155600101612bed565b80821115612b755780547fffffffffffffffffffffffffffff00000000000000000000000000000000000016815560008181612c406001830182612af4565b612c4e600283016000612ad6565b612c5c600383016000612cd1565b612c6a600483016000612cd1565b612c78600583016000612af4565b5050506006810180547fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000016905560006007820155600801612c01565b80821115612b75576000612cc88282612af4565b50600101612cb4565b5080546000825590600052602060002090810190610b1f9190612cb4565b600060208284031215612d0157600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610f9357600080fd5b6000815180845260005b81811015612d5757602081850181015186830182015201612d3b565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000610f936020830184612d31565b63ffffffff81168114610b1f57600080fd5b8035612dc581612da8565b919050565b803560028110612dc557600080fd5b60008060408385031215612dec57600080fd5b8235612df781612da8565b9150612e0560208401612dca565b90509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60028110612e4d57612e4d612e0e565b9052565b60008151808452602080850194506020840160005b83811015612e8257815187529582019590820190600101612e66565b509495945050505050565b60008282518085526020808601955060208260051b8401016020860160005b84811015610b01577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018952612ee6838351612d31565b98840198925090830190600101612eac565b600060208083018184528085518083526040925060408601915060408160051b87010184880160005b838110156130a6577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0898403018552815160608151818652612f668287018251612e3d565b898101516080612f818189018367ffffffffffffffff169052565b8a830151915060a0612f97818a018460ff169052565b938301519360c09250612fb58984018667ffffffffffffffff169052565b818401519450610120915060e082818b0152612fd56101808b0187612d31565b95508185015191507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0610100818c890301818d01526130148885612e51565b958701518c87038301868e015295975061302e8887612e8d565b9750828701519550818c8903016101408d015261304b8887612e8d565b975080870151965050808b8803016101608c0152505050505061306e8282612d31565b9150508882015161308a8a87018267ffffffffffffffff169052565b5090870151938701939093529386019390860190600101612f21565b509098975050505050505050565b6000602082840312156130c657600080fd5b8135610f9381612da8565b600080604083850312156130e457600080fd5b50508035926020909101359150565b60008151606084526131086060850182612e51565b905060ff60208401511660208501526040830151848203604086015261312e8282612d31565b95945050505050565b600060208083018184528085518083526040925060408601915060408160051b87010184880160005b838110156130a6578883037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00185528151805167ffffffffffffffff1684528701518784018790526131b4878501826130f3565b9588019593505090860190600101613160565b6000602082840312156131d957600080fd5b813573ffffffffffffffffffffffffffffffffffffffff81168114610f9357600080fd5b60008083601f84011261320f57600080fd5b50813567ffffffffffffffff81111561322757600080fd5b6020830191508360208260051b850101111561324257600080fd5b9250929050565b6000806000806040858703121561325f57600080fd5b843567ffffffffffffffff8082111561327757600080fd5b613283888389016131fd565b9096509450602087013591508082111561329c57600080fd5b506132a9878288016131fd565b95989497509550505050565b803567ffffffffffffffff81168114612dc557600080fd5b600080600080600080608087890312156132e657600080fd5b863567ffffffffffffffff808211156132fe57600080fd5b61330a8a838b016131fd565b9098509650602089013591508082111561332357600080fd5b818901915089601f83011261333757600080fd5b81358181111561334657600080fd5b8a602082850101111561335857600080fd5b602083019650809550505050613370604088016132b5565b915061337e60608801612dba565b90509295509295509295565b600181811c9082168061339e57607f821691505b6020821081036133d7577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80820281158282048414176102fc576102fc6133dd565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b808201808211156102fc576102fc6133dd565b818103818111156102fc576102fc6133dd565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000602082840312156134b957600080fd5b610f93826132b5565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc18336030181126134f657600080fd5b9190910192915050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa18336030181126134f657600080fd5b604051610120810167ffffffffffffffff8111828210171561355857613558613423565b60405290565b60405160e0810167ffffffffffffffff8111828210171561355857613558613423565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156135c8576135c8613423565b604052919050565b600067ffffffffffffffff8211156135ea576135ea613423565b5060051b60200190565b600082601f83011261360557600080fd5b8135602061361a613615836135d0565b613581565b8083825260208201915060208460051b87010193508684111561363c57600080fd5b602086015b848110156136585780358352918301918301613641565b509695505050505050565b803560ff81168114612dc557600080fd5b600082601f83011261368557600080fd5b813567ffffffffffffffff81111561369f5761369f613423565b6136d060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601613581565b8181528460208386010111156136e557600080fd5b816020850160208301376000918101602001919091529392505050565b60006060823603121561371457600080fd5b6040516060810167ffffffffffffffff828210818311171561373857613738613423565b81604052843591508082111561374d57600080fd5b613759368387016135f4565b835261376760208601613663565b6020840152604085013591508082111561378057600080fd5b5061378d36828601613674565b60408301525092915050565b601f8211156129bb576000816000526020600020601f850160051c810160208610156137c25750805b601f850160051c820191505b818110156137e1578281556001016137ce565b505050505050565b815167ffffffffffffffff81111561380357613803613423565b61381781613811845461338a565b84613799565b602080601f83116001811461386a57600084156138345750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556137e1565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b828110156138b757888601518255948401946001909101908401613898565b50858210156138f357878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b67ffffffffffffffff8316815260406020820152600061392660408301846130f3565b949350505050565b600082601f83011261393f57600080fd5b8135602061394f613615836135d0565b82815260059290921b8401810191818101908684111561396e57600080fd5b8286015b8481101561365857803567ffffffffffffffff8111156139925760008081fd5b6139a08986838b0101613674565b845250918301918301613972565b600060208083850312156139c157600080fd5b823567ffffffffffffffff808211156139d957600080fd5b818501915085601f8301126139ed57600080fd5b81356139fb613615826135d0565b81815260059190911b83018401908481019088831115613a1a57600080fd5b8585015b83811015613b8257803585811115613a3557600080fd5b8601610120818c037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001811315613a6b57600080fd5b613a73613534565b613a7e8a8401612dca565b8152613a8c604084016132b5565b8a820152613a9c60608401613663565b6040820152613aad608084016132b5565b606082015260a083013588811115613ac457600080fd5b613ad28e8c83870101613674565b60808301525060c083013588811115613aea57600080fd5b613af88e8c838701016135f4565b60a08301525060e083013588811115613b115760008081fd5b613b1f8e8c8387010161392e565b60c0830152506101008084013589811115613b3a5760008081fd5b613b488f8d8388010161392e565b60e084015250918301359188831115613b615760008081fd5b613b6f8e8c85870101613674565b9082015285525050918601918601613a1e565b5098975050505050505050565b8051612dc581612da8565b600082601f830112613bab57600080fd5b81516020613bbb613615836135d0565b8083825260208201915060208460051b870101935086841115613bdd57600080fd5b602086015b848110156136585780518352918301918301613be2565b600060208284031215613c0b57600080fd5b815167ffffffffffffffff80821115613c2357600080fd5b9083019060e08286031215613c3757600080fd5b613c3f61355e565b613c4883613b8f565b8152613c5660208401613b8f565b6020820152613c6760408401613b8f565b6040820152606083015160608201526080830151608082015260a083015182811115613c9257600080fd5b613c9e87828601613b9a565b60a08301525060c083015182811115613cb657600080fd5b613cc287828601613b9a565b60c08301525095945050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613d0257613d026133dd565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b8181036000831280158383131683831282161715611d8a57611d8a6133dd565b60038110612e4d57612e4d612e0e565b60408101613d768285613d58565b610f936020830184613d58565b67ffffffffffffffff818116838216019080821115611d8a57611d8a6133dd565b60ff8181168382160290811690818114611d8a57611d8a6133dd565b60ff81811683821601908111156102fc576102fc6133dd565b600061016067ffffffffffffffff8e16835263ffffffff8d166020840152613e04604084018d612e3d565b806060840152613e168184018c612d31565b67ffffffffffffffff8b166080850152905082810360a0840152613e3a818a612e51565b905082810360c0840152613e4e8189612e8d565b905082810360e0840152613e628188612e8d565b60ff8716610100850152905067ffffffffffffffff8516610120840152828103610140840152613e928185612d31565b9e9d505050505050505050505050505056fea164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"capabilitiesRegistry\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainSelectorNotFound\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ChainSelectorNotSet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FChainMustBePositive\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FMustBePositive\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FTooHigh\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"length\",\"type\":\"uint256\"}],\"name\":\"InvalidConfigLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enumCCIPConfigTypes.ConfigState\",\"name\":\"currentState\",\"type\":\"uint8\"},{\"internalType\":\"enumCCIPConfigTypes.ConfigState\",\"name\":\"proposedState\",\"type\":\"uint8\"}],\"name\":\"InvalidConfigStateTransition\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidPluginType\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"}],\"name\":\"NodeNotInRegistry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonExistentConfigTransition\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"got\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minimum\",\"type\":\"uint256\"}],\"name\":\"NotEnoughTransmitters\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OfframpAddressCannotBeZero\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCapabilitiesRegistryCanCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"p2pIdsLength\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"signersLength\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"transmittersLength\",\"type\":\"uint256\"}],\"name\":\"P2PIdsLengthNotMatching\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManyOCR3Configs\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManySigners\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"got\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"expected\",\"type\":\"uint64\"}],\"name\":\"WrongConfigCount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"got\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"}],\"name\":\"WrongConfigDigest\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"got\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"}],\"name\":\"WrongConfigDigestBlueGreen\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"CapabilityConfigurationSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainConfigRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes32[]\",\"name\":\"readers\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint8\",\"name\":\"fChain\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"structCCIPConfigTypes.ChainConfig\",\"name\":\"chainConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"indexed\":true,\"internalType\":\"uint8\",\"name\":\"pluginType\",\"type\":\"uint8\"},{\"components\":[{\"components\":[{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offrampAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"p2pIds\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes[]\",\"name\":\"signers\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes[]\",\"name\":\"transmitters\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPConfigTypes.OCR3Config\",\"name\":\"config\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"configCount\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"indexed\":false,\"internalType\":\"structCCIPConfigTypes.OCR3ConfigWithMeta[]\",\"name\":\"config\",\"type\":\"tuple[]\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"chainSelectorRemoves\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes32[]\",\"name\":\"readers\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint8\",\"name\":\"fChain\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPConfigTypes.ChainConfig\",\"name\":\"chainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structCCIPConfigTypes.ChainConfigInfo[]\",\"name\":\"chainConfigAdds\",\"type\":\"tuple[]\"}],\"name\":\"applyChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"}],\"name\":\"beforeCapabilityConfigSet\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"pageIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pageSize\",\"type\":\"uint256\"}],\"name\":\"getAllChainConfigs\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes32[]\",\"name\":\"readers\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint8\",\"name\":\"fChain\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPConfigTypes.ChainConfig\",\"name\":\"chainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structCCIPConfigTypes.ChainConfigInfo[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"name\":\"getCapabilityConfiguration\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"configuration\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCapabilityRegistry\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNumChainConfigurations\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"}],\"name\":\"getOCRConfig\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offrampAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"p2pIds\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes[]\",\"name\":\"signers\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes[]\",\"name\":\"transmitters\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPConfigTypes.OCR3Config\",\"name\":\"config\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"configCount\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"internalType\":\"structCCIPConfigTypes.OCR3ConfigWithMeta[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x60a06040523480156200001157600080fd5b5060405162004110380380620041108339810160408190526200003491620001a6565b33806000816200008b5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000be57620000be81620000fb565b5050506001600160a01b038116620000e9576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b0316608052620001d8565b336001600160a01b03821603620001555760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000082565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600060208284031215620001b957600080fd5b81516001600160a01b0381168114620001d157600080fd5b9392505050565b608051613f0e620002026000396000818161010301528181610ed901526111490152613f0e6000f3fe608060405234801561001057600080fd5b50600436106100d45760003560e01c80638318ed5d11610081578063f2fde38b1161005b578063f2fde38b14610230578063f442c89a14610243578063fba64a7c1461025657600080fd5b80638318ed5d146101d15780638da5cb5b146101f2578063b74b23561461021057600080fd5b80634bd0473f116100b25780634bd0473f1461019157806379ba5097146101b15780637ac0d41e146101bb57600080fd5b806301ffc9a7146100d9578063020330e614610101578063181f5a7714610148575b600080fd5b6100ec6100e7366004612d4c565b610269565b60405190151581526020015b60405180910390f35b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100f8565b6101846040518060400160405280601481526020017f43434950436f6e66696720312e362e302d64657600000000000000000000000081525081565b6040516100f89190612df2565b6101a461019f366004612e36565b610302565b6040516100f89190612f55565b6101b961077a565b005b6101c361087c565b6040519081526020016100f8565b6101846101df366004613111565b5060408051602081019091526000815290565b60005473ffffffffffffffffffffffffffffffffffffffff16610123565b61022361021e36600461312e565b61088d565b6040516100f89190613194565b6101b961023e366004613224565b610b0e565b6101b96102513660046132a6565b610b22565b6101b961026436600461332a565b610ec1565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f78bea7210000000000000000000000000000000000000000000000000000000014806102fc57507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b63ffffffff8216600090815260056020526040812060609183600181111561032c5761032c612e6b565b600181111561033d5761033d612e6b565b8152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b8282101561076e57600084815260209020604080516101808101909152600884029091018054829060608201908390829060ff1660018111156103b0576103b0612e6b565b60018111156103c1576103c1612e6b565b8152815467ffffffffffffffff61010082048116602084015260ff690100000000000000000083041660408401526a0100000000000000000000909104166060820152600182018054608090920191610419906133e7565b80601f0160208091040260200160405190810160405280929190818152602001828054610445906133e7565b80156104925780601f1061046757610100808354040283529160200191610492565b820191906000526020600020905b81548152906001019060200180831161047557829003601f168201915b50505050508152602001600282018054806020026020016040519081016040528092919081815260200182805480156104ea57602002820191906000526020600020905b8154815260200190600101908083116104d6575b5050505050815260200160038201805480602002602001604051908101604052809291908181526020016000905b828210156105c4578382906000526020600020018054610537906133e7565b80601f0160208091040260200160405190810160405280929190818152602001828054610563906133e7565b80156105b05780601f10610585576101008083540402835291602001916105b0565b820191906000526020600020905b81548152906001019060200180831161059357829003601f168201915b505050505081526020019060010190610518565b50505050815260200160048201805480602002602001604051908101604052809291908181526020016000905b8282101561069d578382906000526020600020018054610610906133e7565b80601f016020809104026020016040519081016040528092919081815260200182805461063c906133e7565b80156106895780601f1061065e57610100808354040283529160200191610689565b820191906000526020600020905b81548152906001019060200180831161066c57829003601f168201915b5050505050815260200190600101906105f1565b5050505081526020016005820180546106b5906133e7565b80601f01602080910402602001604051908101604052809291908181526020018280546106e1906133e7565b801561072e5780601f106107035761010080835404028352916020019161072e565b820191906000526020600020905b81548152906001019060200180831161071157829003601f168201915b505050919092525050508152600682015467ffffffffffffffff16602080830191909152600790920154604090910152908252600192909201910161036b565b50505050905092915050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610800576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b60006108886003610f7c565b905090565b6060600061089b6003610f7c565b905060006108a98486613469565b90508315806108b85750818110155b156108f85760408051600080825260208201909252906108ee565b6108db612aeb565b8152602001906001900390816108d35790505b50925050506102fc565b600061090485836134af565b9050828111156109115750815b600061091d83836134c2565b67ffffffffffffffff81111561093557610935613480565b60405190808252806020026020018201604052801561096e57816020015b61095b612aeb565b8152602001906001900390816109535790505b509050600061097d6003610f86565b9050835b83811015610b0157600082828151811061099d5761099d6134d5565b60209081029190910181015160408051808201825267ffffffffffffffff831680825260009081526002855282902082518154608081880283018101909552606082018181529597509295860194909391928492849190840182828015610a2357602002820191906000526020600020905b815481526020019060010190808311610a0f575b5050509183525050600182015460ff166020820152600282018054604090920191610a4d906133e7565b80601f0160208091040260200160405190810160405280929190818152602001828054610a79906133e7565b8015610ac65780601f10610a9b57610100808354040283529160200191610ac6565b820191906000526020600020905b815481529060010190602001808311610aa957829003601f168201915b50505091909252505050905284610add88856134c2565b81518110610aed57610aed6134d5565b602090810291909101015250600101610981565b5090979650505050505050565b610b16610f9a565b610b1f8161101d565b50565b610b2a610f9a565b60005b83811015610d1057610b71858583818110610b4a57610b4a6134d5565b9050602002016020810190610b5f9190613504565b60039067ffffffffffffffff16611112565b610bdb57848482818110610b8757610b876134d5565b9050602002016020810190610b9c9190613504565b6040517f1bd4d2d200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016107f7565b60026000868684818110610bf157610bf16134d5565b9050602002016020810190610c069190613504565b67ffffffffffffffff1681526020810191909152604001600090812090610c2d8282612b33565b6001820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055610c65600283016000612b51565b5050610ca3858583818110610c7c57610c7c6134d5565b9050602002016020810190610c919190613504565b60039067ffffffffffffffff1661112a565b507f2a680691fef3b2d105196805935232c661ce703e92d464ef0b94a7bc62d714f0858583818110610cd757610cd76134d5565b9050602002016020810190610cec9190613504565b60405167ffffffffffffffff909116815260200160405180910390a1600101610b2d565b5060005b81811015610eba576000838383818110610d3057610d306134d5565b9050602002810190610d42919061351f565b610d5090602081019061355d565b610d599061375f565b90506000848484818110610d6f57610d6f6134d5565b9050602002810190610d81919061351f565b610d8f906020810190613504565b9050610d9e8260000151611136565b816020015160ff16600003610ddf576040517fa9b3766e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff81166000908152600260209081526040909120835180518593610e0f928492910190612b8b565b5060208201516001820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff90921691909117905560408201516002820190610e5c9082613846565b50610e7691506003905067ffffffffffffffff8316611282565b507f05dd57854af2c291a94ea52e7c43d80bc3be7fa73022f98b735dea86642fa5e08183604051610ea8929190613960565b60405180910390a15050600101610d14565b5050505050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610f30576040517fac7a7efd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080610f47610f4286880188613a0b565b61128e565b8151919350915015610f5f57610f5f836000846114d9565b805115610f7257610f72836001836114d9565b5050505050505050565b60006102fc825490565b60606000610f9383611c98565b9392505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461101b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016107f7565b565b3373ffffffffffffffffffffffffffffffffffffffff82160361109c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016107f7565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60008181526001830160205260408120541515610f93565b6000610f938383611cf4565b60005b815181101561127e5760008019167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166350c946fe848481518110611195576111956134d5565b60200260200101516040518263ffffffff1660e01b81526004016111bb91815260200190565b600060405180830381865afa1580156111d8573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261121e9190810190613c56565b608001510361127657818181518110611239576112396134d5565b60200260200101516040517f8907a4fa0000000000000000000000000000000000000000000000000000000081526004016107f791815260200190565b600101611139565b5050565b6000610f938383611dee565b606080600460ff16835111156112d0576040517f8854586400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160028082526060820190925290816020015b61134d6040805161012081019091528060008152602001600067ffffffffffffffff168152602001600060ff168152602001600067ffffffffffffffff16815260200160608152602001606081526020016060815260200160608152602001606081525090565b8152602001906001900390816112e657505060408051600280825260608201909252919350602082015b6113de6040805161012081019091528060008152602001600067ffffffffffffffff168152602001600060ff168152602001600067ffffffffffffffff16815260200160608152602001606081526020016060815260200160608152602001606081525090565b81526020019060019003908161137757905050905060008060005b85518110156114cc576000868281518110611416576114166134d5565b602002602001015160000151600181111561143357611433612e6b565b036114805785818151811061144a5761144a6134d5565b6020026020010151858481518110611464576114646134d5565b60200260200101819052508261147990613d2e565b92506114c4565b858181518110611492576114926134d5565b60200260200101518483815181106114ac576114ac6134d5565b6020026020010181905250816114c190613d2e565b91505b6001016113f9565b5090835281529092909150565b63ffffffff831660009081526005602052604081208184600181111561150157611501612e6b565b600181111561151257611512612e6b565b8152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b8282101561194357600084815260209020604080516101808101909152600884029091018054829060608201908390829060ff16600181111561158557611585612e6b565b600181111561159657611596612e6b565b8152815467ffffffffffffffff61010082048116602084015260ff690100000000000000000083041660408401526a01000000000000000000009091041660608201526001820180546080909201916115ee906133e7565b80601f016020809104026020016040519081016040528092919081815260200182805461161a906133e7565b80156116675780601f1061163c57610100808354040283529160200191611667565b820191906000526020600020905b81548152906001019060200180831161164a57829003601f168201915b50505050508152602001600282018054806020026020016040519081016040528092919081815260200182805480156116bf57602002820191906000526020600020905b8154815260200190600101908083116116ab575b5050505050815260200160038201805480602002602001604051908101604052809291908181526020016000905b8282101561179957838290600052602060002001805461170c906133e7565b80601f0160208091040260200160405190810160405280929190818152602001828054611738906133e7565b80156117855780601f1061175a57610100808354040283529160200191611785565b820191906000526020600020905b81548152906001019060200180831161176857829003601f168201915b5050505050815260200190600101906116ed565b50505050815260200160048201805480602002602001604051908101604052809291908181526020016000905b828210156118725783829060005260206000200180546117e5906133e7565b80601f0160208091040260200160405190810160405280929190818152602001828054611811906133e7565b801561185e5780601f106118335761010080835404028352916020019161185e565b820191906000526020600020905b81548152906001019060200180831161184157829003601f168201915b5050505050815260200190600101906117c6565b50505050815260200160058201805461188a906133e7565b80601f01602080910402602001604051908101604052809291908181526020018280546118b6906133e7565b80156119035780601f106118d857610100808354040283529160200191611903565b820191906000526020600020905b8154815290600101906020018083116118e657829003601f168201915b505050919092525050508152600682015467ffffffffffffffff166020808301919091526007909201546040909101529082526001929092019101611540565b50505050905060006119558251611e3d565b905060006119638451611e3d565b905061196f8282611e8f565b600061197e8785878686611f4b565b905061198a848261232f565b63ffffffff87166000908152600560205260408120908760018111156119b2576119b2612e6b565b60018111156119c3576119c3612e6b565b815260200190815260200160002060006119dd9190612bd6565b60005b8151811015611c3b5763ffffffff8816600090815260056020526040812090886001811115611a1157611a11612e6b565b6001811115611a2257611a22612e6b565b8152602001908152602001600020828281518110611a4257611a426134d5565b6020908102919091018101518254600181810185556000948552929093208151805160089095029091018054929490939192849283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016908381811115611aac57611aac612e6b565b021790555060208201518154604084015160608501517fffffffffffffffffffffffffffffffffffffffffffff000000000000000000ff90921661010067ffffffffffffffff948516027fffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffff1617690100000000000000000060ff90921691909102177fffffffffffffffffffffffffffff0000000000000000ffffffffffffffffffff166a0100000000000000000000929091169190910217815560808201516001820190611b7b9082613846565b5060a08201518051611b97916002840191602090910190612b8b565b5060c08201518051611bb3916003840191602090910190612bf7565b5060e08201518051611bcf916004840191602090910190612bf7565b506101008201516005820190611be59082613846565b50505060208201516006820180547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff9092169190911790556040909101516007909101556001016119e0565b50856001811115611c4e57611c4e612e6b565b60ff168763ffffffff167f403420f960fcf8fdad51d01bc3af8668c5963e6746c63c8f5363c26d9d44514883604051611c879190612f55565b60405180910390a350505050505050565b606081600001805480602002602001604051908101604052809291908181526020018280548015611ce857602002820191906000526020600020905b815481526020019060010190808311611cd4575b50505050509050919050565b60008181526001830160205260408120548015611ddd576000611d186001836134c2565b8554909150600090611d2c906001906134c2565b9050808214611d91576000866000018281548110611d4c57611d4c6134d5565b9060005260206000200154905080876000018481548110611d6f57611d6f6134d5565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080611da257611da2613d66565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506102fc565b60009150506102fc565b5092915050565b6000818152600183016020526040812054611e35575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556102fc565b5060006102fc565b60006002821115611e7d576040517f3e478526000000000000000000000000000000000000000000000000000000008152600481018390526024016107f7565b8160028111156102fc576102fc612e6b565b6000826002811115611ea357611ea3612e6b565b826002811115611eb557611eb5612e6b565b611ebf9190613d95565b90508060011480611f0b5750807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff148015611f0b57506002836002811115611f0957611f09612e6b565b145b15611f1557505050565b82826040517f0a6b675b0000000000000000000000000000000000000000000000000000000081526004016107f7929190613dc5565b60606000845167ffffffffffffffff811115611f6957611f69613480565b604051908082528060200260200182016040528015611f92578160200160208202803683370190505b5090506000846002811115611fa957611fa9612e6b565b148015611fc757506001836002811115611fc557611fc5612e6b565b145b1561200857600181600081518110611fe157611fe16134d5565b602002602001019067ffffffffffffffff16908167ffffffffffffffff1681525050612170565b600184600281111561201c5761201c612e6b565b14801561203a5750600283600281111561203857612038612e6b565b145b156120d15785600081518110612052576120526134d5565b60200260200101516020015181600081518110612071576120716134d5565b602002602001019067ffffffffffffffff16908167ffffffffffffffff1681525050856000815181106120a6576120a66134d5565b60200260200101516020015160016120be9190613de0565b81600181518110611fe157611fe16134d5565b60028460028111156120e5576120e5612e6b565b1480156121035750600183600281111561210157612101612e6b565b145b1561213a578560018151811061211b5761211b6134d5565b60200260200101516020015181600081518110611fe157611fe16134d5565b83836040517f0a6b675b0000000000000000000000000000000000000000000000000000000081526004016107f7929190613dc5565b6000855167ffffffffffffffff81111561218c5761218c613480565b60405190808252806020026020018201604052801561223a57816020015b6040805161018081018252600060608083018281526080840183905260a0840183905260c0840183905260e08401829052610100840182905261012084018290526101408401829052610160840191909152825260208083018290529282015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816121aa5790505b50905060005b82518110156123235761226b87828151811061225e5761225e6134d5565b60200260200101516126ae565b6040518060600160405280888381518110612288576122886134d5565b602002602001015181526020018483815181106122a7576122a76134d5565b602002602001015167ffffffffffffffff1681526020016122fb8b8685815181106122d4576122d46134d5565b60200260200101518b86815181106122ee576122ee6134d5565b6020026020010151612a1d565b815250828281518110612310576123106134d5565b6020908102919091010152600101612240565b50979650505050505050565b81518151811580156123415750806001145b156123e35782600081518110612359576123596134d5565b60200260200101516020015167ffffffffffffffff166001146123dd5782600081518110612389576123896134d5565b60209081029190910181015101516040517fc1658eb800000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152600160248201526044016107f7565b50505050565b8160011480156123f35750806002145b156125a9578360008151811061240b5761240b6134d5565b6020026020010151604001518360008151811061242a5761242a6134d5565b602002602001015160400151146124b6578260008151811061244e5761244e6134d5565b6020026020010151604001518460008151811061246d5761246d6134d5565b6020026020010151604001516040517fc7ccdd7f0000000000000000000000000000000000000000000000000000000081526004016107f7929190918252602082015260400190565b836000815181106124c9576124c96134d5565b60200260200101516020015160016124e19190613de0565b67ffffffffffffffff16836001815181106124fe576124fe6134d5565b60200260200101516020015167ffffffffffffffff16146123dd578260018151811061252c5761252c6134d5565b6020026020010151602001518460008151811061254b5761254b6134d5565b60200260200101516020015160016125639190613de0565b6040517fc1658eb800000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9283166004820152911660248201526044016107f7565b8160021480156125b95750806001145b1561267c57836001815181106125d1576125d16134d5565b602002602001015160400151836000815181106125f0576125f06134d5565b602002602001015160400151146123dd5782600081518110612614576126146134d5565b60200260200101516040015184600181518110612633576126336134d5565b6020026020010151604001516040517f9e9756700000000000000000000000000000000000000000000000000000000081526004016107f7929190918252602082015260400190565b6040517f1f1b2bb600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806020015167ffffffffffffffff166000036126f6576040517f698cf8e000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008151600181111561270b5761270b612e6b565b1415801561272c575060018151600181111561272957612729612e6b565b14155b15612763576040517f3302dbd700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60808101515115806127a0575060408051600060208201520160405160208183030381529060405280519060200120816080015180519060200120145b156127d7576040517f358c192700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208101516127f29060039067ffffffffffffffff16611112565b61283a5760208101516040517f1bd4d2d200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016107f7565b60208082015167ffffffffffffffff1660009081526002909152604081206001015461286a9060ff166003613e01565b612875906001613e1d565b60ff169050808260e001515110156128ca5760e0820151516040517f548dd21f0000000000000000000000000000000000000000000000000000000081526004810191909152602481018290526044016107f7565b60c08201515161010081111561290c576040517f1b925da600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8260a00151518114158061292557508260e00151518114155b1561297f5760a08301515160c08401515160e0850151516040517fba900f6d0000000000000000000000000000000000000000000000000000000081526004810193909352602483019190915260448201526064016107f7565b826040015160ff166000036129c0576040517f39d1a4d000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408301516129d0906003613e01565b60ff168111612a0b576040517f4856694e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612a188360a00151611136565b505050565b60008082602001518584600001518560800151878760a001518860c001518960e001518a604001518b606001518c6101000151604051602001612a6a9b9a99989796959493929190613e36565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e0a000000000000000000000000000000000000000000000000000000000000179150509392505050565b6040518060400160405280600067ffffffffffffffff168152602001612b2e604051806060016040528060608152602001600060ff168152602001606081525090565b905290565b5080546000825590600052602060002090810190610b1f9190612c49565b508054612b5d906133e7565b6000825580601f10612b6d575050565b601f016020900490600052602060002090810190610b1f9190612c49565b828054828255906000526020600020908101928215612bc6579160200282015b82811115612bc6578251825591602001919060010190612bab565b50612bd2929150612c49565b5090565b5080546000825560080290600052602060002090810190610b1f9190612c5e565b828054828255906000526020600020908101928215612c3d579160200282015b82811115612c3d5782518290612c2d9082613846565b5091602001919060010190612c17565b50612bd2929150612d11565b5b80821115612bd25760008155600101612c4a565b80821115612bd25780547fffffffffffffffffffffffffffff00000000000000000000000000000000000016815560008181612c9d6001830182612b51565b612cab600283016000612b33565b612cb9600383016000612d2e565b612cc7600483016000612d2e565b612cd5600583016000612b51565b5050506006810180547fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000016905560006007820155600801612c5e565b80821115612bd2576000612d258282612b51565b50600101612d11565b5080546000825590600052602060002090810190610b1f9190612d11565b600060208284031215612d5e57600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610f9357600080fd5b6000815180845260005b81811015612db457602081850181015186830182015201612d98565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000610f936020830184612d8e565b63ffffffff81168114610b1f57600080fd5b8035612e2281612e05565b919050565b803560028110612e2257600080fd5b60008060408385031215612e4957600080fd5b8235612e5481612e05565b9150612e6260208401612e27565b90509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60028110612eaa57612eaa612e6b565b9052565b60008151808452602080850194506020840160005b83811015612edf57815187529582019590820190600101612ec3565b509495945050505050565b60008282518085526020808601955060208260051b8401016020860160005b84811015610b01577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018952612f43838351612d8e565b98840198925090830190600101612f09565b600060208083018184528085518083526040925060408601915060408160051b87010184880160005b83811015613103577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0898403018552815160608151818652612fc38287018251612e9a565b898101516080612fde8189018367ffffffffffffffff169052565b8a830151915060a0612ff4818a018460ff169052565b938301519360c092506130128984018667ffffffffffffffff169052565b818401519450610120915060e082818b01526130326101808b0187612d8e565b95508185015191507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0610100818c890301818d01526130718885612eae565b958701518c87038301868e015295975061308b8887612eea565b9750828701519550818c8903016101408d01526130a88887612eea565b975080870151965050808b8803016101608c015250505050506130cb8282612d8e565b915050888201516130e78a87018267ffffffffffffffff169052565b5090870151938701939093529386019390860190600101612f7e565b509098975050505050505050565b60006020828403121561312357600080fd5b8135610f9381612e05565b6000806040838503121561314157600080fd5b50508035926020909101359150565b60008151606084526131656060850182612eae565b905060ff60208401511660208501526040830151848203604086015261318b8282612d8e565b95945050505050565b600060208083018184528085518083526040925060408601915060408160051b87010184880160005b83811015613103578883037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00185528151805167ffffffffffffffff16845287015187840187905261321187850182613150565b95880195935050908601906001016131bd565b60006020828403121561323657600080fd5b813573ffffffffffffffffffffffffffffffffffffffff81168114610f9357600080fd5b60008083601f84011261326c57600080fd5b50813567ffffffffffffffff81111561328457600080fd5b6020830191508360208260051b850101111561329f57600080fd5b9250929050565b600080600080604085870312156132bc57600080fd5b843567ffffffffffffffff808211156132d457600080fd5b6132e08883890161325a565b909650945060208701359150808211156132f957600080fd5b506133068782880161325a565b95989497509550505050565b803567ffffffffffffffff81168114612e2257600080fd5b6000806000806000806080878903121561334357600080fd5b863567ffffffffffffffff8082111561335b57600080fd5b6133678a838b0161325a565b9098509650602089013591508082111561338057600080fd5b818901915089601f83011261339457600080fd5b8135818111156133a357600080fd5b8a60208285010111156133b557600080fd5b6020830196508095505050506133cd60408801613312565b91506133db60608801612e17565b90509295509295509295565b600181811c908216806133fb57607f821691505b602082108103613434577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80820281158282048414176102fc576102fc61343a565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b808201808211156102fc576102fc61343a565b818103818111156102fc576102fc61343a565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561351657600080fd5b610f9382613312565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc183360301811261355357600080fd5b9190910192915050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa183360301811261355357600080fd5b604051610120810167ffffffffffffffff811182821017156135b5576135b5613480565b60405290565b60405160e0810167ffffffffffffffff811182821017156135b5576135b5613480565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561362557613625613480565b604052919050565b600067ffffffffffffffff82111561364757613647613480565b5060051b60200190565b600082601f83011261366257600080fd5b813560206136776136728361362d565b6135de565b8083825260208201915060208460051b87010193508684111561369957600080fd5b602086015b848110156136b5578035835291830191830161369e565b509695505050505050565b803560ff81168114612e2257600080fd5b600082601f8301126136e257600080fd5b813567ffffffffffffffff8111156136fc576136fc613480565b61372d60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016135de565b81815284602083860101111561374257600080fd5b816020850160208301376000918101602001919091529392505050565b60006060823603121561377157600080fd5b6040516060810167ffffffffffffffff828210818311171561379557613795613480565b8160405284359150808211156137aa57600080fd5b6137b636838701613651565b83526137c4602086016136c0565b602084015260408501359150808211156137dd57600080fd5b506137ea368286016136d1565b60408301525092915050565b601f821115612a18576000816000526020600020601f850160051c8101602086101561381f5750805b601f850160051c820191505b8181101561383e5782815560010161382b565b505050505050565b815167ffffffffffffffff81111561386057613860613480565b6138748161386e84546133e7565b846137f6565b602080601f8311600181146138c757600084156138915750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b17855561383e565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015613914578886015182559484019460019091019084016138f5565b508582101561395057878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b67ffffffffffffffff831681526040602082015260006139836040830184613150565b949350505050565b600082601f83011261399c57600080fd5b813560206139ac6136728361362d565b82815260059290921b840181019181810190868411156139cb57600080fd5b8286015b848110156136b557803567ffffffffffffffff8111156139ef5760008081fd5b6139fd8986838b01016136d1565b8452509183019183016139cf565b60006020808385031215613a1e57600080fd5b823567ffffffffffffffff80821115613a3657600080fd5b818501915085601f830112613a4a57600080fd5b8135613a586136728261362d565b81815260059190911b83018401908481019088831115613a7757600080fd5b8585015b83811015613bdf57803585811115613a9257600080fd5b8601610120818c037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001811315613ac857600080fd5b613ad0613591565b613adb8a8401612e27565b8152613ae960408401613312565b8a820152613af9606084016136c0565b6040820152613b0a60808401613312565b606082015260a083013588811115613b2157600080fd5b613b2f8e8c838701016136d1565b60808301525060c083013588811115613b4757600080fd5b613b558e8c83870101613651565b60a08301525060e083013588811115613b6e5760008081fd5b613b7c8e8c8387010161398b565b60c0830152506101008084013589811115613b975760008081fd5b613ba58f8d8388010161398b565b60e084015250918301359188831115613bbe5760008081fd5b613bcc8e8c858701016136d1565b9082015285525050918601918601613a7b565b5098975050505050505050565b8051612e2281612e05565b600082601f830112613c0857600080fd5b81516020613c186136728361362d565b8083825260208201915060208460051b870101935086841115613c3a57600080fd5b602086015b848110156136b55780518352918301918301613c3f565b600060208284031215613c6857600080fd5b815167ffffffffffffffff80821115613c8057600080fd5b9083019060e08286031215613c9457600080fd5b613c9c6135bb565b613ca583613bec565b8152613cb360208401613bec565b6020820152613cc460408401613bec565b6040820152606083015160608201526080830151608082015260a083015182811115613cef57600080fd5b613cfb87828601613bf7565b60a08301525060c083015182811115613d1357600080fd5b613d1f87828601613bf7565b60c08301525095945050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613d5f57613d5f61343a565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b8181036000831280158383131683831282161715611de757611de761343a565b60038110612eaa57612eaa612e6b565b60408101613dd38285613db5565b610f936020830184613db5565b67ffffffffffffffff818116838216019080821115611de757611de761343a565b60ff8181168382160290811690818114611de757611de761343a565b60ff81811683821601908111156102fc576102fc61343a565b600061016067ffffffffffffffff8e16835263ffffffff8d166020840152613e61604084018d612e9a565b806060840152613e738184018c612d8e565b67ffffffffffffffff8b166080850152905082810360a0840152613e97818a612eae565b905082810360c0840152613eab8189612eea565b905082810360e0840152613ebf8188612eea565b60ff8716610100850152905067ffffffffffffffff8516610120840152828103610140840152613eef8185612d8e565b9e9d505050505050505050505050505056fea164736f6c6343000818000a", } var CCIPConfigABI = CCIPConfigMetaData.ABI @@ -775,6 +775,143 @@ func (_CCIPConfig *CCIPConfigFilterer) ParseChainConfigSet(log types.Log) (*CCIP return event, nil } +type CCIPConfigConfigSetIterator struct { + Event *CCIPConfigConfigSet + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *CCIPConfigConfigSetIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(CCIPConfigConfigSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(CCIPConfigConfigSet) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *CCIPConfigConfigSetIterator) Error() error { + return it.fail +} + +func (it *CCIPConfigConfigSetIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type CCIPConfigConfigSet struct { + DonId uint32 + PluginType uint8 + Config []CCIPConfigTypesOCR3ConfigWithMeta + Raw types.Log +} + +func (_CCIPConfig *CCIPConfigFilterer) FilterConfigSet(opts *bind.FilterOpts, donId []uint32, pluginType []uint8) (*CCIPConfigConfigSetIterator, error) { + + var donIdRule []interface{} + for _, donIdItem := range donId { + donIdRule = append(donIdRule, donIdItem) + } + var pluginTypeRule []interface{} + for _, pluginTypeItem := range pluginType { + pluginTypeRule = append(pluginTypeRule, pluginTypeItem) + } + + logs, sub, err := _CCIPConfig.contract.FilterLogs(opts, "ConfigSet", donIdRule, pluginTypeRule) + if err != nil { + return nil, err + } + return &CCIPConfigConfigSetIterator{contract: _CCIPConfig.contract, event: "ConfigSet", logs: logs, sub: sub}, nil +} + +func (_CCIPConfig *CCIPConfigFilterer) WatchConfigSet(opts *bind.WatchOpts, sink chan<- *CCIPConfigConfigSet, donId []uint32, pluginType []uint8) (event.Subscription, error) { + + var donIdRule []interface{} + for _, donIdItem := range donId { + donIdRule = append(donIdRule, donIdItem) + } + var pluginTypeRule []interface{} + for _, pluginTypeItem := range pluginType { + pluginTypeRule = append(pluginTypeRule, pluginTypeItem) + } + + logs, sub, err := _CCIPConfig.contract.WatchLogs(opts, "ConfigSet", donIdRule, pluginTypeRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(CCIPConfigConfigSet) + if err := _CCIPConfig.contract.UnpackLog(event, "ConfigSet", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_CCIPConfig *CCIPConfigFilterer) ParseConfigSet(log types.Log) (*CCIPConfigConfigSet, error) { + event := new(CCIPConfigConfigSet) + if err := _CCIPConfig.contract.UnpackLog(event, "ConfigSet", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + type CCIPConfigOwnershipTransferRequestedIterator struct { Event *CCIPConfigOwnershipTransferRequested @@ -1055,6 +1192,8 @@ func (_CCIPConfig *CCIPConfig) ParseLog(log types.Log) (generated.AbigenLog, err return _CCIPConfig.ParseChainConfigRemoved(log) case _CCIPConfig.abi.Events["ChainConfigSet"].ID: return _CCIPConfig.ParseChainConfigSet(log) + case _CCIPConfig.abi.Events["ConfigSet"].ID: + return _CCIPConfig.ParseConfigSet(log) case _CCIPConfig.abi.Events["OwnershipTransferRequested"].ID: return _CCIPConfig.ParseOwnershipTransferRequested(log) case _CCIPConfig.abi.Events["OwnershipTransferred"].ID: @@ -1077,6 +1216,10 @@ func (CCIPConfigChainConfigSet) Topic() common.Hash { return common.HexToHash("0x05dd57854af2c291a94ea52e7c43d80bc3be7fa73022f98b735dea86642fa5e0") } +func (CCIPConfigConfigSet) Topic() common.Hash { + return common.HexToHash("0x403420f960fcf8fdad51d01bc3af8668c5963e6746c63c8f5363c26d9d445148") +} + func (CCIPConfigOwnershipTransferRequested) Topic() common.Hash { return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") } @@ -1132,6 +1275,12 @@ type CCIPConfigInterface interface { ParseChainConfigSet(log types.Log) (*CCIPConfigChainConfigSet, error) + FilterConfigSet(opts *bind.FilterOpts, donId []uint32, pluginType []uint8) (*CCIPConfigConfigSetIterator, error) + + WatchConfigSet(opts *bind.WatchOpts, sink chan<- *CCIPConfigConfigSet, donId []uint32, pluginType []uint8) (event.Subscription, error) + + ParseConfigSet(log types.Log) (*CCIPConfigConfigSet, error) + FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*CCIPConfigOwnershipTransferRequestedIterator, error) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *CCIPConfigOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) diff --git a/core/gethwrappers/ccip/generated/fee_quoter/fee_quoter.go b/core/gethwrappers/ccip/generated/fee_quoter/fee_quoter.go index d8f616053a..e4c17b1886 100644 --- a/core/gethwrappers/ccip/generated/fee_quoter/fee_quoter.go +++ b/core/gethwrappers/ccip/generated/fee_quoter/fee_quoter.go @@ -154,8 +154,8 @@ type KeystoneFeedsPermissionHandlerPermission struct { } var FeeQuoterMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint96\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"linkToken\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"stalenessThreshold\",\"type\":\"uint32\"}],\"internalType\":\"structFeeQuoter.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"priceUpdaters\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"feeTokens\",\"type\":\"address[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"}],\"internalType\":\"structIFeeQuoter.TokenPriceFeedConfig\",\"name\":\"feedConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.TokenPriceFeedUpdate[]\",\"name\":\"tokenPriceFeeds\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigSingleTokenArgs[]\",\"name\":\"tokenTransferFeeConfigs\",\"type\":\"tuple[]\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigArgs[]\",\"name\":\"tokenTransferFeeConfigArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"internalType\":\"structFeeQuoter.PremiumMultiplierWeiPerEthArgs[]\",\"name\":\"premiumMultiplierWeiPerEthArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chain\",\"type\":\"uint64\"}],\"name\":\"ChainNotSupported\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DataFeedValueOutOfUint224Range\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"DestinationChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ExtraArgOutOfOrderExecutionMustBeTrue\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"FeeTokenNotSupported\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"}],\"name\":\"InvalidDestBytesOverhead\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidDestChainConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidEVMAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidExtraArgsTag\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidStaticConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"msgFeeJuels\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint256\"}],\"name\":\"MessageFeeTooHigh\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MessageGasLimitTooHigh\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"maxSize\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualSize\",\"type\":\"uint256\"}],\"name\":\"MessageTooLarge\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"internalType\":\"bytes10\",\"name\":\"workflowName\",\"type\":\"bytes10\"},{\"internalType\":\"bytes2\",\"name\":\"reportName\",\"type\":\"bytes2\"}],\"name\":\"ReportForwarderUnauthorized\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"SourceTokenDataTooLarge\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"threshold\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timePassed\",\"type\":\"uint256\"}],\"name\":\"StaleGasPrice\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feedTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"storedTimeStamp\",\"type\":\"uint256\"}],\"name\":\"StaleKeystoneUpdate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"TokenNotSupported\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"UnauthorizedCaller\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnsupportedNumberOfTokens\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"AuthorizedCallerAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"AuthorizedCallerRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"indexed\":false,\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"name\":\"DestChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"indexed\":false,\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"name\":\"DestChainConfigUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"}],\"name\":\"FeeTokenAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"}],\"name\":\"FeeTokenRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"name\":\"PremiumMultiplierWeiPerEthUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"}],\"indexed\":false,\"internalType\":\"structIFeeQuoter.TokenPriceFeedConfig\",\"name\":\"priceFeedConfig\",\"type\":\"tuple\"}],\"name\":\"PriceFeedPerTokenUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"reportId\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"},{\"internalType\":\"bytes10\",\"name\":\"workflowName\",\"type\":\"bytes10\"},{\"internalType\":\"bytes2\",\"name\":\"reportName\",\"type\":\"bytes2\"},{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isAllowed\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"structKeystoneFeedsPermissionHandler.Permission\",\"name\":\"permission\",\"type\":\"tuple\"}],\"name\":\"ReportPermissionSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"TokenTransferFeeConfigDeleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"name\":\"TokenTransferFeeConfigUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"UsdPerTokenUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChain\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"UsdPerUnitGasUpdated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address[]\",\"name\":\"addedCallers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"removedCallers\",\"type\":\"address[]\"}],\"internalType\":\"structAuthorizedCallers.AuthorizedCallerArgs\",\"name\":\"authorizedCallerArgs\",\"type\":\"tuple\"}],\"name\":\"applyAuthorizedCallerUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyDestChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"feeTokensToAdd\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"feeTokensToRemove\",\"type\":\"address[]\"}],\"name\":\"applyFeeTokensUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"internalType\":\"structFeeQuoter.PremiumMultiplierWeiPerEthArgs[]\",\"name\":\"premiumMultiplierWeiPerEthArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyPremiumMultiplierWeiPerEthUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigSingleTokenArgs[]\",\"name\":\"tokenTransferFeeConfigs\",\"type\":\"tuple[]\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigArgs[]\",\"name\":\"tokenTransferFeeConfigArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigRemoveArgs[]\",\"name\":\"tokensToUseDefaultFeeConfigs\",\"type\":\"tuple[]\"}],\"name\":\"applyTokenTransferFeeConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"fromToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fromTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"toToken\",\"type\":\"address\"}],\"name\":\"convertTokenAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllAuthorizedCallers\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getDestChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getDestinationChainGasPrice\",\"outputs\":[{\"components\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"internalType\":\"structInternal.TimestampedPackedUint224\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getFeeTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getPremiumMultiplierWeiPerEth\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint96\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"linkToken\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"stalenessThreshold\",\"type\":\"uint32\"}],\"internalType\":\"structFeeQuoter.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getTokenAndGasPrices\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"tokenPrice\",\"type\":\"uint224\"},{\"internalType\":\"uint224\",\"name\":\"gasPriceValue\",\"type\":\"uint224\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenPrice\",\"outputs\":[{\"components\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"internalType\":\"structInternal.TimestampedPackedUint224\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenPriceFeedConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"}],\"internalType\":\"structIFeeQuoter.TokenPriceFeedConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"tokens\",\"type\":\"address[]\"}],\"name\":\"getTokenPrices\",\"outputs\":[{\"components\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"internalType\":\"structInternal.TimestampedPackedUint224[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenTransferFeeConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"getValidatedFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getValidatedTokenPrice\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"\",\"type\":\"uint224\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"onReport\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"name\":\"processMessageArgs\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"msgFeeJuels\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isOutOfOrderExecution\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"convertedExtraArgs\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"rampTokenAmounts\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"sourceTokenAmounts\",\"type\":\"tuple[]\"}],\"name\":\"processPoolReturnData\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"destExecDataPerToken\",\"type\":\"bytes[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"},{\"internalType\":\"bytes10\",\"name\":\"workflowName\",\"type\":\"bytes10\"},{\"internalType\":\"bytes2\",\"name\":\"reportName\",\"type\":\"bytes2\"},{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isAllowed\",\"type\":\"bool\"}],\"internalType\":\"structKeystoneFeedsPermissionHandler.Permission[]\",\"name\":\"permissions\",\"type\":\"tuple[]\"}],\"name\":\"setReportPermissions\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"}],\"name\":\"updatePrices\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"}],\"internalType\":\"structIFeeQuoter.TokenPriceFeedConfig\",\"name\":\"feedConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.TokenPriceFeedUpdate[]\",\"name\":\"tokenPriceFeedUpdates\",\"type\":\"tuple[]\"}],\"name\":\"updateTokenPriceFeeds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x60e06040523480156200001157600080fd5b506040516200774438038062007744833981016040819052620000349162001834565b8533806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf8162000207565b5050604080518082018252838152815160008152602080820190935291810191909152620000ee9150620002b2565b5060208701516001600160a01b0316158062000112575086516001600160601b0316155b80620001265750604087015163ffffffff16155b15620001455760405163d794ef9560e01b815260040160405180910390fd5b6020878101516001600160a01b031660a05287516001600160601b031660805260408089015163ffffffff1660c05280516000815291820190526200018c90869062000401565b620001978462000549565b620001a2816200061a565b620001ad8262000a5a565b60408051600080825260208201909252620001fa91859190620001f3565b6040805180820190915260008082526020820152815260200190600190039081620001cb5790505b5062000b26565b5050505050505062001ae5565b336001600160a01b03821603620002615760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b602081015160005b815181101562000342576000828281518110620002db57620002db62001953565b60209081029190910101519050620002f560028262000e5f565b1562000338576040516001600160a01b03821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b50600101620002ba565b50815160005b8151811015620003fb57600082828151811062000369576200036962001953565b6020026020010151905060006001600160a01b0316816001600160a01b031603620003a7576040516342bcdf7f60e11b815260040160405180910390fd5b620003b460028262000e7f565b506040516001600160a01b03821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a15060010162000348565b50505050565b60005b8251811015620004a2576200044083828151811062000427576200042762001953565b6020026020010151600b62000e7f60201b90919060201c565b1562000499578281815181106200045b576200045b62001953565b60200260200101516001600160a01b03167fdf1b1bd32a69711488d71554706bb130b1fc63a5fa1a2cd85e8440f84065ba2360405160405180910390a25b60010162000404565b5060005b81518110156200054457620004e2828281518110620004c957620004c962001953565b6020026020010151600b62000e9660201b90919060201c565b156200053b57818181518110620004fd57620004fd62001953565b60200260200101516001600160a01b03167f1795838dc8ab2ffc5f431a1729a6afa0b587f982f7b2be0b9d7187a1ef547f9160405160405180910390a25b600101620004a6565b505050565b60005b8151811015620006165760008282815181106200056d576200056d62001953565b6020908102919091018101518051818301516001600160a01b0380831660008181526007875260409081902084518154868a018051929096166001600160a81b03199091168117600160a01b60ff9384160217909255825191825293519093169683019690965293955091939092917f08a5f7f5bb38a81d8e43aca13ecd76431dbf8816ae4699affff7b00b2fc1c464910160405180910390a25050508060010190506200054c565b5050565b60005b8151811015620006165760008282815181106200063e576200063e62001953565b6020026020010151905060008383815181106200065f576200065f62001953565b6020026020010151600001519050600082602001519050816001600160401b03166000148062000698575061016081015163ffffffff16155b80620006ba57506101e08101516001600160e01b031916630a04b54b60e21b14155b80620006da5750806060015163ffffffff1681610160015163ffffffff16115b15620007055760405163c35aa79d60e01b81526001600160401b038316600482015260240162000083565b6001600160401b038216600090815260096020526040812060010154600160881b900460e01b6001600160e01b03191690036200078557816001600160401b03167fd31c671936387b2f84ed402b553bd50c0e9c20408ea4e91a836d77b8180fb7248260405162000777919062001969565b60405180910390a2620007c9565b816001600160401b03167f1edd6f3553cfa16f10b95b195abae3a1cfca4783de4843f95d674b1e1df5ab2082604051620007c0919062001969565b60405180910390a25b8060096000846001600160401b03166001600160401b0316815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548161ffff021916908361ffff16021790555060408201518160000160036101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160076101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600b6101000a81548163ffffffff021916908363ffffffff16021790555060a082015181600001600f6101000a81548161ffff021916908361ffff16021790555060c08201518160000160116101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160000160156101000a81548161ffff021916908361ffff1602179055506101008201518160000160176101000a81548161ffff021916908361ffff1602179055506101208201518160000160196101000a81548161ffff021916908361ffff16021790555061014082015181600001601b6101000a81548163ffffffff021916908363ffffffff1602179055506101608201518160010160006101000a81548163ffffffff021916908363ffffffff1602179055506101808201518160010160046101000a8154816001600160401b0302191690836001600160401b031602179055506101a082015181600101600c6101000a81548163ffffffff021916908363ffffffff1602179055506101c08201518160010160106101000a81548160ff0219169083151502179055506101e08201518160010160116101000a81548163ffffffff021916908360e01c02179055509050505050508060010190506200061d565b60005b81518110156200061657600082828151811062000a7e5762000a7e62001953565b6020026020010151600001519050600083838151811062000aa35762000aa362001953565b6020908102919091018101518101516001600160a01b03841660008181526008845260409081902080546001600160401b0319166001600160401b0385169081179091559051908152919350917fbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d910160405180910390a2505060010162000a5d565b60005b825181101562000d9957600083828151811062000b4a5762000b4a62001953565b6020026020010151905060008160000151905060005b82602001515181101562000d8a5760008360200151828151811062000b895762000b8962001953565b602002602001015160200151905060008460200151838151811062000bb25762000bb262001953565b6020026020010151600001519050602063ffffffff16826080015163ffffffff16101562000c115760808201516040516312766e0160e11b81526001600160a01b038316600482015263ffffffff909116602482015260440162000083565b6001600160401b0384166000818152600a602090815260408083206001600160a01b0386168085529083529281902086518154938801518389015160608a015160808b015160a08c01511515600160901b0260ff60901b1963ffffffff928316600160701b021664ffffffffff60701b199383166a01000000000000000000000263ffffffff60501b1961ffff90961668010000000000000000029590951665ffffffffffff60401b19968416640100000000026001600160401b0319909b16939097169290921798909817939093169390931717919091161792909217909155519091907f94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b59062000d77908690600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60405180910390a3505060010162000b60565b50505080600101905062000b29565b5060005b81518110156200054457600082828151811062000dbe5762000dbe62001953565b6020026020010151600001519050600083838151811062000de35762000de362001953565b6020908102919091018101518101516001600160401b0384166000818152600a845260408082206001600160a01b038516808452955280822080546001600160981b03191690555192945090917f4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b9190a3505060010162000d9d565b600062000e76836001600160a01b03841662000ead565b90505b92915050565b600062000e76836001600160a01b03841662000fb1565b600062000e76836001600160a01b03841662001003565b6000818152600183016020526040812054801562000fa657600062000ed460018362001aad565b855490915060009062000eea9060019062001aad565b905081811462000f5657600086600001828154811062000f0e5762000f0e62001953565b906000526020600020015490508087600001848154811062000f345762000f3462001953565b6000918252602080832090910192909255918252600188019052604090208390555b855486908062000f6a5762000f6a62001acf565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505062000e79565b600091505062000e79565b600081815260018301602052604081205462000ffa5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000e79565b50600062000e79565b6000818152600183016020526040812054801562000fa65760006200102a60018362001aad565b8554909150600090620010409060019062001aad565b905080821462000f5657600086600001828154811062000f0e5762000f0e62001953565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b03811182821017156200109f576200109f62001064565b60405290565b60405160c081016001600160401b03811182821017156200109f576200109f62001064565b60405161020081016001600160401b03811182821017156200109f576200109f62001064565b604051601f8201601f191681016001600160401b03811182821017156200111b576200111b62001064565b604052919050565b80516001600160a01b03811681146200113b57600080fd5b919050565b805163ffffffff811681146200113b57600080fd5b6000606082840312156200116857600080fd5b604051606081016001600160401b03811182821017156200118d576200118d62001064565b604052825190915081906001600160601b0381168114620011ad57600080fd5b8152620011bd6020840162001123565b6020820152620011d06040840162001140565b60408201525092915050565b60006001600160401b03821115620011f857620011f862001064565b5060051b60200190565b600082601f8301126200121457600080fd5b815160206200122d6200122783620011dc565b620010f0565b8083825260208201915060208460051b8701019350868411156200125057600080fd5b602086015b848110156200127757620012698162001123565b835291830191830162001255565b509695505050505050565b600082601f8301126200129457600080fd5b81516020620012a76200122783620011dc565b82815260609283028501820192828201919087851115620012c757600080fd5b8387015b858110156200135a5780890382811215620012e65760008081fd5b620012f06200107a565b620012fb8362001123565b8152604080601f1984011215620013125760008081fd5b6200131c6200107a565b92506200132b88850162001123565b835283015160ff81168114620013415760008081fd5b82880152808701919091528452928401928101620012cb565b5090979650505050505050565b80516001600160401b03811681146200113b57600080fd5b805161ffff811681146200113b57600080fd5b805180151581146200113b57600080fd5b600082601f830112620013b557600080fd5b81516020620013c86200122783620011dc565b82815260059290921b84018101918181019086841115620013e857600080fd5b8286015b84811015620012775780516001600160401b03808211156200140d57600080fd5b908801906040601f19838c0381018213156200142857600080fd5b620014326200107a565b6200143f89860162001367565b815282850151848111156200145357600080fd5b8086019550508c603f8601126200146957600080fd5b8885015193506200147e6200122785620011dc565b84815260e09094028501830193898101908e8611156200149d57600080fd5b958401955b858710156200157657868f0360e0811215620014bd57600080fd5b620014c76200107a565b620014d28962001123565b815260c08683011215620014e557600080fd5b620014ef620010a5565b9150620014fe8d8a0162001140565b82526200150d878a0162001140565b8d8301526200151f60608a016200137f565b878301526200153160808a0162001140565b60608301526200154460a08a0162001140565b60808301526200155760c08a0162001392565b60a0830152808d0191909152825260e09690960195908a0190620014a2565b828b015250875250505092840192508301620013ec565b600082601f8301126200159f57600080fd5b81516020620015b26200122783620011dc565b82815260069290921b84018101918181019086841115620015d257600080fd5b8286015b84811015620012775760408189031215620015f15760008081fd5b620015fb6200107a565b620016068262001123565b81526200161585830162001367565b81860152835291830191604001620015d6565b80516001600160e01b0319811681146200113b57600080fd5b600082601f8301126200165357600080fd5b81516020620016666200122783620011dc565b82815261022092830285018201928282019190878511156200168757600080fd5b8387015b858110156200135a5780890382811215620016a65760008081fd5b620016b06200107a565b620016bb8362001367565b815261020080601f1984011215620016d35760008081fd5b620016dd620010ca565b9250620016ec88850162001392565b83526040620016fd8186016200137f565b8985015260606200171081870162001140565b82860152608091506200172582870162001140565b9085015260a06200173886820162001140565b8286015260c091506200174d8287016200137f565b9085015260e06200176086820162001140565b828601526101009150620017768287016200137f565b908501526101206200178a8682016200137f565b828601526101409150620017a08287016200137f565b90850152610160620017b486820162001140565b828601526101809150620017ca82870162001140565b908501526101a0620017de86820162001367565b828601526101c09150620017f482870162001140565b908501526101e06200180886820162001392565b828601526200181983870162001628565b9085015250508087019190915284529284019281016200168b565b6000806000806000806000610120888a0312156200185157600080fd5b6200185d898962001155565b60608901519097506001600160401b03808211156200187b57600080fd5b620018898b838c0162001202565b975060808a0151915080821115620018a057600080fd5b620018ae8b838c0162001202565b965060a08a0151915080821115620018c557600080fd5b620018d38b838c0162001282565b955060c08a0151915080821115620018ea57600080fd5b620018f88b838c01620013a3565b945060e08a01519150808211156200190f57600080fd5b6200191d8b838c016200158d565b93506101008a01519150808211156200193557600080fd5b50620019448a828b0162001641565b91505092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b815115158152610200810160208301516200198a602084018261ffff169052565b506040830151620019a3604084018263ffffffff169052565b506060830151620019bc606084018263ffffffff169052565b506080830151620019d5608084018263ffffffff169052565b5060a0830151620019ec60a084018261ffff169052565b5060c083015162001a0560c084018263ffffffff169052565b5060e083015162001a1c60e084018261ffff169052565b506101008381015161ffff9081169184019190915261012080850151909116908301526101408084015163ffffffff9081169184019190915261016080850151821690840152610180808501516001600160401b0316908401526101a080850151909116908301526101c0808401511515908301526101e0928301516001600160e01b031916929091019190915290565b8181038181111562000e7957634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b60805160a05160c051615c0562001b3f600039600081816102ef015281816121fd01526122660152600081816102b301528181611917015261197701526000818161027f015281816119a00152611a100152615c056000f3fe608060405234801561001057600080fd5b50600436106101ce5760003560e01c806379ba509711610104578063a69c64c0116100a2578063d02641a011610071578063d02641a014610a81578063d8694ccd14610a94578063f2fde38b14610aa7578063ffdb4b3714610aba57600080fd5b8063a69c64c014610997578063bf78e03f146109aa578063c4276bfc14610a57578063cdc73d5114610a7957600080fd5b806382b49eb0116100de57806382b49eb0146107d95780638da5cb5b1461094957806391a2749a146109715780639ea600261461098457600080fd5b806379ba5097146107ab5780637afac322146107b3578063805f2132146107c657600080fd5b8063407e1086116101715780634ab35b0b1161014b5780634ab35b0b14610441578063514e8cff146104815780636def4ce714610524578063770e2dc41461079857600080fd5b8063407e1086146103fb57806341ed29e71461040e57806345ac924d1461042157600080fd5b8063085318f8116101ad578063085318f814610368578063181f5a77146103885780632451a627146103d15780633937306f146103e657600080fd5b806241e5be146101d3578063061877e3146101f957806306285c6914610252575b600080fd5b6101e66101e13660046142bc565b610b02565b6040519081526020015b60405180910390f35b6102396102073660046142f8565b73ffffffffffffffffffffffffffffffffffffffff1660009081526008602052604090205467ffffffffffffffff1690565b60405167ffffffffffffffff90911681526020016101f0565b61031c604080516060810182526000808252602082018190529181019190915260405180606001604052807f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000063ffffffff16815250905090565b6040805182516bffffffffffffffffffffffff16815260208084015173ffffffffffffffffffffffffffffffffffffffff16908201529181015163ffffffff16908201526060016101f0565b61037b610376366004614370565b610b70565b6040516101f09190614482565b6103c46040518060400160405280601381526020017f46656551756f74657220312e362e302d6465760000000000000000000000000081525081565b6040516101f09190614504565b6103d9610ee2565b6040516101f09190614517565b6103f96103f4366004614571565b610ef3565b005b6103f9610409366004614713565b6111a8565b6103f961041c366004614845565b6111bc565b61043461042f366004614980565b6111fe565b6040516101f091906149c2565b61045461044f3660046142f8565b6112c9565b6040517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff90911681526020016101f0565b61051761048f366004614a3d565b60408051808201909152600080825260208201525067ffffffffffffffff166000908152600560209081526040918290208251808401909352547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811683527c0100000000000000000000000000000000000000000000000000000000900463ffffffff169082015290565b6040516101f09190614a58565b61078b610532366004614a3d565b6040805161020081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a081018290526101c081018290526101e08101919091525067ffffffffffffffff908116600090815260096020908152604091829020825161020081018452815460ff8082161515835261ffff61010080840482169685019690965263ffffffff630100000084048116978501979097526701000000000000008304871660608501526b0100000000000000000000008304871660808501526f010000000000000000000000000000008304811660a085015271010000000000000000000000000000000000808404881660c086015275010000000000000000000000000000000000000000008404821660e08087019190915277010000000000000000000000000000000000000000000000850483169786019790975279010000000000000000000000000000000000000000000000000084049091166101208501527b01000000000000000000000000000000000000000000000000000000909204861661014084015260019093015480861661016084015264010000000081049096166101808301526c0100000000000000000000000086049094166101a0820152700100000000000000000000000000000000850490911615156101c08201527fffffffff0000000000000000000000000000000000000000000000000000000092909304901b166101e082015290565b6040516101f09190614a93565b6103f96107a6366004614caa565b6112d4565b6103f96112e6565b6103f96107c1366004614fc4565b6113e3565b6103f96107d436600461506a565b6113f5565b6108e96107e73660046150d6565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101919091525067ffffffffffffffff919091166000908152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff94909416835292815290829020825160c081018452905463ffffffff8082168352640100000000820481169383019390935268010000000000000000810461ffff16938201939093526a01000000000000000000008304821660608201526e01000000000000000000000000000083049091166080820152720100000000000000000000000000000000000090910460ff16151560a082015290565b6040516101f09190600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101f0565b6103f961097f366004615100565b6118dd565b6103f96109923660046151c1565b6118ee565b6103f96109a53660046153ce565b6118ff565b610a236109b83660046142f8565b6040805180820182526000808252602091820181905273ffffffffffffffffffffffffffffffffffffffff93841681526007825282902082518084019093525492831682527401000000000000000000000000000000000000000090920460ff169181019190915290565b60408051825173ffffffffffffffffffffffffffffffffffffffff16815260209283015160ff1692810192909252016101f0565b610a6a610a65366004615493565b611910565b6040516101f093929190615502565b6103d9611b06565b610517610a8f3660046142f8565b611b12565b6101e6610aa2366004615523565b611c0e565b6103f9610ab53660046142f8565b612118565b610acd610ac8366004615578565b612129565b604080517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff9384168152929091166020830152016101f0565b6000610b0d826122b4565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16610b34856122b4565b610b5c907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16856155d1565b610b6691906155e8565b90505b9392505050565b67ffffffffffffffff8086166000908152600960205260409020600101546060917101000000000000000000000000000000000090910460e01b908590811115610bbc57610bbc6145ac565b604051908082528060200260200182016040528015610bef57816020015b6060815260200190600190039081610bda5790505b50915060005b85811015610ed7576000858583818110610c1157610c11615623565b610c2792602060409092020190810191506142f8565b90506000888884818110610c3d57610c3d615623565b9050602002810190610c4f9190615652565b610c5d906040810190615690565b9150506020811115610d125767ffffffffffffffff8a166000908152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff861684529091529020546e010000000000000000000000000000900463ffffffff16811115610d12576040517f36f536ca00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526024015b60405180910390fd5b610d82848a8a86818110610d2857610d28615623565b9050602002810190610d3a9190615652565b610d48906020810190615690565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061234e92505050565b67ffffffffffffffff8a166000818152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684528252808320815160c081018352905463ffffffff8082168352640100000000820481168386015268010000000000000000820461ffff16838501526a01000000000000000000008204811660608401526e010000000000000000000000000000820481166080840152720100000000000000000000000000000000000090910460ff16151560a08301908152958552600990935290832054935190937b0100000000000000000000000000000000000000000000000000000090049091169190610e815781610e87565b82606001515b6040805163ffffffff8316602082015291925001604051602081830303815290604052888781518110610ebc57610ebc615623565b60200260200101819052505050505050806001019050610bf5565b505095945050505050565b6060610eee60026123a5565b905090565b610efb6123b2565b6000610f0782806156f5565b9050905060005b81811015611051576000610f2284806156f5565b83818110610f3257610f32615623565b905060400201803603810190610f489190615789565b604080518082018252602080840180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff908116845263ffffffff42818116858701908152885173ffffffffffffffffffffffffffffffffffffffff9081166000908152600690975295889020965190519092167c010000000000000000000000000000000000000000000000000000000002919092161790935584519051935194955016927f52f50aa6d1a95a4595361ecf953d095f125d442e4673716dede699e049de148a926110409290917bffffffffffffffffffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b60405180910390a250600101610f0e565b50600061106160208401846156f5565b9050905060005b818110156111a257600061107f60208601866156f5565b8381811061108f5761108f615623565b9050604002018036038101906110a591906157c6565b604080518082018252602080840180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff908116845263ffffffff42818116858701908152885167ffffffffffffffff9081166000908152600590975295889020965190519092167c010000000000000000000000000000000000000000000000000000000002919092161790935584519051935194955016927fdd84a3fa9ef9409f550d54d6affec7e9c480c878c6ab27b78912a03e1b371c6e926111919290917bffffffffffffffffffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b60405180910390a250600101611068565b50505050565b6111b06123f7565b6111b981612478565b50565b6111c46123f7565b60005b81518110156111fa576111f28282815181106111e5576111e5615623565b6020026020010151612576565b6001016111c7565b5050565b60608160008167ffffffffffffffff81111561121c5761121c6145ac565b60405190808252806020026020018201604052801561126157816020015b604080518082019091526000808252602082015281526020019060019003908161123a5790505b50905060005b828110156112be5761129986868381811061128457611284615623565b9050602002016020810190610a8f91906142f8565b8282815181106112ab576112ab615623565b6020908102919091010152600101611267565b509150505b92915050565b60006112c3826122b4565b6112dc6123f7565b6111fa8282612748565b60015473ffffffffffffffffffffffffffffffffffffffff163314611367576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610d09565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6113eb6123f7565b6111fa8282612b55565b600080600061143987878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612c9c92505050565b92509250925061144b33838584612cb7565b6000611459858701876157e9565b905060005b81518110156118d25760006007600084848151811061147f5761147f615623565b6020908102919091018101515173ffffffffffffffffffffffffffffffffffffffff16825281019190915260400160009081205474010000000000000000000000000000000000000000900460ff169150819003611540578282815181106114e9576114e9615623565b6020908102919091010151516040517f06439c6b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610d09565b600061158960128386868151811061155a5761155a615623565b6020026020010151602001517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16612e0f565b9050600660008585815181106115a1576115a1615623565b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001601c9054906101000a900463ffffffff1663ffffffff1684848151811061161357611613615623565b60200260200101516040015163ffffffff16101561171d5783838151811061163d5761163d615623565b60200260200101516000015184848151811061165b5761165b615623565b6020026020010151604001516006600087878151811061167d5761167d615623565b6020908102919091018101515173ffffffffffffffffffffffffffffffffffffffff90811683529082019290925260409081016000205490517f191ec70600000000000000000000000000000000000000000000000000000000815293909116600484015263ffffffff91821660248401527c01000000000000000000000000000000000000000000000000000000009004166044820152606401610d09565b6040518060400160405280827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16815260200185858151811061175e5761175e615623565b60200260200101516040015163ffffffff168152506006600086868151811061178957611789615623565b6020908102919091018101515173ffffffffffffffffffffffffffffffffffffffff168252818101929092526040016000208251929091015163ffffffff167c0100000000000000000000000000000000000000000000000000000000027bffffffffffffffffffffffffffffffffffffffffffffffffffffffff909216919091179055835184908490811061182157611821615623565b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff167f52f50aa6d1a95a4595361ecf953d095f125d442e4673716dede699e049de148a8286868151811061187757611877615623565b6020026020010151604001516040516118c09291907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff92909216825263ffffffff16602082015260400190565b60405180910390a2505060010161145e565b505050505050505050565b6118e56123f7565b6111b981612ed5565b6118f66123f7565b6111b981613061565b6119076123f7565b6111b981613507565b60008060607f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff16036119705785925061199e565b61199b87877f0000000000000000000000000000000000000000000000000000000000000000610b02565b92505b7f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff16831115611a3d576040517f6a92a483000000000000000000000000000000000000000000000000000000008152600481018490526bffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166024820152604401610d09565b67ffffffffffffffff881660009081526009602052604081206001015463ffffffff1690611a6c8787846135f1565b9050806020015193508484611af3836040805182516024820152602092830151151560448083019190915282518083039091018152606490910190915290810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f181dcf100000000000000000000000000000000000000000000000000000000017905290565b9450945094505050955095509592505050565b6060610eee600b6123a5565b604080518082019091526000808252602082015273ffffffffffffffffffffffffffffffffffffffff8281166000908152600760209081526040918290208251808401909352549283168083527401000000000000000000000000000000000000000090930460ff169082015290611c0557505073ffffffffffffffffffffffffffffffffffffffff166000908152600660209081526040918290208251808401909352547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811683527c0100000000000000000000000000000000000000000000000000000000900463ffffffff169082015290565b610b698161379a565b67ffffffffffffffff8083166000908152600960209081526040808320815161020081018352815460ff808216151580845261ffff61010080850482169886019890985263ffffffff630100000085048116978601979097526701000000000000008404871660608601526b0100000000000000000000008404871660808601526f010000000000000000000000000000008404811660a086015271010000000000000000000000000000000000808504881660c087015275010000000000000000000000000000000000000000008504821660e08088019190915277010000000000000000000000000000000000000000000000860483169987019990995279010000000000000000000000000000000000000000000000000085049091166101208601527b01000000000000000000000000000000000000000000000000000000909304861661014085015260019094015480861661016085015264010000000081049098166101808401526c0100000000000000000000000088049094166101a0830152700100000000000000000000000000000000870490931615156101c08201527fffffffff000000000000000000000000000000000000000000000000000000009290950490921b166101e0840152909190611e28576040517f99ac52f200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff85166004820152602401610d09565b611e43611e3b60808501606086016142f8565b600b90613929565b611ea257611e5760808401606085016142f8565b6040517f2502348c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610d09565b6000611eb160408501856156f5565b9150611f0d905082611ec66020870187615690565b905083611ed38880615690565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061395892505050565b600080611f29611f2360808801606089016142f8565b88612129565b9092509050600080808515611f6c57611f60878b611f4d60808d0160608e016142f8565b88611f5b60408f018f6156f5565b613a02565b91945092509050611f8c565b6101a0870151611f899063ffffffff16662386f26fc100006155d1565b92505b61010087015160009061ffff1615611fd057611fcd886dffffffffffffffffffffffffffff607088901c16611fc460208e018e615690565b90508a86613cda565b90505b61018088015160009067ffffffffffffffff16611ff9611ff360808e018e615690565b8c613d8a565b600001518563ffffffff168b60a0015161ffff168e806020019061201d9190615690565b6120289291506155d1565b8c6080015163ffffffff1661203d91906158b0565b61204791906158b0565b61205191906158b0565b61206b906dffffffffffffffffffffffffffff89166155d1565b61207591906155d1565b9050867bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168282600860008f60600160208101906120af91906142f8565b73ffffffffffffffffffffffffffffffffffffffff1681526020810191909152604001600020546120ea9067ffffffffffffffff16896155d1565b6120f491906158b0565b6120fe91906158b0565b61210891906155e8565b9c9b505050505050505050505050565b6121206123f7565b6111b981613e4b565b67ffffffffffffffff811660009081526005602090815260408083208151808301909252547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811682527c0100000000000000000000000000000000000000000000000000000000900463ffffffff16918101829052829182036121e1576040517f2e59db3a00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff85166004820152602401610d09565b6000816020015163ffffffff16426121f991906158c3565b90507f000000000000000000000000000000000000000000000000000000000000000063ffffffff1681111561229a576040517ff08bcb3e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8616600482015263ffffffff7f000000000000000000000000000000000000000000000000000000000000000016602482015260448101829052606401610d09565b6122a3866122b4565b9151919350909150505b9250929050565b6000806122c083611b12565b9050806020015163ffffffff16600014806122f8575080517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16155b15612347576040517f06439c6b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152602401610d09565b5192915050565b7fd7ed2ad4000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316016111fa576123a081613f40565b505050565b60606000610b6983613ff3565b6123bd600233613929565b6123f5576040517fd86ad9cf000000000000000000000000000000000000000000000000000000008152336004820152602401610d09565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633146123f5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610d09565b60005b81518110156111fa57600082828151811061249857612498615623565b60209081029190910181015180518183015173ffffffffffffffffffffffffffffffffffffffff80831660008181526007875260409081902084518154868a018051929096167fffffffffffffffffffffff00000000000000000000000000000000000000000090911681177401000000000000000000000000000000000000000060ff9384160217909255825191825293519093169683019690965293955091939092917f08a5f7f5bb38a81d8e43aca13ecd76431dbf8816ae4699affff7b00b2fc1c464910160405180910390a250505080600101905061247b565b600061262f82600001518360600151846020015185604001516040805173ffffffffffffffffffffffffffffffffffffffff80871660208301528516918101919091527fffffffffffffffffffff00000000000000000000000000000000000000000000831660608201527fffff0000000000000000000000000000000000000000000000000000000000008216608082015260009060a001604051602081830303815290604052805190602001209050949350505050565b60808301516000828152600460205260409081902080549215157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00909316929092179091555190915081907f32a4ba3fa3351b11ad555d4c8ec70a744e8705607077a946807030d64b6ab1a39061273c908590600060a08201905073ffffffffffffffffffffffffffffffffffffffff8084511683527fffffffffffffffffffff0000000000000000000000000000000000000000000060208501511660208401527fffff00000000000000000000000000000000000000000000000000000000000060408501511660408401528060608501511660608401525060808301511515608083015292915050565b60405180910390a25050565b60005b8251811015612a7157600083828151811061276857612768615623565b6020026020010151905060008160000151905060005b826020015151811015612a63576000836020015182815181106127a3576127a3615623565b60200260200101516020015190506000846020015183815181106127c9576127c9615623565b6020026020010151600001519050602063ffffffff16826080015163ffffffff16101561284c5760808201516040517f24ecdc0200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8316600482015263ffffffff9091166024820152604401610d09565b67ffffffffffffffff84166000818152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff86168085529083529281902086518154938801518389015160608a015160808b015160a08c015115157201000000000000000000000000000000000000027fffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffff63ffffffff9283166e01000000000000000000000000000002167fffffffffffffffffffffffffff0000000000ffffffffffffffffffffffffffff9383166a0100000000000000000000027fffffffffffffffffffffffffffffffffffff00000000ffffffffffffffffffff61ffff9096166801000000000000000002959095167fffffffffffffffffffffffffffffffffffff000000000000ffffffffffffffff968416640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000909b16939097169290921798909817939093169390931717919091161792909217909155519091907f94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b590612a51908690600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60405180910390a3505060010161277e565b50505080600101905061274b565b5060005b81518110156123a0576000828281518110612a9257612a92615623565b60200260200101516000015190506000838381518110612ab457612ab4615623565b60209081029190910181015181015167ffffffffffffffff84166000818152600a8452604080822073ffffffffffffffffffffffffffffffffffffffff8516808452955280822080547fffffffffffffffffffffffffff000000000000000000000000000000000000001690555192945090917f4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b9190a35050600101612a75565b60005b8251811015612bf857612b8e838281518110612b7657612b76615623565b6020026020010151600b61404f90919063ffffffff16565b15612bf057828181518110612ba557612ba5615623565b602002602001015173ffffffffffffffffffffffffffffffffffffffff167fdf1b1bd32a69711488d71554706bb130b1fc63a5fa1a2cd85e8440f84065ba2360405160405180910390a25b600101612b58565b5060005b81518110156123a057612c32828281518110612c1a57612c1a615623565b6020026020010151600b61407190919063ffffffff16565b15612c9457818181518110612c4957612c49615623565b602002602001015173ffffffffffffffffffffffffffffffffffffffff167f1795838dc8ab2ffc5f431a1729a6afa0b587f982f7b2be0b9d7187a1ef547f9160405160405180910390a25b600101612bfc565b6040810151604a820151605e90920151909260609290921c91565b6040805173ffffffffffffffffffffffffffffffffffffffff868116602080840191909152908616828401527fffffffffffffffffffff00000000000000000000000000000000000000000000851660608301527fffff00000000000000000000000000000000000000000000000000000000000084166080808401919091528351808403909101815260a09092018352815191810191909120600081815260049092529190205460ff16612e08576040517f097e17ff00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8087166004830152851660248201527fffffffffffffffffffff00000000000000000000000000000000000000000000841660448201527fffff00000000000000000000000000000000000000000000000000000000000083166064820152608401610d09565b5050505050565b600080612e1c84866158d6565b9050600060248260ff161115612e5357612e376024836158ef565b612e4290600a615a28565b612e4c90856155e8565b9050612e76565b612e5e8260246158ef565b612e6990600a615a28565b612e7390856155d1565b90505b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811115612ecc576040517f10cb51d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b95945050505050565b602081015160005b8151811015612f70576000828281518110612efa57612efa615623565b60200260200101519050612f1881600261409390919063ffffffff16565b15612f675760405173ffffffffffffffffffffffffffffffffffffffff821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b50600101612edd565b50815160005b81518110156111a2576000828281518110612f9357612f93615623565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603613003576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61300e60028261404f565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a150600101612f76565b60005b81518110156111fa57600082828151811061308157613081615623565b60200260200101519050600083838151811061309f5761309f615623565b60200260200101516000015190506000826020015190508167ffffffffffffffff16600014806130d8575061016081015163ffffffff16155b8061312a57506101e08101517fffffffff00000000000000000000000000000000000000000000000000000000167f2812d52c0000000000000000000000000000000000000000000000000000000014155b806131495750806060015163ffffffff1681610160015163ffffffff16115b1561318c576040517fc35aa79d00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff83166004820152602401610d09565b67ffffffffffffffff821660009081526009602052604081206001015471010000000000000000000000000000000000900460e01b7fffffffff00000000000000000000000000000000000000000000000000000000169003613230578167ffffffffffffffff167fd31c671936387b2f84ed402b553bd50c0e9c20408ea4e91a836d77b8180fb724826040516132239190614a93565b60405180910390a2613273565b8167ffffffffffffffff167f1edd6f3553cfa16f10b95b195abae3a1cfca4783de4843f95d674b1e1df5ab208260405161326a9190614a93565b60405180910390a25b80600960008467ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548161ffff021916908361ffff16021790555060408201518160000160036101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160076101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600b6101000a81548163ffffffff021916908363ffffffff16021790555060a082015181600001600f6101000a81548161ffff021916908361ffff16021790555060c08201518160000160116101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160000160156101000a81548161ffff021916908361ffff1602179055506101008201518160000160176101000a81548161ffff021916908361ffff1602179055506101208201518160000160196101000a81548161ffff021916908361ffff16021790555061014082015181600001601b6101000a81548163ffffffff021916908363ffffffff1602179055506101608201518160010160006101000a81548163ffffffff021916908363ffffffff1602179055506101808201518160010160046101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506101a082015181600101600c6101000a81548163ffffffff021916908363ffffffff1602179055506101c08201518160010160106101000a81548160ff0219169083151502179055506101e08201518160010160116101000a81548163ffffffff021916908360e01c0217905550905050505050806001019050613064565b60005b81518110156111fa57600082828151811061352757613527615623565b6020026020010151600001519050600083838151811061354957613549615623565b60209081029190910181015181015173ffffffffffffffffffffffffffffffffffffffff841660008181526008845260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff85169081179091559051908152919350917fbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d910160405180910390a2505060010161350a565b6040805180820190915260008082526020820152600083900361363257506040805180820190915267ffffffffffffffff8216815260006020820152610b69565b600061363e8486615a37565b9050600061364f8560048189615a7d565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505050507fffffffff0000000000000000000000000000000000000000000000000000000082167fe7e230f000000000000000000000000000000000000000000000000000000000016136ec57808060200190518101906136e39190615aa7565b92505050610b69565b7f6859a837000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831601613768576040518060400160405280828060200190518101906137549190615ad3565b815260006020909101529250610b69915050565b6040517f5247fdce00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080518082019091526000808252602082015260008260000151905060008173ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015613804573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138289190615b06565b5050509150506000811215613869576040517f10cb51d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006138e88373ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156138b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138dd9190615b56565b866020015184612e0f565b604080518082019091527bffffffffffffffffffffffffffffffffffffffffffffffffffffffff909116815263ffffffff4216602082015295945050505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515610b69565b836040015163ffffffff168311156139b15760408085015190517f8693378900000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015260248101849052604401610d09565b836020015161ffff168211156139f3576040517f4c056b6a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6111a2846101e001518261234e565b6000808083815b81811015613ccc576000878783818110613a2557613a25615623565b905060400201803603810190613a3b9190615b73565b67ffffffffffffffff8c166000908152600a60209081526040808320845173ffffffffffffffffffffffffffffffffffffffff168452825291829020825160c081018452905463ffffffff8082168352640100000000820481169383019390935268010000000000000000810461ffff16938201939093526a01000000000000000000008304821660608201526e01000000000000000000000000000083049091166080820152720100000000000000000000000000000000000090910460ff16151560a0820181905291925090613b5b576101208d0151613b289061ffff16662386f26fc100006155d1565b613b3290886158b0565b96508c610140015186613b459190615bac565b9550613b52602086615bac565b94505050613cc4565b604081015160009061ffff1615613c145760008c73ffffffffffffffffffffffffffffffffffffffff16846000015173ffffffffffffffffffffffffffffffffffffffff1614613bb7578351613bb0906122b4565b9050613bba565b508a5b620186a0836040015161ffff16613bfc8660200151847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166140b590919063ffffffff16565b613c0691906155d1565b613c1091906155e8565b9150505b6060820151613c239088615bac565b9650816080015186613c359190615bac565b8251909650600090613c549063ffffffff16662386f26fc100006155d1565b905080821015613c7357613c68818a6158b0565b985050505050613cc4565b6000836020015163ffffffff16662386f26fc10000613c9291906155d1565b905080831115613cb257613ca6818b6158b0565b99505050505050613cc4565b613cbc838b6158b0565b995050505050505b600101613a09565b505096509650969350505050565b60008063ffffffff8316613cf0610160866155d1565b613cfc876101c06158b0565b613d0691906158b0565b613d1091906158b0565b905060008760c0015163ffffffff168860e0015161ffff1683613d3391906155d1565b613d3d91906158b0565b61010089015190915061ffff16613d646dffffffffffffffffffffffffffff8916836155d1565b613d6e91906155d1565b613d7e90655af3107a40006155d1565b98975050505050505050565b60408051808201909152600080825260208201526000613db6858585610160015163ffffffff166135f1565b9050826060015163ffffffff1681600001511115613e00576040517f4c4fc93a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b826101c001518015613e1457508060200151155b15610b66576040517fee433e9900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff821603613eca576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610d09565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60008151602014613f7f57816040517f8d666f60000000000000000000000000000000000000000000000000000000008152600401610d099190614504565b600082806020019051810190613f959190615ad3565b905073ffffffffffffffffffffffffffffffffffffffff811180613fba575061040081105b156112c357826040517f8d666f60000000000000000000000000000000000000000000000000000000008152600401610d099190614504565b60608160000180548060200260200160405190810160405280929190818152602001828054801561404357602002820191906000526020600020905b81548152602001906001019080831161402f575b50505050509050919050565b6000610b698373ffffffffffffffffffffffffffffffffffffffff84166140f2565b6000610b698373ffffffffffffffffffffffffffffffffffffffff8416614141565b6000610b698373ffffffffffffffffffffffffffffffffffffffff841661423b565b6000670de0b6b3a76400006140e8837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff86166155d1565b610b6991906155e8565b6000818152600183016020526040812054614139575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556112c3565b5060006112c3565b6000818152600183016020526040812054801561422a5760006141656001836158c3565b8554909150600090614179906001906158c3565b90508082146141de57600086600001828154811061419957614199615623565b90600052602060002001549050808760000184815481106141bc576141bc615623565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806141ef576141ef615bc9565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506112c3565b60009150506112c3565b5092915050565b6000818152600183016020526040812054801561422a57600061425f6001836158c3565b8554909150600090614273906001906158c3565b90508181146141de57600086600001828154811061419957614199615623565b803573ffffffffffffffffffffffffffffffffffffffff811681146142b757600080fd5b919050565b6000806000606084860312156142d157600080fd5b6142da84614293565b9250602084013591506142ef60408501614293565b90509250925092565b60006020828403121561430a57600080fd5b610b6982614293565b803567ffffffffffffffff811681146142b757600080fd5b60008083601f84011261433d57600080fd5b50813567ffffffffffffffff81111561435557600080fd5b6020830191508360208260051b85010111156122ad57600080fd5b60008060008060006060868803121561438857600080fd5b61439186614313565b9450602086013567ffffffffffffffff808211156143ae57600080fd5b6143ba89838a0161432b565b909650945060408801359150808211156143d357600080fd5b818801915088601f8301126143e757600080fd5b8135818111156143f657600080fd5b8960208260061b850101111561440b57600080fd5b9699959850939650602001949392505050565b6000815180845260005b8181101561444457602081850181015186830182015201614428565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b828110156144f7577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526144e585835161441e565b945092850192908501906001016144ab565b5092979650505050505050565b602081526000610b69602083018461441e565b6020808252825182820181905260009190848201906040850190845b8181101561456557835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101614533565b50909695505050505050565b60006020828403121561458357600080fd5b813567ffffffffffffffff81111561459a57600080fd5b820160408185031215610b6957600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff811182821017156145fe576145fe6145ac565b60405290565b60405160a0810167ffffffffffffffff811182821017156145fe576145fe6145ac565b60405160c0810167ffffffffffffffff811182821017156145fe576145fe6145ac565b604051610200810167ffffffffffffffff811182821017156145fe576145fe6145ac565b6040516060810167ffffffffffffffff811182821017156145fe576145fe6145ac565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156146d8576146d86145ac565b604052919050565b600067ffffffffffffffff8211156146fa576146fa6145ac565b5060051b60200190565b60ff811681146111b957600080fd5b6000602080838503121561472657600080fd5b823567ffffffffffffffff81111561473d57600080fd5b8301601f8101851361474e57600080fd5b803561476161475c826146e0565b614691565b8181526060918202830184019184820191908884111561478057600080fd5b938501935b83851015614820578489038181121561479e5760008081fd5b6147a66145db565b6147af87614293565b81526040807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0840112156147e35760008081fd5b6147eb6145db565b92506147f8898901614293565b835287013561480681614704565b828901528088019190915283529384019391850191614785565b50979650505050505050565b80151581146111b957600080fd5b80356142b78161482c565b6000602080838503121561485857600080fd5b823567ffffffffffffffff81111561486f57600080fd5b8301601f8101851361488057600080fd5b803561488e61475c826146e0565b81815260a091820283018401918482019190888411156148ad57600080fd5b938501935b838510156148205780858a0312156148ca5760008081fd5b6148d2614604565b6148db86614293565b8152868601357fffffffffffffffffffff00000000000000000000000000000000000000000000811681146149105760008081fd5b818801526040868101357fffff000000000000000000000000000000000000000000000000000000000000811681146149495760008081fd5b90820152606061495a878201614293565b9082015260808681013561496d8161482c565b90820152835293840193918501916148b2565b6000806020838503121561499357600080fd5b823567ffffffffffffffff8111156149aa57600080fd5b6149b68582860161432b565b90969095509350505050565b602080825282518282018190526000919060409081850190868401855b82811015614a3057614a2084835180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16825260209081015163ffffffff16910152565b92840192908501906001016149df565b5091979650505050505050565b600060208284031215614a4f57600080fd5b610b6982614313565b81517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16815260208083015163ffffffff1690820152604081016112c3565b81511515815261020081016020830151614ab3602084018261ffff169052565b506040830151614acb604084018263ffffffff169052565b506060830151614ae3606084018263ffffffff169052565b506080830151614afb608084018263ffffffff169052565b5060a0830151614b1160a084018261ffff169052565b5060c0830151614b2960c084018263ffffffff169052565b5060e0830151614b3f60e084018261ffff169052565b506101008381015161ffff9081169184019190915261012080850151909116908301526101408084015163ffffffff90811691840191909152610160808501518216908401526101808085015167ffffffffffffffff16908401526101a080850151909116908301526101c0808401511515908301526101e0808401517fffffffff000000000000000000000000000000000000000000000000000000008116828501525b505092915050565b803563ffffffff811681146142b757600080fd5b803561ffff811681146142b757600080fd5b600082601f830112614c2357600080fd5b81356020614c3361475c836146e0565b82815260069290921b84018101918181019086841115614c5257600080fd5b8286015b84811015614c9f5760408189031215614c6f5760008081fd5b614c776145db565b614c8082614313565b8152614c8d858301614293565b81860152835291830191604001614c56565b509695505050505050565b60008060408385031215614cbd57600080fd5b67ffffffffffffffff83351115614cd357600080fd5b83601f843585010112614ce557600080fd5b614cf561475c84358501356146e0565b8335840180358083526020808401939260059290921b90910101861015614d1b57600080fd5b602085358601015b85358601803560051b01602001811015614f285767ffffffffffffffff81351115614d4d57600080fd5b8035863587010160407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0828a03011215614d8657600080fd5b614d8e6145db565b614d9a60208301614313565b815267ffffffffffffffff60408301351115614db557600080fd5b88603f604084013584010112614dca57600080fd5b614de061475c60206040850135850101356146e0565b6020604084810135850182810135808552928401939260e00201018b1015614e0757600080fd5b6040808501358501015b6040858101358601602081013560e0020101811015614f095760e0818d031215614e3a57600080fd5b614e426145db565b614e4b82614293565b815260c07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0838f03011215614e7f57600080fd5b614e87614627565b614e9360208401614bec565b8152614ea160408401614bec565b6020820152614eb260608401614c00565b6040820152614ec360808401614bec565b6060820152614ed460a08401614bec565b6080820152614ee660c084013561482c565b60c083013560a0820152602082810191909152908452929092019160e001614e11565b5080602084015250508085525050602083019250602081019050614d23565b5092505067ffffffffffffffff60208401351115614f4557600080fd5b614f558460208501358501614c12565b90509250929050565b600082601f830112614f6f57600080fd5b81356020614f7f61475c836146e0565b8083825260208201915060208460051b870101935086841115614fa157600080fd5b602086015b84811015614c9f57614fb781614293565b8352918301918301614fa6565b60008060408385031215614fd757600080fd5b823567ffffffffffffffff80821115614fef57600080fd5b614ffb86838701614f5e565b9350602085013591508082111561501157600080fd5b5061501e85828601614f5e565b9150509250929050565b60008083601f84011261503a57600080fd5b50813567ffffffffffffffff81111561505257600080fd5b6020830191508360208285010111156122ad57600080fd5b6000806000806040858703121561508057600080fd5b843567ffffffffffffffff8082111561509857600080fd5b6150a488838901615028565b909650945060208701359150808211156150bd57600080fd5b506150ca87828801615028565b95989497509550505050565b600080604083850312156150e957600080fd5b6150f283614313565b9150614f5560208401614293565b60006020828403121561511257600080fd5b813567ffffffffffffffff8082111561512a57600080fd5b908301906040828603121561513e57600080fd5b6151466145db565b82358281111561515557600080fd5b61516187828601614f5e565b82525060208301358281111561517657600080fd5b61518287828601614f5e565b60208301525095945050505050565b80357fffffffff00000000000000000000000000000000000000000000000000000000811681146142b757600080fd5b600060208083850312156151d457600080fd5b823567ffffffffffffffff8111156151eb57600080fd5b8301601f810185136151fc57600080fd5b803561520a61475c826146e0565b818152610220918202830184019184820191908884111561522a57600080fd5b938501935b8385101561482057848903818112156152485760008081fd5b6152506145db565b61525987614313565b8152610200807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08401121561528e5760008081fd5b61529661464a565b92506152a389890161483a565b835260406152b2818a01614c00565b8a85015260606152c3818b01614bec565b82860152608091506152d6828b01614bec565b9085015260a06152e78a8201614bec565b8286015260c091506152fa828b01614c00565b9085015260e061530b8a8201614bec565b82860152610100915061531f828b01614c00565b908501526101206153318a8201614c00565b828601526101409150615345828b01614c00565b908501526101606153578a8201614bec565b82860152610180915061536b828b01614bec565b908501526101a061537d8a8201614313565b828601526101c09150615391828b01614bec565b908501526101e06153a38a820161483a565b828601526153b2838b01615191565b908501525050808801919091528352938401939185019161522f565b600060208083850312156153e157600080fd5b823567ffffffffffffffff8111156153f857600080fd5b8301601f8101851361540957600080fd5b803561541761475c826146e0565b81815260069190911b8201830190838101908783111561543657600080fd5b928401925b8284101561548857604084890312156154545760008081fd5b61545c6145db565b61546585614293565b8152615472868601614313565b818701528252604093909301929084019061543b565b979650505050505050565b6000806000806000608086880312156154ab57600080fd5b6154b486614313565b94506154c260208701614293565b935060408601359250606086013567ffffffffffffffff8111156154e557600080fd5b6154f188828901615028565b969995985093965092949392505050565b8381528215156020820152606060408201526000612ecc606083018461441e565b6000806040838503121561553657600080fd5b61553f83614313565b9150602083013567ffffffffffffffff81111561555b57600080fd5b830160a0818603121561556d57600080fd5b809150509250929050565b6000806040838503121561558b57600080fd5b61559483614293565b9150614f5560208401614313565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80820281158282048414176112c3576112c36155a2565b60008261561e577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6183360301811261568657600080fd5b9190910192915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126156c557600080fd5b83018035915067ffffffffffffffff8211156156e057600080fd5b6020019150368190038213156122ad57600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261572a57600080fd5b83018035915067ffffffffffffffff82111561574557600080fd5b6020019150600681901b36038213156122ad57600080fd5b80357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811681146142b757600080fd5b60006040828403121561579b57600080fd5b6157a36145db565b6157ac83614293565b81526157ba6020840161575d565b60208201529392505050565b6000604082840312156157d857600080fd5b6157e06145db565b6157ac83614313565b600060208083850312156157fc57600080fd5b823567ffffffffffffffff81111561581357600080fd5b8301601f8101851361582457600080fd5b803561583261475c826146e0565b8181526060918202830184019184820191908884111561585157600080fd5b938501935b838510156148205780858a03121561586e5760008081fd5b61587661466e565b61587f86614293565b815261588c87870161575d565b87820152604061589d818801614bec565b9082015283529384019391850191615856565b808201808211156112c3576112c36155a2565b818103818111156112c3576112c36155a2565b60ff81811683821601908111156112c3576112c36155a2565b60ff82811682821603908111156112c3576112c36155a2565b600181815b8085111561596157817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115615947576159476155a2565b8085161561595457918102915b93841c939080029061590d565b509250929050565b600082615978575060016112c3565b81615985575060006112c3565b816001811461599b57600281146159a5576159c1565b60019150506112c3565b60ff8411156159b6576159b66155a2565b50506001821b6112c3565b5060208310610133831016604e8410600b84101617156159e4575081810a6112c3565b6159ee8383615908565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115615a2057615a206155a2565b029392505050565b6000610b6960ff841683615969565b7fffffffff000000000000000000000000000000000000000000000000000000008135818116916004851015614be45760049490940360031b84901b1690921692915050565b60008085851115615a8d57600080fd5b83861115615a9a57600080fd5b5050820193919092039150565b600060408284031215615ab957600080fd5b615ac16145db565b8251815260208301516157ba8161482c565b600060208284031215615ae557600080fd5b5051919050565b805169ffffffffffffffffffff811681146142b757600080fd5b600080600080600060a08688031215615b1e57600080fd5b615b2786615aec565b9450602086015193506040860151925060608601519150615b4a60808701615aec565b90509295509295909350565b600060208284031215615b6857600080fd5b8151610b6981614704565b600060408284031215615b8557600080fd5b615b8d6145db565b615b9683614293565b8152602083013560208201528091505092915050565b63ffffffff818116838216019080821115614234576142346155a2565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint96\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"linkToken\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"stalenessThreshold\",\"type\":\"uint32\"}],\"internalType\":\"structFeeQuoter.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"priceUpdaters\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"feeTokens\",\"type\":\"address[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"}],\"internalType\":\"structIFeeQuoter.TokenPriceFeedConfig\",\"name\":\"feedConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.TokenPriceFeedUpdate[]\",\"name\":\"tokenPriceFeeds\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigSingleTokenArgs[]\",\"name\":\"tokenTransferFeeConfigs\",\"type\":\"tuple[]\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigArgs[]\",\"name\":\"tokenTransferFeeConfigArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"internalType\":\"structFeeQuoter.PremiumMultiplierWeiPerEthArgs[]\",\"name\":\"premiumMultiplierWeiPerEthArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chain\",\"type\":\"uint64\"}],\"name\":\"ChainNotSupported\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DataFeedValueOutOfUint224Range\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"DestinationChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ExtraArgOutOfOrderExecutionMustBeTrue\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"FeeTokenNotSupported\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"}],\"name\":\"InvalidDestBytesOverhead\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidDestChainConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidEVMAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidExtraArgsTag\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidStaticConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"msgFeeJuels\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint256\"}],\"name\":\"MessageFeeTooHigh\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MessageGasLimitTooHigh\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"maxSize\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualSize\",\"type\":\"uint256\"}],\"name\":\"MessageTooLarge\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"internalType\":\"bytes10\",\"name\":\"workflowName\",\"type\":\"bytes10\"},{\"internalType\":\"bytes2\",\"name\":\"reportName\",\"type\":\"bytes2\"}],\"name\":\"ReportForwarderUnauthorized\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"SourceTokenDataTooLarge\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"threshold\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timePassed\",\"type\":\"uint256\"}],\"name\":\"StaleGasPrice\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feedTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"storedTimeStamp\",\"type\":\"uint256\"}],\"name\":\"StaleKeystoneUpdate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"TokenNotSupported\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"UnauthorizedCaller\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnsupportedNumberOfTokens\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"AuthorizedCallerAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"AuthorizedCallerRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"indexed\":false,\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"name\":\"DestChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"indexed\":false,\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"name\":\"DestChainConfigUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"}],\"name\":\"FeeTokenAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"}],\"name\":\"FeeTokenRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"name\":\"PremiumMultiplierWeiPerEthUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"}],\"indexed\":false,\"internalType\":\"structIFeeQuoter.TokenPriceFeedConfig\",\"name\":\"priceFeedConfig\",\"type\":\"tuple\"}],\"name\":\"PriceFeedPerTokenUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"reportId\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"},{\"internalType\":\"bytes10\",\"name\":\"workflowName\",\"type\":\"bytes10\"},{\"internalType\":\"bytes2\",\"name\":\"reportName\",\"type\":\"bytes2\"},{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isAllowed\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"structKeystoneFeedsPermissionHandler.Permission\",\"name\":\"permission\",\"type\":\"tuple\"}],\"name\":\"ReportPermissionSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"TokenTransferFeeConfigDeleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"name\":\"TokenTransferFeeConfigUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"UsdPerTokenUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChain\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"UsdPerUnitGasUpdated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"FEE_BASE_DECIMALS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"KEYSTONE_PRICE_DECIMALS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address[]\",\"name\":\"addedCallers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"removedCallers\",\"type\":\"address[]\"}],\"internalType\":\"structAuthorizedCallers.AuthorizedCallerArgs\",\"name\":\"authorizedCallerArgs\",\"type\":\"tuple\"}],\"name\":\"applyAuthorizedCallerUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyDestChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"feeTokensToAdd\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"feeTokensToRemove\",\"type\":\"address[]\"}],\"name\":\"applyFeeTokensUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"internalType\":\"structFeeQuoter.PremiumMultiplierWeiPerEthArgs[]\",\"name\":\"premiumMultiplierWeiPerEthArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyPremiumMultiplierWeiPerEthUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigSingleTokenArgs[]\",\"name\":\"tokenTransferFeeConfigs\",\"type\":\"tuple[]\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigArgs[]\",\"name\":\"tokenTransferFeeConfigArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigRemoveArgs[]\",\"name\":\"tokensToUseDefaultFeeConfigs\",\"type\":\"tuple[]\"}],\"name\":\"applyTokenTransferFeeConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"fromToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fromTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"toToken\",\"type\":\"address\"}],\"name\":\"convertTokenAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllAuthorizedCallers\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getDestChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getDestinationChainGasPrice\",\"outputs\":[{\"components\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"internalType\":\"structInternal.TimestampedPackedUint224\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getFeeTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getPremiumMultiplierWeiPerEth\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint96\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"linkToken\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"stalenessThreshold\",\"type\":\"uint32\"}],\"internalType\":\"structFeeQuoter.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getTokenAndGasPrices\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"tokenPrice\",\"type\":\"uint224\"},{\"internalType\":\"uint224\",\"name\":\"gasPriceValue\",\"type\":\"uint224\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenPrice\",\"outputs\":[{\"components\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"internalType\":\"structInternal.TimestampedPackedUint224\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenPriceFeedConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"}],\"internalType\":\"structIFeeQuoter.TokenPriceFeedConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"tokens\",\"type\":\"address[]\"}],\"name\":\"getTokenPrices\",\"outputs\":[{\"components\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"internalType\":\"structInternal.TimestampedPackedUint224[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenTransferFeeConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"getValidatedFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getValidatedTokenPrice\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"\",\"type\":\"uint224\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"onReport\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"name\":\"processMessageArgs\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"msgFeeJuels\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isOutOfOrderExecution\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"convertedExtraArgs\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"rampTokenAmounts\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"sourceTokenAmounts\",\"type\":\"tuple[]\"}],\"name\":\"processPoolReturnData\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"destExecDataPerToken\",\"type\":\"bytes[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"},{\"internalType\":\"bytes10\",\"name\":\"workflowName\",\"type\":\"bytes10\"},{\"internalType\":\"bytes2\",\"name\":\"reportName\",\"type\":\"bytes2\"},{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isAllowed\",\"type\":\"bool\"}],\"internalType\":\"structKeystoneFeedsPermissionHandler.Permission[]\",\"name\":\"permissions\",\"type\":\"tuple[]\"}],\"name\":\"setReportPermissions\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"}],\"name\":\"updatePrices\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"}],\"internalType\":\"structIFeeQuoter.TokenPriceFeedConfig\",\"name\":\"feedConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.TokenPriceFeedUpdate[]\",\"name\":\"tokenPriceFeedUpdates\",\"type\":\"tuple[]\"}],\"name\":\"updateTokenPriceFeeds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x60e06040523480156200001157600080fd5b506040516200775438038062007754833981016040819052620000349162001834565b8533806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf8162000207565b5050604080518082018252838152815160008152602080820190935291810191909152620000ee9150620002b2565b5060208701516001600160a01b0316158062000112575086516001600160601b0316155b80620001265750604087015163ffffffff16155b15620001455760405163d794ef9560e01b815260040160405180910390fd5b6020878101516001600160a01b031660a05287516001600160601b031660805260408089015163ffffffff1660c05280516000815291820190526200018c90869062000401565b620001978462000549565b620001a2816200061a565b620001ad8262000a5a565b60408051600080825260208201909252620001fa91859190620001f3565b6040805180820190915260008082526020820152815260200190600190039081620001cb5790505b5062000b26565b5050505050505062001ae5565b336001600160a01b03821603620002615760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b602081015160005b815181101562000342576000828281518110620002db57620002db62001953565b60209081029190910101519050620002f560028262000e5f565b1562000338576040516001600160a01b03821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b50600101620002ba565b50815160005b8151811015620003fb57600082828151811062000369576200036962001953565b6020026020010151905060006001600160a01b0316816001600160a01b031603620003a7576040516342bcdf7f60e11b815260040160405180910390fd5b620003b460028262000e7f565b506040516001600160a01b03821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a15060010162000348565b50505050565b60005b8251811015620004a2576200044083828151811062000427576200042762001953565b6020026020010151600b62000e7f60201b90919060201c565b1562000499578281815181106200045b576200045b62001953565b60200260200101516001600160a01b03167fdf1b1bd32a69711488d71554706bb130b1fc63a5fa1a2cd85e8440f84065ba2360405160405180910390a25b60010162000404565b5060005b81518110156200054457620004e2828281518110620004c957620004c962001953565b6020026020010151600b62000e9660201b90919060201c565b156200053b57818181518110620004fd57620004fd62001953565b60200260200101516001600160a01b03167f1795838dc8ab2ffc5f431a1729a6afa0b587f982f7b2be0b9d7187a1ef547f9160405160405180910390a25b600101620004a6565b505050565b60005b8151811015620006165760008282815181106200056d576200056d62001953565b6020908102919091018101518051818301516001600160a01b0380831660008181526007875260409081902084518154868a018051929096166001600160a81b03199091168117600160a01b60ff9384160217909255825191825293519093169683019690965293955091939092917f08a5f7f5bb38a81d8e43aca13ecd76431dbf8816ae4699affff7b00b2fc1c464910160405180910390a25050508060010190506200054c565b5050565b60005b8151811015620006165760008282815181106200063e576200063e62001953565b6020026020010151905060008383815181106200065f576200065f62001953565b6020026020010151600001519050600082602001519050816001600160401b03166000148062000698575061016081015163ffffffff16155b80620006ba57506101e08101516001600160e01b031916630a04b54b60e21b14155b80620006da5750806060015163ffffffff1681610160015163ffffffff16115b15620007055760405163c35aa79d60e01b81526001600160401b038316600482015260240162000083565b6001600160401b038216600090815260096020526040812060010154600160881b900460e01b6001600160e01b03191690036200078557816001600160401b03167fd31c671936387b2f84ed402b553bd50c0e9c20408ea4e91a836d77b8180fb7248260405162000777919062001969565b60405180910390a2620007c9565b816001600160401b03167f1edd6f3553cfa16f10b95b195abae3a1cfca4783de4843f95d674b1e1df5ab2082604051620007c0919062001969565b60405180910390a25b8060096000846001600160401b03166001600160401b0316815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548161ffff021916908361ffff16021790555060408201518160000160036101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160076101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600b6101000a81548163ffffffff021916908363ffffffff16021790555060a082015181600001600f6101000a81548161ffff021916908361ffff16021790555060c08201518160000160116101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160000160156101000a81548161ffff021916908361ffff1602179055506101008201518160000160176101000a81548161ffff021916908361ffff1602179055506101208201518160000160196101000a81548161ffff021916908361ffff16021790555061014082015181600001601b6101000a81548163ffffffff021916908363ffffffff1602179055506101608201518160010160006101000a81548163ffffffff021916908363ffffffff1602179055506101808201518160010160046101000a8154816001600160401b0302191690836001600160401b031602179055506101a082015181600101600c6101000a81548163ffffffff021916908363ffffffff1602179055506101c08201518160010160106101000a81548160ff0219169083151502179055506101e08201518160010160116101000a81548163ffffffff021916908360e01c02179055509050505050508060010190506200061d565b60005b81518110156200061657600082828151811062000a7e5762000a7e62001953565b6020026020010151600001519050600083838151811062000aa35762000aa362001953565b6020908102919091018101518101516001600160a01b03841660008181526008845260409081902080546001600160401b0319166001600160401b0385169081179091559051908152919350917fbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d910160405180910390a2505060010162000a5d565b60005b825181101562000d9957600083828151811062000b4a5762000b4a62001953565b6020026020010151905060008160000151905060005b82602001515181101562000d8a5760008360200151828151811062000b895762000b8962001953565b602002602001015160200151905060008460200151838151811062000bb25762000bb262001953565b6020026020010151600001519050602063ffffffff16826080015163ffffffff16101562000c115760808201516040516312766e0160e11b81526001600160a01b038316600482015263ffffffff909116602482015260440162000083565b6001600160401b0384166000818152600a602090815260408083206001600160a01b0386168085529083529281902086518154938801518389015160608a015160808b015160a08c01511515600160901b0260ff60901b1963ffffffff928316600160701b021664ffffffffff60701b199383166a01000000000000000000000263ffffffff60501b1961ffff90961668010000000000000000029590951665ffffffffffff60401b19968416640100000000026001600160401b0319909b16939097169290921798909817939093169390931717919091161792909217909155519091907f94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b59062000d77908690600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60405180910390a3505060010162000b60565b50505080600101905062000b29565b5060005b81518110156200054457600082828151811062000dbe5762000dbe62001953565b6020026020010151600001519050600083838151811062000de35762000de362001953565b6020908102919091018101518101516001600160401b0384166000818152600a845260408082206001600160a01b038516808452955280822080546001600160981b03191690555192945090917f4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b9190a3505060010162000d9d565b600062000e76836001600160a01b03841662000ead565b90505b92915050565b600062000e76836001600160a01b03841662000fb1565b600062000e76836001600160a01b03841662001003565b6000818152600183016020526040812054801562000fa657600062000ed460018362001aad565b855490915060009062000eea9060019062001aad565b905081811462000f5657600086600001828154811062000f0e5762000f0e62001953565b906000526020600020015490508087600001848154811062000f345762000f3462001953565b6000918252602080832090910192909255918252600188019052604090208390555b855486908062000f6a5762000f6a62001acf565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505062000e79565b600091505062000e79565b600081815260018301602052604081205462000ffa5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000e79565b50600062000e79565b6000818152600183016020526040812054801562000fa65760006200102a60018362001aad565b8554909150600090620010409060019062001aad565b905080821462000f5657600086600001828154811062000f0e5762000f0e62001953565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b03811182821017156200109f576200109f62001064565b60405290565b60405160c081016001600160401b03811182821017156200109f576200109f62001064565b60405161020081016001600160401b03811182821017156200109f576200109f62001064565b604051601f8201601f191681016001600160401b03811182821017156200111b576200111b62001064565b604052919050565b80516001600160a01b03811681146200113b57600080fd5b919050565b805163ffffffff811681146200113b57600080fd5b6000606082840312156200116857600080fd5b604051606081016001600160401b03811182821017156200118d576200118d62001064565b604052825190915081906001600160601b0381168114620011ad57600080fd5b8152620011bd6020840162001123565b6020820152620011d06040840162001140565b60408201525092915050565b60006001600160401b03821115620011f857620011f862001064565b5060051b60200190565b600082601f8301126200121457600080fd5b815160206200122d6200122783620011dc565b620010f0565b8083825260208201915060208460051b8701019350868411156200125057600080fd5b602086015b848110156200127757620012698162001123565b835291830191830162001255565b509695505050505050565b600082601f8301126200129457600080fd5b81516020620012a76200122783620011dc565b82815260609283028501820192828201919087851115620012c757600080fd5b8387015b858110156200135a5780890382811215620012e65760008081fd5b620012f06200107a565b620012fb8362001123565b8152604080601f1984011215620013125760008081fd5b6200131c6200107a565b92506200132b88850162001123565b835283015160ff81168114620013415760008081fd5b82880152808701919091528452928401928101620012cb565b5090979650505050505050565b80516001600160401b03811681146200113b57600080fd5b805161ffff811681146200113b57600080fd5b805180151581146200113b57600080fd5b600082601f830112620013b557600080fd5b81516020620013c86200122783620011dc565b82815260059290921b84018101918181019086841115620013e857600080fd5b8286015b84811015620012775780516001600160401b03808211156200140d57600080fd5b908801906040601f19838c0381018213156200142857600080fd5b620014326200107a565b6200143f89860162001367565b815282850151848111156200145357600080fd5b8086019550508c603f8601126200146957600080fd5b8885015193506200147e6200122785620011dc565b84815260e09094028501830193898101908e8611156200149d57600080fd5b958401955b858710156200157657868f0360e0811215620014bd57600080fd5b620014c76200107a565b620014d28962001123565b815260c08683011215620014e557600080fd5b620014ef620010a5565b9150620014fe8d8a0162001140565b82526200150d878a0162001140565b8d8301526200151f60608a016200137f565b878301526200153160808a0162001140565b60608301526200154460a08a0162001140565b60808301526200155760c08a0162001392565b60a0830152808d0191909152825260e09690960195908a0190620014a2565b828b015250875250505092840192508301620013ec565b600082601f8301126200159f57600080fd5b81516020620015b26200122783620011dc565b82815260069290921b84018101918181019086841115620015d257600080fd5b8286015b84811015620012775760408189031215620015f15760008081fd5b620015fb6200107a565b620016068262001123565b81526200161585830162001367565b81860152835291830191604001620015d6565b80516001600160e01b0319811681146200113b57600080fd5b600082601f8301126200165357600080fd5b81516020620016666200122783620011dc565b82815261022092830285018201928282019190878511156200168757600080fd5b8387015b858110156200135a5780890382811215620016a65760008081fd5b620016b06200107a565b620016bb8362001367565b815261020080601f1984011215620016d35760008081fd5b620016dd620010ca565b9250620016ec88850162001392565b83526040620016fd8186016200137f565b8985015260606200171081870162001140565b82860152608091506200172582870162001140565b9085015260a06200173886820162001140565b8286015260c091506200174d8287016200137f565b9085015260e06200176086820162001140565b828601526101009150620017768287016200137f565b908501526101206200178a8682016200137f565b828601526101409150620017a08287016200137f565b90850152610160620017b486820162001140565b828601526101809150620017ca82870162001140565b908501526101a0620017de86820162001367565b828601526101c09150620017f482870162001140565b908501526101e06200180886820162001392565b828601526200181983870162001628565b9085015250508087019190915284529284019281016200168b565b6000806000806000806000610120888a0312156200185157600080fd5b6200185d898962001155565b60608901519097506001600160401b03808211156200187b57600080fd5b620018898b838c0162001202565b975060808a0151915080821115620018a057600080fd5b620018ae8b838c0162001202565b965060a08a0151915080821115620018c557600080fd5b620018d38b838c0162001282565b955060c08a0151915080821115620018ea57600080fd5b620018f88b838c01620013a3565b945060e08a01519150808211156200190f57600080fd5b6200191d8b838c016200158d565b93506101008a01519150808211156200193557600080fd5b50620019448a828b0162001641565b91505092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b815115158152610200810160208301516200198a602084018261ffff169052565b506040830151620019a3604084018263ffffffff169052565b506060830151620019bc606084018263ffffffff169052565b506080830151620019d5608084018263ffffffff169052565b5060a0830151620019ec60a084018261ffff169052565b5060c083015162001a0560c084018263ffffffff169052565b5060e083015162001a1c60e084018261ffff169052565b506101008381015161ffff9081169184019190915261012080850151909116908301526101408084015163ffffffff9081169184019190915261016080850151821690840152610180808501516001600160401b0316908401526101a080850151909116908301526101c0808401511515908301526101e0928301516001600160e01b031916929091019190915290565b8181038181111562000e7957634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b60805160a05160c051615c1562001b3f6000396000818161030501528181612223015261228c0152600081816102c90152818161193d015261199d015260008181610295015281816119c60152611a360152615c156000f3fe608060405234801561001057600080fd5b50600436106101e45760003560e01c806379ba50971161010f578063bf78e03f116100a2578063d63d3af211610071578063d63d3af214610ab2578063d8694ccd14610aba578063f2fde38b14610acd578063ffdb4b3714610ae057600080fd5b8063bf78e03f146109c8578063c4276bfc14610a75578063cdc73d5114610a97578063d02641a014610a9f57600080fd5b80638da5cb5b116100de5780638da5cb5b1461096757806391a2749a1461098f5780639ea60026146109a2578063a69c64c0146109b557600080fd5b806379ba5097146107c95780637afac322146107d1578063805f2132146107e457806382b49eb0146107f757600080fd5b80633937306f116101875780634ab35b0b116101565780634ab35b0b1461045f578063514e8cff1461049f5780636def4ce714610542578063770e2dc4146107b657600080fd5b80633937306f14610404578063407e10861461041957806341ed29e71461042c57806345ac924d1461043f57600080fd5b8063085318f8116101c3578063085318f81461037e578063181f5a771461039e5780632451a627146103e7578063325c868e146103fc57600080fd5b806241e5be146101e9578063061877e31461020f57806306285c6914610268575b600080fd5b6101fc6101f73660046142e8565b610b28565b6040519081526020015b60405180910390f35b61024f61021d366004614324565b73ffffffffffffffffffffffffffffffffffffffff1660009081526008602052604090205467ffffffffffffffff1690565b60405167ffffffffffffffff9091168152602001610206565b610332604080516060810182526000808252602082018190529181019190915260405180606001604052807f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000063ffffffff16815250905090565b6040805182516bffffffffffffffffffffffff16815260208084015173ffffffffffffffffffffffffffffffffffffffff16908201529181015163ffffffff1690820152606001610206565b61039161038c36600461439c565b610b96565b60405161020691906144ae565b6103da6040518060400160405280601381526020017f46656551756f74657220312e362e302d6465760000000000000000000000000081525081565b6040516102069190614530565b6103ef610f08565b6040516102069190614543565b6101fc602481565b61041761041236600461459d565b610f19565b005b61041761042736600461473f565b6111ce565b61041761043a366004614871565b6111e2565b61045261044d3660046149ac565b611224565b60405161020691906149ee565b61047261046d366004614324565b6112ef565b6040517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff9091168152602001610206565b6105356104ad366004614a69565b60408051808201909152600080825260208201525067ffffffffffffffff166000908152600560209081526040918290208251808401909352547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811683527c0100000000000000000000000000000000000000000000000000000000900463ffffffff169082015290565b6040516102069190614a84565b6107a9610550366004614a69565b6040805161020081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a081018290526101c081018290526101e08101919091525067ffffffffffffffff908116600090815260096020908152604091829020825161020081018452815460ff8082161515835261ffff61010080840482169685019690965263ffffffff630100000084048116978501979097526701000000000000008304871660608501526b0100000000000000000000008304871660808501526f010000000000000000000000000000008304811660a085015271010000000000000000000000000000000000808404881660c086015275010000000000000000000000000000000000000000008404821660e08087019190915277010000000000000000000000000000000000000000000000850483169786019790975279010000000000000000000000000000000000000000000000000084049091166101208501527b01000000000000000000000000000000000000000000000000000000909204861661014084015260019093015480861661016084015264010000000081049096166101808301526c0100000000000000000000000086049094166101a0820152700100000000000000000000000000000000850490911615156101c08201527fffffffff0000000000000000000000000000000000000000000000000000000092909304901b166101e082015290565b6040516102069190614abf565b6104176107c4366004614cd6565b6112fa565b61041761130c565b6104176107df366004614ff0565b611409565b6104176107f2366004615096565b61141b565b610907610805366004615102565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101919091525067ffffffffffffffff919091166000908152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff94909416835292815290829020825160c081018452905463ffffffff8082168352640100000000820481169383019390935268010000000000000000810461ffff16938201939093526a01000000000000000000008304821660608201526e01000000000000000000000000000083049091166080820152720100000000000000000000000000000000000090910460ff16151560a082015290565b6040516102069190600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60005460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610206565b61041761099d36600461512c565b611903565b6104176109b03660046151ed565b611914565b6104176109c33660046153fa565b611925565b610a416109d6366004614324565b6040805180820182526000808252602091820181905273ffffffffffffffffffffffffffffffffffffffff93841681526007825282902082518084019093525492831682527401000000000000000000000000000000000000000090920460ff169181019190915290565b60408051825173ffffffffffffffffffffffffffffffffffffffff16815260209283015160ff169281019290925201610206565b610a88610a833660046154bf565b611936565b6040516102069392919061552e565b6103ef611b2c565b610535610aad366004614324565b611b38565b6101fc601281565b6101fc610ac836600461554f565b611c34565b610417610adb366004614324565b61213e565b610af3610aee3660046155a4565b61214f565b604080517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff938416815292909116602083015201610206565b6000610b33826122da565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16610b5a856122da565b610b82907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16856155fd565b610b8c9190615614565b90505b9392505050565b67ffffffffffffffff8086166000908152600960205260409020600101546060917101000000000000000000000000000000000090910460e01b908590811115610be257610be26145d8565b604051908082528060200260200182016040528015610c1557816020015b6060815260200190600190039081610c005790505b50915060005b85811015610efd576000858583818110610c3757610c3761564f565b610c4d9260206040909202019081019150614324565b90506000888884818110610c6357610c6361564f565b9050602002810190610c75919061567e565b610c839060408101906156bc565b9150506020811115610d385767ffffffffffffffff8a166000908152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff861684529091529020546e010000000000000000000000000000900463ffffffff16811115610d38576040517f36f536ca00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526024015b60405180910390fd5b610da8848a8a86818110610d4e57610d4e61564f565b9050602002810190610d60919061567e565b610d6e9060208101906156bc565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061237492505050565b67ffffffffffffffff8a166000818152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684528252808320815160c081018352905463ffffffff8082168352640100000000820481168386015268010000000000000000820461ffff16838501526a01000000000000000000008204811660608401526e010000000000000000000000000000820481166080840152720100000000000000000000000000000000000090910460ff16151560a08301908152958552600990935290832054935190937b0100000000000000000000000000000000000000000000000000000090049091169190610ea75781610ead565b82606001515b6040805163ffffffff8316602082015291925001604051602081830303815290604052888781518110610ee257610ee261564f565b60200260200101819052505050505050806001019050610c1b565b505095945050505050565b6060610f1460026123cb565b905090565b610f216123d8565b6000610f2d8280615721565b9050905060005b81811015611077576000610f488480615721565b83818110610f5857610f5861564f565b905060400201803603810190610f6e91906157b5565b604080518082018252602080840180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff908116845263ffffffff42818116858701908152885173ffffffffffffffffffffffffffffffffffffffff9081166000908152600690975295889020965190519092167c010000000000000000000000000000000000000000000000000000000002919092161790935584519051935194955016927f52f50aa6d1a95a4595361ecf953d095f125d442e4673716dede699e049de148a926110669290917bffffffffffffffffffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b60405180910390a250600101610f34565b5060006110876020840184615721565b9050905060005b818110156111c85760006110a56020860186615721565b838181106110b5576110b561564f565b9050604002018036038101906110cb91906157f2565b604080518082018252602080840180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff908116845263ffffffff42818116858701908152885167ffffffffffffffff9081166000908152600590975295889020965190519092167c010000000000000000000000000000000000000000000000000000000002919092161790935584519051935194955016927fdd84a3fa9ef9409f550d54d6affec7e9c480c878c6ab27b78912a03e1b371c6e926111b79290917bffffffffffffffffffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b60405180910390a25060010161108e565b50505050565b6111d661241d565b6111df8161249e565b50565b6111ea61241d565b60005b81518110156112205761121882828151811061120b5761120b61564f565b602002602001015161259c565b6001016111ed565b5050565b60608160008167ffffffffffffffff811115611242576112426145d8565b60405190808252806020026020018201604052801561128757816020015b60408051808201909152600080825260208201528152602001906001900390816112605790505b50905060005b828110156112e4576112bf8686838181106112aa576112aa61564f565b9050602002016020810190610aad9190614324565b8282815181106112d1576112d161564f565b602090810291909101015260010161128d565b509150505b92915050565b60006112e9826122da565b61130261241d565b611220828261276e565b60015473ffffffffffffffffffffffffffffffffffffffff16331461138d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610d2f565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b61141161241d565b6112208282612b7b565b600080600061145f87878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612cc292505050565b92509250925061147133838584612cdd565b600061147f85870187615815565b905060005b81518110156118f8576000600760008484815181106114a5576114a561564f565b6020908102919091018101515173ffffffffffffffffffffffffffffffffffffffff16825281019190915260400160009081205474010000000000000000000000000000000000000000900460ff1691508190036115665782828151811061150f5761150f61564f565b6020908102919091010151516040517f06439c6b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610d2f565b60006115af6012838686815181106115805761158061564f565b6020026020010151602001517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16612e35565b9050600660008585815181106115c7576115c761564f565b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001601c9054906101000a900463ffffffff1663ffffffff168484815181106116395761163961564f565b60200260200101516040015163ffffffff161015611743578383815181106116635761166361564f565b6020026020010151600001518484815181106116815761168161564f565b602002602001015160400151600660008787815181106116a3576116a361564f565b6020908102919091018101515173ffffffffffffffffffffffffffffffffffffffff90811683529082019290925260409081016000205490517f191ec70600000000000000000000000000000000000000000000000000000000815293909116600484015263ffffffff91821660248401527c01000000000000000000000000000000000000000000000000000000009004166044820152606401610d2f565b6040518060400160405280827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1681526020018585815181106117845761178461564f565b60200260200101516040015163ffffffff16815250600660008686815181106117af576117af61564f565b6020908102919091018101515173ffffffffffffffffffffffffffffffffffffffff168252818101929092526040016000208251929091015163ffffffff167c0100000000000000000000000000000000000000000000000000000000027bffffffffffffffffffffffffffffffffffffffffffffffffffffffff90921691909117905583518490849081106118475761184761564f565b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff167f52f50aa6d1a95a4595361ecf953d095f125d442e4673716dede699e049de148a8286868151811061189d5761189d61564f565b6020026020010151604001516040516118e69291907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff92909216825263ffffffff16602082015260400190565b60405180910390a25050600101611484565b505050505050505050565b61190b61241d565b6111df81612f01565b61191c61241d565b6111df8161308d565b61192d61241d565b6111df81613533565b60008060607f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff1603611996578592506119c4565b6119c187877f0000000000000000000000000000000000000000000000000000000000000000610b28565b92505b7f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff16831115611a63576040517f6a92a483000000000000000000000000000000000000000000000000000000008152600481018490526bffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166024820152604401610d2f565b67ffffffffffffffff881660009081526009602052604081206001015463ffffffff1690611a9287878461361d565b9050806020015193508484611b19836040805182516024820152602092830151151560448083019190915282518083039091018152606490910190915290810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f181dcf100000000000000000000000000000000000000000000000000000000017905290565b9450945094505050955095509592505050565b6060610f14600b6123cb565b604080518082019091526000808252602082015273ffffffffffffffffffffffffffffffffffffffff8281166000908152600760209081526040918290208251808401909352549283168083527401000000000000000000000000000000000000000090930460ff169082015290611c2b57505073ffffffffffffffffffffffffffffffffffffffff166000908152600660209081526040918290208251808401909352547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811683527c0100000000000000000000000000000000000000000000000000000000900463ffffffff169082015290565b610b8f816137c6565b67ffffffffffffffff8083166000908152600960209081526040808320815161020081018352815460ff808216151580845261ffff61010080850482169886019890985263ffffffff630100000085048116978601979097526701000000000000008404871660608601526b0100000000000000000000008404871660808601526f010000000000000000000000000000008404811660a086015271010000000000000000000000000000000000808504881660c087015275010000000000000000000000000000000000000000008504821660e08088019190915277010000000000000000000000000000000000000000000000860483169987019990995279010000000000000000000000000000000000000000000000000085049091166101208601527b01000000000000000000000000000000000000000000000000000000909304861661014085015260019094015480861661016085015264010000000081049098166101808401526c0100000000000000000000000088049094166101a0830152700100000000000000000000000000000000870490931615156101c08201527fffffffff000000000000000000000000000000000000000000000000000000009290950490921b166101e0840152909190611e4e576040517f99ac52f200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff85166004820152602401610d2f565b611e69611e616080850160608601614324565b600b90613955565b611ec857611e7d6080840160608501614324565b6040517f2502348c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610d2f565b6000611ed76040850185615721565b9150611f33905082611eec60208701876156bc565b905083611ef988806156bc565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061398492505050565b600080611f4f611f496080880160608901614324565b8861214f565b9092509050600080808515611f9257611f86878b611f7360808d0160608e01614324565b88611f8160408f018f615721565b613a2e565b91945092509050611fb2565b6101a0870151611faf9063ffffffff16662386f26fc100006155fd565b92505b61010087015160009061ffff1615611ff657611ff3886dffffffffffffffffffffffffffff607088901c16611fea60208e018e6156bc565b90508a86613d06565b90505b61018088015160009067ffffffffffffffff1661201f61201960808e018e6156bc565b8c613db6565b600001518563ffffffff168b60a0015161ffff168e806020019061204391906156bc565b61204e9291506155fd565b8c6080015163ffffffff1661206391906158dc565b61206d91906158dc565b61207791906158dc565b612091906dffffffffffffffffffffffffffff89166155fd565b61209b91906155fd565b9050867bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168282600860008f60600160208101906120d59190614324565b73ffffffffffffffffffffffffffffffffffffffff1681526020810191909152604001600020546121109067ffffffffffffffff16896155fd565b61211a91906158dc565b61212491906158dc565b61212e9190615614565b9c9b505050505050505050505050565b61214661241d565b6111df81613e77565b67ffffffffffffffff811660009081526005602090815260408083208151808301909252547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811682527c0100000000000000000000000000000000000000000000000000000000900463ffffffff1691810182905282918203612207576040517f2e59db3a00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff85166004820152602401610d2f565b6000816020015163ffffffff164261221f91906158ef565b90507f000000000000000000000000000000000000000000000000000000000000000063ffffffff168111156122c0576040517ff08bcb3e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8616600482015263ffffffff7f000000000000000000000000000000000000000000000000000000000000000016602482015260448101829052606401610d2f565b6122c9866122da565b9151919350909150505b9250929050565b6000806122e683611b38565b9050806020015163ffffffff166000148061231e575080517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16155b1561236d576040517f06439c6b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152602401610d2f565b5192915050565b7fd7ed2ad4000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831601611220576123c681613f6c565b505050565b60606000610b8f8361401f565b6123e3600233613955565b61241b576040517fd86ad9cf000000000000000000000000000000000000000000000000000000008152336004820152602401610d2f565b565b60005473ffffffffffffffffffffffffffffffffffffffff16331461241b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610d2f565b60005b81518110156112205760008282815181106124be576124be61564f565b60209081029190910181015180518183015173ffffffffffffffffffffffffffffffffffffffff80831660008181526007875260409081902084518154868a018051929096167fffffffffffffffffffffff00000000000000000000000000000000000000000090911681177401000000000000000000000000000000000000000060ff9384160217909255825191825293519093169683019690965293955091939092917f08a5f7f5bb38a81d8e43aca13ecd76431dbf8816ae4699affff7b00b2fc1c464910160405180910390a25050508060010190506124a1565b600061265582600001518360600151846020015185604001516040805173ffffffffffffffffffffffffffffffffffffffff80871660208301528516918101919091527fffffffffffffffffffff00000000000000000000000000000000000000000000831660608201527fffff0000000000000000000000000000000000000000000000000000000000008216608082015260009060a001604051602081830303815290604052805190602001209050949350505050565b60808301516000828152600460205260409081902080549215157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00909316929092179091555190915081907f32a4ba3fa3351b11ad555d4c8ec70a744e8705607077a946807030d64b6ab1a390612762908590600060a08201905073ffffffffffffffffffffffffffffffffffffffff8084511683527fffffffffffffffffffff0000000000000000000000000000000000000000000060208501511660208401527fffff00000000000000000000000000000000000000000000000000000000000060408501511660408401528060608501511660608401525060808301511515608083015292915050565b60405180910390a25050565b60005b8251811015612a9757600083828151811061278e5761278e61564f565b6020026020010151905060008160000151905060005b826020015151811015612a89576000836020015182815181106127c9576127c961564f565b60200260200101516020015190506000846020015183815181106127ef576127ef61564f565b6020026020010151600001519050602063ffffffff16826080015163ffffffff1610156128725760808201516040517f24ecdc0200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8316600482015263ffffffff9091166024820152604401610d2f565b67ffffffffffffffff84166000818152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff86168085529083529281902086518154938801518389015160608a015160808b015160a08c015115157201000000000000000000000000000000000000027fffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffff63ffffffff9283166e01000000000000000000000000000002167fffffffffffffffffffffffffff0000000000ffffffffffffffffffffffffffff9383166a0100000000000000000000027fffffffffffffffffffffffffffffffffffff00000000ffffffffffffffffffff61ffff9096166801000000000000000002959095167fffffffffffffffffffffffffffffffffffff000000000000ffffffffffffffff968416640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000909b16939097169290921798909817939093169390931717919091161792909217909155519091907f94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b590612a77908690600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60405180910390a350506001016127a4565b505050806001019050612771565b5060005b81518110156123c6576000828281518110612ab857612ab861564f565b60200260200101516000015190506000838381518110612ada57612ada61564f565b60209081029190910181015181015167ffffffffffffffff84166000818152600a8452604080822073ffffffffffffffffffffffffffffffffffffffff8516808452955280822080547fffffffffffffffffffffffffff000000000000000000000000000000000000001690555192945090917f4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b9190a35050600101612a9b565b60005b8251811015612c1e57612bb4838281518110612b9c57612b9c61564f565b6020026020010151600b61407b90919063ffffffff16565b15612c1657828181518110612bcb57612bcb61564f565b602002602001015173ffffffffffffffffffffffffffffffffffffffff167fdf1b1bd32a69711488d71554706bb130b1fc63a5fa1a2cd85e8440f84065ba2360405160405180910390a25b600101612b7e565b5060005b81518110156123c657612c58828281518110612c4057612c4061564f565b6020026020010151600b61409d90919063ffffffff16565b15612cba57818181518110612c6f57612c6f61564f565b602002602001015173ffffffffffffffffffffffffffffffffffffffff167f1795838dc8ab2ffc5f431a1729a6afa0b587f982f7b2be0b9d7187a1ef547f9160405160405180910390a25b600101612c22565b6040810151604a820151605e90920151909260609290921c91565b6040805173ffffffffffffffffffffffffffffffffffffffff868116602080840191909152908616828401527fffffffffffffffffffff00000000000000000000000000000000000000000000851660608301527fffff00000000000000000000000000000000000000000000000000000000000084166080808401919091528351808403909101815260a09092018352815191810191909120600081815260049092529190205460ff16612e2e576040517f097e17ff00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8087166004830152851660248201527fffffffffffffffffffff00000000000000000000000000000000000000000000841660448201527fffff00000000000000000000000000000000000000000000000000000000000083166064820152608401610d2f565b5050505050565b600080612e428486615902565b9050600060248260ff161115612e7c57612e60602460ff84166158ef565b612e6b90600a615a3b565b612e759085615614565b9050612ea2565b612e8a60ff831660246158ef565b612e9590600a615a3b565b612e9f90856155fd565b90505b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811115612ef8576040517f10cb51d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b95945050505050565b602081015160005b8151811015612f9c576000828281518110612f2657612f2661564f565b60200260200101519050612f448160026140bf90919063ffffffff16565b15612f935760405173ffffffffffffffffffffffffffffffffffffffff821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b50600101612f09565b50815160005b81518110156111c8576000828281518110612fbf57612fbf61564f565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361302f576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61303a60028261407b565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a150600101612fa2565b60005b81518110156112205760008282815181106130ad576130ad61564f565b6020026020010151905060008383815181106130cb576130cb61564f565b60200260200101516000015190506000826020015190508167ffffffffffffffff1660001480613104575061016081015163ffffffff16155b8061315657506101e08101517fffffffff00000000000000000000000000000000000000000000000000000000167f2812d52c0000000000000000000000000000000000000000000000000000000014155b806131755750806060015163ffffffff1681610160015163ffffffff16115b156131b8576040517fc35aa79d00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff83166004820152602401610d2f565b67ffffffffffffffff821660009081526009602052604081206001015471010000000000000000000000000000000000900460e01b7fffffffff0000000000000000000000000000000000000000000000000000000016900361325c578167ffffffffffffffff167fd31c671936387b2f84ed402b553bd50c0e9c20408ea4e91a836d77b8180fb7248260405161324f9190614abf565b60405180910390a261329f565b8167ffffffffffffffff167f1edd6f3553cfa16f10b95b195abae3a1cfca4783de4843f95d674b1e1df5ab20826040516132969190614abf565b60405180910390a25b80600960008467ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548161ffff021916908361ffff16021790555060408201518160000160036101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160076101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600b6101000a81548163ffffffff021916908363ffffffff16021790555060a082015181600001600f6101000a81548161ffff021916908361ffff16021790555060c08201518160000160116101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160000160156101000a81548161ffff021916908361ffff1602179055506101008201518160000160176101000a81548161ffff021916908361ffff1602179055506101208201518160000160196101000a81548161ffff021916908361ffff16021790555061014082015181600001601b6101000a81548163ffffffff021916908363ffffffff1602179055506101608201518160010160006101000a81548163ffffffff021916908363ffffffff1602179055506101808201518160010160046101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506101a082015181600101600c6101000a81548163ffffffff021916908363ffffffff1602179055506101c08201518160010160106101000a81548160ff0219169083151502179055506101e08201518160010160116101000a81548163ffffffff021916908360e01c0217905550905050505050806001019050613090565b60005b81518110156112205760008282815181106135535761355361564f565b602002602001015160000151905060008383815181106135755761357561564f565b60209081029190910181015181015173ffffffffffffffffffffffffffffffffffffffff841660008181526008845260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff85169081179091559051908152919350917fbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d910160405180910390a25050600101613536565b6040805180820190915260008082526020820152600083900361365e57506040805180820190915267ffffffffffffffff8216815260006020820152610b8f565b600061366a8486615a47565b9050600061367b8560048189615a8d565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505050507fffffffff0000000000000000000000000000000000000000000000000000000082167fe7e230f00000000000000000000000000000000000000000000000000000000001613718578080602001905181019061370f9190615ab7565b92505050610b8f565b7f6859a837000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831601613794576040518060400160405280828060200190518101906137809190615ae3565b815260006020909101529250610b8f915050565b6040517f5247fdce00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080518082019091526000808252602082015260008260000151905060008173ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015613830573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138549190615b16565b5050509150506000811215613895576040517f10cb51d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006139148373ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156138e5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139099190615b66565b866020015184612e35565b604080518082019091527bffffffffffffffffffffffffffffffffffffffffffffffffffffffff909116815263ffffffff4216602082015295945050505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515610b8f565b836040015163ffffffff168311156139dd5760408085015190517f8693378900000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015260248101849052604401610d2f565b836020015161ffff16821115613a1f576040517f4c056b6a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6111c8846101e0015182612374565b6000808083815b81811015613cf8576000878783818110613a5157613a5161564f565b905060400201803603810190613a679190615b83565b67ffffffffffffffff8c166000908152600a60209081526040808320845173ffffffffffffffffffffffffffffffffffffffff168452825291829020825160c081018452905463ffffffff8082168352640100000000820481169383019390935268010000000000000000810461ffff16938201939093526a01000000000000000000008304821660608201526e01000000000000000000000000000083049091166080820152720100000000000000000000000000000000000090910460ff16151560a0820181905291925090613b87576101208d0151613b549061ffff16662386f26fc100006155fd565b613b5e90886158dc565b96508c610140015186613b719190615bbc565b9550613b7e602086615bbc565b94505050613cf0565b604081015160009061ffff1615613c405760008c73ffffffffffffffffffffffffffffffffffffffff16846000015173ffffffffffffffffffffffffffffffffffffffff1614613be3578351613bdc906122da565b9050613be6565b508a5b620186a0836040015161ffff16613c288660200151847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166140e190919063ffffffff16565b613c3291906155fd565b613c3c9190615614565b9150505b6060820151613c4f9088615bbc565b9650816080015186613c619190615bbc565b8251909650600090613c809063ffffffff16662386f26fc100006155fd565b905080821015613c9f57613c94818a6158dc565b985050505050613cf0565b6000836020015163ffffffff16662386f26fc10000613cbe91906155fd565b905080831115613cde57613cd2818b6158dc565b99505050505050613cf0565b613ce8838b6158dc565b995050505050505b600101613a35565b505096509650969350505050565b60008063ffffffff8316613d1c610160866155fd565b613d28876101c06158dc565b613d3291906158dc565b613d3c91906158dc565b905060008760c0015163ffffffff168860e0015161ffff1683613d5f91906155fd565b613d6991906158dc565b61010089015190915061ffff16613d906dffffffffffffffffffffffffffff8916836155fd565b613d9a91906155fd565b613daa90655af3107a40006155fd565b98975050505050505050565b60408051808201909152600080825260208201526000613de2858585610160015163ffffffff1661361d565b9050826060015163ffffffff1681600001511115613e2c576040517f4c4fc93a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b826101c001518015613e4057508060200151155b15610b8c576040517fee433e9900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff821603613ef6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610d2f565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60008151602014613fab57816040517f8d666f60000000000000000000000000000000000000000000000000000000008152600401610d2f9190614530565b600082806020019051810190613fc19190615ae3565b905073ffffffffffffffffffffffffffffffffffffffff811180613fe6575061040081105b156112e957826040517f8d666f60000000000000000000000000000000000000000000000000000000008152600401610d2f9190614530565b60608160000180548060200260200160405190810160405280929190818152602001828054801561406f57602002820191906000526020600020905b81548152602001906001019080831161405b575b50505050509050919050565b6000610b8f8373ffffffffffffffffffffffffffffffffffffffff841661411e565b6000610b8f8373ffffffffffffffffffffffffffffffffffffffff841661416d565b6000610b8f8373ffffffffffffffffffffffffffffffffffffffff8416614267565b6000670de0b6b3a7640000614114837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff86166155fd565b610b8f9190615614565b6000818152600183016020526040812054614165575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556112e9565b5060006112e9565b600081815260018301602052604081205480156142565760006141916001836158ef565b85549091506000906141a5906001906158ef565b905080821461420a5760008660000182815481106141c5576141c561564f565b90600052602060002001549050808760000184815481106141e8576141e861564f565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061421b5761421b615bd9565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506112e9565b60009150506112e9565b5092915050565b6000818152600183016020526040812054801561425657600061428b6001836158ef565b855490915060009061429f906001906158ef565b905081811461420a5760008660000182815481106141c5576141c561564f565b803573ffffffffffffffffffffffffffffffffffffffff811681146142e357600080fd5b919050565b6000806000606084860312156142fd57600080fd5b614306846142bf565b92506020840135915061431b604085016142bf565b90509250925092565b60006020828403121561433657600080fd5b610b8f826142bf565b803567ffffffffffffffff811681146142e357600080fd5b60008083601f84011261436957600080fd5b50813567ffffffffffffffff81111561438157600080fd5b6020830191508360208260051b85010111156122d357600080fd5b6000806000806000606086880312156143b457600080fd5b6143bd8661433f565b9450602086013567ffffffffffffffff808211156143da57600080fd5b6143e689838a01614357565b909650945060408801359150808211156143ff57600080fd5b818801915088601f83011261441357600080fd5b81358181111561442257600080fd5b8960208260061b850101111561443757600080fd5b9699959850939650602001949392505050565b6000815180845260005b8181101561447057602081850181015186830182015201614454565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b82811015614523577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc088860301845261451185835161444a565b945092850192908501906001016144d7565b5092979650505050505050565b602081526000610b8f602083018461444a565b6020808252825182820181905260009190848201906040850190845b8181101561459157835173ffffffffffffffffffffffffffffffffffffffff168352928401929184019160010161455f565b50909695505050505050565b6000602082840312156145af57600080fd5b813567ffffffffffffffff8111156145c657600080fd5b820160408185031215610b8f57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561462a5761462a6145d8565b60405290565b60405160a0810167ffffffffffffffff8111828210171561462a5761462a6145d8565b60405160c0810167ffffffffffffffff8111828210171561462a5761462a6145d8565b604051610200810167ffffffffffffffff8111828210171561462a5761462a6145d8565b6040516060810167ffffffffffffffff8111828210171561462a5761462a6145d8565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715614704576147046145d8565b604052919050565b600067ffffffffffffffff821115614726576147266145d8565b5060051b60200190565b60ff811681146111df57600080fd5b6000602080838503121561475257600080fd5b823567ffffffffffffffff81111561476957600080fd5b8301601f8101851361477a57600080fd5b803561478d6147888261470c565b6146bd565b818152606091820283018401918482019190888411156147ac57600080fd5b938501935b8385101561484c57848903818112156147ca5760008081fd5b6147d2614607565b6147db876142bf565b81526040807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08401121561480f5760008081fd5b614817614607565b92506148248989016142bf565b835287013561483281614730565b8289015280880191909152835293840193918501916147b1565b50979650505050505050565b80151581146111df57600080fd5b80356142e381614858565b6000602080838503121561488457600080fd5b823567ffffffffffffffff81111561489b57600080fd5b8301601f810185136148ac57600080fd5b80356148ba6147888261470c565b81815260a091820283018401918482019190888411156148d957600080fd5b938501935b8385101561484c5780858a0312156148f65760008081fd5b6148fe614630565b614907866142bf565b8152868601357fffffffffffffffffffff000000000000000000000000000000000000000000008116811461493c5760008081fd5b818801526040868101357fffff000000000000000000000000000000000000000000000000000000000000811681146149755760008081fd5b9082015260606149868782016142bf565b9082015260808681013561499981614858565b90820152835293840193918501916148de565b600080602083850312156149bf57600080fd5b823567ffffffffffffffff8111156149d657600080fd5b6149e285828601614357565b90969095509350505050565b602080825282518282018190526000919060409081850190868401855b82811015614a5c57614a4c84835180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16825260209081015163ffffffff16910152565b9284019290850190600101614a0b565b5091979650505050505050565b600060208284031215614a7b57600080fd5b610b8f8261433f565b81517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16815260208083015163ffffffff1690820152604081016112e9565b81511515815261020081016020830151614adf602084018261ffff169052565b506040830151614af7604084018263ffffffff169052565b506060830151614b0f606084018263ffffffff169052565b506080830151614b27608084018263ffffffff169052565b5060a0830151614b3d60a084018261ffff169052565b5060c0830151614b5560c084018263ffffffff169052565b5060e0830151614b6b60e084018261ffff169052565b506101008381015161ffff9081169184019190915261012080850151909116908301526101408084015163ffffffff90811691840191909152610160808501518216908401526101808085015167ffffffffffffffff16908401526101a080850151909116908301526101c0808401511515908301526101e0808401517fffffffff000000000000000000000000000000000000000000000000000000008116828501525b505092915050565b803563ffffffff811681146142e357600080fd5b803561ffff811681146142e357600080fd5b600082601f830112614c4f57600080fd5b81356020614c5f6147888361470c565b82815260069290921b84018101918181019086841115614c7e57600080fd5b8286015b84811015614ccb5760408189031215614c9b5760008081fd5b614ca3614607565b614cac8261433f565b8152614cb98583016142bf565b81860152835291830191604001614c82565b509695505050505050565b60008060408385031215614ce957600080fd5b67ffffffffffffffff83351115614cff57600080fd5b83601f843585010112614d1157600080fd5b614d21614788843585013561470c565b8335840180358083526020808401939260059290921b90910101861015614d4757600080fd5b602085358601015b85358601803560051b01602001811015614f545767ffffffffffffffff81351115614d7957600080fd5b8035863587010160407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0828a03011215614db257600080fd5b614dba614607565b614dc66020830161433f565b815267ffffffffffffffff60408301351115614de157600080fd5b88603f604084013584010112614df657600080fd5b614e0c614788602060408501358501013561470c565b6020604084810135850182810135808552928401939260e00201018b1015614e3357600080fd5b6040808501358501015b6040858101358601602081013560e0020101811015614f355760e0818d031215614e6657600080fd5b614e6e614607565b614e77826142bf565b815260c07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0838f03011215614eab57600080fd5b614eb3614653565b614ebf60208401614c18565b8152614ecd60408401614c18565b6020820152614ede60608401614c2c565b6040820152614eef60808401614c18565b6060820152614f0060a08401614c18565b6080820152614f1260c0840135614858565b60c083013560a0820152602082810191909152908452929092019160e001614e3d565b5080602084015250508085525050602083019250602081019050614d4f565b5092505067ffffffffffffffff60208401351115614f7157600080fd5b614f818460208501358501614c3e565b90509250929050565b600082601f830112614f9b57600080fd5b81356020614fab6147888361470c565b8083825260208201915060208460051b870101935086841115614fcd57600080fd5b602086015b84811015614ccb57614fe3816142bf565b8352918301918301614fd2565b6000806040838503121561500357600080fd5b823567ffffffffffffffff8082111561501b57600080fd5b61502786838701614f8a565b9350602085013591508082111561503d57600080fd5b5061504a85828601614f8a565b9150509250929050565b60008083601f84011261506657600080fd5b50813567ffffffffffffffff81111561507e57600080fd5b6020830191508360208285010111156122d357600080fd5b600080600080604085870312156150ac57600080fd5b843567ffffffffffffffff808211156150c457600080fd5b6150d088838901615054565b909650945060208701359150808211156150e957600080fd5b506150f687828801615054565b95989497509550505050565b6000806040838503121561511557600080fd5b61511e8361433f565b9150614f81602084016142bf565b60006020828403121561513e57600080fd5b813567ffffffffffffffff8082111561515657600080fd5b908301906040828603121561516a57600080fd5b615172614607565b82358281111561518157600080fd5b61518d87828601614f8a565b8252506020830135828111156151a257600080fd5b6151ae87828601614f8a565b60208301525095945050505050565b80357fffffffff00000000000000000000000000000000000000000000000000000000811681146142e357600080fd5b6000602080838503121561520057600080fd5b823567ffffffffffffffff81111561521757600080fd5b8301601f8101851361522857600080fd5b80356152366147888261470c565b818152610220918202830184019184820191908884111561525657600080fd5b938501935b8385101561484c57848903818112156152745760008081fd5b61527c614607565b6152858761433f565b8152610200807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0840112156152ba5760008081fd5b6152c2614676565b92506152cf898901614866565b835260406152de818a01614c2c565b8a85015260606152ef818b01614c18565b8286015260809150615302828b01614c18565b9085015260a06153138a8201614c18565b8286015260c09150615326828b01614c2c565b9085015260e06153378a8201614c18565b82860152610100915061534b828b01614c2c565b9085015261012061535d8a8201614c2c565b828601526101409150615371828b01614c2c565b908501526101606153838a8201614c18565b828601526101809150615397828b01614c18565b908501526101a06153a98a820161433f565b828601526101c091506153bd828b01614c18565b908501526101e06153cf8a8201614866565b828601526153de838b016151bd565b908501525050808801919091528352938401939185019161525b565b6000602080838503121561540d57600080fd5b823567ffffffffffffffff81111561542457600080fd5b8301601f8101851361543557600080fd5b80356154436147888261470c565b81815260069190911b8201830190838101908783111561546257600080fd5b928401925b828410156154b457604084890312156154805760008081fd5b615488614607565b615491856142bf565b815261549e86860161433f565b8187015282526040939093019290840190615467565b979650505050505050565b6000806000806000608086880312156154d757600080fd5b6154e08661433f565b94506154ee602087016142bf565b935060408601359250606086013567ffffffffffffffff81111561551157600080fd5b61551d88828901615054565b969995985093965092949392505050565b8381528215156020820152606060408201526000612ef8606083018461444a565b6000806040838503121561556257600080fd5b61556b8361433f565b9150602083013567ffffffffffffffff81111561558757600080fd5b830160a0818603121561559957600080fd5b809150509250929050565b600080604083850312156155b757600080fd5b6155c0836142bf565b9150614f816020840161433f565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80820281158282048414176112e9576112e96155ce565b60008261564a577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff618336030181126156b257600080fd5b9190910192915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126156f157600080fd5b83018035915067ffffffffffffffff82111561570c57600080fd5b6020019150368190038213156122d357600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261575657600080fd5b83018035915067ffffffffffffffff82111561577157600080fd5b6020019150600681901b36038213156122d357600080fd5b80357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811681146142e357600080fd5b6000604082840312156157c757600080fd5b6157cf614607565b6157d8836142bf565b81526157e660208401615789565b60208201529392505050565b60006040828403121561580457600080fd5b61580c614607565b6157d88361433f565b6000602080838503121561582857600080fd5b823567ffffffffffffffff81111561583f57600080fd5b8301601f8101851361585057600080fd5b803561585e6147888261470c565b8181526060918202830184019184820191908884111561587d57600080fd5b938501935b8385101561484c5780858a03121561589a5760008081fd5b6158a261469a565b6158ab866142bf565b81526158b8878701615789565b8782015260406158c9818801614c18565b9082015283529384019391850191615882565b808201808211156112e9576112e96155ce565b818103818111156112e9576112e96155ce565b60ff81811683821601908111156112e9576112e96155ce565b600181815b8085111561597457817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561595a5761595a6155ce565b8085161561596757918102915b93841c9390800290615920565b509250929050565b60008261598b575060016112e9565b81615998575060006112e9565b81600181146159ae57600281146159b8576159d4565b60019150506112e9565b60ff8411156159c9576159c96155ce565b50506001821b6112e9565b5060208310610133831016604e8410600b84101617156159f7575081810a6112e9565b615a01838361591b565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115615a3357615a336155ce565b029392505050565b6000610b8f838361597c565b7fffffffff000000000000000000000000000000000000000000000000000000008135818116916004851015614c105760049490940360031b84901b1690921692915050565b60008085851115615a9d57600080fd5b83861115615aaa57600080fd5b5050820193919092039150565b600060408284031215615ac957600080fd5b615ad1614607565b8251815260208301516157e681614858565b600060208284031215615af557600080fd5b5051919050565b805169ffffffffffffffffffff811681146142e357600080fd5b600080600080600060a08688031215615b2e57600080fd5b615b3786615afc565b9450602086015193506040860151925060608601519150615b5a60808701615afc565b90509295509295909350565b600060208284031215615b7857600080fd5b8151610b8f81614730565b600060408284031215615b9557600080fd5b615b9d614607565b615ba6836142bf565b8152602083013560208201528091505092915050565b63ffffffff818116838216019080821115614260576142606155ce565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea164736f6c6343000818000a", } var FeeQuoterABI = FeeQuoterMetaData.ABI @@ -294,6 +294,50 @@ func (_FeeQuoter *FeeQuoterTransactorRaw) Transact(opts *bind.TransactOpts, meth return _FeeQuoter.Contract.contract.Transact(opts, method, params...) } +func (_FeeQuoter *FeeQuoterCaller) FEEBASEDECIMALS(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _FeeQuoter.contract.Call(opts, &out, "FEE_BASE_DECIMALS") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_FeeQuoter *FeeQuoterSession) FEEBASEDECIMALS() (*big.Int, error) { + return _FeeQuoter.Contract.FEEBASEDECIMALS(&_FeeQuoter.CallOpts) +} + +func (_FeeQuoter *FeeQuoterCallerSession) FEEBASEDECIMALS() (*big.Int, error) { + return _FeeQuoter.Contract.FEEBASEDECIMALS(&_FeeQuoter.CallOpts) +} + +func (_FeeQuoter *FeeQuoterCaller) KEYSTONEPRICEDECIMALS(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _FeeQuoter.contract.Call(opts, &out, "KEYSTONE_PRICE_DECIMALS") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_FeeQuoter *FeeQuoterSession) KEYSTONEPRICEDECIMALS() (*big.Int, error) { + return _FeeQuoter.Contract.KEYSTONEPRICEDECIMALS(&_FeeQuoter.CallOpts) +} + +func (_FeeQuoter *FeeQuoterCallerSession) KEYSTONEPRICEDECIMALS() (*big.Int, error) { + return _FeeQuoter.Contract.KEYSTONEPRICEDECIMALS(&_FeeQuoter.CallOpts) +} + func (_FeeQuoter *FeeQuoterCaller) ConvertTokenAmount(opts *bind.CallOpts, fromToken common.Address, fromTokenAmount *big.Int, toToken common.Address) (*big.Int, error) { var out []interface{} err := _FeeQuoter.contract.Call(opts, &out, "convertTokenAmount", fromToken, fromTokenAmount, toToken) @@ -2883,6 +2927,10 @@ func (_FeeQuoter *FeeQuoter) Address() common.Address { } type FeeQuoterInterface interface { + FEEBASEDECIMALS(opts *bind.CallOpts) (*big.Int, error) + + KEYSTONEPRICEDECIMALS(opts *bind.CallOpts) (*big.Int, error) + ConvertTokenAmount(opts *bind.CallOpts, fromToken common.Address, fromTokenAmount *big.Int, toToken common.Address) (*big.Int, error) GetAllAuthorizedCallers(opts *bind.CallOpts) ([]common.Address, error) diff --git a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt index d050e401b9..d327839ed5 100644 --- a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -4,14 +4,14 @@ burn_mint_token_pool: ../../../contracts/solc/v0.8.24/BurnMintTokenPool/BurnMint burn_mint_token_pool_and_proxy: ../../../contracts/solc/v0.8.24/BurnMintTokenPoolAndProxy/BurnMintTokenPoolAndProxy.abi ../../../contracts/solc/v0.8.24/BurnMintTokenPoolAndProxy/BurnMintTokenPoolAndProxy.bin 717c079d5d13300cf3c3ee871c6e5bf9af904411f204fb081a9f3b263cca1391 burn_with_from_mint_token_pool: ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.abi ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.bin 6333d0314d0bd29e75ea5e05fe62a4516ade0c6db91c30b6f93645035db52ed8 burn_with_from_mint_token_pool_and_proxy: ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPoolAndProxy/BurnWithFromMintTokenPoolAndProxy.abi ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPoolAndProxy/BurnWithFromMintTokenPoolAndProxy.bin 08ed1235dda921ce8841b26aa18d0c0f36db4884779dd7670857159801b6d597 -ccip_config: ../../../contracts/solc/v0.8.24/CCIPConfig/CCIPConfig.abi ../../../contracts/solc/v0.8.24/CCIPConfig/CCIPConfig.bin b64994e8719f666101322b32c87d7d569b865be30bc6966aa8751ecb9249bcf4 +ccip_config: ../../../contracts/solc/v0.8.24/CCIPConfig/CCIPConfig.abi ../../../contracts/solc/v0.8.24/CCIPConfig/CCIPConfig.bin 93e3bceec6fff366e876f636001253f1d9c60b43e2c95484674f7ae245b302e6 ccip_reader_tester: ../../../contracts/solc/v0.8.24/CCIPReaderTester/CCIPReaderTester.abi ../../../contracts/solc/v0.8.24/CCIPReaderTester/CCIPReaderTester.bin 481d461f14c98308cd788b64be1151e92bac6f95ddd55eefc926296454316f13 commit_store: ../../../contracts/solc/v0.8.24/CommitStore/CommitStore.abi ../../../contracts/solc/v0.8.24/CommitStore/CommitStore.bin 274d87db70b643e00ab0a7e7845bb4b791f3b613bfc87708d33fc5a8369e2a41 commit_store_helper: ../../../contracts/solc/v0.8.24/CommitStoreHelper/CommitStoreHelper.abi ../../../contracts/solc/v0.8.24/CommitStoreHelper/CommitStoreHelper.bin f7128dcc2ee6dbcbc976288abcc16970ffb19b59412c5202ef6b259d2007f801 ether_sender_receiver: ../../../contracts/solc/v0.8.24/EtherSenderReceiver/EtherSenderReceiver.abi ../../../contracts/solc/v0.8.24/EtherSenderReceiver/EtherSenderReceiver.bin 09510a3f773f108a3c231e8d202835c845ded862d071ec54c4f89c12d868b8de evm_2_evm_offramp: ../../../contracts/solc/v0.8.24/EVM2EVMOffRamp/EVM2EVMOffRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMOffRamp/EVM2EVMOffRamp.bin b0d77babbe635cd6ba04c2af049badc9e9d28a4b6ed6bb75f830ad902a618beb evm_2_evm_onramp: ../../../contracts/solc/v0.8.24/EVM2EVMOnRamp/EVM2EVMOnRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMOnRamp/EVM2EVMOnRamp.bin 5c02c2b167946b3467636ff2bb58594cb4652fc63d8bdfee2488ed562e2a3e50 -fee_quoter: ../../../contracts/solc/v0.8.24/FeeQuoter/FeeQuoter.abi ../../../contracts/solc/v0.8.24/FeeQuoter/FeeQuoter.bin 7fcb78bfc6f050c9d3bd3396a29fa58c6eceec3be6f9f6e807212e816f881a4c +fee_quoter: ../../../contracts/solc/v0.8.24/FeeQuoter/FeeQuoter.abi ../../../contracts/solc/v0.8.24/FeeQuoter/FeeQuoter.bin 286117b3f17fe2854ddada25666be4ed2eb8069718f4ba595958accad170a4a2 lock_release_token_pool: ../../../contracts/solc/v0.8.24/LockReleaseTokenPool/LockReleaseTokenPool.abi ../../../contracts/solc/v0.8.24/LockReleaseTokenPool/LockReleaseTokenPool.bin e6a8ec9e8faccb1da7d90e0f702ed72975964f97dc3222b54cfcca0a0ba3fea2 lock_release_token_pool_and_proxy: ../../../contracts/solc/v0.8.24/LockReleaseTokenPoolAndProxy/LockReleaseTokenPoolAndProxy.abi ../../../contracts/solc/v0.8.24/LockReleaseTokenPoolAndProxy/LockReleaseTokenPoolAndProxy.bin e632b08be0fbd1d013e8b3a9d75293d0d532b83071c531ff2be1deec1fa48ec1 maybe_revert_message_receiver: ../../../contracts/solc/v0.8.24/MaybeRevertMessageReceiver/MaybeRevertMessageReceiver.abi ../../../contracts/solc/v0.8.24/MaybeRevertMessageReceiver/MaybeRevertMessageReceiver.bin d73956c26232ebcc4a5444429fa99cbefed960e323be9b5a24925885c2e477d5 diff --git a/core/gethwrappers/ccip/mocks/fee_quoter_interface.go b/core/gethwrappers/ccip/mocks/fee_quoter_interface.go index 27f53c0bd9..c2ea02f136 100644 --- a/core/gethwrappers/ccip/mocks/fee_quoter_interface.go +++ b/core/gethwrappers/ccip/mocks/fee_quoter_interface.go @@ -495,6 +495,64 @@ func (_c *FeeQuoterInterface_ConvertTokenAmount_Call) RunAndReturn(run func(*bin return _c } +// FEEBASEDECIMALS provides a mock function with given fields: opts +func (_m *FeeQuoterInterface) FEEBASEDECIMALS(opts *bind.CallOpts) (*big.Int, error) { + ret := _m.Called(opts) + + if len(ret) == 0 { + panic("no return value specified for FEEBASEDECIMALS") + } + + var r0 *big.Int + var r1 error + if rf, ok := ret.Get(0).(func(*bind.CallOpts) (*big.Int, error)); ok { + return rf(opts) + } + if rf, ok := ret.Get(0).(func(*bind.CallOpts) *big.Int); ok { + r0 = rf(opts) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*big.Int) + } + } + + if rf, ok := ret.Get(1).(func(*bind.CallOpts) error); ok { + r1 = rf(opts) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_FEEBASEDECIMALS_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FEEBASEDECIMALS' +type FeeQuoterInterface_FEEBASEDECIMALS_Call struct { + *mock.Call +} + +// FEEBASEDECIMALS is a helper method to define mock.On call +// - opts *bind.CallOpts +func (_e *FeeQuoterInterface_Expecter) FEEBASEDECIMALS(opts interface{}) *FeeQuoterInterface_FEEBASEDECIMALS_Call { + return &FeeQuoterInterface_FEEBASEDECIMALS_Call{Call: _e.mock.On("FEEBASEDECIMALS", opts)} +} + +func (_c *FeeQuoterInterface_FEEBASEDECIMALS_Call) Run(run func(opts *bind.CallOpts)) *FeeQuoterInterface_FEEBASEDECIMALS_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.CallOpts)) + }) + return _c +} + +func (_c *FeeQuoterInterface_FEEBASEDECIMALS_Call) Return(_a0 *big.Int, _a1 error) *FeeQuoterInterface_FEEBASEDECIMALS_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_FEEBASEDECIMALS_Call) RunAndReturn(run func(*bind.CallOpts) (*big.Int, error)) *FeeQuoterInterface_FEEBASEDECIMALS_Call { + _c.Call.Return(run) + return _c +} + // FilterAuthorizedCallerAdded provides a mock function with given fields: opts func (_m *FeeQuoterInterface) FilterAuthorizedCallerAdded(opts *bind.FilterOpts) (*fee_quoter.FeeQuoterAuthorizedCallerAddedIterator, error) { ret := _m.Called(opts) @@ -2133,6 +2191,64 @@ func (_c *FeeQuoterInterface_GetValidatedTokenPrice_Call) RunAndReturn(run func( return _c } +// KEYSTONEPRICEDECIMALS provides a mock function with given fields: opts +func (_m *FeeQuoterInterface) KEYSTONEPRICEDECIMALS(opts *bind.CallOpts) (*big.Int, error) { + ret := _m.Called(opts) + + if len(ret) == 0 { + panic("no return value specified for KEYSTONEPRICEDECIMALS") + } + + var r0 *big.Int + var r1 error + if rf, ok := ret.Get(0).(func(*bind.CallOpts) (*big.Int, error)); ok { + return rf(opts) + } + if rf, ok := ret.Get(0).(func(*bind.CallOpts) *big.Int); ok { + r0 = rf(opts) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*big.Int) + } + } + + if rf, ok := ret.Get(1).(func(*bind.CallOpts) error); ok { + r1 = rf(opts) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeQuoterInterface_KEYSTONEPRICEDECIMALS_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'KEYSTONEPRICEDECIMALS' +type FeeQuoterInterface_KEYSTONEPRICEDECIMALS_Call struct { + *mock.Call +} + +// KEYSTONEPRICEDECIMALS is a helper method to define mock.On call +// - opts *bind.CallOpts +func (_e *FeeQuoterInterface_Expecter) KEYSTONEPRICEDECIMALS(opts interface{}) *FeeQuoterInterface_KEYSTONEPRICEDECIMALS_Call { + return &FeeQuoterInterface_KEYSTONEPRICEDECIMALS_Call{Call: _e.mock.On("KEYSTONEPRICEDECIMALS", opts)} +} + +func (_c *FeeQuoterInterface_KEYSTONEPRICEDECIMALS_Call) Run(run func(opts *bind.CallOpts)) *FeeQuoterInterface_KEYSTONEPRICEDECIMALS_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*bind.CallOpts)) + }) + return _c +} + +func (_c *FeeQuoterInterface_KEYSTONEPRICEDECIMALS_Call) Return(_a0 *big.Int, _a1 error) *FeeQuoterInterface_KEYSTONEPRICEDECIMALS_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeQuoterInterface_KEYSTONEPRICEDECIMALS_Call) RunAndReturn(run func(*bind.CallOpts) (*big.Int, error)) *FeeQuoterInterface_KEYSTONEPRICEDECIMALS_Call { + _c.Call.Return(run) + return _c +} + // OnReport provides a mock function with given fields: opts, metadata, report func (_m *FeeQuoterInterface) OnReport(opts *bind.TransactOpts, metadata []byte, report []byte) (*types.Transaction, error) { ret := _m.Called(opts, metadata, report) From fc50683640bcfd73f0074d791fbaf7cdb6b29c71 Mon Sep 17 00:00:00 2001 From: nogo <110664798+0xnogo@users.noreply.github.com> Date: Wed, 11 Sep 2024 18:18:02 +0400 Subject: [PATCH 083/115] Fix RPCClient Deadlock on Unsubscribe and NewHead (#14236) (#1426) Cherry-pick of https://github.com/smartcontractkit/chainlink/pull/14236 --------- Co-authored-by: Dmytro Haidashenko <34754799+dhaidashenko@users.noreply.github.com> --- .changeset/curly-birds-guess.md | 5 +++++ core/chains/evm/client/rpc_client.go | 15 ++++++++----- core/chains/evm/client/rpc_client_test.go | 27 +++++++++++++++++++++++ 3 files changed, 41 insertions(+), 6 deletions(-) create mode 100644 .changeset/curly-birds-guess.md diff --git a/.changeset/curly-birds-guess.md b/.changeset/curly-birds-guess.md new file mode 100644 index 0000000000..c66bd54178 --- /dev/null +++ b/.changeset/curly-birds-guess.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +Fixed deadlock in RPCClient causing CL Node to stop performing RPC requests for the affected chain #bugfix diff --git a/core/chains/evm/client/rpc_client.go b/core/chains/evm/client/rpc_client.go index 07aa86fc45..72071199d4 100644 --- a/core/chains/evm/client/rpc_client.go +++ b/core/chains/evm/client/rpc_client.go @@ -141,6 +141,7 @@ type rpcClient struct { // stateMu since it can happen on state transitions as well as rpcClient Close. chStopInFlight chan struct{} + chainInfoLock sync.RWMutex // intercepted values seen by callers of the rpcClient excluding health check calls. Need to ensure MultiNode provides repeatable read guarantee highestUserObservations commonclient.ChainInfo // most recent chain info observed during current lifecycle (reseted on DisconnectAll) @@ -336,7 +337,9 @@ func (r *rpcClient) DisconnectAll() { } r.cancelInflightRequests() r.unsubscribeAll() + r.chainInfoLock.Lock() r.latestChainInfo = commonclient.ChainInfo{} + r.chainInfoLock.Unlock() } // unsubscribeAll unsubscribes all subscriptions @@ -1379,8 +1382,8 @@ func (r *rpcClient) onNewHead(ctx context.Context, requestCh <-chan struct{}, he return } - r.stateMu.Lock() - defer r.stateMu.Unlock() + r.chainInfoLock.Lock() + defer r.chainInfoLock.Unlock() if !commonclient.CtxIsHeathCheckRequest(ctx) { r.highestUserObservations.BlockNumber = max(r.highestUserObservations.BlockNumber, head.Number) r.highestUserObservations.TotalDifficulty = commonclient.MaxTotalDifficulty(r.highestUserObservations.TotalDifficulty, head.TotalDifficulty) @@ -1398,8 +1401,8 @@ func (r *rpcClient) onNewFinalizedHead(ctx context.Context, requestCh <-chan str if head == nil { return } - r.stateMu.Lock() - defer r.stateMu.Unlock() + r.chainInfoLock.Lock() + defer r.chainInfoLock.Unlock() if !commonclient.CtxIsHeathCheckRequest(ctx) { r.highestUserObservations.FinalizedBlockNumber = max(r.highestUserObservations.FinalizedBlockNumber, head.Number) } @@ -1412,8 +1415,8 @@ func (r *rpcClient) onNewFinalizedHead(ctx context.Context, requestCh <-chan str } func (r *rpcClient) GetInterceptedChainInfo() (latest, highestUserObservations commonclient.ChainInfo) { - r.stateMu.RLock() - defer r.stateMu.RUnlock() + r.chainInfoLock.RLock() + defer r.chainInfoLock.RUnlock() return r.latestChainInfo, r.highestUserObservations } diff --git a/core/chains/evm/client/rpc_client_test.go b/core/chains/evm/client/rpc_client_test.go index 1282188099..07e097727a 100644 --- a/core/chains/evm/client/rpc_client_test.go +++ b/core/chains/evm/client/rpc_client_test.go @@ -7,6 +7,7 @@ import ( "fmt" "math/big" "net/url" + "sync" "testing" "time" @@ -130,6 +131,32 @@ func TestRPCClient_SubscribeNewHead(t *testing.T) { assert.Equal(t, int64(0), highestUserObservations.FinalizedBlockNumber) assert.Equal(t, (*big.Int)(nil), highestUserObservations.TotalDifficulty) }) + t.Run("Concurrent Unsubscribe and onNewHead calls do not lead to a deadlock", func(t *testing.T) { + const numberOfAttempts = 1000 // need a large number to increase the odds of reproducing the issue + server := testutils.NewWSServer(t, chainId, serverCallBack) + wsURL := server.WSURL() + + rpc := client.NewRPCClient(lggr, *wsURL, nil, "rpc", 1, chainId, commonclient.Primary, 0, commonclient.QueryTimeout, commonclient.QueryTimeout, "") + defer rpc.Close() + require.NoError(t, rpc.Dial(ctx)) + var wg sync.WaitGroup + for i := 0; i < numberOfAttempts; i++ { + ch := make(chan *evmtypes.Head) + sub, err := rpc.SubscribeNewHead(tests.Context(t), ch) + require.NoError(t, err) + wg.Add(2) + go func() { + server.MustWriteBinaryMessageSync(t, makeNewHeadWSMessage(&evmtypes.Head{Number: 256, TotalDifficulty: big.NewInt(1000)})) + wg.Done() + }() + go func() { + rpc.UnsubscribeAllExceptAliveLoop() + sub.Unsubscribe() + wg.Done() + }() + wg.Wait() + } + }) t.Run("Block's chain ID matched configured", func(t *testing.T) { server := testutils.NewWSServer(t, chainId, serverCallBack) wsURL := server.WSURL() From fd212e6ba656ad7cd342a874e95a17ce778b1dbb Mon Sep 17 00:00:00 2001 From: kanth <70688600+defistar@users.noreply.github.com> Date: Thu, 12 Sep 2024 00:32:01 +0530 Subject: [PATCH 084/115] CCIP-2815 commit report event updates (#1407) ## Motivation OffRamp contract emits commitReport event as a Struct to make the event Log filtering and searching more optimized, the report properties are emitted as a event fields rather than emitting the struct --------- Co-authored-by: app-token-issuer-infra-releng[bot] <120227048+app-token-issuer-infra-releng[bot]@users.noreply.github.com> --- contracts/gas-snapshots/ccip.gas-snapshot | 74 ++++++++++--------- contracts/src/v0.8/ccip/offRamp/OffRamp.sol | 4 +- .../src/v0.8/ccip/test/offRamp/OffRamp.t.sol | 10 +-- .../ccip/generated/offramp/offramp.go | 22 ++---- ...rapper-dependency-versions-do-not-edit.txt | 2 +- 5 files changed, 55 insertions(+), 57 deletions(-) diff --git a/contracts/gas-snapshots/ccip.gas-snapshot b/contracts/gas-snapshots/ccip.gas-snapshot index 7a3587415c..5716e70328 100644 --- a/contracts/gas-snapshots/ccip.gas-snapshot +++ b/contracts/gas-snapshots/ccip.gas-snapshot @@ -560,7 +560,7 @@ MultiOCR3Base_transmit:test_UnauthorizedSigner_Revert() (gas: 61131) MultiOCR3Base_transmit:test_UnconfiguredPlugin_Revert() (gas: 39888) MultiOCR3Base_transmit:test_ZeroSignatures_Revert() (gas: 32971) MultiOnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 411709) -MultiRampsE2E:test_E2E_3MessagesMMultiOffRampSuccess_gas() (gas: 1527960) +MultiRampsE2E:test_E2E_3MessagesMMultiOffRampSuccess_gas() (gas: 1526954) NonceManager_NonceIncrementation:test_getIncrementedOutboundNonce_Success() (gas: 37916) NonceManager_NonceIncrementation:test_incrementInboundNonce_Skip() (gas: 23709) NonceManager_NonceIncrementation:test_incrementInboundNonce_Success() (gas: 38799) @@ -608,7 +608,7 @@ OCR2Base_transmit:test_Transmit2SignersSuccess_gas() (gas: 51689) OCR2Base_transmit:test_UnAuthorizedTransmitter_Revert() (gas: 23499) OCR2Base_transmit:test_UnauthorizedSigner_Revert() (gas: 39695) OCR2Base_transmit:test_WrongNumberOfSignatures_Revert() (gas: 20572) -OffRamp_afterOC3ConfigSet:test_afterOCR3ConfigSet_SignatureVerificationDisabled_Revert() (gas: 5849491) +OffRamp_afterOC3ConfigSet:test_afterOCR3ConfigSet_SignatureVerificationDisabled_Revert() (gas: 5841071) OffRamp_applySourceChainConfigUpdates:test_AddMultipleChains_Success() (gas: 468052) OffRamp_applySourceChainConfigUpdates:test_AddNewChain_Success() (gas: 99216) OffRamp_applySourceChainConfigUpdates:test_ApplyZeroUpdates_Success() (gas: 12392) @@ -626,42 +626,45 @@ OffRamp_batchExecute:test_SingleReport_Success() (gas: 155963) OffRamp_batchExecute:test_Unhealthy_Success() (gas: 573311) OffRamp_batchExecute:test_ZeroReports_Revert() (gas: 10440) OffRamp_ccipReceive:test_Reverts() (gas: 15705) -OffRamp_commit:test_FailedRMNVerification_Reverts() (gas: 64462) -OffRamp_commit:test_InvalidIntervalMinLargerThanMax_Revert() (gas: 67674) -OffRamp_commit:test_InvalidInterval_Revert() (gas: 59928) -OffRamp_commit:test_InvalidRootRevert() (gas: 58963) -OffRamp_commit:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6454659) -OffRamp_commit:test_NoConfig_Revert() (gas: 6038472) -OffRamp_commit:test_OnlyGasPriceUpdates_Success() (gas: 113541) -OffRamp_commit:test_OnlyPriceUpdateStaleReport_Revert() (gas: 121576) -OffRamp_commit:test_OnlyTokenPriceUpdates_Success() (gas: 113562) -OffRamp_commit:test_PriceSequenceNumberCleared_Success() (gas: 355724) -OffRamp_commit:test_ReportAndPriceUpdate_Success() (gas: 166923) -OffRamp_commit:test_ReportOnlyRootSuccess_gas() (gas: 141978) -OffRamp_commit:test_RootAlreadyCommitted_Revert() (gas: 142982) -OffRamp_commit:test_SourceChainNotEnabled_Revert() (gas: 59250) -OffRamp_commit:test_StaleReportWithRoot_Success() (gas: 240065) -OffRamp_commit:test_UnauthorizedTransmitter_Revert() (gas: 122475) -OffRamp_commit:test_Unhealthy_Revert() (gas: 57991) -OffRamp_commit:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 212393) -OffRamp_commit:test_ZeroEpochAndRound_Revert() (gas: 51324) -OffRamp_constructor:test_Constructor_Success() (gas: 6038780) -OffRamp_constructor:test_SourceChainSelector_Revert() (gas: 136917) -OffRamp_constructor:test_ZeroChainSelector_Revert() (gas: 103646) -OffRamp_constructor:test_ZeroNonceManager_Revert() (gas: 101523) -OffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 139565) -OffRamp_constructor:test_ZeroRMNRemote_Revert() (gas: 101452) -OffRamp_constructor:test_ZeroTokenAdminRegistry_Revert() (gas: 101467) +OffRamp_commit:test_InvalidIntervalMinLargerThanMax_Revert() (gas: 67657) +OffRamp_commit:test_InvalidInterval_Revert() (gas: 59911) +OffRamp_commit:test_InvalidRootRevert() (gas: 58946) +OffRamp_commit:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6445240) +OffRamp_commit:test_NoConfig_Revert() (gas: 6029053) +OffRamp_commit:test_OnlyGasPriceUpdates_Success() (gas: 112542) +OffRamp_commit:test_OnlyPriceUpdateStaleReport_Revert() (gas: 120551) +OffRamp_commit:test_OnlyTokenPriceUpdates_Success() (gas: 112563) +OffRamp_commit:test_PriceSequenceNumberCleared_Success() (gas: 353726) +OffRamp_commit:test_ReportAndPriceUpdate_Success() (gas: 165014) +OffRamp_commit:test_ReportOnlyRootSuccess_gas() (gas: 140069) +OffRamp_commit:test_RootAlreadyCommitted_Revert() (gas: 141975) +OffRamp_commit:test_SourceChainNotEnabled_Revert() (gas: 59233) +OffRamp_commit:test_StaleReportWithRoot_Success() (gas: 236247) +OffRamp_commit:test_UnauthorizedTransmitter_Revert() (gas: 121476) +OffRamp_commit:test_Unhealthy_Revert() (gas: 57974) +OffRamp_commit:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 209485) +OffRamp_commit:test_WrongConfigWithoutSigners_Revert() (gas: 6582277) +OffRamp_commit:test_ZeroEpochAndRound_Revert() (gas: 51298) +OffRamp_commit:test_FailedRMNVerification_Reverts() (gas: 64445) +OffRamp_constructor:test_ZeroRMNRemote_Revert() (gas: 101442) +OffRamp_manuallyExecute:test_manuallyExecute_SourceChainSelectorMismatch_Revert() (gas: 162246) +OffRamp_constructor:test_Constructor_Success() (gas: 6030360) +OffRamp_constructor:test_SourceChainSelector_Revert() (gas: 136908) +OffRamp_constructor:test_ZeroChainSelector_Revert() (gas: 103636) +OffRamp_constructor:test_ZeroNonceManager_Revert() (gas: 101513) +OffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 139555) +OffRamp_constructor:test_ZeroRMNProxy_Revert() (gas: 101652) +OffRamp_constructor:test_ZeroTokenAdminRegistry_Revert() (gas: 101457) OffRamp_execute:test_IncorrectArrayType_Revert() (gas: 17281) OffRamp_execute:test_LargeBatch_Success() (gas: 3378308) OffRamp_execute:test_MultipleReportsWithPartialValidationFailures_Success() (gas: 372457) OffRamp_execute:test_MultipleReports_Success() (gas: 298416) -OffRamp_execute:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6861122) -OffRamp_execute:test_NoConfig_Revert() (gas: 6085920) +OffRamp_execute:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6852702) +OffRamp_execute:test_NoConfig_Revert() (gas: 6077500) OffRamp_execute:test_NonArray_Revert() (gas: 27721) OffRamp_execute:test_SingleReport_Success() (gas: 175215) OffRamp_execute:test_UnauthorizedTransmitter_Revert() (gas: 147455) -OffRamp_execute:test_WrongConfigWithSigners_Revert() (gas: 6863865) +OffRamp_execute:test_WrongConfigWithSigners_Revert() (gas: 6855445) OffRamp_execute:test_ZeroReports_Revert() (gas: 17162) OffRamp_executeSingleMessage:test_MessageSender_Revert() (gas: 18212) OffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 249178) @@ -678,7 +681,7 @@ OffRamp_executeSingleReport:test_EmptyReport_Revert() (gas: 21860) OffRamp_executeSingleReport:test_InvalidSourcePoolAddress_Success() (gas: 502029) OffRamp_executeSingleReport:test_ManualExecutionNotYetEnabled_Revert() (gas: 47635) OffRamp_executeSingleReport:test_MismatchingDestChainSelector_Revert() (gas: 33895) -OffRamp_executeSingleReport:test_MismatchingOnRampRoot_Revert() (gas: 155054) +OffRamp_executeSingleReport:test_MismatchingOnRampRoot_Revert() (gas: 154048) OffRamp_executeSingleReport:test_NonExistingSourceChain_Revert() (gas: 28472) OffRamp_executeSingleReport:test_ReceiverError_Success() (gas: 187688) OffRamp_executeSingleReport:test_RetryFailedMessageWithoutManualExecution_Revert() (gas: 198173) @@ -712,7 +715,6 @@ OffRamp_manuallyExecute:test_manuallyExecute_GasLimitMismatchMultipleReports_Rev OffRamp_manuallyExecute:test_manuallyExecute_LowGasLimit_Success() (gas: 529914) OffRamp_manuallyExecute:test_manuallyExecute_MultipleReportsWithSingleCursedLane_Revert() (gas: 310504) OffRamp_manuallyExecute:test_manuallyExecute_ReentrancyFails_Success() (gas: 2327501) -OffRamp_manuallyExecute:test_manuallyExecute_SourceChainSelectorMismatch_Revert() (gas: 162246) OffRamp_manuallyExecute:test_manuallyExecute_Success() (gas: 224130) OffRamp_manuallyExecute:test_manuallyExecute_WithGasOverride_Success() (gas: 224711) OffRamp_manuallyExecute:test_manuallyExecute_WithMultiReportGasOverride_Success() (gas: 768287) @@ -731,6 +733,8 @@ OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_InvalidEVMAddress_Revert() OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_PoolDoesNotSupportDest_Reverts() (gas: 83403) OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_Success() (gas: 178169) OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals_Success() (gas: 191356) +OffRamp_resetUnblessedRoots:test_OnlyOwner_Revert() (gas: 11379) +OffRamp_resetUnblessedRoots:test_ResetUnblessedRoots_Success() (gas: 214632) OffRamp_setDynamicConfig:test_FeeQuoterZeroAddress_Revert() (gas: 11610) OffRamp_setDynamicConfig:test_NonOwner_Revert() (gas: 14177) OffRamp_setDynamicConfig:test_SetDynamicConfigWithValidator_Success() (gas: 49192) @@ -739,6 +743,10 @@ OffRamp_trialExecute:test_RateLimitError_Success() (gas: 225885) OffRamp_trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 234506) OffRamp_trialExecute:test_TokenPoolIsNotAContract_Success() (gas: 309185) OffRamp_trialExecute:test_trialExecute_Success() (gas: 284141) +OffRamp_verify:test_Blessed_Success() (gas: 175973) +OffRamp_verify:test_NotBlessedWrongChainSelector_Success() (gas: 178063) +OffRamp_verify:test_NotBlessed_Success() (gas: 140902) +OffRamp_verify:test_TooManyLeaves_Revert() (gas: 51510) OnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 390910) OnRamp_applyAllowListUpdates:test_applyAllowListUpdates_InvalidAllowListRequestDisabledAllowListWithAdds() (gas: 17746) OnRamp_applyAllowListUpdates:test_applyAllowListUpdates_Revert() (gas: 66535) diff --git a/contracts/src/v0.8/ccip/offRamp/OffRamp.sol b/contracts/src/v0.8/ccip/offRamp/OffRamp.sol index 9270214727..82e4a3de37 100644 --- a/contracts/src/v0.8/ccip/offRamp/OffRamp.sol +++ b/contracts/src/v0.8/ccip/offRamp/OffRamp.sol @@ -79,7 +79,7 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { event SkippedAlreadyExecutedMessage(uint64 sourceChainSelector, uint64 sequenceNumber); event AlreadyAttempted(uint64 sourceChainSelector, uint64 sequenceNumber); /// @dev RMN depends on this event, if changing, please notify the RMN maintainers. - event CommitReportAccepted(CommitReport report); + event CommitReportAccepted(Internal.MerkleRoot[] merkleRoots, Internal.PriceUpdates priceUpdates); event RootRemoved(bytes32 root); event SkippedReportExecution(uint64 sourceChainSelector); @@ -635,7 +635,7 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { s_roots[root.sourceChainSelector][merkleRoot] = block.timestamp; } - emit CommitReportAccepted(commitReport); + emit CommitReportAccepted(commitReport.merkleRoots, commitReport.priceUpdates); _transmit(uint8(Internal.OCRPluginType.Commit), reportContext, report, rs, ss, rawVs); } diff --git a/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol index cce4a19105..a2a7fff50a 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol @@ -3120,7 +3120,7 @@ contract OffRamp_commit is OffRampSetup { OffRamp.CommitReport memory commitReport = _constructCommitReport(); vm.expectEmit(); - emit OffRamp.CommitReportAccepted(commitReport); + emit OffRamp.CommitReportAccepted(commitReport.merkleRoots, commitReport.priceUpdates); vm.expectEmit(); emit MultiOCR3Base.Transmitted(uint8(Internal.OCRPluginType.Commit), s_configDigestCommit, s_latestSequenceNumber); @@ -3148,7 +3148,7 @@ contract OffRamp_commit is OffRampSetup { OffRamp.CommitReport({priceUpdates: _getEmptyPriceUpdates(), merkleRoots: roots, rmnSignatures: s_rmnSignatures}); vm.expectEmit(); - emit OffRamp.CommitReportAccepted(commitReport); + emit OffRamp.CommitReportAccepted(commitReport.merkleRoots, commitReport.priceUpdates); vm.expectEmit(); emit MultiOCR3Base.Transmitted(uint8(Internal.OCRPluginType.Commit), s_configDigestCommit, s_latestSequenceNumber); @@ -3176,7 +3176,7 @@ contract OffRamp_commit is OffRampSetup { OffRamp.CommitReport({priceUpdates: _getEmptyPriceUpdates(), merkleRoots: roots, rmnSignatures: s_rmnSignatures}); vm.expectEmit(); - emit OffRamp.CommitReportAccepted(commitReport); + emit OffRamp.CommitReportAccepted(commitReport.merkleRoots, commitReport.priceUpdates); vm.expectEmit(); emit MultiOCR3Base.Transmitted(uint8(Internal.OCRPluginType.Commit), s_configDigestCommit, s_latestSequenceNumber); @@ -3191,7 +3191,7 @@ contract OffRamp_commit is OffRampSetup { commitReport.merkleRoots[0].merkleRoot = "stale report 2"; vm.expectEmit(); - emit OffRamp.CommitReportAccepted(commitReport); + emit OffRamp.CommitReportAccepted(commitReport.merkleRoots, commitReport.priceUpdates); vm.expectEmit(); emit MultiOCR3Base.Transmitted(uint8(Internal.OCRPluginType.Commit), s_configDigestCommit, s_latestSequenceNumber); @@ -3327,7 +3327,7 @@ contract OffRamp_commit is OffRampSetup { commitReport.merkleRoots = roots; vm.expectEmit(); - emit OffRamp.CommitReportAccepted(commitReport); + emit OffRamp.CommitReportAccepted(commitReport.merkleRoots, commitReport.priceUpdates); vm.expectEmit(); emit MultiOCR3Base.Transmitted(uint8(Internal.OCRPluginType.Commit), s_configDigestCommit, s_latestSequenceNumber); diff --git a/core/gethwrappers/ccip/generated/offramp/offramp.go b/core/gethwrappers/ccip/generated/offramp/offramp.go index 60c42366cb..1711c3d1e2 100644 --- a/core/gethwrappers/ccip/generated/offramp/offramp.go +++ b/core/gethwrappers/ccip/generated/offramp/offramp.go @@ -43,11 +43,6 @@ type ClientEVMTokenAmount struct { Amount *big.Int } -type IRMNV2Signature struct { - R [32]byte - S [32]byte -} - type InternalAny2EVMRampMessage struct { Header InternalRampMessageHeader Sender []byte @@ -126,12 +121,6 @@ type MultiOCR3BaseOCRConfigArgs struct { Transmitters []common.Address } -type OffRampCommitReport struct { - PriceUpdates InternalPriceUpdates - MerkleRoots []InternalMerkleRoot - RmnSignatures []IRMNV2Signature -} - type OffRampDynamicConfig struct { FeeQuoter common.Address PermissionLessExecutionThresholdSeconds uint32 @@ -162,8 +151,8 @@ type OffRampStaticConfig struct { } var OffRampMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CanOnlySelfCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"actual\",\"type\":\"bytes32\"}],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ExecutionError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"ForkedChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enumMultiOCR3Base.InvalidConfigErrorType\",\"name\":\"errorType\",\"type\":\"uint8\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"got\",\"type\":\"uint256\"}],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidEVMAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"name\":\"InvalidInterval\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"newLimit\",\"type\":\"uint256\"}],\"name\":\"InvalidManualExecutionGasLimit\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"messageDestChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidMessageDestChainSelector\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"newState\",\"type\":\"uint8\"}],\"name\":\"InvalidNewState\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRoot\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidStaticConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LeavesCannotBeEmpty\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ManualExecutionGasLimitMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"ManualExecutionNotYetEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"errorReason\",\"type\":\"bytes\"}],\"name\":\"MessageValidationError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonUniqueSignatures\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"notPool\",\"type\":\"address\"}],\"name\":\"NotACompatiblePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OracleCannotBeZeroAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ReceiverError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountReleased\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePre\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePost\",\"type\":\"uint256\"}],\"name\":\"ReleaseOrMintBalanceMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"name\":\"RootAlreadyCommitted\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"RootNotCommitted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignatureVerificationDisabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignaturesOutOfRegistration\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"reportSourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"messageSourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainSelectorMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"StaleCommitReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"StaticConfigCannotBeChanged\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"TokenDataMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"TokenHandlingError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnexpectedTokenData\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"WrongMessageLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WrongNumberOfSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroChainSelectorNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"AlreadyAttempted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"structIRMNV2.Signature[]\",\"name\":\"rmnSignatures\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"report\",\"type\":\"tuple\"}],\"name\":\"CommitReportAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"DynamicConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"messageHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"name\":\"ExecutionStateChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"RootRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"SkippedAlreadyExecutedMessage\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SkippedReportExecution\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"sourceConfig\",\"type\":\"tuple\"}],\"name\":\"SourceChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainSelectorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"}],\"name\":\"StaticConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigUpdates\",\"type\":\"tuple[]\"}],\"name\":\"applySourceChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"destTokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structClient.Any2EVMMessage\",\"name\":\"\",\"type\":\"tuple\"}],\"name\":\"ccipReceive\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"rawVs\",\"type\":\"bytes32\"}],\"name\":\"commit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"execute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"bytes[]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[]\"}],\"name\":\"executeSingleMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"getExecutionState\",\"outputs\":[{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLatestPriceSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"getMerkleRoot\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"getSourceChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"latestConfigDetails\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"n\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"}],\"internalType\":\"structMultiOCR3Base.ConfigInfo\",\"name\":\"configInfo\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfig\",\"name\":\"ocrConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage[]\",\"name\":\"messages\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[][]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[][]\"},{\"internalType\":\"bytes32[]\",\"name\":\"proofs\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"proofFlagBits\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.ExecutionReportSingleChain[]\",\"name\":\"reports\",\"type\":\"tuple[]\"},{\"internalType\":\"uint256[][]\",\"name\":\"gasLimitOverrides\",\"type\":\"uint256[][]\"}],\"name\":\"manuallyExecute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"setDynamicConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfigArgs[]\",\"name\":\"ocrConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"setOCR3Configs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x6101206040523480156200001257600080fd5b5060405162006cca38038062006cca8339810160408190526200003591620008c7565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf81620001fa565b5050466080525060208301516001600160a01b03161580620000ec575060408301516001600160a01b0316155b8062000103575060608301516001600160a01b0316155b1562000122576040516342bcdf7f60e11b815260040160405180910390fd5b82516001600160401b03166000036200014e5760405163c656089560e01b815260040160405180910390fd5b82516001600160401b0390811660a052602080850180516001600160a01b0390811660c05260408088018051831660e0526060808a01805185166101005283518b519098168852945184169587019590955251821690850152905116908201527f683eb52ee924eb817377cfa8f41f238f4bb7a877da5267869dfffbad85f564d89060800160405180910390a1620001e682620002a5565b620001f181620003c1565b50505062000c67565b336001600160a01b03821603620002545760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b0316620002ce576040516342bcdf7f60e11b815260040160405180910390fd5b80516004805460208085018051604080880180516060808b0180516001600160a01b039b8c166001600160c01b0319909a168a17600160a01b63ffffffff98891602176001600160c01b0316600160c01b948816949094026001600160e01b031693909317600160e01b93871693909302929092179098556080808b018051600580546001600160a01b031916918d169190911790558451988952955185169688019690965290518316918601919091525116938301939093529151909216908201527fa55bd56595c45f517e5967a3067f3dca684445a3080e7c04a4e0d5a40cda627d9060a00160405180910390a150565b60005b815181101562000666576000828281518110620003e557620003e562000a1d565b60200260200101519050600081602001519050806001600160401b0316600003620004235760405163c656089560e01b815260040160405180910390fd5b81516001600160a01b03166200044c576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160401b0381166000908152600660205260408120600181018054919291620004789062000a33565b80601f0160208091040260200160405190810160405280929190818152602001828054620004a69062000a33565b8015620004f75780601f10620004cb57610100808354040283529160200191620004f7565b820191906000526020600020905b815481529060010190602001808311620004d957829003601f168201915b5050505050905060008460600151905081516000036200059e57805160000362000534576040516342bcdf7f60e11b815260040160405180910390fd5b6001830162000544828262000ac4565b508254600160a81b600160e81b031916600160a81b1783556040516001600160401b03851681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1620005d9565b8080519060200120828051906020012014620005d95760405163c39a620560e01b81526001600160401b038516600482015260240162000083565b604080860151845487516001600160a01b03166001600160a01b0319921515600160a01b02929092166001600160a81b031990911617178455516001600160401b038516907f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b906200064d90869062000b90565b60405180910390a25050505050806001019050620003c4565b5050565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b0381118282101715620006a557620006a56200066a565b60405290565b604051601f8201601f191681016001600160401b0381118282101715620006d657620006d66200066a565b604052919050565b80516001600160401b0381168114620006f657600080fd5b919050565b6001600160a01b03811681146200071157600080fd5b50565b805163ffffffff81168114620006f657600080fd5b6000601f83601f8401126200073d57600080fd5b825160206001600160401b03808311156200075c576200075c6200066a565b8260051b6200076d838201620006ab565b93845286810183019383810190898611156200078857600080fd5b84890192505b85831015620008ba57825184811115620007a85760008081fd5b89016080601f19828d038101821315620007c25760008081fd5b620007cc62000680565b88840151620007db81620006fb565b81526040620007ec858201620006de565b8a8301526060808601518015158114620008065760008081fd5b838301529385015193898511156200081e5760008081fd5b84860195508f603f8701126200083657600094508485fd5b8a8601519450898511156200084f576200084f6200066a565b620008608b858f88011601620006ab565b93508484528f82868801011115620008785760008081fd5b60005b8581101562000898578681018301518582018d01528b016200087b565b5060009484018b0194909452509182015283525091840191908401906200078e565b9998505050505050505050565b6000806000838503610140811215620008df57600080fd5b6080811215620008ee57600080fd5b620008f862000680565b6200090386620006de565b815260208601516200091581620006fb565b602082015260408601516200092a81620006fb565b604082015260608601516200093f81620006fb565b6060820152935060a0607f19820112156200095957600080fd5b5060405160a081016001600160401b0380821183831017156200098057620009806200066a565b81604052608087015191506200099682620006fb565b818352620009a760a0880162000714565b6020840152620009ba60c0880162000714565b6040840152620009cd60e0880162000714565b60608401526101008701519150620009e582620006fb565b608083018290526101208701519294508083111562000a0357600080fd5b505062000a138682870162000729565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b600181811c9082168062000a4857607f821691505b60208210810362000a6957634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111562000abf576000816000526020600020601f850160051c8101602086101562000a9a5750805b601f850160051c820191505b8181101562000abb5782815560010162000aa6565b5050505b505050565b81516001600160401b0381111562000ae05762000ae06200066a565b62000af88162000af1845462000a33565b8462000a6f565b602080601f83116001811462000b30576000841562000b175750858301515b600019600386901b1c1916600185901b17855562000abb565b600085815260208120601f198616915b8281101562000b615788860151825594840194600190910190840162000b40565b508582101562000b805787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b602080825282546001600160a01b0381168383015260a081901c60ff161515604084015260a81c6001600160401b0316606083015260808083015260018084018054600093929190849062000be58162000a33565b8060a089015260c0600183166000811462000c09576001811462000c265762000c58565b60ff19841660c08b015260c083151560051b8b0101945062000c58565b85600052602060002060005b8481101562000c4f5781548c820185015290880190890162000c32565b8b0160c0019550505b50929998505050505050505050565b60805160a05160c05160e05161010051615fed62000cdd600039600081816102400152612a6b0152600081816102110152612f5f0152600081816101e20152818161077f0152818161098601526123ed0152600081816101b2015261267a0152600081816117db01526118270152615fed6000f3fe608060405234801561001057600080fd5b50600436106101515760003560e01c806379ba5097116100cd578063c673e58411610081578063e9d68a8e11610066578063e9d68a8e1461052a578063f2fde38b1461054a578063f716f99f1461055d57600080fd5b8063c673e584146104c5578063ccd37ba3146104e557600080fd5b80638da5cb5b116100b25780638da5cb5b14610484578063991a50181461049f578063a80036b4146104b257600080fd5b806379ba50971461046e57806385572ffb1461047657600080fd5b80632d04ab76116101245780633f4b04aa116101095780633f4b04aa146103365780635e36480c146103525780637437ff9f1461037257600080fd5b80632d04ab7614610310578063311cd5131461032357600080fd5b806304666f9c1461015657806305d938b51461016b57806306285c691461017e578063181f5a77146102c7575b600080fd5b61016961016436600461412b565b610570565b005b6101696101793660046147b5565b610584565b61027060408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316815250905090565b6040516102be9190815167ffffffffffffffff1681526020808301516001600160a01b0390811691830191909152604080840151821690830152606092830151169181019190915260800190565b60405180910390f35b6103036040518060400160405280601181526020017f4f666652616d7020312e362e302d64657600000000000000000000000000000081525081565b6040516102be9190614930565b61016961031e3660046149db565b610729565b610169610331366004614a8e565b610cbf565b60095460405167ffffffffffffffff90911681526020016102be565b610365610360366004614ae2565b610d28565b6040516102be9190614b3f565b6104116040805160a081018252600080825260208201819052918101829052606081018290526080810191909152506040805160a0810182526004546001600160a01b03808216835263ffffffff600160a01b83048116602085015278010000000000000000000000000000000000000000000000008304811694840194909452600160e01b9091049092166060820152600554909116608082015290565b6040516102be9190600060a0820190506001600160a01b03808451168352602084015163ffffffff808216602086015280604087015116604086015280606087015116606086015250508060808501511660808401525092915050565b610169610d7e565b610169610151366004614b4d565b6000546040516001600160a01b0390911681526020016102be565b6101696104ad366004614b9c565b610e3c565b6101696104c0366004614c10565b610e4d565b6104d86104d3366004614c7d565b6111c0565b6040516102be9190614cdd565b61051c6104f3366004614d52565b67ffffffffffffffff919091166000908152600860209081526040808320938352929052205490565b6040519081526020016102be565b61053d610538366004614d7c565b61131e565b6040516102be9190614d97565b610169610558366004614de5565b61142b565b61016961056b366004614e6a565b61143c565b61057861147e565b610581816114da565b50565b61058c6117d8565b8151815181146105c8576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b818110156107195760008482815181106105e7576105e7614fa8565b6020026020010151905060008160200151519050600085848151811061060f5761060f614fa8565b6020026020010151905080518214610653576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8281101561070a57600082828151811061067257610672614fa8565b6020026020010151905080600014610701578460200151828151811061069a5761069a614fa8565b6020026020010151608001518110156107015784516040517fc8e9605100000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260248101839052604481018290526064015b60405180910390fd5b50600101610656565b505050508060010190506105cb565b506107248383611859565b505050565b6000610737878901896151d7565b602081015151909150156107e357602081015160408083015190517fccd5af000000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169263ccd5af00926107b29260040161543d565b60006040518083038186803b1580156107ca57600080fd5b505afa1580156107de573d6000803e3d6000fd5b505050505b805151511515806107f957508051602001515115155b156108f95760095460208a01359067ffffffffffffffff808316911610156108b8576009805467ffffffffffffffff191667ffffffffffffffff83161790556004805483516040517f3937306f0000000000000000000000000000000000000000000000000000000081526001600160a01b0390921692633937306f9261088192910161551f565b600060405180830381600087803b15801561089b57600080fd5b505af11580156108af573d6000803e3d6000fd5b505050506108f7565b8160200151516000036108f7576040517f2261116700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b60005b816020015151811015610c085760008260200151828151811061092157610921614fa8565b602090810291909101015180516040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815277ffffffffffffffff00000000000000000000000000000000608083901b166004820152919250906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632cbc26bb90602401602060405180830381865afa1580156109cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109f19190615532565b15610a34576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff821660048201526024016106f8565b6000610a3f82611909565b6040840151815491925067ffffffffffffffff908116600160a81b90920416141580610a865750826060015167ffffffffffffffff16836040015167ffffffffffffffff16115b15610ae5578251604080850151606086015191517fd5e0f0d600000000000000000000000000000000000000000000000000000000815267ffffffffffffffff93841660048201529083166024820152911660448201526064016106f8565b608083015180610b21576040517f504570e300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b835167ffffffffffffffff16600090815260086020908152604080832084845290915290205415610b945783516040517f32cf0cbf00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602481018290526044016106f8565b6060840151610ba4906001615565565b82547fffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffff16600160a81b67ffffffffffffffff9283160217909255925116600090815260086020908152604080832094835293905291909120429055506001016108fc565b507f23bc80217a08968cec0790cd045b396fa7eea0a21af469e603329940b883d86d81604051610c38919061558d565b60405180910390a1610cb460008a8a8a8a8a8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808e0282810182019093528d82529093508d92508c9182918501908490808284376000920191909152508b9250611970915050565b505050505050505050565b610cff610cce828401846155e5565b6040805160008082526020820190925290610cf9565b6060815260200190600190039081610ce45790505b50611859565b604080516000808252602082019092529050610d22600185858585866000611970565b50505050565b6000610d366001600461561a565b6002610d43608085615643565b67ffffffffffffffff16610d57919061566a565b610d618585611ce7565b901c166003811115610d7557610d75614b15565b90505b92915050565b6001546001600160a01b03163314610dd85760405162461bcd60e51b815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064016106f8565b600080543373ffffffffffffffffffffffffffffffffffffffff19808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610e4461147e565b61058181611d2e565b333014610e86576040517f371a732800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160008082526020820190925281610ec3565b6040805180820190915260008082526020820152815260200190600190039081610e9c5790505b5060a08501515190915015610ef757610ef48460a00151856020015186606001518760000151602001518787611e94565b90505b6040805160a0810182528551518152855160209081015167ffffffffffffffff1681830152808701518351600094840192610f33929101614930565b60408051601f19818403018152918152908252878101516020830152018390526005549091506001600160a01b03168015611040576040517f08d450a10000000000000000000000000000000000000000000000000000000081526001600160a01b038216906308d450a190610fad908590600401615723565b600060405180830381600087803b158015610fc757600080fd5b505af1925050508015610fd8575060015b611040573d808015611006576040519150601f19603f3d011682016040523d82523d6000602084013e61100b565b606091505b50806040517f09c253250000000000000000000000000000000000000000000000000000000081526004016106f89190614930565b60408601515115801561105557506080860151155b8061106c575060608601516001600160a01b03163b155b806110ac575060608601516110aa906001600160a01b03167f85572ffb00000000000000000000000000000000000000000000000000000000611fb3565b155b156110b957505050505050565b855160209081015167ffffffffffffffff1660009081526006909152604080822054608089015160608a015192517f3cf9798300000000000000000000000000000000000000000000000000000000815284936001600160a01b0390931692633cf97983926111319289926113889291600401615736565b6000604051808303816000875af1158015611150573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526111789190810190615772565b5091509150816111b657806040517f0a8d6e8c0000000000000000000000000000000000000000000000000000000081526004016106f89190614930565b5050505050505050565b6112036040805160e081019091526000606082018181526080830182905260a0830182905260c08301919091528190815260200160608152602001606081525090565b60ff808316600090815260026020818152604092839020835160e081018552815460608201908152600183015480881660808401526101008104881660a0840152620100009004909616151560c0820152948552918201805484518184028101840190955280855292938583019390928301828280156112ac57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161128e575b505050505081526020016003820180548060200260200160405190810160405280929190818152602001828054801561130e57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116112f0575b5050505050815250509050919050565b604080516080808201835260008083526020808401829052838501829052606080850181905267ffffffffffffffff878116845260068352928690208651948501875280546001600160a01b0381168652600160a01b810460ff16151593860193909352600160a81b9092049092169483019490945260018401805493949293918401916113ab90615808565b80601f01602080910402602001604051908101604052809291908181526020018280546113d790615808565b801561130e5780601f106113f95761010080835404028352916020019161130e565b820191906000526020600020905b81548152906001019060200180831161140757505050919092525091949350505050565b61143361147e565b61058181611fcf565b61144461147e565b60005b815181101561147a5761147282828151811061146557611465614fa8565b6020026020010151612085565b600101611447565b5050565b6000546001600160a01b031633146114d85760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016106f8565b565b60005b815181101561147a5760008282815181106114fa576114fa614fa8565b602002602001015190506000816020015190508067ffffffffffffffff16600003611551576040517fc656089500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81516001600160a01b0316611579576040516342bcdf7f60e11b815260040160405180910390fd5b67ffffffffffffffff811660009081526006602052604081206001810180549192916115a490615808565b80601f01602080910402602001604051908101604052809291908181526020018280546115d090615808565b801561161d5780601f106115f25761010080835404028352916020019161161d565b820191906000526020600020905b81548152906001019060200180831161160057829003601f168201915b5050505050905060008460600151905081516000036116d5578051600003611658576040516342bcdf7f60e11b815260040160405180910390fd5b600183016116668282615892565b5082547fffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffff16600160a81b17835560405167ffffffffffffffff851681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1611728565b8080519060200120828051906020012014611728576040517fc39a620500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff851660048201526024016106f8565b604080860151845487516001600160a01b031673ffffffffffffffffffffffffffffffffffffffff19921515600160a01b02929092167fffffffffffffffffffffff000000000000000000000000000000000000000000909116171784555167ffffffffffffffff8516907f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b906117c0908690615952565b60405180910390a250505050508060010190506114dd565b467f0000000000000000000000000000000000000000000000000000000000000000146114d8576040517f0f01ce850000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060048201524660248201526044016106f8565b8151600003611893576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160408051600080825260208201909252911591905b8451811015611902576118fa8582815181106118c8576118c8614fa8565b6020026020010151846118f4578583815181106118e7576118e7614fa8565b6020026020010151612399565b83612399565b6001016118aa565b5050505050565b67ffffffffffffffff811660009081526006602052604081208054600160a01b900460ff16610d78576040517fed053c5900000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024016106f8565b60ff878116600090815260026020908152604080832081516080810183528154815260019091015480861693820193909352610100830485169181019190915262010000909104909216151560608301528735906119cf8760a4615a20565b9050826060015115611a175784516119e890602061566a565b86516119f590602061566a565b611a009060a0615a20565b611a0a9190615a20565b611a149082615a20565b90505b368114611a59576040517f8e1192e1000000000000000000000000000000000000000000000000000000008152600481018290523660248201526044016106f8565b5081518114611aa15781516040517f93df584c0000000000000000000000000000000000000000000000000000000081526004810191909152602481018290526044016106f8565b611aa96117d8565b60ff808a1660009081526003602090815260408083203384528252808320815180830190925280548086168352939491939092840191610100909104166002811115611af757611af7614b15565b6002811115611b0857611b08614b15565b9052509050600281602001516002811115611b2557611b25614b15565b148015611b795750600260008b60ff1660ff168152602001908152602001600020600301816000015160ff1681548110611b6157611b61614fa8565b6000918252602090912001546001600160a01b031633145b611baf576040517fda0f08e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50816060015115611c91576020820151611bca906001615a33565b60ff16855114611c06576040517f71253a2500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8351855114611c41576040517fa75d88af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008787604051611c53929190615a4c565b604051908190038120611c6a918b90602001615a5c565b604051602081830303815290604052805190602001209050611c8f8a82888888612d19565b505b6040805182815260208a81013567ffffffffffffffff169082015260ff8b16917f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef0910160405180910390a2505050505050505050565b67ffffffffffffffff8216600090815260076020526040812081611d0c608085615a70565b67ffffffffffffffff1681526020810191909152604001600020549392505050565b80516001600160a01b0316611d56576040516342bcdf7f60e11b815260040160405180910390fd5b80516004805460208085018051604080880180516060808b0180516001600160a01b039b8c167fffffffffffffffff000000000000000000000000000000000000000000000000909a168a17600160a01b63ffffffff988916021777ffffffffffffffffffffffffffffffffffffffffffffffff167801000000000000000000000000000000000000000000000000948816949094026001600160e01b031693909317600160e01b93871693909302929092179098556080808b0180516005805473ffffffffffffffffffffffffffffffffffffffff1916918d169190911790558451988952955185169688019690965290518316918601919091525116938301939093529151909216908201527fa55bd56595c45f517e5967a3067f3dca684445a3080e7c04a4e0d5a40cda627d9060a00160405180910390a150565b6060865167ffffffffffffffff811115611eb057611eb0613f42565b604051908082528060200260200182016040528015611ef557816020015b6040805180820190915260008082526020820152815260200190600190039081611ece5790505b50905060005b8751811015611fa757611f82888281518110611f1957611f19614fa8565b6020026020010151888888888887818110611f3657611f36614fa8565b9050602002810190611f489190615a97565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612efe92505050565b828281518110611f9457611f94614fa8565b6020908102919091010152600101611efb565b505b9695505050505050565b6000611fbe836132a3565b8015610d755750610d758383613307565b336001600160a01b038216036120275760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016106f8565b6001805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b806040015160ff166000036120b0576000604051631b3fab5160e11b81526004016106f89190615ade565b60208082015160ff8082166000908152600290935260408320600181015492939092839216900361211d57606084015160018201805491151562010000027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff909216919091179055612172565b6060840151600182015460ff6201000090910416151590151514612172576040517f87f6037c00000000000000000000000000000000000000000000000000000000815260ff841660048201526024016106f8565b60a08401518051610100101561219e576001604051631b3fab5160e11b81526004016106f89190615ade565b61220484846003018054806020026020016040519081016040528092919081815260200182805480156121fa57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116121dc575b50505050506133c2565b84606001511561230e5761227284846002018054806020026020016040519081016040528092919081815260200182805480156121fa576020028201919060005260206000209081546001600160a01b031681526001909101906020018083116121dc5750505050506133c2565b60808501518051610100101561229e576002604051631b3fab5160e11b81526004016106f89190615ade565b60408601516122ae906003615af8565b60ff168151116122d4576003604051631b3fab5160e11b81526004016106f89190615ade565b805160018401805461ff00191661010060ff8416021790556122ff9060028601906020840190613ebb565b5061230c8582600161342b565b505b61231a8482600261342b565b805161232f9060038501906020840190613ebb565b5060408581015160018401805460ff191660ff8316179055865180855560a088015192517fab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f547936123889389939260028a01929190615b14565b60405180910390a16119028461359f565b815181516040517f2cbc26bb000000000000000000000000000000000000000000000000000000008152608083901b77ffffffffffffffff00000000000000000000000000000000166004820152901515907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632cbc26bb90602401602060405180830381865afa15801561243c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124609190615532565b156124ec5780156124a9576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff831660048201526024016106f8565b60405167ffffffffffffffff831681527faab522ed53d887e56ed53dd37398a01aeef6a58e0fa77c2173beb9512d8949339060200160405180910390a150505050565b60006124f783611909565b600101805461250590615808565b80601f016020809104026020016040519081016040528092919081815260200182805461253190615808565b801561257e5780601f106125535761010080835404028352916020019161257e565b820191906000526020600020905b81548152906001019060200180831161256157829003601f168201915b505050602088015151929350505060008190036125c6576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8560400151518114612604576040517f57e0e08300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008167ffffffffffffffff81111561261f5761261f613f42565b604051908082528060200260200182016040528015612648578160200160208202803683370190505b50905060005b828110156127a15760008860200151828151811061266e5761266e614fa8565b602002602001015190507f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681600001516040015167ffffffffffffffff161461270157805160409081015190517f38432a2200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016106f8565b8667ffffffffffffffff1681600001516020015167ffffffffffffffff1614612771578051602001516040517f6c95f1eb00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808a16600483015290911660248201526044016106f8565b61277b818661360f565b83838151811061278d5761278d614fa8565b60209081029190910101525060010161264e565b5060006127b886838a606001518b60800151613731565b905080600003612800576040517f7dd17a7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff871660048201526024016106f8565b60005b83811015610cb45760005a905060008a60200151838151811061282857612828614fa8565b6020026020010151905060006128468a836000015160600151610d28565b9050600081600381111561285c5761285c614b15565b14806128795750600381600381111561287757612877614b15565b145b6128d1578151606001516040805167ffffffffffffffff808e16825290921660208301527f3b575419319662b2a6f5e2467d84521517a3382b908eb3d557bb3fdb0c50e23c91015b60405180910390a1505050612d11565b88156129a157600454600090600160a01b900463ffffffff166128f4874261561a565b11905080806129145750600382600381111561291257612912614b15565b145b612956576040517fa9cfc86200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8c1660048201526024016106f8565b8b858151811061296857612968614fa8565b602002602001015160001461299b578b858151811061298957612989614fa8565b60200260200101518360800181815250505b50612a02565b60008160038111156129b5576129b5614b15565b14612a02578151606001516040805167ffffffffffffffff808e16825290921660208301527f3ef2a99c550a751d4b0b261268f05a803dfb049ab43616a1ffb388f61fe6512091016128c1565b81516080015167ffffffffffffffff1615612af1576000816003811115612a2b57612a2b614b15565b03612af15781516080015160208301516040517fe0e03cae0000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169263e0e03cae92612aa2928f929190600401615bc0565b6020604051808303816000875af1158015612ac1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae59190615532565b612af157505050612d11565b60008c604001518581518110612b0957612b09614fa8565b6020026020010151905080518360a001515114612b6d578251606001516040517f1cfe6d8b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808e16600483015290911660248201526044016106f8565b612b818b846000015160600151600161376f565b600080612b8e8584613817565b91509150612ba58d8660000151606001518461376f565b8b15612c15576003826003811115612bbf57612bbf614b15565b03612c15576000846003811115612bd857612bd8614b15565b14612c15578451516040517f2b11b8d90000000000000000000000000000000000000000000000000000000081526106f891908390600401615bed565b6002826003811115612c2957612c29614b15565b14612c83576003826003811115612c4257612c42614b15565b14612c83578451606001516040517f926c5a3e0000000000000000000000000000000000000000000000000000000081526106f8918f918590600401615c06565b84600001516000015185600001516060015167ffffffffffffffff168e67ffffffffffffffff167f05665fe9ad095383d018353f4cbcba77e84db27dd215081bbf7cdf9ae6fbe48b8c8b81518110612cdd57612cdd614fa8565b602002602001015186865a612cf2908e61561a565b604051612d029493929190615c2c565b60405180910390a45050505050505b600101612803565b8251600090815b818110156111b6576000600188868460208110612d3f57612d3f614fa8565b612d4c91901a601b615a33565b898581518110612d5e57612d5e614fa8565b6020026020010151898681518110612d7857612d78614fa8565b602002602001015160405160008152602001604052604051612db6949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015612dd8573d6000803e3d6000fd5b505060408051601f1981015160ff808e166000908152600360209081528582206001600160a01b03851683528152858220858701909652855480841686529397509095509293928401916101009004166002811115612e3957612e39614b15565b6002811115612e4a57612e4a614b15565b9052509050600181602001516002811115612e6757612e67614b15565b14612e9e576040517fca31867a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051600160ff9091161b851615612ee1576040517ff67bc7c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806000015160ff166001901b851794505050806001019050612d20565b60408051808201909152600080825260208201526000612f2187602001516138e1565b6040517fbbe4f6db0000000000000000000000000000000000000000000000000000000081526001600160a01b0380831660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063bbe4f6db90602401602060405180830381865afa158015612fa6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fca9190615c63565b90506001600160a01b038116158061301257506130106001600160a01b0382167faff2afbf00000000000000000000000000000000000000000000000000000000611fb3565b155b15613054576040517fae9b4ce90000000000000000000000000000000000000000000000000000000081526001600160a01b03821660048201526024016106f8565b60045460009081906130769089908690600160e01b900463ffffffff16613987565b9150915060008060006131436040518061010001604052808e81526020018c67ffffffffffffffff1681526020018d6001600160a01b031681526020018f606001518152602001896001600160a01b031681526020018f6000015181526020018f6040015181526020018b8152506040516024016130f49190615c80565b60408051601f198184030181529190526020810180516001600160e01b03167f390775370000000000000000000000000000000000000000000000000000000017905287866113886084613ab5565b9250925092508261318257816040517fe1cd55090000000000000000000000000000000000000000000000000000000081526004016106f89190614930565b81516020146131ca5781516040517f78ef80240000000000000000000000000000000000000000000000000000000081526020600482015260248101919091526044016106f8565b6000828060200190518101906131e09190615d4d565b9050866001600160a01b03168c6001600160a01b0316146132755760006132118d8a61320c868a61561a565b613987565b5090508681108061322b575081613228888361561a565b14155b15613273576040517fa966e21f0000000000000000000000000000000000000000000000000000000081526004810183905260248101889052604481018290526064016106f8565b505b604080518082019091526001600160a01b039098168852602088015250949550505050505095945050505050565b60006132cf827f01ffc9a700000000000000000000000000000000000000000000000000000000613307565b8015610d785750613300827fffffffff00000000000000000000000000000000000000000000000000000000613307565b1592915050565b6040517fffffffff0000000000000000000000000000000000000000000000000000000082166024820152600090819060440160408051601f19818403018152919052602080820180516001600160e01b03167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825192935060009283928392909183918a617530fa92503d915060005190508280156133ab575060208210155b80156133b75750600081115b979650505050505050565b60005b81518110156107245760ff8316600090815260036020526040812083519091908490849081106133f7576133f7614fa8565b6020908102919091018101516001600160a01b03168252810191909152604001600020805461ffff191690556001016133c5565b60005b8251811015610d2257600083828151811061344b5761344b614fa8565b602002602001015190506000600281111561346857613468614b15565b60ff80871660009081526003602090815260408083206001600160a01b038716845290915290205461010090041660028111156134a7576134a7614b15565b146134c8576004604051631b3fab5160e11b81526004016106f89190615ade565b6001600160a01b038116613508576040517fd6c62c9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052808360ff16815260200184600281111561352e5761352e614b15565b905260ff80871660009081526003602090815260408083206001600160a01b0387168452825290912083518154931660ff198416811782559184015190929091839161ffff19161761010083600281111561358b5761358b614b15565b02179055509050505080600101905061342e565b60ff81166105815760ff808216600090815260026020526040902060010154620100009004166135fb576040517f7a3b4c9400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6009805467ffffffffffffffff1916905550565b815160208082015160409283015192516000938493613655937f2425b0b9f9054c76ff151b0a175b18f37a4a4e82013a72e9f15c9caa095ed21f93909291889101615d66565b60408051601f1981840301815290829052805160209182012086518051888401516060808b0151908401516080808d0151950151959761369e9794969395929491939101615d99565b604051602081830303815290604052805190602001208560400151805190602001208660a001516040516020016136d59190615e9e565b60408051601f198184030181528282528051602091820120908301969096528101939093526060830191909152608082015260a081019190915260c0015b60405160208183030381529060405280519060200120905092915050565b60008061373f858585613bdb565b67ffffffffffffffff8716600090815260086020908152604080832093835292905220549150505b949350505050565b6000600261377e608085615643565b67ffffffffffffffff16613792919061566a565b905060006137a08585611ce7565b9050816137af6001600461561a565b901b1916818360038111156137c6576137c6614b15565b67ffffffffffffffff871660009081526007602052604081209190921b929092179182916137f5608088615a70565b67ffffffffffffffff1681526020810191909152604001600020555050505050565b6040517fa80036b4000000000000000000000000000000000000000000000000000000008152600090606090309063a80036b49061385b9087908790600401615efe565b600060405180830381600087803b15801561387557600080fd5b505af1925050508015613886575060015b6138c5573d8080156138b4576040519150601f19603f3d011682016040523d82523d6000602084013e6138b9565b606091505b506003925090506138da565b50506040805160208101909152600081526002905b9250929050565b6000815160201461392057816040517f8d666f600000000000000000000000000000000000000000000000000000000081526004016106f89190614930565b6000828060200190518101906139369190615d4d565b90506001600160a01b0381118061394e575061040081105b15610d7857826040517f8d666f600000000000000000000000000000000000000000000000000000000081526004016106f89190614930565b6000806000806000613a01886040516024016139b291906001600160a01b0391909116815260200190565b60408051601f198184030181529190526020810180516001600160e01b03167f70a082310000000000000000000000000000000000000000000000000000000017905288886113886084613ab5565b92509250925082613a4057816040517fe1cd55090000000000000000000000000000000000000000000000000000000081526004016106f89190614930565b6020825114613a885781516040517f78ef80240000000000000000000000000000000000000000000000000000000081526020600482015260248101919091526044016106f8565b81806020019051810190613a9c9190615d4d565b613aa6828861561a565b94509450505050935093915050565b6000606060008361ffff1667ffffffffffffffff811115613ad857613ad8613f42565b6040519080825280601f01601f191660200182016040528015613b02576020820181803683370190505b509150863b613b35577f0c3b563c0000000000000000000000000000000000000000000000000000000060005260046000fd5b5a85811015613b68577fafa32a2c0000000000000000000000000000000000000000000000000000000060005260046000fd5b8590036040810481038710613ba1577f37c3be290000000000000000000000000000000000000000000000000000000060005260046000fd5b505a6000808a5160208c0160008c8cf193505a900390503d84811115613bc45750835b808352806000602085013e50955095509592505050565b8251825160009190818303613c1c576040517f11a6b26400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6101018211801590613c3057506101018111155b613c4d576040516309bde33960e01b815260040160405180910390fd5b60001982820101610100811115613c77576040516309bde33960e01b815260040160405180910390fd5b80600003613ca45786600081518110613c9257613c92614fa8565b60200260200101519350505050613e73565b60008167ffffffffffffffff811115613cbf57613cbf613f42565b604051908082528060200260200182016040528015613ce8578160200160208202803683370190505b50905060008080805b85811015613e125760006001821b8b811603613d4c5788851015613d35578c5160018601958e918110613d2657613d26614fa8565b60200260200101519050613d6e565b8551600185019487918110613d2657613d26614fa8565b8b5160018401938d918110613d6357613d63614fa8565b602002602001015190505b600089861015613d9e578d5160018701968f918110613d8f57613d8f614fa8565b60200260200101519050613dc0565b8651600186019588918110613db557613db5614fa8565b602002602001015190505b82851115613de1576040516309bde33960e01b815260040160405180910390fd5b613deb8282613e7a565b878481518110613dfd57613dfd614fa8565b60209081029190910101525050600101613cf1565b506001850382148015613e2457508683145b8015613e2f57508581145b613e4c576040516309bde33960e01b815260040160405180910390fd5b836001860381518110613e6157613e61614fa8565b60200260200101519750505050505050505b9392505050565b6000818310613e9257613e8d8284613e98565b610d75565b610d7583835b604080516001602082015290810183905260608101829052600090608001613713565b828054828255906000526020600020908101928215613f1d579160200282015b82811115613f1d578251825473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03909116178255602090920191600190910190613edb565b50613f29929150613f2d565b5090565b5b80821115613f295760008155600101613f2e565b634e487b7160e01b600052604160045260246000fd5b6040516080810167ffffffffffffffff81118282101715613f7b57613f7b613f42565b60405290565b60405160a0810167ffffffffffffffff81118282101715613f7b57613f7b613f42565b60405160c0810167ffffffffffffffff81118282101715613f7b57613f7b613f42565b6040805190810167ffffffffffffffff81118282101715613f7b57613f7b613f42565b6040516060810167ffffffffffffffff81118282101715613f7b57613f7b613f42565b604051601f8201601f1916810167ffffffffffffffff8111828210171561403657614036613f42565b604052919050565b600067ffffffffffffffff82111561405857614058613f42565b5060051b60200190565b6001600160a01b038116811461058157600080fd5b803567ffffffffffffffff8116811461408f57600080fd5b919050565b801515811461058157600080fd5b803561408f81614094565b600067ffffffffffffffff8211156140c7576140c7613f42565b50601f01601f191660200190565b600082601f8301126140e657600080fd5b81356140f96140f4826140ad565b61400d565b81815284602083860101111561410e57600080fd5b816020850160208301376000918101602001919091529392505050565b6000602080838503121561413e57600080fd5b823567ffffffffffffffff8082111561415657600080fd5b818501915085601f83011261416a57600080fd5b81356141786140f48261403e565b81815260059190911b8301840190848101908883111561419757600080fd5b8585015b8381101561423d578035858111156141b35760008081fd5b86016080818c03601f19018113156141cb5760008081fd5b6141d3613f58565b898301356141e081614062565b815260406141ef848201614077565b8b83015260608085013561420281614094565b8383015292840135928984111561421b57600091508182fd5b6142298f8d868801016140d5565b90830152508552505091860191860161419b565b5098975050505050505050565b600060a0828403121561425c57600080fd5b614264613f81565b90508135815261427660208301614077565b602082015261428760408301614077565b604082015261429860608301614077565b60608201526142a960808301614077565b608082015292915050565b803561408f81614062565b600082601f8301126142d057600080fd5b813560206142e06140f48361403e565b82815260059290921b840181019181810190868411156142ff57600080fd5b8286015b84811015611fa757803567ffffffffffffffff808211156143245760008081fd5b9088019060a0828b03601f190181131561433e5760008081fd5b614346613f81565b87840135838111156143585760008081fd5b6143668d8a838801016140d5565b8252506040808501358481111561437d5760008081fd5b61438b8e8b838901016140d5565b8a84015250606080860135858111156143a45760008081fd5b6143b28f8c838a01016140d5565b838501525060809150818601358184015250828501359250838311156143d85760008081fd5b6143e68d8a858801016140d5565b908201528652505050918301918301614303565b6000610140828403121561440d57600080fd5b614415613fa4565b9050614421838361424a565b815260a082013567ffffffffffffffff8082111561443e57600080fd5b61444a858386016140d5565b602084015260c084013591508082111561446357600080fd5b61446f858386016140d5565b604084015261448060e085016142b4565b606084015261010084013560808401526101208401359150808211156144a557600080fd5b506144b2848285016142bf565b60a08301525092915050565b600082601f8301126144cf57600080fd5b813560206144df6140f48361403e565b82815260059290921b840181019181810190868411156144fe57600080fd5b8286015b84811015611fa757803567ffffffffffffffff8111156145225760008081fd5b6145308986838b01016143fa565b845250918301918301614502565b600082601f83011261454f57600080fd5b8135602061455f6140f48361403e565b82815260059290921b8401810191818101908684111561457e57600080fd5b8286015b84811015611fa757803567ffffffffffffffff808211156145a257600080fd5b818901915089603f8301126145b657600080fd5b858201356145c66140f48261403e565b81815260059190911b830160400190878101908c8311156145e657600080fd5b604085015b8381101561461f5780358581111561460257600080fd5b6146118f6040838a01016140d5565b8452509189019189016145eb565b50875250505092840192508301614582565b600082601f83011261464257600080fd5b813560206146526140f48361403e565b8083825260208201915060208460051b87010193508684111561467457600080fd5b602086015b84811015611fa75780358352918301918301614679565b600082601f8301126146a157600080fd5b813560206146b16140f48361403e565b82815260059290921b840181019181810190868411156146d057600080fd5b8286015b84811015611fa757803567ffffffffffffffff808211156146f55760008081fd5b9088019060a0828b03601f190181131561470f5760008081fd5b614717613f81565b614722888501614077565b8152604080850135848111156147385760008081fd5b6147468e8b838901016144be565b8a840152506060808601358581111561475f5760008081fd5b61476d8f8c838a010161453e565b83850152506080915081860135858111156147885760008081fd5b6147968f8c838a0101614631565b91840191909152509190930135908301525083529183019183016146d4565b60008060408084860312156147c957600080fd5b833567ffffffffffffffff808211156147e157600080fd5b6147ed87838801614690565b945060209150818601358181111561480457600080fd5b8601601f8101881361481557600080fd5b80356148236140f48261403e565b81815260059190911b8201840190848101908a83111561484257600080fd5b8584015b838110156148ce5780358681111561485e5760008081fd5b8501603f81018d136148705760008081fd5b878101356148806140f48261403e565b81815260059190911b82018a0190898101908f8311156148a05760008081fd5b928b01925b828410156148be5783358252928a0192908a01906148a5565b8652505050918601918601614846565b50809750505050505050509250929050565b60005b838110156148fb5781810151838201526020016148e3565b50506000910152565b6000815180845261491c8160208601602086016148e0565b601f01601f19169290920160200192915050565b602081526000610d756020830184614904565b8060608101831015610d7857600080fd5b60008083601f84011261496657600080fd5b50813567ffffffffffffffff81111561497e57600080fd5b6020830191508360208285010111156138da57600080fd5b60008083601f8401126149a857600080fd5b50813567ffffffffffffffff8111156149c057600080fd5b6020830191508360208260051b85010111156138da57600080fd5b60008060008060008060008060e0898b0312156149f757600080fd5b614a018a8a614943565b9750606089013567ffffffffffffffff80821115614a1e57600080fd5b614a2a8c838d01614954565b909950975060808b0135915080821115614a4357600080fd5b614a4f8c838d01614996565b909750955060a08b0135915080821115614a6857600080fd5b50614a758b828c01614996565b999c989b50969995989497949560c00135949350505050565b600080600060808486031215614aa357600080fd5b614aad8585614943565b9250606084013567ffffffffffffffff811115614ac957600080fd5b614ad586828701614954565b9497909650939450505050565b60008060408385031215614af557600080fd5b614afe83614077565b9150614b0c60208401614077565b90509250929050565b634e487b7160e01b600052602160045260246000fd5b60048110614b3b57614b3b614b15565b9052565b60208101610d788284614b2b565b600060208284031215614b5f57600080fd5b813567ffffffffffffffff811115614b7657600080fd5b820160a08185031215613e7357600080fd5b803563ffffffff8116811461408f57600080fd5b600060a08284031215614bae57600080fd5b614bb6613f81565b8235614bc181614062565b8152614bcf60208401614b88565b6020820152614be060408401614b88565b6040820152614bf160608401614b88565b60608201526080830135614c0481614062565b60808201529392505050565b600080600060408486031215614c2557600080fd5b833567ffffffffffffffff80821115614c3d57600080fd5b614c49878388016143fa565b94506020860135915080821115614c5f57600080fd5b50614ad586828701614996565b803560ff8116811461408f57600080fd5b600060208284031215614c8f57600080fd5b610d7582614c6c565b60008151808452602080850194506020840160005b83811015614cd25781516001600160a01b031687529582019590820190600101614cad565b509495945050505050565b60208152600082518051602084015260ff602082015116604084015260ff604082015116606084015260608101511515608084015250602083015160c060a0840152614d2c60e0840182614c98565b90506040840151601f198483030160c0850152614d498282614c98565b95945050505050565b60008060408385031215614d6557600080fd5b614d6e83614077565b946020939093013593505050565b600060208284031215614d8e57600080fd5b610d7582614077565b602081526001600160a01b03825116602082015260208201511515604082015267ffffffffffffffff60408301511660608201526000606083015160808084015261376760a0840182614904565b600060208284031215614df757600080fd5b8135613e7381614062565b600082601f830112614e1357600080fd5b81356020614e236140f48361403e565b8083825260208201915060208460051b870101935086841115614e4557600080fd5b602086015b84811015611fa7578035614e5d81614062565b8352918301918301614e4a565b60006020808385031215614e7d57600080fd5b823567ffffffffffffffff80821115614e9557600080fd5b818501915085601f830112614ea957600080fd5b8135614eb76140f48261403e565b81815260059190911b83018401908481019088831115614ed657600080fd5b8585015b8381101561423d57803585811115614ef157600080fd5b860160c0818c03601f19011215614f085760008081fd5b614f10613fa4565b8882013581526040614f23818401614c6c565b8a8301526060614f34818501614c6c565b8284015260809150614f478285016140a2565b9083015260a08381013589811115614f5f5760008081fd5b614f6d8f8d83880101614e02565b838501525060c0840135915088821115614f875760008081fd5b614f958e8c84870101614e02565b9083015250845250918601918601614eda565b634e487b7160e01b600052603260045260246000fd5b80356001600160e01b038116811461408f57600080fd5b600082601f830112614fe657600080fd5b81356020614ff66140f48361403e565b82815260069290921b8401810191818101908684111561501557600080fd5b8286015b84811015611fa757604081890312156150325760008081fd5b61503a613fc7565b61504382614077565b8152615050858301614fbe565b81860152835291830191604001615019565b600082601f83011261507357600080fd5b813560206150836140f48361403e565b82815260059290921b840181019181810190868411156150a257600080fd5b8286015b84811015611fa757803567ffffffffffffffff808211156150c75760008081fd5b9088019060a0828b03601f19018113156150e15760008081fd5b6150e9613f81565b6150f4888501614077565b81526040808501358481111561510a5760008081fd5b6151188e8b838901016140d5565b8a840152506060935061512c848601614077565b90820152608061513d858201614077565b938201939093529201359082015283529183019183016150a6565b600082601f83011261516957600080fd5b813560206151796140f48361403e565b82815260069290921b8401810191818101908684111561519857600080fd5b8286015b84811015611fa757604081890312156151b55760008081fd5b6151bd613fc7565b81358152848201358582015283529183019160400161519c565b600060208083850312156151ea57600080fd5b823567ffffffffffffffff8082111561520257600080fd5b908401906060828703121561521657600080fd5b61521e613fea565b82358281111561522d57600080fd5b8301604081890381131561524057600080fd5b615248613fc7565b82358581111561525757600080fd5b8301601f81018b1361526857600080fd5b80356152766140f48261403e565b81815260069190911b8201890190898101908d83111561529557600080fd5b928a01925b828410156152e55785848f0312156152b25760008081fd5b6152ba613fc7565b84356152c581614062565b81526152d2858d01614fbe565b818d0152825292850192908a019061529a565b8452505050828701359150848211156152fd57600080fd5b6153098a838501614fd5565b8188015283525050828401358281111561532257600080fd5b61532e88828601615062565b8583015250604083013593508184111561534757600080fd5b61535387858501615158565b60408201529695505050505050565b600082825180855260208086019550808260051b84010181860160005b848110156153f457601f19868403018952815160a067ffffffffffffffff8083511686528683015182888801526153b883880182614904565b6040858101518416908901526060808601519093169288019290925250608092830151929095019190915250978301979083019060010161537f565b5090979650505050505050565b60008151808452602080850194506020840160005b83811015614cd2578151805188528301518388015260409096019590820190600101615416565b6040815260006154506040830185615362565b8281036020840152614d498185615401565b805160408084528151848201819052600092602091908201906060870190855b818110156154b957835180516001600160a01b031684528501516001600160e01b0316858401529284019291850191600101615482565b50508583015187820388850152805180835290840192506000918401905b80831015615513578351805167ffffffffffffffff1683528501516001600160e01b0316858301529284019260019290920191908501906154d7565b50979650505050505050565b602081526000610d756020830184615462565b60006020828403121561554457600080fd5b8151613e7381614094565b634e487b7160e01b600052601160045260246000fd5b67ffffffffffffffff8181168382160190808211156155865761558661554f565b5092915050565b6020815260008251606060208401526155a96080840182615462565b90506020840151601f19808584030160408601526155c78383615362565b9250604086015191508085840301606086015250614d498282615401565b6000602082840312156155f757600080fd5b813567ffffffffffffffff81111561560e57600080fd5b61376784828501614690565b81810381811115610d7857610d7861554f565b634e487b7160e01b600052601260045260246000fd5b600067ffffffffffffffff8084168061565e5761565e61562d565b92169190910692915050565b8082028115828204841417610d7857610d7861554f565b805182526000602067ffffffffffffffff81840151168185015260408084015160a060408701526156b560a0870182614904565b9050606085015186820360608801526156ce8282614904565b608087810151898303918a01919091528051808352908601935060009250908501905b8083101561551357835180516001600160a01b03168352860151868301529285019260019290920191908401906156f1565b602081526000610d756020830184615681565b6080815260006157496080830187615681565b61ffff9590951660208301525060408101929092526001600160a01b0316606090910152919050565b60008060006060848603121561578757600080fd5b835161579281614094565b602085015190935067ffffffffffffffff8111156157af57600080fd5b8401601f810186136157c057600080fd5b80516157ce6140f4826140ad565b8181528760208385010111156157e357600080fd5b6157f48260208301602086016148e0565b809450505050604084015190509250925092565b600181811c9082168061581c57607f821691505b60208210810361583c57634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115610724576000816000526020600020601f850160051c8101602086101561586b5750805b601f850160051c820191505b8181101561588a57828155600101615877565b505050505050565b815167ffffffffffffffff8111156158ac576158ac613f42565b6158c0816158ba8454615808565b84615842565b602080601f8311600181146158f557600084156158dd5750858301515b600019600386901b1c1916600185901b17855561588a565b600085815260208120601f198616915b8281101561592457888601518255948401946001909101908401615905565b50858210156159425787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6000602080835283546001600160a01b038116602085015260ff8160a01c161515604085015267ffffffffffffffff8160a81c166060850152506001808501608080860152600081546159a481615808565b8060a089015260c060018316600081146159c557600181146159e157615a11565b60ff19841660c08b015260c083151560051b8b01019450615a11565b85600052602060002060005b84811015615a085781548c82018501529088019089016159ed565b8b0160c0019550505b50929998505050505050505050565b80820180821115610d7857610d7861554f565b60ff8181168382160190811115610d7857610d7861554f565b8183823760009101908152919050565b828152606082602083013760800192915050565b600067ffffffffffffffff80841680615a8b57615a8b61562d565b92169190910492915050565b6000808335601e19843603018112615aae57600080fd5b83018035915067ffffffffffffffff821115615ac957600080fd5b6020019150368190038213156138da57600080fd5b6020810160058310615af257615af2614b15565b91905290565b60ff81811683821602908116908181146155865761558661554f565b600060a0820160ff881683526020878185015260a0604085015281875480845260c0860191508860005282600020935060005b81811015615b6c5784546001600160a01b031683526001948501949284019201615b47565b50508481036060860152865180825290820192508187019060005b81811015615bac5782516001600160a01b031685529383019391830191600101615b87565b50505060ff85166080850152509050611fa9565b600067ffffffffffffffff808616835280851660208401525060606040830152614d496060830184614904565b8281526040602082015260006137676040830184614904565b67ffffffffffffffff848116825283166020820152606081016137676040830184614b2b565b848152615c3c6020820185614b2b565b608060408201526000615c526080830185614904565b905082606083015295945050505050565b600060208284031215615c7557600080fd5b8151613e7381614062565b6020815260008251610100806020850152615c9f610120850183614904565b91506020850151615cbc604086018267ffffffffffffffff169052565b5060408501516001600160a01b038116606086015250606085015160808501526080850151615cf660a08601826001600160a01b03169052565b5060a0850151601f19808685030160c0870152615d138483614904565b935060c08701519150808685030160e0870152615d308483614904565b935060e0870151915080868503018387015250611fa98382614904565b600060208284031215615d5f57600080fd5b5051919050565b848152600067ffffffffffffffff808616602084015280851660408401525060806060830152611fa96080830184614904565b86815260c060208201526000615db260c0830188614904565b6001600160a01b039690961660408301525067ffffffffffffffff9384166060820152608081019290925290911660a09091015292915050565b600082825180855260208086019550808260051b84010181860160005b848110156153f457601f19868403018952815160a08151818652615e2f82870182614904565b9150508582015185820387870152615e478282614904565b91505060408083015186830382880152615e618382614904565b92505050606080830151818701525060808083015192508582038187015250615e8a8183614904565b9a86019a9450505090830190600101615e09565b602081526000610d756020830184615dec565b60008282518085526020808601955060208260051b8401016020860160005b848110156153f457601f19868403018952615eec838351614904565b98840198925090830190600101615ed0565b604081526000835180516040840152602081015167ffffffffffffffff80821660608601528060408401511660808601528060608401511660a08601528060808401511660c086015250505060208401516101408060e0850152615f66610180850183614904565b91506040860151603f198086850301610100870152615f858483614904565b935060608801519150615fa46101208701836001600160a01b03169052565b60808801518387015260a0880151925080868503016101608701525050615fcb8282615dec565b9150508281036020840152614d498185615eb156fea164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CanOnlySelfCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"actual\",\"type\":\"bytes32\"}],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ExecutionError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"ForkedChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enumMultiOCR3Base.InvalidConfigErrorType\",\"name\":\"errorType\",\"type\":\"uint8\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"got\",\"type\":\"uint256\"}],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidEVMAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"name\":\"InvalidInterval\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"newLimit\",\"type\":\"uint256\"}],\"name\":\"InvalidManualExecutionGasLimit\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"messageDestChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidMessageDestChainSelector\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"newState\",\"type\":\"uint8\"}],\"name\":\"InvalidNewState\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRoot\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidStaticConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LeavesCannotBeEmpty\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ManualExecutionGasLimitMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"ManualExecutionNotYetEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"errorReason\",\"type\":\"bytes\"}],\"name\":\"MessageValidationError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonUniqueSignatures\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"notPool\",\"type\":\"address\"}],\"name\":\"NotACompatiblePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OracleCannotBeZeroAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ReceiverError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountReleased\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePre\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePost\",\"type\":\"uint256\"}],\"name\":\"ReleaseOrMintBalanceMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"name\":\"RootAlreadyCommitted\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"RootNotCommitted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignatureVerificationDisabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignaturesOutOfRegistration\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"reportSourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"messageSourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainSelectorMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"StaleCommitReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"StaticConfigCannotBeChanged\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"TokenDataMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"TokenHandlingError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnexpectedTokenData\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"WrongMessageLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WrongNumberOfSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroChainSelectorNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"AlreadyAttempted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"indexed\":false,\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"}],\"name\":\"CommitReportAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"DynamicConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"messageHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"name\":\"ExecutionStateChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"RootRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"SkippedAlreadyExecutedMessage\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SkippedReportExecution\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"sourceConfig\",\"type\":\"tuple\"}],\"name\":\"SourceChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainSelectorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"}],\"name\":\"StaticConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigUpdates\",\"type\":\"tuple[]\"}],\"name\":\"applySourceChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"destTokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structClient.Any2EVMMessage\",\"name\":\"\",\"type\":\"tuple\"}],\"name\":\"ccipReceive\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"rawVs\",\"type\":\"bytes32\"}],\"name\":\"commit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"execute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"bytes[]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[]\"}],\"name\":\"executeSingleMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"getExecutionState\",\"outputs\":[{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLatestPriceSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"getMerkleRoot\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"getSourceChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"latestConfigDetails\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"n\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"}],\"internalType\":\"structMultiOCR3Base.ConfigInfo\",\"name\":\"configInfo\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfig\",\"name\":\"ocrConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage[]\",\"name\":\"messages\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[][]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[][]\"},{\"internalType\":\"bytes32[]\",\"name\":\"proofs\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"proofFlagBits\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.ExecutionReportSingleChain[]\",\"name\":\"reports\",\"type\":\"tuple[]\"},{\"internalType\":\"uint256[][]\",\"name\":\"gasLimitOverrides\",\"type\":\"uint256[][]\"}],\"name\":\"manuallyExecute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"setDynamicConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfigArgs[]\",\"name\":\"ocrConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"setOCR3Configs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x6101206040523480156200001257600080fd5b5060405162006ca038038062006ca08339810160408190526200003591620008c7565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf81620001fa565b5050466080525060208301516001600160a01b03161580620000ec575060408301516001600160a01b0316155b8062000103575060608301516001600160a01b0316155b1562000122576040516342bcdf7f60e11b815260040160405180910390fd5b82516001600160401b03166000036200014e5760405163c656089560e01b815260040160405180910390fd5b82516001600160401b0390811660a052602080850180516001600160a01b0390811660c05260408088018051831660e0526060808a01805185166101005283518b519098168852945184169587019590955251821690850152905116908201527f683eb52ee924eb817377cfa8f41f238f4bb7a877da5267869dfffbad85f564d89060800160405180910390a1620001e682620002a5565b620001f181620003c1565b50505062000c67565b336001600160a01b03821603620002545760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b0316620002ce576040516342bcdf7f60e11b815260040160405180910390fd5b80516004805460208085018051604080880180516060808b0180516001600160a01b039b8c166001600160c01b0319909a168a17600160a01b63ffffffff98891602176001600160c01b0316600160c01b948816949094026001600160e01b031693909317600160e01b93871693909302929092179098556080808b018051600580546001600160a01b031916918d169190911790558451988952955185169688019690965290518316918601919091525116938301939093529151909216908201527fa55bd56595c45f517e5967a3067f3dca684445a3080e7c04a4e0d5a40cda627d9060a00160405180910390a150565b60005b815181101562000666576000828281518110620003e557620003e562000a1d565b60200260200101519050600081602001519050806001600160401b0316600003620004235760405163c656089560e01b815260040160405180910390fd5b81516001600160a01b03166200044c576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160401b0381166000908152600660205260408120600181018054919291620004789062000a33565b80601f0160208091040260200160405190810160405280929190818152602001828054620004a69062000a33565b8015620004f75780601f10620004cb57610100808354040283529160200191620004f7565b820191906000526020600020905b815481529060010190602001808311620004d957829003601f168201915b5050505050905060008460600151905081516000036200059e57805160000362000534576040516342bcdf7f60e11b815260040160405180910390fd5b6001830162000544828262000ac4565b508254600160a81b600160e81b031916600160a81b1783556040516001600160401b03851681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1620005d9565b8080519060200120828051906020012014620005d95760405163c39a620560e01b81526001600160401b038516600482015260240162000083565b604080860151845487516001600160a01b03166001600160a01b0319921515600160a01b02929092166001600160a81b031990911617178455516001600160401b038516907f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b906200064d90869062000b90565b60405180910390a25050505050806001019050620003c4565b5050565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b0381118282101715620006a557620006a56200066a565b60405290565b604051601f8201601f191681016001600160401b0381118282101715620006d657620006d66200066a565b604052919050565b80516001600160401b0381168114620006f657600080fd5b919050565b6001600160a01b03811681146200071157600080fd5b50565b805163ffffffff81168114620006f657600080fd5b6000601f83601f8401126200073d57600080fd5b825160206001600160401b03808311156200075c576200075c6200066a565b8260051b6200076d838201620006ab565b93845286810183019383810190898611156200078857600080fd5b84890192505b85831015620008ba57825184811115620007a85760008081fd5b89016080601f19828d038101821315620007c25760008081fd5b620007cc62000680565b88840151620007db81620006fb565b81526040620007ec858201620006de565b8a8301526060808601518015158114620008065760008081fd5b838301529385015193898511156200081e5760008081fd5b84860195508f603f8701126200083657600094508485fd5b8a8601519450898511156200084f576200084f6200066a565b620008608b858f88011601620006ab565b93508484528f82868801011115620008785760008081fd5b60005b8581101562000898578681018301518582018d01528b016200087b565b5060009484018b0194909452509182015283525091840191908401906200078e565b9998505050505050505050565b6000806000838503610140811215620008df57600080fd5b6080811215620008ee57600080fd5b620008f862000680565b6200090386620006de565b815260208601516200091581620006fb565b602082015260408601516200092a81620006fb565b604082015260608601516200093f81620006fb565b6060820152935060a0607f19820112156200095957600080fd5b5060405160a081016001600160401b0380821183831017156200098057620009806200066a565b81604052608087015191506200099682620006fb565b818352620009a760a0880162000714565b6020840152620009ba60c0880162000714565b6040840152620009cd60e0880162000714565b60608401526101008701519150620009e582620006fb565b608083018290526101208701519294508083111562000a0357600080fd5b505062000a138682870162000729565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b600181811c9082168062000a4857607f821691505b60208210810362000a6957634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111562000abf576000816000526020600020601f850160051c8101602086101562000a9a5750805b601f850160051c820191505b8181101562000abb5782815560010162000aa6565b5050505b505050565b81516001600160401b0381111562000ae05762000ae06200066a565b62000af88162000af1845462000a33565b8462000a6f565b602080601f83116001811462000b30576000841562000b175750858301515b600019600386901b1c1916600185901b17855562000abb565b600085815260208120601f198616915b8281101562000b615788860151825594840194600190910190840162000b40565b508582101562000b805787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b602080825282546001600160a01b0381168383015260a081901c60ff161515604084015260a81c6001600160401b0316606083015260808083015260018084018054600093929190849062000be58162000a33565b8060a089015260c0600183166000811462000c09576001811462000c265762000c58565b60ff19841660c08b015260c083151560051b8b0101945062000c58565b85600052602060002060005b8481101562000c4f5781548c820185015290880190890162000c32565b8b0160c0019550505b50929998505050505050505050565b60805160a05160c05160e05161010051615fc362000cdd600039600081816102400152612a730152600081816102110152612f670152600081816101e20152818161077f0152818161098601526123f50152600081816101b201526126820152600081816117e3015261182f0152615fc36000f3fe608060405234801561001057600080fd5b50600436106101515760003560e01c806379ba5097116100cd578063c673e58411610081578063e9d68a8e11610066578063e9d68a8e1461052a578063f2fde38b1461054a578063f716f99f1461055d57600080fd5b8063c673e584146104c5578063ccd37ba3146104e557600080fd5b80638da5cb5b116100b25780638da5cb5b14610484578063991a50181461049f578063a80036b4146104b257600080fd5b806379ba50971461046e57806385572ffb1461047657600080fd5b80632d04ab76116101245780633f4b04aa116101095780633f4b04aa146103365780635e36480c146103525780637437ff9f1461037257600080fd5b80632d04ab7614610310578063311cd5131461032357600080fd5b806304666f9c1461015657806305d938b51461016b57806306285c691461017e578063181f5a77146102c7575b600080fd5b610169610164366004614133565b610570565b005b6101696101793660046147bd565b610584565b61027060408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316815250905090565b6040516102be9190815167ffffffffffffffff1681526020808301516001600160a01b0390811691830191909152604080840151821690830152606092830151169181019190915260800190565b60405180910390f35b6103036040518060400160405280601181526020017f4f666652616d7020312e362e302d64657600000000000000000000000000000081525081565b6040516102be9190614938565b61016961031e3660046149e3565b610729565b610169610331366004614a96565b610cc7565b60095460405167ffffffffffffffff90911681526020016102be565b610365610360366004614aea565b610d30565b6040516102be9190614b47565b6104116040805160a081018252600080825260208201819052918101829052606081018290526080810191909152506040805160a0810182526004546001600160a01b03808216835263ffffffff600160a01b83048116602085015278010000000000000000000000000000000000000000000000008304811694840194909452600160e01b9091049092166060820152600554909116608082015290565b6040516102be9190600060a0820190506001600160a01b03808451168352602084015163ffffffff808216602086015280604087015116604086015280606087015116606086015250508060808501511660808401525092915050565b610169610d86565b610169610151366004614b55565b6000546040516001600160a01b0390911681526020016102be565b6101696104ad366004614ba4565b610e44565b6101696104c0366004614c18565b610e55565b6104d86104d3366004614c85565b6111c8565b6040516102be9190614ce5565b61051c6104f3366004614d5a565b67ffffffffffffffff919091166000908152600860209081526040808320938352929052205490565b6040519081526020016102be565b61053d610538366004614d84565b611326565b6040516102be9190614d9f565b610169610558366004614ded565b611433565b61016961056b366004614e72565b611444565b610578611486565b610581816114e2565b50565b61058c6117e0565b8151815181146105c8576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b818110156107195760008482815181106105e7576105e7614fb0565b6020026020010151905060008160200151519050600085848151811061060f5761060f614fb0565b6020026020010151905080518214610653576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8281101561070a57600082828151811061067257610672614fb0565b6020026020010151905080600014610701578460200151828151811061069a5761069a614fb0565b6020026020010151608001518110156107015784516040517fc8e9605100000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260248101839052604481018290526064015b60405180910390fd5b50600101610656565b505050508060010190506105cb565b506107248383611861565b505050565b6000610737878901896151df565b602081015151909150156107e357602081015160408083015190517fccd5af000000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169263ccd5af00926107b292600401615409565b60006040518083038186803b1580156107ca57600080fd5b505afa1580156107de573d6000803e3d6000fd5b505050505b805151511515806107f957508051602001515115155b156108f95760095460208a01359067ffffffffffffffff808316911610156108b8576009805467ffffffffffffffff191667ffffffffffffffff83161790556004805483516040517f3937306f0000000000000000000000000000000000000000000000000000000081526001600160a01b0390921692633937306f92610881929101615528565b600060405180830381600087803b15801561089b57600080fd5b505af11580156108af573d6000803e3d6000fd5b505050506108f7565b8160200151516000036108f7576040517f2261116700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b60005b816020015151811015610c085760008260200151828151811061092157610921614fb0565b602090810291909101015180516040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815277ffffffffffffffff00000000000000000000000000000000608083901b166004820152919250906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632cbc26bb90602401602060405180830381865afa1580156109cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109f1919061553b565b15610a34576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff821660048201526024016106f8565b6000610a3f82611911565b6040840151815491925067ffffffffffffffff908116600160a81b90920416141580610a865750826060015167ffffffffffffffff16836040015167ffffffffffffffff16115b15610ae5578251604080850151606086015191517fd5e0f0d600000000000000000000000000000000000000000000000000000000815267ffffffffffffffff93841660048201529083166024820152911660448201526064016106f8565b608083015180610b21576040517f504570e300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b835167ffffffffffffffff16600090815260086020908152604080832084845290915290205415610b945783516040517f32cf0cbf00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602481018290526044016106f8565b6060840151610ba490600161556e565b82547fffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffff16600160a81b67ffffffffffffffff9283160217909255925116600090815260086020908152604080832094835293905291909120429055506001016108fc565b50602081015181516040517f35c02761bcd3ef995c6a601a1981f4ed3934dcbe5041e24e286c89f5531d17e492610c40929091615596565b60405180910390a1610cbc60008a8a8a8a8a8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808e0282810182019093528d82529093508d92508c9182918501908490808284376000920191909152508b9250611978915050565b505050505050505050565b610d07610cd6828401846155bb565b6040805160008082526020820190925290610d01565b6060815260200190600190039081610cec5790505b50611861565b604080516000808252602082019092529050610d2a600185858585866000611978565b50505050565b6000610d3e600160046155f0565b6002610d4b608085615619565b67ffffffffffffffff16610d5f9190615640565b610d698585611cef565b901c166003811115610d7d57610d7d614b1d565b90505b92915050565b6001546001600160a01b03163314610de05760405162461bcd60e51b815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064016106f8565b600080543373ffffffffffffffffffffffffffffffffffffffff19808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610e4c611486565b61058181611d36565b333014610e8e576040517f371a732800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160008082526020820190925281610ecb565b6040805180820190915260008082526020820152815260200190600190039081610ea45790505b5060a08501515190915015610eff57610efc8460a00151856020015186606001518760000151602001518787611e9c565b90505b6040805160a0810182528551518152855160209081015167ffffffffffffffff1681830152808701518351600094840192610f3b929101614938565b60408051601f19818403018152918152908252878101516020830152018390526005549091506001600160a01b03168015611048576040517f08d450a10000000000000000000000000000000000000000000000000000000081526001600160a01b038216906308d450a190610fb59085906004016156f9565b600060405180830381600087803b158015610fcf57600080fd5b505af1925050508015610fe0575060015b611048573d80801561100e576040519150601f19603f3d011682016040523d82523d6000602084013e611013565b606091505b50806040517f09c253250000000000000000000000000000000000000000000000000000000081526004016106f89190614938565b60408601515115801561105d57506080860151155b80611074575060608601516001600160a01b03163b155b806110b4575060608601516110b2906001600160a01b03167f85572ffb00000000000000000000000000000000000000000000000000000000611fbb565b155b156110c157505050505050565b855160209081015167ffffffffffffffff1660009081526006909152604080822054608089015160608a015192517f3cf9798300000000000000000000000000000000000000000000000000000000815284936001600160a01b0390931692633cf9798392611139928992611388929160040161570c565b6000604051808303816000875af1158015611158573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526111809190810190615748565b5091509150816111be57806040517f0a8d6e8c0000000000000000000000000000000000000000000000000000000081526004016106f89190614938565b5050505050505050565b61120b6040805160e081019091526000606082018181526080830182905260a0830182905260c08301919091528190815260200160608152602001606081525090565b60ff808316600090815260026020818152604092839020835160e081018552815460608201908152600183015480881660808401526101008104881660a0840152620100009004909616151560c0820152948552918201805484518184028101840190955280855292938583019390928301828280156112b457602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611296575b505050505081526020016003820180548060200260200160405190810160405280929190818152602001828054801561131657602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116112f8575b5050505050815250509050919050565b604080516080808201835260008083526020808401829052838501829052606080850181905267ffffffffffffffff878116845260068352928690208651948501875280546001600160a01b0381168652600160a01b810460ff16151593860193909352600160a81b9092049092169483019490945260018401805493949293918401916113b3906157de565b80601f01602080910402602001604051908101604052809291908181526020018280546113df906157de565b80156113165780601f1061140157610100808354040283529160200191611316565b820191906000526020600020905b81548152906001019060200180831161140f57505050919092525091949350505050565b61143b611486565b61058181611fd7565b61144c611486565b60005b81518110156114825761147a82828151811061146d5761146d614fb0565b602002602001015161208d565b60010161144f565b5050565b6000546001600160a01b031633146114e05760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016106f8565b565b60005b815181101561148257600082828151811061150257611502614fb0565b602002602001015190506000816020015190508067ffffffffffffffff16600003611559576040517fc656089500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81516001600160a01b0316611581576040516342bcdf7f60e11b815260040160405180910390fd5b67ffffffffffffffff811660009081526006602052604081206001810180549192916115ac906157de565b80601f01602080910402602001604051908101604052809291908181526020018280546115d8906157de565b80156116255780601f106115fa57610100808354040283529160200191611625565b820191906000526020600020905b81548152906001019060200180831161160857829003601f168201915b5050505050905060008460600151905081516000036116dd578051600003611660576040516342bcdf7f60e11b815260040160405180910390fd5b6001830161166e8282615868565b5082547fffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffff16600160a81b17835560405167ffffffffffffffff851681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1611730565b8080519060200120828051906020012014611730576040517fc39a620500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff851660048201526024016106f8565b604080860151845487516001600160a01b031673ffffffffffffffffffffffffffffffffffffffff19921515600160a01b02929092167fffffffffffffffffffffff000000000000000000000000000000000000000000909116171784555167ffffffffffffffff8516907f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b906117c8908690615928565b60405180910390a250505050508060010190506114e5565b467f0000000000000000000000000000000000000000000000000000000000000000146114e0576040517f0f01ce850000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060048201524660248201526044016106f8565b815160000361189b576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160408051600080825260208201909252911591905b845181101561190a576119028582815181106118d0576118d0614fb0565b6020026020010151846118fc578583815181106118ef576118ef614fb0565b60200260200101516123a1565b836123a1565b6001016118b2565b5050505050565b67ffffffffffffffff811660009081526006602052604081208054600160a01b900460ff16610d80576040517fed053c5900000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024016106f8565b60ff878116600090815260026020908152604080832081516080810183528154815260019091015480861693820193909352610100830485169181019190915262010000909104909216151560608301528735906119d78760a46159f6565b9050826060015115611a1f5784516119f0906020615640565b86516119fd906020615640565b611a089060a06159f6565b611a1291906159f6565b611a1c90826159f6565b90505b368114611a61576040517f8e1192e1000000000000000000000000000000000000000000000000000000008152600481018290523660248201526044016106f8565b5081518114611aa95781516040517f93df584c0000000000000000000000000000000000000000000000000000000081526004810191909152602481018290526044016106f8565b611ab16117e0565b60ff808a1660009081526003602090815260408083203384528252808320815180830190925280548086168352939491939092840191610100909104166002811115611aff57611aff614b1d565b6002811115611b1057611b10614b1d565b9052509050600281602001516002811115611b2d57611b2d614b1d565b148015611b815750600260008b60ff1660ff168152602001908152602001600020600301816000015160ff1681548110611b6957611b69614fb0565b6000918252602090912001546001600160a01b031633145b611bb7576040517fda0f08e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50816060015115611c99576020820151611bd2906001615a09565b60ff16855114611c0e576040517f71253a2500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8351855114611c49576040517fa75d88af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008787604051611c5b929190615a22565b604051908190038120611c72918b90602001615a32565b604051602081830303815290604052805190602001209050611c978a82888888612d21565b505b6040805182815260208a81013567ffffffffffffffff169082015260ff8b16917f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef0910160405180910390a2505050505050505050565b67ffffffffffffffff8216600090815260076020526040812081611d14608085615a46565b67ffffffffffffffff1681526020810191909152604001600020549392505050565b80516001600160a01b0316611d5e576040516342bcdf7f60e11b815260040160405180910390fd5b80516004805460208085018051604080880180516060808b0180516001600160a01b039b8c167fffffffffffffffff000000000000000000000000000000000000000000000000909a168a17600160a01b63ffffffff988916021777ffffffffffffffffffffffffffffffffffffffffffffffff167801000000000000000000000000000000000000000000000000948816949094026001600160e01b031693909317600160e01b93871693909302929092179098556080808b0180516005805473ffffffffffffffffffffffffffffffffffffffff1916918d169190911790558451988952955185169688019690965290518316918601919091525116938301939093529151909216908201527fa55bd56595c45f517e5967a3067f3dca684445a3080e7c04a4e0d5a40cda627d9060a00160405180910390a150565b6060865167ffffffffffffffff811115611eb857611eb8613f4a565b604051908082528060200260200182016040528015611efd57816020015b6040805180820190915260008082526020820152815260200190600190039081611ed65790505b50905060005b8751811015611faf57611f8a888281518110611f2157611f21614fb0565b6020026020010151888888888887818110611f3e57611f3e614fb0565b9050602002810190611f509190615a6d565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612f0692505050565b828281518110611f9c57611f9c614fb0565b6020908102919091010152600101611f03565b505b9695505050505050565b6000611fc6836132ab565b8015610d7d5750610d7d838361330f565b336001600160a01b0382160361202f5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016106f8565b6001805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b806040015160ff166000036120b8576000604051631b3fab5160e11b81526004016106f89190615ab4565b60208082015160ff8082166000908152600290935260408320600181015492939092839216900361212557606084015160018201805491151562010000027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff90921691909117905561217a565b6060840151600182015460ff620100009091041615159015151461217a576040517f87f6037c00000000000000000000000000000000000000000000000000000000815260ff841660048201526024016106f8565b60a0840151805161010010156121a6576001604051631b3fab5160e11b81526004016106f89190615ab4565b61220c848460030180548060200260200160405190810160405280929190818152602001828054801561220257602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116121e4575b50505050506133ca565b8460600151156123165761227a8484600201805480602002602001604051908101604052809291908181526020018280548015612202576020028201919060005260206000209081546001600160a01b031681526001909101906020018083116121e45750505050506133ca565b6080850151805161010010156122a6576002604051631b3fab5160e11b81526004016106f89190615ab4565b60408601516122b6906003615ace565b60ff168151116122dc576003604051631b3fab5160e11b81526004016106f89190615ab4565b805160018401805461ff00191661010060ff8416021790556123079060028601906020840190613ec3565b5061231485826001613433565b505b61232284826002613433565b80516123379060038501906020840190613ec3565b5060408581015160018401805460ff191660ff8316179055865180855560a088015192517fab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f547936123909389939260028a01929190615aea565b60405180910390a161190a846135a7565b815181516040517f2cbc26bb000000000000000000000000000000000000000000000000000000008152608083901b77ffffffffffffffff00000000000000000000000000000000166004820152901515907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632cbc26bb90602401602060405180830381865afa158015612444573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612468919061553b565b156124f45780156124b1576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff831660048201526024016106f8565b60405167ffffffffffffffff831681527faab522ed53d887e56ed53dd37398a01aeef6a58e0fa77c2173beb9512d8949339060200160405180910390a150505050565b60006124ff83611911565b600101805461250d906157de565b80601f0160208091040260200160405190810160405280929190818152602001828054612539906157de565b80156125865780601f1061255b57610100808354040283529160200191612586565b820191906000526020600020905b81548152906001019060200180831161256957829003601f168201915b505050602088015151929350505060008190036125ce576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b856040015151811461260c576040517f57e0e08300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008167ffffffffffffffff81111561262757612627613f4a565b604051908082528060200260200182016040528015612650578160200160208202803683370190505b50905060005b828110156127a95760008860200151828151811061267657612676614fb0565b602002602001015190507f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681600001516040015167ffffffffffffffff161461270957805160409081015190517f38432a2200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016106f8565b8667ffffffffffffffff1681600001516020015167ffffffffffffffff1614612779578051602001516040517f6c95f1eb00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808a16600483015290911660248201526044016106f8565b6127838186613617565b83838151811061279557612795614fb0565b602090810291909101015250600101612656565b5060006127c086838a606001518b60800151613739565b905080600003612808576040517f7dd17a7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff871660048201526024016106f8565b60005b83811015610cbc5760005a905060008a60200151838151811061283057612830614fb0565b60200260200101519050600061284e8a836000015160600151610d30565b9050600081600381111561286457612864614b1d565b14806128815750600381600381111561287f5761287f614b1d565b145b6128d9578151606001516040805167ffffffffffffffff808e16825290921660208301527f3b575419319662b2a6f5e2467d84521517a3382b908eb3d557bb3fdb0c50e23c91015b60405180910390a1505050612d19565b88156129a957600454600090600160a01b900463ffffffff166128fc87426155f0565b119050808061291c5750600382600381111561291a5761291a614b1d565b145b61295e576040517fa9cfc86200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8c1660048201526024016106f8565b8b858151811061297057612970614fb0565b60200260200101516000146129a3578b858151811061299157612991614fb0565b60200260200101518360800181815250505b50612a0a565b60008160038111156129bd576129bd614b1d565b14612a0a578151606001516040805167ffffffffffffffff808e16825290921660208301527f3ef2a99c550a751d4b0b261268f05a803dfb049ab43616a1ffb388f61fe6512091016128c9565b81516080015167ffffffffffffffff1615612af9576000816003811115612a3357612a33614b1d565b03612af95781516080015160208301516040517fe0e03cae0000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169263e0e03cae92612aaa928f929190600401615b96565b6020604051808303816000875af1158015612ac9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612aed919061553b565b612af957505050612d19565b60008c604001518581518110612b1157612b11614fb0565b6020026020010151905080518360a001515114612b75578251606001516040517f1cfe6d8b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808e16600483015290911660248201526044016106f8565b612b898b8460000151606001516001613777565b600080612b96858461381f565b91509150612bad8d86600001516060015184613777565b8b15612c1d576003826003811115612bc757612bc7614b1d565b03612c1d576000846003811115612be057612be0614b1d565b14612c1d578451516040517f2b11b8d90000000000000000000000000000000000000000000000000000000081526106f891908390600401615bc3565b6002826003811115612c3157612c31614b1d565b14612c8b576003826003811115612c4a57612c4a614b1d565b14612c8b578451606001516040517f926c5a3e0000000000000000000000000000000000000000000000000000000081526106f8918f918590600401615bdc565b84600001516000015185600001516060015167ffffffffffffffff168e67ffffffffffffffff167f05665fe9ad095383d018353f4cbcba77e84db27dd215081bbf7cdf9ae6fbe48b8c8b81518110612ce557612ce5614fb0565b602002602001015186865a612cfa908e6155f0565b604051612d0a9493929190615c02565b60405180910390a45050505050505b60010161280b565b8251600090815b818110156111be576000600188868460208110612d4757612d47614fb0565b612d5491901a601b615a09565b898581518110612d6657612d66614fb0565b6020026020010151898681518110612d8057612d80614fb0565b602002602001015160405160008152602001604052604051612dbe949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015612de0573d6000803e3d6000fd5b505060408051601f1981015160ff808e166000908152600360209081528582206001600160a01b03851683528152858220858701909652855480841686529397509095509293928401916101009004166002811115612e4157612e41614b1d565b6002811115612e5257612e52614b1d565b9052509050600181602001516002811115612e6f57612e6f614b1d565b14612ea6576040517fca31867a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051600160ff9091161b851615612ee9576040517ff67bc7c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806000015160ff166001901b851794505050806001019050612d28565b60408051808201909152600080825260208201526000612f2987602001516138e9565b6040517fbbe4f6db0000000000000000000000000000000000000000000000000000000081526001600160a01b0380831660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063bbe4f6db90602401602060405180830381865afa158015612fae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fd29190615c39565b90506001600160a01b038116158061301a57506130186001600160a01b0382167faff2afbf00000000000000000000000000000000000000000000000000000000611fbb565b155b1561305c576040517fae9b4ce90000000000000000000000000000000000000000000000000000000081526001600160a01b03821660048201526024016106f8565b600454600090819061307e9089908690600160e01b900463ffffffff1661398f565b91509150600080600061314b6040518061010001604052808e81526020018c67ffffffffffffffff1681526020018d6001600160a01b031681526020018f606001518152602001896001600160a01b031681526020018f6000015181526020018f6040015181526020018b8152506040516024016130fc9190615c56565b60408051601f198184030181529190526020810180516001600160e01b03167f390775370000000000000000000000000000000000000000000000000000000017905287866113886084613abd565b9250925092508261318a57816040517fe1cd55090000000000000000000000000000000000000000000000000000000081526004016106f89190614938565b81516020146131d25781516040517f78ef80240000000000000000000000000000000000000000000000000000000081526020600482015260248101919091526044016106f8565b6000828060200190518101906131e89190615d23565b9050866001600160a01b03168c6001600160a01b03161461327d5760006132198d8a613214868a6155f0565b61398f565b5090508681108061323357508161323088836155f0565b14155b1561327b576040517fa966e21f0000000000000000000000000000000000000000000000000000000081526004810183905260248101889052604481018290526064016106f8565b505b604080518082019091526001600160a01b039098168852602088015250949550505050505095945050505050565b60006132d7827f01ffc9a70000000000000000000000000000000000000000000000000000000061330f565b8015610d805750613308827fffffffff0000000000000000000000000000000000000000000000000000000061330f565b1592915050565b6040517fffffffff0000000000000000000000000000000000000000000000000000000082166024820152600090819060440160408051601f19818403018152919052602080820180516001600160e01b03167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825192935060009283928392909183918a617530fa92503d915060005190508280156133b3575060208210155b80156133bf5750600081115b979650505050505050565b60005b81518110156107245760ff8316600090815260036020526040812083519091908490849081106133ff576133ff614fb0565b6020908102919091018101516001600160a01b03168252810191909152604001600020805461ffff191690556001016133cd565b60005b8251811015610d2a57600083828151811061345357613453614fb0565b602002602001015190506000600281111561347057613470614b1d565b60ff80871660009081526003602090815260408083206001600160a01b038716845290915290205461010090041660028111156134af576134af614b1d565b146134d0576004604051631b3fab5160e11b81526004016106f89190615ab4565b6001600160a01b038116613510576040517fd6c62c9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052808360ff16815260200184600281111561353657613536614b1d565b905260ff80871660009081526003602090815260408083206001600160a01b0387168452825290912083518154931660ff198416811782559184015190929091839161ffff19161761010083600281111561359357613593614b1d565b021790555090505050806001019050613436565b60ff81166105815760ff80821660009081526002602052604090206001015462010000900416613603576040517f7a3b4c9400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6009805467ffffffffffffffff1916905550565b81516020808201516040928301519251600093849361365d937f2425b0b9f9054c76ff151b0a175b18f37a4a4e82013a72e9f15c9caa095ed21f93909291889101615d3c565b60408051601f1981840301815290829052805160209182012086518051888401516060808b0151908401516080808d015195015195976136a69794969395929491939101615d6f565b604051602081830303815290604052805190602001208560400151805190602001208660a001516040516020016136dd9190615e74565b60408051601f198184030181528282528051602091820120908301969096528101939093526060830191909152608082015260a081019190915260c0015b60405160208183030381529060405280519060200120905092915050565b600080613747858585613be3565b67ffffffffffffffff8716600090815260086020908152604080832093835292905220549150505b949350505050565b60006002613786608085615619565b67ffffffffffffffff1661379a9190615640565b905060006137a88585611cef565b9050816137b7600160046155f0565b901b1916818360038111156137ce576137ce614b1d565b67ffffffffffffffff871660009081526007602052604081209190921b929092179182916137fd608088615a46565b67ffffffffffffffff1681526020810191909152604001600020555050505050565b6040517fa80036b4000000000000000000000000000000000000000000000000000000008152600090606090309063a80036b4906138639087908790600401615ed4565b600060405180830381600087803b15801561387d57600080fd5b505af192505050801561388e575060015b6138cd573d8080156138bc576040519150601f19603f3d011682016040523d82523d6000602084013e6138c1565b606091505b506003925090506138e2565b50506040805160208101909152600081526002905b9250929050565b6000815160201461392857816040517f8d666f600000000000000000000000000000000000000000000000000000000081526004016106f89190614938565b60008280602001905181019061393e9190615d23565b90506001600160a01b03811180613956575061040081105b15610d8057826040517f8d666f600000000000000000000000000000000000000000000000000000000081526004016106f89190614938565b6000806000806000613a09886040516024016139ba91906001600160a01b0391909116815260200190565b60408051601f198184030181529190526020810180516001600160e01b03167f70a082310000000000000000000000000000000000000000000000000000000017905288886113886084613abd565b92509250925082613a4857816040517fe1cd55090000000000000000000000000000000000000000000000000000000081526004016106f89190614938565b6020825114613a905781516040517f78ef80240000000000000000000000000000000000000000000000000000000081526020600482015260248101919091526044016106f8565b81806020019051810190613aa49190615d23565b613aae82886155f0565b94509450505050935093915050565b6000606060008361ffff1667ffffffffffffffff811115613ae057613ae0613f4a565b6040519080825280601f01601f191660200182016040528015613b0a576020820181803683370190505b509150863b613b3d577f0c3b563c0000000000000000000000000000000000000000000000000000000060005260046000fd5b5a85811015613b70577fafa32a2c0000000000000000000000000000000000000000000000000000000060005260046000fd5b8590036040810481038710613ba9577f37c3be290000000000000000000000000000000000000000000000000000000060005260046000fd5b505a6000808a5160208c0160008c8cf193505a900390503d84811115613bcc5750835b808352806000602085013e50955095509592505050565b8251825160009190818303613c24576040517f11a6b26400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6101018211801590613c3857506101018111155b613c55576040516309bde33960e01b815260040160405180910390fd5b60001982820101610100811115613c7f576040516309bde33960e01b815260040160405180910390fd5b80600003613cac5786600081518110613c9a57613c9a614fb0565b60200260200101519350505050613e7b565b60008167ffffffffffffffff811115613cc757613cc7613f4a565b604051908082528060200260200182016040528015613cf0578160200160208202803683370190505b50905060008080805b85811015613e1a5760006001821b8b811603613d545788851015613d3d578c5160018601958e918110613d2e57613d2e614fb0565b60200260200101519050613d76565b8551600185019487918110613d2e57613d2e614fb0565b8b5160018401938d918110613d6b57613d6b614fb0565b602002602001015190505b600089861015613da6578d5160018701968f918110613d9757613d97614fb0565b60200260200101519050613dc8565b8651600186019588918110613dbd57613dbd614fb0565b602002602001015190505b82851115613de9576040516309bde33960e01b815260040160405180910390fd5b613df38282613e82565b878481518110613e0557613e05614fb0565b60209081029190910101525050600101613cf9565b506001850382148015613e2c57508683145b8015613e3757508581145b613e54576040516309bde33960e01b815260040160405180910390fd5b836001860381518110613e6957613e69614fb0565b60200260200101519750505050505050505b9392505050565b6000818310613e9a57613e958284613ea0565b610d7d565b610d7d83835b60408051600160208201529081018390526060810182905260009060800161371b565b828054828255906000526020600020908101928215613f25579160200282015b82811115613f25578251825473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03909116178255602090920191600190910190613ee3565b50613f31929150613f35565b5090565b5b80821115613f315760008155600101613f36565b634e487b7160e01b600052604160045260246000fd5b6040516080810167ffffffffffffffff81118282101715613f8357613f83613f4a565b60405290565b60405160a0810167ffffffffffffffff81118282101715613f8357613f83613f4a565b60405160c0810167ffffffffffffffff81118282101715613f8357613f83613f4a565b6040805190810167ffffffffffffffff81118282101715613f8357613f83613f4a565b6040516060810167ffffffffffffffff81118282101715613f8357613f83613f4a565b604051601f8201601f1916810167ffffffffffffffff8111828210171561403e5761403e613f4a565b604052919050565b600067ffffffffffffffff82111561406057614060613f4a565b5060051b60200190565b6001600160a01b038116811461058157600080fd5b803567ffffffffffffffff8116811461409757600080fd5b919050565b801515811461058157600080fd5b80356140978161409c565b600067ffffffffffffffff8211156140cf576140cf613f4a565b50601f01601f191660200190565b600082601f8301126140ee57600080fd5b81356141016140fc826140b5565b614015565b81815284602083860101111561411657600080fd5b816020850160208301376000918101602001919091529392505050565b6000602080838503121561414657600080fd5b823567ffffffffffffffff8082111561415e57600080fd5b818501915085601f83011261417257600080fd5b81356141806140fc82614046565b81815260059190911b8301840190848101908883111561419f57600080fd5b8585015b83811015614245578035858111156141bb5760008081fd5b86016080818c03601f19018113156141d35760008081fd5b6141db613f60565b898301356141e88161406a565b815260406141f784820161407f565b8b83015260608085013561420a8161409c565b8383015292840135928984111561422357600091508182fd5b6142318f8d868801016140dd565b9083015250855250509186019186016141a3565b5098975050505050505050565b600060a0828403121561426457600080fd5b61426c613f89565b90508135815261427e6020830161407f565b602082015261428f6040830161407f565b60408201526142a06060830161407f565b60608201526142b16080830161407f565b608082015292915050565b80356140978161406a565b600082601f8301126142d857600080fd5b813560206142e86140fc83614046565b82815260059290921b8401810191818101908684111561430757600080fd5b8286015b84811015611faf57803567ffffffffffffffff8082111561432c5760008081fd5b9088019060a0828b03601f19018113156143465760008081fd5b61434e613f89565b87840135838111156143605760008081fd5b61436e8d8a838801016140dd565b825250604080850135848111156143855760008081fd5b6143938e8b838901016140dd565b8a84015250606080860135858111156143ac5760008081fd5b6143ba8f8c838a01016140dd565b838501525060809150818601358184015250828501359250838311156143e05760008081fd5b6143ee8d8a858801016140dd565b90820152865250505091830191830161430b565b6000610140828403121561441557600080fd5b61441d613fac565b90506144298383614252565b815260a082013567ffffffffffffffff8082111561444657600080fd5b614452858386016140dd565b602084015260c084013591508082111561446b57600080fd5b614477858386016140dd565b604084015261448860e085016142bc565b606084015261010084013560808401526101208401359150808211156144ad57600080fd5b506144ba848285016142c7565b60a08301525092915050565b600082601f8301126144d757600080fd5b813560206144e76140fc83614046565b82815260059290921b8401810191818101908684111561450657600080fd5b8286015b84811015611faf57803567ffffffffffffffff81111561452a5760008081fd5b6145388986838b0101614402565b84525091830191830161450a565b600082601f83011261455757600080fd5b813560206145676140fc83614046565b82815260059290921b8401810191818101908684111561458657600080fd5b8286015b84811015611faf57803567ffffffffffffffff808211156145aa57600080fd5b818901915089603f8301126145be57600080fd5b858201356145ce6140fc82614046565b81815260059190911b830160400190878101908c8311156145ee57600080fd5b604085015b838110156146275780358581111561460a57600080fd5b6146198f6040838a01016140dd565b8452509189019189016145f3565b5087525050509284019250830161458a565b600082601f83011261464a57600080fd5b8135602061465a6140fc83614046565b8083825260208201915060208460051b87010193508684111561467c57600080fd5b602086015b84811015611faf5780358352918301918301614681565b600082601f8301126146a957600080fd5b813560206146b96140fc83614046565b82815260059290921b840181019181810190868411156146d857600080fd5b8286015b84811015611faf57803567ffffffffffffffff808211156146fd5760008081fd5b9088019060a0828b03601f19018113156147175760008081fd5b61471f613f89565b61472a88850161407f565b8152604080850135848111156147405760008081fd5b61474e8e8b838901016144c6565b8a84015250606080860135858111156147675760008081fd5b6147758f8c838a0101614546565b83850152506080915081860135858111156147905760008081fd5b61479e8f8c838a0101614639565b91840191909152509190930135908301525083529183019183016146dc565b60008060408084860312156147d157600080fd5b833567ffffffffffffffff808211156147e957600080fd5b6147f587838801614698565b945060209150818601358181111561480c57600080fd5b8601601f8101881361481d57600080fd5b803561482b6140fc82614046565b81815260059190911b8201840190848101908a83111561484a57600080fd5b8584015b838110156148d6578035868111156148665760008081fd5b8501603f81018d136148785760008081fd5b878101356148886140fc82614046565b81815260059190911b82018a0190898101908f8311156148a85760008081fd5b928b01925b828410156148c65783358252928a0192908a01906148ad565b865250505091860191860161484e565b50809750505050505050509250929050565b60005b838110156149035781810151838201526020016148eb565b50506000910152565b600081518084526149248160208601602086016148e8565b601f01601f19169290920160200192915050565b602081526000610d7d602083018461490c565b8060608101831015610d8057600080fd5b60008083601f84011261496e57600080fd5b50813567ffffffffffffffff81111561498657600080fd5b6020830191508360208285010111156138e257600080fd5b60008083601f8401126149b057600080fd5b50813567ffffffffffffffff8111156149c857600080fd5b6020830191508360208260051b85010111156138e257600080fd5b60008060008060008060008060e0898b0312156149ff57600080fd5b614a098a8a61494b565b9750606089013567ffffffffffffffff80821115614a2657600080fd5b614a328c838d0161495c565b909950975060808b0135915080821115614a4b57600080fd5b614a578c838d0161499e565b909750955060a08b0135915080821115614a7057600080fd5b50614a7d8b828c0161499e565b999c989b50969995989497949560c00135949350505050565b600080600060808486031215614aab57600080fd5b614ab5858561494b565b9250606084013567ffffffffffffffff811115614ad157600080fd5b614add8682870161495c565b9497909650939450505050565b60008060408385031215614afd57600080fd5b614b068361407f565b9150614b146020840161407f565b90509250929050565b634e487b7160e01b600052602160045260246000fd5b60048110614b4357614b43614b1d565b9052565b60208101610d808284614b33565b600060208284031215614b6757600080fd5b813567ffffffffffffffff811115614b7e57600080fd5b820160a08185031215613e7b57600080fd5b803563ffffffff8116811461409757600080fd5b600060a08284031215614bb657600080fd5b614bbe613f89565b8235614bc98161406a565b8152614bd760208401614b90565b6020820152614be860408401614b90565b6040820152614bf960608401614b90565b60608201526080830135614c0c8161406a565b60808201529392505050565b600080600060408486031215614c2d57600080fd5b833567ffffffffffffffff80821115614c4557600080fd5b614c5187838801614402565b94506020860135915080821115614c6757600080fd5b50614add8682870161499e565b803560ff8116811461409757600080fd5b600060208284031215614c9757600080fd5b610d7d82614c74565b60008151808452602080850194506020840160005b83811015614cda5781516001600160a01b031687529582019590820190600101614cb5565b509495945050505050565b60208152600082518051602084015260ff602082015116604084015260ff604082015116606084015260608101511515608084015250602083015160c060a0840152614d3460e0840182614ca0565b90506040840151601f198483030160c0850152614d518282614ca0565b95945050505050565b60008060408385031215614d6d57600080fd5b614d768361407f565b946020939093013593505050565b600060208284031215614d9657600080fd5b610d7d8261407f565b602081526001600160a01b03825116602082015260208201511515604082015267ffffffffffffffff60408301511660608201526000606083015160808084015261376f60a084018261490c565b600060208284031215614dff57600080fd5b8135613e7b8161406a565b600082601f830112614e1b57600080fd5b81356020614e2b6140fc83614046565b8083825260208201915060208460051b870101935086841115614e4d57600080fd5b602086015b84811015611faf578035614e658161406a565b8352918301918301614e52565b60006020808385031215614e8557600080fd5b823567ffffffffffffffff80821115614e9d57600080fd5b818501915085601f830112614eb157600080fd5b8135614ebf6140fc82614046565b81815260059190911b83018401908481019088831115614ede57600080fd5b8585015b8381101561424557803585811115614ef957600080fd5b860160c0818c03601f19011215614f105760008081fd5b614f18613fac565b8882013581526040614f2b818401614c74565b8a8301526060614f3c818501614c74565b8284015260809150614f4f8285016140aa565b9083015260a08381013589811115614f675760008081fd5b614f758f8d83880101614e0a565b838501525060c0840135915088821115614f8f5760008081fd5b614f9d8e8c84870101614e0a565b9083015250845250918601918601614ee2565b634e487b7160e01b600052603260045260246000fd5b80356001600160e01b038116811461409757600080fd5b600082601f830112614fee57600080fd5b81356020614ffe6140fc83614046565b82815260069290921b8401810191818101908684111561501d57600080fd5b8286015b84811015611faf576040818903121561503a5760008081fd5b615042613fcf565b61504b8261407f565b8152615058858301614fc6565b81860152835291830191604001615021565b600082601f83011261507b57600080fd5b8135602061508b6140fc83614046565b82815260059290921b840181019181810190868411156150aa57600080fd5b8286015b84811015611faf57803567ffffffffffffffff808211156150cf5760008081fd5b9088019060a0828b03601f19018113156150e95760008081fd5b6150f1613f89565b6150fc88850161407f565b8152604080850135848111156151125760008081fd5b6151208e8b838901016140dd565b8a840152506060935061513484860161407f565b90820152608061514585820161407f565b938201939093529201359082015283529183019183016150ae565b600082601f83011261517157600080fd5b813560206151816140fc83614046565b82815260069290921b840181019181810190868411156151a057600080fd5b8286015b84811015611faf57604081890312156151bd5760008081fd5b6151c5613fcf565b8135815284820135858201528352918301916040016151a4565b600060208083850312156151f257600080fd5b823567ffffffffffffffff8082111561520a57600080fd5b908401906060828703121561521e57600080fd5b615226613ff2565b82358281111561523557600080fd5b8301604081890381131561524857600080fd5b615250613fcf565b82358581111561525f57600080fd5b8301601f81018b1361527057600080fd5b803561527e6140fc82614046565b81815260069190911b8201890190898101908d83111561529d57600080fd5b928a01925b828410156152ed5785848f0312156152ba5760008081fd5b6152c2613fcf565b84356152cd8161406a565b81526152da858d01614fc6565b818d0152825292850192908a01906152a2565b84525050508287013591508482111561530557600080fd5b6153118a838501614fdd565b8188015283525050828401358281111561532a57600080fd5b6153368882860161506a565b8583015250604083013593508184111561534f57600080fd5b61535b87858501615160565b60408201529695505050505050565b600082825180855260208086019550808260051b84010181860160005b848110156153fc57601f19868403018952815160a067ffffffffffffffff8083511686528683015182888801526153c08388018261490c565b60408581015184169089015260608086015190931692880192909252506080928301519290950191909152509783019790830190600101615387565b5090979650505050505050565b6000604080835261541d604084018661536a565b83810360208581019190915285518083528682019282019060005b8181101561545d57845180518452840151848401529383019391850191600101615438565b509098975050505050505050565b805160408084528151848201819052600092602091908201906060870190855b818110156154c257835180516001600160a01b031684528501516001600160e01b031685840152928401929185019160010161548b565b50508583015187820388850152805180835290840192506000918401905b8083101561551c578351805167ffffffffffffffff1683528501516001600160e01b0316858301529284019260019290920191908501906154e0565b50979650505050505050565b602081526000610d7d602083018461546b565b60006020828403121561554d57600080fd5b8151613e7b8161409c565b634e487b7160e01b600052601160045260246000fd5b67ffffffffffffffff81811683821601908082111561558f5761558f615558565b5092915050565b6040815260006155a9604083018561536a565b8281036020840152614d51818561546b565b6000602082840312156155cd57600080fd5b813567ffffffffffffffff8111156155e457600080fd5b61376f84828501614698565b81810381811115610d8057610d80615558565b634e487b7160e01b600052601260045260246000fd5b600067ffffffffffffffff8084168061563457615634615603565b92169190910692915050565b8082028115828204841417610d8057610d80615558565b805182526000602067ffffffffffffffff81840151168185015260408084015160a0604087015261568b60a087018261490c565b9050606085015186820360608801526156a4828261490c565b608087810151898303918a01919091528051808352908601935060009250908501905b8083101561551c57835180516001600160a01b03168352860151868301529285019260019290920191908401906156c7565b602081526000610d7d6020830184615657565b60808152600061571f6080830187615657565b61ffff9590951660208301525060408101929092526001600160a01b0316606090910152919050565b60008060006060848603121561575d57600080fd5b83516157688161409c565b602085015190935067ffffffffffffffff81111561578557600080fd5b8401601f8101861361579657600080fd5b80516157a46140fc826140b5565b8181528760208385010111156157b957600080fd5b6157ca8260208301602086016148e8565b809450505050604084015190509250925092565b600181811c908216806157f257607f821691505b60208210810361581257634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115610724576000816000526020600020601f850160051c810160208610156158415750805b601f850160051c820191505b818110156158605782815560010161584d565b505050505050565b815167ffffffffffffffff81111561588257615882613f4a565b6158968161589084546157de565b84615818565b602080601f8311600181146158cb57600084156158b35750858301515b600019600386901b1c1916600185901b178555615860565b600085815260208120601f198616915b828110156158fa578886015182559484019460019091019084016158db565b50858210156159185787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6000602080835283546001600160a01b038116602085015260ff8160a01c161515604085015267ffffffffffffffff8160a81c1660608501525060018085016080808601526000815461597a816157de565b8060a089015260c0600183166000811461599b57600181146159b7576159e7565b60ff19841660c08b015260c083151560051b8b010194506159e7565b85600052602060002060005b848110156159de5781548c82018501529088019089016159c3565b8b0160c0019550505b50929998505050505050505050565b80820180821115610d8057610d80615558565b60ff8181168382160190811115610d8057610d80615558565b8183823760009101908152919050565b828152606082602083013760800192915050565b600067ffffffffffffffff80841680615a6157615a61615603565b92169190910492915050565b6000808335601e19843603018112615a8457600080fd5b83018035915067ffffffffffffffff821115615a9f57600080fd5b6020019150368190038213156138e257600080fd5b6020810160058310615ac857615ac8614b1d565b91905290565b60ff818116838216029081169081811461558f5761558f615558565b600060a0820160ff881683526020878185015260a0604085015281875480845260c0860191508860005282600020935060005b81811015615b425784546001600160a01b031683526001948501949284019201615b1d565b50508481036060860152865180825290820192508187019060005b81811015615b825782516001600160a01b031685529383019391830191600101615b5d565b50505060ff85166080850152509050611fb1565b600067ffffffffffffffff808616835280851660208401525060606040830152614d51606083018461490c565b82815260406020820152600061376f604083018461490c565b67ffffffffffffffff8481168252831660208201526060810161376f6040830184614b33565b848152615c126020820185614b33565b608060408201526000615c28608083018561490c565b905082606083015295945050505050565b600060208284031215615c4b57600080fd5b8151613e7b8161406a565b6020815260008251610100806020850152615c7561012085018361490c565b91506020850151615c92604086018267ffffffffffffffff169052565b5060408501516001600160a01b038116606086015250606085015160808501526080850151615ccc60a08601826001600160a01b03169052565b5060a0850151601f19808685030160c0870152615ce9848361490c565b935060c08701519150808685030160e0870152615d06848361490c565b935060e0870151915080868503018387015250611fb1838261490c565b600060208284031215615d3557600080fd5b5051919050565b848152600067ffffffffffffffff808616602084015280851660408401525060806060830152611fb1608083018461490c565b86815260c060208201526000615d8860c083018861490c565b6001600160a01b039690961660408301525067ffffffffffffffff9384166060820152608081019290925290911660a09091015292915050565b600082825180855260208086019550808260051b84010181860160005b848110156153fc57601f19868403018952815160a08151818652615e058287018261490c565b9150508582015185820387870152615e1d828261490c565b91505060408083015186830382880152615e37838261490c565b92505050606080830151818701525060808083015192508582038187015250615e60818361490c565b9a86019a9450505090830190600101615ddf565b602081526000610d7d6020830184615dc2565b60008282518085526020808601955060208260051b8401016020860160005b848110156153fc57601f19868403018952615ec283835161490c565b98840198925090830190600101615ea6565b604081526000835180516040840152602081015167ffffffffffffffff80821660608601528060408401511660808601528060608401511660a08601528060808401511660c086015250505060208401516101408060e0850152615f3c61018085018361490c565b91506040860151603f198086850301610100870152615f5b848361490c565b935060608801519150615f7a6101208701836001600160a01b03169052565b60808801518387015260a0880151925080868503016101608701525050615fa18282615dc2565b9150508281036020840152614d518185615e8756fea164736f6c6343000818000a", } var OffRampABI = OffRampMetaData.ABI @@ -807,8 +796,9 @@ func (it *OffRampCommitReportAcceptedIterator) Close() error { } type OffRampCommitReportAccepted struct { - Report OffRampCommitReport - Raw types.Log + MerkleRoots []InternalMerkleRoot + PriceUpdates InternalPriceUpdates + Raw types.Log } func (_OffRamp *OffRampFilterer) FilterCommitReportAccepted(opts *bind.FilterOpts) (*OffRampCommitReportAcceptedIterator, error) { @@ -2406,7 +2396,7 @@ func (OffRampAlreadyAttempted) Topic() common.Hash { } func (OffRampCommitReportAccepted) Topic() common.Hash { - return common.HexToHash("0x23bc80217a08968cec0790cd045b396fa7eea0a21af469e603329940b883d86d") + return common.HexToHash("0x35c02761bcd3ef995c6a601a1981f4ed3934dcbe5041e24e286c89f5531d17e4") } func (OffRampConfigSet) Topic() common.Hash { diff --git a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt index d327839ed5..fca7e971c4 100644 --- a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -23,7 +23,7 @@ multi_aggregate_rate_limiter: ../../../contracts/solc/v0.8.24/MultiAggregateRate multi_ocr3_helper: ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Helper.abi ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Helper.bin 6b56e0114a4d50797d30a34aecc2641ef340451d0c3fcb9d729bba4df2435122 nonce_manager: ../../../contracts/solc/v0.8.24/NonceManager/NonceManager.abi ../../../contracts/solc/v0.8.24/NonceManager/NonceManager.bin 6f64e1083b356c06ee66b9138e398b9c97a4cd3e8c9ec38cf3010cebc79af536 ocr3_config_encoder: ../../../contracts/solc/v0.8.24/IOCR3ConfigEncoder/IOCR3ConfigEncoder.abi ../../../contracts/solc/v0.8.24/IOCR3ConfigEncoder/IOCR3ConfigEncoder.bin 9254b35a86f00fde7b7193a033ca58f6521a66e87b9cf9da6ce5660082e79f5d -offramp: ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.abi ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.bin 741b4b66670c06c1b09408ec6706656c46e4c98b227111d99f80940cc5faad42 +offramp: ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.abi ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.bin ec0e067fe9cd81ff009b813be775638f53e6c4f17e38610a724304885c96cbf2 onramp: ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.abi ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.bin 594439983f963f4158f9c5009dee7cba4ee56be61900bb1d5b9108eaeac3d6a6 ping_pong_demo: ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.abi ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.bin c1c2f8a65c7ffd971899cae7fe62f2da57d09e936151e2b92163c4bebe699d6b price_registry: ../../../contracts/solc/v0.8.24/PriceRegistry/PriceRegistry.abi ../../../contracts/solc/v0.8.24/PriceRegistry/PriceRegistry.bin e7781d600c1bb7aa4620106af7f6e146a109b97f4cb6a7d06c9e15773340ecb2 From 49fde280f9b7b152617a5e42414568862f473bf2 Mon Sep 17 00:00:00 2001 From: Suryansh <39276431+0xsuryansh@users.noreply.github.com> Date: Thu, 12 Sep 2024 01:45:51 +0530 Subject: [PATCH 085/115] GasLimitOverride for manuallyExecute (#1375) ## Motivation 1. OffRamp should now use destExecData to extract the gas used for 2. Manual execution should enable user to override the gas amount for releaseOrMint per token. ## Solution 1. Removed int32 `maxTokenTransferGas` & `maxPoolReleaseOrMintGas` and used the gas encoded in `RampTokenAmount.destExecData` 2. add a new Struct which holds the receiverExecutionGasLimit and transferGasAmounts ``` struct GasLimitOverride { uint256 receiverExecutionGasLimit; uint256[] tokenGasOverrides; } ``` tokenGasOverrides is an array of GasLimits to be used during the relaseOrMint call for the specific tokenPool associated with token Note: The gas limit can not be lowered as that could cause the message to fail. If manual execution is done from an UNTOUCHED state and we would allow lower gas limit, anyone could grief by executing the message with lower gas limit than the DON would have used. This results in the message being marked FAILURE and the DON would not attempt it with the correct gas limit. for the above we have kept a check that `tokenGasOverrides` < gas encoded in `RampTokenAmount.destExecData` --------- Signed-off-by: 0xsuryansh Co-authored-by: app-token-issuer-infra-releng[bot] <120227048+app-token-issuer-infra-releng[bot]@users.noreply.github.com> --- contracts/gas-snapshots/ccip.gas-snapshot | 287 +++++++------- .../scripts/native_solc_compile_all_ccip | 2 +- contracts/src/v0.8/ccip/offRamp/OffRamp.sol | 98 +++-- .../src/v0.8/ccip/test/NonceManager.t.sol | 20 +- .../v0.8/ccip/test/e2e/MultiRampsEnd2End.sol | 4 + .../v0.8/ccip/test/helpers/OffRampHelper.sol | 18 +- .../receivers/ReentrancyAbuserMultiRamp.sol | 7 +- .../src/v0.8/ccip/test/offRamp/OffRamp.t.sol | 356 ++++++++++++------ .../v0.8/ccip/test/offRamp/OffRampSetup.t.sol | 12 +- .../ccip/deployment_test/deployment_test.go | 2 - .../ccip/generated/offramp/offramp.go | 35 +- ...rapper-dependency-versions-do-not-edit.txt | 2 +- 12 files changed, 517 insertions(+), 326 deletions(-) diff --git a/contracts/gas-snapshots/ccip.gas-snapshot b/contracts/gas-snapshots/ccip.gas-snapshot index 5716e70328..e6596d9f3c 100644 --- a/contracts/gas-snapshots/ccip.gas-snapshot +++ b/contracts/gas-snapshots/ccip.gas-snapshot @@ -560,18 +560,18 @@ MultiOCR3Base_transmit:test_UnauthorizedSigner_Revert() (gas: 61131) MultiOCR3Base_transmit:test_UnconfiguredPlugin_Revert() (gas: 39888) MultiOCR3Base_transmit:test_ZeroSignatures_Revert() (gas: 32971) MultiOnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 411709) -MultiRampsE2E:test_E2E_3MessagesMMultiOffRampSuccess_gas() (gas: 1526954) +MultiRampsE2E:test_E2E_3MessagesMMultiOffRampSuccess_gas() (gas: 1526826) NonceManager_NonceIncrementation:test_getIncrementedOutboundNonce_Success() (gas: 37916) NonceManager_NonceIncrementation:test_incrementInboundNonce_Skip() (gas: 23709) NonceManager_NonceIncrementation:test_incrementInboundNonce_Success() (gas: 38799) NonceManager_NonceIncrementation:test_incrementNoncesInboundAndOutbound_Success() (gas: 71898) -NonceManager_OffRampUpgrade:test_NoPrevOffRampForChain_Success() (gas: 259965) -NonceManager_OffRampUpgrade:test_UpgradedNonceNewSenderStartsAtZero_Success() (gas: 264107) -NonceManager_OffRampUpgrade:test_UpgradedNonceStartsAtV1Nonce_Success() (gas: 326950) -NonceManager_OffRampUpgrade:test_UpgradedOffRampNonceSkipsIfMsgInFlight_Success() (gas: 299064) +NonceManager_OffRampUpgrade:test_NoPrevOffRampForChain_Success() (gas: 260404) +NonceManager_OffRampUpgrade:test_UpgradedNonceNewSenderStartsAtZero_Success() (gas: 264546) +NonceManager_OffRampUpgrade:test_UpgradedNonceStartsAtV1Nonce_Success() (gas: 327828) +NonceManager_OffRampUpgrade:test_UpgradedOffRampNonceSkipsIfMsgInFlight_Success() (gas: 299527) NonceManager_OffRampUpgrade:test_UpgradedSenderNoncesReadsPreviousRampTransitive_Success() (gas: 244871) -NonceManager_OffRampUpgrade:test_UpgradedSenderNoncesReadsPreviousRamp_Success() (gas: 232986) -NonceManager_OffRampUpgrade:test_Upgraded_Success() (gas: 152870) +NonceManager_OffRampUpgrade:test_UpgradedSenderNoncesReadsPreviousRamp_Success() (gas: 232964) +NonceManager_OffRampUpgrade:test_Upgraded_Success() (gas: 153309) NonceManager_OnRampUpgrade:test_UpgradeNonceNewSenderStartsAtZero_Success() (gas: 168358) NonceManager_OnRampUpgrade:test_UpgradeNonceStartsAtV1Nonce_Success() (gas: 220193) NonceManager_OnRampUpgrade:test_UpgradeSenderNoncesReadsPreviousRamp_Success() (gas: 125157) @@ -608,145 +608,140 @@ OCR2Base_transmit:test_Transmit2SignersSuccess_gas() (gas: 51689) OCR2Base_transmit:test_UnAuthorizedTransmitter_Revert() (gas: 23499) OCR2Base_transmit:test_UnauthorizedSigner_Revert() (gas: 39695) OCR2Base_transmit:test_WrongNumberOfSignatures_Revert() (gas: 20572) -OffRamp_afterOC3ConfigSet:test_afterOCR3ConfigSet_SignatureVerificationDisabled_Revert() (gas: 5841071) -OffRamp_applySourceChainConfigUpdates:test_AddMultipleChains_Success() (gas: 468052) -OffRamp_applySourceChainConfigUpdates:test_AddNewChain_Success() (gas: 99216) -OffRamp_applySourceChainConfigUpdates:test_ApplyZeroUpdates_Success() (gas: 12392) -OffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChainOnRamp_Revert() (gas: 93196) -OffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChain_Success() (gas: 109927) -OffRamp_applySourceChainConfigUpdates:test_RouterAddress_Revert() (gas: 13266) -OffRamp_applySourceChainConfigUpdates:test_ZeroOnRampAddress_Revert() (gas: 18000) -OffRamp_applySourceChainConfigUpdates:test_ZeroSourceChainSelector_Revert() (gas: 15349) -OffRamp_batchExecute:test_MultipleReportsDifferentChainsSkipCursedChain_Success() (gas: 176901) -OffRamp_batchExecute:test_MultipleReportsDifferentChains_Success() (gas: 332739) -OffRamp_batchExecute:test_MultipleReportsSameChain_Success() (gas: 276107) -OffRamp_batchExecute:test_MultipleReportsSkipDuplicate_Success() (gas: 168045) -OffRamp_batchExecute:test_OutOfBoundsGasLimitsAccess_Revert() (gas: 187572) -OffRamp_batchExecute:test_SingleReport_Success() (gas: 155963) -OffRamp_batchExecute:test_Unhealthy_Success() (gas: 573311) -OffRamp_batchExecute:test_ZeroReports_Revert() (gas: 10440) -OffRamp_ccipReceive:test_Reverts() (gas: 15705) -OffRamp_commit:test_InvalidIntervalMinLargerThanMax_Revert() (gas: 67657) -OffRamp_commit:test_InvalidInterval_Revert() (gas: 59911) -OffRamp_commit:test_InvalidRootRevert() (gas: 58946) -OffRamp_commit:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6445240) -OffRamp_commit:test_NoConfig_Revert() (gas: 6029053) -OffRamp_commit:test_OnlyGasPriceUpdates_Success() (gas: 112542) -OffRamp_commit:test_OnlyPriceUpdateStaleReport_Revert() (gas: 120551) -OffRamp_commit:test_OnlyTokenPriceUpdates_Success() (gas: 112563) -OffRamp_commit:test_PriceSequenceNumberCleared_Success() (gas: 353726) -OffRamp_commit:test_ReportAndPriceUpdate_Success() (gas: 165014) -OffRamp_commit:test_ReportOnlyRootSuccess_gas() (gas: 140069) -OffRamp_commit:test_RootAlreadyCommitted_Revert() (gas: 141975) -OffRamp_commit:test_SourceChainNotEnabled_Revert() (gas: 59233) -OffRamp_commit:test_StaleReportWithRoot_Success() (gas: 236247) -OffRamp_commit:test_UnauthorizedTransmitter_Revert() (gas: 121476) -OffRamp_commit:test_Unhealthy_Revert() (gas: 57974) -OffRamp_commit:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 209485) -OffRamp_commit:test_WrongConfigWithoutSigners_Revert() (gas: 6582277) -OffRamp_commit:test_ZeroEpochAndRound_Revert() (gas: 51298) -OffRamp_commit:test_FailedRMNVerification_Reverts() (gas: 64445) -OffRamp_constructor:test_ZeroRMNRemote_Revert() (gas: 101442) -OffRamp_manuallyExecute:test_manuallyExecute_SourceChainSelectorMismatch_Revert() (gas: 162246) -OffRamp_constructor:test_Constructor_Success() (gas: 6030360) -OffRamp_constructor:test_SourceChainSelector_Revert() (gas: 136908) -OffRamp_constructor:test_ZeroChainSelector_Revert() (gas: 103636) -OffRamp_constructor:test_ZeroNonceManager_Revert() (gas: 101513) -OffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 139555) -OffRamp_constructor:test_ZeroRMNProxy_Revert() (gas: 101652) -OffRamp_constructor:test_ZeroTokenAdminRegistry_Revert() (gas: 101457) -OffRamp_execute:test_IncorrectArrayType_Revert() (gas: 17281) -OffRamp_execute:test_LargeBatch_Success() (gas: 3378308) -OffRamp_execute:test_MultipleReportsWithPartialValidationFailures_Success() (gas: 372457) -OffRamp_execute:test_MultipleReports_Success() (gas: 298416) -OffRamp_execute:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6852702) -OffRamp_execute:test_NoConfig_Revert() (gas: 6077500) -OffRamp_execute:test_NonArray_Revert() (gas: 27721) -OffRamp_execute:test_SingleReport_Success() (gas: 175215) -OffRamp_execute:test_UnauthorizedTransmitter_Revert() (gas: 147455) -OffRamp_execute:test_WrongConfigWithSigners_Revert() (gas: 6855445) -OffRamp_execute:test_ZeroReports_Revert() (gas: 17162) -OffRamp_executeSingleMessage:test_MessageSender_Revert() (gas: 18212) -OffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 249178) -OffRamp_executeSingleMessage:test_NonContract_Success() (gas: 20494) -OffRamp_executeSingleMessage:test_TokenHandlingError_Revert() (gas: 210308) -OffRamp_executeSingleMessage:test_ZeroGasDONExecution_Revert() (gas: 48776) -OffRamp_executeSingleMessage:test_executeSingleMessage_NoTokens_Success() (gas: 48260) -OffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidationNoRouterCall_Revert() (gas: 229570) -OffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidation_Revert() (gas: 86208) -OffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens_Success() (gas: 281045) -OffRamp_executeSingleMessage:test_executeSingleMessage_WithValidation_Success() (gas: 92487) -OffRamp_executeSingleReport:test_DisabledSourceChain_Revert() (gas: 28238) -OffRamp_executeSingleReport:test_EmptyReport_Revert() (gas: 21860) -OffRamp_executeSingleReport:test_InvalidSourcePoolAddress_Success() (gas: 502029) -OffRamp_executeSingleReport:test_ManualExecutionNotYetEnabled_Revert() (gas: 47635) -OffRamp_executeSingleReport:test_MismatchingDestChainSelector_Revert() (gas: 33895) -OffRamp_executeSingleReport:test_MismatchingOnRampRoot_Revert() (gas: 154048) -OffRamp_executeSingleReport:test_NonExistingSourceChain_Revert() (gas: 28472) -OffRamp_executeSingleReport:test_ReceiverError_Success() (gas: 187688) -OffRamp_executeSingleReport:test_RetryFailedMessageWithoutManualExecution_Revert() (gas: 198173) -OffRamp_executeSingleReport:test_RootNotCommitted_Revert() (gas: 40136) -OffRamp_executeSingleReport:test_RouterYULCall_Revert() (gas: 447500) -OffRamp_executeSingleReport:test_SingleMessageNoTokensOtherChain_Success() (gas: 247946) -OffRamp_executeSingleReport:test_SingleMessageNoTokensUnordered_Success() (gas: 192339) -OffRamp_executeSingleReport:test_SingleMessageNoTokens_Success() (gas: 211938) -OffRamp_executeSingleReport:test_SingleMessageToNonCCIPReceiver_Success() (gas: 259763) -OffRamp_executeSingleReport:test_SingleMessagesNoTokensSuccess_gas() (gas: 140974) -OffRamp_executeSingleReport:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 424565) -OffRamp_executeSingleReport:test_SkippedIncorrectNonce_Success() (gas: 59052) -OffRamp_executeSingleReport:test_TokenDataMismatch_Revert() (gas: 74143) -OffRamp_executeSingleReport:test_TwoMessagesWithTokensAndGE_Success() (gas: 596466) -OffRamp_executeSingleReport:test_TwoMessagesWithTokensSuccess_gas() (gas: 544340) -OffRamp_executeSingleReport:test_UnexpectedTokenData_Revert() (gas: 33678) -OffRamp_executeSingleReport:test_UnhealthySingleChainCurse_Revert() (gas: 569320) -OffRamp_executeSingleReport:test_Unhealthy_Success() (gas: 569334) -OffRamp_executeSingleReport:test_WithCurseOnAnotherSourceChain_Success() (gas: 474664) -OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessageUnordered_Success() (gas: 135508) -OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessage_Success() (gas: 164757) -OffRamp_getExecutionState:test_FillExecutionState_Success() (gas: 3635486) -OffRamp_getExecutionState:test_GetDifferentChainExecutionState_Success() (gas: 118398) -OffRamp_getExecutionState:test_GetExecutionState_Success() (gas: 87417) -OffRamp_manuallyExecute:test_ManualExecGasLimitMismatchSingleReport_Revert() (gas: 75569) -OffRamp_manuallyExecute:test_ManualExecInvalidGasLimit_Revert() (gas: 26442) -OffRamp_manuallyExecute:test_manuallyExecute_DoesNotRevertIfUntouched_Success() (gas: 171318) -OffRamp_manuallyExecute:test_manuallyExecute_FailedTx_Revert() (gas: 211218) -OffRamp_manuallyExecute:test_manuallyExecute_ForkedChain_Revert() (gas: 26060) -OffRamp_manuallyExecute:test_manuallyExecute_GasLimitMismatchMultipleReports_Revert() (gas: 152860) -OffRamp_manuallyExecute:test_manuallyExecute_LowGasLimit_Success() (gas: 529914) -OffRamp_manuallyExecute:test_manuallyExecute_MultipleReportsWithSingleCursedLane_Revert() (gas: 310504) -OffRamp_manuallyExecute:test_manuallyExecute_ReentrancyFails_Success() (gas: 2327501) -OffRamp_manuallyExecute:test_manuallyExecute_Success() (gas: 224130) -OffRamp_manuallyExecute:test_manuallyExecute_WithGasOverride_Success() (gas: 224711) -OffRamp_manuallyExecute:test_manuallyExecute_WithMultiReportGasOverride_Success() (gas: 768287) -OffRamp_manuallyExecute:test_manuallyExecute_WithPartialMessages_Success() (gas: 343255) -OffRamp_releaseOrMintSingleToken:test__releaseOrMintSingleToken_NotACompatiblePool_Revert() (gas: 40194) -OffRamp_releaseOrMintSingleToken:test__releaseOrMintSingleToken_Success() (gas: 107223) -OffRamp_releaseOrMintSingleToken:test__releaseOrMintSingleToken_TokenHandlingError_transfer_Revert() (gas: 88434) -OffRamp_releaseOrMintSingleToken:test_releaseOrMintToken_InvalidDataLength_Revert() (gas: 39933) -OffRamp_releaseOrMintSingleToken:test_releaseOrMintToken_ReleaseOrMintBalanceMismatch_Revert() (gas: 97495) -OffRamp_releaseOrMintSingleToken:test_releaseOrMintToken_TokenHandlingError_BalanceOf_Revert() (gas: 42919) -OffRamp_releaseOrMintSingleToken:test_releaseOrMintToken_skip_ReleaseOrMintBalanceMismatch_if_pool_Revert() (gas: 89679) -OffRamp_releaseOrMintTokens:test_TokenHandlingError_Reverts() (gas: 166024) -OffRamp_releaseOrMintTokens:test__releaseOrMintTokens_PoolIsNotAPool_Reverts() (gas: 24628) -OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_InvalidDataLengthReturnData_Revert() (gas: 66391) -OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_InvalidEVMAddress_Revert() (gas: 41350) -OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_PoolDoesNotSupportDest_Reverts() (gas: 83403) -OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_Success() (gas: 178169) -OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals_Success() (gas: 191356) -OffRamp_resetUnblessedRoots:test_OnlyOwner_Revert() (gas: 11379) -OffRamp_resetUnblessedRoots:test_ResetUnblessedRoots_Success() (gas: 214632) -OffRamp_setDynamicConfig:test_FeeQuoterZeroAddress_Revert() (gas: 11610) -OffRamp_setDynamicConfig:test_NonOwner_Revert() (gas: 14177) -OffRamp_setDynamicConfig:test_SetDynamicConfigWithValidator_Success() (gas: 49192) -OffRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 27137) -OffRamp_trialExecute:test_RateLimitError_Success() (gas: 225885) -OffRamp_trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 234506) -OffRamp_trialExecute:test_TokenPoolIsNotAContract_Success() (gas: 309185) -OffRamp_trialExecute:test_trialExecute_Success() (gas: 284141) -OffRamp_verify:test_Blessed_Success() (gas: 175973) -OffRamp_verify:test_NotBlessedWrongChainSelector_Success() (gas: 178063) -OffRamp_verify:test_NotBlessed_Success() (gas: 140902) -OffRamp_verify:test_TooManyLeaves_Revert() (gas: 51510) +OffRamp_afterOC3ConfigSet:test_afterOCR3ConfigSet_SignatureVerificationDisabled_Revert() (gas: 6056933) +OffRamp_applySourceChainConfigUpdates:test_AddMultipleChains_Success() (gas: 468074) +OffRamp_applySourceChainConfigUpdates:test_AddNewChain_Success() (gas: 99238) +OffRamp_applySourceChainConfigUpdates:test_ApplyZeroUpdates_Success() (gas: 12414) +OffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChainOnRamp_Revert() (gas: 93240) +OffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChain_Success() (gas: 109971) +OffRamp_applySourceChainConfigUpdates:test_RouterAddress_Revert() (gas: 13288) +OffRamp_applySourceChainConfigUpdates:test_ZeroOnRampAddress_Revert() (gas: 18022) +OffRamp_applySourceChainConfigUpdates:test_ZeroSourceChainSelector_Revert() (gas: 15371) +OffRamp_batchExecute:test_MultipleReportsDifferentChainsSkipCursedChain_Success() (gas: 177419) +OffRamp_batchExecute:test_MultipleReportsDifferentChains_Success() (gas: 334109) +OffRamp_batchExecute:test_MultipleReportsSameChain_Success() (gas: 277477) +OffRamp_batchExecute:test_MultipleReportsSkipDuplicate_Success() (gas: 168556) +OffRamp_batchExecute:test_OutOfBoundsGasLimitsAccess_Revert() (gas: 188490) +OffRamp_batchExecute:test_SingleReport_Success() (gas: 156460) +OffRamp_batchExecute:test_Unhealthy_Success() (gas: 572587) +OffRamp_batchExecute:test_ZeroReports_Revert() (gas: 10486) +OffRamp_ccipReceive:test_Reverts() (gas: 15770) +OffRamp_commit:test_FailedRMNVerification_Reverts() (gas: 64420) +OffRamp_commit:test_InvalidIntervalMinLargerThanMax_Revert() (gas: 67632) +OffRamp_commit:test_InvalidInterval_Revert() (gas: 59886) +OffRamp_commit:test_InvalidRootRevert() (gas: 58921) +OffRamp_commit:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6661100) +OffRamp_commit:test_NoConfig_Revert() (gas: 6244915) +OffRamp_commit:test_OnlyGasPriceUpdates_Success() (gas: 112473) +OffRamp_commit:test_OnlyPriceUpdateStaleReport_Revert() (gas: 120501) +OffRamp_commit:test_OnlyTokenPriceUpdates_Success() (gas: 112494) +OffRamp_commit:test_PriceSequenceNumberCleared_Success() (gas: 353540) +OffRamp_commit:test_ReportAndPriceUpdate_Success() (gas: 164945) +OffRamp_commit:test_ReportOnlyRootSuccess_gas() (gas: 139934) +OffRamp_commit:test_RootAlreadyCommitted_Revert() (gas: 141925) +OffRamp_commit:test_SourceChainNotEnabled_Revert() (gas: 59208) +OffRamp_commit:test_StaleReportWithRoot_Success() (gas: 235331) +OffRamp_commit:test_UnauthorizedTransmitter_Revert() (gas: 121451) +OffRamp_commit:test_Unhealthy_Revert() (gas: 57938) +OffRamp_commit:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 208966) +OffRamp_commit:test_ZeroEpochAndRound_Revert() (gas: 51273) +OffRamp_constructor:test_Constructor_Success() (gas: 6244332) +OffRamp_constructor:test_SourceChainSelector_Revert() (gas: 136075) +OffRamp_constructor:test_ZeroChainSelector_Revert() (gas: 103518) +OffRamp_constructor:test_ZeroNonceManager_Revert() (gas: 101418) +OffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 138723) +OffRamp_constructor:test_ZeroRMNRemote_Revert() (gas: 101338) +OffRamp_constructor:test_ZeroTokenAdminRegistry_Revert() (gas: 101376) +OffRamp_execute:test_IncorrectArrayType_Revert() (gas: 17505) +OffRamp_execute:test_LargeBatch_Success() (gas: 3391111) +OffRamp_execute:test_MultipleReportsWithPartialValidationFailures_Success() (gas: 372353) +OffRamp_execute:test_MultipleReports_Success() (gas: 299779) +OffRamp_execute:test_NoConfigWithOtherConfigPresent_Revert() (gas: 7069102) +OffRamp_execute:test_NoConfig_Revert() (gas: 6293902) +OffRamp_execute:test_NonArray_Revert() (gas: 27787) +OffRamp_execute:test_SingleReport_Success() (gas: 175730) +OffRamp_execute:test_UnauthorizedTransmitter_Revert() (gas: 147970) +OffRamp_execute:test_WrongConfigWithSigners_Revert() (gas: 7071845) +OffRamp_execute:test_ZeroReports_Revert() (gas: 17227) +OffRamp_executeSingleMessage:test_MessageSender_Revert() (gas: 18682) +OffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 247849) +OffRamp_executeSingleMessage:test_NonContract_Success() (gas: 21002) +OffRamp_executeSingleMessage:test_TokenHandlingError_Revert() (gas: 208927) +OffRamp_executeSingleMessage:test_ZeroGasDONExecution_Revert() (gas: 49237) +OffRamp_executeSingleMessage:test_executeSingleMessage_NoTokens_Success() (gas: 48725) +OffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidationNoRouterCall_Revert() (gas: 228696) +OffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidation_Revert() (gas: 85260) +OffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens_Success() (gas: 279681) +OffRamp_executeSingleMessage:test_executeSingleMessage_WithValidation_Success() (gas: 91512) +OffRamp_executeSingleReport:test_DisabledSourceChain_Revert() (gas: 28226) +OffRamp_executeSingleReport:test_EmptyReport_Revert() (gas: 21832) +OffRamp_executeSingleReport:test_InvalidSourcePoolAddress_Success() (gas: 499180) +OffRamp_executeSingleReport:test_ManualExecutionNotYetEnabled_Revert() (gas: 48620) +OffRamp_executeSingleReport:test_MismatchingDestChainSelector_Revert() (gas: 33892) +OffRamp_executeSingleReport:test_MismatchingOnRampRoot_Revert() (gas: 154020) +OffRamp_executeSingleReport:test_NonExistingSourceChain_Revert() (gas: 28449) +OffRamp_executeSingleReport:test_ReceiverError_Success() (gas: 188116) +OffRamp_executeSingleReport:test_RetryFailedMessageWithoutManualExecution_Revert() (gas: 198571) +OffRamp_executeSingleReport:test_RootNotCommitted_Revert() (gas: 41037) +OffRamp_executeSingleReport:test_RouterYULCall_Revert() (gas: 447967) +OffRamp_executeSingleReport:test_SingleMessageNoTokensOtherChain_Success() (gas: 248847) +OffRamp_executeSingleReport:test_SingleMessageNoTokensUnordered_Success() (gas: 193195) +OffRamp_executeSingleReport:test_SingleMessageNoTokens_Success() (gas: 212816) +OffRamp_executeSingleReport:test_SingleMessageToNonCCIPReceiver_Success() (gas: 260215) +OffRamp_executeSingleReport:test_SingleMessagesNoTokensSuccess_gas() (gas: 141403) +OffRamp_executeSingleReport:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 423165) +OffRamp_executeSingleReport:test_SkippedIncorrectNonce_Success() (gas: 59057) +OffRamp_executeSingleReport:test_TokenDataMismatch_Revert() (gas: 74155) +OffRamp_executeSingleReport:test_TwoMessagesWithTokensAndGE_Success() (gas: 599623) +OffRamp_executeSingleReport:test_TwoMessagesWithTokensSuccess_gas() (gas: 543529) +OffRamp_executeSingleReport:test_UnexpectedTokenData_Revert() (gas: 33663) +OffRamp_executeSingleReport:test_UnhealthySingleChainCurse_Revert() (gas: 568482) +OffRamp_executeSingleReport:test_Unhealthy_Success() (gas: 568496) +OffRamp_executeSingleReport:test_WithCurseOnAnotherSourceChain_Success() (gas: 473801) +OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessageUnordered_Success() (gas: 135923) +OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessage_Success() (gas: 165161) +OffRamp_getExecutionState:test_FillExecutionState_Success() (gas: 3737630) +OffRamp_getExecutionState:test_GetDifferentChainExecutionState_Success() (gas: 119064) +OffRamp_getExecutionState:test_GetExecutionState_Success() (gas: 88148) +OffRamp_manuallyExecute:test_ManualExecGasLimitMismatchSingleReport_Revert() (gas: 79036) +OffRamp_manuallyExecute:test_manuallyExecute_DestinationGasAmountCountMismatch_Revert() (gas: 78924) +OffRamp_manuallyExecute:test_manuallyExecute_DoesNotRevertIfUntouched_Success() (gas: 172960) +OffRamp_manuallyExecute:test_manuallyExecute_FailedTx_Revert() (gas: 213287) +OffRamp_manuallyExecute:test_manuallyExecute_ForkedChain_Revert() (gas: 26909) +OffRamp_manuallyExecute:test_manuallyExecute_GasLimitMismatchMultipleReports_Revert() (gas: 159537) +OffRamp_manuallyExecute:test_manuallyExecute_InvalidReceiverExecutionGasLimit_Revert() (gas: 27468) +OffRamp_manuallyExecute:test_manuallyExecute_InvalidTokenGasOverride_Revert() (gas: 58874) +OffRamp_manuallyExecute:test_manuallyExecute_LowGasLimit_Success() (gas: 532013) +OffRamp_manuallyExecute:test_manuallyExecute_MultipleReportsWithSingleCursedLane_Revert() (gas: 317521) +OffRamp_manuallyExecute:test_manuallyExecute_ReentrancyFails_Success() (gas: 2390649) +OffRamp_manuallyExecute:test_manuallyExecute_SourceChainSelectorMismatch_Revert() (gas: 164912) +OffRamp_manuallyExecute:test_manuallyExecute_Success() (gas: 226245) +OffRamp_manuallyExecute:test_manuallyExecute_WithGasOverride_Success() (gas: 226785) +OffRamp_manuallyExecute:test_manuallyExecute_WithMultiReportGasOverride_Success() (gas: 778479) +OffRamp_manuallyExecute:test_manuallyExecute_WithPartialMessages_Success() (gas: 346205) +OffRamp_releaseOrMintSingleToken:test__releaseOrMintSingleToken_NotACompatiblePool_Revert() (gas: 40239) +OffRamp_releaseOrMintSingleToken:test__releaseOrMintSingleToken_Success() (gas: 105265) +OffRamp_releaseOrMintSingleToken:test__releaseOrMintSingleToken_TokenHandlingError_transfer_Revert() (gas: 86476) +OffRamp_releaseOrMintSingleToken:test_releaseOrMintToken_InvalidDataLength_Revert() (gas: 37975) +OffRamp_releaseOrMintSingleToken:test_releaseOrMintToken_ReleaseOrMintBalanceMismatch_Revert() (gas: 95515) +OffRamp_releaseOrMintSingleToken:test_releaseOrMintToken_TokenHandlingError_BalanceOf_Revert() (gas: 40961) +OffRamp_releaseOrMintSingleToken:test_releaseOrMintToken_skip_ReleaseOrMintBalanceMismatch_if_pool_Revert() (gas: 87721) +OffRamp_releaseOrMintTokens:test_TokenHandlingError_Reverts() (gas: 164647) +OffRamp_releaseOrMintTokens:test__releaseOrMintTokens_PoolIsNotAPool_Reverts() (gas: 25146) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_InvalidDataLengthReturnData_Revert() (gas: 64911) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_InvalidEVMAddress_Revert() (gas: 41883) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_PoolDoesNotSupportDest_Reverts() (gas: 81999) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_Success() (gas: 176661) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_WithGasOverride_Success() (gas: 178641) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals_Success() (gas: 189850) +OffRamp_setDynamicConfig:test_FeeQuoterZeroAddress_Revert() (gas: 11189) +OffRamp_setDynamicConfig:test_NonOwner_Revert() (gas: 13793) +OffRamp_setDynamicConfig:test_SetDynamicConfigWithValidator_Success() (gas: 46198) +OffRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 24173) +OffRamp_trialExecute:test_RateLimitError_Success() (gas: 225140) +OffRamp_trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 233762) +OffRamp_trialExecute:test_TokenPoolIsNotAContract_Success() (gas: 310735) +OffRamp_trialExecute:test_trialExecute_Success() (gas: 283386) OnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 390910) OnRamp_applyAllowListUpdates:test_applyAllowListUpdates_InvalidAllowListRequestDisabledAllowListWithAdds() (gas: 17746) OnRamp_applyAllowListUpdates:test_applyAllowListUpdates_Revert() (gas: 66535) diff --git a/contracts/scripts/native_solc_compile_all_ccip b/contracts/scripts/native_solc_compile_all_ccip index 7c4ff56bd8..e1f95b2fcb 100755 --- a/contracts/scripts/native_solc_compile_all_ccip +++ b/contracts/scripts/native_solc_compile_all_ccip @@ -10,7 +10,7 @@ SOLC_VERSION="0.8.24" OPTIMIZE_RUNS=26000 OPTIMIZE_RUNS_OFFRAMP=18000 OPTIMIZE_RUNS_ONRAMP=4100 -OPTIMIZE_RUNS_MULTI_OFFRAMP=1925 +OPTIMIZE_RUNS_MULTI_OFFRAMP=800 SCRIPTPATH="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" diff --git a/contracts/src/v0.8/ccip/offRamp/OffRamp.sol b/contracts/src/v0.8/ccip/offRamp/OffRamp.sol index 82e4a3de37..6399244605 100644 --- a/contracts/src/v0.8/ccip/offRamp/OffRamp.sol +++ b/contracts/src/v0.8/ccip/offRamp/OffRamp.sol @@ -40,7 +40,11 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { error UnexpectedTokenData(); error ManualExecutionNotYetEnabled(uint64 sourceChainSelector); error ManualExecutionGasLimitMismatch(); - error InvalidManualExecutionGasLimit(uint64 sourceChainSelector, uint256 index, uint256 newLimit); + error InvalidManualExecutionGasLimit(uint64 sourceChainSelector, bytes32 messageId, uint256 newLimit); + error InvalidManualExecutionTokenGasOverride( + bytes32 messageId, uint256 tokenIndex, uint256 oldLimit, uint256 tokenGasOverride + ); + error ManualExecutionGasAmountCountMismatch(bytes32 messageId, uint64 sequenceNumber); error RootNotCommitted(uint64 sourceChainSelector); error RootAlreadyCommitted(uint64 sourceChainSelector, bytes32 merkleRoot); error InvalidRoot(); @@ -116,9 +120,7 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { /// @dev Since DynamicConfig is part of DynamicConfigSet event, if changing it, we should update the ABI on Atlas struct DynamicConfig { address feeQuoter; // ──────────────────────────────╮ FeeQuoter address on the local chain - uint32 permissionLessExecutionThresholdSeconds; // │ Waiting time before manual execution is enabled - uint32 maxTokenTransferGas; // │ Maximum amount of gas passed on to token `transfer` call - uint32 maxPoolReleaseOrMintGas; // ─────────────────╯ Maximum amount of gas passed on to token pool when calling releaseOrMint + uint32 permissionLessExecutionThresholdSeconds; //──╯ Waiting time before manual execution is enabled address messageValidator; // Optional message validator to validate incoming messages (zero address = no validator) } @@ -130,6 +132,12 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { IRMNV2.Signature[] rmnSignatures; // RMN signatures on the merkle roots } + struct GasLimitOverride { + // A value of zero in both fields signifies no override and allows the corresponding field to be overridden as valid + uint256 receiverExecutionGasLimit; // Overrides EVM2EVMMessage.gasLimit. + uint32[] tokenGasOverrides; // Overrides EVM2EVMMessage.sourceTokenData.destGasAmount, length must be same as tokenAmounts. + } + // STATIC CONFIG string public constant override typeAndVersion = "OffRamp 1.6.0-dev"; /// @dev ChainSelector of this chain @@ -257,7 +265,7 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { /// The reports do not have to contain all the messages (they can be omitted). Multiple reports can be passed in simultaneously. function manuallyExecute( Internal.ExecutionReportSingleChain[] memory reports, - uint256[][] memory gasLimitOverrides + GasLimitOverride[][] memory gasLimitOverrides ) external { // We do this here because the other _execute path is already covered by MultiOCR3Base. _whenChainNotForked(); @@ -269,15 +277,35 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { Internal.ExecutionReportSingleChain memory report = reports[reportIndex]; uint256 numMsgs = report.messages.length; - uint256[] memory msgGasLimitOverrides = gasLimitOverrides[reportIndex]; + GasLimitOverride[] memory msgGasLimitOverrides = gasLimitOverrides[reportIndex]; if (numMsgs != msgGasLimitOverrides.length) revert ManualExecutionGasLimitMismatch(); for (uint256 msgIndex = 0; msgIndex < numMsgs; ++msgIndex) { - uint256 newLimit = msgGasLimitOverrides[msgIndex]; + uint256 newLimit = msgGasLimitOverrides[msgIndex].receiverExecutionGasLimit; // Checks to ensure message cannot be executed with less gas than specified. + Internal.Any2EVMRampMessage memory message = report.messages[msgIndex]; if (newLimit != 0) { - if (newLimit < report.messages[msgIndex].gasLimit) { - revert InvalidManualExecutionGasLimit(report.sourceChainSelector, msgIndex, newLimit); + if (newLimit < message.gasLimit) { + revert InvalidManualExecutionGasLimit(report.sourceChainSelector, message.header.messageId, newLimit); + } + } + if (message.tokenAmounts.length != msgGasLimitOverrides[msgIndex].tokenGasOverrides.length) { + revert ManualExecutionGasAmountCountMismatch(message.header.messageId, message.header.sequenceNumber); + } + + // The gas limit can not be lowered as that could cause the message to fail. If manual execution is done + // from an UNTOUCHED state and we would allow lower gas limit, anyone could grief by executing the message with + // lower gas limit than the DON would have used. This results in the message being marked FAILURE and the DON + // would not attempt it with the correct gas limit. + for (uint256 tokenIndex = 0; tokenIndex < message.tokenAmounts.length; ++tokenIndex) { + uint256 tokenGasOverride = msgGasLimitOverrides[msgIndex].tokenGasOverrides[tokenIndex]; + if (tokenGasOverride != 0) { + uint32 destGasAmount = abi.decode(message.tokenAmounts[tokenIndex].destExecData, (uint32)); + if (tokenGasOverride < destGasAmount) { + revert InvalidManualExecutionTokenGasOverride( + message.header.messageId, tokenIndex, destGasAmount, tokenGasOverride + ); + } } } } @@ -290,7 +318,7 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { /// and expects the exec plugin type to be configured with no signatures. /// @param report serialized execution report function execute(bytes32[3] calldata reportContext, bytes calldata report) external { - _batchExecute(abi.decode(report, (Internal.ExecutionReportSingleChain[])), new uint256[][](0)); + _batchExecute(abi.decode(report, (Internal.ExecutionReportSingleChain[])), new GasLimitOverride[][](0)); bytes32[] memory emptySigs = new bytes32[](0); _transmit(uint8(Internal.OCRPluginType.Execution), reportContext, report, emptySigs, emptySigs, bytes32("")); @@ -305,30 +333,30 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { /// @dev If called from manual execution, each inner array's length has to match the number of messages. function _batchExecute( Internal.ExecutionReportSingleChain[] memory reports, - uint256[][] memory manualExecGasLimits + GasLimitOverride[][] memory manualExecGasOverrides ) internal { if (reports.length == 0) revert EmptyReport(); - bool areManualGasLimitsEmpty = manualExecGasLimits.length == 0; + bool areManualGasLimitsEmpty = manualExecGasOverrides.length == 0; // Cache array for gas savings in the loop's condition - uint256[] memory emptyGasLimits = new uint256[](0); + GasLimitOverride[] memory emptyGasLimits = new GasLimitOverride[](0); for (uint256 i = 0; i < reports.length; ++i) { - _executeSingleReport(reports[i], areManualGasLimitsEmpty ? emptyGasLimits : manualExecGasLimits[i]); + _executeSingleReport(reports[i], areManualGasLimitsEmpty ? emptyGasLimits : manualExecGasOverrides[i]); } } /// @notice Executes a report, executing each message in order. /// @param report The execution report containing the messages and proofs. - /// @param manualExecGasLimits An array of gas limits to use for manual execution. + /// @param manualExecGasExecOverrides An array of gas limits to use for manual execution. /// @dev If called from the DON, this array is always empty. /// @dev If called from manual execution, this array is always same length as messages. function _executeSingleReport( Internal.ExecutionReportSingleChain memory report, - uint256[] memory manualExecGasLimits + GasLimitOverride[] memory manualExecGasExecOverrides ) internal { uint64 sourceChainSelector = report.sourceChainSelector; - bool manualExecution = manualExecGasLimits.length != 0; + bool manualExecution = manualExecGasExecOverrides.length != 0; if (i_rmn.isCursed(bytes16(uint128(sourceChainSelector)))) { if (manualExecution) { // For manual execution we don't want to silently fail so we revert @@ -396,8 +424,9 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { emit SkippedAlreadyExecutedMessage(sourceChainSelector, message.header.sequenceNumber); continue; } - + uint32[] memory tokenGasOverrides; if (manualExecution) { + tokenGasOverrides = manualExecGasExecOverrides[i].tokenGasOverrides; bool isOldCommitReport = (block.timestamp - timestampCommitted) > s_dynamicConfig.permissionLessExecutionThresholdSeconds; // Manually execution is fine if we previously failed or if the commit report is just too old @@ -407,8 +436,8 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { } // Manual execution gas limit can override gas limit specified in the message. Value of 0 indicates no override. - if (manualExecGasLimits[i] != 0) { - message.gasLimit = manualExecGasLimits[i]; + if (manualExecGasExecOverrides[i].receiverExecutionGasLimit != 0) { + message.gasLimit = manualExecGasExecOverrides[i].receiverExecutionGasLimit; } } else { // DON can only execute a message once @@ -445,7 +474,8 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { } _setExecutionState(sourceChainSelector, message.header.sequenceNumber, Internal.MessageExecutionState.IN_PROGRESS); - (Internal.MessageExecutionState newState, bytes memory returnData) = _trialExecute(message, offchainTokenData); + (Internal.MessageExecutionState newState, bytes memory returnData) = + _trialExecute(message, offchainTokenData, tokenGasOverrides); _setExecutionState(sourceChainSelector, message.header.sequenceNumber, newState); // Since it's hard to estimate whether manual execution will succeed, we @@ -490,9 +520,10 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { /// @return errData Revert data in bytes if CCIP receiver reverted during execution. function _trialExecute( Internal.Any2EVMRampMessage memory message, - bytes[] memory offchainTokenData + bytes[] memory offchainTokenData, + uint32[] memory tokenGasOverrides ) internal returns (Internal.MessageExecutionState executionState, bytes memory) { - try this.executeSingleMessage(message, offchainTokenData) {} + try this.executeSingleMessage(message, offchainTokenData, tokenGasOverrides) {} catch (bytes memory err) { // return the message execution state as FAILURE and the revert data // Max length of revert data is Router.MAX_RET_BYTES, max length of err is 4 + Router.MAX_RET_BYTES @@ -511,13 +542,19 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { /// (for example smart contract wallets) without an associated message. function executeSingleMessage( Internal.Any2EVMRampMessage memory message, - bytes[] calldata offchainTokenData + bytes[] calldata offchainTokenData, + uint32[] calldata tokenGasOverrides ) external { if (msg.sender != address(this)) revert CanOnlySelfCall(); Client.EVMTokenAmount[] memory destTokenAmounts = new Client.EVMTokenAmount[](0); if (message.tokenAmounts.length > 0) { destTokenAmounts = _releaseOrMintTokens( - message.tokenAmounts, message.sender, message.receiver, message.header.sourceChainSelector, offchainTokenData + message.tokenAmounts, + message.sender, + message.receiver, + message.header.sourceChainSelector, + offchainTokenData, + tokenGasOverrides ); } @@ -827,7 +864,7 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { // We retrieve the local token balance of the receiver before the pool call. (uint256 balancePre, uint256 gasLeft) = - _getBalanceOfReceiver(receiver, localToken, s_dynamicConfig.maxPoolReleaseOrMintGas); + _getBalanceOfReceiver(receiver, localToken, abi.decode(sourceTokenAmount.destExecData, (uint32))); // We determined that the pool address is a valid EVM address, but that does not mean the code at this // address is a (compatible) pool contract. _callWithExactGasSafeReturnData will check if the location @@ -923,10 +960,17 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { bytes memory originalSender, address receiver, uint64 sourceChainSelector, - bytes[] calldata offchainTokenData + bytes[] calldata offchainTokenData, + uint32[] calldata tokenGasOverrides ) internal returns (Client.EVMTokenAmount[] memory destTokenAmounts) { destTokenAmounts = new Client.EVMTokenAmount[](sourceTokenAmounts.length); + bool isTokenGasOverridesEmpty = tokenGasOverrides.length == 0; for (uint256 i = 0; i < sourceTokenAmounts.length; ++i) { + if (!isTokenGasOverridesEmpty) { + if (tokenGasOverrides[i] != 0) { + sourceTokenAmounts[i].destExecData = abi.encode(tokenGasOverrides[i]); + } + } destTokenAmounts[i] = _releaseOrMintSingleToken( sourceTokenAmounts[i], originalSender, receiver, sourceChainSelector, offchainTokenData[i] ); diff --git a/contracts/src/v0.8/ccip/test/NonceManager.t.sol b/contracts/src/v0.8/ccip/test/NonceManager.t.sol index 8c61ba5d21..2bf7d8ea4d 100644 --- a/contracts/src/v0.8/ccip/test/NonceManager.t.sol +++ b/contracts/src/v0.8/ccip/test/NonceManager.t.sol @@ -390,7 +390,9 @@ contract NonceManager_OffRampUpgrade is OffRampSetup { _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); vm.recordLogs(); - s_offRamp.executeSingleReport(_generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[](0)); + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) + ); assertExecutionStateChangedEventLogs( SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber, @@ -421,7 +423,7 @@ contract NonceManager_OffRampUpgrade is OffRampSetup { vm.recordLogs(); s_offRamp.executeSingleReport( - _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_3, messagesChain3), new uint256[](0) + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_3, messagesChain3), new OffRamp.GasLimitOverride[](0) ); assertExecutionStateChangedEventLogs( SOURCE_CHAIN_SELECTOR_3, @@ -502,7 +504,7 @@ contract NonceManager_OffRampUpgrade is OffRampSetup { vm.recordLogs(); s_offRamp.executeSingleReport( - _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messagesMultiRamp), new uint256[](0) + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messagesMultiRamp), new OffRamp.GasLimitOverride[](0) ); assertExecutionStateChangedEventLogs( @@ -524,7 +526,7 @@ contract NonceManager_OffRampUpgrade is OffRampSetup { vm.recordLogs(); s_offRamp.executeSingleReport( - _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messagesMultiRamp), new uint256[](0) + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messagesMultiRamp), new OffRamp.GasLimitOverride[](0) ); assertExecutionStateChangedEventLogs( SOURCE_CHAIN_SELECTOR_1, @@ -559,7 +561,7 @@ contract NonceManager_OffRampUpgrade is OffRampSetup { assertEq(s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, newSender), 0); vm.recordLogs(); s_offRamp.executeSingleReport( - _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messagesMultiRamp), new uint256[](0) + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messagesMultiRamp), new OffRamp.GasLimitOverride[](0) ); assertExecutionStateChangedEventLogs( SOURCE_CHAIN_SELECTOR_1, @@ -587,7 +589,9 @@ contract NonceManager_OffRampUpgrade is OffRampSetup { // it waits for previous offramp to execute vm.expectEmit(); emit NonceManager.SkippedIncorrectNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].header.nonce, messages[0].sender); - s_offRamp.executeSingleReport(_generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[](0)); + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) + ); assertEq(startNonce, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender)); Internal.EVM2EVMMessage[] memory messagesSingleLane = @@ -611,7 +615,9 @@ contract NonceManager_OffRampUpgrade is OffRampSetup { // new offramp is able to execute vm.recordLogs(); - s_offRamp.executeSingleReport(_generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[](0)); + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) + ); assertExecutionStateChangedEventLogs( SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber, diff --git a/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.sol b/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.sol index 446dcfc344..21643a5df6 100644 --- a/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.sol +++ b/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.sol @@ -267,6 +267,10 @@ contract MultiRampsE2E is OnRampSetup, OffRampSetup { router.ccipSend(DEST_CHAIN_SELECTOR, message); vm.pauseGasMetering(); + uint256 gasLimit = s_feeQuoter.parseEVMExtraArgsFromBytes(msgEvent.extraArgs, DEST_CHAIN_SELECTOR).gasLimit; + for (uint256 i = 0; i < msgEvent.tokenAmounts.length; ++i) { + msgEvent.tokenAmounts[i].destExecData = abi.encode(MAX_TOKEN_POOL_RELEASE_OR_MINT_GAS); + } return Internal.Any2EVMRampMessage({ header: Internal.RampMessageHeader({ messageId: msgEvent.header.messageId, diff --git a/contracts/src/v0.8/ccip/test/helpers/OffRampHelper.sol b/contracts/src/v0.8/ccip/test/helpers/OffRampHelper.sol index e5cf6332d9..80672bf51e 100644 --- a/contracts/src/v0.8/ccip/test/helpers/OffRampHelper.sol +++ b/contracts/src/v0.8/ccip/test/helpers/OffRampHelper.sol @@ -43,28 +43,32 @@ contract OffRampHelper is OffRamp, IgnoreContractSize { bytes calldata originalSender, address receiver, uint64 sourceChainSelector, - bytes[] calldata offchainTokenData + bytes[] calldata offchainTokenData, + uint32[] calldata tokenGasOverrides ) external returns (Client.EVMTokenAmount[] memory) { - return _releaseOrMintTokens(sourceTokenAmounts, originalSender, receiver, sourceChainSelector, offchainTokenData); + return _releaseOrMintTokens( + sourceTokenAmounts, originalSender, receiver, sourceChainSelector, offchainTokenData, tokenGasOverrides + ); } function trialExecute( Internal.Any2EVMRampMessage memory message, - bytes[] memory offchainTokenData + bytes[] memory offchainTokenData, + uint32[] memory tokenGasOverrides ) external returns (Internal.MessageExecutionState, bytes memory) { - return _trialExecute(message, offchainTokenData); + return _trialExecute(message, offchainTokenData, tokenGasOverrides); } function executeSingleReport( Internal.ExecutionReportSingleChain memory rep, - uint256[] memory manualExecGasLimits + GasLimitOverride[] memory manualExecGasExecOverrides ) external { - _executeSingleReport(rep, manualExecGasLimits); + _executeSingleReport(rep, manualExecGasExecOverrides); } function batchExecute( Internal.ExecutionReportSingleChain[] memory reports, - uint256[][] memory manualExecGasLimits + GasLimitOverride[][] memory manualExecGasLimits ) external { _batchExecute(reports, manualExecGasLimits); } diff --git a/contracts/src/v0.8/ccip/test/helpers/receivers/ReentrancyAbuserMultiRamp.sol b/contracts/src/v0.8/ccip/test/helpers/receivers/ReentrancyAbuserMultiRamp.sol index 667fbc13e5..c8eee48808 100644 --- a/contracts/src/v0.8/ccip/test/helpers/receivers/ReentrancyAbuserMultiRamp.sol +++ b/contracts/src/v0.8/ccip/test/helpers/receivers/ReentrancyAbuserMultiRamp.sol @@ -24,10 +24,11 @@ contract ReentrancyAbuserMultiRamp is CCIPReceiver { function _ccipReceive(Client.Any2EVMMessage memory) internal override { // Use original message gas limits in manual execution uint256 numMsgs = s_payload.messages.length; - uint256[][] memory gasOverrides = new uint256[][](1); - gasOverrides[0] = new uint256[](numMsgs); + OffRamp.GasLimitOverride[][] memory gasOverrides = new OffRamp.GasLimitOverride[][](1); + gasOverrides[0] = new OffRamp.GasLimitOverride[](numMsgs); for (uint256 i = 0; i < numMsgs; ++i) { - gasOverrides[0][i] = 0; + gasOverrides[0][i].receiverExecutionGasLimit = 0; + gasOverrides[0][i].tokenGasOverrides = new uint32[](s_payload.messages[i].tokenAmounts.length); } Internal.ExecutionReportSingleChain[] memory batchPayload = new Internal.ExecutionReportSingleChain[](1); diff --git a/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol index a2a7fff50a..8e41f88f91 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol @@ -340,7 +340,9 @@ contract OffRamp_executeSingleReport is OffRampSetup { _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); vm.recordLogs(); - s_offRamp.executeSingleReport(_generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[](0)); + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) + ); assertExecutionStateChangedEventLogs( messages[0].header.sourceChainSelector, messages[0].header.sequenceNumber, @@ -356,7 +358,9 @@ contract OffRamp_executeSingleReport is OffRampSetup { uint64 nonceBefore = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender); vm.recordLogs(); - s_offRamp.executeSingleReport(_generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[](0)); + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) + ); assertExecutionStateChangedEventLogs( messages[0].header.sourceChainSelector, messages[0].header.sequenceNumber, @@ -377,7 +381,9 @@ contract OffRamp_executeSingleReport is OffRampSetup { // Nonce never increments on unordered messages. uint64 nonceBefore = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender); vm.recordLogs(); - s_offRamp.executeSingleReport(_generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[](0)); + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) + ); assertExecutionStateChangedEventLogs( messages[0].header.sourceChainSelector, messages[0].header.sequenceNumber, @@ -399,7 +405,9 @@ contract OffRamp_executeSingleReport is OffRampSetup { // Nonce never increments on unordered messages. nonceBefore = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender); vm.recordLogs(); - s_offRamp.executeSingleReport(_generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[](0)); + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) + ); assertExecutionStateChangedEventLogs( messages[0].header.sourceChainSelector, messages[0].header.sequenceNumber, @@ -419,7 +427,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { Internal.Any2EVMRampMessage[] memory messagesChain1 = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); s_offRamp.executeSingleReport( - _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messagesChain1), new uint256[](0) + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messagesChain1), new OffRamp.GasLimitOverride[](0) ); uint64 nonceChain1 = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messagesChain1[0].sender); @@ -430,7 +438,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { assertEq(s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_3, messagesChain2[0].sender), 0); s_offRamp.executeSingleReport( - _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_3, messagesChain2), new uint256[](0) + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_3, messagesChain2), new OffRamp.GasLimitOverride[](0) ); assertGt(s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_3, messagesChain2[0].sender), 0); @@ -453,7 +461,9 @@ contract OffRamp_executeSingleReport is OffRampSetup { // Nonce should increment on non-strict assertEq(uint64(0), s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(OWNER))); vm.recordLogs(); - s_offRamp.executeSingleReport(_generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[](0)); + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) + ); assertExecutionStateChangedEventLogs( messages[0].header.sourceChainSelector, messages[0].header.sequenceNumber, @@ -480,7 +490,9 @@ contract OffRamp_executeSingleReport is OffRampSetup { messages[0].header.sourceChainSelector, messages[0].header.nonce, messages[0].sender ); - s_offRamp.executeSingleReport(_generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[](0)); + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) + ); } function test_SkippedIncorrectNonceStillExecutes_Success() public { @@ -494,7 +506,9 @@ contract OffRamp_executeSingleReport is OffRampSetup { emit NonceManager.SkippedIncorrectNonce(SOURCE_CHAIN_SELECTOR_1, messages[1].header.nonce, messages[1].sender); vm.recordLogs(); - s_offRamp.executeSingleReport(_generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[](0)); + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) + ); assertExecutionStateChangedEventLogs( messages[0].header.sourceChainSelector, messages[0].header.sequenceNumber, @@ -510,7 +524,9 @@ contract OffRamp_executeSingleReport is OffRampSetup { _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); vm.recordLogs(); - s_offRamp.executeSingleReport(_generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[](0)); + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) + ); assertExecutionStateChangedEventLogs( SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber, @@ -523,7 +539,9 @@ contract OffRamp_executeSingleReport is OffRampSetup { vm.expectEmit(); emit OffRamp.SkippedAlreadyExecutedMessage(SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber); - s_offRamp.executeSingleReport(_generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[](0)); + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) + ); } function test__execute_SkippedAlreadyExecutedMessageUnordered_Success() public { @@ -533,7 +551,9 @@ contract OffRamp_executeSingleReport is OffRampSetup { messages[0].header.messageId = Internal._hash(messages[0], ON_RAMP_ADDRESS_1); vm.recordLogs(); - s_offRamp.executeSingleReport(_generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[](0)); + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) + ); assertExecutionStateChangedEventLogs( SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber, @@ -546,7 +566,9 @@ contract OffRamp_executeSingleReport is OffRampSetup { vm.expectEmit(); emit OffRamp.SkippedAlreadyExecutedMessage(SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber); - s_offRamp.executeSingleReport(_generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[](0)); + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) + ); } // Send a message to a contract that does not implement the CCIPReceiver interface @@ -559,7 +581,9 @@ contract OffRamp_executeSingleReport is OffRampSetup { messages[0].header.messageId = Internal._hash(messages[0], ON_RAMP_ADDRESS_1); vm.recordLogs(); - s_offRamp.executeSingleReport(_generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[](0)); + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) + ); assertExecutionStateChangedEventLogs( messages[0].header.sourceChainSelector, messages[0].header.sequenceNumber, @@ -579,7 +603,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { vm.resumeGasMetering(); vm.recordLogs(); - s_offRamp.executeSingleReport(report, new uint256[](0)); + s_offRamp.executeSingleReport(report, new OffRamp.GasLimitOverride[](0)); assertExecutionStateChangedEventLogs( messages[0].header.sourceChainSelector, messages[0].header.sequenceNumber, @@ -602,10 +626,9 @@ contract OffRamp_executeSingleReport is OffRampSetup { vm.resumeGasMetering(); vm.recordLogs(); - s_offRamp.executeSingleReport(report, new uint256[](0)); + s_offRamp.executeSingleReport(report, new OffRamp.GasLimitOverride[](0)); Vm.Log[] memory logs = vm.getRecordedLogs(); - assertExecutionStateChangedEventLogs( logs, SOURCE_CHAIN_SELECTOR_1, @@ -725,7 +748,9 @@ contract OffRamp_executeSingleReport is OffRampSetup { vm.recordLogs(); - s_offRamp.executeSingleReport(_generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[](0)); + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) + ); assertExecutionStateChangedEventLogs( SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber, @@ -745,7 +770,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { _generateReportFromMessages( SOURCE_CHAIN_SELECTOR_1, _generateMessagesWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1) ), - new uint256[](0) + new OffRamp.GasLimitOverride[](0) ); } @@ -758,7 +783,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { _generateReportFromMessages( SOURCE_CHAIN_SELECTOR_1, _generateMessagesWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1) ), - new uint256[](0) + new OffRamp.GasLimitOverride[](0) ); _setMockRMNChainCurse(SOURCE_CHAIN_SELECTOR_1, false); @@ -767,7 +792,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { _generateReportFromMessages( SOURCE_CHAIN_SELECTOR_1, _generateMessagesWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1) ), - new uint256[](0) + new OffRamp.GasLimitOverride[](0) ); _assertNoEmit(OffRamp.SkippedReportExecution.selector); @@ -786,7 +811,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { vm.expectRevert( abi.encodeWithSelector(OffRamp.InvalidMessageDestChainSelector.selector, messages[0].header.destChainSelector) ); - s_offRamp.executeSingleReport(executionReport, new uint256[](0)); + s_offRamp.executeSingleReport(executionReport, new OffRamp.GasLimitOverride[](0)); } function test_MismatchingOnRampRoot_Revert() public { @@ -804,7 +829,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { Internal.ExecutionReportSingleChain memory executionReport = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); vm.expectRevert(abi.encodeWithSelector(OffRamp.RootNotCommitted.selector, SOURCE_CHAIN_SELECTOR_1)); - s_offRamp.executeSingleReport(executionReport, new uint256[](0)); + s_offRamp.executeSingleReport(executionReport, new OffRamp.GasLimitOverride[](0)); } function test_UnhealthySingleChainCurse_Revert() public { @@ -815,7 +840,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { _generateReportFromMessages( SOURCE_CHAIN_SELECTOR_1, _generateMessagesWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1) ), - new uint256[](0) + new OffRamp.GasLimitOverride[](0) ); vm.recordLogs(); // Uncurse should succeed @@ -824,7 +849,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { _generateReportFromMessages( SOURCE_CHAIN_SELECTOR_1, _generateMessagesWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1) ), - new uint256[](0) + new OffRamp.GasLimitOverride[](0) ); _assertNoEmit(OffRamp.SkippedReportExecution.selector); } @@ -837,7 +862,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { vm.expectRevert(OffRamp.UnexpectedTokenData.selector); - s_offRamp.executeSingleReport(report, new uint256[](0)); + s_offRamp.executeSingleReport(report, new OffRamp.GasLimitOverride[](0)); } function test_EmptyReport_Revert() public { @@ -850,7 +875,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { messages: new Internal.Any2EVMRampMessage[](0), offchainTokenData: new bytes[][](0) }), - new uint256[](0) + new OffRamp.GasLimitOverride[](0) ); } @@ -884,7 +909,9 @@ contract OffRamp_executeSingleReport is OffRampSetup { Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(newSourceChainSelector, newOnRamp); vm.expectRevert(abi.encodeWithSelector(OffRamp.SourceChainNotEnabled.selector, newSourceChainSelector)); - s_offRamp.executeSingleReport(_generateReportFromMessages(newSourceChainSelector, messages), new uint256[](0)); + s_offRamp.executeSingleReport( + _generateReportFromMessages(newSourceChainSelector, messages), new OffRamp.GasLimitOverride[](0) + ); } function test_DisabledSourceChain_Revert() public { @@ -892,7 +919,9 @@ contract OffRamp_executeSingleReport is OffRampSetup { _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_2, ON_RAMP_ADDRESS_2); vm.expectRevert(abi.encodeWithSelector(OffRamp.SourceChainNotEnabled.selector, SOURCE_CHAIN_SELECTOR_2)); - s_offRamp.executeSingleReport(_generateReportFromMessages(SOURCE_CHAIN_SELECTOR_2, messages), new uint256[](0)); + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_2, messages), new OffRamp.GasLimitOverride[](0) + ); } function test_TokenDataMismatch_Revert() public { @@ -907,7 +936,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { OffRamp.TokenDataMismatch.selector, SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber ) ); - s_offRamp.executeSingleReport(report, new uint256[](0)); + s_offRamp.executeSingleReport(report, new OffRamp.GasLimitOverride[](0)); } function test_RouterYULCall_Revert() public { @@ -923,7 +952,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); vm.recordLogs(); - s_offRamp.executeSingleReport(executionReport, new uint256[](0)); + s_offRamp.executeSingleReport(executionReport, new OffRamp.GasLimitOverride[](0)); assertExecutionStateChangedEventLogs( messages[0].header.sourceChainSelector, messages[0].header.sequenceNumber, @@ -947,7 +976,9 @@ contract OffRamp_executeSingleReport is OffRampSetup { messages[0].header.messageId = Internal._hash(messages[0], ON_RAMP_ADDRESS_1); vm.recordLogs(); - s_offRamp.executeSingleReport(_generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[](0)); + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) + ); assertExecutionStateChangedEventLogs( messages[0].header.sourceChainSelector, messages[0].header.sequenceNumber, @@ -964,7 +995,9 @@ contract OffRamp_executeSingleReport is OffRampSetup { vm.expectEmit(); emit OffRamp.AlreadyAttempted(SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber); - s_offRamp.executeSingleReport(_generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[](0)); + s_offRamp.executeSingleReport( + _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[](0) + ); } function _constructCommitReport(bytes32 merkleRoot) internal view returns (OffRamp.CommitReport memory) { @@ -995,7 +1028,7 @@ contract OffRamp_executeSingleMessage is OffRampSetup { function test_executeSingleMessage_NoTokens_Success() public { Internal.Any2EVMRampMessage memory message = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); - s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length)); + s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); } function test_executeSingleMessage_WithTokens_Success() public { @@ -1020,7 +1053,7 @@ contract OffRamp_executeSingleMessage is OffRampSetup { ) ); - s_offRamp.executeSingleMessage(message, offchainTokenData); + s_offRamp.executeSingleMessage(message, offchainTokenData, new uint32[](0)); } function test_executeSingleMessage_WithValidation_Success() public { @@ -1030,14 +1063,14 @@ contract OffRamp_executeSingleMessage is OffRampSetup { vm.startPrank(address(s_offRamp)); Internal.Any2EVMRampMessage memory message = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); - s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length)); + s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); } function test_NonContract_Success() public { Internal.Any2EVMRampMessage memory message = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); message.receiver = STRANGER; - s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length)); + s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); } function test_NonContractWithTokens_Success() public { @@ -1051,7 +1084,7 @@ contract OffRamp_executeSingleMessage is OffRampSetup { Internal.Any2EVMRampMessage memory message = _generateAny2EVMMessageWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1, amounts); message.receiver = STRANGER; - s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length)); + s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); } // Reverts @@ -1069,7 +1102,7 @@ contract OffRamp_executeSingleMessage is OffRampSetup { vm.expectRevert(abi.encodeWithSelector(OffRamp.TokenHandlingError.selector, errorMessage)); - s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length)); + s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); } function test_ZeroGasDONExecution_Revert() public { @@ -1079,7 +1112,7 @@ contract OffRamp_executeSingleMessage is OffRampSetup { vm.expectRevert(abi.encodeWithSelector(OffRamp.ReceiverError.selector, "")); - s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length)); + s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); } function test_MessageSender_Revert() public { @@ -1087,7 +1120,7 @@ contract OffRamp_executeSingleMessage is OffRampSetup { Internal.Any2EVMRampMessage memory message = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); vm.expectRevert(OffRamp.CanOnlySelfCall.selector); - s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length)); + s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); } function test_executeSingleMessage_WithFailingValidation_Revert() public { @@ -1104,7 +1137,7 @@ contract OffRamp_executeSingleMessage is OffRampSetup { abi.encodeWithSelector(IMessageInterceptor.MessageValidationError.selector, bytes("Invalid message")) ) ); - s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length)); + s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); } function test_executeSingleMessage_WithFailingValidationNoRouterCall_Revert() public { @@ -1128,7 +1161,7 @@ contract OffRamp_executeSingleMessage is OffRampSetup { abi.encodeWithSelector(IMessageInterceptor.MessageValidationError.selector, bytes("Invalid message")) ) ); - s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length)); + s_offRamp.executeSingleMessage(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); } } @@ -1147,7 +1180,9 @@ contract OffRamp_batchExecute is OffRampSetup { uint64 nonceBefore = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender); vm.recordLogs(); - s_offRamp.batchExecute(_generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[][](1)); + s_offRamp.batchExecute( + _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[][](1) + ); assertExecutionStateChangedEventLogs( messages[0].header.sourceChainSelector, messages[0].header.sequenceNumber, @@ -1174,10 +1209,9 @@ contract OffRamp_batchExecute is OffRampSetup { uint64 nonceBefore = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages1[0].sender); vm.recordLogs(); - s_offRamp.batchExecute(reports, new uint256[][](2)); + s_offRamp.batchExecute(reports, new OffRamp.GasLimitOverride[][](2)); Vm.Log[] memory logs = vm.getRecordedLogs(); - assertExecutionStateChangedEventLogs( logs, messages1[0].header.sourceChainSelector, @@ -1225,7 +1259,7 @@ contract OffRamp_batchExecute is OffRampSetup { vm.recordLogs(); - s_offRamp.batchExecute(reports, new uint256[][](2)); + s_offRamp.batchExecute(reports, new OffRamp.GasLimitOverride[][](2)); Vm.Log[] memory logs = vm.getRecordedLogs(); @@ -1286,7 +1320,7 @@ contract OffRamp_batchExecute is OffRampSetup { vm.expectEmit(); emit OffRamp.SkippedReportExecution(SOURCE_CHAIN_SELECTOR_1); - s_offRamp.batchExecute(reports, new uint256[][](2)); + s_offRamp.batchExecute(reports, new OffRamp.GasLimitOverride[][](2)); Vm.Log[] memory logs = vm.getRecordedLogs(); @@ -1318,7 +1352,7 @@ contract OffRamp_batchExecute is OffRampSetup { emit OffRamp.SkippedAlreadyExecutedMessage(SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber); vm.recordLogs(); - s_offRamp.batchExecute(reports, new uint256[][](2)); + s_offRamp.batchExecute(reports, new OffRamp.GasLimitOverride[][](2)); assertExecutionStateChangedEventLogs( messages[0].header.sourceChainSelector, messages[0].header.sequenceNumber, @@ -1337,7 +1371,7 @@ contract OffRamp_batchExecute is OffRampSetup { _generateBatchReportFromMessages( SOURCE_CHAIN_SELECTOR_1, _generateMessagesWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1) ), - new uint256[][](1) + new OffRamp.GasLimitOverride[][](1) ); _setMockRMNChainCurse(SOURCE_CHAIN_SELECTOR_1, false); @@ -1347,7 +1381,7 @@ contract OffRamp_batchExecute is OffRampSetup { _generateBatchReportFromMessages( SOURCE_CHAIN_SELECTOR_1, _generateMessagesWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1) ), - new uint256[][](1) + new OffRamp.GasLimitOverride[][](1) ); _assertNoEmit(OffRamp.SkippedReportExecution.selector); @@ -1356,7 +1390,7 @@ contract OffRamp_batchExecute is OffRampSetup { // Reverts function test_ZeroReports_Revert() public { vm.expectRevert(OffRamp.EmptyReport.selector); - s_offRamp.batchExecute(new Internal.ExecutionReportSingleChain[](0), new uint256[][](1)); + s_offRamp.batchExecute(new Internal.ExecutionReportSingleChain[](0), new OffRamp.GasLimitOverride[][](1)); } function test_OutOfBoundsGasLimitsAccess_Revert() public { @@ -1372,7 +1406,7 @@ contract OffRamp_batchExecute is OffRampSetup { reports[1] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages2); vm.expectRevert(); - s_offRamp.batchExecute(reports, new uint256[][](1)); + s_offRamp.batchExecute(reports, new OffRamp.GasLimitOverride[][](1)); } } @@ -1390,12 +1424,14 @@ contract OffRamp_manuallyExecute is OffRampSetup { _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); messages[0].receiver = address(s_reverting_receiver); messages[0].header.messageId = Internal._hash(messages[0], ON_RAMP_ADDRESS_1); - s_offRamp.batchExecute(_generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[][](1)); + s_offRamp.batchExecute( + _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[][](1) + ); s_reverting_receiver.setRevert(false); - uint256[][] memory gasLimitOverrides = new uint256[][](1); - gasLimitOverrides[0] = new uint256[](messages.length); + OffRamp.GasLimitOverride[][] memory gasLimitOverrides = new OffRamp.GasLimitOverride[][](1); + gasLimitOverrides[0] = new OffRamp.GasLimitOverride[](messages.length); vm.recordLogs(); s_offRamp.manuallyExecute(_generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), gasLimitOverrides); @@ -1414,13 +1450,15 @@ contract OffRamp_manuallyExecute is OffRampSetup { _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); messages[0].receiver = address(s_reverting_receiver); messages[0].header.messageId = Internal._hash(messages[0], ON_RAMP_ADDRESS_1); - s_offRamp.batchExecute(_generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[][](1)); + s_offRamp.batchExecute( + _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[][](1) + ); s_reverting_receiver.setRevert(false); - uint256[][] memory gasLimitOverrides = new uint256[][](1); + OffRamp.GasLimitOverride[][] memory gasLimitOverrides = new OffRamp.GasLimitOverride[][](1); gasLimitOverrides[0] = _getGasLimitsFromMessages(messages); - gasLimitOverrides[0][0] += 1; + gasLimitOverrides[0][0].receiverExecutionGasLimit += 1; vm.recordLogs(); s_offRamp.manuallyExecute(_generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), gasLimitOverrides); assertExecutionStateChangedEventLogs( @@ -1445,7 +1483,7 @@ contract OffRamp_manuallyExecute is OffRampSetup { s_reverting_receiver.setRevert(true); - uint256[][] memory gasLimitOverrides = new uint256[][](1); + OffRamp.GasLimitOverride[][] memory gasLimitOverrides = new OffRamp.GasLimitOverride[][](1); gasLimitOverrides[0] = _getGasLimitsFromMessages(messages); vm.recordLogs(); @@ -1486,20 +1524,20 @@ contract OffRamp_manuallyExecute is OffRampSetup { reports[0] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages1); reports[1] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_3, messages2); - s_offRamp.batchExecute(reports, new uint256[][](2)); + s_offRamp.batchExecute(reports, new OffRamp.GasLimitOverride[][](2)); s_reverting_receiver.setRevert(false); - uint256[][] memory gasLimitOverrides = new uint256[][](2); + OffRamp.GasLimitOverride[][] memory gasLimitOverrides = new OffRamp.GasLimitOverride[][](2); gasLimitOverrides[0] = _getGasLimitsFromMessages(messages1); gasLimitOverrides[1] = _getGasLimitsFromMessages(messages2); for (uint256 i = 0; i < 3; ++i) { - gasLimitOverrides[0][i] += 1; + gasLimitOverrides[0][i].receiverExecutionGasLimit += 1; } for (uint256 i = 0; i < 2; ++i) { - gasLimitOverrides[1][i] += 1; + gasLimitOverrides[1][i].receiverExecutionGasLimit += 1; } vm.recordLogs(); @@ -1543,7 +1581,9 @@ contract OffRamp_manuallyExecute is OffRampSetup { messages[1].header.messageId = Internal._hash(messages[1], ON_RAMP_ADDRESS_1); vm.recordLogs(); - s_offRamp.batchExecute(_generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[][](1)); + s_offRamp.batchExecute( + _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[][](1) + ); Vm.Log[] memory logs = vm.getRecordedLogs(); @@ -1586,9 +1626,9 @@ contract OffRamp_manuallyExecute is OffRampSetup { Internal.Any2EVMRampMessage[] memory newMessages = new Internal.Any2EVMRampMessage[](1); newMessages[0] = messages[1]; - uint256[][] memory gasLimitOverrides = new uint256[][](1); + OffRamp.GasLimitOverride[][] memory gasLimitOverrides = new OffRamp.GasLimitOverride[][](1); gasLimitOverrides[0] = _getGasLimitsFromMessages(newMessages); - gasLimitOverrides[0][0] += 1; + gasLimitOverrides[0][0].receiverExecutionGasLimit += 1; vm.recordLogs(); s_offRamp.manuallyExecute(_generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, newMessages), gasLimitOverrides); @@ -1610,7 +1650,9 @@ contract OffRamp_manuallyExecute is OffRampSetup { messages[0].header.messageId = Internal._hash(messages[0], ON_RAMP_ADDRESS_1); vm.recordLogs(); - s_offRamp.batchExecute(_generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[][](1)); + s_offRamp.batchExecute( + _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[][](1) + ); assertExecutionStateChangedEventLogs( SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber, @@ -1620,9 +1662,9 @@ contract OffRamp_manuallyExecute is OffRampSetup { abi.encodeWithSelector(OffRamp.ReceiverError.selector, "") ); - uint256[][] memory gasLimitOverrides = new uint256[][](1); - gasLimitOverrides[0] = new uint256[](1); - gasLimitOverrides[0][0] = 100_000; + OffRamp.GasLimitOverride[][] memory gasLimitOverrides = new OffRamp.GasLimitOverride[][](1); + gasLimitOverrides[0] = new OffRamp.GasLimitOverride[](1); + gasLimitOverrides[0][0].receiverExecutionGasLimit = 100_000; vm.expectEmit(); emit ConformingReceiver.MessageReceived(); @@ -1652,7 +1694,7 @@ contract OffRamp_manuallyExecute is OffRampSetup { vm.chainId(chain2); vm.expectRevert(abi.encodeWithSelector(MultiOCR3Base.ForkedChain.selector, chain1, chain2)); - uint256[][] memory gasLimitOverrides = new uint256[][](1); + OffRamp.GasLimitOverride[][] memory gasLimitOverrides = new OffRamp.GasLimitOverride[][](1); gasLimitOverrides[0] = _getGasLimitsFromMessages(messages); s_offRamp.manuallyExecute(reports, gasLimitOverrides); @@ -1668,22 +1710,22 @@ contract OffRamp_manuallyExecute is OffRampSetup { // No overrides for report vm.expectRevert(OffRamp.ManualExecutionGasLimitMismatch.selector); - s_offRamp.manuallyExecute(reports, new uint256[][](0)); + s_offRamp.manuallyExecute(reports, new OffRamp.GasLimitOverride[][](0)); // No messages - uint256[][] memory gasLimitOverrides = new uint256[][](1); + OffRamp.GasLimitOverride[][] memory gasLimitOverrides = new OffRamp.GasLimitOverride[][](1); vm.expectRevert(OffRamp.ManualExecutionGasLimitMismatch.selector); s_offRamp.manuallyExecute(reports, gasLimitOverrides); // 1 message missing - gasLimitOverrides[0] = new uint256[](1); + gasLimitOverrides[0] = new OffRamp.GasLimitOverride[](1); vm.expectRevert(OffRamp.ManualExecutionGasLimitMismatch.selector); s_offRamp.manuallyExecute(reports, gasLimitOverrides); // 1 message in excess - gasLimitOverrides[0] = new uint256[](3); + gasLimitOverrides[0] = new OffRamp.GasLimitOverride[](3); vm.expectRevert(OffRamp.ManualExecutionGasLimitMismatch.selector); s_offRamp.manuallyExecute(reports, gasLimitOverrides); @@ -1702,47 +1744,99 @@ contract OffRamp_manuallyExecute is OffRampSetup { reports[1] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_3, messages2); vm.expectRevert(OffRamp.ManualExecutionGasLimitMismatch.selector); - s_offRamp.manuallyExecute(reports, new uint256[][](0)); + s_offRamp.manuallyExecute(reports, new OffRamp.GasLimitOverride[][](0)); vm.expectRevert(OffRamp.ManualExecutionGasLimitMismatch.selector); - s_offRamp.manuallyExecute(reports, new uint256[][](1)); + s_offRamp.manuallyExecute(reports, new OffRamp.GasLimitOverride[][](1)); - uint256[][] memory gasLimitOverrides = new uint256[][](2); + OffRamp.GasLimitOverride[][] memory gasLimitOverrides = new OffRamp.GasLimitOverride[][](2); vm.expectRevert(OffRamp.ManualExecutionGasLimitMismatch.selector); s_offRamp.manuallyExecute(reports, gasLimitOverrides); // 2nd report empty - gasLimitOverrides[0] = new uint256[](2); + gasLimitOverrides[0] = new OffRamp.GasLimitOverride[](2); vm.expectRevert(OffRamp.ManualExecutionGasLimitMismatch.selector); s_offRamp.manuallyExecute(reports, gasLimitOverrides); // 1st report empty - gasLimitOverrides[0] = new uint256[](0); - gasLimitOverrides[1] = new uint256[](1); + gasLimitOverrides[0] = new OffRamp.GasLimitOverride[](0); + gasLimitOverrides[1] = new OffRamp.GasLimitOverride[](1); vm.expectRevert(OffRamp.ManualExecutionGasLimitMismatch.selector); s_offRamp.manuallyExecute(reports, gasLimitOverrides); // 1st report oversized - gasLimitOverrides[0] = new uint256[](3); + gasLimitOverrides[0] = new OffRamp.GasLimitOverride[](3); vm.expectRevert(OffRamp.ManualExecutionGasLimitMismatch.selector); s_offRamp.manuallyExecute(reports, gasLimitOverrides); } - function test_ManualExecInvalidGasLimit_Revert() public { + function test_manuallyExecute_InvalidReceiverExecutionGasLimit_Revert() public { Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - uint256[][] memory gasLimitOverrides = new uint256[][](1); + OffRamp.GasLimitOverride[][] memory gasLimitOverrides = new OffRamp.GasLimitOverride[][](1); + gasLimitOverrides[0] = _getGasLimitsFromMessages(messages); + gasLimitOverrides[0][0].receiverExecutionGasLimit--; + + vm.expectRevert( + abi.encodeWithSelector( + OffRamp.InvalidManualExecutionGasLimit.selector, + SOURCE_CHAIN_SELECTOR_1, + messages[0].header.messageId, + gasLimitOverrides[0][0].receiverExecutionGasLimit + ) + ); + s_offRamp.manuallyExecute(_generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), gasLimitOverrides); + } + + function test_manuallyExecute_DestinationGasAmountCountMismatch_Revert() public { + uint256[] memory amounts = new uint256[](2); + amounts[0] = 1000; + amounts[1] = 1000; + Internal.Any2EVMRampMessage[] memory messages = new Internal.Any2EVMRampMessage[](1); + messages[0] = _generateAny2EVMMessageWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1, amounts); + + OffRamp.GasLimitOverride[][] memory gasLimitOverrides = new OffRamp.GasLimitOverride[][](1); gasLimitOverrides[0] = _getGasLimitsFromMessages(messages); - gasLimitOverrides[0][0]--; + // empty tokenGasOverride array provided + vm.expectRevert( + abi.encodeWithSelector(OffRamp.ManualExecutionGasAmountCountMismatch.selector, messages[0].header.messageId, 1) + ); + s_offRamp.manuallyExecute(_generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), gasLimitOverrides); + + //trying with excesss elements tokenGasOverride array provided + gasLimitOverrides[0][0].tokenGasOverrides = new uint32[](3); + vm.expectRevert( + abi.encodeWithSelector(OffRamp.ManualExecutionGasAmountCountMismatch.selector, messages[0].header.messageId, 1) + ); + s_offRamp.manuallyExecute(_generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), gasLimitOverrides); + } + + function test_manuallyExecute_InvalidTokenGasOverride_Revert() public { + uint256[] memory amounts = new uint256[](2); + amounts[0] = 1000; + amounts[1] = 1000; + Internal.Any2EVMRampMessage[] memory messages = new Internal.Any2EVMRampMessage[](1); + messages[0] = _generateAny2EVMMessageWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1, amounts); + + OffRamp.GasLimitOverride[][] memory gasLimitOverrides = new OffRamp.GasLimitOverride[][](1); + gasLimitOverrides[0] = _getGasLimitsFromMessages(messages); + uint32[] memory tokenGasOverrides = new uint32[](2); + tokenGasOverrides[0] = DEFAULT_TOKEN_DEST_GAS_OVERHEAD; + tokenGasOverrides[1] = DEFAULT_TOKEN_DEST_GAS_OVERHEAD - 1; //invalid token gas override value + gasLimitOverrides[0][0].tokenGasOverrides = tokenGasOverrides; vm.expectRevert( abi.encodeWithSelector( - OffRamp.InvalidManualExecutionGasLimit.selector, SOURCE_CHAIN_SELECTOR_1, 0, gasLimitOverrides[0][0] + OffRamp.InvalidManualExecutionTokenGasOverride.selector, + messages[0].header.messageId, + 1, + DEFAULT_TOKEN_DEST_GAS_OVERHEAD, + tokenGasOverrides[1] ) ); s_offRamp.manuallyExecute(_generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), gasLimitOverrides); @@ -1755,11 +1849,13 @@ contract OffRamp_manuallyExecute is OffRampSetup { messages[0].receiver = address(s_reverting_receiver); messages[0].header.messageId = Internal._hash(messages[0], ON_RAMP_ADDRESS_1); - s_offRamp.batchExecute(_generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new uint256[][](1)); + s_offRamp.batchExecute( + _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[][](1) + ); s_reverting_receiver.setRevert(true); - uint256[][] memory gasLimitOverrides = new uint256[][](1); + OffRamp.GasLimitOverride[][] memory gasLimitOverrides = new OffRamp.GasLimitOverride[][](1); gasLimitOverrides[0] = _getGasLimitsFromMessages(messages); vm.expectRevert( @@ -1795,7 +1891,7 @@ contract OffRamp_manuallyExecute is OffRampSetup { destTokenAddress: abi.encode(s_destTokenBySourceToken[s_sourceFeeToken]), extraData: "", amount: tokenAmount, - destExecData: abi.encode(DEFAULT_TOKEN_DEST_GAS_OVERHEAD) + destExecData: abi.encode(MAX_TOKEN_POOL_RELEASE_OR_MINT_GAS) }); messages[0].receiver = address(receiver); @@ -1807,8 +1903,9 @@ contract OffRamp_manuallyExecute is OffRampSetup { // sets the report to be repeated on the ReentrancyAbuser to be able to replay receiver.setPayload(report); - uint256[][] memory gasLimitOverrides = new uint256[][](1); + OffRamp.GasLimitOverride[][] memory gasLimitOverrides = new OffRamp.GasLimitOverride[][](1); gasLimitOverrides[0] = _getGasLimitsFromMessages(messages); + gasLimitOverrides[0][0].tokenGasOverrides = new uint32[](messages[0].tokenAmounts.length); // The first entry should be fine and triggers the second entry which is skipped. Due to the reentrancy // the second completes first, so we expect the skip event before the success event. @@ -1852,7 +1949,7 @@ contract OffRamp_manuallyExecute is OffRampSetup { reports[0] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages1); reports[1] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_3, messages2); - uint256[][] memory gasLimitOverrides = new uint256[][](2); + OffRamp.GasLimitOverride[][] memory gasLimitOverrides = new OffRamp.GasLimitOverride[][](2); gasLimitOverrides[0] = _getGasLimitsFromMessages(messages1); gasLimitOverrides[1] = _getGasLimitsFromMessages(messages2); @@ -1873,7 +1970,7 @@ contract OffRamp_manuallyExecute is OffRampSetup { reports[0] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages1); reports[1] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_3, messages2); - uint256[][] memory gasLimitOverrides = new uint256[][](2); + OffRamp.GasLimitOverride[][] memory gasLimitOverrides = new OffRamp.GasLimitOverride[][](2); gasLimitOverrides[0] = _getGasLimitsFromMessages(messages1); gasLimitOverrides[1] = _getGasLimitsFromMessages(messages2); @@ -2165,7 +2262,7 @@ contract OffRamp_execute is OffRampSetup { function test_IncorrectArrayType_Revert() public { bytes32[3] memory reportContext = [s_configDigestExec, s_configDigestExec, s_configDigestExec]; - uint256[] memory wrongData = new uint256[](1); + uint256[] memory wrongData = new uint256[](2); wrongData[0] = 1; vm.startPrank(s_validTransmitters[0]); @@ -2355,7 +2452,7 @@ contract OffRamp_trialExecute is OffRampSetup { uint256 startingBalance = dstToken0.balanceOf(message.receiver); (Internal.MessageExecutionState newState, bytes memory err) = - s_offRamp.trialExecute(message, new bytes[](message.tokenAmounts.length)); + s_offRamp.trialExecute(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); assertEq(uint256(Internal.MessageExecutionState.SUCCESS), uint256(newState)); assertEq("", err); @@ -2378,7 +2475,7 @@ contract OffRamp_trialExecute is OffRampSetup { s_maybeRevertingPool.setShouldRevert(errorMessage); (Internal.MessageExecutionState newState, bytes memory err) = - s_offRamp.trialExecute(message, new bytes[](message.tokenAmounts.length)); + s_offRamp.trialExecute(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); assertEq(uint256(Internal.MessageExecutionState.FAILURE), uint256(newState)); assertEq(abi.encodeWithSelector(OffRamp.TokenHandlingError.selector, errorMessage), err); @@ -2398,7 +2495,7 @@ contract OffRamp_trialExecute is OffRampSetup { s_maybeRevertingPool.setShouldRevert(errorMessage); (Internal.MessageExecutionState newState, bytes memory err) = - s_offRamp.trialExecute(message, new bytes[](message.tokenAmounts.length)); + s_offRamp.trialExecute(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); assertEq(uint256(Internal.MessageExecutionState.FAILURE), uint256(newState)); assertEq(abi.encodeWithSelector(OffRamp.TokenHandlingError.selector, errorMessage), err); } @@ -2412,7 +2509,7 @@ contract OffRamp_trialExecute is OffRampSetup { // Happy path, pool is correct (Internal.MessageExecutionState newState, bytes memory err) = - s_offRamp.trialExecute(message, new bytes[](message.tokenAmounts.length)); + s_offRamp.trialExecute(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); assertEq(uint256(Internal.MessageExecutionState.SUCCESS), uint256(newState)); assertEq("", err); @@ -2431,7 +2528,7 @@ contract OffRamp_trialExecute is OffRampSetup { message.header.messageId = Internal._hash(message, ON_RAMP_ADDRESS_1); // Unhappy path, no revert but marked as failed. - (newState, err) = s_offRamp.trialExecute(message, new bytes[](message.tokenAmounts.length)); + (newState, err) = s_offRamp.trialExecute(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); assertEq(uint256(Internal.MessageExecutionState.FAILURE), uint256(newState)); assertEq(abi.encodeWithSelector(Internal.InvalidEVMAddress.selector, abi.encode(address(0))), err); @@ -2448,7 +2545,7 @@ contract OffRamp_trialExecute is OffRampSetup { message.header.messageId = Internal._hash(message, ON_RAMP_ADDRESS_1); - (newState, err) = s_offRamp.trialExecute(message, new bytes[](message.tokenAmounts.length)); + (newState, err) = s_offRamp.trialExecute(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); assertEq(uint256(Internal.MessageExecutionState.FAILURE), uint256(newState)); assertEq(abi.encodeWithSelector(OffRamp.NotACompatiblePool.selector, address(0)), err); @@ -2705,7 +2802,47 @@ contract OffRamp_releaseOrMintTokens is OffRampSetup { ); s_offRamp.releaseOrMintTokens( - sourceTokenAmounts, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR_1, offchainTokenData + sourceTokenAmounts, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR_1, offchainTokenData, new uint32[](0) + ); + + assertEq(startingBalance + amount1, dstToken1.balanceOf(OWNER)); + } + + function test_releaseOrMintTokens_WithGasOverride_Success() public { + Client.EVMTokenAmount[] memory srcTokenAmounts = _getCastedSourceEVMTokenAmountsWithZeroAmounts(); + IERC20 dstToken1 = IERC20(s_destFeeToken); + uint256 startingBalance = dstToken1.balanceOf(OWNER); + uint256 amount1 = 100; + srcTokenAmounts[0].amount = amount1; + + bytes[] memory offchainTokenData = new bytes[](srcTokenAmounts.length); + offchainTokenData[0] = abi.encode(0x12345678); + + Internal.RampTokenAmount[] memory sourceTokenAmounts = _getDefaultSourceTokenData(srcTokenAmounts); + + vm.expectCall( + s_destPoolBySourceToken[srcTokenAmounts[0].token], + abi.encodeWithSelector( + LockReleaseTokenPool.releaseOrMint.selector, + Pool.ReleaseOrMintInV1({ + originalSender: abi.encode(OWNER), + receiver: OWNER, + amount: srcTokenAmounts[0].amount, + localToken: s_destTokenBySourceToken[srcTokenAmounts[0].token], + remoteChainSelector: SOURCE_CHAIN_SELECTOR_1, + sourcePoolAddress: sourceTokenAmounts[0].sourcePoolAddress, + sourcePoolData: sourceTokenAmounts[0].extraData, + offchainTokenData: offchainTokenData[0] + }) + ) + ); + + uint32[] memory gasOverrides = new uint32[](sourceTokenAmounts.length); + for (uint256 i = 0; i < gasOverrides.length; i++) { + gasOverrides[i] = DEFAULT_TOKEN_DEST_GAS_OVERHEAD + 1; + } + s_offRamp.releaseOrMintTokens( + sourceTokenAmounts, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR_1, offchainTokenData, gasOverrides ); assertEq(startingBalance + amount1, dstToken1.balanceOf(OWNER)); @@ -2727,7 +2864,7 @@ contract OffRamp_releaseOrMintTokens is OffRampSetup { MaybeRevertingBurnMintTokenPool(pool).setReleaseOrMintMultiplier(destinationDenominationMultiplier); Client.EVMTokenAmount[] memory destTokenAmounts = s_offRamp.releaseOrMintTokens( - sourceTokenAmounts, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR_1, offchainTokenData + sourceTokenAmounts, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR_1, offchainTokenData, new uint32[](0) ); assertEq(destTokenAmounts[1].amount, amount * destinationDenominationMultiplier); assertEq(destTokenAmounts[1].token, destToken); @@ -2748,7 +2885,8 @@ contract OffRamp_releaseOrMintTokens is OffRampSetup { abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR_1, - new bytes[](srcTokenAmounts.length) + new bytes[](srcTokenAmounts.length), + new uint32[](0) ); } @@ -2782,7 +2920,7 @@ contract OffRamp_releaseOrMintTokens is OffRampSetup { vm.expectRevert(abi.encodeWithSelector(OffRamp.InvalidDataLength.selector, Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES, 64)); s_offRamp.releaseOrMintTokens( - sourceTokenAmounts, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR_1, offchainTokenData + sourceTokenAmounts, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR_1, offchainTokenData, new uint32[](0) ); } @@ -2798,7 +2936,7 @@ contract OffRamp_releaseOrMintTokens is OffRampSetup { vm.expectRevert(abi.encodeWithSelector(Internal.InvalidEVMAddress.selector, wrongAddress)); s_offRamp.releaseOrMintTokens( - sourceTokenAmounts, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR_1, offchainTokenData + sourceTokenAmounts, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR_1, offchainTokenData, new uint32[](0) ); } @@ -2816,7 +2954,9 @@ contract OffRamp_releaseOrMintTokens is OffRampSetup { }); vm.expectRevert(abi.encodeWithSelector(OffRamp.NotACompatiblePool.selector, address(0))); - s_offRamp.releaseOrMintTokens(sourceTokenAmounts, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR_1, new bytes[](1)); + s_offRamp.releaseOrMintTokens( + sourceTokenAmounts, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR_1, new bytes[](1), new uint32[](0) + ); } function test_releaseOrMintTokens_PoolDoesNotSupportDest_Reverts() public { @@ -2847,7 +2987,7 @@ contract OffRamp_releaseOrMintTokens is OffRampSetup { ); vm.expectRevert(); s_offRamp.releaseOrMintTokens( - sourceTokenAmounts, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR_3, offchainTokenData + sourceTokenAmounts, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR_3, offchainTokenData, new uint32[](0) ); } @@ -2869,7 +3009,7 @@ contract OffRamp_releaseOrMintTokens is OffRampSetup { }); try s_offRamp.releaseOrMintTokens( - sourceTokenAmounts, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR_1, new bytes[](1) + sourceTokenAmounts, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR_1, new bytes[](1), new uint32[](0) ) {} catch (bytes memory reason) { // Any revert should be a TokenHandlingError, InvalidEVMAddress, InvalidDataLength or NoContract as those are caught by the offramp assertTrue( diff --git a/contracts/src/v0.8/ccip/test/offRamp/OffRampSetup.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRampSetup.t.sol index bb890ef1b8..393d35bdc9 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/OffRampSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRampSetup.t.sol @@ -227,9 +227,7 @@ contract OffRampSetup is FeeQuoterSetup, MultiOCR3BaseSetup { return OffRamp.DynamicConfig({ permissionLessExecutionThresholdSeconds: PERMISSION_LESS_EXECUTION_THRESHOLD_SECONDS, feeQuoter: feeQuoter, - messageValidator: address(0), - maxPoolReleaseOrMintGas: MAX_TOKEN_POOL_RELEASE_OR_MINT_GAS, - maxTokenTransferGas: MAX_TOKEN_POOL_TRANSFER_GAS + messageValidator: address(0) }); } @@ -373,10 +371,10 @@ contract OffRampSetup is FeeQuoterSetup, MultiOCR3BaseSetup { function _getGasLimitsFromMessages( Internal.Any2EVMRampMessage[] memory messages - ) internal pure returns (uint256[] memory) { - uint256[] memory gasLimits = new uint256[](messages.length); + ) internal pure returns (OffRamp.GasLimitOverride[] memory) { + OffRamp.GasLimitOverride[] memory gasLimits = new OffRamp.GasLimitOverride[](messages.length); for (uint256 i = 0; i < messages.length; ++i) { - gasLimits[i] = messages[i].gasLimit; + gasLimits[i].receiverExecutionGasLimit = messages[i].gasLimit; } return gasLimits; @@ -384,8 +382,6 @@ contract OffRampSetup is FeeQuoterSetup, MultiOCR3BaseSetup { function _assertSameConfig(OffRamp.DynamicConfig memory a, OffRamp.DynamicConfig memory b) public pure { assertEq(a.permissionLessExecutionThresholdSeconds, b.permissionLessExecutionThresholdSeconds); - assertEq(a.maxPoolReleaseOrMintGas, b.maxPoolReleaseOrMintGas); - assertEq(a.maxTokenTransferGas, b.maxTokenTransferGas); assertEq(a.messageValidator, b.messageValidator); assertEq(a.feeQuoter, b.feeQuoter); } diff --git a/core/gethwrappers/ccip/deployment_test/deployment_test.go b/core/gethwrappers/ccip/deployment_test/deployment_test.go index c89ca23917..0d91d63b0a 100644 --- a/core/gethwrappers/ccip/deployment_test/deployment_test.go +++ b/core/gethwrappers/ccip/deployment_test/deployment_test.go @@ -48,8 +48,6 @@ func TestDeployAllV1_6(t *testing.T) { }, offramp.OffRampDynamicConfig{ FeeQuoter: common.HexToAddress("0x4"), PermissionLessExecutionThresholdSeconds: uint32((8 * time.Hour).Seconds()), - MaxTokenTransferGas: 50_000, - MaxPoolReleaseOrMintGas: 50_000, MessageValidator: common.HexToAddress("0x5"), }, nil) require.NoError(t, err) diff --git a/core/gethwrappers/ccip/generated/offramp/offramp.go b/core/gethwrappers/ccip/generated/offramp/offramp.go index 1711c3d1e2..d2cfd96e75 100644 --- a/core/gethwrappers/ccip/generated/offramp/offramp.go +++ b/core/gethwrappers/ccip/generated/offramp/offramp.go @@ -124,11 +124,14 @@ type MultiOCR3BaseOCRConfigArgs struct { type OffRampDynamicConfig struct { FeeQuoter common.Address PermissionLessExecutionThresholdSeconds uint32 - MaxTokenTransferGas uint32 - MaxPoolReleaseOrMintGas uint32 MessageValidator common.Address } +type OffRampGasLimitOverride struct { + ReceiverExecutionGasLimit *big.Int + TokenGasOverrides []uint32 +} + type OffRampSourceChainConfig struct { Router common.Address IsEnabled bool @@ -151,8 +154,8 @@ type OffRampStaticConfig struct { } var OffRampMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CanOnlySelfCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"actual\",\"type\":\"bytes32\"}],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ExecutionError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"ForkedChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enumMultiOCR3Base.InvalidConfigErrorType\",\"name\":\"errorType\",\"type\":\"uint8\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"got\",\"type\":\"uint256\"}],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidEVMAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"name\":\"InvalidInterval\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"newLimit\",\"type\":\"uint256\"}],\"name\":\"InvalidManualExecutionGasLimit\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"messageDestChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidMessageDestChainSelector\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"newState\",\"type\":\"uint8\"}],\"name\":\"InvalidNewState\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRoot\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidStaticConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LeavesCannotBeEmpty\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ManualExecutionGasLimitMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"ManualExecutionNotYetEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"errorReason\",\"type\":\"bytes\"}],\"name\":\"MessageValidationError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonUniqueSignatures\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"notPool\",\"type\":\"address\"}],\"name\":\"NotACompatiblePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OracleCannotBeZeroAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ReceiverError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountReleased\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePre\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePost\",\"type\":\"uint256\"}],\"name\":\"ReleaseOrMintBalanceMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"name\":\"RootAlreadyCommitted\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"RootNotCommitted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignatureVerificationDisabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignaturesOutOfRegistration\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"reportSourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"messageSourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainSelectorMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"StaleCommitReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"StaticConfigCannotBeChanged\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"TokenDataMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"TokenHandlingError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnexpectedTokenData\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"WrongMessageLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WrongNumberOfSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroChainSelectorNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"AlreadyAttempted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"indexed\":false,\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"}],\"name\":\"CommitReportAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"DynamicConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"messageHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"name\":\"ExecutionStateChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"RootRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"SkippedAlreadyExecutedMessage\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SkippedReportExecution\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"sourceConfig\",\"type\":\"tuple\"}],\"name\":\"SourceChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainSelectorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"}],\"name\":\"StaticConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigUpdates\",\"type\":\"tuple[]\"}],\"name\":\"applySourceChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"destTokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structClient.Any2EVMMessage\",\"name\":\"\",\"type\":\"tuple\"}],\"name\":\"ccipReceive\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"rawVs\",\"type\":\"bytes32\"}],\"name\":\"commit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"execute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"bytes[]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[]\"}],\"name\":\"executeSingleMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"getExecutionState\",\"outputs\":[{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLatestPriceSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"getMerkleRoot\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"getSourceChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"latestConfigDetails\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"n\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"}],\"internalType\":\"structMultiOCR3Base.ConfigInfo\",\"name\":\"configInfo\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfig\",\"name\":\"ocrConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage[]\",\"name\":\"messages\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[][]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[][]\"},{\"internalType\":\"bytes32[]\",\"name\":\"proofs\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"proofFlagBits\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.ExecutionReportSingleChain[]\",\"name\":\"reports\",\"type\":\"tuple[]\"},{\"internalType\":\"uint256[][]\",\"name\":\"gasLimitOverrides\",\"type\":\"uint256[][]\"}],\"name\":\"manuallyExecute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxTokenTransferGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPoolReleaseOrMintGas\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"setDynamicConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfigArgs[]\",\"name\":\"ocrConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"setOCR3Configs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x6101206040523480156200001257600080fd5b5060405162006ca038038062006ca08339810160408190526200003591620008c7565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf81620001fa565b5050466080525060208301516001600160a01b03161580620000ec575060408301516001600160a01b0316155b8062000103575060608301516001600160a01b0316155b1562000122576040516342bcdf7f60e11b815260040160405180910390fd5b82516001600160401b03166000036200014e5760405163c656089560e01b815260040160405180910390fd5b82516001600160401b0390811660a052602080850180516001600160a01b0390811660c05260408088018051831660e0526060808a01805185166101005283518b519098168852945184169587019590955251821690850152905116908201527f683eb52ee924eb817377cfa8f41f238f4bb7a877da5267869dfffbad85f564d89060800160405180910390a1620001e682620002a5565b620001f181620003c1565b50505062000c67565b336001600160a01b03821603620002545760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b0316620002ce576040516342bcdf7f60e11b815260040160405180910390fd5b80516004805460208085018051604080880180516060808b0180516001600160a01b039b8c166001600160c01b0319909a168a17600160a01b63ffffffff98891602176001600160c01b0316600160c01b948816949094026001600160e01b031693909317600160e01b93871693909302929092179098556080808b018051600580546001600160a01b031916918d169190911790558451988952955185169688019690965290518316918601919091525116938301939093529151909216908201527fa55bd56595c45f517e5967a3067f3dca684445a3080e7c04a4e0d5a40cda627d9060a00160405180910390a150565b60005b815181101562000666576000828281518110620003e557620003e562000a1d565b60200260200101519050600081602001519050806001600160401b0316600003620004235760405163c656089560e01b815260040160405180910390fd5b81516001600160a01b03166200044c576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160401b0381166000908152600660205260408120600181018054919291620004789062000a33565b80601f0160208091040260200160405190810160405280929190818152602001828054620004a69062000a33565b8015620004f75780601f10620004cb57610100808354040283529160200191620004f7565b820191906000526020600020905b815481529060010190602001808311620004d957829003601f168201915b5050505050905060008460600151905081516000036200059e57805160000362000534576040516342bcdf7f60e11b815260040160405180910390fd5b6001830162000544828262000ac4565b508254600160a81b600160e81b031916600160a81b1783556040516001600160401b03851681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1620005d9565b8080519060200120828051906020012014620005d95760405163c39a620560e01b81526001600160401b038516600482015260240162000083565b604080860151845487516001600160a01b03166001600160a01b0319921515600160a01b02929092166001600160a81b031990911617178455516001600160401b038516907f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b906200064d90869062000b90565b60405180910390a25050505050806001019050620003c4565b5050565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b0381118282101715620006a557620006a56200066a565b60405290565b604051601f8201601f191681016001600160401b0381118282101715620006d657620006d66200066a565b604052919050565b80516001600160401b0381168114620006f657600080fd5b919050565b6001600160a01b03811681146200071157600080fd5b50565b805163ffffffff81168114620006f657600080fd5b6000601f83601f8401126200073d57600080fd5b825160206001600160401b03808311156200075c576200075c6200066a565b8260051b6200076d838201620006ab565b93845286810183019383810190898611156200078857600080fd5b84890192505b85831015620008ba57825184811115620007a85760008081fd5b89016080601f19828d038101821315620007c25760008081fd5b620007cc62000680565b88840151620007db81620006fb565b81526040620007ec858201620006de565b8a8301526060808601518015158114620008065760008081fd5b838301529385015193898511156200081e5760008081fd5b84860195508f603f8701126200083657600094508485fd5b8a8601519450898511156200084f576200084f6200066a565b620008608b858f88011601620006ab565b93508484528f82868801011115620008785760008081fd5b60005b8581101562000898578681018301518582018d01528b016200087b565b5060009484018b0194909452509182015283525091840191908401906200078e565b9998505050505050505050565b6000806000838503610140811215620008df57600080fd5b6080811215620008ee57600080fd5b620008f862000680565b6200090386620006de565b815260208601516200091581620006fb565b602082015260408601516200092a81620006fb565b604082015260608601516200093f81620006fb565b6060820152935060a0607f19820112156200095957600080fd5b5060405160a081016001600160401b0380821183831017156200098057620009806200066a565b81604052608087015191506200099682620006fb565b818352620009a760a0880162000714565b6020840152620009ba60c0880162000714565b6040840152620009cd60e0880162000714565b60608401526101008701519150620009e582620006fb565b608083018290526101208701519294508083111562000a0357600080fd5b505062000a138682870162000729565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b600181811c9082168062000a4857607f821691505b60208210810362000a6957634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111562000abf576000816000526020600020601f850160051c8101602086101562000a9a5750805b601f850160051c820191505b8181101562000abb5782815560010162000aa6565b5050505b505050565b81516001600160401b0381111562000ae05762000ae06200066a565b62000af88162000af1845462000a33565b8462000a6f565b602080601f83116001811462000b30576000841562000b175750858301515b600019600386901b1c1916600185901b17855562000abb565b600085815260208120601f198616915b8281101562000b615788860151825594840194600190910190840162000b40565b508582101562000b805787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b602080825282546001600160a01b0381168383015260a081901c60ff161515604084015260a81c6001600160401b0316606083015260808083015260018084018054600093929190849062000be58162000a33565b8060a089015260c0600183166000811462000c09576001811462000c265762000c58565b60ff19841660c08b015260c083151560051b8b0101945062000c58565b85600052602060002060005b8481101562000c4f5781548c820185015290880190890162000c32565b8b0160c0019550505b50929998505050505050505050565b60805160a05160c05160e05161010051615fc362000cdd600039600081816102400152612a730152600081816102110152612f670152600081816101e20152818161077f0152818161098601526123f50152600081816101b201526126820152600081816117e3015261182f0152615fc36000f3fe608060405234801561001057600080fd5b50600436106101515760003560e01c806379ba5097116100cd578063c673e58411610081578063e9d68a8e11610066578063e9d68a8e1461052a578063f2fde38b1461054a578063f716f99f1461055d57600080fd5b8063c673e584146104c5578063ccd37ba3146104e557600080fd5b80638da5cb5b116100b25780638da5cb5b14610484578063991a50181461049f578063a80036b4146104b257600080fd5b806379ba50971461046e57806385572ffb1461047657600080fd5b80632d04ab76116101245780633f4b04aa116101095780633f4b04aa146103365780635e36480c146103525780637437ff9f1461037257600080fd5b80632d04ab7614610310578063311cd5131461032357600080fd5b806304666f9c1461015657806305d938b51461016b57806306285c691461017e578063181f5a77146102c7575b600080fd5b610169610164366004614133565b610570565b005b6101696101793660046147bd565b610584565b61027060408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316815250905090565b6040516102be9190815167ffffffffffffffff1681526020808301516001600160a01b0390811691830191909152604080840151821690830152606092830151169181019190915260800190565b60405180910390f35b6103036040518060400160405280601181526020017f4f666652616d7020312e362e302d64657600000000000000000000000000000081525081565b6040516102be9190614938565b61016961031e3660046149e3565b610729565b610169610331366004614a96565b610cc7565b60095460405167ffffffffffffffff90911681526020016102be565b610365610360366004614aea565b610d30565b6040516102be9190614b47565b6104116040805160a081018252600080825260208201819052918101829052606081018290526080810191909152506040805160a0810182526004546001600160a01b03808216835263ffffffff600160a01b83048116602085015278010000000000000000000000000000000000000000000000008304811694840194909452600160e01b9091049092166060820152600554909116608082015290565b6040516102be9190600060a0820190506001600160a01b03808451168352602084015163ffffffff808216602086015280604087015116604086015280606087015116606086015250508060808501511660808401525092915050565b610169610d86565b610169610151366004614b55565b6000546040516001600160a01b0390911681526020016102be565b6101696104ad366004614ba4565b610e44565b6101696104c0366004614c18565b610e55565b6104d86104d3366004614c85565b6111c8565b6040516102be9190614ce5565b61051c6104f3366004614d5a565b67ffffffffffffffff919091166000908152600860209081526040808320938352929052205490565b6040519081526020016102be565b61053d610538366004614d84565b611326565b6040516102be9190614d9f565b610169610558366004614ded565b611433565b61016961056b366004614e72565b611444565b610578611486565b610581816114e2565b50565b61058c6117e0565b8151815181146105c8576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b818110156107195760008482815181106105e7576105e7614fb0565b6020026020010151905060008160200151519050600085848151811061060f5761060f614fb0565b6020026020010151905080518214610653576040517f83e3f56400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b8281101561070a57600082828151811061067257610672614fb0565b6020026020010151905080600014610701578460200151828151811061069a5761069a614fb0565b6020026020010151608001518110156107015784516040517fc8e9605100000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260248101839052604481018290526064015b60405180910390fd5b50600101610656565b505050508060010190506105cb565b506107248383611861565b505050565b6000610737878901896151df565b602081015151909150156107e357602081015160408083015190517fccd5af000000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169263ccd5af00926107b292600401615409565b60006040518083038186803b1580156107ca57600080fd5b505afa1580156107de573d6000803e3d6000fd5b505050505b805151511515806107f957508051602001515115155b156108f95760095460208a01359067ffffffffffffffff808316911610156108b8576009805467ffffffffffffffff191667ffffffffffffffff83161790556004805483516040517f3937306f0000000000000000000000000000000000000000000000000000000081526001600160a01b0390921692633937306f92610881929101615528565b600060405180830381600087803b15801561089b57600080fd5b505af11580156108af573d6000803e3d6000fd5b505050506108f7565b8160200151516000036108f7576040517f2261116700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b60005b816020015151811015610c085760008260200151828151811061092157610921614fb0565b602090810291909101015180516040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815277ffffffffffffffff00000000000000000000000000000000608083901b166004820152919250906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632cbc26bb90602401602060405180830381865afa1580156109cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109f1919061553b565b15610a34576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff821660048201526024016106f8565b6000610a3f82611911565b6040840151815491925067ffffffffffffffff908116600160a81b90920416141580610a865750826060015167ffffffffffffffff16836040015167ffffffffffffffff16115b15610ae5578251604080850151606086015191517fd5e0f0d600000000000000000000000000000000000000000000000000000000815267ffffffffffffffff93841660048201529083166024820152911660448201526064016106f8565b608083015180610b21576040517f504570e300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b835167ffffffffffffffff16600090815260086020908152604080832084845290915290205415610b945783516040517f32cf0cbf00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602481018290526044016106f8565b6060840151610ba490600161556e565b82547fffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffff16600160a81b67ffffffffffffffff9283160217909255925116600090815260086020908152604080832094835293905291909120429055506001016108fc565b50602081015181516040517f35c02761bcd3ef995c6a601a1981f4ed3934dcbe5041e24e286c89f5531d17e492610c40929091615596565b60405180910390a1610cbc60008a8a8a8a8a8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808e0282810182019093528d82529093508d92508c9182918501908490808284376000920191909152508b9250611978915050565b505050505050505050565b610d07610cd6828401846155bb565b6040805160008082526020820190925290610d01565b6060815260200190600190039081610cec5790505b50611861565b604080516000808252602082019092529050610d2a600185858585866000611978565b50505050565b6000610d3e600160046155f0565b6002610d4b608085615619565b67ffffffffffffffff16610d5f9190615640565b610d698585611cef565b901c166003811115610d7d57610d7d614b1d565b90505b92915050565b6001546001600160a01b03163314610de05760405162461bcd60e51b815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064016106f8565b600080543373ffffffffffffffffffffffffffffffffffffffff19808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610e4c611486565b61058181611d36565b333014610e8e576040517f371a732800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160008082526020820190925281610ecb565b6040805180820190915260008082526020820152815260200190600190039081610ea45790505b5060a08501515190915015610eff57610efc8460a00151856020015186606001518760000151602001518787611e9c565b90505b6040805160a0810182528551518152855160209081015167ffffffffffffffff1681830152808701518351600094840192610f3b929101614938565b60408051601f19818403018152918152908252878101516020830152018390526005549091506001600160a01b03168015611048576040517f08d450a10000000000000000000000000000000000000000000000000000000081526001600160a01b038216906308d450a190610fb59085906004016156f9565b600060405180830381600087803b158015610fcf57600080fd5b505af1925050508015610fe0575060015b611048573d80801561100e576040519150601f19603f3d011682016040523d82523d6000602084013e611013565b606091505b50806040517f09c253250000000000000000000000000000000000000000000000000000000081526004016106f89190614938565b60408601515115801561105d57506080860151155b80611074575060608601516001600160a01b03163b155b806110b4575060608601516110b2906001600160a01b03167f85572ffb00000000000000000000000000000000000000000000000000000000611fbb565b155b156110c157505050505050565b855160209081015167ffffffffffffffff1660009081526006909152604080822054608089015160608a015192517f3cf9798300000000000000000000000000000000000000000000000000000000815284936001600160a01b0390931692633cf9798392611139928992611388929160040161570c565b6000604051808303816000875af1158015611158573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526111809190810190615748565b5091509150816111be57806040517f0a8d6e8c0000000000000000000000000000000000000000000000000000000081526004016106f89190614938565b5050505050505050565b61120b6040805160e081019091526000606082018181526080830182905260a0830182905260c08301919091528190815260200160608152602001606081525090565b60ff808316600090815260026020818152604092839020835160e081018552815460608201908152600183015480881660808401526101008104881660a0840152620100009004909616151560c0820152948552918201805484518184028101840190955280855292938583019390928301828280156112b457602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611296575b505050505081526020016003820180548060200260200160405190810160405280929190818152602001828054801561131657602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116112f8575b5050505050815250509050919050565b604080516080808201835260008083526020808401829052838501829052606080850181905267ffffffffffffffff878116845260068352928690208651948501875280546001600160a01b0381168652600160a01b810460ff16151593860193909352600160a81b9092049092169483019490945260018401805493949293918401916113b3906157de565b80601f01602080910402602001604051908101604052809291908181526020018280546113df906157de565b80156113165780601f1061140157610100808354040283529160200191611316565b820191906000526020600020905b81548152906001019060200180831161140f57505050919092525091949350505050565b61143b611486565b61058181611fd7565b61144c611486565b60005b81518110156114825761147a82828151811061146d5761146d614fb0565b602002602001015161208d565b60010161144f565b5050565b6000546001600160a01b031633146114e05760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016106f8565b565b60005b815181101561148257600082828151811061150257611502614fb0565b602002602001015190506000816020015190508067ffffffffffffffff16600003611559576040517fc656089500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81516001600160a01b0316611581576040516342bcdf7f60e11b815260040160405180910390fd5b67ffffffffffffffff811660009081526006602052604081206001810180549192916115ac906157de565b80601f01602080910402602001604051908101604052809291908181526020018280546115d8906157de565b80156116255780601f106115fa57610100808354040283529160200191611625565b820191906000526020600020905b81548152906001019060200180831161160857829003601f168201915b5050505050905060008460600151905081516000036116dd578051600003611660576040516342bcdf7f60e11b815260040160405180910390fd5b6001830161166e8282615868565b5082547fffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffff16600160a81b17835560405167ffffffffffffffff851681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1611730565b8080519060200120828051906020012014611730576040517fc39a620500000000000000000000000000000000000000000000000000000000815267ffffffffffffffff851660048201526024016106f8565b604080860151845487516001600160a01b031673ffffffffffffffffffffffffffffffffffffffff19921515600160a01b02929092167fffffffffffffffffffffff000000000000000000000000000000000000000000909116171784555167ffffffffffffffff8516907f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b906117c8908690615928565b60405180910390a250505050508060010190506114e5565b467f0000000000000000000000000000000000000000000000000000000000000000146114e0576040517f0f01ce850000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060048201524660248201526044016106f8565b815160000361189b576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160408051600080825260208201909252911591905b845181101561190a576119028582815181106118d0576118d0614fb0565b6020026020010151846118fc578583815181106118ef576118ef614fb0565b60200260200101516123a1565b836123a1565b6001016118b2565b5050505050565b67ffffffffffffffff811660009081526006602052604081208054600160a01b900460ff16610d80576040517fed053c5900000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024016106f8565b60ff878116600090815260026020908152604080832081516080810183528154815260019091015480861693820193909352610100830485169181019190915262010000909104909216151560608301528735906119d78760a46159f6565b9050826060015115611a1f5784516119f0906020615640565b86516119fd906020615640565b611a089060a06159f6565b611a1291906159f6565b611a1c90826159f6565b90505b368114611a61576040517f8e1192e1000000000000000000000000000000000000000000000000000000008152600481018290523660248201526044016106f8565b5081518114611aa95781516040517f93df584c0000000000000000000000000000000000000000000000000000000081526004810191909152602481018290526044016106f8565b611ab16117e0565b60ff808a1660009081526003602090815260408083203384528252808320815180830190925280548086168352939491939092840191610100909104166002811115611aff57611aff614b1d565b6002811115611b1057611b10614b1d565b9052509050600281602001516002811115611b2d57611b2d614b1d565b148015611b815750600260008b60ff1660ff168152602001908152602001600020600301816000015160ff1681548110611b6957611b69614fb0565b6000918252602090912001546001600160a01b031633145b611bb7576040517fda0f08e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50816060015115611c99576020820151611bd2906001615a09565b60ff16855114611c0e576040517f71253a2500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8351855114611c49576040517fa75d88af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008787604051611c5b929190615a22565b604051908190038120611c72918b90602001615a32565b604051602081830303815290604052805190602001209050611c978a82888888612d21565b505b6040805182815260208a81013567ffffffffffffffff169082015260ff8b16917f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef0910160405180910390a2505050505050505050565b67ffffffffffffffff8216600090815260076020526040812081611d14608085615a46565b67ffffffffffffffff1681526020810191909152604001600020549392505050565b80516001600160a01b0316611d5e576040516342bcdf7f60e11b815260040160405180910390fd5b80516004805460208085018051604080880180516060808b0180516001600160a01b039b8c167fffffffffffffffff000000000000000000000000000000000000000000000000909a168a17600160a01b63ffffffff988916021777ffffffffffffffffffffffffffffffffffffffffffffffff167801000000000000000000000000000000000000000000000000948816949094026001600160e01b031693909317600160e01b93871693909302929092179098556080808b0180516005805473ffffffffffffffffffffffffffffffffffffffff1916918d169190911790558451988952955185169688019690965290518316918601919091525116938301939093529151909216908201527fa55bd56595c45f517e5967a3067f3dca684445a3080e7c04a4e0d5a40cda627d9060a00160405180910390a150565b6060865167ffffffffffffffff811115611eb857611eb8613f4a565b604051908082528060200260200182016040528015611efd57816020015b6040805180820190915260008082526020820152815260200190600190039081611ed65790505b50905060005b8751811015611faf57611f8a888281518110611f2157611f21614fb0565b6020026020010151888888888887818110611f3e57611f3e614fb0565b9050602002810190611f509190615a6d565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612f0692505050565b828281518110611f9c57611f9c614fb0565b6020908102919091010152600101611f03565b505b9695505050505050565b6000611fc6836132ab565b8015610d7d5750610d7d838361330f565b336001600160a01b0382160361202f5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016106f8565b6001805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b806040015160ff166000036120b8576000604051631b3fab5160e11b81526004016106f89190615ab4565b60208082015160ff8082166000908152600290935260408320600181015492939092839216900361212557606084015160018201805491151562010000027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff90921691909117905561217a565b6060840151600182015460ff620100009091041615159015151461217a576040517f87f6037c00000000000000000000000000000000000000000000000000000000815260ff841660048201526024016106f8565b60a0840151805161010010156121a6576001604051631b3fab5160e11b81526004016106f89190615ab4565b61220c848460030180548060200260200160405190810160405280929190818152602001828054801561220257602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116121e4575b50505050506133ca565b8460600151156123165761227a8484600201805480602002602001604051908101604052809291908181526020018280548015612202576020028201919060005260206000209081546001600160a01b031681526001909101906020018083116121e45750505050506133ca565b6080850151805161010010156122a6576002604051631b3fab5160e11b81526004016106f89190615ab4565b60408601516122b6906003615ace565b60ff168151116122dc576003604051631b3fab5160e11b81526004016106f89190615ab4565b805160018401805461ff00191661010060ff8416021790556123079060028601906020840190613ec3565b5061231485826001613433565b505b61232284826002613433565b80516123379060038501906020840190613ec3565b5060408581015160018401805460ff191660ff8316179055865180855560a088015192517fab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f547936123909389939260028a01929190615aea565b60405180910390a161190a846135a7565b815181516040517f2cbc26bb000000000000000000000000000000000000000000000000000000008152608083901b77ffffffffffffffff00000000000000000000000000000000166004820152901515907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632cbc26bb90602401602060405180830381865afa158015612444573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612468919061553b565b156124f45780156124b1576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff831660048201526024016106f8565b60405167ffffffffffffffff831681527faab522ed53d887e56ed53dd37398a01aeef6a58e0fa77c2173beb9512d8949339060200160405180910390a150505050565b60006124ff83611911565b600101805461250d906157de565b80601f0160208091040260200160405190810160405280929190818152602001828054612539906157de565b80156125865780601f1061255b57610100808354040283529160200191612586565b820191906000526020600020905b81548152906001019060200180831161256957829003601f168201915b505050602088015151929350505060008190036125ce576040517ebf199700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b856040015151811461260c576040517f57e0e08300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008167ffffffffffffffff81111561262757612627613f4a565b604051908082528060200260200182016040528015612650578160200160208202803683370190505b50905060005b828110156127a95760008860200151828151811061267657612676614fb0565b602002602001015190507f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681600001516040015167ffffffffffffffff161461270957805160409081015190517f38432a2200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016106f8565b8667ffffffffffffffff1681600001516020015167ffffffffffffffff1614612779578051602001516040517f6c95f1eb00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808a16600483015290911660248201526044016106f8565b6127838186613617565b83838151811061279557612795614fb0565b602090810291909101015250600101612656565b5060006127c086838a606001518b60800151613739565b905080600003612808576040517f7dd17a7e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff871660048201526024016106f8565b60005b83811015610cbc5760005a905060008a60200151838151811061283057612830614fb0565b60200260200101519050600061284e8a836000015160600151610d30565b9050600081600381111561286457612864614b1d565b14806128815750600381600381111561287f5761287f614b1d565b145b6128d9578151606001516040805167ffffffffffffffff808e16825290921660208301527f3b575419319662b2a6f5e2467d84521517a3382b908eb3d557bb3fdb0c50e23c91015b60405180910390a1505050612d19565b88156129a957600454600090600160a01b900463ffffffff166128fc87426155f0565b119050808061291c5750600382600381111561291a5761291a614b1d565b145b61295e576040517fa9cfc86200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8c1660048201526024016106f8565b8b858151811061297057612970614fb0565b60200260200101516000146129a3578b858151811061299157612991614fb0565b60200260200101518360800181815250505b50612a0a565b60008160038111156129bd576129bd614b1d565b14612a0a578151606001516040805167ffffffffffffffff808e16825290921660208301527f3ef2a99c550a751d4b0b261268f05a803dfb049ab43616a1ffb388f61fe6512091016128c9565b81516080015167ffffffffffffffff1615612af9576000816003811115612a3357612a33614b1d565b03612af95781516080015160208301516040517fe0e03cae0000000000000000000000000000000000000000000000000000000081526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169263e0e03cae92612aaa928f929190600401615b96565b6020604051808303816000875af1158015612ac9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612aed919061553b565b612af957505050612d19565b60008c604001518581518110612b1157612b11614fb0565b6020026020010151905080518360a001515114612b75578251606001516040517f1cfe6d8b00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff808e16600483015290911660248201526044016106f8565b612b898b8460000151606001516001613777565b600080612b96858461381f565b91509150612bad8d86600001516060015184613777565b8b15612c1d576003826003811115612bc757612bc7614b1d565b03612c1d576000846003811115612be057612be0614b1d565b14612c1d578451516040517f2b11b8d90000000000000000000000000000000000000000000000000000000081526106f891908390600401615bc3565b6002826003811115612c3157612c31614b1d565b14612c8b576003826003811115612c4a57612c4a614b1d565b14612c8b578451606001516040517f926c5a3e0000000000000000000000000000000000000000000000000000000081526106f8918f918590600401615bdc565b84600001516000015185600001516060015167ffffffffffffffff168e67ffffffffffffffff167f05665fe9ad095383d018353f4cbcba77e84db27dd215081bbf7cdf9ae6fbe48b8c8b81518110612ce557612ce5614fb0565b602002602001015186865a612cfa908e6155f0565b604051612d0a9493929190615c02565b60405180910390a45050505050505b60010161280b565b8251600090815b818110156111be576000600188868460208110612d4757612d47614fb0565b612d5491901a601b615a09565b898581518110612d6657612d66614fb0565b6020026020010151898681518110612d8057612d80614fb0565b602002602001015160405160008152602001604052604051612dbe949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015612de0573d6000803e3d6000fd5b505060408051601f1981015160ff808e166000908152600360209081528582206001600160a01b03851683528152858220858701909652855480841686529397509095509293928401916101009004166002811115612e4157612e41614b1d565b6002811115612e5257612e52614b1d565b9052509050600181602001516002811115612e6f57612e6f614b1d565b14612ea6576040517fca31867a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051600160ff9091161b851615612ee9576040517ff67bc7c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806000015160ff166001901b851794505050806001019050612d28565b60408051808201909152600080825260208201526000612f2987602001516138e9565b6040517fbbe4f6db0000000000000000000000000000000000000000000000000000000081526001600160a01b0380831660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063bbe4f6db90602401602060405180830381865afa158015612fae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fd29190615c39565b90506001600160a01b038116158061301a57506130186001600160a01b0382167faff2afbf00000000000000000000000000000000000000000000000000000000611fbb565b155b1561305c576040517fae9b4ce90000000000000000000000000000000000000000000000000000000081526001600160a01b03821660048201526024016106f8565b600454600090819061307e9089908690600160e01b900463ffffffff1661398f565b91509150600080600061314b6040518061010001604052808e81526020018c67ffffffffffffffff1681526020018d6001600160a01b031681526020018f606001518152602001896001600160a01b031681526020018f6000015181526020018f6040015181526020018b8152506040516024016130fc9190615c56565b60408051601f198184030181529190526020810180516001600160e01b03167f390775370000000000000000000000000000000000000000000000000000000017905287866113886084613abd565b9250925092508261318a57816040517fe1cd55090000000000000000000000000000000000000000000000000000000081526004016106f89190614938565b81516020146131d25781516040517f78ef80240000000000000000000000000000000000000000000000000000000081526020600482015260248101919091526044016106f8565b6000828060200190518101906131e89190615d23565b9050866001600160a01b03168c6001600160a01b03161461327d5760006132198d8a613214868a6155f0565b61398f565b5090508681108061323357508161323088836155f0565b14155b1561327b576040517fa966e21f0000000000000000000000000000000000000000000000000000000081526004810183905260248101889052604481018290526064016106f8565b505b604080518082019091526001600160a01b039098168852602088015250949550505050505095945050505050565b60006132d7827f01ffc9a70000000000000000000000000000000000000000000000000000000061330f565b8015610d805750613308827fffffffff0000000000000000000000000000000000000000000000000000000061330f565b1592915050565b6040517fffffffff0000000000000000000000000000000000000000000000000000000082166024820152600090819060440160408051601f19818403018152919052602080820180516001600160e01b03167f01ffc9a700000000000000000000000000000000000000000000000000000000178152825192935060009283928392909183918a617530fa92503d915060005190508280156133b3575060208210155b80156133bf5750600081115b979650505050505050565b60005b81518110156107245760ff8316600090815260036020526040812083519091908490849081106133ff576133ff614fb0565b6020908102919091018101516001600160a01b03168252810191909152604001600020805461ffff191690556001016133cd565b60005b8251811015610d2a57600083828151811061345357613453614fb0565b602002602001015190506000600281111561347057613470614b1d565b60ff80871660009081526003602090815260408083206001600160a01b038716845290915290205461010090041660028111156134af576134af614b1d565b146134d0576004604051631b3fab5160e11b81526004016106f89190615ab4565b6001600160a01b038116613510576040517fd6c62c9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052808360ff16815260200184600281111561353657613536614b1d565b905260ff80871660009081526003602090815260408083206001600160a01b0387168452825290912083518154931660ff198416811782559184015190929091839161ffff19161761010083600281111561359357613593614b1d565b021790555090505050806001019050613436565b60ff81166105815760ff80821660009081526002602052604090206001015462010000900416613603576040517f7a3b4c9400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6009805467ffffffffffffffff1916905550565b81516020808201516040928301519251600093849361365d937f2425b0b9f9054c76ff151b0a175b18f37a4a4e82013a72e9f15c9caa095ed21f93909291889101615d3c565b60408051601f1981840301815290829052805160209182012086518051888401516060808b0151908401516080808d015195015195976136a69794969395929491939101615d6f565b604051602081830303815290604052805190602001208560400151805190602001208660a001516040516020016136dd9190615e74565b60408051601f198184030181528282528051602091820120908301969096528101939093526060830191909152608082015260a081019190915260c0015b60405160208183030381529060405280519060200120905092915050565b600080613747858585613be3565b67ffffffffffffffff8716600090815260086020908152604080832093835292905220549150505b949350505050565b60006002613786608085615619565b67ffffffffffffffff1661379a9190615640565b905060006137a88585611cef565b9050816137b7600160046155f0565b901b1916818360038111156137ce576137ce614b1d565b67ffffffffffffffff871660009081526007602052604081209190921b929092179182916137fd608088615a46565b67ffffffffffffffff1681526020810191909152604001600020555050505050565b6040517fa80036b4000000000000000000000000000000000000000000000000000000008152600090606090309063a80036b4906138639087908790600401615ed4565b600060405180830381600087803b15801561387d57600080fd5b505af192505050801561388e575060015b6138cd573d8080156138bc576040519150601f19603f3d011682016040523d82523d6000602084013e6138c1565b606091505b506003925090506138e2565b50506040805160208101909152600081526002905b9250929050565b6000815160201461392857816040517f8d666f600000000000000000000000000000000000000000000000000000000081526004016106f89190614938565b60008280602001905181019061393e9190615d23565b90506001600160a01b03811180613956575061040081105b15610d8057826040517f8d666f600000000000000000000000000000000000000000000000000000000081526004016106f89190614938565b6000806000806000613a09886040516024016139ba91906001600160a01b0391909116815260200190565b60408051601f198184030181529190526020810180516001600160e01b03167f70a082310000000000000000000000000000000000000000000000000000000017905288886113886084613abd565b92509250925082613a4857816040517fe1cd55090000000000000000000000000000000000000000000000000000000081526004016106f89190614938565b6020825114613a905781516040517f78ef80240000000000000000000000000000000000000000000000000000000081526020600482015260248101919091526044016106f8565b81806020019051810190613aa49190615d23565b613aae82886155f0565b94509450505050935093915050565b6000606060008361ffff1667ffffffffffffffff811115613ae057613ae0613f4a565b6040519080825280601f01601f191660200182016040528015613b0a576020820181803683370190505b509150863b613b3d577f0c3b563c0000000000000000000000000000000000000000000000000000000060005260046000fd5b5a85811015613b70577fafa32a2c0000000000000000000000000000000000000000000000000000000060005260046000fd5b8590036040810481038710613ba9577f37c3be290000000000000000000000000000000000000000000000000000000060005260046000fd5b505a6000808a5160208c0160008c8cf193505a900390503d84811115613bcc5750835b808352806000602085013e50955095509592505050565b8251825160009190818303613c24576040517f11a6b26400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6101018211801590613c3857506101018111155b613c55576040516309bde33960e01b815260040160405180910390fd5b60001982820101610100811115613c7f576040516309bde33960e01b815260040160405180910390fd5b80600003613cac5786600081518110613c9a57613c9a614fb0565b60200260200101519350505050613e7b565b60008167ffffffffffffffff811115613cc757613cc7613f4a565b604051908082528060200260200182016040528015613cf0578160200160208202803683370190505b50905060008080805b85811015613e1a5760006001821b8b811603613d545788851015613d3d578c5160018601958e918110613d2e57613d2e614fb0565b60200260200101519050613d76565b8551600185019487918110613d2e57613d2e614fb0565b8b5160018401938d918110613d6b57613d6b614fb0565b602002602001015190505b600089861015613da6578d5160018701968f918110613d9757613d97614fb0565b60200260200101519050613dc8565b8651600186019588918110613dbd57613dbd614fb0565b602002602001015190505b82851115613de9576040516309bde33960e01b815260040160405180910390fd5b613df38282613e82565b878481518110613e0557613e05614fb0565b60209081029190910101525050600101613cf9565b506001850382148015613e2c57508683145b8015613e3757508581145b613e54576040516309bde33960e01b815260040160405180910390fd5b836001860381518110613e6957613e69614fb0565b60200260200101519750505050505050505b9392505050565b6000818310613e9a57613e958284613ea0565b610d7d565b610d7d83835b60408051600160208201529081018390526060810182905260009060800161371b565b828054828255906000526020600020908101928215613f25579160200282015b82811115613f25578251825473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b03909116178255602090920191600190910190613ee3565b50613f31929150613f35565b5090565b5b80821115613f315760008155600101613f36565b634e487b7160e01b600052604160045260246000fd5b6040516080810167ffffffffffffffff81118282101715613f8357613f83613f4a565b60405290565b60405160a0810167ffffffffffffffff81118282101715613f8357613f83613f4a565b60405160c0810167ffffffffffffffff81118282101715613f8357613f83613f4a565b6040805190810167ffffffffffffffff81118282101715613f8357613f83613f4a565b6040516060810167ffffffffffffffff81118282101715613f8357613f83613f4a565b604051601f8201601f1916810167ffffffffffffffff8111828210171561403e5761403e613f4a565b604052919050565b600067ffffffffffffffff82111561406057614060613f4a565b5060051b60200190565b6001600160a01b038116811461058157600080fd5b803567ffffffffffffffff8116811461409757600080fd5b919050565b801515811461058157600080fd5b80356140978161409c565b600067ffffffffffffffff8211156140cf576140cf613f4a565b50601f01601f191660200190565b600082601f8301126140ee57600080fd5b81356141016140fc826140b5565b614015565b81815284602083860101111561411657600080fd5b816020850160208301376000918101602001919091529392505050565b6000602080838503121561414657600080fd5b823567ffffffffffffffff8082111561415e57600080fd5b818501915085601f83011261417257600080fd5b81356141806140fc82614046565b81815260059190911b8301840190848101908883111561419f57600080fd5b8585015b83811015614245578035858111156141bb5760008081fd5b86016080818c03601f19018113156141d35760008081fd5b6141db613f60565b898301356141e88161406a565b815260406141f784820161407f565b8b83015260608085013561420a8161409c565b8383015292840135928984111561422357600091508182fd5b6142318f8d868801016140dd565b9083015250855250509186019186016141a3565b5098975050505050505050565b600060a0828403121561426457600080fd5b61426c613f89565b90508135815261427e6020830161407f565b602082015261428f6040830161407f565b60408201526142a06060830161407f565b60608201526142b16080830161407f565b608082015292915050565b80356140978161406a565b600082601f8301126142d857600080fd5b813560206142e86140fc83614046565b82815260059290921b8401810191818101908684111561430757600080fd5b8286015b84811015611faf57803567ffffffffffffffff8082111561432c5760008081fd5b9088019060a0828b03601f19018113156143465760008081fd5b61434e613f89565b87840135838111156143605760008081fd5b61436e8d8a838801016140dd565b825250604080850135848111156143855760008081fd5b6143938e8b838901016140dd565b8a84015250606080860135858111156143ac5760008081fd5b6143ba8f8c838a01016140dd565b838501525060809150818601358184015250828501359250838311156143e05760008081fd5b6143ee8d8a858801016140dd565b90820152865250505091830191830161430b565b6000610140828403121561441557600080fd5b61441d613fac565b90506144298383614252565b815260a082013567ffffffffffffffff8082111561444657600080fd5b614452858386016140dd565b602084015260c084013591508082111561446b57600080fd5b614477858386016140dd565b604084015261448860e085016142bc565b606084015261010084013560808401526101208401359150808211156144ad57600080fd5b506144ba848285016142c7565b60a08301525092915050565b600082601f8301126144d757600080fd5b813560206144e76140fc83614046565b82815260059290921b8401810191818101908684111561450657600080fd5b8286015b84811015611faf57803567ffffffffffffffff81111561452a5760008081fd5b6145388986838b0101614402565b84525091830191830161450a565b600082601f83011261455757600080fd5b813560206145676140fc83614046565b82815260059290921b8401810191818101908684111561458657600080fd5b8286015b84811015611faf57803567ffffffffffffffff808211156145aa57600080fd5b818901915089603f8301126145be57600080fd5b858201356145ce6140fc82614046565b81815260059190911b830160400190878101908c8311156145ee57600080fd5b604085015b838110156146275780358581111561460a57600080fd5b6146198f6040838a01016140dd565b8452509189019189016145f3565b5087525050509284019250830161458a565b600082601f83011261464a57600080fd5b8135602061465a6140fc83614046565b8083825260208201915060208460051b87010193508684111561467c57600080fd5b602086015b84811015611faf5780358352918301918301614681565b600082601f8301126146a957600080fd5b813560206146b96140fc83614046565b82815260059290921b840181019181810190868411156146d857600080fd5b8286015b84811015611faf57803567ffffffffffffffff808211156146fd5760008081fd5b9088019060a0828b03601f19018113156147175760008081fd5b61471f613f89565b61472a88850161407f565b8152604080850135848111156147405760008081fd5b61474e8e8b838901016144c6565b8a84015250606080860135858111156147675760008081fd5b6147758f8c838a0101614546565b83850152506080915081860135858111156147905760008081fd5b61479e8f8c838a0101614639565b91840191909152509190930135908301525083529183019183016146dc565b60008060408084860312156147d157600080fd5b833567ffffffffffffffff808211156147e957600080fd5b6147f587838801614698565b945060209150818601358181111561480c57600080fd5b8601601f8101881361481d57600080fd5b803561482b6140fc82614046565b81815260059190911b8201840190848101908a83111561484a57600080fd5b8584015b838110156148d6578035868111156148665760008081fd5b8501603f81018d136148785760008081fd5b878101356148886140fc82614046565b81815260059190911b82018a0190898101908f8311156148a85760008081fd5b928b01925b828410156148c65783358252928a0192908a01906148ad565b865250505091860191860161484e565b50809750505050505050509250929050565b60005b838110156149035781810151838201526020016148eb565b50506000910152565b600081518084526149248160208601602086016148e8565b601f01601f19169290920160200192915050565b602081526000610d7d602083018461490c565b8060608101831015610d8057600080fd5b60008083601f84011261496e57600080fd5b50813567ffffffffffffffff81111561498657600080fd5b6020830191508360208285010111156138e257600080fd5b60008083601f8401126149b057600080fd5b50813567ffffffffffffffff8111156149c857600080fd5b6020830191508360208260051b85010111156138e257600080fd5b60008060008060008060008060e0898b0312156149ff57600080fd5b614a098a8a61494b565b9750606089013567ffffffffffffffff80821115614a2657600080fd5b614a328c838d0161495c565b909950975060808b0135915080821115614a4b57600080fd5b614a578c838d0161499e565b909750955060a08b0135915080821115614a7057600080fd5b50614a7d8b828c0161499e565b999c989b50969995989497949560c00135949350505050565b600080600060808486031215614aab57600080fd5b614ab5858561494b565b9250606084013567ffffffffffffffff811115614ad157600080fd5b614add8682870161495c565b9497909650939450505050565b60008060408385031215614afd57600080fd5b614b068361407f565b9150614b146020840161407f565b90509250929050565b634e487b7160e01b600052602160045260246000fd5b60048110614b4357614b43614b1d565b9052565b60208101610d808284614b33565b600060208284031215614b6757600080fd5b813567ffffffffffffffff811115614b7e57600080fd5b820160a08185031215613e7b57600080fd5b803563ffffffff8116811461409757600080fd5b600060a08284031215614bb657600080fd5b614bbe613f89565b8235614bc98161406a565b8152614bd760208401614b90565b6020820152614be860408401614b90565b6040820152614bf960608401614b90565b60608201526080830135614c0c8161406a565b60808201529392505050565b600080600060408486031215614c2d57600080fd5b833567ffffffffffffffff80821115614c4557600080fd5b614c5187838801614402565b94506020860135915080821115614c6757600080fd5b50614add8682870161499e565b803560ff8116811461409757600080fd5b600060208284031215614c9757600080fd5b610d7d82614c74565b60008151808452602080850194506020840160005b83811015614cda5781516001600160a01b031687529582019590820190600101614cb5565b509495945050505050565b60208152600082518051602084015260ff602082015116604084015260ff604082015116606084015260608101511515608084015250602083015160c060a0840152614d3460e0840182614ca0565b90506040840151601f198483030160c0850152614d518282614ca0565b95945050505050565b60008060408385031215614d6d57600080fd5b614d768361407f565b946020939093013593505050565b600060208284031215614d9657600080fd5b610d7d8261407f565b602081526001600160a01b03825116602082015260208201511515604082015267ffffffffffffffff60408301511660608201526000606083015160808084015261376f60a084018261490c565b600060208284031215614dff57600080fd5b8135613e7b8161406a565b600082601f830112614e1b57600080fd5b81356020614e2b6140fc83614046565b8083825260208201915060208460051b870101935086841115614e4d57600080fd5b602086015b84811015611faf578035614e658161406a565b8352918301918301614e52565b60006020808385031215614e8557600080fd5b823567ffffffffffffffff80821115614e9d57600080fd5b818501915085601f830112614eb157600080fd5b8135614ebf6140fc82614046565b81815260059190911b83018401908481019088831115614ede57600080fd5b8585015b8381101561424557803585811115614ef957600080fd5b860160c0818c03601f19011215614f105760008081fd5b614f18613fac565b8882013581526040614f2b818401614c74565b8a8301526060614f3c818501614c74565b8284015260809150614f4f8285016140aa565b9083015260a08381013589811115614f675760008081fd5b614f758f8d83880101614e0a565b838501525060c0840135915088821115614f8f5760008081fd5b614f9d8e8c84870101614e0a565b9083015250845250918601918601614ee2565b634e487b7160e01b600052603260045260246000fd5b80356001600160e01b038116811461409757600080fd5b600082601f830112614fee57600080fd5b81356020614ffe6140fc83614046565b82815260069290921b8401810191818101908684111561501d57600080fd5b8286015b84811015611faf576040818903121561503a5760008081fd5b615042613fcf565b61504b8261407f565b8152615058858301614fc6565b81860152835291830191604001615021565b600082601f83011261507b57600080fd5b8135602061508b6140fc83614046565b82815260059290921b840181019181810190868411156150aa57600080fd5b8286015b84811015611faf57803567ffffffffffffffff808211156150cf5760008081fd5b9088019060a0828b03601f19018113156150e95760008081fd5b6150f1613f89565b6150fc88850161407f565b8152604080850135848111156151125760008081fd5b6151208e8b838901016140dd565b8a840152506060935061513484860161407f565b90820152608061514585820161407f565b938201939093529201359082015283529183019183016150ae565b600082601f83011261517157600080fd5b813560206151816140fc83614046565b82815260069290921b840181019181810190868411156151a057600080fd5b8286015b84811015611faf57604081890312156151bd5760008081fd5b6151c5613fcf565b8135815284820135858201528352918301916040016151a4565b600060208083850312156151f257600080fd5b823567ffffffffffffffff8082111561520a57600080fd5b908401906060828703121561521e57600080fd5b615226613ff2565b82358281111561523557600080fd5b8301604081890381131561524857600080fd5b615250613fcf565b82358581111561525f57600080fd5b8301601f81018b1361527057600080fd5b803561527e6140fc82614046565b81815260069190911b8201890190898101908d83111561529d57600080fd5b928a01925b828410156152ed5785848f0312156152ba5760008081fd5b6152c2613fcf565b84356152cd8161406a565b81526152da858d01614fc6565b818d0152825292850192908a01906152a2565b84525050508287013591508482111561530557600080fd5b6153118a838501614fdd565b8188015283525050828401358281111561532a57600080fd5b6153368882860161506a565b8583015250604083013593508184111561534f57600080fd5b61535b87858501615160565b60408201529695505050505050565b600082825180855260208086019550808260051b84010181860160005b848110156153fc57601f19868403018952815160a067ffffffffffffffff8083511686528683015182888801526153c08388018261490c565b60408581015184169089015260608086015190931692880192909252506080928301519290950191909152509783019790830190600101615387565b5090979650505050505050565b6000604080835261541d604084018661536a565b83810360208581019190915285518083528682019282019060005b8181101561545d57845180518452840151848401529383019391850191600101615438565b509098975050505050505050565b805160408084528151848201819052600092602091908201906060870190855b818110156154c257835180516001600160a01b031684528501516001600160e01b031685840152928401929185019160010161548b565b50508583015187820388850152805180835290840192506000918401905b8083101561551c578351805167ffffffffffffffff1683528501516001600160e01b0316858301529284019260019290920191908501906154e0565b50979650505050505050565b602081526000610d7d602083018461546b565b60006020828403121561554d57600080fd5b8151613e7b8161409c565b634e487b7160e01b600052601160045260246000fd5b67ffffffffffffffff81811683821601908082111561558f5761558f615558565b5092915050565b6040815260006155a9604083018561536a565b8281036020840152614d51818561546b565b6000602082840312156155cd57600080fd5b813567ffffffffffffffff8111156155e457600080fd5b61376f84828501614698565b81810381811115610d8057610d80615558565b634e487b7160e01b600052601260045260246000fd5b600067ffffffffffffffff8084168061563457615634615603565b92169190910692915050565b8082028115828204841417610d8057610d80615558565b805182526000602067ffffffffffffffff81840151168185015260408084015160a0604087015261568b60a087018261490c565b9050606085015186820360608801526156a4828261490c565b608087810151898303918a01919091528051808352908601935060009250908501905b8083101561551c57835180516001600160a01b03168352860151868301529285019260019290920191908401906156c7565b602081526000610d7d6020830184615657565b60808152600061571f6080830187615657565b61ffff9590951660208301525060408101929092526001600160a01b0316606090910152919050565b60008060006060848603121561575d57600080fd5b83516157688161409c565b602085015190935067ffffffffffffffff81111561578557600080fd5b8401601f8101861361579657600080fd5b80516157a46140fc826140b5565b8181528760208385010111156157b957600080fd5b6157ca8260208301602086016148e8565b809450505050604084015190509250925092565b600181811c908216806157f257607f821691505b60208210810361581257634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115610724576000816000526020600020601f850160051c810160208610156158415750805b601f850160051c820191505b818110156158605782815560010161584d565b505050505050565b815167ffffffffffffffff81111561588257615882613f4a565b6158968161589084546157de565b84615818565b602080601f8311600181146158cb57600084156158b35750858301515b600019600386901b1c1916600185901b178555615860565b600085815260208120601f198616915b828110156158fa578886015182559484019460019091019084016158db565b50858210156159185787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6000602080835283546001600160a01b038116602085015260ff8160a01c161515604085015267ffffffffffffffff8160a81c1660608501525060018085016080808601526000815461597a816157de565b8060a089015260c0600183166000811461599b57600181146159b7576159e7565b60ff19841660c08b015260c083151560051b8b010194506159e7565b85600052602060002060005b848110156159de5781548c82018501529088019089016159c3565b8b0160c0019550505b50929998505050505050505050565b80820180821115610d8057610d80615558565b60ff8181168382160190811115610d8057610d80615558565b8183823760009101908152919050565b828152606082602083013760800192915050565b600067ffffffffffffffff80841680615a6157615a61615603565b92169190910492915050565b6000808335601e19843603018112615a8457600080fd5b83018035915067ffffffffffffffff821115615a9f57600080fd5b6020019150368190038213156138e257600080fd5b6020810160058310615ac857615ac8614b1d565b91905290565b60ff818116838216029081169081811461558f5761558f615558565b600060a0820160ff881683526020878185015260a0604085015281875480845260c0860191508860005282600020935060005b81811015615b425784546001600160a01b031683526001948501949284019201615b1d565b50508481036060860152865180825290820192508187019060005b81811015615b825782516001600160a01b031685529383019391830191600101615b5d565b50505060ff85166080850152509050611fb1565b600067ffffffffffffffff808616835280851660208401525060606040830152614d51606083018461490c565b82815260406020820152600061376f604083018461490c565b67ffffffffffffffff8481168252831660208201526060810161376f6040830184614b33565b848152615c126020820185614b33565b608060408201526000615c28608083018561490c565b905082606083015295945050505050565b600060208284031215615c4b57600080fd5b8151613e7b8161406a565b6020815260008251610100806020850152615c7561012085018361490c565b91506020850151615c92604086018267ffffffffffffffff169052565b5060408501516001600160a01b038116606086015250606085015160808501526080850151615ccc60a08601826001600160a01b03169052565b5060a0850151601f19808685030160c0870152615ce9848361490c565b935060c08701519150808685030160e0870152615d06848361490c565b935060e0870151915080868503018387015250611fb1838261490c565b600060208284031215615d3557600080fd5b5051919050565b848152600067ffffffffffffffff808616602084015280851660408401525060806060830152611fb1608083018461490c565b86815260c060208201526000615d8860c083018861490c565b6001600160a01b039690961660408301525067ffffffffffffffff9384166060820152608081019290925290911660a09091015292915050565b600082825180855260208086019550808260051b84010181860160005b848110156153fc57601f19868403018952815160a08151818652615e058287018261490c565b9150508582015185820387870152615e1d828261490c565b91505060408083015186830382880152615e37838261490c565b92505050606080830151818701525060808083015192508582038187015250615e60818361490c565b9a86019a9450505090830190600101615ddf565b602081526000610d7d6020830184615dc2565b60008282518085526020808601955060208260051b8401016020860160005b848110156153fc57601f19868403018952615ec283835161490c565b98840198925090830190600101615ea6565b604081526000835180516040840152602081015167ffffffffffffffff80821660608601528060408401511660808601528060608401511660a08601528060808401511660c086015250505060208401516101408060e0850152615f3c61018085018361490c565b91506040860151603f198086850301610100870152615f5b848361490c565b935060608801519150615f7a6101208701836001600160a01b03169052565b60808801518387015260a0880151925080868503016101608701525050615fa18282615dc2565b9150508281036020840152614d518185615e8756fea164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CanOnlySelfCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"actual\",\"type\":\"bytes32\"}],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ExecutionError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"ForkedChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enumMultiOCR3Base.InvalidConfigErrorType\",\"name\":\"errorType\",\"type\":\"uint8\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"got\",\"type\":\"uint256\"}],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidEVMAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"name\":\"InvalidInterval\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"newLimit\",\"type\":\"uint256\"}],\"name\":\"InvalidManualExecutionGasLimit\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"tokenIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"oldLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenGasOverride\",\"type\":\"uint256\"}],\"name\":\"InvalidManualExecutionTokenGasOverride\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"messageDestChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidMessageDestChainSelector\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"newState\",\"type\":\"uint8\"}],\"name\":\"InvalidNewState\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRoot\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidStaticConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LeavesCannotBeEmpty\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"ManualExecutionGasAmountCountMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ManualExecutionGasLimitMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"ManualExecutionNotYetEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"errorReason\",\"type\":\"bytes\"}],\"name\":\"MessageValidationError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonUniqueSignatures\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"notPool\",\"type\":\"address\"}],\"name\":\"NotACompatiblePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OracleCannotBeZeroAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ReceiverError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountReleased\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePre\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePost\",\"type\":\"uint256\"}],\"name\":\"ReleaseOrMintBalanceMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"name\":\"RootAlreadyCommitted\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"RootNotCommitted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignatureVerificationDisabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignaturesOutOfRegistration\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"reportSourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"messageSourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainSelectorMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"StaleCommitReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"StaticConfigCannotBeChanged\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"TokenDataMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"TokenHandlingError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnexpectedTokenData\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"WrongMessageLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WrongNumberOfSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroChainSelectorNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"AlreadyAttempted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"indexed\":false,\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"}],\"name\":\"CommitReportAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"DynamicConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"messageHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"name\":\"ExecutionStateChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"RootRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"SkippedAlreadyExecutedMessage\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SkippedReportExecution\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"sourceConfig\",\"type\":\"tuple\"}],\"name\":\"SourceChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainSelectorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"}],\"name\":\"StaticConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigUpdates\",\"type\":\"tuple[]\"}],\"name\":\"applySourceChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"destTokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structClient.Any2EVMMessage\",\"name\":\"\",\"type\":\"tuple\"}],\"name\":\"ccipReceive\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"rawVs\",\"type\":\"bytes32\"}],\"name\":\"commit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"execute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"bytes[]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[]\"},{\"internalType\":\"uint32[]\",\"name\":\"tokenGasOverrides\",\"type\":\"uint32[]\"}],\"name\":\"executeSingleMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"getExecutionState\",\"outputs\":[{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLatestPriceSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"getMerkleRoot\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"getSourceChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"latestConfigDetails\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"n\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"}],\"internalType\":\"structMultiOCR3Base.ConfigInfo\",\"name\":\"configInfo\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfig\",\"name\":\"ocrConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage[]\",\"name\":\"messages\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[][]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[][]\"},{\"internalType\":\"bytes32[]\",\"name\":\"proofs\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"proofFlagBits\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.ExecutionReportSingleChain[]\",\"name\":\"reports\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"receiverExecutionGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint32[]\",\"name\":\"tokenGasOverrides\",\"type\":\"uint32[]\"}],\"internalType\":\"structOffRamp.GasLimitOverride[][]\",\"name\":\"gasLimitOverrides\",\"type\":\"tuple[][]\"}],\"name\":\"manuallyExecute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"setDynamicConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfigArgs[]\",\"name\":\"ocrConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"setOCR3Configs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x6101206040523480156200001257600080fd5b50604051620068603803806200686083398101604081905262000035916200085e565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf81620001fa565b5050466080525060208301516001600160a01b03161580620000ec575060408301516001600160a01b0316155b8062000103575060608301516001600160a01b0316155b1562000122576040516342bcdf7f60e11b815260040160405180910390fd5b82516001600160401b03166000036200014e5760405163c656089560e01b815260040160405180910390fd5b82516001600160401b0390811660a052602080850180516001600160a01b0390811660c05260408088018051831660e0526060808a01805185166101005283518b519098168852945184169587019590955251821690850152905116908201527f683eb52ee924eb817377cfa8f41f238f4bb7a877da5267869dfffbad85f564d89060800160405180910390a1620001e682620002a5565b620001f1816200036d565b50505062000be5565b336001600160a01b03821603620002545760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b0316620002ce576040516342bcdf7f60e11b815260040160405180910390fd5b805160048054602080850180516001600160a01b039586166001600160c01b03199094168417600160a01b63ffffffff928316021790945560408087018051600580546001600160a01b031916918916919091179055815194855291519094169183019190915251909216908201527fa1c15688cb2c24508e158f6942b9276c6f3028a85e1af8cf3fff0c3ff3d5fc8d9060600160405180910390a150565b60005b8151811015620006125760008282815181106200039157620003916200099b565b60200260200101519050600081602001519050806001600160401b0316600003620003cf5760405163c656089560e01b815260040160405180910390fd5b81516001600160a01b0316620003f8576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160401b03811660009081526006602052604081206001810180549192916200042490620009b1565b80601f01602080910402602001604051908101604052809291908181526020018280546200045290620009b1565b8015620004a35780601f106200047757610100808354040283529160200191620004a3565b820191906000526020600020905b8154815290600101906020018083116200048557829003601f168201915b5050505050905060008460600151905081516000036200054a578051600003620004e0576040516342bcdf7f60e11b815260040160405180910390fd5b60018301620004f0828262000a42565b508254600160a81b600160e81b031916600160a81b1783556040516001600160401b03851681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a162000585565b8080519060200120828051906020012014620005855760405163c39a620560e01b81526001600160401b038516600482015260240162000083565b604080860151845487516001600160a01b03166001600160a01b0319921515600160a01b02929092166001600160a81b031990911617178455516001600160401b038516907f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b90620005f990869062000b0e565b60405180910390a2505050505080600101905062000370565b5050565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b038111828210171562000651576200065162000616565b60405290565b604051601f8201601f191681016001600160401b038111828210171562000682576200068262000616565b604052919050565b80516001600160401b0381168114620006a257600080fd5b919050565b6001600160a01b0381168114620006bd57600080fd5b50565b6000601f83601f840112620006d457600080fd5b825160206001600160401b0380831115620006f357620006f362000616565b8260051b6200070483820162000657565b93845286810183019383810190898611156200071f57600080fd5b84890192505b8583101562000851578251848111156200073f5760008081fd5b89016080601f19828d038101821315620007595760008081fd5b620007636200062c565b888401516200077281620006a7565b81526040620007838582016200068a565b8a83015260608086015180151581146200079d5760008081fd5b83830152938501519389851115620007b55760008081fd5b84860195508f603f870112620007cd57600094508485fd5b8a860151945089851115620007e657620007e662000616565b620007f78b858f8801160162000657565b93508484528f828688010111156200080f5760008081fd5b60005b858110156200082f578681018301518582018d01528b0162000812565b5060009484018b01949094525091820152835250918401919084019062000725565b9998505050505050505050565b60008060008385036101008112156200087657600080fd5b60808112156200088557600080fd5b6200088f6200062c565b6200089a866200068a565b81526020860151620008ac81620006a7565b60208201526040860151620008c181620006a7565b60408201526060860151620008d681620006a7565b606082810191909152909450607f1982011215620008f357600080fd5b50604051606081016001600160401b0380821183831017156200091a576200091a62000616565b81604052608087015191506200093082620006a7565b90825260a08601519063ffffffff821682146200094c57600080fd5b81602084015260c087015191506200096482620006a7565b6040830182905260e0870151929450808311156200098157600080fd5b50506200099186828701620006c0565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b600181811c90821680620009c657607f821691505b602082108103620009e757634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111562000a3d576000816000526020600020601f850160051c8101602086101562000a185750805b601f850160051c820191505b8181101562000a395782815560010162000a24565b5050505b505050565b81516001600160401b0381111562000a5e5762000a5e62000616565b62000a768162000a6f8454620009b1565b84620009ed565b602080601f83116001811462000aae576000841562000a955750858301515b600019600386901b1c1916600185901b17855562000a39565b600085815260208120601f198616915b8281101562000adf5788860151825594840194600190910190840162000abe565b508582101562000afe5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b602080825282546001600160a01b0381168383015260a081901c60ff161515604084015260a81c6001600160401b0316606083015260808083015260018084018054600093929190849062000b6381620009b1565b8060a089015260c0600183166000811462000b87576001811462000ba45762000bd6565b60ff19841660c08b015260c083151560051b8b0101945062000bd6565b85600052602060002060005b8481101562000bcd5781548c820185015290880190890162000bb0565b8b0160c0019550505b50929998505050505050505050565b60805160a05160c05160e05161010051615c0562000c5b6000396000818161022c015261292c0152600081816101fd0152612bfe0152600081816101ce01528181610552015281816106ff015261237001526000818161019f01526125af015260008181611d980152611dcb0152615c056000f3fe608060405234801561001057600080fd5b50600436106101515760003560e01c806379ba5097116100cd578063d434969111610081578063e9d68a8e11610066578063e9d68a8e146104bc578063f2fde38b146104dc578063f716f99f146104ef57600080fd5b8063d434969114610496578063e62653f5146104a957600080fd5b80638da5cb5b116100b25780638da5cb5b14610417578063c673e58414610432578063ccd37ba31461045257600080fd5b806379ba50971461040157806385572ffb1461040957600080fd5b8063311cd513116101245780635e36480c116101095780635e36480c1461033c5780636f9e320f1461035c5780637437ff9f1461036f57600080fd5b8063311cd5131461030e5780633f4b04aa1461032157600080fd5b806304666f9c1461015657806306285c691461016b578063181f5a77146102b25780632d04ab76146102fb575b600080fd5b610169610164366004613bc5565b610502565b005b61025c60408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160401b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316815250905090565b6040516102a9919081516001600160401b031681526020808301516001600160a01b0390811691830191909152604080840151821690830152606092830151169181019190915260800190565b60405180910390f35b6102ee6040518060400160405280601181526020017f4f666652616d7020312e362e302d64657600000000000000000000000000000081525081565b6040516102a99190613d33565b610169610309366004613de3565b610516565b61016961031c366004613e95565b6109c5565b6009546040516001600160401b0390911681526020016102a9565b61034f61034a366004613ee8565b610a2e565b6040516102a99190613f45565b61016961036a366004613f70565b610a83565b6103cb604080516060810182526000808252602082018190529181019190915250604080516060810182526004546001600160a01b038082168352600160a01b90910463ffffffff166020830152600554169181019190915290565b6040805182516001600160a01b03908116825260208085015163ffffffff169083015292820151909216908201526060016102a9565b610169610a94565b610169610151366004613fc4565b6000546040516001600160a01b0390911681526020016102a9565b61044561044036600461400f565b610b45565b6040516102a9919061406f565b6104886104603660046140e4565b6001600160401b03919091166000908152600860209081526040808320938352929052205490565b6040519081526020016102a9565b6101696104a4366004614380565b610ca3565b6101696104b7366004614708565b610f83565b6104cf6104ca36600461494f565b61122a565b6040516102a9919061496a565b6101696104ea3660046149b7565b611336565b6101696104fd366004614a3c565b611347565b61050a611389565b610513816113e5565b50565b600061052487890189614d91565b602081015151909150156105b6576020810151604080830151905162ccd5af60e81b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169263ccd5af009261058592600401614fb9565b60006040518083038186803b15801561059d57600080fd5b505afa1580156105b1573d6000803e3d6000fd5b505050505b805151511515806105cc57508051602001515115155b156106985760095460208a0135906001600160401b0380831691161015610670576009805467ffffffffffffffff19166001600160401b038316179055600480548351604051633937306f60e01b81526001600160a01b0390921692633937306f926106399291016150ed565b600060405180830381600087803b15801561065357600080fd5b505af1158015610667573d6000803e3d6000fd5b50505050610696565b81602001515160000361069657604051632261116760e01b815260040160405180910390fd5b505b60005b816020015151811015610906576000826020015182815181106106c0576106c061501b565b60209081029190910101518051604051632cbc26bb60e01b815267ffffffffffffffff60801b608083901b166004820152919250906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632cbc26bb90602401602060405180830381865afa158015610746573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061076a9190615100565b1561079857604051637edeb53960e11b81526001600160401b03821660048201526024015b60405180910390fd5b60006107a38261168b565b604084015181549192506001600160401b03908116600160a81b909204161415806107e7575082606001516001600160401b031683604001516001600160401b0316115b1561082c57825160408085015160608601519151636af0786b60e11b81526001600160401b03938416600482015290831660248201529116604482015260640161078f565b60808301518061084f5760405163504570e360e01b815260040160405180910390fd5b83516001600160401b03166000908152600860209081526040808320848452909152902054156108a75783516040516332cf0cbf60e01b81526001600160401b0390911660048201526024810182905260440161078f565b60608401516108b7906001615133565b825467ffffffffffffffff60a81b1916600160a81b6001600160401b0392831602179092559251166000908152600860209081526040808320948352939052919091204290555060010161069b565b50602081015181516040517f35c02761bcd3ef995c6a601a1981f4ed3934dcbe5041e24e286c89f5531d17e49261093e92909161515a565b60405180910390a16109ba60008a8a8a8a8a8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808e0282810182019093528d82529093508d92508c9182918501908490808284376000920191909152508b92506116d7915050565b505050505050505050565b610a056109d48284018461517f565b60408051600080825260208201909252906109ff565b60608152602001906001900390816109ea5790505b506119d0565b604080516000808252602082019092529050610a286001858585858660006116d7565b50505050565b6000610a3c600160046151b3565b6002610a496080856151dc565b6001600160401b0316610a5c9190615202565b610a668585611a92565b901c166003811115610a7a57610a7a613f1b565b90505b92915050565b610a8b611389565b61051381611ad7565b6001546001600160a01b03163314610aee5760405162461bcd60e51b815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e657200000000000000000000604482015260640161078f565b60008054336001600160a01b0319808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610b886040805160e081019091526000606082018181526080830182905260a0830182905260c08301919091528190815260200160608152602001606081525090565b60ff808316600090815260026020818152604092839020835160e081018552815460608201908152600183015480881660808401526101008104881660a0840152620100009004909616151560c082015294855291820180548451818402810184019095528085529293858301939092830182828015610c3157602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610c13575b5050505050815260200160038201805480602002602001604051908101604052809291908181526020018280548015610c9357602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610c75575b5050505050815250509050919050565b333014610cc3576040516306e34e6560e31b815260040160405180910390fd5b6040805160008082526020820190925281610d00565b6040805180820190915260008082526020820152815260200190600190039081610cd95790505b5060a08701515190915015610d3657610d338660a001518760200151886060015189600001516020015189898989611bb6565b90505b6040805160a081018252875151815287516020908101516001600160401b031681830152808901518351600094840192610d71929101613d33565b60408051601f19818403018152918152908252898101516020830152018390526005549091506001600160a01b03168015610e4c576040516308d450a160e01b81526001600160a01b038216906308d450a190610dd29085906004016152ba565b600060405180830381600087803b158015610dec57600080fd5b505af1925050508015610dfd575060015b610e4c573d808015610e2b576040519150601f19603f3d011682016040523d82523d6000602084013e610e30565b606091505b50806040516309c2532560e01b815260040161078f9190613d33565b604088015151158015610e6157506080880151155b80610e78575060608801516001600160a01b03163b155b80610e9f57506060880151610e9d906001600160a01b03166385572ffb60e01b611d79565b155b15610eac57505050610f7c565b87516020908101516001600160401b03166000908152600690915260408082205460808b015160608c01519251633cf9798360e01b815284936001600160a01b0390931692633cf9798392610f0a92899261138892916004016152cd565b6000604051808303816000875af1158015610f29573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610f519190810190615309565b509150915081610f7657806040516302a35ba360e21b815260040161078f9190613d33565b50505050505b5050505050565b610f8b611d95565b815181518114610fae576040516320f8fd5960e21b815260040160405180910390fd5b60005b8181101561121a576000848281518110610fcd57610fcd61501b565b60200260200101519050600081602001515190506000858481518110610ff557610ff561501b565b6020026020010151905080518214611020576040516320f8fd5960e21b815260040160405180910390fd5b60005b8281101561120b57600082828151811061103f5761103f61501b565b60200260200101516000015190506000856020015183815181106110655761106561501b565b60200260200101519050816000146110b95780608001518210156110b9578551815151604051633a98d46360e11b81526001600160401b03909216600483015260248201526044810183905260640161078f565b8383815181106110cb576110cb61501b565b602002602001015160200151518160a00151511461111857805180516060909101516040516370a193fd60e01b815260048101929092526001600160401b0316602482015260440161078f565b60005b8160a00151518110156111fd57600085858151811061113c5761113c61501b565b60200260200101516020015182815181106111595761115961501b565b602002602001015163ffffffff169050806000146111f45760008360a0015183815181106111895761118961501b565b6020026020010151608001518060200190518101906111a8919061539e565b90508063ffffffff168210156111f2578351516040516348e617b360e01b815260048101919091526024810184905263ffffffff821660448201526064810183905260840161078f565b505b5060010161111b565b505050806001019050611023565b50505050806001019050610fb1565b5061122583836119d0565b505050565b60408051608080820183526000808352602080840182905283850182905260608085018190526001600160401b03878116845260068352928690208651948501875280546001600160a01b0381168652600160a01b810460ff16151593860193909352600160a81b9092049092169483019490945260018401805493949293918401916112b6906153bb565b80601f01602080910402602001604051908101604052809291908181526020018280546112e2906153bb565b8015610c935780601f1061130457610100808354040283529160200191610c93565b820191906000526020600020905b81548152906001019060200180831161131257505050919092525091949350505050565b61133e611389565b61051381611dfd565b61134f611389565b60005b81518110156113855761137d8282815181106113705761137061501b565b6020026020010151611ea6565b600101611352565b5050565b6000546001600160a01b031633146113e35760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640161078f565b565b60005b81518110156113855760008282815181106114055761140561501b565b60200260200101519050600081602001519050806001600160401b03166000036114425760405163c656089560e01b815260040160405180910390fd5b81516001600160a01b031661146a576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160401b0381166000908152600660205260408120600181018054919291611494906153bb565b80601f01602080910402602001604051908101604052809291908181526020018280546114c0906153bb565b801561150d5780601f106114e25761010080835404028352916020019161150d565b820191906000526020600020905b8154815290600101906020018083116114f057829003601f168201915b5050505050905060008460600151905081516000036115b0578051600003611548576040516342bcdf7f60e11b815260040160405180910390fd5b600183016115568282615445565b50825467ffffffffffffffff60a81b1916600160a81b1783556040516001600160401b03851681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a16115e9565b80805190602001208280519060200120146115e95760405163c39a620560e01b81526001600160401b038516600482015260240161078f565b604080860151845487516001600160a01b03166001600160a01b0319921515600160a01b02929092167fffffffffffffffffffffff00000000000000000000000000000000000000000090911617178455516001600160401b038516907f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b90611673908690615504565b60405180910390a250505050508060010190506113e8565b6001600160401b03811660009081526006602052604081208054600160a01b900460ff16610a7d5760405163ed053c5960e01b81526001600160401b038416600482015260240161078f565b60ff878116600090815260026020908152604080832081516080810183528154815260019091015480861693820193909352610100830485169181019190915262010000909104909216151560608301528735906117368760a46155d1565b905082606001511561177e57845161174f906020615202565b865161175c906020615202565b6117679060a06155d1565b61177191906155d1565b61177b90826155d1565b90505b3681146117a757604051638e1192e160e01b81526004810182905236602482015260440161078f565b50815181146117d65781516040516324f7d61360e21b815260048101919091526024810182905260440161078f565b6117de611d95565b60ff808a166000908152600360209081526040808320338452825280832081518083019092528054808616835293949193909284019161010090910416600281111561182c5761182c613f1b565b600281111561183d5761183d613f1b565b905250905060028160200151600281111561185a5761185a613f1b565b1480156118ae5750600260008b60ff1660ff168152602001908152602001600020600301816000015160ff16815481106118965761189661501b565b6000918252602090912001546001600160a01b031633145b6118cb57604051631b41e11d60e31b815260040160405180910390fd5b5081606001511561197b5760208201516118e69060016155e4565b60ff16855114611909576040516371253a2560e01b815260040160405180910390fd5b835185511461192b5760405163a75d88af60e01b815260040160405180910390fd5b6000878760405161193d9291906155fd565b604051908190038120611954918b9060200161560d565b6040516020818303038152906040528051906020012090506119798a82888888612185565b505b6040805182815260208a8101356001600160401b03169082015260ff8b16917f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef0910160405180910390a2505050505050505050565b81516000036119f15760405162bf199760e01b815260040160405180910390fd5b80516040805160008082526020820190925291159181611a34565b604080518082019091526000815260606020820152815260200190600190039081611a0c5790505b50905060005b8451811015610f7c57611a8a858281518110611a5857611a5861501b565b602002602001015184611a8457858381518110611a7757611a7761501b565b6020026020010151612342565b83612342565b600101611a3a565b6001600160401b038216600090815260076020526040812081611ab6608085615621565b6001600160401b031681526020810191909152604001600020549392505050565b80516001600160a01b0316611aff576040516342bcdf7f60e11b815260040160405180910390fd5b805160048054602080850180516001600160a01b039586167fffffffffffffffff0000000000000000000000000000000000000000000000009094168417600160a01b63ffffffff928316021790945560408087018051600580546001600160a01b031916918916919091179055815194855291519094169183019190915251909216908201527fa1c15688cb2c24508e158f6942b9276c6f3028a85e1af8cf3fff0c3ff3d5fc8d9060600160405180910390a150565b606088516001600160401b03811115611bd157611bd16139e5565b604051908082528060200260200182016040528015611c1657816020015b6040805180820190915260008082526020820152815260200190600190039081611bef5790505b509050811560005b8a51811015611d6b5781611cc857848482818110611c3e57611c3e61501b565b9050602002016020810190611c539190615647565b63ffffffff1615611cc857848482818110611c7057611c7061501b565b9050602002016020810190611c859190615647565b6040805163ffffffff9092166020830152016040516020818303038152906040528b8281518110611cb857611cb861501b565b6020026020010151608001819052505b611d468b8281518110611cdd57611cdd61501b565b60200260200101518b8b8b8b8b87818110611cfa57611cfa61501b565b9050602002810190611d0c9190615664565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612bb692505050565b838281518110611d5857611d5861501b565b6020908102919091010152600101611c1e565b505098975050505050505050565b6000611d8483612eb4565b8015610a7a5750610a7a8383612eff565b467f0000000000000000000000000000000000000000000000000000000000000000146113e357604051630f01ce8560e01b81527f0000000000000000000000000000000000000000000000000000000000000000600482015246602482015260440161078f565b336001600160a01b03821603611e555760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161078f565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b806040015160ff16600003611ed1576000604051631b3fab5160e11b815260040161078f91906156aa565b60208082015160ff80821660009081526002909352604083206001810154929390928392169003611f22576060840151600182018054911515620100000262ff000019909216919091179055611f5e565b6060840151600182015460ff6201000090910416151590151514611f5e576040516321fd80df60e21b815260ff8416600482015260240161078f565b60a084015180516101001015611f8a576001604051631b3fab5160e11b815260040161078f91906156aa565b611ff08484600301805480602002602001604051908101604052809291908181526020018280548015611fe657602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611fc8575b5050505050612fa1565b8460600151156120fa5761205e8484600201805480602002602001604051908101604052809291908181526020018280548015611fe6576020028201919060005260206000209081546001600160a01b03168152600190910190602001808311611fc8575050505050612fa1565b60808501518051610100101561208a576002604051631b3fab5160e11b815260040161078f91906156aa565b604086015161209a9060036156c4565b60ff168151116120c0576003604051631b3fab5160e11b815260040161078f91906156aa565b805160018401805461ff00191661010060ff8416021790556120eb906002860190602084019061396b565b506120f88582600161300a565b505b6121068482600261300a565b805161211b906003850190602084019061396b565b5060408581015160018401805460ff191660ff8316179055865180855560a088015192517fab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f547936121749389939260028a019291906156e0565b60405180910390a1610f7c84613165565b8251600090815b818110156123385760006001888684602081106121ab576121ab61501b565b6121b891901a601b6155e4565b8985815181106121ca576121ca61501b565b60200260200101518986815181106121e4576121e461501b565b602002602001015160405160008152602001604052604051612222949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015612244573d6000803e3d6000fd5b505060408051601f1981015160ff808e166000908152600360209081528582206001600160a01b038516835281528582208587019096528554808416865293975090955092939284019161010090041660028111156122a5576122a5613f1b565b60028111156122b6576122b6613f1b565b90525090506001816020015160028111156122d3576122d3613f1b565b146122f157604051636518c33d60e11b815260040160405180910390fd5b8051600160ff9091161b85161561231b57604051633d9ef1f160e21b815260040160405180910390fd5b806000015160ff166001901b85179450505080600101905061218c565b5050505050505050565b81518151604051632cbc26bb60e01b8152608083901b67ffffffffffffffff60801b166004820152901515907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632cbc26bb90602401602060405180830381865afa1580156123bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123e39190615100565b1561245457801561241257604051637edeb53960e11b81526001600160401b038316600482015260240161078f565b6040516001600160401b03831681527faab522ed53d887e56ed53dd37398a01aeef6a58e0fa77c2173beb9512d8949339060200160405180910390a150505050565b600061245f8361168b565b600101805461246d906153bb565b80601f0160208091040260200160405190810160405280929190818152602001828054612499906153bb565b80156124e65780601f106124bb576101008083540402835291602001916124e6565b820191906000526020600020905b8154815290600101906020018083116124c957829003601f168201915b505050602088015151929350505060008190036125155760405162bf199760e01b815260040160405180910390fd5b856040015151811461253a576040516357e0e08360e01b815260040160405180910390fd5b6000816001600160401b03811115612554576125546139e5565b60405190808252806020026020018201604052801561257d578160200160208202803683370190505b50905060005b8281101561269e576000886020015182815181106125a3576125a361501b565b602002602001015190507f00000000000000000000000000000000000000000000000000000000000000006001600160401b03168160000151604001516001600160401b03161461261a5780516040908101519051631c21951160e11b81526001600160401b03909116600482015260240161078f565b866001600160401b03168160000151602001516001600160401b03161461266e57805160200151604051636c95f1eb60e01b81526001600160401b03808a166004830152909116602482015260440161078f565b61267881866131bc565b83838151811061268a5761268a61501b565b602090810291909101015250600101612583565b5060006126b586838a606001518b608001516132de565b9050806000036126e357604051633ee8bd3f60e11b81526001600160401b038716600482015260240161078f565b60005b838110156109ba5760005a905060008a60200151838151811061270b5761270b61501b565b6020026020010151905060006127298a836000015160600151610a2e565b9050600081600381111561273f5761273f613f1b565b148061275c5750600381600381111561275a5761275a613f1b565b145b6127b257815160600151604080516001600160401b03808e16825290921660208301527f3b575419319662b2a6f5e2467d84521517a3382b908eb3d557bb3fdb0c50e23c910160405180910390a1505050612bae565b60608915612891578b85815181106127cc576127cc61501b565b6020908102919091018101510151600454909150600090600160a01b900463ffffffff166127fa88426151b3565b119050808061281a5750600383600381111561281857612818613f1b565b145b612842576040516354e7e43160e11b81526001600160401b038d16600482015260240161078f565b8c86815181106128545761285461501b565b60200260200101516000015160001461288b578c86815181106128795761287961501b565b60209081029190910101515160808501525b506128fd565b60008260038111156128a5576128a5613f1b565b146128fd57825160600151604080516001600160401b03808f16825290921660208301527f3ef2a99c550a751d4b0b261268f05a803dfb049ab43616a1ffb388f61fe65120910160405180910390a150505050612bae565b8251608001516001600160401b0316156129d657600082600381111561292557612925613f1b565b036129d6577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e0e03cae8c85600001516080015186602001516040518463ffffffff1660e01b815260040161298693929190615792565b6020604051808303816000875af11580156129a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129c99190615100565b6129d65750505050612bae565b60008d6040015186815181106129ee576129ee61501b565b6020026020010151905080518460a001515114612a3857835160600151604051631cfe6d8b60e01b81526001600160401b03808f166004830152909116602482015260440161078f565b612a4c8c856000015160600151600161331b565b600080612a5a8684866133c0565b91509150612a718e8760000151606001518461331b565b8c15612ac8576003826003811115612a8b57612a8b613f1b565b03612ac8576000856003811115612aa457612aa4613f1b565b14612ac857855151604051632b11b8d960e01b815261078f919083906004016157be565b6002826003811115612adc57612adc613f1b565b14612b21576003826003811115612af557612af5613f1b565b14612b21578d866000015160600151836040516349362d1f60e11b815260040161078f939291906157d7565b8560000151600001518660000151606001516001600160401b03168f6001600160401b03167f05665fe9ad095383d018353f4cbcba77e84db27dd215081bbf7cdf9ae6fbe48b8d8c81518110612b7957612b7961501b565b602002602001015186865a612b8e908f6151b3565b604051612b9e94939291906157fc565b60405180910390a4505050505050505b6001016126e6565b60408051808201909152600080825260208201526000612bd98760200151613474565b60405163bbe4f6db60e01b81526001600160a01b0380831660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063bbe4f6db90602401602060405180830381865afa158015612c45573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c699190615833565b90506001600160a01b0381161580612c985750612c966001600160a01b03821663aff2afbf60e01b611d79565b155b15612cc15760405163ae9b4ce960e01b81526001600160a01b038216600482015260240161078f565b600080612cec88858c60800151806020019051810190612ce1919061539e565b63ffffffff166134e8565b915091506000806000612d9f6040518061010001604052808e81526020018c6001600160401b031681526020018d6001600160a01b031681526020018f606001518152602001896001600160a01b031681526020018f6000015181526020018f6040015181526020018b815250604051602401612d699190615850565b60408051601f198184030181529190526020810180516001600160e01b0316633907753760e01b179052878661138860846135cb565b92509250925082612dc5578160405163e1cd550960e01b815260040161078f9190613d33565b8151602014612df4578151604051631e3be00960e21b815260206004820152602481019190915260440161078f565b600082806020019051810190612e0a919061591c565b9050866001600160a01b03168c6001600160a01b031614612e86576000612e3b8d8a612e36868a6151b3565b6134e8565b50905086811080612e55575081612e5288836151b3565b14155b15612e845760405163a966e21f60e01b815260048101839052602481018890526044810182905260640161078f565b505b604080518082019091526001600160a01b039098168852602088015250949550505050505095945050505050565b6000612ec7826301ffc9a760e01b612eff565b8015610a7d5750612ef8827fffffffff00000000000000000000000000000000000000000000000000000000612eff565b1592915050565b6040517fffffffff0000000000000000000000000000000000000000000000000000000082166024820152600090819060440160408051601f19818403018152919052602080820180516001600160e01b03166301ffc9a760e01b178152825192935060009283928392909183918a617530fa92503d91506000519050828015612f8a575060208210155b8015612f965750600081115b979650505050505050565b60005b81518110156112255760ff831660009081526003602052604081208351909190849084908110612fd657612fd661501b565b6020908102919091018101516001600160a01b03168252810191909152604001600020805461ffff19169055600101612fa4565b60005b8251811015610a2857600083828151811061302a5761302a61501b565b602002602001015190506000600281111561304757613047613f1b565b60ff80871660009081526003602090815260408083206001600160a01b0387168452909152902054610100900416600281111561308657613086613f1b565b146130a7576004604051631b3fab5160e11b815260040161078f91906156aa565b6001600160a01b0381166130ce5760405163d6c62c9b60e01b815260040160405180910390fd5b60405180604001604052808360ff1681526020018460028111156130f4576130f4613f1b565b905260ff80871660009081526003602090815260408083206001600160a01b0387168452825290912083518154931660ff198416811782559184015190929091839161ffff19161761010083600281111561315157613151613f1b565b02179055509050505080600101905061300d565b60ff81166105135760ff808216600090815260026020526040902060010154620100009004166131a857604051631e8ed32560e21b815260040160405180910390fd5b6009805467ffffffffffffffff1916905550565b815160208082015160409283015192516000938493613202937f2425b0b9f9054c76ff151b0a175b18f37a4a4e82013a72e9f15c9caa095ed21f93909291889101615935565b60408051601f1981840301815290829052805160209182012086518051888401516060808b0151908401516080808d0151950151959761324b9794969395929491939101615967565b604051602081830303815290604052805190602001208560400151805190602001208660a001516040516020016132829190615a6b565b60408051601f198184030181528282528051602091820120908301969096528101939093526060830191909152608082015260a081019190915260c0015b60405160208183030381529060405280519060200120905092915050565b6000806132ec8585856136a5565b6001600160401b038716600090815260086020908152604080832093835292905220549150505b949350505050565b6000600261332a6080856151dc565b6001600160401b031661333d9190615202565b9050600061334b8585611a92565b90508161335a600160046151b3565b901b19168183600381111561337157613371613f1b565b6001600160401b03871660009081526007602052604081209190921b9290921791829161339f608088615621565b6001600160401b031681526020810191909152604001600020555050505050565b60405163d434969160e01b8152600090606090309063d4349691906133ed90889088908890600401615b02565b600060405180830381600087803b15801561340757600080fd5b505af1925050508015613418575060015b613457573d808015613446576040519150601f19603f3d011682016040523d82523d6000602084013e61344b565b606091505b5060039250905061346c565b50506040805160208101909152600081526002905b935093915050565b6000815160201461349a578160405163046b337b60e51b815260040161078f9190613d33565b6000828060200190518101906134b0919061591c565b90506001600160a01b038111806134c8575061040081105b15610a7d578260405163046b337b60e51b815260040161078f9190613d33565b60008060008060006135498860405160240161351391906001600160a01b0391909116815260200190565b60408051601f198184030181529190526020810180516001600160e01b03166370a0823160e01b179052888861138860846135cb565b9250925092508261356f578160405163e1cd550960e01b815260040161078f9190613d33565b602082511461359e578151604051631e3be00960e21b815260206004820152602481019190915260440161078f565b818060200190518101906135b2919061591c565b6135bc82886151b3565b94509450505050935093915050565b6000606060008361ffff166001600160401b038111156135ed576135ed6139e5565b6040519080825280601f01601f191660200182016040528015613617576020820181803683370190505b509150863b6136315763030ed58f60e21b60005260046000fd5b5a8581101561364b57632be8ca8b60e21b60005260046000fd5b859003604081048103871061366b576337c3be2960e01b60005260046000fd5b505a6000808a5160208c0160008c8cf193505a900390503d8481111561368e5750835b808352806000602085013e50955095509592505050565b82518251600091908183036136cd57604051630469ac9960e21b815260040160405180910390fd5b61010182118015906136e157506101018111155b6136fe576040516309bde33960e01b815260040160405180910390fd5b60001982820101610100811115613728576040516309bde33960e01b815260040160405180910390fd5b8060000361375557866000815181106137435761374361501b565b60200260200101519350505050613923565b6000816001600160401b0381111561376f5761376f6139e5565b604051908082528060200260200182016040528015613798578160200160208202803683370190505b50905060008080805b858110156138c25760006001821b8b8116036137fc57888510156137e5578c5160018601958e9181106137d6576137d661501b565b6020026020010151905061381e565b85516001850194879181106137d6576137d661501b565b8b5160018401938d9181106138135761381361501b565b602002602001015190505b60008986101561384e578d5160018701968f91811061383f5761383f61501b565b60200260200101519050613870565b86516001860195889181106138655761386561501b565b602002602001015190505b82851115613891576040516309bde33960e01b815260040160405180910390fd5b61389b828261392a565b8784815181106138ad576138ad61501b565b602090810291909101015250506001016137a1565b5060018503821480156138d457508683145b80156138df57508581145b6138fc576040516309bde33960e01b815260040160405180910390fd5b8360018603815181106139115761391161501b565b60200260200101519750505050505050505b9392505050565b60008183106139425761393d8284613948565b610a7a565b610a7a83835b6040805160016020820152908101839052606081018290526000906080016132c0565b8280548282559060005260206000209081019282156139c0579160200282015b828111156139c057825182546001600160a01b0319166001600160a01b0390911617825560209092019160019091019061398b565b506139cc9291506139d0565b5090565b5b808211156139cc57600081556001016139d1565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b0381118282101715613a1d57613a1d6139e5565b60405290565b604051606081016001600160401b0381118282101715613a1d57613a1d6139e5565b60405160a081016001600160401b0381118282101715613a1d57613a1d6139e5565b60405160c081016001600160401b0381118282101715613a1d57613a1d6139e5565b604080519081016001600160401b0381118282101715613a1d57613a1d6139e5565b604051601f8201601f191681016001600160401b0381118282101715613ad357613ad36139e5565b604052919050565b60006001600160401b03821115613af457613af46139e5565b5060051b60200190565b6001600160a01b038116811461051357600080fd5b80356001600160401b0381168114613b2a57600080fd5b919050565b801515811461051357600080fd5b8035613b2a81613b2f565b60006001600160401b03821115613b6157613b616139e5565b50601f01601f191660200190565b600082601f830112613b8057600080fd5b8135613b93613b8e82613b48565b613aab565b818152846020838601011115613ba857600080fd5b816020850160208301376000918101602001919091529392505050565b60006020808385031215613bd857600080fd5b82356001600160401b0380821115613bef57600080fd5b818501915085601f830112613c0357600080fd5b8135613c11613b8e82613adb565b81815260059190911b83018401908481019088831115613c3057600080fd5b8585015b83811015613cd657803585811115613c4c5760008081fd5b86016080818c03601f1901811315613c645760008081fd5b613c6c6139fb565b89830135613c7981613afe565b81526040613c88848201613b13565b8b830152606080850135613c9b81613b2f565b83830152928401359289841115613cb457600091508182fd5b613cc28f8d86880101613b6f565b908301525085525050918601918601613c34565b5098975050505050505050565b60005b83811015613cfe578181015183820152602001613ce6565b50506000910152565b60008151808452613d1f816020860160208601613ce3565b601f01601f19169290920160200192915050565b602081526000610a7a6020830184613d07565b8060608101831015610a7d57600080fd5b60008083601f840112613d6957600080fd5b5081356001600160401b03811115613d8057600080fd5b602083019150836020828501011115613d9857600080fd5b9250929050565b60008083601f840112613db157600080fd5b5081356001600160401b03811115613dc857600080fd5b6020830191508360208260051b8501011115613d9857600080fd5b60008060008060008060008060e0898b031215613dff57600080fd5b613e098a8a613d46565b975060608901356001600160401b0380821115613e2557600080fd5b613e318c838d01613d57565b909950975060808b0135915080821115613e4a57600080fd5b613e568c838d01613d9f565b909750955060a08b0135915080821115613e6f57600080fd5b50613e7c8b828c01613d9f565b999c989b50969995989497949560c00135949350505050565b600080600060808486031215613eaa57600080fd5b613eb48585613d46565b925060608401356001600160401b03811115613ecf57600080fd5b613edb86828701613d57565b9497909650939450505050565b60008060408385031215613efb57600080fd5b613f0483613b13565b9150613f1260208401613b13565b90509250929050565b634e487b7160e01b600052602160045260246000fd5b60048110613f4157613f41613f1b565b9052565b60208101610a7d8284613f31565b8035613b2a81613afe565b63ffffffff8116811461051357600080fd5b600060608284031215613f8257600080fd5b613f8a613a23565b8235613f9581613afe565b81526020830135613fa581613f5e565b60208201526040830135613fb881613afe565b60408201529392505050565b600060208284031215613fd657600080fd5b81356001600160401b03811115613fec57600080fd5b820160a0818503121561392357600080fd5b803560ff81168114613b2a57600080fd5b60006020828403121561402157600080fd5b610a7a82613ffe565b60008151808452602080850194506020840160005b838110156140645781516001600160a01b03168752958201959082019060010161403f565b509495945050505050565b60208152600082518051602084015260ff602082015116604084015260ff604082015116606084015260608101511515608084015250602083015160c060a08401526140be60e084018261402a565b90506040840151601f198483030160c08501526140db828261402a565b95945050505050565b600080604083850312156140f757600080fd5b61410083613b13565b946020939093013593505050565b600060a0828403121561412057600080fd5b614128613a45565b90508135815261413a60208301613b13565b602082015261414b60408301613b13565b604082015261415c60608301613b13565b606082015261416d60808301613b13565b608082015292915050565b600082601f83011261418957600080fd5b81356020614199613b8e83613adb565b82815260059290921b840181019181810190868411156141b857600080fd5b8286015b848110156142b25780356001600160401b03808211156141dc5760008081fd5b9088019060a0828b03601f19018113156141f65760008081fd5b6141fe613a45565b87840135838111156142105760008081fd5b61421e8d8a83880101613b6f565b825250604080850135848111156142355760008081fd5b6142438e8b83890101613b6f565b8a840152506060808601358581111561425c5760008081fd5b61426a8f8c838a0101613b6f565b838501525060809150818601358184015250828501359250838311156142905760008081fd5b61429e8d8a85880101613b6f565b9082015286525050509183019183016141bc565b509695505050505050565b600061014082840312156142d057600080fd5b6142d8613a67565b90506142e4838361410e565b815260a08201356001600160401b038082111561430057600080fd5b61430c85838601613b6f565b602084015260c084013591508082111561432557600080fd5b61433185838601613b6f565b604084015261434260e08501613f53565b6060840152610100840135608084015261012084013591508082111561436757600080fd5b5061437484828501614178565b60a08301525092915050565b60008060008060006060868803121561439857600080fd5b85356001600160401b03808211156143af57600080fd5b6143bb89838a016142bd565b965060208801359150808211156143d157600080fd5b6143dd89838a01613d9f565b909650945060408801359150808211156143f657600080fd5b5061440388828901613d9f565b969995985093965092949392505050565b600082601f83011261442557600080fd5b81356020614435613b8e83613adb565b82815260059290921b8401810191818101908684111561445457600080fd5b8286015b848110156142b25780356001600160401b038111156144775760008081fd5b6144858986838b01016142bd565b845250918301918301614458565b600082601f8301126144a457600080fd5b813560206144b4613b8e83613adb565b82815260059290921b840181019181810190868411156144d357600080fd5b8286015b848110156142b25780356001600160401b03808211156144f657600080fd5b818901915089603f83011261450a57600080fd5b8582013561451a613b8e82613adb565b81815260059190911b830160400190878101908c83111561453a57600080fd5b604085015b838110156145735780358581111561455657600080fd5b6145658f6040838a0101613b6f565b84525091890191890161453f565b508752505050928401925083016144d7565b600082601f83011261459657600080fd5b813560206145a6613b8e83613adb565b8083825260208201915060208460051b8701019350868411156145c857600080fd5b602086015b848110156142b257803583529183019183016145cd565b600082601f8301126145f557600080fd5b81356020614605613b8e83613adb565b82815260059290921b8401810191818101908684111561462457600080fd5b8286015b848110156142b25780356001600160401b03808211156146485760008081fd5b9088019060a0828b03601f19018113156146625760008081fd5b61466a613a45565b614675888501613b13565b81526040808501358481111561468b5760008081fd5b6146998e8b83890101614414565b8a84015250606080860135858111156146b25760008081fd5b6146c08f8c838a0101614493565b83850152506080915081860135858111156146db5760008081fd5b6146e98f8c838a0101614585565b9184019190915250919093013590830152508352918301918301614628565b6000806040838503121561471b57600080fd5b6001600160401b038335111561473057600080fd5b61473d84843585016145e4565b91506001600160401b036020840135111561475757600080fd5b6020830135830184601f82011261476d57600080fd5b61477a613b8e8235613adb565b81358082526020808301929160051b84010187101561479857600080fd5b602083015b6020843560051b850101811015614941576001600160401b03813511156147c357600080fd5b87603f8235860101126147d557600080fd5b6147e8613b8e6020833587010135613adb565b81358501602081810135808452908301929160059190911b016040018a101561481057600080fd5b604083358701015b83358701602081013560051b01604001811015614931576001600160401b038135111561484457600080fd5b833587018135016040818d03603f1901121561485f57600080fd5b614867613a89565b604082013581526001600160401b036060830135111561488657600080fd5b8c605f60608401358401011261489b57600080fd5b60406060830135830101356148b2613b8e82613adb565b808282526020820191508f60608460051b60608801358801010111156148d757600080fd5b6060808601358601015b60608460051b606088013588010101811015614911576149018135613f5e565b80358352602092830192016148e1565b508060208501525050508085525050602083019250602081019050614818565b508452506020928301920161479d565b508093505050509250929050565b60006020828403121561496157600080fd5b610a7a82613b13565b602081526001600160a01b0382511660208201526020820151151560408201526001600160401b0360408301511660608201526000606083015160808084015261331360a0840182613d07565b6000602082840312156149c957600080fd5b813561392381613afe565b600082601f8301126149e557600080fd5b813560206149f5613b8e83613adb565b8083825260208201915060208460051b870101935086841115614a1757600080fd5b602086015b848110156142b2578035614a2f81613afe565b8352918301918301614a1c565b60006020808385031215614a4f57600080fd5b82356001600160401b0380821115614a6657600080fd5b818501915085601f830112614a7a57600080fd5b8135614a88613b8e82613adb565b81815260059190911b83018401908481019088831115614aa757600080fd5b8585015b83811015613cd657803585811115614ac257600080fd5b860160c0818c03601f19011215614ad95760008081fd5b614ae1613a67565b8882013581526040614af4818401613ffe565b8a8301526060614b05818501613ffe565b8284015260809150614b18828501613b3d565b9083015260a08381013589811115614b305760008081fd5b614b3e8f8d838801016149d4565b838501525060c0840135915088821115614b585760008081fd5b614b668e8c848701016149d4565b9083015250845250918601918601614aab565b80356001600160e01b0381168114613b2a57600080fd5b600082601f830112614ba157600080fd5b81356020614bb1613b8e83613adb565b82815260069290921b84018101918181019086841115614bd057600080fd5b8286015b848110156142b25760408189031215614bed5760008081fd5b614bf5613a89565b614bfe82613b13565b8152614c0b858301614b79565b81860152835291830191604001614bd4565b600082601f830112614c2e57600080fd5b81356020614c3e613b8e83613adb565b82815260059290921b84018101918181019086841115614c5d57600080fd5b8286015b848110156142b25780356001600160401b0380821115614c815760008081fd5b9088019060a0828b03601f1901811315614c9b5760008081fd5b614ca3613a45565b614cae888501613b13565b815260408085013584811115614cc45760008081fd5b614cd28e8b83890101613b6f565b8a8401525060609350614ce6848601613b13565b908201526080614cf7858201613b13565b93820193909352920135908201528352918301918301614c61565b600082601f830112614d2357600080fd5b81356020614d33613b8e83613adb565b82815260069290921b84018101918181019086841115614d5257600080fd5b8286015b848110156142b25760408189031215614d6f5760008081fd5b614d77613a89565b813581528482013585820152835291830191604001614d56565b60006020808385031215614da457600080fd5b82356001600160401b0380821115614dbb57600080fd5b9084019060608287031215614dcf57600080fd5b614dd7613a23565b823582811115614de657600080fd5b83016040818903811315614df957600080fd5b614e01613a89565b823585811115614e1057600080fd5b8301601f81018b13614e2157600080fd5b8035614e2f613b8e82613adb565b81815260069190911b8201890190898101908d831115614e4e57600080fd5b928a01925b82841015614e9e5785848f031215614e6b5760008081fd5b614e73613a89565b8435614e7e81613afe565b8152614e8b858d01614b79565b818d0152825292850192908a0190614e53565b845250505082870135915084821115614eb657600080fd5b614ec28a838501614b90565b81880152835250508284013582811115614edb57600080fd5b614ee788828601614c1d565b85830152506040830135935081841115614f0057600080fd5b614f0c87858501614d12565b60408201529695505050505050565b600082825180855260208086019550808260051b84010181860160005b84811015614fac57601f19868403018952815160a06001600160401b03808351168652868301518288880152614f7083880182613d07565b60408581015184169089015260608086015190931692880192909252506080928301519290950191909152509783019790830190600101614f38565b5090979650505050505050565b60006040808352614fcd6040840186614f1b565b83810360208581019190915285518083528682019282019060005b8181101561500d57845180518452840151848401529383019391850191600101614fe8565b509098975050505050505050565b634e487b7160e01b600052603260045260246000fd5b805160408084528151848201819052600092602091908201906060870190855b8181101561508857835180516001600160a01b031684528501516001600160e01b0316858401529284019291850191600101615051565b50508583015187820388850152805180835290840192506000918401905b808310156150e157835180516001600160401b031683528501516001600160e01b0316858301529284019260019290920191908501906150a6565b50979650505050505050565b602081526000610a7a6020830184615031565b60006020828403121561511257600080fd5b815161392381613b2f565b634e487b7160e01b600052601160045260246000fd5b6001600160401b038181168382160190808211156151535761515361511d565b5092915050565b60408152600061516d6040830185614f1b565b82810360208401526140db8185615031565b60006020828403121561519157600080fd5b81356001600160401b038111156151a757600080fd5b613313848285016145e4565b81810381811115610a7d57610a7d61511d565b634e487b7160e01b600052601260045260246000fd5b60006001600160401b03808416806151f6576151f66151c6565b92169190910692915050565b8082028115828204841417610a7d57610a7d61511d565b80518252600060206001600160401b0381840151168185015260408084015160a0604087015261524c60a0870182613d07565b9050606085015186820360608801526152658282613d07565b608087810151898303918a01919091528051808352908601935060009250908501905b808310156150e157835180516001600160a01b0316835286015186830152928501926001929092019190840190615288565b602081526000610a7a6020830184615219565b6080815260006152e06080830187615219565b61ffff9590951660208301525060408101929092526001600160a01b0316606090910152919050565b60008060006060848603121561531e57600080fd5b835161532981613b2f565b60208501519093506001600160401b0381111561534557600080fd5b8401601f8101861361535657600080fd5b8051615364613b8e82613b48565b81815287602083850101111561537957600080fd5b61538a826020830160208601613ce3565b809450505050604084015190509250925092565b6000602082840312156153b057600080fd5b815161392381613f5e565b600181811c908216806153cf57607f821691505b6020821081036153ef57634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115611225576000816000526020600020601f850160051c8101602086101561541e5750805b601f850160051c820191505b8181101561543d5782815560010161542a565b505050505050565b81516001600160401b0381111561545e5761545e6139e5565b6154728161546c84546153bb565b846153f5565b602080601f8311600181146154a7576000841561548f5750858301515b600019600386901b1c1916600185901b17855561543d565b600085815260208120601f198616915b828110156154d6578886015182559484019460019091019084016154b7565b50858210156154f45787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6000602080835283546001600160a01b038116602085015260ff8160a01c16151560408501526001600160401b038160a81c16606085015250600180850160808086015260008154615555816153bb565b8060a089015260c060018316600081146155765760018114615592576155c2565b60ff19841660c08b015260c083151560051b8b010194506155c2565b85600052602060002060005b848110156155b95781548c820185015290880190890161559e565b8b0160c0019550505b50929998505050505050505050565b80820180821115610a7d57610a7d61511d565b60ff8181168382160190811115610a7d57610a7d61511d565b8183823760009101908152919050565b828152606082602083013760800192915050565b60006001600160401b038084168061563b5761563b6151c6565b92169190910492915050565b60006020828403121561565957600080fd5b813561392381613f5e565b6000808335601e1984360301811261567b57600080fd5b8301803591506001600160401b0382111561569557600080fd5b602001915036819003821315613d9857600080fd5b60208101600583106156be576156be613f1b565b91905290565b60ff81811683821602908116908181146151535761515361511d565b600060a0820160ff881683526020878185015260a0604085015281875480845260c0860191508860005282600020935060005b818110156157385784546001600160a01b031683526001948501949284019201615713565b50508481036060860152865180825290820192508187019060005b818110156157785782516001600160a01b031685529383019391830191600101615753565b50505060ff851660808501525090505b9695505050505050565b60006001600160401b038086168352808516602084015250606060408301526140db6060830184613d07565b8281526040602082015260006133136040830184613d07565b6001600160401b03848116825283166020820152606081016133136040830184613f31565b84815261580c6020820185613f31565b6080604082015260006158226080830185613d07565b905082606083015295945050505050565b60006020828403121561584557600080fd5b815161392381613afe565b602081526000825161010080602085015261586f610120850183613d07565b9150602085015161588b60408601826001600160401b03169052565b5060408501516001600160a01b0381166060860152506060850151608085015260808501516158c560a08601826001600160a01b03169052565b5060a0850151601f19808685030160c08701526158e28483613d07565b935060c08701519150808685030160e08701526158ff8483613d07565b935060e08701519150808685030183870152506157888382613d07565b60006020828403121561592e57600080fd5b5051919050565b84815260006001600160401b038086166020840152808516604084015250608060608301526157886080830184613d07565b86815260c06020820152600061598060c0830188613d07565b6001600160a01b03969096166040830152506001600160401b039384166060820152608081019290925290911660a09091015292915050565b600082825180855260208086019550808260051b84010181860160005b84811015614fac57601f19868403018952815160a081518186526159fc82870182613d07565b9150508582015185820387870152615a148282613d07565b91505060408083015186830382880152615a2e8382613d07565b92505050606080830151818701525060808083015192508582038187015250615a578183613d07565b9a86019a94505050908301906001016159d6565b602081526000610a7a60208301846159b9565b60008282518085526020808601955060208260051b8401016020860160005b84811015614fac57601f19868403018952615ab9838351613d07565b98840198925090830190600101615a9d565b60008151808452602080850194506020840160005b8381101561406457815163ffffffff1687529582019590820190600101615ae0565b60608152600084518051606084015260208101516001600160401b0380821660808601528060408401511660a08601528060608401511660c08601528060808401511660e0860152505050602085015161014080610100850152615b6a6101a0850183613d07565b91506040870151605f198086850301610120870152615b898483613d07565b935060608901519150615ba6838701836001600160a01b03169052565b608089015161016087015260a0890151925080868503016101808701525050615bcf82826159b9565b9150508281036020840152615be48186615a7e565b905082810360408401526157888185615acb56fea164736f6c6343000818000a", } var OffRampABI = OffRampMetaData.ABI @@ -557,27 +560,27 @@ func (_OffRamp *OffRampTransactorSession) Execute(reportContext [3][32]byte, rep return _OffRamp.Contract.Execute(&_OffRamp.TransactOpts, reportContext, report) } -func (_OffRamp *OffRampTransactor) ExecuteSingleMessage(opts *bind.TransactOpts, message InternalAny2EVMRampMessage, offchainTokenData [][]byte) (*types.Transaction, error) { - return _OffRamp.contract.Transact(opts, "executeSingleMessage", message, offchainTokenData) +func (_OffRamp *OffRampTransactor) ExecuteSingleMessage(opts *bind.TransactOpts, message InternalAny2EVMRampMessage, offchainTokenData [][]byte, tokenGasOverrides []uint32) (*types.Transaction, error) { + return _OffRamp.contract.Transact(opts, "executeSingleMessage", message, offchainTokenData, tokenGasOverrides) } -func (_OffRamp *OffRampSession) ExecuteSingleMessage(message InternalAny2EVMRampMessage, offchainTokenData [][]byte) (*types.Transaction, error) { - return _OffRamp.Contract.ExecuteSingleMessage(&_OffRamp.TransactOpts, message, offchainTokenData) +func (_OffRamp *OffRampSession) ExecuteSingleMessage(message InternalAny2EVMRampMessage, offchainTokenData [][]byte, tokenGasOverrides []uint32) (*types.Transaction, error) { + return _OffRamp.Contract.ExecuteSingleMessage(&_OffRamp.TransactOpts, message, offchainTokenData, tokenGasOverrides) } -func (_OffRamp *OffRampTransactorSession) ExecuteSingleMessage(message InternalAny2EVMRampMessage, offchainTokenData [][]byte) (*types.Transaction, error) { - return _OffRamp.Contract.ExecuteSingleMessage(&_OffRamp.TransactOpts, message, offchainTokenData) +func (_OffRamp *OffRampTransactorSession) ExecuteSingleMessage(message InternalAny2EVMRampMessage, offchainTokenData [][]byte, tokenGasOverrides []uint32) (*types.Transaction, error) { + return _OffRamp.Contract.ExecuteSingleMessage(&_OffRamp.TransactOpts, message, offchainTokenData, tokenGasOverrides) } -func (_OffRamp *OffRampTransactor) ManuallyExecute(opts *bind.TransactOpts, reports []InternalExecutionReportSingleChain, gasLimitOverrides [][]*big.Int) (*types.Transaction, error) { +func (_OffRamp *OffRampTransactor) ManuallyExecute(opts *bind.TransactOpts, reports []InternalExecutionReportSingleChain, gasLimitOverrides [][]OffRampGasLimitOverride) (*types.Transaction, error) { return _OffRamp.contract.Transact(opts, "manuallyExecute", reports, gasLimitOverrides) } -func (_OffRamp *OffRampSession) ManuallyExecute(reports []InternalExecutionReportSingleChain, gasLimitOverrides [][]*big.Int) (*types.Transaction, error) { +func (_OffRamp *OffRampSession) ManuallyExecute(reports []InternalExecutionReportSingleChain, gasLimitOverrides [][]OffRampGasLimitOverride) (*types.Transaction, error) { return _OffRamp.Contract.ManuallyExecute(&_OffRamp.TransactOpts, reports, gasLimitOverrides) } -func (_OffRamp *OffRampTransactorSession) ManuallyExecute(reports []InternalExecutionReportSingleChain, gasLimitOverrides [][]*big.Int) (*types.Transaction, error) { +func (_OffRamp *OffRampTransactorSession) ManuallyExecute(reports []InternalExecutionReportSingleChain, gasLimitOverrides [][]OffRampGasLimitOverride) (*types.Transaction, error) { return _OffRamp.Contract.ManuallyExecute(&_OffRamp.TransactOpts, reports, gasLimitOverrides) } @@ -2404,7 +2407,7 @@ func (OffRampConfigSet) Topic() common.Hash { } func (OffRampDynamicConfigSet) Topic() common.Hash { - return common.HexToHash("0xa55bd56595c45f517e5967a3067f3dca684445a3080e7c04a4e0d5a40cda627d") + return common.HexToHash("0xa1c15688cb2c24508e158f6942b9276c6f3028a85e1af8cf3fff0c3ff3d5fc8d") } func (OffRampExecutionStateChanged) Topic() common.Hash { @@ -2480,9 +2483,9 @@ type OffRampInterface interface { Execute(opts *bind.TransactOpts, reportContext [3][32]byte, report []byte) (*types.Transaction, error) - ExecuteSingleMessage(opts *bind.TransactOpts, message InternalAny2EVMRampMessage, offchainTokenData [][]byte) (*types.Transaction, error) + ExecuteSingleMessage(opts *bind.TransactOpts, message InternalAny2EVMRampMessage, offchainTokenData [][]byte, tokenGasOverrides []uint32) (*types.Transaction, error) - ManuallyExecute(opts *bind.TransactOpts, reports []InternalExecutionReportSingleChain, gasLimitOverrides [][]*big.Int) (*types.Transaction, error) + ManuallyExecute(opts *bind.TransactOpts, reports []InternalExecutionReportSingleChain, gasLimitOverrides [][]OffRampGasLimitOverride) (*types.Transaction, error) SetDynamicConfig(opts *bind.TransactOpts, dynamicConfig OffRampDynamicConfig) (*types.Transaction, error) diff --git a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt index fca7e971c4..9908bcfcd8 100644 --- a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -23,7 +23,7 @@ multi_aggregate_rate_limiter: ../../../contracts/solc/v0.8.24/MultiAggregateRate multi_ocr3_helper: ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Helper.abi ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Helper.bin 6b56e0114a4d50797d30a34aecc2641ef340451d0c3fcb9d729bba4df2435122 nonce_manager: ../../../contracts/solc/v0.8.24/NonceManager/NonceManager.abi ../../../contracts/solc/v0.8.24/NonceManager/NonceManager.bin 6f64e1083b356c06ee66b9138e398b9c97a4cd3e8c9ec38cf3010cebc79af536 ocr3_config_encoder: ../../../contracts/solc/v0.8.24/IOCR3ConfigEncoder/IOCR3ConfigEncoder.abi ../../../contracts/solc/v0.8.24/IOCR3ConfigEncoder/IOCR3ConfigEncoder.bin 9254b35a86f00fde7b7193a033ca58f6521a66e87b9cf9da6ce5660082e79f5d -offramp: ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.abi ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.bin ec0e067fe9cd81ff009b813be775638f53e6c4f17e38610a724304885c96cbf2 +offramp: ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.abi ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.bin d7f33e895b1b282930c81ac4e19ec51f6a7900fe6dddda3a7ba1b2796eacff32 onramp: ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.abi ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.bin 594439983f963f4158f9c5009dee7cba4ee56be61900bb1d5b9108eaeac3d6a6 ping_pong_demo: ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.abi ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.bin c1c2f8a65c7ffd971899cae7fe62f2da57d09e936151e2b92163c4bebe699d6b price_registry: ../../../contracts/solc/v0.8.24/PriceRegistry/PriceRegistry.abi ../../../contracts/solc/v0.8.24/PriceRegistry/PriceRegistry.bin e7781d600c1bb7aa4620106af7f6e146a109b97f4cb6a7d06c9e15773340ecb2 From 7ba1e751c809126b1e114e86800d2c1c127b4b50 Mon Sep 17 00:00:00 2001 From: Ryan <80392855+RayXpub@users.noreply.github.com> Date: Thu, 12 Sep 2024 09:09:51 +0400 Subject: [PATCH 086/115] Change data feeds from default to fallback in `FeeQuoter` (#1430) ## Motivation Due to the gas cost of reading from data feeds, it is unlikely to be the default option, we can therefore optimize the `getTokenPrice()` function by defaulting to state instead of data feeds. ## Solution Default to state reported prices and only fall back on data feed external call if the reported prices are stale. --- contracts/gas-snapshots/ccip.gas-snapshot | 258 +++++++++--------- contracts/src/v0.8/ccip/FeeQuoter.sol | 13 +- .../v0.8/ccip/test/feeQuoter/FeeQuoter.t.sol | 11 +- .../ccip/generated/fee_quoter/fee_quoter.go | 2 +- ...rapper-dependency-versions-do-not-edit.txt | 2 +- 5 files changed, 152 insertions(+), 134 deletions(-) diff --git a/contracts/gas-snapshots/ccip.gas-snapshot b/contracts/gas-snapshots/ccip.gas-snapshot index e6596d9f3c..2dbf1fe8c9 100644 --- a/contracts/gas-snapshots/ccip.gas-snapshot +++ b/contracts/gas-snapshots/ccip.gas-snapshot @@ -10,8 +10,8 @@ AggregateTokenLimiter_getTokenBucket:test_GetTokenBucket_Success() (gas: 19835) AggregateTokenLimiter_getTokenBucket:test_Refill_Success() (gas: 41499) AggregateTokenLimiter_getTokenBucket:test_TimeUnderflow_Revert() (gas: 15446) AggregateTokenLimiter_getTokenLimitAdmin:test_GetTokenLimitAdmin_Success() (gas: 10531) -AggregateTokenLimiter_getTokenValue:test_GetTokenValue_Success() (gas: 19652) -AggregateTokenLimiter_getTokenValue:test_NoTokenPrice_Reverts() (gas: 21237) +AggregateTokenLimiter_getTokenValue:test_GetTokenValue_Success() (gas: 17465) +AggregateTokenLimiter_getTokenValue:test_NoTokenPrice_Reverts() (gas: 21360) AggregateTokenLimiter_rateLimitValue:test_AggregateValueMaxCapacityExceeded_Revert() (gas: 16508) AggregateTokenLimiter_rateLimitValue:test_RateLimitValueSuccess_gas() (gas: 18348) AggregateTokenLimiter_setAdmin:test_OnlyOwnerOrAdmin_Revert() (gas: 13054) @@ -34,7 +34,7 @@ BurnWithFromMintTokenPool_lockOrBurn:test_ChainNotAllowed_Revert() (gas: 28779) BurnWithFromMintTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 55124) BurnWithFromMintTokenPool_lockOrBurn:test_PoolBurn_Success() (gas: 243707) BurnWithFromMintTokenPool_lockOrBurn:test_Setup_Success() (gas: 23951) -CCIPClientExample_sanity:test_ImmutableExamples_Success() (gas: 2096747) +CCIPClientExample_sanity:test_ImmutableExamples_Success() (gas: 2091438) CCIPConfigSetup:test_getCapabilityConfiguration_Success() (gas: 9539) CCIPConfig_ConfigStateMachine:test__computeConfigDigest_Success() (gas: 66000) CCIPConfig_ConfigStateMachine:test__computeNewConfigWithMeta_InitToRunning_Success() (gas: 358041) @@ -99,9 +99,9 @@ CommitStore_report:test_Paused_Revert() (gas: 21262) CommitStore_report:test_ReportAndPriceUpdate_Success() (gas: 84276) CommitStore_report:test_ReportOnlyRootSuccess_gas() (gas: 56258) CommitStore_report:test_RootAlreadyCommitted_Revert() (gas: 63984) -CommitStore_report:test_StaleReportWithRoot_Success() (gas: 119350) +CommitStore_report:test_StaleReportWithRoot_Success() (gas: 116976) CommitStore_report:test_Unhealthy_Revert() (gas: 44754) -CommitStore_report:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 100760) +CommitStore_report:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 98573) CommitStore_report:test_ZeroEpochAndRound_Revert() (gas: 27632) CommitStore_resetUnblessedRoots:test_OnlyOwner_Revert() (gas: 11331) CommitStore_resetUnblessedRoots:test_ResetUnblessedRoots_Success() (gas: 143814) @@ -117,7 +117,7 @@ CommitStore_verify:test_Paused_Revert() (gas: 18505) CommitStore_verify:test_TooManyLeaves_Revert() (gas: 36797) DefensiveExampleTest:test_HappyPath_Success() (gas: 200047) DefensiveExampleTest:test_Recovery() (gas: 424294) -E2E:test_E2E_3MessagesSuccess_gas() (gas: 1101745) +E2E:test_E2E_3MessagesSuccess_gas() (gas: 1095501) EVM2EVMOffRamp__releaseOrMintToken:test__releaseOrMintToken_NotACompatiblePool_Revert() (gas: 37818) EVM2EVMOffRamp__releaseOrMintToken:test__releaseOrMintToken_Success() (gas: 103820) EVM2EVMOffRamp__releaseOrMintToken:test__releaseOrMintToken_TokenHandlingError_transfer_Revert() (gas: 85333) @@ -125,20 +125,20 @@ EVM2EVMOffRamp__releaseOrMintToken:test_releaseOrMintToken_InvalidDataLength_Rev EVM2EVMOffRamp__releaseOrMintToken:test_releaseOrMintToken_ReleaseOrMintBalanceMismatch_Revert() (gas: 94389) EVM2EVMOffRamp__releaseOrMintToken:test_releaseOrMintToken_TokenHandlingError_BalanceOf_Revert() (gas: 39813) EVM2EVMOffRamp__releaseOrMintToken:test_releaseOrMintToken_skip_ReleaseOrMintBalanceMismatch_if_pool_Revert() (gas: 86631) -EVM2EVMOffRamp__releaseOrMintTokens:test_OverValueWithARLOff_Success() (gas: 385690) -EVM2EVMOffRamp__releaseOrMintTokens:test_PriceNotFoundForToken_Reverts() (gas: 141997) -EVM2EVMOffRamp__releaseOrMintTokens:test_RateLimitErrors_Reverts() (gas: 804041) -EVM2EVMOffRamp__releaseOrMintTokens:test_TokenHandlingError_Reverts() (gas: 179438) +EVM2EVMOffRamp__releaseOrMintTokens:test_OverValueWithARLOff_Success() (gas: 379129) +EVM2EVMOffRamp__releaseOrMintTokens:test_PriceNotFoundForToken_Reverts() (gas: 139810) +EVM2EVMOffRamp__releaseOrMintTokens:test_RateLimitErrors_Reverts() (gas: 793106) +EVM2EVMOffRamp__releaseOrMintTokens:test_TokenHandlingError_Reverts() (gas: 177251) EVM2EVMOffRamp__releaseOrMintTokens:test__releaseOrMintTokens_NotACompatiblePool_Reverts() (gas: 29243) EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_InvalidDataLengthReturnData_Revert() (gas: 66504) EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_InvalidEVMAddress_Revert() (gas: 43320) -EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_Success() (gas: 211236) -EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals_Success() (gas: 222488) +EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_Success() (gas: 206862) +EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals_Success() (gas: 218114) EVM2EVMOffRamp__report:test_Report_Success() (gas: 126703) -EVM2EVMOffRamp__trialExecute:test_RateLimitError_Success() (gas: 237982) -EVM2EVMOffRamp__trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 246582) -EVM2EVMOffRamp__trialExecute:test_TokenPoolIsNotAContract_Success() (gas: 330144) -EVM2EVMOffRamp__trialExecute:test_trialExecute_Success() (gas: 312575) +EVM2EVMOffRamp__trialExecute:test_RateLimitError_Success() (gas: 235795) +EVM2EVMOffRamp__trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 244395) +EVM2EVMOffRamp__trialExecute:test_TokenPoolIsNotAContract_Success() (gas: 325770) +EVM2EVMOffRamp__trialExecute:test_trialExecute_Success() (gas: 308201) EVM2EVMOffRamp_ccipReceive:test_Reverts() (gas: 17033) EVM2EVMOffRamp_constructor:test_CommitStoreAlreadyInUse_Revert() (gas: 153548) EVM2EVMOffRamp_constructor:test_Constructor_Success() (gas: 5549627) @@ -146,7 +146,7 @@ EVM2EVMOffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 144282) EVM2EVMOffRamp_execute:test_EmptyReport_Revert() (gas: 21321) EVM2EVMOffRamp_execute:test_InvalidMessageId_Revert() (gas: 36558) EVM2EVMOffRamp_execute:test_InvalidSourceChain_Revert() (gas: 51775) -EVM2EVMOffRamp_execute:test_InvalidSourcePoolAddress_Success() (gas: 473981) +EVM2EVMOffRamp_execute:test_InvalidSourcePoolAddress_Success() (gas: 469607) EVM2EVMOffRamp_execute:test_ManualExecutionNotYetEnabled_Revert() (gas: 47830) EVM2EVMOffRamp_execute:test_MessageTooLarge_Revert() (gas: 152518) EVM2EVMOffRamp_execute:test_Paused_Revert() (gas: 103046) @@ -157,25 +157,25 @@ EVM2EVMOffRamp_execute:test_SingleMessageNoTokensUnordered_Success() (gas: 15789 EVM2EVMOffRamp_execute:test_SingleMessageNoTokens_Success() (gas: 173184) EVM2EVMOffRamp_execute:test_SingleMessageToNonCCIPReceiver_Success() (gas: 247246) EVM2EVMOffRamp_execute:test_SingleMessagesNoTokensSuccess_gas() (gas: 113971) -EVM2EVMOffRamp_execute:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 408103) +EVM2EVMOffRamp_execute:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 403729) EVM2EVMOffRamp_execute:test_SkippedIncorrectNonce_Success() (gas: 54294) EVM2EVMOffRamp_execute:test_StrictUntouchedToSuccess_Success() (gas: 131317) EVM2EVMOffRamp_execute:test_TokenDataMismatch_Revert() (gas: 52249) -EVM2EVMOffRamp_execute:test_TwoMessagesWithTokensAndGE_Success() (gas: 564401) -EVM2EVMOffRamp_execute:test_TwoMessagesWithTokensSuccess_gas() (gas: 494916) +EVM2EVMOffRamp_execute:test_TwoMessagesWithTokensAndGE_Success() (gas: 559653) +EVM2EVMOffRamp_execute:test_TwoMessagesWithTokensSuccess_gas() (gas: 490168) EVM2EVMOffRamp_execute:test_UnexpectedTokenData_Revert() (gas: 35497) -EVM2EVMOffRamp_execute:test_Unhealthy_Revert() (gas: 545666) +EVM2EVMOffRamp_execute:test_Unhealthy_Revert() (gas: 540918) EVM2EVMOffRamp_execute:test_UnsupportedNumberOfTokens_Revert() (gas: 64497) EVM2EVMOffRamp_execute:test__execute_SkippedAlreadyExecutedMessageUnordered_Success() (gas: 122676) EVM2EVMOffRamp_execute:test__execute_SkippedAlreadyExecutedMessage_Success() (gas: 142850) EVM2EVMOffRamp_execute:test_execute_RouterYULCall_Success() (gas: 427538) EVM2EVMOffRamp_executeSingleMessage:test_MessageSender_Revert() (gas: 18502) -EVM2EVMOffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 278362) +EVM2EVMOffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 273988) EVM2EVMOffRamp_executeSingleMessage:test_NonContract_Success() (gas: 18668) -EVM2EVMOffRamp_executeSingleMessage:test_TokenHandlingError_Revert() (gas: 224109) +EVM2EVMOffRamp_executeSingleMessage:test_TokenHandlingError_Revert() (gas: 221922) EVM2EVMOffRamp_executeSingleMessage:test_ZeroGasDONExecution_Revert() (gas: 47926) EVM2EVMOffRamp_executeSingleMessage:test_executeSingleMessage_NoTokens_Success() (gas: 47403) -EVM2EVMOffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens_Success() (gas: 314224) +EVM2EVMOffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens_Success() (gas: 309850) EVM2EVMOffRamp_executeSingleMessage:test_executeSingleMessage_ZeroGasZeroData_Success() (gas: 70065) EVM2EVMOffRamp_execute_upgrade:test_V2NonceNewSenderStartsAtZero_Success() (gas: 229454) EVM2EVMOffRamp_execute_upgrade:test_V2NonceStartsAtV1Nonce_Success() (gas: 276982) @@ -189,13 +189,13 @@ EVM2EVMOffRamp_manuallyExecute:test_ManualExecFailedTx_Revert() (gas: 185967) EVM2EVMOffRamp_manuallyExecute:test_ManualExecForkedChain_Revert() (gas: 27052) EVM2EVMOffRamp_manuallyExecute:test_ManualExecGasLimitMismatch_Revert() (gas: 45200) EVM2EVMOffRamp_manuallyExecute:test_ManualExecInvalidGasLimit_Revert() (gas: 27471) -EVM2EVMOffRamp_manuallyExecute:test_ManualExecWithMultipleMessagesAndSourceTokens_Success() (gas: 530789) -EVM2EVMOffRamp_manuallyExecute:test_ManualExecWithSourceTokens_Success() (gas: 346083) +EVM2EVMOffRamp_manuallyExecute:test_ManualExecWithMultipleMessagesAndSourceTokens_Success() (gas: 526041) +EVM2EVMOffRamp_manuallyExecute:test_ManualExecWithSourceTokens_Success() (gas: 341709) EVM2EVMOffRamp_manuallyExecute:test_ManualExec_Success() (gas: 187459) -EVM2EVMOffRamp_manuallyExecute:test_ReentrancyManualExecuteFails_Success() (gas: 2258366) -EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_DestinationGasAmountCountMismatch_Revert() (gas: 363296) +EVM2EVMOffRamp_manuallyExecute:test_ReentrancyManualExecuteFails_Success() (gas: 2256179) +EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_DestinationGasAmountCountMismatch_Revert() (gas: 358922) EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_DoesNotRevertIfUntouched_Success() (gas: 143972) -EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_InvalidTokenGasOverride_Revert() (gas: 366435) +EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_InvalidTokenGasOverride_Revert() (gas: 362061) EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_LowGasLimitManualExec_Success() (gas: 482796) EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_WithGasOverride_Success() (gas: 189862) EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_WithInvalidReceiverExecutionGasOverride_Revert() (gas: 153716) @@ -219,18 +219,18 @@ EVM2EVMOnRamp_forwardFromRouter:test_InvalidAddressEncodePacked_Revert() (gas: 3 EVM2EVMOnRamp_forwardFromRouter:test_InvalidAddress_Revert() (gas: 38497) EVM2EVMOnRamp_forwardFromRouter:test_InvalidChainSelector_Revert() (gas: 25534) EVM2EVMOnRamp_forwardFromRouter:test_InvalidExtraArgsTag_Revert() (gas: 25320) -EVM2EVMOnRamp_forwardFromRouter:test_MaxCapacityExceeded_Revert() (gas: 86138) +EVM2EVMOnRamp_forwardFromRouter:test_MaxCapacityExceeded_Revert() (gas: 83951) EVM2EVMOnRamp_forwardFromRouter:test_MaxFeeBalanceReached_Revert() (gas: 36514) EVM2EVMOnRamp_forwardFromRouter:test_MessageGasLimitTooHigh_Revert() (gas: 29078) EVM2EVMOnRamp_forwardFromRouter:test_MessageTooLarge_Revert() (gas: 107622) EVM2EVMOnRamp_forwardFromRouter:test_OriginalSender_Revert() (gas: 22724) -EVM2EVMOnRamp_forwardFromRouter:test_OverValueWithARLOff_Success() (gas: 227439) +EVM2EVMOnRamp_forwardFromRouter:test_OverValueWithARLOff_Success() (gas: 225252) EVM2EVMOnRamp_forwardFromRouter:test_Paused_Revert() (gas: 53150) EVM2EVMOnRamp_forwardFromRouter:test_Permissions_Revert() (gas: 25559) -EVM2EVMOnRamp_forwardFromRouter:test_PriceNotFoundForToken_Revert() (gas: 59478) +EVM2EVMOnRamp_forwardFromRouter:test_PriceNotFoundForToken_Revert() (gas: 57291) EVM2EVMOnRamp_forwardFromRouter:test_ShouldIncrementNonceOnlyOnOrdered_Success() (gas: 179442) EVM2EVMOnRamp_forwardFromRouter:test_ShouldIncrementSeqNumAndNonce_Success() (gas: 177724) -EVM2EVMOnRamp_forwardFromRouter:test_ShouldStoreNonLinkFees() (gas: 137333) +EVM2EVMOnRamp_forwardFromRouter:test_ShouldStoreNonLinkFees() (gas: 132585) EVM2EVMOnRamp_forwardFromRouter:test_SourceTokenDataTooLarge_Revert() (gas: 3772676) EVM2EVMOnRamp_forwardFromRouter:test_TooManyTokens_Revert() (gas: 30244) EVM2EVMOnRamp_forwardFromRouter:test_Unhealthy_Revert() (gas: 43342) @@ -238,29 +238,29 @@ EVM2EVMOnRamp_forwardFromRouter:test_UnsupportedToken_Revert() (gas: 109440) EVM2EVMOnRamp_forwardFromRouter:test_ZeroAddressReceiver_Revert() (gas: 313095) EVM2EVMOnRamp_forwardFromRouter:test_forwardFromRouter_ShouldStoreLinkFees_Success() (gas: 112430) EVM2EVMOnRamp_forwardFromRouter:test_forwardFromRouter_UnsupportedToken_Revert() (gas: 72269) -EVM2EVMOnRamp_forwardFromRouter:test_forwardFromRouter_correctSourceTokenData_Success() (gas: 713846) +EVM2EVMOnRamp_forwardFromRouter:test_forwardFromRouter_correctSourceTokenData_Success() (gas: 711472) EVM2EVMOnRamp_forwardFromRouter_upgrade:test_V2NonceNewSenderStartsAtZero_Success() (gas: 147709) EVM2EVMOnRamp_forwardFromRouter_upgrade:test_V2NonceStartsAtV1Nonce_Success() (gas: 190616) EVM2EVMOnRamp_forwardFromRouter_upgrade:test_V2SenderNoncesReadsPreviousRamp_Success() (gas: 121404) EVM2EVMOnRamp_forwardFromRouter_upgrade:test_V2_Success() (gas: 95376) EVM2EVMOnRamp_getDataAvailabilityCost:test_EmptyMessageCalculatesDataAvailabilityCost_Success() (gas: 20568) EVM2EVMOnRamp_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCost_Success() (gas: 20936) -EVM2EVMOnRamp_getFee:test_EmptyMessage_Success() (gas: 78401) -EVM2EVMOnRamp_getFee:test_GetFeeOfZeroForTokenMessage_Success() (gas: 81897) -EVM2EVMOnRamp_getFee:test_HighGasMessage_Success() (gas: 234249) +EVM2EVMOnRamp_getFee:test_EmptyMessage_Success() (gas: 74027) +EVM2EVMOnRamp_getFee:test_GetFeeOfZeroForTokenMessage_Success() (gas: 79523) +EVM2EVMOnRamp_getFee:test_HighGasMessage_Success() (gas: 229875) EVM2EVMOnRamp_getFee:test_MessageGasLimitTooHigh_Revert() (gas: 16733) EVM2EVMOnRamp_getFee:test_MessageTooLarge_Revert() (gas: 95283) -EVM2EVMOnRamp_getFee:test_MessageWithDataAndTokenTransfer_Success() (gas: 160123) +EVM2EVMOnRamp_getFee:test_MessageWithDataAndTokenTransfer_Success() (gas: 152627) EVM2EVMOnRamp_getFee:test_NotAFeeToken_Revert() (gas: 24113) -EVM2EVMOnRamp_getFee:test_SingleTokenMessage_Success() (gas: 118345) +EVM2EVMOnRamp_getFee:test_SingleTokenMessage_Success() (gas: 113597) EVM2EVMOnRamp_getFee:test_TooManyTokens_Revert() (gas: 19914) -EVM2EVMOnRamp_getFee:test_ZeroDataAvailabilityMultiplier_Success() (gas: 64726) +EVM2EVMOnRamp_getFee:test_ZeroDataAvailabilityMultiplier_Success() (gas: 62539) EVM2EVMOnRamp_getSupportedTokens:test_GetSupportedTokens_Revert() (gas: 10460) EVM2EVMOnRamp_getTokenPool:test_GetTokenPool_Success() (gas: 35195) -EVM2EVMOnRamp_getTokenTransferCost:test_CustomTokenBpsFee_Success() (gas: 45198) +EVM2EVMOnRamp_getTokenTransferCost:test_CustomTokenBpsFee_Success() (gas: 43011) EVM2EVMOnRamp_getTokenTransferCost:test_FeeTokenBpsFee_Success() (gas: 33079) EVM2EVMOnRamp_getTokenTransferCost:test_LargeTokenTransferChargesMaxFeeAndGas_Success() (gas: 28356) -EVM2EVMOnRamp_getTokenTransferCost:test_MixedTokenTransferFee_Success() (gas: 126939) +EVM2EVMOnRamp_getTokenTransferCost:test_MixedTokenTransferFee_Success() (gas: 121817) EVM2EVMOnRamp_getTokenTransferCost:test_NoTokenTransferChargesZeroFee_Success() (gas: 15250) EVM2EVMOnRamp_getTokenTransferCost:test_SmallTokenTransferChargesMinFeeAndGas_Success() (gas: 28164) EVM2EVMOnRamp_getTokenTransferCost:test_UnsupportedToken_Revert() (gas: 21260) @@ -338,59 +338,59 @@ FeeQuoter_applyTokenTransferFeeConfigUpdates:test_ApplyTokenTransferFeeConfig_Su FeeQuoter_applyTokenTransferFeeConfigUpdates:test_ApplyTokenTransferFeeZeroInput() (gas: 13089) FeeQuoter_applyTokenTransferFeeConfigUpdates:test_InvalidDestBytesOverhead_Revert() (gas: 17071) FeeQuoter_applyTokenTransferFeeConfigUpdates:test_OnlyCallableByOwnerOrAdmin_Revert() (gas: 12246) -FeeQuoter_constructor:test_InvalidLinkTokenEqZeroAddress_Revert() (gas: 106820) -FeeQuoter_constructor:test_InvalidMaxFeeJuelsPerMsg_Revert() (gas: 111170) -FeeQuoter_constructor:test_InvalidStalenessThreshold_Revert() (gas: 111223) -FeeQuoter_constructor:test_Setup_Success() (gas: 5205186) -FeeQuoter_convertTokenAmount:test_ConvertTokenAmount_Success() (gas: 72751) -FeeQuoter_convertTokenAmount:test_LinkTokenNotSupported_Revert() (gas: 30981) +FeeQuoter_constructor:test_InvalidLinkTokenEqZeroAddress_Revert() (gas: 106850) +FeeQuoter_constructor:test_InvalidMaxFeeJuelsPerMsg_Revert() (gas: 111200) +FeeQuoter_constructor:test_InvalidStalenessThreshold_Revert() (gas: 111253) +FeeQuoter_constructor:test_Setup_Success() (gas: 5219649) +FeeQuoter_convertTokenAmount:test_ConvertTokenAmount_Success() (gas: 68377) +FeeQuoter_convertTokenAmount:test_LinkTokenNotSupported_Revert() (gas: 29040) FeeQuoter_getDataAvailabilityCost:test_EmptyMessageCalculatesDataAvailabilityCost_Success() (gas: 94441) FeeQuoter_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCostUnsupportedDestChainSelector_Success() (gas: 14650) FeeQuoter_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCost_Success() (gas: 20482) -FeeQuoter_getTokenAndGasPrices:test_GetFeeTokenAndGasPrices_Success() (gas: 70464) +FeeQuoter_getTokenAndGasPrices:test_GetFeeTokenAndGasPrices_Success() (gas: 68277) FeeQuoter_getTokenAndGasPrices:test_StaleGasPrice_Revert() (gas: 16838) FeeQuoter_getTokenAndGasPrices:test_UnsupportedChain_Revert() (gas: 16140) -FeeQuoter_getTokenAndGasPrices:test_ZeroGasPrice_Success() (gas: 45771) -FeeQuoter_getTokenPrice:test_GetTokenPriceFromFeed_Success() (gas: 62227) -FeeQuoter_getTokenPrices:test_GetTokenPrices_Success() (gas: 84818) -FeeQuoter_getTokenTransferCost:test_CustomTokenBpsFee_Success() (gas: 41281) +FeeQuoter_getTokenAndGasPrices:test_ZeroGasPrice_Success() (gas: 43584) +FeeQuoter_getTokenPrice:test_GetTokenPriceFromFeed_Success() (gas: 66117) +FeeQuoter_getTokenPrices:test_GetTokenPrices_Success() (gas: 78256) +FeeQuoter_getTokenTransferCost:test_CustomTokenBpsFee_Success() (gas: 39094) FeeQuoter_getTokenTransferCost:test_FeeTokenBpsFee_Success() (gas: 34730) FeeQuoter_getTokenTransferCost:test_LargeTokenTransferChargesMaxFeeAndGas_Success() (gas: 27804) -FeeQuoter_getTokenTransferCost:test_MixedTokenTransferFee_Success() (gas: 101864) +FeeQuoter_getTokenTransferCost:test_MixedTokenTransferFee_Success() (gas: 96739) FeeQuoter_getTokenTransferCost:test_NoTokenTransferChargesZeroFee_Success() (gas: 20390) FeeQuoter_getTokenTransferCost:test_SmallTokenTransferChargesMinFeeAndGas_Success() (gas: 27679) FeeQuoter_getTokenTransferCost:test_ZeroAmountTokenTransferChargesMinFeeAndGas_Success() (gas: 27635) FeeQuoter_getTokenTransferCost:test_ZeroFeeConfigChargesMinFee_Success() (gas: 40064) FeeQuoter_getTokenTransferCost:test_getTokenTransferCost_selfServeUsesDefaults_Success() (gas: 29347) FeeQuoter_getValidatedFee:test_DestinationChainNotEnabled_Revert() (gas: 18210) -FeeQuoter_getValidatedFee:test_EmptyMessage_Success() (gas: 86123) -FeeQuoter_getValidatedFee:test_EnforceOutOfOrder_Revert() (gas: 54405) -FeeQuoter_getValidatedFee:test_HighGasMessage_Success() (gas: 242541) +FeeQuoter_getValidatedFee:test_EmptyMessage_Success() (gas: 81749) +FeeQuoter_getValidatedFee:test_EnforceOutOfOrder_Revert() (gas: 52218) +FeeQuoter_getValidatedFee:test_HighGasMessage_Success() (gas: 238167) FeeQuoter_getValidatedFee:test_InvalidEVMAddress_Revert() (gas: 22420) -FeeQuoter_getValidatedFee:test_MessageGasLimitTooHigh_Revert() (gas: 31833) +FeeQuoter_getValidatedFee:test_MessageGasLimitTooHigh_Revert() (gas: 29646) FeeQuoter_getValidatedFee:test_MessageTooLarge_Revert() (gas: 100163) -FeeQuoter_getValidatedFee:test_MessageWithDataAndTokenTransfer_Success() (gas: 148076) +FeeQuoter_getValidatedFee:test_MessageWithDataAndTokenTransfer_Success() (gas: 140577) FeeQuoter_getValidatedFee:test_NotAFeeToken_Revert() (gas: 21073) -FeeQuoter_getValidatedFee:test_SingleTokenMessage_Success() (gas: 117032) +FeeQuoter_getValidatedFee:test_SingleTokenMessage_Success() (gas: 112282) FeeQuoter_getValidatedFee:test_TooManyTokens_Revert() (gas: 22562) -FeeQuoter_getValidatedFee:test_ZeroDataAvailabilityMultiplier_Success() (gas: 64442) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Above18Decimals_Success() (gas: 2076322) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Below18Decimals_Success() (gas: 2076280) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt0Decimals_Success() (gas: 2056399) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt18Decimals_Success() (gas: 2076054) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFlippedDecimals_Success() (gas: 2076258) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedMaxInt224Value_Success() (gas: 2076070) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedOverStalenessPeriod_Success() (gas: 62001) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeed_Success() (gas: 61881) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPrice_Success() (gas: 61042) -FeeQuoter_getValidatedTokenPrice:test_OverflowFeedPrice_Revert() (gas: 2075757) -FeeQuoter_getValidatedTokenPrice:test_StaleFeeToken_Success() (gas: 61569) -FeeQuoter_getValidatedTokenPrice:test_TokenNotSupportedFeed_Revert() (gas: 109117) -FeeQuoter_getValidatedTokenPrice:test_TokenNotSupported_Revert() (gas: 13863) -FeeQuoter_getValidatedTokenPrice:test_UnderflowFeedPrice_Revert() (gas: 2074434) +FeeQuoter_getValidatedFee:test_ZeroDataAvailabilityMultiplier_Success() (gas: 62255) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Above18Decimals_Success() (gas: 2078733) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Below18Decimals_Success() (gas: 2078691) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt0Decimals_Success() (gas: 2058810) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt18Decimals_Success() (gas: 2078465) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFlippedDecimals_Success() (gas: 2078669) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedMaxInt224Value_Success() (gas: 2078481) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedOverStalenessPeriod_Success() (gas: 64412) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeed_Success() (gas: 64292) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPrice_Success() (gas: 58855) +FeeQuoter_getValidatedTokenPrice:test_OverflowFeedPrice_Revert() (gas: 2078166) +FeeQuoter_getValidatedTokenPrice:test_StaleFeeToken_Success() (gas: 61692) +FeeQuoter_getValidatedTokenPrice:test_TokenNotSupportedFeed_Revert() (gas: 116268) +FeeQuoter_getValidatedTokenPrice:test_TokenNotSupported_Revert() (gas: 13986) +FeeQuoter_getValidatedTokenPrice:test_UnderflowFeedPrice_Revert() (gas: 2076843) FeeQuoter_onReport:test_OnReport_StaleUpdate_Revert() (gas: 43336) FeeQuoter_onReport:test_onReport_InvalidForwarder_Reverts() (gas: 23306) -FeeQuoter_onReport:test_onReport_Success() (gas: 80582) +FeeQuoter_onReport:test_onReport_Success() (gas: 79834) FeeQuoter_onReport:test_onReport_UnsupportedToken_Reverts() (gas: 26692) FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsDefault_Success() (gas: 17191) FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsEnforceOutOfOrder_Revert() (gas: 21302) @@ -402,17 +402,17 @@ FeeQuoter_processMessageArgs:test_InvalidExtraArgs_Revert() (gas: 18339) FeeQuoter_processMessageArgs:test_MalformedEVMExtraArgs_Revert() (gas: 18885) FeeQuoter_processMessageArgs:test_MessageFeeTooHigh_Revert() (gas: 16404) FeeQuoter_processMessageArgs:test_WitEVMExtraArgsV2_Success() (gas: 26277) -FeeQuoter_processMessageArgs:test_WithConvertedTokenAmount_Success() (gas: 32443) +FeeQuoter_processMessageArgs:test_WithConvertedTokenAmount_Success() (gas: 27695) FeeQuoter_processMessageArgs:test_WithEVMExtraArgsV1_Success() (gas: 25889) FeeQuoter_processMessageArgs:test_WithEmptyEVMExtraArgs_Success() (gas: 23704) FeeQuoter_processMessageArgs:test_WithLinkTokenAmount_Success() (gas: 17353) FeeQuoter_updatePrices:test_OnlyCallableByUpdater_Revert() (gas: 12114) FeeQuoter_updatePrices:test_OnlyGasPrice_Success() (gas: 23599) -FeeQuoter_updatePrices:test_OnlyTokenPrice_Success() (gas: 30615) -FeeQuoter_updatePrices:test_UpdatableByAuthorizedCaller_Success() (gas: 76009) -FeeQuoter_updatePrices:test_UpdateMultiplePrices_Success() (gas: 151345) +FeeQuoter_updatePrices:test_OnlyTokenPrice_Success() (gas: 28428) +FeeQuoter_updatePrices:test_UpdatableByAuthorizedCaller_Success() (gas: 74260) +FeeQuoter_updatePrices:test_UpdateMultiplePrices_Success() (gas: 144784) FeeQuoter_updateTokenPriceFeeds:test_FeedNotUpdated() (gas: 50523) -FeeQuoter_updateTokenPriceFeeds:test_FeedUnset_Success() (gas: 63574) +FeeQuoter_updateTokenPriceFeeds:test_FeedUnset_Success() (gas: 63200) FeeQuoter_updateTokenPriceFeeds:test_FeedUpdatedByNonOwner_Revert() (gas: 19938) FeeQuoter_updateTokenPriceFeeds:test_MultipleFeedUpdate_Success() (gas: 88920) FeeQuoter_updateTokenPriceFeeds:test_SingleFeedUpdate_Success() (gas: 50795) @@ -498,27 +498,27 @@ MultiAggregateRateLimiter_constructor:test_Constructor_Success() (gas: 2166413) MultiAggregateRateLimiter_getTokenBucket:test_GetTokenBucket_Success() (gas: 30404) MultiAggregateRateLimiter_getTokenBucket:test_Refill_Success() (gas: 47673) MultiAggregateRateLimiter_getTokenBucket:test_TimeUnderflow_Revert() (gas: 15863) -MultiAggregateRateLimiter_getTokenValue:test_GetTokenValue_Success() (gas: 19646) -MultiAggregateRateLimiter_getTokenValue:test_NoTokenPrice_Reverts() (gas: 21231) +MultiAggregateRateLimiter_getTokenValue:test_GetTokenValue_Success() (gas: 17459) +MultiAggregateRateLimiter_getTokenValue:test_NoTokenPrice_Reverts() (gas: 21354) MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageFromUnauthorizedCaller_Revert() (gas: 14533) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithDifferentTokensOnDifferentChains_Success() (gas: 214200) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithDisabledRateLimitToken_Success() (gas: 60457) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithDifferentTokensOnDifferentChains_Success() (gas: 209639) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithDisabledRateLimitToken_Success() (gas: 58270) MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithNoTokens_Success() (gas: 17599) MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitDisabled_Success() (gas: 45006) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitExceeded_Revert() (gas: 50540) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitReset_Success() (gas: 78784) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithTokensOnDifferentChains_Success() (gas: 312459) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithTokens_Success() (gas: 54732) -MultiAggregateRateLimiter_onOutboundMessage:test_RateLimitValueDifferentLanes_Success() (gas: 1073667462) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitExceeded_Revert() (gas: 46166) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitReset_Success() (gas: 76036) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithTokensOnDifferentChains_Success() (gas: 307711) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithTokens_Success() (gas: 50358) +MultiAggregateRateLimiter_onOutboundMessage:test_RateLimitValueDifferentLanes_Success() (gas: 1073669836) MultiAggregateRateLimiter_onOutboundMessage:test_ValidateMessageWithNoTokens_Success() (gas: 19158) MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageFromUnauthorizedCaller_Revert() (gas: 15829) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithDifferentTokensOnDifferentChains_Success() (gas: 214044) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithDisabledRateLimitToken_Success() (gas: 62240) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithDifferentTokensOnDifferentChains_Success() (gas: 209483) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithDisabledRateLimitToken_Success() (gas: 60053) MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitDisabled_Success() (gas: 46818) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitExceeded_Revert() (gas: 52361) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitReset_Success() (gas: 80041) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithTokensOnDifferentChains_Success() (gas: 312529) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithTokens_Success() (gas: 56537) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitExceeded_Revert() (gas: 47987) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitReset_Success() (gas: 77293) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithTokensOnDifferentChains_Success() (gas: 307781) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithTokens_Success() (gas: 52163) MultiAggregateRateLimiter_setFeeQuoter:test_OnlyOwner_Revert() (gas: 11325) MultiAggregateRateLimiter_setFeeQuoter:test_Owner_Success() (gas: 19072) MultiAggregateRateLimiter_setFeeQuoter:test_ZeroAddress_Revert() (gas: 10597) @@ -559,8 +559,8 @@ MultiOCR3Base_transmit:test_UnAuthorizedTransmitter_Revert() (gas: 24189) MultiOCR3Base_transmit:test_UnauthorizedSigner_Revert() (gas: 61131) MultiOCR3Base_transmit:test_UnconfiguredPlugin_Revert() (gas: 39888) MultiOCR3Base_transmit:test_ZeroSignatures_Revert() (gas: 32971) -MultiOnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 411709) -MultiRampsE2E:test_E2E_3MessagesMMultiOffRampSuccess_gas() (gas: 1526826) +MultiOnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 409147) +MultiRampsE2E:test_E2E_3MessagesMMultiOffRampSuccess_gas() (gas: 1526265) NonceManager_NonceIncrementation:test_getIncrementedOutboundNonce_Success() (gas: 37916) NonceManager_NonceIncrementation:test_incrementInboundNonce_Skip() (gas: 23709) NonceManager_NonceIncrementation:test_incrementInboundNonce_Success() (gas: 38799) @@ -640,10 +640,10 @@ OffRamp_commit:test_ReportAndPriceUpdate_Success() (gas: 164945) OffRamp_commit:test_ReportOnlyRootSuccess_gas() (gas: 139934) OffRamp_commit:test_RootAlreadyCommitted_Revert() (gas: 141925) OffRamp_commit:test_SourceChainNotEnabled_Revert() (gas: 59208) -OffRamp_commit:test_StaleReportWithRoot_Success() (gas: 235331) +OffRamp_commit:test_StaleReportWithRoot_Success() (gas: 232957) OffRamp_commit:test_UnauthorizedTransmitter_Revert() (gas: 121451) OffRamp_commit:test_Unhealthy_Revert() (gas: 57938) -OffRamp_commit:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 208966) +OffRamp_commit:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 206779) OffRamp_commit:test_ZeroEpochAndRound_Revert() (gas: 51273) OffRamp_constructor:test_Constructor_Success() (gas: 6244332) OffRamp_constructor:test_SourceChainSelector_Revert() (gas: 136075) @@ -742,7 +742,7 @@ OffRamp_trialExecute:test_RateLimitError_Success() (gas: 225140) OffRamp_trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 233762) OffRamp_trialExecute:test_TokenPoolIsNotAContract_Success() (gas: 310735) OffRamp_trialExecute:test_trialExecute_Success() (gas: 283386) -OnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 390910) +OnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 387975) OnRamp_applyAllowListUpdates:test_applyAllowListUpdates_InvalidAllowListRequestDisabledAllowListWithAdds() (gas: 17746) OnRamp_applyAllowListUpdates:test_applyAllowListUpdates_Revert() (gas: 66535) OnRamp_applyAllowListUpdates:test_applyAllowListUpdates_Success() (gas: 323600) @@ -770,17 +770,17 @@ OnRamp_forwardFromRouter:test_Permissions_Revert() (gas: 18278) OnRamp_forwardFromRouter:test_ShouldIncrementNonceOnlyOnOrdered_Success() (gas: 184562) OnRamp_forwardFromRouter:test_ShouldIncrementSeqNumAndNonce_Success() (gas: 210880) OnRamp_forwardFromRouter:test_ShouldStoreLinkFees() (gas: 124838) -OnRamp_forwardFromRouter:test_ShouldStoreNonLinkFees() (gas: 146211) +OnRamp_forwardFromRouter:test_ShouldStoreNonLinkFees() (gas: 141462) OnRamp_forwardFromRouter:test_SourceTokenDataTooLarge_Revert() (gas: 3829289) OnRamp_forwardFromRouter:test_UnAllowedOriginalSender_Revert() (gas: 18714) OnRamp_forwardFromRouter:test_UnsupportedToken_Revert() (gas: 110907) OnRamp_forwardFromRouter:test_forwardFromRouter_UnsupportedToken_Revert() (gas: 76229) OnRamp_forwardFromRouter:test_forwardFromRouter_WithValidation_Success() (gas: 281171) -OnRamp_getFee:test_EmptyMessage_Success() (gas: 102470) -OnRamp_getFee:test_EnforceOutOfOrder_Revert() (gas: 66390) -OnRamp_getFee:test_GetFeeOfZeroForTokenMessage_Success() (gas: 87796) +OnRamp_getFee:test_EmptyMessage_Success() (gas: 97722) +OnRamp_getFee:test_EnforceOutOfOrder_Revert() (gas: 64203) +OnRamp_getFee:test_GetFeeOfZeroForTokenMessage_Success() (gas: 85422) OnRamp_getFee:test_NotAFeeTokenButPricedToken_Revert() (gas: 34972) -OnRamp_getFee:test_SingleTokenMessage_Success() (gas: 117839) +OnRamp_getFee:test_SingleTokenMessage_Success() (gas: 112713) OnRamp_getFee:test_Unhealthy_Revert() (gas: 17009) OnRamp_getSupportedTokens:test_GetSupportedTokens_Revert() (gas: 10438) OnRamp_getTokenPool:test_GetTokenPool_Success() (gas: 35204) @@ -790,11 +790,11 @@ OnRamp_setDynamicConfig:test_SetConfigInvalidConfig_Revert() (gas: 11377) OnRamp_setDynamicConfig:test_SetConfigOnlyOwner_Revert() (gas: 16409) OnRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 55330) OnRamp_withdrawFeeTokens:test_WithdrawFeeTokens_Success() (gas: 97235) -PingPong_ccipReceive:test_CcipReceive_Success() (gas: 152765) +PingPong_ccipReceive:test_CcipReceive_Success() (gas: 150578) PingPong_plumbing:test_OutOfOrderExecution_Success() (gas: 20280) PingPong_plumbing:test_Pausing_Success() (gas: 17780) -PingPong_startPingPong:test_StartPingPong_With_OOO_Success() (gas: 163361) -PingPong_startPingPong:test_StartPingPong_With_Sequenced_Ordered_Success() (gas: 182770) +PingPong_startPingPong:test_StartPingPong_With_OOO_Success() (gas: 160987) +PingPong_startPingPong:test_StartPingPong_With_Sequenced_Ordered_Success() (gas: 180396) RMNHome:test() (gas: 186) RMN_constructor:test_Constructor_Success() (gas: 48874) RMN_getRecordedCurseRelatedOps:test_OpsPostDeployment() (gas: 19690) @@ -875,24 +875,24 @@ Router_applyRampUpdates:test_OffRampMismatch_Revert() (gas: 89306) Router_applyRampUpdates:test_OffRampUpdatesWithRouting() (gas: 10648972) Router_applyRampUpdates:test_OnRampDisable() (gas: 55971) Router_applyRampUpdates:test_OnlyOwner_Revert() (gas: 12317) -Router_ccipSend:test_CCIPSendLinkFeeNoTokenSuccess_gas() (gas: 114039) -Router_ccipSend:test_CCIPSendLinkFeeOneTokenSuccess_gas() (gas: 201534) -Router_ccipSend:test_CCIPSendNativeFeeNoTokenSuccess_gas() (gas: 128767) -Router_ccipSend:test_CCIPSendNativeFeeOneTokenSuccess_gas() (gas: 216264) -Router_ccipSend:test_FeeTokenAmountTooLow_Revert() (gas: 66368) +Router_ccipSend:test_CCIPSendLinkFeeNoTokenSuccess_gas() (gas: 113852) +Router_ccipSend:test_CCIPSendLinkFeeOneTokenSuccess_gas() (gas: 201347) +Router_ccipSend:test_CCIPSendNativeFeeNoTokenSuccess_gas() (gas: 126206) +Router_ccipSend:test_CCIPSendNativeFeeOneTokenSuccess_gas() (gas: 213703) +Router_ccipSend:test_FeeTokenAmountTooLow_Revert() (gas: 64181) Router_ccipSend:test_InvalidMsgValue() (gas: 32008) -Router_ccipSend:test_NativeFeeTokenInsufficientValue() (gas: 68827) -Router_ccipSend:test_NativeFeeTokenOverpay_Success() (gas: 173903) -Router_ccipSend:test_NativeFeeTokenZeroValue() (gas: 56109) -Router_ccipSend:test_NativeFeeToken_Success() (gas: 172497) -Router_ccipSend:test_NonLinkFeeToken_Success() (gas: 242837) +Router_ccipSend:test_NativeFeeTokenInsufficientValue() (gas: 66640) +Router_ccipSend:test_NativeFeeTokenOverpay_Success() (gas: 169155) +Router_ccipSend:test_NativeFeeTokenZeroValue() (gas: 53922) +Router_ccipSend:test_NativeFeeToken_Success() (gas: 167749) +Router_ccipSend:test_NonLinkFeeToken_Success() (gas: 238276) Router_ccipSend:test_UnsupportedDestinationChain_Revert() (gas: 24761) Router_ccipSend:test_WhenNotHealthy_Revert() (gas: 44736) -Router_ccipSend:test_WrappedNativeFeeToken_Success() (gas: 174755) -Router_ccipSend:test_ZeroFeeAndGasPrice_Success() (gas: 245046) +Router_ccipSend:test_WrappedNativeFeeToken_Success() (gas: 170007) +Router_ccipSend:test_ZeroFeeAndGasPrice_Success() (gas: 240298) Router_constructor:test_Constructor_Success() (gas: 13070) Router_getArmProxy:test_getArmProxy() (gas: 10561) -Router_getFee:test_GetFeeSupportedChain_Success() (gas: 46536) +Router_getFee:test_GetFeeSupportedChain_Success() (gas: 44349) Router_getFee:test_UnsupportedDestinationChain_Revert() (gas: 17144) Router_getSupportedTokens:test_GetSupportedTokens_Revert() (gas: 10460) Router_recoverTokens:test_RecoverTokensInvalidRecipient_Revert() (gas: 11316) @@ -907,7 +907,7 @@ Router_routeMessage:test_OnlyOffRamp_Revert() (gas: 25140) Router_routeMessage:test_WhenNotHealthy_Revert() (gas: 44742) Router_setWrappedNative:test_OnlyOwner_Revert() (gas: 10986) SelfFundedPingPong_ccipReceive:test_FundingIfNotANop_Revert() (gas: 55572) -SelfFundedPingPong_ccipReceive:test_Funding_Success() (gas: 420162) +SelfFundedPingPong_ccipReceive:test_Funding_Success() (gas: 417040) SelfFundedPingPong_setCountIncrBeforeFunding:test_setCountIncrBeforeFunding() (gas: 20169) TokenAdminRegistry_acceptAdminRole:test_acceptAdminRole_OnlyPendingAdministrator_Revert() (gas: 51109) TokenAdminRegistry_acceptAdminRole:test_acceptAdminRole_Success() (gas: 43956) @@ -935,8 +935,8 @@ TokenPoolAndProxy:test_lockOrBurn_burnMint_Success() (gas: 5945631) TokenPoolAndProxy:test_lockOrBurn_burnWithFromMint_Success() (gas: 5977107) TokenPoolAndProxy:test_lockOrBurn_lockRelease_Success() (gas: 6179838) TokenPoolAndProxy:test_setPreviousPool_Success() (gas: 3334200) -TokenPoolAndProxyMigration:test_tokenPoolMigration_Success_1_2() (gas: 6792268) -TokenPoolAndProxyMigration:test_tokenPoolMigration_Success_1_4() (gas: 7024950) +TokenPoolAndProxyMigration:test_tokenPoolMigration_Success_1_2() (gas: 6789707) +TokenPoolAndProxyMigration:test_tokenPoolMigration_Success_1_4() (gas: 7022389) TokenPoolWithAllowList_applyAllowListUpdates:test_AllowListNotEnabled_Revert() (gas: 2100002) TokenPoolWithAllowList_applyAllowListUpdates:test_OnlyOwner_Revert() (gas: 12101) TokenPoolWithAllowList_applyAllowListUpdates:test_SetAllowListSkipsZero_Success() (gas: 23464) @@ -965,16 +965,16 @@ TokenPool_setRemotePool:test_setRemotePool_NonExistentChain_Reverts() (gas: 1565 TokenPool_setRemotePool:test_setRemotePool_OnlyOwner_Reverts() (gas: 13201) TokenPool_setRemotePool:test_setRemotePool_Success() (gas: 282083) TokenProxy_ccipSend:test_CcipSendGasShouldBeZero_Revert() (gas: 17121) -TokenProxy_ccipSend:test_CcipSendInsufficientAllowance_Revert() (gas: 136330) +TokenProxy_ccipSend:test_CcipSendInsufficientAllowance_Revert() (gas: 134143) TokenProxy_ccipSend:test_CcipSendInvalidToken_Revert() (gas: 15931) -TokenProxy_ccipSend:test_CcipSendNative_Success() (gas: 245419) +TokenProxy_ccipSend:test_CcipSendNative_Success() (gas: 242858) TokenProxy_ccipSend:test_CcipSendNoDataAllowed_Revert() (gas: 16315) -TokenProxy_ccipSend:test_CcipSend_Success() (gas: 261760) +TokenProxy_ccipSend:test_CcipSend_Success() (gas: 261460) TokenProxy_constructor:test_Constructor() (gas: 13812) TokenProxy_getFee:test_GetFeeGasShouldBeZero_Revert() (gas: 16839) TokenProxy_getFee:test_GetFeeInvalidToken_Revert() (gas: 12670) TokenProxy_getFee:test_GetFeeNoDataAllowed_Revert() (gas: 15864) -TokenProxy_getFee:test_GetFee_Success() (gas: 86882) +TokenProxy_getFee:test_GetFee_Success() (gas: 84508) USDCTokenPool__validateMessage:test_ValidateInvalidMessage_Revert() (gas: 25407) USDCTokenPool_lockOrBurn:test_CallerIsNotARampOnRouter_Revert() (gas: 35364) USDCTokenPool_lockOrBurn:test_LockOrBurnWithAllowList_Revert() (gas: 30106) diff --git a/contracts/src/v0.8/ccip/FeeQuoter.sol b/contracts/src/v0.8/ccip/FeeQuoter.sol index aa6399d544..944498007f 100644 --- a/contracts/src/v0.8/ccip/FeeQuoter.sol +++ b/contracts/src/v0.8/ccip/FeeQuoter.sol @@ -232,11 +232,22 @@ contract FeeQuoter is AuthorizedCallers, IFeeQuoter, ITypeAndVersion, IReceiver, /// @inheritdoc IPriceRegistry function getTokenPrice(address token) public view override returns (Internal.TimestampedPackedUint224 memory) { + Internal.TimestampedPackedUint224 memory tokenPrice = s_usdPerToken[token]; + + // If the token price is not stale, return it + if (block.timestamp - tokenPrice.timestamp < i_stalenessThreshold) { + return tokenPrice; + } + IFeeQuoter.TokenPriceFeedConfig memory priceFeedConfig = s_usdPriceFeedsPerToken[token]; + + // If the token price feed is not set, return the stale price if (priceFeedConfig.dataFeedAddress == address(0)) { - return s_usdPerToken[token]; + return tokenPrice; } + // If the token price feed is set, return the price from the feed + // The price feed is the fallback because we do not expect it to be the default source due to the gas cost of reading from it return _getTokenPriceFromDataFeed(priceFeedConfig); } diff --git a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.t.sol b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.t.sol index f6dc8c25bf..a9c7679ac2 100644 --- a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.t.sol +++ b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.t.sol @@ -172,8 +172,8 @@ contract FeeQuoter_getTokenPrice is FeeQuoterSetup { function test_GetTokenPriceFromFeed_Success() public { uint256 originalTimestampValue = block.timestamp; - // Below staleness threshold - vm.warp(originalTimestampValue + 1 hours); + // Above staleness threshold + vm.warp(originalTimestampValue + s_feeQuoter.getStaticConfig().stalenessThreshold + 1); address sourceToken = _initialiseSingleTokenPriceFeed(); Internal.TimestampedPackedUint224 memory tokenPriceAnswer = s_feeQuoter.getTokenPrice(sourceToken); @@ -349,6 +349,13 @@ contract FeeQuoter_getValidatedTokenPrice is FeeQuoterSetup { function test_TokenNotSupportedFeed_Revert() public { address sourceToken = _initialiseSingleTokenPriceFeed(); MockV3Aggregator(s_dataFeedByToken[sourceToken]).updateAnswer(0); + Internal.PriceUpdates memory priceUpdates = Internal.PriceUpdates({ + tokenPriceUpdates: new Internal.TokenPriceUpdate[](1), + gasPriceUpdates: new Internal.GasPriceUpdate[](0) + }); + priceUpdates.tokenPriceUpdates[0] = Internal.TokenPriceUpdate({sourceToken: sourceToken, usdPerToken: 0}); + + s_feeQuoter.updatePrices(priceUpdates); vm.expectRevert(abi.encodeWithSelector(FeeQuoter.TokenNotSupported.selector, sourceToken)); s_feeQuoter.getValidatedTokenPrice(sourceToken); diff --git a/core/gethwrappers/ccip/generated/fee_quoter/fee_quoter.go b/core/gethwrappers/ccip/generated/fee_quoter/fee_quoter.go index e4c17b1886..8c7822c6c7 100644 --- a/core/gethwrappers/ccip/generated/fee_quoter/fee_quoter.go +++ b/core/gethwrappers/ccip/generated/fee_quoter/fee_quoter.go @@ -155,7 +155,7 @@ type KeystoneFeedsPermissionHandlerPermission struct { var FeeQuoterMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint96\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"linkToken\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"stalenessThreshold\",\"type\":\"uint32\"}],\"internalType\":\"structFeeQuoter.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"priceUpdaters\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"feeTokens\",\"type\":\"address[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"}],\"internalType\":\"structIFeeQuoter.TokenPriceFeedConfig\",\"name\":\"feedConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.TokenPriceFeedUpdate[]\",\"name\":\"tokenPriceFeeds\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigSingleTokenArgs[]\",\"name\":\"tokenTransferFeeConfigs\",\"type\":\"tuple[]\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigArgs[]\",\"name\":\"tokenTransferFeeConfigArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"internalType\":\"structFeeQuoter.PremiumMultiplierWeiPerEthArgs[]\",\"name\":\"premiumMultiplierWeiPerEthArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chain\",\"type\":\"uint64\"}],\"name\":\"ChainNotSupported\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DataFeedValueOutOfUint224Range\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"DestinationChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ExtraArgOutOfOrderExecutionMustBeTrue\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"FeeTokenNotSupported\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"}],\"name\":\"InvalidDestBytesOverhead\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidDestChainConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidEVMAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidExtraArgsTag\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidStaticConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"msgFeeJuels\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint256\"}],\"name\":\"MessageFeeTooHigh\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MessageGasLimitTooHigh\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"maxSize\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualSize\",\"type\":\"uint256\"}],\"name\":\"MessageTooLarge\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"internalType\":\"bytes10\",\"name\":\"workflowName\",\"type\":\"bytes10\"},{\"internalType\":\"bytes2\",\"name\":\"reportName\",\"type\":\"bytes2\"}],\"name\":\"ReportForwarderUnauthorized\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"SourceTokenDataTooLarge\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"threshold\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timePassed\",\"type\":\"uint256\"}],\"name\":\"StaleGasPrice\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feedTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"storedTimeStamp\",\"type\":\"uint256\"}],\"name\":\"StaleKeystoneUpdate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"TokenNotSupported\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"UnauthorizedCaller\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnsupportedNumberOfTokens\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"AuthorizedCallerAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"AuthorizedCallerRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"indexed\":false,\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"name\":\"DestChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"indexed\":false,\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"name\":\"DestChainConfigUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"}],\"name\":\"FeeTokenAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"}],\"name\":\"FeeTokenRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"name\":\"PremiumMultiplierWeiPerEthUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"}],\"indexed\":false,\"internalType\":\"structIFeeQuoter.TokenPriceFeedConfig\",\"name\":\"priceFeedConfig\",\"type\":\"tuple\"}],\"name\":\"PriceFeedPerTokenUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"reportId\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"},{\"internalType\":\"bytes10\",\"name\":\"workflowName\",\"type\":\"bytes10\"},{\"internalType\":\"bytes2\",\"name\":\"reportName\",\"type\":\"bytes2\"},{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isAllowed\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"structKeystoneFeedsPermissionHandler.Permission\",\"name\":\"permission\",\"type\":\"tuple\"}],\"name\":\"ReportPermissionSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"TokenTransferFeeConfigDeleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"name\":\"TokenTransferFeeConfigUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"UsdPerTokenUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChain\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"UsdPerUnitGasUpdated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"FEE_BASE_DECIMALS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"KEYSTONE_PRICE_DECIMALS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address[]\",\"name\":\"addedCallers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"removedCallers\",\"type\":\"address[]\"}],\"internalType\":\"structAuthorizedCallers.AuthorizedCallerArgs\",\"name\":\"authorizedCallerArgs\",\"type\":\"tuple\"}],\"name\":\"applyAuthorizedCallerUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyDestChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"feeTokensToAdd\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"feeTokensToRemove\",\"type\":\"address[]\"}],\"name\":\"applyFeeTokensUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"internalType\":\"structFeeQuoter.PremiumMultiplierWeiPerEthArgs[]\",\"name\":\"premiumMultiplierWeiPerEthArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyPremiumMultiplierWeiPerEthUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigSingleTokenArgs[]\",\"name\":\"tokenTransferFeeConfigs\",\"type\":\"tuple[]\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigArgs[]\",\"name\":\"tokenTransferFeeConfigArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigRemoveArgs[]\",\"name\":\"tokensToUseDefaultFeeConfigs\",\"type\":\"tuple[]\"}],\"name\":\"applyTokenTransferFeeConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"fromToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fromTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"toToken\",\"type\":\"address\"}],\"name\":\"convertTokenAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllAuthorizedCallers\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getDestChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getDestinationChainGasPrice\",\"outputs\":[{\"components\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"internalType\":\"structInternal.TimestampedPackedUint224\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getFeeTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getPremiumMultiplierWeiPerEth\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint96\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"linkToken\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"stalenessThreshold\",\"type\":\"uint32\"}],\"internalType\":\"structFeeQuoter.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getTokenAndGasPrices\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"tokenPrice\",\"type\":\"uint224\"},{\"internalType\":\"uint224\",\"name\":\"gasPriceValue\",\"type\":\"uint224\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenPrice\",\"outputs\":[{\"components\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"internalType\":\"structInternal.TimestampedPackedUint224\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenPriceFeedConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"}],\"internalType\":\"structIFeeQuoter.TokenPriceFeedConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"tokens\",\"type\":\"address[]\"}],\"name\":\"getTokenPrices\",\"outputs\":[{\"components\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"internalType\":\"structInternal.TimestampedPackedUint224[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenTransferFeeConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"getValidatedFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getValidatedTokenPrice\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"\",\"type\":\"uint224\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"onReport\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"name\":\"processMessageArgs\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"msgFeeJuels\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isOutOfOrderExecution\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"convertedExtraArgs\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"rampTokenAmounts\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"sourceTokenAmounts\",\"type\":\"tuple[]\"}],\"name\":\"processPoolReturnData\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"destExecDataPerToken\",\"type\":\"bytes[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"},{\"internalType\":\"bytes10\",\"name\":\"workflowName\",\"type\":\"bytes10\"},{\"internalType\":\"bytes2\",\"name\":\"reportName\",\"type\":\"bytes2\"},{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isAllowed\",\"type\":\"bool\"}],\"internalType\":\"structKeystoneFeedsPermissionHandler.Permission[]\",\"name\":\"permissions\",\"type\":\"tuple[]\"}],\"name\":\"setReportPermissions\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"}],\"name\":\"updatePrices\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"}],\"internalType\":\"structIFeeQuoter.TokenPriceFeedConfig\",\"name\":\"feedConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.TokenPriceFeedUpdate[]\",\"name\":\"tokenPriceFeedUpdates\",\"type\":\"tuple[]\"}],\"name\":\"updateTokenPriceFeeds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x60e06040523480156200001157600080fd5b506040516200775438038062007754833981016040819052620000349162001834565b8533806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf8162000207565b5050604080518082018252838152815160008152602080820190935291810191909152620000ee9150620002b2565b5060208701516001600160a01b0316158062000112575086516001600160601b0316155b80620001265750604087015163ffffffff16155b15620001455760405163d794ef9560e01b815260040160405180910390fd5b6020878101516001600160a01b031660a05287516001600160601b031660805260408089015163ffffffff1660c05280516000815291820190526200018c90869062000401565b620001978462000549565b620001a2816200061a565b620001ad8262000a5a565b60408051600080825260208201909252620001fa91859190620001f3565b6040805180820190915260008082526020820152815260200190600190039081620001cb5790505b5062000b26565b5050505050505062001ae5565b336001600160a01b03821603620002615760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b602081015160005b815181101562000342576000828281518110620002db57620002db62001953565b60209081029190910101519050620002f560028262000e5f565b1562000338576040516001600160a01b03821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b50600101620002ba565b50815160005b8151811015620003fb57600082828151811062000369576200036962001953565b6020026020010151905060006001600160a01b0316816001600160a01b031603620003a7576040516342bcdf7f60e11b815260040160405180910390fd5b620003b460028262000e7f565b506040516001600160a01b03821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a15060010162000348565b50505050565b60005b8251811015620004a2576200044083828151811062000427576200042762001953565b6020026020010151600b62000e7f60201b90919060201c565b1562000499578281815181106200045b576200045b62001953565b60200260200101516001600160a01b03167fdf1b1bd32a69711488d71554706bb130b1fc63a5fa1a2cd85e8440f84065ba2360405160405180910390a25b60010162000404565b5060005b81518110156200054457620004e2828281518110620004c957620004c962001953565b6020026020010151600b62000e9660201b90919060201c565b156200053b57818181518110620004fd57620004fd62001953565b60200260200101516001600160a01b03167f1795838dc8ab2ffc5f431a1729a6afa0b587f982f7b2be0b9d7187a1ef547f9160405160405180910390a25b600101620004a6565b505050565b60005b8151811015620006165760008282815181106200056d576200056d62001953565b6020908102919091018101518051818301516001600160a01b0380831660008181526007875260409081902084518154868a018051929096166001600160a81b03199091168117600160a01b60ff9384160217909255825191825293519093169683019690965293955091939092917f08a5f7f5bb38a81d8e43aca13ecd76431dbf8816ae4699affff7b00b2fc1c464910160405180910390a25050508060010190506200054c565b5050565b60005b8151811015620006165760008282815181106200063e576200063e62001953565b6020026020010151905060008383815181106200065f576200065f62001953565b6020026020010151600001519050600082602001519050816001600160401b03166000148062000698575061016081015163ffffffff16155b80620006ba57506101e08101516001600160e01b031916630a04b54b60e21b14155b80620006da5750806060015163ffffffff1681610160015163ffffffff16115b15620007055760405163c35aa79d60e01b81526001600160401b038316600482015260240162000083565b6001600160401b038216600090815260096020526040812060010154600160881b900460e01b6001600160e01b03191690036200078557816001600160401b03167fd31c671936387b2f84ed402b553bd50c0e9c20408ea4e91a836d77b8180fb7248260405162000777919062001969565b60405180910390a2620007c9565b816001600160401b03167f1edd6f3553cfa16f10b95b195abae3a1cfca4783de4843f95d674b1e1df5ab2082604051620007c0919062001969565b60405180910390a25b8060096000846001600160401b03166001600160401b0316815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548161ffff021916908361ffff16021790555060408201518160000160036101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160076101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600b6101000a81548163ffffffff021916908363ffffffff16021790555060a082015181600001600f6101000a81548161ffff021916908361ffff16021790555060c08201518160000160116101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160000160156101000a81548161ffff021916908361ffff1602179055506101008201518160000160176101000a81548161ffff021916908361ffff1602179055506101208201518160000160196101000a81548161ffff021916908361ffff16021790555061014082015181600001601b6101000a81548163ffffffff021916908363ffffffff1602179055506101608201518160010160006101000a81548163ffffffff021916908363ffffffff1602179055506101808201518160010160046101000a8154816001600160401b0302191690836001600160401b031602179055506101a082015181600101600c6101000a81548163ffffffff021916908363ffffffff1602179055506101c08201518160010160106101000a81548160ff0219169083151502179055506101e08201518160010160116101000a81548163ffffffff021916908360e01c02179055509050505050508060010190506200061d565b60005b81518110156200061657600082828151811062000a7e5762000a7e62001953565b6020026020010151600001519050600083838151811062000aa35762000aa362001953565b6020908102919091018101518101516001600160a01b03841660008181526008845260409081902080546001600160401b0319166001600160401b0385169081179091559051908152919350917fbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d910160405180910390a2505060010162000a5d565b60005b825181101562000d9957600083828151811062000b4a5762000b4a62001953565b6020026020010151905060008160000151905060005b82602001515181101562000d8a5760008360200151828151811062000b895762000b8962001953565b602002602001015160200151905060008460200151838151811062000bb25762000bb262001953565b6020026020010151600001519050602063ffffffff16826080015163ffffffff16101562000c115760808201516040516312766e0160e11b81526001600160a01b038316600482015263ffffffff909116602482015260440162000083565b6001600160401b0384166000818152600a602090815260408083206001600160a01b0386168085529083529281902086518154938801518389015160608a015160808b015160a08c01511515600160901b0260ff60901b1963ffffffff928316600160701b021664ffffffffff60701b199383166a01000000000000000000000263ffffffff60501b1961ffff90961668010000000000000000029590951665ffffffffffff60401b19968416640100000000026001600160401b0319909b16939097169290921798909817939093169390931717919091161792909217909155519091907f94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b59062000d77908690600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60405180910390a3505060010162000b60565b50505080600101905062000b29565b5060005b81518110156200054457600082828151811062000dbe5762000dbe62001953565b6020026020010151600001519050600083838151811062000de35762000de362001953565b6020908102919091018101518101516001600160401b0384166000818152600a845260408082206001600160a01b038516808452955280822080546001600160981b03191690555192945090917f4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b9190a3505060010162000d9d565b600062000e76836001600160a01b03841662000ead565b90505b92915050565b600062000e76836001600160a01b03841662000fb1565b600062000e76836001600160a01b03841662001003565b6000818152600183016020526040812054801562000fa657600062000ed460018362001aad565b855490915060009062000eea9060019062001aad565b905081811462000f5657600086600001828154811062000f0e5762000f0e62001953565b906000526020600020015490508087600001848154811062000f345762000f3462001953565b6000918252602080832090910192909255918252600188019052604090208390555b855486908062000f6a5762000f6a62001acf565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505062000e79565b600091505062000e79565b600081815260018301602052604081205462000ffa5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000e79565b50600062000e79565b6000818152600183016020526040812054801562000fa65760006200102a60018362001aad565b8554909150600090620010409060019062001aad565b905080821462000f5657600086600001828154811062000f0e5762000f0e62001953565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b03811182821017156200109f576200109f62001064565b60405290565b60405160c081016001600160401b03811182821017156200109f576200109f62001064565b60405161020081016001600160401b03811182821017156200109f576200109f62001064565b604051601f8201601f191681016001600160401b03811182821017156200111b576200111b62001064565b604052919050565b80516001600160a01b03811681146200113b57600080fd5b919050565b805163ffffffff811681146200113b57600080fd5b6000606082840312156200116857600080fd5b604051606081016001600160401b03811182821017156200118d576200118d62001064565b604052825190915081906001600160601b0381168114620011ad57600080fd5b8152620011bd6020840162001123565b6020820152620011d06040840162001140565b60408201525092915050565b60006001600160401b03821115620011f857620011f862001064565b5060051b60200190565b600082601f8301126200121457600080fd5b815160206200122d6200122783620011dc565b620010f0565b8083825260208201915060208460051b8701019350868411156200125057600080fd5b602086015b848110156200127757620012698162001123565b835291830191830162001255565b509695505050505050565b600082601f8301126200129457600080fd5b81516020620012a76200122783620011dc565b82815260609283028501820192828201919087851115620012c757600080fd5b8387015b858110156200135a5780890382811215620012e65760008081fd5b620012f06200107a565b620012fb8362001123565b8152604080601f1984011215620013125760008081fd5b6200131c6200107a565b92506200132b88850162001123565b835283015160ff81168114620013415760008081fd5b82880152808701919091528452928401928101620012cb565b5090979650505050505050565b80516001600160401b03811681146200113b57600080fd5b805161ffff811681146200113b57600080fd5b805180151581146200113b57600080fd5b600082601f830112620013b557600080fd5b81516020620013c86200122783620011dc565b82815260059290921b84018101918181019086841115620013e857600080fd5b8286015b84811015620012775780516001600160401b03808211156200140d57600080fd5b908801906040601f19838c0381018213156200142857600080fd5b620014326200107a565b6200143f89860162001367565b815282850151848111156200145357600080fd5b8086019550508c603f8601126200146957600080fd5b8885015193506200147e6200122785620011dc565b84815260e09094028501830193898101908e8611156200149d57600080fd5b958401955b858710156200157657868f0360e0811215620014bd57600080fd5b620014c76200107a565b620014d28962001123565b815260c08683011215620014e557600080fd5b620014ef620010a5565b9150620014fe8d8a0162001140565b82526200150d878a0162001140565b8d8301526200151f60608a016200137f565b878301526200153160808a0162001140565b60608301526200154460a08a0162001140565b60808301526200155760c08a0162001392565b60a0830152808d0191909152825260e09690960195908a0190620014a2565b828b015250875250505092840192508301620013ec565b600082601f8301126200159f57600080fd5b81516020620015b26200122783620011dc565b82815260069290921b84018101918181019086841115620015d257600080fd5b8286015b84811015620012775760408189031215620015f15760008081fd5b620015fb6200107a565b620016068262001123565b81526200161585830162001367565b81860152835291830191604001620015d6565b80516001600160e01b0319811681146200113b57600080fd5b600082601f8301126200165357600080fd5b81516020620016666200122783620011dc565b82815261022092830285018201928282019190878511156200168757600080fd5b8387015b858110156200135a5780890382811215620016a65760008081fd5b620016b06200107a565b620016bb8362001367565b815261020080601f1984011215620016d35760008081fd5b620016dd620010ca565b9250620016ec88850162001392565b83526040620016fd8186016200137f565b8985015260606200171081870162001140565b82860152608091506200172582870162001140565b9085015260a06200173886820162001140565b8286015260c091506200174d8287016200137f565b9085015260e06200176086820162001140565b828601526101009150620017768287016200137f565b908501526101206200178a8682016200137f565b828601526101409150620017a08287016200137f565b90850152610160620017b486820162001140565b828601526101809150620017ca82870162001140565b908501526101a0620017de86820162001367565b828601526101c09150620017f482870162001140565b908501526101e06200180886820162001392565b828601526200181983870162001628565b9085015250508087019190915284529284019281016200168b565b6000806000806000806000610120888a0312156200185157600080fd5b6200185d898962001155565b60608901519097506001600160401b03808211156200187b57600080fd5b620018898b838c0162001202565b975060808a0151915080821115620018a057600080fd5b620018ae8b838c0162001202565b965060a08a0151915080821115620018c557600080fd5b620018d38b838c0162001282565b955060c08a0151915080821115620018ea57600080fd5b620018f88b838c01620013a3565b945060e08a01519150808211156200190f57600080fd5b6200191d8b838c016200158d565b93506101008a01519150808211156200193557600080fd5b50620019448a828b0162001641565b91505092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b815115158152610200810160208301516200198a602084018261ffff169052565b506040830151620019a3604084018263ffffffff169052565b506060830151620019bc606084018263ffffffff169052565b506080830151620019d5608084018263ffffffff169052565b5060a0830151620019ec60a084018261ffff169052565b5060c083015162001a0560c084018263ffffffff169052565b5060e083015162001a1c60e084018261ffff169052565b506101008381015161ffff9081169184019190915261012080850151909116908301526101408084015163ffffffff9081169184019190915261016080850151821690840152610180808501516001600160401b0316908401526101a080850151909116908301526101c0808401511515908301526101e0928301516001600160e01b031916929091019190915290565b8181038181111562000e7957634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b60805160a05160c051615c1562001b3f6000396000818161030501528181612223015261228c0152600081816102c90152818161193d015261199d015260008181610295015281816119c60152611a360152615c156000f3fe608060405234801561001057600080fd5b50600436106101e45760003560e01c806379ba50971161010f578063bf78e03f116100a2578063d63d3af211610071578063d63d3af214610ab2578063d8694ccd14610aba578063f2fde38b14610acd578063ffdb4b3714610ae057600080fd5b8063bf78e03f146109c8578063c4276bfc14610a75578063cdc73d5114610a97578063d02641a014610a9f57600080fd5b80638da5cb5b116100de5780638da5cb5b1461096757806391a2749a1461098f5780639ea60026146109a2578063a69c64c0146109b557600080fd5b806379ba5097146107c95780637afac322146107d1578063805f2132146107e457806382b49eb0146107f757600080fd5b80633937306f116101875780634ab35b0b116101565780634ab35b0b1461045f578063514e8cff1461049f5780636def4ce714610542578063770e2dc4146107b657600080fd5b80633937306f14610404578063407e10861461041957806341ed29e71461042c57806345ac924d1461043f57600080fd5b8063085318f8116101c3578063085318f81461037e578063181f5a771461039e5780632451a627146103e7578063325c868e146103fc57600080fd5b806241e5be146101e9578063061877e31461020f57806306285c6914610268575b600080fd5b6101fc6101f73660046142e8565b610b28565b6040519081526020015b60405180910390f35b61024f61021d366004614324565b73ffffffffffffffffffffffffffffffffffffffff1660009081526008602052604090205467ffffffffffffffff1690565b60405167ffffffffffffffff9091168152602001610206565b610332604080516060810182526000808252602082018190529181019190915260405180606001604052807f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000063ffffffff16815250905090565b6040805182516bffffffffffffffffffffffff16815260208084015173ffffffffffffffffffffffffffffffffffffffff16908201529181015163ffffffff1690820152606001610206565b61039161038c36600461439c565b610b96565b60405161020691906144ae565b6103da6040518060400160405280601381526020017f46656551756f74657220312e362e302d6465760000000000000000000000000081525081565b6040516102069190614530565b6103ef610f08565b6040516102069190614543565b6101fc602481565b61041761041236600461459d565b610f19565b005b61041761042736600461473f565b6111ce565b61041761043a366004614871565b6111e2565b61045261044d3660046149ac565b611224565b60405161020691906149ee565b61047261046d366004614324565b6112ef565b6040517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff9091168152602001610206565b6105356104ad366004614a69565b60408051808201909152600080825260208201525067ffffffffffffffff166000908152600560209081526040918290208251808401909352547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811683527c0100000000000000000000000000000000000000000000000000000000900463ffffffff169082015290565b6040516102069190614a84565b6107a9610550366004614a69565b6040805161020081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a081018290526101c081018290526101e08101919091525067ffffffffffffffff908116600090815260096020908152604091829020825161020081018452815460ff8082161515835261ffff61010080840482169685019690965263ffffffff630100000084048116978501979097526701000000000000008304871660608501526b0100000000000000000000008304871660808501526f010000000000000000000000000000008304811660a085015271010000000000000000000000000000000000808404881660c086015275010000000000000000000000000000000000000000008404821660e08087019190915277010000000000000000000000000000000000000000000000850483169786019790975279010000000000000000000000000000000000000000000000000084049091166101208501527b01000000000000000000000000000000000000000000000000000000909204861661014084015260019093015480861661016084015264010000000081049096166101808301526c0100000000000000000000000086049094166101a0820152700100000000000000000000000000000000850490911615156101c08201527fffffffff0000000000000000000000000000000000000000000000000000000092909304901b166101e082015290565b6040516102069190614abf565b6104176107c4366004614cd6565b6112fa565b61041761130c565b6104176107df366004614ff0565b611409565b6104176107f2366004615096565b61141b565b610907610805366004615102565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101919091525067ffffffffffffffff919091166000908152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff94909416835292815290829020825160c081018452905463ffffffff8082168352640100000000820481169383019390935268010000000000000000810461ffff16938201939093526a01000000000000000000008304821660608201526e01000000000000000000000000000083049091166080820152720100000000000000000000000000000000000090910460ff16151560a082015290565b6040516102069190600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60005460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610206565b61041761099d36600461512c565b611903565b6104176109b03660046151ed565b611914565b6104176109c33660046153fa565b611925565b610a416109d6366004614324565b6040805180820182526000808252602091820181905273ffffffffffffffffffffffffffffffffffffffff93841681526007825282902082518084019093525492831682527401000000000000000000000000000000000000000090920460ff169181019190915290565b60408051825173ffffffffffffffffffffffffffffffffffffffff16815260209283015160ff169281019290925201610206565b610a88610a833660046154bf565b611936565b6040516102069392919061552e565b6103ef611b2c565b610535610aad366004614324565b611b38565b6101fc601281565b6101fc610ac836600461554f565b611c34565b610417610adb366004614324565b61213e565b610af3610aee3660046155a4565b61214f565b604080517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff938416815292909116602083015201610206565b6000610b33826122da565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16610b5a856122da565b610b82907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16856155fd565b610b8c9190615614565b90505b9392505050565b67ffffffffffffffff8086166000908152600960205260409020600101546060917101000000000000000000000000000000000090910460e01b908590811115610be257610be26145d8565b604051908082528060200260200182016040528015610c1557816020015b6060815260200190600190039081610c005790505b50915060005b85811015610efd576000858583818110610c3757610c3761564f565b610c4d9260206040909202019081019150614324565b90506000888884818110610c6357610c6361564f565b9050602002810190610c75919061567e565b610c839060408101906156bc565b9150506020811115610d385767ffffffffffffffff8a166000908152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff861684529091529020546e010000000000000000000000000000900463ffffffff16811115610d38576040517f36f536ca00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526024015b60405180910390fd5b610da8848a8a86818110610d4e57610d4e61564f565b9050602002810190610d60919061567e565b610d6e9060208101906156bc565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061237492505050565b67ffffffffffffffff8a166000818152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684528252808320815160c081018352905463ffffffff8082168352640100000000820481168386015268010000000000000000820461ffff16838501526a01000000000000000000008204811660608401526e010000000000000000000000000000820481166080840152720100000000000000000000000000000000000090910460ff16151560a08301908152958552600990935290832054935190937b0100000000000000000000000000000000000000000000000000000090049091169190610ea75781610ead565b82606001515b6040805163ffffffff8316602082015291925001604051602081830303815290604052888781518110610ee257610ee261564f565b60200260200101819052505050505050806001019050610c1b565b505095945050505050565b6060610f1460026123cb565b905090565b610f216123d8565b6000610f2d8280615721565b9050905060005b81811015611077576000610f488480615721565b83818110610f5857610f5861564f565b905060400201803603810190610f6e91906157b5565b604080518082018252602080840180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff908116845263ffffffff42818116858701908152885173ffffffffffffffffffffffffffffffffffffffff9081166000908152600690975295889020965190519092167c010000000000000000000000000000000000000000000000000000000002919092161790935584519051935194955016927f52f50aa6d1a95a4595361ecf953d095f125d442e4673716dede699e049de148a926110669290917bffffffffffffffffffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b60405180910390a250600101610f34565b5060006110876020840184615721565b9050905060005b818110156111c85760006110a56020860186615721565b838181106110b5576110b561564f565b9050604002018036038101906110cb91906157f2565b604080518082018252602080840180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff908116845263ffffffff42818116858701908152885167ffffffffffffffff9081166000908152600590975295889020965190519092167c010000000000000000000000000000000000000000000000000000000002919092161790935584519051935194955016927fdd84a3fa9ef9409f550d54d6affec7e9c480c878c6ab27b78912a03e1b371c6e926111b79290917bffffffffffffffffffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b60405180910390a25060010161108e565b50505050565b6111d661241d565b6111df8161249e565b50565b6111ea61241d565b60005b81518110156112205761121882828151811061120b5761120b61564f565b602002602001015161259c565b6001016111ed565b5050565b60608160008167ffffffffffffffff811115611242576112426145d8565b60405190808252806020026020018201604052801561128757816020015b60408051808201909152600080825260208201528152602001906001900390816112605790505b50905060005b828110156112e4576112bf8686838181106112aa576112aa61564f565b9050602002016020810190610aad9190614324565b8282815181106112d1576112d161564f565b602090810291909101015260010161128d565b509150505b92915050565b60006112e9826122da565b61130261241d565b611220828261276e565b60015473ffffffffffffffffffffffffffffffffffffffff16331461138d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610d2f565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b61141161241d565b6112208282612b7b565b600080600061145f87878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612cc292505050565b92509250925061147133838584612cdd565b600061147f85870187615815565b905060005b81518110156118f8576000600760008484815181106114a5576114a561564f565b6020908102919091018101515173ffffffffffffffffffffffffffffffffffffffff16825281019190915260400160009081205474010000000000000000000000000000000000000000900460ff1691508190036115665782828151811061150f5761150f61564f565b6020908102919091010151516040517f06439c6b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610d2f565b60006115af6012838686815181106115805761158061564f565b6020026020010151602001517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16612e35565b9050600660008585815181106115c7576115c761564f565b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001601c9054906101000a900463ffffffff1663ffffffff168484815181106116395761163961564f565b60200260200101516040015163ffffffff161015611743578383815181106116635761166361564f565b6020026020010151600001518484815181106116815761168161564f565b602002602001015160400151600660008787815181106116a3576116a361564f565b6020908102919091018101515173ffffffffffffffffffffffffffffffffffffffff90811683529082019290925260409081016000205490517f191ec70600000000000000000000000000000000000000000000000000000000815293909116600484015263ffffffff91821660248401527c01000000000000000000000000000000000000000000000000000000009004166044820152606401610d2f565b6040518060400160405280827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1681526020018585815181106117845761178461564f565b60200260200101516040015163ffffffff16815250600660008686815181106117af576117af61564f565b6020908102919091018101515173ffffffffffffffffffffffffffffffffffffffff168252818101929092526040016000208251929091015163ffffffff167c0100000000000000000000000000000000000000000000000000000000027bffffffffffffffffffffffffffffffffffffffffffffffffffffffff90921691909117905583518490849081106118475761184761564f565b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff167f52f50aa6d1a95a4595361ecf953d095f125d442e4673716dede699e049de148a8286868151811061189d5761189d61564f565b6020026020010151604001516040516118e69291907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff92909216825263ffffffff16602082015260400190565b60405180910390a25050600101611484565b505050505050505050565b61190b61241d565b6111df81612f01565b61191c61241d565b6111df8161308d565b61192d61241d565b6111df81613533565b60008060607f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff1603611996578592506119c4565b6119c187877f0000000000000000000000000000000000000000000000000000000000000000610b28565b92505b7f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff16831115611a63576040517f6a92a483000000000000000000000000000000000000000000000000000000008152600481018490526bffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166024820152604401610d2f565b67ffffffffffffffff881660009081526009602052604081206001015463ffffffff1690611a9287878461361d565b9050806020015193508484611b19836040805182516024820152602092830151151560448083019190915282518083039091018152606490910190915290810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f181dcf100000000000000000000000000000000000000000000000000000000017905290565b9450945094505050955095509592505050565b6060610f14600b6123cb565b604080518082019091526000808252602082015273ffffffffffffffffffffffffffffffffffffffff8281166000908152600760209081526040918290208251808401909352549283168083527401000000000000000000000000000000000000000090930460ff169082015290611c2b57505073ffffffffffffffffffffffffffffffffffffffff166000908152600660209081526040918290208251808401909352547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811683527c0100000000000000000000000000000000000000000000000000000000900463ffffffff169082015290565b610b8f816137c6565b67ffffffffffffffff8083166000908152600960209081526040808320815161020081018352815460ff808216151580845261ffff61010080850482169886019890985263ffffffff630100000085048116978601979097526701000000000000008404871660608601526b0100000000000000000000008404871660808601526f010000000000000000000000000000008404811660a086015271010000000000000000000000000000000000808504881660c087015275010000000000000000000000000000000000000000008504821660e08088019190915277010000000000000000000000000000000000000000000000860483169987019990995279010000000000000000000000000000000000000000000000000085049091166101208601527b01000000000000000000000000000000000000000000000000000000909304861661014085015260019094015480861661016085015264010000000081049098166101808401526c0100000000000000000000000088049094166101a0830152700100000000000000000000000000000000870490931615156101c08201527fffffffff000000000000000000000000000000000000000000000000000000009290950490921b166101e0840152909190611e4e576040517f99ac52f200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff85166004820152602401610d2f565b611e69611e616080850160608601614324565b600b90613955565b611ec857611e7d6080840160608501614324565b6040517f2502348c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610d2f565b6000611ed76040850185615721565b9150611f33905082611eec60208701876156bc565b905083611ef988806156bc565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061398492505050565b600080611f4f611f496080880160608901614324565b8861214f565b9092509050600080808515611f9257611f86878b611f7360808d0160608e01614324565b88611f8160408f018f615721565b613a2e565b91945092509050611fb2565b6101a0870151611faf9063ffffffff16662386f26fc100006155fd565b92505b61010087015160009061ffff1615611ff657611ff3886dffffffffffffffffffffffffffff607088901c16611fea60208e018e6156bc565b90508a86613d06565b90505b61018088015160009067ffffffffffffffff1661201f61201960808e018e6156bc565b8c613db6565b600001518563ffffffff168b60a0015161ffff168e806020019061204391906156bc565b61204e9291506155fd565b8c6080015163ffffffff1661206391906158dc565b61206d91906158dc565b61207791906158dc565b612091906dffffffffffffffffffffffffffff89166155fd565b61209b91906155fd565b9050867bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168282600860008f60600160208101906120d59190614324565b73ffffffffffffffffffffffffffffffffffffffff1681526020810191909152604001600020546121109067ffffffffffffffff16896155fd565b61211a91906158dc565b61212491906158dc565b61212e9190615614565b9c9b505050505050505050505050565b61214661241d565b6111df81613e77565b67ffffffffffffffff811660009081526005602090815260408083208151808301909252547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811682527c0100000000000000000000000000000000000000000000000000000000900463ffffffff1691810182905282918203612207576040517f2e59db3a00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff85166004820152602401610d2f565b6000816020015163ffffffff164261221f91906158ef565b90507f000000000000000000000000000000000000000000000000000000000000000063ffffffff168111156122c0576040517ff08bcb3e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8616600482015263ffffffff7f000000000000000000000000000000000000000000000000000000000000000016602482015260448101829052606401610d2f565b6122c9866122da565b9151919350909150505b9250929050565b6000806122e683611b38565b9050806020015163ffffffff166000148061231e575080517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16155b1561236d576040517f06439c6b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152602401610d2f565b5192915050565b7fd7ed2ad4000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831601611220576123c681613f6c565b505050565b60606000610b8f8361401f565b6123e3600233613955565b61241b576040517fd86ad9cf000000000000000000000000000000000000000000000000000000008152336004820152602401610d2f565b565b60005473ffffffffffffffffffffffffffffffffffffffff16331461241b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610d2f565b60005b81518110156112205760008282815181106124be576124be61564f565b60209081029190910181015180518183015173ffffffffffffffffffffffffffffffffffffffff80831660008181526007875260409081902084518154868a018051929096167fffffffffffffffffffffff00000000000000000000000000000000000000000090911681177401000000000000000000000000000000000000000060ff9384160217909255825191825293519093169683019690965293955091939092917f08a5f7f5bb38a81d8e43aca13ecd76431dbf8816ae4699affff7b00b2fc1c464910160405180910390a25050508060010190506124a1565b600061265582600001518360600151846020015185604001516040805173ffffffffffffffffffffffffffffffffffffffff80871660208301528516918101919091527fffffffffffffffffffff00000000000000000000000000000000000000000000831660608201527fffff0000000000000000000000000000000000000000000000000000000000008216608082015260009060a001604051602081830303815290604052805190602001209050949350505050565b60808301516000828152600460205260409081902080549215157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00909316929092179091555190915081907f32a4ba3fa3351b11ad555d4c8ec70a744e8705607077a946807030d64b6ab1a390612762908590600060a08201905073ffffffffffffffffffffffffffffffffffffffff8084511683527fffffffffffffffffffff0000000000000000000000000000000000000000000060208501511660208401527fffff00000000000000000000000000000000000000000000000000000000000060408501511660408401528060608501511660608401525060808301511515608083015292915050565b60405180910390a25050565b60005b8251811015612a9757600083828151811061278e5761278e61564f565b6020026020010151905060008160000151905060005b826020015151811015612a89576000836020015182815181106127c9576127c961564f565b60200260200101516020015190506000846020015183815181106127ef576127ef61564f565b6020026020010151600001519050602063ffffffff16826080015163ffffffff1610156128725760808201516040517f24ecdc0200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8316600482015263ffffffff9091166024820152604401610d2f565b67ffffffffffffffff84166000818152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff86168085529083529281902086518154938801518389015160608a015160808b015160a08c015115157201000000000000000000000000000000000000027fffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffff63ffffffff9283166e01000000000000000000000000000002167fffffffffffffffffffffffffff0000000000ffffffffffffffffffffffffffff9383166a0100000000000000000000027fffffffffffffffffffffffffffffffffffff00000000ffffffffffffffffffff61ffff9096166801000000000000000002959095167fffffffffffffffffffffffffffffffffffff000000000000ffffffffffffffff968416640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000909b16939097169290921798909817939093169390931717919091161792909217909155519091907f94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b590612a77908690600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60405180910390a350506001016127a4565b505050806001019050612771565b5060005b81518110156123c6576000828281518110612ab857612ab861564f565b60200260200101516000015190506000838381518110612ada57612ada61564f565b60209081029190910181015181015167ffffffffffffffff84166000818152600a8452604080822073ffffffffffffffffffffffffffffffffffffffff8516808452955280822080547fffffffffffffffffffffffffff000000000000000000000000000000000000001690555192945090917f4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b9190a35050600101612a9b565b60005b8251811015612c1e57612bb4838281518110612b9c57612b9c61564f565b6020026020010151600b61407b90919063ffffffff16565b15612c1657828181518110612bcb57612bcb61564f565b602002602001015173ffffffffffffffffffffffffffffffffffffffff167fdf1b1bd32a69711488d71554706bb130b1fc63a5fa1a2cd85e8440f84065ba2360405160405180910390a25b600101612b7e565b5060005b81518110156123c657612c58828281518110612c4057612c4061564f565b6020026020010151600b61409d90919063ffffffff16565b15612cba57818181518110612c6f57612c6f61564f565b602002602001015173ffffffffffffffffffffffffffffffffffffffff167f1795838dc8ab2ffc5f431a1729a6afa0b587f982f7b2be0b9d7187a1ef547f9160405160405180910390a25b600101612c22565b6040810151604a820151605e90920151909260609290921c91565b6040805173ffffffffffffffffffffffffffffffffffffffff868116602080840191909152908616828401527fffffffffffffffffffff00000000000000000000000000000000000000000000851660608301527fffff00000000000000000000000000000000000000000000000000000000000084166080808401919091528351808403909101815260a09092018352815191810191909120600081815260049092529190205460ff16612e2e576040517f097e17ff00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8087166004830152851660248201527fffffffffffffffffffff00000000000000000000000000000000000000000000841660448201527fffff00000000000000000000000000000000000000000000000000000000000083166064820152608401610d2f565b5050505050565b600080612e428486615902565b9050600060248260ff161115612e7c57612e60602460ff84166158ef565b612e6b90600a615a3b565b612e759085615614565b9050612ea2565b612e8a60ff831660246158ef565b612e9590600a615a3b565b612e9f90856155fd565b90505b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811115612ef8576040517f10cb51d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b95945050505050565b602081015160005b8151811015612f9c576000828281518110612f2657612f2661564f565b60200260200101519050612f448160026140bf90919063ffffffff16565b15612f935760405173ffffffffffffffffffffffffffffffffffffffff821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b50600101612f09565b50815160005b81518110156111c8576000828281518110612fbf57612fbf61564f565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff160361302f576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61303a60028261407b565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a150600101612fa2565b60005b81518110156112205760008282815181106130ad576130ad61564f565b6020026020010151905060008383815181106130cb576130cb61564f565b60200260200101516000015190506000826020015190508167ffffffffffffffff1660001480613104575061016081015163ffffffff16155b8061315657506101e08101517fffffffff00000000000000000000000000000000000000000000000000000000167f2812d52c0000000000000000000000000000000000000000000000000000000014155b806131755750806060015163ffffffff1681610160015163ffffffff16115b156131b8576040517fc35aa79d00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff83166004820152602401610d2f565b67ffffffffffffffff821660009081526009602052604081206001015471010000000000000000000000000000000000900460e01b7fffffffff0000000000000000000000000000000000000000000000000000000016900361325c578167ffffffffffffffff167fd31c671936387b2f84ed402b553bd50c0e9c20408ea4e91a836d77b8180fb7248260405161324f9190614abf565b60405180910390a261329f565b8167ffffffffffffffff167f1edd6f3553cfa16f10b95b195abae3a1cfca4783de4843f95d674b1e1df5ab20826040516132969190614abf565b60405180910390a25b80600960008467ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548161ffff021916908361ffff16021790555060408201518160000160036101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160076101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600b6101000a81548163ffffffff021916908363ffffffff16021790555060a082015181600001600f6101000a81548161ffff021916908361ffff16021790555060c08201518160000160116101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160000160156101000a81548161ffff021916908361ffff1602179055506101008201518160000160176101000a81548161ffff021916908361ffff1602179055506101208201518160000160196101000a81548161ffff021916908361ffff16021790555061014082015181600001601b6101000a81548163ffffffff021916908363ffffffff1602179055506101608201518160010160006101000a81548163ffffffff021916908363ffffffff1602179055506101808201518160010160046101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506101a082015181600101600c6101000a81548163ffffffff021916908363ffffffff1602179055506101c08201518160010160106101000a81548160ff0219169083151502179055506101e08201518160010160116101000a81548163ffffffff021916908360e01c0217905550905050505050806001019050613090565b60005b81518110156112205760008282815181106135535761355361564f565b602002602001015160000151905060008383815181106135755761357561564f565b60209081029190910181015181015173ffffffffffffffffffffffffffffffffffffffff841660008181526008845260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff85169081179091559051908152919350917fbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d910160405180910390a25050600101613536565b6040805180820190915260008082526020820152600083900361365e57506040805180820190915267ffffffffffffffff8216815260006020820152610b8f565b600061366a8486615a47565b9050600061367b8560048189615a8d565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505050507fffffffff0000000000000000000000000000000000000000000000000000000082167fe7e230f00000000000000000000000000000000000000000000000000000000001613718578080602001905181019061370f9190615ab7565b92505050610b8f565b7f6859a837000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831601613794576040518060400160405280828060200190518101906137809190615ae3565b815260006020909101529250610b8f915050565b6040517f5247fdce00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080518082019091526000808252602082015260008260000151905060008173ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015613830573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138549190615b16565b5050509150506000811215613895576040517f10cb51d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006139148373ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156138e5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139099190615b66565b866020015184612e35565b604080518082019091527bffffffffffffffffffffffffffffffffffffffffffffffffffffffff909116815263ffffffff4216602082015295945050505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515610b8f565b836040015163ffffffff168311156139dd5760408085015190517f8693378900000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015260248101849052604401610d2f565b836020015161ffff16821115613a1f576040517f4c056b6a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6111c8846101e0015182612374565b6000808083815b81811015613cf8576000878783818110613a5157613a5161564f565b905060400201803603810190613a679190615b83565b67ffffffffffffffff8c166000908152600a60209081526040808320845173ffffffffffffffffffffffffffffffffffffffff168452825291829020825160c081018452905463ffffffff8082168352640100000000820481169383019390935268010000000000000000810461ffff16938201939093526a01000000000000000000008304821660608201526e01000000000000000000000000000083049091166080820152720100000000000000000000000000000000000090910460ff16151560a0820181905291925090613b87576101208d0151613b549061ffff16662386f26fc100006155fd565b613b5e90886158dc565b96508c610140015186613b719190615bbc565b9550613b7e602086615bbc565b94505050613cf0565b604081015160009061ffff1615613c405760008c73ffffffffffffffffffffffffffffffffffffffff16846000015173ffffffffffffffffffffffffffffffffffffffff1614613be3578351613bdc906122da565b9050613be6565b508a5b620186a0836040015161ffff16613c288660200151847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166140e190919063ffffffff16565b613c3291906155fd565b613c3c9190615614565b9150505b6060820151613c4f9088615bbc565b9650816080015186613c619190615bbc565b8251909650600090613c809063ffffffff16662386f26fc100006155fd565b905080821015613c9f57613c94818a6158dc565b985050505050613cf0565b6000836020015163ffffffff16662386f26fc10000613cbe91906155fd565b905080831115613cde57613cd2818b6158dc565b99505050505050613cf0565b613ce8838b6158dc565b995050505050505b600101613a35565b505096509650969350505050565b60008063ffffffff8316613d1c610160866155fd565b613d28876101c06158dc565b613d3291906158dc565b613d3c91906158dc565b905060008760c0015163ffffffff168860e0015161ffff1683613d5f91906155fd565b613d6991906158dc565b61010089015190915061ffff16613d906dffffffffffffffffffffffffffff8916836155fd565b613d9a91906155fd565b613daa90655af3107a40006155fd565b98975050505050505050565b60408051808201909152600080825260208201526000613de2858585610160015163ffffffff1661361d565b9050826060015163ffffffff1681600001511115613e2c576040517f4c4fc93a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b826101c001518015613e4057508060200151155b15610b8c576040517fee433e9900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff821603613ef6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610d2f565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60008151602014613fab57816040517f8d666f60000000000000000000000000000000000000000000000000000000008152600401610d2f9190614530565b600082806020019051810190613fc19190615ae3565b905073ffffffffffffffffffffffffffffffffffffffff811180613fe6575061040081105b156112e957826040517f8d666f60000000000000000000000000000000000000000000000000000000008152600401610d2f9190614530565b60608160000180548060200260200160405190810160405280929190818152602001828054801561406f57602002820191906000526020600020905b81548152602001906001019080831161405b575b50505050509050919050565b6000610b8f8373ffffffffffffffffffffffffffffffffffffffff841661411e565b6000610b8f8373ffffffffffffffffffffffffffffffffffffffff841661416d565b6000610b8f8373ffffffffffffffffffffffffffffffffffffffff8416614267565b6000670de0b6b3a7640000614114837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff86166155fd565b610b8f9190615614565b6000818152600183016020526040812054614165575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556112e9565b5060006112e9565b600081815260018301602052604081205480156142565760006141916001836158ef565b85549091506000906141a5906001906158ef565b905080821461420a5760008660000182815481106141c5576141c561564f565b90600052602060002001549050808760000184815481106141e8576141e861564f565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061421b5761421b615bd9565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506112e9565b60009150506112e9565b5092915050565b6000818152600183016020526040812054801561425657600061428b6001836158ef565b855490915060009061429f906001906158ef565b905081811461420a5760008660000182815481106141c5576141c561564f565b803573ffffffffffffffffffffffffffffffffffffffff811681146142e357600080fd5b919050565b6000806000606084860312156142fd57600080fd5b614306846142bf565b92506020840135915061431b604085016142bf565b90509250925092565b60006020828403121561433657600080fd5b610b8f826142bf565b803567ffffffffffffffff811681146142e357600080fd5b60008083601f84011261436957600080fd5b50813567ffffffffffffffff81111561438157600080fd5b6020830191508360208260051b85010111156122d357600080fd5b6000806000806000606086880312156143b457600080fd5b6143bd8661433f565b9450602086013567ffffffffffffffff808211156143da57600080fd5b6143e689838a01614357565b909650945060408801359150808211156143ff57600080fd5b818801915088601f83011261441357600080fd5b81358181111561442257600080fd5b8960208260061b850101111561443757600080fd5b9699959850939650602001949392505050565b6000815180845260005b8181101561447057602081850181015186830182015201614454565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b82811015614523577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc088860301845261451185835161444a565b945092850192908501906001016144d7565b5092979650505050505050565b602081526000610b8f602083018461444a565b6020808252825182820181905260009190848201906040850190845b8181101561459157835173ffffffffffffffffffffffffffffffffffffffff168352928401929184019160010161455f565b50909695505050505050565b6000602082840312156145af57600080fd5b813567ffffffffffffffff8111156145c657600080fd5b820160408185031215610b8f57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561462a5761462a6145d8565b60405290565b60405160a0810167ffffffffffffffff8111828210171561462a5761462a6145d8565b60405160c0810167ffffffffffffffff8111828210171561462a5761462a6145d8565b604051610200810167ffffffffffffffff8111828210171561462a5761462a6145d8565b6040516060810167ffffffffffffffff8111828210171561462a5761462a6145d8565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715614704576147046145d8565b604052919050565b600067ffffffffffffffff821115614726576147266145d8565b5060051b60200190565b60ff811681146111df57600080fd5b6000602080838503121561475257600080fd5b823567ffffffffffffffff81111561476957600080fd5b8301601f8101851361477a57600080fd5b803561478d6147888261470c565b6146bd565b818152606091820283018401918482019190888411156147ac57600080fd5b938501935b8385101561484c57848903818112156147ca5760008081fd5b6147d2614607565b6147db876142bf565b81526040807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08401121561480f5760008081fd5b614817614607565b92506148248989016142bf565b835287013561483281614730565b8289015280880191909152835293840193918501916147b1565b50979650505050505050565b80151581146111df57600080fd5b80356142e381614858565b6000602080838503121561488457600080fd5b823567ffffffffffffffff81111561489b57600080fd5b8301601f810185136148ac57600080fd5b80356148ba6147888261470c565b81815260a091820283018401918482019190888411156148d957600080fd5b938501935b8385101561484c5780858a0312156148f65760008081fd5b6148fe614630565b614907866142bf565b8152868601357fffffffffffffffffffff000000000000000000000000000000000000000000008116811461493c5760008081fd5b818801526040868101357fffff000000000000000000000000000000000000000000000000000000000000811681146149755760008081fd5b9082015260606149868782016142bf565b9082015260808681013561499981614858565b90820152835293840193918501916148de565b600080602083850312156149bf57600080fd5b823567ffffffffffffffff8111156149d657600080fd5b6149e285828601614357565b90969095509350505050565b602080825282518282018190526000919060409081850190868401855b82811015614a5c57614a4c84835180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16825260209081015163ffffffff16910152565b9284019290850190600101614a0b565b5091979650505050505050565b600060208284031215614a7b57600080fd5b610b8f8261433f565b81517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16815260208083015163ffffffff1690820152604081016112e9565b81511515815261020081016020830151614adf602084018261ffff169052565b506040830151614af7604084018263ffffffff169052565b506060830151614b0f606084018263ffffffff169052565b506080830151614b27608084018263ffffffff169052565b5060a0830151614b3d60a084018261ffff169052565b5060c0830151614b5560c084018263ffffffff169052565b5060e0830151614b6b60e084018261ffff169052565b506101008381015161ffff9081169184019190915261012080850151909116908301526101408084015163ffffffff90811691840191909152610160808501518216908401526101808085015167ffffffffffffffff16908401526101a080850151909116908301526101c0808401511515908301526101e0808401517fffffffff000000000000000000000000000000000000000000000000000000008116828501525b505092915050565b803563ffffffff811681146142e357600080fd5b803561ffff811681146142e357600080fd5b600082601f830112614c4f57600080fd5b81356020614c5f6147888361470c565b82815260069290921b84018101918181019086841115614c7e57600080fd5b8286015b84811015614ccb5760408189031215614c9b5760008081fd5b614ca3614607565b614cac8261433f565b8152614cb98583016142bf565b81860152835291830191604001614c82565b509695505050505050565b60008060408385031215614ce957600080fd5b67ffffffffffffffff83351115614cff57600080fd5b83601f843585010112614d1157600080fd5b614d21614788843585013561470c565b8335840180358083526020808401939260059290921b90910101861015614d4757600080fd5b602085358601015b85358601803560051b01602001811015614f545767ffffffffffffffff81351115614d7957600080fd5b8035863587010160407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0828a03011215614db257600080fd5b614dba614607565b614dc66020830161433f565b815267ffffffffffffffff60408301351115614de157600080fd5b88603f604084013584010112614df657600080fd5b614e0c614788602060408501358501013561470c565b6020604084810135850182810135808552928401939260e00201018b1015614e3357600080fd5b6040808501358501015b6040858101358601602081013560e0020101811015614f355760e0818d031215614e6657600080fd5b614e6e614607565b614e77826142bf565b815260c07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0838f03011215614eab57600080fd5b614eb3614653565b614ebf60208401614c18565b8152614ecd60408401614c18565b6020820152614ede60608401614c2c565b6040820152614eef60808401614c18565b6060820152614f0060a08401614c18565b6080820152614f1260c0840135614858565b60c083013560a0820152602082810191909152908452929092019160e001614e3d565b5080602084015250508085525050602083019250602081019050614d4f565b5092505067ffffffffffffffff60208401351115614f7157600080fd5b614f818460208501358501614c3e565b90509250929050565b600082601f830112614f9b57600080fd5b81356020614fab6147888361470c565b8083825260208201915060208460051b870101935086841115614fcd57600080fd5b602086015b84811015614ccb57614fe3816142bf565b8352918301918301614fd2565b6000806040838503121561500357600080fd5b823567ffffffffffffffff8082111561501b57600080fd5b61502786838701614f8a565b9350602085013591508082111561503d57600080fd5b5061504a85828601614f8a565b9150509250929050565b60008083601f84011261506657600080fd5b50813567ffffffffffffffff81111561507e57600080fd5b6020830191508360208285010111156122d357600080fd5b600080600080604085870312156150ac57600080fd5b843567ffffffffffffffff808211156150c457600080fd5b6150d088838901615054565b909650945060208701359150808211156150e957600080fd5b506150f687828801615054565b95989497509550505050565b6000806040838503121561511557600080fd5b61511e8361433f565b9150614f81602084016142bf565b60006020828403121561513e57600080fd5b813567ffffffffffffffff8082111561515657600080fd5b908301906040828603121561516a57600080fd5b615172614607565b82358281111561518157600080fd5b61518d87828601614f8a565b8252506020830135828111156151a257600080fd5b6151ae87828601614f8a565b60208301525095945050505050565b80357fffffffff00000000000000000000000000000000000000000000000000000000811681146142e357600080fd5b6000602080838503121561520057600080fd5b823567ffffffffffffffff81111561521757600080fd5b8301601f8101851361522857600080fd5b80356152366147888261470c565b818152610220918202830184019184820191908884111561525657600080fd5b938501935b8385101561484c57848903818112156152745760008081fd5b61527c614607565b6152858761433f565b8152610200807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0840112156152ba5760008081fd5b6152c2614676565b92506152cf898901614866565b835260406152de818a01614c2c565b8a85015260606152ef818b01614c18565b8286015260809150615302828b01614c18565b9085015260a06153138a8201614c18565b8286015260c09150615326828b01614c2c565b9085015260e06153378a8201614c18565b82860152610100915061534b828b01614c2c565b9085015261012061535d8a8201614c2c565b828601526101409150615371828b01614c2c565b908501526101606153838a8201614c18565b828601526101809150615397828b01614c18565b908501526101a06153a98a820161433f565b828601526101c091506153bd828b01614c18565b908501526101e06153cf8a8201614866565b828601526153de838b016151bd565b908501525050808801919091528352938401939185019161525b565b6000602080838503121561540d57600080fd5b823567ffffffffffffffff81111561542457600080fd5b8301601f8101851361543557600080fd5b80356154436147888261470c565b81815260069190911b8201830190838101908783111561546257600080fd5b928401925b828410156154b457604084890312156154805760008081fd5b615488614607565b615491856142bf565b815261549e86860161433f565b8187015282526040939093019290840190615467565b979650505050505050565b6000806000806000608086880312156154d757600080fd5b6154e08661433f565b94506154ee602087016142bf565b935060408601359250606086013567ffffffffffffffff81111561551157600080fd5b61551d88828901615054565b969995985093965092949392505050565b8381528215156020820152606060408201526000612ef8606083018461444a565b6000806040838503121561556257600080fd5b61556b8361433f565b9150602083013567ffffffffffffffff81111561558757600080fd5b830160a0818603121561559957600080fd5b809150509250929050565b600080604083850312156155b757600080fd5b6155c0836142bf565b9150614f816020840161433f565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80820281158282048414176112e9576112e96155ce565b60008261564a577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff618336030181126156b257600080fd5b9190910192915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126156f157600080fd5b83018035915067ffffffffffffffff82111561570c57600080fd5b6020019150368190038213156122d357600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261575657600080fd5b83018035915067ffffffffffffffff82111561577157600080fd5b6020019150600681901b36038213156122d357600080fd5b80357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811681146142e357600080fd5b6000604082840312156157c757600080fd5b6157cf614607565b6157d8836142bf565b81526157e660208401615789565b60208201529392505050565b60006040828403121561580457600080fd5b61580c614607565b6157d88361433f565b6000602080838503121561582857600080fd5b823567ffffffffffffffff81111561583f57600080fd5b8301601f8101851361585057600080fd5b803561585e6147888261470c565b8181526060918202830184019184820191908884111561587d57600080fd5b938501935b8385101561484c5780858a03121561589a5760008081fd5b6158a261469a565b6158ab866142bf565b81526158b8878701615789565b8782015260406158c9818801614c18565b9082015283529384019391850191615882565b808201808211156112e9576112e96155ce565b818103818111156112e9576112e96155ce565b60ff81811683821601908111156112e9576112e96155ce565b600181815b8085111561597457817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561595a5761595a6155ce565b8085161561596757918102915b93841c9390800290615920565b509250929050565b60008261598b575060016112e9565b81615998575060006112e9565b81600181146159ae57600281146159b8576159d4565b60019150506112e9565b60ff8411156159c9576159c96155ce565b50506001821b6112e9565b5060208310610133831016604e8410600b84101617156159f7575081810a6112e9565b615a01838361591b565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115615a3357615a336155ce565b029392505050565b6000610b8f838361597c565b7fffffffff000000000000000000000000000000000000000000000000000000008135818116916004851015614c105760049490940360031b84901b1690921692915050565b60008085851115615a9d57600080fd5b83861115615aaa57600080fd5b5050820193919092039150565b600060408284031215615ac957600080fd5b615ad1614607565b8251815260208301516157e681614858565b600060208284031215615af557600080fd5b5051919050565b805169ffffffffffffffffffff811681146142e357600080fd5b600080600080600060a08688031215615b2e57600080fd5b615b3786615afc565b9450602086015193506040860151925060608601519150615b5a60808701615afc565b90509295509295909350565b600060208284031215615b7857600080fd5b8151610b8f81614730565b600060408284031215615b9557600080fd5b615b9d614607565b615ba6836142bf565b8152602083013560208201528091505092915050565b63ffffffff818116838216019080821115614260576142606155ce565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea164736f6c6343000818000a", + Bin: "0x60e06040523480156200001157600080fd5b50604051620077a3380380620077a3833981016040819052620000349162001834565b8533806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf8162000207565b5050604080518082018252838152815160008152602080820190935291810191909152620000ee9150620002b2565b5060208701516001600160a01b0316158062000112575086516001600160601b0316155b80620001265750604087015163ffffffff16155b15620001455760405163d794ef9560e01b815260040160405180910390fd5b6020878101516001600160a01b031660a05287516001600160601b031660805260408089015163ffffffff1660c05280516000815291820190526200018c90869062000401565b620001978462000549565b620001a2816200061a565b620001ad8262000a5a565b60408051600080825260208201909252620001fa91859190620001f3565b6040805180820190915260008082526020820152815260200190600190039081620001cb5790505b5062000b26565b5050505050505062001ae5565b336001600160a01b03821603620002615760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b602081015160005b815181101562000342576000828281518110620002db57620002db62001953565b60209081029190910101519050620002f560028262000e5f565b1562000338576040516001600160a01b03821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b50600101620002ba565b50815160005b8151811015620003fb57600082828151811062000369576200036962001953565b6020026020010151905060006001600160a01b0316816001600160a01b031603620003a7576040516342bcdf7f60e11b815260040160405180910390fd5b620003b460028262000e7f565b506040516001600160a01b03821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a15060010162000348565b50505050565b60005b8251811015620004a2576200044083828151811062000427576200042762001953565b6020026020010151600b62000e7f60201b90919060201c565b1562000499578281815181106200045b576200045b62001953565b60200260200101516001600160a01b03167fdf1b1bd32a69711488d71554706bb130b1fc63a5fa1a2cd85e8440f84065ba2360405160405180910390a25b60010162000404565b5060005b81518110156200054457620004e2828281518110620004c957620004c962001953565b6020026020010151600b62000e9660201b90919060201c565b156200053b57818181518110620004fd57620004fd62001953565b60200260200101516001600160a01b03167f1795838dc8ab2ffc5f431a1729a6afa0b587f982f7b2be0b9d7187a1ef547f9160405160405180910390a25b600101620004a6565b505050565b60005b8151811015620006165760008282815181106200056d576200056d62001953565b6020908102919091018101518051818301516001600160a01b0380831660008181526007875260409081902084518154868a018051929096166001600160a81b03199091168117600160a01b60ff9384160217909255825191825293519093169683019690965293955091939092917f08a5f7f5bb38a81d8e43aca13ecd76431dbf8816ae4699affff7b00b2fc1c464910160405180910390a25050508060010190506200054c565b5050565b60005b8151811015620006165760008282815181106200063e576200063e62001953565b6020026020010151905060008383815181106200065f576200065f62001953565b6020026020010151600001519050600082602001519050816001600160401b03166000148062000698575061016081015163ffffffff16155b80620006ba57506101e08101516001600160e01b031916630a04b54b60e21b14155b80620006da5750806060015163ffffffff1681610160015163ffffffff16115b15620007055760405163c35aa79d60e01b81526001600160401b038316600482015260240162000083565b6001600160401b038216600090815260096020526040812060010154600160881b900460e01b6001600160e01b03191690036200078557816001600160401b03167fd31c671936387b2f84ed402b553bd50c0e9c20408ea4e91a836d77b8180fb7248260405162000777919062001969565b60405180910390a2620007c9565b816001600160401b03167f1edd6f3553cfa16f10b95b195abae3a1cfca4783de4843f95d674b1e1df5ab2082604051620007c0919062001969565b60405180910390a25b8060096000846001600160401b03166001600160401b0316815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548161ffff021916908361ffff16021790555060408201518160000160036101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160076101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600b6101000a81548163ffffffff021916908363ffffffff16021790555060a082015181600001600f6101000a81548161ffff021916908361ffff16021790555060c08201518160000160116101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160000160156101000a81548161ffff021916908361ffff1602179055506101008201518160000160176101000a81548161ffff021916908361ffff1602179055506101208201518160000160196101000a81548161ffff021916908361ffff16021790555061014082015181600001601b6101000a81548163ffffffff021916908363ffffffff1602179055506101608201518160010160006101000a81548163ffffffff021916908363ffffffff1602179055506101808201518160010160046101000a8154816001600160401b0302191690836001600160401b031602179055506101a082015181600101600c6101000a81548163ffffffff021916908363ffffffff1602179055506101c08201518160010160106101000a81548160ff0219169083151502179055506101e08201518160010160116101000a81548163ffffffff021916908360e01c02179055509050505050508060010190506200061d565b60005b81518110156200061657600082828151811062000a7e5762000a7e62001953565b6020026020010151600001519050600083838151811062000aa35762000aa362001953565b6020908102919091018101518101516001600160a01b03841660008181526008845260409081902080546001600160401b0319166001600160401b0385169081179091559051908152919350917fbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d910160405180910390a2505060010162000a5d565b60005b825181101562000d9957600083828151811062000b4a5762000b4a62001953565b6020026020010151905060008160000151905060005b82602001515181101562000d8a5760008360200151828151811062000b895762000b8962001953565b602002602001015160200151905060008460200151838151811062000bb25762000bb262001953565b6020026020010151600001519050602063ffffffff16826080015163ffffffff16101562000c115760808201516040516312766e0160e11b81526001600160a01b038316600482015263ffffffff909116602482015260440162000083565b6001600160401b0384166000818152600a602090815260408083206001600160a01b0386168085529083529281902086518154938801518389015160608a015160808b015160a08c01511515600160901b0260ff60901b1963ffffffff928316600160701b021664ffffffffff60701b199383166a01000000000000000000000263ffffffff60501b1961ffff90961668010000000000000000029590951665ffffffffffff60401b19968416640100000000026001600160401b0319909b16939097169290921798909817939093169390931717919091161792909217909155519091907f94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b59062000d77908690600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60405180910390a3505060010162000b60565b50505080600101905062000b29565b5060005b81518110156200054457600082828151811062000dbe5762000dbe62001953565b6020026020010151600001519050600083838151811062000de35762000de362001953565b6020908102919091018101518101516001600160401b0384166000818152600a845260408082206001600160a01b038516808452955280822080546001600160981b03191690555192945090917f4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b9190a3505060010162000d9d565b600062000e76836001600160a01b03841662000ead565b90505b92915050565b600062000e76836001600160a01b03841662000fb1565b600062000e76836001600160a01b03841662001003565b6000818152600183016020526040812054801562000fa657600062000ed460018362001aad565b855490915060009062000eea9060019062001aad565b905081811462000f5657600086600001828154811062000f0e5762000f0e62001953565b906000526020600020015490508087600001848154811062000f345762000f3462001953565b6000918252602080832090910192909255918252600188019052604090208390555b855486908062000f6a5762000f6a62001acf565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505062000e79565b600091505062000e79565b600081815260018301602052604081205462000ffa5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000e79565b50600062000e79565b6000818152600183016020526040812054801562000fa65760006200102a60018362001aad565b8554909150600090620010409060019062001aad565b905080821462000f5657600086600001828154811062000f0e5762000f0e62001953565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b03811182821017156200109f576200109f62001064565b60405290565b60405160c081016001600160401b03811182821017156200109f576200109f62001064565b60405161020081016001600160401b03811182821017156200109f576200109f62001064565b604051601f8201601f191681016001600160401b03811182821017156200111b576200111b62001064565b604052919050565b80516001600160a01b03811681146200113b57600080fd5b919050565b805163ffffffff811681146200113b57600080fd5b6000606082840312156200116857600080fd5b604051606081016001600160401b03811182821017156200118d576200118d62001064565b604052825190915081906001600160601b0381168114620011ad57600080fd5b8152620011bd6020840162001123565b6020820152620011d06040840162001140565b60408201525092915050565b60006001600160401b03821115620011f857620011f862001064565b5060051b60200190565b600082601f8301126200121457600080fd5b815160206200122d6200122783620011dc565b620010f0565b8083825260208201915060208460051b8701019350868411156200125057600080fd5b602086015b848110156200127757620012698162001123565b835291830191830162001255565b509695505050505050565b600082601f8301126200129457600080fd5b81516020620012a76200122783620011dc565b82815260609283028501820192828201919087851115620012c757600080fd5b8387015b858110156200135a5780890382811215620012e65760008081fd5b620012f06200107a565b620012fb8362001123565b8152604080601f1984011215620013125760008081fd5b6200131c6200107a565b92506200132b88850162001123565b835283015160ff81168114620013415760008081fd5b82880152808701919091528452928401928101620012cb565b5090979650505050505050565b80516001600160401b03811681146200113b57600080fd5b805161ffff811681146200113b57600080fd5b805180151581146200113b57600080fd5b600082601f830112620013b557600080fd5b81516020620013c86200122783620011dc565b82815260059290921b84018101918181019086841115620013e857600080fd5b8286015b84811015620012775780516001600160401b03808211156200140d57600080fd5b908801906040601f19838c0381018213156200142857600080fd5b620014326200107a565b6200143f89860162001367565b815282850151848111156200145357600080fd5b8086019550508c603f8601126200146957600080fd5b8885015193506200147e6200122785620011dc565b84815260e09094028501830193898101908e8611156200149d57600080fd5b958401955b858710156200157657868f0360e0811215620014bd57600080fd5b620014c76200107a565b620014d28962001123565b815260c08683011215620014e557600080fd5b620014ef620010a5565b9150620014fe8d8a0162001140565b82526200150d878a0162001140565b8d8301526200151f60608a016200137f565b878301526200153160808a0162001140565b60608301526200154460a08a0162001140565b60808301526200155760c08a0162001392565b60a0830152808d0191909152825260e09690960195908a0190620014a2565b828b015250875250505092840192508301620013ec565b600082601f8301126200159f57600080fd5b81516020620015b26200122783620011dc565b82815260069290921b84018101918181019086841115620015d257600080fd5b8286015b84811015620012775760408189031215620015f15760008081fd5b620015fb6200107a565b620016068262001123565b81526200161585830162001367565b81860152835291830191604001620015d6565b80516001600160e01b0319811681146200113b57600080fd5b600082601f8301126200165357600080fd5b81516020620016666200122783620011dc565b82815261022092830285018201928282019190878511156200168757600080fd5b8387015b858110156200135a5780890382811215620016a65760008081fd5b620016b06200107a565b620016bb8362001367565b815261020080601f1984011215620016d35760008081fd5b620016dd620010ca565b9250620016ec88850162001392565b83526040620016fd8186016200137f565b8985015260606200171081870162001140565b82860152608091506200172582870162001140565b9085015260a06200173886820162001140565b8286015260c091506200174d8287016200137f565b9085015260e06200176086820162001140565b828601526101009150620017768287016200137f565b908501526101206200178a8682016200137f565b828601526101409150620017a08287016200137f565b90850152610160620017b486820162001140565b828601526101809150620017ca82870162001140565b908501526101a0620017de86820162001367565b828601526101c09150620017f482870162001140565b908501526101e06200180886820162001392565b828601526200181983870162001628565b9085015250508087019190915284529284019281016200168b565b6000806000806000806000610120888a0312156200185157600080fd5b6200185d898962001155565b60608901519097506001600160401b03808211156200187b57600080fd5b620018898b838c0162001202565b975060808a0151915080821115620018a057600080fd5b620018ae8b838c0162001202565b965060a08a0151915080821115620018c557600080fd5b620018d38b838c0162001282565b955060c08a0151915080821115620018ea57600080fd5b620018f88b838c01620013a3565b945060e08a01519150808211156200190f57600080fd5b6200191d8b838c016200158d565b93506101008a01519150808211156200193557600080fd5b50620019448a828b0162001641565b91505092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b815115158152610200810160208301516200198a602084018261ffff169052565b506040830151620019a3604084018263ffffffff169052565b506060830151620019bc606084018263ffffffff169052565b506080830151620019d5608084018263ffffffff169052565b5060a0830151620019ec60a084018261ffff169052565b5060c083015162001a0560c084018263ffffffff169052565b5060e083015162001a1c60e084018261ffff169052565b506101008381015161ffff9081169184019190915261012080850151909116908301526101408084015163ffffffff9081169184019190915261016080850151821690840152610180808501516001600160401b0316908401526101a080850151909116908301526101c0808401511515908301526101e0928301516001600160e01b031916929091019190915290565b8181038181111562000e7957634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b60805160a05160c051615c5d62001b466000396000818161030501528181611bcf0152818161226b01526122d40152600081816102c90152818161193d015261199d015260008181610295015281816119c60152611a360152615c5d6000f3fe608060405234801561001057600080fd5b50600436106101e45760003560e01c806379ba50971161010f578063bf78e03f116100a2578063d63d3af211610071578063d63d3af214610ab2578063d8694ccd14610aba578063f2fde38b14610acd578063ffdb4b3714610ae057600080fd5b8063bf78e03f146109c8578063c4276bfc14610a75578063cdc73d5114610a97578063d02641a014610a9f57600080fd5b80638da5cb5b116100de5780638da5cb5b1461096757806391a2749a1461098f5780639ea60026146109a2578063a69c64c0146109b557600080fd5b806379ba5097146107c95780637afac322146107d1578063805f2132146107e457806382b49eb0146107f757600080fd5b80633937306f116101875780634ab35b0b116101565780634ab35b0b1461045f578063514e8cff1461049f5780636def4ce714610542578063770e2dc4146107b657600080fd5b80633937306f14610404578063407e10861461041957806341ed29e71461042c57806345ac924d1461043f57600080fd5b8063085318f8116101c3578063085318f81461037e578063181f5a771461039e5780632451a627146103e7578063325c868e146103fc57600080fd5b806241e5be146101e9578063061877e31461020f57806306285c6914610268575b600080fd5b6101fc6101f7366004614330565b610b28565b6040519081526020015b60405180910390f35b61024f61021d36600461436c565b73ffffffffffffffffffffffffffffffffffffffff1660009081526008602052604090205467ffffffffffffffff1690565b60405167ffffffffffffffff9091168152602001610206565b610332604080516060810182526000808252602082018190529181019190915260405180606001604052807f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000063ffffffff16815250905090565b6040805182516bffffffffffffffffffffffff16815260208084015173ffffffffffffffffffffffffffffffffffffffff16908201529181015163ffffffff1690820152606001610206565b61039161038c3660046143e4565b610b96565b60405161020691906144f6565b6103da6040518060400160405280601381526020017f46656551756f74657220312e362e302d6465760000000000000000000000000081525081565b6040516102069190614578565b6103ef610f08565b604051610206919061458b565b6101fc602481565b6104176104123660046145e5565b610f19565b005b610417610427366004614787565b6111ce565b61041761043a3660046148b9565b6111e2565b61045261044d3660046149f4565b611224565b6040516102069190614a36565b61047261046d36600461436c565b6112ef565b6040517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff9091168152602001610206565b6105356104ad366004614ab1565b60408051808201909152600080825260208201525067ffffffffffffffff166000908152600560209081526040918290208251808401909352547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811683527c0100000000000000000000000000000000000000000000000000000000900463ffffffff169082015290565b6040516102069190614acc565b6107a9610550366004614ab1565b6040805161020081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a081018290526101c081018290526101e08101919091525067ffffffffffffffff908116600090815260096020908152604091829020825161020081018452815460ff8082161515835261ffff61010080840482169685019690965263ffffffff630100000084048116978501979097526701000000000000008304871660608501526b0100000000000000000000008304871660808501526f010000000000000000000000000000008304811660a085015271010000000000000000000000000000000000808404881660c086015275010000000000000000000000000000000000000000008404821660e08087019190915277010000000000000000000000000000000000000000000000850483169786019790975279010000000000000000000000000000000000000000000000000084049091166101208501527b01000000000000000000000000000000000000000000000000000000909204861661014084015260019093015480861661016084015264010000000081049096166101808301526c0100000000000000000000000086049094166101a0820152700100000000000000000000000000000000850490911615156101c08201527fffffffff0000000000000000000000000000000000000000000000000000000092909304901b166101e082015290565b6040516102069190614b07565b6104176107c4366004614d1e565b6112fa565b61041761130c565b6104176107df366004615038565b611409565b6104176107f23660046150de565b61141b565b61090761080536600461514a565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101919091525067ffffffffffffffff919091166000908152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff94909416835292815290829020825160c081018452905463ffffffff8082168352640100000000820481169383019390935268010000000000000000810461ffff16938201939093526a01000000000000000000008304821660608201526e01000000000000000000000000000083049091166080820152720100000000000000000000000000000000000090910460ff16151560a082015290565b6040516102069190600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60005460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610206565b61041761099d366004615174565b611903565b6104176109b0366004615235565b611914565b6104176109c3366004615442565b611925565b610a416109d636600461436c565b6040805180820182526000808252602091820181905273ffffffffffffffffffffffffffffffffffffffff93841681526007825282902082518084019093525492831682527401000000000000000000000000000000000000000090920460ff169181019190915290565b60408051825173ffffffffffffffffffffffffffffffffffffffff16815260209283015160ff169281019290925201610206565b610a88610a83366004615507565b611936565b60405161020693929190615576565b6103ef611b2c565b610535610aad36600461436c565b611b38565b6101fc601281565b6101fc610ac8366004615597565b611c7c565b610417610adb36600461436c565b612186565b610af3610aee3660046155ec565b612197565b604080517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff938416815292909116602083015201610206565b6000610b3382612322565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16610b5a85612322565b610b82907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1685615645565b610b8c919061565c565b90505b9392505050565b67ffffffffffffffff8086166000908152600960205260409020600101546060917101000000000000000000000000000000000090910460e01b908590811115610be257610be2614620565b604051908082528060200260200182016040528015610c1557816020015b6060815260200190600190039081610c005790505b50915060005b85811015610efd576000858583818110610c3757610c37615697565b610c4d926020604090920201908101915061436c565b90506000888884818110610c6357610c63615697565b9050602002810190610c7591906156c6565b610c83906040810190615704565b9150506020811115610d385767ffffffffffffffff8a166000908152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff861684529091529020546e010000000000000000000000000000900463ffffffff16811115610d38576040517f36f536ca00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526024015b60405180910390fd5b610da8848a8a86818110610d4e57610d4e615697565b9050602002810190610d6091906156c6565b610d6e906020810190615704565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506123bc92505050565b67ffffffffffffffff8a166000818152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684528252808320815160c081018352905463ffffffff8082168352640100000000820481168386015268010000000000000000820461ffff16838501526a01000000000000000000008204811660608401526e010000000000000000000000000000820481166080840152720100000000000000000000000000000000000090910460ff16151560a08301908152958552600990935290832054935190937b0100000000000000000000000000000000000000000000000000000090049091169190610ea75781610ead565b82606001515b6040805163ffffffff8316602082015291925001604051602081830303815290604052888781518110610ee257610ee2615697565b60200260200101819052505050505050806001019050610c1b565b505095945050505050565b6060610f146002612413565b905090565b610f21612420565b6000610f2d8280615769565b9050905060005b81811015611077576000610f488480615769565b83818110610f5857610f58615697565b905060400201803603810190610f6e91906157fd565b604080518082018252602080840180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff908116845263ffffffff42818116858701908152885173ffffffffffffffffffffffffffffffffffffffff9081166000908152600690975295889020965190519092167c010000000000000000000000000000000000000000000000000000000002919092161790935584519051935194955016927f52f50aa6d1a95a4595361ecf953d095f125d442e4673716dede699e049de148a926110669290917bffffffffffffffffffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b60405180910390a250600101610f34565b5060006110876020840184615769565b9050905060005b818110156111c85760006110a56020860186615769565b838181106110b5576110b5615697565b9050604002018036038101906110cb919061583a565b604080518082018252602080840180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff908116845263ffffffff42818116858701908152885167ffffffffffffffff9081166000908152600590975295889020965190519092167c010000000000000000000000000000000000000000000000000000000002919092161790935584519051935194955016927fdd84a3fa9ef9409f550d54d6affec7e9c480c878c6ab27b78912a03e1b371c6e926111b79290917bffffffffffffffffffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b60405180910390a25060010161108e565b50505050565b6111d6612465565b6111df816124e6565b50565b6111ea612465565b60005b81518110156112205761121882828151811061120b5761120b615697565b60200260200101516125e4565b6001016111ed565b5050565b60608160008167ffffffffffffffff81111561124257611242614620565b60405190808252806020026020018201604052801561128757816020015b60408051808201909152600080825260208201528152602001906001900390816112605790505b50905060005b828110156112e4576112bf8686838181106112aa576112aa615697565b9050602002016020810190610aad919061436c565b8282815181106112d1576112d1615697565b602090810291909101015260010161128d565b509150505b92915050565b60006112e982612322565b611302612465565b61122082826127b6565b60015473ffffffffffffffffffffffffffffffffffffffff16331461138d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610d2f565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b611411612465565b6112208282612bc3565b600080600061145f87878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612d0a92505050565b92509250925061147133838584612d25565b600061147f8587018761585d565b905060005b81518110156118f8576000600760008484815181106114a5576114a5615697565b6020908102919091018101515173ffffffffffffffffffffffffffffffffffffffff16825281019190915260400160009081205474010000000000000000000000000000000000000000900460ff1691508190036115665782828151811061150f5761150f615697565b6020908102919091010151516040517f06439c6b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610d2f565b60006115af60128386868151811061158057611580615697565b6020026020010151602001517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16612e7d565b9050600660008585815181106115c7576115c7615697565b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001601c9054906101000a900463ffffffff1663ffffffff1684848151811061163957611639615697565b60200260200101516040015163ffffffff1610156117435783838151811061166357611663615697565b60200260200101516000015184848151811061168157611681615697565b602002602001015160400151600660008787815181106116a3576116a3615697565b6020908102919091018101515173ffffffffffffffffffffffffffffffffffffffff90811683529082019290925260409081016000205490517f191ec70600000000000000000000000000000000000000000000000000000000815293909116600484015263ffffffff91821660248401527c01000000000000000000000000000000000000000000000000000000009004166044820152606401610d2f565b6040518060400160405280827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16815260200185858151811061178457611784615697565b60200260200101516040015163ffffffff16815250600660008686815181106117af576117af615697565b6020908102919091018101515173ffffffffffffffffffffffffffffffffffffffff168252818101929092526040016000208251929091015163ffffffff167c0100000000000000000000000000000000000000000000000000000000027bffffffffffffffffffffffffffffffffffffffffffffffffffffffff909216919091179055835184908490811061184757611847615697565b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff167f52f50aa6d1a95a4595361ecf953d095f125d442e4673716dede699e049de148a8286868151811061189d5761189d615697565b6020026020010151604001516040516118e69291907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff92909216825263ffffffff16602082015260400190565b60405180910390a25050600101611484565b505050505050505050565b61190b612465565b6111df81612f49565b61191c612465565b6111df816130d5565b61192d612465565b6111df8161357b565b60008060607f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff1603611996578592506119c4565b6119c187877f0000000000000000000000000000000000000000000000000000000000000000610b28565b92505b7f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff16831115611a63576040517f6a92a483000000000000000000000000000000000000000000000000000000008152600481018490526bffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166024820152604401610d2f565b67ffffffffffffffff881660009081526009602052604081206001015463ffffffff1690611a92878784613665565b9050806020015193508484611b19836040805182516024820152602092830151151560448083019190915282518083039091018152606490910190915290810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f181dcf100000000000000000000000000000000000000000000000000000000017905290565b9450945094505050955095509592505050565b6060610f14600b612413565b604080518082019091526000808252602082015273ffffffffffffffffffffffffffffffffffffffff82166000908152600660209081526040918290208251808401909352547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116835263ffffffff7c010000000000000000000000000000000000000000000000000000000090910481169183018290527f00000000000000000000000000000000000000000000000000000000000000001690611bfa9042615924565b1015611c065792915050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600760209081526040918290208251808401909352549283168083527401000000000000000000000000000000000000000090930460ff169082015290611c6b575092915050565b611c748161380e565b949350505050565b67ffffffffffffffff8083166000908152600960209081526040808320815161020081018352815460ff808216151580845261ffff61010080850482169886019890985263ffffffff630100000085048116978601979097526701000000000000008404871660608601526b0100000000000000000000008404871660808601526f010000000000000000000000000000008404811660a086015271010000000000000000000000000000000000808504881660c087015275010000000000000000000000000000000000000000008504821660e08088019190915277010000000000000000000000000000000000000000000000860483169987019990995279010000000000000000000000000000000000000000000000000085049091166101208601527b01000000000000000000000000000000000000000000000000000000909304861661014085015260019094015480861661016085015264010000000081049098166101808401526c0100000000000000000000000088049094166101a0830152700100000000000000000000000000000000870490931615156101c08201527fffffffff000000000000000000000000000000000000000000000000000000009290950490921b166101e0840152909190611e96576040517f99ac52f200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff85166004820152602401610d2f565b611eb1611ea9608085016060860161436c565b600b9061399d565b611f1057611ec5608084016060850161436c565b6040517f2502348c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610d2f565b6000611f1f6040850185615769565b9150611f7b905082611f346020870187615704565b905083611f418880615704565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506139cc92505050565b600080611f97611f91608088016060890161436c565b88612197565b9092509050600080808515611fda57611fce878b611fbb60808d0160608e0161436c565b88611fc960408f018f615769565b613a76565b91945092509050611ffa565b6101a0870151611ff79063ffffffff16662386f26fc10000615645565b92505b61010087015160009061ffff161561203e5761203b886dffffffffffffffffffffffffffff607088901c1661203260208e018e615704565b90508a86613d4e565b90505b61018088015160009067ffffffffffffffff1661206761206160808e018e615704565b8c613dfe565b600001518563ffffffff168b60a0015161ffff168e806020019061208b9190615704565b612096929150615645565b8c6080015163ffffffff166120ab9190615937565b6120b59190615937565b6120bf9190615937565b6120d9906dffffffffffffffffffffffffffff8916615645565b6120e39190615645565b9050867bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168282600860008f606001602081019061211d919061436c565b73ffffffffffffffffffffffffffffffffffffffff1681526020810191909152604001600020546121589067ffffffffffffffff1689615645565b6121629190615937565b61216c9190615937565b612176919061565c565b9c9b505050505050505050505050565b61218e612465565b6111df81613ebf565b67ffffffffffffffff811660009081526005602090815260408083208151808301909252547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811682527c0100000000000000000000000000000000000000000000000000000000900463ffffffff169181018290528291820361224f576040517f2e59db3a00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff85166004820152602401610d2f565b6000816020015163ffffffff16426122679190615924565b90507f000000000000000000000000000000000000000000000000000000000000000063ffffffff16811115612308576040517ff08bcb3e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8616600482015263ffffffff7f000000000000000000000000000000000000000000000000000000000000000016602482015260448101829052606401610d2f565b61231186612322565b9151919350909150505b9250929050565b60008061232e83611b38565b9050806020015163ffffffff1660001480612366575080517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16155b156123b5576040517f06439c6b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152602401610d2f565b5192915050565b7fd7ed2ad4000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316016112205761240e81613fb4565b505050565b60606000610b8f83614067565b61242b60023361399d565b612463576040517fd86ad9cf000000000000000000000000000000000000000000000000000000008152336004820152602401610d2f565b565b60005473ffffffffffffffffffffffffffffffffffffffff163314612463576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610d2f565b60005b815181101561122057600082828151811061250657612506615697565b60209081029190910181015180518183015173ffffffffffffffffffffffffffffffffffffffff80831660008181526007875260409081902084518154868a018051929096167fffffffffffffffffffffff00000000000000000000000000000000000000000090911681177401000000000000000000000000000000000000000060ff9384160217909255825191825293519093169683019690965293955091939092917f08a5f7f5bb38a81d8e43aca13ecd76431dbf8816ae4699affff7b00b2fc1c464910160405180910390a25050508060010190506124e9565b600061269d82600001518360600151846020015185604001516040805173ffffffffffffffffffffffffffffffffffffffff80871660208301528516918101919091527fffffffffffffffffffff00000000000000000000000000000000000000000000831660608201527fffff0000000000000000000000000000000000000000000000000000000000008216608082015260009060a001604051602081830303815290604052805190602001209050949350505050565b60808301516000828152600460205260409081902080549215157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00909316929092179091555190915081907f32a4ba3fa3351b11ad555d4c8ec70a744e8705607077a946807030d64b6ab1a3906127aa908590600060a08201905073ffffffffffffffffffffffffffffffffffffffff8084511683527fffffffffffffffffffff0000000000000000000000000000000000000000000060208501511660208401527fffff00000000000000000000000000000000000000000000000000000000000060408501511660408401528060608501511660608401525060808301511515608083015292915050565b60405180910390a25050565b60005b8251811015612adf5760008382815181106127d6576127d6615697565b6020026020010151905060008160000151905060005b826020015151811015612ad15760008360200151828151811061281157612811615697565b602002602001015160200151905060008460200151838151811061283757612837615697565b6020026020010151600001519050602063ffffffff16826080015163ffffffff1610156128ba5760808201516040517f24ecdc0200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8316600482015263ffffffff9091166024820152604401610d2f565b67ffffffffffffffff84166000818152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff86168085529083529281902086518154938801518389015160608a015160808b015160a08c015115157201000000000000000000000000000000000000027fffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffff63ffffffff9283166e01000000000000000000000000000002167fffffffffffffffffffffffffff0000000000ffffffffffffffffffffffffffff9383166a0100000000000000000000027fffffffffffffffffffffffffffffffffffff00000000ffffffffffffffffffff61ffff9096166801000000000000000002959095167fffffffffffffffffffffffffffffffffffff000000000000ffffffffffffffff968416640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000909b16939097169290921798909817939093169390931717919091161792909217909155519091907f94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b590612abf908690600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60405180910390a350506001016127ec565b5050508060010190506127b9565b5060005b815181101561240e576000828281518110612b0057612b00615697565b60200260200101516000015190506000838381518110612b2257612b22615697565b60209081029190910181015181015167ffffffffffffffff84166000818152600a8452604080822073ffffffffffffffffffffffffffffffffffffffff8516808452955280822080547fffffffffffffffffffffffffff000000000000000000000000000000000000001690555192945090917f4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b9190a35050600101612ae3565b60005b8251811015612c6657612bfc838281518110612be457612be4615697565b6020026020010151600b6140c390919063ffffffff16565b15612c5e57828181518110612c1357612c13615697565b602002602001015173ffffffffffffffffffffffffffffffffffffffff167fdf1b1bd32a69711488d71554706bb130b1fc63a5fa1a2cd85e8440f84065ba2360405160405180910390a25b600101612bc6565b5060005b815181101561240e57612ca0828281518110612c8857612c88615697565b6020026020010151600b6140e590919063ffffffff16565b15612d0257818181518110612cb757612cb7615697565b602002602001015173ffffffffffffffffffffffffffffffffffffffff167f1795838dc8ab2ffc5f431a1729a6afa0b587f982f7b2be0b9d7187a1ef547f9160405160405180910390a25b600101612c6a565b6040810151604a820151605e90920151909260609290921c91565b6040805173ffffffffffffffffffffffffffffffffffffffff868116602080840191909152908616828401527fffffffffffffffffffff00000000000000000000000000000000000000000000851660608301527fffff00000000000000000000000000000000000000000000000000000000000084166080808401919091528351808403909101815260a09092018352815191810191909120600081815260049092529190205460ff16612e76576040517f097e17ff00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8087166004830152851660248201527fffffffffffffffffffff00000000000000000000000000000000000000000000841660448201527fffff00000000000000000000000000000000000000000000000000000000000083166064820152608401610d2f565b5050505050565b600080612e8a848661594a565b9050600060248260ff161115612ec457612ea8602460ff8416615924565b612eb390600a615a83565b612ebd908561565c565b9050612eea565b612ed260ff83166024615924565b612edd90600a615a83565b612ee79085615645565b90505b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811115612f40576040517f10cb51d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b95945050505050565b602081015160005b8151811015612fe4576000828281518110612f6e57612f6e615697565b60200260200101519050612f8c81600261410790919063ffffffff16565b15612fdb5760405173ffffffffffffffffffffffffffffffffffffffff821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b50600101612f51565b50815160005b81518110156111c857600082828151811061300757613007615697565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603613077576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6130826002826140c3565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a150600101612fea565b60005b81518110156112205760008282815181106130f5576130f5615697565b60200260200101519050600083838151811061311357613113615697565b60200260200101516000015190506000826020015190508167ffffffffffffffff166000148061314c575061016081015163ffffffff16155b8061319e57506101e08101517fffffffff00000000000000000000000000000000000000000000000000000000167f2812d52c0000000000000000000000000000000000000000000000000000000014155b806131bd5750806060015163ffffffff1681610160015163ffffffff16115b15613200576040517fc35aa79d00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff83166004820152602401610d2f565b67ffffffffffffffff821660009081526009602052604081206001015471010000000000000000000000000000000000900460e01b7fffffffff000000000000000000000000000000000000000000000000000000001690036132a4578167ffffffffffffffff167fd31c671936387b2f84ed402b553bd50c0e9c20408ea4e91a836d77b8180fb724826040516132979190614b07565b60405180910390a26132e7565b8167ffffffffffffffff167f1edd6f3553cfa16f10b95b195abae3a1cfca4783de4843f95d674b1e1df5ab20826040516132de9190614b07565b60405180910390a25b80600960008467ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548161ffff021916908361ffff16021790555060408201518160000160036101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160076101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600b6101000a81548163ffffffff021916908363ffffffff16021790555060a082015181600001600f6101000a81548161ffff021916908361ffff16021790555060c08201518160000160116101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160000160156101000a81548161ffff021916908361ffff1602179055506101008201518160000160176101000a81548161ffff021916908361ffff1602179055506101208201518160000160196101000a81548161ffff021916908361ffff16021790555061014082015181600001601b6101000a81548163ffffffff021916908363ffffffff1602179055506101608201518160010160006101000a81548163ffffffff021916908363ffffffff1602179055506101808201518160010160046101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506101a082015181600101600c6101000a81548163ffffffff021916908363ffffffff1602179055506101c08201518160010160106101000a81548160ff0219169083151502179055506101e08201518160010160116101000a81548163ffffffff021916908360e01c02179055509050505050508060010190506130d8565b60005b815181101561122057600082828151811061359b5761359b615697565b602002602001015160000151905060008383815181106135bd576135bd615697565b60209081029190910181015181015173ffffffffffffffffffffffffffffffffffffffff841660008181526008845260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff85169081179091559051908152919350917fbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d910160405180910390a2505060010161357e565b604080518082019091526000808252602082015260008390036136a657506040805180820190915267ffffffffffffffff8216815260006020820152610b8f565b60006136b28486615a8f565b905060006136c38560048189615ad5565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505050507fffffffff0000000000000000000000000000000000000000000000000000000082167fe7e230f0000000000000000000000000000000000000000000000000000000000161376057808060200190518101906137579190615aff565b92505050610b8f565b7f6859a837000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316016137dc576040518060400160405280828060200190518101906137c89190615b2b565b815260006020909101529250610b8f915050565b6040517f5247fdce00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080518082019091526000808252602082015260008260000151905060008173ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015613878573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061389c9190615b5e565b50505091505060008112156138dd576040517f10cb51d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061395c8373ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561392d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139519190615bae565b866020015184612e7d565b604080518082019091527bffffffffffffffffffffffffffffffffffffffffffffffffffffffff909116815263ffffffff4216602082015295945050505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515610b8f565b836040015163ffffffff16831115613a255760408085015190517f8693378900000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015260248101849052604401610d2f565b836020015161ffff16821115613a67576040517f4c056b6a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6111c8846101e00151826123bc565b6000808083815b81811015613d40576000878783818110613a9957613a99615697565b905060400201803603810190613aaf9190615bcb565b67ffffffffffffffff8c166000908152600a60209081526040808320845173ffffffffffffffffffffffffffffffffffffffff168452825291829020825160c081018452905463ffffffff8082168352640100000000820481169383019390935268010000000000000000810461ffff16938201939093526a01000000000000000000008304821660608201526e01000000000000000000000000000083049091166080820152720100000000000000000000000000000000000090910460ff16151560a0820181905291925090613bcf576101208d0151613b9c9061ffff16662386f26fc10000615645565b613ba69088615937565b96508c610140015186613bb99190615c04565b9550613bc6602086615c04565b94505050613d38565b604081015160009061ffff1615613c885760008c73ffffffffffffffffffffffffffffffffffffffff16846000015173ffffffffffffffffffffffffffffffffffffffff1614613c2b578351613c2490612322565b9050613c2e565b508a5b620186a0836040015161ffff16613c708660200151847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1661412990919063ffffffff16565b613c7a9190615645565b613c84919061565c565b9150505b6060820151613c979088615c04565b9650816080015186613ca99190615c04565b8251909650600090613cc89063ffffffff16662386f26fc10000615645565b905080821015613ce757613cdc818a615937565b985050505050613d38565b6000836020015163ffffffff16662386f26fc10000613d069190615645565b905080831115613d2657613d1a818b615937565b99505050505050613d38565b613d30838b615937565b995050505050505b600101613a7d565b505096509650969350505050565b60008063ffffffff8316613d6461016086615645565b613d70876101c0615937565b613d7a9190615937565b613d849190615937565b905060008760c0015163ffffffff168860e0015161ffff1683613da79190615645565b613db19190615937565b61010089015190915061ffff16613dd86dffffffffffffffffffffffffffff891683615645565b613de29190615645565b613df290655af3107a4000615645565b98975050505050505050565b60408051808201909152600080825260208201526000613e2a858585610160015163ffffffff16613665565b9050826060015163ffffffff1681600001511115613e74576040517f4c4fc93a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b826101c001518015613e8857508060200151155b15610b8c576040517fee433e9900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff821603613f3e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610d2f565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60008151602014613ff357816040517f8d666f60000000000000000000000000000000000000000000000000000000008152600401610d2f9190614578565b6000828060200190518101906140099190615b2b565b905073ffffffffffffffffffffffffffffffffffffffff81118061402e575061040081105b156112e957826040517f8d666f60000000000000000000000000000000000000000000000000000000008152600401610d2f9190614578565b6060816000018054806020026020016040519081016040528092919081815260200182805480156140b757602002820191906000526020600020905b8154815260200190600101908083116140a3575b50505050509050919050565b6000610b8f8373ffffffffffffffffffffffffffffffffffffffff8416614166565b6000610b8f8373ffffffffffffffffffffffffffffffffffffffff84166141b5565b6000610b8f8373ffffffffffffffffffffffffffffffffffffffff84166142af565b6000670de0b6b3a764000061415c837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8616615645565b610b8f919061565c565b60008181526001830160205260408120546141ad575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556112e9565b5060006112e9565b6000818152600183016020526040812054801561429e5760006141d9600183615924565b85549091506000906141ed90600190615924565b905080821461425257600086600001828154811061420d5761420d615697565b906000526020600020015490508087600001848154811061423057614230615697565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061426357614263615c21565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506112e9565b60009150506112e9565b5092915050565b6000818152600183016020526040812054801561429e5760006142d3600183615924565b85549091506000906142e790600190615924565b905081811461425257600086600001828154811061420d5761420d615697565b803573ffffffffffffffffffffffffffffffffffffffff8116811461432b57600080fd5b919050565b60008060006060848603121561434557600080fd5b61434e84614307565b92506020840135915061436360408501614307565b90509250925092565b60006020828403121561437e57600080fd5b610b8f82614307565b803567ffffffffffffffff8116811461432b57600080fd5b60008083601f8401126143b157600080fd5b50813567ffffffffffffffff8111156143c957600080fd5b6020830191508360208260051b850101111561231b57600080fd5b6000806000806000606086880312156143fc57600080fd5b61440586614387565b9450602086013567ffffffffffffffff8082111561442257600080fd5b61442e89838a0161439f565b9096509450604088013591508082111561444757600080fd5b818801915088601f83011261445b57600080fd5b81358181111561446a57600080fd5b8960208260061b850101111561447f57600080fd5b9699959850939650602001949392505050565b6000815180845260005b818110156144b85760208185018101518683018201520161449c565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b8281101561456b577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0888603018452614559858351614492565b9450928501929085019060010161451f565b5092979650505050505050565b602081526000610b8f6020830184614492565b6020808252825182820181905260009190848201906040850190845b818110156145d957835173ffffffffffffffffffffffffffffffffffffffff16835292840192918401916001016145a7565b50909695505050505050565b6000602082840312156145f757600080fd5b813567ffffffffffffffff81111561460e57600080fd5b820160408185031215610b8f57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561467257614672614620565b60405290565b60405160a0810167ffffffffffffffff8111828210171561467257614672614620565b60405160c0810167ffffffffffffffff8111828210171561467257614672614620565b604051610200810167ffffffffffffffff8111828210171561467257614672614620565b6040516060810167ffffffffffffffff8111828210171561467257614672614620565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561474c5761474c614620565b604052919050565b600067ffffffffffffffff82111561476e5761476e614620565b5060051b60200190565b60ff811681146111df57600080fd5b6000602080838503121561479a57600080fd5b823567ffffffffffffffff8111156147b157600080fd5b8301601f810185136147c257600080fd5b80356147d56147d082614754565b614705565b818152606091820283018401918482019190888411156147f457600080fd5b938501935b8385101561489457848903818112156148125760008081fd5b61481a61464f565b61482387614307565b81526040807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0840112156148575760008081fd5b61485f61464f565b925061486c898901614307565b835287013561487a81614778565b8289015280880191909152835293840193918501916147f9565b50979650505050505050565b80151581146111df57600080fd5b803561432b816148a0565b600060208083850312156148cc57600080fd5b823567ffffffffffffffff8111156148e357600080fd5b8301601f810185136148f457600080fd5b80356149026147d082614754565b81815260a0918202830184019184820191908884111561492157600080fd5b938501935b838510156148945780858a03121561493e5760008081fd5b614946614678565b61494f86614307565b8152868601357fffffffffffffffffffff00000000000000000000000000000000000000000000811681146149845760008081fd5b818801526040868101357fffff000000000000000000000000000000000000000000000000000000000000811681146149bd5760008081fd5b9082015260606149ce878201614307565b908201526080868101356149e1816148a0565b9082015283529384019391850191614926565b60008060208385031215614a0757600080fd5b823567ffffffffffffffff811115614a1e57600080fd5b614a2a8582860161439f565b90969095509350505050565b602080825282518282018190526000919060409081850190868401855b82811015614aa457614a9484835180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16825260209081015163ffffffff16910152565b9284019290850190600101614a53565b5091979650505050505050565b600060208284031215614ac357600080fd5b610b8f82614387565b81517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16815260208083015163ffffffff1690820152604081016112e9565b81511515815261020081016020830151614b27602084018261ffff169052565b506040830151614b3f604084018263ffffffff169052565b506060830151614b57606084018263ffffffff169052565b506080830151614b6f608084018263ffffffff169052565b5060a0830151614b8560a084018261ffff169052565b5060c0830151614b9d60c084018263ffffffff169052565b5060e0830151614bb360e084018261ffff169052565b506101008381015161ffff9081169184019190915261012080850151909116908301526101408084015163ffffffff90811691840191909152610160808501518216908401526101808085015167ffffffffffffffff16908401526101a080850151909116908301526101c0808401511515908301526101e0808401517fffffffff000000000000000000000000000000000000000000000000000000008116828501525b505092915050565b803563ffffffff8116811461432b57600080fd5b803561ffff8116811461432b57600080fd5b600082601f830112614c9757600080fd5b81356020614ca76147d083614754565b82815260069290921b84018101918181019086841115614cc657600080fd5b8286015b84811015614d135760408189031215614ce35760008081fd5b614ceb61464f565b614cf482614387565b8152614d01858301614307565b81860152835291830191604001614cca565b509695505050505050565b60008060408385031215614d3157600080fd5b67ffffffffffffffff83351115614d4757600080fd5b83601f843585010112614d5957600080fd5b614d696147d08435850135614754565b8335840180358083526020808401939260059290921b90910101861015614d8f57600080fd5b602085358601015b85358601803560051b01602001811015614f9c5767ffffffffffffffff81351115614dc157600080fd5b8035863587010160407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0828a03011215614dfa57600080fd5b614e0261464f565b614e0e60208301614387565b815267ffffffffffffffff60408301351115614e2957600080fd5b88603f604084013584010112614e3e57600080fd5b614e546147d06020604085013585010135614754565b6020604084810135850182810135808552928401939260e00201018b1015614e7b57600080fd5b6040808501358501015b6040858101358601602081013560e0020101811015614f7d5760e0818d031215614eae57600080fd5b614eb661464f565b614ebf82614307565b815260c07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0838f03011215614ef357600080fd5b614efb61469b565b614f0760208401614c60565b8152614f1560408401614c60565b6020820152614f2660608401614c74565b6040820152614f3760808401614c60565b6060820152614f4860a08401614c60565b6080820152614f5a60c08401356148a0565b60c083013560a0820152602082810191909152908452929092019160e001614e85565b5080602084015250508085525050602083019250602081019050614d97565b5092505067ffffffffffffffff60208401351115614fb957600080fd5b614fc98460208501358501614c86565b90509250929050565b600082601f830112614fe357600080fd5b81356020614ff36147d083614754565b8083825260208201915060208460051b87010193508684111561501557600080fd5b602086015b84811015614d135761502b81614307565b835291830191830161501a565b6000806040838503121561504b57600080fd5b823567ffffffffffffffff8082111561506357600080fd5b61506f86838701614fd2565b9350602085013591508082111561508557600080fd5b5061509285828601614fd2565b9150509250929050565b60008083601f8401126150ae57600080fd5b50813567ffffffffffffffff8111156150c657600080fd5b60208301915083602082850101111561231b57600080fd5b600080600080604085870312156150f457600080fd5b843567ffffffffffffffff8082111561510c57600080fd5b6151188883890161509c565b9096509450602087013591508082111561513157600080fd5b5061513e8782880161509c565b95989497509550505050565b6000806040838503121561515d57600080fd5b61516683614387565b9150614fc960208401614307565b60006020828403121561518657600080fd5b813567ffffffffffffffff8082111561519e57600080fd5b90830190604082860312156151b257600080fd5b6151ba61464f565b8235828111156151c957600080fd5b6151d587828601614fd2565b8252506020830135828111156151ea57600080fd5b6151f687828601614fd2565b60208301525095945050505050565b80357fffffffff000000000000000000000000000000000000000000000000000000008116811461432b57600080fd5b6000602080838503121561524857600080fd5b823567ffffffffffffffff81111561525f57600080fd5b8301601f8101851361527057600080fd5b803561527e6147d082614754565b818152610220918202830184019184820191908884111561529e57600080fd5b938501935b8385101561489457848903818112156152bc5760008081fd5b6152c461464f565b6152cd87614387565b8152610200807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0840112156153025760008081fd5b61530a6146be565b92506153178989016148ae565b83526040615326818a01614c74565b8a8501526060615337818b01614c60565b828601526080915061534a828b01614c60565b9085015260a061535b8a8201614c60565b8286015260c0915061536e828b01614c74565b9085015260e061537f8a8201614c60565b828601526101009150615393828b01614c74565b908501526101206153a58a8201614c74565b8286015261014091506153b9828b01614c74565b908501526101606153cb8a8201614c60565b8286015261018091506153df828b01614c60565b908501526101a06153f18a8201614387565b828601526101c09150615405828b01614c60565b908501526101e06154178a82016148ae565b82860152615426838b01615205565b90850152505080880191909152835293840193918501916152a3565b6000602080838503121561545557600080fd5b823567ffffffffffffffff81111561546c57600080fd5b8301601f8101851361547d57600080fd5b803561548b6147d082614754565b81815260069190911b820183019083810190878311156154aa57600080fd5b928401925b828410156154fc57604084890312156154c85760008081fd5b6154d061464f565b6154d985614307565b81526154e6868601614387565b81870152825260409390930192908401906154af565b979650505050505050565b60008060008060006080868803121561551f57600080fd5b61552886614387565b945061553660208701614307565b935060408601359250606086013567ffffffffffffffff81111561555957600080fd5b6155658882890161509c565b969995985093965092949392505050565b8381528215156020820152606060408201526000612f406060830184614492565b600080604083850312156155aa57600080fd5b6155b383614387565b9150602083013567ffffffffffffffff8111156155cf57600080fd5b830160a081860312156155e157600080fd5b809150509250929050565b600080604083850312156155ff57600080fd5b61560883614307565b9150614fc960208401614387565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80820281158282048414176112e9576112e9615616565b600082615692577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff618336030181126156fa57600080fd5b9190910192915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261573957600080fd5b83018035915067ffffffffffffffff82111561575457600080fd5b60200191503681900382131561231b57600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261579e57600080fd5b83018035915067ffffffffffffffff8211156157b957600080fd5b6020019150600681901b360382131561231b57600080fd5b80357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116811461432b57600080fd5b60006040828403121561580f57600080fd5b61581761464f565b61582083614307565b815261582e602084016157d1565b60208201529392505050565b60006040828403121561584c57600080fd5b61585461464f565b61582083614387565b6000602080838503121561587057600080fd5b823567ffffffffffffffff81111561588757600080fd5b8301601f8101851361589857600080fd5b80356158a66147d082614754565b818152606091820283018401918482019190888411156158c557600080fd5b938501935b838510156148945780858a0312156158e25760008081fd5b6158ea6146e2565b6158f386614307565b81526159008787016157d1565b878201526040615911818801614c60565b90820152835293840193918501916158ca565b818103818111156112e9576112e9615616565b808201808211156112e9576112e9615616565b60ff81811683821601908111156112e9576112e9615616565b600181815b808511156159bc57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156159a2576159a2615616565b808516156159af57918102915b93841c9390800290615968565b509250929050565b6000826159d3575060016112e9565b816159e0575060006112e9565b81600181146159f65760028114615a0057615a1c565b60019150506112e9565b60ff841115615a1157615a11615616565b50506001821b6112e9565b5060208310610133831016604e8410600b8410161715615a3f575081810a6112e9565b615a498383615963565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115615a7b57615a7b615616565b029392505050565b6000610b8f83836159c4565b7fffffffff000000000000000000000000000000000000000000000000000000008135818116916004851015614c585760049490940360031b84901b1690921692915050565b60008085851115615ae557600080fd5b83861115615af257600080fd5b5050820193919092039150565b600060408284031215615b1157600080fd5b615b1961464f565b82518152602083015161582e816148a0565b600060208284031215615b3d57600080fd5b5051919050565b805169ffffffffffffffffffff8116811461432b57600080fd5b600080600080600060a08688031215615b7657600080fd5b615b7f86615b44565b9450602086015193506040860151925060608601519150615ba260808701615b44565b90509295509295909350565b600060208284031215615bc057600080fd5b8151610b8f81614778565b600060408284031215615bdd57600080fd5b615be561464f565b615bee83614307565b8152602083013560208201528091505092915050565b63ffffffff8181168382160190808211156142a8576142a8615616565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea164736f6c6343000818000a", } var FeeQuoterABI = FeeQuoterMetaData.ABI diff --git a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt index 9908bcfcd8..b3ed8635dd 100644 --- a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -11,7 +11,7 @@ commit_store_helper: ../../../contracts/solc/v0.8.24/CommitStoreHelper/CommitSto ether_sender_receiver: ../../../contracts/solc/v0.8.24/EtherSenderReceiver/EtherSenderReceiver.abi ../../../contracts/solc/v0.8.24/EtherSenderReceiver/EtherSenderReceiver.bin 09510a3f773f108a3c231e8d202835c845ded862d071ec54c4f89c12d868b8de evm_2_evm_offramp: ../../../contracts/solc/v0.8.24/EVM2EVMOffRamp/EVM2EVMOffRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMOffRamp/EVM2EVMOffRamp.bin b0d77babbe635cd6ba04c2af049badc9e9d28a4b6ed6bb75f830ad902a618beb evm_2_evm_onramp: ../../../contracts/solc/v0.8.24/EVM2EVMOnRamp/EVM2EVMOnRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMOnRamp/EVM2EVMOnRamp.bin 5c02c2b167946b3467636ff2bb58594cb4652fc63d8bdfee2488ed562e2a3e50 -fee_quoter: ../../../contracts/solc/v0.8.24/FeeQuoter/FeeQuoter.abi ../../../contracts/solc/v0.8.24/FeeQuoter/FeeQuoter.bin 286117b3f17fe2854ddada25666be4ed2eb8069718f4ba595958accad170a4a2 +fee_quoter: ../../../contracts/solc/v0.8.24/FeeQuoter/FeeQuoter.abi ../../../contracts/solc/v0.8.24/FeeQuoter/FeeQuoter.bin 392a7b95a2ff4e3c5c452965a21f5bdb89ad28316f7280ecf81b81740fd54273 lock_release_token_pool: ../../../contracts/solc/v0.8.24/LockReleaseTokenPool/LockReleaseTokenPool.abi ../../../contracts/solc/v0.8.24/LockReleaseTokenPool/LockReleaseTokenPool.bin e6a8ec9e8faccb1da7d90e0f702ed72975964f97dc3222b54cfcca0a0ba3fea2 lock_release_token_pool_and_proxy: ../../../contracts/solc/v0.8.24/LockReleaseTokenPoolAndProxy/LockReleaseTokenPoolAndProxy.abi ../../../contracts/solc/v0.8.24/LockReleaseTokenPoolAndProxy/LockReleaseTokenPoolAndProxy.bin e632b08be0fbd1d013e8b3a9d75293d0d532b83071c531ff2be1deec1fa48ec1 maybe_revert_message_receiver: ../../../contracts/solc/v0.8.24/MaybeRevertMessageReceiver/MaybeRevertMessageReceiver.abi ../../../contracts/solc/v0.8.24/MaybeRevertMessageReceiver/MaybeRevertMessageReceiver.bin d73956c26232ebcc4a5444429fa99cbefed960e323be9b5a24925885c2e477d5 From 71be1a76b8b2192c3e16a3c79da9afc0eed7fc1e Mon Sep 17 00:00:00 2001 From: Zubin Date: Thu, 12 Sep 2024 19:40:16 +1000 Subject: [PATCH 087/115] Zp/update mockrouter (#1427) Specifically, allow for empty message with zero gas. ## Motivation EVM2EVMOffRamp checks the message for content and gaslimit and skips calling ccip receive if they're not present. Consequently the mock errors (ReceiverError) when sending only tokens to a smart contract. This update will help chainlink-local correctly process fork-based tests too. ## Solution The MockRouter implementation of _routeMessage was last updated in https://github.com/smartcontractkit/ccip/pull/669 and is out of sync with the logic in EVM2EVMOffRamp. --- contracts/gas-snapshots/ccip.gas-snapshot | 4 ++-- contracts/src/v0.8/ccip/test/mocks/MockRouter.sol | 15 +++++++++++++-- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/contracts/gas-snapshots/ccip.gas-snapshot b/contracts/gas-snapshots/ccip.gas-snapshot index 2dbf1fe8c9..bafefa2261 100644 --- a/contracts/gas-snapshots/ccip.gas-snapshot +++ b/contracts/gas-snapshots/ccip.gas-snapshot @@ -481,9 +481,9 @@ MerkleMultiProofTest:test_MerkleRootSingleLeaf_Success() (gas: 3649) MerkleMultiProofTest:test_SpecSync_gas() (gas: 34123) MockRouterTest:test_ccipSendWithInsufficientNativeTokens_Revert() (gas: 34019) MockRouterTest:test_ccipSendWithInvalidMsgValue_Revert() (gas: 60812) -MockRouterTest:test_ccipSendWithLinkFeeTokenAndValidMsgValue_Success() (gas: 126480) +MockRouterTest:test_ccipSendWithLinkFeeTokenAndValidMsgValue_Success() (gas: 126540) MockRouterTest:test_ccipSendWithLinkFeeTokenbutInsufficientAllowance_Revert() (gas: 63419) -MockRouterTest:test_ccipSendWithSufficientNativeFeeTokens_Success() (gas: 43952) +MockRouterTest:test_ccipSendWithSufficientNativeFeeTokens_Success() (gas: 44012) MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_MultipleConfigsBothLanes_Success() (gas: 132457) MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_MultipleConfigs_Success() (gas: 313023) MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_OnlyCallableByOwner_Revert() (gas: 17750) diff --git a/contracts/src/v0.8/ccip/test/mocks/MockRouter.sol b/contracts/src/v0.8/ccip/test/mocks/MockRouter.sol index 050cd6d457..9181fb37c2 100644 --- a/contracts/src/v0.8/ccip/test/mocks/MockRouter.sol +++ b/contracts/src/v0.8/ccip/test/mocks/MockRouter.sol @@ -45,8 +45,19 @@ contract MockCCIPRouter is IRouter, IRouterClient { uint256 gasLimit, address receiver ) internal returns (bool success, bytes memory retData, uint256 gasUsed) { - // Only send through the router if the receiver is a contract and implements the IAny2EVMMessageReceiver interface. - if (receiver.code.length == 0 || !receiver.supportsInterface(type(IAny2EVMMessageReceiver).interfaceId)) { + // There are three cases in which we skip calling the receiver: + // 1. If the message data is empty AND the gas limit is 0. + // This indicates a message that only transfers tokens. It is valid to only send tokens to a contract + // that supports the IAny2EVMMessageReceiver interface, but without this first check we would call the + // receiver without any gas, which would revert the transaction. + // 2. If the receiver is not a contract. + // 3. If the receiver is a contract but it does not support the IAny2EVMMessageReceiver interface. + // + // The ordering of these checks is important, as the first check is the cheapest to execute. + if ( + (message.data.length == 0 && gasLimit == 0) || receiver.code.length == 0 + || !receiver.supportsInterface(type(IAny2EVMMessageReceiver).interfaceId) + ) { return (true, "", 0); } From 3d54dfb3e03e5e7383ece2e133c5e250d05fdb57 Mon Sep 17 00:00:00 2001 From: Josh Weintraub <26035072+jhweintraub@users.noreply.github.com> Date: Thu, 12 Sep 2024 10:48:37 -0400 Subject: [PATCH 088/115] Hybrid Token Pools: Remove problematic liquidity functions and add incoming supply lock (#1396) ## Motivation Minor Changes to the HybridLockReleaseTokenPool to better meet Circle's bridge requirements 1. Add additional supply lock on incoming messages when a proposal has been created. I.E When a proposal for a chain selector is active, new tokens cannot be released or locked to ensure better security control on the destination-chain's token supply. 2. `withdrawLiquidity()` and `transferLiqudity()` have been removed to avoid issues with the supply lock. Allowing for withdrawing liquidity that has been provided would allow for the supply on the destination chain to be greater than the locked amount on the source chain, preventing a successful migration from occuring. 3. Comment fixes for invariants --- contracts/gas-snapshots/ccip.gas-snapshot | 49 ++- .../USDC/HybridLockReleaseUSDCTokenPool.sol | 75 +++- .../ccip/pools/USDC/USDCBridgeMigrator.sol | 45 +- .../HybridLockReleaseUSDCTokenPool.t.sol | 383 ++++++++++++++---- 4 files changed, 431 insertions(+), 121 deletions(-) diff --git a/contracts/gas-snapshots/ccip.gas-snapshot b/contracts/gas-snapshots/ccip.gas-snapshot index bafefa2261..6cb20b3a57 100644 --- a/contracts/gas-snapshots/ccip.gas-snapshot +++ b/contracts/gas-snapshots/ccip.gas-snapshot @@ -426,28 +426,33 @@ FeeQuoter_validatePoolReturnData:test_InvalidEVMAddressDestToken_Revert() (gas: FeeQuoter_validatePoolReturnData:test_ProcessPoolReturnData_Success() (gas: 73306) FeeQuoter_validatePoolReturnData:test_SourceTokenDataTooLarge_Revert() (gas: 107855) FeeQuoter_validatePoolReturnData:test_TokenAmountArraysMismatching_Revert() (gas: 40106) -HybridUSDCTokenPoolMigrationTests:test_LockOrBurn_LocKReleaseMechanism_then_switchToPrimary_Success() (gas: 208384) -HybridUSDCTokenPoolMigrationTests:test_LockOrBurn_PrimaryMechanism_Success() (gas: 135502) -HybridUSDCTokenPoolMigrationTests:test_LockOrBurn_WhileMigrationPause_Revert() (gas: 106651) -HybridUSDCTokenPoolMigrationTests:test_LockOrBurn_onLockReleaseMechanism_Success() (gas: 143944) -HybridUSDCTokenPoolMigrationTests:test_MintOrRelease_OnLockReleaseMechanism_Success() (gas: 230450) -HybridUSDCTokenPoolMigrationTests:test_MintOrRelease_OnLockReleaseMechanism_then_switchToPrimary_Success() (gas: 438517) -HybridUSDCTokenPoolMigrationTests:test_MintOrRelease_incomingMessageWithPrimaryMechanism() (gas: 270081) -HybridUSDCTokenPoolMigrationTests:test_burnLockedUSDC_invalidPermissions_Revert() (gas: 39130) -HybridUSDCTokenPoolMigrationTests:test_cancelExistingCCTPMigrationProposal() (gas: 31181) -HybridUSDCTokenPoolMigrationTests:test_cannotCancelANonExistentMigrationProposal() (gas: 12628) -HybridUSDCTokenPoolMigrationTests:test_cannotModifyLiquidityWithoutPermissions_Revert() (gas: 17158) -HybridUSDCTokenPoolMigrationTests:test_lockOrBurn_then_BurnInCCTPMigration_Success() (gas: 252682) -HybridUSDCTokenPoolMigrationTests:test_transferLiquidity_Success() (gas: 157130) -HybridUSDCTokenPoolMigrationTests:test_withdrawLiquidity_Success() (gas: 140828) -HybridUSDCTokenPoolTests:test_LockOrBurn_LocKReleaseMechanism_then_switchToPrimary_Success() (gas: 208164) -HybridUSDCTokenPoolTests:test_LockOrBurn_PrimaryMechanism_Success() (gas: 135396) -HybridUSDCTokenPoolTests:test_LockOrBurn_WhileMigrationPause_Revert() (gas: 106628) -HybridUSDCTokenPoolTests:test_LockOrBurn_onLockReleaseMechanism_Success() (gas: 143865) -HybridUSDCTokenPoolTests:test_MintOrRelease_OnLockReleaseMechanism_Success() (gas: 230383) -HybridUSDCTokenPoolTests:test_MintOrRelease_OnLockReleaseMechanism_then_switchToPrimary_Success() (gas: 438318) -HybridUSDCTokenPoolTests:test_MintOrRelease_incomingMessageWithPrimaryMechanism() (gas: 270011) -HybridUSDCTokenPoolTests:test_withdrawLiquidity_Success() (gas: 140783) +HybridUSDCTokenPoolMigrationTests:test_LockOrBurn_LockReleaseMechanism_then_switchToPrimary_Success() (gas: 208472) +HybridUSDCTokenPoolMigrationTests:test_LockOrBurn_PrimaryMechanism_Success() (gas: 135538) +HybridUSDCTokenPoolMigrationTests:test_LockOrBurn_WhileMigrationPause_Revert() (gas: 106706) +HybridUSDCTokenPoolMigrationTests:test_LockOrBurn_onLockReleaseMechanism_Success() (gas: 144163) +HybridUSDCTokenPoolMigrationTests:test_MintOrRelease_OnLockReleaseMechanism_Success() (gas: 214070) +HybridUSDCTokenPoolMigrationTests:test_MintOrRelease_OnLockReleaseMechanism_then_switchToPrimary_Success() (gas: 422174) +HybridUSDCTokenPoolMigrationTests:test_MintOrRelease_incomingMessageWithPrimaryMechanism() (gas: 268474) +HybridUSDCTokenPoolMigrationTests:test_ReleaseOrMint_WhileMigrationPause_Revert() (gas: 110983) +HybridUSDCTokenPoolMigrationTests:test_burnLockedUSDC_invalidPermissions_Revert() (gas: 39110) +HybridUSDCTokenPoolMigrationTests:test_cancelExistingCCTPMigrationProposal() (gas: 32949) +HybridUSDCTokenPoolMigrationTests:test_cannotCancelANonExistentMigrationProposal() (gas: 12606) +HybridUSDCTokenPoolMigrationTests:test_cannotModifyLiquidityWithoutPermissions_Revert() (gas: 13161) +HybridUSDCTokenPoolMigrationTests:test_cannotTransferLiquidityDuringPendingMigration_Revert() (gas: 160603) +HybridUSDCTokenPoolMigrationTests:test_lockOrBurn_then_BurnInCCTPMigration_Success() (gas: 254780) +HybridUSDCTokenPoolMigrationTests:test_transferLiquidity_Success() (gas: 165451) +HybridUSDCTokenPoolMigrationTests:test_unstickManualTxAfterMigration_destChain_Success() (gas: 153525) +HybridUSDCTokenPoolMigrationTests:test_unstickManualTxAfterMigration_homeChain_Success() (gas: 462264) +HybridUSDCTokenPoolTests:test_LockOrBurn_LockReleaseMechanism_then_switchToPrimary_Success() (gas: 208270) +HybridUSDCTokenPoolTests:test_LockOrBurn_PrimaryMechanism_Success() (gas: 135460) +HybridUSDCTokenPoolTests:test_LockOrBurn_WhileMigrationPause_Revert() (gas: 106751) +HybridUSDCTokenPoolTests:test_LockOrBurn_onLockReleaseMechanism_Success() (gas: 144151) +HybridUSDCTokenPoolTests:test_MintOrRelease_OnLockReleaseMechanism_Success() (gas: 214003) +HybridUSDCTokenPoolTests:test_MintOrRelease_OnLockReleaseMechanism_then_switchToPrimary_Success() (gas: 421969) +HybridUSDCTokenPoolTests:test_MintOrRelease_incomingMessageWithPrimaryMechanism() (gas: 268399) +HybridUSDCTokenPoolTests:test_ReleaseOrMint_WhileMigrationPause_Revert() (gas: 110982) +HybridUSDCTokenPoolTests:test_cannotTransferLiquidityDuringPendingMigration_Revert() (gas: 160548) +HybridUSDCTokenPoolTests:test_transferLiquidity_Success() (gas: 165371) LockReleaseTokenPoolAndProxy_setRebalancer:test_SetRebalancer_Revert() (gas: 10977) LockReleaseTokenPoolAndProxy_setRebalancer:test_SetRebalancer_Success() (gas: 17998) LockReleaseTokenPoolPoolAndProxy_canAcceptLiquidity:test_CanAcceptLiquidity_Success() (gas: 3315195) diff --git a/contracts/src/v0.8/ccip/pools/USDC/HybridLockReleaseUSDCTokenPool.sol b/contracts/src/v0.8/ccip/pools/USDC/HybridLockReleaseUSDCTokenPool.sol index 49cdeafcbc..5fbd71bb2c 100644 --- a/contracts/src/v0.8/ccip/pools/USDC/HybridLockReleaseUSDCTokenPool.sol +++ b/contracts/src/v0.8/ccip/pools/USDC/HybridLockReleaseUSDCTokenPool.sol @@ -4,6 +4,7 @@ pragma solidity 0.8.24; import {ILiquidityContainer} from "../../../liquiditymanager/interfaces/ILiquidityContainer.sol"; import {ITokenMessenger} from "../USDC/ITokenMessenger.sol"; +import {OwnerIsCreator} from "../../../shared/access/OwnerIsCreator.sol"; import {Pool} from "../../libraries/Pool.sol"; import {TokenPool} from "../TokenPool.sol"; import {USDCTokenPool} from "../USDC/USDCTokenPool.sol"; @@ -33,6 +34,9 @@ contract HybridLockReleaseUSDCTokenPool is USDCTokenPool, USDCBridgeMigrator { error LanePausedForCCTPMigration(uint64 remoteChainSelector); error TokenLockingNotAllowedAfterMigration(uint64 remoteChainSelector); + /// bytes4(keccak256("NO_CTTP_USE_LOCK_RELEASE")) + bytes4 public constant LOCK_RELEASE_FLAG = 0xd43c7897; + /// @notice The address of the liquidity provider for a specific chain. /// External liquidity is not required when there is one canonical token deployed to a chain, /// and CCIP is facilitating mint/burn on all the other chains, in which case the invariant @@ -75,9 +79,16 @@ contract HybridLockReleaseUSDCTokenPool is USDCTokenPool, USDCBridgeMigrator { function releaseOrMint( Pool.ReleaseOrMintInV1 calldata releaseOrMintIn ) public virtual override returns (Pool.ReleaseOrMintOutV1 memory) { - if (!shouldUseLockRelease(releaseOrMintIn.remoteChainSelector)) { + // Use CCTP Burn/Mint mechanism for chains which have it enabled. The LOCK_RELEASE_FLAG is used in sourcePoolData to + // discern this, since the source-chain will not be a hybrid-pool but a standard burn-mint. In the event of a + // stuck message after a migration has occured, and the message was not executed properly before the migration + // began, and locked tokens were not released until now, the message will already have been committed to with this + // flag so it is safe to release the tokens. The source USDC pool is trusted to send messages with the correct + // flag as well. + if (bytes4(releaseOrMintIn.sourcePoolData) != LOCK_RELEASE_FLAG) { return super.releaseOrMint(releaseOrMintIn); } + return _lockReleaseIncomingMessage(releaseOrMintIn); } @@ -87,8 +98,21 @@ contract HybridLockReleaseUSDCTokenPool is USDCTokenPool, USDCBridgeMigrator { ) internal virtual returns (Pool.ReleaseOrMintOutV1 memory) { _validateReleaseOrMint(releaseOrMintIn); + // Circle requires a supply-lock to prevent incoming messages once the migration process begins. + // This prevents new outgoing messages once the migration has begun to ensure any the procedure runs as expected + if (s_proposedUSDCMigrationChain == releaseOrMintIn.remoteChainSelector) { + revert LanePausedForCCTPMigration(s_proposedUSDCMigrationChain); + } + // Decrease internal tracking of locked tokens to ensure accurate accounting for burnLockedUSDC() migration - s_lockedTokensByChainSelector[releaseOrMintIn.remoteChainSelector] -= releaseOrMintIn.amount; + // If the chain has already been migrated, then this mapping would be zero, and the operation would underflow. + // This branch ensures that we're subtracting from the correct mapping. It is also safe to subtract from the + // excluded tokens mapping, as this function would only be invoked in the event of a stuck tx after a migration + if (s_lockedTokensByChainSelector[releaseOrMintIn.remoteChainSelector] == 0) { + s_tokensExcludedFromBurn[releaseOrMintIn.remoteChainSelector] -= releaseOrMintIn.amount; + } else { + s_lockedTokensByChainSelector[releaseOrMintIn.remoteChainSelector] -= releaseOrMintIn.amount; + } // Release to the offRamp, which forwards it to the recipient getToken().safeTransfer(releaseOrMintIn.receiver, releaseOrMintIn.amount); @@ -109,7 +133,10 @@ contract HybridLockReleaseUSDCTokenPool is USDCTokenPool, USDCBridgeMigrator { emit Locked(msg.sender, lockOrBurnIn.amount); - return Pool.LockOrBurnOutV1({destTokenAddress: getRemoteToken(lockOrBurnIn.remoteChainSelector), destPoolData: ""}); + return Pool.LockOrBurnOutV1({ + destTokenAddress: getRemoteToken(lockOrBurnIn.remoteChainSelector), + destPoolData: abi.encode(LOCK_RELEASE_FLAG) + }); } // ================================================================ @@ -135,7 +162,10 @@ contract HybridLockReleaseUSDCTokenPool is USDCTokenPool, USDCBridgeMigrator { /// @notice Adds liquidity to the pool for a specific chain. The tokens should be approved first. /// @dev Liquidity is expected to be added on a per chain basis. Parties are expected to provide liquidity for their /// own chain which implements non canonical USDC and liquidity is not shared across lanes. - /// @param amount The amount of liquidity to provide. + /// @dev Once liquidity is added, it is locked in the pool until it is removed by an incoming message on the + /// lock release mechanism. This is a hard requirement by Circle to ensure parity with the destination chain + /// supply is maintained. + /// @param amount The amount of tokens to provide as liquidity. /// @param remoteChainSelector The chain for which liquidity is provided to. Necessary to ensure there's accurate /// parity between locked USDC in this contract and the circulating supply on the remote chain function provideLiquidity(uint64 remoteChainSelector, uint256 amount) external { @@ -154,32 +184,49 @@ contract HybridLockReleaseUSDCTokenPool is USDCTokenPool, USDCBridgeMigrator { /// @dev The function should only be called if non canonical USDC on the remote chain has been burned and is not being /// withdrawn on this chain, otherwise a mismatch may occur between locked token balance and remote circulating supply /// which may block a potential future migration of the chain to CCTP. - function withdrawLiquidity(uint64 remoteChainSelector, uint256 amount) external { - if (s_liquidityProvider[remoteChainSelector] != msg.sender) revert TokenPool.Unauthorized(msg.sender); + function withdrawLiquidity(uint64 remoteChainSelector, uint256 amount) external onlyOwner { + // Circle requires a supply-lock to prevent outgoing messages once the migration process begins. + // This prevents new outgoing messages once the migration has begun to ensure any the procedure runs as expected + if (remoteChainSelector == s_proposedUSDCMigrationChain) { + revert LanePausedForCCTPMigration(remoteChainSelector); + } s_lockedTokensByChainSelector[remoteChainSelector] -= amount; i_token.safeTransfer(msg.sender, amount); + emit ILiquidityContainer.LiquidityRemoved(msg.sender, amount); } /// @notice This function can be used to transfer liquidity from an older version of the pool to this pool. To do so - /// this pool will have to be set as the liquidity provider in the older version of the pool. This allows it to transfer the - /// funds in the old pool to the new pool. + /// this pool must be the owner of the old pool. Since the pool uses two-step ownership transfer, the old pool must + /// first propose the ownership transfer, and then this pool must accept it. This function can only be called after + /// the ownership transfer has been proposed, as it will accept it and then make the call to withdrawLiquidity /// @dev When upgrading a LockRelease pool, this function can be called at the same time as the pool is changed in the /// TokenAdminRegistry. This allows for a smooth transition of both liquidity and transactions to the new pool. /// Alternatively, when no multicall is available, a portion of the funds can be transferred to the new pool before /// changing which pool CCIP uses, to ensure both pools can operate. Then the pool should be changed in the /// TokenAdminRegistry, which will activate the new pool. All new transactions will use the new pool and its - /// liquidity. Finally, the remaining liquidity can be transferred to the new pool using this function one more time. + /// liquidity. /// @param from The address of the old pool. - /// @param amount The amount of liquidity to transfer. - function transferLiquidity(address from, uint64 remoteChainSelector, uint256 amount) external onlyOwner { - HybridLockReleaseUSDCTokenPool(from).withdrawLiquidity(remoteChainSelector, amount); + /// @param remoteChainSelector The chain for which liquidity is being transferred. + function transferLiquidity(address from, uint64 remoteChainSelector) external onlyOwner { + // Prevent Liquidity Transfers when a migration is pending. This prevents requiring the new pool to manage + // token exclusions for edge-case messages and ensures that the migration is completed before any new liquidity + // is added to the pool. + if (HybridLockReleaseUSDCTokenPool(from).getCurrentProposedCCTPChainMigration() == remoteChainSelector) { + revert LanePausedForCCTPMigration(remoteChainSelector); + } - s_lockedTokensByChainSelector[remoteChainSelector] += amount; + OwnerIsCreator(from).acceptOwnership(); + + // Withdraw all available liquidity from the old pool. + uint256 withdrawAmount = HybridLockReleaseUSDCTokenPool(from).getLockedTokensForChain(remoteChainSelector); + HybridLockReleaseUSDCTokenPool(from).withdrawLiquidity(remoteChainSelector, withdrawAmount); + + s_lockedTokensByChainSelector[remoteChainSelector] += withdrawAmount; - emit LiquidityTransferred(from, remoteChainSelector, amount); + emit LiquidityTransferred(from, remoteChainSelector, withdrawAmount); } // ================================================================ diff --git a/contracts/src/v0.8/ccip/pools/USDC/USDCBridgeMigrator.sol b/contracts/src/v0.8/ccip/pools/USDC/USDCBridgeMigrator.sol index 827787f4cf..98616cd79f 100644 --- a/contracts/src/v0.8/ccip/pools/USDC/USDCBridgeMigrator.sol +++ b/contracts/src/v0.8/ccip/pools/USDC/USDCBridgeMigrator.sol @@ -8,8 +8,8 @@ import {EnumerableSet} from "../../../vendor/openzeppelin-solidity/v4.8.3/contra import {Router} from "../../Router.sol"; /// @notice Allows migration of a lane in a token pool from Lock/Release to CCTP supported Burn/Mint. Contract -/// functionality is based on hard requirements defined by Circle to allow future CCTP compatibility -/// @dev Once a migration for a lane has occured, it can never be reversed, and CCTP will be the mechanism forever. This makes the assumption that Circle will continue to support that lane indefinitely. +/// functionality is based on hard requirements defined by Circle to allow for future CCTP compatibility +/// https://github.com/circlefin/stablecoin-evm/blob/master/doc/bridged_USDC_standard.md abstract contract USDCBridgeMigrator is OwnerIsCreator { using EnumerableSet for EnumerableSet.UintSet; @@ -17,6 +17,9 @@ abstract contract USDCBridgeMigrator is OwnerIsCreator { event CCTPMigrationExecuted(uint64 remoteChainSelector, uint256 USDCBurned); event CCTPMigrationCancelled(uint64 existingProposalSelector); event CircleMigratorAddressSet(address migratorAddress); + event TokensExcludedFromBurn( + uint64 indexed remoteChainSelector, uint256 amount, uint256 burnableAmountAfterExclusion + ); error onlyCircle(); error ExistingMigrationProposal(); @@ -31,6 +34,7 @@ abstract contract USDCBridgeMigrator is OwnerIsCreator { uint64 internal s_proposedUSDCMigrationChain; mapping(uint64 chainSelector => uint256 lockedBalance) internal s_lockedTokensByChainSelector; + mapping(uint64 remoteChainSelector => uint256 excludedTokens) internal s_tokensExcludedFromBurn; mapping(uint64 chainSelector => bool shouldUseLockRelease) internal s_shouldUseLockRelease; @@ -50,7 +54,10 @@ abstract contract USDCBridgeMigrator is OwnerIsCreator { if (s_proposedUSDCMigrationChain == 0) revert ExistingMigrationProposal(); uint64 burnChainSelector = s_proposedUSDCMigrationChain; - uint256 tokensToBurn = s_lockedTokensByChainSelector[burnChainSelector]; + + // Burnable tokens is the total locked minus the amount excluded from burn + uint256 tokensToBurn = + s_lockedTokensByChainSelector[burnChainSelector] - s_tokensExcludedFromBurn[burnChainSelector]; // Even though USDC is a trusted call, ensure CEI by updating state first delete s_lockedTokensByChainSelector[burnChainSelector]; @@ -70,8 +77,8 @@ abstract contract USDCBridgeMigrator is OwnerIsCreator { /// @notice Propose a destination chain to migrate from lock/release mechanism to CCTP enabled burn/mint /// through a Circle controlled burn. /// @param remoteChainSelector the CCIP specific selector for the remote chain currently using a - /// non-canonical form of USDC which they wish to update to canonical. Function will revert if the chain - /// selector is zero, or if a migration has already occured for the specified selector. + /// non-canonical form of USDC which they wish to update to canonical. Function will revert if an existing migration + /// proposal is already in progress. /// @dev This function can only be called by the owner function proposeCCTPMigration(uint64 remoteChainSelector) external onlyOwner { // Prevent overwriting existing migration proposals until the current one is finished @@ -83,12 +90,17 @@ abstract contract USDCBridgeMigrator is OwnerIsCreator { } /// @notice Cancel an existing proposal to migrate a lane to CCTP. + /// @notice This function will revert if no proposal is currently in progress. function cancelExistingCCTPMigrationProposal() external onlyOwner { if (s_proposedUSDCMigrationChain == 0) revert NoExistingMigrationProposal(); uint64 currentProposalChainSelector = s_proposedUSDCMigrationChain; delete s_proposedUSDCMigrationChain; + // If a migration is cancelled, the tokens excluded from burn should be reset, and must be manually + // re-excluded if the proposal is re-proposed in the future + delete s_tokensExcludedFromBurn[currentProposalChainSelector]; + emit CCTPMigrationCancelled(currentProposalChainSelector); } @@ -116,4 +128,27 @@ abstract contract USDCBridgeMigrator is OwnerIsCreator { function getLockedTokensForChain(uint64 remoteChainSelector) public view returns (uint256) { return s_lockedTokensByChainSelector[remoteChainSelector]; } + + /// @notice Exclude tokens to be burned in a CCTP-migration because the amount are locked in an undelivered message. + /// @dev When a message is sitting in manual execution from the L/R chain, those tokens need to be excluded from + /// being burned in a CCTP-migration otherwise the message will never be able to be delivered due to it not having + /// an attestation on the source-chain to mint. In that instance it should use provided liquidity that was designated + /// @dev This function should ONLY be called on the home chain, where tokens are locked, NOT on the remote chain + /// and strict scrutiny should be applied to ensure that the amount of tokens excluded is accurate. + function excludeTokensFromBurn(uint64 remoteChainSelector, uint256 amount) external onlyOwner { + s_tokensExcludedFromBurn[remoteChainSelector] += amount; + + uint256 burnableAmountAfterExclusion = + s_lockedTokensByChainSelector[remoteChainSelector] - s_tokensExcludedFromBurn[remoteChainSelector]; + + emit TokensExcludedFromBurn(remoteChainSelector, amount, burnableAmountAfterExclusion); + } + + /// @notice Get the amount of tokens excluded from being burned in a CCTP-migration + /// @dev The sum of locked tokens and excluded tokens should equal the supply of the token on the remote chain + /// @param remoteChainSelector The chain for which the excluded tokens are being queried + /// @return uint256 amount of tokens excluded from being burned in a CCTP-migration + function getExcludedTokensByChain(uint64 remoteChainSelector) public view returns (uint256) { + return s_tokensExcludedFromBurn[remoteChainSelector]; + } } diff --git a/contracts/src/v0.8/ccip/test/pools/HybridLockReleaseUSDCTokenPool.t.sol b/contracts/src/v0.8/ccip/test/pools/HybridLockReleaseUSDCTokenPool.t.sol index 96216c6fcc..ddb8c29dc2 100644 --- a/contracts/src/v0.8/ccip/test/pools/HybridLockReleaseUSDCTokenPool.t.sol +++ b/contracts/src/v0.8/ccip/test/pools/HybridLockReleaseUSDCTokenPool.t.sol @@ -17,7 +17,6 @@ import {HybridLockReleaseUSDCTokenPool} from "../../pools/USDC/HybridLockRelease import {USDCBridgeMigrator} from "../../pools/USDC/USDCBridgeMigrator.sol"; import {USDCTokenPool} from "../../pools/USDC/USDCTokenPool.sol"; import {BaseTest} from "../BaseTest.t.sol"; -import {USDCTokenPoolHelper} from "../helpers/USDCTokenPoolHelper.sol"; import {MockE2EUSDCTransmitter} from "../mocks/MockE2EUSDCTransmitter.sol"; import {MockUSDCTokenMessenger} from "../mocks/MockUSDCTokenMessenger.sol"; @@ -111,6 +110,7 @@ contract USDCTokenPoolSetup is BaseTest { emit HybridLockReleaseUSDCTokenPool.LiquidityProviderSet(address(0), OWNER, DEST_CHAIN_SELECTOR); s_usdcTokenPool.setLiquidityProvider(DEST_CHAIN_SELECTOR, OWNER); + s_usdcTokenPool.setLiquidityProvider(SOURCE_CHAIN_SELECTOR, OWNER); } function setUpRamps() internal { @@ -224,7 +224,7 @@ contract HybridUSDCTokenPoolTests is USDCTokenPoolSetup { localToken: address(s_token), remoteChainSelector: SOURCE_CHAIN_SELECTOR, sourcePoolAddress: sourceTokenData.sourcePoolAddress, - sourcePoolData: "", + sourcePoolData: abi.encode(s_usdcTokenPool.LOCK_RELEASE_FLAG()), offchainTokenData: "" }) ); @@ -329,7 +329,7 @@ contract HybridUSDCTokenPoolTests is USDCTokenPoolSetup { ); } - function test_LockOrBurn_LocKReleaseMechanism_then_switchToPrimary_Success() public { + function test_LockOrBurn_LockReleaseMechanism_then_switchToPrimary_Success() public { // Test Enabling the LR mechanism and sending an outgoing message test_LockOrBurn_PrimaryMechanism_Success(); @@ -372,44 +372,6 @@ contract HybridUSDCTokenPoolTests is USDCTokenPoolSetup { test_MintOrRelease_incomingMessageWithPrimaryMechanism(); } - function test_withdrawLiquidity_Success() public { - uint256 liquidityAmount = 1e12; - - vm.startPrank(OWNER); - s_token.approve(address(s_usdcTokenPool), type(uint256).max); - - s_usdcTokenPool.setLiquidityProvider(SOURCE_CHAIN_SELECTOR, OWNER); - assertEq(s_usdcTokenPool.getLiquidityProvider(SOURCE_CHAIN_SELECTOR), OWNER, "Owner is not Rebalancer"); - - s_usdcTokenPool.provideLiquidity(SOURCE_CHAIN_SELECTOR, liquidityAmount); - - assertEq(s_usdcTokenPool.getLockedTokensForChain(SOURCE_CHAIN_SELECTOR), liquidityAmount); - - assertEq( - s_token.balanceOf(address(s_usdcTokenPool)), - liquidityAmount, - "Available tokens doesn't match provided liquidity amount" - ); - - uint256 withdrawalAmount = liquidityAmount / 2; // Withdraw half of the liquidity - - vm.expectEmit(); - emit ILiquidityContainer.LiquidityRemoved(OWNER, withdrawalAmount); - - s_usdcTokenPool.withdrawLiquidity(SOURCE_CHAIN_SELECTOR, withdrawalAmount); - - assertEq( - s_usdcTokenPool.getLockedTokensForChain(SOURCE_CHAIN_SELECTOR), - liquidityAmount - withdrawalAmount, - "Remaining liquidity incorrect" - ); - assertEq( - s_token.balanceOf(address(s_usdcTokenPool)), - liquidityAmount - withdrawalAmount, - "Available tokens doesn't match provided liquidity amount" - ); - } - function test_LockOrBurn_WhileMigrationPause_Revert() public { // Create a fake migration proposal s_usdcTokenPool.proposeCCTPMigration(DEST_CHAIN_SELECTOR); @@ -450,6 +412,140 @@ contract HybridUSDCTokenPoolTests is USDCTokenPoolSetup { }) ); } + + function test_ReleaseOrMint_WhileMigrationPause_Revert() public { + address recipient = address(1234); + + // Designate the SOURCE_CHAIN as not using native-USDC, and so the L/R mechanism must be used instead + uint64[] memory destChainAdds = new uint64[](1); + destChainAdds[0] = SOURCE_CHAIN_SELECTOR; + + s_usdcTokenPool.updateChainSelectorMechanisms(new uint64[](0), destChainAdds); + + assertTrue( + s_usdcTokenPool.shouldUseLockRelease(SOURCE_CHAIN_SELECTOR), + "Lock/Release mech not configured for incoming message from SOURCE_CHAIN_SELECTOR" + ); + + vm.startPrank(OWNER); + + vm.expectEmit(); + emit USDCBridgeMigrator.CCTPMigrationProposed(SOURCE_CHAIN_SELECTOR); + + // Propose the migration to CCTP + s_usdcTokenPool.proposeCCTPMigration(SOURCE_CHAIN_SELECTOR); + + Internal.SourceTokenData memory sourceTokenData = Internal.SourceTokenData({ + sourcePoolAddress: abi.encode(SOURCE_CHAIN_USDC_POOL), + destTokenAddress: abi.encode(address(s_usdcTokenPool)), + extraData: abi.encode(USDCTokenPool.SourceTokenDataPayload({nonce: 1, sourceDomain: SOURCE_DOMAIN_IDENTIFIER})), + destGasAmount: USDC_DEST_TOKEN_GAS + }); + + bytes memory sourcePoolDataLockRelease = abi.encode(s_usdcTokenPool.LOCK_RELEASE_FLAG()); + + uint256 amount = 1e6; + + vm.startPrank(s_routerAllowedOffRamp); + + // Expect revert because the lane is paused and no incoming messages should be allowed + vm.expectRevert( + abi.encodeWithSelector(HybridLockReleaseUSDCTokenPool.LanePausedForCCTPMigration.selector, SOURCE_CHAIN_SELECTOR) + ); + + s_usdcTokenPool.releaseOrMint( + Pool.ReleaseOrMintInV1({ + originalSender: abi.encode(OWNER), + receiver: recipient, + amount: amount, + localToken: address(s_token), + remoteChainSelector: SOURCE_CHAIN_SELECTOR, + sourcePoolAddress: sourceTokenData.sourcePoolAddress, + sourcePoolData: sourcePoolDataLockRelease, + offchainTokenData: "" + }) + ); + } + + function test_transferLiquidity_Success() public { + // Set as the OWNER so we can provide liquidity + vm.startPrank(OWNER); + + s_usdcTokenPool.setLiquidityProvider(DEST_CHAIN_SELECTOR, OWNER); + s_token.approve(address(s_usdcTokenPool), type(uint256).max); + + uint256 liquidityAmount = 1e9; + + // Provide some liquidity to the pool + s_usdcTokenPool.provideLiquidity(DEST_CHAIN_SELECTOR, liquidityAmount); + + // Set the new token pool as the rebalancer + s_usdcTokenPool.transferOwnership(address(s_usdcTokenPoolTransferLiquidity)); + + vm.expectEmit(); + emit ILiquidityContainer.LiquidityRemoved(address(s_usdcTokenPoolTransferLiquidity), liquidityAmount); + + vm.expectEmit(); + emit HybridLockReleaseUSDCTokenPool.LiquidityTransferred( + address(s_usdcTokenPool), DEST_CHAIN_SELECTOR, liquidityAmount + ); + + s_usdcTokenPoolTransferLiquidity.transferLiquidity(address(s_usdcTokenPool), DEST_CHAIN_SELECTOR); + + assertEq( + s_usdcTokenPool.owner(), + address(s_usdcTokenPoolTransferLiquidity), + "Ownership of the old pool should be transferred to the new pool" + ); + + assertEq( + s_usdcTokenPoolTransferLiquidity.getLockedTokensForChain(DEST_CHAIN_SELECTOR), + liquidityAmount, + "Tokens locked for dest chain doesn't match expected amount in storage" + ); + + assertEq( + s_usdcTokenPool.getLockedTokensForChain(DEST_CHAIN_SELECTOR), + 0, + "Tokens locked for dest chain in old token pool doesn't match expected amount in storage" + ); + + assertEq( + s_token.balanceOf(address(s_usdcTokenPoolTransferLiquidity)), + liquidityAmount, + "Liquidity amount of tokens should be new in new pool, but aren't" + ); + + assertEq( + s_token.balanceOf(address(s_usdcTokenPool)), + 0, + "Liquidity amount of tokens should be zero in old pool, but aren't" + ); + } + + function test_cannotTransferLiquidityDuringPendingMigration_Revert() public { + // Set as the OWNER so we can provide liquidity + vm.startPrank(OWNER); + + s_usdcTokenPool.setLiquidityProvider(DEST_CHAIN_SELECTOR, OWNER); + s_token.approve(address(s_usdcTokenPool), type(uint256).max); + + uint256 liquidityAmount = 1e9; + + // Provide some liquidity to the pool + s_usdcTokenPool.provideLiquidity(DEST_CHAIN_SELECTOR, liquidityAmount); + + // Set the new token pool as the rebalancer + s_usdcTokenPool.transferOwnership(address(s_usdcTokenPoolTransferLiquidity)); + + s_usdcTokenPool.proposeCCTPMigration(DEST_CHAIN_SELECTOR); + + vm.expectRevert( + abi.encodeWithSelector(HybridLockReleaseUSDCTokenPool.LanePausedForCCTPMigration.selector, DEST_CHAIN_SELECTOR) + ); + + s_usdcTokenPoolTransferLiquidity.transferLiquidity(address(s_usdcTokenPool), DEST_CHAIN_SELECTOR); + } } contract HybridUSDCTokenPoolMigrationTests is HybridUSDCTokenPoolTests { @@ -592,70 +688,197 @@ contract HybridUSDCTokenPoolMigrationTests is HybridUSDCTokenPoolTests { s_usdcTokenPool.burnLockedUSDC(); } - function test_transferLiquidity_Success() public { - // Set as the OWNER so we can provide liquidity - vm.startPrank(OWNER); - s_usdcTokenPoolTransferLiquidity.setLiquidityProvider(DEST_CHAIN_SELECTOR, OWNER); + function test_cannotModifyLiquidityWithoutPermissions_Revert() public { + address randomAddr = makeAddr("RANDOM"); - s_token.approve(address(s_usdcTokenPoolTransferLiquidity), type(uint256).max); + vm.startPrank(randomAddr); - uint256 liquidityAmount = 1e9; + vm.expectRevert(abi.encodeWithSelector(TokenPool.Unauthorized.selector, randomAddr)); - // Provide 1000 USDC as liquidity - s_usdcTokenPoolTransferLiquidity.provideLiquidity(DEST_CHAIN_SELECTOR, liquidityAmount); + // Revert because there's insufficient permissions for the DEST_CHAIN_SELECTOR to provide liquidity + s_usdcTokenPool.provideLiquidity(DEST_CHAIN_SELECTOR, 1e6); + } - // Set the new token pool as the rebalancer - s_usdcTokenPoolTransferLiquidity.setLiquidityProvider(DEST_CHAIN_SELECTOR, address(s_usdcTokenPool)); + function test_cannotCancelANonExistentMigrationProposal() public { + vm.expectRevert(USDCBridgeMigrator.NoExistingMigrationProposal.selector); - vm.expectEmit(); - emit ILiquidityContainer.LiquidityRemoved(address(s_usdcTokenPool), liquidityAmount); + // Proposal to migrate doesn't exist, and so the chain selector is zero, and therefore should revert + s_usdcTokenPool.cancelExistingCCTPMigrationProposal(); + } + + function test_unstickManualTxAfterMigration_destChain_Success() public { + address recipient = address(1234); + // Test the edge case where a tx is stuck in the manual tx queue and the destination chain is the one that + // should process is after a migration. I.E the message will have the Lock-Release flag set in the OffChainData, + // which should tell it to use the lock-release mechanism with the tokens provided. + + // We want the released amount to be 1e6, so to simulate the workflow, we sent those tokens to the contract as + // liquidity + uint256 amount = 1e6; + // Add 1e12 liquidity so that there's enough to release + vm.startPrank(s_usdcTokenPool.getLiquidityProvider(SOURCE_CHAIN_SELECTOR)); + + s_token.approve(address(s_usdcTokenPool), type(uint256).max); + s_usdcTokenPool.provideLiquidity(SOURCE_CHAIN_SELECTOR, amount); + + // By Default, the source chain will be indicated as use-CCTP so we need to change that. We create a message + // that will use the Lock-Release flag in the offchain data to indicate that the tokens should be released + // instead of minted since there's no attestation for us to use. + + vm.startPrank(s_routerAllowedOffRamp); vm.expectEmit(); - emit HybridLockReleaseUSDCTokenPool.LiquidityTransferred( - address(s_usdcTokenPoolTransferLiquidity), DEST_CHAIN_SELECTOR, liquidityAmount + emit TokenPool.Released(s_routerAllowedOffRamp, recipient, amount); + + Internal.SourceTokenData memory sourceTokenData = Internal.SourceTokenData({ + sourcePoolAddress: abi.encode(SOURCE_CHAIN_USDC_POOL), + destTokenAddress: abi.encode(address(s_usdcTokenPool)), + extraData: abi.encode(USDCTokenPool.SourceTokenDataPayload({nonce: 1, sourceDomain: SOURCE_DOMAIN_IDENTIFIER})), + destGasAmount: USDC_DEST_TOKEN_GAS + }); + + Pool.ReleaseOrMintOutV1 memory poolReturnDataV1 = s_usdcTokenPool.releaseOrMint( + Pool.ReleaseOrMintInV1({ + originalSender: abi.encode(OWNER), + receiver: recipient, + amount: amount, + localToken: address(s_token), + remoteChainSelector: SOURCE_CHAIN_SELECTOR, + sourcePoolAddress: sourceTokenData.sourcePoolAddress, + sourcePoolData: abi.encode(s_usdcTokenPool.LOCK_RELEASE_FLAG()), + offchainTokenData: "" + }) + ); + + // By this point, the tx should have executed, with the Lock-Release taking over, and being forwaded to the + // recipient + + assertEq(poolReturnDataV1.destinationAmount, amount, "destinationAmount and actual amount transferred differ"); + assertEq(s_token.balanceOf(address(s_usdcTokenPool)), 0, "Tokens should be transferred out of the pool"); + assertEq(s_token.balanceOf(recipient), amount, "Tokens should be transferred to the recipient"); + + // We also want to check that the system uses CCTP Burn/Mint for all other messages that don't have that flag + // which after a migration will mean all new messages. + + // The message should fail without an error because it failed to decode a non-existent attestation which would + // revert without an error + vm.expectRevert(); + + s_usdcTokenPool.releaseOrMint( + Pool.ReleaseOrMintInV1({ + originalSender: abi.encode(OWNER), + receiver: recipient, + amount: amount, + localToken: address(s_token), + remoteChainSelector: SOURCE_CHAIN_SELECTOR, + sourcePoolAddress: sourceTokenData.sourcePoolAddress, + sourcePoolData: "", + offchainTokenData: "" + }) ); + } - s_usdcTokenPool.transferLiquidity(address(s_usdcTokenPoolTransferLiquidity), DEST_CHAIN_SELECTOR, liquidityAmount); + function test_unstickManualTxAfterMigration_homeChain_Success() public { + address CIRCLE = makeAddr("CIRCLE"); + address recipient = address(1234); + + // Mark the destination chain as supporting CCTP, so use L/R instead. + uint64[] memory destChainAdds = new uint64[](1); + destChainAdds[0] = DEST_CHAIN_SELECTOR; + + s_usdcTokenPool.updateChainSelectorMechanisms(new uint64[](0), destChainAdds); + + // Test the edge case where a tx is stuck in the manual tx queue and the source chain (mainnet) needs unsticking + // In this test we want 1e6 worth of tokens to be stuck, so first we provide liquidity to the pool >1e6 + + uint256 amount = 1e6; + // Add 1e12 liquidity so that there's enough to release + vm.startPrank(s_usdcTokenPool.getLiquidityProvider(SOURCE_CHAIN_SELECTOR)); + + s_token.approve(address(s_usdcTokenPool), type(uint256).max); + + // I picked 3x the amount to be stuck so that we can have enough to release with a buffer + s_usdcTokenPool.provideLiquidity(SOURCE_CHAIN_SELECTOR, amount * 3); + + // At this point in the process, the router will lock new messages, so we want to simulate excluding tokens + // stuck coming back from the destination, to the home chain. This way they can be released and not minted + // since there's no corresponding attestation to use for minting. + vm.startPrank(OWNER); + + // Exclude the tokens from being burned and check for the event + vm.expectEmit(); + emit USDCBridgeMigrator.TokensExcludedFromBurn(SOURCE_CHAIN_SELECTOR, amount, (amount * 3) - amount); + + s_usdcTokenPool.excludeTokensFromBurn(SOURCE_CHAIN_SELECTOR, amount); assertEq( - s_usdcTokenPool.getLockedTokensForChain(DEST_CHAIN_SELECTOR), - liquidityAmount, - "Tokens locked for dest chain doesn't match expected amount in storage" + s_usdcTokenPool.getLockedTokensForChain(SOURCE_CHAIN_SELECTOR), + (amount * 3), + "Tokens locked minus ones excluded from the burn should be 2e6" ); assertEq( - s_usdcTokenPoolTransferLiquidity.getLockedTokensForChain(DEST_CHAIN_SELECTOR), - 0, - "Tokens locked for dest chain in old token pool doesn't match expected amount in storage" + s_usdcTokenPool.getExcludedTokensByChain(SOURCE_CHAIN_SELECTOR), + 1e6, + "1e6 tokens should be excluded from the burn" ); + s_usdcTokenPool.setCircleMigratorAddress(CIRCLE); + + s_usdcTokenPool.proposeCCTPMigration(SOURCE_CHAIN_SELECTOR); + + vm.startPrank(CIRCLE); + + s_usdcTokenPool.burnLockedUSDC(); + assertEq( - s_token.balanceOf(address(s_usdcTokenPool)), - liquidityAmount, - "Liquidity amount of tokens should be new in new pool, but aren't" + s_usdcTokenPool.getLockedTokensForChain(SOURCE_CHAIN_SELECTOR), 0, "All tokens should be burned out of the pool" ); - } - function test_cannotModifyLiquidityWithoutPermissions_Revert() public { - address randomAddr = makeAddr("RANDOM"); + assertEq( + s_usdcTokenPool.getExcludedTokensByChain(SOURCE_CHAIN_SELECTOR), + 1e6, + "There should still be 1e6 tokens excluded from the burn" + ); - vm.startPrank(randomAddr); + assertEq(s_token.balanceOf(address(s_usdcTokenPool)), 1e6, "All tokens minus the excluded should be in the pool"); - vm.expectRevert(abi.encodeWithSelector(TokenPool.Unauthorized.selector, randomAddr)); + // Now that the burn is successful, we can release the tokens that were excluded from the burn + vm.startPrank(s_routerAllowedOffRamp); - // Revert because there's insufficient permissions for the DEST_CHAIN_SELECTOR to provide liquidity - s_usdcTokenPool.provideLiquidity(DEST_CHAIN_SELECTOR, 1e6); + vm.expectEmit(); + emit TokenPool.Released(s_routerAllowedOffRamp, recipient, amount); - vm.expectRevert(abi.encodeWithSelector(TokenPool.Unauthorized.selector, randomAddr)); + Internal.SourceTokenData memory sourceTokenData = Internal.SourceTokenData({ + sourcePoolAddress: abi.encode(SOURCE_CHAIN_USDC_POOL), + destTokenAddress: abi.encode(address(s_usdcTokenPool)), + extraData: abi.encode(USDCTokenPool.SourceTokenDataPayload({nonce: 1, sourceDomain: SOURCE_DOMAIN_IDENTIFIER})), + destGasAmount: USDC_DEST_TOKEN_GAS + }); - // Revert because there's insufficient permissions for the DEST_CHAIN_SELECTOR to withdraw liquidity - s_usdcTokenPool.withdrawLiquidity(DEST_CHAIN_SELECTOR, 1e6); - } + Pool.ReleaseOrMintOutV1 memory poolReturnDataV1 = s_usdcTokenPool.releaseOrMint( + Pool.ReleaseOrMintInV1({ + originalSender: abi.encode(OWNER), + receiver: recipient, + amount: amount, + localToken: address(s_token), + remoteChainSelector: SOURCE_CHAIN_SELECTOR, + sourcePoolAddress: sourceTokenData.sourcePoolAddress, + sourcePoolData: abi.encode(s_usdcTokenPool.LOCK_RELEASE_FLAG()), + offchainTokenData: "" + }) + ); - function test_cannotCancelANonExistentMigrationProposal() public { - vm.expectRevert(USDCBridgeMigrator.NoExistingMigrationProposal.selector); + assertEq(poolReturnDataV1.destinationAmount, amount, "destinationAmount and actual amount transferred differ"); + assertEq(s_token.balanceOf(address(s_usdcTokenPool)), 0, "Tokens should be transferred out of the pool"); + assertEq(s_token.balanceOf(recipient), amount, "Tokens should be transferred to the recipient"); + assertEq( + s_usdcTokenPool.getExcludedTokensByChain(SOURCE_CHAIN_SELECTOR), + 0, + "All tokens should be released from the exclusion list" + ); - // Proposal to migrate doesn't exist, and so the chain selector is zero, and therefore should revert - s_usdcTokenPool.cancelExistingCCTPMigrationProposal(); + // We also want to check that the system uses CCTP Burn/Mint for all other messages that don't have that flag + test_MintOrRelease_incomingMessageWithPrimaryMechanism(); } } From f880d4ef02d44c8c909f88068ed68e8e0900d005 Mon Sep 17 00:00:00 2001 From: Ryan <80392855+RayXpub@users.noreply.github.com> Date: Thu, 12 Sep 2024 20:49:49 +0400 Subject: [PATCH 089/115] Make onRamp mutable in OffRamp (#1422) ## Motivation The goal of this PR is to reduce the misconfig risk on the `OffRamp` with the `onRamp` address. Currently, if we accidentally configure the wrong `onRamp` address on an existing `OffRamp`, the fix would involve a full redeployment + reconfig. ## Solution - Make the `onRamp` mutable in the `OffRamp`. - Add `onRamp` address verification in the `commit()` function - Only allow `onRamp` address modification when `minSeqNr == 1` --------- Co-authored-by: app-token-issuer-infra-releng[bot] <120227048+app-token-issuer-infra-releng[bot]@users.noreply.github.com> --- contracts/foundry.toml | 2 +- contracts/gas-snapshots/ccip.gas-snapshot | 1459 +++++++++-------- contracts/src/v0.8/ccip/offRamp/OffRamp.sol | 32 +- .../v0.8/ccip/test/e2e/MultiRampsEnd2End.sol | 2 +- .../src/v0.8/ccip/test/offRamp/OffRamp.t.sol | 93 +- .../ccip/generated/offramp/offramp.go | 4 +- ...rapper-dependency-versions-do-not-edit.txt | 2 +- 7 files changed, 821 insertions(+), 773 deletions(-) diff --git a/contracts/foundry.toml b/contracts/foundry.toml index c7c34e49d5..cb07c88de9 100644 --- a/contracts/foundry.toml +++ b/contracts/foundry.toml @@ -26,7 +26,7 @@ single_line_statement_blocks = "preserve" solc_version = '0.8.24' src = 'src/v0.8/ccip' test = 'src/v0.8/ccip/test' -optimizer_runs = 1_925 +optimizer_runs = 1_650 evm_version = 'paris' [profile.functions] diff --git a/contracts/gas-snapshots/ccip.gas-snapshot b/contracts/gas-snapshots/ccip.gas-snapshot index 6cb20b3a57..1590d6c3ae 100644 --- a/contracts/gas-snapshots/ccip.gas-snapshot +++ b/contracts/gas-snapshots/ccip.gas-snapshot @@ -2,259 +2,259 @@ ARMProxyStandaloneTest:test_ARMCallEmptyContractRevert() (gas: 19675) ARMProxyStandaloneTest:test_Constructor() (gas: 315049) ARMProxyStandaloneTest:test_SetARM() (gas: 16581) ARMProxyStandaloneTest:test_SetARMzero() (gas: 11267) -ARMProxyTest:test_ARMCallRevertReasonForwarded() (gas: 47868) -ARMProxyTest:test_ARMIsBlessed_Success() (gas: 36334) +ARMProxyTest:test_ARMCallRevertReasonForwarded() (gas: 47874) +ARMProxyTest:test_ARMIsBlessed_Success() (gas: 36353) ARMProxyTest:test_ARMIsCursed_Success() (gas: 49833) -AggregateTokenLimiter_constructor:test_Constructor_Success() (gas: 26992) -AggregateTokenLimiter_getTokenBucket:test_GetTokenBucket_Success() (gas: 19835) -AggregateTokenLimiter_getTokenBucket:test_Refill_Success() (gas: 41499) -AggregateTokenLimiter_getTokenBucket:test_TimeUnderflow_Revert() (gas: 15446) +AggregateTokenLimiter_constructor:test_Constructor_Success() (gas: 26998) +AggregateTokenLimiter_getTokenBucket:test_GetTokenBucket_Success() (gas: 19841) +AggregateTokenLimiter_getTokenBucket:test_Refill_Success() (gas: 41523) +AggregateTokenLimiter_getTokenBucket:test_TimeUnderflow_Revert() (gas: 15452) AggregateTokenLimiter_getTokenLimitAdmin:test_GetTokenLimitAdmin_Success() (gas: 10531) -AggregateTokenLimiter_getTokenValue:test_GetTokenValue_Success() (gas: 17465) -AggregateTokenLimiter_getTokenValue:test_NoTokenPrice_Reverts() (gas: 21360) -AggregateTokenLimiter_rateLimitValue:test_AggregateValueMaxCapacityExceeded_Revert() (gas: 16508) -AggregateTokenLimiter_rateLimitValue:test_RateLimitValueSuccess_gas() (gas: 18348) -AggregateTokenLimiter_setAdmin:test_OnlyOwnerOrAdmin_Revert() (gas: 13054) +AggregateTokenLimiter_getTokenValue:test_GetTokenValue_Success() (gas: 17471) +AggregateTokenLimiter_getTokenValue:test_NoTokenPrice_Reverts() (gas: 21366) +AggregateTokenLimiter_rateLimitValue:test_AggregateValueMaxCapacityExceeded_Revert() (gas: 16520) +AggregateTokenLimiter_rateLimitValue:test_RateLimitValueSuccess_gas() (gas: 18354) +AggregateTokenLimiter_setAdmin:test_OnlyOwnerOrAdmin_Revert() (gas: 13066) AggregateTokenLimiter_setAdmin:test_Owner_Success() (gas: 18998) -AggregateTokenLimiter_setRateLimiterConfig:test_OnlyOnlyCallableByAdminOrOwner_Revert() (gas: 17510) -AggregateTokenLimiter_setRateLimiterConfig:test_Owner_Success() (gas: 30230) -AggregateTokenLimiter_setRateLimiterConfig:test_TokenLimitAdmin_Success() (gas: 32244) -BurnFromMintTokenPool_lockOrBurn:test_ChainNotAllowed_Revert() (gas: 28779) -BurnFromMintTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 55124) -BurnFromMintTokenPool_lockOrBurn:test_PoolBurn_Success() (gas: 243680) +AggregateTokenLimiter_setRateLimiterConfig:test_OnlyOnlyCallableByAdminOrOwner_Revert() (gas: 17522) +AggregateTokenLimiter_setRateLimiterConfig:test_Owner_Success() (gas: 30249) +AggregateTokenLimiter_setRateLimiterConfig:test_TokenLimitAdmin_Success() (gas: 32263) +BurnFromMintTokenPool_lockOrBurn:test_ChainNotAllowed_Revert() (gas: 28791) +BurnFromMintTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 55142) +BurnFromMintTokenPool_lockOrBurn:test_PoolBurn_Success() (gas: 243690) BurnFromMintTokenPool_lockOrBurn:test_Setup_Success() (gas: 23947) -BurnMintTokenPool_lockOrBurn:test_ChainNotAllowed_Revert() (gas: 27546) -BurnMintTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 55130) -BurnMintTokenPool_lockOrBurn:test_PoolBurn_Success() (gas: 241573) +BurnMintTokenPool_lockOrBurn:test_ChainNotAllowed_Revert() (gas: 27558) +BurnMintTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 55142) +BurnMintTokenPool_lockOrBurn:test_PoolBurn_Success() (gas: 241578) BurnMintTokenPool_lockOrBurn:test_Setup_Success() (gas: 17677) -BurnMintTokenPool_releaseOrMint:test_ChainNotAllowed_Revert() (gas: 28775) -BurnMintTokenPool_releaseOrMint:test_PoolMintNotHealthy_Revert() (gas: 56211) -BurnMintTokenPool_releaseOrMint:test_PoolMint_Success() (gas: 112343) -BurnWithFromMintTokenPool_lockOrBurn:test_ChainNotAllowed_Revert() (gas: 28779) -BurnWithFromMintTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 55124) -BurnWithFromMintTokenPool_lockOrBurn:test_PoolBurn_Success() (gas: 243707) +BurnMintTokenPool_releaseOrMint:test_ChainNotAllowed_Revert() (gas: 28787) +BurnMintTokenPool_releaseOrMint:test_PoolMintNotHealthy_Revert() (gas: 56223) +BurnMintTokenPool_releaseOrMint:test_PoolMint_Success() (gas: 112349) +BurnWithFromMintTokenPool_lockOrBurn:test_ChainNotAllowed_Revert() (gas: 28791) +BurnWithFromMintTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 55142) +BurnWithFromMintTokenPool_lockOrBurn:test_PoolBurn_Success() (gas: 243716) BurnWithFromMintTokenPool_lockOrBurn:test_Setup_Success() (gas: 23951) -CCIPClientExample_sanity:test_ImmutableExamples_Success() (gas: 2091438) +CCIPClientExample_sanity:test_ImmutableExamples_Success() (gas: 2092239) CCIPConfigSetup:test_getCapabilityConfiguration_Success() (gas: 9539) -CCIPConfig_ConfigStateMachine:test__computeConfigDigest_Success() (gas: 66000) -CCIPConfig_ConfigStateMachine:test__computeNewConfigWithMeta_InitToRunning_Success() (gas: 358041) -CCIPConfig_ConfigStateMachine:test__computeNewConfigWithMeta_RunningToStaging_Success() (gas: 474705) -CCIPConfig_ConfigStateMachine:test__computeNewConfigWithMeta_StagingToRunning_Success() (gas: 441908) -CCIPConfig_ConfigStateMachine:test__groupByPluginType_TooManyOCR3Configs_Reverts() (gas: 33848) -CCIPConfig_ConfigStateMachine:test__groupByPluginType_threeCommitConfigs_Reverts() (gas: 56914) -CCIPConfig_ConfigStateMachine:test__groupByPluginType_threeExecutionConfigs_Reverts() (gas: 56852) +CCIPConfig_ConfigStateMachine:test__computeConfigDigest_Success() (gas: 66156) +CCIPConfig_ConfigStateMachine:test__computeNewConfigWithMeta_InitToRunning_Success() (gas: 358893) +CCIPConfig_ConfigStateMachine:test__computeNewConfigWithMeta_RunningToStaging_Success() (gas: 476337) +CCIPConfig_ConfigStateMachine:test__computeNewConfigWithMeta_StagingToRunning_Success() (gas: 443036) +CCIPConfig_ConfigStateMachine:test__groupByPluginType_TooManyOCR3Configs_Reverts() (gas: 34154) +CCIPConfig_ConfigStateMachine:test__groupByPluginType_threeCommitConfigs_Reverts() (gas: 57226) +CCIPConfig_ConfigStateMachine:test__groupByPluginType_threeExecutionConfigs_Reverts() (gas: 57164) CCIPConfig_ConfigStateMachine:test__stateFromConfigLength_Success() (gas: 11719) CCIPConfig_ConfigStateMachine:test__validateConfigStateTransition_Success() (gas: 8849) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_InitToRunning_Success() (gas: 309722) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_InitToRunning_WrongConfigCount_Reverts() (gas: 45865) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_NonExistentConfigTransition_Reverts() (gas: 29690) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_RunningToStaging_Success() (gas: 370009) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_RunningToStaging_WrongConfigCount_Reverts() (gas: 111376) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_RunningToStaging_WrongConfigDigestBlueGreen_Reverts() (gas: 145446) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_StagingToRunning_Success() (gas: 369785) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_StagingToRunning_WrongConfigDigest_Reverts() (gas: 145513) -CCIPConfig_ConfigStateMachine:test_getCapabilityConfiguration_Success() (gas: 9627) -CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_CommitAndExecConfig_Success() (gas: 1790808) -CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_CommitConfigOnly_Success() (gas: 1038239) -CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_ExecConfigOnly_Success() (gas: 1038270) +CCIPConfig_ConfigStateMachine:test__validateConfigTransition_InitToRunning_Success() (gas: 310010) +CCIPConfig_ConfigStateMachine:test__validateConfigTransition_InitToRunning_WrongConfigCount_Reverts() (gas: 46015) +CCIPConfig_ConfigStateMachine:test__validateConfigTransition_NonExistentConfigTransition_Reverts() (gas: 29840) +CCIPConfig_ConfigStateMachine:test__validateConfigTransition_RunningToStaging_Success() (gas: 370477) +CCIPConfig_ConfigStateMachine:test__validateConfigTransition_RunningToStaging_WrongConfigCount_Reverts() (gas: 111736) +CCIPConfig_ConfigStateMachine:test__validateConfigTransition_RunningToStaging_WrongConfigDigestBlueGreen_Reverts() (gas: 145866) +CCIPConfig_ConfigStateMachine:test__validateConfigTransition_StagingToRunning_Success() (gas: 370253) +CCIPConfig_ConfigStateMachine:test__validateConfigTransition_StagingToRunning_WrongConfigDigest_Reverts() (gas: 145933) +CCIPConfig_ConfigStateMachine:test_getCapabilityConfiguration_Success() (gas: 9663) +CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_CommitAndExecConfig_Success() (gas: 1790958) +CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_CommitConfigOnly_Success() (gas: 1038383) +CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_ExecConfigOnly_Success() (gas: 1038420) CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_OnlyCapabilitiesRegistryCanCall_Reverts() (gas: 9611) -CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_ZeroLengthConfig_Success() (gas: 15996) +CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_ZeroLengthConfig_Success() (gas: 16008) CCIPConfig_beforeCapabilityConfigSet:test_getCapabilityConfiguration_Success() (gas: 9627) -CCIPConfig_chainConfig:test__applyChainConfigUpdates_FChainNotPositive_Reverts() (gas: 184771) +CCIPConfig_chainConfig:test__applyChainConfigUpdates_FChainNotPositive_Reverts() (gas: 184777) CCIPConfig_chainConfig:test_applyChainConfigUpdates_addChainConfigs_Success() (gas: 346687) -CCIPConfig_chainConfig:test_applyChainConfigUpdates_nodeNotInRegistry_Reverts() (gas: 20340) +CCIPConfig_chainConfig:test_applyChainConfigUpdates_nodeNotInRegistry_Reverts() (gas: 20346) CCIPConfig_chainConfig:test_applyChainConfigUpdates_removeChainConfigs_Success() (gas: 270334) -CCIPConfig_chainConfig:test_applyChainConfigUpdates_selectorNotFound_Reverts() (gas: 14819) +CCIPConfig_chainConfig:test_applyChainConfigUpdates_selectorNotFound_Reverts() (gas: 14825) CCIPConfig_chainConfig:test_getCapabilityConfiguration_Success() (gas: 9648) -CCIPConfig_chainConfig:test_getPaginatedCCIPConfigs_Success() (gas: 370293) -CCIPConfig_constructor:test_constructor_Success() (gas: 3363163) -CCIPConfig_constructor:test_constructor_ZeroAddressNotAllowed_Revert() (gas: 61471) +CCIPConfig_chainConfig:test_getPaginatedCCIPConfigs_Success() (gas: 370299) +CCIPConfig_constructor:test_constructor_Success() (gas: 3333086) +CCIPConfig_constructor:test_constructor_ZeroAddressNotAllowed_Revert() (gas: 61438) CCIPConfig_updatePluginConfig:test__updatePluginConfig_InvalidConfigLength_Reverts() (gas: 25819) -CCIPConfig_updatePluginConfig:test__updatePluginConfig_InvalidConfigStateTransition_Reverts() (gas: 21913) +CCIPConfig_updatePluginConfig:test__updatePluginConfig_InvalidConfigStateTransition_Reverts() (gas: 21919) CCIPConfig_updatePluginConfig:test_getCapabilityConfiguration_Success() (gas: 9649) -CCIPConfig_updatePluginConfig:test_updatePluginConfig_InitToRunning_Success() (gas: 1087677) -CCIPConfig_updatePluginConfig:test_updatePluginConfig_RunningToStaging_Success() (gas: 2032286) -CCIPConfig_updatePluginConfig:test_updatePluginConfig_StagingToRunning_Success() (gas: 2032320) -CCIPConfig_validateConfig:test__validateConfig_ABIEncodedAddress_OfframpAddressCannotBeZero_Reverts() (gas: 290828) -CCIPConfig_validateConfig:test__validateConfig_ChainSelectorNotFound_Reverts() (gas: 293559) -CCIPConfig_validateConfig:test__validateConfig_ChainSelectorNotSet_Reverts() (gas: 290461) -CCIPConfig_validateConfig:test__validateConfig_FMustBePositive_Reverts() (gas: 291668) -CCIPConfig_validateConfig:test__validateConfig_FTooHigh_Reverts() (gas: 291766) -CCIPConfig_validateConfig:test__validateConfig_NodeNotInRegistry_Reverts() (gas: 344947) -CCIPConfig_validateConfig:test__validateConfig_NotEnoughTransmitters_Reverts() (gas: 1208593) -CCIPConfig_validateConfig:test__validateConfig_OfframpAddressCannotBeZero_Reverts() (gas: 290544) -CCIPConfig_validateConfig:test__validateConfig_P2PIdsLengthNotMatching_Reverts() (gas: 292459) -CCIPConfig_validateConfig:test__validateConfig_Success() (gas: 299632) -CCIPConfig_validateConfig:test__validateConfig_TooManySigners_Reverts() (gas: 493084) +CCIPConfig_updatePluginConfig:test_updatePluginConfig_InitToRunning_Success() (gas: 1087725) +CCIPConfig_updatePluginConfig:test_updatePluginConfig_RunningToStaging_Success() (gas: 2032324) +CCIPConfig_updatePluginConfig:test_updatePluginConfig_StagingToRunning_Success() (gas: 2032358) +CCIPConfig_validateConfig:test__validateConfig_ABIEncodedAddress_OfframpAddressCannotBeZero_Reverts() (gas: 290870) +CCIPConfig_validateConfig:test__validateConfig_ChainSelectorNotFound_Reverts() (gas: 293601) +CCIPConfig_validateConfig:test__validateConfig_ChainSelectorNotSet_Reverts() (gas: 290497) +CCIPConfig_validateConfig:test__validateConfig_FMustBePositive_Reverts() (gas: 291704) +CCIPConfig_validateConfig:test__validateConfig_FTooHigh_Reverts() (gas: 291802) +CCIPConfig_validateConfig:test__validateConfig_NodeNotInRegistry_Reverts() (gas: 345019) +CCIPConfig_validateConfig:test__validateConfig_NotEnoughTransmitters_Reverts() (gas: 1209247) +CCIPConfig_validateConfig:test__validateConfig_OfframpAddressCannotBeZero_Reverts() (gas: 290586) +CCIPConfig_validateConfig:test__validateConfig_P2PIdsLengthNotMatching_Reverts() (gas: 292495) +CCIPConfig_validateConfig:test__validateConfig_Success() (gas: 299668) +CCIPConfig_validateConfig:test__validateConfig_TooManySigners_Reverts() (gas: 493120) CCIPConfig_validateConfig:test_getCapabilityConfiguration_Success() (gas: 9606) -CommitStore_constructor:test_Constructor_Success() (gas: 3013980) -CommitStore_isUnpausedAndRMNHealthy:test_RMN_Success() (gas: 73477) -CommitStore_report:test_InvalidIntervalMinLargerThanMax_Revert() (gas: 28676) -CommitStore_report:test_InvalidInterval_Revert() (gas: 28616) -CommitStore_report:test_InvalidRootRevert() (gas: 27849) -CommitStore_report:test_OnlyGasPriceUpdates_Success() (gas: 53290) -CommitStore_report:test_OnlyPriceUpdateStaleReport_Revert() (gas: 59092) -CommitStore_report:test_OnlyTokenPriceUpdates_Success() (gas: 53288) -CommitStore_report:test_Paused_Revert() (gas: 21262) -CommitStore_report:test_ReportAndPriceUpdate_Success() (gas: 84276) -CommitStore_report:test_ReportOnlyRootSuccess_gas() (gas: 56258) -CommitStore_report:test_RootAlreadyCommitted_Revert() (gas: 63984) -CommitStore_report:test_StaleReportWithRoot_Success() (gas: 116976) -CommitStore_report:test_Unhealthy_Revert() (gas: 44754) -CommitStore_report:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 98573) -CommitStore_report:test_ZeroEpochAndRound_Revert() (gas: 27632) -CommitStore_resetUnblessedRoots:test_OnlyOwner_Revert() (gas: 11331) -CommitStore_resetUnblessedRoots:test_ResetUnblessedRoots_Success() (gas: 143814) +CommitStore_constructor:test_Constructor_Success() (gas: 2973887) +CommitStore_isUnpausedAndRMNHealthy:test_RMN_Success() (gas: 73567) +CommitStore_report:test_InvalidIntervalMinLargerThanMax_Revert() (gas: 28688) +CommitStore_report:test_InvalidInterval_Revert() (gas: 28628) +CommitStore_report:test_InvalidRootRevert() (gas: 27861) +CommitStore_report:test_OnlyGasPriceUpdates_Success() (gas: 53302) +CommitStore_report:test_OnlyPriceUpdateStaleReport_Revert() (gas: 59122) +CommitStore_report:test_OnlyTokenPriceUpdates_Success() (gas: 53300) +CommitStore_report:test_Paused_Revert() (gas: 21280) +CommitStore_report:test_ReportAndPriceUpdate_Success() (gas: 84288) +CommitStore_report:test_ReportOnlyRootSuccess_gas() (gas: 56270) +CommitStore_report:test_RootAlreadyCommitted_Revert() (gas: 64008) +CommitStore_report:test_StaleReportWithRoot_Success() (gas: 117012) +CommitStore_report:test_Unhealthy_Revert() (gas: 44766) +CommitStore_report:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 98603) +CommitStore_report:test_ZeroEpochAndRound_Revert() (gas: 27650) +CommitStore_resetUnblessedRoots:test_OnlyOwner_Revert() (gas: 11337) +CommitStore_resetUnblessedRoots:test_ResetUnblessedRoots_Success() (gas: 143871) CommitStore_setDynamicConfig:test_InvalidCommitStoreConfig_Revert() (gas: 37263) CommitStore_setDynamicConfig:test_OnlyOwner_Revert() (gas: 37405) CommitStore_setDynamicConfig:test_PriceEpochCleared_Success() (gas: 129131) -CommitStore_setLatestPriceEpochAndRound:test_OnlyOwner_Revert() (gas: 11054) -CommitStore_setLatestPriceEpochAndRound:test_SetLatestPriceEpochAndRound_Success() (gas: 20645) -CommitStore_setMinSeqNr:test_OnlyOwner_Revert() (gas: 11053) -CommitStore_verify:test_Blessed_Success() (gas: 96452) -CommitStore_verify:test_NotBlessed_Success() (gas: 61398) -CommitStore_verify:test_Paused_Revert() (gas: 18505) -CommitStore_verify:test_TooManyLeaves_Revert() (gas: 36797) -DefensiveExampleTest:test_HappyPath_Success() (gas: 200047) -DefensiveExampleTest:test_Recovery() (gas: 424294) -E2E:test_E2E_3MessagesSuccess_gas() (gas: 1095501) -EVM2EVMOffRamp__releaseOrMintToken:test__releaseOrMintToken_NotACompatiblePool_Revert() (gas: 37818) -EVM2EVMOffRamp__releaseOrMintToken:test__releaseOrMintToken_Success() (gas: 103820) -EVM2EVMOffRamp__releaseOrMintToken:test__releaseOrMintToken_TokenHandlingError_transfer_Revert() (gas: 85333) -EVM2EVMOffRamp__releaseOrMintToken:test_releaseOrMintToken_InvalidDataLength_Revert() (gas: 36843) -EVM2EVMOffRamp__releaseOrMintToken:test_releaseOrMintToken_ReleaseOrMintBalanceMismatch_Revert() (gas: 94389) -EVM2EVMOffRamp__releaseOrMintToken:test_releaseOrMintToken_TokenHandlingError_BalanceOf_Revert() (gas: 39813) -EVM2EVMOffRamp__releaseOrMintToken:test_releaseOrMintToken_skip_ReleaseOrMintBalanceMismatch_if_pool_Revert() (gas: 86631) -EVM2EVMOffRamp__releaseOrMintTokens:test_OverValueWithARLOff_Success() (gas: 379129) -EVM2EVMOffRamp__releaseOrMintTokens:test_PriceNotFoundForToken_Reverts() (gas: 139810) -EVM2EVMOffRamp__releaseOrMintTokens:test_RateLimitErrors_Reverts() (gas: 793106) -EVM2EVMOffRamp__releaseOrMintTokens:test_TokenHandlingError_Reverts() (gas: 177251) -EVM2EVMOffRamp__releaseOrMintTokens:test__releaseOrMintTokens_NotACompatiblePool_Reverts() (gas: 29243) -EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_InvalidDataLengthReturnData_Revert() (gas: 66504) -EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_InvalidEVMAddress_Revert() (gas: 43320) -EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_Success() (gas: 206862) -EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals_Success() (gas: 218114) -EVM2EVMOffRamp__report:test_Report_Success() (gas: 126703) -EVM2EVMOffRamp__trialExecute:test_RateLimitError_Success() (gas: 235795) -EVM2EVMOffRamp__trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 244395) -EVM2EVMOffRamp__trialExecute:test_TokenPoolIsNotAContract_Success() (gas: 325770) -EVM2EVMOffRamp__trialExecute:test_trialExecute_Success() (gas: 308201) +CommitStore_setLatestPriceEpochAndRound:test_OnlyOwner_Revert() (gas: 11060) +CommitStore_setLatestPriceEpochAndRound:test_SetLatestPriceEpochAndRound_Success() (gas: 20651) +CommitStore_setMinSeqNr:test_OnlyOwner_Revert() (gas: 11059) +CommitStore_verify:test_Blessed_Success() (gas: 96485) +CommitStore_verify:test_NotBlessed_Success() (gas: 61422) +CommitStore_verify:test_Paused_Revert() (gas: 18529) +CommitStore_verify:test_TooManyLeaves_Revert() (gas: 36809) +DefensiveExampleTest:test_HappyPath_Success() (gas: 200052) +DefensiveExampleTest:test_Recovery() (gas: 424299) +E2E:test_E2E_3MessagesSuccess_gas() (gas: 1097175) +EVM2EVMOffRamp__releaseOrMintToken:test__releaseOrMintToken_NotACompatiblePool_Revert() (gas: 37854) +EVM2EVMOffRamp__releaseOrMintToken:test__releaseOrMintToken_Success() (gas: 104060) +EVM2EVMOffRamp__releaseOrMintToken:test__releaseOrMintToken_TokenHandlingError_transfer_Revert() (gas: 85597) +EVM2EVMOffRamp__releaseOrMintToken:test_releaseOrMintToken_InvalidDataLength_Revert() (gas: 37068) +EVM2EVMOffRamp__releaseOrMintToken:test_releaseOrMintToken_ReleaseOrMintBalanceMismatch_Revert() (gas: 94629) +EVM2EVMOffRamp__releaseOrMintToken:test_releaseOrMintToken_TokenHandlingError_BalanceOf_Revert() (gas: 40050) +EVM2EVMOffRamp__releaseOrMintToken:test_releaseOrMintToken_skip_ReleaseOrMintBalanceMismatch_if_pool_Revert() (gas: 86871) +EVM2EVMOffRamp__releaseOrMintTokens:test_OverValueWithARLOff_Success() (gas: 379687) +EVM2EVMOffRamp__releaseOrMintTokens:test_PriceNotFoundForToken_Reverts() (gas: 140056) +EVM2EVMOffRamp__releaseOrMintTokens:test_RateLimitErrors_Reverts() (gas: 794492) +EVM2EVMOffRamp__releaseOrMintTokens:test_TokenHandlingError_Reverts() (gas: 177527) +EVM2EVMOffRamp__releaseOrMintTokens:test__releaseOrMintTokens_NotACompatiblePool_Reverts() (gas: 29249) +EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_InvalidDataLengthReturnData_Revert() (gas: 66741) +EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_InvalidEVMAddress_Revert() (gas: 43332) +EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_Success() (gas: 207138) +EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals_Success() (gas: 218390) +EVM2EVMOffRamp__report:test_Report_Success() (gas: 126727) +EVM2EVMOffRamp__trialExecute:test_RateLimitError_Success() (gas: 236077) +EVM2EVMOffRamp__trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 244677) +EVM2EVMOffRamp__trialExecute:test_TokenPoolIsNotAContract_Success() (gas: 326076) +EVM2EVMOffRamp__trialExecute:test_trialExecute_Success() (gas: 308501) EVM2EVMOffRamp_ccipReceive:test_Reverts() (gas: 17033) -EVM2EVMOffRamp_constructor:test_CommitStoreAlreadyInUse_Revert() (gas: 153548) -EVM2EVMOffRamp_constructor:test_Constructor_Success() (gas: 5549627) -EVM2EVMOffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 144282) -EVM2EVMOffRamp_execute:test_EmptyReport_Revert() (gas: 21321) -EVM2EVMOffRamp_execute:test_InvalidMessageId_Revert() (gas: 36558) -EVM2EVMOffRamp_execute:test_InvalidSourceChain_Revert() (gas: 51775) -EVM2EVMOffRamp_execute:test_InvalidSourcePoolAddress_Success() (gas: 469607) -EVM2EVMOffRamp_execute:test_ManualExecutionNotYetEnabled_Revert() (gas: 47830) +EVM2EVMOffRamp_constructor:test_CommitStoreAlreadyInUse_Revert() (gas: 153451) +EVM2EVMOffRamp_constructor:test_Constructor_Success() (gas: 5479225) +EVM2EVMOffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 144185) +EVM2EVMOffRamp_execute:test_EmptyReport_Revert() (gas: 21354) +EVM2EVMOffRamp_execute:test_InvalidMessageId_Revert() (gas: 36591) +EVM2EVMOffRamp_execute:test_InvalidSourceChain_Revert() (gas: 51808) +EVM2EVMOffRamp_execute:test_InvalidSourcePoolAddress_Success() (gas: 470171) +EVM2EVMOffRamp_execute:test_ManualExecutionNotYetEnabled_Revert() (gas: 47902) EVM2EVMOffRamp_execute:test_MessageTooLarge_Revert() (gas: 152518) -EVM2EVMOffRamp_execute:test_Paused_Revert() (gas: 103046) -EVM2EVMOffRamp_execute:test_ReceiverError_Success() (gas: 164107) -EVM2EVMOffRamp_execute:test_RetryFailedMessageWithoutManualExecution_Success() (gas: 178568) -EVM2EVMOffRamp_execute:test_RootNotCommitted_Revert() (gas: 42701) -EVM2EVMOffRamp_execute:test_SingleMessageNoTokensUnordered_Success() (gas: 157899) -EVM2EVMOffRamp_execute:test_SingleMessageNoTokens_Success() (gas: 173184) -EVM2EVMOffRamp_execute:test_SingleMessageToNonCCIPReceiver_Success() (gas: 247246) -EVM2EVMOffRamp_execute:test_SingleMessagesNoTokensSuccess_gas() (gas: 113971) -EVM2EVMOffRamp_execute:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 403729) +EVM2EVMOffRamp_execute:test_Paused_Revert() (gas: 103079) +EVM2EVMOffRamp_execute:test_ReceiverError_Success() (gas: 164230) +EVM2EVMOffRamp_execute:test_RetryFailedMessageWithoutManualExecution_Success() (gas: 178625) +EVM2EVMOffRamp_execute:test_RootNotCommitted_Revert() (gas: 42773) +EVM2EVMOffRamp_execute:test_SingleMessageNoTokensUnordered_Success() (gas: 158079) +EVM2EVMOffRamp_execute:test_SingleMessageNoTokens_Success() (gas: 173331) +EVM2EVMOffRamp_execute:test_SingleMessageToNonCCIPReceiver_Success() (gas: 237073) +EVM2EVMOffRamp_execute:test_SingleMessagesNoTokensSuccess_gas() (gas: 113995) +EVM2EVMOffRamp_execute:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 404062) EVM2EVMOffRamp_execute:test_SkippedIncorrectNonce_Success() (gas: 54294) -EVM2EVMOffRamp_execute:test_StrictUntouchedToSuccess_Success() (gas: 131317) +EVM2EVMOffRamp_execute:test_StrictUntouchedToSuccess_Success() (gas: 131440) EVM2EVMOffRamp_execute:test_TokenDataMismatch_Revert() (gas: 52249) -EVM2EVMOffRamp_execute:test_TwoMessagesWithTokensAndGE_Success() (gas: 559653) -EVM2EVMOffRamp_execute:test_TwoMessagesWithTokensSuccess_gas() (gas: 490168) -EVM2EVMOffRamp_execute:test_UnexpectedTokenData_Revert() (gas: 35497) -EVM2EVMOffRamp_execute:test_Unhealthy_Revert() (gas: 540918) +EVM2EVMOffRamp_execute:test_TwoMessagesWithTokensAndGE_Success() (gas: 560385) +EVM2EVMOffRamp_execute:test_TwoMessagesWithTokensSuccess_gas() (gas: 490768) +EVM2EVMOffRamp_execute:test_UnexpectedTokenData_Revert() (gas: 35530) +EVM2EVMOffRamp_execute:test_Unhealthy_Revert() (gas: 541563) EVM2EVMOffRamp_execute:test_UnsupportedNumberOfTokens_Revert() (gas: 64497) -EVM2EVMOffRamp_execute:test__execute_SkippedAlreadyExecutedMessageUnordered_Success() (gas: 122676) -EVM2EVMOffRamp_execute:test__execute_SkippedAlreadyExecutedMessage_Success() (gas: 142850) -EVM2EVMOffRamp_execute:test_execute_RouterYULCall_Success() (gas: 427538) +EVM2EVMOffRamp_execute:test__execute_SkippedAlreadyExecutedMessageUnordered_Success() (gas: 122733) +EVM2EVMOffRamp_execute:test__execute_SkippedAlreadyExecutedMessage_Success() (gas: 142907) +EVM2EVMOffRamp_execute:test_execute_RouterYULCall_Success() (gas: 427595) EVM2EVMOffRamp_executeSingleMessage:test_MessageSender_Revert() (gas: 18502) -EVM2EVMOffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 273988) +EVM2EVMOffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 274264) EVM2EVMOffRamp_executeSingleMessage:test_NonContract_Success() (gas: 18668) -EVM2EVMOffRamp_executeSingleMessage:test_TokenHandlingError_Revert() (gas: 221922) -EVM2EVMOffRamp_executeSingleMessage:test_ZeroGasDONExecution_Revert() (gas: 47926) -EVM2EVMOffRamp_executeSingleMessage:test_executeSingleMessage_NoTokens_Success() (gas: 47403) -EVM2EVMOffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens_Success() (gas: 309850) -EVM2EVMOffRamp_executeSingleMessage:test_executeSingleMessage_ZeroGasZeroData_Success() (gas: 70065) -EVM2EVMOffRamp_execute_upgrade:test_V2NonceNewSenderStartsAtZero_Success() (gas: 229454) -EVM2EVMOffRamp_execute_upgrade:test_V2NonceStartsAtV1Nonce_Success() (gas: 276982) -EVM2EVMOffRamp_execute_upgrade:test_V2OffRampNonceSkipsIfMsgInFlight_Success() (gas: 258834) -EVM2EVMOffRamp_execute_upgrade:test_V2SenderNoncesReadsPreviousRamp_Success() (gas: 226442) -EVM2EVMOffRamp_execute_upgrade:test_V2_Success() (gas: 130811) +EVM2EVMOffRamp_executeSingleMessage:test_TokenHandlingError_Revert() (gas: 222198) +EVM2EVMOffRamp_executeSingleMessage:test_ZeroGasDONExecution_Revert() (gas: 47950) +EVM2EVMOffRamp_executeSingleMessage:test_executeSingleMessage_NoTokens_Success() (gas: 47427) +EVM2EVMOffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens_Success() (gas: 310150) +EVM2EVMOffRamp_executeSingleMessage:test_executeSingleMessage_ZeroGasZeroData_Success() (gas: 70101) +EVM2EVMOffRamp_execute_upgrade:test_V2NonceNewSenderStartsAtZero_Success() (gas: 229526) +EVM2EVMOffRamp_execute_upgrade:test_V2NonceStartsAtV1Nonce_Success() (gas: 277072) +EVM2EVMOffRamp_execute_upgrade:test_V2OffRampNonceSkipsIfMsgInFlight_Success() (gas: 258912) +EVM2EVMOffRamp_execute_upgrade:test_V2SenderNoncesReadsPreviousRamp_Success() (gas: 226538) +EVM2EVMOffRamp_execute_upgrade:test_V2_Success() (gas: 130841) EVM2EVMOffRamp_getAllRateLimitTokens:test_GetAllRateLimitTokens_Success() (gas: 38446) EVM2EVMOffRamp_getExecutionState:test_FillExecutionState_Success() (gas: 3251974) EVM2EVMOffRamp_getExecutionState:test_GetExecutionState_Success() (gas: 83387) -EVM2EVMOffRamp_manuallyExecute:test_ManualExecFailedTx_Revert() (gas: 185967) +EVM2EVMOffRamp_manuallyExecute:test_ManualExecFailedTx_Revert() (gas: 186015) EVM2EVMOffRamp_manuallyExecute:test_ManualExecForkedChain_Revert() (gas: 27052) EVM2EVMOffRamp_manuallyExecute:test_ManualExecGasLimitMismatch_Revert() (gas: 45200) EVM2EVMOffRamp_manuallyExecute:test_ManualExecInvalidGasLimit_Revert() (gas: 27471) -EVM2EVMOffRamp_manuallyExecute:test_ManualExecWithMultipleMessagesAndSourceTokens_Success() (gas: 526041) -EVM2EVMOffRamp_manuallyExecute:test_ManualExecWithSourceTokens_Success() (gas: 341709) -EVM2EVMOffRamp_manuallyExecute:test_ManualExec_Success() (gas: 187459) -EVM2EVMOffRamp_manuallyExecute:test_ReentrancyManualExecuteFails_Success() (gas: 2256179) -EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_DestinationGasAmountCountMismatch_Revert() (gas: 358922) -EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_DoesNotRevertIfUntouched_Success() (gas: 143972) -EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_InvalidTokenGasOverride_Revert() (gas: 362061) -EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_LowGasLimitManualExec_Success() (gas: 482796) -EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_WithGasOverride_Success() (gas: 189862) -EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_WithInvalidReceiverExecutionGasOverride_Revert() (gas: 153716) +EVM2EVMOffRamp_manuallyExecute:test_ManualExecWithMultipleMessagesAndSourceTokens_Success() (gas: 526641) +EVM2EVMOffRamp_manuallyExecute:test_ManualExecWithSourceTokens_Success() (gas: 342009) +EVM2EVMOffRamp_manuallyExecute:test_ManualExec_Success() (gas: 187507) +EVM2EVMOffRamp_manuallyExecute:test_ReentrancyManualExecuteFails_Success() (gas: 2256449) +EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_DestinationGasAmountCountMismatch_Revert() (gas: 359222) +EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_DoesNotRevertIfUntouched_Success() (gas: 143996) +EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_InvalidTokenGasOverride_Revert() (gas: 362361) +EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_LowGasLimitManualExec_Success() (gas: 482844) +EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_WithGasOverride_Success() (gas: 189910) +EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_WithInvalidReceiverExecutionGasOverride_Revert() (gas: 153740) EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_WithInvalidSourceTokenDataCount_Revert() (gas: 59897) EVM2EVMOffRamp_metadataHash:test_MetadataHash_Success() (gas: 8865) -EVM2EVMOffRamp_setDynamicConfig:test_NonOwner_Revert() (gas: 40162) +EVM2EVMOffRamp_setDynamicConfig:test_NonOwner_Revert() (gas: 40168) EVM2EVMOffRamp_setDynamicConfig:test_RouterZeroAddress_Revert() (gas: 38239) EVM2EVMOffRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 141938) -EVM2EVMOffRamp_updateRateLimitTokens:test_updateRateLimitTokens_AddsAndRemoves_Success() (gas: 162528) -EVM2EVMOffRamp_updateRateLimitTokens:test_updateRateLimitTokens_NonOwner_Revert() (gas: 16699) +EVM2EVMOffRamp_updateRateLimitTokens:test_updateRateLimitTokens_AddsAndRemoves_Success() (gas: 162532) +EVM2EVMOffRamp_updateRateLimitTokens:test_updateRateLimitTokens_NonOwner_Revert() (gas: 16711) EVM2EVMOffRamp_updateRateLimitTokens:test_updateRateLimitTokens_Success() (gas: 197728) -EVM2EVMOnRamp_constructor:test_Constructor_Success() (gas: 5431520) -EVM2EVMOnRamp_forwardFromRouter:test_CannotSendZeroTokens_Revert() (gas: 35835) -EVM2EVMOnRamp_forwardFromRouter:test_EnforceOutOfOrder_Revert() (gas: 98584) -EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() (gas: 114231) -EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2_Success() (gas: 114273) -EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterSuccessCustomExtraArgs() (gas: 130246) -EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterSuccessLegacyExtraArgs() (gas: 138686) -EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouter_Success() (gas: 129865) -EVM2EVMOnRamp_forwardFromRouter:test_InvalidAddressEncodePacked_Revert() (gas: 38314) -EVM2EVMOnRamp_forwardFromRouter:test_InvalidAddress_Revert() (gas: 38497) -EVM2EVMOnRamp_forwardFromRouter:test_InvalidChainSelector_Revert() (gas: 25534) -EVM2EVMOnRamp_forwardFromRouter:test_InvalidExtraArgsTag_Revert() (gas: 25320) -EVM2EVMOnRamp_forwardFromRouter:test_MaxCapacityExceeded_Revert() (gas: 83951) -EVM2EVMOnRamp_forwardFromRouter:test_MaxFeeBalanceReached_Revert() (gas: 36514) -EVM2EVMOnRamp_forwardFromRouter:test_MessageGasLimitTooHigh_Revert() (gas: 29078) -EVM2EVMOnRamp_forwardFromRouter:test_MessageTooLarge_Revert() (gas: 107622) +EVM2EVMOnRamp_constructor:test_Constructor_Success() (gas: 5322415) +EVM2EVMOnRamp_forwardFromRouter:test_CannotSendZeroTokens_Revert() (gas: 35880) +EVM2EVMOnRamp_forwardFromRouter:test_EnforceOutOfOrder_Revert() (gas: 98614) +EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() (gas: 114321) +EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2_Success() (gas: 114363) +EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterSuccessCustomExtraArgs() (gas: 130351) +EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterSuccessLegacyExtraArgs() (gas: 138791) +EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouter_Success() (gas: 129970) +EVM2EVMOnRamp_forwardFromRouter:test_InvalidAddressEncodePacked_Revert() (gas: 38431) +EVM2EVMOnRamp_forwardFromRouter:test_InvalidAddress_Revert() (gas: 38614) +EVM2EVMOnRamp_forwardFromRouter:test_InvalidChainSelector_Revert() (gas: 25540) +EVM2EVMOnRamp_forwardFromRouter:test_InvalidExtraArgsTag_Revert() (gas: 25365) +EVM2EVMOnRamp_forwardFromRouter:test_MaxCapacityExceeded_Revert() (gas: 84002) +EVM2EVMOnRamp_forwardFromRouter:test_MaxFeeBalanceReached_Revert() (gas: 36619) +EVM2EVMOnRamp_forwardFromRouter:test_MessageGasLimitTooHigh_Revert() (gas: 29123) +EVM2EVMOnRamp_forwardFromRouter:test_MessageTooLarge_Revert() (gas: 107667) EVM2EVMOnRamp_forwardFromRouter:test_OriginalSender_Revert() (gas: 22724) -EVM2EVMOnRamp_forwardFromRouter:test_OverValueWithARLOff_Success() (gas: 225252) -EVM2EVMOnRamp_forwardFromRouter:test_Paused_Revert() (gas: 53150) -EVM2EVMOnRamp_forwardFromRouter:test_Permissions_Revert() (gas: 25559) -EVM2EVMOnRamp_forwardFromRouter:test_PriceNotFoundForToken_Revert() (gas: 57291) -EVM2EVMOnRamp_forwardFromRouter:test_ShouldIncrementNonceOnlyOnOrdered_Success() (gas: 179442) -EVM2EVMOnRamp_forwardFromRouter:test_ShouldIncrementSeqNumAndNonce_Success() (gas: 177724) -EVM2EVMOnRamp_forwardFromRouter:test_ShouldStoreNonLinkFees() (gas: 132585) -EVM2EVMOnRamp_forwardFromRouter:test_SourceTokenDataTooLarge_Revert() (gas: 3772676) -EVM2EVMOnRamp_forwardFromRouter:test_TooManyTokens_Revert() (gas: 30244) +EVM2EVMOnRamp_forwardFromRouter:test_OverValueWithARLOff_Success() (gas: 225474) +EVM2EVMOnRamp_forwardFromRouter:test_Paused_Revert() (gas: 53180) +EVM2EVMOnRamp_forwardFromRouter:test_Permissions_Revert() (gas: 25565) +EVM2EVMOnRamp_forwardFromRouter:test_PriceNotFoundForToken_Revert() (gas: 57336) +EVM2EVMOnRamp_forwardFromRouter:test_ShouldIncrementNonceOnlyOnOrdered_Success() (gas: 179712) +EVM2EVMOnRamp_forwardFromRouter:test_ShouldIncrementSeqNumAndNonce_Success() (gas: 178039) +EVM2EVMOnRamp_forwardFromRouter:test_ShouldStoreNonLinkFees() (gas: 132717) +EVM2EVMOnRamp_forwardFromRouter:test_SourceTokenDataTooLarge_Revert() (gas: 3713189) +EVM2EVMOnRamp_forwardFromRouter:test_TooManyTokens_Revert() (gas: 30289) EVM2EVMOnRamp_forwardFromRouter:test_Unhealthy_Revert() (gas: 43342) -EVM2EVMOnRamp_forwardFromRouter:test_UnsupportedToken_Revert() (gas: 109440) -EVM2EVMOnRamp_forwardFromRouter:test_ZeroAddressReceiver_Revert() (gas: 313095) -EVM2EVMOnRamp_forwardFromRouter:test_forwardFromRouter_ShouldStoreLinkFees_Success() (gas: 112430) -EVM2EVMOnRamp_forwardFromRouter:test_forwardFromRouter_UnsupportedToken_Revert() (gas: 72269) -EVM2EVMOnRamp_forwardFromRouter:test_forwardFromRouter_correctSourceTokenData_Success() (gas: 711472) -EVM2EVMOnRamp_forwardFromRouter_upgrade:test_V2NonceNewSenderStartsAtZero_Success() (gas: 147709) -EVM2EVMOnRamp_forwardFromRouter_upgrade:test_V2NonceStartsAtV1Nonce_Success() (gas: 190616) -EVM2EVMOnRamp_forwardFromRouter_upgrade:test_V2SenderNoncesReadsPreviousRamp_Success() (gas: 121404) -EVM2EVMOnRamp_forwardFromRouter_upgrade:test_V2_Success() (gas: 95376) +EVM2EVMOnRamp_forwardFromRouter:test_UnsupportedToken_Revert() (gas: 109557) +EVM2EVMOnRamp_forwardFromRouter:test_ZeroAddressReceiver_Revert() (gas: 314265) +EVM2EVMOnRamp_forwardFromRouter:test_forwardFromRouter_ShouldStoreLinkFees_Success() (gas: 112547) +EVM2EVMOnRamp_forwardFromRouter:test_forwardFromRouter_UnsupportedToken_Revert() (gas: 72386) +EVM2EVMOnRamp_forwardFromRouter:test_forwardFromRouter_correctSourceTokenData_Success() (gas: 711856) +EVM2EVMOnRamp_forwardFromRouter_upgrade:test_V2NonceNewSenderStartsAtZero_Success() (gas: 147925) +EVM2EVMOnRamp_forwardFromRouter_upgrade:test_V2NonceStartsAtV1Nonce_Success() (gas: 190949) +EVM2EVMOnRamp_forwardFromRouter_upgrade:test_V2SenderNoncesReadsPreviousRamp_Success() (gas: 121743) +EVM2EVMOnRamp_forwardFromRouter_upgrade:test_V2_Success() (gas: 95487) EVM2EVMOnRamp_getDataAvailabilityCost:test_EmptyMessageCalculatesDataAvailabilityCost_Success() (gas: 20568) EVM2EVMOnRamp_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCost_Success() (gas: 20936) -EVM2EVMOnRamp_getFee:test_EmptyMessage_Success() (gas: 74027) -EVM2EVMOnRamp_getFee:test_GetFeeOfZeroForTokenMessage_Success() (gas: 79523) -EVM2EVMOnRamp_getFee:test_HighGasMessage_Success() (gas: 229875) -EVM2EVMOnRamp_getFee:test_MessageGasLimitTooHigh_Revert() (gas: 16733) -EVM2EVMOnRamp_getFee:test_MessageTooLarge_Revert() (gas: 95283) -EVM2EVMOnRamp_getFee:test_MessageWithDataAndTokenTransfer_Success() (gas: 152627) -EVM2EVMOnRamp_getFee:test_NotAFeeToken_Revert() (gas: 24113) -EVM2EVMOnRamp_getFee:test_SingleTokenMessage_Success() (gas: 113597) -EVM2EVMOnRamp_getFee:test_TooManyTokens_Revert() (gas: 19914) -EVM2EVMOnRamp_getFee:test_ZeroDataAvailabilityMultiplier_Success() (gas: 62539) +EVM2EVMOnRamp_getFee:test_EmptyMessage_Success() (gas: 74147) +EVM2EVMOnRamp_getFee:test_GetFeeOfZeroForTokenMessage_Success() (gas: 79673) +EVM2EVMOnRamp_getFee:test_HighGasMessage_Success() (gas: 229995) +EVM2EVMOnRamp_getFee:test_MessageGasLimitTooHigh_Revert() (gas: 16778) +EVM2EVMOnRamp_getFee:test_MessageTooLarge_Revert() (gas: 95328) +EVM2EVMOnRamp_getFee:test_MessageWithDataAndTokenTransfer_Success() (gas: 152747) +EVM2EVMOnRamp_getFee:test_NotAFeeToken_Revert() (gas: 24158) +EVM2EVMOnRamp_getFee:test_SingleTokenMessage_Success() (gas: 113717) +EVM2EVMOnRamp_getFee:test_TooManyTokens_Revert() (gas: 19959) +EVM2EVMOnRamp_getFee:test_ZeroDataAvailabilityMultiplier_Success() (gas: 62629) EVM2EVMOnRamp_getSupportedTokens:test_GetSupportedTokens_Revert() (gas: 10460) EVM2EVMOnRamp_getTokenPool:test_GetTokenPool_Success() (gas: 35195) EVM2EVMOnRamp_getTokenTransferCost:test_CustomTokenBpsFee_Success() (gas: 43011) @@ -263,135 +263,135 @@ EVM2EVMOnRamp_getTokenTransferCost:test_LargeTokenTransferChargesMaxFeeAndGas_Su EVM2EVMOnRamp_getTokenTransferCost:test_MixedTokenTransferFee_Success() (gas: 121817) EVM2EVMOnRamp_getTokenTransferCost:test_NoTokenTransferChargesZeroFee_Success() (gas: 15250) EVM2EVMOnRamp_getTokenTransferCost:test_SmallTokenTransferChargesMinFeeAndGas_Success() (gas: 28164) -EVM2EVMOnRamp_getTokenTransferCost:test_UnsupportedToken_Revert() (gas: 21260) +EVM2EVMOnRamp_getTokenTransferCost:test_UnsupportedToken_Revert() (gas: 21266) EVM2EVMOnRamp_getTokenTransferCost:test_ZeroAmountTokenTransferChargesMinFeeAndGas_Success() (gas: 28187) EVM2EVMOnRamp_getTokenTransferCost:test_ZeroFeeConfigChargesMinFee_Success() (gas: 38638) EVM2EVMOnRamp_getTokenTransferCost:test__getTokenTransferCost_selfServeUsesDefaults_Success() (gas: 29440) -EVM2EVMOnRamp_linkAvailableForPayment:test_InsufficientLinkBalance_Success() (gas: 32621) -EVM2EVMOnRamp_linkAvailableForPayment:test_LinkAvailableForPayment_Success() (gas: 134884) -EVM2EVMOnRamp_payNops:test_AdminPayNops_Success() (gas: 143210) -EVM2EVMOnRamp_payNops:test_InsufficientBalance_Revert() (gas: 29055) -EVM2EVMOnRamp_payNops:test_NoFeesToPay_Revert() (gas: 127424) -EVM2EVMOnRamp_payNops:test_NoNopsToPay_Revert() (gas: 133318) -EVM2EVMOnRamp_payNops:test_NopPayNops_Success() (gas: 146497) -EVM2EVMOnRamp_payNops:test_OwnerPayNops_Success() (gas: 141072) -EVM2EVMOnRamp_payNops:test_PayNopsSuccessAfterSetNops() (gas: 297651) +EVM2EVMOnRamp_linkAvailableForPayment:test_InsufficientLinkBalance_Success() (gas: 32651) +EVM2EVMOnRamp_linkAvailableForPayment:test_LinkAvailableForPayment_Success() (gas: 135118) +EVM2EVMOnRamp_payNops:test_AdminPayNops_Success() (gas: 143408) +EVM2EVMOnRamp_payNops:test_InsufficientBalance_Revert() (gas: 29085) +EVM2EVMOnRamp_payNops:test_NoFeesToPay_Revert() (gas: 127622) +EVM2EVMOnRamp_payNops:test_NoNopsToPay_Revert() (gas: 133481) +EVM2EVMOnRamp_payNops:test_NopPayNops_Success() (gas: 146695) +EVM2EVMOnRamp_payNops:test_OwnerPayNops_Success() (gas: 141270) +EVM2EVMOnRamp_payNops:test_PayNopsSuccessAfterSetNops() (gas: 298116) EVM2EVMOnRamp_payNops:test_WrongPermissions_Revert() (gas: 15300) -EVM2EVMOnRamp_setDynamicConfig:test_SetConfigInvalidConfig_Revert() (gas: 42377) -EVM2EVMOnRamp_setDynamicConfig:test_SetConfigOnlyOwner_Revert() (gas: 21258) -EVM2EVMOnRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 53782) -EVM2EVMOnRamp_setFeeTokenConfig:test_OnlyCallableByOwnerOrAdmin_Revert() (gas: 13470) -EVM2EVMOnRamp_setFeeTokenConfig:test_SetFeeTokenConfigByAdmin_Success() (gas: 16455) -EVM2EVMOnRamp_setFeeTokenConfig:test_SetFeeTokenConfig_Success() (gas: 13994) -EVM2EVMOnRamp_setNops:test_AdminCanSetNops_Success() (gas: 61785) -EVM2EVMOnRamp_setNops:test_IncludesPayment_Success() (gas: 469353) -EVM2EVMOnRamp_setNops:test_LinkTokenCannotBeNop_Revert() (gas: 57276) +EVM2EVMOnRamp_setDynamicConfig:test_SetConfigInvalidConfig_Revert() (gas: 42401) +EVM2EVMOnRamp_setDynamicConfig:test_SetConfigOnlyOwner_Revert() (gas: 21270) +EVM2EVMOnRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 53830) +EVM2EVMOnRamp_setFeeTokenConfig:test_OnlyCallableByOwnerOrAdmin_Revert() (gas: 13476) +EVM2EVMOnRamp_setFeeTokenConfig:test_SetFeeTokenConfigByAdmin_Success() (gas: 16461) +EVM2EVMOnRamp_setFeeTokenConfig:test_SetFeeTokenConfig_Success() (gas: 14000) +EVM2EVMOnRamp_setNops:test_AdminCanSetNops_Success() (gas: 61795) +EVM2EVMOnRamp_setNops:test_IncludesPayment_Success() (gas: 469668) +EVM2EVMOnRamp_setNops:test_LinkTokenCannotBeNop_Revert() (gas: 57291) EVM2EVMOnRamp_setNops:test_NonOwnerOrAdmin_Revert() (gas: 14677) -EVM2EVMOnRamp_setNops:test_NotEnoughFundsForPayout_Revert() (gas: 84528) -EVM2EVMOnRamp_setNops:test_SetNopsRemovesOldNopsCompletely_Success() (gas: 60673) -EVM2EVMOnRamp_setNops:test_SetNops_Success() (gas: 173821) +EVM2EVMOnRamp_setNops:test_NotEnoughFundsForPayout_Revert() (gas: 84675) +EVM2EVMOnRamp_setNops:test_SetNopsRemovesOldNopsCompletely_Success() (gas: 60683) +EVM2EVMOnRamp_setNops:test_SetNops_Success() (gas: 173833) EVM2EVMOnRamp_setNops:test_TooManyNops_Revert() (gas: 190350) -EVM2EVMOnRamp_setNops:test_ZeroAddressCannotBeNop_Revert() (gas: 53617) +EVM2EVMOnRamp_setNops:test_ZeroAddressCannotBeNop_Revert() (gas: 53632) EVM2EVMOnRamp_setTokenTransferFeeConfig:test__setTokenTransferFeeConfig_InvalidDestBytesOverhead_Revert() (gas: 14499) EVM2EVMOnRamp_setTokenTransferFeeConfig:test__setTokenTransferFeeConfig_OnlyCallableByOwnerOrAdmin_Revert() (gas: 14283) EVM2EVMOnRamp_setTokenTransferFeeConfig:test__setTokenTransferFeeConfig_Success() (gas: 84107) EVM2EVMOnRamp_setTokenTransferFeeConfig:test__setTokenTransferFeeConfig_byAdmin_Success() (gas: 17375) -EVM2EVMOnRamp_withdrawNonLinkFees:test_LinkBalanceNotSettled_Revert() (gas: 83035) +EVM2EVMOnRamp_withdrawNonLinkFees:test_LinkBalanceNotSettled_Revert() (gas: 83158) EVM2EVMOnRamp_withdrawNonLinkFees:test_NonOwnerOrAdmin_Revert() (gas: 15275) -EVM2EVMOnRamp_withdrawNonLinkFees:test_SettlingBalance_Success() (gas: 272083) -EVM2EVMOnRamp_withdrawNonLinkFees:test_WithdrawNonLinkFees_Success() (gas: 53458) +EVM2EVMOnRamp_withdrawNonLinkFees:test_SettlingBalance_Success() (gas: 272200) +EVM2EVMOnRamp_withdrawNonLinkFees:test_WithdrawNonLinkFees_Success() (gas: 53482) EVM2EVMOnRamp_withdrawNonLinkFees:test_WithdrawToZeroAddress_Revert() (gas: 12830) EtherSenderReceiverTest_ccipReceive:test_ccipReceive_fallbackToWethTransfer() (gas: 96892) EtherSenderReceiverTest_ccipReceive:test_ccipReceive_happyPath() (gas: 49770) EtherSenderReceiverTest_ccipReceive:test_ccipReceive_wrongToken() (gas: 17423) -EtherSenderReceiverTest_ccipReceive:test_ccipReceive_wrongTokenAmount() (gas: 15716) -EtherSenderReceiverTest_ccipSend:test_ccipSend_reverts_insufficientFee_feeToken() (gas: 99831) -EtherSenderReceiverTest_ccipSend:test_ccipSend_reverts_insufficientFee_native() (gas: 76099) -EtherSenderReceiverTest_ccipSend:test_ccipSend_reverts_insufficientFee_weth() (gas: 99853) -EtherSenderReceiverTest_ccipSend:test_ccipSend_success_feeToken() (gas: 144833) -EtherSenderReceiverTest_ccipSend:test_ccipSend_success_native() (gas: 80262) -EtherSenderReceiverTest_ccipSend:test_ccipSend_success_nativeExcess() (gas: 80449) -EtherSenderReceiverTest_ccipSend:test_ccipSend_success_weth() (gas: 95902) +EtherSenderReceiverTest_ccipReceive:test_ccipReceive_wrongTokenAmount() (gas: 15722) +EtherSenderReceiverTest_ccipSend:test_ccipSend_reverts_insufficientFee_feeToken() (gas: 99837) +EtherSenderReceiverTest_ccipSend:test_ccipSend_reverts_insufficientFee_native() (gas: 76105) +EtherSenderReceiverTest_ccipSend:test_ccipSend_reverts_insufficientFee_weth() (gas: 99859) +EtherSenderReceiverTest_ccipSend:test_ccipSend_success_feeToken() (gas: 144845) +EtherSenderReceiverTest_ccipSend:test_ccipSend_success_native() (gas: 80268) +EtherSenderReceiverTest_ccipSend:test_ccipSend_success_nativeExcess() (gas: 80455) +EtherSenderReceiverTest_ccipSend:test_ccipSend_success_weth() (gas: 95914) EtherSenderReceiverTest_constructor:test_constructor() (gas: 17535) -EtherSenderReceiverTest_getFee:test_getFee() (gas: 27316) +EtherSenderReceiverTest_getFee:test_getFee() (gas: 27328) EtherSenderReceiverTest_validateFeeToken:test_validateFeeToken_reverts_feeToken_tokenAmountNotEqualToMsgValue() (gas: 20363) EtherSenderReceiverTest_validateFeeToken:test_validateFeeToken_valid_feeToken() (gas: 16718) EtherSenderReceiverTest_validateFeeToken:test_validateFeeToken_valid_native() (gas: 16657) EtherSenderReceiverTest_validatedMessage:test_validatedMessage_dataOverwrittenToMsgSender() (gas: 25415) EtherSenderReceiverTest_validatedMessage:test_validatedMessage_emptyDataOverwrittenToMsgSender() (gas: 25265) -EtherSenderReceiverTest_validatedMessage:test_validatedMessage_invalidTokenAmounts() (gas: 17907) +EtherSenderReceiverTest_validatedMessage:test_validatedMessage_invalidTokenAmounts() (gas: 17913) EtherSenderReceiverTest_validatedMessage:test_validatedMessage_tokenOverwrittenToWeth() (gas: 25287) -EtherSenderReceiverTest_validatedMessage:test_validatedMessage_validMessage_extraArgs() (gas: 26316) -FeeQuoter_applyDestChainConfigUpdates:test_InvalidChainFamilySelector_Revert() (gas: 16509) -FeeQuoter_applyDestChainConfigUpdates:test_InvalidDestChainConfigDestChainSelectorEqZero_Revert() (gas: 16423) -FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesDefaultTxGasLimitEqZero_Revert() (gas: 16465) -FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesDefaultTxGasLimitGtMaxPerMessageGasLimit_Revert() (gas: 39969) +EtherSenderReceiverTest_validatedMessage:test_validatedMessage_validMessage_extraArgs() (gas: 26328) +FeeQuoter_applyDestChainConfigUpdates:test_InvalidChainFamilySelector_Revert() (gas: 16515) +FeeQuoter_applyDestChainConfigUpdates:test_InvalidDestChainConfigDestChainSelectorEqZero_Revert() (gas: 16429) +FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesDefaultTxGasLimitEqZero_Revert() (gas: 16471) +FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesDefaultTxGasLimitGtMaxPerMessageGasLimit_Revert() (gas: 39975) FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesZeroIntput_Success() (gas: 12342) -FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdates_Success() (gas: 135942) -FeeQuoter_applyFeeTokensUpdates:test_ApplyFeeTokensUpdates_Success() (gas: 80117) -FeeQuoter_applyFeeTokensUpdates:test_OnlyCallableByOwner_Revert() (gas: 12615) -FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_OnlyCallableByOwnerOrAdmin_Revert() (gas: 11456) -FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesMultipleTokens_Success() (gas: 54236) -FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesSingleToken_Success() (gas: 44880) +FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdates_Success() (gas: 135960) +FeeQuoter_applyFeeTokensUpdates:test_ApplyFeeTokensUpdates_Success() (gas: 80127) +FeeQuoter_applyFeeTokensUpdates:test_OnlyCallableByOwner_Revert() (gas: 12621) +FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_OnlyCallableByOwnerOrAdmin_Revert() (gas: 11462) +FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesMultipleTokens_Success() (gas: 54242) +FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesSingleToken_Success() (gas: 44886) FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesZeroInput() (gas: 12280) -FeeQuoter_applyTokenTransferFeeConfigUpdates:test_ApplyTokenTransferFeeConfig_Success() (gas: 86968) +FeeQuoter_applyTokenTransferFeeConfigUpdates:test_ApplyTokenTransferFeeConfig_Success() (gas: 87004) FeeQuoter_applyTokenTransferFeeConfigUpdates:test_ApplyTokenTransferFeeZeroInput() (gas: 13089) FeeQuoter_applyTokenTransferFeeConfigUpdates:test_InvalidDestBytesOverhead_Revert() (gas: 17071) -FeeQuoter_applyTokenTransferFeeConfigUpdates:test_OnlyCallableByOwnerOrAdmin_Revert() (gas: 12246) -FeeQuoter_constructor:test_InvalidLinkTokenEqZeroAddress_Revert() (gas: 106850) -FeeQuoter_constructor:test_InvalidMaxFeeJuelsPerMsg_Revert() (gas: 111200) -FeeQuoter_constructor:test_InvalidStalenessThreshold_Revert() (gas: 111253) -FeeQuoter_constructor:test_Setup_Success() (gas: 5219649) +FeeQuoter_applyTokenTransferFeeConfigUpdates:test_OnlyCallableByOwnerOrAdmin_Revert() (gas: 12252) +FeeQuoter_constructor:test_InvalidLinkTokenEqZeroAddress_Revert() (gas: 106781) +FeeQuoter_constructor:test_InvalidMaxFeeJuelsPerMsg_Revert() (gas: 111131) +FeeQuoter_constructor:test_InvalidStalenessThreshold_Revert() (gas: 111184) +FeeQuoter_constructor:test_Setup_Success() (gas: 5178579) FeeQuoter_convertTokenAmount:test_ConvertTokenAmount_Success() (gas: 68377) -FeeQuoter_convertTokenAmount:test_LinkTokenNotSupported_Revert() (gas: 29040) -FeeQuoter_getDataAvailabilityCost:test_EmptyMessageCalculatesDataAvailabilityCost_Success() (gas: 94441) +FeeQuoter_convertTokenAmount:test_LinkTokenNotSupported_Revert() (gas: 29076) +FeeQuoter_getDataAvailabilityCost:test_EmptyMessageCalculatesDataAvailabilityCost_Success() (gas: 94447) FeeQuoter_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCostUnsupportedDestChainSelector_Success() (gas: 14650) FeeQuoter_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCost_Success() (gas: 20482) FeeQuoter_getTokenAndGasPrices:test_GetFeeTokenAndGasPrices_Success() (gas: 68277) FeeQuoter_getTokenAndGasPrices:test_StaleGasPrice_Revert() (gas: 16838) FeeQuoter_getTokenAndGasPrices:test_UnsupportedChain_Revert() (gas: 16140) -FeeQuoter_getTokenAndGasPrices:test_ZeroGasPrice_Success() (gas: 43584) +FeeQuoter_getTokenAndGasPrices:test_ZeroGasPrice_Success() (gas: 43590) FeeQuoter_getTokenPrice:test_GetTokenPriceFromFeed_Success() (gas: 66117) FeeQuoter_getTokenPrices:test_GetTokenPrices_Success() (gas: 78256) -FeeQuoter_getTokenTransferCost:test_CustomTokenBpsFee_Success() (gas: 39094) -FeeQuoter_getTokenTransferCost:test_FeeTokenBpsFee_Success() (gas: 34730) -FeeQuoter_getTokenTransferCost:test_LargeTokenTransferChargesMaxFeeAndGas_Success() (gas: 27804) -FeeQuoter_getTokenTransferCost:test_MixedTokenTransferFee_Success() (gas: 96739) +FeeQuoter_getTokenTransferCost:test_CustomTokenBpsFee_Success() (gas: 39106) +FeeQuoter_getTokenTransferCost:test_FeeTokenBpsFee_Success() (gas: 34742) +FeeQuoter_getTokenTransferCost:test_LargeTokenTransferChargesMaxFeeAndGas_Success() (gas: 27816) +FeeQuoter_getTokenTransferCost:test_MixedTokenTransferFee_Success() (gas: 96829) FeeQuoter_getTokenTransferCost:test_NoTokenTransferChargesZeroFee_Success() (gas: 20390) -FeeQuoter_getTokenTransferCost:test_SmallTokenTransferChargesMinFeeAndGas_Success() (gas: 27679) -FeeQuoter_getTokenTransferCost:test_ZeroAmountTokenTransferChargesMinFeeAndGas_Success() (gas: 27635) -FeeQuoter_getTokenTransferCost:test_ZeroFeeConfigChargesMinFee_Success() (gas: 40064) -FeeQuoter_getTokenTransferCost:test_getTokenTransferCost_selfServeUsesDefaults_Success() (gas: 29347) +FeeQuoter_getTokenTransferCost:test_SmallTokenTransferChargesMinFeeAndGas_Success() (gas: 27691) +FeeQuoter_getTokenTransferCost:test_ZeroAmountTokenTransferChargesMinFeeAndGas_Success() (gas: 27647) +FeeQuoter_getTokenTransferCost:test_ZeroFeeConfigChargesMinFee_Success() (gas: 40076) +FeeQuoter_getTokenTransferCost:test_getTokenTransferCost_selfServeUsesDefaults_Success() (gas: 29359) FeeQuoter_getValidatedFee:test_DestinationChainNotEnabled_Revert() (gas: 18210) FeeQuoter_getValidatedFee:test_EmptyMessage_Success() (gas: 81749) -FeeQuoter_getValidatedFee:test_EnforceOutOfOrder_Revert() (gas: 52218) +FeeQuoter_getValidatedFee:test_EnforceOutOfOrder_Revert() (gas: 52224) FeeQuoter_getValidatedFee:test_HighGasMessage_Success() (gas: 238167) -FeeQuoter_getValidatedFee:test_InvalidEVMAddress_Revert() (gas: 22420) -FeeQuoter_getValidatedFee:test_MessageGasLimitTooHigh_Revert() (gas: 29646) +FeeQuoter_getValidatedFee:test_InvalidEVMAddress_Revert() (gas: 22426) +FeeQuoter_getValidatedFee:test_MessageGasLimitTooHigh_Revert() (gas: 29652) FeeQuoter_getValidatedFee:test_MessageTooLarge_Revert() (gas: 100163) -FeeQuoter_getValidatedFee:test_MessageWithDataAndTokenTransfer_Success() (gas: 140577) -FeeQuoter_getValidatedFee:test_NotAFeeToken_Revert() (gas: 21073) -FeeQuoter_getValidatedFee:test_SingleTokenMessage_Success() (gas: 112282) +FeeQuoter_getValidatedFee:test_MessageWithDataAndTokenTransfer_Success() (gas: 140673) +FeeQuoter_getValidatedFee:test_NotAFeeToken_Revert() (gas: 21079) +FeeQuoter_getValidatedFee:test_SingleTokenMessage_Success() (gas: 112330) FeeQuoter_getValidatedFee:test_TooManyTokens_Revert() (gas: 22562) FeeQuoter_getValidatedFee:test_ZeroDataAvailabilityMultiplier_Success() (gas: 62255) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Above18Decimals_Success() (gas: 2078733) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Below18Decimals_Success() (gas: 2078691) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt0Decimals_Success() (gas: 2058810) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt18Decimals_Success() (gas: 2078465) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFlippedDecimals_Success() (gas: 2078669) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedMaxInt224Value_Success() (gas: 2078481) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Above18Decimals_Success() (gas: 2068728) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Below18Decimals_Success() (gas: 2068686) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt0Decimals_Success() (gas: 2048805) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt18Decimals_Success() (gas: 2068460) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFlippedDecimals_Success() (gas: 2068664) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedMaxInt224Value_Success() (gas: 2068476) FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedOverStalenessPeriod_Success() (gas: 64412) FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeed_Success() (gas: 64292) FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPrice_Success() (gas: 58855) -FeeQuoter_getValidatedTokenPrice:test_OverflowFeedPrice_Revert() (gas: 2078166) +FeeQuoter_getValidatedTokenPrice:test_OverflowFeedPrice_Revert() (gas: 2068167) FeeQuoter_getValidatedTokenPrice:test_StaleFeeToken_Success() (gas: 61692) -FeeQuoter_getValidatedTokenPrice:test_TokenNotSupportedFeed_Revert() (gas: 116268) -FeeQuoter_getValidatedTokenPrice:test_TokenNotSupported_Revert() (gas: 13986) -FeeQuoter_getValidatedTokenPrice:test_UnderflowFeedPrice_Revert() (gas: 2076843) -FeeQuoter_onReport:test_OnReport_StaleUpdate_Revert() (gas: 43336) -FeeQuoter_onReport:test_onReport_InvalidForwarder_Reverts() (gas: 23306) -FeeQuoter_onReport:test_onReport_Success() (gas: 79834) -FeeQuoter_onReport:test_onReport_UnsupportedToken_Reverts() (gas: 26692) +FeeQuoter_getValidatedTokenPrice:test_TokenNotSupportedFeed_Revert() (gas: 116292) +FeeQuoter_getValidatedTokenPrice:test_TokenNotSupported_Revert() (gas: 14004) +FeeQuoter_getValidatedTokenPrice:test_UnderflowFeedPrice_Revert() (gas: 2066844) +FeeQuoter_onReport:test_OnReport_StaleUpdate_Revert() (gas: 43342) +FeeQuoter_onReport:test_onReport_InvalidForwarder_Reverts() (gas: 23312) +FeeQuoter_onReport:test_onReport_Success() (gas: 79840) +FeeQuoter_onReport:test_onReport_UnsupportedToken_Reverts() (gas: 26704) FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsDefault_Success() (gas: 17191) FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsEnforceOutOfOrder_Revert() (gas: 21302) FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsGasLimitTooHigh_Revert() (gas: 18399) @@ -399,550 +399,551 @@ FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsInvalidExtraArgsTag_Revert FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsV1_Success() (gas: 18291) FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsV2_Success() (gas: 18407) FeeQuoter_processMessageArgs:test_InvalidExtraArgs_Revert() (gas: 18339) -FeeQuoter_processMessageArgs:test_MalformedEVMExtraArgs_Revert() (gas: 18885) +FeeQuoter_processMessageArgs:test_MalformedEVMExtraArgs_Revert() (gas: 18891) FeeQuoter_processMessageArgs:test_MessageFeeTooHigh_Revert() (gas: 16404) -FeeQuoter_processMessageArgs:test_WitEVMExtraArgsV2_Success() (gas: 26277) +FeeQuoter_processMessageArgs:test_WitEVMExtraArgsV2_Success() (gas: 26295) FeeQuoter_processMessageArgs:test_WithConvertedTokenAmount_Success() (gas: 27695) -FeeQuoter_processMessageArgs:test_WithEVMExtraArgsV1_Success() (gas: 25889) -FeeQuoter_processMessageArgs:test_WithEmptyEVMExtraArgs_Success() (gas: 23704) +FeeQuoter_processMessageArgs:test_WithEVMExtraArgsV1_Success() (gas: 25901) +FeeQuoter_processMessageArgs:test_WithEmptyEVMExtraArgs_Success() (gas: 23716) FeeQuoter_processMessageArgs:test_WithLinkTokenAmount_Success() (gas: 17353) FeeQuoter_updatePrices:test_OnlyCallableByUpdater_Revert() (gas: 12114) FeeQuoter_updatePrices:test_OnlyGasPrice_Success() (gas: 23599) FeeQuoter_updatePrices:test_OnlyTokenPrice_Success() (gas: 28428) -FeeQuoter_updatePrices:test_UpdatableByAuthorizedCaller_Success() (gas: 74260) +FeeQuoter_updatePrices:test_UpdatableByAuthorizedCaller_Success() (gas: 74269) FeeQuoter_updatePrices:test_UpdateMultiplePrices_Success() (gas: 144784) FeeQuoter_updateTokenPriceFeeds:test_FeedNotUpdated() (gas: 50523) FeeQuoter_updateTokenPriceFeeds:test_FeedUnset_Success() (gas: 63200) -FeeQuoter_updateTokenPriceFeeds:test_FeedUpdatedByNonOwner_Revert() (gas: 19938) +FeeQuoter_updateTokenPriceFeeds:test_FeedUpdatedByNonOwner_Revert() (gas: 19944) FeeQuoter_updateTokenPriceFeeds:test_MultipleFeedUpdate_Success() (gas: 88920) FeeQuoter_updateTokenPriceFeeds:test_SingleFeedUpdate_Success() (gas: 50795) FeeQuoter_updateTokenPriceFeeds:test_ZeroFeeds_Success() (gas: 12296) -FeeQuoter_validateDestFamilyAddress:test_InvalidEVMAddressEncodePacked_Revert() (gas: 10622) -FeeQuoter_validateDestFamilyAddress:test_InvalidEVMAddressPrecompiles_Revert() (gas: 3967790) -FeeQuoter_validateDestFamilyAddress:test_InvalidEVMAddress_Revert() (gas: 10806) +FeeQuoter_validateDestFamilyAddress:test_InvalidEVMAddressEncodePacked_Revert() (gas: 10634) +FeeQuoter_validateDestFamilyAddress:test_InvalidEVMAddressPrecompiles_Revert() (gas: 3980078) +FeeQuoter_validateDestFamilyAddress:test_InvalidEVMAddress_Revert() (gas: 10818) FeeQuoter_validateDestFamilyAddress:test_ValidEVMAddress_Success() (gas: 6710) FeeQuoter_validateDestFamilyAddress:test_ValidNonEVMAddress_Success() (gas: 6484) -FeeQuoter_validatePoolReturnData:test_InvalidEVMAddressDestToken_Revert() (gas: 42769) -FeeQuoter_validatePoolReturnData:test_ProcessPoolReturnData_Success() (gas: 73306) -FeeQuoter_validatePoolReturnData:test_SourceTokenDataTooLarge_Revert() (gas: 107855) -FeeQuoter_validatePoolReturnData:test_TokenAmountArraysMismatching_Revert() (gas: 40106) -HybridUSDCTokenPoolMigrationTests:test_LockOrBurn_LockReleaseMechanism_then_switchToPrimary_Success() (gas: 208472) -HybridUSDCTokenPoolMigrationTests:test_LockOrBurn_PrimaryMechanism_Success() (gas: 135538) -HybridUSDCTokenPoolMigrationTests:test_LockOrBurn_WhileMigrationPause_Revert() (gas: 106706) -HybridUSDCTokenPoolMigrationTests:test_LockOrBurn_onLockReleaseMechanism_Success() (gas: 144163) -HybridUSDCTokenPoolMigrationTests:test_MintOrRelease_OnLockReleaseMechanism_Success() (gas: 214070) -HybridUSDCTokenPoolMigrationTests:test_MintOrRelease_OnLockReleaseMechanism_then_switchToPrimary_Success() (gas: 422174) -HybridUSDCTokenPoolMigrationTests:test_MintOrRelease_incomingMessageWithPrimaryMechanism() (gas: 268474) -HybridUSDCTokenPoolMigrationTests:test_ReleaseOrMint_WhileMigrationPause_Revert() (gas: 110983) -HybridUSDCTokenPoolMigrationTests:test_burnLockedUSDC_invalidPermissions_Revert() (gas: 39110) -HybridUSDCTokenPoolMigrationTests:test_cancelExistingCCTPMigrationProposal() (gas: 32949) -HybridUSDCTokenPoolMigrationTests:test_cannotCancelANonExistentMigrationProposal() (gas: 12606) -HybridUSDCTokenPoolMigrationTests:test_cannotModifyLiquidityWithoutPermissions_Revert() (gas: 13161) -HybridUSDCTokenPoolMigrationTests:test_cannotTransferLiquidityDuringPendingMigration_Revert() (gas: 160603) -HybridUSDCTokenPoolMigrationTests:test_lockOrBurn_then_BurnInCCTPMigration_Success() (gas: 254780) -HybridUSDCTokenPoolMigrationTests:test_transferLiquidity_Success() (gas: 165451) -HybridUSDCTokenPoolMigrationTests:test_unstickManualTxAfterMigration_destChain_Success() (gas: 153525) -HybridUSDCTokenPoolMigrationTests:test_unstickManualTxAfterMigration_homeChain_Success() (gas: 462264) -HybridUSDCTokenPoolTests:test_LockOrBurn_LockReleaseMechanism_then_switchToPrimary_Success() (gas: 208270) -HybridUSDCTokenPoolTests:test_LockOrBurn_PrimaryMechanism_Success() (gas: 135460) -HybridUSDCTokenPoolTests:test_LockOrBurn_WhileMigrationPause_Revert() (gas: 106751) -HybridUSDCTokenPoolTests:test_LockOrBurn_onLockReleaseMechanism_Success() (gas: 144151) -HybridUSDCTokenPoolTests:test_MintOrRelease_OnLockReleaseMechanism_Success() (gas: 214003) -HybridUSDCTokenPoolTests:test_MintOrRelease_OnLockReleaseMechanism_then_switchToPrimary_Success() (gas: 421969) -HybridUSDCTokenPoolTests:test_MintOrRelease_incomingMessageWithPrimaryMechanism() (gas: 268399) -HybridUSDCTokenPoolTests:test_ReleaseOrMint_WhileMigrationPause_Revert() (gas: 110982) -HybridUSDCTokenPoolTests:test_cannotTransferLiquidityDuringPendingMigration_Revert() (gas: 160548) -HybridUSDCTokenPoolTests:test_transferLiquidity_Success() (gas: 165371) -LockReleaseTokenPoolAndProxy_setRebalancer:test_SetRebalancer_Revert() (gas: 10977) -LockReleaseTokenPoolAndProxy_setRebalancer:test_SetRebalancer_Success() (gas: 17998) -LockReleaseTokenPoolPoolAndProxy_canAcceptLiquidity:test_CanAcceptLiquidity_Success() (gas: 3315195) -LockReleaseTokenPoolPoolAndProxy_provideLiquidity:test_LiquidityNotAccepted_Revert() (gas: 3311601) -LockReleaseTokenPoolPoolAndProxy_provideLiquidity:test_Unauthorized_Revert() (gas: 11405) -LockReleaseTokenPoolPoolAndProxy_supportsInterface:test_SupportsInterface_Success() (gas: 9977) -LockReleaseTokenPoolPoolAndProxy_withdrawalLiquidity:test_InsufficientLiquidity_Revert() (gas: 60060) +FeeQuoter_validatePoolReturnData:test_InvalidEVMAddressDestToken_Revert() (gas: 42781) +FeeQuoter_validatePoolReturnData:test_ProcessPoolReturnData_Success() (gas: 73330) +FeeQuoter_validatePoolReturnData:test_SourceTokenDataTooLarge_Revert() (gas: 107927) +FeeQuoter_validatePoolReturnData:test_TokenAmountArraysMismatching_Revert() (gas: 40112) +HybridUSDCTokenPoolMigrationTests:test_LockOrBurn_LockReleaseMechanism_then_switchToPrimary_Success() (gas: 209099) +HybridUSDCTokenPoolMigrationTests:test_LockOrBurn_PrimaryMechanism_Success() (gas: 135804) +HybridUSDCTokenPoolMigrationTests:test_LockOrBurn_WhileMigrationPause_Revert() (gas: 107078) +HybridUSDCTokenPoolMigrationTests:test_LockOrBurn_onLockReleaseMechanism_Success() (gas: 144568) +HybridUSDCTokenPoolMigrationTests:test_MintOrRelease_OnLockReleaseMechanism_Success() (gas: 214763) +HybridUSDCTokenPoolMigrationTests:test_MintOrRelease_OnLockReleaseMechanism_then_switchToPrimary_Success() (gas: 423554) +HybridUSDCTokenPoolMigrationTests:test_MintOrRelease_incomingMessageWithPrimaryMechanism() (gas: 268901) +HybridUSDCTokenPoolMigrationTests:test_ReleaseOrMint_WhileMigrationPause_Revert() (gas: 111457) +HybridUSDCTokenPoolMigrationTests:test_burnLockedUSDC_invalidPermissions_Revert() (gas: 39338) +HybridUSDCTokenPoolMigrationTests:test_cancelExistingCCTPMigrationProposal() (gas: 33151) +HybridUSDCTokenPoolMigrationTests:test_cannotCancelANonExistentMigrationProposal() (gas: 12651) +HybridUSDCTokenPoolMigrationTests:test_cannotModifyLiquidityWithoutPermissions_Revert() (gas: 13323) +HybridUSDCTokenPoolMigrationTests:test_cannotTransferLiquidityDuringPendingMigration_Revert() (gas: 160885) +HybridUSDCTokenPoolMigrationTests:test_lockOrBurn_then_BurnInCCTPMigration_Success() (gas: 255833) +HybridUSDCTokenPoolMigrationTests:test_transferLiquidity_Success() (gas: 165878) +HybridUSDCTokenPoolMigrationTests:test_unstickManualTxAfterMigration_destChain_Success() (gas: 154182) +HybridUSDCTokenPoolMigrationTests:test_unstickManualTxAfterMigration_homeChain_Success() (gas: 463620) +HybridUSDCTokenPoolTests:test_LockOrBurn_LockReleaseMechanism_then_switchToPrimary_Success() (gas: 208712) +HybridUSDCTokenPoolTests:test_LockOrBurn_PrimaryMechanism_Success() (gas: 135647) +HybridUSDCTokenPoolTests:test_LockOrBurn_WhileMigrationPause_Revert() (gas: 106991) +HybridUSDCTokenPoolTests:test_LockOrBurn_onLockReleaseMechanism_Success() (gas: 144457) +HybridUSDCTokenPoolTests:test_MintOrRelease_OnLockReleaseMechanism_Success() (gas: 214471) +HybridUSDCTokenPoolTests:test_MintOrRelease_OnLockReleaseMechanism_then_switchToPrimary_Success() (gas: 422833) +HybridUSDCTokenPoolTests:test_MintOrRelease_incomingMessageWithPrimaryMechanism() (gas: 268620) +HybridUSDCTokenPoolTests:test_ReleaseOrMint_WhileMigrationPause_Revert() (gas: 111336) +HybridUSDCTokenPoolTests:test_cannotTransferLiquidityDuringPendingMigration_Revert() (gas: 160764) +HybridUSDCTokenPoolTests:test_transferLiquidity_Success() (gas: 165649) +LockReleaseTokenPoolAndProxy_setRebalancer:test_SetRebalancer_Revert() (gas: 10983) +LockReleaseTokenPoolAndProxy_setRebalancer:test_SetRebalancer_Success() (gas: 18010) +LockReleaseTokenPoolPoolAndProxy_canAcceptLiquidity:test_CanAcceptLiquidity_Success() (gas: 3195288) +LockReleaseTokenPoolPoolAndProxy_provideLiquidity:test_LiquidityNotAccepted_Revert() (gas: 3191694) +LockReleaseTokenPoolPoolAndProxy_provideLiquidity:test_Unauthorized_Revert() (gas: 11417) +LockReleaseTokenPoolPoolAndProxy_supportsInterface:test_SupportsInterface_Success() (gas: 10124) +LockReleaseTokenPoolPoolAndProxy_withdrawalLiquidity:test_InsufficientLiquidity_Revert() (gas: 60081) LockReleaseTokenPoolPoolAndProxy_withdrawalLiquidity:test_Unauthorized_Revert() (gas: 11386) -LockReleaseTokenPool_canAcceptLiquidity:test_CanAcceptLiquidity_Success() (gas: 3071906) -LockReleaseTokenPool_lockOrBurn:test_LockOrBurnWithAllowList_Revert() (gas: 29960) -LockReleaseTokenPool_lockOrBurn:test_LockOrBurnWithAllowList_Success() (gas: 79868) -LockReleaseTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 59479) -LockReleaseTokenPool_provideLiquidity:test_LiquidityNotAccepted_Revert() (gas: 3068356) -LockReleaseTokenPool_provideLiquidity:test_Unauthorized_Revert() (gas: 11405) -LockReleaseTokenPool_releaseOrMint:test_ChainNotAllowed_Revert() (gas: 72666) -LockReleaseTokenPool_releaseOrMint:test_PoolMintNotHealthy_Revert() (gas: 56211) -LockReleaseTokenPool_releaseOrMint:test_ReleaseOrMint_Success() (gas: 225296) -LockReleaseTokenPool_setRebalancer:test_SetRebalancer_Revert() (gas: 10999) +LockReleaseTokenPool_canAcceptLiquidity:test_CanAcceptLiquidity_Success() (gas: 2982884) +LockReleaseTokenPool_lockOrBurn:test_LockOrBurnWithAllowList_Revert() (gas: 29972) +LockReleaseTokenPool_lockOrBurn:test_LockOrBurnWithAllowList_Success() (gas: 79880) +LockReleaseTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 59491) +LockReleaseTokenPool_provideLiquidity:test_LiquidityNotAccepted_Revert() (gas: 2979334) +LockReleaseTokenPool_provideLiquidity:test_Unauthorized_Revert() (gas: 11417) +LockReleaseTokenPool_releaseOrMint:test_ChainNotAllowed_Revert() (gas: 72680) +LockReleaseTokenPool_releaseOrMint:test_PoolMintNotHealthy_Revert() (gas: 56223) +LockReleaseTokenPool_releaseOrMint:test_ReleaseOrMint_Success() (gas: 225332) +LockReleaseTokenPool_setRebalancer:test_SetRebalancer_Revert() (gas: 11005) LockReleaseTokenPool_setRebalancer:test_SetRebalancer_Success() (gas: 18064) -LockReleaseTokenPool_supportsInterface:test_SupportsInterface_Success() (gas: 9977) -LockReleaseTokenPool_transferLiquidity:test_transferLiquidity_Success() (gas: 83177) +LockReleaseTokenPool_supportsInterface:test_SupportsInterface_Success() (gas: 10124) +LockReleaseTokenPool_transferLiquidity:test_transferLiquidity_Success() (gas: 83192) LockReleaseTokenPool_transferLiquidity:test_transferLiquidity_transferTooMuch_Revert() (gas: 55899) -LockReleaseTokenPool_withdrawalLiquidity:test_InsufficientLiquidity_Revert() (gas: 60060) +LockReleaseTokenPool_withdrawalLiquidity:test_InsufficientLiquidity_Revert() (gas: 60081) LockReleaseTokenPool_withdrawalLiquidity:test_Unauthorized_Revert() (gas: 11386) -LockRelease_setRateLimitAdmin:test_SetRateLimitAdmin_Revert() (gas: 11036) -LockRelease_setRateLimitAdmin:test_SetRateLimitAdmin_Success() (gas: 35030) -MerkleMultiProofTest:test_CVE_2023_34459() (gas: 5454) -MerkleMultiProofTest:test_EmptyLeaf_Revert() (gas: 3555) +LockRelease_setRateLimitAdmin:test_SetRateLimitAdmin_Revert() (gas: 11048) +LockRelease_setRateLimitAdmin:test_SetRateLimitAdmin_Success() (gas: 35036) +MerkleMultiProofTest:test_CVE_2023_34459() (gas: 5460) +MerkleMultiProofTest:test_EmptyLeaf_Revert() (gas: 3573) MerkleMultiProofTest:test_MerkleRoot256() (gas: 394879) MerkleMultiProofTest:test_MerkleRootSingleLeaf_Success() (gas: 3649) MerkleMultiProofTest:test_SpecSync_gas() (gas: 34123) -MockRouterTest:test_ccipSendWithInsufficientNativeTokens_Revert() (gas: 34019) -MockRouterTest:test_ccipSendWithInvalidMsgValue_Revert() (gas: 60812) -MockRouterTest:test_ccipSendWithLinkFeeTokenAndValidMsgValue_Success() (gas: 126540) -MockRouterTest:test_ccipSendWithLinkFeeTokenbutInsufficientAllowance_Revert() (gas: 63419) +MockRouterTest:test_ccipSendWithInsufficientNativeTokens_Revert() (gas: 34025) +MockRouterTest:test_ccipSendWithInvalidMsgValue_Revert() (gas: 60830) +MockRouterTest:test_ccipSendWithLinkFeeTokenAndValidMsgValue_Success() (gas: 126552) +MockRouterTest:test_ccipSendWithLinkFeeTokenbutInsufficientAllowance_Revert() (gas: 63431) MockRouterTest:test_ccipSendWithSufficientNativeFeeTokens_Success() (gas: 44012) MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_MultipleConfigsBothLanes_Success() (gas: 132457) MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_MultipleConfigs_Success() (gas: 313023) -MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_OnlyCallableByOwner_Revert() (gas: 17750) +MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_OnlyCallableByOwner_Revert() (gas: 17756) MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_SingleConfigOutbound_Success() (gas: 76030) MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_SingleConfig_Success() (gas: 75946) MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_UpdateExistingConfigWithNoDifference_Success() (gas: 38436) MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_UpdateExistingConfig_Success() (gas: 53473) MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_ZeroChainSelector_Revert() (gas: 17046) MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_ZeroConfigs_Success() (gas: 12361) -MultiAggregateRateLimiter_constructor:test_ConstructorNoAuthorizedCallers_Success() (gas: 2050112) -MultiAggregateRateLimiter_constructor:test_Constructor_Success() (gas: 2166413) +MultiAggregateRateLimiter_constructor:test_ConstructorNoAuthorizedCallers_Success() (gas: 2050118) +MultiAggregateRateLimiter_constructor:test_Constructor_Success() (gas: 2166419) MultiAggregateRateLimiter_getTokenBucket:test_GetTokenBucket_Success() (gas: 30404) -MultiAggregateRateLimiter_getTokenBucket:test_Refill_Success() (gas: 47673) +MultiAggregateRateLimiter_getTokenBucket:test_Refill_Success() (gas: 47679) MultiAggregateRateLimiter_getTokenBucket:test_TimeUnderflow_Revert() (gas: 15863) -MultiAggregateRateLimiter_getTokenValue:test_GetTokenValue_Success() (gas: 17459) -MultiAggregateRateLimiter_getTokenValue:test_NoTokenPrice_Reverts() (gas: 21354) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageFromUnauthorizedCaller_Revert() (gas: 14533) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithDifferentTokensOnDifferentChains_Success() (gas: 209639) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithDisabledRateLimitToken_Success() (gas: 58270) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithNoTokens_Success() (gas: 17599) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitDisabled_Success() (gas: 45006) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitExceeded_Revert() (gas: 46166) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitReset_Success() (gas: 76036) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithTokensOnDifferentChains_Success() (gas: 307711) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithTokens_Success() (gas: 50358) +MultiAggregateRateLimiter_getTokenValue:test_GetTokenValue_Success() (gas: 17465) +MultiAggregateRateLimiter_getTokenValue:test_NoTokenPrice_Reverts() (gas: 21360) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageFromUnauthorizedCaller_Revert() (gas: 14539) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithDifferentTokensOnDifferentChains_Success() (gas: 209717) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithDisabledRateLimitToken_Success() (gas: 58293) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithNoTokens_Success() (gas: 17605) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitDisabled_Success() (gas: 45057) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitExceeded_Revert() (gas: 46184) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitReset_Success() (gas: 76162) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithTokensOnDifferentChains_Success() (gas: 307789) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithTokens_Success() (gas: 50381) MultiAggregateRateLimiter_onOutboundMessage:test_RateLimitValueDifferentLanes_Success() (gas: 1073669836) MultiAggregateRateLimiter_onOutboundMessage:test_ValidateMessageWithNoTokens_Success() (gas: 19158) MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageFromUnauthorizedCaller_Revert() (gas: 15829) MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithDifferentTokensOnDifferentChains_Success() (gas: 209483) MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithDisabledRateLimitToken_Success() (gas: 60053) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitDisabled_Success() (gas: 46818) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitDisabled_Success() (gas: 46824) MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitExceeded_Revert() (gas: 47987) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitReset_Success() (gas: 77293) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitReset_Success() (gas: 77305) MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithTokensOnDifferentChains_Success() (gas: 307781) MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithTokens_Success() (gas: 52163) -MultiAggregateRateLimiter_setFeeQuoter:test_OnlyOwner_Revert() (gas: 11325) +MultiAggregateRateLimiter_setFeeQuoter:test_OnlyOwner_Revert() (gas: 11331) MultiAggregateRateLimiter_setFeeQuoter:test_Owner_Success() (gas: 19072) MultiAggregateRateLimiter_setFeeQuoter:test_ZeroAddress_Revert() (gas: 10597) -MultiAggregateRateLimiter_updateRateLimitTokens:test_NonOwner_Revert() (gas: 18800) +MultiAggregateRateLimiter_updateRateLimitTokens:test_NonOwner_Revert() (gas: 18806) MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokensMultipleChains_Success() (gas: 279944) MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokensSingleChain_Success() (gas: 254495) -MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokens_AddsAndRemoves_Success() (gas: 204465) -MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokens_RemoveNonExistentToken_Success() (gas: 28703) +MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokens_AddsAndRemoves_Success() (gas: 204470) +MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokens_RemoveNonExistentToken_Success() (gas: 28709) MultiAggregateRateLimiter_updateRateLimitTokens:test_ZeroDestToken_Revert() (gas: 18279) MultiAggregateRateLimiter_updateRateLimitTokens:test_ZeroSourceToken_Revert() (gas: 18208) MultiOCR3Base_setOCR3Configs:test_FMustBePositive_Revert() (gas: 59255) -MultiOCR3Base_setOCR3Configs:test_FTooHigh_Revert() (gas: 43629) -MultiOCR3Base_setOCR3Configs:test_RepeatSignerAddress_Revert() (gas: 283636) -MultiOCR3Base_setOCR3Configs:test_RepeatTransmitterAddress_Revert() (gas: 422261) -MultiOCR3Base_setOCR3Configs:test_SetConfigIgnoreSigners_Success() (gas: 511281) -MultiOCR3Base_setOCR3Configs:test_SetConfigWithSigners_Success() (gas: 828440) -MultiOCR3Base_setOCR3Configs:test_SetConfigWithoutSigners_Success() (gas: 456886) +MultiOCR3Base_setOCR3Configs:test_FTooHigh_Revert() (gas: 43632) +MultiOCR3Base_setOCR3Configs:test_RepeatSignerAddress_Revert() (gas: 283639) +MultiOCR3Base_setOCR3Configs:test_RepeatTransmitterAddress_Revert() (gas: 422264) +MultiOCR3Base_setOCR3Configs:test_SetConfigIgnoreSigners_Success() (gas: 511308) +MultiOCR3Base_setOCR3Configs:test_SetConfigWithSigners_Success() (gas: 828467) +MultiOCR3Base_setOCR3Configs:test_SetConfigWithoutSigners_Success() (gas: 456913) MultiOCR3Base_setOCR3Configs:test_SetConfigsZeroInput_Success() (gas: 12382) -MultiOCR3Base_setOCR3Configs:test_SetMultipleConfigs_Success() (gas: 2140159) -MultiOCR3Base_setOCR3Configs:test_SignerCannotBeZeroAddress_Revert() (gas: 141717) -MultiOCR3Base_setOCR3Configs:test_StaticConfigChange_Revert() (gas: 807340) -MultiOCR3Base_setOCR3Configs:test_TooManySigners_Revert() (gas: 158799) -MultiOCR3Base_setOCR3Configs:test_TooManyTransmitters_Revert() (gas: 112293) -MultiOCR3Base_setOCR3Configs:test_TransmitterCannotBeZeroAddress_Revert() (gas: 254083) -MultiOCR3Base_setOCR3Configs:test_UpdateConfigSigners_Success() (gas: 860224) -MultiOCR3Base_setOCR3Configs:test_UpdateConfigTransmittersWithoutSigners_Success() (gas: 475193) +MultiOCR3Base_setOCR3Configs:test_SetMultipleConfigs_Success() (gas: 2140246) +MultiOCR3Base_setOCR3Configs:test_SignerCannotBeZeroAddress_Revert() (gas: 141720) +MultiOCR3Base_setOCR3Configs:test_StaticConfigChange_Revert() (gas: 807349) +MultiOCR3Base_setOCR3Configs:test_TooManySigners_Revert() (gas: 158802) +MultiOCR3Base_setOCR3Configs:test_TooManyTransmitters_Revert() (gas: 112296) +MultiOCR3Base_setOCR3Configs:test_TransmitterCannotBeZeroAddress_Revert() (gas: 254086) +MultiOCR3Base_setOCR3Configs:test_UpdateConfigSigners_Success() (gas: 860245) +MultiOCR3Base_setOCR3Configs:test_UpdateConfigTransmittersWithoutSigners_Success() (gas: 475215) MultiOCR3Base_transmit:test_ConfigDigestMismatch_Revert() (gas: 42845) MultiOCR3Base_transmit:test_ForkedChain_Revert() (gas: 48450) -MultiOCR3Base_transmit:test_InsufficientSignatures_Revert() (gas: 76928) +MultiOCR3Base_transmit:test_InsufficientSignatures_Revert() (gas: 76934) MultiOCR3Base_transmit:test_NonUniqueSignature_Revert() (gas: 65768) MultiOCR3Base_transmit:test_SignatureOutOfRegistration_Revert() (gas: 33417) -MultiOCR3Base_transmit:test_TooManySignatures_Revert() (gas: 79519) +MultiOCR3Base_transmit:test_TooManySignatures_Revert() (gas: 79525) MultiOCR3Base_transmit:test_TransmitSigners_gas_Success() (gas: 33631) -MultiOCR3Base_transmit:test_TransmitWithExtraCalldataArgs_Revert() (gas: 47122) -MultiOCR3Base_transmit:test_TransmitWithLessCalldataArgs_Revert() (gas: 25690) +MultiOCR3Base_transmit:test_TransmitWithExtraCalldataArgs_Revert() (gas: 47128) +MultiOCR3Base_transmit:test_TransmitWithLessCalldataArgs_Revert() (gas: 25696) MultiOCR3Base_transmit:test_TransmitWithoutSignatureVerification_gas_Success() (gas: 18712) -MultiOCR3Base_transmit:test_UnAuthorizedTransmitter_Revert() (gas: 24189) +MultiOCR3Base_transmit:test_UnAuthorizedTransmitter_Revert() (gas: 24195) MultiOCR3Base_transmit:test_UnauthorizedSigner_Revert() (gas: 61131) -MultiOCR3Base_transmit:test_UnconfiguredPlugin_Revert() (gas: 39888) -MultiOCR3Base_transmit:test_ZeroSignatures_Revert() (gas: 32971) -MultiOnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 409147) -MultiRampsE2E:test_E2E_3MessagesMMultiOffRampSuccess_gas() (gas: 1526265) -NonceManager_NonceIncrementation:test_getIncrementedOutboundNonce_Success() (gas: 37916) +MultiOCR3Base_transmit:test_UnconfiguredPlugin_Revert() (gas: 39894) +MultiOCR3Base_transmit:test_ZeroSignatures_Revert() (gas: 32977) +MultiOnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 409189) +MultiRampsE2E:test_E2E_3MessagesMMultiOffRampSuccess_gas() (gas: 1537029) +NonceManager_NonceIncrementation:test_getIncrementedOutboundNonce_Success() (gas: 37922) NonceManager_NonceIncrementation:test_incrementInboundNonce_Skip() (gas: 23709) NonceManager_NonceIncrementation:test_incrementInboundNonce_Success() (gas: 38799) -NonceManager_NonceIncrementation:test_incrementNoncesInboundAndOutbound_Success() (gas: 71898) -NonceManager_OffRampUpgrade:test_NoPrevOffRampForChain_Success() (gas: 260404) -NonceManager_OffRampUpgrade:test_UpgradedNonceNewSenderStartsAtZero_Success() (gas: 264546) -NonceManager_OffRampUpgrade:test_UpgradedNonceStartsAtV1Nonce_Success() (gas: 327828) -NonceManager_OffRampUpgrade:test_UpgradedOffRampNonceSkipsIfMsgInFlight_Success() (gas: 299527) -NonceManager_OffRampUpgrade:test_UpgradedSenderNoncesReadsPreviousRampTransitive_Success() (gas: 244871) -NonceManager_OffRampUpgrade:test_UpgradedSenderNoncesReadsPreviousRamp_Success() (gas: 232964) -NonceManager_OffRampUpgrade:test_Upgraded_Success() (gas: 153309) -NonceManager_OnRampUpgrade:test_UpgradeNonceNewSenderStartsAtZero_Success() (gas: 168358) -NonceManager_OnRampUpgrade:test_UpgradeNonceStartsAtV1Nonce_Success() (gas: 220193) -NonceManager_OnRampUpgrade:test_UpgradeSenderNoncesReadsPreviousRamp_Success() (gas: 125157) +NonceManager_NonceIncrementation:test_incrementNoncesInboundAndOutbound_Success() (gas: 71904) +NonceManager_OffRampUpgrade:test_NoPrevOffRampForChain_Success() (gas: 262138) +NonceManager_OffRampUpgrade:test_UpgradedNonceNewSenderStartsAtZero_Success() (gas: 266256) +NonceManager_OffRampUpgrade:test_UpgradedNonceStartsAtV1Nonce_Success() (gas: 331224) +NonceManager_OffRampUpgrade:test_UpgradedOffRampNonceSkipsIfMsgInFlight_Success() (gas: 302071) +NonceManager_OffRampUpgrade:test_UpgradedSenderNoncesReadsPreviousRampTransitive_Success() (gas: 245579) +NonceManager_OffRampUpgrade:test_UpgradedSenderNoncesReadsPreviousRamp_Success() (gas: 233648) +NonceManager_OffRampUpgrade:test_Upgraded_Success() (gas: 154815) +NonceManager_OnRampUpgrade:test_UpgradeNonceNewSenderStartsAtZero_Success() (gas: 168463) +NonceManager_OnRampUpgrade:test_UpgradeNonceStartsAtV1Nonce_Success() (gas: 220298) +NonceManager_OnRampUpgrade:test_UpgradeSenderNoncesReadsPreviousRamp_Success() (gas: 125472) NonceManager_OnRampUpgrade:test_Upgrade_Success() (gas: 107566) -NonceManager_applyPreviousRampsUpdates:test_MultipleRampsUpdates() (gas: 122955) -NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySetOffRamp_Revert() (gas: 42965) -NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySetOnRampAndOffRamp_Revert() (gas: 64288) -NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySetOnRamp_Revert() (gas: 42829) -NonceManager_applyPreviousRampsUpdates:test_SingleRampUpdate() (gas: 66576) +NonceManager_applyPreviousRampsUpdates:test_MultipleRampsUpdates() (gas: 122961) +NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySetOffRamp_Revert() (gas: 42983) +NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySetOnRampAndOffRamp_Revert() (gas: 64312) +NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySetOnRamp_Revert() (gas: 42847) +NonceManager_applyPreviousRampsUpdates:test_SingleRampUpdate() (gas: 66594) NonceManager_applyPreviousRampsUpdates:test_ZeroInput() (gas: 12025) NonceManager_typeAndVersion:test_typeAndVersion() (gas: 9699) -OCR2BaseNoChecks_setOCR2Config:test_FMustBePositive_Revert() (gas: 12183) -OCR2BaseNoChecks_setOCR2Config:test_RepeatAddress_Revert() (gas: 42404) -OCR2BaseNoChecks_setOCR2Config:test_SetConfigSuccess_gas() (gas: 84585) -OCR2BaseNoChecks_setOCR2Config:test_TooManyTransmitter_Revert() (gas: 38150) +OCR2BaseNoChecks_setOCR2Config:test_FMustBePositive_Revert() (gas: 12195) +OCR2BaseNoChecks_setOCR2Config:test_RepeatAddress_Revert() (gas: 42416) +OCR2BaseNoChecks_setOCR2Config:test_SetConfigSuccess_gas() (gas: 84590) +OCR2BaseNoChecks_setOCR2Config:test_TooManyTransmitter_Revert() (gas: 38162) OCR2BaseNoChecks_setOCR2Config:test_TransmitterCannotBeZeroAddress_Revert() (gas: 24290) -OCR2BaseNoChecks_transmit:test_ConfigDigestMismatch_Revert() (gas: 17469) -OCR2BaseNoChecks_transmit:test_ForkedChain_Revert() (gas: 26762) +OCR2BaseNoChecks_transmit:test_ConfigDigestMismatch_Revert() (gas: 17475) +OCR2BaseNoChecks_transmit:test_ForkedChain_Revert() (gas: 26768) OCR2BaseNoChecks_transmit:test_TransmitSuccess_gas() (gas: 27499) OCR2BaseNoChecks_transmit:test_UnAuthorizedTransmitter_Revert() (gas: 21317) OCR2Base_setOCR2Config:test_FMustBePositive_Revert() (gas: 12201) OCR2Base_setOCR2Config:test_FTooHigh_Revert() (gas: 12357) OCR2Base_setOCR2Config:test_OracleOutOfRegister_Revert() (gas: 14904) OCR2Base_setOCR2Config:test_RepeatAddress_Revert() (gas: 45454) -OCR2Base_setOCR2Config:test_SetConfigSuccess_gas() (gas: 155211) -OCR2Base_setOCR2Config:test_SingerCannotBeZeroAddress_Revert() (gas: 24407) +OCR2Base_setOCR2Config:test_SetConfigSuccess_gas() (gas: 155216) +OCR2Base_setOCR2Config:test_SingerCannotBeZeroAddress_Revert() (gas: 24413) OCR2Base_setOCR2Config:test_TooManySigners_Revert() (gas: 20520) -OCR2Base_setOCR2Config:test_TransmitterCannotBeZeroAddress_Revert() (gas: 47298) -OCR2Base_transmit:test_ConfigDigestMismatch_Revert() (gas: 19638) -OCR2Base_transmit:test_ForkedChain_Revert() (gas: 37713) +OCR2Base_setOCR2Config:test_TransmitterCannotBeZeroAddress_Revert() (gas: 47304) +OCR2Base_transmit:test_ConfigDigestMismatch_Revert() (gas: 19644) +OCR2Base_transmit:test_ForkedChain_Revert() (gas: 37719) OCR2Base_transmit:test_NonUniqueSignature_Revert() (gas: 55324) OCR2Base_transmit:test_SignatureOutOfRegistration_Revert() (gas: 20977) OCR2Base_transmit:test_Transmit2SignersSuccess_gas() (gas: 51689) OCR2Base_transmit:test_UnAuthorizedTransmitter_Revert() (gas: 23499) OCR2Base_transmit:test_UnauthorizedSigner_Revert() (gas: 39695) OCR2Base_transmit:test_WrongNumberOfSignatures_Revert() (gas: 20572) -OffRamp_afterOC3ConfigSet:test_afterOCR3ConfigSet_SignatureVerificationDisabled_Revert() (gas: 6056933) -OffRamp_applySourceChainConfigUpdates:test_AddMultipleChains_Success() (gas: 468074) -OffRamp_applySourceChainConfigUpdates:test_AddNewChain_Success() (gas: 99238) -OffRamp_applySourceChainConfigUpdates:test_ApplyZeroUpdates_Success() (gas: 12414) -OffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChainOnRamp_Revert() (gas: 93240) -OffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChain_Success() (gas: 109971) -OffRamp_applySourceChainConfigUpdates:test_RouterAddress_Revert() (gas: 13288) -OffRamp_applySourceChainConfigUpdates:test_ZeroOnRampAddress_Revert() (gas: 18022) -OffRamp_applySourceChainConfigUpdates:test_ZeroSourceChainSelector_Revert() (gas: 15371) -OffRamp_batchExecute:test_MultipleReportsDifferentChainsSkipCursedChain_Success() (gas: 177419) -OffRamp_batchExecute:test_MultipleReportsDifferentChains_Success() (gas: 334109) -OffRamp_batchExecute:test_MultipleReportsSameChain_Success() (gas: 277477) -OffRamp_batchExecute:test_MultipleReportsSkipDuplicate_Success() (gas: 168556) -OffRamp_batchExecute:test_OutOfBoundsGasLimitsAccess_Revert() (gas: 188490) -OffRamp_batchExecute:test_SingleReport_Success() (gas: 156460) -OffRamp_batchExecute:test_Unhealthy_Success() (gas: 572587) -OffRamp_batchExecute:test_ZeroReports_Revert() (gas: 10486) -OffRamp_ccipReceive:test_Reverts() (gas: 15770) -OffRamp_commit:test_FailedRMNVerification_Reverts() (gas: 64420) -OffRamp_commit:test_InvalidIntervalMinLargerThanMax_Revert() (gas: 67632) -OffRamp_commit:test_InvalidInterval_Revert() (gas: 59886) -OffRamp_commit:test_InvalidRootRevert() (gas: 58921) -OffRamp_commit:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6661100) -OffRamp_commit:test_NoConfig_Revert() (gas: 6244915) -OffRamp_commit:test_OnlyGasPriceUpdates_Success() (gas: 112473) -OffRamp_commit:test_OnlyPriceUpdateStaleReport_Revert() (gas: 120501) -OffRamp_commit:test_OnlyTokenPriceUpdates_Success() (gas: 112494) -OffRamp_commit:test_PriceSequenceNumberCleared_Success() (gas: 353540) -OffRamp_commit:test_ReportAndPriceUpdate_Success() (gas: 164945) -OffRamp_commit:test_ReportOnlyRootSuccess_gas() (gas: 139934) -OffRamp_commit:test_RootAlreadyCommitted_Revert() (gas: 141925) -OffRamp_commit:test_SourceChainNotEnabled_Revert() (gas: 59208) -OffRamp_commit:test_StaleReportWithRoot_Success() (gas: 232957) -OffRamp_commit:test_UnauthorizedTransmitter_Revert() (gas: 121451) -OffRamp_commit:test_Unhealthy_Revert() (gas: 57938) -OffRamp_commit:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 206779) -OffRamp_commit:test_ZeroEpochAndRound_Revert() (gas: 51273) -OffRamp_constructor:test_Constructor_Success() (gas: 6244332) -OffRamp_constructor:test_SourceChainSelector_Revert() (gas: 136075) -OffRamp_constructor:test_ZeroChainSelector_Revert() (gas: 103518) -OffRamp_constructor:test_ZeroNonceManager_Revert() (gas: 101418) -OffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 138723) -OffRamp_constructor:test_ZeroRMNRemote_Revert() (gas: 101338) -OffRamp_constructor:test_ZeroTokenAdminRegistry_Revert() (gas: 101376) -OffRamp_execute:test_IncorrectArrayType_Revert() (gas: 17505) -OffRamp_execute:test_LargeBatch_Success() (gas: 3391111) -OffRamp_execute:test_MultipleReportsWithPartialValidationFailures_Success() (gas: 372353) -OffRamp_execute:test_MultipleReports_Success() (gas: 299779) -OffRamp_execute:test_NoConfigWithOtherConfigPresent_Revert() (gas: 7069102) -OffRamp_execute:test_NoConfig_Revert() (gas: 6293902) -OffRamp_execute:test_NonArray_Revert() (gas: 27787) -OffRamp_execute:test_SingleReport_Success() (gas: 175730) -OffRamp_execute:test_UnauthorizedTransmitter_Revert() (gas: 147970) -OffRamp_execute:test_WrongConfigWithSigners_Revert() (gas: 7071845) -OffRamp_execute:test_ZeroReports_Revert() (gas: 17227) -OffRamp_executeSingleMessage:test_MessageSender_Revert() (gas: 18682) -OffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 247849) -OffRamp_executeSingleMessage:test_NonContract_Success() (gas: 21002) -OffRamp_executeSingleMessage:test_TokenHandlingError_Revert() (gas: 208927) -OffRamp_executeSingleMessage:test_ZeroGasDONExecution_Revert() (gas: 49237) -OffRamp_executeSingleMessage:test_executeSingleMessage_NoTokens_Success() (gas: 48725) -OffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidationNoRouterCall_Revert() (gas: 228696) -OffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidation_Revert() (gas: 85260) -OffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens_Success() (gas: 279681) -OffRamp_executeSingleMessage:test_executeSingleMessage_WithValidation_Success() (gas: 91512) -OffRamp_executeSingleReport:test_DisabledSourceChain_Revert() (gas: 28226) -OffRamp_executeSingleReport:test_EmptyReport_Revert() (gas: 21832) -OffRamp_executeSingleReport:test_InvalidSourcePoolAddress_Success() (gas: 499180) -OffRamp_executeSingleReport:test_ManualExecutionNotYetEnabled_Revert() (gas: 48620) -OffRamp_executeSingleReport:test_MismatchingDestChainSelector_Revert() (gas: 33892) -OffRamp_executeSingleReport:test_MismatchingOnRampRoot_Revert() (gas: 154020) -OffRamp_executeSingleReport:test_NonExistingSourceChain_Revert() (gas: 28449) -OffRamp_executeSingleReport:test_ReceiverError_Success() (gas: 188116) -OffRamp_executeSingleReport:test_RetryFailedMessageWithoutManualExecution_Revert() (gas: 198571) -OffRamp_executeSingleReport:test_RootNotCommitted_Revert() (gas: 41037) -OffRamp_executeSingleReport:test_RouterYULCall_Revert() (gas: 447967) -OffRamp_executeSingleReport:test_SingleMessageNoTokensOtherChain_Success() (gas: 248847) -OffRamp_executeSingleReport:test_SingleMessageNoTokensUnordered_Success() (gas: 193195) -OffRamp_executeSingleReport:test_SingleMessageNoTokens_Success() (gas: 212816) -OffRamp_executeSingleReport:test_SingleMessageToNonCCIPReceiver_Success() (gas: 260215) -OffRamp_executeSingleReport:test_SingleMessagesNoTokensSuccess_gas() (gas: 141403) -OffRamp_executeSingleReport:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 423165) -OffRamp_executeSingleReport:test_SkippedIncorrectNonce_Success() (gas: 59057) -OffRamp_executeSingleReport:test_TokenDataMismatch_Revert() (gas: 74155) -OffRamp_executeSingleReport:test_TwoMessagesWithTokensAndGE_Success() (gas: 599623) -OffRamp_executeSingleReport:test_TwoMessagesWithTokensSuccess_gas() (gas: 543529) -OffRamp_executeSingleReport:test_UnexpectedTokenData_Revert() (gas: 33663) -OffRamp_executeSingleReport:test_UnhealthySingleChainCurse_Revert() (gas: 568482) -OffRamp_executeSingleReport:test_Unhealthy_Success() (gas: 568496) -OffRamp_executeSingleReport:test_WithCurseOnAnotherSourceChain_Success() (gas: 473801) -OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessageUnordered_Success() (gas: 135923) -OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessage_Success() (gas: 165161) -OffRamp_getExecutionState:test_FillExecutionState_Success() (gas: 3737630) -OffRamp_getExecutionState:test_GetDifferentChainExecutionState_Success() (gas: 119064) -OffRamp_getExecutionState:test_GetExecutionState_Success() (gas: 88148) -OffRamp_manuallyExecute:test_ManualExecGasLimitMismatchSingleReport_Revert() (gas: 79036) -OffRamp_manuallyExecute:test_manuallyExecute_DestinationGasAmountCountMismatch_Revert() (gas: 78924) -OffRamp_manuallyExecute:test_manuallyExecute_DoesNotRevertIfUntouched_Success() (gas: 172960) -OffRamp_manuallyExecute:test_manuallyExecute_FailedTx_Revert() (gas: 213287) -OffRamp_manuallyExecute:test_manuallyExecute_ForkedChain_Revert() (gas: 26909) -OffRamp_manuallyExecute:test_manuallyExecute_GasLimitMismatchMultipleReports_Revert() (gas: 159537) -OffRamp_manuallyExecute:test_manuallyExecute_InvalidReceiverExecutionGasLimit_Revert() (gas: 27468) -OffRamp_manuallyExecute:test_manuallyExecute_InvalidTokenGasOverride_Revert() (gas: 58874) -OffRamp_manuallyExecute:test_manuallyExecute_LowGasLimit_Success() (gas: 532013) -OffRamp_manuallyExecute:test_manuallyExecute_MultipleReportsWithSingleCursedLane_Revert() (gas: 317521) -OffRamp_manuallyExecute:test_manuallyExecute_ReentrancyFails_Success() (gas: 2390649) -OffRamp_manuallyExecute:test_manuallyExecute_SourceChainSelectorMismatch_Revert() (gas: 164912) -OffRamp_manuallyExecute:test_manuallyExecute_Success() (gas: 226245) -OffRamp_manuallyExecute:test_manuallyExecute_WithGasOverride_Success() (gas: 226785) -OffRamp_manuallyExecute:test_manuallyExecute_WithMultiReportGasOverride_Success() (gas: 778479) -OffRamp_manuallyExecute:test_manuallyExecute_WithPartialMessages_Success() (gas: 346205) -OffRamp_releaseOrMintSingleToken:test__releaseOrMintSingleToken_NotACompatiblePool_Revert() (gas: 40239) -OffRamp_releaseOrMintSingleToken:test__releaseOrMintSingleToken_Success() (gas: 105265) -OffRamp_releaseOrMintSingleToken:test__releaseOrMintSingleToken_TokenHandlingError_transfer_Revert() (gas: 86476) -OffRamp_releaseOrMintSingleToken:test_releaseOrMintToken_InvalidDataLength_Revert() (gas: 37975) -OffRamp_releaseOrMintSingleToken:test_releaseOrMintToken_ReleaseOrMintBalanceMismatch_Revert() (gas: 95515) -OffRamp_releaseOrMintSingleToken:test_releaseOrMintToken_TokenHandlingError_BalanceOf_Revert() (gas: 40961) -OffRamp_releaseOrMintSingleToken:test_releaseOrMintToken_skip_ReleaseOrMintBalanceMismatch_if_pool_Revert() (gas: 87721) -OffRamp_releaseOrMintTokens:test_TokenHandlingError_Reverts() (gas: 164647) -OffRamp_releaseOrMintTokens:test__releaseOrMintTokens_PoolIsNotAPool_Reverts() (gas: 25146) -OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_InvalidDataLengthReturnData_Revert() (gas: 64911) -OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_InvalidEVMAddress_Revert() (gas: 41883) -OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_PoolDoesNotSupportDest_Reverts() (gas: 81999) -OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_Success() (gas: 176661) -OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_WithGasOverride_Success() (gas: 178641) -OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals_Success() (gas: 189850) -OffRamp_setDynamicConfig:test_FeeQuoterZeroAddress_Revert() (gas: 11189) -OffRamp_setDynamicConfig:test_NonOwner_Revert() (gas: 13793) -OffRamp_setDynamicConfig:test_SetDynamicConfigWithValidator_Success() (gas: 46198) -OffRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 24173) -OffRamp_trialExecute:test_RateLimitError_Success() (gas: 225140) -OffRamp_trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 233762) -OffRamp_trialExecute:test_TokenPoolIsNotAContract_Success() (gas: 310735) -OffRamp_trialExecute:test_trialExecute_Success() (gas: 283386) -OnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 387975) -OnRamp_applyAllowListUpdates:test_applyAllowListUpdates_InvalidAllowListRequestDisabledAllowListWithAdds() (gas: 17746) -OnRamp_applyAllowListUpdates:test_applyAllowListUpdates_Revert() (gas: 66535) -OnRamp_applyAllowListUpdates:test_applyAllowListUpdates_Success() (gas: 323600) +OffRamp_afterOC3ConfigSet:test_afterOCR3ConfigSet_SignatureVerificationDisabled_Revert() (gas: 5983389) +OffRamp_applySourceChainConfigUpdates:test_AddMultipleChains_Success() (gas: 468168) +OffRamp_applySourceChainConfigUpdates:test_AddNewChain_Success() (gas: 99296) +OffRamp_applySourceChainConfigUpdates:test_ApplyZeroUpdates_Success() (gas: 12472) +OffRamp_applySourceChainConfigUpdates:test_InvalidOnRampUpdate_Revert() (gas: 204676) +OffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChainOnRamp_Success() (gas: 101379) +OffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChain_Success() (gas: 110796) +OffRamp_applySourceChainConfigUpdates:test_RouterAddress_Revert() (gas: 13418) +OffRamp_applySourceChainConfigUpdates:test_ZeroOnRampAddress_Revert() (gas: 72638) +OffRamp_applySourceChainConfigUpdates:test_ZeroSourceChainSelector_Revert() (gas: 15462) +OffRamp_batchExecute:test_MultipleReportsDifferentChainsSkipCursedChain_Success() (gas: 179216) +OffRamp_batchExecute:test_MultipleReportsDifferentChains_Success() (gas: 337235) +OffRamp_batchExecute:test_MultipleReportsSameChain_Success() (gas: 280603) +OffRamp_batchExecute:test_MultipleReportsSkipDuplicate_Success() (gas: 170311) +OffRamp_batchExecute:test_OutOfBoundsGasLimitsAccess_Revert() (gas: 190845) +OffRamp_batchExecute:test_SingleReport_Success() (gas: 157648) +OffRamp_batchExecute:test_Unhealthy_Success() (gas: 578050) +OffRamp_batchExecute:test_ZeroReports_Revert() (gas: 10576) +OffRamp_ccipReceive:test_Reverts() (gas: 15782) +OffRamp_commit:test_CommitOnRampMismatch_Revert() (gas: 92492) +OffRamp_commit:test_FailedRMNVerification_Reverts() (gas: 63748) +OffRamp_commit:test_InvalidIntervalMinLargerThanMax_Revert() (gas: 67769) +OffRamp_commit:test_InvalidInterval_Revert() (gas: 63936) +OffRamp_commit:test_InvalidRootRevert() (gas: 63009) +OffRamp_commit:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6587105) +OffRamp_commit:test_NoConfig_Revert() (gas: 6170887) +OffRamp_commit:test_OnlyGasPriceUpdates_Success() (gas: 112719) +OffRamp_commit:test_OnlyPriceUpdateStaleReport_Revert() (gas: 120939) +OffRamp_commit:test_OnlyTokenPriceUpdates_Success() (gas: 112740) +OffRamp_commit:test_PriceSequenceNumberCleared_Success() (gas: 354230) +OffRamp_commit:test_ReportAndPriceUpdate_Success() (gas: 163890) +OffRamp_commit:test_ReportOnlyRootSuccess_gas() (gas: 138880) +OffRamp_commit:test_RootAlreadyCommitted_Revert() (gas: 145911) +OffRamp_commit:test_SourceChainNotEnabled_Revert() (gas: 59492) +OffRamp_commit:test_StaleReportWithRoot_Success() (gas: 231183) +OffRamp_commit:test_UnauthorizedTransmitter_Revert() (gas: 124994) +OffRamp_commit:test_Unhealthy_Revert() (gas: 58244) +OffRamp_commit:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 205947) +OffRamp_commit:test_ZeroEpochAndRound_Revert() (gas: 51483) +OffRamp_constructor:test_Constructor_Success() (gas: 6170587) +OffRamp_constructor:test_SourceChainSelector_Revert() (gas: 135943) +OffRamp_constructor:test_ZeroChainSelector_Revert() (gas: 103386) +OffRamp_constructor:test_ZeroNonceManager_Revert() (gas: 101280) +OffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 161468) +OffRamp_constructor:test_ZeroRMNRemote_Revert() (gas: 101200) +OffRamp_constructor:test_ZeroTokenAdminRegistry_Revert() (gas: 101238) +OffRamp_execute:test_IncorrectArrayType_Revert() (gas: 17610) +OffRamp_execute:test_LargeBatch_Success() (gas: 3419182) +OffRamp_execute:test_MultipleReportsWithPartialValidationFailures_Success() (gas: 375374) +OffRamp_execute:test_MultipleReports_Success() (gas: 302902) +OffRamp_execute:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6996650) +OffRamp_execute:test_NoConfig_Revert() (gas: 6221351) +OffRamp_execute:test_NonArray_Revert() (gas: 27961) +OffRamp_execute:test_SingleReport_Success() (gas: 176939) +OffRamp_execute:test_UnauthorizedTransmitter_Revert() (gas: 149068) +OffRamp_execute:test_WrongConfigWithSigners_Revert() (gas: 6999426) +OffRamp_execute:test_ZeroReports_Revert() (gas: 17293) +OffRamp_executeSingleMessage:test_MessageSender_Revert() (gas: 18874) +OffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 248743) +OffRamp_executeSingleMessage:test_NonContract_Success() (gas: 21206) +OffRamp_executeSingleMessage:test_TokenHandlingError_Revert() (gas: 209803) +OffRamp_executeSingleMessage:test_ZeroGasDONExecution_Revert() (gas: 49525) +OffRamp_executeSingleMessage:test_executeSingleMessage_NoTokens_Success() (gas: 49013) +OffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidationNoRouterCall_Revert() (gas: 218730) +OffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidation_Revert() (gas: 85512) +OffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens_Success() (gas: 280659) +OffRamp_executeSingleMessage:test_executeSingleMessage_WithValidation_Success() (gas: 91830) +OffRamp_executeSingleReport:test_DisabledSourceChain_Revert() (gas: 28730) +OffRamp_executeSingleReport:test_EmptyReport_Revert() (gas: 22018) +OffRamp_executeSingleReport:test_InvalidSourcePoolAddress_Success() (gas: 503897) +OffRamp_executeSingleReport:test_ManualExecutionNotYetEnabled_Revert() (gas: 49358) +OffRamp_executeSingleReport:test_MismatchingDestChainSelector_Revert() (gas: 34462) +OffRamp_executeSingleReport:test_NonExistingSourceChain_Revert() (gas: 28977) +OffRamp_executeSingleReport:test_ReceiverError_Success() (gas: 189608) +OffRamp_executeSingleReport:test_RetryFailedMessageWithoutManualExecution_Revert() (gas: 200597) +OffRamp_executeSingleReport:test_RootNotCommitted_Revert() (gas: 41727) +OffRamp_executeSingleReport:test_RouterYULCall_Revert() (gas: 449309) +OffRamp_executeSingleReport:test_SingleMessageNoTokensOtherChain_Success() (gas: 251345) +OffRamp_executeSingleReport:test_SingleMessageNoTokensUnordered_Success() (gas: 196311) +OffRamp_executeSingleReport:test_SingleMessageNoTokens_Success() (gas: 215860) +OffRamp_executeSingleReport:test_SingleMessageToNonCCIPReceiver_Success() (gas: 251303) +OffRamp_executeSingleReport:test_SingleMessagesNoTokensSuccess_gas() (gas: 142769) +OffRamp_executeSingleReport:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 426988) +OffRamp_executeSingleReport:test_SkippedIncorrectNonce_Success() (gas: 59801) +OffRamp_executeSingleReport:test_TokenDataMismatch_Revert() (gas: 74893) +OffRamp_executeSingleReport:test_TwoMessagesWithTokensAndGE_Success() (gas: 605297) +OffRamp_executeSingleReport:test_TwoMessagesWithTokensSuccess_gas() (gas: 548785) +OffRamp_executeSingleReport:test_UnexpectedTokenData_Revert() (gas: 34181) +OffRamp_executeSingleReport:test_UnhealthySingleChainCurse_Revert() (gas: 575250) +OffRamp_executeSingleReport:test_Unhealthy_Success() (gas: 575264) +OffRamp_executeSingleReport:test_WithCurseOnAnotherSourceChain_Success() (gas: 478001) +OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessageUnordered_Success() (gas: 138039) +OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessage_Success() (gas: 167264) +OffRamp_getExecutionState:test_FillExecutionState_Success() (gas: 3894518) +OffRamp_getExecutionState:test_GetDifferentChainExecutionState_Success() (gas: 120480) +OffRamp_getExecutionState:test_GetExecutionState_Success() (gas: 89540) +OffRamp_manuallyExecute:test_ManualExecGasLimitMismatchSingleReport_Revert() (gas: 81676) +OffRamp_manuallyExecute:test_manuallyExecute_DestinationGasAmountCountMismatch_Revert() (gas: 80532) +OffRamp_manuallyExecute:test_manuallyExecute_DoesNotRevertIfUntouched_Success() (gas: 174130) +OffRamp_manuallyExecute:test_manuallyExecute_FailedTx_Revert() (gas: 215543) +OffRamp_manuallyExecute:test_manuallyExecute_ForkedChain_Revert() (gas: 27365) +OffRamp_manuallyExecute:test_manuallyExecute_GasLimitMismatchMultipleReports_Revert() (gas: 165597) +OffRamp_manuallyExecute:test_manuallyExecute_InvalidReceiverExecutionGasLimit_Revert() (gas: 27936) +OffRamp_manuallyExecute:test_manuallyExecute_InvalidTokenGasOverride_Revert() (gas: 59666) +OffRamp_manuallyExecute:test_manuallyExecute_LowGasLimit_Success() (gas: 534293) +OffRamp_manuallyExecute:test_manuallyExecute_MultipleReportsWithSingleCursedLane_Revert() (gas: 321217) +OffRamp_manuallyExecute:test_manuallyExecute_ReentrancyFails_Success() (gas: 2393253) +OffRamp_manuallyExecute:test_manuallyExecute_SourceChainSelectorMismatch_Revert() (gas: 166568) +OffRamp_manuallyExecute:test_manuallyExecute_Success() (gas: 228525) +OffRamp_manuallyExecute:test_manuallyExecute_WithGasOverride_Success() (gas: 229065) +OffRamp_manuallyExecute:test_manuallyExecute_WithMultiReportGasOverride_Success() (gas: 788283) +OffRamp_manuallyExecute:test_manuallyExecute_WithPartialMessages_Success() (gas: 350237) +OffRamp_releaseOrMintSingleToken:test__releaseOrMintSingleToken_NotACompatiblePool_Revert() (gas: 40611) +OffRamp_releaseOrMintSingleToken:test__releaseOrMintSingleToken_Success() (gas: 105733) +OffRamp_releaseOrMintSingleToken:test__releaseOrMintSingleToken_TokenHandlingError_transfer_Revert() (gas: 86956) +OffRamp_releaseOrMintSingleToken:test_releaseOrMintToken_InvalidDataLength_Revert() (gas: 38380) +OffRamp_releaseOrMintSingleToken:test_releaseOrMintToken_ReleaseOrMintBalanceMismatch_Revert() (gas: 95983) +OffRamp_releaseOrMintSingleToken:test_releaseOrMintToken_TokenHandlingError_BalanceOf_Revert() (gas: 41378) +OffRamp_releaseOrMintSingleToken:test_releaseOrMintToken_skip_ReleaseOrMintBalanceMismatch_if_pool_Revert() (gas: 88177) +OffRamp_releaseOrMintTokens:test_TokenHandlingError_Reverts() (gas: 165433) +OffRamp_releaseOrMintTokens:test__releaseOrMintTokens_PoolIsNotAPool_Reverts() (gas: 25404) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_InvalidDataLengthReturnData_Revert() (gas: 65574) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_InvalidEVMAddress_Revert() (gas: 42279) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_PoolDoesNotSupportDest_Reverts() (gas: 82668) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_Success() (gas: 177447) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_WithGasOverride_Success() (gas: 179427) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals_Success() (gas: 190636) +OffRamp_setDynamicConfig:test_FeeQuoterZeroAddress_Revert() (gas: 11201) +OffRamp_setDynamicConfig:test_NonOwner_Revert() (gas: 13811) +OffRamp_setDynamicConfig:test_SetDynamicConfigWithValidator_Success() (gas: 46216) +OffRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 24191) +OffRamp_trialExecute:test_RateLimitError_Success() (gas: 226586) +OffRamp_trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 235208) +OffRamp_trialExecute:test_TokenPoolIsNotAContract_Success() (gas: 314371) +OffRamp_trialExecute:test_trialExecute_Success() (gas: 284928) +OnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 388215) +OnRamp_applyAllowListUpdates:test_applyAllowListUpdates_InvalidAllowListRequestDisabledAllowListWithAdds() (gas: 17758) +OnRamp_applyAllowListUpdates:test_applyAllowListUpdates_Revert() (gas: 66553) +OnRamp_applyAllowListUpdates:test_applyAllowListUpdates_Success() (gas: 323605) OnRamp_applyDestChainConfigUpdates:test_ApplyDestChainConfigUpdates_Success() (gas: 64546) OnRamp_applyDestChainConfigUpdates:test_ApplyDestChainConfigUpdates_WithInvalidChainSelector_Revert() (gas: 13254) -OnRamp_constructor:test_Constructor_InvalidConfigChainSelectorEqZero_Revert() (gas: 94831) -OnRamp_constructor:test_Constructor_InvalidConfigNonceManagerEqAddressZero_Revert() (gas: 92765) -OnRamp_constructor:test_Constructor_InvalidConfigRMNProxyEqAddressZero_Revert() (gas: 97791) -OnRamp_constructor:test_Constructor_InvalidConfigTokenAdminRegistryEqAddressZero_Revert() (gas: 92823) -OnRamp_constructor:test_Constructor_Success() (gas: 2827622) +OnRamp_constructor:test_Constructor_InvalidConfigChainSelectorEqZero_Revert() (gas: 94823) +OnRamp_constructor:test_Constructor_InvalidConfigNonceManagerEqAddressZero_Revert() (gas: 92757) +OnRamp_constructor:test_Constructor_InvalidConfigRMNProxyEqAddressZero_Revert() (gas: 97783) +OnRamp_constructor:test_Constructor_InvalidConfigTokenAdminRegistryEqAddressZero_Revert() (gas: 92815) +OnRamp_constructor:test_Constructor_Success() (gas: 2817599) OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() (gas: 114939) OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2_Success() (gas: 145710) OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessCustomExtraArgs() (gas: 145313) OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessEmptyExtraArgs() (gas: 143538) OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessLegacyExtraArgs() (gas: 145538) OnRamp_forwardFromRouter:test_ForwardFromRouter_Success() (gas: 144917) -OnRamp_forwardFromRouter:test_ForwardFromRouter_Success_ConfigurableSourceRouter() (gas: 140243) +OnRamp_forwardFromRouter:test_ForwardFromRouter_Success_ConfigurableSourceRouter() (gas: 140249) OnRamp_forwardFromRouter:test_InvalidExtraArgsTag_Revert() (gas: 28824) -OnRamp_forwardFromRouter:test_MessageValidationError_Revert() (gas: 138926) +OnRamp_forwardFromRouter:test_MessageValidationError_Revert() (gas: 138938) OnRamp_forwardFromRouter:test_MesssageFeeTooHigh_Revert() (gas: 26924) OnRamp_forwardFromRouter:test_MultiCannotSendZeroTokens_Revert() (gas: 74139) OnRamp_forwardFromRouter:test_OriginalSender_Revert() (gas: 12951) -OnRamp_forwardFromRouter:test_Paused_Revert() (gas: 37326) -OnRamp_forwardFromRouter:test_Permissions_Revert() (gas: 18278) +OnRamp_forwardFromRouter:test_Paused_Revert() (gas: 37338) +OnRamp_forwardFromRouter:test_Permissions_Revert() (gas: 18284) OnRamp_forwardFromRouter:test_ShouldIncrementNonceOnlyOnOrdered_Success() (gas: 184562) OnRamp_forwardFromRouter:test_ShouldIncrementSeqNumAndNonce_Success() (gas: 210880) OnRamp_forwardFromRouter:test_ShouldStoreLinkFees() (gas: 124838) OnRamp_forwardFromRouter:test_ShouldStoreNonLinkFees() (gas: 141462) -OnRamp_forwardFromRouter:test_SourceTokenDataTooLarge_Revert() (gas: 3829289) +OnRamp_forwardFromRouter:test_SourceTokenDataTooLarge_Revert() (gas: 3769244) OnRamp_forwardFromRouter:test_UnAllowedOriginalSender_Revert() (gas: 18714) -OnRamp_forwardFromRouter:test_UnsupportedToken_Revert() (gas: 110907) -OnRamp_forwardFromRouter:test_forwardFromRouter_UnsupportedToken_Revert() (gas: 76229) -OnRamp_forwardFromRouter:test_forwardFromRouter_WithValidation_Success() (gas: 281171) -OnRamp_getFee:test_EmptyMessage_Success() (gas: 97722) -OnRamp_getFee:test_EnforceOutOfOrder_Revert() (gas: 64203) -OnRamp_getFee:test_GetFeeOfZeroForTokenMessage_Success() (gas: 85422) -OnRamp_getFee:test_NotAFeeTokenButPricedToken_Revert() (gas: 34972) -OnRamp_getFee:test_SingleTokenMessage_Success() (gas: 112713) -OnRamp_getFee:test_Unhealthy_Revert() (gas: 17009) +OnRamp_forwardFromRouter:test_UnsupportedToken_Revert() (gas: 110919) +OnRamp_forwardFromRouter:test_forwardFromRouter_UnsupportedToken_Revert() (gas: 76235) +OnRamp_forwardFromRouter:test_forwardFromRouter_WithValidation_Success() (gas: 281240) +OnRamp_getFee:test_EmptyMessage_Success() (gas: 97734) +OnRamp_getFee:test_EnforceOutOfOrder_Revert() (gas: 64215) +OnRamp_getFee:test_GetFeeOfZeroForTokenMessage_Success() (gas: 85428) +OnRamp_getFee:test_NotAFeeTokenButPricedToken_Revert() (gas: 34978) +OnRamp_getFee:test_SingleTokenMessage_Success() (gas: 112749) +OnRamp_getFee:test_Unhealthy_Revert() (gas: 17021) OnRamp_getSupportedTokens:test_GetSupportedTokens_Revert() (gas: 10438) OnRamp_getTokenPool:test_GetTokenPool_Success() (gas: 35204) OnRamp_setDynamicConfig:test_SetConfigInvalidConfigFeeAggregatorEqAddressZero_Revert() (gas: 11420) OnRamp_setDynamicConfig:test_SetConfigInvalidConfigFeeQuoterEqAddressZero_Revert() (gas: 13019) OnRamp_setDynamicConfig:test_SetConfigInvalidConfig_Revert() (gas: 11377) -OnRamp_setDynamicConfig:test_SetConfigOnlyOwner_Revert() (gas: 16409) +OnRamp_setDynamicConfig:test_SetConfigOnlyOwner_Revert() (gas: 16421) OnRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 55330) OnRamp_withdrawFeeTokens:test_WithdrawFeeTokens_Success() (gas: 97235) -PingPong_ccipReceive:test_CcipReceive_Success() (gas: 150578) -PingPong_plumbing:test_OutOfOrderExecution_Success() (gas: 20280) -PingPong_plumbing:test_Pausing_Success() (gas: 17780) -PingPong_startPingPong:test_StartPingPong_With_OOO_Success() (gas: 160987) -PingPong_startPingPong:test_StartPingPong_With_Sequenced_Ordered_Success() (gas: 180396) +PingPong_ccipReceive:test_CcipReceive_Success() (gas: 150719) +PingPong_plumbing:test_OutOfOrderExecution_Success() (gas: 20286) +PingPong_plumbing:test_Pausing_Success() (gas: 17786) +PingPong_startPingPong:test_StartPingPong_With_OOO_Success() (gas: 161185) +PingPong_startPingPong:test_StartPingPong_With_Sequenced_Ordered_Success() (gas: 180603) RMNHome:test() (gas: 186) RMN_constructor:test_Constructor_Success() (gas: 48874) -RMN_getRecordedCurseRelatedOps:test_OpsPostDeployment() (gas: 19690) -RMN_lazyVoteToCurseUpdate_Benchmark:test_VoteToCurseLazilyRetain3VotersUponConfigChange_gas() (gas: 152263) -RMN_ownerUnbless:test_Unbless_Success() (gas: 74882) -RMN_ownerUnvoteToCurse:test_CanBlessAndCurseAfterGlobalCurseIsLifted() (gas: 471457) -RMN_ownerUnvoteToCurse:test_IsIdempotent() (gas: 398096) +RMN_getRecordedCurseRelatedOps:test_OpsPostDeployment() (gas: 19696) +RMN_lazyVoteToCurseUpdate_Benchmark:test_VoteToCurseLazilyRetain3VotersUponConfigChange_gas() (gas: 152287) +RMN_ownerUnbless:test_Unbless_Success() (gas: 74900) +RMN_ownerUnvoteToCurse:test_CanBlessAndCurseAfterGlobalCurseIsLifted() (gas: 471574) +RMN_ownerUnvoteToCurse:test_IsIdempotent() (gas: 398222) RMN_ownerUnvoteToCurse:test_NonOwner_Revert() (gas: 18669) -RMN_ownerUnvoteToCurse:test_OwnerUnvoteToCurseSuccess_gas() (gas: 357751) -RMN_ownerUnvoteToCurse:test_UnknownVoter_Revert() (gas: 33034) -RMN_ownerUnvoteToCurse_Benchmark:test_OwnerUnvoteToCurse_1Voter_LiftsCurse_gas() (gas: 262211) +RMN_ownerUnvoteToCurse:test_OwnerUnvoteToCurseSuccess_gas() (gas: 357841) +RMN_ownerUnvoteToCurse:test_UnknownVoter_Revert() (gas: 33058) +RMN_ownerUnvoteToCurse_Benchmark:test_OwnerUnvoteToCurse_1Voter_LiftsCurse_gas() (gas: 262247) RMN_permaBlessing:test_PermaBlessing() (gas: 202691) RMN_setConfig:test_BlessVoterIsZeroAddress_Revert() (gas: 15494) RMN_setConfig:test_EitherThresholdIsZero_Revert() (gas: 21095) -RMN_setConfig:test_NonOwner_Revert() (gas: 14719) +RMN_setConfig:test_NonOwner_Revert() (gas: 14725) RMN_setConfig:test_RepeatedAddress_Revert() (gas: 18213) -RMN_setConfig:test_SetConfigSuccess_gas() (gas: 104080) +RMN_setConfig:test_SetConfigSuccess_gas() (gas: 104089) RMN_setConfig:test_TotalWeightsSmallerThanEachThreshold_Revert() (gas: 30173) -RMN_setConfig:test_VoteToBlessByEjectedVoter_Revert() (gas: 130363) +RMN_setConfig:test_VoteToBlessByEjectedVoter_Revert() (gas: 130377) RMN_setConfig:test_VotersLengthIsZero_Revert() (gas: 12128) RMN_setConfig:test_WeightIsZeroAddress_Revert() (gas: 15734) -RMN_setConfig_Benchmark_1:test_SetConfig_7Voters_gas() (gas: 659462) -RMN_setConfig_Benchmark_2:test_ResetConfig_7Voters_gas() (gas: 212484) -RMN_unvoteToCurse:test_InvalidCursesHash() (gas: 26412) -RMN_unvoteToCurse:test_OwnerSkips() (gas: 33813) -RMN_unvoteToCurse:test_OwnerSucceeds() (gas: 63981) -RMN_unvoteToCurse:test_UnauthorizedVoter() (gas: 47598) -RMN_unvoteToCurse:test_ValidCursesHash() (gas: 61127) -RMN_unvoteToCurse:test_VotersCantLiftCurseButOwnerCan() (gas: 628641) -RMN_voteToBless:test_Curse_Revert() (gas: 473252) -RMN_voteToBless:test_IsAlreadyBlessed_Revert() (gas: 115312) -RMN_voteToBless:test_RootSuccess() (gas: 558319) -RMN_voteToBless:test_SenderAlreadyVoted_Revert() (gas: 97177) +RMN_setConfig_Benchmark_1:test_SetConfig_7Voters_gas() (gas: 659495) +RMN_setConfig_Benchmark_2:test_ResetConfig_7Voters_gas() (gas: 212511) +RMN_unvoteToCurse:test_InvalidCursesHash() (gas: 26430) +RMN_unvoteToCurse:test_OwnerSkips() (gas: 33831) +RMN_unvoteToCurse:test_OwnerSucceeds() (gas: 63999) +RMN_unvoteToCurse:test_UnauthorizedVoter() (gas: 47634) +RMN_unvoteToCurse:test_ValidCursesHash() (gas: 61139) +RMN_unvoteToCurse:test_VotersCantLiftCurseButOwnerCan() (gas: 628827) +RMN_voteToBless:test_Curse_Revert() (gas: 473342) +RMN_voteToBless:test_IsAlreadyBlessed_Revert() (gas: 115339) +RMN_voteToBless:test_RootSuccess() (gas: 558469) +RMN_voteToBless:test_SenderAlreadyVoted_Revert() (gas: 97204) RMN_voteToBless:test_UnauthorizedVoter_Revert() (gas: 17096) -RMN_voteToBless_Benchmark:test_1RootSuccess_gas() (gas: 44703) -RMN_voteToBless_Benchmark:test_3RootSuccess_gas() (gas: 98673) -RMN_voteToBless_Benchmark:test_5RootSuccess_gas() (gas: 152581) -RMN_voteToBless_Blessed_Benchmark:test_1RootSuccessBecameBlessed_gas() (gas: 29673) -RMN_voteToBless_Blessed_Benchmark:test_1RootSuccess_gas() (gas: 27619) -RMN_voteToBless_Blessed_Benchmark:test_3RootSuccess_gas() (gas: 81611) -RMN_voteToBless_Blessed_Benchmark:test_5RootSuccess_gas() (gas: 135497) -RMN_voteToCurse:test_CurseOnlyWhenThresholdReached_Success() (gas: 1650405) -RMN_voteToCurse:test_EmptySubjects_Revert() (gas: 14031) -RMN_voteToCurse:test_EvenIfAlreadyCursed_Success() (gas: 534854) -RMN_voteToCurse:test_OwnerCanCurseAndUncurse() (gas: 399532) -RMN_voteToCurse:test_RepeatedSubject_Revert() (gas: 144336) -RMN_voteToCurse:test_ReusedCurseId_Revert() (gas: 146885) -RMN_voteToCurse:test_UnauthorizedVoter_Revert() (gas: 12630) -RMN_voteToCurse:test_VoteToCurse_NoCurse_Success() (gas: 187388) -RMN_voteToCurse:test_VoteToCurse_YesCurse_Success() (gas: 472854) -RMN_voteToCurse_2:test_VotesAreDroppedIfSubjectIsNotCursedDuringConfigChange() (gas: 370837) -RMN_voteToCurse_2:test_VotesAreRetainedIfSubjectIsCursedDuringConfigChange() (gas: 1153282) -RMN_voteToCurse_Benchmark_1:test_VoteToCurse_NewSubject_NewVoter_NoCurse_gas() (gas: 141079) -RMN_voteToCurse_Benchmark_1:test_VoteToCurse_NewSubject_NewVoter_YesCurse_gas() (gas: 165213) -RMN_voteToCurse_Benchmark_2:test_VoteToCurse_OldSubject_NewVoter_NoCurse_gas() (gas: 121413) -RMN_voteToCurse_Benchmark_2:test_VoteToCurse_OldSubject_OldVoter_NoCurse_gas() (gas: 98355) -RMN_voteToCurse_Benchmark_3:test_VoteToCurse_OldSubject_NewVoter_YesCurse_gas() (gas: 145748) +RMN_voteToBless_Benchmark:test_1RootSuccess_gas() (gas: 44706) +RMN_voteToBless_Benchmark:test_3RootSuccess_gas() (gas: 98682) +RMN_voteToBless_Benchmark:test_5RootSuccess_gas() (gas: 152596) +RMN_voteToBless_Blessed_Benchmark:test_1RootSuccessBecameBlessed_gas() (gas: 29676) +RMN_voteToBless_Blessed_Benchmark:test_1RootSuccess_gas() (gas: 27622) +RMN_voteToBless_Blessed_Benchmark:test_3RootSuccess_gas() (gas: 81620) +RMN_voteToBless_Blessed_Benchmark:test_5RootSuccess_gas() (gas: 135512) +RMN_voteToCurse:test_CurseOnlyWhenThresholdReached_Success() (gas: 1651029) +RMN_voteToCurse:test_EmptySubjects_Revert() (gas: 14055) +RMN_voteToCurse:test_EvenIfAlreadyCursed_Success() (gas: 535106) +RMN_voteToCurse:test_OwnerCanCurseAndUncurse() (gas: 399724) +RMN_voteToCurse:test_RepeatedSubject_Revert() (gas: 144396) +RMN_voteToCurse:test_ReusedCurseId_Revert() (gas: 146963) +RMN_voteToCurse:test_UnauthorizedVoter_Revert() (gas: 12660) +RMN_voteToCurse:test_VoteToCurse_NoCurse_Success() (gas: 187466) +RMN_voteToCurse:test_VoteToCurse_YesCurse_Success() (gas: 473034) +RMN_voteToCurse_2:test_VotesAreDroppedIfSubjectIsNotCursedDuringConfigChange() (gas: 370924) +RMN_voteToCurse_2:test_VotesAreRetainedIfSubjectIsCursedDuringConfigChange() (gas: 1153719) +RMN_voteToCurse_Benchmark_1:test_VoteToCurse_NewSubject_NewVoter_NoCurse_gas() (gas: 141103) +RMN_voteToCurse_Benchmark_1:test_VoteToCurse_NewSubject_NewVoter_YesCurse_gas() (gas: 165243) +RMN_voteToCurse_Benchmark_2:test_VoteToCurse_OldSubject_NewVoter_NoCurse_gas() (gas: 121431) +RMN_voteToCurse_Benchmark_2:test_VoteToCurse_OldSubject_OldVoter_NoCurse_gas() (gas: 98367) +RMN_voteToCurse_Benchmark_3:test_VoteToCurse_OldSubject_NewVoter_YesCurse_gas() (gas: 145778) RateLimiter_constructor:test_Constructor_Success() (gas: 19704) -RateLimiter_consume:test_AggregateValueMaxCapacityExceeded_Revert() (gas: 16006) +RateLimiter_consume:test_AggregateValueMaxCapacityExceeded_Revert() (gas: 16012) RateLimiter_consume:test_AggregateValueRateLimitReached_Revert() (gas: 22345) RateLimiter_consume:test_ConsumeAggregateValue_Success() (gas: 31443) RateLimiter_consume:test_ConsumeTokens_Success() (gas: 20366) -RateLimiter_consume:test_ConsumeUnlimited_Success() (gas: 40573) -RateLimiter_consume:test_ConsumingMoreThanUint128_Revert() (gas: 15786) +RateLimiter_consume:test_ConsumeUnlimited_Success() (gas: 40585) +RateLimiter_consume:test_ConsumingMoreThanUint128_Revert() (gas: 15792) RateLimiter_consume:test_RateLimitReachedOverConsecutiveBlocks_Revert() (gas: 25747) RateLimiter_consume:test_Refill_Success() (gas: 37354) RateLimiter_consume:test_TokenMaxCapacityExceeded_Revert() (gas: 18340) RateLimiter_consume:test_TokenRateLimitReached_Revert() (gas: 24823) -RateLimiter_currentTokenBucketState:test_CurrentTokenBucketState_Success() (gas: 38875) -RateLimiter_currentTokenBucketState:test_Refill_Success() (gas: 46768) -RateLimiter_setTokenBucketConfig:test_SetRateLimiterConfig_Success() (gas: 38446) +RateLimiter_currentTokenBucketState:test_CurrentTokenBucketState_Success() (gas: 38884) +RateLimiter_currentTokenBucketState:test_Refill_Success() (gas: 46777) +RateLimiter_setTokenBucketConfig:test_SetRateLimiterConfig_Success() (gas: 38449) RegistryModuleOwnerCustom_constructor:test_constructor_Revert() (gas: 36037) -RegistryModuleOwnerCustom_registerAdminViaGetCCIPAdmin:test_registerAdminViaGetCCIPAdmin_Revert() (gas: 19643) -RegistryModuleOwnerCustom_registerAdminViaGetCCIPAdmin:test_registerAdminViaGetCCIPAdmin_Success() (gas: 129930) -RegistryModuleOwnerCustom_registerAdminViaOwner:test_registerAdminViaOwner_Revert() (gas: 19457) -RegistryModuleOwnerCustom_registerAdminViaOwner:test_registerAdminViaOwner_Success() (gas: 129743) -Router_applyRampUpdates:test_OffRampMismatch_Revert() (gas: 89306) -Router_applyRampUpdates:test_OffRampUpdatesWithRouting() (gas: 10648972) +RegistryModuleOwnerCustom_registerAdminViaGetCCIPAdmin:test_registerAdminViaGetCCIPAdmin_Revert() (gas: 19655) +RegistryModuleOwnerCustom_registerAdminViaGetCCIPAdmin:test_registerAdminViaGetCCIPAdmin_Success() (gas: 129978) +RegistryModuleOwnerCustom_registerAdminViaOwner:test_registerAdminViaOwner_Revert() (gas: 19475) +RegistryModuleOwnerCustom_registerAdminViaOwner:test_registerAdminViaOwner_Success() (gas: 129797) +Router_applyRampUpdates:test_OffRampMismatch_Revert() (gas: 89321) +Router_applyRampUpdates:test_OffRampUpdatesWithRouting() (gas: 10652272) Router_applyRampUpdates:test_OnRampDisable() (gas: 55971) Router_applyRampUpdates:test_OnlyOwner_Revert() (gas: 12317) -Router_ccipSend:test_CCIPSendLinkFeeNoTokenSuccess_gas() (gas: 113852) -Router_ccipSend:test_CCIPSendLinkFeeOneTokenSuccess_gas() (gas: 201347) -Router_ccipSend:test_CCIPSendNativeFeeNoTokenSuccess_gas() (gas: 126206) -Router_ccipSend:test_CCIPSendNativeFeeOneTokenSuccess_gas() (gas: 213703) -Router_ccipSend:test_FeeTokenAmountTooLow_Revert() (gas: 64181) -Router_ccipSend:test_InvalidMsgValue() (gas: 32008) -Router_ccipSend:test_NativeFeeTokenInsufficientValue() (gas: 66640) -Router_ccipSend:test_NativeFeeTokenOverpay_Success() (gas: 169155) -Router_ccipSend:test_NativeFeeTokenZeroValue() (gas: 53922) -Router_ccipSend:test_NativeFeeToken_Success() (gas: 167749) -Router_ccipSend:test_NonLinkFeeToken_Success() (gas: 238276) -Router_ccipSend:test_UnsupportedDestinationChain_Revert() (gas: 24761) -Router_ccipSend:test_WhenNotHealthy_Revert() (gas: 44736) -Router_ccipSend:test_WrappedNativeFeeToken_Success() (gas: 170007) -Router_ccipSend:test_ZeroFeeAndGasPrice_Success() (gas: 240298) +Router_ccipSend:test_CCIPSendLinkFeeNoTokenSuccess_gas() (gas: 114017) +Router_ccipSend:test_CCIPSendLinkFeeOneTokenSuccess_gas() (gas: 201533) +Router_ccipSend:test_CCIPSendNativeFeeNoTokenSuccess_gas() (gas: 126386) +Router_ccipSend:test_CCIPSendNativeFeeOneTokenSuccess_gas() (gas: 213904) +Router_ccipSend:test_FeeTokenAmountTooLow_Revert() (gas: 64241) +Router_ccipSend:test_InvalidMsgValue() (gas: 32014) +Router_ccipSend:test_NativeFeeTokenInsufficientValue() (gas: 66706) +Router_ccipSend:test_NativeFeeTokenOverpay_Success() (gas: 169401) +Router_ccipSend:test_NativeFeeTokenZeroValue() (gas: 53982) +Router_ccipSend:test_NativeFeeToken_Success() (gas: 167995) +Router_ccipSend:test_NonLinkFeeToken_Success() (gas: 238462) +Router_ccipSend:test_UnsupportedDestinationChain_Revert() (gas: 24767) +Router_ccipSend:test_WhenNotHealthy_Revert() (gas: 44742) +Router_ccipSend:test_WrappedNativeFeeToken_Success() (gas: 170253) +Router_ccipSend:test_ZeroFeeAndGasPrice_Success() (gas: 240550) Router_constructor:test_Constructor_Success() (gas: 13070) Router_getArmProxy:test_getArmProxy() (gas: 10561) -Router_getFee:test_GetFeeSupportedChain_Success() (gas: 44349) -Router_getFee:test_UnsupportedDestinationChain_Revert() (gas: 17144) +Router_getFee:test_GetFeeSupportedChain_Success() (gas: 44415) +Router_getFee:test_UnsupportedDestinationChain_Revert() (gas: 17156) Router_getSupportedTokens:test_GetSupportedTokens_Revert() (gas: 10460) -Router_recoverTokens:test_RecoverTokensInvalidRecipient_Revert() (gas: 11316) +Router_recoverTokens:test_RecoverTokensInvalidRecipient_Revert() (gas: 11322) Router_recoverTokens:test_RecoverTokensNoFunds_Revert() (gas: 20261) -Router_recoverTokens:test_RecoverTokensNonOwner_Revert() (gas: 11159) -Router_recoverTokens:test_RecoverTokensValueReceiver_Revert() (gas: 402507) -Router_recoverTokens:test_RecoverTokens_Success() (gas: 52437) +Router_recoverTokens:test_RecoverTokensNonOwner_Revert() (gas: 11171) +Router_recoverTokens:test_RecoverTokensValueReceiver_Revert() (gas: 392489) +Router_recoverTokens:test_RecoverTokens_Success() (gas: 52442) Router_routeMessage:test_AutoExec_Success() (gas: 42738) Router_routeMessage:test_ExecutionEvent_Success() (gas: 158166) Router_routeMessage:test_ManualExec_Success() (gas: 35429) -Router_routeMessage:test_OnlyOffRamp_Revert() (gas: 25140) -Router_routeMessage:test_WhenNotHealthy_Revert() (gas: 44742) -Router_setWrappedNative:test_OnlyOwner_Revert() (gas: 10986) -SelfFundedPingPong_ccipReceive:test_FundingIfNotANop_Revert() (gas: 55572) -SelfFundedPingPong_ccipReceive:test_Funding_Success() (gas: 417040) +Router_routeMessage:test_OnlyOffRamp_Revert() (gas: 25146) +Router_routeMessage:test_WhenNotHealthy_Revert() (gas: 44754) +Router_setWrappedNative:test_OnlyOwner_Revert() (gas: 10992) +SelfFundedPingPong_ccipReceive:test_FundingIfNotANop_Revert() (gas: 55596) +SelfFundedPingPong_ccipReceive:test_Funding_Success() (gas: 417712) SelfFundedPingPong_setCountIncrBeforeFunding:test_setCountIncrBeforeFunding() (gas: 20169) -TokenAdminRegistry_acceptAdminRole:test_acceptAdminRole_OnlyPendingAdministrator_Revert() (gas: 51109) -TokenAdminRegistry_acceptAdminRole:test_acceptAdminRole_Success() (gas: 43956) +TokenAdminRegistry_acceptAdminRole:test_acceptAdminRole_OnlyPendingAdministrator_Revert() (gas: 51115) +TokenAdminRegistry_acceptAdminRole:test_acceptAdminRole_Success() (gas: 43961) TokenAdminRegistry_addRegistryModule:test_addRegistryModule_OnlyOwner_Revert() (gas: 12641) TokenAdminRegistry_addRegistryModule:test_addRegistryModule_Success() (gas: 67038) -TokenAdminRegistry_getAllConfiguredTokens:test_getAllConfiguredTokens_outOfBounds_Success() (gas: 11350) +TokenAdminRegistry_getAllConfiguredTokens:test_getAllConfiguredTokens_outOfBounds_Success() (gas: 11356) TokenAdminRegistry_getPool:test_getPool_Success() (gas: 17596) TokenAdminRegistry_getPools:test_getPools_Success() (gas: 39920) -TokenAdminRegistry_isAdministrator:test_isAdministrator_Success() (gas: 105946) +TokenAdminRegistry_isAdministrator:test_isAdministrator_Success() (gas: 105952) TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_AlreadyRegistered_Revert() (gas: 104067) TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_OnlyRegistryModule_Revert() (gas: 15499) TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_ZeroAddress_Revert() (gas: 15044) -TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_module_Success() (gas: 112572) -TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_owner_Success() (gas: 107686) -TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_reRegisterWhileUnclaimed_Success() (gas: 115710) +TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_module_Success() (gas: 112578) +TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_owner_Success() (gas: 107692) +TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_reRegisterWhileUnclaimed_Success() (gas: 115716) TokenAdminRegistry_removeRegistryModule:test_removeRegistryModule_OnlyOwner_Revert() (gas: 12597) -TokenAdminRegistry_removeRegistryModule:test_removeRegistryModule_Success() (gas: 54495) +TokenAdminRegistry_removeRegistryModule:test_removeRegistryModule_Success() (gas: 54509) TokenAdminRegistry_setPool:test_setPool_InvalidTokenPoolToken_Revert() (gas: 19166) -TokenAdminRegistry_setPool:test_setPool_OnlyAdministrator_Revert() (gas: 18026) +TokenAdminRegistry_setPool:test_setPool_OnlyAdministrator_Revert() (gas: 18032) TokenAdminRegistry_setPool:test_setPool_Success() (gas: 35961) TokenAdminRegistry_setPool:test_setPool_ZeroAddressRemovesPool_Success() (gas: 30635) -TokenAdminRegistry_transferAdminRole:test_transferAdminRole_OnlyAdministrator_Revert() (gas: 18085) -TokenAdminRegistry_transferAdminRole:test_transferAdminRole_Success() (gas: 49390) -TokenPoolAndProxy:test_lockOrBurn_burnMint_Success() (gas: 5945631) -TokenPoolAndProxy:test_lockOrBurn_burnWithFromMint_Success() (gas: 5977107) -TokenPoolAndProxy:test_lockOrBurn_lockRelease_Success() (gas: 6179838) -TokenPoolAndProxy:test_setPreviousPool_Success() (gas: 3334200) -TokenPoolAndProxyMigration:test_tokenPoolMigration_Success_1_2() (gas: 6789707) -TokenPoolAndProxyMigration:test_tokenPoolMigration_Success_1_4() (gas: 7022389) -TokenPoolWithAllowList_applyAllowListUpdates:test_AllowListNotEnabled_Revert() (gas: 2100002) +TokenAdminRegistry_transferAdminRole:test_transferAdminRole_OnlyAdministrator_Revert() (gas: 18091) +TokenAdminRegistry_transferAdminRole:test_transferAdminRole_Success() (gas: 49402) +TokenPoolAndProxy:test_lockOrBurn_burnMint_Success() (gas: 5855541) +TokenPoolAndProxy:test_lockOrBurn_burnWithFromMint_Success() (gas: 5887014) +TokenPoolAndProxy:test_lockOrBurn_lockRelease_Success() (gas: 6040093) +TokenPoolAndProxy:test_setPreviousPool_Success() (gas: 3214305) +TokenPoolAndProxyMigration:test_tokenPoolMigration_Success_1_2() (gas: 6699954) +TokenPoolAndProxyMigration:test_tokenPoolMigration_Success_1_4() (gas: 6912610) +TokenPoolWithAllowList_applyAllowListUpdates:test_AllowListNotEnabled_Revert() (gas: 2069936) TokenPoolWithAllowList_applyAllowListUpdates:test_OnlyOwner_Revert() (gas: 12101) TokenPoolWithAllowList_applyAllowListUpdates:test_SetAllowListSkipsZero_Success() (gas: 23464) TokenPoolWithAllowList_applyAllowListUpdates:test_SetAllowList_Success() (gas: 177802) @@ -952,42 +953,42 @@ TokenPoolWithAllowList_setRouter:test_SetRouter_Success() (gas: 24843) TokenPool_applyChainUpdates:test_applyChainUpdates_DisabledNonZeroRateLimit_Revert() (gas: 271551) TokenPool_applyChainUpdates:test_applyChainUpdates_InvalidRateLimitRate_Revert() (gas: 542134) TokenPool_applyChainUpdates:test_applyChainUpdates_NonExistentChain_Revert() (gas: 18449) -TokenPool_applyChainUpdates:test_applyChainUpdates_OnlyCallableByOwner_Revert() (gas: 11391) +TokenPool_applyChainUpdates:test_applyChainUpdates_OnlyCallableByOwner_Revert() (gas: 11397) TokenPool_applyChainUpdates:test_applyChainUpdates_Success() (gas: 477675) -TokenPool_applyChainUpdates:test_applyChainUpdates_ZeroAddressNotAllowed_Revert() (gas: 157320) -TokenPool_constructor:test_ZeroAddressNotAllowed_Revert() (gas: 70594) +TokenPool_applyChainUpdates:test_applyChainUpdates_ZeroAddressNotAllowed_Revert() (gas: 157356) +TokenPool_constructor:test_ZeroAddressNotAllowed_Revert() (gas: 70564) TokenPool_constructor:test_immutableFields_Success() (gas: 20544) -TokenPool_getRemotePool:test_getRemotePool_Success() (gas: 274133) -TokenPool_onlyOffRamp:test_CallerIsNotARampOnRouter_Revert() (gas: 277110) -TokenPool_onlyOffRamp:test_ChainNotAllowed_Revert() (gas: 289682) +TokenPool_getRemotePool:test_getRemotePool_Success() (gas: 274145) +TokenPool_onlyOffRamp:test_CallerIsNotARampOnRouter_Revert() (gas: 277116) +TokenPool_onlyOffRamp:test_ChainNotAllowed_Revert() (gas: 289701) TokenPool_onlyOffRamp:test_onlyOffRamp_Success() (gas: 349912) -TokenPool_onlyOnRamp:test_CallerIsNotARampOnRouter_Revert() (gas: 276850) -TokenPool_onlyOnRamp:test_ChainNotAllowed_Revert() (gas: 253710) +TokenPool_onlyOnRamp:test_CallerIsNotARampOnRouter_Revert() (gas: 276856) +TokenPool_onlyOnRamp:test_ChainNotAllowed_Revert() (gas: 253729) TokenPool_onlyOnRamp:test_onlyOnRamp_Success() (gas: 304962) -TokenPool_setChainRateLimiterConfig:test_NonExistentChain_Revert() (gas: 17142) -TokenPool_setChainRateLimiterConfig:test_OnlyOwnerOrRateLimitAdmin_Revert() (gas: 15137) -TokenPool_setRemotePool:test_setRemotePool_NonExistentChain_Reverts() (gas: 15653) -TokenPool_setRemotePool:test_setRemotePool_OnlyOwner_Reverts() (gas: 13201) -TokenPool_setRemotePool:test_setRemotePool_Success() (gas: 282083) -TokenProxy_ccipSend:test_CcipSendGasShouldBeZero_Revert() (gas: 17121) -TokenProxy_ccipSend:test_CcipSendInsufficientAllowance_Revert() (gas: 134143) +TokenPool_setChainRateLimiterConfig:test_NonExistentChain_Revert() (gas: 17148) +TokenPool_setChainRateLimiterConfig:test_OnlyOwnerOrRateLimitAdmin_Revert() (gas: 15149) +TokenPool_setRemotePool:test_setRemotePool_NonExistentChain_Reverts() (gas: 15665) +TokenPool_setRemotePool:test_setRemotePool_OnlyOwner_Reverts() (gas: 13213) +TokenPool_setRemotePool:test_setRemotePool_Success() (gas: 282095) +TokenProxy_ccipSend:test_CcipSendGasShouldBeZero_Revert() (gas: 17127) +TokenProxy_ccipSend:test_CcipSendInsufficientAllowance_Revert() (gas: 134209) TokenProxy_ccipSend:test_CcipSendInvalidToken_Revert() (gas: 15931) -TokenProxy_ccipSend:test_CcipSendNative_Success() (gas: 242858) +TokenProxy_ccipSend:test_CcipSendNative_Success() (gas: 243059) TokenProxy_ccipSend:test_CcipSendNoDataAllowed_Revert() (gas: 16315) -TokenProxy_ccipSend:test_CcipSend_Success() (gas: 261460) +TokenProxy_ccipSend:test_CcipSend_Success() (gas: 261662) TokenProxy_constructor:test_Constructor() (gas: 13812) -TokenProxy_getFee:test_GetFeeGasShouldBeZero_Revert() (gas: 16839) +TokenProxy_getFee:test_GetFeeGasShouldBeZero_Revert() (gas: 16845) TokenProxy_getFee:test_GetFeeInvalidToken_Revert() (gas: 12670) TokenProxy_getFee:test_GetFeeNoDataAllowed_Revert() (gas: 15864) -TokenProxy_getFee:test_GetFee_Success() (gas: 84508) +TokenProxy_getFee:test_GetFee_Success() (gas: 84634) USDCTokenPool__validateMessage:test_ValidateInvalidMessage_Revert() (gas: 25407) -USDCTokenPool_lockOrBurn:test_CallerIsNotARampOnRouter_Revert() (gas: 35364) -USDCTokenPool_lockOrBurn:test_LockOrBurnWithAllowList_Revert() (gas: 30106) -USDCTokenPool_lockOrBurn:test_LockOrBurn_Success() (gas: 133143) -USDCTokenPool_lockOrBurn:test_UnknownDomain_Revert() (gas: 477468) -USDCTokenPool_releaseOrMint:test_ReleaseOrMintRealTx_Success() (gas: 268219) -USDCTokenPool_releaseOrMint:test_TokenMaxCapacityExceeded_Revert() (gas: 50718) -USDCTokenPool_releaseOrMint:test_UnlockingUSDCFailed_Revert() (gas: 98636) -USDCTokenPool_setDomains:test_InvalidDomain_Revert() (gas: 66174) -USDCTokenPool_setDomains:test_OnlyOwner_Revert() (gas: 11339) -USDCTokenPool_supportsInterface:test_SupportsInterface_Success() (gas: 9876) \ No newline at end of file +USDCTokenPool_lockOrBurn:test_CallerIsNotARampOnRouter_Revert() (gas: 35376) +USDCTokenPool_lockOrBurn:test_LockOrBurnWithAllowList_Revert() (gas: 30112) +USDCTokenPool_lockOrBurn:test_LockOrBurn_Success() (gas: 133148) +USDCTokenPool_lockOrBurn:test_UnknownDomain_Revert() (gas: 477486) +USDCTokenPool_releaseOrMint:test_ReleaseOrMintRealTx_Success() (gas: 268238) +USDCTokenPool_releaseOrMint:test_TokenMaxCapacityExceeded_Revert() (gas: 50724) +USDCTokenPool_releaseOrMint:test_UnlockingUSDCFailed_Revert() (gas: 98642) +USDCTokenPool_setDomains:test_InvalidDomain_Revert() (gas: 66189) +USDCTokenPool_setDomains:test_OnlyOwner_Revert() (gas: 11345) +USDCTokenPool_supportsInterface:test_SupportsInterface_Success() (gas: 9888) \ No newline at end of file diff --git a/contracts/src/v0.8/ccip/offRamp/OffRamp.sol b/contracts/src/v0.8/ccip/offRamp/OffRamp.sol index 6399244605..2bb89e3c33 100644 --- a/contracts/src/v0.8/ccip/offRamp/OffRamp.sol +++ b/contracts/src/v0.8/ccip/offRamp/OffRamp.sol @@ -57,13 +57,14 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { error NotACompatiblePool(address notPool); error InvalidDataLength(uint256 expected, uint256 got); error InvalidNewState(uint64 sourceChainSelector, uint64 sequenceNumber, Internal.MessageExecutionState newState); - error InvalidStaticConfig(uint64 sourceChainSelector); error StaleCommitReport(); error InvalidInterval(uint64 sourceChainSelector, uint64 min, uint64 max); error ZeroAddressNotAllowed(); error InvalidMessageDestChainSelector(uint64 messageDestChainSelector); error SourceChainSelectorMismatch(uint64 reportSourceChainSelector, uint64 messageSourceChainSelector); error SignatureVerificationDisabled(); + error CommitOnRampMismatch(bytes reportOnRamp, bytes configOnRamp); + error InvalidOnRampUpdate(uint64 sourceChainSelector); /// @dev Atlas depends on this event, if changing, please notify Atlas. event StaticConfigSet(StaticConfig staticConfig); @@ -140,6 +141,8 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { // STATIC CONFIG string public constant override typeAndVersion = "OffRamp 1.6.0-dev"; + /// @dev Hash of encoded address(0) used for empty address checks + bytes32 internal constant EMPTY_ENCODED_ADDRESS_HASH = keccak256(abi.encode(address(0))); /// @dev ChainSelector of this chain uint64 internal immutable i_chainSelector; /// @dev The RMN verification contract @@ -655,6 +658,10 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { SourceChainConfig storage sourceChainConfig = _getEnabledSourceChainConfig(sourceChainSelector); + if (keccak256(root.onRampAddress) != keccak256(sourceChainConfig.onRamp)) { + revert CommitOnRampMismatch(root.onRampAddress, sourceChainConfig.onRamp); + } + if (sourceChainConfig.minSeqNr != root.minSeqNr || root.minSeqNr > root.maxSeqNr) { revert InvalidInterval(root.sourceChainSelector, root.minSeqNr, root.maxSeqNr); } @@ -775,24 +782,27 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { } SourceChainConfig storage currentConfig = s_sourceChainConfigs[sourceChainSelector]; - bytes memory currentOnRamp = currentConfig.onRamp; bytes memory newOnRamp = sourceConfigUpdate.onRamp; - // OnRamp can never be zero - if it is, then the source chain has been added for the first time - if (currentOnRamp.length == 0) { - if (newOnRamp.length == 0) { - revert ZeroAddressNotAllowed(); - } - - currentConfig.onRamp = newOnRamp; + if (currentConfig.onRamp.length == 0) { currentConfig.minSeqNr = 1; emit SourceChainSelectorAdded(sourceChainSelector); - } else if (keccak256(currentOnRamp) != keccak256(newOnRamp)) { - revert InvalidStaticConfig(sourceChainSelector); + } else if (currentConfig.minSeqNr != 1) { + // OnRamp updates should only happens due to a misconfiguration + // If an OnRamp is misconfigured not reports should have been committed and no messages should have been executed + // This is enforced byt the onRamp address check in the commit function + revert InvalidOnRampUpdate(sourceChainSelector); } + // OnRamp can never be zero - if it is, then the source chain has been added for the first time + if (newOnRamp.length == 0 || keccak256(newOnRamp) == EMPTY_ENCODED_ADDRESS_HASH) { + revert ZeroAddressNotAllowed(); + } + + currentConfig.onRamp = newOnRamp; currentConfig.isEnabled = sourceConfigUpdate.isEnabled; currentConfig.router = sourceConfigUpdate.router; + emit SourceChainConfigSet(sourceChainSelector, currentConfig); } } diff --git a/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.sol b/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.sol index 21643a5df6..82531c3148 100644 --- a/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.sol +++ b/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.sol @@ -162,7 +162,7 @@ contract MultiRampsE2E is OnRampSetup, OffRampSetup { }); roots[1] = Internal.MerkleRoot({ sourceChainSelector: SOURCE_CHAIN_SELECTOR + 1, - onRampAddress: abi.encode(address(s_onRamp)), + onRampAddress: abi.encode(address(s_onRamp2)), minSeqNr: messages2[0].header.sequenceNumber, maxSeqNr: messages2[0].header.sequenceNumber, merkleRoot: merkleRoots[1] diff --git a/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol index 8e41f88f91..b5fff3e9bd 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol @@ -814,24 +814,6 @@ contract OffRamp_executeSingleReport is OffRampSetup { s_offRamp.executeSingleReport(executionReport, new OffRamp.GasLimitOverride[](0)); } - function test_MismatchingOnRampRoot_Revert() public { - s_offRamp.setVerifyOverrideResult(SOURCE_CHAIN_SELECTOR_1, 0); - - Internal.Any2EVMRampMessage[] memory messages = - _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - - OffRamp.CommitReport memory commitReport = _constructCommitReport( - // Root against mismatching on ramp - Internal._hash(messages[0], ON_RAMP_ADDRESS_3) - ); - _commit(commitReport, s_latestSequenceNumber); - - Internal.ExecutionReportSingleChain memory executionReport = - _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); - vm.expectRevert(abi.encodeWithSelector(OffRamp.RootNotCommitted.selector, SOURCE_CHAIN_SELECTOR_1)); - s_offRamp.executeSingleReport(executionReport, new OffRamp.GasLimitOverride[](0)); - } - function test_UnhealthySingleChainCurse_Revert() public { _setMockRMNChainCurse(SOURCE_CHAIN_SELECTOR_1, true); vm.expectEmit(); @@ -3187,6 +3169,27 @@ contract OffRamp_applySourceChainConfigUpdates is OffRampSetup { ); } + function test_ReplaceExistingChainOnRamp_Success() public { + OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](1); + sourceChainConfigs[0] = OffRamp.SourceChainConfigArgs({ + router: s_destRouter, + sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, + onRamp: ON_RAMP_ADDRESS_1, + isEnabled: true + }); + + s_offRamp.applySourceChainConfigUpdates(sourceChainConfigs); + + sourceChainConfigs[0].onRamp = ON_RAMP_ADDRESS_2; + + vm.expectEmit(); + emit OffRamp.SourceChainConfigSet( + SOURCE_CHAIN_SELECTOR_1, + OffRamp.SourceChainConfig({router: s_destRouter, isEnabled: true, minSeqNr: 1, onRamp: ON_RAMP_ADDRESS_2}) + ); + s_offRamp.applySourceChainConfigUpdates(sourceChainConfigs); + } + // Reverts function test_ZeroOnRampAddress_Revert() public { @@ -3200,6 +3203,10 @@ contract OffRamp_applySourceChainConfigUpdates is OffRampSetup { vm.expectRevert(OffRamp.ZeroAddressNotAllowed.selector); s_offRamp.applySourceChainConfigUpdates(sourceChainConfigs); + + sourceChainConfigs[0].onRamp = abi.encode(address(0)); + vm.expectRevert(OffRamp.ZeroAddressNotAllowed.selector); + s_offRamp.applySourceChainConfigUpdates(sourceChainConfigs); } function test_RouterAddress_Revert() public { @@ -3228,7 +3235,7 @@ contract OffRamp_applySourceChainConfigUpdates is OffRampSetup { s_offRamp.applySourceChainConfigUpdates(sourceChainConfigs); } - function test_ReplaceExistingChainOnRamp_Revert() public { + function test_InvalidOnRampUpdate_Revert() public { OffRamp.SourceChainConfigArgs[] memory sourceChainConfigs = new OffRamp.SourceChainConfigArgs[](1); sourceChainConfigs[0] = OffRamp.SourceChainConfigArgs({ router: s_destRouter, @@ -3239,9 +3246,30 @@ contract OffRamp_applySourceChainConfigUpdates is OffRampSetup { s_offRamp.applySourceChainConfigUpdates(sourceChainConfigs); + Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](1); + roots[0] = Internal.MerkleRoot({ + sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, + onRampAddress: ON_RAMP_ADDRESS_1, + minSeqNr: 1, + maxSeqNr: 2, + merkleRoot: "test #2" + }); + + _commit( + OffRamp.CommitReport({ + priceUpdates: _getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), + merkleRoots: roots, + rmnSignatures: s_rmnSignatures + }), + s_latestSequenceNumber + ); + + vm.stopPrank(); + vm.startPrank(OWNER); + sourceChainConfigs[0].onRamp = ON_RAMP_ADDRESS_2; - vm.expectRevert(abi.encodeWithSelector(OffRamp.InvalidStaticConfig.selector, SOURCE_CHAIN_SELECTOR_1)); + vm.expectRevert(abi.encodeWithSelector(OffRamp.InvalidOnRampUpdate.selector, SOURCE_CHAIN_SELECTOR_1)); s_offRamp.applySourceChainConfigUpdates(sourceChainConfigs); } } @@ -3278,7 +3306,7 @@ contract OffRamp_commit is OffRampSetup { Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](1); roots[0] = Internal.MerkleRoot({ sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, - onRampAddress: abi.encode(ON_RAMP_ADDRESS_1), + onRampAddress: ON_RAMP_ADDRESS_1, minSeqNr: 1, maxSeqNr: max1, merkleRoot: root @@ -3307,7 +3335,7 @@ contract OffRamp_commit is OffRampSetup { Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](1); roots[0] = Internal.MerkleRoot({ sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, - onRampAddress: abi.encode(ON_RAMP_ADDRESS_1), + onRampAddress: ON_RAMP_ADDRESS_1, minSeqNr: 1, maxSeqNr: maxSeq, merkleRoot: "stale report 1" @@ -3458,7 +3486,7 @@ contract OffRamp_commit is OffRampSetup { roots = new Internal.MerkleRoot[](1); roots[0] = Internal.MerkleRoot({ sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, - onRampAddress: abi.encode(ON_RAMP_ADDRESS_1), + onRampAddress: ON_RAMP_ADDRESS_1, minSeqNr: 1, maxSeqNr: maxSeq, merkleRoot: "stale report" @@ -3564,7 +3592,7 @@ contract OffRamp_commit is OffRampSetup { Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](1); roots[0] = Internal.MerkleRoot({ sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, - onRampAddress: abi.encode(ON_RAMP_ADDRESS_1), + onRampAddress: ON_RAMP_ADDRESS_1, minSeqNr: 1, maxSeqNr: 4, merkleRoot: bytes32(0) @@ -3580,7 +3608,7 @@ contract OffRamp_commit is OffRampSetup { Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](1); roots[0] = Internal.MerkleRoot({ sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, - onRampAddress: abi.encode(ON_RAMP_ADDRESS_1), + onRampAddress: ON_RAMP_ADDRESS_1, minSeqNr: 2, maxSeqNr: 2, merkleRoot: bytes32(0) @@ -3601,7 +3629,7 @@ contract OffRamp_commit is OffRampSetup { Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](1); roots[0] = Internal.MerkleRoot({ sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, - onRampAddress: abi.encode(ON_RAMP_ADDRESS_1), + onRampAddress: ON_RAMP_ADDRESS_1, minSeqNr: 1, maxSeqNr: 0, merkleRoot: bytes32(0) @@ -3666,7 +3694,7 @@ contract OffRamp_commit is OffRampSetup { Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](1); roots[0] = Internal.MerkleRoot({ sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, - onRampAddress: abi.encode(ON_RAMP_ADDRESS_1), + onRampAddress: ON_RAMP_ADDRESS_1, minSeqNr: 1, maxSeqNr: 2, merkleRoot: "Only a single root" @@ -3684,11 +3712,20 @@ contract OffRamp_commit is OffRampSetup { _commit(commitReport, ++s_latestSequenceNumber); } + function test_CommitOnRampMismatch_Revert() public { + OffRamp.CommitReport memory commitReport = _constructCommitReport(); + + commitReport.merkleRoots[0].onRampAddress = ON_RAMP_ADDRESS_2; + + vm.expectRevert(abi.encodeWithSelector(OffRamp.CommitOnRampMismatch.selector, ON_RAMP_ADDRESS_2, ON_RAMP_ADDRESS_1)); + _commit(commitReport, s_latestSequenceNumber); + } + function _constructCommitReport() internal view returns (OffRamp.CommitReport memory) { Internal.MerkleRoot[] memory roots = new Internal.MerkleRoot[](1); roots[0] = Internal.MerkleRoot({ sourceChainSelector: SOURCE_CHAIN_SELECTOR_1, - onRampAddress: abi.encode(ON_RAMP_ADDRESS_1), + onRampAddress: ON_RAMP_ADDRESS_1, minSeqNr: 1, maxSeqNr: s_maxInterval, merkleRoot: "test #2" diff --git a/core/gethwrappers/ccip/generated/offramp/offramp.go b/core/gethwrappers/ccip/generated/offramp/offramp.go index d2cfd96e75..1cae9daaa3 100644 --- a/core/gethwrappers/ccip/generated/offramp/offramp.go +++ b/core/gethwrappers/ccip/generated/offramp/offramp.go @@ -154,8 +154,8 @@ type OffRampStaticConfig struct { } var OffRampMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CanOnlySelfCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"actual\",\"type\":\"bytes32\"}],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ExecutionError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"ForkedChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enumMultiOCR3Base.InvalidConfigErrorType\",\"name\":\"errorType\",\"type\":\"uint8\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"got\",\"type\":\"uint256\"}],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidEVMAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"name\":\"InvalidInterval\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"newLimit\",\"type\":\"uint256\"}],\"name\":\"InvalidManualExecutionGasLimit\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"tokenIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"oldLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenGasOverride\",\"type\":\"uint256\"}],\"name\":\"InvalidManualExecutionTokenGasOverride\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"messageDestChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidMessageDestChainSelector\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"newState\",\"type\":\"uint8\"}],\"name\":\"InvalidNewState\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRoot\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidStaticConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LeavesCannotBeEmpty\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"ManualExecutionGasAmountCountMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ManualExecutionGasLimitMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"ManualExecutionNotYetEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"errorReason\",\"type\":\"bytes\"}],\"name\":\"MessageValidationError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonUniqueSignatures\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"notPool\",\"type\":\"address\"}],\"name\":\"NotACompatiblePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OracleCannotBeZeroAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ReceiverError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountReleased\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePre\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePost\",\"type\":\"uint256\"}],\"name\":\"ReleaseOrMintBalanceMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"name\":\"RootAlreadyCommitted\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"RootNotCommitted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignatureVerificationDisabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignaturesOutOfRegistration\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"reportSourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"messageSourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainSelectorMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"StaleCommitReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"StaticConfigCannotBeChanged\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"TokenDataMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"TokenHandlingError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnexpectedTokenData\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"WrongMessageLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WrongNumberOfSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroChainSelectorNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"AlreadyAttempted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"indexed\":false,\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"}],\"name\":\"CommitReportAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"DynamicConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"messageHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"name\":\"ExecutionStateChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"RootRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"SkippedAlreadyExecutedMessage\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SkippedReportExecution\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"sourceConfig\",\"type\":\"tuple\"}],\"name\":\"SourceChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainSelectorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"}],\"name\":\"StaticConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigUpdates\",\"type\":\"tuple[]\"}],\"name\":\"applySourceChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"destTokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structClient.Any2EVMMessage\",\"name\":\"\",\"type\":\"tuple\"}],\"name\":\"ccipReceive\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"rawVs\",\"type\":\"bytes32\"}],\"name\":\"commit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"execute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"bytes[]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[]\"},{\"internalType\":\"uint32[]\",\"name\":\"tokenGasOverrides\",\"type\":\"uint32[]\"}],\"name\":\"executeSingleMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"getExecutionState\",\"outputs\":[{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLatestPriceSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"getMerkleRoot\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"getSourceChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"latestConfigDetails\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"n\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"}],\"internalType\":\"structMultiOCR3Base.ConfigInfo\",\"name\":\"configInfo\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfig\",\"name\":\"ocrConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage[]\",\"name\":\"messages\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[][]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[][]\"},{\"internalType\":\"bytes32[]\",\"name\":\"proofs\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"proofFlagBits\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.ExecutionReportSingleChain[]\",\"name\":\"reports\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"receiverExecutionGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint32[]\",\"name\":\"tokenGasOverrides\",\"type\":\"uint32[]\"}],\"internalType\":\"structOffRamp.GasLimitOverride[][]\",\"name\":\"gasLimitOverrides\",\"type\":\"tuple[][]\"}],\"name\":\"manuallyExecute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"setDynamicConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfigArgs[]\",\"name\":\"ocrConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"setOCR3Configs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x6101206040523480156200001257600080fd5b50604051620068603803806200686083398101604081905262000035916200085e565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf81620001fa565b5050466080525060208301516001600160a01b03161580620000ec575060408301516001600160a01b0316155b8062000103575060608301516001600160a01b0316155b1562000122576040516342bcdf7f60e11b815260040160405180910390fd5b82516001600160401b03166000036200014e5760405163c656089560e01b815260040160405180910390fd5b82516001600160401b0390811660a052602080850180516001600160a01b0390811660c05260408088018051831660e0526060808a01805185166101005283518b519098168852945184169587019590955251821690850152905116908201527f683eb52ee924eb817377cfa8f41f238f4bb7a877da5267869dfffbad85f564d89060800160405180910390a1620001e682620002a5565b620001f1816200036d565b50505062000be5565b336001600160a01b03821603620002545760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b0316620002ce576040516342bcdf7f60e11b815260040160405180910390fd5b805160048054602080850180516001600160a01b039586166001600160c01b03199094168417600160a01b63ffffffff928316021790945560408087018051600580546001600160a01b031916918916919091179055815194855291519094169183019190915251909216908201527fa1c15688cb2c24508e158f6942b9276c6f3028a85e1af8cf3fff0c3ff3d5fc8d9060600160405180910390a150565b60005b8151811015620006125760008282815181106200039157620003916200099b565b60200260200101519050600081602001519050806001600160401b0316600003620003cf5760405163c656089560e01b815260040160405180910390fd5b81516001600160a01b0316620003f8576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160401b03811660009081526006602052604081206001810180549192916200042490620009b1565b80601f01602080910402602001604051908101604052809291908181526020018280546200045290620009b1565b8015620004a35780601f106200047757610100808354040283529160200191620004a3565b820191906000526020600020905b8154815290600101906020018083116200048557829003601f168201915b5050505050905060008460600151905081516000036200054a578051600003620004e0576040516342bcdf7f60e11b815260040160405180910390fd5b60018301620004f0828262000a42565b508254600160a81b600160e81b031916600160a81b1783556040516001600160401b03851681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a162000585565b8080519060200120828051906020012014620005855760405163c39a620560e01b81526001600160401b038516600482015260240162000083565b604080860151845487516001600160a01b03166001600160a01b0319921515600160a01b02929092166001600160a81b031990911617178455516001600160401b038516907f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b90620005f990869062000b0e565b60405180910390a2505050505080600101905062000370565b5050565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b038111828210171562000651576200065162000616565b60405290565b604051601f8201601f191681016001600160401b038111828210171562000682576200068262000616565b604052919050565b80516001600160401b0381168114620006a257600080fd5b919050565b6001600160a01b0381168114620006bd57600080fd5b50565b6000601f83601f840112620006d457600080fd5b825160206001600160401b0380831115620006f357620006f362000616565b8260051b6200070483820162000657565b93845286810183019383810190898611156200071f57600080fd5b84890192505b8583101562000851578251848111156200073f5760008081fd5b89016080601f19828d038101821315620007595760008081fd5b620007636200062c565b888401516200077281620006a7565b81526040620007838582016200068a565b8a83015260608086015180151581146200079d5760008081fd5b83830152938501519389851115620007b55760008081fd5b84860195508f603f870112620007cd57600094508485fd5b8a860151945089851115620007e657620007e662000616565b620007f78b858f8801160162000657565b93508484528f828688010111156200080f5760008081fd5b60005b858110156200082f578681018301518582018d01528b0162000812565b5060009484018b01949094525091820152835250918401919084019062000725565b9998505050505050505050565b60008060008385036101008112156200087657600080fd5b60808112156200088557600080fd5b6200088f6200062c565b6200089a866200068a565b81526020860151620008ac81620006a7565b60208201526040860151620008c181620006a7565b60408201526060860151620008d681620006a7565b606082810191909152909450607f1982011215620008f357600080fd5b50604051606081016001600160401b0380821183831017156200091a576200091a62000616565b81604052608087015191506200093082620006a7565b90825260a08601519063ffffffff821682146200094c57600080fd5b81602084015260c087015191506200096482620006a7565b6040830182905260e0870151929450808311156200098157600080fd5b50506200099186828701620006c0565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b600181811c90821680620009c657607f821691505b602082108103620009e757634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111562000a3d576000816000526020600020601f850160051c8101602086101562000a185750805b601f850160051c820191505b8181101562000a395782815560010162000a24565b5050505b505050565b81516001600160401b0381111562000a5e5762000a5e62000616565b62000a768162000a6f8454620009b1565b84620009ed565b602080601f83116001811462000aae576000841562000a955750858301515b600019600386901b1c1916600185901b17855562000a39565b600085815260208120601f198616915b8281101562000adf5788860151825594840194600190910190840162000abe565b508582101562000afe5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b602080825282546001600160a01b0381168383015260a081901c60ff161515604084015260a81c6001600160401b0316606083015260808083015260018084018054600093929190849062000b6381620009b1565b8060a089015260c0600183166000811462000b87576001811462000ba45762000bd6565b60ff19841660c08b015260c083151560051b8b0101945062000bd6565b85600052602060002060005b8481101562000bcd5781548c820185015290880190890162000bb0565b8b0160c0019550505b50929998505050505050505050565b60805160a05160c05160e05161010051615c0562000c5b6000396000818161022c015261292c0152600081816101fd0152612bfe0152600081816101ce01528181610552015281816106ff015261237001526000818161019f01526125af015260008181611d980152611dcb0152615c056000f3fe608060405234801561001057600080fd5b50600436106101515760003560e01c806379ba5097116100cd578063d434969111610081578063e9d68a8e11610066578063e9d68a8e146104bc578063f2fde38b146104dc578063f716f99f146104ef57600080fd5b8063d434969114610496578063e62653f5146104a957600080fd5b80638da5cb5b116100b25780638da5cb5b14610417578063c673e58414610432578063ccd37ba31461045257600080fd5b806379ba50971461040157806385572ffb1461040957600080fd5b8063311cd513116101245780635e36480c116101095780635e36480c1461033c5780636f9e320f1461035c5780637437ff9f1461036f57600080fd5b8063311cd5131461030e5780633f4b04aa1461032157600080fd5b806304666f9c1461015657806306285c691461016b578063181f5a77146102b25780632d04ab76146102fb575b600080fd5b610169610164366004613bc5565b610502565b005b61025c60408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160401b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316815250905090565b6040516102a9919081516001600160401b031681526020808301516001600160a01b0390811691830191909152604080840151821690830152606092830151169181019190915260800190565b60405180910390f35b6102ee6040518060400160405280601181526020017f4f666652616d7020312e362e302d64657600000000000000000000000000000081525081565b6040516102a99190613d33565b610169610309366004613de3565b610516565b61016961031c366004613e95565b6109c5565b6009546040516001600160401b0390911681526020016102a9565b61034f61034a366004613ee8565b610a2e565b6040516102a99190613f45565b61016961036a366004613f70565b610a83565b6103cb604080516060810182526000808252602082018190529181019190915250604080516060810182526004546001600160a01b038082168352600160a01b90910463ffffffff166020830152600554169181019190915290565b6040805182516001600160a01b03908116825260208085015163ffffffff169083015292820151909216908201526060016102a9565b610169610a94565b610169610151366004613fc4565b6000546040516001600160a01b0390911681526020016102a9565b61044561044036600461400f565b610b45565b6040516102a9919061406f565b6104886104603660046140e4565b6001600160401b03919091166000908152600860209081526040808320938352929052205490565b6040519081526020016102a9565b6101696104a4366004614380565b610ca3565b6101696104b7366004614708565b610f83565b6104cf6104ca36600461494f565b61122a565b6040516102a9919061496a565b6101696104ea3660046149b7565b611336565b6101696104fd366004614a3c565b611347565b61050a611389565b610513816113e5565b50565b600061052487890189614d91565b602081015151909150156105b6576020810151604080830151905162ccd5af60e81b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169263ccd5af009261058592600401614fb9565b60006040518083038186803b15801561059d57600080fd5b505afa1580156105b1573d6000803e3d6000fd5b505050505b805151511515806105cc57508051602001515115155b156106985760095460208a0135906001600160401b0380831691161015610670576009805467ffffffffffffffff19166001600160401b038316179055600480548351604051633937306f60e01b81526001600160a01b0390921692633937306f926106399291016150ed565b600060405180830381600087803b15801561065357600080fd5b505af1158015610667573d6000803e3d6000fd5b50505050610696565b81602001515160000361069657604051632261116760e01b815260040160405180910390fd5b505b60005b816020015151811015610906576000826020015182815181106106c0576106c061501b565b60209081029190910101518051604051632cbc26bb60e01b815267ffffffffffffffff60801b608083901b166004820152919250906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632cbc26bb90602401602060405180830381865afa158015610746573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061076a9190615100565b1561079857604051637edeb53960e11b81526001600160401b03821660048201526024015b60405180910390fd5b60006107a38261168b565b604084015181549192506001600160401b03908116600160a81b909204161415806107e7575082606001516001600160401b031683604001516001600160401b0316115b1561082c57825160408085015160608601519151636af0786b60e11b81526001600160401b03938416600482015290831660248201529116604482015260640161078f565b60808301518061084f5760405163504570e360e01b815260040160405180910390fd5b83516001600160401b03166000908152600860209081526040808320848452909152902054156108a75783516040516332cf0cbf60e01b81526001600160401b0390911660048201526024810182905260440161078f565b60608401516108b7906001615133565b825467ffffffffffffffff60a81b1916600160a81b6001600160401b0392831602179092559251166000908152600860209081526040808320948352939052919091204290555060010161069b565b50602081015181516040517f35c02761bcd3ef995c6a601a1981f4ed3934dcbe5041e24e286c89f5531d17e49261093e92909161515a565b60405180910390a16109ba60008a8a8a8a8a8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808e0282810182019093528d82529093508d92508c9182918501908490808284376000920191909152508b92506116d7915050565b505050505050505050565b610a056109d48284018461517f565b60408051600080825260208201909252906109ff565b60608152602001906001900390816109ea5790505b506119d0565b604080516000808252602082019092529050610a286001858585858660006116d7565b50505050565b6000610a3c600160046151b3565b6002610a496080856151dc565b6001600160401b0316610a5c9190615202565b610a668585611a92565b901c166003811115610a7a57610a7a613f1b565b90505b92915050565b610a8b611389565b61051381611ad7565b6001546001600160a01b03163314610aee5760405162461bcd60e51b815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e657200000000000000000000604482015260640161078f565b60008054336001600160a01b0319808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610b886040805160e081019091526000606082018181526080830182905260a0830182905260c08301919091528190815260200160608152602001606081525090565b60ff808316600090815260026020818152604092839020835160e081018552815460608201908152600183015480881660808401526101008104881660a0840152620100009004909616151560c082015294855291820180548451818402810184019095528085529293858301939092830182828015610c3157602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610c13575b5050505050815260200160038201805480602002602001604051908101604052809291908181526020018280548015610c9357602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610c75575b5050505050815250509050919050565b333014610cc3576040516306e34e6560e31b815260040160405180910390fd5b6040805160008082526020820190925281610d00565b6040805180820190915260008082526020820152815260200190600190039081610cd95790505b5060a08701515190915015610d3657610d338660a001518760200151886060015189600001516020015189898989611bb6565b90505b6040805160a081018252875151815287516020908101516001600160401b031681830152808901518351600094840192610d71929101613d33565b60408051601f19818403018152918152908252898101516020830152018390526005549091506001600160a01b03168015610e4c576040516308d450a160e01b81526001600160a01b038216906308d450a190610dd29085906004016152ba565b600060405180830381600087803b158015610dec57600080fd5b505af1925050508015610dfd575060015b610e4c573d808015610e2b576040519150601f19603f3d011682016040523d82523d6000602084013e610e30565b606091505b50806040516309c2532560e01b815260040161078f9190613d33565b604088015151158015610e6157506080880151155b80610e78575060608801516001600160a01b03163b155b80610e9f57506060880151610e9d906001600160a01b03166385572ffb60e01b611d79565b155b15610eac57505050610f7c565b87516020908101516001600160401b03166000908152600690915260408082205460808b015160608c01519251633cf9798360e01b815284936001600160a01b0390931692633cf9798392610f0a92899261138892916004016152cd565b6000604051808303816000875af1158015610f29573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610f519190810190615309565b509150915081610f7657806040516302a35ba360e21b815260040161078f9190613d33565b50505050505b5050505050565b610f8b611d95565b815181518114610fae576040516320f8fd5960e21b815260040160405180910390fd5b60005b8181101561121a576000848281518110610fcd57610fcd61501b565b60200260200101519050600081602001515190506000858481518110610ff557610ff561501b565b6020026020010151905080518214611020576040516320f8fd5960e21b815260040160405180910390fd5b60005b8281101561120b57600082828151811061103f5761103f61501b565b60200260200101516000015190506000856020015183815181106110655761106561501b565b60200260200101519050816000146110b95780608001518210156110b9578551815151604051633a98d46360e11b81526001600160401b03909216600483015260248201526044810183905260640161078f565b8383815181106110cb576110cb61501b565b602002602001015160200151518160a00151511461111857805180516060909101516040516370a193fd60e01b815260048101929092526001600160401b0316602482015260440161078f565b60005b8160a00151518110156111fd57600085858151811061113c5761113c61501b565b60200260200101516020015182815181106111595761115961501b565b602002602001015163ffffffff169050806000146111f45760008360a0015183815181106111895761118961501b565b6020026020010151608001518060200190518101906111a8919061539e565b90508063ffffffff168210156111f2578351516040516348e617b360e01b815260048101919091526024810184905263ffffffff821660448201526064810183905260840161078f565b505b5060010161111b565b505050806001019050611023565b50505050806001019050610fb1565b5061122583836119d0565b505050565b60408051608080820183526000808352602080840182905283850182905260608085018190526001600160401b03878116845260068352928690208651948501875280546001600160a01b0381168652600160a01b810460ff16151593860193909352600160a81b9092049092169483019490945260018401805493949293918401916112b6906153bb565b80601f01602080910402602001604051908101604052809291908181526020018280546112e2906153bb565b8015610c935780601f1061130457610100808354040283529160200191610c93565b820191906000526020600020905b81548152906001019060200180831161131257505050919092525091949350505050565b61133e611389565b61051381611dfd565b61134f611389565b60005b81518110156113855761137d8282815181106113705761137061501b565b6020026020010151611ea6565b600101611352565b5050565b6000546001600160a01b031633146113e35760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640161078f565b565b60005b81518110156113855760008282815181106114055761140561501b565b60200260200101519050600081602001519050806001600160401b03166000036114425760405163c656089560e01b815260040160405180910390fd5b81516001600160a01b031661146a576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160401b0381166000908152600660205260408120600181018054919291611494906153bb565b80601f01602080910402602001604051908101604052809291908181526020018280546114c0906153bb565b801561150d5780601f106114e25761010080835404028352916020019161150d565b820191906000526020600020905b8154815290600101906020018083116114f057829003601f168201915b5050505050905060008460600151905081516000036115b0578051600003611548576040516342bcdf7f60e11b815260040160405180910390fd5b600183016115568282615445565b50825467ffffffffffffffff60a81b1916600160a81b1783556040516001600160401b03851681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a16115e9565b80805190602001208280519060200120146115e95760405163c39a620560e01b81526001600160401b038516600482015260240161078f565b604080860151845487516001600160a01b03166001600160a01b0319921515600160a01b02929092167fffffffffffffffffffffff00000000000000000000000000000000000000000090911617178455516001600160401b038516907f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b90611673908690615504565b60405180910390a250505050508060010190506113e8565b6001600160401b03811660009081526006602052604081208054600160a01b900460ff16610a7d5760405163ed053c5960e01b81526001600160401b038416600482015260240161078f565b60ff878116600090815260026020908152604080832081516080810183528154815260019091015480861693820193909352610100830485169181019190915262010000909104909216151560608301528735906117368760a46155d1565b905082606001511561177e57845161174f906020615202565b865161175c906020615202565b6117679060a06155d1565b61177191906155d1565b61177b90826155d1565b90505b3681146117a757604051638e1192e160e01b81526004810182905236602482015260440161078f565b50815181146117d65781516040516324f7d61360e21b815260048101919091526024810182905260440161078f565b6117de611d95565b60ff808a166000908152600360209081526040808320338452825280832081518083019092528054808616835293949193909284019161010090910416600281111561182c5761182c613f1b565b600281111561183d5761183d613f1b565b905250905060028160200151600281111561185a5761185a613f1b565b1480156118ae5750600260008b60ff1660ff168152602001908152602001600020600301816000015160ff16815481106118965761189661501b565b6000918252602090912001546001600160a01b031633145b6118cb57604051631b41e11d60e31b815260040160405180910390fd5b5081606001511561197b5760208201516118e69060016155e4565b60ff16855114611909576040516371253a2560e01b815260040160405180910390fd5b835185511461192b5760405163a75d88af60e01b815260040160405180910390fd5b6000878760405161193d9291906155fd565b604051908190038120611954918b9060200161560d565b6040516020818303038152906040528051906020012090506119798a82888888612185565b505b6040805182815260208a8101356001600160401b03169082015260ff8b16917f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef0910160405180910390a2505050505050505050565b81516000036119f15760405162bf199760e01b815260040160405180910390fd5b80516040805160008082526020820190925291159181611a34565b604080518082019091526000815260606020820152815260200190600190039081611a0c5790505b50905060005b8451811015610f7c57611a8a858281518110611a5857611a5861501b565b602002602001015184611a8457858381518110611a7757611a7761501b565b6020026020010151612342565b83612342565b600101611a3a565b6001600160401b038216600090815260076020526040812081611ab6608085615621565b6001600160401b031681526020810191909152604001600020549392505050565b80516001600160a01b0316611aff576040516342bcdf7f60e11b815260040160405180910390fd5b805160048054602080850180516001600160a01b039586167fffffffffffffffff0000000000000000000000000000000000000000000000009094168417600160a01b63ffffffff928316021790945560408087018051600580546001600160a01b031916918916919091179055815194855291519094169183019190915251909216908201527fa1c15688cb2c24508e158f6942b9276c6f3028a85e1af8cf3fff0c3ff3d5fc8d9060600160405180910390a150565b606088516001600160401b03811115611bd157611bd16139e5565b604051908082528060200260200182016040528015611c1657816020015b6040805180820190915260008082526020820152815260200190600190039081611bef5790505b509050811560005b8a51811015611d6b5781611cc857848482818110611c3e57611c3e61501b565b9050602002016020810190611c539190615647565b63ffffffff1615611cc857848482818110611c7057611c7061501b565b9050602002016020810190611c859190615647565b6040805163ffffffff9092166020830152016040516020818303038152906040528b8281518110611cb857611cb861501b565b6020026020010151608001819052505b611d468b8281518110611cdd57611cdd61501b565b60200260200101518b8b8b8b8b87818110611cfa57611cfa61501b565b9050602002810190611d0c9190615664565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612bb692505050565b838281518110611d5857611d5861501b565b6020908102919091010152600101611c1e565b505098975050505050505050565b6000611d8483612eb4565b8015610a7a5750610a7a8383612eff565b467f0000000000000000000000000000000000000000000000000000000000000000146113e357604051630f01ce8560e01b81527f0000000000000000000000000000000000000000000000000000000000000000600482015246602482015260440161078f565b336001600160a01b03821603611e555760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161078f565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b806040015160ff16600003611ed1576000604051631b3fab5160e11b815260040161078f91906156aa565b60208082015160ff80821660009081526002909352604083206001810154929390928392169003611f22576060840151600182018054911515620100000262ff000019909216919091179055611f5e565b6060840151600182015460ff6201000090910416151590151514611f5e576040516321fd80df60e21b815260ff8416600482015260240161078f565b60a084015180516101001015611f8a576001604051631b3fab5160e11b815260040161078f91906156aa565b611ff08484600301805480602002602001604051908101604052809291908181526020018280548015611fe657602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611fc8575b5050505050612fa1565b8460600151156120fa5761205e8484600201805480602002602001604051908101604052809291908181526020018280548015611fe6576020028201919060005260206000209081546001600160a01b03168152600190910190602001808311611fc8575050505050612fa1565b60808501518051610100101561208a576002604051631b3fab5160e11b815260040161078f91906156aa565b604086015161209a9060036156c4565b60ff168151116120c0576003604051631b3fab5160e11b815260040161078f91906156aa565b805160018401805461ff00191661010060ff8416021790556120eb906002860190602084019061396b565b506120f88582600161300a565b505b6121068482600261300a565b805161211b906003850190602084019061396b565b5060408581015160018401805460ff191660ff8316179055865180855560a088015192517fab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f547936121749389939260028a019291906156e0565b60405180910390a1610f7c84613165565b8251600090815b818110156123385760006001888684602081106121ab576121ab61501b565b6121b891901a601b6155e4565b8985815181106121ca576121ca61501b565b60200260200101518986815181106121e4576121e461501b565b602002602001015160405160008152602001604052604051612222949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015612244573d6000803e3d6000fd5b505060408051601f1981015160ff808e166000908152600360209081528582206001600160a01b038516835281528582208587019096528554808416865293975090955092939284019161010090041660028111156122a5576122a5613f1b565b60028111156122b6576122b6613f1b565b90525090506001816020015160028111156122d3576122d3613f1b565b146122f157604051636518c33d60e11b815260040160405180910390fd5b8051600160ff9091161b85161561231b57604051633d9ef1f160e21b815260040160405180910390fd5b806000015160ff166001901b85179450505080600101905061218c565b5050505050505050565b81518151604051632cbc26bb60e01b8152608083901b67ffffffffffffffff60801b166004820152901515907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632cbc26bb90602401602060405180830381865afa1580156123bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123e39190615100565b1561245457801561241257604051637edeb53960e11b81526001600160401b038316600482015260240161078f565b6040516001600160401b03831681527faab522ed53d887e56ed53dd37398a01aeef6a58e0fa77c2173beb9512d8949339060200160405180910390a150505050565b600061245f8361168b565b600101805461246d906153bb565b80601f0160208091040260200160405190810160405280929190818152602001828054612499906153bb565b80156124e65780601f106124bb576101008083540402835291602001916124e6565b820191906000526020600020905b8154815290600101906020018083116124c957829003601f168201915b505050602088015151929350505060008190036125155760405162bf199760e01b815260040160405180910390fd5b856040015151811461253a576040516357e0e08360e01b815260040160405180910390fd5b6000816001600160401b03811115612554576125546139e5565b60405190808252806020026020018201604052801561257d578160200160208202803683370190505b50905060005b8281101561269e576000886020015182815181106125a3576125a361501b565b602002602001015190507f00000000000000000000000000000000000000000000000000000000000000006001600160401b03168160000151604001516001600160401b03161461261a5780516040908101519051631c21951160e11b81526001600160401b03909116600482015260240161078f565b866001600160401b03168160000151602001516001600160401b03161461266e57805160200151604051636c95f1eb60e01b81526001600160401b03808a166004830152909116602482015260440161078f565b61267881866131bc565b83838151811061268a5761268a61501b565b602090810291909101015250600101612583565b5060006126b586838a606001518b608001516132de565b9050806000036126e357604051633ee8bd3f60e11b81526001600160401b038716600482015260240161078f565b60005b838110156109ba5760005a905060008a60200151838151811061270b5761270b61501b565b6020026020010151905060006127298a836000015160600151610a2e565b9050600081600381111561273f5761273f613f1b565b148061275c5750600381600381111561275a5761275a613f1b565b145b6127b257815160600151604080516001600160401b03808e16825290921660208301527f3b575419319662b2a6f5e2467d84521517a3382b908eb3d557bb3fdb0c50e23c910160405180910390a1505050612bae565b60608915612891578b85815181106127cc576127cc61501b565b6020908102919091018101510151600454909150600090600160a01b900463ffffffff166127fa88426151b3565b119050808061281a5750600383600381111561281857612818613f1b565b145b612842576040516354e7e43160e11b81526001600160401b038d16600482015260240161078f565b8c86815181106128545761285461501b565b60200260200101516000015160001461288b578c86815181106128795761287961501b565b60209081029190910101515160808501525b506128fd565b60008260038111156128a5576128a5613f1b565b146128fd57825160600151604080516001600160401b03808f16825290921660208301527f3ef2a99c550a751d4b0b261268f05a803dfb049ab43616a1ffb388f61fe65120910160405180910390a150505050612bae565b8251608001516001600160401b0316156129d657600082600381111561292557612925613f1b565b036129d6577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e0e03cae8c85600001516080015186602001516040518463ffffffff1660e01b815260040161298693929190615792565b6020604051808303816000875af11580156129a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129c99190615100565b6129d65750505050612bae565b60008d6040015186815181106129ee576129ee61501b565b6020026020010151905080518460a001515114612a3857835160600151604051631cfe6d8b60e01b81526001600160401b03808f166004830152909116602482015260440161078f565b612a4c8c856000015160600151600161331b565b600080612a5a8684866133c0565b91509150612a718e8760000151606001518461331b565b8c15612ac8576003826003811115612a8b57612a8b613f1b565b03612ac8576000856003811115612aa457612aa4613f1b565b14612ac857855151604051632b11b8d960e01b815261078f919083906004016157be565b6002826003811115612adc57612adc613f1b565b14612b21576003826003811115612af557612af5613f1b565b14612b21578d866000015160600151836040516349362d1f60e11b815260040161078f939291906157d7565b8560000151600001518660000151606001516001600160401b03168f6001600160401b03167f05665fe9ad095383d018353f4cbcba77e84db27dd215081bbf7cdf9ae6fbe48b8d8c81518110612b7957612b7961501b565b602002602001015186865a612b8e908f6151b3565b604051612b9e94939291906157fc565b60405180910390a4505050505050505b6001016126e6565b60408051808201909152600080825260208201526000612bd98760200151613474565b60405163bbe4f6db60e01b81526001600160a01b0380831660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063bbe4f6db90602401602060405180830381865afa158015612c45573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c699190615833565b90506001600160a01b0381161580612c985750612c966001600160a01b03821663aff2afbf60e01b611d79565b155b15612cc15760405163ae9b4ce960e01b81526001600160a01b038216600482015260240161078f565b600080612cec88858c60800151806020019051810190612ce1919061539e565b63ffffffff166134e8565b915091506000806000612d9f6040518061010001604052808e81526020018c6001600160401b031681526020018d6001600160a01b031681526020018f606001518152602001896001600160a01b031681526020018f6000015181526020018f6040015181526020018b815250604051602401612d699190615850565b60408051601f198184030181529190526020810180516001600160e01b0316633907753760e01b179052878661138860846135cb565b92509250925082612dc5578160405163e1cd550960e01b815260040161078f9190613d33565b8151602014612df4578151604051631e3be00960e21b815260206004820152602481019190915260440161078f565b600082806020019051810190612e0a919061591c565b9050866001600160a01b03168c6001600160a01b031614612e86576000612e3b8d8a612e36868a6151b3565b6134e8565b50905086811080612e55575081612e5288836151b3565b14155b15612e845760405163a966e21f60e01b815260048101839052602481018890526044810182905260640161078f565b505b604080518082019091526001600160a01b039098168852602088015250949550505050505095945050505050565b6000612ec7826301ffc9a760e01b612eff565b8015610a7d5750612ef8827fffffffff00000000000000000000000000000000000000000000000000000000612eff565b1592915050565b6040517fffffffff0000000000000000000000000000000000000000000000000000000082166024820152600090819060440160408051601f19818403018152919052602080820180516001600160e01b03166301ffc9a760e01b178152825192935060009283928392909183918a617530fa92503d91506000519050828015612f8a575060208210155b8015612f965750600081115b979650505050505050565b60005b81518110156112255760ff831660009081526003602052604081208351909190849084908110612fd657612fd661501b565b6020908102919091018101516001600160a01b03168252810191909152604001600020805461ffff19169055600101612fa4565b60005b8251811015610a2857600083828151811061302a5761302a61501b565b602002602001015190506000600281111561304757613047613f1b565b60ff80871660009081526003602090815260408083206001600160a01b0387168452909152902054610100900416600281111561308657613086613f1b565b146130a7576004604051631b3fab5160e11b815260040161078f91906156aa565b6001600160a01b0381166130ce5760405163d6c62c9b60e01b815260040160405180910390fd5b60405180604001604052808360ff1681526020018460028111156130f4576130f4613f1b565b905260ff80871660009081526003602090815260408083206001600160a01b0387168452825290912083518154931660ff198416811782559184015190929091839161ffff19161761010083600281111561315157613151613f1b565b02179055509050505080600101905061300d565b60ff81166105135760ff808216600090815260026020526040902060010154620100009004166131a857604051631e8ed32560e21b815260040160405180910390fd5b6009805467ffffffffffffffff1916905550565b815160208082015160409283015192516000938493613202937f2425b0b9f9054c76ff151b0a175b18f37a4a4e82013a72e9f15c9caa095ed21f93909291889101615935565b60408051601f1981840301815290829052805160209182012086518051888401516060808b0151908401516080808d0151950151959761324b9794969395929491939101615967565b604051602081830303815290604052805190602001208560400151805190602001208660a001516040516020016132829190615a6b565b60408051601f198184030181528282528051602091820120908301969096528101939093526060830191909152608082015260a081019190915260c0015b60405160208183030381529060405280519060200120905092915050565b6000806132ec8585856136a5565b6001600160401b038716600090815260086020908152604080832093835292905220549150505b949350505050565b6000600261332a6080856151dc565b6001600160401b031661333d9190615202565b9050600061334b8585611a92565b90508161335a600160046151b3565b901b19168183600381111561337157613371613f1b565b6001600160401b03871660009081526007602052604081209190921b9290921791829161339f608088615621565b6001600160401b031681526020810191909152604001600020555050505050565b60405163d434969160e01b8152600090606090309063d4349691906133ed90889088908890600401615b02565b600060405180830381600087803b15801561340757600080fd5b505af1925050508015613418575060015b613457573d808015613446576040519150601f19603f3d011682016040523d82523d6000602084013e61344b565b606091505b5060039250905061346c565b50506040805160208101909152600081526002905b935093915050565b6000815160201461349a578160405163046b337b60e51b815260040161078f9190613d33565b6000828060200190518101906134b0919061591c565b90506001600160a01b038111806134c8575061040081105b15610a7d578260405163046b337b60e51b815260040161078f9190613d33565b60008060008060006135498860405160240161351391906001600160a01b0391909116815260200190565b60408051601f198184030181529190526020810180516001600160e01b03166370a0823160e01b179052888861138860846135cb565b9250925092508261356f578160405163e1cd550960e01b815260040161078f9190613d33565b602082511461359e578151604051631e3be00960e21b815260206004820152602481019190915260440161078f565b818060200190518101906135b2919061591c565b6135bc82886151b3565b94509450505050935093915050565b6000606060008361ffff166001600160401b038111156135ed576135ed6139e5565b6040519080825280601f01601f191660200182016040528015613617576020820181803683370190505b509150863b6136315763030ed58f60e21b60005260046000fd5b5a8581101561364b57632be8ca8b60e21b60005260046000fd5b859003604081048103871061366b576337c3be2960e01b60005260046000fd5b505a6000808a5160208c0160008c8cf193505a900390503d8481111561368e5750835b808352806000602085013e50955095509592505050565b82518251600091908183036136cd57604051630469ac9960e21b815260040160405180910390fd5b61010182118015906136e157506101018111155b6136fe576040516309bde33960e01b815260040160405180910390fd5b60001982820101610100811115613728576040516309bde33960e01b815260040160405180910390fd5b8060000361375557866000815181106137435761374361501b565b60200260200101519350505050613923565b6000816001600160401b0381111561376f5761376f6139e5565b604051908082528060200260200182016040528015613798578160200160208202803683370190505b50905060008080805b858110156138c25760006001821b8b8116036137fc57888510156137e5578c5160018601958e9181106137d6576137d661501b565b6020026020010151905061381e565b85516001850194879181106137d6576137d661501b565b8b5160018401938d9181106138135761381361501b565b602002602001015190505b60008986101561384e578d5160018701968f91811061383f5761383f61501b565b60200260200101519050613870565b86516001860195889181106138655761386561501b565b602002602001015190505b82851115613891576040516309bde33960e01b815260040160405180910390fd5b61389b828261392a565b8784815181106138ad576138ad61501b565b602090810291909101015250506001016137a1565b5060018503821480156138d457508683145b80156138df57508581145b6138fc576040516309bde33960e01b815260040160405180910390fd5b8360018603815181106139115761391161501b565b60200260200101519750505050505050505b9392505050565b60008183106139425761393d8284613948565b610a7a565b610a7a83835b6040805160016020820152908101839052606081018290526000906080016132c0565b8280548282559060005260206000209081019282156139c0579160200282015b828111156139c057825182546001600160a01b0319166001600160a01b0390911617825560209092019160019091019061398b565b506139cc9291506139d0565b5090565b5b808211156139cc57600081556001016139d1565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b0381118282101715613a1d57613a1d6139e5565b60405290565b604051606081016001600160401b0381118282101715613a1d57613a1d6139e5565b60405160a081016001600160401b0381118282101715613a1d57613a1d6139e5565b60405160c081016001600160401b0381118282101715613a1d57613a1d6139e5565b604080519081016001600160401b0381118282101715613a1d57613a1d6139e5565b604051601f8201601f191681016001600160401b0381118282101715613ad357613ad36139e5565b604052919050565b60006001600160401b03821115613af457613af46139e5565b5060051b60200190565b6001600160a01b038116811461051357600080fd5b80356001600160401b0381168114613b2a57600080fd5b919050565b801515811461051357600080fd5b8035613b2a81613b2f565b60006001600160401b03821115613b6157613b616139e5565b50601f01601f191660200190565b600082601f830112613b8057600080fd5b8135613b93613b8e82613b48565b613aab565b818152846020838601011115613ba857600080fd5b816020850160208301376000918101602001919091529392505050565b60006020808385031215613bd857600080fd5b82356001600160401b0380821115613bef57600080fd5b818501915085601f830112613c0357600080fd5b8135613c11613b8e82613adb565b81815260059190911b83018401908481019088831115613c3057600080fd5b8585015b83811015613cd657803585811115613c4c5760008081fd5b86016080818c03601f1901811315613c645760008081fd5b613c6c6139fb565b89830135613c7981613afe565b81526040613c88848201613b13565b8b830152606080850135613c9b81613b2f565b83830152928401359289841115613cb457600091508182fd5b613cc28f8d86880101613b6f565b908301525085525050918601918601613c34565b5098975050505050505050565b60005b83811015613cfe578181015183820152602001613ce6565b50506000910152565b60008151808452613d1f816020860160208601613ce3565b601f01601f19169290920160200192915050565b602081526000610a7a6020830184613d07565b8060608101831015610a7d57600080fd5b60008083601f840112613d6957600080fd5b5081356001600160401b03811115613d8057600080fd5b602083019150836020828501011115613d9857600080fd5b9250929050565b60008083601f840112613db157600080fd5b5081356001600160401b03811115613dc857600080fd5b6020830191508360208260051b8501011115613d9857600080fd5b60008060008060008060008060e0898b031215613dff57600080fd5b613e098a8a613d46565b975060608901356001600160401b0380821115613e2557600080fd5b613e318c838d01613d57565b909950975060808b0135915080821115613e4a57600080fd5b613e568c838d01613d9f565b909750955060a08b0135915080821115613e6f57600080fd5b50613e7c8b828c01613d9f565b999c989b50969995989497949560c00135949350505050565b600080600060808486031215613eaa57600080fd5b613eb48585613d46565b925060608401356001600160401b03811115613ecf57600080fd5b613edb86828701613d57565b9497909650939450505050565b60008060408385031215613efb57600080fd5b613f0483613b13565b9150613f1260208401613b13565b90509250929050565b634e487b7160e01b600052602160045260246000fd5b60048110613f4157613f41613f1b565b9052565b60208101610a7d8284613f31565b8035613b2a81613afe565b63ffffffff8116811461051357600080fd5b600060608284031215613f8257600080fd5b613f8a613a23565b8235613f9581613afe565b81526020830135613fa581613f5e565b60208201526040830135613fb881613afe565b60408201529392505050565b600060208284031215613fd657600080fd5b81356001600160401b03811115613fec57600080fd5b820160a0818503121561392357600080fd5b803560ff81168114613b2a57600080fd5b60006020828403121561402157600080fd5b610a7a82613ffe565b60008151808452602080850194506020840160005b838110156140645781516001600160a01b03168752958201959082019060010161403f565b509495945050505050565b60208152600082518051602084015260ff602082015116604084015260ff604082015116606084015260608101511515608084015250602083015160c060a08401526140be60e084018261402a565b90506040840151601f198483030160c08501526140db828261402a565b95945050505050565b600080604083850312156140f757600080fd5b61410083613b13565b946020939093013593505050565b600060a0828403121561412057600080fd5b614128613a45565b90508135815261413a60208301613b13565b602082015261414b60408301613b13565b604082015261415c60608301613b13565b606082015261416d60808301613b13565b608082015292915050565b600082601f83011261418957600080fd5b81356020614199613b8e83613adb565b82815260059290921b840181019181810190868411156141b857600080fd5b8286015b848110156142b25780356001600160401b03808211156141dc5760008081fd5b9088019060a0828b03601f19018113156141f65760008081fd5b6141fe613a45565b87840135838111156142105760008081fd5b61421e8d8a83880101613b6f565b825250604080850135848111156142355760008081fd5b6142438e8b83890101613b6f565b8a840152506060808601358581111561425c5760008081fd5b61426a8f8c838a0101613b6f565b838501525060809150818601358184015250828501359250838311156142905760008081fd5b61429e8d8a85880101613b6f565b9082015286525050509183019183016141bc565b509695505050505050565b600061014082840312156142d057600080fd5b6142d8613a67565b90506142e4838361410e565b815260a08201356001600160401b038082111561430057600080fd5b61430c85838601613b6f565b602084015260c084013591508082111561432557600080fd5b61433185838601613b6f565b604084015261434260e08501613f53565b6060840152610100840135608084015261012084013591508082111561436757600080fd5b5061437484828501614178565b60a08301525092915050565b60008060008060006060868803121561439857600080fd5b85356001600160401b03808211156143af57600080fd5b6143bb89838a016142bd565b965060208801359150808211156143d157600080fd5b6143dd89838a01613d9f565b909650945060408801359150808211156143f657600080fd5b5061440388828901613d9f565b969995985093965092949392505050565b600082601f83011261442557600080fd5b81356020614435613b8e83613adb565b82815260059290921b8401810191818101908684111561445457600080fd5b8286015b848110156142b25780356001600160401b038111156144775760008081fd5b6144858986838b01016142bd565b845250918301918301614458565b600082601f8301126144a457600080fd5b813560206144b4613b8e83613adb565b82815260059290921b840181019181810190868411156144d357600080fd5b8286015b848110156142b25780356001600160401b03808211156144f657600080fd5b818901915089603f83011261450a57600080fd5b8582013561451a613b8e82613adb565b81815260059190911b830160400190878101908c83111561453a57600080fd5b604085015b838110156145735780358581111561455657600080fd5b6145658f6040838a0101613b6f565b84525091890191890161453f565b508752505050928401925083016144d7565b600082601f83011261459657600080fd5b813560206145a6613b8e83613adb565b8083825260208201915060208460051b8701019350868411156145c857600080fd5b602086015b848110156142b257803583529183019183016145cd565b600082601f8301126145f557600080fd5b81356020614605613b8e83613adb565b82815260059290921b8401810191818101908684111561462457600080fd5b8286015b848110156142b25780356001600160401b03808211156146485760008081fd5b9088019060a0828b03601f19018113156146625760008081fd5b61466a613a45565b614675888501613b13565b81526040808501358481111561468b5760008081fd5b6146998e8b83890101614414565b8a84015250606080860135858111156146b25760008081fd5b6146c08f8c838a0101614493565b83850152506080915081860135858111156146db5760008081fd5b6146e98f8c838a0101614585565b9184019190915250919093013590830152508352918301918301614628565b6000806040838503121561471b57600080fd5b6001600160401b038335111561473057600080fd5b61473d84843585016145e4565b91506001600160401b036020840135111561475757600080fd5b6020830135830184601f82011261476d57600080fd5b61477a613b8e8235613adb565b81358082526020808301929160051b84010187101561479857600080fd5b602083015b6020843560051b850101811015614941576001600160401b03813511156147c357600080fd5b87603f8235860101126147d557600080fd5b6147e8613b8e6020833587010135613adb565b81358501602081810135808452908301929160059190911b016040018a101561481057600080fd5b604083358701015b83358701602081013560051b01604001811015614931576001600160401b038135111561484457600080fd5b833587018135016040818d03603f1901121561485f57600080fd5b614867613a89565b604082013581526001600160401b036060830135111561488657600080fd5b8c605f60608401358401011261489b57600080fd5b60406060830135830101356148b2613b8e82613adb565b808282526020820191508f60608460051b60608801358801010111156148d757600080fd5b6060808601358601015b60608460051b606088013588010101811015614911576149018135613f5e565b80358352602092830192016148e1565b508060208501525050508085525050602083019250602081019050614818565b508452506020928301920161479d565b508093505050509250929050565b60006020828403121561496157600080fd5b610a7a82613b13565b602081526001600160a01b0382511660208201526020820151151560408201526001600160401b0360408301511660608201526000606083015160808084015261331360a0840182613d07565b6000602082840312156149c957600080fd5b813561392381613afe565b600082601f8301126149e557600080fd5b813560206149f5613b8e83613adb565b8083825260208201915060208460051b870101935086841115614a1757600080fd5b602086015b848110156142b2578035614a2f81613afe565b8352918301918301614a1c565b60006020808385031215614a4f57600080fd5b82356001600160401b0380821115614a6657600080fd5b818501915085601f830112614a7a57600080fd5b8135614a88613b8e82613adb565b81815260059190911b83018401908481019088831115614aa757600080fd5b8585015b83811015613cd657803585811115614ac257600080fd5b860160c0818c03601f19011215614ad95760008081fd5b614ae1613a67565b8882013581526040614af4818401613ffe565b8a8301526060614b05818501613ffe565b8284015260809150614b18828501613b3d565b9083015260a08381013589811115614b305760008081fd5b614b3e8f8d838801016149d4565b838501525060c0840135915088821115614b585760008081fd5b614b668e8c848701016149d4565b9083015250845250918601918601614aab565b80356001600160e01b0381168114613b2a57600080fd5b600082601f830112614ba157600080fd5b81356020614bb1613b8e83613adb565b82815260069290921b84018101918181019086841115614bd057600080fd5b8286015b848110156142b25760408189031215614bed5760008081fd5b614bf5613a89565b614bfe82613b13565b8152614c0b858301614b79565b81860152835291830191604001614bd4565b600082601f830112614c2e57600080fd5b81356020614c3e613b8e83613adb565b82815260059290921b84018101918181019086841115614c5d57600080fd5b8286015b848110156142b25780356001600160401b0380821115614c815760008081fd5b9088019060a0828b03601f1901811315614c9b5760008081fd5b614ca3613a45565b614cae888501613b13565b815260408085013584811115614cc45760008081fd5b614cd28e8b83890101613b6f565b8a8401525060609350614ce6848601613b13565b908201526080614cf7858201613b13565b93820193909352920135908201528352918301918301614c61565b600082601f830112614d2357600080fd5b81356020614d33613b8e83613adb565b82815260069290921b84018101918181019086841115614d5257600080fd5b8286015b848110156142b25760408189031215614d6f5760008081fd5b614d77613a89565b813581528482013585820152835291830191604001614d56565b60006020808385031215614da457600080fd5b82356001600160401b0380821115614dbb57600080fd5b9084019060608287031215614dcf57600080fd5b614dd7613a23565b823582811115614de657600080fd5b83016040818903811315614df957600080fd5b614e01613a89565b823585811115614e1057600080fd5b8301601f81018b13614e2157600080fd5b8035614e2f613b8e82613adb565b81815260069190911b8201890190898101908d831115614e4e57600080fd5b928a01925b82841015614e9e5785848f031215614e6b5760008081fd5b614e73613a89565b8435614e7e81613afe565b8152614e8b858d01614b79565b818d0152825292850192908a0190614e53565b845250505082870135915084821115614eb657600080fd5b614ec28a838501614b90565b81880152835250508284013582811115614edb57600080fd5b614ee788828601614c1d565b85830152506040830135935081841115614f0057600080fd5b614f0c87858501614d12565b60408201529695505050505050565b600082825180855260208086019550808260051b84010181860160005b84811015614fac57601f19868403018952815160a06001600160401b03808351168652868301518288880152614f7083880182613d07565b60408581015184169089015260608086015190931692880192909252506080928301519290950191909152509783019790830190600101614f38565b5090979650505050505050565b60006040808352614fcd6040840186614f1b565b83810360208581019190915285518083528682019282019060005b8181101561500d57845180518452840151848401529383019391850191600101614fe8565b509098975050505050505050565b634e487b7160e01b600052603260045260246000fd5b805160408084528151848201819052600092602091908201906060870190855b8181101561508857835180516001600160a01b031684528501516001600160e01b0316858401529284019291850191600101615051565b50508583015187820388850152805180835290840192506000918401905b808310156150e157835180516001600160401b031683528501516001600160e01b0316858301529284019260019290920191908501906150a6565b50979650505050505050565b602081526000610a7a6020830184615031565b60006020828403121561511257600080fd5b815161392381613b2f565b634e487b7160e01b600052601160045260246000fd5b6001600160401b038181168382160190808211156151535761515361511d565b5092915050565b60408152600061516d6040830185614f1b565b82810360208401526140db8185615031565b60006020828403121561519157600080fd5b81356001600160401b038111156151a757600080fd5b613313848285016145e4565b81810381811115610a7d57610a7d61511d565b634e487b7160e01b600052601260045260246000fd5b60006001600160401b03808416806151f6576151f66151c6565b92169190910692915050565b8082028115828204841417610a7d57610a7d61511d565b80518252600060206001600160401b0381840151168185015260408084015160a0604087015261524c60a0870182613d07565b9050606085015186820360608801526152658282613d07565b608087810151898303918a01919091528051808352908601935060009250908501905b808310156150e157835180516001600160a01b0316835286015186830152928501926001929092019190840190615288565b602081526000610a7a6020830184615219565b6080815260006152e06080830187615219565b61ffff9590951660208301525060408101929092526001600160a01b0316606090910152919050565b60008060006060848603121561531e57600080fd5b835161532981613b2f565b60208501519093506001600160401b0381111561534557600080fd5b8401601f8101861361535657600080fd5b8051615364613b8e82613b48565b81815287602083850101111561537957600080fd5b61538a826020830160208601613ce3565b809450505050604084015190509250925092565b6000602082840312156153b057600080fd5b815161392381613f5e565b600181811c908216806153cf57607f821691505b6020821081036153ef57634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115611225576000816000526020600020601f850160051c8101602086101561541e5750805b601f850160051c820191505b8181101561543d5782815560010161542a565b505050505050565b81516001600160401b0381111561545e5761545e6139e5565b6154728161546c84546153bb565b846153f5565b602080601f8311600181146154a7576000841561548f5750858301515b600019600386901b1c1916600185901b17855561543d565b600085815260208120601f198616915b828110156154d6578886015182559484019460019091019084016154b7565b50858210156154f45787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6000602080835283546001600160a01b038116602085015260ff8160a01c16151560408501526001600160401b038160a81c16606085015250600180850160808086015260008154615555816153bb565b8060a089015260c060018316600081146155765760018114615592576155c2565b60ff19841660c08b015260c083151560051b8b010194506155c2565b85600052602060002060005b848110156155b95781548c820185015290880190890161559e565b8b0160c0019550505b50929998505050505050505050565b80820180821115610a7d57610a7d61511d565b60ff8181168382160190811115610a7d57610a7d61511d565b8183823760009101908152919050565b828152606082602083013760800192915050565b60006001600160401b038084168061563b5761563b6151c6565b92169190910492915050565b60006020828403121561565957600080fd5b813561392381613f5e565b6000808335601e1984360301811261567b57600080fd5b8301803591506001600160401b0382111561569557600080fd5b602001915036819003821315613d9857600080fd5b60208101600583106156be576156be613f1b565b91905290565b60ff81811683821602908116908181146151535761515361511d565b600060a0820160ff881683526020878185015260a0604085015281875480845260c0860191508860005282600020935060005b818110156157385784546001600160a01b031683526001948501949284019201615713565b50508481036060860152865180825290820192508187019060005b818110156157785782516001600160a01b031685529383019391830191600101615753565b50505060ff851660808501525090505b9695505050505050565b60006001600160401b038086168352808516602084015250606060408301526140db6060830184613d07565b8281526040602082015260006133136040830184613d07565b6001600160401b03848116825283166020820152606081016133136040830184613f31565b84815261580c6020820185613f31565b6080604082015260006158226080830185613d07565b905082606083015295945050505050565b60006020828403121561584557600080fd5b815161392381613afe565b602081526000825161010080602085015261586f610120850183613d07565b9150602085015161588b60408601826001600160401b03169052565b5060408501516001600160a01b0381166060860152506060850151608085015260808501516158c560a08601826001600160a01b03169052565b5060a0850151601f19808685030160c08701526158e28483613d07565b935060c08701519150808685030160e08701526158ff8483613d07565b935060e08701519150808685030183870152506157888382613d07565b60006020828403121561592e57600080fd5b5051919050565b84815260006001600160401b038086166020840152808516604084015250608060608301526157886080830184613d07565b86815260c06020820152600061598060c0830188613d07565b6001600160a01b03969096166040830152506001600160401b039384166060820152608081019290925290911660a09091015292915050565b600082825180855260208086019550808260051b84010181860160005b84811015614fac57601f19868403018952815160a081518186526159fc82870182613d07565b9150508582015185820387870152615a148282613d07565b91505060408083015186830382880152615a2e8382613d07565b92505050606080830151818701525060808083015192508582038187015250615a578183613d07565b9a86019a94505050908301906001016159d6565b602081526000610a7a60208301846159b9565b60008282518085526020808601955060208260051b8401016020860160005b84811015614fac57601f19868403018952615ab9838351613d07565b98840198925090830190600101615a9d565b60008151808452602080850194506020840160005b8381101561406457815163ffffffff1687529582019590820190600101615ae0565b60608152600084518051606084015260208101516001600160401b0380821660808601528060408401511660a08601528060608401511660c08601528060808401511660e0860152505050602085015161014080610100850152615b6a6101a0850183613d07565b91506040870151605f198086850301610120870152615b898483613d07565b935060608901519150615ba6838701836001600160a01b03169052565b608089015161016087015260a0890151925080868503016101808701525050615bcf82826159b9565b9150508281036020840152615be48186615a7e565b905082810360408401526157888185615acb56fea164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CanOnlySelfCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"reportOnRamp\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"configOnRamp\",\"type\":\"bytes\"}],\"name\":\"CommitOnRampMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"actual\",\"type\":\"bytes32\"}],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ExecutionError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"ForkedChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enumMultiOCR3Base.InvalidConfigErrorType\",\"name\":\"errorType\",\"type\":\"uint8\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"got\",\"type\":\"uint256\"}],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidEVMAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"name\":\"InvalidInterval\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"newLimit\",\"type\":\"uint256\"}],\"name\":\"InvalidManualExecutionGasLimit\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"tokenIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"oldLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenGasOverride\",\"type\":\"uint256\"}],\"name\":\"InvalidManualExecutionTokenGasOverride\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"messageDestChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidMessageDestChainSelector\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"newState\",\"type\":\"uint8\"}],\"name\":\"InvalidNewState\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidOnRampUpdate\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRoot\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LeavesCannotBeEmpty\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"ManualExecutionGasAmountCountMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ManualExecutionGasLimitMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"ManualExecutionNotYetEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"errorReason\",\"type\":\"bytes\"}],\"name\":\"MessageValidationError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonUniqueSignatures\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"notPool\",\"type\":\"address\"}],\"name\":\"NotACompatiblePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OracleCannotBeZeroAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ReceiverError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountReleased\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePre\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePost\",\"type\":\"uint256\"}],\"name\":\"ReleaseOrMintBalanceMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"name\":\"RootAlreadyCommitted\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"RootNotCommitted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignatureVerificationDisabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignaturesOutOfRegistration\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"reportSourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"messageSourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainSelectorMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"StaleCommitReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"StaticConfigCannotBeChanged\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"TokenDataMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"TokenHandlingError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnexpectedTokenData\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"WrongMessageLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WrongNumberOfSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroChainSelectorNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"AlreadyAttempted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"indexed\":false,\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"}],\"name\":\"CommitReportAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"DynamicConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"messageHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"name\":\"ExecutionStateChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"RootRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"SkippedAlreadyExecutedMessage\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SkippedReportExecution\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"sourceConfig\",\"type\":\"tuple\"}],\"name\":\"SourceChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainSelectorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"}],\"name\":\"StaticConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigUpdates\",\"type\":\"tuple[]\"}],\"name\":\"applySourceChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"destTokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structClient.Any2EVMMessage\",\"name\":\"\",\"type\":\"tuple\"}],\"name\":\"ccipReceive\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"rawVs\",\"type\":\"bytes32\"}],\"name\":\"commit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"execute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"bytes[]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[]\"},{\"internalType\":\"uint32[]\",\"name\":\"tokenGasOverrides\",\"type\":\"uint32[]\"}],\"name\":\"executeSingleMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"getExecutionState\",\"outputs\":[{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLatestPriceSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"getMerkleRoot\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"getSourceChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"latestConfigDetails\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"n\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"}],\"internalType\":\"structMultiOCR3Base.ConfigInfo\",\"name\":\"configInfo\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfig\",\"name\":\"ocrConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage[]\",\"name\":\"messages\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[][]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[][]\"},{\"internalType\":\"bytes32[]\",\"name\":\"proofs\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"proofFlagBits\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.ExecutionReportSingleChain[]\",\"name\":\"reports\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"receiverExecutionGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint32[]\",\"name\":\"tokenGasOverrides\",\"type\":\"uint32[]\"}],\"internalType\":\"structOffRamp.GasLimitOverride[][]\",\"name\":\"gasLimitOverrides\",\"type\":\"tuple[][]\"}],\"name\":\"manuallyExecute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"setDynamicConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfigArgs[]\",\"name\":\"ocrConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"setOCR3Configs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x6101206040523480156200001257600080fd5b506040516200689b3803806200689b833981016040819052620000359162000806565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf81620001fa565b5050466080525060208301516001600160a01b03161580620000ec575060408301516001600160a01b0316155b8062000103575060608301516001600160a01b0316155b1562000122576040516342bcdf7f60e11b815260040160405180910390fd5b82516001600160401b03166000036200014e5760405163c656089560e01b815260040160405180910390fd5b82516001600160401b0390811660a052602080850180516001600160a01b0390811660c05260408088018051831660e0526060808a01805185166101005283518b519098168852945184169587019590955251821690850152905116908201527f683eb52ee924eb817377cfa8f41f238f4bb7a877da5267869dfffbad85f564d89060800160405180910390a1620001e682620002a5565b620001f1816200036d565b50505062000b8d565b336001600160a01b03821603620002545760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b0316620002ce576040516342bcdf7f60e11b815260040160405180910390fd5b805160048054602080850180516001600160a01b039586166001600160c01b03199094168417600160a01b63ffffffff928316021790945560408087018051600580546001600160a01b031916918916919091179055815194855291519094169183019190915251909216908201527fa1c15688cb2c24508e158f6942b9276c6f3028a85e1af8cf3fff0c3ff3d5fc8d9060600160405180910390a150565b60005b8151811015620005ba57600082828151811062000391576200039162000943565b60200260200101519050600081602001519050806001600160401b0316600003620003cf5760405163c656089560e01b815260040160405180910390fd5b81516001600160a01b0316620003f8576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160401b03811660009081526006602052604090206060830151600182018054620004269062000959565b905060000362000489578154600160a81b600160e81b031916600160a81b1782556040516001600160401b03841681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1620004c8565b8154600160a81b90046001600160401b0316600114620004c857604051632105803760e11b81526001600160401b038416600482015260240162000083565b80511580620004fe5750604080516000602082015201604051602081830303815290604052805190602001208180519060200120145b156200051d576040516342bcdf7f60e11b815260040160405180910390fd5b600182016200052d8282620009ea565b50604080850151835486516001600160a01b03166001600160a01b0319921515600160a01b02929092166001600160a81b031990911617178355516001600160401b038416907f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b90620005a290859062000ab6565b60405180910390a25050505080600101905062000370565b5050565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b0381118282101715620005f957620005f9620005be565b60405290565b604051601f8201601f191681016001600160401b03811182821017156200062a576200062a620005be565b604052919050565b80516001600160401b03811681146200064a57600080fd5b919050565b6001600160a01b03811681146200066557600080fd5b50565b6000601f83601f8401126200067c57600080fd5b825160206001600160401b03808311156200069b576200069b620005be565b8260051b620006ac838201620005ff565b9384528681018301938381019089861115620006c757600080fd5b84890192505b85831015620007f957825184811115620006e75760008081fd5b89016080601f19828d038101821315620007015760008081fd5b6200070b620005d4565b888401516200071a816200064f565b815260406200072b85820162000632565b8a8301526060808601518015158114620007455760008081fd5b838301529385015193898511156200075d5760008081fd5b84860195508f603f8701126200077557600094508485fd5b8a8601519450898511156200078e576200078e620005be565b6200079f8b858f88011601620005ff565b93508484528f82868801011115620007b75760008081fd5b60005b85811015620007d7578681018301518582018d01528b01620007ba565b5060009484018b019490945250918201528352509184019190840190620006cd565b9998505050505050505050565b60008060008385036101008112156200081e57600080fd5b60808112156200082d57600080fd5b62000837620005d4565b620008428662000632565b8152602086015162000854816200064f565b6020820152604086015162000869816200064f565b604082015260608601516200087e816200064f565b606082810191909152909450607f19820112156200089b57600080fd5b50604051606081016001600160401b038082118383101715620008c257620008c2620005be565b8160405260808701519150620008d8826200064f565b90825260a08601519063ffffffff82168214620008f457600080fd5b81602084015260c087015191506200090c826200064f565b6040830182905260e0870151929450808311156200092957600080fd5b5050620009398682870162000668565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b600181811c908216806200096e57607f821691505b6020821081036200098f57634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115620009e5576000816000526020600020601f850160051c81016020861015620009c05750805b601f850160051c820191505b81811015620009e157828155600101620009cc565b5050505b505050565b81516001600160401b0381111562000a065762000a06620005be565b62000a1e8162000a17845462000959565b8462000995565b602080601f83116001811462000a56576000841562000a3d5750858301515b600019600386901b1c1916600185901b178555620009e1565b600085815260208120601f198616915b8281101562000a875788860151825594840194600190910190840162000a66565b508582101562000aa65787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b602080825282546001600160a01b0381168383015260a081901c60ff161515604084015260a81c6001600160401b0316606083015260808083015260018084018054600093929190849062000b0b8162000959565b8060a089015260c0600183166000811462000b2f576001811462000b4c5762000b7e565b60ff19841660c08b015260c083151560051b8b0101945062000b7e565b85600052602060002060005b8481101562000b755781548c820185015290880190890162000b58565b8b0160c0019550505b50929998505050505050505050565b60805160a05160c05160e05161010051615c9862000c036000396000818161022c01526129260152600081816101fd0152612bf80152600081816101ce01528181610552015281816106ff015261236a01526000818161019f01526125a9015260008181611d920152611dc50152615c986000f3fe608060405234801561001057600080fd5b50600436106101515760003560e01c806379ba5097116100cd578063d434969111610081578063e9d68a8e11610066578063e9d68a8e146104bc578063f2fde38b146104dc578063f716f99f146104ef57600080fd5b8063d434969114610496578063e62653f5146104a957600080fd5b80638da5cb5b116100b25780638da5cb5b14610417578063c673e58414610432578063ccd37ba31461045257600080fd5b806379ba50971461040157806385572ffb1461040957600080fd5b8063311cd513116101245780635e36480c116101095780635e36480c1461033c5780636f9e320f1461035c5780637437ff9f1461036f57600080fd5b8063311cd5131461030e5780633f4b04aa1461032157600080fd5b806304666f9c1461015657806306285c691461016b578063181f5a77146102b25780632d04ab76146102fb575b600080fd5b610169610164366004613bbf565b610502565b005b61025c60408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160401b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316815250905090565b6040516102a9919081516001600160401b031681526020808301516001600160a01b0390811691830191909152604080840151821690830152606092830151169181019190915260800190565b60405180910390f35b6102ee6040518060400160405280601181526020017f4f666652616d7020312e362e302d64657600000000000000000000000000000081525081565b6040516102a99190613d2d565b610169610309366004613ddd565b610516565b61016961031c366004613e8f565b610a12565b6009546040516001600160401b0390911681526020016102a9565b61034f61034a366004613ee2565b610a7b565b6040516102a99190613f3f565b61016961036a366004613f6a565b610ad0565b6103cb604080516060810182526000808252602082018190529181019190915250604080516060810182526004546001600160a01b038082168352600160a01b90910463ffffffff166020830152600554169181019190915290565b6040805182516001600160a01b03908116825260208085015163ffffffff169083015292820151909216908201526060016102a9565b610169610ae1565b610169610151366004613fbe565b6000546040516001600160a01b0390911681526020016102a9565b610445610440366004614009565b610b92565b6040516102a99190614069565b6104886104603660046140de565b6001600160401b03919091166000908152600860209081526040808320938352929052205490565b6040519081526020016102a9565b6101696104a436600461437a565b610cf0565b6101696104b7366004614702565b610fd0565b6104cf6104ca366004614949565b611277565b6040516102a99190614964565b6101696104ea3660046149b1565b611383565b6101696104fd366004614a36565b611394565b61050a6113d6565b61051381611432565b50565b600061052487890189614d8b565b602081015151909150156105b6576020810151604080830151905162ccd5af60e81b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169263ccd5af009261058592600401614fb3565b60006040518083038186803b15801561059d57600080fd5b505afa1580156105b1573d6000803e3d6000fd5b505050505b805151511515806105cc57508051602001515115155b156106985760095460208a0135906001600160401b0380831691161015610670576009805467ffffffffffffffff19166001600160401b038316179055600480548351604051633937306f60e01b81526001600160a01b0390921692633937306f926106399291016150e7565b600060405180830381600087803b15801561065357600080fd5b505af1158015610667573d6000803e3d6000fd5b50505050610696565b81602001515160000361069657604051632261116760e01b815260040160405180910390fd5b505b60005b816020015151811015610953576000826020015182815181106106c0576106c0615015565b60209081029190910101518051604051632cbc26bb60e01b815267ffffffffffffffff60801b608083901b166004820152919250906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632cbc26bb90602401602060405180830381865afa158015610746573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061076a91906150fa565b1561079857604051637edeb53960e11b81526001600160401b03821660048201526024015b60405180910390fd5b60006107a382611685565b9050806001016040516107b69190615151565b6040518091039020836020015180519060200120146107f35782602001518160010160405163b80d8fa960e01b815260040161078f929190615244565b60408301518154600160a81b90046001600160401b039081169116141580610834575082606001516001600160401b031683604001516001600160401b0316115b1561087957825160408085015160608601519151636af0786b60e11b81526001600160401b03938416600482015290831660248201529116604482015260640161078f565b60808301518061089c5760405163504570e360e01b815260040160405180910390fd5b83516001600160401b03166000908152600860209081526040808320848452909152902054156108f45783516040516332cf0cbf60e01b81526001600160401b0390911660048201526024810182905260440161078f565b606084015161090490600161527f565b825467ffffffffffffffff60a81b1916600160a81b6001600160401b0392831602179092559251166000908152600860209081526040808320948352939052919091204290555060010161069b565b50602081015181516040517f35c02761bcd3ef995c6a601a1981f4ed3934dcbe5041e24e286c89f5531d17e49261098b9290916152a6565b60405180910390a1610a0760008a8a8a8a8a8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808e0282810182019093528d82529093508d92508c9182918501908490808284376000920191909152508b92506116d1915050565b505050505050505050565b610a52610a21828401846152cb565b6040805160008082526020820190925290610a4c565b6060815260200190600190039081610a375790505b506119ca565b604080516000808252602082019092529050610a756001858585858660006116d1565b50505050565b6000610a89600160046152ff565b6002610a96608085615328565b6001600160401b0316610aa9919061534e565b610ab38585611a8c565b901c166003811115610ac757610ac7613f15565b90505b92915050565b610ad86113d6565b61051381611ad1565b6001546001600160a01b03163314610b3b5760405162461bcd60e51b815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e657200000000000000000000604482015260640161078f565b60008054336001600160a01b0319808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610bd56040805160e081019091526000606082018181526080830182905260a0830182905260c08301919091528190815260200160608152602001606081525090565b60ff808316600090815260026020818152604092839020835160e081018552815460608201908152600183015480881660808401526101008104881660a0840152620100009004909616151560c082015294855291820180548451818402810184019095528085529293858301939092830182828015610c7e57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610c60575b5050505050815260200160038201805480602002602001604051908101604052809291908181526020018280548015610ce057602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610cc2575b5050505050815250509050919050565b333014610d10576040516306e34e6560e31b815260040160405180910390fd5b6040805160008082526020820190925281610d4d565b6040805180820190915260008082526020820152815260200190600190039081610d265790505b5060a08701515190915015610d8357610d808660a001518760200151886060015189600001516020015189898989611bb0565b90505b6040805160a081018252875151815287516020908101516001600160401b031681830152808901518351600094840192610dbe929101613d2d565b60408051601f19818403018152918152908252898101516020830152018390526005549091506001600160a01b03168015610e99576040516308d450a160e01b81526001600160a01b038216906308d450a190610e1f908590600401615406565b600060405180830381600087803b158015610e3957600080fd5b505af1925050508015610e4a575060015b610e99573d808015610e78576040519150601f19603f3d011682016040523d82523d6000602084013e610e7d565b606091505b50806040516309c2532560e01b815260040161078f9190613d2d565b604088015151158015610eae57506080880151155b80610ec5575060608801516001600160a01b03163b155b80610eec57506060880151610eea906001600160a01b03166385572ffb60e01b611d73565b155b15610ef957505050610fc9565b87516020908101516001600160401b03166000908152600690915260408082205460808b015160608c01519251633cf9798360e01b815284936001600160a01b0390931692633cf9798392610f579289926113889291600401615419565b6000604051808303816000875af1158015610f76573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610f9e9190810190615455565b509150915081610fc357806040516302a35ba360e21b815260040161078f9190613d2d565b50505050505b5050505050565b610fd8611d8f565b815181518114610ffb576040516320f8fd5960e21b815260040160405180910390fd5b60005b8181101561126757600084828151811061101a5761101a615015565b6020026020010151905060008160200151519050600085848151811061104257611042615015565b602002602001015190508051821461106d576040516320f8fd5960e21b815260040160405180910390fd5b60005b8281101561125857600082828151811061108c5761108c615015565b60200260200101516000015190506000856020015183815181106110b2576110b2615015565b6020026020010151905081600014611106578060800151821015611106578551815151604051633a98d46360e11b81526001600160401b03909216600483015260248201526044810183905260640161078f565b83838151811061111857611118615015565b602002602001015160200151518160a00151511461116557805180516060909101516040516370a193fd60e01b815260048101929092526001600160401b0316602482015260440161078f565b60005b8160a001515181101561124a57600085858151811061118957611189615015565b60200260200101516020015182815181106111a6576111a6615015565b602002602001015163ffffffff169050806000146112415760008360a0015183815181106111d6576111d6615015565b6020026020010151608001518060200190518101906111f591906154ea565b90508063ffffffff1682101561123f578351516040516348e617b360e01b815260048101919091526024810184905263ffffffff821660448201526064810183905260840161078f565b505b50600101611168565b505050806001019050611070565b50505050806001019050610ffe565b5061127283836119ca565b505050565b60408051608080820183526000808352602080840182905283850182905260608085018190526001600160401b03878116845260068352928690208651948501875280546001600160a01b0381168652600160a01b810460ff16151593860193909352600160a81b90920490921694830194909452600184018054939492939184019161130390615117565b80601f016020809104026020016040519081016040528092919081815260200182805461132f90615117565b8015610ce05780601f1061135157610100808354040283529160200191610ce0565b820191906000526020600020905b81548152906001019060200180831161135f57505050919092525091949350505050565b61138b6113d6565b61051381611df7565b61139c6113d6565b60005b81518110156113d2576113ca8282815181106113bd576113bd615015565b6020026020010151611ea0565b60010161139f565b5050565b6000546001600160a01b031633146114305760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640161078f565b565b60005b81518110156113d257600082828151811061145257611452615015565b60200260200101519050600081602001519050806001600160401b031660000361148f5760405163c656089560e01b815260040160405180910390fd5b81516001600160a01b03166114b7576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160401b038116600090815260066020526040902060608301516001820180546114e390615117565b905060000361154557815467ffffffffffffffff60a81b1916600160a81b1782556040516001600160401b03841681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1611582565b8154600160a81b90046001600160401b031660011461158257604051632105803760e11b81526001600160401b038416600482015260240161078f565b805115806115b75750604080516000602082015201604051602081830303815290604052805190602001208180519060200120145b156115d5576040516342bcdf7f60e11b815260040160405180910390fd5b600182016115e38282615557565b50604080850151835486516001600160a01b03166001600160a01b0319921515600160a01b02929092167fffffffffffffffffffffff00000000000000000000000000000000000000000090911617178355516001600160401b038416907f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b9061166e908590615616565b60405180910390a250505050806001019050611435565b6001600160401b03811660009081526006602052604081208054600160a01b900460ff16610aca5760405163ed053c5960e01b81526001600160401b038416600482015260240161078f565b60ff878116600090815260026020908152604080832081516080810183528154815260019091015480861693820193909352610100830485169181019190915262010000909104909216151560608301528735906117308760a4615664565b905082606001511561177857845161174990602061534e565b865161175690602061534e565b6117619060a0615664565b61176b9190615664565b6117759082615664565b90505b3681146117a157604051638e1192e160e01b81526004810182905236602482015260440161078f565b50815181146117d05781516040516324f7d61360e21b815260048101919091526024810182905260440161078f565b6117d8611d8f565b60ff808a166000908152600360209081526040808320338452825280832081518083019092528054808616835293949193909284019161010090910416600281111561182657611826613f15565b600281111561183757611837613f15565b905250905060028160200151600281111561185457611854613f15565b1480156118a85750600260008b60ff1660ff168152602001908152602001600020600301816000015160ff168154811061189057611890615015565b6000918252602090912001546001600160a01b031633145b6118c557604051631b41e11d60e31b815260040160405180910390fd5b508160600151156119755760208201516118e0906001615677565b60ff16855114611903576040516371253a2560e01b815260040160405180910390fd5b83518551146119255760405163a75d88af60e01b815260040160405180910390fd5b60008787604051611937929190615690565b60405190819003812061194e918b906020016156a0565b6040516020818303038152906040528051906020012090506119738a8288888861217f565b505b6040805182815260208a8101356001600160401b03169082015260ff8b16917f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef0910160405180910390a2505050505050505050565b81516000036119eb5760405162bf199760e01b815260040160405180910390fd5b80516040805160008082526020820190925291159181611a2e565b604080518082019091526000815260606020820152815260200190600190039081611a065790505b50905060005b8451811015610fc957611a84858281518110611a5257611a52615015565b602002602001015184611a7e57858381518110611a7157611a71615015565b602002602001015161233c565b8361233c565b600101611a34565b6001600160401b038216600090815260076020526040812081611ab06080856156b4565b6001600160401b031681526020810191909152604001600020549392505050565b80516001600160a01b0316611af9576040516342bcdf7f60e11b815260040160405180910390fd5b805160048054602080850180516001600160a01b039586167fffffffffffffffff0000000000000000000000000000000000000000000000009094168417600160a01b63ffffffff928316021790945560408087018051600580546001600160a01b031916918916919091179055815194855291519094169183019190915251909216908201527fa1c15688cb2c24508e158f6942b9276c6f3028a85e1af8cf3fff0c3ff3d5fc8d9060600160405180910390a150565b606088516001600160401b03811115611bcb57611bcb6139df565b604051908082528060200260200182016040528015611c1057816020015b6040805180820190915260008082526020820152815260200190600190039081611be95790505b509050811560005b8a51811015611d655781611cc257848482818110611c3857611c38615015565b9050602002016020810190611c4d91906156da565b63ffffffff1615611cc257848482818110611c6a57611c6a615015565b9050602002016020810190611c7f91906156da565b6040805163ffffffff9092166020830152016040516020818303038152906040528b8281518110611cb257611cb2615015565b6020026020010151608001819052505b611d408b8281518110611cd757611cd7615015565b60200260200101518b8b8b8b8b87818110611cf457611cf4615015565b9050602002810190611d0691906156f7565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612bb092505050565b838281518110611d5257611d52615015565b6020908102919091010152600101611c18565b505098975050505050505050565b6000611d7e83612eae565b8015610ac75750610ac78383612ef9565b467f00000000000000000000000000000000000000000000000000000000000000001461143057604051630f01ce8560e01b81527f0000000000000000000000000000000000000000000000000000000000000000600482015246602482015260440161078f565b336001600160a01b03821603611e4f5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161078f565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b806040015160ff16600003611ecb576000604051631b3fab5160e11b815260040161078f919061573d565b60208082015160ff80821660009081526002909352604083206001810154929390928392169003611f1c576060840151600182018054911515620100000262ff000019909216919091179055611f58565b6060840151600182015460ff6201000090910416151590151514611f58576040516321fd80df60e21b815260ff8416600482015260240161078f565b60a084015180516101001015611f84576001604051631b3fab5160e11b815260040161078f919061573d565b611fea8484600301805480602002602001604051908101604052809291908181526020018280548015611fe057602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611fc2575b5050505050612f9b565b8460600151156120f4576120588484600201805480602002602001604051908101604052809291908181526020018280548015611fe0576020028201919060005260206000209081546001600160a01b03168152600190910190602001808311611fc2575050505050612f9b565b608085015180516101001015612084576002604051631b3fab5160e11b815260040161078f919061573d565b6040860151612094906003615757565b60ff168151116120ba576003604051631b3fab5160e11b815260040161078f919061573d565b805160018401805461ff00191661010060ff8416021790556120e59060028601906020840190613965565b506120f285826001613004565b505b61210084826002613004565b80516121159060038501906020840190613965565b5060408581015160018401805460ff191660ff8316179055865180855560a088015192517fab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f5479361216e9389939260028a01929190615773565b60405180910390a1610fc98461315f565b8251600090815b818110156123325760006001888684602081106121a5576121a5615015565b6121b291901a601b615677565b8985815181106121c4576121c4615015565b60200260200101518986815181106121de576121de615015565b60200260200101516040516000815260200160405260405161221c949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa15801561223e573d6000803e3d6000fd5b505060408051601f1981015160ff808e166000908152600360209081528582206001600160a01b0385168352815285822085870190965285548084168652939750909550929392840191610100900416600281111561229f5761229f613f15565b60028111156122b0576122b0613f15565b90525090506001816020015160028111156122cd576122cd613f15565b146122eb57604051636518c33d60e11b815260040160405180910390fd5b8051600160ff9091161b85161561231557604051633d9ef1f160e21b815260040160405180910390fd5b806000015160ff166001901b851794505050806001019050612186565b5050505050505050565b81518151604051632cbc26bb60e01b8152608083901b67ffffffffffffffff60801b166004820152901515907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632cbc26bb90602401602060405180830381865afa1580156123b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123dd91906150fa565b1561244e57801561240c57604051637edeb53960e11b81526001600160401b038316600482015260240161078f565b6040516001600160401b03831681527faab522ed53d887e56ed53dd37398a01aeef6a58e0fa77c2173beb9512d8949339060200160405180910390a150505050565b600061245983611685565b600101805461246790615117565b80601f016020809104026020016040519081016040528092919081815260200182805461249390615117565b80156124e05780601f106124b5576101008083540402835291602001916124e0565b820191906000526020600020905b8154815290600101906020018083116124c357829003601f168201915b5050506020880151519293505050600081900361250f5760405162bf199760e01b815260040160405180910390fd5b8560400151518114612534576040516357e0e08360e01b815260040160405180910390fd5b6000816001600160401b0381111561254e5761254e6139df565b604051908082528060200260200182016040528015612577578160200160208202803683370190505b50905060005b828110156126985760008860200151828151811061259d5761259d615015565b602002602001015190507f00000000000000000000000000000000000000000000000000000000000000006001600160401b03168160000151604001516001600160401b0316146126145780516040908101519051631c21951160e11b81526001600160401b03909116600482015260240161078f565b866001600160401b03168160000151602001516001600160401b03161461266857805160200151604051636c95f1eb60e01b81526001600160401b03808a166004830152909116602482015260440161078f565b61267281866131b6565b83838151811061268457612684615015565b60209081029190910101525060010161257d565b5060006126af86838a606001518b608001516132d8565b9050806000036126dd57604051633ee8bd3f60e11b81526001600160401b038716600482015260240161078f565b60005b83811015610a075760005a905060008a60200151838151811061270557612705615015565b6020026020010151905060006127238a836000015160600151610a7b565b9050600081600381111561273957612739613f15565b14806127565750600381600381111561275457612754613f15565b145b6127ac57815160600151604080516001600160401b03808e16825290921660208301527f3b575419319662b2a6f5e2467d84521517a3382b908eb3d557bb3fdb0c50e23c910160405180910390a1505050612ba8565b6060891561288b578b85815181106127c6576127c6615015565b6020908102919091018101510151600454909150600090600160a01b900463ffffffff166127f488426152ff565b11905080806128145750600383600381111561281257612812613f15565b145b61283c576040516354e7e43160e11b81526001600160401b038d16600482015260240161078f565b8c868151811061284e5761284e615015565b602002602001015160000151600014612885578c868151811061287357612873615015565b60209081029190910101515160808501525b506128f7565b600082600381111561289f5761289f613f15565b146128f757825160600151604080516001600160401b03808f16825290921660208301527f3ef2a99c550a751d4b0b261268f05a803dfb049ab43616a1ffb388f61fe65120910160405180910390a150505050612ba8565b8251608001516001600160401b0316156129d057600082600381111561291f5761291f613f15565b036129d0577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e0e03cae8c85600001516080015186602001516040518463ffffffff1660e01b815260040161298093929190615825565b6020604051808303816000875af115801561299f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129c391906150fa565b6129d05750505050612ba8565b60008d6040015186815181106129e8576129e8615015565b6020026020010151905080518460a001515114612a3257835160600151604051631cfe6d8b60e01b81526001600160401b03808f166004830152909116602482015260440161078f565b612a468c8560000151606001516001613315565b600080612a548684866133ba565b91509150612a6b8e87600001516060015184613315565b8c15612ac2576003826003811115612a8557612a85613f15565b03612ac2576000856003811115612a9e57612a9e613f15565b14612ac257855151604051632b11b8d960e01b815261078f91908390600401615851565b6002826003811115612ad657612ad6613f15565b14612b1b576003826003811115612aef57612aef613f15565b14612b1b578d866000015160600151836040516349362d1f60e11b815260040161078f9392919061586a565b8560000151600001518660000151606001516001600160401b03168f6001600160401b03167f05665fe9ad095383d018353f4cbcba77e84db27dd215081bbf7cdf9ae6fbe48b8d8c81518110612b7357612b73615015565b602002602001015186865a612b88908f6152ff565b604051612b98949392919061588f565b60405180910390a4505050505050505b6001016126e0565b60408051808201909152600080825260208201526000612bd3876020015161346e565b60405163bbe4f6db60e01b81526001600160a01b0380831660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063bbe4f6db90602401602060405180830381865afa158015612c3f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c6391906158c6565b90506001600160a01b0381161580612c925750612c906001600160a01b03821663aff2afbf60e01b611d73565b155b15612cbb5760405163ae9b4ce960e01b81526001600160a01b038216600482015260240161078f565b600080612ce688858c60800151806020019051810190612cdb91906154ea565b63ffffffff166134e2565b915091506000806000612d996040518061010001604052808e81526020018c6001600160401b031681526020018d6001600160a01b031681526020018f606001518152602001896001600160a01b031681526020018f6000015181526020018f6040015181526020018b815250604051602401612d6391906158e3565b60408051601f198184030181529190526020810180516001600160e01b0316633907753760e01b179052878661138860846135c5565b92509250925082612dbf578160405163e1cd550960e01b815260040161078f9190613d2d565b8151602014612dee578151604051631e3be00960e21b815260206004820152602481019190915260440161078f565b600082806020019051810190612e0491906159af565b9050866001600160a01b03168c6001600160a01b031614612e80576000612e358d8a612e30868a6152ff565b6134e2565b50905086811080612e4f575081612e4c88836152ff565b14155b15612e7e5760405163a966e21f60e01b815260048101839052602481018890526044810182905260640161078f565b505b604080518082019091526001600160a01b039098168852602088015250949550505050505095945050505050565b6000612ec1826301ffc9a760e01b612ef9565b8015610aca5750612ef2827fffffffff00000000000000000000000000000000000000000000000000000000612ef9565b1592915050565b6040517fffffffff0000000000000000000000000000000000000000000000000000000082166024820152600090819060440160408051601f19818403018152919052602080820180516001600160e01b03166301ffc9a760e01b178152825192935060009283928392909183918a617530fa92503d91506000519050828015612f84575060208210155b8015612f905750600081115b979650505050505050565b60005b81518110156112725760ff831660009081526003602052604081208351909190849084908110612fd057612fd0615015565b6020908102919091018101516001600160a01b03168252810191909152604001600020805461ffff19169055600101612f9e565b60005b8251811015610a7557600083828151811061302457613024615015565b602002602001015190506000600281111561304157613041613f15565b60ff80871660009081526003602090815260408083206001600160a01b0387168452909152902054610100900416600281111561308057613080613f15565b146130a1576004604051631b3fab5160e11b815260040161078f919061573d565b6001600160a01b0381166130c85760405163d6c62c9b60e01b815260040160405180910390fd5b60405180604001604052808360ff1681526020018460028111156130ee576130ee613f15565b905260ff80871660009081526003602090815260408083206001600160a01b0387168452825290912083518154931660ff198416811782559184015190929091839161ffff19161761010083600281111561314b5761314b613f15565b021790555090505050806001019050613007565b60ff81166105135760ff808216600090815260026020526040902060010154620100009004166131a257604051631e8ed32560e21b815260040160405180910390fd5b6009805467ffffffffffffffff1916905550565b8151602080820151604092830151925160009384936131fc937f2425b0b9f9054c76ff151b0a175b18f37a4a4e82013a72e9f15c9caa095ed21f939092918891016159c8565b60408051601f1981840301815290829052805160209182012086518051888401516060808b0151908401516080808d0151950151959761324597949693959294919391016159fa565b604051602081830303815290604052805190602001208560400151805190602001208660a0015160405160200161327c9190615afe565b60408051601f198184030181528282528051602091820120908301969096528101939093526060830191909152608082015260a081019190915260c0015b60405160208183030381529060405280519060200120905092915050565b6000806132e685858561369f565b6001600160401b038716600090815260086020908152604080832093835292905220549150505b949350505050565b60006002613324608085615328565b6001600160401b0316613337919061534e565b905060006133458585611a8c565b905081613354600160046152ff565b901b19168183600381111561336b5761336b613f15565b6001600160401b03871660009081526007602052604081209190921b929092179182916133996080886156b4565b6001600160401b031681526020810191909152604001600020555050505050565b60405163d434969160e01b8152600090606090309063d4349691906133e790889088908890600401615b95565b600060405180830381600087803b15801561340157600080fd5b505af1925050508015613412575060015b613451573d808015613440576040519150601f19603f3d011682016040523d82523d6000602084013e613445565b606091505b50600392509050613466565b50506040805160208101909152600081526002905b935093915050565b60008151602014613494578160405163046b337b60e51b815260040161078f9190613d2d565b6000828060200190518101906134aa91906159af565b90506001600160a01b038111806134c2575061040081105b15610aca578260405163046b337b60e51b815260040161078f9190613d2d565b60008060008060006135438860405160240161350d91906001600160a01b0391909116815260200190565b60408051601f198184030181529190526020810180516001600160e01b03166370a0823160e01b179052888861138860846135c5565b92509250925082613569578160405163e1cd550960e01b815260040161078f9190613d2d565b6020825114613598578151604051631e3be00960e21b815260206004820152602481019190915260440161078f565b818060200190518101906135ac91906159af565b6135b682886152ff565b94509450505050935093915050565b6000606060008361ffff166001600160401b038111156135e7576135e76139df565b6040519080825280601f01601f191660200182016040528015613611576020820181803683370190505b509150863b61362b5763030ed58f60e21b60005260046000fd5b5a8581101561364557632be8ca8b60e21b60005260046000fd5b8590036040810481038710613665576337c3be2960e01b60005260046000fd5b505a6000808a5160208c0160008c8cf193505a900390503d848111156136885750835b808352806000602085013e50955095509592505050565b82518251600091908183036136c757604051630469ac9960e21b815260040160405180910390fd5b61010182118015906136db57506101018111155b6136f8576040516309bde33960e01b815260040160405180910390fd5b60001982820101610100811115613722576040516309bde33960e01b815260040160405180910390fd5b8060000361374f578660008151811061373d5761373d615015565b6020026020010151935050505061391d565b6000816001600160401b03811115613769576137696139df565b604051908082528060200260200182016040528015613792578160200160208202803683370190505b50905060008080805b858110156138bc5760006001821b8b8116036137f657888510156137df578c5160018601958e9181106137d0576137d0615015565b60200260200101519050613818565b85516001850194879181106137d0576137d0615015565b8b5160018401938d91811061380d5761380d615015565b602002602001015190505b600089861015613848578d5160018701968f91811061383957613839615015565b6020026020010151905061386a565b865160018601958891811061385f5761385f615015565b602002602001015190505b8285111561388b576040516309bde33960e01b815260040160405180910390fd5b6138958282613924565b8784815181106138a7576138a7615015565b6020908102919091010152505060010161379b565b5060018503821480156138ce57508683145b80156138d957508581145b6138f6576040516309bde33960e01b815260040160405180910390fd5b83600186038151811061390b5761390b615015565b60200260200101519750505050505050505b9392505050565b600081831061393c576139378284613942565b610ac7565b610ac783835b6040805160016020820152908101839052606081018290526000906080016132ba565b8280548282559060005260206000209081019282156139ba579160200282015b828111156139ba57825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190613985565b506139c69291506139ca565b5090565b5b808211156139c657600081556001016139cb565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b0381118282101715613a1757613a176139df565b60405290565b604051606081016001600160401b0381118282101715613a1757613a176139df565b60405160a081016001600160401b0381118282101715613a1757613a176139df565b60405160c081016001600160401b0381118282101715613a1757613a176139df565b604080519081016001600160401b0381118282101715613a1757613a176139df565b604051601f8201601f191681016001600160401b0381118282101715613acd57613acd6139df565b604052919050565b60006001600160401b03821115613aee57613aee6139df565b5060051b60200190565b6001600160a01b038116811461051357600080fd5b80356001600160401b0381168114613b2457600080fd5b919050565b801515811461051357600080fd5b8035613b2481613b29565b60006001600160401b03821115613b5b57613b5b6139df565b50601f01601f191660200190565b600082601f830112613b7a57600080fd5b8135613b8d613b8882613b42565b613aa5565b818152846020838601011115613ba257600080fd5b816020850160208301376000918101602001919091529392505050565b60006020808385031215613bd257600080fd5b82356001600160401b0380821115613be957600080fd5b818501915085601f830112613bfd57600080fd5b8135613c0b613b8882613ad5565b81815260059190911b83018401908481019088831115613c2a57600080fd5b8585015b83811015613cd057803585811115613c465760008081fd5b86016080818c03601f1901811315613c5e5760008081fd5b613c666139f5565b89830135613c7381613af8565b81526040613c82848201613b0d565b8b830152606080850135613c9581613b29565b83830152928401359289841115613cae57600091508182fd5b613cbc8f8d86880101613b69565b908301525085525050918601918601613c2e565b5098975050505050505050565b60005b83811015613cf8578181015183820152602001613ce0565b50506000910152565b60008151808452613d19816020860160208601613cdd565b601f01601f19169290920160200192915050565b602081526000610ac76020830184613d01565b8060608101831015610aca57600080fd5b60008083601f840112613d6357600080fd5b5081356001600160401b03811115613d7a57600080fd5b602083019150836020828501011115613d9257600080fd5b9250929050565b60008083601f840112613dab57600080fd5b5081356001600160401b03811115613dc257600080fd5b6020830191508360208260051b8501011115613d9257600080fd5b60008060008060008060008060e0898b031215613df957600080fd5b613e038a8a613d40565b975060608901356001600160401b0380821115613e1f57600080fd5b613e2b8c838d01613d51565b909950975060808b0135915080821115613e4457600080fd5b613e508c838d01613d99565b909750955060a08b0135915080821115613e6957600080fd5b50613e768b828c01613d99565b999c989b50969995989497949560c00135949350505050565b600080600060808486031215613ea457600080fd5b613eae8585613d40565b925060608401356001600160401b03811115613ec957600080fd5b613ed586828701613d51565b9497909650939450505050565b60008060408385031215613ef557600080fd5b613efe83613b0d565b9150613f0c60208401613b0d565b90509250929050565b634e487b7160e01b600052602160045260246000fd5b60048110613f3b57613f3b613f15565b9052565b60208101610aca8284613f2b565b8035613b2481613af8565b63ffffffff8116811461051357600080fd5b600060608284031215613f7c57600080fd5b613f84613a1d565b8235613f8f81613af8565b81526020830135613f9f81613f58565b60208201526040830135613fb281613af8565b60408201529392505050565b600060208284031215613fd057600080fd5b81356001600160401b03811115613fe657600080fd5b820160a0818503121561391d57600080fd5b803560ff81168114613b2457600080fd5b60006020828403121561401b57600080fd5b610ac782613ff8565b60008151808452602080850194506020840160005b8381101561405e5781516001600160a01b031687529582019590820190600101614039565b509495945050505050565b60208152600082518051602084015260ff602082015116604084015260ff604082015116606084015260608101511515608084015250602083015160c060a08401526140b860e0840182614024565b90506040840151601f198483030160c08501526140d58282614024565b95945050505050565b600080604083850312156140f157600080fd5b6140fa83613b0d565b946020939093013593505050565b600060a0828403121561411a57600080fd5b614122613a3f565b90508135815261413460208301613b0d565b602082015261414560408301613b0d565b604082015261415660608301613b0d565b606082015261416760808301613b0d565b608082015292915050565b600082601f83011261418357600080fd5b81356020614193613b8883613ad5565b82815260059290921b840181019181810190868411156141b257600080fd5b8286015b848110156142ac5780356001600160401b03808211156141d65760008081fd5b9088019060a0828b03601f19018113156141f05760008081fd5b6141f8613a3f565b878401358381111561420a5760008081fd5b6142188d8a83880101613b69565b8252506040808501358481111561422f5760008081fd5b61423d8e8b83890101613b69565b8a84015250606080860135858111156142565760008081fd5b6142648f8c838a0101613b69565b8385015250608091508186013581840152508285013592508383111561428a5760008081fd5b6142988d8a85880101613b69565b9082015286525050509183019183016141b6565b509695505050505050565b600061014082840312156142ca57600080fd5b6142d2613a61565b90506142de8383614108565b815260a08201356001600160401b03808211156142fa57600080fd5b61430685838601613b69565b602084015260c084013591508082111561431f57600080fd5b61432b85838601613b69565b604084015261433c60e08501613f4d565b6060840152610100840135608084015261012084013591508082111561436157600080fd5b5061436e84828501614172565b60a08301525092915050565b60008060008060006060868803121561439257600080fd5b85356001600160401b03808211156143a957600080fd5b6143b589838a016142b7565b965060208801359150808211156143cb57600080fd5b6143d789838a01613d99565b909650945060408801359150808211156143f057600080fd5b506143fd88828901613d99565b969995985093965092949392505050565b600082601f83011261441f57600080fd5b8135602061442f613b8883613ad5565b82815260059290921b8401810191818101908684111561444e57600080fd5b8286015b848110156142ac5780356001600160401b038111156144715760008081fd5b61447f8986838b01016142b7565b845250918301918301614452565b600082601f83011261449e57600080fd5b813560206144ae613b8883613ad5565b82815260059290921b840181019181810190868411156144cd57600080fd5b8286015b848110156142ac5780356001600160401b03808211156144f057600080fd5b818901915089603f83011261450457600080fd5b85820135614514613b8882613ad5565b81815260059190911b830160400190878101908c83111561453457600080fd5b604085015b8381101561456d5780358581111561455057600080fd5b61455f8f6040838a0101613b69565b845250918901918901614539565b508752505050928401925083016144d1565b600082601f83011261459057600080fd5b813560206145a0613b8883613ad5565b8083825260208201915060208460051b8701019350868411156145c257600080fd5b602086015b848110156142ac57803583529183019183016145c7565b600082601f8301126145ef57600080fd5b813560206145ff613b8883613ad5565b82815260059290921b8401810191818101908684111561461e57600080fd5b8286015b848110156142ac5780356001600160401b03808211156146425760008081fd5b9088019060a0828b03601f190181131561465c5760008081fd5b614664613a3f565b61466f888501613b0d565b8152604080850135848111156146855760008081fd5b6146938e8b8389010161440e565b8a84015250606080860135858111156146ac5760008081fd5b6146ba8f8c838a010161448d565b83850152506080915081860135858111156146d55760008081fd5b6146e38f8c838a010161457f565b9184019190915250919093013590830152508352918301918301614622565b6000806040838503121561471557600080fd5b6001600160401b038335111561472a57600080fd5b61473784843585016145de565b91506001600160401b036020840135111561475157600080fd5b6020830135830184601f82011261476757600080fd5b614774613b888235613ad5565b81358082526020808301929160051b84010187101561479257600080fd5b602083015b6020843560051b85010181101561493b576001600160401b03813511156147bd57600080fd5b87603f8235860101126147cf57600080fd5b6147e2613b886020833587010135613ad5565b81358501602081810135808452908301929160059190911b016040018a101561480a57600080fd5b604083358701015b83358701602081013560051b0160400181101561492b576001600160401b038135111561483e57600080fd5b833587018135016040818d03603f1901121561485957600080fd5b614861613a83565b604082013581526001600160401b036060830135111561488057600080fd5b8c605f60608401358401011261489557600080fd5b60406060830135830101356148ac613b8882613ad5565b808282526020820191508f60608460051b60608801358801010111156148d157600080fd5b6060808601358601015b60608460051b60608801358801010181101561490b576148fb8135613f58565b80358352602092830192016148db565b508060208501525050508085525050602083019250602081019050614812565b5084525060209283019201614797565b508093505050509250929050565b60006020828403121561495b57600080fd5b610ac782613b0d565b602081526001600160a01b0382511660208201526020820151151560408201526001600160401b0360408301511660608201526000606083015160808084015261330d60a0840182613d01565b6000602082840312156149c357600080fd5b813561391d81613af8565b600082601f8301126149df57600080fd5b813560206149ef613b8883613ad5565b8083825260208201915060208460051b870101935086841115614a1157600080fd5b602086015b848110156142ac578035614a2981613af8565b8352918301918301614a16565b60006020808385031215614a4957600080fd5b82356001600160401b0380821115614a6057600080fd5b818501915085601f830112614a7457600080fd5b8135614a82613b8882613ad5565b81815260059190911b83018401908481019088831115614aa157600080fd5b8585015b83811015613cd057803585811115614abc57600080fd5b860160c0818c03601f19011215614ad35760008081fd5b614adb613a61565b8882013581526040614aee818401613ff8565b8a8301526060614aff818501613ff8565b8284015260809150614b12828501613b37565b9083015260a08381013589811115614b2a5760008081fd5b614b388f8d838801016149ce565b838501525060c0840135915088821115614b525760008081fd5b614b608e8c848701016149ce565b9083015250845250918601918601614aa5565b80356001600160e01b0381168114613b2457600080fd5b600082601f830112614b9b57600080fd5b81356020614bab613b8883613ad5565b82815260069290921b84018101918181019086841115614bca57600080fd5b8286015b848110156142ac5760408189031215614be75760008081fd5b614bef613a83565b614bf882613b0d565b8152614c05858301614b73565b81860152835291830191604001614bce565b600082601f830112614c2857600080fd5b81356020614c38613b8883613ad5565b82815260059290921b84018101918181019086841115614c5757600080fd5b8286015b848110156142ac5780356001600160401b0380821115614c7b5760008081fd5b9088019060a0828b03601f1901811315614c955760008081fd5b614c9d613a3f565b614ca8888501613b0d565b815260408085013584811115614cbe5760008081fd5b614ccc8e8b83890101613b69565b8a8401525060609350614ce0848601613b0d565b908201526080614cf1858201613b0d565b93820193909352920135908201528352918301918301614c5b565b600082601f830112614d1d57600080fd5b81356020614d2d613b8883613ad5565b82815260069290921b84018101918181019086841115614d4c57600080fd5b8286015b848110156142ac5760408189031215614d695760008081fd5b614d71613a83565b813581528482013585820152835291830191604001614d50565b60006020808385031215614d9e57600080fd5b82356001600160401b0380821115614db557600080fd5b9084019060608287031215614dc957600080fd5b614dd1613a1d565b823582811115614de057600080fd5b83016040818903811315614df357600080fd5b614dfb613a83565b823585811115614e0a57600080fd5b8301601f81018b13614e1b57600080fd5b8035614e29613b8882613ad5565b81815260069190911b8201890190898101908d831115614e4857600080fd5b928a01925b82841015614e985785848f031215614e655760008081fd5b614e6d613a83565b8435614e7881613af8565b8152614e85858d01614b73565b818d0152825292850192908a0190614e4d565b845250505082870135915084821115614eb057600080fd5b614ebc8a838501614b8a565b81880152835250508284013582811115614ed557600080fd5b614ee188828601614c17565b85830152506040830135935081841115614efa57600080fd5b614f0687858501614d0c565b60408201529695505050505050565b600082825180855260208086019550808260051b84010181860160005b84811015614fa657601f19868403018952815160a06001600160401b03808351168652868301518288880152614f6a83880182613d01565b60408581015184169089015260608086015190931692880192909252506080928301519290950191909152509783019790830190600101614f32565b5090979650505050505050565b60006040808352614fc76040840186614f15565b83810360208581019190915285518083528682019282019060005b8181101561500757845180518452840151848401529383019391850191600101614fe2565b509098975050505050505050565b634e487b7160e01b600052603260045260246000fd5b805160408084528151848201819052600092602091908201906060870190855b8181101561508257835180516001600160a01b031684528501516001600160e01b031685840152928401929185019160010161504b565b50508583015187820388850152805180835290840192506000918401905b808310156150db57835180516001600160401b031683528501516001600160e01b0316858301529284019260019290920191908501906150a0565b50979650505050505050565b602081526000610ac7602083018461502b565b60006020828403121561510c57600080fd5b815161391d81613b29565b600181811c9082168061512b57607f821691505b60208210810361514b57634e487b7160e01b600052602260045260246000fd5b50919050565b600080835461515f81615117565b60018281168015615177576001811461518c576151bb565b60ff19841687528215158302870194506151bb565b8760005260208060002060005b858110156151b25781548a820152908401908201615199565b50505082870194505b50929695505050505050565b600081546151d481615117565b8085526020600183811680156151f1576001811461520b57615239565b60ff1985168884015283151560051b880183019550615239565b866000528260002060005b858110156152315781548a8201860152908301908401615216565b890184019650505b505050505092915050565b6040815260006152576040830185613d01565b82810360208401526140d581856151c7565b634e487b7160e01b600052601160045260246000fd5b6001600160401b0381811683821601908082111561529f5761529f615269565b5092915050565b6040815260006152b96040830185614f15565b82810360208401526140d5818561502b565b6000602082840312156152dd57600080fd5b81356001600160401b038111156152f357600080fd5b61330d848285016145de565b81810381811115610aca57610aca615269565b634e487b7160e01b600052601260045260246000fd5b60006001600160401b038084168061534257615342615312565b92169190910692915050565b8082028115828204841417610aca57610aca615269565b80518252600060206001600160401b0381840151168185015260408084015160a0604087015261539860a0870182613d01565b9050606085015186820360608801526153b18282613d01565b608087810151898303918a01919091528051808352908601935060009250908501905b808310156150db57835180516001600160a01b03168352860151868301529285019260019290920191908401906153d4565b602081526000610ac76020830184615365565b60808152600061542c6080830187615365565b61ffff9590951660208301525060408101929092526001600160a01b0316606090910152919050565b60008060006060848603121561546a57600080fd5b835161547581613b29565b60208501519093506001600160401b0381111561549157600080fd5b8401601f810186136154a257600080fd5b80516154b0613b8882613b42565b8181528760208385010111156154c557600080fd5b6154d6826020830160208601613cdd565b809450505050604084015190509250925092565b6000602082840312156154fc57600080fd5b815161391d81613f58565b601f821115611272576000816000526020600020601f850160051c810160208610156155305750805b601f850160051c820191505b8181101561554f5782815560010161553c565b505050505050565b81516001600160401b03811115615570576155706139df565b6155848161557e8454615117565b84615507565b602080601f8311600181146155b957600084156155a15750858301515b600019600386901b1c1916600185901b17855561554f565b600085815260208120601f198616915b828110156155e8578886015182559484019460019091019084016155c9565b50858210156156065787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60208152600082546001600160a01b038116602084015260ff8160a01c16151560408401526001600160401b038160a81c16606084015250608080830152610ac760a08301600185016151c7565b80820180821115610aca57610aca615269565b60ff8181168382160190811115610aca57610aca615269565b8183823760009101908152919050565b828152606082602083013760800192915050565b60006001600160401b03808416806156ce576156ce615312565b92169190910492915050565b6000602082840312156156ec57600080fd5b813561391d81613f58565b6000808335601e1984360301811261570e57600080fd5b8301803591506001600160401b0382111561572857600080fd5b602001915036819003821315613d9257600080fd5b602081016005831061575157615751613f15565b91905290565b60ff818116838216029081169081811461529f5761529f615269565b600060a0820160ff881683526020878185015260a0604085015281875480845260c0860191508860005282600020935060005b818110156157cb5784546001600160a01b0316835260019485019492840192016157a6565b50508481036060860152865180825290820192508187019060005b8181101561580b5782516001600160a01b0316855293830193918301916001016157e6565b50505060ff851660808501525090505b9695505050505050565b60006001600160401b038086168352808516602084015250606060408301526140d56060830184613d01565b82815260406020820152600061330d6040830184613d01565b6001600160401b038481168252831660208201526060810161330d6040830184613f2b565b84815261589f6020820185613f2b565b6080604082015260006158b56080830185613d01565b905082606083015295945050505050565b6000602082840312156158d857600080fd5b815161391d81613af8565b6020815260008251610100806020850152615902610120850183613d01565b9150602085015161591e60408601826001600160401b03169052565b5060408501516001600160a01b03811660608601525060608501516080850152608085015161595860a08601826001600160a01b03169052565b5060a0850151601f19808685030160c08701526159758483613d01565b935060c08701519150808685030160e08701526159928483613d01565b935060e087015191508086850301838701525061581b8382613d01565b6000602082840312156159c157600080fd5b5051919050565b84815260006001600160401b0380861660208401528085166040840152506080606083015261581b6080830184613d01565b86815260c060208201526000615a1360c0830188613d01565b6001600160a01b03969096166040830152506001600160401b039384166060820152608081019290925290911660a09091015292915050565b600082825180855260208086019550808260051b84010181860160005b84811015614fa657601f19868403018952815160a08151818652615a8f82870182613d01565b9150508582015185820387870152615aa78282613d01565b91505060408083015186830382880152615ac18382613d01565b92505050606080830151818701525060808083015192508582038187015250615aea8183613d01565b9a86019a9450505090830190600101615a69565b602081526000610ac76020830184615a4c565b60008282518085526020808601955060208260051b8401016020860160005b84811015614fa657601f19868403018952615b4c838351613d01565b98840198925090830190600101615b30565b60008151808452602080850194506020840160005b8381101561405e57815163ffffffff1687529582019590820190600101615b73565b60608152600084518051606084015260208101516001600160401b0380821660808601528060408401511660a08601528060608401511660c08601528060808401511660e0860152505050602085015161014080610100850152615bfd6101a0850183613d01565b91506040870151605f198086850301610120870152615c1c8483613d01565b935060608901519150615c39838701836001600160a01b03169052565b608089015161016087015260a0890151925080868503016101808701525050615c628282615a4c565b9150508281036020840152615c778186615b11565b9050828103604084015261581b8185615b5e56fea164736f6c6343000818000a", } var OffRampABI = OffRampMetaData.ABI diff --git a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt index b3ed8635dd..cdcd337b8e 100644 --- a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -23,7 +23,7 @@ multi_aggregate_rate_limiter: ../../../contracts/solc/v0.8.24/MultiAggregateRate multi_ocr3_helper: ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Helper.abi ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Helper.bin 6b56e0114a4d50797d30a34aecc2641ef340451d0c3fcb9d729bba4df2435122 nonce_manager: ../../../contracts/solc/v0.8.24/NonceManager/NonceManager.abi ../../../contracts/solc/v0.8.24/NonceManager/NonceManager.bin 6f64e1083b356c06ee66b9138e398b9c97a4cd3e8c9ec38cf3010cebc79af536 ocr3_config_encoder: ../../../contracts/solc/v0.8.24/IOCR3ConfigEncoder/IOCR3ConfigEncoder.abi ../../../contracts/solc/v0.8.24/IOCR3ConfigEncoder/IOCR3ConfigEncoder.bin 9254b35a86f00fde7b7193a033ca58f6521a66e87b9cf9da6ce5660082e79f5d -offramp: ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.abi ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.bin d7f33e895b1b282930c81ac4e19ec51f6a7900fe6dddda3a7ba1b2796eacff32 +offramp: ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.abi ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.bin 56945d1dff7a37553ad6db6b0701159af4ad2d85fb49acf368f66881c382f08a onramp: ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.abi ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.bin 594439983f963f4158f9c5009dee7cba4ee56be61900bb1d5b9108eaeac3d6a6 ping_pong_demo: ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.abi ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.bin c1c2f8a65c7ffd971899cae7fe62f2da57d09e936151e2b92163c4bebe699d6b price_registry: ../../../contracts/solc/v0.8.24/PriceRegistry/PriceRegistry.abi ../../../contracts/solc/v0.8.24/PriceRegistry/PriceRegistry.bin e7781d600c1bb7aa4620106af7f6e146a109b97f4cb6a7d06c9e15773340ecb2 From ba47d7ddd53bb4e27829511224fbe072989d576b Mon Sep 17 00:00:00 2001 From: Rens Rooimans Date: Fri, 13 Sep 2024 09:29:02 +0200 Subject: [PATCH 090/115] update offramp layout (#1434) ## Motivation Some header are outdated. The exec logic is above the commit logic, but then after the commit logic we have the token handling logic, which is only used for exec. It has been moved to be above the commit logic --- contracts/src/v0.8/ccip/offRamp/OffRamp.sol | 314 ++++++++++---------- 1 file changed, 155 insertions(+), 159 deletions(-) diff --git a/contracts/src/v0.8/ccip/offRamp/OffRamp.sol b/contracts/src/v0.8/ccip/offRamp/OffRamp.sol index 2bb89e3c33..a74c293b1a 100644 --- a/contracts/src/v0.8/ccip/offRamp/OffRamp.sol +++ b/contracts/src/v0.8/ccip/offRamp/OffRamp.sol @@ -198,7 +198,7 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { } // ================================================================ - // │ Messaging │ + // │ Execution │ // ================================================================ // The size of the execution state in bits @@ -206,10 +206,6 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { // The mask for the execution state bits uint256 private constant MESSAGE_EXECUTION_STATE_MASK = (1 << MESSAGE_EXECUTION_STATE_BIT_WIDTH) - 1; - // ================================================================ - // │ Execution │ - // ================================================================ - /// @notice Returns the current execution state of a message based on its sequenceNumber. /// @param sourceChainSelector The source chain to get the execution state for /// @param sequenceNumber The sequence number of the message to get the execution state for. @@ -598,6 +594,158 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { if (!success) revert ReceiverError(returnData); } + // ================================================================ + // │ Tokens and pools │ + // ================================================================ + + /// @notice Uses a pool to release or mint a token to a receiver address, with balance checks before and after the + /// transfer. This is done to ensure the exact number of tokens the pool claims to release are actually transferred. + /// @dev The local token address is validated through the TokenAdminRegistry. If, due to some misconfiguration, the + /// token is unknown to the registry, the offRamp will revert. The tx, and the tokens, can be retrieved by + /// registering the token on this chain, and re-trying the msg. + /// @param sourceTokenAmount Amount and source data of the token to be released/minted. + /// @param originalSender The message sender on the source chain. + /// @param receiver The address that will receive the tokens. + /// @param sourceChainSelector The remote source chain selector + /// @param offchainTokenData Data fetched offchain by the DON. + /// @return destTokenAmount local token address with amount + function _releaseOrMintSingleToken( + Internal.RampTokenAmount memory sourceTokenAmount, + bytes memory originalSender, + address receiver, + uint64 sourceChainSelector, + bytes memory offchainTokenData + ) internal returns (Client.EVMTokenAmount memory destTokenAmount) { + // We need to safely decode the token address from the sourceTokenData, as it could be wrong, + // in which case it doesn't have to be a valid EVM address. + address localToken = Internal._validateEVMAddress(sourceTokenAmount.destTokenAddress); + // We check with the token admin registry if the token has a pool on this chain. + address localPoolAddress = ITokenAdminRegistry(i_tokenAdminRegistry).getPool(localToken); + // This will call the supportsInterface through the ERC165Checker, and not directly on the pool address. + // This is done to prevent a pool from reverting the entire transaction if it doesn't support the interface. + // The call gets a max or 30k gas per instance, of which there are three. This means gas estimations should + // account for 90k gas overhead due to the interface check. + if (localPoolAddress == address(0) || !localPoolAddress.supportsInterface(Pool.CCIP_POOL_V1)) { + revert NotACompatiblePool(localPoolAddress); + } + + // We retrieve the local token balance of the receiver before the pool call. + (uint256 balancePre, uint256 gasLeft) = + _getBalanceOfReceiver(receiver, localToken, abi.decode(sourceTokenAmount.destExecData, (uint32))); + + // We determined that the pool address is a valid EVM address, but that does not mean the code at this + // address is a (compatible) pool contract. _callWithExactGasSafeReturnData will check if the location + // contains a contract. If it doesn't it reverts with a known error, which we catch gracefully. + // We call the pool with exact gas to increase resistance against malicious tokens or token pools. + // We protect against return data bombs by capping the return data size at MAX_RET_BYTES. + (bool success, bytes memory returnData, uint256 gasUsedReleaseOrMint) = CallWithExactGas + ._callWithExactGasSafeReturnData( + abi.encodeCall( + IPoolV1.releaseOrMint, + Pool.ReleaseOrMintInV1({ + originalSender: originalSender, + receiver: receiver, + amount: sourceTokenAmount.amount, + localToken: localToken, + remoteChainSelector: sourceChainSelector, + sourcePoolAddress: sourceTokenAmount.sourcePoolAddress, + sourcePoolData: sourceTokenAmount.extraData, + offchainTokenData: offchainTokenData + }) + ), + localPoolAddress, + gasLeft, + Internal.GAS_FOR_CALL_EXACT_CHECK, + Internal.MAX_RET_BYTES + ); + + // Wrap and rethrow the error so we can catch it lower in the stack + if (!success) revert TokenHandlingError(returnData); + + // If the call was successful, the returnData should be the local token address. + if (returnData.length != Pool.CCIP_POOL_V1_RET_BYTES) { + revert InvalidDataLength(Pool.CCIP_POOL_V1_RET_BYTES, returnData.length); + } + + uint256 localAmount = abi.decode(returnData, (uint256)); + // We don't need to do balance checks if the pool is the receiver, as they would always fail in the case + // of a lockRelease pool. + if (receiver != localPoolAddress) { + (uint256 balancePost,) = _getBalanceOfReceiver(receiver, localToken, gasLeft - gasUsedReleaseOrMint); + + // First we check if the subtraction would result in an underflow to ensure we revert with a clear error + if (balancePost < balancePre || balancePost - balancePre != localAmount) { + revert ReleaseOrMintBalanceMismatch(localAmount, balancePre, balancePost); + } + } + + return Client.EVMTokenAmount({token: localToken, amount: localAmount}); + } + + /// @notice Retrieves the balance of a receiver address for a given token. + /// @param receiver The address to check the balance of. + /// @param token The token address. + /// @param gasLimit The gas limit to use for the call. + /// @return balance The balance of the receiver. + /// @return gasLeft The gas left after the call. + function _getBalanceOfReceiver( + address receiver, + address token, + uint256 gasLimit + ) internal returns (uint256 balance, uint256 gasLeft) { + (bool success, bytes memory returnData, uint256 gasUsed) = CallWithExactGas._callWithExactGasSafeReturnData( + abi.encodeCall(IERC20.balanceOf, (receiver)), + token, + gasLimit, + Internal.GAS_FOR_CALL_EXACT_CHECK, + Internal.MAX_RET_BYTES + ); + if (!success) revert TokenHandlingError(returnData); + + // If the call was successful, the returnData should contain only the balance. + if (returnData.length != Internal.MAX_BALANCE_OF_RET_BYTES) { + revert InvalidDataLength(Internal.MAX_BALANCE_OF_RET_BYTES, returnData.length); + } + + // Return the decoded balance, which cannot fail as we checked the length, and the gas that is left + // after this call. + return (abi.decode(returnData, (uint256)), gasLimit - gasUsed); + } + + /// @notice Uses pools to release or mint a number of different tokens to a receiver address. + /// @param sourceTokenAmounts List of token amounts with source data of the tokens to be released/minted. + /// @param originalSender The message sender on the source chain. + /// @param receiver The address that will receive the tokens. + /// @param sourceChainSelector The remote source chain selector. + /// @param offchainTokenData Array of token data fetched offchain by the DON. + /// @return destTokenAmounts local token addresses with amounts + /// @dev This function wraps the token pool call in a try catch block to gracefully handle + /// any non-rate limiting errors that may occur. If we encounter a rate limiting related error + /// we bubble it up. If we encounter a non-rate limiting error we wrap it in a TokenHandlingError. + function _releaseOrMintTokens( + Internal.RampTokenAmount[] memory sourceTokenAmounts, + bytes memory originalSender, + address receiver, + uint64 sourceChainSelector, + bytes[] calldata offchainTokenData, + uint32[] calldata tokenGasOverrides + ) internal returns (Client.EVMTokenAmount[] memory destTokenAmounts) { + destTokenAmounts = new Client.EVMTokenAmount[](sourceTokenAmounts.length); + bool isTokenGasOverridesEmpty = tokenGasOverrides.length == 0; + for (uint256 i = 0; i < sourceTokenAmounts.length; ++i) { + if (!isTokenGasOverridesEmpty) { + if (tokenGasOverrides[i] != 0) { + sourceTokenAmounts[i].destExecData = abi.encode(tokenGasOverrides[i]); + } + } + destTokenAmounts[i] = _releaseOrMintSingleToken( + sourceTokenAmounts[i], originalSender, receiver, sourceChainSelector, offchainTokenData[i] + ); + } + + return destTokenAmounts; + } + // ================================================================ // │ Commit │ // ================================================================ @@ -838,162 +986,10 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { } // ================================================================ - // │ Tokens and pools │ - // ================================================================ - - /// @notice Uses a pool to release or mint a token to a receiver address, with balance checks before and after the - /// transfer. This is done to ensure the exact number of tokens the pool claims to release are actually transferred. - /// @dev The local token address is validated through the TokenAdminRegistry. If, due to some misconfiguration, the - /// token is unknown to the registry, the offRamp will revert. The tx, and the tokens, can be retrieved by - /// registering the token on this chain, and re-trying the msg. - /// @param sourceTokenAmount Amount and source data of the token to be released/minted. - /// @param originalSender The message sender on the source chain. - /// @param receiver The address that will receive the tokens. - /// @param sourceChainSelector The remote source chain selector - /// @param offchainTokenData Data fetched offchain by the DON. - /// @return destTokenAmount local token address with amount - function _releaseOrMintSingleToken( - Internal.RampTokenAmount memory sourceTokenAmount, - bytes memory originalSender, - address receiver, - uint64 sourceChainSelector, - bytes memory offchainTokenData - ) internal returns (Client.EVMTokenAmount memory destTokenAmount) { - // We need to safely decode the token address from the sourceTokenData, as it could be wrong, - // in which case it doesn't have to be a valid EVM address. - address localToken = Internal._validateEVMAddress(sourceTokenAmount.destTokenAddress); - // We check with the token admin registry if the token has a pool on this chain. - address localPoolAddress = ITokenAdminRegistry(i_tokenAdminRegistry).getPool(localToken); - // This will call the supportsInterface through the ERC165Checker, and not directly on the pool address. - // This is done to prevent a pool from reverting the entire transaction if it doesn't support the interface. - // The call gets a max or 30k gas per instance, of which there are three. This means gas estimations should - // account for 90k gas overhead due to the interface check. - if (localPoolAddress == address(0) || !localPoolAddress.supportsInterface(Pool.CCIP_POOL_V1)) { - revert NotACompatiblePool(localPoolAddress); - } - - // We retrieve the local token balance of the receiver before the pool call. - (uint256 balancePre, uint256 gasLeft) = - _getBalanceOfReceiver(receiver, localToken, abi.decode(sourceTokenAmount.destExecData, (uint32))); - - // We determined that the pool address is a valid EVM address, but that does not mean the code at this - // address is a (compatible) pool contract. _callWithExactGasSafeReturnData will check if the location - // contains a contract. If it doesn't it reverts with a known error, which we catch gracefully. - // We call the pool with exact gas to increase resistance against malicious tokens or token pools. - // We protect against return data bombs by capping the return data size at MAX_RET_BYTES. - (bool success, bytes memory returnData, uint256 gasUsedReleaseOrMint) = CallWithExactGas - ._callWithExactGasSafeReturnData( - abi.encodeCall( - IPoolV1.releaseOrMint, - Pool.ReleaseOrMintInV1({ - originalSender: originalSender, - receiver: receiver, - amount: sourceTokenAmount.amount, - localToken: localToken, - remoteChainSelector: sourceChainSelector, - sourcePoolAddress: sourceTokenAmount.sourcePoolAddress, - sourcePoolData: sourceTokenAmount.extraData, - offchainTokenData: offchainTokenData - }) - ), - localPoolAddress, - gasLeft, - Internal.GAS_FOR_CALL_EXACT_CHECK, - Internal.MAX_RET_BYTES - ); - - // Wrap and rethrow the error so we can catch it lower in the stack - if (!success) revert TokenHandlingError(returnData); - - // If the call was successful, the returnData should be the local token address. - if (returnData.length != Pool.CCIP_POOL_V1_RET_BYTES) { - revert InvalidDataLength(Pool.CCIP_POOL_V1_RET_BYTES, returnData.length); - } - - uint256 localAmount = abi.decode(returnData, (uint256)); - // We don't need to do balance checks if the pool is the receiver, as they would always fail in the case - // of a lockRelease pool. - if (receiver != localPoolAddress) { - (uint256 balancePost,) = _getBalanceOfReceiver(receiver, localToken, gasLeft - gasUsedReleaseOrMint); - - // First we check if the subtraction would result in an underflow to ensure we revert with a clear error - if (balancePost < balancePre || balancePost - balancePre != localAmount) { - revert ReleaseOrMintBalanceMismatch(localAmount, balancePre, balancePost); - } - } - - return Client.EVMTokenAmount({token: localToken, amount: localAmount}); - } - - /// @notice Retrieves the balance of a receiver address for a given token. - /// @param receiver The address to check the balance of. - /// @param token The token address. - /// @param gasLimit The gas limit to use for the call. - /// @return balance The balance of the receiver. - /// @return gasLeft The gas left after the call. - function _getBalanceOfReceiver( - address receiver, - address token, - uint256 gasLimit - ) internal returns (uint256 balance, uint256 gasLeft) { - (bool success, bytes memory returnData, uint256 gasUsed) = CallWithExactGas._callWithExactGasSafeReturnData( - abi.encodeCall(IERC20.balanceOf, (receiver)), - token, - gasLimit, - Internal.GAS_FOR_CALL_EXACT_CHECK, - Internal.MAX_RET_BYTES - ); - if (!success) revert TokenHandlingError(returnData); - - // If the call was successful, the returnData should contain only the balance. - if (returnData.length != Internal.MAX_BALANCE_OF_RET_BYTES) { - revert InvalidDataLength(Internal.MAX_BALANCE_OF_RET_BYTES, returnData.length); - } - - // Return the decoded balance, which cannot fail as we checked the length, and the gas that is left - // after this call. - return (abi.decode(returnData, (uint256)), gasLimit - gasUsed); - } - - /// @notice Uses pools to release or mint a number of different tokens to a receiver address. - /// @param sourceTokenAmounts List of token amounts with source data of the tokens to be released/minted. - /// @param originalSender The message sender on the source chain. - /// @param receiver The address that will receive the tokens. - /// @param sourceChainSelector The remote source chain selector. - /// @param offchainTokenData Array of token data fetched offchain by the DON. - /// @return destTokenAmounts local token addresses with amounts - /// @dev This function wraps the token pool call in a try catch block to gracefully handle - /// any non-rate limiting errors that may occur. If we encounter a rate limiting related error - /// we bubble it up. If we encounter a non-rate limiting error we wrap it in a TokenHandlingError. - function _releaseOrMintTokens( - Internal.RampTokenAmount[] memory sourceTokenAmounts, - bytes memory originalSender, - address receiver, - uint64 sourceChainSelector, - bytes[] calldata offchainTokenData, - uint32[] calldata tokenGasOverrides - ) internal returns (Client.EVMTokenAmount[] memory destTokenAmounts) { - destTokenAmounts = new Client.EVMTokenAmount[](sourceTokenAmounts.length); - bool isTokenGasOverridesEmpty = tokenGasOverrides.length == 0; - for (uint256 i = 0; i < sourceTokenAmounts.length; ++i) { - if (!isTokenGasOverridesEmpty) { - if (tokenGasOverrides[i] != 0) { - sourceTokenAmounts[i].destExecData = abi.encode(tokenGasOverrides[i]); - } - } - destTokenAmounts[i] = _releaseOrMintSingleToken( - sourceTokenAmounts[i], originalSender, receiver, sourceChainSelector, offchainTokenData[i] - ); - } - - return destTokenAmounts; - } - - // ================================================================ - // │ Access and RMN │ + // │ Access │ // ================================================================ - /// @notice Reverts as this contract should not access CCIP messages + /// @notice Reverts as this contract should not be able to receive CCIP messages function ccipReceive(Client.Any2EVMMessage calldata) external pure { // solhint-disable-next-line revert(); From f169c88a50b04a4c19ea5031cbb525fab8430afc Mon Sep 17 00:00:00 2001 From: Ryan Hall Date: Fri, 13 Sep 2024 05:06:22 -0400 Subject: [PATCH 091/115] add CCIPEncodingUtils contract and gethwrapper (#1429) ## Motivation I encountered a scenario w/ RMN where offchain needs to abi.encode a [struct](https://github.com/smartcontractkit/ccip/blob/fc50683640bcfd73f0074d791fbaf7cdb6b29c71/contracts/src/v0.8/ccip/rmn/RMNRemote.sol#L90:L97) that is not included in any public contract functions (as input param or return value) and so it is not a part of the ABI or the go wrapper. Offchain is currently doing a manual encoding by re-defining the type, which I usually try to avoid at all costs. In the past, we've used a Utils contract ([ex here](https://github.com/smartcontractkit/chainlink/blob/develop/contracts/src/v0.8/automation/AutomationCompatibleUtils.sol) from automation) to expose all private structs in public functions so that offchain components can use E2E type safety when encoding / decoding. ## Solution Create a `CCIPEncodingUtils` contract and accompanying gethwrapper --- .../scripts/native_solc_compile_all_ccip | 4 + contracts/src/v0.8/ccip/CCIPEncodingUtils.sol | 18 ++ .../ccip_encoding_utils.go | 209 ++++++++++++++++++ ...rapper-dependency-versions-do-not-edit.txt | 1 + core/gethwrappers/ccip/go_generate.go | 3 + 5 files changed, 235 insertions(+) create mode 100644 contracts/src/v0.8/ccip/CCIPEncodingUtils.sol create mode 100644 core/gethwrappers/ccip/generated/ccip_encoding_utils/ccip_encoding_utils.go diff --git a/contracts/scripts/native_solc_compile_all_ccip b/contracts/scripts/native_solc_compile_all_ccip index e1f95b2fcb..0696d66115 100755 --- a/contracts/scripts/native_solc_compile_all_ccip +++ b/contracts/scripts/native_solc_compile_all_ccip @@ -102,6 +102,10 @@ compileContract ccip/test/mocks/MockE2EUSDCTokenMessenger.sol compileContract ccip/test/mocks/MockE2EUSDCTransmitter.sol compileContract ccip/test/WETH9.sol + +# Encoding Utils +compileContract ccip/CCIPEncodingUtils.sol + # Customer contracts compileContract ccip/pools/USDC/USDCTokenPool.sol diff --git a/contracts/src/v0.8/ccip/CCIPEncodingUtils.sol b/contracts/src/v0.8/ccip/CCIPEncodingUtils.sol new file mode 100644 index 0000000000..010fa4a1cd --- /dev/null +++ b/contracts/src/v0.8/ccip/CCIPEncodingUtils.sol @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {RMNRemote} from "./rmn/RMNRemote.sol"; + +/// @dev this file exposes structs that are otherwise internal to the CCIP codebase +/// doing this allows those structs to be encoded and decoded with type safety in offchain code +/// and tests because generated wrappers are available +contract CCIPEncodingUtils { + error DoNotDeploy(); + + constructor() { + revert DoNotDeploy(); + } + + /// @dev the RMN Report struct is used in integration / E2E tests + function _rmnReport(bytes32 rmnReportVersion, RMNRemote.Report memory rmnReport) external {} +} diff --git a/core/gethwrappers/ccip/generated/ccip_encoding_utils/ccip_encoding_utils.go b/core/gethwrappers/ccip/generated/ccip_encoding_utils/ccip_encoding_utils.go new file mode 100644 index 0000000000..60daca1c57 --- /dev/null +++ b/core/gethwrappers/ccip/generated/ccip_encoding_utils/ccip_encoding_utils.go @@ -0,0 +1,209 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package ccip_encoding_utils + +import ( + "errors" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" +) + +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +type InternalMerkleRoot struct { + SourceChainSelector uint64 + OnRampAddress []byte + MinSeqNr uint64 + MaxSeqNr uint64 + MerkleRoot [32]byte +} + +type RMNRemoteReport struct { + DestChainId *big.Int + DestChainSelector uint64 + RmnRemoteContractAddress common.Address + OfframpAddress common.Address + RmnHomeContractConfigDigest [32]byte + DestLaneUpdates []InternalMerkleRoot +} + +var EncodingUtilsMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"DoNotDeploy\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"rmnReportVersion\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"destChainId\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnRemoteContractAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"offrampAddress\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"rmnHomeContractConfigDigest\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"destLaneUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structRMNRemote.Report\",\"name\":\"rmnReport\",\"type\":\"tuple\"}],\"name\":\"_rmnReport\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x608060405234801561001057600080fd5b50604051636f1e4f5f60e01b815260040160405180910390fdfe", +} + +var EncodingUtilsABI = EncodingUtilsMetaData.ABI + +var EncodingUtilsBin = EncodingUtilsMetaData.Bin + +func DeployEncodingUtils(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *EncodingUtils, error) { + parsed, err := EncodingUtilsMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(EncodingUtilsBin), backend) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &EncodingUtils{address: address, abi: *parsed, EncodingUtilsCaller: EncodingUtilsCaller{contract: contract}, EncodingUtilsTransactor: EncodingUtilsTransactor{contract: contract}, EncodingUtilsFilterer: EncodingUtilsFilterer{contract: contract}}, nil +} + +type EncodingUtils struct { + address common.Address + abi abi.ABI + EncodingUtilsCaller + EncodingUtilsTransactor + EncodingUtilsFilterer +} + +type EncodingUtilsCaller struct { + contract *bind.BoundContract +} + +type EncodingUtilsTransactor struct { + contract *bind.BoundContract +} + +type EncodingUtilsFilterer struct { + contract *bind.BoundContract +} + +type EncodingUtilsSession struct { + Contract *EncodingUtils + CallOpts bind.CallOpts + TransactOpts bind.TransactOpts +} + +type EncodingUtilsCallerSession struct { + Contract *EncodingUtilsCaller + CallOpts bind.CallOpts +} + +type EncodingUtilsTransactorSession struct { + Contract *EncodingUtilsTransactor + TransactOpts bind.TransactOpts +} + +type EncodingUtilsRaw struct { + Contract *EncodingUtils +} + +type EncodingUtilsCallerRaw struct { + Contract *EncodingUtilsCaller +} + +type EncodingUtilsTransactorRaw struct { + Contract *EncodingUtilsTransactor +} + +func NewEncodingUtils(address common.Address, backend bind.ContractBackend) (*EncodingUtils, error) { + abi, err := abi.JSON(strings.NewReader(EncodingUtilsABI)) + if err != nil { + return nil, err + } + contract, err := bindEncodingUtils(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &EncodingUtils{address: address, abi: abi, EncodingUtilsCaller: EncodingUtilsCaller{contract: contract}, EncodingUtilsTransactor: EncodingUtilsTransactor{contract: contract}, EncodingUtilsFilterer: EncodingUtilsFilterer{contract: contract}}, nil +} + +func NewEncodingUtilsCaller(address common.Address, caller bind.ContractCaller) (*EncodingUtilsCaller, error) { + contract, err := bindEncodingUtils(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &EncodingUtilsCaller{contract: contract}, nil +} + +func NewEncodingUtilsTransactor(address common.Address, transactor bind.ContractTransactor) (*EncodingUtilsTransactor, error) { + contract, err := bindEncodingUtils(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &EncodingUtilsTransactor{contract: contract}, nil +} + +func NewEncodingUtilsFilterer(address common.Address, filterer bind.ContractFilterer) (*EncodingUtilsFilterer, error) { + contract, err := bindEncodingUtils(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &EncodingUtilsFilterer{contract: contract}, nil +} + +func bindEncodingUtils(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := EncodingUtilsMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +func (_EncodingUtils *EncodingUtilsRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _EncodingUtils.Contract.EncodingUtilsCaller.contract.Call(opts, result, method, params...) +} + +func (_EncodingUtils *EncodingUtilsRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _EncodingUtils.Contract.EncodingUtilsTransactor.contract.Transfer(opts) +} + +func (_EncodingUtils *EncodingUtilsRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _EncodingUtils.Contract.EncodingUtilsTransactor.contract.Transact(opts, method, params...) +} + +func (_EncodingUtils *EncodingUtilsCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _EncodingUtils.Contract.contract.Call(opts, result, method, params...) +} + +func (_EncodingUtils *EncodingUtilsTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _EncodingUtils.Contract.contract.Transfer(opts) +} + +func (_EncodingUtils *EncodingUtilsTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _EncodingUtils.Contract.contract.Transact(opts, method, params...) +} + +func (_EncodingUtils *EncodingUtilsTransactor) RmnReport(opts *bind.TransactOpts, rmnReportVersion [32]byte, rmnReport RMNRemoteReport) (*types.Transaction, error) { + return _EncodingUtils.contract.Transact(opts, "_rmnReport", rmnReportVersion, rmnReport) +} + +func (_EncodingUtils *EncodingUtilsSession) RmnReport(rmnReportVersion [32]byte, rmnReport RMNRemoteReport) (*types.Transaction, error) { + return _EncodingUtils.Contract.RmnReport(&_EncodingUtils.TransactOpts, rmnReportVersion, rmnReport) +} + +func (_EncodingUtils *EncodingUtilsTransactorSession) RmnReport(rmnReportVersion [32]byte, rmnReport RMNRemoteReport) (*types.Transaction, error) { + return _EncodingUtils.Contract.RmnReport(&_EncodingUtils.TransactOpts, rmnReportVersion, rmnReport) +} + +func (_EncodingUtils *EncodingUtils) Address() common.Address { + return _EncodingUtils.address +} + +type EncodingUtilsInterface interface { + RmnReport(opts *bind.TransactOpts, rmnReportVersion [32]byte, rmnReport RMNRemoteReport) (*types.Transaction, error) + + Address() common.Address +} diff --git a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt index cdcd337b8e..bda0200e51 100644 --- a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -5,6 +5,7 @@ burn_mint_token_pool_and_proxy: ../../../contracts/solc/v0.8.24/BurnMintTokenPoo burn_with_from_mint_token_pool: ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.abi ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.bin 6333d0314d0bd29e75ea5e05fe62a4516ade0c6db91c30b6f93645035db52ed8 burn_with_from_mint_token_pool_and_proxy: ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPoolAndProxy/BurnWithFromMintTokenPoolAndProxy.abi ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPoolAndProxy/BurnWithFromMintTokenPoolAndProxy.bin 08ed1235dda921ce8841b26aa18d0c0f36db4884779dd7670857159801b6d597 ccip_config: ../../../contracts/solc/v0.8.24/CCIPConfig/CCIPConfig.abi ../../../contracts/solc/v0.8.24/CCIPConfig/CCIPConfig.bin 93e3bceec6fff366e876f636001253f1d9c60b43e2c95484674f7ae245b302e6 +ccip_encoding_utils: ../../../contracts/solc/v0.8.24/CCIPEncodingUtils/CCIPEncodingUtils.abi ../../../contracts/solc/v0.8.24/CCIPEncodingUtils/CCIPEncodingUtils.bin 1d48b49fc0668c4f8c5e19a208cf4cae124a9a5c361e7900fbc35b97a62dd1bc ccip_reader_tester: ../../../contracts/solc/v0.8.24/CCIPReaderTester/CCIPReaderTester.abi ../../../contracts/solc/v0.8.24/CCIPReaderTester/CCIPReaderTester.bin 481d461f14c98308cd788b64be1151e92bac6f95ddd55eefc926296454316f13 commit_store: ../../../contracts/solc/v0.8.24/CommitStore/CommitStore.abi ../../../contracts/solc/v0.8.24/CommitStore/CommitStore.bin 274d87db70b643e00ab0a7e7845bb4b791f3b613bfc87708d33fc5a8369e2a41 commit_store_helper: ../../../contracts/solc/v0.8.24/CommitStoreHelper/CommitStoreHelper.abi ../../../contracts/solc/v0.8.24/CommitStoreHelper/CommitStoreHelper.bin f7128dcc2ee6dbcbc976288abcc16970ffb19b59412c5202ef6b259d2007f801 diff --git a/core/gethwrappers/ccip/go_generate.go b/core/gethwrappers/ccip/go_generate.go index ba51fe13fc..8f3102525a 100644 --- a/core/gethwrappers/ccip/go_generate.go +++ b/core/gethwrappers/ccip/go_generate.go @@ -45,6 +45,9 @@ package ccip //go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/MockE2EUSDCTokenMessenger/MockE2EUSDCTokenMessenger.abi ../../../contracts/solc/v0.8.24/MockE2EUSDCTokenMessenger/MockE2EUSDCTokenMessenger.bin MockE2EUSDCTokenMessenger mock_usdc_token_messenger //go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/MockE2EUSDCTransmitter/MockE2EUSDCTransmitter.abi ../../../contracts/solc/v0.8.24/MockE2EUSDCTransmitter/MockE2EUSDCTransmitter.bin MockE2EUSDCTransmitter mock_usdc_token_transmitter +// EncodingUtils +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.24/CCIPEncodingUtils/CCIPEncodingUtils.abi ../../../contracts/solc/v0.8.24/CCIPEncodingUtils/CCIPEncodingUtils.bin EncodingUtils ccip_encoding_utils + // To run these commands, you must either install docker, or the correct version // of abigen. The latter can be installed with these commands, at least on linux: // From bd417edd43be5a60b9472dfe198d9d85396b7477 Mon Sep 17 00:00:00 2001 From: Ryan <80392855+RayXpub@users.noreply.github.com> Date: Fri, 13 Sep 2024 18:30:12 +0400 Subject: [PATCH 092/115] Remove TODO and rename messageValidator to messageInterceptor (#1438) - Replaces `CCIPConfigTypes.ConfigState` `/// TODO: explain rollbacks?` by rollbacks comment - Renames `messageValidator` to `messageInterceptor` in ramps --------- Co-authored-by: Rens Rooimans --- contracts/gas-snapshots/ccip.gas-snapshot | 42 +++++++++---------- .../capability/libraries/CCIPConfigTypes.sol | 9 +++- contracts/src/v0.8/ccip/offRamp/OffRamp.sol | 8 ++-- contracts/src/v0.8/ccip/onRamp/OnRamp.sol | 8 ++-- .../src/v0.8/ccip/test/offRamp/OffRamp.t.sol | 22 +++++----- .../v0.8/ccip/test/offRamp/OffRampSetup.t.sol | 12 +++--- .../src/v0.8/ccip/test/onRamp/OnRamp.t.sol | 20 ++++----- .../v0.8/ccip/test/onRamp/OnRampSetup.t.sol | 10 ++--- .../ccip/deployment_test/deployment_test.go | 10 ++--- .../ccip/generated/offramp/offramp.go | 4 +- .../ccip/generated/onramp/onramp.go | 10 ++--- ...rapper-dependency-versions-do-not-edit.txt | 4 +- 12 files changed, 83 insertions(+), 76 deletions(-) diff --git a/contracts/gas-snapshots/ccip.gas-snapshot b/contracts/gas-snapshots/ccip.gas-snapshot index 1590d6c3ae..36b43c9bf2 100644 --- a/contracts/gas-snapshots/ccip.gas-snapshot +++ b/contracts/gas-snapshots/ccip.gas-snapshot @@ -671,7 +671,7 @@ OffRamp_execute:test_UnauthorizedTransmitter_Revert() (gas: 149068) OffRamp_execute:test_WrongConfigWithSigners_Revert() (gas: 6999426) OffRamp_execute:test_ZeroReports_Revert() (gas: 17293) OffRamp_executeSingleMessage:test_MessageSender_Revert() (gas: 18874) -OffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 248743) +OffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 248721) OffRamp_executeSingleMessage:test_NonContract_Success() (gas: 21206) OffRamp_executeSingleMessage:test_TokenHandlingError_Revert() (gas: 209803) OffRamp_executeSingleMessage:test_ZeroGasDONExecution_Revert() (gas: 49525) @@ -679,7 +679,7 @@ OffRamp_executeSingleMessage:test_executeSingleMessage_NoTokens_Success() (gas: OffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidationNoRouterCall_Revert() (gas: 218730) OffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidation_Revert() (gas: 85512) OffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens_Success() (gas: 280659) -OffRamp_executeSingleMessage:test_executeSingleMessage_WithValidation_Success() (gas: 91830) +OffRamp_executeSingleMessage:test_executeSingleMessage_WithVInterception_Success() (gas: 91829) OffRamp_executeSingleReport:test_DisabledSourceChain_Revert() (gas: 28730) OffRamp_executeSingleReport:test_EmptyReport_Revert() (gas: 22018) OffRamp_executeSingleReport:test_InvalidSourcePoolAddress_Success() (gas: 503897) @@ -741,9 +741,9 @@ OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_Success() (gas: 177447) OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_WithGasOverride_Success() (gas: 179427) OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals_Success() (gas: 190636) OffRamp_setDynamicConfig:test_FeeQuoterZeroAddress_Revert() (gas: 11201) -OffRamp_setDynamicConfig:test_NonOwner_Revert() (gas: 13811) -OffRamp_setDynamicConfig:test_SetDynamicConfigWithValidator_Success() (gas: 46216) -OffRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 24191) +OffRamp_setDynamicConfig:test_NonOwner_Revert() (gas: 13789) +OffRamp_setDynamicConfig:test_SetDynamicConfigWithInterceptor_Success() (gas: 46192) +OffRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 24234) OffRamp_trialExecute:test_RateLimitError_Success() (gas: 226586) OffRamp_trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 235208) OffRamp_trialExecute:test_TokenPoolIsNotAContract_Success() (gas: 314371) @@ -759,29 +759,29 @@ OnRamp_constructor:test_Constructor_InvalidConfigNonceManagerEqAddressZero_Rever OnRamp_constructor:test_Constructor_InvalidConfigRMNProxyEqAddressZero_Revert() (gas: 97783) OnRamp_constructor:test_Constructor_InvalidConfigTokenAdminRegistryEqAddressZero_Revert() (gas: 92815) OnRamp_constructor:test_Constructor_Success() (gas: 2817599) -OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() (gas: 114939) +OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() (gas: 114917) OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2_Success() (gas: 145710) -OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessCustomExtraArgs() (gas: 145313) +OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessCustomExtraArgs() (gas: 145291) OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessEmptyExtraArgs() (gas: 143538) -OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessLegacyExtraArgs() (gas: 145538) -OnRamp_forwardFromRouter:test_ForwardFromRouter_Success() (gas: 144917) -OnRamp_forwardFromRouter:test_ForwardFromRouter_Success_ConfigurableSourceRouter() (gas: 140249) +OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessLegacyExtraArgs() (gas: 145516) +OnRamp_forwardFromRouter:test_ForwardFromRouter_Success() (gas: 144895) +OnRamp_forwardFromRouter:test_ForwardFromRouter_Success_ConfigurableSourceRouter() (gas: 140292) OnRamp_forwardFromRouter:test_InvalidExtraArgsTag_Revert() (gas: 28824) -OnRamp_forwardFromRouter:test_MessageValidationError_Revert() (gas: 138938) +OnRamp_forwardFromRouter:test_MessageInterceptionError_Revert() (gas: 138916) OnRamp_forwardFromRouter:test_MesssageFeeTooHigh_Revert() (gas: 26924) -OnRamp_forwardFromRouter:test_MultiCannotSendZeroTokens_Revert() (gas: 74139) -OnRamp_forwardFromRouter:test_OriginalSender_Revert() (gas: 12951) -OnRamp_forwardFromRouter:test_Paused_Revert() (gas: 37338) -OnRamp_forwardFromRouter:test_Permissions_Revert() (gas: 18284) -OnRamp_forwardFromRouter:test_ShouldIncrementNonceOnlyOnOrdered_Success() (gas: 184562) +OnRamp_forwardFromRouter:test_MultiCannotSendZeroTokens_Revert() (gas: 74162) +OnRamp_forwardFromRouter:test_OriginalSender_Revert() (gas: 12995) +OnRamp_forwardFromRouter:test_Paused_Revert() (gas: 37361) +OnRamp_forwardFromRouter:test_Permissions_Revert() (gas: 18307) +OnRamp_forwardFromRouter:test_ShouldIncrementNonceOnlyOnOrdered_Success() (gas: 184585) OnRamp_forwardFromRouter:test_ShouldIncrementSeqNumAndNonce_Success() (gas: 210880) -OnRamp_forwardFromRouter:test_ShouldStoreLinkFees() (gas: 124838) +OnRamp_forwardFromRouter:test_ShouldStoreLinkFees() (gas: 124861) OnRamp_forwardFromRouter:test_ShouldStoreNonLinkFees() (gas: 141462) -OnRamp_forwardFromRouter:test_SourceTokenDataTooLarge_Revert() (gas: 3769244) +OnRamp_forwardFromRouter:test_SourceTokenDataTooLarge_Revert() (gas: 3769222) OnRamp_forwardFromRouter:test_UnAllowedOriginalSender_Revert() (gas: 18714) -OnRamp_forwardFromRouter:test_UnsupportedToken_Revert() (gas: 110919) -OnRamp_forwardFromRouter:test_forwardFromRouter_UnsupportedToken_Revert() (gas: 76235) -OnRamp_forwardFromRouter:test_forwardFromRouter_WithValidation_Success() (gas: 281240) +OnRamp_forwardFromRouter:test_UnsupportedToken_Revert() (gas: 110897) +OnRamp_forwardFromRouter:test_forwardFromRouter_UnsupportedToken_Revert() (gas: 76213) +OnRamp_forwardFromRouter:test_forwardFromRouter_WithInterception_Success() (gas: 281260) OnRamp_getFee:test_EmptyMessage_Success() (gas: 97734) OnRamp_getFee:test_EnforceOutOfOrder_Revert() (gas: 64215) OnRamp_getFee:test_GetFeeOfZeroForTokenMessage_Success() (gas: 85428) diff --git a/contracts/src/v0.8/ccip/capability/libraries/CCIPConfigTypes.sol b/contracts/src/v0.8/ccip/capability/libraries/CCIPConfigTypes.sol index 2148f991c8..02d8e321ac 100644 --- a/contracts/src/v0.8/ccip/capability/libraries/CCIPConfigTypes.sol +++ b/contracts/src/v0.8/ccip/capability/libraries/CCIPConfigTypes.sol @@ -9,7 +9,14 @@ library CCIPConfigTypes { /// The only valid transition from "Init" is to the "Running" state - this is the first ever configuration. /// The only valid transition from "Running" is to the "Staging" state - this is a blue/green proposal. /// The only valid transition from "Staging" is back to the "Running" state - this is a promotion. - /// TODO: explain rollbacks? + /// In order to rollback a configuration, we must therefore do the following: + /// - Suppose that we have a correct configuration in the "Running" state (V1). + /// - We propose a new configuration and transition to the "Staging" state (V2). + /// - V2 turns out to be buggy + /// - In the same transaction, we must: + /// - Promote V2 + /// - Re-propose V1 + /// - Promote V1 enum ConfigState { Init, Running, diff --git a/contracts/src/v0.8/ccip/offRamp/OffRamp.sol b/contracts/src/v0.8/ccip/offRamp/OffRamp.sol index a74c293b1a..39a781393c 100644 --- a/contracts/src/v0.8/ccip/offRamp/OffRamp.sol +++ b/contracts/src/v0.8/ccip/offRamp/OffRamp.sol @@ -122,7 +122,7 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { struct DynamicConfig { address feeQuoter; // ──────────────────────────────╮ FeeQuoter address on the local chain uint32 permissionLessExecutionThresholdSeconds; //──╯ Waiting time before manual execution is enabled - address messageValidator; // Optional message validator to validate incoming messages (zero address = no validator) + address messageInterceptor; // Optional message interceptor to validate incoming messages (zero address = no interceptor) } /// @dev Report that is committed by the observing DON at the committing phase @@ -565,9 +565,9 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { destTokenAmounts: destTokenAmounts }); - address messageValidator = s_dynamicConfig.messageValidator; - if (messageValidator != address(0)) { - try IMessageInterceptor(messageValidator).onInboundMessage(any2EvmMessage) {} + address messageInterceptor = s_dynamicConfig.messageInterceptor; + if (messageInterceptor != address(0)) { + try IMessageInterceptor(messageInterceptor).onInboundMessage(any2EvmMessage) {} catch (bytes memory err) { revert IMessageInterceptor.MessageValidationError(err); } diff --git a/contracts/src/v0.8/ccip/onRamp/OnRamp.sol b/contracts/src/v0.8/ccip/onRamp/OnRamp.sol index a454293eb6..5b1795cd57 100644 --- a/contracts/src/v0.8/ccip/onRamp/OnRamp.sol +++ b/contracts/src/v0.8/ccip/onRamp/OnRamp.sol @@ -67,7 +67,7 @@ contract OnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCreator { // solhint-disable-next-line gas-struct-packing struct DynamicConfig { address feeQuoter; // FeeQuoter address - address messageValidator; // Optional message validator to validate outbound messages (zero address = no validator) + address messageInterceptor; // Optional message interceptor to validate outbound messages (zero address = no interceptor) address feeAggregator; // Fee aggregator address address allowListAdmin; // authorized admin to add or remove allowed senders } @@ -179,9 +179,9 @@ contract OnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCreator { { // scoped to reduce stack usage - address messageValidator = s_dynamicConfig.messageValidator; - if (messageValidator != address(0)) { - IMessageInterceptor(messageValidator).onOutboundMessage(destChainSelector, message); + address messageInterceptor = s_dynamicConfig.messageInterceptor; + if (messageInterceptor != address(0)) { + IMessageInterceptor(messageInterceptor).onOutboundMessage(destChainSelector, message); } } diff --git a/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol index b5fff3e9bd..febd577455 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol @@ -283,9 +283,9 @@ contract OffRamp_setDynamicConfig is OffRampSetup { _assertSameConfig(dynamicConfig, newConfig); } - function test_SetDynamicConfigWithValidator_Success() public { + function test_SetDynamicConfigWithInterceptor_Success() public { OffRamp.DynamicConfig memory dynamicConfig = _generateDynamicOffRampConfig(address(s_feeQuoter)); - dynamicConfig.messageValidator = address(s_inboundMessageValidator); + dynamicConfig.messageInterceptor = address(s_inboundMessageInterceptor); vm.expectEmit(); emit OffRamp.DynamicConfigSet(dynamicConfig); @@ -1038,10 +1038,10 @@ contract OffRamp_executeSingleMessage is OffRampSetup { s_offRamp.executeSingleMessage(message, offchainTokenData, new uint32[](0)); } - function test_executeSingleMessage_WithValidation_Success() public { + function test_executeSingleMessage_WithVInterception_Success() public { vm.stopPrank(); vm.startPrank(OWNER); - _enableInboundMessageValidator(); + _enableInboundMessageInterceptor(); vm.startPrank(address(s_offRamp)); Internal.Any2EVMRampMessage memory message = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); @@ -1108,11 +1108,11 @@ contract OffRamp_executeSingleMessage is OffRampSetup { function test_executeSingleMessage_WithFailingValidation_Revert() public { vm.stopPrank(); vm.startPrank(OWNER); - _enableInboundMessageValidator(); + _enableInboundMessageInterceptor(); vm.startPrank(address(s_offRamp)); Internal.Any2EVMRampMessage memory message = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, 1); - s_inboundMessageValidator.setMessageIdValidationState(message.header.messageId, true); + s_inboundMessageInterceptor.setMessageIdValidationState(message.header.messageId, true); vm.expectRevert( abi.encodeWithSelector( IMessageInterceptor.MessageValidationError.selector, @@ -1125,7 +1125,7 @@ contract OffRamp_executeSingleMessage is OffRampSetup { function test_executeSingleMessage_WithFailingValidationNoRouterCall_Revert() public { vm.stopPrank(); vm.startPrank(OWNER); - _enableInboundMessageValidator(); + _enableInboundMessageInterceptor(); vm.startPrank(address(s_offRamp)); Internal.Any2EVMRampMessage memory message = @@ -1136,7 +1136,7 @@ contract OffRamp_executeSingleMessage is OffRampSetup { message.receiver = address(newReceiver); message.header.messageId = Internal._hash(message, ON_RAMP_ADDRESS_1); - s_inboundMessageValidator.setMessageIdValidationState(message.header.messageId, true); + s_inboundMessageInterceptor.setMessageIdValidationState(message.header.messageId, true); vm.expectRevert( abi.encodeWithSelector( IMessageInterceptor.MessageValidationError.selector, @@ -2088,7 +2088,7 @@ contract OffRamp_execute is OffRampSetup { } function test_MultipleReportsWithPartialValidationFailures_Success() public { - _enableInboundMessageValidator(); + _enableInboundMessageInterceptor(); Internal.Any2EVMRampMessage[] memory messages1 = new Internal.Any2EVMRampMessage[](2); Internal.Any2EVMRampMessage[] memory messages2 = new Internal.Any2EVMRampMessage[](1); @@ -2101,8 +2101,8 @@ contract OffRamp_execute is OffRampSetup { reports[0] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages1); reports[1] = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages2); - s_inboundMessageValidator.setMessageIdValidationState(messages1[0].header.messageId, true); - s_inboundMessageValidator.setMessageIdValidationState(messages2[0].header.messageId, true); + s_inboundMessageInterceptor.setMessageIdValidationState(messages1[0].header.messageId, true); + s_inboundMessageInterceptor.setMessageIdValidationState(messages2[0].header.messageId, true); vm.expectEmit(); emit MultiOCR3Base.Transmitted( diff --git a/contracts/src/v0.8/ccip/test/offRamp/OffRampSetup.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRampSetup.t.sol index 393d35bdc9..c461e50c0b 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/OffRampSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRampSetup.t.sol @@ -42,7 +42,7 @@ contract OffRampSetup is FeeQuoterSetup, MultiOCR3BaseSetup { MaybeRevertingBurnMintTokenPool internal s_maybeRevertingPool; OffRampHelper internal s_offRamp; - MessageInterceptorHelper internal s_inboundMessageValidator; + MessageInterceptorHelper internal s_inboundMessageInterceptor; NonceManager internal s_inboundNonceManager; RMN internal s_realRMN; address internal s_sourceTokenPool = makeAddr("sourceTokenPool"); @@ -60,7 +60,7 @@ contract OffRampSetup is FeeQuoterSetup, MultiOCR3BaseSetup { FeeQuoterSetup.setUp(); MultiOCR3BaseSetup.setUp(); - s_inboundMessageValidator = new MessageInterceptorHelper(); + s_inboundMessageInterceptor = new MessageInterceptorHelper(); s_receiver = new MaybeRevertMessageReceiver(false); s_secondary_receiver = new MaybeRevertMessageReceiver(false); s_reverting_receiver = new MaybeRevertMessageReceiver(true); @@ -227,7 +227,7 @@ contract OffRampSetup is FeeQuoterSetup, MultiOCR3BaseSetup { return OffRamp.DynamicConfig({ permissionLessExecutionThresholdSeconds: PERMISSION_LESS_EXECUTION_THRESHOLD_SECONDS, feeQuoter: feeQuoter, - messageValidator: address(0) + messageInterceptor: address(0) }); } @@ -382,7 +382,7 @@ contract OffRampSetup is FeeQuoterSetup, MultiOCR3BaseSetup { function _assertSameConfig(OffRamp.DynamicConfig memory a, OffRamp.DynamicConfig memory b) public pure { assertEq(a.permissionLessExecutionThresholdSeconds, b.permissionLessExecutionThresholdSeconds); - assertEq(a.messageValidator, b.messageValidator); + assertEq(a.messageInterceptor, b.messageInterceptor); assertEq(a.feeQuoter, b.feeQuoter); } @@ -412,9 +412,9 @@ contract OffRampSetup is FeeQuoterSetup, MultiOCR3BaseSetup { return sourceTokenData; } - function _enableInboundMessageValidator() internal { + function _enableInboundMessageInterceptor() internal { OffRamp.DynamicConfig memory dynamicConfig = s_offRamp.getDynamicConfig(); - dynamicConfig.messageValidator = address(s_inboundMessageValidator); + dynamicConfig.messageInterceptor = address(s_inboundMessageInterceptor); s_offRamp.setDynamicConfig(dynamicConfig); } diff --git a/contracts/src/v0.8/ccip/test/onRamp/OnRamp.t.sol b/contracts/src/v0.8/ccip/test/onRamp/OnRamp.t.sol index 11b15048c1..da4e731344 100644 --- a/contracts/src/v0.8/ccip/test/onRamp/OnRamp.t.sol +++ b/contracts/src/v0.8/ccip/test/onRamp/OnRamp.t.sol @@ -363,8 +363,8 @@ contract OnRamp_forwardFromRouter is OnRampSetup { ); } - function test_forwardFromRouter_WithValidation_Success() public { - _enableOutboundMessageValidator(); + function test_forwardFromRouter_WithInterception_Success() public { + _enableOutboundMessageInterceptor(); Client.EVM2AnyMessage memory message = _generateEmptyMessage(); message.extraArgs = Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: GAS_LIMIT * 2})); @@ -373,7 +373,7 @@ contract OnRamp_forwardFromRouter is OnRampSetup { message.tokenAmounts[0].amount = 1e18; message.tokenAmounts[0].token = s_sourceTokens[0]; IERC20(s_sourceFeeToken).transferFrom(OWNER, address(s_onRamp), feeAmount); - s_outboundMessageValidator.setMessageIdValidationState(keccak256(abi.encode(message)), false); + s_outboundmessageInterceptor.setMessageIdValidationState(keccak256(abi.encode(message)), false); vm.expectEmit(); emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, _messageToEvent(message, 1, 1, feeAmount, OWNER)); @@ -420,8 +420,8 @@ contract OnRamp_forwardFromRouter is OnRampSetup { s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, _generateEmptyMessage(), 0, STRANGER); } - function test_MessageValidationError_Revert() public { - _enableOutboundMessageValidator(); + function test_MessageInterceptionError_Revert() public { + _enableOutboundMessageInterceptor(); Client.EVM2AnyMessage memory message = _generateEmptyMessage(); message.extraArgs = Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: GAS_LIMIT * 2})); @@ -430,7 +430,7 @@ contract OnRamp_forwardFromRouter is OnRampSetup { message.tokenAmounts[0].amount = 1e18; message.tokenAmounts[0].token = s_sourceTokens[0]; IERC20(s_sourceFeeToken).transferFrom(OWNER, address(s_onRamp), feeAmount); - s_outboundMessageValidator.setMessageIdValidationState(keccak256(abi.encode(message)), true); + s_outboundmessageInterceptor.setMessageIdValidationState(keccak256(abi.encode(message)), true); vm.expectRevert( abi.encodeWithSelector(IMessageInterceptor.MessageValidationError.selector, bytes("Invalid message")) @@ -671,7 +671,7 @@ contract OnRamp_setDynamicConfig is OnRampSetup { OnRamp.StaticConfig memory staticConfig = s_onRamp.getStaticConfig(); OnRamp.DynamicConfig memory newConfig = OnRamp.DynamicConfig({ feeQuoter: address(23423), - messageValidator: makeAddr("messageValidator"), + messageInterceptor: makeAddr("messageInterceptor"), feeAggregator: FEE_AGGREGATOR, allowListAdmin: address(0) }); @@ -691,7 +691,7 @@ contract OnRamp_setDynamicConfig is OnRampSetup { OnRamp.DynamicConfig memory newConfig = OnRamp.DynamicConfig({ feeQuoter: address(0), feeAggregator: FEE_AGGREGATOR, - messageValidator: makeAddr("messageValidator"), + messageInterceptor: makeAddr("messageInterceptor"), allowListAdmin: address(0) }); @@ -702,7 +702,7 @@ contract OnRamp_setDynamicConfig is OnRampSetup { function test_SetConfigInvalidConfig_Revert() public { OnRamp.DynamicConfig memory newConfig = OnRamp.DynamicConfig({ feeQuoter: address(23423), - messageValidator: address(0), + messageInterceptor: address(0), feeAggregator: FEE_AGGREGATOR, allowListAdmin: address(0) }); @@ -716,7 +716,7 @@ contract OnRamp_setDynamicConfig is OnRampSetup { function test_SetConfigInvalidConfigFeeAggregatorEqAddressZero_Revert() public { OnRamp.DynamicConfig memory newConfig = OnRamp.DynamicConfig({ feeQuoter: address(23423), - messageValidator: address(0), + messageInterceptor: address(0), feeAggregator: address(0), allowListAdmin: address(0) }); diff --git a/contracts/src/v0.8/ccip/test/onRamp/OnRampSetup.t.sol b/contracts/src/v0.8/ccip/test/onRamp/OnRampSetup.t.sol index 4c43c16f59..9ff7161696 100644 --- a/contracts/src/v0.8/ccip/test/onRamp/OnRampSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/onRamp/OnRampSetup.t.sol @@ -22,14 +22,14 @@ contract OnRampSetup is FeeQuoterFeeSetup { bytes32 internal s_metadataHash; OnRampHelper internal s_onRamp; - MessageInterceptorHelper internal s_outboundMessageValidator; + MessageInterceptorHelper internal s_outboundmessageInterceptor; address[] internal s_offRamps; NonceManager internal s_outboundNonceManager; function setUp() public virtual override { super.setUp(); - s_outboundMessageValidator = new MessageInterceptorHelper(); + s_outboundmessageInterceptor = new MessageInterceptorHelper(); s_outboundNonceManager = new NonceManager(new address[](0)); (s_onRamp, s_metadataHash) = _deployOnRamp( SOURCE_CHAIN_SELECTOR, s_sourceRouter, address(s_outboundNonceManager), address(s_tokenAdminRegistry) @@ -87,7 +87,7 @@ contract OnRampSetup is FeeQuoterFeeSetup { function _generateDynamicOnRampConfig(address feeQuoter) internal pure returns (OnRamp.DynamicConfig memory) { return OnRamp.DynamicConfig({ feeQuoter: feeQuoter, - messageValidator: address(0), + messageInterceptor: address(0), feeAggregator: FEE_AGGREGATOR, allowListAdmin: address(0) }); @@ -138,7 +138,7 @@ contract OnRampSetup is FeeQuoterFeeSetup { ); } - function _enableOutboundMessageValidator() internal { + function _enableOutboundMessageInterceptor() internal { (, address msgSender,) = vm.readCallers(); bool resetPrank = false; @@ -150,7 +150,7 @@ contract OnRampSetup is FeeQuoterFeeSetup { } OnRamp.DynamicConfig memory dynamicConfig = s_onRamp.getDynamicConfig(); - dynamicConfig.messageValidator = address(s_outboundMessageValidator); + dynamicConfig.messageInterceptor = address(s_outboundmessageInterceptor); s_onRamp.setDynamicConfig(dynamicConfig); if (resetPrank) { diff --git a/core/gethwrappers/ccip/deployment_test/deployment_test.go b/core/gethwrappers/ccip/deployment_test/deployment_test.go index 0d91d63b0a..295dee120f 100644 --- a/core/gethwrappers/ccip/deployment_test/deployment_test.go +++ b/core/gethwrappers/ccip/deployment_test/deployment_test.go @@ -48,7 +48,7 @@ func TestDeployAllV1_6(t *testing.T) { }, offramp.OffRampDynamicConfig{ FeeQuoter: common.HexToAddress("0x4"), PermissionLessExecutionThresholdSeconds: uint32((8 * time.Hour).Seconds()), - MessageValidator: common.HexToAddress("0x5"), + MessageInterceptor: common.HexToAddress("0x5"), }, nil) require.NoError(t, err) chain.Commit() @@ -60,10 +60,10 @@ func TestDeployAllV1_6(t *testing.T) { NonceManager: common.HexToAddress("0x2"), TokenAdminRegistry: common.HexToAddress("0x3"), }, onramp.OnRampDynamicConfig{ - FeeQuoter: common.HexToAddress("0x4"), - MessageValidator: common.HexToAddress("0x5"), - FeeAggregator: common.HexToAddress("0x6"), - AllowListAdmin: common.HexToAddress("0x7"), + FeeQuoter: common.HexToAddress("0x4"), + MessageInterceptor: common.HexToAddress("0x5"), + FeeAggregator: common.HexToAddress("0x6"), + AllowListAdmin: common.HexToAddress("0x7"), }, nil) require.NoError(t, err) chain.Commit() diff --git a/core/gethwrappers/ccip/generated/offramp/offramp.go b/core/gethwrappers/ccip/generated/offramp/offramp.go index 1cae9daaa3..2ff1011ab7 100644 --- a/core/gethwrappers/ccip/generated/offramp/offramp.go +++ b/core/gethwrappers/ccip/generated/offramp/offramp.go @@ -124,7 +124,7 @@ type MultiOCR3BaseOCRConfigArgs struct { type OffRampDynamicConfig struct { FeeQuoter common.Address PermissionLessExecutionThresholdSeconds uint32 - MessageValidator common.Address + MessageInterceptor common.Address } type OffRampGasLimitOverride struct { @@ -154,7 +154,7 @@ type OffRampStaticConfig struct { } var OffRampMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CanOnlySelfCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"reportOnRamp\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"configOnRamp\",\"type\":\"bytes\"}],\"name\":\"CommitOnRampMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"actual\",\"type\":\"bytes32\"}],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ExecutionError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"ForkedChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enumMultiOCR3Base.InvalidConfigErrorType\",\"name\":\"errorType\",\"type\":\"uint8\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"got\",\"type\":\"uint256\"}],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidEVMAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"name\":\"InvalidInterval\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"newLimit\",\"type\":\"uint256\"}],\"name\":\"InvalidManualExecutionGasLimit\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"tokenIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"oldLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenGasOverride\",\"type\":\"uint256\"}],\"name\":\"InvalidManualExecutionTokenGasOverride\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"messageDestChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidMessageDestChainSelector\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"newState\",\"type\":\"uint8\"}],\"name\":\"InvalidNewState\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidOnRampUpdate\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRoot\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LeavesCannotBeEmpty\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"ManualExecutionGasAmountCountMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ManualExecutionGasLimitMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"ManualExecutionNotYetEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"errorReason\",\"type\":\"bytes\"}],\"name\":\"MessageValidationError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonUniqueSignatures\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"notPool\",\"type\":\"address\"}],\"name\":\"NotACompatiblePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OracleCannotBeZeroAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ReceiverError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountReleased\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePre\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePost\",\"type\":\"uint256\"}],\"name\":\"ReleaseOrMintBalanceMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"name\":\"RootAlreadyCommitted\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"RootNotCommitted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignatureVerificationDisabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignaturesOutOfRegistration\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"reportSourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"messageSourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainSelectorMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"StaleCommitReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"StaticConfigCannotBeChanged\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"TokenDataMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"TokenHandlingError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnexpectedTokenData\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"WrongMessageLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WrongNumberOfSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroChainSelectorNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"AlreadyAttempted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"indexed\":false,\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"}],\"name\":\"CommitReportAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"DynamicConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"messageHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"name\":\"ExecutionStateChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"RootRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"SkippedAlreadyExecutedMessage\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SkippedReportExecution\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"sourceConfig\",\"type\":\"tuple\"}],\"name\":\"SourceChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainSelectorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"}],\"name\":\"StaticConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigUpdates\",\"type\":\"tuple[]\"}],\"name\":\"applySourceChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"destTokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structClient.Any2EVMMessage\",\"name\":\"\",\"type\":\"tuple\"}],\"name\":\"ccipReceive\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"rawVs\",\"type\":\"bytes32\"}],\"name\":\"commit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"execute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"bytes[]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[]\"},{\"internalType\":\"uint32[]\",\"name\":\"tokenGasOverrides\",\"type\":\"uint32[]\"}],\"name\":\"executeSingleMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"getExecutionState\",\"outputs\":[{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLatestPriceSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"getMerkleRoot\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"getSourceChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"latestConfigDetails\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"n\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"}],\"internalType\":\"structMultiOCR3Base.ConfigInfo\",\"name\":\"configInfo\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfig\",\"name\":\"ocrConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage[]\",\"name\":\"messages\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[][]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[][]\"},{\"internalType\":\"bytes32[]\",\"name\":\"proofs\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"proofFlagBits\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.ExecutionReportSingleChain[]\",\"name\":\"reports\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"receiverExecutionGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint32[]\",\"name\":\"tokenGasOverrides\",\"type\":\"uint32[]\"}],\"internalType\":\"structOffRamp.GasLimitOverride[][]\",\"name\":\"gasLimitOverrides\",\"type\":\"tuple[][]\"}],\"name\":\"manuallyExecute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"setDynamicConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfigArgs[]\",\"name\":\"ocrConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"setOCR3Configs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CanOnlySelfCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"reportOnRamp\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"configOnRamp\",\"type\":\"bytes\"}],\"name\":\"CommitOnRampMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"actual\",\"type\":\"bytes32\"}],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ExecutionError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"ForkedChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enumMultiOCR3Base.InvalidConfigErrorType\",\"name\":\"errorType\",\"type\":\"uint8\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"got\",\"type\":\"uint256\"}],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidEVMAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"name\":\"InvalidInterval\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"newLimit\",\"type\":\"uint256\"}],\"name\":\"InvalidManualExecutionGasLimit\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"tokenIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"oldLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenGasOverride\",\"type\":\"uint256\"}],\"name\":\"InvalidManualExecutionTokenGasOverride\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"messageDestChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidMessageDestChainSelector\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"newState\",\"type\":\"uint8\"}],\"name\":\"InvalidNewState\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidOnRampUpdate\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRoot\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LeavesCannotBeEmpty\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"ManualExecutionGasAmountCountMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ManualExecutionGasLimitMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"ManualExecutionNotYetEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"errorReason\",\"type\":\"bytes\"}],\"name\":\"MessageValidationError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonUniqueSignatures\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"notPool\",\"type\":\"address\"}],\"name\":\"NotACompatiblePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OracleCannotBeZeroAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ReceiverError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountReleased\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePre\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePost\",\"type\":\"uint256\"}],\"name\":\"ReleaseOrMintBalanceMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"name\":\"RootAlreadyCommitted\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"RootNotCommitted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignatureVerificationDisabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignaturesOutOfRegistration\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"reportSourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"messageSourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainSelectorMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"StaleCommitReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"StaticConfigCannotBeChanged\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"TokenDataMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"TokenHandlingError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnexpectedTokenData\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"WrongMessageLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WrongNumberOfSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroChainSelectorNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"AlreadyAttempted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"indexed\":false,\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"}],\"name\":\"CommitReportAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"DynamicConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"messageHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"name\":\"ExecutionStateChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"RootRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"SkippedAlreadyExecutedMessage\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SkippedReportExecution\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"sourceConfig\",\"type\":\"tuple\"}],\"name\":\"SourceChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainSelectorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"}],\"name\":\"StaticConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigUpdates\",\"type\":\"tuple[]\"}],\"name\":\"applySourceChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"destTokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structClient.Any2EVMMessage\",\"name\":\"\",\"type\":\"tuple\"}],\"name\":\"ccipReceive\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"rawVs\",\"type\":\"bytes32\"}],\"name\":\"commit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"execute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"bytes[]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[]\"},{\"internalType\":\"uint32[]\",\"name\":\"tokenGasOverrides\",\"type\":\"uint32[]\"}],\"name\":\"executeSingleMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"getExecutionState\",\"outputs\":[{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLatestPriceSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"getMerkleRoot\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"getSourceChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"latestConfigDetails\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"n\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"}],\"internalType\":\"structMultiOCR3Base.ConfigInfo\",\"name\":\"configInfo\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfig\",\"name\":\"ocrConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage[]\",\"name\":\"messages\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[][]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[][]\"},{\"internalType\":\"bytes32[]\",\"name\":\"proofs\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"proofFlagBits\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.ExecutionReportSingleChain[]\",\"name\":\"reports\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"receiverExecutionGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint32[]\",\"name\":\"tokenGasOverrides\",\"type\":\"uint32[]\"}],\"internalType\":\"structOffRamp.GasLimitOverride[][]\",\"name\":\"gasLimitOverrides\",\"type\":\"tuple[][]\"}],\"name\":\"manuallyExecute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"setDynamicConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfigArgs[]\",\"name\":\"ocrConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"setOCR3Configs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", Bin: "0x6101206040523480156200001257600080fd5b506040516200689b3803806200689b833981016040819052620000359162000806565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf81620001fa565b5050466080525060208301516001600160a01b03161580620000ec575060408301516001600160a01b0316155b8062000103575060608301516001600160a01b0316155b1562000122576040516342bcdf7f60e11b815260040160405180910390fd5b82516001600160401b03166000036200014e5760405163c656089560e01b815260040160405180910390fd5b82516001600160401b0390811660a052602080850180516001600160a01b0390811660c05260408088018051831660e0526060808a01805185166101005283518b519098168852945184169587019590955251821690850152905116908201527f683eb52ee924eb817377cfa8f41f238f4bb7a877da5267869dfffbad85f564d89060800160405180910390a1620001e682620002a5565b620001f1816200036d565b50505062000b8d565b336001600160a01b03821603620002545760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b0316620002ce576040516342bcdf7f60e11b815260040160405180910390fd5b805160048054602080850180516001600160a01b039586166001600160c01b03199094168417600160a01b63ffffffff928316021790945560408087018051600580546001600160a01b031916918916919091179055815194855291519094169183019190915251909216908201527fa1c15688cb2c24508e158f6942b9276c6f3028a85e1af8cf3fff0c3ff3d5fc8d9060600160405180910390a150565b60005b8151811015620005ba57600082828151811062000391576200039162000943565b60200260200101519050600081602001519050806001600160401b0316600003620003cf5760405163c656089560e01b815260040160405180910390fd5b81516001600160a01b0316620003f8576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160401b03811660009081526006602052604090206060830151600182018054620004269062000959565b905060000362000489578154600160a81b600160e81b031916600160a81b1782556040516001600160401b03841681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1620004c8565b8154600160a81b90046001600160401b0316600114620004c857604051632105803760e11b81526001600160401b038416600482015260240162000083565b80511580620004fe5750604080516000602082015201604051602081830303815290604052805190602001208180519060200120145b156200051d576040516342bcdf7f60e11b815260040160405180910390fd5b600182016200052d8282620009ea565b50604080850151835486516001600160a01b03166001600160a01b0319921515600160a01b02929092166001600160a81b031990911617178355516001600160401b038416907f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b90620005a290859062000ab6565b60405180910390a25050505080600101905062000370565b5050565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b0381118282101715620005f957620005f9620005be565b60405290565b604051601f8201601f191681016001600160401b03811182821017156200062a576200062a620005be565b604052919050565b80516001600160401b03811681146200064a57600080fd5b919050565b6001600160a01b03811681146200066557600080fd5b50565b6000601f83601f8401126200067c57600080fd5b825160206001600160401b03808311156200069b576200069b620005be565b8260051b620006ac838201620005ff565b9384528681018301938381019089861115620006c757600080fd5b84890192505b85831015620007f957825184811115620006e75760008081fd5b89016080601f19828d038101821315620007015760008081fd5b6200070b620005d4565b888401516200071a816200064f565b815260406200072b85820162000632565b8a8301526060808601518015158114620007455760008081fd5b838301529385015193898511156200075d5760008081fd5b84860195508f603f8701126200077557600094508485fd5b8a8601519450898511156200078e576200078e620005be565b6200079f8b858f88011601620005ff565b93508484528f82868801011115620007b75760008081fd5b60005b85811015620007d7578681018301518582018d01528b01620007ba565b5060009484018b019490945250918201528352509184019190840190620006cd565b9998505050505050505050565b60008060008385036101008112156200081e57600080fd5b60808112156200082d57600080fd5b62000837620005d4565b620008428662000632565b8152602086015162000854816200064f565b6020820152604086015162000869816200064f565b604082015260608601516200087e816200064f565b606082810191909152909450607f19820112156200089b57600080fd5b50604051606081016001600160401b038082118383101715620008c257620008c2620005be565b8160405260808701519150620008d8826200064f565b90825260a08601519063ffffffff82168214620008f457600080fd5b81602084015260c087015191506200090c826200064f565b6040830182905260e0870151929450808311156200092957600080fd5b5050620009398682870162000668565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b600181811c908216806200096e57607f821691505b6020821081036200098f57634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115620009e5576000816000526020600020601f850160051c81016020861015620009c05750805b601f850160051c820191505b81811015620009e157828155600101620009cc565b5050505b505050565b81516001600160401b0381111562000a065762000a06620005be565b62000a1e8162000a17845462000959565b8462000995565b602080601f83116001811462000a56576000841562000a3d5750858301515b600019600386901b1c1916600185901b178555620009e1565b600085815260208120601f198616915b8281101562000a875788860151825594840194600190910190840162000a66565b508582101562000aa65787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b602080825282546001600160a01b0381168383015260a081901c60ff161515604084015260a81c6001600160401b0316606083015260808083015260018084018054600093929190849062000b0b8162000959565b8060a089015260c0600183166000811462000b2f576001811462000b4c5762000b7e565b60ff19841660c08b015260c083151560051b8b0101945062000b7e565b85600052602060002060005b8481101562000b755781548c820185015290880190890162000b58565b8b0160c0019550505b50929998505050505050505050565b60805160a05160c05160e05161010051615c9862000c036000396000818161022c01526129260152600081816101fd0152612bf80152600081816101ce01528181610552015281816106ff015261236a01526000818161019f01526125a9015260008181611d920152611dc50152615c986000f3fe608060405234801561001057600080fd5b50600436106101515760003560e01c806379ba5097116100cd578063d434969111610081578063e9d68a8e11610066578063e9d68a8e146104bc578063f2fde38b146104dc578063f716f99f146104ef57600080fd5b8063d434969114610496578063e62653f5146104a957600080fd5b80638da5cb5b116100b25780638da5cb5b14610417578063c673e58414610432578063ccd37ba31461045257600080fd5b806379ba50971461040157806385572ffb1461040957600080fd5b8063311cd513116101245780635e36480c116101095780635e36480c1461033c5780636f9e320f1461035c5780637437ff9f1461036f57600080fd5b8063311cd5131461030e5780633f4b04aa1461032157600080fd5b806304666f9c1461015657806306285c691461016b578063181f5a77146102b25780632d04ab76146102fb575b600080fd5b610169610164366004613bbf565b610502565b005b61025c60408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160401b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316815250905090565b6040516102a9919081516001600160401b031681526020808301516001600160a01b0390811691830191909152604080840151821690830152606092830151169181019190915260800190565b60405180910390f35b6102ee6040518060400160405280601181526020017f4f666652616d7020312e362e302d64657600000000000000000000000000000081525081565b6040516102a99190613d2d565b610169610309366004613ddd565b610516565b61016961031c366004613e8f565b610a12565b6009546040516001600160401b0390911681526020016102a9565b61034f61034a366004613ee2565b610a7b565b6040516102a99190613f3f565b61016961036a366004613f6a565b610ad0565b6103cb604080516060810182526000808252602082018190529181019190915250604080516060810182526004546001600160a01b038082168352600160a01b90910463ffffffff166020830152600554169181019190915290565b6040805182516001600160a01b03908116825260208085015163ffffffff169083015292820151909216908201526060016102a9565b610169610ae1565b610169610151366004613fbe565b6000546040516001600160a01b0390911681526020016102a9565b610445610440366004614009565b610b92565b6040516102a99190614069565b6104886104603660046140de565b6001600160401b03919091166000908152600860209081526040808320938352929052205490565b6040519081526020016102a9565b6101696104a436600461437a565b610cf0565b6101696104b7366004614702565b610fd0565b6104cf6104ca366004614949565b611277565b6040516102a99190614964565b6101696104ea3660046149b1565b611383565b6101696104fd366004614a36565b611394565b61050a6113d6565b61051381611432565b50565b600061052487890189614d8b565b602081015151909150156105b6576020810151604080830151905162ccd5af60e81b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169263ccd5af009261058592600401614fb3565b60006040518083038186803b15801561059d57600080fd5b505afa1580156105b1573d6000803e3d6000fd5b505050505b805151511515806105cc57508051602001515115155b156106985760095460208a0135906001600160401b0380831691161015610670576009805467ffffffffffffffff19166001600160401b038316179055600480548351604051633937306f60e01b81526001600160a01b0390921692633937306f926106399291016150e7565b600060405180830381600087803b15801561065357600080fd5b505af1158015610667573d6000803e3d6000fd5b50505050610696565b81602001515160000361069657604051632261116760e01b815260040160405180910390fd5b505b60005b816020015151811015610953576000826020015182815181106106c0576106c0615015565b60209081029190910101518051604051632cbc26bb60e01b815267ffffffffffffffff60801b608083901b166004820152919250906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632cbc26bb90602401602060405180830381865afa158015610746573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061076a91906150fa565b1561079857604051637edeb53960e11b81526001600160401b03821660048201526024015b60405180910390fd5b60006107a382611685565b9050806001016040516107b69190615151565b6040518091039020836020015180519060200120146107f35782602001518160010160405163b80d8fa960e01b815260040161078f929190615244565b60408301518154600160a81b90046001600160401b039081169116141580610834575082606001516001600160401b031683604001516001600160401b0316115b1561087957825160408085015160608601519151636af0786b60e11b81526001600160401b03938416600482015290831660248201529116604482015260640161078f565b60808301518061089c5760405163504570e360e01b815260040160405180910390fd5b83516001600160401b03166000908152600860209081526040808320848452909152902054156108f45783516040516332cf0cbf60e01b81526001600160401b0390911660048201526024810182905260440161078f565b606084015161090490600161527f565b825467ffffffffffffffff60a81b1916600160a81b6001600160401b0392831602179092559251166000908152600860209081526040808320948352939052919091204290555060010161069b565b50602081015181516040517f35c02761bcd3ef995c6a601a1981f4ed3934dcbe5041e24e286c89f5531d17e49261098b9290916152a6565b60405180910390a1610a0760008a8a8a8a8a8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808e0282810182019093528d82529093508d92508c9182918501908490808284376000920191909152508b92506116d1915050565b505050505050505050565b610a52610a21828401846152cb565b6040805160008082526020820190925290610a4c565b6060815260200190600190039081610a375790505b506119ca565b604080516000808252602082019092529050610a756001858585858660006116d1565b50505050565b6000610a89600160046152ff565b6002610a96608085615328565b6001600160401b0316610aa9919061534e565b610ab38585611a8c565b901c166003811115610ac757610ac7613f15565b90505b92915050565b610ad86113d6565b61051381611ad1565b6001546001600160a01b03163314610b3b5760405162461bcd60e51b815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e657200000000000000000000604482015260640161078f565b60008054336001600160a01b0319808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610bd56040805160e081019091526000606082018181526080830182905260a0830182905260c08301919091528190815260200160608152602001606081525090565b60ff808316600090815260026020818152604092839020835160e081018552815460608201908152600183015480881660808401526101008104881660a0840152620100009004909616151560c082015294855291820180548451818402810184019095528085529293858301939092830182828015610c7e57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610c60575b5050505050815260200160038201805480602002602001604051908101604052809291908181526020018280548015610ce057602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610cc2575b5050505050815250509050919050565b333014610d10576040516306e34e6560e31b815260040160405180910390fd5b6040805160008082526020820190925281610d4d565b6040805180820190915260008082526020820152815260200190600190039081610d265790505b5060a08701515190915015610d8357610d808660a001518760200151886060015189600001516020015189898989611bb0565b90505b6040805160a081018252875151815287516020908101516001600160401b031681830152808901518351600094840192610dbe929101613d2d565b60408051601f19818403018152918152908252898101516020830152018390526005549091506001600160a01b03168015610e99576040516308d450a160e01b81526001600160a01b038216906308d450a190610e1f908590600401615406565b600060405180830381600087803b158015610e3957600080fd5b505af1925050508015610e4a575060015b610e99573d808015610e78576040519150601f19603f3d011682016040523d82523d6000602084013e610e7d565b606091505b50806040516309c2532560e01b815260040161078f9190613d2d565b604088015151158015610eae57506080880151155b80610ec5575060608801516001600160a01b03163b155b80610eec57506060880151610eea906001600160a01b03166385572ffb60e01b611d73565b155b15610ef957505050610fc9565b87516020908101516001600160401b03166000908152600690915260408082205460808b015160608c01519251633cf9798360e01b815284936001600160a01b0390931692633cf9798392610f579289926113889291600401615419565b6000604051808303816000875af1158015610f76573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610f9e9190810190615455565b509150915081610fc357806040516302a35ba360e21b815260040161078f9190613d2d565b50505050505b5050505050565b610fd8611d8f565b815181518114610ffb576040516320f8fd5960e21b815260040160405180910390fd5b60005b8181101561126757600084828151811061101a5761101a615015565b6020026020010151905060008160200151519050600085848151811061104257611042615015565b602002602001015190508051821461106d576040516320f8fd5960e21b815260040160405180910390fd5b60005b8281101561125857600082828151811061108c5761108c615015565b60200260200101516000015190506000856020015183815181106110b2576110b2615015565b6020026020010151905081600014611106578060800151821015611106578551815151604051633a98d46360e11b81526001600160401b03909216600483015260248201526044810183905260640161078f565b83838151811061111857611118615015565b602002602001015160200151518160a00151511461116557805180516060909101516040516370a193fd60e01b815260048101929092526001600160401b0316602482015260440161078f565b60005b8160a001515181101561124a57600085858151811061118957611189615015565b60200260200101516020015182815181106111a6576111a6615015565b602002602001015163ffffffff169050806000146112415760008360a0015183815181106111d6576111d6615015565b6020026020010151608001518060200190518101906111f591906154ea565b90508063ffffffff1682101561123f578351516040516348e617b360e01b815260048101919091526024810184905263ffffffff821660448201526064810183905260840161078f565b505b50600101611168565b505050806001019050611070565b50505050806001019050610ffe565b5061127283836119ca565b505050565b60408051608080820183526000808352602080840182905283850182905260608085018190526001600160401b03878116845260068352928690208651948501875280546001600160a01b0381168652600160a01b810460ff16151593860193909352600160a81b90920490921694830194909452600184018054939492939184019161130390615117565b80601f016020809104026020016040519081016040528092919081815260200182805461132f90615117565b8015610ce05780601f1061135157610100808354040283529160200191610ce0565b820191906000526020600020905b81548152906001019060200180831161135f57505050919092525091949350505050565b61138b6113d6565b61051381611df7565b61139c6113d6565b60005b81518110156113d2576113ca8282815181106113bd576113bd615015565b6020026020010151611ea0565b60010161139f565b5050565b6000546001600160a01b031633146114305760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640161078f565b565b60005b81518110156113d257600082828151811061145257611452615015565b60200260200101519050600081602001519050806001600160401b031660000361148f5760405163c656089560e01b815260040160405180910390fd5b81516001600160a01b03166114b7576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160401b038116600090815260066020526040902060608301516001820180546114e390615117565b905060000361154557815467ffffffffffffffff60a81b1916600160a81b1782556040516001600160401b03841681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1611582565b8154600160a81b90046001600160401b031660011461158257604051632105803760e11b81526001600160401b038416600482015260240161078f565b805115806115b75750604080516000602082015201604051602081830303815290604052805190602001208180519060200120145b156115d5576040516342bcdf7f60e11b815260040160405180910390fd5b600182016115e38282615557565b50604080850151835486516001600160a01b03166001600160a01b0319921515600160a01b02929092167fffffffffffffffffffffff00000000000000000000000000000000000000000090911617178355516001600160401b038416907f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b9061166e908590615616565b60405180910390a250505050806001019050611435565b6001600160401b03811660009081526006602052604081208054600160a01b900460ff16610aca5760405163ed053c5960e01b81526001600160401b038416600482015260240161078f565b60ff878116600090815260026020908152604080832081516080810183528154815260019091015480861693820193909352610100830485169181019190915262010000909104909216151560608301528735906117308760a4615664565b905082606001511561177857845161174990602061534e565b865161175690602061534e565b6117619060a0615664565b61176b9190615664565b6117759082615664565b90505b3681146117a157604051638e1192e160e01b81526004810182905236602482015260440161078f565b50815181146117d05781516040516324f7d61360e21b815260048101919091526024810182905260440161078f565b6117d8611d8f565b60ff808a166000908152600360209081526040808320338452825280832081518083019092528054808616835293949193909284019161010090910416600281111561182657611826613f15565b600281111561183757611837613f15565b905250905060028160200151600281111561185457611854613f15565b1480156118a85750600260008b60ff1660ff168152602001908152602001600020600301816000015160ff168154811061189057611890615015565b6000918252602090912001546001600160a01b031633145b6118c557604051631b41e11d60e31b815260040160405180910390fd5b508160600151156119755760208201516118e0906001615677565b60ff16855114611903576040516371253a2560e01b815260040160405180910390fd5b83518551146119255760405163a75d88af60e01b815260040160405180910390fd5b60008787604051611937929190615690565b60405190819003812061194e918b906020016156a0565b6040516020818303038152906040528051906020012090506119738a8288888861217f565b505b6040805182815260208a8101356001600160401b03169082015260ff8b16917f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef0910160405180910390a2505050505050505050565b81516000036119eb5760405162bf199760e01b815260040160405180910390fd5b80516040805160008082526020820190925291159181611a2e565b604080518082019091526000815260606020820152815260200190600190039081611a065790505b50905060005b8451811015610fc957611a84858281518110611a5257611a52615015565b602002602001015184611a7e57858381518110611a7157611a71615015565b602002602001015161233c565b8361233c565b600101611a34565b6001600160401b038216600090815260076020526040812081611ab06080856156b4565b6001600160401b031681526020810191909152604001600020549392505050565b80516001600160a01b0316611af9576040516342bcdf7f60e11b815260040160405180910390fd5b805160048054602080850180516001600160a01b039586167fffffffffffffffff0000000000000000000000000000000000000000000000009094168417600160a01b63ffffffff928316021790945560408087018051600580546001600160a01b031916918916919091179055815194855291519094169183019190915251909216908201527fa1c15688cb2c24508e158f6942b9276c6f3028a85e1af8cf3fff0c3ff3d5fc8d9060600160405180910390a150565b606088516001600160401b03811115611bcb57611bcb6139df565b604051908082528060200260200182016040528015611c1057816020015b6040805180820190915260008082526020820152815260200190600190039081611be95790505b509050811560005b8a51811015611d655781611cc257848482818110611c3857611c38615015565b9050602002016020810190611c4d91906156da565b63ffffffff1615611cc257848482818110611c6a57611c6a615015565b9050602002016020810190611c7f91906156da565b6040805163ffffffff9092166020830152016040516020818303038152906040528b8281518110611cb257611cb2615015565b6020026020010151608001819052505b611d408b8281518110611cd757611cd7615015565b60200260200101518b8b8b8b8b87818110611cf457611cf4615015565b9050602002810190611d0691906156f7565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612bb092505050565b838281518110611d5257611d52615015565b6020908102919091010152600101611c18565b505098975050505050505050565b6000611d7e83612eae565b8015610ac75750610ac78383612ef9565b467f00000000000000000000000000000000000000000000000000000000000000001461143057604051630f01ce8560e01b81527f0000000000000000000000000000000000000000000000000000000000000000600482015246602482015260440161078f565b336001600160a01b03821603611e4f5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161078f565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b806040015160ff16600003611ecb576000604051631b3fab5160e11b815260040161078f919061573d565b60208082015160ff80821660009081526002909352604083206001810154929390928392169003611f1c576060840151600182018054911515620100000262ff000019909216919091179055611f58565b6060840151600182015460ff6201000090910416151590151514611f58576040516321fd80df60e21b815260ff8416600482015260240161078f565b60a084015180516101001015611f84576001604051631b3fab5160e11b815260040161078f919061573d565b611fea8484600301805480602002602001604051908101604052809291908181526020018280548015611fe057602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611fc2575b5050505050612f9b565b8460600151156120f4576120588484600201805480602002602001604051908101604052809291908181526020018280548015611fe0576020028201919060005260206000209081546001600160a01b03168152600190910190602001808311611fc2575050505050612f9b565b608085015180516101001015612084576002604051631b3fab5160e11b815260040161078f919061573d565b6040860151612094906003615757565b60ff168151116120ba576003604051631b3fab5160e11b815260040161078f919061573d565b805160018401805461ff00191661010060ff8416021790556120e59060028601906020840190613965565b506120f285826001613004565b505b61210084826002613004565b80516121159060038501906020840190613965565b5060408581015160018401805460ff191660ff8316179055865180855560a088015192517fab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f5479361216e9389939260028a01929190615773565b60405180910390a1610fc98461315f565b8251600090815b818110156123325760006001888684602081106121a5576121a5615015565b6121b291901a601b615677565b8985815181106121c4576121c4615015565b60200260200101518986815181106121de576121de615015565b60200260200101516040516000815260200160405260405161221c949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa15801561223e573d6000803e3d6000fd5b505060408051601f1981015160ff808e166000908152600360209081528582206001600160a01b0385168352815285822085870190965285548084168652939750909550929392840191610100900416600281111561229f5761229f613f15565b60028111156122b0576122b0613f15565b90525090506001816020015160028111156122cd576122cd613f15565b146122eb57604051636518c33d60e11b815260040160405180910390fd5b8051600160ff9091161b85161561231557604051633d9ef1f160e21b815260040160405180910390fd5b806000015160ff166001901b851794505050806001019050612186565b5050505050505050565b81518151604051632cbc26bb60e01b8152608083901b67ffffffffffffffff60801b166004820152901515907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632cbc26bb90602401602060405180830381865afa1580156123b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123dd91906150fa565b1561244e57801561240c57604051637edeb53960e11b81526001600160401b038316600482015260240161078f565b6040516001600160401b03831681527faab522ed53d887e56ed53dd37398a01aeef6a58e0fa77c2173beb9512d8949339060200160405180910390a150505050565b600061245983611685565b600101805461246790615117565b80601f016020809104026020016040519081016040528092919081815260200182805461249390615117565b80156124e05780601f106124b5576101008083540402835291602001916124e0565b820191906000526020600020905b8154815290600101906020018083116124c357829003601f168201915b5050506020880151519293505050600081900361250f5760405162bf199760e01b815260040160405180910390fd5b8560400151518114612534576040516357e0e08360e01b815260040160405180910390fd5b6000816001600160401b0381111561254e5761254e6139df565b604051908082528060200260200182016040528015612577578160200160208202803683370190505b50905060005b828110156126985760008860200151828151811061259d5761259d615015565b602002602001015190507f00000000000000000000000000000000000000000000000000000000000000006001600160401b03168160000151604001516001600160401b0316146126145780516040908101519051631c21951160e11b81526001600160401b03909116600482015260240161078f565b866001600160401b03168160000151602001516001600160401b03161461266857805160200151604051636c95f1eb60e01b81526001600160401b03808a166004830152909116602482015260440161078f565b61267281866131b6565b83838151811061268457612684615015565b60209081029190910101525060010161257d565b5060006126af86838a606001518b608001516132d8565b9050806000036126dd57604051633ee8bd3f60e11b81526001600160401b038716600482015260240161078f565b60005b83811015610a075760005a905060008a60200151838151811061270557612705615015565b6020026020010151905060006127238a836000015160600151610a7b565b9050600081600381111561273957612739613f15565b14806127565750600381600381111561275457612754613f15565b145b6127ac57815160600151604080516001600160401b03808e16825290921660208301527f3b575419319662b2a6f5e2467d84521517a3382b908eb3d557bb3fdb0c50e23c910160405180910390a1505050612ba8565b6060891561288b578b85815181106127c6576127c6615015565b6020908102919091018101510151600454909150600090600160a01b900463ffffffff166127f488426152ff565b11905080806128145750600383600381111561281257612812613f15565b145b61283c576040516354e7e43160e11b81526001600160401b038d16600482015260240161078f565b8c868151811061284e5761284e615015565b602002602001015160000151600014612885578c868151811061287357612873615015565b60209081029190910101515160808501525b506128f7565b600082600381111561289f5761289f613f15565b146128f757825160600151604080516001600160401b03808f16825290921660208301527f3ef2a99c550a751d4b0b261268f05a803dfb049ab43616a1ffb388f61fe65120910160405180910390a150505050612ba8565b8251608001516001600160401b0316156129d057600082600381111561291f5761291f613f15565b036129d0577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e0e03cae8c85600001516080015186602001516040518463ffffffff1660e01b815260040161298093929190615825565b6020604051808303816000875af115801561299f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129c391906150fa565b6129d05750505050612ba8565b60008d6040015186815181106129e8576129e8615015565b6020026020010151905080518460a001515114612a3257835160600151604051631cfe6d8b60e01b81526001600160401b03808f166004830152909116602482015260440161078f565b612a468c8560000151606001516001613315565b600080612a548684866133ba565b91509150612a6b8e87600001516060015184613315565b8c15612ac2576003826003811115612a8557612a85613f15565b03612ac2576000856003811115612a9e57612a9e613f15565b14612ac257855151604051632b11b8d960e01b815261078f91908390600401615851565b6002826003811115612ad657612ad6613f15565b14612b1b576003826003811115612aef57612aef613f15565b14612b1b578d866000015160600151836040516349362d1f60e11b815260040161078f9392919061586a565b8560000151600001518660000151606001516001600160401b03168f6001600160401b03167f05665fe9ad095383d018353f4cbcba77e84db27dd215081bbf7cdf9ae6fbe48b8d8c81518110612b7357612b73615015565b602002602001015186865a612b88908f6152ff565b604051612b98949392919061588f565b60405180910390a4505050505050505b6001016126e0565b60408051808201909152600080825260208201526000612bd3876020015161346e565b60405163bbe4f6db60e01b81526001600160a01b0380831660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063bbe4f6db90602401602060405180830381865afa158015612c3f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c6391906158c6565b90506001600160a01b0381161580612c925750612c906001600160a01b03821663aff2afbf60e01b611d73565b155b15612cbb5760405163ae9b4ce960e01b81526001600160a01b038216600482015260240161078f565b600080612ce688858c60800151806020019051810190612cdb91906154ea565b63ffffffff166134e2565b915091506000806000612d996040518061010001604052808e81526020018c6001600160401b031681526020018d6001600160a01b031681526020018f606001518152602001896001600160a01b031681526020018f6000015181526020018f6040015181526020018b815250604051602401612d6391906158e3565b60408051601f198184030181529190526020810180516001600160e01b0316633907753760e01b179052878661138860846135c5565b92509250925082612dbf578160405163e1cd550960e01b815260040161078f9190613d2d565b8151602014612dee578151604051631e3be00960e21b815260206004820152602481019190915260440161078f565b600082806020019051810190612e0491906159af565b9050866001600160a01b03168c6001600160a01b031614612e80576000612e358d8a612e30868a6152ff565b6134e2565b50905086811080612e4f575081612e4c88836152ff565b14155b15612e7e5760405163a966e21f60e01b815260048101839052602481018890526044810182905260640161078f565b505b604080518082019091526001600160a01b039098168852602088015250949550505050505095945050505050565b6000612ec1826301ffc9a760e01b612ef9565b8015610aca5750612ef2827fffffffff00000000000000000000000000000000000000000000000000000000612ef9565b1592915050565b6040517fffffffff0000000000000000000000000000000000000000000000000000000082166024820152600090819060440160408051601f19818403018152919052602080820180516001600160e01b03166301ffc9a760e01b178152825192935060009283928392909183918a617530fa92503d91506000519050828015612f84575060208210155b8015612f905750600081115b979650505050505050565b60005b81518110156112725760ff831660009081526003602052604081208351909190849084908110612fd057612fd0615015565b6020908102919091018101516001600160a01b03168252810191909152604001600020805461ffff19169055600101612f9e565b60005b8251811015610a7557600083828151811061302457613024615015565b602002602001015190506000600281111561304157613041613f15565b60ff80871660009081526003602090815260408083206001600160a01b0387168452909152902054610100900416600281111561308057613080613f15565b146130a1576004604051631b3fab5160e11b815260040161078f919061573d565b6001600160a01b0381166130c85760405163d6c62c9b60e01b815260040160405180910390fd5b60405180604001604052808360ff1681526020018460028111156130ee576130ee613f15565b905260ff80871660009081526003602090815260408083206001600160a01b0387168452825290912083518154931660ff198416811782559184015190929091839161ffff19161761010083600281111561314b5761314b613f15565b021790555090505050806001019050613007565b60ff81166105135760ff808216600090815260026020526040902060010154620100009004166131a257604051631e8ed32560e21b815260040160405180910390fd5b6009805467ffffffffffffffff1916905550565b8151602080820151604092830151925160009384936131fc937f2425b0b9f9054c76ff151b0a175b18f37a4a4e82013a72e9f15c9caa095ed21f939092918891016159c8565b60408051601f1981840301815290829052805160209182012086518051888401516060808b0151908401516080808d0151950151959761324597949693959294919391016159fa565b604051602081830303815290604052805190602001208560400151805190602001208660a0015160405160200161327c9190615afe565b60408051601f198184030181528282528051602091820120908301969096528101939093526060830191909152608082015260a081019190915260c0015b60405160208183030381529060405280519060200120905092915050565b6000806132e685858561369f565b6001600160401b038716600090815260086020908152604080832093835292905220549150505b949350505050565b60006002613324608085615328565b6001600160401b0316613337919061534e565b905060006133458585611a8c565b905081613354600160046152ff565b901b19168183600381111561336b5761336b613f15565b6001600160401b03871660009081526007602052604081209190921b929092179182916133996080886156b4565b6001600160401b031681526020810191909152604001600020555050505050565b60405163d434969160e01b8152600090606090309063d4349691906133e790889088908890600401615b95565b600060405180830381600087803b15801561340157600080fd5b505af1925050508015613412575060015b613451573d808015613440576040519150601f19603f3d011682016040523d82523d6000602084013e613445565b606091505b50600392509050613466565b50506040805160208101909152600081526002905b935093915050565b60008151602014613494578160405163046b337b60e51b815260040161078f9190613d2d565b6000828060200190518101906134aa91906159af565b90506001600160a01b038111806134c2575061040081105b15610aca578260405163046b337b60e51b815260040161078f9190613d2d565b60008060008060006135438860405160240161350d91906001600160a01b0391909116815260200190565b60408051601f198184030181529190526020810180516001600160e01b03166370a0823160e01b179052888861138860846135c5565b92509250925082613569578160405163e1cd550960e01b815260040161078f9190613d2d565b6020825114613598578151604051631e3be00960e21b815260206004820152602481019190915260440161078f565b818060200190518101906135ac91906159af565b6135b682886152ff565b94509450505050935093915050565b6000606060008361ffff166001600160401b038111156135e7576135e76139df565b6040519080825280601f01601f191660200182016040528015613611576020820181803683370190505b509150863b61362b5763030ed58f60e21b60005260046000fd5b5a8581101561364557632be8ca8b60e21b60005260046000fd5b8590036040810481038710613665576337c3be2960e01b60005260046000fd5b505a6000808a5160208c0160008c8cf193505a900390503d848111156136885750835b808352806000602085013e50955095509592505050565b82518251600091908183036136c757604051630469ac9960e21b815260040160405180910390fd5b61010182118015906136db57506101018111155b6136f8576040516309bde33960e01b815260040160405180910390fd5b60001982820101610100811115613722576040516309bde33960e01b815260040160405180910390fd5b8060000361374f578660008151811061373d5761373d615015565b6020026020010151935050505061391d565b6000816001600160401b03811115613769576137696139df565b604051908082528060200260200182016040528015613792578160200160208202803683370190505b50905060008080805b858110156138bc5760006001821b8b8116036137f657888510156137df578c5160018601958e9181106137d0576137d0615015565b60200260200101519050613818565b85516001850194879181106137d0576137d0615015565b8b5160018401938d91811061380d5761380d615015565b602002602001015190505b600089861015613848578d5160018701968f91811061383957613839615015565b6020026020010151905061386a565b865160018601958891811061385f5761385f615015565b602002602001015190505b8285111561388b576040516309bde33960e01b815260040160405180910390fd5b6138958282613924565b8784815181106138a7576138a7615015565b6020908102919091010152505060010161379b565b5060018503821480156138ce57508683145b80156138d957508581145b6138f6576040516309bde33960e01b815260040160405180910390fd5b83600186038151811061390b5761390b615015565b60200260200101519750505050505050505b9392505050565b600081831061393c576139378284613942565b610ac7565b610ac783835b6040805160016020820152908101839052606081018290526000906080016132ba565b8280548282559060005260206000209081019282156139ba579160200282015b828111156139ba57825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190613985565b506139c69291506139ca565b5090565b5b808211156139c657600081556001016139cb565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b0381118282101715613a1757613a176139df565b60405290565b604051606081016001600160401b0381118282101715613a1757613a176139df565b60405160a081016001600160401b0381118282101715613a1757613a176139df565b60405160c081016001600160401b0381118282101715613a1757613a176139df565b604080519081016001600160401b0381118282101715613a1757613a176139df565b604051601f8201601f191681016001600160401b0381118282101715613acd57613acd6139df565b604052919050565b60006001600160401b03821115613aee57613aee6139df565b5060051b60200190565b6001600160a01b038116811461051357600080fd5b80356001600160401b0381168114613b2457600080fd5b919050565b801515811461051357600080fd5b8035613b2481613b29565b60006001600160401b03821115613b5b57613b5b6139df565b50601f01601f191660200190565b600082601f830112613b7a57600080fd5b8135613b8d613b8882613b42565b613aa5565b818152846020838601011115613ba257600080fd5b816020850160208301376000918101602001919091529392505050565b60006020808385031215613bd257600080fd5b82356001600160401b0380821115613be957600080fd5b818501915085601f830112613bfd57600080fd5b8135613c0b613b8882613ad5565b81815260059190911b83018401908481019088831115613c2a57600080fd5b8585015b83811015613cd057803585811115613c465760008081fd5b86016080818c03601f1901811315613c5e5760008081fd5b613c666139f5565b89830135613c7381613af8565b81526040613c82848201613b0d565b8b830152606080850135613c9581613b29565b83830152928401359289841115613cae57600091508182fd5b613cbc8f8d86880101613b69565b908301525085525050918601918601613c2e565b5098975050505050505050565b60005b83811015613cf8578181015183820152602001613ce0565b50506000910152565b60008151808452613d19816020860160208601613cdd565b601f01601f19169290920160200192915050565b602081526000610ac76020830184613d01565b8060608101831015610aca57600080fd5b60008083601f840112613d6357600080fd5b5081356001600160401b03811115613d7a57600080fd5b602083019150836020828501011115613d9257600080fd5b9250929050565b60008083601f840112613dab57600080fd5b5081356001600160401b03811115613dc257600080fd5b6020830191508360208260051b8501011115613d9257600080fd5b60008060008060008060008060e0898b031215613df957600080fd5b613e038a8a613d40565b975060608901356001600160401b0380821115613e1f57600080fd5b613e2b8c838d01613d51565b909950975060808b0135915080821115613e4457600080fd5b613e508c838d01613d99565b909750955060a08b0135915080821115613e6957600080fd5b50613e768b828c01613d99565b999c989b50969995989497949560c00135949350505050565b600080600060808486031215613ea457600080fd5b613eae8585613d40565b925060608401356001600160401b03811115613ec957600080fd5b613ed586828701613d51565b9497909650939450505050565b60008060408385031215613ef557600080fd5b613efe83613b0d565b9150613f0c60208401613b0d565b90509250929050565b634e487b7160e01b600052602160045260246000fd5b60048110613f3b57613f3b613f15565b9052565b60208101610aca8284613f2b565b8035613b2481613af8565b63ffffffff8116811461051357600080fd5b600060608284031215613f7c57600080fd5b613f84613a1d565b8235613f8f81613af8565b81526020830135613f9f81613f58565b60208201526040830135613fb281613af8565b60408201529392505050565b600060208284031215613fd057600080fd5b81356001600160401b03811115613fe657600080fd5b820160a0818503121561391d57600080fd5b803560ff81168114613b2457600080fd5b60006020828403121561401b57600080fd5b610ac782613ff8565b60008151808452602080850194506020840160005b8381101561405e5781516001600160a01b031687529582019590820190600101614039565b509495945050505050565b60208152600082518051602084015260ff602082015116604084015260ff604082015116606084015260608101511515608084015250602083015160c060a08401526140b860e0840182614024565b90506040840151601f198483030160c08501526140d58282614024565b95945050505050565b600080604083850312156140f157600080fd5b6140fa83613b0d565b946020939093013593505050565b600060a0828403121561411a57600080fd5b614122613a3f565b90508135815261413460208301613b0d565b602082015261414560408301613b0d565b604082015261415660608301613b0d565b606082015261416760808301613b0d565b608082015292915050565b600082601f83011261418357600080fd5b81356020614193613b8883613ad5565b82815260059290921b840181019181810190868411156141b257600080fd5b8286015b848110156142ac5780356001600160401b03808211156141d65760008081fd5b9088019060a0828b03601f19018113156141f05760008081fd5b6141f8613a3f565b878401358381111561420a5760008081fd5b6142188d8a83880101613b69565b8252506040808501358481111561422f5760008081fd5b61423d8e8b83890101613b69565b8a84015250606080860135858111156142565760008081fd5b6142648f8c838a0101613b69565b8385015250608091508186013581840152508285013592508383111561428a5760008081fd5b6142988d8a85880101613b69565b9082015286525050509183019183016141b6565b509695505050505050565b600061014082840312156142ca57600080fd5b6142d2613a61565b90506142de8383614108565b815260a08201356001600160401b03808211156142fa57600080fd5b61430685838601613b69565b602084015260c084013591508082111561431f57600080fd5b61432b85838601613b69565b604084015261433c60e08501613f4d565b6060840152610100840135608084015261012084013591508082111561436157600080fd5b5061436e84828501614172565b60a08301525092915050565b60008060008060006060868803121561439257600080fd5b85356001600160401b03808211156143a957600080fd5b6143b589838a016142b7565b965060208801359150808211156143cb57600080fd5b6143d789838a01613d99565b909650945060408801359150808211156143f057600080fd5b506143fd88828901613d99565b969995985093965092949392505050565b600082601f83011261441f57600080fd5b8135602061442f613b8883613ad5565b82815260059290921b8401810191818101908684111561444e57600080fd5b8286015b848110156142ac5780356001600160401b038111156144715760008081fd5b61447f8986838b01016142b7565b845250918301918301614452565b600082601f83011261449e57600080fd5b813560206144ae613b8883613ad5565b82815260059290921b840181019181810190868411156144cd57600080fd5b8286015b848110156142ac5780356001600160401b03808211156144f057600080fd5b818901915089603f83011261450457600080fd5b85820135614514613b8882613ad5565b81815260059190911b830160400190878101908c83111561453457600080fd5b604085015b8381101561456d5780358581111561455057600080fd5b61455f8f6040838a0101613b69565b845250918901918901614539565b508752505050928401925083016144d1565b600082601f83011261459057600080fd5b813560206145a0613b8883613ad5565b8083825260208201915060208460051b8701019350868411156145c257600080fd5b602086015b848110156142ac57803583529183019183016145c7565b600082601f8301126145ef57600080fd5b813560206145ff613b8883613ad5565b82815260059290921b8401810191818101908684111561461e57600080fd5b8286015b848110156142ac5780356001600160401b03808211156146425760008081fd5b9088019060a0828b03601f190181131561465c5760008081fd5b614664613a3f565b61466f888501613b0d565b8152604080850135848111156146855760008081fd5b6146938e8b8389010161440e565b8a84015250606080860135858111156146ac5760008081fd5b6146ba8f8c838a010161448d565b83850152506080915081860135858111156146d55760008081fd5b6146e38f8c838a010161457f565b9184019190915250919093013590830152508352918301918301614622565b6000806040838503121561471557600080fd5b6001600160401b038335111561472a57600080fd5b61473784843585016145de565b91506001600160401b036020840135111561475157600080fd5b6020830135830184601f82011261476757600080fd5b614774613b888235613ad5565b81358082526020808301929160051b84010187101561479257600080fd5b602083015b6020843560051b85010181101561493b576001600160401b03813511156147bd57600080fd5b87603f8235860101126147cf57600080fd5b6147e2613b886020833587010135613ad5565b81358501602081810135808452908301929160059190911b016040018a101561480a57600080fd5b604083358701015b83358701602081013560051b0160400181101561492b576001600160401b038135111561483e57600080fd5b833587018135016040818d03603f1901121561485957600080fd5b614861613a83565b604082013581526001600160401b036060830135111561488057600080fd5b8c605f60608401358401011261489557600080fd5b60406060830135830101356148ac613b8882613ad5565b808282526020820191508f60608460051b60608801358801010111156148d157600080fd5b6060808601358601015b60608460051b60608801358801010181101561490b576148fb8135613f58565b80358352602092830192016148db565b508060208501525050508085525050602083019250602081019050614812565b5084525060209283019201614797565b508093505050509250929050565b60006020828403121561495b57600080fd5b610ac782613b0d565b602081526001600160a01b0382511660208201526020820151151560408201526001600160401b0360408301511660608201526000606083015160808084015261330d60a0840182613d01565b6000602082840312156149c357600080fd5b813561391d81613af8565b600082601f8301126149df57600080fd5b813560206149ef613b8883613ad5565b8083825260208201915060208460051b870101935086841115614a1157600080fd5b602086015b848110156142ac578035614a2981613af8565b8352918301918301614a16565b60006020808385031215614a4957600080fd5b82356001600160401b0380821115614a6057600080fd5b818501915085601f830112614a7457600080fd5b8135614a82613b8882613ad5565b81815260059190911b83018401908481019088831115614aa157600080fd5b8585015b83811015613cd057803585811115614abc57600080fd5b860160c0818c03601f19011215614ad35760008081fd5b614adb613a61565b8882013581526040614aee818401613ff8565b8a8301526060614aff818501613ff8565b8284015260809150614b12828501613b37565b9083015260a08381013589811115614b2a5760008081fd5b614b388f8d838801016149ce565b838501525060c0840135915088821115614b525760008081fd5b614b608e8c848701016149ce565b9083015250845250918601918601614aa5565b80356001600160e01b0381168114613b2457600080fd5b600082601f830112614b9b57600080fd5b81356020614bab613b8883613ad5565b82815260069290921b84018101918181019086841115614bca57600080fd5b8286015b848110156142ac5760408189031215614be75760008081fd5b614bef613a83565b614bf882613b0d565b8152614c05858301614b73565b81860152835291830191604001614bce565b600082601f830112614c2857600080fd5b81356020614c38613b8883613ad5565b82815260059290921b84018101918181019086841115614c5757600080fd5b8286015b848110156142ac5780356001600160401b0380821115614c7b5760008081fd5b9088019060a0828b03601f1901811315614c955760008081fd5b614c9d613a3f565b614ca8888501613b0d565b815260408085013584811115614cbe5760008081fd5b614ccc8e8b83890101613b69565b8a8401525060609350614ce0848601613b0d565b908201526080614cf1858201613b0d565b93820193909352920135908201528352918301918301614c5b565b600082601f830112614d1d57600080fd5b81356020614d2d613b8883613ad5565b82815260069290921b84018101918181019086841115614d4c57600080fd5b8286015b848110156142ac5760408189031215614d695760008081fd5b614d71613a83565b813581528482013585820152835291830191604001614d50565b60006020808385031215614d9e57600080fd5b82356001600160401b0380821115614db557600080fd5b9084019060608287031215614dc957600080fd5b614dd1613a1d565b823582811115614de057600080fd5b83016040818903811315614df357600080fd5b614dfb613a83565b823585811115614e0a57600080fd5b8301601f81018b13614e1b57600080fd5b8035614e29613b8882613ad5565b81815260069190911b8201890190898101908d831115614e4857600080fd5b928a01925b82841015614e985785848f031215614e655760008081fd5b614e6d613a83565b8435614e7881613af8565b8152614e85858d01614b73565b818d0152825292850192908a0190614e4d565b845250505082870135915084821115614eb057600080fd5b614ebc8a838501614b8a565b81880152835250508284013582811115614ed557600080fd5b614ee188828601614c17565b85830152506040830135935081841115614efa57600080fd5b614f0687858501614d0c565b60408201529695505050505050565b600082825180855260208086019550808260051b84010181860160005b84811015614fa657601f19868403018952815160a06001600160401b03808351168652868301518288880152614f6a83880182613d01565b60408581015184169089015260608086015190931692880192909252506080928301519290950191909152509783019790830190600101614f32565b5090979650505050505050565b60006040808352614fc76040840186614f15565b83810360208581019190915285518083528682019282019060005b8181101561500757845180518452840151848401529383019391850191600101614fe2565b509098975050505050505050565b634e487b7160e01b600052603260045260246000fd5b805160408084528151848201819052600092602091908201906060870190855b8181101561508257835180516001600160a01b031684528501516001600160e01b031685840152928401929185019160010161504b565b50508583015187820388850152805180835290840192506000918401905b808310156150db57835180516001600160401b031683528501516001600160e01b0316858301529284019260019290920191908501906150a0565b50979650505050505050565b602081526000610ac7602083018461502b565b60006020828403121561510c57600080fd5b815161391d81613b29565b600181811c9082168061512b57607f821691505b60208210810361514b57634e487b7160e01b600052602260045260246000fd5b50919050565b600080835461515f81615117565b60018281168015615177576001811461518c576151bb565b60ff19841687528215158302870194506151bb565b8760005260208060002060005b858110156151b25781548a820152908401908201615199565b50505082870194505b50929695505050505050565b600081546151d481615117565b8085526020600183811680156151f1576001811461520b57615239565b60ff1985168884015283151560051b880183019550615239565b866000528260002060005b858110156152315781548a8201860152908301908401615216565b890184019650505b505050505092915050565b6040815260006152576040830185613d01565b82810360208401526140d581856151c7565b634e487b7160e01b600052601160045260246000fd5b6001600160401b0381811683821601908082111561529f5761529f615269565b5092915050565b6040815260006152b96040830185614f15565b82810360208401526140d5818561502b565b6000602082840312156152dd57600080fd5b81356001600160401b038111156152f357600080fd5b61330d848285016145de565b81810381811115610aca57610aca615269565b634e487b7160e01b600052601260045260246000fd5b60006001600160401b038084168061534257615342615312565b92169190910692915050565b8082028115828204841417610aca57610aca615269565b80518252600060206001600160401b0381840151168185015260408084015160a0604087015261539860a0870182613d01565b9050606085015186820360608801526153b18282613d01565b608087810151898303918a01919091528051808352908601935060009250908501905b808310156150db57835180516001600160a01b03168352860151868301529285019260019290920191908401906153d4565b602081526000610ac76020830184615365565b60808152600061542c6080830187615365565b61ffff9590951660208301525060408101929092526001600160a01b0316606090910152919050565b60008060006060848603121561546a57600080fd5b835161547581613b29565b60208501519093506001600160401b0381111561549157600080fd5b8401601f810186136154a257600080fd5b80516154b0613b8882613b42565b8181528760208385010111156154c557600080fd5b6154d6826020830160208601613cdd565b809450505050604084015190509250925092565b6000602082840312156154fc57600080fd5b815161391d81613f58565b601f821115611272576000816000526020600020601f850160051c810160208610156155305750805b601f850160051c820191505b8181101561554f5782815560010161553c565b505050505050565b81516001600160401b03811115615570576155706139df565b6155848161557e8454615117565b84615507565b602080601f8311600181146155b957600084156155a15750858301515b600019600386901b1c1916600185901b17855561554f565b600085815260208120601f198616915b828110156155e8578886015182559484019460019091019084016155c9565b50858210156156065787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60208152600082546001600160a01b038116602084015260ff8160a01c16151560408401526001600160401b038160a81c16606084015250608080830152610ac760a08301600185016151c7565b80820180821115610aca57610aca615269565b60ff8181168382160190811115610aca57610aca615269565b8183823760009101908152919050565b828152606082602083013760800192915050565b60006001600160401b03808416806156ce576156ce615312565b92169190910492915050565b6000602082840312156156ec57600080fd5b813561391d81613f58565b6000808335601e1984360301811261570e57600080fd5b8301803591506001600160401b0382111561572857600080fd5b602001915036819003821315613d9257600080fd5b602081016005831061575157615751613f15565b91905290565b60ff818116838216029081169081811461529f5761529f615269565b600060a0820160ff881683526020878185015260a0604085015281875480845260c0860191508860005282600020935060005b818110156157cb5784546001600160a01b0316835260019485019492840192016157a6565b50508481036060860152865180825290820192508187019060005b8181101561580b5782516001600160a01b0316855293830193918301916001016157e6565b50505060ff851660808501525090505b9695505050505050565b60006001600160401b038086168352808516602084015250606060408301526140d56060830184613d01565b82815260406020820152600061330d6040830184613d01565b6001600160401b038481168252831660208201526060810161330d6040830184613f2b565b84815261589f6020820185613f2b565b6080604082015260006158b56080830185613d01565b905082606083015295945050505050565b6000602082840312156158d857600080fd5b815161391d81613af8565b6020815260008251610100806020850152615902610120850183613d01565b9150602085015161591e60408601826001600160401b03169052565b5060408501516001600160a01b03811660608601525060608501516080850152608085015161595860a08601826001600160a01b03169052565b5060a0850151601f19808685030160c08701526159758483613d01565b935060c08701519150808685030160e08701526159928483613d01565b935060e087015191508086850301838701525061581b8382613d01565b6000602082840312156159c157600080fd5b5051919050565b84815260006001600160401b0380861660208401528085166040840152506080606083015261581b6080830184613d01565b86815260c060208201526000615a1360c0830188613d01565b6001600160a01b03969096166040830152506001600160401b039384166060820152608081019290925290911660a09091015292915050565b600082825180855260208086019550808260051b84010181860160005b84811015614fa657601f19868403018952815160a08151818652615a8f82870182613d01565b9150508582015185820387870152615aa78282613d01565b91505060408083015186830382880152615ac18382613d01565b92505050606080830151818701525060808083015192508582038187015250615aea8183613d01565b9a86019a9450505090830190600101615a69565b602081526000610ac76020830184615a4c565b60008282518085526020808601955060208260051b8401016020860160005b84811015614fa657601f19868403018952615b4c838351613d01565b98840198925090830190600101615b30565b60008151808452602080850194506020840160005b8381101561405e57815163ffffffff1687529582019590820190600101615b73565b60608152600084518051606084015260208101516001600160401b0380821660808601528060408401511660a08601528060608401511660c08601528060808401511660e0860152505050602085015161014080610100850152615bfd6101a0850183613d01565b91506040870151605f198086850301610120870152615c1c8483613d01565b935060608901519150615c39838701836001600160a01b03169052565b608089015161016087015260a0890151925080868503016101808701525050615c628282615a4c565b9150508281036020840152615c778186615b11565b9050828103604084015261581b8185615b5e56fea164736f6c6343000818000a", } diff --git a/core/gethwrappers/ccip/generated/onramp/onramp.go b/core/gethwrappers/ccip/generated/onramp/onramp.go index 16e352909e..f15bd4e3c9 100644 --- a/core/gethwrappers/ccip/generated/onramp/onramp.go +++ b/core/gethwrappers/ccip/generated/onramp/onramp.go @@ -83,10 +83,10 @@ type OnRampDestChainConfigArgs struct { } type OnRampDynamicConfig struct { - FeeQuoter common.Address - MessageValidator common.Address - FeeAggregator common.Address - AllowListAdmin common.Address + FeeQuoter common.Address + MessageInterceptor common.Address + FeeAggregator common.Address + AllowListAdmin common.Address } type OnRampStaticConfig struct { @@ -97,7 +97,7 @@ type OnRampStaticConfig struct { } var OnRampMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CannotSendZeroTokens\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GetSupportedTokensFunctionalityRemovedCheckAdminRegistry\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidAllowListRequest\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidDestChainConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeCalledByRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrAllowlistAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RouterMustSetOriginalSender\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"UnsupportedToken\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"name\":\"AllowListAdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"senders\",\"type\":\"address[]\"}],\"name\":\"AllowListSendersAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"senders\",\"type\":\"address[]\"}],\"name\":\"AllowListSendersRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"CCIPMessageSent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOnRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"allowListEnabled\",\"type\":\"bool\"}],\"name\":\"DestChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"feeValueJuels\",\"type\":\"uint256\"}],\"name\":\"FeePaid\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeeTokenWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"allowListEnabled\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"addedAllowlistedSenders\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"removedAllowlistedSenders\",\"type\":\"address[]\"}],\"internalType\":\"structOnRamp.AllowListConfigArgs[]\",\"name\":\"allowListConfigArgsItems\",\"type\":\"tuple[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyDestChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"}],\"name\":\"forwardFromRouter\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getAllowedSendersList\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getDestChainConfig\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"allowListEnabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getExpectedNextSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"getFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"},{\"internalType\":\"contractIERC20\",\"name\":\"sourceToken\",\"type\":\"address\"}],\"name\":\"getPoolBySourceToken\",\"outputs\":[{\"internalType\":\"contractIPoolV1\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"contractIRouter\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"name\":\"getSupportedTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageValidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"setDynamicConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"withdrawFeeTokens\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CannotSendZeroTokens\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GetSupportedTokensFunctionalityRemovedCheckAdminRegistry\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidAllowListRequest\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidDestChainConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeCalledByRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrAllowlistAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RouterMustSetOriginalSender\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"UnsupportedToken\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"name\":\"AllowListAdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"senders\",\"type\":\"address[]\"}],\"name\":\"AllowListSendersAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"senders\",\"type\":\"address[]\"}],\"name\":\"AllowListSendersRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"CCIPMessageSent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOnRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"allowListEnabled\",\"type\":\"bool\"}],\"name\":\"DestChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"feeValueJuels\",\"type\":\"uint256\"}],\"name\":\"FeePaid\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeeTokenWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"allowListEnabled\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"addedAllowlistedSenders\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"removedAllowlistedSenders\",\"type\":\"address[]\"}],\"internalType\":\"structOnRamp.AllowListConfigArgs[]\",\"name\":\"allowListConfigArgsItems\",\"type\":\"tuple[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyDestChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"}],\"name\":\"forwardFromRouter\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getAllowedSendersList\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getDestChainConfig\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"allowListEnabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getExpectedNextSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"getFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"},{\"internalType\":\"contractIERC20\",\"name\":\"sourceToken\",\"type\":\"address\"}],\"name\":\"getPoolBySourceToken\",\"outputs\":[{\"internalType\":\"contractIPoolV1\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"contractIRouter\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"name\":\"getSupportedTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"setDynamicConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"withdrawFeeTokens\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", Bin: "0x6101006040523480156200001257600080fd5b506040516200407238038062004072833981016040819052620000359162000665565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf8162000186565b505083516001600160401b031615905080620000e6575060208301516001600160a01b0316155b80620000fd575060408301516001600160a01b0316155b8062000114575060608301516001600160a01b0316155b1562000133576040516306b7c75960e31b815260040160405180910390fd5b82516001600160401b031660805260208301516001600160a01b0390811660a0526040840151811660c05260608401511660e052620001728262000231565b6200017d8162000390565b5050506200079f565b336001600160a01b03821603620001e05760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b0316158062000254575060408101516001600160a01b0316155b1562000273576040516306b7c75960e31b815260040160405180910390fd5b8051600280546001600160a01b03199081166001600160a01b0393841617909155602080840180516003805485169186169190911790556040808601805160048054871691881691909117905560608088018051600580549098169089161790965582516080808201855280516001600160401b031680835260a080518b16848a0190815260c080518d16868a0190815260e080518f169789019788528a5195865292518e169b85019b909b5299518c169783019790975292518a169381019390935289518916908301529351871693810193909352518516928201929092529151909216918101919091527f23a1adf8ad7fad6091a4803227af2cee848c01a7c812404cade7c25636925e32906101000160405180910390a150565b60005b8151811015620004cf576000828281518110620003b457620003b462000789565b602002602001015190506000838381518110620003d557620003d562000789565b6020026020010151600001519050806001600160401b03166000036200041a5760405163c35aa79d60e01b81526001600160401b038216600482015260240162000083565b6001600160401b03818116600081815260066020908152604091829020868201518154600160481b600160e81b0319811669010000000000000000006001600160a01b03909316928302908117808555865192891691909816178152928301526801000000000000000090940460ff161515918101919091527fd5ad72bc37dc7a80a8b9b9df20500046fd7341adb1be2258a540466fdd7dcef59060600160405180910390a250505080600101905062000393565b5050565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b03811182821017156200050e576200050e620004d3565b60405290565b604080519081016001600160401b03811182821017156200050e576200050e620004d3565b604051601f8201601f191681016001600160401b0381118282101715620005645762000564620004d3565b604052919050565b80516001600160401b03811681146200058457600080fd5b919050565b6001600160a01b03811681146200059f57600080fd5b50565b600082601f830112620005b457600080fd5b815160206001600160401b03821115620005d257620005d2620004d3565b620005e2818360051b0162000539565b82815260069290921b840181019181810190868411156200060257600080fd5b8286015b848110156200065a5760408189031215620006215760008081fd5b6200062b62000514565b62000636826200056c565b815284820151620006478162000589565b8186015283529183019160400162000606565b509695505050505050565b60008060008385036101208112156200067d57600080fd5b60808112156200068c57600080fd5b62000696620004e9565b620006a1866200056c565b81526020860151620006b38162000589565b60208201526040860151620006c88162000589565b60408201526060860151620006dd8162000589565b606082015293506080607f1982011215620006f757600080fd5b5062000702620004e9565b6080850151620007128162000589565b815260a0850151620007248162000589565b602082015260c0850151620007398162000589565b604082015260e08501516200074e8162000589565b60608201526101008501519092506001600160401b038111156200077157600080fd5b6200077f86828701620005a2565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b60805160a05160c05160e05161385a620008186000396000818161022c01528181610cc20152611bea0152600081816101f0015281816112910152611bc30152600081816101b4015281816105de0152611b99015260008181610184015281816111b7015281816116940152611b6c015261385a6000f3fe608060405234801561001057600080fd5b50600436106101365760003560e01c806379ba5097116100b2578063a6f3ab6c11610081578063df0aa9e911610066578063df0aa9e91461052d578063f2fde38b14610540578063fbca3b741461055357600080fd5b8063a6f3ab6c146104cd578063d77d5ed0146104e057600080fd5b806379ba50971461045b5780638da5cb5b146104635780639041be3d14610481578063972b4612146104ad57600080fd5b806334adf4941161010957806348a98aa4116100ee57806348a98aa4146103045780636def4ce71461033c5780637437ff9f146103db57600080fd5b806334adf494146102e95780633a019940146102fc57600080fd5b80630242cf601461013b57806306285c6914610150578063181f5a771461027f57806320487ded146102c8575b600080fd5b61014e6101493660046126df565b610566565b005b61026960408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16815250905090565b60405161027691906127a2565b60405180910390f35b6102bb6040518060400160405280601081526020017f4f6e52616d7020312e362e302d6465760000000000000000000000000000000081525081565b6040516102769190612867565b6102db6102d6366004612892565b61057a565b604051908152602001610276565b61014e6102f73660046128e2565b610733565b61014e610a4f565b610317610312366004612957565b610c7a565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610276565b61039f61034a366004612990565b67ffffffffffffffff9081166000908152600660205260409020549081169168010000000000000000820460ff16916901000000000000000000900473ffffffffffffffffffffffffffffffffffffffff1690565b6040805167ffffffffffffffff9094168452911515602084015273ffffffffffffffffffffffffffffffffffffffff1690820152606001610276565b61044e604080516080810182526000808252602082018190529181018290526060810191909152506040805160808101825260025473ffffffffffffffffffffffffffffffffffffffff908116825260035481166020830152600454811692820192909252600554909116606082015290565b60405161027691906129ad565b61014e610d2f565b60005473ffffffffffffffffffffffffffffffffffffffff16610317565b61049461048f366004612990565b610e2c565b60405167ffffffffffffffff9091168152602001610276565b6104c06104bb366004612990565b610e55565b60405161027691906129f6565b61014e6104db366004612a60565b610e7d565b6103176104ee366004612990565b67ffffffffffffffff166000908152600660205260409020546901000000000000000000900473ffffffffffffffffffffffffffffffffffffffff1690565b6102db61053b366004612ac7565b610e8e565b61014e61054e366004612b33565b611747565b6104c0610561366004612990565b611758565b61056e61178c565b6105778161180f565b50565b6040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815277ffffffffffffffff00000000000000000000000000000000608084901b16600482015260009073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690632cbc26bb90602401602060405180830381865afa158015610625573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106499190612b5e565b15610691576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024015b60405180910390fd5b6002546040517fd8694ccd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063d8694ccd906106e99086908690600401612c8f565b602060405180830381865afa158015610706573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061072a9190612dd8565b90505b92915050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146107a35760055473ffffffffffffffffffffffffffffffffffffffff1633146107a3576040517f905d7d9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015610a4a5760008383838181106107c2576107c2612df1565b90506020028101906107d49190612e20565b6107dd90612ed1565b805167ffffffffffffffff1660009081526006602090815260409182902090830151815490151568010000000000000000027fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff9091161781559082015151919250901561099d5781602001511561095c5760005b82604001515181101561090c5760008360400151828151811061087657610876612df1565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036108f55783516040517f463258ff00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610688565b6109026001840182611986565b5050600101610851565b50816000015167ffffffffffffffff167f330939f6eafe8bb516716892fe962ff19770570838686e6579dbc1cc51fc3281836040015160405161094f91906129f6565b60405180910390a261099d565b81516040517f463258ff00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610688565b60005b8260600151518110156109e9576109e0836060015182815181106109c6576109c6612df1565b6020026020010151836001016119a890919063ffffffff16565b506001016109a0565b5060608201515115610a4057816000015167ffffffffffffffff167fc237ec1921f855ccd5e9a5af9733f2d58943a5a8501ec5988e305d7a4d4215868360600151604051610a3791906129f6565b60405180910390a25b50506001016107a6565b505050565b600254604080517fcdc73d51000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163cdc73d5191600480830192869291908290030181865afa158015610abe573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610b049190810190612f64565b60045490915073ffffffffffffffffffffffffffffffffffffffff1660005b8251811015610a4a576000838281518110610b4057610b40612df1565b60209081029190910101516040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915060009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa158015610bbb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bdf9190612dd8565b90508015610c7057610c0873ffffffffffffffffffffffffffffffffffffffff831685836119ca565b8173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f508d7d183612c18fc339b42618912b9fa3239f631dd7ec0671f950200a0fa66e83604051610c6791815260200190565b60405180910390a35b5050600101610b23565b6040517fbbe4f6db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063bbe4f6db90602401602060405180830381865afa158015610d0b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061072a9190612ff3565b60015473ffffffffffffffffffffffffffffffffffffffff163314610db0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610688565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b67ffffffffffffffff808216600090815260066020526040812054909161072d9116600161303f565b67ffffffffffffffff8116600090815260066020526040902060609061072d90600101611a57565b610e8561178c565b61057781611a6b565b67ffffffffffffffff8416600090815260066020526040812073ffffffffffffffffffffffffffffffffffffffff8316610ef4576040517fa4ec747900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805468010000000000000000900460ff1615610f6557610f176001820184611c4d565b610f65576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152602401610688565b80546901000000000000000000900473ffffffffffffffffffffffffffffffffffffffff163314610fc2576040517f1c0a352900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60035473ffffffffffffffffffffffffffffffffffffffff168015611068576040517fe0a0e50600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82169063e0a0e50690611035908a908a90600401612c8f565b600060405180830381600087803b15801561104f57600080fd5b505af1158015611063573d6000803e3d6000fd5b505050505b506002546000908190819073ffffffffffffffffffffffffffffffffffffffff1663c4276bfc8a61109f60808c0160608d01612b33565b8a6110ad60808e018e613060565b6040518663ffffffff1660e01b81526004016110cd9594939291906130c5565b600060405180830381865afa1580156110ea573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611130919081019061318d565b919450925090506111476080890160608a01612b33565b73ffffffffffffffffffffffffffffffffffffffff167f075a2720282fdf622141dae0b048ef90a21a7e57c134c76912d19d006b3b3f6f8460405161118e91815260200190565b60405180910390a2604080516101a081019091526000610100820181815267ffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000081166101208501528c811661014085015287549293928392916101608401918a91879161120391166131e7565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905567ffffffffffffffff16815260200186611303576040517fea458c0c00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8f16600482015273ffffffffffffffffffffffffffffffffffffffff8c811660248301527f0000000000000000000000000000000000000000000000000000000000000000169063ea458c0c906044016020604051808303816000875af11580156112da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112fe919061320e565b611306565b60005b67ffffffffffffffff1681525081526020018873ffffffffffffffffffffffffffffffffffffffff1681526020018a80602001906113449190613060565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050908252506020016113888b80613060565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250505090825250602081018490526040016113d960808c0160608d01612b33565b73ffffffffffffffffffffffffffffffffffffffff1681526020018981526020018a806040019061140a919061322b565b905067ffffffffffffffff811115611424576114246125b9565b60405190808252806020026020018201604052801561148757816020015b6114746040518060a0016040528060608152602001606081526020016060815260200160008152602001606081525090565b8152602001906001900390816114425790505b509052905060005b61149c60408b018b61322b565b905081101561154b576115226114b560408c018c61322b565b838181106114c5576114c5612df1565b9050604002018036038101906114db9190613293565b8c6114e68d80613060565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508e9250611c7c915050565b8260e00151828151811061153857611538612df1565b602090810291909101015260010161148f565b5060025460e082015160009173ffffffffffffffffffffffffffffffffffffffff169063085318f8908d9061158360408f018f61322b565b6040518563ffffffff1660e01b81526004016115a294939291906133aa565b600060405180830381865afa1580156115bf573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261160591908101906133e0565b905060005b8260e001515181101561165e5781818151811061162957611629612df1565b60200260200101518360e00151828151811061164757611647612df1565b60209081029190910101516080015260010161160a565b50604080517f130ac867e79e2789f923760a88743d292acdf7002139a588206e2260f73f7321602082015267ffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811692820192909252908c1660608201523060808201526116ee90839060a00160405160208183030381529060405280519060200120611fa2565b82515260405167ffffffffffffffff8c16907ff6e86ef8896c7a0d629406168f396e883280680c99e649b9e2d36466fbc9f9e59061172d908590613491565b60405180910390a25051519450505050505b949350505050565b61174f61178c565b610577816120a2565b60606040517f9e7177c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005473ffffffffffffffffffffffffffffffffffffffff16331461180d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610688565b565b60005b815181101561198257600082828151811061182f5761182f612df1565b60200260200101519050600083838151811061184d5761184d612df1565b60200260200101516000015190508067ffffffffffffffff166000036118ab576040517fc35aa79d00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610688565b67ffffffffffffffff8181166000818152600660209081526040918290208682015181547fffffff0000000000000000000000000000000000000000ffffffffffffffffff8116690100000000000000000073ffffffffffffffffffffffffffffffffffffffff909316928302908117808555865192891691909816178152928301526801000000000000000090940460ff161515918101919091527fd5ad72bc37dc7a80a8b9b9df20500046fd7341adb1be2258a540466fdd7dcef59060600160405180910390a2505050806001019050611812565b5050565b600061072a8373ffffffffffffffffffffffffffffffffffffffff8416612197565b600061072a8373ffffffffffffffffffffffffffffffffffffffff84166121e6565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052610a4a9084906122e0565b60606000611a64836123ec565b9392505050565b805173ffffffffffffffffffffffffffffffffffffffff161580611aa75750604081015173ffffffffffffffffffffffffffffffffffffffff16155b15611ade576040517f35be3ac800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051600280547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff93841617909155602080840151600380548416918516919091179055604080850151600480548516918616919091179055606080860151600580549095169086161790935580516080810182527f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681527f00000000000000000000000000000000000000000000000000000000000000008516928101929092527f00000000000000000000000000000000000000000000000000000000000000008416828201527f00000000000000000000000000000000000000000000000000000000000000009093169181019190915290517f23a1adf8ad7fad6091a4803227af2cee848c01a7c812404cade7c25636925e3291611c429184906135df565b60405180910390a150565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600183016020526040812054151561072a565b611cae6040518060a0016040528060608152602001606081526020016060815260200160008152602001606081525090565b8460200151600003611cec576040517f5cf0444900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611cfc858760000151610c7a565b905073ffffffffffffffffffffffffffffffffffffffff81161580611dcc57506040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527faff2afbf00000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff8216906301ffc9a790602401602060405180830381865afa158015611da6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dca9190612b5e565b155b15611e1e5785516040517fbf16aab600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610688565b60008173ffffffffffffffffffffffffffffffffffffffff16639a4575b96040518060a001604052808881526020018967ffffffffffffffff1681526020018773ffffffffffffffffffffffffffffffffffffffff1681526020018a6020015181526020018a6000015173ffffffffffffffffffffffffffffffffffffffff168152506040518263ffffffff1660e01b8152600401611ebd919061367e565b6000604051808303816000875af1158015611edc573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611f2291908101906136f4565b6040805160a0810190915273ffffffffffffffffffffffffffffffffffffffff841660c08201529091508060e0810160405160208183030381529060405281526020018260000151815260200182602001518152602001886020015181526020016040518060200160405280600081525081525092505050949350505050565b60008060001b82846020015185606001518660000151606001518760000151608001518860a001518960c00151604051602001611fe496959493929190613785565b604051602081830303815290604052805190602001208560400151805190602001208660e0015160405160200161201b91906137e6565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201206080808c0151805190840120928501989098529183019590955260608201939093529384015260a083015260c082015260e00160405160208183030381529060405280519060200120905092915050565b3373ffffffffffffffffffffffffffffffffffffffff821603612121576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610688565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60008181526001830160205260408120546121de5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561072d565b50600061072d565b600081815260018301602052604081205480156122cf57600061220a6001836137f9565b855490915060009061221e906001906137f9565b905080821461228357600086600001828154811061223e5761223e612df1565b906000526020600020015490508087600001848154811061226157612261612df1565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806122945761229461380c565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061072d565b600091505061072d565b5092915050565b6000612342826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166124489092919063ffffffff16565b805190915015610a4a57808060200190518101906123609190612b5e565b610a4a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610688565b60608160000180548060200260200160405190810160405280929190818152602001828054801561243c57602002820191906000526020600020905b815481526020019060010190808311612428575b50505050509050919050565b606061173f8484600085856000808673ffffffffffffffffffffffffffffffffffffffff16858760405161247c919061383b565b60006040518083038185875af1925050503d80600081146124b9576040519150601f19603f3d011682016040523d82523d6000602084013e6124be565b606091505b50915091506124cf878383876124da565b979650505050505050565b606083156125705782516000036125695773ffffffffffffffffffffffffffffffffffffffff85163b612569576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610688565b508161173f565b61173f83838151156125855781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106889190612867565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561260b5761260b6125b9565b60405290565b6040516080810167ffffffffffffffff8111828210171561260b5761260b6125b9565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561267b5761267b6125b9565b604052919050565b600067ffffffffffffffff82111561269d5761269d6125b9565b5060051b60200190565b67ffffffffffffffff8116811461057757600080fd5b73ffffffffffffffffffffffffffffffffffffffff8116811461057757600080fd5b600060208083850312156126f257600080fd5b823567ffffffffffffffff81111561270957600080fd5b8301601f8101851361271a57600080fd5b803561272d61272882612683565b612634565b81815260069190911b8201830190838101908783111561274c57600080fd5b928401925b828410156124cf576040848903121561276a5760008081fd5b6127726125e8565b843561277d816126a7565b81528486013561278c816126bd565b8187015282526040939093019290840190612751565b6080810161072d828467ffffffffffffffff8151168252602081015173ffffffffffffffffffffffffffffffffffffffff808216602085015280604084015116604085015280606084015116606085015250505050565b60005b838110156128145781810151838201526020016127fc565b50506000910152565b600081518084526128358160208601602086016127f9565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061072a602083018461281d565b600060a0828403121561288c57600080fd5b50919050565b600080604083850312156128a557600080fd5b82356128b0816126a7565b9150602083013567ffffffffffffffff8111156128cc57600080fd5b6128d88582860161287a565b9150509250929050565b600080602083850312156128f557600080fd5b823567ffffffffffffffff8082111561290d57600080fd5b818501915085601f83011261292157600080fd5b81358181111561293057600080fd5b8660208260051b850101111561294557600080fd5b60209290920196919550909350505050565b6000806040838503121561296a57600080fd5b8235612975816126a7565b91506020830135612985816126bd565b809150509250929050565b6000602082840312156129a257600080fd5b8135611a64816126a7565b6080810161072d8284805173ffffffffffffffffffffffffffffffffffffffff908116835260208083015182169084015260408083015182169084015260609182015116910152565b6020808252825182820181905260009190848201906040850190845b81811015612a4457835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101612a12565b50909695505050505050565b8035612a5b816126bd565b919050565b600060808284031215612a7257600080fd5b612a7a612611565b8235612a85816126bd565b81526020830135612a95816126bd565b60208201526040830135612aa8816126bd565b60408201526060830135612abb816126bd565b60608201529392505050565b60008060008060808587031215612add57600080fd5b8435612ae8816126a7565b9350602085013567ffffffffffffffff811115612b0457600080fd5b612b108782880161287a565b935050604085013591506060850135612b28816126bd565b939692955090935050565b600060208284031215612b4557600080fd5b8135611a64816126bd565b801515811461057757600080fd5b600060208284031215612b7057600080fd5b8151611a6481612b50565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112612bb057600080fd5b830160208101925035905067ffffffffffffffff811115612bd057600080fd5b803603821315612bdf57600080fd5b9250929050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b8183526000602080850194508260005b85811015612c84578135612c52816126bd565b73ffffffffffffffffffffffffffffffffffffffff168752818301358388015260409687019690910190600101612c3f565b509495945050505050565b600067ffffffffffffffff808516835260406020840152612cb08485612b7b565b60a06040860152612cc560e086018284612be6565b915050612cd56020860186612b7b565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc080878503016060880152612d0b848385612be6565b9350604088013592507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1883603018312612d4457600080fd5b60209288019283019235915084821115612d5d57600080fd5b8160061b3603831315612d6f57600080fd5b80878503016080880152612d84848385612c2f565b9450612d9260608901612a50565b73ffffffffffffffffffffffffffffffffffffffff811660a08901529350612dbd6080890189612b7b565b94509250808786030160c088015250506124cf838383612be6565b600060208284031215612dea57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81833603018112612e5457600080fd5b9190910192915050565b600082601f830112612e6f57600080fd5b81356020612e7f61272883612683565b8083825260208201915060208460051b870101935086841115612ea157600080fd5b602086015b84811015612ec6578035612eb9816126bd565b8352918301918301612ea6565b509695505050505050565b600060808236031215612ee357600080fd5b612eeb612611565b8235612ef6816126a7565b81526020830135612f0681612b50565b6020820152604083013567ffffffffffffffff80821115612f2657600080fd5b612f3236838701612e5e565b60408401526060850135915080821115612f4b57600080fd5b50612f5836828601612e5e565b60608301525092915050565b60006020808385031215612f7757600080fd5b825167ffffffffffffffff811115612f8e57600080fd5b8301601f81018513612f9f57600080fd5b8051612fad61272882612683565b81815260059190911b82018301908381019087831115612fcc57600080fd5b928401925b828410156124cf578351612fe4816126bd565b82529284019290840190612fd1565b60006020828403121561300557600080fd5b8151611a64816126bd565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b67ffffffffffffffff8181168382160190808211156122d9576122d9613010565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261309557600080fd5b83018035915067ffffffffffffffff8211156130b057600080fd5b602001915036819003821315612bdf57600080fd5b67ffffffffffffffff8616815273ffffffffffffffffffffffffffffffffffffffff851660208201528360408201526080606082015260006124cf608083018486612be6565b600082601f83011261311c57600080fd5b815167ffffffffffffffff811115613136576131366125b9565b61316760207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601612634565b81815284602083860101111561317c57600080fd5b61173f8260208301602087016127f9565b6000806000606084860312156131a257600080fd5b8351925060208401516131b481612b50565b604085015190925067ffffffffffffffff8111156131d157600080fd5b6131dd8682870161310b565b9150509250925092565b600067ffffffffffffffff80831681810361320457613204613010565b6001019392505050565b60006020828403121561322057600080fd5b8151611a64816126a7565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261326057600080fd5b83018035915067ffffffffffffffff82111561327b57600080fd5b6020019150600681901b3603821315612bdf57600080fd5b6000604082840312156132a557600080fd5b6132ad6125e8565b82356132b8816126bd565b81526020928301359281019290925250919050565b600082825180855260208086019550808260051b84010181860160005b8481101561339d577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018952815160a0815181865261332e8287018261281d565b9150508582015185820387870152613346828261281d565b91505060408083015186830382880152613360838261281d565b92505050606080830151818701525060808083015192508582038187015250613389818361281d565b9a86019a94505050908301906001016132ea565b5090979650505050505050565b67ffffffffffffffff851681526060602082015260006133cd60608301866132cd565b82810360408401526124cf818587612c2f565b600060208083850312156133f357600080fd5b825167ffffffffffffffff8082111561340b57600080fd5b818501915085601f83011261341f57600080fd5b815161342d61272882612683565b81815260059190911b8301840190848101908883111561344c57600080fd5b8585015b83811015613484578051858111156134685760008081fd5b6134768b89838a010161310b565b845250918601918601613450565b5098975050505050505050565b602081526134e260208201835180518252602081015167ffffffffffffffff808216602085015280604084015116604085015280606084015116606085015280608084015116608085015250505050565b6000602083015161350b60c084018273ffffffffffffffffffffffffffffffffffffffff169052565b5060408301516101808060e08501526135286101a085018361281d565b915060608501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08086850301610100870152613565848361281d565b9350608087015191508086850301610120870152613583848361281d565b935060a087015191506135af61014087018373ffffffffffffffffffffffffffffffffffffffff169052565b60c087015161016087015260e08701519150808685030183870152506135d583826132cd565b9695505050505050565b6101008101613637828567ffffffffffffffff8151168252602081015173ffffffffffffffffffffffffffffffffffffffff808216602085015280604084015116604085015280606084015116606085015250505050565b825173ffffffffffffffffffffffffffffffffffffffff90811660808401526020840151811660a08401526040840151811660c084015260608401511660e0830152611a64565b602081526000825160a0602084015261369a60c084018261281d565b905067ffffffffffffffff6020850151166040840152604084015173ffffffffffffffffffffffffffffffffffffffff8082166060860152606086015160808601528060808701511660a086015250508091505092915050565b60006020828403121561370657600080fd5b815167ffffffffffffffff8082111561371e57600080fd5b908301906040828603121561373257600080fd5b61373a6125e8565b82518281111561374957600080fd5b6137558782860161310b565b82525060208301518281111561376a57600080fd5b6137768782860161310b565b60208301525095945050505050565b600073ffffffffffffffffffffffffffffffffffffffff808916835260c060208401526137b560c084018961281d565b67ffffffffffffffff97881660408501529590961660608301525091909316608082015260a0019190915292915050565b60208152600061072a60208301846132cd565b8181038181111561072d5761072d613010565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b60008251612e548184602087016127f956fea164736f6c6343000818000a", } diff --git a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt index bda0200e51..a869de6bcf 100644 --- a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -24,8 +24,8 @@ multi_aggregate_rate_limiter: ../../../contracts/solc/v0.8.24/MultiAggregateRate multi_ocr3_helper: ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Helper.abi ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Helper.bin 6b56e0114a4d50797d30a34aecc2641ef340451d0c3fcb9d729bba4df2435122 nonce_manager: ../../../contracts/solc/v0.8.24/NonceManager/NonceManager.abi ../../../contracts/solc/v0.8.24/NonceManager/NonceManager.bin 6f64e1083b356c06ee66b9138e398b9c97a4cd3e8c9ec38cf3010cebc79af536 ocr3_config_encoder: ../../../contracts/solc/v0.8.24/IOCR3ConfigEncoder/IOCR3ConfigEncoder.abi ../../../contracts/solc/v0.8.24/IOCR3ConfigEncoder/IOCR3ConfigEncoder.bin 9254b35a86f00fde7b7193a033ca58f6521a66e87b9cf9da6ce5660082e79f5d -offramp: ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.abi ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.bin 56945d1dff7a37553ad6db6b0701159af4ad2d85fb49acf368f66881c382f08a -onramp: ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.abi ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.bin 594439983f963f4158f9c5009dee7cba4ee56be61900bb1d5b9108eaeac3d6a6 +offramp: ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.abi ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.bin 948feede308d265d1cc2e020bb063229d90cd712bddb1fa9138cb0045c0de2c8 +onramp: ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.abi ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.bin 8e02667c4f38d55f0857ddb2c9d125b93c5c80d83c1fd6e8d7221035c6a50bd1 ping_pong_demo: ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.abi ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.bin c1c2f8a65c7ffd971899cae7fe62f2da57d09e936151e2b92163c4bebe699d6b price_registry: ../../../contracts/solc/v0.8.24/PriceRegistry/PriceRegistry.abi ../../../contracts/solc/v0.8.24/PriceRegistry/PriceRegistry.bin e7781d600c1bb7aa4620106af7f6e146a109b97f4cb6a7d06c9e15773340ecb2 registry_module_owner_custom: ../../../contracts/solc/v0.8.24/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.abi ../../../contracts/solc/v0.8.24/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.bin 75be86323c227917a9bbc3f799d7ed02f92db546653a36db30ed0ebe64461353 From 1cc98dba552a5aa0b3bf9d90ee1b79e1a5f19292 Mon Sep 17 00:00:00 2001 From: Rens Rooimans Date: Fri, 13 Sep 2024 16:30:35 +0200 Subject: [PATCH 093/115] update diagram (#1439) --- .../ccip/docs/multi-chain-overview-ocr3.png | Bin 818615 -> 862669 bytes .../ccip/docs/multi-chain-overview.drawio | 67 +++++++++--------- 2 files changed, 35 insertions(+), 32 deletions(-) diff --git a/contracts/src/v0.8/ccip/docs/multi-chain-overview-ocr3.png b/contracts/src/v0.8/ccip/docs/multi-chain-overview-ocr3.png index 39302619cb445c67ea075ded0124745a15fe7d03..c0d5e2faf7d892e1c89905e5efb6fd34df6c1bc8 100644 GIT binary patch literal 862669 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�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

CgV(yPfz{t*?cAJtNp0AYu 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 QNha8 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%0D>RFw)=RJFmi4>(V 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

=L0=0s4yR6pk#WUz>*rw?giFV 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%0APdUpJ$Ly*-<{t4EY<XP!gZjfu zM-z?KKI-J{ui;u;w{NmP5va&^679b;fP8cwR?8rs!{>}fk;&Tvvq9}yVJtFVfvd5B zlT(6AB)*;m9FwT|-uoj*TDLRscDvG)CECq))~1c1<CTEQy2YE|c<g9<<?3W>_)N#* z9>3m@I#N9ke)s24CR^I%<8v6kwVs~oy1f!BM+3BEO=}@6Q>1eR1B{)*?9l!2EqwgE z%n5|e+rUp~?594`KM~DE7mqSmyh&b2@B^vU<8vr@P^4O(zz67Ui%i!nq`3t;#;`1Q zp20RYRYzXsuw@t71&v5Lz@$fQFQM3gZQJq$6__n*aA9Kyh#tu1=KjWZFWk?mHtPb- zp^V|FBuc<)O2P`}6H!R7?ClYqw;r8e0uT0{l}0*bX@_(hrm71cq{dO1))8>T!EJqk zI|0oV>P{+RR^3dm{JW|VDzDM~TWXcxw&p1?%252$0uUlcn8oK=FaBjIQ%C7I7Cbr{ zC1{+6?)dBB)Z#`1udip8^I{|$Px-vH&F~i9S=-s?hUJHB4M8c<7ep=H+TAx!MOIsf zA~H7jT4U$c>X44EerQbyy>jA%u}_+t<p;48SgVt4>x!IK+Am|ws=9WX!{Wmd{jcbo z9@-JPB2L8W^Z5sRSS`_ltlJDj$0PTy=T`G+QEhlDjSew7kn4LKaT`utF42>V%kB6T zgCo-Y0AZhQlJExKB2)vz)K_&c{;Ep7FH`uWkY&8KX9H3}SM@SYvci7l4xX#a_IglN zTGHh4ff3PDGr%!MG;5lmTp{2SCp13~&BLx;g0ozT21>lTjthbD@2ME{gV>Fvi;XJ* zb7FT~(l5^2(ryR+%k~9Q=)SBvYvn>WS^ksE2uLJR!*JM|l5L6!?1R$%ASz(Bq{P<n zw(k~5y;ZdL(<||YrN&r*6B*B!(<U@E4tHApe*X@YmBs$?=+s@;`Mj|#1wA8E2a3X` zz)<glNjzBjnlz2jmww)F&l+UqVTAzF<$VE;T7&*IUbJ00XKlMg+MX8=1TMMxuAbZ4 z`>=39nr3PJOT%%SvG2D_StqH2_&t&^H%51h6n5Mh-2}+!!KR4{=ba$gUHsIJ6t%R+ zA(_63Z0!O1Q|Qt1$;kHE0n2P1ZmL7`^C^Vm_3c8GO5e-08g5G>s(=kfc%@Q$C5}=y z>gk!EU79EN6BV;wQ5e@eIV1TDoWPUR2Oxz2+i@z<&y0b7W}&-S>0vBXb(fDk1;DQf zvdXi4F@5`RFxY0pqH-pX)vkcTnbSbWJB#<aEGpfG^??)uA1*=_nOc{sLj@x|>lzB6 zo|FS>1p`^yJsEhLn{z$ivijpr5Z(aok&2=hFLE~C!3k1eugCf-I7(u9wO{;XpGq$A z`PK2=;wWTj3C7=&N=PY89bOXaI^Klk3}=kBT8}Z9Csd`f7<}@LRn0boPVmfA$h?rD zex1!vlgMyO0){2D4wg%q2QAhGJ%E)K6>#a-$shm=GF>s2RQq>$tJlIim?|Zup<`Bp zS|p4zsC?-gt@OaOX@_3agwG7C8SxD9AA?0*H}>NZy+jJuKq`sT2r<0CX@dI#+nT{Q zewLUQVTVP7+sTXCo0a7B%7*Ow7wpb!Be%w^^1Q`+OcuRT25ttGc1zNZP38NV#i;i@ zqb!)hvIsy1a1zH?NM0jYGSGCm<e$23$Xt;xtbas0)smS)tt~M|D<#W8NJ4>{)3{r1 zTdsHLx#$8YjAsB$GSyj_BV$gfF@k&iExag7RkGYgAPDFcBWniwIuKyy={(+LE^@GF zd$W9tz8i|0mq^&y*pMYM77_%lC?Ms9Lb~Kc)C4V<>)ya9s7+sGN(FjaC#Xox2z+2~ zae?Qg2Bj`*UDN6)rRp~;ljr%J3xMqYDQg<Zcwu(f(rCG|d$GHcPOr+<ve*w=HGMRq zSoR20vY4m!1mSZ;w*4G~N_~Fg<T{kXh2&3hmA7nRj76c(={v|UEv1xpif5JMrh>M6 zN6xS;<XmEvT>yNlO1-4?8nH!K?Ev3d7b5)|CcUbD`+27X;Txc4uw-_5W)LE~*+>R_ zTPKuJLm~Qx$~>D!G}C_F(AUUjunO6~ZYb1lqB`YR^8Rr#bm7?tjQ86ngZ4hgT~nN~ zR8L~O9$H<zfZi&602NR<VKjP6H_lYGl+|GKVxnf~O0wX@oR5yp)S-iXLsVhm7;*Gl zkK3j@BGXr2L&1o-wsMs#7&BX^n&ozr`WNTjqE@=L%)x84>$03U-AI$VvMam?`A`%g z@?d$tuHk`=>+1^D;ABlsNTUKFkkS;%bRidU2t<v{glMCqdF-WO<u5Dfe&G`mA>Cx> z&w$va9zy*>Gjntu;t)=~&J>J{&@fmdDGgNIFK!$F&CBcvA)zZASODk|+#+?Jq97<( z&>@C)G6Q-1>B9VGz~BmW%-T=im_e3o5UnAbnvnS*MwxmtaI!hgF}&(0%u+YKac#sz zMJ2PfOR1sNl7PWu${7NsI9;O4Jn8zbG9me^YsUTvo!y@cMPKH)oB(4KVm9BK=>gSk zAM}Q~w~{1YADHZw1O4ipeF3F?d8N;rfZ1q1WQG-Nn)Qi7o*2DmKp<cuc|n(qK1~IZ zAB>A1=ZW)g%lksm%3AYMwOMErKdum}_B_Pxqi9;Wj^D-AjEb+z%2~rHaqdA-zYS)M zp9IUesyJLW_TkHnRzo}MA_Kp!W>_<c!QDlNa-Ij)S(kZpHBY=stvQa3Vc%B}Ix*WR zlayy<*tt1$<k3TBtaeVddknU8wVQG|0ZAY8PnmNo(0V=WfxF*Klq85)oo6CqaGAbn z1R{ds%lk7|HGq#+3NO+KSW>;-W1pwg4?V5Q;eWA?$D751l1@VqBi1?xYYlN?{j(jz z+i1w)#~=MLt4sK4<6rHUMZ1TEu9f-gljmxV1Ir`R)&zwMDAnw?7kLj>PtQmB!lwC@ z{h%pJW@GrEhuj!5eWyEEE!x>^XRfBHzDeLFaal`1aVnNaC*ro!a$n<INu6Ln2NwKf zG~F8rnu6NmQCool&h?CbnLQ+|*Nq|zW8h!Ao$Mo##i;svXrKj6fx(HO$Tk0Z_kLGJ zX{Rb6zhd*I=AYsZYdAd#u8B^6fS;s0knSmtK_BRD_O)xj^Ve9A&k_FDua~VWNGTz& z@a+k1m^tOk`}t9+_Qe@qG6zAg))&lO4iQQTT>fCYsF`xA5jfU4hO0k|xf_+Jtf>0j z9A}Li9Uh!=AsONFk}BhmgJ|41nqo!j-T`_;?b!MJC9S;BJfO5Z7uqYM3hwt(KZtq2 zi9vx30*Dg9E_%44HxQan#cTA#J-q!ViEB37<M03+dAO)U7V<5FMQz(|@*zqHN1Kx6 z(4nZ??qwwCng5ARyCVpQ_&+)=y)f85yJ6qsG3O$8#rR!%5WUL-g2Mjti(3<TEAQ$= z3f=>Kpb;caX+U{@!LI~?4bPH)K}4#)j>*>~zJHT6-nuO)t)ZcT;rx6z476?=ib6k- zoU)QhE+C|Fd!_VXNc2P>G%4TipS||(khos6>XCN2yUsDYd8T<?*CWIrP%8p1iA?f3 zviSuchYL9jnIFxz2>Ktyrfv=$66gSj0?0*|?gHf?EM|Ki6g5T<FDh35hIuwRt9^Q+ zIpmkmg-=>iM%v2f{>o$#R$`Z>CxIA&n@xgtwUZ|MJvT`k!gR|7wYlsv_pPLp7gvJS zUIM4}0=wa}cKD7c^op}1f|!6~(E<Wn<x3{0Yo?Pqb(Gz<ku!*{n4_E{&0AZ*Lv+J( zTh&F^U$#|Rv@yDu+v5o`MEyng@YX9ge_X<emC%f~oNq2|BT3)muiJlrF7ya16GW;9 zD{f1N=F$EEak!k>*^jA*O*P5`s6c1uYW&a#_qU4u8kRo^H>E`sN4N)Sp}ouky2yyQ zV4kr;clF`4;1cZ9ZVpYz0jNB>md5bVdB2qmgKk65>K?L$>!%q!L{{Qd87_qUsHFbH zVCK(raXVT1XqV*aD2d$*6i(8LNS&z6P}udLs}xWzKibcIk<*e1>8B&Y#kXq_Ate1P zuOHC@a2SHjnXzb>ye`aI5xu?bv}PQ1O@ioy3xSpsyYu7A1I5C#w0cEdB)n<VGUnm^ zR!8A7-p~+D9u5~;kPe-A|52uGa=?FOqltOH%v&7iNg2GlTOQa~J;0Zdb0PIe&L#9I z>KE1cjMXKrUYa-h+!(6ab-yj~C1~49!hIhj;rr?_47q;~qnL*{_(ESh;WzS!tKKzI zCYjv%zbTv6L_tbs#o*AiRBHAPcDj=Xw!@Fho+~yO9v=<Wu^H_bmP@ma3=3kXtn|4% zSiWQN{jO7WA90?QM?uC-ATEukrNlz|-}tO|pPGT8QMC>lKu?NlpvW7CmQ^0)Ik$_< zBN4*rsl;!*IrWongAW+<XYL+u3{AX`-0y9nHT5PqjTr*i*C2L0WnhktD!1)H#hUXj zv(sjWy0B4iGl8clGMRCXj1xVT-A{$wiKQPtKovu8ZCmBj$?9DrwHa=pQ?^$%OYgf= zKsW^G&T?xDIu25hGZ)?foIfq~I;;uyflfm=iDxjm_VuU8mY-j?fQ2M{ivMU<p-x8k z`<7n8R`Bfzu_4N2h|DAARBU!o=d|n(Ie1)G|7C<=ynQ;q>XH&NWV(fKvSxm2dab2N zDO<K}ufNQVSG*|aA_c$)LB5I;G$Jau$*A6NwS!GQ>3#0K;CezW3qnTpOFZ6!@Rppy z(>jO*><`EFA{qT;N2m~#iv9;m#fVj8-b-!p^i+81HDlTxHV|i)lf+&I9nZ6POi?#z ztnYsFGSd9@jo^W5(YOBmKW@FhC&5SCt@a$7`A-j|qUfu~-KH)Od>mbv>CEb5zu$N{ zlEXNXNw4(gX;Pkxn{ovZLIck|^Ysl}F?u26XG%C;daNVKI=(_`#`>V0lsnh9Xrnng z@{&~glDX85D=AS4SP+JT#reom46lr?5Cb}eM(mv8V9T6hj$&J9k(y-qck{AbS!Abq zE+Wc5hV=<u5(EkB9}ZUfe`#R4U22z>ir*O86h5}EfkC%SJN8r*M;lck0XrfYiY*6h z)>ry%TOlD8)9#A?TN3y4%MT;`DFgby1Kim<N9l}NvxBb@cbO>R@%O3)rAQhjXzrEq z*ltu@=5_|1uF{Lum+nIow}=p#$un$>&|MjCaaWjhoQm7F+1QeoddU|v-mucfPjUhe zj|r}>XCbNYCmzoPj#<gIw+3w!g*V#Xe7Mxf|19=QE_Cw=E-}+8Bd%On5&?Vf{%|y# z!f1L!=Ub{tXs(?itJdEjW4Ect&pPEvAi}@^eP=`XXxhhZB!8Oc9~d_gxh=<$f8dp< zQ_+a?PEe3<PyEwB{j!m~XPCGI><^WB(6W5WjuWDfH;r;{-D3}>=9=s9@yUv9iVshO zq$(?%zAV7BSZGPZKjeI^Mxtp6ALrzejH7fiBtuh~{zz#gaA$pU$l|M+VS|5~<`5uJ z*Py^c`%!$*D+WR@7P?HrG4yO0`y|!cqEkQtdN<>tcg=CS72wA0cZOW}ZDC*_K5~Oi z|CwSOlRx)$L|J*F*Y8abts6^&-X1qW#}qCS2Hicc)fLICRi7yI8E@{FRPr)DaUjKZ z^c!5H2yrQiBP>hSmB&_w-ifp=hlaK7#`qr*(0uAGqz`gC$9?Vf&!Mei8A%@IywG_d zCaB*B3+a-4dit;uNupfbB7c9^2MAUY_Rs8q+uG(}g^1hUJu+D}w|({Oh0qRB?lL3^ zc%(I4&8$4pwrwKug*pQsk*kF6!;~CCW#*wLIhHB}qHw_;8}s3(nP16NZw{UKqR7sK zi6H}1?D|>QZ_u%R30cALmH>TM@#~R0gkE{S0X*oti|a<H->&r*Bbb5)?%!F|W|K7y zS$&-2HOp)^yC`47MqO<%2-AeiI>@Vk$7sF1cc!O&Lfrx*@|$XyUD^xmMZ@!@H1La< z?j(Kt<D6rGB0&!{i7N)@#HNRml>hJ#q@cieL>|OS?mT*T05Xxl;OmDrK~Et>v7tWW zLpOeIF&Mf_4r~5zX=DvL9aZ|r8S`Sxp9}6C5rw$|f9$48270CBuPxiKp$8ww$Wx?z zvZ05docea2ij7B@+F7D7rV#Fka?swU)4g>iFG&b!0rfx+s5fin3}qFVGHv2!r^jqY z-cQk$eYAa1Bg+&FjDBETfk^eYGIR9?<{UC;F^E>$L9!}zCAy@JyzYM{L<^q5mpEJN z<AbYB?ru&nF!!vgURMnGah(WCoTn4_%BNdeKb}-HqBdxM^N#blxH)(*f+im)p@%ps z?(wDOgQd!v9G292Zr%Js;vcW#;~=Ueo|OW=$cA*G8dy7kyU5a_<Qjdpf)f81vd4yj zg4GFk!$S>8e>-MsdE^nv{^7kBAZN25?WZhtG)m#Bdaw69#DZpI&gSkY?=yH#@@~x2 z^RbKF1BNM2q}UsR*NvoNnb^CNYaD}xz}n7|uReQ-pW0iIWZqpQr+LFw?dite74lED z<oGyt$fZXn-atk7_WRd=Wnr_`mZg?qd_Px(U?6t74D<a6`0NS0*r)^5z28#kBNUm9 zA3{05zQe<6#9osA;j-fKxk}wv3q<3hQ`3wZ6@_hx9NR>1{<udH!z<fVc@9lEy$`P? z(lcN9CP2jZ*f>#&0e+2CsZ%%qxzw+Dp_$veR`+$QV^1y)%#!*)k)Xoo12cVOoOK>i zIDc591OCN<xgus{OwNlP^ATj!Qr4LSZ$xYS;m77+>h<_9D*!jS1w+MGZ~Vrz)xwr% z0raGgzzW7VluE4cwBG%ejki~-QMAV=KD#*GG9Wk08OXz9f1tqa;goSB@lnz%X+xDF zp^Kyj=zWc%`a?z2Hp_E2rNWp(Vdt%IkXMpy(Bw)WtPQh1>uUDt83FCB3{|t+g%5)H z^ospmyNVUw^Nb*fln@zL8t;tpH)E@H^v;R3pF1b6pc_MfI)`s`azP6uLtme!R_QZQ zQc?zbH+6$?iDSSvutJ2Orj#s8AGNWV|Ft;+J*oFA&#9F_OzOAcBmlHY(mgCE-UL-F zUd5p6jHv4`V}f)i7-|=3m8ZKjdT)<)@;%c92B7C3gj}}f<)Vk>w=U^?F9@a9c@=bo zN9idcG7^Y!hw!|J5)RkUte;s&$k(_{ndcHKCov!C!n^;%N<o0!IbkKla`Jw}Ku@M$ zCF+e@*k~dF+J>G&q$~#DLoOW$>`4{mEXlcTCW5?XJ9|y;$^On=#~eknB8?M&IY4s~ zuF`ofzGb9050gzROgAPp-Nsa}%vmSow&?USrLbmx>9;wTN*QUpbjM72P}B|<SRG-t zUj0P4Z9K;1Q~E#^f=V!?F<5&M7ltbdt=(~|m3r9OXLlDD=Jg$UVBF-o$>vk0Z8N{? znTk5@m%E4F(|zT@*f;~-nu`Iu9cw<fVRQh+#pc#9g=`wc!9{``EQWxQ6dcUFn)v<Q ziRn596Om{>r#xV5a{YN`z!VIF#)srbx{Uf%J@>c&&6&l_oPurvgGanSP~Vhy?NLPP zhj%dLqg6U9NV)lSpjKzP(-72j6pu4l<>iG;C;UpJd_F>LZL-P7?Q%E#M#AODi;|*^ z+DESQJU#miIlu?1=Yt6`S_?gtiL$k6)??FY$BvyU7(KJ*^Kc&GY`3LUBtG0O{IkfN z4!`gt;@f$qCpFc-rIJX5iWGEca)roP#*ib#L3kG`Dk0jH&Z@oDo3Rx=rNO7}eLVMD zNh(B6fqYcQKixyY2cNs;sIijE0``+yj&IoeS+}2aTvZH4d*K=aE;qZ3%Y*qEmo#>+ z2S_FtI8-fPT@r76h9L!}MxJ%d;H}c@1}ze!!Mq8jx@9@vYFCc#Mv1SS7)57tdC(m1 z&*^~BB}b)IALf1Vna)IKGMGr@7&H12@-cK?8&9^dJM}w);%Wx0G+_GT-LwT4>=*{Z zTm)W#*|o^4V-8Lw=C?03Kd1i_RRHHBB#d0u3}jyAx30bjvvtB07~&N$#I|$!<1CCl zD=Q;r1Vc)8Ug&d~7=6%_zwOcc49qYT%n<v_)Ol%gKnjkJcib_*hg-4L;==CIpyagU zBhBuVTB=3&id%k1m^=`U2D8odDiJ!Yc_8(n%#Yvg$+Fb7GSP+%%trh~FtK(5FOb1D zmQtag1R$kE4aLYJ{hNWUPe*=}yn2YR>Qv6p{_{()Sto1(N=p@<z0g5zOYE-6Zb*MO zfdQRhZ0ZiHHJ|F)-83w9-VV7D5gi#NnZCrd>8|ff4&Eyo^CLT(BmwC8ROdHqlt{)p zS3Hs>Iq*Bq--d;;fh0<Y9QU5W`+G=&u5lTD<UuDfm@nQ4S<g5O0=|GA0>Yj-bLQPu z^G}d{-n?=Zka#DUG%S3%dGU+ht0I##PxAHae?=d}=jn$b34zq#>j2BtWAf0sVDMIu zdwGd%QuO`%L?IvXARdd;1V+<HzFAU?fsJYjT1{ENoL%_Q&9}3{uKo5{8cggKGx1}& zCpC;ZWeo*Rs}l_pO-)u*)pDW={m+G_kc2a)@E%gTJ&Zx#VGixDFVaNB9EJkR5rJW# zEZ@uA?B}0;J`X#+>oJifPC!<9i8Q#s2GNXnmD)ZwKX#J%uOJ0uaY&Dd={ee)z-Rv$ z=RMU?<3m~Dyq|iRn_u<YNd-ch?H7V{^i*w8sWR&D2sM>wxGIc&q6NytTpWMg7Q%(k zLXM_ikp5I}lELuuIg^2`@;x5oY!wDA@q2EEI(&=C+!*l)mUO)<<~Cv!?-0c#M=W$@ z?5TfdE76Q|JI-M8h&_;t^ngxsmPy1o8XN;A2EeHZ3$Pv<7zJPbBSEm%B|!<_H<|)* zKEI9yd3FY0`+pSL@t3(2eTj1psOVZ+x<skk48vT-E=fKQxi5Pz8NEUJK9>Ky9zEUZ ztS-`vgo=`RhN&+Ljt<{1g5vk?3nRm`?l=YW%P;q=I?dCT>OZhgdVh8AzX=QC$*teJ zpp!oG^Jv5R(agn{#rQni5$-qJd0zyWR!FmqKjLYt2Aqcw086~I$P5v*i$yPuxbQnm zMsf0DPMKWz9YDmP2EGoifyF;f3o_h^?Iw?=wACh#j{4Nhpkfn#sWY*?qDJTpCrEs_ z+q1)FbXar#&danF$qnE2pzrVaKBB+{n-?d_)_V)>2DmhA4H-+82GJP3>n3w8NH~84 za}7fcTmENsYZGiMu>G?l<K@-qWbXQ0P&JK%7z}wX`fK9-Fgsa{I{(Wri$1?<66AF- z{b2bgO4dp$`%OO+PE81-dVeFTVt=C#Sy*JDl2ha%!sE84_=jI${O^9Prt%yDqX+!m z0%@#muvh1jPT72aZ#qv&`Pt3p@UcCOkth#A68a|P!Un-ALK{H7HUgi8a9_R?Y)s9> z)ZgpfR&IgRU8wt!5#BXgaceK%eoK~_zWdQ|dFw4{p*C=zI3b@LRJnq#DIhn6V9NM2 zm;$i%7x2~l<y)c@6$rz=gi+|Te8-DE8dl)+i+BPW+z7HzaIfgI6)QTD@++1X%CpVn ze-A)^AfLK;<nKqw;u%~XVa%H4@I?Ng4OgX`TH&Q8lzQ`)M_Z7p`VYcq2M#Zzxr^j3 z=>WPJ#B4w!MHI#^B+-=n=q9*_tC?pFu8R!EDC{=iRm;Cr!V|dSA%EFQJbcab;XLw{ z-F+g-5zi!p&JTXvXv~ZnVmE<Mwh!Lrr>bF&8d370|GqWq1yo@vM=m{$v17GZ7!*v_ z%cEjF)gINEdeyo_APopfn#29^mMHbIjTw4{j`RtJf36!v?%ELcKguv5_D4*zScH8e zRx|Nx2ucd<_cD_#YsM?#97UJg_?{6_>JwiUwrxh51uR5grY(e<UohoH-H<v%PGxxh z9g>Y}sQW*tQ-A%<c;Be~kXGugu$SS)xX*HB%m&VrL@2HUwNbPP8y>R~39K|fn!b;2 z>jNOqey`g)lGpa$RfWfIsUFtwpRJGJ4z6e~D=cu?wU7$q+vdNB74RG1`46Pl1l*tJ zU%tj$Hdfsp8oCx{JJnx|i`iFj>4m@>vBU^6eLZ9enN@Ew{Q%?}%G+&%gg7DwCvPAw z<FS|_uKRI2k|i(Sh@}^N8o3YmIE?c2HoxF_-hya!c4qO9?*Yi;!v<R1G5a6o!5n$6 z$D*#plwnw=cA1I_4hR%9p(2QEuihkA&(=OmLSiATV0VYuGrH7PW_o2JNqRjc(elGn zR3y<Vy5{`##|tDfeE1jQpJQEx4Zo&5k1!pl0gLIWHX{~t?h}0UP$VzAA58-PDRdU5 ziU+SqY%)9WvjLdca9(xL{_}AR9}xBl(zv;RN90NRxGKcTos`aNWg^u6TgtJf+zWIV zn;@6hz&|lLg7(43k&ArN8-0<x6@MSJAxWu=9;H~i>CH(~Z7|tYv}osBrxX9xE@*7X zmp0&1iX3XCpSvi|&d@N?upvyYEm_8Rx0L-RI`#PZ$5k|nLG$;T71R%`nxojl$H%un z+D!Bw$x>Wdl5BWc9b{O)@_I2U6{(t-&Xu^YXI|d6D%IxNkJ|{z%{^zMx08OBP_h1f zN}K%^Bw~G3#rw?dvDblrVP#CCA&#!t{ME9S3FTEY%u#xM`(eYhu}k3{ije<1`ZFzj zpINN#OX#W(B5}aD2bk51U0O}FL+chs$`JNHU%$HNf>kB6776cQ>e!}{N3Z>><FQ@2 ztj8L1Z$2*AEhgiR9(FG|^LsGH&&@}yqT>hq81lkj8U;R=R+~R^*ldjQsDD`7Bn&cl zA`1>Vb3xlE8u`s?C*btR>o#(N;NIR3crF_$!=94CG(yj=xo@(AcM}{QMadKe&xFEL zcdEw{hvb`+%@jZxI;n`2>?gDbNmOm?i%#?zdQu=UndHyZIYVflj-fnRZEwUoY3NIi zPFM6Ze6A6l-@-1~axJovu^Z>Fs_EzOy<jtA7hc2kD&zRhXXWfmdEe<-Z?A*|=jIw_ zv!nfGK2}TIAS2!BY!Gn{C@*U{zn*INjA5+oJLZvmaA^_D(jJ}+UmUiI*@w#)Y1E6% z^V}BZgh*(|gvnncsb9Oz)$?fk5JX~=$e(GY#F704+LrCNO+Lz_EsUN74tPk8|J$3k z0{2ys*3bN5G8+r&nhGf)gMNxIjk$M~-+@=^C3|6icz!{D`0O1Ci95@)zR25o=vnhI z9~*j}P=X&(&!|_~lu5o)cUop-v$T=xW)0M3bZV(>#^kuJ0;9a!=CzUys3EsJmv{X_ zmnjW|$%m0A?hm?3{^N;}t4j6%<%!v>`uUiRS+av=)DP_kqAB?b4FUaNH)3U(iAEqW z$<&(C;KRo0H(KLur6SoZ?}Jku=1i2-5-4AkAP<fhnc7U71NrfjmpL>ANN#8^G({+G zFzMn;iWo5AU?MwxAL?8@hMw2gCx^5CqfYS$+zBsb0JCD=ax|K%JerF}6uR1l!$|A> zueZH~&|$-yV{HB<8a^@5tt4eOX0-@m>{?h5c<tO2nDlHzPvuj^@x^Ff$e0o_v-S8H zjTPp?^6MNL*E1%yZ53kq{1O%Ra}yPm8&yGRSBe5c27QQ=I600h_jifu_4Qi~5iBut zyS5L=Px`Qt<1Zm4sJqX3Bs9W4Wr&Tsx9r5Wrmk`!fk0TOrVlLTem+>rqnZYt<47p} z?eT#h&EVRX`h(mC|L{wfAh^~beYjz}2`+c++=E#rKGl%KCY4)l_ZsOGFDy7@jA6is zl%OVjwYe%=mxpvq?GAD;Njg6F4Pvo>Q0GC@-&l%XP!UZXdcC!@3q$X4E#Gx*LOtk) z+(qt!(N-7!%dr7Mw{U<0-&5g~AHrZH*RA%KlEFQlV(sGBSB(SFch(2dPBVY@D}jo^ z^hI$#XbIMlUy#iG;Im5d4!utW?&*)TYZzIYV0B6LU*=x#l79D#GM;!J8e_9O!{Xyp zI^Ovp&u|36%%x&jQWE8(<S5_dN#~8z5A<3CTX}=11S&G^Qb$>qIKdg52+^i>Mq>jx zE;-R7NLU2b?EqDYBN$Rh&QD+H)LD7%yntne>(WPkDUvf35^6am;UXhFIGDiR3VwZ? z;TU>B#A^W4<3B9fJP#l~_Z&HlDBSaieX*BE_rHX(SyzcA^w0h2fwmxokMxOm{J;&7 zR_nv8qjce{dR6m2#Xt8w8Na>Xg?*sSq~%WfW_{Ccav^#BQX`2@RgoTx-T-5G&ORMm zakg`k<b{{INMF{vE~EDp4If`2wZa*S2BpLh!#ng)%vB6Zz-CU&<eGUcHk;YbQ$D3m za+ZT7l$<$wkPNi)9`Mqsv&KPl-qM-G(NJ3A{O2>*r3e&n1<}dO7oPIMp)Q0knn*P1 zv?;AW&PtFZbLa^j&XQ=2{2kp>k0&YdRWNpHqy`iPqXbYHhsZ9_WY!BLNQrY3?Uf_{ z^vW+D3YJH4O*XR7Q35uzcnm?&{-f0bmc*lS*#CoG3c7Xu{VUkImF^nZ+Je+G>%Hr5 zY_u$IAIOrz@A72CkEMJp`eZWjnMx@QyOE_tJvF;Ec2m8u8f2mMEN=C3d%IG>6Z`IQ zGArW^6Kgvh6r3Kkz6d@MO)cu@g1$iu@Lh4o2y1>(@>nnq=HL_=%cEh~yo%WI_bluP zrZ3_Qr@;ev{ur24tLgL%?(_c;Yz0#EAizrBdRI9c1WPFAtncC`#l`f8nQ_Y3uSd~M zeENLN|FEUeFJkp9fvuF~K-GdV*>#aWJZp$0Y3YMfP<!EO?}K?!Y|<|Qx~ylS|B#P= z_4wXLgD0oK=~bK(78|ak2X(Bts$RQR3r#YHZ}(zxsHFidz0bGMCAvN_fA7ah47SrF z1;ZSA^3d<k8uPJ`D{|L3+a0*?coR(WdaD2K`h;qb2FB2h^kaX8#x>7i`Sqs}J6A%h zZ%G&?a_Di9p%FG&oz~Yga~tzf!18_7kHS>29P)oK_v9?2%Q=<RJGnSdf`lSonQPcU zP4IqMj{y*1)hlvwrM<{}=qch*dMCmyryZ-6dpU!eG3Z9fd$^&W!1?`DRKdrQMe2gt zyL53@)q6@$PoJN9W&JAk%I#9OC`1pY(O2G7K<(z~g`q{$wlWbHr^63;I$f+CR^*pD zvpcfY=et>^uNhi*JP5MG5VIX`Ck@LHIucoV*Qt#^f{p^e7Gt?*pqBgdt)Yo0H9o5` zHUE{*G4duLU_;k)$VCT?<86a5yB`-8ZF2;@m211QnS<+R2B}bXqv*{qe?b2H6KC@) zL2x$ZjKAY-4`VP0)gJaWOh$R?)i1$ZeT2B&o*2W<@*y+Ie1O5vly4rj*ksWs-KF4M z+W4w7n@Wq*qAeSwmnkFJjZqym8{?C(2m9U8T@t-}L9&C}ucJgY*0MBwNQ}w*7f(iy zH$<s_&(?)h|L#c~%mN`{IC=RiAr9Q2?CwhZ|MW^=3CIvm#4{-bK>=^vEeb~`M-+6w zmj3Gf4YC!@P2M3jSHlh)sn6JDqu1XYfx~meL;on|8}ygk>T9Ue8ctNqCr)a8ee*$E zT8v`*Y5E;1`lEEL0?G<EfNRI^{;?=4h)tPx{}xvlup7SKv3~xL4C6Q)PLIWvMH}Ja z+HIC$!rz<)P<W8^t=KR9UzD-f&Y-bT_~Beoye5cZqW<<wS-&y5bj7rIL9<+>=`f@~ z@&0Iq_pyJWlgyn<&Ap2?H$KK}9Yo6@-EK*prj)eO0Bfx*(o{ztaF=*gYh7xsX?W+h zJHC?CM0w|q($qW3Ag0^w#T!1Q;ODDJ5ji;%AECSOnrFObSU_$wdhw6{r>BDw4ABkx zw`P^xsz=W1u#jHZw>fzi(gdBKX7#tS4E?4vAI7+XWI{+!v0y+bLr2E$c;Ck6P+Q`? zERFS8&tQ#HvP|%dKP2x=d>-Zu$N`;S=jlnC@h=poq~;Ct>|vBeKfbK#xF<o56*lhQ z{WBmCgqD}zvMl+C2_J#59B2qfEt^PdeV39Jjd?;8BLM$&<F;h-nUtDlu@_0(E-?it z7b4ccUG{svtE3mn@n_)w5#A@M*+V)g!{>69U%!7&m>V1*V6Bv|%OA;W@Kju_`hmf= z>r|J(cGb?@we5x3c+JWK0eI`53TManO7k_#rD15iK{@eDi^64I+Kh14t`?b47OKt3 zRyyp1KDtX?S)re2IqQ3_87FEq1SwUhNYU?h8)WacpOPVFvR-qNKejnf2SCu*ovE+I zIf*iH^5rQ)@xq#s)gIB@Zkl1Nx=g%9=Ai?;4kpF?8kr@08kwnl`_0!7VvmMS+GNIq z)HfzRXO(iT@611*%uhL_-97AMWbUn?4d7R#?{tgBGE>WL{~pM6+a|4V>2|5}db(`n z(u)uJF^P6_S68Qp-^CW!d$??vwDulsLIZu}iNR!qcVhFKiKNsIjL^SQb5R`zfx2-} zD7(M!+*4{Fb-8;pZoEEJMmn686)&8bahilIkCUg}pEDzzIlNkp$)Ueok42{flx2)U zFLT>UC8aA!r?DIPT8391?oruZUgTdV<#OK29d8VlAhn)*rd**yPp=;TXrywc$HS_d zoVUo5kno9;ciG}d-o&^kr5CJw8GpK|?DJ3;Ni`WvR_<n~DOKMmm|jLn^yEEwgL+|0 z3?0GLV=c~ZhbTch>${tT_uPNxYKWg8*MADJ)IjW?`SZWG@dJ&Wl!`CQI#~nRShh5~ zZkr#S@J`|5*n>I6ADq@dfDab3#_guRb>|~)cY_2O*LJR+-ge%Qv8IMlsYQ3W1SKVv z!I^ZtEp<laPQs0;-HGtFu>oEW1<-N1o~2V)c(i6EON$yNs5Lzph7rlE`HD?qz4|OI zwziC>n1OTrWLwR)rzY|#M6~0BomFE)_{$w!ZhXt;bz6(C=&h>k;<56YRm%x;&^2RB zQHWhr%fgb{ap%^M4r7^D%fUF!+U_RK=mOD)hDmn(g+N?c@7jgyk{3B#zS_^vChDw) z8}=lKX|9i+noUw2qs_Bg)ScIKt9P3hbeOzgyPE8}JE6|rFM}gC@VXaocUpq}aBHl0 ze@76=x6M%;GR_sN*=F<Wo9V0BacgG_iw6A-VA*qqxS!70MyI%!O?x&soV;y@Kg_Eg zR5~}5EJ~Ea^jEA^kCIDO@zu|z`Nl~ub^dvdgRc9`*{hUdWI-bab*3X1)G6q2&f`ou zaDK&>i!OGAd8Jvt$8_-}hzFP~|2KI7?%(r*pCz-XEE>&)(w`RYw|QQmES0?Hc9Xi~ z80S!DuSFcMmW`9E#+8=SCZL##`>Q;#aebUm_`43rE;1s!eE!G2Rve)tyjTpG!-a@* zSovzaUodbjn(TmV=fim?5UkXAGSjyom!quC=uvcE*{MR>Xu54gZk~t2lVCmGvXJWO z>QaT;1hbxtT-o}8s9D=mT8d%U1~2bRuEhscsOb)6-TPfFPWQKX3>wc(?|j#?v``Tm znTyQNzUr56Ggpw-E6><s<~B^N<$w8YFC8@yaizXu-w%0w&Dv(Zm*f5<&QvOi;+h0) zUHBi4PmNUmNF6!RIvaIi!8&0m>yuM(vAgQho4OP?YB9%>{K(WA$tYsokm>`E;)|;B z-(NPq<!#zv*3zDjp7=)0VvXgk($lq%UH>en%BE1+mSyFO$XU0kz^JrdlF4#C+LGQh zg2GFUO@0?k3zauBL=N4RY%h%9l&9hy+LG&251;f+-F#^aLlYa~o&?5P#)30E?Wq3` z@jch1!}R`^ICj=RSkJZbgJ|xt{}eOd;6<-Z^{JCG=*sGvE@ggFo9sEZ^09d66XoSO zlg)k34+S=bW*@h0C$-=CJ%Ol*mpWAPwkTNalWgR8yAMIz<l}_|)Sxx#rOo{mtPAah zy+&eQx<!_~iK-a`%I$7<Of$|1`k$C=H7hURdVIXKa_f=Z;x`GU6sb1@Zfi?-ru(ZN zXCBV7&hzMbVz66$74BMH2OAz!(U{<t*rL>XhoO{c!q)I=z>O2nn0G(J-J8JJX|*$_ zk;<q^Y9pFE(QbQ1a~Y3HyuL=k*=%y=!_v{JZE*%cRk;&ZsU+f6msSe*K<TN4#c&}# zG>A@5psO&4M1F0AqGM}dVIWB?s<XG{Mx)7sZ{*5@6!~m-0kWOKRC^oJYX7+5boKHG zSMC|!hG5PdHMfp4x`QRCn2Le2LdHK<`bNbdhrrfZPdahV4n^~Z_JA?~##&$;qN}kp zTa#w7$YK(=-S=?c!6{Muw)!q7EG<qtL1fa^c(58j#MMt`GZ$tnvoYT@)@?t@-&5gU zsg@&r^8~~|m~JRtn8ZAy;7Lrv%f5~KimPu2=Ddnj-x1ia+3qdUs=yR*d|q2K!S8t$ zhz9_d0PnBV|36*vB(qNG{h}PR`5P?}ELbb!KL0Vs!vaUIa4qRjZ?Xq&^&SJ&hb6-2 z8<pH5s%_G|3!MpFZ`}-V0wO1m^@?r)Y1{YDyd$W|S31x!m!4!Dt_Zmx6K+y&%ymN7 zH93~?R_@(CHCTF;`C?YJI$wOfw{Rk3QQ{*mRceh`)6-Kr<!P>8%8Lsev-~;>jfX|o z+4Q%r`oPTa>{m-96^cty2xbounCTRs*H_AaKbHOFQ-RlsLVd5Qm$<{OYcRRD9`2*L z92LVWwYxcJ%K@@hikk)2PhQ-})X6BE?K!knERS#`t(J>rBC8lsWK=UyHn1b*=d}-O z7^^c2r>YAGrb}0~RV&q9Ut}ZHSGq}SpQ%;ZJF**%(mhzNo2a9&Hl5rNRLPaXif&)N zQ(e`TsmeI-`mrr(<rP)`o704}k(I8IqRH}EI=qJ^jw6p!H=o&dMUc72Fa@Y(PGx>4 z^u#<46Y4>)u`##hfb8RX<buF2s00bW)R6k(8r=KuqOV%!5V^f(b#kE=r(62DMu*8L zv$2YokRInk>5mWZ+aEp=^DR2ZWO^Lqx_0M}!Vglb>RR`C@28S*v@cIMP$k`~bY>AR zG<dRuU(M5=O&)iel<8Wstdz>IDAqA3Kxkksq#b{q(~8pmv23B*lA+{s)ZVRipX1Rg z42o@p>5*J!$stTSz1xz-U2#>r@;jSzNum6!+9DUO&b73#z?p#_uymODgGH0k&eAbq zsC5V8D=Q91ykq4I_aev=bEpE}oGuhFjj13pEe=oiC%M=jFH3Ayl3(s!wn4<z^VUA& zdirufI#J={CSSquG8FMw+{43wC{9bshTX-30joj144TdTO|wE<<K{pZH19-(In8Gk zQ}gj@dt{&l>}rIzH=0-rR}Y3xhC2IQyg$h>mC&h9!cehR-IJdP31n~KDjwlZPo;r3 zDw57hpevirs=8N`Xm8nDZDE_#elSB91aXy)t?h_1nzjS0@R~_r)hk=fQG|{c;alT_ zP-A|8UFZbr;ls0lknIWliAMZ_)&G5gQ#f{1mP7A;R^hH$qoGso@PO4N|J8etawi}u zx7|qO4X_XVaSRl$ipJY>s1-!1&6_?pTT8uf|HCxbQt;sD$v3W?cPdoUH95X|25W*0 z+VD#U43?HjE|}=(l{?@>WumxEM_HBLN)sBZJ_5LkMK{F83)gHPDKbx#m+-7}ZJT|> zz28ydqo$cSC6a(5R`ed6`U;Chyc>cGR<=N_Fxs(iKy*FjJuL%}9tZVYM{xe&e-q<! z5RZyWTe_vFzN}Y{lJ2#eE-(X?3qm5NVhi4^gPvr$iN^w!I-Ab16+jor)ZR%^n=_*$ zP)++}y|Q&27Vv5Mi%K-jOfYKCrp&B+24|>eOHN~8slJ`PwOHJHYNqMKM59#ET#wE~ zES)`rT9BK|rs+r1$*4?$-t=3a8T~Gr%|8#jLQ&lkHQPhjg;NVuR3A2CPlBJqynn$X z2rRti_V5>K`AbLq-<LqW%vy=gFVqWAjI?qgqh15mZa03WK+wH;CuZCT$NlgWCc5h6 zMpvB)!bcTCnbF0`R`ffsh=}uPD@#<pE##&W&qMo)@AGO>qr8K^XX%BK#<|bfr|s~d z_Rb4B`>GkM4MTcEf}}YG0&%Hoaw-qscRc{bIHw8|Hud$+DG_v)3d>8vb%S(|Vwd#R zPKuIo-7c}rg1UmSb3W@8j24Em2B?y%zuV*RkjmzBD!4a@K}Y3%@+C#wW<W-i#`?~e zXXzF0`(=AP?iI3e*KfD8Fp7ImR<7P_34y$Lc0KHo*9jTsx&<CpQ<d=1B<a%Le(Sjs zCF$a^=NXj#1g$!HqbBkk7`o6TaWr~B2zy2qt$}#<o6&DUGj1eUJmbH#`LT`p6~lZY z&2mAH3#>_`&R1JpAj3>O0U74)GP^W!ZLv*@p?i@4xmdo?rIJC(c9dmmWk=oC`Gy`f z7J7IBDJifDf0oVaac;CjZu}}^m$+O@+AX%`K)#>Vn!Rfm<ojLho&`U*nSLtG6QA!T zmSJH_XLFxZ+Dm1&lcjDxQ@fG*M%U-tnT<4O3ZGObeD)E0{)E4jW=8VvY{`?caht8y z#T1hKa@+0C&5NAZs)rUi0whr1H!Jt5;wBwPcTE~ys`A#GSSO}$Sag_WQ@qeWN+;!} zlxUT{>(P3Z(mL<pn}XPJ=PLnqv97}63a=6c95(9?S+oOPtTM*UZHT$1yG!#cqHnbH z)Wy+ddj@l8RiC9fr?~YsSIxqBE5$mhxQonEgSB|bX&dv5gJ*C!_Q{Y<lAC8d$exFf zCi9`jze}&=5AbCx9QV8ObUWqcxzo{CY+WlYqAEh!<njdfZaGbFe9fV=ZuzAJkZ2^c zel9xWU`t|qx{fSKN>-<Mze0z}Wy~*cWY)uZR`?Qz0CLK7l-8pI-fDl{ANVgJ*tI&c z4|m9cOcOyEsNe^uK=oQwLN*y;k3$tf2`-B%?`6n{@^G9>)yon(p0xeWiq)d_bf<|Z zcem5YM=@?dllSg7zZ7%i=f^=;Ugi8-Lba9Ub6h<WTmx6%-nI?Rxs#t9#O9ElSh@GS zIfh%ga-%arY^6rz!HjJ_pd=4P>LfG?Q{~)7z6Znwj5mDP9LgzDDIGh#J(b@?=eK7& ztLBuTYPMeX)sui`{LK@$kh+?Y4~gI1Hq%<&_8)k}@FZYf5AiOq@tGYId=*IUqo8w; zIcYYS4m)*>8pA@b9c~8{Ja?(Ta6?hP(kanG%g4_{GQIz{s%4g4)RnI9mCMP#Bm&wo zojSwRhwg`fJQTsmv}@u0;4AUu6Vw;G>Q-4d!rVcV$IAbfT^273lph;Ci`8@<SJavd zGx{cB(MY@bBnpFtau|B}qx%*RN6PWCe!EWKUMRs~?e6|TwkS}5VDjS7IR1+0@B2r{ z0@V(2Kw^M^YZy||e@Lmxw%Tks8sMO^>$b9Cp0*oay>(dx8*>g;VAL)w{xKr~r_)TY zpCsgUhF714tn16WKsJN%G|Sd>!*CXzAR@fl#&<`t+q*8IT$wFMEw9ua>|1e&E^TMW zv|N4MgF#mpKoWe6!!+G~K&>>-b?@UO=@4ypO8j-xui6I!E=9eZA)di^_IH~`u@=)e zW4H{S7MS;a8go8$`R<FT89nF5IIqr&L9~tM;7QQs=8_;od_lm{+<lW$ur-#Sk+>yJ zJtutUTO3SYNuTl>k307!nlz7V*PxiLpyXJn_EEZQTZVTb?*l$~pKiEbcb{Rqu>6?2 zwu0O3e2WZ~RE@Vw*6W2U0&0)g8pi@YzL0rPC&-77gGiG(@B{b8&E)UsKe8ZZ5V$0c zoAC%Rc@>dM^ar^_yIMnrANI}!vzoP(m!vKTU{!4|xTNiBB=lN!%yCY54pmQgO$zal z>l+|=*`TX5@@8e3&~LU6-mC(QBrzL|iYgwg<gVP3uepVR+c?&ctz*>Pt==)&NS6K1 zi$zLmrT9z^S07J-t0>BRD7#8cn9<0pWMpNP!;CuZoAS(Rq5ypxCr1bOr}c&ip#B_a z<+saNF}bQ=tgYjXiZkC&9d}<3-Py^H;cZvujP?_Vt?gHp3nAbLsViqZP)IQALh+6! z3Ah<eyDX+zRAR4%5Be{8uizLB8+I1lXTQ^KvR)NXV8%$0te_r8d@%NKY*q9Bu=d{Z zT>stwcwSLd-ifrNBzX}sD%n&<c1HFpqU=4hN=c+_vdYXJkv%G9Mj^^Bd+)uz=kY@6 z`d!!cx&HY5<0kQXKAz{C$C>wYPW3M0#_H6c`+D!gwYU|3<m~=4EK`Gus%^X2YPs*z zrch!-dfcBiaY;R<*UY$&v<t0wabfEFaU!ew&UM?EcMqo0#*5`N^L9ze`pN0oDFoU( zPGWzUOMk9DMb(@krWIqHT@datJNxcr%=a6L9;B8s?**#5118f%-Qy#zDf{jfkF3t$ zHWfQLn@t)gd*#OeZycPXT)3>CW0W?hI;k6122&C(_ED0gL;nI<LCMb7Cy@li1D20m zc*G?DC1K~rI+#X}T|9S%gL~L9VcsGA@?9^t(#rBk6aQ8y4P`1wA6AoYe+(*NjZe>8 z&2jb{LB7edxhK!JzN)*_oUJ*cd3(qk`Cjb{TbWobi4ihPwlEq`QK7#W9UYz)fL$*z zy}SgVynFdW+OzqjUNRUq+_gA!t-i@jU()Faja3if;7D-vg!bER`GCpO!ihl!AImDZ ztAi5i-t;j)|G9J5>pE5bCJl}13OW{fBF~y&Hles;_71ytSme%SlIFD9^U*b^-`v`o zhjVc_O?JI*{&kSr)e9$`(&cx}4aI7tnKnpf8h(y9AGK=E`zJtCI_$ZE_e(GHv(Ki2 zdkO#f_RIm`&l*&y_l#`(7Oaw3{_=MXln%ieO7>4oj$OsIi~>%Ij1r0s1CJ}^H<XwX zDmDnQ`?B5Jvoc(M@=U&!YIbL4&ES-2Q9fV!7d*TI)I7Y*?XrXniNzizu;yj|D4}|T zV1@;6_!Ya=c!N|QX6tcT>5%Ih49`pnq|{)U&Dub8ed>p9+0h7xo;X$Gyh0Xc=Lilb zwHHk({XCq})<yR9Hl~SOYh@YQneApv<rR(ZYUkc#bKKZWqx^p^1?2`bpT<g<x;fqI zePNImu<9^h<*!&?)x=yP|Dut1>COjxJr3c#zH_EgYU{UFcMUeZdN3vL$g_US<nFgM zR`;Ku%?G+JD_@v5vKtS#nF`(O#*R#|`yr-qqebmBddH{TJs~MmUo&HCcStzJr?wYV z@1?ICx_hB>q=jjeLX+qMJv4QfCtT`1>mL*iBi>uz8v0y{TWhzw;yrwV?q*=Ex0Msv z5w2OI0EX%>iscoN293{Q%xWUG)9d((?|DPn<^$jDhKqz`la(@7VkgL4UBC#~>RGI+ zXAe(EcW^iS&8hG5P<)?%T3)_kUR->@K3l^2oT$^ZavPm&S_eRr9r|&tYJ%Q$V&Z1P zkId{Algg|T@$T=t?|Hx4iLpM+!e#0^yx{5d^<nW(6=sXx>G9gDp|?lJ&J6jd+>)Jr z@xl&QgQZq06?26+KBcFd!PGY-;@n_&eVCUtZ?ohhuM?y9Qh10IyUJ#Z7xx}xF??;g zyxQZrVi4ivlw}#RZ{SCR+?(lqb4*oCO$`Qn#|=^mq1~O;5#tMP=jDH?g@s~Gm{e%? z^Bh!s`4Q%I4aS6NM1`^c8h(X;#ozCm+R4@Y`R6yPg9<dxPO1HPrrZ!mo?AQ^$}8J) z07Ail18n6thv9d{GBf!V%6sNl$6)yQv^G)gb<wri_x#lzw$Y5RXOdoXa%%9x!&bYe zF8n~JLIc=vw;|yhVI8u%FQMOlVhuvO|An9v4R!q0yr0iGKNxk8YlyXLd+^_6U#}%b zG|ElNzdSu7tqMjtCe}@_FBo_7-KCtrz9t@$GqY1hYNwgwy@hwOM;9C_t`Z%ld-ZIk zyuql2>nbUQ&8YuywZBX#pJt9m#PD|+$BqJL=Rw|=&TG#x{0$mTLVdMi2^yiRYYwvG z?-(L4JMo%bvFBO!vVS48M&*pbRt1|_kNK9+o~bM;UOwmi1jFxlJl>3E|8b=*!Nai+ zh6hhbTRA8^@;WM~71ngPsKC<a;*ZGJ?G|rM7);NK{^VS<`H3?Nab6UPxuTA%T_5&~ zON&tTtOaukwM_5C-Wbch%C}^A)o1SFNxkZqhczuD27a|%KHBi6Q?vK08-8>3(6k)1 z*nYqH0og6`yGeGPj%-zCq}A;g6Fm*W#mZMoEAuS+by~_i*rsO_gg*6a+Qz7>4)R;R zZuK*eT3bpgWE(IszRFy6mxp(~MUjhlIay6TQ)kU`MUaXPguG)BZpwzu{{vsR4p0DF z=aXIC8_sU&H9Ya%QZQ%JB7vntqx`@WELUK-r<~KwpR9UXvo18Yw%M>tJpZ#npobL4 z8n)iYd0lmFxmEcMV~7=Cecxde$r)&Grxi#U{|v<t2kI_e18<i!f%`-L%%O$F0hzoc zv-4IhHt`a^A}73?mk-sryY%9NgOkz`9Pi*L?7Y_NM%JF=MTE4X987(>eiNUAPx$pN z_I?=s-y2lOv-t6Vw<2a&4rCe?S0|r2Nyg!G`j=LAv^yN<pBMiaY7$tmwxX9eomvp1 zlOXH#nfytuSjDeU^#Yyo)OPc^5fg7e?z3XE4&wpb$A^jgCSmAZrBnI3>W??t@yAzt z4_{o7U99EqS>v)oZScd5%aBW*UGDAY$y<&XlASKTlNV=sxBtk;h0ykbZw=R~ZoH=Z zHnwQt%K40w&%k(jN_^3}?gZy_<odOc%-g+($~6?MR-8{TS@m*Cb+^5-h}T}ZBnzu) z6HMiV5>6gg?2<p$f6Mm1013Kp-T%{lgD9y(vdwuhz-RuF`4}ArD?FtUvHUAmJk$1D z`PAeR@zi3I(Nwq3=}(>h+~6hC6NqUzW;Z4%%N^spuGzwVm*xh8BKvJh#$$NUW)il* zAng2R&vC1J4<;!0Us4EKuPvLLy3;MJ%k<FdGzsil!k&um6UJFJF6gG6@b=gWf0Do> zpDcd!zt~5YSjf2?fA-!sFE0<^wdxC*=hD`fJJ+A6OL63NEi`3_zR|6oAsDa9AS)UA zRZas%IA&LC$<S+JLAA04y2K9TQrT~z>F!nmQ;yL)tW>yfmD&EJ**ZI;uq>0N#<zzK zdb=p#HJ6J1;#O91zdNQk)2}JT@wJfL63s|pM7fV;>vQV4*L818$Z<2R*arANDV1X> zR20DBCIqMu`IG)F`R~nsq&>=N`tk|u;O9#*L+v&@yODQH@E{&&BJh|1gm>o&$>!NH zv9&99{*219&34n+>5I+>UH$Hzb#!*h)lJzK!6Ng|@uf;mv!}-{qDgURhH1hGNA^pY zkyy(f0Zb|aWF|ke$np4-qu(>GvKxM<g2lvVchtul=pFr$BkgKX2;fvWWO7z$<1fjs znUM45;)Y=@y(t;mG#R(|nzY{qxQsivAsxGLtkQ*5F25X`&G{AuX}yofT36ZXMYMe) zO6z!s3kGlw{<1JE<NE*V_vFuOg0xTbS2_>rIj0L6=S~W1sez5n)tW%lp9nLMuk&uy z^nInl`OfF84Z0lPNJ&X)I60Mnb$5q1+oH6HEm=i%wO>t*L<q~x`(ftyD2k^ZC&`I) z9OqU!8_3XaL}x@8jG_+uoToy&sU|u*YsEe;Weio+e2wn$XnKavviB-UdXNj`^1{N7 zlQ%xDGpIuR%xGQ?K<lPl(KPo((lO^Xh;)y(#HY1zm`~B<0q~E<7MF%p($u;Z$u~9I zWTgMfgjtogIfzMnHEQ+sbC}4YWcgP#)Ve3RLWS{s1GBTiN@iF#>8v~d_onyiKk=p7 z5=@EF3j<t^j50js1jkW!PIZmQ<+o=QV#UbOmYOWs*(P!sh5p<`bnpCNfneo*g1wEI zNs2{snQU=YOyp<3d$_6?QGvYd3YG9kbTN<m_LOz@TYrOaF|~BI-NB=P1_4B6*=~~0 zIJO-C>|WXO+v7Z@0`~l?UM&fA;tyiYsslTAZ+M_uM6N-;aysR6qxwu_db(BW^KIH5 z`7>wlmwIUU*8H^}UExs0x=C7d5dCQrW=-8**`0~7J4nEAA4*hMLX&dT-tJz}<l`J6 zY!0b~VQcv+cVLe4Z5Zc=Hi1#j215e@O#acWIfC|#sW`O{lw6w&Qzj)RzpePs(A$?l zl)c7h&*YKk!Z<4b1oG&&l8$!4md2g6M*QcfT}sJ;MT(5J8yMCTt}E+<3CXsLOICf# zwvQE-PL|(ImFBA#D{5_EE~KL5()=gVZD6hqw^5u*0`tIr&YzdtI?-mm^|eoZ*H8Bk zS-us8Os;+vZHE;$g8$9ro6nh-Va8Em=H?FH5`Fm`6m*!*VH99}Du&(l3|uSJn=+6) zt3VvqW7xuIls_*Y`|H;)o!OypXox;#FYYbRJr4||O-M*M`@!NFwkqb-gHZr_93lm6 z^XhZV!AMMVr=|!DWTEkMFQ#cHCA&8lkDNmI?|GXYv#7DE4_!8gPEv|XK4>vnwe@I> z-nvuq?k@-pEKoXwp;wO#a31YUYx<gEV{&(1P^6(bMh_2`sx|7I+laU~V6f?lr7<$m zI!1F?*(42KyW8(=lLC*Lsso}nPMZoP!Ltx_lPFC>>sx8%RcXF6c?I*=VDEwstb>&W zzz>7aGy(&E5q$~Uu-Gj6B&^;hdnMFoT~3xdf1Vig6WL-7=dlwit`tL!ey|Fy!tI^2 z-(fCm!qLxp6c}2x|LMJ?b|p?00lG9F+V$`s$}{8O7Pr21-A8$;X?}-2?uG?xbmf(m zBZHjnEkddJe)38rUtF4K9R}!~P^pIdfXy#jH(U?w++C%pY3NJ)jE9>30kgAN+6@EZ zm~+ri|C$x?{EG-E13vE|MumN0HMJ_#jv~)whC^ZI8R$nL5msDsEtQb2b43|unRA+U zxs)~KYbw;*Pm7(dBVj=riOl4L_`K@ND@96+qa(_q6c+^SE$!>aC-(`I8iU##dE4EH z8zYH^GL1VPZ+sIp@+0FaQf?uu??^j$4gh)&jE=o)c__Qzo08SICK=|j%ST~(-+z9q zc$Mrx<gs<v@i5iVoKeoMaT%sIC1s)9iF6chW}T$%Z4ARMsbiM5SFA@?6_D(~5(mX6 zy=X*_mWzO{E-YC4dNtf`vF0eL=A}<A1uSPUuMnG5OvVmrxQ1$<^j{BKO!FFCSG4;& zdGa0THy0bc=$+UNLpths0PpSDNN1Z9EsO>>nrq@&DYq5^V|UOWMHeqv3cW3pDvxt< zO}I~jb=XQ%sCj(%UiM8bsn}I&(<y2mlv<0aZZmyQqrT)ieNkEv7J#1n;~=8%3isa2 zo3uDOn^TeyE-V#6GY?q=M;BsMqOk9#4fIFx@TpO<$y@bic4=i?o3q%Pb9ISVrYYC` zvY-``OP>|?ic)oHyu9`CiEmI4R-LRxd@23a7`GWY9vNWfSikCKG`=J-_Vf($i<hdd zD5kHEXTWw75Le*`qHDIu6eoc0kuNavp2={Xh<C;GGn?z&e10?cyD5kwCwU)lOk0Q} z556=_Z0Fp;1LLNBVTE6Ul|)6@sc(sjmy9IsnZrswI-+XaH#G-NIu*!*FX;OtizlY( zkW#a5`tVy-L+l9*HlKwJZNMNwLw;Spx9!hV>CzdQkvJN}DTk&4#!E*ktY6JruF6B< z<^c8!3_uRybIfm(FD@LZ)JW(ot8o*61)^bYL=mlzgu3Pygw02qHE-KadDgGzRln;^ zXLJjt)*=NZN&AB?5H=qXQe77Syf5BA&zLoivRnuF0L^@xLt2bv^~CpQyKqWkdT-&E zjOd<KOQl=g-M6)+yj8B3pHuHi=#M<_Y{qp%pi2;YEe<z=WQ%*^d(?7GFXv|&VdJGD z{M|z@1~`3qq?}o+<q2|{Ox2C#v=me%zOkZC%r^{n)L|}Ant%O@3hbq2P@D=X_B7-; z43sBv1@Bw@)~zV6`8o3Ho;g*Mi#>c2PXu10HxzrZEO=kwo3LbWkaoGwwX_H}y1~V3 zN~8t?R8jERf-`gJ9JuqN9rZk=2lH1d-A`6En%y1xc6Yq+bdEx*{OjG!a1?<1Q>9xq z=-S;b-I4A8PFq;K78_adDVuXsxd)PqHOB7x&70pbsgk?^=MO>7pMrM#Y<q9py*AVK zR5+%l47KHH?F)#BUcf}HnLSUlRk~t?Jr$5|%y#Dsm8f{Z3ctwSfEu(2Uckl`W<ZPI zC|~!IJE443F81yNrS|c6ZiH^&sEE>K=PBkAthHr5JigX@SadXk=7EFt{(19Ue#`+_ z0!#BN=P?1UH#Qe6>#toOKgW`ldsk0C<3HD58}4^_DW)R2#5wO#XsQ~nPQa2O@M(c) zYI3Sqc1YUUms6boITI`mF<>r<Qn+x+;*orkMtj+}!5m8rc1f9S`>Gp4C20YoP`X!s z_01X#Zvq(uVJoXr+BM3v)TU88spXJv#zP%eB(?1<Nd!{H$#T-Q+};M_($Yb&b>8NT z1#)S=s0%E59$7pY7WeG<sqmJprqvS?j|J#}S#GkS4i8nS_|tj17W;L+dltPfIzIMH zpbU~#9t%vjTydAi7<q%2Cr$7Es_^kP$=76Z&hI;Rbgjj}ysqdX?@SLH(A>r4D1p<` zq{vawv|&7ESB_=hIpyeHNYh^%5illg?HldQ++&;B`ev%<P2G!(3+>GkU4k~UwA&_{ z?ZERSG+eNJ+U>blLm|m7S6OcGl3}pW*@lvRK$TFo)9{p+H$d$u&=apFALPi}^g|TF zLqh09MMaO{4<J``;PmxmB~}@y{jvKgsMX0%H0a6dUIrHfU+O)6ozVyCi68}|p3+xW zr<(N&su&!7KV<GQe&P~>@AXeuPfyS5<CBw<`ETg9G%T}BzcIOA;xcbA8Vw;p#RfFH z(;1YOW9)azaq0C=<C3Jrn7S9Sjx4-5fu`2z3Rv5zGu-!ih--QON!m%t(8Rj)@e)4! z4{NR^H@?y2zx$(Dy{!4x42CG|2vg0<rp?63wwAD~=F}8TLO0n|$@(hPXbc+SD<ci2 zVlPI_`IdTMkESB$;}h`a>(}6|y2x8JMrU|5M{N=cQ8}>(dxTypgj#2=yFc))?>%~S zwz*itzTRyI<_Q?hj@`J&;bMi()S~H66jL3o(~XyByMOh>DwZ!?!YkT%3t6qDGSN)) zL0K!K{TJ^t?sQsbSLuE4p<RC5^+U1wgyy<zD^{oWx&F7Lq`J|i-H=%x<FVR4hrs2M z>zZhLZ!5&i=XjUrg91le?1zn)*)iC+&U<&jTigWKBkDAavZrJX0ngJAAq$#XP4a#b zg((?}(^q&3NG#+3ScZIZb3?e!h|Ai)e~a~0;*pN4#XqveDZlHPCSGvrIk1ksiH`(Q zpp4MaB20fOv)hua*K9f^r^?Ib@ImF)x3GRbXjy&D<aD$DIi|gQOX=56a;pOo<J;r@ zD*t_<W`PmJ%Gri_Ewis^C68<Bu&7nDsLr24^p3ZMNCBD&$tW)&ONc8`{b9wTt6$>@ zQMOzWo9b^OmkD$CG)j+970izY!By~YUSqGw_UH!-iHs=4!E?C0q+lU@*m}-DW2N7e zd{R@bYtiwaBZrI@-(JBIN+WNPj0oMU2&b&479Z2<LYQuh6*erk%vSCmKj;6WAub`v zpG?Z%PikZdUZpua-WaEXH@}!-S&YA%{>ZgXc{5lv@~n5r_e^-2-7lE&;^A;O6)Cb; zP?w8}X8X_lD1AT~>7Q2egQ3pKR*kmEe<&6!iOUXh{B+!uUNCO1qb)5X(mM68WoqA< zJ*Ds@<ymaF*vyeOiI2NJnFRhO5jTom+1DqVUtNv4Io-F&+`bmZWABx`xS*}q8azX9 zZjz!>+iYzI-sm}Q$?)y>1D4Abn3M#VU3IVYiF7izcCcG9kS%a>>^F$8g<J6J$0IaM zqx24(gKG~N$JYaX3GmM*xcY`gtAPv=r5?R+{qGkNmf6^=yd7_00`1^8bMtE9Obm<_ zf+88Va6is1uYt9WG!yE}w^r@#W@8!FBh=yyl?Mk2!yBJ@?!6}~j8pta&ZUosn&@=Y zgk%~`2h}>v+TBgRVEm(gv8C0orqZwX!<myD1zC`nB#juNX%3+8F4Ua`h<$SLhsM7= zl45)XCRN(=w3304_2w#=qhOafVcgWX_yXGjy5`@P?9!q6hfLL^r1uG+ne&)pshBZO zBgd#!VQr*dOLjm>2>^7ZU!eLm%4COzGJO5|^^q3CHl=1l{vkp5k-&L0c8SClD0IKo zzq{PK(oIpgqPg`gC)Pe!`Mih6(}3JhPs281d@2$rSIX9$q>{AG@QbZ^N6zTfM?3S= z%S5?NzX-%S*o+6VKG5{-7I~J~Zjv|3ZWrU|;NhKcIsjG@vOP>#2Dfi^E(31OmahW$ z=X#ejgd}mqk(_Hku6NB;7bGbL{q**e1mDca<$SBf5tvRk#(m?oi+~RFu6#8+3Bd-g z;-X~$+<M#LR8213Rc5X#c3A`eh1DQ!=yB(FtCb?E)m}2E|1DPqBh^FKn^ZIJ)V5*# z0*WSuMJ9UiW+|rE)!yj3vTNWX9XDYxmI9hib0I4Y2lnxp4?Lfa>t#^z*K?Tl-$hKp zmA1GnxacWt5m)#8_IQz^*6S(m^|gG~p*98LND>bE^xnchZwTLc?xlP8m>AZD>v=mv z3OY(4o05zFv~<bD70B^?p#>){l&lC5<uq8?f!AUPT(Dn`lHW-U?bv%V3*!)YW`2Q* z4OV}tQDi@Kz;|cFIBg1r-MV#M60EPuY*xqS$R}&fWh$2lfy5|TYSUMz2vi$0SA0rQ zjs0+%srRX(NWtg_A!wL{L{`reg1QYUhv~h7B}FQs;Y^&7_oy`;GZHFdaugD2E^!yH zYAgm`?S)cIWNdg{+F9!xKCEiEx0+xw?W=L_0VQSLGFg}47vI>wm}bLOEQt0~5zyu> zHmSxctlCd~_mi%A+FO12&fb}iFJP6M73`v0UDX_%J1aZcr^-0LyuP|PEwm_NS2+Jw zWJr4LFOuQcoHd2TKMavf()5wc)BJi7{*DgC^rUQgV@t!|>H;NI_^9Wb@;j4nyF0dn zT`wkJ1YgpSQERZY5@zpTjkvaO(I#mnZ1vSrpg#M=nTF!*a~g$oxAi~19<HmY@sEj# zNpFlw)`q=YnXv0dxx}gHIFBt0<8T*@e<4}KoJlKI8R94=O8vQWHrB{bST@_dw?gv* zLl%r0B2zUyFSK@UVqkCk?e-v5npbw`Lju?jq4~e3x{h(=8FaCnEIOUG_+`*Ur#Yjp z@nQB8(Wiw3nbbJJzlwNVw^R*Pl0ISzo$CI`g4OEsrB0utIJ;X&)Z;EO#D0eg#ak%` z*Nv=~R-H$_v&yW=oVbysKwS0o-FAHlJ{P|Ka}RSdU8C}#BZAy~s)v|0+V)j@4_qYW z@E91qX$CQ;8OoA2h_y4`F!Jxl_o8<7Q!CFQ6A}@jkfp<h4U{L|d(fC`)=k69tL}Y* zHxUIgFh%pgo#rf$7|TJ%Y=fqB$<GImg@BHrw$M}xV8x8u&-h;SHqkR~jmaqF{drN_ z_<b^=(zViyroIbOfnxzjR~K#iUwzKBo+q^e_E>iE;oLlG1+X?5s?qnjf6<C82rkl= zb$hR$OI)*%ShSOnisZUI@;QVOtVFtx0Bd>WkK4w%msjJHm);~V6?Qz>UqxxtPHs*F z&4O4{(y5$-m$rM3t|UZinsE|7bwTsxjR7y_I}b;ZfA5FMu_JGq<so46!2)ZJPTa{) z-77zJxGEa(#`(3O{2^(JL}5MR1QX}OuwiID5?VUh>AYTK(R)$9@%g8x6yl>T*|C}3 zjrU<jHFqmYb<Q2Sj?ou^(JZhMtYTNWW`$C={tdk6eCpf~$2#s&>n6aw0@sFA%xH|< z*wwA0GIQz8)B2W4Nv3J6G~s^?AkGK|)rNET?|Y@j;e1Nark5S~?2?V2nm4CH?{HN) zuW3^9jjo;2&-wLQ=QTOu7!AIo(?!qt*!J=cZzlvEe%l^3^~9cDW)?bCg{ZZO-8qiA zuS-B|S0zKxB!n+80Yos#|B+LeX%t?iNRUjlaOK3$58*}sM@n~THI%>mxQJXar*)P* zqhf9A^%fEqRPsKREOG1=hEi^+D$!~<_V&uvOcqCTw^ZNTr${(4!n>u+&CMHcJze05 zy$6*ZzY06%3{toWRQ@1NR}wzs6d$nsQEA^(idcgyQ7ScIAC+Y<u{RxiD1(-*;5>_s zF9H=P`1E=~f!rm81Uh(%Xa(cyS32tN^I#XTFKjwV@`F7LLa=Ix8b&n{8_NoxMj1i> zE)R2+dPvmDKNz|(?hgqvbMc3J-d=n)F@dH&J>#|^ekKrKG8eSJIXNJ1Kl}6Kl9Ce< zLZ*uN5;WkI3Wk1^#of*@ICI!Ro~?lUDg5)om9Hqi+NQlqqk-7ZE?ht-e}p`BpWsr_ zuHd_O@A@t+%e2692>*wB4~xMnr=5|{ec%O4$1$*&!w2?oC8iAtuM1`N*Z97EO?Quk z5SEepJ(sbFCM2=dEu~T}UOHJn;JP&RZpMpH>43NZRVHYA!MU|`F5Cg;;W%vtrdyqd zg?r^o26eM{V#920qPBjxdC*dr>_RqwP7T+f57}rzk=qz-3u}&1D=q9ays;Z**9iIg z`F-m*Gc(JypVg;_T?TWN11M>+Kw?Uq%{y-!C2@@HdpY5Y17FaXSf{|6gNvBDHKTOK zMGn;yi4>>TFIfopFb9)Uljwq_zS*(E7|mqaO0OIN6@vtPlwfKnwg|$5j-5-b9XogY zMadm_>%ioNejyY1v4Avk>hwuDzCN-WYvTm3L(r!dW}%Utxrg$g)J8b-bf0{nqo|-J zj8iV0mO(r5f)NSDh`*PJfFHcCq=aSW<I-tnVxM__l{3Wp&A!h%>_1T7klBU#gmO}~ zfgw09d!edR7}NQUXh!QcJXfJZT^~2i=r^CeP@1Zc)du~52mX4JhOE>IX!wPPKnhl0 zqNzq-*@<w{%}?Op$qPkQzn#1Pxn`KMe7iUK(rTFN7$H8`ej1ib!Xa`m%fI}b8hf%o zcFpnY)MS`)ALIQSr%9l55qqkvPXTuc@=>elQ(un_4yFePG`k7@C^U<1eEKwi)ANnt z4epOPuk_D_!AEHd+pD_hh!~V$d>s~Q1|sq@H?QZMDe2+ESXkX_(GV(*7~zBo2??o> z7TIt0zW2P|wR`PHR%!KU@p<5WOz!w_TYS%qlbu`P8^gTDyqvfd?G82ZrfV{U1N2&! zT{M?2DZ;M2S+z`ybK8It*$S))xJnmrS_v)d$es_{TrbHYMy35;urioKCfup{XQWp? z@$|o(T?xkCcnDnz%mnux*11Sow$TD{S=xcPu(kuXTGX@SA>z7H;h$AVrn9rNtH1cF zC}uy!u`-E$LIN-voy<sTCi9U%RmE2}o66nh&a*?A*6(->4hoSI9zjdn1=QkjOWRo_ z;7K>LBsS)WyTlUsH%R)+N%^~*zxOb&C))on5{aLMK#6CC(0&R5XC#s@KqS5MOgi~O zU^=8kD7)llwlEOx@F>|A)UZN${Uxl3VS_E#c?tLIe)tu!l`0>3<YEnf-jXtK*U8mM z`%{(bxL&2^Sg~povx?T*{ntD29>DEBvae<a$Nopa2v)ZMQJjR5q(2mx4K-F69%(Nr znK|*L^Uy^(n!k0W3m;Hz#!LsrLsT%d8S?ISN3M32?euc5Mq6P=Mhx$Mje3}@R;jr( zS6X%(41==P<gbsu!M2O4jc?PGXmdL4lWJ|WxbXMD8`BTGV=&me@A&+S8nxVOiHa#_ zBlVavtuy4^UH(Dr5zyI#2<7@56dn;L=ca8gWy4evVXH*3RocL2M!CZe|41k9yCWc? zWwzR5NWa@c`Q?`=t;;ZMalV=)pWq7~+4Wt-$7n!vt`WywLdxT1DJ<lTP3&gA!tiXP z%wgzqo^>Cd5u725^K11nOhPxdYG!e755Qf5KA+T4j;2c#C>4PB-}Q^_B2MMpgx}p4 zef!o1V;PyBv)+u-kqCR;R7sBw>@?o<w>7ndixb6w^+P7d3EgwgY6m@pu-uaau9g}q z;SLTC`uh6H=7yl{rY@&2DE|jJy4M!cCpoWhW#2Wba11`US-@P$dQkdBR8D88b-Jgv zDnMsAbN|S7wu{sxFh$=FmSf<gkc1Y_d-Hz(TO8*Jl>}cdNnT0{0Q6YJBiUVl@tK4g ze)ZJ-KAg8e0pA;6#}o;62^O?L`ZiW6<JOQ1)MQ1)#OnEiBjDo%o@1)UPxj7VUrIk! zfAMDqm7X>SW;4wErh;LPFF7ZtTNiLPr-M3=Ay74mBk^+S4pe;L<m4Pm?C$Qi(kz<# z<J^tG9nbH4fWvO!Q_DfxRA+2&5-#B>P|Ao2GrtuWe(SFY9s)U_qDS(o)<snDhZA#+ z!ETe$U|^u?SGX)Qpje|y=+E14#`D8OUP}&-By24L+pOh;eq>Bt9VWjfL^uG`iv{(r z$8F4*g9akM=PVXzd>AM@MyBV^RUWcEsUP^2^A(=_t+=-;Pc<l2h!5cq4avp*+7M^E zm|28uCS!g(8k}H%CfL*cN|PG&uBr4<n9D6rWnvv-!^Pqi@G&5;q$Cs%aL;^?rYYA@ zl#Xs*P?sI?VM<zL^mu<c2dI?pNAkde8xC431d3;`aJn>6*qy`Bv)TRx81!<}Q~Qb% zOLgp7O43wDeH2qeSx05p9#QnPI_s#W37owmpoa+efDJeJT;LjVi`+s&H!hc!9o`iX z<Xiu%Age)5Cs%*sIE?Cn6dX<Cuesur5Ot52v?oR`^f4Y?oZpxCb7{D@AbUMsb+OUY z1t#`Lt<Y-Y47dP3=p_#qNiCx7vdYacxT%;RiLvn?e=dG5s1vhqU7YAXtDx7gheVCH zD99{1WKeNB6>`1N=nW%`?qo!i`v0)#?VV}v&99H`b)PjzQKTY2^%Bu1{Bj6xGB*_s zoaoB?8c7@{Ksh2`@^(v^Xw-`Q2`g>wSjBaxA!*ee*Z);VBG2SS!T=hFKLEIKK@nNx z1pz;DqOkBIP)>r*a=J6X+OjvqOig6LOLN?8mi0P$aq{$>S!PAEdt#{ZEf4)kv2dj= zO<7j;cZR#OSGTl_H|_<nAaUM)Kb&<Fi~#0Ww2~=o`aVAh@@Z+fu42WQ@TF^tqmvOX z7m4r2moJ(i9&2$m=x}$C61pLFl^=sW_S|Xw%73O6s6HC26~VlGL88i5%f(Ro6vZ<@ ztw^BODq{$4b~cqIqL$w0@J(v@34C(%@MSf-<?1{A09z&0%lWT1Zy7k2G2S5uEOXN= zt#|c1uUD&fR-({mTq6NCIsUB9FIv0Ver(acgVCy3cc*5(QO9-Z82l?$jZb7uLN{{r z`R7i_?gUW%$)FGJ`#nidK*vi(tBB%GT9_m=L4<ag`FCF3$ZK4j%74BsuhEr#^692= zcr>hVFgVZD2ic*O$;70dPE~g03_<-X0*WZcO}f-K$d$tu@-@;KN<;HZ+E>suL+*n_ zh9o2D24&^;7<S~!#7Tz9cV+plTmko!bwAHbjVB&OE9XnphwE1CvgYDp((WID1+9sa zPaa;5TI8U!q|u|sX}cL8k_bVPa5W3MK@u$fC6i!!0dj=kO#B-h)?3S>gYlaTp`Rk? zu;&+FdU}+>dEu)6@y`4+Q-^Ez96)(xKNgc6IS6Y{LU;`n>n4r^F^wO83K&Jwo7eGd z<%?+A+A0U9kcnE~-+FEzLNkysHXzYEhR;aJVHS2>rswgKwl+1i?@XZE`EalNK0r+M z9U3E(LUs%-ft{JLL<{=f3N@e=AEw)r0H%3Wa`;b>FQEUPe0Wcd`jl&o*YT7?wzpaj zLGd-yI79vsI0JxHE3?V849@5}h{N{z-R~$w24Mt2sQ%=01s@4GbqR7V3flFQG#OZJ zh5*ACDW|s+9%TOriomFp;!vn^fiQQM)GnSEsW;u`&TWCOmZ|vdmtOEc0ie%|hxsat zZhnw36Dt8oILsZkQBa2+xp&)gGtdgpv)oclbg+=^%~Q}yF!lb-OY5GB13xmf-C_Lo zWf0{XJ7T1pYuPeQ00Ls`>XHQ4Mv*u|RlO_xc6IE0_31{o^`hH;Nc565*k(`tH>*u` zU6AU_ga@gH8Kw9@3?UN~Re#@YaFiaSdGcne@9%?z3WJ1NwiyC1ypN`mNeMqab_Onq z&AAJwPF;p5><k}YhaEaG3|4h5Eaa(#1Qrn)Z3Qg3Y)mz?8mb7@77>TxjD^IppX1=8 z4D%=1nH+vXG_m}pdObBD=Weu`dX$^w89EAZlr|&shesyuL>5=7iLfnmAsXnjzkwA| zG7?GHy>U+*_RvA&N*B>9GKb>*ua9l~a6>oMK;E#7$Kj(GY&)^Xom~#;%?}4Sj$XL) z9Icj8*MU9YIxxSr{;iSfsAn8#Q>rfNm-y2D4Zbk^^rc3M#;jCjRq)vy`PW_bp7Df_ z(a1wBtn0jDs&D`9{W9Wfcf0Ku<q~AA&qk^om_Xq}r_Mec1s}ucSL}gwBE~J#YDqTm z;`sp2sM{A0<79~q<%%;-TWWo?%6I_<;}X3Er(s}}@FMRON)AzRalgh!`PsQ`LHTsh z2WfasDlJ!5?N1djhW6W}RrEUb4+~vUd3pKLY1S|3m6LPg<$IL1MCY(mBQLAhYiB<! z9nVXhxfsFS0Di@lE;krJgNS+*eE49qW~K9+3dNS}wNt}qeT(+*N+EAJs#O(R{t^p3 z{P!U4G!heShtTx{t@CvfI;8};;{X^38I8&xZ}h$q82!8G{9`?eG*Ajs-(hT0Fyw+x z`m+NUT4A!fN4RyUN>JLGJI{Ho=X)ksTcl%0W}98%oEpG#+jp-v%)%{{Oc-fOXW2AB zgx9x%G|JEPSUhUBzlRR8D8VPcE0sV|y)7z%6O?zN8119izOXQE8!0h=IvE|-|1m(% zfu*Wso`y8H?~pE-epVTrX<pOsbc}SO?yU;^cEMYU@H;B|s@p{5BlpSz7|A-nmSMkn zQd8zH7f;Eso3znEbi4dJ0kT0^LKqO{XF9%P9#knek^r-LF!1I3M7neU^9)(N!=s)t zIQevUA+-hw=8NMTrUJJN+L;;jiU!N?<g1{?Qvo(XEqnGRtK?{K#m(Gc9$(Z6XzL+d znS#^QfjIEAenIXe6-gfagWASK34wi3P=kN2%f6}-98m(k1E)7!!{2IPA5iTUAp_1i zcmbTabF03|qtt^P8>{$wCl+O1jN7?J_u>vm@*6lrnRl;mpGO)6St;Ybj2A$*q*1zA zTQa59AHt#o;mOuN@`kSFW#1A)_|Vch+;z9GIK#!&LZY`VIA8fMj>!(p5+O<*Sy4-I zel7P?{#!zMK}<IBUM|k?wky+9EilztF#_}S)jwf1k^GumRzvby#JC!W7s=~^h3apA z!gKvHrr-wLET*?N886YfUId7kHLrbwMUPXiT4I~I`1NVlBX~)`r;Me4<d7NGl7#Et z)TWrY5moHKGh4A)#brJ~Wwaw2|1lWbJ*+tdc<k0dzU5t=E<xpw#g5B5FinrmsO19v zjYR)2K1Y?PsHiOF=eW4Y1yf`{>pR#GUoF{NT^%tJfLHsTg#kj9jCx~PPiEIyO=F)X zW=q8aBlR`cHsu80v{PB9w~A0ta4m5RpcS)J%inLZxzv5rv5IOjfav$$OdO!5w$pNZ z3e@#JkaCYb{w$a=Yd(m#s>IN?)*nB9)JF;JRnGG*nMrZ9K?%5bgp3-6N~C0D-{?1^ zbOV+K)+P-6J!86u|4U`9?k1!9%+_iBb!PqwU;UiUR69n>1L@HqD%@jS7g1KL4<)bG zcw;cXFVF_0GKvRa9+!Td-A+>~64)w<{ps6ZjPw~Hl!rSBAXd|UL~SZtIr+3@_x=<9 zus>K-MdiiZM-;%35W+67wN+Wjid#L}4AM#7ur}_26DFs7Hom-}C1;#^VYps$bj_~G zLAGcpT*bY9Kb|V`GJD_3A^eV(Jv=k6^U9vB%fgKLW|FULG`bm9;A)%O%qhe!XauHz zOB-@q=pern^HSt`8r-S=y+U0vwv)fi*H-LAHy|;ip3&&Olem>aZ$*rt2kFqh1`+S) zQbsDfSt+ijAn5L%f@{Po1jQ{GSC8?w3yl`v{90f>-u^A?pV*U_w+J#>Z4`e8hzCGV za4t(89^8_{?Hcv>`3Qmbek{K%3?R>q60ejfg38i9M#;fy?=%{K6!!?--<Xv*r|~Wp zfciIk*Okyq@OHd|X;PXmr77f17iC`B5^rEy2<8BxaOps)sFaj<e&NExf>z+5b@HFk zJiF+IL}IIx8ZMiW4v`1h@F+bw4rc%vXL8q6B9BbFZsDJ9ehjoce|wJ9Xcjun2*v=2 zUjR(`YSxc5<^?X2TQe&y46#7G?=qkhp&n!L8K?Vh@w%qXj|J@J=1Dj-_sq^BwzlYE ziXsgJ9!Tmo@Eu@M(Y?PS{Q2qTC7{}eIZ8$=_NmMR()|j3jJ10{?8!azm+ZN?z{XbW zn0zk6HoD;uhqW7|Biu$hV3>EoSf1`yz&Pf(9P4yzcXs*+=bM-g$FEHczE4QLpd)WJ z693)g0J5+P9&=NmKX98e0cl4+J@y<2Dnf3kpa?9qYhiu*kJ}O6k~y(KxQ*6G7|PY> z)y{8*>ssUU>%PHrMEW<ue4NV2)>lru2JyNGd=l3!HiU|F`JG+Z<c7cze27A-Qfw&K z==U*n{e6ZVm@zO7xpF^`A(1_XK86dY(=4gV1{Sjw#lTtFyxaNxFNnfy-@f{2kLg@B zy*_5rAjLGY-VuCi|Hm=_jQ!uIfGh%Dxa!}T*ki~r2}JFMr)vQ+l8o}^|1AqU-JN_( zvh3xV3<tgL)~7r14wH*Q#s+TX@3#4^(#Gjc4Mg~0tNvrJC&fYZVV5aF=>5Jy0;Lb& z+51`4P|EfS+)zOgo&S>+UFD}m5cuzHZ_SCVSpfPsH-UbeNBWb#wo;o6Nbs*K;off) zm|YO``mpN97>&C<I71GB9Qele4)nNm!w$TSHL$8X{wh~Iz7EVekk85pD##GkRLYHL zO`|9q1_T~|oi<4G2Q#CE#K5}Es_r5g$E4v^&slu$l_}4*_N<30-=mu2uX(!vO8#H2 z4OF~cYMK6aCy3#4U7-4kb}g}7`yHf@y!}6dboRf4^mn+^?tWsnvS7w}Zy}xTXN-8z zlS1B|;ek*}Cb@|L96ed@{1=!00?}dNr-i9wiMKw+j94{SGLbXbj*3LvA&1vyTq$oI zQvw4IZ%|ykvHM&wkBrL2d*9bZkGQ%#{oVW3`>(xU;MIL(&$zZF64#-g%%*1+*!Z*; zzjG7c{KwW0pgN|a6yy)^@K;DpiNj`$*=o}=d^$LvK)Fp-u#3i&yV>VSca)H)&c`R@ znNF+roVF7$4bImgy2T4rCZz>(T{IB;uzN_nmG)_jes2|2D}qs^kvISB+cMS^(7U~J z3)Pnka<GMc3yw|SONa)Zx_pKU@!jwPJzDXSzU8)V9?L})_-m}3i`%cbWfBP8)Ipzq z&v79Djq;QL7l~8J^bmS%MB?l^)d6x096tpqQodrJgJMZLTlaS`o;H?+jJ6Pd%S9t< zdUY=G(H9q=WSPBF!!)-ms;ZmnKchL?7G02cs80XDgj`q8V1s$<gUO-SKkjPxX7qht zL8Yee;#<Y}j})tmL1a*qXQM^7K?3!n9BeJ4-jpUPlq<)34>|Si_wR3KABerr_CmY3 z^m?fO%EKub<QTL5;G)+A>VP66esUt;^u5RKBg8>4XW{JX(ySjW9Pap00AX!?u9<d% zdcj+H>oAq;`IdL}C;-=1+JO-h7_IO*ovB^^&yVz*50X`~6L(yTObx%S)5%AWI{97= zM7t(iGnt*kb)AE6N83v2gCQD|VlI^v&M~)5$=Hqo#0Gqag<WzdkeZT#H#pR;RJG+W zLg+wbg1`NBHc*^`eZ}c8{U9CnP*Ki@kRg-oi1GM3?T~2M_*#bT-h!!~#g!}fX|P!F zdn>&rOV;cY2*fr)^&BAWP%dM;`5vFsYRJEZAytaf&SK<Ff>LUjyNsGQS^?@)$ek={ z;@Vjo;kRe@#P#@aR(&^~#XAN?ChzVMDv52H?xEXd{ReudnXzF?L!;MNk&Cr0DT&1D z?+%Sk`=qrOp78d&?i0Zsu7oH#*!>CYwD(<{QE0!x1yJXs{7!`}@_*Wvn$#6jk-_2n zQw?t{{+8514+^n2a1Z%C@7SxqQ}ds2D01W1a?(YjpBR{{8%A4>I9$~gf#D_K?-aW- zqFiNq0uV0LnCJFpp%gby^~as6zX~V~;6k&u2WDu&@8j&pB|q?RC8Bqp60XzCt<TE3 zASx+&gZYx-_v?qwsnPXT2Qjxj#T8OIe^<r3w^hYU`fmy>z!h|>i{N(G=z{poe09~T zks^No$+PMw4NfiznTq`Ps{LN%XLiNOk|JBY6+S3kfqQ@Etq(QGBe=zoj^X%iU)Ete zP0z@WH~Q~jHL*`mkIt-}np#-0Mv=;s!_29a4^aHzvLCPcdh2F0k)zj3PG2~qV7+mA z;B`W1l{#Hj;z?hU<lm{x0}t5D?c<&<n2M6Z?Gy^QwkbHzI}l}}j^{_WTfYrx*pXLN zu&c?%g&la`5_Vx0@ZTOV2p4!>u~-+*jXeV)x2z%b1_=^H$|uSvT%$laCs!?ke4Fue zkg}DJM;RAMin3kYXS%PVJcHnuHriYGRUaFJEc)xJ7aA}7&Ip!2RzAG<G8HMx2K-7* zr^VeHO(4lVqOWMQ8alNuLLB$CYmaWDAl0@)x$8Al#OeO$0515V5>$TZGwlG=K|{`q zz|yHGN>?1oPC_XvLjPN0rR&b!G;f<$GtHYqoxI`<U{iLOn_Q%W`_-2)k6@~^)5$Mm z=dyTOJl8{QqBb(T2JnknKPzNh#~ls!4Peh5;o0i&t41MPTc9l3clU?8Tca6(`2INV z0t^`(xqWVQNi610Fk~n<mqR(nINW-NJ#v5W2z7LI#h#tuZS<+ut9`zZ&x%*`{`qyp znQV^vy*Z^!#J_rGoNFrvoE*>OO`rd%@z1;nv_2pNd0(HHrDfKsUE8Vvi{MHeGe1d- zJL6*>IIvF+HW|0_2{iBwWCEii&z#@%1~*A;j~s6~zdR%c8z_k0Y^al^@emwC$G*gd zJNDvqzj(aVy$3d~l6?S{IYNCs<Cah*G-9R_jh=D*e*Nm$yO<^PNzHygs5M_sUEN>p z;TNwX7^yS3Y}j0($-*E=<pl(J|F|v%X8<t3+0Aw)WB^L>;XftPMHvxt=(js&h*}l{ zTcy5&M{o*9PC^C(se^$O!;OB^htFNJx6cQF-2mNfLty=DA6K&5Yp`OlvZvDTc1zY> zG;E&JaVbksNQhn%uEP$zs|5D5LuVS|rGrANf`WK|Fc23V_8Ugv#FHYrtj|iJNjWeY zD^-zx*r6I6j}X0|$p>9oKnjR<a^>K(4WSB{*e`ApTO2=ts&V%(xyNoNs!Iw8)_415 z`V)|5L*>JA;&fblh)7TQX}gW~5b*|?ss(V^T*(Nc?WX&D!^4@FRI;82Ff599<`-WM z2D8YsXDa}o8)XQr9L?z%$^c9W*ijm`IoBI*QeCN^KKJxTi}c1u@b;LrYZA6U%_I94 zJ^njG2<%qcN-+JQFi^e*2wPL=kPLvh8dRGqr_6%GI@Wbe4fbnZgYLiH=x2QOGF8W1 z{Qz)K`R>7PVxpdbC!ck|0@C9eTL5zM?FBTYiZ$%Y2u!Sd@)2&vuT)vTORf$tvi&2S z)|7XhDWbY+KReMBz>aT-O7U|hcstN3<UnRvd*5cD7#Bp8<O}lMPakaGe!?BDB<Mo0 za^xTvY@=Tof4NcL)lV^APfVpxVq2Ew{uy)cOH25q(fx{h5SA#6-&v!+q2bJ#Gar?a z4}b=10s0N8u<ItQjxY_TF)rIDN86YZ)aZaq#lbkz*D$5yIL|$$C4LyLft_dn)}qXa zd4<GP-)szrr+$eHIq$&`Tni=~i5d*QXw2BY;Vnl1_cGh2uuvg9mt|uPG<t1jB*<Uz zI~Q9HHHuzh0t=-Zsd?!RE&R3ko`Vbu68@bQgC8DUYj!JVRE`dKLT!30wms$$6J|c! zn4xohA$n%CMM!w&jDONcFTOc)R21~{i~jYgynNU@`5w$Wx$`Euy+|;;00Q%|c`a0% z+TmJ(kb)u0?-MsED{vCD!x9G@inq3e8LGl)$w84&$bQ5MBn$-sbrG<Vh>qaWz=Ye# z_vMtbj~^@Zt%mO%yECda2l6}IJai2pD(Ug?hZdvU=*!_GVvU#9t>rqMt~;l0^~c|q zC@I;+f9gDy)=hZkp$;`M#79O{?0g?8es}ZvR4^f*Y}--bP(CQt!Z!c##wiyUUc{f= zx{W4IMn{p7#Iv8nxfQu=#*#gQzq%5?sY~0-<_AXWHi`=j3}8CHL5Y&l1jg#5xW7s9 zvW7k1Y>XEL2h{>m2p-;E<i<_($)Z^IuTvrF062g5CY6v#0`ZXNL;8y10|E&h!s#Jh z=)61_;T~~M%-m+&$Go?yG7!cZ!cyeRNg=$DzF2y&OBa$}>CjY5W?{s<MHZ^LN$<?* zR!1;@yN^aL<#b_ncKt;OmxpkCC0h&nEvz5F0#4v=#_uoGfLIcBGu~GX@}i0o_hz9f z$2gP=?!L(y?T`z2;_2z<ywZJgs+@m~m5wudCxvb#Kb_hxz$f<NNaOjNG-lG4zRqKd z!uh-rbbjvp{&BjZD^U6#-jA^`&mXx7N+|XI@KR9yCON>r9pA2>A=PpPK2vbuQ#vEO zEW#{P=KM%>C3|?MY9w#Ud}%mQ;ZNuHqRVW}2}q}`;(cI)7AF+CmZ`N$z?bEZ`VS7< zE+pvbwAQNE_h!sZEls?7Ctb1c?-Ok28j@Ma%kut_UG$ycYjAQ1+m8f7BRAUm7}d?L z%4r(KLL3@)F0IZ{l{`r{_DM{9ym%<P5r*^vSNhGl#hq7fgAM<Vaz1%)U%;0+&u_b! zzr<K5E>1;iR?8W+R%9Ju-n}WnzuRMt9>4sP1hZNLe9EIX_YKq(H2@Vwdq#;Ew)DX& zKB^h0laYQS>SwI=&CkeKlB|{3e(~V&cu2_wd!s%$fiJ*>`?Q5@uHSZI#bVPw-@E!r zBJ?LC7b~j_-1Xj9?kCJO8m7udTuGvv(>^}u11W}G>e#*(2lRzmK~-MsLtt9ZJFaX` zcH7+g!eNW4k1!Qda9F{Y(>}&sgMj%NH0^2}X^VDvw@c#`Ah+RSc4}4OE+)jgWl<F3 z%A4nV2`c*M(|@6J9C9W%8s_In(k;7sz~u_sW76GG<PfWpt^bgDcy7tv%AjZ1?hW*p z5Z@Ecu{(V?irk>7N}P<g%JnKgXV8sp^-})^>D0WwV|t+lSTU{Bw6wxTRXFfGjZHhI zSQi&;>||P5nCv!Rn7AqPUOMO;x!v+^E~ajf!1wq=-;%IZ<FD}QZ2X#@9<x(#zwz;j z=#Sx4Kh?7e6D`k#yFqsx(W|a`b>KP%n-U@I3k_3IXGo?hEJUY%C~8)AGpRypv)ooa zhAoGbUB+oGf0ZH4@vdO$6I5hYFsW%M5{%|w2b|uR>L)iKiwiw`V(_g{r7fHXKA0^U z0ggx8y?`B<UBFS+Bf*2n;bBG})gk%GZt!k#91K?ZWYhxST%G#lA8d~A3d~2!(k{0@ zhJ3=kDoqZ}tUEq1g6c|BnkF-3z4zT?`)@UVANk|1e%D%vn@C@~kaEaeIaT#RaUw=i zc7NrMl~|ZyBHvfox3=?<!56{mu%V}mJMp&1C0aXy^X%Vs#5Q87(oZ0GhJ}m%TMjr* z1`Z&&PE?NjN6^C`H}VP-*LxnjZ{-zK1LV$(Kq$`8A+&q)*Nv0a<*;a?Up1%lnTU5T zyMet_mmry(t5knoWDpD}5e2X9IIn${00lErD@>Tt7wkU%=fY#HKOa-cZ@?15i7t1s zUbuzt@A8<G%goVsPej)E4^_U^mA!Wxa(!w-IXbK!A5*F1|5}#q+90WR(bgEdIiDpz z$arHqi(@sei;@MYBsoJe&&^QLbqA;`e8Tdr(&L6wE!BcY?%H{t7py^-5K0DheYIrf zT{V&2MDVZeZ(@1hydndMFS?<&-ZE%O>FHb#Twk+p8m<vL^!le<-D^jvaK@gk&$S$s z9c)gEytlqOU;7po-ChH<Lo6&Mmi=L-e|fMzHrxoox*hh?;boupX6b@GvO1t5Ga)>| zP&wvX2l_ZJAI$x<*AWgnFkET)lgyO2x6F$C;REcml3?l|6nuUP`^&5E)B821K9s&N z$=;Fuw4YE3GCv;QY=V~%MGfG>X7m-y;&Q;C6xG0YdC$F7#NJTlk70ul)+diS8I9t= z<q#d;b`xP;r_^DjB+AseL+&?~L%)&kDBrzY3xTcd#J$4lV>ma;1Ov6UsFjXzG=+uB zN^JC)V!U_ZAILri`5RQnKTu1Rw$o!%J>~CXt4`a@pHL2YBlUv+AeKHn@_-HYMXoor zOak(uRdO>=A*Nr}Pk_r)d>^G0F9P{1MY!lfvP~0Inv4NGdZy2Hcg(!Y+6nOqtZCHD z4Fta8trgk%moww?pP{Lt)d-%vkb7Y(e~|>PEi5uQcozmKKa;tD5)EV9@)!SX%U`tZ z@6s=YYXWmKwD9-XashV|z8R-cJCv*k`R9#sajp%grAi7#9Ok2py|()tYK!@g%JsWI z=|zcp7$%nUj;xu_;*ee*u^*iyV1{U_q@}07yZDiAX3I7mk>|i#BKk|0ke=QH_K&{w zK-*r3FjpaWo+E1?7aJ?8ub;^E`sRm6nWjIl&}$YKI{SU00Gn-kdTZWFi|nN(W?x>t zK!}U-1}kF)(3Ln_o_p=!gjJPCi2<$Yue2kpDF7KS)8`iBMd}VYU*EMO6E=}eNqgwx z!{{#itcd(9eVkM30jlMwrmf*x*velS8E_&08?>yf;M-QdBc4h1?KN}r%q5<4=cE+U zG?)NWI?soff}VX6lltmy{|RY-(W|?bSzn|U!&w$cquLEIDo{0+CA&$+BsP<g5BEH2 zoMjd%;3iZm`Ro|GIdF7@y6YI7SqdjV&##sU=l7yNUy82fuCOkqE#gKa{4s1=Velc{ zh9RhW3Y!kQ%7UJs97RPSnB8P(wbcsn&;N)tScfY~WI~WcG+<Q)dqa|n&cDWPz@u?v zNd&0cK!)BI?QGjZ<J~8xyI18gd~cM?@_FodQM`s2CFd1B^;t7lGMTAmQufNAE>unY zb6#AL=9O9BIYg$7@)f2~7%&{ip+uw*fx%kz)%d`08QT-rke5&5<}y_Pb4B#cVTZFv zid9K+*sLz9mm<VN(yqD`YLXFptea%=l+;UaEhH2S6}TQsR|F3sa_5@g;w~?Nnlvks zr3PTVt5`QH6`S!JA%NUPwT!)x=QD#GF!x{M7ARvV3dqKQf>KeG&{EB*ou*Pj7n%~E z?fm&zk!L4{BsTLOTs2h((XK2d8LIDcQs4_us$Z6LB|JjOQTh3Ez`($OKwzJR*B{R- z+axJiK2m!CM;0w&xN1$`MG`ml`WU7|igWVz)$e6NB!8ulTwK<G`ZJeq3&Xhu5c(=b z_Sh0+kz8gR4nuV>rR_KVe~RZZg0>4_U7wIMh-qj<SW4buhVX3YLQ+vY^k<K+=9tgA zMwnmuURE`}M}Jxos9ADr28XA6jE}Tz`rhO%<$Ir;u+N_igMBx29&!VlDh=K333OA| zb-mERX8=$a6%?Zlqe9khb|}S1gq4_H-V9<(-tpNpxCX+slY}CFlM!h#u_@N~CA!i5 zojE3v5)nMgagw35u-w)ck{sgl^8U`AF*rQCi$I!2k<QZ0;3ly6_Kx!`G3nsMy{9gG z`$XVnJnZtzsN#0v+F%;B1y0V~P`2as$Gk0+;*m2X6-Y$9T8R6$@?aZpQ3$TizfLS& za9580cp4^R@F28SOl<7prSBppxP)w)e{-RoMP+Sm;2|cJimHH>Sd){gQh;3=ph>r# zyd^3jA+Oh3d@H2QX*h-Jvtj35&_6cgqu1@I;=@+JJLCRx{WN9+$`XYeVIkm#z~1S^ zH#s+N2uZpC{4VmSLpLT%Y~37z>%jT@zqDD<mDm8o@A-$;RQAh<=A=1ZhwAu9=To4L z{GahHRVdn&v}_b%WetI-Jzeh}Ji<3$c^?BO{VuizKFIFd9E6lIbSVl7x5BU4^kN7X z9IA-oLj|j9GrX?>LWGo_`yCgK;Vba3U(XIXZq-5R3063J-O@#4#%YI<UjHo>3@AvQ z8k41fxCZGrN}I=}9?rpOQg!}WH6h!wTZ@-mgF1wFU-632q)+)9g24O@4P<~RGNv2) z%Z=;jjL+#9xzMI1N#lkPAgg7!k^Ec!_%PFakEb0+{1Xw5i<XuP=gA5Nqj0K~Byel` z*JYvw3(#hMFJB+sXk&rT#z_i3=t~+pK8P}RU@ikIh@PZ%X<@Jgy!VP){6iT&=Ud7Z zeBOZU^cXzuv))L0oTs4#WM3c#%4SgOQ`=}2U{yUfpnL%mEEhu<NC~nc%-;{v`s6w! z)3<Fw3Q19W0P~H-m4fLny2=F(9$Yq{1aK2o&|$Wv4RFU3=t8FAlp$#@^LAv^g7e%M ze#fJw_3j1t5+;78tb{CmnYWq#zkIL7+>!CPQgJMRPW<kHSJX>qs?N#KCm52aGWj0# z@jc`-LO<m>)VzN0lgX#B-VTSrapk_SW}XvV=Q~3dYv-3&{%LopwX1`=odhUO)>qdk zfkpzBAa+p}d+iQE0|8^+A%&9cgyi;#r#iQ9S3>2`oR{4<Tw}jmS;4B0k~t%WPzNC? z-e^m8l_g`dW8(xk-h{Cfi0XS&rih_Le$SGH6_OO!0WgPx{hzjiwdeVmpEa-<kjAR~ zS>X0)L_inLQt4$D7X&-%Ucg!QdGCb~j<sCUL2k^!+{Nmb8xdKIkmn&EMbckhw!7I2 zHJl0Aa9dl^0IjPxbsm;_91uP$YUWy~%X!n<@8C&+7eN<5zllcozsCsyD?Gsi@0r|| zVBaP%4@H7q^$!K{cENT<h+*H$4<r>~FK{oM|HyGt4EF2Iroy7UWR3NJFxy`qndZG> zoZVjMqmnAD0-JZ9nlvu)d~yTcm<mCZNkk<88g%Pdx6Xbdo{Q%G`;ITlRvbECAbRc4 zo&zKpY#ToAKpNl({Q4*p{dq%1p_(RO{04MFrTDYe%^z)8Q-KvQcV(Ty3`l%9L3}Gk zX`h&5ure<fr7G8KA6_u-{L012z#!iDITTB<_mEd==6X2!c<H0&;b%lae()Nj@BzV; zw=h^;-UOy>f|2F+b}`*cW(MirE~wGMdH-A7wJt<C4~lL<hAkSIyIzMAv3s=nod13A zaeTE!#B@IkgHLy0exeIiN1q%G<%*97r(X7dl6)@WPMkCM4WPzxQsHN@;g+%$+8^j= z?5SuvM)#LL*9Jma;Ev?5ym#T=U`H|o5~A12Qo-#s7t5b0#KImrzs4iGRdBP(NKpT0 zMIpx)__pvgiGCoMsg9%kDu2y99z>B~QF&0uDHj2K6y0+00Utix(-~kn%6BvBMy0Y| z_!$Ui{GbLabmMN}P6~}Q{<HE@S9Z91f!e!e{Th-_voUWQ52ugY8PQ)(YCOrT60GKG zyBp{BkuxZGiDPHyJFWOro{!9$D9>I>ZaIIh`IRh=CXG<Q@U_>z;<-tx(l8f?K(hC= zeQF6fWa)3^`4}Z+lkbNi$fzJ{PP8w0d7dZ?-$zi5Wg#{wcKxwWt)1lmBke82qFlqS zVFeKbL_tN6lu}Xzqy$8910tZH(x7xRbPtXwA&N+&Lx>>K-7P99-JQ}Y<xt;w59;2} zbG+~S=lipdy|;=p*L`1StaGh(zU4=%Bbo1S1tPOh4@>Bd_&RP?@s6K6bh1Vh-fP3^ z!QB-xof5&>+ZKr&!%-8@dgPTHvBqkq@MvUTS;qiJABi?d;%V^v@cW5YXb>!@LEYkH zHfPNBJ2>JaWE?^dU8U1;0SGw}j`7RzCY+z=ufeD0(>o2>S<?xr3eOGdLqmYoC<8U- zEhC9b4^zUkdD>qbz6z_|Ou;wZG&sksi@W{ty|AyMC&?Fa9~OkzE<CyZ4}2hA(T0fA zLcdJ<9D07vrmu7jdAz$7ceUxLX3yLS6Z@a?o%BrtQHRf;5lWJIe98IqQJa3=>T{`r zTI@`yKyD^k2_%*@Aoo&jOx|k$yJQfp&-JntyL+6V715`RpP$teqYL(9zaO9h)>;-@ zGSw$9Gv57lmr;0dV^HVl5Is^R{dok)`X1)N&+W()80QRt6~Ijrd)v|2V!CLta@cz$ zIv8#8Ks#M}aZ{6-&~#@uy<ESh+j?a*Sy{hnP)Bcu7ZVh|DFl`H6=W%HkEG%xY`T<x zr~l3Sr$J@bM3&9G`mZK>kMOS_uEJ9E^B5%-xw?rE?l)#xrZwN!(%)?VT8Wn*(w+7Z zMcHV-mex&Vzcjg<vuF0prb%hGmo$0(&h7IB7m??4eH88q^B|UEpN<qjf++>>a9hI? zCO=BffF_BZ`{<rhQL695Zvh-Qh#9R83-IGmc|)CRCg=I>)p)_^SFvW(xBn6`h6Ui= z(LT@H3!Z?}%)=+Jn(qJ1+ReNj->S|(v~G;pLuTrJt<YuaYe4BfYe^5>!+9-z7q&H6 z7-h*a?=Z?T=(}3JGhz-`UfLJ#@c|4IL~DQ5a8<eLirNITuG*!e6ch7g;{1|QkXQm9 z6R`M;J`}lHtW}g-2J?f90gp>J7Slvgt>YmkyP~A#U$_3fPh2c0-A5Ilkd5X`2&LpT z$?5O=RXxLPjD^G==ZEOM{1OpM&0ql(VB`8l*RzY&W&2zg-UKE@y`4V2`lnd|AUp>C zyl41*#4=OrB79G~a<u9*qe*nZ4<0+=nNJ^VBreyLI(H}zGvDsMFK)32X2@5E><0FJ zjXg^H-kx%A{)eM_HH6xb7m>(gfSG*|Ltyx^xr*9`79QDG>>+wd9A^|3w)!tqT}8+0 zD9?1I^B`Uc0Jh7@4sjlaIK0}|1S&=Sv<ifB8)S7gPSIWQMx>xs6w+c;3jNGco=99E zlc@s3YJ-S8$ck<MV0V${JdF&|#J;`Rw_#y8dHc~ycjn3}#m;zhB~x^j7W&tOQlFri z<nv=^;y~xG6esiMZh{g(;#3!xysbKaLV;NGR=`Xj1AiynS>a>w8w2Uww{HKuI=$Ae zoZy*)zw`KiFl$0E`dnMc0B_qc+*Ip}x;l@&g1SlNJC=s_c2!=eB$+;t9{v){z6Qte z5xL8Pt#S|1?4*5p+3c$>!vKm$w&rzJWjRgUPL`0Sch9j~9MtN~x8h-ocFPjxH-+e$ zb5^wg_5Ru(kfeXSvl7{vYfJRJ*1ce9BpUQ^lve1Tl@<U@2G|E4dj?(<V=4EM_tgoZ zBCvV+?wbrToXo7K+HefY|EOT!INP2WWH;B{;!^Wcx#k#r@BqIj;^u~5d`@-JZ)Kc+ zcQs`9rg!(dlKnda2MV<`vJw5$v=B1D^?^a7Y{N5Yb_SHqmkT{+u%%p#Koj1b5@hJp zKNT-GJf1M$7cV=>y)yC5iVJJ_{cUXk<IN*)!;2q$I*NHo5zedU)$cguzEVXdq3XWa zoArFPcyI8fEd(g*n+o0#pfEYmUIw16l40AAI!hE&y+yCwgk19;eB`4dqZL7z38RiA z=aHAIfIy^gd1qsY2aJ#M6!3<l^rEc&ZNmTQUNHf1&u(PhMUI9Und3_W&+{;^UJB5> zUOvGBB1(mX?f#{No5SPL9=mT`Qq}8UbeM65!(&i_)=KY$?_0>bdPEL$-Hh_?ib9$h zk1z&Ho26P4WyR`-!Ni!Lm(-Rbh*xMF82<+4P~8^6llh-KVHu9<iL;;WykbbAb8NB` z!YCgBs4(nz<sW~f;QQFV|J&dX>Sw_pyhG=XgO5{-kRwn?{q*H!COZLJAt8Fb$H-=B zxU!$@O3p^B98U;1<(yCYUjFtKH~^+;6=OeVH;KPXm=~o^VZJ@QG2{`(Q?~iJ5bGtt zT{upD>2Ayu<sZ3cV1)2b1Fg`nwV#ULA7Crq7Oi>Q{#L^Ky=b%oLx{{CZVz`9o`x?` z4BmF$ah3x`jcq4}sMccJi{@JG7W3LbJ$QnM1D_q~Af=4HuZ&H^|JRXm#>>ugs?$T0 zk7qA_W_5m)3D8t5Im%lBw@GK*Q6fM4X=a4^KWXF$7KPuMT??6Cw;5cuBpc2pUqA)& z#h??@Q6ry)=^r`0MpKm=x5RpxiD_#2o#oPRjgwUvfG-@HKZNe<F(krB9Wj0abD!Jj zFqg&BjX1!@&<5JQ@B=M#sPin?s6`U*#b-6p>;x9Rpt#>gEGH4j8d<EWV%C)w`I1_I zT~g)86}SMh1QNTO9}v?IhlT!2XLvZ7{65}k3}2uSf;}=HKOk?JI+Oyk$s=)m_%BPv znK3^Z9ltxFQo}ezSZCV)Y2+Ho1y9*25rQLMWMkl!?=0s<;)Za2sBEpWqHkNsCq#_1 zpF<fUAuYxIoN5(>{Dy4&JuD5~-=D9~0PfWm-JaL^k*4BaJ=V5_PROLWDAg@zhEMos z1D^rZV6pUvGm!wad@>v`+8oo4x+Gko_g0OTyyc5(1En+t0=7$n%=~zE2m=ZH4UZYD zk02TG00G@erz}T$XZwDk<oIZ}72mbXN67f!v4YT$m`HqQRe5qK+|V&M(3_ZK=@E}H z-jfjt0Z*<YJ|WDmhYDcpBJ!qEczyuWEC$1u4^9cyQUz4VHeQ{RWI(vZEuRb;g{!qS zduCD^En~B>P9|yvqZB6XX`UV9Z<wTSZ>`Ulw!8I0@kw_&Bic@NVf&~4^sKU2w`a{e zn#GD*82Q8l2=Ydd^CjQvzxhoXsTW^n3+-FLAv68Bs*A0}`0DWvW%pJ+kImOx23%eW zks`Inc}fDNnURb(%Gq3KYedDX`^-M%b(tnx^%)+zNe(4s9DomPPp%`L7_#}N;w2!2 zv)~_w-@gyzQ7j>w2kbLE&8;akdH8Ea0(4PVOj?-}yuj9{9+m*in`b}0egQrV^NpT& zU8-3t$}Ln1cFVfM<AZ3$x=q1^`dYSV&b~a0pFbFyO(8W0S0tyGv4eX;e((0~Giw{Q zug9WHJ@{X-pvYfQPvSomGw?@cv!tKQ?sMW!7FV<{Q;hp+m!`ZZ+Z;W9NhM8lE<_0d z!~^^)U|^5+Fr#yxxl~yCpkCA8kn-<WJ3vqg@6c2Ei-^|@If8n|K=17temF_weVxI| zq>e{z#^b6uxD1C)uPHr0tiHRrx7);i4quBpZXW+C?eAm3HMnNgUvQ7#DX?n=>O3K< z?ZVd`Y%G))?^bA?wkef)bHS!jc=B1lQ7pKmAH6m6yFQ<GE%TD+w~MV$kETbjDOuIG zn=wc%b~A$CkzJI?kNEYrhj18CPj=_jz-JTjW?nTPQgE@qvlkHp751Wd{8#)Fx^PIL z;P~$>PzK!kRQ<}W#rlab9d3H})i)cWQe;rBP!OnST0iI1$h%|OmCVL-=iH+2)wVwr zU`QwJ(4Pc~=t;^!2>*$1N^OzwPkR4B-fk`wWe(0umBa?kF_OqR+$w>VG;L2t(MG3@ zXJ-O<v{Nxq-}0pZImp-RIE3WG@kO8Dr$~JbU1uva5=26bK$UNp$j(kEm(8;Mt5jA+ zaPY7!`(?-@5S<4%%bSRr-<Sb`Y?HauS=)5nDyzhfrcVP#Y&&`p{{puo<+=Kpq}l#g z_4y~prEq1Xeqo@s*wJcwsN9490qO)i*pr#pqs86zE1n!w+TI*9nC|7dARhf^egaSV z3i9e0zLqGJK7biV_%~C?CH;s=vYhKy`@y5Zjf>A!%QmF?v@COG`2;``yG&xW?%?pg zAU<~snHHevpOK@QEU(zE%Ei8?;Nha@+>v=}x1cMaX7rUERIg!g6*U0YsUjc~TMZzg zyQX?Og!9tukA_v0;%74vOwbZm2*yru&bi11?R09U-j8}0&U9y+g|%PQsT8r8X-~B2 zv&g@tPE?J&;rEV~toNF==9nnY_Os}uydh`9o_rvN{a1q-fVhTTvF)D*?~OQUZYey+ z;9W+()!`DM+lODd$i6ts#lE$%80PkCh3eB9>i1VeF+zFtYYiCKI(s;k_U!n}Rk8(4 z(*t9=rP80L3wQfcJtkMRUm7x^$fMpiZZ5ai+>3fQ%~Uc-L~lR$)tiu28#^H7`g2Bf zQMS75wK}aRP`^*J-@jN86pY+c>yzhTe%9~0SgMq9{a{b-%9xNQV{Q`je;(v#$Zh0N z6w>=>O+XUCklR`af0}zpM+xk*lYxdoIX5u}xc;qo9>M%j3C8BhDtu=f!hY5T%VyKH z((WG~yc8HGc$&Tm-1f+c6+(MnJHQrO3Od2j7h9F|FjiSp&&x~Wb6(Lm=}d{pH2a2c zBCDQXrV?r?rx$5!C|)e%fC?#ev23f+<R74Q#Y3@;c=i|0Bqhh)3Af_@=e&>_OsCBU ziaH9*O2K=Ri6cheinz>_J}Wyr747zGA}q_G{_G{CI3Eays*U1X=AhhvyT+WMtSBb1 z)E>}hngKp|Mnk@AQ5WrJ+B5Syc7qhf-{cRv$bl@H1$Y^OrLG&d!Dwkbr%fS<BfUfk zxg<zZi~K2{nxdBd5C7C-p2;ZJG^|bCrOqE#<vXktYzo1^P^|CL@!)zVXcgL~C^6t- zt6F`Jv@V3hD4M#(?ApScio>6h{mTcvvyGbaddtB^XEx(!lY|abi5CEO2(ITYz5_M# z87G&Td1FF0B-tAjKCU|at8U|9^lnSuCq2m3oYj8ZMKY$HDJBC(j68G+pZB)P_p)yY zRnbi|rCOF<`k34;N#Q=<^FDHQrdj+Wt^}2J*zB;sTdiplrIBEZ*K3cTT!r}%Q==uy zx1k=@ew6SEA~Y)jPw8r4j+Mve-kEaruF2a~_DRbxq9|mBH#<7As~Kb~=eaS}WI2mg zXY83B%5u00d2W;8Ha-%xA}-SECpaSUbdwqejD1<t0n5UVWgTN794hM3P5O5?ra@}Q zd~X;ICRg0AjTQW){Darr>Aw9fEb&D$1e=giA$XrE5QkXLkGSXW=qb4ZcvxTMnx=Mr z$gk{8WT(c=<X;WRJzw@FC53ZV?ng`esTr&j@r_X}k5A&y+4;^0wKP8yPgEzQ9^rf~ zwjRDZ*VA^)X57Jz9}@&ZXBkLyo=K&<xLJgv$rwGFKDJ!PkuC!qSp8~$TFJ@7XZbDr zRlQEonm)fvuu+&#?=r<mb<HV5Iqva0AWGH>4!JQ|^yXwf6>e;#c?dRoMrvo4#EAOa zV-J#VsEXmHKE&#+d_K-20|SqgyHb{2t!R_tV`n+T`yQjWM(tl0@WfW0EF}|II^Aef z&z0{ZZcvKs1gE1j86FSQL1%t*AFjX@cA71wfHP1Dd`>0M4-{WqNC(aFLX7Xg@SV-k z3{msZjvjft5@amFl@3o3F@iPxiU+p<kbtXL1>vaRchFtRgVVHnO`j@VQ4jyS<eEzk z;y#Ek^kmAQpdWvIkPH4y1JKNLQFGwd{DuF1M}dh|ox9?R4AXZ|z8PPy{6fBXU8ZD~ ztc#(u!Z&KD)YXydioQ%in4N!H535~+-M5$6P#HqD1)j@Avn9*l&KrO#o{^B7_ykRW zhE?eU!$$11I7^Cs>EM9lP~=$Vdjd9C7Z5a?R?J;(dt<%;Zq)d%$!M}%j-;%+V0kie z-IHyETf`Dv_P^U64s{x0a&Q&66L&CBCJgwXy~ld{t*dDRd34GG5~Rt6dJ1h51Z-u6 zDp@wZ=Fs9cBo{lRI5VN2B9hPf9&x$YcfIs+pF`tGXW>WS4Mp|OLx}#B1Pjq!CEJU} z1?CMX^0d>{_y`ym2nTYXnzVQS)x3@f0WJuRk$~C=aRYeCl>56VJ3tTtOeJPz=_oX~ zwz4CAv(PcXwRNdel77s8H(0}^kAI<1JRM2B{gSWIr*M7$B`r9Rd02t}+Iv3tFIg$e z^7GndZodK^NRbO6^`9L~Nj}k$GQuQHc-)+Z`f8#|dKB0-@=ukZj@$hc(wVB^eeK$1 zu!W4dd|YC4m@rWz-!fc!60Q1Zn0e!a?O-yaul&2KvfyuJd+p-jhL5%rGIMK_7o6z! zLOG0|r8_2wT7kyPuQ86#b$t%SO|=pZeTs(N;YcT*mO~0Q$KG~Z$ZznF78_k{5pRN~ zWQv4MTMMck`*CAIf<Z)2>p&7Qf=mVQ$3=sXJ0kbX)F=6noSj^^jl~GG;eU@#w0!tG z^}N1<l;$2J@S*}>g4}LBeAcf_%97A#eAVZeW7<$x7YH}(ISHkdP3`Z)a)+8TR`Lyu zJ`Zc%HsWqM@Xa7hixoT<$meIhNYAG<SA(Uar+-((l~7K#3pk?93YPu~-^SgRT(ho< zws<HbI#W&&9XoxbH-U)oFiC*8JMPeY^4<4ObIf~MXLR1*c&-m=W~D`%z7{Y*I=hs! zP@!>--{Ep5QsB?91`>@NY{MB3*YkhVk*rb=;s3_rM|NjJyR==o#@Cp*8aPm`ALY-R z^yVZ6vp=}aAN)aYXSGeS9&R#~T_Q2P8)EEr`hFUbZ-I1<yHT`z-l4{ev3X#cm-!7z zZZ_~1*8-}aihAJ{cY}5h3W54d30U&>FccvhleB-ZKP}mwhQ3Oy7n#I%hNkO$u2Po1 zY!3`ux0kBOI>q82(+oK9;5LllE(NxU&5B<QU6UbTbB5QRc3Qkx_E9%8ElzHjIka37 z3yps!yrsUkcs4a*1k8#r5RQBSnk}=#P1E0PA5z8yCN|}ssxgO<5+Sy``gc(Le?_(9 z?o`^2vDSR3I^j)a+LguyS2iR_LFCfR`aVotHSffU34%~r-(P6E!ySK+f=hJd8O3(p zJgIxoy>ch|O#_deSTyup^Hta`6i89&nt2w8xv9@liMiPM>+}y5*(YNidQC71zK1VH zIgK8@1iK%a#Yv+yohL#h84q%4WIU2=UM?h30PtG>xe%0EGmcS>f!15|`Ss_mN=8)D z&f~1^zPWJgX&n<+%_USU<16rm<G6TQHDQng^zg^1xO)n$KLm4Yi7cI#{UUb7Y3b2D zqm9^|aG*&;&;3<vF2!o7Ov~=aJD`S$8WaU8e`4#es3jHbXW%nzK+Uu}xGjIBwD}QX zBx0}-qJ#c*%d&X>YD<q<zuzuxYlP!y;WG-Mqin{y`Mi-vg0j^azW(Pi6k7`u;8#hG zz&a^HFm8)#$BSc7KzlvvNU+}{4I(#be)+@N5hsK`A13`eZ@=Y&J68+WF>sqVh6pkM zV#q+^FNX9^)}LnHysy&VeCGS`yHTWlC<z#C19*SBBV?2oh73C+4kEo3u&4rkQANi+ zcgTR>Jaz(Myl{~9tAbq-NW!YpRm;QEvty=6PA;&d!-Xn(fACGkEu$&uyYAPhDbMLa z8sz{p&rHG8E^w-oTO2IisUr~Nce@M55;4utPr8wxM!`wjG>L8aG}Z;StyI%{sAeaB z@^w`!c1R88(&*GW-Ql7Dk>2DZs3HnGsf1WvGQ0!{j6C20WWlnbm`4$Va@5R61-AT) z^@_oC8)~167q|Ic*Wt;HiC=~Dhree|C3?`C+NI8-<;iQW@&0<-CNZ{+LD%%+noSo= zASOO#?ai<YpJzI$dXu#X26cf$X%QcE0;wOcZ-qG9dxD{Zw7&z>usf1KtM3}s)Xz>v z8K-|L-%Hyvd9I)CQJ)n1xFf3N;aBH<XacI`(aeJ%3io?+#1-u5fyW?hCr3OkAGd4% zQM;U!k%J#;BAj9ey~Z`f6KMGQDIs1Ts)VG&<*Qk%^t`Q!rLsY+h%rZ^TJ}ffvyHd$ zU7ZA0e1^B>umZbE8mCB~w`+ueSt#(tDzt*fT;Oo^KR-K)-V(@&sU+GUKWAwSjz1+k z>wTS!iehW`Yfv&!#7qFJn?K$ZJ){*fRD|YT9QET_=V)8P96o;R4EwkWo$1XgPFfMW zrM~$2>7KSdIVZ@))IQzN+(cDkVbhoFP?`HqTBdQ!h1$Bh6%Ic`ru)O=0PBXDw0)dV z8vv%cR1=vdOl6n>1GjrYVg35kMvSB<)@<g*TQVA<=5)@4S71?FujM!}kuQ4x+(j&~ zIF{-mw(%^M{Pfq^!N6_AG(L$<Telf<-|%hhr)XliKg`?;<xQDg#DLURIRZ6nU?hX= zNIHOou=q$DW}GeXhBv&R5aOMcwZNagH_{8T?Wf~m3pnjTItlgHPr{Ha<h*Ju`UhkP zKz6Ft(i5t~m5Ja$hCyIZx=kUJBf?YxB?rB#x%pQ0t>fc<vU;hwnY9{s)<b%f@v%OK z1~me>N~4`0Ufs#*5LPsL{z*B(e=2O)emw}VAK|SVsZ(JU@JLMOTTzn54)Zr?&)P?X z5wby-M@cGQ5C)iEE#z7r$Ui8`$%3?O86<$Cw{Cvt4g~osyu88Ebk1KE-3F$5bCaj$ zPJ&hL@!m;pCxB7oVawIR1?P<c$BClZw4WUHCVFtkBr&HVmnWcb-w=fZlS&^*)etNn zyJ1lRZ+t9<Xe0LVdD4L|MbD05rN|9U21^P{a5Ks1@7?>ct(RS{UCd@WKI}y!=a}~D z-oeR8$Ef0q)oVz+0!`gW{$5gY8j^#5g**r0_RgNn?pnIXugHY+)G4i7Lix8mb#T?% ztGnN4>GEE`TJNA067HgOYM~P2N1d8(O=($c?cb=D^P^?Y>`U2cOkA8k$Dg?+4-%?j ze3%QU#RPfrC|+r#T^#a&8e%ix9wR)X;iK?)qRz2W@AKiV`@?g#iF-^8FeQTHV=;+; zQ;>`;{8kh33Of*pD5+P_3QcPYmUx#X*m-Nds)rdyd}UH}g^tG#%gt~8L6ka?7hKnO zXYzSkNrB3ws{@PN?|-^mnSS}c>X${3D0>o<-G-d7eH-3Ng$N<*SRJ)b6}2p3nir79 zVaU3urO4h4NkOVQ?Og|2>UqlNRH^}A;)K3<m80I`15BB-fNwh)0NGA9&uVDFeD*f{ z1juypcOtH!tDpC(mbn#b!ZZh6%qstu*|Fc+TStxm{ChAr@KhcSAHSdPuM7&O9S4ui z5$}he<c?F=zoxNm;LU>eFoE{{=L<-WfefA?9NMpYQCCB9RF?#&ZWd9|zQlTMr0&SE z8q!WH7=4jp*qqtqH<?T;)RIyAPtQRw#y?&FLoY=+r4O0jPvpcUsCchSA8SJannHbo zUF${#GTdu80dnU5pUKCBR%lu5)NT#a$e!T0WR>(#DA~Rld|5l*1GP0}Z@~kc&Jfqi z4{YHT$7OQ0ycxcpEDMb<T^CTJitCM{i-*2vjhr~YNgw&MlZaB20Y@b4nh5>R)VqKM zmdmKoLCOL&B$66vnCVq%Y(y_}#u7uF%Qc=Ud}e)Npf7#LrJvqon-M7O4hl!l2>pU9 z5)Yt!Bd>7kRJj4Aj$7u?f)kNKTFJ_7HJFMF<=XT$H#gj()Eam6K|8N56ffr0kz2o> z8!XjO5E?mDe)SqOa*S0nXksGsDag$muNoiO&Sh4MNPC?Zf~|qZQQ2KnDFV5s9f8n> zwz!J-t6{L;&Z%b-vaOjJ)?#n@k#@|Kn)0j0`jr_zNYpKLNvCYd1%GTiODs$*Gmq=r z49C@SyxA$C@^>gfreZ;;e=zuQ>neql>&$(st<Oi2^^_+YkIuTkTvd*d-p@Bq2))m- z+CP+O7y;$A=_PxS5%)eMt1{d+L0>;6=A!!Q+!dUGaM#ApjkEY}@XL_`Lbic)dc)P& zx8=<fpFa3sQBT)W(_WioLg^|mQ>Rr7g80;;*rC>AS15e;(p!V1fo+A^b8v0$zc0H_ zzmP(^@D?C3rk|5dj+C_?ds{l?RJSjHL&hz+P|i1ihHrIHnKGdaU*4^jQqD7KqC>=Q zwx*vdWPPwO9dKoN144#W^;)ps?+<ITcL(d(SUyYv<@{^~#yg?qHe`HY+$4e^zW8Wo ziU7=>);Q|TZW>KG!^PM+(I!|WK%&bta#&$?cfP+c`z4KVtGGZ{7j%N^c3vUxEQ@5R zubN*hiv0BT1eU}#?sZPlFIH#M@rzVKEAc)&I)fX20~K^+Qf}H=3K@i~wMA%lt*{DN z_E(23BpI>+1q`RP!gFWvvZvvUiqB-?0Y=eNMiwPYb<Dy8f}*T{glbL*9m(<Ai_i-J z$o9Qf3#n<czllZ_Gq)iTz_@dwTu{ssr(xq(QRPF?N1cY0b^4)rRPZ|qpt{N>>^q}Q z%eTGD8-QWuk+FJwjp-j6bX|PuBw$EqNUf!^`cYM+SM<J-lq;X05gHDA<j0S)+5I&M zdlWntRJ@0X+|Iu@{C4CTYwvujMt&Xi45QeEkP6v+%YpG8qiFly$gVn&O2z~BjrN|N zW5p3EX~7GQH0Cz5srk6v$DJu^tuc~><yj?Hp_5{TOcOoy7{j;z?7UFR?bV?Zq#4&> zl#I6b%5H%Ta4iwGaHG#Qj_}e_oD<6A@MCpC@K-7UJ|ByTHI?75;uA;6z2UUQa1Yhb z%#fIVq}<sFqf)q&tb|ZFhe<I4$q#F*Ht2S>e)+z?Ij%eOGJtdc<z*PAh4*=oibMUy zf2SS$jpcP+qQQ6TA4|r!xWl;l&Kk;<ZU3U^JFtJOz#^sa^u*73UZ~s}9#@1p;`N$) zMe})m<4|&J^leN=3)3$;#+Z$*)boUa@LrTfq`1nejLNuQ&Jya+5Is=#EL5egK{A$t z?!q_5rg#`E6~k;{L^Q~c!;QU`sGClRUTB{Vsi@U^EyfDm%uj6#B@cl={(~~5Wej{D z&;W+`*qdHhI7Rx@eyX`LJrOLe$fv`&*3ix?wQM^xN3oe~u-Qth1=e=l>JtJG6tRHN z!cHbP+98J7msB$zMOA;Zxeg_9aih#rHW4!)F9p>SWF(?7cFXLP3>zGfp)|M(s41G_ z`D{X*8P092({9xx5gv>419CG`n<!$MKh!RyAqbpp>Nr({xHLpu!>#@WeSEYY)fHG@ zF_;q)PII!3*!17?Owmh^q{c%+Hc;UPzEgO%1=E8gKSruxZv+j)bWe5y2{nI>m7So~ zASZB9SKxY%jRz@)!mvch`$4+47Bt|akpC3+VK#7FHvk|jHv7gQZjpLfU|16RrOw~< zJ|PQhSa;S<x>@c!eO-*Xc6IgmHVjMGMe8^)LBw=U*Q1<&P?hIR=4IAx#I*r@x<%WX zZ>8hBy<DA|CDqRa^8R4Jj2hEPm0=48u#Isc6S>x1T8>1ocHl8^!|cmm;T32IuyY!} z*88jsDxVT{M#Cgu1<rkPkTz#9QJKwo<T>TjI{CBXXM{4-&sZ)!Q&TYKT`Yl>!Hudd zN{3qI;fnX10<KDDP%r*WP8{D}*eYFHH#@I>-f`2Azclyj$kI`ez2V=_VTATQc#cio z_d2YR7Lu*L7q9sHmw?`L$j$-KtnoS9rjW;D-&hwuYvRdb*I`IgaugY!-&syN0%t4) zl}1kg{8kpmRV~jv;(qeO?^?mLxIdS;8W4*sQ+|8z3D^K~&ZC%XUXp=&(bF*C6C_GE zI3MB0Rs<{j1<4FM8*SGr8_TB@t_|O+@Moi_!RQy?$BsHTDPT?Wil}z^HPazVz$D6W zGaQ9WpO5eK#z=kwxB_bT^jE#PW`2z?b$Q+|JXa-Ta~Qzkpy;WAA>KH!A%dX^sD-9w zpg7XLG=EIEUbX;USV?Ch#qfzQp(~9X7>dQ0XSi-L4B*4+z5j$&pX)&)_P0C)Eg-bD zE@LdE9WwC!E*#<|ge5oO?Q{4-KpqlR9gL^X{f(+8F^tfZtZ&iF#Mg5NRYy6CFm{b! zz@ISE0-P(M`0p{cL{O&{&9IlBqM3Zxm<GFK&<2GT4N+nmX{GDx<u~mdNPr?(dg!o% z-QiQD*n%*4V`Nj+bNg>~;sBoJ8Yp%oWAA!;-c2VooVUuOw{!@-C2#jJ2t`>c-7g1V zozz|dW%?n7Mu|PQU%1)y0r@6-Eek?V+S#u3Fp%)5PO^;BwRpT9$PSo#zDC#X%G+<y z6eVT@4`_=vDkOx(MX@jp!8n*(B-Y7i&>0(rIuf`krbL}`baM(DQaVAGRzN0D1c>mL zGAGMQ3Pa({kdo!wznPmdh_{lVbjW|=zy;JsYJTl{v`46%J725#wWUNRQPtm+S4=Ph z60F>mB0MF7xb~Qc=Ggu9ypi##fO4TGp<W`isBH0!!+Zzd|LbUfjd;_K&t*5QpRY`M zkX#1|VY|+z?+8iYRAvyXe4yw;LDgbT#n=rZh1F+QEqZIZGb`Js+<$%-v`MpiQCblX zD>q`Z9~Xpy`=Ey8X-74MS?B}3`18zrMrmx|w`uS_6e21+1E-tw9gaN}3lVtXhqq=| z!n+v~-i5N+6b8T@YzYK?i=-7KcI?U>j6EIad(WJ{aJ1)?&U-Iq^?b|ue2qnx$oF4M z0dO&Cjq@$}_2XTm2^5PVmy|yW^%bU0IlGj(0&b)d2aV3cg%7jPYtQ}j>{!(0df(Ks zSCGp7y~@0zNl+fUAQX5If}O$;i#i0Rccz7mDGEt`llPddInlWfqXUr`-o&`=lP%W| zwLXNdrS}9E?O)O{`Gw|^5&NvBjpiwhg_4^K=3U(X&tnECGVW33Q%R-*xbukf^j+si zl>oDN8j`m}+=7#3M&KIJYk+`&nLz5vFTg+BZY*D^<1iR3aSoL5K$qK)<{J+z#6t^; z6jp5fBTzz%+fCh_?o55Bvkagqcn5O>59Juv_{d~p!U|e<`in0`JdnxIJMHt(y^9*a zA>a6ZpAVq0=@GeN@9g$OWocMSvFK>*;NZ~wQW*A#ucDi`K5HX;AYkm3Cur+#U;fLI zeiN<*j5hjpt*AX-37~WZFJ5-~%*mE_XQrH7NOp%e_W6-GMDvo(l$;&=AVsysJbo`( z-eXT|qwQF&w#TO2H`3&l)9(weD<eDG0%8fQ6rwmO{_)RJ7qn|IzBKQ;bog&Ib`wIi z;5Xlg7XthV7Me;1!$qa*9)1e&ABg)Kf{`ic=J*GL*2VYUDQ~0CiAZs$DY2YTd4C&U z8-pGbJI+jTOBfS$vH6<IF`%{(vWdju;?bna1(c+YC0h%{N-+O-%p58@e9E$P?O{ug zRDV4b1>9ivVNa<xi<G60NU!zVcWFu5mu#=pBWA$mHao?dX_~@FINq+a|L6-vYHd0v zN)KR8n?dJE*+&Hv3DM|4m`ipnqIifDaz-F$1_8!ZlTNnq3W~bh4<9}Z=mT2(Q-W&{ zszZ5nxB*r!EcT7fPDN${;|*6A2yZ_3%CQ34kqy0JDrhDn=C&><43mgKzZe3j8c_$O z>SYj7PB*{z)L8~PNb1QDo%fZb$`G<;9q@VYO}hsRDiEh9b^Mf!3O=%g{x`B@R0#%| z^l4b;9$PSX%wP1iair_1MQjU@%om63><*@*qxQb84&z?g*^zkLzll$i$ZK_$t!L4L zL7Lw7<(;Ts+M4ONCh)(!Px*-DhM~4VB%9(jgz1sM!@z6aeR&#?kQQ;{m|Nvbseb65 z60N|GPqv`ueQLPZe0ArS(E=X4sX>}VFez%Oio9iXG(y<+V=$*$>!oa!oF@Eij?p1v zr^t1~5?R?-I$iP)Y%al>!PN9QDfXBfhlpz(wCEEs-?gRGm@io<n%%Cm(*ts0Yo=ax zj15<F&t=Q<9S6iNdk7urdjr%onk8q2?s3fPg`7NUO{&$Nt|Rejk$UOwP{lF=sQ^)c zsK-oV&|`0h#;Cvc5_S~=<%>oa@&X7#NRq(A0SQU38b1bUOu@L1<)Kftdu&uf<wqy( zkC0+D1e^jViaq$9J_q(9Wt)UJ?&nt^w|%zs+3j-xWLb`Ah++g_ZR&Mr8lUS)KnLO# zz3^{ndQx7YH{e>61ncLH*N25kGHEXj)t>$Rl%!ZLL#0<(YQI#K9h=1I9R%<DfuIUq z_ocVus_gyoci-Qzfr98ZkiI82$6k|d@cZ8cT?9Gs5<YMIGWaFOEh|h+{V&zwWW*Ek zFGU7p=k<qxQya3D7HawW8o3$~%`2o6J&8EFhaY`?ANKG0++s}$N%crI@5$4mb6b)` zbXYCiu41Uzb4c|D6f~m3sj!J$%_=tPmF{e#*D!p!vs%9mkLsw1HcX(X6mD?6fiUA1 z`TnL6_fbu1K}$}kejFZU@|(8TybWPNNy9#@IEav)VJ^qdavBq{+g*JHsJ6h;U9*2) z@sw|087DrVeH_~zshoZu)~p?)<Tigb1RU1WS&J?u{ua={&nfR{1BB@YvjX8p!&ZQN zW~(BQ$@~erYZq~>`G>EG!=SC)Vdfv8LZrG&in<XYk*@@%Hr{rvJ#sUhsb=3_DudaN znF9^!r>Ta^?-vr$WnXroSfWX~^sR36j1X_<b@ms<a4-cFlg=1mfK0$1IO3^2J%N-Y zKBu08oml^P8q9r!W#}LU9n@MJeu{h014HIUcE%Y!JhJiSpOTdq!6H9N_6WOw`#NBJ zi1<;uJj=(T03&@KwBa(J+f@htT^~#<geS2~xR`9PL#XF1W82CC+89O(Mq0*K?E9TA zO}fe`m+W$_1&UhymC==O$MC&_VPBD*$K1U{s!>d(_9D|fA|q5n#NCyrzy{`I8{vb2 z?#%24ojgr`x65XooFBLpyeoXyM`n`K^MIavR@(EJ2*q>pT(Nd?lVPdZskVgIB<C(O zd=iPoNDaj}@&Mc$xt6mDfwRz$NnHn~4Vu<p&oDMEn+`MU8{If9zR_=M11w3eZrg&3 zr(k|LjYmm!W%6csHZsLCJ2qA`?#dP5J;HsxG;|B2v$C>M%9W83U&m=ZgF^~0@44h% zK;YgYkit34rh~16GvJ(3(NCtHBP0LVJ*)Oxgh|xu`n8Bbm0>lkPXE(TEm3wCPg0u9 zy7JsI`cb?!m}cW1#JWqIfpE-`fOqdGe_fJEq~n&Bw~+|%j)4hCbV&VLf^=b7JZTHD z>a@{aBkahl=0!k#t;F2wEz8Ay7NB0r6LkK55)qlq#rT%ZtTc|^qPid__`6X%fLT4; zoZ;)G;J^NSp}K7C<66M@>H=>mQavakE5|B%LFS1ZJ*ks*FbVZq;At-P`|FECJgjBs zOdUmOL4O^FY}{)5D1Wn&Tz5ktL51|4aX<nn@q}qFz)&|wo>CKqfmLT;)3r&@OuZYx zD8HEv{(*b0MH($tG?j8m<h+c69~3^of=Qn1&E<$)LdH1ybKRNFyQMxGV!C}Bi$fAg zYLctRn?%NBfrv7f^i;cw6g%aMH?y)Vy7b8(b&NkHmc9au#!ZjV(6#X*0x7x8T7*gN zr;-+|P1}3E_$r1%FZiCy_-^5iJ+9V>TpM-tPx<r7+49ei<qSadyrN$dfK`xBT!CeM zzKyszzg-Wtt*?R35EC2xh5rR9PjW8JQ7F~`N)zmHhJ)3em<-|`aTDixx3et26Hvgr zCyh2&46tS&DXJ<#OH??`W~c*G@+FM%!b2#=={xVtVxrBad2u~op_skKTfYn)PMl^T zlLQA)l^@oHa?LKV&r&g*Ob11Av(zPl93zp8u!A?HDE~gVU<%bM9vBkz>b+zwmCj=I zqOVKMBf+yYq{s!m2F7z=h94m_pJ_~zIJoG|<eFRL+JQB9Yl<45UaCS^h3`{@g@cea zXMHC`9p-A<WXd1m8u*%IpcY_BSECVen7asLU~p>UZO*JQLo%JF<AA-SHz_s0420Cm z7@M8X$$5!Gdmn!s7pZs<Gr!pK!MopmV*r^GcSQ|%RMWZMq4U_bHj-x6N!x*Y`qZ%B z={FBq!M!ETIHq!^^11(4Kc2FSa4pXW)L9fx#ro-QE{!O$Jxx45=KQ*#uLx#AEj-$@ z-aI3mWY?CS2=LWqR@1$k9f78Yaz5X+<&liS;UTx5ug-+31LD0EOw+Yi<}{O-5T{k_ zpp@~blIAsEA<Wujzkg}($gmJ?8J2B2G5_+AB5(o>`)!I}fLtWYKn|=N-7LK|w(=|o z*kScqAQhkCCT%fv4Vr{lG%=gCXN4^Jvhq|b0$G3i{QP+8G27#*w_I=S>^Kf6axlB@ zXgoXv+M1Vn?2Y)^dnu!WGFd!GeDB@B>fF!9kjG`-iW&Po`;+T)1nZn^3vcgycY^)P zsc*6Nj$p%fH5<<0+W9QUMQuDtK$jLz_B{zm7EzOITL&Pl&|%sO%BEqS1+yw;L%~cI zr+*_TM@HL5u~Kp0TlFD{c5M>0^|N4WqMp(|K6S*-#A*L71K@hHjp@OIfAyEX=!k*# zKz1++*=ccEU92Ac>Sq9s{aFb43&vBa5swwFElUXl7#D9h-KtcMb}t-#!9l(rkCWL- z(CLm8bxdn`C)jjMe;a-`(C;P9z8#Is+J>oLD9pa^y*Pb|+@#}@y&Fs>K-Q3QHK{WA zlJYoAGja@{we+~#{U9aPoC->Wra9@F=M7=|s}Og02U-Pzs20TqLW4qkdednB`>_Y# z^EF*-oAF#{N{^9M*g2A*+4tTHfq!8N=+hYYf&T27pJJyT8p*e+IRV|4X7)9D>3*z~ zFDgmEfdskuN0Vi$SgA!a!&E(CJ+yi4c<Ddj^3gf7_YQH;0lZ9M4D!Q3fTY~ylhbO9 zsK5(^Z^jLgQs=<GrOtI@jEXi|O*>kswpZ;t7<w!o+__0FgLDc=N&1ZIq)@%@)))L= z(f_tq?KLY(H-GiiP@5Yt$z@&JT#ocU8oFbfSO)d#+Ns-jw(bxq*c^XrtO&|P-m%&T zzxz2LGakRzoL1^K=6W)No7SD|geB_cn3GN*4uAV?5b+1$9saKf|NZB>@Yu)FOB-Us z6*FI;UQbawerNR}Eg>7L<|igz0-z<3w-KZTB7_Qff2Pu`nrueJMSF+AmLXr)rt<?S z*4PZr*%_&Q+fb45NdS{II(#~_BmB_Fy!A5H3kgPM-{a!5Iay47ucBfl1l@s|g4d?V zcbuFmoQ&eItdhYkK~M4meIQK^YN89mA$p_;C+W#l(o<N!<%x(_4`2$8tr`zWmaXq_ zCf1jhy4<E6s-jT+)52aw#GnOcFR$WnL^yU0GHA5>dITt0YE3p%^9R|}OV{6K)0(oJ z8Qk&%Vh&%0+ggW8=gr~Ok;g#ydUNCXvF9_UQ3kk^Spu*I8lgstFqvPY7Y{YkyR!5I zz$751m@ED7Yjb%t!brdIrDMv8_SNq*-8(I1gYzU@Na@jf9m#)^%*dU&`Jm&sKzHg6 zEr&|l>778m6wnZ>5(!J3g`>@!imxsNcAKz22EK*sDU+pV6}}og!m|q*QZQpP0Fd{w zARfU2a(k~Zx+Z|p22N45Z{f^N3?R9A$SBV-GaC)iKpnXBrbdKeZ*<)TybNm_4V;q} zHqIY8Z~<@a?ksv}6!+zrFns_rMki>Mkg-V9G=Jels0IQ#ll7LvDpBXD_uk_$pa_JB z@@u}UCm*;e%z&0QELRzA>@BW(HYzI!-vR?UPROB-GdO5+u=Wqh5t3O7n5_Sq#|30p zh!0V&zZEQL6pm5eAdW-pMO~eIlJT3KcAB8@yUl1CcPsvF(zfZ;JBpo}Y!Oi|D%JGZ zSzBoo^)7#A5Z05PS++45C4bAvD;o4^TK3Je5E~e&(Jk>nZ^?50X=tW3#OJo!BAvQ+ zcdvzb(0G#x)st%$Cg6&Yo)Bszx_Au>1YHf6^*IxF@!9;J9_Jwwh5d|55|5F7y*LC5 z8fUwjgxz|w43tvU1&rQ>Y#x_7FLYGUI9BYDL(t}HCY61T5j@vXuFFer%2w_<<k?1a z4MlU@@)xNCsSKW!y$s2o<SmT(eWu_4C5NeFLqZHnd(<J7gu4J#$SSVjf3ISPNHZ07 z@q%orA^e=#gdGp`Ma!+mzw!mzA+$4nCWXS-I+?{tEVQCFPBv)UQ0twDeNw+epM@kX zf&h)f<dKA(?7?LO<A7SZIfYS#;zi?&SU+^dR=cv|bCCgdTaTJq^olMtM+U$Y6OKyA zemO;4zwlM;{EOmis8V?4A3hlepz3HpOErz{ON#p~*ZuPL;Glkr`opFs=^Iy}o;QFX z^ao3}p{zmg5mJrf2y{YuR8uO0pn?hA@}2vgM=&%*D{m*hxa$@mRf}crcuF;NuN&#N z!?@@9HR%hk=zck3)Thn6Jg5V+9{s82_YXq=<O~50ad!uCsRCB$-fE?AQNc}STvQ*h zGM@T7QXVQJ&eyLcF9aye^C|0st({gnA8ZE!a-sGxH^+7?<2fyU{a6bRm;vqhGoePS z-vqn@D(9O+@^dGEJIPha@jJRQ42xkF%YOZHSbW>ZysxOkWc!06S!ms%ue4;qs62o{ ze3f}G;)#9LNiLTChn(%YQOO-Z#yh*CJ1NT+dD@-_#tQP)zJ~#IId^^4=?vUh(I?0| zyzoF9|BX}kzwu@7oySReXi!HZ1n_eIsh5|i4_NbvaL52yI}QalWh4vBQY{9@X#exa z_kjc--wIj4L8Od0e(i28Mjr6dma4i?G{wmQQl#w8H3@gz>YIavhlTozVlBGzK%l8` z)x3K+U$Kf6Q5eAvpU>(2FvIQ}={>TY(U<GjA%uLF<8pWd1U%JooGZg^S(mE0__ggL z>!GGcwC?YNOv}7;{#F#@1S5@b7lqUDckv<qE*cj|8BOO>4s<sAy7I0KM*CJE!XE}4 z8Zcp3eTYj6eD-HgyO*bdnhY%&3Tu!2a0Qe*4Qp8dbwg^eTbZaIC{9^>EwQW0UAn4N zzEZIvv*WO91+~z{kj>EN=Y@P(jbpit;D-6r=l-RJEuRkO)AM>sbLIZ3YtVY@{2S@< zIv16`-;zmYWJiRg8zL|fQ|(~7>5YhbQ$wTeJJmWVna%@O>;aT!QeVHxdLhs0=_*P9 z_Fr6cD*HGoQ14spC`<&uTo4kNO(#E$xRR_ulcSCyDeeH0B&GX>7}u8TzFwF6F@dmn z<gnP$rP7VTAOJN7g&#zp`}95l^3>oZzEdzpv~5x!MIVbT)zK;6#hC#@`%*cM{!Te) zEo{D?Q4uo0Rc4DHw9Z_t_g{}yya)9z@x1)308n2%ImBF65iPFT&NZNKY&Sk;LM(L} zsLjHYft+K=v7=*w+gdD&ekik!%TEdPdf@tPLIl~64s%E`jE<WQtJ{yv>RaW^hCC{` zC=soW4L*&Bk;!uxfNBI03i!cyFfxY1)+!Oo_(XC^cotfz)yj(?kvV!y&p6-%^j8Yf zcgi-5pfeV{Lx1|iVqs4`%uZ5?Yr6YzNsCt6b}hHi*(ZTot`3do7|q8;=_x{!xd;`z zYJo0Iy&fUrUk?$iT&x<nc&c{aCIVUH)X6eo5*V|^-#Nw^pfb$d3w5UX|4NvQOB+Dp zua*nN?LzTYw#eCCPgFK^9EUT!DvS%)`|}k75wYv=0eFjjrd$4!&P<@Cm4{si+)CMo z@(G++kXw#iw7ydU&-sg7r|24f2=?66qyUm=6DbK2L1&qb27px(Ar6{f`YcAA<j;kH z;tAmM1;bpei$^M!zR@&5>L%5~EhFL<GJ|=R``up#6CV4+bguVZXOlpcH+@ux{Ba6e zp~4Zb^ZH(kwX8)`#9wsW*Fvx^Gl`vfTM~#c21(1#qwf!!U$yMNXxUX!Aq&=Zw~VY2 z8-il?P737faQ=rTc`~A6oL6r=cbQ^af!+G^(X!#%38e%{!b@Yg&+msM&3_mAPol5$ z!*}60^55@rc8Zfhm<uP~1t^ZeE~xcEttH|;?W%{X2(M^jkT2T^n*!RSjT;oC!tU+6 z0_NS#J$WjtV)w)vcf=>)n~ejhJA>@#G3?ZqC%xMeW{rVvlHnmacYyLRb7zdN1GqJi zi(@sxXmr24@=<>@Zxmf0NOW93aj_}gbpzL7Yvw09;a|MC&Y_35@@4o%05lrVnN>(& zzMQ{mo)PtsT-DO_FE?#wW^KwMNquHHpu+WdR{REEQ{BhtJdxB+9=*;)<!TpQ|3-9R z7bTSd3fW0C>*n6;2&^=0k*XxaAl!{nE-Y@X4->Rtp;5nf&Hd^cF{jk=#rZBB@jV-N zAF)Ep9(<oH%A%VtdhXQswbe-<2(vo=FxH7_8<6w^bxJLWYo7XBQ%-qzuA4Jb>$W7E z>Xo}d$cAgLf;iO|mM8AB2-59r+JY;v8><j_iLe!S`j(MfCS|^7=+5@frp_SJ`JED0 zX@(#|Hd37^eHyXB^1UlnzRQds5Tjs*`9oRm5<%Rn?wN}~W+7fn4PHEsNr*xhtp$s? zD{1i#MSplL+}qo^MzE*CFhz50|8Q&WV+OT~zxCUTIw`%sZBRJz7WdE{YQ!Az;unQB z>^?FKz?pBUE%OvGk6oOecD2R$ZHc9;4sFT7#;lvn&?BeJ_2oCsw8GTlLVEeG%cBjf z1?fluAuDyxbVqVnwgk#62x7C`4$gbg75|)1o)h{7G`9M7>#-d}>6dx;2sO!WzsNhW z-+AIg$YrLOY|4eLdBL8=t!%64#n+_^t^=DLU6PDJdhSDJpYG3JN$eX|zoauw&i5(? z&(t~ifncFRcCv`@RcGW}-O4E;+4Yn93u}8T@*7w6=Y*V>J1%7zEvEBI0*~AGb<hWB zL&%BL-$v>ZE3~F)*s&2{a01!-jj>;mA<(bB4GfvwD3LBH77OEG{91149Ji^<Z6_64 z+}E#Ik4ho4;rZ_Y>9}WKT^9<gdlDojr^+dcn6IE#zMZ#HRb<UMPrliHqqra4alqGg zJ;*4^`5!u`;e)RE1rl!MeH+hClZs?8Bko~6yntT*DRN>dy9@QaQ<jLHsNl-ZQL(#` zyMM?2@w<C-Ow;+hz!jVapDBEe`%MkYAc@F1qvw`gn`=4Hn=bhg|6ue11F`8fNf6#~ zhAv}=j&*Dfm8yxVB#K>hpNi#sKlSqB`sfMl6iGAn-N&+JPef5l#g<w<+f`(>R;NMF z^5^Esym;buCkc4zA?}hvFCHYx0P8=n^#nIQ7o3c`u1>7rrg-D%+Y$ZW<`_$M7p~1n z?EQKTTD)h*Cg@EM_x#~^wm<6nzsl+NBsJ;R=UJTE05aDXeeB5(6~JlIe>bb$kucu1 zRytiDC=7S)icyN~%ygkq)TQ%+79bd>xJyts06Rl`5XZ;y2lfwhcD6Pk`)dG&Lj0(R z;X;3*Qo6QSf*TMeY<djBg!_P#8L#Oy@*En$5MkRNn_7E7Nui9)ln;}Fanq&eP|swh zCGWK?`FO?JXhflLCPo|3JhMUXXrDKL34(TFkmvpw&6nGsiLMCa-8jCLj_qvm@L|u< zUtvdFH?G{c9&Ndi$>SEQn6+iFu~6l)J~d0%vscchZgl8S<ZojRS%QSE!7jC>5%129 zqgZC6lLUlp;6Krj$yi3r`QorF2=6@or~C5LukCJ*DHKj`?2?0?ug5n#D+^nO^dL$f z?@$?uw%0*ttnba!ogz2f(6CTZ`$}-|q7_WjKCxev%YcX1+9~Lo+vrpCuOuvBkN~96 z++U$uz$t%r;bIKCUwXez%f{Np5ep7L2MA19_kBOYTLw*bZ-jk-F2cCf!N9pA`gMh` z{8zK2BXeu=$MY?^xWTN2*w!M@Fy2&9Vmrqg;6SBJAZ?E_JR(*o%D3R^>MCSEp%PQ) zbo}MJ_0X3dd@E$l2w}2RBq#qf>&E&l*oX`ghRE$KRQRHYuc5a$HT}g)<e~{aRR%+= zD^xwR4s8;49#)m&#Hdg})wMy`f?GFJ525dtf{YHKc-tF8s6<@$f%g5}R9DpilN}Dc zJoQCd$Np0f#b{0=9?FL9|50&m9;Xqpt2z39du>u@xt!s50|lhb(qe~Kh4B+Sg;H+^ zJ8rLR8K#xuV;+F6hOd$c{)Mt;e?hT@pm36luT7kRdz1Q8zI=mHc35htyab3eDGoI5 zt1T<<7WwXNAZr*wxQ$iLahO-1eSFmcBTmAF`gYb;M<{*&qr!0QP0I&qZ)MWzFKR%) zb=F&;QOjOYo_(S0Hby^t<<aJnYVxq#@015u@Fu~n7j*VQkCbAcjn|Jc26}PJ3gCen zYs5U_WH=S*r3{@O;Br<*Lz2`%K6Pc=FlOrrvt-3z9^XgioF{VM*imy|Lzt32pLjc! z%uW3eCWoiqFMECf1|rj{i8qchxAYMD5j5s|8nAdncQLelZ&$QQ?FP)Nc|hiA-PppD zp#t3BUVmm3B8RG7oo-A0xk@+$LZ0u5$||cyQNU+cHFz%`oTgJ=HuaLLg&X<|@}1#c zZ4lX!C$0hgV$R9<`kgRvu#8CUR(ZF(TTjCFO)c?nhQ~*oBjn*%9I#(j49rE1W7CUL zeu||$1H&-e8^>eevl6bAmdNpx-iLwJM2;hLCdedMtq<azA2SM34GQrc@piG|Nw27d zsv7UJjXN`adw44bL}+L3G%RB<L0NmQ(Q12<Z7iW4vz8k~QI=NjLaV{ygQzqA9{c{k zT|uadm6_0cp5&`SY%4|t4-7~%)Ixj;ymo+BdpGgT2mRriu+K>>myLC!rGTg{Gia8B zp|G$9)I%S{z6xV&ms$Yc%gF;ehD9Ne2P54<XP%8rTYFCA0^uONCeo2E%2|G+*yxro zGelqq3$Rtp<31%n90xj}6+j`?Cucp%e*HLaB!&$cvv<)RvMXH&$Td_Z6-Ew*)c_0s znZNvv*@2AB7iX95WWUiCMLroclz%?iG9W7Kir1E(wK=($e@8bzgLnfxRDd27aqIJD zxg6l2E{^>OBqfFN)k?letgU}`WY=xjT0H>`z5NO3Ztupm151sf_)X?v#X+@_nzR=x z|NG=lUIs($FAS`RnubdI3?_)A{NR*0fh@eVf#U~#mRCj^ECZFBzm$PjfyM>r^h~hx zr9WgwhTd6IX+b^bHgi+V00-^Z+_XJ4gaPi*V}QhQgx}^xLZv%@Y&)YHDr&Zq!0o(z z|4ghz9}RHB5!Sbv2k2Bm3#qUGoWca)d~DR0@2>F}iMB$a{^kYC4<|UY$bUn`pCpIK zBU<)9lqGCI`2C>>Zn9(>eh&l<nrbBP&S3PG`!^tK_<9l9s3ZC$=bg2#)B(&Qqv>O9 zK5T*K5tnV?fH44~($VqhEDX0YzwR(^2$h3cx0?@pNLvUn%WUkS+gbQYF9Nszsj;b$ z$VHQ?ju5dLmVnQuze#$1<CF|y7sE_;og}Qu%ps`cDeHPXjLOJsT|w5j(yjNp7J}0P zKcf7yX_aMD>!aSxsA5x(Ie0?!&M0<R{TK9%co{apW~%YfTZRGiUP$_Wnx-1uAOj0Q zQ0lG{F5dOq@{}5&mmk*u(GX!XVBaO&0o}C*@a7lIiPI3R__4Mr5}u+vZ~0{bX`ZC{ zXZXu|nM62HL+}67+eglIvUZLYpvt*C3ZYDvzzu4-VSOOhpe0|zgseWIrF+%Y1NS5X zsClAyVQPif+CX=J42;>LoML}wL>L3ZKRL_QVN|=+rS{1|!a2D^r87o}h~6qitGKhb z3k*Muyv}ez`6d-gPPDM$YYRi_SFc#{L>W4e^#12`;he*f(Qu>E|NVGP9D-1u|KoU( zDH61v*l+L&H*7l9jD-6Z0({Oc^ki2rR%uRNAF9hSX&VpKu(W=m?L2V?QHx~LHhPcY z_-qi&^U;ea8u?)<LS|}oW?03NpO$4g_zK<o$Damt!O;K3!#>eQnCE$4h<}K1eow$@ ziY5M88?j%O%fwwT$bR?iJbz{%(43JgEVP(7(O!gr88CDEG1uvxg2;Fq^J+JC35JaN zff0*!9CU8XojXJ7`tls_=fPk&Ntdj~hLr4_ZaK?E4RB6*fRHn`?pimk#y&r!K=U?O z-518-g5rV5%h_#O@*h(u{2@M4fG{X52Ve&mUn%$$MWBhBJq`tO0E}3;+oCPjKF9jz zu>73a-)Aj#^DK2<Mi_9Rez_kheN;(+*bmGNC?zVfIK$*@JXl%5y3P(+OG8d--(8Q) z+Cg)Ydm8LUxC6mzLB)%Ve!-kr-1%;FQg^PI3XHW%Y+t5<Drd@j4Dvt9Un5iZ`TbP& zj-JjCxZ?G|6qpN!TPF_}b-at!y>%2(u>lj&(f_!;7`PcJ-cE%!UX<qFG05M$7a#+M zn1a6iAT5ln@a1|_(gmo!$Oma?X(PYQk}xlLH-)<`DjF#w=wGDSwCf9SS4e{qayxrl z&ztI(R7@ZRL;1Ia+{FaJuP7imBh3cjIWNlcC$+&Iml-$`HZN9P5bPg|`g~L&A`O-; zRJ(ZG8***GW#kAKBO4qiYI-~O5OXmlQ<mNe-vM8gCtHJ!uHW+i@Nb0I`pKVA5k3OW zJYK-qX0Eb2Q1tqGAQ0%7oe#v8l(;$s8UK%W`3kV5%M+-9teT8g+-lPX8@3u8s(ax* z`eHKu=g>>a{~%&CY9;5fSAuf`oo2&r<hhrZZa(5dl)k|nDvh`RN03CTpU!!9?1_1Q zLCfM%-`<Zf0qZ|j+D-p<wy94&AAQ||hdR84Y#Jt7mqZ;Ga-s}3fqT$hoJxiToYZ38 z@t8XYgn8=3Y<QRFRHsVQ6^UO}$9m9r?d06Z>MA#QFqC21<fQ2(@@GDbkIk5ur)w<m zU+60H-?$7EzHz~K*3g~ngW3`u3CQ3Oya=gFKE*cfO$s*|5!HMIpHY#c@a%g6Hn3HD zy|&vAUj5iHaA|o|>IjPO?~#s!mqhBbN~hMq3XT<b84I2fRW3s|p!i<5oV5p31Ifna zR|we9G?%hZnGJtgkO7Dl*rf6Q4lVaD>h+43z{lhBf5?Rh*r6ap3bDgTA%-Zh0*M)3 z)c0k-`$Em1$%Dwb;39*d7y4n1gCxak0E-6!l~P!du6+e)Yw8DsfLqw>J%LN2SD*Fn zdLIhx#M|ZQog4Eub*r8u04Ll;l3>VlxDWn7xz$4WpV$NrT;)%shR$jd--1YOGD<08 z?ck*f)x^5%l~{LJ$gFW8R~s@PE!qDm)C6Du)FZD;3i5R}l&&1}q5xq2(8;q`(>h|? zoJbwvM}Omarn^!qK^lUL&>Pom)Tx9}F{^XVn~zV!A-iY;w=|XN9>Hw$<rk$ugQ$0* zw}!sV;a*z0qQp+l(4Fe_N*G)Ewz~)bZ`?IR1J9ph`GXh!?Kl5F_TD?L=JtO8<|yq! zDO8G5DP%;uj*&!5DlH8~(UkUdkO)OdX(Op<Xzx-;Xo&XK-g~d-eVumh`}@1^@3UU7 z=lT89>u}EJ`drt0@9Q4a%Sd+Lm7xIPM5;ti>@U}HXyPZ|mXW1FMj@nNaIl!H52y@= zux}ZTM|8l4*TCGNj^p~t5<)Z-4Ezpy3V$DEkgReKBPp#KLZE{6knM1L3^%#`*B60X zuUUFz*^B83Pc(ZDLeW;6a?(a|$b#&Idnt_2xC-In;uAZmu9il4SujPufpWmIgOedS z_h~pbGDYX1-V(<a9FC?oT=qgYRD`0UMaR5UzTs3V(eYs9cJ^LEF+b>icjYyz`c;{C zW)K2|J_!KZMHhd8a@N6oGlD|nOI%9==z_!C*?OX%D6v!~_2Ef8d;g1lFY3g2C+dPk zzn{|EcD+dEQc@CBCzhSK0?Fy$-(w^C_88Y^){1_#0Y@cr#PoSKQ6V@+wlShUCa5eA zT4dX5vc29$rGB*)iv^X6OMBM?k-G<l)9=o@P%<@tqSuTsn~*gll!6+Yx`kTa+@-9= zqAq<8MT+-pi^Fj+Q22xEdR**CwAa4sL^aK)j8K_|+a8VvQ+`ovfSFldAc4yTO{>Uq zTdvi+i0^&Q0qP>|v;A0a?I65O*$Gw73-rYQ41o-ge4?QWnh>+wX?9v0he|qPuQ#2V zfN+<%(|%D%+(*W^IIi1~|FX>ybn#2s!@u6_3<Ny~Wu@;QE4KgKK0@Lq*mYmD_S^|J z+YBf}LH#_N2N_Av!>FYDl><=!^A}LBi1YKIT%dQ|&u_!WW);rf-ZiOl`>rH3b82Up zSp5*EzdzL|U=x1L2j%-|jmpnSFkLSA{&KyS+=I;eH+^cIN1&g>kSV%PpfmUSS8pEX zPTH^X>MR;y9#`Y=vf}a|vVsNO%lLj`A^=2z`|U?t2^Z!z8H;r2K~vGevd<kL=dsop zlgx=w-m4`a1;>Z1^uAQS@h0s%>2`)2p1yj--+beGS$r9z`d=tDYLoRdvBRqMxx&c3 z<u%>x?wl<ttPl<^d(NhNRt+DGZ!-!1=&4q#zf3>0R>MG@7Meq}dH=7gFaRW6jxI9$ zCcQ*{@Hrkya04#GmF=5Em^dNBfG$x*lh+I)CeO<Vp3Ag#qGZ{IW_p|;3N&VYjBc9$ zPKjAg#V(Q&@kg}=viiMI187(Vk~aOYh5K};6+pszZ-mT9#r8jp5Nfy&-Lt*tRv{Z$ ze8-QGW0<ExU82fk6BKjdx<E9j;^42(Xi6c#?Tx>gt6_Dbv}&FCEAqZ6Q)`av3RM6r z$+VrXPY_$9o1!XTsKUHWMQ!j=zbkbw7f;VUQ?$yB5P76|n{<^Hg1hz5xMY(vFzyFJ zUN1LrG$y#dT4dp6CxQo%V?!by6O=7Upv<`a8Foa??`suB{b?noXM0uSIp5vjM-A@x zl(ax^mAp7X)HQ6Sv3*a%{>be{ivDfrs*xQqnA;u3i6Ns<_^%{25&Wp*fa~!3^(KI) zf!5?7FmrCn^}~MxJ2#yO8M`4|XSHhL`C2kLh?Ki%*rgtWLBfKj!G9EQD1LDQ-w}s` z@q=f)zxcm@)nvxRHG-yZnLMP4Jjud@--P1-`AtX!ubAla6s8(|-3Enz-8%S7sCO4< zI@tZ-ndm&!<J@RwG13_t5xRp49jzhwhb}=0n&nxEgBpfEc-S0Okx;%m%}m`NiZ<=W z5Q*;nUI`3%_JbY#IVKfhMzA<4B@tq4$RUBss$+U$XwoJ29R`X%JRqm2S{k4E`aXHj zPwp}<f%+z(VPVmmyv*yV5dMX%|AN^bQ^Jo*v}rpwVCvAs@`CHHN@2+*3ln{UXRWE= z&pk;+M@-QpKNfdN24k-k^S?dn58@LpKZv2;6N{#i2H0NxL^?P-{vHkK(U17;&x_{A zow_Y~fw~{&`qRX105@!LjLg#OI^fQ8Hl|ZgL|Gc7fllfe`Bc|BoAB)IG4#hrVGCRT zmtyTh_BkitPQQyQ^nlr#lF*fX%k32cBe8@Qc$S0N8>qejk45J42q(p-PxQ65#CveK z+z`wQNdcbZW!6e{!II*k!@tnD>>D}kl+e+awK(qT%yuOaVKr6t{ij~90nBHV9(@(E z3s?dMMN8h%VqA4|6~c@w0v<m#GOXkkPvbuDWbB=hcxXO)<Z8)Dh*j-^@S*uvWi<ZK zjHWm^KkVGA=I45Wa1GO_iVL(3!${;#p53y-2b0cMdLIK!9nz11X<B>G{W#q>Vd=$b z2#Y(z3c?E|UCxD25nG=J%Hhj<q_mV4Uii`S3<Q*CdJNUhVlfpJqwWvrzR-JqRvjtr z`cbW%p>XHszWx>S!7ZP_*bXJs1`HfP7cdi|{Qgp*C>o^{M>sn@BwLwi<cAXLbUYe+ zAxk>2AtgzX%;tBd-OSetDC8j-143duyO{a$U!D0`rhArNIOT7d?}V^0k`)5ka;q<U zKtLq}`yil;Qfi>=R9U(`M8`HX>Gu&&L-oy}6?u}ntNi=K*WsRSN^a~-ElIdc7Ooy; z_%;6i-4HiG{jY6gs<*JAcrEn%zhsOMi-u<A`px_w7f5F#9Yf`8k<%<Iny&3}CWm%B zx{uE3MxpxiH0%3&)kdBh4isF<MltR?o6#)vaQP_zUzzE?yisZrg(5@W<y_9)y$L;^ zcNpN#7LVO%WCDA%)ZxM%t41a)GbgnbK<GM0E2y%^x8Y2TTAXV|2#ZF{`I^O90G|kJ zAOl!Vb+}5kK(pQK*Exx8k>yc)qbG+T9UpF8Knvr?XV|MPdpzc*uOB#{DkTP!H>hx! zxiKgC-xWHDb=t18rETJei6+hW2o2!1%CLhg8GjX$S{{I!j&9QRYdZCIjaC8yc&UGf z)?LKRi&fT=r~#GNcK<`{XT+6uWP8<<iz8wn;&X+2v@{f-F1)UU&tNP|%HL>=QSV1} z#76kqJn~PA46!K4LXwft*Z^Tp7IsB^MF$X42{16*qd+p&$Efb;JIa$T_IoWp$MP=) z<RXtPT~48krrE`zt4$Y+x|Z-4f^cTORebX1O+HXo);DVOVSwb4G{k=b$x*ifFFqD; zRAYk%Rmqa}lmnP;&^P(98$Up3VIbGiv;R(#{w?tTO9=zpY7l`x|L=f0yK_#j&$ywR ztIO_(7zy>gn^=}~0$R7z)+8~d)LRIM>|gw%HsVf77^%5ddi?E<jKBv*u0~>QqhSdd zNlAIOk>cDEpH#aVY2H>`JNHd$-G`?v8_03@zN%r^aQ(j6bvN{k)V1~WJXGS^D(xcm zBKv0T+XFN7dgg|NVf0RNs@6>FHYSQlC2r#%nhM{dobt-v5$C>rmQb&fu76eY^SP&R z$tz3_V!_@-AAXZU>BWcwjO6}}!Ek(vWR%4J_tN(fY!D@U&w%0BbkJ+p{3B;*;O@0Y zb=d^ldEmP-ZunDv{>X|oiGLl#HiS@KjNgd43d@I7^2M>wKf1UqESI%m^_t^f`FN<Z z=HARjip)Y=+7{@~QLIuYm%53KBbaS9nPs={zs*c;*PUrsVLC%)kTq^6;Y4ek@w>Xm zB5<tb+skOER}l=qwR|#S>eCtxc}cZ&b!KH<Rb9ytzsWVw81ii{*IiFQ9J152;7Iu$ zhyY}WRGO$y^fmf4xt-PdePzx0x9^AJ4UoZ~P0$dCUma!y_qokU1P#@V;YP<HbS}XU z^E%G@J;0Gr>p#n8o^52ln>GC{i(G=y_Vm`N!mKjK0Srfi$$P@h3qVI;2sXn|8C6ir zh;=lNre{u;M&GR;e^eh<!zc}R6WEeY{}h`!Z(UtoSEf-@%2!X@%4jYpLVrzh<@sQd zD}c033|y;s7gT%0#JbWWDLyZ&JN8?STK!~MN$Vvo41w?N{!qS*J@!-8^_0;<Bc+X9 zK@;XZ^gO2WQ*>%9E6IXuPromXEI9+SJ*PSp5;f{DPbu$i)0Zb8{w3SM$~<v;d^}HV z2c^$p4)w#9XJ_d2#n)^s6u&X<l^avQH5H0-)Fc@@Sohi0Gl<S~Ox6!y<VySiU?YP- z`4NcwiE2Y5Nh1{xznJ>)6#XxaQw<@b`x3D$iAzDg!J*GuFL}_FJ16{2;C4r#3k5Sb zcJZ6o83Gxho_JH}M7kSSC@N$>`9L$Q9us+Q6~z<(g6=T3OFD!yyDo8w&r|zTu6~@@ zl>Yed*l3p%R3f}+`u^*}PYndbyeAsCH7Cwk1IX$$y0>Viv!zFrM$F_)G4XHPw(Tkd zB?X0e()VR9GvLvP=bhY2x)Rklu}%cD17w=yb2IL<VHc+%>`emwV(mrP2>4k8Jw``I zr}5)JtygSb(DX!*OTB%YkmCS@>}rtS#FoOnKf5eXH?Zvr1w<eY#)e~9xo26^C#LHS ziW>W7d;4+->3=!B!O4H1kO6P5$3T+-mDZd7p4Q1ZqB(Vq^(2AJ_8(Usu&v-nYzx7T zy5xiYmN_?e(g-nLh!SBx8T<?b>CCC5p3vFbYI!-cM2vFZEL3S%k_a(%*elQkAERL2 z(?_Un!+*zlvBBRegG1de*FEQn#ExxnpCJ?C<Vk<HH6F;?zT>PWX`gl84X4t67#l9$ zXjN!uAVOc2z=iYNPYorsD>y_;3&Whz{<7a|Zo+xg8b*^iC?}gXW`8~kHwhMOR!%Xy z%-{0#eAR>5$a)(+2tzrgtE^KxyIOp0rUz%d0*mv!=W}M${MxU{?8kf!a%}phuy#A3 zP{A>I{P%;iL7wn#IWZj6&Zf;U`<F*+GOOk>(?6SQ68mNHL`daHcD{^Oy7a2m9q5yt zda6td!{0bVO~ReSh5W30;nK-Io$YYeE2Par40=w#I)%z-Sr`RPG!E~4=ewE^+2D$Z z&F`TeU|F_u?d*TyK4X*I>~yg#@SEoJC(S!z<G01aKBi0E0{9UN!+^&|7>nhQ3|WCH zvdPb%f=Ki-JH1Af)p3f%{<K&#xIuOW-3&`NFpD}#j#n_xT~C`$tDouZA9I=;b6_~D z4dP%=f8ba;hyCnOkO|N1OLs@!={BpZx6i4SR-cn#GaZ7W@Jc9pQCC2-BL7rCA1U`K zlWRq7NJ1n-?+({NK2H`bixCb|3eHIxJw}a?r#0kho||kS%9$Gw>N{<B?!13Sc0TO~ zMwwOM{6Q!>_+oB*=4@$nVi#$^$u`Bu*jI#tx$Ie!iS@+HQ(alc@h+ceR!|6lSpm-z zGAnuFGC^6*9M-yPYVNGEMV@Tc4O?K|9kZR$vs{d3Uv_#ue|4Xl<?*v@zO0FY{tr}+ z2Wp^4ujjr~15*~$?39bBPuZ?r-xKR`o<Dy4D881k>$`d0=E{-23g0c-)}^tdJoG%O zsZGb~cCKKdbvQNx(f%kamp+H7>YkLq>z}tZM(3H3Y9^a%Z@$4Ni6MyKh=F?1{ufjZ z`qfdNqvu*~<h<FR5@Jhp1cqQOszv;V;K#sKJ3}uKk@(ZzFk4``$AQ^1UF9xg(?29~ z6w9LxWgVe5kb+*rT06Pn78!wTiNTv~G@Q~}ka%f4A2g|u41zzgppmt2CZnIIZLT-5 zTzc|YLx^N;qSDIODX0bCc;jgp+UL+`S3S2EYCo%J_=GS7T&xF<9;Fi<dR}x#)@kx* zb*rwPrxC5=D$uXT<b!fQX&8_#c~a{2{1I?xNT)mI#&yS==`-VNYoHOw|M5&qZnu~y zOfr6<4U^3(ddD=VS&G$hP{Em=@j!C)0!7x`OrJ})m|&YbD^(D^sAJ>YwnCAv@6(Z= zMacYlqgv=dbSx1y?hM&<ZW|BD+*r_zN(EE|CfWo-8D}Fn;G{73(TxB1J=Pozm~_`; z1=|g-#K?+H=qAI2x?E|#T3Q&v^%bcH;|(y_P${`zb`DSS2Gw?J&qh!}8wTDLl%drK zwkHZ7vOS?}^(iafMPw?Mp2F6;X+f9}Ozw{veD=PdPjgy+ysghMx=&{tP~{}a_e!U% z{;8}Hzs9W0E~^~q!`H|nl+hLsz<KJ3PIH_e*F8dcacI1!vCJjvs_d14m#<5Go~o=A ze>bz^33@f{G{>jr`p!3U&kd3NjA+UQjdY<Q$+0b<QKZkwiQl{~y>*wez!G@yAHtqs z^%|NV@kEs~d;7e%nEp}wcAk_|>)i&cC^^n;-LgQun>QslMWyBNWsc35wj`80cbTN@ zHgp^eKY7L2cZQB1qRP4b{iazi=frm6SU+2d365+5BhCDCM`L8$w7idi&Z*;Zef0`L z8#vk=CSuz+j7&{h85X!6NWZ3HR|gkeRKH<axwSJ}tgV|q_xG6CA66I1H2CnSNyyt6 z>Z;}2bWDLoxJ|SD1sX3y^jU_vo}$CMey}xWZatBLRqT~hD@XvXD5Vm7*wn1iLsn*D zC~Xq^EbGe-=oqUj)fSmEj-AACi2R&fe6v<3#-P`UMR*v-!#&pv3Yc_pc&UWRecMMY z!NmV&MmCb}%E9w=J{jeKjm5VqNvE><ozKr2(ulH{mfYE|#=3I<ojd!B?@}~=7;u8D zk-R&hig*#`f>T?4&iN)jO#18vr`K)UMU|;=5KwjAkT+Lb??2!qyo$LIZ6L1cj$~S4 zet<X%$xcYB-4T^$WMS9KJn6MtGU`JJ3Hg~|5JOL%JQ<b0d-v{3o;_)^3AvKyN`$NQ z<W1~r!r2z?xvhcL-S0;kHB+^YS%2z?4j;Ccc3Wngg>z_4f?@WPuSV%ugD!(J^U~(F zbM?cejuVMqS(C{VjlY`QYDcT62#5{A#E;Ezxv*M9-NYsk3U1(laY*ECGre{ZBHD4R zE2Sa+T|S97v-9Igf?$QgbmyR@H~DfDr=&?{+NSw8Zw@5s=7bl#x^K1g_526iHB$4t z(u3QoTG+h%SMoo8>9A;Ic+{;lJV50L;0kM{2lK1(k7!A($9XbIr=M6uI11;rUcw+O znTSg6xCMV^`PCn3LC=NlSz)vSzCsAtt7@Uh^rDOzNfALJ7!;Ltklk4gkzij8jkEON z^S{~e8?@idHT&IzyKl*tPp{?esh)Ef*8_?yaSVd_D+vy4tkCQzXeAd2zf$yl?RPBH zXTg$v)@;qRQZo|}v$4j!1xScj;33gqgL5R3IVB-+;%%v|WA;6<%jH=*21<7t6~9#} zf-c+sK6SyGTzWNDk-&1x(fl@j{MJ@)2!yI5vhD3wIvoHeT>{GlKr8V)T7}nQeF?3! zP=nJF;+t`JEeLO7$pK|sU9-Yaecht71uL@=xON+R@O<3Qk#a{5Qv_qH#@Sa1O4zp| z9Vc88-DdLF8`eM@o?3&~f3~a-l-}*<Q0xs!S(Nxo<YEh?&{1pbB1`Jujr~orND;X0 zWKx%{JpDh+?{_C`m+p`4Zt*!&!KQh8o~D*oTmaG}F_I9kSLjth0T<5!FF@+2d89&c z!)gs>Q-?)ic_4M>uaFe<hrFb2R|J>*LJEl}hv}j9u1QO;ytb$KTQ9r79sEwD>D$LB zIapa)jefs)@uL0LvejeR^Xb8}Q_LrhEuM0LD1sSr8aeC}QaxrKXRX&b`QR&_K%N%! zN>2-n?5j8pMEAM~S2unF+565?#5k^ASWX%Tx4(3o$rl9rZux@%F94xvw6Kr+XXg`e z)-ADdSU|QptbDK=ZN@kjc+NA;q~{Mt{Ym22%pLnpa)0CVC5m78@Hi7O>W<Zn8XSue zs;+GoCt})42~$>L2Hk?<+X8!Z&1#L_a;UpplwsE$xROf%j#ZiIx81AdAPI5zUQ>@A z_1JoU0qv%{6g`UF2Mv_0ZNEJuxc~qlQAuADZ-A(UJOWxZxOz+ODF96pFD!1cM~n7W zn0_1|DzK{Cl4;c>-ILOm<|8%yy!+<#n3sB(<fg4RLF}%3OmS=tdC=1Na2k3zOK89_ zu*NNKve;{^dn~j^q>E<KvL-l!7&R;*K5{ZBe`EYNNo`A_RsJi24i_pHdk^(M%gzc& zrx0vgFMGf-Py1LJLYcvO3nEzn{x@sm2!P{xArlzGwvzNgN(MAODGZhrt-g=pnCKG} z^UKf!GWdLWEs9x;0LAxaX!!5n3t#d&!BHK|{&Et%EsfN_Ij`9ww%k%6Us0Iv9MY5X zHqPX6zl(Ejkt&<+Uf5?)uK8CnFJkJg53xJ8KIhc;DAKxs^PKicml>@Bc6HTTO@-iK zr{ZND$7+f6l|<cggevE)yU<a_>%};s0JSIClCzC_tvy6!n4&w51>c9Kq`Om(tZ`PZ zk=B@w9O=2A@q4(u+x(U|z`!N0A-|O)kQnLF!6f0;4<M+pamsaN=R=w?(Q*v+2xvoT zO|6N9ox|85cW!~VMoE;_s0)v)(uJMNd*4GW1!I+RY`;IjiXlb)K+Nju@QX=@83Py3 z_I>9cuO@p1RW0zo&+vR~UWF_?{g9HGZ<MJUyDLjOt4>N(2)UgX(ygZ#NlT6cuq0^l zQ*{!Eqr^meWVKzg4(9`KIC!LVi9;71h>)G=P-O!WRt)ossnb#DYZu)4MI_{Z@`b{k z#SOBYgBP4+(5re)4ErdY8od0Yt+=mC6Mkj#{MH)cDuI`I8N28IA*d&J6>sBDG0o?A z<@Th7CpHgFsVOUXAg$zdH(OGsWmyVjYXKK;Y%+Xm3ljL(D|e+eOys)@j`>tZjbkmj zHrT*E+xCUdcrwX^N{20O9|kbOp6>G%4-;_}!^Lf1zMQrbIdS5|k8-bzb5)IOf^YxD z8G!wsD6a5x;U$t_O0rcR_1rHB!kx`JcP-P3fUX?=*m`0$ppZ?2yyiq`D_Dvo{qJfk zaQffEZG{wyP3>NCh0<n!i=Ul3<o0q69<UZbZV^Ap4zCI&pnZ^^0Uhu%ezgVQ0oJKx ztP%S~4-l@B{dd=>8UowRV2|7{aQTCaCE-rClZH@LvE--2JN|dIMa}fz!VQ}Rx1_ML z_IOc13|Ld!az-feiuhIysIj&Kcm7A7+!{Gc9rg?mmoTY)bPXM>!yQ8wp90-#ZRY{9 zLo%@-<SgKI4@q6jny0X`@V&_U35bTS{)Xi$(w#kPbm#xBwg9I88gA`Y4Z7y$yz#1$ zneX<e%`&OQ?IMp>EsM&s{!x<o@D=A8JjgKt8ajt_r2gQ?+knvfocmVW6l@@pJq-OM zy&>Tyzd2odttt%!Sz&u=Xy+PaLlPO2K<RG?J>CXZRw&#KT}SmZmht6QJXwco>^pY% z*y=frztp$bvaE$4-vUA;y?7`u0;yFxr{0qGpPgeP(M&QglcbKVeuEsMrZY)-&3_!j zVN*M~e|jH9Q2V#7m$wA$G?k~zxW2S)UkGlO{3=wl;sG+v2%CUQR#%a!9AXBQ!Ov@@ z81Yk%1>1nHr@dWYKS33&9h(fO@zrwi<b3M7$hE{MdhVg$B$Y;sE6mQf(ahXC$@ups z4k*Zyo`cXGx%wDbO#-lw==V?P{yG>tEk5caVrTg))#iPEXA#^W7{0<D+xigfYAydq z@>Bp1+u<K@=hmV%gFax-6FA0RQ&diwju<tg&m4VdIy{iace$hN5BpyK9US~)S#{&z zDBs19&sP-ki9YbRA)hE_D!*xSVRH`=0vWDaF3&$AFef2Td;iq7TmM$>BdqG$TX~-U zY$Y(T@{IFlO;{4z|LkfXiA55i!d88yWH*=`PYFzv*8n;gS&D%b_G?mc5crBmtBsPZ z$RR-}=YL!cq1->^MlOS6&jq`Pravs4^_UL46AeS@|DDnsuY(kzOIfsulTt$n$8qLm zrde?8*f@|Mba}NOg!kF<6Q7$)0<rJ@!0>Fz0-XQQF4<r}?_`-)G&4!qW-?Yqwgx<4 zl1&2OPIia?-F}g>dG+emi_&W&mn~NK<ul-yk6vaJU*fxYvcz2@ey5gplw5N*vWNXf ztH+Jp4@0d+V}bN*=pVK>f}~M}?3xhL9$+rrYN=E<z?(+{#hSDl#9y_#C%v={TfX*) zCTTV1#56p0uFhy9T*KtR7a1V8c8$VZf`4Obo~IkH`V>^#c(}5cy>dUtj=$LT7PM=% zf4OT(t(Oo(!KgH_kp)_>;$J+Tew|0Ix8~}2#p4j5P!FTS9UgF!Gq?Emt~uj@-MEW{ z5UMz|`wY<^?wbeV!HPrwZkx1p?c{#x&ErkEvKJz+IVBG1rTNpgnzO8VF+@B8IrsMc zt)fQ?OIJ4}BNhd7xc{dlH9(++3=vF>aZlCg$+~faEV|6J?i45b;)%G6GGF^VxBUUJ z$=$#V=al{(a-9hTt@u=8OtpQinx9k?%9PbvT-d6X5_^$*YUb8?I=YB1mOt6U98X4P z{@t5ANzGlPV-Mti9$`o%^JhFT7F?XN!L>L)<Q?T7a_zt3>x$P{y$Uv={&F7vEQjfn zIL~f+&9w2jo_f7GiS||T^+j!wK#d6E)W0K$ZiQeWL$d`gPH?YRY0#~$O6UoY8GLyh z9~51~A6OLR-(<)6?<@=^g4p6Ok=!Q4l{aRA0CoF%AapeoC1md5tkAl{Qd!ybYfg9h zU-066l+iGRd$#^s)c#x1HA^Z*%bTCGOQj-Y>iyenNk_vm$~~3F9F-^f+2{xVNCuon zLGVjitK((=1Jmj!W9bg5WQ}IV%w|p{R{vnr$;a#xB6ES@wC<7A6C9Oxm8@??tm?FP zlEwdpoR|+^;A1jL+W$Bv1C>z4yKlU6h2)&>K->ODqLGf8C<<WvjdrmdgN^%fZE`n0 z>QGAi<<{;>Rx)p0_kbCb(WqPOJydRUK`$X(H6B1H8(XjU!ZXE%=^1mCV_^>GJXV64 zF*$BCa*CdKX$IUHyaxjb$FYn?ngrERa-65?$j?iQlt{1{NKrCaGE{jRh>@@HIVYFC zVc*m~eRjO^g;1J`jmIHJd^NxpnlHwgBHE4Iq<#E{O0y+1YxY_n`eDp9(I<kJdbnc{ zDq^-uj4Kar(-mH3V8tzvN7d~bf5qT9Z#?%Vy-J7j@f$I@lC)>Um)^M<1iEDW_0Wq5 zKF#Sonsg47GnpvgHT-PPV#F!z=}o`e+@+MB;4x>%6Aor|2NFufO3d1FIonbAo4Y-6 z*%~)?M^5naG@eW@lj){8T&7z8G*(F4esN2<2of-Q_p1-)hyDCENMETl+Fg0BtMwE6 zTd@-jY;RT&nAQPcqubYyo)H1z)A>W<?V`~5CCQRTGG6Az*KJPZIo;X}cqr2tt+9cw zo&0Q7IFcMaZrUkMCyL`#gKq3Zg}A|?omm`UK;Se8%c3(((%ju5)l+J_rkxvBMWM5A zAim8avHUwn@DGXJW4bv&@z}!Apc*LG+sVKsSkf}ijBbDat=%)p*HeBGGWa8U2;F<& zUUvRdj+PC0X`$tdsqA&D)Ooq?44vrvrhHzU1O8_SAuK4Ib#EW--)&=!KUz&975`R} zZodFf#~rCe&%s;heFQT0L};<#UX03kh>-OzbNR6-HReSnmaPkC^(2vQ9K&#&&o*1~ zp0NAC5xQ2X^q|ud^lp%r*OG(4xwqKiuvf68wjhd52S0)59~q{J1NFh@+VV5UIUY@K zSBApZd1;u<gH(ni%y?TFNdH^GfK|(;P{<@k&mK^O<A=Kn1fpZe(|xhL&6qi@R{iWT z;c$_<8Prm&C>AKDMW71!r>^^psn6lvq2b-Fd#Lc+jNyjIFLsQ>{X>v0Q4Bu(&g6|} zs%2#=f*d}~Y6&VfmOEh2tW1Nhs}?1qBK!%%0suTcs@IM=Kv<}QH418p7amEY#T!qf zc6?GsulhHjUrRyY@({^mO~k2KBf{7Knb-!$QBw-V>Z58~@yo#%*)jkyOU%!2)vFyg zYycwvU(yC0Nh?M9w*O>>{w5oTdzhsaL9l^m1Sy`9t6fOQ;f&X(owR&ly;NXSj10_s zwf_u$aET<bA8+!+GbkLw5hGrq_CjF7=@JT_;2<jUqc2o9GmbSlczuBe095BUQS(1{ zEn~|g^_RjlmoGsn0kU`D4iEMncnNS^sklgycyOG#HALp{`56A^Eb!C(-FRORd!Fzv z&z#biTO1&o{dGUk%%c&H6bty-{R-`WrrPymvdj0+8rqGJ(d{QElToSAA~`!RAplyo z=Z3bS6NGs}))_&5DL}{xPOrQ|L^c$S5k6)-z7&Wz04S;^mH*y_LVX(*m-7Bv-WW^1 z%H8goC^U>+55K~krbMgZs>sZH%`UZlsY<HGEIALKQC!#&dPn~W%LKoGwXf<o?ehaL zZ$eKlB&_mDVd+J4Wp^4K%@WbF$ejd7{GR*=9ReBB;{p%oNf{V85s;Z+6zM#2Y|;IF z=K}6;k?4vzO9sSQ+I2V=bpZ>tZ1B+CFhVl=yM%A{KD?m58-Yw8+;mADRihUOa|iBY zceEGfu&cCxyuJ9Uo7e!fRZA!r{wE&EcFqHqGhYuRnq9VQ$#VQKK|vd%i{5i@Cs@8G z&f&AZVYjpUTk1(wVl<)ZxfZIP(Yq0h^8uIaG`=}~gfgKwTjZAhUlk0dU$K#NrN}E5 z{lK;4UB%pnAOj^^9scPZh!U_vo6uunud!|WJ&w;L7`_)@%5Rv1i)*eWH70@c>>!<l zf%5b3#dZQP!>x*^iNJ|FblON~@d4j`{Rt1msy8Zw?Tw7ND>}*|=%L}g5UM#GK!vA~ z0u&I@+b@um@l&$knZCfnS>Shx;Gr76@|lGW=%0KFxJ7{CQ+4rEdZV{NgKvA6^kY#D zNki4(RkN|k0QltqoaMJl#7RW39c0OcXR=(B@Jxf2my-gb@HzkD6%fTifu#^Z@Mk#3 z5#y-W;)t<iB3Kp=2!d*m;l*@IZNNGkM0*6Juru0AX81@b?@5-d!dOq;6WfiSFYFzO z4KPqMSM&LD0DPrX`;WeLC=c?D4%km5RXG#Lg!VzpE>uw>=r#AM38C$olj)YLRE|7@ zyYL<^%Nh&37kKU;N(LXG;N0!TDX{x?RAI|}-3w*bam|qZ%m+8#d2dbMa$+ht3dupC zm6g`;+rNt@QqVwjXBvVKe1;>>@ML!oxZ%>Z2z()QIKU~S?%2>0zjAV+SR4$?N>1QB z`L1clwv3(c(tc}JwG__wi@*OGv0PolLIR}BR;BB)1w{oJhZ@Dgzr1sm)hTF7a#3SW z4V}S3pn`5Lm~~0kY~)(vEGe8Pu7m+eg9Lz7_{FpP@I(*_Ja&jen0d(pIDH1Hz6L+j zXK{z8$R4fSrk2NCOZ3Ri?XJ?>(izLA<zP4Ege?`oVsij8Bz#4`i1tJNPoVFcw>WcF z{c`ck5Gb8G(WP3dA3&ln&v5~X;ywc$cxSoS;l-;U!Jt9p?Y06k#1u_@j*GTB&@B%N zLph%n-DYuJWp<Yx-18-Ltv0<vcLb(-?<rd5oQ)9EJ;b7)`|CImI-OBG@gk?T5DxkU z$KJ1M3>oY>bPWDiL3Kr-a%&9MF><%*Aua3NMHVI|R|jurSIXMzF(8xq5XIztU3#>k zzCPz9X&gRPs;9V^i6{oUls)WSa<-)Ay)6J%tPUJ{`_F4+2*fxHW+DM7cl}<MMdO2* z4WIRQ018`b|5&I{_={*)@d32DVI_ux!XUE+qzMbE!O)d!K@x%GDsEa8E`#ql>boqd z<`t4S)h7NuTrK<yP+5mdMe;EruB;TrS{=h8mSU*I`ySU5cxCXImP9rkLHs5qj&0E8 zQgy@cKb5SxTouD%(HB3m1TSFxX-fFBRH6R&(M4=70m8;*C^~&NftUmL1qkTLF)tKZ zg_P-_!9JX4NVWdp5@HDfdZa8{L{2t@ggtFqlzRl7NJ*C$s$LL-?<ZeGu%n$KkYbat zjx-9RAc&IO@Y3PH7C2zIz5qU6*t!3)rU8lnuZ*8%5{rr*l+1t-{8?2G1swZVnF0!$ zFDAEOSi5OSOsm>{c;`xEz=Q5fbOJnQ{3?GbNJR?{;GUZb!_+v>m-22)@#C<!fVGQ4 z1{Y_jms1{&QX;y`tTO_2V^!YQX_q+DClj4aNwPtAGLQ?78k`THlkUw-z+0SfY@p+k zee*cOL!uTyv&$0h-Tp^Pm>r>gpISqRc0rOl0P`d&NGFeAM1W=6hX)&5?J3V?xy1q) zSQp;D6T>0?nsEu5a;R`9)v_#g5+q9rmEw^lVU&tz#4$pdREu=Hunh;@Dkc8yJwlwE z6`piMdIJ(g7cjXF7P?oD{w(zsz)t=qXsYjnfRktl7f>ImH-mRls{j)p3Nu5CKaR%( z$HSaK8t-o)LJ5W%9?A6~FI_;bd70r)i3i$6z<g(wN>`@~d@rU@x+IF)=@9Dc==nR! z2JlS=p~&FhvM&#>(rf2QH`S_Y5>JLmWdigaiIz<^{7(KR&>5_anUI#Nj3tBuCwo-j zgw=(Ee+mAIm<-ZSc%e~Z#0wXt%r6gu1evF<J9dGs`t|z4|E|YafPoNhpcna;88bua z|M20%_%|ZFytEFJD?Ev{b!Iqz^m3IWI8Xl22n3pNL|8rP7KpI2PvT#me^Rh+nR=1i z_|f>Er6>NE<q<7_dAZE;;7qzi_%7kB7LWTW3`eb?1|H-JKsuo>Tkr{<urxgF%8$t` z`}GL=eeh?cOSNoj!51qk7kH&uvPihp62ac_H9_{yJ+P%VZ&Sdh=}xP%WR<~{eW{Pw zWf#Sv92V5$I{6<b2xMH(2rPLycpJ!~=bgpKi4`Rn2S*<Nhe|Lgghqt58*FF02qfUy zk<w3@D#JIWz_F1k{2z@th2srX)y5`8O;9ntk2gpI!!c%TeL$U0w9w{Fkdi(*(WbBm zaOR7GSD_sl@$fp_HL_;DW0&J-`NJ)vzoR4Erc+L`G*U*<NXVi%-|anO>JjiDR^rEX zQt3qxG&WnI=)punnF5BRa%)ml`cD6p=9({Y7nVS96FWz6jfuY!#;TPWr^2*4mx&>0 z=3(j?sr?pB&ZlWBnO0ZHoXM$r(RoP*5I^0GioR{^+AlEkiAm83KZp1_m2b`A9sGOb zVeC7DH#Q4-1NibW?LTs>a;I6+j_pZ%5#G)USQOF#CFqNkU@;@E@mtoG*c;z&Ig@cv z+>wIw1l@N1W$c#hg_lQ)gt0@~mKxs+)hcyjgLNGPxi|CY-)0vtN>My=h-XQPTp<NV z9MzuvBGraMt;or%2bailH;HbVzq(a*r_rlEE=GAa(~@nx`41f1FFb1&vt=*d3IghL zeAV$q`F@U2(BzhH_r@^82Cz`N+aQYCeYo<~>6ua7EEQgfa6b;ZFi6-9Yw?<v*!1Ri z_C{P0jhe3qlq19m-+NwgIkrL4F|%5+A>^>WM|5<%g^FYPih{w*WWNMWW1-uELRe66 zyK1D;SoJv#le%<)ibgil*SnUs4uMoFfe!z&lOH@GZ^TaOt2@FT@l(Jphy=xdOwH=N zc^+hb|06UENuf-VYZpE|Mh4utF5gj$9bK&rIX$K<uzwHwcH!ve2hZDu52!SR3<<}+ z6`bgsPhO*NC(*&Ui5{p<3>ssHC<p}C4SG5!Bd_gfU17f?$3Q)~+4J1F|C|T+3B-== z=Ljej+`tMYpO$p6SVb)q>DTZA%tI||Y!_iZKwxP}^Xnwv{uUtjSABZ{tY7us$u7<U zkg}{f$+u0f&knEIL<rdhqno*VggKyIw!~pazL=kgm1E|RgBTJz>u?c}6ZrVOwTekN zzsLzf+5v>pg9*LezI*2~R-ix;)$dnqf$G2&<{mWK(!hjAf&9JJu|*no&V9Ak=cjt+ zdWL`ISU}4~Z)Lw$n|Ad~%{HaVUV05`{hP=gL^aT#P}<D55?>Y($F&%C@bSowGQQPG z9*DU3Q<{l!=k&$424l+JU;U_x)puu1+|ZfK$?lp1eP38}t-SXcWQ}~*oJxopg+`l- zuU->7g@lEI77NBtW3?_E`))XC)6X^~AVhTq=Sf4CxvM61@a|&=OFgQ#PXYPXLGv;i zbRTl;HwnQIpOxm|SCZ~)-kus923AlLZ68Gmzp-e4c?2(PU_)PNIL&Aj=!84Sy_#{J zg=47~8rZ{(H$?-Qipg>Lh1?mO{BMR|wjM?V3Y4CI%cqht4noMY{t0b?+TYI0N(=T( z+ZvW^U;;!SUO`&;650vFuGKp^Ln@W{Enk7%$O_rCiEd~o-4RC?ZSjrV2fV<(etwy6 zwzre#M_ZnG@8d%iTedwytA3^BG}G84D5kw=isHCPKT=*2<WYM6trZ_O!0!)QcSFLU zkr>(C0?TEhS8+aR{y>Hu(YNv?P=@Vh7{TIJ8!^VWu8q@Y58@3kmR6fjj}o5vy~0~n z<mxO}sDJjdZ!ig3zeu+PyHGmo<C@_2Wx`9{W|yoyzb2M{+z34@hp>hx77uo9FZB>R zCm&Jy_=8JVVVj(s)J^HX?d7Sfweg$2ic>x&)%NL3Qf2d!>?H;Jk`~KldoNq^+@8F} zm54+3QtNorr1^zRQydsm1^~WiD_so!@v3D@%N6uyl>$q!Bw`;9xiT2&Sc!`ulyIJ9 zIfV{#*`g>Jy%UeB_n@jTNxGG9S{=uKO&A*Y?S8E^SFNfiL-5MrhxiIZ?2p0%SCWs( zBwq_Ye0s+O!2%pRu~ZuzvgD4*y(1vig9R`@DF9tZ+tMz*Uf2On5XD`(qgEROT>B0L zT$JfHmhUL@tyu>a?Z$gXoC`u9TR>Ptpg6QqZ3kd)<K6=S=!`@)d-47+ww^GQ=3{)C zWPP>Hx`hYU;nt%%kCSWS$1Q}ml`S88*}Y8Ol2FQli+Ho*?qVeeFIG#C?^udJ@_J3` zvtU7I(-PVWMDqtpZK`ZU8-IKU8;#J#R%PI^1j@hj^jM0&?dP!M3qR2oxf2yM?Ul4x zgg(Kc^?b)BcHqUE6i%a%+xXq1%Jm88>)<n(41$9_#`3QzeaRN+^kz0nafiMtA5mG| z3VjV4Kk)FHioQ)Ka}Ex(G7aFP5bW(2T*D~5=j{eqx>y+(?tj5wcKg(k_s~*D%zIob z0v+a*{l2{(3*3v>j`t$hfNV47JRW3{@xR!J))4siT_7{=@>U%J9y!2*-cX|~6dbzs zE?V&njn5fGdao1mvzOrIfSB;!A1y+zcplQNy83bh?P4y=7m3-oU;jf3{V+Qc95swJ ze(z<0Q-UQi;)UFW9MY4glwqD5fiJfl@4b%nikiNAUU+Q*|A$=g&F|yZ#4Sz*e?i!i z3=Lox#Dcn7e~DqSr>d9*uyrJ?^4S@n?e)a80@2CuE!RCdfEObQ$AeF!BYNq3NiOgf z_@GGH+*{LB6armPh_^hhz0UuG@T7vjNXr>h8drGdATRI$1@2-1;3{-|*DE~X`Dg1Q zTs5m+%UJ^C-w_^r%v(HBBpIv8?uDZ$dvq@C%$zKlBtq?@0pbxKx9liHdI4_litxsl zD<+Nf5;U}Za`Rp4y7=2%To3fVAwEhlh$9ropLe+%BbySFmWl*|kf{wmy3W4IryV51 zArjyDJkvfxOS+Hd8t*Qr?OTL0Rttr%ewU*d*5V8UprL$7AmX8B@QQ?LExXEr)T1y= z-3_P>cE`{J0PR&vn7&5hI=BQwLx}jO<Jt2iFFBhR@e!_k2I8&rdTw5C`LY+MpqKcT zIdla?EQ>v93sq;gqGj@PM?E7iik9QhS}_=!T7s6=h7Y6J`T)`}Pi&jbr-=}mfCM@` zh$FC8)IV*mN8EB-3P7BOihQ<9NoyT!2;w99i*;rfSxbL%i2mXSo<U{|CrV--h>ppj zdl?;*WgD)LB@~G2s^5KtLp&c3vn=(6_`TD}5d0n_mNnI*AKj<ncsY5Z<ZRUliqZb) zL;+1;2-tRNHjQ5(rL4$^VMS{09Ffw<b3aW(Tr@ck6~~T|-=>4-BtGqr)VPF!+1#w@ zTBE(%W$$V?`%P$tR&V21nNB(TimGZ=>qRjKZl7P`o$jC@v93$6Wj}sZQrG%aI=5p- zRX^758IMTs$NrKgnTYX+Q(_s<o65Q3G!DF-k)4w`jDbN0{6S@}+z%=}3AoV8$Xh<a zw(-jEBmS~9Ccz!DXSIe{{c;b>iZo^2mp*%NhDt16`=avok+Hm@`%!TveXYYv2Xsym zr}ey7t1zg~$oXEYCll=>yU6-noDl7`f%zimK5QEmeZ38mnN1UHco48)wGQDVm}@up zrndcv8O`L#nWXT`jVqe9k98l1R0zeE3cEg$oSio`sonVPgG_%tnR4#dOt-rOgXz@f z;XcXQKkO;%LSzgb#nx@N8ygec@4Vp?s|~^_?0$SN`*4~OrF(C}(eIA7GCmnCH&0#> z@wwW2(9S((PJ7CE!`x3?<6|8v61(n%JgtpKNpS=OaA<vb$@AX}xn=uCLvEaroK<8j zn}~P4c<@aH#=U0jw6as)WPh;;L#_^$@X;N-14I;;7~ZJ%y&o`$bO`eI?i?;iqr%t~ zRSGfoznsafdDV7zgS%i16)Wdr)O2e)HgW?;6TP*NdgDT{oW5he*JjvR=^UaBV5Q?2 zh8;DG#wjBoOv`KCmGqTDkKe>{Vc=dCHU8NOfyNL*BIoCa{Q|&{^!G;tcamZtmJSj3 zx<mL7I@A-$ii|2G4~g}XkHICcyxbG~P}Hc)cdTc2sM44+FeE`Dz5AZ&ua~br&vEqx zdNOvD6LfMn*sIppscyp^BjFFCJX6Jgn_79!lcKTL%gXuDn5gi*#)rplVhadj`|}^r zXL2$+mNXtwd)~4j>ZF&P7Vn_{(AYyQq1EEPL*GSO@GX=5I8M88=ah>BRfSNufL+-* zMROua@9@B3@c)H}hU2t<Hu>eUQi;+XedoX_JlaoF%|BYH=N_Zq_@eQXM0Z+GM(7O0 z4&&X_co0bqpKl0cuBCBIpLXjXatolR;<wH+Eq+0ChrY0qqkH6*NUm{OUs=(fFzK7v z<Cr4RAwz4kpXVEYxa^=}=&j#+G|Eo5x?8XJ=wZg8D(}1W8Pnp`bwe9)p}-$UU;iwV zWO2JWbd^y;F=Ef-o~JfbUP&%fCU#oY1Xk4!SNNOn-9By^nNs9v=c3Y-)>IG^Fm{w# zj9NbyJIePysBTcIVz{EUzkgC9H}wcrVzj^w&l#$EF-E(x>6pF`1v4g>Qk)l@Cl+Z? zA@>~Oa+kw4xHBY%Rnt<*oxVpJXNdySRP4t@EXgE-tabSZD{`xMdY+Lk(*>#WF8lVF z7^7oiXP{|)Kv!bHz-5jiib&5^W4qcA=7ns;4KyW3uOP~4xm>0FTtk_Y+Lki6$lB44 zS8fdTFSMqE_R^xn7H$_tg@3kCaqO;;iJhZMhz%Jf8OL-9iMVL*R!jo5sc57)!@gTk z>{9sV^&o@r%j{eOW)hwH9b|sYHoei^y)!wLjl0R*$aw;te8f`eeyHrhSkQl&RjZIS z$>0zk&K?qC+c(}q*cj796**NB>AoNyUx4}cF?40zFzg{-V%Db(_V)MZ$|kg#kDsNa zAk(mU7%X{NP<IzW2~F}`?}&D{%iBCFF`HPC2^v}c1AFZ!c6RL3^*v0-|C~M89WRz} z*KvNCHs_VC@+K3-6NfHYM#jz^<Ix588y85hqq1K)`SPbuBR+xxhYoA(YyroZ!Z#P< z5Vi(;U-_i(Uf2;rf7!S7tcPn-vOn7$z02${^SOUW&#_Ll{WS;EHaD@B*FtkQ>wzh> zHsiY88EWind#c?8XCLJ`=gJD&R~v{e@C$)FGRrC;=CvHQ_S!UF&h1E77VXp<&CfLE z`YQKe<SVYjd^9_;EEnPOtD4QmTQheXCY$KkZ6ecjH02+-bGziC9Mxe6Hm@&`z+1am z7i^p6C8vRdL&v*@n}i&@BoJ%tKVVxBVLH~?W+~&Fq*XUA!!bMd+Dba;T`JIYsgSNC zLCF?VQRyTr>3|6uDkIWzr;$k{T$4yN4w_%$pWa<CbwX0QC(DAS{Z01g5%)V@7wR@2 z6&t8wzGRTm(tKd7J!OVb-e_Ka-NY&&682wd@p0`mt#zHs=@E16z0%*!!++T+KOb2t z?+F}dhawxR`f6f&qKSfLCRuZ}U3!_`+P8EO`zvIMv*UgJEp*9k5@UC&qt$BzU&Kf{ zGhDs~gK*l@B}XgbT3ryUl0<+0MIyDg!CvtF11lKx#?fHEy-5D`EZMv1s;@BvbuQH# z_Sx3vHx{$jlGiy|uu|*0W$Q37GtZe^5+ki-*7ZALr(|7flEu}XGWM=@o${V}CG{62 z@tha63aavQ$D-2HMBG{3MTGtBtFFH;%13HFD7!T;i2NIm=BC7lbEU}}+Pb$C&a`;{ zF|~+&lXd6&H#tYVr&*?_D}!7FT)LSxhC-b^?Q`(K0Ke=bbE&aRkAqUGznfO2$&lIg zr0JPB+q+^3f&92DXwUDGJHNi|r|;3kE8kMPCew1<z3YEyl-{~fNX4VVVyGTRr$&i8 z19j&^TH}pd_!8U9Do9+M3ETYT?%O<HbjP(00h;pfg!bFvJojh`EDWOyOV75-w9~WJ zstrA07nG6HRcCw6N8rYlmNvs%Fsp5kX%W+yGedN0g2=>qO&et&r|;{p?$>pV0~Xum zlZ$Mmn^5j$JU3RIE5cV-?P&4YLtK0Aw#FCap*U=^*3H%FxoNL7EzTpfi*YJd2j7hM z6-3Ft6SY1t2dTln>U-v!_)fhb$D`^am2Z*tK|?9}JG(!EFLUqf4nOcS?vvEm&M-A{ z@YR<Fj=ZcF-ra3g;dnnX+Z_LTaEMXZpgVPivx}1_>`j}yZ~AF0Xo~(~Wg&YdCBBrs z{S9{3o05uOE4sgx?}(1K=hA$J&a>6AUG?veaOd<#T<)2CK)<i&8^0^w=EE7|-sD+{ zGfY&s^dz|p_TDos2{)eYJv!(M7b|1<H0|t?hZ5V48=vTNFsjgr7WqvXydAe0%!{*F zJ~rH4GEgYfWO4&7^%;Y`F}BTlJt~2j<4;YqKN!zOS$~sqheS@%LzkM&sf2;Y)z9>9 zU4&fW>-k(E?iA`xFicu~w5XXz2kj9ihTOn7J?FT3%TwVu4)VifE^6hWpHsOMtU5iP zW(O-JoNu>f29J`_<BP5EdFV+N)4ukM#>Bq*x+weB=ybtuyX-oLt>Q2xiCCDYzv44T zPQRFDxnomuIWvQsKGVQ7&&)~a1aA9@I)Q-)L1-k~Q20!`I*q&cw{LL2o8nSL5-mE_ zLZSSA_huHkL~Q1_{D;pE=cx3F9sXY9aHaD6A<;zx&>Mm(Y0b~8c%UYywMBnkdIYCp z=DNDx=7vfa5jY)8P8B(H7-K;@UVhdEtV3Z2RgMA*9w8fJChz20Ul`NT)Q_)lB&OZG zb>_1^GFW=D`2A*DR8Tb-`SFHMrxZ~`^|8}FcEiVBj69p|-o<~<V(V?}eh}zrOoG;9 z&|SBG9aTDq<6yQsq&|~kQ00=Oal_tvVA@7ptP^FzhxhjP-<8N!^q!NL8j4Kv7j}$P znVVxTJNyh^rvr5Dg%{=<R|@mjB*LTP&tke6tm5;;THbl)XiG4uFHTW(9Is`_O|@et zAEK=0NFT7^iJJLMD08j;5*fZSPn7tf{S_N)+o7M0KA!HRdHaM@=Z#1l6QQx%glB(~ zUoW}c_c~VcnOOrX;cOv-%`||CciN$6gW2IcN3QA?JR8XFv}kNKsjbl{?J5%5m#$S` zc|`36*lTi%IPTeji2h%mYB}ekg}Ks)&F9?SMmQ|S`y24R4D|%7PxDS?%6h!c%PJ|) zsdhX|y}mk2ohOohBYQC~PO-dxQ*ZJ_RLmIJD0I(v9!$`Lyn2tCAr9HI)GAuvLicG; z)L$%(O6~tnlbb$ge!6+nQ%DnLf5aF#jbfDr?9WblN6%y&&Ur`w-FF<@xA`<Sdx96o z{(KkCmlXVy`1kjDy7a`RRmSs=h*8*er%3R(B@sNJF?rKLbNWm}mDAL@ikQ(Cru}Ez z?t0eSo5|ncQ&}J<8x$V3+rJ__3PU4<riU9%M-mLGn|K`aRJ7r`pw|VTAY{UOwm~nc zj>dSRv2$Rq_W7pSv3lXm(FZFyW*3=oX5)Zqt+!)E)TA%pKJpusm12X$C;_W=3FlHK z!WcE-?bV~1IhmxnWmG^v=swl({srH{W6$QWa8S6?41VLWixQGyR79)K6!G3bsSmKm z9+K(y2({b{s~Y-Iza&lN;l%UuzNsk-&L#yutZu#rHJLg($)he~&f5-OxpSj_BDJJd z8;zLcFfH#f$dMLHj?Cz{N}st?wP9Gu^w6P0B}W;zZ+A6*z9J>30gm?Y!G+@YT8z7B zzq0ZG6?c_M)@VUA`4m&K$=FVmbPVRfxC@UfE6*0R&5pHsnK)gxZrnLL_J*g}mGWfv zggMLijXSYg7!VL7a_Nex*%5tpbY(T^?A=bqnT-#3NAGnIg`7V220`rHj%PDg@4F`t zr4<e@I?@U#8Gp%YrK|pw9m)r`XW&S9HQ>A63-BlE%{4?<a+x<7bieiCwo&Uxz$d?| z3EQaZiTFT=1el5qMtf-S>(+vE4IwrnNtZB+P<k4EhU5D}?I9=R<mFF>HyniI_zT8` ziB`)6KMAO&p;`mynH(5_;=$MnjPc`rSwvS*&fEC0(Y3a&6yvs^wxgvH#33voNsfE_ z@<Hie>qw0&i2~HYgm48MSSUvgz6Zwarq{RfAjo{jY@xz;xs&r3R2i`u+Y!qAwvE8= zqlGN_SmN{!pY^y<Quq`e5Z#s<Alp@W;q5Ny6&<=tdhuEvBcY6M`3-J%IaIR}VV<)v z*b1z5D6)7;x`WkJp86|3;0=3!4RKwr+8v&(a;P#jxn~Ri{jTusNCrRUY1mjfXs5N2 zz?Ta?g<56?c3Fx>>S;#0Vo5=a>@g3wxk1Z+Rih}<2j&n#gM10e&;qVpQPBJxm-WMJ z$zz-@3qf-)fLpk^os=6k5?=Z{5ehs1pF&pM{K%2tbTi@!%kBPC0V{j*uy24)gpNQ% zLN*Iw4T})eV~(h0PsG>fbkeZI90sC=6i=2EK<UuPBWV~|hv8U=@q=^l3(mjGQffuC z40{!R@cIXX54H)N))D>rzXXYkO~iaTa7$V4G>lcNcN?ATZMksQk0&GKVqZ6vCT(QY zal`}=2?2kd*q<EybyV`mD_|Nse#6`HhSZcrRx~(yhkEGt;KL>7X-#i;;|D!rdDruO zIrT~*3<EgcqJL`-wSE{7)(Hm90VudqNIw=Tu~hGgM=WmpQu_Cr^I>QSD3yJ%kO^5V zr=w<BsF(d|d!j*C)m{|e^sxorX-MdI=?npctv6QQ<xSoB&0N&z^s9ZIOO`Ath9i>z zXc21b<)5W5G%e#a@ELT$+4fW0n9u~}w^Kcw(QrixW4GyMXL)=bE(oKOfU3;{6w<+s z7-`D+P>2;OD_ju@*$iiu!55nkOJ`HWI=oU$CICclE~b#Y34I0=zvy4M0vZ*&T?IDj z-vw4ZJZb2KhiveE)UZS5ZGWgU_CMueT_LkVn`8!It?PISAe|rL3=H;_9*#dDa$o~S zdJB9yFQi#yArw>=7p)}DLI|6nP5qTFK<dvM-KHcJ%!PK*amQxCKNJUYbLHG3{F(AU zNT@oPM`!r~g7(SId2eBs7@WIszBX41!CUg?G+3mWBp^mi;z_+hP^n^4ccKx${6Uku z6d->Q0<kR)uoIy=_*78jd{*KY$S<}_94k97|5phAuMqwx8uR~4Liqo;n)LsEvq!Ha ze`c!RDmSfu%1zQ;s7LXQi>K^0XHPnRMj0_9&UDjydYQ>>MAYqQyn(v*A7<Fk=Qsne zj`j&CZw9k0ZNq1Gh#G7^f1^LaUzW(k_@g!GwSm2gu4p_!QS8GrPP23Ny!N9WS+y<2 zM1=yJ>Ax?N<<0q3e9O7d;ZIw*6@ox%J&D!(#hSbcHljjz;>$V<V)(D}_Hw?kt*gW5 zHfH{wswbhJ_O_A^FMFVAt~*}yCX2c?Yq(;ML*WO4OQ07%ZefDS<n+kgR<ll5{kyp| zkR?2psKy2ta442^dRH1FyR1hf{S4?Q-kw>3pwQZ^(4xAD_>TIU*P@`a#n)kv;9K|E zPflb(bHDW-?5Gp%wK!oyJlCgb&(%GaGZQ*2Ktyv7)r+es;A;{<R|bK8*<|sjRCjoa zOPhN&^jt69I4xCHbVN7VraQF%BaOSsnB(a0-?A4s7dp-e2*Gd>41QP&Hw;TzxMP4* z6Eteen3mvS)5t?iB0>A0Z!h+;RrdHnh*IfXqs)9Z)X`AzXsaw7Bk=W^`NorH=fV%e z7(QLIl3SihexFY;Fq87tnl)MWUFL}u`#3u0H1)~!`;Q^3@c=&j>?K{flFtjq#wD;h zKgvyuQ>=D>V9LcQ=F1I*bM4cEWjQh3%sfFcy&JlA5a)i&VtzK;;aoj4tC=;MVLJVu z!w}6~*a)`9;9QawbAy?e#cXyx8^Pw|(Is~6>IAn~j<?@if8j!zqLo)xRBDvgv16>y z5~90OpD7v=N99Dl+-kmw_M{{y=82^<HL=Lf;q9kcNv8V*8YypllWMJluG7n+V>Vv` z1X`@>#)gENg*^r8pC^~V%`75{_|o-husi*nsH(Q%%DH;lEBQ>oJZY_6p9d6d3l!XJ zkP_&Yp2GT>##H2yUbwt47&z9?Y!o7>{Qajhsa)J0`*k+leShhb>w!L8N@GpXTu4#U z3%2!MZ}<Cc`}~N3Pm7t1_~9MsTsqAuv~fPpGC!GASC(ld)Kb7^Y(B-@k{y}ZQDYaQ z5@$lek=bU{c%Oq=mY(TG^ZUlBISZw}Ygr@@!w?f1FEimRFkL|wQP0C{124<rZoecj zs)u@SHs#U6p2GzO6VzoT>S{JMkt7Fxj#JnZ2#*VY6Xr_T%pcBN9?dhY$lub$9JX(= z=1nGT-9VyMS)d(O3pL4{lCOThVA5K`KdZL9t43X1xhEDp`FLb*8(kFaf05bY-)%my zoBpn+%tTw&N2jT`XLEbgde7O_O=;zO>~0)$O6IJwt=^~In?99G#*;~XwAy?qru3Pb zbNP-VyJtuT>x}H2c&sgtCC`3--tm(uvHGB4+(@GKC{vR2Tw41r(>{l>I|p@?$S&Gh zI?s#=v2<sYi)N&iIwqw#MLs5ajiNo(?0*50VEt%Cj})n_LD@!UdJW>P=p@I}nL7_n zuz%5<nWWb)yqM&o7vylXJF`0Qg@JoU?h6;jx}mDe-*0v#rOn;EMMtXy9OP{D2uE=u zd&GRJK4I0T5%Y$TWNgpDr;5bMfl-(*o$6p2nrXXR7Qfgi<FUc1mF$hn4ad>?j;$Uh z0x5&BT{+{|n|`*9I0?^w)M<QKuer51b*ivGd)h{OdVD}T?t<YC%PQ?l{G&ciIjLRm z)Us?Q`EB~TqwIR6nER%_N^18cl*wpX6()BM_GfPx$~nbgOgmb2qtCSeEeF+PplaF_ z)z-&^&fw|oF}EXMD0*!NQCmV467UAY0aWchpT^;I1=ODtJeYo+yiK~T<(s$jZFfNy z;ps0YI*!#36^=Rol%0|aTCeU<;MEu;HZH5(nA0}7H`;0Nb9oST=H#b2^0$#k6BEbp z`bAN3Oy_p}Y-1Mec%|J@vb%9gOz>4==Ik-EnxCT6_YYVarq6VB*{RzDyCjQjUUG1o zkszJ6D=s8<9aU|C>l(?c`!dA^U(bv_r>&cc8gm&76dvcO&TK7pxfAWwl9ltB!APD} z-)c^EC)Jsq@T`1%K8qUAwb7=CV84{W(TpAR@zQrovDqW>>mPnffiQFP*ZR>9E;Rfp zZFOn6o6b{4F-=M6O|vmxuQ->`mVbM0vbQ{!FLNkC^xLG^L^ns)R+(uRs}YsyjKf(p znUjxr-h6ZH?}^KmEff)&o=AN=Y4~%B&F0bb^k}8IpS`mq3Bvo)9Ml0j-8=K{UiLTO z0v@&anbQp+M#l*k_yvQ!@n8}oa&3MSK@OL<b9qCrD8<;P`-Q}!9{qlw$4ueEH03L* z?U`XK+A>zzMi){qFJB$g_CaX2F`)5A(6qeKIfsUj#QxVrH0<w6-&~0u_hEIXsGp0D zyXKd;g6KngdwYvZOSdGopDpz$&x&g;BLAr;d)8a(IqwnACQhi>0in|gLQXCETxOoQ zU8Fqo){ba_3InfZPm}26Vc(cmUz(DF>e{TigCabMAUYn@GQVQ*z1h`KobH;K&~>%G z>-vw$|D(Mx4~Keh|L>3}TPw;kttOR_GS;D^NMTyZPPPh-vafR-;#8KRQdvu-vXgxo z5mF)hI>tl>gRzZmw%_|>rjE|(InVR`ea~}U&-Gm2{?f(g^La1#e!uSfwpOj<GDXEu z&&Nc7-6O}d!j(Z!i)*6@EIo`MgD{O2=$B8J_w^)p<IO~y3e}l9^D{*CQ$Fz}$R0PM znNP1^F+z26pg;FZZJ>PFWZ*=Rb$Et!iePAqP}z)SX8XegYD;v5O7H9xH|%vWhH33> z?g(h-!d%S|`$WsYG5e`?c}qGs2_?j_^9sL0$NY3%rC7By-jzW?Ctp8<bid}^GM0x! z(uO}rt6v?igsDi;2J?lVk|I$ii=XWoY3@<2XHe>!{HewGrxu6f9dFYD7o_FMJYYWE z@qE}m*{McB|9vIH{AhiwH|=o<4D|6Hu_u_=)9j1<rfQgs`DjA9q4-8yrtv92lt8EF z>-|8V9BwpE;S&;hIMvl262)B5v?AUpo>@7Xz%QR(qUt-*f_bS&y&Hw%hxszKn}}oM z7JEkyORWU=bW>ro%`J}fWa*zbxyrXUuN}##;c|+yI<yv0{R-==P)TFqRKDK?VU<2| zG9&qV0&@z})DOp>j`TIrAvXksjEPG44?Lc^l&!itXr_!v0g{HGf@j(-mKkIpp4u{{ zV!`w$r(0!~A6tK1X}&e8(%2zQeEfln&-~zK3*Knc*<#m(0kzz{OlPz6m{LkJv^de< zmV~U-(HK59RL&DZ@qB&>w*L)qyA=VhtY;`m%(DQkY%v$@P+_9)d&Y^+19w0sbhEsq zpE)yvgs@OiNiD7~${q8D(QxVvJs|S2Pf;0#wBU)GdWaLSIl)+3-BmOno;I=>67g`v zRWr{?bQ7^QKbbZtEUev$bzkvM4t_>3)UmWxf#4x*YQWn*S5L9WDk5SToe>lyKf>J4 z;XH=U|8p_5eU10YH9+Ctf1<al^T{uyOSevP;XYDaZLPik@u8Q|OVL0$QPrFJVcru2 zLXEm2!jCo(g$nYs$gy86V3fXE4A^g;tvH(3ATa!7z-=J(MEc9LahS-$dm>hd!3fH4 zZG#KOlNOu<rO?XCALBeQMKn5@uAw+qxfgrt8IDdBdlyv!MKQ{bu3}@WTUMV{cD^=U zhrpgkw6F7;*PRO^G@g(-9^p1~DLLYuocLG3?^>u&)APZ1?OVoU>OJr-hKf@KnwL4_ z{rc6cdJ3)%Pm`HLp_#73kq3`7F=5qF{E?z*y|h_G3kTfL)Z3}!@`to$KPtEW7A^xY zJfb$U;jqtB>Q2nZ;WG75aTNu?oN0-G7KR4E(3fPtqK#^=U;{MbI8VNsms`=r_fKC^ zQdFTTv7a~|@)R6a*wD6aukq{lJ#@|;wftJOVOoK7F>3XWiZPFm`i60H&6lj0bO8}i z96iDa6tBtt424(=O69U2^A^Ml;8KtI6f6n(mx$`@%RjX@pA+r8FaVh*y{d!jLPSC3 zDvim1M&0GI@?A)W_<N1N7d!$c$`fg$SPSDajN(vvAUB^!<CE)Fb9DFP(QsJVeP13E zGRn_#=jv42V#%$``0%D;y(wz;2N`~{(lGPcErAYZE5V-W=f7Bhqc?A7><$AW?~<`? zB1_<FL}>W+4ZKLhpOcC@rG^&a=ZUqUug-AEC{XRWR^KW0v|Q&|Jsj%70?t5u2Z*AL z8wk$n5l!sqhe{Y^^B8^P!Wyy(^FZ>pw_rv`Q^p3&5P`cgP_RxA8|!X9Kka7Nnup$~ zILy>R<%*kopJeLoX~r;#nRRX5pcfpUJ(E#0QPRN?C#I-G=(&g9T{U_VAQbHD5;i|? zh`%oY8hF_eTOdSlfEE-R-+3nd3y}Lw>dx2dz943UMlIxa54NB%2V>__5}uJ5{U`7| zAmv2{6>q^s%tY?&%uL9Ob9CTy6aiwWQe*F@{prbmfFUl2J$}8l&%28wQcnwD6>Z+u zCP_FK1VrUvyzS;I3>k;SKaj$ekg=0tu!CalPpWQJXbPtJsymKz&V|6@>7`xyQ3rWr zY5gYpd=~Q`vHZp!y__zU+q7Y~)4QDm!zw6-^h188FvZRFj6jKx6%|06Z_GQiik%JM z+kO(Js6?4Z^JiC02uqunDB`?;0aYo}WYci2Rao)Tul8TNp(ow}H@4&9wS6$a1C)g4 zubTxnR6Y~dC(9EC&cyl8_mi(bWt7h0n(fV)@GuUzwwU|b`Nqxa!&tAeg<_Pl9Bpz+ z{b@sk8mVL^Drp2uuu-J8-}C{p0+=&S|G=DihUo*9?l7Jt?Fb3ioA&g9kZpx`q!t$X zsOszWl@?mSvyaCUgr>DGK~nya!RCv+kd)uL$#X+{bHj7oFtB9`&IK#{22}6X-9lf$ zaJ5Ju-mWd>&YW<I#Svmf1jEPn-GCX{6E#26(m>f<^O2On-|RpALAL+Z@Gy5K#mH#x zsZrm+85q-XK6wM)B%ks@&@lD<I`<xzl&)X9uau~S!Vt(7ZvEgK783)L@lOK%_D)M* z0ChU~jIDRSS+|6;VcI0hZzt_SS3~nvF}Ha+LI{50s*^6!!r5GLEGoGrehwph32%74 z`%1zlq5Z!5&02RmN75?2rvwMW{72Le&8L#-2gQ&J?~r)s1F>{b@eflMz#YFG`v9~9 z@IK+FaFc>$<Eh1VMC=iEVYUHe^_^R>$=40&Q?T?^ytsB3#$ts9(DaM|*G6iu-|6{z zZDc3t-5<-gIT7!Ku-aN3ML?jF4373RQC^cN1;42scwP+-Jj^Mz76nA4I#onlLcebS zatpY{<z5QyT=)n_!g?2GJ(4SR%;Elv(+NCGmtGXNcyG{Z2TF;D+mV8a&-kaL7%u(D zxz5PB?k#jN&yKQOxgP)KQme2-Z9^L%(hUo@^@17)-0T!iV&m#pfhG-`du-32;L;DS zvV*hTCrhBoxg6fD4UvyU#6=~(lZcXR3!fod(7ZjT@nyUGkPfqHgaU-PnMpn_uRFv# zTvegua#Mg6NjiVEiBqAQh>E+TC%Kl)hna8QHSBK4AQWYO5!$Q%@Fhd^xV~pUK7={n zgt(l$sIE9!ism((@ijg>HGRuvKab9Bpk$gauq0cL!Rl`T@+l}l&QQB(zjDb^RP1E4 zWiDaH-?`1B(vUHIYj`ojf2f}@fMJ|WD6e&%MSIHbT_Xi<>F2zv#9-hyE9(~gIy&gx zHRo-5J5NN5Wy^Fr9)ZO6U6sW*!5b8H%1Q^w_{sd-EZXFgy_K`wW4Dpa1sNvX_p=2m zC9NBsphNggGeUqmT8dsQGh8pLQ?}Wq7^i^Bza*rn(<^wQS6Fm3nIWp5*Lyiewm;IL zsgA{^g6{i1+yqk>PxthSY-YLJvJhxGu{JXrBxPdi!`VU{WPtV8w1ism*#ZOIVgf@9 ziO{86j$Nz`GpOZ1Q`=yOo%}Mh;a+4-h=i}_{G0p+fs~9g@2S@f4UILhE#oCV`bDXy z`fQ@(JovH2eGz`MDVWpDOZo^i7nAd79Ayy*(;SSSU&JkF4rIReKQIshK}UMwe8)yJ z$CXI}%2mzk)U1gdi`bZS6;iSK>JXUs*`+gv&1eV-{lFE42wNjf?yk^EQ<RBDcI|J# zXb4sGYT*=sJ5T-2tTPz=FdFaeTkw(^?240uCu~8^Ga~pz$WbWdx>>)v_~9u~T{TxS z?MIktM#@_<ZQcNNgu>eH^74IarF|V1HyJfxm4JrG`_ekhT`iEPIGA>T-Lxf98?pp1 z{n!$GfmX)5kZ}YG8mX`oe=U-x>orEI^eAJ{yUvebfo+7QZ7msp(C<L<h5>v=k`+^P zcHD1EdcjQBObjZLi-JEHsmdg|<%i_9o5Q_2h{O?xj5W;pbVTxp*$$@$XTri>tn`x2 z^mfT+dg}z{4Va=@A@Q{p14VQ2f$mx-mrM{iG2YF5$t2L7e8|-hR4Uk!n^%H(&@|4- z{Z-=b&%oDzb}{O3-fp1ewx2zWa8Wbse9%j}dbr!>JU=*M(em@LP&IHm%?alFA|MKH zw%9$v5X9!Y_sICo;w!s>AvNR0Z1*gMg&K6vKjX$SE2{_=$eHmOqnvV`sj=Ny)j0&+ z1C@Z84rTJ;M;2rj7Kj*c%!9>7)UycElA=jIN;|a$D2t}o?={$Njs*DcZ^;46F-AR5 z&><<}TAu;l)jaEh*F5%?zj)b9YeNV;-nYbk)FBzaQ2}Su+%+wT8GSktgEt2p_PhPL zOAyR!7eRV<Q7d6GOid@RB($QAg5uyi>q-x-m)+vM{!*2lR?+!bYFaKTY%zK+Rt)L> zet39<0ckP34<Gi!lIMf^2ZTL?eYm^u)X-<%{k%}j#pzM4LIQOvxe~=7j=FZ5`;3bF zPv5%LTmxJS709&!Vn?dW=C<^jg7`e1bD!!=QJOEXKlbfS_+wS6qrW=Oq8j*gJ|)e; z3*&XEo!6~CK9DQDRRIZ6Wa3yh-h7>Vhks31(ZCzJ3z?Vf*<e!H<29H30g~SQ$mtsm zAs%IZwu-xOkBJe~aV$d2qe3pXpEl1;4AvAxs+yU>6m^97+?cO_Q$G$FaX?|S`>=fi z|6M<M5UOzbTJdo^22jP7nNtF$%;zqrWf%60FD7jIU>HOt;)KUb$?=O-!~JCc=@3Fk zQUoc7mYP75-O02}py@uyGyvL5Ul5E#J$pXW@^C>Gb<w%LfuYjlUo-0JM~3OdwTpQk zThx<;3}^+6OOI&fWKG$&(Sk~SLNArPn#rKZv|ip>Gv9yIu<d7=v2nbL<UhL`!O)#9 zKDO;;gfX<5oa@-a`-zrj6lJAe{Tg9&+7!I04a0l9n3`{W34aIZgVA>}Di_>==IrbY zKVr*rNOxF`i%bHB=r?+`5mKh{wi5S7IN>_;)^oVoA^Fg%TS6f|<HagaY{~CFy5Nl# zfv8SD*Kw5^x3~{8rvq<8S~?|*O9l%j&>AzD{@gP`N5*;E@rv@kL~i^muA|-_u?(tu zh@Lm{ofEBK@-fD8XXhX%^V)I6c@P>Jc!10A*@&cHZ+1A;I}?lu$?#i<DSg(}i#2!` zcpAh6?gEF74e>7l{bklqp8er%^)U5_1~(<QMaW~P`<?qz1h!;)O^xl)mOyxwt5>(9 zAJBF%9K0D>G#YPxigd4azFOsVqQ&}EyrC@$TL#`hp#Z<?#&JfVSj7_#D7)aK@8RJw zG%|A2WaioBS`yx9+CF$VC;8cl=emy`)qd>>LIL)5TKjH%|C3UK&HH4VbSXPviqfU0 zUU<Z~&ymymJ(M5|F&w$s)&U%Qn$jk>z3t6q?fp+?YYSEhJFAKJR5kemZ8}9k&ka!m zq6{3yvZvDtsbt1M$Ffc#PWOk0sBO+YG2s%KCH`+xEGUmM9T&1EqD9kFr2X;5sF8*8 zJe0r|k(W*_<iqPV7MjWFYe=c3`c8G00r$Gz`wOn>#^NR8g@BF!w2%J)yJ2M_6#0RL z&&Kn_z9!nE*+z^AFk-5PDxI|_Yd$d7Mxrc@TN~WFufX!U?WnR}a%)1YBb4^j2cBtB zd)yl02uWwuH!{3Qb({)bIJue-8UI0i1r!fv%%;_}mudNCme<~3PNZj247!(m?8^zg zEhe&?8;Hn-XU-FcqkM#)VM(0u%1$gw4z*@Uw}MGAe+uS9!Iu_pt;qHr7K~BDN+}q# z{Fh9>^`Dp>A?oWG1Zgslb#>^=b&xX)MUVe1eW>OUyj_x&mmzm&MfGP>aN5_tps9Tp zjEII1c?^yI+%2-*6<A^CI=qt2D)6O~(!(L~VG?RZ1SICsRipV1xcd5d&#6gd_f9v4 zMFZ6|*|)F7`3&&d$&5+<TnZ>xESn_b1q>~G&Ls#skZ^?C?P6OPlnoX<-ROKx@{<`4 zzdqo0%t;OE5Wv^h;J0(KTbhgj(LW;F<+t0pDLs+SRuS8wNZ4cED$&ZDoAy@JVM?WT z5~7}+hz=^9^S149BjPGMvaB5f&0b%$I)<cQ0zrAJkTDNkb@5ji%YmE(+J$46>k3KX zGtCLr6yK_Of$lMpqS?_kDQUCU(t4i&v0_p~z6QSWb}Z^o>UDd#WkJTdMQ$yI>*TrN znL#yKgkRc}X+yr6WX8GK4!?{g>*j$sh*a;sc=$0Cj2xO3=~)XRiXl90+hU62-H#=? z#6Krps^@o}KMZ!e%654EI<Jqppd|SQ&W~(nRX6Dn>^IvhvlDh!_HxUMM|J%uRUs&5 zwfJUb@p!h+Vo?@Sb_$1%-yE*yeS9(AXige&-2`2{%Q1WMxfLX7222cAQ7?Hg-&{5} zFa`Sb^KA7ywu=LLvcNg@f=iF|*>t$Nvrl;qkQ=8H?ao^64&>4bK9J@<2Ya987=r~& z&?5oP0h$XA3{1Ag{Gy3x3zwF0oHdY}-eTRGG=V8mH57R2?K+Ty>3{M5cz}CG$k=#> z;FtBzYSM;SW!u*r@VKVoI}eGL0e2pY72@b2*Y<S}0*a2r2)Y>~@hes+R_Gi#d^VI_ zqIS^?aHCtwxhqo6*~hnwveTivK;}d0aMbaGZ{0a}0A;#;kLDOa*4^;g@}nhomA=Wv z(Nk<XSG!ydbcDMWx(p6^cPW)h+<2Jhqvq(ryz?N*`t5hAu07X3U9o(Mqf-)1!6|(i ziEd;euJxh5bDpaJ_W4^ofp>a96Cf6kOBCSBj}=o5*XLG50bjY>^iO%2b6XA<BMLwm z``$hktNmAQj|J`bs24LssU)}WkZWE#DfRU(uA!bl{C&$CpWYR)fmr?t5P$F>5R6N9 z{8kIdGGZ(*Y`6xxq}7I%MRH$3$O60W-jTG4rvL}0;87jA`O=%(D0q!@&lzbix{3qi zqpaWT>({e)b<QMxo!<5d%AnGZs-m?MaiXRmDjt{B?J)ph)20T)AH)HV(mgNkJZMjA zRZR7G;`NX?>TNtYe$Hc*1Kv93Bq8rGCwjaKryilCGB^R~I2dh@Vy)B?idt=d#QUT3 zntwhnT7fU4%)4G;x_<VlOhz&~x7FnUl5mw3B|<~i^SS;c<X#>8by3vR17wa0W-5j? zADIL08n#rZHv=0e%r9TD9hg#DZ_n;|4P7iodUrHfd*NcMRMIBJ;k)_~A5}4)vmTXL zzp-1xZ<aD1joKyd$GER}Ft>?+tS$uFY@nBelMOBm20fz=tV})Uw8uGn&o&ZU<{W@D z?c)<)wpdS9U!9T%d}+mB0#@yIQsoOkr>u`Q`vy0>jfIku<io96pQy$=9=1E1X8_^b zs+yt-L%cI6ERI7U+MDZ1UTyMM=Da(`8Ac5#`uDg0>>fvHdoH1*T6fRuVl475a5|o< zmL53GCIko^ZT|xc*~5}U98wc=5Kfm3vt(zXz(6bIbKtb%x)v_icT-+J@;kJb!xn_u zr8T3K(V>7p+g;=(Pi_Px_QbV9ku59?00A1Gx_nhMAWG=5BRe*=5o%5MX-rO$143MW zhg4-}XSFmE&j2#&2Jq3r5;Igvr(w?aldC{P^MLEi>1rU#z0?ra97h4~N*#xXvQe=Y zA>`_&XF~bw6fdoNZ^w3BA4BQ@ClR<~3ADN#Kl<<ASnt1{ZX(G2#IXa43*2dOPfZ1~ zK1awP0g6e27>v!n1}IF8@~e^j1fe?PaF`rceX#9PJ4iWjo8Ov;u~OsY@|DU<h-1)5 z>?_{k9mK5*bLBidt`Oo_C3m_tHlK9q5cRUb%J)EZ8wc-q>lNYBSI!{X=_c+5A38c5 zbd@bS(|ABcJ^Nzg6JhF(j}PVHy0MB`%+D7ah~`(l3ckeVG<$0&xO=}YTEoWDuG9j9 zr)-`+6%Sbvz<{E!53da>(UrRV<0&KyymOQLt&L0Q&ut)t?f#pk0$gM3Be1BXQ+v*? z0Qbys@XcBt*B5{bLlnyTnuQdlJOlY6G_Hfo+|y%vhSj5M)5aG7Sl~KfxaUyiDKN2Z zB)OKo+8t1v#GgM2X#P?T^;i38r;{|m2;OR_hlt{&2Jmx*GNpo#Bx(ZFv3pzC`0YzY zkXF@;()bA+J#WWGO@Qmv=Ku-|jI^jd(fbwGNq|ma>OunwbC-3st(dEKiMNDh1j?4R z=Fx!ql_-5yIT#=y3`PD|6XRi}R3j{d!VhmWdA=2jw4_4rbIOWrfN=Z>77?>KtwIT8 z$OnHJzYWTiz^&^CLES?(X6>y$k|+<jNI9v&j%B33`Wo6j8fOrRJ?38>0fXgUL1&$7 zg@M+1C%zz9ksOUgH?Z}#G)I6Gg;aP!{GX&^=r0<{PznJ+JL|lP;|+2$?2ab#fsfk` zohF6>@cFd&mFkr@A?(~;eGzWfdp|*W@x8~Tuk?%R8wX{x<3=Yhf=~RMU(>hLcoIOu z?LR)aBNVIZb*-mD4a&8G17Z)U%Y>3h019xKW95Mjz?igqy@m+L?-6H_=K8I-fgo01 zcN4UYIQ=$VWJ5qbP}#$w$e3MAAAbRT`>p=+(n^*d_2!oRGzm`qDr#w`EZF;hmoQld zZ2P~B{eO%9vGH*MGc&WRx5~~gGizLHfmtK3#Gb2{XbyOjvPELUR@q44e2VKh)x0+@ zryO*E#!_C~37ni`)l;fK6iu~wIC8{66DvFE2%jb0dQt%p;BVr~C#kT*9Rj+EOF;X0 zh)lo7Q~mGwaEEi#_Pcd#h5Ivak6%MG;gy4gZjIuXx0Mw`jY+&}=7Bpj5|ugTdKF}P zym7JdSP!l1`B=C15#7``x)MWWQa$d&<fdGBtdD<SS}^u}pUu4c>{2b)g*B>k^Dcz0 z1oLQt@x=BqQH2iI(hCADFF?I$Y<W}!QartEDA?7UyQKe|Ra#ivs~$1E7cL;!0jyKI z<B1o6FgZ&4ZE`1v2W>c9mORK^(M3Y>gp?6h>;|$}L@ppEqeS{+G3jyU_#i1*2i=K& z8&1+->FyN)1Yk4qX{WtGf<~~G`&fz6mB)9<GT#s@Y@-|WYJBHcX9#R)ldyO-DGJ8v zeA)ECk8VatHyIb)&?Y7d!utAO;*Q<g0rFj6ErPyX0YqUnSo%EU-f)heAZ~|a8Sc3w zI6c|z9D=>nV+B@=X~S6pUiddwltYHFJN?Q$0sFvya-d-t0S4eFlT+Ds$9Q{uaHWLt z6!L28b`eo?YM!Rn;zYRiFB;surY^O5gh}oMzL?R1s~seYk6UKYOLk8QTL^pgec5#3 zYE^2_v{e^+{CETwZ{-tQmxtS#pQR}K6Gz-GXB_N`04QfV(&3wvTX8A`ZMIMgiX6(S zSe3<_c|OkfZnEn9Y-^QVn#W%}TCBNB`y_-p;N-f3C5$^0Ey%pqH4*$#%&M^8IIr)M ziUBIMQ`xR$<*RK#<A)&)oP;7idL8VU>NaV*B;Gi^&Cy|TZQiTg4qu*)27OHl7Mt(y z_eVMwGxMx!+UF7J6$<am*`#(B3S{2^_Qmgz2Ezagb6NO4<JYQ=#UJilHE?>=yX_Ou z|3!nyW9nN!lX+p`=BHd@wH3KkA)WS?OMegk!iFU><6BvT!HG*06DKnnlBD2v-A<Xn zrM?pZ0UU;Au6~{)jrJAQ-RO-)y`K&_bDrS2s|!F(HvICY9GigCn09Q(UWKq-y!V4r z{9WCYQ_=(7`AtwgB^TrmigT>IxqD)!pSR+kFk_dvv0+1gjAPHVG~A!Hjh{G<LPluE z_xQp!rY<;50C+=PKUAF|5$^xtO<{P|o7HQF_yQK@RK>2u%I%FC&C*7TDs+0*y+^5n z-qs*1ce)aIOxpRn=FIv>>hih?YSL+HwoNTVUk5nyNls|YaS~?Ld+($x&xCOY<+jJj zcG%qqHq+Ke<vA!BzGj&Mg|z$+>r_Idi}OMaOtx`&0U+YwE^@(2WkaxI7axn@hYhp@ zY!Fw(J|0nY)?vjy(5letUG=eFG-|o76f@GD=cMOCP9<qyuhd5#3^jLht+ltAXB)$< zkXz+`et8v8I)|WIiLB{j4YgTrlrmygp`e1kL-G`hT@f(COI!FXTCpKQRlLmtW9msK z<z+B}eC&Yzz0OGiDzXJ_HZvV-vt|2>4WFL#+hJ{E`UNoc*}nS@WS+S?|E*?-1$szO zR)4iXQQY;F?}6wvetu>1-hj)%)G<hkI2TvdBRUwYBtNd39PJxrHx>2>x|Q4a%BO7i zR@h<-_U!ZV_v&!Wud5i(z)7cQzWmzX{x?upw?6E^cSW9syflX3+;wdUvyIgmhxUsx zo^w_XH6o36%{>=c5pZ*js&l(0;rU+l344z|M$GjaDrpvt4`<^*b50Avh9zRqNa4t5 z4u?;a*X>0!kOTAd$|BJ;+(>#JRP1?sWxUttPUk9So$g%cHL`T&{t&Y2Q@RuA#RLht z@$js5U@Rx;QtqNrRcGo@;R5wN%zV>*88Zom&TEwuuaaidKOd~Su_EACo*DmQoddBt zXq-%H@x$9DhmEa8*cY?`Xb(w6O*7D|`>b3yTWA~=dcf>+A!L6bKG)O*cGSZ24eHR@ zOJ{l#BI89180+ILrhGe`1FsSatX2BE_11%8z7G2+Z|J3;q&QB*n{8qE&L&jy?ltET zbu0o&9XG1``<6N&(AEhR6cJ-Y5=Iv!s~fGgLJYB_R;!*ahtLTgv2YDmAp4c>FB%rW zC@+(U-*l#rK_Ux!m|rziF2Kzth~(k@QdsI>cW!wSNCLN;dAlfc<FA|^G1#KIWV8(_ zLMl;Ocv%MEBu{{YJ#yoC!SqYleZ}MX)*V+HoYu(g4+Kc>EgUi>6Bi0*=Mceg?<;-B z{lk$LVlq4TN}jd8CjIf}zNcI}W0uVPfK?pRR~`wE7x?NIxsz_hgaEF0%6wJ@b}a&0 zOSa}z_9zKHS0Vd$yv=Ogi*r>})$!S61eoX@PELWN6}YZxS}+w`Aq4Gn@I(veUS^ti z6T#=Yp<~X~WL=!<>b0Qvr+tF=en_5M4Syz9j`Y_A8<qk+7q%MNV!3iioK?HM_BY_~ zum344Kd4+MBM8sF$$KmJmksnzboAe9mKw`$5U@&4cS<>^<^q~wzyqGC;V)k6pE0Qf zjYIfy$Eff1DkO@X?lxbXQc8sYgW*d^#MX5MW0BnzfjJV#;X7SV$CW)=9k89J1us^- zFdlOq7v7o1Q+Z$&gdB>ut9S+SEozY85SYDspYOF(1q@<)i0z5{&ouG&QxaCU#t_oo z2ScM*1aPcTrF6&>f<K`7Zwc?$(Qc<8e6ELiti8O~GKKF36r}^RFTjqPR@f=t0x9?; zJJ^zCqmeko!7D7y8*PR}sM2SeTwj<tGH+&587h#BG@p4a3MTS!ZSwRSx3+3?bE$Yj zG+<ONju$(L%=*|8ORq+|^*t>vR&jN6v%My?^LGeNTf%`$mnCaXu^Kp}9#5n)8CxWZ zNm;Hr{0e3=qgl+ind4dx8J7`IBt`Z`xjaf$^val5+SI@ad_}=zxM)avJNeL1p3wRi zk%0g16<yj71sc@=%3Dj;Hz0XXZPS&azQKu#DdDE=D&x6&9d3B>5Q|UopyIHk+%E^l zlW*#yU1!z4!(+9{XztOmLT=U_t_Xl)Hb+Jym!}ecUcJw_MAg)bLYtV_!P|T_O~GBa z!z#iFlAGH+PruOL%olKhS9Nltnb6xgU7<OrW-L0?>qF@&&$YMrzX{^OV+SW#QOei5 zoV$1B_>>I~yfF@Q^5{IUlbKe^2<kc@2=T3MUuUv#Fcq|i+KJ$xFy`%|%vWPojsp5U zqwEyFG8+UQ>*@`@+}Y&0_{P2>^_EZB4a+z01$7@~*3W0s$Gd|DVh#at&7thTs|P`E zy}h?fgxwpQrZ2-T-qy95v-S{-8C$&BR9{=pj!)HZdg0n<)A;15%q)5=R>`H}?Trmo znebWP@lDYoCiO}xX&wMPr=61Wbxd#~4+o-W=2!tG55CA}8zrs4R|{VaN4TWP`SUY7 zdbMjd0NXgzxASJ^d|?$~I3BgypY{f>IrZFy++gew#ve87b+p4frJlZWY7vZ+l5ZG( zc4JnBwB#xpr)*rpWbv?AyySEGM8(Z}2|vf&HN`}^Rcd9NS5M7(V{FwEbg1Hiob`4w zoz)yGUv13<r3INbgr>~CT4F`Np!%kG@0o{PueBmJi@Ph^)BrJ%|4Moqc)fsS+>a;M zMQMluxuzKYYU3G8U_=qZKahC@@r+|mzgQcHZcxBotBh}dM7o~aW+tDCyy7Tw==h3f zs|J1w5D@a5tP-xAB1VT?Z<sBC&vyJeF+_t`L>@iiu$|<TW!|xndBbW<PkBx)YfCVj zoHV4kK-Lc~zHsk!{o}?&?bWddpJaWVlm!U2CgFT+u>N>LvE}^HQQ)-KtVzwPevnD3 z7Y$PLz`y9{yvzX?r(y$cKx#olYe}q+Ge7uQ_14K?G!JWqoW2jKImbee2E<OiE`?AN zpRk+tpI-B%0_VlGRVxn&*FwM`E-;4=yCynt5g~<$9$370-|#j5o{Ov3?hYys;+G6c zo9o=;nAI+HT_oZ#JDjpIc<;&KavhYnXE`F))x#qsJw2V^eF%r1{9N@05qoe~HXG*p z;&%D3Tn!;qqBM^n^0h30D16R*G9DGQ_n_VxAozYQ4?0v6tcNg?cPy+jw(53j8(V0} z=Q+Cf<P)UxwTeQbcETwD&hz_yQrn%C_oa=5BntcQOuY3&1tr6LC3hz1l0tx(3S1p3 zuC9=p-&tf;Ii|oDGhT8@q<dPb6<84G0j_357i{+&xLt#1j)ryt_7dKbs_yO9gxW&X zb$ghf0^c>2(+`vFN1^tM$9|S1p>xeUJVU}NgS)SYWM!ZJDgkIK!JQ>bFw<Ue>P!jO zHq1}<C$)`9=e=44GiJPB(%3!;kBv;Gb7M9@ir$RJ*fcQChl49pS_z`)o7%*%#^?Pg za$iIycp^^s*#x~2Un)CLHt1V8+7L2;6*ln9YRZCxdmVzy77=sbk2s{qGuqMjl0ioY z7LHjCP@J>cSl?ib_j%gK&zZi%*T^@Nguws}u1G;+QF(XWhJ4#_-Xud&z3VIqzV#$) zq$dbDEg!f6QBD<Cwm>Y%|L@oYg=buA2PhfnZ<V)SZ+yufV!vt$o4Ir#i6?>cx~_ZM zGMk?z%FaUB&(Hh{>~bx37KR-U|NdRTOa(@$!pUVuDC;{f3P5nDO4M=5Z2A40KYCX{ zB#5{laZFq$m|4N8lUISQaTC!o^Zhsfv=Qi~yP%{@hsN^YDQlCT!6rAMGl##1GXLUT z$Dw>fR>1O<%F<thLk5w`Udv`yq>@cdtTp~|Yj?rf?YzLbyta*H-`wQ25my{$1uP!! zmi$L5^RKULt2$(T&HlSq2-;kgym|g@F2*1C_WRm)7eb-CRm($nEb`a{uHmI;pdPz> z+7D@leSasfL3`o<zM(SoyFK6<PEW3iftvmP#ce^qN*sVlSoHgerqE-54+(3u1w?^9 zCQp~}nfo7>Fyanj>>eO}jE#K&+Pg90@z#I7#9uU^@{M)$A5p~ro%iw!{(D45Kq@C3 zhr>NiN!h!hYJfscU68Mw>1=LVJR_-BH^A<i^-r#C0IJq)H2+@;wQo6=Is5upC9BVG zZ_tIceUNiEKU7K+W8>OX7GF0fwVwMn*lbBQzS;$#-cWj_5gxsiTv=agyN2CxXZd0M zk+ar7&nXSR%h-6?aZJGOZn;iz(CoLqv(R4$q=LjlcH}vBMcf}>@ExaZ4c2(Z3746r z&1jFXL>5@OSDEMJ=RQ&WCnxuOn=lBy_dPGba_TG2(T1k$7MIiyyZ7ghg#EIUzrG&I z_;}OupM*=-TI^KsuZf5-&d=|7H4?F2aroKP(hRq6%eo0Q-+3J_vNV_BcS-caZD^DN z@l>i669J5mm|xtNAA<(>Y9NOn%2{i@Qu3M_7<yF;Ww4e_OJz%^AIUzA$KV9F=Yess z%exeVTlsq^_rFTn{T-t1ow9Qi4kunzRCM6f@-Un_2*c@yCw-d@`&U=y4+-C~{}aA! zRr+tX*C635Z};&S7aSEYW_I8oK}~+dT)$sp00i*czPKDO!s7D(F5}`q#y&RU)-Nh9 z)-*IUl)SkNxJgM~4&3}J-NUo?9fX8^Qu-fY!2{Q}whn=(eLglvd^j#znG|h)S7LUk zSsylBsq(!=dG|;n(mA{NQo{b)7ZwtO-zxbmfo&&~G4Z`#{-%e%`yp{X2LPca<@p=# z8f;OyaSGCy$YDCLKOm{)ouEY@1N!pX9yV5HNo@rj|E4cpfWG`@pj-t6k52gYuMc`j zk@rBMhb1?*{|{~~Xlj1ipB-psy-0%qbk>^o^_*YlT>O>ld;yKwth_k)7_E58@DpSC zQijC7^0pkr+v113=p?YUoNohgeyE69OuhRq<Sn=_2h9B+L;o8c-v26w{<pg1e}|Rw zcR0Ma-TG`mc<E)|Ky6ggiRHn8co0vYvHpF!^<SvY+Zlk(j$r<iLm>Yt=lypC7`Bqi zbyy`2?~lkWvve5C(I@}J1zLbQD8F8wOk>^e|11P@Paqa#>4&Nq^oR2H`VSPZUSL)= z#y6CHo^t-6WS>kC@T@6*@@GdgvyTu`;S|l-AJ+on^*4}(sTRyOOl7TuI~CJdld*M~ ztF~MdEEn`3w$ZT9Te0UFp4@yG0`E<U>kcGEyjO8v?}dc=(Eh%EjiX%eB@|y?G||2F zyQ%jNKLLOp@458NM;C_ixIcjND8OBN_G0^YOFHQlu%TW}eNimOpKihgz&!4MZTXK^ z>Z>tKPSr#W$V4Vg_Sa~qb(=VzqiBCwr|31vpjK>gNNrT9eu0hNZ}zBduLIp?!lPFS zKKi=(?Th`TRqw~6DDw+*@lt`zLG^+Y<fc@=?DT|>m3Z}1oY;H}QzL3|ml4&*O#R`l zX>3`NA8eXTYGfL<A&uHmgZ(rzzBM{w8q;|pQ`?9-lYwQpcMB?n=H0gySM+jxL(8l# z2sLN!_Zp_4bx82An5C<gOKQjNnlpMdIlq8lrUYWjkhBGa@WnC((sc4DWrJEfzM6Ql zjs6ASfi$XAw}3HdF}w#YVkiq|W*2Y7lhFMxyGe{Gv|~alAt6H$!>HqWlu@@xlk%Y- zX`tj!D&2L%EFkhwZ4(XcA?nOQj=FX`KgQis|0l%7?s>8IMOd0>H{3z13)AeDe;Jv$ zE#2(gR-50xta2=SwO9z|2%j3fm$`ZC!M9u~9O4%W4<i~DgOdjmY243H!r-g@G_+$> zYHb&sv{)+^%e+z1r%vPc7&d#9i)y1pc_}h|ij^i1%m7KsiR{_hBL4%zM2w#{6*-7+ zPh#e<PS+mD$>G<MsQ4a?x08B<H_bL9VFi_%JbCH<zqIywBB?R~;}S6Fkb}g$H&<_T zp*#5s*y1c0VPjE;Xwwuz1GZ3OI@c&c9lUv{kfDGK$sU(sR?pUMVJs|85b>so3tg!V z2@fdTJ}^}~y4LA*Y?uv=jz4er<xy%wLn;ZL^I~d2#yR_yd;#7YZmNFUAC<GTowz+r zL41aprvH1a5{nG%h%|JMH6zR^@(_zs0;knaiO@orefvvKupSa5V$cX~#-RGAr~W!D z+Bwjn{<^gxE3U>U0t;^41j9Utto-33v)fTKrWnx#O{2MJj5XDUpXuv2KaJl1$=9ik zi0UN4y}{xe9;Z@2V6*(Pga37U+K|JrBnQ@{;*Y(j<lhO!GDSb6nnqC;9=g$Ogw7$E zT>1uXtL99|K_u=b@};F^KR@$@NucIByhAM@;2)NVU^JE)=JOGorI#(~kN^(O#hC$L z6Udx^^*r-nJv2z5k;ewh@igv7Eix?1F<nIs$y-#)n^q)EMwj|uAdwTQ?a%+)iT*pn zxzGk1^_zG=5!C?%5;-}Cv3_{ZAseZl1Ni?5s5LFGeO2G*Pl|J<Yb>hOE$!9y6;0h2 z>(0L*#T>L@U3T0w_G$#+H=Q<{u_$nG0`<%zRueErVDZd;)<deX%s<MK50=bN2I@8L z6835gaJ`Ondh<Nr2R3JZx5)nub^kTtd|V7H6_m*F-yzkG*E+ypp!elm(`zHz11>f? zyFe3GG-}=4gD%~W4m*ZTX6;q~9y5g8p1w`}3qE$=(q-qkFc9N%%xZ<&M=aKUvyiZx zk5P$nj_!TNdMIQXn;*l8nTB0Fjorzjkj<m8t`TBKeSd0=1(0cJSj?6LtG}DN|5{q! zFv4Wcy|HdX@BFgZeXJVK46`*zuU({l1QP4ko&+WbJViN>n&weK;T)bjxU}r%ms89M zde@<WWLiv=?b2nt*E6ft2Jsz|Mo~-RPf3xv;rbiQyx@3KG3%jeXU3enOCOrSsW%eM zqLBT8bWIbwShrU!W&VS?dKP64)i1yAZxHGK1HzFb3C<!tKQ4wn1(Kz9o{G)-`2LVl zLITigcBj5fV_HCK7jx5d8`74?UH=80&$bnY#6TdlemM8xzYz8Q&KX~N-WXu~FWsos z`p!I9W`_LLIs)oJ4a#t=c?^5vibkR}mjP%ZBDCLB<o-UR_4j2gdb0#1mnK0kd;dn1 zWp1khZ+~?d?*>U-sJv3DcSYDg2p=dLfZVFJ3Hmep1ppI&{`JLEo{PiDD%RQTqJZDG zb=TOkl+woQkX~r_l4v=x?5oTC_><z`#71VCbiX~fxSA(shI5iVM&+9sw!7q)PdWq> zn_qtTo*`&Fa`>g(Z^Pu2Pgqvn+(fveEis&`6C?cxW9{VX06hfmAV5k!U+*FZ5F6jV zzU+tHkWb>}V?Xfiw|Xmu_MKlF4+e-ynw$p{L%)CP?&sy8CD*1lBm1}u0`&lw{B7;a zen_;2N+_PUO0rtK@vI%%2gbMg9o%P8R+1y>l=tmhtRFOXtu!!k%FV2mj5&K@za$tX z_5C+lZ~g+N&`Y7op<gi^8i_Z`0|k*CHfiVn@V*rQ669F6Fjys#*!Z1^`|Z6NU$_|R Zj~n;PJe9iqWd-=Bb5#FG`p=fX{y#Xm|Dyl^ literal 818615 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%0AaY>sguW89sxn#7QQeUrT)XqrA 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%0Af+XFM#M2U>a~QAMZdNtku>^52Z4_wIhx=vE z0YsQ#A3uIX+V6J|K?i`4Wte;t3k_((rwDZeS&^g(xCxo~yB%wW<zN+LHX>2=VOg2! zi;8{RuZ1lVx`xhf9$Qx~)J%>3y_T`&yfmL9enY9Y+53}<i@OE}P1cojULB-3RlM`! z0PU5aKoF|Ns9`i*eu?Vu$i|JCA_81gjw9Z=(|Uo^gcrZJRyV)#fjc3!hn;^43Zdu! zB=jW>jJE_XxTFpzTg<;Jb<rPEuXrRQAm!sR_>S-}*<qzJqW0h)*I&-<l^e~8o#&mw zK?3N7Z84iwmFzGAYp5<>F+bV|r;0J%-^$4iC}ZPDn7{#m6!7UV;EfVDFhF;m1R6y! zFwmHCc|K|Ig(3~GQ09quIWfGz>(al-6pYT2td0gi4_PypeN*+b?9VMv=m@5Qz~yS2 zQuaY}mg%WkPlt7Zb_+CnWXr;qtN8|_#npDImYM(4d@e5I8v3wQe<eMrrEZWjMT&JI zzs@XiNyAK*=c-@g-#=DveWPvwWU@DTQxUWS4CiY#UOP|%b{&{)eC>^GYz{i|xb9sO zJ3=g69r>vEJx4JCry9kB8}7?p3SHqEXOMvK8{XQQUjzvwUc(y@L0{{DWY$SDM&AYW zpjge-mYQOH`0!!x@K9}q)Mp>C0_*FoT4!4U$9Sg7G8UPZK(DX_XrZcxkwom}z{_vy ziaM_j5T2f%GF2XeA}g=uFw?;bahYL@BxosK(V3~WCoj^{YDqH;SO!va62`{w6E%Pc z;PzadQX@Zu^KuV1qVjd~Jebg|+!o;PO_XOZA)%iUFD3Ne<OkME>d)Oj)0)4i%PDly zR~+!#9uF5h%LHaT8r}mH2=KcZrhU!!PFUkK<WJ_Xn09rdLks$09d2>ks+3`&@u!C! zDf~)+=qHVq-NN1$()wf0c=_9^2oOnhueTUL){DDIXqD&+#jazMi9zgzq(k&H2oend z0gNnQHfR1$d?%xT$F^1r{VPJ@a!*E3F7NH7EAGi@sK(`AI@%U~XgTr@mZO`OH-|*v z{fnd?0*dCd*q{%pq}&yL`xH?m6R(Y8vTJdV$m?(&<<|cuLu8Z9cLjEqRV-(od&3g@ ztCE*y;;&Sn7FNbF>EuI0FP{+prZPORlh+FZmPQn`mHRvav6TBjVH|n~2StGU#X0tA zhn(AC;uidk#F0w56@|U<v1Aj6zn8h_(Zx~?=w&``?#m*d{hWnuJAETn(la7lTLM49 zDQf0fEjC>oV2`+H<k(W@Kq6-Fe0G?@GaZiXUC}vP?tRp^^C@9mr>m<*Ph+%sWjSt; z1MuU!bJG-7>b!Nub`7sWU&ArXWi|?zt(0@<lz4*~)LwcjW^(B-dlDV{4wR3Mt01e- z+Gu}fj*H`gBS}Y)_%CMg0EH8D1QmLNV^bmtK1Q)|{tFPcl-~v~v%B@<MWY)LBxKR= zYU_zK_T>X%{@n?MI^)q-`V#wJQe-R}eCu}itw>5F{@a^$xA9TOT1|%c{Cu2fUn+CX z(lz2X?f%Hvq)6G#UVznPMcz_tZ6xSm`e1xqfI&IyUuiaY{k)mU7xVCy&I2%vRXw`M zA??RkSK~+O#Rh~5YaHF6Fqq4OMDUn(C=R6^2#gq2I&eoMGO;B=@PFuf%6uJexpX<H z2#lW<t@2V3A|BMxPw?mXE*yr2iMQtqU>e&SgV)ZTJ+_3rschq=j#`WGOu0P%(zLh{ zXV5#i$Eh#jcoO9s=~LQ{oJ52HM$UoGM0!XSvB{S9<b#~9%B3_pS_2=?SJ`dZsd>(Z zHC}|$*koT0XD!{%dh*CD(kJX#oGJe;Q07F@TKvDFaKa?i7=Q|Ji7jdWve>c$k$IB- z&@WN%OWZ{*&c$y@kzVI3GzlMN?@jY<{>&(QEK;?K@J8pi3C84Kmy~k)^->Uz@x>jK zCc~s?#!@srpf)TX#t?H-xvUJ)+7DN)#H~UjNczFhEG5CfV*(BXLDq65);Ik}x8K@s zl;fc8;?7x8AAow0YR0dDOB3bQYxM*eBo;8*I<iR}7qEy8*Ww=*s(uXCih0+^D#F=I zm_<vuUp{SV0a_yAE@z<5c;k<XobVVF(H@O#_r0yVwbUKEi`bxa7y^Or_k_`)zaayT z0x+g910ga&a9Q&J&(LSAjFKe!2nBbu8v93;w}4;-e<yg+%DrUxW-rrGup{Kg|NIma zl(m9v8~K>%?Dmva)8*N=oYp_aW<$5X!@oDV#tw2S<~u+CRg~KML(kJ$t3F#XPPEz8 zSD_Mtj7#GLSv{a#K3x_lTlo1WoVR1}{cl>eWW~MVq`RQMjn{SLc=9`FgZK=c({G}P z;WTQ+@RibEeA|moHT!+X_PqxW8K}aV(^!$9R-f3H2h!}l5iS%ygiJtXlwj(y3WaTp zA|-n`Q+`5@PYg<*XUWRdsdgV+26n7A4QIeZJ*}NU>AaqU>l~T==!ZMi9Y7aePs=nL z1|*GMeF3s3DF4+C0pDLj6ib@{UbsXicoJK%jdZX>mMHI4Rg$}Z=p+s4_QF!9%}1*S z9eMU|w}i#P0^S8iTZbm2Xbf~lsHoxnUz!ICAl(I-p$bS9Q-c$uAd+BtTC{HU7lR=L zpW}L}%TNZ8saifgjE=+*{O>Pf0gq;8ff4jzU+CeJLH@2x2eq;iR)s_8or*}XunOB2 z>sr`jpzi@3dugr9CpsjP_t&I<O0jx&WpJpx-3{8;OEY<}YqGCU4on5KAUJ8Nqn>y# z>WQ0`rWED?C|KP^ePk5n#sgWUp%GW5;Vm(JW6+4az?&8V$g9^{{4UKP_?=;WNk$Bo zq6=P$yoY7+lpcKUZATpt%=`-|0YRQ5u(E#ylW?2B>+qVUGF~d6nc{<&nvUDBt^+(G z0o@=CAbkYm_1(w1poo2}bnA<FJ}Tg%v-*#`K}2_RU4%b+x7!ap-E34{@#8Qs;PS`d z*RWws$D{*K97FUv)Kmp*lr}+`Tr{8^;?-*Fgu@cG8@BnZp~l3hO^&p9|4bVdglGoY znFC0g1T!k)-?3W%z^{}VsM8;V`s^~1&!lL;7bV~axmjO?*+hY(qRY`l$rjG!(ZuH= z$^|~HkGGW*%CRK&!NFecDY5?l%+UDryM7V@Rl;!N-w8(r%6Z8-&p&VWC_p2|*$cZF zz+><Js@jPPnLt>dXmxAU{v(YOAj3_RX}%lz=pIIO3d)xs(=u{i01K5dcuFSl*ADi< zVwb#ZrD;(X`oA)ObrieXwIqkR3YZ&#jk-*x1VA;Mylx;_{@Y_Jxw2`JEvTVl*kH@7 z9)EZU<Z{7oLY;x3p00<Y!2iFJPZTKIim5Tok4c6RsP(Ie%Fyir0la;a-f;Y0NZ78M z8QA;H<Ox%JumPr4g(kp9A!&f!^960xszKgcT3qP906S$XYQ+aW8#p;Y$0~xijN?l* zMi&Zj?8>UiPs0nIL4mz9wM#08^bq=pdwHhPL9Hjzq-`_W8Q}lxxA-hw@euCN0l;U} zXxg7(3JnYE92`_&pY}`nD}Vtk<TJ34v@#R&YOs~q@6}Sk+i8cO9`<Lu!x!M`pW%JI z1;l7jhqA=LCx?-PSfz+v+r;f^gXMo!d#R<L1ZtS)Z}h-UP$u^1jtUg(>jydJ3lf58 zFjOg6`x#iMcEu1MN)QVXWPnN)Ig*3#qhu@}qJl%IAa#_gT@#8b^n)Y18y%dXZipH> zSkA`dy|qqWiq`7j1@_<LctAXAQYE1hyv<i>&>rQ+EdD|d@^K(i3N$cGzeSbRa*0rG zUI}c|%z9(0uexuCICSNj_%e%+n{0Yd!1Hi|3S|TmjKTh&wVbYo)y&UDsnXXyM|ENx zP{`T_FKUgY7~h)@?}x?0_kPduv&4AqFMYFNn&1RKSrOG9!urSwD3C7oM895(ZZ@0U zwr&I~#RYIMm==iCe#?J^5+cq+9SP>j2@dc>wWudps@3js)pqlTB8-D$<u22f0Y0<A z*qj5`1WNC;BBDLgGuCN)fJkgzwc*=R9jwrF^3u8z_BbC6v@1j3%#V>lRsrc_@8~F+ zS*i3$-2WUc0)Zrqo*JSEIP$&*6oaqz&Ss?+On;eH#+az3yehh?@xJ_Rx!trcH=};? z;2S@SN#NaF6m<Qw8jXMVX;|;b{A0^>w1T&+;p4+^8Hil(xIpr*2adQMl}kgU!f^KA zspbt)?*v_4D?n5xg2w3~PLJ=zX8E;$^7lMLkZW=V5%h1|lu=ln0X(w(114H_YjC+O zM0P9T){%{u&>wxPy?^&+0d<}19&x+70ZCpU-|qOlhzh7B0bwZ$&^i(dq_M@xzbV6D zXm{@3ts!#!`u;Y^5s^n(AJT5FFE}|2n+sG#Kx65~*AK6yufeFb3a3TM0>|(I{RSSO z*;1-99~YG)6T1Xdo>WJHlx+@B8yR~-Z-+|w=bSzoqAXJcb@`3V82X+bU-2Hl%j^kD znQnRbUDcv)`omZ~3f1Dd^M6=->$oiQrfpmi5k!TH6a+=OQ9`;e8YB%=M3EE(r8^Y# z0tBTc1id6gx;sRW6a<tGrMo+SbF!=V?sM<`zR&Y}-oJJ~s|)9Oe&;)L%rVEz5XC+l zo=Mwvy-L38Oz&Rmefg4X)G1UZ=dTtT(R<tKT|qFIBqyKalCknOwCSQ2Bi*5;C^6?< z6ufJfApDjY7q=#X;xjE3cUL#pON*X<_x@s6(LN?(la*i(zvrv^oz|##@D#_Ci&$iQ zQ&&cP+;3!Ub3;sW*)>}`QJJxQ=+9XI=*n;yroR;^5M8xN+(1?zI5S7)-WNVC?MCX= zg}$TmRane<3onwl_{}Y)f-Zi$C=ReDc#P|j$UVlhOqd(0_Pv)MTUuKB6=rlJWp<dT z*51oaD)-@P+K0TRg`b};T6A4VTR%~6$g2dM2@5|y9tjwt;xn$^-Ch@1>TVQ-14{{- zA0B>UGv0jOeP@Gu9osn3Um}=z`87Lv`}YDJPm-(W!NRXx&}Kot0Fp{v^0ZXYo0F70 z7FS*_*TG*D#9?z$l$z=!GWpVk`Qf7F1xrZ+SuC!SW=BB|pL*DsJT4~y^-#rBG6bDa z{zF)p9k<%Q+xD}w)H%p?Zeca?BzIzVyfgg5)0cmI9KP07K97^}l|PO!oAHH-qY*pR zG!j0i!(#x_&G=P*o)ugio24{t9P+cSDV@D<!G9XuQA|i>M8;s2q27hKm<oOBk)_L% zF{BB)e-fU5x~h*ePe3L@f2#TWcXEG99{Ifc->W$TawGscUMq51PL!vW<-7b^#OLu* z!uwq5DtN6>OOt259E0)nJd`#&*~o~JJ4f5w4{*hPCfNjjD<^^?8<+CdJ6igCo?<8? zegv}$E00?m&VNc+L@p;I?y09~A4}9TUY<`NS}N|e4c2Yt$9S$HZ&Z)enI&x@7B~AT zL(l$?>u|FkrLOwbn_heE_M(@k;=J8)%5N#bJj`mEdhpvYp3=CdVhf+92%ckjv?Da3 zx8(3-O5<%80tUNE*7$Ac?-1c$j&pgO*~qid$n)rHw!0=HMtvz>Je4rO3txy2xzYF% zZco&+E(;Lt#LiqZiA91D@nQJk7D%Py43DQzae+5{A^}!b{L#h;N*IXXMt_{+G&S{c zNl8gLT3H@s+9C{HFz2%L!&Fg23Qm!2{N+QQnqK6=xVBzbNX#1JoLK-sSR<~2=B9$_ z=1>1dAs2IwbN4mpqZB8D2T)Jd?jd-?i=fnT9lti+;wRq%DP!o$<L5HR!0taIP%ap; z9gl~AL1O-vnvjRI-gaCezsckALrsT0l2o@}t0rFfgUW&KLFLDn67>xeb9^3cR&5!b zx^P7+C+MnDM89o8bVB)z3rpWkEH>9E&dGR*>1xn97~eegYzqJc9R>0AvRSg*6}uQ) zvyeB|x?7Q?gyAuX2Lhu^7?!MQ;WudT8U%ve+}xm$l*`?9+ux(*xn24rNaYnjcJ|JL zi(U*@*uPXTpjogdsQK~1i*<CQ4wS}8deFnbb;qrh<PPgZKUU7-#<khry!>R25M(%m zMYKA---Au<dE~Mq1bq0t>C;^M&)($lEv#;{#H;)a#EB)Rz1PLB497$hUO9QjWnp5J zixCrnPrg%3xQrRjw0Y}AdidtSM-xLn8ZJ^*`TIv}Z{2g-;kxa*;}u%(A^YUR=Di-8 z?{G*Eni(^BHjbwcYVNics<av^#!gVaHk!mk-8uMbhmo(w{P4%bk-nn!a0NNDTm9#h z^c1nVt5F*J=t^Az@7u-CUfL9Ft~7+%$|gSNZWg%$T|sonPwpZ>T&UssCb1KCs07%| z08^VIG|R+XH;6$Z@p-PlL|_Ui`I9gg>TBH#ka}0umAS0Hk&p;@`i&R3S1)=wzxSi^ zdQs4VNYRmY^V!zww1NPInjZoZyC*JzcfwKcM^<?}LZT#1R=>l;-Mbg67y=g_ZJDGz z&#lkt+I?l_36CPg>{XjF_v4%0_xXU^RLXQWw+sS>QIP6nUW8|)rv&5wB<cI_cX85` zM`F+KON5T5=F&(V2D>S4(8Ku0cQYj}blpXrdgi^nW1vfdeSYl0$ahaP6*cbPHFR;; z1ojV8FTXnhr#BPlDaP)1bBpZ#Rpx?Sq9}Q=F3(RW$BmVf`FO8~hwU4GJYGuZqp>{2 ze+T|L63N8i&4dP`sCW(RT0fDYd{&n?mrbB$`}ECx3r*W-9(@U9l2lMFH!`LqGK57P zd*|b0PO}9RF|j8M&!6TzM~bQef7h9=_i4UjKRw57^W?!`J{Fi^vX^%!`#Ust#>+ta z=fe7WM7kZ*h@=XHhV!Lwp4?`K&6TVtXhn2nK4a11Fhq@jgz@Fl3KM9I9d+2UR4d$f zFSzeGE(SNFrJjK0QY#wheFnC-`eWwi#>S`s$^O*iAql%hbJwly`>ES>U%h=jeF$7P z*9a7NtjOFuN=e;27-c8>XuT=%zvjgGWN9y7Msl<|pS%_M7?)>6bQU!R12<v18_m`* zKwDX!b0=fLU5SHbwjQZfvU-3*hhC6YysPj>AW`GFT>Ooni~bHNjsvuMr^`k-4o==0 z!m53YzeIJ+Zpsn<zelA4?@*+NO&A~kY_o|G&hVQUosB$|aNJ3FnBVL&Vzih_aIjf! z`$t_jHjV<<D4oWBRx$irW`OD?YF@hoH$#VW86l%sbQSZ=>I7fp+=OeLIyc)}@N;gi zIoNNwVt-HjRt_S(z9*=c^JRXrJ*l=m>BC?xzX&<60Z1FyitT6p0507(zrpYVO?Hye zK1dpl!|1(k4s-s4US@IwUaF9)p&EadQ8Se~k8sE{>G>hLKc^Aa^75Ap{BS)BORwHr z14}kOb~V0$H9L13LfMu$l}QgD1$!nFGMKFix%N}YO?I^^M@OmsoyOYKhR-ETZBNS) zwHW+Y(Ut1bj-pNvj>T34{7@TTPvt=CV=KHOqxteEU69~Z)PbbQZ(05=O%|5l-W~V2 zZa+qQwruxfG{;L(zT+eH27!smC&6M3guS2$KU}$J9#fUEIP}KJoicut%aSumrd==; zEaYi0)*8O?^{C39_fUmS<0t1oH;SKZps2q)$(@W4<pzfjQxF*GFOYM;&72J9jz#J6 z1?AEbhR6Qthza33bk*>_awA^)GMu{j3N-8PZShKrbN!;>p@Go0x!}qss|d|3BK9*F z&|)dqT*nQD$v#vxx<5h4#d<aMl};QJ%rST(=TD)843@q3`T55;(osAO{QO#kzN{qn zCCc!%J%piS?yB?Dx8#ZLoTLH2r8p)=?0XF}Qq8WGcx2y%QN3lhB0DG6Z-)*gclk+M z4}3LjfbvXJ$=-$2KT!%BBie=WvJx+>6+?d%bP+r;R)eeFjqkd(b=Jgc?h_;lj?o8> z$a!>L-+1~tHINzJ@P&d1;a>iXb3_ywa!i1BA95ldpu;)RJl9HMzdCApesQHtS-w8_ zBGd6vJB1}f-!I>f=D{jBDNg!@(P;<on2G?EpG2Ff!-Q52mLuC|vKc$~6Z5WnV-oKl z0^2y@iIziBD{8M@g}LE5x9@nVI&AK;C`kuH#pu5KyV?qfyQK8`s<KXOJ(tg)j6K?Z zzJz60HONx~vOokY{OWa8ItGVeap)qsCd{aO1}KwbY-y;5FkUf8CMXFeH#uGTpraW| zc<Piq#7lCgV(xD>FF=;`=HbsOzb}38?WLuqy9%t%LH9_~1h0Cmn2^nwYA%ZYTkX3P zE4g9YyNFw#P)LOzB``No<_|k8CQ~{0bwRUoJmeCprl!V6;eqn23vVxnbNYoQC9%Lj zvIJJ>1jae0XL=rhECp+p&~(G@k;2stMwXX!w`DdA*>MVVy6;^?MTtO+x_Ex!hm#O@ zzi42_pyZ-)UpvL)f}4@A_?7J7!xJO-VDlm*xeNPe|B6D;zO1yZnU+pDM0*CA>`hJ| z;uC%bch%0!YClON-Po9wv?y9REU51qLcLfYepXnltx6!lKU9GL@#vo1I93C0G8?lj z_$Aa{8H44^2FbzIa%yqaigBTgWO{w9`l4`1xi)Wa!C$vf__2|!Q0TlH#(!vCHTeg4 zD$B{x=*)PWKM3+V{0q9#Fyc{nd$sq)&gEOuUEG?CN91IJ9$^{(2*KB%flYP%w3xj; z5?!l12uGD|(h|6^@UVv8eQ$?g)g7oiLCZcV7y$d|XVuZ<^0#L)x<9YO1lQ%00|rJE z1fvjhj|ZV6PE@Ul!KA%wsSPcv=({AUbA3eum%P;@d5>CHY@LFMg{@ir;_#20P9`kU zXa~Ze4qe^7K_OpOc2yu4?M+}-_xr19QJ2G2Z8<dFcz$-1^*DQ9C;s_$g!H+d^9@gZ zW$Ybk;nt5gI<ayJ^+QunPO#-DIsNgb6AZ+QLn3n$Wt?)-ca3ZeIZwW@^;y00&IOG1 zv?BZfMGbIR8@?z%-5cmdj-_J~ZhMctjvT|njPIvJ&k=kL&P58D-`f_kOe*i7@Z|&3 zy{}PgAAkcIH&8E9n0NjBF`9i@kLDV01X?kK9V#4Z-rg0TJ2zxQt_L>5@2Td++4mx3 zu{wHqbkg6!ac`;&M{4gx1@`eZ`s!__K>9dX2y-4n%tddKFoZwr!L{sj4rm{bJwDj| z-dm-^V+c*~@{%3zS+xtARk#~Idmb%4jWW9^AWRl^dx=W77a}EDB%Qb9FJ3M<!M(7q z!mtzjS}I7L5`Oo=y-NiGhRj?e-~Alo{MNzwLFH0rsJa0&3G-eH?PsGtSHpQimro4@ zk*@_-`pKm!DIB0(#Rf=NkJO<;Ig@v`zd=vqg}YU_sxd;E_gk)`5@0M~SBV49bzAb) zVPs`MjBt)~zAd;R@2YfAi%saCf}X{-*D%5J>W56Tc4n9sce6O01%QIBFDuOatA+WO z57%aNy?uNZr&JFuudX6XA{M7JDjK3kCZVI~Ng9=CUw?lQ&F8&d<NYtsyuBYTa$QTm z1<MH}_o-fr70ta5g8qwYfOsfs>IR<zpuQ_VeLAwYw`bas8u__}XTWSk^2IsH&yaXL zn(Gt3U=}F%jO})*5R?nCs70kz7D`QOep634?8Td@8IZX6*YG!kcsIDPae5M3eQ?Ps z%6#SC6+106!&KvEwv*lwZwiavT8}n}@rKH?$l%>1%x4Dap-h?cYNh+r99Es@9QUfH z_|jnx&W5Cm367QQrsNMRt!^wQ`T1^kKjm<GMng64_ZSMM8#>DFYcpKg@`hYm`8qck zZ-yp}TB)}h5F~uRG2~H^A(|vS9xFOF;9}ft9k;$b858N?5$7;hFYXY#DdOId;NZF) zqf-t-lK_jJTqXV+;N*<Zow0l-mvu|*({^^(2ZI6RX?9<{)mElgWStPX4lOHRqHG6> zC1HXAVJA8_HZUbw`U#%#Ig^%Hu5<1iZ)f^TuEF5Zd$_fk0r&VxQB3lJ%nj{Zqb>7B zje$%{wQt3}B4c8iQbt5eUXC;eUCVwQshu5T@BHTZ5qv2+8&V<nA${Scb?MFJuNg{9 z^_H9K8y+5=4I#s>Mf_~XmG}B;cm)}+5_#d1NTHRU`eKImJ}lipCwGpV-`uN>8%Zyj z3x<spg>k0^&L29AZ|LbM(cR#Dzi}jDTQSTp!sJcC0t_6kvhmI98zedxaYZz+E}~>F z{9bLy9RK=-*{(H@#C3Y61{a~@da{+0I37F2Fr#xzCGgz-wc`|J-zvQBnZ{?2$FY(7 z$1wRU6CY)In$I+sIFxswAo~;#J!>eFcODbHh30vj-D0&X{h0;@m>1H|h&`oNkm1R< zE?IV4Vc*e+><m(_w??BFYDv8G?f2KKCw6?4YummV7;rD3*c_!VvuTTDka4Mww7x22 zjl{*JJLILRd<eyKQE<S0xiI|#1ARk?x&#%Yo2iF0!*-?Dk<|;VKBStLEV}Mkp6xjE zY1RxF8tV`924~$j?otU`8@|zndtn4)28OQUDRI&J`LRaz<UinOPgEmZ$v6gkR4xhT z9W&~=+!y%3yy`6xF0p3J`Cd6P@-w$xW(8U&WTJFVXcG+2<Y@2RHrVGR00sTc{3gs% zaIA!)hslY6sbB@s(kb?9$@C6$ea!P~y;c#xXHXT%EX#)YS+T#L5R(m&SJ3LNIs2&o zwnFbj-lI<^1-o*-WHk@~colrC;8zv@{2M)Ew_GU9kdJJUH6Pe|Q>*bvefw&%EK>wD z-bTF*^<5?Ic?b{h4D^XI%C~|4vU}0iREioIMVR(XGGux3dtY~TP#R1OVbWDhVGlp( zC~b}`KYyMv41ywBkvfPi+9y($+a@jsPz&(Rth(ch6REKaOb$GiAI_edwBrNcw7gHr zp*|SrGFRleQRuj6&???mmLJTkq~@A6Rox>BH1@2b#TNxD+ugf^luCjT&-Q5o)4JvD zFO?MRQh&SqmITdFaK!7yYrNW@_#@4aVsF_FeAmjAdWc*9(60W;A>1~3ILAmzdcSSL zT60vw@;%wncQq+$ubP1_`<LBTLTWXVoD|C|4ijXhkB>;Q94Yg$f^m4UDyd^1yq8v6 z_Uni$XhY)mM3~v%(+JzsPd2vKec9-)Ro`1o`u?PakXL!6uuXdfpEE}MR{4$1{1}J3 z1Vz(Xk6NQK>I`vVtNisLT>dc;)3$8Rm#?zv{Wwu?XG{?%Z}JMw?1>4kD{1VZdntr# zKPN#~vQ87KzjiKMa)0Y)AdNUhs|N?mspO`dU@r5)pfBc^2UJ^ghr60`9!79{v2eXC zxyxT4IebExrA61;-HS%6P=niMhJ^Av9b8DMLpZT0DfHrr2RfqpgJS8VN-r>2b?iA& z`&6;LjbXNqrGAG&A2(_@A(WgIb4MLs$CuWtCUE$tf>l#pr}Y?^0SE|AFfYPP?bA-x zX(z1NQF06y-qYRdM_UG@c`%sw<R;ruuguxcypfM_ynF}>x{uytu&v7cSZ}-8XCdcv z6}C;3-eZ=gQZk}23~ND+VH_+Kdt2sGg_#X2(o$;^@*?R>*z0yN19|!ZV~@5b_r?45 z88Y8LzpKtJOvb7qm2Wk8wyr}gAo$TwA4<HXnO3D#)v&8FK2gWcI!b|1`MgQYqo-HY zX6PGWUYVLLYuY=uya`_Ffa>5!D~EHb116hA=lLJVbaRXYffc35nkduee_Whe6HV0> zGB!Pat0Q$^9KUH#_l%|5+FFBrufFSIjn~ZczzmlZYkzs^M<G>^?fy(u3SpN1@+nQO z)@eGe;4vdp3A|)B=VtBH2~-U|YOlW-zQs@GV5UKVpBzDFLU7$hGgaL8hDA4be{c&w zbgZD+9G7ZyXs^9zogNew>PKPqVz0@zvrwB{8co1V7<cDv<nByvd$wXepS4o@%;rc; zj8D8&?2xr(`u^U7(C*DlcYJizA$nzAO*GkhM0h8CLv`}9(L`p*d9hVWoutfnb0%tP z$ay#8uK3%Y47-hWyzAt!=HDFFu6y4tC`i&lO;}VR(soTI2TlKSyy3X9@cd;*-4A*; zOF}^%wKsUrd8I#j*3g*I63WY@(vXy6Y%Fmo^)wEO-V;M|{-y1a17j*Dd3Dh&xapNp z{c~ZDO<w)lz-J$SkP?+t(;)6&ijI#M!bFoEVrm@UFgVViR+8J!dF+5laGoN7_kz>X zNTu4;n*EloQ^0LvZed?m0BI2l=iK<es#<w=oavYq)HrrL<P^VwvMJe-v<wdp2aYE( z%IMa`s(#fBK{1Xe4+R@aXnV^k0?SxDF+)v4I_TCoE~5@OTB%PhlKWylU3d36v;0{h zEidt1xa-SF-7o9$*=DrCXsb8t-m|_(wY1E^zQz+KFZaYgsJ>;3!DwX}$dQW6)#SmN zgI6u7mi>GF+_cnXvYl_@NTYP>zQ!4mTR>UEVC1Fom#CwL_yOth%k72{GApiM-$-Le zsq4|50<ZzAXuf<qw=O<eI|+|K&>k+yB|WFnFl$(28eN=rBQN+NQN(vU7*k#St##sD z#qQe8H!T_{xp%JDhf_?K$D*y2VN}1`O>$hoN^HfK{L7fOBabWbzz<qpSyp{F2<tDU zV2dv|Atg6|?bY44vd{47F{ZcWYv(&N;)3jQd3Iy2DUE+VW5vI$u?C`QLJ}Vtxlqad z9c_@~k-vN#I_b|-&N?3FQBEW7{4G_ViQIhGc~-a8%~lmGc|0n&T)u=|D;|TwrcN&y zn$1*@pqSRyF;w!;DxdOH1kWkO4MyQHyLH@hC)cE%5j}iP^kg7%<Qpo8cNIjuYl}II zop%sTxSJEA->^E<-7Yp-vpe&i0I`c%+!eyJyTQs88l?q#q)tOYm(1p?<p|MalrMR8 z$<d*z`9CA?6!pit-M;Pop!ins3V-r<8xy0)<T+@3M_KSHXVO=WA6Vc3iB#^xF~V~u z5}`7OaELt*;qHKi4pEwU)MgEeovjaA#k;rbVt2nDCa|1o2NfFix0QD<BzOf`j~Ow? zy`SMVZh9pZG=NT3ukReWiuZ^C8>4u9I~{dzWz51w%gned^X?j_&5ZpF*~$8a&_htg z9e@a!uOTe$VJVQjk_q#G=!C&t7*J}i*u3%B-%ETgPo(7}dz9EkD@*O&o79^H&4wwe z3v~=HUJb(udz1^1Xuf|1tGmQEe>@>ljRu-Y34&wOV#$0t2ND)**+os`Uj{1?;pVVx zj|cf((D&H2)3Ws>m8aItGVn>>YE$9yl@}*aV~;Z(AyH$G<h;2y_=yRQ7dBZczm@U9 z8S+m5LSmg;)^P49AqD@a$hClCY-vxf@aFnDJV7Tcy>xuQ4m*@yLV_24Z`<GP6npvm z)VqieBWZw)oXKNv=W3SIHMY;et}>&M&!6wNt4mT*bllncs$w3ODi-F(T{IGWC_@8P z<NhEIB%sF4s+%tb1M;;%sh6VCYW{`f7-+inrV)(v{>+PG7}mu?^QLYh91KNs=+EJ% zXIhA7x{YASM1R1LyvsMxt&zDNZ!%nq@0StyZvK3Bt~ie707J$<@sud5IeuQuYHZos zY|_82wJ|xG4jU7tX`JGP3GTKRTkPx|_MtQy`DUgygvBn^+_WL}_?SwJa~6qo_?-O* zcHx<XOUxCsSXCQIlz><XM8gVvI_!pA&)}mO!51(F3{n|C3E@GuZmXUAsqVNA{j?hb zS(b-7t;-JIvce@&+uvD!G13^pvrz5A)oFT+`mS`yO{(eu40hLTd$wSVV8_`)-Mk|; z$UMF1bL^<|UjpEL`UZzVH%d(YTXAoBv22g<E;+J*%WzVOEfU+R?AOvQ0%i4e#@gaw z@ARO1N$FaT`51UI&8#2Ujof@jYY{N`M-g^>s&#lCJ`xXeg2xIU^yc$E=;627S!q{q z1pGPsr77z;UC%h=QD2HAFq$46R|;F>t^ERBwkDIJZMOa0@m@QPMS7(I*o$_t<Nw6% zH8J>2)M1WOU2M@?4BjmfR=ky-=em)LpL<23^R`QxZ~@k#i{YY=A1n1?x$%UVD->BR zpQdsl#awFQYk8$T`f&WU!worUl%~#|Ol%4+J0mUUja<e1o#_v<;Z_(mr!75yF3HBm zo0_f};&+LC#aqSswfM?c*~B`S{KINU8D&4)L(Z7rwXOA0&WBOW9uK_R`VGn2S+|~T zOawH=J9e{;O$r`H6PgSyJQ|Z_Lk^9HfDX&pE{A^P5xIFD>zeDBXX`#QLg}*QUo3IO z3m1GsB_WRF&cYL?r4aYX>lw{?OG964%T9k@fn<fMr*QT(ipjDd&^Jlu&H4grX(*me zD|NwV$zwjo^@cwCmHMZLaB09Ugeu?SA9xdk@IzRi<&Mh#WH;7^ZX#s^3uop&o6?T! z(EBN~5J_y@xuZ-?`vZD1lv?9<naxs`tSWYy$75^)g#&Ui*w-Hnm%nMN>wbz{e~6;* z3#9#qVu>Y{LO+s^iNavh__cf+h_ALy$N|@QDQT^RL<OCt!U&S<2sm_IHSJO;JYCnZ z{i>6GOSpCWC4cw!*OtR!=qjfEPB{H&EaYFfBZMyBUVO#S{oKl0(#ihXa#4+X(GaFv zUDfn+2vbT`R9dTJ{D~$DVAO`?745ZY1q1i#W3SWpFp=**|HjG#3#Yy}J70Ti4CAS= z+e@ItZKyrx!3kTp^ZcGLp7@fR(+#^+G)9P1g2ZLQnzz9{<oRipCK<W9@RRnJ^jem1 z$$3QGjo1ei2Bn_SDncIq2P@RyHj~12aI)!bCr#FWe0-vI1ssm1%iem$enN*_-v|S? z`peaensEelH-wHnd%<^38Hp&4N=QWEhKSPGM1+zvX<uypnC&=ugYTl7miHcx(qp*G z#AY~Kp}~;*M_ZOXe~LXqhebQD4^>E_Lt)m%Rbtg2k(%#DiwH;)6h9IgesW=nYa+Y# zgbz&R<lziCvJ8*?{y!5&&b+%dmX_hFw1|HqRy>3_tZ4lI5L_$+`k)*?ec}5$s4VIM zZ9vn`qTB~NnYaO~3`cfwjv-m!n~N{@igY@-vA)}tH-8Pw%ULRJwpthPV%*1VM#HY% z50Pp+)0n1s$g3&-NPy>?R&_W-la_E4gFJ3*U&c|(+EY{Bq%C0dLJamKn&9D$>7%Yo zuG<GyLCo=G-Qv?KcXi^s1KFh<Q^2=2Sm}UxZ!d!sBKWvLO67Z7(^9nCA7{FA5}<{M zxse--?1m)1sN~Un#rjbQ{|CRdkPgEag{aGDP2FLvKX)*a>ZL;|#{p_cFD9G`$=MCD zwOutO+P<v7riT%bGS`K&X{(}%k~VwB6IbDg)g^ZsDQ`WL_8Vi*C*!>Sb>tbTW}9fa z9}6`~z8x^eS&YOzUJIVB{V2$)qG;g3)>(BjZuehp@Bb;j-gnQ@>_G{J*KKRXvu-3k zsVmh7LlV7Rm5NnA)LP|4^yBaGVtO?|NRs;|=X8=9|GV$A&b+RP5oe~22HkyG2lq2? zM&-}3!^mjzlXf5Oa;b!|kB+uYoWUWkGXxl10A-h`D-KQ*_C@=1#<3877Rjt`*#}}s zB6>f^)8e0SHA_7~C3yRItV68D=7RXMC^G3oIG2%Rd_n{70B&R{BhO^=`<aM6J@w(w zcj#y5h1Q~L?M9+4i<JgE_T4%|G}wj_prM}AdFHchdq%|``*^I2rRf?Q1J?8j_}W&n z*1`L!M2aq82C3Sc+w&D)0;bm<$ugWR43lo7$4=k^NO)jbN2JQUDfNz+j7_ULrifNF zm#Ddn3BkIZfM~+m-|D>AIRCZ2*Q$aGzyry)i7!)7mru^uxIw97^~czYVjg{_^0Gjz z0RgtlIh5}WMe$j%rYmG&VyU)33<^)D=A>%Zt|R$5C~s(|y*a+Mu<E5G0?Zk6m><x? zJ4qe?%z%KH<7(<l@avIcv@S4*Z>&oRjj&YjT}_m@61`><fV{%qDzNOoZ~YogHX6fm zjr-<w$g|7z%JQE(^QNK%CU>+-;*{hfEV{EJox#(et8;<)5w(+B3XN0pphLMI)g>4D zb>AUAq2>Aqe+-FA$;Vp;zKHj={Ox^986h`Tr9{>28jVF@uzb$*pTgQklPQ}<bmW~N zAH+N#a!)}ZrVz2?Qay_iP}Pa@!+76EyAKnIehXAZ(JLDYF>CQ)SbcM&Q{@OwI60M` zpy9jP+!&!=uDfzx1Bf151eUM}MZwVnZKQ*Eqv7A)2;71@0xSG;D~7wQ&UOa1vtzI4 ze6Ks^d@oDycxyJeX%!e0ns(pIVf*CN)iFR=qf3oE1(&~QPtOCwt1OZyfVzkNkHiro z$(^rFf*R*1e?X%Hae(I?rUG8Y8**f``V8fz8$<pb8e?UUW%61Lh#~m%%_*V97zBR~ z!A0!Z0&XH0P=8b)Og7~N#+_n!GdCDH`ZNG=ji541V`m$f)qFV<q|Qr^^={xgc8Ufc z-Klud>*a|OG`8wf+4{g4EruPl?rftYL3%T8NPSVnVa|fO+vu#n|L$_t*#I^HK#SJh zMiECD$wmi1T;YIh20B0LnXDIUD5J%xBwP!{wkF;g_bK|ZQqfj`Tx$t3mnf%6J8ZCK zq2azozCSCw)YJ`u$yF@Q(`Z{bAZ6gi)UKe(1go_&?)6s$<vk>=51x<u#-WAdb(+r8 z^k*r-KZbfX>_n<@^KF>(8Rx3?ICh#RgF5yV67A{4abc)E8?5gN0zE<GnBDy=;Xy49 zYU<a_Ebsj*&*d*jk{*JCQz{kzGQ;7#7v|e$HDX%t&@7zoR*!88e6lJ_*AExDEg<me z0X!s@Lwx_jZ?O8;iyj1>yd7H(6R>#{kLwQ9Alm>tz7Z3L<Y8xLxyAan7Ot5~HkQZq zwrTZa3a%S<aNF-@Snf$kSafAd#SZXSKqRd!vb$5!-QAEgc*1hDdr+X~u|$pj=xG;c z;1keRV+DiP(?^p79#}PIts@SIssyEZ>Z}-R#BFCYsmEWRoxWk<w`S?fTCua_541?- ziR-0~kGk_8-2CvQSCVu_=9)a3j8?UVc-pG>jG!f100{~A>SVhDuqT#&x1A@MmNn!9 zV&5uB_9AR?;HNUvc=CW#2}<w$uE(V$`?9iJj=8|=EfDMe^u2e|JbUQOV1*<xEwccO zZcu?r#r}@XG8L(a<o37*qg?3oz(H6nZ!_rCeC=H~KP11lQ)9Qr``}@0EGRY0x93D# z&6V4e)49llVGgIo6u=5SP!8P>L}{LQYFlxA-HHwyf9Cv2H%2gk6K5ovU0Hn~s{df} zQf0x?h}ce`h2BszYo4^pXnWB}(YR$ss<v)dV!wX>wEouWO=v$iGYp+`lV{mAu=|#( z8Rz;&-Qp_?hd1Gq8A5zKuS2*)ewEoqjZKv6=Uf-0?+m2f_!cJ7FN)h-CXrcQ2bVd@ zc4y@UhD6e(MztU1_^6F+Qry*hL}`oR(~HK4LUS}1nAy?8C78B{JGo?|R9_ZgOj1C} z)yCj2Hck9zuFizFPPUyrK#N1(h`*Bm_)lmt^-N-#X8ReGT<`SBJrKd<7xT_Tor0w7 zrx1U)l|g=k3<L&u_%F|M4ZgRY`2=fd*dgEw2p0A-WKOiN!X>x7A~3%eohiT|K*cCd z@3*!NT-K|KlIg6lmBa<Wm{(VrZ3Ri5e-Cu<KrpP0J^VzXpYBi7V!2RqEdnw@t2U4h z!~q3xCH21aJbS8IByY_~G8tA<GK!ZS+r?nD0vkJ>SEr1&@+w?6M<c9Pzh8^y+}-Sl zX0Fs5dCKW!Ydul};ICLsUfYG2MGEgh*ithjQDKJ>nh|8|I(4B5%vjU6&2pW|O7nx7 zKhf<^h$L7+4|S<_D;Uu2&<pv*R<fSYhRhYFwq(1PZ)zXdPX<bLu43PvFC$Scx&gsR zq=HoSJRp0HxM^7=rz7>v5JnWf>xb*}QBk2@?a2VLml6~&mz>u2)#<Rfca@iY?e_8L zm7`i)>5e0r-rG;V&Y+a>4yC5Z_p>vj8W&sF%`mJ~gU?JctRmC%9$j3rPu0R|R66mv zhN8^VFIGIC<f#(29>HfH#s$n!3Yg)Hn@oVaQn~%?jpc9T{_<Ws;|=$S2G6UV>CDY` zbt*WppQ8@9PCUktQ1(_cwoBa^`F1U#mhcnfwYG|S`?OoJPs4S<nrGk=&+rRDdI2HE z@jT+`w10a#K%zW27*_Y7HHR4RrI7IF`3B$7_Zq-F=(l*#LgYZ|0)%WrNXcAr<A4r7 z^(UBF91w57BlPfx=SWjzd+ewPyOOgU8EupMyApxI;}@t`fg_<O5uL}dHoN@1if+9< zS2%ns62{p0otmZh)5A*vPi|UG7odDs9d?_Bez=l?mu){kz=aS7<5c9D5?d1tt&arE za)Xdf$yo+9O+~8)`&9YZxc7IgYsjzRGM?Jibzf;!NMrU|2Z(n&)^UiyCf$5vBt#v@ z2=WK_0jNiCYjlciYz)5`eR{?+^RhO%CbQ}*y7hjCxMT-NnH$YB$|y|V9oyP$ukhHX zTVxIfuu$7MAq4xzPBaPM!u?<p>%?rj2VmjMhdQi`KXaHaKYcj)Y_%bCnd@4&$>Fz( z%kF;yRW^C_#nWxO2K^O43RrscuLQwO<g?fiT7F9gSJN{Bm-jU$c*S2CW*u%NsKUxs z@w;h1QN9=w;oNgvx4AODxT;I&<w;n-ZX?B|d&!1>>!G`ZnUgtfQPS)eC3P3!_H}`q z`i8(51WFhmL!*7W)9xBfGA^{4^Tqe(v?%4rv)rH6%j11r_Vok~ai%}(7yZ}dkLa93 zo+MHW+((yM?e0ckSW&ggP>TYO^ce9Im;TXD(6eDp$qrACJu)ZPE3qecvvxPN=D_Yi zMJE_UE^o%RMqC5XypM*erQBg5p&|HhFPrH~chb@^IT7#)$%0?>ohK8#-V;S7B^%WE zfuoHIVNuFR4xoKs>BWP@l8Z@l=<X7Sj8NG0R+DE%skt^k$U~{``shvbYNtNW5xf%@ zf}e$(g^~qK+?7+CY)kMjU8o}TQZfd1HE`;C3JdsAuSso&SQw~&E4_G%ogpuPickJF z5S*2cTQ5I@(BsuIBC<iYJR4Dap%Y$!oUd+u(1Qm8-$@Md4W)z#h=~_91_8q=ubDDA zr(>G{AyYGI$5Wu>#*^bNUd<j$M49T8f1SRSaL%Qz<x^6e`;DdX7OQNID<8-<o@+H1 zS&wF46Rcfpu?sMMx1GR7GTi&F$~2Bze7bl#oisq=-L{dOOe?S2TlxkhH-mC6{w-11 zU?4c846h{DNWppij$w63T8&~*G0RmMbe3ZLJka(>P)u$+rlULv?J)5BhVl>qIAx(G zdNHBlyziU%_1Izb{g*2%9@O;8pBEK4U><5yfm?xgIQPCx`Nn;J*OCX%X8PAtXe6xp zbE(GxM=~?LTwQ4&?X$6Il#}Cm$<YuVYR(Z6GIb@xkNxDd{|R*HdrMi>laPyO_kJ{_ zm-;c<X`<ZuQFioss_tk+UJCtJ20bXy0yeFW*>3)TWX9E^@QmZM-oG;CzhYCg7CLM2 zf@K;O^xnv>-)a7ZIdB7bYiEX6OM!9(20OU&OKp^(!`!W+(eRrq7g&K#nec>diV=_r z;0Dk-gGW<l6d4B((l;w<^|n>GDlbONDLWTd$-V~$$JC403Zx?%uOG5d7a5K<MJjnD zNeF6K?BCK{G=L@DUcCRxI#VEyVO#lA<68xxR!@wvG#GtW{(@RSS;TINEHth4GXGS4 za<DQvl;Dqlu!oY856$b8u(Qq+=cz6lc-!3{&?eQ)UC8gX<kOUTOzj=>{=~*iP7B`X z4NYkPx2DgiX!pOqm4*H9Ii8GU{PiQSu_OxDn|gN!1i0=Rc~D_j0_OMeQq}7|+jcei zJGly~P-anRaEnEPhM$Y^x94Y(^IrSQc_TCv6T&)hUWEz^Um`Q&xVz}?xCMD(NX~4d z2y>*+zCL<)P6aVuSp1^fW>iU6Z{1_I)Ei;W&@JF5O{WcTvtFn7ive<0j3<z@O8ZY| z)f(M0E4VqO+>>X{0uQg8^*$Gdcv%`qIxf5!f&S?lAxLkLa0s`r5w_ZEHGOQ50*ghj z)1qo3EBp?#+ncpbe0A0nO^83%qYMRx=QPIO3CT72_2)V61H}Kpi;<t2faZL^7UJFR ze0n>bv>R6>Hb+R!U%hb%*t=VA3h6h>WrQ$o1DKvVxAlG&tMW}_4N>t{d}?;{_ui!3 z$vX()hgWZPRs2D3j)}Uq<*4p_@mce;NOTX<PvvzR%r^4BW#4V&l?thVul(~YmVlLb z&FlO=@~^bsj<hPA3xl#@SM;lUVfH#NIrPh2k4LtUXhQ6v*l1Fo<<nvCHzlJ|d%MFY zQofel`J!2W(+YGEIjU`&f)9Fh=8C7ei@*=5#m;?%lrh+RXFYLN$My!~oF0+&3J5`V zUiRtfpAbDbrAI$KJxPdGZJn+niG0jn(_P=lQ^5%is3LMTtD=0#cCBOg42Ct<AaNNV z1qB2=f?piZLNHQP(?g1CRA3obzj;H%zQb~G>;_4}MK4gAyz6@`LsLmjksL(p(^lbY zE-=z+>(~$UEk5(do|NEVOW!ER9V8Jy1Q4sL`fXKzjq_jU&#xvgf-cv+m<83NU&zvB zK5mB6T)|tiX%=SrE}ZvAR!p7W$AgkPHdyME1FQ@4j2I&7xWZpf0g=d0)HD+uDiz8I z=%2AN#UOfXz-(uz7)+XDr0vQ?TJbqV_Fyu@16+St`lkq~mp1-|x5KanqYFc#@3tC- zs6~!baGK(VPp6k~PkFR-7e0EY3vAvl<7h(|X_yeQO8NR@>uXB)fPU5jrlDxakAq%h zTrnWyxx;J^le1ooU5Bpmp0i|6*tOecfhD$+^gN{tGI#XWj)cXPZ;qW|5JT8;M8{Gz zf%T6E%Gdfcl}T3$^U6hfWf?0T|HebeH*);_js8OLp2rrN$Q=|h?ExLxQ`2x9Mw6vK zK{G5&-CR!4o-a4ntw_~lGBNxTWvXH*PQ2g)`7zHcD!^_KW9e0as-a?ajoH-rqf|t^ z;17SUAHPe>qC->v9(HVOjz>qoPP;PEK2h+X*Z4KwKs$I7hJbit?qIKQvs@hV+f_`G z0ILSi9zJg?fnj}%#@c{~rk#6!{IIAOObx}zXSK%DYk=RHsqq?yd{DVIkoL<abaKUO zCtdd9J*9<^3H9DI_^inNpFZ@j+~zPk)UX)CI>*BYww8KO7OO<+<(Hq_1A3>*?xiX2 zZI5xiq6!6`oYb<EtIGK!N#aaBBDzGlrJxWP61cnd3;~medGLXu(DwPqC~yPKb~8WK zm--IO<MP#ytF%%#Bi95#zyv&hrUOby!gk`NA&|TeEhQIjq5=70LV5HD&@P!RvS8>k zzUXlp6q86F6*-PQ4t3BNRGtKMP2$}0XJESmtDirGsbNS;M)?hXzkoz2EHu_o>RSXl z5vT)WD@JLJfLzy;|HR!q#SF!gA5?d`fZ6OadzcEhrtlO=KxOoN8PB@Ju4GPXKSzX0 zGmS9G1K-qRIOW6(pzZrt+I1r3DS63e)pO|sQ3Kr;g80{ee_W&vDF>gDr)@8g)C`pX z+R$tep1zUONxiNKVV`bud7Nk@=?YpHajzg?{W>6G+L``ZHHyDpL~U`d0D~pHUhY~1 z9Hn^8En-bAI$veTEp#&ZSaG$8S&_1+M(!Kn!rFkzVS^1|z^*EEr0a1&@^(D5;E#(N zg(c#B3~z_K{Nn@;1)RP=dc$GEdt8PaIW$Sg&lt7Ww&Y{ZMR0|$wlhbyPT9}S)ebmc zf`DXVI(ZuC=Z9eR1mzzmub-t?7J1Xkm`KpH`S5M7$I^(}xFokey;E@PAvxf`+rVy^ zW}8e8A5fI7EJ$*3?DvKGtJ8ty)W>2kWiSYuwV^>v7BQzJw%o+mmeN^Y*Rpo`YU=g# zoq7&>bmqvOcmS7`MQ1Jgi@*1I(}bFd77YiA8o~mpe42}oRlwmqS(;%1Pmz1#teDWt zD+k4hGcxV4m2(8DR)h_=^DQE8dF-xAJ6WoOBAXRKeji}&t63}Sq4){77QWmb^3Ocw ze&n=Bgg_?HA)>Zgb|vL1Qr4=E5-|T@$0`KWzYoV@oS(qKd5;^6R@Ksf6h*$?K2ikY zQ-C7S;(zoJ7ho5m+44q+vF;$(=Jlo65SG^PI%m2cgy2K;FYw_bKL;QE3ds^Qeq{*= z=|Bm8UZKc$3gI8%UwJ0m1VJ+-#SjN;O7#bTogq7Ug+`}UqcKQB>jyzJfB_1^NMd5R z-TuD~5cxm<ueW<ZuM}-Lzf`E(A?Q!h;Iz5K+(QDF+x0wLZbD;(w*bI_Pl`mR<G-TQ zzslR6;m;8^bcjiB>#5WhJ~AMs9CpGYd3cP+-X>BOs0Y4#OQf+njaZX+aV*DH0Vu6N zM`F8}#RHF6sSWm3?}*au(>DP}q^n7aBucNrM}l|?)NVf0bglTVnHEL4t{a*;sa%AE z5s!}^XZ-*Dl!tJ!NG&I7g-SFWDQL`}`sJG|RgfpKMV`bsiy1r9z3p!?kgaDwzo~ob zoXC*-c_a#xL`ij|CaIK{jw|{O$;CGrF&P-7VOTF_oxCVO0DZ$fr<h3(<D5&o&Q@UW zT(^?Dxa*LxaFi1L=323*)EEO0$D3<0<g!Rz2N&V?O8%j)^S7`1_vgLwpPrWvo7$Us zC9&le-F$gPlOpS!i8{nAIzE!R5SEB<$#$>#t!~urP;%j6SX=4Ol?>BktLFwT<gB2s z?{u>ljd~qZ8{T(uC?_jfs9Lc@bKo0V<J|UVh1J^v-sa!lqaL+EIV1c}x=D5LB!|8K z#%WvpKdKQ*NHs$L->VT{gbq?(fFkiKgOGjj!}msqNZhOCMZ!?O*RNplm*N^{6n#VS z>P@2`Im1RBeLiz6st1wx5>A2&c}TimkJ9#~f-dV_VKjR2nT=QgWC!XcHMjbSua_IA z@fXj#Yp?om+9aS`v6fMq$8d=8!Hh|8ytNMsX&6G}gZJY8U(EQw_rY69H1Q<&{Z=OU zcrUa9R?)L8nZ1;JvmhNRA<}@2nISPe9%=)(+t3mRDcU368I+lHjp1A&Py?$67lori z{jKD-eA!n$KMJ<fb<0~2EzGMHJ0<CrcV?;h?3pu{{CN`g`q!hB&BvO9+bH#C`aD6j zK*tFeJM(%S0tyd#oj&li(*N#hjcLH?A~t=yEx`)@uP6v_Sf#kEdyz=mKle`|k>VsO zVYaN_XshX{aWMOvm8tJ4h;~#Ms>XflF;Q@ai7an;8=!1z1Z#nx%6%j}Ubj;JWOVBT zx$E60;4#Jusc}(E>G}Tk#dMid`yERCB|Xtmam~)M4WXPrvE*0afi>Wf-lByLaD$iQ z0o|_h|K#b%3NURuYqf?0z2~9{1|Y}ch4wKv-R$^n0&T>rNa1_I-Ze$oMW||-Z(&mJ zviy02{v93G+X6S~F{Vlmz>b8vpUjo%=8~ptiAZ7D^ul;sELYH~R3#-mbNL-(;y(=O z0s<D_{J(kTBuv|6>tWuxFu^Y)Kr+(}e-5yb)Vz<#MIO>!02<q@73-7yHc0cTtJoE= zlZmhN!*W0$n!GX<hxpSIm>rvO$ts*WZJwVl{IbWDbWR(pg8~vFdOOA+g_MvzrM@8r zB&)-}Tpj$kKVc{p+!7?)@QbjWgbF2w8BEKx&1B{}GZMc=f4}2j0P!XhR@Lo6dEc%S z4__AO{GstnyH7nBtm6>wE#k~Z){|3uJj;VLlh`X;DZr`6>0$HHXr*tjzm!h*WZI?Z zJm~H@be;c!-z}S((MU=>j%QMM_>Npy$KCDu&w43F^<%<Mr9S!f^GZEVJV;=O)e&Un zK==!`{tH<>2LT}BJ!({nS58784S}?Yf0ECh6A4%Yw7()M@NUGK!IREz49$O1_g_pA z>fTyie7=_mHM$V=PHSrEX|~Bck2Tam8$dHLxmkP~zEWKbF7zAIL4)W8|8tUwFLJGH z{7vYHHN|Al6wrcHV7BApq7J^rK)%|CzMi&FcOfUNPI<N~y8t5Lh(YM@*0;dK!Iv=z zLvCI3?^_3f{}1U;)Fb#;<nuZzMU<aE<YkJW5@xs0fkp@M;m9v{^_QG5@*I7G=XoBL z`MrBh@f6&*SYf`py`=Pk(I_%_v0wR62l;HgZL&f3q`#Ay#ca6<y^zI>#jjZakWoe^ zFw-j=cTYCuG^Y)^@sLLk+@~o05w@t6SM@#8WHFTt2L*ARMEaHO(E}%6jwGn^Cx1Q6 ze}Dl0J>Th$VWrfw4w>mGyJlIodNoqOJbb(UAnr?vAe#`>VPDey8|4zKx@H5pmqna~ z?MTs~+I$Tb0stX;16lT*3-$|T(~CC^4U-FMUxZD8yWPX;p2roV11NG>r})4z9tOR_ z4Izf7zoN`<Vv2tl{uPmZEe3PDK_qTPUQ})CIc?*CnH~FOW`D&`8FHcPl<6<!zlcN< zK+V!c3qbjL$h!kN#+IaTCcDuP9J>;UvYwOM)K}ZJp*~RHMyeZg%AxC@m&A6N@7?XR zWb4e#(j6(ydN=ws9;3|&E_oL0vaR_!#UEzwh8(!dq5sV{j=YTC1X1&4M*{vlSUg<8 zV>tM1K5D2~uO#Uz7xz*bg=Vq6$L*&9G0ecC#6spR$o=Yq5<JNsf!OX!JFnxy9S~eZ z%nWY&vJlFk7jeyRIe^~0v$uBS6LD9ONk(W|XJu#;wYb)lP8qi<S2p-_Z4?mA3B_w- zS5{wf4BGuL?_QZc&X)nXQBB{@E8+u)3v$WUsz{FijsF4aQ$%il&HDYTiS1lcCAL0Q z42C37c|#1&CQ7iMD=u|M=1+6Fx}o%v5Gl)6;qv2XKfz<MioIRnoF7`0iuP6@mPY#u zwH3}2qnPFjULN%(?plUwsnY9^)*0hKN6o1#6%z4yNq}6=;Mk)QHdBK3Uz-9|YYYVX zw}*VM`M(RhZe&{Y<=qIkh`rZy9ve?^F6@8^MQE1s*(d)Sdn>^#p@)B>XqD$BTSLWN z)-Y@4cHyymC{0dhD#vxmqi<#BBe-;Brdu0|`Vn4{Z3lG)7aURhnU`2O|0p~geGg4) z!PLp}ti~t|E4Q=}_CAI+(lm#!Udv-|^%|RQN}%rS%H0-~PiO8M2Z!aT;-kaCYZ^MW zojEwEjf0co``?@tgrz@7%O-OaQ*ROZNLQAJ(YN=SZOPg!>!g2NniIquP_P*R4IjU_ z>gjfcp1dNa-^~ri&2Vj+O5$Fb@6W!FjK3am!}yVQ+!=PY`-87u5gJ_~UU&r&tJZV! zk9wyVlH)%o|8;K<!UJ6}eM4%If4o9PMANqlpnxjED*=uk!bOtDwh{*`S%b!ipcn6V z8bXV#J;uuu_hAvE6b+JlSmAySq~!o!g@2fKdzwSNHg9gQ?na@nVZB2@(!Ew;TwX+e z6G`{$6a6)B0L-l0Qr@O&4C0hF*k$qibxDL~bK6yk?kTK<y7Uf4eH_rb1ZBIrxRS(} z*Y8vtj*l3M0K|y2Y$SF6=y6tvPVU3^3)3<DhA;U`k}az;B9F>|q7a~*MuPeQ23d$g za>l#ABHTgF=mk}~bFM3qVr{F!e5;VfDh-r6?cTsc{9R;B<*SSL3_(a7%;LbUn`diX zZPpaK9@N({M$kTA?zSB-<%NSf_v92}%H9lLD?B_Vq47Az#nN(fv)1V62Q+8PL0Q5; zak5Spaa0d~s}lYqp_N5HYVkvGqAT#uz8Sm9-re+A#wzY?JW;PF&xlmsnx{mjE*{xd zX~bKdt)T($%MFpQ5LZs%4`ju50MQTs%>@!Gp^QEyK4{wsOltZjAR-N2XTM)c3dRZ; z!CP88MUwDN=bc9-EpA3c$6K%Vs#QSp5(Z4Qg6jzpBp?t6O7-SHFoM==t)Cxwv+sAW zJiJ05{tQEMG1PYC2!iP9{t4~;O6}>&A(~frx-(T-pfpMDQtCc=UD;Z(AHK}4XP*68 zqW#(pK}$oPF<?v{B7lU6^}`?19aSW74xIY8g93^!go8aV9L%l`q>bD}Vhf)7jduXE z(}j?}hr+1q{_c9)Qin)eM(r-VR*PgUqe8jg*zyBd1+@f%+rPXQxTn!*tMZ`jo<Vk= zfC;K}<?1D3P5P(7fvyO=K0)>CYWy{%{UZFTfolle=*d98;-XikpP@I;Bo$hluL#bN zVG0o_R<|lz4v+qIRDVZl#(9tj+7#XY^G!<+K$rBty{X8!i--gRhs3rd(xznuMH+Xm zCjff9R8<khAQVjaWPkX4)QkV9c18THW`&Z1?#5!0b-!I_JtR_MR8KA=HrYi0g%x@B zD<Yc?pF5dPhWAEw=1?l^fRJ`baq{awTI7Eb>GkwCim#Shp~+fMe26_T!F|%iiSvC1 z&Zas#?u|-kl4PvScL8I&PcCaO?F%lceGSXz#CL>df|{G<E2j={&;T(U=h)w=5Mncw z(O9Zan@gn-pBuTRj^cUb=of;eV6V0jxEt%SNRzs$1Z~Ef`F!G3bECdFBOevEqRX$K zHP8DTh=o;fz}<ubbK9V6@|vvz&^HWLShg0D25lhEYlXk_Lw}-KdTe1u6R~Dr4i-=d zF{1w)GOr-Hn-8k8O#jsLp_N6~u7yG+t&wow<;I*@t61(U8%PL`0-Z$p@;%PM+gwyY zQg@ZVr|$GzSQ_!I0-Y4Mj2*ilFJT6j0+e@$JGD+ju2AQVi_C{uoqGM8_@PP4R@-p0 zi`ct|BXycZnbiSHwQ<Md&Ds-Td09PvUF=E4S|nv;&U9KfhN8>!yI&{wI(T=AlElWn zFhjxyco;h5-o5%C-8)%UFC6ley21S&h8BAlEs@+}uK&TCO_bJ_^WMBoBk+myXSYdQ z7$`exGDa@|(e|<)Uu>cBNVaJ!ea@7R)r)X?pO*E|$~Pt~iY@N%noa|i9(L(LkE6)h z*Wk7yBcz~2W(W&;@hUs)<`ozH30+PdLDkq)pCFb-oY;l`k$ZfqfkUa2%>L{JO^~$S zxrk%)h2sC+mntRJw4GDCA;GQhvHS#RbiLcacUF>??cSh79KWynooWmUslMiXRS?Mw z4_qIZYQ$y~=li4%E(CyXLpz*DpZl7gT^P?WFYu8so$#SSQekUt)|{d*!-QpWZ^W&f z^DL@{vgriLdF0LL{>N{2HI4h&sk5PbFT~l2@<u03-?|Dt19%0+MOK8RL9(L&Bs&WH zdv@dq%Pe;dLi(K4d2*gt`4Be30FBXL74AiIT_o{i6!Jo3z%S3sHnC?^%&}8RZh4fa zId1y#j68LAh+gC_-!MS>;zs;9(ia}M;sHlZ5?yK2BF+Me1_A%l<jYr_9GXoBDV}47 z&fLfIJ17BR{-?I+|DiJ!Y*A%PV(Fz=Pr07yMJTj;68>V(a-a(H)W17Et>NdVXGX*6 z-?I&uY1%VE;B7YT+4BePFF^8+f>Xbo^Z|aU<NyVN<ak<5TUkqeG)s%{I1SZ>JD%Ut zZgyrQTtv+E4em;g;nGOGv0Z`+MOgi?vkJsPSH0PhYlFcqqHCA#0kwWj=eZg5LT1?9 zxd3rx5#M&QP3|_x!*enl8^eRa$U|_BE^Xy&pveX`_%v{l8jkGm>hND^IY?&2Igs>n z5h@x?<!c-RCfoHrEeSu%Xq$KkUN2<plqAZO^7wAbRuZ$`UY76P-=1&FS$?uqUA8WD z6u3@MDumify(2h)nCREYVN?8<!v=9B^+3#a(8`S9rOX(h$B-(P+`IUf2t^+6QwauO z1Xbv4@FndtOT0{m)i&yiZyz6RYg4P9D(5u{>>Di7e^cQyUv{n7VV;|s>A<zpap8_N zzvh5A6OvKB)xe+f@CudF@b~diEQ}RtQ+qm1k2O4fo_0eK93j=Ee}Z(sNNEfrj#|vq zUzE5BO(BEQV{z18T7n&6ZrkfB>w!dd+UtW6Hw2a-Rvm-Cc<Lc5(i3pV>lG71qzL>r ztAj!az{KJ}^{ehoWyhX}=#_Y!;!J^lXJ!#)D0qg@Q*Err&sX9K!MzxITnSQqBdDEc z-}#863&Y0mGz$u*a_>5e(RF9PrmFM*{PEbiw9sScCV3=x3PmrtPIsiK*@i;tf?19i z6Ua#V>clbd!A&H9{GOD;1VmmKaiUvd|KLunL+*W61djqUd30$<1kn@o52F!H5TD$y zApU=fHA8L?YZl9&G)W5JM0`)<DOsNlVG-?P*>_p+`t~7+2+==7KZ&O->fqF?fwctj z!Ee?Ve3LtBK^EPb2jWWf(-%&9iKT0o{Ssa~3^*Z`TBQ8q$IA<!uu16$2rHI=Wo2@+ zr#X(JF@u$9OO~}U>wDv@;m)sqibjmFERKrdlR`z50kzL@a+2NW!^>Ppsd?#Mni0^5 zIcnI?be%_}#|9c7M&#OZdUvh2ADn!=v?~SyHssPhqfq3fe<PRw_DgqKF^UH7-C5fZ zcTmZACX#S9z!i?y3v!bqG=7NLO3@h~5N{`c8P);u=BZEbmlsQ0vW8?RBV|Na8(xU6 zU+*qOssaxgAL@l!TiXP?TB{641+HRsH~QB_jfO&<mOjrA8A2-~R+#)VkV``tso66h zF!Iu7HZH^OTc}Y?Q#UJd+oTXXrug;i{+gQnpX`|9j6l%5{amO*Z$FdUIX9ua`y=o$ zrvOvX{LnxU$|0PKDhO0C|2tIJq0pR}-ZJhz)m`XRvQv2P#m?Gx+|qoO#~*+(GQ83( zm}@%{I>1Y{p!K&X`<5AWgm*uZyEi=cV5ue|+OT(xcBwI=qVb}{;L!d3SDa8zddc8& ziA^WdGqfnzTPI!T^3v#+;n9a?Q)f_2YK8A<4rsA6zgd#M&|<%(5<^g8S9YDfR@y>= zVj6IGxtS#YMkd5~X_iP*ar}})gJ*3?{GVs#*-7u$S+Q^VXFh+mE7L&mS(w%z@9c|4 z-dXT>yaUIskBeo)Zsf@$HJXDHhBFg_%pdqEto#fD4hIPT%jNk;+VRW*Q~(n}`@*w^ zR+_Zk1x?4~XOqW9*Y0=RDj(Q;ZCm;-@5I~|n)&)g6>q5#q<9j`CjLhsA*ivrVyJ$r zOW{fWLM9%hQl3&4(9PvLyL;FEBmCvZPTsK}Swit4I6-qNQip1yh6V<?XMYyKy*7}R zYW;2U`5Za4?>epFUNWjMz2-soVzgC)Y)bf&MM08Qio66AB&7fkA3i1bN9@Wuh+TMp zi(T;NJZ(sX2D3Q`?$Pjy7V|_ogg`2zniy72Nc_qF|2PL<&aeYalSkyg<|B@AkdKtk z(=Dq9RIa93M%djf4==gNA8~izMdZJ0pGZ#(Qib~StmyLLBUZ2NT`0K&K<1;EOv?{a zWp6;mhj9Ks=H3Gu>;L~BE+eySLe^znWMn0>U6(z&jBLsZ4HC(Y$c1d#QT8ekLRL~n zQbZae4SVkq?&n*dPv1V@`};fh@7(|2{r}(RbWZ0K*Lc6i^Z9%{ACJd#ho;>F)d^Y# zy^v>5Jg2}5q0XZw8~=T~=0bUC*72TY<HzUM@XO5i^`MD@&AbfPd>Mk->Za@<ARdrv z^>_%R=A5`~E)DW{Nu3wu_F2)$%`0alT~})s$(B5#DE#%C&%Y3E$DzF*+Rq8<UympO z35kvW42g&^bPpZ=Z!G9v?Bd~O9Lt0xCh=B+I;P`<st=M{A)xq$S?%m@avENoSCVJ{ zrB8bAN-adaBx}uHEYBQ-rUoY)0z~eQ;`_Czo=BQ!@%xA&JLZ?1`Hx*+t_zt!^;*~m zVkrAaM`?TxWSv4~AXnIYj8Z-wPLC%K9Ixkgcl0}xML8azpLs(Ekr9fPwv?6Wqq;x- zQXCIT=k9^1lz_)}a4Mx0Ajcui4JQ*#I@mYMzA;@=mTR1IQ~W_-(}^@0!%(H^ziF)t z;lfsReamJ!YEk&L`%Sx`4gYGo_c)a-_s${T-{%lk|Br?`axKHB#9xFcUEZMBB?8qI z_E^jtiS-cLkv#w?kO<^tbWvgI9%mYMF@~$tAGkl3^_%%@DjtMk5Xn1UD5R<3=vu`7 z9!Sy-#{l}(?FI@%S9Hiq+hN$zhd;#<WgS9k1-rWOSzABzm2KzG3KS8Z97rI$alqb| zR)~#Y0-OTk1Fly7>fwzeAb}&*KVT1lvYDL!n-3hGnfQ66ARM>V#drh#>IYEby_&8c zlj6AcWxw}CUUExfhHMF_o+`jU35<(sE_|w<={sm!{{pnWNAt99lXt=YAaz?tv$xuz z<+16`qxx#~2n4h|HTK%DmkLxL(9#q)6g7E}F)oKn)k;Kjf%&pmf1WkJiRI-`u!J-P zY=tgCTn~I%>;a^4l;2vLORo1`sx!Ah8L412L#%FPNx=bpZ7ue;lBT9sRo$%4r%Lj^ zg*qP<TSoPZJ_u{TP^1?j`n5s`Q=t3Ff&aCq0@n(YRcSb4vlj<mG_^KLDQRniS7LNh zj&bR96g>hFIqio!&yoyCJ1RhFW+;tcU=a*k217q5FgyAA=sP$}p+)8SZ2~s(Ed5vd z^PQoA_&xPprl!8M^Q9b|DbUj{egsmX+VM++DWeJ*EFhA@T%8@9Fyg&n1|&%Pcco_T zv$bP4g=0=T!lMSFn3UtX|JJHz5CO5c+-*>0n<)I8SADAw3VaOl15+K?m^DYkPx50D zTR(s5YOKg-JK52e6~HGwY^t3vzk9*4?dc|0tO#u2i54~PUk_`qr+)DIe@35w-GD*w zfwD#WY3tcEP=d^fmPqAq=%Z=65p-o;9Zqwq6fjLAMc!c&!MLy!Qm$trN;yX3QOjxF z3R}}gt^rNJ(M9}d$Un6eiPLFfHh{~RXIgG6kQ)KVIlPmQSvOS~gX<Xu{gHmqBnbHy zUr7(=;xi0@al`FznynLY6W2bkg6SbW0d9TLC8^S`nUc=EJmg1DuEgTe1&)}gb_6&) zqU{qQOdu?)D8vy^p~CX6l<TdHA6GSB+XYT)egx^T&q+b9js2uVaB@gn;=U3o2*k$z zq8?G>$>9tZo;i2w*S!hHpZW^?lI<n!lvo7lBRQdo{hg2h(b#;RhW{$L1o}ulaL05h zMrHwmFT;qDyp;nuvkHOWSyD^gsn{Sd!Vd&2_dYl)#3bR}zqXP=UfwY7+nphk2ZUzl z%qNC~zMwwLtvApP{J9W@bkV^QhNcin;frjV0=~$7BmpQg0lYo%TFlUFtc73WeP*bF zkqLjZiQ*2NO>@5*EzUfuMY4e0vW;so9}4vD_H$c(Z^(Q3J%4iGB`deJP6LV;GW%lq zW(HW*{l9W-q%%GC>Yq9Guf+bZSPbd(d%iRO(!9OT6ngY>842Q|`~SW#|C#>=oAJiu zL0fhbe8D2jzCac(j4;fEPUm>r8-2ki;b~1n)JcFe>On5piZGjj<)$LR?I7>=MJdLS ziS;uoJ7bV!k6iw~MkGg`0vgP7`@Z>NzeKlX#(F7O3ssd^^FLCLS#~+R8LFg0_fL{t z7rRvHd*OR)5zqJV)aF3=tUGozv!n_mg|Q^R?(+F8NV#{rm}&N6DY7kEQTwNM4uY-U zAloQC!1bs^jd>ZrU~e}>K-;VjC#R#bp^;{+%^}iZyE5Fd5;|mCwQV#UN8_-GAmM%q z{6anuQio1|tkOp497th?SoN&A9n<H{cCrr#4hL~s5}f)6jhmA|Q7cRV7Y;!j?%UF9 zMQMit%PUcqUY|V?FA5oGtlgNL>OcssKmZrtU<p#?jYEV|pc!<2_b_lbpy<@SU?;`? z5|d;AIrGP#W!{UE?FQC`Qc^W?<}j&Fli;XQsN+`bG5&_@Q8fG{;^F)QsF1f2HEcTz zlzkMX4Zv{UvqhK%i8dcd8R}#jzXVetd{=N?WKRX+{Dr|9Tr|79%R5B-k{(d`6|Ok$ zEWgEYvl8(q2sak|v)sXytKEC-&biGB>z(a28*f0OUpZ&Wd3X7hioe?Zk!-^Q16bVw zTG<0N;HuAF8kkbzrTcLWah4G)y}G(q8G-(I6|kA!`=2_}7c0T|E$PD($|FZfqAC{q zO>9!Pf%{pQx?441eH5PL!9ML7r4I<e3kVwzRJ(KyJLZ*6XHm~et)86T+1YaKNEXc+ z_q@Q{a5G?QM*2!|i_Ume&cF+xVB3SMyrbU79YA@G4Y&Y(;>RtC?uT{al%CUId;1db zfOCt8#RMpUk|;#$-%KYvPVP*3p7}8|)L`)<hC_7oL#ZD*J(_y_5eQw~LD56fJwqZZ zeg24*E4=i~^8&ed=woRwqQ?c+s+(34SKgXG-9&*v<NkNrM+zt{+u5Tfw6!HuhT^Ux z>h7wyJH=h6568lBn}BX~{2?dFUmUu^J#?Jl?=!ZSlLVQ9n4Uv%cAx^GVc;(lm{r(^ zFEHo3`uKI{#jxJzjKve#E?nu}YrN2u)wEjBL6(^L+dkwEA#xHP712o-qp(?6yC5$` z`}v6%(`|ku(}(>0G(TV?#NRx~dcgh=1CNpWLv_Xt5ZGY3<Lb9pKdoLOY!hs8N+l;< z%_Tr=6Lph@9+p)+C!~@)Q$~B@bdW0doe*;3AaYF-L4QzP4A~bI&V!>*d(Gu<1pbVo z)`J=(@1izWtKXGJ91|2NyiS`|xeffFJXmnVVgp?OY|r$cP|J7H>C16}I-Go_C1Xk! z{=spxJcQ8qIp8|1FRogz?ijb8s(r2{SXNkg&-NMMKezmH#zx}FxdgXE@|W>wZuRKI zFphxt9{u^ctf{h|E>4fdeOE6$;+NfZn+RpHjuo-03ppBpgM>;8;^?h?wC2hKn;=a* z{NkNd@!08#l<^H{a|QEIH|Ti`6}>8gb0co|f|7gQX{(LhR|g(YewaYKbrV?99NT#3 znK$qnjANWvpRxesboN+}org$T<?iYG=BeM_B#YU-&;VtmPPMf*`1l{X|Ml9XR{;Lf z(1rf(OhtEvXm<9Um1EOxkfqH6i}$&oH7V&Fbiqn;fQf{MS=mPaO11y}ZbC9s#vrF~ z^jzS2xR7~;);qsO<;IOw^^J|>;Sko!98ZR0B1E<^N<d)J98nq5{2<PoH(6z(*-+P? z+m-j+&Ncgx#K%g9C*$WnN9Z>tMx{62zVl?QBaU00%^WG^?fD1<v+3IdA0!Hz83~@Q zvAk4j_QCHRHevrS>Wn!8SkV3MV*ddG3iV*<Z=aH^3sIYT7(Y~47AL0?8Uosxb`lOh z&UddS%@skZ&3&sdB>QVP9|Mo%<a30H-MxZ+elY4wIY@w%G8rbG){)sz7@fi4?t&^T z2$A4_dOsDGd7hi$q5&O2rDaZ%>6JT*fsIb~6j3j556>tIAJ=>-rKMey+hgehL`2CL zx0TZRJ{ZI{IMD!bW(6n%jY<lavkk%-QdK{gW^22kBCh6V2!G(R9P2bzJUZ=LxYEm= zU1)g^ry|*~*m=|)q<`slQ`qMP;8|%_Fe*Rz(@23u%ocOzzBz87q~(?x>T<%etS5K& z_)3ZI1%27*PNUWBQ+kM<O9mJMstJ0-9WkRz(6)N{epZp&z$_qE&WA1JB;8-Z4Mwp2 zo=S2vhT-`+kYuYZRwQRlzE2}Tbrxyh*vTO7#NE~4DA&0AY}co=%ZsVq)5L~%PB()( z($HRy8t)B1Al8J{`BfCQKp8_y_&kZ2gOzfxFAJ9nj^|4O-hKQH4fApL;#<BBNz*$M z-=9@y*Ld7SK%rYo_tS3YzTLhLB5GD!pHbI_N2Y2q>0BJ5W^8Yl?A;+@n5ID+&CAv9 zW{&p$xK|y|t$uu%ACLcf()~c!e=UOG1=TE0HZx$;nNZ0!cmT~RXfb|p0&FqkAXSV| zqc87;n;7GI>#@NJnjerAO800%$|zx|`<yhY>r71VJz|!XZ{X@D<te!szIuOdlPDK% zrH}1or#S>G#$RopuF-mex0TiK>1k(S;pGPN5Xi-?>6le=TudimvPitJMW@Y>hY*9S zq`-}=z#X%0*(sqb){ie)(M74~gJXaYO9!`Qg?i7MT9@y%KdwPi_SQP}gF`CV6d+Ph zP!tc~kFg%Va7=EdCAxbAVptLYt1pr0*ZHhbzte)-77;i)S>2X5qI8Dg&mY3T`6kUy z_^qVJ_^FAHRZ|@a-v>YsRrgp>V-SK$kb==yH26z@@dKHe0hC6~wd99cLV4hsWDg{1 z9qw$?V$sE}4QV0JGkCtH8-CVjFuqj3p!Vqaj0N}n`<!?0L#Z#?4{JlNcsoBy$jo-L zUyMEQ=Vb~0SL?G+=DLmurD~21f~MWjq-_7^IWQAWTSAzlkWwGv@h~I67sW1TFTHC= zBjr~j8rL$71wrY3+YQJ-bnhss^*;T}^@h^Eh%-lA$2?w&3X@oQD(8|9AQ!pGM`mpA zD79Hbi}I&euEB<Tg<EH?X_m;+4J93fg4S{Itij$L<wlOwVb}i+`J=_<Hy*dioRzX% zo&CgN`jME)l9R>Enj`Hh2wF(w?S)Q-BWA9Kw1_;omPv_Y$4TDfH9=2dz(Ho&yOD_^ z#$BBe;cNGY{Y3S5TvO_ohI;RAAXI(#eq)mkERz)v!l3;vfo^1Ph|%OIEMB`ke&h0e zj~(v~`%_Koxif6i7G{n0+}Z2Fsmdq>u4Cr;Pv9ry?}cvnz6RY^0Mh`Z4SoM@^Vau{ zgghw2M&*q9NEvWQUQs)dpH9$YWTeugLA%QOy($N>$LM=&#~>{ktPc78ie&7vqi@tZ zTWmF=DApxnxKAwzw(N+L67k2$pa_0JQB!BgK}KI*oEr3*ds`3_r?6}p8V1cD3+&g* zt0nQ>+E^0ZPIc~v_q8sK(f&}YPu<f5gA$;RA+7P##!C;}@m52m48fJXb}{md_)Rc} zJ3R5eJjZzow39MZa>n1w3qWH=lp6ujsN)v1#PoBpze0p*Jz!+Isa+Kz=_CA}H})@t zg`nT~;~UX2p?lx*lC5c@d}z~*6ne@fo&9G__B2+2my5S;E`qX`bwnUG&f~6lr1j&| z%S_U!PVg%{3bMt69yxI#NCJ6c;09z-X^MBpFN0^S13VBPCj$`fz<9cyQB!Op2p)No zGyDJ(l-Hg)mk)45P*$k)&^1-a<!JiapnXT^%Rb9OUYyYxj_gIFeQ|6!xbkS8Yn~Is z+`Td!AbxSy!eC^vVsW9w(9X$GhnQdijP`f~RwGjPfY1LT{lCtE(kf6V;lV0<OFTRg zwfunU@Y^Pic%%}@h`6qBVGdGGhHc-+3a1PVSAqH4dik|Rq@$;P|6uZ>^q3#oYk1i3 z5QmJ*i?>bkitAr)j0R=GNn3F^L<xQJR_P#c(^5iG#nrH>p+J2K=IyV$einyO5w3;I zXab~o;`)y{nFjb_hSUAX^qm!pEVF596f%9tDTD_N3bFicjps0?^hsA=RU{fb6_SuR z3gYLpom$Bv7f~8uU~~-I1VDjA&*@6eLEV+pgi&tUar}}Kmi#&?XQDwqA0Z?dXo}O( z3H_c7sSI)M0g%;aeoA<t%gd~-^@dbv)#=D4)}+yIgFqJqBf@mAP{`s+Zvz>sL$vQ1 zma=@ZxGTptl8+xm{YQSd=mTHoAm#+_EG8@Zj3(h}`6u|hG$)M$-h78`M|yNsgZp$7 zlrQn14o!b+UgZ)FZwB@c^1DWD0Ktjl&QGr_3rHtX<_*MHp9h_ET|<P->GB`I@S^-) zGPq~f;&c?Sj>jDXXaT{}5N+92RVsP=h(SCW@p*c)!Z4d=9Ii&p;{W>2$;a=xQ*yBw zC_=n2WAtg$iWDOlI^WhLw*hCTz>)6z=K;$+!nTM)%Hv+lgy?Bfxy`P9sgl0YmZ{6G zd3h4nQMaANs7PBG5O1yR$5ng!_l(HSc~-CcNxbR$S{(<EX5NZtS_m5d3xSPB5ZI)D zBCx=Bk!;!)OI=%SbChAB`2viAgK}N3%A~}R4(th{1BZ^FcefziIW$SuhYfmpEftEm z{cJVsU5HDd;_M5jJbX+Envv}NGGZqHg=ivL-bqIs{)Ud`OeDPkWN4Ym&x{&{$OU;+ zkbR{5U+klZ04{N-H=K{wp`_7<TF;Oe2Xa59!-F6q(}w#-*Ge1HlK^(&9Z;ka_>X($ zd5^?5+)*1LjY_et>anR_KH#e>h<55@)V)f>JE*&nZ_pd5MvPNdO;Etyz4ZA@L9QS8 zD5z!jxJO~`sYH58G>$sgZH%Vt+8>mEho%?gdY|AgjHE#H!sdO}M^0p(^m<TuJqIzg z9A|~Hg{<=J4PYT_K{2SCDNlfJh?jTK0{#n@y8(%-;F+N;IjQFKvD{Amj4p)DIH-mt z3$?&5B8oi+oPT<hjmCSn`*LaYr+b`(59rGFG?>=7-Rn3VuH_*3WPV|Ds_f;($DbKL zc4bT{BnujM9sw(w%51CUH&+gF1j06n*tuW{jspU#I#Z?{3T1{^jEv8+Q>?w+$~_u~ z#H!npm?{QrJ3ASlq)VLf@T(`DGu+uV_po<vA;2?Q`D2@4P#ejiBr?}}fn<KN+ee2| zXiDDNTT|nmk({hSUgyvrxL^QW!#MJk@4r1Aeu2xP*u?6!tH~1*`U=Yr5L-ltPWq;# z=g@jkBA|N{);T_Gzv7yg=BUHWQq_)TA<J8_(ogdqe<m*F9?3-YM2v7AE*h8(;S+dk z<!=8c*Yli){FKXn+n^5ScDxQg=ap_Z|C2h{3>A)E)nLCDr=$|@WJDX)es^MHEGrob znyw?CcqtRk`qn~`_XEo8M?W&;D5FH;vQ-3`Hyxt2Xws%p5o*<kA@O~G8p7N|uwLp- z1pDyiNVnTurMcNyCj*?C!=a-y!%a4&v32))Y$XlU0m{5ztUQM}OoD$)Dw2pt5!i+v zu9gOuCBQo4nI#N{-lyScunspVL~5E9N@d=SA3bf94tbd1gz5Q8uiOl<c&0L|a=A^W zeL?hXp#<P<4?24JU!c<~`97;|6Bs<F)226Y?ud9m`*9c=G6b|?7Eo90^Z`$dTE1<l zK&=ROPi?mZEFdG$BA2lATT++ihGiQUUa<c77Nf7AsiRtHZkwR?s1~~2x>C2xB#k_M zXi-`|g*|)?NSi}D`f9n}mkzGioi)s5FCBQb+Rr_@@uS}~>m;N;rAT>p`_38mz0@a` z5lMY2|C##K|1JHwvN(5{P1XYmv>R1C2vje=KM4GvI&`H!+uK85y*vK3Nq1szUc^S- zB9iDZJb0oDVMcIM+NxpgE_jtSb_YELM6Q+Z?wa3t14r8Cnzu%sd_YVAh1&lU^NUs! zgP=y>3(e%X0BE8Fjj{pvSt{SH!7H!BBLvb^;M(hb?!ywE)U?!nGFy7{Q-az-0T@3c z|FXY)Xu1i~Yr_FBP_SoWINZVuC;>DAC`frnKISJ$gEea{klc04<!M75GfrGaRXM61 z>uG0BGoZtPNdk~64VTX{;SA{fz^|w9LIRk#(A$BXM~{=hh&{V+fuOvV?@U#YP?T0q za46sQw~$5M^SxEWpyxLLJ5$6z*0~YtHl@CVH#?G(8r2s*=v2cRA1xu3f@FJ%Ui3+Z z{hW;h>Na*77cdCcpSRTm84a~Ji75SPZ}M$<o?$Wq($b|9x$nXZ6;Kg$Y@L4u0*}C1 zV&?71^9HgL!?Nc`Uq$~N2r!8?A4T{OUidzOjy=Sa_#bG@eo;)~uElOut&GLMU8*Uc zxrVi$=7;vkv-s<3YCT~GTwIKrZg%<F)yS+){YXlRX+Jq9EcHy-tRh4M9T0Tx2&ug| z0pjgJHQMh`;$gBAp)CiU*00Rwva8n-hJn%F@AoId3JdAnR~T2nHT%SIf#v=;umI9z z2vK8WmU2lHc&u&<<a%hR#3PWrp}ssXWDioF#_TvQPMB8{)Hu_Fmb?PfZ3IvnM1r3V z!H^9uK^Lcp5WFpuG@$ku%6Vu$#RjP|=m|Z|hcp4~=(1A8pS-!ttVe?bjD>MsMNlFV z-C2a`HT?S6b@)M;IKc7FAVZdc;^Fb~)WGW_=R@eU*Tt9*i2|f^8$8`2<vU}@<=?H) zel${CdQiWpm2iiV=J}*LcfHf@W@tf#<mp7(5=-uKCk*3JtQKYiCP)zW*j3H}GSdmA z8#CTC2bB_G4MC&)rruld(ns2TH{fK7lg5sUY2O`tI3jM_X(V7>iT9HUwC?Io2v_Dr zw3@Apv&W?OFntZ6i(y^t^+x~M0l&tTJ@_uaq$~6BDd@-P^b`_rN^{a8$hau!dyY&Q z-xtTgpyGh&P0gM$i#eer3kxr?jm_&i{-^lJ;C8>xM6~=gkLBV7_#q@&xE66s6v$6K zKbEf#l+ic6<s`_Sx%XcL=uXJh`M~Z$A~Nt>lyolm&J+a~8WqJCmS$_ZJ{(}3kurmn z?FfuYkihW;Y_FKmEwn})UI6puJ%@PzsXQ=F*k7(nOy#>wS`yuOJ|qsY{ubIM*eZS0 zE#4MKjgu4%QyY6D`Bya{b7(EQR~cYwLhNwB*2OQ89#4!Gpfp4b76@0SNx+vX2_WM1 z(k_wg%1fWkffeZaOr`8#gPLRm)IYrdqFpK7y0;Z?E(?Ntn!rj+?%G0350snC;`VrF zTc&)Kt(4;z(<(21dS?%@)<_P~Jrrfh`(8zuIj545)&`ABorlZ@aW3O5z~o@KV?PNC z-qSrjy_a$FYH)Wr!DW$*RNqGm#)xTn<@=lxtRbLI@TxyC<$vSViuOMHm8W*RMWtf) z^J6>zx-KdLF+`us_c&DZ7vL{|u+j*F|IygOSK@7BZe|B&y=gMs<A+_-RN@dpU`=hn zKfXVEYy&zGrD0E2uh^L6(&KAtP>S%zzTRt+h?0&!vsmGJkXC;yA{hVm`D{;t39_;s zu(GdrA9?Y)Nf`Sd+2s$9uL$jozfVicWuf(s$NrUwLpa(&z@eit@q&XuXnbs5ZpbuQ zXlWchHstZ+gA7A!JKakepS)jm`Oiv7cx9%Z3m98+hOsM2zO!o?wK?ay*LG6133!x1 zdUO{buaOMBHs>Um>@2i6_pz#^?plbKWt~Tn4Rx#t43)7R;}X0P?Us$D$0*1I{H(Eh zK~L^R-J?`&RAf6g3|aJ5r&(as;;l7YnKTAdWUl1HI-Q<@OH~)#t?pK<GT`P(vJrBt z0viuvc=~axk(JtZ@yE+^FC`G0!hr3~B3nm$=AW;DPEP1wQnC#W1TO&u?YmkZiH_Cr z=*s|*vmI`nyc#9SV9t;b8PE0kvla>lBy=|O%Otn5qKmWhV!(@03xH6gBKXZt7+c!q z;<5#RZtq=XLNFE&dH(bgh8}a#dwnF#*uP7;3maGj^&~+N1(}@{7=c!?>Cq75ZXFwo z<(&EQ(G$Zc=iHSsP<)Eq8l9cHk1_J5&UKVlJLw0dMB2mR6AaAqGoG~yULqfs%69`T zu+9S?glX|C2-DJfcXw`<JKbSrC?qiKo$x1VmzoN0c+~J`i1x12NLMm|0>_exG_E6m zP*~1El-BT=O_G>slR&c7)l`UaEj!!C3<jPp#qJ|(<p_c~Kibgd?F*fIU!fH7+47Ac zsc)kKn)jtbVYk?&!4nfh4NnTj?7kuIah>Fz?RGDMB<U;m=&4Z#w9ujHadJ;P)#Oo1 z07wXJoLD+5LIy8<O%uKk%Bqa%>k;cGT35T%9(136WO5-)Kvx?@&iHWH?b*Rq7!JDl z!=S;()0cx4Pt*h6zGjdI%SNLGMH|<%t@vW`1ebH5{HpL-aWSrjS&J3t2Sk)5$#S88 ztqyhez3QGYAd_oArq<sWplr_|R2;?=Txt8990}?DR|`=Q0tfm^O!N_d*!~A^DO%}5 zwy-TLN^hRFY(q8ismGq0`2dZb&SjDxPv@SJ(CsLNZeL@<`K-+f=cx0CP(L^Q5`IX7 zS_dHjK!e|83;%wpm5ymwUuqO-4&LuHf`KdV%52K2Y4ZDSX?%0l1Ma|y4!T+>^c*oq zmi#7j!$nh;sP#P(??5oqd|+8?^gzZ7I<05b?Rr+K_62)~o_EtalgO=psD~!Z1G+&k z$v2s`dbd;LcD%iF{c}#GEn1lDa&fCCJ^4|5G-5;e*^LENc(OlldDdG^%y$^tw|*~* zKY8xZhsS<q^;QaH$wVzG@c*XADrjh7a6Km&8o;KY%=o`=iiMLboda8qhD{p{kT=KG zQD%k_X>dl9ojIrsG!TX$oT{(Z>)DHPc?-Sksl88zwI`3j_K%0_#oI^WxE`|MINww_ zXs62iRuB5UjjEW63|TQB;ma9t&275ZnENt7y(ayfFAw!;0(#+$%kglljmGaIi-m*$ zoz2smhyNOomd8s&Y!Y?sgCh|Y#uuRv15Tyh!3A{lc$q7s@2`7&C-aBSP_W-{AvajJ zmm&i)jh|<4gXFUls=q!3#xMFXS_|@X-m%wNCXpL7_p#alari%`#fda58yG9l(-6DA zg3HqNu{`*?IuF*Ay9`V?Kv`*!ufzO=G~@={6BG}Kd#pVw>DtlwuKi;ByrIugokwOR zGlZp=NJOKC>Y+Gfi7JJu+2Pdv1^OH-glfP){sB&mCUHj1Cj5q{TEvEBK7%(2FP^im z6Bcn=16|k1O7jEwrt#p2<=ZXk(x>t2he{|p*&?+4av$uEyB>@5T4657yMj~R;N|jo zi5gb`!X$TSR+iYA?*nhsy9Ak)IXQ$y2TGYRDLp-Bmdg_xrvgr4GzDamsBZ4VCY~uQ z*At>XEI%W~EIwh};k<p=^UK>G<!>BT<A}1O;Rgy?X|Lk<t^yE4L@;*8wu4FI70tb? zL4(tPs6`<Ar^j^2cVPonPqwC|FKg_4$gaT?1%dOS_I-)Mz+L&pp_6v<@(wv+nTgM} zPZzE1J3sJXW!dsV2J*U+`{lk=0>|8CEzC7ZJ9ALR^Yr^6f$WfjysSVnN8YjH?{@@( zCOwXJ!T@tw@l|gcKDdzFbF#0Tmz<v#`XyD|f#dFaDDqAv_n^af>Ff_RtOr0zP4E=+ zlCSR8+!oS2MR){Yo7CM+j>T+%?O`rpf>$lTdZWPd@^gmOfV&4Zc=6Sj=f5Z$6N&F@ znL}}9QxLHioQDbM;YvQr5neRJ!G>U7MNd)BNe%{Kcc^DtZ`J3-Y&F_lTA3SG>==1l zpkFdB5vxa#2a3a^%A^~OG?yV(@FVkIjm0uay(2;jWeUgmQkRbWXo4h`XCTaOeGs@= z^yz{XhlV~!pkwa}8Wmm_yxQ_M&@YGlL#l{08YExOZO?Kk(eMf#{-8lmd(C;1Rov+( zro(5Ye{nlaKj&fCG%XoMaeoB5M^SB>3%NaGo1YV*%`LlH<x~{-4qi%te}O+rlQg6S z_{E8|R|ZQv(UZ2&>*jqt<a2(~>hNnF0v>7;BA?}PF2qr;g?OoRz{dZ}MAfjLg}jX0 zJju#krH13pZ|N#7BMbbH^vlx%Fz_-FQZN%YE;bfsx++4CYl%)g=%aBRvUkhH%cIXM zk)H%<&mc@SB$(OVAgqJ-y#VyGn@S%ZIaz=8_H>4nRh99hfk$VZC8}7$d1)M`-<S7- zQ(0&+L}!G3-Si$1at`GXa*XqQ^1~AWBQ2o@;Di@hQH9^@yhAbWhEvGB4sKcR7u68L z5VR1k)&l<si!?f7E&b?Fk;t%w;C6IlHfi=5rJqVH$Id9l7m7HZtO;;aQpt^iR9`b$ z#L5WfjrjtuW4ugz;fZFxDWUQxkaDh8fmxasAh_FF^7;xJxwP)^_Su~|Y|E@<C>;Qy z`>RDcJm2^P;SGVeQ^o2ev`{I)=1KUC?5c+2)?rorIazSp`7rCs$u$P}X7G9J;(#KC zxW~O4BnQSkhd&40^)lp9NrkDf9dLie(}%71fNyh<(2sPtrj`}1VVhvd5Pr-pc6oES zRPC6Q6Vo7lC@yg45<EovF$Lt{Rxj+`7r$$stdt=Ca^?C4i^hqT!(0ZM04~j}F5hG( zKG60v99{DO!21co{ll02A!H`NL?7Jkg(yL~hcLUA9v8pAb^0M>TC}G#E(k@C-bxoU z+>Bx4H!Gc6<#<;Xo}F2Kl!y8xkq%AXY-Ql?9mWSo=Qno)y*NGym8^-J`h4G_+O?+c z)zx1aLw3eKEXCM<6j0H+cp-owF+^i;->qg)<;~=58x0U{zo0Lg`sxk8@HMhoTeN{k zUw$RgzUx};&&#$61x#5o=e%WnS4CH-u??#&|JrkB?)QUfS&?a1%5fv}<7KS>^`5&f zknM3_q2;9^7W*mr6o$<Ih^;0@bD|%HlVzG#UK!Ja=y1!&orcm^=-L29pW(;+Pm89f zsFVrDUZ;rVDACqH{8x>h|FZh?_5+6-e|rIp2ztTXO<r2g>;pUucru61L}YddpJf5Q z<mxdhuJ{YXjaCa?V8S0i%IQ;cC&B3(I01qOsCDhn#g`0<T~$CBDY~ekvTm36DTKqY zas4X=!;kMk9&-oQVP}-|5SrSZT9+5-wENS8uX%oH-rr9}YHhAWZu*of2M%j?P9wtm zpbnPp%T3i|->sMHZNwG6vNE#ySA@4pd`-B3g$V8!<t1k|lWXSs@{wpGkBMU^kGk~E z(cu?#gw{vNLbTu~3W?0J_U?90DbiDwZuxq^OitNLyCF2kp{Vs}epE>hC3Jr#DH+Cg zXDM<NX@5c1OhZZDsRATk5v{eukA2mMnzql?$c~(iGtAeCi)N$CR`R~8avbgxC4vL{ zOR-P=+ox7oCtM3fCn|=|W~8R`Q2WE(bRvfAk6e#)7DGQJuo=LeeFnD**ySkMc_D&x zz(;g?YjgYIiOj%ux7W9LHI?X;j56WcDftYEGll)ZKxYv32#OzCgmHR>*|Y0MneMlN zVYLwCW+tD({yv4arV>M|mF3B5y~}k2rG?H(ygF%s(L8C_aa2?5%;L06@3}swS~=AN z8{SJVa#IJn_tUyzo9S^ZO;W?gcM|D?TO*ACQAjkpV$8U^`x1|SaH^adxl40pkfbCm z@!!&-3{<D2HfBPFhSxx~4atuW6M<2_AU%$fbC730twsV-C4RAZg|kOp-Y*u7O_Y@J z?;XVAD&5!({<tw=_sUthTAJ#IuJCK5mWFZp#sxd?(ng@~QDM!&&Q6xCT8W@Y`wUq8 zxi7tvF442}>^Bb9I0-O;X0HH-M>#ibIB?gB4KbsPaEi}8l{kmEhKbu^R1TK`b+v;# zMvgX#-4H`Yp?3Uh{5~vw@?BG*QBoaWuLpASe!01iGYvc@U%nC>2)vp?lpO?#fYV{( z)u3OSB@bCWI_`g-Z@4@JdgZA8%Fe)^<08Zy3<VOC#A&D1C8;5alq3HRlObwhU+{pq zHUb^)!3?x|$sB}MuN|-CLfxJ&T}FG#Z5Gn8j=Rb?U^X$zefquF#@9$uWERTR07$!# z#$Qp-EBdS}z!`9d`Jyu5h<6Ldo%V-axG_}+ZifbgnN8&MxSzNYu`<$An1u+TPr4Tg zT)P7GGY^aFh?L7N4$s)+U-h~cK#SLel)~2i{d?!Vti=~u(}I1!_a&?!CIY^^M%*Z} z@9TM#5ciY|>5%4{!z+g;#hp<^o({zrj`R295G8{ID_8rU-)tRNo_UbHb!5U=(@}A- zs?mgTuoVtD_mrS<<p6iGW}UeAqW#HfkN8`hUg&HhvgrO`6vTY=g;IJ#B1aKRo){{Y zQlHJN`xf7OJtl1L4osuSFigk;mSUeixEJ5ApG3ZZOx)j@G7|E0kq=7mjO6Bf2~>UV z%WBBqvO|$YWhPtYW<kzAJMkae5B>*JM~@rSmxut9v2q@=TyVovK%frbb*^WNBnp`s zz_9I{MLVp@Q)~)~9CeSgLL1cOqIHd@4#903%088!2(OYzYqw#_b!=;!Dpz|qsQ3wg zwVw#H$P=N{b=?8+N`2I@X{1!2MkA>SoT%&YAkUfp-XgF|s0CnoP}sCFE+mhDZ3<V& zMF=M_FPeteTrGGTe*pQy>OsFxA+kigaUxjywYRqrGf*K-f+F27;GU2KIF)tu5g8P8 z%Hv_&jV^$3oqe;XPmL-1Z&t!cH6!423juI=s5t7oAP%D$O}+FCDM3#-SKN0(&CiBu z=h-!l87D{kH!6!ebRE|HY-gjv$%j1M@Uyo3zfxj9c$V|~zdq7dP*AG*`z9^Iz{>~* zjXA^5v>^Ac>E#MB_!ekh_^etaH$Q7JAm5@q;qPVpv%tY2CIP(go3@egK;N^Jna&Ag z6HPgkR~4y)HaJ8R4*6#pe^9(+der23;XdZ^&1)G%DCOq!G|#7YcR%~vKPnx1qI9nq zA~a9z!V%=?DG}h5AVpi^jQ#ul{#Uk%wP>r%UzyyU`;KKHq2AVqN|P@dB8D-a_~6FV zg(Wmd2>5v?9g5B<?|RFH>>o#SFP14xx>K3$9%$s#PP$g>Va-n#5(QuI;XQlRUmuc& z2f+i5|4*MqKr9&H%#=%6mk(LM-wMIgft&;!esx;rD}Lq<9F|oE73UiGPT|=3_tTOp z!D{V0Cbt*Mc&Pi4i;s%xf6qtK9w?0q^I10fuw~*0o7SGnD6tK;0ReJo_EA#(%IGmt zNQv}J^`C(owv|DyH#=Nu$X)c;Lf{!;A+jBK-p4p`!jtu;|6R%bSyw@^aqf9MtUx)E zLR^S4DP2o~0j@EeTO9ai{;7A`32nZG(+w{b;-}oLSPRiH@HvP$;SKj4W{1^AN<SB5 zGlzx!K9X>8qL3HM)mV~)7e)|0ut2QVh2t#@g*@h^#zT&ty&Z}Ey(9nIC*XG0MbL9j z<yUz5S7H`NJLvw;e<Z2&<1Y#C)D=$8XfwWyk{+b~`y+jUp~sG|SUg7od^j+!JRkNt zLx%fF%!Q<WU#3E}$)p)pKf6**<bd)}8}4m2rvE)#ZFF$QeSttALox7fwjAIx(9Xjq z?mKfW<yX8fCPM-Q`|kjOEHXWup*YklB*Q^~I&eh$a2$e7C9*q(xt|7L2$7AMqx5@Y z{sH8wAp+?n$cFI3Nc25lZ`<&A)OMT7CSCCM9GY$_xpgPuI_lx&PgjdRH{SR-RCy+I z(DET?2NEM<;giu5*zMJzoI!<qJNfYMoeZfdU=pyWA|zj{{*`1{_d0xnN7{pcT9vnm zwrCFSC7%SpAMIa2BZRsFW{4Z5rt$D9)yTbme<5OJ$N&?*LSw&6Nb|nJuE5Ckt)4^R zao6ZU^IVPpV-E`+nm^HpT_vLG*&*(=$_w`^241BK^SU+){GY$JZ2Y&Y2K(#tI;~e$ zg#`T1mn&ht0qB9YQUrQ`^Zc>BJVnU}!4&1>{>NiI548m>f9tzz&wX44vRgMvD|UlO zr*}qKi{9tfc3O)q=?Yj>VE$gXJw5C0?vt%{N3#a6pt`y`hphuOT7O++8t3;m3i|g( zf&KUYHXEE;QOS6A-lU`3>}~%CmsOv4FU3~sFGc`iVU!H+M}u(K)<y&z1qFF{+5$oj zlH~1`r#B3Cp7Kp<B{wY84SM?)ov3lKMv;Xi!%xmH+Mh>m2`JLI;3`j*_@DTQe<rN| zIY^QmVv84F;V}BZ(Rkcga2WUhgCIG)J)e_UY+~ckq_|>SWd6YN@1_0!;sV2;r1=4M zAG=E=9=ki+29-{@K(n(lSFg<oevmm|=ThQWcJ5iPql*+2e^u>Ekckpl(?P70I$P}u zG0(R5%T;rf+xob^!PmyEeqLce&upWTQ(VGU>}8=uC>1C=C-u@9R<HPM?>7A%6#@pJ zKQq03?#8d>?$JaNx0>H!@;@hTtcn+R=K^;VkP^_!4eV%mp^3F{Wud+|1&P#rH^ae? z2DzT^{t2z-<9n+%Nk#P;7%tktH(0(5(xQ&|DLong%~E8z8NhO{-<<4XMC$)$;vmJH zb#N7&6f|~!ab7jg;ZdE4OI~UFgM)NNp-0SSlS&?-lPWre?u^1cs(D4VlR}HfZF&8* zyY_uq7uTWI1%pTKycLkuYjDB6AVBou>#r|}Q%1hvv48u5m=Zi<wl^`{)D*S9$pmIv z^sZ!oL8_^zH%MkS8+_N2fU^H_YfyuY0KsHnR8w(+s71Ao%e&H4S+)_gw?~4U7;#;V z#1xGH6(f_(4;XL1vv9o)ws9IygNc8@FusGuQBK7k0J#W&TlnX^Up+c9s{IvI2Wl69 z5~*2akY_Z549>B>HWJEdp=DMDZ7f5m8cGFkLqYT=#*J@y4pUGqrjK-cfash6r0FL+ zL!K@YgWias<{<0wLPz~Ovb@lxp;!~hu9lBL<4#IWn+hVuG3A}#8B;wEwHGSFVR<VG zAG}*$J5&8h?yUc47xP&J4{;S(x$d_#a~A2U-C~vQ_QxWjlrxB$6p>$T$C2p@*@zp@ z7MY8Ly!&YaO_D6_dUm*0%DA&u%eHD(2)%nItNKE_nWayIE#c7_8_BX*q86QBn1^E5 z{YV61ssheY|HH>oySonHo@?i@xBsZ=_L361f8I7qpk9LcGc`{8A6i^K3lKZ#7bkc~ zK_;b%Xldh*eAD|*Hcq^7Vkw?iJNMG(d3mCXfLnmLpsX;m`1Jj>zA_udMW(~g&fW41 z$e+GEyEc;<)e3xao@f1JYst{K)j;gO<e5etpu$WL9y7WN!#fv0o-dPOAWQLjt1C^0 zQn3LFjr-5_h3h|Tc?sP~8@anYfYlB{jxcX@;l-t`Z?$8YbQ*DS8u%9Y6pWt5AgJg7 z(#A8NkD$5jgz;D@UyolFMZ^?{;`F&^L+L5-M~8)qlzooOq5-&&a>IioVEvvS&_asY z{2na$Gem`h3?!O-E72TzFbVvBKmaMI&bKQqPewVW^kaeF_Pv9b=<N<KJx+y#qKrFR z(xu0cF>t=fsK@{dF7&KEVIK&Pz*xh13{*A<qeO7yTM$G1Nt5xw`XzZ`EWHhCp+O(i zjctm;HrpLG0dXp8MkdMY@3if5t*d-{7k?~%)M%!IbP8#uLYV-kRE`fRppO09Y6*p- zFEQD2$4AV4JqsyZ8m@b6!2t7=;H!BREjwxJ!c}&Xz}oU|(KKu#tU)J0(m&6d#HBxs zWhaZvA`lL61-d_6f^Dv>9c((<s7^rI@}TL&q{(n8@9uZg=Qr>KI0+bm&UEj({R&Vl zc*6N^ssO{oxHpW^L8Lf^oCG|WsP~@(x!a@*OxmNb66c24m*OVp(1&!N<s^S61%F~h zFmBr0`KQjrXVDQd`4OM^8(SrIny~Ay@&4{0x?fTLP|GVfa?9V$0JFeLJG@1Y`|A7i z?PCA#+T&rKT`RK1j$1w4dCE~l0=&XD5@k_DExM2t)`VBc|AkT`=TIm0_c`3FTsRTh zLGO#;86b}zXtk3M!NL4SzaACy2(tZgSV;gCF_#O*?Ex+sA?HIy7`{Zr(}3m|p<bm+ zCqtvTt?1e*Z)cdj2{b-VtuWU*pqM!T4Ye`Mus+KiMc()X^v?p<n&3qAubD=ioICaO z7M?)w3j=x^h@1rXuE4&&8keV?taV4$b9%dPXdUS1KVZwoYKzojBA7%)z|xMQRvUU_ z)RVt~RvK}W<9o#xe4~Fg^#6cIz;DuFuJMM!*Ju*sFqlBe4>CBfVVPf-2`A}KnDJ{o z61iZMT9D<$&wW6V26ME-q$jYwJ?_V)+Q|sp4wEzClF0K*V;`z%tQm&8@KT{ivh6Yd z)?>~_Cr66>E*}hK(kBo=5Sh?s)4gt=2B+X2+H~Nb#RQ`5Yesav2GCu*ey#E6qBhJf zh-A_;z>wjEvY|tPia3eo2cYl}6PDg9qh7Ed(b$UF-E`Rjad{jl20j(2NK)bP_j3Da zaVis!((43haBtW{4r5ZxVJ?IVduiA~*3nTTF^iiht(G?vE3A-2UlnXKZWDl#Ui$YT z`J)&}9YB%$7(BA(-|$%BV_0>EOKbLI8&VtdP!k0)Szl8Ix8u7mmp-2`(P9*3`Rnlj zT}7_s8d{l#mt9Rpp=@Cp8n|QKT9aQ34zUTnnjB)v;=I<+Lrnl-kE_|v_}9iW;zo|D z{O?b(muV^q;nBKjl5v0+3h+QkOM=+|2U?e4jM7JngjYU#s7~;}>q}S$CK@<~9f|eZ zSkwfH6M`~=0;u}>n92)~(ijh)ngb<ZECDfjVZkHSn?*o}Xs$y{*1J+A)T=Lj7BrQM z3Mr^l?JKl;QVkYo5@$Y3oa=4})lR`AJJ<m|JhlU~;9_C;7Y<xqd0^Zer708hx%*8f z0nnO59HtNe*5{ZR0Be2TKu70~^^SdG4GP%4>N$#lvLU!bC!YaFBo7l#8({{*XddVj zG(Mm42OcGuIVJ)5s(7>JkmVSJTqDJ&WE4d`0k;K>c|g~6H60W}G#E{#RQRgJ-|#7K z8vT6%IBnqU3~?oQ>;hV=FeD;52$^~DjVe{qP6JF&cA4eWqN;x7u{@4brr$q5*x>uv zzB|JVC|5jSOB)Ma_u&Pyou|ulFznah3Kz(81wZcZjv?N9a&?9la{_HuSD7emaT;Vr z3Z4h+%AU?!Jic@%P4!IlX383jDnk6CioHHpZ)6$-I9f@6LcH$4ETJfSEMRyxU+a{E zfdz)_roTH4j@rx?*oMbrAlMXb*m68P&dGNH#v^gMjQbMJUSR;L@0zfmh~J*F1Zbf~ zVKhO6@uai2v;0?6(-eU#VUXoqc?ITs6umBSWgS%*U62~EwBu0Oh5^5%DV!r~7u$(C z@{peMRI@zw+8eO7H2d7-Mm1D!7v?|nT7E49CViMnh52&Ne$W7DGYR-*6bc0}CMti^ zZx=WXlbZ+$X7&d<Z0jd9toy5inP)9(28O`*&3&e7ARB*Y-c4hWFb-tfF8v&Ln5P?X z18u%qSo%I@8TVXZsxhTc!u2&{UNy5t+qK<!f$+k-KO%l%SfE^@8Xm?|E`hAE9THLD znzFO(Qz0_TFx9Ehid3RzAf4=r9q?`@PqJJ&w6Y){I(HYQSavuhTRAed`BRQ%0x9H+ zLIilYNekFC)+1skmwGqKZ!z9?V@B9d!pM=QA7%YSQ-?nRiIfR*c`5mgv_HF_7g%e& zw<*8gHgERKf4qO;^~;<YR$?Kh3pcHs;7pnZmofq5FP!20AHi0v3dXG7{<fsgxMqJ5 z(5cCH@SPZ>&a$R%=CGS5k^cF#<nl8X@pGe2qIx+W`vTh`zi0lM;*x^W(mBX<GM#`R z&_eO}ccFCZ(VzWH2ecwdCiCtdkBr|(29OGUH{q}2Zi+yg-hKZDTi7aNQcqmY{^C3h zQlcj<iv<ip>!8!FA*Er|Qbh#`U6=IV^g!5Q{Z~0@h*d~Jh(A{gUZ}5M?$r*iYb0yB zhZr4$@MbREVa{uI(CpN(NmujNb9hSAeKVqGgTyz9nO{iXH!W9T_nUuueH-iDE*p#L z3azeV%XoD5*-e-7Duw)EE?T71EKkhQhFITuM#*x_nTAA$elVSf*BF_Bvm=U-W122h zkshW9i1W+&bSCIHBX>>|C=|_wkF_;6RbKw4#%sap3Il11OPkzJ-1I)1f2QpSL7251 z<;3`q@7!&0vna{$83QKfD}{rdQqT+eaw15o6R`le%GN-mv+EWG5zSB+;YPupV2CBd z9B#KX)rm=@4KQuqZKcyMd_GWIk;PPM*Gv#F?43m$5Rj(3ddeIoj-H+4$^J4FhBh=G zZQdp!NMSbnuDH7qQ~3xL2j7|`pl$yWvv<vI8W{l=qG=zO(EB!jx;1Pd839SFfX%&T zA&LpYwevi9a;OvbW}jVDX?Zp`m~81DZYJDue346J{mE|j4xWY^vF<F67RbJC2y(=} z%Y(y+;FC9z*IDi|$w1JS<j0;h%11|9m5&|wPMuM0y<VSh_;5|liev669!<xm6ARgA zi6epL-KT?P9!>LBaAwtcuaDbpvaK2UsVjYadxd^W)|v19E=Uv-G&ocE$E7DXv}@EG zA$y1*TU@Yuz^gXAn9@W|9=BZI@^b<R$aQU#S1K=jFu=wr+r++UR3xMIE~{UR@R<3? zkUsf@7UiHt3oV&9wjV0>kSdGxzd8cSt}K#MT-r$waBR=$R5LQOzcsEw9|ewqCfOHF z3lQHKk~|J@#HtF6=t|OOKnh^6y3nW&?qTPYJ~r$uy-NtMxGhp5;`a6WPH)}W?MmPB zdU4u${J+61*@llVv>1MuQ+e+AD`CyXBb~IT|LUYcey2f$C#G?LPG2zT5%Wz%<uZ(2 zrIwo~x{?dls>SVeprbI@+QHCE_(TZWH=LoVw$><)IXfcReKCUV+T;!xUV6~*>Youi zj=JSUb0F39VR4pwjDKZRK}GslbGDrv1Dn2sG+kzH4Dln`ks@RUrfx+IBaH|(uM!1K zolxdzG`7`Ig@^EGV<}U2n)gn%KhR7Ko@QJA)Vs(R*u}Yjg7}-GSpgnB+F~1cF>U5d zocK=WjY475j9dJJBwG1++Rl`86!8lk3aJxi0@?MeAI~q2=fv<$9AeD;R<tu(^NnmX z3wBO?=-SiO*FeR{I8pA}Xm_X)j>r9o-mgg<7*Y(GN-OCdx6jvV?vx!P`as+yH5vK| zJ(rYq>15uVvl)i$wm;kmYlk$@v8dQ%`ZOy9Sx4`1Ug8W6^R{_b!=1WBeuexB*&5Fs z9U5ZKuEoZ!Lc$J#SnBJ3?cQ}|)I;;NZT>yC21EQX&I`!~K2(%E+3V*&tsS22Z(MVD zM48J(>b2=he4%ojRs*BFojAz)YKfRTTj_yPA~jEYl=*bu%mLpf6@N?7?C&XSxX%xo zyt)jfQRJg#bFzXNB;vPa*i!=68@tn_O5(LR&u(gudarDE4G%tVl4`yNUEN}4%t{&* zUQK+)%N)W14WLcYT3oa^)~vjT7`j>Rl?BuPUKTW1<FEV$y~tX;vMy))%x!?`+#wA6 z9<BB2`|`vi!9nhwYc~|%iNzr>NewBdz0}UBNJ;xI-+I@I4vn~cbUg`8V%zXfH=s_q zI{xizOPPqVn$_6L*DDFDQ5?4-&yQl`l}<nhg^XXf8jI}zy@sT4hUV{+^9z7!4aO7P z%Z6euICM+nTIY$(<Fo1D340V=7>vTo&#ZuJ4X#Jot=R-4mdEhjZULQnH(KN9?)F?@ zKY@WEpAr$791S~JWDA^Dt*R)dpN^5^hfR+}R6?_0g~v~rErlY7t4zsOxdr7y$_gXj zPHmZ{L>82Sron8+PHdMy%P+fn!B&J^&1T+c1v0pjpOBMu!0h_-iVkcP4(08Zq8V5& zA-(}xO}JPcny>G7Q5ITk*0$kTjq}6OPji#+qx~2N7A1+6*GUf`LUo7-MG8d(?<g1_ zG6@=K%oTe*Mv;@-J(XfqR6SF3Mt=GnbgW%0q)))m7={hPEo!k?ss$3VZ&5pG100<x zIl6|q%?iDc-92Dzu-mW5*kRZG<8{`swOh>d4m^7f(`q`!5{{#Xh+1a9K;q5@9gaHc z9+>@T`L$R!*V2TmBX$Ft0J8NzU=6_22eo4~4hLd<nu7z6-OMFYro;(*KoXYZL_^s& zIRDo3hPVDpV6#kb1JCKTvd|Xv+8Hk4Y4BZV)FzY;pbY#VXckl2pS*Q+XdyL(lT=3e zanS4ijB8Wla*a!DQC}2pXy9t**c1aSKR=q6c{2fzP^;_h)+XCn@N!7Vh8I8y2!W?R z0HA^XF^-cvJaWeEK4K2i%M5Ya$HG>Aw)sgpq<+WH`>B7qLPX;TI7LK(!1R~;l;rin zZBUp`N;n0mHM8~@$AUlyogVMY-N~JY!90Dh5_|1?oI0(bMOo|#gvmY^=H8^jT_gJS zBq`Z9vJZ5_IW@;Cqe$f(`&bM~mD#QcEm);XoYOm^w<r%IomTn`uM$<wHE!v>QWTaL z@#WaPq||bx`Pw&MN*IKLU2G<#;@LPP)}(*x!1fET<KGSZ27*2Tx#p(OZE9W$hb|;T zu6n1<af6ePnU5F13@xYf3+DVtauV_<H29l!iQ>(^tG>kOhoY*Qxi9Ml1~xANIrER} znQI*T6(M$Mo8La2S0y)ybX@D`8lc^Iv*;Q=?~22aDZVwm6o=9hiecZ%JQ6hR(Agn# zboyuH>($%pX~#7moLGV&0PS<k!u}SkUuhDcmGDVY{yj~?Vqg<T?qv%YGNF(Cv<FPj z?ng5c+9?Y%27G1H=N@nm705pGR3MkJ;V?`?w_(7@FX*nnB5JzBc~360GTL6@GFv3R zJmtN#GQNkxl3y>wi2`+yMKTs47Ja2Y4eIa*JjPtL-@EU8vZjoh>W#E{71|oaSe8aZ z7_dG<!Z5Orzgfjy2(3<#b?2m);8_(m4Zo+h?wI;F9rU>7M=-eXYSY7{eUUw{h#r{M zP}Uykpl9=tffK~Y4V2VRNgf{lFoZFd$hnOk_wc<{!Kt<*GwTubDJ166y<=hy=ynCX zO9G4zy>ox)m3V9x6z2tu%3<RCm;HSf6!i#-_SxA7sJRU$N<EBu{?k0f{cD)}VY)j= z)%<j2BVT&h?`?F*4R6Ozf=lZg)yeVxOCP(p8|8V84UHJHIw(!}Ew^9_Q7-Vw1&Ze^ zu63n|RiFBCvH*Ad$TS2uQp5GqagF0CqA9OU18w=P=qU{<5m6bosG12?xB088S1ToQ zXt-)LqR2zi6#O>}<+ceHhzRcLtq*de@UAQ;-0s#De5u(P92eJH(o0ru;*{k)dr2ix zVoWmn+aNsQwtOw1>0(6N1091;oa<z56ld%NX5-uFO@dVF;forVfR#KO<uv?rr+JO# z#h|ouQjo@t+A~_5jZ1QUTN5CK&24<WvH{9-!mTY$jvMGu@5niJ9#G(WPf4G^$H|Ut z^{wq}f%^DE+zXcD7tj=pJQy)`Hi=$lOd=FHQ~7;Qc0^w2-F<y)gAEy`3>vP9xgcuY zm6WY?RZYFaXTtV+{zrgi4$#2K-$nT!(0~~amVVjg<MKvtUK{n38-PbLgf!Tr5E%9h zX(^=G+d)^hRznm!j~ANgj=tVmi&=VFIZ=HGOaD0cYt9jD;`-sSYYm;}UmC|Y?d({n ztxoXX;c#IuJACak549vf1Ijse*uS8GJsO0<?@#dy8Yso1uXW02Usj4%TD1D&tVMrK zMUjz++cr#*#sMJMRn#WTHz_9WlT8cnV2gB@ux~%Z(b8gxslMJ!FhWR1kp|;=c^(hC zM_L_X#VbK^eaMqiUn>lA!(O45qes#@VB-f5!T!#>?33Ihay|=3c_=ZN&9;}Xls^)5 zYFHOJ^llp)kbeB45f9-7ReI;)M)~8STKMjuc1DeSJVEM#ZLE95iR+;=*9_!o86T+L z6icYpV8WR`tTE+ZB3p|k@4`#gbpbCr57K*=$ACx#``_upF6Cbf`3Yy?VhV~lGq@~g zj#IzDvex|rMFEW%V#_7_GC&bzRl@skLv=2{t=PA-5rItIGwxxYPGDiZX4{mRo=^Fs zmFh}9tVl5frblUOrx)s8WW430N1XiQuWzyjTz$@Yytf!nduTNukNBo2SLOk@BG_3& zf-<1RC=A;VQTff)I+|(N;N^lsyb++e2<R+NxA!fEMcZbR^E9Rqz!dGN>8%ox8{VN? znMt&6O`=eub~EC=VG_aPHLfkLw9wRt<AK2OpNwVJ?GU<gagdd(no}km9qZoQud^;U zLCR092EJpC!%dzth8U&RLu_0x@8fB^8feCjW9dILNzdhL6uk`dX;P_V@YClWIcctl zHhf$*{A!L3cKYx;SGUohi_+&Vm$iDG7<vTI8BegL7C4j7iGDt}^yrJeq!@R?MtVUV zTY*;uTF)be$rahnF(-cSqd#|ZF6?H?IGn7<gllMkLWyjIA~h5Z#-UI8^@T475+gS| zbqvvbo8nKdH<Vt3MXGeE%kEA15$N@c^@&|ZMWDsRbf)cNi586tg$nNT`yTYIEAY73 zFW!FIG>Yge(z0A<^R<>iAnsQ2Jz{|RZ(;zXRX{ZbO;1S7$+>#Ndx*X>;##&$YJ3DE zIP#-SZ`~r!*0?4vhcY12x|Rlc$4ldC>%o|U(k(S&r9j97_y9?%M;BlJunO7!bZFa& z=z?Oq5sB~Qn3QABnI2^}T@<R52i;!0Jg4-T%c7Z^WeEb=oVNQJUAafX*BaxfJlG^E zfO4s%@-+JlQr1~5Cwf_N=;ul^g?uYoHL>xp>Slb5>I5?aBeN&AUk|h<0oGO|-xV6g zD*X|gfr)@k%P)o{59~RG=(Twvxlg5WUM^RfySMt<1aq0iPD6*fD)!hpu!AV5zOz1Z zFXdSnmB|ms*O|gp^2@OwSJ#5kim_y|h|H+Sq%8BJUUZfqeT%j^1Fq#MNVb|IHPp;8 zEsag%YA2%Y->Fu{Dy<#FlgW~k&)VTrZrDelcNl+^sJx><VU*q|nZq1c+SNY2uN3UX zq}~U})^tdP&EIGXWw+8{-YK>Cv(g5qcAZC1JAV$bmuFZ}>_kU+_@RK1l_00-3<Qxh zK`mv+t?ax*u-9>h$V@l<axgeskc|%ES8p)jI4w{Wk<4s7eOtE${16z?-zz(&k?fmg zt_F?gduUn(=Z^<%1Bp`;Cej)$mjf=fku9dme5Wgbmub&pZE?##%2(8MDrAm$dyZIw z_Lgfa+G^<4Ni4l|qA8#C9!Bi^8zV-je}6F&AN5h=-aOeRIixukAleb1cRt>Oao5ln zk-YF1t>65lYY=-9cGP9;KK)r)&;t5YFzxIs&0--Wt-bOi_Uw&1?erwgtV7?VI3v*3 zbkX<!FV5aFtjcX|8x{lsQA$FjCfy*2B3+XP3F(%SP7&!4WD3&V(k<PMAW|wwh;*lP z=QnO#uD#xU?03J<^Bu?f<3cC%zQ;ALJkRqw04RasSEbdA)M3>Qs>gjNuXm^E-J}k| z7z?a@11X6g)lGV&-=GDSt3t%$??U8vJy1%Mu2W+ta(?mFKSfH*p~cq#PTIOjt}*Tc zK>3xzTww@Kz|*d5d7SmG^ez#mR`}xAR0_pU3;>+mT@P6I3qUbV%HbZ%BMCSLfB1yH z#gCFSt(s8(!3)nN0sC1$Fm{kAk$MS|;fsWl(0HnwDQ6*$)FN8wQN5^B*$4-~yrv7+ zK^{63xB!|_(m*D4{Uadyv;61-${@N5wy-wuknu1e_)BVJ6NrC7SZ3t&>Mb6viaG~2 z?$9Ua(uO9isYAunCFb-aZJOe*JTKQZASK(MK+2%`);%sMYreM(rd$|PX83iw=OLf( zB5ryce@UA^S~+QL%25R$yDpFMG1eBSoy`BLo;na<Y3iqCW5SvCCdL5S5Uf0yLTJ*q z2y{Do{4nmQqzK`5yj%7Y)so^OdCicqY5&-Bb&wG(_)KJ)CCNi;j?Ym@oh-DmO;kz- zcmI{tI*_4T=XL#vuav-T%eL9D8}g-W3J^AZYq@9VL9CIMl>AV}XKL+zXG1$okiu=9 z<AJPrG9cX+@Di?`-yFy$^oOyE=<USHt$Z&+_#%W5GDaU>f3v2Rx$SrFEWk{)Df}DA z$rnjStP?jE4{6EK^E>Ev$x)A20nvb?pms7FF?){y^Ai%}wO-5p?X~^^XNu9H3f!2P zr7bWXh~n8<S(QJ*nSvS`Ed)M5hl7@k!iGk`ts+{EnB7^GKFOaU-7nH~y;>ZX_MkIN z9VbrMC;#v>d-Da|^*ZOs6zpnjoiH9?!JZgEPo+>Z5_YIwq&2j8EXMQdQ{bD5zo04> z**2q1X<VIk;BSKeIN(r2$Kc;^zwHqSWU%Y+y6|eQPHma!Fz7IW?t9=*ESmK9x6)lR zxt<|yf5aBDQXd1W>fhaa$Rs`Q!uP=bx*=3LGDB3)<b5#j?#`5s9Bi{>9r_XfmIQ|w zmZ(yo*7t=oBl-tg@NND=J3!MuFtlP#j|*}s#Ua9G#f*|8ZjD0k74P*~J>k0mZRUd9 zo4jAa+eclvfF~J<N7=orWmG;2dg&|0&+r<b;hyi}^eMT;CFo92;S(;P$t*6VE2Ii? z8n&aW4w9aN@^&CbI!qJL?I7)8rbA$6`MLNOonL!Oo_)*&Wg`>X0De1u=KN8fC}l%j zP{UV{?fS(e6^J5w?3~)#T*fW$zf7aK53#E)+EN>Euns`>N;r^sm;&1Q=!7SU7-i9n z;qfj{#uf!W;Vao~zG<0e2f@1eY$u2{>ZpKZ`R>Lx;^MWjM0!h8<U6!hl<)^(z&sJI zzNgK$oZ?Z!z6!ZiGWQQ9_P#d+P)9@w#dkK4qd!MvX5FC?M<<j@n=Ib)C^C^lkLF!{ zD;Vo3IT#MEb-pfCRL@<!+gv1mVESV!picfAD;^!Uy_Z1<++g@ZtH*uC1VC2~ta{__ zNFL{Vll)%(<pf?XP$FYYN1^&Sw+(Tvc60x3NBk2unN@{IcdK)r5;-;-bsgP0e#t!B zio~<?{j0;to@R2NGssmR(}xM3XGKuEsWIv>q(-qi7L2=nO;)a#$WqAy5D?XE$%!t; zbofMAiP$q5#at~Xp5s*g`PvV<nIjn(LY{u5E|0{K&A~?VC@!J)24N^+1q25uYi9nP zXZXoX2W&RS3h+61ccm(P2CO3+f&F97t{CciomB4PsIrtVsX(1eQK9t&Sh2aEFwmaX zxE1O@Dh0tOfHa=IxU+B+S|$*gl?DH2sH%2)Qb$9`pyis&j6abIG5m3VQ1lQ|0Fe|v zXp7Y3q7dFF1{$a(CHS0eAiIi);vhPu?<#o->I>>u!k+-{5+$grkNzZM9pFV&Dq?~7 z46Ta=KViS9L#x=s5{3gH)~RxM0LCkyXFGz1%zMpfOu_Uw6B|G8y009VO{#c2g>w*L z0k*SN3C@^&KG1W<!=SH(1Cw@fpz^P^8{^iJbtn}5mCBeNN9EnTYv}W6k!AqoC06F` z(r}R%serJiI3&`JJ|!i@M7@m~&JHnG4tmY5b!|TwLpS9s3S^iuumwE8F|eyNcd-TV zSqUt9iP4duG$eQu|A(C&81fN`hm~NGkU(N~9$x4H2*W@UoV^Mf!=!;pKf83)M2J8E zY8}-SMy_e^r*Qo7p8b!3vzl<E9Ed^cCy@yWja_9UVvYLoN}jMiloP?$ge!iMV>TSF zL;x70uS8CdLj0w!Z@0@KK#Plo*IyPcQt^mP;D)uB;5oR3>t=d5tuR+GntqZB)=dJO zHy9Ose+;?G>;KVJ60%YSo|2c-K=Blg2I`!C4y^tG%-<Z503sBdd_CEaWPZl4FE(gA z_yP|6xY$oRA4$W0f+pPC16;#P2z=y?a)t}$^r79&ou8NV3CF2??C>-WTG2SI+u*cm zk1NMYG#{*->^*fzuEYss{DqgRzHf6ptfi5_?d7R?aQvylEv=y}480vNNKp>~#-WO+ z^8$2?lp9{zxAGA(rt&&<6H<WNy|@iTQa>{nH{gZMfV_Sv-2`9Q4-1`ikt69lH<_Tj z##=TG;b0VV6opaAsY{UeIo%SSUWla+RtfFshnnOHiX)=kK+!b|NaaFG!#~2AA=U(8 z#Obi)$L!^2fefZ9sBnU=Xy(|}fKAx|EHY@{;%W)VM2GuFzz~+y+|(l!MMmQV<|t~A zNh!mGoav=|#{DQ}^(QbM80zkz7kxO@ActgX#2v=_Xb;tUgMh^TQ1RAv!7vX%*J3{| zI^6~Gvb2L2AZ<7~NxeLy?-Dg5{SJf(o*<iFU%9?EbsL8)Ea_+;OpYqnvz9XR=a)K2 zC0TYp8QKDOdTh=l9`L(X(t@`(wDXHcVf5m{`TGwOAQf0~3(mAeB`(;jxPIzh2cHe= z8G!7Fz8*n@w=q=n98D$+3v4s6eNOS%PPhyIv4IT1l>2V*33(~zJrdLTJV28tcU`7z zJtxPApjt#%&OIyuvA!D+=2W$_3$wBAvX`6oMF6gIE;Z0aK+q$egn+IEoou^8an(NN zMi-6+EPFN6L}5JuSfw@{-{&+0JUfFP@No6P{q-{xp#^31Govgn8OTSr{73fq-{cCZ z7KqxD*$N<;N!QKeg-f*#yKvXA`w(w@a~b4-Z(^hdC<c=TjfCHjXx^&~743J1D#hp{ zROH|H^~EM7b0Ph94$bX*53~|0tl}e>SV$z0r#w!J8g>^G^E>#MRbwnFE&WTKEc=Ux z77vFb3(GZeNryM(?xj%{(i<9a$is%=_${B1zW@PCrVWIduXw3c6J}mtM;Y)#4;)ab zkc3IM>7CAiOpHShYxR$TAia`6|56QDkRLiL5GAVr`AEOyK1o079+j;W9gY|*3r3mH z<qNbXm<|r0rVkivS$Kh_yRUdXP#{x_xQTTG4+$0ryiBJJnnIamCO(a$5=*)&sQ-r8 za=1YsfQZ2Q8s<<q2+m51K-ZusgxhvfXVPVf49t9eQ72FCReBr6NVDS74svuptifgM z{ruq7$%Vk-xRGAd&l_Iw+ajWVNG$KLD!rPh0*Q&Gk{Py9jgnZkADxCV7CwH<fOBmx z$p^ji#fozMZO7}FmqDNnN+D`|jm+fZZJ~NY91?R?I0l*<Yx<Ey565P>aEKWUNTQXl zBpSUrjrcc750SEj`_FuTVyVK90d!_aKqD3VFdGPZtWE??Zu5Kwve;w<9q*2eBw|G1 z*ym)kV+i7NMnKY+65_S^0#<%Pdi}~ZqQE7l4hc{BhY{n>V3v_akbv4~0DveoqB}_k z`x^(5=1{3<n<T@b74?X5e|#X!fty(|KT_vpNiZQNX)Hp+bv8!z0}kfR4u!FVSMYh& z|5VNV;a3577zc36aa=X>xc-hX);kRL`T{)ed%1h=HI28HCs|qbnE+ggAJCpU?i5-@ zT^V7E5j4m~`W^g*WzY@m9Y-Eno1Cu>N#{>IEq{a0tfYK%N<{_I>O6KGu^BxZea<BM zM$>M3S!rNU>vJEz3o;4NCX-AQ%6u|jWhA-sz|25{4@}7mAAh$pDrHDtAFq8X6T{-t zA9uud#!aM|NOcn>5-_bldomm1;86+iZv!ohN;KTLm7G+yPG;47nzfN)^|8fmVTDKB zL}!+i*A*<A!Mf-5-MFB=U$2KHnmx~<t*WbGo?7m*viFj}jGq_Wa4r!)ya$v6GN6W7 z7q9>PfI59T?;uPmtmH0P_;s9MG5WpRL0>5EFM~R_$rp(#cHF*`tS;A8k_6P>g#71Z zT~mgeQg0cwwiL-q^+d@WD~#B>FJ}TM=5Giob=dW>H*ERxvJ&nYQ8p11+~|MNqT3_L zTPK%$zDuC=tr{pN$b$SpRe#Hu6Ra*Tq4fds3;8bZG2?*LppcZt;{M4U-TN0ns!X-t z^&1_PiviZk{F_uZlHU5-n)C6^vDfBps$?u-U+tVkqloBvKB^k2QL=1pf@G6vLt*D8 z+Nm&@g~0)y(%5OXnGz^wGXTVdazD*CO7!P7#js~*&g(zyl`_db%W0?-FYN(Qhj}n1 zS9KC4P?F<#50GR#U_VL0%VfRYQ~D2RhivdNXj&G?=3j@n_1a7zo6CO=lZXwlVBB#M znL6qb$j9Jp@IHx7jR8aUuzdRiVU-=(e2PIOK69!{&kZgiZs*yTVe4r!NAg(=<9jp@ zMC1NQiYTEL5%p5j^fK$beu|ty8iW49L`8S_u&E$4XFmD=Js<d+Jw#*h8}ST!SzmlA z<fac?Z_mHqpEC}vvYz*+cgtLmU8oHArUy3v$~QU~z$3s7cqIoM^#g;yd@6=dtmM0} zytz+fsy8))GW3!-HEkI6#s#yvp~zOO;3}?Hl~Q7x9m*;~I~9!DD>fbiQ4Dasd!N$C z!U)Cjb)xh%ir8^5gGyn%9w&PzVS!P;^x@PX5*`3}A|u!e06Nj&2TGV9fO0)Ez^F93 z-sC5&S~F(*@X2r;q6j|ELubVi!wH_RAs{$@u$IExR>v(iEX?`UTJUWnNd1uWGQrR< zf>P`TEf#D5#rQ_@3w*-QoEkqu{Vc^#U;X4YjsX^WGo9|ez9}eQQ@~nhG4afn*|ERW zM^tbte8f965RKMjk1AWV57nzdPVo2*Ix<2c<IYJ4f&%f%hrU7RbiI6aW#_ZxDX6q$ z@zPK`8}XIgO^D&<H2~~1B<hyL7sVmz!A;cxFc?g6Vy@fUpb=0+)n(8`wSz@iHHUE~ z1-_E_C9k0r!}-UfY>=*17U*v@>^>o&1(l(L1E|1h-wV6<cR6o6JDl}O!OgDYqTO%4 zzsYe3snnXDx^ArQ*3RVg+}KS~6UQ$>k8W(zKaqfoj5R4qZt;-wzF;UDO!wGr@<Ba9 zEWdUmypVs}afXP>pvCWX9%n99BxeLFDu#Cio9nE{zryNhV{x+bfui3_j=fUQNn6!| z1+09f*iedlfOCE8*he_0L+naB#a(iFlNt^Hx_#Ua6T&ugnjG(iH^UIqg0(<HhDMq8 z$tqC(BRB`Jw9G|^G*N#P7toVd9(kXUJHz+taAV@&;mpa;YTM$2@Bjoa>P`HTj1(|+ z6QKr3$LbCt4?K9>%3xmP<n2{p+KN9k7=y1GJSBfOc>V&QGN#w0ngV=hxnUm-%C|pS z004c8gm)h#rX1#Wz%ecfYth+BzLwYt-oO5GM2*$t$9D{&yEzMMz|e(jpkn^jzi|Bw zEKWTKx4FryB!5qpuNc+Xw|*B*HMCm=mDg(9SUc8dRSR>pLfxzrjC-TH1Q%_Mf-22w zf4vS~FQgleJU|PUel=U_5k`^%(F}MDQvfVqgFvZ7@m`Rhlk3@br^(roR~A1hHa@QS zNNc*$1H;#X8>b<t<%^M{;g>*#xeF*S%xmwZd$5duYBOUcIRi4yGAcE>?^CaX{g3%C z0ElQo*s7&XV-PzE_DJ{x2N5RF$<Puwrf@2mCJk}{T19trF+esM0_mYLQH-FymB;~b zG+8hw{pCM?Qq%0L-z5?Y;fr}-K1ZBwRF27_#E#Wes7Gm54qf^x@dl?$3UGT~A;LK7 zHXmCs$l^g9rxER(4nI6x`jTuZnfk4BV(0t9)031K@hHVn(2AN~XO5pqae^9tlt1d7 zi-qs^i%Pw>_nAk|`vvB9<w1T_>2bKO-==|jUOY`*m<L|!ZFfQ(Yq6;%*mZ!He-iC` zAJwIMMJs{JoGMH&Y*rWUqXU5Y+#Sg52xQ+)u4Lav{WQTQ1ssnX1JdtRz!piqwisJD zDf&yTl=fGEeE#&|>%TQzaK(EY1W7*%VEZyC16Z7tA_0?%qSHR6AGDuib>clxvO)0= zjvipRs)=O(t$j4I=KnZg<U>Sqd3Hhh(E5I1tkJ5=7{G8#_TB*wF;fZPxd)b8Zn$XT zEBT^yT5yO=f02+kDc+Yn`NEpe^Let-F#YQ~4F>!UR7!E(TgSX=RC;SeiGlR*ZV>oG zq`s%-r%+N8BK@lE2VIr|wIlNPeio-T2%O)pU#3qKj3wDwczQ}-NDo%RdN%%SDtbXo zz`C&IJk?XhUiDdB-zNI<Vkc-^t1J`0xhQk|nSlNIz~0KQm+sspFuQ=t_x8p6gNGAu z71r2o#PJxMBsCe`pDLZ^jW+Ek9e6!{A%*3+8_eWTzfZH)JN&e0#N#BdP`^^flm85C z;EflP(NI|XU<SrHwijnl<nwY2aw@!<H5D54jRdwy@-*J!Dd(CgjaGWpv*=c6V0kzz zY6<P+j%#K)wCs`#y_9>Tt<XMIZj{q2^{z&-$-%^>#N|Pdq-$+)YX|0XQ$@<`*-)&0 zcS<tf!jVGfysKsDzI=yG>4$Bb{f$lIL)CniDQ(Oz<qMxF*PQ8sqr7)=io}zdg)V-4 z2wZE~k7JD6##}n%IBm1GMF%VtL&3LXLC-*!v6SYTd+Ka6Kt8s9-{{)|n=^75=pPRk zsIwD4T%9`2Vha#20LY{=YK`T&SL_xZbR`-T$4x81K`SfWd~*tq<Lr58Yje(OH!sx{ z`^t96MFY&4F)H3uVAgfMBhL6zK-84ZMhK=4d#>9>HrSg0qnpb>#HOQ&slQKU^%O3` z!*bE_bn<y$LNxqGuIbx%VJ<lS*Q_ZU0la7+O$@EFNIwia<h*bb$14wr9LfA_jr?^^ z3ukJX)u&+*e)A*!smYpPZaj+C3r_%UK%&UJY8bR{GEIB}!Wu(Qm*t634>=y7@-0HE z*3Y9ZfC!Er{;v*xwDeXk>z{k+3=bJz`}f6ho2rnN+uT3@_;3}$5LXR=y}0n}oIKN{ z2xJbcANQd_{nX~v{1F6#V2Z$63~TliA2-X$+_y!U0%*P_r-}8>e1xF{Ut1hyL})Yq zO_1jctDUw6j&CH|=`%d@xLiAZv-y0DXl=?PY!-I+n68&`oF12W0RSVVB7&D0aD>8e zG_SV>HT#(<Ondu%7OtUq7DDBUG61l>`RTE_WJK)Q8gnG5H&S)oAMH1Ovcj4rYyZfi zS(f|JOi~i1Re;fPv3IqGonqn!oOIkV9630P*y$sFTkpa4ajPq9a+|#^Tm?s<3CNDC zg&Vv$^_i3pM>je12)*IhJh1f9!xGS|IDvLDfvPNp<Zo%7O+I*sNZaB4rs@}*@qnuY z_~c(dln)A^?>-E(^WzYO(|b)lU2GQk_Ff3o6&mAnk+L;{?%+X7Y*pgtSJAq25O|1N zp`FxMgR*~Vvizgv{5OLZh7<{KrI9zP8Pn~sGEI=96CTCto;HU|COix$N`1!VSHVBr z@W>W|RlH%={;kHd6$9xkH2scp({EaMEIG{l4Xc6N=vi8zkQJ+i=gF~G#&w#JPmGov zw$TyQqa7zr_oaSnV4jD;Uc9jCSGI08V13hMH`8!yeM0irY18<nff%ukfcekVcfJVL zuLsMN1%jFz+Va1|GGBFQ*~Qb_hsRHedSX3Eysz|03)4KDu7N{$($%BRYDe>3VL@=* zeLZrsag9wn7wjr89QA~eM*YhDD1z{r2wC{2TNlns8`DJkQ4*}=G7fBxOW#9drK=Bq z^@&MW9iF`yoD_0fe0K}L$9mmPtxw}NB|6C`vUcw%NP&}yGzMMVIPPTaN<wrtsW4Sj zZOonB35{#@OsGBdI=hmGuQw<05Nfy`V+Buso)E7&Rsrnts11fmCo3*HfLF<gwo<7+ zMUmEGeuiy`LddmQW?U~+_*E5at^5U0F3n%2g=Xl@OsjYO!hzzTsDKZd!n01%t+SZN z0d=ni>h-qP$65eG#w2pT)<4SOU|my{P!y2yh}YAX(Foylbv8}Mi$U<ax;Q~SmzEPb z_Ij)waSAQ^fLho>-;==xjVL@}H<1Ysd3DPLi$?&f@4R}wB2z%;4k3r7eFwiSgON>D z<oKh-JHxsL+kAvHMjVe{(Z?$P6w=2PXOH+at_7g$cttR3VHBAS^D~>HXEWT3{Est= z5ig#CewR~lmxpOY{ei)*kt$F}+RvtQW6AAw|MX*SiuA~R0&oDjzT`#eWsEG?Uv@l4 zQKk^gsBxYtx9@v6^2%eCYt&O_Q~d(=J{SPqa&y(7<!ns8wQAjXJ>f8n+P9+FH?`Su z-1eN;DP;`;8hkd@$6s%g6*TX@aM>lBvIU$4oW1J~y6-oQ%AdUd1-g-AO8Nj1P7QFt z>hIG(gg%Aa2M40gL9!rAB6R;CSN*%b3Me1EAriXuYY;piqYZHS)RS8<>i;^|`pIoW z!!ATL)_?8$&g1Q$>Ch;8nT+J%-S0NeeQ?EmMqz(x6^!EutAuGetCa+Kf>K$U2AS{U zvpMrM^Y4gRpTV+^9|zdCF_yBW?6UUvp0n1!Pudg=5i#)jY)A)JG#|?iCup3bKfS+7 z75_`bJC5Hn8(%@k%#`TmkNe{IQ-&8OhvOw_18tIL=viLbh=?Ao5*t10lgK1Qnd`BG zOQF2>)Q7QCEx3>0&bRZ!o+bgeU;H{#!Ty*9U^#(^WrpEUy>SA;d8^JfQYoMkTs@T; zM4M(+NoYVdbI+7j%S^JpwN&xQ&*<Vkwj3Y@<I-{_Jw0UsIZ&-uRFJ1iWx6=!iBB^m z3(mKSG>mx^WHnPv9-77GBTOZ;dcainJd_BRwoJw45gxh_5`00k;qlC+&`s^jZ2!U; zc1kKNsyUcE&`A`Z*j8uL3I*NIAB5OJ1kBkeY`aq{tp`Bcqhwx#o%Je#&i}tB(ElN6 zRxDB_Id&MaG5=oTBX@VpU8_k&j|Aftpz8<HYm74d&S*NJslxTYY=9f(k*315?NrTM z-Mxa30axgb!wD<7d%Nj!W$Df^)jT!%?1uB0pI|!S)Z!|l5-#}qhRm?lC`!M|4WZpa z_nnylUhOK6%VbxF62Wg-P9&P;hW<ar=Ob~|@b5ItF%C|7ofhr6mF2kaFT^rYP_=in zS3MR?)~F70_M+<kk@u8^I3wS<X_aZzR^XOl1VNWcha^RwMHqLC?Ig{Jai0bE9T_mq z66Z!(x|JM@DZf_~S>v^hwsc$?(Da-tH9IP=v|Lasz)~IyA<H^!L6U~!?ef~+ernnb zdU*B$OuHlcUR{A%6w>U>cp*=y>7RtT#++qDf^dO%GkwDBz@><OxA}PTEGT`zuZ^B` zS5p7_R3km;4Y_^lw|fI^JpjFA74>}0!&AUJ)f;4Gxn%=rd%T`tR~<TG{~M$Jb#eMx zpAt|uP=Ptm`uD)w5ug~y3BJ)^7xtm-Vj|?Xl#~P8f02@EM<43>cPXg|iL1V-)IWM% zkocb(V&>8XgG+I&*|SpB^MYmuEij?c@HFpRKV3R0pQrMHr-xz)IUnWoC#ko&P_7gx zo}&!pG^><7ua~$<(97Im!-!9y4)~8uZzwHzL5IrXjW5}@w{URPFOyw$zRZs6`}2Tq z;c9o|ku<V-BEWLsuMoI#j)V&xbfsKcDZW;zwwkIC&}iVj0#zX;0+&MKKXrR&JIEhR z8YYfH_{C);f+t1A3Fc7vGXdt5nHi2f>85b<!c9ljC#+<BH`roKoo0EoIF)~($TA`u z>~UevvSl%&I5p_AU{tBd{W(=)8qBKk-d1*`I8shs=UHsWCyL>=vVe_Z`l*en;*e$z zuau}_6-McJVZQA5KAh|t1JZLbtP%K<r@<D3`0x;s)gR~fE^S&kZ}2TH-NmC;!IG0) zbvkJf##B#j^m{#p;Xcb5-@Sl>YIle1vTpok7boK)y>DxqbCJsyyp7+xu<Y3(TUQw6 z>wGZGKRZ|}-a*hdt^aJ&T`=l>t`)B6u<*q?6^+ES*_XIkaY-TKi(RK9#2A$%C7^$7 zJb{Uc&tPzfsw@L4FIvzdDVwUprZ(&bT%hMmVmjuVcci<&%u5X7zDEF?S*4@pgM+2# zJBxh<DERn!#^<MA-`<NT0|W>_5X1#eK6F2_<7@s)#W7$wo!;^<xvo~{4Y1orwG%cr zUH4(@*elJzP5%GZC<O;O`1!CTHYYH!ioNuLVMZMeaiHh!+@|Ud(LFUesFz*%7&^j) z(c!VF3CVVlW9WD|ndT`KrE}S6h@Ho3-2&psgvZPLVCTd#DbWEFKZ=FW8NzD3PCj9% zQ6U?Pj5I}J^d?3-F49xD`PuMUiT?3D%WzU<)wPwbnI~YwZ}^1dqn_19OqK6I-cmm9 z*A<w2@5;|T`a6Xx7@p0>$dD*VCn%VtE$)k-%hrnEO!aJ#tD|M(`VvDOP&id9wvb4L z1V=$<(z3ZvVzw{rF<J-6#e2iE;>vY8Je3pYGgvRV@Zd~&s>LaqeUqM!-T1^0?ZSTA z4$e{%C*4i%V8by0Fo?idCfZH5^KY9^Pt{pZ;dND(Ia-YBrRjlZKFL=oj>6F<c?Yea z+NTL}GauFAnp<B;T|PWl7|J9r`gBOTRMcTZyR%r1&8`WqmKNr5m>llHM<>fHvG1m3 z&zGJ=tG_o8i7%ZNXg<e^R><9zbP8j~g=QayxlhmGcj%u)by6sVVJGvxcF?V-i^fjw ze!#vDnjmS2h?DX#0T|LD3QR~XSCMk`CPaS)0@l)CrWMIbavK$p@fmw!*%bz&yCUgj zAthi^OcQ{$WZ2W-E`la{{OSJ;98cjcb(1wEDK~#JsPTtiIvKTADBy~J$D9#(C>}+| zci2<X|K0eaE%WlhowkJ%CV=u!!e!9P^xktVORlg@#<3BIhy_j~q9Wr`CmXS|cEFy| z{1ND*W_q`rhrWyeOVYzWRa$nfQNPK0PxoI*S}nJIYKPMceHu@5)5ACxJu3#~D``wj zo44QGa;Zw?Rf7soqe-1g>p+xBidVvV37kCA0*w!H74%)Ww=p`tFE&s|<1N^*3cn|% z%F<c8V=p!`Rc{$vVL7Pri|Qv@x@V0v&|he<)?N`ZteLV9A{S(N*fW*4BiBy{4etWG z`fTY*v3TDyuxl&$rto_D<_nxet7qDLZ1HNgo_L?;UTYr7#Ap8LR&9>y?MiFCB~avs zd$=9^Y}BlA$eNC8HXg<_Jrhk9x;SY!ngmyPmTb(-$^`%vA(RDxRji3m6o6g5fxc~0 z3`A*fPp)SplnXUDMjPFn2M>A1$&z@T@*97gj&EXwH@A6URX{qJU3O09LwoqLxxdWB zxr_k%Rf@+4%7Q_DO9d2=n{pihqc<yrz#iwglqzkS3XG7#6>&ys#|`Plqk^(AvD-PI z66dwTzqLhTae?$)IpFb1G#u6ObKjqlMBgL4{MZkYmwm7<wmV8`Ci;Q)vmf!$H24|{ zBoIq*;1s(*2ZZ%4O(5Vqz?_WPZ4~H=(>3iC&i5pC3NG&75XUdZ=u|tsQXKj*7KNKT zwZfrk&5CZWm{HezSAf$bS`(V?fmYsCJ30((c7u%4>hD|rsd6pz^?u^Df#_jdB<-fr zP3V>*Bz$ver22kVgd<T)=2}0cF&mwEw(^`6c{lcr;9*k3`N@muEOGoZvYjgT<8uOM z{x_eQ3##he9=~Nw-y`Ny#F1~;=k>a1h^nD1POjXau6D@Vhc76eJ`ZG&*RG84$&egf zlInUBiP$mjd{Val8e7HDQBa49R+gT{b$_IZC!`S#E9~W41>HyfcvG&2LO&EG<P+xI zG|tI*R0Pv{Q-gThumA23&gSyB0!Rh>)o#Ye_M(8s&JspsXkKcoA}YV|L`0&0B|?_1 zKhb{o2`;V8n*^eSPv~c0Fz&mV3G#a>Hs-czz#X7d*K;wE(^~*p#=>%chOd)W?RCUa zn%-T|pTj8g)PhvpUAX=udq7zXZod1uobz<TFDG%vi|gbNpjGRgV}XR~Cy&l6|Gj}B zEYTWS{D@YNm0e*YiSx7%S2;^L9#N8pz{Bn3a0C*V91m31&2Uie2@K1txmPKzs@6+R zx|+-3u$BNf&W$7if4jN8Gz7_`2^U@+pu^t>h#i0>UBt)yL!5hkl2)_aq#R_86|V1_ ztR~9D34RS-x|mO81%a&5H$<SW=Z?qeiS?IMgu`AZMV9NRgJ%yP85ecT<7lxI#&o%g z^g5Mts<0a}hf!?Qon9x>Cbp*+d^{$sbzsn$jWE2)?{k8)ToZ{Hs4-<7EqBbxuLDU$ z1h<z#?eo=|?VYlHXT40l>nF0OUy_HaiV?`8lI6la>d*V4@`nlv%1&rW=ZLz``p>7` z<{>32Qp=RL08s|y9hDl4dSU>)EIj}!Wr#5kXn^|#@?6*dk#m8c{MK(QmkMGC*4~Q} zr*O~b)hJM7g$Smu%E5my7&Nr^0XEU)i>oW8@~3yPJ(59sZxQc6cwc$keo8JL^(qy~ z{PZMIa8fL$NSoa$f0EV_tj`)F>M5W`!iJg(*O(F^@e!cT2#NkaZ~yyMA3H8(!YAEd zD&>5Jy`(g{9&z0mEg4G6RX}q7>kSoNl7ORx3=vCaVl?++U-XON>y;6*0G$>wn<Yc5 zE(c;|_qW(inUC$C?>9yFAsBFYU@!bKyufCUx(XX=OSMA9Sgyml(9D|s7t6xtX3d^E z2YcKq2Q?%5k@pTKa;oHUv)mWDIiH=Z?aYRy?QHbMGg0h(l_VMNQPnK_As+yix$kyv zpmS460QzFP;w~J__{kw<I!c{KkTTsvNJXqqv4r~HwG#gcu@YB?ubi|i#_yc)57maK z<sJjElA28hS!kZ+eccBX{<1)bUIha#F}k%P*A>ehDi-{$8~^~n+-I!>F_kr#uDBz% zMNDBYDyv{bO5U=+v*GQWdwHz_GELYm(9`X@W(ZW(AX8SkGG&&(-fxWX<_BGqE?@ur zqv-etJ#}RI(h{=Ec9ACn+nFrxhq|g2iv8(j%ip7Y{pF?70#QuyBUHz#WIl}7s@6BL zgC%U2^LwdY`5$9VKEsF$FUM&>M{y4uj<g-?$?E{$Xv`?=t^<K2p36w0tqPZxHtqs2 zqltM8-uK4ws_r|l4>Bqj=m~hm=7u~ha!iF%OzW?g#_?d{ENX3ui|S}}{vp``Y-{W( zzC14uMBiPa@XF=HuC%28icOJSwJ)1HN3?on+{Tb`-+G?n4~!dht(6)UdWIq6ehnG- zU9<zL{{v_N+1Wp!z+mM2V9HaUd?RVgNCr%Pj3s8V={DTDuOu3#<yxYYpb#*b%H3Kk zil_zJD=2ZF@}I(`jjnh1NQ=JTf7&>I9-Z3VNWlErSDlWoYYq#%=pB>>LZya_%c;Ne zzCnLzMaD6vDaKXl;KTJ>q3Ac91T@zJnospC)C<jsY%K*^R#z^*j)}fao+;l3p>L-> zgX~wvT#*#<(Ar?>p%?)MZ>1IOnxH&lUC?fi!Te`_^h8x{>8nY8muxp|r`&~)zp_#Z zYDeV(qHw^Zr(1iI{XpA#AdbjnAc#G`0ZW%6G6ye1G~j2m6oO&1;W+!2=c4A2Gdy3U z{hn8sGnUoQ!%DIlcn|}^z07k7tNsLSvytATPQYgKt5$_#cNDwrW<WRn;IWaj9|<m{ z-A3o(LR%hd#7cLPa<0m5*cYB(!H1c$hpiE8y1XKAs^3EX{}B4iq(ib5kGkyoa2uof zS@zd4;Q<ro$b{H#$4KEas6MCum*n?v4cvcIJ(D>StBbw9W-<nD@t34?*+Bea=FX7R zC}lOX6M)2Xagn}K)(ye9Rq46z!M2SyYF>OR>Y#|^mBeeRz~^R0WnetY!DF>vA&dOW z^)T8$l_fTRp{MKgsh*Q&PzT5cAnHs4$`$$+2&Mv2HO!^{-(Sin3g_;hna9mc|L{BX zpC4+L|Lp7yuC;BXz3#SOg*~CNPUvEL>`-Z^Lvc%$=E!b_YGwb2QGTtC%g*On)l`|7 zg5u%60%!PQuJ!`k@z<_M3$K&$T8HP+-O}ACKRLwlqg)pKi8A*yLTMO1m#3WvYSdW! z!-ZfD-nW$j*gzC+{-ZGdmWNBB$L-EgvPd@@cI(Y%8}Z^iJ9PrEz+~xbawI+9%LoDr zkIazjwLxiDY*K?*44QNpp8V-2dE?#Zsd+$dV=1<yKpm<IhdguLK}L6gYDZ0l@`d79 z@k{EN4qG!-J$`MYxYSZ60uN764QO(rL-Nfy)1^>;+>5iN3_qUocPw)=YO{@7*?k!C zLQ}Tm7ST&C!K*Oh{GY=Jf<a93Ni>p}o>H=w%{fe^(begY%=oICBSq;0@iqXAgGM|E zKTJTID66FEbQYSI1_nd`YVEVAxx;&W{NEK8z4l5~nlj$GAN?FWLTzQH_kls=T0GJM zsHg(-E+!})Jo=qGz-UpPT%46x*bb;PO*Bt^c!PeIfYm(hb6>So6Y}u_v~?<Zth(ob zy(vm}xc-T{=@*tw&kB{BglvV_d54PP$OtU!dx8x5T3$wQ-{mdPd~?_>s_q7Ozxe|8 z<|v{<GYTzH#^>TrE*=~8T@nsT!J6y<6&&L1vLl_RvCr08xmiKJ=x;`)C2IbyBJUQ- zVc7?^v;%e>u*j4v68Fw0S>R1Uj6tD9>({{<5(g6ftq&I)4zxy_or`-t=Wc7(El-)< zFDP1TdgRQes{;Uq40c;BNVQXVJ}*{(WYqKbb5r^nT^(Vaf_vyKpIspjswFQydSXt~ z@N|=(Z(b+^iI^E969Cl30d5iliM#*=miAjnpqAZT`qDiq{~bSQ4>duyuD~{!m~Gw6 z{VGOm{EiU-7yi%jHMnv+Q!26{qylVUt$YLsP4%0kSAj|x2L;G5(ExEWm4{2cq^!Xt z!|3VJ^97*Enxe!X4LCju8Dw4~KUZomIG=X~D9;=y?`)G4cT!x_<G}C(`LYb+nr8Cv zeyS?e{`vIR$bym9?x2^Ln8z-xfzNUAa<m@%h#~MIbgmg+#@l-@`$bqbdK)z%3M!-T zfZ@kx4MinJDj9XfK;J+raZ~~VmCV=a_#z4DRK8NS1ND1MnP;|iwYw2Ibg|>s5sjzo zYpA0WjC{K(9yg_%xb?VIXTp?HLt|wC2FY?R6xKQgw)&htvetbTX^bshljckPfRv(T zf&9Hx-iO_$99UpE%ZmEY<v2mJl<{Q4+dy~X)Mj4>3t{J>I?WJr!6Y-QL~M$I5hkhc zr4t!t2ZvL4qTT9Vd5vqBJ4|`J4U`kXS5@-YQTfr~B6n%-qmrkmtA8>(7kb#qL)WCm zj^k(*-%ffV-PYzP6Rn-Hz2bwS<UX6hfsB3x6UOO4<4>US_O?bTyp^s~>#kOHxt&#o z&VE?qCqZ{nf;<M}`1T$bX7)_a!o628ipu*Mvf51?xb!z##O%4HsS}RLqylrMc;XXR zVMnsD0zl*&JZ)9FgM@-3l_N~hiTxhHlvmNyxMFPS8<M~1_4c8s$9eb`MZsiBieB0E z9r`2LejX`rj^yQ@gkjRV<LX2{uR=c(@rDIb;H)5nj}eA_L`Bz%>)PfxRSXn%MI{7_ zOm9(eX&h`$BpMP~5Jl0atTB)Q`6CAj_^ZNdhf#->t#4v=h2MMFWpmW^4m50kc#kaf z*l+WBc?voOTGC@bUnmEPLTdtUT@9N}j*|`^s&lU{vTO!6y6B&h1{63%+&P4Gm-J^C z5AEn1FV1&KTf80b2Qp*C{8HU9?5Txv6H=Q;k3Q(LV?VOaK6T&AqZj|B5;19%Hn$`w zcG8%@@NV{2dahtbv0gOxl$*XF`Sw%@+s0RApY-s#&YpeMNVLEtk*M^Jpq|-EuNv;} zOH3_;J0I$GH-Q?V(|p0^#n?02M!^eLuZY`mBr)jiDMz~L*zK3kD^7mty1U*G!B0Ih zdv^_45FH1wlS8x7VFn~f%&!?@zfeT#uFYM_M;FaH;zbl>TI<|3v%85?ale>P(3C<3 zSNIwdGb(yI%`zT*`{H3aFJd5L)6T_f5Y9OJ!{QuNPm|d163}7Z-q^?hh!hS4XJne( zUFO?;^xc;k7qU^5l&dg4;rTMO)~vQZSo&}stt<9{sdSNrs>$}qo!8H2d-0KkFu-@Z zLo)#bW`b^<drbuM0r%DK-cp?&A1yC)9D6xh>J+p-x?ertMZ)NRlPKn9G_!1Q!b37X z3cu461XraxpQqJCMHfekHP~;D#i-Q~H&~>uu(Q|`o9&qtJ@J}>TJRix53p}y+4W;? zuMKxC-X_Vk3r|;WQl<@^x%Hf4L;qYr@UW?or+F1U(Q2wpTvSXf%dFHe{iVIMYZ9-^ zz)ZF3ORLfRC9Rng8Rh=clnx-G6c!eiIdtxtJSym!d@Gsu4nm+@GyPC*;E?&U__g2j zp6J4mYHsxOSIpu9C^%cy*F^BWf(9tSGm1m6e(A}t@W#aEk?&vB7ECa@JmuAB4CK&j zP|&q%82D4B=feFH!Fv^c15QlZfDT-oQ*d#zL?UzMWA#U507KT~XNCE{-o6D|Hkfs( zA8w7Tt|(UqE-BpJo52;u=^$!sv6RK3-5QP}KBwOr2;(+68(eY7m?MJ6c%ANhp(as! zd#fX>p((|%>E?GT0jx;zr^pzYSklz{4J*?Ynq?+$Y=#@2Y*ujPupvVS9Sq$pB5aCs z>?~kKgj@J<j_UXLNGQs9i254+4;zT7(Omc709q=AnW+41*HoBHK3oNuQ4k7xx(14D zH99OT3-TLDymiu88)uqdxle<OgZ%tV@@gO4MTr2mC&d(TbT74?T!#`^1Tmv94y{Nc zEby>6c}OJ6l9>w}@n!gko|`<_#=LyqlKU2z%@M2w+RLMwAGPspv6_0mY4NuEa-ZW< zUxpN2-+eZbC<EQ&>9|8?+uM-}bPC}X1kByVPn&OtNI#H8Ib#40Ei~?hKlmJ2*fV4l z*51LRI1dK#Ye?nb%%JDY6o+lBYSz{rlTBo*EG$M;8`M^CDX7H4WT>#%fVa60u81-0 zQK;xOAGtdvoCt>(n@l{O)6N)Ogp8y42fY<MI|e8X1i&N4v~{kFF@j%YkabNY3PsnK zVY1m2ynTnoX3g{rBjdg0{(-!w^qXiB^1zL?p!tBkw=w|R>4cr?2|7vJ8q5@~yW>%? zz~`|Bjo@50)CC_ePMrR7UdXVelU{IGn6D;&`r2rq7Y|7YxZG`OI$h{3q8rCS_v+#A zJKe$po*4QX<^(l6BP3Mz{mO;CWXie5eHD+Khv*Tr>C-4kD4ZJJFqs>#cORqRe8z_? z_O!Y$_Q9o9Y}j}ft+s#80~1eve4h$*;4Ca>j1JO(4d9e0gMZ`8CW61I|DfPC!%R5$ zN-MP3BE{oC^UpI$`h<nyOnmI5){o3dwOTW>?Ml1@m$t#{bw*D|*<D4u7(c!3r7xjy zCc_lP#_H9Zf_rqw^bPuvCh+g6A}d%|{#^{*leqXR|9%bG6v>wXa#m6WEko8uG#fj( zUHTOXQH6HST8Z_mci{F)cD}%pz*Ez{Zgn9AZzIq<S|mz$tvOnDDOA?XM+?tWcTFyy z0$Uu$3Z1{!U+0ffhz~<VyqCr4I30NhOi*nQehtYD_^Z+p*HMoO6s7eh-*;0q-@MwT zj;Djzv(}wPx>KjVK2puPg@nQn`C9KbR&b8jd|23pzqK{M|JYT_5w=j2GurLpXbBHN zy?c+WEo_8=Roq2QKYSAY<2wnBy0JZ@vr$y(hrBRYpmYG|?^hcbUAGr}4OvsXr5o0r z9ZeylWA)B2+KlR%|K?|=r>3OnnGC|;sKoE-dWVh%C_@G$16~bA9g0$e7YL%SY{h|9 zmBa$8b}NdVkOa@Q!TkA19{IXtaQIAWaI7+IV9y(hrMP_MH`kEK!G(P#JVOZGdf^x% zD4bLM4(GzF$oBU3brHL6ae3A6Zy=**(%?A0$ZIFnWJr59nrShyq?{kK>fy_fho^*u zgu;RcLm1++Oi+Q3!7E`xI2_MnjMi?D2#jnw{G#P5GmJ^#el5}x2`p5B>2l)Zk`U$> z=$*YI1TP=<1iXCp(0{%B$6koj?aw3gEA(S09$O^p?*=>wyT^p7998$-E?=0jg9kp) zVwXsK<U>i}$zmIN3YWoWrP5yfDz9y1LGA6WK?W~9nQBhN`Vd2_ZMqz7rI*9a90=Wg z92)5CF@yhlch|rbP=+0hzkGY)mhNfnpYV(3`3K(>SALPG7p48^NGNAeCWMW6;R8-Y zuO%PWy<((2-xA{QdNG>69}%|2uQ>^z-r(HNu%`cy`|)9@8BuOKYB+k|zQI##j@+Y2 z=V{L=9m0@@0~<WI9C%+5(pw@Y8omr7bz35wzn&R&b|q2-N2mMW>^|_v^fexqyMuHI z#m!V&f#3H#3B0}XzwS5q<~W}feU>pDOuj3ge~uv7h&dB4$XeS@RY;=!+OSn;LqbNz zx*AK%bM=~W?mjSm2O%Xv&|Bz^uZ$7obZgSWBOzf1kf|7;3#fU*!Yc_rGzpo5g9DG8 z`~$nt@s^XzPN~`#s?=ukpOx?@<fAZ3o|{rt-R#HX6lAb4T<BGH|L?BR)<#Zh*ZY17 znY6QGlabjY1$@q-9B`5FFhK}hZzX^X(OUqz_#+s<!_Spxs{ofi16+EJ+H5I;+A710 z7Xlac6fshX0re|YU}I&hWpU#p-ScnY#BihvgaHfL1RC>INQv;&SSo2H=Hz*H?c82i zF1-T@C3J!HsNV-;x*?-?Ma3e03<KhY$u@#>W4I1pyEj&TF=^H(dwEjFvL}UoJL8sq zl~>i(UF##Ph7Vm3g8z{3O5k+3F<XFixe;8bAC`^lf?B=|FZD$}+2Xyr+-0BN$Cl`N z2o!wvI=^_6f(Y~oSg`qS`lG9RH;e;)EZU!s1wZab?ni5i{c)#&*6mA!^2%c8_x&UJ zL}!^`?erI8Kq&%R^!9xSI~Y3Jikon8@h+fsyAU#F(H(J|np5eLu*z+=lX<qY#%n%S zRV0`Ah*jP?52S|Znd$~$m@)uH6cg^}w%;?ghHiqVRjOZRCNf^zoZD~QvecF_YyJ7Q zyH*%haFrw8`d5zV%Z6|OdU=l(-j7w=#sVy!3)4<dqeqB-%h-L6i_6cCHu^`{JxtZ; zQIt4kQ<lK%7(zx-DkRMIat6=4aW4rip(PjN&ce{4gp~2dxPw7QnQ$Wcu1Jdm(jiP{ zSAp*2+(qs3)cJesP?>ShErE?iC)ZPtvlob~sQnO1N=8usX%)ijE5Ue;&Sjofe{SwQ z(F?rlo?1tuOy|wX9iW|^Re*gDx;^Fu40;VUq&yCAz15vKKy>Ocw@%4E5jeq$J(QG> zf`pcVJnO%#0*nKxfjmd_=g;E~tKS0mUPcy9fV;oY5|X-iZWUcGEfunN?$u&U=6D?` z2>NC|e+4RZ4aRA5_{yMJZggljo<{(<z#e4i=|?tF*x+QrL!=w`IbjSc;leQnqfPW= zrau-phYN1ribW*xEPQ6V^l-eZi{dK|Vr)qv*Di=fD9Ezj@BLi_{(L@^Fk-grL@<*~ z4TiF+En+dMl$qAO*|Iw&=d@l_0K3}=MjKol>rUR|0`m$Zgc`i{FAWkNcvNs%yGv>% z<kW67pf*bdRV6#|Rf>s#-tWLT+U?)Aq*A1%3U;?sDHUyogUT#&c#&~<s@bC{iKj_d z)PXSEYQ$N(lpGb^_#u)n;UYon-<gi^H&mrr(g6BzK<82x)b9KQ$L^a0S+Z>*43iJu zNKR%lhyKYCNR**6a7ziq`cQ8!1rQUWxa^fiO_7c0<zrGlPR6W{mUV4UsgGLi-6Hbo zC9=a#hkHEi+q|v?mML$PgEhyVo7(56v1CeTUt|IxhrtRtjM#rVj5or2AHLEaoJ~dW z=}R+eH_F$&c`wSq^e#OF$kWOIy@!F{*9XZKH9b8YA~Y(ezrr1@_VB6hbI(`LS2p5# zaTEtFV9u7`y*y<0xJMd{D-4@PG3`sB1wt&tyULXK1QOdLr6xlfZ{OB}@N64ff+v4I z#Ci@hsD%<Sj(=U8@z)H+<A*-_6j`2^a57w6T+d%4qnfTK*p!IbdD%<#mvHH3GFI^U zmcR{m{am|amO+icGh^;{A4e5T<dm;#K92G8f79Jn*<4R#A94*@56U}`-!g%R2Z8Ac zWFOL7P$3N66mMZu^mfuqRYR=4q0pwLgUAS0$&?qjGi3T=%8Zuu^0cczKs#P_J+9p4 zmV^PAMGoXDQS0sptLuk(HgYb$76`aSLVx{+S8i&(-HfO?(0bthn1uzI6Pu5=ZKEmx z>(UZ1N5!zNndTH=D+GT@9%pr{?(G*J?RE|e<2T_~og+uqREEBn=AZASah2tRQ~U3E zioRSbB|Fx=^n#@0UF@f--5|kv4U!pbhH=rWn70E(9a+DB1aL9fMmJ+^-GadR@~p|4 zbSoZrmgU{Q!yq3d$v;x8Uw4vrbsrLh0pi&hNaH}!VYGAx4G>$OTgaa&dv4E~<h>Ge z<Z)g10|>OIK=FJn)^i19$v9F>_l-Z}xB!)|{a*@#?z$=Ny<YWwWIwhelLV_&Ma%T5 zNAnw!_WE_G!?GY>5R3Mgm-3DV4iN7JM*6GE1YG#`WFV-c4gN}B>O*5-ffMRs+leSm z2@kb-8wC~BdA2((Ft9Nns6sI@0xAoU+i0O9{SPJ{^T)*Ta5YuBr;ZHj0_?q1h>q<q z943HTMIIgjLG(tG8RR@);k|-*7HxhQb!KOs*R#$u4&CxiM;kHpz33GLM)VJXXtdk$ zP7gb)8zC9Bx3Jw!5HsY-Uri$k9J?hBMs8*Y?~uT)tSYRIt&`e2K1pfJjL{atpEmEy zOQIY5L1_u+zpVZ5RsuC*wvpf=u5gPUcnj;5dM_zhMeys3VRPIVawnc4{D(iU=`Q?O zjRw^ImrtF*NyFX(UqA!Xfx1cPKSUw(iT`6hkXd82r<{qUAATJORTsf0kdppd>O4hR zd%khtFuyER$MY;|k73{jRHiQfD9wOa6hzMJTi)-8!+H4FomL;gKY2b<4V?p;ThTyE zDx1rAgBpqqcy`!n_{>^TYG?c+GO<kI*@AM>3gn{<0WVpHRm)Ue^+c)8Mygk8qbR4r z(Gi+T|B2N9Xn6gX1R!o_PRAwN_N;0&K>dQMmWoPlh*9jC4@g9nBE0RO$`)pT33*eK zKXoJcQt@;+M6BwMni%oiRBz(fi^xRThHa#=oGxIS5AX0CA9kxwbOO$FmVR^ZvB~xe z1>ZN|Zf2nX`6*hU^%eufxL52e>o#rT5Bl8Vc|Ya8oG=+a6k6i|sCX5LP;yovRq%C? zW7`gt3e_!u_dh?RKIiozj@s=}Jm0BN?QTfoId5L`Wdak?SF&(W4AN-(KR^4)olN=v zE9<*&bb;(rrcR-2a>*`BYn#HKy&6U7EsTc*>c@Wu`~nd0>Ep>_uiTms6I4!>{mCzZ zbv!^d#QG8*=j9n07N(eY)|^Aj!Y^4DkkQ8QD`k1%Cvld|MBM-&H<%CQtJa-nQX-?H zq_zNmZ`_W+P50zET^%~I)2<KLh{j0e^>x&oHoJVGe{8xF>PiDPD11+=2mf5U$^E#j zW%({Lus?AF0Q2Pp`~XN2pS<iR#zG?dn_~e#hnZfH(MFDo=Y%sOl@Z^NFK*ZV=t#8x zsSVld`5$}z?e0ca_1j0QtxB!p9_tAe*@rf%eaKtzxC1XuibDeyO$YM(E}A2l2a8A) zO!o*Df3WT!lzGl9uy1w9a;~|v`!NTm>5{zyxr~d5Op2>I^Bt6i4uAS9^g_nMh~vCc zqBC)kMlRYvP%SfKX?e<()Od;|9lK%M6}lT+e*(6G1VW;_t0TqifKwO?bR%RnG~x=9 z?x5hH+xP$+OgGTJF#(LIGJ{s+cmShe_D(mx(L5>c+B{AvOL?2@BEI3|gkdC31-9UW zMji&#{$v3dItx(TBAC_L)OqMZaWxJV4-Q9L&qizPGgx%%R3PanuvFSUZG0><<(+GB zXcU`jo6}c)deCQxd~msrgYlJhv|xKi^THu3^&QkaIr#Hj|7@Os+O|5K4jhRr$Qc@k zdp0s?5r&5Z#%FXsJVCLaGuRso3)atE((u{Brc{zaAuUA(`T!W{zYVGCD!-=tb8Epx z8Aa}|Z;ts<u1%|bFz(=yoO8yR^p*ZgMD^6E&dc@jwbJHq-xNa+Yr*AgrN<#5S+gIo z)}EmDa1&&GXj3z3<YGFd)BG&4;rJkj(_>hHJfO|%tBdgr9kK{x*nrnp)j~xr*Oy+( zAWS4o%(3b7Q}T^?Wb}OuoTPo$v4JJyMQ7~=UHFIXf2U9XY83sKXLad`=@HYdUtt>a zOknT0NyPa-2@_Sq>$SRg=Z8eDcRPB9BYkOYcE-Z8`_81Z`*dKtL>Ej;Uv#&$n_u`{ zL-t`*JU%HKNZ0gmnQt}KeB>RWqKB$XCm+x3xX2b=H1?97b@3h)4ry?R<FymG>g3b4 zxL=;t(ksO`vtw=O(By>J5Mp42TdBH9BaGDXu~61QucEEN;?EuapS4=Hz6TQE4doSl zD07(%RW8#|`k%xGH5|mnsq9;U>hGn@GUS~f7!<TPGeOPN{b2%azP;-^9vPWY*Mnuy zz*?upnZ0WRhd*J|Yba5%_frfcVzw&ApdtP>L)~c-MEwpJuzl@|m9lnP#w9!?6yK*X zetx-|gf$Y~v5ji^szqUx=&|f))O?ponW+S7M_3rl{WM}JJz_W|P{h(C_}|5TPrX_h zEukrC_2ae9&8!!1@&5QmUj}L68YutADe(spc9#=szztp^^HteIp1U1>UWv@1p`-hG ziTz#@{FN->F9>u-or>J3Vhts)$^{x0(u$jDx%UHk17n(0Z|ZB0wdM3bgi?vC6cHpQ ze_cVl^*4BnKW;A&blNbu6uOgoP#fey=_~vHE}*k$pVyBct~=Is*KIzRu3h`^Cx-#O z7)_A3dm4g`=aKxQhdn?Fu`By^fk{^kaa}o7;Y~6MTz#v51pHMBpJRXl+igmvZf4PA zA^MVfsF1S<8hl91ieGRgY74dn1{$0!^K^=|TE09ex)U_H8{D2UN|ly21IpzCyc7Xv zt@`(Ze?P7;9cGeHqr!nzLXjk{+8!GQ^Gj#CP(&y7bRv|zQ2g(nweZNOXnbsjSl6Vl za7DRPj`+VC=xSoiJL#$JoD9jHl;+EWA4+Csxt*uu@M}KPcM!qB`;S-XShb`&ZP@Xo z?3dehd1=(Ey)u(`h>GZFnYUzv$o22pT;)SoslLYaW^;CThodA7jkaEwT2}oe0WBtW zY#L=)K6Gff|M5X0%A#FEZR%F&)csF4>J^$!H~2=JWau*_f+K)f;OZ<;<j{8ATMkzq zdSB~xykqj#&I)(a^BpM<v?FQOleuFTKw*1;23Jz<8CVXl{9f1xepn;iq6@rn{f#9x zP_&e4#a%pjI$bR^B0EQ)G9ae$&?8WVQD5*uz{hgjl4Ov;kFgS8mw>F<4(cX1-++9A zd}>SDbu?qe)TXi*GotEfKrtgchE+T8=lKU9xd}<#U|?c8MmvIoZ)LUHo)rf`&uVD# z6CsNR3|eRbI_GtYb^9ySUtjKTEZzSgf%FQ`aZB>;@$;+{&3Fq|+OH3@knLjRFu?Bx z^9c~^<b3V~Ttt1Wk6r8X2QwB?%yH7VJ0@x(w2-43|BsGJrd!SHY&&2O>~c}^2NGCP zmYr3L*>jDDlaYW+q^S-Ozq3N;NX}b5b1B{cIo?<GySxAv4}`oL(*gG&xHpOCfzkvJ zvX!1`^S?7Ohm7=BKSY}qbQdk2oqUz^c}Vg|=3^)Mh?oY4NrVbO;Qv3~Tz$(XvwC;W zR{{3R$4yIlApjdIQ>@pRsal|BzWI(21mg;12p5h^E%E=+_TBMV_u;=K$|&wsMB&Z| zS%p%zvdNChYLHb#*;x&vL79<JcVrV%HYM3aWRJ}3z1O)uHyY1*p5Hm=kMl?BRdRp7 zpK*=%^}gO0%rH8m<K|E09g&<Pa_#olke^<~s~lP%oUxW#)pC-fpVU_0d}g>q)q1jm zesi5lvIw-eBc9Qj<p*YD>?e7`$@8N(yd>+Mp#gEE1Xwv5vVXO5a!qCGm?)TsoeEm5 zrO=J|a2E-VIeKERq-r{fO+gb%p}k<F3TT-uFgV5Bwo4iQo#}@(B?LHN?%rv@k&4Q> z9bQT>bi(4<_K{U(pDRs~$x+e)Wx>LX^gf#a+kP%|x5aaiVSIs*@Y;7IF_<zw3Nc3L z38>k%gMywD432^}YaKdtt%P;edV;p2oS>ob&GrC@aRM8%Pm^h0>8kPyd(G0DAusB@ z_wV;|Ihl<gI(l{Eu!t92BUpOBj5ShTO_T{stev8yRQ+^~?@|V_9TnF2M^lkKHA6I^ zJ`_;h9#aFJdkNv#K|WYGFyVLE;%1?5o%zUh-&zR_OQxc{gg=a=Xh?TdoYb7KMS=wo zJ}GD_VpwQM1U6E=s3=GZID4a}6sa2D-gwbEp|ZS2wYFSOn3?I2u1LSzM`kmXdQ63O z3abZOv2eBk!id;80uPw3<MHCd&5`@O)`J>e4<AnEZ8N<us;#}L1%S-Rb~jKQE6cF# zzWv0b`9sjwLU&rz9nPxL?T~3W+zU4jHce!%KHfmI8W{}n^SZaVqz;$nd-;#H^68(2 z50Cr5#qGK-xX1m8xD`Y(rDt2mI=hoTo`Uawnu5~Z9F*>M!91L%BT?9grV}uY1BHqr zCk}i1hO$Iq<sku=JoUmG{$4*1q$Lf`LB{y6XW)hHsK54W`r6m?1Lf7dF2~I)dUj9P zfd{{2jVT&*Su+>RxEOdn_*Kn|hJhPAccdR7-}clTC24{v+;iX=U%onGIPmE~*49IN z$J$UGv7Jm9)K7UYe<Ez_tfY{Zjo-mAooDG<|2W%0Dao9Hi_%FoRYr$tpQ$h>6gmj5 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 N<x5Jk85fNH{6CSAEzJM` diff --git a/contracts/src/v0.8/ccip/docs/multi-chain-overview.drawio b/contracts/src/v0.8/ccip/docs/multi-chain-overview.drawio index 5743bf5182..785edfc2f5 100644 --- a/contracts/src/v0.8/ccip/docs/multi-chain-overview.drawio +++ b/contracts/src/v0.8/ccip/docs/multi-chain-overview.drawio @@ -1,6 +1,6 @@ -<mxfile host="app.diagrams.net" modified="2024-06-18T09:41:15.719Z" agent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36" etag="VX1ypz7fLI3pwnHRlB4Z" version="24.5.4" type="device"> +<mxfile host="app.diagrams.net" agent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36" version="24.7.13"> <diagram id="C5RBs43oDa-KdzZeNtuy" name="Page-1"> - <mxGraphModel dx="6839" dy="4034" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0"> + <mxGraphModel dx="3728" dy="2314" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0"> <root> <mxCell id="WIyWlLk6GJQsqaUBKTNV-0" /> <mxCell id="WIyWlLk6GJQsqaUBKTNV-1" parent="WIyWlLk6GJQsqaUBKTNV-0" /> @@ -1340,7 +1340,7 @@ <mxCell id="woXJvjXyPqNF8OMwea0D-9" value="&lt;font style=&quot;font-size: 14px;&quot;&gt;Router&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fontSize=12;glass=0;strokeWidth=1;shadow=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> <mxGeometry x="100" y="1300" width="120" height="40" as="geometry" /> </mxCell> - <mxCell id="woXJvjXyPqNF8OMwea0D-10" value="Multi&lt;br&gt;OnRamp" style="rounded=1;whiteSpace=wrap;html=1;fontSize=12;glass=0;strokeWidth=1;shadow=0;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> + <mxCell id="woXJvjXyPqNF8OMwea0D-10" value="OnRamp" style="rounded=1;whiteSpace=wrap;html=1;fontSize=12;glass=0;strokeWidth=1;shadow=0;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> <mxGeometry x="-20" y="1460" width="120" height="40" as="geometry" /> </mxCell> <mxCell id="woXJvjXyPqNF8OMwea0D-11" value="" style="rounded=1;html=1;jettySize=auto;orthogonalLoop=1;fontSize=11;endArrow=none;endFill=0;endSize=8;strokeWidth=1;shadow=0;labelBackgroundColor=none;entryX=0.5;entryY=0;entryDx=0;entryDy=0;dashed=1;startArrow=block;startFill=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;curved=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="woXJvjXyPqNF8OMwea0D-10" target="woXJvjXyPqNF8OMwea0D-48" edge="1"> @@ -1356,7 +1356,7 @@ <mxCell id="woXJvjXyPqNF8OMwea0D-12" value="Optimism" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontStyle=1;fontSize=17;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> <mxGeometry x="20" y="1700" width="70" height="30" as="geometry" /> </mxCell> - <mxCell id="woXJvjXyPqNF8OMwea0D-13" value="Multi&lt;br&gt;OffRamp" style="rounded=1;whiteSpace=wrap;html=1;fontSize=12;glass=0;strokeWidth=1;shadow=0;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> + <mxCell id="woXJvjXyPqNF8OMwea0D-13" value="&lt;div&gt;&lt;span style=&quot;background-color: initial;&quot;&gt;OffRamp&lt;/span&gt;&lt;br&gt;&lt;/div&gt;" style="rounded=1;whiteSpace=wrap;html=1;fontSize=12;glass=0;strokeWidth=1;shadow=0;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> <mxGeometry x="110" y="1785" width="120" height="40" as="geometry" /> </mxCell> <mxCell id="woXJvjXyPqNF8OMwea0D-14" value="" style="html=1;jettySize=auto;orthogonalLoop=1;fontSize=11;endArrow=classic;endFill=1;endSize=8;strokeWidth=1;shadow=0;labelBackgroundColor=none;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;rounded=1;strokeColor=#242424;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="woXJvjXyPqNF8OMwea0D-13" target="woXJvjXyPqNF8OMwea0D-46" edge="1"> @@ -1376,10 +1376,10 @@ <mxCell id="woXJvjXyPqNF8OMwea0D-17" value="Router" style="rounded=1;whiteSpace=wrap;html=1;fontSize=14;glass=0;strokeWidth=1;shadow=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> <mxGeometry x="460" y="1330" width="120" height="40" as="geometry" /> </mxCell> - <mxCell id="woXJvjXyPqNF8OMwea0D-18" value="Multi&lt;div&gt;OnRamp&lt;/div&gt;" style="rounded=1;whiteSpace=wrap;html=1;fontSize=12;glass=0;strokeWidth=1;shadow=0;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> + <mxCell id="woXJvjXyPqNF8OMwea0D-18" value="&lt;span style=&quot;background-color: initial;&quot;&gt;OnRamp&lt;/span&gt;" style="rounded=1;whiteSpace=wrap;html=1;fontSize=12;glass=0;strokeWidth=1;shadow=0;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> <mxGeometry x="390" y="1460" width="120" height="40" as="geometry" /> </mxCell> - <mxCell id="woXJvjXyPqNF8OMwea0D-19" value="Multi&lt;div&gt;OnRamp&amp;nbsp;- New&lt;/div&gt;" style="rounded=1;whiteSpace=wrap;html=1;fontSize=12;glass=0;strokeWidth=1;shadow=0;fillColor=#d5e8d4;strokeColor=#82b366;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> + <mxCell id="woXJvjXyPqNF8OMwea0D-19" value="&lt;span style=&quot;background-color: initial;&quot;&gt;OnRamp&amp;nbsp;- New&lt;/span&gt;" style="rounded=1;whiteSpace=wrap;html=1;fontSize=12;glass=0;strokeWidth=1;shadow=0;fillColor=#d5e8d4;strokeColor=#82b366;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> <mxGeometry x="545" y="1460" width="120" height="40" as="geometry" /> </mxCell> <mxCell id="woXJvjXyPqNF8OMwea0D-20" value="" style="rounded=1;html=1;jettySize=auto;orthogonalLoop=1;fontSize=11;endArrow=block;endFill=0;endSize=8;strokeWidth=1;shadow=0;labelBackgroundColor=none;edgeStyle=orthogonalEdgeStyle;entryX=0.5;entryY=0;entryDx=0;entryDy=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;dashed=1;dashPattern=1 4;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="woXJvjXyPqNF8OMwea0D-17" target="woXJvjXyPqNF8OMwea0D-19" edge="1"> @@ -1388,7 +1388,7 @@ <mxPoint x="530" y="1470" as="targetPoint" /> </mxGeometry> </mxCell> - <mxCell id="woXJvjXyPqNF8OMwea0D-22" value="Multi&lt;div&gt;OffRamp - New&lt;/div&gt;" style="rounded=1;whiteSpace=wrap;html=1;fontSize=12;glass=0;strokeWidth=1;shadow=0;fillColor=#d5e8d4;strokeColor=#82b366;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> + <mxCell id="woXJvjXyPqNF8OMwea0D-22" value="&lt;span style=&quot;background-color: initial;&quot;&gt;OffRamp - New&lt;/span&gt;" style="rounded=1;whiteSpace=wrap;html=1;fontSize=12;glass=0;strokeWidth=1;shadow=0;fillColor=#d5e8d4;strokeColor=#82b366;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> <mxGeometry x="713" y="1785" width="120" height="40" as="geometry" /> </mxCell> <mxCell id="woXJvjXyPqNF8OMwea0D-24" value="" style="html=1;jettySize=auto;orthogonalLoop=1;fontSize=11;endArrow=classic;endFill=1;endSize=8;strokeWidth=1;shadow=0;labelBackgroundColor=none;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;rounded=1;strokeColor=#242424;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="woXJvjXyPqNF8OMwea0D-22" target="woXJvjXyPqNF8OMwea0D-46" edge="1"> @@ -1426,7 +1426,7 @@ <mxGeometry x="40" y="1540" width="90" height="20" as="geometry" /> </mxCell> <mxCell id="woXJvjXyPqNF8OMwea0D-34" value="&lt;font style=&quot;font-size: 12px;&quot;&gt;Relay&amp;nbsp;roots&lt;br&gt;&amp;amp; prices&lt;/font&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=13;rotation=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> - <mxGeometry x="160" y="1705" width="100" height="20" as="geometry" /> + <mxGeometry x="160" y="1711.5" width="100" height="20" as="geometry" /> </mxCell> <mxCell id="woXJvjXyPqNF8OMwea0D-35" value="" style="endArrow=classic;html=1;rounded=0;fontSize=13;fontColor=#660000;strokeWidth=1;entryX=0.5;entryY=0;entryDx=0;entryDy=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;endFill=1;endSize=8;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="woXJvjXyPqNF8OMwea0D-48" target="woXJvjXyPqNF8OMwea0D-13" edge="1"> <mxGeometry width="50" height="50" relative="1" as="geometry"> @@ -1496,7 +1496,7 @@ <mxCell id="woXJvjXyPqNF8OMwea0D-53" value="Solana" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontStyle=1;fontSize=17;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> <mxGeometry x="-369" y="1695" width="70" height="30" as="geometry" /> </mxCell> - <mxCell id="woXJvjXyPqNF8OMwea0D-54" value="Multi&lt;br&gt;OffRamp" style="rounded=1;whiteSpace=wrap;html=1;fontSize=12;glass=0;strokeWidth=1;shadow=0;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> + <mxCell id="woXJvjXyPqNF8OMwea0D-54" value="OffRamp" style="rounded=1;whiteSpace=wrap;html=1;fontSize=12;glass=0;strokeWidth=1;shadow=0;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> <mxGeometry x="-188" y="1785" width="120" height="40" as="geometry" /> </mxCell> <mxCell id="woXJvjXyPqNF8OMwea0D-55" value="Router" style="rounded=1;whiteSpace=wrap;html=1;fontSize=14;glass=0;strokeWidth=1;shadow=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> @@ -1617,8 +1617,8 @@ <mxPoint x="-57.99999999999977" y="1470" as="sourcePoint" /> <mxPoint x="-60" y="1350" as="targetPoint" /> <Array as="points"> - <mxPoint x="10" y="1450" /> - <mxPoint x="10" y="1360" /> + <mxPoint x="20" y="1450" /> + <mxPoint x="20" y="1360" /> <mxPoint x="-70" y="1360" /> </Array> </mxGeometry> @@ -1667,10 +1667,10 @@ <mxCell id="woXJvjXyPqNF8OMwea0D-143" value="Mint or release" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=12;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> <mxGeometry x="215" y="1975" width="90" height="20" as="geometry" /> </mxCell> - <mxCell id="woXJvjXyPqNF8OMwea0D-161" value="Multi&lt;br&gt;OnRamp" style="rounded=1;whiteSpace=wrap;html=1;fontSize=12;glass=0;strokeWidth=1;shadow=0;fillColor=#d5e8d4;strokeColor=#82b366;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> + <mxCell id="woXJvjXyPqNF8OMwea0D-161" value="OnRamp" style="rounded=1;whiteSpace=wrap;html=1;fontSize=12;glass=0;strokeWidth=1;shadow=0;fillColor=#d5e8d4;strokeColor=#82b366;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> <mxGeometry x="-1088" y="1650" width="120" height="40" as="geometry" /> </mxCell> - <mxCell id="woXJvjXyPqNF8OMwea0D-162" value="Multi&lt;br&gt;OffRamp" style="rounded=1;whiteSpace=wrap;html=1;fontSize=12;glass=0;strokeWidth=1;shadow=0;fillColor=#d5e8d4;strokeColor=#82b366;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> + <mxCell id="woXJvjXyPqNF8OMwea0D-162" value="OffRamp" style="rounded=1;whiteSpace=wrap;html=1;fontSize=12;glass=0;strokeWidth=1;shadow=0;fillColor=#d5e8d4;strokeColor=#82b366;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> <mxGeometry x="-1087" y="1875" width="120" height="40" as="geometry" /> </mxCell> <mxCell id="woXJvjXyPqNF8OMwea0D-163" value="Router" style="rounded=1;whiteSpace=wrap;html=1;fontSize=14;glass=0;strokeWidth=1;shadow=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> @@ -1789,7 +1789,7 @@ <mxGeometry x="-1030" y="2040" width="67" height="20" as="geometry" /> </mxCell> <mxCell id="woXJvjXyPqNF8OMwea0D-191" value="Write merkle root" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> - <mxGeometry x="-1110" y="1845" width="72" height="30" as="geometry" /> + <mxGeometry x="-1102" y="1835" width="72" height="30" as="geometry" /> </mxCell> <mxCell id="woXJvjXyPqNF8OMwea0D-192" value="Read merkle root&lt;br&gt;&amp;amp; execute msgs" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> <mxGeometry x="-920" y="1830" width="100" height="30" as="geometry" /> @@ -1810,7 +1810,7 @@ <mxCell id="woXJvjXyPqNF8OMwea0D-221" value="Multi chain" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontStyle=1;fontSize=17;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> <mxGeometry x="-420" y="1190" width="180" height="30" as="geometry" /> </mxCell> - <mxCell id="woXJvjXyPqNF8OMwea0D-223" value="&lt;font style=&quot;font-size: 16px;&quot;&gt;PriceRegistry&lt;br&gt;&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fontSize=12;glass=0;strokeWidth=1;shadow=0;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> + <mxCell id="woXJvjXyPqNF8OMwea0D-223" value="&lt;font style=&quot;font-size: 16px;&quot;&gt;FeeQuoter&lt;br&gt;&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fontSize=12;glass=0;strokeWidth=1;shadow=0;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> <mxGeometry x="-359" y="1745" width="120" height="40" as="geometry" /> </mxCell> <mxCell id="woXJvjXyPqNF8OMwea0D-240" value="&lt;font style=&quot;font-size: 112px;&quot;&gt;OCR3&lt;/font&gt;" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> @@ -1862,7 +1862,7 @@ <mxCell id="woXJvjXyPqNF8OMwea0D-282" value="&lt;font style=&quot;font-size: 18px;&quot;&gt;RMN&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fontSize=18;glass=0;strokeWidth=1;shadow=0;strokeColor=#242424;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> <mxGeometry x="410" y="1806.5" width="120" height="40" as="geometry" /> </mxCell> - <mxCell id="woXJvjXyPqNF8OMwea0D-283" value="&lt;font style=&quot;font-size: 16px;&quot;&gt;PriceRegistry&lt;br&gt;&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fontSize=12;glass=0;strokeWidth=1;shadow=0;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> + <mxCell id="woXJvjXyPqNF8OMwea0D-283" value="&lt;font style=&quot;font-size: 16px;&quot;&gt;FeeQuoter&lt;br&gt;&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fontSize=12;glass=0;strokeWidth=1;shadow=0;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> <mxGeometry x="410" y="1761.5" width="120" height="40" as="geometry" /> </mxCell> <mxCell id="woXJvjXyPqNF8OMwea0D-284" value="&lt;font style=&quot;font-size: 12px;&quot;&gt;TokenAdminRegistry&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fontSize=12;glass=0;strokeWidth=1;shadow=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> @@ -1880,7 +1880,7 @@ <mxCell id="woXJvjXyPqNF8OMwea0D-290" value="&lt;font style=&quot;font-size: 18px;&quot;&gt;RMN&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fontSize=18;glass=0;strokeWidth=1;shadow=0;strokeColor=#242424;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> <mxGeometry x="633.5" y="1315" width="120" height="40" as="geometry" /> </mxCell> - <mxCell id="woXJvjXyPqNF8OMwea0D-291" value="&lt;font style=&quot;font-size: 16px;&quot;&gt;PriceRegistry&lt;br&gt;&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fontSize=12;glass=0;strokeWidth=1;shadow=0;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> + <mxCell id="woXJvjXyPqNF8OMwea0D-291" value="&lt;font style=&quot;font-size: 16px;&quot;&gt;FeeQuoter&lt;br&gt;&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fontSize=12;glass=0;strokeWidth=1;shadow=0;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> <mxGeometry x="633.5" y="1270" width="120" height="40" as="geometry" /> </mxCell> <mxCell id="woXJvjXyPqNF8OMwea0D-292" value="&lt;font style=&quot;font-size: 12px;&quot;&gt;TokenAdminRegistry&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fontSize=12;glass=0;strokeWidth=1;shadow=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> @@ -1908,7 +1908,7 @@ <mxCell id="woXJvjXyPqNF8OMwea0D-302" value="&lt;font style=&quot;font-size: 18px;&quot;&gt;RMN&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fontSize=18;glass=0;strokeWidth=1;shadow=0;strokeColor=#242424;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> <mxGeometry x="-366" y="1455" width="120" height="40" as="geometry" /> </mxCell> - <mxCell id="woXJvjXyPqNF8OMwea0D-303" value="&lt;font style=&quot;font-size: 16px;&quot;&gt;PriceRegistry&lt;br&gt;&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fontSize=12;glass=0;strokeWidth=1;shadow=0;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> + <mxCell id="woXJvjXyPqNF8OMwea0D-303" value="&lt;font style=&quot;font-size: 16px;&quot;&gt;FeeQuoter&lt;br&gt;&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fontSize=12;glass=0;strokeWidth=1;shadow=0;fillColor=#dae8fc;strokeColor=#6c8ebf;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> <mxGeometry x="-366" y="1410" width="120" height="40" as="geometry" /> </mxCell> <mxCell id="woXJvjXyPqNF8OMwea0D-304" value="&lt;font style=&quot;font-size: 12px;&quot;&gt;TokenAdminRegistry&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fontSize=12;glass=0;strokeWidth=1;shadow=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> @@ -1926,11 +1926,8 @@ <mxPoint x="-101" y="1489.97" as="targetPoint" /> </mxGeometry> </mxCell> - <mxCell id="woXJvjXyPqNF8OMwea0D-311" value="getPrices&lt;div&gt;getPool&lt;br&gt;&lt;/div&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=12;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> - <mxGeometry x="-92" y="1445" width="75" height="30" as="geometry" /> - </mxCell> - <mxCell id="woXJvjXyPqNF8OMwea0D-312" value="&lt;div&gt;isCursed&lt;div&gt;getNonce&lt;/div&gt;&lt;/div&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=12;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> - <mxGeometry x="-92" y="1490" width="75" height="20" as="geometry" /> + <mxCell id="woXJvjXyPqNF8OMwea0D-311" value="&lt;font style=&quot;font-size: 11px;&quot;&gt;processMessageArgs&lt;/font&gt;&lt;div style=&quot;font-size: 11px; line-height: 180%;&quot;&gt;&lt;font style=&quot;font-size: 11px;&quot;&gt;onOutboundMessage&lt;/font&gt;&lt;/div&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=12;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> + <mxGeometry x="-90" y="1420" width="85" height="40" as="geometry" /> </mxCell> <mxCell id="woXJvjXyPqNF8OMwea0D-313" value="Old ramp is configured, don&#39;t send to the new one yet" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> <mxGeometry x="382.5" y="1380" width="128.5" height="30" as="geometry" /> @@ -1987,12 +1984,6 @@ </Array> </mxGeometry> </mxCell> - <mxCell id="woXJvjXyPqNF8OMwea0D-323" value="&lt;font style=&quot;font-size: 12px;&quot;&gt;Read events&lt;/font&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=13;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> - <mxGeometry x="330" y="1542" width="100" height="20" as="geometry" /> - </mxCell> - <mxCell id="woXJvjXyPqNF8OMwea0D-324" value="&lt;font style=&quot;font-size: 12px;&quot;&gt;Read events&lt;/font&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=13;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> - <mxGeometry x="637.25" y="1542" width="83.5" height="20" as="geometry" /> - </mxCell> <mxCell id="woXJvjXyPqNF8OMwea0D-328" value="COMMIT DON&lt;div&gt;BLUE&lt;/div&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontStyle=1;fontSize=17;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> <mxGeometry x="230" y="1630" width="130" height="30" as="geometry" /> </mxCell> @@ -2030,10 +2021,10 @@ <mxCell id="woXJvjXyPqNF8OMwea0D-343" value="EXEC DON&lt;div&gt;GREEN&lt;/div&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontStyle=1;fontSize=17;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> <mxGeometry x="821" y="1630" width="115" height="30" as="geometry" /> </mxCell> - <mxCell id="LKB6LAdQHVU2I6fmtLf7-1" value="&lt;font style=&quot;font-size: 16px;&quot;&gt;PriceRegistry&lt;br&gt;&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fontSize=12;glass=0;strokeWidth=1;shadow=0;fillColor=#d5e8d4;strokeColor=#82b366;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> + <mxCell id="LKB6LAdQHVU2I6fmtLf7-1" value="&lt;font style=&quot;font-size: 16px;&quot;&gt;FeeQuoter&lt;br&gt;&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fontSize=12;glass=0;strokeWidth=1;shadow=0;fillColor=#d5e8d4;strokeColor=#82b366;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> <mxGeometry x="540" y="1761.5" width="120" height="40" as="geometry" /> </mxCell> - <mxCell id="LKB6LAdQHVU2I6fmtLf7-2" value="&lt;font style=&quot;font-size: 16px;&quot;&gt;PriceRegistry&lt;br&gt;&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fontSize=12;glass=0;strokeWidth=1;shadow=0;fillColor=#d5e8d4;strokeColor=#82b366;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> + <mxCell id="LKB6LAdQHVU2I6fmtLf7-2" value="&lt;font style=&quot;font-size: 16px;&quot;&gt;FeeQuoter&lt;br&gt;&lt;/font&gt;" style="rounded=1;whiteSpace=wrap;html=1;fontSize=12;glass=0;strokeWidth=1;shadow=0;fillColor=#d5e8d4;strokeColor=#82b366;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> <mxGeometry x="765" y="1270" width="120" height="40" as="geometry" /> </mxCell> <mxCell id="LKB6LAdQHVU2I6fmtLf7-5" value="&lt;span style=&quot;font-size: 13px;&quot;&gt;Shared&lt;/span&gt;" style="rounded=1;whiteSpace=wrap;html=1;fontSize=12;glass=0;strokeWidth=1;shadow=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> @@ -2051,9 +2042,21 @@ <mxCell id="LKB6LAdQHVU2I6fmtLf7-10" value="&lt;span style=&quot;font-size: 13px;&quot;&gt;External&lt;/span&gt;" style="rounded=1;whiteSpace=wrap;html=1;fontSize=12;glass=0;strokeWidth=1;shadow=0;fillColor=#e1d5e7;strokeColor=#9673a6;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> <mxGeometry x="-287.5" y="1315" width="77.5" height="40" as="geometry" /> </mxCell> - <mxCell id="LndgSB7H6BAqNtGT-OBd-0" value="&lt;font style=&quot;font-size: 112px;&quot;&gt;OCR2&lt;/font&gt;" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1"> + <mxCell id="LndgSB7H6BAqNtGT-OBd-0" value="&lt;font style=&quot;font-size: 112px;&quot;&gt;OCR2&lt;/font&gt;" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> <mxGeometry x="-1175" y="-160" width="569" height="190" as="geometry" /> </mxCell> + <mxCell id="lUZlNMkhEWmQk4-FoNXM-0" value="Read events" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=13;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> + <mxGeometry x="330" y="1540" width="90" height="20" as="geometry" /> + </mxCell> + <mxCell id="lUZlNMkhEWmQk4-FoNXM-1" value="Read events" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=13;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> + <mxGeometry x="635" y="1540" width="90" height="20" as="geometry" /> + </mxCell> + <mxCell id="lUZlNMkhEWmQk4-FoNXM-2" value="&lt;div style=&quot;font-size: 11px; line-height: 120%;&quot;&gt;&lt;font style=&quot;font-size: 11px;&quot;&gt;&lt;br&gt;&lt;/font&gt;&lt;/div&gt;&lt;div style=&quot;font-size: 11px; line-height: 120%;&quot;&gt;&lt;font style=&quot;font-size: 11px;&quot;&gt;getIncremented-&lt;/font&gt;&lt;/div&gt;&lt;div style=&quot;font-size: 11px; line-height: 120%;&quot;&gt;&lt;font style=&quot;font-size: 11px;&quot;&gt;OutboundNonce&lt;br&gt;&lt;/font&gt;&lt;/div&gt;&lt;div style=&quot;font-size: 11px; line-height: 120%;&quot;&gt;&lt;font style=&quot;font-size: 11px;&quot;&gt;getPool&lt;/font&gt;&lt;/div&gt;&lt;div style=&quot;font-size: 11px; line-height: 120%;&quot;&gt;&lt;div style=&quot;line-height: 120%;&quot;&gt;&lt;br&gt;&lt;/div&gt;&lt;/div&gt;" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=12;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1"> + <mxGeometry x="-105" y="1480" width="85" height="53" as="geometry" /> + </mxCell> + <mxCell id="2QNqtgelfZp8qdsyauz8-0" value="All chains are senders and receivers, to keep this readable the top chains only send and the bottom chains only receive" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontStyle=1;fontSize=17;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1"> + <mxGeometry x="-144.5" y="1192" width="1165" height="30" as="geometry" /> + </mxCell> </root> </mxGraphModel> </diagram> From a847f78b958976e4f22ee56fc33310359092e9c1 Mon Sep 17 00:00:00 2001 From: Ryan <80392855+RayXpub@users.noreply.github.com> Date: Fri, 13 Sep 2024 18:49:53 +0400 Subject: [PATCH 094/115] Make forwardFromRouter non reentrant (#1437) ## Motivation Currently the `OnRamp` performs 3 separate calls to the `FeeQuoter` on the hot path, including 2 in the `forwardFromRouter` function: 1. `getValidatedFee` 2. `processMessageArgs` 3. `processPoolReturnData` This is done to follow the CEI pattern and guard against reentrancy due to the untrusted calls to the pools. This is not optimal for gas but it also makes contract interactions more complex. ## Solution Implement a non reentrant flag and reorder the `forwardFromRouter` function layout. The calls to the pools are now performed first, relying on the reentrancy protection. We reduce the `FeeQuoter` calls in `forwardFromRouter` to a single `processMessageArgs` call. ## Notes Optimizer runs had to be decreased due to contract size which is why gas diffs are showing a gas increase. At equivalent runs diffs are: ``` test_ForwardFromRouterExtraArgsV2_Success() (gas: -65 (-0.045%)) test_ForwardFromRouterSuccessLegacyExtraArgs() (gas: -65 (-0.045%)) test_ForwardFromRouterSuccessCustomExtraArgs() (gas: -65 (-0.045%)) test_ForwardFromRouter_Success() (gas: -65 (-0.045%)) test_ForwardFromRouterSuccessEmptyExtraArgs() (gas: -66 (-0.046%)) test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() (gas: -65 (-0.057%)) test_forwardFromRouter_WithValidation_Success() (gas: 318 (0.113%)) test_E2E_3MessagesMMultiOffRampSuccess_gas() (gas: -1139 (-0.074%)) ``` --- contracts/foundry.toml | 2 +- contracts/gas-snapshots/ccip.gas-snapshot | 1961 +++++++++-------- contracts/src/v0.8/ccip/FeeQuoter.sol | 97 +- .../src/v0.8/ccip/interfaces/IFeeQuoter.sol | 38 +- .../v0.8/ccip/interfaces/IPriceRegistry.sol | 36 - contracts/src/v0.8/ccip/onRamp/OnRamp.sol | 50 +- .../MultiOnRampTokenPoolReentrancy.t.sol | 26 +- .../v0.8/ccip/test/e2e/MultiRampsEnd2End.sol | 2 +- .../v0.8/ccip/test/feeQuoter/FeeQuoter.t.sol | 139 +- .../ccip/test/feeQuoter/FeeQuoterSetup.t.sol | 10 +- .../src/v0.8/ccip/test/onRamp/OnRamp.t.sol | 27 +- .../v0.8/ccip/test/onRamp/OnRampSetup.t.sol | 1 + .../rateLimiter/AggregateRateLimiter.t.sol | 6 +- .../ccip/generated/fee_quoter/fee_quoter.go | 70 +- .../ccip/generated/onramp/onramp.go | 15 +- ...rapper-dependency-versions-do-not-edit.txt | 4 +- .../ccip/mocks/fee_quoter_interface.go | 103 +- 17 files changed, 1292 insertions(+), 1295 deletions(-) diff --git a/contracts/foundry.toml b/contracts/foundry.toml index cb07c88de9..501390eb80 100644 --- a/contracts/foundry.toml +++ b/contracts/foundry.toml @@ -26,7 +26,7 @@ single_line_statement_blocks = "preserve" solc_version = '0.8.24' src = 'src/v0.8/ccip' test = 'src/v0.8/ccip/test' -optimizer_runs = 1_650 +optimizer_runs = 800 evm_version = 'paris' [profile.functions] diff --git a/contracts/gas-snapshots/ccip.gas-snapshot b/contracts/gas-snapshots/ccip.gas-snapshot index 36b43c9bf2..98071286f6 100644 --- a/contracts/gas-snapshots/ccip.gas-snapshot +++ b/contracts/gas-snapshots/ccip.gas-snapshot @@ -1,994 +1,995 @@ ARMProxyStandaloneTest:test_ARMCallEmptyContractRevert() (gas: 19675) -ARMProxyStandaloneTest:test_Constructor() (gas: 315049) -ARMProxyStandaloneTest:test_SetARM() (gas: 16581) -ARMProxyStandaloneTest:test_SetARMzero() (gas: 11267) -ARMProxyTest:test_ARMCallRevertReasonForwarded() (gas: 47874) -ARMProxyTest:test_ARMIsBlessed_Success() (gas: 36353) -ARMProxyTest:test_ARMIsCursed_Success() (gas: 49833) -AggregateTokenLimiter_constructor:test_Constructor_Success() (gas: 26998) -AggregateTokenLimiter_getTokenBucket:test_GetTokenBucket_Success() (gas: 19841) -AggregateTokenLimiter_getTokenBucket:test_Refill_Success() (gas: 41523) +ARMProxyStandaloneTest:test_Constructor() (gas: 310043) +ARMProxyStandaloneTest:test_SetARM() (gas: 16587) +ARMProxyStandaloneTest:test_SetARMzero() (gas: 11297) +ARMProxyTest:test_ARMCallRevertReasonForwarded() (gas: 47898) +ARMProxyTest:test_ARMIsBlessed_Success() (gas: 36363) +ARMProxyTest:test_ARMIsCursed_Success() (gas: 49851) +AggregateTokenLimiter_constructor:test_Constructor_Success() (gas: 27118) +AggregateTokenLimiter_getTokenBucket:test_GetTokenBucket_Success() (gas: 19871) +AggregateTokenLimiter_getTokenBucket:test_Refill_Success() (gas: 41586) AggregateTokenLimiter_getTokenBucket:test_TimeUnderflow_Revert() (gas: 15452) -AggregateTokenLimiter_getTokenLimitAdmin:test_GetTokenLimitAdmin_Success() (gas: 10531) -AggregateTokenLimiter_getTokenValue:test_GetTokenValue_Success() (gas: 17471) -AggregateTokenLimiter_getTokenValue:test_NoTokenPrice_Reverts() (gas: 21366) -AggregateTokenLimiter_rateLimitValue:test_AggregateValueMaxCapacityExceeded_Revert() (gas: 16520) -AggregateTokenLimiter_rateLimitValue:test_RateLimitValueSuccess_gas() (gas: 18354) -AggregateTokenLimiter_setAdmin:test_OnlyOwnerOrAdmin_Revert() (gas: 13066) -AggregateTokenLimiter_setAdmin:test_Owner_Success() (gas: 18998) -AggregateTokenLimiter_setRateLimiterConfig:test_OnlyOnlyCallableByAdminOrOwner_Revert() (gas: 17522) -AggregateTokenLimiter_setRateLimiterConfig:test_Owner_Success() (gas: 30249) -AggregateTokenLimiter_setRateLimiterConfig:test_TokenLimitAdmin_Success() (gas: 32263) -BurnFromMintTokenPool_lockOrBurn:test_ChainNotAllowed_Revert() (gas: 28791) -BurnFromMintTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 55142) -BurnFromMintTokenPool_lockOrBurn:test_PoolBurn_Success() (gas: 243690) -BurnFromMintTokenPool_lockOrBurn:test_Setup_Success() (gas: 23947) -BurnMintTokenPool_lockOrBurn:test_ChainNotAllowed_Revert() (gas: 27558) -BurnMintTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 55142) -BurnMintTokenPool_lockOrBurn:test_PoolBurn_Success() (gas: 241578) -BurnMintTokenPool_lockOrBurn:test_Setup_Success() (gas: 17677) -BurnMintTokenPool_releaseOrMint:test_ChainNotAllowed_Revert() (gas: 28787) -BurnMintTokenPool_releaseOrMint:test_PoolMintNotHealthy_Revert() (gas: 56223) -BurnMintTokenPool_releaseOrMint:test_PoolMint_Success() (gas: 112349) -BurnWithFromMintTokenPool_lockOrBurn:test_ChainNotAllowed_Revert() (gas: 28791) -BurnWithFromMintTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 55142) -BurnWithFromMintTokenPool_lockOrBurn:test_PoolBurn_Success() (gas: 243716) -BurnWithFromMintTokenPool_lockOrBurn:test_Setup_Success() (gas: 23951) -CCIPClientExample_sanity:test_ImmutableExamples_Success() (gas: 2092239) -CCIPConfigSetup:test_getCapabilityConfiguration_Success() (gas: 9539) -CCIPConfig_ConfigStateMachine:test__computeConfigDigest_Success() (gas: 66156) -CCIPConfig_ConfigStateMachine:test__computeNewConfigWithMeta_InitToRunning_Success() (gas: 358893) -CCIPConfig_ConfigStateMachine:test__computeNewConfigWithMeta_RunningToStaging_Success() (gas: 476337) -CCIPConfig_ConfigStateMachine:test__computeNewConfigWithMeta_StagingToRunning_Success() (gas: 443036) -CCIPConfig_ConfigStateMachine:test__groupByPluginType_TooManyOCR3Configs_Reverts() (gas: 34154) -CCIPConfig_ConfigStateMachine:test__groupByPluginType_threeCommitConfigs_Reverts() (gas: 57226) -CCIPConfig_ConfigStateMachine:test__groupByPluginType_threeExecutionConfigs_Reverts() (gas: 57164) -CCIPConfig_ConfigStateMachine:test__stateFromConfigLength_Success() (gas: 11719) +AggregateTokenLimiter_getTokenLimitAdmin:test_GetTokenLimitAdmin_Success() (gas: 10537) +AggregateTokenLimiter_getTokenValue:test_GetTokenValue_Success() (gas: 17531) +AggregateTokenLimiter_getTokenValue:test_NoTokenPrice_Reverts() (gas: 21414) +AggregateTokenLimiter_rateLimitValue:test_AggregateValueMaxCapacityExceeded_Revert() (gas: 16586) +AggregateTokenLimiter_rateLimitValue:test_RateLimitValueSuccess_gas() (gas: 18357) +AggregateTokenLimiter_setAdmin:test_OnlyOwnerOrAdmin_Revert() (gas: 13078) +AggregateTokenLimiter_setAdmin:test_Owner_Success() (gas: 19016) +AggregateTokenLimiter_setRateLimiterConfig:test_OnlyOnlyCallableByAdminOrOwner_Revert() (gas: 17546) +AggregateTokenLimiter_setRateLimiterConfig:test_Owner_Success() (gas: 30393) +AggregateTokenLimiter_setRateLimiterConfig:test_TokenLimitAdmin_Success() (gas: 32407) +BurnFromMintTokenPool_lockOrBurn:test_ChainNotAllowed_Revert() (gas: 28842) +BurnFromMintTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 55271) +BurnFromMintTokenPool_lockOrBurn:test_PoolBurn_Success() (gas: 244024) +BurnFromMintTokenPool_lockOrBurn:test_Setup_Success() (gas: 24166) +BurnMintTokenPool_lockOrBurn:test_ChainNotAllowed_Revert() (gas: 27609) +BurnMintTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 55271) +BurnMintTokenPool_lockOrBurn:test_PoolBurn_Success() (gas: 241912) +BurnMintTokenPool_lockOrBurn:test_Setup_Success() (gas: 17851) +BurnMintTokenPool_releaseOrMint:test_ChainNotAllowed_Revert() (gas: 28805) +BurnMintTokenPool_releaseOrMint:test_PoolMintNotHealthy_Revert() (gas: 56253) +BurnMintTokenPool_releaseOrMint:test_PoolMint_Success() (gas: 112391) +BurnWithFromMintTokenPool_lockOrBurn:test_ChainNotAllowed_Revert() (gas: 28842) +BurnWithFromMintTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 55271) +BurnWithFromMintTokenPool_lockOrBurn:test_PoolBurn_Success() (gas: 244050) +BurnWithFromMintTokenPool_lockOrBurn:test_Setup_Success() (gas: 24170) +CCIPClientExample_sanity:test_ImmutableExamples_Success() (gas: 2052437) +CCIPConfigSetup:test_getCapabilityConfiguration_Success() (gas: 9551) +CCIPConfig_ConfigStateMachine:test__computeConfigDigest_Success() (gas: 67698) +CCIPConfig_ConfigStateMachine:test__computeNewConfigWithMeta_InitToRunning_Success() (gas: 361455) +CCIPConfig_ConfigStateMachine:test__computeNewConfigWithMeta_RunningToStaging_Success() (gas: 482385) +CCIPConfig_ConfigStateMachine:test__computeNewConfigWithMeta_StagingToRunning_Success() (gas: 448598) +CCIPConfig_ConfigStateMachine:test__groupByPluginType_TooManyOCR3Configs_Reverts() (gas: 35102) +CCIPConfig_ConfigStateMachine:test__groupByPluginType_threeCommitConfigs_Reverts() (gas: 58762) +CCIPConfig_ConfigStateMachine:test__groupByPluginType_threeExecutionConfigs_Reverts() (gas: 58700) +CCIPConfig_ConfigStateMachine:test__stateFromConfigLength_Success() (gas: 11737) CCIPConfig_ConfigStateMachine:test__validateConfigStateTransition_Success() (gas: 8849) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_InitToRunning_Success() (gas: 310010) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_InitToRunning_WrongConfigCount_Reverts() (gas: 46015) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_NonExistentConfigTransition_Reverts() (gas: 29840) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_RunningToStaging_Success() (gas: 370477) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_RunningToStaging_WrongConfigCount_Reverts() (gas: 111736) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_RunningToStaging_WrongConfigDigestBlueGreen_Reverts() (gas: 145866) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_StagingToRunning_Success() (gas: 370253) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_StagingToRunning_WrongConfigDigest_Reverts() (gas: 145933) -CCIPConfig_ConfigStateMachine:test_getCapabilityConfiguration_Success() (gas: 9663) -CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_CommitAndExecConfig_Success() (gas: 1790958) -CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_CommitConfigOnly_Success() (gas: 1038383) -CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_ExecConfigOnly_Success() (gas: 1038420) -CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_OnlyCapabilitiesRegistryCanCall_Reverts() (gas: 9611) -CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_ZeroLengthConfig_Success() (gas: 16008) -CCIPConfig_beforeCapabilityConfigSet:test_getCapabilityConfiguration_Success() (gas: 9627) -CCIPConfig_chainConfig:test__applyChainConfigUpdates_FChainNotPositive_Reverts() (gas: 184777) -CCIPConfig_chainConfig:test_applyChainConfigUpdates_addChainConfigs_Success() (gas: 346687) -CCIPConfig_chainConfig:test_applyChainConfigUpdates_nodeNotInRegistry_Reverts() (gas: 20346) -CCIPConfig_chainConfig:test_applyChainConfigUpdates_removeChainConfigs_Success() (gas: 270334) -CCIPConfig_chainConfig:test_applyChainConfigUpdates_selectorNotFound_Reverts() (gas: 14825) -CCIPConfig_chainConfig:test_getCapabilityConfiguration_Success() (gas: 9648) -CCIPConfig_chainConfig:test_getPaginatedCCIPConfigs_Success() (gas: 370299) -CCIPConfig_constructor:test_constructor_Success() (gas: 3333086) -CCIPConfig_constructor:test_constructor_ZeroAddressNotAllowed_Revert() (gas: 61438) -CCIPConfig_updatePluginConfig:test__updatePluginConfig_InvalidConfigLength_Reverts() (gas: 25819) -CCIPConfig_updatePluginConfig:test__updatePluginConfig_InvalidConfigStateTransition_Reverts() (gas: 21919) -CCIPConfig_updatePluginConfig:test_getCapabilityConfiguration_Success() (gas: 9649) -CCIPConfig_updatePluginConfig:test_updatePluginConfig_InitToRunning_Success() (gas: 1087725) -CCIPConfig_updatePluginConfig:test_updatePluginConfig_RunningToStaging_Success() (gas: 2032324) -CCIPConfig_updatePluginConfig:test_updatePluginConfig_StagingToRunning_Success() (gas: 2032358) -CCIPConfig_validateConfig:test__validateConfig_ABIEncodedAddress_OfframpAddressCannotBeZero_Reverts() (gas: 290870) -CCIPConfig_validateConfig:test__validateConfig_ChainSelectorNotFound_Reverts() (gas: 293601) -CCIPConfig_validateConfig:test__validateConfig_ChainSelectorNotSet_Reverts() (gas: 290497) -CCIPConfig_validateConfig:test__validateConfig_FMustBePositive_Reverts() (gas: 291704) -CCIPConfig_validateConfig:test__validateConfig_FTooHigh_Reverts() (gas: 291802) -CCIPConfig_validateConfig:test__validateConfig_NodeNotInRegistry_Reverts() (gas: 345019) -CCIPConfig_validateConfig:test__validateConfig_NotEnoughTransmitters_Reverts() (gas: 1209247) -CCIPConfig_validateConfig:test__validateConfig_OfframpAddressCannotBeZero_Reverts() (gas: 290586) -CCIPConfig_validateConfig:test__validateConfig_P2PIdsLengthNotMatching_Reverts() (gas: 292495) -CCIPConfig_validateConfig:test__validateConfig_Success() (gas: 299668) -CCIPConfig_validateConfig:test__validateConfig_TooManySigners_Reverts() (gas: 493120) -CCIPConfig_validateConfig:test_getCapabilityConfiguration_Success() (gas: 9606) -CommitStore_constructor:test_Constructor_Success() (gas: 2973887) -CommitStore_isUnpausedAndRMNHealthy:test_RMN_Success() (gas: 73567) -CommitStore_report:test_InvalidIntervalMinLargerThanMax_Revert() (gas: 28688) -CommitStore_report:test_InvalidInterval_Revert() (gas: 28628) -CommitStore_report:test_InvalidRootRevert() (gas: 27861) -CommitStore_report:test_OnlyGasPriceUpdates_Success() (gas: 53302) -CommitStore_report:test_OnlyPriceUpdateStaleReport_Revert() (gas: 59122) -CommitStore_report:test_OnlyTokenPriceUpdates_Success() (gas: 53300) -CommitStore_report:test_Paused_Revert() (gas: 21280) -CommitStore_report:test_ReportAndPriceUpdate_Success() (gas: 84288) -CommitStore_report:test_ReportOnlyRootSuccess_gas() (gas: 56270) -CommitStore_report:test_RootAlreadyCommitted_Revert() (gas: 64008) -CommitStore_report:test_StaleReportWithRoot_Success() (gas: 117012) -CommitStore_report:test_Unhealthy_Revert() (gas: 44766) -CommitStore_report:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 98603) -CommitStore_report:test_ZeroEpochAndRound_Revert() (gas: 27650) -CommitStore_resetUnblessedRoots:test_OnlyOwner_Revert() (gas: 11337) -CommitStore_resetUnblessedRoots:test_ResetUnblessedRoots_Success() (gas: 143871) -CommitStore_setDynamicConfig:test_InvalidCommitStoreConfig_Revert() (gas: 37263) -CommitStore_setDynamicConfig:test_OnlyOwner_Revert() (gas: 37405) -CommitStore_setDynamicConfig:test_PriceEpochCleared_Success() (gas: 129131) -CommitStore_setLatestPriceEpochAndRound:test_OnlyOwner_Revert() (gas: 11060) -CommitStore_setLatestPriceEpochAndRound:test_SetLatestPriceEpochAndRound_Success() (gas: 20651) -CommitStore_setMinSeqNr:test_OnlyOwner_Revert() (gas: 11059) -CommitStore_verify:test_Blessed_Success() (gas: 96485) -CommitStore_verify:test_NotBlessed_Success() (gas: 61422) -CommitStore_verify:test_Paused_Revert() (gas: 18529) -CommitStore_verify:test_TooManyLeaves_Revert() (gas: 36809) -DefensiveExampleTest:test_HappyPath_Success() (gas: 200052) -DefensiveExampleTest:test_Recovery() (gas: 424299) -E2E:test_E2E_3MessagesSuccess_gas() (gas: 1097175) -EVM2EVMOffRamp__releaseOrMintToken:test__releaseOrMintToken_NotACompatiblePool_Revert() (gas: 37854) -EVM2EVMOffRamp__releaseOrMintToken:test__releaseOrMintToken_Success() (gas: 104060) -EVM2EVMOffRamp__releaseOrMintToken:test__releaseOrMintToken_TokenHandlingError_transfer_Revert() (gas: 85597) -EVM2EVMOffRamp__releaseOrMintToken:test_releaseOrMintToken_InvalidDataLength_Revert() (gas: 37068) -EVM2EVMOffRamp__releaseOrMintToken:test_releaseOrMintToken_ReleaseOrMintBalanceMismatch_Revert() (gas: 94629) -EVM2EVMOffRamp__releaseOrMintToken:test_releaseOrMintToken_TokenHandlingError_BalanceOf_Revert() (gas: 40050) -EVM2EVMOffRamp__releaseOrMintToken:test_releaseOrMintToken_skip_ReleaseOrMintBalanceMismatch_if_pool_Revert() (gas: 86871) -EVM2EVMOffRamp__releaseOrMintTokens:test_OverValueWithARLOff_Success() (gas: 379687) -EVM2EVMOffRamp__releaseOrMintTokens:test_PriceNotFoundForToken_Reverts() (gas: 140056) -EVM2EVMOffRamp__releaseOrMintTokens:test_RateLimitErrors_Reverts() (gas: 794492) -EVM2EVMOffRamp__releaseOrMintTokens:test_TokenHandlingError_Reverts() (gas: 177527) -EVM2EVMOffRamp__releaseOrMintTokens:test__releaseOrMintTokens_NotACompatiblePool_Reverts() (gas: 29249) -EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_InvalidDataLengthReturnData_Revert() (gas: 66741) -EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_InvalidEVMAddress_Revert() (gas: 43332) -EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_Success() (gas: 207138) -EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals_Success() (gas: 218390) -EVM2EVMOffRamp__report:test_Report_Success() (gas: 126727) -EVM2EVMOffRamp__trialExecute:test_RateLimitError_Success() (gas: 236077) -EVM2EVMOffRamp__trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 244677) -EVM2EVMOffRamp__trialExecute:test_TokenPoolIsNotAContract_Success() (gas: 326076) -EVM2EVMOffRamp__trialExecute:test_trialExecute_Success() (gas: 308501) -EVM2EVMOffRamp_ccipReceive:test_Reverts() (gas: 17033) -EVM2EVMOffRamp_constructor:test_CommitStoreAlreadyInUse_Revert() (gas: 153451) -EVM2EVMOffRamp_constructor:test_Constructor_Success() (gas: 5479225) -EVM2EVMOffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 144185) -EVM2EVMOffRamp_execute:test_EmptyReport_Revert() (gas: 21354) -EVM2EVMOffRamp_execute:test_InvalidMessageId_Revert() (gas: 36591) -EVM2EVMOffRamp_execute:test_InvalidSourceChain_Revert() (gas: 51808) -EVM2EVMOffRamp_execute:test_InvalidSourcePoolAddress_Success() (gas: 470171) -EVM2EVMOffRamp_execute:test_ManualExecutionNotYetEnabled_Revert() (gas: 47902) -EVM2EVMOffRamp_execute:test_MessageTooLarge_Revert() (gas: 152518) -EVM2EVMOffRamp_execute:test_Paused_Revert() (gas: 103079) -EVM2EVMOffRamp_execute:test_ReceiverError_Success() (gas: 164230) -EVM2EVMOffRamp_execute:test_RetryFailedMessageWithoutManualExecution_Success() (gas: 178625) -EVM2EVMOffRamp_execute:test_RootNotCommitted_Revert() (gas: 42773) -EVM2EVMOffRamp_execute:test_SingleMessageNoTokensUnordered_Success() (gas: 158079) -EVM2EVMOffRamp_execute:test_SingleMessageNoTokens_Success() (gas: 173331) -EVM2EVMOffRamp_execute:test_SingleMessageToNonCCIPReceiver_Success() (gas: 237073) -EVM2EVMOffRamp_execute:test_SingleMessagesNoTokensSuccess_gas() (gas: 113995) -EVM2EVMOffRamp_execute:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 404062) -EVM2EVMOffRamp_execute:test_SkippedIncorrectNonce_Success() (gas: 54294) -EVM2EVMOffRamp_execute:test_StrictUntouchedToSuccess_Success() (gas: 131440) -EVM2EVMOffRamp_execute:test_TokenDataMismatch_Revert() (gas: 52249) -EVM2EVMOffRamp_execute:test_TwoMessagesWithTokensAndGE_Success() (gas: 560385) -EVM2EVMOffRamp_execute:test_TwoMessagesWithTokensSuccess_gas() (gas: 490768) -EVM2EVMOffRamp_execute:test_UnexpectedTokenData_Revert() (gas: 35530) -EVM2EVMOffRamp_execute:test_Unhealthy_Revert() (gas: 541563) -EVM2EVMOffRamp_execute:test_UnsupportedNumberOfTokens_Revert() (gas: 64497) -EVM2EVMOffRamp_execute:test__execute_SkippedAlreadyExecutedMessageUnordered_Success() (gas: 122733) -EVM2EVMOffRamp_execute:test__execute_SkippedAlreadyExecutedMessage_Success() (gas: 142907) -EVM2EVMOffRamp_execute:test_execute_RouterYULCall_Success() (gas: 427595) -EVM2EVMOffRamp_executeSingleMessage:test_MessageSender_Revert() (gas: 18502) -EVM2EVMOffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 274264) -EVM2EVMOffRamp_executeSingleMessage:test_NonContract_Success() (gas: 18668) -EVM2EVMOffRamp_executeSingleMessage:test_TokenHandlingError_Revert() (gas: 222198) -EVM2EVMOffRamp_executeSingleMessage:test_ZeroGasDONExecution_Revert() (gas: 47950) -EVM2EVMOffRamp_executeSingleMessage:test_executeSingleMessage_NoTokens_Success() (gas: 47427) -EVM2EVMOffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens_Success() (gas: 310150) -EVM2EVMOffRamp_executeSingleMessage:test_executeSingleMessage_ZeroGasZeroData_Success() (gas: 70101) -EVM2EVMOffRamp_execute_upgrade:test_V2NonceNewSenderStartsAtZero_Success() (gas: 229526) -EVM2EVMOffRamp_execute_upgrade:test_V2NonceStartsAtV1Nonce_Success() (gas: 277072) -EVM2EVMOffRamp_execute_upgrade:test_V2OffRampNonceSkipsIfMsgInFlight_Success() (gas: 258912) -EVM2EVMOffRamp_execute_upgrade:test_V2SenderNoncesReadsPreviousRamp_Success() (gas: 226538) -EVM2EVMOffRamp_execute_upgrade:test_V2_Success() (gas: 130841) -EVM2EVMOffRamp_getAllRateLimitTokens:test_GetAllRateLimitTokens_Success() (gas: 38446) -EVM2EVMOffRamp_getExecutionState:test_FillExecutionState_Success() (gas: 3251974) -EVM2EVMOffRamp_getExecutionState:test_GetExecutionState_Success() (gas: 83387) -EVM2EVMOffRamp_manuallyExecute:test_ManualExecFailedTx_Revert() (gas: 186015) -EVM2EVMOffRamp_manuallyExecute:test_ManualExecForkedChain_Revert() (gas: 27052) -EVM2EVMOffRamp_manuallyExecute:test_ManualExecGasLimitMismatch_Revert() (gas: 45200) -EVM2EVMOffRamp_manuallyExecute:test_ManualExecInvalidGasLimit_Revert() (gas: 27471) -EVM2EVMOffRamp_manuallyExecute:test_ManualExecWithMultipleMessagesAndSourceTokens_Success() (gas: 526641) -EVM2EVMOffRamp_manuallyExecute:test_ManualExecWithSourceTokens_Success() (gas: 342009) -EVM2EVMOffRamp_manuallyExecute:test_ManualExec_Success() (gas: 187507) -EVM2EVMOffRamp_manuallyExecute:test_ReentrancyManualExecuteFails_Success() (gas: 2256449) -EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_DestinationGasAmountCountMismatch_Revert() (gas: 359222) -EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_DoesNotRevertIfUntouched_Success() (gas: 143996) -EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_InvalidTokenGasOverride_Revert() (gas: 362361) -EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_LowGasLimitManualExec_Success() (gas: 482844) -EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_WithGasOverride_Success() (gas: 189910) -EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_WithInvalidReceiverExecutionGasOverride_Revert() (gas: 153740) -EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_WithInvalidSourceTokenDataCount_Revert() (gas: 59897) -EVM2EVMOffRamp_metadataHash:test_MetadataHash_Success() (gas: 8865) -EVM2EVMOffRamp_setDynamicConfig:test_NonOwner_Revert() (gas: 40168) -EVM2EVMOffRamp_setDynamicConfig:test_RouterZeroAddress_Revert() (gas: 38239) -EVM2EVMOffRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 141938) -EVM2EVMOffRamp_updateRateLimitTokens:test_updateRateLimitTokens_AddsAndRemoves_Success() (gas: 162532) -EVM2EVMOffRamp_updateRateLimitTokens:test_updateRateLimitTokens_NonOwner_Revert() (gas: 16711) -EVM2EVMOffRamp_updateRateLimitTokens:test_updateRateLimitTokens_Success() (gas: 197728) -EVM2EVMOnRamp_constructor:test_Constructor_Success() (gas: 5322415) -EVM2EVMOnRamp_forwardFromRouter:test_CannotSendZeroTokens_Revert() (gas: 35880) -EVM2EVMOnRamp_forwardFromRouter:test_EnforceOutOfOrder_Revert() (gas: 98614) -EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() (gas: 114321) -EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2_Success() (gas: 114363) -EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterSuccessCustomExtraArgs() (gas: 130351) -EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterSuccessLegacyExtraArgs() (gas: 138791) -EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouter_Success() (gas: 129970) -EVM2EVMOnRamp_forwardFromRouter:test_InvalidAddressEncodePacked_Revert() (gas: 38431) -EVM2EVMOnRamp_forwardFromRouter:test_InvalidAddress_Revert() (gas: 38614) -EVM2EVMOnRamp_forwardFromRouter:test_InvalidChainSelector_Revert() (gas: 25540) -EVM2EVMOnRamp_forwardFromRouter:test_InvalidExtraArgsTag_Revert() (gas: 25365) -EVM2EVMOnRamp_forwardFromRouter:test_MaxCapacityExceeded_Revert() (gas: 84002) -EVM2EVMOnRamp_forwardFromRouter:test_MaxFeeBalanceReached_Revert() (gas: 36619) -EVM2EVMOnRamp_forwardFromRouter:test_MessageGasLimitTooHigh_Revert() (gas: 29123) -EVM2EVMOnRamp_forwardFromRouter:test_MessageTooLarge_Revert() (gas: 107667) -EVM2EVMOnRamp_forwardFromRouter:test_OriginalSender_Revert() (gas: 22724) -EVM2EVMOnRamp_forwardFromRouter:test_OverValueWithARLOff_Success() (gas: 225474) -EVM2EVMOnRamp_forwardFromRouter:test_Paused_Revert() (gas: 53180) -EVM2EVMOnRamp_forwardFromRouter:test_Permissions_Revert() (gas: 25565) -EVM2EVMOnRamp_forwardFromRouter:test_PriceNotFoundForToken_Revert() (gas: 57336) -EVM2EVMOnRamp_forwardFromRouter:test_ShouldIncrementNonceOnlyOnOrdered_Success() (gas: 179712) -EVM2EVMOnRamp_forwardFromRouter:test_ShouldIncrementSeqNumAndNonce_Success() (gas: 178039) -EVM2EVMOnRamp_forwardFromRouter:test_ShouldStoreNonLinkFees() (gas: 132717) -EVM2EVMOnRamp_forwardFromRouter:test_SourceTokenDataTooLarge_Revert() (gas: 3713189) -EVM2EVMOnRamp_forwardFromRouter:test_TooManyTokens_Revert() (gas: 30289) -EVM2EVMOnRamp_forwardFromRouter:test_Unhealthy_Revert() (gas: 43342) -EVM2EVMOnRamp_forwardFromRouter:test_UnsupportedToken_Revert() (gas: 109557) -EVM2EVMOnRamp_forwardFromRouter:test_ZeroAddressReceiver_Revert() (gas: 314265) -EVM2EVMOnRamp_forwardFromRouter:test_forwardFromRouter_ShouldStoreLinkFees_Success() (gas: 112547) -EVM2EVMOnRamp_forwardFromRouter:test_forwardFromRouter_UnsupportedToken_Revert() (gas: 72386) -EVM2EVMOnRamp_forwardFromRouter:test_forwardFromRouter_correctSourceTokenData_Success() (gas: 711856) -EVM2EVMOnRamp_forwardFromRouter_upgrade:test_V2NonceNewSenderStartsAtZero_Success() (gas: 147925) -EVM2EVMOnRamp_forwardFromRouter_upgrade:test_V2NonceStartsAtV1Nonce_Success() (gas: 190949) -EVM2EVMOnRamp_forwardFromRouter_upgrade:test_V2SenderNoncesReadsPreviousRamp_Success() (gas: 121743) -EVM2EVMOnRamp_forwardFromRouter_upgrade:test_V2_Success() (gas: 95487) -EVM2EVMOnRamp_getDataAvailabilityCost:test_EmptyMessageCalculatesDataAvailabilityCost_Success() (gas: 20568) -EVM2EVMOnRamp_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCost_Success() (gas: 20936) -EVM2EVMOnRamp_getFee:test_EmptyMessage_Success() (gas: 74147) -EVM2EVMOnRamp_getFee:test_GetFeeOfZeroForTokenMessage_Success() (gas: 79673) -EVM2EVMOnRamp_getFee:test_HighGasMessage_Success() (gas: 229995) -EVM2EVMOnRamp_getFee:test_MessageGasLimitTooHigh_Revert() (gas: 16778) -EVM2EVMOnRamp_getFee:test_MessageTooLarge_Revert() (gas: 95328) -EVM2EVMOnRamp_getFee:test_MessageWithDataAndTokenTransfer_Success() (gas: 152747) -EVM2EVMOnRamp_getFee:test_NotAFeeToken_Revert() (gas: 24158) -EVM2EVMOnRamp_getFee:test_SingleTokenMessage_Success() (gas: 113717) -EVM2EVMOnRamp_getFee:test_TooManyTokens_Revert() (gas: 19959) -EVM2EVMOnRamp_getFee:test_ZeroDataAvailabilityMultiplier_Success() (gas: 62629) -EVM2EVMOnRamp_getSupportedTokens:test_GetSupportedTokens_Revert() (gas: 10460) -EVM2EVMOnRamp_getTokenPool:test_GetTokenPool_Success() (gas: 35195) -EVM2EVMOnRamp_getTokenTransferCost:test_CustomTokenBpsFee_Success() (gas: 43011) -EVM2EVMOnRamp_getTokenTransferCost:test_FeeTokenBpsFee_Success() (gas: 33079) -EVM2EVMOnRamp_getTokenTransferCost:test_LargeTokenTransferChargesMaxFeeAndGas_Success() (gas: 28356) -EVM2EVMOnRamp_getTokenTransferCost:test_MixedTokenTransferFee_Success() (gas: 121817) -EVM2EVMOnRamp_getTokenTransferCost:test_NoTokenTransferChargesZeroFee_Success() (gas: 15250) -EVM2EVMOnRamp_getTokenTransferCost:test_SmallTokenTransferChargesMinFeeAndGas_Success() (gas: 28164) -EVM2EVMOnRamp_getTokenTransferCost:test_UnsupportedToken_Revert() (gas: 21266) -EVM2EVMOnRamp_getTokenTransferCost:test_ZeroAmountTokenTransferChargesMinFeeAndGas_Success() (gas: 28187) -EVM2EVMOnRamp_getTokenTransferCost:test_ZeroFeeConfigChargesMinFee_Success() (gas: 38638) -EVM2EVMOnRamp_getTokenTransferCost:test__getTokenTransferCost_selfServeUsesDefaults_Success() (gas: 29440) -EVM2EVMOnRamp_linkAvailableForPayment:test_InsufficientLinkBalance_Success() (gas: 32651) -EVM2EVMOnRamp_linkAvailableForPayment:test_LinkAvailableForPayment_Success() (gas: 135118) -EVM2EVMOnRamp_payNops:test_AdminPayNops_Success() (gas: 143408) -EVM2EVMOnRamp_payNops:test_InsufficientBalance_Revert() (gas: 29085) -EVM2EVMOnRamp_payNops:test_NoFeesToPay_Revert() (gas: 127622) -EVM2EVMOnRamp_payNops:test_NoNopsToPay_Revert() (gas: 133481) -EVM2EVMOnRamp_payNops:test_NopPayNops_Success() (gas: 146695) -EVM2EVMOnRamp_payNops:test_OwnerPayNops_Success() (gas: 141270) -EVM2EVMOnRamp_payNops:test_PayNopsSuccessAfterSetNops() (gas: 298116) -EVM2EVMOnRamp_payNops:test_WrongPermissions_Revert() (gas: 15300) -EVM2EVMOnRamp_setDynamicConfig:test_SetConfigInvalidConfig_Revert() (gas: 42401) -EVM2EVMOnRamp_setDynamicConfig:test_SetConfigOnlyOwner_Revert() (gas: 21270) -EVM2EVMOnRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 53830) -EVM2EVMOnRamp_setFeeTokenConfig:test_OnlyCallableByOwnerOrAdmin_Revert() (gas: 13476) -EVM2EVMOnRamp_setFeeTokenConfig:test_SetFeeTokenConfigByAdmin_Success() (gas: 16461) -EVM2EVMOnRamp_setFeeTokenConfig:test_SetFeeTokenConfig_Success() (gas: 14000) -EVM2EVMOnRamp_setNops:test_AdminCanSetNops_Success() (gas: 61795) -EVM2EVMOnRamp_setNops:test_IncludesPayment_Success() (gas: 469668) -EVM2EVMOnRamp_setNops:test_LinkTokenCannotBeNop_Revert() (gas: 57291) -EVM2EVMOnRamp_setNops:test_NonOwnerOrAdmin_Revert() (gas: 14677) -EVM2EVMOnRamp_setNops:test_NotEnoughFundsForPayout_Revert() (gas: 84675) -EVM2EVMOnRamp_setNops:test_SetNopsRemovesOldNopsCompletely_Success() (gas: 60683) -EVM2EVMOnRamp_setNops:test_SetNops_Success() (gas: 173833) -EVM2EVMOnRamp_setNops:test_TooManyNops_Revert() (gas: 190350) -EVM2EVMOnRamp_setNops:test_ZeroAddressCannotBeNop_Revert() (gas: 53632) -EVM2EVMOnRamp_setTokenTransferFeeConfig:test__setTokenTransferFeeConfig_InvalidDestBytesOverhead_Revert() (gas: 14499) -EVM2EVMOnRamp_setTokenTransferFeeConfig:test__setTokenTransferFeeConfig_OnlyCallableByOwnerOrAdmin_Revert() (gas: 14283) -EVM2EVMOnRamp_setTokenTransferFeeConfig:test__setTokenTransferFeeConfig_Success() (gas: 84107) -EVM2EVMOnRamp_setTokenTransferFeeConfig:test__setTokenTransferFeeConfig_byAdmin_Success() (gas: 17375) -EVM2EVMOnRamp_withdrawNonLinkFees:test_LinkBalanceNotSettled_Revert() (gas: 83158) -EVM2EVMOnRamp_withdrawNonLinkFees:test_NonOwnerOrAdmin_Revert() (gas: 15275) -EVM2EVMOnRamp_withdrawNonLinkFees:test_SettlingBalance_Success() (gas: 272200) -EVM2EVMOnRamp_withdrawNonLinkFees:test_WithdrawNonLinkFees_Success() (gas: 53482) -EVM2EVMOnRamp_withdrawNonLinkFees:test_WithdrawToZeroAddress_Revert() (gas: 12830) -EtherSenderReceiverTest_ccipReceive:test_ccipReceive_fallbackToWethTransfer() (gas: 96892) -EtherSenderReceiverTest_ccipReceive:test_ccipReceive_happyPath() (gas: 49770) -EtherSenderReceiverTest_ccipReceive:test_ccipReceive_wrongToken() (gas: 17423) -EtherSenderReceiverTest_ccipReceive:test_ccipReceive_wrongTokenAmount() (gas: 15722) -EtherSenderReceiverTest_ccipSend:test_ccipSend_reverts_insufficientFee_feeToken() (gas: 99837) -EtherSenderReceiverTest_ccipSend:test_ccipSend_reverts_insufficientFee_native() (gas: 76105) -EtherSenderReceiverTest_ccipSend:test_ccipSend_reverts_insufficientFee_weth() (gas: 99859) -EtherSenderReceiverTest_ccipSend:test_ccipSend_success_feeToken() (gas: 144845) -EtherSenderReceiverTest_ccipSend:test_ccipSend_success_native() (gas: 80268) -EtherSenderReceiverTest_ccipSend:test_ccipSend_success_nativeExcess() (gas: 80455) -EtherSenderReceiverTest_ccipSend:test_ccipSend_success_weth() (gas: 95914) -EtherSenderReceiverTest_constructor:test_constructor() (gas: 17535) -EtherSenderReceiverTest_getFee:test_getFee() (gas: 27328) -EtherSenderReceiverTest_validateFeeToken:test_validateFeeToken_reverts_feeToken_tokenAmountNotEqualToMsgValue() (gas: 20363) -EtherSenderReceiverTest_validateFeeToken:test_validateFeeToken_valid_feeToken() (gas: 16718) +CCIPConfig_ConfigStateMachine:test__validateConfigTransition_InitToRunning_Success() (gas: 311552) +CCIPConfig_ConfigStateMachine:test__validateConfigTransition_InitToRunning_WrongConfigCount_Reverts() (gas: 47113) +CCIPConfig_ConfigStateMachine:test__validateConfigTransition_NonExistentConfigTransition_Reverts() (gas: 30728) +CCIPConfig_ConfigStateMachine:test__validateConfigTransition_RunningToStaging_Success() (gas: 374071) +CCIPConfig_ConfigStateMachine:test__validateConfigTransition_RunningToStaging_WrongConfigCount_Reverts() (gas: 114898) +CCIPConfig_ConfigStateMachine:test__validateConfigTransition_RunningToStaging_WrongConfigDigestBlueGreen_Reverts() (gas: 150024) +CCIPConfig_ConfigStateMachine:test__validateConfigTransition_StagingToRunning_Success() (gas: 373811) +CCIPConfig_ConfigStateMachine:test__validateConfigTransition_StagingToRunning_WrongConfigDigest_Reverts() (gas: 150091) +CCIPConfig_ConfigStateMachine:test_getCapabilityConfiguration_Success() (gas: 9675) +CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_CommitAndExecConfig_Success() (gas: 1793946) +CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_CommitConfigOnly_Success() (gas: 1040198) +CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_ExecConfigOnly_Success() (gas: 1040229) +CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_OnlyCapabilitiesRegistryCanCall_Reverts() (gas: 9665) +CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_ZeroLengthConfig_Success() (gas: 16188) +CCIPConfig_beforeCapabilityConfigSet:test_getCapabilityConfiguration_Success() (gas: 9639) +CCIPConfig_chainConfig:test__applyChainConfigUpdates_FChainNotPositive_Reverts() (gas: 185224) +CCIPConfig_chainConfig:test_applyChainConfigUpdates_addChainConfigs_Success() (gas: 347338) +CCIPConfig_chainConfig:test_applyChainConfigUpdates_nodeNotInRegistry_Reverts() (gas: 20613) +CCIPConfig_chainConfig:test_applyChainConfigUpdates_removeChainConfigs_Success() (gas: 270910) +CCIPConfig_chainConfig:test_applyChainConfigUpdates_selectorNotFound_Reverts() (gas: 14921) +CCIPConfig_chainConfig:test_getCapabilityConfiguration_Success() (gas: 9660) +CCIPConfig_chainConfig:test_getPaginatedCCIPConfigs_Success() (gas: 371100) +CCIPConfig_constructor:test_constructor_Success() (gas: 3191349) +CCIPConfig_constructor:test_constructor_ZeroAddressNotAllowed_Revert() (gas: 61266) +CCIPConfig_updatePluginConfig:test__updatePluginConfig_InvalidConfigLength_Reverts() (gas: 26551) +CCIPConfig_updatePluginConfig:test__updatePluginConfig_InvalidConfigStateTransition_Reverts() (gas: 22417) +CCIPConfig_updatePluginConfig:test_getCapabilityConfiguration_Success() (gas: 9697) +CCIPConfig_updatePluginConfig:test_updatePluginConfig_InitToRunning_Success() (gas: 1090890) +CCIPConfig_updatePluginConfig:test_updatePluginConfig_RunningToStaging_Success() (gas: 2037835) +CCIPConfig_updatePluginConfig:test_updatePluginConfig_StagingToRunning_Success() (gas: 2037868) +CCIPConfig_validateConfig:test__validateConfig_ABIEncodedAddress_OfframpAddressCannotBeZero_Reverts() (gas: 291812) +CCIPConfig_validateConfig:test__validateConfig_ChainSelectorNotFound_Reverts() (gas: 294567) +CCIPConfig_validateConfig:test__validateConfig_ChainSelectorNotSet_Reverts() (gas: 291445) +CCIPConfig_validateConfig:test__validateConfig_FMustBePositive_Reverts() (gas: 292676) +CCIPConfig_validateConfig:test__validateConfig_FTooHigh_Reverts() (gas: 292774) +CCIPConfig_validateConfig:test__validateConfig_NodeNotInRegistry_Reverts() (gas: 346525) +CCIPConfig_validateConfig:test__validateConfig_NotEnoughTransmitters_Reverts() (gas: 1213555) +CCIPConfig_validateConfig:test__validateConfig_OfframpAddressCannotBeZero_Reverts() (gas: 291528) +CCIPConfig_validateConfig:test__validateConfig_P2PIdsLengthNotMatching_Reverts() (gas: 293467) +CCIPConfig_validateConfig:test__validateConfig_Success() (gas: 300916) +CCIPConfig_validateConfig:test__validateConfig_TooManySigners_Reverts() (gas: 503200) +CCIPConfig_validateConfig:test_getCapabilityConfiguration_Success() (gas: 9618) +CommitStore_constructor:test_Constructor_Success() (gas: 2855567) +CommitStore_isUnpausedAndRMNHealthy:test_RMN_Success() (gas: 73954) +CommitStore_report:test_InvalidIntervalMinLargerThanMax_Revert() (gas: 28739) +CommitStore_report:test_InvalidInterval_Revert() (gas: 28679) +CommitStore_report:test_InvalidRootRevert() (gas: 27912) +CommitStore_report:test_OnlyGasPriceUpdates_Success() (gas: 53448) +CommitStore_report:test_OnlyPriceUpdateStaleReport_Revert() (gas: 59286) +CommitStore_report:test_OnlyTokenPriceUpdates_Success() (gas: 53446) +CommitStore_report:test_Paused_Revert() (gas: 21319) +CommitStore_report:test_ReportAndPriceUpdate_Success() (gas: 84485) +CommitStore_report:test_ReportOnlyRootSuccess_gas() (gas: 56342) +CommitStore_report:test_RootAlreadyCommitted_Revert() (gas: 64077) +CommitStore_report:test_StaleReportWithRoot_Success() (gas: 117309) +CommitStore_report:test_Unhealthy_Revert() (gas: 44823) +CommitStore_report:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 98929) +CommitStore_report:test_ZeroEpochAndRound_Revert() (gas: 27707) +CommitStore_resetUnblessedRoots:test_OnlyOwner_Revert() (gas: 11376) +CommitStore_resetUnblessedRoots:test_ResetUnblessedRoots_Success() (gas: 144186) +CommitStore_setDynamicConfig:test_InvalidCommitStoreConfig_Revert() (gas: 37314) +CommitStore_setDynamicConfig:test_OnlyOwner_Revert() (gas: 37483) +CommitStore_setDynamicConfig:test_PriceEpochCleared_Success() (gas: 129329) +CommitStore_setLatestPriceEpochAndRound:test_OnlyOwner_Revert() (gas: 11099) +CommitStore_setLatestPriceEpochAndRound:test_SetLatestPriceEpochAndRound_Success() (gas: 20690) +CommitStore_setMinSeqNr:test_OnlyOwner_Revert() (gas: 11098) +CommitStore_verify:test_Blessed_Success() (gas: 96581) +CommitStore_verify:test_NotBlessed_Success() (gas: 61473) +CommitStore_verify:test_Paused_Revert() (gas: 18568) +CommitStore_verify:test_TooManyLeaves_Revert() (gas: 36848) +DefensiveExampleTest:test_HappyPath_Success() (gas: 200200) +DefensiveExampleTest:test_Recovery() (gas: 424479) +E2E:test_E2E_3MessagesSuccess_gas() (gas: 1106985) +EVM2EVMOffRamp__releaseOrMintToken:test__releaseOrMintToken_NotACompatiblePool_Revert() (gas: 38313) +EVM2EVMOffRamp__releaseOrMintToken:test__releaseOrMintToken_Success() (gas: 104441) +EVM2EVMOffRamp__releaseOrMintToken:test__releaseOrMintToken_TokenHandlingError_transfer_Revert() (gas: 86029) +EVM2EVMOffRamp__releaseOrMintToken:test_releaseOrMintToken_InvalidDataLength_Revert() (gas: 37362) +EVM2EVMOffRamp__releaseOrMintToken:test_releaseOrMintToken_ReleaseOrMintBalanceMismatch_Revert() (gas: 95010) +EVM2EVMOffRamp__releaseOrMintToken:test_releaseOrMintToken_TokenHandlingError_BalanceOf_Revert() (gas: 40338) +EVM2EVMOffRamp__releaseOrMintToken:test_releaseOrMintToken_skip_ReleaseOrMintBalanceMismatch_if_pool_Revert() (gas: 87189) +EVM2EVMOffRamp__releaseOrMintTokens:test_OverValueWithARLOff_Success() (gas: 381594) +EVM2EVMOffRamp__releaseOrMintTokens:test_PriceNotFoundForToken_Reverts() (gas: 140568) +EVM2EVMOffRamp__releaseOrMintTokens:test_RateLimitErrors_Reverts() (gas: 798833) +EVM2EVMOffRamp__releaseOrMintTokens:test_TokenHandlingError_Reverts() (gas: 178400) +EVM2EVMOffRamp__releaseOrMintTokens:test__releaseOrMintTokens_NotACompatiblePool_Reverts() (gas: 29684) +EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_InvalidDataLengthReturnData_Revert() (gas: 67146) +EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_InvalidEVMAddress_Revert() (gas: 43605) +EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_Success() (gas: 208068) +EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals_Success() (gas: 219365) +EVM2EVMOffRamp__report:test_Report_Success() (gas: 127777) +EVM2EVMOffRamp__trialExecute:test_RateLimitError_Success() (gas: 237403) +EVM2EVMOffRamp__trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 246036) +EVM2EVMOffRamp__trialExecute:test_TokenPoolIsNotAContract_Success() (gas: 329283) +EVM2EVMOffRamp__trialExecute:test_trialExecute_Success() (gas: 310166) +EVM2EVMOffRamp_ccipReceive:test_Reverts() (gas: 17051) +EVM2EVMOffRamp_constructor:test_CommitStoreAlreadyInUse_Revert() (gas: 153120) +EVM2EVMOffRamp_constructor:test_Constructor_Success() (gas: 5212744) +EVM2EVMOffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 143845) +EVM2EVMOffRamp_execute:test_EmptyReport_Revert() (gas: 21504) +EVM2EVMOffRamp_execute:test_InvalidMessageId_Revert() (gas: 36933) +EVM2EVMOffRamp_execute:test_InvalidSourceChain_Revert() (gas: 52324) +EVM2EVMOffRamp_execute:test_InvalidSourcePoolAddress_Success() (gas: 473387) +EVM2EVMOffRamp_execute:test_ManualExecutionNotYetEnabled_Revert() (gas: 48346) +EVM2EVMOffRamp_execute:test_MessageTooLarge_Revert() (gas: 153016) +EVM2EVMOffRamp_execute:test_Paused_Revert() (gas: 103946) +EVM2EVMOffRamp_execute:test_ReceiverError_Success() (gas: 165364) +EVM2EVMOffRamp_execute:test_RetryFailedMessageWithoutManualExecution_Success() (gas: 180107) +EVM2EVMOffRamp_execute:test_RootNotCommitted_Revert() (gas: 43157) +EVM2EVMOffRamp_execute:test_SingleMessageNoTokensUnordered_Success() (gas: 160119) +EVM2EVMOffRamp_execute:test_SingleMessageNoTokens_Success() (gas: 175497) +EVM2EVMOffRamp_execute:test_SingleMessageToNonCCIPReceiver_Success() (gas: 237901) +EVM2EVMOffRamp_execute:test_SingleMessagesNoTokensSuccess_gas() (gas: 115045) +EVM2EVMOffRamp_execute:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 406606) +EVM2EVMOffRamp_execute:test_SkippedIncorrectNonce_Success() (gas: 54774) +EVM2EVMOffRamp_execute:test_StrictUntouchedToSuccess_Success() (gas: 132562) +EVM2EVMOffRamp_execute:test_TokenDataMismatch_Revert() (gas: 52783) +EVM2EVMOffRamp_execute:test_TwoMessagesWithTokensAndGE_Success() (gas: 564477) +EVM2EVMOffRamp_execute:test_TwoMessagesWithTokensSuccess_gas() (gas: 494716) +EVM2EVMOffRamp_execute:test_UnexpectedTokenData_Revert() (gas: 35884) +EVM2EVMOffRamp_execute:test_Unhealthy_Revert() (gas: 546333) +EVM2EVMOffRamp_execute:test_UnsupportedNumberOfTokens_Revert() (gas: 65295) +EVM2EVMOffRamp_execute:test__execute_SkippedAlreadyExecutedMessageUnordered_Success() (gas: 124107) +EVM2EVMOffRamp_execute:test__execute_SkippedAlreadyExecutedMessage_Success() (gas: 144365) +EVM2EVMOffRamp_execute:test_execute_RouterYULCall_Success() (gas: 394187) +EVM2EVMOffRamp_executeSingleMessage:test_MessageSender_Revert() (gas: 18685) +EVM2EVMOffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 275266) +EVM2EVMOffRamp_executeSingleMessage:test_NonContract_Success() (gas: 18824) +EVM2EVMOffRamp_executeSingleMessage:test_TokenHandlingError_Revert() (gas: 223179) +EVM2EVMOffRamp_executeSingleMessage:test_ZeroGasDONExecution_Revert() (gas: 48391) +EVM2EVMOffRamp_executeSingleMessage:test_executeSingleMessage_NoTokens_Success() (gas: 47823) +EVM2EVMOffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens_Success() (gas: 311554) +EVM2EVMOffRamp_executeSingleMessage:test_executeSingleMessage_ZeroGasZeroData_Success() (gas: 70839) +EVM2EVMOffRamp_execute_upgrade:test_V2NonceNewSenderStartsAtZero_Success() (gas: 232142) +EVM2EVMOffRamp_execute_upgrade:test_V2NonceStartsAtV1Nonce_Success() (gas: 281170) +EVM2EVMOffRamp_execute_upgrade:test_V2OffRampNonceSkipsIfMsgInFlight_Success() (gas: 262488) +EVM2EVMOffRamp_execute_upgrade:test_V2SenderNoncesReadsPreviousRamp_Success() (gas: 230645) +EVM2EVMOffRamp_execute_upgrade:test_V2_Success() (gas: 132092) +EVM2EVMOffRamp_getAllRateLimitTokens:test_GetAllRateLimitTokens_Success() (gas: 38626) +EVM2EVMOffRamp_getExecutionState:test_FillExecutionState_Success() (gas: 3402112) +EVM2EVMOffRamp_getExecutionState:test_GetExecutionState_Success() (gas: 84887) +EVM2EVMOffRamp_manuallyExecute:test_ManualExecFailedTx_Revert() (gas: 188280) +EVM2EVMOffRamp_manuallyExecute:test_ManualExecForkedChain_Revert() (gas: 27574) +EVM2EVMOffRamp_manuallyExecute:test_ManualExecGasLimitMismatch_Revert() (gas: 46457) +EVM2EVMOffRamp_manuallyExecute:test_ManualExecInvalidGasLimit_Revert() (gas: 27948) +EVM2EVMOffRamp_manuallyExecute:test_ManualExecWithMultipleMessagesAndSourceTokens_Success() (gas: 531330) +EVM2EVMOffRamp_manuallyExecute:test_ManualExecWithSourceTokens_Success() (gas: 344463) +EVM2EVMOffRamp_manuallyExecute:test_ManualExec_Success() (gas: 189760) +EVM2EVMOffRamp_manuallyExecute:test_ReentrancyManualExecuteFails_Success() (gas: 2195134) +EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_DestinationGasAmountCountMismatch_Revert() (gas: 362054) +EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_DoesNotRevertIfUntouched_Success() (gas: 145457) +EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_InvalidTokenGasOverride_Revert() (gas: 365283) +EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_LowGasLimitManualExec_Success() (gas: 450711) +EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_WithGasOverride_Success() (gas: 192223) +EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_WithInvalidReceiverExecutionGasOverride_Revert() (gas: 155387) +EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_WithInvalidSourceTokenDataCount_Revert() (gas: 60494) +EVM2EVMOffRamp_metadataHash:test_MetadataHash_Success() (gas: 8916) +EVM2EVMOffRamp_setDynamicConfig:test_NonOwner_Revert() (gas: 40360) +EVM2EVMOffRamp_setDynamicConfig:test_RouterZeroAddress_Revert() (gas: 38422) +EVM2EVMOffRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 142430) +EVM2EVMOffRamp_updateRateLimitTokens:test_updateRateLimitTokens_AddsAndRemoves_Success() (gas: 162820) +EVM2EVMOffRamp_updateRateLimitTokens:test_updateRateLimitTokens_NonOwner_Revert() (gas: 16939) +EVM2EVMOffRamp_updateRateLimitTokens:test_updateRateLimitTokens_Success() (gas: 197992) +EVM2EVMOnRamp_constructor:test_Constructor_Success() (gas: 5056686) +EVM2EVMOnRamp_forwardFromRouter:test_CannotSendZeroTokens_Revert() (gas: 36063) +EVM2EVMOnRamp_forwardFromRouter:test_EnforceOutOfOrder_Revert() (gas: 99028) +EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() (gas: 114931) +EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2_Success() (gas: 114973) +EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterSuccessCustomExtraArgs() (gas: 130997) +EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterSuccessLegacyExtraArgs() (gas: 139437) +EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouter_Success() (gas: 130616) +EVM2EVMOnRamp_forwardFromRouter:test_InvalidAddressEncodePacked_Revert() (gas: 38647) +EVM2EVMOnRamp_forwardFromRouter:test_InvalidAddress_Revert() (gas: 38830) +EVM2EVMOnRamp_forwardFromRouter:test_InvalidChainSelector_Revert() (gas: 25726) +EVM2EVMOnRamp_forwardFromRouter:test_InvalidExtraArgsTag_Revert() (gas: 25545) +EVM2EVMOnRamp_forwardFromRouter:test_MaxCapacityExceeded_Revert() (gas: 84266) +EVM2EVMOnRamp_forwardFromRouter:test_MaxFeeBalanceReached_Revert() (gas: 36847) +EVM2EVMOnRamp_forwardFromRouter:test_MessageGasLimitTooHigh_Revert() (gas: 29327) +EVM2EVMOnRamp_forwardFromRouter:test_MessageTooLarge_Revert() (gas: 107850) +EVM2EVMOnRamp_forwardFromRouter:test_OriginalSender_Revert() (gas: 22823) +EVM2EVMOnRamp_forwardFromRouter:test_OverValueWithARLOff_Success() (gas: 226568) +EVM2EVMOnRamp_forwardFromRouter:test_Paused_Revert() (gas: 53432) +EVM2EVMOnRamp_forwardFromRouter:test_Permissions_Revert() (gas: 25757) +EVM2EVMOnRamp_forwardFromRouter:test_PriceNotFoundForToken_Revert() (gas: 57722) +EVM2EVMOnRamp_forwardFromRouter:test_ShouldIncrementNonceOnlyOnOrdered_Success() (gas: 182247) +EVM2EVMOnRamp_forwardFromRouter:test_ShouldIncrementSeqNumAndNonce_Success() (gas: 180718) +EVM2EVMOnRamp_forwardFromRouter:test_ShouldStoreNonLinkFees() (gas: 133236) +EVM2EVMOnRamp_forwardFromRouter:test_SourceTokenDataTooLarge_Revert() (gas: 3573653) +EVM2EVMOnRamp_forwardFromRouter:test_TooManyTokens_Revert() (gas: 30472) +EVM2EVMOnRamp_forwardFromRouter:test_Unhealthy_Revert() (gas: 43480) +EVM2EVMOnRamp_forwardFromRouter:test_UnsupportedToken_Revert() (gas: 110111) +EVM2EVMOnRamp_forwardFromRouter:test_ZeroAddressReceiver_Revert() (gas: 316020) +EVM2EVMOnRamp_forwardFromRouter:test_forwardFromRouter_ShouldStoreLinkFees_Success() (gas: 113042) +EVM2EVMOnRamp_forwardFromRouter:test_forwardFromRouter_UnsupportedToken_Revert() (gas: 72824) +EVM2EVMOnRamp_forwardFromRouter:test_forwardFromRouter_correctSourceTokenData_Success() (gas: 714726) +EVM2EVMOnRamp_forwardFromRouter_upgrade:test_V2NonceNewSenderStartsAtZero_Success() (gas: 148808) +EVM2EVMOnRamp_forwardFromRouter_upgrade:test_V2NonceStartsAtV1Nonce_Success() (gas: 192679) +EVM2EVMOnRamp_forwardFromRouter_upgrade:test_V2SenderNoncesReadsPreviousRamp_Success() (gas: 123243) +EVM2EVMOnRamp_forwardFromRouter_upgrade:test_V2_Success() (gas: 96028) +EVM2EVMOnRamp_getDataAvailabilityCost:test_EmptyMessageCalculatesDataAvailabilityCost_Success() (gas: 20598) +EVM2EVMOnRamp_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCost_Success() (gas: 20966) +EVM2EVMOnRamp_getFee:test_EmptyMessage_Success() (gas: 74897) +EVM2EVMOnRamp_getFee:test_GetFeeOfZeroForTokenMessage_Success() (gas: 80393) +EVM2EVMOnRamp_getFee:test_HighGasMessage_Success() (gas: 230745) +EVM2EVMOnRamp_getFee:test_MessageGasLimitTooHigh_Revert() (gas: 16943) +EVM2EVMOnRamp_getFee:test_MessageTooLarge_Revert() (gas: 95505) +EVM2EVMOnRamp_getFee:test_MessageWithDataAndTokenTransfer_Success() (gas: 153881) +EVM2EVMOnRamp_getFee:test_NotAFeeToken_Revert() (gas: 24323) +EVM2EVMOnRamp_getFee:test_SingleTokenMessage_Success() (gas: 114699) +EVM2EVMOnRamp_getFee:test_TooManyTokens_Revert() (gas: 20142) +EVM2EVMOnRamp_getFee:test_ZeroDataAvailabilityMultiplier_Success() (gas: 63070) +EVM2EVMOnRamp_getSupportedTokens:test_GetSupportedTokens_Revert() (gas: 10532) +EVM2EVMOnRamp_getTokenPool:test_GetTokenPool_Success() (gas: 35297) +EVM2EVMOnRamp_getTokenTransferCost:test_CustomTokenBpsFee_Success() (gas: 43196) +EVM2EVMOnRamp_getTokenTransferCost:test_FeeTokenBpsFee_Success() (gas: 33280) +EVM2EVMOnRamp_getTokenTransferCost:test_LargeTokenTransferChargesMaxFeeAndGas_Success() (gas: 28551) +EVM2EVMOnRamp_getTokenTransferCost:test_MixedTokenTransferFee_Success() (gas: 122558) +EVM2EVMOnRamp_getTokenTransferCost:test_NoTokenTransferChargesZeroFee_Success() (gas: 15403) +EVM2EVMOnRamp_getTokenTransferCost:test_SmallTokenTransferChargesMinFeeAndGas_Success() (gas: 28359) +EVM2EVMOnRamp_getTokenTransferCost:test_UnsupportedToken_Revert() (gas: 21353) +EVM2EVMOnRamp_getTokenTransferCost:test_ZeroAmountTokenTransferChargesMinFeeAndGas_Success() (gas: 28382) +EVM2EVMOnRamp_getTokenTransferCost:test_ZeroFeeConfigChargesMinFee_Success() (gas: 38899) +EVM2EVMOnRamp_getTokenTransferCost:test__getTokenTransferCost_selfServeUsesDefaults_Success() (gas: 29674) +EVM2EVMOnRamp_linkAvailableForPayment:test_InsufficientLinkBalance_Success() (gas: 32756) +EVM2EVMOnRamp_linkAvailableForPayment:test_LinkAvailableForPayment_Success() (gas: 135247) +EVM2EVMOnRamp_payNops:test_AdminPayNops_Success() (gas: 143660) +EVM2EVMOnRamp_payNops:test_InsufficientBalance_Revert() (gas: 29196) +EVM2EVMOnRamp_payNops:test_NoFeesToPay_Revert() (gas: 127718) +EVM2EVMOnRamp_payNops:test_NoNopsToPay_Revert() (gas: 133580) +EVM2EVMOnRamp_payNops:test_NopPayNops_Success() (gas: 146947) +EVM2EVMOnRamp_payNops:test_OwnerPayNops_Success() (gas: 141522) +EVM2EVMOnRamp_payNops:test_PayNopsSuccessAfterSetNops() (gas: 298728) +EVM2EVMOnRamp_payNops:test_WrongPermissions_Revert() (gas: 15378) +EVM2EVMOnRamp_setDynamicConfig:test_SetConfigInvalidConfig_Revert() (gas: 42524) +EVM2EVMOnRamp_setDynamicConfig:test_SetConfigOnlyOwner_Revert() (gas: 21426) +EVM2EVMOnRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 54301) +EVM2EVMOnRamp_setFeeTokenConfig:test_OnlyCallableByOwnerOrAdmin_Revert() (gas: 13530) +EVM2EVMOnRamp_setFeeTokenConfig:test_SetFeeTokenConfigByAdmin_Success() (gas: 16497) +EVM2EVMOnRamp_setFeeTokenConfig:test_SetFeeTokenConfig_Success() (gas: 14036) +EVM2EVMOnRamp_setNops:test_AdminCanSetNops_Success() (gas: 61872) +EVM2EVMOnRamp_setNops:test_IncludesPayment_Success() (gas: 470835) +EVM2EVMOnRamp_setNops:test_LinkTokenCannotBeNop_Revert() (gas: 57370) +EVM2EVMOnRamp_setNops:test_NonOwnerOrAdmin_Revert() (gas: 14779) +EVM2EVMOnRamp_setNops:test_NotEnoughFundsForPayout_Revert() (gas: 85200) +EVM2EVMOnRamp_setNops:test_SetNopsRemovesOldNopsCompletely_Success() (gas: 60868) +EVM2EVMOnRamp_setNops:test_SetNops_Success() (gas: 174097) +EVM2EVMOnRamp_setNops:test_TooManyNops_Revert() (gas: 193503) +EVM2EVMOnRamp_setNops:test_ZeroAddressCannotBeNop_Revert() (gas: 53711) +EVM2EVMOnRamp_setTokenTransferFeeConfig:test__setTokenTransferFeeConfig_InvalidDestBytesOverhead_Revert() (gas: 14616) +EVM2EVMOnRamp_setTokenTransferFeeConfig:test__setTokenTransferFeeConfig_OnlyCallableByOwnerOrAdmin_Revert() (gas: 14427) +EVM2EVMOnRamp_setTokenTransferFeeConfig:test__setTokenTransferFeeConfig_Success() (gas: 85487) +EVM2EVMOnRamp_setTokenTransferFeeConfig:test__setTokenTransferFeeConfig_byAdmin_Success() (gas: 17468) +EVM2EVMOnRamp_withdrawNonLinkFees:test_LinkBalanceNotSettled_Revert() (gas: 83617) +EVM2EVMOnRamp_withdrawNonLinkFees:test_NonOwnerOrAdmin_Revert() (gas: 15353) +EVM2EVMOnRamp_withdrawNonLinkFees:test_SettlingBalance_Success() (gas: 272851) +EVM2EVMOnRamp_withdrawNonLinkFees:test_WithdrawNonLinkFees_Success() (gas: 53566) +EVM2EVMOnRamp_withdrawNonLinkFees:test_WithdrawToZeroAddress_Revert() (gas: 12875) +EtherSenderReceiverTest_ccipReceive:test_ccipReceive_fallbackToWethTransfer() (gas: 96907) +EtherSenderReceiverTest_ccipReceive:test_ccipReceive_happyPath() (gas: 49775) +EtherSenderReceiverTest_ccipReceive:test_ccipReceive_wrongToken() (gas: 17435) +EtherSenderReceiverTest_ccipReceive:test_ccipReceive_wrongTokenAmount() (gas: 15728) +EtherSenderReceiverTest_ccipSend:test_ccipSend_reverts_insufficientFee_feeToken() (gas: 99909) +EtherSenderReceiverTest_ccipSend:test_ccipSend_reverts_insufficientFee_native() (gas: 76138) +EtherSenderReceiverTest_ccipSend:test_ccipSend_reverts_insufficientFee_weth() (gas: 99931) +EtherSenderReceiverTest_ccipSend:test_ccipSend_success_feeToken() (gas: 145010) +EtherSenderReceiverTest_ccipSend:test_ccipSend_success_native() (gas: 80373) +EtherSenderReceiverTest_ccipSend:test_ccipSend_success_nativeExcess() (gas: 80560) +EtherSenderReceiverTest_ccipSend:test_ccipSend_success_weth() (gas: 96064) +EtherSenderReceiverTest_constructor:test_constructor() (gas: 17553) +EtherSenderReceiverTest_getFee:test_getFee() (gas: 27346) +EtherSenderReceiverTest_validateFeeToken:test_validateFeeToken_reverts_feeToken_tokenAmountNotEqualToMsgValue() (gas: 20375) +EtherSenderReceiverTest_validateFeeToken:test_validateFeeToken_valid_feeToken() (gas: 16724) EtherSenderReceiverTest_validateFeeToken:test_validateFeeToken_valid_native() (gas: 16657) -EtherSenderReceiverTest_validatedMessage:test_validatedMessage_dataOverwrittenToMsgSender() (gas: 25415) -EtherSenderReceiverTest_validatedMessage:test_validatedMessage_emptyDataOverwrittenToMsgSender() (gas: 25265) -EtherSenderReceiverTest_validatedMessage:test_validatedMessage_invalidTokenAmounts() (gas: 17913) -EtherSenderReceiverTest_validatedMessage:test_validatedMessage_tokenOverwrittenToWeth() (gas: 25287) -EtherSenderReceiverTest_validatedMessage:test_validatedMessage_validMessage_extraArgs() (gas: 26328) -FeeQuoter_applyDestChainConfigUpdates:test_InvalidChainFamilySelector_Revert() (gas: 16515) -FeeQuoter_applyDestChainConfigUpdates:test_InvalidDestChainConfigDestChainSelectorEqZero_Revert() (gas: 16429) -FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesDefaultTxGasLimitEqZero_Revert() (gas: 16471) -FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesDefaultTxGasLimitGtMaxPerMessageGasLimit_Revert() (gas: 39975) -FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesZeroIntput_Success() (gas: 12342) -FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdates_Success() (gas: 135960) -FeeQuoter_applyFeeTokensUpdates:test_ApplyFeeTokensUpdates_Success() (gas: 80127) -FeeQuoter_applyFeeTokensUpdates:test_OnlyCallableByOwner_Revert() (gas: 12621) -FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_OnlyCallableByOwnerOrAdmin_Revert() (gas: 11462) -FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesMultipleTokens_Success() (gas: 54242) -FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesSingleToken_Success() (gas: 44886) -FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesZeroInput() (gas: 12280) -FeeQuoter_applyTokenTransferFeeConfigUpdates:test_ApplyTokenTransferFeeConfig_Success() (gas: 87004) -FeeQuoter_applyTokenTransferFeeConfigUpdates:test_ApplyTokenTransferFeeZeroInput() (gas: 13089) -FeeQuoter_applyTokenTransferFeeConfigUpdates:test_InvalidDestBytesOverhead_Revert() (gas: 17071) -FeeQuoter_applyTokenTransferFeeConfigUpdates:test_OnlyCallableByOwnerOrAdmin_Revert() (gas: 12252) -FeeQuoter_constructor:test_InvalidLinkTokenEqZeroAddress_Revert() (gas: 106781) -FeeQuoter_constructor:test_InvalidMaxFeeJuelsPerMsg_Revert() (gas: 111131) -FeeQuoter_constructor:test_InvalidStalenessThreshold_Revert() (gas: 111184) -FeeQuoter_constructor:test_Setup_Success() (gas: 5178579) -FeeQuoter_convertTokenAmount:test_ConvertTokenAmount_Success() (gas: 68377) +EtherSenderReceiverTest_validatedMessage:test_validatedMessage_dataOverwrittenToMsgSender() (gas: 25457) +EtherSenderReceiverTest_validatedMessage:test_validatedMessage_emptyDataOverwrittenToMsgSender() (gas: 25307) +EtherSenderReceiverTest_validatedMessage:test_validatedMessage_invalidTokenAmounts() (gas: 17925) +EtherSenderReceiverTest_validatedMessage:test_validatedMessage_tokenOverwrittenToWeth() (gas: 25329) +EtherSenderReceiverTest_validatedMessage:test_validatedMessage_validMessage_extraArgs() (gas: 26370) +FeeQuoter_applyDestChainConfigUpdates:test_InvalidChainFamilySelector_Revert() (gas: 16686) +FeeQuoter_applyDestChainConfigUpdates:test_InvalidDestChainConfigDestChainSelectorEqZero_Revert() (gas: 16588) +FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesDefaultTxGasLimitEqZero_Revert() (gas: 16630) +FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesDefaultTxGasLimitGtMaxPerMessageGasLimit_Revert() (gas: 40326) +FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesZeroIntput_Success() (gas: 12483) +FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdates_Success() (gas: 137509) +FeeQuoter_applyFeeTokensUpdates:test_ApplyFeeTokensUpdates_Success() (gas: 80556) +FeeQuoter_applyFeeTokensUpdates:test_OnlyCallableByOwner_Revert() (gas: 12752) +FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_OnlyCallableByOwnerOrAdmin_Revert() (gas: 11547) +FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesMultipleTokens_Success() (gas: 54684) +FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesSingleToken_Success() (gas: 45130) +FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesZeroInput() (gas: 12332) +FeeQuoter_applyTokenTransferFeeConfigUpdates:test_ApplyTokenTransferFeeConfig_Success() (gas: 87679) +FeeQuoter_applyTokenTransferFeeConfigUpdates:test_ApplyTokenTransferFeeZeroInput() (gas: 13256) +FeeQuoter_applyTokenTransferFeeConfigUpdates:test_InvalidDestBytesOverhead_Revert() (gas: 17301) +FeeQuoter_applyTokenTransferFeeConfigUpdates:test_OnlyCallableByOwnerOrAdmin_Revert() (gas: 12353) +FeeQuoter_constructor:test_InvalidLinkTokenEqZeroAddress_Revert() (gas: 106501) +FeeQuoter_constructor:test_InvalidMaxFeeJuelsPerMsg_Revert() (gas: 110851) +FeeQuoter_constructor:test_InvalidStalenessThreshold_Revert() (gas: 110904) +FeeQuoter_constructor:test_Setup_Success() (gas: 4972856) +FeeQuoter_convertTokenAmount:test_ConvertTokenAmount_Success() (gas: 68383) FeeQuoter_convertTokenAmount:test_LinkTokenNotSupported_Revert() (gas: 29076) -FeeQuoter_getDataAvailabilityCost:test_EmptyMessageCalculatesDataAvailabilityCost_Success() (gas: 94447) -FeeQuoter_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCostUnsupportedDestChainSelector_Success() (gas: 14650) -FeeQuoter_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCost_Success() (gas: 20482) -FeeQuoter_getTokenAndGasPrices:test_GetFeeTokenAndGasPrices_Success() (gas: 68277) -FeeQuoter_getTokenAndGasPrices:test_StaleGasPrice_Revert() (gas: 16838) -FeeQuoter_getTokenAndGasPrices:test_UnsupportedChain_Revert() (gas: 16140) -FeeQuoter_getTokenAndGasPrices:test_ZeroGasPrice_Success() (gas: 43590) -FeeQuoter_getTokenPrice:test_GetTokenPriceFromFeed_Success() (gas: 66117) -FeeQuoter_getTokenPrices:test_GetTokenPrices_Success() (gas: 78256) -FeeQuoter_getTokenTransferCost:test_CustomTokenBpsFee_Success() (gas: 39106) -FeeQuoter_getTokenTransferCost:test_FeeTokenBpsFee_Success() (gas: 34742) -FeeQuoter_getTokenTransferCost:test_LargeTokenTransferChargesMaxFeeAndGas_Success() (gas: 27816) -FeeQuoter_getTokenTransferCost:test_MixedTokenTransferFee_Success() (gas: 96829) -FeeQuoter_getTokenTransferCost:test_NoTokenTransferChargesZeroFee_Success() (gas: 20390) -FeeQuoter_getTokenTransferCost:test_SmallTokenTransferChargesMinFeeAndGas_Success() (gas: 27691) -FeeQuoter_getTokenTransferCost:test_ZeroAmountTokenTransferChargesMinFeeAndGas_Success() (gas: 27647) -FeeQuoter_getTokenTransferCost:test_ZeroFeeConfigChargesMinFee_Success() (gas: 40076) -FeeQuoter_getTokenTransferCost:test_getTokenTransferCost_selfServeUsesDefaults_Success() (gas: 29359) -FeeQuoter_getValidatedFee:test_DestinationChainNotEnabled_Revert() (gas: 18210) -FeeQuoter_getValidatedFee:test_EmptyMessage_Success() (gas: 81749) -FeeQuoter_getValidatedFee:test_EnforceOutOfOrder_Revert() (gas: 52224) -FeeQuoter_getValidatedFee:test_HighGasMessage_Success() (gas: 238167) -FeeQuoter_getValidatedFee:test_InvalidEVMAddress_Revert() (gas: 22426) -FeeQuoter_getValidatedFee:test_MessageGasLimitTooHigh_Revert() (gas: 29652) -FeeQuoter_getValidatedFee:test_MessageTooLarge_Revert() (gas: 100163) -FeeQuoter_getValidatedFee:test_MessageWithDataAndTokenTransfer_Success() (gas: 140673) -FeeQuoter_getValidatedFee:test_NotAFeeToken_Revert() (gas: 21079) -FeeQuoter_getValidatedFee:test_SingleTokenMessage_Success() (gas: 112330) -FeeQuoter_getValidatedFee:test_TooManyTokens_Revert() (gas: 22562) -FeeQuoter_getValidatedFee:test_ZeroDataAvailabilityMultiplier_Success() (gas: 62255) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Above18Decimals_Success() (gas: 2068728) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Below18Decimals_Success() (gas: 2068686) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt0Decimals_Success() (gas: 2048805) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt18Decimals_Success() (gas: 2068460) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFlippedDecimals_Success() (gas: 2068664) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedMaxInt224Value_Success() (gas: 2068476) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedOverStalenessPeriod_Success() (gas: 64412) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeed_Success() (gas: 64292) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPrice_Success() (gas: 58855) -FeeQuoter_getValidatedTokenPrice:test_OverflowFeedPrice_Revert() (gas: 2068167) -FeeQuoter_getValidatedTokenPrice:test_StaleFeeToken_Success() (gas: 61692) -FeeQuoter_getValidatedTokenPrice:test_TokenNotSupportedFeed_Revert() (gas: 116292) -FeeQuoter_getValidatedTokenPrice:test_TokenNotSupported_Revert() (gas: 14004) -FeeQuoter_getValidatedTokenPrice:test_UnderflowFeedPrice_Revert() (gas: 2066844) -FeeQuoter_onReport:test_OnReport_StaleUpdate_Revert() (gas: 43342) -FeeQuoter_onReport:test_onReport_InvalidForwarder_Reverts() (gas: 23312) -FeeQuoter_onReport:test_onReport_Success() (gas: 79840) -FeeQuoter_onReport:test_onReport_UnsupportedToken_Reverts() (gas: 26704) -FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsDefault_Success() (gas: 17191) -FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsEnforceOutOfOrder_Revert() (gas: 21302) -FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsGasLimitTooHigh_Revert() (gas: 18399) -FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsInvalidExtraArgsTag_Revert() (gas: 17923) -FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsV1_Success() (gas: 18291) -FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsV2_Success() (gas: 18407) -FeeQuoter_processMessageArgs:test_InvalidExtraArgs_Revert() (gas: 18339) -FeeQuoter_processMessageArgs:test_MalformedEVMExtraArgs_Revert() (gas: 18891) -FeeQuoter_processMessageArgs:test_MessageFeeTooHigh_Revert() (gas: 16404) -FeeQuoter_processMessageArgs:test_WitEVMExtraArgsV2_Success() (gas: 26295) -FeeQuoter_processMessageArgs:test_WithConvertedTokenAmount_Success() (gas: 27695) -FeeQuoter_processMessageArgs:test_WithEVMExtraArgsV1_Success() (gas: 25901) -FeeQuoter_processMessageArgs:test_WithEmptyEVMExtraArgs_Success() (gas: 23716) -FeeQuoter_processMessageArgs:test_WithLinkTokenAmount_Success() (gas: 17353) -FeeQuoter_updatePrices:test_OnlyCallableByUpdater_Revert() (gas: 12114) -FeeQuoter_updatePrices:test_OnlyGasPrice_Success() (gas: 23599) -FeeQuoter_updatePrices:test_OnlyTokenPrice_Success() (gas: 28428) -FeeQuoter_updatePrices:test_UpdatableByAuthorizedCaller_Success() (gas: 74269) -FeeQuoter_updatePrices:test_UpdateMultiplePrices_Success() (gas: 144784) -FeeQuoter_updateTokenPriceFeeds:test_FeedNotUpdated() (gas: 50523) -FeeQuoter_updateTokenPriceFeeds:test_FeedUnset_Success() (gas: 63200) -FeeQuoter_updateTokenPriceFeeds:test_FeedUpdatedByNonOwner_Revert() (gas: 19944) -FeeQuoter_updateTokenPriceFeeds:test_MultipleFeedUpdate_Success() (gas: 88920) -FeeQuoter_updateTokenPriceFeeds:test_SingleFeedUpdate_Success() (gas: 50795) -FeeQuoter_updateTokenPriceFeeds:test_ZeroFeeds_Success() (gas: 12296) -FeeQuoter_validateDestFamilyAddress:test_InvalidEVMAddressEncodePacked_Revert() (gas: 10634) -FeeQuoter_validateDestFamilyAddress:test_InvalidEVMAddressPrecompiles_Revert() (gas: 3980078) -FeeQuoter_validateDestFamilyAddress:test_InvalidEVMAddress_Revert() (gas: 10818) -FeeQuoter_validateDestFamilyAddress:test_ValidEVMAddress_Success() (gas: 6710) -FeeQuoter_validateDestFamilyAddress:test_ValidNonEVMAddress_Success() (gas: 6484) -FeeQuoter_validatePoolReturnData:test_InvalidEVMAddressDestToken_Revert() (gas: 42781) -FeeQuoter_validatePoolReturnData:test_ProcessPoolReturnData_Success() (gas: 73330) -FeeQuoter_validatePoolReturnData:test_SourceTokenDataTooLarge_Revert() (gas: 107927) -FeeQuoter_validatePoolReturnData:test_TokenAmountArraysMismatching_Revert() (gas: 40112) -HybridUSDCTokenPoolMigrationTests:test_LockOrBurn_LockReleaseMechanism_then_switchToPrimary_Success() (gas: 209099) -HybridUSDCTokenPoolMigrationTests:test_LockOrBurn_PrimaryMechanism_Success() (gas: 135804) -HybridUSDCTokenPoolMigrationTests:test_LockOrBurn_WhileMigrationPause_Revert() (gas: 107078) -HybridUSDCTokenPoolMigrationTests:test_LockOrBurn_onLockReleaseMechanism_Success() (gas: 144568) -HybridUSDCTokenPoolMigrationTests:test_MintOrRelease_OnLockReleaseMechanism_Success() (gas: 214763) -HybridUSDCTokenPoolMigrationTests:test_MintOrRelease_OnLockReleaseMechanism_then_switchToPrimary_Success() (gas: 423554) -HybridUSDCTokenPoolMigrationTests:test_MintOrRelease_incomingMessageWithPrimaryMechanism() (gas: 268901) -HybridUSDCTokenPoolMigrationTests:test_ReleaseOrMint_WhileMigrationPause_Revert() (gas: 111457) -HybridUSDCTokenPoolMigrationTests:test_burnLockedUSDC_invalidPermissions_Revert() (gas: 39338) -HybridUSDCTokenPoolMigrationTests:test_cancelExistingCCTPMigrationProposal() (gas: 33151) -HybridUSDCTokenPoolMigrationTests:test_cannotCancelANonExistentMigrationProposal() (gas: 12651) -HybridUSDCTokenPoolMigrationTests:test_cannotModifyLiquidityWithoutPermissions_Revert() (gas: 13323) -HybridUSDCTokenPoolMigrationTests:test_cannotTransferLiquidityDuringPendingMigration_Revert() (gas: 160885) -HybridUSDCTokenPoolMigrationTests:test_lockOrBurn_then_BurnInCCTPMigration_Success() (gas: 255833) -HybridUSDCTokenPoolMigrationTests:test_transferLiquidity_Success() (gas: 165878) -HybridUSDCTokenPoolMigrationTests:test_unstickManualTxAfterMigration_destChain_Success() (gas: 154182) -HybridUSDCTokenPoolMigrationTests:test_unstickManualTxAfterMigration_homeChain_Success() (gas: 463620) -HybridUSDCTokenPoolTests:test_LockOrBurn_LockReleaseMechanism_then_switchToPrimary_Success() (gas: 208712) -HybridUSDCTokenPoolTests:test_LockOrBurn_PrimaryMechanism_Success() (gas: 135647) -HybridUSDCTokenPoolTests:test_LockOrBurn_WhileMigrationPause_Revert() (gas: 106991) -HybridUSDCTokenPoolTests:test_LockOrBurn_onLockReleaseMechanism_Success() (gas: 144457) -HybridUSDCTokenPoolTests:test_MintOrRelease_OnLockReleaseMechanism_Success() (gas: 214471) -HybridUSDCTokenPoolTests:test_MintOrRelease_OnLockReleaseMechanism_then_switchToPrimary_Success() (gas: 422833) -HybridUSDCTokenPoolTests:test_MintOrRelease_incomingMessageWithPrimaryMechanism() (gas: 268620) -HybridUSDCTokenPoolTests:test_ReleaseOrMint_WhileMigrationPause_Revert() (gas: 111336) -HybridUSDCTokenPoolTests:test_cannotTransferLiquidityDuringPendingMigration_Revert() (gas: 160764) -HybridUSDCTokenPoolTests:test_transferLiquidity_Success() (gas: 165649) -LockReleaseTokenPoolAndProxy_setRebalancer:test_SetRebalancer_Revert() (gas: 10983) -LockReleaseTokenPoolAndProxy_setRebalancer:test_SetRebalancer_Success() (gas: 18010) -LockReleaseTokenPoolPoolAndProxy_canAcceptLiquidity:test_CanAcceptLiquidity_Success() (gas: 3195288) -LockReleaseTokenPoolPoolAndProxy_provideLiquidity:test_LiquidityNotAccepted_Revert() (gas: 3191694) -LockReleaseTokenPoolPoolAndProxy_provideLiquidity:test_Unauthorized_Revert() (gas: 11417) -LockReleaseTokenPoolPoolAndProxy_supportsInterface:test_SupportsInterface_Success() (gas: 10124) -LockReleaseTokenPoolPoolAndProxy_withdrawalLiquidity:test_InsufficientLiquidity_Revert() (gas: 60081) -LockReleaseTokenPoolPoolAndProxy_withdrawalLiquidity:test_Unauthorized_Revert() (gas: 11386) -LockReleaseTokenPool_canAcceptLiquidity:test_CanAcceptLiquidity_Success() (gas: 2982884) -LockReleaseTokenPool_lockOrBurn:test_LockOrBurnWithAllowList_Revert() (gas: 29972) -LockReleaseTokenPool_lockOrBurn:test_LockOrBurnWithAllowList_Success() (gas: 79880) -LockReleaseTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 59491) -LockReleaseTokenPool_provideLiquidity:test_LiquidityNotAccepted_Revert() (gas: 2979334) -LockReleaseTokenPool_provideLiquidity:test_Unauthorized_Revert() (gas: 11417) -LockReleaseTokenPool_releaseOrMint:test_ChainNotAllowed_Revert() (gas: 72680) -LockReleaseTokenPool_releaseOrMint:test_PoolMintNotHealthy_Revert() (gas: 56223) -LockReleaseTokenPool_releaseOrMint:test_ReleaseOrMint_Success() (gas: 225332) -LockReleaseTokenPool_setRebalancer:test_SetRebalancer_Revert() (gas: 11005) -LockReleaseTokenPool_setRebalancer:test_SetRebalancer_Success() (gas: 18064) -LockReleaseTokenPool_supportsInterface:test_SupportsInterface_Success() (gas: 10124) -LockReleaseTokenPool_transferLiquidity:test_transferLiquidity_Success() (gas: 83192) -LockReleaseTokenPool_transferLiquidity:test_transferLiquidity_transferTooMuch_Revert() (gas: 55899) -LockReleaseTokenPool_withdrawalLiquidity:test_InsufficientLiquidity_Revert() (gas: 60081) -LockReleaseTokenPool_withdrawalLiquidity:test_Unauthorized_Revert() (gas: 11386) -LockRelease_setRateLimitAdmin:test_SetRateLimitAdmin_Revert() (gas: 11048) -LockRelease_setRateLimitAdmin:test_SetRateLimitAdmin_Success() (gas: 35036) -MerkleMultiProofTest:test_CVE_2023_34459() (gas: 5460) -MerkleMultiProofTest:test_EmptyLeaf_Revert() (gas: 3573) -MerkleMultiProofTest:test_MerkleRoot256() (gas: 394879) -MerkleMultiProofTest:test_MerkleRootSingleLeaf_Success() (gas: 3649) -MerkleMultiProofTest:test_SpecSync_gas() (gas: 34123) -MockRouterTest:test_ccipSendWithInsufficientNativeTokens_Revert() (gas: 34025) -MockRouterTest:test_ccipSendWithInvalidMsgValue_Revert() (gas: 60830) -MockRouterTest:test_ccipSendWithLinkFeeTokenAndValidMsgValue_Success() (gas: 126552) -MockRouterTest:test_ccipSendWithLinkFeeTokenbutInsufficientAllowance_Revert() (gas: 63431) +FeeQuoter_getDataAvailabilityCost:test_EmptyMessageCalculatesDataAvailabilityCost_Success() (gas: 94737) +FeeQuoter_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCostUnsupportedDestChainSelector_Success() (gas: 14670) +FeeQuoter_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCost_Success() (gas: 20528) +FeeQuoter_getTokenAndGasPrices:test_GetFeeTokenAndGasPrices_Success() (gas: 68313) +FeeQuoter_getTokenAndGasPrices:test_StaleGasPrice_Revert() (gas: 16892) +FeeQuoter_getTokenAndGasPrices:test_UnsupportedChain_Revert() (gas: 16188) +FeeQuoter_getTokenAndGasPrices:test_ZeroGasPrice_Success() (gas: 43682) +FeeQuoter_getTokenPrice:test_GetTokenPriceFromFeed_Success() (gas: 66273) +FeeQuoter_getTokenPrices:test_GetTokenPrices_Success() (gas: 78300) +FeeQuoter_getTokenTransferCost:test_CustomTokenBpsFee_Success() (gas: 39200) +FeeQuoter_getTokenTransferCost:test_FeeTokenBpsFee_Success() (gas: 34836) +FeeQuoter_getTokenTransferCost:test_LargeTokenTransferChargesMaxFeeAndGas_Success() (gas: 27910) +FeeQuoter_getTokenTransferCost:test_MixedTokenTransferFee_Success() (gas: 97315) +FeeQuoter_getTokenTransferCost:test_NoTokenTransferChargesZeroFee_Success() (gas: 20446) +FeeQuoter_getTokenTransferCost:test_SmallTokenTransferChargesMinFeeAndGas_Success() (gas: 27785) +FeeQuoter_getTokenTransferCost:test_ZeroAmountTokenTransferChargesMinFeeAndGas_Success() (gas: 27741) +FeeQuoter_getTokenTransferCost:test_ZeroFeeConfigChargesMinFee_Success() (gas: 40377) +FeeQuoter_getTokenTransferCost:test_getTokenTransferCost_selfServeUsesDefaults_Success() (gas: 29459) +FeeQuoter_getValidatedFee:test_DestinationChainNotEnabled_Revert() (gas: 18315) +FeeQuoter_getValidatedFee:test_EmptyMessage_Success() (gas: 82303) +FeeQuoter_getValidatedFee:test_EnforceOutOfOrder_Revert() (gas: 52638) +FeeQuoter_getValidatedFee:test_HighGasMessage_Success() (gas: 238721) +FeeQuoter_getValidatedFee:test_InvalidEVMAddress_Revert() (gas: 22555) +FeeQuoter_getValidatedFee:test_MessageGasLimitTooHigh_Revert() (gas: 29847) +FeeQuoter_getValidatedFee:test_MessageTooLarge_Revert() (gas: 100292) +FeeQuoter_getValidatedFee:test_MessageWithDataAndTokenTransfer_Success() (gas: 141631) +FeeQuoter_getValidatedFee:test_NotAFeeToken_Revert() (gas: 21172) +FeeQuoter_getValidatedFee:test_SingleTokenMessage_Success() (gas: 113136) +FeeQuoter_getValidatedFee:test_TooManyTokens_Revert() (gas: 22691) +FeeQuoter_getValidatedFee:test_ZeroDataAvailabilityMultiplier_Success() (gas: 62692) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Above18Decimals_Success() (gas: 1973885) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Below18Decimals_Success() (gas: 1973843) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt0Decimals_Success() (gas: 1953962) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt18Decimals_Success() (gas: 1973617) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFlippedDecimals_Success() (gas: 1973821) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedMaxInt224Value_Success() (gas: 1973633) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedOverStalenessPeriod_Success() (gas: 64588) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeed_Success() (gas: 64468) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPrice_Success() (gas: 58872) +FeeQuoter_getValidatedTokenPrice:test_OverflowFeedPrice_Revert() (gas: 1973330) +FeeQuoter_getValidatedTokenPrice:test_StaleFeeToken_Success() (gas: 61742) +FeeQuoter_getValidatedTokenPrice:test_TokenNotSupportedFeed_Revert() (gas: 116473) +FeeQuoter_getValidatedTokenPrice:test_TokenNotSupported_Revert() (gas: 14015) +FeeQuoter_getValidatedTokenPrice:test_UnderflowFeedPrice_Revert() (gas: 1972007) +FeeQuoter_onReport:test_OnReport_StaleUpdate_Revert() (gas: 43587) +FeeQuoter_onReport:test_onReport_InvalidForwarder_Reverts() (gas: 23470) +FeeQuoter_onReport:test_onReport_Success() (gas: 80072) +FeeQuoter_onReport:test_onReport_UnsupportedToken_Reverts() (gas: 26838) +FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsDefault_Success() (gas: 17262) +FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsEnforceOutOfOrder_Revert() (gas: 21406) +FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsGasLimitTooHigh_Revert() (gas: 18494) +FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsInvalidExtraArgsTag_Revert() (gas: 18012) +FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsV1_Success() (gas: 18368) +FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsV2_Success() (gas: 18490) +FeeQuoter_processMessageArgs:test_processMessageArgs_InvalidEVMAddressDestToken_Revert() (gas: 44991) +FeeQuoter_processMessageArgs:test_processMessageArgs_InvalidExtraArgs_Revert() (gas: 19936) +FeeQuoter_processMessageArgs:test_processMessageArgs_MalformedEVMExtraArgs_Revert() (gas: 20355) +FeeQuoter_processMessageArgs:test_processMessageArgs_MessageFeeTooHigh_Revert() (gas: 17937) +FeeQuoter_processMessageArgs:test_processMessageArgs_SourceTokenDataTooLarge_Revert() (gas: 124099) +FeeQuoter_processMessageArgs:test_processMessageArgs_TokenAmountArraysMismatching_Revert() (gas: 42235) +FeeQuoter_processMessageArgs:test_processMessageArgs_WitEVMExtraArgsV2_Success() (gas: 28540) +FeeQuoter_processMessageArgs:test_processMessageArgs_WithConvertedTokenAmount_Success() (gas: 29971) +FeeQuoter_processMessageArgs:test_processMessageArgs_WithCorrectPoolReturnData_Success() (gas: 76711) +FeeQuoter_processMessageArgs:test_processMessageArgs_WithEVMExtraArgsV1_Success() (gas: 28138) +FeeQuoter_processMessageArgs:test_processMessageArgs_WithEmptyEVMExtraArgs_Success() (gas: 26009) +FeeQuoter_processMessageArgs:test_processMessageArgs_WithLinkTokenAmount_Success() (gas: 19545) +FeeQuoter_updatePrices:test_OnlyCallableByUpdater_Revert() (gas: 12176) +FeeQuoter_updatePrices:test_OnlyGasPrice_Success() (gas: 23774) +FeeQuoter_updatePrices:test_OnlyTokenPrice_Success() (gas: 28505) +FeeQuoter_updatePrices:test_UpdatableByAuthorizedCaller_Success() (gas: 74668) +FeeQuoter_updatePrices:test_UpdateMultiplePrices_Success() (gas: 145452) +FeeQuoter_updateTokenPriceFeeds:test_FeedNotUpdated() (gas: 50875) +FeeQuoter_updateTokenPriceFeeds:test_FeedUnset_Success() (gas: 63847) +FeeQuoter_updateTokenPriceFeeds:test_FeedUpdatedByNonOwner_Revert() (gas: 20142) +FeeQuoter_updateTokenPriceFeeds:test_MultipleFeedUpdate_Success() (gas: 89470) +FeeQuoter_updateTokenPriceFeeds:test_SingleFeedUpdate_Success() (gas: 51121) +FeeQuoter_updateTokenPriceFeeds:test_ZeroFeeds_Success() (gas: 12437) +FeeQuoter_validateDestFamilyAddress:test_InvalidEVMAddressEncodePacked_Revert() (gas: 10655) +FeeQuoter_validateDestFamilyAddress:test_InvalidEVMAddressPrecompiles_Revert() (gas: 4001603) +FeeQuoter_validateDestFamilyAddress:test_InvalidEVMAddress_Revert() (gas: 10839) +FeeQuoter_validateDestFamilyAddress:test_ValidEVMAddress_Success() (gas: 6731) +FeeQuoter_validateDestFamilyAddress:test_ValidNonEVMAddress_Success() (gas: 6511) +HybridUSDCTokenPoolMigrationTests:test_LockOrBurn_LockReleaseMechanism_then_switchToPrimary_Success() (gas: 209257) +HybridUSDCTokenPoolMigrationTests:test_LockOrBurn_PrimaryMechanism_Success() (gas: 135884) +HybridUSDCTokenPoolMigrationTests:test_LockOrBurn_WhileMigrationPause_Revert() (gas: 107099) +HybridUSDCTokenPoolMigrationTests:test_LockOrBurn_onLockReleaseMechanism_Success() (gas: 144595) +HybridUSDCTokenPoolMigrationTests:test_MintOrRelease_OnLockReleaseMechanism_Success() (gas: 214814) +HybridUSDCTokenPoolMigrationTests:test_MintOrRelease_OnLockReleaseMechanism_then_switchToPrimary_Success() (gas: 423659) +HybridUSDCTokenPoolMigrationTests:test_MintOrRelease_incomingMessageWithPrimaryMechanism() (gas: 268944) +HybridUSDCTokenPoolMigrationTests:test_ReleaseOrMint_WhileMigrationPause_Revert() (gas: 111487) +HybridUSDCTokenPoolMigrationTests:test_burnLockedUSDC_invalidPermissions_Revert() (gas: 39362) +HybridUSDCTokenPoolMigrationTests:test_cancelExistingCCTPMigrationProposal() (gas: 33189) +HybridUSDCTokenPoolMigrationTests:test_cannotCancelANonExistentMigrationProposal() (gas: 12669) +HybridUSDCTokenPoolMigrationTests:test_cannotModifyLiquidityWithoutPermissions_Revert() (gas: 13329) +HybridUSDCTokenPoolMigrationTests:test_cannotTransferLiquidityDuringPendingMigration_Revert() (gas: 160900) +HybridUSDCTokenPoolMigrationTests:test_lockOrBurn_then_BurnInCCTPMigration_Success() (gas: 255996) +HybridUSDCTokenPoolMigrationTests:test_transferLiquidity_Success() (gas: 165921) +HybridUSDCTokenPoolMigrationTests:test_unstickManualTxAfterMigration_destChain_Success() (gas: 154242) +HybridUSDCTokenPoolMigrationTests:test_unstickManualTxAfterMigration_homeChain_Success() (gas: 463757) +HybridUSDCTokenPoolTests:test_LockOrBurn_LockReleaseMechanism_then_switchToPrimary_Success() (gas: 209240) +HybridUSDCTokenPoolTests:test_LockOrBurn_PrimaryMechanism_Success() (gas: 135884) +HybridUSDCTokenPoolTests:test_LockOrBurn_WhileMigrationPause_Revert() (gas: 107144) +HybridUSDCTokenPoolTests:test_LockOrBurn_onLockReleaseMechanism_Success() (gas: 144616) +HybridUSDCTokenPoolTests:test_MintOrRelease_OnLockReleaseMechanism_Success() (gas: 214792) +HybridUSDCTokenPoolTests:test_MintOrRelease_OnLockReleaseMechanism_then_switchToPrimary_Success() (gas: 423637) +HybridUSDCTokenPoolTests:test_MintOrRelease_incomingMessageWithPrimaryMechanism() (gas: 268927) +HybridUSDCTokenPoolTests:test_ReleaseOrMint_WhileMigrationPause_Revert() (gas: 111531) +HybridUSDCTokenPoolTests:test_cannotTransferLiquidityDuringPendingMigration_Revert() (gas: 160845) +HybridUSDCTokenPoolTests:test_transferLiquidity_Success() (gas: 165904) +LockReleaseTokenPoolAndProxy_setRebalancer:test_SetRebalancer_Revert() (gas: 10989) +LockReleaseTokenPoolAndProxy_setRebalancer:test_SetRebalancer_Success() (gas: 18028) +LockReleaseTokenPoolPoolAndProxy_canAcceptLiquidity:test_CanAcceptLiquidity_Success() (gas: 3051555) +LockReleaseTokenPoolPoolAndProxy_provideLiquidity:test_LiquidityNotAccepted_Revert() (gas: 3047994) +LockReleaseTokenPoolPoolAndProxy_provideLiquidity:test_Unauthorized_Revert() (gas: 11489) +LockReleaseTokenPoolPoolAndProxy_supportsInterface:test_SupportsInterface_Success() (gas: 10184) +LockReleaseTokenPoolPoolAndProxy_withdrawalLiquidity:test_InsufficientLiquidity_Revert() (gas: 60189) +LockReleaseTokenPoolPoolAndProxy_withdrawalLiquidity:test_Unauthorized_Revert() (gas: 11464) +LockReleaseTokenPool_canAcceptLiquidity:test_CanAcceptLiquidity_Success() (gas: 2836141) +LockReleaseTokenPool_lockOrBurn:test_LockOrBurnWithAllowList_Revert() (gas: 30062) +LockReleaseTokenPool_lockOrBurn:test_LockOrBurnWithAllowList_Success() (gas: 79943) +LockReleaseTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 59620) +LockReleaseTokenPool_provideLiquidity:test_LiquidityNotAccepted_Revert() (gas: 2832624) +LockReleaseTokenPool_provideLiquidity:test_Unauthorized_Revert() (gas: 11489) +LockReleaseTokenPool_releaseOrMint:test_ChainNotAllowed_Revert() (gas: 72743) +LockReleaseTokenPool_releaseOrMint:test_PoolMintNotHealthy_Revert() (gas: 56352) +LockReleaseTokenPool_releaseOrMint:test_ReleaseOrMint_Success() (gas: 225548) +LockReleaseTokenPool_setRebalancer:test_SetRebalancer_Revert() (gas: 11011) +LockReleaseTokenPool_setRebalancer:test_SetRebalancer_Success() (gas: 18094) +LockReleaseTokenPool_supportsInterface:test_SupportsInterface_Success() (gas: 10184) +LockReleaseTokenPool_transferLiquidity:test_transferLiquidity_Success() (gas: 83234) +LockReleaseTokenPool_transferLiquidity:test_transferLiquidity_transferTooMuch_Revert() (gas: 55947) +LockReleaseTokenPool_withdrawalLiquidity:test_InsufficientLiquidity_Revert() (gas: 60189) +LockReleaseTokenPool_withdrawalLiquidity:test_Unauthorized_Revert() (gas: 11464) +LockRelease_setRateLimitAdmin:test_SetRateLimitAdmin_Revert() (gas: 11054) +LockRelease_setRateLimitAdmin:test_SetRateLimitAdmin_Success() (gas: 35060) +MerkleMultiProofTest:test_CVE_2023_34459() (gas: 5478) +MerkleMultiProofTest:test_EmptyLeaf_Revert() (gas: 3585) +MerkleMultiProofTest:test_MerkleRoot256() (gas: 394891) +MerkleMultiProofTest:test_MerkleRootSingleLeaf_Success() (gas: 3661) +MerkleMultiProofTest:test_SpecSync_gas() (gas: 34129) +MockRouterTest:test_ccipSendWithInsufficientNativeTokens_Revert() (gas: 34037) +MockRouterTest:test_ccipSendWithInvalidMsgValue_Revert() (gas: 60842) +MockRouterTest:test_ccipSendWithLinkFeeTokenAndValidMsgValue_Success() (gas: 126588) +MockRouterTest:test_ccipSendWithLinkFeeTokenbutInsufficientAllowance_Revert() (gas: 63455) MockRouterTest:test_ccipSendWithSufficientNativeFeeTokens_Success() (gas: 44012) -MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_MultipleConfigsBothLanes_Success() (gas: 132457) -MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_MultipleConfigs_Success() (gas: 313023) -MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_OnlyCallableByOwner_Revert() (gas: 17756) -MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_SingleConfigOutbound_Success() (gas: 76030) -MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_SingleConfig_Success() (gas: 75946) -MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_UpdateExistingConfigWithNoDifference_Success() (gas: 38436) -MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_UpdateExistingConfig_Success() (gas: 53473) -MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_ZeroChainSelector_Revert() (gas: 17046) -MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_ZeroConfigs_Success() (gas: 12361) -MultiAggregateRateLimiter_constructor:test_ConstructorNoAuthorizedCallers_Success() (gas: 2050118) -MultiAggregateRateLimiter_constructor:test_Constructor_Success() (gas: 2166419) -MultiAggregateRateLimiter_getTokenBucket:test_GetTokenBucket_Success() (gas: 30404) -MultiAggregateRateLimiter_getTokenBucket:test_Refill_Success() (gas: 47679) -MultiAggregateRateLimiter_getTokenBucket:test_TimeUnderflow_Revert() (gas: 15863) -MultiAggregateRateLimiter_getTokenValue:test_GetTokenValue_Success() (gas: 17465) -MultiAggregateRateLimiter_getTokenValue:test_NoTokenPrice_Reverts() (gas: 21360) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageFromUnauthorizedCaller_Revert() (gas: 14539) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithDifferentTokensOnDifferentChains_Success() (gas: 209717) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithDisabledRateLimitToken_Success() (gas: 58293) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithNoTokens_Success() (gas: 17605) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitDisabled_Success() (gas: 45057) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitExceeded_Revert() (gas: 46184) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitReset_Success() (gas: 76162) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithTokensOnDifferentChains_Success() (gas: 307789) -MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithTokens_Success() (gas: 50381) -MultiAggregateRateLimiter_onOutboundMessage:test_RateLimitValueDifferentLanes_Success() (gas: 1073669836) -MultiAggregateRateLimiter_onOutboundMessage:test_ValidateMessageWithNoTokens_Success() (gas: 19158) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageFromUnauthorizedCaller_Revert() (gas: 15829) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithDifferentTokensOnDifferentChains_Success() (gas: 209483) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithDisabledRateLimitToken_Success() (gas: 60053) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitDisabled_Success() (gas: 46824) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitExceeded_Revert() (gas: 47987) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitReset_Success() (gas: 77305) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithTokensOnDifferentChains_Success() (gas: 307781) -MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithTokens_Success() (gas: 52163) -MultiAggregateRateLimiter_setFeeQuoter:test_OnlyOwner_Revert() (gas: 11331) -MultiAggregateRateLimiter_setFeeQuoter:test_Owner_Success() (gas: 19072) -MultiAggregateRateLimiter_setFeeQuoter:test_ZeroAddress_Revert() (gas: 10597) -MultiAggregateRateLimiter_updateRateLimitTokens:test_NonOwner_Revert() (gas: 18806) -MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokensMultipleChains_Success() (gas: 279944) -MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokensSingleChain_Success() (gas: 254495) -MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokens_AddsAndRemoves_Success() (gas: 204470) -MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokens_RemoveNonExistentToken_Success() (gas: 28709) -MultiAggregateRateLimiter_updateRateLimitTokens:test_ZeroDestToken_Revert() (gas: 18279) -MultiAggregateRateLimiter_updateRateLimitTokens:test_ZeroSourceToken_Revert() (gas: 18208) -MultiOCR3Base_setOCR3Configs:test_FMustBePositive_Revert() (gas: 59255) -MultiOCR3Base_setOCR3Configs:test_FTooHigh_Revert() (gas: 43632) -MultiOCR3Base_setOCR3Configs:test_RepeatSignerAddress_Revert() (gas: 283639) -MultiOCR3Base_setOCR3Configs:test_RepeatTransmitterAddress_Revert() (gas: 422264) -MultiOCR3Base_setOCR3Configs:test_SetConfigIgnoreSigners_Success() (gas: 511308) -MultiOCR3Base_setOCR3Configs:test_SetConfigWithSigners_Success() (gas: 828467) -MultiOCR3Base_setOCR3Configs:test_SetConfigWithoutSigners_Success() (gas: 456913) -MultiOCR3Base_setOCR3Configs:test_SetConfigsZeroInput_Success() (gas: 12382) -MultiOCR3Base_setOCR3Configs:test_SetMultipleConfigs_Success() (gas: 2140246) -MultiOCR3Base_setOCR3Configs:test_SignerCannotBeZeroAddress_Revert() (gas: 141720) -MultiOCR3Base_setOCR3Configs:test_StaticConfigChange_Revert() (gas: 807349) -MultiOCR3Base_setOCR3Configs:test_TooManySigners_Revert() (gas: 158802) -MultiOCR3Base_setOCR3Configs:test_TooManyTransmitters_Revert() (gas: 112296) -MultiOCR3Base_setOCR3Configs:test_TransmitterCannotBeZeroAddress_Revert() (gas: 254086) -MultiOCR3Base_setOCR3Configs:test_UpdateConfigSigners_Success() (gas: 860245) -MultiOCR3Base_setOCR3Configs:test_UpdateConfigTransmittersWithoutSigners_Success() (gas: 475215) -MultiOCR3Base_transmit:test_ConfigDigestMismatch_Revert() (gas: 42845) -MultiOCR3Base_transmit:test_ForkedChain_Revert() (gas: 48450) -MultiOCR3Base_transmit:test_InsufficientSignatures_Revert() (gas: 76934) -MultiOCR3Base_transmit:test_NonUniqueSignature_Revert() (gas: 65768) -MultiOCR3Base_transmit:test_SignatureOutOfRegistration_Revert() (gas: 33417) -MultiOCR3Base_transmit:test_TooManySignatures_Revert() (gas: 79525) -MultiOCR3Base_transmit:test_TransmitSigners_gas_Success() (gas: 33631) -MultiOCR3Base_transmit:test_TransmitWithExtraCalldataArgs_Revert() (gas: 47128) -MultiOCR3Base_transmit:test_TransmitWithLessCalldataArgs_Revert() (gas: 25696) -MultiOCR3Base_transmit:test_TransmitWithoutSignatureVerification_gas_Success() (gas: 18712) -MultiOCR3Base_transmit:test_UnAuthorizedTransmitter_Revert() (gas: 24195) -MultiOCR3Base_transmit:test_UnauthorizedSigner_Revert() (gas: 61131) -MultiOCR3Base_transmit:test_UnconfiguredPlugin_Revert() (gas: 39894) -MultiOCR3Base_transmit:test_ZeroSignatures_Revert() (gas: 32977) -MultiOnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 409189) -MultiRampsE2E:test_E2E_3MessagesMMultiOffRampSuccess_gas() (gas: 1537029) -NonceManager_NonceIncrementation:test_getIncrementedOutboundNonce_Success() (gas: 37922) -NonceManager_NonceIncrementation:test_incrementInboundNonce_Skip() (gas: 23709) -NonceManager_NonceIncrementation:test_incrementInboundNonce_Success() (gas: 38799) -NonceManager_NonceIncrementation:test_incrementNoncesInboundAndOutbound_Success() (gas: 71904) -NonceManager_OffRampUpgrade:test_NoPrevOffRampForChain_Success() (gas: 262138) -NonceManager_OffRampUpgrade:test_UpgradedNonceNewSenderStartsAtZero_Success() (gas: 266256) -NonceManager_OffRampUpgrade:test_UpgradedNonceStartsAtV1Nonce_Success() (gas: 331224) -NonceManager_OffRampUpgrade:test_UpgradedOffRampNonceSkipsIfMsgInFlight_Success() (gas: 302071) -NonceManager_OffRampUpgrade:test_UpgradedSenderNoncesReadsPreviousRampTransitive_Success() (gas: 245579) -NonceManager_OffRampUpgrade:test_UpgradedSenderNoncesReadsPreviousRamp_Success() (gas: 233648) -NonceManager_OffRampUpgrade:test_Upgraded_Success() (gas: 154815) -NonceManager_OnRampUpgrade:test_UpgradeNonceNewSenderStartsAtZero_Success() (gas: 168463) -NonceManager_OnRampUpgrade:test_UpgradeNonceStartsAtV1Nonce_Success() (gas: 220298) -NonceManager_OnRampUpgrade:test_UpgradeSenderNoncesReadsPreviousRamp_Success() (gas: 125472) -NonceManager_OnRampUpgrade:test_Upgrade_Success() (gas: 107566) -NonceManager_applyPreviousRampsUpdates:test_MultipleRampsUpdates() (gas: 122961) -NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySetOffRamp_Revert() (gas: 42983) -NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySetOnRampAndOffRamp_Revert() (gas: 64312) -NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySetOnRamp_Revert() (gas: 42847) -NonceManager_applyPreviousRampsUpdates:test_SingleRampUpdate() (gas: 66594) -NonceManager_applyPreviousRampsUpdates:test_ZeroInput() (gas: 12025) -NonceManager_typeAndVersion:test_typeAndVersion() (gas: 9699) -OCR2BaseNoChecks_setOCR2Config:test_FMustBePositive_Revert() (gas: 12195) -OCR2BaseNoChecks_setOCR2Config:test_RepeatAddress_Revert() (gas: 42416) -OCR2BaseNoChecks_setOCR2Config:test_SetConfigSuccess_gas() (gas: 84590) -OCR2BaseNoChecks_setOCR2Config:test_TooManyTransmitter_Revert() (gas: 38162) -OCR2BaseNoChecks_setOCR2Config:test_TransmitterCannotBeZeroAddress_Revert() (gas: 24290) -OCR2BaseNoChecks_transmit:test_ConfigDigestMismatch_Revert() (gas: 17475) -OCR2BaseNoChecks_transmit:test_ForkedChain_Revert() (gas: 26768) +MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_MultipleConfigsBothLanes_Success() (gas: 133528) +MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_MultipleConfigs_Success() (gas: 315630) +MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_OnlyCallableByOwner_Revert() (gas: 17864) +MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_SingleConfigOutbound_Success() (gas: 76453) +MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_SingleConfig_Success() (gas: 76369) +MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_UpdateExistingConfigWithNoDifference_Success() (gas: 38736) +MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_UpdateExistingConfig_Success() (gas: 53869) +MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_ZeroChainSelector_Revert() (gas: 17109) +MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_ZeroConfigs_Success() (gas: 12436) +MultiAggregateRateLimiter_constructor:test_ConstructorNoAuthorizedCallers_Success() (gas: 1958738) +MultiAggregateRateLimiter_constructor:test_Constructor_Success() (gas: 2075046) +MultiAggregateRateLimiter_getTokenBucket:test_GetTokenBucket_Success() (gas: 30794) +MultiAggregateRateLimiter_getTokenBucket:test_Refill_Success() (gas: 48099) +MultiAggregateRateLimiter_getTokenBucket:test_TimeUnderflow_Revert() (gas: 15929) +MultiAggregateRateLimiter_getTokenValue:test_GetTokenValue_Success() (gas: 17525) +MultiAggregateRateLimiter_getTokenValue:test_NoTokenPrice_Reverts() (gas: 21408) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageFromUnauthorizedCaller_Revert() (gas: 14617) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithDifferentTokensOnDifferentChains_Success() (gas: 210107) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithDisabledRateLimitToken_Success() (gas: 58416) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithNoTokens_Success() (gas: 17743) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitDisabled_Success() (gas: 45162) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitExceeded_Revert() (gas: 46370) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithRateLimitReset_Success() (gas: 76561) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithTokensOnDifferentChains_Success() (gas: 308233) +MultiAggregateRateLimiter_onInboundMessage:test_ValidateMessageWithTokens_Success() (gas: 50558) +MultiAggregateRateLimiter_onOutboundMessage:test_RateLimitValueDifferentLanes_Success() (gas: 1073669578) +MultiAggregateRateLimiter_onOutboundMessage:test_ValidateMessageWithNoTokens_Success() (gas: 19302) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageFromUnauthorizedCaller_Revert() (gas: 15913) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithDifferentTokensOnDifferentChains_Success() (gas: 209885) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithDisabledRateLimitToken_Success() (gas: 60182) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitDisabled_Success() (gas: 46935) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitExceeded_Revert() (gas: 48179) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithRateLimitReset_Success() (gas: 77728) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithTokensOnDifferentChains_Success() (gas: 308237) +MultiAggregateRateLimiter_onOutboundMessage:test_onOutboundMessage_ValidateMessageWithTokens_Success() (gas: 52346) +MultiAggregateRateLimiter_setFeeQuoter:test_OnlyOwner_Revert() (gas: 11337) +MultiAggregateRateLimiter_setFeeQuoter:test_Owner_Success() (gas: 19090) +MultiAggregateRateLimiter_setFeeQuoter:test_ZeroAddress_Revert() (gas: 10609) +MultiAggregateRateLimiter_updateRateLimitTokens:test_NonOwner_Revert() (gas: 18878) +MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokensMultipleChains_Success() (gas: 280256) +MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokensSingleChain_Success() (gas: 254729) +MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokens_AddsAndRemoves_Success() (gas: 204595) +MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokens_RemoveNonExistentToken_Success() (gas: 28826) +MultiAggregateRateLimiter_updateRateLimitTokens:test_ZeroDestToken_Revert() (gas: 18324) +MultiAggregateRateLimiter_updateRateLimitTokens:test_ZeroSourceToken_Revert() (gas: 18253) +MultiOCR3Base_setOCR3Configs:test_FMustBePositive_Revert() (gas: 59294) +MultiOCR3Base_setOCR3Configs:test_FTooHigh_Revert() (gas: 43671) +MultiOCR3Base_setOCR3Configs:test_RepeatSignerAddress_Revert() (gas: 283678) +MultiOCR3Base_setOCR3Configs:test_RepeatTransmitterAddress_Revert() (gas: 422303) +MultiOCR3Base_setOCR3Configs:test_SetConfigIgnoreSigners_Success() (gas: 511914) +MultiOCR3Base_setOCR3Configs:test_SetConfigWithSigners_Success() (gas: 828842) +MultiOCR3Base_setOCR3Configs:test_SetConfigWithoutSigners_Success() (gas: 457288) +MultiOCR3Base_setOCR3Configs:test_SetConfigsZeroInput_Success() (gas: 12481) +MultiOCR3Base_setOCR3Configs:test_SetMultipleConfigs_Success() (gas: 2141470) +MultiOCR3Base_setOCR3Configs:test_SignerCannotBeZeroAddress_Revert() (gas: 141777) +MultiOCR3Base_setOCR3Configs:test_StaticConfigChange_Revert() (gas: 807499) +MultiOCR3Base_setOCR3Configs:test_TooManySigners_Revert() (gas: 158841) +MultiOCR3Base_setOCR3Configs:test_TooManyTransmitters_Revert() (gas: 112335) +MultiOCR3Base_setOCR3Configs:test_TransmitterCannotBeZeroAddress_Revert() (gas: 254143) +MultiOCR3Base_setOCR3Configs:test_UpdateConfigSigners_Success() (gas: 861131) +MultiOCR3Base_setOCR3Configs:test_UpdateConfigTransmittersWithoutSigners_Success() (gas: 475810) +MultiOCR3Base_transmit:test_ConfigDigestMismatch_Revert() (gas: 42956) +MultiOCR3Base_transmit:test_ForkedChain_Revert() (gas: 48639) +MultiOCR3Base_transmit:test_InsufficientSignatures_Revert() (gas: 77138) +MultiOCR3Base_transmit:test_NonUniqueSignature_Revert() (gas: 65912) +MultiOCR3Base_transmit:test_SignatureOutOfRegistration_Revert() (gas: 33495) +MultiOCR3Base_transmit:test_TooManySignatures_Revert() (gas: 79795) +MultiOCR3Base_transmit:test_TransmitSigners_gas_Success() (gas: 33664) +MultiOCR3Base_transmit:test_TransmitWithExtraCalldataArgs_Revert() (gas: 47200) +MultiOCR3Base_transmit:test_TransmitWithLessCalldataArgs_Revert() (gas: 25768) +MultiOCR3Base_transmit:test_TransmitWithoutSignatureVerification_gas_Success() (gas: 18745) +MultiOCR3Base_transmit:test_UnAuthorizedTransmitter_Revert() (gas: 24234) +MultiOCR3Base_transmit:test_UnauthorizedSigner_Revert() (gas: 61275) +MultiOCR3Base_transmit:test_UnconfiguredPlugin_Revert() (gas: 39933) +MultiOCR3Base_transmit:test_ZeroSignatures_Revert() (gas: 33049) +MultiOnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 233745) +MultiRampsE2E:test_E2E_3MessagesMMultiOffRampSuccess_gas() (gas: 1542394) +NonceManager_NonceIncrementation:test_getIncrementedOutboundNonce_Success() (gas: 37934) +NonceManager_NonceIncrementation:test_incrementInboundNonce_Skip() (gas: 23721) +NonceManager_NonceIncrementation:test_incrementInboundNonce_Success() (gas: 38805) +NonceManager_NonceIncrementation:test_incrementNoncesInboundAndOutbound_Success() (gas: 71934) +NonceManager_OffRampUpgrade:test_NoPrevOffRampForChain_Success() (gas: 263674) +NonceManager_OffRampUpgrade:test_UpgradedNonceNewSenderStartsAtZero_Success() (gas: 267840) +NonceManager_OffRampUpgrade:test_UpgradedNonceStartsAtV1Nonce_Success() (gas: 333345) +NonceManager_OffRampUpgrade:test_UpgradedOffRampNonceSkipsIfMsgInFlight_Success() (gas: 303817) +NonceManager_OffRampUpgrade:test_UpgradedSenderNoncesReadsPreviousRampTransitive_Success() (gas: 249140) +NonceManager_OffRampUpgrade:test_UpgradedSenderNoncesReadsPreviousRamp_Success() (gas: 237047) +NonceManager_OffRampUpgrade:test_Upgraded_Success() (gas: 155247) +NonceManager_OnRampUpgrade:test_UpgradeNonceNewSenderStartsAtZero_Success() (gas: 169478) +NonceManager_OnRampUpgrade:test_UpgradeNonceStartsAtV1Nonce_Success() (gas: 222172) +NonceManager_OnRampUpgrade:test_UpgradeSenderNoncesReadsPreviousRamp_Success() (gas: 126858) +NonceManager_OnRampUpgrade:test_Upgrade_Success() (gas: 108239) +NonceManager_applyPreviousRampsUpdates:test_MultipleRampsUpdates() (gas: 123201) +NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySetOffRamp_Revert() (gas: 43073) +NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySetOnRampAndOffRamp_Revert() (gas: 64402) +NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySetOnRamp_Revert() (gas: 42937) +NonceManager_applyPreviousRampsUpdates:test_SingleRampUpdate() (gas: 66690) +NonceManager_applyPreviousRampsUpdates:test_ZeroInput() (gas: 12067) +NonceManager_typeAndVersion:test_typeAndVersion() (gas: 9705) +OCR2BaseNoChecks_setOCR2Config:test_FMustBePositive_Revert() (gas: 12210) +OCR2BaseNoChecks_setOCR2Config:test_RepeatAddress_Revert() (gas: 42431) +OCR2BaseNoChecks_setOCR2Config:test_SetConfigSuccess_gas() (gas: 84597) +OCR2BaseNoChecks_setOCR2Config:test_TooManyTransmitter_Revert() (gas: 38177) +OCR2BaseNoChecks_setOCR2Config:test_TransmitterCannotBeZeroAddress_Revert() (gas: 24308) +OCR2BaseNoChecks_transmit:test_ConfigDigestMismatch_Revert() (gas: 17499) +OCR2BaseNoChecks_transmit:test_ForkedChain_Revert() (gas: 26798) OCR2BaseNoChecks_transmit:test_TransmitSuccess_gas() (gas: 27499) -OCR2BaseNoChecks_transmit:test_UnAuthorizedTransmitter_Revert() (gas: 21317) -OCR2Base_setOCR2Config:test_FMustBePositive_Revert() (gas: 12201) -OCR2Base_setOCR2Config:test_FTooHigh_Revert() (gas: 12357) -OCR2Base_setOCR2Config:test_OracleOutOfRegister_Revert() (gas: 14904) -OCR2Base_setOCR2Config:test_RepeatAddress_Revert() (gas: 45454) -OCR2Base_setOCR2Config:test_SetConfigSuccess_gas() (gas: 155216) -OCR2Base_setOCR2Config:test_SingerCannotBeZeroAddress_Revert() (gas: 24413) -OCR2Base_setOCR2Config:test_TooManySigners_Revert() (gas: 20520) -OCR2Base_setOCR2Config:test_TransmitterCannotBeZeroAddress_Revert() (gas: 47304) -OCR2Base_transmit:test_ConfigDigestMismatch_Revert() (gas: 19644) -OCR2Base_transmit:test_ForkedChain_Revert() (gas: 37719) -OCR2Base_transmit:test_NonUniqueSignature_Revert() (gas: 55324) -OCR2Base_transmit:test_SignatureOutOfRegistration_Revert() (gas: 20977) +OCR2BaseNoChecks_transmit:test_UnAuthorizedTransmitter_Revert() (gas: 21335) +OCR2Base_setOCR2Config:test_FMustBePositive_Revert() (gas: 12216) +OCR2Base_setOCR2Config:test_FTooHigh_Revert() (gas: 12372) +OCR2Base_setOCR2Config:test_OracleOutOfRegister_Revert() (gas: 14919) +OCR2Base_setOCR2Config:test_RepeatAddress_Revert() (gas: 45469) +OCR2Base_setOCR2Config:test_SetConfigSuccess_gas() (gas: 155220) +OCR2Base_setOCR2Config:test_SingerCannotBeZeroAddress_Revert() (gas: 24425) +OCR2Base_setOCR2Config:test_TooManySigners_Revert() (gas: 20535) +OCR2Base_setOCR2Config:test_TransmitterCannotBeZeroAddress_Revert() (gas: 47316) +OCR2Base_transmit:test_ConfigDigestMismatch_Revert() (gas: 19668) +OCR2Base_transmit:test_ForkedChain_Revert() (gas: 37749) +OCR2Base_transmit:test_NonUniqueSignature_Revert() (gas: 55360) +OCR2Base_transmit:test_SignatureOutOfRegistration_Revert() (gas: 20989) OCR2Base_transmit:test_Transmit2SignersSuccess_gas() (gas: 51689) -OCR2Base_transmit:test_UnAuthorizedTransmitter_Revert() (gas: 23499) -OCR2Base_transmit:test_UnauthorizedSigner_Revert() (gas: 39695) -OCR2Base_transmit:test_WrongNumberOfSignatures_Revert() (gas: 20572) -OffRamp_afterOC3ConfigSet:test_afterOCR3ConfigSet_SignatureVerificationDisabled_Revert() (gas: 5983389) -OffRamp_applySourceChainConfigUpdates:test_AddMultipleChains_Success() (gas: 468168) -OffRamp_applySourceChainConfigUpdates:test_AddNewChain_Success() (gas: 99296) -OffRamp_applySourceChainConfigUpdates:test_ApplyZeroUpdates_Success() (gas: 12472) -OffRamp_applySourceChainConfigUpdates:test_InvalidOnRampUpdate_Revert() (gas: 204676) -OffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChainOnRamp_Success() (gas: 101379) -OffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChain_Success() (gas: 110796) -OffRamp_applySourceChainConfigUpdates:test_RouterAddress_Revert() (gas: 13418) -OffRamp_applySourceChainConfigUpdates:test_ZeroOnRampAddress_Revert() (gas: 72638) -OffRamp_applySourceChainConfigUpdates:test_ZeroSourceChainSelector_Revert() (gas: 15462) -OffRamp_batchExecute:test_MultipleReportsDifferentChainsSkipCursedChain_Success() (gas: 179216) -OffRamp_batchExecute:test_MultipleReportsDifferentChains_Success() (gas: 337235) -OffRamp_batchExecute:test_MultipleReportsSameChain_Success() (gas: 280603) -OffRamp_batchExecute:test_MultipleReportsSkipDuplicate_Success() (gas: 170311) -OffRamp_batchExecute:test_OutOfBoundsGasLimitsAccess_Revert() (gas: 190845) -OffRamp_batchExecute:test_SingleReport_Success() (gas: 157648) -OffRamp_batchExecute:test_Unhealthy_Success() (gas: 578050) -OffRamp_batchExecute:test_ZeroReports_Revert() (gas: 10576) -OffRamp_ccipReceive:test_Reverts() (gas: 15782) -OffRamp_commit:test_CommitOnRampMismatch_Revert() (gas: 92492) -OffRamp_commit:test_FailedRMNVerification_Reverts() (gas: 63748) -OffRamp_commit:test_InvalidIntervalMinLargerThanMax_Revert() (gas: 67769) -OffRamp_commit:test_InvalidInterval_Revert() (gas: 63936) -OffRamp_commit:test_InvalidRootRevert() (gas: 63009) -OffRamp_commit:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6587105) -OffRamp_commit:test_NoConfig_Revert() (gas: 6170887) -OffRamp_commit:test_OnlyGasPriceUpdates_Success() (gas: 112719) -OffRamp_commit:test_OnlyPriceUpdateStaleReport_Revert() (gas: 120939) -OffRamp_commit:test_OnlyTokenPriceUpdates_Success() (gas: 112740) -OffRamp_commit:test_PriceSequenceNumberCleared_Success() (gas: 354230) -OffRamp_commit:test_ReportAndPriceUpdate_Success() (gas: 163890) -OffRamp_commit:test_ReportOnlyRootSuccess_gas() (gas: 138880) -OffRamp_commit:test_RootAlreadyCommitted_Revert() (gas: 145911) -OffRamp_commit:test_SourceChainNotEnabled_Revert() (gas: 59492) -OffRamp_commit:test_StaleReportWithRoot_Success() (gas: 231183) -OffRamp_commit:test_UnauthorizedTransmitter_Revert() (gas: 124994) -OffRamp_commit:test_Unhealthy_Revert() (gas: 58244) -OffRamp_commit:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 205947) -OffRamp_commit:test_ZeroEpochAndRound_Revert() (gas: 51483) -OffRamp_constructor:test_Constructor_Success() (gas: 6170587) -OffRamp_constructor:test_SourceChainSelector_Revert() (gas: 135943) -OffRamp_constructor:test_ZeroChainSelector_Revert() (gas: 103386) -OffRamp_constructor:test_ZeroNonceManager_Revert() (gas: 101280) -OffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 161468) -OffRamp_constructor:test_ZeroRMNRemote_Revert() (gas: 101200) -OffRamp_constructor:test_ZeroTokenAdminRegistry_Revert() (gas: 101238) -OffRamp_execute:test_IncorrectArrayType_Revert() (gas: 17610) -OffRamp_execute:test_LargeBatch_Success() (gas: 3419182) -OffRamp_execute:test_MultipleReportsWithPartialValidationFailures_Success() (gas: 375374) -OffRamp_execute:test_MultipleReports_Success() (gas: 302902) -OffRamp_execute:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6996650) -OffRamp_execute:test_NoConfig_Revert() (gas: 6221351) -OffRamp_execute:test_NonArray_Revert() (gas: 27961) -OffRamp_execute:test_SingleReport_Success() (gas: 176939) -OffRamp_execute:test_UnauthorizedTransmitter_Revert() (gas: 149068) -OffRamp_execute:test_WrongConfigWithSigners_Revert() (gas: 6999426) -OffRamp_execute:test_ZeroReports_Revert() (gas: 17293) -OffRamp_executeSingleMessage:test_MessageSender_Revert() (gas: 18874) -OffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 248721) -OffRamp_executeSingleMessage:test_NonContract_Success() (gas: 21206) -OffRamp_executeSingleMessage:test_TokenHandlingError_Revert() (gas: 209803) -OffRamp_executeSingleMessage:test_ZeroGasDONExecution_Revert() (gas: 49525) -OffRamp_executeSingleMessage:test_executeSingleMessage_NoTokens_Success() (gas: 49013) -OffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidationNoRouterCall_Revert() (gas: 218730) -OffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidation_Revert() (gas: 85512) -OffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens_Success() (gas: 280659) -OffRamp_executeSingleMessage:test_executeSingleMessage_WithVInterception_Success() (gas: 91829) -OffRamp_executeSingleReport:test_DisabledSourceChain_Revert() (gas: 28730) -OffRamp_executeSingleReport:test_EmptyReport_Revert() (gas: 22018) -OffRamp_executeSingleReport:test_InvalidSourcePoolAddress_Success() (gas: 503897) -OffRamp_executeSingleReport:test_ManualExecutionNotYetEnabled_Revert() (gas: 49358) -OffRamp_executeSingleReport:test_MismatchingDestChainSelector_Revert() (gas: 34462) -OffRamp_executeSingleReport:test_NonExistingSourceChain_Revert() (gas: 28977) -OffRamp_executeSingleReport:test_ReceiverError_Success() (gas: 189608) -OffRamp_executeSingleReport:test_RetryFailedMessageWithoutManualExecution_Revert() (gas: 200597) -OffRamp_executeSingleReport:test_RootNotCommitted_Revert() (gas: 41727) -OffRamp_executeSingleReport:test_RouterYULCall_Revert() (gas: 449309) -OffRamp_executeSingleReport:test_SingleMessageNoTokensOtherChain_Success() (gas: 251345) -OffRamp_executeSingleReport:test_SingleMessageNoTokensUnordered_Success() (gas: 196311) -OffRamp_executeSingleReport:test_SingleMessageNoTokens_Success() (gas: 215860) -OffRamp_executeSingleReport:test_SingleMessageToNonCCIPReceiver_Success() (gas: 251303) -OffRamp_executeSingleReport:test_SingleMessagesNoTokensSuccess_gas() (gas: 142769) -OffRamp_executeSingleReport:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 426988) -OffRamp_executeSingleReport:test_SkippedIncorrectNonce_Success() (gas: 59801) -OffRamp_executeSingleReport:test_TokenDataMismatch_Revert() (gas: 74893) -OffRamp_executeSingleReport:test_TwoMessagesWithTokensAndGE_Success() (gas: 605297) -OffRamp_executeSingleReport:test_TwoMessagesWithTokensSuccess_gas() (gas: 548785) -OffRamp_executeSingleReport:test_UnexpectedTokenData_Revert() (gas: 34181) -OffRamp_executeSingleReport:test_UnhealthySingleChainCurse_Revert() (gas: 575250) -OffRamp_executeSingleReport:test_Unhealthy_Success() (gas: 575264) -OffRamp_executeSingleReport:test_WithCurseOnAnotherSourceChain_Success() (gas: 478001) -OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessageUnordered_Success() (gas: 138039) -OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessage_Success() (gas: 167264) -OffRamp_getExecutionState:test_FillExecutionState_Success() (gas: 3894518) -OffRamp_getExecutionState:test_GetDifferentChainExecutionState_Success() (gas: 120480) -OffRamp_getExecutionState:test_GetExecutionState_Success() (gas: 89540) -OffRamp_manuallyExecute:test_ManualExecGasLimitMismatchSingleReport_Revert() (gas: 81676) -OffRamp_manuallyExecute:test_manuallyExecute_DestinationGasAmountCountMismatch_Revert() (gas: 80532) -OffRamp_manuallyExecute:test_manuallyExecute_DoesNotRevertIfUntouched_Success() (gas: 174130) -OffRamp_manuallyExecute:test_manuallyExecute_FailedTx_Revert() (gas: 215543) -OffRamp_manuallyExecute:test_manuallyExecute_ForkedChain_Revert() (gas: 27365) -OffRamp_manuallyExecute:test_manuallyExecute_GasLimitMismatchMultipleReports_Revert() (gas: 165597) -OffRamp_manuallyExecute:test_manuallyExecute_InvalidReceiverExecutionGasLimit_Revert() (gas: 27936) -OffRamp_manuallyExecute:test_manuallyExecute_InvalidTokenGasOverride_Revert() (gas: 59666) -OffRamp_manuallyExecute:test_manuallyExecute_LowGasLimit_Success() (gas: 534293) -OffRamp_manuallyExecute:test_manuallyExecute_MultipleReportsWithSingleCursedLane_Revert() (gas: 321217) -OffRamp_manuallyExecute:test_manuallyExecute_ReentrancyFails_Success() (gas: 2393253) -OffRamp_manuallyExecute:test_manuallyExecute_SourceChainSelectorMismatch_Revert() (gas: 166568) -OffRamp_manuallyExecute:test_manuallyExecute_Success() (gas: 228525) -OffRamp_manuallyExecute:test_manuallyExecute_WithGasOverride_Success() (gas: 229065) -OffRamp_manuallyExecute:test_manuallyExecute_WithMultiReportGasOverride_Success() (gas: 788283) -OffRamp_manuallyExecute:test_manuallyExecute_WithPartialMessages_Success() (gas: 350237) -OffRamp_releaseOrMintSingleToken:test__releaseOrMintSingleToken_NotACompatiblePool_Revert() (gas: 40611) -OffRamp_releaseOrMintSingleToken:test__releaseOrMintSingleToken_Success() (gas: 105733) -OffRamp_releaseOrMintSingleToken:test__releaseOrMintSingleToken_TokenHandlingError_transfer_Revert() (gas: 86956) -OffRamp_releaseOrMintSingleToken:test_releaseOrMintToken_InvalidDataLength_Revert() (gas: 38380) -OffRamp_releaseOrMintSingleToken:test_releaseOrMintToken_ReleaseOrMintBalanceMismatch_Revert() (gas: 95983) -OffRamp_releaseOrMintSingleToken:test_releaseOrMintToken_TokenHandlingError_BalanceOf_Revert() (gas: 41378) -OffRamp_releaseOrMintSingleToken:test_releaseOrMintToken_skip_ReleaseOrMintBalanceMismatch_if_pool_Revert() (gas: 88177) -OffRamp_releaseOrMintTokens:test_TokenHandlingError_Reverts() (gas: 165433) -OffRamp_releaseOrMintTokens:test__releaseOrMintTokens_PoolIsNotAPool_Reverts() (gas: 25404) -OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_InvalidDataLengthReturnData_Revert() (gas: 65574) -OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_InvalidEVMAddress_Revert() (gas: 42279) -OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_PoolDoesNotSupportDest_Reverts() (gas: 82668) -OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_Success() (gas: 177447) -OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_WithGasOverride_Success() (gas: 179427) -OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals_Success() (gas: 190636) -OffRamp_setDynamicConfig:test_FeeQuoterZeroAddress_Revert() (gas: 11201) -OffRamp_setDynamicConfig:test_NonOwner_Revert() (gas: 13789) -OffRamp_setDynamicConfig:test_SetDynamicConfigWithInterceptor_Success() (gas: 46192) -OffRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 24234) -OffRamp_trialExecute:test_RateLimitError_Success() (gas: 226586) -OffRamp_trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 235208) -OffRamp_trialExecute:test_TokenPoolIsNotAContract_Success() (gas: 314371) -OffRamp_trialExecute:test_trialExecute_Success() (gas: 284928) -OnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 388215) -OnRamp_applyAllowListUpdates:test_applyAllowListUpdates_InvalidAllowListRequestDisabledAllowListWithAdds() (gas: 17758) -OnRamp_applyAllowListUpdates:test_applyAllowListUpdates_Revert() (gas: 66553) -OnRamp_applyAllowListUpdates:test_applyAllowListUpdates_Success() (gas: 323605) -OnRamp_applyDestChainConfigUpdates:test_ApplyDestChainConfigUpdates_Success() (gas: 64546) -OnRamp_applyDestChainConfigUpdates:test_ApplyDestChainConfigUpdates_WithInvalidChainSelector_Revert() (gas: 13254) -OnRamp_constructor:test_Constructor_InvalidConfigChainSelectorEqZero_Revert() (gas: 94823) -OnRamp_constructor:test_Constructor_InvalidConfigNonceManagerEqAddressZero_Revert() (gas: 92757) -OnRamp_constructor:test_Constructor_InvalidConfigRMNProxyEqAddressZero_Revert() (gas: 97783) -OnRamp_constructor:test_Constructor_InvalidConfigTokenAdminRegistryEqAddressZero_Revert() (gas: 92815) -OnRamp_constructor:test_Constructor_Success() (gas: 2817599) -OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() (gas: 114917) -OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2_Success() (gas: 145710) -OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessCustomExtraArgs() (gas: 145291) -OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessEmptyExtraArgs() (gas: 143538) -OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessLegacyExtraArgs() (gas: 145516) -OnRamp_forwardFromRouter:test_ForwardFromRouter_Success() (gas: 144895) -OnRamp_forwardFromRouter:test_ForwardFromRouter_Success_ConfigurableSourceRouter() (gas: 140292) -OnRamp_forwardFromRouter:test_InvalidExtraArgsTag_Revert() (gas: 28824) -OnRamp_forwardFromRouter:test_MessageInterceptionError_Revert() (gas: 138916) -OnRamp_forwardFromRouter:test_MesssageFeeTooHigh_Revert() (gas: 26924) -OnRamp_forwardFromRouter:test_MultiCannotSendZeroTokens_Revert() (gas: 74162) -OnRamp_forwardFromRouter:test_OriginalSender_Revert() (gas: 12995) -OnRamp_forwardFromRouter:test_Paused_Revert() (gas: 37361) -OnRamp_forwardFromRouter:test_Permissions_Revert() (gas: 18307) -OnRamp_forwardFromRouter:test_ShouldIncrementNonceOnlyOnOrdered_Success() (gas: 184585) -OnRamp_forwardFromRouter:test_ShouldIncrementSeqNumAndNonce_Success() (gas: 210880) -OnRamp_forwardFromRouter:test_ShouldStoreLinkFees() (gas: 124861) -OnRamp_forwardFromRouter:test_ShouldStoreNonLinkFees() (gas: 141462) -OnRamp_forwardFromRouter:test_SourceTokenDataTooLarge_Revert() (gas: 3769222) -OnRamp_forwardFromRouter:test_UnAllowedOriginalSender_Revert() (gas: 18714) -OnRamp_forwardFromRouter:test_UnsupportedToken_Revert() (gas: 110897) -OnRamp_forwardFromRouter:test_forwardFromRouter_UnsupportedToken_Revert() (gas: 76213) -OnRamp_forwardFromRouter:test_forwardFromRouter_WithInterception_Success() (gas: 281260) -OnRamp_getFee:test_EmptyMessage_Success() (gas: 97734) -OnRamp_getFee:test_EnforceOutOfOrder_Revert() (gas: 64215) -OnRamp_getFee:test_GetFeeOfZeroForTokenMessage_Success() (gas: 85428) -OnRamp_getFee:test_NotAFeeTokenButPricedToken_Revert() (gas: 34978) -OnRamp_getFee:test_SingleTokenMessage_Success() (gas: 112749) -OnRamp_getFee:test_Unhealthy_Revert() (gas: 17021) -OnRamp_getSupportedTokens:test_GetSupportedTokens_Revert() (gas: 10438) -OnRamp_getTokenPool:test_GetTokenPool_Success() (gas: 35204) -OnRamp_setDynamicConfig:test_SetConfigInvalidConfigFeeAggregatorEqAddressZero_Revert() (gas: 11420) -OnRamp_setDynamicConfig:test_SetConfigInvalidConfigFeeQuoterEqAddressZero_Revert() (gas: 13019) -OnRamp_setDynamicConfig:test_SetConfigInvalidConfig_Revert() (gas: 11377) -OnRamp_setDynamicConfig:test_SetConfigOnlyOwner_Revert() (gas: 16421) -OnRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 55330) -OnRamp_withdrawFeeTokens:test_WithdrawFeeTokens_Success() (gas: 97235) -PingPong_ccipReceive:test_CcipReceive_Success() (gas: 150719) -PingPong_plumbing:test_OutOfOrderExecution_Success() (gas: 20286) -PingPong_plumbing:test_Pausing_Success() (gas: 17786) -PingPong_startPingPong:test_StartPingPong_With_OOO_Success() (gas: 161185) -PingPong_startPingPong:test_StartPingPong_With_Sequenced_Ordered_Success() (gas: 180603) +OCR2Base_transmit:test_UnAuthorizedTransmitter_Revert() (gas: 23511) +OCR2Base_transmit:test_UnauthorizedSigner_Revert() (gas: 39707) +OCR2Base_transmit:test_WrongNumberOfSignatures_Revert() (gas: 20584) +OffRamp_afterOC3ConfigSet:test_afterOCR3ConfigSet_SignatureVerificationDisabled_Revert() (gas: 5711320) +OffRamp_applySourceChainConfigUpdates:test_AddMultipleChains_Success() (gas: 469413) +OffRamp_applySourceChainConfigUpdates:test_AddNewChain_Success() (gas: 99659) +OffRamp_applySourceChainConfigUpdates:test_ApplyZeroUpdates_Success() (gas: 12613) +OffRamp_applySourceChainConfigUpdates:test_InvalidOnRampUpdate_Revert() (gas: 205048) +OffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChainOnRamp_Success() (gas: 101481) +OffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChain_Success() (gas: 111351) +OffRamp_applySourceChainConfigUpdates:test_RouterAddress_Revert() (gas: 13463) +OffRamp_applySourceChainConfigUpdates:test_ZeroOnRampAddress_Revert() (gas: 72746) +OffRamp_applySourceChainConfigUpdates:test_ZeroSourceChainSelector_Revert() (gas: 15519) +OffRamp_batchExecute:test_MultipleReportsDifferentChainsSkipCursedChain_Success() (gas: 180443) +OffRamp_batchExecute:test_MultipleReportsDifferentChains_Success() (gas: 340118) +OffRamp_batchExecute:test_MultipleReportsSameChain_Success() (gas: 283384) +OffRamp_batchExecute:test_MultipleReportsSkipDuplicate_Success() (gas: 171325) +OffRamp_batchExecute:test_OutOfBoundsGasLimitsAccess_Revert() (gas: 191523) +OffRamp_batchExecute:test_SingleReport_Success() (gas: 158623) +OffRamp_batchExecute:test_Unhealthy_Success() (gas: 581440) +OffRamp_batchExecute:test_ZeroReports_Revert() (gas: 10621) +OffRamp_ccipReceive:test_Reverts() (gas: 15884) +OffRamp_commit:test_CommitOnRampMismatch_Revert() (gas: 92593) +OffRamp_commit:test_FailedRMNVerification_Reverts() (gas: 63787) +OffRamp_commit:test_InvalidIntervalMinLargerThanMax_Revert() (gas: 67826) +OffRamp_commit:test_InvalidInterval_Revert() (gas: 63993) +OffRamp_commit:test_InvalidRootRevert() (gas: 63066) +OffRamp_commit:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6315259) +OffRamp_commit:test_NoConfig_Revert() (gas: 5898957) +OffRamp_commit:test_OnlyGasPriceUpdates_Success() (gas: 112835) +OffRamp_commit:test_OnlyPriceUpdateStaleReport_Revert() (gas: 121022) +OffRamp_commit:test_OnlyTokenPriceUpdates_Success() (gas: 112856) +OffRamp_commit:test_PriceSequenceNumberCleared_Success() (gas: 354720) +OffRamp_commit:test_ReportAndPriceUpdate_Success() (gas: 164033) +OffRamp_commit:test_ReportOnlyRootSuccess_gas() (gas: 139030) +OffRamp_commit:test_RootAlreadyCommitted_Revert() (gas: 145995) +OffRamp_commit:test_SourceChainNotEnabled_Revert() (gas: 59555) +OffRamp_commit:test_StaleReportWithRoot_Success() (gas: 231426) +OffRamp_commit:test_UnauthorizedTransmitter_Revert() (gas: 125104) +OffRamp_commit:test_Unhealthy_Revert() (gas: 58334) +OffRamp_commit:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 206207) +OffRamp_commit:test_ZeroEpochAndRound_Revert() (gas: 51522) +OffRamp_constructor:test_Constructor_Success() (gas: 5900076) +OffRamp_constructor:test_SourceChainSelector_Revert() (gas: 135592) +OffRamp_constructor:test_ZeroChainSelector_Revert() (gas: 103026) +OffRamp_constructor:test_ZeroNonceManager_Revert() (gas: 100920) +OffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 161117) +OffRamp_constructor:test_ZeroRMNRemote_Revert() (gas: 100840) +OffRamp_constructor:test_ZeroTokenAdminRegistry_Revert() (gas: 100878) +OffRamp_execute:test_IncorrectArrayType_Revert() (gas: 17643) +OffRamp_execute:test_LargeBatch_Success() (gas: 3479707) +OffRamp_execute:test_MultipleReportsWithPartialValidationFailures_Success() (gas: 377669) +OffRamp_execute:test_MultipleReports_Success() (gas: 305677) +OffRamp_execute:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6725435) +OffRamp_execute:test_NoConfig_Revert() (gas: 5949968) +OffRamp_execute:test_NonArray_Revert() (gas: 28081) +OffRamp_execute:test_SingleReport_Success() (gas: 177908) +OffRamp_execute:test_UnauthorizedTransmitter_Revert() (gas: 149413) +OffRamp_execute:test_WrongConfigWithSigners_Revert() (gas: 6728184) +OffRamp_execute:test_ZeroReports_Revert() (gas: 17365) +OffRamp_executeSingleMessage:test_MessageSender_Revert() (gas: 19042) +OffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 249246) +OffRamp_executeSingleMessage:test_NonContract_Success() (gas: 21290) +OffRamp_executeSingleMessage:test_TokenHandlingError_Revert() (gas: 210286) +OffRamp_executeSingleMessage:test_ZeroGasDONExecution_Revert() (gas: 49816) +OffRamp_executeSingleMessage:test_executeSingleMessage_NoTokens_Success() (gas: 49259) +OffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidationNoRouterCall_Revert() (gas: 219024) +OffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidation_Revert() (gas: 85782) +OffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens_Success() (gas: 281397) +OffRamp_executeSingleMessage:test_executeSingleMessage_WithVInterception_Success() (gas: 92210) +OffRamp_executeSingleReport:test_DisabledSourceChain_Revert() (gas: 28775) +OffRamp_executeSingleReport:test_EmptyReport_Revert() (gas: 22063) +OffRamp_executeSingleReport:test_InvalidSourcePoolAddress_Success() (gas: 504821) +OffRamp_executeSingleReport:test_ManualExecutionNotYetEnabled_Revert() (gas: 49409) +OffRamp_executeSingleReport:test_MismatchingDestChainSelector_Revert() (gas: 34474) +OffRamp_executeSingleReport:test_NonExistingSourceChain_Revert() (gas: 29022) +OffRamp_executeSingleReport:test_ReceiverError_Success() (gas: 190142) +OffRamp_executeSingleReport:test_RetryFailedMessageWithoutManualExecution_Revert() (gas: 201092) +OffRamp_executeSingleReport:test_RootNotCommitted_Revert() (gas: 41778) +OffRamp_executeSingleReport:test_RouterYULCall_Revert() (gas: 415283) +OffRamp_executeSingleReport:test_SingleMessageNoTokensOtherChain_Success() (gas: 251849) +OffRamp_executeSingleReport:test_SingleMessageNoTokensUnordered_Success() (gas: 197205) +OffRamp_executeSingleReport:test_SingleMessageNoTokens_Success() (gas: 216715) +OffRamp_executeSingleReport:test_SingleMessageToNonCCIPReceiver_Success() (gas: 251588) +OffRamp_executeSingleReport:test_SingleMessagesNoTokensSuccess_gas() (gas: 143177) +OffRamp_executeSingleReport:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 427792) +OffRamp_executeSingleReport:test_SkippedIncorrectNonce_Success() (gas: 59840) +OffRamp_executeSingleReport:test_TokenDataMismatch_Revert() (gas: 74905) +OffRamp_executeSingleReport:test_TwoMessagesWithTokensAndGE_Success() (gas: 606911) +OffRamp_executeSingleReport:test_TwoMessagesWithTokensSuccess_gas() (gas: 550321) +OffRamp_executeSingleReport:test_UnexpectedTokenData_Revert() (gas: 34232) +OffRamp_executeSingleReport:test_UnhealthySingleChainCurse_Revert() (gas: 577092) +OffRamp_executeSingleReport:test_Unhealthy_Success() (gas: 577106) +OffRamp_executeSingleReport:test_WithCurseOnAnotherSourceChain_Success() (gas: 479102) +OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessageUnordered_Success() (gas: 138486) +OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessage_Success() (gas: 167678) +OffRamp_getExecutionState:test_FillExecutionState_Success() (gas: 3936242) +OffRamp_getExecutionState:test_GetDifferentChainExecutionState_Success() (gas: 120870) +OffRamp_getExecutionState:test_GetExecutionState_Success() (gas: 89684) +OffRamp_manuallyExecute:test_ManualExecGasLimitMismatchSingleReport_Revert() (gas: 82048) +OffRamp_manuallyExecute:test_manuallyExecute_DestinationGasAmountCountMismatch_Revert() (gas: 80838) +OffRamp_manuallyExecute:test_manuallyExecute_DoesNotRevertIfUntouched_Success() (gas: 175234) +OffRamp_manuallyExecute:test_manuallyExecute_FailedTx_Revert() (gas: 216194) +OffRamp_manuallyExecute:test_manuallyExecute_ForkedChain_Revert() (gas: 27599) +OffRamp_manuallyExecute:test_manuallyExecute_GasLimitMismatchMultipleReports_Revert() (gas: 166251) +OffRamp_manuallyExecute:test_manuallyExecute_InvalidReceiverExecutionGasLimit_Revert() (gas: 28137) +OffRamp_manuallyExecute:test_manuallyExecute_InvalidTokenGasOverride_Revert() (gas: 59861) +OffRamp_manuallyExecute:test_manuallyExecute_LowGasLimit_Success() (gas: 501650) +OffRamp_manuallyExecute:test_manuallyExecute_MultipleReportsWithSingleCursedLane_Revert() (gas: 322849) +OffRamp_manuallyExecute:test_manuallyExecute_ReentrancyFails_Success() (gas: 2354253) +OffRamp_manuallyExecute:test_manuallyExecute_SourceChainSelectorMismatch_Revert() (gas: 167081) +OffRamp_manuallyExecute:test_manuallyExecute_Success() (gas: 229749) +OffRamp_manuallyExecute:test_manuallyExecute_WithGasOverride_Success() (gas: 230289) +OffRamp_manuallyExecute:test_manuallyExecute_WithMultiReportGasOverride_Success() (gas: 794511) +OffRamp_manuallyExecute:test_manuallyExecute_WithPartialMessages_Success() (gas: 353603) +OffRamp_releaseOrMintSingleToken:test__releaseOrMintSingleToken_NotACompatiblePool_Revert() (gas: 40854) +OffRamp_releaseOrMintSingleToken:test__releaseOrMintSingleToken_Success() (gas: 105958) +OffRamp_releaseOrMintSingleToken:test__releaseOrMintSingleToken_TokenHandlingError_transfer_Revert() (gas: 87217) +OffRamp_releaseOrMintSingleToken:test_releaseOrMintToken_InvalidDataLength_Revert() (gas: 38554) +OffRamp_releaseOrMintSingleToken:test_releaseOrMintToken_ReleaseOrMintBalanceMismatch_Revert() (gas: 96196) +OffRamp_releaseOrMintSingleToken:test_releaseOrMintToken_TokenHandlingError_BalanceOf_Revert() (gas: 41546) +OffRamp_releaseOrMintSingleToken:test_releaseOrMintToken_skip_ReleaseOrMintBalanceMismatch_if_pool_Revert() (gas: 88339) +OffRamp_releaseOrMintTokens:test_TokenHandlingError_Reverts() (gas: 165892) +OffRamp_releaseOrMintTokens:test__releaseOrMintTokens_PoolIsNotAPool_Reverts() (gas: 25497) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_InvalidDataLengthReturnData_Revert() (gas: 65805) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_InvalidEVMAddress_Revert() (gas: 42396) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_PoolDoesNotSupportDest_Reverts() (gas: 82866) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_Success() (gas: 177978) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_WithGasOverride_Success() (gas: 179970) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals_Success() (gas: 191188) +OffRamp_setDynamicConfig:test_FeeQuoterZeroAddress_Revert() (gas: 11246) +OffRamp_setDynamicConfig:test_NonOwner_Revert() (gas: 13861) +OffRamp_setDynamicConfig:test_SetDynamicConfigWithInterceptor_Success() (gas: 46354) +OffRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 24396) +OffRamp_trialExecute:test_RateLimitError_Success() (gas: 227084) +OffRamp_trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 235706) +OffRamp_trialExecute:test_TokenPoolIsNotAContract_Success() (gas: 315277) +OffRamp_trialExecute:test_trialExecute_Success() (gas: 285609) +OnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 390842) +OnRamp_applyAllowListUpdates:test_applyAllowListUpdates_InvalidAllowListRequestDisabledAllowListWithAdds() (gas: 18030) +OnRamp_applyAllowListUpdates:test_applyAllowListUpdates_Revert() (gas: 67429) +OnRamp_applyAllowListUpdates:test_applyAllowListUpdates_Success() (gas: 325126) +OnRamp_applyDestChainConfigUpdates:test_ApplyDestChainConfigUpdates_Success() (gas: 65230) +OnRamp_applyDestChainConfigUpdates:test_ApplyDestChainConfigUpdates_WithInvalidChainSelector_Revert() (gas: 13446) +OnRamp_constructor:test_Constructor_InvalidConfigChainSelectorEqZero_Revert() (gas: 95056) +OnRamp_constructor:test_Constructor_InvalidConfigNonceManagerEqAddressZero_Revert() (gas: 92998) +OnRamp_constructor:test_Constructor_InvalidConfigRMNProxyEqAddressZero_Revert() (gas: 98031) +OnRamp_constructor:test_Constructor_InvalidConfigTokenAdminRegistryEqAddressZero_Revert() (gas: 93054) +OnRamp_constructor:test_Constructor_Success() (gas: 2759290) +OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() (gas: 115668) +OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2_Success() (gas: 146491) +OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessCustomExtraArgs() (gas: 146066) +OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessEmptyExtraArgs() (gas: 144306) +OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessLegacyExtraArgs() (gas: 146285) +OnRamp_forwardFromRouter:test_ForwardFromRouter_Success() (gas: 145664) +OnRamp_forwardFromRouter:test_ForwardFromRouter_Success_ConfigurableSourceRouter() (gas: 146249) +OnRamp_forwardFromRouter:test_InvalidExtraArgsTag_Revert() (gas: 38615) +OnRamp_forwardFromRouter:test_MessageInterceptionError_Revert() (gas: 143071) +OnRamp_forwardFromRouter:test_MesssageFeeTooHigh_Revert() (gas: 36739) +OnRamp_forwardFromRouter:test_MultiCannotSendZeroTokens_Revert() (gas: 36473) +OnRamp_forwardFromRouter:test_OriginalSender_Revert() (gas: 18291) +OnRamp_forwardFromRouter:test_Paused_Revert() (gas: 38454) +OnRamp_forwardFromRouter:test_Permissions_Revert() (gas: 23663) +OnRamp_forwardFromRouter:test_ShouldIncrementNonceOnlyOnOrdered_Success() (gas: 187735) +OnRamp_forwardFromRouter:test_ShouldIncrementSeqNumAndNonce_Success() (gas: 214120) +OnRamp_forwardFromRouter:test_ShouldStoreLinkFees() (gas: 125405) +OnRamp_forwardFromRouter:test_ShouldStoreNonLinkFees() (gas: 142036) +OnRamp_forwardFromRouter:test_SourceTokenDataTooLarge_Revert() (gas: 3623626) +OnRamp_forwardFromRouter:test_UnAllowedOriginalSender_Revert() (gas: 24010) +OnRamp_forwardFromRouter:test_UnsupportedToken_Revert() (gas: 75790) +OnRamp_forwardFromRouter:test_forwardFromRouter_UnsupportedToken_Revert() (gas: 38523) +OnRamp_forwardFromRouter:test_forwardFromRouter_WithInterception_Success() (gas: 282956) +OnRamp_getFee:test_EmptyMessage_Success() (gas: 98760) +OnRamp_getFee:test_EnforceOutOfOrder_Revert() (gas: 64779) +OnRamp_getFee:test_GetFeeOfZeroForTokenMessage_Success() (gas: 86359) +OnRamp_getFee:test_NotAFeeTokenButPricedToken_Revert() (gas: 35185) +OnRamp_getFee:test_SingleTokenMessage_Success() (gas: 113919) +OnRamp_getFee:test_Unhealthy_Revert() (gas: 17171) +OnRamp_getSupportedTokens:test_GetSupportedTokens_Revert() (gas: 10510) +OnRamp_getTokenPool:test_GetTokenPool_Success() (gas: 35372) +OnRamp_setDynamicConfig:test_setDynamicConfig_InvalidConfigFeeAggregatorEqAddressZero_Revert() (gas: 11581) +OnRamp_setDynamicConfig:test_setDynamicConfig_InvalidConfigFeeQuoterEqAddressZero_Revert() (gas: 13195) +OnRamp_setDynamicConfig:test_setDynamicConfig_InvalidConfigInvalidConfig_Revert() (gas: 11522) +OnRamp_setDynamicConfig:test_setDynamicConfig_InvalidConfigOnlyOwner_Revert() (gas: 16850) +OnRamp_setDynamicConfig:test_setDynamicConfig_InvalidConfigReentrancyGuardEnteredEqTrue_Revert() (gas: 13265) +OnRamp_setDynamicConfig:test_setDynamicConfig_Success() (gas: 56460) +OnRamp_withdrawFeeTokens:test_WithdrawFeeTokens_Success() (gas: 97290) +PingPong_ccipReceive:test_CcipReceive_Success() (gas: 151349) +PingPong_plumbing:test_OutOfOrderExecution_Success() (gas: 20310) +PingPong_plumbing:test_Pausing_Success() (gas: 17810) +PingPong_startPingPong:test_StartPingPong_With_OOO_Success() (gas: 162091) +PingPong_startPingPong:test_StartPingPong_With_Sequenced_Ordered_Success() (gas: 181509) RMNHome:test() (gas: 186) -RMN_constructor:test_Constructor_Success() (gas: 48874) -RMN_getRecordedCurseRelatedOps:test_OpsPostDeployment() (gas: 19696) -RMN_lazyVoteToCurseUpdate_Benchmark:test_VoteToCurseLazilyRetain3VotersUponConfigChange_gas() (gas: 152287) -RMN_ownerUnbless:test_Unbless_Success() (gas: 74900) -RMN_ownerUnvoteToCurse:test_CanBlessAndCurseAfterGlobalCurseIsLifted() (gas: 471574) -RMN_ownerUnvoteToCurse:test_IsIdempotent() (gas: 398222) -RMN_ownerUnvoteToCurse:test_NonOwner_Revert() (gas: 18669) -RMN_ownerUnvoteToCurse:test_OwnerUnvoteToCurseSuccess_gas() (gas: 357841) -RMN_ownerUnvoteToCurse:test_UnknownVoter_Revert() (gas: 33058) -RMN_ownerUnvoteToCurse_Benchmark:test_OwnerUnvoteToCurse_1Voter_LiftsCurse_gas() (gas: 262247) -RMN_permaBlessing:test_PermaBlessing() (gas: 202691) -RMN_setConfig:test_BlessVoterIsZeroAddress_Revert() (gas: 15494) -RMN_setConfig:test_EitherThresholdIsZero_Revert() (gas: 21095) +RMN_constructor:test_Constructor_Success() (gas: 48994) +RMN_getRecordedCurseRelatedOps:test_OpsPostDeployment() (gas: 19732) +RMN_lazyVoteToCurseUpdate_Benchmark:test_VoteToCurseLazilyRetain3VotersUponConfigChange_gas() (gas: 152296) +RMN_ownerUnbless:test_Unbless_Success() (gas: 74936) +RMN_ownerUnvoteToCurse:test_CanBlessAndCurseAfterGlobalCurseIsLifted() (gas: 471829) +RMN_ownerUnvoteToCurse:test_IsIdempotent() (gas: 398492) +RMN_ownerUnvoteToCurse:test_NonOwner_Revert() (gas: 18723) +RMN_ownerUnvoteToCurse:test_OwnerUnvoteToCurseSuccess_gas() (gas: 358084) +RMN_ownerUnvoteToCurse:test_UnknownVoter_Revert() (gas: 33190) +RMN_ownerUnvoteToCurse_Benchmark:test_OwnerUnvoteToCurse_1Voter_LiftsCurse_gas() (gas: 262408) +RMN_permaBlessing:test_PermaBlessing() (gas: 202777) +RMN_setConfig:test_BlessVoterIsZeroAddress_Revert() (gas: 15500) +RMN_setConfig:test_EitherThresholdIsZero_Revert() (gas: 21107) RMN_setConfig:test_NonOwner_Revert() (gas: 14725) -RMN_setConfig:test_RepeatedAddress_Revert() (gas: 18213) -RMN_setConfig:test_SetConfigSuccess_gas() (gas: 104089) -RMN_setConfig:test_TotalWeightsSmallerThanEachThreshold_Revert() (gas: 30173) -RMN_setConfig:test_VoteToBlessByEjectedVoter_Revert() (gas: 130377) -RMN_setConfig:test_VotersLengthIsZero_Revert() (gas: 12128) -RMN_setConfig:test_WeightIsZeroAddress_Revert() (gas: 15734) -RMN_setConfig_Benchmark_1:test_SetConfig_7Voters_gas() (gas: 659495) -RMN_setConfig_Benchmark_2:test_ResetConfig_7Voters_gas() (gas: 212511) +RMN_setConfig:test_RepeatedAddress_Revert() (gas: 18219) +RMN_setConfig:test_SetConfigSuccess_gas() (gas: 104154) +RMN_setConfig:test_TotalWeightsSmallerThanEachThreshold_Revert() (gas: 30185) +RMN_setConfig:test_VoteToBlessByEjectedVoter_Revert() (gas: 130461) +RMN_setConfig:test_VotersLengthIsZero_Revert() (gas: 12149) +RMN_setConfig:test_WeightIsZeroAddress_Revert() (gas: 15740) +RMN_setConfig_Benchmark_1:test_SetConfig_7Voters_gas() (gas: 659600) +RMN_setConfig_Benchmark_2:test_ResetConfig_7Voters_gas() (gas: 212652) RMN_unvoteToCurse:test_InvalidCursesHash() (gas: 26430) RMN_unvoteToCurse:test_OwnerSkips() (gas: 33831) -RMN_unvoteToCurse:test_OwnerSucceeds() (gas: 63999) -RMN_unvoteToCurse:test_UnauthorizedVoter() (gas: 47634) -RMN_unvoteToCurse:test_ValidCursesHash() (gas: 61139) -RMN_unvoteToCurse:test_VotersCantLiftCurseButOwnerCan() (gas: 628827) -RMN_voteToBless:test_Curse_Revert() (gas: 473342) -RMN_voteToBless:test_IsAlreadyBlessed_Revert() (gas: 115339) -RMN_voteToBless:test_RootSuccess() (gas: 558469) -RMN_voteToBless:test_SenderAlreadyVoted_Revert() (gas: 97204) -RMN_voteToBless:test_UnauthorizedVoter_Revert() (gas: 17096) -RMN_voteToBless_Benchmark:test_1RootSuccess_gas() (gas: 44706) -RMN_voteToBless_Benchmark:test_3RootSuccess_gas() (gas: 98682) -RMN_voteToBless_Benchmark:test_5RootSuccess_gas() (gas: 152596) -RMN_voteToBless_Blessed_Benchmark:test_1RootSuccessBecameBlessed_gas() (gas: 29676) -RMN_voteToBless_Blessed_Benchmark:test_1RootSuccess_gas() (gas: 27622) -RMN_voteToBless_Blessed_Benchmark:test_3RootSuccess_gas() (gas: 81620) -RMN_voteToBless_Blessed_Benchmark:test_5RootSuccess_gas() (gas: 135512) -RMN_voteToCurse:test_CurseOnlyWhenThresholdReached_Success() (gas: 1651029) -RMN_voteToCurse:test_EmptySubjects_Revert() (gas: 14055) -RMN_voteToCurse:test_EvenIfAlreadyCursed_Success() (gas: 535106) -RMN_voteToCurse:test_OwnerCanCurseAndUncurse() (gas: 399724) -RMN_voteToCurse:test_RepeatedSubject_Revert() (gas: 144396) -RMN_voteToCurse:test_ReusedCurseId_Revert() (gas: 146963) -RMN_voteToCurse:test_UnauthorizedVoter_Revert() (gas: 12660) -RMN_voteToCurse:test_VoteToCurse_NoCurse_Success() (gas: 187466) -RMN_voteToCurse:test_VoteToCurse_YesCurse_Success() (gas: 473034) -RMN_voteToCurse_2:test_VotesAreDroppedIfSubjectIsNotCursedDuringConfigChange() (gas: 370924) -RMN_voteToCurse_2:test_VotesAreRetainedIfSubjectIsCursedDuringConfigChange() (gas: 1153719) -RMN_voteToCurse_Benchmark_1:test_VoteToCurse_NewSubject_NewVoter_NoCurse_gas() (gas: 141103) -RMN_voteToCurse_Benchmark_1:test_VoteToCurse_NewSubject_NewVoter_YesCurse_gas() (gas: 165243) -RMN_voteToCurse_Benchmark_2:test_VoteToCurse_OldSubject_NewVoter_NoCurse_gas() (gas: 121431) -RMN_voteToCurse_Benchmark_2:test_VoteToCurse_OldSubject_OldVoter_NoCurse_gas() (gas: 98367) -RMN_voteToCurse_Benchmark_3:test_VoteToCurse_OldSubject_NewVoter_YesCurse_gas() (gas: 145778) -RateLimiter_constructor:test_Constructor_Success() (gas: 19704) -RateLimiter_consume:test_AggregateValueMaxCapacityExceeded_Revert() (gas: 16012) -RateLimiter_consume:test_AggregateValueRateLimitReached_Revert() (gas: 22345) -RateLimiter_consume:test_ConsumeAggregateValue_Success() (gas: 31443) -RateLimiter_consume:test_ConsumeTokens_Success() (gas: 20366) -RateLimiter_consume:test_ConsumeUnlimited_Success() (gas: 40585) -RateLimiter_consume:test_ConsumingMoreThanUint128_Revert() (gas: 15792) -RateLimiter_consume:test_RateLimitReachedOverConsecutiveBlocks_Revert() (gas: 25747) -RateLimiter_consume:test_Refill_Success() (gas: 37354) -RateLimiter_consume:test_TokenMaxCapacityExceeded_Revert() (gas: 18340) -RateLimiter_consume:test_TokenRateLimitReached_Revert() (gas: 24823) -RateLimiter_currentTokenBucketState:test_CurrentTokenBucketState_Success() (gas: 38884) -RateLimiter_currentTokenBucketState:test_Refill_Success() (gas: 46777) -RateLimiter_setTokenBucketConfig:test_SetRateLimiterConfig_Success() (gas: 38449) -RegistryModuleOwnerCustom_constructor:test_constructor_Revert() (gas: 36037) -RegistryModuleOwnerCustom_registerAdminViaGetCCIPAdmin:test_registerAdminViaGetCCIPAdmin_Revert() (gas: 19655) -RegistryModuleOwnerCustom_registerAdminViaGetCCIPAdmin:test_registerAdminViaGetCCIPAdmin_Success() (gas: 129978) -RegistryModuleOwnerCustom_registerAdminViaOwner:test_registerAdminViaOwner_Revert() (gas: 19475) -RegistryModuleOwnerCustom_registerAdminViaOwner:test_registerAdminViaOwner_Success() (gas: 129797) -Router_applyRampUpdates:test_OffRampMismatch_Revert() (gas: 89321) -Router_applyRampUpdates:test_OffRampUpdatesWithRouting() (gas: 10652272) -Router_applyRampUpdates:test_OnRampDisable() (gas: 55971) -Router_applyRampUpdates:test_OnlyOwner_Revert() (gas: 12317) -Router_ccipSend:test_CCIPSendLinkFeeNoTokenSuccess_gas() (gas: 114017) -Router_ccipSend:test_CCIPSendLinkFeeOneTokenSuccess_gas() (gas: 201533) -Router_ccipSend:test_CCIPSendNativeFeeNoTokenSuccess_gas() (gas: 126386) -Router_ccipSend:test_CCIPSendNativeFeeOneTokenSuccess_gas() (gas: 213904) -Router_ccipSend:test_FeeTokenAmountTooLow_Revert() (gas: 64241) -Router_ccipSend:test_InvalidMsgValue() (gas: 32014) -Router_ccipSend:test_NativeFeeTokenInsufficientValue() (gas: 66706) -Router_ccipSend:test_NativeFeeTokenOverpay_Success() (gas: 169401) -Router_ccipSend:test_NativeFeeTokenZeroValue() (gas: 53982) -Router_ccipSend:test_NativeFeeToken_Success() (gas: 167995) -Router_ccipSend:test_NonLinkFeeToken_Success() (gas: 238462) -Router_ccipSend:test_UnsupportedDestinationChain_Revert() (gas: 24767) -Router_ccipSend:test_WhenNotHealthy_Revert() (gas: 44742) -Router_ccipSend:test_WrappedNativeFeeToken_Success() (gas: 170253) -Router_ccipSend:test_ZeroFeeAndGasPrice_Success() (gas: 240550) -Router_constructor:test_Constructor_Success() (gas: 13070) -Router_getArmProxy:test_getArmProxy() (gas: 10561) -Router_getFee:test_GetFeeSupportedChain_Success() (gas: 44415) -Router_getFee:test_UnsupportedDestinationChain_Revert() (gas: 17156) -Router_getSupportedTokens:test_GetSupportedTokens_Revert() (gas: 10460) -Router_recoverTokens:test_RecoverTokensInvalidRecipient_Revert() (gas: 11322) -Router_recoverTokens:test_RecoverTokensNoFunds_Revert() (gas: 20261) +RMN_unvoteToCurse:test_OwnerSucceeds() (gas: 64005) +RMN_unvoteToCurse:test_UnauthorizedVoter() (gas: 47715) +RMN_unvoteToCurse:test_ValidCursesHash() (gas: 61145) +RMN_unvoteToCurse:test_VotersCantLiftCurseButOwnerCan() (gas: 629190) +RMN_voteToBless:test_Curse_Revert() (gas: 473408) +RMN_voteToBless:test_IsAlreadyBlessed_Revert() (gas: 115435) +RMN_voteToBless:test_RootSuccess() (gas: 558661) +RMN_voteToBless:test_SenderAlreadyVoted_Revert() (gas: 97234) +RMN_voteToBless:test_UnauthorizedVoter_Revert() (gas: 17126) +RMN_voteToBless_Benchmark:test_1RootSuccess_gas() (gas: 44718) +RMN_voteToBless_Benchmark:test_3RootSuccess_gas() (gas: 98694) +RMN_voteToBless_Benchmark:test_5RootSuccess_gas() (gas: 152608) +RMN_voteToBless_Blessed_Benchmark:test_1RootSuccessBecameBlessed_gas() (gas: 29682) +RMN_voteToBless_Blessed_Benchmark:test_1RootSuccess_gas() (gas: 27628) +RMN_voteToBless_Blessed_Benchmark:test_3RootSuccess_gas() (gas: 81626) +RMN_voteToBless_Blessed_Benchmark:test_5RootSuccess_gas() (gas: 135518) +RMN_voteToCurse:test_CurseOnlyWhenThresholdReached_Success() (gas: 1651170) +RMN_voteToCurse:test_EmptySubjects_Revert() (gas: 14061) +RMN_voteToCurse:test_EvenIfAlreadyCursed_Success() (gas: 535124) +RMN_voteToCurse:test_OwnerCanCurseAndUncurse() (gas: 400060) +RMN_voteToCurse:test_RepeatedSubject_Revert() (gas: 144405) +RMN_voteToCurse:test_ReusedCurseId_Revert() (gas: 146972) +RMN_voteToCurse:test_UnauthorizedVoter_Revert() (gas: 12666) +RMN_voteToCurse:test_VoteToCurse_NoCurse_Success() (gas: 187556) +RMN_voteToCurse:test_VoteToCurse_YesCurse_Success() (gas: 473079) +RMN_voteToCurse_2:test_VotesAreDroppedIfSubjectIsNotCursedDuringConfigChange() (gas: 371083) +RMN_voteToCurse_2:test_VotesAreRetainedIfSubjectIsCursedDuringConfigChange() (gas: 1154362) +RMN_voteToCurse_Benchmark_1:test_VoteToCurse_NewSubject_NewVoter_NoCurse_gas() (gas: 141118) +RMN_voteToCurse_Benchmark_1:test_VoteToCurse_NewSubject_NewVoter_YesCurse_gas() (gas: 165258) +RMN_voteToCurse_Benchmark_2:test_VoteToCurse_OldSubject_NewVoter_NoCurse_gas() (gas: 121437) +RMN_voteToCurse_Benchmark_2:test_VoteToCurse_OldSubject_OldVoter_NoCurse_gas() (gas: 98373) +RMN_voteToCurse_Benchmark_3:test_VoteToCurse_OldSubject_NewVoter_YesCurse_gas() (gas: 145784) +RateLimiter_constructor:test_Constructor_Success() (gas: 19734) +RateLimiter_consume:test_AggregateValueMaxCapacityExceeded_Revert() (gas: 16042) +RateLimiter_consume:test_AggregateValueRateLimitReached_Revert() (gas: 22390) +RateLimiter_consume:test_ConsumeAggregateValue_Success() (gas: 31518) +RateLimiter_consume:test_ConsumeTokens_Success() (gas: 20381) +RateLimiter_consume:test_ConsumeUnlimited_Success() (gas: 40687) +RateLimiter_consume:test_ConsumingMoreThanUint128_Revert() (gas: 15822) +RateLimiter_consume:test_RateLimitReachedOverConsecutiveBlocks_Revert() (gas: 25798) +RateLimiter_consume:test_Refill_Success() (gas: 37444) +RateLimiter_consume:test_TokenMaxCapacityExceeded_Revert() (gas: 18388) +RateLimiter_consume:test_TokenRateLimitReached_Revert() (gas: 24886) +RateLimiter_currentTokenBucketState:test_CurrentTokenBucketState_Success() (gas: 38944) +RateLimiter_currentTokenBucketState:test_Refill_Success() (gas: 46849) +RateLimiter_setTokenBucketConfig:test_SetRateLimiterConfig_Success() (gas: 38506) +RegistryModuleOwnerCustom_constructor:test_constructor_Revert() (gas: 36033) +RegistryModuleOwnerCustom_registerAdminViaGetCCIPAdmin:test_registerAdminViaGetCCIPAdmin_Revert() (gas: 19739) +RegistryModuleOwnerCustom_registerAdminViaGetCCIPAdmin:test_registerAdminViaGetCCIPAdmin_Success() (gas: 130086) +RegistryModuleOwnerCustom_registerAdminViaOwner:test_registerAdminViaOwner_Revert() (gas: 19559) +RegistryModuleOwnerCustom_registerAdminViaOwner:test_registerAdminViaOwner_Success() (gas: 129905) +Router_applyRampUpdates:test_OffRampMismatch_Revert() (gas: 89366) +Router_applyRampUpdates:test_OffRampUpdatesWithRouting() (gas: 10662612) +Router_applyRampUpdates:test_OnRampDisable() (gas: 56028) +Router_applyRampUpdates:test_OnlyOwner_Revert() (gas: 12356) +Router_ccipSend:test_CCIPSendLinkFeeNoTokenSuccess_gas() (gas: 114599) +Router_ccipSend:test_CCIPSendLinkFeeOneTokenSuccess_gas() (gas: 202430) +Router_ccipSend:test_CCIPSendNativeFeeNoTokenSuccess_gas() (gas: 126968) +Router_ccipSend:test_CCIPSendNativeFeeOneTokenSuccess_gas() (gas: 214801) +Router_ccipSend:test_FeeTokenAmountTooLow_Revert() (gas: 64532) +Router_ccipSend:test_InvalidMsgValue() (gas: 32155) +Router_ccipSend:test_NativeFeeTokenInsufficientValue() (gas: 67174) +Router_ccipSend:test_NativeFeeTokenOverpay_Success() (gas: 170385) +Router_ccipSend:test_NativeFeeTokenZeroValue() (gas: 54279) +Router_ccipSend:test_NativeFeeToken_Success() (gas: 168901) +Router_ccipSend:test_NonLinkFeeToken_Success() (gas: 239295) +Router_ccipSend:test_UnsupportedDestinationChain_Revert() (gas: 24854) +Router_ccipSend:test_WhenNotHealthy_Revert() (gas: 44811) +Router_ccipSend:test_WrappedNativeFeeToken_Success() (gas: 171159) +Router_ccipSend:test_ZeroFeeAndGasPrice_Success() (gas: 241766) +Router_constructor:test_Constructor_Success() (gas: 13124) +Router_getArmProxy:test_getArmProxy() (gas: 10573) +Router_getFee:test_GetFeeSupportedChain_Success() (gas: 44673) +Router_getFee:test_UnsupportedDestinationChain_Revert() (gas: 17192) +Router_getSupportedTokens:test_GetSupportedTokens_Revert() (gas: 10532) +Router_recoverTokens:test_RecoverTokensInvalidRecipient_Revert() (gas: 11334) +Router_recoverTokens:test_RecoverTokensNoFunds_Revert() (gas: 20267) Router_recoverTokens:test_RecoverTokensNonOwner_Revert() (gas: 11171) -Router_recoverTokens:test_RecoverTokensValueReceiver_Revert() (gas: 392489) -Router_recoverTokens:test_RecoverTokens_Success() (gas: 52442) -Router_routeMessage:test_AutoExec_Success() (gas: 42738) -Router_routeMessage:test_ExecutionEvent_Success() (gas: 158166) -Router_routeMessage:test_ManualExec_Success() (gas: 35429) -Router_routeMessage:test_OnlyOffRamp_Revert() (gas: 25146) -Router_routeMessage:test_WhenNotHealthy_Revert() (gas: 44754) -Router_setWrappedNative:test_OnlyOwner_Revert() (gas: 10992) -SelfFundedPingPong_ccipReceive:test_FundingIfNotANop_Revert() (gas: 55596) -SelfFundedPingPong_ccipReceive:test_Funding_Success() (gas: 417712) -SelfFundedPingPong_setCountIncrBeforeFunding:test_setCountIncrBeforeFunding() (gas: 20169) -TokenAdminRegistry_acceptAdminRole:test_acceptAdminRole_OnlyPendingAdministrator_Revert() (gas: 51115) -TokenAdminRegistry_acceptAdminRole:test_acceptAdminRole_Success() (gas: 43961) -TokenAdminRegistry_addRegistryModule:test_addRegistryModule_OnlyOwner_Revert() (gas: 12641) -TokenAdminRegistry_addRegistryModule:test_addRegistryModule_Success() (gas: 67038) -TokenAdminRegistry_getAllConfiguredTokens:test_getAllConfiguredTokens_outOfBounds_Success() (gas: 11356) -TokenAdminRegistry_getPool:test_getPool_Success() (gas: 17596) -TokenAdminRegistry_getPools:test_getPools_Success() (gas: 39920) -TokenAdminRegistry_isAdministrator:test_isAdministrator_Success() (gas: 105952) -TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_AlreadyRegistered_Revert() (gas: 104067) -TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_OnlyRegistryModule_Revert() (gas: 15499) -TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_ZeroAddress_Revert() (gas: 15044) -TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_module_Success() (gas: 112578) -TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_owner_Success() (gas: 107692) -TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_reRegisterWhileUnclaimed_Success() (gas: 115716) -TokenAdminRegistry_removeRegistryModule:test_removeRegistryModule_OnlyOwner_Revert() (gas: 12597) -TokenAdminRegistry_removeRegistryModule:test_removeRegistryModule_Success() (gas: 54509) -TokenAdminRegistry_setPool:test_setPool_InvalidTokenPoolToken_Revert() (gas: 19166) -TokenAdminRegistry_setPool:test_setPool_OnlyAdministrator_Revert() (gas: 18032) -TokenAdminRegistry_setPool:test_setPool_Success() (gas: 35961) -TokenAdminRegistry_setPool:test_setPool_ZeroAddressRemovesPool_Success() (gas: 30635) -TokenAdminRegistry_transferAdminRole:test_transferAdminRole_OnlyAdministrator_Revert() (gas: 18091) -TokenAdminRegistry_transferAdminRole:test_transferAdminRole_Success() (gas: 49402) -TokenPoolAndProxy:test_lockOrBurn_burnMint_Success() (gas: 5855541) -TokenPoolAndProxy:test_lockOrBurn_burnWithFromMint_Success() (gas: 5887014) -TokenPoolAndProxy:test_lockOrBurn_lockRelease_Success() (gas: 6040093) -TokenPoolAndProxy:test_setPreviousPool_Success() (gas: 3214305) -TokenPoolAndProxyMigration:test_tokenPoolMigration_Success_1_2() (gas: 6699954) -TokenPoolAndProxyMigration:test_tokenPoolMigration_Success_1_4() (gas: 6912610) -TokenPoolWithAllowList_applyAllowListUpdates:test_AllowListNotEnabled_Revert() (gas: 2069936) -TokenPoolWithAllowList_applyAllowListUpdates:test_OnlyOwner_Revert() (gas: 12101) -TokenPoolWithAllowList_applyAllowListUpdates:test_SetAllowListSkipsZero_Success() (gas: 23464) -TokenPoolWithAllowList_applyAllowListUpdates:test_SetAllowList_Success() (gas: 177802) -TokenPoolWithAllowList_getAllowList:test_GetAllowList_Success() (gas: 23740) -TokenPoolWithAllowList_getAllowListEnabled:test_GetAllowListEnabled_Success() (gas: 8363) -TokenPoolWithAllowList_setRouter:test_SetRouter_Success() (gas: 24843) -TokenPool_applyChainUpdates:test_applyChainUpdates_DisabledNonZeroRateLimit_Revert() (gas: 271551) -TokenPool_applyChainUpdates:test_applyChainUpdates_InvalidRateLimitRate_Revert() (gas: 542134) +Router_recoverTokens:test_RecoverTokensValueReceiver_Revert() (gas: 358049) +Router_recoverTokens:test_RecoverTokens_Success() (gas: 52480) +Router_routeMessage:test_AutoExec_Success() (gas: 42816) +Router_routeMessage:test_ExecutionEvent_Success() (gas: 158529) +Router_routeMessage:test_ManualExec_Success() (gas: 35546) +Router_routeMessage:test_OnlyOffRamp_Revert() (gas: 25224) +Router_routeMessage:test_WhenNotHealthy_Revert() (gas: 44799) +Router_setWrappedNative:test_OnlyOwner_Revert() (gas: 10998) +SelfFundedPingPong_ccipReceive:test_FundingIfNotANop_Revert() (gas: 55660) +SelfFundedPingPong_ccipReceive:test_Funding_Success() (gas: 421258) +SelfFundedPingPong_setCountIncrBeforeFunding:test_setCountIncrBeforeFunding() (gas: 20181) +TokenAdminRegistry_acceptAdminRole:test_acceptAdminRole_OnlyPendingAdministrator_Revert() (gas: 51163) +TokenAdminRegistry_acceptAdminRole:test_acceptAdminRole_Success() (gas: 44004) +TokenAdminRegistry_addRegistryModule:test_addRegistryModule_OnlyOwner_Revert() (gas: 12653) +TokenAdminRegistry_addRegistryModule:test_addRegistryModule_Success() (gas: 67056) +TokenAdminRegistry_getAllConfiguredTokens:test_getAllConfiguredTokens_outOfBounds_Success() (gas: 11362) +TokenAdminRegistry_getPool:test_getPool_Success() (gas: 17602) +TokenAdminRegistry_getPools:test_getPools_Success() (gas: 39962) +TokenAdminRegistry_isAdministrator:test_isAdministrator_Success() (gas: 106006) +TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_AlreadyRegistered_Revert() (gas: 104346) +TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_OnlyRegistryModule_Revert() (gas: 15610) +TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_ZeroAddress_Revert() (gas: 15155) +TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_module_Success() (gas: 112962) +TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_owner_Success() (gas: 107965) +TokenAdminRegistry_proposeAdministrator:test_proposeAdministrator_reRegisterWhileUnclaimed_Success() (gas: 116067) +TokenAdminRegistry_removeRegistryModule:test_removeRegistryModule_OnlyOwner_Revert() (gas: 12609) +TokenAdminRegistry_removeRegistryModule:test_removeRegistryModule_Success() (gas: 54524) +TokenAdminRegistry_setPool:test_setPool_InvalidTokenPoolToken_Revert() (gas: 19316) +TokenAdminRegistry_setPool:test_setPool_OnlyAdministrator_Revert() (gas: 18137) +TokenAdminRegistry_setPool:test_setPool_Success() (gas: 36135) +TokenAdminRegistry_setPool:test_setPool_ZeroAddressRemovesPool_Success() (gas: 30842) +TokenAdminRegistry_transferAdminRole:test_transferAdminRole_OnlyAdministrator_Revert() (gas: 18103) +TokenAdminRegistry_transferAdminRole:test_transferAdminRole_Success() (gas: 49438) +TokenPoolAndProxy:test_lockOrBurn_burnMint_Success() (gas: 5586496) +TokenPoolAndProxy:test_lockOrBurn_burnWithFromMint_Success() (gas: 5617966) +TokenPoolAndProxy:test_lockOrBurn_lockRelease_Success() (gas: 5793243) +TokenPoolAndProxy:test_setPreviousPool_Success() (gas: 3070731) +TokenPoolAndProxyMigration:test_tokenPoolMigration_Success_1_2() (gas: 6434780) +TokenPoolAndProxyMigration:test_tokenPoolMigration_Success_1_4() (gas: 6634919) +TokenPoolWithAllowList_applyAllowListUpdates:test_AllowListNotEnabled_Revert() (gas: 1979949) +TokenPoolWithAllowList_applyAllowListUpdates:test_OnlyOwner_Revert() (gas: 12107) +TokenPoolWithAllowList_applyAllowListUpdates:test_SetAllowListSkipsZero_Success() (gas: 23476) +TokenPoolWithAllowList_applyAllowListUpdates:test_SetAllowList_Success() (gas: 177845) +TokenPoolWithAllowList_getAllowList:test_GetAllowList_Success() (gas: 23764) +TokenPoolWithAllowList_getAllowListEnabled:test_GetAllowListEnabled_Success() (gas: 8375) +TokenPoolWithAllowList_setRouter:test_SetRouter_Success() (gas: 24879) +TokenPool_applyChainUpdates:test_applyChainUpdates_DisabledNonZeroRateLimit_Revert() (gas: 271569) +TokenPool_applyChainUpdates:test_applyChainUpdates_InvalidRateLimitRate_Revert() (gas: 542359) TokenPool_applyChainUpdates:test_applyChainUpdates_NonExistentChain_Revert() (gas: 18449) -TokenPool_applyChainUpdates:test_applyChainUpdates_OnlyCallableByOwner_Revert() (gas: 11397) -TokenPool_applyChainUpdates:test_applyChainUpdates_Success() (gas: 477675) -TokenPool_applyChainUpdates:test_applyChainUpdates_ZeroAddressNotAllowed_Revert() (gas: 157356) -TokenPool_constructor:test_ZeroAddressNotAllowed_Revert() (gas: 70564) -TokenPool_constructor:test_immutableFields_Success() (gas: 20544) -TokenPool_getRemotePool:test_getRemotePool_Success() (gas: 274145) -TokenPool_onlyOffRamp:test_CallerIsNotARampOnRouter_Revert() (gas: 277116) -TokenPool_onlyOffRamp:test_ChainNotAllowed_Revert() (gas: 289701) -TokenPool_onlyOffRamp:test_onlyOffRamp_Success() (gas: 349912) -TokenPool_onlyOnRamp:test_CallerIsNotARampOnRouter_Revert() (gas: 276856) -TokenPool_onlyOnRamp:test_ChainNotAllowed_Revert() (gas: 253729) -TokenPool_onlyOnRamp:test_onlyOnRamp_Success() (gas: 304962) -TokenPool_setChainRateLimiterConfig:test_NonExistentChain_Revert() (gas: 17148) -TokenPool_setChainRateLimiterConfig:test_OnlyOwnerOrRateLimitAdmin_Revert() (gas: 15149) -TokenPool_setRemotePool:test_setRemotePool_NonExistentChain_Reverts() (gas: 15665) -TokenPool_setRemotePool:test_setRemotePool_OnlyOwner_Reverts() (gas: 13213) -TokenPool_setRemotePool:test_setRemotePool_Success() (gas: 282095) -TokenProxy_ccipSend:test_CcipSendGasShouldBeZero_Revert() (gas: 17127) -TokenProxy_ccipSend:test_CcipSendInsufficientAllowance_Revert() (gas: 134209) -TokenProxy_ccipSend:test_CcipSendInvalidToken_Revert() (gas: 15931) -TokenProxy_ccipSend:test_CcipSendNative_Success() (gas: 243059) -TokenProxy_ccipSend:test_CcipSendNoDataAllowed_Revert() (gas: 16315) -TokenProxy_ccipSend:test_CcipSend_Success() (gas: 261662) -TokenProxy_constructor:test_Constructor() (gas: 13812) -TokenProxy_getFee:test_GetFeeGasShouldBeZero_Revert() (gas: 16845) -TokenProxy_getFee:test_GetFeeInvalidToken_Revert() (gas: 12670) -TokenProxy_getFee:test_GetFeeNoDataAllowed_Revert() (gas: 15864) -TokenProxy_getFee:test_GetFee_Success() (gas: 84634) -USDCTokenPool__validateMessage:test_ValidateInvalidMessage_Revert() (gas: 25407) -USDCTokenPool_lockOrBurn:test_CallerIsNotARampOnRouter_Revert() (gas: 35376) -USDCTokenPool_lockOrBurn:test_LockOrBurnWithAllowList_Revert() (gas: 30112) -USDCTokenPool_lockOrBurn:test_LockOrBurn_Success() (gas: 133148) -USDCTokenPool_lockOrBurn:test_UnknownDomain_Revert() (gas: 477486) -USDCTokenPool_releaseOrMint:test_ReleaseOrMintRealTx_Success() (gas: 268238) -USDCTokenPool_releaseOrMint:test_TokenMaxCapacityExceeded_Revert() (gas: 50724) -USDCTokenPool_releaseOrMint:test_UnlockingUSDCFailed_Revert() (gas: 98642) -USDCTokenPool_setDomains:test_InvalidDomain_Revert() (gas: 66189) -USDCTokenPool_setDomains:test_OnlyOwner_Revert() (gas: 11345) -USDCTokenPool_supportsInterface:test_SupportsInterface_Success() (gas: 9888) \ No newline at end of file +TokenPool_applyChainUpdates:test_applyChainUpdates_OnlyCallableByOwner_Revert() (gas: 11469) +TokenPool_applyChainUpdates:test_applyChainUpdates_Success() (gas: 479160) +TokenPool_applyChainUpdates:test_applyChainUpdates_ZeroAddressNotAllowed_Revert() (gas: 157422) +TokenPool_constructor:test_ZeroAddressNotAllowed_Revert() (gas: 70484) +TokenPool_constructor:test_immutableFields_Success() (gas: 20586) +TokenPool_getRemotePool:test_getRemotePool_Success() (gas: 274175) +TokenPool_onlyOffRamp:test_CallerIsNotARampOnRouter_Revert() (gas: 277296) +TokenPool_onlyOffRamp:test_ChainNotAllowed_Revert() (gas: 290035) +TokenPool_onlyOffRamp:test_onlyOffRamp_Success() (gas: 350059) +TokenPool_onlyOnRamp:test_CallerIsNotARampOnRouter_Revert() (gas: 277036) +TokenPool_onlyOnRamp:test_ChainNotAllowed_Revert() (gas: 254072) +TokenPool_onlyOnRamp:test_onlyOnRamp_Success() (gas: 305115) +TokenPool_setChainRateLimiterConfig:test_NonExistentChain_Revert() (gas: 17187) +TokenPool_setChainRateLimiterConfig:test_OnlyOwnerOrRateLimitAdmin_Revert() (gas: 15227) +TokenPool_setRemotePool:test_setRemotePool_NonExistentChain_Reverts() (gas: 15671) +TokenPool_setRemotePool:test_setRemotePool_OnlyOwner_Reverts() (gas: 13219) +TokenPool_setRemotePool:test_setRemotePool_Success() (gas: 282125) +TokenProxy_ccipSend:test_CcipSendGasShouldBeZero_Revert() (gas: 17226) +TokenProxy_ccipSend:test_CcipSendInsufficientAllowance_Revert() (gas: 134605) +TokenProxy_ccipSend:test_CcipSendInvalidToken_Revert() (gas: 16000) +TokenProxy_ccipSend:test_CcipSendNative_Success() (gas: 244013) +TokenProxy_ccipSend:test_CcipSendNoDataAllowed_Revert() (gas: 16384) +TokenProxy_ccipSend:test_CcipSend_Success() (gas: 262651) +TokenProxy_constructor:test_Constructor() (gas: 13836) +TokenProxy_getFee:test_GetFeeGasShouldBeZero_Revert() (gas: 16899) +TokenProxy_getFee:test_GetFeeInvalidToken_Revert() (gas: 12706) +TokenProxy_getFee:test_GetFeeNoDataAllowed_Revert() (gas: 15888) +TokenProxy_getFee:test_GetFee_Success() (gas: 85240) +USDCTokenPool__validateMessage:test_ValidateInvalidMessage_Revert() (gas: 25704) +USDCTokenPool_lockOrBurn:test_CallerIsNotARampOnRouter_Revert() (gas: 35499) +USDCTokenPool_lockOrBurn:test_LockOrBurnWithAllowList_Revert() (gas: 30244) +USDCTokenPool_lockOrBurn:test_LockOrBurn_Success() (gas: 133512) +USDCTokenPool_lockOrBurn:test_UnknownDomain_Revert() (gas: 478191) +USDCTokenPool_releaseOrMint:test_ReleaseOrMintRealTx_Success() (gas: 268689) +USDCTokenPool_releaseOrMint:test_TokenMaxCapacityExceeded_Revert() (gas: 50964) +USDCTokenPool_releaseOrMint:test_UnlockingUSDCFailed_Revert() (gas: 99005) +USDCTokenPool_setDomains:test_InvalidDomain_Revert() (gas: 66393) +USDCTokenPool_setDomains:test_OnlyOwner_Revert() (gas: 11363) +USDCTokenPool_supportsInterface:test_SupportsInterface_Success() (gas: 10041) \ No newline at end of file diff --git a/contracts/src/v0.8/ccip/FeeQuoter.sol b/contracts/src/v0.8/ccip/FeeQuoter.sol index 944498007f..aad7dd2941 100644 --- a/contracts/src/v0.8/ccip/FeeQuoter.sol +++ b/contracts/src/v0.8/ccip/FeeQuoter.sol @@ -49,7 +49,7 @@ contract FeeQuoter is AuthorizedCallers, IFeeQuoter, ITypeAndVersion, IReceiver, event FeeTokenRemoved(address indexed feeToken); event UsdPerUnitGasUpdated(uint64 indexed destChain, uint256 value, uint256 timestamp); event UsdPerTokenUpdated(address indexed token, uint256 value, uint256 timestamp); - event PriceFeedPerTokenUpdated(address indexed token, IFeeQuoter.TokenPriceFeedConfig priceFeedConfig); + event PriceFeedPerTokenUpdated(address indexed token, TokenPriceFeedConfig priceFeedConfig); event TokenTransferFeeConfigUpdated( uint64 indexed destChainSelector, address indexed token, TokenTransferFeeConfig tokenTransferFeeConfig ); @@ -58,10 +58,16 @@ contract FeeQuoter is AuthorizedCallers, IFeeQuoter, ITypeAndVersion, IReceiver, event DestChainConfigUpdated(uint64 indexed destChainSelector, DestChainConfig destChainConfig); event DestChainAdded(uint64 indexed destChainSelector, DestChainConfig destChainConfig); + /// @dev Token price data feed configuration + struct TokenPriceFeedConfig { + address dataFeedAddress; // ──╮ AggregatorV3Interface contract (0 - feed is unset) + uint8 tokenDecimals; // ──────╯ Decimals of the token that the feed represents + } + /// @dev Token price data feed update struct TokenPriceFeedUpdate { address sourceToken; // Source token to update feed for - IFeeQuoter.TokenPriceFeedConfig feedConfig; // Feed config update data + TokenPriceFeedConfig feedConfig; // Feed config update data } /// @dev Struct that contains the static configuration @@ -177,7 +183,7 @@ contract FeeQuoter is AuthorizedCallers, IFeeQuoter, ITypeAndVersion, IReceiver, mapping(address token => Internal.TimestampedPackedUint224 price) private s_usdPerToken; /// @dev Stores the price data feed configurations per token. - mapping(address token => IFeeQuoter.TokenPriceFeedConfig dataFeedAddress) private s_usdPriceFeedsPerToken; + mapping(address token => TokenPriceFeedConfig dataFeedAddress) private s_usdPriceFeedsPerToken; /// @dev The multiplier for destination chain specific premiums that can be set by the owner or fee admin mapping(address token => uint64 premiumMultiplierWeiPerEth) private s_premiumMultiplierWeiPerEth; @@ -239,7 +245,7 @@ contract FeeQuoter is AuthorizedCallers, IFeeQuoter, ITypeAndVersion, IReceiver, return tokenPrice; } - IFeeQuoter.TokenPriceFeedConfig memory priceFeedConfig = s_usdPriceFeedsPerToken[token]; + TokenPriceFeedConfig memory priceFeedConfig = s_usdPriceFeedsPerToken[token]; // If the token price feed is not set, return the stale price if (priceFeedConfig.dataFeedAddress == address(0)) { @@ -251,15 +257,17 @@ contract FeeQuoter is AuthorizedCallers, IFeeQuoter, ITypeAndVersion, IReceiver, return _getTokenPriceFromDataFeed(priceFeedConfig); } - /// @inheritdoc IPriceRegistry - function getValidatedTokenPrice(address token) external view override returns (uint224) { + /// @notice Get the `tokenPrice` for a given token, checks if the price is valid. + /// @param token The token to get the price for. + /// @return tokenPrice The tokenPrice for the given token if it exists and is valid. + function getValidatedTokenPrice(address token) external view returns (uint224) { return _getValidatedTokenPrice(token); } - /// @inheritdoc IPriceRegistry - function getTokenPrices( - address[] calldata tokens - ) external view override returns (Internal.TimestampedPackedUint224[] memory) { + /// @notice Get the `tokenPrice` for an array of tokens. + /// @param tokens The tokens to get prices for. + /// @return tokenPrices The tokenPrices for the given tokens. + function getTokenPrices(address[] calldata tokens) external view returns (Internal.TimestampedPackedUint224[] memory) { uint256 length = tokens.length; Internal.TimestampedPackedUint224[] memory tokenPrices = new Internal.TimestampedPackedUint224[](length); for (uint256 i = 0; i < length; ++i) { @@ -268,25 +276,36 @@ contract FeeQuoter is AuthorizedCallers, IFeeQuoter, ITypeAndVersion, IReceiver, return tokenPrices; } - /// @inheritdoc IFeeQuoter - function getTokenPriceFeedConfig( - address token - ) external view override returns (IFeeQuoter.TokenPriceFeedConfig memory) { + /// @notice Returns the token price data feed configuration + /// @param token The token to retrieve the feed config for + /// @return tokenPriceFeedConfig The token price data feed config (if feed address is 0, the feed config is disabled) + function getTokenPriceFeedConfig(address token) external view returns (TokenPriceFeedConfig memory) { return s_usdPriceFeedsPerToken[token]; } - /// @inheritdoc IPriceRegistry + /// @notice Get an encoded `gasPrice` for a given destination chain ID. + /// The 224-bit result encodes necessary gas price components. + /// On L1 chains like Ethereum or Avax, the only component is the gas price. + /// On Optimistic Rollups, there are two components - the L2 gas price, and L1 base fee for data availability. + /// On future chains, there could be more or differing price components. + /// PriceRegistry does not contain chain-specific logic to parse destination chain price components. + /// @param destChainSelector The destination chain to get the price for. + /// @return gasPrice The encoded gasPrice for the given destination chain ID. function getDestinationChainGasPrice( uint64 destChainSelector - ) external view override returns (Internal.TimestampedPackedUint224 memory) { + ) external view returns (Internal.TimestampedPackedUint224 memory) { return s_usdPerUnitGasByDestChainSelector[destChainSelector]; } - /// @inheritdoc IPriceRegistry + /// @notice Gets the fee token price and the gas price, both denominated in dollars. + /// @param token The source token to get the price for. + /// @param destChainSelector The destination chain to get the gas price for. + /// @return tokenPrice The price of the feeToken in 1e18 dollars per base unit. + /// @return gasPriceValue The price of gas in 1e18 dollars per base unit. function getTokenAndGasPrices( address token, uint64 destChainSelector - ) public view override returns (uint224 tokenPrice, uint224 gasPriceValue) { + ) public view returns (uint224 tokenPrice, uint224 gasPriceValue) { Internal.TimestampedPackedUint224 memory gasPrice = s_usdPerUnitGasByDestChainSelector[destChainSelector]; // We do allow a gas price of 0, but no stale or unset gas prices if (gasPrice.timestamp == 0) revert ChainNotSupported(destChainSelector); @@ -296,15 +315,19 @@ contract FeeQuoter is AuthorizedCallers, IFeeQuoter, ITypeAndVersion, IReceiver, return (_getValidatedTokenPrice(token), gasPrice.value); } - /// @inheritdoc IPriceRegistry + /// @notice Convert a given token amount to target token amount. /// @dev this function assumes that no more than 1e59 dollars are sent as payment. /// If more is sent, the multiplication of feeTokenAmount and feeTokenValue will overflow. /// Since there isn't even close to 1e59 dollars in the world economy this is safe. + /// @param fromToken The given token address. + /// @param fromTokenAmount The given token amount. + /// @param toToken The target token address. + /// @return toTokenAmount The target token amount. function convertTokenAmount( address fromToken, uint256 fromTokenAmount, address toToken - ) public view override returns (uint256) { + ) public view returns (uint256) { /// Example: /// fromTokenAmount: 1e18 // 1 ETH /// ETH: 2_000e18 @@ -327,7 +350,7 @@ contract FeeQuoter is AuthorizedCallers, IFeeQuoter, ITypeAndVersion, IReceiver, /// @param priceFeedConfig token data feed configuration with valid data feed address (used to retrieve price & timestamp) /// @return tokenPrice data feed price answer rebased to s_usdPerToken units, with latest block timestamp function _getTokenPriceFromDataFeed( - IFeeQuoter.TokenPriceFeedConfig memory priceFeedConfig + TokenPriceFeedConfig memory priceFeedConfig ) internal view returns (Internal.TimestampedPackedUint224 memory tokenPrice) { AggregatorV3Interface dataFeedContract = AggregatorV3Interface(priceFeedConfig.dataFeedAddress); ( @@ -428,7 +451,7 @@ contract FeeQuoter is AuthorizedCallers, IFeeQuoter, ITypeAndVersion, IReceiver, for (uint256 i; i < tokenPriceFeedUpdates.length; ++i) { TokenPriceFeedUpdate memory update = tokenPriceFeedUpdates[i]; address sourceToken = update.sourceToken; - IFeeQuoter.TokenPriceFeedConfig memory tokenPriceFeedConfig = update.feedConfig; + TokenPriceFeedConfig memory tokenPriceFeedConfig = update.feedConfig; s_usdPriceFeedsPerToken[sourceToken] = tokenPriceFeedConfig; emit PriceFeedPerTokenUpdated(sourceToken, tokenPriceFeedConfig); @@ -839,12 +862,24 @@ contract FeeQuoter is AuthorizedCallers, IFeeQuoter, ITypeAndVersion, IReceiver, } /// @inheritdoc IFeeQuoter + /// @dev precondition - rampTokenAmounts and sourceTokenAmounts lengths must be equal function processMessageArgs( uint64 destChainSelector, address feeToken, uint256 feeTokenAmount, - bytes calldata extraArgs - ) external view returns (uint256 msgFeeJuels, bool isOutOfOrderExecution, bytes memory convertedExtraArgs) { + bytes calldata extraArgs, + Internal.RampTokenAmount[] calldata rampTokenAmounts, + Client.EVMTokenAmount[] calldata sourceTokenAmounts + ) + external + view + returns ( + uint256 msgFeeJuels, + bool isOutOfOrderExecution, + bytes memory convertedExtraArgs, + bytes[] memory destExecDataPerToken + ) + { // Convert feeToken to link if not already in link if (feeToken == i_linkToken) { msgFeeJuels = feeTokenAmount; @@ -859,17 +894,21 @@ contract FeeQuoter is AuthorizedCallers, IFeeQuoter, ITypeAndVersion, IReceiver, // We can parse unvalidated args since this message is called after getFee (which will already validate the params) Client.EVMExtraArgsV2 memory parsedExtraArgs = _parseUnvalidatedEVMExtraArgsFromBytes(extraArgs, defaultTxGasLimit); isOutOfOrderExecution = parsedExtraArgs.allowOutOfOrderExecution; + destExecDataPerToken = _processPoolReturnData(destChainSelector, rampTokenAmounts, sourceTokenAmounts); - return (msgFeeJuels, isOutOfOrderExecution, Client._argsToBytes(parsedExtraArgs)); + return (msgFeeJuels, isOutOfOrderExecution, Client._argsToBytes(parsedExtraArgs), destExecDataPerToken); } - /// @inheritdoc IFeeQuoter - /// @dev precondition - rampTokenAmounts and sourceTokenAmounts lengths must be equal - function processPoolReturnData( + /// @notice Validates pool return data + /// @param destChainSelector Destination chain selector to which the token amounts are sent to + /// @param rampTokenAmounts Token amounts with populated pool return data + /// @param sourceTokenAmounts Token amounts originally sent in a Client.EVM2AnyMessage message + /// @return destExecDataPerToken Destination chain execution data + function _processPoolReturnData( uint64 destChainSelector, Internal.RampTokenAmount[] calldata rampTokenAmounts, Client.EVMTokenAmount[] calldata sourceTokenAmounts - ) external view returns (bytes[] memory destExecDataPerToken) { + ) internal view returns (bytes[] memory destExecDataPerToken) { bytes4 chainFamilySelector = s_destChainConfigs[destChainSelector].chainFamilySelector; destExecDataPerToken = new bytes[](rampTokenAmounts.length); for (uint256 i = 0; i < rampTokenAmounts.length; ++i) { diff --git a/contracts/src/v0.8/ccip/interfaces/IFeeQuoter.sol b/contracts/src/v0.8/ccip/interfaces/IFeeQuoter.sol index f8fb1969de..e02947961d 100644 --- a/contracts/src/v0.8/ccip/interfaces/IFeeQuoter.sol +++ b/contracts/src/v0.8/ccip/interfaces/IFeeQuoter.sol @@ -6,17 +6,6 @@ import {Internal} from "../libraries/Internal.sol"; import {IPriceRegistry} from "./IPriceRegistry.sol"; interface IFeeQuoter is IPriceRegistry { - /// @dev Token price data feed configuration - struct TokenPriceFeedConfig { - address dataFeedAddress; // ──╮ AggregatorV3Interface contract (0 - feed is unset) - uint8 tokenDecimals; // ──────╯ Decimals of the token that the feed represents - } - - /// @notice Returns the token price data feed configuration - /// @param token The token to retrieve the feed config for - /// @return tokenPriceFeedConfig The token price data feed config (if feed address is 0, the feed config is disabled) - function getTokenPriceFeedConfig(address token) external view returns (TokenPriceFeedConfig memory); - /// @notice Validates the ccip message & returns the fee /// @param destChainSelector The destination chain selector. /// @param message The message to get quote for. @@ -27,28 +16,31 @@ interface IFeeQuoter is IPriceRegistry { ) external view returns (uint256 feeTokenAmount); /// @notice Converts the extraArgs to the latest version and returns the converted message fee in juels + /// @notice Validates pool return data /// @param destChainSelector destination chain selector to process /// @param feeToken Fee token address used to pay for message fees /// @param feeTokenAmount Fee token amount /// @param extraArgs Message extra args that were passed in by the client + /// @param rampTokenAmounts Token amounts with populated pool return data + /// @param sourceTokenAmounts Token amounts originally sent in a Client.EVM2AnyMessage message /// @return msgFeeJuels message fee in juels /// @return isOutOfOrderExecution true if the message should be executed out of order /// @return convertedExtraArgs extra args converted to the latest family-specific args version + /// @return destExecDataPerToken Destination chain execution data function processMessageArgs( uint64 destChainSelector, address feeToken, uint256 feeTokenAmount, - bytes memory extraArgs - ) external view returns (uint256 msgFeeJuels, bool isOutOfOrderExecution, bytes memory convertedExtraArgs); - - /// @notice Validates pool return data - /// @param destChainSelector Destination chain selector to which the token amounts are sent to - /// @param rampTokenAmounts Token amounts with populated pool return data - /// @param sourceTokenAmounts Token amounts originally sent in a Client.EVM2AnyMessage message - /// @return destExecData Destination chain execution data - function processPoolReturnData( - uint64 destChainSelector, - Internal.RampTokenAmount[] memory rampTokenAmounts, + bytes memory extraArgs, + Internal.RampTokenAmount[] calldata rampTokenAmounts, Client.EVMTokenAmount[] calldata sourceTokenAmounts - ) external view returns (bytes[] memory); + ) + external + view + returns ( + uint256 msgFeeJuels, + bool isOutOfOrderExecution, + bytes memory convertedExtraArgs, + bytes[] memory destExecDataPerToken + ); } diff --git a/contracts/src/v0.8/ccip/interfaces/IPriceRegistry.sol b/contracts/src/v0.8/ccip/interfaces/IPriceRegistry.sol index 757ef09b0c..ed69b7b0cd 100644 --- a/contracts/src/v0.8/ccip/interfaces/IPriceRegistry.sol +++ b/contracts/src/v0.8/ccip/interfaces/IPriceRegistry.sol @@ -1,7 +1,6 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import {Client} from "../libraries/Client.sol"; import {Internal} from "../libraries/Internal.sol"; interface IPriceRegistry { @@ -60,39 +59,4 @@ interface IPriceRegistry { /// @notice Get the list of fee tokens. /// @return feeTokens The tokens set as fee tokens. function getFeeTokens() external view returns (address[] memory); - - /// @notice Validates the ccip message & returns the fee - /// @param destChainSelector The destination chain selector. - /// @param message The message to get quote for. - /// @return feeTokenAmount The amount of fee token needed for the fee, in smallest denomination of the fee token. - function getValidatedFee( - uint64 destChainSelector, - Client.EVM2AnyMessage calldata message - ) external view returns (uint256 feeTokenAmount); - - /// @notice Converts the extraArgs to the latest version and returns the converted message fee in juels - /// @param destChainSelector destination chain selector to process - /// @param feeToken Fee token address used to pay for message fees - /// @param feeTokenAmount Fee token amount - /// @param extraArgs Message extra args that were passed in by the client - /// @return msgFeeJuels message fee in juels - /// @return isOutOfOrderExecution true if the message should be executed out of order - /// @return convertedExtraArgs extra args converted to the latest family-specific args version - function processMessageArgs( - uint64 destChainSelector, - address feeToken, - uint256 feeTokenAmount, - bytes memory extraArgs - ) external view returns (uint256 msgFeeJuels, bool isOutOfOrderExecution, bytes memory convertedExtraArgs); - - /// @notice Validates pool return data - /// @param destChainSelector Destination chain selector to which the token amounts are sent to - /// @param rampTokenAmounts Token amounts with populated pool return data - /// @param sourceTokenAmounts Token amounts originally sent in a Client.EVM2AnyMessage message - /// @return destExecData Destination chain execution data - function processPoolReturnData( - uint64 destChainSelector, - Internal.RampTokenAmount[] memory rampTokenAmounts, - Client.EVMTokenAmount[] calldata sourceTokenAmounts - ) external view returns (bytes[] memory); } diff --git a/contracts/src/v0.8/ccip/onRamp/OnRamp.sol b/contracts/src/v0.8/ccip/onRamp/OnRamp.sol index 5b1795cd57..a8ba346388 100644 --- a/contracts/src/v0.8/ccip/onRamp/OnRamp.sol +++ b/contracts/src/v0.8/ccip/onRamp/OnRamp.sol @@ -40,6 +40,7 @@ contract OnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCreator { error OnlyCallableByOwnerOrAllowlistAdmin(); error SenderNotAllowed(address sender); error InvalidAllowListRequest(uint64 destChainSelector); + error ReentrancyGuardReentrantCall(); event ConfigSet(StaticConfig staticConfig, DynamicConfig dynamicConfig); event DestChainConfigSet( @@ -67,6 +68,7 @@ contract OnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCreator { // solhint-disable-next-line gas-struct-packing struct DynamicConfig { address feeQuoter; // FeeQuoter address + bool reentrancyGuardEntered; // Reentrancy protection address messageInterceptor; // Optional message interceptor to validate outbound messages (zero address = no interceptor) address feeAggregator; // Fee aggregator address address allowListAdmin; // authorized admin to add or remove allowed senders @@ -162,6 +164,12 @@ contract OnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCreator { uint256 feeTokenAmount, address originalSender ) external returns (bytes32) { + // We rely on a reentrancy guard here due to the untrusted calls performed to the pools + // This enables some optimizations by not following the CEI pattern + if (s_dynamicConfig.reentrancyGuardEntered) revert ReentrancyGuardReentrantCall(); + + s_dynamicConfig.reentrancyGuardEntered = true; + DestChainConfig storage destChainConfig = s_destChainConfigs[destChainSelector]; // NOTE: assumes the message has already been validated through the getFee call @@ -185,13 +193,6 @@ contract OnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCreator { } } - // Convert message fee to juels and retrieve converted args - (uint256 msgFeeJuels, bool isOutOfOrderExecution, bytes memory convertedExtraArgs) = IFeeQuoter( - s_dynamicConfig.feeQuoter - ).processMessageArgs(destChainSelector, message.feeToken, feeTokenAmount, message.extraArgs); - - emit FeePaid(message.feeToken, msgFeeJuels); - Internal.EVM2AnyRampMessage memory newMessage = Internal.EVM2AnyRampMessage({ header: Internal.RampMessageHeader({ // Should be generated after the message is complete @@ -202,13 +203,11 @@ contract OnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCreator { sequenceNumber: ++destChainConfig.sequenceNumber, // Only bump nonce for messages that specify allowOutOfOrderExecution == false. Otherwise, we // may block ordered message nonces, which is not what we want. - nonce: isOutOfOrderExecution - ? 0 - : INonceManager(i_nonceManager).getIncrementedOutboundNonce(destChainSelector, originalSender) + nonce: 0 }), sender: originalSender, data: message.data, - extraArgs: convertedExtraArgs, + extraArgs: "", receiver: message.receiver, feeToken: message.feeToken, feeTokenAmount: feeTokenAmount, @@ -217,17 +216,30 @@ contract OnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCreator { }); // Lock / burn the tokens as last step. TokenPools may not always be trusted. - // There should be no state changes after external call to TokenPools. + Client.EVMTokenAmount[] memory tokenAmounts = message.tokenAmounts; for (uint256 i = 0; i < message.tokenAmounts.length; ++i) { newMessage.tokenAmounts[i] = - _lockOrBurnSingleToken(message.tokenAmounts[i], destChainSelector, message.receiver, originalSender); + _lockOrBurnSingleToken(tokenAmounts[i], destChainSelector, message.receiver, originalSender); } + // Convert message fee to juels and retrieve converted args // Validate pool return data after it is populated (view function - no state changes) - bytes[] memory destExecDataPerToken = IFeeQuoter(s_dynamicConfig.feeQuoter).processPoolReturnData( - destChainSelector, newMessage.tokenAmounts, message.tokenAmounts + ( + uint256 msgFeeJuels, + bool isOutOfOrderExecution, + bytes memory convertedExtraArgs, + bytes[] memory destExecDataPerToken + ) = IFeeQuoter(s_dynamicConfig.feeQuoter).processMessageArgs( + destChainSelector, message.feeToken, feeTokenAmount, message.extraArgs, newMessage.tokenAmounts, tokenAmounts ); + emit FeePaid(message.feeToken, msgFeeJuels); + + newMessage.header.nonce = isOutOfOrderExecution + ? 0 + : INonceManager(i_nonceManager).getIncrementedOutboundNonce(destChainSelector, originalSender); + newMessage.extraArgs = convertedExtraArgs; + for (uint256 i = 0; i < newMessage.tokenAmounts.length; ++i) { newMessage.tokenAmounts[i].destExecData = destExecDataPerToken[i]; } @@ -244,6 +256,9 @@ contract OnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCreator { // This must happen after any pool events as some tokens (e.g. USDC) emit events that we expect to precede this // event in the offchain code. emit CCIPMessageSent(destChainSelector, newMessage); + + s_dynamicConfig.reentrancyGuardEntered = false; + return newMessage.header.messageId; } @@ -326,7 +341,10 @@ contract OnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCreator { /// @notice Internal version of setDynamicConfig to allow for reuse in the constructor. function _setDynamicConfig(DynamicConfig memory dynamicConfig) internal { - if (dynamicConfig.feeQuoter == address(0) || dynamicConfig.feeAggregator == address(0)) revert InvalidConfig(); + if ( + dynamicConfig.feeQuoter == address(0) || dynamicConfig.feeAggregator == address(0) + || dynamicConfig.reentrancyGuardEntered + ) revert InvalidConfig(); s_dynamicConfig = dynamicConfig; diff --git a/contracts/src/v0.8/ccip/test/attacks/onRamp/MultiOnRampTokenPoolReentrancy.t.sol b/contracts/src/v0.8/ccip/test/attacks/onRamp/MultiOnRampTokenPoolReentrancy.t.sol index 5161aba883..4700d7edea 100644 --- a/contracts/src/v0.8/ccip/test/attacks/onRamp/MultiOnRampTokenPoolReentrancy.t.sol +++ b/contracts/src/v0.8/ccip/test/attacks/onRamp/MultiOnRampTokenPoolReentrancy.t.sol @@ -64,8 +64,7 @@ contract MultiOnRampTokenPoolReentrancy is OnRampSetup { /// Any user -> Facade -> 1st call to ccipSend -> pool’s lockOrBurn —> /// (reenter)-> Facade -> 2nd call to ccipSend /// In this case, Facade's second call would produce an EVM2Any msg with a lower sequence number. - /// The issue was fixed by moving state updates and event construction to before TokenPool calls. - /// This test is kept to verify message sequence expectations are not broken. + /// The issue was fixed by implementing a reentrancy guard in OnRamp. function test_OnRampTokenPoolReentrancy_Success() public { uint256 amount = 1; @@ -81,14 +80,6 @@ contract MultiOnRampTokenPoolReentrancy is OnRampSetup { feeToken: address(s_feeToken) }); - Client.EVM2AnyMessage memory message2 = Client.EVM2AnyMessage({ - receiver: abi.encode(i_receiver), - data: abi.encodePacked(uint256(2)), // message 2 contains data 2 - tokenAmounts: tokenAmounts, - extraArgs: Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: 200_000})), - feeToken: address(s_feeToken) - }); - uint256 expectedFee = s_sourceRouter.getFee(DEST_CHAIN_SELECTOR, message1); assertGt(expectedFee, 0); @@ -97,20 +88,7 @@ contract MultiOnRampTokenPoolReentrancy is OnRampSetup { // Internal.EVM2EVMMessage memory msgEvent1 = _messageToEvent(message1, 2, 2, expectedFee, address(s_facadeClient)); // Internal.EVM2EVMMessage memory msgEvent2 = _messageToEvent(message2, 1, 1, expectedFee, address(s_facadeClient)); - // vm.expectEmit(); - // emit CCIPSendRequested(msgEvent2); - // vm.expectEmit(); - // emit CCIPSendRequested(msgEvent1); - - // After issue is fixed, sequence now increments as expected - Internal.EVM2AnyRampMessage memory msgEvent1 = _messageToEvent(message1, 1, 1, expectedFee, address(s_facadeClient)); - Internal.EVM2AnyRampMessage memory msgEvent2 = _messageToEvent(message2, 2, 2, expectedFee, address(s_facadeClient)); - - vm.expectEmit(); - emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, msgEvent2); - vm.expectEmit(); - emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, msgEvent1); - + vm.expectRevert(OnRamp.ReentrancyGuardReentrantCall.selector); s_facadeClient.send(amount); } } diff --git a/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.sol b/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.sol index 82531c3148..0333cbb739 100644 --- a/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.sol +++ b/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.sol @@ -267,10 +267,10 @@ contract MultiRampsE2E is OnRampSetup, OffRampSetup { router.ccipSend(DEST_CHAIN_SELECTOR, message); vm.pauseGasMetering(); - uint256 gasLimit = s_feeQuoter.parseEVMExtraArgsFromBytes(msgEvent.extraArgs, DEST_CHAIN_SELECTOR).gasLimit; for (uint256 i = 0; i < msgEvent.tokenAmounts.length; ++i) { msgEvent.tokenAmounts[i].destExecData = abi.encode(MAX_TOKEN_POOL_RELEASE_OR_MINT_GAS); } + return Internal.Any2EVMRampMessage({ header: Internal.RampMessageHeader({ messageId: msgEvent.header.messageId, diff --git a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.t.sol b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.t.sol index a9c7679ac2..6fd0a40e95 100644 --- a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.t.sol +++ b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.t.sol @@ -1735,24 +1735,28 @@ contract FeeQuoter_processMessageArgs is FeeQuoterFeeSetup { super.setUp(); } - function test_WithLinkTokenAmount_Success() public view { + function test_processMessageArgs_WithLinkTokenAmount_Success() public view { ( uint256 msgFeeJuels, /* bool isOutOfOrderExecution */ , /* bytes memory convertedExtraArgs */ + , + /* destExecDataPerToken */ ) = s_feeQuoter.processMessageArgs( DEST_CHAIN_SELECTOR, // LINK s_sourceTokens[0], MAX_MSG_FEES_JUELS, - "" + "", + new Internal.RampTokenAmount[](0), + new Client.EVMTokenAmount[](0) ); assertEq(msgFeeJuels, MAX_MSG_FEES_JUELS); } - function test_WithConvertedTokenAmount_Success() public view { + function test_processMessageArgs_WithConvertedTokenAmount_Success() public view { address feeToken = s_sourceTokens[1]; uint256 feeTokenAmount = 10_000 gwei; uint256 expectedConvertedAmount = s_feeQuoter.convertTokenAmount(feeToken, feeTokenAmount, s_sourceTokens[0]); @@ -1762,32 +1766,52 @@ contract FeeQuoter_processMessageArgs is FeeQuoterFeeSetup { /* bool isOutOfOrderExecution */ , /* bytes memory convertedExtraArgs */ - ) = s_feeQuoter.processMessageArgs(DEST_CHAIN_SELECTOR, feeToken, feeTokenAmount, ""); + , + /* destExecDataPerToken */ + ) = s_feeQuoter.processMessageArgs( + DEST_CHAIN_SELECTOR, + feeToken, + feeTokenAmount, + "", + new Internal.RampTokenAmount[](0), + new Client.EVMTokenAmount[](0) + ); assertEq(msgFeeJuels, expectedConvertedAmount); } - function test_WithEmptyEVMExtraArgs_Success() public view { + function test_processMessageArgs_WithEmptyEVMExtraArgs_Success() public view { ( /* uint256 msgFeeJuels */ , bool isOutOfOrderExecution, - bytes memory convertedExtraArgs - ) = s_feeQuoter.processMessageArgs(DEST_CHAIN_SELECTOR, s_sourceTokens[0], 0, ""); + bytes memory convertedExtraArgs, + /* destExecDataPerToken */ + ) = s_feeQuoter.processMessageArgs( + DEST_CHAIN_SELECTOR, s_sourceTokens[0], 0, "", new Internal.RampTokenAmount[](0), new Client.EVMTokenAmount[](0) + ); assertEq(isOutOfOrderExecution, false); assertEq(convertedExtraArgs, Client._argsToBytes(s_feeQuoter.parseEVMExtraArgsFromBytes("", DEST_CHAIN_SELECTOR))); } - function test_WithEVMExtraArgsV1_Success() public view { + function test_processMessageArgs_WithEVMExtraArgsV1_Success() public view { bytes memory extraArgs = Client._argsToBytes(Client.EVMExtraArgsV1({gasLimit: 1000})); ( /* uint256 msgFeeJuels */ , bool isOutOfOrderExecution, - bytes memory convertedExtraArgs - ) = s_feeQuoter.processMessageArgs(DEST_CHAIN_SELECTOR, s_sourceTokens[0], 0, extraArgs); + bytes memory convertedExtraArgs, + /* destExecDataPerToken */ + ) = s_feeQuoter.processMessageArgs( + DEST_CHAIN_SELECTOR, + s_sourceTokens[0], + 0, + extraArgs, + new Internal.RampTokenAmount[](0), + new Client.EVMTokenAmount[](0) + ); assertEq(isOutOfOrderExecution, false); assertEq( @@ -1795,15 +1819,23 @@ contract FeeQuoter_processMessageArgs is FeeQuoterFeeSetup { ); } - function test_WitEVMExtraArgsV2_Success() public view { + function test_processMessageArgs_WitEVMExtraArgsV2_Success() public view { bytes memory extraArgs = Client._argsToBytes(Client.EVMExtraArgsV2({gasLimit: 0, allowOutOfOrderExecution: true})); ( /* uint256 msgFeeJuels */ , bool isOutOfOrderExecution, - bytes memory convertedExtraArgs - ) = s_feeQuoter.processMessageArgs(DEST_CHAIN_SELECTOR, s_sourceTokens[0], 0, extraArgs); + bytes memory convertedExtraArgs, + /* destExecDataPerToken */ + ) = s_feeQuoter.processMessageArgs( + DEST_CHAIN_SELECTOR, + s_sourceTokens[0], + 0, + extraArgs, + new Internal.RampTokenAmount[](0), + new Client.EVMTokenAmount[](0) + ); assertEq(isOutOfOrderExecution, true); assertEq( @@ -1813,21 +1845,35 @@ contract FeeQuoter_processMessageArgs is FeeQuoterFeeSetup { // Reverts - function test_MessageFeeTooHigh_Revert() public { + function test_processMessageArgs_MessageFeeTooHigh_Revert() public { vm.expectRevert( abi.encodeWithSelector(FeeQuoter.MessageFeeTooHigh.selector, MAX_MSG_FEES_JUELS + 1, MAX_MSG_FEES_JUELS) ); - s_feeQuoter.processMessageArgs(DEST_CHAIN_SELECTOR, s_sourceTokens[0], MAX_MSG_FEES_JUELS + 1, ""); + s_feeQuoter.processMessageArgs( + DEST_CHAIN_SELECTOR, + s_sourceTokens[0], + MAX_MSG_FEES_JUELS + 1, + "", + new Internal.RampTokenAmount[](0), + new Client.EVMTokenAmount[](0) + ); } - function test_InvalidExtraArgs_Revert() public { + function test_processMessageArgs_InvalidExtraArgs_Revert() public { vm.expectRevert(FeeQuoter.InvalidExtraArgsTag.selector); - s_feeQuoter.processMessageArgs(DEST_CHAIN_SELECTOR, s_sourceTokens[0], 0, "abcde"); + s_feeQuoter.processMessageArgs( + DEST_CHAIN_SELECTOR, + s_sourceTokens[0], + 0, + "abcde", + new Internal.RampTokenAmount[](0), + new Client.EVMTokenAmount[](0) + ); } - function test_MalformedEVMExtraArgs_Revert() public { + function test_processMessageArgs_MalformedEVMExtraArgs_Revert() public { // abi.decode error vm.expectRevert(); @@ -1835,13 +1881,13 @@ contract FeeQuoter_processMessageArgs is FeeQuoterFeeSetup { DEST_CHAIN_SELECTOR, s_sourceTokens[0], 0, - abi.encodeWithSelector(Client.EVM_EXTRA_ARGS_V2_TAG, Client.EVMExtraArgsV1({gasLimit: 100})) + abi.encodeWithSelector(Client.EVM_EXTRA_ARGS_V2_TAG, Client.EVMExtraArgsV1({gasLimit: 100})), + new Internal.RampTokenAmount[](0), + new Client.EVMTokenAmount[](0) ); } -} -contract FeeQuoter_validatePoolReturnData is FeeQuoterFeeSetup { - function test_ProcessPoolReturnData_Success() public view { + function test_processMessageArgs_WithCorrectPoolReturnData_Success() public view { Client.EVMTokenAmount[] memory sourceTokenAmounts = new Client.EVMTokenAmount[](2); sourceTokenAmounts[0].amount = 1e18; sourceTokenAmounts[0].token = s_sourceTokens[0]; @@ -1858,15 +1904,17 @@ contract FeeQuoter_validatePoolReturnData is FeeQuoterFeeSetup { expectedDestExecData[1] = abi.encode(DEFAULT_TOKEN_DEST_GAS_OVERHEAD); //expected return data should be abi.encoded default as isEnabled is false // No revert - successful - bytes[] memory destExecData = - s_feeQuoter.processPoolReturnData(DEST_CHAIN_SELECTOR, rampTokenAmounts, sourceTokenAmounts); + ( /* msgFeeJuels */ , /* isOutOfOrderExecution */, /* convertedExtraArgs */, bytes[] memory destExecData) = + s_feeQuoter.processMessageArgs( + DEST_CHAIN_SELECTOR, s_sourceTokens[0], MAX_MSG_FEES_JUELS, "", rampTokenAmounts, sourceTokenAmounts + ); for (uint256 i = 0; i < destExecData.length; ++i) { assertEq(destExecData[i], expectedDestExecData[i]); } } - function test_TokenAmountArraysMismatching_Revert() public { + function test_processMessageArgs_TokenAmountArraysMismatching_Revert() public { Client.EVMTokenAmount[] memory sourceTokenAmounts = new Client.EVMTokenAmount[](2); sourceTokenAmounts[0].amount = 1e18; sourceTokenAmounts[0].token = s_sourceTokens[0]; @@ -1877,12 +1925,17 @@ contract FeeQuoter_validatePoolReturnData is FeeQuoterFeeSetup { // Revert due to index out of bounds access vm.expectRevert(); - s_feeQuoter.processPoolReturnData( - DEST_CHAIN_SELECTOR, new Internal.RampTokenAmount[](1), new Client.EVMTokenAmount[](0) + s_feeQuoter.processMessageArgs( + DEST_CHAIN_SELECTOR, + s_sourceTokens[0], + MAX_MSG_FEES_JUELS, + "", + new Internal.RampTokenAmount[](1), + new Client.EVMTokenAmount[](0) ); } - function test_SourceTokenDataTooLarge_Revert() public { + function test_processMessageArgs_SourceTokenDataTooLarge_Revert() public { address sourceETH = s_sourceTokens[1]; Client.EVMTokenAmount[] memory sourceTokenAmounts = new Client.EVMTokenAmount[](1); @@ -1893,16 +1946,22 @@ contract FeeQuoter_validatePoolReturnData is FeeQuoterFeeSetup { rampTokenAmounts[0] = _getSourceTokenData(sourceTokenAmounts[0], s_tokenAdminRegistry, DEST_CHAIN_SELECTOR); // No data set, should succeed - s_feeQuoter.processPoolReturnData(DEST_CHAIN_SELECTOR, rampTokenAmounts, sourceTokenAmounts); + s_feeQuoter.processMessageArgs( + DEST_CHAIN_SELECTOR, s_sourceTokens[0], MAX_MSG_FEES_JUELS, "", rampTokenAmounts, sourceTokenAmounts + ); // Set max data length, should succeed rampTokenAmounts[0].extraData = new bytes(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES); - s_feeQuoter.processPoolReturnData(DEST_CHAIN_SELECTOR, rampTokenAmounts, sourceTokenAmounts); + s_feeQuoter.processMessageArgs( + DEST_CHAIN_SELECTOR, s_sourceTokens[0], MAX_MSG_FEES_JUELS, "", rampTokenAmounts, sourceTokenAmounts + ); // Set data to max length +1, should revert rampTokenAmounts[0].extraData = new bytes(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES + 1); vm.expectRevert(abi.encodeWithSelector(FeeQuoter.SourceTokenDataTooLarge.selector, sourceETH)); - s_feeQuoter.processPoolReturnData(DEST_CHAIN_SELECTOR, rampTokenAmounts, sourceTokenAmounts); + s_feeQuoter.processMessageArgs( + DEST_CHAIN_SELECTOR, s_sourceTokens[0], MAX_MSG_FEES_JUELS, "", rampTokenAmounts, sourceTokenAmounts + ); // Set token config to allow larger data FeeQuoter.TokenTransferFeeConfigArgs[] memory tokenTransferFeeConfigArgs = _generateTokenTransferFeeConfigArgs(1, 1); @@ -1920,16 +1979,20 @@ contract FeeQuoter_validatePoolReturnData is FeeQuoterFeeSetup { tokenTransferFeeConfigArgs, new FeeQuoter.TokenTransferFeeConfigRemoveArgs[](0) ); - s_feeQuoter.processPoolReturnData(DEST_CHAIN_SELECTOR, rampTokenAmounts, sourceTokenAmounts); + s_feeQuoter.processMessageArgs( + DEST_CHAIN_SELECTOR, s_sourceTokens[0], MAX_MSG_FEES_JUELS, "", rampTokenAmounts, sourceTokenAmounts + ); // Set the token data larger than the configured token data, should revert rampTokenAmounts[0].extraData = new bytes(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES + 32 + 1); vm.expectRevert(abi.encodeWithSelector(FeeQuoter.SourceTokenDataTooLarge.selector, sourceETH)); - s_feeQuoter.processPoolReturnData(DEST_CHAIN_SELECTOR, rampTokenAmounts, sourceTokenAmounts); + s_feeQuoter.processMessageArgs( + DEST_CHAIN_SELECTOR, s_sourceTokens[0], MAX_MSG_FEES_JUELS, "", rampTokenAmounts, sourceTokenAmounts + ); } - function test_InvalidEVMAddressDestToken_Revert() public { + function test_processMessageArgs_InvalidEVMAddressDestToken_Revert() public { bytes memory nonEvmAddress = abi.encode(type(uint208).max); Client.EVMTokenAmount[] memory sourceTokenAmounts = new Client.EVMTokenAmount[](1); @@ -1941,7 +2004,9 @@ contract FeeQuoter_validatePoolReturnData is FeeQuoterFeeSetup { rampTokenAmounts[0].destTokenAddress = nonEvmAddress; vm.expectRevert(abi.encodeWithSelector(Internal.InvalidEVMAddress.selector, nonEvmAddress)); - s_feeQuoter.processPoolReturnData(DEST_CHAIN_SELECTOR, rampTokenAmounts, sourceTokenAmounts); + s_feeQuoter.processMessageArgs( + DEST_CHAIN_SELECTOR, s_sourceTokens[0], MAX_MSG_FEES_JUELS, "", rampTokenAmounts, sourceTokenAmounts + ); } } @@ -2078,11 +2143,11 @@ contract FeeQuoter_KeystoneSetup is FeeQuoterSetup { FeeQuoter.TokenPriceFeedUpdate[] memory tokenPriceFeeds = new FeeQuoter.TokenPriceFeedUpdate[](2); tokenPriceFeeds[0] = FeeQuoter.TokenPriceFeedUpdate({ sourceToken: onReportTestToken1, - feedConfig: IFeeQuoter.TokenPriceFeedConfig({dataFeedAddress: address(0x0), tokenDecimals: 18}) + feedConfig: FeeQuoter.TokenPriceFeedConfig({dataFeedAddress: address(0x0), tokenDecimals: 18}) }); tokenPriceFeeds[1] = FeeQuoter.TokenPriceFeedUpdate({ sourceToken: onReportTestToken2, - feedConfig: IFeeQuoter.TokenPriceFeedConfig({dataFeedAddress: address(0x0), tokenDecimals: 20}) + feedConfig: FeeQuoter.TokenPriceFeedConfig({dataFeedAddress: address(0x0), tokenDecimals: 20}) }); s_feeQuoter.setReportPermissions(permissions); s_feeQuoter.updateTokenPriceFeeds(tokenPriceFeeds); diff --git a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoterSetup.t.sol b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoterSetup.t.sol index 124980bc81..31a92a5ed4 100644 --- a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoterSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoterSetup.t.sol @@ -210,7 +210,7 @@ contract FeeQuoterSetup is TokenSetup { ) internal pure returns (FeeQuoter.TokenPriceFeedUpdate memory) { return FeeQuoter.TokenPriceFeedUpdate({ sourceToken: sourceToken, - feedConfig: IFeeQuoter.TokenPriceFeedConfig({dataFeedAddress: dataFeedAddress, tokenDecimals: tokenDecimals}) + feedConfig: FeeQuoter.TokenPriceFeedConfig({dataFeedAddress: dataFeedAddress, tokenDecimals: tokenDecimals}) }); } @@ -262,16 +262,16 @@ contract FeeQuoterSetup is TokenSetup { } function _assertTokenPriceFeedConfigEquality( - IFeeQuoter.TokenPriceFeedConfig memory config1, - IFeeQuoter.TokenPriceFeedConfig memory config2 + FeeQuoter.TokenPriceFeedConfig memory config1, + FeeQuoter.TokenPriceFeedConfig memory config2 ) internal pure virtual { assertEq(config1.dataFeedAddress, config2.dataFeedAddress); assertEq(config1.tokenDecimals, config2.tokenDecimals); } - function _assertTokenPriceFeedConfigUnconfigured(IFeeQuoter.TokenPriceFeedConfig memory config) internal pure virtual { + function _assertTokenPriceFeedConfigUnconfigured(FeeQuoter.TokenPriceFeedConfig memory config) internal pure virtual { _assertTokenPriceFeedConfigEquality( - config, IFeeQuoter.TokenPriceFeedConfig({dataFeedAddress: address(0), tokenDecimals: 0}) + config, FeeQuoter.TokenPriceFeedConfig({dataFeedAddress: address(0), tokenDecimals: 0}) ); } diff --git a/contracts/src/v0.8/ccip/test/onRamp/OnRamp.t.sol b/contracts/src/v0.8/ccip/test/onRamp/OnRamp.t.sol index da4e731344..72be798738 100644 --- a/contracts/src/v0.8/ccip/test/onRamp/OnRamp.t.sol +++ b/contracts/src/v0.8/ccip/test/onRamp/OnRamp.t.sol @@ -667,10 +667,11 @@ contract OnRamp_getFee is OnRampSetup { } contract OnRamp_setDynamicConfig is OnRampSetup { - function test_SetDynamicConfig_Success() public { + function test_setDynamicConfig_Success() public { OnRamp.StaticConfig memory staticConfig = s_onRamp.getStaticConfig(); OnRamp.DynamicConfig memory newConfig = OnRamp.DynamicConfig({ feeQuoter: address(23423), + reentrancyGuardEntered: false, messageInterceptor: makeAddr("messageInterceptor"), feeAggregator: FEE_AGGREGATOR, allowListAdmin: address(0) @@ -687,9 +688,10 @@ contract OnRamp_setDynamicConfig is OnRampSetup { // Reverts - function test_SetConfigInvalidConfigFeeQuoterEqAddressZero_Revert() public { + function test_setDynamicConfig_InvalidConfigFeeQuoterEqAddressZero_Revert() public { OnRamp.DynamicConfig memory newConfig = OnRamp.DynamicConfig({ feeQuoter: address(0), + reentrancyGuardEntered: false, feeAggregator: FEE_AGGREGATOR, messageInterceptor: makeAddr("messageInterceptor"), allowListAdmin: address(0) @@ -699,9 +701,10 @@ contract OnRamp_setDynamicConfig is OnRampSetup { s_onRamp.setDynamicConfig(newConfig); } - function test_SetConfigInvalidConfig_Revert() public { + function test_setDynamicConfig_InvalidConfigInvalidConfig_Revert() public { OnRamp.DynamicConfig memory newConfig = OnRamp.DynamicConfig({ feeQuoter: address(23423), + reentrancyGuardEntered: false, messageInterceptor: address(0), feeAggregator: FEE_AGGREGATOR, allowListAdmin: address(0) @@ -713,9 +716,10 @@ contract OnRamp_setDynamicConfig is OnRampSetup { s_onRamp.setDynamicConfig(newConfig); } - function test_SetConfigInvalidConfigFeeAggregatorEqAddressZero_Revert() public { + function test_setDynamicConfig_InvalidConfigFeeAggregatorEqAddressZero_Revert() public { OnRamp.DynamicConfig memory newConfig = OnRamp.DynamicConfig({ feeQuoter: address(23423), + reentrancyGuardEntered: false, messageInterceptor: address(0), feeAggregator: address(0), allowListAdmin: address(0) @@ -725,7 +729,7 @@ contract OnRamp_setDynamicConfig is OnRampSetup { s_onRamp.setDynamicConfig(newConfig); } - function test_SetConfigOnlyOwner_Revert() public { + function test_setDynamicConfig_InvalidConfigOnlyOwner_Revert() public { vm.startPrank(STRANGER); vm.expectRevert("Only callable by owner"); s_onRamp.setDynamicConfig(_generateDynamicOnRampConfig(address(2))); @@ -733,6 +737,19 @@ contract OnRamp_setDynamicConfig is OnRampSetup { vm.expectRevert("Only callable by owner"); s_onRamp.setDynamicConfig(_generateDynamicOnRampConfig(address(2))); } + + function test_setDynamicConfig_InvalidConfigReentrancyGuardEnteredEqTrue_Revert() public { + OnRamp.DynamicConfig memory newConfig = OnRamp.DynamicConfig({ + feeQuoter: address(23423), + reentrancyGuardEntered: true, + messageInterceptor: makeAddr("messageInterceptor"), + feeAggregator: FEE_AGGREGATOR, + allowListAdmin: address(0) + }); + + vm.expectRevert(OnRamp.InvalidConfig.selector); + s_onRamp.setDynamicConfig(newConfig); + } } contract OnRamp_withdrawFeeTokens is OnRampSetup { diff --git a/contracts/src/v0.8/ccip/test/onRamp/OnRampSetup.t.sol b/contracts/src/v0.8/ccip/test/onRamp/OnRampSetup.t.sol index 9ff7161696..ddcbbd5620 100644 --- a/contracts/src/v0.8/ccip/test/onRamp/OnRampSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/onRamp/OnRampSetup.t.sol @@ -87,6 +87,7 @@ contract OnRampSetup is FeeQuoterFeeSetup { function _generateDynamicOnRampConfig(address feeQuoter) internal pure returns (OnRamp.DynamicConfig memory) { return OnRamp.DynamicConfig({ feeQuoter: feeQuoter, + reentrancyGuardEntered: false, messageInterceptor: address(0), feeAggregator: FEE_AGGREGATOR, allowListAdmin: address(0) diff --git a/contracts/src/v0.8/ccip/test/rateLimiter/AggregateRateLimiter.t.sol b/contracts/src/v0.8/ccip/test/rateLimiter/AggregateRateLimiter.t.sol index 318821c441..90b56d4370 100644 --- a/contracts/src/v0.8/ccip/test/rateLimiter/AggregateRateLimiter.t.sol +++ b/contracts/src/v0.8/ccip/test/rateLimiter/AggregateRateLimiter.t.sol @@ -1,6 +1,8 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.24; +import {IPriceRegistry} from "../../interfaces/IPriceRegistry.sol"; + import {AggregateRateLimiter} from "../../AggregateRateLimiter.sol"; import {Client} from "../../libraries/Client.sol"; import {Internal} from "../../libraries/Internal.sol"; @@ -220,7 +222,7 @@ contract AggregateTokenLimiter_getTokenValue is AggregateTokenLimiterSetup { function test_GetTokenValue_Success() public view { uint256 numberOfTokens = 10; Client.EVMTokenAmount memory tokenAmount = Client.EVMTokenAmount({token: TOKEN, amount: 10}); - uint256 value = s_rateLimiter.getTokenValue(tokenAmount, s_feeQuoter); + uint256 value = s_rateLimiter.getTokenValue(tokenAmount, IPriceRegistry(address(s_feeQuoter))); assertEq(value, (numberOfTokens * TOKEN_PRICE) / 1e18); } @@ -230,6 +232,6 @@ contract AggregateTokenLimiter_getTokenValue is AggregateTokenLimiterSetup { Client.EVMTokenAmount memory tokenAmount = Client.EVMTokenAmount({token: tokenWithNoPrice, amount: 10}); vm.expectRevert(abi.encodeWithSelector(AggregateRateLimiter.PriceNotFoundForToken.selector, tokenWithNoPrice)); - s_rateLimiter.getTokenValue(tokenAmount, s_feeQuoter); + s_rateLimiter.getTokenValue(tokenAmount, IPriceRegistry(address(s_feeQuoter))); } } diff --git a/core/gethwrappers/ccip/generated/fee_quoter/fee_quoter.go b/core/gethwrappers/ccip/generated/fee_quoter/fee_quoter.go index 8c7822c6c7..e5c162e751 100644 --- a/core/gethwrappers/ccip/generated/fee_quoter/fee_quoter.go +++ b/core/gethwrappers/ccip/generated/fee_quoter/fee_quoter.go @@ -83,9 +83,14 @@ type FeeQuoterStaticConfig struct { StalenessThreshold uint32 } +type FeeQuoterTokenPriceFeedConfig struct { + DataFeedAddress common.Address + TokenDecimals uint8 +} + type FeeQuoterTokenPriceFeedUpdate struct { SourceToken common.Address - FeedConfig IFeeQuoterTokenPriceFeedConfig + FeedConfig FeeQuoterTokenPriceFeedConfig } type FeeQuoterTokenTransferFeeConfig struct { @@ -112,11 +117,6 @@ type FeeQuoterTokenTransferFeeConfigSingleTokenArgs struct { TokenTransferFeeConfig FeeQuoterTokenTransferFeeConfig } -type IFeeQuoterTokenPriceFeedConfig struct { - DataFeedAddress common.Address - TokenDecimals uint8 -} - type InternalGasPriceUpdate struct { DestChainSelector uint64 UsdPerUnitGas *big.Int @@ -154,8 +154,8 @@ type KeystoneFeedsPermissionHandlerPermission struct { } var FeeQuoterMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint96\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"linkToken\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"stalenessThreshold\",\"type\":\"uint32\"}],\"internalType\":\"structFeeQuoter.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"priceUpdaters\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"feeTokens\",\"type\":\"address[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"}],\"internalType\":\"structIFeeQuoter.TokenPriceFeedConfig\",\"name\":\"feedConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.TokenPriceFeedUpdate[]\",\"name\":\"tokenPriceFeeds\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigSingleTokenArgs[]\",\"name\":\"tokenTransferFeeConfigs\",\"type\":\"tuple[]\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigArgs[]\",\"name\":\"tokenTransferFeeConfigArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"internalType\":\"structFeeQuoter.PremiumMultiplierWeiPerEthArgs[]\",\"name\":\"premiumMultiplierWeiPerEthArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chain\",\"type\":\"uint64\"}],\"name\":\"ChainNotSupported\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DataFeedValueOutOfUint224Range\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"DestinationChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ExtraArgOutOfOrderExecutionMustBeTrue\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"FeeTokenNotSupported\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"}],\"name\":\"InvalidDestBytesOverhead\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidDestChainConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidEVMAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidExtraArgsTag\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidStaticConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"msgFeeJuels\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint256\"}],\"name\":\"MessageFeeTooHigh\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MessageGasLimitTooHigh\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"maxSize\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualSize\",\"type\":\"uint256\"}],\"name\":\"MessageTooLarge\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"internalType\":\"bytes10\",\"name\":\"workflowName\",\"type\":\"bytes10\"},{\"internalType\":\"bytes2\",\"name\":\"reportName\",\"type\":\"bytes2\"}],\"name\":\"ReportForwarderUnauthorized\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"SourceTokenDataTooLarge\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"threshold\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timePassed\",\"type\":\"uint256\"}],\"name\":\"StaleGasPrice\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feedTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"storedTimeStamp\",\"type\":\"uint256\"}],\"name\":\"StaleKeystoneUpdate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"TokenNotSupported\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"UnauthorizedCaller\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnsupportedNumberOfTokens\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"AuthorizedCallerAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"AuthorizedCallerRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"indexed\":false,\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"name\":\"DestChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"indexed\":false,\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"name\":\"DestChainConfigUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"}],\"name\":\"FeeTokenAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"}],\"name\":\"FeeTokenRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"name\":\"PremiumMultiplierWeiPerEthUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"}],\"indexed\":false,\"internalType\":\"structIFeeQuoter.TokenPriceFeedConfig\",\"name\":\"priceFeedConfig\",\"type\":\"tuple\"}],\"name\":\"PriceFeedPerTokenUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"reportId\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"},{\"internalType\":\"bytes10\",\"name\":\"workflowName\",\"type\":\"bytes10\"},{\"internalType\":\"bytes2\",\"name\":\"reportName\",\"type\":\"bytes2\"},{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isAllowed\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"structKeystoneFeedsPermissionHandler.Permission\",\"name\":\"permission\",\"type\":\"tuple\"}],\"name\":\"ReportPermissionSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"TokenTransferFeeConfigDeleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"name\":\"TokenTransferFeeConfigUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"UsdPerTokenUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChain\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"UsdPerUnitGasUpdated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"FEE_BASE_DECIMALS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"KEYSTONE_PRICE_DECIMALS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address[]\",\"name\":\"addedCallers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"removedCallers\",\"type\":\"address[]\"}],\"internalType\":\"structAuthorizedCallers.AuthorizedCallerArgs\",\"name\":\"authorizedCallerArgs\",\"type\":\"tuple\"}],\"name\":\"applyAuthorizedCallerUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyDestChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"feeTokensToAdd\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"feeTokensToRemove\",\"type\":\"address[]\"}],\"name\":\"applyFeeTokensUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"internalType\":\"structFeeQuoter.PremiumMultiplierWeiPerEthArgs[]\",\"name\":\"premiumMultiplierWeiPerEthArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyPremiumMultiplierWeiPerEthUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigSingleTokenArgs[]\",\"name\":\"tokenTransferFeeConfigs\",\"type\":\"tuple[]\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigArgs[]\",\"name\":\"tokenTransferFeeConfigArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigRemoveArgs[]\",\"name\":\"tokensToUseDefaultFeeConfigs\",\"type\":\"tuple[]\"}],\"name\":\"applyTokenTransferFeeConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"fromToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fromTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"toToken\",\"type\":\"address\"}],\"name\":\"convertTokenAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllAuthorizedCallers\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getDestChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getDestinationChainGasPrice\",\"outputs\":[{\"components\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"internalType\":\"structInternal.TimestampedPackedUint224\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getFeeTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getPremiumMultiplierWeiPerEth\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint96\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"linkToken\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"stalenessThreshold\",\"type\":\"uint32\"}],\"internalType\":\"structFeeQuoter.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getTokenAndGasPrices\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"tokenPrice\",\"type\":\"uint224\"},{\"internalType\":\"uint224\",\"name\":\"gasPriceValue\",\"type\":\"uint224\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenPrice\",\"outputs\":[{\"components\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"internalType\":\"structInternal.TimestampedPackedUint224\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenPriceFeedConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"}],\"internalType\":\"structIFeeQuoter.TokenPriceFeedConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"tokens\",\"type\":\"address[]\"}],\"name\":\"getTokenPrices\",\"outputs\":[{\"components\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"internalType\":\"structInternal.TimestampedPackedUint224[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenTransferFeeConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"getValidatedFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getValidatedTokenPrice\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"\",\"type\":\"uint224\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"onReport\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"name\":\"processMessageArgs\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"msgFeeJuels\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isOutOfOrderExecution\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"convertedExtraArgs\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"rampTokenAmounts\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"sourceTokenAmounts\",\"type\":\"tuple[]\"}],\"name\":\"processPoolReturnData\",\"outputs\":[{\"internalType\":\"bytes[]\",\"name\":\"destExecDataPerToken\",\"type\":\"bytes[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"},{\"internalType\":\"bytes10\",\"name\":\"workflowName\",\"type\":\"bytes10\"},{\"internalType\":\"bytes2\",\"name\":\"reportName\",\"type\":\"bytes2\"},{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isAllowed\",\"type\":\"bool\"}],\"internalType\":\"structKeystoneFeedsPermissionHandler.Permission[]\",\"name\":\"permissions\",\"type\":\"tuple[]\"}],\"name\":\"setReportPermissions\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"}],\"name\":\"updatePrices\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"}],\"internalType\":\"structIFeeQuoter.TokenPriceFeedConfig\",\"name\":\"feedConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.TokenPriceFeedUpdate[]\",\"name\":\"tokenPriceFeedUpdates\",\"type\":\"tuple[]\"}],\"name\":\"updateTokenPriceFeeds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x60e06040523480156200001157600080fd5b50604051620077a3380380620077a3833981016040819052620000349162001834565b8533806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf8162000207565b5050604080518082018252838152815160008152602080820190935291810191909152620000ee9150620002b2565b5060208701516001600160a01b0316158062000112575086516001600160601b0316155b80620001265750604087015163ffffffff16155b15620001455760405163d794ef9560e01b815260040160405180910390fd5b6020878101516001600160a01b031660a05287516001600160601b031660805260408089015163ffffffff1660c05280516000815291820190526200018c90869062000401565b620001978462000549565b620001a2816200061a565b620001ad8262000a5a565b60408051600080825260208201909252620001fa91859190620001f3565b6040805180820190915260008082526020820152815260200190600190039081620001cb5790505b5062000b26565b5050505050505062001ae5565b336001600160a01b03821603620002615760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b602081015160005b815181101562000342576000828281518110620002db57620002db62001953565b60209081029190910101519050620002f560028262000e5f565b1562000338576040516001600160a01b03821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b50600101620002ba565b50815160005b8151811015620003fb57600082828151811062000369576200036962001953565b6020026020010151905060006001600160a01b0316816001600160a01b031603620003a7576040516342bcdf7f60e11b815260040160405180910390fd5b620003b460028262000e7f565b506040516001600160a01b03821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a15060010162000348565b50505050565b60005b8251811015620004a2576200044083828151811062000427576200042762001953565b6020026020010151600b62000e7f60201b90919060201c565b1562000499578281815181106200045b576200045b62001953565b60200260200101516001600160a01b03167fdf1b1bd32a69711488d71554706bb130b1fc63a5fa1a2cd85e8440f84065ba2360405160405180910390a25b60010162000404565b5060005b81518110156200054457620004e2828281518110620004c957620004c962001953565b6020026020010151600b62000e9660201b90919060201c565b156200053b57818181518110620004fd57620004fd62001953565b60200260200101516001600160a01b03167f1795838dc8ab2ffc5f431a1729a6afa0b587f982f7b2be0b9d7187a1ef547f9160405160405180910390a25b600101620004a6565b505050565b60005b8151811015620006165760008282815181106200056d576200056d62001953565b6020908102919091018101518051818301516001600160a01b0380831660008181526007875260409081902084518154868a018051929096166001600160a81b03199091168117600160a01b60ff9384160217909255825191825293519093169683019690965293955091939092917f08a5f7f5bb38a81d8e43aca13ecd76431dbf8816ae4699affff7b00b2fc1c464910160405180910390a25050508060010190506200054c565b5050565b60005b8151811015620006165760008282815181106200063e576200063e62001953565b6020026020010151905060008383815181106200065f576200065f62001953565b6020026020010151600001519050600082602001519050816001600160401b03166000148062000698575061016081015163ffffffff16155b80620006ba57506101e08101516001600160e01b031916630a04b54b60e21b14155b80620006da5750806060015163ffffffff1681610160015163ffffffff16115b15620007055760405163c35aa79d60e01b81526001600160401b038316600482015260240162000083565b6001600160401b038216600090815260096020526040812060010154600160881b900460e01b6001600160e01b03191690036200078557816001600160401b03167fd31c671936387b2f84ed402b553bd50c0e9c20408ea4e91a836d77b8180fb7248260405162000777919062001969565b60405180910390a2620007c9565b816001600160401b03167f1edd6f3553cfa16f10b95b195abae3a1cfca4783de4843f95d674b1e1df5ab2082604051620007c0919062001969565b60405180910390a25b8060096000846001600160401b03166001600160401b0316815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548161ffff021916908361ffff16021790555060408201518160000160036101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160076101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600b6101000a81548163ffffffff021916908363ffffffff16021790555060a082015181600001600f6101000a81548161ffff021916908361ffff16021790555060c08201518160000160116101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160000160156101000a81548161ffff021916908361ffff1602179055506101008201518160000160176101000a81548161ffff021916908361ffff1602179055506101208201518160000160196101000a81548161ffff021916908361ffff16021790555061014082015181600001601b6101000a81548163ffffffff021916908363ffffffff1602179055506101608201518160010160006101000a81548163ffffffff021916908363ffffffff1602179055506101808201518160010160046101000a8154816001600160401b0302191690836001600160401b031602179055506101a082015181600101600c6101000a81548163ffffffff021916908363ffffffff1602179055506101c08201518160010160106101000a81548160ff0219169083151502179055506101e08201518160010160116101000a81548163ffffffff021916908360e01c02179055509050505050508060010190506200061d565b60005b81518110156200061657600082828151811062000a7e5762000a7e62001953565b6020026020010151600001519050600083838151811062000aa35762000aa362001953565b6020908102919091018101518101516001600160a01b03841660008181526008845260409081902080546001600160401b0319166001600160401b0385169081179091559051908152919350917fbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d910160405180910390a2505060010162000a5d565b60005b825181101562000d9957600083828151811062000b4a5762000b4a62001953565b6020026020010151905060008160000151905060005b82602001515181101562000d8a5760008360200151828151811062000b895762000b8962001953565b602002602001015160200151905060008460200151838151811062000bb25762000bb262001953565b6020026020010151600001519050602063ffffffff16826080015163ffffffff16101562000c115760808201516040516312766e0160e11b81526001600160a01b038316600482015263ffffffff909116602482015260440162000083565b6001600160401b0384166000818152600a602090815260408083206001600160a01b0386168085529083529281902086518154938801518389015160608a015160808b015160a08c01511515600160901b0260ff60901b1963ffffffff928316600160701b021664ffffffffff60701b199383166a01000000000000000000000263ffffffff60501b1961ffff90961668010000000000000000029590951665ffffffffffff60401b19968416640100000000026001600160401b0319909b16939097169290921798909817939093169390931717919091161792909217909155519091907f94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b59062000d77908690600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60405180910390a3505060010162000b60565b50505080600101905062000b29565b5060005b81518110156200054457600082828151811062000dbe5762000dbe62001953565b6020026020010151600001519050600083838151811062000de35762000de362001953565b6020908102919091018101518101516001600160401b0384166000818152600a845260408082206001600160a01b038516808452955280822080546001600160981b03191690555192945090917f4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b9190a3505060010162000d9d565b600062000e76836001600160a01b03841662000ead565b90505b92915050565b600062000e76836001600160a01b03841662000fb1565b600062000e76836001600160a01b03841662001003565b6000818152600183016020526040812054801562000fa657600062000ed460018362001aad565b855490915060009062000eea9060019062001aad565b905081811462000f5657600086600001828154811062000f0e5762000f0e62001953565b906000526020600020015490508087600001848154811062000f345762000f3462001953565b6000918252602080832090910192909255918252600188019052604090208390555b855486908062000f6a5762000f6a62001acf565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505062000e79565b600091505062000e79565b600081815260018301602052604081205462000ffa5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000e79565b50600062000e79565b6000818152600183016020526040812054801562000fa65760006200102a60018362001aad565b8554909150600090620010409060019062001aad565b905080821462000f5657600086600001828154811062000f0e5762000f0e62001953565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b03811182821017156200109f576200109f62001064565b60405290565b60405160c081016001600160401b03811182821017156200109f576200109f62001064565b60405161020081016001600160401b03811182821017156200109f576200109f62001064565b604051601f8201601f191681016001600160401b03811182821017156200111b576200111b62001064565b604052919050565b80516001600160a01b03811681146200113b57600080fd5b919050565b805163ffffffff811681146200113b57600080fd5b6000606082840312156200116857600080fd5b604051606081016001600160401b03811182821017156200118d576200118d62001064565b604052825190915081906001600160601b0381168114620011ad57600080fd5b8152620011bd6020840162001123565b6020820152620011d06040840162001140565b60408201525092915050565b60006001600160401b03821115620011f857620011f862001064565b5060051b60200190565b600082601f8301126200121457600080fd5b815160206200122d6200122783620011dc565b620010f0565b8083825260208201915060208460051b8701019350868411156200125057600080fd5b602086015b848110156200127757620012698162001123565b835291830191830162001255565b509695505050505050565b600082601f8301126200129457600080fd5b81516020620012a76200122783620011dc565b82815260609283028501820192828201919087851115620012c757600080fd5b8387015b858110156200135a5780890382811215620012e65760008081fd5b620012f06200107a565b620012fb8362001123565b8152604080601f1984011215620013125760008081fd5b6200131c6200107a565b92506200132b88850162001123565b835283015160ff81168114620013415760008081fd5b82880152808701919091528452928401928101620012cb565b5090979650505050505050565b80516001600160401b03811681146200113b57600080fd5b805161ffff811681146200113b57600080fd5b805180151581146200113b57600080fd5b600082601f830112620013b557600080fd5b81516020620013c86200122783620011dc565b82815260059290921b84018101918181019086841115620013e857600080fd5b8286015b84811015620012775780516001600160401b03808211156200140d57600080fd5b908801906040601f19838c0381018213156200142857600080fd5b620014326200107a565b6200143f89860162001367565b815282850151848111156200145357600080fd5b8086019550508c603f8601126200146957600080fd5b8885015193506200147e6200122785620011dc565b84815260e09094028501830193898101908e8611156200149d57600080fd5b958401955b858710156200157657868f0360e0811215620014bd57600080fd5b620014c76200107a565b620014d28962001123565b815260c08683011215620014e557600080fd5b620014ef620010a5565b9150620014fe8d8a0162001140565b82526200150d878a0162001140565b8d8301526200151f60608a016200137f565b878301526200153160808a0162001140565b60608301526200154460a08a0162001140565b60808301526200155760c08a0162001392565b60a0830152808d0191909152825260e09690960195908a0190620014a2565b828b015250875250505092840192508301620013ec565b600082601f8301126200159f57600080fd5b81516020620015b26200122783620011dc565b82815260069290921b84018101918181019086841115620015d257600080fd5b8286015b84811015620012775760408189031215620015f15760008081fd5b620015fb6200107a565b620016068262001123565b81526200161585830162001367565b81860152835291830191604001620015d6565b80516001600160e01b0319811681146200113b57600080fd5b600082601f8301126200165357600080fd5b81516020620016666200122783620011dc565b82815261022092830285018201928282019190878511156200168757600080fd5b8387015b858110156200135a5780890382811215620016a65760008081fd5b620016b06200107a565b620016bb8362001367565b815261020080601f1984011215620016d35760008081fd5b620016dd620010ca565b9250620016ec88850162001392565b83526040620016fd8186016200137f565b8985015260606200171081870162001140565b82860152608091506200172582870162001140565b9085015260a06200173886820162001140565b8286015260c091506200174d8287016200137f565b9085015260e06200176086820162001140565b828601526101009150620017768287016200137f565b908501526101206200178a8682016200137f565b828601526101409150620017a08287016200137f565b90850152610160620017b486820162001140565b828601526101809150620017ca82870162001140565b908501526101a0620017de86820162001367565b828601526101c09150620017f482870162001140565b908501526101e06200180886820162001392565b828601526200181983870162001628565b9085015250508087019190915284529284019281016200168b565b6000806000806000806000610120888a0312156200185157600080fd5b6200185d898962001155565b60608901519097506001600160401b03808211156200187b57600080fd5b620018898b838c0162001202565b975060808a0151915080821115620018a057600080fd5b620018ae8b838c0162001202565b965060a08a0151915080821115620018c557600080fd5b620018d38b838c0162001282565b955060c08a0151915080821115620018ea57600080fd5b620018f88b838c01620013a3565b945060e08a01519150808211156200190f57600080fd5b6200191d8b838c016200158d565b93506101008a01519150808211156200193557600080fd5b50620019448a828b0162001641565b91505092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b815115158152610200810160208301516200198a602084018261ffff169052565b506040830151620019a3604084018263ffffffff169052565b506060830151620019bc606084018263ffffffff169052565b506080830151620019d5608084018263ffffffff169052565b5060a0830151620019ec60a084018261ffff169052565b5060c083015162001a0560c084018263ffffffff169052565b5060e083015162001a1c60e084018261ffff169052565b506101008381015161ffff9081169184019190915261012080850151909116908301526101408084015163ffffffff9081169184019190915261016080850151821690840152610180808501516001600160401b0316908401526101a080850151909116908301526101c0808401511515908301526101e0928301516001600160e01b031916929091019190915290565b8181038181111562000e7957634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b60805160a05160c051615c5d62001b466000396000818161030501528181611bcf0152818161226b01526122d40152600081816102c90152818161193d015261199d015260008181610295015281816119c60152611a360152615c5d6000f3fe608060405234801561001057600080fd5b50600436106101e45760003560e01c806379ba50971161010f578063bf78e03f116100a2578063d63d3af211610071578063d63d3af214610ab2578063d8694ccd14610aba578063f2fde38b14610acd578063ffdb4b3714610ae057600080fd5b8063bf78e03f146109c8578063c4276bfc14610a75578063cdc73d5114610a97578063d02641a014610a9f57600080fd5b80638da5cb5b116100de5780638da5cb5b1461096757806391a2749a1461098f5780639ea60026146109a2578063a69c64c0146109b557600080fd5b806379ba5097146107c95780637afac322146107d1578063805f2132146107e457806382b49eb0146107f757600080fd5b80633937306f116101875780634ab35b0b116101565780634ab35b0b1461045f578063514e8cff1461049f5780636def4ce714610542578063770e2dc4146107b657600080fd5b80633937306f14610404578063407e10861461041957806341ed29e71461042c57806345ac924d1461043f57600080fd5b8063085318f8116101c3578063085318f81461037e578063181f5a771461039e5780632451a627146103e7578063325c868e146103fc57600080fd5b806241e5be146101e9578063061877e31461020f57806306285c6914610268575b600080fd5b6101fc6101f7366004614330565b610b28565b6040519081526020015b60405180910390f35b61024f61021d36600461436c565b73ffffffffffffffffffffffffffffffffffffffff1660009081526008602052604090205467ffffffffffffffff1690565b60405167ffffffffffffffff9091168152602001610206565b610332604080516060810182526000808252602082018190529181019190915260405180606001604052807f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000063ffffffff16815250905090565b6040805182516bffffffffffffffffffffffff16815260208084015173ffffffffffffffffffffffffffffffffffffffff16908201529181015163ffffffff1690820152606001610206565b61039161038c3660046143e4565b610b96565b60405161020691906144f6565b6103da6040518060400160405280601381526020017f46656551756f74657220312e362e302d6465760000000000000000000000000081525081565b6040516102069190614578565b6103ef610f08565b604051610206919061458b565b6101fc602481565b6104176104123660046145e5565b610f19565b005b610417610427366004614787565b6111ce565b61041761043a3660046148b9565b6111e2565b61045261044d3660046149f4565b611224565b6040516102069190614a36565b61047261046d36600461436c565b6112ef565b6040517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff9091168152602001610206565b6105356104ad366004614ab1565b60408051808201909152600080825260208201525067ffffffffffffffff166000908152600560209081526040918290208251808401909352547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811683527c0100000000000000000000000000000000000000000000000000000000900463ffffffff169082015290565b6040516102069190614acc565b6107a9610550366004614ab1565b6040805161020081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a081018290526101c081018290526101e08101919091525067ffffffffffffffff908116600090815260096020908152604091829020825161020081018452815460ff8082161515835261ffff61010080840482169685019690965263ffffffff630100000084048116978501979097526701000000000000008304871660608501526b0100000000000000000000008304871660808501526f010000000000000000000000000000008304811660a085015271010000000000000000000000000000000000808404881660c086015275010000000000000000000000000000000000000000008404821660e08087019190915277010000000000000000000000000000000000000000000000850483169786019790975279010000000000000000000000000000000000000000000000000084049091166101208501527b01000000000000000000000000000000000000000000000000000000909204861661014084015260019093015480861661016084015264010000000081049096166101808301526c0100000000000000000000000086049094166101a0820152700100000000000000000000000000000000850490911615156101c08201527fffffffff0000000000000000000000000000000000000000000000000000000092909304901b166101e082015290565b6040516102069190614b07565b6104176107c4366004614d1e565b6112fa565b61041761130c565b6104176107df366004615038565b611409565b6104176107f23660046150de565b61141b565b61090761080536600461514a565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101919091525067ffffffffffffffff919091166000908152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff94909416835292815290829020825160c081018452905463ffffffff8082168352640100000000820481169383019390935268010000000000000000810461ffff16938201939093526a01000000000000000000008304821660608201526e01000000000000000000000000000083049091166080820152720100000000000000000000000000000000000090910460ff16151560a082015290565b6040516102069190600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60005460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610206565b61041761099d366004615174565b611903565b6104176109b0366004615235565b611914565b6104176109c3366004615442565b611925565b610a416109d636600461436c565b6040805180820182526000808252602091820181905273ffffffffffffffffffffffffffffffffffffffff93841681526007825282902082518084019093525492831682527401000000000000000000000000000000000000000090920460ff169181019190915290565b60408051825173ffffffffffffffffffffffffffffffffffffffff16815260209283015160ff169281019290925201610206565b610a88610a83366004615507565b611936565b60405161020693929190615576565b6103ef611b2c565b610535610aad36600461436c565b611b38565b6101fc601281565b6101fc610ac8366004615597565b611c7c565b610417610adb36600461436c565b612186565b610af3610aee3660046155ec565b612197565b604080517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff938416815292909116602083015201610206565b6000610b3382612322565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16610b5a85612322565b610b82907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1685615645565b610b8c919061565c565b90505b9392505050565b67ffffffffffffffff8086166000908152600960205260409020600101546060917101000000000000000000000000000000000090910460e01b908590811115610be257610be2614620565b604051908082528060200260200182016040528015610c1557816020015b6060815260200190600190039081610c005790505b50915060005b85811015610efd576000858583818110610c3757610c37615697565b610c4d926020604090920201908101915061436c565b90506000888884818110610c6357610c63615697565b9050602002810190610c7591906156c6565b610c83906040810190615704565b9150506020811115610d385767ffffffffffffffff8a166000908152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff861684529091529020546e010000000000000000000000000000900463ffffffff16811115610d38576040517f36f536ca00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff831660048201526024015b60405180910390fd5b610da8848a8a86818110610d4e57610d4e615697565b9050602002810190610d6091906156c6565b610d6e906020810190615704565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506123bc92505050565b67ffffffffffffffff8a166000818152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684528252808320815160c081018352905463ffffffff8082168352640100000000820481168386015268010000000000000000820461ffff16838501526a01000000000000000000008204811660608401526e010000000000000000000000000000820481166080840152720100000000000000000000000000000000000090910460ff16151560a08301908152958552600990935290832054935190937b0100000000000000000000000000000000000000000000000000000090049091169190610ea75781610ead565b82606001515b6040805163ffffffff8316602082015291925001604051602081830303815290604052888781518110610ee257610ee2615697565b60200260200101819052505050505050806001019050610c1b565b505095945050505050565b6060610f146002612413565b905090565b610f21612420565b6000610f2d8280615769565b9050905060005b81811015611077576000610f488480615769565b83818110610f5857610f58615697565b905060400201803603810190610f6e91906157fd565b604080518082018252602080840180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff908116845263ffffffff42818116858701908152885173ffffffffffffffffffffffffffffffffffffffff9081166000908152600690975295889020965190519092167c010000000000000000000000000000000000000000000000000000000002919092161790935584519051935194955016927f52f50aa6d1a95a4595361ecf953d095f125d442e4673716dede699e049de148a926110669290917bffffffffffffffffffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b60405180910390a250600101610f34565b5060006110876020840184615769565b9050905060005b818110156111c85760006110a56020860186615769565b838181106110b5576110b5615697565b9050604002018036038101906110cb919061583a565b604080518082018252602080840180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff908116845263ffffffff42818116858701908152885167ffffffffffffffff9081166000908152600590975295889020965190519092167c010000000000000000000000000000000000000000000000000000000002919092161790935584519051935194955016927fdd84a3fa9ef9409f550d54d6affec7e9c480c878c6ab27b78912a03e1b371c6e926111b79290917bffffffffffffffffffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b60405180910390a25060010161108e565b50505050565b6111d6612465565b6111df816124e6565b50565b6111ea612465565b60005b81518110156112205761121882828151811061120b5761120b615697565b60200260200101516125e4565b6001016111ed565b5050565b60608160008167ffffffffffffffff81111561124257611242614620565b60405190808252806020026020018201604052801561128757816020015b60408051808201909152600080825260208201528152602001906001900390816112605790505b50905060005b828110156112e4576112bf8686838181106112aa576112aa615697565b9050602002016020810190610aad919061436c565b8282815181106112d1576112d1615697565b602090810291909101015260010161128d565b509150505b92915050565b60006112e982612322565b611302612465565b61122082826127b6565b60015473ffffffffffffffffffffffffffffffffffffffff16331461138d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610d2f565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b611411612465565b6112208282612bc3565b600080600061145f87878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612d0a92505050565b92509250925061147133838584612d25565b600061147f8587018761585d565b905060005b81518110156118f8576000600760008484815181106114a5576114a5615697565b6020908102919091018101515173ffffffffffffffffffffffffffffffffffffffff16825281019190915260400160009081205474010000000000000000000000000000000000000000900460ff1691508190036115665782828151811061150f5761150f615697565b6020908102919091010151516040517f06439c6b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610d2f565b60006115af60128386868151811061158057611580615697565b6020026020010151602001517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16612e7d565b9050600660008585815181106115c7576115c7615697565b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001601c9054906101000a900463ffffffff1663ffffffff1684848151811061163957611639615697565b60200260200101516040015163ffffffff1610156117435783838151811061166357611663615697565b60200260200101516000015184848151811061168157611681615697565b602002602001015160400151600660008787815181106116a3576116a3615697565b6020908102919091018101515173ffffffffffffffffffffffffffffffffffffffff90811683529082019290925260409081016000205490517f191ec70600000000000000000000000000000000000000000000000000000000815293909116600484015263ffffffff91821660248401527c01000000000000000000000000000000000000000000000000000000009004166044820152606401610d2f565b6040518060400160405280827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16815260200185858151811061178457611784615697565b60200260200101516040015163ffffffff16815250600660008686815181106117af576117af615697565b6020908102919091018101515173ffffffffffffffffffffffffffffffffffffffff168252818101929092526040016000208251929091015163ffffffff167c0100000000000000000000000000000000000000000000000000000000027bffffffffffffffffffffffffffffffffffffffffffffffffffffffff909216919091179055835184908490811061184757611847615697565b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff167f52f50aa6d1a95a4595361ecf953d095f125d442e4673716dede699e049de148a8286868151811061189d5761189d615697565b6020026020010151604001516040516118e69291907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff92909216825263ffffffff16602082015260400190565b60405180910390a25050600101611484565b505050505050505050565b61190b612465565b6111df81612f49565b61191c612465565b6111df816130d5565b61192d612465565b6111df8161357b565b60008060607f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff1603611996578592506119c4565b6119c187877f0000000000000000000000000000000000000000000000000000000000000000610b28565b92505b7f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff16831115611a63576040517f6a92a483000000000000000000000000000000000000000000000000000000008152600481018490526bffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166024820152604401610d2f565b67ffffffffffffffff881660009081526009602052604081206001015463ffffffff1690611a92878784613665565b9050806020015193508484611b19836040805182516024820152602092830151151560448083019190915282518083039091018152606490910190915290810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f181dcf100000000000000000000000000000000000000000000000000000000017905290565b9450945094505050955095509592505050565b6060610f14600b612413565b604080518082019091526000808252602082015273ffffffffffffffffffffffffffffffffffffffff82166000908152600660209081526040918290208251808401909352547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116835263ffffffff7c010000000000000000000000000000000000000000000000000000000090910481169183018290527f00000000000000000000000000000000000000000000000000000000000000001690611bfa9042615924565b1015611c065792915050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600760209081526040918290208251808401909352549283168083527401000000000000000000000000000000000000000090930460ff169082015290611c6b575092915050565b611c748161380e565b949350505050565b67ffffffffffffffff8083166000908152600960209081526040808320815161020081018352815460ff808216151580845261ffff61010080850482169886019890985263ffffffff630100000085048116978601979097526701000000000000008404871660608601526b0100000000000000000000008404871660808601526f010000000000000000000000000000008404811660a086015271010000000000000000000000000000000000808504881660c087015275010000000000000000000000000000000000000000008504821660e08088019190915277010000000000000000000000000000000000000000000000860483169987019990995279010000000000000000000000000000000000000000000000000085049091166101208601527b01000000000000000000000000000000000000000000000000000000909304861661014085015260019094015480861661016085015264010000000081049098166101808401526c0100000000000000000000000088049094166101a0830152700100000000000000000000000000000000870490931615156101c08201527fffffffff000000000000000000000000000000000000000000000000000000009290950490921b166101e0840152909190611e96576040517f99ac52f200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff85166004820152602401610d2f565b611eb1611ea9608085016060860161436c565b600b9061399d565b611f1057611ec5608084016060850161436c565b6040517f2502348c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610d2f565b6000611f1f6040850185615769565b9150611f7b905082611f346020870187615704565b905083611f418880615704565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506139cc92505050565b600080611f97611f91608088016060890161436c565b88612197565b9092509050600080808515611fda57611fce878b611fbb60808d0160608e0161436c565b88611fc960408f018f615769565b613a76565b91945092509050611ffa565b6101a0870151611ff79063ffffffff16662386f26fc10000615645565b92505b61010087015160009061ffff161561203e5761203b886dffffffffffffffffffffffffffff607088901c1661203260208e018e615704565b90508a86613d4e565b90505b61018088015160009067ffffffffffffffff1661206761206160808e018e615704565b8c613dfe565b600001518563ffffffff168b60a0015161ffff168e806020019061208b9190615704565b612096929150615645565b8c6080015163ffffffff166120ab9190615937565b6120b59190615937565b6120bf9190615937565b6120d9906dffffffffffffffffffffffffffff8916615645565b6120e39190615645565b9050867bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168282600860008f606001602081019061211d919061436c565b73ffffffffffffffffffffffffffffffffffffffff1681526020810191909152604001600020546121589067ffffffffffffffff1689615645565b6121629190615937565b61216c9190615937565b612176919061565c565b9c9b505050505050505050505050565b61218e612465565b6111df81613ebf565b67ffffffffffffffff811660009081526005602090815260408083208151808301909252547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811682527c0100000000000000000000000000000000000000000000000000000000900463ffffffff169181018290528291820361224f576040517f2e59db3a00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff85166004820152602401610d2f565b6000816020015163ffffffff16426122679190615924565b90507f000000000000000000000000000000000000000000000000000000000000000063ffffffff16811115612308576040517ff08bcb3e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8616600482015263ffffffff7f000000000000000000000000000000000000000000000000000000000000000016602482015260448101829052606401610d2f565b61231186612322565b9151919350909150505b9250929050565b60008061232e83611b38565b9050806020015163ffffffff1660001480612366575080517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16155b156123b5576040517f06439c6b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152602401610d2f565b5192915050565b7fd7ed2ad4000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316016112205761240e81613fb4565b505050565b60606000610b8f83614067565b61242b60023361399d565b612463576040517fd86ad9cf000000000000000000000000000000000000000000000000000000008152336004820152602401610d2f565b565b60005473ffffffffffffffffffffffffffffffffffffffff163314612463576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610d2f565b60005b815181101561122057600082828151811061250657612506615697565b60209081029190910181015180518183015173ffffffffffffffffffffffffffffffffffffffff80831660008181526007875260409081902084518154868a018051929096167fffffffffffffffffffffff00000000000000000000000000000000000000000090911681177401000000000000000000000000000000000000000060ff9384160217909255825191825293519093169683019690965293955091939092917f08a5f7f5bb38a81d8e43aca13ecd76431dbf8816ae4699affff7b00b2fc1c464910160405180910390a25050508060010190506124e9565b600061269d82600001518360600151846020015185604001516040805173ffffffffffffffffffffffffffffffffffffffff80871660208301528516918101919091527fffffffffffffffffffff00000000000000000000000000000000000000000000831660608201527fffff0000000000000000000000000000000000000000000000000000000000008216608082015260009060a001604051602081830303815290604052805190602001209050949350505050565b60808301516000828152600460205260409081902080549215157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00909316929092179091555190915081907f32a4ba3fa3351b11ad555d4c8ec70a744e8705607077a946807030d64b6ab1a3906127aa908590600060a08201905073ffffffffffffffffffffffffffffffffffffffff8084511683527fffffffffffffffffffff0000000000000000000000000000000000000000000060208501511660208401527fffff00000000000000000000000000000000000000000000000000000000000060408501511660408401528060608501511660608401525060808301511515608083015292915050565b60405180910390a25050565b60005b8251811015612adf5760008382815181106127d6576127d6615697565b6020026020010151905060008160000151905060005b826020015151811015612ad15760008360200151828151811061281157612811615697565b602002602001015160200151905060008460200151838151811061283757612837615697565b6020026020010151600001519050602063ffffffff16826080015163ffffffff1610156128ba5760808201516040517f24ecdc0200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8316600482015263ffffffff9091166024820152604401610d2f565b67ffffffffffffffff84166000818152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff86168085529083529281902086518154938801518389015160608a015160808b015160a08c015115157201000000000000000000000000000000000000027fffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffff63ffffffff9283166e01000000000000000000000000000002167fffffffffffffffffffffffffff0000000000ffffffffffffffffffffffffffff9383166a0100000000000000000000027fffffffffffffffffffffffffffffffffffff00000000ffffffffffffffffffff61ffff9096166801000000000000000002959095167fffffffffffffffffffffffffffffffffffff000000000000ffffffffffffffff968416640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000909b16939097169290921798909817939093169390931717919091161792909217909155519091907f94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b590612abf908690600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60405180910390a350506001016127ec565b5050508060010190506127b9565b5060005b815181101561240e576000828281518110612b0057612b00615697565b60200260200101516000015190506000838381518110612b2257612b22615697565b60209081029190910181015181015167ffffffffffffffff84166000818152600a8452604080822073ffffffffffffffffffffffffffffffffffffffff8516808452955280822080547fffffffffffffffffffffffffff000000000000000000000000000000000000001690555192945090917f4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b9190a35050600101612ae3565b60005b8251811015612c6657612bfc838281518110612be457612be4615697565b6020026020010151600b6140c390919063ffffffff16565b15612c5e57828181518110612c1357612c13615697565b602002602001015173ffffffffffffffffffffffffffffffffffffffff167fdf1b1bd32a69711488d71554706bb130b1fc63a5fa1a2cd85e8440f84065ba2360405160405180910390a25b600101612bc6565b5060005b815181101561240e57612ca0828281518110612c8857612c88615697565b6020026020010151600b6140e590919063ffffffff16565b15612d0257818181518110612cb757612cb7615697565b602002602001015173ffffffffffffffffffffffffffffffffffffffff167f1795838dc8ab2ffc5f431a1729a6afa0b587f982f7b2be0b9d7187a1ef547f9160405160405180910390a25b600101612c6a565b6040810151604a820151605e90920151909260609290921c91565b6040805173ffffffffffffffffffffffffffffffffffffffff868116602080840191909152908616828401527fffffffffffffffffffff00000000000000000000000000000000000000000000851660608301527fffff00000000000000000000000000000000000000000000000000000000000084166080808401919091528351808403909101815260a09092018352815191810191909120600081815260049092529190205460ff16612e76576040517f097e17ff00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8087166004830152851660248201527fffffffffffffffffffff00000000000000000000000000000000000000000000841660448201527fffff00000000000000000000000000000000000000000000000000000000000083166064820152608401610d2f565b5050505050565b600080612e8a848661594a565b9050600060248260ff161115612ec457612ea8602460ff8416615924565b612eb390600a615a83565b612ebd908561565c565b9050612eea565b612ed260ff83166024615924565b612edd90600a615a83565b612ee79085615645565b90505b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811115612f40576040517f10cb51d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b95945050505050565b602081015160005b8151811015612fe4576000828281518110612f6e57612f6e615697565b60200260200101519050612f8c81600261410790919063ffffffff16565b15612fdb5760405173ffffffffffffffffffffffffffffffffffffffff821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b50600101612f51565b50815160005b81518110156111c857600082828151811061300757613007615697565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603613077576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6130826002826140c3565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a150600101612fea565b60005b81518110156112205760008282815181106130f5576130f5615697565b60200260200101519050600083838151811061311357613113615697565b60200260200101516000015190506000826020015190508167ffffffffffffffff166000148061314c575061016081015163ffffffff16155b8061319e57506101e08101517fffffffff00000000000000000000000000000000000000000000000000000000167f2812d52c0000000000000000000000000000000000000000000000000000000014155b806131bd5750806060015163ffffffff1681610160015163ffffffff16115b15613200576040517fc35aa79d00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff83166004820152602401610d2f565b67ffffffffffffffff821660009081526009602052604081206001015471010000000000000000000000000000000000900460e01b7fffffffff000000000000000000000000000000000000000000000000000000001690036132a4578167ffffffffffffffff167fd31c671936387b2f84ed402b553bd50c0e9c20408ea4e91a836d77b8180fb724826040516132979190614b07565b60405180910390a26132e7565b8167ffffffffffffffff167f1edd6f3553cfa16f10b95b195abae3a1cfca4783de4843f95d674b1e1df5ab20826040516132de9190614b07565b60405180910390a25b80600960008467ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548161ffff021916908361ffff16021790555060408201518160000160036101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160076101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600b6101000a81548163ffffffff021916908363ffffffff16021790555060a082015181600001600f6101000a81548161ffff021916908361ffff16021790555060c08201518160000160116101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160000160156101000a81548161ffff021916908361ffff1602179055506101008201518160000160176101000a81548161ffff021916908361ffff1602179055506101208201518160000160196101000a81548161ffff021916908361ffff16021790555061014082015181600001601b6101000a81548163ffffffff021916908363ffffffff1602179055506101608201518160010160006101000a81548163ffffffff021916908363ffffffff1602179055506101808201518160010160046101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506101a082015181600101600c6101000a81548163ffffffff021916908363ffffffff1602179055506101c08201518160010160106101000a81548160ff0219169083151502179055506101e08201518160010160116101000a81548163ffffffff021916908360e01c02179055509050505050508060010190506130d8565b60005b815181101561122057600082828151811061359b5761359b615697565b602002602001015160000151905060008383815181106135bd576135bd615697565b60209081029190910181015181015173ffffffffffffffffffffffffffffffffffffffff841660008181526008845260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff85169081179091559051908152919350917fbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d910160405180910390a2505060010161357e565b604080518082019091526000808252602082015260008390036136a657506040805180820190915267ffffffffffffffff8216815260006020820152610b8f565b60006136b28486615a8f565b905060006136c38560048189615ad5565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505050507fffffffff0000000000000000000000000000000000000000000000000000000082167fe7e230f0000000000000000000000000000000000000000000000000000000000161376057808060200190518101906137579190615aff565b92505050610b8f565b7f6859a837000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316016137dc576040518060400160405280828060200190518101906137c89190615b2b565b815260006020909101529250610b8f915050565b6040517f5247fdce00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604080518082019091526000808252602082015260008260000151905060008173ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015613878573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061389c9190615b5e565b50505091505060008112156138dd576040517f10cb51d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061395c8373ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561392d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139519190615bae565b866020015184612e7d565b604080518082019091527bffffffffffffffffffffffffffffffffffffffffffffffffffffffff909116815263ffffffff4216602082015295945050505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515610b8f565b836040015163ffffffff16831115613a255760408085015190517f8693378900000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015260248101849052604401610d2f565b836020015161ffff16821115613a67576040517f4c056b6a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6111c8846101e00151826123bc565b6000808083815b81811015613d40576000878783818110613a9957613a99615697565b905060400201803603810190613aaf9190615bcb565b67ffffffffffffffff8c166000908152600a60209081526040808320845173ffffffffffffffffffffffffffffffffffffffff168452825291829020825160c081018452905463ffffffff8082168352640100000000820481169383019390935268010000000000000000810461ffff16938201939093526a01000000000000000000008304821660608201526e01000000000000000000000000000083049091166080820152720100000000000000000000000000000000000090910460ff16151560a0820181905291925090613bcf576101208d0151613b9c9061ffff16662386f26fc10000615645565b613ba69088615937565b96508c610140015186613bb99190615c04565b9550613bc6602086615c04565b94505050613d38565b604081015160009061ffff1615613c885760008c73ffffffffffffffffffffffffffffffffffffffff16846000015173ffffffffffffffffffffffffffffffffffffffff1614613c2b578351613c2490612322565b9050613c2e565b508a5b620186a0836040015161ffff16613c708660200151847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1661412990919063ffffffff16565b613c7a9190615645565b613c84919061565c565b9150505b6060820151613c979088615c04565b9650816080015186613ca99190615c04565b8251909650600090613cc89063ffffffff16662386f26fc10000615645565b905080821015613ce757613cdc818a615937565b985050505050613d38565b6000836020015163ffffffff16662386f26fc10000613d069190615645565b905080831115613d2657613d1a818b615937565b99505050505050613d38565b613d30838b615937565b995050505050505b600101613a7d565b505096509650969350505050565b60008063ffffffff8316613d6461016086615645565b613d70876101c0615937565b613d7a9190615937565b613d849190615937565b905060008760c0015163ffffffff168860e0015161ffff1683613da79190615645565b613db19190615937565b61010089015190915061ffff16613dd86dffffffffffffffffffffffffffff891683615645565b613de29190615645565b613df290655af3107a4000615645565b98975050505050505050565b60408051808201909152600080825260208201526000613e2a858585610160015163ffffffff16613665565b9050826060015163ffffffff1681600001511115613e74576040517f4c4fc93a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b826101c001518015613e8857508060200151155b15610b8c576040517fee433e9900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff821603613f3e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610d2f565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60008151602014613ff357816040517f8d666f60000000000000000000000000000000000000000000000000000000008152600401610d2f9190614578565b6000828060200190518101906140099190615b2b565b905073ffffffffffffffffffffffffffffffffffffffff81118061402e575061040081105b156112e957826040517f8d666f60000000000000000000000000000000000000000000000000000000008152600401610d2f9190614578565b6060816000018054806020026020016040519081016040528092919081815260200182805480156140b757602002820191906000526020600020905b8154815260200190600101908083116140a3575b50505050509050919050565b6000610b8f8373ffffffffffffffffffffffffffffffffffffffff8416614166565b6000610b8f8373ffffffffffffffffffffffffffffffffffffffff84166141b5565b6000610b8f8373ffffffffffffffffffffffffffffffffffffffff84166142af565b6000670de0b6b3a764000061415c837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8616615645565b610b8f919061565c565b60008181526001830160205260408120546141ad575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556112e9565b5060006112e9565b6000818152600183016020526040812054801561429e5760006141d9600183615924565b85549091506000906141ed90600190615924565b905080821461425257600086600001828154811061420d5761420d615697565b906000526020600020015490508087600001848154811061423057614230615697565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061426357614263615c21565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506112e9565b60009150506112e9565b5092915050565b6000818152600183016020526040812054801561429e5760006142d3600183615924565b85549091506000906142e790600190615924565b905081811461425257600086600001828154811061420d5761420d615697565b803573ffffffffffffffffffffffffffffffffffffffff8116811461432b57600080fd5b919050565b60008060006060848603121561434557600080fd5b61434e84614307565b92506020840135915061436360408501614307565b90509250925092565b60006020828403121561437e57600080fd5b610b8f82614307565b803567ffffffffffffffff8116811461432b57600080fd5b60008083601f8401126143b157600080fd5b50813567ffffffffffffffff8111156143c957600080fd5b6020830191508360208260051b850101111561231b57600080fd5b6000806000806000606086880312156143fc57600080fd5b61440586614387565b9450602086013567ffffffffffffffff8082111561442257600080fd5b61442e89838a0161439f565b9096509450604088013591508082111561444757600080fd5b818801915088601f83011261445b57600080fd5b81358181111561446a57600080fd5b8960208260061b850101111561447f57600080fd5b9699959850939650602001949392505050565b6000815180845260005b818110156144b85760208185018101518683018201520161449c565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b600060208083016020845280855180835260408601915060408160051b87010192506020870160005b8281101561456b577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0888603018452614559858351614492565b9450928501929085019060010161451f565b5092979650505050505050565b602081526000610b8f6020830184614492565b6020808252825182820181905260009190848201906040850190845b818110156145d957835173ffffffffffffffffffffffffffffffffffffffff16835292840192918401916001016145a7565b50909695505050505050565b6000602082840312156145f757600080fd5b813567ffffffffffffffff81111561460e57600080fd5b820160408185031215610b8f57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561467257614672614620565b60405290565b60405160a0810167ffffffffffffffff8111828210171561467257614672614620565b60405160c0810167ffffffffffffffff8111828210171561467257614672614620565b604051610200810167ffffffffffffffff8111828210171561467257614672614620565b6040516060810167ffffffffffffffff8111828210171561467257614672614620565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561474c5761474c614620565b604052919050565b600067ffffffffffffffff82111561476e5761476e614620565b5060051b60200190565b60ff811681146111df57600080fd5b6000602080838503121561479a57600080fd5b823567ffffffffffffffff8111156147b157600080fd5b8301601f810185136147c257600080fd5b80356147d56147d082614754565b614705565b818152606091820283018401918482019190888411156147f457600080fd5b938501935b8385101561489457848903818112156148125760008081fd5b61481a61464f565b61482387614307565b81526040807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0840112156148575760008081fd5b61485f61464f565b925061486c898901614307565b835287013561487a81614778565b8289015280880191909152835293840193918501916147f9565b50979650505050505050565b80151581146111df57600080fd5b803561432b816148a0565b600060208083850312156148cc57600080fd5b823567ffffffffffffffff8111156148e357600080fd5b8301601f810185136148f457600080fd5b80356149026147d082614754565b81815260a0918202830184019184820191908884111561492157600080fd5b938501935b838510156148945780858a03121561493e5760008081fd5b614946614678565b61494f86614307565b8152868601357fffffffffffffffffffff00000000000000000000000000000000000000000000811681146149845760008081fd5b818801526040868101357fffff000000000000000000000000000000000000000000000000000000000000811681146149bd5760008081fd5b9082015260606149ce878201614307565b908201526080868101356149e1816148a0565b9082015283529384019391850191614926565b60008060208385031215614a0757600080fd5b823567ffffffffffffffff811115614a1e57600080fd5b614a2a8582860161439f565b90969095509350505050565b602080825282518282018190526000919060409081850190868401855b82811015614aa457614a9484835180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16825260209081015163ffffffff16910152565b9284019290850190600101614a53565b5091979650505050505050565b600060208284031215614ac357600080fd5b610b8f82614387565b81517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16815260208083015163ffffffff1690820152604081016112e9565b81511515815261020081016020830151614b27602084018261ffff169052565b506040830151614b3f604084018263ffffffff169052565b506060830151614b57606084018263ffffffff169052565b506080830151614b6f608084018263ffffffff169052565b5060a0830151614b8560a084018261ffff169052565b5060c0830151614b9d60c084018263ffffffff169052565b5060e0830151614bb360e084018261ffff169052565b506101008381015161ffff9081169184019190915261012080850151909116908301526101408084015163ffffffff90811691840191909152610160808501518216908401526101808085015167ffffffffffffffff16908401526101a080850151909116908301526101c0808401511515908301526101e0808401517fffffffff000000000000000000000000000000000000000000000000000000008116828501525b505092915050565b803563ffffffff8116811461432b57600080fd5b803561ffff8116811461432b57600080fd5b600082601f830112614c9757600080fd5b81356020614ca76147d083614754565b82815260069290921b84018101918181019086841115614cc657600080fd5b8286015b84811015614d135760408189031215614ce35760008081fd5b614ceb61464f565b614cf482614387565b8152614d01858301614307565b81860152835291830191604001614cca565b509695505050505050565b60008060408385031215614d3157600080fd5b67ffffffffffffffff83351115614d4757600080fd5b83601f843585010112614d5957600080fd5b614d696147d08435850135614754565b8335840180358083526020808401939260059290921b90910101861015614d8f57600080fd5b602085358601015b85358601803560051b01602001811015614f9c5767ffffffffffffffff81351115614dc157600080fd5b8035863587010160407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0828a03011215614dfa57600080fd5b614e0261464f565b614e0e60208301614387565b815267ffffffffffffffff60408301351115614e2957600080fd5b88603f604084013584010112614e3e57600080fd5b614e546147d06020604085013585010135614754565b6020604084810135850182810135808552928401939260e00201018b1015614e7b57600080fd5b6040808501358501015b6040858101358601602081013560e0020101811015614f7d5760e0818d031215614eae57600080fd5b614eb661464f565b614ebf82614307565b815260c07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0838f03011215614ef357600080fd5b614efb61469b565b614f0760208401614c60565b8152614f1560408401614c60565b6020820152614f2660608401614c74565b6040820152614f3760808401614c60565b6060820152614f4860a08401614c60565b6080820152614f5a60c08401356148a0565b60c083013560a0820152602082810191909152908452929092019160e001614e85565b5080602084015250508085525050602083019250602081019050614d97565b5092505067ffffffffffffffff60208401351115614fb957600080fd5b614fc98460208501358501614c86565b90509250929050565b600082601f830112614fe357600080fd5b81356020614ff36147d083614754565b8083825260208201915060208460051b87010193508684111561501557600080fd5b602086015b84811015614d135761502b81614307565b835291830191830161501a565b6000806040838503121561504b57600080fd5b823567ffffffffffffffff8082111561506357600080fd5b61506f86838701614fd2565b9350602085013591508082111561508557600080fd5b5061509285828601614fd2565b9150509250929050565b60008083601f8401126150ae57600080fd5b50813567ffffffffffffffff8111156150c657600080fd5b60208301915083602082850101111561231b57600080fd5b600080600080604085870312156150f457600080fd5b843567ffffffffffffffff8082111561510c57600080fd5b6151188883890161509c565b9096509450602087013591508082111561513157600080fd5b5061513e8782880161509c565b95989497509550505050565b6000806040838503121561515d57600080fd5b61516683614387565b9150614fc960208401614307565b60006020828403121561518657600080fd5b813567ffffffffffffffff8082111561519e57600080fd5b90830190604082860312156151b257600080fd5b6151ba61464f565b8235828111156151c957600080fd5b6151d587828601614fd2565b8252506020830135828111156151ea57600080fd5b6151f687828601614fd2565b60208301525095945050505050565b80357fffffffff000000000000000000000000000000000000000000000000000000008116811461432b57600080fd5b6000602080838503121561524857600080fd5b823567ffffffffffffffff81111561525f57600080fd5b8301601f8101851361527057600080fd5b803561527e6147d082614754565b818152610220918202830184019184820191908884111561529e57600080fd5b938501935b8385101561489457848903818112156152bc5760008081fd5b6152c461464f565b6152cd87614387565b8152610200807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0840112156153025760008081fd5b61530a6146be565b92506153178989016148ae565b83526040615326818a01614c74565b8a8501526060615337818b01614c60565b828601526080915061534a828b01614c60565b9085015260a061535b8a8201614c60565b8286015260c0915061536e828b01614c74565b9085015260e061537f8a8201614c60565b828601526101009150615393828b01614c74565b908501526101206153a58a8201614c74565b8286015261014091506153b9828b01614c74565b908501526101606153cb8a8201614c60565b8286015261018091506153df828b01614c60565b908501526101a06153f18a8201614387565b828601526101c09150615405828b01614c60565b908501526101e06154178a82016148ae565b82860152615426838b01615205565b90850152505080880191909152835293840193918501916152a3565b6000602080838503121561545557600080fd5b823567ffffffffffffffff81111561546c57600080fd5b8301601f8101851361547d57600080fd5b803561548b6147d082614754565b81815260069190911b820183019083810190878311156154aa57600080fd5b928401925b828410156154fc57604084890312156154c85760008081fd5b6154d061464f565b6154d985614307565b81526154e6868601614387565b81870152825260409390930192908401906154af565b979650505050505050565b60008060008060006080868803121561551f57600080fd5b61552886614387565b945061553660208701614307565b935060408601359250606086013567ffffffffffffffff81111561555957600080fd5b6155658882890161509c565b969995985093965092949392505050565b8381528215156020820152606060408201526000612f406060830184614492565b600080604083850312156155aa57600080fd5b6155b383614387565b9150602083013567ffffffffffffffff8111156155cf57600080fd5b830160a081860312156155e157600080fd5b809150509250929050565b600080604083850312156155ff57600080fd5b61560883614307565b9150614fc960208401614387565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80820281158282048414176112e9576112e9615616565b600082615692577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff618336030181126156fa57600080fd5b9190910192915050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261573957600080fd5b83018035915067ffffffffffffffff82111561575457600080fd5b60200191503681900382131561231b57600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261579e57600080fd5b83018035915067ffffffffffffffff8211156157b957600080fd5b6020019150600681901b360382131561231b57600080fd5b80357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116811461432b57600080fd5b60006040828403121561580f57600080fd5b61581761464f565b61582083614307565b815261582e602084016157d1565b60208201529392505050565b60006040828403121561584c57600080fd5b61585461464f565b61582083614387565b6000602080838503121561587057600080fd5b823567ffffffffffffffff81111561588757600080fd5b8301601f8101851361589857600080fd5b80356158a66147d082614754565b818152606091820283018401918482019190888411156158c557600080fd5b938501935b838510156148945780858a0312156158e25760008081fd5b6158ea6146e2565b6158f386614307565b81526159008787016157d1565b878201526040615911818801614c60565b90820152835293840193918501916158ca565b818103818111156112e9576112e9615616565b808201808211156112e9576112e9615616565b60ff81811683821601908111156112e9576112e9615616565b600181815b808511156159bc57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156159a2576159a2615616565b808516156159af57918102915b93841c9390800290615968565b509250929050565b6000826159d3575060016112e9565b816159e0575060006112e9565b81600181146159f65760028114615a0057615a1c565b60019150506112e9565b60ff841115615a1157615a11615616565b50506001821b6112e9565b5060208310610133831016604e8410600b8410161715615a3f575081810a6112e9565b615a498383615963565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115615a7b57615a7b615616565b029392505050565b6000610b8f83836159c4565b7fffffffff000000000000000000000000000000000000000000000000000000008135818116916004851015614c585760049490940360031b84901b1690921692915050565b60008085851115615ae557600080fd5b83861115615af257600080fd5b5050820193919092039150565b600060408284031215615b1157600080fd5b615b1961464f565b82518152602083015161582e816148a0565b600060208284031215615b3d57600080fd5b5051919050565b805169ffffffffffffffffffff8116811461432b57600080fd5b600080600080600060a08688031215615b7657600080fd5b615b7f86615b44565b9450602086015193506040860151925060608601519150615ba260808701615b44565b90509295509295909350565b600060208284031215615bc057600080fd5b8151610b8f81614778565b600060408284031215615bdd57600080fd5b615be561464f565b615bee83614307565b8152602083013560208201528091505092915050565b63ffffffff8181168382160190808211156142a8576142a8615616565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint96\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"linkToken\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"stalenessThreshold\",\"type\":\"uint32\"}],\"internalType\":\"structFeeQuoter.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"priceUpdaters\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"feeTokens\",\"type\":\"address[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"}],\"internalType\":\"structFeeQuoter.TokenPriceFeedConfig\",\"name\":\"feedConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.TokenPriceFeedUpdate[]\",\"name\":\"tokenPriceFeeds\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigSingleTokenArgs[]\",\"name\":\"tokenTransferFeeConfigs\",\"type\":\"tuple[]\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigArgs[]\",\"name\":\"tokenTransferFeeConfigArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"internalType\":\"structFeeQuoter.PremiumMultiplierWeiPerEthArgs[]\",\"name\":\"premiumMultiplierWeiPerEthArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chain\",\"type\":\"uint64\"}],\"name\":\"ChainNotSupported\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DataFeedValueOutOfUint224Range\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"DestinationChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ExtraArgOutOfOrderExecutionMustBeTrue\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"FeeTokenNotSupported\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"}],\"name\":\"InvalidDestBytesOverhead\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidDestChainConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidEVMAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidExtraArgsTag\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidStaticConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"msgFeeJuels\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint256\"}],\"name\":\"MessageFeeTooHigh\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MessageGasLimitTooHigh\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"maxSize\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualSize\",\"type\":\"uint256\"}],\"name\":\"MessageTooLarge\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"internalType\":\"bytes10\",\"name\":\"workflowName\",\"type\":\"bytes10\"},{\"internalType\":\"bytes2\",\"name\":\"reportName\",\"type\":\"bytes2\"}],\"name\":\"ReportForwarderUnauthorized\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"SourceTokenDataTooLarge\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"threshold\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timePassed\",\"type\":\"uint256\"}],\"name\":\"StaleGasPrice\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feedTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"storedTimeStamp\",\"type\":\"uint256\"}],\"name\":\"StaleKeystoneUpdate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"TokenNotSupported\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"UnauthorizedCaller\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnsupportedNumberOfTokens\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"AuthorizedCallerAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"AuthorizedCallerRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"indexed\":false,\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"name\":\"DestChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"indexed\":false,\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"name\":\"DestChainConfigUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"}],\"name\":\"FeeTokenAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"}],\"name\":\"FeeTokenRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"name\":\"PremiumMultiplierWeiPerEthUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"}],\"indexed\":false,\"internalType\":\"structFeeQuoter.TokenPriceFeedConfig\",\"name\":\"priceFeedConfig\",\"type\":\"tuple\"}],\"name\":\"PriceFeedPerTokenUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"reportId\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"},{\"internalType\":\"bytes10\",\"name\":\"workflowName\",\"type\":\"bytes10\"},{\"internalType\":\"bytes2\",\"name\":\"reportName\",\"type\":\"bytes2\"},{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isAllowed\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"structKeystoneFeedsPermissionHandler.Permission\",\"name\":\"permission\",\"type\":\"tuple\"}],\"name\":\"ReportPermissionSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"TokenTransferFeeConfigDeleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"name\":\"TokenTransferFeeConfigUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"UsdPerTokenUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChain\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"UsdPerUnitGasUpdated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"FEE_BASE_DECIMALS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"KEYSTONE_PRICE_DECIMALS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address[]\",\"name\":\"addedCallers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"removedCallers\",\"type\":\"address[]\"}],\"internalType\":\"structAuthorizedCallers.AuthorizedCallerArgs\",\"name\":\"authorizedCallerArgs\",\"type\":\"tuple\"}],\"name\":\"applyAuthorizedCallerUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyDestChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"feeTokensToAdd\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"feeTokensToRemove\",\"type\":\"address[]\"}],\"name\":\"applyFeeTokensUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"internalType\":\"structFeeQuoter.PremiumMultiplierWeiPerEthArgs[]\",\"name\":\"premiumMultiplierWeiPerEthArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyPremiumMultiplierWeiPerEthUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigSingleTokenArgs[]\",\"name\":\"tokenTransferFeeConfigs\",\"type\":\"tuple[]\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigArgs[]\",\"name\":\"tokenTransferFeeConfigArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigRemoveArgs[]\",\"name\":\"tokensToUseDefaultFeeConfigs\",\"type\":\"tuple[]\"}],\"name\":\"applyTokenTransferFeeConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"fromToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fromTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"toToken\",\"type\":\"address\"}],\"name\":\"convertTokenAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllAuthorizedCallers\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getDestChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getDestinationChainGasPrice\",\"outputs\":[{\"components\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"internalType\":\"structInternal.TimestampedPackedUint224\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getFeeTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getPremiumMultiplierWeiPerEth\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint96\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"linkToken\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"stalenessThreshold\",\"type\":\"uint32\"}],\"internalType\":\"structFeeQuoter.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getTokenAndGasPrices\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"tokenPrice\",\"type\":\"uint224\"},{\"internalType\":\"uint224\",\"name\":\"gasPriceValue\",\"type\":\"uint224\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenPrice\",\"outputs\":[{\"components\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"internalType\":\"structInternal.TimestampedPackedUint224\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenPriceFeedConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"}],\"internalType\":\"structFeeQuoter.TokenPriceFeedConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"tokens\",\"type\":\"address[]\"}],\"name\":\"getTokenPrices\",\"outputs\":[{\"components\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"internalType\":\"structInternal.TimestampedPackedUint224[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenTransferFeeConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"getValidatedFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getValidatedTokenPrice\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"\",\"type\":\"uint224\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"onReport\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"rampTokenAmounts\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"sourceTokenAmounts\",\"type\":\"tuple[]\"}],\"name\":\"processMessageArgs\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"msgFeeJuels\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isOutOfOrderExecution\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"convertedExtraArgs\",\"type\":\"bytes\"},{\"internalType\":\"bytes[]\",\"name\":\"destExecDataPerToken\",\"type\":\"bytes[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"},{\"internalType\":\"bytes10\",\"name\":\"workflowName\",\"type\":\"bytes10\"},{\"internalType\":\"bytes2\",\"name\":\"reportName\",\"type\":\"bytes2\"},{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isAllowed\",\"type\":\"bool\"}],\"internalType\":\"structKeystoneFeedsPermissionHandler.Permission[]\",\"name\":\"permissions\",\"type\":\"tuple[]\"}],\"name\":\"setReportPermissions\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"}],\"name\":\"updatePrices\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"}],\"internalType\":\"structFeeQuoter.TokenPriceFeedConfig\",\"name\":\"feedConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.TokenPriceFeedUpdate[]\",\"name\":\"tokenPriceFeedUpdates\",\"type\":\"tuple[]\"}],\"name\":\"updateTokenPriceFeeds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x60e06040523480156200001157600080fd5b506040516200776138038062007761833981016040819052620000349162001834565b8533806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf8162000207565b5050604080518082018252838152815160008152602080820190935291810191909152620000ee9150620002b2565b5060208701516001600160a01b0316158062000112575086516001600160601b0316155b80620001265750604087015163ffffffff16155b15620001455760405163d794ef9560e01b815260040160405180910390fd5b6020878101516001600160a01b031660a05287516001600160601b031660805260408089015163ffffffff1660c05280516000815291820190526200018c90869062000401565b620001978462000549565b620001a2816200061a565b620001ad8262000a5a565b60408051600080825260208201909252620001fa91859190620001f3565b6040805180820190915260008082526020820152815260200190600190039081620001cb5790505b5062000b26565b5050505050505062001ae5565b336001600160a01b03821603620002615760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b602081015160005b815181101562000342576000828281518110620002db57620002db62001953565b60209081029190910101519050620002f560028262000e5f565b1562000338576040516001600160a01b03821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b50600101620002ba565b50815160005b8151811015620003fb57600082828151811062000369576200036962001953565b6020026020010151905060006001600160a01b0316816001600160a01b031603620003a7576040516342bcdf7f60e11b815260040160405180910390fd5b620003b460028262000e7f565b506040516001600160a01b03821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a15060010162000348565b50505050565b60005b8251811015620004a2576200044083828151811062000427576200042762001953565b6020026020010151600b62000e7f60201b90919060201c565b1562000499578281815181106200045b576200045b62001953565b60200260200101516001600160a01b03167fdf1b1bd32a69711488d71554706bb130b1fc63a5fa1a2cd85e8440f84065ba2360405160405180910390a25b60010162000404565b5060005b81518110156200054457620004e2828281518110620004c957620004c962001953565b6020026020010151600b62000e9660201b90919060201c565b156200053b57818181518110620004fd57620004fd62001953565b60200260200101516001600160a01b03167f1795838dc8ab2ffc5f431a1729a6afa0b587f982f7b2be0b9d7187a1ef547f9160405160405180910390a25b600101620004a6565b505050565b60005b8151811015620006165760008282815181106200056d576200056d62001953565b6020908102919091018101518051818301516001600160a01b0380831660008181526007875260409081902084518154868a018051929096166001600160a81b03199091168117600160a01b60ff9384160217909255825191825293519093169683019690965293955091939092917f08a5f7f5bb38a81d8e43aca13ecd76431dbf8816ae4699affff7b00b2fc1c464910160405180910390a25050508060010190506200054c565b5050565b60005b8151811015620006165760008282815181106200063e576200063e62001953565b6020026020010151905060008383815181106200065f576200065f62001953565b6020026020010151600001519050600082602001519050816001600160401b03166000148062000698575061016081015163ffffffff16155b80620006ba57506101e08101516001600160e01b031916630a04b54b60e21b14155b80620006da5750806060015163ffffffff1681610160015163ffffffff16115b15620007055760405163c35aa79d60e01b81526001600160401b038316600482015260240162000083565b6001600160401b038216600090815260096020526040812060010154600160881b900460e01b6001600160e01b03191690036200078557816001600160401b03167fd31c671936387b2f84ed402b553bd50c0e9c20408ea4e91a836d77b8180fb7248260405162000777919062001969565b60405180910390a2620007c9565b816001600160401b03167f1edd6f3553cfa16f10b95b195abae3a1cfca4783de4843f95d674b1e1df5ab2082604051620007c0919062001969565b60405180910390a25b8060096000846001600160401b03166001600160401b0316815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548161ffff021916908361ffff16021790555060408201518160000160036101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160076101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600b6101000a81548163ffffffff021916908363ffffffff16021790555060a082015181600001600f6101000a81548161ffff021916908361ffff16021790555060c08201518160000160116101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160000160156101000a81548161ffff021916908361ffff1602179055506101008201518160000160176101000a81548161ffff021916908361ffff1602179055506101208201518160000160196101000a81548161ffff021916908361ffff16021790555061014082015181600001601b6101000a81548163ffffffff021916908363ffffffff1602179055506101608201518160010160006101000a81548163ffffffff021916908363ffffffff1602179055506101808201518160010160046101000a8154816001600160401b0302191690836001600160401b031602179055506101a082015181600101600c6101000a81548163ffffffff021916908363ffffffff1602179055506101c08201518160010160106101000a81548160ff0219169083151502179055506101e08201518160010160116101000a81548163ffffffff021916908360e01c02179055509050505050508060010190506200061d565b60005b81518110156200061657600082828151811062000a7e5762000a7e62001953565b6020026020010151600001519050600083838151811062000aa35762000aa362001953565b6020908102919091018101518101516001600160a01b03841660008181526008845260409081902080546001600160401b0319166001600160401b0385169081179091559051908152919350917fbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d910160405180910390a2505060010162000a5d565b60005b825181101562000d9957600083828151811062000b4a5762000b4a62001953565b6020026020010151905060008160000151905060005b82602001515181101562000d8a5760008360200151828151811062000b895762000b8962001953565b602002602001015160200151905060008460200151838151811062000bb25762000bb262001953565b6020026020010151600001519050602063ffffffff16826080015163ffffffff16101562000c115760808201516040516312766e0160e11b81526001600160a01b038316600482015263ffffffff909116602482015260440162000083565b6001600160401b0384166000818152600a602090815260408083206001600160a01b0386168085529083529281902086518154938801518389015160608a015160808b015160a08c01511515600160901b0260ff60901b1963ffffffff928316600160701b021664ffffffffff60701b199383166a01000000000000000000000263ffffffff60501b1961ffff90961668010000000000000000029590951665ffffffffffff60401b19968416640100000000026001600160401b0319909b16939097169290921798909817939093169390931717919091161792909217909155519091907f94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b59062000d77908690600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60405180910390a3505060010162000b60565b50505080600101905062000b29565b5060005b81518110156200054457600082828151811062000dbe5762000dbe62001953565b6020026020010151600001519050600083838151811062000de35762000de362001953565b6020908102919091018101518101516001600160401b0384166000818152600a845260408082206001600160a01b038516808452955280822080546001600160981b03191690555192945090917f4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b9190a3505060010162000d9d565b600062000e76836001600160a01b03841662000ead565b90505b92915050565b600062000e76836001600160a01b03841662000fb1565b600062000e76836001600160a01b03841662001003565b6000818152600183016020526040812054801562000fa657600062000ed460018362001aad565b855490915060009062000eea9060019062001aad565b905081811462000f5657600086600001828154811062000f0e5762000f0e62001953565b906000526020600020015490508087600001848154811062000f345762000f3462001953565b6000918252602080832090910192909255918252600188019052604090208390555b855486908062000f6a5762000f6a62001acf565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505062000e79565b600091505062000e79565b600081815260018301602052604081205462000ffa5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000e79565b50600062000e79565b6000818152600183016020526040812054801562000fa65760006200102a60018362001aad565b8554909150600090620010409060019062001aad565b905080821462000f5657600086600001828154811062000f0e5762000f0e62001953565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b03811182821017156200109f576200109f62001064565b60405290565b60405160c081016001600160401b03811182821017156200109f576200109f62001064565b60405161020081016001600160401b03811182821017156200109f576200109f62001064565b604051601f8201601f191681016001600160401b03811182821017156200111b576200111b62001064565b604052919050565b80516001600160a01b03811681146200113b57600080fd5b919050565b805163ffffffff811681146200113b57600080fd5b6000606082840312156200116857600080fd5b604051606081016001600160401b03811182821017156200118d576200118d62001064565b604052825190915081906001600160601b0381168114620011ad57600080fd5b8152620011bd6020840162001123565b6020820152620011d06040840162001140565b60408201525092915050565b60006001600160401b03821115620011f857620011f862001064565b5060051b60200190565b600082601f8301126200121457600080fd5b815160206200122d6200122783620011dc565b620010f0565b8083825260208201915060208460051b8701019350868411156200125057600080fd5b602086015b848110156200127757620012698162001123565b835291830191830162001255565b509695505050505050565b600082601f8301126200129457600080fd5b81516020620012a76200122783620011dc565b82815260609283028501820192828201919087851115620012c757600080fd5b8387015b858110156200135a5780890382811215620012e65760008081fd5b620012f06200107a565b620012fb8362001123565b8152604080601f1984011215620013125760008081fd5b6200131c6200107a565b92506200132b88850162001123565b835283015160ff81168114620013415760008081fd5b82880152808701919091528452928401928101620012cb565b5090979650505050505050565b80516001600160401b03811681146200113b57600080fd5b805161ffff811681146200113b57600080fd5b805180151581146200113b57600080fd5b600082601f830112620013b557600080fd5b81516020620013c86200122783620011dc565b82815260059290921b84018101918181019086841115620013e857600080fd5b8286015b84811015620012775780516001600160401b03808211156200140d57600080fd5b908801906040601f19838c0381018213156200142857600080fd5b620014326200107a565b6200143f89860162001367565b815282850151848111156200145357600080fd5b8086019550508c603f8601126200146957600080fd5b8885015193506200147e6200122785620011dc565b84815260e09094028501830193898101908e8611156200149d57600080fd5b958401955b858710156200157657868f0360e0811215620014bd57600080fd5b620014c76200107a565b620014d28962001123565b815260c08683011215620014e557600080fd5b620014ef620010a5565b9150620014fe8d8a0162001140565b82526200150d878a0162001140565b8d8301526200151f60608a016200137f565b878301526200153160808a0162001140565b60608301526200154460a08a0162001140565b60808301526200155760c08a0162001392565b60a0830152808d0191909152825260e09690960195908a0190620014a2565b828b015250875250505092840192508301620013ec565b600082601f8301126200159f57600080fd5b81516020620015b26200122783620011dc565b82815260069290921b84018101918181019086841115620015d257600080fd5b8286015b84811015620012775760408189031215620015f15760008081fd5b620015fb6200107a565b620016068262001123565b81526200161585830162001367565b81860152835291830191604001620015d6565b80516001600160e01b0319811681146200113b57600080fd5b600082601f8301126200165357600080fd5b81516020620016666200122783620011dc565b82815261022092830285018201928282019190878511156200168757600080fd5b8387015b858110156200135a5780890382811215620016a65760008081fd5b620016b06200107a565b620016bb8362001367565b815261020080601f1984011215620016d35760008081fd5b620016dd620010ca565b9250620016ec88850162001392565b83526040620016fd8186016200137f565b8985015260606200171081870162001140565b82860152608091506200172582870162001140565b9085015260a06200173886820162001140565b8286015260c091506200174d8287016200137f565b9085015260e06200176086820162001140565b828601526101009150620017768287016200137f565b908501526101206200178a8682016200137f565b828601526101409150620017a08287016200137f565b90850152610160620017b486820162001140565b828601526101809150620017ca82870162001140565b908501526101a0620017de86820162001367565b828601526101c09150620017f482870162001140565b908501526101e06200180886820162001392565b828601526200181983870162001628565b9085015250508087019190915284529284019281016200168b565b6000806000806000806000610120888a0312156200185157600080fd5b6200185d898962001155565b60608901519097506001600160401b03808211156200187b57600080fd5b620018898b838c0162001202565b975060808a0151915080821115620018a057600080fd5b620018ae8b838c0162001202565b965060a08a0151915080821115620018c557600080fd5b620018d38b838c0162001282565b955060c08a0151915080821115620018ea57600080fd5b620018f88b838c01620013a3565b945060e08a01519150808211156200190f57600080fd5b6200191d8b838c016200158d565b93506101008a01519150808211156200193557600080fd5b50620019448a828b0162001641565b91505092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b815115158152610200810160208301516200198a602084018261ffff169052565b506040830151620019a3604084018263ffffffff169052565b506060830151620019bc606084018263ffffffff169052565b506080830151620019d5608084018263ffffffff169052565b5060a0830151620019ec60a084018261ffff169052565b5060c083015162001a0560c084018263ffffffff169052565b5060e083015162001a1c60e084018261ffff169052565b506101008381015161ffff9081169184019190915261012080850151909116908301526101408084015163ffffffff9081169184019190915261016080850151821690840152610180808501516001600160401b0316908401526101a080850151909116908301526101c0808401511515908301526101e0928301516001600160e01b031916929091019190915290565b8181038181111562000e7957634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b60805160a05160c051615c1b62001b46600039600081816102fa0152818161184d01528181611ee90152611f520152600081816102be0152818161158501526115e501526000818161028a0152818161160e015261167e0152615c1b6000f3fe608060405234801561001057600080fd5b50600436106101d95760003560e01c80637afac32211610104578063a69c64c0116100a2578063d63d3af211610071578063d63d3af214610a88578063d8694ccd14610a90578063f2fde38b14610aa3578063ffdb4b3714610ab657600080fd5b8063a69c64c0146109ad578063bf78e03f146109c0578063cdc73d5114610a6d578063d02641a014610a7557600080fd5b80638da5cb5b116100de5780638da5cb5b1461093c57806391a2749a1461096457806397d640a2146109775780639ea600261461099a57600080fd5b80637afac322146107a6578063805f2132146107b957806382b49eb0146107cc57600080fd5b8063407e10861161017c578063514e8cff1161014b578063514e8cff146104745780636def4ce714610517578063770e2dc41461078b57806379ba50971461079e57600080fd5b8063407e1086146103ee57806341ed29e71461040157806345ac924d146104145780634ab35b0b1461043457600080fd5b8063181f5a77116101b8578063181f5a77146103735780632451a627146103bc578063325c868e146103d15780633937306f146103d957600080fd5b806241e5be146101de578063061877e31461020457806306285c691461025d575b600080fd5b6101f16101ec36600461431b565b610afe565b6040519081526020015b60405180910390f35b610244610212366004614357565b73ffffffffffffffffffffffffffffffffffffffff1660009081526008602052604090205467ffffffffffffffff1690565b60405167ffffffffffffffff90911681526020016101fb565b610327604080516060810182526000808252602082018190529181019190915260405180606001604052807f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000063ffffffff16815250905090565b6040805182516bffffffffffffffffffffffff16815260208084015173ffffffffffffffffffffffffffffffffffffffff16908201529181015163ffffffff16908201526060016101fb565b6103af6040518060400160405280601381526020017f46656551756f74657220312e362e302d6465760000000000000000000000000081525081565b6040516101fb91906143d6565b6103c4610b6c565b6040516101fb91906143e9565b6101f1602481565b6103ec6103e7366004614443565b610b7d565b005b6103ec6103fc3660046145e5565b610e32565b6103ec61040f366004614717565b610e46565b610427610422366004614897565b610e88565b6040516101fb91906148d9565b610447610442366004614357565b610f53565b6040517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff90911681526020016101fb565b61050a61048236600461496c565b60408051808201909152600080825260208201525067ffffffffffffffff166000908152600560209081526040918290208251808401909352547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811683527c0100000000000000000000000000000000000000000000000000000000900463ffffffff169082015290565b6040516101fb9190614987565b61077e61052536600461496c565b6040805161020081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a081018290526101c081018290526101e08101919091525067ffffffffffffffff908116600090815260096020908152604091829020825161020081018452815460ff8082161515835261ffff61010080840482169685019690965263ffffffff630100000084048116978501979097526701000000000000008304871660608501526b0100000000000000000000008304871660808501526f010000000000000000000000000000008304811660a085015271010000000000000000000000000000000000808404881660c086015275010000000000000000000000000000000000000000008404821660e08087019190915277010000000000000000000000000000000000000000000000850483169786019790975279010000000000000000000000000000000000000000000000000084049091166101208501527b01000000000000000000000000000000000000000000000000000000909204861661014084015260019093015480861661016084015264010000000081049096166101808301526c0100000000000000000000000086049094166101a0820152700100000000000000000000000000000000850490911615156101c08201527fffffffff0000000000000000000000000000000000000000000000000000000092909304901b166101e082015290565b6040516101fb91906149c2565b6103ec610799366004614bd9565b610f5e565b6103ec610f70565b6103ec6107b4366004614ef3565b611072565b6103ec6107c7366004614f99565b611084565b6108dc6107da366004615005565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101919091525067ffffffffffffffff919091166000908152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff94909416835292815290829020825160c081018452905463ffffffff8082168352640100000000820481169383019390935268010000000000000000810461ffff16938201939093526a01000000000000000000008304821660608201526e01000000000000000000000000000083049091166080820152720100000000000000000000000000000000000090910460ff16151560a082015290565b6040516101fb9190600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101fb565b6103ec61097236600461502f565b61156c565b61098a6109853660046150c0565b61157d565b6040516101fb94939291906151b4565b6103ec6109a8366004615283565b611788565b6103ec6109bb366004615490565b611799565b610a396109ce366004614357565b6040805180820182526000808252602091820181905273ffffffffffffffffffffffffffffffffffffffff93841681526007825282902082518084019093525492831682527401000000000000000000000000000000000000000090920460ff169181019190915290565b60408051825173ffffffffffffffffffffffffffffffffffffffff16815260209283015160ff1692810192909252016101fb565b6103c46117aa565b61050a610a83366004614357565b6117b6565b6101f1601281565b6101f1610a9e366004615555565b6118fa565b6103ec610ab1366004614357565b611e04565b610ac9610ac43660046155aa565b611e15565b604080517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff9384168152929091166020830152016101fb565b6000610b0982611fa0565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16610b3085611fa0565b610b58907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1685615603565b610b62919061561a565b90505b9392505050565b6060610b78600261203a565b905090565b610b85612047565b6000610b918280615655565b9050905060005b81811015610cdb576000610bac8480615655565b83818110610bbc57610bbc6156bd565b905060400201803603810190610bd29190615718565b604080518082018252602080840180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff908116845263ffffffff42818116858701908152885173ffffffffffffffffffffffffffffffffffffffff9081166000908152600690975295889020965190519092167c010000000000000000000000000000000000000000000000000000000002919092161790935584519051935194955016927f52f50aa6d1a95a4595361ecf953d095f125d442e4673716dede699e049de148a92610cca9290917bffffffffffffffffffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b60405180910390a250600101610b98565b506000610ceb6020840184615655565b9050905060005b81811015610e2c576000610d096020860186615655565b83818110610d1957610d196156bd565b905060400201803603810190610d2f9190615755565b604080518082018252602080840180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff908116845263ffffffff42818116858701908152885167ffffffffffffffff9081166000908152600590975295889020965190519092167c010000000000000000000000000000000000000000000000000000000002919092161790935584519051935194955016927fdd84a3fa9ef9409f550d54d6affec7e9c480c878c6ab27b78912a03e1b371c6e92610e1b9290917bffffffffffffffffffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b60405180910390a250600101610cf2565b50505050565b610e3a61208c565b610e438161210d565b50565b610e4e61208c565b60005b8151811015610e8457610e7c828281518110610e6f57610e6f6156bd565b602002602001015161220b565b600101610e51565b5050565b60608160008167ffffffffffffffff811115610ea657610ea661447e565b604051908082528060200260200182016040528015610eeb57816020015b6040805180820190915260008082526020820152815260200190600190039081610ec45790505b50905060005b82811015610f4857610f23868683818110610f0e57610f0e6156bd565b9050602002016020810190610a839190614357565b828281518110610f3557610f356156bd565b6020908102919091010152600101610ef1565b509150505b92915050565b6000610f4d82611fa0565b610f6661208c565b610e8482826123dd565b60015473ffffffffffffffffffffffffffffffffffffffff163314610ff6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b61107a61208c565b610e8482826127ef565b60008060006110c887878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061293692505050565b9250925092506110da33838584612951565b60006110e885870187615778565b905060005b81518110156115615760006007600084848151811061110e5761110e6156bd565b6020908102919091018101515173ffffffffffffffffffffffffffffffffffffffff16825281019190915260400160009081205474010000000000000000000000000000000000000000900460ff1691508190036111cf57828281518110611178576111786156bd565b6020908102919091010151516040517f06439c6b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610fed565b60006112186012838686815181106111e9576111e96156bd565b6020026020010151602001517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16612aa9565b905060066000858581518110611230576112306156bd565b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001601c9054906101000a900463ffffffff1663ffffffff168484815181106112a2576112a26156bd565b60200260200101516040015163ffffffff1610156113ac578383815181106112cc576112cc6156bd565b6020026020010151600001518484815181106112ea576112ea6156bd565b6020026020010151604001516006600087878151811061130c5761130c6156bd565b6020908102919091018101515173ffffffffffffffffffffffffffffffffffffffff90811683529082019290925260409081016000205490517f191ec70600000000000000000000000000000000000000000000000000000000815293909116600484015263ffffffff91821660248401527c01000000000000000000000000000000000000000000000000000000009004166044820152606401610fed565b6040518060400160405280827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1681526020018585815181106113ed576113ed6156bd565b60200260200101516040015163ffffffff1681525060066000868681518110611418576114186156bd565b6020908102919091018101515173ffffffffffffffffffffffffffffffffffffffff168252818101929092526040016000208251929091015163ffffffff167c0100000000000000000000000000000000000000000000000000000000027bffffffffffffffffffffffffffffffffffffffffffffffffffffffff90921691909117905583518490849081106114b0576114b06156bd565b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff167f52f50aa6d1a95a4595361ecf953d095f125d442e4673716dede699e049de148a82868681518110611506576115066156bd565b60200260200101516040015160405161154f9291907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff92909216825263ffffffff16602082015260400190565b60405180910390a250506001016110ed565b505050505050505050565b61157461208c565b610e4381612b75565b6000806060807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168c73ffffffffffffffffffffffffffffffffffffffff16036115de578a935061160c565b6116098c8c7f0000000000000000000000000000000000000000000000000000000000000000610afe565b93505b7f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff168411156116ab576040517f6a92a483000000000000000000000000000000000000000000000000000000008152600481018590526bffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166024820152604401610fed565b67ffffffffffffffff8d1660009081526009602052604081206001015463ffffffff16906116da8c8c84612d01565b9050806020015194506116f08f8b8b8b8b612eaa565b92508585611770836040805182516024820152602092830151151560448083019190915282518083039091018152606490910190915290810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f181dcf100000000000000000000000000000000000000000000000000000000017905290565b95509550955050509950995099509995505050505050565b61179061208c565b610e4381613217565b6117a161208c565b610e43816136bd565b6060610b78600b61203a565b604080518082019091526000808252602082015273ffffffffffffffffffffffffffffffffffffffff82166000908152600660209081526040918290208251808401909352547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116835263ffffffff7c010000000000000000000000000000000000000000000000000000000090910481169183018290527f00000000000000000000000000000000000000000000000000000000000000001690611878904261583f565b10156118845792915050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600760209081526040918290208251808401909352549283168083527401000000000000000000000000000000000000000090930460ff1690820152906118e9575092915050565b6118f2816137a7565b949350505050565b67ffffffffffffffff8083166000908152600960209081526040808320815161020081018352815460ff808216151580845261ffff61010080850482169886019890985263ffffffff630100000085048116978601979097526701000000000000008404871660608601526b0100000000000000000000008404871660808601526f010000000000000000000000000000008404811660a086015271010000000000000000000000000000000000808504881660c087015275010000000000000000000000000000000000000000008504821660e08088019190915277010000000000000000000000000000000000000000000000860483169987019990995279010000000000000000000000000000000000000000000000000085049091166101208601527b01000000000000000000000000000000000000000000000000000000909304861661014085015260019094015480861661016085015264010000000081049098166101808401526c0100000000000000000000000088049094166101a0830152700100000000000000000000000000000000870490931615156101c08201527fffffffff000000000000000000000000000000000000000000000000000000009290950490921b166101e0840152909190611b14576040517f99ac52f200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff85166004820152602401610fed565b611b2f611b276080850160608601614357565b600b90613936565b611b8e57611b436080840160608501614357565b6040517f2502348c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610fed565b6000611b9d6040850185615655565b9150611bf9905082611bb26020870187615852565b905083611bbf8880615852565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061396592505050565b600080611c15611c0f6080880160608901614357565b88611e15565b9092509050600080808515611c5857611c4c878b611c3960808d0160608e01614357565b88611c4760408f018f615655565b613a0f565b91945092509050611c78565b6101a0870151611c759063ffffffff16662386f26fc10000615603565b92505b61010087015160009061ffff1615611cbc57611cb9886dffffffffffffffffffffffffffff607088901c16611cb060208e018e615852565b90508a86613ce7565b90505b61018088015160009067ffffffffffffffff16611ce5611cdf60808e018e615852565b8c613d97565b600001518563ffffffff168b60a0015161ffff168e8060200190611d099190615852565b611d14929150615603565b8c6080015163ffffffff16611d2991906158b7565b611d3391906158b7565b611d3d91906158b7565b611d57906dffffffffffffffffffffffffffff8916615603565b611d619190615603565b9050867bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168282600860008f6060016020810190611d9b9190614357565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160002054611dd69067ffffffffffffffff1689615603565b611de091906158b7565b611dea91906158b7565b611df4919061561a565b9c9b505050505050505050505050565b611e0c61208c565b610e4381613e58565b67ffffffffffffffff811660009081526005602090815260408083208151808301909252547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811682527c0100000000000000000000000000000000000000000000000000000000900463ffffffff1691810182905282918203611ecd576040517f2e59db3a00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff85166004820152602401610fed565b6000816020015163ffffffff1642611ee5919061583f565b90507f000000000000000000000000000000000000000000000000000000000000000063ffffffff16811115611f86576040517ff08bcb3e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8616600482015263ffffffff7f000000000000000000000000000000000000000000000000000000000000000016602482015260448101829052606401610fed565b611f8f86611fa0565b9151919350909150505b9250929050565b600080611fac836117b6565b9050806020015163ffffffff1660001480611fe4575080517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16155b15612033576040517f06439c6b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152602401610fed565b5192915050565b60606000610b6583613f4d565b612052600233613936565b61208a576040517fd86ad9cf000000000000000000000000000000000000000000000000000000008152336004820152602401610fed565b565b60005473ffffffffffffffffffffffffffffffffffffffff16331461208a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610fed565b60005b8151811015610e8457600082828151811061212d5761212d6156bd565b60209081029190910181015180518183015173ffffffffffffffffffffffffffffffffffffffff80831660008181526007875260409081902084518154868a018051929096167fffffffffffffffffffffff00000000000000000000000000000000000000000090911681177401000000000000000000000000000000000000000060ff9384160217909255825191825293519093169683019690965293955091939092917f08a5f7f5bb38a81d8e43aca13ecd76431dbf8816ae4699affff7b00b2fc1c464910160405180910390a2505050806001019050612110565b60006122c482600001518360600151846020015185604001516040805173ffffffffffffffffffffffffffffffffffffffff80871660208301528516918101919091527fffffffffffffffffffff00000000000000000000000000000000000000000000831660608201527fffff0000000000000000000000000000000000000000000000000000000000008216608082015260009060a001604051602081830303815290604052805190602001209050949350505050565b60808301516000828152600460205260409081902080549215157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00909316929092179091555190915081907f32a4ba3fa3351b11ad555d4c8ec70a744e8705607077a946807030d64b6ab1a3906123d1908590600060a08201905073ffffffffffffffffffffffffffffffffffffffff8084511683527fffffffffffffffffffff0000000000000000000000000000000000000000000060208501511660208401527fffff00000000000000000000000000000000000000000000000000000000000060408501511660408401528060608501511660608401525060808301511515608083015292915050565b60405180910390a25050565b60005b82518110156127065760008382815181106123fd576123fd6156bd565b6020026020010151905060008160000151905060005b8260200151518110156126f857600083602001518281518110612438576124386156bd565b602002602001015160200151905060008460200151838151811061245e5761245e6156bd565b6020026020010151600001519050602063ffffffff16826080015163ffffffff1610156124e15760808201516040517f24ecdc0200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8316600482015263ffffffff9091166024820152604401610fed565b67ffffffffffffffff84166000818152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff86168085529083529281902086518154938801518389015160608a015160808b015160a08c015115157201000000000000000000000000000000000000027fffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffff63ffffffff9283166e01000000000000000000000000000002167fffffffffffffffffffffffffff0000000000ffffffffffffffffffffffffffff9383166a0100000000000000000000027fffffffffffffffffffffffffffffffffffff00000000ffffffffffffffffffff61ffff9096166801000000000000000002959095167fffffffffffffffffffffffffffffffffffff000000000000ffffffffffffffff968416640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000909b16939097169290921798909817939093169390931717919091161792909217909155519091907f94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b5906126e6908690600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60405180910390a35050600101612413565b5050508060010190506123e0565b5060005b81518110156127ea576000828281518110612727576127276156bd565b60200260200101516000015190506000838381518110612749576127496156bd565b60209081029190910181015181015167ffffffffffffffff84166000818152600a8452604080822073ffffffffffffffffffffffffffffffffffffffff8516808452955280822080547fffffffffffffffffffffffffff000000000000000000000000000000000000001690555192945090917f4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b9190a3505060010161270a565b505050565b60005b825181101561289257612828838281518110612810576128106156bd565b6020026020010151600b613fa990919063ffffffff16565b1561288a5782818151811061283f5761283f6156bd565b602002602001015173ffffffffffffffffffffffffffffffffffffffff167fdf1b1bd32a69711488d71554706bb130b1fc63a5fa1a2cd85e8440f84065ba2360405160405180910390a25b6001016127f2565b5060005b81518110156127ea576128cc8282815181106128b4576128b46156bd565b6020026020010151600b613fcb90919063ffffffff16565b1561292e578181815181106128e3576128e36156bd565b602002602001015173ffffffffffffffffffffffffffffffffffffffff167f1795838dc8ab2ffc5f431a1729a6afa0b587f982f7b2be0b9d7187a1ef547f9160405160405180910390a25b600101612896565b6040810151604a820151605e90920151909260609290921c91565b6040805173ffffffffffffffffffffffffffffffffffffffff868116602080840191909152908616828401527fffffffffffffffffffff00000000000000000000000000000000000000000000851660608301527fffff00000000000000000000000000000000000000000000000000000000000084166080808401919091528351808403909101815260a09092018352815191810191909120600081815260049092529190205460ff16612aa2576040517f097e17ff00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8087166004830152851660248201527fffffffffffffffffffff00000000000000000000000000000000000000000000841660448201527fffff00000000000000000000000000000000000000000000000000000000000083166064820152608401610fed565b5050505050565b600080612ab684866158ca565b9050600060248260ff161115612af057612ad4602460ff841661583f565b612adf90600a615a03565b612ae9908561561a565b9050612b16565b612afe60ff8316602461583f565b612b0990600a615a03565b612b139085615603565b90505b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811115612b6c576040517f10cb51d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b95945050505050565b602081015160005b8151811015612c10576000828281518110612b9a57612b9a6156bd565b60200260200101519050612bb8816002613fed90919063ffffffff16565b15612c075760405173ffffffffffffffffffffffffffffffffffffffff821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b50600101612b7d565b50815160005b8151811015610e2c576000828281518110612c3357612c336156bd565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603612ca3576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612cae600282613fa9565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a150600101612c16565b60408051808201909152600080825260208201526000839003612d4257506040805180820190915267ffffffffffffffff8216815260006020820152610b65565b6000612d4e8486615a0f565b90506000612d5f8560048189615a55565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505050507fffffffff0000000000000000000000000000000000000000000000000000000082167fe7e230f00000000000000000000000000000000000000000000000000000000001612dfc5780806020019051810190612df39190615a7f565b92505050610b65565b7f6859a837000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831601612e7857604051806040016040528082806020019051810190612e649190615aab565b815260006020909101529250610b65915050565b6040517f5247fdce00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff8086166000908152600960205260409020600101546060917101000000000000000000000000000000000090910460e01b908590811115612ef657612ef661447e565b604051908082528060200260200182016040528015612f2957816020015b6060815260200190600190039081612f145790505b50915060005b8581101561320c576000858583818110612f4b57612f4b6156bd565b612f619260206040909202019081019150614357565b90506000888884818110612f7757612f776156bd565b9050602002810190612f899190615ac4565b612f97906040810190615852565b91505060208111156130475767ffffffffffffffff8a166000908152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff861684529091529020546e010000000000000000000000000000900463ffffffff16811115613047576040517f36f536ca00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83166004820152602401610fed565b6130b7848a8a8681811061305d5761305d6156bd565b905060200281019061306f9190615ac4565b61307d906020810190615852565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061400f92505050565b67ffffffffffffffff8a166000818152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684528252808320815160c081018352905463ffffffff8082168352640100000000820481168386015268010000000000000000820461ffff16838501526a01000000000000000000008204811660608401526e010000000000000000000000000000820481166080840152720100000000000000000000000000000000000090910460ff16151560a08301908152958552600990935290832054935190937b01000000000000000000000000000000000000000000000000000000900490911691906131b657816131bc565b82606001515b6040805163ffffffff83166020820152919250016040516020818303038152906040528887815181106131f1576131f16156bd565b60200260200101819052505050505050806001019050612f2f565b505095945050505050565b60005b8151811015610e84576000828281518110613237576132376156bd565b602002602001015190506000838381518110613255576132556156bd565b60200260200101516000015190506000826020015190508167ffffffffffffffff166000148061328e575061016081015163ffffffff16155b806132e057506101e08101517fffffffff00000000000000000000000000000000000000000000000000000000167f2812d52c0000000000000000000000000000000000000000000000000000000014155b806132ff5750806060015163ffffffff1681610160015163ffffffff16115b15613342576040517fc35aa79d00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff83166004820152602401610fed565b67ffffffffffffffff821660009081526009602052604081206001015471010000000000000000000000000000000000900460e01b7fffffffff000000000000000000000000000000000000000000000000000000001690036133e6578167ffffffffffffffff167fd31c671936387b2f84ed402b553bd50c0e9c20408ea4e91a836d77b8180fb724826040516133d991906149c2565b60405180910390a2613429565b8167ffffffffffffffff167f1edd6f3553cfa16f10b95b195abae3a1cfca4783de4843f95d674b1e1df5ab208260405161342091906149c2565b60405180910390a25b80600960008467ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548161ffff021916908361ffff16021790555060408201518160000160036101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160076101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600b6101000a81548163ffffffff021916908363ffffffff16021790555060a082015181600001600f6101000a81548161ffff021916908361ffff16021790555060c08201518160000160116101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160000160156101000a81548161ffff021916908361ffff1602179055506101008201518160000160176101000a81548161ffff021916908361ffff1602179055506101208201518160000160196101000a81548161ffff021916908361ffff16021790555061014082015181600001601b6101000a81548163ffffffff021916908363ffffffff1602179055506101608201518160010160006101000a81548163ffffffff021916908363ffffffff1602179055506101808201518160010160046101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506101a082015181600101600c6101000a81548163ffffffff021916908363ffffffff1602179055506101c08201518160010160106101000a81548160ff0219169083151502179055506101e08201518160010160116101000a81548163ffffffff021916908360e01c021790555090505050505080600101905061321a565b60005b8151811015610e845760008282815181106136dd576136dd6156bd565b602002602001015160000151905060008383815181106136ff576136ff6156bd565b60209081029190910181015181015173ffffffffffffffffffffffffffffffffffffffff841660008181526008845260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff85169081179091559051908152919350917fbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d910160405180910390a250506001016136c0565b604080518082019091526000808252602082015260008260000151905060008173ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015613811573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138359190615b1c565b5050509150506000811215613876576040517f10cb51d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006138f58373ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156138c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138ea9190615b6c565b866020015184612aa9565b604080518082019091527bffffffffffffffffffffffffffffffffffffffffffffffffffffffff909116815263ffffffff4216602082015295945050505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515610b65565b836040015163ffffffff168311156139be5760408085015190517f8693378900000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015260248101849052604401610fed565b836020015161ffff16821115613a00576040517f4c056b6a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610e2c846101e001518261400f565b6000808083815b81811015613cd9576000878783818110613a3257613a326156bd565b905060400201803603810190613a489190615b89565b67ffffffffffffffff8c166000908152600a60209081526040808320845173ffffffffffffffffffffffffffffffffffffffff168452825291829020825160c081018452905463ffffffff8082168352640100000000820481169383019390935268010000000000000000810461ffff16938201939093526a01000000000000000000008304821660608201526e01000000000000000000000000000083049091166080820152720100000000000000000000000000000000000090910460ff16151560a0820181905291925090613b68576101208d0151613b359061ffff16662386f26fc10000615603565b613b3f90886158b7565b96508c610140015186613b529190615bc2565b9550613b5f602086615bc2565b94505050613cd1565b604081015160009061ffff1615613c215760008c73ffffffffffffffffffffffffffffffffffffffff16846000015173ffffffffffffffffffffffffffffffffffffffff1614613bc4578351613bbd90611fa0565b9050613bc7565b508a5b620186a0836040015161ffff16613c098660200151847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1661406190919063ffffffff16565b613c139190615603565b613c1d919061561a565b9150505b6060820151613c309088615bc2565b9650816080015186613c429190615bc2565b8251909650600090613c619063ffffffff16662386f26fc10000615603565b905080821015613c8057613c75818a6158b7565b985050505050613cd1565b6000836020015163ffffffff16662386f26fc10000613c9f9190615603565b905080831115613cbf57613cb3818b6158b7565b99505050505050613cd1565b613cc9838b6158b7565b995050505050505b600101613a16565b505096509650969350505050565b60008063ffffffff8316613cfd61016086615603565b613d09876101c06158b7565b613d1391906158b7565b613d1d91906158b7565b905060008760c0015163ffffffff168860e0015161ffff1683613d409190615603565b613d4a91906158b7565b61010089015190915061ffff16613d716dffffffffffffffffffffffffffff891683615603565b613d7b9190615603565b613d8b90655af3107a4000615603565b98975050505050505050565b60408051808201909152600080825260208201526000613dc3858585610160015163ffffffff16612d01565b9050826060015163ffffffff1681600001511115613e0d576040517f4c4fc93a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b826101c001518015613e2157508060200151155b15610b62576040517fee433e9900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff821603613ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610fed565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b606081600001805480602002602001604051908101604052809291908181526020018280548015613f9d57602002820191906000526020600020905b815481526020019060010190808311613f89575b50505050509050919050565b6000610b658373ffffffffffffffffffffffffffffffffffffffff841661409e565b6000610b658373ffffffffffffffffffffffffffffffffffffffff84166140ed565b6000610b658373ffffffffffffffffffffffffffffffffffffffff84166141e7565b7fd7ed2ad4000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831601610e84576127ea8161423f565b6000670de0b6b3a7640000614094837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8616615603565b610b65919061561a565b60008181526001830160205260408120546140e557508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610f4d565b506000610f4d565b600081815260018301602052604081205480156141d657600061411160018361583f565b85549091506000906141259060019061583f565b905080821461418a576000866000018281548110614145576141456156bd565b9060005260206000200154905080876000018481548110614168576141686156bd565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061419b5761419b615bdf565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610f4d565b6000915050610f4d565b5092915050565b600081815260018301602052604081205480156141d657600061420b60018361583f565b855490915060009061421f9060019061583f565b905081811461418a576000866000018281548110614145576141456156bd565b6000815160201461427e57816040517f8d666f60000000000000000000000000000000000000000000000000000000008152600401610fed91906143d6565b6000828060200190518101906142949190615aab565b905073ffffffffffffffffffffffffffffffffffffffff8111806142b9575061040081105b15610f4d57826040517f8d666f60000000000000000000000000000000000000000000000000000000008152600401610fed91906143d6565b803573ffffffffffffffffffffffffffffffffffffffff8116811461431657600080fd5b919050565b60008060006060848603121561433057600080fd5b614339846142f2565b92506020840135915061434e604085016142f2565b90509250925092565b60006020828403121561436957600080fd5b610b65826142f2565b6000815180845260005b818110156143985760208185018101518683018201520161437c565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000610b656020830184614372565b6020808252825182820181905260009190848201906040850190845b8181101561443757835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101614405565b50909695505050505050565b60006020828403121561445557600080fd5b813567ffffffffffffffff81111561446c57600080fd5b820160408185031215610b6557600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff811182821017156144d0576144d061447e565b60405290565b60405160a0810167ffffffffffffffff811182821017156144d0576144d061447e565b60405160c0810167ffffffffffffffff811182821017156144d0576144d061447e565b604051610200810167ffffffffffffffff811182821017156144d0576144d061447e565b6040516060810167ffffffffffffffff811182821017156144d0576144d061447e565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156145aa576145aa61447e565b604052919050565b600067ffffffffffffffff8211156145cc576145cc61447e565b5060051b60200190565b60ff81168114610e4357600080fd5b600060208083850312156145f857600080fd5b823567ffffffffffffffff81111561460f57600080fd5b8301601f8101851361462057600080fd5b803561463361462e826145b2565b614563565b8181526060918202830184019184820191908884111561465257600080fd5b938501935b838510156146f257848903818112156146705760008081fd5b6146786144ad565b614681876142f2565b81526040807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0840112156146b55760008081fd5b6146bd6144ad565b92506146ca8989016142f2565b83528701356146d8816145d6565b828901528088019190915283529384019391850191614657565b50979650505050505050565b8015158114610e4357600080fd5b8035614316816146fe565b6000602080838503121561472a57600080fd5b823567ffffffffffffffff81111561474157600080fd5b8301601f8101851361475257600080fd5b803561476061462e826145b2565b81815260a0918202830184019184820191908884111561477f57600080fd5b938501935b838510156146f25780858a03121561479c5760008081fd5b6147a46144d6565b6147ad866142f2565b8152868601357fffffffffffffffffffff00000000000000000000000000000000000000000000811681146147e25760008081fd5b818801526040868101357fffff0000000000000000000000000000000000000000000000000000000000008116811461481b5760008081fd5b90820152606061482c8782016142f2565b9082015260808681013561483f816146fe565b9082015283529384019391850191614784565b60008083601f84011261486457600080fd5b50813567ffffffffffffffff81111561487c57600080fd5b6020830191508360208260051b8501011115611f9957600080fd5b600080602083850312156148aa57600080fd5b823567ffffffffffffffff8111156148c157600080fd5b6148cd85828601614852565b90969095509350505050565b602080825282518282018190526000919060409081850190868401855b828110156149475761493784835180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16825260209081015163ffffffff16910152565b92840192908501906001016148f6565b5091979650505050505050565b803567ffffffffffffffff8116811461431657600080fd5b60006020828403121561497e57600080fd5b610b6582614954565b81517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16815260208083015163ffffffff169082015260408101610f4d565b815115158152610200810160208301516149e2602084018261ffff169052565b5060408301516149fa604084018263ffffffff169052565b506060830151614a12606084018263ffffffff169052565b506080830151614a2a608084018263ffffffff169052565b5060a0830151614a4060a084018261ffff169052565b5060c0830151614a5860c084018263ffffffff169052565b5060e0830151614a6e60e084018261ffff169052565b506101008381015161ffff9081169184019190915261012080850151909116908301526101408084015163ffffffff90811691840191909152610160808501518216908401526101808085015167ffffffffffffffff16908401526101a080850151909116908301526101c0808401511515908301526101e0808401517fffffffff000000000000000000000000000000000000000000000000000000008116828501525b505092915050565b803563ffffffff8116811461431657600080fd5b803561ffff8116811461431657600080fd5b600082601f830112614b5257600080fd5b81356020614b6261462e836145b2565b82815260069290921b84018101918181019086841115614b8157600080fd5b8286015b84811015614bce5760408189031215614b9e5760008081fd5b614ba66144ad565b614baf82614954565b8152614bbc8583016142f2565b81860152835291830191604001614b85565b509695505050505050565b60008060408385031215614bec57600080fd5b67ffffffffffffffff83351115614c0257600080fd5b83601f843585010112614c1457600080fd5b614c2461462e84358501356145b2565b8335840180358083526020808401939260059290921b90910101861015614c4a57600080fd5b602085358601015b85358601803560051b01602001811015614e575767ffffffffffffffff81351115614c7c57600080fd5b8035863587010160407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0828a03011215614cb557600080fd5b614cbd6144ad565b614cc960208301614954565b815267ffffffffffffffff60408301351115614ce457600080fd5b88603f604084013584010112614cf957600080fd5b614d0f61462e60206040850135850101356145b2565b6020604084810135850182810135808552928401939260e00201018b1015614d3657600080fd5b6040808501358501015b6040858101358601602081013560e0020101811015614e385760e0818d031215614d6957600080fd5b614d716144ad565b614d7a826142f2565b815260c07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0838f03011215614dae57600080fd5b614db66144f9565b614dc260208401614b1b565b8152614dd060408401614b1b565b6020820152614de160608401614b2f565b6040820152614df260808401614b1b565b6060820152614e0360a08401614b1b565b6080820152614e1560c08401356146fe565b60c083013560a0820152602082810191909152908452929092019160e001614d40565b5080602084015250508085525050602083019250602081019050614c52565b5092505067ffffffffffffffff60208401351115614e7457600080fd5b614e848460208501358501614b41565b90509250929050565b600082601f830112614e9e57600080fd5b81356020614eae61462e836145b2565b8083825260208201915060208460051b870101935086841115614ed057600080fd5b602086015b84811015614bce57614ee6816142f2565b8352918301918301614ed5565b60008060408385031215614f0657600080fd5b823567ffffffffffffffff80821115614f1e57600080fd5b614f2a86838701614e8d565b93506020850135915080821115614f4057600080fd5b50614f4d85828601614e8d565b9150509250929050565b60008083601f840112614f6957600080fd5b50813567ffffffffffffffff811115614f8157600080fd5b602083019150836020828501011115611f9957600080fd5b60008060008060408587031215614faf57600080fd5b843567ffffffffffffffff80821115614fc757600080fd5b614fd388838901614f57565b90965094506020870135915080821115614fec57600080fd5b50614ff987828801614f57565b95989497509550505050565b6000806040838503121561501857600080fd5b61502183614954565b9150614e84602084016142f2565b60006020828403121561504157600080fd5b813567ffffffffffffffff8082111561505957600080fd5b908301906040828603121561506d57600080fd5b6150756144ad565b82358281111561508457600080fd5b61509087828601614e8d565b8252506020830135828111156150a557600080fd5b6150b187828601614e8d565b60208301525095945050505050565b600080600080600080600080600060c08a8c0312156150de57600080fd5b6150e78a614954565b98506150f560208b016142f2565b975060408a0135965060608a013567ffffffffffffffff8082111561511957600080fd5b6151258d838e01614f57565b909850965060808c013591508082111561513e57600080fd5b61514a8d838e01614852565b909650945060a08c013591508082111561516357600080fd5b818c0191508c601f83011261517757600080fd5b81358181111561518657600080fd5b8d60208260061b850101111561519b57600080fd5b6020830194508093505050509295985092959850929598565b8481526000602085151581840152608060408401526151d66080840186614372565b8381036060850152845180825282820190600581901b8301840184880160005b83811015615242577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018552615230838351614372565b948701949250908601906001016151f6565b50909b9a5050505050505050505050565b80357fffffffff000000000000000000000000000000000000000000000000000000008116811461431657600080fd5b6000602080838503121561529657600080fd5b823567ffffffffffffffff8111156152ad57600080fd5b8301601f810185136152be57600080fd5b80356152cc61462e826145b2565b81815261022091820283018401918482019190888411156152ec57600080fd5b938501935b838510156146f2578489038181121561530a5760008081fd5b6153126144ad565b61531b87614954565b8152610200807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0840112156153505760008081fd5b61535861451c565b925061536589890161470c565b83526040615374818a01614b2f565b8a8501526060615385818b01614b1b565b8286015260809150615398828b01614b1b565b9085015260a06153a98a8201614b1b565b8286015260c091506153bc828b01614b2f565b9085015260e06153cd8a8201614b1b565b8286015261010091506153e1828b01614b2f565b908501526101206153f38a8201614b2f565b828601526101409150615407828b01614b2f565b908501526101606154198a8201614b1b565b82860152610180915061542d828b01614b1b565b908501526101a061543f8a8201614954565b828601526101c09150615453828b01614b1b565b908501526101e06154658a820161470c565b82860152615474838b01615253565b90850152505080880191909152835293840193918501916152f1565b600060208083850312156154a357600080fd5b823567ffffffffffffffff8111156154ba57600080fd5b8301601f810185136154cb57600080fd5b80356154d961462e826145b2565b81815260069190911b820183019083810190878311156154f857600080fd5b928401925b8284101561554a57604084890312156155165760008081fd5b61551e6144ad565b615527856142f2565b8152615534868601614954565b81870152825260409390930192908401906154fd565b979650505050505050565b6000806040838503121561556857600080fd5b61557183614954565b9150602083013567ffffffffffffffff81111561558d57600080fd5b830160a0818603121561559f57600080fd5b809150509250929050565b600080604083850312156155bd57600080fd5b6155c6836142f2565b9150614e8460208401614954565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082028115828204841417610f4d57610f4d6155d4565b600082615650577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261568a57600080fd5b83018035915067ffffffffffffffff8211156156a557600080fd5b6020019150600681901b3603821315611f9957600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b80357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116811461431657600080fd5b60006040828403121561572a57600080fd5b6157326144ad565b61573b836142f2565b8152615749602084016156ec565b60208201529392505050565b60006040828403121561576757600080fd5b61576f6144ad565b61573b83614954565b6000602080838503121561578b57600080fd5b823567ffffffffffffffff8111156157a257600080fd5b8301601f810185136157b357600080fd5b80356157c161462e826145b2565b818152606091820283018401918482019190888411156157e057600080fd5b938501935b838510156146f25780858a0312156157fd5760008081fd5b615805614540565b61580e866142f2565b815261581b8787016156ec565b87820152604061582c818801614b1b565b90820152835293840193918501916157e5565b81810381811115610f4d57610f4d6155d4565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261588757600080fd5b83018035915067ffffffffffffffff8211156158a257600080fd5b602001915036819003821315611f9957600080fd5b80820180821115610f4d57610f4d6155d4565b60ff8181168382160190811115610f4d57610f4d6155d4565b600181815b8085111561593c57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115615922576159226155d4565b8085161561592f57918102915b93841c93908002906158e8565b509250929050565b60008261595357506001610f4d565b8161596057506000610f4d565b816001811461597657600281146159805761599c565b6001915050610f4d565b60ff841115615991576159916155d4565b50506001821b610f4d565b5060208310610133831016604e8410600b84101617156159bf575081810a610f4d565b6159c983836158e3565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156159fb576159fb6155d4565b029392505050565b6000610b658383615944565b7fffffffff000000000000000000000000000000000000000000000000000000008135818116916004851015614b135760049490940360031b84901b1690921692915050565b60008085851115615a6557600080fd5b83861115615a7257600080fd5b5050820193919092039150565b600060408284031215615a9157600080fd5b615a996144ad565b825181526020830151615749816146fe565b600060208284031215615abd57600080fd5b5051919050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61833603018112615af857600080fd5b9190910192915050565b805169ffffffffffffffffffff8116811461431657600080fd5b600080600080600060a08688031215615b3457600080fd5b615b3d86615b02565b9450602086015193506040860151925060608601519150615b6060808701615b02565b90509295509295909350565b600060208284031215615b7e57600080fd5b8151610b65816145d6565b600060408284031215615b9b57600080fd5b615ba36144ad565b615bac836142f2565b8152602083013560208201528091505092915050565b63ffffffff8181168382160190808211156141e0576141e06155d4565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea164736f6c6343000818000a", } var FeeQuoterABI = FeeQuoterMetaData.ABI @@ -544,25 +544,25 @@ func (_FeeQuoter *FeeQuoterCallerSession) GetTokenPrice(token common.Address) (I return _FeeQuoter.Contract.GetTokenPrice(&_FeeQuoter.CallOpts, token) } -func (_FeeQuoter *FeeQuoterCaller) GetTokenPriceFeedConfig(opts *bind.CallOpts, token common.Address) (IFeeQuoterTokenPriceFeedConfig, error) { +func (_FeeQuoter *FeeQuoterCaller) GetTokenPriceFeedConfig(opts *bind.CallOpts, token common.Address) (FeeQuoterTokenPriceFeedConfig, error) { var out []interface{} err := _FeeQuoter.contract.Call(opts, &out, "getTokenPriceFeedConfig", token) if err != nil { - return *new(IFeeQuoterTokenPriceFeedConfig), err + return *new(FeeQuoterTokenPriceFeedConfig), err } - out0 := *abi.ConvertType(out[0], new(IFeeQuoterTokenPriceFeedConfig)).(*IFeeQuoterTokenPriceFeedConfig) + out0 := *abi.ConvertType(out[0], new(FeeQuoterTokenPriceFeedConfig)).(*FeeQuoterTokenPriceFeedConfig) return out0, err } -func (_FeeQuoter *FeeQuoterSession) GetTokenPriceFeedConfig(token common.Address) (IFeeQuoterTokenPriceFeedConfig, error) { +func (_FeeQuoter *FeeQuoterSession) GetTokenPriceFeedConfig(token common.Address) (FeeQuoterTokenPriceFeedConfig, error) { return _FeeQuoter.Contract.GetTokenPriceFeedConfig(&_FeeQuoter.CallOpts, token) } -func (_FeeQuoter *FeeQuoterCallerSession) GetTokenPriceFeedConfig(token common.Address) (IFeeQuoterTokenPriceFeedConfig, error) { +func (_FeeQuoter *FeeQuoterCallerSession) GetTokenPriceFeedConfig(token common.Address) (FeeQuoterTokenPriceFeedConfig, error) { return _FeeQuoter.Contract.GetTokenPriceFeedConfig(&_FeeQuoter.CallOpts, token) } @@ -676,11 +676,11 @@ func (_FeeQuoter *FeeQuoterCallerSession) Owner() (common.Address, error) { return _FeeQuoter.Contract.Owner(&_FeeQuoter.CallOpts) } -func (_FeeQuoter *FeeQuoterCaller) ProcessMessageArgs(opts *bind.CallOpts, destChainSelector uint64, feeToken common.Address, feeTokenAmount *big.Int, extraArgs []byte) (ProcessMessageArgs, +func (_FeeQuoter *FeeQuoterCaller) ProcessMessageArgs(opts *bind.CallOpts, destChainSelector uint64, feeToken common.Address, feeTokenAmount *big.Int, extraArgs []byte, rampTokenAmounts []InternalRampTokenAmount, sourceTokenAmounts []ClientEVMTokenAmount) (ProcessMessageArgs, error) { var out []interface{} - err := _FeeQuoter.contract.Call(opts, &out, "processMessageArgs", destChainSelector, feeToken, feeTokenAmount, extraArgs) + err := _FeeQuoter.contract.Call(opts, &out, "processMessageArgs", destChainSelector, feeToken, feeTokenAmount, extraArgs, rampTokenAmounts, sourceTokenAmounts) outstruct := new(ProcessMessageArgs) if err != nil { @@ -690,43 +690,22 @@ func (_FeeQuoter *FeeQuoterCaller) ProcessMessageArgs(opts *bind.CallOpts, destC outstruct.MsgFeeJuels = *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) outstruct.IsOutOfOrderExecution = *abi.ConvertType(out[1], new(bool)).(*bool) outstruct.ConvertedExtraArgs = *abi.ConvertType(out[2], new([]byte)).(*[]byte) + outstruct.DestExecDataPerToken = *abi.ConvertType(out[3], new([][]byte)).(*[][]byte) return *outstruct, err } -func (_FeeQuoter *FeeQuoterSession) ProcessMessageArgs(destChainSelector uint64, feeToken common.Address, feeTokenAmount *big.Int, extraArgs []byte) (ProcessMessageArgs, +func (_FeeQuoter *FeeQuoterSession) ProcessMessageArgs(destChainSelector uint64, feeToken common.Address, feeTokenAmount *big.Int, extraArgs []byte, rampTokenAmounts []InternalRampTokenAmount, sourceTokenAmounts []ClientEVMTokenAmount) (ProcessMessageArgs, error) { - return _FeeQuoter.Contract.ProcessMessageArgs(&_FeeQuoter.CallOpts, destChainSelector, feeToken, feeTokenAmount, extraArgs) + return _FeeQuoter.Contract.ProcessMessageArgs(&_FeeQuoter.CallOpts, destChainSelector, feeToken, feeTokenAmount, extraArgs, rampTokenAmounts, sourceTokenAmounts) } -func (_FeeQuoter *FeeQuoterCallerSession) ProcessMessageArgs(destChainSelector uint64, feeToken common.Address, feeTokenAmount *big.Int, extraArgs []byte) (ProcessMessageArgs, +func (_FeeQuoter *FeeQuoterCallerSession) ProcessMessageArgs(destChainSelector uint64, feeToken common.Address, feeTokenAmount *big.Int, extraArgs []byte, rampTokenAmounts []InternalRampTokenAmount, sourceTokenAmounts []ClientEVMTokenAmount) (ProcessMessageArgs, error) { - return _FeeQuoter.Contract.ProcessMessageArgs(&_FeeQuoter.CallOpts, destChainSelector, feeToken, feeTokenAmount, extraArgs) -} - -func (_FeeQuoter *FeeQuoterCaller) ProcessPoolReturnData(opts *bind.CallOpts, destChainSelector uint64, rampTokenAmounts []InternalRampTokenAmount, sourceTokenAmounts []ClientEVMTokenAmount) ([][]byte, error) { - var out []interface{} - err := _FeeQuoter.contract.Call(opts, &out, "processPoolReturnData", destChainSelector, rampTokenAmounts, sourceTokenAmounts) - - if err != nil { - return *new([][]byte), err - } - - out0 := *abi.ConvertType(out[0], new([][]byte)).(*[][]byte) - - return out0, err - -} - -func (_FeeQuoter *FeeQuoterSession) ProcessPoolReturnData(destChainSelector uint64, rampTokenAmounts []InternalRampTokenAmount, sourceTokenAmounts []ClientEVMTokenAmount) ([][]byte, error) { - return _FeeQuoter.Contract.ProcessPoolReturnData(&_FeeQuoter.CallOpts, destChainSelector, rampTokenAmounts, sourceTokenAmounts) -} - -func (_FeeQuoter *FeeQuoterCallerSession) ProcessPoolReturnData(destChainSelector uint64, rampTokenAmounts []InternalRampTokenAmount, sourceTokenAmounts []ClientEVMTokenAmount) ([][]byte, error) { - return _FeeQuoter.Contract.ProcessPoolReturnData(&_FeeQuoter.CallOpts, destChainSelector, rampTokenAmounts, sourceTokenAmounts) + return _FeeQuoter.Contract.ProcessMessageArgs(&_FeeQuoter.CallOpts, destChainSelector, feeToken, feeTokenAmount, extraArgs, rampTokenAmounts, sourceTokenAmounts) } func (_FeeQuoter *FeeQuoterCaller) TypeAndVersion(opts *bind.CallOpts) (string, error) { @@ -2089,7 +2068,7 @@ func (it *FeeQuoterPriceFeedPerTokenUpdatedIterator) Close() error { type FeeQuoterPriceFeedPerTokenUpdated struct { Token common.Address - PriceFeedConfig IFeeQuoterTokenPriceFeedConfig + PriceFeedConfig FeeQuoterTokenPriceFeedConfig Raw types.Log } @@ -2822,6 +2801,7 @@ type ProcessMessageArgs struct { MsgFeeJuels *big.Int IsOutOfOrderExecution bool ConvertedExtraArgs []byte + DestExecDataPerToken [][]byte } func (_FeeQuoter *FeeQuoter) ParseLog(log types.Log) (generated.AbigenLog, error) { @@ -2951,7 +2931,7 @@ type FeeQuoterInterface interface { GetTokenPrice(opts *bind.CallOpts, token common.Address) (InternalTimestampedPackedUint224, error) - GetTokenPriceFeedConfig(opts *bind.CallOpts, token common.Address) (IFeeQuoterTokenPriceFeedConfig, error) + GetTokenPriceFeedConfig(opts *bind.CallOpts, token common.Address) (FeeQuoterTokenPriceFeedConfig, error) GetTokenPrices(opts *bind.CallOpts, tokens []common.Address) ([]InternalTimestampedPackedUint224, error) @@ -2963,12 +2943,10 @@ type FeeQuoterInterface interface { Owner(opts *bind.CallOpts) (common.Address, error) - ProcessMessageArgs(opts *bind.CallOpts, destChainSelector uint64, feeToken common.Address, feeTokenAmount *big.Int, extraArgs []byte) (ProcessMessageArgs, + ProcessMessageArgs(opts *bind.CallOpts, destChainSelector uint64, feeToken common.Address, feeTokenAmount *big.Int, extraArgs []byte, rampTokenAmounts []InternalRampTokenAmount, sourceTokenAmounts []ClientEVMTokenAmount) (ProcessMessageArgs, error) - ProcessPoolReturnData(opts *bind.CallOpts, destChainSelector uint64, rampTokenAmounts []InternalRampTokenAmount, sourceTokenAmounts []ClientEVMTokenAmount) ([][]byte, error) - TypeAndVersion(opts *bind.CallOpts) (string, error) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) diff --git a/core/gethwrappers/ccip/generated/onramp/onramp.go b/core/gethwrappers/ccip/generated/onramp/onramp.go index f15bd4e3c9..7d326f4bfd 100644 --- a/core/gethwrappers/ccip/generated/onramp/onramp.go +++ b/core/gethwrappers/ccip/generated/onramp/onramp.go @@ -83,10 +83,11 @@ type OnRampDestChainConfigArgs struct { } type OnRampDynamicConfig struct { - FeeQuoter common.Address - MessageInterceptor common.Address - FeeAggregator common.Address - AllowListAdmin common.Address + FeeQuoter common.Address + ReentrancyGuardEntered bool + MessageInterceptor common.Address + FeeAggregator common.Address + AllowListAdmin common.Address } type OnRampStaticConfig struct { @@ -97,8 +98,8 @@ type OnRampStaticConfig struct { } var OnRampMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CannotSendZeroTokens\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GetSupportedTokensFunctionalityRemovedCheckAdminRegistry\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidAllowListRequest\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidDestChainConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeCalledByRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrAllowlistAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RouterMustSetOriginalSender\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"UnsupportedToken\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"name\":\"AllowListAdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"senders\",\"type\":\"address[]\"}],\"name\":\"AllowListSendersAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"senders\",\"type\":\"address[]\"}],\"name\":\"AllowListSendersRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"CCIPMessageSent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOnRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"allowListEnabled\",\"type\":\"bool\"}],\"name\":\"DestChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"feeValueJuels\",\"type\":\"uint256\"}],\"name\":\"FeePaid\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeeTokenWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"allowListEnabled\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"addedAllowlistedSenders\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"removedAllowlistedSenders\",\"type\":\"address[]\"}],\"internalType\":\"structOnRamp.AllowListConfigArgs[]\",\"name\":\"allowListConfigArgsItems\",\"type\":\"tuple[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyDestChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"}],\"name\":\"forwardFromRouter\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getAllowedSendersList\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getDestChainConfig\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"allowListEnabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getExpectedNextSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"getFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"},{\"internalType\":\"contractIERC20\",\"name\":\"sourceToken\",\"type\":\"address\"}],\"name\":\"getPoolBySourceToken\",\"outputs\":[{\"internalType\":\"contractIPoolV1\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"contractIRouter\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"name\":\"getSupportedTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"setDynamicConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"withdrawFeeTokens\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x6101006040523480156200001257600080fd5b506040516200407238038062004072833981016040819052620000359162000665565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf8162000186565b505083516001600160401b031615905080620000e6575060208301516001600160a01b0316155b80620000fd575060408301516001600160a01b0316155b8062000114575060608301516001600160a01b0316155b1562000133576040516306b7c75960e31b815260040160405180910390fd5b82516001600160401b031660805260208301516001600160a01b0390811660a0526040840151811660c05260608401511660e052620001728262000231565b6200017d8162000390565b5050506200079f565b336001600160a01b03821603620001e05760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b0316158062000254575060408101516001600160a01b0316155b1562000273576040516306b7c75960e31b815260040160405180910390fd5b8051600280546001600160a01b03199081166001600160a01b0393841617909155602080840180516003805485169186169190911790556040808601805160048054871691881691909117905560608088018051600580549098169089161790965582516080808201855280516001600160401b031680835260a080518b16848a0190815260c080518d16868a0190815260e080518f169789019788528a5195865292518e169b85019b909b5299518c169783019790975292518a169381019390935289518916908301529351871693810193909352518516928201929092529151909216918101919091527f23a1adf8ad7fad6091a4803227af2cee848c01a7c812404cade7c25636925e32906101000160405180910390a150565b60005b8151811015620004cf576000828281518110620003b457620003b462000789565b602002602001015190506000838381518110620003d557620003d562000789565b6020026020010151600001519050806001600160401b03166000036200041a5760405163c35aa79d60e01b81526001600160401b038216600482015260240162000083565b6001600160401b03818116600081815260066020908152604091829020868201518154600160481b600160e81b0319811669010000000000000000006001600160a01b03909316928302908117808555865192891691909816178152928301526801000000000000000090940460ff161515918101919091527fd5ad72bc37dc7a80a8b9b9df20500046fd7341adb1be2258a540466fdd7dcef59060600160405180910390a250505080600101905062000393565b5050565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b03811182821017156200050e576200050e620004d3565b60405290565b604080519081016001600160401b03811182821017156200050e576200050e620004d3565b604051601f8201601f191681016001600160401b0381118282101715620005645762000564620004d3565b604052919050565b80516001600160401b03811681146200058457600080fd5b919050565b6001600160a01b03811681146200059f57600080fd5b50565b600082601f830112620005b457600080fd5b815160206001600160401b03821115620005d257620005d2620004d3565b620005e2818360051b0162000539565b82815260069290921b840181019181810190868411156200060257600080fd5b8286015b848110156200065a5760408189031215620006215760008081fd5b6200062b62000514565b62000636826200056c565b815284820151620006478162000589565b8186015283529183019160400162000606565b509695505050505050565b60008060008385036101208112156200067d57600080fd5b60808112156200068c57600080fd5b62000696620004e9565b620006a1866200056c565b81526020860151620006b38162000589565b60208201526040860151620006c88162000589565b60408201526060860151620006dd8162000589565b606082015293506080607f1982011215620006f757600080fd5b5062000702620004e9565b6080850151620007128162000589565b815260a0850151620007248162000589565b602082015260c0850151620007398162000589565b604082015260e08501516200074e8162000589565b60608201526101008501519092506001600160401b038111156200077157600080fd5b6200077f86828701620005a2565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b60805160a05160c05160e05161385a620008186000396000818161022c01528181610cc20152611bea0152600081816101f0015281816112910152611bc30152600081816101b4015281816105de0152611b99015260008181610184015281816111b7015281816116940152611b6c015261385a6000f3fe608060405234801561001057600080fd5b50600436106101365760003560e01c806379ba5097116100b2578063a6f3ab6c11610081578063df0aa9e911610066578063df0aa9e91461052d578063f2fde38b14610540578063fbca3b741461055357600080fd5b8063a6f3ab6c146104cd578063d77d5ed0146104e057600080fd5b806379ba50971461045b5780638da5cb5b146104635780639041be3d14610481578063972b4612146104ad57600080fd5b806334adf4941161010957806348a98aa4116100ee57806348a98aa4146103045780636def4ce71461033c5780637437ff9f146103db57600080fd5b806334adf494146102e95780633a019940146102fc57600080fd5b80630242cf601461013b57806306285c6914610150578063181f5a771461027f57806320487ded146102c8575b600080fd5b61014e6101493660046126df565b610566565b005b61026960408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16815250905090565b60405161027691906127a2565b60405180910390f35b6102bb6040518060400160405280601081526020017f4f6e52616d7020312e362e302d6465760000000000000000000000000000000081525081565b6040516102769190612867565b6102db6102d6366004612892565b61057a565b604051908152602001610276565b61014e6102f73660046128e2565b610733565b61014e610a4f565b610317610312366004612957565b610c7a565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610276565b61039f61034a366004612990565b67ffffffffffffffff9081166000908152600660205260409020549081169168010000000000000000820460ff16916901000000000000000000900473ffffffffffffffffffffffffffffffffffffffff1690565b6040805167ffffffffffffffff9094168452911515602084015273ffffffffffffffffffffffffffffffffffffffff1690820152606001610276565b61044e604080516080810182526000808252602082018190529181018290526060810191909152506040805160808101825260025473ffffffffffffffffffffffffffffffffffffffff908116825260035481166020830152600454811692820192909252600554909116606082015290565b60405161027691906129ad565b61014e610d2f565b60005473ffffffffffffffffffffffffffffffffffffffff16610317565b61049461048f366004612990565b610e2c565b60405167ffffffffffffffff9091168152602001610276565b6104c06104bb366004612990565b610e55565b60405161027691906129f6565b61014e6104db366004612a60565b610e7d565b6103176104ee366004612990565b67ffffffffffffffff166000908152600660205260409020546901000000000000000000900473ffffffffffffffffffffffffffffffffffffffff1690565b6102db61053b366004612ac7565b610e8e565b61014e61054e366004612b33565b611747565b6104c0610561366004612990565b611758565b61056e61178c565b6105778161180f565b50565b6040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815277ffffffffffffffff00000000000000000000000000000000608084901b16600482015260009073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690632cbc26bb90602401602060405180830381865afa158015610625573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106499190612b5e565b15610691576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024015b60405180910390fd5b6002546040517fd8694ccd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063d8694ccd906106e99086908690600401612c8f565b602060405180830381865afa158015610706573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061072a9190612dd8565b90505b92915050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146107a35760055473ffffffffffffffffffffffffffffffffffffffff1633146107a3576040517f905d7d9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015610a4a5760008383838181106107c2576107c2612df1565b90506020028101906107d49190612e20565b6107dd90612ed1565b805167ffffffffffffffff1660009081526006602090815260409182902090830151815490151568010000000000000000027fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff9091161781559082015151919250901561099d5781602001511561095c5760005b82604001515181101561090c5760008360400151828151811061087657610876612df1565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036108f55783516040517f463258ff00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610688565b6109026001840182611986565b5050600101610851565b50816000015167ffffffffffffffff167f330939f6eafe8bb516716892fe962ff19770570838686e6579dbc1cc51fc3281836040015160405161094f91906129f6565b60405180910390a261099d565b81516040517f463258ff00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152602401610688565b60005b8260600151518110156109e9576109e0836060015182815181106109c6576109c6612df1565b6020026020010151836001016119a890919063ffffffff16565b506001016109a0565b5060608201515115610a4057816000015167ffffffffffffffff167fc237ec1921f855ccd5e9a5af9733f2d58943a5a8501ec5988e305d7a4d4215868360600151604051610a3791906129f6565b60405180910390a25b50506001016107a6565b505050565b600254604080517fcdc73d51000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163cdc73d5191600480830192869291908290030181865afa158015610abe573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610b049190810190612f64565b60045490915073ffffffffffffffffffffffffffffffffffffffff1660005b8251811015610a4a576000838281518110610b4057610b40612df1565b60209081029190910101516040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915060009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa158015610bbb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bdf9190612dd8565b90508015610c7057610c0873ffffffffffffffffffffffffffffffffffffffff831685836119ca565b8173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f508d7d183612c18fc339b42618912b9fa3239f631dd7ec0671f950200a0fa66e83604051610c6791815260200190565b60405180910390a35b5050600101610b23565b6040517fbbe4f6db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063bbe4f6db90602401602060405180830381865afa158015610d0b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061072a9190612ff3565b60015473ffffffffffffffffffffffffffffffffffffffff163314610db0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610688565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b67ffffffffffffffff808216600090815260066020526040812054909161072d9116600161303f565b67ffffffffffffffff8116600090815260066020526040902060609061072d90600101611a57565b610e8561178c565b61057781611a6b565b67ffffffffffffffff8416600090815260066020526040812073ffffffffffffffffffffffffffffffffffffffff8316610ef4576040517fa4ec747900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805468010000000000000000900460ff1615610f6557610f176001820184611c4d565b610f65576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152602401610688565b80546901000000000000000000900473ffffffffffffffffffffffffffffffffffffffff163314610fc2576040517f1c0a352900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60035473ffffffffffffffffffffffffffffffffffffffff168015611068576040517fe0a0e50600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82169063e0a0e50690611035908a908a90600401612c8f565b600060405180830381600087803b15801561104f57600080fd5b505af1158015611063573d6000803e3d6000fd5b505050505b506002546000908190819073ffffffffffffffffffffffffffffffffffffffff1663c4276bfc8a61109f60808c0160608d01612b33565b8a6110ad60808e018e613060565b6040518663ffffffff1660e01b81526004016110cd9594939291906130c5565b600060405180830381865afa1580156110ea573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611130919081019061318d565b919450925090506111476080890160608a01612b33565b73ffffffffffffffffffffffffffffffffffffffff167f075a2720282fdf622141dae0b048ef90a21a7e57c134c76912d19d006b3b3f6f8460405161118e91815260200190565b60405180910390a2604080516101a081019091526000610100820181815267ffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000081166101208501528c811661014085015287549293928392916101608401918a91879161120391166131e7565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905567ffffffffffffffff16815260200186611303576040517fea458c0c00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8f16600482015273ffffffffffffffffffffffffffffffffffffffff8c811660248301527f0000000000000000000000000000000000000000000000000000000000000000169063ea458c0c906044016020604051808303816000875af11580156112da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112fe919061320e565b611306565b60005b67ffffffffffffffff1681525081526020018873ffffffffffffffffffffffffffffffffffffffff1681526020018a80602001906113449190613060565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505050908252506020016113888b80613060565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250505090825250602081018490526040016113d960808c0160608d01612b33565b73ffffffffffffffffffffffffffffffffffffffff1681526020018981526020018a806040019061140a919061322b565b905067ffffffffffffffff811115611424576114246125b9565b60405190808252806020026020018201604052801561148757816020015b6114746040518060a0016040528060608152602001606081526020016060815260200160008152602001606081525090565b8152602001906001900390816114425790505b509052905060005b61149c60408b018b61322b565b905081101561154b576115226114b560408c018c61322b565b838181106114c5576114c5612df1565b9050604002018036038101906114db9190613293565b8c6114e68d80613060565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508e9250611c7c915050565b8260e00151828151811061153857611538612df1565b602090810291909101015260010161148f565b5060025460e082015160009173ffffffffffffffffffffffffffffffffffffffff169063085318f8908d9061158360408f018f61322b565b6040518563ffffffff1660e01b81526004016115a294939291906133aa565b600060405180830381865afa1580156115bf573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261160591908101906133e0565b905060005b8260e001515181101561165e5781818151811061162957611629612df1565b60200260200101518360e00151828151811061164757611647612df1565b60209081029190910101516080015260010161160a565b50604080517f130ac867e79e2789f923760a88743d292acdf7002139a588206e2260f73f7321602082015267ffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811692820192909252908c1660608201523060808201526116ee90839060a00160405160208183030381529060405280519060200120611fa2565b82515260405167ffffffffffffffff8c16907ff6e86ef8896c7a0d629406168f396e883280680c99e649b9e2d36466fbc9f9e59061172d908590613491565b60405180910390a25051519450505050505b949350505050565b61174f61178c565b610577816120a2565b60606040517f9e7177c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005473ffffffffffffffffffffffffffffffffffffffff16331461180d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610688565b565b60005b815181101561198257600082828151811061182f5761182f612df1565b60200260200101519050600083838151811061184d5761184d612df1565b60200260200101516000015190508067ffffffffffffffff166000036118ab576040517fc35aa79d00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff82166004820152602401610688565b67ffffffffffffffff8181166000818152600660209081526040918290208682015181547fffffff0000000000000000000000000000000000000000ffffffffffffffffff8116690100000000000000000073ffffffffffffffffffffffffffffffffffffffff909316928302908117808555865192891691909816178152928301526801000000000000000090940460ff161515918101919091527fd5ad72bc37dc7a80a8b9b9df20500046fd7341adb1be2258a540466fdd7dcef59060600160405180910390a2505050806001019050611812565b5050565b600061072a8373ffffffffffffffffffffffffffffffffffffffff8416612197565b600061072a8373ffffffffffffffffffffffffffffffffffffffff84166121e6565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052610a4a9084906122e0565b60606000611a64836123ec565b9392505050565b805173ffffffffffffffffffffffffffffffffffffffff161580611aa75750604081015173ffffffffffffffffffffffffffffffffffffffff16155b15611ade576040517f35be3ac800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051600280547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff93841617909155602080840151600380548416918516919091179055604080850151600480548516918616919091179055606080860151600580549095169086161790935580516080810182527f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681527f00000000000000000000000000000000000000000000000000000000000000008516928101929092527f00000000000000000000000000000000000000000000000000000000000000008416828201527f00000000000000000000000000000000000000000000000000000000000000009093169181019190915290517f23a1adf8ad7fad6091a4803227af2cee848c01a7c812404cade7c25636925e3291611c429184906135df565b60405180910390a150565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600183016020526040812054151561072a565b611cae6040518060a0016040528060608152602001606081526020016060815260200160008152602001606081525090565b8460200151600003611cec576040517f5cf0444900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611cfc858760000151610c7a565b905073ffffffffffffffffffffffffffffffffffffffff81161580611dcc57506040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527faff2afbf00000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff8216906301ffc9a790602401602060405180830381865afa158015611da6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dca9190612b5e565b155b15611e1e5785516040517fbf16aab600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610688565b60008173ffffffffffffffffffffffffffffffffffffffff16639a4575b96040518060a001604052808881526020018967ffffffffffffffff1681526020018773ffffffffffffffffffffffffffffffffffffffff1681526020018a6020015181526020018a6000015173ffffffffffffffffffffffffffffffffffffffff168152506040518263ffffffff1660e01b8152600401611ebd919061367e565b6000604051808303816000875af1158015611edc573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611f2291908101906136f4565b6040805160a0810190915273ffffffffffffffffffffffffffffffffffffffff841660c08201529091508060e0810160405160208183030381529060405281526020018260000151815260200182602001518152602001886020015181526020016040518060200160405280600081525081525092505050949350505050565b60008060001b82846020015185606001518660000151606001518760000151608001518860a001518960c00151604051602001611fe496959493929190613785565b604051602081830303815290604052805190602001208560400151805190602001208660e0015160405160200161201b91906137e6565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201206080808c0151805190840120928501989098529183019590955260608201939093529384015260a083015260c082015260e00160405160208183030381529060405280519060200120905092915050565b3373ffffffffffffffffffffffffffffffffffffffff821603612121576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610688565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60008181526001830160205260408120546121de5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561072d565b50600061072d565b600081815260018301602052604081205480156122cf57600061220a6001836137f9565b855490915060009061221e906001906137f9565b905080821461228357600086600001828154811061223e5761223e612df1565b906000526020600020015490508087600001848154811061226157612261612df1565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806122945761229461380c565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061072d565b600091505061072d565b5092915050565b6000612342826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166124489092919063ffffffff16565b805190915015610a4a57808060200190518101906123609190612b5e565b610a4a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610688565b60608160000180548060200260200160405190810160405280929190818152602001828054801561243c57602002820191906000526020600020905b815481526020019060010190808311612428575b50505050509050919050565b606061173f8484600085856000808673ffffffffffffffffffffffffffffffffffffffff16858760405161247c919061383b565b60006040518083038185875af1925050503d80600081146124b9576040519150601f19603f3d011682016040523d82523d6000602084013e6124be565b606091505b50915091506124cf878383876124da565b979650505050505050565b606083156125705782516000036125695773ffffffffffffffffffffffffffffffffffffffff85163b612569576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610688565b508161173f565b61173f83838151156125855781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106889190612867565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561260b5761260b6125b9565b60405290565b6040516080810167ffffffffffffffff8111828210171561260b5761260b6125b9565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561267b5761267b6125b9565b604052919050565b600067ffffffffffffffff82111561269d5761269d6125b9565b5060051b60200190565b67ffffffffffffffff8116811461057757600080fd5b73ffffffffffffffffffffffffffffffffffffffff8116811461057757600080fd5b600060208083850312156126f257600080fd5b823567ffffffffffffffff81111561270957600080fd5b8301601f8101851361271a57600080fd5b803561272d61272882612683565b612634565b81815260069190911b8201830190838101908783111561274c57600080fd5b928401925b828410156124cf576040848903121561276a5760008081fd5b6127726125e8565b843561277d816126a7565b81528486013561278c816126bd565b8187015282526040939093019290840190612751565b6080810161072d828467ffffffffffffffff8151168252602081015173ffffffffffffffffffffffffffffffffffffffff808216602085015280604084015116604085015280606084015116606085015250505050565b60005b838110156128145781810151838201526020016127fc565b50506000910152565b600081518084526128358160208601602086016127f9565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061072a602083018461281d565b600060a0828403121561288c57600080fd5b50919050565b600080604083850312156128a557600080fd5b82356128b0816126a7565b9150602083013567ffffffffffffffff8111156128cc57600080fd5b6128d88582860161287a565b9150509250929050565b600080602083850312156128f557600080fd5b823567ffffffffffffffff8082111561290d57600080fd5b818501915085601f83011261292157600080fd5b81358181111561293057600080fd5b8660208260051b850101111561294557600080fd5b60209290920196919550909350505050565b6000806040838503121561296a57600080fd5b8235612975816126a7565b91506020830135612985816126bd565b809150509250929050565b6000602082840312156129a257600080fd5b8135611a64816126a7565b6080810161072d8284805173ffffffffffffffffffffffffffffffffffffffff908116835260208083015182169084015260408083015182169084015260609182015116910152565b6020808252825182820181905260009190848201906040850190845b81811015612a4457835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101612a12565b50909695505050505050565b8035612a5b816126bd565b919050565b600060808284031215612a7257600080fd5b612a7a612611565b8235612a85816126bd565b81526020830135612a95816126bd565b60208201526040830135612aa8816126bd565b60408201526060830135612abb816126bd565b60608201529392505050565b60008060008060808587031215612add57600080fd5b8435612ae8816126a7565b9350602085013567ffffffffffffffff811115612b0457600080fd5b612b108782880161287a565b935050604085013591506060850135612b28816126bd565b939692955090935050565b600060208284031215612b4557600080fd5b8135611a64816126bd565b801515811461057757600080fd5b600060208284031215612b7057600080fd5b8151611a6481612b50565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112612bb057600080fd5b830160208101925035905067ffffffffffffffff811115612bd057600080fd5b803603821315612bdf57600080fd5b9250929050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b8183526000602080850194508260005b85811015612c84578135612c52816126bd565b73ffffffffffffffffffffffffffffffffffffffff168752818301358388015260409687019690910190600101612c3f565b509495945050505050565b600067ffffffffffffffff808516835260406020840152612cb08485612b7b565b60a06040860152612cc560e086018284612be6565b915050612cd56020860186612b7b565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc080878503016060880152612d0b848385612be6565b9350604088013592507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1883603018312612d4457600080fd5b60209288019283019235915084821115612d5d57600080fd5b8160061b3603831315612d6f57600080fd5b80878503016080880152612d84848385612c2f565b9450612d9260608901612a50565b73ffffffffffffffffffffffffffffffffffffffff811660a08901529350612dbd6080890189612b7b565b94509250808786030160c088015250506124cf838383612be6565b600060208284031215612dea57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81833603018112612e5457600080fd5b9190910192915050565b600082601f830112612e6f57600080fd5b81356020612e7f61272883612683565b8083825260208201915060208460051b870101935086841115612ea157600080fd5b602086015b84811015612ec6578035612eb9816126bd565b8352918301918301612ea6565b509695505050505050565b600060808236031215612ee357600080fd5b612eeb612611565b8235612ef6816126a7565b81526020830135612f0681612b50565b6020820152604083013567ffffffffffffffff80821115612f2657600080fd5b612f3236838701612e5e565b60408401526060850135915080821115612f4b57600080fd5b50612f5836828601612e5e565b60608301525092915050565b60006020808385031215612f7757600080fd5b825167ffffffffffffffff811115612f8e57600080fd5b8301601f81018513612f9f57600080fd5b8051612fad61272882612683565b81815260059190911b82018301908381019087831115612fcc57600080fd5b928401925b828410156124cf578351612fe4816126bd565b82529284019290840190612fd1565b60006020828403121561300557600080fd5b8151611a64816126bd565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b67ffffffffffffffff8181168382160190808211156122d9576122d9613010565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261309557600080fd5b83018035915067ffffffffffffffff8211156130b057600080fd5b602001915036819003821315612bdf57600080fd5b67ffffffffffffffff8616815273ffffffffffffffffffffffffffffffffffffffff851660208201528360408201526080606082015260006124cf608083018486612be6565b600082601f83011261311c57600080fd5b815167ffffffffffffffff811115613136576131366125b9565b61316760207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601612634565b81815284602083860101111561317c57600080fd5b61173f8260208301602087016127f9565b6000806000606084860312156131a257600080fd5b8351925060208401516131b481612b50565b604085015190925067ffffffffffffffff8111156131d157600080fd5b6131dd8682870161310b565b9150509250925092565b600067ffffffffffffffff80831681810361320457613204613010565b6001019392505050565b60006020828403121561322057600080fd5b8151611a64816126a7565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261326057600080fd5b83018035915067ffffffffffffffff82111561327b57600080fd5b6020019150600681901b3603821315612bdf57600080fd5b6000604082840312156132a557600080fd5b6132ad6125e8565b82356132b8816126bd565b81526020928301359281019290925250919050565b600082825180855260208086019550808260051b84010181860160005b8481101561339d577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018952815160a0815181865261332e8287018261281d565b9150508582015185820387870152613346828261281d565b91505060408083015186830382880152613360838261281d565b92505050606080830151818701525060808083015192508582038187015250613389818361281d565b9a86019a94505050908301906001016132ea565b5090979650505050505050565b67ffffffffffffffff851681526060602082015260006133cd60608301866132cd565b82810360408401526124cf818587612c2f565b600060208083850312156133f357600080fd5b825167ffffffffffffffff8082111561340b57600080fd5b818501915085601f83011261341f57600080fd5b815161342d61272882612683565b81815260059190911b8301840190848101908883111561344c57600080fd5b8585015b83811015613484578051858111156134685760008081fd5b6134768b89838a010161310b565b845250918601918601613450565b5098975050505050505050565b602081526134e260208201835180518252602081015167ffffffffffffffff808216602085015280604084015116604085015280606084015116606085015280608084015116608085015250505050565b6000602083015161350b60c084018273ffffffffffffffffffffffffffffffffffffffff169052565b5060408301516101808060e08501526135286101a085018361281d565b915060608501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08086850301610100870152613565848361281d565b9350608087015191508086850301610120870152613583848361281d565b935060a087015191506135af61014087018373ffffffffffffffffffffffffffffffffffffffff169052565b60c087015161016087015260e08701519150808685030183870152506135d583826132cd565b9695505050505050565b6101008101613637828567ffffffffffffffff8151168252602081015173ffffffffffffffffffffffffffffffffffffffff808216602085015280604084015116604085015280606084015116606085015250505050565b825173ffffffffffffffffffffffffffffffffffffffff90811660808401526020840151811660a08401526040840151811660c084015260608401511660e0830152611a64565b602081526000825160a0602084015261369a60c084018261281d565b905067ffffffffffffffff6020850151166040840152604084015173ffffffffffffffffffffffffffffffffffffffff8082166060860152606086015160808601528060808701511660a086015250508091505092915050565b60006020828403121561370657600080fd5b815167ffffffffffffffff8082111561371e57600080fd5b908301906040828603121561373257600080fd5b61373a6125e8565b82518281111561374957600080fd5b6137558782860161310b565b82525060208301518281111561376a57600080fd5b6137768782860161310b565b60208301525095945050505050565b600073ffffffffffffffffffffffffffffffffffffffff808916835260c060208401526137b560c084018961281d565b67ffffffffffffffff97881660408501529590961660608301525091909316608082015260a0019190915292915050565b60208152600061072a60208301846132cd565b8181038181111561072d5761072d613010565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b60008251612e548184602087016127f956fea164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"reentrancyGuardEntered\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CannotSendZeroTokens\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GetSupportedTokensFunctionalityRemovedCheckAdminRegistry\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidAllowListRequest\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidDestChainConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeCalledByRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrAllowlistAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrancyGuardReentrantCall\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RouterMustSetOriginalSender\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"UnsupportedToken\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"name\":\"AllowListAdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"senders\",\"type\":\"address[]\"}],\"name\":\"AllowListSendersAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"senders\",\"type\":\"address[]\"}],\"name\":\"AllowListSendersRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"CCIPMessageSent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOnRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"reentrancyGuardEntered\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"allowListEnabled\",\"type\":\"bool\"}],\"name\":\"DestChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"feeValueJuels\",\"type\":\"uint256\"}],\"name\":\"FeePaid\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeeTokenWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"allowListEnabled\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"addedAllowlistedSenders\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"removedAllowlistedSenders\",\"type\":\"address[]\"}],\"internalType\":\"structOnRamp.AllowListConfigArgs[]\",\"name\":\"allowListConfigArgsItems\",\"type\":\"tuple[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyDestChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"}],\"name\":\"forwardFromRouter\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getAllowedSendersList\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getDestChainConfig\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"allowListEnabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"reentrancyGuardEntered\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getExpectedNextSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"getFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"},{\"internalType\":\"contractIERC20\",\"name\":\"sourceToken\",\"type\":\"address\"}],\"name\":\"getPoolBySourceToken\",\"outputs\":[{\"internalType\":\"contractIPoolV1\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"contractIRouter\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"name\":\"getSupportedTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"reentrancyGuardEntered\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"setDynamicConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"withdrawFeeTokens\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x6101006040523480156200001257600080fd5b506040516200429d3803806200429d83398101604081905262000035916200073f565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf8162000186565b505083516001600160401b031615905080620000e6575060208301516001600160a01b0316155b80620000fd575060408301516001600160a01b0316155b8062000114575060608301516001600160a01b0316155b1562000133576040516306b7c75960e31b815260040160405180910390fd5b82516001600160401b031660805260208301516001600160a01b0390811660a0526040840151811660c05260608401511660e052620001728262000231565b6200017d81620003e0565b50505062000840565b336001600160a01b03821603620001e05760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b0316158062000254575060608101516001600160a01b0316155b8062000261575080602001515b1562000280576040516306b7c75960e31b815260040160405180910390fd5b8051600280546020808501511515600160a01b026001600160a81b03199092166001600160a01b039485161791909117909155604080840151600380549185166001600160a01b0319928316179055606080860151600480549187169184169190911790556080808701516005805491881691909416179092558251808301845291516001600160401b0316825260a05185169382019390935260c05184168183015260e05190931691830191909152517fc7372d2d886367d7bb1b0e0708a5436f2c91d6963de210eb2dc1ec2ecd6d21f191620003d591849082516001600160401b031681526020808401516001600160a01b03908116828401526040858101518216818501526060958601518216868501528451821660808086019190915292850151151560a0850152840151811660c084015293830151841660e0830152909101519091166101008201526101200190565b60405180910390a150565b60005b81518110156200051f5760008282815181106200040457620004046200082a565b6020026020010151905060008383815181106200042557620004256200082a565b6020026020010151600001519050806001600160401b03166000036200046a5760405163c35aa79d60e01b81526001600160401b038216600482015260240162000083565b6001600160401b03818116600081815260066020908152604091829020868201518154600160481b600160e81b0319811669010000000000000000006001600160a01b03909316928302908117808555865192891691909816178152928301526801000000000000000090940460ff161515918101919091527fd5ad72bc37dc7a80a8b9b9df20500046fd7341adb1be2258a540466fdd7dcef59060600160405180910390a2505050806001019050620003e3565b5050565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b03811182821017156200055e576200055e62000523565b60405290565b604051601f8201601f191681016001600160401b03811182821017156200058f576200058f62000523565b604052919050565b80516001600160401b0381168114620005af57600080fd5b919050565b6001600160a01b0381168114620005ca57600080fd5b50565b600060a08284031215620005e057600080fd5b60405160a081016001600160401b038111828210171562000605576200060562000523565b806040525080915082516200061a81620005b4565b8152602083015180151581146200063057600080fd5b602082015260408301516200064581620005b4565b604082015260608301516200065a81620005b4565b606082015260808301516200066f81620005b4565b6080919091015292915050565b600082601f8301126200068e57600080fd5b815160206001600160401b03821115620006ac57620006ac62000523565b620006bc818360051b0162000564565b82815260069290921b84018101918181019086841115620006dc57600080fd5b8286015b84811015620007345760408189031215620006fb5760008081fd5b6200070562000539565b620007108262000597565b8152848201516200072181620005b4565b81860152835291830191604001620006e0565b509695505050505050565b60008060008385036101408112156200075757600080fd5b60808112156200076657600080fd5b50604051608081016001600160401b0380821183831017156200078d576200078d62000523565b816040526200079c8762000597565b835260208701519150620007b082620005b4565b81602084015260408701519150620007c882620005b4565b81604084015260608701519150620007e082620005b4565b816060840152829550620007f88860808901620005cd565b94506101208701519250808311156200081057600080fd5b505062000820868287016200067c565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b60805160a05160c05160e0516139e4620008b96000396000818161022c01528181610cfd0152611c290152600081816101f0015281816116240152611c020152600081816101b4015281816106080152611bd80152600081816101840152818161114b0152818161173f0152611bb401526139e46000f3fe608060405234801561001057600080fd5b50600436106101365760003560e01c80637437ff9f116100b2578063972b461211610081578063df0aa9e911610066578063df0aa9e914610557578063f2fde38b1461056a578063fbca3b741461057d57600080fd5b8063972b4612146104ea578063d77d5ed01461050a57600080fd5b80637437ff9f146103ee57806379ba5097146104985780638da5cb5b146104a05780639041be3d146104be57600080fd5b806327e936f1116101095780633a019940116100ee5780633a0199401461030f57806348a98aa4146103175780636def4ce71461034f57600080fd5b806327e936f1146102e957806334adf494146102fc57600080fd5b80630242cf601461013b57806306285c6914610150578063181f5a771461027f57806320487ded146102c8575b600080fd5b61014e6101493660046127df565b610590565b005b61026960408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16815250905090565b60405161027691906128a2565b60405180910390f35b6102bb6040518060400160405280601081526020017f4f6e52616d7020312e362e302d6465760000000000000000000000000000000081525081565b6040516102769190612967565b6102db6102d6366004612992565b6105a4565b604051908152602001610276565b61014e6102f7366004612a00565b61075d565b61014e61030a366004612a98565b61076e565b61014e610a8a565b61032a610325366004612b0d565b610cb5565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610276565b6103b261035d366004612b46565b67ffffffffffffffff9081166000908152600660205260409020549081169168010000000000000000820460ff16916901000000000000000000900473ffffffffffffffffffffffffffffffffffffffff1690565b6040805167ffffffffffffffff9094168452911515602084015273ffffffffffffffffffffffffffffffffffffffff1690820152606001610276565b61048b6040805160a081018252600080825260208201819052918101829052606081018290526080810191909152506040805160a08101825260025473ffffffffffffffffffffffffffffffffffffffff80821683527401000000000000000000000000000000000000000090910460ff161515602083015260035481169282019290925260045482166060820152600554909116608082015290565b6040516102769190612b63565b61014e610d6a565b60005473ffffffffffffffffffffffffffffffffffffffff1661032a565b6104d16104cc366004612b46565b610e67565b60405167ffffffffffffffff9091168152602001610276565b6104fd6104f8366004612b46565b610e90565b6040516102769190612bbc565b61032a610518366004612b46565b67ffffffffffffffff166000908152600660205260409020546901000000000000000000900473ffffffffffffffffffffffffffffffffffffffff1690565b6102db610565366004612c16565b610eb8565b61014e610578366004612c82565b61181c565b6104fd61058b366004612b46565b61182d565b610598611861565b6105a1816118e4565b50565b6040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815277ffffffffffffffff00000000000000000000000000000000608084901b16600482015260009073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690632cbc26bb90602401602060405180830381865afa15801561064f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106739190612c9f565b156106bb576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024015b60405180910390fd5b6002546040517fd8694ccd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063d8694ccd906107139086908690600401612dd0565b602060405180830381865afa158015610730573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107549190612f19565b90505b92915050565b610765611861565b6105a181611a5b565b60005473ffffffffffffffffffffffffffffffffffffffff1633146107de5760055473ffffffffffffffffffffffffffffffffffffffff1633146107de576040517f905d7d9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015610a855760008383838181106107fd576107fd612f32565b905060200281019061080f9190612f61565b61081890613012565b805167ffffffffffffffff1660009081526006602090815260409182902090830151815490151568010000000000000000027fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff909116178155908201515191925090156109d8578160200151156109975760005b826040015151811015610947576000836040015182815181106108b1576108b1612f32565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036109305783516040517f463258ff00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016106b2565b61093d6001840182611c8b565b505060010161088c565b50816000015167ffffffffffffffff167f330939f6eafe8bb516716892fe962ff19770570838686e6579dbc1cc51fc3281836040015160405161098a9190612bbc565b60405180910390a26109d8565b81516040517f463258ff00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016106b2565b60005b826060015151811015610a2457610a1b83606001518281518110610a0157610a01612f32565b602002602001015183600101611cad90919063ffffffff16565b506001016109db565b5060608201515115610a7b57816000015167ffffffffffffffff167fc237ec1921f855ccd5e9a5af9733f2d58943a5a8501ec5988e305d7a4d4215868360600151604051610a729190612bbc565b60405180910390a25b50506001016107e1565b505050565b600254604080517fcdc73d51000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163cdc73d5191600480830192869291908290030181865afa158015610af9573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610b3f91908101906130c3565b60045490915073ffffffffffffffffffffffffffffffffffffffff1660005b8251811015610a85576000838281518110610b7b57610b7b612f32565b60209081029190910101516040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915060009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa158015610bf6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c1a9190612f19565b90508015610cab57610c4373ffffffffffffffffffffffffffffffffffffffff83168583611ccf565b8173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f508d7d183612c18fc339b42618912b9fa3239f631dd7ec0671f950200a0fa66e83604051610ca291815260200190565b60405180910390a35b5050600101610b5e565b6040517fbbe4f6db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063bbe4f6db90602401602060405180830381865afa158015610d46573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107549190613152565b60015473ffffffffffffffffffffffffffffffffffffffff163314610deb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064016106b2565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b67ffffffffffffffff80821660009081526006602052604081205490916107579116600161319e565b67ffffffffffffffff8116600090815260066020526040902060609061075790600101611d5c565b60025460009074010000000000000000000000000000000000000000900460ff1615610f10576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905567ffffffffffffffff8516600090815260066020526040902073ffffffffffffffffffffffffffffffffffffffff8316610fb5576040517fa4ec747900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805468010000000000000000900460ff161561102657610fd86001820184611d70565b611026576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841660048201526024016106b2565b80546901000000000000000000900473ffffffffffffffffffffffffffffffffffffffff163314611083576040517f1c0a352900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60035473ffffffffffffffffffffffffffffffffffffffff168015611129576040517fe0a0e50600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82169063e0a0e506906110f6908a908a90600401612dd0565b600060405180830381600087803b15801561111057600080fd5b505af1158015611124573d6000803e3d6000fd5b505050505b50604080516101a081019091526000610100820181815267ffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811661012085015289811661014085015284549293928392916101608401918791879161119791166131bf565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905567ffffffffffffffff168152602001600067ffffffffffffffff1681525081526020018573ffffffffffffffffffffffffffffffffffffffff16815260200187806020019061120b91906131e6565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050509082525060200161124f88806131e6565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920182905250938552505060408051602081810183529381529284019290925250016112ab6080890160608a01612c82565b73ffffffffffffffffffffffffffffffffffffffff1681526020018681526020018780604001906112dc919061324b565b905067ffffffffffffffff8111156112f6576112f66126dc565b60405190808252806020026020018201604052801561135957816020015b6113466040518060a0016040528060608152602001606081526020016060815260200160008152602001606081525090565b8152602001906001900390816113145790505b5090529050600061136d604088018861324b565b808060200260200160405190810160405280939291908181526020016000905b828210156113b9576113aa604083028601368190038101906132b3565b8152602001906001019061138d565b5050505050905060005b6113d0604089018961324b565b9050811015611469576114408282815181106113ee576113ee612f32565b60209081029190910101518a6114048b806131e6565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508c9250611d9f915050565b8360e00151828151811061145657611456612f32565b60209081029190910101526001016113c3565b50600080600080600260000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166397d640a28d8d60600160208101906114c59190612c82565b8d8f80608001906114d691906131e6565b8c60e001518c6040518863ffffffff1660e01b81526004016114fe97969594939291906133ca565b600060405180830381865afa15801561151b573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261156191908101906134fc565b9296509094509250905061157b60808c0160608d01612c82565b73ffffffffffffffffffffffffffffffffffffffff167f075a2720282fdf622141dae0b048ef90a21a7e57c134c76912d19d006b3b3f6f856040516115c291815260200190565b60405180910390a282611696576040517fea458c0c00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8d16600482015273ffffffffffffffffffffffffffffffffffffffff8a811660248301527f0000000000000000000000000000000000000000000000000000000000000000169063ea458c0c906044016020604051808303816000875af115801561166d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061169191906135ef565b611699565b60005b865167ffffffffffffffff909116608091820152860182905260005b8660e0015151811015611709578181815181106116d4576116d4612f32565b60200260200101518760e0015182815181106116f2576116f2612f32565b6020908102919091010151608001526001016116b5565b50604080517f130ac867e79e2789f923760a88743d292acdf7002139a588206e2260f73f7321602082015267ffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811692820192909252908d16606082015230608082015261179990879060a001604051602081830303815290604052805190602001206120c5565b86515260405167ffffffffffffffff8d16907ff6e86ef8896c7a0d629406168f396e883280680c99e649b9e2d36466fbc9f9e5906117d890899061360c565b60405180910390a25050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1690555050905151925050505b949350505050565b611824611861565b6105a1816121c5565b60606040517f9e7177c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005473ffffffffffffffffffffffffffffffffffffffff1633146118e2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016106b2565b565b60005b8151811015611a5757600082828151811061190457611904612f32565b60200260200101519050600083838151811061192257611922612f32565b60200260200101516000015190508067ffffffffffffffff16600003611980576040517fc35aa79d00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff821660048201526024016106b2565b67ffffffffffffffff8181166000818152600660209081526040918290208682015181547fffffff0000000000000000000000000000000000000000ffffffffffffffffff8116690100000000000000000073ffffffffffffffffffffffffffffffffffffffff909316928302908117808555865192891691909816178152928301526801000000000000000090940460ff161515918101919091527fd5ad72bc37dc7a80a8b9b9df20500046fd7341adb1be2258a540466fdd7dcef59060600160405180910390a25050508060010190506118e7565b5050565b805173ffffffffffffffffffffffffffffffffffffffff161580611a975750606081015173ffffffffffffffffffffffffffffffffffffffff16155b80611aa3575080602001515b15611ada576040517f35be3ac800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160028054602080850151151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00000000000000000000000000000000000000000090921673ffffffffffffffffffffffffffffffffffffffff9485161791909117909155604080840151600380549185167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316179055606080860151600480549187169184169190911790556080808701516005805491881691909416179092558251918201835267ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001682527f00000000000000000000000000000000000000000000000000000000000000008516938201939093527f00000000000000000000000000000000000000000000000000000000000000008416818301527f000000000000000000000000000000000000000000000000000000000000000090931691830191909152517fc7372d2d886367d7bb1b0e0708a5436f2c91d6963de210eb2dc1ec2ecd6d21f191611c8091849061375a565b60405180910390a150565b60006107548373ffffffffffffffffffffffffffffffffffffffff84166122ba565b60006107548373ffffffffffffffffffffffffffffffffffffffff8416612309565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052610a85908490612403565b60606000611d698361250f565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515610754565b611dd16040518060a0016040528060608152602001606081526020016060815260200160008152602001606081525090565b8460200151600003611e0f576040517f5cf0444900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611e1f858760000151610cb5565b905073ffffffffffffffffffffffffffffffffffffffff81161580611eef57506040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527faff2afbf00000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff8216906301ffc9a790602401602060405180830381865afa158015611ec9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611eed9190612c9f565b155b15611f415785516040517fbf16aab600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911660048201526024016106b2565b60008173ffffffffffffffffffffffffffffffffffffffff16639a4575b96040518060a001604052808881526020018967ffffffffffffffff1681526020018773ffffffffffffffffffffffffffffffffffffffff1681526020018a6020015181526020018a6000015173ffffffffffffffffffffffffffffffffffffffff168152506040518263ffffffff1660e01b8152600401611fe09190613808565b6000604051808303816000875af1158015611fff573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052612045919081019061387e565b6040805160a0810190915273ffffffffffffffffffffffffffffffffffffffff841660c08201529091508060e0810160405160208183030381529060405281526020018260000151815260200182602001518152602001886020015181526020016040518060200160405280600081525081525092505050949350505050565b60008060001b82846020015185606001518660000151606001518760000151608001518860a001518960c001516040516020016121079695949392919061390f565b604051602081830303815290604052805190602001208560400151805190602001208660e0015160405160200161213e9190613970565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201206080808c0151805190840120928501989098529183019590955260608201939093529384015260a083015260c082015260e00160405160208183030381529060405280519060200120905092915050565b3373ffffffffffffffffffffffffffffffffffffffff821603612244576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016106b2565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600081815260018301602052604081205461230157508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610757565b506000610757565b600081815260018301602052604081205480156123f257600061232d600183613983565b855490915060009061234190600190613983565b90508082146123a657600086600001828154811061236157612361612f32565b906000526020600020015490508087600001848154811061238457612384612f32565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806123b7576123b7613996565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610757565b6000915050610757565b5092915050565b6000612465826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff1661256b9092919063ffffffff16565b805190915015610a8557808060200190518101906124839190612c9f565b610a85576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016106b2565b60608160000180548060200260200160405190810160405280929190818152602001828054801561255f57602002820191906000526020600020905b81548152602001906001019080831161254b575b50505050509050919050565b60606118148484600085856000808673ffffffffffffffffffffffffffffffffffffffff16858760405161259f91906139c5565b60006040518083038185875af1925050503d80600081146125dc576040519150601f19603f3d011682016040523d82523d6000602084013e6125e1565b606091505b50915091506125f2878383876125fd565b979650505050505050565b6060831561269357825160000361268c5773ffffffffffffffffffffffffffffffffffffffff85163b61268c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016106b2565b5081611814565b61181483838151156126a85781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106b29190612967565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561272e5761272e6126dc565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561277b5761277b6126dc565b604052919050565b600067ffffffffffffffff82111561279d5761279d6126dc565b5060051b60200190565b67ffffffffffffffff811681146105a157600080fd5b73ffffffffffffffffffffffffffffffffffffffff811681146105a157600080fd5b600060208083850312156127f257600080fd5b823567ffffffffffffffff81111561280957600080fd5b8301601f8101851361281a57600080fd5b803561282d61282882612783565b612734565b81815260069190911b8201830190838101908783111561284c57600080fd5b928401925b828410156125f2576040848903121561286a5760008081fd5b61287261270b565b843561287d816127a7565b81528486013561288c816127bd565b8187015282526040939093019290840190612851565b60808101610757828467ffffffffffffffff8151168252602081015173ffffffffffffffffffffffffffffffffffffffff808216602085015280604084015116604085015280606084015116606085015250505050565b60005b838110156129145781810151838201526020016128fc565b50506000910152565b600081518084526129358160208601602086016128f9565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610754602083018461291d565b600060a0828403121561298c57600080fd5b50919050565b600080604083850312156129a557600080fd5b82356129b0816127a7565b9150602083013567ffffffffffffffff8111156129cc57600080fd5b6129d88582860161297a565b9150509250929050565b80356129ed816127bd565b919050565b80151581146105a157600080fd5b600060a08284031215612a1257600080fd5b60405160a0810181811067ffffffffffffffff82111715612a3557612a356126dc565b6040528235612a43816127bd565b81526020830135612a53816129f2565b60208201526040830135612a66816127bd565b60408201526060830135612a79816127bd565b60608201526080830135612a8c816127bd565b60808201529392505050565b60008060208385031215612aab57600080fd5b823567ffffffffffffffff80821115612ac357600080fd5b818501915085601f830112612ad757600080fd5b813581811115612ae657600080fd5b8660208260051b8501011115612afb57600080fd5b60209290920196919550909350505050565b60008060408385031215612b2057600080fd5b8235612b2b816127a7565b91506020830135612b3b816127bd565b809150509250929050565b600060208284031215612b5857600080fd5b8135611d69816127a7565b60a08101610757828473ffffffffffffffffffffffffffffffffffffffff808251168352602082015115156020840152806040830151166040840152806060830151166060840152806080830151166080840152505050565b6020808252825182820181905260009190848201906040850190845b81811015612c0a57835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101612bd8565b50909695505050505050565b60008060008060808587031215612c2c57600080fd5b8435612c37816127a7565b9350602085013567ffffffffffffffff811115612c5357600080fd5b612c5f8782880161297a565b935050604085013591506060850135612c77816127bd565b939692955090935050565b600060208284031215612c9457600080fd5b8135611d69816127bd565b600060208284031215612cb157600080fd5b8151611d69816129f2565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112612cf157600080fd5b830160208101925035905067ffffffffffffffff811115612d1157600080fd5b803603821315612d2057600080fd5b9250929050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b8183526000602080850194508260005b85811015612dc5578135612d93816127bd565b73ffffffffffffffffffffffffffffffffffffffff168752818301358388015260409687019690910190600101612d80565b509495945050505050565b600067ffffffffffffffff808516835260406020840152612df18485612cbc565b60a06040860152612e0660e086018284612d27565b915050612e166020860186612cbc565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc080878503016060880152612e4c848385612d27565b9350604088013592507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1883603018312612e8557600080fd5b60209288019283019235915084821115612e9e57600080fd5b8160061b3603831315612eb057600080fd5b80878503016080880152612ec5848385612d70565b9450612ed3606089016129e2565b73ffffffffffffffffffffffffffffffffffffffff811660a08901529350612efe6080890189612cbc565b94509250808786030160c088015250506125f2838383612d27565b600060208284031215612f2b57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81833603018112612f9557600080fd5b9190910192915050565b600082601f830112612fb057600080fd5b81356020612fc061282883612783565b8083825260208201915060208460051b870101935086841115612fe257600080fd5b602086015b84811015613007578035612ffa816127bd565b8352918301918301612fe7565b509695505050505050565b60006080823603121561302457600080fd5b6040516080810167ffffffffffffffff8282108183111715613048576130486126dc565b8160405284359150613059826127a7565b90825260208401359061306b826129f2565b816020840152604085013591508082111561308557600080fd5b61309136838701612f9f565b604084015260608501359150808211156130aa57600080fd5b506130b736828601612f9f565b60608301525092915050565b600060208083850312156130d657600080fd5b825167ffffffffffffffff8111156130ed57600080fd5b8301601f810185136130fe57600080fd5b805161310c61282882612783565b81815260059190911b8201830190838101908783111561312b57600080fd5b928401925b828410156125f2578351613143816127bd565b82529284019290840190613130565b60006020828403121561316457600080fd5b8151611d69816127bd565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b67ffffffffffffffff8181168382160190808211156123fc576123fc61316f565b600067ffffffffffffffff8083168181036131dc576131dc61316f565b6001019392505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261321b57600080fd5b83018035915067ffffffffffffffff82111561323657600080fd5b602001915036819003821315612d2057600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261328057600080fd5b83018035915067ffffffffffffffff82111561329b57600080fd5b6020019150600681901b3603821315612d2057600080fd5b6000604082840312156132c557600080fd5b6132cd61270b565b82356132d8816127bd565b81526020928301359281019290925250919050565b600082825180855260208086019550808260051b84010181860160005b848110156133bd577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018952815160a0815181865261334e8287018261291d565b9150508582015185820387870152613366828261291d565b91505060408083015186830382880152613380838261291d565b925050506060808301518187015250608080830151925085820381870152506133a9818361291d565b9a86019a945050509083019060010161330a565b5090979650505050505050565b67ffffffffffffffff881681526000602073ffffffffffffffffffffffffffffffffffffffff808a1682850152604089604086015260c0606086015261341460c08601898b612d27565b858103608087015261342681896132ed565b86810360a0880152875180825285890192509085019060005b8181101561346657835180518716845287015187840152928601929184019160010161343f565b50909e9d5050505050505050505050505050565b600082601f83011261348b57600080fd5b815167ffffffffffffffff8111156134a5576134a56126dc565b6134d660207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601612734565b8181528460208386010111156134eb57600080fd5b6118148260208301602087016128f9565b6000806000806080858703121561351257600080fd5b84519350602080860151613525816129f2565b604087015190945067ffffffffffffffff8082111561354357600080fd5b61354f89838a0161347a565b9450606088015191508082111561356557600080fd5b818801915088601f83011261357957600080fd5b815161358761282882612783565b81815260059190911b8301840190848101908b8311156135a657600080fd5b8585015b838110156135de578051858111156135c25760008081fd5b6135d08e89838a010161347a565b8452509186019186016135aa565b50989b979a50959850505050505050565b60006020828403121561360157600080fd5b8151611d69816127a7565b6020815261365d60208201835180518252602081015167ffffffffffffffff808216602085015280604084015116604085015280606084015116606085015280608084015116608085015250505050565b6000602083015161368660c084018273ffffffffffffffffffffffffffffffffffffffff169052565b5060408301516101808060e08501526136a36101a085018361291d565b915060608501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe080868503016101008701526136e0848361291d565b93506080870151915080868503016101208701526136fe848361291d565b935060a0870151915061372a61014087018373ffffffffffffffffffffffffffffffffffffffff169052565b60c087015161016087015260e087015191508086850301838701525061375083826132ed565b9695505050505050565b61012081016137b2828567ffffffffffffffff8151168252602081015173ffffffffffffffffffffffffffffffffffffffff808216602085015280604084015116604085015280606084015116606085015250505050565b825173ffffffffffffffffffffffffffffffffffffffff9081166080848101919091526020850151151560a08501526040850151821660c08501526060850151821660e085015284015116610100830152611d69565b602081526000825160a0602084015261382460c084018261291d565b905067ffffffffffffffff6020850151166040840152604084015173ffffffffffffffffffffffffffffffffffffffff8082166060860152606086015160808601528060808701511660a086015250508091505092915050565b60006020828403121561389057600080fd5b815167ffffffffffffffff808211156138a857600080fd5b90830190604082860312156138bc57600080fd5b6138c461270b565b8251828111156138d357600080fd5b6138df8782860161347a565b8252506020830151828111156138f457600080fd5b6139008782860161347a565b60208301525095945050505050565b600073ffffffffffffffffffffffffffffffffffffffff808916835260c0602084015261393f60c084018961291d565b67ffffffffffffffff97881660408501529590961660608301525091909316608082015260a0019190915292915050565b60208152600061075460208301846132ed565b818103818111156107575761075761316f565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b60008251612f958184602087016128f956fea164736f6c6343000818000a", } var OnRampABI = OnRampMetaData.ABI @@ -1919,7 +1920,7 @@ func (OnRampCCIPMessageSent) Topic() common.Hash { } func (OnRampConfigSet) Topic() common.Hash { - return common.HexToHash("0x23a1adf8ad7fad6091a4803227af2cee848c01a7c812404cade7c25636925e32") + return common.HexToHash("0xc7372d2d886367d7bb1b0e0708a5436f2c91d6963de210eb2dc1ec2ecd6d21f1") } func (OnRampDestChainConfigSet) Topic() common.Hash { diff --git a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt index a869de6bcf..9eeee161c2 100644 --- a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -12,7 +12,7 @@ commit_store_helper: ../../../contracts/solc/v0.8.24/CommitStoreHelper/CommitSto ether_sender_receiver: ../../../contracts/solc/v0.8.24/EtherSenderReceiver/EtherSenderReceiver.abi ../../../contracts/solc/v0.8.24/EtherSenderReceiver/EtherSenderReceiver.bin 09510a3f773f108a3c231e8d202835c845ded862d071ec54c4f89c12d868b8de evm_2_evm_offramp: ../../../contracts/solc/v0.8.24/EVM2EVMOffRamp/EVM2EVMOffRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMOffRamp/EVM2EVMOffRamp.bin b0d77babbe635cd6ba04c2af049badc9e9d28a4b6ed6bb75f830ad902a618beb evm_2_evm_onramp: ../../../contracts/solc/v0.8.24/EVM2EVMOnRamp/EVM2EVMOnRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMOnRamp/EVM2EVMOnRamp.bin 5c02c2b167946b3467636ff2bb58594cb4652fc63d8bdfee2488ed562e2a3e50 -fee_quoter: ../../../contracts/solc/v0.8.24/FeeQuoter/FeeQuoter.abi ../../../contracts/solc/v0.8.24/FeeQuoter/FeeQuoter.bin 392a7b95a2ff4e3c5c452965a21f5bdb89ad28316f7280ecf81b81740fd54273 +fee_quoter: ../../../contracts/solc/v0.8.24/FeeQuoter/FeeQuoter.abi ../../../contracts/solc/v0.8.24/FeeQuoter/FeeQuoter.bin 29d5a1e39275bd6d378e4bd2d90e7121bb867c039d27c763086e028066dd51de lock_release_token_pool: ../../../contracts/solc/v0.8.24/LockReleaseTokenPool/LockReleaseTokenPool.abi ../../../contracts/solc/v0.8.24/LockReleaseTokenPool/LockReleaseTokenPool.bin e6a8ec9e8faccb1da7d90e0f702ed72975964f97dc3222b54cfcca0a0ba3fea2 lock_release_token_pool_and_proxy: ../../../contracts/solc/v0.8.24/LockReleaseTokenPoolAndProxy/LockReleaseTokenPoolAndProxy.abi ../../../contracts/solc/v0.8.24/LockReleaseTokenPoolAndProxy/LockReleaseTokenPoolAndProxy.bin e632b08be0fbd1d013e8b3a9d75293d0d532b83071c531ff2be1deec1fa48ec1 maybe_revert_message_receiver: ../../../contracts/solc/v0.8.24/MaybeRevertMessageReceiver/MaybeRevertMessageReceiver.abi ../../../contracts/solc/v0.8.24/MaybeRevertMessageReceiver/MaybeRevertMessageReceiver.bin d73956c26232ebcc4a5444429fa99cbefed960e323be9b5a24925885c2e477d5 @@ -25,7 +25,7 @@ multi_ocr3_helper: ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Help nonce_manager: ../../../contracts/solc/v0.8.24/NonceManager/NonceManager.abi ../../../contracts/solc/v0.8.24/NonceManager/NonceManager.bin 6f64e1083b356c06ee66b9138e398b9c97a4cd3e8c9ec38cf3010cebc79af536 ocr3_config_encoder: ../../../contracts/solc/v0.8.24/IOCR3ConfigEncoder/IOCR3ConfigEncoder.abi ../../../contracts/solc/v0.8.24/IOCR3ConfigEncoder/IOCR3ConfigEncoder.bin 9254b35a86f00fde7b7193a033ca58f6521a66e87b9cf9da6ce5660082e79f5d offramp: ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.abi ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.bin 948feede308d265d1cc2e020bb063229d90cd712bddb1fa9138cb0045c0de2c8 -onramp: ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.abi ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.bin 8e02667c4f38d55f0857ddb2c9d125b93c5c80d83c1fd6e8d7221035c6a50bd1 +onramp: ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.abi ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.bin b6bd68506798be2ac8d29a9e3d78575b42a73e81758b6e3d638bb282a5db1db8 ping_pong_demo: ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.abi ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.bin c1c2f8a65c7ffd971899cae7fe62f2da57d09e936151e2b92163c4bebe699d6b price_registry: ../../../contracts/solc/v0.8.24/PriceRegistry/PriceRegistry.abi ../../../contracts/solc/v0.8.24/PriceRegistry/PriceRegistry.bin e7781d600c1bb7aa4620106af7f6e146a109b97f4cb6a7d06c9e15773340ecb2 registry_module_owner_custom: ../../../contracts/solc/v0.8.24/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.abi ../../../contracts/solc/v0.8.24/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.bin 75be86323c227917a9bbc3f799d7ed02f92db546653a36db30ed0ebe64461353 diff --git a/core/gethwrappers/ccip/mocks/fee_quoter_interface.go b/core/gethwrappers/ccip/mocks/fee_quoter_interface.go index c2ea02f136..c4da25361f 100644 --- a/core/gethwrappers/ccip/mocks/fee_quoter_interface.go +++ b/core/gethwrappers/ccip/mocks/fee_quoter_interface.go @@ -1899,22 +1899,22 @@ func (_c *FeeQuoterInterface_GetTokenPrice_Call) RunAndReturn(run func(*bind.Cal } // GetTokenPriceFeedConfig provides a mock function with given fields: opts, token -func (_m *FeeQuoterInterface) GetTokenPriceFeedConfig(opts *bind.CallOpts, token common.Address) (fee_quoter.IFeeQuoterTokenPriceFeedConfig, error) { +func (_m *FeeQuoterInterface) GetTokenPriceFeedConfig(opts *bind.CallOpts, token common.Address) (fee_quoter.FeeQuoterTokenPriceFeedConfig, error) { ret := _m.Called(opts, token) if len(ret) == 0 { panic("no return value specified for GetTokenPriceFeedConfig") } - var r0 fee_quoter.IFeeQuoterTokenPriceFeedConfig + var r0 fee_quoter.FeeQuoterTokenPriceFeedConfig var r1 error - if rf, ok := ret.Get(0).(func(*bind.CallOpts, common.Address) (fee_quoter.IFeeQuoterTokenPriceFeedConfig, error)); ok { + if rf, ok := ret.Get(0).(func(*bind.CallOpts, common.Address) (fee_quoter.FeeQuoterTokenPriceFeedConfig, error)); ok { return rf(opts, token) } - if rf, ok := ret.Get(0).(func(*bind.CallOpts, common.Address) fee_quoter.IFeeQuoterTokenPriceFeedConfig); ok { + if rf, ok := ret.Get(0).(func(*bind.CallOpts, common.Address) fee_quoter.FeeQuoterTokenPriceFeedConfig); ok { r0 = rf(opts, token) } else { - r0 = ret.Get(0).(fee_quoter.IFeeQuoterTokenPriceFeedConfig) + r0 = ret.Get(0).(fee_quoter.FeeQuoterTokenPriceFeedConfig) } if rf, ok := ret.Get(1).(func(*bind.CallOpts, common.Address) error); ok { @@ -1945,12 +1945,12 @@ func (_c *FeeQuoterInterface_GetTokenPriceFeedConfig_Call) Run(run func(opts *bi return _c } -func (_c *FeeQuoterInterface_GetTokenPriceFeedConfig_Call) Return(_a0 fee_quoter.IFeeQuoterTokenPriceFeedConfig, _a1 error) *FeeQuoterInterface_GetTokenPriceFeedConfig_Call { +func (_c *FeeQuoterInterface_GetTokenPriceFeedConfig_Call) Return(_a0 fee_quoter.FeeQuoterTokenPriceFeedConfig, _a1 error) *FeeQuoterInterface_GetTokenPriceFeedConfig_Call { _c.Call.Return(_a0, _a1) return _c } -func (_c *FeeQuoterInterface_GetTokenPriceFeedConfig_Call) RunAndReturn(run func(*bind.CallOpts, common.Address) (fee_quoter.IFeeQuoterTokenPriceFeedConfig, error)) *FeeQuoterInterface_GetTokenPriceFeedConfig_Call { +func (_c *FeeQuoterInterface_GetTokenPriceFeedConfig_Call) RunAndReturn(run func(*bind.CallOpts, common.Address) (fee_quoter.FeeQuoterTokenPriceFeedConfig, error)) *FeeQuoterInterface_GetTokenPriceFeedConfig_Call { _c.Call.Return(run) return _c } @@ -3295,9 +3295,9 @@ func (_c *FeeQuoterInterface_ParseUsdPerUnitGasUpdated_Call) RunAndReturn(run fu return _c } -// ProcessMessageArgs provides a mock function with given fields: opts, destChainSelector, feeToken, feeTokenAmount, extraArgs -func (_m *FeeQuoterInterface) ProcessMessageArgs(opts *bind.CallOpts, destChainSelector uint64, feeToken common.Address, feeTokenAmount *big.Int, extraArgs []byte) (fee_quoter.ProcessMessageArgs, error) { - ret := _m.Called(opts, destChainSelector, feeToken, feeTokenAmount, extraArgs) +// ProcessMessageArgs provides a mock function with given fields: opts, destChainSelector, feeToken, feeTokenAmount, extraArgs, rampTokenAmounts, sourceTokenAmounts +func (_m *FeeQuoterInterface) ProcessMessageArgs(opts *bind.CallOpts, destChainSelector uint64, feeToken common.Address, feeTokenAmount *big.Int, extraArgs []byte, rampTokenAmounts []fee_quoter.InternalRampTokenAmount, sourceTokenAmounts []fee_quoter.ClientEVMTokenAmount) (fee_quoter.ProcessMessageArgs, error) { + ret := _m.Called(opts, destChainSelector, feeToken, feeTokenAmount, extraArgs, rampTokenAmounts, sourceTokenAmounts) if len(ret) == 0 { panic("no return value specified for ProcessMessageArgs") @@ -3305,17 +3305,17 @@ func (_m *FeeQuoterInterface) ProcessMessageArgs(opts *bind.CallOpts, destChainS var r0 fee_quoter.ProcessMessageArgs var r1 error - if rf, ok := ret.Get(0).(func(*bind.CallOpts, uint64, common.Address, *big.Int, []byte) (fee_quoter.ProcessMessageArgs, error)); ok { - return rf(opts, destChainSelector, feeToken, feeTokenAmount, extraArgs) + if rf, ok := ret.Get(0).(func(*bind.CallOpts, uint64, common.Address, *big.Int, []byte, []fee_quoter.InternalRampTokenAmount, []fee_quoter.ClientEVMTokenAmount) (fee_quoter.ProcessMessageArgs, error)); ok { + return rf(opts, destChainSelector, feeToken, feeTokenAmount, extraArgs, rampTokenAmounts, sourceTokenAmounts) } - if rf, ok := ret.Get(0).(func(*bind.CallOpts, uint64, common.Address, *big.Int, []byte) fee_quoter.ProcessMessageArgs); ok { - r0 = rf(opts, destChainSelector, feeToken, feeTokenAmount, extraArgs) + if rf, ok := ret.Get(0).(func(*bind.CallOpts, uint64, common.Address, *big.Int, []byte, []fee_quoter.InternalRampTokenAmount, []fee_quoter.ClientEVMTokenAmount) fee_quoter.ProcessMessageArgs); ok { + r0 = rf(opts, destChainSelector, feeToken, feeTokenAmount, extraArgs, rampTokenAmounts, sourceTokenAmounts) } else { r0 = ret.Get(0).(fee_quoter.ProcessMessageArgs) } - if rf, ok := ret.Get(1).(func(*bind.CallOpts, uint64, common.Address, *big.Int, []byte) error); ok { - r1 = rf(opts, destChainSelector, feeToken, feeTokenAmount, extraArgs) + if rf, ok := ret.Get(1).(func(*bind.CallOpts, uint64, common.Address, *big.Int, []byte, []fee_quoter.InternalRampTokenAmount, []fee_quoter.ClientEVMTokenAmount) error); ok { + r1 = rf(opts, destChainSelector, feeToken, feeTokenAmount, extraArgs, rampTokenAmounts, sourceTokenAmounts) } else { r1 = ret.Error(1) } @@ -3334,84 +3334,25 @@ type FeeQuoterInterface_ProcessMessageArgs_Call struct { // - feeToken common.Address // - feeTokenAmount *big.Int // - extraArgs []byte -func (_e *FeeQuoterInterface_Expecter) ProcessMessageArgs(opts interface{}, destChainSelector interface{}, feeToken interface{}, feeTokenAmount interface{}, extraArgs interface{}) *FeeQuoterInterface_ProcessMessageArgs_Call { - return &FeeQuoterInterface_ProcessMessageArgs_Call{Call: _e.mock.On("ProcessMessageArgs", opts, destChainSelector, feeToken, feeTokenAmount, extraArgs)} -} - -func (_c *FeeQuoterInterface_ProcessMessageArgs_Call) Run(run func(opts *bind.CallOpts, destChainSelector uint64, feeToken common.Address, feeTokenAmount *big.Int, extraArgs []byte)) *FeeQuoterInterface_ProcessMessageArgs_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.CallOpts), args[1].(uint64), args[2].(common.Address), args[3].(*big.Int), args[4].([]byte)) - }) - return _c -} - -func (_c *FeeQuoterInterface_ProcessMessageArgs_Call) Return(_a0 fee_quoter.ProcessMessageArgs, _a1 error) *FeeQuoterInterface_ProcessMessageArgs_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *FeeQuoterInterface_ProcessMessageArgs_Call) RunAndReturn(run func(*bind.CallOpts, uint64, common.Address, *big.Int, []byte) (fee_quoter.ProcessMessageArgs, error)) *FeeQuoterInterface_ProcessMessageArgs_Call { - _c.Call.Return(run) - return _c -} - -// ProcessPoolReturnData provides a mock function with given fields: opts, destChainSelector, rampTokenAmounts, sourceTokenAmounts -func (_m *FeeQuoterInterface) ProcessPoolReturnData(opts *bind.CallOpts, destChainSelector uint64, rampTokenAmounts []fee_quoter.InternalRampTokenAmount, sourceTokenAmounts []fee_quoter.ClientEVMTokenAmount) ([][]byte, error) { - ret := _m.Called(opts, destChainSelector, rampTokenAmounts, sourceTokenAmounts) - - if len(ret) == 0 { - panic("no return value specified for ProcessPoolReturnData") - } - - var r0 [][]byte - var r1 error - if rf, ok := ret.Get(0).(func(*bind.CallOpts, uint64, []fee_quoter.InternalRampTokenAmount, []fee_quoter.ClientEVMTokenAmount) ([][]byte, error)); ok { - return rf(opts, destChainSelector, rampTokenAmounts, sourceTokenAmounts) - } - if rf, ok := ret.Get(0).(func(*bind.CallOpts, uint64, []fee_quoter.InternalRampTokenAmount, []fee_quoter.ClientEVMTokenAmount) [][]byte); ok { - r0 = rf(opts, destChainSelector, rampTokenAmounts, sourceTokenAmounts) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([][]byte) - } - } - - if rf, ok := ret.Get(1).(func(*bind.CallOpts, uint64, []fee_quoter.InternalRampTokenAmount, []fee_quoter.ClientEVMTokenAmount) error); ok { - r1 = rf(opts, destChainSelector, rampTokenAmounts, sourceTokenAmounts) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// FeeQuoterInterface_ProcessPoolReturnData_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ProcessPoolReturnData' -type FeeQuoterInterface_ProcessPoolReturnData_Call struct { - *mock.Call -} - -// ProcessPoolReturnData is a helper method to define mock.On call -// - opts *bind.CallOpts -// - destChainSelector uint64 // - rampTokenAmounts []fee_quoter.InternalRampTokenAmount // - sourceTokenAmounts []fee_quoter.ClientEVMTokenAmount -func (_e *FeeQuoterInterface_Expecter) ProcessPoolReturnData(opts interface{}, destChainSelector interface{}, rampTokenAmounts interface{}, sourceTokenAmounts interface{}) *FeeQuoterInterface_ProcessPoolReturnData_Call { - return &FeeQuoterInterface_ProcessPoolReturnData_Call{Call: _e.mock.On("ProcessPoolReturnData", opts, destChainSelector, rampTokenAmounts, sourceTokenAmounts)} +func (_e *FeeQuoterInterface_Expecter) ProcessMessageArgs(opts interface{}, destChainSelector interface{}, feeToken interface{}, feeTokenAmount interface{}, extraArgs interface{}, rampTokenAmounts interface{}, sourceTokenAmounts interface{}) *FeeQuoterInterface_ProcessMessageArgs_Call { + return &FeeQuoterInterface_ProcessMessageArgs_Call{Call: _e.mock.On("ProcessMessageArgs", opts, destChainSelector, feeToken, feeTokenAmount, extraArgs, rampTokenAmounts, sourceTokenAmounts)} } -func (_c *FeeQuoterInterface_ProcessPoolReturnData_Call) Run(run func(opts *bind.CallOpts, destChainSelector uint64, rampTokenAmounts []fee_quoter.InternalRampTokenAmount, sourceTokenAmounts []fee_quoter.ClientEVMTokenAmount)) *FeeQuoterInterface_ProcessPoolReturnData_Call { +func (_c *FeeQuoterInterface_ProcessMessageArgs_Call) Run(run func(opts *bind.CallOpts, destChainSelector uint64, feeToken common.Address, feeTokenAmount *big.Int, extraArgs []byte, rampTokenAmounts []fee_quoter.InternalRampTokenAmount, sourceTokenAmounts []fee_quoter.ClientEVMTokenAmount)) *FeeQuoterInterface_ProcessMessageArgs_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.CallOpts), args[1].(uint64), args[2].([]fee_quoter.InternalRampTokenAmount), args[3].([]fee_quoter.ClientEVMTokenAmount)) + run(args[0].(*bind.CallOpts), args[1].(uint64), args[2].(common.Address), args[3].(*big.Int), args[4].([]byte), args[5].([]fee_quoter.InternalRampTokenAmount), args[6].([]fee_quoter.ClientEVMTokenAmount)) }) return _c } -func (_c *FeeQuoterInterface_ProcessPoolReturnData_Call) Return(_a0 [][]byte, _a1 error) *FeeQuoterInterface_ProcessPoolReturnData_Call { +func (_c *FeeQuoterInterface_ProcessMessageArgs_Call) Return(_a0 fee_quoter.ProcessMessageArgs, _a1 error) *FeeQuoterInterface_ProcessMessageArgs_Call { _c.Call.Return(_a0, _a1) return _c } -func (_c *FeeQuoterInterface_ProcessPoolReturnData_Call) RunAndReturn(run func(*bind.CallOpts, uint64, []fee_quoter.InternalRampTokenAmount, []fee_quoter.ClientEVMTokenAmount) ([][]byte, error)) *FeeQuoterInterface_ProcessPoolReturnData_Call { +func (_c *FeeQuoterInterface_ProcessMessageArgs_Call) RunAndReturn(run func(*bind.CallOpts, uint64, common.Address, *big.Int, []byte, []fee_quoter.InternalRampTokenAmount, []fee_quoter.ClientEVMTokenAmount) (fee_quoter.ProcessMessageArgs, error)) *FeeQuoterInterface_ProcessMessageArgs_Call { _c.Call.Return(run) return _c } From 65f31a88727f58a5bb807b3c72ea9575aa30e034 Mon Sep 17 00:00:00 2001 From: Ryan <80392855+RayXpub@users.noreply.github.com> Date: Fri, 13 Sep 2024 20:28:05 +0400 Subject: [PATCH 095/115] Standardize message hashing functions (#1424) ## Motivation The goal of this PR is to standardize the message hashing functions. Currently we have equivalent but inconsistent message hashing functions: ```solidity function _hash(Any2EVMRampMessage memory original, bytes memory onRamp) internal pure returns (bytes32) ``` and ```solidity function _hash(EVM2AnyRampMessage memory original, bytes32 metadataHash) internal pure returns (bytes32) ``` ## Solution Standardize to `function _hash(message, metadataHash)` and consistently encode dynamic fields. --------- Co-authored-by: app-token-issuer-infra-releng[bot] <120227048+app-token-issuer-infra-releng[bot]@users.noreply.github.com> --- contracts/gas-snapshots/ccip.gas-snapshot | 218 +++++++++--------- .../src/v0.8/ccip/libraries/Internal.sol | 15 +- contracts/src/v0.8/ccip/offRamp/OffRamp.sol | 12 +- .../src/v0.8/ccip/test/NonceManager.t.sol | 22 +- .../v0.8/ccip/test/e2e/MultiRampsEnd2End.sol | 12 +- .../v0.8/ccip/test/helpers/MessageHasher.sol | 9 +- .../src/v0.8/ccip/test/offRamp/OffRamp.t.sol | 152 ++++++------ .../v0.8/ccip/test/offRamp/OffRampSetup.t.sol | 19 +- .../message_hasher/message_hasher.go | 2 +- .../ccip/generated/offramp/offramp.go | 2 +- .../ccip/generated/onramp/onramp.go | 2 +- ...rapper-dependency-versions-do-not-edit.txt | 6 +- 12 files changed, 250 insertions(+), 221 deletions(-) diff --git a/contracts/gas-snapshots/ccip.gas-snapshot b/contracts/gas-snapshots/ccip.gas-snapshot index 98071286f6..ad717fb01a 100644 --- a/contracts/gas-snapshots/ccip.gas-snapshot +++ b/contracts/gas-snapshots/ccip.gas-snapshot @@ -565,22 +565,22 @@ MultiOCR3Base_transmit:test_UnauthorizedSigner_Revert() (gas: 61275) MultiOCR3Base_transmit:test_UnconfiguredPlugin_Revert() (gas: 39933) MultiOCR3Base_transmit:test_ZeroSignatures_Revert() (gas: 33049) MultiOnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 233745) -MultiRampsE2E:test_E2E_3MessagesMMultiOffRampSuccess_gas() (gas: 1542394) +MultiRampsE2E:test_E2E_3MessagesMMultiOffRampSuccess_gas() (gas: 1538496) NonceManager_NonceIncrementation:test_getIncrementedOutboundNonce_Success() (gas: 37934) NonceManager_NonceIncrementation:test_incrementInboundNonce_Skip() (gas: 23721) NonceManager_NonceIncrementation:test_incrementInboundNonce_Success() (gas: 38805) NonceManager_NonceIncrementation:test_incrementNoncesInboundAndOutbound_Success() (gas: 71934) -NonceManager_OffRampUpgrade:test_NoPrevOffRampForChain_Success() (gas: 263674) -NonceManager_OffRampUpgrade:test_UpgradedNonceNewSenderStartsAtZero_Success() (gas: 267840) -NonceManager_OffRampUpgrade:test_UpgradedNonceStartsAtV1Nonce_Success() (gas: 333345) -NonceManager_OffRampUpgrade:test_UpgradedOffRampNonceSkipsIfMsgInFlight_Success() (gas: 303817) -NonceManager_OffRampUpgrade:test_UpgradedSenderNoncesReadsPreviousRampTransitive_Success() (gas: 249140) -NonceManager_OffRampUpgrade:test_UpgradedSenderNoncesReadsPreviousRamp_Success() (gas: 237047) -NonceManager_OffRampUpgrade:test_Upgraded_Success() (gas: 155247) -NonceManager_OnRampUpgrade:test_UpgradeNonceNewSenderStartsAtZero_Success() (gas: 169478) -NonceManager_OnRampUpgrade:test_UpgradeNonceStartsAtV1Nonce_Success() (gas: 222172) +NonceManager_OffRampUpgrade:test_NoPrevOffRampForChain_Success() (gas: 262150) +NonceManager_OffRampUpgrade:test_UpgradedNonceNewSenderStartsAtZero_Success() (gas: 265827) +NonceManager_OffRampUpgrade:test_UpgradedNonceStartsAtV1Nonce_Success() (gas: 329806) +NonceManager_OffRampUpgrade:test_UpgradedOffRampNonceSkipsIfMsgInFlight_Success() (gas: 300776) +NonceManager_OffRampUpgrade:test_UpgradedSenderNoncesReadsPreviousRampTransitive_Success() (gas: 249120) +NonceManager_OffRampUpgrade:test_UpgradedSenderNoncesReadsPreviousRamp_Success() (gas: 237027) +NonceManager_OffRampUpgrade:test_Upgraded_Success() (gas: 153739) +NonceManager_OnRampUpgrade:test_UpgradeNonceNewSenderStartsAtZero_Success() (gas: 168984) +NonceManager_OnRampUpgrade:test_UpgradeNonceStartsAtV1Nonce_Success() (gas: 221183) NonceManager_OnRampUpgrade:test_UpgradeSenderNoncesReadsPreviousRamp_Success() (gas: 126858) -NonceManager_OnRampUpgrade:test_Upgrade_Success() (gas: 108239) +NonceManager_OnRampUpgrade:test_Upgrade_Success() (gas: 107745) NonceManager_applyPreviousRampsUpdates:test_MultipleRampsUpdates() (gas: 123201) NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySetOffRamp_Revert() (gas: 43073) NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySetOnRampAndOffRamp_Revert() (gas: 64402) @@ -613,7 +613,7 @@ OCR2Base_transmit:test_Transmit2SignersSuccess_gas() (gas: 51689) OCR2Base_transmit:test_UnAuthorizedTransmitter_Revert() (gas: 23511) OCR2Base_transmit:test_UnauthorizedSigner_Revert() (gas: 39707) OCR2Base_transmit:test_WrongNumberOfSignatures_Revert() (gas: 20584) -OffRamp_afterOC3ConfigSet:test_afterOCR3ConfigSet_SignatureVerificationDisabled_Revert() (gas: 5711320) +OffRamp_afterOC3ConfigSet:test_afterOCR3ConfigSet_SignatureVerificationDisabled_Revert() (gas: 5705901) OffRamp_applySourceChainConfigUpdates:test_AddMultipleChains_Success() (gas: 469413) OffRamp_applySourceChainConfigUpdates:test_AddNewChain_Success() (gas: 99659) OffRamp_applySourceChainConfigUpdates:test_ApplyZeroUpdates_Success() (gas: 12613) @@ -623,22 +623,22 @@ OffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChain_Success() (gas: OffRamp_applySourceChainConfigUpdates:test_RouterAddress_Revert() (gas: 13463) OffRamp_applySourceChainConfigUpdates:test_ZeroOnRampAddress_Revert() (gas: 72746) OffRamp_applySourceChainConfigUpdates:test_ZeroSourceChainSelector_Revert() (gas: 15519) -OffRamp_batchExecute:test_MultipleReportsDifferentChainsSkipCursedChain_Success() (gas: 180443) -OffRamp_batchExecute:test_MultipleReportsDifferentChains_Success() (gas: 340118) -OffRamp_batchExecute:test_MultipleReportsSameChain_Success() (gas: 283384) -OffRamp_batchExecute:test_MultipleReportsSkipDuplicate_Success() (gas: 171325) -OffRamp_batchExecute:test_OutOfBoundsGasLimitsAccess_Revert() (gas: 191523) -OffRamp_batchExecute:test_SingleReport_Success() (gas: 158623) -OffRamp_batchExecute:test_Unhealthy_Success() (gas: 581440) +OffRamp_batchExecute:test_MultipleReportsDifferentChainsSkipCursedChain_Success() (gas: 177990) +OffRamp_batchExecute:test_MultipleReportsDifferentChains_Success() (gas: 335637) +OffRamp_batchExecute:test_MultipleReportsSameChain_Success() (gas: 278903) +OffRamp_batchExecute:test_MultipleReportsSkipDuplicate_Success() (gas: 169319) +OffRamp_batchExecute:test_OutOfBoundsGasLimitsAccess_Revert() (gas: 189032) +OffRamp_batchExecute:test_SingleReport_Success() (gas: 157143) +OffRamp_batchExecute:test_Unhealthy_Success() (gas: 578427) OffRamp_batchExecute:test_ZeroReports_Revert() (gas: 10621) -OffRamp_ccipReceive:test_Reverts() (gas: 15884) +OffRamp_ccipReceive:test_Reverts() (gas: 15406) OffRamp_commit:test_CommitOnRampMismatch_Revert() (gas: 92593) OffRamp_commit:test_FailedRMNVerification_Reverts() (gas: 63787) OffRamp_commit:test_InvalidIntervalMinLargerThanMax_Revert() (gas: 67826) OffRamp_commit:test_InvalidInterval_Revert() (gas: 63993) OffRamp_commit:test_InvalidRootRevert() (gas: 63066) -OffRamp_commit:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6315259) -OffRamp_commit:test_NoConfig_Revert() (gas: 5898957) +OffRamp_commit:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6309840) +OffRamp_commit:test_NoConfig_Revert() (gas: 5893538) OffRamp_commit:test_OnlyGasPriceUpdates_Success() (gas: 112835) OffRamp_commit:test_OnlyPriceUpdateStaleReport_Revert() (gas: 121022) OffRamp_commit:test_OnlyTokenPriceUpdates_Success() (gas: 112856) @@ -652,79 +652,79 @@ OffRamp_commit:test_UnauthorizedTransmitter_Revert() (gas: 125104) OffRamp_commit:test_Unhealthy_Revert() (gas: 58334) OffRamp_commit:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 206207) OffRamp_commit:test_ZeroEpochAndRound_Revert() (gas: 51522) -OffRamp_constructor:test_Constructor_Success() (gas: 5900076) -OffRamp_constructor:test_SourceChainSelector_Revert() (gas: 135592) -OffRamp_constructor:test_ZeroChainSelector_Revert() (gas: 103026) -OffRamp_constructor:test_ZeroNonceManager_Revert() (gas: 100920) -OffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 161117) -OffRamp_constructor:test_ZeroRMNRemote_Revert() (gas: 100840) -OffRamp_constructor:test_ZeroTokenAdminRegistry_Revert() (gas: 100878) -OffRamp_execute:test_IncorrectArrayType_Revert() (gas: 17643) -OffRamp_execute:test_LargeBatch_Success() (gas: 3479707) -OffRamp_execute:test_MultipleReportsWithPartialValidationFailures_Success() (gas: 377669) -OffRamp_execute:test_MultipleReports_Success() (gas: 305677) -OffRamp_execute:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6725435) -OffRamp_execute:test_NoConfig_Revert() (gas: 5949968) -OffRamp_execute:test_NonArray_Revert() (gas: 28081) -OffRamp_execute:test_SingleReport_Success() (gas: 177908) -OffRamp_execute:test_UnauthorizedTransmitter_Revert() (gas: 149413) -OffRamp_execute:test_WrongConfigWithSigners_Revert() (gas: 6728184) -OffRamp_execute:test_ZeroReports_Revert() (gas: 17365) -OffRamp_executeSingleMessage:test_MessageSender_Revert() (gas: 19042) -OffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 249246) -OffRamp_executeSingleMessage:test_NonContract_Success() (gas: 21290) -OffRamp_executeSingleMessage:test_TokenHandlingError_Revert() (gas: 210286) -OffRamp_executeSingleMessage:test_ZeroGasDONExecution_Revert() (gas: 49816) -OffRamp_executeSingleMessage:test_executeSingleMessage_NoTokens_Success() (gas: 49259) -OffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidationNoRouterCall_Revert() (gas: 219024) -OffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidation_Revert() (gas: 85782) -OffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens_Success() (gas: 281397) -OffRamp_executeSingleMessage:test_executeSingleMessage_WithVInterception_Success() (gas: 92210) -OffRamp_executeSingleReport:test_DisabledSourceChain_Revert() (gas: 28775) +OffRamp_constructor:test_Constructor_Success() (gas: 5894658) +OffRamp_constructor:test_SourceChainSelector_Revert() (gas: 135582) +OffRamp_constructor:test_ZeroChainSelector_Revert() (gas: 103017) +OffRamp_constructor:test_ZeroNonceManager_Revert() (gas: 100911) +OffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 161108) +OffRamp_constructor:test_ZeroRMNRemote_Revert() (gas: 100831) +OffRamp_constructor:test_ZeroTokenAdminRegistry_Revert() (gas: 100869) +OffRamp_execute:test_IncorrectArrayType_Revert() (gas: 17639) +OffRamp_execute:test_LargeBatch_Success() (gas: 3426335) +OffRamp_execute:test_MultipleReportsWithPartialValidationFailures_Success() (gas: 372966) +OffRamp_execute:test_MultipleReports_Success() (gas: 300979) +OffRamp_execute:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6718990) +OffRamp_execute:test_NoConfig_Revert() (gas: 5943523) +OffRamp_execute:test_NonArray_Revert() (gas: 27562) +OffRamp_execute:test_SingleReport_Success() (gas: 176354) +OffRamp_execute:test_UnauthorizedTransmitter_Revert() (gas: 148372) +OffRamp_execute:test_WrongConfigWithSigners_Revert() (gas: 6721739) +OffRamp_execute:test_ZeroReports_Revert() (gas: 17361) +OffRamp_executeSingleMessage:test_MessageSender_Revert() (gas: 18533) +OffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 248725) +OffRamp_executeSingleMessage:test_NonContract_Success() (gas: 20781) +OffRamp_executeSingleMessage:test_TokenHandlingError_Revert() (gas: 209765) +OffRamp_executeSingleMessage:test_ZeroGasDONExecution_Revert() (gas: 49306) +OffRamp_executeSingleMessage:test_executeSingleMessage_NoTokens_Success() (gas: 48750) +OffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidationNoRouterCall_Revert() (gas: 218004) +OffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidation_Revert() (gas: 85272) +OffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens_Success() (gas: 280350) +OffRamp_executeSingleMessage:test_executeSingleMessage_WithVInterception_Success() (gas: 91700) +OffRamp_executeSingleReport:test_DisabledSourceChain_Revert() (gas: 28261) OffRamp_executeSingleReport:test_EmptyReport_Revert() (gas: 22063) -OffRamp_executeSingleReport:test_InvalidSourcePoolAddress_Success() (gas: 504821) -OffRamp_executeSingleReport:test_ManualExecutionNotYetEnabled_Revert() (gas: 49409) -OffRamp_executeSingleReport:test_MismatchingDestChainSelector_Revert() (gas: 34474) -OffRamp_executeSingleReport:test_NonExistingSourceChain_Revert() (gas: 29022) -OffRamp_executeSingleReport:test_ReceiverError_Success() (gas: 190142) -OffRamp_executeSingleReport:test_RetryFailedMessageWithoutManualExecution_Revert() (gas: 201092) -OffRamp_executeSingleReport:test_RootNotCommitted_Revert() (gas: 41778) -OffRamp_executeSingleReport:test_RouterYULCall_Revert() (gas: 415283) -OffRamp_executeSingleReport:test_SingleMessageNoTokensOtherChain_Success() (gas: 251849) -OffRamp_executeSingleReport:test_SingleMessageNoTokensUnordered_Success() (gas: 197205) -OffRamp_executeSingleReport:test_SingleMessageNoTokens_Success() (gas: 216715) -OffRamp_executeSingleReport:test_SingleMessageToNonCCIPReceiver_Success() (gas: 251588) -OffRamp_executeSingleReport:test_SingleMessagesNoTokensSuccess_gas() (gas: 143177) -OffRamp_executeSingleReport:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 427792) -OffRamp_executeSingleReport:test_SkippedIncorrectNonce_Success() (gas: 59840) -OffRamp_executeSingleReport:test_TokenDataMismatch_Revert() (gas: 74905) -OffRamp_executeSingleReport:test_TwoMessagesWithTokensAndGE_Success() (gas: 606911) -OffRamp_executeSingleReport:test_TwoMessagesWithTokensSuccess_gas() (gas: 550321) -OffRamp_executeSingleReport:test_UnexpectedTokenData_Revert() (gas: 34232) -OffRamp_executeSingleReport:test_UnhealthySingleChainCurse_Revert() (gas: 577092) -OffRamp_executeSingleReport:test_Unhealthy_Success() (gas: 577106) -OffRamp_executeSingleReport:test_WithCurseOnAnotherSourceChain_Success() (gas: 479102) -OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessageUnordered_Success() (gas: 138486) -OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessage_Success() (gas: 167678) +OffRamp_executeSingleReport:test_InvalidSourcePoolAddress_Success() (gas: 501125) +OffRamp_executeSingleReport:test_ManualExecutionNotYetEnabled_Revert() (gas: 48373) +OffRamp_executeSingleReport:test_MismatchingDestChainSelector_Revert() (gas: 33960) +OffRamp_executeSingleReport:test_NonExistingSourceChain_Revert() (gas: 28437) +OffRamp_executeSingleReport:test_ReceiverError_Success() (gas: 188072) +OffRamp_executeSingleReport:test_RetryFailedMessageWithoutManualExecution_Revert() (gas: 198507) +OffRamp_executeSingleReport:test_RootNotCommitted_Revert() (gas: 40742) +OffRamp_executeSingleReport:test_RouterYULCall_Revert() (gas: 413224) +OffRamp_executeSingleReport:test_SingleMessageNoTokensOtherChain_Success() (gas: 249758) +OffRamp_executeSingleReport:test_SingleMessageNoTokensUnordered_Success() (gas: 193572) +OffRamp_executeSingleReport:test_SingleMessageNoTokens_Success() (gas: 213606) +OffRamp_executeSingleReport:test_SingleMessageToNonCCIPReceiver_Success() (gas: 249529) +OffRamp_executeSingleReport:test_SingleMessagesNoTokensSuccess_gas() (gas: 142142) +OffRamp_executeSingleReport:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 424632) +OffRamp_executeSingleReport:test_SkippedIncorrectNonce_Success() (gas: 58294) +OffRamp_executeSingleReport:test_TokenDataMismatch_Revert() (gas: 73869) +OffRamp_executeSingleReport:test_TwoMessagesWithTokensAndGE_Success() (gas: 603198) +OffRamp_executeSingleReport:test_TwoMessagesWithTokensSuccess_gas() (gas: 548187) +OffRamp_executeSingleReport:test_UnexpectedTokenData_Revert() (gas: 33718) +OffRamp_executeSingleReport:test_UnhealthySingleChainCurse_Revert() (gas: 573911) +OffRamp_executeSingleReport:test_Unhealthy_Success() (gas: 573925) +OffRamp_executeSingleReport:test_WithCurseOnAnotherSourceChain_Success() (gas: 477004) +OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessageUnordered_Success() (gas: 135902) +OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessage_Success() (gas: 165607) OffRamp_getExecutionState:test_FillExecutionState_Success() (gas: 3936242) OffRamp_getExecutionState:test_GetDifferentChainExecutionState_Success() (gas: 120870) OffRamp_getExecutionState:test_GetExecutionState_Success() (gas: 89684) -OffRamp_manuallyExecute:test_ManualExecGasLimitMismatchSingleReport_Revert() (gas: 82048) -OffRamp_manuallyExecute:test_manuallyExecute_DestinationGasAmountCountMismatch_Revert() (gas: 80838) -OffRamp_manuallyExecute:test_manuallyExecute_DoesNotRevertIfUntouched_Success() (gas: 175234) -OffRamp_manuallyExecute:test_manuallyExecute_FailedTx_Revert() (gas: 216194) -OffRamp_manuallyExecute:test_manuallyExecute_ForkedChain_Revert() (gas: 27599) -OffRamp_manuallyExecute:test_manuallyExecute_GasLimitMismatchMultipleReports_Revert() (gas: 166251) -OffRamp_manuallyExecute:test_manuallyExecute_InvalidReceiverExecutionGasLimit_Revert() (gas: 28137) -OffRamp_manuallyExecute:test_manuallyExecute_InvalidTokenGasOverride_Revert() (gas: 59861) -OffRamp_manuallyExecute:test_manuallyExecute_LowGasLimit_Success() (gas: 501650) -OffRamp_manuallyExecute:test_manuallyExecute_MultipleReportsWithSingleCursedLane_Revert() (gas: 322849) -OffRamp_manuallyExecute:test_manuallyExecute_ReentrancyFails_Success() (gas: 2354253) -OffRamp_manuallyExecute:test_manuallyExecute_SourceChainSelectorMismatch_Revert() (gas: 167081) -OffRamp_manuallyExecute:test_manuallyExecute_Success() (gas: 229749) -OffRamp_manuallyExecute:test_manuallyExecute_WithGasOverride_Success() (gas: 230289) -OffRamp_manuallyExecute:test_manuallyExecute_WithMultiReportGasOverride_Success() (gas: 794511) -OffRamp_manuallyExecute:test_manuallyExecute_WithPartialMessages_Success() (gas: 353603) +OffRamp_manuallyExecute:test_ManualExecGasLimitMismatchSingleReport_Revert() (gas: 81016) +OffRamp_manuallyExecute:test_manuallyExecute_DestinationGasAmountCountMismatch_Revert() (gas: 80316) +OffRamp_manuallyExecute:test_manuallyExecute_DoesNotRevertIfUntouched_Success() (gas: 173164) +OffRamp_manuallyExecute:test_manuallyExecute_FailedTx_Revert() (gas: 214120) +OffRamp_manuallyExecute:test_manuallyExecute_ForkedChain_Revert() (gas: 27085) +OffRamp_manuallyExecute:test_manuallyExecute_GasLimitMismatchMultipleReports_Revert() (gas: 164696) +OffRamp_manuallyExecute:test_manuallyExecute_InvalidReceiverExecutionGasLimit_Revert() (gas: 27622) +OffRamp_manuallyExecute:test_manuallyExecute_InvalidTokenGasOverride_Revert() (gas: 59339) +OffRamp_manuallyExecute:test_manuallyExecute_LowGasLimit_Success() (gas: 498548) +OffRamp_manuallyExecute:test_manuallyExecute_MultipleReportsWithSingleCursedLane_Revert() (gas: 316061) +OffRamp_manuallyExecute:test_manuallyExecute_ReentrancyFails_Success() (gas: 2351652) +OffRamp_manuallyExecute:test_manuallyExecute_SourceChainSelectorMismatch_Revert() (gas: 165525) +OffRamp_manuallyExecute:test_manuallyExecute_Success() (gas: 227165) +OffRamp_manuallyExecute:test_manuallyExecute_WithGasOverride_Success() (gas: 227705) +OffRamp_manuallyExecute:test_manuallyExecute_WithMultiReportGasOverride_Success() (gas: 781361) +OffRamp_manuallyExecute:test_manuallyExecute_WithPartialMessages_Success() (gas: 347342) OffRamp_releaseOrMintSingleToken:test__releaseOrMintSingleToken_NotACompatiblePool_Revert() (gas: 40854) OffRamp_releaseOrMintSingleToken:test__releaseOrMintSingleToken_Success() (gas: 105958) OffRamp_releaseOrMintSingleToken:test__releaseOrMintSingleToken_TokenHandlingError_transfer_Revert() (gas: 87217) @@ -744,10 +744,10 @@ OffRamp_setDynamicConfig:test_FeeQuoterZeroAddress_Revert() (gas: 11246) OffRamp_setDynamicConfig:test_NonOwner_Revert() (gas: 13861) OffRamp_setDynamicConfig:test_SetDynamicConfigWithInterceptor_Success() (gas: 46354) OffRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 24396) -OffRamp_trialExecute:test_RateLimitError_Success() (gas: 227084) -OffRamp_trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 235706) -OffRamp_trialExecute:test_TokenPoolIsNotAContract_Success() (gas: 315277) -OffRamp_trialExecute:test_trialExecute_Success() (gas: 285609) +OffRamp_trialExecute:test_RateLimitError_Success() (gas: 226578) +OffRamp_trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 235200) +OffRamp_trialExecute:test_TokenPoolIsNotAContract_Success() (gas: 313735) +OffRamp_trialExecute:test_trialExecute_Success() (gas: 285095) OnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 390842) OnRamp_applyAllowListUpdates:test_applyAllowListUpdates_InvalidAllowListRequestDisabledAllowListWithAdds() (gas: 18030) OnRamp_applyAllowListUpdates:test_applyAllowListUpdates_Revert() (gas: 67429) @@ -758,14 +758,14 @@ OnRamp_constructor:test_Constructor_InvalidConfigChainSelectorEqZero_Revert() (g OnRamp_constructor:test_Constructor_InvalidConfigNonceManagerEqAddressZero_Revert() (gas: 92998) OnRamp_constructor:test_Constructor_InvalidConfigRMNProxyEqAddressZero_Revert() (gas: 98031) OnRamp_constructor:test_Constructor_InvalidConfigTokenAdminRegistryEqAddressZero_Revert() (gas: 93054) -OnRamp_constructor:test_Constructor_Success() (gas: 2759290) -OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() (gas: 115668) -OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2_Success() (gas: 146491) -OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessCustomExtraArgs() (gas: 146066) -OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessEmptyExtraArgs() (gas: 144306) -OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessLegacyExtraArgs() (gas: 146285) -OnRamp_forwardFromRouter:test_ForwardFromRouter_Success() (gas: 145664) -OnRamp_forwardFromRouter:test_ForwardFromRouter_Success_ConfigurableSourceRouter() (gas: 146249) +OnRamp_constructor:test_Constructor_Success() (gas: 2756090) +OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() (gas: 115174) +OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2_Success() (gas: 145997) +OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessCustomExtraArgs() (gas: 145573) +OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessEmptyExtraArgs() (gas: 143812) +OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessLegacyExtraArgs() (gas: 145791) +OnRamp_forwardFromRouter:test_ForwardFromRouter_Success() (gas: 145170) +OnRamp_forwardFromRouter:test_ForwardFromRouter_Success_ConfigurableSourceRouter() (gas: 146002) OnRamp_forwardFromRouter:test_InvalidExtraArgsTag_Revert() (gas: 38615) OnRamp_forwardFromRouter:test_MessageInterceptionError_Revert() (gas: 143071) OnRamp_forwardFromRouter:test_MesssageFeeTooHigh_Revert() (gas: 36739) @@ -773,15 +773,15 @@ OnRamp_forwardFromRouter:test_MultiCannotSendZeroTokens_Revert() (gas: 36473) OnRamp_forwardFromRouter:test_OriginalSender_Revert() (gas: 18291) OnRamp_forwardFromRouter:test_Paused_Revert() (gas: 38454) OnRamp_forwardFromRouter:test_Permissions_Revert() (gas: 23663) -OnRamp_forwardFromRouter:test_ShouldIncrementNonceOnlyOnOrdered_Success() (gas: 187735) -OnRamp_forwardFromRouter:test_ShouldIncrementSeqNumAndNonce_Success() (gas: 214120) -OnRamp_forwardFromRouter:test_ShouldStoreLinkFees() (gas: 125405) -OnRamp_forwardFromRouter:test_ShouldStoreNonLinkFees() (gas: 142036) -OnRamp_forwardFromRouter:test_SourceTokenDataTooLarge_Revert() (gas: 3623626) +OnRamp_forwardFromRouter:test_ShouldIncrementNonceOnlyOnOrdered_Success() (gas: 186250) +OnRamp_forwardFromRouter:test_ShouldIncrementSeqNumAndNonce_Success() (gas: 212635) +OnRamp_forwardFromRouter:test_ShouldStoreLinkFees() (gas: 125158) +OnRamp_forwardFromRouter:test_ShouldStoreNonLinkFees() (gas: 141789) +OnRamp_forwardFromRouter:test_SourceTokenDataTooLarge_Revert() (gas: 3622885) OnRamp_forwardFromRouter:test_UnAllowedOriginalSender_Revert() (gas: 24010) OnRamp_forwardFromRouter:test_UnsupportedToken_Revert() (gas: 75790) OnRamp_forwardFromRouter:test_forwardFromRouter_UnsupportedToken_Revert() (gas: 38523) -OnRamp_forwardFromRouter:test_forwardFromRouter_WithInterception_Success() (gas: 282956) +OnRamp_forwardFromRouter:test_forwardFromRouter_WithInterception_Success() (gas: 282461) OnRamp_getFee:test_EmptyMessage_Success() (gas: 98760) OnRamp_getFee:test_EnforceOutOfOrder_Revert() (gas: 64779) OnRamp_getFee:test_GetFeeOfZeroForTokenMessage_Success() (gas: 86359) diff --git a/contracts/src/v0.8/ccip/libraries/Internal.sol b/contracts/src/v0.8/ccip/libraries/Internal.sol index 5d91219e04..e704113e10 100644 --- a/contracts/src/v0.8/ccip/libraries/Internal.sol +++ b/contracts/src/v0.8/ccip/libraries/Internal.sol @@ -187,30 +187,25 @@ library Internal { /// OnRamp hash(EVM2AnyMessage) != Any2EVMRampMessage.messageId /// OnRamp hash(EVM2AnyMessage) != OffRamp hash(Any2EVMRampMessage) /// @param original OffRamp message to hash - /// @param onRamp OnRamp to hash the message with - used to compute the metadataHash + /// @param metadataHash Hash preimage to ensure global uniqueness /// @return hashedMessage hashed message as a keccak256 - function _hash(Any2EVMRampMessage memory original, bytes memory onRamp) internal pure returns (bytes32) { + function _hash(Any2EVMRampMessage memory original, bytes32 metadataHash) internal pure returns (bytes32) { // Fixed-size message fields are included in nested hash to reduce stack pressure. // This hashing scheme is also used by RMN. If changing it, please notify the RMN maintainers. return keccak256( abi.encode( MerkleMultiProof.LEAF_DOMAIN_SEPARATOR, - // Implicit metadata hash - keccak256( - abi.encode( - ANY_2_EVM_MESSAGE_HASH, original.header.sourceChainSelector, original.header.destChainSelector, onRamp - ) - ), + metadataHash, keccak256( abi.encode( original.header.messageId, - original.sender, original.receiver, original.header.sequenceNumber, original.gasLimit, original.header.nonce ) ), + keccak256(original.sender), keccak256(original.data), keccak256(abi.encode(original.tokenAmounts)) ) @@ -227,13 +222,13 @@ library Internal { keccak256( abi.encode( original.sender, - original.receiver, original.header.sequenceNumber, original.header.nonce, original.feeToken, original.feeTokenAmount ) ), + keccak256(original.receiver), keccak256(original.data), keccak256(abi.encode(original.tokenAmounts)), keccak256(original.extraArgs) diff --git a/contracts/src/v0.8/ccip/offRamp/OffRamp.sol b/contracts/src/v0.8/ccip/offRamp/OffRamp.sol index 39a781393c..5a15910fc9 100644 --- a/contracts/src/v0.8/ccip/offRamp/OffRamp.sol +++ b/contracts/src/v0.8/ccip/offRamp/OffRamp.sol @@ -393,7 +393,17 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { // over the same data, which increases gas cost. // Hashing all of the message fields ensures that the message being executed is correct and not tampered with. // Including the known OnRamp ensures that the message originates from the correct on ramp version - hashedLeaves[i] = Internal._hash(message, onRamp); + hashedLeaves[i] = Internal._hash( + message, + keccak256( + abi.encode( + Internal.ANY_2_EVM_MESSAGE_HASH, + message.header.sourceChainSelector, + message.header.destChainSelector, + keccak256(onRamp) + ) + ) + ); } // SECURITY CRITICAL CHECK diff --git a/contracts/src/v0.8/ccip/test/NonceManager.t.sol b/contracts/src/v0.8/ccip/test/NonceManager.t.sol index 2bf7d8ea4d..f25bdaa5d4 100644 --- a/contracts/src/v0.8/ccip/test/NonceManager.t.sol +++ b/contracts/src/v0.8/ccip/test/NonceManager.t.sol @@ -397,7 +397,7 @@ contract NonceManager_OffRampUpgrade is OffRampSetup { SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber, messages[0].header.messageId, - Internal._hash(messages[0], ON_RAMP_ADDRESS_1), + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -429,7 +429,7 @@ contract NonceManager_OffRampUpgrade is OffRampSetup { SOURCE_CHAIN_SELECTOR_3, messagesChain3[0].header.sequenceNumber, messagesChain3[0].header.messageId, - Internal._hash(messagesChain3[0], ON_RAMP_ADDRESS_3), + _hashMessage(messagesChain3[0], ON_RAMP_ADDRESS_3), Internal.MessageExecutionState.SUCCESS, "" ); @@ -499,7 +499,7 @@ contract NonceManager_OffRampUpgrade is OffRampSetup { _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); messagesMultiRamp[0].header.nonce++; - messagesMultiRamp[0].header.messageId = Internal._hash(messagesMultiRamp[0], ON_RAMP_ADDRESS_1); + messagesMultiRamp[0].header.messageId = _hashMessage(messagesMultiRamp[0], ON_RAMP_ADDRESS_1); vm.recordLogs(); @@ -511,7 +511,7 @@ contract NonceManager_OffRampUpgrade is OffRampSetup { SOURCE_CHAIN_SELECTOR_1, messagesMultiRamp[0].header.sequenceNumber, messagesMultiRamp[0].header.messageId, - Internal._hash(messagesMultiRamp[0], ON_RAMP_ADDRESS_1), + _hashMessage(messagesMultiRamp[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -522,7 +522,7 @@ contract NonceManager_OffRampUpgrade is OffRampSetup { messagesMultiRamp[0].header.nonce++; messagesMultiRamp[0].header.sequenceNumber++; - messagesMultiRamp[0].header.messageId = Internal._hash(messagesMultiRamp[0], ON_RAMP_ADDRESS_1); + messagesMultiRamp[0].header.messageId = _hashMessage(messagesMultiRamp[0], ON_RAMP_ADDRESS_1); vm.recordLogs(); s_offRamp.executeSingleReport( @@ -532,7 +532,7 @@ contract NonceManager_OffRampUpgrade is OffRampSetup { SOURCE_CHAIN_SELECTOR_1, messagesMultiRamp[0].header.sequenceNumber, messagesMultiRamp[0].header.messageId, - Internal._hash(messagesMultiRamp[0], ON_RAMP_ADDRESS_1), + _hashMessage(messagesMultiRamp[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -555,7 +555,7 @@ contract NonceManager_OffRampUpgrade is OffRampSetup { bytes memory newSender = abi.encode(address(1234567)); messagesMultiRamp[0].sender = newSender; - messagesMultiRamp[0].header.messageId = Internal._hash(messagesMultiRamp[0], ON_RAMP_ADDRESS_1); + messagesMultiRamp[0].header.messageId = _hashMessage(messagesMultiRamp[0], ON_RAMP_ADDRESS_1); // new sender nonce in new offramp should go from 0 -> 1 assertEq(s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, newSender), 0); @@ -567,7 +567,7 @@ contract NonceManager_OffRampUpgrade is OffRampSetup { SOURCE_CHAIN_SELECTOR_1, messagesMultiRamp[0].header.sequenceNumber, messagesMultiRamp[0].header.messageId, - Internal._hash(messagesMultiRamp[0], ON_RAMP_ADDRESS_1), + _hashMessage(messagesMultiRamp[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -581,7 +581,7 @@ contract NonceManager_OffRampUpgrade is OffRampSetup { address newSender = address(1234567); messages[0].sender = abi.encode(newSender); messages[0].header.nonce = 2; - messages[0].header.messageId = Internal._hash(messages[0], ON_RAMP_ADDRESS_1); + messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); uint64 startNonce = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender); @@ -611,7 +611,7 @@ contract NonceManager_OffRampUpgrade is OffRampSetup { ); messages[0].header.nonce = 2; - messages[0].header.messageId = Internal._hash(messages[0], ON_RAMP_ADDRESS_1); + messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); // new offramp is able to execute vm.recordLogs(); @@ -622,7 +622,7 @@ contract NonceManager_OffRampUpgrade is OffRampSetup { SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber, messages[0].header.messageId, - Internal._hash(messages[0], ON_RAMP_ADDRESS_1), + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); diff --git a/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.sol b/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.sol index 0333cbb739..8a70bea6c9 100644 --- a/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.sol +++ b/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.sol @@ -141,10 +141,10 @@ contract MultiRampsE2E is OnRampSetup, OffRampSetup { // Scoped to commit to reduce stack pressure { bytes32[] memory hashedMessages1 = new bytes32[](2); - hashedMessages1[0] = messages1[0]._hash(abi.encode(address(s_onRamp))); - hashedMessages1[1] = messages1[1]._hash(abi.encode(address(s_onRamp))); + hashedMessages1[0] = _hashMessage(messages1[0], abi.encode(address(s_onRamp))); + hashedMessages1[1] = _hashMessage(messages1[1], abi.encode(address(s_onRamp))); bytes32[] memory hashedMessages2 = new bytes32[](1); - hashedMessages2[0] = messages2[0]._hash(abi.encode(address(s_onRamp2))); + hashedMessages2[0] = _hashMessage(messages2[0], abi.encode(address(s_onRamp2))); merkleRoots[0] = MerkleHelper.getMerkleRoot(hashedMessages1); merkleRoots[1] = MerkleHelper.getMerkleRoot(hashedMessages2); @@ -211,7 +211,7 @@ contract MultiRampsE2E is OnRampSetup, OffRampSetup { SOURCE_CHAIN_SELECTOR, messages1[0].header.sequenceNumber, messages1[0].header.messageId, - messages1[0]._hash(abi.encode(address(s_onRamp))), + _hashMessage(messages1[0], abi.encode(address(s_onRamp))), Internal.MessageExecutionState.SUCCESS, "" ); @@ -220,7 +220,7 @@ contract MultiRampsE2E is OnRampSetup, OffRampSetup { SOURCE_CHAIN_SELECTOR, messages1[1].header.sequenceNumber, messages1[1].header.messageId, - messages1[1]._hash(abi.encode(address(s_onRamp))), + _hashMessage(messages1[1], abi.encode(address(s_onRamp))), Internal.MessageExecutionState.SUCCESS, "" ); @@ -229,7 +229,7 @@ contract MultiRampsE2E is OnRampSetup, OffRampSetup { SOURCE_CHAIN_SELECTOR + 1, messages2[0].header.sequenceNumber, messages2[0].header.messageId, - messages2[0]._hash(abi.encode(address(s_onRamp2))), + _hashMessage(messages2[0], abi.encode(address(s_onRamp2))), Internal.MessageExecutionState.SUCCESS, "" ); diff --git a/contracts/src/v0.8/ccip/test/helpers/MessageHasher.sol b/contracts/src/v0.8/ccip/test/helpers/MessageHasher.sol index d56cf8949a..f27e48b137 100644 --- a/contracts/src/v0.8/ccip/test/helpers/MessageHasher.sol +++ b/contracts/src/v0.8/ccip/test/helpers/MessageHasher.sol @@ -9,7 +9,14 @@ import {Internal} from "../../libraries/Internal.sol"; /// @dev This is only deployed in tests and is not part of the production contracts. contract MessageHasher { function hash(Internal.Any2EVMRampMessage memory message, bytes memory onRamp) public pure returns (bytes32) { - return Internal._hash(message, onRamp); + return Internal._hash( + message, + keccak256( + abi.encode( + Internal.ANY_2_EVM_MESSAGE_HASH, message.header.sourceChainSelector, message.header.destChainSelector, onRamp + ) + ) + ); } function encodeTokenAmountsHashPreimage( diff --git a/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol index febd577455..079e0e3c41 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol @@ -347,14 +347,14 @@ contract OffRamp_executeSingleReport is OffRampSetup { messages[0].header.sourceChainSelector, messages[0].header.sequenceNumber, messages[0].header.messageId, - Internal._hash(messages[0], ON_RAMP_ADDRESS_1), + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); messages[0].header.nonce++; messages[0].header.sequenceNumber++; - messages[0].header.messageId = Internal._hash(messages[0], ON_RAMP_ADDRESS_1); + messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); uint64 nonceBefore = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender); vm.recordLogs(); @@ -365,7 +365,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { messages[0].header.sourceChainSelector, messages[0].header.sequenceNumber, messages[0].header.messageId, - Internal._hash(messages[0], ON_RAMP_ADDRESS_1), + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -376,7 +376,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); messages[0].header.nonce = 0; - messages[0].header.messageId = Internal._hash(messages[0], ON_RAMP_ADDRESS_1); + messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); // Nonce never increments on unordered messages. uint64 nonceBefore = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender); @@ -388,7 +388,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { messages[0].header.sourceChainSelector, messages[0].header.sequenceNumber, messages[0].header.messageId, - Internal._hash(messages[0], ON_RAMP_ADDRESS_1), + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -400,7 +400,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { ); messages[0].header.sequenceNumber++; - messages[0].header.messageId = Internal._hash(messages[0], ON_RAMP_ADDRESS_1); + messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); // Nonce never increments on unordered messages. nonceBefore = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender); @@ -412,7 +412,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { messages[0].header.sourceChainSelector, messages[0].header.sequenceNumber, messages[0].header.messageId, - Internal._hash(messages[0], ON_RAMP_ADDRESS_1), + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -456,7 +456,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { s_reverting_receiver.setErr(realError1); messages[0].receiver = address(s_reverting_receiver); - messages[0].header.messageId = Internal._hash(messages[0], ON_RAMP_ADDRESS_1); + messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); // Nonce should increment on non-strict assertEq(uint64(0), s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(OWNER))); @@ -468,7 +468,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { messages[0].header.sourceChainSelector, messages[0].header.sequenceNumber, messages[0].header.messageId, - Internal._hash(messages[0], ON_RAMP_ADDRESS_1), + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.FAILURE, abi.encodeWithSelector( OffRamp.ReceiverError.selector, @@ -483,7 +483,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); messages[0].header.nonce++; - messages[0].header.messageId = Internal._hash(messages[0], ON_RAMP_ADDRESS_1); + messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); vm.expectEmit(); emit NonceManager.SkippedIncorrectNonce( @@ -500,7 +500,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { _generateMessagesWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); messages[1].header.nonce++; - messages[1].header.messageId = Internal._hash(messages[1], ON_RAMP_ADDRESS_1); + messages[1].header.messageId = _hashMessage(messages[1], ON_RAMP_ADDRESS_1); vm.expectEmit(); emit NonceManager.SkippedIncorrectNonce(SOURCE_CHAIN_SELECTOR_1, messages[1].header.nonce, messages[1].sender); @@ -513,7 +513,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { messages[0].header.sourceChainSelector, messages[0].header.sequenceNumber, messages[0].header.messageId, - Internal._hash(messages[0], ON_RAMP_ADDRESS_1), + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -531,7 +531,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber, messages[0].header.messageId, - Internal._hash(messages[0], ON_RAMP_ADDRESS_1), + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -548,7 +548,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); messages[0].header.nonce = 0; - messages[0].header.messageId = Internal._hash(messages[0], ON_RAMP_ADDRESS_1); + messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); vm.recordLogs(); s_offRamp.executeSingleReport( @@ -558,7 +558,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber, messages[0].header.messageId, - Internal._hash(messages[0], ON_RAMP_ADDRESS_1), + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -578,7 +578,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); MaybeRevertMessageReceiverNo165 newReceiver = new MaybeRevertMessageReceiverNo165(true); messages[0].receiver = address(newReceiver); - messages[0].header.messageId = Internal._hash(messages[0], ON_RAMP_ADDRESS_1); + messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); vm.recordLogs(); s_offRamp.executeSingleReport( @@ -588,7 +588,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { messages[0].header.sourceChainSelector, messages[0].header.sequenceNumber, messages[0].header.messageId, - Internal._hash(messages[0], ON_RAMP_ADDRESS_1), + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -608,7 +608,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { messages[0].header.sourceChainSelector, messages[0].header.sequenceNumber, messages[0].header.messageId, - Internal._hash(messages[0], ON_RAMP_ADDRESS_1), + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -620,7 +620,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { _generateMessagesWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); // Set message 1 to use another receiver to simulate more fair gas costs messages[1].receiver = address(s_secondary_receiver); - messages[1].header.messageId = Internal._hash(messages[1], ON_RAMP_ADDRESS_1); + messages[1].header.messageId = _hashMessage(messages[1], ON_RAMP_ADDRESS_1); Internal.ExecutionReportSingleChain memory report = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); @@ -634,7 +634,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber, messages[0].header.messageId, - Internal._hash(messages[0], ON_RAMP_ADDRESS_1), + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -644,7 +644,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { SOURCE_CHAIN_SELECTOR_1, messages[1].header.sequenceNumber, messages[1].header.messageId, - Internal._hash(messages[1], ON_RAMP_ADDRESS_1), + _hashMessage(messages[1], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -655,7 +655,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { _generateMessagesWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); // Set message 1 to use another receiver to simulate more fair gas costs messages[1].receiver = address(s_secondary_receiver); - messages[1].header.messageId = Internal._hash(messages[1], ON_RAMP_ADDRESS_1); + messages[1].header.messageId = _hashMessage(messages[1], ON_RAMP_ADDRESS_1); assertEq(uint64(0), s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(OWNER))); @@ -671,7 +671,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber, messages[0].header.messageId, - Internal._hash(messages[0], ON_RAMP_ADDRESS_1), + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -680,7 +680,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { SOURCE_CHAIN_SELECTOR_1, messages[1].header.sequenceNumber, messages[1].header.messageId, - Internal._hash(messages[1], ON_RAMP_ADDRESS_1), + _hashMessage(messages[1], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -703,7 +703,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { if (orderings[i]) { messages[i].header.nonce = ++expectedNonce; } - messages[i].header.messageId = Internal._hash(messages[i], ON_RAMP_ADDRESS_1); + messages[i].header.messageId = _hashMessage(messages[i], ON_RAMP_ADDRESS_1); } uint64 nonceBefore = s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, abi.encode(OWNER)); @@ -726,7 +726,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { SOURCE_CHAIN_SELECTOR_1, messages[i].header.sequenceNumber, messages[i].header.messageId, - Internal._hash(messages[i], ON_RAMP_ADDRESS_1), + _hashMessage(messages[i], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -743,8 +743,8 @@ contract OffRamp_executeSingleReport is OffRampSetup { _generateMessagesWithTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); messages[0].tokenAmounts[0].sourcePoolAddress = abi.encode(fakePoolAddress); - messages[0].header.messageId = Internal._hash(messages[0], ON_RAMP_ADDRESS_1); - messages[1].header.messageId = Internal._hash(messages[1], ON_RAMP_ADDRESS_1); + messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); + messages[1].header.messageId = _hashMessage(messages[1], ON_RAMP_ADDRESS_1); vm.recordLogs(); @@ -755,7 +755,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber, messages[0].header.messageId, - Internal._hash(messages[0], ON_RAMP_ADDRESS_1), + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.FAILURE, abi.encodeWithSelector( OffRamp.TokenHandlingError.selector, @@ -928,7 +928,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { // gas limit too high, Router's external call should revert messages[0].gasLimit = 1e36; messages[0].receiver = address(new ConformingReceiver(address(s_destRouter), s_destFeeToken)); - messages[0].header.messageId = Internal._hash(messages[0], ON_RAMP_ADDRESS_1); + messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); Internal.ExecutionReportSingleChain memory executionReport = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); @@ -939,7 +939,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { messages[0].header.sourceChainSelector, messages[0].header.sequenceNumber, messages[0].header.messageId, - Internal._hash(messages[0], ON_RAMP_ADDRESS_1), + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.FAILURE, abi.encodeWithSelector(CallWithExactGas.NotEnoughGasForCall.selector) ); @@ -955,7 +955,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { s_reverting_receiver.setErr(realError1); messages[0].receiver = address(s_reverting_receiver); - messages[0].header.messageId = Internal._hash(messages[0], ON_RAMP_ADDRESS_1); + messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); vm.recordLogs(); s_offRamp.executeSingleReport( @@ -965,7 +965,7 @@ contract OffRamp_executeSingleReport is OffRampSetup { messages[0].header.sourceChainSelector, messages[0].header.sequenceNumber, messages[0].header.messageId, - Internal._hash(messages[0], ON_RAMP_ADDRESS_1), + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.FAILURE, abi.encodeWithSelector( OffRamp.ReceiverError.selector, @@ -1134,7 +1134,7 @@ contract OffRamp_executeSingleMessage is OffRampSetup { // Setup the receiver to a non-CCIP Receiver, which will skip the Router call (but should still perform the validation) MaybeRevertMessageReceiverNo165 newReceiver = new MaybeRevertMessageReceiverNo165(true); message.receiver = address(newReceiver); - message.header.messageId = Internal._hash(message, ON_RAMP_ADDRESS_1); + message.header.messageId = _hashMessage(message, ON_RAMP_ADDRESS_1); s_inboundMessageInterceptor.setMessageIdValidationState(message.header.messageId, true); vm.expectRevert( @@ -1169,7 +1169,7 @@ contract OffRamp_batchExecute is OffRampSetup { messages[0].header.sourceChainSelector, messages[0].header.sequenceNumber, messages[0].header.messageId, - Internal._hash(messages[0], ON_RAMP_ADDRESS_1), + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -1199,7 +1199,7 @@ contract OffRamp_batchExecute is OffRampSetup { messages1[0].header.sourceChainSelector, messages1[0].header.sequenceNumber, messages1[0].header.messageId, - Internal._hash(messages1[0], ON_RAMP_ADDRESS_1), + _hashMessage(messages1[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -1209,7 +1209,7 @@ contract OffRamp_batchExecute is OffRampSetup { messages1[1].header.sourceChainSelector, messages1[1].header.sequenceNumber, messages1[1].header.messageId, - Internal._hash(messages1[1], ON_RAMP_ADDRESS_1), + _hashMessage(messages1[1], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -1219,7 +1219,7 @@ contract OffRamp_batchExecute is OffRampSetup { messages2[0].header.sourceChainSelector, messages2[0].header.sequenceNumber, messages2[0].header.messageId, - Internal._hash(messages2[0], ON_RAMP_ADDRESS_1), + _hashMessage(messages2[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -1250,7 +1250,7 @@ contract OffRamp_batchExecute is OffRampSetup { messages1[0].header.sourceChainSelector, messages1[0].header.sequenceNumber, messages1[0].header.messageId, - Internal._hash(messages1[0], ON_RAMP_ADDRESS_1), + _hashMessage(messages1[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -1260,7 +1260,7 @@ contract OffRamp_batchExecute is OffRampSetup { messages1[1].header.sourceChainSelector, messages1[1].header.sequenceNumber, messages1[1].header.messageId, - Internal._hash(messages1[1], ON_RAMP_ADDRESS_1), + _hashMessage(messages1[1], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -1270,7 +1270,7 @@ contract OffRamp_batchExecute is OffRampSetup { messages2[0].header.sourceChainSelector, messages2[0].header.sequenceNumber, messages2[0].header.messageId, - Internal._hash(messages2[0], ON_RAMP_ADDRESS_3), + _hashMessage(messages2[0], ON_RAMP_ADDRESS_3), Internal.MessageExecutionState.SUCCESS, "" ); @@ -1316,7 +1316,7 @@ contract OffRamp_batchExecute is OffRampSetup { assertEq(logSourceChainSelector, messages2[0].header.sourceChainSelector); assertEq(logSequenceNumber, messages2[0].header.sequenceNumber); assertEq(logMessageId, messages2[0].header.messageId); - assertEq(logMessageHash, Internal._hash(messages2[0], ON_RAMP_ADDRESS_3)); + assertEq(logMessageHash, _hashMessage(messages2[0], ON_RAMP_ADDRESS_3)); assertEq(logState, uint8(Internal.MessageExecutionState.SUCCESS)); } } @@ -1339,7 +1339,7 @@ contract OffRamp_batchExecute is OffRampSetup { messages[0].header.sourceChainSelector, messages[0].header.sequenceNumber, messages[0].header.messageId, - Internal._hash(messages[0], ON_RAMP_ADDRESS_1), + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -1405,7 +1405,7 @@ contract OffRamp_manuallyExecute is OffRampSetup { Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); messages[0].receiver = address(s_reverting_receiver); - messages[0].header.messageId = Internal._hash(messages[0], ON_RAMP_ADDRESS_1); + messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); s_offRamp.batchExecute( _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[][](1) ); @@ -1421,7 +1421,7 @@ contract OffRamp_manuallyExecute is OffRampSetup { SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber, messages[0].header.messageId, - Internal._hash(messages[0], ON_RAMP_ADDRESS_1), + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -1431,7 +1431,7 @@ contract OffRamp_manuallyExecute is OffRampSetup { Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); messages[0].receiver = address(s_reverting_receiver); - messages[0].header.messageId = Internal._hash(messages[0], ON_RAMP_ADDRESS_1); + messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); s_offRamp.batchExecute( _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[][](1) ); @@ -1447,7 +1447,7 @@ contract OffRamp_manuallyExecute is OffRampSetup { SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber, messages[0].header.messageId, - Internal._hash(messages[0], ON_RAMP_ADDRESS_1), + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -1457,7 +1457,7 @@ contract OffRamp_manuallyExecute is OffRampSetup { Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); messages[0].receiver = address(s_reverting_receiver); - messages[0].header.messageId = Internal._hash(messages[0], ON_RAMP_ADDRESS_1); + messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); assertEq( messages[0].header.nonce - 1, s_inboundNonceManager.getInboundNonce(SOURCE_CHAIN_SELECTOR_1, messages[0].sender) @@ -1474,7 +1474,7 @@ contract OffRamp_manuallyExecute is OffRampSetup { SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber, messages[0].header.messageId, - Internal._hash(messages[0], ON_RAMP_ADDRESS_1), + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.FAILURE, abi.encodeWithSelector( OffRamp.ReceiverError.selector, abi.encodeWithSelector(MaybeRevertMessageReceiver.CustomError.selector, "") @@ -1493,13 +1493,13 @@ contract OffRamp_manuallyExecute is OffRampSetup { for (uint64 i = 0; i < 3; ++i) { messages1[i] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, i + 1); messages1[i].receiver = address(s_reverting_receiver); - messages1[i].header.messageId = Internal._hash(messages1[i], ON_RAMP_ADDRESS_1); + messages1[i].header.messageId = _hashMessage(messages1[i], ON_RAMP_ADDRESS_1); } for (uint64 i = 0; i < 2; ++i) { messages2[i] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_3, ON_RAMP_ADDRESS_3, i + 1); messages2[i].receiver = address(s_reverting_receiver); - messages2[i].header.messageId = Internal._hash(messages2[i], ON_RAMP_ADDRESS_3); + messages2[i].header.messageId = _hashMessage(messages2[i], ON_RAMP_ADDRESS_3); } Internal.ExecutionReportSingleChain[] memory reports = new Internal.ExecutionReportSingleChain[](2); @@ -1533,7 +1533,7 @@ contract OffRamp_manuallyExecute is OffRampSetup { SOURCE_CHAIN_SELECTOR_1, messages1[j].header.sequenceNumber, messages1[j].header.messageId, - Internal._hash(messages1[j], ON_RAMP_ADDRESS_1), + _hashMessage(messages1[j], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -1545,7 +1545,7 @@ contract OffRamp_manuallyExecute is OffRampSetup { SOURCE_CHAIN_SELECTOR_3, messages2[k].header.sequenceNumber, messages2[k].header.messageId, - Internal._hash(messages2[k], ON_RAMP_ADDRESS_3), + _hashMessage(messages2[k], ON_RAMP_ADDRESS_3), Internal.MessageExecutionState.SUCCESS, "" ); @@ -1560,7 +1560,7 @@ contract OffRamp_manuallyExecute is OffRampSetup { } messages[1].receiver = address(s_reverting_receiver); - messages[1].header.messageId = Internal._hash(messages[1], ON_RAMP_ADDRESS_1); + messages[1].header.messageId = _hashMessage(messages[1], ON_RAMP_ADDRESS_1); vm.recordLogs(); s_offRamp.batchExecute( @@ -1574,7 +1574,7 @@ contract OffRamp_manuallyExecute is OffRampSetup { SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber, messages[0].header.messageId, - Internal._hash(messages[0], ON_RAMP_ADDRESS_1), + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -1584,7 +1584,7 @@ contract OffRamp_manuallyExecute is OffRampSetup { SOURCE_CHAIN_SELECTOR_1, messages[1].header.sequenceNumber, messages[1].header.messageId, - Internal._hash(messages[1], ON_RAMP_ADDRESS_1), + _hashMessage(messages[1], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.FAILURE, abi.encodeWithSelector( OffRamp.ReceiverError.selector, @@ -1597,7 +1597,7 @@ contract OffRamp_manuallyExecute is OffRampSetup { SOURCE_CHAIN_SELECTOR_1, messages[2].header.sequenceNumber, messages[2].header.messageId, - Internal._hash(messages[2], ON_RAMP_ADDRESS_1), + _hashMessage(messages[2], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -1618,7 +1618,7 @@ contract OffRamp_manuallyExecute is OffRampSetup { SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber, messages[0].header.messageId, - Internal._hash(messages[0], ON_RAMP_ADDRESS_1), + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -1629,7 +1629,7 @@ contract OffRamp_manuallyExecute is OffRampSetup { _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); messages[0].gasLimit = 1; messages[0].receiver = address(new ConformingReceiver(address(s_destRouter), s_destFeeToken)); - messages[0].header.messageId = Internal._hash(messages[0], ON_RAMP_ADDRESS_1); + messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); vm.recordLogs(); s_offRamp.batchExecute( @@ -1639,7 +1639,7 @@ contract OffRamp_manuallyExecute is OffRampSetup { SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber, messages[0].header.messageId, - Internal._hash(messages[0], ON_RAMP_ADDRESS_1), + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.FAILURE, abi.encodeWithSelector(OffRamp.ReceiverError.selector, "") ); @@ -1657,7 +1657,7 @@ contract OffRamp_manuallyExecute is OffRampSetup { SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber, messages[0].header.messageId, - Internal._hash(messages[0], ON_RAMP_ADDRESS_1), + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -1829,7 +1829,7 @@ contract OffRamp_manuallyExecute is OffRampSetup { _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); messages[0].receiver = address(s_reverting_receiver); - messages[0].header.messageId = Internal._hash(messages[0], ON_RAMP_ADDRESS_1); + messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); s_offRamp.batchExecute( _generateBatchReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages), new OffRamp.GasLimitOverride[][](1) @@ -1878,7 +1878,7 @@ contract OffRamp_manuallyExecute is OffRampSetup { messages[0].receiver = address(receiver); - messages[0].header.messageId = Internal._hash(messages[0], ON_RAMP_ADDRESS_1); + messages[0].header.messageId = _hashMessage(messages[0], ON_RAMP_ADDRESS_1); Internal.ExecutionReportSingleChain memory report = _generateReportFromMessages(SOURCE_CHAIN_SELECTOR_1, messages); @@ -1902,7 +1902,7 @@ contract OffRamp_manuallyExecute is OffRampSetup { SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber, messages[0].header.messageId, - Internal._hash(messages[0], ON_RAMP_ADDRESS_1), + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -1918,13 +1918,13 @@ contract OffRamp_manuallyExecute is OffRampSetup { for (uint64 i = 0; i < 3; ++i) { messages1[i] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1, i + 1); messages1[i].receiver = address(s_reverting_receiver); - messages1[i].header.messageId = Internal._hash(messages1[i], ON_RAMP_ADDRESS_1); + messages1[i].header.messageId = _hashMessage(messages1[i], ON_RAMP_ADDRESS_1); } for (uint64 i = 0; i < 2; ++i) { messages2[i] = _generateAny2EVMMessageNoTokens(SOURCE_CHAIN_SELECTOR_3, ON_RAMP_ADDRESS_3, i + 1); messages2[i].receiver = address(s_reverting_receiver); - messages2[i].header.messageId = Internal._hash(messages2[i], ON_RAMP_ADDRESS_3); + messages2[i].header.messageId = _hashMessage(messages2[i], ON_RAMP_ADDRESS_3); } Internal.ExecutionReportSingleChain[] memory reports = new Internal.ExecutionReportSingleChain[](2); @@ -1992,7 +1992,7 @@ contract OffRamp_execute is OffRampSetup { SOURCE_CHAIN_SELECTOR_1, messages[0].header.sequenceNumber, messages[0].header.messageId, - Internal._hash(messages[0], ON_RAMP_ADDRESS_1), + _hashMessage(messages[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -2025,7 +2025,7 @@ contract OffRamp_execute is OffRampSetup { messages1[0].header.sourceChainSelector, messages1[0].header.sequenceNumber, messages1[0].header.messageId, - Internal._hash(messages1[0], ON_RAMP_ADDRESS_1), + _hashMessage(messages1[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -2035,7 +2035,7 @@ contract OffRamp_execute is OffRampSetup { messages1[1].header.sourceChainSelector, messages1[1].header.sequenceNumber, messages1[1].header.messageId, - Internal._hash(messages1[1], ON_RAMP_ADDRESS_1), + _hashMessage(messages1[1], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -2045,7 +2045,7 @@ contract OffRamp_execute is OffRampSetup { messages2[0].header.sourceChainSelector, messages2[0].header.sequenceNumber, messages2[0].header.messageId, - Internal._hash(messages2[0], ON_RAMP_ADDRESS_1), + _hashMessage(messages2[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -2079,7 +2079,7 @@ contract OffRamp_execute is OffRampSetup { reports[i].messages[j].header.sourceChainSelector, reports[i].messages[j].header.sequenceNumber, reports[i].messages[j].header.messageId, - Internal._hash(reports[i].messages[j], ON_RAMP_ADDRESS_1), + _hashMessage(reports[i].messages[j], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -2119,7 +2119,7 @@ contract OffRamp_execute is OffRampSetup { messages1[0].header.sourceChainSelector, messages1[0].header.sequenceNumber, messages1[0].header.messageId, - Internal._hash(messages1[0], ON_RAMP_ADDRESS_1), + _hashMessage(messages1[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.FAILURE, abi.encodeWithSelector( IMessageInterceptor.MessageValidationError.selector, @@ -2132,7 +2132,7 @@ contract OffRamp_execute is OffRampSetup { messages1[1].header.sourceChainSelector, messages1[1].header.sequenceNumber, messages1[1].header.messageId, - Internal._hash(messages1[1], ON_RAMP_ADDRESS_1), + _hashMessage(messages1[1], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.SUCCESS, "" ); @@ -2142,7 +2142,7 @@ contract OffRamp_execute is OffRampSetup { messages2[0].header.sourceChainSelector, messages2[0].header.sequenceNumber, messages2[0].header.messageId, - Internal._hash(messages2[0], ON_RAMP_ADDRESS_1), + _hashMessage(messages2[0], ON_RAMP_ADDRESS_1), Internal.MessageExecutionState.FAILURE, abi.encodeWithSelector( IMessageInterceptor.MessageValidationError.selector, @@ -2507,7 +2507,7 @@ contract OffRamp_trialExecute is OffRampSetup { destExecData: abi.encode(DEFAULT_TOKEN_DEST_GAS_OVERHEAD) }); - message.header.messageId = Internal._hash(message, ON_RAMP_ADDRESS_1); + message.header.messageId = _hashMessage(message, ON_RAMP_ADDRESS_1); // Unhappy path, no revert but marked as failed. (newState, err) = s_offRamp.trialExecute(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); @@ -2525,7 +2525,7 @@ contract OffRamp_trialExecute is OffRampSetup { destExecData: abi.encode(DEFAULT_TOKEN_DEST_GAS_OVERHEAD) }); - message.header.messageId = Internal._hash(message, ON_RAMP_ADDRESS_1); + message.header.messageId = _hashMessage(message, ON_RAMP_ADDRESS_1); (newState, err) = s_offRamp.trialExecute(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); diff --git a/contracts/src/v0.8/ccip/test/offRamp/OffRampSetup.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRampSetup.t.sol index c461e50c0b..ea3f56bc08 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/OffRampSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRampSetup.t.sol @@ -313,7 +313,7 @@ contract OffRampSetup is FeeQuoterSetup, MultiOCR3BaseSetup { gasLimit: GAS_LIMIT }); - message.header.messageId = Internal._hash(message, onRamp); + message.header.messageId = _hashMessage(message, onRamp); return message; } @@ -532,4 +532,21 @@ contract OffRampSetup is FeeQuoterSetup, MultiOCR3BaseSetup { assertTrue(logs[i].topics[0] != eventSelector); } } + + function _hashMessage( + Internal.Any2EVMRampMessage memory message, + bytes memory onRamp + ) internal pure returns (bytes32) { + return Internal._hash( + message, + keccak256( + abi.encode( + Internal.ANY_2_EVM_MESSAGE_HASH, + message.header.sourceChainSelector, + message.header.destChainSelector, + keccak256(onRamp) + ) + ) + ); + } } diff --git a/core/gethwrappers/ccip/generated/message_hasher/message_hasher.go b/core/gethwrappers/ccip/generated/message_hasher/message_hasher.go index 1d95e75778..13d5e7b8d4 100644 --- a/core/gethwrappers/ccip/generated/message_hasher/message_hasher.go +++ b/core/gethwrappers/ccip/generated/message_hasher/message_hasher.go @@ -64,7 +64,7 @@ type InternalRampTokenAmount struct { var MessageHasherMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"}],\"name\":\"decodeEVMExtraArgsV1\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMExtraArgsV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"allowOutOfOrderExecution\",\"type\":\"bool\"}],\"name\":\"decodeEVMExtraArgsV2\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"allowOutOfOrderExecution\",\"type\":\"bool\"}],\"internalType\":\"structClient.EVMExtraArgsV2\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMExtraArgsV1\",\"name\":\"extraArgs\",\"type\":\"tuple\"}],\"name\":\"encodeEVMExtraArgsV1\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"allowOutOfOrderExecution\",\"type\":\"bool\"}],\"internalType\":\"structClient.EVMExtraArgsV2\",\"name\":\"extraArgs\",\"type\":\"tuple\"}],\"name\":\"encodeEVMExtraArgsV2\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"leafDomainSeparator\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"implicitMetadataHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"fixedSizeFieldsHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"dataHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"tokenAmountsHash\",\"type\":\"bytes32\"}],\"name\":\"encodeFinalHashPreimage\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"name\":\"encodeFixedSizeFieldsHashPreimage\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"any2EVMMessageHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"name\":\"encodeMetadataHashPreimage\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"rampTokenAmounts\",\"type\":\"tuple[]\"}],\"name\":\"encodeTokenAmountsHashPreimage\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"name\":\"hash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]", - Bin: "0x608060405234801561001057600080fd5b50610e08806100206000396000f3fe608060405234801561001057600080fd5b50600436106100a35760003560e01c8063a91d3aeb11610076578063c63641bd1161005b578063c63641bd1461019e578063c7ca9a18146101f5578063e733d2091461020857600080fd5b8063a91d3aeb14610150578063b17df7141461016357600080fd5b80632d6d4c5e146100a85780632efb5ac2146100d157806399df8d05146100f2578063a1e747df1461013d575b600080fd5b6100bb6100b63660046107ff565b61021b565b6040516100c891906108a0565b60405180910390f35b6100e46100df36600461095e565b610244565b6040519081526020016100c8565b6100bb610100366004610a68565b604080516020810196909652858101949094526060850192909252608084015260a0808401919091528151808403909101815260c0909201905290565b6100bb61014b366004610aa3565b610257565b6100bb61015e366004610b0b565b610289565b61018f610171366004610b8c565b60408051602080820183526000909152815190810190915290815290565b604051905181526020016100c8565b6101d86101ac366004610bb5565b604080518082019091526000808252602082015250604080518082019091529182521515602082015290565b6040805182518152602092830151151592810192909252016100c8565b6100bb610203366004610be1565b6102c1565b6100bb610216366004610c35565b6102d2565b60608160405160200161022e9190610c77565b6040516020818303038152906040529050919050565b600061025083836102dd565b9392505050565b6060848484846040516020016102709493929190610d5e565b6040516020818303038152906040529050949350505050565b60608686868686866040516020016102a696959493929190610d9b565b60405160208183030381529060405290509695505050505050565b60606102cc8261043a565b92915050565b60606102cc826104fc565b815160208082015160409283015192516000938493610323937f2425b0b9f9054c76ff151b0a175b18f37a4a4e82013a72e9f15c9caa095ed21f93909291889101610d5e565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815290829052805160209182012086518051888401516060808b0151908401516080808d0151950151959761038a9794969395929491939101610d9b565b604051602081830303815290604052805190602001208560400151805190602001208660a001516040516020016103c19190610c77565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120908301969096528101939093526060830191909152608082015260a081019190915260c00160405160208183030381529060405280519060200120905092915050565b604051815160248201526020820151151560448201526060907f181dcf1000000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915292915050565b604051815160248201526060907f97a657c90000000000000000000000000000000000000000000000000000000090604401610479565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff8111828210171561058557610585610533565b60405290565b60405160c0810167ffffffffffffffff8111828210171561058557610585610533565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156105f5576105f5610533565b604052919050565b600082601f83011261060e57600080fd5b813567ffffffffffffffff81111561062857610628610533565b61065960207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016105ae565b81815284602083860101111561066e57600080fd5b816020850160208301376000918101602001919091529392505050565b600082601f83011261069c57600080fd5b8135602067ffffffffffffffff808311156106b9576106b9610533565b8260051b6106c88382016105ae565b93845285810183019383810190888611156106e257600080fd5b84880192505b858310156107f3578235848111156107005760008081fd5b880160a0818b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018113156107365760008081fd5b61073e610562565b87830135878111156107505760008081fd5b61075e8d8a838701016105fd565b825250604080840135888111156107755760008081fd5b6107838e8b838801016105fd565b8a840152506060808501358981111561079c5760008081fd5b6107aa8f8c838901016105fd565b838501525060809150818501358184015250828401359250878311156107d05760008081fd5b6107de8d8a858701016105fd565b908201528452505091840191908401906106e8565b98975050505050505050565b60006020828403121561081157600080fd5b813567ffffffffffffffff81111561082857600080fd5b6108348482850161068b565b949350505050565b6000815180845260005b8181101561086257602081850181015186830182015201610846565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000610250602083018461083c565b803567ffffffffffffffff811681146108cb57600080fd5b919050565b600060a082840312156108e257600080fd5b6108ea610562565b9050813581526108fc602083016108b3565b602082015261090d604083016108b3565b604082015261091e606083016108b3565b606082015261092f608083016108b3565b608082015292915050565b803573ffffffffffffffffffffffffffffffffffffffff811681146108cb57600080fd5b6000806040838503121561097157600080fd5b823567ffffffffffffffff8082111561098957600080fd5b90840190610140828703121561099e57600080fd5b6109a661058b565b6109b087846108d0565b815260a0830135828111156109c457600080fd5b6109d0888286016105fd565b60208301525060c0830135828111156109e857600080fd5b6109f4888286016105fd565b604083015250610a0660e0840161093a565b6060820152610100830135608082015261012083013582811115610a2957600080fd5b610a358882860161068b565b60a08301525093506020850135915080821115610a5157600080fd5b50610a5e858286016105fd565b9150509250929050565b600080600080600060a08688031215610a8057600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b60008060008060808587031215610ab957600080fd5b84359350610ac9602086016108b3565b9250610ad7604086016108b3565b9150606085013567ffffffffffffffff811115610af357600080fd5b610aff878288016105fd565b91505092959194509250565b60008060008060008060c08789031215610b2457600080fd5b86359550602087013567ffffffffffffffff811115610b4257600080fd5b610b4e89828a016105fd565b955050610b5d6040880161093a565b9350610b6b606088016108b3565b925060808701359150610b8060a088016108b3565b90509295509295509295565b600060208284031215610b9e57600080fd5b5035919050565b803580151581146108cb57600080fd5b60008060408385031215610bc857600080fd5b82359150610bd860208401610ba5565b90509250929050565b600060408284031215610bf357600080fd5b6040516040810181811067ffffffffffffffff82111715610c1657610c16610533565b60405282358152610c2960208401610ba5565b60208201529392505050565b600060208284031215610c4757600080fd5b6040516020810181811067ffffffffffffffff82111715610c6a57610c6a610533565b6040529135825250919050565b600060208083018184528085518083526040925060408601915060408160051b87010184880160005b83811015610d50577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0898403018552815160a08151818652610ce48287018261083c565b915050888201518582038a870152610cfc828261083c565b9150508782015185820389870152610d14828261083c565b915050606080830151818701525060808083015192508582038187015250610d3c818361083c565b968901969450505090860190600101610ca0565b509098975050505050505050565b848152600067ffffffffffffffff808616602084015280851660408401525060806060830152610d91608083018461083c565b9695505050505050565b86815260c060208201526000610db460c083018861083c565b73ffffffffffffffffffffffffffffffffffffffff9690961660408301525067ffffffffffffffff9384166060820152608081019290925290911660a0909101529291505056fea164736f6c6343000818000a", + Bin: "0x608060405234801561001057600080fd5b50610e3a806100206000396000f3fe608060405234801561001057600080fd5b50600436106100a35760003560e01c8063a91d3aeb11610076578063c63641bd1161005b578063c63641bd1461019e578063c7ca9a18146101f5578063e733d2091461020857600080fd5b8063a91d3aeb14610150578063b17df7141461016357600080fd5b80632d6d4c5e146100a85780632efb5ac2146100d157806399df8d05146100f2578063a1e747df1461013d575b600080fd5b6100bb6100b6366004610831565b61021b565b6040516100c891906108d2565b60405180910390f35b6100e46100df366004610990565b610244565b6040519081526020016100c8565b6100bb610100366004610a9a565b604080516020810196909652858101949094526060850192909252608084015260a0808401919091528151808403909101815260c0909201905290565b6100bb61014b366004610ad5565b6102b3565b6100bb61015e366004610b3d565b6102e5565b61018f610171366004610bbe565b60408051602080820183526000909152815190810190915290815290565b604051905181526020016100c8565b6101d86101ac366004610be7565b604080518082019091526000808252602082015250604080518082019091529182521515602082015290565b6040805182518152602092830151151592810192909252016100c8565b6100bb610203366004610c13565b61031d565b6100bb610216366004610c67565b61032e565b60608160405160200161022e9190610ca9565b6040516020818303038152906040529050919050565b60006102ac837f2425b0b9f9054c76ff151b0a175b18f37a4a4e82013a72e9f15c9caa095ed21f856000015160200151866000015160400151866040516020016102919493929190610d90565b60405160208183030381529060405280519060200120610339565b9392505050565b6060848484846040516020016102cc9493929190610d90565b6040516020818303038152906040529050949350505050565b606086868686868660405160200161030296959493929190610dcd565b60405160208183030381529060405290509695505050505050565b60606103288261046c565b92915050565b60606103288261052e565b8151805160608085015190830151608080870151940151604051600095869588956103ab959194909391929160200194855273ffffffffffffffffffffffffffffffffffffffff93909316602085015267ffffffffffffffff9182166040850152606084015216608082015260a00190565b604051602081830303815290604052805190602001208560200151805190602001208660400151805190602001208760a001516040516020016103ee9190610ca9565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120908301979097528101949094526060840192909252608083015260a082015260c081019190915260e00160405160208183030381529060405280519060200120905092915050565b604051815160248201526020820151151560448201526060907f181dcf1000000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915292915050565b604051815160248201526060907f97a657c900000000000000000000000000000000000000000000000000000000906044016104ab565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff811182821017156105b7576105b7610565565b60405290565b60405160c0810167ffffffffffffffff811182821017156105b7576105b7610565565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561062757610627610565565b604052919050565b600082601f83011261064057600080fd5b813567ffffffffffffffff81111561065a5761065a610565565b61068b60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016105e0565b8181528460208386010111156106a057600080fd5b816020850160208301376000918101602001919091529392505050565b600082601f8301126106ce57600080fd5b8135602067ffffffffffffffff808311156106eb576106eb610565565b8260051b6106fa8382016105e0565b938452858101830193838101908886111561071457600080fd5b84880192505b85831015610825578235848111156107325760008081fd5b880160a0818b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018113156107685760008081fd5b610770610594565b87830135878111156107825760008081fd5b6107908d8a8387010161062f565b825250604080840135888111156107a75760008081fd5b6107b58e8b8388010161062f565b8a84015250606080850135898111156107ce5760008081fd5b6107dc8f8c8389010161062f565b838501525060809150818501358184015250828401359250878311156108025760008081fd5b6108108d8a8587010161062f565b9082015284525050918401919084019061071a565b98975050505050505050565b60006020828403121561084357600080fd5b813567ffffffffffffffff81111561085a57600080fd5b610866848285016106bd565b949350505050565b6000815180845260005b8181101561089457602081850181015186830182015201610878565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b6020815260006102ac602083018461086e565b803567ffffffffffffffff811681146108fd57600080fd5b919050565b600060a0828403121561091457600080fd5b61091c610594565b90508135815261092e602083016108e5565b602082015261093f604083016108e5565b6040820152610950606083016108e5565b6060820152610961608083016108e5565b608082015292915050565b803573ffffffffffffffffffffffffffffffffffffffff811681146108fd57600080fd5b600080604083850312156109a357600080fd5b823567ffffffffffffffff808211156109bb57600080fd5b9084019061014082870312156109d057600080fd5b6109d86105bd565b6109e28784610902565b815260a0830135828111156109f657600080fd5b610a028882860161062f565b60208301525060c083013582811115610a1a57600080fd5b610a268882860161062f565b604083015250610a3860e0840161096c565b6060820152610100830135608082015261012083013582811115610a5b57600080fd5b610a67888286016106bd565b60a08301525093506020850135915080821115610a8357600080fd5b50610a908582860161062f565b9150509250929050565b600080600080600060a08688031215610ab257600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b60008060008060808587031215610aeb57600080fd5b84359350610afb602086016108e5565b9250610b09604086016108e5565b9150606085013567ffffffffffffffff811115610b2557600080fd5b610b318782880161062f565b91505092959194509250565b60008060008060008060c08789031215610b5657600080fd5b86359550602087013567ffffffffffffffff811115610b7457600080fd5b610b8089828a0161062f565b955050610b8f6040880161096c565b9350610b9d606088016108e5565b925060808701359150610bb260a088016108e5565b90509295509295509295565b600060208284031215610bd057600080fd5b5035919050565b803580151581146108fd57600080fd5b60008060408385031215610bfa57600080fd5b82359150610c0a60208401610bd7565b90509250929050565b600060408284031215610c2557600080fd5b6040516040810181811067ffffffffffffffff82111715610c4857610c48610565565b60405282358152610c5b60208401610bd7565b60208201529392505050565b600060208284031215610c7957600080fd5b6040516020810181811067ffffffffffffffff82111715610c9c57610c9c610565565b6040529135825250919050565b600060208083018184528085518083526040925060408601915060408160051b87010184880160005b83811015610d82577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0898403018552815160a08151818652610d168287018261086e565b915050888201518582038a870152610d2e828261086e565b9150508782015185820389870152610d46828261086e565b915050606080830151818701525060808083015192508582038187015250610d6e818361086e565b968901969450505090860190600101610cd2565b509098975050505050505050565b848152600067ffffffffffffffff808616602084015280851660408401525060806060830152610dc3608083018461086e565b9695505050505050565b86815260c060208201526000610de660c083018861086e565b73ffffffffffffffffffffffffffffffffffffffff9690961660408301525067ffffffffffffffff9384166060820152608081019290925290911660a0909101529291505056fea164736f6c6343000818000a", } var MessageHasherABI = MessageHasherMetaData.ABI diff --git a/core/gethwrappers/ccip/generated/offramp/offramp.go b/core/gethwrappers/ccip/generated/offramp/offramp.go index 2ff1011ab7..0294359052 100644 --- a/core/gethwrappers/ccip/generated/offramp/offramp.go +++ b/core/gethwrappers/ccip/generated/offramp/offramp.go @@ -155,7 +155,7 @@ type OffRampStaticConfig struct { var OffRampMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CanOnlySelfCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"reportOnRamp\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"configOnRamp\",\"type\":\"bytes\"}],\"name\":\"CommitOnRampMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"actual\",\"type\":\"bytes32\"}],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ExecutionError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"ForkedChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enumMultiOCR3Base.InvalidConfigErrorType\",\"name\":\"errorType\",\"type\":\"uint8\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"got\",\"type\":\"uint256\"}],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidEVMAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"name\":\"InvalidInterval\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"newLimit\",\"type\":\"uint256\"}],\"name\":\"InvalidManualExecutionGasLimit\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"tokenIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"oldLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenGasOverride\",\"type\":\"uint256\"}],\"name\":\"InvalidManualExecutionTokenGasOverride\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"messageDestChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidMessageDestChainSelector\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"newState\",\"type\":\"uint8\"}],\"name\":\"InvalidNewState\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidOnRampUpdate\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRoot\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LeavesCannotBeEmpty\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"ManualExecutionGasAmountCountMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ManualExecutionGasLimitMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"ManualExecutionNotYetEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"errorReason\",\"type\":\"bytes\"}],\"name\":\"MessageValidationError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonUniqueSignatures\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"notPool\",\"type\":\"address\"}],\"name\":\"NotACompatiblePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OracleCannotBeZeroAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ReceiverError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountReleased\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePre\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePost\",\"type\":\"uint256\"}],\"name\":\"ReleaseOrMintBalanceMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"name\":\"RootAlreadyCommitted\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"RootNotCommitted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignatureVerificationDisabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignaturesOutOfRegistration\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"reportSourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"messageSourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainSelectorMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"StaleCommitReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"StaticConfigCannotBeChanged\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"TokenDataMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"TokenHandlingError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnexpectedTokenData\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"WrongMessageLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WrongNumberOfSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroChainSelectorNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"AlreadyAttempted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"indexed\":false,\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"}],\"name\":\"CommitReportAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"DynamicConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"messageHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"name\":\"ExecutionStateChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"RootRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"SkippedAlreadyExecutedMessage\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SkippedReportExecution\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"sourceConfig\",\"type\":\"tuple\"}],\"name\":\"SourceChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainSelectorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"}],\"name\":\"StaticConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigUpdates\",\"type\":\"tuple[]\"}],\"name\":\"applySourceChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"destTokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structClient.Any2EVMMessage\",\"name\":\"\",\"type\":\"tuple\"}],\"name\":\"ccipReceive\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"rawVs\",\"type\":\"bytes32\"}],\"name\":\"commit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"execute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"bytes[]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[]\"},{\"internalType\":\"uint32[]\",\"name\":\"tokenGasOverrides\",\"type\":\"uint32[]\"}],\"name\":\"executeSingleMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"getExecutionState\",\"outputs\":[{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLatestPriceSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"getMerkleRoot\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"getSourceChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"latestConfigDetails\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"n\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"}],\"internalType\":\"structMultiOCR3Base.ConfigInfo\",\"name\":\"configInfo\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfig\",\"name\":\"ocrConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage[]\",\"name\":\"messages\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[][]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[][]\"},{\"internalType\":\"bytes32[]\",\"name\":\"proofs\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"proofFlagBits\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.ExecutionReportSingleChain[]\",\"name\":\"reports\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"receiverExecutionGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint32[]\",\"name\":\"tokenGasOverrides\",\"type\":\"uint32[]\"}],\"internalType\":\"structOffRamp.GasLimitOverride[][]\",\"name\":\"gasLimitOverrides\",\"type\":\"tuple[][]\"}],\"name\":\"manuallyExecute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"setDynamicConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfigArgs[]\",\"name\":\"ocrConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"setOCR3Configs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x6101206040523480156200001257600080fd5b506040516200689b3803806200689b833981016040819052620000359162000806565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf81620001fa565b5050466080525060208301516001600160a01b03161580620000ec575060408301516001600160a01b0316155b8062000103575060608301516001600160a01b0316155b1562000122576040516342bcdf7f60e11b815260040160405180910390fd5b82516001600160401b03166000036200014e5760405163c656089560e01b815260040160405180910390fd5b82516001600160401b0390811660a052602080850180516001600160a01b0390811660c05260408088018051831660e0526060808a01805185166101005283518b519098168852945184169587019590955251821690850152905116908201527f683eb52ee924eb817377cfa8f41f238f4bb7a877da5267869dfffbad85f564d89060800160405180910390a1620001e682620002a5565b620001f1816200036d565b50505062000b8d565b336001600160a01b03821603620002545760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b0316620002ce576040516342bcdf7f60e11b815260040160405180910390fd5b805160048054602080850180516001600160a01b039586166001600160c01b03199094168417600160a01b63ffffffff928316021790945560408087018051600580546001600160a01b031916918916919091179055815194855291519094169183019190915251909216908201527fa1c15688cb2c24508e158f6942b9276c6f3028a85e1af8cf3fff0c3ff3d5fc8d9060600160405180910390a150565b60005b8151811015620005ba57600082828151811062000391576200039162000943565b60200260200101519050600081602001519050806001600160401b0316600003620003cf5760405163c656089560e01b815260040160405180910390fd5b81516001600160a01b0316620003f8576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160401b03811660009081526006602052604090206060830151600182018054620004269062000959565b905060000362000489578154600160a81b600160e81b031916600160a81b1782556040516001600160401b03841681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1620004c8565b8154600160a81b90046001600160401b0316600114620004c857604051632105803760e11b81526001600160401b038416600482015260240162000083565b80511580620004fe5750604080516000602082015201604051602081830303815290604052805190602001208180519060200120145b156200051d576040516342bcdf7f60e11b815260040160405180910390fd5b600182016200052d8282620009ea565b50604080850151835486516001600160a01b03166001600160a01b0319921515600160a01b02929092166001600160a81b031990911617178355516001600160401b038416907f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b90620005a290859062000ab6565b60405180910390a25050505080600101905062000370565b5050565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b0381118282101715620005f957620005f9620005be565b60405290565b604051601f8201601f191681016001600160401b03811182821017156200062a576200062a620005be565b604052919050565b80516001600160401b03811681146200064a57600080fd5b919050565b6001600160a01b03811681146200066557600080fd5b50565b6000601f83601f8401126200067c57600080fd5b825160206001600160401b03808311156200069b576200069b620005be565b8260051b620006ac838201620005ff565b9384528681018301938381019089861115620006c757600080fd5b84890192505b85831015620007f957825184811115620006e75760008081fd5b89016080601f19828d038101821315620007015760008081fd5b6200070b620005d4565b888401516200071a816200064f565b815260406200072b85820162000632565b8a8301526060808601518015158114620007455760008081fd5b838301529385015193898511156200075d5760008081fd5b84860195508f603f8701126200077557600094508485fd5b8a8601519450898511156200078e576200078e620005be565b6200079f8b858f88011601620005ff565b93508484528f82868801011115620007b75760008081fd5b60005b85811015620007d7578681018301518582018d01528b01620007ba565b5060009484018b019490945250918201528352509184019190840190620006cd565b9998505050505050505050565b60008060008385036101008112156200081e57600080fd5b60808112156200082d57600080fd5b62000837620005d4565b620008428662000632565b8152602086015162000854816200064f565b6020820152604086015162000869816200064f565b604082015260608601516200087e816200064f565b606082810191909152909450607f19820112156200089b57600080fd5b50604051606081016001600160401b038082118383101715620008c257620008c2620005be565b8160405260808701519150620008d8826200064f565b90825260a08601519063ffffffff82168214620008f457600080fd5b81602084015260c087015191506200090c826200064f565b6040830182905260e0870151929450808311156200092957600080fd5b5050620009398682870162000668565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b600181811c908216806200096e57607f821691505b6020821081036200098f57634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115620009e5576000816000526020600020601f850160051c81016020861015620009c05750805b601f850160051c820191505b81811015620009e157828155600101620009cc565b5050505b505050565b81516001600160401b0381111562000a065762000a06620005be565b62000a1e8162000a17845462000959565b8462000995565b602080601f83116001811462000a56576000841562000a3d5750858301515b600019600386901b1c1916600185901b178555620009e1565b600085815260208120601f198616915b8281101562000a875788860151825594840194600190910190840162000a66565b508582101562000aa65787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b602080825282546001600160a01b0381168383015260a081901c60ff161515604084015260a81c6001600160401b0316606083015260808083015260018084018054600093929190849062000b0b8162000959565b8060a089015260c0600183166000811462000b2f576001811462000b4c5762000b7e565b60ff19841660c08b015260c083151560051b8b0101945062000b7e565b85600052602060002060005b8481101562000b755781548c820185015290880190890162000b58565b8b0160c0019550505b50929998505050505050505050565b60805160a05160c05160e05161010051615c9862000c036000396000818161022c01526129260152600081816101fd0152612bf80152600081816101ce01528181610552015281816106ff015261236a01526000818161019f01526125a9015260008181611d920152611dc50152615c986000f3fe608060405234801561001057600080fd5b50600436106101515760003560e01c806379ba5097116100cd578063d434969111610081578063e9d68a8e11610066578063e9d68a8e146104bc578063f2fde38b146104dc578063f716f99f146104ef57600080fd5b8063d434969114610496578063e62653f5146104a957600080fd5b80638da5cb5b116100b25780638da5cb5b14610417578063c673e58414610432578063ccd37ba31461045257600080fd5b806379ba50971461040157806385572ffb1461040957600080fd5b8063311cd513116101245780635e36480c116101095780635e36480c1461033c5780636f9e320f1461035c5780637437ff9f1461036f57600080fd5b8063311cd5131461030e5780633f4b04aa1461032157600080fd5b806304666f9c1461015657806306285c691461016b578063181f5a77146102b25780632d04ab76146102fb575b600080fd5b610169610164366004613bbf565b610502565b005b61025c60408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160401b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316815250905090565b6040516102a9919081516001600160401b031681526020808301516001600160a01b0390811691830191909152604080840151821690830152606092830151169181019190915260800190565b60405180910390f35b6102ee6040518060400160405280601181526020017f4f666652616d7020312e362e302d64657600000000000000000000000000000081525081565b6040516102a99190613d2d565b610169610309366004613ddd565b610516565b61016961031c366004613e8f565b610a12565b6009546040516001600160401b0390911681526020016102a9565b61034f61034a366004613ee2565b610a7b565b6040516102a99190613f3f565b61016961036a366004613f6a565b610ad0565b6103cb604080516060810182526000808252602082018190529181019190915250604080516060810182526004546001600160a01b038082168352600160a01b90910463ffffffff166020830152600554169181019190915290565b6040805182516001600160a01b03908116825260208085015163ffffffff169083015292820151909216908201526060016102a9565b610169610ae1565b610169610151366004613fbe565b6000546040516001600160a01b0390911681526020016102a9565b610445610440366004614009565b610b92565b6040516102a99190614069565b6104886104603660046140de565b6001600160401b03919091166000908152600860209081526040808320938352929052205490565b6040519081526020016102a9565b6101696104a436600461437a565b610cf0565b6101696104b7366004614702565b610fd0565b6104cf6104ca366004614949565b611277565b6040516102a99190614964565b6101696104ea3660046149b1565b611383565b6101696104fd366004614a36565b611394565b61050a6113d6565b61051381611432565b50565b600061052487890189614d8b565b602081015151909150156105b6576020810151604080830151905162ccd5af60e81b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169263ccd5af009261058592600401614fb3565b60006040518083038186803b15801561059d57600080fd5b505afa1580156105b1573d6000803e3d6000fd5b505050505b805151511515806105cc57508051602001515115155b156106985760095460208a0135906001600160401b0380831691161015610670576009805467ffffffffffffffff19166001600160401b038316179055600480548351604051633937306f60e01b81526001600160a01b0390921692633937306f926106399291016150e7565b600060405180830381600087803b15801561065357600080fd5b505af1158015610667573d6000803e3d6000fd5b50505050610696565b81602001515160000361069657604051632261116760e01b815260040160405180910390fd5b505b60005b816020015151811015610953576000826020015182815181106106c0576106c0615015565b60209081029190910101518051604051632cbc26bb60e01b815267ffffffffffffffff60801b608083901b166004820152919250906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632cbc26bb90602401602060405180830381865afa158015610746573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061076a91906150fa565b1561079857604051637edeb53960e11b81526001600160401b03821660048201526024015b60405180910390fd5b60006107a382611685565b9050806001016040516107b69190615151565b6040518091039020836020015180519060200120146107f35782602001518160010160405163b80d8fa960e01b815260040161078f929190615244565b60408301518154600160a81b90046001600160401b039081169116141580610834575082606001516001600160401b031683604001516001600160401b0316115b1561087957825160408085015160608601519151636af0786b60e11b81526001600160401b03938416600482015290831660248201529116604482015260640161078f565b60808301518061089c5760405163504570e360e01b815260040160405180910390fd5b83516001600160401b03166000908152600860209081526040808320848452909152902054156108f45783516040516332cf0cbf60e01b81526001600160401b0390911660048201526024810182905260440161078f565b606084015161090490600161527f565b825467ffffffffffffffff60a81b1916600160a81b6001600160401b0392831602179092559251166000908152600860209081526040808320948352939052919091204290555060010161069b565b50602081015181516040517f35c02761bcd3ef995c6a601a1981f4ed3934dcbe5041e24e286c89f5531d17e49261098b9290916152a6565b60405180910390a1610a0760008a8a8a8a8a8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808e0282810182019093528d82529093508d92508c9182918501908490808284376000920191909152508b92506116d1915050565b505050505050505050565b610a52610a21828401846152cb565b6040805160008082526020820190925290610a4c565b6060815260200190600190039081610a375790505b506119ca565b604080516000808252602082019092529050610a756001858585858660006116d1565b50505050565b6000610a89600160046152ff565b6002610a96608085615328565b6001600160401b0316610aa9919061534e565b610ab38585611a8c565b901c166003811115610ac757610ac7613f15565b90505b92915050565b610ad86113d6565b61051381611ad1565b6001546001600160a01b03163314610b3b5760405162461bcd60e51b815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e657200000000000000000000604482015260640161078f565b60008054336001600160a01b0319808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610bd56040805160e081019091526000606082018181526080830182905260a0830182905260c08301919091528190815260200160608152602001606081525090565b60ff808316600090815260026020818152604092839020835160e081018552815460608201908152600183015480881660808401526101008104881660a0840152620100009004909616151560c082015294855291820180548451818402810184019095528085529293858301939092830182828015610c7e57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610c60575b5050505050815260200160038201805480602002602001604051908101604052809291908181526020018280548015610ce057602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610cc2575b5050505050815250509050919050565b333014610d10576040516306e34e6560e31b815260040160405180910390fd5b6040805160008082526020820190925281610d4d565b6040805180820190915260008082526020820152815260200190600190039081610d265790505b5060a08701515190915015610d8357610d808660a001518760200151886060015189600001516020015189898989611bb0565b90505b6040805160a081018252875151815287516020908101516001600160401b031681830152808901518351600094840192610dbe929101613d2d565b60408051601f19818403018152918152908252898101516020830152018390526005549091506001600160a01b03168015610e99576040516308d450a160e01b81526001600160a01b038216906308d450a190610e1f908590600401615406565b600060405180830381600087803b158015610e3957600080fd5b505af1925050508015610e4a575060015b610e99573d808015610e78576040519150601f19603f3d011682016040523d82523d6000602084013e610e7d565b606091505b50806040516309c2532560e01b815260040161078f9190613d2d565b604088015151158015610eae57506080880151155b80610ec5575060608801516001600160a01b03163b155b80610eec57506060880151610eea906001600160a01b03166385572ffb60e01b611d73565b155b15610ef957505050610fc9565b87516020908101516001600160401b03166000908152600690915260408082205460808b015160608c01519251633cf9798360e01b815284936001600160a01b0390931692633cf9798392610f579289926113889291600401615419565b6000604051808303816000875af1158015610f76573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610f9e9190810190615455565b509150915081610fc357806040516302a35ba360e21b815260040161078f9190613d2d565b50505050505b5050505050565b610fd8611d8f565b815181518114610ffb576040516320f8fd5960e21b815260040160405180910390fd5b60005b8181101561126757600084828151811061101a5761101a615015565b6020026020010151905060008160200151519050600085848151811061104257611042615015565b602002602001015190508051821461106d576040516320f8fd5960e21b815260040160405180910390fd5b60005b8281101561125857600082828151811061108c5761108c615015565b60200260200101516000015190506000856020015183815181106110b2576110b2615015565b6020026020010151905081600014611106578060800151821015611106578551815151604051633a98d46360e11b81526001600160401b03909216600483015260248201526044810183905260640161078f565b83838151811061111857611118615015565b602002602001015160200151518160a00151511461116557805180516060909101516040516370a193fd60e01b815260048101929092526001600160401b0316602482015260440161078f565b60005b8160a001515181101561124a57600085858151811061118957611189615015565b60200260200101516020015182815181106111a6576111a6615015565b602002602001015163ffffffff169050806000146112415760008360a0015183815181106111d6576111d6615015565b6020026020010151608001518060200190518101906111f591906154ea565b90508063ffffffff1682101561123f578351516040516348e617b360e01b815260048101919091526024810184905263ffffffff821660448201526064810183905260840161078f565b505b50600101611168565b505050806001019050611070565b50505050806001019050610ffe565b5061127283836119ca565b505050565b60408051608080820183526000808352602080840182905283850182905260608085018190526001600160401b03878116845260068352928690208651948501875280546001600160a01b0381168652600160a01b810460ff16151593860193909352600160a81b90920490921694830194909452600184018054939492939184019161130390615117565b80601f016020809104026020016040519081016040528092919081815260200182805461132f90615117565b8015610ce05780601f1061135157610100808354040283529160200191610ce0565b820191906000526020600020905b81548152906001019060200180831161135f57505050919092525091949350505050565b61138b6113d6565b61051381611df7565b61139c6113d6565b60005b81518110156113d2576113ca8282815181106113bd576113bd615015565b6020026020010151611ea0565b60010161139f565b5050565b6000546001600160a01b031633146114305760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640161078f565b565b60005b81518110156113d257600082828151811061145257611452615015565b60200260200101519050600081602001519050806001600160401b031660000361148f5760405163c656089560e01b815260040160405180910390fd5b81516001600160a01b03166114b7576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160401b038116600090815260066020526040902060608301516001820180546114e390615117565b905060000361154557815467ffffffffffffffff60a81b1916600160a81b1782556040516001600160401b03841681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1611582565b8154600160a81b90046001600160401b031660011461158257604051632105803760e11b81526001600160401b038416600482015260240161078f565b805115806115b75750604080516000602082015201604051602081830303815290604052805190602001208180519060200120145b156115d5576040516342bcdf7f60e11b815260040160405180910390fd5b600182016115e38282615557565b50604080850151835486516001600160a01b03166001600160a01b0319921515600160a01b02929092167fffffffffffffffffffffff00000000000000000000000000000000000000000090911617178355516001600160401b038416907f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b9061166e908590615616565b60405180910390a250505050806001019050611435565b6001600160401b03811660009081526006602052604081208054600160a01b900460ff16610aca5760405163ed053c5960e01b81526001600160401b038416600482015260240161078f565b60ff878116600090815260026020908152604080832081516080810183528154815260019091015480861693820193909352610100830485169181019190915262010000909104909216151560608301528735906117308760a4615664565b905082606001511561177857845161174990602061534e565b865161175690602061534e565b6117619060a0615664565b61176b9190615664565b6117759082615664565b90505b3681146117a157604051638e1192e160e01b81526004810182905236602482015260440161078f565b50815181146117d05781516040516324f7d61360e21b815260048101919091526024810182905260440161078f565b6117d8611d8f565b60ff808a166000908152600360209081526040808320338452825280832081518083019092528054808616835293949193909284019161010090910416600281111561182657611826613f15565b600281111561183757611837613f15565b905250905060028160200151600281111561185457611854613f15565b1480156118a85750600260008b60ff1660ff168152602001908152602001600020600301816000015160ff168154811061189057611890615015565b6000918252602090912001546001600160a01b031633145b6118c557604051631b41e11d60e31b815260040160405180910390fd5b508160600151156119755760208201516118e0906001615677565b60ff16855114611903576040516371253a2560e01b815260040160405180910390fd5b83518551146119255760405163a75d88af60e01b815260040160405180910390fd5b60008787604051611937929190615690565b60405190819003812061194e918b906020016156a0565b6040516020818303038152906040528051906020012090506119738a8288888861217f565b505b6040805182815260208a8101356001600160401b03169082015260ff8b16917f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef0910160405180910390a2505050505050505050565b81516000036119eb5760405162bf199760e01b815260040160405180910390fd5b80516040805160008082526020820190925291159181611a2e565b604080518082019091526000815260606020820152815260200190600190039081611a065790505b50905060005b8451811015610fc957611a84858281518110611a5257611a52615015565b602002602001015184611a7e57858381518110611a7157611a71615015565b602002602001015161233c565b8361233c565b600101611a34565b6001600160401b038216600090815260076020526040812081611ab06080856156b4565b6001600160401b031681526020810191909152604001600020549392505050565b80516001600160a01b0316611af9576040516342bcdf7f60e11b815260040160405180910390fd5b805160048054602080850180516001600160a01b039586167fffffffffffffffff0000000000000000000000000000000000000000000000009094168417600160a01b63ffffffff928316021790945560408087018051600580546001600160a01b031916918916919091179055815194855291519094169183019190915251909216908201527fa1c15688cb2c24508e158f6942b9276c6f3028a85e1af8cf3fff0c3ff3d5fc8d9060600160405180910390a150565b606088516001600160401b03811115611bcb57611bcb6139df565b604051908082528060200260200182016040528015611c1057816020015b6040805180820190915260008082526020820152815260200190600190039081611be95790505b509050811560005b8a51811015611d655781611cc257848482818110611c3857611c38615015565b9050602002016020810190611c4d91906156da565b63ffffffff1615611cc257848482818110611c6a57611c6a615015565b9050602002016020810190611c7f91906156da565b6040805163ffffffff9092166020830152016040516020818303038152906040528b8281518110611cb257611cb2615015565b6020026020010151608001819052505b611d408b8281518110611cd757611cd7615015565b60200260200101518b8b8b8b8b87818110611cf457611cf4615015565b9050602002810190611d0691906156f7565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612bb092505050565b838281518110611d5257611d52615015565b6020908102919091010152600101611c18565b505098975050505050505050565b6000611d7e83612eae565b8015610ac75750610ac78383612ef9565b467f00000000000000000000000000000000000000000000000000000000000000001461143057604051630f01ce8560e01b81527f0000000000000000000000000000000000000000000000000000000000000000600482015246602482015260440161078f565b336001600160a01b03821603611e4f5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161078f565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b806040015160ff16600003611ecb576000604051631b3fab5160e11b815260040161078f919061573d565b60208082015160ff80821660009081526002909352604083206001810154929390928392169003611f1c576060840151600182018054911515620100000262ff000019909216919091179055611f58565b6060840151600182015460ff6201000090910416151590151514611f58576040516321fd80df60e21b815260ff8416600482015260240161078f565b60a084015180516101001015611f84576001604051631b3fab5160e11b815260040161078f919061573d565b611fea8484600301805480602002602001604051908101604052809291908181526020018280548015611fe057602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611fc2575b5050505050612f9b565b8460600151156120f4576120588484600201805480602002602001604051908101604052809291908181526020018280548015611fe0576020028201919060005260206000209081546001600160a01b03168152600190910190602001808311611fc2575050505050612f9b565b608085015180516101001015612084576002604051631b3fab5160e11b815260040161078f919061573d565b6040860151612094906003615757565b60ff168151116120ba576003604051631b3fab5160e11b815260040161078f919061573d565b805160018401805461ff00191661010060ff8416021790556120e59060028601906020840190613965565b506120f285826001613004565b505b61210084826002613004565b80516121159060038501906020840190613965565b5060408581015160018401805460ff191660ff8316179055865180855560a088015192517fab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f5479361216e9389939260028a01929190615773565b60405180910390a1610fc98461315f565b8251600090815b818110156123325760006001888684602081106121a5576121a5615015565b6121b291901a601b615677565b8985815181106121c4576121c4615015565b60200260200101518986815181106121de576121de615015565b60200260200101516040516000815260200160405260405161221c949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa15801561223e573d6000803e3d6000fd5b505060408051601f1981015160ff808e166000908152600360209081528582206001600160a01b0385168352815285822085870190965285548084168652939750909550929392840191610100900416600281111561229f5761229f613f15565b60028111156122b0576122b0613f15565b90525090506001816020015160028111156122cd576122cd613f15565b146122eb57604051636518c33d60e11b815260040160405180910390fd5b8051600160ff9091161b85161561231557604051633d9ef1f160e21b815260040160405180910390fd5b806000015160ff166001901b851794505050806001019050612186565b5050505050505050565b81518151604051632cbc26bb60e01b8152608083901b67ffffffffffffffff60801b166004820152901515907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632cbc26bb90602401602060405180830381865afa1580156123b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123dd91906150fa565b1561244e57801561240c57604051637edeb53960e11b81526001600160401b038316600482015260240161078f565b6040516001600160401b03831681527faab522ed53d887e56ed53dd37398a01aeef6a58e0fa77c2173beb9512d8949339060200160405180910390a150505050565b600061245983611685565b600101805461246790615117565b80601f016020809104026020016040519081016040528092919081815260200182805461249390615117565b80156124e05780601f106124b5576101008083540402835291602001916124e0565b820191906000526020600020905b8154815290600101906020018083116124c357829003601f168201915b5050506020880151519293505050600081900361250f5760405162bf199760e01b815260040160405180910390fd5b8560400151518114612534576040516357e0e08360e01b815260040160405180910390fd5b6000816001600160401b0381111561254e5761254e6139df565b604051908082528060200260200182016040528015612577578160200160208202803683370190505b50905060005b828110156126985760008860200151828151811061259d5761259d615015565b602002602001015190507f00000000000000000000000000000000000000000000000000000000000000006001600160401b03168160000151604001516001600160401b0316146126145780516040908101519051631c21951160e11b81526001600160401b03909116600482015260240161078f565b866001600160401b03168160000151602001516001600160401b03161461266857805160200151604051636c95f1eb60e01b81526001600160401b03808a166004830152909116602482015260440161078f565b61267281866131b6565b83838151811061268457612684615015565b60209081029190910101525060010161257d565b5060006126af86838a606001518b608001516132d8565b9050806000036126dd57604051633ee8bd3f60e11b81526001600160401b038716600482015260240161078f565b60005b83811015610a075760005a905060008a60200151838151811061270557612705615015565b6020026020010151905060006127238a836000015160600151610a7b565b9050600081600381111561273957612739613f15565b14806127565750600381600381111561275457612754613f15565b145b6127ac57815160600151604080516001600160401b03808e16825290921660208301527f3b575419319662b2a6f5e2467d84521517a3382b908eb3d557bb3fdb0c50e23c910160405180910390a1505050612ba8565b6060891561288b578b85815181106127c6576127c6615015565b6020908102919091018101510151600454909150600090600160a01b900463ffffffff166127f488426152ff565b11905080806128145750600383600381111561281257612812613f15565b145b61283c576040516354e7e43160e11b81526001600160401b038d16600482015260240161078f565b8c868151811061284e5761284e615015565b602002602001015160000151600014612885578c868151811061287357612873615015565b60209081029190910101515160808501525b506128f7565b600082600381111561289f5761289f613f15565b146128f757825160600151604080516001600160401b03808f16825290921660208301527f3ef2a99c550a751d4b0b261268f05a803dfb049ab43616a1ffb388f61fe65120910160405180910390a150505050612ba8565b8251608001516001600160401b0316156129d057600082600381111561291f5761291f613f15565b036129d0577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e0e03cae8c85600001516080015186602001516040518463ffffffff1660e01b815260040161298093929190615825565b6020604051808303816000875af115801561299f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129c391906150fa565b6129d05750505050612ba8565b60008d6040015186815181106129e8576129e8615015565b6020026020010151905080518460a001515114612a3257835160600151604051631cfe6d8b60e01b81526001600160401b03808f166004830152909116602482015260440161078f565b612a468c8560000151606001516001613315565b600080612a548684866133ba565b91509150612a6b8e87600001516060015184613315565b8c15612ac2576003826003811115612a8557612a85613f15565b03612ac2576000856003811115612a9e57612a9e613f15565b14612ac257855151604051632b11b8d960e01b815261078f91908390600401615851565b6002826003811115612ad657612ad6613f15565b14612b1b576003826003811115612aef57612aef613f15565b14612b1b578d866000015160600151836040516349362d1f60e11b815260040161078f9392919061586a565b8560000151600001518660000151606001516001600160401b03168f6001600160401b03167f05665fe9ad095383d018353f4cbcba77e84db27dd215081bbf7cdf9ae6fbe48b8d8c81518110612b7357612b73615015565b602002602001015186865a612b88908f6152ff565b604051612b98949392919061588f565b60405180910390a4505050505050505b6001016126e0565b60408051808201909152600080825260208201526000612bd3876020015161346e565b60405163bbe4f6db60e01b81526001600160a01b0380831660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063bbe4f6db90602401602060405180830381865afa158015612c3f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c6391906158c6565b90506001600160a01b0381161580612c925750612c906001600160a01b03821663aff2afbf60e01b611d73565b155b15612cbb5760405163ae9b4ce960e01b81526001600160a01b038216600482015260240161078f565b600080612ce688858c60800151806020019051810190612cdb91906154ea565b63ffffffff166134e2565b915091506000806000612d996040518061010001604052808e81526020018c6001600160401b031681526020018d6001600160a01b031681526020018f606001518152602001896001600160a01b031681526020018f6000015181526020018f6040015181526020018b815250604051602401612d6391906158e3565b60408051601f198184030181529190526020810180516001600160e01b0316633907753760e01b179052878661138860846135c5565b92509250925082612dbf578160405163e1cd550960e01b815260040161078f9190613d2d565b8151602014612dee578151604051631e3be00960e21b815260206004820152602481019190915260440161078f565b600082806020019051810190612e0491906159af565b9050866001600160a01b03168c6001600160a01b031614612e80576000612e358d8a612e30868a6152ff565b6134e2565b50905086811080612e4f575081612e4c88836152ff565b14155b15612e7e5760405163a966e21f60e01b815260048101839052602481018890526044810182905260640161078f565b505b604080518082019091526001600160a01b039098168852602088015250949550505050505095945050505050565b6000612ec1826301ffc9a760e01b612ef9565b8015610aca5750612ef2827fffffffff00000000000000000000000000000000000000000000000000000000612ef9565b1592915050565b6040517fffffffff0000000000000000000000000000000000000000000000000000000082166024820152600090819060440160408051601f19818403018152919052602080820180516001600160e01b03166301ffc9a760e01b178152825192935060009283928392909183918a617530fa92503d91506000519050828015612f84575060208210155b8015612f905750600081115b979650505050505050565b60005b81518110156112725760ff831660009081526003602052604081208351909190849084908110612fd057612fd0615015565b6020908102919091018101516001600160a01b03168252810191909152604001600020805461ffff19169055600101612f9e565b60005b8251811015610a7557600083828151811061302457613024615015565b602002602001015190506000600281111561304157613041613f15565b60ff80871660009081526003602090815260408083206001600160a01b0387168452909152902054610100900416600281111561308057613080613f15565b146130a1576004604051631b3fab5160e11b815260040161078f919061573d565b6001600160a01b0381166130c85760405163d6c62c9b60e01b815260040160405180910390fd5b60405180604001604052808360ff1681526020018460028111156130ee576130ee613f15565b905260ff80871660009081526003602090815260408083206001600160a01b0387168452825290912083518154931660ff198416811782559184015190929091839161ffff19161761010083600281111561314b5761314b613f15565b021790555090505050806001019050613007565b60ff81166105135760ff808216600090815260026020526040902060010154620100009004166131a257604051631e8ed32560e21b815260040160405180910390fd5b6009805467ffffffffffffffff1916905550565b8151602080820151604092830151925160009384936131fc937f2425b0b9f9054c76ff151b0a175b18f37a4a4e82013a72e9f15c9caa095ed21f939092918891016159c8565b60408051601f1981840301815290829052805160209182012086518051888401516060808b0151908401516080808d0151950151959761324597949693959294919391016159fa565b604051602081830303815290604052805190602001208560400151805190602001208660a0015160405160200161327c9190615afe565b60408051601f198184030181528282528051602091820120908301969096528101939093526060830191909152608082015260a081019190915260c0015b60405160208183030381529060405280519060200120905092915050565b6000806132e685858561369f565b6001600160401b038716600090815260086020908152604080832093835292905220549150505b949350505050565b60006002613324608085615328565b6001600160401b0316613337919061534e565b905060006133458585611a8c565b905081613354600160046152ff565b901b19168183600381111561336b5761336b613f15565b6001600160401b03871660009081526007602052604081209190921b929092179182916133996080886156b4565b6001600160401b031681526020810191909152604001600020555050505050565b60405163d434969160e01b8152600090606090309063d4349691906133e790889088908890600401615b95565b600060405180830381600087803b15801561340157600080fd5b505af1925050508015613412575060015b613451573d808015613440576040519150601f19603f3d011682016040523d82523d6000602084013e613445565b606091505b50600392509050613466565b50506040805160208101909152600081526002905b935093915050565b60008151602014613494578160405163046b337b60e51b815260040161078f9190613d2d565b6000828060200190518101906134aa91906159af565b90506001600160a01b038111806134c2575061040081105b15610aca578260405163046b337b60e51b815260040161078f9190613d2d565b60008060008060006135438860405160240161350d91906001600160a01b0391909116815260200190565b60408051601f198184030181529190526020810180516001600160e01b03166370a0823160e01b179052888861138860846135c5565b92509250925082613569578160405163e1cd550960e01b815260040161078f9190613d2d565b6020825114613598578151604051631e3be00960e21b815260206004820152602481019190915260440161078f565b818060200190518101906135ac91906159af565b6135b682886152ff565b94509450505050935093915050565b6000606060008361ffff166001600160401b038111156135e7576135e76139df565b6040519080825280601f01601f191660200182016040528015613611576020820181803683370190505b509150863b61362b5763030ed58f60e21b60005260046000fd5b5a8581101561364557632be8ca8b60e21b60005260046000fd5b8590036040810481038710613665576337c3be2960e01b60005260046000fd5b505a6000808a5160208c0160008c8cf193505a900390503d848111156136885750835b808352806000602085013e50955095509592505050565b82518251600091908183036136c757604051630469ac9960e21b815260040160405180910390fd5b61010182118015906136db57506101018111155b6136f8576040516309bde33960e01b815260040160405180910390fd5b60001982820101610100811115613722576040516309bde33960e01b815260040160405180910390fd5b8060000361374f578660008151811061373d5761373d615015565b6020026020010151935050505061391d565b6000816001600160401b03811115613769576137696139df565b604051908082528060200260200182016040528015613792578160200160208202803683370190505b50905060008080805b858110156138bc5760006001821b8b8116036137f657888510156137df578c5160018601958e9181106137d0576137d0615015565b60200260200101519050613818565b85516001850194879181106137d0576137d0615015565b8b5160018401938d91811061380d5761380d615015565b602002602001015190505b600089861015613848578d5160018701968f91811061383957613839615015565b6020026020010151905061386a565b865160018601958891811061385f5761385f615015565b602002602001015190505b8285111561388b576040516309bde33960e01b815260040160405180910390fd5b6138958282613924565b8784815181106138a7576138a7615015565b6020908102919091010152505060010161379b565b5060018503821480156138ce57508683145b80156138d957508581145b6138f6576040516309bde33960e01b815260040160405180910390fd5b83600186038151811061390b5761390b615015565b60200260200101519750505050505050505b9392505050565b600081831061393c576139378284613942565b610ac7565b610ac783835b6040805160016020820152908101839052606081018290526000906080016132ba565b8280548282559060005260206000209081019282156139ba579160200282015b828111156139ba57825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190613985565b506139c69291506139ca565b5090565b5b808211156139c657600081556001016139cb565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b0381118282101715613a1757613a176139df565b60405290565b604051606081016001600160401b0381118282101715613a1757613a176139df565b60405160a081016001600160401b0381118282101715613a1757613a176139df565b60405160c081016001600160401b0381118282101715613a1757613a176139df565b604080519081016001600160401b0381118282101715613a1757613a176139df565b604051601f8201601f191681016001600160401b0381118282101715613acd57613acd6139df565b604052919050565b60006001600160401b03821115613aee57613aee6139df565b5060051b60200190565b6001600160a01b038116811461051357600080fd5b80356001600160401b0381168114613b2457600080fd5b919050565b801515811461051357600080fd5b8035613b2481613b29565b60006001600160401b03821115613b5b57613b5b6139df565b50601f01601f191660200190565b600082601f830112613b7a57600080fd5b8135613b8d613b8882613b42565b613aa5565b818152846020838601011115613ba257600080fd5b816020850160208301376000918101602001919091529392505050565b60006020808385031215613bd257600080fd5b82356001600160401b0380821115613be957600080fd5b818501915085601f830112613bfd57600080fd5b8135613c0b613b8882613ad5565b81815260059190911b83018401908481019088831115613c2a57600080fd5b8585015b83811015613cd057803585811115613c465760008081fd5b86016080818c03601f1901811315613c5e5760008081fd5b613c666139f5565b89830135613c7381613af8565b81526040613c82848201613b0d565b8b830152606080850135613c9581613b29565b83830152928401359289841115613cae57600091508182fd5b613cbc8f8d86880101613b69565b908301525085525050918601918601613c2e565b5098975050505050505050565b60005b83811015613cf8578181015183820152602001613ce0565b50506000910152565b60008151808452613d19816020860160208601613cdd565b601f01601f19169290920160200192915050565b602081526000610ac76020830184613d01565b8060608101831015610aca57600080fd5b60008083601f840112613d6357600080fd5b5081356001600160401b03811115613d7a57600080fd5b602083019150836020828501011115613d9257600080fd5b9250929050565b60008083601f840112613dab57600080fd5b5081356001600160401b03811115613dc257600080fd5b6020830191508360208260051b8501011115613d9257600080fd5b60008060008060008060008060e0898b031215613df957600080fd5b613e038a8a613d40565b975060608901356001600160401b0380821115613e1f57600080fd5b613e2b8c838d01613d51565b909950975060808b0135915080821115613e4457600080fd5b613e508c838d01613d99565b909750955060a08b0135915080821115613e6957600080fd5b50613e768b828c01613d99565b999c989b50969995989497949560c00135949350505050565b600080600060808486031215613ea457600080fd5b613eae8585613d40565b925060608401356001600160401b03811115613ec957600080fd5b613ed586828701613d51565b9497909650939450505050565b60008060408385031215613ef557600080fd5b613efe83613b0d565b9150613f0c60208401613b0d565b90509250929050565b634e487b7160e01b600052602160045260246000fd5b60048110613f3b57613f3b613f15565b9052565b60208101610aca8284613f2b565b8035613b2481613af8565b63ffffffff8116811461051357600080fd5b600060608284031215613f7c57600080fd5b613f84613a1d565b8235613f8f81613af8565b81526020830135613f9f81613f58565b60208201526040830135613fb281613af8565b60408201529392505050565b600060208284031215613fd057600080fd5b81356001600160401b03811115613fe657600080fd5b820160a0818503121561391d57600080fd5b803560ff81168114613b2457600080fd5b60006020828403121561401b57600080fd5b610ac782613ff8565b60008151808452602080850194506020840160005b8381101561405e5781516001600160a01b031687529582019590820190600101614039565b509495945050505050565b60208152600082518051602084015260ff602082015116604084015260ff604082015116606084015260608101511515608084015250602083015160c060a08401526140b860e0840182614024565b90506040840151601f198483030160c08501526140d58282614024565b95945050505050565b600080604083850312156140f157600080fd5b6140fa83613b0d565b946020939093013593505050565b600060a0828403121561411a57600080fd5b614122613a3f565b90508135815261413460208301613b0d565b602082015261414560408301613b0d565b604082015261415660608301613b0d565b606082015261416760808301613b0d565b608082015292915050565b600082601f83011261418357600080fd5b81356020614193613b8883613ad5565b82815260059290921b840181019181810190868411156141b257600080fd5b8286015b848110156142ac5780356001600160401b03808211156141d65760008081fd5b9088019060a0828b03601f19018113156141f05760008081fd5b6141f8613a3f565b878401358381111561420a5760008081fd5b6142188d8a83880101613b69565b8252506040808501358481111561422f5760008081fd5b61423d8e8b83890101613b69565b8a84015250606080860135858111156142565760008081fd5b6142648f8c838a0101613b69565b8385015250608091508186013581840152508285013592508383111561428a5760008081fd5b6142988d8a85880101613b69565b9082015286525050509183019183016141b6565b509695505050505050565b600061014082840312156142ca57600080fd5b6142d2613a61565b90506142de8383614108565b815260a08201356001600160401b03808211156142fa57600080fd5b61430685838601613b69565b602084015260c084013591508082111561431f57600080fd5b61432b85838601613b69565b604084015261433c60e08501613f4d565b6060840152610100840135608084015261012084013591508082111561436157600080fd5b5061436e84828501614172565b60a08301525092915050565b60008060008060006060868803121561439257600080fd5b85356001600160401b03808211156143a957600080fd5b6143b589838a016142b7565b965060208801359150808211156143cb57600080fd5b6143d789838a01613d99565b909650945060408801359150808211156143f057600080fd5b506143fd88828901613d99565b969995985093965092949392505050565b600082601f83011261441f57600080fd5b8135602061442f613b8883613ad5565b82815260059290921b8401810191818101908684111561444e57600080fd5b8286015b848110156142ac5780356001600160401b038111156144715760008081fd5b61447f8986838b01016142b7565b845250918301918301614452565b600082601f83011261449e57600080fd5b813560206144ae613b8883613ad5565b82815260059290921b840181019181810190868411156144cd57600080fd5b8286015b848110156142ac5780356001600160401b03808211156144f057600080fd5b818901915089603f83011261450457600080fd5b85820135614514613b8882613ad5565b81815260059190911b830160400190878101908c83111561453457600080fd5b604085015b8381101561456d5780358581111561455057600080fd5b61455f8f6040838a0101613b69565b845250918901918901614539565b508752505050928401925083016144d1565b600082601f83011261459057600080fd5b813560206145a0613b8883613ad5565b8083825260208201915060208460051b8701019350868411156145c257600080fd5b602086015b848110156142ac57803583529183019183016145c7565b600082601f8301126145ef57600080fd5b813560206145ff613b8883613ad5565b82815260059290921b8401810191818101908684111561461e57600080fd5b8286015b848110156142ac5780356001600160401b03808211156146425760008081fd5b9088019060a0828b03601f190181131561465c5760008081fd5b614664613a3f565b61466f888501613b0d565b8152604080850135848111156146855760008081fd5b6146938e8b8389010161440e565b8a84015250606080860135858111156146ac5760008081fd5b6146ba8f8c838a010161448d565b83850152506080915081860135858111156146d55760008081fd5b6146e38f8c838a010161457f565b9184019190915250919093013590830152508352918301918301614622565b6000806040838503121561471557600080fd5b6001600160401b038335111561472a57600080fd5b61473784843585016145de565b91506001600160401b036020840135111561475157600080fd5b6020830135830184601f82011261476757600080fd5b614774613b888235613ad5565b81358082526020808301929160051b84010187101561479257600080fd5b602083015b6020843560051b85010181101561493b576001600160401b03813511156147bd57600080fd5b87603f8235860101126147cf57600080fd5b6147e2613b886020833587010135613ad5565b81358501602081810135808452908301929160059190911b016040018a101561480a57600080fd5b604083358701015b83358701602081013560051b0160400181101561492b576001600160401b038135111561483e57600080fd5b833587018135016040818d03603f1901121561485957600080fd5b614861613a83565b604082013581526001600160401b036060830135111561488057600080fd5b8c605f60608401358401011261489557600080fd5b60406060830135830101356148ac613b8882613ad5565b808282526020820191508f60608460051b60608801358801010111156148d157600080fd5b6060808601358601015b60608460051b60608801358801010181101561490b576148fb8135613f58565b80358352602092830192016148db565b508060208501525050508085525050602083019250602081019050614812565b5084525060209283019201614797565b508093505050509250929050565b60006020828403121561495b57600080fd5b610ac782613b0d565b602081526001600160a01b0382511660208201526020820151151560408201526001600160401b0360408301511660608201526000606083015160808084015261330d60a0840182613d01565b6000602082840312156149c357600080fd5b813561391d81613af8565b600082601f8301126149df57600080fd5b813560206149ef613b8883613ad5565b8083825260208201915060208460051b870101935086841115614a1157600080fd5b602086015b848110156142ac578035614a2981613af8565b8352918301918301614a16565b60006020808385031215614a4957600080fd5b82356001600160401b0380821115614a6057600080fd5b818501915085601f830112614a7457600080fd5b8135614a82613b8882613ad5565b81815260059190911b83018401908481019088831115614aa157600080fd5b8585015b83811015613cd057803585811115614abc57600080fd5b860160c0818c03601f19011215614ad35760008081fd5b614adb613a61565b8882013581526040614aee818401613ff8565b8a8301526060614aff818501613ff8565b8284015260809150614b12828501613b37565b9083015260a08381013589811115614b2a5760008081fd5b614b388f8d838801016149ce565b838501525060c0840135915088821115614b525760008081fd5b614b608e8c848701016149ce565b9083015250845250918601918601614aa5565b80356001600160e01b0381168114613b2457600080fd5b600082601f830112614b9b57600080fd5b81356020614bab613b8883613ad5565b82815260069290921b84018101918181019086841115614bca57600080fd5b8286015b848110156142ac5760408189031215614be75760008081fd5b614bef613a83565b614bf882613b0d565b8152614c05858301614b73565b81860152835291830191604001614bce565b600082601f830112614c2857600080fd5b81356020614c38613b8883613ad5565b82815260059290921b84018101918181019086841115614c5757600080fd5b8286015b848110156142ac5780356001600160401b0380821115614c7b5760008081fd5b9088019060a0828b03601f1901811315614c955760008081fd5b614c9d613a3f565b614ca8888501613b0d565b815260408085013584811115614cbe5760008081fd5b614ccc8e8b83890101613b69565b8a8401525060609350614ce0848601613b0d565b908201526080614cf1858201613b0d565b93820193909352920135908201528352918301918301614c5b565b600082601f830112614d1d57600080fd5b81356020614d2d613b8883613ad5565b82815260069290921b84018101918181019086841115614d4c57600080fd5b8286015b848110156142ac5760408189031215614d695760008081fd5b614d71613a83565b813581528482013585820152835291830191604001614d50565b60006020808385031215614d9e57600080fd5b82356001600160401b0380821115614db557600080fd5b9084019060608287031215614dc957600080fd5b614dd1613a1d565b823582811115614de057600080fd5b83016040818903811315614df357600080fd5b614dfb613a83565b823585811115614e0a57600080fd5b8301601f81018b13614e1b57600080fd5b8035614e29613b8882613ad5565b81815260069190911b8201890190898101908d831115614e4857600080fd5b928a01925b82841015614e985785848f031215614e655760008081fd5b614e6d613a83565b8435614e7881613af8565b8152614e85858d01614b73565b818d0152825292850192908a0190614e4d565b845250505082870135915084821115614eb057600080fd5b614ebc8a838501614b8a565b81880152835250508284013582811115614ed557600080fd5b614ee188828601614c17565b85830152506040830135935081841115614efa57600080fd5b614f0687858501614d0c565b60408201529695505050505050565b600082825180855260208086019550808260051b84010181860160005b84811015614fa657601f19868403018952815160a06001600160401b03808351168652868301518288880152614f6a83880182613d01565b60408581015184169089015260608086015190931692880192909252506080928301519290950191909152509783019790830190600101614f32565b5090979650505050505050565b60006040808352614fc76040840186614f15565b83810360208581019190915285518083528682019282019060005b8181101561500757845180518452840151848401529383019391850191600101614fe2565b509098975050505050505050565b634e487b7160e01b600052603260045260246000fd5b805160408084528151848201819052600092602091908201906060870190855b8181101561508257835180516001600160a01b031684528501516001600160e01b031685840152928401929185019160010161504b565b50508583015187820388850152805180835290840192506000918401905b808310156150db57835180516001600160401b031683528501516001600160e01b0316858301529284019260019290920191908501906150a0565b50979650505050505050565b602081526000610ac7602083018461502b565b60006020828403121561510c57600080fd5b815161391d81613b29565b600181811c9082168061512b57607f821691505b60208210810361514b57634e487b7160e01b600052602260045260246000fd5b50919050565b600080835461515f81615117565b60018281168015615177576001811461518c576151bb565b60ff19841687528215158302870194506151bb565b8760005260208060002060005b858110156151b25781548a820152908401908201615199565b50505082870194505b50929695505050505050565b600081546151d481615117565b8085526020600183811680156151f1576001811461520b57615239565b60ff1985168884015283151560051b880183019550615239565b866000528260002060005b858110156152315781548a8201860152908301908401615216565b890184019650505b505050505092915050565b6040815260006152576040830185613d01565b82810360208401526140d581856151c7565b634e487b7160e01b600052601160045260246000fd5b6001600160401b0381811683821601908082111561529f5761529f615269565b5092915050565b6040815260006152b96040830185614f15565b82810360208401526140d5818561502b565b6000602082840312156152dd57600080fd5b81356001600160401b038111156152f357600080fd5b61330d848285016145de565b81810381811115610aca57610aca615269565b634e487b7160e01b600052601260045260246000fd5b60006001600160401b038084168061534257615342615312565b92169190910692915050565b8082028115828204841417610aca57610aca615269565b80518252600060206001600160401b0381840151168185015260408084015160a0604087015261539860a0870182613d01565b9050606085015186820360608801526153b18282613d01565b608087810151898303918a01919091528051808352908601935060009250908501905b808310156150db57835180516001600160a01b03168352860151868301529285019260019290920191908401906153d4565b602081526000610ac76020830184615365565b60808152600061542c6080830187615365565b61ffff9590951660208301525060408101929092526001600160a01b0316606090910152919050565b60008060006060848603121561546a57600080fd5b835161547581613b29565b60208501519093506001600160401b0381111561549157600080fd5b8401601f810186136154a257600080fd5b80516154b0613b8882613b42565b8181528760208385010111156154c557600080fd5b6154d6826020830160208601613cdd565b809450505050604084015190509250925092565b6000602082840312156154fc57600080fd5b815161391d81613f58565b601f821115611272576000816000526020600020601f850160051c810160208610156155305750805b601f850160051c820191505b8181101561554f5782815560010161553c565b505050505050565b81516001600160401b03811115615570576155706139df565b6155848161557e8454615117565b84615507565b602080601f8311600181146155b957600084156155a15750858301515b600019600386901b1c1916600185901b17855561554f565b600085815260208120601f198616915b828110156155e8578886015182559484019460019091019084016155c9565b50858210156156065787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60208152600082546001600160a01b038116602084015260ff8160a01c16151560408401526001600160401b038160a81c16606084015250608080830152610ac760a08301600185016151c7565b80820180821115610aca57610aca615269565b60ff8181168382160190811115610aca57610aca615269565b8183823760009101908152919050565b828152606082602083013760800192915050565b60006001600160401b03808416806156ce576156ce615312565b92169190910492915050565b6000602082840312156156ec57600080fd5b813561391d81613f58565b6000808335601e1984360301811261570e57600080fd5b8301803591506001600160401b0382111561572857600080fd5b602001915036819003821315613d9257600080fd5b602081016005831061575157615751613f15565b91905290565b60ff818116838216029081169081811461529f5761529f615269565b600060a0820160ff881683526020878185015260a0604085015281875480845260c0860191508860005282600020935060005b818110156157cb5784546001600160a01b0316835260019485019492840192016157a6565b50508481036060860152865180825290820192508187019060005b8181101561580b5782516001600160a01b0316855293830193918301916001016157e6565b50505060ff851660808501525090505b9695505050505050565b60006001600160401b038086168352808516602084015250606060408301526140d56060830184613d01565b82815260406020820152600061330d6040830184613d01565b6001600160401b038481168252831660208201526060810161330d6040830184613f2b565b84815261589f6020820185613f2b565b6080604082015260006158b56080830185613d01565b905082606083015295945050505050565b6000602082840312156158d857600080fd5b815161391d81613af8565b6020815260008251610100806020850152615902610120850183613d01565b9150602085015161591e60408601826001600160401b03169052565b5060408501516001600160a01b03811660608601525060608501516080850152608085015161595860a08601826001600160a01b03169052565b5060a0850151601f19808685030160c08701526159758483613d01565b935060c08701519150808685030160e08701526159928483613d01565b935060e087015191508086850301838701525061581b8382613d01565b6000602082840312156159c157600080fd5b5051919050565b84815260006001600160401b0380861660208401528085166040840152506080606083015261581b6080830184613d01565b86815260c060208201526000615a1360c0830188613d01565b6001600160a01b03969096166040830152506001600160401b039384166060820152608081019290925290911660a09091015292915050565b600082825180855260208086019550808260051b84010181860160005b84811015614fa657601f19868403018952815160a08151818652615a8f82870182613d01565b9150508582015185820387870152615aa78282613d01565b91505060408083015186830382880152615ac18382613d01565b92505050606080830151818701525060808083015192508582038187015250615aea8183613d01565b9a86019a9450505090830190600101615a69565b602081526000610ac76020830184615a4c565b60008282518085526020808601955060208260051b8401016020860160005b84811015614fa657601f19868403018952615b4c838351613d01565b98840198925090830190600101615b30565b60008151808452602080850194506020840160005b8381101561405e57815163ffffffff1687529582019590820190600101615b73565b60608152600084518051606084015260208101516001600160401b0380821660808601528060408401511660a08601528060608401511660c08601528060808401511660e0860152505050602085015161014080610100850152615bfd6101a0850183613d01565b91506040870151605f198086850301610120870152615c1c8483613d01565b935060608901519150615c39838701836001600160a01b03169052565b608089015161016087015260a0890151925080868503016101808701525050615c628282615a4c565b9150508281036020840152615c778186615b11565b9050828103604084015261581b8185615b5e56fea164736f6c6343000818000a", + Bin: "0x6101206040523480156200001257600080fd5b506040516200688038038062006880833981016040819052620000359162000806565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf81620001fa565b5050466080525060208301516001600160a01b03161580620000ec575060408301516001600160a01b0316155b8062000103575060608301516001600160a01b0316155b1562000122576040516342bcdf7f60e11b815260040160405180910390fd5b82516001600160401b03166000036200014e5760405163c656089560e01b815260040160405180910390fd5b82516001600160401b0390811660a052602080850180516001600160a01b0390811660c05260408088018051831660e0526060808a01805185166101005283518b519098168852945184169587019590955251821690850152905116908201527f683eb52ee924eb817377cfa8f41f238f4bb7a877da5267869dfffbad85f564d89060800160405180910390a1620001e682620002a5565b620001f1816200036d565b50505062000b8d565b336001600160a01b03821603620002545760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b0316620002ce576040516342bcdf7f60e11b815260040160405180910390fd5b805160048054602080850180516001600160a01b039586166001600160c01b03199094168417600160a01b63ffffffff928316021790945560408087018051600580546001600160a01b031916918916919091179055815194855291519094169183019190915251909216908201527fa1c15688cb2c24508e158f6942b9276c6f3028a85e1af8cf3fff0c3ff3d5fc8d9060600160405180910390a150565b60005b8151811015620005ba57600082828151811062000391576200039162000943565b60200260200101519050600081602001519050806001600160401b0316600003620003cf5760405163c656089560e01b815260040160405180910390fd5b81516001600160a01b0316620003f8576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160401b03811660009081526006602052604090206060830151600182018054620004269062000959565b905060000362000489578154600160a81b600160e81b031916600160a81b1782556040516001600160401b03841681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1620004c8565b8154600160a81b90046001600160401b0316600114620004c857604051632105803760e11b81526001600160401b038416600482015260240162000083565b80511580620004fe5750604080516000602082015201604051602081830303815290604052805190602001208180519060200120145b156200051d576040516342bcdf7f60e11b815260040160405180910390fd5b600182016200052d8282620009ea565b50604080850151835486516001600160a01b03166001600160a01b0319921515600160a01b02929092166001600160a81b031990911617178355516001600160401b038416907f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b90620005a290859062000ab6565b60405180910390a25050505080600101905062000370565b5050565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b0381118282101715620005f957620005f9620005be565b60405290565b604051601f8201601f191681016001600160401b03811182821017156200062a576200062a620005be565b604052919050565b80516001600160401b03811681146200064a57600080fd5b919050565b6001600160a01b03811681146200066557600080fd5b50565b6000601f83601f8401126200067c57600080fd5b825160206001600160401b03808311156200069b576200069b620005be565b8260051b620006ac838201620005ff565b9384528681018301938381019089861115620006c757600080fd5b84890192505b85831015620007f957825184811115620006e75760008081fd5b89016080601f19828d038101821315620007015760008081fd5b6200070b620005d4565b888401516200071a816200064f565b815260406200072b85820162000632565b8a8301526060808601518015158114620007455760008081fd5b838301529385015193898511156200075d5760008081fd5b84860195508f603f8701126200077557600094508485fd5b8a8601519450898511156200078e576200078e620005be565b6200079f8b858f88011601620005ff565b93508484528f82868801011115620007b75760008081fd5b60005b85811015620007d7578681018301518582018d01528b01620007ba565b5060009484018b019490945250918201528352509184019190840190620006cd565b9998505050505050505050565b60008060008385036101008112156200081e57600080fd5b60808112156200082d57600080fd5b62000837620005d4565b620008428662000632565b8152602086015162000854816200064f565b6020820152604086015162000869816200064f565b604082015260608601516200087e816200064f565b606082810191909152909450607f19820112156200089b57600080fd5b50604051606081016001600160401b038082118383101715620008c257620008c2620005be565b8160405260808701519150620008d8826200064f565b90825260a08601519063ffffffff82168214620008f457600080fd5b81602084015260c087015191506200090c826200064f565b6040830182905260e0870151929450808311156200092957600080fd5b5050620009398682870162000668565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b600181811c908216806200096e57607f821691505b6020821081036200098f57634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115620009e5576000816000526020600020601f850160051c81016020861015620009c05750805b601f850160051c820191505b81811015620009e157828155600101620009cc565b5050505b505050565b81516001600160401b0381111562000a065762000a06620005be565b62000a1e8162000a17845462000959565b8462000995565b602080601f83116001811462000a56576000841562000a3d5750858301515b600019600386901b1c1916600185901b178555620009e1565b600085815260208120601f198616915b8281101562000a875788860151825594840194600190910190840162000a66565b508582101562000aa65787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b602080825282546001600160a01b0381168383015260a081901c60ff161515604084015260a81c6001600160401b0316606083015260808083015260018084018054600093929190849062000b0b8162000959565b8060a089015260c0600183166000811462000b2f576001811462000b4c5762000b7e565b60ff19841660c08b015260c083151560051b8b0101945062000b7e565b85600052602060002060005b8481101562000b755781548c820185015290880190890162000b58565b8b0160c0019550505b50929998505050505050505050565b60805160a05160c05160e05161010051615c7d62000c036000396000818161022c01526129a90152600081816101fd0152612c7b0152600081816101ce01528181610552015281816106ff015261236a01526000818161019f01526125a9015260008181611d920152611dc50152615c7d6000f3fe608060405234801561001057600080fd5b50600436106101515760003560e01c806379ba5097116100cd578063d434969111610081578063e9d68a8e11610066578063e9d68a8e146104bc578063f2fde38b146104dc578063f716f99f146104ef57600080fd5b8063d434969114610496578063e62653f5146104a957600080fd5b80638da5cb5b116100b25780638da5cb5b14610417578063c673e58414610432578063ccd37ba31461045257600080fd5b806379ba50971461040157806385572ffb1461040957600080fd5b8063311cd513116101245780635e36480c116101095780635e36480c1461033c5780636f9e320f1461035c5780637437ff9f1461036f57600080fd5b8063311cd5131461030e5780633f4b04aa1461032157600080fd5b806304666f9c1461015657806306285c691461016b578063181f5a77146102b25780632d04ab76146102fb575b600080fd5b610169610164366004613c28565b610502565b005b61025c60408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160401b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316815250905090565b6040516102a9919081516001600160401b031681526020808301516001600160a01b0390811691830191909152604080840151821690830152606092830151169181019190915260800190565b60405180910390f35b6102ee6040518060400160405280601181526020017f4f666652616d7020312e362e302d64657600000000000000000000000000000081525081565b6040516102a99190613d96565b610169610309366004613e46565b610516565b61016961031c366004613ef8565b610a12565b6009546040516001600160401b0390911681526020016102a9565b61034f61034a366004613f4b565b610a7b565b6040516102a99190613fa8565b61016961036a366004613fd3565b610ad0565b6103cb604080516060810182526000808252602082018190529181019190915250604080516060810182526004546001600160a01b038082168352600160a01b90910463ffffffff166020830152600554169181019190915290565b6040805182516001600160a01b03908116825260208085015163ffffffff169083015292820151909216908201526060016102a9565b610169610ae1565b610169610151366004614027565b6000546040516001600160a01b0390911681526020016102a9565b610445610440366004614072565b610b92565b6040516102a991906140d2565b610488610460366004614147565b6001600160401b03919091166000908152600860209081526040808320938352929052205490565b6040519081526020016102a9565b6101696104a43660046143e3565b610cf0565b6101696104b736600461476b565b610fd0565b6104cf6104ca3660046149b2565b611277565b6040516102a991906149cd565b6101696104ea366004614a1a565b611383565b6101696104fd366004614a9f565b611394565b61050a6113d6565b61051381611432565b50565b600061052487890189614df4565b602081015151909150156105b6576020810151604080830151905162ccd5af60e81b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169263ccd5af00926105859260040161501c565b60006040518083038186803b15801561059d57600080fd5b505afa1580156105b1573d6000803e3d6000fd5b505050505b805151511515806105cc57508051602001515115155b156106985760095460208a0135906001600160401b0380831691161015610670576009805467ffffffffffffffff19166001600160401b038316179055600480548351604051633937306f60e01b81526001600160a01b0390921692633937306f92610639929101615150565b600060405180830381600087803b15801561065357600080fd5b505af1158015610667573d6000803e3d6000fd5b50505050610696565b81602001515160000361069657604051632261116760e01b815260040160405180910390fd5b505b60005b816020015151811015610953576000826020015182815181106106c0576106c061507e565b60209081029190910101518051604051632cbc26bb60e01b815267ffffffffffffffff60801b608083901b166004820152919250906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632cbc26bb90602401602060405180830381865afa158015610746573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061076a9190615163565b1561079857604051637edeb53960e11b81526001600160401b03821660048201526024015b60405180910390fd5b60006107a382611685565b9050806001016040516107b691906151ba565b6040518091039020836020015180519060200120146107f35782602001518160010160405163b80d8fa960e01b815260040161078f9291906152ad565b60408301518154600160a81b90046001600160401b039081169116141580610834575082606001516001600160401b031683604001516001600160401b0316115b1561087957825160408085015160608601519151636af0786b60e11b81526001600160401b03938416600482015290831660248201529116604482015260640161078f565b60808301518061089c5760405163504570e360e01b815260040160405180910390fd5b83516001600160401b03166000908152600860209081526040808320848452909152902054156108f45783516040516332cf0cbf60e01b81526001600160401b0390911660048201526024810182905260440161078f565b60608401516109049060016152e8565b825467ffffffffffffffff60a81b1916600160a81b6001600160401b0392831602179092559251166000908152600860209081526040808320948352939052919091204290555060010161069b565b50602081015181516040517f35c02761bcd3ef995c6a601a1981f4ed3934dcbe5041e24e286c89f5531d17e49261098b92909161530f565b60405180910390a1610a0760008a8a8a8a8a8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808e0282810182019093528d82529093508d92508c9182918501908490808284376000920191909152508b92506116d1915050565b505050505050505050565b610a52610a2182840184615334565b6040805160008082526020820190925290610a4c565b6060815260200190600190039081610a375790505b506119ca565b604080516000808252602082019092529050610a756001858585858660006116d1565b50505050565b6000610a8960016004615368565b6002610a96608085615391565b6001600160401b0316610aa991906153b7565b610ab38585611a8c565b901c166003811115610ac757610ac7613f7e565b90505b92915050565b610ad86113d6565b61051381611ad1565b6001546001600160a01b03163314610b3b5760405162461bcd60e51b815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e657200000000000000000000604482015260640161078f565b60008054336001600160a01b0319808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610bd56040805160e081019091526000606082018181526080830182905260a0830182905260c08301919091528190815260200160608152602001606081525090565b60ff808316600090815260026020818152604092839020835160e081018552815460608201908152600183015480881660808401526101008104881660a0840152620100009004909616151560c082015294855291820180548451818402810184019095528085529293858301939092830182828015610c7e57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610c60575b5050505050815260200160038201805480602002602001604051908101604052809291908181526020018280548015610ce057602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610cc2575b5050505050815250509050919050565b333014610d10576040516306e34e6560e31b815260040160405180910390fd5b6040805160008082526020820190925281610d4d565b6040805180820190915260008082526020820152815260200190600190039081610d265790505b5060a08701515190915015610d8357610d808660a001518760200151886060015189600001516020015189898989611bb0565b90505b6040805160a081018252875151815287516020908101516001600160401b031681830152808901518351600094840192610dbe929101613d96565b60408051601f19818403018152918152908252898101516020830152018390526005549091506001600160a01b03168015610e99576040516308d450a160e01b81526001600160a01b038216906308d450a190610e1f90859060040161546f565b600060405180830381600087803b158015610e3957600080fd5b505af1925050508015610e4a575060015b610e99573d808015610e78576040519150601f19603f3d011682016040523d82523d6000602084013e610e7d565b606091505b50806040516309c2532560e01b815260040161078f9190613d96565b604088015151158015610eae57506080880151155b80610ec5575060608801516001600160a01b03163b155b80610eec57506060880151610eea906001600160a01b03166385572ffb60e01b611d73565b155b15610ef957505050610fc9565b87516020908101516001600160401b03166000908152600690915260408082205460808b015160608c01519251633cf9798360e01b815284936001600160a01b0390931692633cf9798392610f579289926113889291600401615482565b6000604051808303816000875af1158015610f76573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610f9e91908101906154be565b509150915081610fc357806040516302a35ba360e21b815260040161078f9190613d96565b50505050505b5050505050565b610fd8611d8f565b815181518114610ffb576040516320f8fd5960e21b815260040160405180910390fd5b60005b8181101561126757600084828151811061101a5761101a61507e565b602002602001015190506000816020015151905060008584815181106110425761104261507e565b602002602001015190508051821461106d576040516320f8fd5960e21b815260040160405180910390fd5b60005b8281101561125857600082828151811061108c5761108c61507e565b60200260200101516000015190506000856020015183815181106110b2576110b261507e565b6020026020010151905081600014611106578060800151821015611106578551815151604051633a98d46360e11b81526001600160401b03909216600483015260248201526044810183905260640161078f565b8383815181106111185761111861507e565b602002602001015160200151518160a00151511461116557805180516060909101516040516370a193fd60e01b815260048101929092526001600160401b0316602482015260440161078f565b60005b8160a001515181101561124a5760008585815181106111895761118961507e565b60200260200101516020015182815181106111a6576111a661507e565b602002602001015163ffffffff169050806000146112415760008360a0015183815181106111d6576111d661507e565b6020026020010151608001518060200190518101906111f59190615553565b90508063ffffffff1682101561123f578351516040516348e617b360e01b815260048101919091526024810184905263ffffffff821660448201526064810183905260840161078f565b505b50600101611168565b505050806001019050611070565b50505050806001019050610ffe565b5061127283836119ca565b505050565b60408051608080820183526000808352602080840182905283850182905260608085018190526001600160401b03878116845260068352928690208651948501875280546001600160a01b0381168652600160a01b810460ff16151593860193909352600160a81b90920490921694830194909452600184018054939492939184019161130390615180565b80601f016020809104026020016040519081016040528092919081815260200182805461132f90615180565b8015610ce05780601f1061135157610100808354040283529160200191610ce0565b820191906000526020600020905b81548152906001019060200180831161135f57505050919092525091949350505050565b61138b6113d6565b61051381611df7565b61139c6113d6565b60005b81518110156113d2576113ca8282815181106113bd576113bd61507e565b6020026020010151611ea0565b60010161139f565b5050565b6000546001600160a01b031633146114305760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640161078f565b565b60005b81518110156113d25760008282815181106114525761145261507e565b60200260200101519050600081602001519050806001600160401b031660000361148f5760405163c656089560e01b815260040160405180910390fd5b81516001600160a01b03166114b7576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160401b038116600090815260066020526040902060608301516001820180546114e390615180565b905060000361154557815467ffffffffffffffff60a81b1916600160a81b1782556040516001600160401b03841681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1611582565b8154600160a81b90046001600160401b031660011461158257604051632105803760e11b81526001600160401b038416600482015260240161078f565b805115806115b75750604080516000602082015201604051602081830303815290604052805190602001208180519060200120145b156115d5576040516342bcdf7f60e11b815260040160405180910390fd5b600182016115e382826155c0565b50604080850151835486516001600160a01b03166001600160a01b0319921515600160a01b02929092167fffffffffffffffffffffff00000000000000000000000000000000000000000090911617178355516001600160401b038416907f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b9061166e90859061567f565b60405180910390a250505050806001019050611435565b6001600160401b03811660009081526006602052604081208054600160a01b900460ff16610aca5760405163ed053c5960e01b81526001600160401b038416600482015260240161078f565b60ff878116600090815260026020908152604080832081516080810183528154815260019091015480861693820193909352610100830485169181019190915262010000909104909216151560608301528735906117308760a46156cd565b90508260600151156117785784516117499060206153b7565b86516117569060206153b7565b6117619060a06156cd565b61176b91906156cd565b61177590826156cd565b90505b3681146117a157604051638e1192e160e01b81526004810182905236602482015260440161078f565b50815181146117d05781516040516324f7d61360e21b815260048101919091526024810182905260440161078f565b6117d8611d8f565b60ff808a166000908152600360209081526040808320338452825280832081518083019092528054808616835293949193909284019161010090910416600281111561182657611826613f7e565b600281111561183757611837613f7e565b905250905060028160200151600281111561185457611854613f7e565b1480156118a85750600260008b60ff1660ff168152602001908152602001600020600301816000015160ff16815481106118905761189061507e565b6000918252602090912001546001600160a01b031633145b6118c557604051631b41e11d60e31b815260040160405180910390fd5b508160600151156119755760208201516118e09060016156e0565b60ff16855114611903576040516371253a2560e01b815260040160405180910390fd5b83518551146119255760405163a75d88af60e01b815260040160405180910390fd5b600087876040516119379291906156f9565b60405190819003812061194e918b90602001615709565b6040516020818303038152906040528051906020012090506119738a8288888861217f565b505b6040805182815260208a8101356001600160401b03169082015260ff8b16917f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef0910160405180910390a2505050505050505050565b81516000036119eb5760405162bf199760e01b815260040160405180910390fd5b80516040805160008082526020820190925291159181611a2e565b604080518082019091526000815260606020820152815260200190600190039081611a065790505b50905060005b8451811015610fc957611a84858281518110611a5257611a5261507e565b602002602001015184611a7e57858381518110611a7157611a7161507e565b602002602001015161233c565b8361233c565b600101611a34565b6001600160401b038216600090815260076020526040812081611ab060808561571d565b6001600160401b031681526020810191909152604001600020549392505050565b80516001600160a01b0316611af9576040516342bcdf7f60e11b815260040160405180910390fd5b805160048054602080850180516001600160a01b039586167fffffffffffffffff0000000000000000000000000000000000000000000000009094168417600160a01b63ffffffff928316021790945560408087018051600580546001600160a01b031916918916919091179055815194855291519094169183019190915251909216908201527fa1c15688cb2c24508e158f6942b9276c6f3028a85e1af8cf3fff0c3ff3d5fc8d9060600160405180910390a150565b606088516001600160401b03811115611bcb57611bcb613a48565b604051908082528060200260200182016040528015611c1057816020015b6040805180820190915260008082526020820152815260200190600190039081611be95790505b509050811560005b8a51811015611d655781611cc257848482818110611c3857611c3861507e565b9050602002016020810190611c4d9190615743565b63ffffffff1615611cc257848482818110611c6a57611c6a61507e565b9050602002016020810190611c7f9190615743565b6040805163ffffffff9092166020830152016040516020818303038152906040528b8281518110611cb257611cb261507e565b6020026020010151608001819052505b611d408b8281518110611cd757611cd761507e565b60200260200101518b8b8b8b8b87818110611cf457611cf461507e565b9050602002810190611d069190615760565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612c3392505050565b838281518110611d5257611d5261507e565b6020908102919091010152600101611c18565b505098975050505050505050565b6000611d7e83612f31565b8015610ac75750610ac78383612f7c565b467f00000000000000000000000000000000000000000000000000000000000000001461143057604051630f01ce8560e01b81527f0000000000000000000000000000000000000000000000000000000000000000600482015246602482015260440161078f565b336001600160a01b03821603611e4f5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161078f565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b806040015160ff16600003611ecb576000604051631b3fab5160e11b815260040161078f91906157a6565b60208082015160ff80821660009081526002909352604083206001810154929390928392169003611f1c576060840151600182018054911515620100000262ff000019909216919091179055611f58565b6060840151600182015460ff6201000090910416151590151514611f58576040516321fd80df60e21b815260ff8416600482015260240161078f565b60a084015180516101001015611f84576001604051631b3fab5160e11b815260040161078f91906157a6565b611fea8484600301805480602002602001604051908101604052809291908181526020018280548015611fe057602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611fc2575b505050505061301e565b8460600151156120f4576120588484600201805480602002602001604051908101604052809291908181526020018280548015611fe0576020028201919060005260206000209081546001600160a01b03168152600190910190602001808311611fc257505050505061301e565b608085015180516101001015612084576002604051631b3fab5160e11b815260040161078f91906157a6565b60408601516120949060036157c0565b60ff168151116120ba576003604051631b3fab5160e11b815260040161078f91906157a6565b805160018401805461ff00191661010060ff8416021790556120e590600286019060208401906139ce565b506120f285826001613087565b505b61210084826002613087565b805161211590600385019060208401906139ce565b5060408581015160018401805460ff191660ff8316179055865180855560a088015192517fab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f5479361216e9389939260028a019291906157dc565b60405180910390a1610fc9846131e2565b8251600090815b818110156123325760006001888684602081106121a5576121a561507e565b6121b291901a601b6156e0565b8985815181106121c4576121c461507e565b60200260200101518986815181106121de576121de61507e565b60200260200101516040516000815260200160405260405161221c949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa15801561223e573d6000803e3d6000fd5b505060408051601f1981015160ff808e166000908152600360209081528582206001600160a01b0385168352815285822085870190965285548084168652939750909550929392840191610100900416600281111561229f5761229f613f7e565b60028111156122b0576122b0613f7e565b90525090506001816020015160028111156122cd576122cd613f7e565b146122eb57604051636518c33d60e11b815260040160405180910390fd5b8051600160ff9091161b85161561231557604051633d9ef1f160e21b815260040160405180910390fd5b806000015160ff166001901b851794505050806001019050612186565b5050505050505050565b81518151604051632cbc26bb60e01b8152608083901b67ffffffffffffffff60801b166004820152901515907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632cbc26bb90602401602060405180830381865afa1580156123b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123dd9190615163565b1561244e57801561240c57604051637edeb53960e11b81526001600160401b038316600482015260240161078f565b6040516001600160401b03831681527faab522ed53d887e56ed53dd37398a01aeef6a58e0fa77c2173beb9512d8949339060200160405180910390a150505050565b600061245983611685565b600101805461246790615180565b80601f016020809104026020016040519081016040528092919081815260200182805461249390615180565b80156124e05780601f106124b5576101008083540402835291602001916124e0565b820191906000526020600020905b8154815290600101906020018083116124c357829003601f168201915b5050506020880151519293505050600081900361250f5760405162bf199760e01b815260040160405180910390fd5b8560400151518114612534576040516357e0e08360e01b815260040160405180910390fd5b6000816001600160401b0381111561254e5761254e613a48565b604051908082528060200260200182016040528015612577578160200160208202803683370190505b50905060005b8281101561271b5760008860200151828151811061259d5761259d61507e565b602002602001015190507f00000000000000000000000000000000000000000000000000000000000000006001600160401b03168160000151604001516001600160401b0316146126145780516040908101519051631c21951160e11b81526001600160401b03909116600482015260240161078f565b866001600160401b03168160000151602001516001600160401b03161461266857805160200151604051636c95f1eb60e01b81526001600160401b03808a166004830152909116602482015260440161078f565b6126f5817f2425b0b9f9054c76ff151b0a175b18f37a4a4e82013a72e9f15c9caa095ed21f83600001516020015184600001516040015189805190602001206040516020016126da94939291909384526001600160401b03928316602085015291166040830152606082015260800190565b60405160208183030381529060405280519060200120613239565b8383815181106127075761270761507e565b60209081029190910101525060010161257d565b50600061273286838a606001518b60800151613341565b90508060000361276057604051633ee8bd3f60e11b81526001600160401b038716600482015260240161078f565b60005b83811015610a075760005a905060008a6020015183815181106127885761278861507e565b6020026020010151905060006127a68a836000015160600151610a7b565b905060008160038111156127bc576127bc613f7e565b14806127d9575060038160038111156127d7576127d7613f7e565b145b61282f57815160600151604080516001600160401b03808e16825290921660208301527f3b575419319662b2a6f5e2467d84521517a3382b908eb3d557bb3fdb0c50e23c910160405180910390a1505050612c2b565b6060891561290e578b85815181106128495761284961507e565b6020908102919091018101510151600454909150600090600160a01b900463ffffffff166128778842615368565b11905080806128975750600383600381111561289557612895613f7e565b145b6128bf576040516354e7e43160e11b81526001600160401b038d16600482015260240161078f565b8c86815181106128d1576128d161507e565b602002602001015160000151600014612908578c86815181106128f6576128f661507e565b60209081029190910101515160808501525b5061297a565b600082600381111561292257612922613f7e565b1461297a57825160600151604080516001600160401b03808f16825290921660208301527f3ef2a99c550a751d4b0b261268f05a803dfb049ab43616a1ffb388f61fe65120910160405180910390a150505050612c2b565b8251608001516001600160401b031615612a535760008260038111156129a2576129a2613f7e565b03612a53577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e0e03cae8c85600001516080015186602001516040518463ffffffff1660e01b8152600401612a039392919061588e565b6020604051808303816000875af1158015612a22573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a469190615163565b612a535750505050612c2b565b60008d604001518681518110612a6b57612a6b61507e565b6020026020010151905080518460a001515114612ab557835160600151604051631cfe6d8b60e01b81526001600160401b03808f166004830152909116602482015260440161078f565b612ac98c856000015160600151600161337e565b600080612ad7868486613423565b91509150612aee8e8760000151606001518461337e565b8c15612b45576003826003811115612b0857612b08613f7e565b03612b45576000856003811115612b2157612b21613f7e565b14612b4557855151604051632b11b8d960e01b815261078f919083906004016158ba565b6002826003811115612b5957612b59613f7e565b14612b9e576003826003811115612b7257612b72613f7e565b14612b9e578d866000015160600151836040516349362d1f60e11b815260040161078f939291906158d3565b8560000151600001518660000151606001516001600160401b03168f6001600160401b03167f05665fe9ad095383d018353f4cbcba77e84db27dd215081bbf7cdf9ae6fbe48b8d8c81518110612bf657612bf661507e565b602002602001015186865a612c0b908f615368565b604051612c1b94939291906158f8565b60405180910390a4505050505050505b600101612763565b60408051808201909152600080825260208201526000612c5687602001516134d7565b60405163bbe4f6db60e01b81526001600160a01b0380831660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063bbe4f6db90602401602060405180830381865afa158015612cc2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ce6919061592f565b90506001600160a01b0381161580612d155750612d136001600160a01b03821663aff2afbf60e01b611d73565b155b15612d3e5760405163ae9b4ce960e01b81526001600160a01b038216600482015260240161078f565b600080612d6988858c60800151806020019051810190612d5e9190615553565b63ffffffff1661354b565b915091506000806000612e1c6040518061010001604052808e81526020018c6001600160401b031681526020018d6001600160a01b031681526020018f606001518152602001896001600160a01b031681526020018f6000015181526020018f6040015181526020018b815250604051602401612de6919061594c565b60408051601f198184030181529190526020810180516001600160e01b0316633907753760e01b1790528786611388608461362e565b92509250925082612e42578160405163e1cd550960e01b815260040161078f9190613d96565b8151602014612e71578151604051631e3be00960e21b815260206004820152602481019190915260440161078f565b600082806020019051810190612e879190615a18565b9050866001600160a01b03168c6001600160a01b031614612f03576000612eb88d8a612eb3868a615368565b61354b565b50905086811080612ed2575081612ecf8883615368565b14155b15612f015760405163a966e21f60e01b815260048101839052602481018890526044810182905260640161078f565b505b604080518082019091526001600160a01b039098168852602088015250949550505050505095945050505050565b6000612f44826301ffc9a760e01b612f7c565b8015610aca5750612f75827fffffffff00000000000000000000000000000000000000000000000000000000612f7c565b1592915050565b6040517fffffffff0000000000000000000000000000000000000000000000000000000082166024820152600090819060440160408051601f19818403018152919052602080820180516001600160e01b03166301ffc9a760e01b178152825192935060009283928392909183918a617530fa92503d91506000519050828015613007575060208210155b80156130135750600081115b979650505050505050565b60005b81518110156112725760ff8316600090815260036020526040812083519091908490849081106130535761305361507e565b6020908102919091018101516001600160a01b03168252810191909152604001600020805461ffff19169055600101613021565b60005b8251811015610a755760008382815181106130a7576130a761507e565b60200260200101519050600060028111156130c4576130c4613f7e565b60ff80871660009081526003602090815260408083206001600160a01b0387168452909152902054610100900416600281111561310357613103613f7e565b14613124576004604051631b3fab5160e11b815260040161078f91906157a6565b6001600160a01b03811661314b5760405163d6c62c9b60e01b815260040160405180910390fd5b60405180604001604052808360ff16815260200184600281111561317157613171613f7e565b905260ff80871660009081526003602090815260408083206001600160a01b0387168452825290912083518154931660ff198416811782559184015190929091839161ffff1916176101008360028111156131ce576131ce613f7e565b02179055509050505080600101905061308a565b60ff81166105135760ff8082166000908152600260205260409020600101546201000090041661322557604051631e8ed32560e21b815260040160405180910390fd5b6009805467ffffffffffffffff1916905550565b81518051606080850151908301516080808701519401516040516000958695889561329d95919490939192916020019485526001600160a01b039390931660208501526001600160401b039182166040850152606084015216608082015260a00190565b604051602081830303815290604052805190602001208560200151805190602001208660400151805190602001208760a001516040516020016132e09190615ae3565b60408051601f198184030181528282528051602091820120908301979097528101949094526060840192909252608083015260a082015260c081019190915260e0015b60405160208183030381529060405280519060200120905092915050565b60008061334f858585613708565b6001600160401b038716600090815260086020908152604080832093835292905220549150505b949350505050565b6000600261338d608085615391565b6001600160401b03166133a091906153b7565b905060006133ae8585611a8c565b9050816133bd60016004615368565b901b1916818360038111156133d4576133d4613f7e565b6001600160401b03871660009081526007602052604081209190921b9290921791829161340260808861571d565b6001600160401b031681526020810191909152604001600020555050505050565b60405163d434969160e01b8152600090606090309063d43496919061345090889088908890600401615b7a565b600060405180830381600087803b15801561346a57600080fd5b505af192505050801561347b575060015b6134ba573d8080156134a9576040519150601f19603f3d011682016040523d82523d6000602084013e6134ae565b606091505b506003925090506134cf565b50506040805160208101909152600081526002905b935093915050565b600081516020146134fd578160405163046b337b60e51b815260040161078f9190613d96565b6000828060200190518101906135139190615a18565b90506001600160a01b0381118061352b575061040081105b15610aca578260405163046b337b60e51b815260040161078f9190613d96565b60008060008060006135ac8860405160240161357691906001600160a01b0391909116815260200190565b60408051601f198184030181529190526020810180516001600160e01b03166370a0823160e01b1790528888611388608461362e565b925092509250826135d2578160405163e1cd550960e01b815260040161078f9190613d96565b6020825114613601578151604051631e3be00960e21b815260206004820152602481019190915260440161078f565b818060200190518101906136159190615a18565b61361f8288615368565b94509450505050935093915050565b6000606060008361ffff166001600160401b0381111561365057613650613a48565b6040519080825280601f01601f19166020018201604052801561367a576020820181803683370190505b509150863b6136945763030ed58f60e21b60005260046000fd5b5a858110156136ae57632be8ca8b60e21b60005260046000fd5b85900360408104810387106136ce576337c3be2960e01b60005260046000fd5b505a6000808a5160208c0160008c8cf193505a900390503d848111156136f15750835b808352806000602085013e50955095509592505050565b825182516000919081830361373057604051630469ac9960e21b815260040160405180910390fd5b610101821180159061374457506101018111155b613761576040516309bde33960e01b815260040160405180910390fd5b6000198282010161010081111561378b576040516309bde33960e01b815260040160405180910390fd5b806000036137b857866000815181106137a6576137a661507e565b60200260200101519350505050613986565b6000816001600160401b038111156137d2576137d2613a48565b6040519080825280602002602001820160405280156137fb578160200160208202803683370190505b50905060008080805b858110156139255760006001821b8b81160361385f5788851015613848578c5160018601958e9181106138395761383961507e565b60200260200101519050613881565b85516001850194879181106138395761383961507e565b8b5160018401938d9181106138765761387661507e565b602002602001015190505b6000898610156138b1578d5160018701968f9181106138a2576138a261507e565b602002602001015190506138d3565b86516001860195889181106138c8576138c861507e565b602002602001015190505b828511156138f4576040516309bde33960e01b815260040160405180910390fd5b6138fe828261398d565b8784815181106139105761391061507e565b60209081029190910101525050600101613804565b50600185038214801561393757508683145b801561394257508581145b61395f576040516309bde33960e01b815260040160405180910390fd5b8360018603815181106139745761397461507e565b60200260200101519750505050505050505b9392505050565b60008183106139a5576139a082846139ab565b610ac7565b610ac783835b604080516001602082015290810183905260608101829052600090608001613323565b828054828255906000526020600020908101928215613a23579160200282015b82811115613a2357825182546001600160a01b0319166001600160a01b039091161782556020909201916001909101906139ee565b50613a2f929150613a33565b5090565b5b80821115613a2f5760008155600101613a34565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b0381118282101715613a8057613a80613a48565b60405290565b604051606081016001600160401b0381118282101715613a8057613a80613a48565b60405160a081016001600160401b0381118282101715613a8057613a80613a48565b60405160c081016001600160401b0381118282101715613a8057613a80613a48565b604080519081016001600160401b0381118282101715613a8057613a80613a48565b604051601f8201601f191681016001600160401b0381118282101715613b3657613b36613a48565b604052919050565b60006001600160401b03821115613b5757613b57613a48565b5060051b60200190565b6001600160a01b038116811461051357600080fd5b80356001600160401b0381168114613b8d57600080fd5b919050565b801515811461051357600080fd5b8035613b8d81613b92565b60006001600160401b03821115613bc457613bc4613a48565b50601f01601f191660200190565b600082601f830112613be357600080fd5b8135613bf6613bf182613bab565b613b0e565b818152846020838601011115613c0b57600080fd5b816020850160208301376000918101602001919091529392505050565b60006020808385031215613c3b57600080fd5b82356001600160401b0380821115613c5257600080fd5b818501915085601f830112613c6657600080fd5b8135613c74613bf182613b3e565b81815260059190911b83018401908481019088831115613c9357600080fd5b8585015b83811015613d3957803585811115613caf5760008081fd5b86016080818c03601f1901811315613cc75760008081fd5b613ccf613a5e565b89830135613cdc81613b61565b81526040613ceb848201613b76565b8b830152606080850135613cfe81613b92565b83830152928401359289841115613d1757600091508182fd5b613d258f8d86880101613bd2565b908301525085525050918601918601613c97565b5098975050505050505050565b60005b83811015613d61578181015183820152602001613d49565b50506000910152565b60008151808452613d82816020860160208601613d46565b601f01601f19169290920160200192915050565b602081526000610ac76020830184613d6a565b8060608101831015610aca57600080fd5b60008083601f840112613dcc57600080fd5b5081356001600160401b03811115613de357600080fd5b602083019150836020828501011115613dfb57600080fd5b9250929050565b60008083601f840112613e1457600080fd5b5081356001600160401b03811115613e2b57600080fd5b6020830191508360208260051b8501011115613dfb57600080fd5b60008060008060008060008060e0898b031215613e6257600080fd5b613e6c8a8a613da9565b975060608901356001600160401b0380821115613e8857600080fd5b613e948c838d01613dba565b909950975060808b0135915080821115613ead57600080fd5b613eb98c838d01613e02565b909750955060a08b0135915080821115613ed257600080fd5b50613edf8b828c01613e02565b999c989b50969995989497949560c00135949350505050565b600080600060808486031215613f0d57600080fd5b613f178585613da9565b925060608401356001600160401b03811115613f3257600080fd5b613f3e86828701613dba565b9497909650939450505050565b60008060408385031215613f5e57600080fd5b613f6783613b76565b9150613f7560208401613b76565b90509250929050565b634e487b7160e01b600052602160045260246000fd5b60048110613fa457613fa4613f7e565b9052565b60208101610aca8284613f94565b8035613b8d81613b61565b63ffffffff8116811461051357600080fd5b600060608284031215613fe557600080fd5b613fed613a86565b8235613ff881613b61565b8152602083013561400881613fc1565b6020820152604083013561401b81613b61565b60408201529392505050565b60006020828403121561403957600080fd5b81356001600160401b0381111561404f57600080fd5b820160a0818503121561398657600080fd5b803560ff81168114613b8d57600080fd5b60006020828403121561408457600080fd5b610ac782614061565b60008151808452602080850194506020840160005b838110156140c75781516001600160a01b0316875295820195908201906001016140a2565b509495945050505050565b60208152600082518051602084015260ff602082015116604084015260ff604082015116606084015260608101511515608084015250602083015160c060a084015261412160e084018261408d565b90506040840151601f198483030160c085015261413e828261408d565b95945050505050565b6000806040838503121561415a57600080fd5b61416383613b76565b946020939093013593505050565b600060a0828403121561418357600080fd5b61418b613aa8565b90508135815261419d60208301613b76565b60208201526141ae60408301613b76565b60408201526141bf60608301613b76565b60608201526141d060808301613b76565b608082015292915050565b600082601f8301126141ec57600080fd5b813560206141fc613bf183613b3e565b82815260059290921b8401810191818101908684111561421b57600080fd5b8286015b848110156143155780356001600160401b038082111561423f5760008081fd5b9088019060a0828b03601f19018113156142595760008081fd5b614261613aa8565b87840135838111156142735760008081fd5b6142818d8a83880101613bd2565b825250604080850135848111156142985760008081fd5b6142a68e8b83890101613bd2565b8a84015250606080860135858111156142bf5760008081fd5b6142cd8f8c838a0101613bd2565b838501525060809150818601358184015250828501359250838311156142f35760008081fd5b6143018d8a85880101613bd2565b90820152865250505091830191830161421f565b509695505050505050565b6000610140828403121561433357600080fd5b61433b613aca565b90506143478383614171565b815260a08201356001600160401b038082111561436357600080fd5b61436f85838601613bd2565b602084015260c084013591508082111561438857600080fd5b61439485838601613bd2565b60408401526143a560e08501613fb6565b606084015261010084013560808401526101208401359150808211156143ca57600080fd5b506143d7848285016141db565b60a08301525092915050565b6000806000806000606086880312156143fb57600080fd5b85356001600160401b038082111561441257600080fd5b61441e89838a01614320565b9650602088013591508082111561443457600080fd5b61444089838a01613e02565b9096509450604088013591508082111561445957600080fd5b5061446688828901613e02565b969995985093965092949392505050565b600082601f83011261448857600080fd5b81356020614498613bf183613b3e565b82815260059290921b840181019181810190868411156144b757600080fd5b8286015b848110156143155780356001600160401b038111156144da5760008081fd5b6144e88986838b0101614320565b8452509183019183016144bb565b600082601f83011261450757600080fd5b81356020614517613bf183613b3e565b82815260059290921b8401810191818101908684111561453657600080fd5b8286015b848110156143155780356001600160401b038082111561455957600080fd5b818901915089603f83011261456d57600080fd5b8582013561457d613bf182613b3e565b81815260059190911b830160400190878101908c83111561459d57600080fd5b604085015b838110156145d6578035858111156145b957600080fd5b6145c88f6040838a0101613bd2565b8452509189019189016145a2565b5087525050509284019250830161453a565b600082601f8301126145f957600080fd5b81356020614609613bf183613b3e565b8083825260208201915060208460051b87010193508684111561462b57600080fd5b602086015b848110156143155780358352918301918301614630565b600082601f83011261465857600080fd5b81356020614668613bf183613b3e565b82815260059290921b8401810191818101908684111561468757600080fd5b8286015b848110156143155780356001600160401b03808211156146ab5760008081fd5b9088019060a0828b03601f19018113156146c55760008081fd5b6146cd613aa8565b6146d8888501613b76565b8152604080850135848111156146ee5760008081fd5b6146fc8e8b83890101614477565b8a84015250606080860135858111156147155760008081fd5b6147238f8c838a01016144f6565b838501525060809150818601358581111561473e5760008081fd5b61474c8f8c838a01016145e8565b918401919091525091909301359083015250835291830191830161468b565b6000806040838503121561477e57600080fd5b6001600160401b038335111561479357600080fd5b6147a08484358501614647565b91506001600160401b03602084013511156147ba57600080fd5b6020830135830184601f8201126147d057600080fd5b6147dd613bf18235613b3e565b81358082526020808301929160051b8401018710156147fb57600080fd5b602083015b6020843560051b8501018110156149a4576001600160401b038135111561482657600080fd5b87603f82358601011261483857600080fd5b61484b613bf16020833587010135613b3e565b81358501602081810135808452908301929160059190911b016040018a101561487357600080fd5b604083358701015b83358701602081013560051b01604001811015614994576001600160401b03813511156148a757600080fd5b833587018135016040818d03603f190112156148c257600080fd5b6148ca613aec565b604082013581526001600160401b03606083013511156148e957600080fd5b8c605f6060840135840101126148fe57600080fd5b6040606083013583010135614915613bf182613b3e565b808282526020820191508f60608460051b606088013588010101111561493a57600080fd5b6060808601358601015b60608460051b606088013588010101811015614974576149648135613fc1565b8035835260209283019201614944565b50806020850152505050808552505060208301925060208101905061487b565b5084525060209283019201614800565b508093505050509250929050565b6000602082840312156149c457600080fd5b610ac782613b76565b602081526001600160a01b0382511660208201526020820151151560408201526001600160401b0360408301511660608201526000606083015160808084015261337660a0840182613d6a565b600060208284031215614a2c57600080fd5b813561398681613b61565b600082601f830112614a4857600080fd5b81356020614a58613bf183613b3e565b8083825260208201915060208460051b870101935086841115614a7a57600080fd5b602086015b84811015614315578035614a9281613b61565b8352918301918301614a7f565b60006020808385031215614ab257600080fd5b82356001600160401b0380821115614ac957600080fd5b818501915085601f830112614add57600080fd5b8135614aeb613bf182613b3e565b81815260059190911b83018401908481019088831115614b0a57600080fd5b8585015b83811015613d3957803585811115614b2557600080fd5b860160c0818c03601f19011215614b3c5760008081fd5b614b44613aca565b8882013581526040614b57818401614061565b8a8301526060614b68818501614061565b8284015260809150614b7b828501613ba0565b9083015260a08381013589811115614b935760008081fd5b614ba18f8d83880101614a37565b838501525060c0840135915088821115614bbb5760008081fd5b614bc98e8c84870101614a37565b9083015250845250918601918601614b0e565b80356001600160e01b0381168114613b8d57600080fd5b600082601f830112614c0457600080fd5b81356020614c14613bf183613b3e565b82815260069290921b84018101918181019086841115614c3357600080fd5b8286015b848110156143155760408189031215614c505760008081fd5b614c58613aec565b614c6182613b76565b8152614c6e858301614bdc565b81860152835291830191604001614c37565b600082601f830112614c9157600080fd5b81356020614ca1613bf183613b3e565b82815260059290921b84018101918181019086841115614cc057600080fd5b8286015b848110156143155780356001600160401b0380821115614ce45760008081fd5b9088019060a0828b03601f1901811315614cfe5760008081fd5b614d06613aa8565b614d11888501613b76565b815260408085013584811115614d275760008081fd5b614d358e8b83890101613bd2565b8a8401525060609350614d49848601613b76565b908201526080614d5a858201613b76565b93820193909352920135908201528352918301918301614cc4565b600082601f830112614d8657600080fd5b81356020614d96613bf183613b3e565b82815260069290921b84018101918181019086841115614db557600080fd5b8286015b848110156143155760408189031215614dd25760008081fd5b614dda613aec565b813581528482013585820152835291830191604001614db9565b60006020808385031215614e0757600080fd5b82356001600160401b0380821115614e1e57600080fd5b9084019060608287031215614e3257600080fd5b614e3a613a86565b823582811115614e4957600080fd5b83016040818903811315614e5c57600080fd5b614e64613aec565b823585811115614e7357600080fd5b8301601f81018b13614e8457600080fd5b8035614e92613bf182613b3e565b81815260069190911b8201890190898101908d831115614eb157600080fd5b928a01925b82841015614f015785848f031215614ece5760008081fd5b614ed6613aec565b8435614ee181613b61565b8152614eee858d01614bdc565b818d0152825292850192908a0190614eb6565b845250505082870135915084821115614f1957600080fd5b614f258a838501614bf3565b81880152835250508284013582811115614f3e57600080fd5b614f4a88828601614c80565b85830152506040830135935081841115614f6357600080fd5b614f6f87858501614d75565b60408201529695505050505050565b600082825180855260208086019550808260051b84010181860160005b8481101561500f57601f19868403018952815160a06001600160401b03808351168652868301518288880152614fd383880182613d6a565b60408581015184169089015260608086015190931692880192909252506080928301519290950191909152509783019790830190600101614f9b565b5090979650505050505050565b600060408083526150306040840186614f7e565b83810360208581019190915285518083528682019282019060005b818110156150705784518051845284015184840152938301939185019160010161504b565b509098975050505050505050565b634e487b7160e01b600052603260045260246000fd5b805160408084528151848201819052600092602091908201906060870190855b818110156150eb57835180516001600160a01b031684528501516001600160e01b03168584015292840192918501916001016150b4565b50508583015187820388850152805180835290840192506000918401905b8083101561514457835180516001600160401b031683528501516001600160e01b031685830152928401926001929092019190850190615109565b50979650505050505050565b602081526000610ac76020830184615094565b60006020828403121561517557600080fd5b815161398681613b92565b600181811c9082168061519457607f821691505b6020821081036151b457634e487b7160e01b600052602260045260246000fd5b50919050565b60008083546151c881615180565b600182811680156151e057600181146151f557615224565b60ff1984168752821515830287019450615224565b8760005260208060002060005b8581101561521b5781548a820152908401908201615202565b50505082870194505b50929695505050505050565b6000815461523d81615180565b80855260206001838116801561525a5760018114615274576152a2565b60ff1985168884015283151560051b8801830195506152a2565b866000528260002060005b8581101561529a5781548a820186015290830190840161527f565b890184019650505b505050505092915050565b6040815260006152c06040830185613d6a565b828103602084015261413e8185615230565b634e487b7160e01b600052601160045260246000fd5b6001600160401b03818116838216019080821115615308576153086152d2565b5092915050565b6040815260006153226040830185614f7e565b828103602084015261413e8185615094565b60006020828403121561534657600080fd5b81356001600160401b0381111561535c57600080fd5b61337684828501614647565b81810381811115610aca57610aca6152d2565b634e487b7160e01b600052601260045260246000fd5b60006001600160401b03808416806153ab576153ab61537b565b92169190910692915050565b8082028115828204841417610aca57610aca6152d2565b80518252600060206001600160401b0381840151168185015260408084015160a0604087015261540160a0870182613d6a565b90506060850151868203606088015261541a8282613d6a565b608087810151898303918a01919091528051808352908601935060009250908501905b8083101561514457835180516001600160a01b031683528601518683015292850192600192909201919084019061543d565b602081526000610ac760208301846153ce565b60808152600061549560808301876153ce565b61ffff9590951660208301525060408101929092526001600160a01b0316606090910152919050565b6000806000606084860312156154d357600080fd5b83516154de81613b92565b60208501519093506001600160401b038111156154fa57600080fd5b8401601f8101861361550b57600080fd5b8051615519613bf182613bab565b81815287602083850101111561552e57600080fd5b61553f826020830160208601613d46565b809450505050604084015190509250925092565b60006020828403121561556557600080fd5b815161398681613fc1565b601f821115611272576000816000526020600020601f850160051c810160208610156155995750805b601f850160051c820191505b818110156155b8578281556001016155a5565b505050505050565b81516001600160401b038111156155d9576155d9613a48565b6155ed816155e78454615180565b84615570565b602080601f831160018114615622576000841561560a5750858301515b600019600386901b1c1916600185901b1785556155b8565b600085815260208120601f198616915b8281101561565157888601518255948401946001909101908401615632565b508582101561566f5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60208152600082546001600160a01b038116602084015260ff8160a01c16151560408401526001600160401b038160a81c16606084015250608080830152610ac760a0830160018501615230565b80820180821115610aca57610aca6152d2565b60ff8181168382160190811115610aca57610aca6152d2565b8183823760009101908152919050565b828152606082602083013760800192915050565b60006001600160401b03808416806157375761573761537b565b92169190910492915050565b60006020828403121561575557600080fd5b813561398681613fc1565b6000808335601e1984360301811261577757600080fd5b8301803591506001600160401b0382111561579157600080fd5b602001915036819003821315613dfb57600080fd5b60208101600583106157ba576157ba613f7e565b91905290565b60ff8181168382160290811690818114615308576153086152d2565b600060a0820160ff881683526020878185015260a0604085015281875480845260c0860191508860005282600020935060005b818110156158345784546001600160a01b03168352600194850194928401920161580f565b50508481036060860152865180825290820192508187019060005b818110156158745782516001600160a01b03168552938301939183019160010161584f565b50505060ff851660808501525090505b9695505050505050565b60006001600160401b0380861683528085166020840152506060604083015261413e6060830184613d6a565b8281526040602082015260006133766040830184613d6a565b6001600160401b03848116825283166020820152606081016133766040830184613f94565b8481526159086020820185613f94565b60806040820152600061591e6080830185613d6a565b905082606083015295945050505050565b60006020828403121561594157600080fd5b815161398681613b61565b602081526000825161010080602085015261596b610120850183613d6a565b9150602085015161598760408601826001600160401b03169052565b5060408501516001600160a01b0381166060860152506060850151608085015260808501516159c160a08601826001600160a01b03169052565b5060a0850151601f19808685030160c08701526159de8483613d6a565b935060c08701519150808685030160e08701526159fb8483613d6a565b935060e08701519150808685030183870152506158848382613d6a565b600060208284031215615a2a57600080fd5b5051919050565b600082825180855260208086019550808260051b84010181860160005b8481101561500f57601f19868403018952815160a08151818652615a7482870182613d6a565b9150508582015185820387870152615a8c8282613d6a565b91505060408083015186830382880152615aa68382613d6a565b92505050606080830151818701525060808083015192508582038187015250615acf8183613d6a565b9a86019a9450505090830190600101615a4e565b602081526000610ac76020830184615a31565b60008282518085526020808601955060208260051b8401016020860160005b8481101561500f57601f19868403018952615b31838351613d6a565b98840198925090830190600101615b15565b60008151808452602080850194506020840160005b838110156140c757815163ffffffff1687529582019590820190600101615b58565b60608152600084518051606084015260208101516001600160401b0380821660808601528060408401511660a08601528060608401511660c08601528060808401511660e0860152505050602085015161014080610100850152615be26101a0850183613d6a565b91506040870151605f198086850301610120870152615c018483613d6a565b935060608901519150615c1e838701836001600160a01b03169052565b608089015161016087015260a0890151925080868503016101808701525050615c478282615a31565b9150508281036020840152615c5c8186615af6565b905082810360408401526158848185615b4356fea164736f6c6343000818000a", } var OffRampABI = OffRampMetaData.ABI diff --git a/core/gethwrappers/ccip/generated/onramp/onramp.go b/core/gethwrappers/ccip/generated/onramp/onramp.go index 7d326f4bfd..1663e49f2e 100644 --- a/core/gethwrappers/ccip/generated/onramp/onramp.go +++ b/core/gethwrappers/ccip/generated/onramp/onramp.go @@ -99,7 +99,7 @@ type OnRampStaticConfig struct { var OnRampMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"reentrancyGuardEntered\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CannotSendZeroTokens\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GetSupportedTokensFunctionalityRemovedCheckAdminRegistry\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidAllowListRequest\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidDestChainConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeCalledByRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrAllowlistAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrancyGuardReentrantCall\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RouterMustSetOriginalSender\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"UnsupportedToken\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"name\":\"AllowListAdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"senders\",\"type\":\"address[]\"}],\"name\":\"AllowListSendersAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"senders\",\"type\":\"address[]\"}],\"name\":\"AllowListSendersRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"CCIPMessageSent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOnRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"reentrancyGuardEntered\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"allowListEnabled\",\"type\":\"bool\"}],\"name\":\"DestChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"feeValueJuels\",\"type\":\"uint256\"}],\"name\":\"FeePaid\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeeTokenWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"allowListEnabled\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"addedAllowlistedSenders\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"removedAllowlistedSenders\",\"type\":\"address[]\"}],\"internalType\":\"structOnRamp.AllowListConfigArgs[]\",\"name\":\"allowListConfigArgsItems\",\"type\":\"tuple[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyDestChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"}],\"name\":\"forwardFromRouter\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getAllowedSendersList\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getDestChainConfig\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"allowListEnabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"reentrancyGuardEntered\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getExpectedNextSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"getFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"},{\"internalType\":\"contractIERC20\",\"name\":\"sourceToken\",\"type\":\"address\"}],\"name\":\"getPoolBySourceToken\",\"outputs\":[{\"internalType\":\"contractIPoolV1\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"contractIRouter\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"name\":\"getSupportedTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"reentrancyGuardEntered\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"setDynamicConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"withdrawFeeTokens\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x6101006040523480156200001257600080fd5b506040516200429d3803806200429d83398101604081905262000035916200073f565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf8162000186565b505083516001600160401b031615905080620000e6575060208301516001600160a01b0316155b80620000fd575060408301516001600160a01b0316155b8062000114575060608301516001600160a01b0316155b1562000133576040516306b7c75960e31b815260040160405180910390fd5b82516001600160401b031660805260208301516001600160a01b0390811660a0526040840151811660c05260608401511660e052620001728262000231565b6200017d81620003e0565b50505062000840565b336001600160a01b03821603620001e05760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b0316158062000254575060608101516001600160a01b0316155b8062000261575080602001515b1562000280576040516306b7c75960e31b815260040160405180910390fd5b8051600280546020808501511515600160a01b026001600160a81b03199092166001600160a01b039485161791909117909155604080840151600380549185166001600160a01b0319928316179055606080860151600480549187169184169190911790556080808701516005805491881691909416179092558251808301845291516001600160401b0316825260a05185169382019390935260c05184168183015260e05190931691830191909152517fc7372d2d886367d7bb1b0e0708a5436f2c91d6963de210eb2dc1ec2ecd6d21f191620003d591849082516001600160401b031681526020808401516001600160a01b03908116828401526040858101518216818501526060958601518216868501528451821660808086019190915292850151151560a0850152840151811660c084015293830151841660e0830152909101519091166101008201526101200190565b60405180910390a150565b60005b81518110156200051f5760008282815181106200040457620004046200082a565b6020026020010151905060008383815181106200042557620004256200082a565b6020026020010151600001519050806001600160401b03166000036200046a5760405163c35aa79d60e01b81526001600160401b038216600482015260240162000083565b6001600160401b03818116600081815260066020908152604091829020868201518154600160481b600160e81b0319811669010000000000000000006001600160a01b03909316928302908117808555865192891691909816178152928301526801000000000000000090940460ff161515918101919091527fd5ad72bc37dc7a80a8b9b9df20500046fd7341adb1be2258a540466fdd7dcef59060600160405180910390a2505050806001019050620003e3565b5050565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b03811182821017156200055e576200055e62000523565b60405290565b604051601f8201601f191681016001600160401b03811182821017156200058f576200058f62000523565b604052919050565b80516001600160401b0381168114620005af57600080fd5b919050565b6001600160a01b0381168114620005ca57600080fd5b50565b600060a08284031215620005e057600080fd5b60405160a081016001600160401b038111828210171562000605576200060562000523565b806040525080915082516200061a81620005b4565b8152602083015180151581146200063057600080fd5b602082015260408301516200064581620005b4565b604082015260608301516200065a81620005b4565b606082015260808301516200066f81620005b4565b6080919091015292915050565b600082601f8301126200068e57600080fd5b815160206001600160401b03821115620006ac57620006ac62000523565b620006bc818360051b0162000564565b82815260069290921b84018101918181019086841115620006dc57600080fd5b8286015b84811015620007345760408189031215620006fb5760008081fd5b6200070562000539565b620007108262000597565b8152848201516200072181620005b4565b81860152835291830191604001620006e0565b509695505050505050565b60008060008385036101408112156200075757600080fd5b60808112156200076657600080fd5b50604051608081016001600160401b0380821183831017156200078d576200078d62000523565b816040526200079c8762000597565b835260208701519150620007b082620005b4565b81602084015260408701519150620007c882620005b4565b81604084015260608701519150620007e082620005b4565b816060840152829550620007f88860808901620005cd565b94506101208701519250808311156200081057600080fd5b505062000820868287016200067c565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b60805160a05160c05160e0516139e4620008b96000396000818161022c01528181610cfd0152611c290152600081816101f0015281816116240152611c020152600081816101b4015281816106080152611bd80152600081816101840152818161114b0152818161173f0152611bb401526139e46000f3fe608060405234801561001057600080fd5b50600436106101365760003560e01c80637437ff9f116100b2578063972b461211610081578063df0aa9e911610066578063df0aa9e914610557578063f2fde38b1461056a578063fbca3b741461057d57600080fd5b8063972b4612146104ea578063d77d5ed01461050a57600080fd5b80637437ff9f146103ee57806379ba5097146104985780638da5cb5b146104a05780639041be3d146104be57600080fd5b806327e936f1116101095780633a019940116100ee5780633a0199401461030f57806348a98aa4146103175780636def4ce71461034f57600080fd5b806327e936f1146102e957806334adf494146102fc57600080fd5b80630242cf601461013b57806306285c6914610150578063181f5a771461027f57806320487ded146102c8575b600080fd5b61014e6101493660046127df565b610590565b005b61026960408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16815250905090565b60405161027691906128a2565b60405180910390f35b6102bb6040518060400160405280601081526020017f4f6e52616d7020312e362e302d6465760000000000000000000000000000000081525081565b6040516102769190612967565b6102db6102d6366004612992565b6105a4565b604051908152602001610276565b61014e6102f7366004612a00565b61075d565b61014e61030a366004612a98565b61076e565b61014e610a8a565b61032a610325366004612b0d565b610cb5565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610276565b6103b261035d366004612b46565b67ffffffffffffffff9081166000908152600660205260409020549081169168010000000000000000820460ff16916901000000000000000000900473ffffffffffffffffffffffffffffffffffffffff1690565b6040805167ffffffffffffffff9094168452911515602084015273ffffffffffffffffffffffffffffffffffffffff1690820152606001610276565b61048b6040805160a081018252600080825260208201819052918101829052606081018290526080810191909152506040805160a08101825260025473ffffffffffffffffffffffffffffffffffffffff80821683527401000000000000000000000000000000000000000090910460ff161515602083015260035481169282019290925260045482166060820152600554909116608082015290565b6040516102769190612b63565b61014e610d6a565b60005473ffffffffffffffffffffffffffffffffffffffff1661032a565b6104d16104cc366004612b46565b610e67565b60405167ffffffffffffffff9091168152602001610276565b6104fd6104f8366004612b46565b610e90565b6040516102769190612bbc565b61032a610518366004612b46565b67ffffffffffffffff166000908152600660205260409020546901000000000000000000900473ffffffffffffffffffffffffffffffffffffffff1690565b6102db610565366004612c16565b610eb8565b61014e610578366004612c82565b61181c565b6104fd61058b366004612b46565b61182d565b610598611861565b6105a1816118e4565b50565b6040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815277ffffffffffffffff00000000000000000000000000000000608084901b16600482015260009073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690632cbc26bb90602401602060405180830381865afa15801561064f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106739190612c9f565b156106bb576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024015b60405180910390fd5b6002546040517fd8694ccd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063d8694ccd906107139086908690600401612dd0565b602060405180830381865afa158015610730573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107549190612f19565b90505b92915050565b610765611861565b6105a181611a5b565b60005473ffffffffffffffffffffffffffffffffffffffff1633146107de5760055473ffffffffffffffffffffffffffffffffffffffff1633146107de576040517f905d7d9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015610a855760008383838181106107fd576107fd612f32565b905060200281019061080f9190612f61565b61081890613012565b805167ffffffffffffffff1660009081526006602090815260409182902090830151815490151568010000000000000000027fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff909116178155908201515191925090156109d8578160200151156109975760005b826040015151811015610947576000836040015182815181106108b1576108b1612f32565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036109305783516040517f463258ff00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016106b2565b61093d6001840182611c8b565b505060010161088c565b50816000015167ffffffffffffffff167f330939f6eafe8bb516716892fe962ff19770570838686e6579dbc1cc51fc3281836040015160405161098a9190612bbc565b60405180910390a26109d8565b81516040517f463258ff00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016106b2565b60005b826060015151811015610a2457610a1b83606001518281518110610a0157610a01612f32565b602002602001015183600101611cad90919063ffffffff16565b506001016109db565b5060608201515115610a7b57816000015167ffffffffffffffff167fc237ec1921f855ccd5e9a5af9733f2d58943a5a8501ec5988e305d7a4d4215868360600151604051610a729190612bbc565b60405180910390a25b50506001016107e1565b505050565b600254604080517fcdc73d51000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163cdc73d5191600480830192869291908290030181865afa158015610af9573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610b3f91908101906130c3565b60045490915073ffffffffffffffffffffffffffffffffffffffff1660005b8251811015610a85576000838281518110610b7b57610b7b612f32565b60209081029190910101516040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915060009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa158015610bf6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c1a9190612f19565b90508015610cab57610c4373ffffffffffffffffffffffffffffffffffffffff83168583611ccf565b8173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f508d7d183612c18fc339b42618912b9fa3239f631dd7ec0671f950200a0fa66e83604051610ca291815260200190565b60405180910390a35b5050600101610b5e565b6040517fbbe4f6db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063bbe4f6db90602401602060405180830381865afa158015610d46573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107549190613152565b60015473ffffffffffffffffffffffffffffffffffffffff163314610deb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064016106b2565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b67ffffffffffffffff80821660009081526006602052604081205490916107579116600161319e565b67ffffffffffffffff8116600090815260066020526040902060609061075790600101611d5c565b60025460009074010000000000000000000000000000000000000000900460ff1615610f10576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905567ffffffffffffffff8516600090815260066020526040902073ffffffffffffffffffffffffffffffffffffffff8316610fb5576040517fa4ec747900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805468010000000000000000900460ff161561102657610fd86001820184611d70565b611026576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841660048201526024016106b2565b80546901000000000000000000900473ffffffffffffffffffffffffffffffffffffffff163314611083576040517f1c0a352900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60035473ffffffffffffffffffffffffffffffffffffffff168015611129576040517fe0a0e50600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82169063e0a0e506906110f6908a908a90600401612dd0565b600060405180830381600087803b15801561111057600080fd5b505af1158015611124573d6000803e3d6000fd5b505050505b50604080516101a081019091526000610100820181815267ffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811661012085015289811661014085015284549293928392916101608401918791879161119791166131bf565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905567ffffffffffffffff168152602001600067ffffffffffffffff1681525081526020018573ffffffffffffffffffffffffffffffffffffffff16815260200187806020019061120b91906131e6565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050509082525060200161124f88806131e6565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920182905250938552505060408051602081810183529381529284019290925250016112ab6080890160608a01612c82565b73ffffffffffffffffffffffffffffffffffffffff1681526020018681526020018780604001906112dc919061324b565b905067ffffffffffffffff8111156112f6576112f66126dc565b60405190808252806020026020018201604052801561135957816020015b6113466040518060a0016040528060608152602001606081526020016060815260200160008152602001606081525090565b8152602001906001900390816113145790505b5090529050600061136d604088018861324b565b808060200260200160405190810160405280939291908181526020016000905b828210156113b9576113aa604083028601368190038101906132b3565b8152602001906001019061138d565b5050505050905060005b6113d0604089018961324b565b9050811015611469576114408282815181106113ee576113ee612f32565b60209081029190910101518a6114048b806131e6565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508c9250611d9f915050565b8360e00151828151811061145657611456612f32565b60209081029190910101526001016113c3565b50600080600080600260000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166397d640a28d8d60600160208101906114c59190612c82565b8d8f80608001906114d691906131e6565b8c60e001518c6040518863ffffffff1660e01b81526004016114fe97969594939291906133ca565b600060405180830381865afa15801561151b573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261156191908101906134fc565b9296509094509250905061157b60808c0160608d01612c82565b73ffffffffffffffffffffffffffffffffffffffff167f075a2720282fdf622141dae0b048ef90a21a7e57c134c76912d19d006b3b3f6f856040516115c291815260200190565b60405180910390a282611696576040517fea458c0c00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8d16600482015273ffffffffffffffffffffffffffffffffffffffff8a811660248301527f0000000000000000000000000000000000000000000000000000000000000000169063ea458c0c906044016020604051808303816000875af115801561166d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061169191906135ef565b611699565b60005b865167ffffffffffffffff909116608091820152860182905260005b8660e0015151811015611709578181815181106116d4576116d4612f32565b60200260200101518760e0015182815181106116f2576116f2612f32565b6020908102919091010151608001526001016116b5565b50604080517f130ac867e79e2789f923760a88743d292acdf7002139a588206e2260f73f7321602082015267ffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811692820192909252908d16606082015230608082015261179990879060a001604051602081830303815290604052805190602001206120c5565b86515260405167ffffffffffffffff8d16907ff6e86ef8896c7a0d629406168f396e883280680c99e649b9e2d36466fbc9f9e5906117d890899061360c565b60405180910390a25050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1690555050905151925050505b949350505050565b611824611861565b6105a1816121c5565b60606040517f9e7177c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005473ffffffffffffffffffffffffffffffffffffffff1633146118e2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016106b2565b565b60005b8151811015611a5757600082828151811061190457611904612f32565b60200260200101519050600083838151811061192257611922612f32565b60200260200101516000015190508067ffffffffffffffff16600003611980576040517fc35aa79d00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff821660048201526024016106b2565b67ffffffffffffffff8181166000818152600660209081526040918290208682015181547fffffff0000000000000000000000000000000000000000ffffffffffffffffff8116690100000000000000000073ffffffffffffffffffffffffffffffffffffffff909316928302908117808555865192891691909816178152928301526801000000000000000090940460ff161515918101919091527fd5ad72bc37dc7a80a8b9b9df20500046fd7341adb1be2258a540466fdd7dcef59060600160405180910390a25050508060010190506118e7565b5050565b805173ffffffffffffffffffffffffffffffffffffffff161580611a975750606081015173ffffffffffffffffffffffffffffffffffffffff16155b80611aa3575080602001515b15611ada576040517f35be3ac800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160028054602080850151151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00000000000000000000000000000000000000000090921673ffffffffffffffffffffffffffffffffffffffff9485161791909117909155604080840151600380549185167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316179055606080860151600480549187169184169190911790556080808701516005805491881691909416179092558251918201835267ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001682527f00000000000000000000000000000000000000000000000000000000000000008516938201939093527f00000000000000000000000000000000000000000000000000000000000000008416818301527f000000000000000000000000000000000000000000000000000000000000000090931691830191909152517fc7372d2d886367d7bb1b0e0708a5436f2c91d6963de210eb2dc1ec2ecd6d21f191611c8091849061375a565b60405180910390a150565b60006107548373ffffffffffffffffffffffffffffffffffffffff84166122ba565b60006107548373ffffffffffffffffffffffffffffffffffffffff8416612309565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052610a85908490612403565b60606000611d698361250f565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515610754565b611dd16040518060a0016040528060608152602001606081526020016060815260200160008152602001606081525090565b8460200151600003611e0f576040517f5cf0444900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611e1f858760000151610cb5565b905073ffffffffffffffffffffffffffffffffffffffff81161580611eef57506040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527faff2afbf00000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff8216906301ffc9a790602401602060405180830381865afa158015611ec9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611eed9190612c9f565b155b15611f415785516040517fbf16aab600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911660048201526024016106b2565b60008173ffffffffffffffffffffffffffffffffffffffff16639a4575b96040518060a001604052808881526020018967ffffffffffffffff1681526020018773ffffffffffffffffffffffffffffffffffffffff1681526020018a6020015181526020018a6000015173ffffffffffffffffffffffffffffffffffffffff168152506040518263ffffffff1660e01b8152600401611fe09190613808565b6000604051808303816000875af1158015611fff573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052612045919081019061387e565b6040805160a0810190915273ffffffffffffffffffffffffffffffffffffffff841660c08201529091508060e0810160405160208183030381529060405281526020018260000151815260200182602001518152602001886020015181526020016040518060200160405280600081525081525092505050949350505050565b60008060001b82846020015185606001518660000151606001518760000151608001518860a001518960c001516040516020016121079695949392919061390f565b604051602081830303815290604052805190602001208560400151805190602001208660e0015160405160200161213e9190613970565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201206080808c0151805190840120928501989098529183019590955260608201939093529384015260a083015260c082015260e00160405160208183030381529060405280519060200120905092915050565b3373ffffffffffffffffffffffffffffffffffffffff821603612244576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016106b2565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600081815260018301602052604081205461230157508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610757565b506000610757565b600081815260018301602052604081205480156123f257600061232d600183613983565b855490915060009061234190600190613983565b90508082146123a657600086600001828154811061236157612361612f32565b906000526020600020015490508087600001848154811061238457612384612f32565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806123b7576123b7613996565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610757565b6000915050610757565b5092915050565b6000612465826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff1661256b9092919063ffffffff16565b805190915015610a8557808060200190518101906124839190612c9f565b610a85576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016106b2565b60608160000180548060200260200160405190810160405280929190818152602001828054801561255f57602002820191906000526020600020905b81548152602001906001019080831161254b575b50505050509050919050565b60606118148484600085856000808673ffffffffffffffffffffffffffffffffffffffff16858760405161259f91906139c5565b60006040518083038185875af1925050503d80600081146125dc576040519150601f19603f3d011682016040523d82523d6000602084013e6125e1565b606091505b50915091506125f2878383876125fd565b979650505050505050565b6060831561269357825160000361268c5773ffffffffffffffffffffffffffffffffffffffff85163b61268c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016106b2565b5081611814565b61181483838151156126a85781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106b29190612967565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561272e5761272e6126dc565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561277b5761277b6126dc565b604052919050565b600067ffffffffffffffff82111561279d5761279d6126dc565b5060051b60200190565b67ffffffffffffffff811681146105a157600080fd5b73ffffffffffffffffffffffffffffffffffffffff811681146105a157600080fd5b600060208083850312156127f257600080fd5b823567ffffffffffffffff81111561280957600080fd5b8301601f8101851361281a57600080fd5b803561282d61282882612783565b612734565b81815260069190911b8201830190838101908783111561284c57600080fd5b928401925b828410156125f2576040848903121561286a5760008081fd5b61287261270b565b843561287d816127a7565b81528486013561288c816127bd565b8187015282526040939093019290840190612851565b60808101610757828467ffffffffffffffff8151168252602081015173ffffffffffffffffffffffffffffffffffffffff808216602085015280604084015116604085015280606084015116606085015250505050565b60005b838110156129145781810151838201526020016128fc565b50506000910152565b600081518084526129358160208601602086016128f9565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610754602083018461291d565b600060a0828403121561298c57600080fd5b50919050565b600080604083850312156129a557600080fd5b82356129b0816127a7565b9150602083013567ffffffffffffffff8111156129cc57600080fd5b6129d88582860161297a565b9150509250929050565b80356129ed816127bd565b919050565b80151581146105a157600080fd5b600060a08284031215612a1257600080fd5b60405160a0810181811067ffffffffffffffff82111715612a3557612a356126dc565b6040528235612a43816127bd565b81526020830135612a53816129f2565b60208201526040830135612a66816127bd565b60408201526060830135612a79816127bd565b60608201526080830135612a8c816127bd565b60808201529392505050565b60008060208385031215612aab57600080fd5b823567ffffffffffffffff80821115612ac357600080fd5b818501915085601f830112612ad757600080fd5b813581811115612ae657600080fd5b8660208260051b8501011115612afb57600080fd5b60209290920196919550909350505050565b60008060408385031215612b2057600080fd5b8235612b2b816127a7565b91506020830135612b3b816127bd565b809150509250929050565b600060208284031215612b5857600080fd5b8135611d69816127a7565b60a08101610757828473ffffffffffffffffffffffffffffffffffffffff808251168352602082015115156020840152806040830151166040840152806060830151166060840152806080830151166080840152505050565b6020808252825182820181905260009190848201906040850190845b81811015612c0a57835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101612bd8565b50909695505050505050565b60008060008060808587031215612c2c57600080fd5b8435612c37816127a7565b9350602085013567ffffffffffffffff811115612c5357600080fd5b612c5f8782880161297a565b935050604085013591506060850135612c77816127bd565b939692955090935050565b600060208284031215612c9457600080fd5b8135611d69816127bd565b600060208284031215612cb157600080fd5b8151611d69816129f2565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112612cf157600080fd5b830160208101925035905067ffffffffffffffff811115612d1157600080fd5b803603821315612d2057600080fd5b9250929050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b8183526000602080850194508260005b85811015612dc5578135612d93816127bd565b73ffffffffffffffffffffffffffffffffffffffff168752818301358388015260409687019690910190600101612d80565b509495945050505050565b600067ffffffffffffffff808516835260406020840152612df18485612cbc565b60a06040860152612e0660e086018284612d27565b915050612e166020860186612cbc565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc080878503016060880152612e4c848385612d27565b9350604088013592507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1883603018312612e8557600080fd5b60209288019283019235915084821115612e9e57600080fd5b8160061b3603831315612eb057600080fd5b80878503016080880152612ec5848385612d70565b9450612ed3606089016129e2565b73ffffffffffffffffffffffffffffffffffffffff811660a08901529350612efe6080890189612cbc565b94509250808786030160c088015250506125f2838383612d27565b600060208284031215612f2b57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81833603018112612f9557600080fd5b9190910192915050565b600082601f830112612fb057600080fd5b81356020612fc061282883612783565b8083825260208201915060208460051b870101935086841115612fe257600080fd5b602086015b84811015613007578035612ffa816127bd565b8352918301918301612fe7565b509695505050505050565b60006080823603121561302457600080fd5b6040516080810167ffffffffffffffff8282108183111715613048576130486126dc565b8160405284359150613059826127a7565b90825260208401359061306b826129f2565b816020840152604085013591508082111561308557600080fd5b61309136838701612f9f565b604084015260608501359150808211156130aa57600080fd5b506130b736828601612f9f565b60608301525092915050565b600060208083850312156130d657600080fd5b825167ffffffffffffffff8111156130ed57600080fd5b8301601f810185136130fe57600080fd5b805161310c61282882612783565b81815260059190911b8201830190838101908783111561312b57600080fd5b928401925b828410156125f2578351613143816127bd565b82529284019290840190613130565b60006020828403121561316457600080fd5b8151611d69816127bd565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b67ffffffffffffffff8181168382160190808211156123fc576123fc61316f565b600067ffffffffffffffff8083168181036131dc576131dc61316f565b6001019392505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261321b57600080fd5b83018035915067ffffffffffffffff82111561323657600080fd5b602001915036819003821315612d2057600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261328057600080fd5b83018035915067ffffffffffffffff82111561329b57600080fd5b6020019150600681901b3603821315612d2057600080fd5b6000604082840312156132c557600080fd5b6132cd61270b565b82356132d8816127bd565b81526020928301359281019290925250919050565b600082825180855260208086019550808260051b84010181860160005b848110156133bd577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018952815160a0815181865261334e8287018261291d565b9150508582015185820387870152613366828261291d565b91505060408083015186830382880152613380838261291d565b925050506060808301518187015250608080830151925085820381870152506133a9818361291d565b9a86019a945050509083019060010161330a565b5090979650505050505050565b67ffffffffffffffff881681526000602073ffffffffffffffffffffffffffffffffffffffff808a1682850152604089604086015260c0606086015261341460c08601898b612d27565b858103608087015261342681896132ed565b86810360a0880152875180825285890192509085019060005b8181101561346657835180518716845287015187840152928601929184019160010161343f565b50909e9d5050505050505050505050505050565b600082601f83011261348b57600080fd5b815167ffffffffffffffff8111156134a5576134a56126dc565b6134d660207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601612734565b8181528460208386010111156134eb57600080fd5b6118148260208301602087016128f9565b6000806000806080858703121561351257600080fd5b84519350602080860151613525816129f2565b604087015190945067ffffffffffffffff8082111561354357600080fd5b61354f89838a0161347a565b9450606088015191508082111561356557600080fd5b818801915088601f83011261357957600080fd5b815161358761282882612783565b81815260059190911b8301840190848101908b8311156135a657600080fd5b8585015b838110156135de578051858111156135c25760008081fd5b6135d08e89838a010161347a565b8452509186019186016135aa565b50989b979a50959850505050505050565b60006020828403121561360157600080fd5b8151611d69816127a7565b6020815261365d60208201835180518252602081015167ffffffffffffffff808216602085015280604084015116604085015280606084015116606085015280608084015116608085015250505050565b6000602083015161368660c084018273ffffffffffffffffffffffffffffffffffffffff169052565b5060408301516101808060e08501526136a36101a085018361291d565b915060608501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe080868503016101008701526136e0848361291d565b93506080870151915080868503016101208701526136fe848361291d565b935060a0870151915061372a61014087018373ffffffffffffffffffffffffffffffffffffffff169052565b60c087015161016087015260e087015191508086850301838701525061375083826132ed565b9695505050505050565b61012081016137b2828567ffffffffffffffff8151168252602081015173ffffffffffffffffffffffffffffffffffffffff808216602085015280604084015116604085015280606084015116606085015250505050565b825173ffffffffffffffffffffffffffffffffffffffff9081166080848101919091526020850151151560a08501526040850151821660c08501526060850151821660e085015284015116610100830152611d69565b602081526000825160a0602084015261382460c084018261291d565b905067ffffffffffffffff6020850151166040840152604084015173ffffffffffffffffffffffffffffffffffffffff8082166060860152606086015160808601528060808701511660a086015250508091505092915050565b60006020828403121561389057600080fd5b815167ffffffffffffffff808211156138a857600080fd5b90830190604082860312156138bc57600080fd5b6138c461270b565b8251828111156138d357600080fd5b6138df8782860161347a565b8252506020830151828111156138f457600080fd5b6139008782860161347a565b60208301525095945050505050565b600073ffffffffffffffffffffffffffffffffffffffff808916835260c0602084015261393f60c084018961291d565b67ffffffffffffffff97881660408501529590961660608301525091909316608082015260a0019190915292915050565b60208152600061075460208301846132ed565b818103818111156107575761075761316f565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b60008251612f958184602087016128f956fea164736f6c6343000818000a", + Bin: "0x6101006040523480156200001257600080fd5b506040516200428d3803806200428d83398101604081905262000035916200073f565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf8162000186565b505083516001600160401b031615905080620000e6575060208301516001600160a01b0316155b80620000fd575060408301516001600160a01b0316155b8062000114575060608301516001600160a01b0316155b1562000133576040516306b7c75960e31b815260040160405180910390fd5b82516001600160401b031660805260208301516001600160a01b0390811660a0526040840151811660c05260608401511660e052620001728262000231565b6200017d81620003e0565b50505062000840565b336001600160a01b03821603620001e05760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b0316158062000254575060608101516001600160a01b0316155b8062000261575080602001515b1562000280576040516306b7c75960e31b815260040160405180910390fd5b8051600280546020808501511515600160a01b026001600160a81b03199092166001600160a01b039485161791909117909155604080840151600380549185166001600160a01b0319928316179055606080860151600480549187169184169190911790556080808701516005805491881691909416179092558251808301845291516001600160401b0316825260a05185169382019390935260c05184168183015260e05190931691830191909152517fc7372d2d886367d7bb1b0e0708a5436f2c91d6963de210eb2dc1ec2ecd6d21f191620003d591849082516001600160401b031681526020808401516001600160a01b03908116828401526040858101518216818501526060958601518216868501528451821660808086019190915292850151151560a0850152840151811660c084015293830151841660e0830152909101519091166101008201526101200190565b60405180910390a150565b60005b81518110156200051f5760008282815181106200040457620004046200082a565b6020026020010151905060008383815181106200042557620004256200082a565b6020026020010151600001519050806001600160401b03166000036200046a5760405163c35aa79d60e01b81526001600160401b038216600482015260240162000083565b6001600160401b03818116600081815260066020908152604091829020868201518154600160481b600160e81b0319811669010000000000000000006001600160a01b03909316928302908117808555865192891691909816178152928301526801000000000000000090940460ff161515918101919091527fd5ad72bc37dc7a80a8b9b9df20500046fd7341adb1be2258a540466fdd7dcef59060600160405180910390a2505050806001019050620003e3565b5050565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b03811182821017156200055e576200055e62000523565b60405290565b604051601f8201601f191681016001600160401b03811182821017156200058f576200058f62000523565b604052919050565b80516001600160401b0381168114620005af57600080fd5b919050565b6001600160a01b0381168114620005ca57600080fd5b50565b600060a08284031215620005e057600080fd5b60405160a081016001600160401b038111828210171562000605576200060562000523565b806040525080915082516200061a81620005b4565b8152602083015180151581146200063057600080fd5b602082015260408301516200064581620005b4565b604082015260608301516200065a81620005b4565b606082015260808301516200066f81620005b4565b6080919091015292915050565b600082601f8301126200068e57600080fd5b815160206001600160401b03821115620006ac57620006ac62000523565b620006bc818360051b0162000564565b82815260069290921b84018101918181019086841115620006dc57600080fd5b8286015b84811015620007345760408189031215620006fb5760008081fd5b6200070562000539565b620007108262000597565b8152848201516200072181620005b4565b81860152835291830191604001620006e0565b509695505050505050565b60008060008385036101408112156200075757600080fd5b60808112156200076657600080fd5b50604051608081016001600160401b0380821183831017156200078d576200078d62000523565b816040526200079c8762000597565b835260208701519150620007b082620005b4565b81602084015260408701519150620007c882620005b4565b81604084015260608701519150620007e082620005b4565b816060840152829550620007f88860808901620005cd565b94506101208701519250808311156200081057600080fd5b505062000820868287016200067c565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b60805160a05160c05160e0516139d4620008b96000396000818161022c01528181610cfd0152611c290152600081816101f0015281816116240152611c020152600081816101b4015281816106080152611bd80152600081816101840152818161114b0152818161173f0152611bb401526139d46000f3fe608060405234801561001057600080fd5b50600436106101365760003560e01c80637437ff9f116100b2578063972b461211610081578063df0aa9e911610066578063df0aa9e914610557578063f2fde38b1461056a578063fbca3b741461057d57600080fd5b8063972b4612146104ea578063d77d5ed01461050a57600080fd5b80637437ff9f146103ee57806379ba5097146104985780638da5cb5b146104a05780639041be3d146104be57600080fd5b806327e936f1116101095780633a019940116100ee5780633a0199401461030f57806348a98aa4146103175780636def4ce71461034f57600080fd5b806327e936f1146102e957806334adf494146102fc57600080fd5b80630242cf601461013b57806306285c6914610150578063181f5a771461027f57806320487ded146102c8575b600080fd5b61014e610149366004612830565b610590565b005b61026960408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16815250905090565b60405161027691906128f3565b60405180910390f35b6102bb6040518060400160405280601081526020017f4f6e52616d7020312e362e302d6465760000000000000000000000000000000081525081565b60405161027691906129b8565b6102db6102d63660046129e3565b6105a4565b604051908152602001610276565b61014e6102f7366004612a51565b61075d565b61014e61030a366004612ae9565b61076e565b61014e610a8a565b61032a610325366004612b5e565b610cb5565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610276565b6103b261035d366004612b97565b67ffffffffffffffff9081166000908152600660205260409020549081169168010000000000000000820460ff16916901000000000000000000900473ffffffffffffffffffffffffffffffffffffffff1690565b6040805167ffffffffffffffff9094168452911515602084015273ffffffffffffffffffffffffffffffffffffffff1690820152606001610276565b61048b6040805160a081018252600080825260208201819052918101829052606081018290526080810191909152506040805160a08101825260025473ffffffffffffffffffffffffffffffffffffffff80821683527401000000000000000000000000000000000000000090910460ff161515602083015260035481169282019290925260045482166060820152600554909116608082015290565b6040516102769190612bb4565b61014e610d6a565b60005473ffffffffffffffffffffffffffffffffffffffff1661032a565b6104d16104cc366004612b97565b610e67565b60405167ffffffffffffffff9091168152602001610276565b6104fd6104f8366004612b97565b610e90565b6040516102769190612c0d565b61032a610518366004612b97565b67ffffffffffffffff166000908152600660205260409020546901000000000000000000900473ffffffffffffffffffffffffffffffffffffffff1690565b6102db610565366004612c67565b610eb8565b61014e610578366004612cd3565b61181c565b6104fd61058b366004612b97565b61182d565b610598611861565b6105a1816118e4565b50565b6040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815277ffffffffffffffff00000000000000000000000000000000608084901b16600482015260009073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690632cbc26bb90602401602060405180830381865afa15801561064f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106739190612cf0565b156106bb576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024015b60405180910390fd5b6002546040517fd8694ccd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063d8694ccd906107139086908690600401612e21565b602060405180830381865afa158015610730573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107549190612f6a565b90505b92915050565b610765611861565b6105a181611a5b565b60005473ffffffffffffffffffffffffffffffffffffffff1633146107de5760055473ffffffffffffffffffffffffffffffffffffffff1633146107de576040517f905d7d9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015610a855760008383838181106107fd576107fd612f83565b905060200281019061080f9190612fb2565b61081890613063565b805167ffffffffffffffff1660009081526006602090815260409182902090830151815490151568010000000000000000027fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff909116178155908201515191925090156109d8578160200151156109975760005b826040015151811015610947576000836040015182815181106108b1576108b1612f83565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036109305783516040517f463258ff00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016106b2565b61093d6001840182611c8b565b505060010161088c565b50816000015167ffffffffffffffff167f330939f6eafe8bb516716892fe962ff19770570838686e6579dbc1cc51fc3281836040015160405161098a9190612c0d565b60405180910390a26109d8565b81516040517f463258ff00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016106b2565b60005b826060015151811015610a2457610a1b83606001518281518110610a0157610a01612f83565b602002602001015183600101611cad90919063ffffffff16565b506001016109db565b5060608201515115610a7b57816000015167ffffffffffffffff167fc237ec1921f855ccd5e9a5af9733f2d58943a5a8501ec5988e305d7a4d4215868360600151604051610a729190612c0d565b60405180910390a25b50506001016107e1565b505050565b600254604080517fcdc73d51000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163cdc73d5191600480830192869291908290030181865afa158015610af9573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610b3f9190810190613114565b60045490915073ffffffffffffffffffffffffffffffffffffffff1660005b8251811015610a85576000838281518110610b7b57610b7b612f83565b60209081029190910101516040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915060009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa158015610bf6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c1a9190612f6a565b90508015610cab57610c4373ffffffffffffffffffffffffffffffffffffffff83168583611ccf565b8173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f508d7d183612c18fc339b42618912b9fa3239f631dd7ec0671f950200a0fa66e83604051610ca291815260200190565b60405180910390a35b5050600101610b5e565b6040517fbbe4f6db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063bbe4f6db90602401602060405180830381865afa158015610d46573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061075491906131a3565b60015473ffffffffffffffffffffffffffffffffffffffff163314610deb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064016106b2565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b67ffffffffffffffff8082166000908152600660205260408120549091610757911660016131ef565b67ffffffffffffffff8116600090815260066020526040902060609061075790600101611d5c565b60025460009074010000000000000000000000000000000000000000900460ff1615610f10576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905567ffffffffffffffff8516600090815260066020526040902073ffffffffffffffffffffffffffffffffffffffff8316610fb5576040517fa4ec747900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805468010000000000000000900460ff161561102657610fd86001820184611d70565b611026576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841660048201526024016106b2565b80546901000000000000000000900473ffffffffffffffffffffffffffffffffffffffff163314611083576040517f1c0a352900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60035473ffffffffffffffffffffffffffffffffffffffff168015611129576040517fe0a0e50600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82169063e0a0e506906110f6908a908a90600401612e21565b600060405180830381600087803b15801561111057600080fd5b505af1158015611124573d6000803e3d6000fd5b505050505b50604080516101a081019091526000610100820181815267ffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000081166101208501528981166101408501528454929392839291610160840191879187916111979116613210565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905567ffffffffffffffff168152602001600067ffffffffffffffff1681525081526020018573ffffffffffffffffffffffffffffffffffffffff16815260200187806020019061120b9190613237565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050509082525060200161124f8880613237565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920182905250938552505060408051602081810183529381529284019290925250016112ab6080890160608a01612cd3565b73ffffffffffffffffffffffffffffffffffffffff1681526020018681526020018780604001906112dc919061329c565b905067ffffffffffffffff8111156112f6576112f661272d565b60405190808252806020026020018201604052801561135957816020015b6113466040518060a0016040528060608152602001606081526020016060815260200160008152602001606081525090565b8152602001906001900390816113145790505b5090529050600061136d604088018861329c565b808060200260200160405190810160405280939291908181526020016000905b828210156113b9576113aa60408302860136819003810190613304565b8152602001906001019061138d565b5050505050905060005b6113d0604089018961329c565b9050811015611469576114408282815181106113ee576113ee612f83565b60209081029190910101518a6114048b80613237565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508c9250611d9f915050565b8360e00151828151811061145657611456612f83565b60209081029190910101526001016113c3565b50600080600080600260000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166397d640a28d8d60600160208101906114c59190612cd3565b8d8f80608001906114d69190613237565b8c60e001518c6040518863ffffffff1660e01b81526004016114fe979695949392919061341b565b600060405180830381865afa15801561151b573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611561919081019061354d565b9296509094509250905061157b60808c0160608d01612cd3565b73ffffffffffffffffffffffffffffffffffffffff167f075a2720282fdf622141dae0b048ef90a21a7e57c134c76912d19d006b3b3f6f856040516115c291815260200190565b60405180910390a282611696576040517fea458c0c00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8d16600482015273ffffffffffffffffffffffffffffffffffffffff8a811660248301527f0000000000000000000000000000000000000000000000000000000000000000169063ea458c0c906044016020604051808303816000875af115801561166d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116919190613640565b611699565b60005b865167ffffffffffffffff909116608091820152860182905260005b8660e0015151811015611709578181815181106116d4576116d4612f83565b60200260200101518760e0015182815181106116f2576116f2612f83565b6020908102919091010151608001526001016116b5565b50604080517f130ac867e79e2789f923760a88743d292acdf7002139a588206e2260f73f7321602082015267ffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811692820192909252908d16606082015230608082015261179990879060a001604051602081830303815290604052805190602001206120c5565b86515260405167ffffffffffffffff8d16907ff6e86ef8896c7a0d629406168f396e883280680c99e649b9e2d36466fbc9f9e5906117d890899061365d565b60405180910390a25050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1690555050905151925050505b949350505050565b611824611861565b6105a181612216565b60606040517f9e7177c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005473ffffffffffffffffffffffffffffffffffffffff1633146118e2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016106b2565b565b60005b8151811015611a5757600082828151811061190457611904612f83565b60200260200101519050600083838151811061192257611922612f83565b60200260200101516000015190508067ffffffffffffffff16600003611980576040517fc35aa79d00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff821660048201526024016106b2565b67ffffffffffffffff8181166000818152600660209081526040918290208682015181547fffffff0000000000000000000000000000000000000000ffffffffffffffffff8116690100000000000000000073ffffffffffffffffffffffffffffffffffffffff909316928302908117808555865192891691909816178152928301526801000000000000000090940460ff161515918101919091527fd5ad72bc37dc7a80a8b9b9df20500046fd7341adb1be2258a540466fdd7dcef59060600160405180910390a25050508060010190506118e7565b5050565b805173ffffffffffffffffffffffffffffffffffffffff161580611a975750606081015173ffffffffffffffffffffffffffffffffffffffff16155b80611aa3575080602001515b15611ada576040517f35be3ac800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160028054602080850151151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00000000000000000000000000000000000000000090921673ffffffffffffffffffffffffffffffffffffffff9485161791909117909155604080840151600380549185167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316179055606080860151600480549187169184169190911790556080808701516005805491881691909416179092558251918201835267ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001682527f00000000000000000000000000000000000000000000000000000000000000008516938201939093527f00000000000000000000000000000000000000000000000000000000000000008416818301527f000000000000000000000000000000000000000000000000000000000000000090931691830191909152517fc7372d2d886367d7bb1b0e0708a5436f2c91d6963de210eb2dc1ec2ecd6d21f191611c809184906137ab565b60405180910390a150565b60006107548373ffffffffffffffffffffffffffffffffffffffff841661230b565b60006107548373ffffffffffffffffffffffffffffffffffffffff841661235a565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052610a85908490612454565b60606000611d6983612560565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515610754565b611dd16040518060a0016040528060608152602001606081526020016060815260200160008152602001606081525090565b8460200151600003611e0f576040517f5cf0444900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611e1f858760000151610cb5565b905073ffffffffffffffffffffffffffffffffffffffff81161580611eef57506040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527faff2afbf00000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff8216906301ffc9a790602401602060405180830381865afa158015611ec9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611eed9190612cf0565b155b15611f415785516040517fbf16aab600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911660048201526024016106b2565b60008173ffffffffffffffffffffffffffffffffffffffff16639a4575b96040518060a001604052808881526020018967ffffffffffffffff1681526020018773ffffffffffffffffffffffffffffffffffffffff1681526020018a6020015181526020018a6000015173ffffffffffffffffffffffffffffffffffffffff168152506040518263ffffffff1660e01b8152600401611fe09190613859565b6000604051808303816000875af1158015611fff573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261204591908101906138cf565b6040805160a0810190915273ffffffffffffffffffffffffffffffffffffffff841660c08201529091508060e0810160405160208183030381529060405281526020018260000151815260200182602001518152602001886020015181526020016040518060200160405280600081525081525092505050949350505050565b60008060001b8284602001518560000151606001518660000151608001518760a001518860c0015160405160200161214395949392919073ffffffffffffffffffffffffffffffffffffffff958616815267ffffffffffffffff94851660208201529290931660408301529092166060830152608082015260a00190565b604051602081830303815290604052805190602001208560600151805190602001208660400151805190602001208760e001516040516020016121869190613960565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201206080808d0151805190840120928501999099529183019690965260608201949094529485019190915260a084015260c083015260e08201526101000160405160208183030381529060405280519060200120905092915050565b3373ffffffffffffffffffffffffffffffffffffffff821603612295576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016106b2565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600081815260018301602052604081205461235257508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610757565b506000610757565b6000818152600183016020526040812054801561244357600061237e600183613973565b855490915060009061239290600190613973565b90508082146123f75760008660000182815481106123b2576123b2612f83565b90600052602060002001549050808760000184815481106123d5576123d5612f83565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061240857612408613986565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610757565b6000915050610757565b5092915050565b60006124b6826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166125bc9092919063ffffffff16565b805190915015610a8557808060200190518101906124d49190612cf0565b610a85576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016106b2565b6060816000018054806020026020016040519081016040528092919081815260200182805480156125b057602002820191906000526020600020905b81548152602001906001019080831161259c575b50505050509050919050565b60606118148484600085856000808673ffffffffffffffffffffffffffffffffffffffff1685876040516125f091906139b5565b60006040518083038185875af1925050503d806000811461262d576040519150601f19603f3d011682016040523d82523d6000602084013e612632565b606091505b50915091506126438783838761264e565b979650505050505050565b606083156126e45782516000036126dd5773ffffffffffffffffffffffffffffffffffffffff85163b6126dd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016106b2565b5081611814565b61181483838151156126f95781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106b291906129b8565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561277f5761277f61272d565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156127cc576127cc61272d565b604052919050565b600067ffffffffffffffff8211156127ee576127ee61272d565b5060051b60200190565b67ffffffffffffffff811681146105a157600080fd5b73ffffffffffffffffffffffffffffffffffffffff811681146105a157600080fd5b6000602080838503121561284357600080fd5b823567ffffffffffffffff81111561285a57600080fd5b8301601f8101851361286b57600080fd5b803561287e612879826127d4565b612785565b81815260069190911b8201830190838101908783111561289d57600080fd5b928401925b8284101561264357604084890312156128bb5760008081fd5b6128c361275c565b84356128ce816127f8565b8152848601356128dd8161280e565b81870152825260409390930192908401906128a2565b60808101610757828467ffffffffffffffff8151168252602081015173ffffffffffffffffffffffffffffffffffffffff808216602085015280604084015116604085015280606084015116606085015250505050565b60005b8381101561296557818101518382015260200161294d565b50506000910152565b6000815180845261298681602086016020860161294a565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610754602083018461296e565b600060a082840312156129dd57600080fd5b50919050565b600080604083850312156129f657600080fd5b8235612a01816127f8565b9150602083013567ffffffffffffffff811115612a1d57600080fd5b612a29858286016129cb565b9150509250929050565b8035612a3e8161280e565b919050565b80151581146105a157600080fd5b600060a08284031215612a6357600080fd5b60405160a0810181811067ffffffffffffffff82111715612a8657612a8661272d565b6040528235612a948161280e565b81526020830135612aa481612a43565b60208201526040830135612ab78161280e565b60408201526060830135612aca8161280e565b60608201526080830135612add8161280e565b60808201529392505050565b60008060208385031215612afc57600080fd5b823567ffffffffffffffff80821115612b1457600080fd5b818501915085601f830112612b2857600080fd5b813581811115612b3757600080fd5b8660208260051b8501011115612b4c57600080fd5b60209290920196919550909350505050565b60008060408385031215612b7157600080fd5b8235612b7c816127f8565b91506020830135612b8c8161280e565b809150509250929050565b600060208284031215612ba957600080fd5b8135611d69816127f8565b60a08101610757828473ffffffffffffffffffffffffffffffffffffffff808251168352602082015115156020840152806040830151166040840152806060830151166060840152806080830151166080840152505050565b6020808252825182820181905260009190848201906040850190845b81811015612c5b57835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101612c29565b50909695505050505050565b60008060008060808587031215612c7d57600080fd5b8435612c88816127f8565b9350602085013567ffffffffffffffff811115612ca457600080fd5b612cb0878288016129cb565b935050604085013591506060850135612cc88161280e565b939692955090935050565b600060208284031215612ce557600080fd5b8135611d698161280e565b600060208284031215612d0257600080fd5b8151611d6981612a43565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112612d4257600080fd5b830160208101925035905067ffffffffffffffff811115612d6257600080fd5b803603821315612d7157600080fd5b9250929050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b8183526000602080850194508260005b85811015612e16578135612de48161280e565b73ffffffffffffffffffffffffffffffffffffffff168752818301358388015260409687019690910190600101612dd1565b509495945050505050565b600067ffffffffffffffff808516835260406020840152612e428485612d0d565b60a06040860152612e5760e086018284612d78565b915050612e676020860186612d0d565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc080878503016060880152612e9d848385612d78565b9350604088013592507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1883603018312612ed657600080fd5b60209288019283019235915084821115612eef57600080fd5b8160061b3603831315612f0157600080fd5b80878503016080880152612f16848385612dc1565b9450612f2460608901612a33565b73ffffffffffffffffffffffffffffffffffffffff811660a08901529350612f4f6080890189612d0d565b94509250808786030160c08801525050612643838383612d78565b600060208284031215612f7c57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81833603018112612fe657600080fd5b9190910192915050565b600082601f83011261300157600080fd5b81356020613011612879836127d4565b8083825260208201915060208460051b87010193508684111561303357600080fd5b602086015b8481101561305857803561304b8161280e565b8352918301918301613038565b509695505050505050565b60006080823603121561307557600080fd5b6040516080810167ffffffffffffffff82821081831117156130995761309961272d565b81604052843591506130aa826127f8565b9082526020840135906130bc82612a43565b81602084015260408501359150808211156130d657600080fd5b6130e236838701612ff0565b604084015260608501359150808211156130fb57600080fd5b5061310836828601612ff0565b60608301525092915050565b6000602080838503121561312757600080fd5b825167ffffffffffffffff81111561313e57600080fd5b8301601f8101851361314f57600080fd5b805161315d612879826127d4565b81815260059190911b8201830190838101908783111561317c57600080fd5b928401925b828410156126435783516131948161280e565b82529284019290840190613181565b6000602082840312156131b557600080fd5b8151611d698161280e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b67ffffffffffffffff81811683821601908082111561244d5761244d6131c0565b600067ffffffffffffffff80831681810361322d5761322d6131c0565b6001019392505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261326c57600080fd5b83018035915067ffffffffffffffff82111561328757600080fd5b602001915036819003821315612d7157600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126132d157600080fd5b83018035915067ffffffffffffffff8211156132ec57600080fd5b6020019150600681901b3603821315612d7157600080fd5b60006040828403121561331657600080fd5b61331e61275c565b82356133298161280e565b81526020928301359281019290925250919050565b600082825180855260208086019550808260051b84010181860160005b8481101561340e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018952815160a0815181865261339f8287018261296e565b91505085820151858203878701526133b7828261296e565b915050604080830151868303828801526133d1838261296e565b925050506060808301518187015250608080830151925085820381870152506133fa818361296e565b9a86019a945050509083019060010161335b565b5090979650505050505050565b67ffffffffffffffff881681526000602073ffffffffffffffffffffffffffffffffffffffff808a1682850152604089604086015260c0606086015261346560c08601898b612d78565b8581036080870152613477818961333e565b86810360a0880152875180825285890192509085019060005b818110156134b7578351805187168452870151878401529286019291840191600101613490565b50909e9d5050505050505050505050505050565b600082601f8301126134dc57600080fd5b815167ffffffffffffffff8111156134f6576134f661272d565b61352760207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601612785565b81815284602083860101111561353c57600080fd5b61181482602083016020870161294a565b6000806000806080858703121561356357600080fd5b8451935060208086015161357681612a43565b604087015190945067ffffffffffffffff8082111561359457600080fd5b6135a089838a016134cb565b945060608801519150808211156135b657600080fd5b818801915088601f8301126135ca57600080fd5b81516135d8612879826127d4565b81815260059190911b8301840190848101908b8311156135f757600080fd5b8585015b8381101561362f578051858111156136135760008081fd5b6136218e89838a01016134cb565b8452509186019186016135fb565b50989b979a50959850505050505050565b60006020828403121561365257600080fd5b8151611d69816127f8565b602081526136ae60208201835180518252602081015167ffffffffffffffff808216602085015280604084015116604085015280606084015116606085015280608084015116608085015250505050565b600060208301516136d760c084018273ffffffffffffffffffffffffffffffffffffffff169052565b5060408301516101808060e08501526136f46101a085018361296e565b915060608501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08086850301610100870152613731848361296e565b935060808701519150808685030161012087015261374f848361296e565b935060a0870151915061377b61014087018373ffffffffffffffffffffffffffffffffffffffff169052565b60c087015161016087015260e08701519150808685030183870152506137a1838261333e565b9695505050505050565b6101208101613803828567ffffffffffffffff8151168252602081015173ffffffffffffffffffffffffffffffffffffffff808216602085015280604084015116604085015280606084015116606085015250505050565b825173ffffffffffffffffffffffffffffffffffffffff9081166080848101919091526020850151151560a08501526040850151821660c08501526060850151821660e085015284015116610100830152611d69565b602081526000825160a0602084015261387560c084018261296e565b905067ffffffffffffffff6020850151166040840152604084015173ffffffffffffffffffffffffffffffffffffffff8082166060860152606086015160808601528060808701511660a086015250508091505092915050565b6000602082840312156138e157600080fd5b815167ffffffffffffffff808211156138f957600080fd5b908301906040828603121561390d57600080fd5b61391561275c565b82518281111561392457600080fd5b613930878286016134cb565b82525060208301518281111561394557600080fd5b613951878286016134cb565b60208301525095945050505050565b602081526000610754602083018461333e565b81810381811115610757576107576131c0565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b60008251612fe681846020870161294a56fea164736f6c6343000818000a", } var OnRampABI = OnRampMetaData.ABI diff --git a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt index 9eeee161c2..cbd6b1cd5a 100644 --- a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -16,7 +16,7 @@ fee_quoter: ../../../contracts/solc/v0.8.24/FeeQuoter/FeeQuoter.abi ../../../con lock_release_token_pool: ../../../contracts/solc/v0.8.24/LockReleaseTokenPool/LockReleaseTokenPool.abi ../../../contracts/solc/v0.8.24/LockReleaseTokenPool/LockReleaseTokenPool.bin e6a8ec9e8faccb1da7d90e0f702ed72975964f97dc3222b54cfcca0a0ba3fea2 lock_release_token_pool_and_proxy: ../../../contracts/solc/v0.8.24/LockReleaseTokenPoolAndProxy/LockReleaseTokenPoolAndProxy.abi ../../../contracts/solc/v0.8.24/LockReleaseTokenPoolAndProxy/LockReleaseTokenPoolAndProxy.bin e632b08be0fbd1d013e8b3a9d75293d0d532b83071c531ff2be1deec1fa48ec1 maybe_revert_message_receiver: ../../../contracts/solc/v0.8.24/MaybeRevertMessageReceiver/MaybeRevertMessageReceiver.abi ../../../contracts/solc/v0.8.24/MaybeRevertMessageReceiver/MaybeRevertMessageReceiver.bin d73956c26232ebcc4a5444429fa99cbefed960e323be9b5a24925885c2e477d5 -message_hasher: ../../../contracts/solc/v0.8.24/MessageHasher/MessageHasher.abi ../../../contracts/solc/v0.8.24/MessageHasher/MessageHasher.bin 5712fbc30cf826c0cf38c68f54f744741b553d98c60e66696b7a845778cb2b3d +message_hasher: ../../../contracts/solc/v0.8.24/MessageHasher/MessageHasher.abi ../../../contracts/solc/v0.8.24/MessageHasher/MessageHasher.bin 9c840c4ee02bd865630f2ef0070b8c745925577c4ee52cbc2e4f978177fc977c mock_usdc_token_messenger: ../../../contracts/solc/v0.8.24/MockE2EUSDCTokenMessenger/MockE2EUSDCTokenMessenger.abi ../../../contracts/solc/v0.8.24/MockE2EUSDCTokenMessenger/MockE2EUSDCTokenMessenger.bin d976651d36b33ac2196b32b9d2f4fa6690c6a18d41b621365659fce1c1d1e737 mock_usdc_token_transmitter: ../../../contracts/solc/v0.8.24/MockE2EUSDCTransmitter/MockE2EUSDCTransmitter.abi ../../../contracts/solc/v0.8.24/MockE2EUSDCTransmitter/MockE2EUSDCTransmitter.bin be0dbc3e475741ea0b7a54ec2b935a321b428baa9f4ce18180a87fb38bb87de2 mock_v3_aggregator_contract: ../../../contracts/solc/v0.8.24/MockV3Aggregator/MockV3Aggregator.abi ../../../contracts/solc/v0.8.24/MockV3Aggregator/MockV3Aggregator.bin 518e19efa2ff52b0fefd8e597b05765317ee7638189bfe34ca43de2f6599faf4 @@ -24,8 +24,8 @@ multi_aggregate_rate_limiter: ../../../contracts/solc/v0.8.24/MultiAggregateRate multi_ocr3_helper: ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Helper.abi ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Helper.bin 6b56e0114a4d50797d30a34aecc2641ef340451d0c3fcb9d729bba4df2435122 nonce_manager: ../../../contracts/solc/v0.8.24/NonceManager/NonceManager.abi ../../../contracts/solc/v0.8.24/NonceManager/NonceManager.bin 6f64e1083b356c06ee66b9138e398b9c97a4cd3e8c9ec38cf3010cebc79af536 ocr3_config_encoder: ../../../contracts/solc/v0.8.24/IOCR3ConfigEncoder/IOCR3ConfigEncoder.abi ../../../contracts/solc/v0.8.24/IOCR3ConfigEncoder/IOCR3ConfigEncoder.bin 9254b35a86f00fde7b7193a033ca58f6521a66e87b9cf9da6ce5660082e79f5d -offramp: ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.abi ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.bin 948feede308d265d1cc2e020bb063229d90cd712bddb1fa9138cb0045c0de2c8 -onramp: ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.abi ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.bin b6bd68506798be2ac8d29a9e3d78575b42a73e81758b6e3d638bb282a5db1db8 +offramp: ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.abi ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.bin 46914fd423a8d3377ebe65ff8567d7e3a76adfba50204c5468cd71ef663c614e +onramp: ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.abi ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.bin 57a053c78e7f91fdde84854609ad110c4db5b65142a0aab2c884c5c008e0873a ping_pong_demo: ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.abi ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.bin c1c2f8a65c7ffd971899cae7fe62f2da57d09e936151e2b92163c4bebe699d6b price_registry: ../../../contracts/solc/v0.8.24/PriceRegistry/PriceRegistry.abi ../../../contracts/solc/v0.8.24/PriceRegistry/PriceRegistry.bin e7781d600c1bb7aa4620106af7f6e146a109b97f4cb6a7d06c9e15773340ecb2 registry_module_owner_custom: ../../../contracts/solc/v0.8.24/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.abi ../../../contracts/solc/v0.8.24/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.bin 75be86323c227917a9bbc3f799d7ed02f92db546653a36db30ed0ebe64461353 From 258959a897da4c19609c5ea9785d9cfb8e2a2c3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Evaldas=20Lato=C5=A1kinas?= <34982762+elatoskinas@users.noreply.github.com> Date: Fri, 13 Sep 2024 19:51:44 +0300 Subject: [PATCH 096/115] Validate transmitter lengths against F values (#1432) ## Motivation Improves validations for OCR3 and CCIPConfig contracts ## Solution Covers validations: * `fChain <= F`, since `F` represents the full role DON * Allows setting empty transmitters in CCIPConfig to allow `len(transmitters) <= len(signers)`, while still enforcing `len(transmitters) >= 3 * fChain + 1` * Validates non-zero transmitters length in MultiOCR3 * Validates `len(signers) >= len(transmitters)` in MultiOCR3 ### Tooling implications * When setting OCR configs on OffRamp contracts, the list from CCIPConfig must be filtered to exclude 0-bytes addresses. The reason for this is that the MultiOCR3Base disallows zero addresses and duplicates * Signer and transmitter duplication must be checked in tooling scripts off-chain prior to setting CCIPConfig (otherwise it will result in OffRamp breakage) * `chainConfigs` must be set before OCR3 configs due to the added `fChain == F` validation * If `fChain` becomes higher than `F` after updates, existing OCR3 configs get invalidated without an on-chain check (since it is difficult to do). There should be an off-chain validation script that prevents this (first, F should be increased for all configs, only after which fChain can be increased) * `OffRamp` transmitters.length should be validated such that it meets the `3 * fChain + 1` criteria off-chain, since `fChain` is not tracked in the `OffRamp` ### Gas | Function Name | min | avg | median | max | # calls | |---------------------------------------------------------------------------|-----------------|--------|--------|---------|---------| | validateConfig (without loop check) | 7040 | 20701 | 8436 | 122591 | 11 | | validateConfig (with loop check) | 7040 | 21006 | 9132 | 123442 | 11 | --- contracts/gas-snapshots/ccip.gas-snapshot | 164 +++---- .../src/v0.8/ccip/capability/CCIPConfig.sol | 89 +++- .../capability/libraries/CCIPConfigTypes.sol | 20 +- contracts/src/v0.8/ccip/ocr/MultiOCR3Base.sol | 11 +- .../ccip/test/capability/CCIPConfig.t.sol | 402 +++++++++--------- .../v0.8/ccip/test/ocr/MultiOCR3Base.t.sol | 91 +++- .../ccip/generated/ccip_config/ccip_config.go | 18 +- .../multi_ocr3_helper/multi_ocr3_helper.go | 2 +- .../ocr3_config_encoder.go | 14 +- .../ccip/generated/offramp/offramp.go | 2 +- ...rapper-dependency-versions-do-not-edit.txt | 8 +- 11 files changed, 493 insertions(+), 328 deletions(-) diff --git a/contracts/gas-snapshots/ccip.gas-snapshot b/contracts/gas-snapshots/ccip.gas-snapshot index ad717fb01a..6c62f81495 100644 --- a/contracts/gas-snapshots/ccip.gas-snapshot +++ b/contracts/gas-snapshots/ccip.gas-snapshot @@ -35,58 +35,63 @@ BurnWithFromMintTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas BurnWithFromMintTokenPool_lockOrBurn:test_PoolBurn_Success() (gas: 244050) BurnWithFromMintTokenPool_lockOrBurn:test_Setup_Success() (gas: 24170) CCIPClientExample_sanity:test_ImmutableExamples_Success() (gas: 2052437) -CCIPConfigSetup:test_getCapabilityConfiguration_Success() (gas: 9551) -CCIPConfig_ConfigStateMachine:test__computeConfigDigest_Success() (gas: 67698) -CCIPConfig_ConfigStateMachine:test__computeNewConfigWithMeta_InitToRunning_Success() (gas: 361455) -CCIPConfig_ConfigStateMachine:test__computeNewConfigWithMeta_RunningToStaging_Success() (gas: 482385) -CCIPConfig_ConfigStateMachine:test__computeNewConfigWithMeta_StagingToRunning_Success() (gas: 448598) -CCIPConfig_ConfigStateMachine:test__groupByPluginType_TooManyOCR3Configs_Reverts() (gas: 35102) -CCIPConfig_ConfigStateMachine:test__groupByPluginType_threeCommitConfigs_Reverts() (gas: 58762) -CCIPConfig_ConfigStateMachine:test__groupByPluginType_threeExecutionConfigs_Reverts() (gas: 58700) -CCIPConfig_ConfigStateMachine:test__stateFromConfigLength_Success() (gas: 11737) -CCIPConfig_ConfigStateMachine:test__validateConfigStateTransition_Success() (gas: 8849) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_InitToRunning_Success() (gas: 311552) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_InitToRunning_WrongConfigCount_Reverts() (gas: 47113) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_NonExistentConfigTransition_Reverts() (gas: 30728) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_RunningToStaging_Success() (gas: 374071) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_RunningToStaging_WrongConfigCount_Reverts() (gas: 114898) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_RunningToStaging_WrongConfigDigestBlueGreen_Reverts() (gas: 150024) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_StagingToRunning_Success() (gas: 373811) -CCIPConfig_ConfigStateMachine:test__validateConfigTransition_StagingToRunning_WrongConfigDigest_Reverts() (gas: 150091) -CCIPConfig_ConfigStateMachine:test_getCapabilityConfiguration_Success() (gas: 9675) -CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_CommitAndExecConfig_Success() (gas: 1793946) -CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_CommitConfigOnly_Success() (gas: 1040198) -CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_ExecConfigOnly_Success() (gas: 1040229) +CCIPConfigSetup:test_getCapabilityConfiguration_Success() (gas: 9508) +CCIPConfig_ConfigStateMachine:test__computeConfigDigest_Success() (gas: 83274) +CCIPConfig_ConfigStateMachine:test__computeNewConfigWithMeta_InitToRunning_Success() (gas: 354656) +CCIPConfig_ConfigStateMachine:test__computeNewConfigWithMeta_RunningToStaging_Success() (gas: 466876) +CCIPConfig_ConfigStateMachine:test__computeNewConfigWithMeta_StagingToRunning_Success() (gas: 433253) +CCIPConfig_ConfigStateMachine:test__groupByPluginType_TooManyOCR3Configs_Reverts() (gas: 28063) +CCIPConfig_ConfigStateMachine:test__groupByPluginType_threeCommitConfigs_Reverts() (gas: 61002) +CCIPConfig_ConfigStateMachine:test__groupByPluginType_threeExecutionConfigs_Reverts() (gas: 60940) +CCIPConfig_ConfigStateMachine:test__stateFromConfigLength_Success() (gas: 11668) +CCIPConfig_ConfigStateMachine:test__validateConfigStateTransition_Success() (gas: 8783) +CCIPConfig_ConfigStateMachine:test__validateConfigTransition_InitToRunning_Success() (gas: 305974) +CCIPConfig_ConfigStateMachine:test__validateConfigTransition_InitToRunning_WrongConfigCount_Reverts() (gas: 46142) +CCIPConfig_ConfigStateMachine:test__validateConfigTransition_NonExistentConfigTransition_Reverts() (gas: 25040) +CCIPConfig_ConfigStateMachine:test__validateConfigTransition_RunningToStaging_Success() (gas: 362471) +CCIPConfig_ConfigStateMachine:test__validateConfigTransition_RunningToStaging_WrongConfigCount_Reverts() (gas: 110001) +CCIPConfig_ConfigStateMachine:test__validateConfigTransition_RunningToStaging_WrongConfigDigestBlueGreen_Reverts() (gas: 141606) +CCIPConfig_ConfigStateMachine:test__validateConfigTransition_StagingToRunning_Success() (gas: 362211) +CCIPConfig_ConfigStateMachine:test__validateConfigTransition_StagingToRunning_WrongConfigDigest_Reverts() (gas: 141673) +CCIPConfig_ConfigStateMachine:test_getCapabilityConfiguration_Success() (gas: 9632) +CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_CommitAndExecConfig_Success() (gas: 1699166) +CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_CommitConfigOnly_Success() (gas: 991503) +CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_ExecConfigOnly_Success() (gas: 991534) CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_OnlyCapabilitiesRegistryCanCall_Reverts() (gas: 9665) -CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_ZeroLengthConfig_Success() (gas: 16188) -CCIPConfig_beforeCapabilityConfigSet:test_getCapabilityConfiguration_Success() (gas: 9639) -CCIPConfig_chainConfig:test__applyChainConfigUpdates_FChainNotPositive_Reverts() (gas: 185224) -CCIPConfig_chainConfig:test_applyChainConfigUpdates_addChainConfigs_Success() (gas: 347338) -CCIPConfig_chainConfig:test_applyChainConfigUpdates_nodeNotInRegistry_Reverts() (gas: 20613) -CCIPConfig_chainConfig:test_applyChainConfigUpdates_removeChainConfigs_Success() (gas: 270910) -CCIPConfig_chainConfig:test_applyChainConfigUpdates_selectorNotFound_Reverts() (gas: 14921) -CCIPConfig_chainConfig:test_getCapabilityConfiguration_Success() (gas: 9660) -CCIPConfig_chainConfig:test_getPaginatedCCIPConfigs_Success() (gas: 371100) -CCIPConfig_constructor:test_constructor_Success() (gas: 3191349) -CCIPConfig_constructor:test_constructor_ZeroAddressNotAllowed_Revert() (gas: 61266) -CCIPConfig_updatePluginConfig:test__updatePluginConfig_InvalidConfigLength_Reverts() (gas: 26551) -CCIPConfig_updatePluginConfig:test__updatePluginConfig_InvalidConfigStateTransition_Reverts() (gas: 22417) -CCIPConfig_updatePluginConfig:test_getCapabilityConfiguration_Success() (gas: 9697) -CCIPConfig_updatePluginConfig:test_updatePluginConfig_InitToRunning_Success() (gas: 1090890) -CCIPConfig_updatePluginConfig:test_updatePluginConfig_RunningToStaging_Success() (gas: 2037835) -CCIPConfig_updatePluginConfig:test_updatePluginConfig_StagingToRunning_Success() (gas: 2037868) -CCIPConfig_validateConfig:test__validateConfig_ABIEncodedAddress_OfframpAddressCannotBeZero_Reverts() (gas: 291812) -CCIPConfig_validateConfig:test__validateConfig_ChainSelectorNotFound_Reverts() (gas: 294567) -CCIPConfig_validateConfig:test__validateConfig_ChainSelectorNotSet_Reverts() (gas: 291445) -CCIPConfig_validateConfig:test__validateConfig_FMustBePositive_Reverts() (gas: 292676) -CCIPConfig_validateConfig:test__validateConfig_FTooHigh_Reverts() (gas: 292774) -CCIPConfig_validateConfig:test__validateConfig_NodeNotInRegistry_Reverts() (gas: 346525) -CCIPConfig_validateConfig:test__validateConfig_NotEnoughTransmitters_Reverts() (gas: 1213555) -CCIPConfig_validateConfig:test__validateConfig_OfframpAddressCannotBeZero_Reverts() (gas: 291528) -CCIPConfig_validateConfig:test__validateConfig_P2PIdsLengthNotMatching_Reverts() (gas: 293467) -CCIPConfig_validateConfig:test__validateConfig_Success() (gas: 300916) -CCIPConfig_validateConfig:test__validateConfig_TooManySigners_Reverts() (gas: 503200) -CCIPConfig_validateConfig:test_getCapabilityConfiguration_Success() (gas: 9618) +CCIPConfig_beforeCapabilityConfigSet:test_beforeCapabilityConfigSet_ZeroLengthConfig_Success() (gas: 16042) +CCIPConfig_beforeCapabilityConfigSet:test_getCapabilityConfiguration_Success() (gas: 9596) +CCIPConfig_chainConfig:test__applyChainConfigUpdates_FChainNotPositive_Reverts() (gas: 185139) +CCIPConfig_chainConfig:test_applyChainConfigUpdates_addChainConfigs_Success() (gas: 347170) +CCIPConfig_chainConfig:test_applyChainConfigUpdates_nodeNotInRegistry_Reverts() (gas: 20599) +CCIPConfig_chainConfig:test_applyChainConfigUpdates_removeChainConfigs_Success() (gas: 270867) +CCIPConfig_chainConfig:test_applyChainConfigUpdates_selectorNotFound_Reverts() (gas: 14943) +CCIPConfig_chainConfig:test_getCapabilityConfiguration_Success() (gas: 9617) +CCIPConfig_chainConfig:test_getPaginatedCCIPConfigs_Success() (gas: 370770) +CCIPConfig_constructor:test_constructor_Success() (gas: 3155264) +CCIPConfig_constructor:test_constructor_ZeroAddressNotAllowed_Revert() (gas: 61226) +CCIPConfig_updatePluginConfig:test__updatePluginConfig_InvalidConfigLength_Reverts() (gas: 22160) +CCIPConfig_updatePluginConfig:test__updatePluginConfig_InvalidConfigStateTransition_Reverts() (gas: 19491) +CCIPConfig_updatePluginConfig:test_getCapabilityConfiguration_Success() (gas: 9654) +CCIPConfig_updatePluginConfig:test_updatePluginConfig_InitToRunning_Success() (gas: 1039133) +CCIPConfig_updatePluginConfig:test_updatePluginConfig_RunningToStaging_Success() (gas: 1923111) +CCIPConfig_updatePluginConfig:test_updatePluginConfig_StagingToRunning_Success() (gas: 1923145) +CCIPConfig_validateConfig:test__validateConfigLessTransmittersThanSigners_Success() (gas: 333177) +CCIPConfig_validateConfig:test__validateConfigSmallerFChain_Success() (gas: 464532) +CCIPConfig_validateConfig:test__validateConfig_ABIEncodedAddress_OfframpAddressCannotBeZero_Reverts() (gas: 288463) +CCIPConfig_validateConfig:test__validateConfig_ChainSelectorNotFound_Reverts() (gas: 291264) +CCIPConfig_validateConfig:test__validateConfig_ChainSelectorNotSet_Reverts() (gas: 288096) +CCIPConfig_validateConfig:test__validateConfig_FChainTooHigh_Reverts() (gas: 335512) +CCIPConfig_validateConfig:test__validateConfig_FMustBePositive_Reverts() (gas: 289648) +CCIPConfig_validateConfig:test__validateConfig_FTooHigh_Reverts() (gas: 289087) +CCIPConfig_validateConfig:test__validateConfig_NodeNotInRegistry_Reverts() (gas: 342330) +CCIPConfig_validateConfig:test__validateConfig_NotEnoughTransmittersEmptyAddresses_Reverts() (gas: 306844) +CCIPConfig_validateConfig:test__validateConfig_NotEnoughTransmitters_Reverts() (gas: 1209806) +CCIPConfig_validateConfig:test__validateConfig_OfframpAddressCannotBeZero_Reverts() (gas: 288202) +CCIPConfig_validateConfig:test__validateConfig_Success() (gas: 299119) +CCIPConfig_validateConfig:test__validateConfig_TooManySigners_Reverts() (gas: 788872) +CCIPConfig_validateConfig:test__validateConfig_ZeroP2PId_Reverts() (gas: 292418) +CCIPConfig_validateConfig:test__validateConfig_ZeroSignerKey_Reverts() (gas: 292467) +CCIPConfig_validateConfig:test_getCapabilityConfiguration_Success() (gas: 9596) CommitStore_constructor:test_Constructor_Success() (gas: 2855567) CommitStore_isUnpausedAndRMNHealthy:test_RMN_Success() (gas: 73954) CommitStore_report:test_InvalidIntervalMinLargerThanMax_Revert() (gas: 28739) @@ -535,21 +540,24 @@ MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokens_Remov MultiAggregateRateLimiter_updateRateLimitTokens:test_ZeroDestToken_Revert() (gas: 18324) MultiAggregateRateLimiter_updateRateLimitTokens:test_ZeroSourceToken_Revert() (gas: 18253) MultiOCR3Base_setOCR3Configs:test_FMustBePositive_Revert() (gas: 59294) -MultiOCR3Base_setOCR3Configs:test_FTooHigh_Revert() (gas: 43671) -MultiOCR3Base_setOCR3Configs:test_RepeatSignerAddress_Revert() (gas: 283678) -MultiOCR3Base_setOCR3Configs:test_RepeatTransmitterAddress_Revert() (gas: 422303) -MultiOCR3Base_setOCR3Configs:test_SetConfigIgnoreSigners_Success() (gas: 511914) -MultiOCR3Base_setOCR3Configs:test_SetConfigWithSigners_Success() (gas: 828842) -MultiOCR3Base_setOCR3Configs:test_SetConfigWithoutSigners_Success() (gas: 457288) +MultiOCR3Base_setOCR3Configs:test_FTooHigh_Revert() (gas: 44190) +MultiOCR3Base_setOCR3Configs:test_MoreTransmittersThanSigners_Revert() (gas: 104822) +MultiOCR3Base_setOCR3Configs:test_NoTransmitters_Revert() (gas: 18886) +MultiOCR3Base_setOCR3Configs:test_RepeatSignerAddress_Revert() (gas: 283736) +MultiOCR3Base_setOCR3Configs:test_RepeatTransmitterAddress_Revert() (gas: 422361) +MultiOCR3Base_setOCR3Configs:test_SetConfigIgnoreSigners_Success() (gas: 511918) +MultiOCR3Base_setOCR3Configs:test_SetConfigWithSignersMismatchingTransmitters_Success() (gas: 680323) +MultiOCR3Base_setOCR3Configs:test_SetConfigWithSigners_Success() (gas: 828900) +MultiOCR3Base_setOCR3Configs:test_SetConfigWithoutSigners_Success() (gas: 457292) MultiOCR3Base_setOCR3Configs:test_SetConfigsZeroInput_Success() (gas: 12481) -MultiOCR3Base_setOCR3Configs:test_SetMultipleConfigs_Success() (gas: 2141470) -MultiOCR3Base_setOCR3Configs:test_SignerCannotBeZeroAddress_Revert() (gas: 141777) -MultiOCR3Base_setOCR3Configs:test_StaticConfigChange_Revert() (gas: 807499) -MultiOCR3Base_setOCR3Configs:test_TooManySigners_Revert() (gas: 158841) +MultiOCR3Base_setOCR3Configs:test_SetMultipleConfigs_Success() (gas: 2141622) +MultiOCR3Base_setOCR3Configs:test_SignerCannotBeZeroAddress_Revert() (gas: 141835) +MultiOCR3Base_setOCR3Configs:test_StaticConfigChange_Revert() (gas: 807623) +MultiOCR3Base_setOCR3Configs:test_TooManySigners_Revert() (gas: 158867) MultiOCR3Base_setOCR3Configs:test_TooManyTransmitters_Revert() (gas: 112335) -MultiOCR3Base_setOCR3Configs:test_TransmitterCannotBeZeroAddress_Revert() (gas: 254143) -MultiOCR3Base_setOCR3Configs:test_UpdateConfigSigners_Success() (gas: 861131) -MultiOCR3Base_setOCR3Configs:test_UpdateConfigTransmittersWithoutSigners_Success() (gas: 475810) +MultiOCR3Base_setOCR3Configs:test_TransmitterCannotBeZeroAddress_Revert() (gas: 254201) +MultiOCR3Base_setOCR3Configs:test_UpdateConfigSigners_Success() (gas: 861206) +MultiOCR3Base_setOCR3Configs:test_UpdateConfigTransmittersWithoutSigners_Success() (gas: 475852) MultiOCR3Base_transmit:test_ConfigDigestMismatch_Revert() (gas: 42956) MultiOCR3Base_transmit:test_ForkedChain_Revert() (gas: 48639) MultiOCR3Base_transmit:test_InsufficientSignatures_Revert() (gas: 77138) @@ -613,7 +621,7 @@ OCR2Base_transmit:test_Transmit2SignersSuccess_gas() (gas: 51689) OCR2Base_transmit:test_UnAuthorizedTransmitter_Revert() (gas: 23511) OCR2Base_transmit:test_UnauthorizedSigner_Revert() (gas: 39707) OCR2Base_transmit:test_WrongNumberOfSignatures_Revert() (gas: 20584) -OffRamp_afterOC3ConfigSet:test_afterOCR3ConfigSet_SignatureVerificationDisabled_Revert() (gas: 5705901) +OffRamp_afterOC3ConfigSet:test_afterOCR3ConfigSet_SignatureVerificationDisabled_Revert() (gas: 5720983) OffRamp_applySourceChainConfigUpdates:test_AddMultipleChains_Success() (gas: 469413) OffRamp_applySourceChainConfigUpdates:test_AddNewChain_Success() (gas: 99659) OffRamp_applySourceChainConfigUpdates:test_ApplyZeroUpdates_Success() (gas: 12613) @@ -637,12 +645,12 @@ OffRamp_commit:test_FailedRMNVerification_Reverts() (gas: 63787) OffRamp_commit:test_InvalidIntervalMinLargerThanMax_Revert() (gas: 67826) OffRamp_commit:test_InvalidInterval_Revert() (gas: 63993) OffRamp_commit:test_InvalidRootRevert() (gas: 63066) -OffRamp_commit:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6309840) -OffRamp_commit:test_NoConfig_Revert() (gas: 5893538) +OffRamp_commit:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6324922) +OffRamp_commit:test_NoConfig_Revert() (gas: 5908594) OffRamp_commit:test_OnlyGasPriceUpdates_Success() (gas: 112835) OffRamp_commit:test_OnlyPriceUpdateStaleReport_Revert() (gas: 121022) OffRamp_commit:test_OnlyTokenPriceUpdates_Success() (gas: 112856) -OffRamp_commit:test_PriceSequenceNumberCleared_Success() (gas: 354720) +OffRamp_commit:test_PriceSequenceNumberCleared_Success() (gas: 354804) OffRamp_commit:test_ReportAndPriceUpdate_Success() (gas: 164033) OffRamp_commit:test_ReportOnlyRootSuccess_gas() (gas: 139030) OffRamp_commit:test_RootAlreadyCommitted_Revert() (gas: 145995) @@ -652,23 +660,23 @@ OffRamp_commit:test_UnauthorizedTransmitter_Revert() (gas: 125104) OffRamp_commit:test_Unhealthy_Revert() (gas: 58334) OffRamp_commit:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 206207) OffRamp_commit:test_ZeroEpochAndRound_Revert() (gas: 51522) -OffRamp_constructor:test_Constructor_Success() (gas: 5894658) -OffRamp_constructor:test_SourceChainSelector_Revert() (gas: 135582) -OffRamp_constructor:test_ZeroChainSelector_Revert() (gas: 103017) -OffRamp_constructor:test_ZeroNonceManager_Revert() (gas: 100911) -OffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 161108) -OffRamp_constructor:test_ZeroRMNRemote_Revert() (gas: 100831) -OffRamp_constructor:test_ZeroTokenAdminRegistry_Revert() (gas: 100869) +OffRamp_constructor:test_Constructor_Success() (gas: 5909740) +OffRamp_constructor:test_SourceChainSelector_Revert() (gas: 135611) +OffRamp_constructor:test_ZeroChainSelector_Revert() (gas: 103046) +OffRamp_constructor:test_ZeroNonceManager_Revert() (gas: 100940) +OffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 161137) +OffRamp_constructor:test_ZeroRMNRemote_Revert() (gas: 100860) +OffRamp_constructor:test_ZeroTokenAdminRegistry_Revert() (gas: 100898) OffRamp_execute:test_IncorrectArrayType_Revert() (gas: 17639) OffRamp_execute:test_LargeBatch_Success() (gas: 3426335) OffRamp_execute:test_MultipleReportsWithPartialValidationFailures_Success() (gas: 372966) OffRamp_execute:test_MultipleReports_Success() (gas: 300979) -OffRamp_execute:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6718990) -OffRamp_execute:test_NoConfig_Revert() (gas: 5943523) +OffRamp_execute:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6734104) +OffRamp_execute:test_NoConfig_Revert() (gas: 5958579) OffRamp_execute:test_NonArray_Revert() (gas: 27562) OffRamp_execute:test_SingleReport_Success() (gas: 176354) OffRamp_execute:test_UnauthorizedTransmitter_Revert() (gas: 148372) -OffRamp_execute:test_WrongConfigWithSigners_Revert() (gas: 6721739) +OffRamp_execute:test_WrongConfigWithSigners_Revert() (gas: 6736853) OffRamp_execute:test_ZeroReports_Revert() (gas: 17361) OffRamp_executeSingleMessage:test_MessageSender_Revert() (gas: 18533) OffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 248725) diff --git a/contracts/src/v0.8/ccip/capability/CCIPConfig.sol b/contracts/src/v0.8/ccip/capability/CCIPConfig.sol index 10f5e6706f..3414f4912f 100644 --- a/contracts/src/v0.8/ccip/capability/CCIPConfig.sol +++ b/contracts/src/v0.8/ccip/capability/CCIPConfig.sol @@ -34,11 +34,11 @@ contract CCIPConfig is ITypeAndVersion, ICapabilityConfiguration, OwnerIsCreator error ChainSelectorNotSet(); error TooManyOCR3Configs(); error TooManySigners(); - error P2PIdsLengthNotMatching(uint256 p2pIdsLength, uint256 signersLength, uint256 transmittersLength); + error InvalidNode(CCIPConfigTypes.OCR3Node node); error NotEnoughTransmitters(uint256 got, uint256 minimum); - error FMustBePositive(); error FChainMustBePositive(); error FTooHigh(); + error FChainTooHigh(uint256 fChain, uint256 FRoleDON); error InvalidPluginType(); error OfframpAddressCannotBeZero(); error InvalidConfigLength(uint256 length); @@ -167,6 +167,7 @@ contract CCIPConfig is ITypeAndVersion, ICapabilityConfiguration, OwnerIsCreator } /// @notice Called by the registry prior to the config being set for a particular DON. + /// @dev precondition Requires destination chain config to be set function beforeCapabilityConfigSet( bytes32[] calldata, /* nodes */ bytes calldata config, @@ -213,7 +214,32 @@ contract CCIPConfig is ITypeAndVersion, ICapabilityConfiguration, OwnerIsCreator // We won't run out of gas from this delete since the array is at most 2 elements long. delete s_ocr3Configs[donId][pluginType]; for (uint256 i = 0; i < newConfigWithMeta.length; ++i) { - s_ocr3Configs[donId][pluginType].push(newConfigWithMeta[i]); + // Struct has to be manually copied since there is a nested OCR3Node array. Direct assignment + // will result in Unimplemented Feature issue. + CCIPConfigTypes.OCR3ConfigWithMeta storage ocr3ConfigWithMeta = s_ocr3Configs[donId][pluginType].push(); + ocr3ConfigWithMeta.configDigest = newConfigWithMeta[i].configDigest; + ocr3ConfigWithMeta.configCount = newConfigWithMeta[i].configCount; + + CCIPConfigTypes.OCR3Config storage ocr3Config = ocr3ConfigWithMeta.config; + CCIPConfigTypes.OCR3Config memory newOcr3Config = newConfigWithMeta[i].config; + ocr3Config.pluginType = newOcr3Config.pluginType; + ocr3Config.chainSelector = newOcr3Config.chainSelector; + ocr3Config.FRoleDON = newOcr3Config.FRoleDON; + ocr3Config.offchainConfigVersion = newOcr3Config.offchainConfigVersion; + ocr3Config.offrampAddress = newOcr3Config.offrampAddress; + ocr3Config.offchainConfig = newOcr3Config.offchainConfig; + + // Remove all excess nodes + while (ocr3Config.nodes.length > newOcr3Config.nodes.length) { + ocr3Config.nodes.pop(); + } + + // Assign nodes + for (uint256 j = 0; j < newOcr3Config.nodes.length; ++j) { + if (j >= ocr3Config.nodes.length) { + ocr3Config.nodes.push(newOcr3Config.nodes[j]); + } + } } emit ConfigSet(donId, uint8(pluginType), newConfigWithMeta); @@ -402,21 +428,49 @@ contract CCIPConfig is ITypeAndVersion, ICapabilityConfiguration, OwnerIsCreator } if (!s_remoteChainSelectors.contains(cfg.chainSelector)) revert ChainSelectorNotFound(cfg.chainSelector); - // We check for chain config presence above, so fChain here must be non-zero. - uint256 minTransmittersLength = 3 * s_chainConfigurations[cfg.chainSelector].fChain + 1; - if (cfg.transmitters.length < minTransmittersLength) { - revert NotEnoughTransmitters(cfg.transmitters.length, minTransmittersLength); + // fChain cannot exceed FRoleDON, since it is a subcommittee in the larger DON + uint256 FRoleDON = cfg.FRoleDON; + uint256 fChain = s_chainConfigurations[cfg.chainSelector].fChain; + // fChain > 0 is enforced in applyChainConfigUpdates, and the presence of a chain config is checked above + // FRoleDON != 0 because FRoleDON >= fChain is enforced here + if (fChain > FRoleDON) { + revert FChainTooHigh(fChain, FRoleDON); + } + + // len(nodes) >= 3 * FRoleDON + 1 + // len(nodes) == numberOfSigners + uint256 numberOfNodes = cfg.nodes.length; + if (numberOfNodes > MAX_NUM_ORACLES) revert TooManySigners(); + if (numberOfNodes <= 3 * FRoleDON) revert FTooHigh(); + + uint256 nonZeroTransmitters = 0; + bytes32[] memory p2pIds = new bytes32[](numberOfNodes); + for (uint256 i = 0; i < numberOfNodes; ++i) { + CCIPConfigTypes.OCR3Node memory node = cfg.nodes[i]; + + // 3 * fChain + 1 <= nonZeroTransmitters <= 3 * FRoleDON + 1 + // Transmitters can be set to 0 since there can be more signers than transmitters, + if (node.transmitterKey.length != 0) { + nonZeroTransmitters++; + } + + // Signer key and p2pIds must always be present + if (node.signerKey.length == 0 || node.p2pId == bytes32(0)) { + revert InvalidNode(node); + } + + p2pIds[i] = node.p2pId; } - uint256 numberOfSigners = cfg.signers.length; - if (numberOfSigners > MAX_NUM_ORACLES) revert TooManySigners(); - if (numberOfSigners != cfg.p2pIds.length || numberOfSigners != cfg.transmitters.length) { - revert P2PIdsLengthNotMatching(cfg.p2pIds.length, cfg.signers.length, cfg.transmitters.length); + + // We check for chain config presence above, so fChain here must be non-zero. fChain <= FRoleDON due to the checks above. + // There can be less transmitters than signers - so they can be set to zero (which indicates that a node is a signer, but not a transmitter). + uint256 minTransmittersLength = 3 * fChain + 1; + if (nonZeroTransmitters < minTransmittersLength) { + revert NotEnoughTransmitters(nonZeroTransmitters, minTransmittersLength); } - if (cfg.F == 0) revert FMustBePositive(); - if (numberOfSigners <= 3 * cfg.F) revert FTooHigh(); // Check that the readers are in the capabilities registry. - _ensureInRegistry(cfg.p2pIds); + _ensureInRegistry(p2pIds); } /// @notice Computes the digest of the provided configuration. @@ -441,10 +495,8 @@ contract CCIPConfig is ITypeAndVersion, ICapabilityConfiguration, OwnerIsCreator ocr3Config.pluginType, ocr3Config.offrampAddress, configCount, - ocr3Config.p2pIds, - ocr3Config.signers, - ocr3Config.transmitters, - ocr3Config.F, + ocr3Config.nodes, + ocr3Config.FRoleDON, ocr3Config.offchainConfigVersion, ocr3Config.offchainConfig ) @@ -459,6 +511,7 @@ contract CCIPConfig is ITypeAndVersion, ICapabilityConfiguration, OwnerIsCreator // ================================================================ /// @notice Sets and/or removes chain configurations. + /// Does not validate that fChain <= FRoleDON and relies on OCR3Configs to be changed in case fChain becomes larger than the FRoleDON value. /// @param chainSelectorRemoves The chain configurations to remove. /// @param chainConfigAdds The chain configurations to add. function applyChainConfigUpdates( diff --git a/contracts/src/v0.8/ccip/capability/libraries/CCIPConfigTypes.sol b/contracts/src/v0.8/ccip/capability/libraries/CCIPConfigTypes.sol index 02d8e321ac..eca133f5dd 100644 --- a/contracts/src/v0.8/ccip/capability/libraries/CCIPConfigTypes.sol +++ b/contracts/src/v0.8/ccip/capability/libraries/CCIPConfigTypes.sol @@ -37,19 +37,25 @@ library CCIPConfigTypes { ChainConfig chainConfig; } + /// @notice Represents an oracle node in OCR3 configs part of the role DON. + /// Every configured node should be a signer, but does not have to be a transmitter. + struct OCR3Node { + bytes32 p2pId; // Peer2Peer connection ID of the oracle + bytes signerKey; // On-chain signer public key + bytes transmitterKey; // On-chain transmitter public key. Can be set to empty bytes to represent that the node is a signer but not a transmitter. + } + /// @notice OCR3 configuration. + /// Note that FRoleDON >= fChain, since FRoleDON represents the role DON, and fChain represents sub-committees. + /// FRoleDON values are typically identical across multiple OCR3 configs since the chains pertain to one role DON, + /// but FRoleDON values can change across OCR3 configs to indicate role DON splits. struct OCR3Config { Internal.OCRPluginType pluginType; // ────────╮ The plugin that the configuration is for. uint64 chainSelector; // | The (remote) chain that the configuration is for. - uint8 F; // | The "big F" parameter for the role DON. + uint8 FRoleDON; // | The "big F" parameter for the role DON. uint64 offchainConfigVersion; // ─────────────╯ The version of the offchain configuration. bytes offrampAddress; // The remote chain offramp address. - // len(p2pIds) == len(signers) == len(transmitters) == 3 * F + 1 - // NOTE: indexes matter here! The p2p ID at index i corresponds to the signer at index i and the transmitter at index i. - // This is crucial in order to build the oracle ID <-> peer ID mapping offchain. - bytes32[] p2pIds; // The P2P IDs of the oracles that are part of the role DON. - bytes[] signers; // The onchain signing keys of nodes in the don. - bytes[] transmitters; // The onchain transmitter keys of nodes in the don. + OCR3Node[] nodes; // Keys & IDs of nodes part of the role DON bytes offchainConfig; // The offchain configuration for the OCR3 protocol. Protobuf encoded. } diff --git a/contracts/src/v0.8/ccip/ocr/MultiOCR3Base.sol b/contracts/src/v0.8/ccip/ocr/MultiOCR3Base.sol index c9fff4d624..f3e4d5a9ed 100644 --- a/contracts/src/v0.8/ccip/ocr/MultiOCR3Base.sol +++ b/contracts/src/v0.8/ccip/ocr/MultiOCR3Base.sol @@ -28,7 +28,8 @@ abstract contract MultiOCR3Base is ITypeAndVersion, OwnerIsCreator { TOO_MANY_TRANSMITTERS, TOO_MANY_SIGNERS, F_TOO_HIGH, - REPEATED_ORACLE_ADDRESS + REPEATED_ORACLE_ADDRESS, + NO_TRANSMITTERS } error InvalidConfig(InvalidConfigErrorType errorType); @@ -74,6 +75,7 @@ abstract contract MultiOCR3Base is ITypeAndVersion, OwnerIsCreator { /// @notice OCR configuration for a single OCR plugin within a DON. struct OCRConfig { ConfigInfo configInfo; // latest OCR config + // NOTE: len(signers) can be different from len(transmitters). There is no index relationship between the two arrays address[] signers; // addresses oracles use to sign the reports address[] transmitters; // addresses oracles use to transmit the reports } @@ -123,6 +125,9 @@ abstract contract MultiOCR3Base is ITypeAndVersion, OwnerIsCreator { /// NOTE: The OCR3 config must be sanity-checked against the home-chain registry configuration, to ensure /// home-chain and remote-chain parity! /// @param ocrConfigArgs OCR config update args. + /// @dev precondition number of transmitters should match the expected F/fChain relationship. + /// For transmitters, the function only validates that len(transmitters) > 0 && len(transmitters) <= MAX_NUM_ORACLES + /// && len(transmitters) <= len(signers) [if sig verification is enabled] function setOCR3Configs(OCRConfigArgs[] memory ocrConfigArgs) external onlyOwner { for (uint256 i; i < ocrConfigArgs.length; ++i) { _setOCR3Config(ocrConfigArgs[i]); @@ -147,6 +152,7 @@ abstract contract MultiOCR3Base is ITypeAndVersion, OwnerIsCreator { address[] memory transmitters = ocrConfigArgs.transmitters; if (transmitters.length > MAX_NUM_ORACLES) revert InvalidConfig(InvalidConfigErrorType.TOO_MANY_TRANSMITTERS); + if (transmitters.length == 0) revert InvalidConfig(InvalidConfigErrorType.NO_TRANSMITTERS); _clearOracleRoles(ocrPluginType, ocrConfig.transmitters); @@ -157,6 +163,9 @@ abstract contract MultiOCR3Base is ITypeAndVersion, OwnerIsCreator { if (signers.length > MAX_NUM_ORACLES) revert InvalidConfig(InvalidConfigErrorType.TOO_MANY_SIGNERS); if (signers.length <= 3 * ocrConfigArgs.F) revert InvalidConfig(InvalidConfigErrorType.F_TOO_HIGH); + // NOTE: Transmitters cannot exceed signers. Transmitters do not have to be >= 3F + 1 because they can match >= 3fChain + 1, where fChain <= F. + // fChain is not represented in MultiOCR3Base - so we skip this check. + if (signers.length < transmitters.length) revert InvalidConfig(InvalidConfigErrorType.TOO_MANY_TRANSMITTERS); configInfo.n = uint8(signers.length); ocrConfig.signers = signers; diff --git a/contracts/src/v0.8/ccip/test/capability/CCIPConfig.t.sol b/contracts/src/v0.8/ccip/test/capability/CCIPConfig.t.sol index 384528eeeb..a64fee8b9a 100644 --- a/contracts/src/v0.8/ccip/test/capability/CCIPConfig.t.sol +++ b/contracts/src/v0.8/ccip/test/capability/CCIPConfig.t.sol @@ -43,33 +43,20 @@ contract CCIPConfigSetup is Test { return subset; } - //TODO: Use OZ's Arrays.sort when we upgrade to OZ v5 - function _sort(bytes32[] memory arr, int256 left, int256 right) private pure { - int256 i = left; - int256 j = right; - if (i == j) return; - bytes32 pivot = arr[uint256(left + (right - left) / 2)]; - while (i <= j) { - while (arr[uint256(i)] < pivot) i++; - while (pivot < arr[uint256(j)]) j--; - if (i <= j) { - (arr[uint256(i)], arr[uint256(j)]) = (arr[uint256(j)], arr[uint256(i)]); - i++; - j--; - } - } - if (left < j) _sort(arr, left, j); - if (i < right) _sort(arr, i, right); + function _addChainConfig(uint256 numNodes) internal returns (CCIPConfigTypes.OCR3Node[] memory nodes) { + return _addChainConfig(numNodes, 1); } - function _addChainConfig( - uint256 numNodes - ) internal returns (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) { - p2pIds = _makeBytes32Array(numNodes, 0); - _sort(p2pIds, 0, int256(numNodes - 1)); - signers = _makeBytesArray(numNodes, 10); - transmitters = _makeBytesArray(numNodes, 20); + function _addChainConfig(uint256 numNodes, uint8 fChain) internal returns (CCIPConfigTypes.OCR3Node[] memory nodes) { + bytes32[] memory p2pIds = _makeBytes32Array(numNodes, 0); + bytes[] memory signers = _makeBytesArray(numNodes, 10); + bytes[] memory transmitters = _makeBytesArray(numNodes, 20); + + nodes = new CCIPConfigTypes.OCR3Node[](numNodes); + for (uint256 i = 0; i < numNodes; i++) { + nodes[i] = CCIPConfigTypes.OCR3Node({p2pId: p2pIds[i], signerKey: signers[i], transmitterKey: transmitters[i]}); + vm.mockCall( CAPABILITIES_REGISTRY, abi.encodeWithSelector(ICapabilitiesRegistry.getNode.selector, p2pIds[i]), @@ -90,14 +77,28 @@ contract CCIPConfigSetup is Test { CCIPConfigTypes.ChainConfigInfo[] memory adds = new CCIPConfigTypes.ChainConfigInfo[](1); adds[0] = CCIPConfigTypes.ChainConfigInfo({ chainSelector: 1, - chainConfig: CCIPConfigTypes.ChainConfig({readers: p2pIds, fChain: 1, config: bytes("config1")}) + chainConfig: CCIPConfigTypes.ChainConfig({readers: p2pIds, fChain: fChain, config: bytes("config1")}) }); vm.expectEmit(); emit CCIPConfig.ChainConfigSet(1, adds[0].chainConfig); s_ccipCC.applyChainConfigUpdates(new uint64[](0), adds); - return (p2pIds, signers, transmitters); + return nodes; + } + + function _constructNodesArray( + bytes32[] memory p2pIds, + bytes[] memory signers, + bytes[] memory transmitters + ) internal pure returns (CCIPConfigTypes.OCR3Node[] memory nodes) { + nodes = new CCIPConfigTypes.OCR3Node[](p2pIds.length); + + for (uint256 i = 0; i < p2pIds.length; i++) { + nodes[i] = CCIPConfigTypes.OCR3Node({p2pId: p2pIds[i], signerKey: signers[i], transmitterKey: transmitters[i]}); + } + + return nodes; } function _assertOCR3ConfigWithMetaEqual( @@ -118,20 +119,16 @@ contract CCIPConfigSetup is Test { ) internal pure { assertEq(uint8(a.pluginType), uint8(b.pluginType), "pluginType must match"); assertEq(a.chainSelector, b.chainSelector, "chainSelector must match"); - assertEq(a.F, b.F, "F must match"); + assertEq(a.FRoleDON, b.FRoleDON, "FRoleDON must match"); assertEq(a.offchainConfigVersion, b.offchainConfigVersion, "offchainConfigVersion must match"); assertEq(a.offrampAddress, b.offrampAddress, "offrampAddress must match"); - assertEq(a.p2pIds.length, b.p2pIds.length, "p2pIds length must match"); + assertEq(a.nodes.length, b.nodes.length, "nodes length must match"); assertEq(a.offchainConfig, b.offchainConfig, "offchainConfig must match"); - for (uint256 i = 0; i < a.p2pIds.length; ++i) { - assertEq(a.p2pIds[i], b.p2pIds[i], "p2pId must match"); - } - for (uint256 i = 0; i < a.signers.length; ++i) { - assertEq(a.signers[i], b.signers[i], "signer must match"); - } - for (uint256 i = 0; i < a.transmitters.length; ++i) { - assertEq(a.transmitters[i], b.transmitters[i], "transmitter must match"); + for (uint256 i = 0; i < a.nodes.length; ++i) { + assertEq(a.nodes[i].p2pId, b.nodes[i].p2pId, "p2pId must match"); + assertEq(a.nodes[i].signerKey, b.nodes[i].signerKey, "signerKey must match"); + assertEq(a.nodes[i].transmitterKey, b.nodes[i].transmitterKey, "transmitterKey must match"); } } @@ -373,28 +370,47 @@ contract CCIPConfig_chainConfig is CCIPConfigSetup { } contract CCIPConfig_validateConfig is CCIPConfigSetup { - function _getCorrectOCR3Config() internal returns (CCIPConfigTypes.OCR3Config memory) { - (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); + function _getCorrectOCR3Config(uint8 numNodes, uint8 FRoleDON) internal returns (CCIPConfigTypes.OCR3Config memory) { + CCIPConfigTypes.OCR3Node[] memory nodes = _addChainConfig(numNodes); return CCIPConfigTypes.OCR3Config({ pluginType: Internal.OCRPluginType.Commit, offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), chainSelector: 1, - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, + nodes: nodes, + FRoleDON: FRoleDON, offchainConfigVersion: 30, offchainConfig: bytes("offchainConfig") }); } + function _getCorrectOCR3Config() internal returns (CCIPConfigTypes.OCR3Config memory) { + return _getCorrectOCR3Config(4, 1); + } + // Successes. function test__validateConfig_Success() public { s_ccipCC.validateConfig(_getCorrectOCR3Config()); } + function test__validateConfigLessTransmittersThanSigners_Success() public { + // fChain is 1, so there should be at least 4 transmitters. + CCIPConfigTypes.OCR3Config memory config = _getCorrectOCR3Config(5, 1); + config.nodes[1].transmitterKey = bytes(""); + + s_ccipCC.validateConfig(config); + } + + function test__validateConfigSmallerFChain_Success() public { + CCIPConfigTypes.OCR3Config memory config = _getCorrectOCR3Config(11, 3); + + // Set fChain to 2 + _addChainConfig(4, 2); + + s_ccipCC.validateConfig(config); + } + // Reverts. function test__validateConfig_ChainSelectorNotSet_Reverts() public { @@ -434,65 +450,90 @@ contract CCIPConfig_validateConfig is CCIPConfigSetup { uint256 numberOfTransmitters = 3; // 32 > 31 (max num oracles) - (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(31); + CCIPConfigTypes.OCR3Node[] memory nodes = _addChainConfig(31); // truncate transmitters to < 3 * fChain + 1 // since fChain is 1 in this case, we need to truncate to 3 transmitters. - assembly { - mstore(transmitters, numberOfTransmitters) + for (uint256 i = numberOfTransmitters; i < nodes.length; ++i) { + nodes[i].transmitterKey = bytes(""); } - config.transmitters = transmitters; - config.p2pIds = p2pIds; - config.signers = signers; - + config.nodes = nodes; vm.expectRevert(abi.encodeWithSelector(CCIPConfig.NotEnoughTransmitters.selector, numberOfTransmitters, 4)); s_ccipCC.validateConfig(config); } + function test__validateConfig_NotEnoughTransmittersEmptyAddresses_Reverts() public { + CCIPConfigTypes.OCR3Config memory config = _getCorrectOCR3Config(); + config.nodes[0].transmitterKey = bytes(""); + + vm.expectRevert(abi.encodeWithSelector(CCIPConfig.NotEnoughTransmitters.selector, 3, 4)); + s_ccipCC.validateConfig(config); + + // Zero out remaining transmitters to verify error changes + for (uint256 i = 1; i < config.nodes.length; ++i) { + config.nodes[i].transmitterKey = bytes(""); + } + + vm.expectRevert(abi.encodeWithSelector(CCIPConfig.NotEnoughTransmitters.selector, 0, 4)); + s_ccipCC.validateConfig(config); + } + function test__validateConfig_TooManySigners_Reverts() public { CCIPConfigTypes.OCR3Config memory config = _getCorrectOCR3Config(); - config.signers = new bytes[](257); + config.nodes = new CCIPConfigTypes.OCR3Node[](257); vm.expectRevert(CCIPConfig.TooManySigners.selector); s_ccipCC.validateConfig(config); } + function test__validateConfig_FChainTooHigh_Reverts() public { + CCIPConfigTypes.OCR3Config memory config = _getCorrectOCR3Config(); + config.FRoleDON = 2; // too low + + // Set fChain to 3 + _addChainConfig(4, 3); + + vm.expectRevert(abi.encodeWithSelector(CCIPConfig.FChainTooHigh.selector, 3, 2)); + s_ccipCC.validateConfig(config); + } + function test__validateConfig_FMustBePositive_Reverts() public { CCIPConfigTypes.OCR3Config memory config = _getCorrectOCR3Config(); - config.F = 0; // not positive + config.FRoleDON = 0; // not positive - vm.expectRevert(CCIPConfig.FMustBePositive.selector); + vm.expectRevert(abi.encodeWithSelector(CCIPConfig.FChainTooHigh.selector, 1, 0)); s_ccipCC.validateConfig(config); } function test__validateConfig_FTooHigh_Reverts() public { CCIPConfigTypes.OCR3Config memory config = _getCorrectOCR3Config(); - config.F = 2; // too high + config.FRoleDON = 2; // too high vm.expectRevert(CCIPConfig.FTooHigh.selector); s_ccipCC.validateConfig(config); } - function test__validateConfig_P2PIdsLengthNotMatching_Reverts() public { + function test__validateConfig_ZeroP2PId_Reverts() public { CCIPConfigTypes.OCR3Config memory config = _getCorrectOCR3Config(); + config.nodes[1].p2pId = bytes32(0); - uint256 expectedNumberOfP2pIds = config.signers.length; - uint256 wrongNumberOfP2pIds = expectedNumberOfP2pIds - 1; - config.p2pIds = new bytes32[](wrongNumberOfP2pIds); // Not enough + vm.expectRevert(abi.encodeWithSelector(CCIPConfig.InvalidNode.selector, config.nodes[1])); + s_ccipCC.validateConfig(config); + } - vm.expectRevert( - abi.encodeWithSelector( - CCIPConfig.P2PIdsLengthNotMatching.selector, wrongNumberOfP2pIds, expectedNumberOfP2pIds, expectedNumberOfP2pIds - ) - ); + function test__validateConfig_ZeroSignerKey_Reverts() public { + CCIPConfigTypes.OCR3Config memory config = _getCorrectOCR3Config(); + config.nodes[2].signerKey = bytes(""); + + vm.expectRevert(abi.encodeWithSelector(CCIPConfig.InvalidNode.selector, config.nodes[2])); s_ccipCC.validateConfig(config); } function test__validateConfig_NodeNotInRegistry_Reverts() public { - (bytes32[] memory p2pIds,,) = _addChainConfig(4); + CCIPConfigTypes.OCR3Node[] memory nodes = _addChainConfig(4); bytes32 nonExistentP2PId = keccak256("notInRegistry"); - p2pIds[0] = nonExistentP2PId; + nodes[0].p2pId = nonExistentP2PId; vm.mockCall( CAPABILITIES_REGISTRY, @@ -510,7 +551,7 @@ contract CCIPConfig_validateConfig is CCIPConfigSetup { ) ); CCIPConfigTypes.OCR3Config memory config = _getCorrectOCR3Config(); - config.p2pIds = p2pIds; + config.nodes = nodes; vm.expectRevert(abi.encodeWithSelector(CCIPConfig.NodeNotInRegistry.selector, nonExistentP2PId)); s_ccipCC.validateConfig(config); @@ -548,16 +589,20 @@ contract CCIPConfig_ConfigStateMachine is CCIPConfigSetup { // - don id change // - config count change bytes32[] memory p2pIds = _makeBytes32Array(4, 0); - bytes[] memory signers = _makeBytesArray(2, 10); - bytes[] memory transmitters = _makeBytesArray(2, 20); + bytes[] memory signers = _makeBytesArray(4, 10); + bytes[] memory transmitters = _makeBytesArray(4, 20); + + CCIPConfigTypes.OCR3Node[] memory nodes = new CCIPConfigTypes.OCR3Node[](4); + for (uint256 i = 0; i < 4; ++i) { + nodes[i] = CCIPConfigTypes.OCR3Node({p2pId: p2pIds[i], signerKey: signers[i], transmitterKey: transmitters[i]}); + } + CCIPConfigTypes.OCR3Config memory config = CCIPConfigTypes.OCR3Config({ pluginType: Internal.OCRPluginType.Commit, offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), chainSelector: 1, - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, + nodes: nodes, + FRoleDON: 1, offchainConfigVersion: 30, offchainConfig: bytes("offchainConfig") }); @@ -592,16 +637,19 @@ contract CCIPConfig_ConfigStateMachine is CCIPConfigSetup { bytes32[] memory p2pIds = _makeBytes32Array(4, 0); bytes[] memory signers = _makeBytesArray(4, 10); bytes[] memory transmitters = _makeBytesArray(4, 20); + CCIPConfigTypes.OCR3Node[] memory nodes = new CCIPConfigTypes.OCR3Node[](4); + for (uint256 i = 0; i < 4; ++i) { + nodes[i] = CCIPConfigTypes.OCR3Node({p2pId: p2pIds[i], signerKey: signers[i], transmitterKey: transmitters[i]}); + } + CCIPConfigTypes.OCR3Config[] memory cfgs = new CCIPConfigTypes.OCR3Config[](numCommitCfgs + numExecCfgs); for (uint256 i = 0; i < numCommitCfgs; i++) { cfgs[i] = CCIPConfigTypes.OCR3Config({ pluginType: Internal.OCRPluginType.Commit, offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), chainSelector: 1, - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, + nodes: nodes, + FRoleDON: 1, offchainConfigVersion: 30, offchainConfig: abi.encode("commit", i) }); @@ -611,10 +659,8 @@ contract CCIPConfig_ConfigStateMachine is CCIPConfigSetup { pluginType: Internal.OCRPluginType.Execution, offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), chainSelector: 1, - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, + nodes: nodes, + FRoleDON: 1, offchainConfigVersion: 30, offchainConfig: abi.encode("exec", numCommitCfgs + i) }); @@ -635,7 +681,7 @@ contract CCIPConfig_ConfigStateMachine is CCIPConfigSetup { } function test__computeNewConfigWithMeta_InitToRunning_Success() public { - (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); + CCIPConfigTypes.OCR3Node[] memory nodes = _addChainConfig(4); uint32 donId = 1; CCIPConfigTypes.OCR3ConfigWithMeta[] memory currentConfig = new CCIPConfigTypes.OCR3ConfigWithMeta[](0); CCIPConfigTypes.OCR3Config[] memory newConfig = new CCIPConfigTypes.OCR3Config[](1); @@ -643,10 +689,8 @@ contract CCIPConfig_ConfigStateMachine is CCIPConfigSetup { pluginType: Internal.OCRPluginType.Commit, offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), chainSelector: 1, - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, + nodes: nodes, + FRoleDON: 1, offchainConfigVersion: 30, offchainConfig: bytes("commit") }); @@ -669,16 +713,14 @@ contract CCIPConfig_ConfigStateMachine is CCIPConfigSetup { } function test__computeNewConfigWithMeta_RunningToStaging_Success() public { - (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); + CCIPConfigTypes.OCR3Node[] memory nodes = _addChainConfig(4); uint32 donId = 1; CCIPConfigTypes.OCR3Config memory blueConfig = CCIPConfigTypes.OCR3Config({ pluginType: Internal.OCRPluginType.Commit, offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), chainSelector: 1, - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, + nodes: nodes, + FRoleDON: 1, offchainConfigVersion: 30, offchainConfig: bytes("commit") }); @@ -686,10 +728,8 @@ contract CCIPConfig_ConfigStateMachine is CCIPConfigSetup { pluginType: Internal.OCRPluginType.Commit, offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), chainSelector: 1, - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, + nodes: nodes, + FRoleDON: 1, offchainConfigVersion: 30, offchainConfig: bytes("commit-new") }); @@ -745,16 +785,14 @@ contract CCIPConfig_ConfigStateMachine is CCIPConfigSetup { } function test__computeNewConfigWithMeta_StagingToRunning_Success() public { - (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); + CCIPConfigTypes.OCR3Node[] memory nodes = _addChainConfig(4); uint32 donId = 1; CCIPConfigTypes.OCR3Config memory blueConfig = CCIPConfigTypes.OCR3Config({ pluginType: Internal.OCRPluginType.Commit, offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), chainSelector: 1, - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, + nodes: nodes, + FRoleDON: 1, offchainConfigVersion: 30, offchainConfig: bytes("commit") }); @@ -762,10 +800,8 @@ contract CCIPConfig_ConfigStateMachine is CCIPConfigSetup { pluginType: Internal.OCRPluginType.Commit, offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), chainSelector: 1, - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, + nodes: nodes, + FRoleDON: 1, offchainConfigVersion: 30, offchainConfig: bytes("commit-new") }); @@ -803,16 +839,14 @@ contract CCIPConfig_ConfigStateMachine is CCIPConfigSetup { } function test__validateConfigTransition_InitToRunning_Success() public { - (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); + CCIPConfigTypes.OCR3Node[] memory nodes = _addChainConfig(4); uint32 donId = 1; CCIPConfigTypes.OCR3Config memory blueConfig = CCIPConfigTypes.OCR3Config({ pluginType: Internal.OCRPluginType.Commit, offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), chainSelector: 1, - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, + nodes: nodes, + FRoleDON: 1, offchainConfigVersion: 30, offchainConfig: bytes("commit") }); @@ -829,16 +863,14 @@ contract CCIPConfig_ConfigStateMachine is CCIPConfigSetup { } function test__validateConfigTransition_RunningToStaging_Success() public { - (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); + CCIPConfigTypes.OCR3Node[] memory nodes = _addChainConfig(4); uint32 donId = 1; CCIPConfigTypes.OCR3Config memory blueConfig = CCIPConfigTypes.OCR3Config({ pluginType: Internal.OCRPluginType.Commit, offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), chainSelector: 1, - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, + nodes: nodes, + FRoleDON: 1, offchainConfigVersion: 30, offchainConfig: bytes("commit") }); @@ -846,10 +878,8 @@ contract CCIPConfig_ConfigStateMachine is CCIPConfigSetup { pluginType: Internal.OCRPluginType.Commit, offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), chainSelector: 1, - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, + nodes: nodes, + FRoleDON: 1, offchainConfigVersion: 30, offchainConfig: bytes("commit-new") }); @@ -877,16 +907,14 @@ contract CCIPConfig_ConfigStateMachine is CCIPConfigSetup { } function test__validateConfigTransition_StagingToRunning_Success() public { - (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); + CCIPConfigTypes.OCR3Node[] memory nodes = _addChainConfig(4); uint32 donId = 1; CCIPConfigTypes.OCR3Config memory blueConfig = CCIPConfigTypes.OCR3Config({ pluginType: Internal.OCRPluginType.Commit, offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), chainSelector: 1, - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, + nodes: nodes, + FRoleDON: 1, offchainConfigVersion: 30, offchainConfig: bytes("commit") }); @@ -894,10 +922,8 @@ contract CCIPConfig_ConfigStateMachine is CCIPConfigSetup { pluginType: Internal.OCRPluginType.Commit, offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), chainSelector: 1, - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, + nodes: nodes, + FRoleDON: 1, offchainConfigVersion: 30, offchainConfig: bytes("commit-new") }); @@ -942,10 +968,8 @@ contract CCIPConfig_ConfigStateMachine is CCIPConfigSetup { pluginType: Internal.OCRPluginType.Commit, offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), chainSelector: 1, - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, + nodes: _constructNodesArray(p2pIds, signers, transmitters), + FRoleDON: 1, offchainConfigVersion: 30, offchainConfig: abi.encode("commit", i) }); @@ -964,10 +988,8 @@ contract CCIPConfig_ConfigStateMachine is CCIPConfigSetup { pluginType: Internal.OCRPluginType.Execution, offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), chainSelector: 1, - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, + nodes: _constructNodesArray(p2pIds, signers, transmitters), + FRoleDON: 1, offchainConfigVersion: 30, offchainConfig: abi.encode("exec", i) }); @@ -988,10 +1010,11 @@ contract CCIPConfig_ConfigStateMachine is CCIPConfigSetup { pluginType: Internal.OCRPluginType.Commit, offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), chainSelector: 1, - p2pIds: _makeBytes32Array(4, 0), - signers: _makeBytesArray(4, 10), - transmitters: _makeBytesArray(4, 20), - F: 1, + nodes: _constructNodesArray(_makeBytes32Array(4, 0), _makeBytesArray(4, 10), _makeBytesArray(4, 20)), + // p2pIds: _makeBytes32Array(4, 0), + // signers: _makeBytesArray(4, 10), + // transmitters: _makeBytesArray(4, 20), + FRoleDON: 1, offchainConfigVersion: 30, offchainConfig: bytes("commit") }); @@ -1014,10 +1037,8 @@ contract CCIPConfig_ConfigStateMachine is CCIPConfigSetup { pluginType: Internal.OCRPluginType.Commit, offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), chainSelector: 1, - p2pIds: _makeBytes32Array(4, 0), - signers: _makeBytesArray(4, 10), - transmitters: _makeBytesArray(4, 20), - F: 1, + nodes: _constructNodesArray(_makeBytes32Array(4, 0), _makeBytesArray(4, 10), _makeBytesArray(4, 20)), + FRoleDON: 1, offchainConfigVersion: 30, offchainConfig: bytes("commit") }); @@ -1025,10 +1046,11 @@ contract CCIPConfig_ConfigStateMachine is CCIPConfigSetup { pluginType: Internal.OCRPluginType.Commit, offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), chainSelector: 1, - p2pIds: _makeBytes32Array(4, 0), - signers: _makeBytesArray(4, 10), - transmitters: _makeBytesArray(4, 20), - F: 1, + nodes: _constructNodesArray(_makeBytes32Array(4, 0), _makeBytesArray(4, 10), _makeBytesArray(4, 20)), + // p2pIds: _makeBytes32Array(4, 0), + // signers: _makeBytesArray(4, 10), + // transmitters: _makeBytesArray(4, 20), + FRoleDON: 1, offchainConfigVersion: 30, offchainConfig: bytes("commit-new") }); @@ -1068,10 +1090,8 @@ contract CCIPConfig_ConfigStateMachine is CCIPConfigSetup { pluginType: Internal.OCRPluginType.Commit, offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), chainSelector: 1, - p2pIds: _makeBytes32Array(4, 0), - signers: _makeBytesArray(4, 10), - transmitters: _makeBytesArray(4, 20), - F: 1, + nodes: _constructNodesArray(_makeBytes32Array(4, 0), _makeBytesArray(4, 10), _makeBytesArray(4, 20)), + FRoleDON: 1, offchainConfigVersion: 30, offchainConfig: bytes("commit") }); @@ -1079,10 +1099,8 @@ contract CCIPConfig_ConfigStateMachine is CCIPConfigSetup { pluginType: Internal.OCRPluginType.Commit, offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), chainSelector: 1, - p2pIds: _makeBytes32Array(4, 0), - signers: _makeBytesArray(4, 10), - transmitters: _makeBytesArray(4, 20), - F: 1, + nodes: _constructNodesArray(_makeBytes32Array(4, 0), _makeBytesArray(4, 10), _makeBytesArray(4, 20)), + FRoleDON: 1, offchainConfigVersion: 30, offchainConfig: bytes("commit-new") }); @@ -1116,10 +1134,8 @@ contract CCIPConfig_ConfigStateMachine is CCIPConfigSetup { pluginType: Internal.OCRPluginType.Commit, offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), chainSelector: 1, - p2pIds: _makeBytes32Array(4, 0), - signers: _makeBytesArray(4, 10), - transmitters: _makeBytesArray(4, 20), - F: 1, + nodes: _constructNodesArray(_makeBytes32Array(4, 0), _makeBytesArray(4, 10), _makeBytesArray(4, 20)), + FRoleDON: 1, offchainConfigVersion: 30, offchainConfig: bytes("commit") }); @@ -1127,10 +1143,8 @@ contract CCIPConfig_ConfigStateMachine is CCIPConfigSetup { pluginType: Internal.OCRPluginType.Commit, offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), chainSelector: 1, - p2pIds: _makeBytes32Array(4, 0), - signers: _makeBytesArray(4, 10), - transmitters: _makeBytesArray(4, 20), - F: 1, + nodes: _constructNodesArray(_makeBytes32Array(4, 0), _makeBytesArray(4, 10), _makeBytesArray(4, 20)), + FRoleDON: 1, offchainConfigVersion: 30, offchainConfig: bytes("commit-new") }); @@ -1176,16 +1190,14 @@ contract CCIPConfig_updatePluginConfig is CCIPConfigSetup { // Successes. function test_updatePluginConfig_InitToRunning_Success() public { - (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); + CCIPConfigTypes.OCR3Node[] memory nodes = _addChainConfig(4); uint32 donId = 1; CCIPConfigTypes.OCR3Config memory blueConfig = CCIPConfigTypes.OCR3Config({ pluginType: Internal.OCRPluginType.Commit, offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), chainSelector: 1, - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, + nodes: nodes, + FRoleDON: 1, offchainConfigVersion: 30, offchainConfig: bytes("commit") }); @@ -1211,17 +1223,15 @@ contract CCIPConfig_updatePluginConfig is CCIPConfigSetup { } function test_updatePluginConfig_RunningToStaging_Success() public { - (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); + CCIPConfigTypes.OCR3Node[] memory nodes = _addChainConfig(4); // add blue config. uint32 donId = 1; CCIPConfigTypes.OCR3Config memory blueConfig = CCIPConfigTypes.OCR3Config({ pluginType: Internal.OCRPluginType.Commit, offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), chainSelector: 1, - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, + nodes: nodes, + FRoleDON: 1, offchainConfigVersion: 30, offchainConfig: bytes("commit") }); @@ -1234,10 +1244,8 @@ contract CCIPConfig_updatePluginConfig is CCIPConfigSetup { pluginType: Internal.OCRPluginType.Commit, offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), chainSelector: 1, - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, + nodes: nodes, + FRoleDON: 1, offchainConfigVersion: 30, offchainConfig: bytes("commit-new") }); @@ -1270,17 +1278,15 @@ contract CCIPConfig_updatePluginConfig is CCIPConfigSetup { } function test_updatePluginConfig_StagingToRunning_Success() public { - (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); + CCIPConfigTypes.OCR3Node[] memory nodes = _addChainConfig(4); // add blue config. uint32 donId = 1; CCIPConfigTypes.OCR3Config memory blueConfig = CCIPConfigTypes.OCR3Config({ pluginType: Internal.OCRPluginType.Commit, offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), chainSelector: 1, - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, + nodes: nodes, + FRoleDON: 1, offchainConfigVersion: 30, offchainConfig: bytes("commit") }); @@ -1293,10 +1299,8 @@ contract CCIPConfig_updatePluginConfig is CCIPConfigSetup { pluginType: Internal.OCRPluginType.Commit, offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), chainSelector: 1, - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, + nodes: nodes, + FRoleDON: 1, offchainConfigVersion: 30, offchainConfig: bytes("commit-new") }); @@ -1356,7 +1360,7 @@ contract CCIPConfig_beforeCapabilityConfigSet is CCIPConfigSetup { } function test_beforeCapabilityConfigSet_CommitConfigOnly_Success() public { - (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); + CCIPConfigTypes.OCR3Node[] memory nodes = _addChainConfig(4); changePrank(CAPABILITIES_REGISTRY); uint32 donId = 1; @@ -1364,10 +1368,8 @@ contract CCIPConfig_beforeCapabilityConfigSet is CCIPConfigSetup { pluginType: Internal.OCRPluginType.Commit, offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), chainSelector: 1, - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, + nodes: nodes, + FRoleDON: 1, offchainConfigVersion: 30, offchainConfig: bytes("commit") }); @@ -1387,7 +1389,7 @@ contract CCIPConfig_beforeCapabilityConfigSet is CCIPConfigSetup { } function test_beforeCapabilityConfigSet_ExecConfigOnly_Success() public { - (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); + CCIPConfigTypes.OCR3Node[] memory nodes = _addChainConfig(4); changePrank(CAPABILITIES_REGISTRY); uint32 donId = 1; @@ -1395,10 +1397,8 @@ contract CCIPConfig_beforeCapabilityConfigSet is CCIPConfigSetup { pluginType: Internal.OCRPluginType.Execution, offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), chainSelector: 1, - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, + nodes: nodes, + FRoleDON: 1, offchainConfigVersion: 30, offchainConfig: bytes("exec") }); @@ -1420,7 +1420,7 @@ contract CCIPConfig_beforeCapabilityConfigSet is CCIPConfigSetup { } function test_beforeCapabilityConfigSet_CommitAndExecConfig_Success() public { - (bytes32[] memory p2pIds, bytes[] memory signers, bytes[] memory transmitters) = _addChainConfig(4); + CCIPConfigTypes.OCR3Node[] memory nodes = _addChainConfig(4); changePrank(CAPABILITIES_REGISTRY); uint32 donId = 1; @@ -1428,10 +1428,8 @@ contract CCIPConfig_beforeCapabilityConfigSet is CCIPConfigSetup { pluginType: Internal.OCRPluginType.Commit, offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), chainSelector: 1, - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, + nodes: nodes, + FRoleDON: 1, offchainConfigVersion: 30, offchainConfig: bytes("commit") }); @@ -1439,10 +1437,8 @@ contract CCIPConfig_beforeCapabilityConfigSet is CCIPConfigSetup { pluginType: Internal.OCRPluginType.Execution, offrampAddress: abi.encodePacked(keccak256(abi.encode("offramp"))), chainSelector: 1, - p2pIds: p2pIds, - signers: signers, - transmitters: transmitters, - F: 1, + nodes: nodes, + FRoleDON: 1, offchainConfigVersion: 30, offchainConfig: bytes("exec") }); diff --git a/contracts/src/v0.8/ccip/test/ocr/MultiOCR3Base.t.sol b/contracts/src/v0.8/ccip/test/ocr/MultiOCR3Base.t.sol index 8867d1b127..2783608e68 100644 --- a/contracts/src/v0.8/ccip/test/ocr/MultiOCR3Base.t.sol +++ b/contracts/src/v0.8/ccip/test/ocr/MultiOCR3Base.t.sol @@ -373,6 +373,48 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { _assertOCRConfigEquality(s_multiOCR3.latestConfigDetails(0), expectedConfig); } + function test_SetConfigWithSignersMismatchingTransmitters_Success() public { + uint8 F = 2; + + _assertOCRConfigUnconfigured(s_multiOCR3.latestConfigDetails(0)); + + MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); + ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ + ocrPluginType: 0, + configDigest: _getBasicConfigDigest(F, s_validSigners, s_partialTransmitters), + F: F, + isSignatureVerificationEnabled: true, + signers: s_validSigners, + transmitters: s_partialTransmitters + }); + + vm.expectEmit(); + emit MultiOCR3Base.ConfigSet( + ocrConfigs[0].ocrPluginType, + ocrConfigs[0].configDigest, + ocrConfigs[0].signers, + ocrConfigs[0].transmitters, + ocrConfigs[0].F + ); + + vm.expectEmit(); + emit MultiOCR3Helper.AfterConfigSet(ocrConfigs[0].ocrPluginType); + + s_multiOCR3.setOCR3Configs(ocrConfigs); + + MultiOCR3Base.OCRConfig memory expectedConfig = MultiOCR3Base.OCRConfig({ + configInfo: MultiOCR3Base.ConfigInfo({ + configDigest: ocrConfigs[0].configDigest, + F: ocrConfigs[0].F, + n: uint8(ocrConfigs[0].signers.length), + isSignatureVerificationEnabled: ocrConfigs[0].isSignatureVerificationEnabled + }), + signers: s_validSigners, + transmitters: s_partialTransmitters + }); + _assertOCRConfigEquality(s_multiOCR3.latestConfigDetails(0), expectedConfig); + } + function test_SetConfigWithoutSigners_Success() public { uint8 F = 1; address[] memory signers = new address[](0); @@ -530,8 +572,12 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { function test_Fuzz_SetConfig_Success(MultiOCR3Base.OCRConfigArgs memory ocrConfig, uint64 randomAddressOffset) public { // condition: cannot assume max oracle count - vm.assume(ocrConfig.transmitters.length <= 31); - vm.assume(ocrConfig.signers.length <= 31); + vm.assume(ocrConfig.transmitters.length <= 255); + vm.assume(ocrConfig.signers.length <= 255); + // condition: at least one transmitter + vm.assume(ocrConfig.transmitters.length > 0); + // condition: number of transmitters does not exceed signers + vm.assume(ocrConfig.signers.length == 0 || ocrConfig.transmitters.length <= ocrConfig.signers.length); // condition: F > 0 ocrConfig.F = uint8(bound(ocrConfig.F, 1, 3)); @@ -839,7 +885,7 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { function test_FTooHigh_Revert() public { address[] memory signers = new address[](0); - address[] memory transmitters = new address[](0); + address[] memory transmitters = new address[](1); MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ @@ -876,6 +922,26 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { s_multiOCR3.setOCR3Configs(ocrConfigs); } + function test_NoTransmitters_Revert() public { + address[] memory signers = new address[](0); + address[] memory transmitters = new address[](0); + + MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); + ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ + ocrPluginType: 0, + configDigest: _getBasicConfigDigest(10, signers, transmitters), + F: 1, + isSignatureVerificationEnabled: false, + signers: signers, + transmitters: transmitters + }); + + vm.expectRevert( + abi.encodeWithSelector(MultiOCR3Base.InvalidConfig.selector, MultiOCR3Base.InvalidConfigErrorType.NO_TRANSMITTERS) + ); + s_multiOCR3.setOCR3Configs(ocrConfigs); + } + function test_TooManyTransmitters_Revert() public { address[] memory signers = new address[](0); address[] memory transmitters = new address[](257); @@ -918,4 +984,23 @@ contract MultiOCR3Base_setOCR3Configs is MultiOCR3BaseSetup { ); s_multiOCR3.setOCR3Configs(ocrConfigs); } + + function test_MoreTransmittersThanSigners_Revert() public { + MultiOCR3Base.OCRConfigArgs[] memory ocrConfigs = new MultiOCR3Base.OCRConfigArgs[](1); + ocrConfigs[0] = MultiOCR3Base.OCRConfigArgs({ + ocrPluginType: 0, + configDigest: _getBasicConfigDigest(1, s_validSigners, s_partialTransmitters), + F: 1, + isSignatureVerificationEnabled: true, + signers: s_partialSigners, + transmitters: s_validTransmitters + }); + + vm.expectRevert( + abi.encodeWithSelector( + MultiOCR3Base.InvalidConfig.selector, MultiOCR3Base.InvalidConfigErrorType.TOO_MANY_TRANSMITTERS + ) + ); + s_multiOCR3.setOCR3Configs(ocrConfigs); + } } diff --git a/core/gethwrappers/ccip/generated/ccip_config/ccip_config.go b/core/gethwrappers/ccip/generated/ccip_config/ccip_config.go index 380819d6ac..990209e958 100644 --- a/core/gethwrappers/ccip/generated/ccip_config/ccip_config.go +++ b/core/gethwrappers/ccip/generated/ccip_config/ccip_config.go @@ -44,12 +44,10 @@ type CCIPConfigTypesChainConfigInfo struct { type CCIPConfigTypesOCR3Config struct { PluginType uint8 ChainSelector uint64 - F uint8 + FRoleDON uint8 OffchainConfigVersion uint64 OfframpAddress []byte - P2pIds [][32]byte - Signers [][]byte - Transmitters [][]byte + Nodes []CCIPConfigTypesOCR3Node OffchainConfig []byte } @@ -59,9 +57,15 @@ type CCIPConfigTypesOCR3ConfigWithMeta struct { ConfigDigest [32]byte } +type CCIPConfigTypesOCR3Node struct { + P2pId [32]byte + SignerKey []byte + TransmitterKey []byte +} + var CCIPConfigMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"capabilitiesRegistry\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainSelectorNotFound\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ChainSelectorNotSet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FChainMustBePositive\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FMustBePositive\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FTooHigh\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"length\",\"type\":\"uint256\"}],\"name\":\"InvalidConfigLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enumCCIPConfigTypes.ConfigState\",\"name\":\"currentState\",\"type\":\"uint8\"},{\"internalType\":\"enumCCIPConfigTypes.ConfigState\",\"name\":\"proposedState\",\"type\":\"uint8\"}],\"name\":\"InvalidConfigStateTransition\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidPluginType\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"}],\"name\":\"NodeNotInRegistry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonExistentConfigTransition\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"got\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minimum\",\"type\":\"uint256\"}],\"name\":\"NotEnoughTransmitters\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OfframpAddressCannotBeZero\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCapabilitiesRegistryCanCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"p2pIdsLength\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"signersLength\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"transmittersLength\",\"type\":\"uint256\"}],\"name\":\"P2PIdsLengthNotMatching\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManyOCR3Configs\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManySigners\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"got\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"expected\",\"type\":\"uint64\"}],\"name\":\"WrongConfigCount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"got\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"}],\"name\":\"WrongConfigDigest\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"got\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"}],\"name\":\"WrongConfigDigestBlueGreen\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"CapabilityConfigurationSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainConfigRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes32[]\",\"name\":\"readers\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint8\",\"name\":\"fChain\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"structCCIPConfigTypes.ChainConfig\",\"name\":\"chainConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"indexed\":true,\"internalType\":\"uint8\",\"name\":\"pluginType\",\"type\":\"uint8\"},{\"components\":[{\"components\":[{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offrampAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"p2pIds\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes[]\",\"name\":\"signers\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes[]\",\"name\":\"transmitters\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPConfigTypes.OCR3Config\",\"name\":\"config\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"configCount\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"indexed\":false,\"internalType\":\"structCCIPConfigTypes.OCR3ConfigWithMeta[]\",\"name\":\"config\",\"type\":\"tuple[]\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"chainSelectorRemoves\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes32[]\",\"name\":\"readers\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint8\",\"name\":\"fChain\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPConfigTypes.ChainConfig\",\"name\":\"chainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structCCIPConfigTypes.ChainConfigInfo[]\",\"name\":\"chainConfigAdds\",\"type\":\"tuple[]\"}],\"name\":\"applyChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"}],\"name\":\"beforeCapabilityConfigSet\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"pageIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pageSize\",\"type\":\"uint256\"}],\"name\":\"getAllChainConfigs\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes32[]\",\"name\":\"readers\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint8\",\"name\":\"fChain\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPConfigTypes.ChainConfig\",\"name\":\"chainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structCCIPConfigTypes.ChainConfigInfo[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"name\":\"getCapabilityConfiguration\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"configuration\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCapabilityRegistry\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNumChainConfigurations\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"}],\"name\":\"getOCRConfig\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offrampAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"p2pIds\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes[]\",\"name\":\"signers\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes[]\",\"name\":\"transmitters\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPConfigTypes.OCR3Config\",\"name\":\"config\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"configCount\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"internalType\":\"structCCIPConfigTypes.OCR3ConfigWithMeta[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x60a06040523480156200001157600080fd5b5060405162004110380380620041108339810160408190526200003491620001a6565b33806000816200008b5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000be57620000be81620000fb565b5050506001600160a01b038116620000e9576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b0316608052620001d8565b336001600160a01b03821603620001555760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000082565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600060208284031215620001b957600080fd5b81516001600160a01b0381168114620001d157600080fd5b9392505050565b608051613f0e620002026000396000818161010301528181610ed901526111490152613f0e6000f3fe608060405234801561001057600080fd5b50600436106100d45760003560e01c80638318ed5d11610081578063f2fde38b1161005b578063f2fde38b14610230578063f442c89a14610243578063fba64a7c1461025657600080fd5b80638318ed5d146101d15780638da5cb5b146101f2578063b74b23561461021057600080fd5b80634bd0473f116100b25780634bd0473f1461019157806379ba5097146101b15780637ac0d41e146101bb57600080fd5b806301ffc9a7146100d9578063020330e614610101578063181f5a7714610148575b600080fd5b6100ec6100e7366004612d4c565b610269565b60405190151581526020015b60405180910390f35b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100f8565b6101846040518060400160405280601481526020017f43434950436f6e66696720312e362e302d64657600000000000000000000000081525081565b6040516100f89190612df2565b6101a461019f366004612e36565b610302565b6040516100f89190612f55565b6101b961077a565b005b6101c361087c565b6040519081526020016100f8565b6101846101df366004613111565b5060408051602081019091526000815290565b60005473ffffffffffffffffffffffffffffffffffffffff16610123565b61022361021e36600461312e565b61088d565b6040516100f89190613194565b6101b961023e366004613224565b610b0e565b6101b96102513660046132a6565b610b22565b6101b961026436600461332a565b610ec1565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f78bea7210000000000000000000000000000000000000000000000000000000014806102fc57507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b63ffffffff8216600090815260056020526040812060609183600181111561032c5761032c612e6b565b600181111561033d5761033d612e6b565b8152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b8282101561076e57600084815260209020604080516101808101909152600884029091018054829060608201908390829060ff1660018111156103b0576103b0612e6b565b60018111156103c1576103c1612e6b565b8152815467ffffffffffffffff61010082048116602084015260ff690100000000000000000083041660408401526a0100000000000000000000909104166060820152600182018054608090920191610419906133e7565b80601f0160208091040260200160405190810160405280929190818152602001828054610445906133e7565b80156104925780601f1061046757610100808354040283529160200191610492565b820191906000526020600020905b81548152906001019060200180831161047557829003601f168201915b50505050508152602001600282018054806020026020016040519081016040528092919081815260200182805480156104ea57602002820191906000526020600020905b8154815260200190600101908083116104d6575b5050505050815260200160038201805480602002602001604051908101604052809291908181526020016000905b828210156105c4578382906000526020600020018054610537906133e7565b80601f0160208091040260200160405190810160405280929190818152602001828054610563906133e7565b80156105b05780601f10610585576101008083540402835291602001916105b0565b820191906000526020600020905b81548152906001019060200180831161059357829003601f168201915b505050505081526020019060010190610518565b50505050815260200160048201805480602002602001604051908101604052809291908181526020016000905b8282101561069d578382906000526020600020018054610610906133e7565b80601f016020809104026020016040519081016040528092919081815260200182805461063c906133e7565b80156106895780601f1061065e57610100808354040283529160200191610689565b820191906000526020600020905b81548152906001019060200180831161066c57829003601f168201915b5050505050815260200190600101906105f1565b5050505081526020016005820180546106b5906133e7565b80601f01602080910402602001604051908101604052809291908181526020018280546106e1906133e7565b801561072e5780601f106107035761010080835404028352916020019161072e565b820191906000526020600020905b81548152906001019060200180831161071157829003601f168201915b505050919092525050508152600682015467ffffffffffffffff16602080830191909152600790920154604090910152908252600192909201910161036b565b50505050905092915050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610800576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b60006108886003610f7c565b905090565b6060600061089b6003610f7c565b905060006108a98486613469565b90508315806108b85750818110155b156108f85760408051600080825260208201909252906108ee565b6108db612aeb565b8152602001906001900390816108d35790505b50925050506102fc565b600061090485836134af565b9050828111156109115750815b600061091d83836134c2565b67ffffffffffffffff81111561093557610935613480565b60405190808252806020026020018201604052801561096e57816020015b61095b612aeb565b8152602001906001900390816109535790505b509050600061097d6003610f86565b9050835b83811015610b0157600082828151811061099d5761099d6134d5565b60209081029190910181015160408051808201825267ffffffffffffffff831680825260009081526002855282902082518154608081880283018101909552606082018181529597509295860194909391928492849190840182828015610a2357602002820191906000526020600020905b815481526020019060010190808311610a0f575b5050509183525050600182015460ff166020820152600282018054604090920191610a4d906133e7565b80601f0160208091040260200160405190810160405280929190818152602001828054610a79906133e7565b8015610ac65780601f10610a9b57610100808354040283529160200191610ac6565b820191906000526020600020905b815481529060010190602001808311610aa957829003601f168201915b50505091909252505050905284610add88856134c2565b81518110610aed57610aed6134d5565b602090810291909101015250600101610981565b5090979650505050505050565b610b16610f9a565b610b1f8161101d565b50565b610b2a610f9a565b60005b83811015610d1057610b71858583818110610b4a57610b4a6134d5565b9050602002016020810190610b5f9190613504565b60039067ffffffffffffffff16611112565b610bdb57848482818110610b8757610b876134d5565b9050602002016020810190610b9c9190613504565b6040517f1bd4d2d200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016107f7565b60026000868684818110610bf157610bf16134d5565b9050602002016020810190610c069190613504565b67ffffffffffffffff1681526020810191909152604001600090812090610c2d8282612b33565b6001820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055610c65600283016000612b51565b5050610ca3858583818110610c7c57610c7c6134d5565b9050602002016020810190610c919190613504565b60039067ffffffffffffffff1661112a565b507f2a680691fef3b2d105196805935232c661ce703e92d464ef0b94a7bc62d714f0858583818110610cd757610cd76134d5565b9050602002016020810190610cec9190613504565b60405167ffffffffffffffff909116815260200160405180910390a1600101610b2d565b5060005b81811015610eba576000838383818110610d3057610d306134d5565b9050602002810190610d42919061351f565b610d5090602081019061355d565b610d599061375f565b90506000848484818110610d6f57610d6f6134d5565b9050602002810190610d81919061351f565b610d8f906020810190613504565b9050610d9e8260000151611136565b816020015160ff16600003610ddf576040517fa9b3766e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff81166000908152600260209081526040909120835180518593610e0f928492910190612b8b565b5060208201516001820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff90921691909117905560408201516002820190610e5c9082613846565b50610e7691506003905067ffffffffffffffff8316611282565b507f05dd57854af2c291a94ea52e7c43d80bc3be7fa73022f98b735dea86642fa5e08183604051610ea8929190613960565b60405180910390a15050600101610d14565b5050505050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610f30576040517fac7a7efd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080610f47610f4286880188613a0b565b61128e565b8151919350915015610f5f57610f5f836000846114d9565b805115610f7257610f72836001836114d9565b5050505050505050565b60006102fc825490565b60606000610f9383611c98565b9392505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461101b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016107f7565b565b3373ffffffffffffffffffffffffffffffffffffffff82160361109c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016107f7565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60008181526001830160205260408120541515610f93565b6000610f938383611cf4565b60005b815181101561127e5760008019167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166350c946fe848481518110611195576111956134d5565b60200260200101516040518263ffffffff1660e01b81526004016111bb91815260200190565b600060405180830381865afa1580156111d8573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261121e9190810190613c56565b608001510361127657818181518110611239576112396134d5565b60200260200101516040517f8907a4fa0000000000000000000000000000000000000000000000000000000081526004016107f791815260200190565b600101611139565b5050565b6000610f938383611dee565b606080600460ff16835111156112d0576040517f8854586400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160028082526060820190925290816020015b61134d6040805161012081019091528060008152602001600067ffffffffffffffff168152602001600060ff168152602001600067ffffffffffffffff16815260200160608152602001606081526020016060815260200160608152602001606081525090565b8152602001906001900390816112e657505060408051600280825260608201909252919350602082015b6113de6040805161012081019091528060008152602001600067ffffffffffffffff168152602001600060ff168152602001600067ffffffffffffffff16815260200160608152602001606081526020016060815260200160608152602001606081525090565b81526020019060019003908161137757905050905060008060005b85518110156114cc576000868281518110611416576114166134d5565b602002602001015160000151600181111561143357611433612e6b565b036114805785818151811061144a5761144a6134d5565b6020026020010151858481518110611464576114646134d5565b60200260200101819052508261147990613d2e565b92506114c4565b858181518110611492576114926134d5565b60200260200101518483815181106114ac576114ac6134d5565b6020026020010181905250816114c190613d2e565b91505b6001016113f9565b5090835281529092909150565b63ffffffff831660009081526005602052604081208184600181111561150157611501612e6b565b600181111561151257611512612e6b565b8152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b8282101561194357600084815260209020604080516101808101909152600884029091018054829060608201908390829060ff16600181111561158557611585612e6b565b600181111561159657611596612e6b565b8152815467ffffffffffffffff61010082048116602084015260ff690100000000000000000083041660408401526a01000000000000000000009091041660608201526001820180546080909201916115ee906133e7565b80601f016020809104026020016040519081016040528092919081815260200182805461161a906133e7565b80156116675780601f1061163c57610100808354040283529160200191611667565b820191906000526020600020905b81548152906001019060200180831161164a57829003601f168201915b50505050508152602001600282018054806020026020016040519081016040528092919081815260200182805480156116bf57602002820191906000526020600020905b8154815260200190600101908083116116ab575b5050505050815260200160038201805480602002602001604051908101604052809291908181526020016000905b8282101561179957838290600052602060002001805461170c906133e7565b80601f0160208091040260200160405190810160405280929190818152602001828054611738906133e7565b80156117855780601f1061175a57610100808354040283529160200191611785565b820191906000526020600020905b81548152906001019060200180831161176857829003601f168201915b5050505050815260200190600101906116ed565b50505050815260200160048201805480602002602001604051908101604052809291908181526020016000905b828210156118725783829060005260206000200180546117e5906133e7565b80601f0160208091040260200160405190810160405280929190818152602001828054611811906133e7565b801561185e5780601f106118335761010080835404028352916020019161185e565b820191906000526020600020905b81548152906001019060200180831161184157829003601f168201915b5050505050815260200190600101906117c6565b50505050815260200160058201805461188a906133e7565b80601f01602080910402602001604051908101604052809291908181526020018280546118b6906133e7565b80156119035780601f106118d857610100808354040283529160200191611903565b820191906000526020600020905b8154815290600101906020018083116118e657829003601f168201915b505050919092525050508152600682015467ffffffffffffffff166020808301919091526007909201546040909101529082526001929092019101611540565b50505050905060006119558251611e3d565b905060006119638451611e3d565b905061196f8282611e8f565b600061197e8785878686611f4b565b905061198a848261232f565b63ffffffff87166000908152600560205260408120908760018111156119b2576119b2612e6b565b60018111156119c3576119c3612e6b565b815260200190815260200160002060006119dd9190612bd6565b60005b8151811015611c3b5763ffffffff8816600090815260056020526040812090886001811115611a1157611a11612e6b565b6001811115611a2257611a22612e6b565b8152602001908152602001600020828281518110611a4257611a426134d5565b6020908102919091018101518254600181810185556000948552929093208151805160089095029091018054929490939192849283917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016908381811115611aac57611aac612e6b565b021790555060208201518154604084015160608501517fffffffffffffffffffffffffffffffffffffffffffff000000000000000000ff90921661010067ffffffffffffffff948516027fffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffff1617690100000000000000000060ff90921691909102177fffffffffffffffffffffffffffff0000000000000000ffffffffffffffffffff166a0100000000000000000000929091169190910217815560808201516001820190611b7b9082613846565b5060a08201518051611b97916002840191602090910190612b8b565b5060c08201518051611bb3916003840191602090910190612bf7565b5060e08201518051611bcf916004840191602090910190612bf7565b506101008201516005820190611be59082613846565b50505060208201516006820180547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff9092169190911790556040909101516007909101556001016119e0565b50856001811115611c4e57611c4e612e6b565b60ff168763ffffffff167f403420f960fcf8fdad51d01bc3af8668c5963e6746c63c8f5363c26d9d44514883604051611c879190612f55565b60405180910390a350505050505050565b606081600001805480602002602001604051908101604052809291908181526020018280548015611ce857602002820191906000526020600020905b815481526020019060010190808311611cd4575b50505050509050919050565b60008181526001830160205260408120548015611ddd576000611d186001836134c2565b8554909150600090611d2c906001906134c2565b9050808214611d91576000866000018281548110611d4c57611d4c6134d5565b9060005260206000200154905080876000018481548110611d6f57611d6f6134d5565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080611da257611da2613d66565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506102fc565b60009150506102fc565b5092915050565b6000818152600183016020526040812054611e35575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556102fc565b5060006102fc565b60006002821115611e7d576040517f3e478526000000000000000000000000000000000000000000000000000000008152600481018390526024016107f7565b8160028111156102fc576102fc612e6b565b6000826002811115611ea357611ea3612e6b565b826002811115611eb557611eb5612e6b565b611ebf9190613d95565b90508060011480611f0b5750807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff148015611f0b57506002836002811115611f0957611f09612e6b565b145b15611f1557505050565b82826040517f0a6b675b0000000000000000000000000000000000000000000000000000000081526004016107f7929190613dc5565b60606000845167ffffffffffffffff811115611f6957611f69613480565b604051908082528060200260200182016040528015611f92578160200160208202803683370190505b5090506000846002811115611fa957611fa9612e6b565b148015611fc757506001836002811115611fc557611fc5612e6b565b145b1561200857600181600081518110611fe157611fe16134d5565b602002602001019067ffffffffffffffff16908167ffffffffffffffff1681525050612170565b600184600281111561201c5761201c612e6b565b14801561203a5750600283600281111561203857612038612e6b565b145b156120d15785600081518110612052576120526134d5565b60200260200101516020015181600081518110612071576120716134d5565b602002602001019067ffffffffffffffff16908167ffffffffffffffff1681525050856000815181106120a6576120a66134d5565b60200260200101516020015160016120be9190613de0565b81600181518110611fe157611fe16134d5565b60028460028111156120e5576120e5612e6b565b1480156121035750600183600281111561210157612101612e6b565b145b1561213a578560018151811061211b5761211b6134d5565b60200260200101516020015181600081518110611fe157611fe16134d5565b83836040517f0a6b675b0000000000000000000000000000000000000000000000000000000081526004016107f7929190613dc5565b6000855167ffffffffffffffff81111561218c5761218c613480565b60405190808252806020026020018201604052801561223a57816020015b6040805161018081018252600060608083018281526080840183905260a0840183905260c0840183905260e08401829052610100840182905261012084018290526101408401829052610160840191909152825260208083018290529282015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816121aa5790505b50905060005b82518110156123235761226b87828151811061225e5761225e6134d5565b60200260200101516126ae565b6040518060600160405280888381518110612288576122886134d5565b602002602001015181526020018483815181106122a7576122a76134d5565b602002602001015167ffffffffffffffff1681526020016122fb8b8685815181106122d4576122d46134d5565b60200260200101518b86815181106122ee576122ee6134d5565b6020026020010151612a1d565b815250828281518110612310576123106134d5565b6020908102919091010152600101612240565b50979650505050505050565b81518151811580156123415750806001145b156123e35782600081518110612359576123596134d5565b60200260200101516020015167ffffffffffffffff166001146123dd5782600081518110612389576123896134d5565b60209081029190910181015101516040517fc1658eb800000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9091166004820152600160248201526044016107f7565b50505050565b8160011480156123f35750806002145b156125a9578360008151811061240b5761240b6134d5565b6020026020010151604001518360008151811061242a5761242a6134d5565b602002602001015160400151146124b6578260008151811061244e5761244e6134d5565b6020026020010151604001518460008151811061246d5761246d6134d5565b6020026020010151604001516040517fc7ccdd7f0000000000000000000000000000000000000000000000000000000081526004016107f7929190918252602082015260400190565b836000815181106124c9576124c96134d5565b60200260200101516020015160016124e19190613de0565b67ffffffffffffffff16836001815181106124fe576124fe6134d5565b60200260200101516020015167ffffffffffffffff16146123dd578260018151811061252c5761252c6134d5565b6020026020010151602001518460008151811061254b5761254b6134d5565b60200260200101516020015160016125639190613de0565b6040517fc1658eb800000000000000000000000000000000000000000000000000000000815267ffffffffffffffff9283166004820152911660248201526044016107f7565b8160021480156125b95750806001145b1561267c57836001815181106125d1576125d16134d5565b602002602001015160400151836000815181106125f0576125f06134d5565b602002602001015160400151146123dd5782600081518110612614576126146134d5565b60200260200101516040015184600181518110612633576126336134d5565b6020026020010151604001516040517f9e9756700000000000000000000000000000000000000000000000000000000081526004016107f7929190918252602082015260400190565b6040517f1f1b2bb600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806020015167ffffffffffffffff166000036126f6576040517f698cf8e000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008151600181111561270b5761270b612e6b565b1415801561272c575060018151600181111561272957612729612e6b565b14155b15612763576040517f3302dbd700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60808101515115806127a0575060408051600060208201520160405160208183030381529060405280519060200120816080015180519060200120145b156127d7576040517f358c192700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208101516127f29060039067ffffffffffffffff16611112565b61283a5760208101516040517f1bd4d2d200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016107f7565b60208082015167ffffffffffffffff1660009081526002909152604081206001015461286a9060ff166003613e01565b612875906001613e1d565b60ff169050808260e001515110156128ca5760e0820151516040517f548dd21f0000000000000000000000000000000000000000000000000000000081526004810191909152602481018290526044016107f7565b60c08201515161010081111561290c576040517f1b925da600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8260a00151518114158061292557508260e00151518114155b1561297f5760a08301515160c08401515160e0850151516040517fba900f6d0000000000000000000000000000000000000000000000000000000081526004810193909352602483019190915260448201526064016107f7565b826040015160ff166000036129c0576040517f39d1a4d000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408301516129d0906003613e01565b60ff168111612a0b576040517f4856694e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612a188360a00151611136565b505050565b60008082602001518584600001518560800151878760a001518860c001518960e001518a604001518b606001518c6101000151604051602001612a6a9b9a99989796959493929190613e36565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e0a000000000000000000000000000000000000000000000000000000000000179150509392505050565b6040518060400160405280600067ffffffffffffffff168152602001612b2e604051806060016040528060608152602001600060ff168152602001606081525090565b905290565b5080546000825590600052602060002090810190610b1f9190612c49565b508054612b5d906133e7565b6000825580601f10612b6d575050565b601f016020900490600052602060002090810190610b1f9190612c49565b828054828255906000526020600020908101928215612bc6579160200282015b82811115612bc6578251825591602001919060010190612bab565b50612bd2929150612c49565b5090565b5080546000825560080290600052602060002090810190610b1f9190612c5e565b828054828255906000526020600020908101928215612c3d579160200282015b82811115612c3d5782518290612c2d9082613846565b5091602001919060010190612c17565b50612bd2929150612d11565b5b80821115612bd25760008155600101612c4a565b80821115612bd25780547fffffffffffffffffffffffffffff00000000000000000000000000000000000016815560008181612c9d6001830182612b51565b612cab600283016000612b33565b612cb9600383016000612d2e565b612cc7600483016000612d2e565b612cd5600583016000612b51565b5050506006810180547fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000016905560006007820155600801612c5e565b80821115612bd2576000612d258282612b51565b50600101612d11565b5080546000825590600052602060002090810190610b1f9190612d11565b600060208284031215612d5e57600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610f9357600080fd5b6000815180845260005b81811015612db457602081850181015186830182015201612d98565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000610f936020830184612d8e565b63ffffffff81168114610b1f57600080fd5b8035612e2281612e05565b919050565b803560028110612e2257600080fd5b60008060408385031215612e4957600080fd5b8235612e5481612e05565b9150612e6260208401612e27565b90509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60028110612eaa57612eaa612e6b565b9052565b60008151808452602080850194506020840160005b83811015612edf57815187529582019590820190600101612ec3565b509495945050505050565b60008282518085526020808601955060208260051b8401016020860160005b84811015610b01577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018952612f43838351612d8e565b98840198925090830190600101612f09565b600060208083018184528085518083526040925060408601915060408160051b87010184880160005b83811015613103577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0898403018552815160608151818652612fc38287018251612e9a565b898101516080612fde8189018367ffffffffffffffff169052565b8a830151915060a0612ff4818a018460ff169052565b938301519360c092506130128984018667ffffffffffffffff169052565b818401519450610120915060e082818b01526130326101808b0187612d8e565b95508185015191507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0610100818c890301818d01526130718885612eae565b958701518c87038301868e015295975061308b8887612eea565b9750828701519550818c8903016101408d01526130a88887612eea565b975080870151965050808b8803016101608c015250505050506130cb8282612d8e565b915050888201516130e78a87018267ffffffffffffffff169052565b5090870151938701939093529386019390860190600101612f7e565b509098975050505050505050565b60006020828403121561312357600080fd5b8135610f9381612e05565b6000806040838503121561314157600080fd5b50508035926020909101359150565b60008151606084526131656060850182612eae565b905060ff60208401511660208501526040830151848203604086015261318b8282612d8e565b95945050505050565b600060208083018184528085518083526040925060408601915060408160051b87010184880160005b83811015613103578883037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00185528151805167ffffffffffffffff16845287015187840187905261321187850182613150565b95880195935050908601906001016131bd565b60006020828403121561323657600080fd5b813573ffffffffffffffffffffffffffffffffffffffff81168114610f9357600080fd5b60008083601f84011261326c57600080fd5b50813567ffffffffffffffff81111561328457600080fd5b6020830191508360208260051b850101111561329f57600080fd5b9250929050565b600080600080604085870312156132bc57600080fd5b843567ffffffffffffffff808211156132d457600080fd5b6132e08883890161325a565b909650945060208701359150808211156132f957600080fd5b506133068782880161325a565b95989497509550505050565b803567ffffffffffffffff81168114612e2257600080fd5b6000806000806000806080878903121561334357600080fd5b863567ffffffffffffffff8082111561335b57600080fd5b6133678a838b0161325a565b9098509650602089013591508082111561338057600080fd5b818901915089601f83011261339457600080fd5b8135818111156133a357600080fd5b8a60208285010111156133b557600080fd5b6020830196508095505050506133cd60408801613312565b91506133db60608801612e17565b90509295509295509295565b600181811c908216806133fb57607f821691505b602082108103613434577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80820281158282048414176102fc576102fc61343a565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b808201808211156102fc576102fc61343a565b818103818111156102fc576102fc61343a565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561351657600080fd5b610f9382613312565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc183360301811261355357600080fd5b9190910192915050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa183360301811261355357600080fd5b604051610120810167ffffffffffffffff811182821017156135b5576135b5613480565b60405290565b60405160e0810167ffffffffffffffff811182821017156135b5576135b5613480565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561362557613625613480565b604052919050565b600067ffffffffffffffff82111561364757613647613480565b5060051b60200190565b600082601f83011261366257600080fd5b813560206136776136728361362d565b6135de565b8083825260208201915060208460051b87010193508684111561369957600080fd5b602086015b848110156136b5578035835291830191830161369e565b509695505050505050565b803560ff81168114612e2257600080fd5b600082601f8301126136e257600080fd5b813567ffffffffffffffff8111156136fc576136fc613480565b61372d60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016135de565b81815284602083860101111561374257600080fd5b816020850160208301376000918101602001919091529392505050565b60006060823603121561377157600080fd5b6040516060810167ffffffffffffffff828210818311171561379557613795613480565b8160405284359150808211156137aa57600080fd5b6137b636838701613651565b83526137c4602086016136c0565b602084015260408501359150808211156137dd57600080fd5b506137ea368286016136d1565b60408301525092915050565b601f821115612a18576000816000526020600020601f850160051c8101602086101561381f5750805b601f850160051c820191505b8181101561383e5782815560010161382b565b505050505050565b815167ffffffffffffffff81111561386057613860613480565b6138748161386e84546133e7565b846137f6565b602080601f8311600181146138c757600084156138915750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b17855561383e565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015613914578886015182559484019460019091019084016138f5565b508582101561395057878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b67ffffffffffffffff831681526040602082015260006139836040830184613150565b949350505050565b600082601f83011261399c57600080fd5b813560206139ac6136728361362d565b82815260059290921b840181019181810190868411156139cb57600080fd5b8286015b848110156136b557803567ffffffffffffffff8111156139ef5760008081fd5b6139fd8986838b01016136d1565b8452509183019183016139cf565b60006020808385031215613a1e57600080fd5b823567ffffffffffffffff80821115613a3657600080fd5b818501915085601f830112613a4a57600080fd5b8135613a586136728261362d565b81815260059190911b83018401908481019088831115613a7757600080fd5b8585015b83811015613bdf57803585811115613a9257600080fd5b8601610120818c037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001811315613ac857600080fd5b613ad0613591565b613adb8a8401612e27565b8152613ae960408401613312565b8a820152613af9606084016136c0565b6040820152613b0a60808401613312565b606082015260a083013588811115613b2157600080fd5b613b2f8e8c838701016136d1565b60808301525060c083013588811115613b4757600080fd5b613b558e8c83870101613651565b60a08301525060e083013588811115613b6e5760008081fd5b613b7c8e8c8387010161398b565b60c0830152506101008084013589811115613b975760008081fd5b613ba58f8d8388010161398b565b60e084015250918301359188831115613bbe5760008081fd5b613bcc8e8c858701016136d1565b9082015285525050918601918601613a7b565b5098975050505050505050565b8051612e2281612e05565b600082601f830112613c0857600080fd5b81516020613c186136728361362d565b8083825260208201915060208460051b870101935086841115613c3a57600080fd5b602086015b848110156136b55780518352918301918301613c3f565b600060208284031215613c6857600080fd5b815167ffffffffffffffff80821115613c8057600080fd5b9083019060e08286031215613c9457600080fd5b613c9c6135bb565b613ca583613bec565b8152613cb360208401613bec565b6020820152613cc460408401613bec565b6040820152606083015160608201526080830151608082015260a083015182811115613cef57600080fd5b613cfb87828601613bf7565b60a08301525060c083015182811115613d1357600080fd5b613d1f87828601613bf7565b60c08301525095945050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613d5f57613d5f61343a565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b8181036000831280158383131683831282161715611de757611de761343a565b60038110612eaa57612eaa612e6b565b60408101613dd38285613db5565b610f936020830184613db5565b67ffffffffffffffff818116838216019080821115611de757611de761343a565b60ff8181168382160290811690818114611de757611de761343a565b60ff81811683821601908111156102fc576102fc61343a565b600061016067ffffffffffffffff8e16835263ffffffff8d166020840152613e61604084018d612e9a565b806060840152613e738184018c612d8e565b67ffffffffffffffff8b166080850152905082810360a0840152613e97818a612eae565b905082810360c0840152613eab8189612eea565b905082810360e0840152613ebf8188612eea565b60ff8716610100850152905067ffffffffffffffff8516610120840152828103610140840152613eef8185612d8e565b9e9d505050505050505050505050505056fea164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"capabilitiesRegistry\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainSelectorNotFound\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ChainSelectorNotSet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FChainMustBePositive\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"fChain\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"FRoleDON\",\"type\":\"uint256\"}],\"name\":\"FChainTooHigh\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FTooHigh\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"length\",\"type\":\"uint256\"}],\"name\":\"InvalidConfigLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enumCCIPConfigTypes.ConfigState\",\"name\":\"currentState\",\"type\":\"uint8\"},{\"internalType\":\"enumCCIPConfigTypes.ConfigState\",\"name\":\"proposedState\",\"type\":\"uint8\"}],\"name\":\"InvalidConfigStateTransition\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"signerKey\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"transmitterKey\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPConfigTypes.OCR3Node\",\"name\":\"node\",\"type\":\"tuple\"}],\"name\":\"InvalidNode\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidPluginType\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"}],\"name\":\"NodeNotInRegistry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonExistentConfigTransition\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"got\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minimum\",\"type\":\"uint256\"}],\"name\":\"NotEnoughTransmitters\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OfframpAddressCannotBeZero\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCapabilitiesRegistryCanCall\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManyOCR3Configs\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManySigners\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"got\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"expected\",\"type\":\"uint64\"}],\"name\":\"WrongConfigCount\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"got\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"}],\"name\":\"WrongConfigDigest\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"got\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"}],\"name\":\"WrongConfigDigestBlueGreen\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"CapabilityConfigurationSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"name\":\"ChainConfigRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes32[]\",\"name\":\"readers\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint8\",\"name\":\"fChain\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"structCCIPConfigTypes.ChainConfig\",\"name\":\"chainConfig\",\"type\":\"tuple\"}],\"name\":\"ChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"indexed\":true,\"internalType\":\"uint8\",\"name\":\"pluginType\",\"type\":\"uint8\"},{\"components\":[{\"components\":[{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint8\",\"name\":\"FRoleDON\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offrampAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"signerKey\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"transmitterKey\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPConfigTypes.OCR3Node[]\",\"name\":\"nodes\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPConfigTypes.OCR3Config\",\"name\":\"config\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"configCount\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"indexed\":false,\"internalType\":\"structCCIPConfigTypes.OCR3ConfigWithMeta[]\",\"name\":\"config\",\"type\":\"tuple[]\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64[]\",\"name\":\"chainSelectorRemoves\",\"type\":\"uint64[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes32[]\",\"name\":\"readers\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint8\",\"name\":\"fChain\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPConfigTypes.ChainConfig\",\"name\":\"chainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structCCIPConfigTypes.ChainConfigInfo[]\",\"name\":\"chainConfigAdds\",\"type\":\"tuple[]\"}],\"name\":\"applyChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"}],\"name\":\"beforeCapabilityConfigSet\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"pageIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"pageSize\",\"type\":\"uint256\"}],\"name\":\"getAllChainConfigs\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes32[]\",\"name\":\"readers\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint8\",\"name\":\"fChain\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPConfigTypes.ChainConfig\",\"name\":\"chainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structCCIPConfigTypes.ChainConfigInfo[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"name\":\"getCapabilityConfiguration\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"configuration\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCapabilityRegistry\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNumChainConfigurations\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"donId\",\"type\":\"uint32\"},{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"}],\"name\":\"getOCRConfig\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint8\",\"name\":\"FRoleDON\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offrampAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"signerKey\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"transmitterKey\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPConfigTypes.OCR3Node[]\",\"name\":\"nodes\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPConfigTypes.OCR3Config\",\"name\":\"config\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"configCount\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"internalType\":\"structCCIPConfigTypes.OCR3ConfigWithMeta[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x60a06040523480156200001157600080fd5b506040516200410a3803806200410a8339810160408190526200003491620001a6565b33806000816200008b5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000be57620000be81620000fb565b5050506001600160a01b038116620000e9576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160a01b0316608052620001d8565b336001600160a01b03821603620001555760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000082565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600060208284031215620001b957600080fd5b81516001600160a01b0381168114620001d157600080fd5b9392505050565b608051613f08620002026000396000818161010301528181610e5c01526110cc0152613f086000f3fe608060405234801561001057600080fd5b50600436106100d45760003560e01c80638318ed5d11610081578063f2fde38b1161005b578063f2fde38b14610230578063f442c89a14610243578063fba64a7c1461025657600080fd5b80638318ed5d146101d15780638da5cb5b146101f2578063b74b23561461021057600080fd5b80634bd0473f116100b25780634bd0473f1461019157806379ba5097146101b15780637ac0d41e146101bb57600080fd5b806301ffc9a7146100d9578063020330e614610101578063181f5a7714610148575b600080fd5b6100ec6100e7366004612d37565b610269565b60405190151581526020015b60405180910390f35b7f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100f8565b6101846040518060400160405280601481526020017f43434950436f6e66696720312e362e302d64657600000000000000000000000081525081565b6040516100f89190612ddd565b6101a461019f366004612e21565b610302565b6040516100f89190612f45565b6101b96106fd565b005b6101c36107ff565b6040519081526020016100f8565b6101846101df3660046130b7565b5060408051602081019091526000815290565b60005473ffffffffffffffffffffffffffffffffffffffff16610123565b61022361021e3660046130d4565b610810565b6040516100f89190613164565b6101b961023e3660046131f4565b610a91565b6101b9610251366004613276565b610aa5565b6101b96102643660046132fa565b610e44565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f78bea7210000000000000000000000000000000000000000000000000000000014806102fc57507fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a700000000000000000000000000000000000000000000000000000000145b92915050565b63ffffffff8216600090815260056020526040812060609183600181111561032c5761032c612e56565b600181111561033d5761033d612e56565b8152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b828210156106f157600084815260209020604080516101408101909152600684029091018054829060608201908390829060ff1660018111156103b0576103b0612e56565b60018111156103c1576103c1612e56565b8152815467ffffffffffffffff61010082048116602084015260ff690100000000000000000083041660408401526a0100000000000000000000909104166060820152600182018054608090920191610419906133b7565b80601f0160208091040260200160405190810160405280929190818152602001828054610445906133b7565b80156104925780601f1061046757610100808354040283529160200191610492565b820191906000526020600020905b81548152906001019060200180831161047557829003601f168201915b5050505050815260200160028201805480602002602001604051908101604052809291908181526020016000905b828210156106205783829060005260206000209060030201604051806060016040529081600082015481526020016001820180546104fd906133b7565b80601f0160208091040260200160405190810160405280929190818152602001828054610529906133b7565b80156105765780601f1061054b57610100808354040283529160200191610576565b820191906000526020600020905b81548152906001019060200180831161055957829003601f168201915b5050505050815260200160028201805461058f906133b7565b80601f01602080910402602001604051908101604052809291908181526020018280546105bb906133b7565b80156106085780601f106105dd57610100808354040283529160200191610608565b820191906000526020600020905b8154815290600101906020018083116105eb57829003601f168201915b505050505081525050815260200190600101906104c0565b505050508152602001600382018054610638906133b7565b80601f0160208091040260200160405190810160405280929190818152602001828054610664906133b7565b80156106b15780601f10610686576101008083540402835291602001916106b1565b820191906000526020600020905b81548152906001019060200180831161069457829003601f168201915b505050919092525050508152600482015467ffffffffffffffff16602080830191909152600590920154604090910152908252600192909201910161036b565b50505050905092915050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610783576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b600061080b6003610eff565b905090565b6060600061081e6003610eff565b9050600061082c8486613439565b905083158061083b5750818110155b1561087b576040805160008082526020820190925290610871565b61085e612b31565b8152602001906001900390816108565790505b50925050506102fc565b6000610887858361347f565b9050828111156108945750815b60006108a08383613492565b67ffffffffffffffff8111156108b8576108b8613450565b6040519080825280602002602001820160405280156108f157816020015b6108de612b31565b8152602001906001900390816108d65790505b50905060006109006003610f09565b9050835b83811015610a84576000828281518110610920576109206134a5565b60209081029190910181015160408051808201825267ffffffffffffffff8316808252600090815260028552829020825181546080818802830181019095526060820181815295975092958601949093919284928491908401828280156109a657602002820191906000526020600020905b815481526020019060010190808311610992575b5050509183525050600182015460ff1660208201526002820180546040909201916109d0906133b7565b80601f01602080910402602001604051908101604052809291908181526020018280546109fc906133b7565b8015610a495780601f10610a1e57610100808354040283529160200191610a49565b820191906000526020600020905b815481529060010190602001808311610a2c57829003601f168201915b50505091909252505050905284610a608885613492565b81518110610a7057610a706134a5565b602090810291909101015250600101610904565b5090979650505050505050565b610a99610f1d565b610aa281610fa0565b50565b610aad610f1d565b60005b83811015610c9357610af4858583818110610acd57610acd6134a5565b9050602002016020810190610ae291906134d4565b60039067ffffffffffffffff16611095565b610b5e57848482818110610b0a57610b0a6134a5565b9050602002016020810190610b1f91906134d4565b6040517f1bd4d2d200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260240161077a565b60026000868684818110610b7457610b746134a5565b9050602002016020810190610b8991906134d4565b67ffffffffffffffff1681526020810191909152604001600090812090610bb08282612b79565b6001820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055610be8600283016000612b97565b5050610c26858583818110610bff57610bff6134a5565b9050602002016020810190610c1491906134d4565b60039067ffffffffffffffff166110ad565b507f2a680691fef3b2d105196805935232c661ce703e92d464ef0b94a7bc62d714f0858583818110610c5a57610c5a6134a5565b9050602002016020810190610c6f91906134d4565b60405167ffffffffffffffff909116815260200160405180910390a1600101610ab0565b5060005b81811015610e3d576000838383818110610cb357610cb36134a5565b9050602002810190610cc591906134ef565b610cd390602081019061352d565b610cdc906136bf565b90506000848484818110610cf257610cf26134a5565b9050602002810190610d0491906134ef565b610d129060208101906134d4565b9050610d2182600001516110b9565b816020015160ff16600003610d62576040517fa9b3766e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff81166000908152600260209081526040909120835180518593610d92928492910190612bd1565b5060208201516001820180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff90921691909117905560408201516002820190610ddf90826137e7565b50610df991506003905067ffffffffffffffff8316611205565b507f05dd57854af2c291a94ea52e7c43d80bc3be7fa73022f98b735dea86642fa5e08183604051610e2b929190613901565b60405180910390a15050600101610c97565b5050505050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610eb3576040517fac7a7efd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080610eca610ec586880188613a3f565b611211565b8151919350915015610ee257610ee28360008461143e565b805115610ef557610ef58360018361143e565b5050505050505050565b60006102fc825490565b60606000610f1683611c70565b9392505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610f9e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640161077a565b565b3373ffffffffffffffffffffffffffffffffffffffff82160361101f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161077a565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60008181526001830160205260408120541515610f16565b6000610f168383611ccc565b60005b81518110156112015760008019167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166350c946fe848481518110611118576111186134a5565b60200260200101516040518263ffffffff1660e01b815260040161113e91815260200190565b600060405180830381865afa15801561115b573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526111a19190810190613c44565b60800151036111f9578181815181106111bc576111bc6134a5565b60200260200101516040517f8907a4fa00000000000000000000000000000000000000000000000000000000815260040161077a91815260200190565b6001016110bc565b5050565b6000610f168383611dc6565b606080600460ff1683511115611253576040517f8854586400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160028082526060820190925290816020015b6112c16040805160e081019091528060008152602001600067ffffffffffffffff168152602001600060ff168152602001600067ffffffffffffffff1681526020016060815260200160608152602001606081525090565b81526020019060019003908161126957505060408051600280825260608201909252919350602082015b6113436040805160e081019091528060008152602001600067ffffffffffffffff168152602001600060ff168152602001600067ffffffffffffffff1681526020016060815260200160608152602001606081525090565b8152602001906001900390816112eb57905050905060008060005b855181101561143157600086828151811061137b5761137b6134a5565b602002602001015160000151600181111561139857611398612e56565b036113e5578581815181106113af576113af6134a5565b60200260200101518584815181106113c9576113c96134a5565b6020026020010181905250826113de90613d1c565b9250611429565b8581815181106113f7576113f76134a5565b6020026020010151848381518110611411576114116134a5565b60200260200101819052508161142690613d1c565b91505b60010161135e565b5090835281529092909150565b63ffffffff831660009081526005602052604081208184600181111561146657611466612e56565b600181111561147757611477612e56565b8152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b8282101561182b57600084815260209020604080516101408101909152600684029091018054829060608201908390829060ff1660018111156114ea576114ea612e56565b60018111156114fb576114fb612e56565b8152815467ffffffffffffffff61010082048116602084015260ff690100000000000000000083041660408401526a0100000000000000000000909104166060820152600182018054608090920191611553906133b7565b80601f016020809104026020016040519081016040528092919081815260200182805461157f906133b7565b80156115cc5780601f106115a1576101008083540402835291602001916115cc565b820191906000526020600020905b8154815290600101906020018083116115af57829003601f168201915b5050505050815260200160028201805480602002602001604051908101604052809291908181526020016000905b8282101561175a578382906000526020600020906003020160405180606001604052908160008201548152602001600182018054611637906133b7565b80601f0160208091040260200160405190810160405280929190818152602001828054611663906133b7565b80156116b05780601f10611685576101008083540402835291602001916116b0565b820191906000526020600020905b81548152906001019060200180831161169357829003601f168201915b505050505081526020016002820180546116c9906133b7565b80601f01602080910402602001604051908101604052809291908181526020018280546116f5906133b7565b80156117425780601f1061171757610100808354040283529160200191611742565b820191906000526020600020905b81548152906001019060200180831161172557829003601f168201915b505050505081525050815260200190600101906115fa565b505050508152602001600382018054611772906133b7565b80601f016020809104026020016040519081016040528092919081815260200182805461179e906133b7565b80156117eb5780601f106117c0576101008083540402835291602001916117eb565b820191906000526020600020905b8154815290600101906020018083116117ce57829003601f168201915b505050919092525050508152600482015467ffffffffffffffff1660208083019190915260059092015460409091015290825260019290920191016114a5565b505050509050600061183d8251611e15565b9050600061184b8451611e15565b90506118578282611e67565b60006118668785878686611f23565b905061187284826122f7565b63ffffffff871660009081526005602052604081209087600181111561189a5761189a612e56565b60018111156118ab576118ab612e56565b815260200190815260200160002060006118c59190612c1c565b60005b8151811015611c135763ffffffff88166000908152600560205260408120818960018111156118f9576118f9612e56565b600181111561190a5761190a612e56565b8152602001908152602001600020600181600181540180825580915050039060005260206000209060060201905082828151811061194a5761194a6134a5565b6020026020010151604001518160050181905550828281518110611970576119706134a5565b6020026020010151602001518160040160006101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550600081600001905060008484815181106119c2576119c26134a5565b602090810291909101015151805183549192509083907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660018381811115611a0d57611a0d612e56565b021790555060208101518254604083015160608401517fffffffffffffffffffffffffffffffffffffffffffff000000000000000000ff90921661010067ffffffffffffffff948516027fffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffff1617690100000000000000000060ff90921691909102177fffffffffffffffffffffffffffff0000000000000000ffffffffffffffffffff166a0100000000000000000000929091169190910217825560808101516001830190611adc90826137e7565b5060c08101516003830190611af190826137e7565b505b60a08101515160028301541115611b725781600201805480611b1757611b17613d54565b60008281526020812060037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9093019283020181815590611b5b6001830182612b97565b611b69600283016000612b97565b50509055611af3565b60005b8160a0015151811015611c045760028301548110611bfc57826002018260a001518281518110611ba757611ba76134a5565b6020908102919091018101518254600181810185556000948552938390208251600390920201908155918101519092820190611be390826137e7565b5060408201516002820190611bf890826137e7565b5050505b600101611b75565b505050508060010190506118c8565b50856001811115611c2657611c26612e56565b60ff168763ffffffff167f0fe4c45ffc7f05233ddfee7d79ac01d075176a0aa116068c486a2f7490088a0b83604051611c5f9190612f45565b60405180910390a350505050505050565b606081600001805480602002602001604051908101604052809291908181526020018280548015611cc057602002820191906000526020600020905b815481526020019060010190808311611cac575b50505050509050919050565b60008181526001830160205260408120548015611db5576000611cf0600183613492565b8554909150600090611d0490600190613492565b9050808214611d69576000866000018281548110611d2457611d246134a5565b9060005260206000200154905080876000018481548110611d4757611d476134a5565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080611d7a57611d7a613d54565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506102fc565b60009150506102fc565b5092915050565b6000818152600183016020526040812054611e0d575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556102fc565b5060006102fc565b60006002821115611e55576040517f3e4785260000000000000000000000000000000000000000000000000000000081526004810183905260240161077a565b8160028111156102fc576102fc612e56565b6000826002811115611e7b57611e7b612e56565b826002811115611e8d57611e8d612e56565b611e979190613d83565b90508060011480611ee35750807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff148015611ee357506002836002811115611ee157611ee1612e56565b145b15611eed57505050565b82826040517f0a6b675b00000000000000000000000000000000000000000000000000000000815260040161077a929190613db3565b60606000845167ffffffffffffffff811115611f4157611f41613450565b604051908082528060200260200182016040528015611f6a578160200160208202803683370190505b5090506000846002811115611f8157611f81612e56565b148015611f9f57506001836002811115611f9d57611f9d612e56565b145b15611fe057600181600081518110611fb957611fb96134a5565b602002602001019067ffffffffffffffff16908167ffffffffffffffff1681525050612148565b6001846002811115611ff457611ff4612e56565b1480156120125750600283600281111561201057612010612e56565b145b156120a9578560008151811061202a5761202a6134a5565b60200260200101516020015181600081518110612049576120496134a5565b602002602001019067ffffffffffffffff16908167ffffffffffffffff16815250508560008151811061207e5761207e6134a5565b60200260200101516020015160016120969190613dce565b81600181518110611fb957611fb96134a5565b60028460028111156120bd576120bd612e56565b1480156120db575060018360028111156120d9576120d9612e56565b145b1561211257856001815181106120f3576120f36134a5565b60200260200101516020015181600081518110611fb957611fb96134a5565b83836040517f0a6b675b00000000000000000000000000000000000000000000000000000000815260040161077a929190613db3565b6000855167ffffffffffffffff81111561216457612164613450565b60405190808252806020026020018201604052801561220257816020015b6040805161014081018252600060608083018281526080840183905260a0840183905260c0840183905260e084018290526101008401829052610120840191909152825260208083018290529282015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816121825790505b50905060005b82518110156122eb57612233878281518110612226576122266134a5565b6020026020010151612676565b6040518060600160405280888381518110612250576122506134a5565b6020026020010151815260200184838151811061226f5761226f6134a5565b602002602001015167ffffffffffffffff1681526020016122c38b86858151811061229c5761229c6134a5565b60200260200101518b86815181106122b6576122b66134a5565b6020026020010151612a70565b8152508282815181106122d8576122d86134a5565b6020908102919091010152600101612208565b50979650505050505050565b81518151811580156123095750806001145b156123ab5782600081518110612321576123216134a5565b60200260200101516020015167ffffffffffffffff166001146123a55782600081518110612351576123516134a5565b60209081029190910181015101516040517fc1658eb800000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526001602482015260440161077a565b50505050565b8160011480156123bb5750806002145b1561257157836000815181106123d3576123d36134a5565b602002602001015160400151836000815181106123f2576123f26134a5565b6020026020010151604001511461247e5782600081518110612416576124166134a5565b60200260200101516040015184600081518110612435576124356134a5565b6020026020010151604001516040517fc7ccdd7f00000000000000000000000000000000000000000000000000000000815260040161077a929190918252602082015260400190565b83600081518110612491576124916134a5565b60200260200101516020015160016124a99190613dce565b67ffffffffffffffff16836001815181106124c6576124c66134a5565b60200260200101516020015167ffffffffffffffff16146123a557826001815181106124f4576124f46134a5565b60200260200101516020015184600081518110612513576125136134a5565b602002602001015160200151600161252b9190613dce565b6040517fc1658eb800000000000000000000000000000000000000000000000000000000815267ffffffffffffffff92831660048201529116602482015260440161077a565b8160021480156125815750806001145b156126445783600181518110612599576125996134a5565b602002602001015160400151836000815181106125b8576125b86134a5565b602002602001015160400151146123a557826000815181106125dc576125dc6134a5565b602002602001015160400151846001815181106125fb576125fb6134a5565b6020026020010151604001516040517f9e97567000000000000000000000000000000000000000000000000000000000815260040161077a929190918252602082015260400190565b6040517f1f1b2bb600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806020015167ffffffffffffffff166000036126be576040517f698cf8e000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000815160018111156126d3576126d3612e56565b141580156126f457506001815160018111156126f1576126f1612e56565b14155b1561272b576040517f3302dbd700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6080810151511580612768575060408051600060208201520160405160208183030381529060405280519060200120816080015180519060200120145b1561279f576040517f358c192700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208101516127ba9060039067ffffffffffffffff16611095565b6128025760208101516040517f1bd4d2d200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff909116600482015260240161077a565b60408082015160208084015167ffffffffffffffff1660009081526002909152919091206001015460ff918216911681811115612875576040517f2db22040000000000000000000000000000000000000000000000000000000008152600481018290526024810183905260440161077a565b60a0830151516101008111156128b7576040517f1b925da600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6128c2836003613439565b81116128fa576040517f4856694e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000808267ffffffffffffffff81111561291657612916613450565b60405190808252806020026020018201604052801561293f578160200160208202803683370190505b50905060005b838110156129ff5760008760a001518281518110612965576129656134a5565b6020026020010151905080604001515160001461298a578361298681613d1c565b9450505b602081015151158061299b57508051155b156129d457806040517f9fa4031400000000000000000000000000000000000000000000000000000000815260040161077a9190613def565b80600001518383815181106129eb576129eb6134a5565b602090810291909101015250600101612945565b506000612a0d856003613439565b612a1890600161347f565b905080831015612a5e576040517f548dd21f000000000000000000000000000000000000000000000000000000008152600481018490526024810182905260440161077a565b612a67826110b9565b50505050505050565b60008082602001518584600001518560800151878760a00151886040015189606001518a60c00151604051602001612ab099989796959493929190613e02565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e0a000000000000000000000000000000000000000000000000000000000000179150509392505050565b6040518060400160405280600067ffffffffffffffff168152602001612b74604051806060016040528060608152602001600060ff168152602001606081525090565b905290565b5080546000825590600052602060002090810190610aa29190612c3d565b508054612ba3906133b7565b6000825580601f10612bb3575050565b601f016020900490600052602060002090810190610aa29190612c3d565b828054828255906000526020600020908101928215612c0c579160200282015b82811115612c0c578251825591602001919060010190612bf1565b50612c18929150612c3d565b5090565b5080546000825560060290600052602060002090810190610aa29190612c52565b5b80821115612c185760008155600101612c3e565b80821115612c185780547fffffffffffffffffffffffffffff00000000000000000000000000000000000016815560008181612c916001830182612b97565b612c9f600283016000612ce9565b612cad600383016000612b97565b5050506004810180547fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000016905560006005820155600601612c52565b5080546000825560030290600052602060002090810190610aa291905b80821115612c18576000808255612d206001830182612b97565b612d2e600283016000612b97565b50600301612d06565b600060208284031215612d4957600080fd5b81357fffffffff0000000000000000000000000000000000000000000000000000000081168114610f1657600080fd5b6000815180845260005b81811015612d9f57602081850181015186830182015201612d83565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000610f166020830184612d79565b63ffffffff81168114610aa257600080fd5b8035612e0d81612df0565b919050565b803560028110612e0d57600080fd5b60008060408385031215612e3457600080fd5b8235612e3f81612df0565b9150612e4d60208401612e12565b90509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60028110612e9557612e95612e56565b9052565b805182526000602082015160606020850152612eb86060850182612d79565b905060408301518482036040860152612ed18282612d79565b95945050505050565b60008282518085526020808601955060208260051b8401016020860160005b84811015610a84577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018952612f33838351612e99565b98840198925090830190600101612ef9565b600060208083018184528085518083526040925060408601915060408160051b87010184880160005b838110156130a9577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0898403018552815160608151818652612fb38287018251612e85565b89810151608067ffffffffffffffff8216818901528a830151915060a060ff8316818a015284840151945060c09250612ff7838a018667ffffffffffffffff169052565b81840151945060e0915081828a01526130146101408a0186612d79565b9450808401519150507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa080898603016101008a01526130538583612eda565b92909301518883039093016101208901525091506130718282612d79565b9150508882015161308d8a87018267ffffffffffffffff169052565b5090870151938701939093529386019390860190600101612f6e565b509098975050505050505050565b6000602082840312156130c957600080fd5b8135610f1681612df0565b600080604083850312156130e757600080fd5b50508035926020909101359150565b805160608084528151908401819052600091602091908201906080860190845b8181101561313257835183529284019291840191600101613116565b505060ff602086015116602087015260408501519250858103604087015261315a8184612d79565b9695505050505050565b600060208083018184528085518083526040925060408601915060408160051b87010184880160005b838110156130a9578883037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00185528151805167ffffffffffffffff1684528701518784018790526131e1878501826130f6565b958801959350509086019060010161318d565b60006020828403121561320657600080fd5b813573ffffffffffffffffffffffffffffffffffffffff81168114610f1657600080fd5b60008083601f84011261323c57600080fd5b50813567ffffffffffffffff81111561325457600080fd5b6020830191508360208260051b850101111561326f57600080fd5b9250929050565b6000806000806040858703121561328c57600080fd5b843567ffffffffffffffff808211156132a457600080fd5b6132b08883890161322a565b909650945060208701359150808211156132c957600080fd5b506132d68782880161322a565b95989497509550505050565b803567ffffffffffffffff81168114612e0d57600080fd5b6000806000806000806080878903121561331357600080fd5b863567ffffffffffffffff8082111561332b57600080fd5b6133378a838b0161322a565b9098509650602089013591508082111561335057600080fd5b818901915089601f83011261336457600080fd5b81358181111561337357600080fd5b8a602082850101111561338557600080fd5b60208301965080955050505061339d604088016132e2565b91506133ab60608801612e02565b90509295509295509295565b600181811c908216806133cb57607f821691505b602082108103613404577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80820281158282048414176102fc576102fc61340a565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b808201808211156102fc576102fc61340a565b818103818111156102fc576102fc61340a565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000602082840312156134e657600080fd5b610f16826132e2565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc183360301811261352357600080fd5b9190910192915050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa183360301811261352357600080fd5b6040516060810167ffffffffffffffff8111828210171561358457613584613450565b60405290565b60405160e0810167ffffffffffffffff8111828210171561358457613584613450565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156135f4576135f4613450565b604052919050565b600067ffffffffffffffff82111561361657613616613450565b5060051b60200190565b803560ff81168114612e0d57600080fd5b600082601f83011261364257600080fd5b813567ffffffffffffffff81111561365c5761365c613450565b61368d60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016135ad565b8181528460208386010111156136a257600080fd5b816020850160208301376000918101602001919091529392505050565b6000606082360312156136d157600080fd5b6136d9613561565b823567ffffffffffffffff808211156136f157600080fd5b9084019036601f83011261370457600080fd5b81356020613719613714836135fc565b6135ad565b82815260059290921b8401810191818101903684111561373857600080fd5b948201945b838610156137565785358252948201949082019061373d565b865250613764878201613620565b9085015250604085013591508082111561377d57600080fd5b5061378a36828601613631565b60408301525092915050565b601f8211156137e2576000816000526020600020601f850160051c810160208610156137bf5750805b601f850160051c820191505b818110156137de578281556001016137cb565b5050505b505050565b815167ffffffffffffffff81111561380157613801613450565b6138158161380f84546133b7565b84613796565b602080601f83116001811461386857600084156138325750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b1785556137de565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b828110156138b557888601518255948401946001909101908401613896565b50858210156138f157878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b67ffffffffffffffff8316815260406020820152600061392460408301846130f6565b949350505050565b600082601f83011261393d57600080fd5b8135602061394d613714836135fc565b82815260059290921b8401810191818101908684111561396c57600080fd5b8286015b84811015613a3457803567ffffffffffffffff808211156139915760008081fd5b81890191506060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848d030112156139ca5760008081fd5b6139d2613561565b878401358152604080850135848111156139ec5760008081fd5b6139fa8e8b83890101613631565b838b015250918401359183831115613a125760008081fd5b613a208d8a85880101613631565b908201528652505050918301918301613970565b509695505050505050565b60006020808385031215613a5257600080fd5b823567ffffffffffffffff80821115613a6a57600080fd5b818501915085601f830112613a7e57600080fd5b8135613a8c613714826135fc565b81815260059190911b83018401908481019088831115613aab57600080fd5b8585015b83811015613bcd57803585811115613ac657600080fd5b860160e0818c037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0011215613afb5760008081fd5b613b0361358a565b613b0e898301612e12565b81526040613b1d8184016132e2565b8a8301526060613b2e818501613620565b8284015260809150613b418285016132e2565b9083015260a08381013589811115613b595760008081fd5b613b678f8d83880101613631565b838501525060c091508184013589811115613b825760008081fd5b613b908f8d8388010161392c565b82850152505060e083013588811115613ba95760008081fd5b613bb78e8c83870101613631565b9183019190915250845250918601918601613aaf565b5098975050505050505050565b8051612e0d81612df0565b600082601f830112613bf657600080fd5b81516020613c06613714836135fc565b8083825260208201915060208460051b870101935086841115613c2857600080fd5b602086015b84811015613a345780518352918301918301613c2d565b600060208284031215613c5657600080fd5b815167ffffffffffffffff80821115613c6e57600080fd5b9083019060e08286031215613c8257600080fd5b613c8a61358a565b613c9383613bda565b8152613ca160208401613bda565b6020820152613cb260408401613bda565b6040820152606083015160608201526080830151608082015260a083015182811115613cdd57600080fd5b613ce987828601613be5565b60a08301525060c083015182811115613d0157600080fd5b613d0d87828601613be5565b60c08301525095945050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613d4d57613d4d61340a565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b8181036000831280158383131683831282161715611dbf57611dbf61340a565b60038110612e9557612e95612e56565b60408101613dc18285613da3565b610f166020830184613da3565b67ffffffffffffffff818116838216019080821115611dbf57611dbf61340a565b602081526000610f166020830184612e99565b600061012067ffffffffffffffff808d168452602063ffffffff8d1681860152613e2f604086018d612e85565b826060860152613e418386018c612d79565b918a16608086015284820360a0860152885180835291925080830191600581901b84018201828b0160005b83811015613eb8577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0878403018652613ea6838351612e99565b95850195925090840190600101613e6c565b505060ff8a1660c088015267ffffffffffffffff891660e0880152868103610100880152613ee68189612d79565b955050505050509a995050505050505050505056fea164736f6c6343000818000a", } var CCIPConfigABI = CCIPConfigMetaData.ABI @@ -1217,7 +1221,7 @@ func (CCIPConfigChainConfigSet) Topic() common.Hash { } func (CCIPConfigConfigSet) Topic() common.Hash { - return common.HexToHash("0x403420f960fcf8fdad51d01bc3af8668c5963e6746c63c8f5363c26d9d445148") + return common.HexToHash("0x0fe4c45ffc7f05233ddfee7d79ac01d075176a0aa116068c486a2f7490088a0b") } func (CCIPConfigOwnershipTransferRequested) Topic() common.Hash { diff --git a/core/gethwrappers/ccip/generated/multi_ocr3_helper/multi_ocr3_helper.go b/core/gethwrappers/ccip/generated/multi_ocr3_helper/multi_ocr3_helper.go index 285aaaa338..bd0cb8898d 100644 --- a/core/gethwrappers/ccip/generated/multi_ocr3_helper/multi_ocr3_helper.go +++ b/core/gethwrappers/ccip/generated/multi_ocr3_helper/multi_ocr3_helper.go @@ -59,7 +59,7 @@ type MultiOCR3BaseOracle struct { var MultiOCR3HelperMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"actual\",\"type\":\"bytes32\"}],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"ForkedChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enumMultiOCR3Base.InvalidConfigErrorType\",\"name\":\"errorType\",\"type\":\"uint8\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonUniqueSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OracleCannotBeZeroAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignaturesOutOfRegistration\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"StaticConfigCannotBeChanged\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedTransmitter\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"WrongMessageLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WrongNumberOfSignatures\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"AfterConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"oracleAddress\",\"type\":\"address\"}],\"name\":\"getOracle\",\"outputs\":[{\"components\":[{\"internalType\":\"uint8\",\"name\":\"index\",\"type\":\"uint8\"},{\"internalType\":\"enumMultiOCR3Base.Role\",\"name\":\"role\",\"type\":\"uint8\"}],\"internalType\":\"structMultiOCR3Base.Oracle\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"latestConfigDetails\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"n\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"}],\"internalType\":\"structMultiOCR3Base.ConfigInfo\",\"name\":\"configInfo\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfig\",\"name\":\"ocrConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfigArgs[]\",\"name\":\"ocrConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"setOCR3Configs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"setTransmitOcrPluginType\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"rawVs\",\"type\":\"bytes32\"}],\"name\":\"transmitWithSignatures\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"transmitWithoutSignatures\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]", - Bin: "0x60a06040523480156200001157600080fd5b503380600081620000695760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b03848116919091179091558116156200009c576200009c81620000a9565b5050466080525062000154565b336001600160a01b03821603620001035760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000060565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b608051611d386200017760003960008181610ef00152610f3c0152611d386000f3fe608060405234801561001057600080fd5b50600436106100be5760003560e01c80637ac0aa1a11610076578063c673e5841161005b578063c673e584146101c5578063f2fde38b146101e5578063f716f99f146101f857600080fd5b80637ac0aa1a1461015b5780638da5cb5b1461019d57600080fd5b806334a9c92e116100a757806334a9c92e1461012057806344e65e551461014057806379ba50971461015357600080fd5b8063181f5a77146100c357806326bf9d261461010b575b600080fd5b604080518082018252601981527f4d756c74694f4352334261736548656c70657220312e302e30000000000000006020820152905161010291906114dd565b60405180910390f35b61011e6101193660046115a4565b61020b565b005b61013361012e366004611632565b61023a565b6040516101029190611694565b61011e61014e366004611707565b6102ca565b61011e61034d565b61011e6101693660046117ba565b600480547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff92909216919091179055565b60005460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610102565b6101d86101d33660046117ba565b61044f565b604051610102919061182e565b61011e6101f33660046118c1565b6105c7565b61011e610206366004611a2d565b6105db565b604080516000808252602082019092526004549091506102349060ff168585858580600061061d565b50505050565b6040805180820182526000808252602080830182905260ff86811683526003825284832073ffffffffffffffffffffffffffffffffffffffff871684528252918490208451808601909552805480841686529394939092918401916101009091041660028111156102ad576102ad611665565b60028111156102be576102be611665565b90525090505b92915050565b60045460408051602080880282810182019093528782526103439360ff16928c928c928c928c918c91829185019084908082843760009201919091525050604080516020808d0282810182019093528c82529093508c92508b9182918501908490808284376000920191909152508a925061061d915050565b5050505050505050565b60015473ffffffffffffffffffffffffffffffffffffffff1633146103d3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6104926040805160e081019091526000606082018181526080830182905260a0830182905260c08301919091528190815260200160608152602001606081525090565b60ff808316600090815260026020818152604092839020835160e081018552815460608201908152600183015480881660808401526101008104881660a0840152620100009004909616151560c08201529485529182018054845181840281018401909552808552929385830193909283018282801561054857602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff16815260019091019060200180831161051d575b50505050508152602001600382018054806020026020016040519081016040528092919081815260200182805480156105b757602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff16815260019091019060200180831161058c575b5050505050815250509050919050565b6105cf6109a1565b6105d881610a24565b50565b6105e36109a1565b60005b81518110156106195761061182828151811061060457610604611b96565b6020026020010151610b19565b6001016105e6565b5050565b60ff8781166000908152600260209081526040808320815160808101835281548152600190910154808616938201939093526101008304851691810191909152620100009091049092161515606083015287359061067c8760a4611bf4565b90508260600151156106c4578451610695906020611c07565b86516106a2906020611c07565b6106ad9060a0611bf4565b6106b79190611bf4565b6106c19082611bf4565b90505b368114610706576040517f8e1192e1000000000000000000000000000000000000000000000000000000008152600481018290523660248201526044016103ca565b508151811461074e5781516040517f93df584c0000000000000000000000000000000000000000000000000000000081526004810191909152602481018290526044016103ca565b610756610eed565b60ff808a16600090815260036020908152604080832033845282528083208151808301909252805480861683529394919390928401916101009091041660028111156107a4576107a4611665565b60028111156107b5576107b5611665565b90525090506002816020015160028111156107d2576107d2611665565b1480156108335750600260008b60ff1660ff168152602001908152602001600020600301816000015160ff168154811061080e5761080e611b96565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1633145b610869576040517fda0f08e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5081606001511561094b576020820151610884906001611c1e565b60ff168551146108c0576040517f71253a2500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83518551146108fb576040517fa75d88af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000878760405161090d929190611c37565b604051908190038120610924918b90602001611c47565b6040516020818303038152906040528051906020012090506109498a82888888610f6e565b505b6040805182815260208a81013567ffffffffffffffff169082015260ff8b16917f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef0910160405180910390a2505050505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610a22576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016103ca565b565b3373ffffffffffffffffffffffffffffffffffffffff821603610aa3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016103ca565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b806040015160ff16600003610b5d5760006040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016103ca9190611c5b565b60208082015160ff80821660009081526002909352604083206001810154929390928392169003610bca57606084015160018201805491151562010000027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff909216919091179055610c1f565b6060840151600182015460ff6201000090910416151590151514610c1f576040517f87f6037c00000000000000000000000000000000000000000000000000000000815260ff841660048201526024016103ca565b60a084015180516101001015610c645760016040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016103ca9190611c5b565b610cd78484600301805480602002602001604051908101604052809291908181526020018280548015610ccd57602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610ca2575b505050505061117e565b846060015115610e3d57610d528484600201805480602002602001604051908101604052809291908181526020018280548015610ccd5760200282019190600052602060002090815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610ca257505050505061117e565b608085015180516101001015610d975760026040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016103ca9190611c5b565b6040860151610da7906003611c75565b60ff16815111610de65760036040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016103ca9190611c5b565b80516001840180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1661010060ff841602179055610e2e906002860190602084019061143e565b50610e3b85826001611216565b505b610e4984826002611216565b8051610e5e906003850190602084019061143e565b506040858101516001840180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff8316179055865180855560a088015192517fab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f54793610ed59389939260028a01929190611c98565b60405180910390a1610ee684611405565b5050505050565b467f000000000000000000000000000000000000000000000000000000000000000014610a22576040517f0f01ce850000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060048201524660248201526044016103ca565b8251600090815b81811015610343576000600188868460208110610f9457610f94611b96565b610fa191901a601b611c1e565b898581518110610fb357610fb3611b96565b6020026020010151898681518110610fcd57610fcd611b96565b60200260200101516040516000815260200160405260405161100b949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa15801561102d573d6000803e3d6000fd5b5050604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081015160ff808e1660009081526003602090815285822073ffffffffffffffffffffffffffffffffffffffff8516835281528582208587019096528554808416865293975090955092939284019161010090041660028111156110b9576110b9611665565b60028111156110ca576110ca611665565b90525090506001816020015160028111156110e7576110e7611665565b1461111e576040517fca31867a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051600160ff9091161b851615611161576040517ff67bc7c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806000015160ff166001901b851794505050806001019050610f75565b60005b81518110156112115760ff8316600090815260036020526040812083519091908490849081106111b3576111b3611b96565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff16825281019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000169055600101611181565b505050565b60005b825181101561023457600083828151811061123657611236611b96565b602002602001015190506000600281111561125357611253611665565b60ff808716600090815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff87168452909152902054610100900416600281111561129f5761129f611665565b146112d95760046040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016103ca9190611c5b565b73ffffffffffffffffffffffffffffffffffffffff8116611326576040517fd6c62c9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052808360ff16815260200184600281111561134c5761134c611665565b905260ff808716600090815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845282529091208351815493167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00841681178255918401519092909183917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000016176101008360028111156113f1576113f1611665565b021790555090505050806001019050611219565b60405160ff821681527f897ac1b2c12867721b284f3eb147bd4ab046d4eef1cf31c1d8988bfcfb962b539060200160405180910390a150565b8280548282559060005260206000209081019282156114b8579160200282015b828111156114b857825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff90911617825560209092019160019091019061145e565b506114c49291506114c8565b5090565b5b808211156114c457600081556001016114c9565b60006020808352835180602085015260005b8181101561150b578581018301518582016040015282016114ef565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b80606081018310156102c457600080fd5b60008083601f84011261156d57600080fd5b50813567ffffffffffffffff81111561158557600080fd5b60208301915083602082850101111561159d57600080fd5b9250929050565b6000806000608084860312156115b957600080fd5b6115c3858561154a565b9250606084013567ffffffffffffffff8111156115df57600080fd5b6115eb8682870161155b565b9497909650939450505050565b803560ff8116811461160957600080fd5b919050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461160957600080fd5b6000806040838503121561164557600080fd5b61164e836115f8565b915061165c6020840161160e565b90509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b815160ff16815260208201516040820190600381106116b5576116b5611665565b8060208401525092915050565b60008083601f8401126116d457600080fd5b50813567ffffffffffffffff8111156116ec57600080fd5b6020830191508360208260051b850101111561159d57600080fd5b60008060008060008060008060e0898b03121561172357600080fd5b61172d8a8a61154a565b9750606089013567ffffffffffffffff8082111561174a57600080fd5b6117568c838d0161155b565b909950975060808b013591508082111561176f57600080fd5b61177b8c838d016116c2565b909750955060a08b013591508082111561179457600080fd5b506117a18b828c016116c2565b999c989b50969995989497949560c00135949350505050565b6000602082840312156117cc57600080fd5b6117d5826115f8565b9392505050565b60008151808452602080850194506020840160005b8381101561182357815173ffffffffffffffffffffffffffffffffffffffff16875295820195908201906001016117f1565b509495945050505050565b60208152600082518051602084015260ff602082015116604084015260ff604082015116606084015260608101511515608084015250602083015160c060a084015261187d60e08401826117dc565b905060408401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08483030160c08501526118b882826117dc565b95945050505050565b6000602082840312156118d357600080fd5b6117d58261160e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160c0810167ffffffffffffffff8111828210171561192e5761192e6118dc565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561197b5761197b6118dc565b604052919050565b600067ffffffffffffffff82111561199d5761199d6118dc565b5060051b60200190565b8035801515811461160957600080fd5b600082601f8301126119c857600080fd5b813560206119dd6119d883611983565b611934565b8083825260208201915060208460051b8701019350868411156119ff57600080fd5b602086015b84811015611a2257611a158161160e565b8352918301918301611a04565b509695505050505050565b60006020808385031215611a4057600080fd5b823567ffffffffffffffff80821115611a5857600080fd5b818501915085601f830112611a6c57600080fd5b8135611a7a6119d882611983565b81815260059190911b83018401908481019088831115611a9957600080fd5b8585015b83811015611b8957803585811115611ab457600080fd5b860160c0818c037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0011215611ae95760008081fd5b611af161190b565b8882013581526040611b048184016115f8565b8a8301526060611b158185016115f8565b8284015260809150611b288285016119a7565b9083015260a08381013589811115611b405760008081fd5b611b4e8f8d838801016119b7565b838501525060c0840135915088821115611b685760008081fd5b611b768e8c848701016119b7565b9083015250845250918601918601611a9d565b5098975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156102c4576102c4611bc5565b80820281158282048414176102c4576102c4611bc5565b60ff81811683821601908111156102c4576102c4611bc5565b8183823760009101908152919050565b828152606082602083013760800192915050565b6020810160058310611c6f57611c6f611665565b91905290565b60ff8181168382160290811690818114611c9157611c91611bc5565b5092915050565b600060a0820160ff88168352602087602085015260a0604085015281875480845260c086019150886000526020600020935060005b81811015611cff57845473ffffffffffffffffffffffffffffffffffffffff1683526001948501949284019201611ccd565b50508481036060860152611d1381886117dc565b935050505060ff83166080830152969550505050505056fea164736f6c6343000818000a", + Bin: "0x60a06040523480156200001157600080fd5b503380600081620000695760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b03848116919091179091558116156200009c576200009c81620000a9565b5050466080525062000154565b336001600160a01b03821603620001035760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000060565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b608051611db56200017760003960008181610f6d0152610fb90152611db56000f3fe608060405234801561001057600080fd5b50600436106100be5760003560e01c80637ac0aa1a11610076578063c673e5841161005b578063c673e584146101c5578063f2fde38b146101e5578063f716f99f146101f857600080fd5b80637ac0aa1a1461015b5780638da5cb5b1461019d57600080fd5b806334a9c92e116100a757806334a9c92e1461012057806344e65e551461014057806379ba50971461015357600080fd5b8063181f5a77146100c357806326bf9d261461010b575b600080fd5b604080518082018252601981527f4d756c74694f4352334261736548656c70657220312e302e300000000000000060208201529051610102919061155a565b60405180910390f35b61011e610119366004611621565b61020b565b005b61013361012e3660046116af565b61023a565b6040516101029190611711565b61011e61014e366004611784565b6102ca565b61011e61034d565b61011e610169366004611837565b600480547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff92909216919091179055565b60005460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610102565b6101d86101d3366004611837565b61044f565b60405161010291906118ab565b61011e6101f336600461193e565b6105c7565b61011e610206366004611aaa565b6105db565b604080516000808252602082019092526004549091506102349060ff168585858580600061061d565b50505050565b6040805180820182526000808252602080830182905260ff86811683526003825284832073ffffffffffffffffffffffffffffffffffffffff871684528252918490208451808601909552805480841686529394939092918401916101009091041660028111156102ad576102ad6116e2565b60028111156102be576102be6116e2565b90525090505b92915050565b60045460408051602080880282810182019093528782526103439360ff16928c928c928c928c918c91829185019084908082843760009201919091525050604080516020808d0282810182019093528c82529093508c92508b9182918501908490808284376000920191909152508a925061061d915050565b5050505050505050565b60015473ffffffffffffffffffffffffffffffffffffffff1633146103d3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6104926040805160e081019091526000606082018181526080830182905260a0830182905260c08301919091528190815260200160608152602001606081525090565b60ff808316600090815260026020818152604092839020835160e081018552815460608201908152600183015480881660808401526101008104881660a0840152620100009004909616151560c08201529485529182018054845181840281018401909552808552929385830193909283018282801561054857602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff16815260019091019060200180831161051d575b50505050508152602001600382018054806020026020016040519081016040528092919081815260200182805480156105b757602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff16815260019091019060200180831161058c575b5050505050815250509050919050565b6105cf6109a1565b6105d881610a24565b50565b6105e36109a1565b60005b81518110156106195761061182828151811061060457610604611c13565b6020026020010151610b19565b6001016105e6565b5050565b60ff8781166000908152600260209081526040808320815160808101835281548152600190910154808616938201939093526101008304851691810191909152620100009091049092161515606083015287359061067c8760a4611c71565b90508260600151156106c4578451610695906020611c84565b86516106a2906020611c84565b6106ad9060a0611c71565b6106b79190611c71565b6106c19082611c71565b90505b368114610706576040517f8e1192e1000000000000000000000000000000000000000000000000000000008152600481018290523660248201526044016103ca565b508151811461074e5781516040517f93df584c0000000000000000000000000000000000000000000000000000000081526004810191909152602481018290526044016103ca565b610756610f6a565b60ff808a16600090815260036020908152604080832033845282528083208151808301909252805480861683529394919390928401916101009091041660028111156107a4576107a46116e2565b60028111156107b5576107b56116e2565b90525090506002816020015160028111156107d2576107d26116e2565b1480156108335750600260008b60ff1660ff168152602001908152602001600020600301816000015160ff168154811061080e5761080e611c13565b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff1633145b610869576040517fda0f08e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5081606001511561094b576020820151610884906001611c9b565b60ff168551146108c0576040517f71253a2500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83518551146108fb576040517fa75d88af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000878760405161090d929190611cb4565b604051908190038120610924918b90602001611cc4565b6040516020818303038152906040528051906020012090506109498a82888888610feb565b505b6040805182815260208a81013567ffffffffffffffff169082015260ff8b16917f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef0910160405180910390a2505050505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314610a22576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016103ca565b565b3373ffffffffffffffffffffffffffffffffffffffff821603610aa3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016103ca565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b806040015160ff16600003610b5d5760006040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016103ca9190611cd8565b60208082015160ff80821660009081526002909352604083206001810154929390928392169003610bca57606084015160018201805491151562010000027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff909216919091179055610c1f565b6060840151600182015460ff6201000090910416151590151514610c1f576040517f87f6037c00000000000000000000000000000000000000000000000000000000815260ff841660048201526024016103ca565b60a084015180516101001015610c645760016040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016103ca9190611cd8565b8051600003610ca25760056040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016103ca9190611cd8565b610d158484600301805480602002602001604051908101604052809291908181526020018280548015610d0b57602002820191906000526020600020905b815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610ce0575b50505050506111fb565b846060015115610eba57610d908484600201805480602002602001604051908101604052809291908181526020018280548015610d0b5760200282019190600052602060002090815473ffffffffffffffffffffffffffffffffffffffff168152600190910190602001808311610ce05750505050506111fb565b608085015180516101001015610dd55760026040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016103ca9190611cd8565b6040860151610de5906003611cf2565b60ff16815111610e245760036040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016103ca9190611cd8565b815181511015610e635760016040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016103ca9190611cd8565b80516001840180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1661010060ff841602179055610eab90600286019060208401906114bb565b50610eb885826001611293565b505b610ec684826002611293565b8051610edb90600385019060208401906114bb565b506040858101516001840180547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff8316179055865180855560a088015192517fab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f54793610f529389939260028a01929190611d15565b60405180910390a1610f6384611482565b5050505050565b467f000000000000000000000000000000000000000000000000000000000000000014610a22576040517f0f01ce850000000000000000000000000000000000000000000000000000000081527f000000000000000000000000000000000000000000000000000000000000000060048201524660248201526044016103ca565b8251600090815b8181101561034357600060018886846020811061101157611011611c13565b61101e91901a601b611c9b565b89858151811061103057611030611c13565b602002602001015189868151811061104a5761104a611c13565b602002602001015160405160008152602001604052604051611088949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa1580156110aa573d6000803e3d6000fd5b5050604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081015160ff808e1660009081526003602090815285822073ffffffffffffffffffffffffffffffffffffffff851683528152858220858701909652855480841686529397509095509293928401916101009004166002811115611136576111366116e2565b6002811115611147576111476116e2565b9052509050600181602001516002811115611164576111646116e2565b1461119b576040517fca31867a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051600160ff9091161b8516156111de576040517ff67bc7c400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b806000015160ff166001901b851794505050806001019050610ff2565b60005b815181101561128e5760ff83166000908152600360205260408120835190919084908490811061123057611230611c13565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff16825281019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001690556001016111fe565b505050565b60005b82518110156102345760008382815181106112b3576112b3611c13565b60200260200101519050600060028111156112d0576112d06116e2565b60ff808716600090815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff87168452909152902054610100900416600281111561131c5761131c6116e2565b146113565760046040517f367f56a20000000000000000000000000000000000000000000000000000000081526004016103ca9190611cd8565b73ffffffffffffffffffffffffffffffffffffffff81166113a3576040517fd6c62c9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052808360ff1681526020018460028111156113c9576113c96116e2565b905260ff808716600090815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845282529091208351815493167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00841681178255918401519092909183917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000161761010083600281111561146e5761146e6116e2565b021790555090505050806001019050611296565b60405160ff821681527f897ac1b2c12867721b284f3eb147bd4ab046d4eef1cf31c1d8988bfcfb962b539060200160405180910390a150565b828054828255906000526020600020908101928215611535579160200282015b8281111561153557825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9091161782556020909201916001909101906114db565b50611541929150611545565b5090565b5b808211156115415760008155600101611546565b60006020808352835180602085015260005b818110156115885785810183015185820160400152820161156c565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b80606081018310156102c457600080fd5b60008083601f8401126115ea57600080fd5b50813567ffffffffffffffff81111561160257600080fd5b60208301915083602082850101111561161a57600080fd5b9250929050565b60008060006080848603121561163657600080fd5b61164085856115c7565b9250606084013567ffffffffffffffff81111561165c57600080fd5b611668868287016115d8565b9497909650939450505050565b803560ff8116811461168657600080fd5b919050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461168657600080fd5b600080604083850312156116c257600080fd5b6116cb83611675565b91506116d96020840161168b565b90509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b815160ff1681526020820151604082019060038110611732576117326116e2565b8060208401525092915050565b60008083601f84011261175157600080fd5b50813567ffffffffffffffff81111561176957600080fd5b6020830191508360208260051b850101111561161a57600080fd5b60008060008060008060008060e0898b0312156117a057600080fd5b6117aa8a8a6115c7565b9750606089013567ffffffffffffffff808211156117c757600080fd5b6117d38c838d016115d8565b909950975060808b01359150808211156117ec57600080fd5b6117f88c838d0161173f565b909750955060a08b013591508082111561181157600080fd5b5061181e8b828c0161173f565b999c989b50969995989497949560c00135949350505050565b60006020828403121561184957600080fd5b61185282611675565b9392505050565b60008151808452602080850194506020840160005b838110156118a057815173ffffffffffffffffffffffffffffffffffffffff168752958201959082019060010161186e565b509495945050505050565b60208152600082518051602084015260ff602082015116604084015260ff604082015116606084015260608101511515608084015250602083015160c060a08401526118fa60e0840182611859565b905060408401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08483030160c08501526119358282611859565b95945050505050565b60006020828403121561195057600080fd5b6118528261168b565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160c0810167ffffffffffffffff811182821017156119ab576119ab611959565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156119f8576119f8611959565b604052919050565b600067ffffffffffffffff821115611a1a57611a1a611959565b5060051b60200190565b8035801515811461168657600080fd5b600082601f830112611a4557600080fd5b81356020611a5a611a5583611a00565b6119b1565b8083825260208201915060208460051b870101935086841115611a7c57600080fd5b602086015b84811015611a9f57611a928161168b565b8352918301918301611a81565b509695505050505050565b60006020808385031215611abd57600080fd5b823567ffffffffffffffff80821115611ad557600080fd5b818501915085601f830112611ae957600080fd5b8135611af7611a5582611a00565b81815260059190911b83018401908481019088831115611b1657600080fd5b8585015b83811015611c0657803585811115611b3157600080fd5b860160c0818c037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0011215611b665760008081fd5b611b6e611988565b8882013581526040611b81818401611675565b8a8301526060611b92818501611675565b8284015260809150611ba5828501611a24565b9083015260a08381013589811115611bbd5760008081fd5b611bcb8f8d83880101611a34565b838501525060c0840135915088821115611be55760008081fd5b611bf38e8c84870101611a34565b9083015250845250918601918601611b1a565b5098975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156102c4576102c4611c42565b80820281158282048414176102c4576102c4611c42565b60ff81811683821601908111156102c4576102c4611c42565b8183823760009101908152919050565b828152606082602083013760800192915050565b6020810160068310611cec57611cec6116e2565b91905290565b60ff8181168382160290811690818114611d0e57611d0e611c42565b5092915050565b600060a0820160ff88168352602087602085015260a0604085015281875480845260c086019150886000526020600020935060005b81811015611d7c57845473ffffffffffffffffffffffffffffffffffffffff1683526001948501949284019201611d4a565b50508481036060860152611d908188611859565b935050505060ff83166080830152969550505050505056fea164736f6c6343000818000a", } var MultiOCR3HelperABI = MultiOCR3HelperMetaData.ABI diff --git a/core/gethwrappers/ccip/generated/ocr3_config_encoder/ocr3_config_encoder.go b/core/gethwrappers/ccip/generated/ocr3_config_encoder/ocr3_config_encoder.go index 737a768dbe..5056db1005 100644 --- a/core/gethwrappers/ccip/generated/ocr3_config_encoder/ocr3_config_encoder.go +++ b/core/gethwrappers/ccip/generated/ocr3_config_encoder/ocr3_config_encoder.go @@ -31,17 +31,21 @@ var ( type CCIPConfigTypesOCR3Config struct { PluginType uint8 ChainSelector uint64 - F uint8 + FRoleDON uint8 OffchainConfigVersion uint64 OfframpAddress []byte - P2pIds [][32]byte - Signers [][]byte - Transmitters [][]byte + Nodes []CCIPConfigTypesOCR3Node OffchainConfig []byte } +type CCIPConfigTypesOCR3Node struct { + P2pId [32]byte + SignerKey []byte + TransmitterKey []byte +} + var IOCR3ConfigEncoderMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offrampAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"p2pIds\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes[]\",\"name\":\"signers\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes[]\",\"name\":\"transmitters\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPConfigTypes.OCR3Config[]\",\"name\":\"config\",\"type\":\"tuple[]\"}],\"name\":\"exposeOCR3Config\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"enumInternal.OCRPluginType\",\"name\":\"pluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint8\",\"name\":\"FRoleDON\",\"type\":\"uint8\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offrampAddress\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"p2pId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"signerKey\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"transmitterKey\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPConfigTypes.OCR3Node[]\",\"name\":\"nodes\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structCCIPConfigTypes.OCR3Config[]\",\"name\":\"config\",\"type\":\"tuple[]\"}],\"name\":\"exposeOCR3Config\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", } var IOCR3ConfigEncoderABI = IOCR3ConfigEncoderMetaData.ABI diff --git a/core/gethwrappers/ccip/generated/offramp/offramp.go b/core/gethwrappers/ccip/generated/offramp/offramp.go index 0294359052..8828214d11 100644 --- a/core/gethwrappers/ccip/generated/offramp/offramp.go +++ b/core/gethwrappers/ccip/generated/offramp/offramp.go @@ -155,7 +155,7 @@ type OffRampStaticConfig struct { var OffRampMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CanOnlySelfCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"reportOnRamp\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"configOnRamp\",\"type\":\"bytes\"}],\"name\":\"CommitOnRampMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"actual\",\"type\":\"bytes32\"}],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ExecutionError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"ForkedChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enumMultiOCR3Base.InvalidConfigErrorType\",\"name\":\"errorType\",\"type\":\"uint8\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"got\",\"type\":\"uint256\"}],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidEVMAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"name\":\"InvalidInterval\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"newLimit\",\"type\":\"uint256\"}],\"name\":\"InvalidManualExecutionGasLimit\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"tokenIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"oldLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenGasOverride\",\"type\":\"uint256\"}],\"name\":\"InvalidManualExecutionTokenGasOverride\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"messageDestChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidMessageDestChainSelector\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"newState\",\"type\":\"uint8\"}],\"name\":\"InvalidNewState\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidOnRampUpdate\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRoot\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LeavesCannotBeEmpty\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"ManualExecutionGasAmountCountMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ManualExecutionGasLimitMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"ManualExecutionNotYetEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"errorReason\",\"type\":\"bytes\"}],\"name\":\"MessageValidationError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonUniqueSignatures\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"notPool\",\"type\":\"address\"}],\"name\":\"NotACompatiblePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OracleCannotBeZeroAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ReceiverError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountReleased\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePre\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePost\",\"type\":\"uint256\"}],\"name\":\"ReleaseOrMintBalanceMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"name\":\"RootAlreadyCommitted\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"RootNotCommitted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignatureVerificationDisabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignaturesOutOfRegistration\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"reportSourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"messageSourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainSelectorMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"StaleCommitReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"StaticConfigCannotBeChanged\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"TokenDataMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"TokenHandlingError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnexpectedTokenData\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"WrongMessageLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WrongNumberOfSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroChainSelectorNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"AlreadyAttempted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"indexed\":false,\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"}],\"name\":\"CommitReportAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"DynamicConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"messageHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"name\":\"ExecutionStateChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"RootRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"SkippedAlreadyExecutedMessage\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SkippedReportExecution\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"sourceConfig\",\"type\":\"tuple\"}],\"name\":\"SourceChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainSelectorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"}],\"name\":\"StaticConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigUpdates\",\"type\":\"tuple[]\"}],\"name\":\"applySourceChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"destTokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structClient.Any2EVMMessage\",\"name\":\"\",\"type\":\"tuple\"}],\"name\":\"ccipReceive\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"rawVs\",\"type\":\"bytes32\"}],\"name\":\"commit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"execute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"bytes[]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[]\"},{\"internalType\":\"uint32[]\",\"name\":\"tokenGasOverrides\",\"type\":\"uint32[]\"}],\"name\":\"executeSingleMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"getExecutionState\",\"outputs\":[{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLatestPriceSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"getMerkleRoot\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"getSourceChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"latestConfigDetails\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"n\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"}],\"internalType\":\"structMultiOCR3Base.ConfigInfo\",\"name\":\"configInfo\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfig\",\"name\":\"ocrConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage[]\",\"name\":\"messages\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[][]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[][]\"},{\"internalType\":\"bytes32[]\",\"name\":\"proofs\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"proofFlagBits\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.ExecutionReportSingleChain[]\",\"name\":\"reports\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"receiverExecutionGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint32[]\",\"name\":\"tokenGasOverrides\",\"type\":\"uint32[]\"}],\"internalType\":\"structOffRamp.GasLimitOverride[][]\",\"name\":\"gasLimitOverrides\",\"type\":\"tuple[][]\"}],\"name\":\"manuallyExecute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"setDynamicConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfigArgs[]\",\"name\":\"ocrConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"setOCR3Configs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x6101206040523480156200001257600080fd5b506040516200688038038062006880833981016040819052620000359162000806565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf81620001fa565b5050466080525060208301516001600160a01b03161580620000ec575060408301516001600160a01b0316155b8062000103575060608301516001600160a01b0316155b1562000122576040516342bcdf7f60e11b815260040160405180910390fd5b82516001600160401b03166000036200014e5760405163c656089560e01b815260040160405180910390fd5b82516001600160401b0390811660a052602080850180516001600160a01b0390811660c05260408088018051831660e0526060808a01805185166101005283518b519098168852945184169587019590955251821690850152905116908201527f683eb52ee924eb817377cfa8f41f238f4bb7a877da5267869dfffbad85f564d89060800160405180910390a1620001e682620002a5565b620001f1816200036d565b50505062000b8d565b336001600160a01b03821603620002545760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b0316620002ce576040516342bcdf7f60e11b815260040160405180910390fd5b805160048054602080850180516001600160a01b039586166001600160c01b03199094168417600160a01b63ffffffff928316021790945560408087018051600580546001600160a01b031916918916919091179055815194855291519094169183019190915251909216908201527fa1c15688cb2c24508e158f6942b9276c6f3028a85e1af8cf3fff0c3ff3d5fc8d9060600160405180910390a150565b60005b8151811015620005ba57600082828151811062000391576200039162000943565b60200260200101519050600081602001519050806001600160401b0316600003620003cf5760405163c656089560e01b815260040160405180910390fd5b81516001600160a01b0316620003f8576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160401b03811660009081526006602052604090206060830151600182018054620004269062000959565b905060000362000489578154600160a81b600160e81b031916600160a81b1782556040516001600160401b03841681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1620004c8565b8154600160a81b90046001600160401b0316600114620004c857604051632105803760e11b81526001600160401b038416600482015260240162000083565b80511580620004fe5750604080516000602082015201604051602081830303815290604052805190602001208180519060200120145b156200051d576040516342bcdf7f60e11b815260040160405180910390fd5b600182016200052d8282620009ea565b50604080850151835486516001600160a01b03166001600160a01b0319921515600160a01b02929092166001600160a81b031990911617178355516001600160401b038416907f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b90620005a290859062000ab6565b60405180910390a25050505080600101905062000370565b5050565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b0381118282101715620005f957620005f9620005be565b60405290565b604051601f8201601f191681016001600160401b03811182821017156200062a576200062a620005be565b604052919050565b80516001600160401b03811681146200064a57600080fd5b919050565b6001600160a01b03811681146200066557600080fd5b50565b6000601f83601f8401126200067c57600080fd5b825160206001600160401b03808311156200069b576200069b620005be565b8260051b620006ac838201620005ff565b9384528681018301938381019089861115620006c757600080fd5b84890192505b85831015620007f957825184811115620006e75760008081fd5b89016080601f19828d038101821315620007015760008081fd5b6200070b620005d4565b888401516200071a816200064f565b815260406200072b85820162000632565b8a8301526060808601518015158114620007455760008081fd5b838301529385015193898511156200075d5760008081fd5b84860195508f603f8701126200077557600094508485fd5b8a8601519450898511156200078e576200078e620005be565b6200079f8b858f88011601620005ff565b93508484528f82868801011115620007b75760008081fd5b60005b85811015620007d7578681018301518582018d01528b01620007ba565b5060009484018b019490945250918201528352509184019190840190620006cd565b9998505050505050505050565b60008060008385036101008112156200081e57600080fd5b60808112156200082d57600080fd5b62000837620005d4565b620008428662000632565b8152602086015162000854816200064f565b6020820152604086015162000869816200064f565b604082015260608601516200087e816200064f565b606082810191909152909450607f19820112156200089b57600080fd5b50604051606081016001600160401b038082118383101715620008c257620008c2620005be565b8160405260808701519150620008d8826200064f565b90825260a08601519063ffffffff82168214620008f457600080fd5b81602084015260c087015191506200090c826200064f565b6040830182905260e0870151929450808311156200092957600080fd5b5050620009398682870162000668565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b600181811c908216806200096e57607f821691505b6020821081036200098f57634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115620009e5576000816000526020600020601f850160051c81016020861015620009c05750805b601f850160051c820191505b81811015620009e157828155600101620009cc565b5050505b505050565b81516001600160401b0381111562000a065762000a06620005be565b62000a1e8162000a17845462000959565b8462000995565b602080601f83116001811462000a56576000841562000a3d5750858301515b600019600386901b1c1916600185901b178555620009e1565b600085815260208120601f198616915b8281101562000a875788860151825594840194600190910190840162000a66565b508582101562000aa65787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b602080825282546001600160a01b0381168383015260a081901c60ff161515604084015260a81c6001600160401b0316606083015260808083015260018084018054600093929190849062000b0b8162000959565b8060a089015260c0600183166000811462000b2f576001811462000b4c5762000b7e565b60ff19841660c08b015260c083151560051b8b0101945062000b7e565b85600052602060002060005b8481101562000b755781548c820185015290880190890162000b58565b8b0160c0019550505b50929998505050505050505050565b60805160a05160c05160e05161010051615c7d62000c036000396000818161022c01526129a90152600081816101fd0152612c7b0152600081816101ce01528181610552015281816106ff015261236a01526000818161019f01526125a9015260008181611d920152611dc50152615c7d6000f3fe608060405234801561001057600080fd5b50600436106101515760003560e01c806379ba5097116100cd578063d434969111610081578063e9d68a8e11610066578063e9d68a8e146104bc578063f2fde38b146104dc578063f716f99f146104ef57600080fd5b8063d434969114610496578063e62653f5146104a957600080fd5b80638da5cb5b116100b25780638da5cb5b14610417578063c673e58414610432578063ccd37ba31461045257600080fd5b806379ba50971461040157806385572ffb1461040957600080fd5b8063311cd513116101245780635e36480c116101095780635e36480c1461033c5780636f9e320f1461035c5780637437ff9f1461036f57600080fd5b8063311cd5131461030e5780633f4b04aa1461032157600080fd5b806304666f9c1461015657806306285c691461016b578063181f5a77146102b25780632d04ab76146102fb575b600080fd5b610169610164366004613c28565b610502565b005b61025c60408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160401b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316815250905090565b6040516102a9919081516001600160401b031681526020808301516001600160a01b0390811691830191909152604080840151821690830152606092830151169181019190915260800190565b60405180910390f35b6102ee6040518060400160405280601181526020017f4f666652616d7020312e362e302d64657600000000000000000000000000000081525081565b6040516102a99190613d96565b610169610309366004613e46565b610516565b61016961031c366004613ef8565b610a12565b6009546040516001600160401b0390911681526020016102a9565b61034f61034a366004613f4b565b610a7b565b6040516102a99190613fa8565b61016961036a366004613fd3565b610ad0565b6103cb604080516060810182526000808252602082018190529181019190915250604080516060810182526004546001600160a01b038082168352600160a01b90910463ffffffff166020830152600554169181019190915290565b6040805182516001600160a01b03908116825260208085015163ffffffff169083015292820151909216908201526060016102a9565b610169610ae1565b610169610151366004614027565b6000546040516001600160a01b0390911681526020016102a9565b610445610440366004614072565b610b92565b6040516102a991906140d2565b610488610460366004614147565b6001600160401b03919091166000908152600860209081526040808320938352929052205490565b6040519081526020016102a9565b6101696104a43660046143e3565b610cf0565b6101696104b736600461476b565b610fd0565b6104cf6104ca3660046149b2565b611277565b6040516102a991906149cd565b6101696104ea366004614a1a565b611383565b6101696104fd366004614a9f565b611394565b61050a6113d6565b61051381611432565b50565b600061052487890189614df4565b602081015151909150156105b6576020810151604080830151905162ccd5af60e81b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169263ccd5af00926105859260040161501c565b60006040518083038186803b15801561059d57600080fd5b505afa1580156105b1573d6000803e3d6000fd5b505050505b805151511515806105cc57508051602001515115155b156106985760095460208a0135906001600160401b0380831691161015610670576009805467ffffffffffffffff19166001600160401b038316179055600480548351604051633937306f60e01b81526001600160a01b0390921692633937306f92610639929101615150565b600060405180830381600087803b15801561065357600080fd5b505af1158015610667573d6000803e3d6000fd5b50505050610696565b81602001515160000361069657604051632261116760e01b815260040160405180910390fd5b505b60005b816020015151811015610953576000826020015182815181106106c0576106c061507e565b60209081029190910101518051604051632cbc26bb60e01b815267ffffffffffffffff60801b608083901b166004820152919250906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632cbc26bb90602401602060405180830381865afa158015610746573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061076a9190615163565b1561079857604051637edeb53960e11b81526001600160401b03821660048201526024015b60405180910390fd5b60006107a382611685565b9050806001016040516107b691906151ba565b6040518091039020836020015180519060200120146107f35782602001518160010160405163b80d8fa960e01b815260040161078f9291906152ad565b60408301518154600160a81b90046001600160401b039081169116141580610834575082606001516001600160401b031683604001516001600160401b0316115b1561087957825160408085015160608601519151636af0786b60e11b81526001600160401b03938416600482015290831660248201529116604482015260640161078f565b60808301518061089c5760405163504570e360e01b815260040160405180910390fd5b83516001600160401b03166000908152600860209081526040808320848452909152902054156108f45783516040516332cf0cbf60e01b81526001600160401b0390911660048201526024810182905260440161078f565b60608401516109049060016152e8565b825467ffffffffffffffff60a81b1916600160a81b6001600160401b0392831602179092559251166000908152600860209081526040808320948352939052919091204290555060010161069b565b50602081015181516040517f35c02761bcd3ef995c6a601a1981f4ed3934dcbe5041e24e286c89f5531d17e49261098b92909161530f565b60405180910390a1610a0760008a8a8a8a8a8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808e0282810182019093528d82529093508d92508c9182918501908490808284376000920191909152508b92506116d1915050565b505050505050505050565b610a52610a2182840184615334565b6040805160008082526020820190925290610a4c565b6060815260200190600190039081610a375790505b506119ca565b604080516000808252602082019092529050610a756001858585858660006116d1565b50505050565b6000610a8960016004615368565b6002610a96608085615391565b6001600160401b0316610aa991906153b7565b610ab38585611a8c565b901c166003811115610ac757610ac7613f7e565b90505b92915050565b610ad86113d6565b61051381611ad1565b6001546001600160a01b03163314610b3b5760405162461bcd60e51b815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e657200000000000000000000604482015260640161078f565b60008054336001600160a01b0319808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610bd56040805160e081019091526000606082018181526080830182905260a0830182905260c08301919091528190815260200160608152602001606081525090565b60ff808316600090815260026020818152604092839020835160e081018552815460608201908152600183015480881660808401526101008104881660a0840152620100009004909616151560c082015294855291820180548451818402810184019095528085529293858301939092830182828015610c7e57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610c60575b5050505050815260200160038201805480602002602001604051908101604052809291908181526020018280548015610ce057602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610cc2575b5050505050815250509050919050565b333014610d10576040516306e34e6560e31b815260040160405180910390fd5b6040805160008082526020820190925281610d4d565b6040805180820190915260008082526020820152815260200190600190039081610d265790505b5060a08701515190915015610d8357610d808660a001518760200151886060015189600001516020015189898989611bb0565b90505b6040805160a081018252875151815287516020908101516001600160401b031681830152808901518351600094840192610dbe929101613d96565b60408051601f19818403018152918152908252898101516020830152018390526005549091506001600160a01b03168015610e99576040516308d450a160e01b81526001600160a01b038216906308d450a190610e1f90859060040161546f565b600060405180830381600087803b158015610e3957600080fd5b505af1925050508015610e4a575060015b610e99573d808015610e78576040519150601f19603f3d011682016040523d82523d6000602084013e610e7d565b606091505b50806040516309c2532560e01b815260040161078f9190613d96565b604088015151158015610eae57506080880151155b80610ec5575060608801516001600160a01b03163b155b80610eec57506060880151610eea906001600160a01b03166385572ffb60e01b611d73565b155b15610ef957505050610fc9565b87516020908101516001600160401b03166000908152600690915260408082205460808b015160608c01519251633cf9798360e01b815284936001600160a01b0390931692633cf9798392610f579289926113889291600401615482565b6000604051808303816000875af1158015610f76573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610f9e91908101906154be565b509150915081610fc357806040516302a35ba360e21b815260040161078f9190613d96565b50505050505b5050505050565b610fd8611d8f565b815181518114610ffb576040516320f8fd5960e21b815260040160405180910390fd5b60005b8181101561126757600084828151811061101a5761101a61507e565b602002602001015190506000816020015151905060008584815181106110425761104261507e565b602002602001015190508051821461106d576040516320f8fd5960e21b815260040160405180910390fd5b60005b8281101561125857600082828151811061108c5761108c61507e565b60200260200101516000015190506000856020015183815181106110b2576110b261507e565b6020026020010151905081600014611106578060800151821015611106578551815151604051633a98d46360e11b81526001600160401b03909216600483015260248201526044810183905260640161078f565b8383815181106111185761111861507e565b602002602001015160200151518160a00151511461116557805180516060909101516040516370a193fd60e01b815260048101929092526001600160401b0316602482015260440161078f565b60005b8160a001515181101561124a5760008585815181106111895761118961507e565b60200260200101516020015182815181106111a6576111a661507e565b602002602001015163ffffffff169050806000146112415760008360a0015183815181106111d6576111d661507e565b6020026020010151608001518060200190518101906111f59190615553565b90508063ffffffff1682101561123f578351516040516348e617b360e01b815260048101919091526024810184905263ffffffff821660448201526064810183905260840161078f565b505b50600101611168565b505050806001019050611070565b50505050806001019050610ffe565b5061127283836119ca565b505050565b60408051608080820183526000808352602080840182905283850182905260608085018190526001600160401b03878116845260068352928690208651948501875280546001600160a01b0381168652600160a01b810460ff16151593860193909352600160a81b90920490921694830194909452600184018054939492939184019161130390615180565b80601f016020809104026020016040519081016040528092919081815260200182805461132f90615180565b8015610ce05780601f1061135157610100808354040283529160200191610ce0565b820191906000526020600020905b81548152906001019060200180831161135f57505050919092525091949350505050565b61138b6113d6565b61051381611df7565b61139c6113d6565b60005b81518110156113d2576113ca8282815181106113bd576113bd61507e565b6020026020010151611ea0565b60010161139f565b5050565b6000546001600160a01b031633146114305760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640161078f565b565b60005b81518110156113d25760008282815181106114525761145261507e565b60200260200101519050600081602001519050806001600160401b031660000361148f5760405163c656089560e01b815260040160405180910390fd5b81516001600160a01b03166114b7576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160401b038116600090815260066020526040902060608301516001820180546114e390615180565b905060000361154557815467ffffffffffffffff60a81b1916600160a81b1782556040516001600160401b03841681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1611582565b8154600160a81b90046001600160401b031660011461158257604051632105803760e11b81526001600160401b038416600482015260240161078f565b805115806115b75750604080516000602082015201604051602081830303815290604052805190602001208180519060200120145b156115d5576040516342bcdf7f60e11b815260040160405180910390fd5b600182016115e382826155c0565b50604080850151835486516001600160a01b03166001600160a01b0319921515600160a01b02929092167fffffffffffffffffffffff00000000000000000000000000000000000000000090911617178355516001600160401b038416907f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b9061166e90859061567f565b60405180910390a250505050806001019050611435565b6001600160401b03811660009081526006602052604081208054600160a01b900460ff16610aca5760405163ed053c5960e01b81526001600160401b038416600482015260240161078f565b60ff878116600090815260026020908152604080832081516080810183528154815260019091015480861693820193909352610100830485169181019190915262010000909104909216151560608301528735906117308760a46156cd565b90508260600151156117785784516117499060206153b7565b86516117569060206153b7565b6117619060a06156cd565b61176b91906156cd565b61177590826156cd565b90505b3681146117a157604051638e1192e160e01b81526004810182905236602482015260440161078f565b50815181146117d05781516040516324f7d61360e21b815260048101919091526024810182905260440161078f565b6117d8611d8f565b60ff808a166000908152600360209081526040808320338452825280832081518083019092528054808616835293949193909284019161010090910416600281111561182657611826613f7e565b600281111561183757611837613f7e565b905250905060028160200151600281111561185457611854613f7e565b1480156118a85750600260008b60ff1660ff168152602001908152602001600020600301816000015160ff16815481106118905761189061507e565b6000918252602090912001546001600160a01b031633145b6118c557604051631b41e11d60e31b815260040160405180910390fd5b508160600151156119755760208201516118e09060016156e0565b60ff16855114611903576040516371253a2560e01b815260040160405180910390fd5b83518551146119255760405163a75d88af60e01b815260040160405180910390fd5b600087876040516119379291906156f9565b60405190819003812061194e918b90602001615709565b6040516020818303038152906040528051906020012090506119738a8288888861217f565b505b6040805182815260208a8101356001600160401b03169082015260ff8b16917f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef0910160405180910390a2505050505050505050565b81516000036119eb5760405162bf199760e01b815260040160405180910390fd5b80516040805160008082526020820190925291159181611a2e565b604080518082019091526000815260606020820152815260200190600190039081611a065790505b50905060005b8451811015610fc957611a84858281518110611a5257611a5261507e565b602002602001015184611a7e57858381518110611a7157611a7161507e565b602002602001015161233c565b8361233c565b600101611a34565b6001600160401b038216600090815260076020526040812081611ab060808561571d565b6001600160401b031681526020810191909152604001600020549392505050565b80516001600160a01b0316611af9576040516342bcdf7f60e11b815260040160405180910390fd5b805160048054602080850180516001600160a01b039586167fffffffffffffffff0000000000000000000000000000000000000000000000009094168417600160a01b63ffffffff928316021790945560408087018051600580546001600160a01b031916918916919091179055815194855291519094169183019190915251909216908201527fa1c15688cb2c24508e158f6942b9276c6f3028a85e1af8cf3fff0c3ff3d5fc8d9060600160405180910390a150565b606088516001600160401b03811115611bcb57611bcb613a48565b604051908082528060200260200182016040528015611c1057816020015b6040805180820190915260008082526020820152815260200190600190039081611be95790505b509050811560005b8a51811015611d655781611cc257848482818110611c3857611c3861507e565b9050602002016020810190611c4d9190615743565b63ffffffff1615611cc257848482818110611c6a57611c6a61507e565b9050602002016020810190611c7f9190615743565b6040805163ffffffff9092166020830152016040516020818303038152906040528b8281518110611cb257611cb261507e565b6020026020010151608001819052505b611d408b8281518110611cd757611cd761507e565b60200260200101518b8b8b8b8b87818110611cf457611cf461507e565b9050602002810190611d069190615760565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612c3392505050565b838281518110611d5257611d5261507e565b6020908102919091010152600101611c18565b505098975050505050505050565b6000611d7e83612f31565b8015610ac75750610ac78383612f7c565b467f00000000000000000000000000000000000000000000000000000000000000001461143057604051630f01ce8560e01b81527f0000000000000000000000000000000000000000000000000000000000000000600482015246602482015260440161078f565b336001600160a01b03821603611e4f5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161078f565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b806040015160ff16600003611ecb576000604051631b3fab5160e11b815260040161078f91906157a6565b60208082015160ff80821660009081526002909352604083206001810154929390928392169003611f1c576060840151600182018054911515620100000262ff000019909216919091179055611f58565b6060840151600182015460ff6201000090910416151590151514611f58576040516321fd80df60e21b815260ff8416600482015260240161078f565b60a084015180516101001015611f84576001604051631b3fab5160e11b815260040161078f91906157a6565b611fea8484600301805480602002602001604051908101604052809291908181526020018280548015611fe057602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611fc2575b505050505061301e565b8460600151156120f4576120588484600201805480602002602001604051908101604052809291908181526020018280548015611fe0576020028201919060005260206000209081546001600160a01b03168152600190910190602001808311611fc257505050505061301e565b608085015180516101001015612084576002604051631b3fab5160e11b815260040161078f91906157a6565b60408601516120949060036157c0565b60ff168151116120ba576003604051631b3fab5160e11b815260040161078f91906157a6565b805160018401805461ff00191661010060ff8416021790556120e590600286019060208401906139ce565b506120f285826001613087565b505b61210084826002613087565b805161211590600385019060208401906139ce565b5060408581015160018401805460ff191660ff8316179055865180855560a088015192517fab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f5479361216e9389939260028a019291906157dc565b60405180910390a1610fc9846131e2565b8251600090815b818110156123325760006001888684602081106121a5576121a561507e565b6121b291901a601b6156e0565b8985815181106121c4576121c461507e565b60200260200101518986815181106121de576121de61507e565b60200260200101516040516000815260200160405260405161221c949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa15801561223e573d6000803e3d6000fd5b505060408051601f1981015160ff808e166000908152600360209081528582206001600160a01b0385168352815285822085870190965285548084168652939750909550929392840191610100900416600281111561229f5761229f613f7e565b60028111156122b0576122b0613f7e565b90525090506001816020015160028111156122cd576122cd613f7e565b146122eb57604051636518c33d60e11b815260040160405180910390fd5b8051600160ff9091161b85161561231557604051633d9ef1f160e21b815260040160405180910390fd5b806000015160ff166001901b851794505050806001019050612186565b5050505050505050565b81518151604051632cbc26bb60e01b8152608083901b67ffffffffffffffff60801b166004820152901515907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632cbc26bb90602401602060405180830381865afa1580156123b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123dd9190615163565b1561244e57801561240c57604051637edeb53960e11b81526001600160401b038316600482015260240161078f565b6040516001600160401b03831681527faab522ed53d887e56ed53dd37398a01aeef6a58e0fa77c2173beb9512d8949339060200160405180910390a150505050565b600061245983611685565b600101805461246790615180565b80601f016020809104026020016040519081016040528092919081815260200182805461249390615180565b80156124e05780601f106124b5576101008083540402835291602001916124e0565b820191906000526020600020905b8154815290600101906020018083116124c357829003601f168201915b5050506020880151519293505050600081900361250f5760405162bf199760e01b815260040160405180910390fd5b8560400151518114612534576040516357e0e08360e01b815260040160405180910390fd5b6000816001600160401b0381111561254e5761254e613a48565b604051908082528060200260200182016040528015612577578160200160208202803683370190505b50905060005b8281101561271b5760008860200151828151811061259d5761259d61507e565b602002602001015190507f00000000000000000000000000000000000000000000000000000000000000006001600160401b03168160000151604001516001600160401b0316146126145780516040908101519051631c21951160e11b81526001600160401b03909116600482015260240161078f565b866001600160401b03168160000151602001516001600160401b03161461266857805160200151604051636c95f1eb60e01b81526001600160401b03808a166004830152909116602482015260440161078f565b6126f5817f2425b0b9f9054c76ff151b0a175b18f37a4a4e82013a72e9f15c9caa095ed21f83600001516020015184600001516040015189805190602001206040516020016126da94939291909384526001600160401b03928316602085015291166040830152606082015260800190565b60405160208183030381529060405280519060200120613239565b8383815181106127075761270761507e565b60209081029190910101525060010161257d565b50600061273286838a606001518b60800151613341565b90508060000361276057604051633ee8bd3f60e11b81526001600160401b038716600482015260240161078f565b60005b83811015610a075760005a905060008a6020015183815181106127885761278861507e565b6020026020010151905060006127a68a836000015160600151610a7b565b905060008160038111156127bc576127bc613f7e565b14806127d9575060038160038111156127d7576127d7613f7e565b145b61282f57815160600151604080516001600160401b03808e16825290921660208301527f3b575419319662b2a6f5e2467d84521517a3382b908eb3d557bb3fdb0c50e23c910160405180910390a1505050612c2b565b6060891561290e578b85815181106128495761284961507e565b6020908102919091018101510151600454909150600090600160a01b900463ffffffff166128778842615368565b11905080806128975750600383600381111561289557612895613f7e565b145b6128bf576040516354e7e43160e11b81526001600160401b038d16600482015260240161078f565b8c86815181106128d1576128d161507e565b602002602001015160000151600014612908578c86815181106128f6576128f661507e565b60209081029190910101515160808501525b5061297a565b600082600381111561292257612922613f7e565b1461297a57825160600151604080516001600160401b03808f16825290921660208301527f3ef2a99c550a751d4b0b261268f05a803dfb049ab43616a1ffb388f61fe65120910160405180910390a150505050612c2b565b8251608001516001600160401b031615612a535760008260038111156129a2576129a2613f7e565b03612a53577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e0e03cae8c85600001516080015186602001516040518463ffffffff1660e01b8152600401612a039392919061588e565b6020604051808303816000875af1158015612a22573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a469190615163565b612a535750505050612c2b565b60008d604001518681518110612a6b57612a6b61507e565b6020026020010151905080518460a001515114612ab557835160600151604051631cfe6d8b60e01b81526001600160401b03808f166004830152909116602482015260440161078f565b612ac98c856000015160600151600161337e565b600080612ad7868486613423565b91509150612aee8e8760000151606001518461337e565b8c15612b45576003826003811115612b0857612b08613f7e565b03612b45576000856003811115612b2157612b21613f7e565b14612b4557855151604051632b11b8d960e01b815261078f919083906004016158ba565b6002826003811115612b5957612b59613f7e565b14612b9e576003826003811115612b7257612b72613f7e565b14612b9e578d866000015160600151836040516349362d1f60e11b815260040161078f939291906158d3565b8560000151600001518660000151606001516001600160401b03168f6001600160401b03167f05665fe9ad095383d018353f4cbcba77e84db27dd215081bbf7cdf9ae6fbe48b8d8c81518110612bf657612bf661507e565b602002602001015186865a612c0b908f615368565b604051612c1b94939291906158f8565b60405180910390a4505050505050505b600101612763565b60408051808201909152600080825260208201526000612c5687602001516134d7565b60405163bbe4f6db60e01b81526001600160a01b0380831660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063bbe4f6db90602401602060405180830381865afa158015612cc2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ce6919061592f565b90506001600160a01b0381161580612d155750612d136001600160a01b03821663aff2afbf60e01b611d73565b155b15612d3e5760405163ae9b4ce960e01b81526001600160a01b038216600482015260240161078f565b600080612d6988858c60800151806020019051810190612d5e9190615553565b63ffffffff1661354b565b915091506000806000612e1c6040518061010001604052808e81526020018c6001600160401b031681526020018d6001600160a01b031681526020018f606001518152602001896001600160a01b031681526020018f6000015181526020018f6040015181526020018b815250604051602401612de6919061594c565b60408051601f198184030181529190526020810180516001600160e01b0316633907753760e01b1790528786611388608461362e565b92509250925082612e42578160405163e1cd550960e01b815260040161078f9190613d96565b8151602014612e71578151604051631e3be00960e21b815260206004820152602481019190915260440161078f565b600082806020019051810190612e879190615a18565b9050866001600160a01b03168c6001600160a01b031614612f03576000612eb88d8a612eb3868a615368565b61354b565b50905086811080612ed2575081612ecf8883615368565b14155b15612f015760405163a966e21f60e01b815260048101839052602481018890526044810182905260640161078f565b505b604080518082019091526001600160a01b039098168852602088015250949550505050505095945050505050565b6000612f44826301ffc9a760e01b612f7c565b8015610aca5750612f75827fffffffff00000000000000000000000000000000000000000000000000000000612f7c565b1592915050565b6040517fffffffff0000000000000000000000000000000000000000000000000000000082166024820152600090819060440160408051601f19818403018152919052602080820180516001600160e01b03166301ffc9a760e01b178152825192935060009283928392909183918a617530fa92503d91506000519050828015613007575060208210155b80156130135750600081115b979650505050505050565b60005b81518110156112725760ff8316600090815260036020526040812083519091908490849081106130535761305361507e565b6020908102919091018101516001600160a01b03168252810191909152604001600020805461ffff19169055600101613021565b60005b8251811015610a755760008382815181106130a7576130a761507e565b60200260200101519050600060028111156130c4576130c4613f7e565b60ff80871660009081526003602090815260408083206001600160a01b0387168452909152902054610100900416600281111561310357613103613f7e565b14613124576004604051631b3fab5160e11b815260040161078f91906157a6565b6001600160a01b03811661314b5760405163d6c62c9b60e01b815260040160405180910390fd5b60405180604001604052808360ff16815260200184600281111561317157613171613f7e565b905260ff80871660009081526003602090815260408083206001600160a01b0387168452825290912083518154931660ff198416811782559184015190929091839161ffff1916176101008360028111156131ce576131ce613f7e565b02179055509050505080600101905061308a565b60ff81166105135760ff8082166000908152600260205260409020600101546201000090041661322557604051631e8ed32560e21b815260040160405180910390fd5b6009805467ffffffffffffffff1916905550565b81518051606080850151908301516080808701519401516040516000958695889561329d95919490939192916020019485526001600160a01b039390931660208501526001600160401b039182166040850152606084015216608082015260a00190565b604051602081830303815290604052805190602001208560200151805190602001208660400151805190602001208760a001516040516020016132e09190615ae3565b60408051601f198184030181528282528051602091820120908301979097528101949094526060840192909252608083015260a082015260c081019190915260e0015b60405160208183030381529060405280519060200120905092915050565b60008061334f858585613708565b6001600160401b038716600090815260086020908152604080832093835292905220549150505b949350505050565b6000600261338d608085615391565b6001600160401b03166133a091906153b7565b905060006133ae8585611a8c565b9050816133bd60016004615368565b901b1916818360038111156133d4576133d4613f7e565b6001600160401b03871660009081526007602052604081209190921b9290921791829161340260808861571d565b6001600160401b031681526020810191909152604001600020555050505050565b60405163d434969160e01b8152600090606090309063d43496919061345090889088908890600401615b7a565b600060405180830381600087803b15801561346a57600080fd5b505af192505050801561347b575060015b6134ba573d8080156134a9576040519150601f19603f3d011682016040523d82523d6000602084013e6134ae565b606091505b506003925090506134cf565b50506040805160208101909152600081526002905b935093915050565b600081516020146134fd578160405163046b337b60e51b815260040161078f9190613d96565b6000828060200190518101906135139190615a18565b90506001600160a01b0381118061352b575061040081105b15610aca578260405163046b337b60e51b815260040161078f9190613d96565b60008060008060006135ac8860405160240161357691906001600160a01b0391909116815260200190565b60408051601f198184030181529190526020810180516001600160e01b03166370a0823160e01b1790528888611388608461362e565b925092509250826135d2578160405163e1cd550960e01b815260040161078f9190613d96565b6020825114613601578151604051631e3be00960e21b815260206004820152602481019190915260440161078f565b818060200190518101906136159190615a18565b61361f8288615368565b94509450505050935093915050565b6000606060008361ffff166001600160401b0381111561365057613650613a48565b6040519080825280601f01601f19166020018201604052801561367a576020820181803683370190505b509150863b6136945763030ed58f60e21b60005260046000fd5b5a858110156136ae57632be8ca8b60e21b60005260046000fd5b85900360408104810387106136ce576337c3be2960e01b60005260046000fd5b505a6000808a5160208c0160008c8cf193505a900390503d848111156136f15750835b808352806000602085013e50955095509592505050565b825182516000919081830361373057604051630469ac9960e21b815260040160405180910390fd5b610101821180159061374457506101018111155b613761576040516309bde33960e01b815260040160405180910390fd5b6000198282010161010081111561378b576040516309bde33960e01b815260040160405180910390fd5b806000036137b857866000815181106137a6576137a661507e565b60200260200101519350505050613986565b6000816001600160401b038111156137d2576137d2613a48565b6040519080825280602002602001820160405280156137fb578160200160208202803683370190505b50905060008080805b858110156139255760006001821b8b81160361385f5788851015613848578c5160018601958e9181106138395761383961507e565b60200260200101519050613881565b85516001850194879181106138395761383961507e565b8b5160018401938d9181106138765761387661507e565b602002602001015190505b6000898610156138b1578d5160018701968f9181106138a2576138a261507e565b602002602001015190506138d3565b86516001860195889181106138c8576138c861507e565b602002602001015190505b828511156138f4576040516309bde33960e01b815260040160405180910390fd5b6138fe828261398d565b8784815181106139105761391061507e565b60209081029190910101525050600101613804565b50600185038214801561393757508683145b801561394257508581145b61395f576040516309bde33960e01b815260040160405180910390fd5b8360018603815181106139745761397461507e565b60200260200101519750505050505050505b9392505050565b60008183106139a5576139a082846139ab565b610ac7565b610ac783835b604080516001602082015290810183905260608101829052600090608001613323565b828054828255906000526020600020908101928215613a23579160200282015b82811115613a2357825182546001600160a01b0319166001600160a01b039091161782556020909201916001909101906139ee565b50613a2f929150613a33565b5090565b5b80821115613a2f5760008155600101613a34565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b0381118282101715613a8057613a80613a48565b60405290565b604051606081016001600160401b0381118282101715613a8057613a80613a48565b60405160a081016001600160401b0381118282101715613a8057613a80613a48565b60405160c081016001600160401b0381118282101715613a8057613a80613a48565b604080519081016001600160401b0381118282101715613a8057613a80613a48565b604051601f8201601f191681016001600160401b0381118282101715613b3657613b36613a48565b604052919050565b60006001600160401b03821115613b5757613b57613a48565b5060051b60200190565b6001600160a01b038116811461051357600080fd5b80356001600160401b0381168114613b8d57600080fd5b919050565b801515811461051357600080fd5b8035613b8d81613b92565b60006001600160401b03821115613bc457613bc4613a48565b50601f01601f191660200190565b600082601f830112613be357600080fd5b8135613bf6613bf182613bab565b613b0e565b818152846020838601011115613c0b57600080fd5b816020850160208301376000918101602001919091529392505050565b60006020808385031215613c3b57600080fd5b82356001600160401b0380821115613c5257600080fd5b818501915085601f830112613c6657600080fd5b8135613c74613bf182613b3e565b81815260059190911b83018401908481019088831115613c9357600080fd5b8585015b83811015613d3957803585811115613caf5760008081fd5b86016080818c03601f1901811315613cc75760008081fd5b613ccf613a5e565b89830135613cdc81613b61565b81526040613ceb848201613b76565b8b830152606080850135613cfe81613b92565b83830152928401359289841115613d1757600091508182fd5b613d258f8d86880101613bd2565b908301525085525050918601918601613c97565b5098975050505050505050565b60005b83811015613d61578181015183820152602001613d49565b50506000910152565b60008151808452613d82816020860160208601613d46565b601f01601f19169290920160200192915050565b602081526000610ac76020830184613d6a565b8060608101831015610aca57600080fd5b60008083601f840112613dcc57600080fd5b5081356001600160401b03811115613de357600080fd5b602083019150836020828501011115613dfb57600080fd5b9250929050565b60008083601f840112613e1457600080fd5b5081356001600160401b03811115613e2b57600080fd5b6020830191508360208260051b8501011115613dfb57600080fd5b60008060008060008060008060e0898b031215613e6257600080fd5b613e6c8a8a613da9565b975060608901356001600160401b0380821115613e8857600080fd5b613e948c838d01613dba565b909950975060808b0135915080821115613ead57600080fd5b613eb98c838d01613e02565b909750955060a08b0135915080821115613ed257600080fd5b50613edf8b828c01613e02565b999c989b50969995989497949560c00135949350505050565b600080600060808486031215613f0d57600080fd5b613f178585613da9565b925060608401356001600160401b03811115613f3257600080fd5b613f3e86828701613dba565b9497909650939450505050565b60008060408385031215613f5e57600080fd5b613f6783613b76565b9150613f7560208401613b76565b90509250929050565b634e487b7160e01b600052602160045260246000fd5b60048110613fa457613fa4613f7e565b9052565b60208101610aca8284613f94565b8035613b8d81613b61565b63ffffffff8116811461051357600080fd5b600060608284031215613fe557600080fd5b613fed613a86565b8235613ff881613b61565b8152602083013561400881613fc1565b6020820152604083013561401b81613b61565b60408201529392505050565b60006020828403121561403957600080fd5b81356001600160401b0381111561404f57600080fd5b820160a0818503121561398657600080fd5b803560ff81168114613b8d57600080fd5b60006020828403121561408457600080fd5b610ac782614061565b60008151808452602080850194506020840160005b838110156140c75781516001600160a01b0316875295820195908201906001016140a2565b509495945050505050565b60208152600082518051602084015260ff602082015116604084015260ff604082015116606084015260608101511515608084015250602083015160c060a084015261412160e084018261408d565b90506040840151601f198483030160c085015261413e828261408d565b95945050505050565b6000806040838503121561415a57600080fd5b61416383613b76565b946020939093013593505050565b600060a0828403121561418357600080fd5b61418b613aa8565b90508135815261419d60208301613b76565b60208201526141ae60408301613b76565b60408201526141bf60608301613b76565b60608201526141d060808301613b76565b608082015292915050565b600082601f8301126141ec57600080fd5b813560206141fc613bf183613b3e565b82815260059290921b8401810191818101908684111561421b57600080fd5b8286015b848110156143155780356001600160401b038082111561423f5760008081fd5b9088019060a0828b03601f19018113156142595760008081fd5b614261613aa8565b87840135838111156142735760008081fd5b6142818d8a83880101613bd2565b825250604080850135848111156142985760008081fd5b6142a68e8b83890101613bd2565b8a84015250606080860135858111156142bf5760008081fd5b6142cd8f8c838a0101613bd2565b838501525060809150818601358184015250828501359250838311156142f35760008081fd5b6143018d8a85880101613bd2565b90820152865250505091830191830161421f565b509695505050505050565b6000610140828403121561433357600080fd5b61433b613aca565b90506143478383614171565b815260a08201356001600160401b038082111561436357600080fd5b61436f85838601613bd2565b602084015260c084013591508082111561438857600080fd5b61439485838601613bd2565b60408401526143a560e08501613fb6565b606084015261010084013560808401526101208401359150808211156143ca57600080fd5b506143d7848285016141db565b60a08301525092915050565b6000806000806000606086880312156143fb57600080fd5b85356001600160401b038082111561441257600080fd5b61441e89838a01614320565b9650602088013591508082111561443457600080fd5b61444089838a01613e02565b9096509450604088013591508082111561445957600080fd5b5061446688828901613e02565b969995985093965092949392505050565b600082601f83011261448857600080fd5b81356020614498613bf183613b3e565b82815260059290921b840181019181810190868411156144b757600080fd5b8286015b848110156143155780356001600160401b038111156144da5760008081fd5b6144e88986838b0101614320565b8452509183019183016144bb565b600082601f83011261450757600080fd5b81356020614517613bf183613b3e565b82815260059290921b8401810191818101908684111561453657600080fd5b8286015b848110156143155780356001600160401b038082111561455957600080fd5b818901915089603f83011261456d57600080fd5b8582013561457d613bf182613b3e565b81815260059190911b830160400190878101908c83111561459d57600080fd5b604085015b838110156145d6578035858111156145b957600080fd5b6145c88f6040838a0101613bd2565b8452509189019189016145a2565b5087525050509284019250830161453a565b600082601f8301126145f957600080fd5b81356020614609613bf183613b3e565b8083825260208201915060208460051b87010193508684111561462b57600080fd5b602086015b848110156143155780358352918301918301614630565b600082601f83011261465857600080fd5b81356020614668613bf183613b3e565b82815260059290921b8401810191818101908684111561468757600080fd5b8286015b848110156143155780356001600160401b03808211156146ab5760008081fd5b9088019060a0828b03601f19018113156146c55760008081fd5b6146cd613aa8565b6146d8888501613b76565b8152604080850135848111156146ee5760008081fd5b6146fc8e8b83890101614477565b8a84015250606080860135858111156147155760008081fd5b6147238f8c838a01016144f6565b838501525060809150818601358581111561473e5760008081fd5b61474c8f8c838a01016145e8565b918401919091525091909301359083015250835291830191830161468b565b6000806040838503121561477e57600080fd5b6001600160401b038335111561479357600080fd5b6147a08484358501614647565b91506001600160401b03602084013511156147ba57600080fd5b6020830135830184601f8201126147d057600080fd5b6147dd613bf18235613b3e565b81358082526020808301929160051b8401018710156147fb57600080fd5b602083015b6020843560051b8501018110156149a4576001600160401b038135111561482657600080fd5b87603f82358601011261483857600080fd5b61484b613bf16020833587010135613b3e565b81358501602081810135808452908301929160059190911b016040018a101561487357600080fd5b604083358701015b83358701602081013560051b01604001811015614994576001600160401b03813511156148a757600080fd5b833587018135016040818d03603f190112156148c257600080fd5b6148ca613aec565b604082013581526001600160401b03606083013511156148e957600080fd5b8c605f6060840135840101126148fe57600080fd5b6040606083013583010135614915613bf182613b3e565b808282526020820191508f60608460051b606088013588010101111561493a57600080fd5b6060808601358601015b60608460051b606088013588010101811015614974576149648135613fc1565b8035835260209283019201614944565b50806020850152505050808552505060208301925060208101905061487b565b5084525060209283019201614800565b508093505050509250929050565b6000602082840312156149c457600080fd5b610ac782613b76565b602081526001600160a01b0382511660208201526020820151151560408201526001600160401b0360408301511660608201526000606083015160808084015261337660a0840182613d6a565b600060208284031215614a2c57600080fd5b813561398681613b61565b600082601f830112614a4857600080fd5b81356020614a58613bf183613b3e565b8083825260208201915060208460051b870101935086841115614a7a57600080fd5b602086015b84811015614315578035614a9281613b61565b8352918301918301614a7f565b60006020808385031215614ab257600080fd5b82356001600160401b0380821115614ac957600080fd5b818501915085601f830112614add57600080fd5b8135614aeb613bf182613b3e565b81815260059190911b83018401908481019088831115614b0a57600080fd5b8585015b83811015613d3957803585811115614b2557600080fd5b860160c0818c03601f19011215614b3c5760008081fd5b614b44613aca565b8882013581526040614b57818401614061565b8a8301526060614b68818501614061565b8284015260809150614b7b828501613ba0565b9083015260a08381013589811115614b935760008081fd5b614ba18f8d83880101614a37565b838501525060c0840135915088821115614bbb5760008081fd5b614bc98e8c84870101614a37565b9083015250845250918601918601614b0e565b80356001600160e01b0381168114613b8d57600080fd5b600082601f830112614c0457600080fd5b81356020614c14613bf183613b3e565b82815260069290921b84018101918181019086841115614c3357600080fd5b8286015b848110156143155760408189031215614c505760008081fd5b614c58613aec565b614c6182613b76565b8152614c6e858301614bdc565b81860152835291830191604001614c37565b600082601f830112614c9157600080fd5b81356020614ca1613bf183613b3e565b82815260059290921b84018101918181019086841115614cc057600080fd5b8286015b848110156143155780356001600160401b0380821115614ce45760008081fd5b9088019060a0828b03601f1901811315614cfe5760008081fd5b614d06613aa8565b614d11888501613b76565b815260408085013584811115614d275760008081fd5b614d358e8b83890101613bd2565b8a8401525060609350614d49848601613b76565b908201526080614d5a858201613b76565b93820193909352920135908201528352918301918301614cc4565b600082601f830112614d8657600080fd5b81356020614d96613bf183613b3e565b82815260069290921b84018101918181019086841115614db557600080fd5b8286015b848110156143155760408189031215614dd25760008081fd5b614dda613aec565b813581528482013585820152835291830191604001614db9565b60006020808385031215614e0757600080fd5b82356001600160401b0380821115614e1e57600080fd5b9084019060608287031215614e3257600080fd5b614e3a613a86565b823582811115614e4957600080fd5b83016040818903811315614e5c57600080fd5b614e64613aec565b823585811115614e7357600080fd5b8301601f81018b13614e8457600080fd5b8035614e92613bf182613b3e565b81815260069190911b8201890190898101908d831115614eb157600080fd5b928a01925b82841015614f015785848f031215614ece5760008081fd5b614ed6613aec565b8435614ee181613b61565b8152614eee858d01614bdc565b818d0152825292850192908a0190614eb6565b845250505082870135915084821115614f1957600080fd5b614f258a838501614bf3565b81880152835250508284013582811115614f3e57600080fd5b614f4a88828601614c80565b85830152506040830135935081841115614f6357600080fd5b614f6f87858501614d75565b60408201529695505050505050565b600082825180855260208086019550808260051b84010181860160005b8481101561500f57601f19868403018952815160a06001600160401b03808351168652868301518288880152614fd383880182613d6a565b60408581015184169089015260608086015190931692880192909252506080928301519290950191909152509783019790830190600101614f9b565b5090979650505050505050565b600060408083526150306040840186614f7e565b83810360208581019190915285518083528682019282019060005b818110156150705784518051845284015184840152938301939185019160010161504b565b509098975050505050505050565b634e487b7160e01b600052603260045260246000fd5b805160408084528151848201819052600092602091908201906060870190855b818110156150eb57835180516001600160a01b031684528501516001600160e01b03168584015292840192918501916001016150b4565b50508583015187820388850152805180835290840192506000918401905b8083101561514457835180516001600160401b031683528501516001600160e01b031685830152928401926001929092019190850190615109565b50979650505050505050565b602081526000610ac76020830184615094565b60006020828403121561517557600080fd5b815161398681613b92565b600181811c9082168061519457607f821691505b6020821081036151b457634e487b7160e01b600052602260045260246000fd5b50919050565b60008083546151c881615180565b600182811680156151e057600181146151f557615224565b60ff1984168752821515830287019450615224565b8760005260208060002060005b8581101561521b5781548a820152908401908201615202565b50505082870194505b50929695505050505050565b6000815461523d81615180565b80855260206001838116801561525a5760018114615274576152a2565b60ff1985168884015283151560051b8801830195506152a2565b866000528260002060005b8581101561529a5781548a820186015290830190840161527f565b890184019650505b505050505092915050565b6040815260006152c06040830185613d6a565b828103602084015261413e8185615230565b634e487b7160e01b600052601160045260246000fd5b6001600160401b03818116838216019080821115615308576153086152d2565b5092915050565b6040815260006153226040830185614f7e565b828103602084015261413e8185615094565b60006020828403121561534657600080fd5b81356001600160401b0381111561535c57600080fd5b61337684828501614647565b81810381811115610aca57610aca6152d2565b634e487b7160e01b600052601260045260246000fd5b60006001600160401b03808416806153ab576153ab61537b565b92169190910692915050565b8082028115828204841417610aca57610aca6152d2565b80518252600060206001600160401b0381840151168185015260408084015160a0604087015261540160a0870182613d6a565b90506060850151868203606088015261541a8282613d6a565b608087810151898303918a01919091528051808352908601935060009250908501905b8083101561514457835180516001600160a01b031683528601518683015292850192600192909201919084019061543d565b602081526000610ac760208301846153ce565b60808152600061549560808301876153ce565b61ffff9590951660208301525060408101929092526001600160a01b0316606090910152919050565b6000806000606084860312156154d357600080fd5b83516154de81613b92565b60208501519093506001600160401b038111156154fa57600080fd5b8401601f8101861361550b57600080fd5b8051615519613bf182613bab565b81815287602083850101111561552e57600080fd5b61553f826020830160208601613d46565b809450505050604084015190509250925092565b60006020828403121561556557600080fd5b815161398681613fc1565b601f821115611272576000816000526020600020601f850160051c810160208610156155995750805b601f850160051c820191505b818110156155b8578281556001016155a5565b505050505050565b81516001600160401b038111156155d9576155d9613a48565b6155ed816155e78454615180565b84615570565b602080601f831160018114615622576000841561560a5750858301515b600019600386901b1c1916600185901b1785556155b8565b600085815260208120601f198616915b8281101561565157888601518255948401946001909101908401615632565b508582101561566f5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60208152600082546001600160a01b038116602084015260ff8160a01c16151560408401526001600160401b038160a81c16606084015250608080830152610ac760a0830160018501615230565b80820180821115610aca57610aca6152d2565b60ff8181168382160190811115610aca57610aca6152d2565b8183823760009101908152919050565b828152606082602083013760800192915050565b60006001600160401b03808416806157375761573761537b565b92169190910492915050565b60006020828403121561575557600080fd5b813561398681613fc1565b6000808335601e1984360301811261577757600080fd5b8301803591506001600160401b0382111561579157600080fd5b602001915036819003821315613dfb57600080fd5b60208101600583106157ba576157ba613f7e565b91905290565b60ff8181168382160290811690818114615308576153086152d2565b600060a0820160ff881683526020878185015260a0604085015281875480845260c0860191508860005282600020935060005b818110156158345784546001600160a01b03168352600194850194928401920161580f565b50508481036060860152865180825290820192508187019060005b818110156158745782516001600160a01b03168552938301939183019160010161584f565b50505060ff851660808501525090505b9695505050505050565b60006001600160401b0380861683528085166020840152506060604083015261413e6060830184613d6a565b8281526040602082015260006133766040830184613d6a565b6001600160401b03848116825283166020820152606081016133766040830184613f94565b8481526159086020820185613f94565b60806040820152600061591e6080830185613d6a565b905082606083015295945050505050565b60006020828403121561594157600080fd5b815161398681613b61565b602081526000825161010080602085015261596b610120850183613d6a565b9150602085015161598760408601826001600160401b03169052565b5060408501516001600160a01b0381166060860152506060850151608085015260808501516159c160a08601826001600160a01b03169052565b5060a0850151601f19808685030160c08701526159de8483613d6a565b935060c08701519150808685030160e08701526159fb8483613d6a565b935060e08701519150808685030183870152506158848382613d6a565b600060208284031215615a2a57600080fd5b5051919050565b600082825180855260208086019550808260051b84010181860160005b8481101561500f57601f19868403018952815160a08151818652615a7482870182613d6a565b9150508582015185820387870152615a8c8282613d6a565b91505060408083015186830382880152615aa68382613d6a565b92505050606080830151818701525060808083015192508582038187015250615acf8183613d6a565b9a86019a9450505090830190600101615a4e565b602081526000610ac76020830184615a31565b60008282518085526020808601955060208260051b8401016020860160005b8481101561500f57601f19868403018952615b31838351613d6a565b98840198925090830190600101615b15565b60008151808452602080850194506020840160005b838110156140c757815163ffffffff1687529582019590820190600101615b58565b60608152600084518051606084015260208101516001600160401b0380821660808601528060408401511660a08601528060608401511660c08601528060808401511660e0860152505050602085015161014080610100850152615be26101a0850183613d6a565b91506040870151605f198086850301610120870152615c018483613d6a565b935060608901519150615c1e838701836001600160a01b03169052565b608089015161016087015260a0890151925080868503016101808701525050615c478282615a31565b9150508281036020840152615c5c8186615af6565b905082810360408401526158848185615b4356fea164736f6c6343000818000a", + Bin: "0x6101206040523480156200001257600080fd5b50604051620068cb380380620068cb833981016040819052620000359162000806565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf81620001fa565b5050466080525060208301516001600160a01b03161580620000ec575060408301516001600160a01b0316155b8062000103575060608301516001600160a01b0316155b1562000122576040516342bcdf7f60e11b815260040160405180910390fd5b82516001600160401b03166000036200014e5760405163c656089560e01b815260040160405180910390fd5b82516001600160401b0390811660a052602080850180516001600160a01b0390811660c05260408088018051831660e0526060808a01805185166101005283518b519098168852945184169587019590955251821690850152905116908201527f683eb52ee924eb817377cfa8f41f238f4bb7a877da5267869dfffbad85f564d89060800160405180910390a1620001e682620002a5565b620001f1816200036d565b50505062000b8d565b336001600160a01b03821603620002545760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b0316620002ce576040516342bcdf7f60e11b815260040160405180910390fd5b805160048054602080850180516001600160a01b039586166001600160c01b03199094168417600160a01b63ffffffff928316021790945560408087018051600580546001600160a01b031916918916919091179055815194855291519094169183019190915251909216908201527fa1c15688cb2c24508e158f6942b9276c6f3028a85e1af8cf3fff0c3ff3d5fc8d9060600160405180910390a150565b60005b8151811015620005ba57600082828151811062000391576200039162000943565b60200260200101519050600081602001519050806001600160401b0316600003620003cf5760405163c656089560e01b815260040160405180910390fd5b81516001600160a01b0316620003f8576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160401b03811660009081526006602052604090206060830151600182018054620004269062000959565b905060000362000489578154600160a81b600160e81b031916600160a81b1782556040516001600160401b03841681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1620004c8565b8154600160a81b90046001600160401b0316600114620004c857604051632105803760e11b81526001600160401b038416600482015260240162000083565b80511580620004fe5750604080516000602082015201604051602081830303815290604052805190602001208180519060200120145b156200051d576040516342bcdf7f60e11b815260040160405180910390fd5b600182016200052d8282620009ea565b50604080850151835486516001600160a01b03166001600160a01b0319921515600160a01b02929092166001600160a81b031990911617178355516001600160401b038416907f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b90620005a290859062000ab6565b60405180910390a25050505080600101905062000370565b5050565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b0381118282101715620005f957620005f9620005be565b60405290565b604051601f8201601f191681016001600160401b03811182821017156200062a576200062a620005be565b604052919050565b80516001600160401b03811681146200064a57600080fd5b919050565b6001600160a01b03811681146200066557600080fd5b50565b6000601f83601f8401126200067c57600080fd5b825160206001600160401b03808311156200069b576200069b620005be565b8260051b620006ac838201620005ff565b9384528681018301938381019089861115620006c757600080fd5b84890192505b85831015620007f957825184811115620006e75760008081fd5b89016080601f19828d038101821315620007015760008081fd5b6200070b620005d4565b888401516200071a816200064f565b815260406200072b85820162000632565b8a8301526060808601518015158114620007455760008081fd5b838301529385015193898511156200075d5760008081fd5b84860195508f603f8701126200077557600094508485fd5b8a8601519450898511156200078e576200078e620005be565b6200079f8b858f88011601620005ff565b93508484528f82868801011115620007b75760008081fd5b60005b85811015620007d7578681018301518582018d01528b01620007ba565b5060009484018b019490945250918201528352509184019190840190620006cd565b9998505050505050505050565b60008060008385036101008112156200081e57600080fd5b60808112156200082d57600080fd5b62000837620005d4565b620008428662000632565b8152602086015162000854816200064f565b6020820152604086015162000869816200064f565b604082015260608601516200087e816200064f565b606082810191909152909450607f19820112156200089b57600080fd5b50604051606081016001600160401b038082118383101715620008c257620008c2620005be565b8160405260808701519150620008d8826200064f565b90825260a08601519063ffffffff82168214620008f457600080fd5b81602084015260c087015191506200090c826200064f565b6040830182905260e0870151929450808311156200092957600080fd5b5050620009398682870162000668565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b600181811c908216806200096e57607f821691505b6020821081036200098f57634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115620009e5576000816000526020600020601f850160051c81016020861015620009c05750805b601f850160051c820191505b81811015620009e157828155600101620009cc565b5050505b505050565b81516001600160401b0381111562000a065762000a06620005be565b62000a1e8162000a17845462000959565b8462000995565b602080601f83116001811462000a56576000841562000a3d5750858301515b600019600386901b1c1916600185901b178555620009e1565b600085815260208120601f198616915b8281101562000a875788860151825594840194600190910190840162000a66565b508582101562000aa65787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b602080825282546001600160a01b0381168383015260a081901c60ff161515604084015260a81c6001600160401b0316606083015260808083015260018084018054600093929190849062000b0b8162000959565b8060a089015260c0600183166000811462000b2f576001811462000b4c5762000b7e565b60ff19841660c08b015260c083151560051b8b0101945062000b7e565b85600052602060002060005b8481101562000b755781548c820185015290880190890162000b58565b8b0160c0019550505b50929998505050505050505050565b60805160a05160c05160e05161010051615cc862000c036000396000818161022c01526129f40152600081816101fd0152612cc60152600081816101ce01528181610552015281816106ff01526123b501526000818161019f01526125f4015260008181611d920152611dc50152615cc86000f3fe608060405234801561001057600080fd5b50600436106101515760003560e01c806379ba5097116100cd578063d434969111610081578063e9d68a8e11610066578063e9d68a8e146104bc578063f2fde38b146104dc578063f716f99f146104ef57600080fd5b8063d434969114610496578063e62653f5146104a957600080fd5b80638da5cb5b116100b25780638da5cb5b14610417578063c673e58414610432578063ccd37ba31461045257600080fd5b806379ba50971461040157806385572ffb1461040957600080fd5b8063311cd513116101245780635e36480c116101095780635e36480c1461033c5780636f9e320f1461035c5780637437ff9f1461036f57600080fd5b8063311cd5131461030e5780633f4b04aa1461032157600080fd5b806304666f9c1461015657806306285c691461016b578063181f5a77146102b25780632d04ab76146102fb575b600080fd5b610169610164366004613c73565b610502565b005b61025c60408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160401b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316815250905090565b6040516102a9919081516001600160401b031681526020808301516001600160a01b0390811691830191909152604080840151821690830152606092830151169181019190915260800190565b60405180910390f35b6102ee6040518060400160405280601181526020017f4f666652616d7020312e362e302d64657600000000000000000000000000000081525081565b6040516102a99190613de1565b610169610309366004613e91565b610516565b61016961031c366004613f43565b610a12565b6009546040516001600160401b0390911681526020016102a9565b61034f61034a366004613f96565b610a7b565b6040516102a99190613ff3565b61016961036a36600461401e565b610ad0565b6103cb604080516060810182526000808252602082018190529181019190915250604080516060810182526004546001600160a01b038082168352600160a01b90910463ffffffff166020830152600554169181019190915290565b6040805182516001600160a01b03908116825260208085015163ffffffff169083015292820151909216908201526060016102a9565b610169610ae1565b610169610151366004614072565b6000546040516001600160a01b0390911681526020016102a9565b6104456104403660046140bd565b610b92565b6040516102a9919061411d565b610488610460366004614192565b6001600160401b03919091166000908152600860209081526040808320938352929052205490565b6040519081526020016102a9565b6101696104a436600461442e565b610cf0565b6101696104b73660046147b6565b610fd0565b6104cf6104ca3660046149fd565b611277565b6040516102a99190614a18565b6101696104ea366004614a65565b611383565b6101696104fd366004614aea565b611394565b61050a6113d6565b61051381611432565b50565b600061052487890189614e3f565b602081015151909150156105b6576020810151604080830151905162ccd5af60e81b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169263ccd5af009261058592600401615067565b60006040518083038186803b15801561059d57600080fd5b505afa1580156105b1573d6000803e3d6000fd5b505050505b805151511515806105cc57508051602001515115155b156106985760095460208a0135906001600160401b0380831691161015610670576009805467ffffffffffffffff19166001600160401b038316179055600480548351604051633937306f60e01b81526001600160a01b0390921692633937306f9261063992910161519b565b600060405180830381600087803b15801561065357600080fd5b505af1158015610667573d6000803e3d6000fd5b50505050610696565b81602001515160000361069657604051632261116760e01b815260040160405180910390fd5b505b60005b816020015151811015610953576000826020015182815181106106c0576106c06150c9565b60209081029190910101518051604051632cbc26bb60e01b815267ffffffffffffffff60801b608083901b166004820152919250906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632cbc26bb90602401602060405180830381865afa158015610746573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061076a91906151ae565b1561079857604051637edeb53960e11b81526001600160401b03821660048201526024015b60405180910390fd5b60006107a382611685565b9050806001016040516107b69190615205565b6040518091039020836020015180519060200120146107f35782602001518160010160405163b80d8fa960e01b815260040161078f9291906152f8565b60408301518154600160a81b90046001600160401b039081169116141580610834575082606001516001600160401b031683604001516001600160401b0316115b1561087957825160408085015160608601519151636af0786b60e11b81526001600160401b03938416600482015290831660248201529116604482015260640161078f565b60808301518061089c5760405163504570e360e01b815260040160405180910390fd5b83516001600160401b03166000908152600860209081526040808320848452909152902054156108f45783516040516332cf0cbf60e01b81526001600160401b0390911660048201526024810182905260440161078f565b6060840151610904906001615333565b825467ffffffffffffffff60a81b1916600160a81b6001600160401b0392831602179092559251166000908152600860209081526040808320948352939052919091204290555060010161069b565b50602081015181516040517f35c02761bcd3ef995c6a601a1981f4ed3934dcbe5041e24e286c89f5531d17e49261098b92909161535a565b60405180910390a1610a0760008a8a8a8a8a8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808e0282810182019093528d82529093508d92508c9182918501908490808284376000920191909152508b92506116d1915050565b505050505050505050565b610a52610a218284018461537f565b6040805160008082526020820190925290610a4c565b6060815260200190600190039081610a375790505b506119ca565b604080516000808252602082019092529050610a756001858585858660006116d1565b50505050565b6000610a89600160046153b3565b6002610a966080856153dc565b6001600160401b0316610aa99190615402565b610ab38585611a8c565b901c166003811115610ac757610ac7613fc9565b90505b92915050565b610ad86113d6565b61051381611ad1565b6001546001600160a01b03163314610b3b5760405162461bcd60e51b815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e657200000000000000000000604482015260640161078f565b60008054336001600160a01b0319808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610bd56040805160e081019091526000606082018181526080830182905260a0830182905260c08301919091528190815260200160608152602001606081525090565b60ff808316600090815260026020818152604092839020835160e081018552815460608201908152600183015480881660808401526101008104881660a0840152620100009004909616151560c082015294855291820180548451818402810184019095528085529293858301939092830182828015610c7e57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610c60575b5050505050815260200160038201805480602002602001604051908101604052809291908181526020018280548015610ce057602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610cc2575b5050505050815250509050919050565b333014610d10576040516306e34e6560e31b815260040160405180910390fd5b6040805160008082526020820190925281610d4d565b6040805180820190915260008082526020820152815260200190600190039081610d265790505b5060a08701515190915015610d8357610d808660a001518760200151886060015189600001516020015189898989611bb0565b90505b6040805160a081018252875151815287516020908101516001600160401b031681830152808901518351600094840192610dbe929101613de1565b60408051601f19818403018152918152908252898101516020830152018390526005549091506001600160a01b03168015610e99576040516308d450a160e01b81526001600160a01b038216906308d450a190610e1f9085906004016154ba565b600060405180830381600087803b158015610e3957600080fd5b505af1925050508015610e4a575060015b610e99573d808015610e78576040519150601f19603f3d011682016040523d82523d6000602084013e610e7d565b606091505b50806040516309c2532560e01b815260040161078f9190613de1565b604088015151158015610eae57506080880151155b80610ec5575060608801516001600160a01b03163b155b80610eec57506060880151610eea906001600160a01b03166385572ffb60e01b611d73565b155b15610ef957505050610fc9565b87516020908101516001600160401b03166000908152600690915260408082205460808b015160608c01519251633cf9798360e01b815284936001600160a01b0390931692633cf9798392610f5792899261138892916004016154cd565b6000604051808303816000875af1158015610f76573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610f9e9190810190615509565b509150915081610fc357806040516302a35ba360e21b815260040161078f9190613de1565b50505050505b5050505050565b610fd8611d8f565b815181518114610ffb576040516320f8fd5960e21b815260040160405180910390fd5b60005b8181101561126757600084828151811061101a5761101a6150c9565b60200260200101519050600081602001515190506000858481518110611042576110426150c9565b602002602001015190508051821461106d576040516320f8fd5960e21b815260040160405180910390fd5b60005b8281101561125857600082828151811061108c5761108c6150c9565b60200260200101516000015190506000856020015183815181106110b2576110b26150c9565b6020026020010151905081600014611106578060800151821015611106578551815151604051633a98d46360e11b81526001600160401b03909216600483015260248201526044810183905260640161078f565b838381518110611118576111186150c9565b602002602001015160200151518160a00151511461116557805180516060909101516040516370a193fd60e01b815260048101929092526001600160401b0316602482015260440161078f565b60005b8160a001515181101561124a576000858581518110611189576111896150c9565b60200260200101516020015182815181106111a6576111a66150c9565b602002602001015163ffffffff169050806000146112415760008360a0015183815181106111d6576111d66150c9565b6020026020010151608001518060200190518101906111f5919061559e565b90508063ffffffff1682101561123f578351516040516348e617b360e01b815260048101919091526024810184905263ffffffff821660448201526064810183905260840161078f565b505b50600101611168565b505050806001019050611070565b50505050806001019050610ffe565b5061127283836119ca565b505050565b60408051608080820183526000808352602080840182905283850182905260608085018190526001600160401b03878116845260068352928690208651948501875280546001600160a01b0381168652600160a01b810460ff16151593860193909352600160a81b909204909216948301949094526001840180549394929391840191611303906151cb565b80601f016020809104026020016040519081016040528092919081815260200182805461132f906151cb565b8015610ce05780601f1061135157610100808354040283529160200191610ce0565b820191906000526020600020905b81548152906001019060200180831161135f57505050919092525091949350505050565b61138b6113d6565b61051381611df7565b61139c6113d6565b60005b81518110156113d2576113ca8282815181106113bd576113bd6150c9565b6020026020010151611ea0565b60010161139f565b5050565b6000546001600160a01b031633146114305760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640161078f565b565b60005b81518110156113d2576000828281518110611452576114526150c9565b60200260200101519050600081602001519050806001600160401b031660000361148f5760405163c656089560e01b815260040160405180910390fd5b81516001600160a01b03166114b7576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160401b038116600090815260066020526040902060608301516001820180546114e3906151cb565b905060000361154557815467ffffffffffffffff60a81b1916600160a81b1782556040516001600160401b03841681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1611582565b8154600160a81b90046001600160401b031660011461158257604051632105803760e11b81526001600160401b038416600482015260240161078f565b805115806115b75750604080516000602082015201604051602081830303815290604052805190602001208180519060200120145b156115d5576040516342bcdf7f60e11b815260040160405180910390fd5b600182016115e3828261560b565b50604080850151835486516001600160a01b03166001600160a01b0319921515600160a01b02929092167fffffffffffffffffffffff00000000000000000000000000000000000000000090911617178355516001600160401b038416907f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b9061166e9085906156ca565b60405180910390a250505050806001019050611435565b6001600160401b03811660009081526006602052604081208054600160a01b900460ff16610aca5760405163ed053c5960e01b81526001600160401b038416600482015260240161078f565b60ff878116600090815260026020908152604080832081516080810183528154815260019091015480861693820193909352610100830485169181019190915262010000909104909216151560608301528735906117308760a4615718565b9050826060015115611778578451611749906020615402565b8651611756906020615402565b6117619060a0615718565b61176b9190615718565b6117759082615718565b90505b3681146117a157604051638e1192e160e01b81526004810182905236602482015260440161078f565b50815181146117d05781516040516324f7d61360e21b815260048101919091526024810182905260440161078f565b6117d8611d8f565b60ff808a166000908152600360209081526040808320338452825280832081518083019092528054808616835293949193909284019161010090910416600281111561182657611826613fc9565b600281111561183757611837613fc9565b905250905060028160200151600281111561185457611854613fc9565b1480156118a85750600260008b60ff1660ff168152602001908152602001600020600301816000015160ff1681548110611890576118906150c9565b6000918252602090912001546001600160a01b031633145b6118c557604051631b41e11d60e31b815260040160405180910390fd5b508160600151156119755760208201516118e090600161572b565b60ff16855114611903576040516371253a2560e01b815260040160405180910390fd5b83518551146119255760405163a75d88af60e01b815260040160405180910390fd5b60008787604051611937929190615744565b60405190819003812061194e918b90602001615754565b6040516020818303038152906040528051906020012090506119738a828888886121ca565b505b6040805182815260208a8101356001600160401b03169082015260ff8b16917f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef0910160405180910390a2505050505050505050565b81516000036119eb5760405162bf199760e01b815260040160405180910390fd5b80516040805160008082526020820190925291159181611a2e565b604080518082019091526000815260606020820152815260200190600190039081611a065790505b50905060005b8451811015610fc957611a84858281518110611a5257611a526150c9565b602002602001015184611a7e57858381518110611a7157611a716150c9565b6020026020010151612387565b83612387565b600101611a34565b6001600160401b038216600090815260076020526040812081611ab0608085615768565b6001600160401b031681526020810191909152604001600020549392505050565b80516001600160a01b0316611af9576040516342bcdf7f60e11b815260040160405180910390fd5b805160048054602080850180516001600160a01b039586167fffffffffffffffff0000000000000000000000000000000000000000000000009094168417600160a01b63ffffffff928316021790945560408087018051600580546001600160a01b031916918916919091179055815194855291519094169183019190915251909216908201527fa1c15688cb2c24508e158f6942b9276c6f3028a85e1af8cf3fff0c3ff3d5fc8d9060600160405180910390a150565b606088516001600160401b03811115611bcb57611bcb613a93565b604051908082528060200260200182016040528015611c1057816020015b6040805180820190915260008082526020820152815260200190600190039081611be95790505b509050811560005b8a51811015611d655781611cc257848482818110611c3857611c386150c9565b9050602002016020810190611c4d919061578e565b63ffffffff1615611cc257848482818110611c6a57611c6a6150c9565b9050602002016020810190611c7f919061578e565b6040805163ffffffff9092166020830152016040516020818303038152906040528b8281518110611cb257611cb26150c9565b6020026020010151608001819052505b611d408b8281518110611cd757611cd76150c9565b60200260200101518b8b8b8b8b87818110611cf457611cf46150c9565b9050602002810190611d0691906157ab565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612c7e92505050565b838281518110611d5257611d526150c9565b6020908102919091010152600101611c18565b505098975050505050505050565b6000611d7e83612f7c565b8015610ac75750610ac78383612fc7565b467f00000000000000000000000000000000000000000000000000000000000000001461143057604051630f01ce8560e01b81527f0000000000000000000000000000000000000000000000000000000000000000600482015246602482015260440161078f565b336001600160a01b03821603611e4f5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161078f565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b806040015160ff16600003611ecb576000604051631b3fab5160e11b815260040161078f91906157f1565b60208082015160ff80821660009081526002909352604083206001810154929390928392169003611f1c576060840151600182018054911515620100000262ff000019909216919091179055611f58565b6060840151600182015460ff6201000090910416151590151514611f58576040516321fd80df60e21b815260ff8416600482015260240161078f565b60a084015180516101001015611f84576001604051631b3fab5160e11b815260040161078f91906157f1565b8051600003611fa9576005604051631b3fab5160e11b815260040161078f91906157f1565b61200f848460030180548060200260200160405190810160405280929190818152602001828054801561200557602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611fe7575b5050505050613069565b84606001511561213f5761207d8484600201805480602002602001604051908101604052809291908181526020018280548015612005576020028201919060005260206000209081546001600160a01b03168152600190910190602001808311611fe7575050505050613069565b6080850151805161010010156120a9576002604051631b3fab5160e11b815260040161078f91906157f1565b60408601516120b990600361580b565b60ff168151116120df576003604051631b3fab5160e11b815260040161078f91906157f1565b815181511015612105576001604051631b3fab5160e11b815260040161078f91906157f1565b805160018401805461ff00191661010060ff8416021790556121309060028601906020840190613a19565b5061213d858260016130d2565b505b61214b848260026130d2565b80516121609060038501906020840190613a19565b5060408581015160018401805460ff191660ff8316179055865180855560a088015192517fab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f547936121b99389939260028a01929190615827565b60405180910390a1610fc98461322d565b8251600090815b8181101561237d5760006001888684602081106121f0576121f06150c9565b6121fd91901a601b61572b565b89858151811061220f5761220f6150c9565b6020026020010151898681518110612229576122296150c9565b602002602001015160405160008152602001604052604051612267949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015612289573d6000803e3d6000fd5b505060408051601f1981015160ff808e166000908152600360209081528582206001600160a01b038516835281528582208587019096528554808416865293975090955092939284019161010090041660028111156122ea576122ea613fc9565b60028111156122fb576122fb613fc9565b905250905060018160200151600281111561231857612318613fc9565b1461233657604051636518c33d60e11b815260040160405180910390fd5b8051600160ff9091161b85161561236057604051633d9ef1f160e21b815260040160405180910390fd5b806000015160ff166001901b8517945050508060010190506121d1565b5050505050505050565b81518151604051632cbc26bb60e01b8152608083901b67ffffffffffffffff60801b166004820152901515907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632cbc26bb90602401602060405180830381865afa158015612404573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061242891906151ae565b1561249957801561245757604051637edeb53960e11b81526001600160401b038316600482015260240161078f565b6040516001600160401b03831681527faab522ed53d887e56ed53dd37398a01aeef6a58e0fa77c2173beb9512d8949339060200160405180910390a150505050565b60006124a483611685565b60010180546124b2906151cb565b80601f01602080910402602001604051908101604052809291908181526020018280546124de906151cb565b801561252b5780601f106125005761010080835404028352916020019161252b565b820191906000526020600020905b81548152906001019060200180831161250e57829003601f168201915b5050506020880151519293505050600081900361255a5760405162bf199760e01b815260040160405180910390fd5b856040015151811461257f576040516357e0e08360e01b815260040160405180910390fd5b6000816001600160401b0381111561259957612599613a93565b6040519080825280602002602001820160405280156125c2578160200160208202803683370190505b50905060005b82811015612766576000886020015182815181106125e8576125e86150c9565b602002602001015190507f00000000000000000000000000000000000000000000000000000000000000006001600160401b03168160000151604001516001600160401b03161461265f5780516040908101519051631c21951160e11b81526001600160401b03909116600482015260240161078f565b866001600160401b03168160000151602001516001600160401b0316146126b357805160200151604051636c95f1eb60e01b81526001600160401b03808a166004830152909116602482015260440161078f565b612740817f2425b0b9f9054c76ff151b0a175b18f37a4a4e82013a72e9f15c9caa095ed21f836000015160200151846000015160400151898051906020012060405160200161272594939291909384526001600160401b03928316602085015291166040830152606082015260800190565b60405160208183030381529060405280519060200120613284565b838381518110612752576127526150c9565b6020908102919091010152506001016125c8565b50600061277d86838a606001518b6080015161338c565b9050806000036127ab57604051633ee8bd3f60e11b81526001600160401b038716600482015260240161078f565b60005b83811015610a075760005a905060008a6020015183815181106127d3576127d36150c9565b6020026020010151905060006127f18a836000015160600151610a7b565b9050600081600381111561280757612807613fc9565b14806128245750600381600381111561282257612822613fc9565b145b61287a57815160600151604080516001600160401b03808e16825290921660208301527f3b575419319662b2a6f5e2467d84521517a3382b908eb3d557bb3fdb0c50e23c910160405180910390a1505050612c76565b60608915612959578b8581518110612894576128946150c9565b6020908102919091018101510151600454909150600090600160a01b900463ffffffff166128c288426153b3565b11905080806128e2575060038360038111156128e0576128e0613fc9565b145b61290a576040516354e7e43160e11b81526001600160401b038d16600482015260240161078f565b8c868151811061291c5761291c6150c9565b602002602001015160000151600014612953578c8681518110612941576129416150c9565b60209081029190910101515160808501525b506129c5565b600082600381111561296d5761296d613fc9565b146129c557825160600151604080516001600160401b03808f16825290921660208301527f3ef2a99c550a751d4b0b261268f05a803dfb049ab43616a1ffb388f61fe65120910160405180910390a150505050612c76565b8251608001516001600160401b031615612a9e5760008260038111156129ed576129ed613fc9565b03612a9e577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e0e03cae8c85600001516080015186602001516040518463ffffffff1660e01b8152600401612a4e939291906158d9565b6020604051808303816000875af1158015612a6d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a9191906151ae565b612a9e5750505050612c76565b60008d604001518681518110612ab657612ab66150c9565b6020026020010151905080518460a001515114612b0057835160600151604051631cfe6d8b60e01b81526001600160401b03808f166004830152909116602482015260440161078f565b612b148c85600001516060015160016133c9565b600080612b2286848661346e565b91509150612b398e876000015160600151846133c9565b8c15612b90576003826003811115612b5357612b53613fc9565b03612b90576000856003811115612b6c57612b6c613fc9565b14612b9057855151604051632b11b8d960e01b815261078f91908390600401615905565b6002826003811115612ba457612ba4613fc9565b14612be9576003826003811115612bbd57612bbd613fc9565b14612be9578d866000015160600151836040516349362d1f60e11b815260040161078f9392919061591e565b8560000151600001518660000151606001516001600160401b03168f6001600160401b03167f05665fe9ad095383d018353f4cbcba77e84db27dd215081bbf7cdf9ae6fbe48b8d8c81518110612c4157612c416150c9565b602002602001015186865a612c56908f6153b3565b604051612c669493929190615943565b60405180910390a4505050505050505b6001016127ae565b60408051808201909152600080825260208201526000612ca18760200151613522565b60405163bbe4f6db60e01b81526001600160a01b0380831660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063bbe4f6db90602401602060405180830381865afa158015612d0d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d31919061597a565b90506001600160a01b0381161580612d605750612d5e6001600160a01b03821663aff2afbf60e01b611d73565b155b15612d895760405163ae9b4ce960e01b81526001600160a01b038216600482015260240161078f565b600080612db488858c60800151806020019051810190612da9919061559e565b63ffffffff16613596565b915091506000806000612e676040518061010001604052808e81526020018c6001600160401b031681526020018d6001600160a01b031681526020018f606001518152602001896001600160a01b031681526020018f6000015181526020018f6040015181526020018b815250604051602401612e319190615997565b60408051601f198184030181529190526020810180516001600160e01b0316633907753760e01b17905287866113886084613679565b92509250925082612e8d578160405163e1cd550960e01b815260040161078f9190613de1565b8151602014612ebc578151604051631e3be00960e21b815260206004820152602481019190915260440161078f565b600082806020019051810190612ed29190615a63565b9050866001600160a01b03168c6001600160a01b031614612f4e576000612f038d8a612efe868a6153b3565b613596565b50905086811080612f1d575081612f1a88836153b3565b14155b15612f4c5760405163a966e21f60e01b815260048101839052602481018890526044810182905260640161078f565b505b604080518082019091526001600160a01b039098168852602088015250949550505050505095945050505050565b6000612f8f826301ffc9a760e01b612fc7565b8015610aca5750612fc0827fffffffff00000000000000000000000000000000000000000000000000000000612fc7565b1592915050565b6040517fffffffff0000000000000000000000000000000000000000000000000000000082166024820152600090819060440160408051601f19818403018152919052602080820180516001600160e01b03166301ffc9a760e01b178152825192935060009283928392909183918a617530fa92503d91506000519050828015613052575060208210155b801561305e5750600081115b979650505050505050565b60005b81518110156112725760ff83166000908152600360205260408120835190919084908490811061309e5761309e6150c9565b6020908102919091018101516001600160a01b03168252810191909152604001600020805461ffff1916905560010161306c565b60005b8251811015610a755760008382815181106130f2576130f26150c9565b602002602001015190506000600281111561310f5761310f613fc9565b60ff80871660009081526003602090815260408083206001600160a01b0387168452909152902054610100900416600281111561314e5761314e613fc9565b1461316f576004604051631b3fab5160e11b815260040161078f91906157f1565b6001600160a01b0381166131965760405163d6c62c9b60e01b815260040160405180910390fd5b60405180604001604052808360ff1681526020018460028111156131bc576131bc613fc9565b905260ff80871660009081526003602090815260408083206001600160a01b0387168452825290912083518154931660ff198416811782559184015190929091839161ffff19161761010083600281111561321957613219613fc9565b0217905550905050508060010190506130d5565b60ff81166105135760ff8082166000908152600260205260409020600101546201000090041661327057604051631e8ed32560e21b815260040160405180910390fd5b6009805467ffffffffffffffff1916905550565b8151805160608085015190830151608080870151940151604051600095869588956132e895919490939192916020019485526001600160a01b039390931660208501526001600160401b039182166040850152606084015216608082015260a00190565b604051602081830303815290604052805190602001208560200151805190602001208660400151805190602001208760a0015160405160200161332b9190615b2e565b60408051601f198184030181528282528051602091820120908301979097528101949094526060840192909252608083015260a082015260c081019190915260e0015b60405160208183030381529060405280519060200120905092915050565b60008061339a858585613753565b6001600160401b038716600090815260086020908152604080832093835292905220549150505b949350505050565b600060026133d86080856153dc565b6001600160401b03166133eb9190615402565b905060006133f98585611a8c565b905081613408600160046153b3565b901b19168183600381111561341f5761341f613fc9565b6001600160401b03871660009081526007602052604081209190921b9290921791829161344d608088615768565b6001600160401b031681526020810191909152604001600020555050505050565b60405163d434969160e01b8152600090606090309063d43496919061349b90889088908890600401615bc5565b600060405180830381600087803b1580156134b557600080fd5b505af19250505080156134c6575060015b613505573d8080156134f4576040519150601f19603f3d011682016040523d82523d6000602084013e6134f9565b606091505b5060039250905061351a565b50506040805160208101909152600081526002905b935093915050565b60008151602014613548578160405163046b337b60e51b815260040161078f9190613de1565b60008280602001905181019061355e9190615a63565b90506001600160a01b03811180613576575061040081105b15610aca578260405163046b337b60e51b815260040161078f9190613de1565b60008060008060006135f7886040516024016135c191906001600160a01b0391909116815260200190565b60408051601f198184030181529190526020810180516001600160e01b03166370a0823160e01b17905288886113886084613679565b9250925092508261361d578160405163e1cd550960e01b815260040161078f9190613de1565b602082511461364c578151604051631e3be00960e21b815260206004820152602481019190915260440161078f565b818060200190518101906136609190615a63565b61366a82886153b3565b94509450505050935093915050565b6000606060008361ffff166001600160401b0381111561369b5761369b613a93565b6040519080825280601f01601f1916602001820160405280156136c5576020820181803683370190505b509150863b6136df5763030ed58f60e21b60005260046000fd5b5a858110156136f957632be8ca8b60e21b60005260046000fd5b8590036040810481038710613719576337c3be2960e01b60005260046000fd5b505a6000808a5160208c0160008c8cf193505a900390503d8481111561373c5750835b808352806000602085013e50955095509592505050565b825182516000919081830361377b57604051630469ac9960e21b815260040160405180910390fd5b610101821180159061378f57506101018111155b6137ac576040516309bde33960e01b815260040160405180910390fd5b600019828201016101008111156137d6576040516309bde33960e01b815260040160405180910390fd5b8060000361380357866000815181106137f1576137f16150c9565b602002602001015193505050506139d1565b6000816001600160401b0381111561381d5761381d613a93565b604051908082528060200260200182016040528015613846578160200160208202803683370190505b50905060008080805b858110156139705760006001821b8b8116036138aa5788851015613893578c5160018601958e918110613884576138846150c9565b602002602001015190506138cc565b8551600185019487918110613884576138846150c9565b8b5160018401938d9181106138c1576138c16150c9565b602002602001015190505b6000898610156138fc578d5160018701968f9181106138ed576138ed6150c9565b6020026020010151905061391e565b8651600186019588918110613913576139136150c9565b602002602001015190505b8285111561393f576040516309bde33960e01b815260040160405180910390fd5b61394982826139d8565b87848151811061395b5761395b6150c9565b6020908102919091010152505060010161384f565b50600185038214801561398257508683145b801561398d57508581145b6139aa576040516309bde33960e01b815260040160405180910390fd5b8360018603815181106139bf576139bf6150c9565b60200260200101519750505050505050505b9392505050565b60008183106139f0576139eb82846139f6565b610ac7565b610ac783835b60408051600160208201529081018390526060810182905260009060800161336e565b828054828255906000526020600020908101928215613a6e579160200282015b82811115613a6e57825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190613a39565b50613a7a929150613a7e565b5090565b5b80821115613a7a5760008155600101613a7f565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b0381118282101715613acb57613acb613a93565b60405290565b604051606081016001600160401b0381118282101715613acb57613acb613a93565b60405160a081016001600160401b0381118282101715613acb57613acb613a93565b60405160c081016001600160401b0381118282101715613acb57613acb613a93565b604080519081016001600160401b0381118282101715613acb57613acb613a93565b604051601f8201601f191681016001600160401b0381118282101715613b8157613b81613a93565b604052919050565b60006001600160401b03821115613ba257613ba2613a93565b5060051b60200190565b6001600160a01b038116811461051357600080fd5b80356001600160401b0381168114613bd857600080fd5b919050565b801515811461051357600080fd5b8035613bd881613bdd565b60006001600160401b03821115613c0f57613c0f613a93565b50601f01601f191660200190565b600082601f830112613c2e57600080fd5b8135613c41613c3c82613bf6565b613b59565b818152846020838601011115613c5657600080fd5b816020850160208301376000918101602001919091529392505050565b60006020808385031215613c8657600080fd5b82356001600160401b0380821115613c9d57600080fd5b818501915085601f830112613cb157600080fd5b8135613cbf613c3c82613b89565b81815260059190911b83018401908481019088831115613cde57600080fd5b8585015b83811015613d8457803585811115613cfa5760008081fd5b86016080818c03601f1901811315613d125760008081fd5b613d1a613aa9565b89830135613d2781613bac565b81526040613d36848201613bc1565b8b830152606080850135613d4981613bdd565b83830152928401359289841115613d6257600091508182fd5b613d708f8d86880101613c1d565b908301525085525050918601918601613ce2565b5098975050505050505050565b60005b83811015613dac578181015183820152602001613d94565b50506000910152565b60008151808452613dcd816020860160208601613d91565b601f01601f19169290920160200192915050565b602081526000610ac76020830184613db5565b8060608101831015610aca57600080fd5b60008083601f840112613e1757600080fd5b5081356001600160401b03811115613e2e57600080fd5b602083019150836020828501011115613e4657600080fd5b9250929050565b60008083601f840112613e5f57600080fd5b5081356001600160401b03811115613e7657600080fd5b6020830191508360208260051b8501011115613e4657600080fd5b60008060008060008060008060e0898b031215613ead57600080fd5b613eb78a8a613df4565b975060608901356001600160401b0380821115613ed357600080fd5b613edf8c838d01613e05565b909950975060808b0135915080821115613ef857600080fd5b613f048c838d01613e4d565b909750955060a08b0135915080821115613f1d57600080fd5b50613f2a8b828c01613e4d565b999c989b50969995989497949560c00135949350505050565b600080600060808486031215613f5857600080fd5b613f628585613df4565b925060608401356001600160401b03811115613f7d57600080fd5b613f8986828701613e05565b9497909650939450505050565b60008060408385031215613fa957600080fd5b613fb283613bc1565b9150613fc060208401613bc1565b90509250929050565b634e487b7160e01b600052602160045260246000fd5b60048110613fef57613fef613fc9565b9052565b60208101610aca8284613fdf565b8035613bd881613bac565b63ffffffff8116811461051357600080fd5b60006060828403121561403057600080fd5b614038613ad1565b823561404381613bac565b815260208301356140538161400c565b6020820152604083013561406681613bac565b60408201529392505050565b60006020828403121561408457600080fd5b81356001600160401b0381111561409a57600080fd5b820160a081850312156139d157600080fd5b803560ff81168114613bd857600080fd5b6000602082840312156140cf57600080fd5b610ac7826140ac565b60008151808452602080850194506020840160005b838110156141125781516001600160a01b0316875295820195908201906001016140ed565b509495945050505050565b60208152600082518051602084015260ff602082015116604084015260ff604082015116606084015260608101511515608084015250602083015160c060a084015261416c60e08401826140d8565b90506040840151601f198483030160c085015261418982826140d8565b95945050505050565b600080604083850312156141a557600080fd5b6141ae83613bc1565b946020939093013593505050565b600060a082840312156141ce57600080fd5b6141d6613af3565b9050813581526141e860208301613bc1565b60208201526141f960408301613bc1565b604082015261420a60608301613bc1565b606082015261421b60808301613bc1565b608082015292915050565b600082601f83011261423757600080fd5b81356020614247613c3c83613b89565b82815260059290921b8401810191818101908684111561426657600080fd5b8286015b848110156143605780356001600160401b038082111561428a5760008081fd5b9088019060a0828b03601f19018113156142a45760008081fd5b6142ac613af3565b87840135838111156142be5760008081fd5b6142cc8d8a83880101613c1d565b825250604080850135848111156142e35760008081fd5b6142f18e8b83890101613c1d565b8a840152506060808601358581111561430a5760008081fd5b6143188f8c838a0101613c1d565b8385015250608091508186013581840152508285013592508383111561433e5760008081fd5b61434c8d8a85880101613c1d565b90820152865250505091830191830161426a565b509695505050505050565b6000610140828403121561437e57600080fd5b614386613b15565b905061439283836141bc565b815260a08201356001600160401b03808211156143ae57600080fd5b6143ba85838601613c1d565b602084015260c08401359150808211156143d357600080fd5b6143df85838601613c1d565b60408401526143f060e08501614001565b6060840152610100840135608084015261012084013591508082111561441557600080fd5b5061442284828501614226565b60a08301525092915050565b60008060008060006060868803121561444657600080fd5b85356001600160401b038082111561445d57600080fd5b61446989838a0161436b565b9650602088013591508082111561447f57600080fd5b61448b89838a01613e4d565b909650945060408801359150808211156144a457600080fd5b506144b188828901613e4d565b969995985093965092949392505050565b600082601f8301126144d357600080fd5b813560206144e3613c3c83613b89565b82815260059290921b8401810191818101908684111561450257600080fd5b8286015b848110156143605780356001600160401b038111156145255760008081fd5b6145338986838b010161436b565b845250918301918301614506565b600082601f83011261455257600080fd5b81356020614562613c3c83613b89565b82815260059290921b8401810191818101908684111561458157600080fd5b8286015b848110156143605780356001600160401b03808211156145a457600080fd5b818901915089603f8301126145b857600080fd5b858201356145c8613c3c82613b89565b81815260059190911b830160400190878101908c8311156145e857600080fd5b604085015b838110156146215780358581111561460457600080fd5b6146138f6040838a0101613c1d565b8452509189019189016145ed565b50875250505092840192508301614585565b600082601f83011261464457600080fd5b81356020614654613c3c83613b89565b8083825260208201915060208460051b87010193508684111561467657600080fd5b602086015b84811015614360578035835291830191830161467b565b600082601f8301126146a357600080fd5b813560206146b3613c3c83613b89565b82815260059290921b840181019181810190868411156146d257600080fd5b8286015b848110156143605780356001600160401b03808211156146f65760008081fd5b9088019060a0828b03601f19018113156147105760008081fd5b614718613af3565b614723888501613bc1565b8152604080850135848111156147395760008081fd5b6147478e8b838901016144c2565b8a84015250606080860135858111156147605760008081fd5b61476e8f8c838a0101614541565b83850152506080915081860135858111156147895760008081fd5b6147978f8c838a0101614633565b91840191909152509190930135908301525083529183019183016146d6565b600080604083850312156147c957600080fd5b6001600160401b03833511156147de57600080fd5b6147eb8484358501614692565b91506001600160401b036020840135111561480557600080fd5b6020830135830184601f82011261481b57600080fd5b614828613c3c8235613b89565b81358082526020808301929160051b84010187101561484657600080fd5b602083015b6020843560051b8501018110156149ef576001600160401b038135111561487157600080fd5b87603f82358601011261488357600080fd5b614896613c3c6020833587010135613b89565b81358501602081810135808452908301929160059190911b016040018a10156148be57600080fd5b604083358701015b83358701602081013560051b016040018110156149df576001600160401b03813511156148f257600080fd5b833587018135016040818d03603f1901121561490d57600080fd5b614915613b37565b604082013581526001600160401b036060830135111561493457600080fd5b8c605f60608401358401011261494957600080fd5b6040606083013583010135614960613c3c82613b89565b808282526020820191508f60608460051b606088013588010101111561498557600080fd5b6060808601358601015b60608460051b6060880135880101018110156149bf576149af813561400c565b803583526020928301920161498f565b5080602085015250505080855250506020830192506020810190506148c6565b508452506020928301920161484b565b508093505050509250929050565b600060208284031215614a0f57600080fd5b610ac782613bc1565b602081526001600160a01b0382511660208201526020820151151560408201526001600160401b036040830151166060820152600060608301516080808401526133c160a0840182613db5565b600060208284031215614a7757600080fd5b81356139d181613bac565b600082601f830112614a9357600080fd5b81356020614aa3613c3c83613b89565b8083825260208201915060208460051b870101935086841115614ac557600080fd5b602086015b84811015614360578035614add81613bac565b8352918301918301614aca565b60006020808385031215614afd57600080fd5b82356001600160401b0380821115614b1457600080fd5b818501915085601f830112614b2857600080fd5b8135614b36613c3c82613b89565b81815260059190911b83018401908481019088831115614b5557600080fd5b8585015b83811015613d8457803585811115614b7057600080fd5b860160c0818c03601f19011215614b875760008081fd5b614b8f613b15565b8882013581526040614ba28184016140ac565b8a8301526060614bb38185016140ac565b8284015260809150614bc6828501613beb565b9083015260a08381013589811115614bde5760008081fd5b614bec8f8d83880101614a82565b838501525060c0840135915088821115614c065760008081fd5b614c148e8c84870101614a82565b9083015250845250918601918601614b59565b80356001600160e01b0381168114613bd857600080fd5b600082601f830112614c4f57600080fd5b81356020614c5f613c3c83613b89565b82815260069290921b84018101918181019086841115614c7e57600080fd5b8286015b848110156143605760408189031215614c9b5760008081fd5b614ca3613b37565b614cac82613bc1565b8152614cb9858301614c27565b81860152835291830191604001614c82565b600082601f830112614cdc57600080fd5b81356020614cec613c3c83613b89565b82815260059290921b84018101918181019086841115614d0b57600080fd5b8286015b848110156143605780356001600160401b0380821115614d2f5760008081fd5b9088019060a0828b03601f1901811315614d495760008081fd5b614d51613af3565b614d5c888501613bc1565b815260408085013584811115614d725760008081fd5b614d808e8b83890101613c1d565b8a8401525060609350614d94848601613bc1565b908201526080614da5858201613bc1565b93820193909352920135908201528352918301918301614d0f565b600082601f830112614dd157600080fd5b81356020614de1613c3c83613b89565b82815260069290921b84018101918181019086841115614e0057600080fd5b8286015b848110156143605760408189031215614e1d5760008081fd5b614e25613b37565b813581528482013585820152835291830191604001614e04565b60006020808385031215614e5257600080fd5b82356001600160401b0380821115614e6957600080fd5b9084019060608287031215614e7d57600080fd5b614e85613ad1565b823582811115614e9457600080fd5b83016040818903811315614ea757600080fd5b614eaf613b37565b823585811115614ebe57600080fd5b8301601f81018b13614ecf57600080fd5b8035614edd613c3c82613b89565b81815260069190911b8201890190898101908d831115614efc57600080fd5b928a01925b82841015614f4c5785848f031215614f195760008081fd5b614f21613b37565b8435614f2c81613bac565b8152614f39858d01614c27565b818d0152825292850192908a0190614f01565b845250505082870135915084821115614f6457600080fd5b614f708a838501614c3e565b81880152835250508284013582811115614f8957600080fd5b614f9588828601614ccb565b85830152506040830135935081841115614fae57600080fd5b614fba87858501614dc0565b60408201529695505050505050565b600082825180855260208086019550808260051b84010181860160005b8481101561505a57601f19868403018952815160a06001600160401b0380835116865286830151828888015261501e83880182613db5565b60408581015184169089015260608086015190931692880192909252506080928301519290950191909152509783019790830190600101614fe6565b5090979650505050505050565b6000604080835261507b6040840186614fc9565b83810360208581019190915285518083528682019282019060005b818110156150bb57845180518452840151848401529383019391850191600101615096565b509098975050505050505050565b634e487b7160e01b600052603260045260246000fd5b805160408084528151848201819052600092602091908201906060870190855b8181101561513657835180516001600160a01b031684528501516001600160e01b03168584015292840192918501916001016150ff565b50508583015187820388850152805180835290840192506000918401905b8083101561518f57835180516001600160401b031683528501516001600160e01b031685830152928401926001929092019190850190615154565b50979650505050505050565b602081526000610ac760208301846150df565b6000602082840312156151c057600080fd5b81516139d181613bdd565b600181811c908216806151df57607f821691505b6020821081036151ff57634e487b7160e01b600052602260045260246000fd5b50919050565b6000808354615213816151cb565b6001828116801561522b57600181146152405761526f565b60ff198416875282151583028701945061526f565b8760005260208060002060005b858110156152665781548a82015290840190820161524d565b50505082870194505b50929695505050505050565b60008154615288816151cb565b8085526020600183811680156152a557600181146152bf576152ed565b60ff1985168884015283151560051b8801830195506152ed565b866000528260002060005b858110156152e55781548a82018601529083019084016152ca565b890184019650505b505050505092915050565b60408152600061530b6040830185613db5565b8281036020840152614189818561527b565b634e487b7160e01b600052601160045260246000fd5b6001600160401b038181168382160190808211156153535761535361531d565b5092915050565b60408152600061536d6040830185614fc9565b828103602084015261418981856150df565b60006020828403121561539157600080fd5b81356001600160401b038111156153a757600080fd5b6133c184828501614692565b81810381811115610aca57610aca61531d565b634e487b7160e01b600052601260045260246000fd5b60006001600160401b03808416806153f6576153f66153c6565b92169190910692915050565b8082028115828204841417610aca57610aca61531d565b80518252600060206001600160401b0381840151168185015260408084015160a0604087015261544c60a0870182613db5565b9050606085015186820360608801526154658282613db5565b608087810151898303918a01919091528051808352908601935060009250908501905b8083101561518f57835180516001600160a01b0316835286015186830152928501926001929092019190840190615488565b602081526000610ac76020830184615419565b6080815260006154e06080830187615419565b61ffff9590951660208301525060408101929092526001600160a01b0316606090910152919050565b60008060006060848603121561551e57600080fd5b835161552981613bdd565b60208501519093506001600160401b0381111561554557600080fd5b8401601f8101861361555657600080fd5b8051615564613c3c82613bf6565b81815287602083850101111561557957600080fd5b61558a826020830160208601613d91565b809450505050604084015190509250925092565b6000602082840312156155b057600080fd5b81516139d18161400c565b601f821115611272576000816000526020600020601f850160051c810160208610156155e45750805b601f850160051c820191505b81811015615603578281556001016155f0565b505050505050565b81516001600160401b0381111561562457615624613a93565b6156388161563284546151cb565b846155bb565b602080601f83116001811461566d57600084156156555750858301515b600019600386901b1c1916600185901b178555615603565b600085815260208120601f198616915b8281101561569c5788860151825594840194600190910190840161567d565b50858210156156ba5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60208152600082546001600160a01b038116602084015260ff8160a01c16151560408401526001600160401b038160a81c16606084015250608080830152610ac760a083016001850161527b565b80820180821115610aca57610aca61531d565b60ff8181168382160190811115610aca57610aca61531d565b8183823760009101908152919050565b828152606082602083013760800192915050565b60006001600160401b0380841680615782576157826153c6565b92169190910492915050565b6000602082840312156157a057600080fd5b81356139d18161400c565b6000808335601e198436030181126157c257600080fd5b8301803591506001600160401b038211156157dc57600080fd5b602001915036819003821315613e4657600080fd5b602081016006831061580557615805613fc9565b91905290565b60ff81811683821602908116908181146153535761535361531d565b600060a0820160ff881683526020878185015260a0604085015281875480845260c0860191508860005282600020935060005b8181101561587f5784546001600160a01b03168352600194850194928401920161585a565b50508481036060860152865180825290820192508187019060005b818110156158bf5782516001600160a01b03168552938301939183019160010161589a565b50505060ff851660808501525090505b9695505050505050565b60006001600160401b038086168352808516602084015250606060408301526141896060830184613db5565b8281526040602082015260006133c16040830184613db5565b6001600160401b03848116825283166020820152606081016133c16040830184613fdf565b8481526159536020820185613fdf565b6080604082015260006159696080830185613db5565b905082606083015295945050505050565b60006020828403121561598c57600080fd5b81516139d181613bac565b60208152600082516101008060208501526159b6610120850183613db5565b915060208501516159d260408601826001600160401b03169052565b5060408501516001600160a01b038116606086015250606085015160808501526080850151615a0c60a08601826001600160a01b03169052565b5060a0850151601f19808685030160c0870152615a298483613db5565b935060c08701519150808685030160e0870152615a468483613db5565b935060e08701519150808685030183870152506158cf8382613db5565b600060208284031215615a7557600080fd5b5051919050565b600082825180855260208086019550808260051b84010181860160005b8481101561505a57601f19868403018952815160a08151818652615abf82870182613db5565b9150508582015185820387870152615ad78282613db5565b91505060408083015186830382880152615af18382613db5565b92505050606080830151818701525060808083015192508582038187015250615b1a8183613db5565b9a86019a9450505090830190600101615a99565b602081526000610ac76020830184615a7c565b60008282518085526020808601955060208260051b8401016020860160005b8481101561505a57601f19868403018952615b7c838351613db5565b98840198925090830190600101615b60565b60008151808452602080850194506020840160005b8381101561411257815163ffffffff1687529582019590820190600101615ba3565b60608152600084518051606084015260208101516001600160401b0380821660808601528060408401511660a08601528060608401511660c08601528060808401511660e0860152505050602085015161014080610100850152615c2d6101a0850183613db5565b91506040870151605f198086850301610120870152615c4c8483613db5565b935060608901519150615c69838701836001600160a01b03169052565b608089015161016087015260a0890151925080868503016101808701525050615c928282615a7c565b9150508281036020840152615ca78186615b41565b905082810360408401526158cf8185615b8e56fea164736f6c6343000818000a", } var OffRampABI = OffRampMetaData.ABI diff --git a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt index cbd6b1cd5a..66838f0141 100644 --- a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -4,7 +4,7 @@ burn_mint_token_pool: ../../../contracts/solc/v0.8.24/BurnMintTokenPool/BurnMint burn_mint_token_pool_and_proxy: ../../../contracts/solc/v0.8.24/BurnMintTokenPoolAndProxy/BurnMintTokenPoolAndProxy.abi ../../../contracts/solc/v0.8.24/BurnMintTokenPoolAndProxy/BurnMintTokenPoolAndProxy.bin 717c079d5d13300cf3c3ee871c6e5bf9af904411f204fb081a9f3b263cca1391 burn_with_from_mint_token_pool: ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.abi ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.bin 6333d0314d0bd29e75ea5e05fe62a4516ade0c6db91c30b6f93645035db52ed8 burn_with_from_mint_token_pool_and_proxy: ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPoolAndProxy/BurnWithFromMintTokenPoolAndProxy.abi ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPoolAndProxy/BurnWithFromMintTokenPoolAndProxy.bin 08ed1235dda921ce8841b26aa18d0c0f36db4884779dd7670857159801b6d597 -ccip_config: ../../../contracts/solc/v0.8.24/CCIPConfig/CCIPConfig.abi ../../../contracts/solc/v0.8.24/CCIPConfig/CCIPConfig.bin 93e3bceec6fff366e876f636001253f1d9c60b43e2c95484674f7ae245b302e6 +ccip_config: ../../../contracts/solc/v0.8.24/CCIPConfig/CCIPConfig.abi ../../../contracts/solc/v0.8.24/CCIPConfig/CCIPConfig.bin f67d4a98804a9534a6554da3a57779632d55ad76db5ecc16ade74774769cdd69 ccip_encoding_utils: ../../../contracts/solc/v0.8.24/CCIPEncodingUtils/CCIPEncodingUtils.abi ../../../contracts/solc/v0.8.24/CCIPEncodingUtils/CCIPEncodingUtils.bin 1d48b49fc0668c4f8c5e19a208cf4cae124a9a5c361e7900fbc35b97a62dd1bc ccip_reader_tester: ../../../contracts/solc/v0.8.24/CCIPReaderTester/CCIPReaderTester.abi ../../../contracts/solc/v0.8.24/CCIPReaderTester/CCIPReaderTester.bin 481d461f14c98308cd788b64be1151e92bac6f95ddd55eefc926296454316f13 commit_store: ../../../contracts/solc/v0.8.24/CommitStore/CommitStore.abi ../../../contracts/solc/v0.8.24/CommitStore/CommitStore.bin 274d87db70b643e00ab0a7e7845bb4b791f3b613bfc87708d33fc5a8369e2a41 @@ -21,10 +21,10 @@ mock_usdc_token_messenger: ../../../contracts/solc/v0.8.24/MockE2EUSDCTokenMesse mock_usdc_token_transmitter: ../../../contracts/solc/v0.8.24/MockE2EUSDCTransmitter/MockE2EUSDCTransmitter.abi ../../../contracts/solc/v0.8.24/MockE2EUSDCTransmitter/MockE2EUSDCTransmitter.bin be0dbc3e475741ea0b7a54ec2b935a321b428baa9f4ce18180a87fb38bb87de2 mock_v3_aggregator_contract: ../../../contracts/solc/v0.8.24/MockV3Aggregator/MockV3Aggregator.abi ../../../contracts/solc/v0.8.24/MockV3Aggregator/MockV3Aggregator.bin 518e19efa2ff52b0fefd8e597b05765317ee7638189bfe34ca43de2f6599faf4 multi_aggregate_rate_limiter: ../../../contracts/solc/v0.8.24/MultiAggregateRateLimiter/MultiAggregateRateLimiter.abi ../../../contracts/solc/v0.8.24/MultiAggregateRateLimiter/MultiAggregateRateLimiter.bin 0b541232e49727e947dc164eadf35963c66e67576f21baa0ecaa06a8833148ed -multi_ocr3_helper: ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Helper.abi ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Helper.bin 6b56e0114a4d50797d30a34aecc2641ef340451d0c3fcb9d729bba4df2435122 +multi_ocr3_helper: ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Helper.abi ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Helper.bin 04b6b261dd71925670bf4d904aaf7bf08543452009feefb88e07d4c49d12e969 nonce_manager: ../../../contracts/solc/v0.8.24/NonceManager/NonceManager.abi ../../../contracts/solc/v0.8.24/NonceManager/NonceManager.bin 6f64e1083b356c06ee66b9138e398b9c97a4cd3e8c9ec38cf3010cebc79af536 -ocr3_config_encoder: ../../../contracts/solc/v0.8.24/IOCR3ConfigEncoder/IOCR3ConfigEncoder.abi ../../../contracts/solc/v0.8.24/IOCR3ConfigEncoder/IOCR3ConfigEncoder.bin 9254b35a86f00fde7b7193a033ca58f6521a66e87b9cf9da6ce5660082e79f5d -offramp: ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.abi ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.bin 46914fd423a8d3377ebe65ff8567d7e3a76adfba50204c5468cd71ef663c614e +ocr3_config_encoder: ../../../contracts/solc/v0.8.24/IOCR3ConfigEncoder/IOCR3ConfigEncoder.abi ../../../contracts/solc/v0.8.24/IOCR3ConfigEncoder/IOCR3ConfigEncoder.bin d507c3ac70a7d1033b75151c1e5b854b41aaee164dfaa3e5477de400db1aa1f7 +offramp: ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.abi ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.bin abc5cb0a9c3194aa1256e953c59ae86b416340631fc2594032babd138552df1e onramp: ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.abi ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.bin 57a053c78e7f91fdde84854609ad110c4db5b65142a0aab2c884c5c008e0873a ping_pong_demo: ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.abi ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.bin c1c2f8a65c7ffd971899cae7fe62f2da57d09e936151e2b92163c4bebe699d6b price_registry: ../../../contracts/solc/v0.8.24/PriceRegistry/PriceRegistry.abi ../../../contracts/solc/v0.8.24/PriceRegistry/PriceRegistry.bin e7781d600c1bb7aa4620106af7f6e146a109b97f4cb6a7d06c9e15773340ecb2 From ef3e36607a0b8899e4ad32bbe10bcbc128d82de3 Mon Sep 17 00:00:00 2001 From: Suryansh <39276431+0xsuryansh@users.noreply.github.com> Date: Sat, 14 Sep 2024 01:41:36 +0530 Subject: [PATCH 097/115] Split RampTokenAmount into EVM2AnyTokenTransfer and Any2EVMTokenTransfer (#1435) --- contracts/gas-snapshots/ccip.gas-snapshot | 439 +++++++++--------- contracts/src/v0.8/ccip/FeeQuoter.sol | 18 +- .../src/v0.8/ccip/interfaces/IFeeQuoter.sol | 4 +- .../src/v0.8/ccip/libraries/Internal.sol | 50 +- contracts/src/v0.8/ccip/offRamp/OffRamp.sol | 14 +- contracts/src/v0.8/ccip/onRamp/OnRamp.sol | 10 +- ...mpsEnd2End.sol => MultiRampsEnd2End.t.sol} | 12 +- .../v0.8/ccip/test/feeQuoter/FeeQuoter.t.sol | 63 +-- .../ccip/test/feeQuoter/FeeQuoterSetup.t.sol | 12 +- .../v0.8/ccip/test/helpers/MessageHasher.sol | 10 +- .../v0.8/ccip/test/helpers/OffRampHelper.sol | 4 +- .../src/v0.8/ccip/test/offRamp/OffRamp.t.sol | 114 ++--- .../v0.8/ccip/test/offRamp/OffRampSetup.t.sol | 25 +- .../ccip_reader_tester/ccip_reader_tester.go | 24 +- .../ccip/generated/fee_quoter/fee_quoter.go | 34 +- .../message_hasher/message_hasher.go | 68 ++- .../ccip/generated/offramp/offramp.go | 22 +- .../ccip/generated/onramp/onramp.go | 24 +- .../generated/report_codec/report_codec.go | 24 +- ...rapper-dependency-versions-do-not-edit.txt | 12 +- .../ccip/mocks/fee_quoter_interface.go | 30 +- 21 files changed, 531 insertions(+), 482 deletions(-) rename contracts/src/v0.8/ccip/test/e2e/{MultiRampsEnd2End.sol => MultiRampsEnd2End.t.sol} (94%) diff --git a/contracts/gas-snapshots/ccip.gas-snapshot b/contracts/gas-snapshots/ccip.gas-snapshot index 6c62f81495..c3f52691d9 100644 --- a/contracts/gas-snapshots/ccip.gas-snapshot +++ b/contracts/gas-snapshots/ccip.gas-snapshot @@ -255,17 +255,17 @@ EVM2EVMOnRamp_getFee:test_GetFeeOfZeroForTokenMessage_Success() (gas: 80393) EVM2EVMOnRamp_getFee:test_HighGasMessage_Success() (gas: 230745) EVM2EVMOnRamp_getFee:test_MessageGasLimitTooHigh_Revert() (gas: 16943) EVM2EVMOnRamp_getFee:test_MessageTooLarge_Revert() (gas: 95505) -EVM2EVMOnRamp_getFee:test_MessageWithDataAndTokenTransfer_Success() (gas: 153881) +EVM2EVMOnRamp_getFee:test_MessageWithDataAndTokenTransfer_Success() (gas: 154013) EVM2EVMOnRamp_getFee:test_NotAFeeToken_Revert() (gas: 24323) -EVM2EVMOnRamp_getFee:test_SingleTokenMessage_Success() (gas: 114699) +EVM2EVMOnRamp_getFee:test_SingleTokenMessage_Success() (gas: 114743) EVM2EVMOnRamp_getFee:test_TooManyTokens_Revert() (gas: 20142) EVM2EVMOnRamp_getFee:test_ZeroDataAvailabilityMultiplier_Success() (gas: 63070) EVM2EVMOnRamp_getSupportedTokens:test_GetSupportedTokens_Revert() (gas: 10532) EVM2EVMOnRamp_getTokenPool:test_GetTokenPool_Success() (gas: 35297) -EVM2EVMOnRamp_getTokenTransferCost:test_CustomTokenBpsFee_Success() (gas: 43196) +EVM2EVMOnRamp_getTokenTransferCost:test_CustomTokenBpsFee_Success() (gas: 43218) EVM2EVMOnRamp_getTokenTransferCost:test_FeeTokenBpsFee_Success() (gas: 33280) EVM2EVMOnRamp_getTokenTransferCost:test_LargeTokenTransferChargesMaxFeeAndGas_Success() (gas: 28551) -EVM2EVMOnRamp_getTokenTransferCost:test_MixedTokenTransferFee_Success() (gas: 122558) +EVM2EVMOnRamp_getTokenTransferCost:test_MixedTokenTransferFee_Success() (gas: 122690) EVM2EVMOnRamp_getTokenTransferCost:test_NoTokenTransferChargesZeroFee_Success() (gas: 15403) EVM2EVMOnRamp_getTokenTransferCost:test_SmallTokenTransferChargesMinFeeAndGas_Success() (gas: 28359) EVM2EVMOnRamp_getTokenTransferCost:test_UnsupportedToken_Revert() (gas: 21353) @@ -332,94 +332,94 @@ FeeQuoter_applyDestChainConfigUpdates:test_InvalidDestChainConfigDestChainSelect FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesDefaultTxGasLimitEqZero_Revert() (gas: 16630) FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesDefaultTxGasLimitGtMaxPerMessageGasLimit_Revert() (gas: 40326) FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdatesZeroIntput_Success() (gas: 12483) -FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdates_Success() (gas: 137509) -FeeQuoter_applyFeeTokensUpdates:test_ApplyFeeTokensUpdates_Success() (gas: 80556) -FeeQuoter_applyFeeTokensUpdates:test_OnlyCallableByOwner_Revert() (gas: 12752) +FeeQuoter_applyDestChainConfigUpdates:test_applyDestChainConfigUpdates_Success() (gas: 137553) +FeeQuoter_applyFeeTokensUpdates:test_ApplyFeeTokensUpdates_Success() (gas: 80348) +FeeQuoter_applyFeeTokensUpdates:test_OnlyCallableByOwner_Revert() (gas: 12687) FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_OnlyCallableByOwnerOrAdmin_Revert() (gas: 11547) FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesMultipleTokens_Success() (gas: 54684) FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesSingleToken_Success() (gas: 45130) FeeQuoter_applyPremiumMultiplierWeiPerEthUpdates:test_applyPremiumMultiplierWeiPerEthUpdatesZeroInput() (gas: 12332) -FeeQuoter_applyTokenTransferFeeConfigUpdates:test_ApplyTokenTransferFeeConfig_Success() (gas: 87679) -FeeQuoter_applyTokenTransferFeeConfigUpdates:test_ApplyTokenTransferFeeZeroInput() (gas: 13256) -FeeQuoter_applyTokenTransferFeeConfigUpdates:test_InvalidDestBytesOverhead_Revert() (gas: 17301) -FeeQuoter_applyTokenTransferFeeConfigUpdates:test_OnlyCallableByOwnerOrAdmin_Revert() (gas: 12353) +FeeQuoter_applyTokenTransferFeeConfigUpdates:test_ApplyTokenTransferFeeConfig_Success() (gas: 87721) +FeeQuoter_applyTokenTransferFeeConfigUpdates:test_ApplyTokenTransferFeeZeroInput() (gas: 13233) +FeeQuoter_applyTokenTransferFeeConfigUpdates:test_InvalidDestBytesOverhead_Revert() (gas: 17278) +FeeQuoter_applyTokenTransferFeeConfigUpdates:test_OnlyCallableByOwnerOrAdmin_Revert() (gas: 12330) FeeQuoter_constructor:test_InvalidLinkTokenEqZeroAddress_Revert() (gas: 106501) FeeQuoter_constructor:test_InvalidMaxFeeJuelsPerMsg_Revert() (gas: 110851) FeeQuoter_constructor:test_InvalidStalenessThreshold_Revert() (gas: 110904) -FeeQuoter_constructor:test_Setup_Success() (gas: 4972856) +FeeQuoter_constructor:test_Setup_Success() (gas: 4972944) FeeQuoter_convertTokenAmount:test_ConvertTokenAmount_Success() (gas: 68383) FeeQuoter_convertTokenAmount:test_LinkTokenNotSupported_Revert() (gas: 29076) -FeeQuoter_getDataAvailabilityCost:test_EmptyMessageCalculatesDataAvailabilityCost_Success() (gas: 94737) +FeeQuoter_getDataAvailabilityCost:test_EmptyMessageCalculatesDataAvailabilityCost_Success() (gas: 94781) FeeQuoter_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCostUnsupportedDestChainSelector_Success() (gas: 14670) -FeeQuoter_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCost_Success() (gas: 20528) +FeeQuoter_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCost_Success() (gas: 20550) FeeQuoter_getTokenAndGasPrices:test_GetFeeTokenAndGasPrices_Success() (gas: 68313) FeeQuoter_getTokenAndGasPrices:test_StaleGasPrice_Revert() (gas: 16892) FeeQuoter_getTokenAndGasPrices:test_UnsupportedChain_Revert() (gas: 16188) FeeQuoter_getTokenAndGasPrices:test_ZeroGasPrice_Success() (gas: 43682) FeeQuoter_getTokenPrice:test_GetTokenPriceFromFeed_Success() (gas: 66273) -FeeQuoter_getTokenPrices:test_GetTokenPrices_Success() (gas: 78300) -FeeQuoter_getTokenTransferCost:test_CustomTokenBpsFee_Success() (gas: 39200) -FeeQuoter_getTokenTransferCost:test_FeeTokenBpsFee_Success() (gas: 34836) -FeeQuoter_getTokenTransferCost:test_LargeTokenTransferChargesMaxFeeAndGas_Success() (gas: 27910) -FeeQuoter_getTokenTransferCost:test_MixedTokenTransferFee_Success() (gas: 97315) -FeeQuoter_getTokenTransferCost:test_NoTokenTransferChargesZeroFee_Success() (gas: 20446) -FeeQuoter_getTokenTransferCost:test_SmallTokenTransferChargesMinFeeAndGas_Success() (gas: 27785) -FeeQuoter_getTokenTransferCost:test_ZeroAmountTokenTransferChargesMinFeeAndGas_Success() (gas: 27741) -FeeQuoter_getTokenTransferCost:test_ZeroFeeConfigChargesMinFee_Success() (gas: 40377) -FeeQuoter_getTokenTransferCost:test_getTokenTransferCost_selfServeUsesDefaults_Success() (gas: 29459) +FeeQuoter_getTokenPrices:test_GetTokenPrices_Success() (gas: 78322) +FeeQuoter_getTokenTransferCost:test_CustomTokenBpsFee_Success() (gas: 39244) +FeeQuoter_getTokenTransferCost:test_FeeTokenBpsFee_Success() (gas: 34880) +FeeQuoter_getTokenTransferCost:test_LargeTokenTransferChargesMaxFeeAndGas_Success() (gas: 27954) +FeeQuoter_getTokenTransferCost:test_MixedTokenTransferFee_Success() (gas: 97513) +FeeQuoter_getTokenTransferCost:test_NoTokenTransferChargesZeroFee_Success() (gas: 20468) +FeeQuoter_getTokenTransferCost:test_SmallTokenTransferChargesMinFeeAndGas_Success() (gas: 27829) +FeeQuoter_getTokenTransferCost:test_ZeroAmountTokenTransferChargesMinFeeAndGas_Success() (gas: 27785) +FeeQuoter_getTokenTransferCost:test_ZeroFeeConfigChargesMinFee_Success() (gas: 40376) +FeeQuoter_getTokenTransferCost:test_getTokenTransferCost_selfServeUsesDefaults_Success() (gas: 29503) FeeQuoter_getValidatedFee:test_DestinationChainNotEnabled_Revert() (gas: 18315) -FeeQuoter_getValidatedFee:test_EmptyMessage_Success() (gas: 82303) +FeeQuoter_getValidatedFee:test_EmptyMessage_Success() (gas: 82347) FeeQuoter_getValidatedFee:test_EnforceOutOfOrder_Revert() (gas: 52638) -FeeQuoter_getValidatedFee:test_HighGasMessage_Success() (gas: 238721) +FeeQuoter_getValidatedFee:test_HighGasMessage_Success() (gas: 238765) FeeQuoter_getValidatedFee:test_InvalidEVMAddress_Revert() (gas: 22555) FeeQuoter_getValidatedFee:test_MessageGasLimitTooHigh_Revert() (gas: 29847) FeeQuoter_getValidatedFee:test_MessageTooLarge_Revert() (gas: 100292) -FeeQuoter_getValidatedFee:test_MessageWithDataAndTokenTransfer_Success() (gas: 141631) +FeeQuoter_getValidatedFee:test_MessageWithDataAndTokenTransfer_Success() (gas: 141895) FeeQuoter_getValidatedFee:test_NotAFeeToken_Revert() (gas: 21172) -FeeQuoter_getValidatedFee:test_SingleTokenMessage_Success() (gas: 113136) +FeeQuoter_getValidatedFee:test_SingleTokenMessage_Success() (gas: 113312) FeeQuoter_getValidatedFee:test_TooManyTokens_Revert() (gas: 22691) -FeeQuoter_getValidatedFee:test_ZeroDataAvailabilityMultiplier_Success() (gas: 62692) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Above18Decimals_Success() (gas: 1973885) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Below18Decimals_Success() (gas: 1973843) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt0Decimals_Success() (gas: 1953962) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt18Decimals_Success() (gas: 1973617) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFlippedDecimals_Success() (gas: 1973821) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedMaxInt224Value_Success() (gas: 1973633) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedOverStalenessPeriod_Success() (gas: 64588) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeed_Success() (gas: 64468) -FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPrice_Success() (gas: 58872) -FeeQuoter_getValidatedTokenPrice:test_OverflowFeedPrice_Revert() (gas: 1973330) -FeeQuoter_getValidatedTokenPrice:test_StaleFeeToken_Success() (gas: 61742) -FeeQuoter_getValidatedTokenPrice:test_TokenNotSupportedFeed_Revert() (gas: 116473) -FeeQuoter_getValidatedTokenPrice:test_TokenNotSupported_Revert() (gas: 14015) -FeeQuoter_getValidatedTokenPrice:test_UnderflowFeedPrice_Revert() (gas: 1972007) -FeeQuoter_onReport:test_OnReport_StaleUpdate_Revert() (gas: 43587) -FeeQuoter_onReport:test_onReport_InvalidForwarder_Reverts() (gas: 23470) -FeeQuoter_onReport:test_onReport_Success() (gas: 80072) -FeeQuoter_onReport:test_onReport_UnsupportedToken_Reverts() (gas: 26838) -FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsDefault_Success() (gas: 17262) -FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsEnforceOutOfOrder_Revert() (gas: 21406) -FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsGasLimitTooHigh_Revert() (gas: 18494) -FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsInvalidExtraArgsTag_Revert() (gas: 18012) -FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsV1_Success() (gas: 18368) -FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsV2_Success() (gas: 18490) -FeeQuoter_processMessageArgs:test_processMessageArgs_InvalidEVMAddressDestToken_Revert() (gas: 44991) -FeeQuoter_processMessageArgs:test_processMessageArgs_InvalidExtraArgs_Revert() (gas: 19936) -FeeQuoter_processMessageArgs:test_processMessageArgs_MalformedEVMExtraArgs_Revert() (gas: 20355) -FeeQuoter_processMessageArgs:test_processMessageArgs_MessageFeeTooHigh_Revert() (gas: 17937) -FeeQuoter_processMessageArgs:test_processMessageArgs_SourceTokenDataTooLarge_Revert() (gas: 124099) -FeeQuoter_processMessageArgs:test_processMessageArgs_TokenAmountArraysMismatching_Revert() (gas: 42235) -FeeQuoter_processMessageArgs:test_processMessageArgs_WitEVMExtraArgsV2_Success() (gas: 28540) -FeeQuoter_processMessageArgs:test_processMessageArgs_WithConvertedTokenAmount_Success() (gas: 29971) -FeeQuoter_processMessageArgs:test_processMessageArgs_WithCorrectPoolReturnData_Success() (gas: 76711) -FeeQuoter_processMessageArgs:test_processMessageArgs_WithEVMExtraArgsV1_Success() (gas: 28138) -FeeQuoter_processMessageArgs:test_processMessageArgs_WithEmptyEVMExtraArgs_Success() (gas: 26009) -FeeQuoter_processMessageArgs:test_processMessageArgs_WithLinkTokenAmount_Success() (gas: 19545) +FeeQuoter_getValidatedFee:test_ZeroDataAvailabilityMultiplier_Success() (gas: 62714) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Above18Decimals_Success() (gas: 1973907) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Below18Decimals_Success() (gas: 1973865) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt0Decimals_Success() (gas: 1953984) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFeedAt18Decimals_Success() (gas: 1973639) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedFlippedDecimals_Success() (gas: 1973843) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedMaxInt224Value_Success() (gas: 1973655) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedOverStalenessPeriod_Success() (gas: 64610) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeed_Success() (gas: 64490) +FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPrice_Success() (gas: 58894) +FeeQuoter_getValidatedTokenPrice:test_OverflowFeedPrice_Revert() (gas: 1973352) +FeeQuoter_getValidatedTokenPrice:test_StaleFeeToken_Success() (gas: 61764) +FeeQuoter_getValidatedTokenPrice:test_TokenNotSupportedFeed_Revert() (gas: 116495) +FeeQuoter_getValidatedTokenPrice:test_TokenNotSupported_Revert() (gas: 14037) +FeeQuoter_getValidatedTokenPrice:test_UnderflowFeedPrice_Revert() (gas: 1972029) +FeeQuoter_onReport:test_OnReport_StaleUpdate_Revert() (gas: 43631) +FeeQuoter_onReport:test_onReport_InvalidForwarder_Reverts() (gas: 23492) +FeeQuoter_onReport:test_onReport_Success() (gas: 80094) +FeeQuoter_onReport:test_onReport_UnsupportedToken_Reverts() (gas: 26860) +FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsDefault_Success() (gas: 17284) +FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsEnforceOutOfOrder_Revert() (gas: 21428) +FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsGasLimitTooHigh_Revert() (gas: 18516) +FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsInvalidExtraArgsTag_Revert() (gas: 18034) +FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsV1_Success() (gas: 18390) +FeeQuoter_parseEVMExtraArgsFromBytes:test_EVMExtraArgsV2_Success() (gas: 18512) +FeeQuoter_processMessageArgs:test_processMessageArgs_InvalidEVMAddressDestToken_Revert() (gas: 44703) +FeeQuoter_processMessageArgs:test_processMessageArgs_InvalidExtraArgs_Revert() (gas: 19914) +FeeQuoter_processMessageArgs:test_processMessageArgs_MalformedEVMExtraArgs_Revert() (gas: 20333) +FeeQuoter_processMessageArgs:test_processMessageArgs_MessageFeeTooHigh_Revert() (gas: 17904) +FeeQuoter_processMessageArgs:test_processMessageArgs_SourceTokenDataTooLarge_Revert() (gas: 122709) +FeeQuoter_processMessageArgs:test_processMessageArgs_TokenAmountArraysMismatching_Revert() (gas: 42032) +FeeQuoter_processMessageArgs:test_processMessageArgs_WitEVMExtraArgsV2_Success() (gas: 28518) +FeeQuoter_processMessageArgs:test_processMessageArgs_WithConvertedTokenAmount_Success() (gas: 29949) +FeeQuoter_processMessageArgs:test_processMessageArgs_WithCorrectPoolReturnData_Success() (gas: 76145) +FeeQuoter_processMessageArgs:test_processMessageArgs_WithEVMExtraArgsV1_Success() (gas: 28116) +FeeQuoter_processMessageArgs:test_processMessageArgs_WithEmptyEVMExtraArgs_Success() (gas: 25987) +FeeQuoter_processMessageArgs:test_processMessageArgs_WithLinkTokenAmount_Success() (gas: 19523) FeeQuoter_updatePrices:test_OnlyCallableByUpdater_Revert() (gas: 12176) -FeeQuoter_updatePrices:test_OnlyGasPrice_Success() (gas: 23774) +FeeQuoter_updatePrices:test_OnlyGasPrice_Success() (gas: 23730) FeeQuoter_updatePrices:test_OnlyTokenPrice_Success() (gas: 28505) -FeeQuoter_updatePrices:test_UpdatableByAuthorizedCaller_Success() (gas: 74668) -FeeQuoter_updatePrices:test_UpdateMultiplePrices_Success() (gas: 145452) +FeeQuoter_updatePrices:test_UpdatableByAuthorizedCaller_Success() (gas: 74598) +FeeQuoter_updatePrices:test_UpdateMultiplePrices_Success() (gas: 145320) FeeQuoter_updateTokenPriceFeeds:test_FeedNotUpdated() (gas: 50875) FeeQuoter_updateTokenPriceFeeds:test_FeedUnset_Success() (gas: 63847) FeeQuoter_updateTokenPriceFeeds:test_FeedUpdatedByNonOwner_Revert() (gas: 20142) @@ -572,23 +572,23 @@ MultiOCR3Base_transmit:test_UnAuthorizedTransmitter_Revert() (gas: 24234) MultiOCR3Base_transmit:test_UnauthorizedSigner_Revert() (gas: 61275) MultiOCR3Base_transmit:test_UnconfiguredPlugin_Revert() (gas: 39933) MultiOCR3Base_transmit:test_ZeroSignatures_Revert() (gas: 33049) -MultiOnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 233745) -MultiRampsE2E:test_E2E_3MessagesMMultiOffRampSuccess_gas() (gas: 1538496) +MultiOnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 233781) +MultiRampsE2E:test_E2E_3MessagesMMultiOffRampSuccess_gas() (gas: 1504341) NonceManager_NonceIncrementation:test_getIncrementedOutboundNonce_Success() (gas: 37934) NonceManager_NonceIncrementation:test_incrementInboundNonce_Skip() (gas: 23721) NonceManager_NonceIncrementation:test_incrementInboundNonce_Success() (gas: 38805) NonceManager_NonceIncrementation:test_incrementNoncesInboundAndOutbound_Success() (gas: 71934) -NonceManager_OffRampUpgrade:test_NoPrevOffRampForChain_Success() (gas: 262150) -NonceManager_OffRampUpgrade:test_UpgradedNonceNewSenderStartsAtZero_Success() (gas: 265827) -NonceManager_OffRampUpgrade:test_UpgradedNonceStartsAtV1Nonce_Success() (gas: 329806) -NonceManager_OffRampUpgrade:test_UpgradedOffRampNonceSkipsIfMsgInFlight_Success() (gas: 300776) +NonceManager_OffRampUpgrade:test_NoPrevOffRampForChain_Success() (gas: 262159) +NonceManager_OffRampUpgrade:test_UpgradedNonceNewSenderStartsAtZero_Success() (gas: 265836) +NonceManager_OffRampUpgrade:test_UpgradedNonceStartsAtV1Nonce_Success() (gas: 329824) +NonceManager_OffRampUpgrade:test_UpgradedOffRampNonceSkipsIfMsgInFlight_Success() (gas: 300784) NonceManager_OffRampUpgrade:test_UpgradedSenderNoncesReadsPreviousRampTransitive_Success() (gas: 249120) NonceManager_OffRampUpgrade:test_UpgradedSenderNoncesReadsPreviousRamp_Success() (gas: 237027) -NonceManager_OffRampUpgrade:test_Upgraded_Success() (gas: 153739) -NonceManager_OnRampUpgrade:test_UpgradeNonceNewSenderStartsAtZero_Success() (gas: 168984) -NonceManager_OnRampUpgrade:test_UpgradeNonceStartsAtV1Nonce_Success() (gas: 221183) +NonceManager_OffRampUpgrade:test_Upgraded_Success() (gas: 153748) +NonceManager_OnRampUpgrade:test_UpgradeNonceNewSenderStartsAtZero_Success() (gas: 168962) +NonceManager_OnRampUpgrade:test_UpgradeNonceStartsAtV1Nonce_Success() (gas: 221139) NonceManager_OnRampUpgrade:test_UpgradeSenderNoncesReadsPreviousRamp_Success() (gas: 126858) -NonceManager_OnRampUpgrade:test_Upgrade_Success() (gas: 107745) +NonceManager_OnRampUpgrade:test_Upgrade_Success() (gas: 107723) NonceManager_applyPreviousRampsUpdates:test_MultipleRampsUpdates() (gas: 123201) NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySetOffRamp_Revert() (gas: 43073) NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySetOnRampAndOffRamp_Revert() (gas: 64402) @@ -621,175 +621,174 @@ OCR2Base_transmit:test_Transmit2SignersSuccess_gas() (gas: 51689) OCR2Base_transmit:test_UnAuthorizedTransmitter_Revert() (gas: 23511) OCR2Base_transmit:test_UnauthorizedSigner_Revert() (gas: 39707) OCR2Base_transmit:test_WrongNumberOfSignatures_Revert() (gas: 20584) -OffRamp_afterOC3ConfigSet:test_afterOCR3ConfigSet_SignatureVerificationDisabled_Revert() (gas: 5720983) -OffRamp_applySourceChainConfigUpdates:test_AddMultipleChains_Success() (gas: 469413) -OffRamp_applySourceChainConfigUpdates:test_AddNewChain_Success() (gas: 99659) -OffRamp_applySourceChainConfigUpdates:test_ApplyZeroUpdates_Success() (gas: 12613) -OffRamp_applySourceChainConfigUpdates:test_InvalidOnRampUpdate_Revert() (gas: 205048) -OffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChainOnRamp_Success() (gas: 101481) -OffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChain_Success() (gas: 111351) -OffRamp_applySourceChainConfigUpdates:test_RouterAddress_Revert() (gas: 13463) -OffRamp_applySourceChainConfigUpdates:test_ZeroOnRampAddress_Revert() (gas: 72746) -OffRamp_applySourceChainConfigUpdates:test_ZeroSourceChainSelector_Revert() (gas: 15519) -OffRamp_batchExecute:test_MultipleReportsDifferentChainsSkipCursedChain_Success() (gas: 177990) -OffRamp_batchExecute:test_MultipleReportsDifferentChains_Success() (gas: 335637) -OffRamp_batchExecute:test_MultipleReportsSameChain_Success() (gas: 278903) -OffRamp_batchExecute:test_MultipleReportsSkipDuplicate_Success() (gas: 169319) -OffRamp_batchExecute:test_OutOfBoundsGasLimitsAccess_Revert() (gas: 189032) -OffRamp_batchExecute:test_SingleReport_Success() (gas: 157143) -OffRamp_batchExecute:test_Unhealthy_Success() (gas: 578427) -OffRamp_batchExecute:test_ZeroReports_Revert() (gas: 10621) -OffRamp_ccipReceive:test_Reverts() (gas: 15406) +OffRamp_afterOC3ConfigSet:test_afterOCR3ConfigSet_SignatureVerificationDisabled_Revert() (gas: 5647759) +OffRamp_applySourceChainConfigUpdates:test_AddMultipleChains_Success() (gas: 469391) +OffRamp_applySourceChainConfigUpdates:test_AddNewChain_Success() (gas: 99637) +OffRamp_applySourceChainConfigUpdates:test_ApplyZeroUpdates_Success() (gas: 12591) +OffRamp_applySourceChainConfigUpdates:test_InvalidOnRampUpdate_Revert() (gas: 205004) +OffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChainOnRamp_Success() (gas: 101437) +OffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChain_Success() (gas: 111307) +OffRamp_applySourceChainConfigUpdates:test_RouterAddress_Revert() (gas: 13441) +OffRamp_applySourceChainConfigUpdates:test_ZeroOnRampAddress_Revert() (gas: 72702) +OffRamp_applySourceChainConfigUpdates:test_ZeroSourceChainSelector_Revert() (gas: 15497) +OffRamp_batchExecute:test_MultipleReportsDifferentChainsSkipCursedChain_Success() (gas: 177979) +OffRamp_batchExecute:test_MultipleReportsDifferentChains_Success() (gas: 335646) +OffRamp_batchExecute:test_MultipleReportsSameChain_Success() (gas: 278912) +OffRamp_batchExecute:test_MultipleReportsSkipDuplicate_Success() (gas: 169308) +OffRamp_batchExecute:test_OutOfBoundsGasLimitsAccess_Revert() (gas: 189031) +OffRamp_batchExecute:test_SingleReport_Success() (gas: 157132) +OffRamp_batchExecute:test_Unhealthy_Success() (gas: 554208) +OffRamp_batchExecute:test_ZeroReports_Revert() (gas: 10600) +OffRamp_ccipReceive:test_Reverts() (gas: 15385) OffRamp_commit:test_CommitOnRampMismatch_Revert() (gas: 92593) OffRamp_commit:test_FailedRMNVerification_Reverts() (gas: 63787) OffRamp_commit:test_InvalidIntervalMinLargerThanMax_Revert() (gas: 67826) OffRamp_commit:test_InvalidInterval_Revert() (gas: 63993) OffRamp_commit:test_InvalidRootRevert() (gas: 63066) -OffRamp_commit:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6324922) -OffRamp_commit:test_NoConfig_Revert() (gas: 5908594) +OffRamp_commit:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6251632) +OffRamp_commit:test_NoConfig_Revert() (gas: 5835304) OffRamp_commit:test_OnlyGasPriceUpdates_Success() (gas: 112835) OffRamp_commit:test_OnlyPriceUpdateStaleReport_Revert() (gas: 121022) OffRamp_commit:test_OnlyTokenPriceUpdates_Success() (gas: 112856) OffRamp_commit:test_PriceSequenceNumberCleared_Success() (gas: 354804) OffRamp_commit:test_ReportAndPriceUpdate_Success() (gas: 164033) -OffRamp_commit:test_ReportOnlyRootSuccess_gas() (gas: 139030) +OffRamp_commit:test_ReportOnlyRootSuccess_gas() (gas: 139074) OffRamp_commit:test_RootAlreadyCommitted_Revert() (gas: 145995) OffRamp_commit:test_SourceChainNotEnabled_Revert() (gas: 59555) -OffRamp_commit:test_StaleReportWithRoot_Success() (gas: 231426) +OffRamp_commit:test_StaleReportWithRoot_Success() (gas: 231514) OffRamp_commit:test_UnauthorizedTransmitter_Revert() (gas: 125104) OffRamp_commit:test_Unhealthy_Revert() (gas: 58334) -OffRamp_commit:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 206207) +OffRamp_commit:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 206251) OffRamp_commit:test_ZeroEpochAndRound_Revert() (gas: 51522) -OffRamp_constructor:test_Constructor_Success() (gas: 5909740) -OffRamp_constructor:test_SourceChainSelector_Revert() (gas: 135611) -OffRamp_constructor:test_ZeroChainSelector_Revert() (gas: 103046) -OffRamp_constructor:test_ZeroNonceManager_Revert() (gas: 100940) -OffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 161137) -OffRamp_constructor:test_ZeroRMNRemote_Revert() (gas: 100860) -OffRamp_constructor:test_ZeroTokenAdminRegistry_Revert() (gas: 100898) +OffRamp_constructor:test_Constructor_Success() (gas: 5836579) +OffRamp_constructor:test_SourceChainSelector_Revert() (gas: 135495) +OffRamp_constructor:test_ZeroChainSelector_Revert() (gas: 102930) +OffRamp_constructor:test_ZeroNonceManager_Revert() (gas: 100824) +OffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 161021) +OffRamp_constructor:test_ZeroRMNRemote_Revert() (gas: 100744) +OffRamp_constructor:test_ZeroTokenAdminRegistry_Revert() (gas: 100782) OffRamp_execute:test_IncorrectArrayType_Revert() (gas: 17639) -OffRamp_execute:test_LargeBatch_Success() (gas: 3426335) -OffRamp_execute:test_MultipleReportsWithPartialValidationFailures_Success() (gas: 372966) -OffRamp_execute:test_MultipleReports_Success() (gas: 300979) -OffRamp_execute:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6734104) -OffRamp_execute:test_NoConfig_Revert() (gas: 5958579) +OffRamp_execute:test_LargeBatch_Success() (gas: 3426635) +OffRamp_execute:test_MultipleReportsWithPartialValidationFailures_Success() (gas: 373122) +OffRamp_execute:test_MultipleReports_Success() (gas: 301009) +OffRamp_execute:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6660824) +OffRamp_execute:test_NoConfig_Revert() (gas: 5885299) OffRamp_execute:test_NonArray_Revert() (gas: 27562) -OffRamp_execute:test_SingleReport_Success() (gas: 176354) -OffRamp_execute:test_UnauthorizedTransmitter_Revert() (gas: 148372) -OffRamp_execute:test_WrongConfigWithSigners_Revert() (gas: 6736853) +OffRamp_execute:test_SingleReport_Success() (gas: 176364) +OffRamp_execute:test_UnauthorizedTransmitter_Revert() (gas: 148382) +OffRamp_execute:test_WrongConfigWithSigners_Revert() (gas: 6663573) OffRamp_execute:test_ZeroReports_Revert() (gas: 17361) -OffRamp_executeSingleMessage:test_MessageSender_Revert() (gas: 18533) -OffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 248725) -OffRamp_executeSingleMessage:test_NonContract_Success() (gas: 20781) -OffRamp_executeSingleMessage:test_TokenHandlingError_Revert() (gas: 209765) -OffRamp_executeSingleMessage:test_ZeroGasDONExecution_Revert() (gas: 49306) -OffRamp_executeSingleMessage:test_executeSingleMessage_NoTokens_Success() (gas: 48750) -OffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidationNoRouterCall_Revert() (gas: 218004) -OffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidation_Revert() (gas: 85272) -OffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens_Success() (gas: 280350) -OffRamp_executeSingleMessage:test_executeSingleMessage_WithVInterception_Success() (gas: 91700) -OffRamp_executeSingleReport:test_DisabledSourceChain_Revert() (gas: 28261) -OffRamp_executeSingleReport:test_EmptyReport_Revert() (gas: 22063) -OffRamp_executeSingleReport:test_InvalidSourcePoolAddress_Success() (gas: 501125) -OffRamp_executeSingleReport:test_ManualExecutionNotYetEnabled_Revert() (gas: 48373) -OffRamp_executeSingleReport:test_MismatchingDestChainSelector_Revert() (gas: 33960) -OffRamp_executeSingleReport:test_NonExistingSourceChain_Revert() (gas: 28437) -OffRamp_executeSingleReport:test_ReceiverError_Success() (gas: 188072) -OffRamp_executeSingleReport:test_RetryFailedMessageWithoutManualExecution_Revert() (gas: 198507) -OffRamp_executeSingleReport:test_RootNotCommitted_Revert() (gas: 40742) -OffRamp_executeSingleReport:test_RouterYULCall_Revert() (gas: 413224) -OffRamp_executeSingleReport:test_SingleMessageNoTokensOtherChain_Success() (gas: 249758) -OffRamp_executeSingleReport:test_SingleMessageNoTokensUnordered_Success() (gas: 193572) -OffRamp_executeSingleReport:test_SingleMessageNoTokens_Success() (gas: 213606) -OffRamp_executeSingleReport:test_SingleMessageToNonCCIPReceiver_Success() (gas: 249529) -OffRamp_executeSingleReport:test_SingleMessagesNoTokensSuccess_gas() (gas: 142142) -OffRamp_executeSingleReport:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 424632) -OffRamp_executeSingleReport:test_SkippedIncorrectNonce_Success() (gas: 58294) -OffRamp_executeSingleReport:test_TokenDataMismatch_Revert() (gas: 73869) -OffRamp_executeSingleReport:test_TwoMessagesWithTokensAndGE_Success() (gas: 603198) -OffRamp_executeSingleReport:test_TwoMessagesWithTokensSuccess_gas() (gas: 548187) -OffRamp_executeSingleReport:test_UnexpectedTokenData_Revert() (gas: 33718) -OffRamp_executeSingleReport:test_UnhealthySingleChainCurse_Revert() (gas: 573911) -OffRamp_executeSingleReport:test_Unhealthy_Success() (gas: 573925) -OffRamp_executeSingleReport:test_WithCurseOnAnotherSourceChain_Success() (gas: 477004) -OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessageUnordered_Success() (gas: 135902) -OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessage_Success() (gas: 165607) -OffRamp_getExecutionState:test_FillExecutionState_Success() (gas: 3936242) -OffRamp_getExecutionState:test_GetDifferentChainExecutionState_Success() (gas: 120870) -OffRamp_getExecutionState:test_GetExecutionState_Success() (gas: 89684) -OffRamp_manuallyExecute:test_ManualExecGasLimitMismatchSingleReport_Revert() (gas: 81016) -OffRamp_manuallyExecute:test_manuallyExecute_DestinationGasAmountCountMismatch_Revert() (gas: 80316) -OffRamp_manuallyExecute:test_manuallyExecute_DoesNotRevertIfUntouched_Success() (gas: 173164) -OffRamp_manuallyExecute:test_manuallyExecute_FailedTx_Revert() (gas: 214120) -OffRamp_manuallyExecute:test_manuallyExecute_ForkedChain_Revert() (gas: 27085) -OffRamp_manuallyExecute:test_manuallyExecute_GasLimitMismatchMultipleReports_Revert() (gas: 164696) -OffRamp_manuallyExecute:test_manuallyExecute_InvalidReceiverExecutionGasLimit_Revert() (gas: 27622) -OffRamp_manuallyExecute:test_manuallyExecute_InvalidTokenGasOverride_Revert() (gas: 59339) -OffRamp_manuallyExecute:test_manuallyExecute_LowGasLimit_Success() (gas: 498548) -OffRamp_manuallyExecute:test_manuallyExecute_MultipleReportsWithSingleCursedLane_Revert() (gas: 316061) -OffRamp_manuallyExecute:test_manuallyExecute_ReentrancyFails_Success() (gas: 2351652) -OffRamp_manuallyExecute:test_manuallyExecute_SourceChainSelectorMismatch_Revert() (gas: 165525) -OffRamp_manuallyExecute:test_manuallyExecute_Success() (gas: 227165) -OffRamp_manuallyExecute:test_manuallyExecute_WithGasOverride_Success() (gas: 227705) -OffRamp_manuallyExecute:test_manuallyExecute_WithMultiReportGasOverride_Success() (gas: 781361) -OffRamp_manuallyExecute:test_manuallyExecute_WithPartialMessages_Success() (gas: 347342) -OffRamp_releaseOrMintSingleToken:test__releaseOrMintSingleToken_NotACompatiblePool_Revert() (gas: 40854) -OffRamp_releaseOrMintSingleToken:test__releaseOrMintSingleToken_Success() (gas: 105958) -OffRamp_releaseOrMintSingleToken:test__releaseOrMintSingleToken_TokenHandlingError_transfer_Revert() (gas: 87217) -OffRamp_releaseOrMintSingleToken:test_releaseOrMintToken_InvalidDataLength_Revert() (gas: 38554) -OffRamp_releaseOrMintSingleToken:test_releaseOrMintToken_ReleaseOrMintBalanceMismatch_Revert() (gas: 96196) -OffRamp_releaseOrMintSingleToken:test_releaseOrMintToken_TokenHandlingError_BalanceOf_Revert() (gas: 41546) -OffRamp_releaseOrMintSingleToken:test_releaseOrMintToken_skip_ReleaseOrMintBalanceMismatch_if_pool_Revert() (gas: 88339) -OffRamp_releaseOrMintTokens:test_TokenHandlingError_Reverts() (gas: 165892) -OffRamp_releaseOrMintTokens:test__releaseOrMintTokens_PoolIsNotAPool_Reverts() (gas: 25497) -OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_InvalidDataLengthReturnData_Revert() (gas: 65805) -OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_InvalidEVMAddress_Revert() (gas: 42396) -OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_PoolDoesNotSupportDest_Reverts() (gas: 82866) -OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_Success() (gas: 177978) -OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_WithGasOverride_Success() (gas: 179970) -OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals_Success() (gas: 191188) -OffRamp_setDynamicConfig:test_FeeQuoterZeroAddress_Revert() (gas: 11246) -OffRamp_setDynamicConfig:test_NonOwner_Revert() (gas: 13861) -OffRamp_setDynamicConfig:test_SetDynamicConfigWithInterceptor_Success() (gas: 46354) -OffRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 24396) -OffRamp_trialExecute:test_RateLimitError_Success() (gas: 226578) -OffRamp_trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 235200) -OffRamp_trialExecute:test_TokenPoolIsNotAContract_Success() (gas: 313735) -OffRamp_trialExecute:test_trialExecute_Success() (gas: 285095) +OffRamp_executeSingleMessage:test_MessageSender_Revert() (gas: 18511) +OffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 244057) +OffRamp_executeSingleMessage:test_NonContract_Success() (gas: 20759) +OffRamp_executeSingleMessage:test_TokenHandlingError_Revert() (gas: 205097) +OffRamp_executeSingleMessage:test_ZeroGasDONExecution_Revert() (gas: 49316) +OffRamp_executeSingleMessage:test_executeSingleMessage_NoTokens_Success() (gas: 48760) +OffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidationNoRouterCall_Revert() (gas: 218108) +OffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidation_Revert() (gas: 85376) +OffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens_Success() (gas: 274194) +OffRamp_executeSingleMessage:test_executeSingleMessage_WithVInterception_Success() (gas: 91836) +OffRamp_executeSingleReport:test_DisabledSourceChain_Revert() (gas: 28260) +OffRamp_executeSingleReport:test_EmptyReport_Revert() (gas: 22062) +OffRamp_executeSingleReport:test_InvalidSourcePoolAddress_Success() (gas: 481748) +OffRamp_executeSingleReport:test_ManualExecutionNotYetEnabled_Revert() (gas: 48372) +OffRamp_executeSingleReport:test_MismatchingDestChainSelector_Revert() (gas: 33959) +OffRamp_executeSingleReport:test_NonExistingSourceChain_Revert() (gas: 28436) +OffRamp_executeSingleReport:test_ReceiverError_Success() (gas: 188081) +OffRamp_executeSingleReport:test_RetryFailedMessageWithoutManualExecution_Revert() (gas: 198515) +OffRamp_executeSingleReport:test_RootNotCommitted_Revert() (gas: 40741) +OffRamp_executeSingleReport:test_RouterYULCall_Revert() (gas: 413233) +OffRamp_executeSingleReport:test_SingleMessageNoTokensOtherChain_Success() (gas: 249776) +OffRamp_executeSingleReport:test_SingleMessageNoTokensUnordered_Success() (gas: 193590) +OffRamp_executeSingleReport:test_SingleMessageNoTokens_Success() (gas: 213624) +OffRamp_executeSingleReport:test_SingleMessageToNonCCIPReceiver_Success() (gas: 249506) +OffRamp_executeSingleReport:test_SingleMessagesNoTokensSuccess_gas() (gas: 142151) +OffRamp_executeSingleReport:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 409289) +OffRamp_executeSingleReport:test_SkippedIncorrectNonce_Success() (gas: 58293) +OffRamp_executeSingleReport:test_TokenDataMismatch_Revert() (gas: 73868) +OffRamp_executeSingleReport:test_TwoMessagesWithTokensAndGE_Success() (gas: 583401) +OffRamp_executeSingleReport:test_TwoMessagesWithTokensSuccess_gas() (gas: 532115) +OffRamp_executeSingleReport:test_UnexpectedTokenData_Revert() (gas: 33717) +OffRamp_executeSingleReport:test_UnhealthySingleChainCurse_Revert() (gas: 549738) +OffRamp_executeSingleReport:test_Unhealthy_Success() (gas: 549752) +OffRamp_executeSingleReport:test_WithCurseOnAnotherSourceChain_Success() (gas: 460495) +OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessageUnordered_Success() (gas: 135910) +OffRamp_executeSingleReport:test__execute_SkippedAlreadyExecutedMessage_Success() (gas: 165615) +OffRamp_getExecutionState:test_FillExecutionState_Success() (gas: 3868658) +OffRamp_getExecutionState:test_GetDifferentChainExecutionState_Success() (gas: 120474) +OffRamp_getExecutionState:test_GetExecutionState_Success() (gas: 89178) +OffRamp_manuallyExecute:test_ManualExecGasLimitMismatchSingleReport_Revert() (gas: 81284) +OffRamp_manuallyExecute:test_manuallyExecute_DestinationGasAmountCountMismatch_Revert() (gas: 74161) +OffRamp_manuallyExecute:test_manuallyExecute_DoesNotRevertIfUntouched_Success() (gas: 173241) +OffRamp_manuallyExecute:test_manuallyExecute_FailedTx_Revert() (gas: 214186) +OffRamp_manuallyExecute:test_manuallyExecute_ForkedChain_Revert() (gas: 27152) +OffRamp_manuallyExecute:test_manuallyExecute_GasLimitMismatchMultipleReports_Revert() (gas: 165098) +OffRamp_manuallyExecute:test_manuallyExecute_InvalidReceiverExecutionGasLimit_Revert() (gas: 27689) +OffRamp_manuallyExecute:test_manuallyExecute_InvalidTokenGasOverride_Revert() (gas: 55260) +OffRamp_manuallyExecute:test_manuallyExecute_LowGasLimit_Success() (gas: 498614) +OffRamp_manuallyExecute:test_manuallyExecute_MultipleReportsWithSingleCursedLane_Revert() (gas: 316158) +OffRamp_manuallyExecute:test_manuallyExecute_ReentrancyFails_Success() (gas: 2245360) +OffRamp_manuallyExecute:test_manuallyExecute_SourceChainSelectorMismatch_Revert() (gas: 165602) +OffRamp_manuallyExecute:test_manuallyExecute_Success() (gas: 227231) +OffRamp_manuallyExecute:test_manuallyExecute_WithGasOverride_Success() (gas: 227771) +OffRamp_manuallyExecute:test_manuallyExecute_WithMultiReportGasOverride_Success() (gas: 781507) +OffRamp_manuallyExecute:test_manuallyExecute_WithPartialMessages_Success() (gas: 347428) +OffRamp_releaseOrMintSingleToken:test__releaseOrMintSingleToken_NotACompatiblePool_Revert() (gas: 37634) +OffRamp_releaseOrMintSingleToken:test__releaseOrMintSingleToken_Success() (gas: 104404) +OffRamp_releaseOrMintSingleToken:test__releaseOrMintSingleToken_TokenHandlingError_transfer_Revert() (gas: 85342) +OffRamp_releaseOrMintSingleToken:test_releaseOrMintToken_InvalidDataLength_Revert() (gas: 36752) +OffRamp_releaseOrMintSingleToken:test_releaseOrMintToken_ReleaseOrMintBalanceMismatch_Revert() (gas: 94382) +OffRamp_releaseOrMintSingleToken:test_releaseOrMintToken_TokenHandlingError_BalanceOf_Revert() (gas: 39741) +OffRamp_releaseOrMintSingleToken:test_releaseOrMintToken_skip_ReleaseOrMintBalanceMismatch_if_pool_Revert() (gas: 86516) +OffRamp_releaseOrMintTokens:test_TokenHandlingError_Reverts() (gas: 162381) +OffRamp_releaseOrMintTokens:test__releaseOrMintTokens_PoolIsNotAPool_Reverts() (gas: 23903) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_InvalidDataLengthReturnData_Revert() (gas: 62751) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_PoolDoesNotSupportDest_Reverts() (gas: 79790) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_Success() (gas: 174512) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_WithGasOverride_Success() (gas: 176424) +OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals_Success() (gas: 187723) +OffRamp_setDynamicConfig:test_FeeQuoterZeroAddress_Revert() (gas: 11296) +OffRamp_setDynamicConfig:test_NonOwner_Revert() (gas: 13911) +OffRamp_setDynamicConfig:test_SetDynamicConfigWithInterceptor_Success() (gas: 46448) +OffRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 24490) +OffRamp_trialExecute:test_RateLimitError_Success() (gas: 219358) +OffRamp_trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 227980) +OffRamp_trialExecute:test_TokenPoolIsNotAContract_Success() (gas: 295350) +OffRamp_trialExecute:test_trialExecute_Success() (gas: 277894) OnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 390842) OnRamp_applyAllowListUpdates:test_applyAllowListUpdates_InvalidAllowListRequestDisabledAllowListWithAdds() (gas: 18030) OnRamp_applyAllowListUpdates:test_applyAllowListUpdates_Revert() (gas: 67429) OnRamp_applyAllowListUpdates:test_applyAllowListUpdates_Success() (gas: 325126) OnRamp_applyDestChainConfigUpdates:test_ApplyDestChainConfigUpdates_Success() (gas: 65230) OnRamp_applyDestChainConfigUpdates:test_ApplyDestChainConfigUpdates_WithInvalidChainSelector_Revert() (gas: 13446) -OnRamp_constructor:test_Constructor_InvalidConfigChainSelectorEqZero_Revert() (gas: 95056) -OnRamp_constructor:test_Constructor_InvalidConfigNonceManagerEqAddressZero_Revert() (gas: 92998) -OnRamp_constructor:test_Constructor_InvalidConfigRMNProxyEqAddressZero_Revert() (gas: 98031) -OnRamp_constructor:test_Constructor_InvalidConfigTokenAdminRegistryEqAddressZero_Revert() (gas: 93054) -OnRamp_constructor:test_Constructor_Success() (gas: 2756090) -OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() (gas: 115174) -OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2_Success() (gas: 145997) -OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessCustomExtraArgs() (gas: 145573) -OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessEmptyExtraArgs() (gas: 143812) -OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessLegacyExtraArgs() (gas: 145791) -OnRamp_forwardFromRouter:test_ForwardFromRouter_Success() (gas: 145170) -OnRamp_forwardFromRouter:test_ForwardFromRouter_Success_ConfigurableSourceRouter() (gas: 146002) -OnRamp_forwardFromRouter:test_InvalidExtraArgsTag_Revert() (gas: 38615) +OnRamp_constructor:test_Constructor_InvalidConfigChainSelectorEqZero_Revert() (gas: 95048) +OnRamp_constructor:test_Constructor_InvalidConfigNonceManagerEqAddressZero_Revert() (gas: 92990) +OnRamp_constructor:test_Constructor_InvalidConfigRMNProxyEqAddressZero_Revert() (gas: 98023) +OnRamp_constructor:test_Constructor_InvalidConfigTokenAdminRegistryEqAddressZero_Revert() (gas: 93046) +OnRamp_constructor:test_Constructor_Success() (gas: 2750875) +OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() (gas: 115152) +OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2_Success() (gas: 145975) +OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessCustomExtraArgs() (gas: 145551) +OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessEmptyExtraArgs() (gas: 143790) +OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessLegacyExtraArgs() (gas: 145769) +OnRamp_forwardFromRouter:test_ForwardFromRouter_Success() (gas: 145148) +OnRamp_forwardFromRouter:test_ForwardFromRouter_Success_ConfigurableSourceRouter() (gas: 145980) +OnRamp_forwardFromRouter:test_InvalidExtraArgsTag_Revert() (gas: 38593) OnRamp_forwardFromRouter:test_MessageInterceptionError_Revert() (gas: 143071) -OnRamp_forwardFromRouter:test_MesssageFeeTooHigh_Revert() (gas: 36739) -OnRamp_forwardFromRouter:test_MultiCannotSendZeroTokens_Revert() (gas: 36473) +OnRamp_forwardFromRouter:test_MesssageFeeTooHigh_Revert() (gas: 36706) +OnRamp_forwardFromRouter:test_MultiCannotSendZeroTokens_Revert() (gas: 36509) OnRamp_forwardFromRouter:test_OriginalSender_Revert() (gas: 18291) OnRamp_forwardFromRouter:test_Paused_Revert() (gas: 38454) OnRamp_forwardFromRouter:test_Permissions_Revert() (gas: 23663) -OnRamp_forwardFromRouter:test_ShouldIncrementNonceOnlyOnOrdered_Success() (gas: 186250) -OnRamp_forwardFromRouter:test_ShouldIncrementSeqNumAndNonce_Success() (gas: 212635) -OnRamp_forwardFromRouter:test_ShouldStoreLinkFees() (gas: 125158) -OnRamp_forwardFromRouter:test_ShouldStoreNonLinkFees() (gas: 141789) -OnRamp_forwardFromRouter:test_SourceTokenDataTooLarge_Revert() (gas: 3622885) +OnRamp_forwardFromRouter:test_ShouldIncrementNonceOnlyOnOrdered_Success() (gas: 186184) +OnRamp_forwardFromRouter:test_ShouldIncrementSeqNumAndNonce_Success() (gas: 212569) +OnRamp_forwardFromRouter:test_ShouldStoreLinkFees() (gas: 125136) +OnRamp_forwardFromRouter:test_ShouldStoreNonLinkFees() (gas: 141767) +OnRamp_forwardFromRouter:test_SourceTokenDataTooLarge_Revert() (gas: 3618195) OnRamp_forwardFromRouter:test_UnAllowedOriginalSender_Revert() (gas: 24010) -OnRamp_forwardFromRouter:test_UnsupportedToken_Revert() (gas: 75790) -OnRamp_forwardFromRouter:test_forwardFromRouter_UnsupportedToken_Revert() (gas: 38523) -OnRamp_forwardFromRouter:test_forwardFromRouter_WithInterception_Success() (gas: 282461) +OnRamp_forwardFromRouter:test_UnsupportedToken_Revert() (gas: 75826) +OnRamp_forwardFromRouter:test_forwardFromRouter_UnsupportedToken_Revert() (gas: 38559) +OnRamp_forwardFromRouter:test_forwardFromRouter_WithInterception_Success() (gas: 280065) OnRamp_getFee:test_EmptyMessage_Success() (gas: 98760) OnRamp_getFee:test_EnforceOutOfOrder_Revert() (gas: 64779) OnRamp_getFee:test_GetFeeOfZeroForTokenMessage_Success() (gas: 86359) @@ -900,11 +899,11 @@ Router_ccipSend:test_NativeFeeTokenInsufficientValue() (gas: 67174) Router_ccipSend:test_NativeFeeTokenOverpay_Success() (gas: 170385) Router_ccipSend:test_NativeFeeTokenZeroValue() (gas: 54279) Router_ccipSend:test_NativeFeeToken_Success() (gas: 168901) -Router_ccipSend:test_NonLinkFeeToken_Success() (gas: 239295) +Router_ccipSend:test_NonLinkFeeToken_Success() (gas: 239230) Router_ccipSend:test_UnsupportedDestinationChain_Revert() (gas: 24854) Router_ccipSend:test_WhenNotHealthy_Revert() (gas: 44811) Router_ccipSend:test_WrappedNativeFeeToken_Success() (gas: 171159) -Router_ccipSend:test_ZeroFeeAndGasPrice_Success() (gas: 241766) +Router_ccipSend:test_ZeroFeeAndGasPrice_Success() (gas: 241701) Router_constructor:test_Constructor_Success() (gas: 13124) Router_getArmProxy:test_getArmProxy() (gas: 10573) Router_getFee:test_GetFeeSupportedChain_Success() (gas: 44673) diff --git a/contracts/src/v0.8/ccip/FeeQuoter.sol b/contracts/src/v0.8/ccip/FeeQuoter.sol index aad7dd2941..9004c6b97d 100644 --- a/contracts/src/v0.8/ccip/FeeQuoter.sol +++ b/contracts/src/v0.8/ccip/FeeQuoter.sol @@ -862,13 +862,13 @@ contract FeeQuoter is AuthorizedCallers, IFeeQuoter, ITypeAndVersion, IReceiver, } /// @inheritdoc IFeeQuoter - /// @dev precondition - rampTokenAmounts and sourceTokenAmounts lengths must be equal + /// @dev precondition - onRampTokenTransfers and sourceTokenAmounts lengths must be equal function processMessageArgs( uint64 destChainSelector, address feeToken, uint256 feeTokenAmount, bytes calldata extraArgs, - Internal.RampTokenAmount[] calldata rampTokenAmounts, + Internal.EVM2AnyTokenTransfer[] calldata onRampTokenTransfers, Client.EVMTokenAmount[] calldata sourceTokenAmounts ) external @@ -894,37 +894,37 @@ contract FeeQuoter is AuthorizedCallers, IFeeQuoter, ITypeAndVersion, IReceiver, // We can parse unvalidated args since this message is called after getFee (which will already validate the params) Client.EVMExtraArgsV2 memory parsedExtraArgs = _parseUnvalidatedEVMExtraArgsFromBytes(extraArgs, defaultTxGasLimit); isOutOfOrderExecution = parsedExtraArgs.allowOutOfOrderExecution; - destExecDataPerToken = _processPoolReturnData(destChainSelector, rampTokenAmounts, sourceTokenAmounts); + destExecDataPerToken = _processPoolReturnData(destChainSelector, onRampTokenTransfers, sourceTokenAmounts); return (msgFeeJuels, isOutOfOrderExecution, Client._argsToBytes(parsedExtraArgs), destExecDataPerToken); } /// @notice Validates pool return data /// @param destChainSelector Destination chain selector to which the token amounts are sent to - /// @param rampTokenAmounts Token amounts with populated pool return data + /// @param onRampTokenTransfers Token amounts with populated pool return data /// @param sourceTokenAmounts Token amounts originally sent in a Client.EVM2AnyMessage message /// @return destExecDataPerToken Destination chain execution data function _processPoolReturnData( uint64 destChainSelector, - Internal.RampTokenAmount[] calldata rampTokenAmounts, + Internal.EVM2AnyTokenTransfer[] calldata onRampTokenTransfers, Client.EVMTokenAmount[] calldata sourceTokenAmounts ) internal view returns (bytes[] memory destExecDataPerToken) { bytes4 chainFamilySelector = s_destChainConfigs[destChainSelector].chainFamilySelector; - destExecDataPerToken = new bytes[](rampTokenAmounts.length); - for (uint256 i = 0; i < rampTokenAmounts.length; ++i) { + destExecDataPerToken = new bytes[](onRampTokenTransfers.length); + for (uint256 i = 0; i < onRampTokenTransfers.length; ++i) { address sourceToken = sourceTokenAmounts[i].token; // Since the DON has to pay for the extraData to be included on the destination chain, we cap the length of the // extraData. This prevents gas bomb attacks on the NOPs. As destBytesOverhead accounts for both // extraData and offchainData, this caps the worst case abuse to the number of bytes reserved for offchainData. - uint256 destPoolDataLength = rampTokenAmounts[i].extraData.length; + uint256 destPoolDataLength = onRampTokenTransfers[i].extraData.length; if (destPoolDataLength > Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES) { if (destPoolDataLength > s_tokenTransferFeeConfig[destChainSelector][sourceToken].destBytesOverhead) { revert SourceTokenDataTooLarge(sourceToken); } } - _validateDestFamilyAddress(chainFamilySelector, rampTokenAmounts[i].destTokenAddress); + _validateDestFamilyAddress(chainFamilySelector, onRampTokenTransfers[i].destTokenAddress); FeeQuoter.TokenTransferFeeConfig memory tokenTransferFeeConfig = s_tokenTransferFeeConfig[destChainSelector][sourceToken]; uint32 defaultGasOverhead = s_destChainConfigs[destChainSelector].defaultTokenDestGasOverhead; diff --git a/contracts/src/v0.8/ccip/interfaces/IFeeQuoter.sol b/contracts/src/v0.8/ccip/interfaces/IFeeQuoter.sol index e02947961d..4fa9cbfec4 100644 --- a/contracts/src/v0.8/ccip/interfaces/IFeeQuoter.sol +++ b/contracts/src/v0.8/ccip/interfaces/IFeeQuoter.sol @@ -21,7 +21,7 @@ interface IFeeQuoter is IPriceRegistry { /// @param feeToken Fee token address used to pay for message fees /// @param feeTokenAmount Fee token amount /// @param extraArgs Message extra args that were passed in by the client - /// @param rampTokenAmounts Token amounts with populated pool return data + /// @param onRampTokenTransfers Token amounts with populated pool return data /// @param sourceTokenAmounts Token amounts originally sent in a Client.EVM2AnyMessage message /// @return msgFeeJuels message fee in juels /// @return isOutOfOrderExecution true if the message should be executed out of order @@ -32,7 +32,7 @@ interface IFeeQuoter is IPriceRegistry { address feeToken, uint256 feeTokenAmount, bytes memory extraArgs, - Internal.RampTokenAmount[] calldata rampTokenAmounts, + Internal.EVM2AnyTokenTransfer[] calldata onRampTokenTransfers, Client.EVMTokenAmount[] calldata sourceTokenAmounts ) external diff --git a/contracts/src/v0.8/ccip/libraries/Internal.sol b/contracts/src/v0.8/ccip/libraries/Internal.sol index e704113e10..d09717f63a 100644 --- a/contracts/src/v0.8/ccip/libraries/Internal.sol +++ b/contracts/src/v0.8/ccip/libraries/Internal.sol @@ -140,11 +140,12 @@ library Internal { uint256 public constant ANY_2_EVM_MESSAGE_FIXED_BYTES = 32 * 14; /// @dev Each token transfer adds 1 RampTokenAmount - /// RampTokenAmount has 5 fields, 3 of which are bytes type, 1 uint256 and 1 uint32. + /// RampTokenAmount has 5 fields, 2 of which are bytes type, 1 Address, 1 uint256 and 1 uint32. /// Each bytes type takes 1 slot for length, 1 slot for data and 1 slot for the offset. + /// address /// uint256 amount takes 1 slot. /// uint32 destGasAmount takes 1 slot. - uint256 public constant ANY_2_EVM_MESSAGE_FIXED_BYTES_PER_TOKEN = 32 * ((3 * 3) + 2); + uint256 public constant ANY_2_EVM_MESSAGE_FIXED_BYTES_PER_TOKEN = 32 * ((2 * 3) + 3); bytes32 internal constant EVM_2_EVM_MESSAGE_HASH = keccak256("EVM2EVMMessageHashV2"); @@ -277,12 +278,21 @@ library Internal { Execution } - /// @notice Family-agnostic token amounts used for both OnRamp & OffRamp messages - struct RampTokenAmount { - // The source pool address, abi encoded. This value is trusted as it was obtained through the onRamp. It can be + /// @notice Family-agnostic header for OnRamp & OffRamp messages. + /// The messageId is not expected to match hash(message), since it may originate from another ramp family + struct RampMessageHeader { + bytes32 messageId; // Unique identifier for the message, generated with the source chain's encoding scheme (i.e. not necessarily abi.encoded) + uint64 sourceChainSelector; // ──╮ the chain selector of the source chain, note: not chainId + uint64 destChainSelector; // | the chain selector of the destination chain, note: not chainId + uint64 sequenceNumber; // │ sequence number, not unique across lanes + uint64 nonce; // ────────────────╯ nonce for this lane for this sender, not unique across senders/lanes + } + + struct EVM2AnyTokenTransfer { + // The source pool EVM address. This value is trusted as it was obtained through the onRamp. It can be // relied upon by the destination pool to validate the source pool. - bytes sourcePoolAddress; - // The address of the destination token, abi encoded in the case of EVM chains + address sourcePoolAddress; + // The EVM address of the destination token // This value is UNTRUSTED as any pool owner can return whatever value they want. bytes destTokenAddress; // Optional pool data to be transferred to the destination chain. Be default this is capped at @@ -291,18 +301,22 @@ library Internal { bytes extraData; uint256 amount; // Amount of tokens. // Destination chain specific execution data encoded in bytes - //(for EVM destination it consists of the amount of gas available for the releaseOrMint and transfer calls on the offRamp + // for an EVM destination, it consists of the amount of gas available for the releaseOrMint + // and transfer calls made by the offRamp bytes destExecData; } - /// @notice Family-agnostic header for OnRamp & OffRamp messages. - /// The messageId is not expected to match hash(message), since it may originate from another ramp family - struct RampMessageHeader { - bytes32 messageId; // Unique identifier for the message, generated with the source chain's encoding scheme (i.e. not necessarily abi.encoded) - uint64 sourceChainSelector; // ──╮ the chain selector of the source chain, note: not chainId - uint64 destChainSelector; // | the chain selector of the destination chain, note: not chainId - uint64 sequenceNumber; // │ sequence number, not unique across lanes - uint64 nonce; // ────────────────╯ nonce for this lane for this sender, not unique across senders/lanes + struct Any2EVMTokenTransfer { + // The source pool EVM address encoded to bytes. This value is trusted as it is obtained through the onRamp. It can be + // relied upon by the destination pool to validate the source pool. + bytes sourcePoolAddress; + address destTokenAddress; // ───╮ Address of destination token + uint32 destGasAmount; //────────╯ The amount of gas available for the releaseOrMint and transfer calls on the offRamp. + // Optional pool data to be transferred to the destination chain. Be default this is capped at + // CCIP_LOCK_OR_BURN_V1_RET_BYTES bytes. If more data is required, the TokenTransferFeeConfig.destBytesOverhead + // has to be set for the specific token. + bytes extraData; + uint256 amount; // Amount of tokens. } /// @notice Family-agnostic message routed to an OffRamp @@ -314,7 +328,7 @@ library Internal { bytes data; // arbitrary data payload supplied by the message sender address receiver; // receiver address on the destination chain uint256 gasLimit; // user supplied maximum gas amount available for dest chain execution - RampTokenAmount[] tokenAmounts; // array of tokens and amounts to transfer + Any2EVMTokenTransfer[] tokenAmounts; // array of tokens and amounts to transfer } /// @notice Family-agnostic message emitted from the OnRamp @@ -328,7 +342,7 @@ library Internal { bytes extraArgs; // destination-chain specific extra args, such as the gasLimit for EVM chains address feeToken; // fee token uint256 feeTokenAmount; // fee token amount - RampTokenAmount[] tokenAmounts; // array of tokens and amounts to transfer + EVM2AnyTokenTransfer[] tokenAmounts; // array of tokens and amounts to transfer } // bytes4(keccak256("CCIP ChainFamilySelector EVM")) diff --git a/contracts/src/v0.8/ccip/offRamp/OffRamp.sol b/contracts/src/v0.8/ccip/offRamp/OffRamp.sol index 5a15910fc9..99872451b8 100644 --- a/contracts/src/v0.8/ccip/offRamp/OffRamp.sol +++ b/contracts/src/v0.8/ccip/offRamp/OffRamp.sol @@ -299,7 +299,7 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { for (uint256 tokenIndex = 0; tokenIndex < message.tokenAmounts.length; ++tokenIndex) { uint256 tokenGasOverride = msgGasLimitOverrides[msgIndex].tokenGasOverrides[tokenIndex]; if (tokenGasOverride != 0) { - uint32 destGasAmount = abi.decode(message.tokenAmounts[tokenIndex].destExecData, (uint32)); + uint256 destGasAmount = message.tokenAmounts[tokenIndex].destGasAmount; if (tokenGasOverride < destGasAmount) { revert InvalidManualExecutionTokenGasOverride( message.header.messageId, tokenIndex, destGasAmount, tokenGasOverride @@ -620,7 +620,7 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { /// @param offchainTokenData Data fetched offchain by the DON. /// @return destTokenAmount local token address with amount function _releaseOrMintSingleToken( - Internal.RampTokenAmount memory sourceTokenAmount, + Internal.Any2EVMTokenTransfer memory sourceTokenAmount, bytes memory originalSender, address receiver, uint64 sourceChainSelector, @@ -628,7 +628,8 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { ) internal returns (Client.EVMTokenAmount memory destTokenAmount) { // We need to safely decode the token address from the sourceTokenData, as it could be wrong, // in which case it doesn't have to be a valid EVM address. - address localToken = Internal._validateEVMAddress(sourceTokenAmount.destTokenAddress); + // We assume this destTokenAddress has already been fully validated by a (trusted) OnRamp. + address localToken = sourceTokenAmount.destTokenAddress; // We check with the token admin registry if the token has a pool on this chain. address localPoolAddress = ITokenAdminRegistry(i_tokenAdminRegistry).getPool(localToken); // This will call the supportsInterface through the ERC165Checker, and not directly on the pool address. @@ -640,8 +641,7 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { } // We retrieve the local token balance of the receiver before the pool call. - (uint256 balancePre, uint256 gasLeft) = - _getBalanceOfReceiver(receiver, localToken, abi.decode(sourceTokenAmount.destExecData, (uint32))); + (uint256 balancePre, uint256 gasLeft) = _getBalanceOfReceiver(receiver, localToken, sourceTokenAmount.destGasAmount); // We determined that the pool address is a valid EVM address, but that does not mean the code at this // address is a (compatible) pool contract. _callWithExactGasSafeReturnData will check if the location @@ -733,7 +733,7 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { /// any non-rate limiting errors that may occur. If we encounter a rate limiting related error /// we bubble it up. If we encounter a non-rate limiting error we wrap it in a TokenHandlingError. function _releaseOrMintTokens( - Internal.RampTokenAmount[] memory sourceTokenAmounts, + Internal.Any2EVMTokenTransfer[] memory sourceTokenAmounts, bytes memory originalSender, address receiver, uint64 sourceChainSelector, @@ -745,7 +745,7 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { for (uint256 i = 0; i < sourceTokenAmounts.length; ++i) { if (!isTokenGasOverridesEmpty) { if (tokenGasOverrides[i] != 0) { - sourceTokenAmounts[i].destExecData = abi.encode(tokenGasOverrides[i]); + sourceTokenAmounts[i].destGasAmount = tokenGasOverrides[i]; } } destTokenAmounts[i] = _releaseOrMintSingleToken( diff --git a/contracts/src/v0.8/ccip/onRamp/OnRamp.sol b/contracts/src/v0.8/ccip/onRamp/OnRamp.sol index a8ba346388..76e966311d 100644 --- a/contracts/src/v0.8/ccip/onRamp/OnRamp.sol +++ b/contracts/src/v0.8/ccip/onRamp/OnRamp.sol @@ -212,7 +212,7 @@ contract OnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCreator { feeToken: message.feeToken, feeTokenAmount: feeTokenAmount, // Should be populated via lock / burn pool calls - tokenAmounts: new Internal.RampTokenAmount[](message.tokenAmounts.length) + tokenAmounts: new Internal.EVM2AnyTokenTransfer[](message.tokenAmounts.length) }); // Lock / burn the tokens as last step. TokenPools may not always be trusted. @@ -267,13 +267,13 @@ contract OnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCreator { /// @param destChainSelector Target destination chain selector of the message /// @param receiver Message receiver /// @param originalSender Message sender - /// @return rampTokenAmount Ramp token and amount data + /// @return evm2AnyTokenTransfer EVM2Any token and amount data function _lockOrBurnSingleToken( Client.EVMTokenAmount memory tokenAndAmount, uint64 destChainSelector, bytes memory receiver, address originalSender - ) internal returns (Internal.RampTokenAmount memory) { + ) internal returns (Internal.EVM2AnyTokenTransfer memory) { if (tokenAndAmount.amount == 0) revert CannotSendZeroTokens(); IPoolV1 sourcePool = getPoolBySourceToken(destChainSelector, IERC20(tokenAndAmount.token)); @@ -295,8 +295,8 @@ contract OnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCreator { ); // NOTE: pool data validations are outsourced to the FeeQuoter to handle family-specific logic handling - return Internal.RampTokenAmount({ - sourcePoolAddress: abi.encode(sourcePool), + return Internal.EVM2AnyTokenTransfer({ + sourcePoolAddress: address(sourcePool), destTokenAddress: poolReturnData.destTokenAddress, extraData: poolReturnData.destPoolData, amount: tokenAndAmount.amount, diff --git a/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.sol b/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.t.sol similarity index 94% rename from contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.sol rename to contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.t.sol index 8a70bea6c9..12967558ce 100644 --- a/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.sol +++ b/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.t.sol @@ -267,8 +267,16 @@ contract MultiRampsE2E is OnRampSetup, OffRampSetup { router.ccipSend(DEST_CHAIN_SELECTOR, message); vm.pauseGasMetering(); + Internal.Any2EVMTokenTransfer[] memory any2EVMTokenTransfer = + new Internal.Any2EVMTokenTransfer[](message.tokenAmounts.length); for (uint256 i = 0; i < msgEvent.tokenAmounts.length; ++i) { - msgEvent.tokenAmounts[i].destExecData = abi.encode(MAX_TOKEN_POOL_RELEASE_OR_MINT_GAS); + any2EVMTokenTransfer[i] = Internal.Any2EVMTokenTransfer({ + sourcePoolAddress: abi.encode(msgEvent.tokenAmounts[i].sourcePoolAddress), + destTokenAddress: abi.decode(msgEvent.tokenAmounts[i].destTokenAddress, (address)), + extraData: msgEvent.tokenAmounts[i].extraData, + amount: msgEvent.tokenAmounts[i].amount, + destGasAmount: abi.decode(msgEvent.tokenAmounts[i].destExecData, (uint32)) + }); } return Internal.Any2EVMRampMessage({ @@ -283,7 +291,7 @@ contract MultiRampsE2E is OnRampSetup, OffRampSetup { data: msgEvent.data, receiver: abi.decode(msgEvent.receiver, (address)), gasLimit: s_feeQuoter.parseEVMExtraArgsFromBytes(msgEvent.extraArgs, DEST_CHAIN_SELECTOR).gasLimit, - tokenAmounts: msgEvent.tokenAmounts + tokenAmounts: any2EVMTokenTransfer }); } } diff --git a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.t.sol b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.t.sol index 6fd0a40e95..41720898dd 100644 --- a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.t.sol +++ b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoter.t.sol @@ -1749,7 +1749,7 @@ contract FeeQuoter_processMessageArgs is FeeQuoterFeeSetup { s_sourceTokens[0], MAX_MSG_FEES_JUELS, "", - new Internal.RampTokenAmount[](0), + new Internal.EVM2AnyTokenTransfer[](0), new Client.EVMTokenAmount[](0) ); @@ -1773,7 +1773,7 @@ contract FeeQuoter_processMessageArgs is FeeQuoterFeeSetup { feeToken, feeTokenAmount, "", - new Internal.RampTokenAmount[](0), + new Internal.EVM2AnyTokenTransfer[](0), new Client.EVMTokenAmount[](0) ); @@ -1788,7 +1788,12 @@ contract FeeQuoter_processMessageArgs is FeeQuoterFeeSetup { bytes memory convertedExtraArgs, /* destExecDataPerToken */ ) = s_feeQuoter.processMessageArgs( - DEST_CHAIN_SELECTOR, s_sourceTokens[0], 0, "", new Internal.RampTokenAmount[](0), new Client.EVMTokenAmount[](0) + DEST_CHAIN_SELECTOR, + s_sourceTokens[0], + 0, + "", + new Internal.EVM2AnyTokenTransfer[](0), + new Client.EVMTokenAmount[](0) ); assertEq(isOutOfOrderExecution, false); @@ -1809,7 +1814,7 @@ contract FeeQuoter_processMessageArgs is FeeQuoterFeeSetup { s_sourceTokens[0], 0, extraArgs, - new Internal.RampTokenAmount[](0), + new Internal.EVM2AnyTokenTransfer[](0), new Client.EVMTokenAmount[](0) ); @@ -1833,7 +1838,7 @@ contract FeeQuoter_processMessageArgs is FeeQuoterFeeSetup { s_sourceTokens[0], 0, extraArgs, - new Internal.RampTokenAmount[](0), + new Internal.EVM2AnyTokenTransfer[](0), new Client.EVMTokenAmount[](0) ); @@ -1855,7 +1860,7 @@ contract FeeQuoter_processMessageArgs is FeeQuoterFeeSetup { s_sourceTokens[0], MAX_MSG_FEES_JUELS + 1, "", - new Internal.RampTokenAmount[](0), + new Internal.EVM2AnyTokenTransfer[](0), new Client.EVMTokenAmount[](0) ); } @@ -1868,7 +1873,7 @@ contract FeeQuoter_processMessageArgs is FeeQuoterFeeSetup { s_sourceTokens[0], 0, "abcde", - new Internal.RampTokenAmount[](0), + new Internal.EVM2AnyTokenTransfer[](0), new Client.EVMTokenAmount[](0) ); } @@ -1882,7 +1887,7 @@ contract FeeQuoter_processMessageArgs is FeeQuoterFeeSetup { s_sourceTokens[0], 0, abi.encodeWithSelector(Client.EVM_EXTRA_ARGS_V2_TAG, Client.EVMExtraArgsV1({gasLimit: 100})), - new Internal.RampTokenAmount[](0), + new Internal.EVM2AnyTokenTransfer[](0), new Client.EVMTokenAmount[](0) ); } @@ -1894,9 +1899,9 @@ contract FeeQuoter_processMessageArgs is FeeQuoterFeeSetup { sourceTokenAmounts[1].amount = 1e18; sourceTokenAmounts[1].token = CUSTOM_TOKEN_2; - Internal.RampTokenAmount[] memory rampTokenAmounts = new Internal.RampTokenAmount[](2); - rampTokenAmounts[0] = _getSourceTokenData(sourceTokenAmounts[0], s_tokenAdminRegistry, DEST_CHAIN_SELECTOR); - rampTokenAmounts[1] = _getSourceTokenData(sourceTokenAmounts[1], s_tokenAdminRegistry, DEST_CHAIN_SELECTOR); + Internal.EVM2AnyTokenTransfer[] memory tokenAmounts = new Internal.EVM2AnyTokenTransfer[](2); + tokenAmounts[0] = _getSourceTokenData(sourceTokenAmounts[0], s_tokenAdminRegistry, DEST_CHAIN_SELECTOR); + tokenAmounts[1] = _getSourceTokenData(sourceTokenAmounts[1], s_tokenAdminRegistry, DEST_CHAIN_SELECTOR); bytes[] memory expectedDestExecData = new bytes[](2); expectedDestExecData[0] = abi.encode( s_feeQuoterTokenTransferFeeConfigArgs[0].tokenTransferFeeConfigs[0].tokenTransferFeeConfig.destGasOverhead @@ -1906,7 +1911,7 @@ contract FeeQuoter_processMessageArgs is FeeQuoterFeeSetup { // No revert - successful ( /* msgFeeJuels */ , /* isOutOfOrderExecution */, /* convertedExtraArgs */, bytes[] memory destExecData) = s_feeQuoter.processMessageArgs( - DEST_CHAIN_SELECTOR, s_sourceTokens[0], MAX_MSG_FEES_JUELS, "", rampTokenAmounts, sourceTokenAmounts + DEST_CHAIN_SELECTOR, s_sourceTokens[0], MAX_MSG_FEES_JUELS, "", tokenAmounts, sourceTokenAmounts ); for (uint256 i = 0; i < destExecData.length; ++i) { @@ -1919,8 +1924,8 @@ contract FeeQuoter_processMessageArgs is FeeQuoterFeeSetup { sourceTokenAmounts[0].amount = 1e18; sourceTokenAmounts[0].token = s_sourceTokens[0]; - Internal.RampTokenAmount[] memory rampTokenAmounts = new Internal.RampTokenAmount[](1); - rampTokenAmounts[0] = _getSourceTokenData(sourceTokenAmounts[0], s_tokenAdminRegistry, DEST_CHAIN_SELECTOR); + Internal.EVM2AnyTokenTransfer[] memory tokenAmounts = new Internal.EVM2AnyTokenTransfer[](1); + tokenAmounts[0] = _getSourceTokenData(sourceTokenAmounts[0], s_tokenAdminRegistry, DEST_CHAIN_SELECTOR); // Revert due to index out of bounds access vm.expectRevert(); @@ -1930,7 +1935,7 @@ contract FeeQuoter_processMessageArgs is FeeQuoterFeeSetup { s_sourceTokens[0], MAX_MSG_FEES_JUELS, "", - new Internal.RampTokenAmount[](1), + new Internal.EVM2AnyTokenTransfer[](1), new Client.EVMTokenAmount[](0) ); } @@ -1942,25 +1947,25 @@ contract FeeQuoter_processMessageArgs is FeeQuoterFeeSetup { sourceTokenAmounts[0].amount = 1000; sourceTokenAmounts[0].token = sourceETH; - Internal.RampTokenAmount[] memory rampTokenAmounts = new Internal.RampTokenAmount[](1); - rampTokenAmounts[0] = _getSourceTokenData(sourceTokenAmounts[0], s_tokenAdminRegistry, DEST_CHAIN_SELECTOR); + Internal.EVM2AnyTokenTransfer[] memory tokenAmounts = new Internal.EVM2AnyTokenTransfer[](1); + tokenAmounts[0] = _getSourceTokenData(sourceTokenAmounts[0], s_tokenAdminRegistry, DEST_CHAIN_SELECTOR); // No data set, should succeed s_feeQuoter.processMessageArgs( - DEST_CHAIN_SELECTOR, s_sourceTokens[0], MAX_MSG_FEES_JUELS, "", rampTokenAmounts, sourceTokenAmounts + DEST_CHAIN_SELECTOR, s_sourceTokens[0], MAX_MSG_FEES_JUELS, "", tokenAmounts, sourceTokenAmounts ); // Set max data length, should succeed - rampTokenAmounts[0].extraData = new bytes(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES); + tokenAmounts[0].extraData = new bytes(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES); s_feeQuoter.processMessageArgs( - DEST_CHAIN_SELECTOR, s_sourceTokens[0], MAX_MSG_FEES_JUELS, "", rampTokenAmounts, sourceTokenAmounts + DEST_CHAIN_SELECTOR, s_sourceTokens[0], MAX_MSG_FEES_JUELS, "", tokenAmounts, sourceTokenAmounts ); // Set data to max length +1, should revert - rampTokenAmounts[0].extraData = new bytes(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES + 1); + tokenAmounts[0].extraData = new bytes(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES + 1); vm.expectRevert(abi.encodeWithSelector(FeeQuoter.SourceTokenDataTooLarge.selector, sourceETH)); s_feeQuoter.processMessageArgs( - DEST_CHAIN_SELECTOR, s_sourceTokens[0], MAX_MSG_FEES_JUELS, "", rampTokenAmounts, sourceTokenAmounts + DEST_CHAIN_SELECTOR, s_sourceTokens[0], MAX_MSG_FEES_JUELS, "", tokenAmounts, sourceTokenAmounts ); // Set token config to allow larger data @@ -1980,15 +1985,15 @@ contract FeeQuoter_processMessageArgs is FeeQuoterFeeSetup { ); s_feeQuoter.processMessageArgs( - DEST_CHAIN_SELECTOR, s_sourceTokens[0], MAX_MSG_FEES_JUELS, "", rampTokenAmounts, sourceTokenAmounts + DEST_CHAIN_SELECTOR, s_sourceTokens[0], MAX_MSG_FEES_JUELS, "", tokenAmounts, sourceTokenAmounts ); // Set the token data larger than the configured token data, should revert - rampTokenAmounts[0].extraData = new bytes(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES + 32 + 1); + tokenAmounts[0].extraData = new bytes(Pool.CCIP_LOCK_OR_BURN_V1_RET_BYTES + 32 + 1); vm.expectRevert(abi.encodeWithSelector(FeeQuoter.SourceTokenDataTooLarge.selector, sourceETH)); s_feeQuoter.processMessageArgs( - DEST_CHAIN_SELECTOR, s_sourceTokens[0], MAX_MSG_FEES_JUELS, "", rampTokenAmounts, sourceTokenAmounts + DEST_CHAIN_SELECTOR, s_sourceTokens[0], MAX_MSG_FEES_JUELS, "", tokenAmounts, sourceTokenAmounts ); } @@ -1999,13 +2004,13 @@ contract FeeQuoter_processMessageArgs is FeeQuoterFeeSetup { sourceTokenAmounts[0].amount = 1e18; sourceTokenAmounts[0].token = s_sourceTokens[0]; - Internal.RampTokenAmount[] memory rampTokenAmounts = new Internal.RampTokenAmount[](1); - rampTokenAmounts[0] = _getSourceTokenData(sourceTokenAmounts[0], s_tokenAdminRegistry, DEST_CHAIN_SELECTOR); - rampTokenAmounts[0].destTokenAddress = nonEvmAddress; + Internal.EVM2AnyTokenTransfer[] memory tokenAmounts = new Internal.EVM2AnyTokenTransfer[](1); + tokenAmounts[0] = _getSourceTokenData(sourceTokenAmounts[0], s_tokenAdminRegistry, DEST_CHAIN_SELECTOR); + tokenAmounts[0].destTokenAddress = nonEvmAddress; vm.expectRevert(abi.encodeWithSelector(Internal.InvalidEVMAddress.selector, nonEvmAddress)); s_feeQuoter.processMessageArgs( - DEST_CHAIN_SELECTOR, s_sourceTokens[0], MAX_MSG_FEES_JUELS, "", rampTokenAmounts, sourceTokenAmounts + DEST_CHAIN_SELECTOR, s_sourceTokens[0], MAX_MSG_FEES_JUELS, "", tokenAmounts, sourceTokenAmounts ); } } diff --git a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoterSetup.t.sol b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoterSetup.t.sol index 31a92a5ed4..340fe3662d 100644 --- a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoterSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoterSetup.t.sol @@ -122,7 +122,7 @@ contract FeeQuoterSetup is TokenSetup { minFeeUSDCents: 1_00, // 1 USD maxFeeUSDCents: 1000_00, // 1,000 USD deciBps: 2_5, // 2.5 bps, or 0.025% - destGasOverhead: 40_000, + destGasOverhead: 100_000, destBytesOverhead: 32, isEnabled: true }) @@ -135,7 +135,7 @@ contract FeeQuoterSetup is TokenSetup { minFeeUSDCents: 2_00, // 1 USD maxFeeUSDCents: 2000_00, // 1,000 USD deciBps: 10_0, // 10 bps, or 0.1% - destGasOverhead: 1, + destGasOverhead: 95_000, destBytesOverhead: 200, isEnabled: true }) @@ -388,7 +388,7 @@ contract FeeQuoterFeeSetup is FeeQuoterSetup { extraArgs: Client._argsToBytes(extraArgs), feeToken: message.feeToken, feeTokenAmount: feeTokenAmount, - tokenAmounts: new Internal.RampTokenAmount[](message.tokenAmounts.length) + tokenAmounts: new Internal.EVM2AnyTokenTransfer[](message.tokenAmounts.length) }); for (uint256 i = 0; i < message.tokenAmounts.length; ++i) { @@ -404,7 +404,7 @@ contract FeeQuoterFeeSetup is FeeQuoterSetup { Client.EVMTokenAmount memory tokenAmount, TokenAdminRegistry tokenAdminRegistry, uint64 destChainSelector - ) internal view returns (Internal.RampTokenAmount memory) { + ) internal view returns (Internal.EVM2AnyTokenTransfer memory) { address destToken = s_destTokenBySourceToken[tokenAmount.token]; uint32 expectedDestGasAmount; @@ -413,8 +413,8 @@ contract FeeQuoterFeeSetup is FeeQuoterSetup { expectedDestGasAmount = tokenTransferFeeConfig.isEnabled ? tokenTransferFeeConfig.destGasOverhead : DEFAULT_TOKEN_DEST_GAS_OVERHEAD; - return Internal.RampTokenAmount({ - sourcePoolAddress: abi.encode(tokenAdminRegistry.getTokenConfig(tokenAmount.token).tokenPool), + return Internal.EVM2AnyTokenTransfer({ + sourcePoolAddress: tokenAdminRegistry.getTokenConfig(tokenAmount.token).tokenPool, destTokenAddress: abi.encode(destToken), extraData: "", amount: tokenAmount.amount, diff --git a/contracts/src/v0.8/ccip/test/helpers/MessageHasher.sol b/contracts/src/v0.8/ccip/test/helpers/MessageHasher.sol index f27e48b137..deffb617ca 100644 --- a/contracts/src/v0.8/ccip/test/helpers/MessageHasher.sol +++ b/contracts/src/v0.8/ccip/test/helpers/MessageHasher.sol @@ -20,9 +20,15 @@ contract MessageHasher { } function encodeTokenAmountsHashPreimage( - Internal.RampTokenAmount[] memory rampTokenAmounts + Internal.Any2EVMTokenTransfer[] memory tokenAmounts ) public pure returns (bytes memory) { - return abi.encode(rampTokenAmounts); + return abi.encode(tokenAmounts); + } + + function encodeTokenAmountsHashPreimage( + Internal.EVM2AnyTokenTransfer[] memory tokenAmount + ) public pure returns (bytes memory) { + return abi.encode(tokenAmount); } function encodeMetadataHashPreimage( diff --git a/contracts/src/v0.8/ccip/test/helpers/OffRampHelper.sol b/contracts/src/v0.8/ccip/test/helpers/OffRampHelper.sol index 80672bf51e..0e9352a9ef 100644 --- a/contracts/src/v0.8/ccip/test/helpers/OffRampHelper.sol +++ b/contracts/src/v0.8/ccip/test/helpers/OffRampHelper.sol @@ -28,7 +28,7 @@ contract OffRampHelper is OffRamp, IgnoreContractSize { } function releaseOrMintSingleToken( - Internal.RampTokenAmount calldata sourceTokenAmount, + Internal.Any2EVMTokenTransfer calldata sourceTokenAmount, bytes calldata originalSender, address receiver, uint64 sourceChainSelector, @@ -39,7 +39,7 @@ contract OffRampHelper is OffRamp, IgnoreContractSize { } function releaseOrMintTokens( - Internal.RampTokenAmount[] calldata sourceTokenAmounts, + Internal.Any2EVMTokenTransfer[] calldata sourceTokenAmounts, bytes calldata originalSender, address receiver, uint64 sourceChainSelector, diff --git a/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol index 079e0e3c41..1a31691c22 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol @@ -1026,7 +1026,7 @@ contract OffRamp_executeSingleMessage is OffRampSetup { originalSender: message.sender, receiver: message.receiver, amount: message.tokenAmounts[0].amount, - localToken: abi.decode(message.tokenAmounts[0].destTokenAddress, (address)), + localToken: message.tokenAmounts[0].destTokenAddress, remoteChainSelector: SOURCE_CHAIN_SELECTOR_1, sourcePoolAddress: message.tokenAmounts[0].sourcePoolAddress, sourcePoolData: message.tokenAmounts[0].extraData, @@ -1867,13 +1867,13 @@ contract OffRamp_manuallyExecute is OffRampSetup { // send the message that they want to replay. Internal.Any2EVMRampMessage[] memory messages = _generateSingleBasicMessage(SOURCE_CHAIN_SELECTOR_1, ON_RAMP_ADDRESS_1); - messages[0].tokenAmounts = new Internal.RampTokenAmount[](1); - messages[0].tokenAmounts[0] = Internal.RampTokenAmount({ + messages[0].tokenAmounts = new Internal.Any2EVMTokenTransfer[](1); + messages[0].tokenAmounts[0] = Internal.Any2EVMTokenTransfer({ sourcePoolAddress: abi.encode(s_sourcePoolByToken[s_sourceFeeToken]), - destTokenAddress: abi.encode(s_destTokenBySourceToken[s_sourceFeeToken]), + destTokenAddress: s_destTokenBySourceToken[s_sourceFeeToken], extraData: "", amount: tokenAmount, - destExecData: abi.encode(MAX_TOKEN_POOL_RELEASE_OR_MINT_GAS) + destGasAmount: MAX_TOKEN_POOL_RELEASE_OR_MINT_GAS }); messages[0].receiver = address(receiver); @@ -2499,12 +2499,12 @@ contract OffRamp_trialExecute is OffRampSetup { // address 0 has no contract assertEq(address(0).code.length, 0); - message.tokenAmounts[0] = Internal.RampTokenAmount({ + message.tokenAmounts[0] = Internal.Any2EVMTokenTransfer({ sourcePoolAddress: abi.encode(address(0)), - destTokenAddress: abi.encode(address(0)), + destTokenAddress: address(0), extraData: "", amount: message.tokenAmounts[0].amount, - destExecData: abi.encode(DEFAULT_TOKEN_DEST_GAS_OVERHEAD) + destGasAmount: DEFAULT_TOKEN_DEST_GAS_OVERHEAD }); message.header.messageId = _hashMessage(message, ON_RAMP_ADDRESS_1); @@ -2513,16 +2513,16 @@ contract OffRamp_trialExecute is OffRampSetup { (newState, err) = s_offRamp.trialExecute(message, new bytes[](message.tokenAmounts.length), new uint32[](0)); assertEq(uint256(Internal.MessageExecutionState.FAILURE), uint256(newState)); - assertEq(abi.encodeWithSelector(Internal.InvalidEVMAddress.selector, abi.encode(address(0))), err); + assertEq(abi.encodeWithSelector(OffRamp.NotACompatiblePool.selector, address(0)), err); address notAContract = makeAddr("not_a_contract"); - message.tokenAmounts[0] = Internal.RampTokenAmount({ + message.tokenAmounts[0] = Internal.Any2EVMTokenTransfer({ sourcePoolAddress: abi.encode(address(0)), - destTokenAddress: abi.encode(notAContract), + destTokenAddress: notAContract, extraData: "", amount: message.tokenAmounts[0].amount, - destExecData: abi.encode(DEFAULT_TOKEN_DEST_GAS_OVERHEAD) + destGasAmount: DEFAULT_TOKEN_DEST_GAS_OVERHEAD }); message.header.messageId = _hashMessage(message, ON_RAMP_ADDRESS_1); @@ -2549,12 +2549,12 @@ contract OffRamp_releaseOrMintSingleToken is OffRampSetup { IERC20 dstToken1 = IERC20(s_destTokenBySourceToken[token]); uint256 startingBalance = dstToken1.balanceOf(OWNER); - Internal.RampTokenAmount memory tokenAmount = Internal.RampTokenAmount({ + Internal.Any2EVMTokenTransfer memory tokenAmount = Internal.Any2EVMTokenTransfer({ sourcePoolAddress: abi.encode(s_sourcePoolByToken[token]), - destTokenAddress: abi.encode(s_destTokenBySourceToken[token]), + destTokenAddress: s_destTokenBySourceToken[token], extraData: "", amount: amount, - destExecData: abi.encode(DEFAULT_TOKEN_DEST_GAS_OVERHEAD) + destGasAmount: DEFAULT_TOKEN_DEST_GAS_OVERHEAD }); vm.expectCall( @@ -2583,12 +2583,12 @@ contract OffRamp_releaseOrMintSingleToken is OffRampSetup { uint256 amount = 123123; address token = s_sourceTokens[0]; - Internal.RampTokenAmount memory tokenAmount = Internal.RampTokenAmount({ + Internal.Any2EVMTokenTransfer memory tokenAmount = Internal.Any2EVMTokenTransfer({ sourcePoolAddress: abi.encode(s_sourcePoolByToken[token]), - destTokenAddress: abi.encode(s_destTokenBySourceToken[token]), + destTokenAddress: s_destTokenBySourceToken[token], extraData: "", amount: amount, - destExecData: abi.encode(DEFAULT_TOKEN_DEST_GAS_OVERHEAD) + destGasAmount: DEFAULT_TOKEN_DEST_GAS_OVERHEAD }); // Mock the call so returns 2 slots of data @@ -2605,12 +2605,12 @@ contract OffRamp_releaseOrMintSingleToken is OffRampSetup { uint256 amount = 123123; address token = s_sourceTokens[0]; - Internal.RampTokenAmount memory tokenAmount = Internal.RampTokenAmount({ + Internal.Any2EVMTokenTransfer memory tokenAmount = Internal.Any2EVMTokenTransfer({ sourcePoolAddress: abi.encode(s_sourcePoolByToken[token]), - destTokenAddress: abi.encode(s_destTokenBySourceToken[token]), + destTokenAddress: s_destTokenBySourceToken[token], extraData: "", amount: amount, - destExecData: abi.encode(DEFAULT_TOKEN_DEST_GAS_OVERHEAD) + destGasAmount: DEFAULT_TOKEN_DEST_GAS_OVERHEAD }); bytes memory revertData = "failed to balanceOf"; @@ -2630,12 +2630,12 @@ contract OffRamp_releaseOrMintSingleToken is OffRampSetup { address token = s_sourceTokens[0]; uint256 mockedStaticBalance = 50000; - Internal.RampTokenAmount memory tokenAmount = Internal.RampTokenAmount({ + Internal.Any2EVMTokenTransfer memory tokenAmount = Internal.Any2EVMTokenTransfer({ sourcePoolAddress: abi.encode(s_sourcePoolByToken[token]), - destTokenAddress: abi.encode(s_destTokenBySourceToken[token]), + destTokenAddress: s_destTokenBySourceToken[token], extraData: "", amount: amount, - destExecData: abi.encode(DEFAULT_TOKEN_DEST_GAS_OVERHEAD) + destGasAmount: DEFAULT_TOKEN_DEST_GAS_OVERHEAD }); vm.mockCall( @@ -2658,12 +2658,12 @@ contract OffRamp_releaseOrMintSingleToken is OffRampSetup { address token = s_sourceTokens[0]; uint256 mockedStaticBalance = 50000; - Internal.RampTokenAmount memory tokenAmount = Internal.RampTokenAmount({ + Internal.Any2EVMTokenTransfer memory tokenAmount = Internal.Any2EVMTokenTransfer({ sourcePoolAddress: abi.encode(s_sourcePoolByToken[token]), - destTokenAddress: abi.encode(s_destTokenBySourceToken[token]), + destTokenAddress: s_destTokenBySourceToken[token], extraData: "", amount: amount, - destExecData: abi.encode(DEFAULT_TOKEN_DEST_GAS_OVERHEAD) + destGasAmount: DEFAULT_TOKEN_DEST_GAS_OVERHEAD }); // This should make the call fail if it does not skip the check @@ -2686,12 +2686,12 @@ contract OffRamp_releaseOrMintSingleToken is OffRampSetup { bytes memory originalSender = abi.encode(OWNER); bytes memory offchainTokenData = abi.encode(keccak256("offchainTokenData")); - Internal.RampTokenAmount memory tokenAmount = Internal.RampTokenAmount({ + Internal.Any2EVMTokenTransfer memory tokenAmount = Internal.Any2EVMTokenTransfer({ sourcePoolAddress: abi.encode(s_sourcePoolByToken[token]), - destTokenAddress: abi.encode(destToken), + destTokenAddress: destToken, extraData: "", amount: amount, - destExecData: abi.encode(DEFAULT_TOKEN_DEST_GAS_OVERHEAD) + destGasAmount: DEFAULT_TOKEN_DEST_GAS_OVERHEAD }); // Address(0) should always revert @@ -2729,12 +2729,12 @@ contract OffRamp_releaseOrMintSingleToken is OffRampSetup { bytes memory originalSender = abi.encode(OWNER); bytes memory offchainTokenData = abi.encode(keccak256("offchainTokenData")); - Internal.RampTokenAmount memory tokenAmount = Internal.RampTokenAmount({ + Internal.Any2EVMTokenTransfer memory tokenAmount = Internal.Any2EVMTokenTransfer({ sourcePoolAddress: abi.encode(s_sourcePoolByToken[token]), - destTokenAddress: abi.encode(destToken), + destTokenAddress: destToken, extraData: "", amount: amount, - destExecData: abi.encode(DEFAULT_TOKEN_DEST_GAS_OVERHEAD) + destGasAmount: DEFAULT_TOKEN_DEST_GAS_OVERHEAD }); bytes memory revertData = "call reverted :o"; @@ -2764,7 +2764,7 @@ contract OffRamp_releaseOrMintTokens is OffRampSetup { bytes[] memory offchainTokenData = new bytes[](srcTokenAmounts.length); offchainTokenData[0] = abi.encode(0x12345678); - Internal.RampTokenAmount[] memory sourceTokenAmounts = _getDefaultSourceTokenData(srcTokenAmounts); + Internal.Any2EVMTokenTransfer[] memory sourceTokenAmounts = _getDefaultSourceTokenData(srcTokenAmounts); vm.expectCall( s_destPoolBySourceToken[srcTokenAmounts[0].token], @@ -2800,7 +2800,7 @@ contract OffRamp_releaseOrMintTokens is OffRampSetup { bytes[] memory offchainTokenData = new bytes[](srcTokenAmounts.length); offchainTokenData[0] = abi.encode(0x12345678); - Internal.RampTokenAmount[] memory sourceTokenAmounts = _getDefaultSourceTokenData(srcTokenAmounts); + Internal.Any2EVMTokenTransfer[] memory sourceTokenAmounts = _getDefaultSourceTokenData(srcTokenAmounts); vm.expectCall( s_destPoolBySourceToken[srcTokenAmounts[0].token], @@ -2838,7 +2838,7 @@ contract OffRamp_releaseOrMintTokens is OffRampSetup { bytes[] memory offchainTokenData = new bytes[](srcTokenAmounts.length); - Internal.RampTokenAmount[] memory sourceTokenAmounts = _getDefaultSourceTokenData(srcTokenAmounts); + Internal.Any2EVMTokenTransfer[] memory sourceTokenAmounts = _getDefaultSourceTokenData(srcTokenAmounts); address pool = s_destPoolBySourceToken[srcTokenAmounts[1].token]; address destToken = s_destTokenBySourceToken[srcTokenAmounts[1].token]; @@ -2878,7 +2878,7 @@ contract OffRamp_releaseOrMintTokens is OffRampSetup { srcTokenAmounts[0].amount = amount; bytes[] memory offchainTokenData = new bytes[](srcTokenAmounts.length); - Internal.RampTokenAmount[] memory sourceTokenAmounts = _getDefaultSourceTokenData(srcTokenAmounts); + Internal.Any2EVMTokenTransfer[] memory sourceTokenAmounts = _getDefaultSourceTokenData(srcTokenAmounts); vm.mockCall( s_destPoolBySourceToken[srcTokenAmounts[0].token], @@ -2906,33 +2906,17 @@ contract OffRamp_releaseOrMintTokens is OffRampSetup { ); } - function test_releaseOrMintTokens_InvalidEVMAddress_Revert() public { - Client.EVMTokenAmount[] memory srcTokenAmounts = _getCastedSourceEVMTokenAmountsWithZeroAmounts(); - - bytes[] memory offchainTokenData = new bytes[](srcTokenAmounts.length); - Internal.RampTokenAmount[] memory sourceTokenAmounts = _getDefaultSourceTokenData(srcTokenAmounts); - bytes memory wrongAddress = abi.encode(address(1000), address(10000), address(10000)); - - sourceTokenAmounts[0].destTokenAddress = wrongAddress; - - vm.expectRevert(abi.encodeWithSelector(Internal.InvalidEVMAddress.selector, wrongAddress)); - - s_offRamp.releaseOrMintTokens( - sourceTokenAmounts, abi.encode(OWNER), OWNER, SOURCE_CHAIN_SELECTOR_1, offchainTokenData, new uint32[](0) - ); - } - function test__releaseOrMintTokens_PoolIsNotAPool_Reverts() public { // The offRamp is a contract, but not a pool address fakePoolAddress = address(s_offRamp); - Internal.RampTokenAmount[] memory sourceTokenAmounts = new Internal.RampTokenAmount[](1); - sourceTokenAmounts[0] = Internal.RampTokenAmount({ + Internal.Any2EVMTokenTransfer[] memory sourceTokenAmounts = new Internal.Any2EVMTokenTransfer[](1); + sourceTokenAmounts[0] = Internal.Any2EVMTokenTransfer({ sourcePoolAddress: abi.encode(fakePoolAddress), - destTokenAddress: abi.encode(s_offRamp), + destTokenAddress: address(s_offRamp), extraData: "", amount: 1, - destExecData: abi.encode(DEFAULT_TOKEN_DEST_GAS_OVERHEAD) + destGasAmount: DEFAULT_TOKEN_DEST_GAS_OVERHEAD }); vm.expectRevert(abi.encodeWithSelector(OffRamp.NotACompatiblePool.selector, address(0))); @@ -2949,7 +2933,7 @@ contract OffRamp_releaseOrMintTokens is OffRampSetup { bytes[] memory offchainTokenData = new bytes[](srcTokenAmounts.length); offchainTokenData[0] = abi.encode(0x12345678); - Internal.RampTokenAmount[] memory sourceTokenAmounts = _getDefaultSourceTokenData(srcTokenAmounts); + Internal.Any2EVMTokenTransfer[] memory sourceTokenAmounts = _getDefaultSourceTokenData(srcTokenAmounts); vm.expectCall( s_destPoolBySourceToken[srcTokenAmounts[0].token], @@ -2976,18 +2960,18 @@ contract OffRamp_releaseOrMintTokens is OffRampSetup { /// forge-config: default.fuzz.runs = 32 /// forge-config: ccip.fuzz.runs = 1024 // Uint256 gives a good range of values to test, both inside and outside of the eth address space. - function test_Fuzz__releaseOrMintTokens_AnyRevertIsCaught_Success(uint256 destPool) public { + function test_Fuzz__releaseOrMintTokens_AnyRevertIsCaught_Success(address destPool) public { // Input 447301751254033913445893214690834296930546521452, which is 0x4E59B44847B379578588920CA78FBF26C0B4956C // triggers some Create2Deployer and causes it to fail - vm.assume(destPool != 447301751254033913445893214690834296930546521452); + vm.assume(destPool != 0x4e59b44847b379578588920cA78FbF26c0B4956C); bytes memory unusedVar = abi.encode(makeAddr("unused")); - Internal.RampTokenAmount[] memory sourceTokenAmounts = new Internal.RampTokenAmount[](1); - sourceTokenAmounts[0] = Internal.RampTokenAmount({ + Internal.Any2EVMTokenTransfer[] memory sourceTokenAmounts = new Internal.Any2EVMTokenTransfer[](1); + sourceTokenAmounts[0] = Internal.Any2EVMTokenTransfer({ sourcePoolAddress: unusedVar, - destTokenAddress: abi.encode(destPool), + destTokenAddress: destPool, extraData: unusedVar, amount: 1, - destExecData: abi.encode(DEFAULT_TOKEN_DEST_GAS_OVERHEAD) + destGasAmount: DEFAULT_TOKEN_DEST_GAS_OVERHEAD }); try s_offRamp.releaseOrMintTokens( @@ -3002,7 +2986,7 @@ contract OffRamp_releaseOrMintTokens is OffRampSetup { "Expected TokenHandlingError or InvalidEVMAddress" ); - if (destPool > type(uint160).max) { + if (uint160(destPool) > type(uint160).max) { assertEq(reason, abi.encodeWithSelector(Internal.InvalidEVMAddress.selector, abi.encode(destPool))); } } diff --git a/contracts/src/v0.8/ccip/test/offRamp/OffRampSetup.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRampSetup.t.sol index ea3f56bc08..6b18992f69 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/OffRampSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRampSetup.t.sol @@ -238,9 +238,9 @@ contract OffRampSetup is FeeQuoterSetup, MultiOCR3BaseSetup { Client.EVMTokenAmount[] memory destTokenAmounts = new Client.EVMTokenAmount[](numberOfTokens); for (uint256 i = 0; i < numberOfTokens; ++i) { - Internal.RampTokenAmount memory tokenAmount = original.tokenAmounts[i]; + Internal.Any2EVMTokenTransfer memory tokenAmount = original.tokenAmounts[i]; - address destPoolAddress = abi.decode(tokenAmount.destTokenAddress, (address)); + address destPoolAddress = tokenAmount.destTokenAddress; TokenPool pool = TokenPool(destPoolAddress); destTokenAmounts[i].token = address(pool.getToken()); destTokenAmounts[i].amount = tokenAmount.amount; @@ -285,16 +285,17 @@ contract OffRampSetup is FeeQuoterSetup, MultiOCR3BaseSetup { ) internal view returns (Internal.Any2EVMRampMessage memory) { bytes memory data = abi.encode(0); - Internal.RampTokenAmount[] memory rampTokenAmounts = new Internal.RampTokenAmount[](tokenAmounts.length); + Internal.Any2EVMTokenTransfer[] memory any2EVMTokenTransfer = + new Internal.Any2EVMTokenTransfer[](tokenAmounts.length); // Correctly set the TokenDataPayload for each token. Tokens have to be set up in the TokenSetup. for (uint256 i = 0; i < tokenAmounts.length; ++i) { - rampTokenAmounts[i] = Internal.RampTokenAmount({ + any2EVMTokenTransfer[i] = Internal.Any2EVMTokenTransfer({ sourcePoolAddress: abi.encode(s_sourcePoolByToken[tokenAmounts[i].token]), - destTokenAddress: abi.encode(s_destTokenBySourceToken[tokenAmounts[i].token]), + destTokenAddress: s_destTokenBySourceToken[tokenAmounts[i].token], extraData: "", amount: tokenAmounts[i].amount, - destExecData: abi.encode(DEFAULT_TOKEN_DEST_GAS_OVERHEAD) + destGasAmount: DEFAULT_TOKEN_DEST_GAS_OVERHEAD }); } @@ -309,7 +310,7 @@ contract OffRampSetup is FeeQuoterSetup, MultiOCR3BaseSetup { sender: abi.encode(OWNER), data: data, receiver: address(s_receiver), - tokenAmounts: rampTokenAmounts, + tokenAmounts: any2EVMTokenTransfer, gasLimit: GAS_LIMIT }); @@ -398,15 +399,15 @@ contract OffRampSetup is FeeQuoterSetup, MultiOCR3BaseSetup { function _getDefaultSourceTokenData( Client.EVMTokenAmount[] memory srcTokenAmounts - ) internal view returns (Internal.RampTokenAmount[] memory) { - Internal.RampTokenAmount[] memory sourceTokenData = new Internal.RampTokenAmount[](srcTokenAmounts.length); + ) internal view returns (Internal.Any2EVMTokenTransfer[] memory) { + Internal.Any2EVMTokenTransfer[] memory sourceTokenData = new Internal.Any2EVMTokenTransfer[](srcTokenAmounts.length); for (uint256 i = 0; i < srcTokenAmounts.length; ++i) { - sourceTokenData[i] = Internal.RampTokenAmount({ + sourceTokenData[i] = Internal.Any2EVMTokenTransfer({ sourcePoolAddress: abi.encode(s_sourcePoolByToken[srcTokenAmounts[i].token]), - destTokenAddress: abi.encode(s_destTokenBySourceToken[srcTokenAmounts[i].token]), + destTokenAddress: s_destTokenBySourceToken[srcTokenAmounts[i].token], extraData: "", amount: srcTokenAmounts[i].amount, - destExecData: abi.encode(DEFAULT_TOKEN_DEST_GAS_OVERHEAD) + destGasAmount: DEFAULT_TOKEN_DEST_GAS_OVERHEAD }); } return sourceTokenData; diff --git a/core/gethwrappers/ccip/generated/ccip_reader_tester/ccip_reader_tester.go b/core/gethwrappers/ccip/generated/ccip_reader_tester/ccip_reader_tester.go index fa9224ef21..127de4a3c8 100644 --- a/core/gethwrappers/ccip/generated/ccip_reader_tester/ccip_reader_tester.go +++ b/core/gethwrappers/ccip/generated/ccip_reader_tester/ccip_reader_tester.go @@ -43,7 +43,15 @@ type InternalEVM2AnyRampMessage struct { ExtraArgs []byte FeeToken common.Address FeeTokenAmount *big.Int - TokenAmounts []InternalRampTokenAmount + TokenAmounts []InternalEVM2AnyTokenTransfer +} + +type InternalEVM2AnyTokenTransfer struct { + SourcePoolAddress common.Address + DestTokenAddress []byte + ExtraData []byte + Amount *big.Int + DestExecData []byte } type InternalGasPriceUpdate struct { @@ -72,14 +80,6 @@ type InternalRampMessageHeader struct { Nonce uint64 } -type InternalRampTokenAmount struct { - SourcePoolAddress []byte - DestTokenAddress []byte - ExtraData []byte - Amount *big.Int - DestExecData []byte -} - type InternalTokenPriceUpdate struct { SourceToken common.Address UsdPerToken *big.Int @@ -99,8 +99,8 @@ type OffRampSourceChainConfig struct { } var CCIPReaderTesterMetaData = &bind.MetaData{ - ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"CCIPSendRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"structIRMNV2.Signature[]\",\"name\":\"rmnSignatures\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"report\",\"type\":\"tuple\"}],\"name\":\"CommitReportAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"name\":\"ExecutionStateChanged\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"emitCCIPSendRequested\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"structIRMNV2.Signature[]\",\"name\":\"rmnSignatures\",\"type\":\"tuple[]\"}],\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"report\",\"type\":\"tuple\"}],\"name\":\"emitCommitReportAccepted\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"name\":\"emitExecutionStateChanged\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getExpectedNextSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"getSourceChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"setDestChainSeqNr\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"sourceChainConfig\",\"type\":\"tuple\"}],\"name\":\"setSourceChainConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x608060405234801561001057600080fd5b506113f4806100206000396000f3fe608060405234801561001057600080fd5b506004361061006d5760003560e01c80634cf66e361461007257806385096da9146100875780639041be3d1461009a578063bfc9b789146100ca578063c1a5a355146100dd578063e83eabba14610119578063e9d68a8e1461012c575b600080fd5b610085610080366004610571565b61014c565b005b6100856100953660046107e9565b6101a1565b6100ad6100a8366004610917565b6101e6565b6040516001600160401b0390911681526020015b60405180910390f35b6100856100d8366004610b51565b610215565b6100856100eb366004610cdb565b6001600160401b03918216600090815260016020526040902080546001600160401b03191691909216179055565b610085610127366004610d0e565b61024f565b61013f61013a366004610917565b6102db565b6040516100c19190610e0f565b82846001600160401b0316866001600160401b03167f8c324ce1367b83031769f6a813e3bb4c117aba2185789d66b98b791405be6df28585604051610192929190610e67565b60405180910390a45050505050565b816001600160401b03167fcae3d9f68a9ed33d0a770e9bcc6fc25d4041dd6391e6cd8015546547a3c93140826040516101da9190610f6a565b60405180910390a25050565b6001600160401b038082166000908152600160208190526040822054919261020f92169061106c565b92915050565b7f23bc80217a08968cec0790cd045b396fa7eea0a21af469e603329940b883d86d8160405161024491906111cb565b60405180910390a150565b6001600160401b0380831660009081526020818152604091829020845181549286015193860151909416600160a81b02600160a81b600160e81b0319931515600160a01b026001600160a81b03199093166001600160a01b03909516949094179190911791909116919091178155606082015182919060018201906102d49082611328565b5050505050565b60408051608080820183526000808352602080840182905283850182905260608085018190526001600160401b038781168452838352928690208651948501875280546001600160a01b0381168652600160a01b810460ff16151593860193909352600160a81b9092049092169483019490945260018401805493949293918401916103669061129d565b80601f01602080910402602001604051908101604052809291908181526020018280546103929061129d565b80156103df5780601f106103b4576101008083540402835291602001916103df565b820191906000526020600020905b8154815290600101906020018083116103c257829003601f168201915b5050505050815250509050919050565b80356001600160401b038116811461040657600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60405160a081016001600160401b03811182821017156104435761044361040b565b60405290565b60405161010081016001600160401b03811182821017156104435761044361040b565b604080519081016001600160401b03811182821017156104435761044361040b565b604051606081016001600160401b03811182821017156104435761044361040b565b604051608081016001600160401b03811182821017156104435761044361040b565b604051601f8201601f191681016001600160401b03811182821017156104fa576104fa61040b565b604052919050565b600082601f83011261051357600080fd5b81356001600160401b0381111561052c5761052c61040b565b61053f601f8201601f19166020016104d2565b81815284602083860101111561055457600080fd5b816020850160208301376000918101602001919091529392505050565b600080600080600060a0868803121561058957600080fd5b610592866103ef565b94506105a0602087016103ef565b9350604086013592506060860135600481106105bb57600080fd5b915060808601356001600160401b038111156105d657600080fd5b6105e288828901610502565b9150509295509295909350565b600060a0828403121561060157600080fd5b610609610421565b90508135815261061b602083016103ef565b602082015261062c604083016103ef565b604082015261063d606083016103ef565b606082015261064e608083016103ef565b608082015292915050565b6001600160a01b038116811461066e57600080fd5b50565b803561040681610659565b60006001600160401b038211156106955761069561040b565b5060051b60200190565b600082601f8301126106b057600080fd5b813560206106c56106c08361067c565b6104d2565b82815260059290921b840181019181810190868411156106e457600080fd5b8286015b848110156107de5780356001600160401b03808211156107085760008081fd5b9088019060a0828b03601f19018113156107225760008081fd5b61072a610421565b878401358381111561073c5760008081fd5b61074a8d8a83880101610502565b825250604080850135848111156107615760008081fd5b61076f8e8b83890101610502565b8a84015250606080860135858111156107885760008081fd5b6107968f8c838a0101610502565b838501525060809150818601358184015250828501359250838311156107bc5760008081fd5b6107ca8d8a85880101610502565b9082015286525050509183019183016106e8565b509695505050505050565b600080604083850312156107fc57600080fd5b610805836103ef565b915060208301356001600160401b038082111561082157600080fd5b90840190610180828703121561083657600080fd5b61083e610449565b61084887846105ef565b815261085660a08401610671565b602082015260c08301358281111561086d57600080fd5b61087988828601610502565b60408301525060e08301358281111561089157600080fd5b61089d88828601610502565b606083015250610100830135828111156108b657600080fd5b6108c288828601610502565b6080830152506108d56101208401610671565b60a082015261014083013560c0820152610160830135828111156108f857600080fd5b6109048882860161069f565b60e0830152508093505050509250929050565b60006020828403121561092957600080fd5b610932826103ef565b9392505050565b80356001600160e01b038116811461040657600080fd5b600082601f83011261096157600080fd5b813560206109716106c08361067c565b82815260069290921b8401810191818101908684111561099057600080fd5b8286015b848110156107de57604081890312156109ad5760008081fd5b6109b561046c565b6109be826103ef565b81526109cb858301610939565b81860152835291830191604001610994565b600082601f8301126109ee57600080fd5b813560206109fe6106c08361067c565b82815260059290921b84018101918181019086841115610a1d57600080fd5b8286015b848110156107de5780356001600160401b0380821115610a415760008081fd5b9088019060a0828b03601f1901811315610a5b5760008081fd5b610a63610421565b610a6e8885016103ef565b815260408085013584811115610a845760008081fd5b610a928e8b83890101610502565b8a8401525060609350610aa68486016103ef565b908201526080610ab78582016103ef565b93820193909352920135908201528352918301918301610a21565b600082601f830112610ae357600080fd5b81356020610af36106c08361067c565b82815260069290921b84018101918181019086841115610b1257600080fd5b8286015b848110156107de5760408189031215610b2f5760008081fd5b610b3761046c565b813581528482013585820152835291830191604001610b16565b60006020808385031215610b6457600080fd5b82356001600160401b0380821115610b7b57600080fd5b9084019060608287031215610b8f57600080fd5b610b9761048e565b823582811115610ba657600080fd5b83016040818903811315610bb957600080fd5b610bc161046c565b823585811115610bd057600080fd5b8301601f81018b13610be157600080fd5b8035610bef6106c08261067c565b81815260069190911b8201890190898101908d831115610c0e57600080fd5b928a01925b82841015610c5e5785848f031215610c2b5760008081fd5b610c3361046c565b8435610c3e81610659565b8152610c4b858d01610939565b818d0152825292850192908a0190610c13565b845250505082870135915084821115610c7657600080fd5b610c828a838501610950565b81880152835250508284013582811115610c9b57600080fd5b610ca7888286016109dd565b85830152506040830135935081841115610cc057600080fd5b610ccc87858501610ad2565b60408201529695505050505050565b60008060408385031215610cee57600080fd5b610cf7836103ef565b9150610d05602084016103ef565b90509250929050565b60008060408385031215610d2157600080fd5b610d2a836103ef565b915060208301356001600160401b0380821115610d4657600080fd5b9084019060808287031215610d5a57600080fd5b610d626104b0565b8235610d6d81610659565b815260208301358015158114610d8257600080fd5b6020820152610d93604084016103ef565b6040820152606083013582811115610daa57600080fd5b610db688828601610502565b6060830152508093505050509250929050565b6000815180845260005b81811015610def57602081850181015186830182015201610dd3565b506000602082860101526020601f19601f83011685010191505092915050565b602080825282516001600160a01b03168282015282015115156040808301919091528201516001600160401b0316606080830191909152820151608080830152600090610e5f60a0840182610dc9565b949350505050565b600060048410610e8757634e487b7160e01b600052602160045260246000fd5b83825260406020830152610e5f6040830184610dc9565b6001600160a01b03169052565b600082825180855260208086019550808260051b84010181860160005b84811015610f5d57601f19868403018952815160a08151818652610eee82870182610dc9565b9150508582015185820387870152610f068282610dc9565b91505060408083015186830382880152610f208382610dc9565b92505050606080830151818701525060808083015192508582038187015250610f498183610dc9565b9a86019a9450505090830190600101610ec8565b5090979650505050505050565b60208152610fb7602082018351805182526020808201516001600160401b039081169184019190915260408083015182169084015260608083015182169084015260809182015116910152565b60006020830151610fcb60c0840182610e9e565b5060408301516101808060e0850152610fe86101a0850183610dc9565b91506060850151601f1980868503016101008701526110078483610dc9565b93506080870151915080868503016101208701526110258483610dc9565b935060a0870151915061103c610140870183610e9e565b60c087015161016087015260e08701519150808685030183870152506110628382610eab565b9695505050505050565b6001600160401b0381811683821601908082111561109a57634e487b7160e01b600052601160045260246000fd5b5092915050565b60008151808452602080850194506020840160005b838110156110ef57815180516001600160401b031688528301516001600160e01b031683880152604090960195908201906001016110b6565b509495945050505050565b600082825180855260208086019550808260051b84010181860160005b84811015610f5d57858303601f19018952815180516001600160401b0390811685528582015160a0878701819052919061115383880182610dc9565b60408581015184169089015260608086015190931692880192909252506080928301519290950191909152509783019790830190600101611117565b60008151808452602080850194506020840160005b838110156110ef5781518051885283015183880152604090960195908201906001016111a4565b602080825282516060838301528051604060808501819052815160c086018190526000949392840191859160e08801905b8084101561123757845180516001600160a01b031683528701516001600160e01b0316878301529386019360019390930192908201906111fc565b5093850151878503607f190160a08901529361125381866110a1565b945050505050818501519150601f198085830301604086015261127682846110fa565b9250604086015191508085840301606086015250611294828261118f565b95945050505050565b600181811c908216806112b157607f821691505b6020821081036112d157634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115611323576000816000526020600020601f850160051c810160208610156113005750805b601f850160051c820191505b8181101561131f5782815560010161130c565b5050505b505050565b81516001600160401b038111156113415761134161040b565b6113558161134f845461129d565b846112d7565b602080601f83116001811461138a57600084156113725750858301515b600019600386901b1c1916600185901b17855561131f565b600085815260208120601f198616915b828110156113b95788860151825594840194600190910190840161139a565b50858210156113d75787850151600019600388901b60f8161c191681555b5050505050600190811b0190555056fea164736f6c6343000818000a", + ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"sourcePoolAddress\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.EVM2AnyTokenTransfer[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"CCIPSendRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"structIRMNV2.Signature[]\",\"name\":\"rmnSignatures\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"report\",\"type\":\"tuple\"}],\"name\":\"CommitReportAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"name\":\"ExecutionStateChanged\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"sourcePoolAddress\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.EVM2AnyTokenTransfer[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"emitCCIPSendRequested\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"structIRMNV2.Signature[]\",\"name\":\"rmnSignatures\",\"type\":\"tuple[]\"}],\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"report\",\"type\":\"tuple\"}],\"name\":\"emitCommitReportAccepted\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"name\":\"emitExecutionStateChanged\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getExpectedNextSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"getSourceChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"setDestChainSeqNr\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"sourceChainConfig\",\"type\":\"tuple\"}],\"name\":\"setSourceChainConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x608060405234801561001057600080fd5b506113d9806100206000396000f3fe608060405234801561001057600080fd5b506004361061006d5760003560e01c80634cf66e36146100725780639041be3d14610087578063bfc9b789146100b7578063c1a5a355146100ca578063e4d0223414610106578063e83eabba14610119578063e9d68a8e1461012c575b600080fd5b610085610080366004610571565b61014c565b005b61009a6100953660046105ef565b6101a1565b6040516001600160401b0390911681526020015b60405180910390f35b6100856100c536600461087f565b6101d0565b6100856100d8366004610a09565b6001600160401b03918216600090815260016020526040902080546001600160401b03191691909216179055565b610085610114366004610bca565b61020a565b610085610127366004610cf8565b61024f565b61013f61013a3660046105ef565b6102db565b6040516100ae9190610df9565b82846001600160401b0316866001600160401b03167f8c324ce1367b83031769f6a813e3bb4c117aba2185789d66b98b791405be6df28585604051610192929190610e51565b60405180910390a45050505050565b6001600160401b03808216600090815260016020819052604082205491926101ca921690610e88565b92915050565b7f23bc80217a08968cec0790cd045b396fa7eea0a21af469e603329940b883d86d816040516101ff9190611001565b60405180910390a150565b816001600160401b03167fe07a589f12eccf1bc0f7421666687a6986a0c8dbbdc877d1af562a97ba60ecfd826040516102439190611180565b60405180910390a25050565b6001600160401b0380831660009081526020818152604091829020845181549286015193860151909416600160a81b02600160a81b600160e81b0319931515600160a01b026001600160a81b03199093166001600160a01b03909516949094179190911791909116919091178155606082015182919060018201906102d4908261130d565b5050505050565b60408051608080820183526000808352602080840182905283850182905260608085018190526001600160401b038781168452838352928690208651948501875280546001600160a01b0381168652600160a01b810460ff16151593860193909352600160a81b90920490921694830194909452600184018054939492939184019161036690611282565b80601f016020809104026020016040519081016040528092919081815260200182805461039290611282565b80156103df5780601f106103b4576101008083540402835291602001916103df565b820191906000526020600020905b8154815290600101906020018083116103c257829003601f168201915b5050505050815250509050919050565b80356001600160401b038116811461040657600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b03811182821017156104435761044361040b565b60405290565b60405160a081016001600160401b03811182821017156104435761044361040b565b604051606081016001600160401b03811182821017156104435761044361040b565b60405161010081016001600160401b03811182821017156104435761044361040b565b604051608081016001600160401b03811182821017156104435761044361040b565b604051601f8201601f191681016001600160401b03811182821017156104fa576104fa61040b565b604052919050565b600082601f83011261051357600080fd5b81356001600160401b0381111561052c5761052c61040b565b61053f601f8201601f19166020016104d2565b81815284602083860101111561055457600080fd5b816020850160208301376000918101602001919091529392505050565b600080600080600060a0868803121561058957600080fd5b610592866103ef565b94506105a0602087016103ef565b9350604086013592506060860135600481106105bb57600080fd5b915060808601356001600160401b038111156105d657600080fd5b6105e288828901610502565b9150509295509295909350565b60006020828403121561060157600080fd5b61060a826103ef565b9392505050565b60006001600160401b0382111561062a5761062a61040b565b5060051b60200190565b6001600160a01b038116811461064957600080fd5b50565b803561040681610634565b80356001600160e01b038116811461040657600080fd5b600082601f83011261067f57600080fd5b8135602061069461068f83610611565b6104d2565b82815260069290921b840181019181810190868411156106b357600080fd5b8286015b8481101561070057604081890312156106d05760008081fd5b6106d8610421565b6106e1826103ef565b81526106ee858301610657565b818601528352918301916040016106b7565b509695505050505050565b600082601f83011261071c57600080fd5b8135602061072c61068f83610611565b82815260059290921b8401810191818101908684111561074b57600080fd5b8286015b848110156107005780356001600160401b038082111561076f5760008081fd5b9088019060a0828b03601f19018113156107895760008081fd5b610791610449565b61079c8885016103ef565b8152604080850135848111156107b25760008081fd5b6107c08e8b83890101610502565b8a84015250606093506107d48486016103ef565b9082015260806107e58582016103ef565b9382019390935292013590820152835291830191830161074f565b600082601f83011261081157600080fd5b8135602061082161068f83610611565b82815260069290921b8401810191818101908684111561084057600080fd5b8286015b84811015610700576040818903121561085d5760008081fd5b610865610421565b813581528482013585820152835291830191604001610844565b6000602080838503121561089257600080fd5b82356001600160401b03808211156108a957600080fd5b90840190606082870312156108bd57600080fd5b6108c561046b565b8235828111156108d457600080fd5b830160408189038113156108e757600080fd5b6108ef610421565b8235858111156108fe57600080fd5b8301601f81018b1361090f57600080fd5b803561091d61068f82610611565b81815260069190911b8201890190898101908d83111561093c57600080fd5b928a01925b8284101561098c5785848f0312156109595760008081fd5b610961610421565b843561096c81610634565b8152610979858d01610657565b818d0152825292850192908a0190610941565b8452505050828701359150848211156109a457600080fd5b6109b08a83850161066e565b818801528352505082840135828111156109c957600080fd5b6109d58882860161070b565b858301525060408301359350818411156109ee57600080fd5b6109fa87858501610800565b60408201529695505050505050565b60008060408385031215610a1c57600080fd5b610a25836103ef565b9150610a33602084016103ef565b90509250929050565b600060a08284031215610a4e57600080fd5b610a56610449565b905081358152610a68602083016103ef565b6020820152610a79604083016103ef565b6040820152610a8a606083016103ef565b6060820152610a9b608083016103ef565b608082015292915050565b600082601f830112610ab757600080fd5b81356020610ac761068f83610611565b82815260059290921b84018101918181019086841115610ae657600080fd5b8286015b848110156107005780356001600160401b0380821115610b0a5760008081fd5b9088019060a0828b03601f1901811315610b245760008081fd5b610b2c610449565b610b3788850161064c565b815260408085013584811115610b4d5760008081fd5b610b5b8e8b83890101610502565b8a8401525060608086013585811115610b745760008081fd5b610b828f8c838a0101610502565b83850152506080915081860135818401525082850135925083831115610ba85760008081fd5b610bb68d8a85880101610502565b908201528652505050918301918301610aea565b60008060408385031215610bdd57600080fd5b610be6836103ef565b915060208301356001600160401b0380821115610c0257600080fd5b908401906101808287031215610c1757600080fd5b610c1f61048d565b610c298784610a3c565b8152610c3760a0840161064c565b602082015260c083013582811115610c4e57600080fd5b610c5a88828601610502565b60408301525060e083013582811115610c7257600080fd5b610c7e88828601610502565b60608301525061010083013582811115610c9757600080fd5b610ca388828601610502565b608083015250610cb6610120840161064c565b60a082015261014083013560c082015261016083013582811115610cd957600080fd5b610ce588828601610aa6565b60e0830152508093505050509250929050565b60008060408385031215610d0b57600080fd5b610d14836103ef565b915060208301356001600160401b0380821115610d3057600080fd5b9084019060808287031215610d4457600080fd5b610d4c6104b0565b8235610d5781610634565b815260208301358015158114610d6c57600080fd5b6020820152610d7d604084016103ef565b6040820152606083013582811115610d9457600080fd5b610da088828601610502565b6060830152508093505050509250929050565b6000815180845260005b81811015610dd957602081850181015186830182015201610dbd565b506000602082860101526020601f19601f83011685010191505092915050565b602080825282516001600160a01b03168282015282015115156040808301919091528201516001600160401b0316606080830191909152820151608080830152600090610e4960a0840182610db3565b949350505050565b600060048410610e7157634e487b7160e01b600052602160045260246000fd5b83825260406020830152610e496040830184610db3565b6001600160401b03818116838216019080821115610eb657634e487b7160e01b600052601160045260246000fd5b5092915050565b6001600160a01b03169052565b60008151808452602080850194506020840160005b83811015610f1857815180516001600160401b031688528301516001600160e01b03168388015260409096019590820190600101610edf565b509495945050505050565b600082825180855260208086019550808260051b84010181860160005b84811015610fb857858303601f19018952815180516001600160401b0390811685528582015160a08787018190529190610f7c83880182610db3565b60408581015184169089015260608086015190931692880192909252506080928301519290950191909152509783019790830190600101610f40565b5090979650505050505050565b60008151808452602080850194506020840160005b83811015610f18578151805188528301518388015260409096019590820190600101610fda565b602080825282516060838301528051604060808501819052815160c086018190526000949392840191859160e08801905b8084101561106d57845180516001600160a01b031683528701516001600160e01b031687830152938601936001939093019290820190611032565b5093850151878503607f190160a0890152936110898186610eca565b945050505050818501519150601f19808583030160408601526110ac8284610f23565b92506040860151915080858403016060860152506110ca8282610fc5565b95945050505050565b600082825180855260208086019550808260051b84010181860160005b84811015610fb857858303601f19018952815180516001600160a01b031684528481015160a08686018190529061112982870182610db3565b915050604080830151868303828801526111438382610db3565b9250505060608083015181870152506080808301519250858203818701525061116c8183610db3565b9a86019a94505050908301906001016110f0565b602081526111cd602082018351805182526020808201516001600160401b039081169184019190915260408083015182169084015260608083015182169084015260809182015116910152565b600060208301516111e160c0840182610ebd565b5060408301516101808060e08501526111fe6101a0850183610db3565b91506060850151601f19808685030161010087015261121d8483610db3565b935060808701519150808685030161012087015261123b8483610db3565b935060a08701519150611252610140870183610ebd565b60c087015161016087015260e087015191508086850301838701525061127883826110d3565b9695505050505050565b600181811c9082168061129657607f821691505b6020821081036112b657634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115611308576000816000526020600020601f850160051c810160208610156112e55750805b601f850160051c820191505b81811015611304578281556001016112f1565b5050505b505050565b81516001600160401b038111156113265761132661040b565b61133a816113348454611282565b846112bc565b602080601f83116001811461136f57600084156113575750858301515b600019600386901b1c1916600185901b178555611304565b600085815260208120601f198616915b8281101561139e5788860151825594840194600190910190840161137f565b50858210156113bc5787850151600019600388901b60f8161c191681555b5050505050600190811b0190555056fea164736f6c6343000818000a", } var CCIPReaderTesterABI = CCIPReaderTesterMetaData.ABI @@ -750,7 +750,7 @@ func (_CCIPReaderTester *CCIPReaderTester) ParseLog(log types.Log) (generated.Ab } func (CCIPReaderTesterCCIPSendRequested) Topic() common.Hash { - return common.HexToHash("0xcae3d9f68a9ed33d0a770e9bcc6fc25d4041dd6391e6cd8015546547a3c93140") + return common.HexToHash("0xe07a589f12eccf1bc0f7421666687a6986a0c8dbbdc877d1af562a97ba60ecfd") } func (CCIPReaderTesterCommitReportAccepted) Topic() common.Hash { diff --git a/core/gethwrappers/ccip/generated/fee_quoter/fee_quoter.go b/core/gethwrappers/ccip/generated/fee_quoter/fee_quoter.go index e5c162e751..e6b3176924 100644 --- a/core/gethwrappers/ccip/generated/fee_quoter/fee_quoter.go +++ b/core/gethwrappers/ccip/generated/fee_quoter/fee_quoter.go @@ -117,6 +117,14 @@ type FeeQuoterTokenTransferFeeConfigSingleTokenArgs struct { TokenTransferFeeConfig FeeQuoterTokenTransferFeeConfig } +type InternalEVM2AnyTokenTransfer struct { + SourcePoolAddress common.Address + DestTokenAddress []byte + ExtraData []byte + Amount *big.Int + DestExecData []byte +} + type InternalGasPriceUpdate struct { DestChainSelector uint64 UsdPerUnitGas *big.Int @@ -127,14 +135,6 @@ type InternalPriceUpdates struct { GasPriceUpdates []InternalGasPriceUpdate } -type InternalRampTokenAmount struct { - SourcePoolAddress []byte - DestTokenAddress []byte - ExtraData []byte - Amount *big.Int - DestExecData []byte -} - type InternalTimestampedPackedUint224 struct { Value *big.Int Timestamp uint32 @@ -154,8 +154,8 @@ type KeystoneFeedsPermissionHandlerPermission struct { } var FeeQuoterMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint96\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"linkToken\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"stalenessThreshold\",\"type\":\"uint32\"}],\"internalType\":\"structFeeQuoter.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"priceUpdaters\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"feeTokens\",\"type\":\"address[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"}],\"internalType\":\"structFeeQuoter.TokenPriceFeedConfig\",\"name\":\"feedConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.TokenPriceFeedUpdate[]\",\"name\":\"tokenPriceFeeds\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigSingleTokenArgs[]\",\"name\":\"tokenTransferFeeConfigs\",\"type\":\"tuple[]\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigArgs[]\",\"name\":\"tokenTransferFeeConfigArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"internalType\":\"structFeeQuoter.PremiumMultiplierWeiPerEthArgs[]\",\"name\":\"premiumMultiplierWeiPerEthArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chain\",\"type\":\"uint64\"}],\"name\":\"ChainNotSupported\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DataFeedValueOutOfUint224Range\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"DestinationChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ExtraArgOutOfOrderExecutionMustBeTrue\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"FeeTokenNotSupported\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"}],\"name\":\"InvalidDestBytesOverhead\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidDestChainConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidEVMAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidExtraArgsTag\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidStaticConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"msgFeeJuels\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint256\"}],\"name\":\"MessageFeeTooHigh\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MessageGasLimitTooHigh\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"maxSize\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualSize\",\"type\":\"uint256\"}],\"name\":\"MessageTooLarge\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"internalType\":\"bytes10\",\"name\":\"workflowName\",\"type\":\"bytes10\"},{\"internalType\":\"bytes2\",\"name\":\"reportName\",\"type\":\"bytes2\"}],\"name\":\"ReportForwarderUnauthorized\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"SourceTokenDataTooLarge\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"threshold\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timePassed\",\"type\":\"uint256\"}],\"name\":\"StaleGasPrice\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feedTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"storedTimeStamp\",\"type\":\"uint256\"}],\"name\":\"StaleKeystoneUpdate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"TokenNotSupported\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"UnauthorizedCaller\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnsupportedNumberOfTokens\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"AuthorizedCallerAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"AuthorizedCallerRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"indexed\":false,\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"name\":\"DestChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"indexed\":false,\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"name\":\"DestChainConfigUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"}],\"name\":\"FeeTokenAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"}],\"name\":\"FeeTokenRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"name\":\"PremiumMultiplierWeiPerEthUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"}],\"indexed\":false,\"internalType\":\"structFeeQuoter.TokenPriceFeedConfig\",\"name\":\"priceFeedConfig\",\"type\":\"tuple\"}],\"name\":\"PriceFeedPerTokenUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"reportId\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"},{\"internalType\":\"bytes10\",\"name\":\"workflowName\",\"type\":\"bytes10\"},{\"internalType\":\"bytes2\",\"name\":\"reportName\",\"type\":\"bytes2\"},{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isAllowed\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"structKeystoneFeedsPermissionHandler.Permission\",\"name\":\"permission\",\"type\":\"tuple\"}],\"name\":\"ReportPermissionSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"TokenTransferFeeConfigDeleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"name\":\"TokenTransferFeeConfigUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"UsdPerTokenUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChain\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"UsdPerUnitGasUpdated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"FEE_BASE_DECIMALS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"KEYSTONE_PRICE_DECIMALS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address[]\",\"name\":\"addedCallers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"removedCallers\",\"type\":\"address[]\"}],\"internalType\":\"structAuthorizedCallers.AuthorizedCallerArgs\",\"name\":\"authorizedCallerArgs\",\"type\":\"tuple\"}],\"name\":\"applyAuthorizedCallerUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyDestChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"feeTokensToAdd\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"feeTokensToRemove\",\"type\":\"address[]\"}],\"name\":\"applyFeeTokensUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"internalType\":\"structFeeQuoter.PremiumMultiplierWeiPerEthArgs[]\",\"name\":\"premiumMultiplierWeiPerEthArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyPremiumMultiplierWeiPerEthUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigSingleTokenArgs[]\",\"name\":\"tokenTransferFeeConfigs\",\"type\":\"tuple[]\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigArgs[]\",\"name\":\"tokenTransferFeeConfigArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigRemoveArgs[]\",\"name\":\"tokensToUseDefaultFeeConfigs\",\"type\":\"tuple[]\"}],\"name\":\"applyTokenTransferFeeConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"fromToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fromTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"toToken\",\"type\":\"address\"}],\"name\":\"convertTokenAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllAuthorizedCallers\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getDestChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getDestinationChainGasPrice\",\"outputs\":[{\"components\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"internalType\":\"structInternal.TimestampedPackedUint224\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getFeeTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getPremiumMultiplierWeiPerEth\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint96\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"linkToken\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"stalenessThreshold\",\"type\":\"uint32\"}],\"internalType\":\"structFeeQuoter.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getTokenAndGasPrices\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"tokenPrice\",\"type\":\"uint224\"},{\"internalType\":\"uint224\",\"name\":\"gasPriceValue\",\"type\":\"uint224\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenPrice\",\"outputs\":[{\"components\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"internalType\":\"structInternal.TimestampedPackedUint224\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenPriceFeedConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"}],\"internalType\":\"structFeeQuoter.TokenPriceFeedConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"tokens\",\"type\":\"address[]\"}],\"name\":\"getTokenPrices\",\"outputs\":[{\"components\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"internalType\":\"structInternal.TimestampedPackedUint224[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenTransferFeeConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"getValidatedFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getValidatedTokenPrice\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"\",\"type\":\"uint224\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"onReport\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"rampTokenAmounts\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"sourceTokenAmounts\",\"type\":\"tuple[]\"}],\"name\":\"processMessageArgs\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"msgFeeJuels\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isOutOfOrderExecution\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"convertedExtraArgs\",\"type\":\"bytes\"},{\"internalType\":\"bytes[]\",\"name\":\"destExecDataPerToken\",\"type\":\"bytes[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"},{\"internalType\":\"bytes10\",\"name\":\"workflowName\",\"type\":\"bytes10\"},{\"internalType\":\"bytes2\",\"name\":\"reportName\",\"type\":\"bytes2\"},{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isAllowed\",\"type\":\"bool\"}],\"internalType\":\"structKeystoneFeedsPermissionHandler.Permission[]\",\"name\":\"permissions\",\"type\":\"tuple[]\"}],\"name\":\"setReportPermissions\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"}],\"name\":\"updatePrices\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"}],\"internalType\":\"structFeeQuoter.TokenPriceFeedConfig\",\"name\":\"feedConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.TokenPriceFeedUpdate[]\",\"name\":\"tokenPriceFeedUpdates\",\"type\":\"tuple[]\"}],\"name\":\"updateTokenPriceFeeds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x60e06040523480156200001157600080fd5b506040516200776138038062007761833981016040819052620000349162001834565b8533806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf8162000207565b5050604080518082018252838152815160008152602080820190935291810191909152620000ee9150620002b2565b5060208701516001600160a01b0316158062000112575086516001600160601b0316155b80620001265750604087015163ffffffff16155b15620001455760405163d794ef9560e01b815260040160405180910390fd5b6020878101516001600160a01b031660a05287516001600160601b031660805260408089015163ffffffff1660c05280516000815291820190526200018c90869062000401565b620001978462000549565b620001a2816200061a565b620001ad8262000a5a565b60408051600080825260208201909252620001fa91859190620001f3565b6040805180820190915260008082526020820152815260200190600190039081620001cb5790505b5062000b26565b5050505050505062001ae5565b336001600160a01b03821603620002615760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b602081015160005b815181101562000342576000828281518110620002db57620002db62001953565b60209081029190910101519050620002f560028262000e5f565b1562000338576040516001600160a01b03821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b50600101620002ba565b50815160005b8151811015620003fb57600082828151811062000369576200036962001953565b6020026020010151905060006001600160a01b0316816001600160a01b031603620003a7576040516342bcdf7f60e11b815260040160405180910390fd5b620003b460028262000e7f565b506040516001600160a01b03821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a15060010162000348565b50505050565b60005b8251811015620004a2576200044083828151811062000427576200042762001953565b6020026020010151600b62000e7f60201b90919060201c565b1562000499578281815181106200045b576200045b62001953565b60200260200101516001600160a01b03167fdf1b1bd32a69711488d71554706bb130b1fc63a5fa1a2cd85e8440f84065ba2360405160405180910390a25b60010162000404565b5060005b81518110156200054457620004e2828281518110620004c957620004c962001953565b6020026020010151600b62000e9660201b90919060201c565b156200053b57818181518110620004fd57620004fd62001953565b60200260200101516001600160a01b03167f1795838dc8ab2ffc5f431a1729a6afa0b587f982f7b2be0b9d7187a1ef547f9160405160405180910390a25b600101620004a6565b505050565b60005b8151811015620006165760008282815181106200056d576200056d62001953565b6020908102919091018101518051818301516001600160a01b0380831660008181526007875260409081902084518154868a018051929096166001600160a81b03199091168117600160a01b60ff9384160217909255825191825293519093169683019690965293955091939092917f08a5f7f5bb38a81d8e43aca13ecd76431dbf8816ae4699affff7b00b2fc1c464910160405180910390a25050508060010190506200054c565b5050565b60005b8151811015620006165760008282815181106200063e576200063e62001953565b6020026020010151905060008383815181106200065f576200065f62001953565b6020026020010151600001519050600082602001519050816001600160401b03166000148062000698575061016081015163ffffffff16155b80620006ba57506101e08101516001600160e01b031916630a04b54b60e21b14155b80620006da5750806060015163ffffffff1681610160015163ffffffff16115b15620007055760405163c35aa79d60e01b81526001600160401b038316600482015260240162000083565b6001600160401b038216600090815260096020526040812060010154600160881b900460e01b6001600160e01b03191690036200078557816001600160401b03167fd31c671936387b2f84ed402b553bd50c0e9c20408ea4e91a836d77b8180fb7248260405162000777919062001969565b60405180910390a2620007c9565b816001600160401b03167f1edd6f3553cfa16f10b95b195abae3a1cfca4783de4843f95d674b1e1df5ab2082604051620007c0919062001969565b60405180910390a25b8060096000846001600160401b03166001600160401b0316815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548161ffff021916908361ffff16021790555060408201518160000160036101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160076101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600b6101000a81548163ffffffff021916908363ffffffff16021790555060a082015181600001600f6101000a81548161ffff021916908361ffff16021790555060c08201518160000160116101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160000160156101000a81548161ffff021916908361ffff1602179055506101008201518160000160176101000a81548161ffff021916908361ffff1602179055506101208201518160000160196101000a81548161ffff021916908361ffff16021790555061014082015181600001601b6101000a81548163ffffffff021916908363ffffffff1602179055506101608201518160010160006101000a81548163ffffffff021916908363ffffffff1602179055506101808201518160010160046101000a8154816001600160401b0302191690836001600160401b031602179055506101a082015181600101600c6101000a81548163ffffffff021916908363ffffffff1602179055506101c08201518160010160106101000a81548160ff0219169083151502179055506101e08201518160010160116101000a81548163ffffffff021916908360e01c02179055509050505050508060010190506200061d565b60005b81518110156200061657600082828151811062000a7e5762000a7e62001953565b6020026020010151600001519050600083838151811062000aa35762000aa362001953565b6020908102919091018101518101516001600160a01b03841660008181526008845260409081902080546001600160401b0319166001600160401b0385169081179091559051908152919350917fbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d910160405180910390a2505060010162000a5d565b60005b825181101562000d9957600083828151811062000b4a5762000b4a62001953565b6020026020010151905060008160000151905060005b82602001515181101562000d8a5760008360200151828151811062000b895762000b8962001953565b602002602001015160200151905060008460200151838151811062000bb25762000bb262001953565b6020026020010151600001519050602063ffffffff16826080015163ffffffff16101562000c115760808201516040516312766e0160e11b81526001600160a01b038316600482015263ffffffff909116602482015260440162000083565b6001600160401b0384166000818152600a602090815260408083206001600160a01b0386168085529083529281902086518154938801518389015160608a015160808b015160a08c01511515600160901b0260ff60901b1963ffffffff928316600160701b021664ffffffffff60701b199383166a01000000000000000000000263ffffffff60501b1961ffff90961668010000000000000000029590951665ffffffffffff60401b19968416640100000000026001600160401b0319909b16939097169290921798909817939093169390931717919091161792909217909155519091907f94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b59062000d77908690600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60405180910390a3505060010162000b60565b50505080600101905062000b29565b5060005b81518110156200054457600082828151811062000dbe5762000dbe62001953565b6020026020010151600001519050600083838151811062000de35762000de362001953565b6020908102919091018101518101516001600160401b0384166000818152600a845260408082206001600160a01b038516808452955280822080546001600160981b03191690555192945090917f4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b9190a3505060010162000d9d565b600062000e76836001600160a01b03841662000ead565b90505b92915050565b600062000e76836001600160a01b03841662000fb1565b600062000e76836001600160a01b03841662001003565b6000818152600183016020526040812054801562000fa657600062000ed460018362001aad565b855490915060009062000eea9060019062001aad565b905081811462000f5657600086600001828154811062000f0e5762000f0e62001953565b906000526020600020015490508087600001848154811062000f345762000f3462001953565b6000918252602080832090910192909255918252600188019052604090208390555b855486908062000f6a5762000f6a62001acf565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505062000e79565b600091505062000e79565b600081815260018301602052604081205462000ffa5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000e79565b50600062000e79565b6000818152600183016020526040812054801562000fa65760006200102a60018362001aad565b8554909150600090620010409060019062001aad565b905080821462000f5657600086600001828154811062000f0e5762000f0e62001953565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b03811182821017156200109f576200109f62001064565b60405290565b60405160c081016001600160401b03811182821017156200109f576200109f62001064565b60405161020081016001600160401b03811182821017156200109f576200109f62001064565b604051601f8201601f191681016001600160401b03811182821017156200111b576200111b62001064565b604052919050565b80516001600160a01b03811681146200113b57600080fd5b919050565b805163ffffffff811681146200113b57600080fd5b6000606082840312156200116857600080fd5b604051606081016001600160401b03811182821017156200118d576200118d62001064565b604052825190915081906001600160601b0381168114620011ad57600080fd5b8152620011bd6020840162001123565b6020820152620011d06040840162001140565b60408201525092915050565b60006001600160401b03821115620011f857620011f862001064565b5060051b60200190565b600082601f8301126200121457600080fd5b815160206200122d6200122783620011dc565b620010f0565b8083825260208201915060208460051b8701019350868411156200125057600080fd5b602086015b848110156200127757620012698162001123565b835291830191830162001255565b509695505050505050565b600082601f8301126200129457600080fd5b81516020620012a76200122783620011dc565b82815260609283028501820192828201919087851115620012c757600080fd5b8387015b858110156200135a5780890382811215620012e65760008081fd5b620012f06200107a565b620012fb8362001123565b8152604080601f1984011215620013125760008081fd5b6200131c6200107a565b92506200132b88850162001123565b835283015160ff81168114620013415760008081fd5b82880152808701919091528452928401928101620012cb565b5090979650505050505050565b80516001600160401b03811681146200113b57600080fd5b805161ffff811681146200113b57600080fd5b805180151581146200113b57600080fd5b600082601f830112620013b557600080fd5b81516020620013c86200122783620011dc565b82815260059290921b84018101918181019086841115620013e857600080fd5b8286015b84811015620012775780516001600160401b03808211156200140d57600080fd5b908801906040601f19838c0381018213156200142857600080fd5b620014326200107a565b6200143f89860162001367565b815282850151848111156200145357600080fd5b8086019550508c603f8601126200146957600080fd5b8885015193506200147e6200122785620011dc565b84815260e09094028501830193898101908e8611156200149d57600080fd5b958401955b858710156200157657868f0360e0811215620014bd57600080fd5b620014c76200107a565b620014d28962001123565b815260c08683011215620014e557600080fd5b620014ef620010a5565b9150620014fe8d8a0162001140565b82526200150d878a0162001140565b8d8301526200151f60608a016200137f565b878301526200153160808a0162001140565b60608301526200154460a08a0162001140565b60808301526200155760c08a0162001392565b60a0830152808d0191909152825260e09690960195908a0190620014a2565b828b015250875250505092840192508301620013ec565b600082601f8301126200159f57600080fd5b81516020620015b26200122783620011dc565b82815260069290921b84018101918181019086841115620015d257600080fd5b8286015b84811015620012775760408189031215620015f15760008081fd5b620015fb6200107a565b620016068262001123565b81526200161585830162001367565b81860152835291830191604001620015d6565b80516001600160e01b0319811681146200113b57600080fd5b600082601f8301126200165357600080fd5b81516020620016666200122783620011dc565b82815261022092830285018201928282019190878511156200168757600080fd5b8387015b858110156200135a5780890382811215620016a65760008081fd5b620016b06200107a565b620016bb8362001367565b815261020080601f1984011215620016d35760008081fd5b620016dd620010ca565b9250620016ec88850162001392565b83526040620016fd8186016200137f565b8985015260606200171081870162001140565b82860152608091506200172582870162001140565b9085015260a06200173886820162001140565b8286015260c091506200174d8287016200137f565b9085015260e06200176086820162001140565b828601526101009150620017768287016200137f565b908501526101206200178a8682016200137f565b828601526101409150620017a08287016200137f565b90850152610160620017b486820162001140565b828601526101809150620017ca82870162001140565b908501526101a0620017de86820162001367565b828601526101c09150620017f482870162001140565b908501526101e06200180886820162001392565b828601526200181983870162001628565b9085015250508087019190915284529284019281016200168b565b6000806000806000806000610120888a0312156200185157600080fd5b6200185d898962001155565b60608901519097506001600160401b03808211156200187b57600080fd5b620018898b838c0162001202565b975060808a0151915080821115620018a057600080fd5b620018ae8b838c0162001202565b965060a08a0151915080821115620018c557600080fd5b620018d38b838c0162001282565b955060c08a0151915080821115620018ea57600080fd5b620018f88b838c01620013a3565b945060e08a01519150808211156200190f57600080fd5b6200191d8b838c016200158d565b93506101008a01519150808211156200193557600080fd5b50620019448a828b0162001641565b91505092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b815115158152610200810160208301516200198a602084018261ffff169052565b506040830151620019a3604084018263ffffffff169052565b506060830151620019bc606084018263ffffffff169052565b506080830151620019d5608084018263ffffffff169052565b5060a0830151620019ec60a084018261ffff169052565b5060c083015162001a0560c084018263ffffffff169052565b5060e083015162001a1c60e084018261ffff169052565b506101008381015161ffff9081169184019190915261012080850151909116908301526101408084015163ffffffff9081169184019190915261016080850151821690840152610180808501516001600160401b0316908401526101a080850151909116908301526101c0808401511515908301526101e0928301516001600160e01b031916929091019190915290565b8181038181111562000e7957634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b60805160a05160c051615c1b62001b46600039600081816102fa0152818161184d01528181611ee90152611f520152600081816102be0152818161158501526115e501526000818161028a0152818161160e015261167e0152615c1b6000f3fe608060405234801561001057600080fd5b50600436106101d95760003560e01c80637afac32211610104578063a69c64c0116100a2578063d63d3af211610071578063d63d3af214610a88578063d8694ccd14610a90578063f2fde38b14610aa3578063ffdb4b3714610ab657600080fd5b8063a69c64c0146109ad578063bf78e03f146109c0578063cdc73d5114610a6d578063d02641a014610a7557600080fd5b80638da5cb5b116100de5780638da5cb5b1461093c57806391a2749a1461096457806397d640a2146109775780639ea600261461099a57600080fd5b80637afac322146107a6578063805f2132146107b957806382b49eb0146107cc57600080fd5b8063407e10861161017c578063514e8cff1161014b578063514e8cff146104745780636def4ce714610517578063770e2dc41461078b57806379ba50971461079e57600080fd5b8063407e1086146103ee57806341ed29e71461040157806345ac924d146104145780634ab35b0b1461043457600080fd5b8063181f5a77116101b8578063181f5a77146103735780632451a627146103bc578063325c868e146103d15780633937306f146103d957600080fd5b806241e5be146101de578063061877e31461020457806306285c691461025d575b600080fd5b6101f16101ec36600461431b565b610afe565b6040519081526020015b60405180910390f35b610244610212366004614357565b73ffffffffffffffffffffffffffffffffffffffff1660009081526008602052604090205467ffffffffffffffff1690565b60405167ffffffffffffffff90911681526020016101fb565b610327604080516060810182526000808252602082018190529181019190915260405180606001604052807f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000063ffffffff16815250905090565b6040805182516bffffffffffffffffffffffff16815260208084015173ffffffffffffffffffffffffffffffffffffffff16908201529181015163ffffffff16908201526060016101fb565b6103af6040518060400160405280601381526020017f46656551756f74657220312e362e302d6465760000000000000000000000000081525081565b6040516101fb91906143d6565b6103c4610b6c565b6040516101fb91906143e9565b6101f1602481565b6103ec6103e7366004614443565b610b7d565b005b6103ec6103fc3660046145e5565b610e32565b6103ec61040f366004614717565b610e46565b610427610422366004614897565b610e88565b6040516101fb91906148d9565b610447610442366004614357565b610f53565b6040517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff90911681526020016101fb565b61050a61048236600461496c565b60408051808201909152600080825260208201525067ffffffffffffffff166000908152600560209081526040918290208251808401909352547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811683527c0100000000000000000000000000000000000000000000000000000000900463ffffffff169082015290565b6040516101fb9190614987565b61077e61052536600461496c565b6040805161020081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a081018290526101c081018290526101e08101919091525067ffffffffffffffff908116600090815260096020908152604091829020825161020081018452815460ff8082161515835261ffff61010080840482169685019690965263ffffffff630100000084048116978501979097526701000000000000008304871660608501526b0100000000000000000000008304871660808501526f010000000000000000000000000000008304811660a085015271010000000000000000000000000000000000808404881660c086015275010000000000000000000000000000000000000000008404821660e08087019190915277010000000000000000000000000000000000000000000000850483169786019790975279010000000000000000000000000000000000000000000000000084049091166101208501527b01000000000000000000000000000000000000000000000000000000909204861661014084015260019093015480861661016084015264010000000081049096166101808301526c0100000000000000000000000086049094166101a0820152700100000000000000000000000000000000850490911615156101c08201527fffffffff0000000000000000000000000000000000000000000000000000000092909304901b166101e082015290565b6040516101fb91906149c2565b6103ec610799366004614bd9565b610f5e565b6103ec610f70565b6103ec6107b4366004614ef3565b611072565b6103ec6107c7366004614f99565b611084565b6108dc6107da366004615005565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101919091525067ffffffffffffffff919091166000908152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff94909416835292815290829020825160c081018452905463ffffffff8082168352640100000000820481169383019390935268010000000000000000810461ffff16938201939093526a01000000000000000000008304821660608201526e01000000000000000000000000000083049091166080820152720100000000000000000000000000000000000090910460ff16151560a082015290565b6040516101fb9190600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101fb565b6103ec61097236600461502f565b61156c565b61098a6109853660046150c0565b61157d565b6040516101fb94939291906151b4565b6103ec6109a8366004615283565b611788565b6103ec6109bb366004615490565b611799565b610a396109ce366004614357565b6040805180820182526000808252602091820181905273ffffffffffffffffffffffffffffffffffffffff93841681526007825282902082518084019093525492831682527401000000000000000000000000000000000000000090920460ff169181019190915290565b60408051825173ffffffffffffffffffffffffffffffffffffffff16815260209283015160ff1692810192909252016101fb565b6103c46117aa565b61050a610a83366004614357565b6117b6565b6101f1601281565b6101f1610a9e366004615555565b6118fa565b6103ec610ab1366004614357565b611e04565b610ac9610ac43660046155aa565b611e15565b604080517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff9384168152929091166020830152016101fb565b6000610b0982611fa0565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16610b3085611fa0565b610b58907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1685615603565b610b62919061561a565b90505b9392505050565b6060610b78600261203a565b905090565b610b85612047565b6000610b918280615655565b9050905060005b81811015610cdb576000610bac8480615655565b83818110610bbc57610bbc6156bd565b905060400201803603810190610bd29190615718565b604080518082018252602080840180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff908116845263ffffffff42818116858701908152885173ffffffffffffffffffffffffffffffffffffffff9081166000908152600690975295889020965190519092167c010000000000000000000000000000000000000000000000000000000002919092161790935584519051935194955016927f52f50aa6d1a95a4595361ecf953d095f125d442e4673716dede699e049de148a92610cca9290917bffffffffffffffffffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b60405180910390a250600101610b98565b506000610ceb6020840184615655565b9050905060005b81811015610e2c576000610d096020860186615655565b83818110610d1957610d196156bd565b905060400201803603810190610d2f9190615755565b604080518082018252602080840180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff908116845263ffffffff42818116858701908152885167ffffffffffffffff9081166000908152600590975295889020965190519092167c010000000000000000000000000000000000000000000000000000000002919092161790935584519051935194955016927fdd84a3fa9ef9409f550d54d6affec7e9c480c878c6ab27b78912a03e1b371c6e92610e1b9290917bffffffffffffffffffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b60405180910390a250600101610cf2565b50505050565b610e3a61208c565b610e438161210d565b50565b610e4e61208c565b60005b8151811015610e8457610e7c828281518110610e6f57610e6f6156bd565b602002602001015161220b565b600101610e51565b5050565b60608160008167ffffffffffffffff811115610ea657610ea661447e565b604051908082528060200260200182016040528015610eeb57816020015b6040805180820190915260008082526020820152815260200190600190039081610ec45790505b50905060005b82811015610f4857610f23868683818110610f0e57610f0e6156bd565b9050602002016020810190610a839190614357565b828281518110610f3557610f356156bd565b6020908102919091010152600101610ef1565b509150505b92915050565b6000610f4d82611fa0565b610f6661208c565b610e8482826123dd565b60015473ffffffffffffffffffffffffffffffffffffffff163314610ff6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b61107a61208c565b610e8482826127ef565b60008060006110c887878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061293692505050565b9250925092506110da33838584612951565b60006110e885870187615778565b905060005b81518110156115615760006007600084848151811061110e5761110e6156bd565b6020908102919091018101515173ffffffffffffffffffffffffffffffffffffffff16825281019190915260400160009081205474010000000000000000000000000000000000000000900460ff1691508190036111cf57828281518110611178576111786156bd565b6020908102919091010151516040517f06439c6b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610fed565b60006112186012838686815181106111e9576111e96156bd565b6020026020010151602001517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16612aa9565b905060066000858581518110611230576112306156bd565b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001601c9054906101000a900463ffffffff1663ffffffff168484815181106112a2576112a26156bd565b60200260200101516040015163ffffffff1610156113ac578383815181106112cc576112cc6156bd565b6020026020010151600001518484815181106112ea576112ea6156bd565b6020026020010151604001516006600087878151811061130c5761130c6156bd565b6020908102919091018101515173ffffffffffffffffffffffffffffffffffffffff90811683529082019290925260409081016000205490517f191ec70600000000000000000000000000000000000000000000000000000000815293909116600484015263ffffffff91821660248401527c01000000000000000000000000000000000000000000000000000000009004166044820152606401610fed565b6040518060400160405280827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1681526020018585815181106113ed576113ed6156bd565b60200260200101516040015163ffffffff1681525060066000868681518110611418576114186156bd565b6020908102919091018101515173ffffffffffffffffffffffffffffffffffffffff168252818101929092526040016000208251929091015163ffffffff167c0100000000000000000000000000000000000000000000000000000000027bffffffffffffffffffffffffffffffffffffffffffffffffffffffff90921691909117905583518490849081106114b0576114b06156bd565b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff167f52f50aa6d1a95a4595361ecf953d095f125d442e4673716dede699e049de148a82868681518110611506576115066156bd565b60200260200101516040015160405161154f9291907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff92909216825263ffffffff16602082015260400190565b60405180910390a250506001016110ed565b505050505050505050565b61157461208c565b610e4381612b75565b6000806060807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168c73ffffffffffffffffffffffffffffffffffffffff16036115de578a935061160c565b6116098c8c7f0000000000000000000000000000000000000000000000000000000000000000610afe565b93505b7f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff168411156116ab576040517f6a92a483000000000000000000000000000000000000000000000000000000008152600481018590526bffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166024820152604401610fed565b67ffffffffffffffff8d1660009081526009602052604081206001015463ffffffff16906116da8c8c84612d01565b9050806020015194506116f08f8b8b8b8b612eaa565b92508585611770836040805182516024820152602092830151151560448083019190915282518083039091018152606490910190915290810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f181dcf100000000000000000000000000000000000000000000000000000000017905290565b95509550955050509950995099509995505050505050565b61179061208c565b610e4381613217565b6117a161208c565b610e43816136bd565b6060610b78600b61203a565b604080518082019091526000808252602082015273ffffffffffffffffffffffffffffffffffffffff82166000908152600660209081526040918290208251808401909352547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116835263ffffffff7c010000000000000000000000000000000000000000000000000000000090910481169183018290527f00000000000000000000000000000000000000000000000000000000000000001690611878904261583f565b10156118845792915050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600760209081526040918290208251808401909352549283168083527401000000000000000000000000000000000000000090930460ff1690820152906118e9575092915050565b6118f2816137a7565b949350505050565b67ffffffffffffffff8083166000908152600960209081526040808320815161020081018352815460ff808216151580845261ffff61010080850482169886019890985263ffffffff630100000085048116978601979097526701000000000000008404871660608601526b0100000000000000000000008404871660808601526f010000000000000000000000000000008404811660a086015271010000000000000000000000000000000000808504881660c087015275010000000000000000000000000000000000000000008504821660e08088019190915277010000000000000000000000000000000000000000000000860483169987019990995279010000000000000000000000000000000000000000000000000085049091166101208601527b01000000000000000000000000000000000000000000000000000000909304861661014085015260019094015480861661016085015264010000000081049098166101808401526c0100000000000000000000000088049094166101a0830152700100000000000000000000000000000000870490931615156101c08201527fffffffff000000000000000000000000000000000000000000000000000000009290950490921b166101e0840152909190611b14576040517f99ac52f200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff85166004820152602401610fed565b611b2f611b276080850160608601614357565b600b90613936565b611b8e57611b436080840160608501614357565b6040517f2502348c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610fed565b6000611b9d6040850185615655565b9150611bf9905082611bb26020870187615852565b905083611bbf8880615852565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061396592505050565b600080611c15611c0f6080880160608901614357565b88611e15565b9092509050600080808515611c5857611c4c878b611c3960808d0160608e01614357565b88611c4760408f018f615655565b613a0f565b91945092509050611c78565b6101a0870151611c759063ffffffff16662386f26fc10000615603565b92505b61010087015160009061ffff1615611cbc57611cb9886dffffffffffffffffffffffffffff607088901c16611cb060208e018e615852565b90508a86613ce7565b90505b61018088015160009067ffffffffffffffff16611ce5611cdf60808e018e615852565b8c613d97565b600001518563ffffffff168b60a0015161ffff168e8060200190611d099190615852565b611d14929150615603565b8c6080015163ffffffff16611d2991906158b7565b611d3391906158b7565b611d3d91906158b7565b611d57906dffffffffffffffffffffffffffff8916615603565b611d619190615603565b9050867bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168282600860008f6060016020810190611d9b9190614357565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160002054611dd69067ffffffffffffffff1689615603565b611de091906158b7565b611dea91906158b7565b611df4919061561a565b9c9b505050505050505050505050565b611e0c61208c565b610e4381613e58565b67ffffffffffffffff811660009081526005602090815260408083208151808301909252547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811682527c0100000000000000000000000000000000000000000000000000000000900463ffffffff1691810182905282918203611ecd576040517f2e59db3a00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff85166004820152602401610fed565b6000816020015163ffffffff1642611ee5919061583f565b90507f000000000000000000000000000000000000000000000000000000000000000063ffffffff16811115611f86576040517ff08bcb3e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8616600482015263ffffffff7f000000000000000000000000000000000000000000000000000000000000000016602482015260448101829052606401610fed565b611f8f86611fa0565b9151919350909150505b9250929050565b600080611fac836117b6565b9050806020015163ffffffff1660001480611fe4575080517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16155b15612033576040517f06439c6b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152602401610fed565b5192915050565b60606000610b6583613f4d565b612052600233613936565b61208a576040517fd86ad9cf000000000000000000000000000000000000000000000000000000008152336004820152602401610fed565b565b60005473ffffffffffffffffffffffffffffffffffffffff16331461208a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610fed565b60005b8151811015610e8457600082828151811061212d5761212d6156bd565b60209081029190910181015180518183015173ffffffffffffffffffffffffffffffffffffffff80831660008181526007875260409081902084518154868a018051929096167fffffffffffffffffffffff00000000000000000000000000000000000000000090911681177401000000000000000000000000000000000000000060ff9384160217909255825191825293519093169683019690965293955091939092917f08a5f7f5bb38a81d8e43aca13ecd76431dbf8816ae4699affff7b00b2fc1c464910160405180910390a2505050806001019050612110565b60006122c482600001518360600151846020015185604001516040805173ffffffffffffffffffffffffffffffffffffffff80871660208301528516918101919091527fffffffffffffffffffff00000000000000000000000000000000000000000000831660608201527fffff0000000000000000000000000000000000000000000000000000000000008216608082015260009060a001604051602081830303815290604052805190602001209050949350505050565b60808301516000828152600460205260409081902080549215157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00909316929092179091555190915081907f32a4ba3fa3351b11ad555d4c8ec70a744e8705607077a946807030d64b6ab1a3906123d1908590600060a08201905073ffffffffffffffffffffffffffffffffffffffff8084511683527fffffffffffffffffffff0000000000000000000000000000000000000000000060208501511660208401527fffff00000000000000000000000000000000000000000000000000000000000060408501511660408401528060608501511660608401525060808301511515608083015292915050565b60405180910390a25050565b60005b82518110156127065760008382815181106123fd576123fd6156bd565b6020026020010151905060008160000151905060005b8260200151518110156126f857600083602001518281518110612438576124386156bd565b602002602001015160200151905060008460200151838151811061245e5761245e6156bd565b6020026020010151600001519050602063ffffffff16826080015163ffffffff1610156124e15760808201516040517f24ecdc0200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8316600482015263ffffffff9091166024820152604401610fed565b67ffffffffffffffff84166000818152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff86168085529083529281902086518154938801518389015160608a015160808b015160a08c015115157201000000000000000000000000000000000000027fffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffff63ffffffff9283166e01000000000000000000000000000002167fffffffffffffffffffffffffff0000000000ffffffffffffffffffffffffffff9383166a0100000000000000000000027fffffffffffffffffffffffffffffffffffff00000000ffffffffffffffffffff61ffff9096166801000000000000000002959095167fffffffffffffffffffffffffffffffffffff000000000000ffffffffffffffff968416640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000909b16939097169290921798909817939093169390931717919091161792909217909155519091907f94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b5906126e6908690600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60405180910390a35050600101612413565b5050508060010190506123e0565b5060005b81518110156127ea576000828281518110612727576127276156bd565b60200260200101516000015190506000838381518110612749576127496156bd565b60209081029190910181015181015167ffffffffffffffff84166000818152600a8452604080822073ffffffffffffffffffffffffffffffffffffffff8516808452955280822080547fffffffffffffffffffffffffff000000000000000000000000000000000000001690555192945090917f4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b9190a3505060010161270a565b505050565b60005b825181101561289257612828838281518110612810576128106156bd565b6020026020010151600b613fa990919063ffffffff16565b1561288a5782818151811061283f5761283f6156bd565b602002602001015173ffffffffffffffffffffffffffffffffffffffff167fdf1b1bd32a69711488d71554706bb130b1fc63a5fa1a2cd85e8440f84065ba2360405160405180910390a25b6001016127f2565b5060005b81518110156127ea576128cc8282815181106128b4576128b46156bd565b6020026020010151600b613fcb90919063ffffffff16565b1561292e578181815181106128e3576128e36156bd565b602002602001015173ffffffffffffffffffffffffffffffffffffffff167f1795838dc8ab2ffc5f431a1729a6afa0b587f982f7b2be0b9d7187a1ef547f9160405160405180910390a25b600101612896565b6040810151604a820151605e90920151909260609290921c91565b6040805173ffffffffffffffffffffffffffffffffffffffff868116602080840191909152908616828401527fffffffffffffffffffff00000000000000000000000000000000000000000000851660608301527fffff00000000000000000000000000000000000000000000000000000000000084166080808401919091528351808403909101815260a09092018352815191810191909120600081815260049092529190205460ff16612aa2576040517f097e17ff00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8087166004830152851660248201527fffffffffffffffffffff00000000000000000000000000000000000000000000841660448201527fffff00000000000000000000000000000000000000000000000000000000000083166064820152608401610fed565b5050505050565b600080612ab684866158ca565b9050600060248260ff161115612af057612ad4602460ff841661583f565b612adf90600a615a03565b612ae9908561561a565b9050612b16565b612afe60ff8316602461583f565b612b0990600a615a03565b612b139085615603565b90505b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811115612b6c576040517f10cb51d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b95945050505050565b602081015160005b8151811015612c10576000828281518110612b9a57612b9a6156bd565b60200260200101519050612bb8816002613fed90919063ffffffff16565b15612c075760405173ffffffffffffffffffffffffffffffffffffffff821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b50600101612b7d565b50815160005b8151811015610e2c576000828281518110612c3357612c336156bd565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603612ca3576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b612cae600282613fa9565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a150600101612c16565b60408051808201909152600080825260208201526000839003612d4257506040805180820190915267ffffffffffffffff8216815260006020820152610b65565b6000612d4e8486615a0f565b90506000612d5f8560048189615a55565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505050507fffffffff0000000000000000000000000000000000000000000000000000000082167fe7e230f00000000000000000000000000000000000000000000000000000000001612dfc5780806020019051810190612df39190615a7f565b92505050610b65565b7f6859a837000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831601612e7857604051806040016040528082806020019051810190612e649190615aab565b815260006020909101529250610b65915050565b6040517f5247fdce00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff8086166000908152600960205260409020600101546060917101000000000000000000000000000000000090910460e01b908590811115612ef657612ef661447e565b604051908082528060200260200182016040528015612f2957816020015b6060815260200190600190039081612f145790505b50915060005b8581101561320c576000858583818110612f4b57612f4b6156bd565b612f619260206040909202019081019150614357565b90506000888884818110612f7757612f776156bd565b9050602002810190612f899190615ac4565b612f97906040810190615852565b91505060208111156130475767ffffffffffffffff8a166000908152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff861684529091529020546e010000000000000000000000000000900463ffffffff16811115613047576040517f36f536ca00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83166004820152602401610fed565b6130b7848a8a8681811061305d5761305d6156bd565b905060200281019061306f9190615ac4565b61307d906020810190615852565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061400f92505050565b67ffffffffffffffff8a166000818152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684528252808320815160c081018352905463ffffffff8082168352640100000000820481168386015268010000000000000000820461ffff16838501526a01000000000000000000008204811660608401526e010000000000000000000000000000820481166080840152720100000000000000000000000000000000000090910460ff16151560a08301908152958552600990935290832054935190937b01000000000000000000000000000000000000000000000000000000900490911691906131b657816131bc565b82606001515b6040805163ffffffff83166020820152919250016040516020818303038152906040528887815181106131f1576131f16156bd565b60200260200101819052505050505050806001019050612f2f565b505095945050505050565b60005b8151811015610e84576000828281518110613237576132376156bd565b602002602001015190506000838381518110613255576132556156bd565b60200260200101516000015190506000826020015190508167ffffffffffffffff166000148061328e575061016081015163ffffffff16155b806132e057506101e08101517fffffffff00000000000000000000000000000000000000000000000000000000167f2812d52c0000000000000000000000000000000000000000000000000000000014155b806132ff5750806060015163ffffffff1681610160015163ffffffff16115b15613342576040517fc35aa79d00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff83166004820152602401610fed565b67ffffffffffffffff821660009081526009602052604081206001015471010000000000000000000000000000000000900460e01b7fffffffff000000000000000000000000000000000000000000000000000000001690036133e6578167ffffffffffffffff167fd31c671936387b2f84ed402b553bd50c0e9c20408ea4e91a836d77b8180fb724826040516133d991906149c2565b60405180910390a2613429565b8167ffffffffffffffff167f1edd6f3553cfa16f10b95b195abae3a1cfca4783de4843f95d674b1e1df5ab208260405161342091906149c2565b60405180910390a25b80600960008467ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548161ffff021916908361ffff16021790555060408201518160000160036101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160076101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600b6101000a81548163ffffffff021916908363ffffffff16021790555060a082015181600001600f6101000a81548161ffff021916908361ffff16021790555060c08201518160000160116101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160000160156101000a81548161ffff021916908361ffff1602179055506101008201518160000160176101000a81548161ffff021916908361ffff1602179055506101208201518160000160196101000a81548161ffff021916908361ffff16021790555061014082015181600001601b6101000a81548163ffffffff021916908363ffffffff1602179055506101608201518160010160006101000a81548163ffffffff021916908363ffffffff1602179055506101808201518160010160046101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506101a082015181600101600c6101000a81548163ffffffff021916908363ffffffff1602179055506101c08201518160010160106101000a81548160ff0219169083151502179055506101e08201518160010160116101000a81548163ffffffff021916908360e01c021790555090505050505080600101905061321a565b60005b8151811015610e845760008282815181106136dd576136dd6156bd565b602002602001015160000151905060008383815181106136ff576136ff6156bd565b60209081029190910181015181015173ffffffffffffffffffffffffffffffffffffffff841660008181526008845260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff85169081179091559051908152919350917fbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d910160405180910390a250506001016136c0565b604080518082019091526000808252602082015260008260000151905060008173ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015613811573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138359190615b1c565b5050509150506000811215613876576040517f10cb51d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006138f58373ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156138c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138ea9190615b6c565b866020015184612aa9565b604080518082019091527bffffffffffffffffffffffffffffffffffffffffffffffffffffffff909116815263ffffffff4216602082015295945050505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515610b65565b836040015163ffffffff168311156139be5760408085015190517f8693378900000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015260248101849052604401610fed565b836020015161ffff16821115613a00576040517f4c056b6a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610e2c846101e001518261400f565b6000808083815b81811015613cd9576000878783818110613a3257613a326156bd565b905060400201803603810190613a489190615b89565b67ffffffffffffffff8c166000908152600a60209081526040808320845173ffffffffffffffffffffffffffffffffffffffff168452825291829020825160c081018452905463ffffffff8082168352640100000000820481169383019390935268010000000000000000810461ffff16938201939093526a01000000000000000000008304821660608201526e01000000000000000000000000000083049091166080820152720100000000000000000000000000000000000090910460ff16151560a0820181905291925090613b68576101208d0151613b359061ffff16662386f26fc10000615603565b613b3f90886158b7565b96508c610140015186613b529190615bc2565b9550613b5f602086615bc2565b94505050613cd1565b604081015160009061ffff1615613c215760008c73ffffffffffffffffffffffffffffffffffffffff16846000015173ffffffffffffffffffffffffffffffffffffffff1614613bc4578351613bbd90611fa0565b9050613bc7565b508a5b620186a0836040015161ffff16613c098660200151847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1661406190919063ffffffff16565b613c139190615603565b613c1d919061561a565b9150505b6060820151613c309088615bc2565b9650816080015186613c429190615bc2565b8251909650600090613c619063ffffffff16662386f26fc10000615603565b905080821015613c8057613c75818a6158b7565b985050505050613cd1565b6000836020015163ffffffff16662386f26fc10000613c9f9190615603565b905080831115613cbf57613cb3818b6158b7565b99505050505050613cd1565b613cc9838b6158b7565b995050505050505b600101613a16565b505096509650969350505050565b60008063ffffffff8316613cfd61016086615603565b613d09876101c06158b7565b613d1391906158b7565b613d1d91906158b7565b905060008760c0015163ffffffff168860e0015161ffff1683613d409190615603565b613d4a91906158b7565b61010089015190915061ffff16613d716dffffffffffffffffffffffffffff891683615603565b613d7b9190615603565b613d8b90655af3107a4000615603565b98975050505050505050565b60408051808201909152600080825260208201526000613dc3858585610160015163ffffffff16612d01565b9050826060015163ffffffff1681600001511115613e0d576040517f4c4fc93a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b826101c001518015613e2157508060200151155b15610b62576040517fee433e9900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff821603613ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610fed565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b606081600001805480602002602001604051908101604052809291908181526020018280548015613f9d57602002820191906000526020600020905b815481526020019060010190808311613f89575b50505050509050919050565b6000610b658373ffffffffffffffffffffffffffffffffffffffff841661409e565b6000610b658373ffffffffffffffffffffffffffffffffffffffff84166140ed565b6000610b658373ffffffffffffffffffffffffffffffffffffffff84166141e7565b7fd7ed2ad4000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831601610e84576127ea8161423f565b6000670de0b6b3a7640000614094837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8616615603565b610b65919061561a565b60008181526001830160205260408120546140e557508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610f4d565b506000610f4d565b600081815260018301602052604081205480156141d657600061411160018361583f565b85549091506000906141259060019061583f565b905080821461418a576000866000018281548110614145576141456156bd565b9060005260206000200154905080876000018481548110614168576141686156bd565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061419b5761419b615bdf565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610f4d565b6000915050610f4d565b5092915050565b600081815260018301602052604081205480156141d657600061420b60018361583f565b855490915060009061421f9060019061583f565b905081811461418a576000866000018281548110614145576141456156bd565b6000815160201461427e57816040517f8d666f60000000000000000000000000000000000000000000000000000000008152600401610fed91906143d6565b6000828060200190518101906142949190615aab565b905073ffffffffffffffffffffffffffffffffffffffff8111806142b9575061040081105b15610f4d57826040517f8d666f60000000000000000000000000000000000000000000000000000000008152600401610fed91906143d6565b803573ffffffffffffffffffffffffffffffffffffffff8116811461431657600080fd5b919050565b60008060006060848603121561433057600080fd5b614339846142f2565b92506020840135915061434e604085016142f2565b90509250925092565b60006020828403121561436957600080fd5b610b65826142f2565b6000815180845260005b818110156143985760208185018101518683018201520161437c565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000610b656020830184614372565b6020808252825182820181905260009190848201906040850190845b8181101561443757835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101614405565b50909695505050505050565b60006020828403121561445557600080fd5b813567ffffffffffffffff81111561446c57600080fd5b820160408185031215610b6557600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff811182821017156144d0576144d061447e565b60405290565b60405160a0810167ffffffffffffffff811182821017156144d0576144d061447e565b60405160c0810167ffffffffffffffff811182821017156144d0576144d061447e565b604051610200810167ffffffffffffffff811182821017156144d0576144d061447e565b6040516060810167ffffffffffffffff811182821017156144d0576144d061447e565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156145aa576145aa61447e565b604052919050565b600067ffffffffffffffff8211156145cc576145cc61447e565b5060051b60200190565b60ff81168114610e4357600080fd5b600060208083850312156145f857600080fd5b823567ffffffffffffffff81111561460f57600080fd5b8301601f8101851361462057600080fd5b803561463361462e826145b2565b614563565b8181526060918202830184019184820191908884111561465257600080fd5b938501935b838510156146f257848903818112156146705760008081fd5b6146786144ad565b614681876142f2565b81526040807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0840112156146b55760008081fd5b6146bd6144ad565b92506146ca8989016142f2565b83528701356146d8816145d6565b828901528088019190915283529384019391850191614657565b50979650505050505050565b8015158114610e4357600080fd5b8035614316816146fe565b6000602080838503121561472a57600080fd5b823567ffffffffffffffff81111561474157600080fd5b8301601f8101851361475257600080fd5b803561476061462e826145b2565b81815260a0918202830184019184820191908884111561477f57600080fd5b938501935b838510156146f25780858a03121561479c5760008081fd5b6147a46144d6565b6147ad866142f2565b8152868601357fffffffffffffffffffff00000000000000000000000000000000000000000000811681146147e25760008081fd5b818801526040868101357fffff0000000000000000000000000000000000000000000000000000000000008116811461481b5760008081fd5b90820152606061482c8782016142f2565b9082015260808681013561483f816146fe565b9082015283529384019391850191614784565b60008083601f84011261486457600080fd5b50813567ffffffffffffffff81111561487c57600080fd5b6020830191508360208260051b8501011115611f9957600080fd5b600080602083850312156148aa57600080fd5b823567ffffffffffffffff8111156148c157600080fd5b6148cd85828601614852565b90969095509350505050565b602080825282518282018190526000919060409081850190868401855b828110156149475761493784835180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16825260209081015163ffffffff16910152565b92840192908501906001016148f6565b5091979650505050505050565b803567ffffffffffffffff8116811461431657600080fd5b60006020828403121561497e57600080fd5b610b6582614954565b81517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16815260208083015163ffffffff169082015260408101610f4d565b815115158152610200810160208301516149e2602084018261ffff169052565b5060408301516149fa604084018263ffffffff169052565b506060830151614a12606084018263ffffffff169052565b506080830151614a2a608084018263ffffffff169052565b5060a0830151614a4060a084018261ffff169052565b5060c0830151614a5860c084018263ffffffff169052565b5060e0830151614a6e60e084018261ffff169052565b506101008381015161ffff9081169184019190915261012080850151909116908301526101408084015163ffffffff90811691840191909152610160808501518216908401526101808085015167ffffffffffffffff16908401526101a080850151909116908301526101c0808401511515908301526101e0808401517fffffffff000000000000000000000000000000000000000000000000000000008116828501525b505092915050565b803563ffffffff8116811461431657600080fd5b803561ffff8116811461431657600080fd5b600082601f830112614b5257600080fd5b81356020614b6261462e836145b2565b82815260069290921b84018101918181019086841115614b8157600080fd5b8286015b84811015614bce5760408189031215614b9e5760008081fd5b614ba66144ad565b614baf82614954565b8152614bbc8583016142f2565b81860152835291830191604001614b85565b509695505050505050565b60008060408385031215614bec57600080fd5b67ffffffffffffffff83351115614c0257600080fd5b83601f843585010112614c1457600080fd5b614c2461462e84358501356145b2565b8335840180358083526020808401939260059290921b90910101861015614c4a57600080fd5b602085358601015b85358601803560051b01602001811015614e575767ffffffffffffffff81351115614c7c57600080fd5b8035863587010160407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0828a03011215614cb557600080fd5b614cbd6144ad565b614cc960208301614954565b815267ffffffffffffffff60408301351115614ce457600080fd5b88603f604084013584010112614cf957600080fd5b614d0f61462e60206040850135850101356145b2565b6020604084810135850182810135808552928401939260e00201018b1015614d3657600080fd5b6040808501358501015b6040858101358601602081013560e0020101811015614e385760e0818d031215614d6957600080fd5b614d716144ad565b614d7a826142f2565b815260c07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0838f03011215614dae57600080fd5b614db66144f9565b614dc260208401614b1b565b8152614dd060408401614b1b565b6020820152614de160608401614b2f565b6040820152614df260808401614b1b565b6060820152614e0360a08401614b1b565b6080820152614e1560c08401356146fe565b60c083013560a0820152602082810191909152908452929092019160e001614d40565b5080602084015250508085525050602083019250602081019050614c52565b5092505067ffffffffffffffff60208401351115614e7457600080fd5b614e848460208501358501614b41565b90509250929050565b600082601f830112614e9e57600080fd5b81356020614eae61462e836145b2565b8083825260208201915060208460051b870101935086841115614ed057600080fd5b602086015b84811015614bce57614ee6816142f2565b8352918301918301614ed5565b60008060408385031215614f0657600080fd5b823567ffffffffffffffff80821115614f1e57600080fd5b614f2a86838701614e8d565b93506020850135915080821115614f4057600080fd5b50614f4d85828601614e8d565b9150509250929050565b60008083601f840112614f6957600080fd5b50813567ffffffffffffffff811115614f8157600080fd5b602083019150836020828501011115611f9957600080fd5b60008060008060408587031215614faf57600080fd5b843567ffffffffffffffff80821115614fc757600080fd5b614fd388838901614f57565b90965094506020870135915080821115614fec57600080fd5b50614ff987828801614f57565b95989497509550505050565b6000806040838503121561501857600080fd5b61502183614954565b9150614e84602084016142f2565b60006020828403121561504157600080fd5b813567ffffffffffffffff8082111561505957600080fd5b908301906040828603121561506d57600080fd5b6150756144ad565b82358281111561508457600080fd5b61509087828601614e8d565b8252506020830135828111156150a557600080fd5b6150b187828601614e8d565b60208301525095945050505050565b600080600080600080600080600060c08a8c0312156150de57600080fd5b6150e78a614954565b98506150f560208b016142f2565b975060408a0135965060608a013567ffffffffffffffff8082111561511957600080fd5b6151258d838e01614f57565b909850965060808c013591508082111561513e57600080fd5b61514a8d838e01614852565b909650945060a08c013591508082111561516357600080fd5b818c0191508c601f83011261517757600080fd5b81358181111561518657600080fd5b8d60208260061b850101111561519b57600080fd5b6020830194508093505050509295985092959850929598565b8481526000602085151581840152608060408401526151d66080840186614372565b8381036060850152845180825282820190600581901b8301840184880160005b83811015615242577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018552615230838351614372565b948701949250908601906001016151f6565b50909b9a5050505050505050505050565b80357fffffffff000000000000000000000000000000000000000000000000000000008116811461431657600080fd5b6000602080838503121561529657600080fd5b823567ffffffffffffffff8111156152ad57600080fd5b8301601f810185136152be57600080fd5b80356152cc61462e826145b2565b81815261022091820283018401918482019190888411156152ec57600080fd5b938501935b838510156146f2578489038181121561530a5760008081fd5b6153126144ad565b61531b87614954565b8152610200807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0840112156153505760008081fd5b61535861451c565b925061536589890161470c565b83526040615374818a01614b2f565b8a8501526060615385818b01614b1b565b8286015260809150615398828b01614b1b565b9085015260a06153a98a8201614b1b565b8286015260c091506153bc828b01614b2f565b9085015260e06153cd8a8201614b1b565b8286015261010091506153e1828b01614b2f565b908501526101206153f38a8201614b2f565b828601526101409150615407828b01614b2f565b908501526101606154198a8201614b1b565b82860152610180915061542d828b01614b1b565b908501526101a061543f8a8201614954565b828601526101c09150615453828b01614b1b565b908501526101e06154658a820161470c565b82860152615474838b01615253565b90850152505080880191909152835293840193918501916152f1565b600060208083850312156154a357600080fd5b823567ffffffffffffffff8111156154ba57600080fd5b8301601f810185136154cb57600080fd5b80356154d961462e826145b2565b81815260069190911b820183019083810190878311156154f857600080fd5b928401925b8284101561554a57604084890312156155165760008081fd5b61551e6144ad565b615527856142f2565b8152615534868601614954565b81870152825260409390930192908401906154fd565b979650505050505050565b6000806040838503121561556857600080fd5b61557183614954565b9150602083013567ffffffffffffffff81111561558d57600080fd5b830160a0818603121561559f57600080fd5b809150509250929050565b600080604083850312156155bd57600080fd5b6155c6836142f2565b9150614e8460208401614954565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082028115828204841417610f4d57610f4d6155d4565b600082615650577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261568a57600080fd5b83018035915067ffffffffffffffff8211156156a557600080fd5b6020019150600681901b3603821315611f9957600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b80357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116811461431657600080fd5b60006040828403121561572a57600080fd5b6157326144ad565b61573b836142f2565b8152615749602084016156ec565b60208201529392505050565b60006040828403121561576757600080fd5b61576f6144ad565b61573b83614954565b6000602080838503121561578b57600080fd5b823567ffffffffffffffff8111156157a257600080fd5b8301601f810185136157b357600080fd5b80356157c161462e826145b2565b818152606091820283018401918482019190888411156157e057600080fd5b938501935b838510156146f25780858a0312156157fd5760008081fd5b615805614540565b61580e866142f2565b815261581b8787016156ec565b87820152604061582c818801614b1b565b90820152835293840193918501916157e5565b81810381811115610f4d57610f4d6155d4565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261588757600080fd5b83018035915067ffffffffffffffff8211156158a257600080fd5b602001915036819003821315611f9957600080fd5b80820180821115610f4d57610f4d6155d4565b60ff8181168382160190811115610f4d57610f4d6155d4565b600181815b8085111561593c57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115615922576159226155d4565b8085161561592f57918102915b93841c93908002906158e8565b509250929050565b60008261595357506001610f4d565b8161596057506000610f4d565b816001811461597657600281146159805761599c565b6001915050610f4d565b60ff841115615991576159916155d4565b50506001821b610f4d565b5060208310610133831016604e8410600b84101617156159bf575081810a610f4d565b6159c983836158e3565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156159fb576159fb6155d4565b029392505050565b6000610b658383615944565b7fffffffff000000000000000000000000000000000000000000000000000000008135818116916004851015614b135760049490940360031b84901b1690921692915050565b60008085851115615a6557600080fd5b83861115615a7257600080fd5b5050820193919092039150565b600060408284031215615a9157600080fd5b615a996144ad565b825181526020830151615749816146fe565b600060208284031215615abd57600080fd5b5051919050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61833603018112615af857600080fd5b9190910192915050565b805169ffffffffffffffffffff8116811461431657600080fd5b600080600080600060a08688031215615b3457600080fd5b615b3d86615b02565b9450602086015193506040860151925060608601519150615b6060808701615b02565b90509295509295909350565b600060208284031215615b7e57600080fd5b8151610b65816145d6565b600060408284031215615b9b57600080fd5b615ba36144ad565b615bac836142f2565b8152602083013560208201528091505092915050565b63ffffffff8181168382160190808211156141e0576141e06155d4565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint96\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"linkToken\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"stalenessThreshold\",\"type\":\"uint32\"}],\"internalType\":\"structFeeQuoter.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"priceUpdaters\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"feeTokens\",\"type\":\"address[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"}],\"internalType\":\"structFeeQuoter.TokenPriceFeedConfig\",\"name\":\"feedConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.TokenPriceFeedUpdate[]\",\"name\":\"tokenPriceFeeds\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigSingleTokenArgs[]\",\"name\":\"tokenTransferFeeConfigs\",\"type\":\"tuple[]\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigArgs[]\",\"name\":\"tokenTransferFeeConfigArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"internalType\":\"structFeeQuoter.PremiumMultiplierWeiPerEthArgs[]\",\"name\":\"premiumMultiplierWeiPerEthArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chain\",\"type\":\"uint64\"}],\"name\":\"ChainNotSupported\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DataFeedValueOutOfUint224Range\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"DestinationChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ExtraArgOutOfOrderExecutionMustBeTrue\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"FeeTokenNotSupported\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"}],\"name\":\"InvalidDestBytesOverhead\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidDestChainConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidEVMAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidExtraArgsTag\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidStaticConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"msgFeeJuels\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint256\"}],\"name\":\"MessageFeeTooHigh\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MessageGasLimitTooHigh\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"maxSize\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actualSize\",\"type\":\"uint256\"}],\"name\":\"MessageTooLarge\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"internalType\":\"bytes10\",\"name\":\"workflowName\",\"type\":\"bytes10\"},{\"internalType\":\"bytes2\",\"name\":\"reportName\",\"type\":\"bytes2\"}],\"name\":\"ReportForwarderUnauthorized\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"SourceTokenDataTooLarge\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"threshold\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timePassed\",\"type\":\"uint256\"}],\"name\":\"StaleGasPrice\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feedTimestamp\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"storedTimeStamp\",\"type\":\"uint256\"}],\"name\":\"StaleKeystoneUpdate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"TokenNotSupported\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"UnauthorizedCaller\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnsupportedNumberOfTokens\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"AuthorizedCallerAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"}],\"name\":\"AuthorizedCallerRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"indexed\":false,\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"name\":\"DestChainAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"indexed\":false,\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"name\":\"DestChainConfigUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"}],\"name\":\"FeeTokenAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"}],\"name\":\"FeeTokenRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"name\":\"PremiumMultiplierWeiPerEthUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"}],\"indexed\":false,\"internalType\":\"structFeeQuoter.TokenPriceFeedConfig\",\"name\":\"priceFeedConfig\",\"type\":\"tuple\"}],\"name\":\"PriceFeedPerTokenUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"reportId\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"},{\"internalType\":\"bytes10\",\"name\":\"workflowName\",\"type\":\"bytes10\"},{\"internalType\":\"bytes2\",\"name\":\"reportName\",\"type\":\"bytes2\"},{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isAllowed\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"structKeystoneFeedsPermissionHandler.Permission\",\"name\":\"permission\",\"type\":\"tuple\"}],\"name\":\"ReportPermissionSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"TokenTransferFeeConfigDeleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"indexed\":false,\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"name\":\"TokenTransferFeeConfigUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"UsdPerTokenUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChain\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"}],\"name\":\"UsdPerUnitGasUpdated\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"FEE_BASE_DECIMALS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"KEYSTONE_PRICE_DECIMALS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address[]\",\"name\":\"addedCallers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"removedCallers\",\"type\":\"address[]\"}],\"internalType\":\"structAuthorizedCallers.AuthorizedCallerArgs\",\"name\":\"authorizedCallerArgs\",\"type\":\"tuple\"}],\"name\":\"applyAuthorizedCallerUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"destChainConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyDestChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"feeTokensToAdd\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"feeTokensToRemove\",\"type\":\"address[]\"}],\"name\":\"applyFeeTokensUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"internalType\":\"structFeeQuoter.PremiumMultiplierWeiPerEthArgs[]\",\"name\":\"premiumMultiplierWeiPerEthArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyPremiumMultiplierWeiPerEthUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigSingleTokenArgs[]\",\"name\":\"tokenTransferFeeConfigs\",\"type\":\"tuple[]\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigArgs[]\",\"name\":\"tokenTransferFeeConfigArgs\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfigRemoveArgs[]\",\"name\":\"tokensToUseDefaultFeeConfigs\",\"type\":\"tuple[]\"}],\"name\":\"applyTokenTransferFeeConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"fromToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fromTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"toToken\",\"type\":\"address\"}],\"name\":\"convertTokenAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllAuthorizedCallers\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getDestChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint16\",\"name\":\"maxNumberOfTokensPerMsg\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxDataBytes\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerMsgGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerPayloadByte\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destDataAvailabilityOverheadGas\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"destGasPerDataAvailabilityByte\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"destDataAvailabilityMultiplierBps\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"defaultTokenFeeUSDCents\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"defaultTokenDestGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"defaultTxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"gasMultiplierWeiPerEth\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"networkFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"enforceOutOfOrder\",\"type\":\"bool\"},{\"internalType\":\"bytes4\",\"name\":\"chainFamilySelector\",\"type\":\"bytes4\"}],\"internalType\":\"structFeeQuoter.DestChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getDestinationChainGasPrice\",\"outputs\":[{\"components\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"internalType\":\"structInternal.TimestampedPackedUint224\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getFeeTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getPremiumMultiplierWeiPerEth\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"premiumMultiplierWeiPerEth\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint96\",\"name\":\"maxFeeJuelsPerMsg\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"linkToken\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"stalenessThreshold\",\"type\":\"uint32\"}],\"internalType\":\"structFeeQuoter.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getTokenAndGasPrices\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"tokenPrice\",\"type\":\"uint224\"},{\"internalType\":\"uint224\",\"name\":\"gasPriceValue\",\"type\":\"uint224\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenPrice\",\"outputs\":[{\"components\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"internalType\":\"structInternal.TimestampedPackedUint224\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenPriceFeedConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"}],\"internalType\":\"structFeeQuoter.TokenPriceFeedConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"tokens\",\"type\":\"address[]\"}],\"name\":\"getTokenPrices\",\"outputs\":[{\"components\":[{\"internalType\":\"uint224\",\"name\":\"value\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"timestamp\",\"type\":\"uint32\"}],\"internalType\":\"structInternal.TimestampedPackedUint224[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getTokenTransferFeeConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"minFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxFeeUSDCents\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"deciBps\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"destGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"destBytesOverhead\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"}],\"internalType\":\"structFeeQuoter.TokenTransferFeeConfig\",\"name\":\"tokenTransferFeeConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"getValidatedFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getValidatedTokenPrice\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"\",\"type\":\"uint224\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"metadata\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"onReport\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"sourcePoolAddress\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.EVM2AnyTokenTransfer[]\",\"name\":\"onRampTokenTransfers\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"sourceTokenAmounts\",\"type\":\"tuple[]\"}],\"name\":\"processMessageArgs\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"msgFeeJuels\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isOutOfOrderExecution\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"convertedExtraArgs\",\"type\":\"bytes\"},{\"internalType\":\"bytes[]\",\"name\":\"destExecDataPerToken\",\"type\":\"bytes[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"},{\"internalType\":\"bytes10\",\"name\":\"workflowName\",\"type\":\"bytes10\"},{\"internalType\":\"bytes2\",\"name\":\"reportName\",\"type\":\"bytes2\"},{\"internalType\":\"address\",\"name\":\"workflowOwner\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isAllowed\",\"type\":\"bool\"}],\"internalType\":\"structKeystoneFeedsPermissionHandler.Permission[]\",\"name\":\"permissions\",\"type\":\"tuple[]\"}],\"name\":\"setReportPermissions\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"}],\"name\":\"updatePrices\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"dataFeedAddress\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"tokenDecimals\",\"type\":\"uint8\"}],\"internalType\":\"structFeeQuoter.TokenPriceFeedConfig\",\"name\":\"feedConfig\",\"type\":\"tuple\"}],\"internalType\":\"structFeeQuoter.TokenPriceFeedUpdate[]\",\"name\":\"tokenPriceFeedUpdates\",\"type\":\"tuple[]\"}],\"name\":\"updateTokenPriceFeeds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x60e06040523480156200001157600080fd5b506040516200776138038062007761833981016040819052620000349162001834565b8533806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf8162000207565b5050604080518082018252838152815160008152602080820190935291810191909152620000ee9150620002b2565b5060208701516001600160a01b0316158062000112575086516001600160601b0316155b80620001265750604087015163ffffffff16155b15620001455760405163d794ef9560e01b815260040160405180910390fd5b6020878101516001600160a01b031660a05287516001600160601b031660805260408089015163ffffffff1660c05280516000815291820190526200018c90869062000401565b620001978462000549565b620001a2816200061a565b620001ad8262000a5a565b60408051600080825260208201909252620001fa91859190620001f3565b6040805180820190915260008082526020820152815260200190600190039081620001cb5790505b5062000b26565b5050505050505062001ae5565b336001600160a01b03821603620002615760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b602081015160005b815181101562000342576000828281518110620002db57620002db62001953565b60209081029190910101519050620002f560028262000e5f565b1562000338576040516001600160a01b03821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b50600101620002ba565b50815160005b8151811015620003fb57600082828151811062000369576200036962001953565b6020026020010151905060006001600160a01b0316816001600160a01b031603620003a7576040516342bcdf7f60e11b815260040160405180910390fd5b620003b460028262000e7f565b506040516001600160a01b03821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a15060010162000348565b50505050565b60005b8251811015620004a2576200044083828151811062000427576200042762001953565b6020026020010151600b62000e7f60201b90919060201c565b1562000499578281815181106200045b576200045b62001953565b60200260200101516001600160a01b03167fdf1b1bd32a69711488d71554706bb130b1fc63a5fa1a2cd85e8440f84065ba2360405160405180910390a25b60010162000404565b5060005b81518110156200054457620004e2828281518110620004c957620004c962001953565b6020026020010151600b62000e9660201b90919060201c565b156200053b57818181518110620004fd57620004fd62001953565b60200260200101516001600160a01b03167f1795838dc8ab2ffc5f431a1729a6afa0b587f982f7b2be0b9d7187a1ef547f9160405160405180910390a25b600101620004a6565b505050565b60005b8151811015620006165760008282815181106200056d576200056d62001953565b6020908102919091018101518051818301516001600160a01b0380831660008181526007875260409081902084518154868a018051929096166001600160a81b03199091168117600160a01b60ff9384160217909255825191825293519093169683019690965293955091939092917f08a5f7f5bb38a81d8e43aca13ecd76431dbf8816ae4699affff7b00b2fc1c464910160405180910390a25050508060010190506200054c565b5050565b60005b8151811015620006165760008282815181106200063e576200063e62001953565b6020026020010151905060008383815181106200065f576200065f62001953565b6020026020010151600001519050600082602001519050816001600160401b03166000148062000698575061016081015163ffffffff16155b80620006ba57506101e08101516001600160e01b031916630a04b54b60e21b14155b80620006da5750806060015163ffffffff1681610160015163ffffffff16115b15620007055760405163c35aa79d60e01b81526001600160401b038316600482015260240162000083565b6001600160401b038216600090815260096020526040812060010154600160881b900460e01b6001600160e01b03191690036200078557816001600160401b03167fd31c671936387b2f84ed402b553bd50c0e9c20408ea4e91a836d77b8180fb7248260405162000777919062001969565b60405180910390a2620007c9565b816001600160401b03167f1edd6f3553cfa16f10b95b195abae3a1cfca4783de4843f95d674b1e1df5ab2082604051620007c0919062001969565b60405180910390a25b8060096000846001600160401b03166001600160401b0316815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548161ffff021916908361ffff16021790555060408201518160000160036101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160076101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600b6101000a81548163ffffffff021916908363ffffffff16021790555060a082015181600001600f6101000a81548161ffff021916908361ffff16021790555060c08201518160000160116101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160000160156101000a81548161ffff021916908361ffff1602179055506101008201518160000160176101000a81548161ffff021916908361ffff1602179055506101208201518160000160196101000a81548161ffff021916908361ffff16021790555061014082015181600001601b6101000a81548163ffffffff021916908363ffffffff1602179055506101608201518160010160006101000a81548163ffffffff021916908363ffffffff1602179055506101808201518160010160046101000a8154816001600160401b0302191690836001600160401b031602179055506101a082015181600101600c6101000a81548163ffffffff021916908363ffffffff1602179055506101c08201518160010160106101000a81548160ff0219169083151502179055506101e08201518160010160116101000a81548163ffffffff021916908360e01c02179055509050505050508060010190506200061d565b60005b81518110156200061657600082828151811062000a7e5762000a7e62001953565b6020026020010151600001519050600083838151811062000aa35762000aa362001953565b6020908102919091018101518101516001600160a01b03841660008181526008845260409081902080546001600160401b0319166001600160401b0385169081179091559051908152919350917fbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d910160405180910390a2505060010162000a5d565b60005b825181101562000d9957600083828151811062000b4a5762000b4a62001953565b6020026020010151905060008160000151905060005b82602001515181101562000d8a5760008360200151828151811062000b895762000b8962001953565b602002602001015160200151905060008460200151838151811062000bb25762000bb262001953565b6020026020010151600001519050602063ffffffff16826080015163ffffffff16101562000c115760808201516040516312766e0160e11b81526001600160a01b038316600482015263ffffffff909116602482015260440162000083565b6001600160401b0384166000818152600a602090815260408083206001600160a01b0386168085529083529281902086518154938801518389015160608a015160808b015160a08c01511515600160901b0260ff60901b1963ffffffff928316600160701b021664ffffffffff60701b199383166a01000000000000000000000263ffffffff60501b1961ffff90961668010000000000000000029590951665ffffffffffff60401b19968416640100000000026001600160401b0319909b16939097169290921798909817939093169390931717919091161792909217909155519091907f94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b59062000d77908690600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60405180910390a3505060010162000b60565b50505080600101905062000b29565b5060005b81518110156200054457600082828151811062000dbe5762000dbe62001953565b6020026020010151600001519050600083838151811062000de35762000de362001953565b6020908102919091018101518101516001600160401b0384166000818152600a845260408082206001600160a01b038516808452955280822080546001600160981b03191690555192945090917f4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b9190a3505060010162000d9d565b600062000e76836001600160a01b03841662000ead565b90505b92915050565b600062000e76836001600160a01b03841662000fb1565b600062000e76836001600160a01b03841662001003565b6000818152600183016020526040812054801562000fa657600062000ed460018362001aad565b855490915060009062000eea9060019062001aad565b905081811462000f5657600086600001828154811062000f0e5762000f0e62001953565b906000526020600020015490508087600001848154811062000f345762000f3462001953565b6000918252602080832090910192909255918252600188019052604090208390555b855486908062000f6a5762000f6a62001acf565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505062000e79565b600091505062000e79565b600081815260018301602052604081205462000ffa5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562000e79565b50600062000e79565b6000818152600183016020526040812054801562000fa65760006200102a60018362001aad565b8554909150600090620010409060019062001aad565b905080821462000f5657600086600001828154811062000f0e5762000f0e62001953565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b03811182821017156200109f576200109f62001064565b60405290565b60405160c081016001600160401b03811182821017156200109f576200109f62001064565b60405161020081016001600160401b03811182821017156200109f576200109f62001064565b604051601f8201601f191681016001600160401b03811182821017156200111b576200111b62001064565b604052919050565b80516001600160a01b03811681146200113b57600080fd5b919050565b805163ffffffff811681146200113b57600080fd5b6000606082840312156200116857600080fd5b604051606081016001600160401b03811182821017156200118d576200118d62001064565b604052825190915081906001600160601b0381168114620011ad57600080fd5b8152620011bd6020840162001123565b6020820152620011d06040840162001140565b60408201525092915050565b60006001600160401b03821115620011f857620011f862001064565b5060051b60200190565b600082601f8301126200121457600080fd5b815160206200122d6200122783620011dc565b620010f0565b8083825260208201915060208460051b8701019350868411156200125057600080fd5b602086015b848110156200127757620012698162001123565b835291830191830162001255565b509695505050505050565b600082601f8301126200129457600080fd5b81516020620012a76200122783620011dc565b82815260609283028501820192828201919087851115620012c757600080fd5b8387015b858110156200135a5780890382811215620012e65760008081fd5b620012f06200107a565b620012fb8362001123565b8152604080601f1984011215620013125760008081fd5b6200131c6200107a565b92506200132b88850162001123565b835283015160ff81168114620013415760008081fd5b82880152808701919091528452928401928101620012cb565b5090979650505050505050565b80516001600160401b03811681146200113b57600080fd5b805161ffff811681146200113b57600080fd5b805180151581146200113b57600080fd5b600082601f830112620013b557600080fd5b81516020620013c86200122783620011dc565b82815260059290921b84018101918181019086841115620013e857600080fd5b8286015b84811015620012775780516001600160401b03808211156200140d57600080fd5b908801906040601f19838c0381018213156200142857600080fd5b620014326200107a565b6200143f89860162001367565b815282850151848111156200145357600080fd5b8086019550508c603f8601126200146957600080fd5b8885015193506200147e6200122785620011dc565b84815260e09094028501830193898101908e8611156200149d57600080fd5b958401955b858710156200157657868f0360e0811215620014bd57600080fd5b620014c76200107a565b620014d28962001123565b815260c08683011215620014e557600080fd5b620014ef620010a5565b9150620014fe8d8a0162001140565b82526200150d878a0162001140565b8d8301526200151f60608a016200137f565b878301526200153160808a0162001140565b60608301526200154460a08a0162001140565b60808301526200155760c08a0162001392565b60a0830152808d0191909152825260e09690960195908a0190620014a2565b828b015250875250505092840192508301620013ec565b600082601f8301126200159f57600080fd5b81516020620015b26200122783620011dc565b82815260069290921b84018101918181019086841115620015d257600080fd5b8286015b84811015620012775760408189031215620015f15760008081fd5b620015fb6200107a565b620016068262001123565b81526200161585830162001367565b81860152835291830191604001620015d6565b80516001600160e01b0319811681146200113b57600080fd5b600082601f8301126200165357600080fd5b81516020620016666200122783620011dc565b82815261022092830285018201928282019190878511156200168757600080fd5b8387015b858110156200135a5780890382811215620016a65760008081fd5b620016b06200107a565b620016bb8362001367565b815261020080601f1984011215620016d35760008081fd5b620016dd620010ca565b9250620016ec88850162001392565b83526040620016fd8186016200137f565b8985015260606200171081870162001140565b82860152608091506200172582870162001140565b9085015260a06200173886820162001140565b8286015260c091506200174d8287016200137f565b9085015260e06200176086820162001140565b828601526101009150620017768287016200137f565b908501526101206200178a8682016200137f565b828601526101409150620017a08287016200137f565b90850152610160620017b486820162001140565b828601526101809150620017ca82870162001140565b908501526101a0620017de86820162001367565b828601526101c09150620017f482870162001140565b908501526101e06200180886820162001392565b828601526200181983870162001628565b9085015250508087019190915284529284019281016200168b565b6000806000806000806000610120888a0312156200185157600080fd5b6200185d898962001155565b60608901519097506001600160401b03808211156200187b57600080fd5b620018898b838c0162001202565b975060808a0151915080821115620018a057600080fd5b620018ae8b838c0162001202565b965060a08a0151915080821115620018c557600080fd5b620018d38b838c0162001282565b955060c08a0151915080821115620018ea57600080fd5b620018f88b838c01620013a3565b945060e08a01519150808211156200190f57600080fd5b6200191d8b838c016200158d565b93506101008a01519150808211156200193557600080fd5b50620019448a828b0162001641565b91505092959891949750929550565b634e487b7160e01b600052603260045260246000fd5b815115158152610200810160208301516200198a602084018261ffff169052565b506040830151620019a3604084018263ffffffff169052565b506060830151620019bc606084018263ffffffff169052565b506080830151620019d5608084018263ffffffff169052565b5060a0830151620019ec60a084018261ffff169052565b5060c083015162001a0560c084018263ffffffff169052565b5060e083015162001a1c60e084018261ffff169052565b506101008381015161ffff9081169184019190915261012080850151909116908301526101408084015163ffffffff9081169184019190915261016080850151821690840152610180808501516001600160401b0316908401526101a080850151909116908301526101c0808401511515908301526101e0928301516001600160e01b031916929091019190915290565b8181038181111562000e7957634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b60805160a05160c051615c1b62001b46600039600081816102fa0152818161184d01528181611ee90152611f520152600081816102be01528181610e900152610ef001526000818161028a01528181610f190152610f890152615c1b6000f3fe608060405234801561001057600080fd5b50600436106101d95760003560e01c806379ba509711610104578063a69c64c0116100a2578063d63d3af211610071578063d63d3af214610a88578063d8694ccd14610a90578063f2fde38b14610aa3578063ffdb4b3714610ab657600080fd5b8063a69c64c0146109ad578063bf78e03f146109c0578063cdc73d5114610a6d578063d02641a014610a7557600080fd5b806382b49eb0116100de57806382b49eb0146107ef5780638da5cb5b1461095f57806391a2749a146109875780639ea600261461099a57600080fd5b806379ba5097146107c15780637afac322146107c9578063805f2132146107dc57600080fd5b8063407e10861161017c5780634ab35b0b1161014b5780634ab35b0b14610457578063514e8cff146104975780636def4ce71461053a578063770e2dc4146107ae57600080fd5b8063407e1086146103ee57806341ed29e714610401578063430d138c1461041457806345ac924d1461043757600080fd5b8063181f5a77116101b8578063181f5a77146103735780632451a627146103bc578063325c868e146103d15780633937306f146103d957600080fd5b806241e5be146101de578063061877e31461020457806306285c691461025d575b600080fd5b6101f16101ec36600461431b565b610afe565b6040519081526020015b60405180910390f35b610244610212366004614357565b73ffffffffffffffffffffffffffffffffffffffff1660009081526008602052604090205467ffffffffffffffff1690565b60405167ffffffffffffffff90911681526020016101fb565b610327604080516060810182526000808252602082018190529181019190915260405180606001604052807f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000063ffffffff16815250905090565b6040805182516bffffffffffffffffffffffff16815260208084015173ffffffffffffffffffffffffffffffffffffffff16908201529181015163ffffffff16908201526060016101fb565b6103af6040518060400160405280601381526020017f46656551756f74657220312e362e302d6465760000000000000000000000000081525081565b6040516101fb91906143d6565b6103c4610b6c565b6040516101fb91906143e9565b6101f1602481565b6103ec6103e7366004614443565b610b7d565b005b6103ec6103fc3660046145e5565b610e32565b6103ec61040f366004614717565b610e46565b6104276104223660046148f1565b610e88565b6040516101fb94939291906149e5565b61044a610445366004614a84565b611098565b6040516101fb9190614ac6565b61046a610465366004614357565b611163565b6040517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff90911681526020016101fb565b61052d6104a5366004614b41565b60408051808201909152600080825260208201525067ffffffffffffffff166000908152600560209081526040918290208251808401909352547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811683527c0100000000000000000000000000000000000000000000000000000000900463ffffffff169082015290565b6040516101fb9190614b5c565b6107a1610548366004614b41565b6040805161020081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a081018290526101c081018290526101e08101919091525067ffffffffffffffff908116600090815260096020908152604091829020825161020081018452815460ff8082161515835261ffff61010080840482169685019690965263ffffffff630100000084048116978501979097526701000000000000008304871660608501526b0100000000000000000000008304871660808501526f010000000000000000000000000000008304811660a085015271010000000000000000000000000000000000808404881660c086015275010000000000000000000000000000000000000000008404821660e08087019190915277010000000000000000000000000000000000000000000000850483169786019790975279010000000000000000000000000000000000000000000000000084049091166101208501527b01000000000000000000000000000000000000000000000000000000909204861661014084015260019093015480861661016084015264010000000081049096166101808301526c0100000000000000000000000086049094166101a0820152700100000000000000000000000000000000850490911615156101c08201527fffffffff0000000000000000000000000000000000000000000000000000000092909304901b166101e082015290565b6040516101fb9190614b97565b6103ec6107bc366004614dae565b61116e565b6103ec611180565b6103ec6107d73660046150c8565b61127d565b6103ec6107ea36600461512c565b61128f565b6108ff6107fd366004615198565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101919091525067ffffffffffffffff919091166000908152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff94909416835292815290829020825160c081018452905463ffffffff8082168352640100000000820481169383019390935268010000000000000000810461ffff16938201939093526a01000000000000000000008304821660608201526e01000000000000000000000000000083049091166080820152720100000000000000000000000000000000000090910460ff16151560a082015290565b6040516101fb9190600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101fb565b6103ec6109953660046151c2565b611777565b6103ec6109a8366004615283565b611788565b6103ec6109bb366004615490565b611799565b610a396109ce366004614357565b6040805180820182526000808252602091820181905273ffffffffffffffffffffffffffffffffffffffff93841681526007825282902082518084019093525492831682527401000000000000000000000000000000000000000090920460ff169181019190915290565b60408051825173ffffffffffffffffffffffffffffffffffffffff16815260209283015160ff1692810192909252016101fb565b6103c46117aa565b61052d610a83366004614357565b6117b6565b6101f1601281565b6101f1610a9e366004615555565b6118fa565b6103ec610ab1366004614357565b611e04565b610ac9610ac43660046155aa565b611e15565b604080517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff9384168152929091166020830152016101fb565b6000610b0982611fa0565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16610b3085611fa0565b610b58907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1685615603565b610b62919061561a565b90505b9392505050565b6060610b78600261203a565b905090565b610b85612047565b6000610b918280615655565b9050905060005b81811015610cdb576000610bac8480615655565b83818110610bbc57610bbc6156bd565b905060400201803603810190610bd29190615718565b604080518082018252602080840180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff908116845263ffffffff42818116858701908152885173ffffffffffffffffffffffffffffffffffffffff9081166000908152600690975295889020965190519092167c010000000000000000000000000000000000000000000000000000000002919092161790935584519051935194955016927f52f50aa6d1a95a4595361ecf953d095f125d442e4673716dede699e049de148a92610cca9290917bffffffffffffffffffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b60405180910390a250600101610b98565b506000610ceb6020840184615655565b9050905060005b81811015610e2c576000610d096020860186615655565b83818110610d1957610d196156bd565b905060400201803603810190610d2f9190615755565b604080518082018252602080840180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff908116845263ffffffff42818116858701908152885167ffffffffffffffff9081166000908152600590975295889020965190519092167c010000000000000000000000000000000000000000000000000000000002919092161790935584519051935194955016927fdd84a3fa9ef9409f550d54d6affec7e9c480c878c6ab27b78912a03e1b371c6e92610e1b9290917bffffffffffffffffffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b60405180910390a250600101610cf2565b50505050565b610e3a61208c565b610e438161210d565b50565b610e4e61208c565b60005b8151811015610e8457610e7c828281518110610e6f57610e6f6156bd565b602002602001015161220b565b600101610e51565b5050565b6000806060807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168c73ffffffffffffffffffffffffffffffffffffffff1603610ee9578a9350610f17565b610f148c8c7f0000000000000000000000000000000000000000000000000000000000000000610afe565b93505b7f00000000000000000000000000000000000000000000000000000000000000006bffffffffffffffffffffffff16841115610fbb576040517f6a92a483000000000000000000000000000000000000000000000000000000008152600481018590526bffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001660248201526044015b60405180910390fd5b67ffffffffffffffff8d1660009081526009602052604081206001015463ffffffff1690610fea8c8c846123dd565b9050806020015194506110008f8b8b8b8b612586565b92508585611080836040805182516024820152602092830151151560448083019190915282518083039091018152606490910190915290810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f181dcf100000000000000000000000000000000000000000000000000000000017905290565b95509550955050509950995099509995505050505050565b60608160008167ffffffffffffffff8111156110b6576110b661447e565b6040519080825280602002602001820160405280156110fb57816020015b60408051808201909152600080825260208201528152602001906001900390816110d45790505b50905060005b828110156111585761113386868381811061111e5761111e6156bd565b9050602002016020810190610a839190614357565b828281518110611145576111456156bd565b6020908102919091010152600101611101565b509150505b92915050565b600061115d82611fa0565b61117661208c565b610e8482826128f3565b60015473ffffffffffffffffffffffffffffffffffffffff163314611201576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610fb2565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b61128561208c565b610e848282612d05565b60008060006112d387878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612e4c92505050565b9250925092506112e533838584612e67565b60006112f385870187615778565b905060005b815181101561176c57600060076000848481518110611319576113196156bd565b6020908102919091018101515173ffffffffffffffffffffffffffffffffffffffff16825281019190915260400160009081205474010000000000000000000000000000000000000000900460ff1691508190036113da57828281518110611383576113836156bd565b6020908102919091010151516040517f06439c6b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610fb2565b60006114236012838686815181106113f4576113f46156bd565b6020026020010151602001517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16612fbf565b90506006600085858151811061143b5761143b6156bd565b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600001601c9054906101000a900463ffffffff1663ffffffff168484815181106114ad576114ad6156bd565b60200260200101516040015163ffffffff1610156115b7578383815181106114d7576114d76156bd565b6020026020010151600001518484815181106114f5576114f56156bd565b60200260200101516040015160066000878781518110611517576115176156bd565b6020908102919091018101515173ffffffffffffffffffffffffffffffffffffffff90811683529082019290925260409081016000205490517f191ec70600000000000000000000000000000000000000000000000000000000815293909116600484015263ffffffff91821660248401527c01000000000000000000000000000000000000000000000000000000009004166044820152606401610fb2565b6040518060400160405280827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1681526020018585815181106115f8576115f86156bd565b60200260200101516040015163ffffffff1681525060066000868681518110611623576116236156bd565b6020908102919091018101515173ffffffffffffffffffffffffffffffffffffffff168252818101929092526040016000208251929091015163ffffffff167c0100000000000000000000000000000000000000000000000000000000027bffffffffffffffffffffffffffffffffffffffffffffffffffffffff90921691909117905583518490849081106116bb576116bb6156bd565b60200260200101516000015173ffffffffffffffffffffffffffffffffffffffff167f52f50aa6d1a95a4595361ecf953d095f125d442e4673716dede699e049de148a82868681518110611711576117116156bd565b60200260200101516040015160405161175a9291907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff92909216825263ffffffff16602082015260400190565b60405180910390a250506001016112f8565b505050505050505050565b61177f61208c565b610e438161308b565b61179061208c565b610e4381613217565b6117a161208c565b610e43816136bd565b6060610b78600b61203a565b604080518082019091526000808252602082015273ffffffffffffffffffffffffffffffffffffffff82166000908152600660209081526040918290208251808401909352547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116835263ffffffff7c010000000000000000000000000000000000000000000000000000000090910481169183018290527f00000000000000000000000000000000000000000000000000000000000000001690611878904261583f565b10156118845792915050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600760209081526040918290208251808401909352549283168083527401000000000000000000000000000000000000000090930460ff1690820152906118e9575092915050565b6118f2816137a7565b949350505050565b67ffffffffffffffff8083166000908152600960209081526040808320815161020081018352815460ff808216151580845261ffff61010080850482169886019890985263ffffffff630100000085048116978601979097526701000000000000008404871660608601526b0100000000000000000000008404871660808601526f010000000000000000000000000000008404811660a086015271010000000000000000000000000000000000808504881660c087015275010000000000000000000000000000000000000000008504821660e08088019190915277010000000000000000000000000000000000000000000000860483169987019990995279010000000000000000000000000000000000000000000000000085049091166101208601527b01000000000000000000000000000000000000000000000000000000909304861661014085015260019094015480861661016085015264010000000081049098166101808401526c0100000000000000000000000088049094166101a0830152700100000000000000000000000000000000870490931615156101c08201527fffffffff000000000000000000000000000000000000000000000000000000009290950490921b166101e0840152909190611b14576040517f99ac52f200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff85166004820152602401610fb2565b611b2f611b276080850160608601614357565b600b90613936565b611b8e57611b436080840160608501614357565b6040517f2502348c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610fb2565b6000611b9d6040850185615655565b9150611bf9905082611bb26020870187615852565b905083611bbf8880615852565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061396592505050565b600080611c15611c0f6080880160608901614357565b88611e15565b9092509050600080808515611c5857611c4c878b611c3960808d0160608e01614357565b88611c4760408f018f615655565b613a0f565b91945092509050611c78565b6101a0870151611c759063ffffffff16662386f26fc10000615603565b92505b61010087015160009061ffff1615611cbc57611cb9886dffffffffffffffffffffffffffff607088901c16611cb060208e018e615852565b90508a86613ce7565b90505b61018088015160009067ffffffffffffffff16611ce5611cdf60808e018e615852565b8c613d97565b600001518563ffffffff168b60a0015161ffff168e8060200190611d099190615852565b611d14929150615603565b8c6080015163ffffffff16611d2991906158b7565b611d3391906158b7565b611d3d91906158b7565b611d57906dffffffffffffffffffffffffffff8916615603565b611d619190615603565b9050867bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168282600860008f6060016020810190611d9b9190614357565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160002054611dd69067ffffffffffffffff1689615603565b611de091906158b7565b611dea91906158b7565b611df4919061561a565b9c9b505050505050505050505050565b611e0c61208c565b610e4381613e58565b67ffffffffffffffff811660009081526005602090815260408083208151808301909252547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811682527c0100000000000000000000000000000000000000000000000000000000900463ffffffff1691810182905282918203611ecd576040517f2e59db3a00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff85166004820152602401610fb2565b6000816020015163ffffffff1642611ee5919061583f565b90507f000000000000000000000000000000000000000000000000000000000000000063ffffffff16811115611f86576040517ff08bcb3e00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8616600482015263ffffffff7f000000000000000000000000000000000000000000000000000000000000000016602482015260448101829052606401610fb2565b611f8f86611fa0565b9151919350909150505b9250929050565b600080611fac836117b6565b9050806020015163ffffffff1660001480611fe4575080517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16155b15612033576040517f06439c6b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152602401610fb2565b5192915050565b60606000610b6583613f4d565b612052600233613936565b61208a576040517fd86ad9cf000000000000000000000000000000000000000000000000000000008152336004820152602401610fb2565b565b60005473ffffffffffffffffffffffffffffffffffffffff16331461208a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610fb2565b60005b8151811015610e8457600082828151811061212d5761212d6156bd565b60209081029190910181015180518183015173ffffffffffffffffffffffffffffffffffffffff80831660008181526007875260409081902084518154868a018051929096167fffffffffffffffffffffff00000000000000000000000000000000000000000090911681177401000000000000000000000000000000000000000060ff9384160217909255825191825293519093169683019690965293955091939092917f08a5f7f5bb38a81d8e43aca13ecd76431dbf8816ae4699affff7b00b2fc1c464910160405180910390a2505050806001019050612110565b60006122c482600001518360600151846020015185604001516040805173ffffffffffffffffffffffffffffffffffffffff80871660208301528516918101919091527fffffffffffffffffffff00000000000000000000000000000000000000000000831660608201527fffff0000000000000000000000000000000000000000000000000000000000008216608082015260009060a001604051602081830303815290604052805190602001209050949350505050565b60808301516000828152600460205260409081902080549215157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00909316929092179091555190915081907f32a4ba3fa3351b11ad555d4c8ec70a744e8705607077a946807030d64b6ab1a3906123d1908590600060a08201905073ffffffffffffffffffffffffffffffffffffffff8084511683527fffffffffffffffffffff0000000000000000000000000000000000000000000060208501511660208401527fffff00000000000000000000000000000000000000000000000000000000000060408501511660408401528060608501511660608401525060808301511515608083015292915050565b60405180910390a25050565b6040805180820190915260008082526020820152600083900361241e57506040805180820190915267ffffffffffffffff8216815260006020820152610b65565b600061242a84866158ca565b9050600061243b8560048189615910565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505050507fffffffff0000000000000000000000000000000000000000000000000000000082167fe7e230f000000000000000000000000000000000000000000000000000000000016124d857808060200190518101906124cf919061593a565b92505050610b65565b7f6859a837000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831601612554576040518060400160405280828060200190518101906125409190615966565b815260006020909101529250610b65915050565b6040517f5247fdce00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b67ffffffffffffffff8086166000908152600960205260409020600101546060917101000000000000000000000000000000000090910460e01b9085908111156125d2576125d261447e565b60405190808252806020026020018201604052801561260557816020015b60608152602001906001900390816125f05790505b50915060005b858110156128e8576000858583818110612627576126276156bd565b61263d9260206040909202019081019150614357565b90506000888884818110612653576126536156bd565b9050602002810190612665919061597f565b612673906040810190615852565b91505060208111156127235767ffffffffffffffff8a166000908152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff861684529091529020546e010000000000000000000000000000900463ffffffff16811115612723576040517f36f536ca00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83166004820152602401610fb2565b612793848a8a86818110612739576127396156bd565b905060200281019061274b919061597f565b612759906020810190615852565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250613fa992505050565b67ffffffffffffffff8a166000818152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684528252808320815160c081018352905463ffffffff8082168352640100000000820481168386015268010000000000000000820461ffff16838501526a01000000000000000000008204811660608401526e010000000000000000000000000000820481166080840152720100000000000000000000000000000000000090910460ff16151560a08301908152958552600990935290832054935190937b01000000000000000000000000000000000000000000000000000000900490911691906128925781612898565b82606001515b6040805163ffffffff83166020820152919250016040516020818303038152906040528887815181106128cd576128cd6156bd565b6020026020010181905250505050505080600101905061260b565b505095945050505050565b60005b8251811015612c1c576000838281518110612913576129136156bd565b6020026020010151905060008160000151905060005b826020015151811015612c0e5760008360200151828151811061294e5761294e6156bd565b6020026020010151602001519050600084602001518381518110612974576129746156bd565b6020026020010151600001519050602063ffffffff16826080015163ffffffff1610156129f75760808201516040517f24ecdc0200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8316600482015263ffffffff9091166024820152604401610fb2565b67ffffffffffffffff84166000818152600a6020908152604080832073ffffffffffffffffffffffffffffffffffffffff86168085529083529281902086518154938801518389015160608a015160808b015160a08c015115157201000000000000000000000000000000000000027fffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffff63ffffffff9283166e01000000000000000000000000000002167fffffffffffffffffffffffffff0000000000ffffffffffffffffffffffffffff9383166a0100000000000000000000027fffffffffffffffffffffffffffffffffffff00000000ffffffffffffffffffff61ffff9096166801000000000000000002959095167fffffffffffffffffffffffffffffffffffff000000000000ffffffffffffffff968416640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000909b16939097169290921798909817939093169390931717919091161792909217909155519091907f94967ae9ea7729ad4f54021c1981765d2b1d954f7c92fbec340aa0a54f46b8b590612bfc908690600060c08201905063ffffffff80845116835280602085015116602084015261ffff60408501511660408401528060608501511660608401528060808501511660808401525060a0830151151560a083015292915050565b60405180910390a35050600101612929565b5050508060010190506128f6565b5060005b8151811015612d00576000828281518110612c3d57612c3d6156bd565b60200260200101516000015190506000838381518110612c5f57612c5f6156bd565b60209081029190910181015181015167ffffffffffffffff84166000818152600a8452604080822073ffffffffffffffffffffffffffffffffffffffff8516808452955280822080547fffffffffffffffffffffffffff000000000000000000000000000000000000001690555192945090917f4de5b1bcbca6018c11303a2c3f4a4b4f22a1c741d8c4ba430d246ac06c5ddf8b9190a35050600101612c20565b505050565b60005b8251811015612da857612d3e838281518110612d2657612d266156bd565b6020026020010151600b613ffb90919063ffffffff16565b15612da057828181518110612d5557612d556156bd565b602002602001015173ffffffffffffffffffffffffffffffffffffffff167fdf1b1bd32a69711488d71554706bb130b1fc63a5fa1a2cd85e8440f84065ba2360405160405180910390a25b600101612d08565b5060005b8151811015612d0057612de2828281518110612dca57612dca6156bd565b6020026020010151600b61401d90919063ffffffff16565b15612e4457818181518110612df957612df96156bd565b602002602001015173ffffffffffffffffffffffffffffffffffffffff167f1795838dc8ab2ffc5f431a1729a6afa0b587f982f7b2be0b9d7187a1ef547f9160405160405180910390a25b600101612dac565b6040810151604a820151605e90920151909260609290921c91565b6040805173ffffffffffffffffffffffffffffffffffffffff868116602080840191909152908616828401527fffffffffffffffffffff00000000000000000000000000000000000000000000851660608301527fffff00000000000000000000000000000000000000000000000000000000000084166080808401919091528351808403909101815260a09092018352815191810191909120600081815260049092529190205460ff16612fb8576040517f097e17ff00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8087166004830152851660248201527fffffffffffffffffffff00000000000000000000000000000000000000000000841660448201527fffff00000000000000000000000000000000000000000000000000000000000083166064820152608401610fb2565b5050505050565b600080612fcc84866159bd565b9050600060248260ff16111561300657612fea602460ff841661583f565b612ff590600a615af6565b612fff908561561a565b905061302c565b61301460ff8316602461583f565b61301f90600a615af6565b6130299085615603565b90505b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811115613082576040517f10cb51d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b95945050505050565b602081015160005b81518110156131265760008282815181106130b0576130b06156bd565b602002602001015190506130ce81600261403f90919063ffffffff16565b1561311d5760405173ffffffffffffffffffffffffffffffffffffffff821681527fc3803387881faad271c47728894e3e36fac830ffc8602ca6fc07733cbda775809060200160405180910390a15b50600101613093565b50815160005b8151811015610e2c576000828281518110613149576131496156bd565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036131b9576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6131c4600282613ffb565b5060405173ffffffffffffffffffffffffffffffffffffffff821681527feb1b9b92e50b7f88f9ff25d56765095ac6e91540eee214906f4036a908ffbdef9060200160405180910390a15060010161312c565b60005b8151811015610e84576000828281518110613237576132376156bd565b602002602001015190506000838381518110613255576132556156bd565b60200260200101516000015190506000826020015190508167ffffffffffffffff166000148061328e575061016081015163ffffffff16155b806132e057506101e08101517fffffffff00000000000000000000000000000000000000000000000000000000167f2812d52c0000000000000000000000000000000000000000000000000000000014155b806132ff5750806060015163ffffffff1681610160015163ffffffff16115b15613342576040517fc35aa79d00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff83166004820152602401610fb2565b67ffffffffffffffff821660009081526009602052604081206001015471010000000000000000000000000000000000900460e01b7fffffffff000000000000000000000000000000000000000000000000000000001690036133e6578167ffffffffffffffff167fd31c671936387b2f84ed402b553bd50c0e9c20408ea4e91a836d77b8180fb724826040516133d99190614b97565b60405180910390a2613429565b8167ffffffffffffffff167f1edd6f3553cfa16f10b95b195abae3a1cfca4783de4843f95d674b1e1df5ab20826040516134209190614b97565b60405180910390a25b80600960008467ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548161ffff021916908361ffff16021790555060408201518160000160036101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160076101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600b6101000a81548163ffffffff021916908363ffffffff16021790555060a082015181600001600f6101000a81548161ffff021916908361ffff16021790555060c08201518160000160116101000a81548163ffffffff021916908363ffffffff16021790555060e08201518160000160156101000a81548161ffff021916908361ffff1602179055506101008201518160000160176101000a81548161ffff021916908361ffff1602179055506101208201518160000160196101000a81548161ffff021916908361ffff16021790555061014082015181600001601b6101000a81548163ffffffff021916908363ffffffff1602179055506101608201518160010160006101000a81548163ffffffff021916908363ffffffff1602179055506101808201518160010160046101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506101a082015181600101600c6101000a81548163ffffffff021916908363ffffffff1602179055506101c08201518160010160106101000a81548160ff0219169083151502179055506101e08201518160010160116101000a81548163ffffffff021916908360e01c021790555090505050505080600101905061321a565b60005b8151811015610e845760008282815181106136dd576136dd6156bd565b602002602001015160000151905060008383815181106136ff576136ff6156bd565b60209081029190910181015181015173ffffffffffffffffffffffffffffffffffffffff841660008181526008845260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff85169081179091559051908152919350917fbb77da6f7210cdd16904228a9360133d1d7dfff99b1bc75f128da5b53e28f97d910160405180910390a250506001016136c0565b604080518082019091526000808252602082015260008260000151905060008173ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015613811573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138359190615b1c565b5050509150506000811215613876576040517f10cb51d100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006138f58373ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156138c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138ea9190615b6c565b866020015184612fbf565b604080518082019091527bffffffffffffffffffffffffffffffffffffffffffffffffffffffff909116815263ffffffff4216602082015295945050505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515610b65565b836040015163ffffffff168311156139be5760408085015190517f8693378900000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015260248101849052604401610fb2565b836020015161ffff16821115613a00576040517f4c056b6a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610e2c846101e0015182613fa9565b6000808083815b81811015613cd9576000878783818110613a3257613a326156bd565b905060400201803603810190613a489190615b89565b67ffffffffffffffff8c166000908152600a60209081526040808320845173ffffffffffffffffffffffffffffffffffffffff168452825291829020825160c081018452905463ffffffff8082168352640100000000820481169383019390935268010000000000000000810461ffff16938201939093526a01000000000000000000008304821660608201526e01000000000000000000000000000083049091166080820152720100000000000000000000000000000000000090910460ff16151560a0820181905291925090613b68576101208d0151613b359061ffff16662386f26fc10000615603565b613b3f90886158b7565b96508c610140015186613b529190615bc2565b9550613b5f602086615bc2565b94505050613cd1565b604081015160009061ffff1615613c215760008c73ffffffffffffffffffffffffffffffffffffffff16846000015173ffffffffffffffffffffffffffffffffffffffff1614613bc4578351613bbd90611fa0565b9050613bc7565b508a5b620186a0836040015161ffff16613c098660200151847bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1661406190919063ffffffff16565b613c139190615603565b613c1d919061561a565b9150505b6060820151613c309088615bc2565b9650816080015186613c429190615bc2565b8251909650600090613c619063ffffffff16662386f26fc10000615603565b905080821015613c8057613c75818a6158b7565b985050505050613cd1565b6000836020015163ffffffff16662386f26fc10000613c9f9190615603565b905080831115613cbf57613cb3818b6158b7565b99505050505050613cd1565b613cc9838b6158b7565b995050505050505b600101613a16565b505096509650969350505050565b60008063ffffffff8316613cfd61012086615603565b613d09876101c06158b7565b613d1391906158b7565b613d1d91906158b7565b905060008760c0015163ffffffff168860e0015161ffff1683613d409190615603565b613d4a91906158b7565b61010089015190915061ffff16613d716dffffffffffffffffffffffffffff891683615603565b613d7b9190615603565b613d8b90655af3107a4000615603565b98975050505050505050565b60408051808201909152600080825260208201526000613dc3858585610160015163ffffffff166123dd565b9050826060015163ffffffff1681600001511115613e0d576040517f4c4fc93a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b826101c001518015613e2157508060200151155b15610b62576040517fee433e9900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff821603613ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610fb2565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b606081600001805480602002602001604051908101604052809291908181526020018280548015613f9d57602002820191906000526020600020905b815481526020019060010190808311613f89575b50505050509050919050565b7fd7ed2ad4000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831601610e8457612d008161409e565b6000610b658373ffffffffffffffffffffffffffffffffffffffff8416614151565b6000610b658373ffffffffffffffffffffffffffffffffffffffff84166141a0565b6000610b658373ffffffffffffffffffffffffffffffffffffffff841661429a565b6000670de0b6b3a7640000614094837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8616615603565b610b65919061561a565b600081516020146140dd57816040517f8d666f60000000000000000000000000000000000000000000000000000000008152600401610fb291906143d6565b6000828060200190518101906140f39190615966565b905073ffffffffffffffffffffffffffffffffffffffff811180614118575061040081105b1561115d57826040517f8d666f60000000000000000000000000000000000000000000000000000000008152600401610fb291906143d6565b60008181526001830160205260408120546141985750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561115d565b50600061115d565b600081815260018301602052604081205480156142895760006141c460018361583f565b85549091506000906141d89060019061583f565b905080821461423d5760008660000182815481106141f8576141f86156bd565b906000526020600020015490508087600001848154811061421b5761421b6156bd565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061424e5761424e615bdf565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061115d565b600091505061115d565b5092915050565b600081815260018301602052604081205480156142895760006142be60018361583f565b85549091506000906142d29060019061583f565b905081811461423d5760008660000182815481106141f8576141f86156bd565b803573ffffffffffffffffffffffffffffffffffffffff8116811461431657600080fd5b919050565b60008060006060848603121561433057600080fd5b614339846142f2565b92506020840135915061434e604085016142f2565b90509250925092565b60006020828403121561436957600080fd5b610b65826142f2565b6000815180845260005b818110156143985760208185018101518683018201520161437c565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000610b656020830184614372565b6020808252825182820181905260009190848201906040850190845b8181101561443757835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101614405565b50909695505050505050565b60006020828403121561445557600080fd5b813567ffffffffffffffff81111561446c57600080fd5b820160408185031215610b6557600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff811182821017156144d0576144d061447e565b60405290565b60405160a0810167ffffffffffffffff811182821017156144d0576144d061447e565b60405160c0810167ffffffffffffffff811182821017156144d0576144d061447e565b604051610200810167ffffffffffffffff811182821017156144d0576144d061447e565b6040516060810167ffffffffffffffff811182821017156144d0576144d061447e565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156145aa576145aa61447e565b604052919050565b600067ffffffffffffffff8211156145cc576145cc61447e565b5060051b60200190565b60ff81168114610e4357600080fd5b600060208083850312156145f857600080fd5b823567ffffffffffffffff81111561460f57600080fd5b8301601f8101851361462057600080fd5b803561463361462e826145b2565b614563565b8181526060918202830184019184820191908884111561465257600080fd5b938501935b838510156146f257848903818112156146705760008081fd5b6146786144ad565b614681876142f2565b81526040807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0840112156146b55760008081fd5b6146bd6144ad565b92506146ca8989016142f2565b83528701356146d8816145d6565b828901528088019190915283529384019391850191614657565b50979650505050505050565b8015158114610e4357600080fd5b8035614316816146fe565b6000602080838503121561472a57600080fd5b823567ffffffffffffffff81111561474157600080fd5b8301601f8101851361475257600080fd5b803561476061462e826145b2565b81815260a0918202830184019184820191908884111561477f57600080fd5b938501935b838510156146f25780858a03121561479c5760008081fd5b6147a46144d6565b6147ad866142f2565b8152868601357fffffffffffffffffffff00000000000000000000000000000000000000000000811681146147e25760008081fd5b818801526040868101357fffff0000000000000000000000000000000000000000000000000000000000008116811461481b5760008081fd5b90820152606061482c8782016142f2565b9082015260808681013561483f816146fe565b9082015283529384019391850191614784565b803567ffffffffffffffff8116811461431657600080fd5b60008083601f84011261487c57600080fd5b50813567ffffffffffffffff81111561489457600080fd5b602083019150836020828501011115611f9957600080fd5b60008083601f8401126148be57600080fd5b50813567ffffffffffffffff8111156148d657600080fd5b6020830191508360208260051b8501011115611f9957600080fd5b600080600080600080600080600060c08a8c03121561490f57600080fd5b6149188a614852565b985061492660208b016142f2565b975060408a0135965060608a013567ffffffffffffffff8082111561494a57600080fd5b6149568d838e0161486a565b909850965060808c013591508082111561496f57600080fd5b61497b8d838e016148ac565b909650945060a08c013591508082111561499457600080fd5b818c0191508c601f8301126149a857600080fd5b8135818111156149b757600080fd5b8d60208260061b85010111156149cc57600080fd5b6020830194508093505050509295985092959850929598565b848152600060208515158184015260806040840152614a076080840186614372565b8381036060850152845180825282820190600581901b8301840184880160005b83811015614a73577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018552614a61838351614372565b94870194925090860190600101614a27565b50909b9a5050505050505050505050565b60008060208385031215614a9757600080fd5b823567ffffffffffffffff811115614aae57600080fd5b614aba858286016148ac565b90969095509350505050565b602080825282518282018190526000919060409081850190868401855b82811015614b3457614b2484835180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16825260209081015163ffffffff16910152565b9284019290850190600101614ae3565b5091979650505050505050565b600060208284031215614b5357600080fd5b610b6582614852565b81517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16815260208083015163ffffffff16908201526040810161115d565b81511515815261020081016020830151614bb7602084018261ffff169052565b506040830151614bcf604084018263ffffffff169052565b506060830151614be7606084018263ffffffff169052565b506080830151614bff608084018263ffffffff169052565b5060a0830151614c1560a084018261ffff169052565b5060c0830151614c2d60c084018263ffffffff169052565b5060e0830151614c4360e084018261ffff169052565b506101008381015161ffff9081169184019190915261012080850151909116908301526101408084015163ffffffff90811691840191909152610160808501518216908401526101808085015167ffffffffffffffff16908401526101a080850151909116908301526101c0808401511515908301526101e0808401517fffffffff000000000000000000000000000000000000000000000000000000008116828501525b505092915050565b803563ffffffff8116811461431657600080fd5b803561ffff8116811461431657600080fd5b600082601f830112614d2757600080fd5b81356020614d3761462e836145b2565b82815260069290921b84018101918181019086841115614d5657600080fd5b8286015b84811015614da35760408189031215614d735760008081fd5b614d7b6144ad565b614d8482614852565b8152614d918583016142f2565b81860152835291830191604001614d5a565b509695505050505050565b60008060408385031215614dc157600080fd5b67ffffffffffffffff83351115614dd757600080fd5b83601f843585010112614de957600080fd5b614df961462e84358501356145b2565b8335840180358083526020808401939260059290921b90910101861015614e1f57600080fd5b602085358601015b85358601803560051b0160200181101561502c5767ffffffffffffffff81351115614e5157600080fd5b8035863587010160407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0828a03011215614e8a57600080fd5b614e926144ad565b614e9e60208301614852565b815267ffffffffffffffff60408301351115614eb957600080fd5b88603f604084013584010112614ece57600080fd5b614ee461462e60206040850135850101356145b2565b6020604084810135850182810135808552928401939260e00201018b1015614f0b57600080fd5b6040808501358501015b6040858101358601602081013560e002010181101561500d5760e0818d031215614f3e57600080fd5b614f466144ad565b614f4f826142f2565b815260c07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0838f03011215614f8357600080fd5b614f8b6144f9565b614f9760208401614cf0565b8152614fa560408401614cf0565b6020820152614fb660608401614d04565b6040820152614fc760808401614cf0565b6060820152614fd860a08401614cf0565b6080820152614fea60c08401356146fe565b60c083013560a0820152602082810191909152908452929092019160e001614f15565b5080602084015250508085525050602083019250602081019050614e27565b5092505067ffffffffffffffff6020840135111561504957600080fd5b6150598460208501358501614d16565b90509250929050565b600082601f83011261507357600080fd5b8135602061508361462e836145b2565b8083825260208201915060208460051b8701019350868411156150a557600080fd5b602086015b84811015614da3576150bb816142f2565b83529183019183016150aa565b600080604083850312156150db57600080fd5b823567ffffffffffffffff808211156150f357600080fd5b6150ff86838701615062565b9350602085013591508082111561511557600080fd5b5061512285828601615062565b9150509250929050565b6000806000806040858703121561514257600080fd5b843567ffffffffffffffff8082111561515a57600080fd5b6151668883890161486a565b9096509450602087013591508082111561517f57600080fd5b5061518c8782880161486a565b95989497509550505050565b600080604083850312156151ab57600080fd5b6151b483614852565b9150615059602084016142f2565b6000602082840312156151d457600080fd5b813567ffffffffffffffff808211156151ec57600080fd5b908301906040828603121561520057600080fd5b6152086144ad565b82358281111561521757600080fd5b61522387828601615062565b82525060208301358281111561523857600080fd5b61524487828601615062565b60208301525095945050505050565b80357fffffffff000000000000000000000000000000000000000000000000000000008116811461431657600080fd5b6000602080838503121561529657600080fd5b823567ffffffffffffffff8111156152ad57600080fd5b8301601f810185136152be57600080fd5b80356152cc61462e826145b2565b81815261022091820283018401918482019190888411156152ec57600080fd5b938501935b838510156146f2578489038181121561530a5760008081fd5b6153126144ad565b61531b87614852565b8152610200807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0840112156153505760008081fd5b61535861451c565b925061536589890161470c565b83526040615374818a01614d04565b8a8501526060615385818b01614cf0565b8286015260809150615398828b01614cf0565b9085015260a06153a98a8201614cf0565b8286015260c091506153bc828b01614d04565b9085015260e06153cd8a8201614cf0565b8286015261010091506153e1828b01614d04565b908501526101206153f38a8201614d04565b828601526101409150615407828b01614d04565b908501526101606154198a8201614cf0565b82860152610180915061542d828b01614cf0565b908501526101a061543f8a8201614852565b828601526101c09150615453828b01614cf0565b908501526101e06154658a820161470c565b82860152615474838b01615253565b90850152505080880191909152835293840193918501916152f1565b600060208083850312156154a357600080fd5b823567ffffffffffffffff8111156154ba57600080fd5b8301601f810185136154cb57600080fd5b80356154d961462e826145b2565b81815260069190911b820183019083810190878311156154f857600080fd5b928401925b8284101561554a57604084890312156155165760008081fd5b61551e6144ad565b615527856142f2565b8152615534868601614852565b81870152825260409390930192908401906154fd565b979650505050505050565b6000806040838503121561556857600080fd5b61557183614852565b9150602083013567ffffffffffffffff81111561558d57600080fd5b830160a0818603121561559f57600080fd5b809150509250929050565b600080604083850312156155bd57600080fd5b6155c6836142f2565b915061505960208401614852565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808202811582820484141761115d5761115d6155d4565b600082615650577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261568a57600080fd5b83018035915067ffffffffffffffff8211156156a557600080fd5b6020019150600681901b3603821315611f9957600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b80357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116811461431657600080fd5b60006040828403121561572a57600080fd5b6157326144ad565b61573b836142f2565b8152615749602084016156ec565b60208201529392505050565b60006040828403121561576757600080fd5b61576f6144ad565b61573b83614852565b6000602080838503121561578b57600080fd5b823567ffffffffffffffff8111156157a257600080fd5b8301601f810185136157b357600080fd5b80356157c161462e826145b2565b818152606091820283018401918482019190888411156157e057600080fd5b938501935b838510156146f25780858a0312156157fd5760008081fd5b615805614540565b61580e866142f2565b815261581b8787016156ec565b87820152604061582c818801614cf0565b90820152835293840193918501916157e5565b8181038181111561115d5761115d6155d4565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261588757600080fd5b83018035915067ffffffffffffffff8211156158a257600080fd5b602001915036819003821315611f9957600080fd5b8082018082111561115d5761115d6155d4565b7fffffffff000000000000000000000000000000000000000000000000000000008135818116916004851015614ce85760049490940360031b84901b1690921692915050565b6000808585111561592057600080fd5b8386111561592d57600080fd5b5050820193919092039150565b60006040828403121561594c57600080fd5b6159546144ad565b825181526020830151615749816146fe565b60006020828403121561597857600080fd5b5051919050565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff618336030181126159b357600080fd5b9190910192915050565b60ff818116838216019081111561115d5761115d6155d4565b600181815b80851115615a2f57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115615a1557615a156155d4565b80851615615a2257918102915b93841c93908002906159db565b509250929050565b600082615a465750600161115d565b81615a535750600061115d565b8160018114615a695760028114615a7357615a8f565b600191505061115d565b60ff841115615a8457615a846155d4565b50506001821b61115d565b5060208310610133831016604e8410600b8410161715615ab2575081810a61115d565b615abc83836159d6565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115615aee57615aee6155d4565b029392505050565b6000610b658383615a37565b805169ffffffffffffffffffff8116811461431657600080fd5b600080600080600060a08688031215615b3457600080fd5b615b3d86615b02565b9450602086015193506040860151925060608601519150615b6060808701615b02565b90509295509295909350565b600060208284031215615b7e57600080fd5b8151610b65816145d6565b600060408284031215615b9b57600080fd5b615ba36144ad565b615bac836142f2565b8152602083013560208201528091505092915050565b63ffffffff818116838216019080821115614293576142936155d4565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea164736f6c6343000818000a", } var FeeQuoterABI = FeeQuoterMetaData.ABI @@ -676,11 +676,11 @@ func (_FeeQuoter *FeeQuoterCallerSession) Owner() (common.Address, error) { return _FeeQuoter.Contract.Owner(&_FeeQuoter.CallOpts) } -func (_FeeQuoter *FeeQuoterCaller) ProcessMessageArgs(opts *bind.CallOpts, destChainSelector uint64, feeToken common.Address, feeTokenAmount *big.Int, extraArgs []byte, rampTokenAmounts []InternalRampTokenAmount, sourceTokenAmounts []ClientEVMTokenAmount) (ProcessMessageArgs, +func (_FeeQuoter *FeeQuoterCaller) ProcessMessageArgs(opts *bind.CallOpts, destChainSelector uint64, feeToken common.Address, feeTokenAmount *big.Int, extraArgs []byte, onRampTokenTransfers []InternalEVM2AnyTokenTransfer, sourceTokenAmounts []ClientEVMTokenAmount) (ProcessMessageArgs, error) { var out []interface{} - err := _FeeQuoter.contract.Call(opts, &out, "processMessageArgs", destChainSelector, feeToken, feeTokenAmount, extraArgs, rampTokenAmounts, sourceTokenAmounts) + err := _FeeQuoter.contract.Call(opts, &out, "processMessageArgs", destChainSelector, feeToken, feeTokenAmount, extraArgs, onRampTokenTransfers, sourceTokenAmounts) outstruct := new(ProcessMessageArgs) if err != nil { @@ -696,16 +696,16 @@ func (_FeeQuoter *FeeQuoterCaller) ProcessMessageArgs(opts *bind.CallOpts, destC } -func (_FeeQuoter *FeeQuoterSession) ProcessMessageArgs(destChainSelector uint64, feeToken common.Address, feeTokenAmount *big.Int, extraArgs []byte, rampTokenAmounts []InternalRampTokenAmount, sourceTokenAmounts []ClientEVMTokenAmount) (ProcessMessageArgs, +func (_FeeQuoter *FeeQuoterSession) ProcessMessageArgs(destChainSelector uint64, feeToken common.Address, feeTokenAmount *big.Int, extraArgs []byte, onRampTokenTransfers []InternalEVM2AnyTokenTransfer, sourceTokenAmounts []ClientEVMTokenAmount) (ProcessMessageArgs, error) { - return _FeeQuoter.Contract.ProcessMessageArgs(&_FeeQuoter.CallOpts, destChainSelector, feeToken, feeTokenAmount, extraArgs, rampTokenAmounts, sourceTokenAmounts) + return _FeeQuoter.Contract.ProcessMessageArgs(&_FeeQuoter.CallOpts, destChainSelector, feeToken, feeTokenAmount, extraArgs, onRampTokenTransfers, sourceTokenAmounts) } -func (_FeeQuoter *FeeQuoterCallerSession) ProcessMessageArgs(destChainSelector uint64, feeToken common.Address, feeTokenAmount *big.Int, extraArgs []byte, rampTokenAmounts []InternalRampTokenAmount, sourceTokenAmounts []ClientEVMTokenAmount) (ProcessMessageArgs, +func (_FeeQuoter *FeeQuoterCallerSession) ProcessMessageArgs(destChainSelector uint64, feeToken common.Address, feeTokenAmount *big.Int, extraArgs []byte, onRampTokenTransfers []InternalEVM2AnyTokenTransfer, sourceTokenAmounts []ClientEVMTokenAmount) (ProcessMessageArgs, error) { - return _FeeQuoter.Contract.ProcessMessageArgs(&_FeeQuoter.CallOpts, destChainSelector, feeToken, feeTokenAmount, extraArgs, rampTokenAmounts, sourceTokenAmounts) + return _FeeQuoter.Contract.ProcessMessageArgs(&_FeeQuoter.CallOpts, destChainSelector, feeToken, feeTokenAmount, extraArgs, onRampTokenTransfers, sourceTokenAmounts) } func (_FeeQuoter *FeeQuoterCaller) TypeAndVersion(opts *bind.CallOpts) (string, error) { @@ -2943,7 +2943,7 @@ type FeeQuoterInterface interface { Owner(opts *bind.CallOpts) (common.Address, error) - ProcessMessageArgs(opts *bind.CallOpts, destChainSelector uint64, feeToken common.Address, feeTokenAmount *big.Int, extraArgs []byte, rampTokenAmounts []InternalRampTokenAmount, sourceTokenAmounts []ClientEVMTokenAmount) (ProcessMessageArgs, + ProcessMessageArgs(opts *bind.CallOpts, destChainSelector uint64, feeToken common.Address, feeTokenAmount *big.Int, extraArgs []byte, onRampTokenTransfers []InternalEVM2AnyTokenTransfer, sourceTokenAmounts []ClientEVMTokenAmount) (ProcessMessageArgs, error) diff --git a/core/gethwrappers/ccip/generated/message_hasher/message_hasher.go b/core/gethwrappers/ccip/generated/message_hasher/message_hasher.go index 13d5e7b8d4..f8dc4728f7 100644 --- a/core/gethwrappers/ccip/generated/message_hasher/message_hasher.go +++ b/core/gethwrappers/ccip/generated/message_hasher/message_hasher.go @@ -43,28 +43,36 @@ type InternalAny2EVMRampMessage struct { Data []byte Receiver common.Address GasLimit *big.Int - TokenAmounts []InternalRampTokenAmount + TokenAmounts []InternalAny2EVMTokenTransfer } -type InternalRampMessageHeader struct { - MessageId [32]byte - SourceChainSelector uint64 - DestChainSelector uint64 - SequenceNumber uint64 - Nonce uint64 +type InternalAny2EVMTokenTransfer struct { + SourcePoolAddress []byte + DestTokenAddress common.Address + DestGasAmount uint32 + ExtraData []byte + Amount *big.Int } -type InternalRampTokenAmount struct { - SourcePoolAddress []byte +type InternalEVM2AnyTokenTransfer struct { + SourcePoolAddress common.Address DestTokenAddress []byte ExtraData []byte Amount *big.Int DestExecData []byte } +type InternalRampMessageHeader struct { + MessageId [32]byte + SourceChainSelector uint64 + DestChainSelector uint64 + SequenceNumber uint64 + Nonce uint64 +} + var MessageHasherMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"}],\"name\":\"decodeEVMExtraArgsV1\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMExtraArgsV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"allowOutOfOrderExecution\",\"type\":\"bool\"}],\"name\":\"decodeEVMExtraArgsV2\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"allowOutOfOrderExecution\",\"type\":\"bool\"}],\"internalType\":\"structClient.EVMExtraArgsV2\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMExtraArgsV1\",\"name\":\"extraArgs\",\"type\":\"tuple\"}],\"name\":\"encodeEVMExtraArgsV1\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"allowOutOfOrderExecution\",\"type\":\"bool\"}],\"internalType\":\"structClient.EVMExtraArgsV2\",\"name\":\"extraArgs\",\"type\":\"tuple\"}],\"name\":\"encodeEVMExtraArgsV2\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"leafDomainSeparator\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"implicitMetadataHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"fixedSizeFieldsHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"dataHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"tokenAmountsHash\",\"type\":\"bytes32\"}],\"name\":\"encodeFinalHashPreimage\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"name\":\"encodeFixedSizeFieldsHashPreimage\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"any2EVMMessageHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"name\":\"encodeMetadataHashPreimage\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"rampTokenAmounts\",\"type\":\"tuple[]\"}],\"name\":\"encodeTokenAmountsHashPreimage\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"name\":\"hash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]", - Bin: "0x608060405234801561001057600080fd5b50610e3a806100206000396000f3fe608060405234801561001057600080fd5b50600436106100a35760003560e01c8063a91d3aeb11610076578063c63641bd1161005b578063c63641bd1461019e578063c7ca9a18146101f5578063e733d2091461020857600080fd5b8063a91d3aeb14610150578063b17df7141461016357600080fd5b80632d6d4c5e146100a85780632efb5ac2146100d157806399df8d05146100f2578063a1e747df1461013d575b600080fd5b6100bb6100b6366004610831565b61021b565b6040516100c891906108d2565b60405180910390f35b6100e46100df366004610990565b610244565b6040519081526020016100c8565b6100bb610100366004610a9a565b604080516020810196909652858101949094526060850192909252608084015260a0808401919091528151808403909101815260c0909201905290565b6100bb61014b366004610ad5565b6102b3565b6100bb61015e366004610b3d565b6102e5565b61018f610171366004610bbe565b60408051602080820183526000909152815190810190915290815290565b604051905181526020016100c8565b6101d86101ac366004610be7565b604080518082019091526000808252602082015250604080518082019091529182521515602082015290565b6040805182518152602092830151151592810192909252016100c8565b6100bb610203366004610c13565b61031d565b6100bb610216366004610c67565b61032e565b60608160405160200161022e9190610ca9565b6040516020818303038152906040529050919050565b60006102ac837f2425b0b9f9054c76ff151b0a175b18f37a4a4e82013a72e9f15c9caa095ed21f856000015160200151866000015160400151866040516020016102919493929190610d90565b60405160208183030381529060405280519060200120610339565b9392505050565b6060848484846040516020016102cc9493929190610d90565b6040516020818303038152906040529050949350505050565b606086868686868660405160200161030296959493929190610dcd565b60405160208183030381529060405290509695505050505050565b60606103288261046c565b92915050565b60606103288261052e565b8151805160608085015190830151608080870151940151604051600095869588956103ab959194909391929160200194855273ffffffffffffffffffffffffffffffffffffffff93909316602085015267ffffffffffffffff9182166040850152606084015216608082015260a00190565b604051602081830303815290604052805190602001208560200151805190602001208660400151805190602001208760a001516040516020016103ee9190610ca9565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120908301979097528101949094526060840192909252608083015260a082015260c081019190915260e00160405160208183030381529060405280519060200120905092915050565b604051815160248201526020820151151560448201526060907f181dcf1000000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915292915050565b604051815160248201526060907f97a657c900000000000000000000000000000000000000000000000000000000906044016104ab565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff811182821017156105b7576105b7610565565b60405290565b60405160c0810167ffffffffffffffff811182821017156105b7576105b7610565565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561062757610627610565565b604052919050565b600082601f83011261064057600080fd5b813567ffffffffffffffff81111561065a5761065a610565565b61068b60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016105e0565b8181528460208386010111156106a057600080fd5b816020850160208301376000918101602001919091529392505050565b600082601f8301126106ce57600080fd5b8135602067ffffffffffffffff808311156106eb576106eb610565565b8260051b6106fa8382016105e0565b938452858101830193838101908886111561071457600080fd5b84880192505b85831015610825578235848111156107325760008081fd5b880160a0818b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018113156107685760008081fd5b610770610594565b87830135878111156107825760008081fd5b6107908d8a8387010161062f565b825250604080840135888111156107a75760008081fd5b6107b58e8b8388010161062f565b8a84015250606080850135898111156107ce5760008081fd5b6107dc8f8c8389010161062f565b838501525060809150818501358184015250828401359250878311156108025760008081fd5b6108108d8a8587010161062f565b9082015284525050918401919084019061071a565b98975050505050505050565b60006020828403121561084357600080fd5b813567ffffffffffffffff81111561085a57600080fd5b610866848285016106bd565b949350505050565b6000815180845260005b8181101561089457602081850181015186830182015201610878565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b6020815260006102ac602083018461086e565b803567ffffffffffffffff811681146108fd57600080fd5b919050565b600060a0828403121561091457600080fd5b61091c610594565b90508135815261092e602083016108e5565b602082015261093f604083016108e5565b6040820152610950606083016108e5565b6060820152610961608083016108e5565b608082015292915050565b803573ffffffffffffffffffffffffffffffffffffffff811681146108fd57600080fd5b600080604083850312156109a357600080fd5b823567ffffffffffffffff808211156109bb57600080fd5b9084019061014082870312156109d057600080fd5b6109d86105bd565b6109e28784610902565b815260a0830135828111156109f657600080fd5b610a028882860161062f565b60208301525060c083013582811115610a1a57600080fd5b610a268882860161062f565b604083015250610a3860e0840161096c565b6060820152610100830135608082015261012083013582811115610a5b57600080fd5b610a67888286016106bd565b60a08301525093506020850135915080821115610a8357600080fd5b50610a908582860161062f565b9150509250929050565b600080600080600060a08688031215610ab257600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b60008060008060808587031215610aeb57600080fd5b84359350610afb602086016108e5565b9250610b09604086016108e5565b9150606085013567ffffffffffffffff811115610b2557600080fd5b610b318782880161062f565b91505092959194509250565b60008060008060008060c08789031215610b5657600080fd5b86359550602087013567ffffffffffffffff811115610b7457600080fd5b610b8089828a0161062f565b955050610b8f6040880161096c565b9350610b9d606088016108e5565b925060808701359150610bb260a088016108e5565b90509295509295509295565b600060208284031215610bd057600080fd5b5035919050565b803580151581146108fd57600080fd5b60008060408385031215610bfa57600080fd5b82359150610c0a60208401610bd7565b90509250929050565b600060408284031215610c2557600080fd5b6040516040810181811067ffffffffffffffff82111715610c4857610c48610565565b60405282358152610c5b60208401610bd7565b60208201529392505050565b600060208284031215610c7957600080fd5b6040516020810181811067ffffffffffffffff82111715610c9c57610c9c610565565b6040529135825250919050565b600060208083018184528085518083526040925060408601915060408160051b87010184880160005b83811015610d82577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0898403018552815160a08151818652610d168287018261086e565b915050888201518582038a870152610d2e828261086e565b9150508782015185820389870152610d46828261086e565b915050606080830151818701525060808083015192508582038187015250610d6e818361086e565b968901969450505090860190600101610cd2565b509098975050505050505050565b848152600067ffffffffffffffff808616602084015280851660408401525060806060830152610dc3608083018461086e565b9695505050505050565b86815260c060208201526000610de660c083018861086e565b73ffffffffffffffffffffffffffffffffffffffff9690961660408301525067ffffffffffffffff9384166060820152608081019290925290911660a0909101529291505056fea164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"}],\"name\":\"decodeEVMExtraArgsV1\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMExtraArgsV1\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"allowOutOfOrderExecution\",\"type\":\"bool\"}],\"name\":\"decodeEVMExtraArgsV2\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"allowOutOfOrderExecution\",\"type\":\"bool\"}],\"internalType\":\"structClient.EVMExtraArgsV2\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMExtraArgsV1\",\"name\":\"extraArgs\",\"type\":\"tuple\"}],\"name\":\"encodeEVMExtraArgsV1\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"allowOutOfOrderExecution\",\"type\":\"bool\"}],\"internalType\":\"structClient.EVMExtraArgsV2\",\"name\":\"extraArgs\",\"type\":\"tuple\"}],\"name\":\"encodeEVMExtraArgsV2\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"leafDomainSeparator\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"implicitMetadataHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"fixedSizeFieldsHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"dataHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"tokenAmountsHash\",\"type\":\"bytes32\"}],\"name\":\"encodeFinalHashPreimage\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"name\":\"encodeFixedSizeFieldsHashPreimage\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"any2EVMMessageHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"name\":\"encodeMetadataHashPreimage\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourcePoolAddress\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.EVM2AnyTokenTransfer[]\",\"name\":\"tokenAmount\",\"type\":\"tuple[]\"}],\"name\":\"encodeTokenAmountsHashPreimage\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"destTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"destGasAmount\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.Any2EVMTokenTransfer[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"name\":\"encodeTokenAmountsHashPreimage\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"destTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"destGasAmount\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.Any2EVMTokenTransfer[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"name\":\"hash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]", + Bin: "0x608060405234801561001057600080fd5b506110c2806100206000396000f3fe608060405234801561001057600080fd5b50600436106100be5760003560e01c8063a91d3aeb11610076578063c63641bd1161005b578063c63641bd146101cc578063c7ca9a1814610223578063e733d2091461023657600080fd5b8063a91d3aeb1461017e578063b17df7141461019157600080fd5b80638d3191a0116100a75780638d3191a01461010d57806399df8d0514610120578063a1e747df1461016b57600080fd5b8063750e2ea8146100c35780638503839d146100ec575b600080fd5b6100d66100d136600461074b565b610249565b6040516100e39190610924565b60405180910390f35b6100ff6100fa366004610b00565b610272565b6040519081526020016100e3565b6100d661011b366004610c0a565b6102e1565b6100d661012e366004610c47565b604080516020810196909652858101949094526060850192909252608084015260a0808401919091528151808403909101815260c0909201905290565b6100d6610179366004610c82565b6102f4565b6100d661018c366004610cea565b610326565b6101bd61019f366004610d6b565b60408051602080820183526000909152815190810190915290815290565b604051905181526020016100e3565b6102066101da366004610d94565b604080518082019091526000808252602082015250604080518082019091529182521515602082015290565b6040805182518152602092830151151592810192909252016100e3565b6100d6610231366004610dc0565b61035e565b6100d6610244366004610e14565b61036f565b60608160405160200161025c9190610e56565b6040516020818303038152906040529050919050565b60006102da837f2425b0b9f9054c76ff151b0a175b18f37a4a4e82013a72e9f15c9caa095ed21f856000015160200151866000015160400151866040516020016102bf9493929190610f43565b6040516020818303038152906040528051906020012061037a565b9392505050565b60608160405160200161025c9190610f80565b60608484848460405160200161030d9493929190610f43565b6040516020818303038152906040529050949350505050565b606086868686868660405160200161034396959493929190611055565b60405160208183030381529060405290509695505050505050565b6060610369826104ad565b92915050565b60606103698261056f565b8151805160608085015190830151608080870151940151604051600095869588956103ec959194909391929160200194855273ffffffffffffffffffffffffffffffffffffffff93909316602085015267ffffffffffffffff9182166040850152606084015216608082015260a00190565b604051602081830303815290604052805190602001208560200151805190602001208660400151805190602001208760a0015160405160200161042f9190610f80565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120908301979097528101949094526060840192909252608083015260a082015260c081019190915260e00160405160208183030381529060405280519060200120905092915050565b604051815160248201526020820151151560448201526060907f181dcf1000000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915292915050565b604051815160248201526060907f97a657c900000000000000000000000000000000000000000000000000000000906044016104ec565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff811182821017156105f8576105f86105a6565b60405290565b60405160c0810167ffffffffffffffff811182821017156105f8576105f86105a6565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715610668576106686105a6565b604052919050565b600067ffffffffffffffff82111561068a5761068a6105a6565b5060051b60200190565b803573ffffffffffffffffffffffffffffffffffffffff811681146106b857600080fd5b919050565b600082601f8301126106ce57600080fd5b813567ffffffffffffffff8111156106e8576106e86105a6565b61071960207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601610621565b81815284602083860101111561072e57600080fd5b816020850160208301376000918101602001919091529392505050565b6000602080838503121561075e57600080fd5b823567ffffffffffffffff8082111561077657600080fd5b818501915085601f83011261078a57600080fd5b813561079d61079882610670565b610621565b81815260059190911b830184019084810190888311156107bc57600080fd5b8585015b838110156108b3578035858111156107d757600080fd5b860160a0818c037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001121561080c5760008081fd5b6108146105d5565b61081f898301610694565b8152604080830135888111156108355760008081fd5b6108438e8c838701016106bd565b8b840152506060808401358981111561085c5760008081fd5b61086a8f8d838801016106bd565b83850152506080915081840135818401525060a08301358881111561088f5760008081fd5b61089d8e8c838701016106bd565b91830191909152508452509186019186016107c0565b5098975050505050505050565b6000815180845260005b818110156108e6576020818501810151868301820152016108ca565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b6020815260006102da60208301846108c0565b803567ffffffffffffffff811681146106b857600080fd5b600060a0828403121561096157600080fd5b6109696105d5565b90508135815261097b60208301610937565b602082015261098c60408301610937565b604082015261099d60608301610937565b60608201526109ae60808301610937565b608082015292915050565b600082601f8301126109ca57600080fd5b813560206109da61079883610670565b82815260059290921b840181019181810190868411156109f957600080fd5b8286015b84811015610af557803567ffffffffffffffff80821115610a1e5760008081fd5b818901915060a0807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848d03011215610a575760008081fd5b610a5f6105d5565b8784013583811115610a715760008081fd5b610a7f8d8a838801016106bd565b8252506040610a8f818601610694565b8983015260608086013563ffffffff81168114610aac5760008081fd5b808385015250608091508186013585811115610ac85760008081fd5b610ad68f8c838a01016106bd565b91840191909152509190930135908301525083529183019183016109fd565b509695505050505050565b60008060408385031215610b1357600080fd5b823567ffffffffffffffff80821115610b2b57600080fd5b908401906101408287031215610b4057600080fd5b610b486105fe565b610b52878461094f565b815260a083013582811115610b6657600080fd5b610b72888286016106bd565b60208301525060c083013582811115610b8a57600080fd5b610b96888286016106bd565b604083015250610ba860e08401610694565b6060820152610100830135608082015261012083013582811115610bcb57600080fd5b610bd7888286016109b9565b60a08301525093506020850135915080821115610bf357600080fd5b50610c00858286016106bd565b9150509250929050565b600060208284031215610c1c57600080fd5b813567ffffffffffffffff811115610c3357600080fd5b610c3f848285016109b9565b949350505050565b600080600080600060a08688031215610c5f57600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b60008060008060808587031215610c9857600080fd5b84359350610ca860208601610937565b9250610cb660408601610937565b9150606085013567ffffffffffffffff811115610cd257600080fd5b610cde878288016106bd565b91505092959194509250565b60008060008060008060c08789031215610d0357600080fd5b86359550602087013567ffffffffffffffff811115610d2157600080fd5b610d2d89828a016106bd565b955050610d3c60408801610694565b9350610d4a60608801610937565b925060808701359150610d5f60a08801610937565b90509295509295509295565b600060208284031215610d7d57600080fd5b5035919050565b803580151581146106b857600080fd5b60008060408385031215610da757600080fd5b82359150610db760208401610d84565b90509250929050565b600060408284031215610dd257600080fd5b6040516040810181811067ffffffffffffffff82111715610df557610df56105a6565b60405282358152610e0860208401610d84565b60208201529392505050565b600060208284031215610e2657600080fd5b6040516020810181811067ffffffffffffffff82111715610e4957610e496105a6565b6040529135825250919050565b600060208083018184528085518083526040925060408601915060408160051b87010184880160005b83811015610f35577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0898403018552815160a073ffffffffffffffffffffffffffffffffffffffff825116855288820151818a870152610ee1828701826108c0565b9150508782015185820389870152610ef982826108c0565b915050606080830151818701525060808083015192508582038187015250610f2181836108c0565b968901969450505090860190600101610e7f565b509098975050505050505050565b848152600067ffffffffffffffff808616602084015280851660408401525060806060830152610f7660808301846108c0565b9695505050505050565b600060208083018184528085518083526040925060408601915060408160051b87010184880160005b83811015610f35577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0898403018552815160a08151818652610fed828701826108c0565b91505073ffffffffffffffffffffffffffffffffffffffff89830151168986015263ffffffff8883015116888601526060808301518683038288015261103383826108c0565b6080948501519790940196909652505094870194925090860190600101610fa9565b86815260c06020820152600061106e60c08301886108c0565b73ffffffffffffffffffffffffffffffffffffffff9690961660408301525067ffffffffffffffff9384166060820152608081019290925290911660a0909101529291505056fea164736f6c6343000818000a", } var MessageHasherABI = MessageHasherMetaData.ABI @@ -357,9 +365,9 @@ func (_MessageHasher *MessageHasherCallerSession) EncodeMetadataHashPreimage(any return _MessageHasher.Contract.EncodeMetadataHashPreimage(&_MessageHasher.CallOpts, any2EVMMessageHash, sourceChainSelector, destChainSelector, onRamp) } -func (_MessageHasher *MessageHasherCaller) EncodeTokenAmountsHashPreimage(opts *bind.CallOpts, rampTokenAmounts []InternalRampTokenAmount) ([]byte, error) { +func (_MessageHasher *MessageHasherCaller) EncodeTokenAmountsHashPreimage(opts *bind.CallOpts, tokenAmount []InternalEVM2AnyTokenTransfer) ([]byte, error) { var out []interface{} - err := _MessageHasher.contract.Call(opts, &out, "encodeTokenAmountsHashPreimage", rampTokenAmounts) + err := _MessageHasher.contract.Call(opts, &out, "encodeTokenAmountsHashPreimage", tokenAmount) if err != nil { return *new([]byte), err @@ -371,12 +379,34 @@ func (_MessageHasher *MessageHasherCaller) EncodeTokenAmountsHashPreimage(opts * } -func (_MessageHasher *MessageHasherSession) EncodeTokenAmountsHashPreimage(rampTokenAmounts []InternalRampTokenAmount) ([]byte, error) { - return _MessageHasher.Contract.EncodeTokenAmountsHashPreimage(&_MessageHasher.CallOpts, rampTokenAmounts) +func (_MessageHasher *MessageHasherSession) EncodeTokenAmountsHashPreimage(tokenAmount []InternalEVM2AnyTokenTransfer) ([]byte, error) { + return _MessageHasher.Contract.EncodeTokenAmountsHashPreimage(&_MessageHasher.CallOpts, tokenAmount) } -func (_MessageHasher *MessageHasherCallerSession) EncodeTokenAmountsHashPreimage(rampTokenAmounts []InternalRampTokenAmount) ([]byte, error) { - return _MessageHasher.Contract.EncodeTokenAmountsHashPreimage(&_MessageHasher.CallOpts, rampTokenAmounts) +func (_MessageHasher *MessageHasherCallerSession) EncodeTokenAmountsHashPreimage(tokenAmount []InternalEVM2AnyTokenTransfer) ([]byte, error) { + return _MessageHasher.Contract.EncodeTokenAmountsHashPreimage(&_MessageHasher.CallOpts, tokenAmount) +} + +func (_MessageHasher *MessageHasherCaller) EncodeTokenAmountsHashPreimage0(opts *bind.CallOpts, tokenAmounts []InternalAny2EVMTokenTransfer) ([]byte, error) { + var out []interface{} + err := _MessageHasher.contract.Call(opts, &out, "encodeTokenAmountsHashPreimage0", tokenAmounts) + + if err != nil { + return *new([]byte), err + } + + out0 := *abi.ConvertType(out[0], new([]byte)).(*[]byte) + + return out0, err + +} + +func (_MessageHasher *MessageHasherSession) EncodeTokenAmountsHashPreimage0(tokenAmounts []InternalAny2EVMTokenTransfer) ([]byte, error) { + return _MessageHasher.Contract.EncodeTokenAmountsHashPreimage0(&_MessageHasher.CallOpts, tokenAmounts) +} + +func (_MessageHasher *MessageHasherCallerSession) EncodeTokenAmountsHashPreimage0(tokenAmounts []InternalAny2EVMTokenTransfer) ([]byte, error) { + return _MessageHasher.Contract.EncodeTokenAmountsHashPreimage0(&_MessageHasher.CallOpts, tokenAmounts) } func (_MessageHasher *MessageHasherCaller) Hash(opts *bind.CallOpts, message InternalAny2EVMRampMessage, onRamp []byte) ([32]byte, error) { @@ -420,7 +450,9 @@ type MessageHasherInterface interface { EncodeMetadataHashPreimage(opts *bind.CallOpts, any2EVMMessageHash [32]byte, sourceChainSelector uint64, destChainSelector uint64, onRamp []byte) ([]byte, error) - EncodeTokenAmountsHashPreimage(opts *bind.CallOpts, rampTokenAmounts []InternalRampTokenAmount) ([]byte, error) + EncodeTokenAmountsHashPreimage(opts *bind.CallOpts, tokenAmount []InternalEVM2AnyTokenTransfer) ([]byte, error) + + EncodeTokenAmountsHashPreimage0(opts *bind.CallOpts, tokenAmounts []InternalAny2EVMTokenTransfer) ([]byte, error) Hash(opts *bind.CallOpts, message InternalAny2EVMRampMessage, onRamp []byte) ([32]byte, error) diff --git a/core/gethwrappers/ccip/generated/offramp/offramp.go b/core/gethwrappers/ccip/generated/offramp/offramp.go index 8828214d11..5b063866b4 100644 --- a/core/gethwrappers/ccip/generated/offramp/offramp.go +++ b/core/gethwrappers/ccip/generated/offramp/offramp.go @@ -49,7 +49,15 @@ type InternalAny2EVMRampMessage struct { Data []byte Receiver common.Address GasLimit *big.Int - TokenAmounts []InternalRampTokenAmount + TokenAmounts []InternalAny2EVMTokenTransfer +} + +type InternalAny2EVMTokenTransfer struct { + SourcePoolAddress []byte + DestTokenAddress common.Address + DestGasAmount uint32 + ExtraData []byte + Amount *big.Int } type InternalExecutionReportSingleChain struct { @@ -86,14 +94,6 @@ type InternalRampMessageHeader struct { Nonce uint64 } -type InternalRampTokenAmount struct { - SourcePoolAddress []byte - DestTokenAddress []byte - ExtraData []byte - Amount *big.Int - DestExecData []byte -} - type InternalTokenPriceUpdate struct { SourceToken common.Address UsdPerToken *big.Int @@ -154,8 +154,8 @@ type OffRampStaticConfig struct { } var OffRampMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CanOnlySelfCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"reportOnRamp\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"configOnRamp\",\"type\":\"bytes\"}],\"name\":\"CommitOnRampMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"actual\",\"type\":\"bytes32\"}],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ExecutionError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"ForkedChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enumMultiOCR3Base.InvalidConfigErrorType\",\"name\":\"errorType\",\"type\":\"uint8\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"got\",\"type\":\"uint256\"}],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedAddress\",\"type\":\"bytes\"}],\"name\":\"InvalidEVMAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"name\":\"InvalidInterval\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"newLimit\",\"type\":\"uint256\"}],\"name\":\"InvalidManualExecutionGasLimit\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"tokenIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"oldLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenGasOverride\",\"type\":\"uint256\"}],\"name\":\"InvalidManualExecutionTokenGasOverride\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"messageDestChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidMessageDestChainSelector\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"newState\",\"type\":\"uint8\"}],\"name\":\"InvalidNewState\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidOnRampUpdate\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRoot\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LeavesCannotBeEmpty\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"ManualExecutionGasAmountCountMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ManualExecutionGasLimitMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"ManualExecutionNotYetEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"errorReason\",\"type\":\"bytes\"}],\"name\":\"MessageValidationError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonUniqueSignatures\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"notPool\",\"type\":\"address\"}],\"name\":\"NotACompatiblePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OracleCannotBeZeroAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ReceiverError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountReleased\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePre\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePost\",\"type\":\"uint256\"}],\"name\":\"ReleaseOrMintBalanceMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"name\":\"RootAlreadyCommitted\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"RootNotCommitted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignatureVerificationDisabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignaturesOutOfRegistration\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"reportSourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"messageSourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainSelectorMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"StaleCommitReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"StaticConfigCannotBeChanged\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"TokenDataMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"TokenHandlingError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnexpectedTokenData\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"WrongMessageLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WrongNumberOfSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroChainSelectorNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"AlreadyAttempted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"indexed\":false,\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"}],\"name\":\"CommitReportAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"DynamicConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"messageHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"name\":\"ExecutionStateChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"RootRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"SkippedAlreadyExecutedMessage\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SkippedReportExecution\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"sourceConfig\",\"type\":\"tuple\"}],\"name\":\"SourceChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainSelectorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"}],\"name\":\"StaticConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigUpdates\",\"type\":\"tuple[]\"}],\"name\":\"applySourceChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"destTokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structClient.Any2EVMMessage\",\"name\":\"\",\"type\":\"tuple\"}],\"name\":\"ccipReceive\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"rawVs\",\"type\":\"bytes32\"}],\"name\":\"commit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"execute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"bytes[]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[]\"},{\"internalType\":\"uint32[]\",\"name\":\"tokenGasOverrides\",\"type\":\"uint32[]\"}],\"name\":\"executeSingleMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"getExecutionState\",\"outputs\":[{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLatestPriceSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"getMerkleRoot\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"getSourceChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"latestConfigDetails\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"n\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"}],\"internalType\":\"structMultiOCR3Base.ConfigInfo\",\"name\":\"configInfo\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfig\",\"name\":\"ocrConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage[]\",\"name\":\"messages\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[][]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[][]\"},{\"internalType\":\"bytes32[]\",\"name\":\"proofs\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"proofFlagBits\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.ExecutionReportSingleChain[]\",\"name\":\"reports\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"receiverExecutionGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint32[]\",\"name\":\"tokenGasOverrides\",\"type\":\"uint32[]\"}],\"internalType\":\"structOffRamp.GasLimitOverride[][]\",\"name\":\"gasLimitOverrides\",\"type\":\"tuple[][]\"}],\"name\":\"manuallyExecute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"setDynamicConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfigArgs[]\",\"name\":\"ocrConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"setOCR3Configs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x6101206040523480156200001257600080fd5b50604051620068cb380380620068cb833981016040819052620000359162000806565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf81620001fa565b5050466080525060208301516001600160a01b03161580620000ec575060408301516001600160a01b0316155b8062000103575060608301516001600160a01b0316155b1562000122576040516342bcdf7f60e11b815260040160405180910390fd5b82516001600160401b03166000036200014e5760405163c656089560e01b815260040160405180910390fd5b82516001600160401b0390811660a052602080850180516001600160a01b0390811660c05260408088018051831660e0526060808a01805185166101005283518b519098168852945184169587019590955251821690850152905116908201527f683eb52ee924eb817377cfa8f41f238f4bb7a877da5267869dfffbad85f564d89060800160405180910390a1620001e682620002a5565b620001f1816200036d565b50505062000b8d565b336001600160a01b03821603620002545760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b0316620002ce576040516342bcdf7f60e11b815260040160405180910390fd5b805160048054602080850180516001600160a01b039586166001600160c01b03199094168417600160a01b63ffffffff928316021790945560408087018051600580546001600160a01b031916918916919091179055815194855291519094169183019190915251909216908201527fa1c15688cb2c24508e158f6942b9276c6f3028a85e1af8cf3fff0c3ff3d5fc8d9060600160405180910390a150565b60005b8151811015620005ba57600082828151811062000391576200039162000943565b60200260200101519050600081602001519050806001600160401b0316600003620003cf5760405163c656089560e01b815260040160405180910390fd5b81516001600160a01b0316620003f8576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160401b03811660009081526006602052604090206060830151600182018054620004269062000959565b905060000362000489578154600160a81b600160e81b031916600160a81b1782556040516001600160401b03841681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1620004c8565b8154600160a81b90046001600160401b0316600114620004c857604051632105803760e11b81526001600160401b038416600482015260240162000083565b80511580620004fe5750604080516000602082015201604051602081830303815290604052805190602001208180519060200120145b156200051d576040516342bcdf7f60e11b815260040160405180910390fd5b600182016200052d8282620009ea565b50604080850151835486516001600160a01b03166001600160a01b0319921515600160a01b02929092166001600160a81b031990911617178355516001600160401b038416907f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b90620005a290859062000ab6565b60405180910390a25050505080600101905062000370565b5050565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b0381118282101715620005f957620005f9620005be565b60405290565b604051601f8201601f191681016001600160401b03811182821017156200062a576200062a620005be565b604052919050565b80516001600160401b03811681146200064a57600080fd5b919050565b6001600160a01b03811681146200066557600080fd5b50565b6000601f83601f8401126200067c57600080fd5b825160206001600160401b03808311156200069b576200069b620005be565b8260051b620006ac838201620005ff565b9384528681018301938381019089861115620006c757600080fd5b84890192505b85831015620007f957825184811115620006e75760008081fd5b89016080601f19828d038101821315620007015760008081fd5b6200070b620005d4565b888401516200071a816200064f565b815260406200072b85820162000632565b8a8301526060808601518015158114620007455760008081fd5b838301529385015193898511156200075d5760008081fd5b84860195508f603f8701126200077557600094508485fd5b8a8601519450898511156200078e576200078e620005be565b6200079f8b858f88011601620005ff565b93508484528f82868801011115620007b75760008081fd5b60005b85811015620007d7578681018301518582018d01528b01620007ba565b5060009484018b019490945250918201528352509184019190840190620006cd565b9998505050505050505050565b60008060008385036101008112156200081e57600080fd5b60808112156200082d57600080fd5b62000837620005d4565b620008428662000632565b8152602086015162000854816200064f565b6020820152604086015162000869816200064f565b604082015260608601516200087e816200064f565b606082810191909152909450607f19820112156200089b57600080fd5b50604051606081016001600160401b038082118383101715620008c257620008c2620005be565b8160405260808701519150620008d8826200064f565b90825260a08601519063ffffffff82168214620008f457600080fd5b81602084015260c087015191506200090c826200064f565b6040830182905260e0870151929450808311156200092957600080fd5b5050620009398682870162000668565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b600181811c908216806200096e57607f821691505b6020821081036200098f57634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115620009e5576000816000526020600020601f850160051c81016020861015620009c05750805b601f850160051c820191505b81811015620009e157828155600101620009cc565b5050505b505050565b81516001600160401b0381111562000a065762000a06620005be565b62000a1e8162000a17845462000959565b8462000995565b602080601f83116001811462000a56576000841562000a3d5750858301515b600019600386901b1c1916600185901b178555620009e1565b600085815260208120601f198616915b8281101562000a875788860151825594840194600190910190840162000a66565b508582101562000aa65787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b602080825282546001600160a01b0381168383015260a081901c60ff161515604084015260a81c6001600160401b0316606083015260808083015260018084018054600093929190849062000b0b8162000959565b8060a089015260c0600183166000811462000b2f576001811462000b4c5762000b7e565b60ff19841660c08b015260c083151560051b8b0101945062000b7e565b85600052602060002060005b8481101562000b755781548c820185015290880190890162000b58565b8b0160c0019550505b50929998505050505050505050565b60805160a05160c05160e05161010051615cc862000c036000396000818161022c01526129f40152600081816101fd0152612cc60152600081816101ce01528181610552015281816106ff01526123b501526000818161019f01526125f4015260008181611d920152611dc50152615cc86000f3fe608060405234801561001057600080fd5b50600436106101515760003560e01c806379ba5097116100cd578063d434969111610081578063e9d68a8e11610066578063e9d68a8e146104bc578063f2fde38b146104dc578063f716f99f146104ef57600080fd5b8063d434969114610496578063e62653f5146104a957600080fd5b80638da5cb5b116100b25780638da5cb5b14610417578063c673e58414610432578063ccd37ba31461045257600080fd5b806379ba50971461040157806385572ffb1461040957600080fd5b8063311cd513116101245780635e36480c116101095780635e36480c1461033c5780636f9e320f1461035c5780637437ff9f1461036f57600080fd5b8063311cd5131461030e5780633f4b04aa1461032157600080fd5b806304666f9c1461015657806306285c691461016b578063181f5a77146102b25780632d04ab76146102fb575b600080fd5b610169610164366004613c73565b610502565b005b61025c60408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160401b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316815250905090565b6040516102a9919081516001600160401b031681526020808301516001600160a01b0390811691830191909152604080840151821690830152606092830151169181019190915260800190565b60405180910390f35b6102ee6040518060400160405280601181526020017f4f666652616d7020312e362e302d64657600000000000000000000000000000081525081565b6040516102a99190613de1565b610169610309366004613e91565b610516565b61016961031c366004613f43565b610a12565b6009546040516001600160401b0390911681526020016102a9565b61034f61034a366004613f96565b610a7b565b6040516102a99190613ff3565b61016961036a36600461401e565b610ad0565b6103cb604080516060810182526000808252602082018190529181019190915250604080516060810182526004546001600160a01b038082168352600160a01b90910463ffffffff166020830152600554169181019190915290565b6040805182516001600160a01b03908116825260208085015163ffffffff169083015292820151909216908201526060016102a9565b610169610ae1565b610169610151366004614072565b6000546040516001600160a01b0390911681526020016102a9565b6104456104403660046140bd565b610b92565b6040516102a9919061411d565b610488610460366004614192565b6001600160401b03919091166000908152600860209081526040808320938352929052205490565b6040519081526020016102a9565b6101696104a436600461442e565b610cf0565b6101696104b73660046147b6565b610fd0565b6104cf6104ca3660046149fd565b611277565b6040516102a99190614a18565b6101696104ea366004614a65565b611383565b6101696104fd366004614aea565b611394565b61050a6113d6565b61051381611432565b50565b600061052487890189614e3f565b602081015151909150156105b6576020810151604080830151905162ccd5af60e81b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169263ccd5af009261058592600401615067565b60006040518083038186803b15801561059d57600080fd5b505afa1580156105b1573d6000803e3d6000fd5b505050505b805151511515806105cc57508051602001515115155b156106985760095460208a0135906001600160401b0380831691161015610670576009805467ffffffffffffffff19166001600160401b038316179055600480548351604051633937306f60e01b81526001600160a01b0390921692633937306f9261063992910161519b565b600060405180830381600087803b15801561065357600080fd5b505af1158015610667573d6000803e3d6000fd5b50505050610696565b81602001515160000361069657604051632261116760e01b815260040160405180910390fd5b505b60005b816020015151811015610953576000826020015182815181106106c0576106c06150c9565b60209081029190910101518051604051632cbc26bb60e01b815267ffffffffffffffff60801b608083901b166004820152919250906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632cbc26bb90602401602060405180830381865afa158015610746573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061076a91906151ae565b1561079857604051637edeb53960e11b81526001600160401b03821660048201526024015b60405180910390fd5b60006107a382611685565b9050806001016040516107b69190615205565b6040518091039020836020015180519060200120146107f35782602001518160010160405163b80d8fa960e01b815260040161078f9291906152f8565b60408301518154600160a81b90046001600160401b039081169116141580610834575082606001516001600160401b031683604001516001600160401b0316115b1561087957825160408085015160608601519151636af0786b60e11b81526001600160401b03938416600482015290831660248201529116604482015260640161078f565b60808301518061089c5760405163504570e360e01b815260040160405180910390fd5b83516001600160401b03166000908152600860209081526040808320848452909152902054156108f45783516040516332cf0cbf60e01b81526001600160401b0390911660048201526024810182905260440161078f565b6060840151610904906001615333565b825467ffffffffffffffff60a81b1916600160a81b6001600160401b0392831602179092559251166000908152600860209081526040808320948352939052919091204290555060010161069b565b50602081015181516040517f35c02761bcd3ef995c6a601a1981f4ed3934dcbe5041e24e286c89f5531d17e49261098b92909161535a565b60405180910390a1610a0760008a8a8a8a8a8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808e0282810182019093528d82529093508d92508c9182918501908490808284376000920191909152508b92506116d1915050565b505050505050505050565b610a52610a218284018461537f565b6040805160008082526020820190925290610a4c565b6060815260200190600190039081610a375790505b506119ca565b604080516000808252602082019092529050610a756001858585858660006116d1565b50505050565b6000610a89600160046153b3565b6002610a966080856153dc565b6001600160401b0316610aa99190615402565b610ab38585611a8c565b901c166003811115610ac757610ac7613fc9565b90505b92915050565b610ad86113d6565b61051381611ad1565b6001546001600160a01b03163314610b3b5760405162461bcd60e51b815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e657200000000000000000000604482015260640161078f565b60008054336001600160a01b0319808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610bd56040805160e081019091526000606082018181526080830182905260a0830182905260c08301919091528190815260200160608152602001606081525090565b60ff808316600090815260026020818152604092839020835160e081018552815460608201908152600183015480881660808401526101008104881660a0840152620100009004909616151560c082015294855291820180548451818402810184019095528085529293858301939092830182828015610c7e57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610c60575b5050505050815260200160038201805480602002602001604051908101604052809291908181526020018280548015610ce057602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610cc2575b5050505050815250509050919050565b333014610d10576040516306e34e6560e31b815260040160405180910390fd5b6040805160008082526020820190925281610d4d565b6040805180820190915260008082526020820152815260200190600190039081610d265790505b5060a08701515190915015610d8357610d808660a001518760200151886060015189600001516020015189898989611bb0565b90505b6040805160a081018252875151815287516020908101516001600160401b031681830152808901518351600094840192610dbe929101613de1565b60408051601f19818403018152918152908252898101516020830152018390526005549091506001600160a01b03168015610e99576040516308d450a160e01b81526001600160a01b038216906308d450a190610e1f9085906004016154ba565b600060405180830381600087803b158015610e3957600080fd5b505af1925050508015610e4a575060015b610e99573d808015610e78576040519150601f19603f3d011682016040523d82523d6000602084013e610e7d565b606091505b50806040516309c2532560e01b815260040161078f9190613de1565b604088015151158015610eae57506080880151155b80610ec5575060608801516001600160a01b03163b155b80610eec57506060880151610eea906001600160a01b03166385572ffb60e01b611d73565b155b15610ef957505050610fc9565b87516020908101516001600160401b03166000908152600690915260408082205460808b015160608c01519251633cf9798360e01b815284936001600160a01b0390931692633cf9798392610f5792899261138892916004016154cd565b6000604051808303816000875af1158015610f76573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610f9e9190810190615509565b509150915081610fc357806040516302a35ba360e21b815260040161078f9190613de1565b50505050505b5050505050565b610fd8611d8f565b815181518114610ffb576040516320f8fd5960e21b815260040160405180910390fd5b60005b8181101561126757600084828151811061101a5761101a6150c9565b60200260200101519050600081602001515190506000858481518110611042576110426150c9565b602002602001015190508051821461106d576040516320f8fd5960e21b815260040160405180910390fd5b60005b8281101561125857600082828151811061108c5761108c6150c9565b60200260200101516000015190506000856020015183815181106110b2576110b26150c9565b6020026020010151905081600014611106578060800151821015611106578551815151604051633a98d46360e11b81526001600160401b03909216600483015260248201526044810183905260640161078f565b838381518110611118576111186150c9565b602002602001015160200151518160a00151511461116557805180516060909101516040516370a193fd60e01b815260048101929092526001600160401b0316602482015260440161078f565b60005b8160a001515181101561124a576000858581518110611189576111896150c9565b60200260200101516020015182815181106111a6576111a66150c9565b602002602001015163ffffffff169050806000146112415760008360a0015183815181106111d6576111d66150c9565b6020026020010151608001518060200190518101906111f5919061559e565b90508063ffffffff1682101561123f578351516040516348e617b360e01b815260048101919091526024810184905263ffffffff821660448201526064810183905260840161078f565b505b50600101611168565b505050806001019050611070565b50505050806001019050610ffe565b5061127283836119ca565b505050565b60408051608080820183526000808352602080840182905283850182905260608085018190526001600160401b03878116845260068352928690208651948501875280546001600160a01b0381168652600160a01b810460ff16151593860193909352600160a81b909204909216948301949094526001840180549394929391840191611303906151cb565b80601f016020809104026020016040519081016040528092919081815260200182805461132f906151cb565b8015610ce05780601f1061135157610100808354040283529160200191610ce0565b820191906000526020600020905b81548152906001019060200180831161135f57505050919092525091949350505050565b61138b6113d6565b61051381611df7565b61139c6113d6565b60005b81518110156113d2576113ca8282815181106113bd576113bd6150c9565b6020026020010151611ea0565b60010161139f565b5050565b6000546001600160a01b031633146114305760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640161078f565b565b60005b81518110156113d2576000828281518110611452576114526150c9565b60200260200101519050600081602001519050806001600160401b031660000361148f5760405163c656089560e01b815260040160405180910390fd5b81516001600160a01b03166114b7576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160401b038116600090815260066020526040902060608301516001820180546114e3906151cb565b905060000361154557815467ffffffffffffffff60a81b1916600160a81b1782556040516001600160401b03841681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1611582565b8154600160a81b90046001600160401b031660011461158257604051632105803760e11b81526001600160401b038416600482015260240161078f565b805115806115b75750604080516000602082015201604051602081830303815290604052805190602001208180519060200120145b156115d5576040516342bcdf7f60e11b815260040160405180910390fd5b600182016115e3828261560b565b50604080850151835486516001600160a01b03166001600160a01b0319921515600160a01b02929092167fffffffffffffffffffffff00000000000000000000000000000000000000000090911617178355516001600160401b038416907f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b9061166e9085906156ca565b60405180910390a250505050806001019050611435565b6001600160401b03811660009081526006602052604081208054600160a01b900460ff16610aca5760405163ed053c5960e01b81526001600160401b038416600482015260240161078f565b60ff878116600090815260026020908152604080832081516080810183528154815260019091015480861693820193909352610100830485169181019190915262010000909104909216151560608301528735906117308760a4615718565b9050826060015115611778578451611749906020615402565b8651611756906020615402565b6117619060a0615718565b61176b9190615718565b6117759082615718565b90505b3681146117a157604051638e1192e160e01b81526004810182905236602482015260440161078f565b50815181146117d05781516040516324f7d61360e21b815260048101919091526024810182905260440161078f565b6117d8611d8f565b60ff808a166000908152600360209081526040808320338452825280832081518083019092528054808616835293949193909284019161010090910416600281111561182657611826613fc9565b600281111561183757611837613fc9565b905250905060028160200151600281111561185457611854613fc9565b1480156118a85750600260008b60ff1660ff168152602001908152602001600020600301816000015160ff1681548110611890576118906150c9565b6000918252602090912001546001600160a01b031633145b6118c557604051631b41e11d60e31b815260040160405180910390fd5b508160600151156119755760208201516118e090600161572b565b60ff16855114611903576040516371253a2560e01b815260040160405180910390fd5b83518551146119255760405163a75d88af60e01b815260040160405180910390fd5b60008787604051611937929190615744565b60405190819003812061194e918b90602001615754565b6040516020818303038152906040528051906020012090506119738a828888886121ca565b505b6040805182815260208a8101356001600160401b03169082015260ff8b16917f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef0910160405180910390a2505050505050505050565b81516000036119eb5760405162bf199760e01b815260040160405180910390fd5b80516040805160008082526020820190925291159181611a2e565b604080518082019091526000815260606020820152815260200190600190039081611a065790505b50905060005b8451811015610fc957611a84858281518110611a5257611a526150c9565b602002602001015184611a7e57858381518110611a7157611a716150c9565b6020026020010151612387565b83612387565b600101611a34565b6001600160401b038216600090815260076020526040812081611ab0608085615768565b6001600160401b031681526020810191909152604001600020549392505050565b80516001600160a01b0316611af9576040516342bcdf7f60e11b815260040160405180910390fd5b805160048054602080850180516001600160a01b039586167fffffffffffffffff0000000000000000000000000000000000000000000000009094168417600160a01b63ffffffff928316021790945560408087018051600580546001600160a01b031916918916919091179055815194855291519094169183019190915251909216908201527fa1c15688cb2c24508e158f6942b9276c6f3028a85e1af8cf3fff0c3ff3d5fc8d9060600160405180910390a150565b606088516001600160401b03811115611bcb57611bcb613a93565b604051908082528060200260200182016040528015611c1057816020015b6040805180820190915260008082526020820152815260200190600190039081611be95790505b509050811560005b8a51811015611d655781611cc257848482818110611c3857611c386150c9565b9050602002016020810190611c4d919061578e565b63ffffffff1615611cc257848482818110611c6a57611c6a6150c9565b9050602002016020810190611c7f919061578e565b6040805163ffffffff9092166020830152016040516020818303038152906040528b8281518110611cb257611cb26150c9565b6020026020010151608001819052505b611d408b8281518110611cd757611cd76150c9565b60200260200101518b8b8b8b8b87818110611cf457611cf46150c9565b9050602002810190611d0691906157ab565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612c7e92505050565b838281518110611d5257611d526150c9565b6020908102919091010152600101611c18565b505098975050505050505050565b6000611d7e83612f7c565b8015610ac75750610ac78383612fc7565b467f00000000000000000000000000000000000000000000000000000000000000001461143057604051630f01ce8560e01b81527f0000000000000000000000000000000000000000000000000000000000000000600482015246602482015260440161078f565b336001600160a01b03821603611e4f5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161078f565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b806040015160ff16600003611ecb576000604051631b3fab5160e11b815260040161078f91906157f1565b60208082015160ff80821660009081526002909352604083206001810154929390928392169003611f1c576060840151600182018054911515620100000262ff000019909216919091179055611f58565b6060840151600182015460ff6201000090910416151590151514611f58576040516321fd80df60e21b815260ff8416600482015260240161078f565b60a084015180516101001015611f84576001604051631b3fab5160e11b815260040161078f91906157f1565b8051600003611fa9576005604051631b3fab5160e11b815260040161078f91906157f1565b61200f848460030180548060200260200160405190810160405280929190818152602001828054801561200557602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611fe7575b5050505050613069565b84606001511561213f5761207d8484600201805480602002602001604051908101604052809291908181526020018280548015612005576020028201919060005260206000209081546001600160a01b03168152600190910190602001808311611fe7575050505050613069565b6080850151805161010010156120a9576002604051631b3fab5160e11b815260040161078f91906157f1565b60408601516120b990600361580b565b60ff168151116120df576003604051631b3fab5160e11b815260040161078f91906157f1565b815181511015612105576001604051631b3fab5160e11b815260040161078f91906157f1565b805160018401805461ff00191661010060ff8416021790556121309060028601906020840190613a19565b5061213d858260016130d2565b505b61214b848260026130d2565b80516121609060038501906020840190613a19565b5060408581015160018401805460ff191660ff8316179055865180855560a088015192517fab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f547936121b99389939260028a01929190615827565b60405180910390a1610fc98461322d565b8251600090815b8181101561237d5760006001888684602081106121f0576121f06150c9565b6121fd91901a601b61572b565b89858151811061220f5761220f6150c9565b6020026020010151898681518110612229576122296150c9565b602002602001015160405160008152602001604052604051612267949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015612289573d6000803e3d6000fd5b505060408051601f1981015160ff808e166000908152600360209081528582206001600160a01b038516835281528582208587019096528554808416865293975090955092939284019161010090041660028111156122ea576122ea613fc9565b60028111156122fb576122fb613fc9565b905250905060018160200151600281111561231857612318613fc9565b1461233657604051636518c33d60e11b815260040160405180910390fd5b8051600160ff9091161b85161561236057604051633d9ef1f160e21b815260040160405180910390fd5b806000015160ff166001901b8517945050508060010190506121d1565b5050505050505050565b81518151604051632cbc26bb60e01b8152608083901b67ffffffffffffffff60801b166004820152901515907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632cbc26bb90602401602060405180830381865afa158015612404573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061242891906151ae565b1561249957801561245757604051637edeb53960e11b81526001600160401b038316600482015260240161078f565b6040516001600160401b03831681527faab522ed53d887e56ed53dd37398a01aeef6a58e0fa77c2173beb9512d8949339060200160405180910390a150505050565b60006124a483611685565b60010180546124b2906151cb565b80601f01602080910402602001604051908101604052809291908181526020018280546124de906151cb565b801561252b5780601f106125005761010080835404028352916020019161252b565b820191906000526020600020905b81548152906001019060200180831161250e57829003601f168201915b5050506020880151519293505050600081900361255a5760405162bf199760e01b815260040160405180910390fd5b856040015151811461257f576040516357e0e08360e01b815260040160405180910390fd5b6000816001600160401b0381111561259957612599613a93565b6040519080825280602002602001820160405280156125c2578160200160208202803683370190505b50905060005b82811015612766576000886020015182815181106125e8576125e86150c9565b602002602001015190507f00000000000000000000000000000000000000000000000000000000000000006001600160401b03168160000151604001516001600160401b03161461265f5780516040908101519051631c21951160e11b81526001600160401b03909116600482015260240161078f565b866001600160401b03168160000151602001516001600160401b0316146126b357805160200151604051636c95f1eb60e01b81526001600160401b03808a166004830152909116602482015260440161078f565b612740817f2425b0b9f9054c76ff151b0a175b18f37a4a4e82013a72e9f15c9caa095ed21f836000015160200151846000015160400151898051906020012060405160200161272594939291909384526001600160401b03928316602085015291166040830152606082015260800190565b60405160208183030381529060405280519060200120613284565b838381518110612752576127526150c9565b6020908102919091010152506001016125c8565b50600061277d86838a606001518b6080015161338c565b9050806000036127ab57604051633ee8bd3f60e11b81526001600160401b038716600482015260240161078f565b60005b83811015610a075760005a905060008a6020015183815181106127d3576127d36150c9565b6020026020010151905060006127f18a836000015160600151610a7b565b9050600081600381111561280757612807613fc9565b14806128245750600381600381111561282257612822613fc9565b145b61287a57815160600151604080516001600160401b03808e16825290921660208301527f3b575419319662b2a6f5e2467d84521517a3382b908eb3d557bb3fdb0c50e23c910160405180910390a1505050612c76565b60608915612959578b8581518110612894576128946150c9565b6020908102919091018101510151600454909150600090600160a01b900463ffffffff166128c288426153b3565b11905080806128e2575060038360038111156128e0576128e0613fc9565b145b61290a576040516354e7e43160e11b81526001600160401b038d16600482015260240161078f565b8c868151811061291c5761291c6150c9565b602002602001015160000151600014612953578c8681518110612941576129416150c9565b60209081029190910101515160808501525b506129c5565b600082600381111561296d5761296d613fc9565b146129c557825160600151604080516001600160401b03808f16825290921660208301527f3ef2a99c550a751d4b0b261268f05a803dfb049ab43616a1ffb388f61fe65120910160405180910390a150505050612c76565b8251608001516001600160401b031615612a9e5760008260038111156129ed576129ed613fc9565b03612a9e577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e0e03cae8c85600001516080015186602001516040518463ffffffff1660e01b8152600401612a4e939291906158d9565b6020604051808303816000875af1158015612a6d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a9191906151ae565b612a9e5750505050612c76565b60008d604001518681518110612ab657612ab66150c9565b6020026020010151905080518460a001515114612b0057835160600151604051631cfe6d8b60e01b81526001600160401b03808f166004830152909116602482015260440161078f565b612b148c85600001516060015160016133c9565b600080612b2286848661346e565b91509150612b398e876000015160600151846133c9565b8c15612b90576003826003811115612b5357612b53613fc9565b03612b90576000856003811115612b6c57612b6c613fc9565b14612b9057855151604051632b11b8d960e01b815261078f91908390600401615905565b6002826003811115612ba457612ba4613fc9565b14612be9576003826003811115612bbd57612bbd613fc9565b14612be9578d866000015160600151836040516349362d1f60e11b815260040161078f9392919061591e565b8560000151600001518660000151606001516001600160401b03168f6001600160401b03167f05665fe9ad095383d018353f4cbcba77e84db27dd215081bbf7cdf9ae6fbe48b8d8c81518110612c4157612c416150c9565b602002602001015186865a612c56908f6153b3565b604051612c669493929190615943565b60405180910390a4505050505050505b6001016127ae565b60408051808201909152600080825260208201526000612ca18760200151613522565b60405163bbe4f6db60e01b81526001600160a01b0380831660048301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063bbe4f6db90602401602060405180830381865afa158015612d0d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d31919061597a565b90506001600160a01b0381161580612d605750612d5e6001600160a01b03821663aff2afbf60e01b611d73565b155b15612d895760405163ae9b4ce960e01b81526001600160a01b038216600482015260240161078f565b600080612db488858c60800151806020019051810190612da9919061559e565b63ffffffff16613596565b915091506000806000612e676040518061010001604052808e81526020018c6001600160401b031681526020018d6001600160a01b031681526020018f606001518152602001896001600160a01b031681526020018f6000015181526020018f6040015181526020018b815250604051602401612e319190615997565b60408051601f198184030181529190526020810180516001600160e01b0316633907753760e01b17905287866113886084613679565b92509250925082612e8d578160405163e1cd550960e01b815260040161078f9190613de1565b8151602014612ebc578151604051631e3be00960e21b815260206004820152602481019190915260440161078f565b600082806020019051810190612ed29190615a63565b9050866001600160a01b03168c6001600160a01b031614612f4e576000612f038d8a612efe868a6153b3565b613596565b50905086811080612f1d575081612f1a88836153b3565b14155b15612f4c5760405163a966e21f60e01b815260048101839052602481018890526044810182905260640161078f565b505b604080518082019091526001600160a01b039098168852602088015250949550505050505095945050505050565b6000612f8f826301ffc9a760e01b612fc7565b8015610aca5750612fc0827fffffffff00000000000000000000000000000000000000000000000000000000612fc7565b1592915050565b6040517fffffffff0000000000000000000000000000000000000000000000000000000082166024820152600090819060440160408051601f19818403018152919052602080820180516001600160e01b03166301ffc9a760e01b178152825192935060009283928392909183918a617530fa92503d91506000519050828015613052575060208210155b801561305e5750600081115b979650505050505050565b60005b81518110156112725760ff83166000908152600360205260408120835190919084908490811061309e5761309e6150c9565b6020908102919091018101516001600160a01b03168252810191909152604001600020805461ffff1916905560010161306c565b60005b8251811015610a755760008382815181106130f2576130f26150c9565b602002602001015190506000600281111561310f5761310f613fc9565b60ff80871660009081526003602090815260408083206001600160a01b0387168452909152902054610100900416600281111561314e5761314e613fc9565b1461316f576004604051631b3fab5160e11b815260040161078f91906157f1565b6001600160a01b0381166131965760405163d6c62c9b60e01b815260040160405180910390fd5b60405180604001604052808360ff1681526020018460028111156131bc576131bc613fc9565b905260ff80871660009081526003602090815260408083206001600160a01b0387168452825290912083518154931660ff198416811782559184015190929091839161ffff19161761010083600281111561321957613219613fc9565b0217905550905050508060010190506130d5565b60ff81166105135760ff8082166000908152600260205260409020600101546201000090041661327057604051631e8ed32560e21b815260040160405180910390fd5b6009805467ffffffffffffffff1916905550565b8151805160608085015190830151608080870151940151604051600095869588956132e895919490939192916020019485526001600160a01b039390931660208501526001600160401b039182166040850152606084015216608082015260a00190565b604051602081830303815290604052805190602001208560200151805190602001208660400151805190602001208760a0015160405160200161332b9190615b2e565b60408051601f198184030181528282528051602091820120908301979097528101949094526060840192909252608083015260a082015260c081019190915260e0015b60405160208183030381529060405280519060200120905092915050565b60008061339a858585613753565b6001600160401b038716600090815260086020908152604080832093835292905220549150505b949350505050565b600060026133d86080856153dc565b6001600160401b03166133eb9190615402565b905060006133f98585611a8c565b905081613408600160046153b3565b901b19168183600381111561341f5761341f613fc9565b6001600160401b03871660009081526007602052604081209190921b9290921791829161344d608088615768565b6001600160401b031681526020810191909152604001600020555050505050565b60405163d434969160e01b8152600090606090309063d43496919061349b90889088908890600401615bc5565b600060405180830381600087803b1580156134b557600080fd5b505af19250505080156134c6575060015b613505573d8080156134f4576040519150601f19603f3d011682016040523d82523d6000602084013e6134f9565b606091505b5060039250905061351a565b50506040805160208101909152600081526002905b935093915050565b60008151602014613548578160405163046b337b60e51b815260040161078f9190613de1565b60008280602001905181019061355e9190615a63565b90506001600160a01b03811180613576575061040081105b15610aca578260405163046b337b60e51b815260040161078f9190613de1565b60008060008060006135f7886040516024016135c191906001600160a01b0391909116815260200190565b60408051601f198184030181529190526020810180516001600160e01b03166370a0823160e01b17905288886113886084613679565b9250925092508261361d578160405163e1cd550960e01b815260040161078f9190613de1565b602082511461364c578151604051631e3be00960e21b815260206004820152602481019190915260440161078f565b818060200190518101906136609190615a63565b61366a82886153b3565b94509450505050935093915050565b6000606060008361ffff166001600160401b0381111561369b5761369b613a93565b6040519080825280601f01601f1916602001820160405280156136c5576020820181803683370190505b509150863b6136df5763030ed58f60e21b60005260046000fd5b5a858110156136f957632be8ca8b60e21b60005260046000fd5b8590036040810481038710613719576337c3be2960e01b60005260046000fd5b505a6000808a5160208c0160008c8cf193505a900390503d8481111561373c5750835b808352806000602085013e50955095509592505050565b825182516000919081830361377b57604051630469ac9960e21b815260040160405180910390fd5b610101821180159061378f57506101018111155b6137ac576040516309bde33960e01b815260040160405180910390fd5b600019828201016101008111156137d6576040516309bde33960e01b815260040160405180910390fd5b8060000361380357866000815181106137f1576137f16150c9565b602002602001015193505050506139d1565b6000816001600160401b0381111561381d5761381d613a93565b604051908082528060200260200182016040528015613846578160200160208202803683370190505b50905060008080805b858110156139705760006001821b8b8116036138aa5788851015613893578c5160018601958e918110613884576138846150c9565b602002602001015190506138cc565b8551600185019487918110613884576138846150c9565b8b5160018401938d9181106138c1576138c16150c9565b602002602001015190505b6000898610156138fc578d5160018701968f9181106138ed576138ed6150c9565b6020026020010151905061391e565b8651600186019588918110613913576139136150c9565b602002602001015190505b8285111561393f576040516309bde33960e01b815260040160405180910390fd5b61394982826139d8565b87848151811061395b5761395b6150c9565b6020908102919091010152505060010161384f565b50600185038214801561398257508683145b801561398d57508581145b6139aa576040516309bde33960e01b815260040160405180910390fd5b8360018603815181106139bf576139bf6150c9565b60200260200101519750505050505050505b9392505050565b60008183106139f0576139eb82846139f6565b610ac7565b610ac783835b60408051600160208201529081018390526060810182905260009060800161336e565b828054828255906000526020600020908101928215613a6e579160200282015b82811115613a6e57825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190613a39565b50613a7a929150613a7e565b5090565b5b80821115613a7a5760008155600101613a7f565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b0381118282101715613acb57613acb613a93565b60405290565b604051606081016001600160401b0381118282101715613acb57613acb613a93565b60405160a081016001600160401b0381118282101715613acb57613acb613a93565b60405160c081016001600160401b0381118282101715613acb57613acb613a93565b604080519081016001600160401b0381118282101715613acb57613acb613a93565b604051601f8201601f191681016001600160401b0381118282101715613b8157613b81613a93565b604052919050565b60006001600160401b03821115613ba257613ba2613a93565b5060051b60200190565b6001600160a01b038116811461051357600080fd5b80356001600160401b0381168114613bd857600080fd5b919050565b801515811461051357600080fd5b8035613bd881613bdd565b60006001600160401b03821115613c0f57613c0f613a93565b50601f01601f191660200190565b600082601f830112613c2e57600080fd5b8135613c41613c3c82613bf6565b613b59565b818152846020838601011115613c5657600080fd5b816020850160208301376000918101602001919091529392505050565b60006020808385031215613c8657600080fd5b82356001600160401b0380821115613c9d57600080fd5b818501915085601f830112613cb157600080fd5b8135613cbf613c3c82613b89565b81815260059190911b83018401908481019088831115613cde57600080fd5b8585015b83811015613d8457803585811115613cfa5760008081fd5b86016080818c03601f1901811315613d125760008081fd5b613d1a613aa9565b89830135613d2781613bac565b81526040613d36848201613bc1565b8b830152606080850135613d4981613bdd565b83830152928401359289841115613d6257600091508182fd5b613d708f8d86880101613c1d565b908301525085525050918601918601613ce2565b5098975050505050505050565b60005b83811015613dac578181015183820152602001613d94565b50506000910152565b60008151808452613dcd816020860160208601613d91565b601f01601f19169290920160200192915050565b602081526000610ac76020830184613db5565b8060608101831015610aca57600080fd5b60008083601f840112613e1757600080fd5b5081356001600160401b03811115613e2e57600080fd5b602083019150836020828501011115613e4657600080fd5b9250929050565b60008083601f840112613e5f57600080fd5b5081356001600160401b03811115613e7657600080fd5b6020830191508360208260051b8501011115613e4657600080fd5b60008060008060008060008060e0898b031215613ead57600080fd5b613eb78a8a613df4565b975060608901356001600160401b0380821115613ed357600080fd5b613edf8c838d01613e05565b909950975060808b0135915080821115613ef857600080fd5b613f048c838d01613e4d565b909750955060a08b0135915080821115613f1d57600080fd5b50613f2a8b828c01613e4d565b999c989b50969995989497949560c00135949350505050565b600080600060808486031215613f5857600080fd5b613f628585613df4565b925060608401356001600160401b03811115613f7d57600080fd5b613f8986828701613e05565b9497909650939450505050565b60008060408385031215613fa957600080fd5b613fb283613bc1565b9150613fc060208401613bc1565b90509250929050565b634e487b7160e01b600052602160045260246000fd5b60048110613fef57613fef613fc9565b9052565b60208101610aca8284613fdf565b8035613bd881613bac565b63ffffffff8116811461051357600080fd5b60006060828403121561403057600080fd5b614038613ad1565b823561404381613bac565b815260208301356140538161400c565b6020820152604083013561406681613bac565b60408201529392505050565b60006020828403121561408457600080fd5b81356001600160401b0381111561409a57600080fd5b820160a081850312156139d157600080fd5b803560ff81168114613bd857600080fd5b6000602082840312156140cf57600080fd5b610ac7826140ac565b60008151808452602080850194506020840160005b838110156141125781516001600160a01b0316875295820195908201906001016140ed565b509495945050505050565b60208152600082518051602084015260ff602082015116604084015260ff604082015116606084015260608101511515608084015250602083015160c060a084015261416c60e08401826140d8565b90506040840151601f198483030160c085015261418982826140d8565b95945050505050565b600080604083850312156141a557600080fd5b6141ae83613bc1565b946020939093013593505050565b600060a082840312156141ce57600080fd5b6141d6613af3565b9050813581526141e860208301613bc1565b60208201526141f960408301613bc1565b604082015261420a60608301613bc1565b606082015261421b60808301613bc1565b608082015292915050565b600082601f83011261423757600080fd5b81356020614247613c3c83613b89565b82815260059290921b8401810191818101908684111561426657600080fd5b8286015b848110156143605780356001600160401b038082111561428a5760008081fd5b9088019060a0828b03601f19018113156142a45760008081fd5b6142ac613af3565b87840135838111156142be5760008081fd5b6142cc8d8a83880101613c1d565b825250604080850135848111156142e35760008081fd5b6142f18e8b83890101613c1d565b8a840152506060808601358581111561430a5760008081fd5b6143188f8c838a0101613c1d565b8385015250608091508186013581840152508285013592508383111561433e5760008081fd5b61434c8d8a85880101613c1d565b90820152865250505091830191830161426a565b509695505050505050565b6000610140828403121561437e57600080fd5b614386613b15565b905061439283836141bc565b815260a08201356001600160401b03808211156143ae57600080fd5b6143ba85838601613c1d565b602084015260c08401359150808211156143d357600080fd5b6143df85838601613c1d565b60408401526143f060e08501614001565b6060840152610100840135608084015261012084013591508082111561441557600080fd5b5061442284828501614226565b60a08301525092915050565b60008060008060006060868803121561444657600080fd5b85356001600160401b038082111561445d57600080fd5b61446989838a0161436b565b9650602088013591508082111561447f57600080fd5b61448b89838a01613e4d565b909650945060408801359150808211156144a457600080fd5b506144b188828901613e4d565b969995985093965092949392505050565b600082601f8301126144d357600080fd5b813560206144e3613c3c83613b89565b82815260059290921b8401810191818101908684111561450257600080fd5b8286015b848110156143605780356001600160401b038111156145255760008081fd5b6145338986838b010161436b565b845250918301918301614506565b600082601f83011261455257600080fd5b81356020614562613c3c83613b89565b82815260059290921b8401810191818101908684111561458157600080fd5b8286015b848110156143605780356001600160401b03808211156145a457600080fd5b818901915089603f8301126145b857600080fd5b858201356145c8613c3c82613b89565b81815260059190911b830160400190878101908c8311156145e857600080fd5b604085015b838110156146215780358581111561460457600080fd5b6146138f6040838a0101613c1d565b8452509189019189016145ed565b50875250505092840192508301614585565b600082601f83011261464457600080fd5b81356020614654613c3c83613b89565b8083825260208201915060208460051b87010193508684111561467657600080fd5b602086015b84811015614360578035835291830191830161467b565b600082601f8301126146a357600080fd5b813560206146b3613c3c83613b89565b82815260059290921b840181019181810190868411156146d257600080fd5b8286015b848110156143605780356001600160401b03808211156146f65760008081fd5b9088019060a0828b03601f19018113156147105760008081fd5b614718613af3565b614723888501613bc1565b8152604080850135848111156147395760008081fd5b6147478e8b838901016144c2565b8a84015250606080860135858111156147605760008081fd5b61476e8f8c838a0101614541565b83850152506080915081860135858111156147895760008081fd5b6147978f8c838a0101614633565b91840191909152509190930135908301525083529183019183016146d6565b600080604083850312156147c957600080fd5b6001600160401b03833511156147de57600080fd5b6147eb8484358501614692565b91506001600160401b036020840135111561480557600080fd5b6020830135830184601f82011261481b57600080fd5b614828613c3c8235613b89565b81358082526020808301929160051b84010187101561484657600080fd5b602083015b6020843560051b8501018110156149ef576001600160401b038135111561487157600080fd5b87603f82358601011261488357600080fd5b614896613c3c6020833587010135613b89565b81358501602081810135808452908301929160059190911b016040018a10156148be57600080fd5b604083358701015b83358701602081013560051b016040018110156149df576001600160401b03813511156148f257600080fd5b833587018135016040818d03603f1901121561490d57600080fd5b614915613b37565b604082013581526001600160401b036060830135111561493457600080fd5b8c605f60608401358401011261494957600080fd5b6040606083013583010135614960613c3c82613b89565b808282526020820191508f60608460051b606088013588010101111561498557600080fd5b6060808601358601015b60608460051b6060880135880101018110156149bf576149af813561400c565b803583526020928301920161498f565b5080602085015250505080855250506020830192506020810190506148c6565b508452506020928301920161484b565b508093505050509250929050565b600060208284031215614a0f57600080fd5b610ac782613bc1565b602081526001600160a01b0382511660208201526020820151151560408201526001600160401b036040830151166060820152600060608301516080808401526133c160a0840182613db5565b600060208284031215614a7757600080fd5b81356139d181613bac565b600082601f830112614a9357600080fd5b81356020614aa3613c3c83613b89565b8083825260208201915060208460051b870101935086841115614ac557600080fd5b602086015b84811015614360578035614add81613bac565b8352918301918301614aca565b60006020808385031215614afd57600080fd5b82356001600160401b0380821115614b1457600080fd5b818501915085601f830112614b2857600080fd5b8135614b36613c3c82613b89565b81815260059190911b83018401908481019088831115614b5557600080fd5b8585015b83811015613d8457803585811115614b7057600080fd5b860160c0818c03601f19011215614b875760008081fd5b614b8f613b15565b8882013581526040614ba28184016140ac565b8a8301526060614bb38185016140ac565b8284015260809150614bc6828501613beb565b9083015260a08381013589811115614bde5760008081fd5b614bec8f8d83880101614a82565b838501525060c0840135915088821115614c065760008081fd5b614c148e8c84870101614a82565b9083015250845250918601918601614b59565b80356001600160e01b0381168114613bd857600080fd5b600082601f830112614c4f57600080fd5b81356020614c5f613c3c83613b89565b82815260069290921b84018101918181019086841115614c7e57600080fd5b8286015b848110156143605760408189031215614c9b5760008081fd5b614ca3613b37565b614cac82613bc1565b8152614cb9858301614c27565b81860152835291830191604001614c82565b600082601f830112614cdc57600080fd5b81356020614cec613c3c83613b89565b82815260059290921b84018101918181019086841115614d0b57600080fd5b8286015b848110156143605780356001600160401b0380821115614d2f5760008081fd5b9088019060a0828b03601f1901811315614d495760008081fd5b614d51613af3565b614d5c888501613bc1565b815260408085013584811115614d725760008081fd5b614d808e8b83890101613c1d565b8a8401525060609350614d94848601613bc1565b908201526080614da5858201613bc1565b93820193909352920135908201528352918301918301614d0f565b600082601f830112614dd157600080fd5b81356020614de1613c3c83613b89565b82815260069290921b84018101918181019086841115614e0057600080fd5b8286015b848110156143605760408189031215614e1d5760008081fd5b614e25613b37565b813581528482013585820152835291830191604001614e04565b60006020808385031215614e5257600080fd5b82356001600160401b0380821115614e6957600080fd5b9084019060608287031215614e7d57600080fd5b614e85613ad1565b823582811115614e9457600080fd5b83016040818903811315614ea757600080fd5b614eaf613b37565b823585811115614ebe57600080fd5b8301601f81018b13614ecf57600080fd5b8035614edd613c3c82613b89565b81815260069190911b8201890190898101908d831115614efc57600080fd5b928a01925b82841015614f4c5785848f031215614f195760008081fd5b614f21613b37565b8435614f2c81613bac565b8152614f39858d01614c27565b818d0152825292850192908a0190614f01565b845250505082870135915084821115614f6457600080fd5b614f708a838501614c3e565b81880152835250508284013582811115614f8957600080fd5b614f9588828601614ccb565b85830152506040830135935081841115614fae57600080fd5b614fba87858501614dc0565b60408201529695505050505050565b600082825180855260208086019550808260051b84010181860160005b8481101561505a57601f19868403018952815160a06001600160401b0380835116865286830151828888015261501e83880182613db5565b60408581015184169089015260608086015190931692880192909252506080928301519290950191909152509783019790830190600101614fe6565b5090979650505050505050565b6000604080835261507b6040840186614fc9565b83810360208581019190915285518083528682019282019060005b818110156150bb57845180518452840151848401529383019391850191600101615096565b509098975050505050505050565b634e487b7160e01b600052603260045260246000fd5b805160408084528151848201819052600092602091908201906060870190855b8181101561513657835180516001600160a01b031684528501516001600160e01b03168584015292840192918501916001016150ff565b50508583015187820388850152805180835290840192506000918401905b8083101561518f57835180516001600160401b031683528501516001600160e01b031685830152928401926001929092019190850190615154565b50979650505050505050565b602081526000610ac760208301846150df565b6000602082840312156151c057600080fd5b81516139d181613bdd565b600181811c908216806151df57607f821691505b6020821081036151ff57634e487b7160e01b600052602260045260246000fd5b50919050565b6000808354615213816151cb565b6001828116801561522b57600181146152405761526f565b60ff198416875282151583028701945061526f565b8760005260208060002060005b858110156152665781548a82015290840190820161524d565b50505082870194505b50929695505050505050565b60008154615288816151cb565b8085526020600183811680156152a557600181146152bf576152ed565b60ff1985168884015283151560051b8801830195506152ed565b866000528260002060005b858110156152e55781548a82018601529083019084016152ca565b890184019650505b505050505092915050565b60408152600061530b6040830185613db5565b8281036020840152614189818561527b565b634e487b7160e01b600052601160045260246000fd5b6001600160401b038181168382160190808211156153535761535361531d565b5092915050565b60408152600061536d6040830185614fc9565b828103602084015261418981856150df565b60006020828403121561539157600080fd5b81356001600160401b038111156153a757600080fd5b6133c184828501614692565b81810381811115610aca57610aca61531d565b634e487b7160e01b600052601260045260246000fd5b60006001600160401b03808416806153f6576153f66153c6565b92169190910692915050565b8082028115828204841417610aca57610aca61531d565b80518252600060206001600160401b0381840151168185015260408084015160a0604087015261544c60a0870182613db5565b9050606085015186820360608801526154658282613db5565b608087810151898303918a01919091528051808352908601935060009250908501905b8083101561518f57835180516001600160a01b0316835286015186830152928501926001929092019190840190615488565b602081526000610ac76020830184615419565b6080815260006154e06080830187615419565b61ffff9590951660208301525060408101929092526001600160a01b0316606090910152919050565b60008060006060848603121561551e57600080fd5b835161552981613bdd565b60208501519093506001600160401b0381111561554557600080fd5b8401601f8101861361555657600080fd5b8051615564613c3c82613bf6565b81815287602083850101111561557957600080fd5b61558a826020830160208601613d91565b809450505050604084015190509250925092565b6000602082840312156155b057600080fd5b81516139d18161400c565b601f821115611272576000816000526020600020601f850160051c810160208610156155e45750805b601f850160051c820191505b81811015615603578281556001016155f0565b505050505050565b81516001600160401b0381111561562457615624613a93565b6156388161563284546151cb565b846155bb565b602080601f83116001811461566d57600084156156555750858301515b600019600386901b1c1916600185901b178555615603565b600085815260208120601f198616915b8281101561569c5788860151825594840194600190910190840161567d565b50858210156156ba5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60208152600082546001600160a01b038116602084015260ff8160a01c16151560408401526001600160401b038160a81c16606084015250608080830152610ac760a083016001850161527b565b80820180821115610aca57610aca61531d565b60ff8181168382160190811115610aca57610aca61531d565b8183823760009101908152919050565b828152606082602083013760800192915050565b60006001600160401b0380841680615782576157826153c6565b92169190910492915050565b6000602082840312156157a057600080fd5b81356139d18161400c565b6000808335601e198436030181126157c257600080fd5b8301803591506001600160401b038211156157dc57600080fd5b602001915036819003821315613e4657600080fd5b602081016006831061580557615805613fc9565b91905290565b60ff81811683821602908116908181146153535761535361531d565b600060a0820160ff881683526020878185015260a0604085015281875480845260c0860191508860005282600020935060005b8181101561587f5784546001600160a01b03168352600194850194928401920161585a565b50508481036060860152865180825290820192508187019060005b818110156158bf5782516001600160a01b03168552938301939183019160010161589a565b50505060ff851660808501525090505b9695505050505050565b60006001600160401b038086168352808516602084015250606060408301526141896060830184613db5565b8281526040602082015260006133c16040830184613db5565b6001600160401b03848116825283166020820152606081016133c16040830184613fdf565b8481526159536020820185613fdf565b6080604082015260006159696080830185613db5565b905082606083015295945050505050565b60006020828403121561598c57600080fd5b81516139d181613bac565b60208152600082516101008060208501526159b6610120850183613db5565b915060208501516159d260408601826001600160401b03169052565b5060408501516001600160a01b038116606086015250606085015160808501526080850151615a0c60a08601826001600160a01b03169052565b5060a0850151601f19808685030160c0870152615a298483613db5565b935060c08701519150808685030160e0870152615a468483613db5565b935060e08701519150808685030183870152506158cf8382613db5565b600060208284031215615a7557600080fd5b5051919050565b600082825180855260208086019550808260051b84010181860160005b8481101561505a57601f19868403018952815160a08151818652615abf82870182613db5565b9150508582015185820387870152615ad78282613db5565b91505060408083015186830382880152615af18382613db5565b92505050606080830151818701525060808083015192508582038187015250615b1a8183613db5565b9a86019a9450505090830190600101615a99565b602081526000610ac76020830184615a7c565b60008282518085526020808601955060208260051b8401016020860160005b8481101561505a57601f19868403018952615b7c838351613db5565b98840198925090830190600101615b60565b60008151808452602080850194506020840160005b8381101561411257815163ffffffff1687529582019590820190600101615ba3565b60608152600084518051606084015260208101516001600160401b0380821660808601528060408401511660a08601528060608401511660c08601528060808401511660e0860152505050602085015161014080610100850152615c2d6101a0850183613db5565b91506040870151605f198086850301610120870152615c4c8483613db5565b935060608901519150615c69838701836001600160a01b03169052565b608089015161016087015260a0890151925080868503016101808701525050615c928282615a7c565b9150508281036020840152615ca78186615b41565b905082810360408401526158cf8185615b8e56fea164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CanOnlySelfCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"reportOnRamp\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"configOnRamp\",\"type\":\"bytes\"}],\"name\":\"CommitOnRampMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"actual\",\"type\":\"bytes32\"}],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ExecutionError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"ForkedChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enumMultiOCR3Base.InvalidConfigErrorType\",\"name\":\"errorType\",\"type\":\"uint8\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"got\",\"type\":\"uint256\"}],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"name\":\"InvalidInterval\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"newLimit\",\"type\":\"uint256\"}],\"name\":\"InvalidManualExecutionGasLimit\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"tokenIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"oldLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenGasOverride\",\"type\":\"uint256\"}],\"name\":\"InvalidManualExecutionTokenGasOverride\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"messageDestChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidMessageDestChainSelector\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"newState\",\"type\":\"uint8\"}],\"name\":\"InvalidNewState\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidOnRampUpdate\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRoot\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LeavesCannotBeEmpty\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"ManualExecutionGasAmountCountMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ManualExecutionGasLimitMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"ManualExecutionNotYetEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"errorReason\",\"type\":\"bytes\"}],\"name\":\"MessageValidationError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonUniqueSignatures\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"notPool\",\"type\":\"address\"}],\"name\":\"NotACompatiblePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OracleCannotBeZeroAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ReceiverError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountReleased\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePre\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePost\",\"type\":\"uint256\"}],\"name\":\"ReleaseOrMintBalanceMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"name\":\"RootAlreadyCommitted\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"RootNotCommitted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignatureVerificationDisabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignaturesOutOfRegistration\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"reportSourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"messageSourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainSelectorMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"StaleCommitReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"StaticConfigCannotBeChanged\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"TokenDataMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"TokenHandlingError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnexpectedTokenData\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"WrongMessageLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WrongNumberOfSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroChainSelectorNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"AlreadyAttempted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"indexed\":false,\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"}],\"name\":\"CommitReportAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"DynamicConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"messageHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"name\":\"ExecutionStateChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"RootRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"SkippedAlreadyExecutedMessage\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SkippedReportExecution\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"sourceConfig\",\"type\":\"tuple\"}],\"name\":\"SourceChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainSelectorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"}],\"name\":\"StaticConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigUpdates\",\"type\":\"tuple[]\"}],\"name\":\"applySourceChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"destTokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structClient.Any2EVMMessage\",\"name\":\"\",\"type\":\"tuple\"}],\"name\":\"ccipReceive\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"rawVs\",\"type\":\"bytes32\"}],\"name\":\"commit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"execute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"destTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"destGasAmount\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.Any2EVMTokenTransfer[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"bytes[]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[]\"},{\"internalType\":\"uint32[]\",\"name\":\"tokenGasOverrides\",\"type\":\"uint32[]\"}],\"name\":\"executeSingleMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"getExecutionState\",\"outputs\":[{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLatestPriceSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"getMerkleRoot\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"getSourceChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"latestConfigDetails\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"n\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"}],\"internalType\":\"structMultiOCR3Base.ConfigInfo\",\"name\":\"configInfo\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfig\",\"name\":\"ocrConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"destTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"destGasAmount\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.Any2EVMTokenTransfer[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage[]\",\"name\":\"messages\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[][]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[][]\"},{\"internalType\":\"bytes32[]\",\"name\":\"proofs\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"proofFlagBits\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.ExecutionReportSingleChain[]\",\"name\":\"reports\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"receiverExecutionGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint32[]\",\"name\":\"tokenGasOverrides\",\"type\":\"uint32[]\"}],\"internalType\":\"structOffRamp.GasLimitOverride[][]\",\"name\":\"gasLimitOverrides\",\"type\":\"tuple[][]\"}],\"name\":\"manuallyExecute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"setDynamicConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfigArgs[]\",\"name\":\"ocrConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"setOCR3Configs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x6101206040523480156200001257600080fd5b50604051620067b2380380620067b2833981016040819052620000359162000806565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf81620001fa565b5050466080525060208301516001600160a01b03161580620000ec575060408301516001600160a01b0316155b8062000103575060608301516001600160a01b0316155b1562000122576040516342bcdf7f60e11b815260040160405180910390fd5b82516001600160401b03166000036200014e5760405163c656089560e01b815260040160405180910390fd5b82516001600160401b0390811660a052602080850180516001600160a01b0390811660c05260408088018051831660e0526060808a01805185166101005283518b519098168852945184169587019590955251821690850152905116908201527f683eb52ee924eb817377cfa8f41f238f4bb7a877da5267869dfffbad85f564d89060800160405180910390a1620001e682620002a5565b620001f1816200036d565b50505062000b8d565b336001600160a01b03821603620002545760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b0316620002ce576040516342bcdf7f60e11b815260040160405180910390fd5b805160048054602080850180516001600160a01b039586166001600160c01b03199094168417600160a01b63ffffffff928316021790945560408087018051600580546001600160a01b031916918916919091179055815194855291519094169183019190915251909216908201527fa1c15688cb2c24508e158f6942b9276c6f3028a85e1af8cf3fff0c3ff3d5fc8d9060600160405180910390a150565b60005b8151811015620005ba57600082828151811062000391576200039162000943565b60200260200101519050600081602001519050806001600160401b0316600003620003cf5760405163c656089560e01b815260040160405180910390fd5b81516001600160a01b0316620003f8576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160401b03811660009081526006602052604090206060830151600182018054620004269062000959565b905060000362000489578154600160a81b600160e81b031916600160a81b1782556040516001600160401b03841681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1620004c8565b8154600160a81b90046001600160401b0316600114620004c857604051632105803760e11b81526001600160401b038416600482015260240162000083565b80511580620004fe5750604080516000602082015201604051602081830303815290604052805190602001208180519060200120145b156200051d576040516342bcdf7f60e11b815260040160405180910390fd5b600182016200052d8282620009ea565b50604080850151835486516001600160a01b03166001600160a01b0319921515600160a01b02929092166001600160a81b031990911617178355516001600160401b038416907f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b90620005a290859062000ab6565b60405180910390a25050505080600101905062000370565b5050565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b0381118282101715620005f957620005f9620005be565b60405290565b604051601f8201601f191681016001600160401b03811182821017156200062a576200062a620005be565b604052919050565b80516001600160401b03811681146200064a57600080fd5b919050565b6001600160a01b03811681146200066557600080fd5b50565b6000601f83601f8401126200067c57600080fd5b825160206001600160401b03808311156200069b576200069b620005be565b8260051b620006ac838201620005ff565b9384528681018301938381019089861115620006c757600080fd5b84890192505b85831015620007f957825184811115620006e75760008081fd5b89016080601f19828d038101821315620007015760008081fd5b6200070b620005d4565b888401516200071a816200064f565b815260406200072b85820162000632565b8a8301526060808601518015158114620007455760008081fd5b838301529385015193898511156200075d5760008081fd5b84860195508f603f8701126200077557600094508485fd5b8a8601519450898511156200078e576200078e620005be565b6200079f8b858f88011601620005ff565b93508484528f82868801011115620007b75760008081fd5b60005b85811015620007d7578681018301518582018d01528b01620007ba565b5060009484018b019490945250918201528352509184019190840190620006cd565b9998505050505050505050565b60008060008385036101008112156200081e57600080fd5b60808112156200082d57600080fd5b62000837620005d4565b620008428662000632565b8152602086015162000854816200064f565b6020820152604086015162000869816200064f565b604082015260608601516200087e816200064f565b606082810191909152909450607f19820112156200089b57600080fd5b50604051606081016001600160401b038082118383101715620008c257620008c2620005be565b8160405260808701519150620008d8826200064f565b90825260a08601519063ffffffff82168214620008f457600080fd5b81602084015260c087015191506200090c826200064f565b6040830182905260e0870151929450808311156200092957600080fd5b5050620009398682870162000668565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b600181811c908216806200096e57607f821691505b6020821081036200098f57634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115620009e5576000816000526020600020601f850160051c81016020861015620009c05750805b601f850160051c820191505b81811015620009e157828155600101620009cc565b5050505b505050565b81516001600160401b0381111562000a065762000a06620005be565b62000a1e8162000a17845462000959565b8462000995565b602080601f83116001811462000a56576000841562000a3d5750858301515b600019600386901b1c1916600185901b178555620009e1565b600085815260208120601f198616915b8281101562000a875788860151825594840194600190910190840162000a66565b508582101562000aa65787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b602080825282546001600160a01b0381168383015260a081901c60ff161515604084015260a81c6001600160401b0316606083015260808083015260018084018054600093929190849062000b0b8162000959565b8060a089015260c0600183166000811462000b2f576001811462000b4c5762000b7e565b60ff19841660c08b015260c083151560051b8b0101945062000b7e565b85600052602060002060005b8481101562000b755781548c820185015290880190890162000b58565b8b0160c0019550505b50929998505050505050505050565b60805160a05160c05160e05161010051615baf62000c036000396000818161022c01526129ca0152600081816101fd0152612c8f0152600081816101ce01528181610552015281816106ff015261238b01526000818161019f01526125ca015260008181611abc0152611aef0152615baf6000f3fe608060405234801561001057600080fd5b50600436106101515760003560e01c80636f9e320f116100cd578063c673e58411610081578063e9d68a8e11610066578063e9d68a8e146104bc578063f2fde38b146104dc578063f716f99f146104ef57600080fd5b8063c673e58414610458578063ccd37ba31461047857600080fd5b806379ba5097116100b257806379ba50971461042757806385572ffb1461042f5780638da5cb5b1461043d57600080fd5b80636f9e320f146103825780637437ff9f1461039557600080fd5b8063311cd513116101245780635e36480c116101095780635e36480c1461033c5780635e7bb0081461035c57806360987c201461036f57600080fd5b8063311cd5131461030e5780633f4b04aa1461032157600080fd5b806304666f9c1461015657806306285c691461016b578063181f5a77146102b25780632d04ab76146102fb575b600080fd5b610169610164366004613bb7565b610502565b005b61025c60408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160401b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316815250905090565b6040516102a9919081516001600160401b031681526020808301516001600160a01b0390811691830191909152604080840151821690830152606092830151169181019190915260800190565b60405180910390f35b6102ee6040518060400160405280601181526020017f4f666652616d7020312e362e302d64657600000000000000000000000000000081525081565b6040516102a99190613d25565b610169610309366004613dd5565b610516565b61016961031c366004613e87565b610a12565b6009546040516001600160401b0390911681526020016102a9565b61034f61034a366004613eda565b610a7b565b6040516102a99190613f37565b61016961036a3660046144a0565b610ad0565b61016961037d3660046146e4565b610d5f565b610169610390366004614778565b61103f565b6103f1604080516060810182526000808252602082018190529181019190915250604080516060810182526004546001600160a01b038082168352600160a01b90910463ffffffff166020830152600554169181019190915290565b6040805182516001600160a01b03908116825260208085015163ffffffff169083015292820151909216908201526060016102a9565b610169611050565b6101696101513660046147ca565b6000546040516001600160a01b0390911681526020016102a9565b61046b610466366004614815565b611101565b6040516102a99190614875565b6104ae6104863660046148ea565b6001600160401b03919091166000908152600860209081526040808320938352929052205490565b6040519081526020016102a9565b6104cf6104ca366004614914565b61125f565b6040516102a9919061492f565b6101696104ea36600461497c565b61136b565b6101696104fd366004614a01565b61137c565b61050a6113be565b6105138161141a565b50565b600061052487890189614d56565b602081015151909150156105b6576020810151604080830151905162ccd5af60e81b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169263ccd5af009261058592600401614f7e565b60006040518083038186803b15801561059d57600080fd5b505afa1580156105b1573d6000803e3d6000fd5b505050505b805151511515806105cc57508051602001515115155b156106985760095460208a0135906001600160401b0380831691161015610670576009805467ffffffffffffffff19166001600160401b038316179055600480548351604051633937306f60e01b81526001600160a01b0390921692633937306f926106399291016150b2565b600060405180830381600087803b15801561065357600080fd5b505af1158015610667573d6000803e3d6000fd5b50505050610696565b81602001515160000361069657604051632261116760e01b815260040160405180910390fd5b505b60005b816020015151811015610953576000826020015182815181106106c0576106c0614fe0565b60209081029190910101518051604051632cbc26bb60e01b815267ffffffffffffffff60801b608083901b166004820152919250906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632cbc26bb90602401602060405180830381865afa158015610746573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061076a91906150c5565b1561079857604051637edeb53960e11b81526001600160401b03821660048201526024015b60405180910390fd5b60006107a38261166d565b9050806001016040516107b6919061511c565b6040518091039020836020015180519060200120146107f35782602001518160010160405163b80d8fa960e01b815260040161078f92919061520f565b60408301518154600160a81b90046001600160401b039081169116141580610834575082606001516001600160401b031683604001516001600160401b0316115b1561087957825160408085015160608601519151636af0786b60e11b81526001600160401b03938416600482015290831660248201529116604482015260640161078f565b60808301518061089c5760405163504570e360e01b815260040160405180910390fd5b83516001600160401b03166000908152600860209081526040808320848452909152902054156108f45783516040516332cf0cbf60e01b81526001600160401b0390911660048201526024810182905260440161078f565b606084015161090490600161524a565b825467ffffffffffffffff60a81b1916600160a81b6001600160401b0392831602179092559251166000908152600860209081526040808320948352939052919091204290555060010161069b565b50602081015181516040517f35c02761bcd3ef995c6a601a1981f4ed3934dcbe5041e24e286c89f5531d17e49261098b929091615271565b60405180910390a1610a0760008a8a8a8a8a8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808e0282810182019093528d82529093508d92508c9182918501908490808284376000920191909152508b92506116b9915050565b505050505050505050565b610a52610a2182840184615296565b6040805160008082526020820190925290610a4c565b6060815260200190600190039081610a375790505b506119b2565b604080516000808252602082019092529050610a756001858585858660006116b9565b50505050565b6000610a89600160046152ca565b6002610a966080856152f3565b6001600160401b0316610aa99190615319565b610ab38585611a74565b901c166003811115610ac757610ac7613f0d565b90505b92915050565b610ad8611ab9565b815181518114610afb576040516320f8fd5960e21b815260040160405180910390fd5b60005b81811015610d4f576000848281518110610b1a57610b1a614fe0565b60200260200101519050600081602001515190506000858481518110610b4257610b42614fe0565b6020026020010151905080518214610b6d576040516320f8fd5960e21b815260040160405180910390fd5b60005b82811015610d40576000828281518110610b8c57610b8c614fe0565b6020026020010151600001519050600085602001518381518110610bb257610bb2614fe0565b6020026020010151905081600014610c06578060800151821015610c06578551815151604051633a98d46360e11b81526001600160401b03909216600483015260248201526044810183905260640161078f565b838381518110610c1857610c18614fe0565b602002602001015160200151518160a001515114610c6557805180516060909101516040516370a193fd60e01b815260048101929092526001600160401b0316602482015260440161078f565b60005b8160a0015151811015610d32576000858581518110610c8957610c89614fe0565b6020026020010151602001518281518110610ca657610ca6614fe0565b602002602001015163ffffffff16905080600014610d295760008360a001518381518110610cd657610cd6614fe0565b60200260200101516040015163ffffffff16905080821015610d27578351516040516348e617b360e01b8152600481019190915260248101849052604481018290526064810183905260840161078f565b505b50600101610c68565b505050806001019050610b70565b50505050806001019050610afe565b50610d5a83836119b2565b505050565b333014610d7f576040516306e34e6560e31b815260040160405180910390fd5b6040805160008082526020820190925281610dbc565b6040805180820190915260008082526020820152815260200190600190039081610d955790505b5060a08701515190915015610df257610def8660a001518760200151886060015189600001516020015189898989611b21565b90505b6040805160a081018252875151815287516020908101516001600160401b031681830152808901518351600094840192610e2d929101613d25565b60408051601f19818403018152918152908252898101516020830152018390526005549091506001600160a01b03168015610f08576040516308d450a160e01b81526001600160a01b038216906308d450a190610e8e9085906004016153d1565b600060405180830381600087803b158015610ea857600080fd5b505af1925050508015610eb9575060015b610f08573d808015610ee7576040519150601f19603f3d011682016040523d82523d6000602084013e610eec565b606091505b50806040516309c2532560e01b815260040161078f9190613d25565b604088015151158015610f1d57506080880151155b80610f34575060608801516001600160a01b03163b155b80610f5b57506060880151610f59906001600160a01b03166385572ffb60e01b611cd2565b155b15610f6857505050611038565b87516020908101516001600160401b03166000908152600690915260408082205460808b015160608c01519251633cf9798360e01b815284936001600160a01b0390931692633cf9798392610fc692899261138892916004016153e4565b6000604051808303816000875af1158015610fe5573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261100d9190810190615420565b50915091508161103257806040516302a35ba360e21b815260040161078f9190613d25565b50505050505b5050505050565b6110476113be565b61051381611cee565b6001546001600160a01b031633146110aa5760405162461bcd60e51b815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e657200000000000000000000604482015260640161078f565b60008054336001600160a01b0319808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6111446040805160e081019091526000606082018181526080830182905260a0830182905260c08301919091528190815260200160608152602001606081525090565b60ff808316600090815260026020818152604092839020835160e081018552815460608201908152600183015480881660808401526101008104881660a0840152620100009004909616151560c0820152948552918201805484518184028101840190955280855292938583019390928301828280156111ed57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116111cf575b505050505081526020016003820180548060200260200160405190810160405280929190818152602001828054801561124f57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611231575b5050505050815250509050919050565b60408051608080820183526000808352602080840182905283850182905260608085018190526001600160401b03878116845260068352928690208651948501875280546001600160a01b0381168652600160a01b810460ff16151593860193909352600160a81b9092049092169483019490945260018401805493949293918401916112eb906150e2565b80601f0160208091040260200160405190810160405280929190818152602001828054611317906150e2565b801561124f5780601f106113395761010080835404028352916020019161124f565b820191906000526020600020905b81548152906001019060200180831161134757505050919092525091949350505050565b6113736113be565b61051381611dcd565b6113846113be565b60005b81518110156113ba576113b28282815181106113a5576113a5614fe0565b6020026020010151611e76565b600101611387565b5050565b6000546001600160a01b031633146114185760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640161078f565b565b60005b81518110156113ba57600082828151811061143a5761143a614fe0565b60200260200101519050600081602001519050806001600160401b03166000036114775760405163c656089560e01b815260040160405180910390fd5b81516001600160a01b031661149f576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160401b038116600090815260066020526040902060608301516001820180546114cb906150e2565b905060000361152d57815467ffffffffffffffff60a81b1916600160a81b1782556040516001600160401b03841681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a161156a565b8154600160a81b90046001600160401b031660011461156a57604051632105803760e11b81526001600160401b038416600482015260240161078f565b8051158061159f5750604080516000602082015201604051602081830303815290604052805190602001208180519060200120145b156115bd576040516342bcdf7f60e11b815260040160405180910390fd5b600182016115cb8282615505565b50604080850151835486516001600160a01b03166001600160a01b0319921515600160a01b02929092167fffffffffffffffffffffff00000000000000000000000000000000000000000090911617178355516001600160401b038416907f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b906116569085906155c4565b60405180910390a25050505080600101905061141d565b6001600160401b03811660009081526006602052604081208054600160a01b900460ff16610aca5760405163ed053c5960e01b81526001600160401b038416600482015260240161078f565b60ff878116600090815260026020908152604080832081516080810183528154815260019091015480861693820193909352610100830485169181019190915262010000909104909216151560608301528735906117188760a4615612565b9050826060015115611760578451611731906020615319565b865161173e906020615319565b6117499060a0615612565b6117539190615612565b61175d9082615612565b90505b36811461178957604051638e1192e160e01b81526004810182905236602482015260440161078f565b50815181146117b85781516040516324f7d61360e21b815260048101919091526024810182905260440161078f565b6117c0611ab9565b60ff808a166000908152600360209081526040808320338452825280832081518083019092528054808616835293949193909284019161010090910416600281111561180e5761180e613f0d565b600281111561181f5761181f613f0d565b905250905060028160200151600281111561183c5761183c613f0d565b1480156118905750600260008b60ff1660ff168152602001908152602001600020600301816000015160ff168154811061187857611878614fe0565b6000918252602090912001546001600160a01b031633145b6118ad57604051631b41e11d60e31b815260040160405180910390fd5b5081606001511561195d5760208201516118c8906001615625565b60ff168551146118eb576040516371253a2560e01b815260040160405180910390fd5b835185511461190d5760405163a75d88af60e01b815260040160405180910390fd5b6000878760405161191f92919061563e565b604051908190038120611936918b9060200161564e565b60405160208183030381529060405280519060200120905061195b8a828888886121a0565b505b6040805182815260208a8101356001600160401b03169082015260ff8b16917f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef0910160405180910390a2505050505050505050565b81516000036119d35760405162bf199760e01b815260040160405180910390fd5b80516040805160008082526020820190925291159181611a16565b6040805180820190915260008152606060208201528152602001906001900390816119ee5790505b50905060005b845181101561103857611a6c858281518110611a3a57611a3a614fe0565b602002602001015184611a6657858381518110611a5957611a59614fe0565b602002602001015161235d565b8361235d565b600101611a1c565b6001600160401b038216600090815260076020526040812081611a98608085615662565b6001600160401b031681526020810191909152604001600020549392505050565b467f00000000000000000000000000000000000000000000000000000000000000001461141857604051630f01ce8560e01b81527f0000000000000000000000000000000000000000000000000000000000000000600482015246602482015260440161078f565b606088516001600160401b03811115611b3c57611b3c6139d7565b604051908082528060200260200182016040528015611b8157816020015b6040805180820190915260008082526020820152815260200190600190039081611b5a5790505b509050811560005b8a51811015611cc45781611c2157848482818110611ba957611ba9614fe0565b9050602002016020810190611bbe9190615688565b63ffffffff1615611c2157848482818110611bdb57611bdb614fe0565b9050602002016020810190611bf09190615688565b8b8281518110611c0257611c02614fe0565b60200260200101516040019063ffffffff16908163ffffffff16815250505b611c9f8b8281518110611c3657611c36614fe0565b60200260200101518b8b8b8b8b87818110611c5357611c53614fe0565b9050602002810190611c6591906156a3565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612c5492505050565b838281518110611cb157611cb1614fe0565b6020908102919091010152600101611b89565b505098975050505050505050565b6000611cdd83612f34565b8015610ac75750610ac78383612f7f565b80516001600160a01b0316611d16576040516342bcdf7f60e11b815260040160405180910390fd5b805160048054602080850180516001600160a01b039586167fffffffffffffffff0000000000000000000000000000000000000000000000009094168417600160a01b63ffffffff928316021790945560408087018051600580546001600160a01b031916918916919091179055815194855291519094169183019190915251909216908201527fa1c15688cb2c24508e158f6942b9276c6f3028a85e1af8cf3fff0c3ff3d5fc8d9060600160405180910390a150565b336001600160a01b03821603611e255760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161078f565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b806040015160ff16600003611ea1576000604051631b3fab5160e11b815260040161078f91906156e9565b60208082015160ff80821660009081526002909352604083206001810154929390928392169003611ef2576060840151600182018054911515620100000262ff000019909216919091179055611f2e565b6060840151600182015460ff6201000090910416151590151514611f2e576040516321fd80df60e21b815260ff8416600482015260240161078f565b60a084015180516101001015611f5a576001604051631b3fab5160e11b815260040161078f91906156e9565b8051600003611f7f576005604051631b3fab5160e11b815260040161078f91906156e9565b611fe58484600301805480602002602001604051908101604052809291908181526020018280548015611fdb57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611fbd575b5050505050613021565b846060015115612115576120538484600201805480602002602001604051908101604052809291908181526020018280548015611fdb576020028201919060005260206000209081546001600160a01b03168152600190910190602001808311611fbd575050505050613021565b60808501518051610100101561207f576002604051631b3fab5160e11b815260040161078f91906156e9565b604086015161208f906003615703565b60ff168151116120b5576003604051631b3fab5160e11b815260040161078f91906156e9565b8151815110156120db576001604051631b3fab5160e11b815260040161078f91906156e9565b805160018401805461ff00191661010060ff841602179055612106906002860190602084019061395d565b506121138582600161308a565b505b6121218482600261308a565b8051612136906003850190602084019061395d565b5060408581015160018401805460ff191660ff8316179055865180855560a088015192517fab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f5479361218f9389939260028a0192919061571f565b60405180910390a1611038846131e5565b8251600090815b818110156123535760006001888684602081106121c6576121c6614fe0565b6121d391901a601b615625565b8985815181106121e5576121e5614fe0565b60200260200101518986815181106121ff576121ff614fe0565b60200260200101516040516000815260200160405260405161223d949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa15801561225f573d6000803e3d6000fd5b505060408051601f1981015160ff808e166000908152600360209081528582206001600160a01b038516835281528582208587019096528554808416865293975090955092939284019161010090041660028111156122c0576122c0613f0d565b60028111156122d1576122d1613f0d565b90525090506001816020015160028111156122ee576122ee613f0d565b1461230c57604051636518c33d60e11b815260040160405180910390fd5b8051600160ff9091161b85161561233657604051633d9ef1f160e21b815260040160405180910390fd5b806000015160ff166001901b8517945050508060010190506121a7565b5050505050505050565b81518151604051632cbc26bb60e01b8152608083901b67ffffffffffffffff60801b166004820152901515907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632cbc26bb90602401602060405180830381865afa1580156123da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123fe91906150c5565b1561246f57801561242d57604051637edeb53960e11b81526001600160401b038316600482015260240161078f565b6040516001600160401b03831681527faab522ed53d887e56ed53dd37398a01aeef6a58e0fa77c2173beb9512d8949339060200160405180910390a150505050565b600061247a8361166d565b6001018054612488906150e2565b80601f01602080910402602001604051908101604052809291908181526020018280546124b4906150e2565b80156125015780601f106124d657610100808354040283529160200191612501565b820191906000526020600020905b8154815290600101906020018083116124e457829003601f168201915b505050602088015151929350505060008190036125305760405162bf199760e01b815260040160405180910390fd5b8560400151518114612555576040516357e0e08360e01b815260040160405180910390fd5b6000816001600160401b0381111561256f5761256f6139d7565b604051908082528060200260200182016040528015612598578160200160208202803683370190505b50905060005b8281101561273c576000886020015182815181106125be576125be614fe0565b602002602001015190507f00000000000000000000000000000000000000000000000000000000000000006001600160401b03168160000151604001516001600160401b0316146126355780516040908101519051631c21951160e11b81526001600160401b03909116600482015260240161078f565b866001600160401b03168160000151602001516001600160401b03161461268957805160200151604051636c95f1eb60e01b81526001600160401b03808a166004830152909116602482015260440161078f565b612716817f2425b0b9f9054c76ff151b0a175b18f37a4a4e82013a72e9f15c9caa095ed21f83600001516020015184600001516040015189805190602001206040516020016126fb94939291909384526001600160401b03928316602085015291166040830152606082015260800190565b6040516020818303038152906040528051906020012061323c565b83838151811061272857612728614fe0565b60209081029190910101525060010161259e565b50600061275386838a606001518b60800151613344565b90508060000361278157604051633ee8bd3f60e11b81526001600160401b038716600482015260240161078f565b60005b83811015610a075760005a905060008a6020015183815181106127a9576127a9614fe0565b6020026020010151905060006127c78a836000015160600151610a7b565b905060008160038111156127dd576127dd613f0d565b14806127fa575060038160038111156127f8576127f8613f0d565b145b61285057815160600151604080516001600160401b03808e16825290921660208301527f3b575419319662b2a6f5e2467d84521517a3382b908eb3d557bb3fdb0c50e23c910160405180910390a1505050612c4c565b6060891561292f578b858151811061286a5761286a614fe0565b6020908102919091018101510151600454909150600090600160a01b900463ffffffff1661289888426152ca565b11905080806128b8575060038360038111156128b6576128b6613f0d565b145b6128e0576040516354e7e43160e11b81526001600160401b038d16600482015260240161078f565b8c86815181106128f2576128f2614fe0565b602002602001015160000151600014612929578c868151811061291757612917614fe0565b60209081029190910101515160808501525b5061299b565b600082600381111561294357612943613f0d565b1461299b57825160600151604080516001600160401b03808f16825290921660208301527f3ef2a99c550a751d4b0b261268f05a803dfb049ab43616a1ffb388f61fe65120910160405180910390a150505050612c4c565b8251608001516001600160401b031615612a745760008260038111156129c3576129c3613f0d565b03612a74577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e0e03cae8c85600001516080015186602001516040518463ffffffff1660e01b8152600401612a24939291906157d1565b6020604051808303816000875af1158015612a43573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a6791906150c5565b612a745750505050612c4c565b60008d604001518681518110612a8c57612a8c614fe0565b6020026020010151905080518460a001515114612ad657835160600151604051631cfe6d8b60e01b81526001600160401b03808f166004830152909116602482015260440161078f565b612aea8c8560000151606001516001613381565b600080612af8868486613426565b91509150612b0f8e87600001516060015184613381565b8c15612b66576003826003811115612b2957612b29613f0d565b03612b66576000856003811115612b4257612b42613f0d565b14612b6657855151604051632b11b8d960e01b815261078f919083906004016157fd565b6002826003811115612b7a57612b7a613f0d565b14612bbf576003826003811115612b9357612b93613f0d565b14612bbf578d866000015160600151836040516349362d1f60e11b815260040161078f93929190615816565b8560000151600001518660000151606001516001600160401b03168f6001600160401b03167f05665fe9ad095383d018353f4cbcba77e84db27dd215081bbf7cdf9ae6fbe48b8d8c81518110612c1757612c17614fe0565b602002602001015186865a612c2c908f6152ca565b604051612c3c949392919061583b565b60405180910390a4505050505050505b600101612784565b6040805180820190915260008082526020820152602086015160405163bbe4f6db60e01b81526001600160a01b0380831660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063bbe4f6db90602401602060405180830381865afa158015612cd8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cfc9190615872565b90506001600160a01b0381161580612d2b5750612d296001600160a01b03821663aff2afbf60e01b611cd2565b155b15612d545760405163ae9b4ce960e01b81526001600160a01b038216600482015260240161078f565b600080612d6c88858c6040015163ffffffff166134da565b915091506000806000612e1f6040518061010001604052808e81526020018c6001600160401b031681526020018d6001600160a01b031681526020018f608001518152602001896001600160a01b031681526020018f6000015181526020018f6060015181526020018b815250604051602401612de9919061588f565b60408051601f198184030181529190526020810180516001600160e01b0316633907753760e01b179052878661138860846135bd565b92509250925082612e45578160405163e1cd550960e01b815260040161078f9190613d25565b8151602014612e74578151604051631e3be00960e21b815260206004820152602481019190915260440161078f565b600082806020019051810190612e8a919061595b565b9050866001600160a01b03168c6001600160a01b031614612f06576000612ebb8d8a612eb6868a6152ca565b6134da565b50905086811080612ed5575081612ed288836152ca565b14155b15612f045760405163a966e21f60e01b815260048101839052602481018890526044810182905260640161078f565b505b604080518082019091526001600160a01b039098168852602088015250949550505050505095945050505050565b6000612f47826301ffc9a760e01b612f7f565b8015610aca5750612f78827fffffffff00000000000000000000000000000000000000000000000000000000612f7f565b1592915050565b6040517fffffffff0000000000000000000000000000000000000000000000000000000082166024820152600090819060440160408051601f19818403018152919052602080820180516001600160e01b03166301ffc9a760e01b178152825192935060009283928392909183918a617530fa92503d9150600051905082801561300a575060208210155b80156130165750600081115b979650505050505050565b60005b8151811015610d5a5760ff83166000908152600360205260408120835190919084908490811061305657613056614fe0565b6020908102919091018101516001600160a01b03168252810191909152604001600020805461ffff19169055600101613024565b60005b8251811015610a755760008382815181106130aa576130aa614fe0565b60200260200101519050600060028111156130c7576130c7613f0d565b60ff80871660009081526003602090815260408083206001600160a01b0387168452909152902054610100900416600281111561310657613106613f0d565b14613127576004604051631b3fab5160e11b815260040161078f91906156e9565b6001600160a01b03811661314e5760405163d6c62c9b60e01b815260040160405180910390fd5b60405180604001604052808360ff16815260200184600281111561317457613174613f0d565b905260ff80871660009081526003602090815260408083206001600160a01b0387168452825290912083518154931660ff198416811782559184015190929091839161ffff1916176101008360028111156131d1576131d1613f0d565b02179055509050505080600101905061308d565b60ff81166105135760ff8082166000908152600260205260409020600101546201000090041661322857604051631e8ed32560e21b815260040160405180910390fd5b6009805467ffffffffffffffff1916905550565b8151805160608085015190830151608080870151940151604051600095869588956132a095919490939192916020019485526001600160a01b039390931660208501526001600160401b039182166040850152606084015216608082015260a00190565b604051602081830303815290604052805190602001208560200151805190602001208660400151805190602001208760a001516040516020016132e39190615a15565b60408051601f198184030181528282528051602091820120908301979097528101949094526060840192909252608083015260a082015260c081019190915260e0015b60405160208183030381529060405280519060200120905092915050565b600080613352858585613697565b6001600160401b038716600090815260086020908152604080832093835292905220549150505b949350505050565b600060026133906080856152f3565b6001600160401b03166133a39190615319565b905060006133b18585611a74565b9050816133c0600160046152ca565b901b1916818360038111156133d7576133d7613f0d565b6001600160401b03871660009081526007602052604081209190921b92909217918291613405608088615662565b6001600160401b031681526020810191909152604001600020555050505050565b604051630304c3e160e51b815260009060609030906360987c209061345390889088908890600401615aac565b600060405180830381600087803b15801561346d57600080fd5b505af192505050801561347e575060015b6134bd573d8080156134ac576040519150601f19603f3d011682016040523d82523d6000602084013e6134b1565b606091505b506003925090506134d2565b50506040805160208101909152600081526002905b935093915050565b600080600080600061353b8860405160240161350591906001600160a01b0391909116815260200190565b60408051601f198184030181529190526020810180516001600160e01b03166370a0823160e01b179052888861138860846135bd565b92509250925082613561578160405163e1cd550960e01b815260040161078f9190613d25565b6020825114613590578151604051631e3be00960e21b815260206004820152602481019190915260440161078f565b818060200190518101906135a4919061595b565b6135ae82886152ca565b94509450505050935093915050565b6000606060008361ffff166001600160401b038111156135df576135df6139d7565b6040519080825280601f01601f191660200182016040528015613609576020820181803683370190505b509150863b6136235763030ed58f60e21b60005260046000fd5b5a8581101561363d57632be8ca8b60e21b60005260046000fd5b859003604081048103871061365d576337c3be2960e01b60005260046000fd5b505a6000808a5160208c0160008c8cf193505a900390503d848111156136805750835b808352806000602085013e50955095509592505050565b82518251600091908183036136bf57604051630469ac9960e21b815260040160405180910390fd5b61010182118015906136d357506101018111155b6136f0576040516309bde33960e01b815260040160405180910390fd5b6000198282010161010081111561371a576040516309bde33960e01b815260040160405180910390fd5b80600003613747578660008151811061373557613735614fe0565b60200260200101519350505050613915565b6000816001600160401b03811115613761576137616139d7565b60405190808252806020026020018201604052801561378a578160200160208202803683370190505b50905060008080805b858110156138b45760006001821b8b8116036137ee57888510156137d7578c5160018601958e9181106137c8576137c8614fe0565b60200260200101519050613810565b85516001850194879181106137c8576137c8614fe0565b8b5160018401938d91811061380557613805614fe0565b602002602001015190505b600089861015613840578d5160018701968f91811061383157613831614fe0565b60200260200101519050613862565b865160018601958891811061385757613857614fe0565b602002602001015190505b82851115613883576040516309bde33960e01b815260040160405180910390fd5b61388d828261391c565b87848151811061389f5761389f614fe0565b60209081029190910101525050600101613793565b5060018503821480156138c657508683145b80156138d157508581145b6138ee576040516309bde33960e01b815260040160405180910390fd5b83600186038151811061390357613903614fe0565b60200260200101519750505050505050505b9392505050565b60008183106139345761392f828461393a565b610ac7565b610ac783835b604080516001602082015290810183905260608101829052600090608001613326565b8280548282559060005260206000209081019282156139b2579160200282015b828111156139b257825182546001600160a01b0319166001600160a01b0390911617825560209092019160019091019061397d565b506139be9291506139c2565b5090565b5b808211156139be57600081556001016139c3565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b0381118282101715613a0f57613a0f6139d7565b60405290565b60405160a081016001600160401b0381118282101715613a0f57613a0f6139d7565b60405160c081016001600160401b0381118282101715613a0f57613a0f6139d7565b604080519081016001600160401b0381118282101715613a0f57613a0f6139d7565b604051606081016001600160401b0381118282101715613a0f57613a0f6139d7565b604051601f8201601f191681016001600160401b0381118282101715613ac557613ac56139d7565b604052919050565b60006001600160401b03821115613ae657613ae66139d7565b5060051b60200190565b6001600160a01b038116811461051357600080fd5b80356001600160401b0381168114613b1c57600080fd5b919050565b801515811461051357600080fd5b8035613b1c81613b21565b60006001600160401b03821115613b5357613b536139d7565b50601f01601f191660200190565b600082601f830112613b7257600080fd5b8135613b85613b8082613b3a565b613a9d565b818152846020838601011115613b9a57600080fd5b816020850160208301376000918101602001919091529392505050565b60006020808385031215613bca57600080fd5b82356001600160401b0380821115613be157600080fd5b818501915085601f830112613bf557600080fd5b8135613c03613b8082613acd565b81815260059190911b83018401908481019088831115613c2257600080fd5b8585015b83811015613cc857803585811115613c3e5760008081fd5b86016080818c03601f1901811315613c565760008081fd5b613c5e6139ed565b89830135613c6b81613af0565b81526040613c7a848201613b05565b8b830152606080850135613c8d81613b21565b83830152928401359289841115613ca657600091508182fd5b613cb48f8d86880101613b61565b908301525085525050918601918601613c26565b5098975050505050505050565b60005b83811015613cf0578181015183820152602001613cd8565b50506000910152565b60008151808452613d11816020860160208601613cd5565b601f01601f19169290920160200192915050565b602081526000610ac76020830184613cf9565b8060608101831015610aca57600080fd5b60008083601f840112613d5b57600080fd5b5081356001600160401b03811115613d7257600080fd5b602083019150836020828501011115613d8a57600080fd5b9250929050565b60008083601f840112613da357600080fd5b5081356001600160401b03811115613dba57600080fd5b6020830191508360208260051b8501011115613d8a57600080fd5b60008060008060008060008060e0898b031215613df157600080fd5b613dfb8a8a613d38565b975060608901356001600160401b0380821115613e1757600080fd5b613e238c838d01613d49565b909950975060808b0135915080821115613e3c57600080fd5b613e488c838d01613d91565b909750955060a08b0135915080821115613e6157600080fd5b50613e6e8b828c01613d91565b999c989b50969995989497949560c00135949350505050565b600080600060808486031215613e9c57600080fd5b613ea68585613d38565b925060608401356001600160401b03811115613ec157600080fd5b613ecd86828701613d49565b9497909650939450505050565b60008060408385031215613eed57600080fd5b613ef683613b05565b9150613f0460208401613b05565b90509250929050565b634e487b7160e01b600052602160045260246000fd5b60048110613f3357613f33613f0d565b9052565b60208101610aca8284613f23565b600060a08284031215613f5757600080fd5b613f5f613a15565b905081358152613f7160208301613b05565b6020820152613f8260408301613b05565b6040820152613f9360608301613b05565b6060820152613fa460808301613b05565b608082015292915050565b8035613b1c81613af0565b803563ffffffff81168114613b1c57600080fd5b600082601f830112613fdf57600080fd5b81356020613fef613b8083613acd565b82815260059290921b8401810191818101908684111561400e57600080fd5b8286015b848110156140de5780356001600160401b03808211156140325760008081fd5b9088019060a0828b03601f190181131561404c5760008081fd5b614054613a15565b87840135838111156140665760008081fd5b6140748d8a83880101613b61565b82525060408085013561408681613af0565b828a01526060614097868201613fba565b828401526080915081860135858111156140b15760008081fd5b6140bf8f8c838a0101613b61565b9184019190915250919093013590830152508352918301918301614012565b509695505050505050565b600061014082840312156140fc57600080fd5b614104613a37565b90506141108383613f45565b815260a08201356001600160401b038082111561412c57600080fd5b61413885838601613b61565b602084015260c084013591508082111561415157600080fd5b61415d85838601613b61565b604084015261416e60e08501613faf565b6060840152610100840135608084015261012084013591508082111561419357600080fd5b506141a084828501613fce565b60a08301525092915050565b600082601f8301126141bd57600080fd5b813560206141cd613b8083613acd565b82815260059290921b840181019181810190868411156141ec57600080fd5b8286015b848110156140de5780356001600160401b0381111561420f5760008081fd5b61421d8986838b01016140e9565b8452509183019183016141f0565b600082601f83011261423c57600080fd5b8135602061424c613b8083613acd565b82815260059290921b8401810191818101908684111561426b57600080fd5b8286015b848110156140de5780356001600160401b038082111561428e57600080fd5b818901915089603f8301126142a257600080fd5b858201356142b2613b8082613acd565b81815260059190911b830160400190878101908c8311156142d257600080fd5b604085015b8381101561430b578035858111156142ee57600080fd5b6142fd8f6040838a0101613b61565b8452509189019189016142d7565b5087525050509284019250830161426f565b600082601f83011261432e57600080fd5b8135602061433e613b8083613acd565b8083825260208201915060208460051b87010193508684111561436057600080fd5b602086015b848110156140de5780358352918301918301614365565b600082601f83011261438d57600080fd5b8135602061439d613b8083613acd565b82815260059290921b840181019181810190868411156143bc57600080fd5b8286015b848110156140de5780356001600160401b03808211156143e05760008081fd5b9088019060a0828b03601f19018113156143fa5760008081fd5b614402613a15565b61440d888501613b05565b8152604080850135848111156144235760008081fd5b6144318e8b838901016141ac565b8a840152506060808601358581111561444a5760008081fd5b6144588f8c838a010161422b565b83850152506080915081860135858111156144735760008081fd5b6144818f8c838a010161431d565b91840191909152509190930135908301525083529183019183016143c0565b600080604083850312156144b357600080fd5b6001600160401b03833511156144c857600080fd5b6144d5848435850161437c565b91506001600160401b03602084013511156144ef57600080fd5b6020830135830184601f82011261450557600080fd5b614512613b808235613acd565b81358082526020808301929160051b84010187101561453057600080fd5b602083015b6020843560051b8501018110156146d6576001600160401b038135111561455b57600080fd5b87603f82358601011261456d57600080fd5b614580613b806020833587010135613acd565b81358501602081810135808452908301929160059190911b016040018a10156145a857600080fd5b604083358701015b83358701602081013560051b016040018110156146c6576001600160401b03813511156145dc57600080fd5b833587018135016040818d03603f190112156145f757600080fd5b6145ff613a59565b604082013581526001600160401b036060830135111561461e57600080fd5b8c605f60608401358401011261463357600080fd5b604060608301358301013561464a613b8082613acd565b808282526020820191508f60608460051b606088013588010101111561466f57600080fd5b6060808601358601015b60608460051b6060880135880101018110156146a65761469881613fba565b835260209283019201614679565b5080602085015250505080855250506020830192506020810190506145b0565b5084525060209283019201614535565b508093505050509250929050565b6000806000806000606086880312156146fc57600080fd5b85356001600160401b038082111561471357600080fd5b61471f89838a016140e9565b9650602088013591508082111561473557600080fd5b61474189838a01613d91565b9096509450604088013591508082111561475a57600080fd5b5061476788828901613d91565b969995985093965092949392505050565b60006060828403121561478a57600080fd5b614792613a7b565b823561479d81613af0565b81526147ab60208401613fba565b602082015260408301356147be81613af0565b60408201529392505050565b6000602082840312156147dc57600080fd5b81356001600160401b038111156147f257600080fd5b820160a0818503121561391557600080fd5b803560ff81168114613b1c57600080fd5b60006020828403121561482757600080fd5b610ac782614804565b60008151808452602080850194506020840160005b8381101561486a5781516001600160a01b031687529582019590820190600101614845565b509495945050505050565b60208152600082518051602084015260ff602082015116604084015260ff604082015116606084015260608101511515608084015250602083015160c060a08401526148c460e0840182614830565b90506040840151601f198483030160c08501526148e18282614830565b95945050505050565b600080604083850312156148fd57600080fd5b61490683613b05565b946020939093013593505050565b60006020828403121561492657600080fd5b610ac782613b05565b602081526001600160a01b0382511660208201526020820151151560408201526001600160401b0360408301511660608201526000606083015160808084015261337960a0840182613cf9565b60006020828403121561498e57600080fd5b813561391581613af0565b600082601f8301126149aa57600080fd5b813560206149ba613b8083613acd565b8083825260208201915060208460051b8701019350868411156149dc57600080fd5b602086015b848110156140de5780356149f481613af0565b83529183019183016149e1565b60006020808385031215614a1457600080fd5b82356001600160401b0380821115614a2b57600080fd5b818501915085601f830112614a3f57600080fd5b8135614a4d613b8082613acd565b81815260059190911b83018401908481019088831115614a6c57600080fd5b8585015b83811015613cc857803585811115614a8757600080fd5b860160c0818c03601f19011215614a9e5760008081fd5b614aa6613a37565b8882013581526040614ab9818401614804565b8a8301526060614aca818501614804565b8284015260809150614add828501613b2f565b9083015260a08381013589811115614af55760008081fd5b614b038f8d83880101614999565b838501525060c0840135915088821115614b1d5760008081fd5b614b2b8e8c84870101614999565b9083015250845250918601918601614a70565b80356001600160e01b0381168114613b1c57600080fd5b600082601f830112614b6657600080fd5b81356020614b76613b8083613acd565b82815260069290921b84018101918181019086841115614b9557600080fd5b8286015b848110156140de5760408189031215614bb25760008081fd5b614bba613a59565b614bc382613b05565b8152614bd0858301614b3e565b81860152835291830191604001614b99565b600082601f830112614bf357600080fd5b81356020614c03613b8083613acd565b82815260059290921b84018101918181019086841115614c2257600080fd5b8286015b848110156140de5780356001600160401b0380821115614c465760008081fd5b9088019060a0828b03601f1901811315614c605760008081fd5b614c68613a15565b614c73888501613b05565b815260408085013584811115614c895760008081fd5b614c978e8b83890101613b61565b8a8401525060609350614cab848601613b05565b908201526080614cbc858201613b05565b93820193909352920135908201528352918301918301614c26565b600082601f830112614ce857600080fd5b81356020614cf8613b8083613acd565b82815260069290921b84018101918181019086841115614d1757600080fd5b8286015b848110156140de5760408189031215614d345760008081fd5b614d3c613a59565b813581528482013585820152835291830191604001614d1b565b60006020808385031215614d6957600080fd5b82356001600160401b0380821115614d8057600080fd5b9084019060608287031215614d9457600080fd5b614d9c613a7b565b823582811115614dab57600080fd5b83016040818903811315614dbe57600080fd5b614dc6613a59565b823585811115614dd557600080fd5b8301601f81018b13614de657600080fd5b8035614df4613b8082613acd565b81815260069190911b8201890190898101908d831115614e1357600080fd5b928a01925b82841015614e635785848f031215614e305760008081fd5b614e38613a59565b8435614e4381613af0565b8152614e50858d01614b3e565b818d0152825292850192908a0190614e18565b845250505082870135915084821115614e7b57600080fd5b614e878a838501614b55565b81880152835250508284013582811115614ea057600080fd5b614eac88828601614be2565b85830152506040830135935081841115614ec557600080fd5b614ed187858501614cd7565b60408201529695505050505050565b600082825180855260208086019550808260051b84010181860160005b84811015614f7157601f19868403018952815160a06001600160401b03808351168652868301518288880152614f3583880182613cf9565b60408581015184169089015260608086015190931692880192909252506080928301519290950191909152509783019790830190600101614efd565b5090979650505050505050565b60006040808352614f926040840186614ee0565b83810360208581019190915285518083528682019282019060005b81811015614fd257845180518452840151848401529383019391850191600101614fad565b509098975050505050505050565b634e487b7160e01b600052603260045260246000fd5b805160408084528151848201819052600092602091908201906060870190855b8181101561504d57835180516001600160a01b031684528501516001600160e01b0316858401529284019291850191600101615016565b50508583015187820388850152805180835290840192506000918401905b808310156150a657835180516001600160401b031683528501516001600160e01b03168583015292840192600192909201919085019061506b565b50979650505050505050565b602081526000610ac76020830184614ff6565b6000602082840312156150d757600080fd5b815161391581613b21565b600181811c908216806150f657607f821691505b60208210810361511657634e487b7160e01b600052602260045260246000fd5b50919050565b600080835461512a816150e2565b60018281168015615142576001811461515757615186565b60ff1984168752821515830287019450615186565b8760005260208060002060005b8581101561517d5781548a820152908401908201615164565b50505082870194505b50929695505050505050565b6000815461519f816150e2565b8085526020600183811680156151bc57600181146151d657615204565b60ff1985168884015283151560051b880183019550615204565b866000528260002060005b858110156151fc5781548a82018601529083019084016151e1565b890184019650505b505050505092915050565b6040815260006152226040830185613cf9565b82810360208401526148e18185615192565b634e487b7160e01b600052601160045260246000fd5b6001600160401b0381811683821601908082111561526a5761526a615234565b5092915050565b6040815260006152846040830185614ee0565b82810360208401526148e18185614ff6565b6000602082840312156152a857600080fd5b81356001600160401b038111156152be57600080fd5b6133798482850161437c565b81810381811115610aca57610aca615234565b634e487b7160e01b600052601260045260246000fd5b60006001600160401b038084168061530d5761530d6152dd565b92169190910692915050565b8082028115828204841417610aca57610aca615234565b80518252600060206001600160401b0381840151168185015260408084015160a0604087015261536360a0870182613cf9565b90506060850151868203606088015261537c8282613cf9565b608087810151898303918a01919091528051808352908601935060009250908501905b808310156150a657835180516001600160a01b031683528601518683015292850192600192909201919084019061539f565b602081526000610ac76020830184615330565b6080815260006153f76080830187615330565b61ffff9590951660208301525060408101929092526001600160a01b0316606090910152919050565b60008060006060848603121561543557600080fd5b835161544081613b21565b60208501519093506001600160401b0381111561545c57600080fd5b8401601f8101861361546d57600080fd5b805161547b613b8082613b3a565b81815287602083850101111561549057600080fd5b6154a1826020830160208601613cd5565b809450505050604084015190509250925092565b601f821115610d5a576000816000526020600020601f850160051c810160208610156154de5750805b601f850160051c820191505b818110156154fd578281556001016154ea565b505050505050565b81516001600160401b0381111561551e5761551e6139d7565b6155328161552c84546150e2565b846154b5565b602080601f831160018114615567576000841561554f5750858301515b600019600386901b1c1916600185901b1785556154fd565b600085815260208120601f198616915b8281101561559657888601518255948401946001909101908401615577565b50858210156155b45787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60208152600082546001600160a01b038116602084015260ff8160a01c16151560408401526001600160401b038160a81c16606084015250608080830152610ac760a0830160018501615192565b80820180821115610aca57610aca615234565b60ff8181168382160190811115610aca57610aca615234565b8183823760009101908152919050565b828152606082602083013760800192915050565b60006001600160401b038084168061567c5761567c6152dd565b92169190910492915050565b60006020828403121561569a57600080fd5b610ac782613fba565b6000808335601e198436030181126156ba57600080fd5b8301803591506001600160401b038211156156d457600080fd5b602001915036819003821315613d8a57600080fd5b60208101600683106156fd576156fd613f0d565b91905290565b60ff818116838216029081169081811461526a5761526a615234565b600060a0820160ff881683526020878185015260a0604085015281875480845260c0860191508860005282600020935060005b818110156157775784546001600160a01b031683526001948501949284019201615752565b50508481036060860152865180825290820192508187019060005b818110156157b75782516001600160a01b031685529383019391830191600101615792565b50505060ff851660808501525090505b9695505050505050565b60006001600160401b038086168352808516602084015250606060408301526148e16060830184613cf9565b8281526040602082015260006133796040830184613cf9565b6001600160401b03848116825283166020820152606081016133796040830184613f23565b84815261584b6020820185613f23565b6080604082015260006158616080830185613cf9565b905082606083015295945050505050565b60006020828403121561588457600080fd5b815161391581613af0565b60208152600082516101008060208501526158ae610120850183613cf9565b915060208501516158ca60408601826001600160401b03169052565b5060408501516001600160a01b03811660608601525060608501516080850152608085015161590460a08601826001600160a01b03169052565b5060a0850151601f19808685030160c08701526159218483613cf9565b935060c08701519150808685030160e087015261593e8483613cf9565b935060e08701519150808685030183870152506157c78382613cf9565b60006020828403121561596d57600080fd5b5051919050565b600082825180855260208086019550808260051b84010181860160005b84811015614f7157601f19868403018952815160a081518186526159b782870182613cf9565b9150506001600160a01b03868301511686860152604063ffffffff81840151168187015250606080830151868303828801526159f38382613cf9565b6080948501519790940196909652505098840198925090830190600101615991565b602081526000610ac76020830184615974565b60008282518085526020808601955060208260051b8401016020860160005b84811015614f7157601f19868403018952615a63838351613cf9565b98840198925090830190600101615a47565b60008151808452602080850194506020840160005b8381101561486a57815163ffffffff1687529582019590820190600101615a8a565b60608152600084518051606084015260208101516001600160401b0380821660808601528060408401511660a08601528060608401511660c08601528060808401511660e0860152505050602085015161014080610100850152615b146101a0850183613cf9565b91506040870151605f198086850301610120870152615b338483613cf9565b935060608901519150615b50838701836001600160a01b03169052565b608089015161016087015260a0890151925080868503016101808701525050615b798282615974565b9150508281036020840152615b8e8186615a28565b905082810360408401526157c78185615a7556fea164736f6c6343000818000a", } var OffRampABI = OffRampMetaData.ABI diff --git a/core/gethwrappers/ccip/generated/onramp/onramp.go b/core/gethwrappers/ccip/generated/onramp/onramp.go index 1663e49f2e..25dd768201 100644 --- a/core/gethwrappers/ccip/generated/onramp/onramp.go +++ b/core/gethwrappers/ccip/generated/onramp/onramp.go @@ -51,7 +51,15 @@ type InternalEVM2AnyRampMessage struct { ExtraArgs []byte FeeToken common.Address FeeTokenAmount *big.Int - TokenAmounts []InternalRampTokenAmount + TokenAmounts []InternalEVM2AnyTokenTransfer +} + +type InternalEVM2AnyTokenTransfer struct { + SourcePoolAddress common.Address + DestTokenAddress []byte + ExtraData []byte + Amount *big.Int + DestExecData []byte } type InternalRampMessageHeader struct { @@ -62,14 +70,6 @@ type InternalRampMessageHeader struct { Nonce uint64 } -type InternalRampTokenAmount struct { - SourcePoolAddress []byte - DestTokenAddress []byte - ExtraData []byte - Amount *big.Int - DestExecData []byte -} - type OnRampAllowListConfigArgs struct { DestChainSelector uint64 AllowListEnabled bool @@ -98,8 +98,8 @@ type OnRampStaticConfig struct { } var OnRampMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"reentrancyGuardEntered\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CannotSendZeroTokens\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GetSupportedTokensFunctionalityRemovedCheckAdminRegistry\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidAllowListRequest\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidDestChainConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeCalledByRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrAllowlistAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrancyGuardReentrantCall\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RouterMustSetOriginalSender\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"UnsupportedToken\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"name\":\"AllowListAdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"senders\",\"type\":\"address[]\"}],\"name\":\"AllowListSendersAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"senders\",\"type\":\"address[]\"}],\"name\":\"AllowListSendersRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"CCIPMessageSent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOnRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"reentrancyGuardEntered\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"allowListEnabled\",\"type\":\"bool\"}],\"name\":\"DestChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"feeValueJuels\",\"type\":\"uint256\"}],\"name\":\"FeePaid\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeeTokenWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"allowListEnabled\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"addedAllowlistedSenders\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"removedAllowlistedSenders\",\"type\":\"address[]\"}],\"internalType\":\"structOnRamp.AllowListConfigArgs[]\",\"name\":\"allowListConfigArgsItems\",\"type\":\"tuple[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyDestChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"}],\"name\":\"forwardFromRouter\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getAllowedSendersList\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getDestChainConfig\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"allowListEnabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"reentrancyGuardEntered\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getExpectedNextSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"getFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"},{\"internalType\":\"contractIERC20\",\"name\":\"sourceToken\",\"type\":\"address\"}],\"name\":\"getPoolBySourceToken\",\"outputs\":[{\"internalType\":\"contractIPoolV1\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"contractIRouter\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"name\":\"getSupportedTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"reentrancyGuardEntered\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"setDynamicConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"withdrawFeeTokens\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x6101006040523480156200001257600080fd5b506040516200428d3803806200428d83398101604081905262000035916200073f565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf8162000186565b505083516001600160401b031615905080620000e6575060208301516001600160a01b0316155b80620000fd575060408301516001600160a01b0316155b8062000114575060608301516001600160a01b0316155b1562000133576040516306b7c75960e31b815260040160405180910390fd5b82516001600160401b031660805260208301516001600160a01b0390811660a0526040840151811660c05260608401511660e052620001728262000231565b6200017d81620003e0565b50505062000840565b336001600160a01b03821603620001e05760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b0316158062000254575060608101516001600160a01b0316155b8062000261575080602001515b1562000280576040516306b7c75960e31b815260040160405180910390fd5b8051600280546020808501511515600160a01b026001600160a81b03199092166001600160a01b039485161791909117909155604080840151600380549185166001600160a01b0319928316179055606080860151600480549187169184169190911790556080808701516005805491881691909416179092558251808301845291516001600160401b0316825260a05185169382019390935260c05184168183015260e05190931691830191909152517fc7372d2d886367d7bb1b0e0708a5436f2c91d6963de210eb2dc1ec2ecd6d21f191620003d591849082516001600160401b031681526020808401516001600160a01b03908116828401526040858101518216818501526060958601518216868501528451821660808086019190915292850151151560a0850152840151811660c084015293830151841660e0830152909101519091166101008201526101200190565b60405180910390a150565b60005b81518110156200051f5760008282815181106200040457620004046200082a565b6020026020010151905060008383815181106200042557620004256200082a565b6020026020010151600001519050806001600160401b03166000036200046a5760405163c35aa79d60e01b81526001600160401b038216600482015260240162000083565b6001600160401b03818116600081815260066020908152604091829020868201518154600160481b600160e81b0319811669010000000000000000006001600160a01b03909316928302908117808555865192891691909816178152928301526801000000000000000090940460ff161515918101919091527fd5ad72bc37dc7a80a8b9b9df20500046fd7341adb1be2258a540466fdd7dcef59060600160405180910390a2505050806001019050620003e3565b5050565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b03811182821017156200055e576200055e62000523565b60405290565b604051601f8201601f191681016001600160401b03811182821017156200058f576200058f62000523565b604052919050565b80516001600160401b0381168114620005af57600080fd5b919050565b6001600160a01b0381168114620005ca57600080fd5b50565b600060a08284031215620005e057600080fd5b60405160a081016001600160401b038111828210171562000605576200060562000523565b806040525080915082516200061a81620005b4565b8152602083015180151581146200063057600080fd5b602082015260408301516200064581620005b4565b604082015260608301516200065a81620005b4565b606082015260808301516200066f81620005b4565b6080919091015292915050565b600082601f8301126200068e57600080fd5b815160206001600160401b03821115620006ac57620006ac62000523565b620006bc818360051b0162000564565b82815260069290921b84018101918181019086841115620006dc57600080fd5b8286015b84811015620007345760408189031215620006fb5760008081fd5b6200070562000539565b620007108262000597565b8152848201516200072181620005b4565b81860152835291830191604001620006e0565b509695505050505050565b60008060008385036101408112156200075757600080fd5b60808112156200076657600080fd5b50604051608081016001600160401b0380821183831017156200078d576200078d62000523565b816040526200079c8762000597565b835260208701519150620007b082620005b4565b81602084015260408701519150620007c882620005b4565b81604084015260608701519150620007e082620005b4565b816060840152829550620007f88860808901620005cd565b94506101208701519250808311156200081057600080fd5b505062000820868287016200067c565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b60805160a05160c05160e0516139d4620008b96000396000818161022c01528181610cfd0152611c290152600081816101f0015281816116240152611c020152600081816101b4015281816106080152611bd80152600081816101840152818161114b0152818161173f0152611bb401526139d46000f3fe608060405234801561001057600080fd5b50600436106101365760003560e01c80637437ff9f116100b2578063972b461211610081578063df0aa9e911610066578063df0aa9e914610557578063f2fde38b1461056a578063fbca3b741461057d57600080fd5b8063972b4612146104ea578063d77d5ed01461050a57600080fd5b80637437ff9f146103ee57806379ba5097146104985780638da5cb5b146104a05780639041be3d146104be57600080fd5b806327e936f1116101095780633a019940116100ee5780633a0199401461030f57806348a98aa4146103175780636def4ce71461034f57600080fd5b806327e936f1146102e957806334adf494146102fc57600080fd5b80630242cf601461013b57806306285c6914610150578063181f5a771461027f57806320487ded146102c8575b600080fd5b61014e610149366004612830565b610590565b005b61026960408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16815250905090565b60405161027691906128f3565b60405180910390f35b6102bb6040518060400160405280601081526020017f4f6e52616d7020312e362e302d6465760000000000000000000000000000000081525081565b60405161027691906129b8565b6102db6102d63660046129e3565b6105a4565b604051908152602001610276565b61014e6102f7366004612a51565b61075d565b61014e61030a366004612ae9565b61076e565b61014e610a8a565b61032a610325366004612b5e565b610cb5565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610276565b6103b261035d366004612b97565b67ffffffffffffffff9081166000908152600660205260409020549081169168010000000000000000820460ff16916901000000000000000000900473ffffffffffffffffffffffffffffffffffffffff1690565b6040805167ffffffffffffffff9094168452911515602084015273ffffffffffffffffffffffffffffffffffffffff1690820152606001610276565b61048b6040805160a081018252600080825260208201819052918101829052606081018290526080810191909152506040805160a08101825260025473ffffffffffffffffffffffffffffffffffffffff80821683527401000000000000000000000000000000000000000090910460ff161515602083015260035481169282019290925260045482166060820152600554909116608082015290565b6040516102769190612bb4565b61014e610d6a565b60005473ffffffffffffffffffffffffffffffffffffffff1661032a565b6104d16104cc366004612b97565b610e67565b60405167ffffffffffffffff9091168152602001610276565b6104fd6104f8366004612b97565b610e90565b6040516102769190612c0d565b61032a610518366004612b97565b67ffffffffffffffff166000908152600660205260409020546901000000000000000000900473ffffffffffffffffffffffffffffffffffffffff1690565b6102db610565366004612c67565b610eb8565b61014e610578366004612cd3565b61181c565b6104fd61058b366004612b97565b61182d565b610598611861565b6105a1816118e4565b50565b6040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815277ffffffffffffffff00000000000000000000000000000000608084901b16600482015260009073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690632cbc26bb90602401602060405180830381865afa15801561064f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106739190612cf0565b156106bb576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024015b60405180910390fd5b6002546040517fd8694ccd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063d8694ccd906107139086908690600401612e21565b602060405180830381865afa158015610730573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107549190612f6a565b90505b92915050565b610765611861565b6105a181611a5b565b60005473ffffffffffffffffffffffffffffffffffffffff1633146107de5760055473ffffffffffffffffffffffffffffffffffffffff1633146107de576040517f905d7d9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015610a855760008383838181106107fd576107fd612f83565b905060200281019061080f9190612fb2565b61081890613063565b805167ffffffffffffffff1660009081526006602090815260409182902090830151815490151568010000000000000000027fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff909116178155908201515191925090156109d8578160200151156109975760005b826040015151811015610947576000836040015182815181106108b1576108b1612f83565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036109305783516040517f463258ff00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016106b2565b61093d6001840182611c8b565b505060010161088c565b50816000015167ffffffffffffffff167f330939f6eafe8bb516716892fe962ff19770570838686e6579dbc1cc51fc3281836040015160405161098a9190612c0d565b60405180910390a26109d8565b81516040517f463258ff00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016106b2565b60005b826060015151811015610a2457610a1b83606001518281518110610a0157610a01612f83565b602002602001015183600101611cad90919063ffffffff16565b506001016109db565b5060608201515115610a7b57816000015167ffffffffffffffff167fc237ec1921f855ccd5e9a5af9733f2d58943a5a8501ec5988e305d7a4d4215868360600151604051610a729190612c0d565b60405180910390a25b50506001016107e1565b505050565b600254604080517fcdc73d51000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163cdc73d5191600480830192869291908290030181865afa158015610af9573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610b3f9190810190613114565b60045490915073ffffffffffffffffffffffffffffffffffffffff1660005b8251811015610a85576000838281518110610b7b57610b7b612f83565b60209081029190910101516040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915060009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa158015610bf6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c1a9190612f6a565b90508015610cab57610c4373ffffffffffffffffffffffffffffffffffffffff83168583611ccf565b8173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f508d7d183612c18fc339b42618912b9fa3239f631dd7ec0671f950200a0fa66e83604051610ca291815260200190565b60405180910390a35b5050600101610b5e565b6040517fbbe4f6db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063bbe4f6db90602401602060405180830381865afa158015610d46573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061075491906131a3565b60015473ffffffffffffffffffffffffffffffffffffffff163314610deb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064016106b2565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b67ffffffffffffffff8082166000908152600660205260408120549091610757911660016131ef565b67ffffffffffffffff8116600090815260066020526040902060609061075790600101611d5c565b60025460009074010000000000000000000000000000000000000000900460ff1615610f10576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905567ffffffffffffffff8516600090815260066020526040902073ffffffffffffffffffffffffffffffffffffffff8316610fb5576040517fa4ec747900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805468010000000000000000900460ff161561102657610fd86001820184611d70565b611026576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841660048201526024016106b2565b80546901000000000000000000900473ffffffffffffffffffffffffffffffffffffffff163314611083576040517f1c0a352900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60035473ffffffffffffffffffffffffffffffffffffffff168015611129576040517fe0a0e50600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82169063e0a0e506906110f6908a908a90600401612e21565b600060405180830381600087803b15801561111057600080fd5b505af1158015611124573d6000803e3d6000fd5b505050505b50604080516101a081019091526000610100820181815267ffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000081166101208501528981166101408501528454929392839291610160840191879187916111979116613210565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905567ffffffffffffffff168152602001600067ffffffffffffffff1681525081526020018573ffffffffffffffffffffffffffffffffffffffff16815260200187806020019061120b9190613237565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050509082525060200161124f8880613237565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920182905250938552505060408051602081810183529381529284019290925250016112ab6080890160608a01612cd3565b73ffffffffffffffffffffffffffffffffffffffff1681526020018681526020018780604001906112dc919061329c565b905067ffffffffffffffff8111156112f6576112f661272d565b60405190808252806020026020018201604052801561135957816020015b6113466040518060a0016040528060608152602001606081526020016060815260200160008152602001606081525090565b8152602001906001900390816113145790505b5090529050600061136d604088018861329c565b808060200260200160405190810160405280939291908181526020016000905b828210156113b9576113aa60408302860136819003810190613304565b8152602001906001019061138d565b5050505050905060005b6113d0604089018961329c565b9050811015611469576114408282815181106113ee576113ee612f83565b60209081029190910101518a6114048b80613237565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508c9250611d9f915050565b8360e00151828151811061145657611456612f83565b60209081029190910101526001016113c3565b50600080600080600260000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166397d640a28d8d60600160208101906114c59190612cd3565b8d8f80608001906114d69190613237565b8c60e001518c6040518863ffffffff1660e01b81526004016114fe979695949392919061341b565b600060405180830381865afa15801561151b573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611561919081019061354d565b9296509094509250905061157b60808c0160608d01612cd3565b73ffffffffffffffffffffffffffffffffffffffff167f075a2720282fdf622141dae0b048ef90a21a7e57c134c76912d19d006b3b3f6f856040516115c291815260200190565b60405180910390a282611696576040517fea458c0c00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8d16600482015273ffffffffffffffffffffffffffffffffffffffff8a811660248301527f0000000000000000000000000000000000000000000000000000000000000000169063ea458c0c906044016020604051808303816000875af115801561166d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116919190613640565b611699565b60005b865167ffffffffffffffff909116608091820152860182905260005b8660e0015151811015611709578181815181106116d4576116d4612f83565b60200260200101518760e0015182815181106116f2576116f2612f83565b6020908102919091010151608001526001016116b5565b50604080517f130ac867e79e2789f923760a88743d292acdf7002139a588206e2260f73f7321602082015267ffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811692820192909252908d16606082015230608082015261179990879060a001604051602081830303815290604052805190602001206120c5565b86515260405167ffffffffffffffff8d16907ff6e86ef8896c7a0d629406168f396e883280680c99e649b9e2d36466fbc9f9e5906117d890899061365d565b60405180910390a25050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1690555050905151925050505b949350505050565b611824611861565b6105a181612216565b60606040517f9e7177c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005473ffffffffffffffffffffffffffffffffffffffff1633146118e2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016106b2565b565b60005b8151811015611a5757600082828151811061190457611904612f83565b60200260200101519050600083838151811061192257611922612f83565b60200260200101516000015190508067ffffffffffffffff16600003611980576040517fc35aa79d00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff821660048201526024016106b2565b67ffffffffffffffff8181166000818152600660209081526040918290208682015181547fffffff0000000000000000000000000000000000000000ffffffffffffffffff8116690100000000000000000073ffffffffffffffffffffffffffffffffffffffff909316928302908117808555865192891691909816178152928301526801000000000000000090940460ff161515918101919091527fd5ad72bc37dc7a80a8b9b9df20500046fd7341adb1be2258a540466fdd7dcef59060600160405180910390a25050508060010190506118e7565b5050565b805173ffffffffffffffffffffffffffffffffffffffff161580611a975750606081015173ffffffffffffffffffffffffffffffffffffffff16155b80611aa3575080602001515b15611ada576040517f35be3ac800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160028054602080850151151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00000000000000000000000000000000000000000090921673ffffffffffffffffffffffffffffffffffffffff9485161791909117909155604080840151600380549185167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316179055606080860151600480549187169184169190911790556080808701516005805491881691909416179092558251918201835267ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001682527f00000000000000000000000000000000000000000000000000000000000000008516938201939093527f00000000000000000000000000000000000000000000000000000000000000008416818301527f000000000000000000000000000000000000000000000000000000000000000090931691830191909152517fc7372d2d886367d7bb1b0e0708a5436f2c91d6963de210eb2dc1ec2ecd6d21f191611c809184906137ab565b60405180910390a150565b60006107548373ffffffffffffffffffffffffffffffffffffffff841661230b565b60006107548373ffffffffffffffffffffffffffffffffffffffff841661235a565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052610a85908490612454565b60606000611d6983612560565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515610754565b611dd16040518060a0016040528060608152602001606081526020016060815260200160008152602001606081525090565b8460200151600003611e0f576040517f5cf0444900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611e1f858760000151610cb5565b905073ffffffffffffffffffffffffffffffffffffffff81161580611eef57506040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527faff2afbf00000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff8216906301ffc9a790602401602060405180830381865afa158015611ec9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611eed9190612cf0565b155b15611f415785516040517fbf16aab600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911660048201526024016106b2565b60008173ffffffffffffffffffffffffffffffffffffffff16639a4575b96040518060a001604052808881526020018967ffffffffffffffff1681526020018773ffffffffffffffffffffffffffffffffffffffff1681526020018a6020015181526020018a6000015173ffffffffffffffffffffffffffffffffffffffff168152506040518263ffffffff1660e01b8152600401611fe09190613859565b6000604051808303816000875af1158015611fff573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261204591908101906138cf565b6040805160a0810190915273ffffffffffffffffffffffffffffffffffffffff841660c08201529091508060e0810160405160208183030381529060405281526020018260000151815260200182602001518152602001886020015181526020016040518060200160405280600081525081525092505050949350505050565b60008060001b8284602001518560000151606001518660000151608001518760a001518860c0015160405160200161214395949392919073ffffffffffffffffffffffffffffffffffffffff958616815267ffffffffffffffff94851660208201529290931660408301529092166060830152608082015260a00190565b604051602081830303815290604052805190602001208560600151805190602001208660400151805190602001208760e001516040516020016121869190613960565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201206080808d0151805190840120928501999099529183019690965260608201949094529485019190915260a084015260c083015260e08201526101000160405160208183030381529060405280519060200120905092915050565b3373ffffffffffffffffffffffffffffffffffffffff821603612295576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016106b2565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600081815260018301602052604081205461235257508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610757565b506000610757565b6000818152600183016020526040812054801561244357600061237e600183613973565b855490915060009061239290600190613973565b90508082146123f75760008660000182815481106123b2576123b2612f83565b90600052602060002001549050808760000184815481106123d5576123d5612f83565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061240857612408613986565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610757565b6000915050610757565b5092915050565b60006124b6826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166125bc9092919063ffffffff16565b805190915015610a8557808060200190518101906124d49190612cf0565b610a85576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016106b2565b6060816000018054806020026020016040519081016040528092919081815260200182805480156125b057602002820191906000526020600020905b81548152602001906001019080831161259c575b50505050509050919050565b60606118148484600085856000808673ffffffffffffffffffffffffffffffffffffffff1685876040516125f091906139b5565b60006040518083038185875af1925050503d806000811461262d576040519150601f19603f3d011682016040523d82523d6000602084013e612632565b606091505b50915091506126438783838761264e565b979650505050505050565b606083156126e45782516000036126dd5773ffffffffffffffffffffffffffffffffffffffff85163b6126dd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016106b2565b5081611814565b61181483838151156126f95781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106b291906129b8565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561277f5761277f61272d565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156127cc576127cc61272d565b604052919050565b600067ffffffffffffffff8211156127ee576127ee61272d565b5060051b60200190565b67ffffffffffffffff811681146105a157600080fd5b73ffffffffffffffffffffffffffffffffffffffff811681146105a157600080fd5b6000602080838503121561284357600080fd5b823567ffffffffffffffff81111561285a57600080fd5b8301601f8101851361286b57600080fd5b803561287e612879826127d4565b612785565b81815260069190911b8201830190838101908783111561289d57600080fd5b928401925b8284101561264357604084890312156128bb5760008081fd5b6128c361275c565b84356128ce816127f8565b8152848601356128dd8161280e565b81870152825260409390930192908401906128a2565b60808101610757828467ffffffffffffffff8151168252602081015173ffffffffffffffffffffffffffffffffffffffff808216602085015280604084015116604085015280606084015116606085015250505050565b60005b8381101561296557818101518382015260200161294d565b50506000910152565b6000815180845261298681602086016020860161294a565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610754602083018461296e565b600060a082840312156129dd57600080fd5b50919050565b600080604083850312156129f657600080fd5b8235612a01816127f8565b9150602083013567ffffffffffffffff811115612a1d57600080fd5b612a29858286016129cb565b9150509250929050565b8035612a3e8161280e565b919050565b80151581146105a157600080fd5b600060a08284031215612a6357600080fd5b60405160a0810181811067ffffffffffffffff82111715612a8657612a8661272d565b6040528235612a948161280e565b81526020830135612aa481612a43565b60208201526040830135612ab78161280e565b60408201526060830135612aca8161280e565b60608201526080830135612add8161280e565b60808201529392505050565b60008060208385031215612afc57600080fd5b823567ffffffffffffffff80821115612b1457600080fd5b818501915085601f830112612b2857600080fd5b813581811115612b3757600080fd5b8660208260051b8501011115612b4c57600080fd5b60209290920196919550909350505050565b60008060408385031215612b7157600080fd5b8235612b7c816127f8565b91506020830135612b8c8161280e565b809150509250929050565b600060208284031215612ba957600080fd5b8135611d69816127f8565b60a08101610757828473ffffffffffffffffffffffffffffffffffffffff808251168352602082015115156020840152806040830151166040840152806060830151166060840152806080830151166080840152505050565b6020808252825182820181905260009190848201906040850190845b81811015612c5b57835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101612c29565b50909695505050505050565b60008060008060808587031215612c7d57600080fd5b8435612c88816127f8565b9350602085013567ffffffffffffffff811115612ca457600080fd5b612cb0878288016129cb565b935050604085013591506060850135612cc88161280e565b939692955090935050565b600060208284031215612ce557600080fd5b8135611d698161280e565b600060208284031215612d0257600080fd5b8151611d6981612a43565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112612d4257600080fd5b830160208101925035905067ffffffffffffffff811115612d6257600080fd5b803603821315612d7157600080fd5b9250929050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b8183526000602080850194508260005b85811015612e16578135612de48161280e565b73ffffffffffffffffffffffffffffffffffffffff168752818301358388015260409687019690910190600101612dd1565b509495945050505050565b600067ffffffffffffffff808516835260406020840152612e428485612d0d565b60a06040860152612e5760e086018284612d78565b915050612e676020860186612d0d565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc080878503016060880152612e9d848385612d78565b9350604088013592507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1883603018312612ed657600080fd5b60209288019283019235915084821115612eef57600080fd5b8160061b3603831315612f0157600080fd5b80878503016080880152612f16848385612dc1565b9450612f2460608901612a33565b73ffffffffffffffffffffffffffffffffffffffff811660a08901529350612f4f6080890189612d0d565b94509250808786030160c08801525050612643838383612d78565b600060208284031215612f7c57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81833603018112612fe657600080fd5b9190910192915050565b600082601f83011261300157600080fd5b81356020613011612879836127d4565b8083825260208201915060208460051b87010193508684111561303357600080fd5b602086015b8481101561305857803561304b8161280e565b8352918301918301613038565b509695505050505050565b60006080823603121561307557600080fd5b6040516080810167ffffffffffffffff82821081831117156130995761309961272d565b81604052843591506130aa826127f8565b9082526020840135906130bc82612a43565b81602084015260408501359150808211156130d657600080fd5b6130e236838701612ff0565b604084015260608501359150808211156130fb57600080fd5b5061310836828601612ff0565b60608301525092915050565b6000602080838503121561312757600080fd5b825167ffffffffffffffff81111561313e57600080fd5b8301601f8101851361314f57600080fd5b805161315d612879826127d4565b81815260059190911b8201830190838101908783111561317c57600080fd5b928401925b828410156126435783516131948161280e565b82529284019290840190613181565b6000602082840312156131b557600080fd5b8151611d698161280e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b67ffffffffffffffff81811683821601908082111561244d5761244d6131c0565b600067ffffffffffffffff80831681810361322d5761322d6131c0565b6001019392505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261326c57600080fd5b83018035915067ffffffffffffffff82111561328757600080fd5b602001915036819003821315612d7157600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126132d157600080fd5b83018035915067ffffffffffffffff8211156132ec57600080fd5b6020019150600681901b3603821315612d7157600080fd5b60006040828403121561331657600080fd5b61331e61275c565b82356133298161280e565b81526020928301359281019290925250919050565b600082825180855260208086019550808260051b84010181860160005b8481101561340e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018952815160a0815181865261339f8287018261296e565b91505085820151858203878701526133b7828261296e565b915050604080830151868303828801526133d1838261296e565b925050506060808301518187015250608080830151925085820381870152506133fa818361296e565b9a86019a945050509083019060010161335b565b5090979650505050505050565b67ffffffffffffffff881681526000602073ffffffffffffffffffffffffffffffffffffffff808a1682850152604089604086015260c0606086015261346560c08601898b612d78565b8581036080870152613477818961333e565b86810360a0880152875180825285890192509085019060005b818110156134b7578351805187168452870151878401529286019291840191600101613490565b50909e9d5050505050505050505050505050565b600082601f8301126134dc57600080fd5b815167ffffffffffffffff8111156134f6576134f661272d565b61352760207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601612785565b81815284602083860101111561353c57600080fd5b61181482602083016020870161294a565b6000806000806080858703121561356357600080fd5b8451935060208086015161357681612a43565b604087015190945067ffffffffffffffff8082111561359457600080fd5b6135a089838a016134cb565b945060608801519150808211156135b657600080fd5b818801915088601f8301126135ca57600080fd5b81516135d8612879826127d4565b81815260059190911b8301840190848101908b8311156135f757600080fd5b8585015b8381101561362f578051858111156136135760008081fd5b6136218e89838a01016134cb565b8452509186019186016135fb565b50989b979a50959850505050505050565b60006020828403121561365257600080fd5b8151611d69816127f8565b602081526136ae60208201835180518252602081015167ffffffffffffffff808216602085015280604084015116604085015280606084015116606085015280608084015116608085015250505050565b600060208301516136d760c084018273ffffffffffffffffffffffffffffffffffffffff169052565b5060408301516101808060e08501526136f46101a085018361296e565b915060608501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08086850301610100870152613731848361296e565b935060808701519150808685030161012087015261374f848361296e565b935060a0870151915061377b61014087018373ffffffffffffffffffffffffffffffffffffffff169052565b60c087015161016087015260e08701519150808685030183870152506137a1838261333e565b9695505050505050565b6101208101613803828567ffffffffffffffff8151168252602081015173ffffffffffffffffffffffffffffffffffffffff808216602085015280604084015116604085015280606084015116606085015250505050565b825173ffffffffffffffffffffffffffffffffffffffff9081166080848101919091526020850151151560a08501526040850151821660c08501526060850151821660e085015284015116610100830152611d69565b602081526000825160a0602084015261387560c084018261296e565b905067ffffffffffffffff6020850151166040840152604084015173ffffffffffffffffffffffffffffffffffffffff8082166060860152606086015160808601528060808701511660a086015250508091505092915050565b6000602082840312156138e157600080fd5b815167ffffffffffffffff808211156138f957600080fd5b908301906040828603121561390d57600080fd5b61391561275c565b82518281111561392457600080fd5b613930878286016134cb565b82525060208301518281111561394557600080fd5b613951878286016134cb565b60208301525095945050505050565b602081526000610754602083018461333e565b81810381811115610757576107576131c0565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b60008251612fe681846020870161294a56fea164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"reentrancyGuardEntered\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CannotSendZeroTokens\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GetSupportedTokensFunctionalityRemovedCheckAdminRegistry\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidAllowListRequest\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidDestChainConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeCalledByRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrAllowlistAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrancyGuardReentrantCall\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RouterMustSetOriginalSender\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"UnsupportedToken\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"name\":\"AllowListAdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"senders\",\"type\":\"address[]\"}],\"name\":\"AllowListSendersAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"senders\",\"type\":\"address[]\"}],\"name\":\"AllowListSendersRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"sourcePoolAddress\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.EVM2AnyTokenTransfer[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"CCIPMessageSent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOnRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"reentrancyGuardEntered\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"allowListEnabled\",\"type\":\"bool\"}],\"name\":\"DestChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"feeValueJuels\",\"type\":\"uint256\"}],\"name\":\"FeePaid\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeeTokenWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"allowListEnabled\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"addedAllowlistedSenders\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"removedAllowlistedSenders\",\"type\":\"address[]\"}],\"internalType\":\"structOnRamp.AllowListConfigArgs[]\",\"name\":\"allowListConfigArgsItems\",\"type\":\"tuple[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyDestChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"}],\"name\":\"forwardFromRouter\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getAllowedSendersList\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getDestChainConfig\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"allowListEnabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"reentrancyGuardEntered\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getExpectedNextSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"getFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"},{\"internalType\":\"contractIERC20\",\"name\":\"sourceToken\",\"type\":\"address\"}],\"name\":\"getPoolBySourceToken\",\"outputs\":[{\"internalType\":\"contractIPoolV1\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"contractIRouter\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"name\":\"getSupportedTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"reentrancyGuardEntered\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"setDynamicConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"withdrawFeeTokens\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x6101006040523480156200001257600080fd5b506040516200429a3803806200429a83398101604081905262000035916200073f565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf8162000186565b505083516001600160401b031615905080620000e6575060208301516001600160a01b0316155b80620000fd575060408301516001600160a01b0316155b8062000114575060608301516001600160a01b0316155b1562000133576040516306b7c75960e31b815260040160405180910390fd5b82516001600160401b031660805260208301516001600160a01b0390811660a0526040840151811660c05260608401511660e052620001728262000231565b6200017d81620003e0565b50505062000840565b336001600160a01b03821603620001e05760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b0316158062000254575060608101516001600160a01b0316155b8062000261575080602001515b1562000280576040516306b7c75960e31b815260040160405180910390fd5b8051600280546020808501511515600160a01b026001600160a81b03199092166001600160a01b039485161791909117909155604080840151600380549185166001600160a01b0319928316179055606080860151600480549187169184169190911790556080808701516005805491881691909416179092558251808301845291516001600160401b0316825260a05185169382019390935260c05184168183015260e05190931691830191909152517fc7372d2d886367d7bb1b0e0708a5436f2c91d6963de210eb2dc1ec2ecd6d21f191620003d591849082516001600160401b031681526020808401516001600160a01b03908116828401526040858101518216818501526060958601518216868501528451821660808086019190915292850151151560a0850152840151811660c084015293830151841660e0830152909101519091166101008201526101200190565b60405180910390a150565b60005b81518110156200051f5760008282815181106200040457620004046200082a565b6020026020010151905060008383815181106200042557620004256200082a565b6020026020010151600001519050806001600160401b03166000036200046a5760405163c35aa79d60e01b81526001600160401b038216600482015260240162000083565b6001600160401b03818116600081815260066020908152604091829020868201518154600160481b600160e81b0319811669010000000000000000006001600160a01b03909316928302908117808555865192891691909816178152928301526801000000000000000090940460ff161515918101919091527fd5ad72bc37dc7a80a8b9b9df20500046fd7341adb1be2258a540466fdd7dcef59060600160405180910390a2505050806001019050620003e3565b5050565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b03811182821017156200055e576200055e62000523565b60405290565b604051601f8201601f191681016001600160401b03811182821017156200058f576200058f62000523565b604052919050565b80516001600160401b0381168114620005af57600080fd5b919050565b6001600160a01b0381168114620005ca57600080fd5b50565b600060a08284031215620005e057600080fd5b60405160a081016001600160401b038111828210171562000605576200060562000523565b806040525080915082516200061a81620005b4565b8152602083015180151581146200063057600080fd5b602082015260408301516200064581620005b4565b604082015260608301516200065a81620005b4565b606082015260808301516200066f81620005b4565b6080919091015292915050565b600082601f8301126200068e57600080fd5b815160206001600160401b03821115620006ac57620006ac62000523565b620006bc818360051b0162000564565b82815260069290921b84018101918181019086841115620006dc57600080fd5b8286015b84811015620007345760408189031215620006fb5760008081fd5b6200070562000539565b620007108262000597565b8152848201516200072181620005b4565b81860152835291830191604001620006e0565b509695505050505050565b60008060008385036101408112156200075757600080fd5b60808112156200076657600080fd5b50604051608081016001600160401b0380821183831017156200078d576200078d62000523565b816040526200079c8762000597565b835260208701519150620007b082620005b4565b81602084015260408701519150620007c882620005b4565b81604084015260608701519150620007e082620005b4565b816060840152829550620007f88860808901620005cd565b94506101208701519250808311156200081057600080fd5b505062000820868287016200067c565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b60805160a05160c05160e0516139e1620008b96000396000818161022c01528181610cfd0152611c3f0152600081816101f00152818161163a0152611c180152600081816101b4015281816106080152611bee0152600081816101840152818161114b015281816117550152611bca01526139e16000f3fe608060405234801561001057600080fd5b50600436106101365760003560e01c80637437ff9f116100b2578063972b461211610081578063df0aa9e911610066578063df0aa9e914610557578063f2fde38b1461056a578063fbca3b741461057d57600080fd5b8063972b4612146104ea578063d77d5ed01461050a57600080fd5b80637437ff9f146103ee57806379ba5097146104985780638da5cb5b146104a05780639041be3d146104be57600080fd5b806327e936f1116101095780633a019940116100ee5780633a0199401461030f57806348a98aa4146103175780636def4ce71461034f57600080fd5b806327e936f1146102e957806334adf494146102fc57600080fd5b80630242cf601461013b57806306285c6914610150578063181f5a771461027f57806320487ded146102c8575b600080fd5b61014e610149366004612837565b610590565b005b61026960408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16815250905090565b60405161027691906128fa565b60405180910390f35b6102bb6040518060400160405280601081526020017f4f6e52616d7020312e362e302d6465760000000000000000000000000000000081525081565b60405161027691906129bf565b6102db6102d63660046129ea565b6105a4565b604051908152602001610276565b61014e6102f7366004612a58565b61075d565b61014e61030a366004612af0565b61076e565b61014e610a8a565b61032a610325366004612b65565b610cb5565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610276565b6103b261035d366004612b9e565b67ffffffffffffffff9081166000908152600660205260409020549081169168010000000000000000820460ff16916901000000000000000000900473ffffffffffffffffffffffffffffffffffffffff1690565b6040805167ffffffffffffffff9094168452911515602084015273ffffffffffffffffffffffffffffffffffffffff1690820152606001610276565b61048b6040805160a081018252600080825260208201819052918101829052606081018290526080810191909152506040805160a08101825260025473ffffffffffffffffffffffffffffffffffffffff80821683527401000000000000000000000000000000000000000090910460ff161515602083015260035481169282019290925260045482166060820152600554909116608082015290565b6040516102769190612bbb565b61014e610d6a565b60005473ffffffffffffffffffffffffffffffffffffffff1661032a565b6104d16104cc366004612b9e565b610e67565b60405167ffffffffffffffff9091168152602001610276565b6104fd6104f8366004612b9e565b610e90565b6040516102769190612c14565b61032a610518366004612b9e565b67ffffffffffffffff166000908152600660205260409020546901000000000000000000900473ffffffffffffffffffffffffffffffffffffffff1690565b6102db610565366004612c6e565b610eb8565b61014e610578366004612cda565b611832565b6104fd61058b366004612b9e565b611843565b610598611877565b6105a1816118fa565b50565b6040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815277ffffffffffffffff00000000000000000000000000000000608084901b16600482015260009073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690632cbc26bb90602401602060405180830381865afa15801561064f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106739190612cf7565b156106bb576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024015b60405180910390fd5b6002546040517fd8694ccd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063d8694ccd906107139086908690600401612e28565b602060405180830381865afa158015610730573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107549190612f71565b90505b92915050565b610765611877565b6105a181611a71565b60005473ffffffffffffffffffffffffffffffffffffffff1633146107de5760055473ffffffffffffffffffffffffffffffffffffffff1633146107de576040517f905d7d9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015610a855760008383838181106107fd576107fd612f8a565b905060200281019061080f9190612fb9565b6108189061306a565b805167ffffffffffffffff1660009081526006602090815260409182902090830151815490151568010000000000000000027fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff909116178155908201515191925090156109d8578160200151156109975760005b826040015151811015610947576000836040015182815181106108b1576108b1612f8a565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036109305783516040517f463258ff00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016106b2565b61093d6001840182611ca1565b505060010161088c565b50816000015167ffffffffffffffff167f330939f6eafe8bb516716892fe962ff19770570838686e6579dbc1cc51fc3281836040015160405161098a9190612c14565b60405180910390a26109d8565b81516040517f463258ff00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016106b2565b60005b826060015151811015610a2457610a1b83606001518281518110610a0157610a01612f8a565b602002602001015183600101611cc390919063ffffffff16565b506001016109db565b5060608201515115610a7b57816000015167ffffffffffffffff167fc237ec1921f855ccd5e9a5af9733f2d58943a5a8501ec5988e305d7a4d4215868360600151604051610a729190612c14565b60405180910390a25b50506001016107e1565b505050565b600254604080517fcdc73d51000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163cdc73d5191600480830192869291908290030181865afa158015610af9573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610b3f919081019061311b565b60045490915073ffffffffffffffffffffffffffffffffffffffff1660005b8251811015610a85576000838281518110610b7b57610b7b612f8a565b60209081029190910101516040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915060009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa158015610bf6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c1a9190612f71565b90508015610cab57610c4373ffffffffffffffffffffffffffffffffffffffff83168583611ce5565b8173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f508d7d183612c18fc339b42618912b9fa3239f631dd7ec0671f950200a0fa66e83604051610ca291815260200190565b60405180910390a35b5050600101610b5e565b6040517fbbe4f6db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063bbe4f6db90602401602060405180830381865afa158015610d46573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061075491906131aa565b60015473ffffffffffffffffffffffffffffffffffffffff163314610deb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064016106b2565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b67ffffffffffffffff8082166000908152600660205260408120549091610757911660016131f6565b67ffffffffffffffff8116600090815260066020526040902060609061075790600101611d72565b60025460009074010000000000000000000000000000000000000000900460ff1615610f10576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905567ffffffffffffffff8516600090815260066020526040902073ffffffffffffffffffffffffffffffffffffffff8316610fb5576040517fa4ec747900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805468010000000000000000900460ff161561102657610fd86001820184611d86565b611026576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841660048201526024016106b2565b80546901000000000000000000900473ffffffffffffffffffffffffffffffffffffffff163314611083576040517f1c0a352900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60035473ffffffffffffffffffffffffffffffffffffffff168015611129576040517fe0a0e50600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82169063e0a0e506906110f6908a908a90600401612e28565b600060405180830381600087803b15801561111057600080fd5b505af1158015611124573d6000803e3d6000fd5b505050505b50604080516101a081019091526000610100820181815267ffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000081166101208501528981166101408501528454929392839291610160840191879187916111979116613217565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905567ffffffffffffffff168152602001600067ffffffffffffffff1681525081526020018573ffffffffffffffffffffffffffffffffffffffff16815260200187806020019061120b919061323e565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050509082525060200161124f888061323e565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920182905250938552505060408051602081810183529381529284019290925250016112ab6080890160608a01612cda565b73ffffffffffffffffffffffffffffffffffffffff1681526020018681526020018780604001906112dc91906132a3565b905067ffffffffffffffff8111156112f6576112f6612734565b60405190808252806020026020018201604052801561136f57816020015b61135c6040518060a00160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001606081526020016060815260200160008152602001606081525090565b8152602001906001900390816113145790505b5090529050600061138360408801886132a3565b808060200260200160405190810160405280939291908181526020016000905b828210156113cf576113c06040830286013681900381019061330b565b815260200190600101906113a3565b5050505050905060005b6113e660408901896132a3565b905081101561147f5761145682828151811061140457611404612f8a565b60209081029190910101518a61141a8b8061323e565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508c9250611db5915050565b8360e00151828151811061146c5761146c612f8a565b60209081029190910101526001016113d9565b50600080600080600260000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663430d138c8d8d60600160208101906114db9190612cda565b8d8f80608001906114ec919061323e565b8c60e001518c6040518863ffffffff1660e01b81526004016115149796959493929190613428565b600060405180830381865afa158015611531573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611577919081019061355a565b9296509094509250905061159160808c0160608d01612cda565b73ffffffffffffffffffffffffffffffffffffffff167f075a2720282fdf622141dae0b048ef90a21a7e57c134c76912d19d006b3b3f6f856040516115d891815260200190565b60405180910390a2826116ac576040517fea458c0c00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8d16600482015273ffffffffffffffffffffffffffffffffffffffff8a811660248301527f0000000000000000000000000000000000000000000000000000000000000000169063ea458c0c906044016020604051808303816000875af1158015611683573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a7919061364d565b6116af565b60005b865167ffffffffffffffff909116608091820152860182905260005b8660e001515181101561171f578181815181106116ea576116ea612f8a565b60200260200101518760e00151828151811061170857611708612f8a565b6020908102919091010151608001526001016116cb565b50604080517f130ac867e79e2789f923760a88743d292acdf7002139a588206e2260f73f7321602082015267ffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811692820192909252908d1660608201523060808201526117af90879060a001604051602081830303815290604052805190602001206120cc565b86515260405167ffffffffffffffff8d16907f9f4bd3af5ec85ce7c750c95aca08cf5460a4a3f952cf1db9c2bbf22cdfe78bbf906117ee90899061366a565b60405180910390a25050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1690555050905151925050505b949350505050565b61183a611877565b6105a18161221d565b60606040517f9e7177c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005473ffffffffffffffffffffffffffffffffffffffff1633146118f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016106b2565b565b60005b8151811015611a6d57600082828151811061191a5761191a612f8a565b60200260200101519050600083838151811061193857611938612f8a565b60200260200101516000015190508067ffffffffffffffff16600003611996576040517fc35aa79d00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff821660048201526024016106b2565b67ffffffffffffffff8181166000818152600660209081526040918290208682015181547fffffff0000000000000000000000000000000000000000ffffffffffffffffff8116690100000000000000000073ffffffffffffffffffffffffffffffffffffffff909316928302908117808555865192891691909816178152928301526801000000000000000090940460ff161515918101919091527fd5ad72bc37dc7a80a8b9b9df20500046fd7341adb1be2258a540466fdd7dcef59060600160405180910390a25050508060010190506118fd565b5050565b805173ffffffffffffffffffffffffffffffffffffffff161580611aad5750606081015173ffffffffffffffffffffffffffffffffffffffff16155b80611ab9575080602001515b15611af0576040517f35be3ac800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160028054602080850151151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00000000000000000000000000000000000000000090921673ffffffffffffffffffffffffffffffffffffffff9485161791909117909155604080840151600380549185167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316179055606080860151600480549187169184169190911790556080808701516005805491881691909416179092558251918201835267ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001682527f00000000000000000000000000000000000000000000000000000000000000008516938201939093527f00000000000000000000000000000000000000000000000000000000000000008416818301527f000000000000000000000000000000000000000000000000000000000000000090931691830191909152517fc7372d2d886367d7bb1b0e0708a5436f2c91d6963de210eb2dc1ec2ecd6d21f191611c969184906137b8565b60405180910390a150565b60006107548373ffffffffffffffffffffffffffffffffffffffff8416612312565b60006107548373ffffffffffffffffffffffffffffffffffffffff8416612361565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052610a8590849061245b565b60606000611d7f83612567565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515610754565b611dfd6040518060a00160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001606081526020016060815260200160008152602001606081525090565b8460200151600003611e3b576040517f5cf0444900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611e4b858760000151610cb5565b905073ffffffffffffffffffffffffffffffffffffffff81161580611f1b57506040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527faff2afbf00000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff8216906301ffc9a790602401602060405180830381865afa158015611ef5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f199190612cf7565b155b15611f6d5785516040517fbf16aab600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911660048201526024016106b2565b60008173ffffffffffffffffffffffffffffffffffffffff16639a4575b96040518060a001604052808881526020018967ffffffffffffffff1681526020018773ffffffffffffffffffffffffffffffffffffffff1681526020018a6020015181526020018a6000015173ffffffffffffffffffffffffffffffffffffffff168152506040518263ffffffff1660e01b815260040161200c9190613866565b6000604051808303816000875af115801561202b573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261207191908101906138dc565b6040805160a08101825273ffffffffffffffffffffffffffffffffffffffff90941684528151602080860191909152918201518482015288820151606085015280519182019052600081526080830152509050949350505050565b60008060001b8284602001518560000151606001518660000151608001518760a001518860c0015160405160200161214a95949392919073ffffffffffffffffffffffffffffffffffffffff958616815267ffffffffffffffff94851660208201529290931660408301529092166060830152608082015260a00190565b604051602081830303815290604052805190602001208560600151805190602001208660400151805190602001208760e0015160405160200161218d919061396d565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201206080808d0151805190840120928501999099529183019690965260608201949094529485019190915260a084015260c083015260e08201526101000160405160208183030381529060405280519060200120905092915050565b3373ffffffffffffffffffffffffffffffffffffffff82160361229c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016106b2565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600081815260018301602052604081205461235957508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610757565b506000610757565b6000818152600183016020526040812054801561244a576000612385600183613980565b855490915060009061239990600190613980565b90508082146123fe5760008660000182815481106123b9576123b9612f8a565b90600052602060002001549050808760000184815481106123dc576123dc612f8a565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061240f5761240f613993565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610757565b6000915050610757565b5092915050565b60006124bd826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166125c39092919063ffffffff16565b805190915015610a8557808060200190518101906124db9190612cf7565b610a85576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016106b2565b6060816000018054806020026020016040519081016040528092919081815260200182805480156125b757602002820191906000526020600020905b8154815260200190600101908083116125a3575b50505050509050919050565b606061182a8484600085856000808673ffffffffffffffffffffffffffffffffffffffff1685876040516125f791906139c2565b60006040518083038185875af1925050503d8060008114612634576040519150601f19603f3d011682016040523d82523d6000602084013e612639565b606091505b509150915061264a87838387612655565b979650505050505050565b606083156126eb5782516000036126e45773ffffffffffffffffffffffffffffffffffffffff85163b6126e4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016106b2565b508161182a565b61182a83838151156127005781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106b291906129bf565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561278657612786612734565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156127d3576127d3612734565b604052919050565b600067ffffffffffffffff8211156127f5576127f5612734565b5060051b60200190565b67ffffffffffffffff811681146105a157600080fd5b73ffffffffffffffffffffffffffffffffffffffff811681146105a157600080fd5b6000602080838503121561284a57600080fd5b823567ffffffffffffffff81111561286157600080fd5b8301601f8101851361287257600080fd5b8035612885612880826127db565b61278c565b81815260069190911b820183019083810190878311156128a457600080fd5b928401925b8284101561264a57604084890312156128c25760008081fd5b6128ca612763565b84356128d5816127ff565b8152848601356128e481612815565b81870152825260409390930192908401906128a9565b60808101610757828467ffffffffffffffff8151168252602081015173ffffffffffffffffffffffffffffffffffffffff808216602085015280604084015116604085015280606084015116606085015250505050565b60005b8381101561296c578181015183820152602001612954565b50506000910152565b6000815180845261298d816020860160208601612951565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006107546020830184612975565b600060a082840312156129e457600080fd5b50919050565b600080604083850312156129fd57600080fd5b8235612a08816127ff565b9150602083013567ffffffffffffffff811115612a2457600080fd5b612a30858286016129d2565b9150509250929050565b8035612a4581612815565b919050565b80151581146105a157600080fd5b600060a08284031215612a6a57600080fd5b60405160a0810181811067ffffffffffffffff82111715612a8d57612a8d612734565b6040528235612a9b81612815565b81526020830135612aab81612a4a565b60208201526040830135612abe81612815565b60408201526060830135612ad181612815565b60608201526080830135612ae481612815565b60808201529392505050565b60008060208385031215612b0357600080fd5b823567ffffffffffffffff80821115612b1b57600080fd5b818501915085601f830112612b2f57600080fd5b813581811115612b3e57600080fd5b8660208260051b8501011115612b5357600080fd5b60209290920196919550909350505050565b60008060408385031215612b7857600080fd5b8235612b83816127ff565b91506020830135612b9381612815565b809150509250929050565b600060208284031215612bb057600080fd5b8135611d7f816127ff565b60a08101610757828473ffffffffffffffffffffffffffffffffffffffff808251168352602082015115156020840152806040830151166040840152806060830151166060840152806080830151166080840152505050565b6020808252825182820181905260009190848201906040850190845b81811015612c6257835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101612c30565b50909695505050505050565b60008060008060808587031215612c8457600080fd5b8435612c8f816127ff565b9350602085013567ffffffffffffffff811115612cab57600080fd5b612cb7878288016129d2565b935050604085013591506060850135612ccf81612815565b939692955090935050565b600060208284031215612cec57600080fd5b8135611d7f81612815565b600060208284031215612d0957600080fd5b8151611d7f81612a4a565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112612d4957600080fd5b830160208101925035905067ffffffffffffffff811115612d6957600080fd5b803603821315612d7857600080fd5b9250929050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b8183526000602080850194508260005b85811015612e1d578135612deb81612815565b73ffffffffffffffffffffffffffffffffffffffff168752818301358388015260409687019690910190600101612dd8565b509495945050505050565b600067ffffffffffffffff808516835260406020840152612e498485612d14565b60a06040860152612e5e60e086018284612d7f565b915050612e6e6020860186612d14565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc080878503016060880152612ea4848385612d7f565b9350604088013592507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1883603018312612edd57600080fd5b60209288019283019235915084821115612ef657600080fd5b8160061b3603831315612f0857600080fd5b80878503016080880152612f1d848385612dc8565b9450612f2b60608901612a3a565b73ffffffffffffffffffffffffffffffffffffffff811660a08901529350612f566080890189612d14565b94509250808786030160c0880152505061264a838383612d7f565b600060208284031215612f8357600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81833603018112612fed57600080fd5b9190910192915050565b600082601f83011261300857600080fd5b81356020613018612880836127db565b8083825260208201915060208460051b87010193508684111561303a57600080fd5b602086015b8481101561305f57803561305281612815565b835291830191830161303f565b509695505050505050565b60006080823603121561307c57600080fd5b6040516080810167ffffffffffffffff82821081831117156130a0576130a0612734565b81604052843591506130b1826127ff565b9082526020840135906130c382612a4a565b81602084015260408501359150808211156130dd57600080fd5b6130e936838701612ff7565b6040840152606085013591508082111561310257600080fd5b5061310f36828601612ff7565b60608301525092915050565b6000602080838503121561312e57600080fd5b825167ffffffffffffffff81111561314557600080fd5b8301601f8101851361315657600080fd5b8051613164612880826127db565b81815260059190911b8201830190838101908783111561318357600080fd5b928401925b8284101561264a57835161319b81612815565b82529284019290840190613188565b6000602082840312156131bc57600080fd5b8151611d7f81612815565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b67ffffffffffffffff818116838216019080821115612454576124546131c7565b600067ffffffffffffffff808316818103613234576132346131c7565b6001019392505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261327357600080fd5b83018035915067ffffffffffffffff82111561328e57600080fd5b602001915036819003821315612d7857600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126132d857600080fd5b83018035915067ffffffffffffffff8211156132f357600080fd5b6020019150600681901b3603821315612d7857600080fd5b60006040828403121561331d57600080fd5b613325612763565b823561333081612815565b81526020928301359281019290925250919050565b600082825180855260208086019550808260051b84010181860160005b8481101561341b577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018952815160a073ffffffffffffffffffffffffffffffffffffffff82511685528582015181878701526133c482870182612975565b915050604080830151868303828801526133de8382612975565b925050506060808301518187015250608080830151925085820381870152506134078183612975565b9a86019a9450505090830190600101613362565b5090979650505050505050565b67ffffffffffffffff881681526000602073ffffffffffffffffffffffffffffffffffffffff808a1682850152604089604086015260c0606086015261347260c08601898b612d7f565b85810360808701526134848189613345565b86810360a0880152875180825285890192509085019060005b818110156134c457835180518716845287015187840152928601929184019160010161349d565b50909e9d5050505050505050505050505050565b600082601f8301126134e957600080fd5b815167ffffffffffffffff81111561350357613503612734565b61353460207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160161278c565b81815284602083860101111561354957600080fd5b61182a826020830160208701612951565b6000806000806080858703121561357057600080fd5b8451935060208086015161358381612a4a565b604087015190945067ffffffffffffffff808211156135a157600080fd5b6135ad89838a016134d8565b945060608801519150808211156135c357600080fd5b818801915088601f8301126135d757600080fd5b81516135e5612880826127db565b81815260059190911b8301840190848101908b83111561360457600080fd5b8585015b8381101561363c578051858111156136205760008081fd5b61362e8e89838a01016134d8565b845250918601918601613608565b50989b979a50959850505050505050565b60006020828403121561365f57600080fd5b8151611d7f816127ff565b602081526136bb60208201835180518252602081015167ffffffffffffffff808216602085015280604084015116604085015280606084015116606085015280608084015116608085015250505050565b600060208301516136e460c084018273ffffffffffffffffffffffffffffffffffffffff169052565b5060408301516101808060e08501526137016101a0850183612975565b915060608501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0808685030161010087015261373e8483612975565b935060808701519150808685030161012087015261375c8483612975565b935060a0870151915061378861014087018373ffffffffffffffffffffffffffffffffffffffff169052565b60c087015161016087015260e08701519150808685030183870152506137ae8382613345565b9695505050505050565b6101208101613810828567ffffffffffffffff8151168252602081015173ffffffffffffffffffffffffffffffffffffffff808216602085015280604084015116604085015280606084015116606085015250505050565b825173ffffffffffffffffffffffffffffffffffffffff9081166080848101919091526020850151151560a08501526040850151821660c08501526060850151821660e085015284015116610100830152611d7f565b602081526000825160a0602084015261388260c0840182612975565b905067ffffffffffffffff6020850151166040840152604084015173ffffffffffffffffffffffffffffffffffffffff8082166060860152606086015160808601528060808701511660a086015250508091505092915050565b6000602082840312156138ee57600080fd5b815167ffffffffffffffff8082111561390657600080fd5b908301906040828603121561391a57600080fd5b613922612763565b82518281111561393157600080fd5b61393d878286016134d8565b82525060208301518281111561395257600080fd5b61395e878286016134d8565b60208301525095945050505050565b6020815260006107546020830184613345565b81810381811115610757576107576131c7565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b60008251612fed81846020870161295156fea164736f6c6343000818000a", } var OnRampABI = OnRampMetaData.ABI @@ -1916,7 +1916,7 @@ func (OnRampAllowListSendersRemoved) Topic() common.Hash { } func (OnRampCCIPMessageSent) Topic() common.Hash { - return common.HexToHash("0xf6e86ef8896c7a0d629406168f396e883280680c99e649b9e2d36466fbc9f9e5") + return common.HexToHash("0x9f4bd3af5ec85ce7c750c95aca08cf5460a4a3f952cf1db9c2bbf22cdfe78bbf") } func (OnRampConfigSet) Topic() common.Hash { diff --git a/core/gethwrappers/ccip/generated/report_codec/report_codec.go b/core/gethwrappers/ccip/generated/report_codec/report_codec.go index 03c190690f..06ec6c7b41 100644 --- a/core/gethwrappers/ccip/generated/report_codec/report_codec.go +++ b/core/gethwrappers/ccip/generated/report_codec/report_codec.go @@ -41,7 +41,15 @@ type InternalAny2EVMRampMessage struct { Data []byte Receiver common.Address GasLimit *big.Int - TokenAmounts []InternalRampTokenAmount + TokenAmounts []InternalAny2EVMTokenTransfer +} + +type InternalAny2EVMTokenTransfer struct { + SourcePoolAddress []byte + DestTokenAddress common.Address + DestGasAmount uint32 + ExtraData []byte + Amount *big.Int } type InternalExecutionReportSingleChain struct { @@ -78,14 +86,6 @@ type InternalRampMessageHeader struct { Nonce uint64 } -type InternalRampTokenAmount struct { - SourcePoolAddress []byte - DestTokenAddress []byte - ExtraData []byte - Amount *big.Int - DestExecData []byte -} - type InternalTokenPriceUpdate struct { SourceToken common.Address UsdPerToken *big.Int @@ -98,8 +98,8 @@ type OffRampCommitReport struct { } var ReportCodecMetaData = &bind.MetaData{ - ABI: "[{\"anonymous\":false,\"inputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"structIRMNV2.Signature[]\",\"name\":\"rmnSignatures\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"report\",\"type\":\"tuple\"}],\"name\":\"CommitReportDecoded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage[]\",\"name\":\"messages\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[][]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[][]\"},{\"internalType\":\"bytes32[]\",\"name\":\"proofs\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"proofFlagBits\",\"type\":\"uint256\"}],\"indexed\":false,\"internalType\":\"structInternal.ExecutionReportSingleChain[]\",\"name\":\"report\",\"type\":\"tuple[]\"}],\"name\":\"ExecuteReportDecoded\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"decodeCommitReport\",\"outputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"structIRMNV2.Signature[]\",\"name\":\"rmnSignatures\",\"type\":\"tuple[]\"}],\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"decodeExecuteReport\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.RampTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage[]\",\"name\":\"messages\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[][]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[][]\"},{\"internalType\":\"bytes32[]\",\"name\":\"proofs\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"proofFlagBits\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.ExecutionReportSingleChain[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]", - Bin: "0x608060405234801561001057600080fd5b506113e5806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80636fb349561461003b578063f816ec6014610064575b600080fd5b61004e610049366004610231565b610084565b60405161005b91906104f2565b60405180910390f35b610077610072366004610231565b6100a0565b60405161005b9190610837565b60608180602001905181019061009a9190610e8f565b92915050565b6040805160a08101825260608082018181526080830182905282526020808301829052928201528251909161009a918401810190840161124f565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff8111828210171561012d5761012d6100db565b60405290565b60405160c0810167ffffffffffffffff8111828210171561012d5761012d6100db565b6040805190810167ffffffffffffffff8111828210171561012d5761012d6100db565b6040516060810167ffffffffffffffff8111828210171561012d5761012d6100db565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156101e3576101e36100db565b604052919050565b600067ffffffffffffffff821115610205576102056100db565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b60006020828403121561024357600080fd5b813567ffffffffffffffff81111561025a57600080fd5b8201601f8101841361026b57600080fd5b803561027e610279826101eb565b61019c565b81815285602083850101111561029357600080fd5b81602084016020830137600091810160200191909152949350505050565b60005b838110156102cc5781810151838201526020016102b4565b50506000910152565b600081518084526102ed8160208601602086016102b1565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b600082825180855260208086019550808260051b84010181860160005b848110156103ef577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018952815160a08151818652610380828701826102d5565b915050858201518582038787015261039882826102d5565b915050604080830151868303828801526103b283826102d5565b925050506060808301518187015250608080830151925085820381870152506103db81836102d5565b9a86019a945050509083019060010161033c565b5090979650505050505050565b6000828251808552602080860195506005818360051b8501018287016000805b868110156104a7577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe088850381018c5283518051808752908801908887019080891b88018a01865b8281101561049057858a830301845261047e8286516102d5565b948c0194938c01939150600101610464565b509e8a019e9750505093870193505060010161041c565b50919998505050505050505050565b60008151808452602080850194506020840160005b838110156104e7578151875295820195908201906001016104cb565b509495945050505050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b828110156106da577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0888603018452815160a0860167ffffffffffffffff8083511688528883015160a08a8a015282815180855260c08b01915060c08160051b8c010194508b8301925060005b81811015610683577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff408c87030183528351805180518852868f820151168f890152866040820151166040890152866060820151166060890152866080820151166080890152508d81015161014060a08901526106066101408901826102d5565b9050604082015188820360c08a015261061f82826102d5565b915050606082015161064960e08a018273ffffffffffffffffffffffffffffffffffffffff169052565b50608082015161010089015260a0820151915087810361012089015261066f818361031f565b97505050928c0192918c0191600101610586565b50505050506040820151878203604089015261069f82826103fc565b915050606082015187820360608901526106b982826104b6565b60809384015198909301979097525094509285019290850190600101610519565b5092979650505050505050565b60008151808452602080850194506020840160005b838110156104e7578151805167ffffffffffffffff1688528301517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1683880152604090960195908201906001016106fc565b600082825180855260208086019550808260051b84010181860160005b848110156103ef577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018952815160a067ffffffffffffffff8083511686528683015182888801526107bf838801826102d5565b60408581015184169089015260608086015190931692880192909252506080928301519290950191909152509783019790830190600101610768565b60008151808452602080850194506020840160005b838110156104e7578151805188528301518388015260409096019590820190600101610810565b602080825282516060838301528051604060808501819052815160c086018190526000949392840191859160e08801905b808410156108c5578451805173ffffffffffffffffffffffffffffffffffffffff1683528701517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1687830152938601936001939093019290820190610868565b50938501518785037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff800160a0890152936108ff81866106e7565b9450505050508185015191507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe080858303016040860152610940828461074b565b925060408601519150808584030160608601525061095e82826107fb565b95945050505050565b600067ffffffffffffffff821115610981576109816100db565b5060051b60200190565b805167ffffffffffffffff811681146109a357600080fd5b919050565b600060a082840312156109ba57600080fd5b6109c261010a565b9050815181526109d46020830161098b565b60208201526109e56040830161098b565b60408201526109f66060830161098b565b6060820152610a076080830161098b565b608082015292915050565b600082601f830112610a2357600080fd5b8151610a31610279826101eb565b818152846020838601011115610a4657600080fd5b610a578260208301602087016102b1565b949350505050565b805173ffffffffffffffffffffffffffffffffffffffff811681146109a357600080fd5b600082601f830112610a9457600080fd5b81516020610aa461027983610967565b82815260059290921b84018101918181019086841115610ac357600080fd5b8286015b84811015610bdd57805167ffffffffffffffff80821115610ae85760008081fd5b818901915060a0807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848d03011215610b215760008081fd5b610b2961010a565b8784015183811115610b3b5760008081fd5b610b498d8a83880101610a12565b82525060408085015184811115610b605760008081fd5b610b6e8e8b83890101610a12565b8a8401525060608086015185811115610b875760008081fd5b610b958f8c838a0101610a12565b83850152506080915081860151818401525082850151925083831115610bbb5760008081fd5b610bc98d8a85880101610a12565b908201528652505050918301918301610ac7565b509695505050505050565b600082601f830112610bf957600080fd5b81516020610c0961027983610967565b82815260059290921b84018101918181019086841115610c2857600080fd5b8286015b84811015610bdd57805167ffffffffffffffff80821115610c4d5760008081fd5b8189019150610140807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848d03011215610c875760008081fd5b610c8f610133565b610c9b8c8986016109a8565b815260c084015183811115610cb05760008081fd5b610cbe8d8a83880101610a12565b898301525060e084015183811115610cd65760008081fd5b610ce48d8a83880101610a12565b604083015250610cf76101008501610a5f565b60608201526101208401516080820152908301519082821115610d1a5760008081fd5b610d288c8984870101610a83565b60a08201528652505050918301918301610c2c565b600082601f830112610d4e57600080fd5b81516020610d5e61027983610967565b82815260059290921b84018101918181019086841115610d7d57600080fd5b8286015b84811015610bdd57805167ffffffffffffffff80821115610da157600080fd5b818901915089603f830112610db557600080fd5b85820151610dc561027982610967565b81815260059190911b830160400190878101908c831115610de557600080fd5b604085015b83811015610e1e57805185811115610e0157600080fd5b610e108f6040838a0101610a12565b845250918901918901610dea565b50875250505092840192508301610d81565b600082601f830112610e4157600080fd5b81516020610e5161027983610967565b8083825260208201915060208460051b870101935086841115610e7357600080fd5b602086015b84811015610bdd5780518352918301918301610e78565b60006020808385031215610ea257600080fd5b825167ffffffffffffffff80821115610eba57600080fd5b818501915085601f830112610ece57600080fd5b8151610edc61027982610967565b81815260059190911b83018401908481019088831115610efb57600080fd5b8585015b83811015610ff557805185811115610f1657600080fd5b860160a0818c037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0011215610f4b5760008081fd5b610f5361010a565b610f5e89830161098b565b815260408083015188811115610f745760008081fd5b610f828e8c83870101610be8565b8b8401525060608084015189811115610f9b5760008081fd5b610fa98f8d83880101610d3d565b8385015250608091508184015189811115610fc45760008081fd5b610fd28f8d83880101610e30565b918401919091525060a09290920151918101919091528352918601918601610eff565b5098975050505050505050565b80517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811681146109a357600080fd5b600082601f83011261103f57600080fd5b8151602061104f61027983610967565b82815260069290921b8401810191818101908684111561106e57600080fd5b8286015b84811015610bdd576040818903121561108b5760008081fd5b611093610156565b61109c8261098b565b81526110a9858301611002565b81860152835291830191604001611072565b600082601f8301126110cc57600080fd5b815160206110dc61027983610967565b82815260059290921b840181019181810190868411156110fb57600080fd5b8286015b84811015610bdd57805167ffffffffffffffff808211156111205760008081fd5b818901915060a0807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848d030112156111595760008081fd5b61116161010a565b61116c88850161098b565b8152604080850151848111156111825760008081fd5b6111908e8b83890101610a12565b8a84015250606093506111a484860161098b565b9082015260806111b585820161098b565b938201939093529201519082015283529183019183016110ff565b600082601f8301126111e157600080fd5b815160206111f161027983610967565b82815260069290921b8401810191818101908684111561121057600080fd5b8286015b84811015610bdd576040818903121561122d5760008081fd5b611235610156565b815181528482015185820152835291830191604001611214565b6000602080838503121561126257600080fd5b825167ffffffffffffffff8082111561127a57600080fd5b908401906060828703121561128e57600080fd5b611296610179565b8251828111156112a557600080fd5b830160408189038113156112b857600080fd5b6112c0610156565b8251858111156112cf57600080fd5b8301601f81018b136112e057600080fd5b80516112ee61027982610967565b81815260069190911b8201890190898101908d83111561130d57600080fd5b928a01925b8284101561135b5785848f03121561132a5760008081fd5b611332610156565b61133b85610a5f565b81526113488c8601611002565b818d0152825292850192908a0190611312565b84525050508287015191508482111561137357600080fd5b61137f8a83850161102e565b8188015283525050828401518281111561139857600080fd5b6113a4888286016110bb565b858301525060408301519350818411156113bd57600080fd5b6113c9878585016111d0565b6040820152969550505050505056fea164736f6c6343000818000a", + ABI: "[{\"anonymous\":false,\"inputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"structIRMNV2.Signature[]\",\"name\":\"rmnSignatures\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"report\",\"type\":\"tuple\"}],\"name\":\"CommitReportDecoded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"destTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"destGasAmount\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.Any2EVMTokenTransfer[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage[]\",\"name\":\"messages\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[][]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[][]\"},{\"internalType\":\"bytes32[]\",\"name\":\"proofs\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"proofFlagBits\",\"type\":\"uint256\"}],\"indexed\":false,\"internalType\":\"structInternal.ExecutionReportSingleChain[]\",\"name\":\"report\",\"type\":\"tuple[]\"}],\"name\":\"ExecuteReportDecoded\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"decodeCommitReport\",\"outputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"structIRMNV2.Signature[]\",\"name\":\"rmnSignatures\",\"type\":\"tuple[]\"}],\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"decodeExecuteReport\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"destTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"destGasAmount\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.Any2EVMTokenTransfer[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage[]\",\"name\":\"messages\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[][]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[][]\"},{\"internalType\":\"bytes32[]\",\"name\":\"proofs\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"proofFlagBits\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.ExecutionReportSingleChain[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]", + Bin: "0x608060405234801561001057600080fd5b506113c3806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80636fb349561461003b578063f816ec6014610064575b600080fd5b61004e610049366004610231565b610084565b60405161005b91906104ee565b60405180910390f35b610077610072366004610231565b6100a0565b60405161005b9190610833565b60608180602001905181019061009a9190610e6d565b92915050565b6040805160a08101825260608082018181526080830182905282526020808301829052928201528251909161009a918401810190840161122d565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff8111828210171561012d5761012d6100db565b60405290565b60405160c0810167ffffffffffffffff8111828210171561012d5761012d6100db565b6040805190810167ffffffffffffffff8111828210171561012d5761012d6100db565b6040516060810167ffffffffffffffff8111828210171561012d5761012d6100db565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156101e3576101e36100db565b604052919050565b600067ffffffffffffffff821115610205576102056100db565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b60006020828403121561024357600080fd5b813567ffffffffffffffff81111561025a57600080fd5b8201601f8101841361026b57600080fd5b803561027e610279826101eb565b61019c565b81815285602083850101111561029357600080fd5b81602084016020830137600091810160200191909152949350505050565b60005b838110156102cc5781810151838201526020016102b4565b50506000910152565b600081518084526102ed8160208601602086016102b1565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b600082825180855260208086019550808260051b84010181860160005b848110156103eb577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018952815160a08151818652610380828701826102d5565b91505073ffffffffffffffffffffffffffffffffffffffff868301511686860152604063ffffffff81840151168187015250606080830151868303828801526103c983826102d5565b608094850151979094019690965250509884019892509083019060010161033c565b5090979650505050505050565b6000828251808552602080860195506005818360051b8501018287016000805b868110156104a3577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe088850381018c5283518051808752908801908887019080891b88018a01865b8281101561048c57858a830301845261047a8286516102d5565b948c0194938c01939150600101610460565b509e8a019e97505050938701935050600101610418565b50919998505050505050505050565b60008151808452602080850194506020840160005b838110156104e3578151875295820195908201906001016104c7565b509495945050505050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b828110156106d6577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0888603018452815160a0860167ffffffffffffffff8083511688528883015160a08a8a015282815180855260c08b01915060c08160051b8c010194508b8301925060005b8181101561067f577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff408c87030183528351805180518852868f820151168f890152866040820151166040890152866060820151166060890152866080820151166080890152508d81015161014060a08901526106026101408901826102d5565b9050604082015188820360c08a015261061b82826102d5565b915050606082015161064560e08a018273ffffffffffffffffffffffffffffffffffffffff169052565b50608082015161010089015260a0820151915087810361012089015261066b818361031f565b97505050928c0192918c0191600101610582565b50505050506040820151878203604089015261069b82826103f8565b915050606082015187820360608901526106b582826104b2565b60809384015198909301979097525094509285019290850190600101610515565b5092979650505050505050565b60008151808452602080850194506020840160005b838110156104e3578151805167ffffffffffffffff1688528301517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1683880152604090960195908201906001016106f8565b600082825180855260208086019550808260051b84010181860160005b848110156103eb577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018952815160a067ffffffffffffffff8083511686528683015182888801526107bb838801826102d5565b60408581015184169089015260608086015190931692880192909252506080928301519290950191909152509783019790830190600101610764565b60008151808452602080850194506020840160005b838110156104e357815180518852830151838801526040909601959082019060010161080c565b602080825282516060838301528051604060808501819052815160c086018190526000949392840191859160e08801905b808410156108c1578451805173ffffffffffffffffffffffffffffffffffffffff1683528701517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1687830152938601936001939093019290820190610864565b50938501518785037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff800160a0890152936108fb81866106e3565b9450505050508185015191507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08085830301604086015261093c8284610747565b925060408601519150808584030160608601525061095a82826107f7565b95945050505050565b600067ffffffffffffffff82111561097d5761097d6100db565b5060051b60200190565b805167ffffffffffffffff8116811461099f57600080fd5b919050565b600060a082840312156109b657600080fd5b6109be61010a565b9050815181526109d060208301610987565b60208201526109e160408301610987565b60408201526109f260608301610987565b6060820152610a0360808301610987565b608082015292915050565b600082601f830112610a1f57600080fd5b8151610a2d610279826101eb565b818152846020838601011115610a4257600080fd5b610a538260208301602087016102b1565b949350505050565b805173ffffffffffffffffffffffffffffffffffffffff8116811461099f57600080fd5b600082601f830112610a9057600080fd5b81516020610aa061027983610963565b82815260059290921b84018101918181019086841115610abf57600080fd5b8286015b84811015610bbb57805167ffffffffffffffff80821115610ae45760008081fd5b818901915060a0807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848d03011215610b1d5760008081fd5b610b2561010a565b8784015183811115610b375760008081fd5b610b458d8a83880101610a0e565b8252506040610b55818601610a5b565b8983015260608086015163ffffffff81168114610b725760008081fd5b808385015250608091508186015185811115610b8e5760008081fd5b610b9c8f8c838a0101610a0e565b9184019190915250919093015190830152508352918301918301610ac3565b509695505050505050565b600082601f830112610bd757600080fd5b81516020610be761027983610963565b82815260059290921b84018101918181019086841115610c0657600080fd5b8286015b84811015610bbb57805167ffffffffffffffff80821115610c2b5760008081fd5b8189019150610140807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848d03011215610c655760008081fd5b610c6d610133565b610c798c8986016109a4565b815260c084015183811115610c8e5760008081fd5b610c9c8d8a83880101610a0e565b898301525060e084015183811115610cb45760008081fd5b610cc28d8a83880101610a0e565b604083015250610cd56101008501610a5b565b60608201526101208401516080820152908301519082821115610cf85760008081fd5b610d068c8984870101610a7f565b60a08201528652505050918301918301610c0a565b600082601f830112610d2c57600080fd5b81516020610d3c61027983610963565b82815260059290921b84018101918181019086841115610d5b57600080fd5b8286015b84811015610bbb57805167ffffffffffffffff80821115610d7f57600080fd5b818901915089603f830112610d9357600080fd5b85820151610da361027982610963565b81815260059190911b830160400190878101908c831115610dc357600080fd5b604085015b83811015610dfc57805185811115610ddf57600080fd5b610dee8f6040838a0101610a0e565b845250918901918901610dc8565b50875250505092840192508301610d5f565b600082601f830112610e1f57600080fd5b81516020610e2f61027983610963565b8083825260208201915060208460051b870101935086841115610e5157600080fd5b602086015b84811015610bbb5780518352918301918301610e56565b60006020808385031215610e8057600080fd5b825167ffffffffffffffff80821115610e9857600080fd5b818501915085601f830112610eac57600080fd5b8151610eba61027982610963565b81815260059190911b83018401908481019088831115610ed957600080fd5b8585015b83811015610fd357805185811115610ef457600080fd5b860160a0818c037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0011215610f295760008081fd5b610f3161010a565b610f3c898301610987565b815260408083015188811115610f525760008081fd5b610f608e8c83870101610bc6565b8b8401525060608084015189811115610f795760008081fd5b610f878f8d83880101610d1b565b8385015250608091508184015189811115610fa25760008081fd5b610fb08f8d83880101610e0e565b918401919091525060a09290920151918101919091528352918601918601610edd565b5098975050505050505050565b80517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116811461099f57600080fd5b600082601f83011261101d57600080fd5b8151602061102d61027983610963565b82815260069290921b8401810191818101908684111561104c57600080fd5b8286015b84811015610bbb57604081890312156110695760008081fd5b611071610156565b61107a82610987565b8152611087858301610fe0565b81860152835291830191604001611050565b600082601f8301126110aa57600080fd5b815160206110ba61027983610963565b82815260059290921b840181019181810190868411156110d957600080fd5b8286015b84811015610bbb57805167ffffffffffffffff808211156110fe5760008081fd5b818901915060a0807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848d030112156111375760008081fd5b61113f61010a565b61114a888501610987565b8152604080850151848111156111605760008081fd5b61116e8e8b83890101610a0e565b8a8401525060609350611182848601610987565b908201526080611193858201610987565b938201939093529201519082015283529183019183016110dd565b600082601f8301126111bf57600080fd5b815160206111cf61027983610963565b82815260069290921b840181019181810190868411156111ee57600080fd5b8286015b84811015610bbb576040818903121561120b5760008081fd5b611213610156565b8151815284820151858201528352918301916040016111f2565b6000602080838503121561124057600080fd5b825167ffffffffffffffff8082111561125857600080fd5b908401906060828703121561126c57600080fd5b611274610179565b82518281111561128357600080fd5b8301604081890381131561129657600080fd5b61129e610156565b8251858111156112ad57600080fd5b8301601f81018b136112be57600080fd5b80516112cc61027982610963565b81815260069190911b8201890190898101908d8311156112eb57600080fd5b928a01925b828410156113395785848f0312156113085760008081fd5b611310610156565b61131985610a5b565b81526113268c8601610fe0565b818d0152825292850192908a01906112f0565b84525050508287015191508482111561135157600080fd5b61135d8a83850161100c565b8188015283525050828401518281111561137657600080fd5b61138288828601611099565b8583015250604083015193508184111561139b57600080fd5b6113a7878585016111ae565b6040820152969550505050505056fea164736f6c6343000818000a", } var ReportCodecABI = ReportCodecMetaData.ABI @@ -533,7 +533,7 @@ func (ReportCodecCommitReportDecoded) Topic() common.Hash { } func (ReportCodecExecuteReportDecoded) Topic() common.Hash { - return common.HexToHash("0x70d042e9d8463eeac7e835e7172c08846ad327fc4eb6fc89f3bb5226e17ad618") + return common.HexToHash("0x9467c8093a35a72f74398d5b6e351d67dc82eddc378efc6177eafb4fc7a01d39") } func (_ReportCodec *ReportCodec) Address() common.Address { diff --git a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt index 66838f0141..c71e5d53dd 100644 --- a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -6,17 +6,17 @@ burn_with_from_mint_token_pool: ../../../contracts/solc/v0.8.24/BurnWithFromMint burn_with_from_mint_token_pool_and_proxy: ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPoolAndProxy/BurnWithFromMintTokenPoolAndProxy.abi ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPoolAndProxy/BurnWithFromMintTokenPoolAndProxy.bin 08ed1235dda921ce8841b26aa18d0c0f36db4884779dd7670857159801b6d597 ccip_config: ../../../contracts/solc/v0.8.24/CCIPConfig/CCIPConfig.abi ../../../contracts/solc/v0.8.24/CCIPConfig/CCIPConfig.bin f67d4a98804a9534a6554da3a57779632d55ad76db5ecc16ade74774769cdd69 ccip_encoding_utils: ../../../contracts/solc/v0.8.24/CCIPEncodingUtils/CCIPEncodingUtils.abi ../../../contracts/solc/v0.8.24/CCIPEncodingUtils/CCIPEncodingUtils.bin 1d48b49fc0668c4f8c5e19a208cf4cae124a9a5c361e7900fbc35b97a62dd1bc -ccip_reader_tester: ../../../contracts/solc/v0.8.24/CCIPReaderTester/CCIPReaderTester.abi ../../../contracts/solc/v0.8.24/CCIPReaderTester/CCIPReaderTester.bin 481d461f14c98308cd788b64be1151e92bac6f95ddd55eefc926296454316f13 +ccip_reader_tester: ../../../contracts/solc/v0.8.24/CCIPReaderTester/CCIPReaderTester.abi ../../../contracts/solc/v0.8.24/CCIPReaderTester/CCIPReaderTester.bin f6405e2c1e76b22810953572079710a5aa28d1171c70d3a0dc3ca8b365c8df1c commit_store: ../../../contracts/solc/v0.8.24/CommitStore/CommitStore.abi ../../../contracts/solc/v0.8.24/CommitStore/CommitStore.bin 274d87db70b643e00ab0a7e7845bb4b791f3b613bfc87708d33fc5a8369e2a41 commit_store_helper: ../../../contracts/solc/v0.8.24/CommitStoreHelper/CommitStoreHelper.abi ../../../contracts/solc/v0.8.24/CommitStoreHelper/CommitStoreHelper.bin f7128dcc2ee6dbcbc976288abcc16970ffb19b59412c5202ef6b259d2007f801 ether_sender_receiver: ../../../contracts/solc/v0.8.24/EtherSenderReceiver/EtherSenderReceiver.abi ../../../contracts/solc/v0.8.24/EtherSenderReceiver/EtherSenderReceiver.bin 09510a3f773f108a3c231e8d202835c845ded862d071ec54c4f89c12d868b8de evm_2_evm_offramp: ../../../contracts/solc/v0.8.24/EVM2EVMOffRamp/EVM2EVMOffRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMOffRamp/EVM2EVMOffRamp.bin b0d77babbe635cd6ba04c2af049badc9e9d28a4b6ed6bb75f830ad902a618beb evm_2_evm_onramp: ../../../contracts/solc/v0.8.24/EVM2EVMOnRamp/EVM2EVMOnRamp.abi ../../../contracts/solc/v0.8.24/EVM2EVMOnRamp/EVM2EVMOnRamp.bin 5c02c2b167946b3467636ff2bb58594cb4652fc63d8bdfee2488ed562e2a3e50 -fee_quoter: ../../../contracts/solc/v0.8.24/FeeQuoter/FeeQuoter.abi ../../../contracts/solc/v0.8.24/FeeQuoter/FeeQuoter.bin 29d5a1e39275bd6d378e4bd2d90e7121bb867c039d27c763086e028066dd51de +fee_quoter: ../../../contracts/solc/v0.8.24/FeeQuoter/FeeQuoter.abi ../../../contracts/solc/v0.8.24/FeeQuoter/FeeQuoter.bin 6806f01f305df73a923361f128b8962e9a8d3e7338a9a5b5fbe0636e6c9fc35f lock_release_token_pool: ../../../contracts/solc/v0.8.24/LockReleaseTokenPool/LockReleaseTokenPool.abi ../../../contracts/solc/v0.8.24/LockReleaseTokenPool/LockReleaseTokenPool.bin e6a8ec9e8faccb1da7d90e0f702ed72975964f97dc3222b54cfcca0a0ba3fea2 lock_release_token_pool_and_proxy: ../../../contracts/solc/v0.8.24/LockReleaseTokenPoolAndProxy/LockReleaseTokenPoolAndProxy.abi ../../../contracts/solc/v0.8.24/LockReleaseTokenPoolAndProxy/LockReleaseTokenPoolAndProxy.bin e632b08be0fbd1d013e8b3a9d75293d0d532b83071c531ff2be1deec1fa48ec1 maybe_revert_message_receiver: ../../../contracts/solc/v0.8.24/MaybeRevertMessageReceiver/MaybeRevertMessageReceiver.abi ../../../contracts/solc/v0.8.24/MaybeRevertMessageReceiver/MaybeRevertMessageReceiver.bin d73956c26232ebcc4a5444429fa99cbefed960e323be9b5a24925885c2e477d5 -message_hasher: ../../../contracts/solc/v0.8.24/MessageHasher/MessageHasher.abi ../../../contracts/solc/v0.8.24/MessageHasher/MessageHasher.bin 9c840c4ee02bd865630f2ef0070b8c745925577c4ee52cbc2e4f978177fc977c +message_hasher: ../../../contracts/solc/v0.8.24/MessageHasher/MessageHasher.abi ../../../contracts/solc/v0.8.24/MessageHasher/MessageHasher.bin 0a2661da24147160383ad61d56a258515d1cc07f5e0f471ec5cbb4bccaf82389 mock_usdc_token_messenger: ../../../contracts/solc/v0.8.24/MockE2EUSDCTokenMessenger/MockE2EUSDCTokenMessenger.abi ../../../contracts/solc/v0.8.24/MockE2EUSDCTokenMessenger/MockE2EUSDCTokenMessenger.bin d976651d36b33ac2196b32b9d2f4fa6690c6a18d41b621365659fce1c1d1e737 mock_usdc_token_transmitter: ../../../contracts/solc/v0.8.24/MockE2EUSDCTransmitter/MockE2EUSDCTransmitter.abi ../../../contracts/solc/v0.8.24/MockE2EUSDCTransmitter/MockE2EUSDCTransmitter.bin be0dbc3e475741ea0b7a54ec2b935a321b428baa9f4ce18180a87fb38bb87de2 mock_v3_aggregator_contract: ../../../contracts/solc/v0.8.24/MockV3Aggregator/MockV3Aggregator.abi ../../../contracts/solc/v0.8.24/MockV3Aggregator/MockV3Aggregator.bin 518e19efa2ff52b0fefd8e597b05765317ee7638189bfe34ca43de2f6599faf4 @@ -24,12 +24,12 @@ multi_aggregate_rate_limiter: ../../../contracts/solc/v0.8.24/MultiAggregateRate multi_ocr3_helper: ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Helper.abi ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Helper.bin 04b6b261dd71925670bf4d904aaf7bf08543452009feefb88e07d4c49d12e969 nonce_manager: ../../../contracts/solc/v0.8.24/NonceManager/NonceManager.abi ../../../contracts/solc/v0.8.24/NonceManager/NonceManager.bin 6f64e1083b356c06ee66b9138e398b9c97a4cd3e8c9ec38cf3010cebc79af536 ocr3_config_encoder: ../../../contracts/solc/v0.8.24/IOCR3ConfigEncoder/IOCR3ConfigEncoder.abi ../../../contracts/solc/v0.8.24/IOCR3ConfigEncoder/IOCR3ConfigEncoder.bin d507c3ac70a7d1033b75151c1e5b854b41aaee164dfaa3e5477de400db1aa1f7 -offramp: ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.abi ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.bin abc5cb0a9c3194aa1256e953c59ae86b416340631fc2594032babd138552df1e -onramp: ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.abi ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.bin 57a053c78e7f91fdde84854609ad110c4db5b65142a0aab2c884c5c008e0873a +offramp: ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.abi ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.bin 2eb54a0993aee70490421597d0ada1de92abe0929d415b56f527ba52050bb948 +onramp: ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.abi ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.bin 1f31a62ebb3fa5f4702ee27d4fa86604de5afff56787ef67c8dac764eefd2956 ping_pong_demo: ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.abi ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.bin c1c2f8a65c7ffd971899cae7fe62f2da57d09e936151e2b92163c4bebe699d6b price_registry: ../../../contracts/solc/v0.8.24/PriceRegistry/PriceRegistry.abi ../../../contracts/solc/v0.8.24/PriceRegistry/PriceRegistry.bin e7781d600c1bb7aa4620106af7f6e146a109b97f4cb6a7d06c9e15773340ecb2 registry_module_owner_custom: ../../../contracts/solc/v0.8.24/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.abi ../../../contracts/solc/v0.8.24/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.bin 75be86323c227917a9bbc3f799d7ed02f92db546653a36db30ed0ebe64461353 -report_codec: ../../../contracts/solc/v0.8.24/ReportCodec/ReportCodec.abi ../../../contracts/solc/v0.8.24/ReportCodec/ReportCodec.bin cb9183d8d8ebbc1e64bc0d4c9525264e8b71de3e8d3622962dbada53970ecfc8 +report_codec: ../../../contracts/solc/v0.8.24/ReportCodec/ReportCodec.abi ../../../contracts/solc/v0.8.24/ReportCodec/ReportCodec.bin 314427fc02cbf208d6b27197b89bb98bb81d1b9b18dc46e6a761cdc024b1e538 rmn_contract: ../../../contracts/solc/v0.8.24/RMN/RMN.abi ../../../contracts/solc/v0.8.24/RMN/RMN.bin 8b45b0fb08631c6b582fd3c0b4052a79cc2b4e091e6286af1ab131bef63661f9 rmn_proxy_contract: ../../../contracts/solc/v0.8.24/ARMProxy/ARMProxy.abi ../../../contracts/solc/v0.8.24/ARMProxy/ARMProxy.bin b048d8e752e3c41113ebb305c1efa06737ad36b4907b93e627fb0a3113023454 rmn_remote: ../../../contracts/solc/v0.8.24/RMNRemote/RMNRemote.abi ../../../contracts/solc/v0.8.24/RMNRemote/RMNRemote.bin c58cc9f0102413373f45882e87d69b4bf9a4f4516ecfa866584618a1384a8416 diff --git a/core/gethwrappers/ccip/mocks/fee_quoter_interface.go b/core/gethwrappers/ccip/mocks/fee_quoter_interface.go index c4da25361f..df9d6642cb 100644 --- a/core/gethwrappers/ccip/mocks/fee_quoter_interface.go +++ b/core/gethwrappers/ccip/mocks/fee_quoter_interface.go @@ -3295,9 +3295,9 @@ func (_c *FeeQuoterInterface_ParseUsdPerUnitGasUpdated_Call) RunAndReturn(run fu return _c } -// ProcessMessageArgs provides a mock function with given fields: opts, destChainSelector, feeToken, feeTokenAmount, extraArgs, rampTokenAmounts, sourceTokenAmounts -func (_m *FeeQuoterInterface) ProcessMessageArgs(opts *bind.CallOpts, destChainSelector uint64, feeToken common.Address, feeTokenAmount *big.Int, extraArgs []byte, rampTokenAmounts []fee_quoter.InternalRampTokenAmount, sourceTokenAmounts []fee_quoter.ClientEVMTokenAmount) (fee_quoter.ProcessMessageArgs, error) { - ret := _m.Called(opts, destChainSelector, feeToken, feeTokenAmount, extraArgs, rampTokenAmounts, sourceTokenAmounts) +// ProcessMessageArgs provides a mock function with given fields: opts, destChainSelector, feeToken, feeTokenAmount, extraArgs, onRampTokenTransfers, sourceTokenAmounts +func (_m *FeeQuoterInterface) ProcessMessageArgs(opts *bind.CallOpts, destChainSelector uint64, feeToken common.Address, feeTokenAmount *big.Int, extraArgs []byte, onRampTokenTransfers []fee_quoter.InternalEVM2AnyTokenTransfer, sourceTokenAmounts []fee_quoter.ClientEVMTokenAmount) (fee_quoter.ProcessMessageArgs, error) { + ret := _m.Called(opts, destChainSelector, feeToken, feeTokenAmount, extraArgs, onRampTokenTransfers, sourceTokenAmounts) if len(ret) == 0 { panic("no return value specified for ProcessMessageArgs") @@ -3305,17 +3305,17 @@ func (_m *FeeQuoterInterface) ProcessMessageArgs(opts *bind.CallOpts, destChainS var r0 fee_quoter.ProcessMessageArgs var r1 error - if rf, ok := ret.Get(0).(func(*bind.CallOpts, uint64, common.Address, *big.Int, []byte, []fee_quoter.InternalRampTokenAmount, []fee_quoter.ClientEVMTokenAmount) (fee_quoter.ProcessMessageArgs, error)); ok { - return rf(opts, destChainSelector, feeToken, feeTokenAmount, extraArgs, rampTokenAmounts, sourceTokenAmounts) + if rf, ok := ret.Get(0).(func(*bind.CallOpts, uint64, common.Address, *big.Int, []byte, []fee_quoter.InternalEVM2AnyTokenTransfer, []fee_quoter.ClientEVMTokenAmount) (fee_quoter.ProcessMessageArgs, error)); ok { + return rf(opts, destChainSelector, feeToken, feeTokenAmount, extraArgs, onRampTokenTransfers, sourceTokenAmounts) } - if rf, ok := ret.Get(0).(func(*bind.CallOpts, uint64, common.Address, *big.Int, []byte, []fee_quoter.InternalRampTokenAmount, []fee_quoter.ClientEVMTokenAmount) fee_quoter.ProcessMessageArgs); ok { - r0 = rf(opts, destChainSelector, feeToken, feeTokenAmount, extraArgs, rampTokenAmounts, sourceTokenAmounts) + if rf, ok := ret.Get(0).(func(*bind.CallOpts, uint64, common.Address, *big.Int, []byte, []fee_quoter.InternalEVM2AnyTokenTransfer, []fee_quoter.ClientEVMTokenAmount) fee_quoter.ProcessMessageArgs); ok { + r0 = rf(opts, destChainSelector, feeToken, feeTokenAmount, extraArgs, onRampTokenTransfers, sourceTokenAmounts) } else { r0 = ret.Get(0).(fee_quoter.ProcessMessageArgs) } - if rf, ok := ret.Get(1).(func(*bind.CallOpts, uint64, common.Address, *big.Int, []byte, []fee_quoter.InternalRampTokenAmount, []fee_quoter.ClientEVMTokenAmount) error); ok { - r1 = rf(opts, destChainSelector, feeToken, feeTokenAmount, extraArgs, rampTokenAmounts, sourceTokenAmounts) + if rf, ok := ret.Get(1).(func(*bind.CallOpts, uint64, common.Address, *big.Int, []byte, []fee_quoter.InternalEVM2AnyTokenTransfer, []fee_quoter.ClientEVMTokenAmount) error); ok { + r1 = rf(opts, destChainSelector, feeToken, feeTokenAmount, extraArgs, onRampTokenTransfers, sourceTokenAmounts) } else { r1 = ret.Error(1) } @@ -3334,15 +3334,15 @@ type FeeQuoterInterface_ProcessMessageArgs_Call struct { // - feeToken common.Address // - feeTokenAmount *big.Int // - extraArgs []byte -// - rampTokenAmounts []fee_quoter.InternalRampTokenAmount +// - onRampTokenTransfers []fee_quoter.InternalEVM2AnyTokenTransfer // - sourceTokenAmounts []fee_quoter.ClientEVMTokenAmount -func (_e *FeeQuoterInterface_Expecter) ProcessMessageArgs(opts interface{}, destChainSelector interface{}, feeToken interface{}, feeTokenAmount interface{}, extraArgs interface{}, rampTokenAmounts interface{}, sourceTokenAmounts interface{}) *FeeQuoterInterface_ProcessMessageArgs_Call { - return &FeeQuoterInterface_ProcessMessageArgs_Call{Call: _e.mock.On("ProcessMessageArgs", opts, destChainSelector, feeToken, feeTokenAmount, extraArgs, rampTokenAmounts, sourceTokenAmounts)} +func (_e *FeeQuoterInterface_Expecter) ProcessMessageArgs(opts interface{}, destChainSelector interface{}, feeToken interface{}, feeTokenAmount interface{}, extraArgs interface{}, onRampTokenTransfers interface{}, sourceTokenAmounts interface{}) *FeeQuoterInterface_ProcessMessageArgs_Call { + return &FeeQuoterInterface_ProcessMessageArgs_Call{Call: _e.mock.On("ProcessMessageArgs", opts, destChainSelector, feeToken, feeTokenAmount, extraArgs, onRampTokenTransfers, sourceTokenAmounts)} } -func (_c *FeeQuoterInterface_ProcessMessageArgs_Call) Run(run func(opts *bind.CallOpts, destChainSelector uint64, feeToken common.Address, feeTokenAmount *big.Int, extraArgs []byte, rampTokenAmounts []fee_quoter.InternalRampTokenAmount, sourceTokenAmounts []fee_quoter.ClientEVMTokenAmount)) *FeeQuoterInterface_ProcessMessageArgs_Call { +func (_c *FeeQuoterInterface_ProcessMessageArgs_Call) Run(run func(opts *bind.CallOpts, destChainSelector uint64, feeToken common.Address, feeTokenAmount *big.Int, extraArgs []byte, onRampTokenTransfers []fee_quoter.InternalEVM2AnyTokenTransfer, sourceTokenAmounts []fee_quoter.ClientEVMTokenAmount)) *FeeQuoterInterface_ProcessMessageArgs_Call { _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*bind.CallOpts), args[1].(uint64), args[2].(common.Address), args[3].(*big.Int), args[4].([]byte), args[5].([]fee_quoter.InternalRampTokenAmount), args[6].([]fee_quoter.ClientEVMTokenAmount)) + run(args[0].(*bind.CallOpts), args[1].(uint64), args[2].(common.Address), args[3].(*big.Int), args[4].([]byte), args[5].([]fee_quoter.InternalEVM2AnyTokenTransfer), args[6].([]fee_quoter.ClientEVMTokenAmount)) }) return _c } @@ -3352,7 +3352,7 @@ func (_c *FeeQuoterInterface_ProcessMessageArgs_Call) Return(_a0 fee_quoter.Proc return _c } -func (_c *FeeQuoterInterface_ProcessMessageArgs_Call) RunAndReturn(run func(*bind.CallOpts, uint64, common.Address, *big.Int, []byte, []fee_quoter.InternalRampTokenAmount, []fee_quoter.ClientEVMTokenAmount) (fee_quoter.ProcessMessageArgs, error)) *FeeQuoterInterface_ProcessMessageArgs_Call { +func (_c *FeeQuoterInterface_ProcessMessageArgs_Call) RunAndReturn(run func(*bind.CallOpts, uint64, common.Address, *big.Int, []byte, []fee_quoter.InternalEVM2AnyTokenTransfer, []fee_quoter.ClientEVMTokenAmount) (fee_quoter.ProcessMessageArgs, error)) *FeeQuoterInterface_ProcessMessageArgs_Call { _c.Call.Return(run) return _c } From f8d2f981e54aa7eb739d21ab925a954e043da9b6 Mon Sep 17 00:00:00 2001 From: Sergey Kudasov <f4hrenh9it@gmail.com> Date: Mon, 16 Sep 2024 17:03:34 +0200 Subject: [PATCH 098/115] Update CTF deps (#1442) --- .github/actions/build-test-image/action.yml | 2 +- .github/workflows/integration-tests.yml | 2 +- core/scripts/ccip/manual-execution/go.mod | 2 + core/scripts/go.mod | 2 + dashboard-lib/go.mod | 2 + go.mod | 2 + integration-tests/actions/actions.go | 14 +- .../actions/automation_ocr_helpers.go | 2 +- .../actions/automationv2/actions.go | 6 +- integration-tests/actions/keeper_helpers.go | 4 +- integration-tests/actions/ocr2_helpers.go | 2 +- .../actions/ocr2_helpers_local.go | 2 +- integration-tests/actions/ocr_helpers.go | 2 +- .../actions/ocr_helpers_local.go | 2 +- integration-tests/actions/private_network.go | 6 +- integration-tests/actions/refund.go | 2 +- .../actions/vrf/common/actions.go | 6 +- .../actions/vrf/vrfv2/contract_steps.go | 2 +- .../actions/vrf/vrfv2/setup_steps.go | 4 +- .../actions/vrf/vrfv2plus/contract_steps.go | 2 +- .../actions/vrf/vrfv2plus/setup_steps.go | 6 +- integration-tests/benchmark/keeper_test.go | 20 +-- .../ccip-tests/actions/ccip_helpers.go | 18 +- .../ccip-tests/actions/lm_helpers.go | 2 +- .../ccip-tests/actions/reorg_helpers.go | 2 +- .../ccip-tests/chaos/ccip_test.go | 6 +- .../ccip-tests/contracts/contract_deployer.go | 2 +- .../ccip-tests/contracts/contract_models.go | 2 +- .../ccip-tests/contracts/lm_contracts.go | 2 +- .../ccip-tests/contracts/multicall.go | 2 +- .../ccip-tests/load/ccip_loadgen.go | 3 +- .../ccip-tests/load/ccip_multicall_loadgen.go | 7 +- .../ccip-tests/load/ccip_test.go | 6 +- integration-tests/ccip-tests/load/helper.go | 7 +- .../ccip-tests/smoke/ccip_test.go | 4 +- integration-tests/ccip-tests/smoke/lm_test.go | 2 +- .../ccip-tests/testconfig/ccip.go | 4 +- .../ccip-tests/testconfig/global.go | 16 +- .../ccip-tests/testreporters/ccip.go | 4 +- .../ccip-tests/testsetups/ccip.go | 18 +- .../ccip-tests/testsetups/lm_setup.go | 8 +- .../ccip-tests/testsetups/test_env.go | 26 +-- .../ccip-tests/types/config/node/core.go | 4 +- .../chaos/automation_chaos_test.go | 20 +-- integration-tests/chaos/ocr_chaos_test.go | 28 ++-- .../citool/cmd/create_test_config_cmd.go | 4 +- integration-tests/citool/cmd/filter_cmd.go | 2 +- .../citool/cmd/test_config_cmd.go | 2 +- .../citool/cmd/test_config_cmd_test.go | 4 +- integration-tests/client/chainlink_k8s.go | 2 +- .../ethereum/OffchainAggregatorEventsMock.go | 1 + .../contracts/ethereum/StakingEventsMock.go | 1 + .../ethereum_contracts_automation.go | 4 +- .../contracts/ethereum_vrf_contracts.go | 2 +- integration-tests/crib/chaos.go | 11 +- integration-tests/crib/connect.go | 8 +- integration-tests/crib/ocr_test.go | 7 +- .../docker/cmd/internal/commands.go | 4 +- integration-tests/docker/test_env/cl_node.go | 10 +- integration-tests/docker/test_env/test_env.go | 14 +- .../docker/test_env/test_env_builder.go | 16 +- .../docker/test_env/test_env_config.go | 2 +- integration-tests/experiments/gas_test.go | 6 +- integration-tests/go.mod | 74 ++++----- integration-tests/go.sum | 156 +++++++++--------- .../automationv2_1/automationv2_1_test.go | 21 +-- integration-tests/load/automationv2_1/gun.go | 3 +- .../load/automationv2_1/helpers.go | 4 +- .../load/functions/functions_test.go | 3 +- .../load/functions/functionscmd/dashboard.go | 3 +- .../load/functions/gateway_gun.go | 3 +- .../load/functions/gateway_test.go | 3 +- .../load/functions/onchain_monitoring.go | 5 +- .../load/functions/request_gun.go | 2 +- integration-tests/load/functions/setup.go | 6 +- integration-tests/load/go.mod | 38 +++-- integration-tests/load/go.sum | 62 ++++--- integration-tests/load/ocr/gun.go | 3 +- integration-tests/load/ocr/ocr_test.go | 4 +- integration-tests/load/ocr/vu.go | 5 +- integration-tests/load/vrfv2/gun.go | 5 +- .../load/vrfv2/onchain_monitoring.go | 3 +- integration-tests/load/vrfv2/vrfv2_test.go | 11 +- .../load/vrfv2/vrfv2cmd/dashboard.go | 2 +- integration-tests/load/vrfv2plus/gun.go | 5 +- .../load/vrfv2plus/onchain_monitoring.go | 3 +- .../load/vrfv2plus/vrfv2plus_test.go | 11 +- .../load/vrfv2plus/vrfv2pluscmd/dashboard.go | 2 +- .../load/zcluster/cluster_entrypoint_test.go | 3 +- .../migration/upgrade_version_test.go | 2 +- .../reorg/automation_reorg_test.go | 10 +- integration-tests/runner_helpers.go | 2 +- integration-tests/smoke/automation_test.go | 8 +- integration-tests/smoke/cron_test.go | 2 +- integration-tests/smoke/flux_test.go | 6 +- integration-tests/smoke/forwarder_ocr_test.go | 6 +- .../smoke/forwarders_ocr2_test.go | 6 +- integration-tests/smoke/keeper_test.go | 6 +- integration-tests/smoke/log_poller_test.go | 6 +- integration-tests/smoke/ocr2_test.go | 8 +- integration-tests/smoke/ocr_test.go | 6 +- .../smoke/reorg_above_finality_test.go | 4 +- integration-tests/smoke/runlog_test.go | 6 +- integration-tests/smoke/vrf_test.go | 6 +- integration-tests/smoke/vrfv2_test.go | 12 +- integration-tests/smoke/vrfv2plus_test.go | 12 +- integration-tests/soak/forwarder_ocr_test.go | 2 +- integration-tests/soak/ocr_test.go | 23 +-- .../testconfig/common/vrf/common.go | 2 +- .../testconfig/functions/config.go | 4 +- integration-tests/testconfig/keeper/config.go | 2 +- .../testconfig/log_poller/config.go | 2 +- integration-tests/testconfig/ocr/ocr.go | 2 +- integration-tests/testconfig/ocr2/ocr2.go | 2 +- integration-tests/testconfig/testconfig.go | 16 +- .../testconfig/testconfig_test.go | 29 ++-- integration-tests/testreporters/keeper.go | 2 +- .../testreporters/keeper_benchmark.go | 2 +- integration-tests/testreporters/ocr.go | 2 +- integration-tests/testreporters/profile.go | 2 +- integration-tests/testreporters/vrfv2.go | 2 +- integration-tests/testreporters/vrfv2plus.go | 2 +- .../testsetups/keeper_benchmark.go | 12 +- integration-tests/testsetups/ocr.go | 58 +++---- integration-tests/types/config/node/core.go | 4 +- integration-tests/types/testconfigs.go | 4 +- integration-tests/universal/log_poller/gun.go | 2 +- .../universal/log_poller/helpers.go | 15 +- integration-tests/utils/templates/secrets.go | 2 +- .../web/sdk/internal/generated/generated.go | 1 + integration-tests/wrappers/contract_caller.go | 2 +- 131 files changed, 576 insertions(+), 555 deletions(-) diff --git a/.github/actions/build-test-image/action.yml b/.github/actions/build-test-image/action.yml index e7e84bdb2c..b719e296f8 100644 --- a/.github/actions/build-test-image/action.yml +++ b/.github/actions/build-test-image/action.yml @@ -37,7 +37,7 @@ runs: uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/mod-version@fc3e0df622521019f50d772726d6bf8dc919dd38 # v2.3.19 with: go-project-path: ./integration-tests - module-name: github.com/smartcontractkit/chainlink-testing-framework + module-name: github.com/smartcontractkit/chainlink-testing-framework/lib enforce-semantic-tag: false - name: Get CTF sha if: steps.version.outputs.is_semantic == 'false' diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index b03f30c979..3a61256c8c 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -69,7 +69,7 @@ jobs: uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/mod-version@fc3e0df622521019f50d772726d6bf8dc919dd38 # v2.3.19 with: go-project-path: ./integration-tests - module-name: github.com/smartcontractkit/chainlink-testing-framework + module-name: github.com/smartcontractkit/chainlink-testing-framework/lib enforce-semantic-tag: "true" changes: diff --git a/core/scripts/ccip/manual-execution/go.mod b/core/scripts/ccip/manual-execution/go.mod index ec295ec868..c01e615d6d 100644 --- a/core/scripts/ccip/manual-execution/go.mod +++ b/core/scripts/ccip/manual-execution/go.mod @@ -28,3 +28,5 @@ require ( gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) + +exclude github.com/sourcegraph/sourcegraph/lib v0.0.0-20221216004406-749998a2ac74 diff --git a/core/scripts/go.mod b/core/scripts/go.mod index ac50bc8655..b8cddfbb5a 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -373,3 +373,5 @@ replace ( // until merged upstream: https://github.com/mwitkow/grpc-proxy/pull/69 github.com/mwitkow/grpc-proxy => github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f ) + +exclude github.com/sourcegraph/sourcegraph/lib v0.0.0-20221216004406-749998a2ac74 diff --git a/dashboard-lib/go.mod b/dashboard-lib/go.mod index 10270853ed..f115486231 100644 --- a/dashboard-lib/go.mod +++ b/dashboard-lib/go.mod @@ -23,3 +23,5 @@ require ( github.com/stretchr/testify v1.9.0 // indirect golang.org/x/sys v0.16.0 // indirect ) + +exclude github.com/sourcegraph/sourcegraph/lib v0.0.0-20221216004406-749998a2ac74 diff --git a/go.mod b/go.mod index 64c460303b..0c6c29d0e6 100644 --- a/go.mod +++ b/go.mod @@ -367,3 +367,5 @@ replace ( // until merged upstream: https://github.com/mwitkow/grpc-proxy/pull/69 github.com/mwitkow/grpc-proxy => github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f ) + +exclude github.com/sourcegraph/sourcegraph/lib v0.0.0-20221216004406-749998a2ac74 diff --git a/integration-tests/actions/actions.go b/integration-tests/actions/actions.go index 73365da443..6f7a301f2f 100644 --- a/integration-tests/actions/actions.go +++ b/integration-tests/actions/actions.go @@ -22,11 +22,11 @@ import ( "github.com/ethereum/go-ethereum/rpc" "go.uber.org/zap/zapcore" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/testreporters" - "github.com/smartcontractkit/chainlink-testing-framework/utils/conversions" + "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/environment" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/testreporters" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/conversions" "github.com/smartcontractkit/chainlink/integration-tests/contracts" ethContracts "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" @@ -47,8 +47,8 @@ import ( "github.com/pkg/errors" "github.com/test-go/testify/require" - ctfconfig "github.com/smartcontractkit/chainlink-testing-framework/config" - "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" + ctfconfig "github.com/smartcontractkit/chainlink-testing-framework/lib/config" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/types/config/node" diff --git a/integration-tests/actions/automation_ocr_helpers.go b/integration-tests/actions/automation_ocr_helpers.go index 866d1078a6..9157faf202 100644 --- a/integration-tests/actions/automation_ocr_helpers.go +++ b/integration-tests/actions/automation_ocr_helpers.go @@ -26,7 +26,7 @@ import ( ocr2keepers20config "github.com/smartcontractkit/chainlink-automation/pkg/v2/config" ocr2keepers30config "github.com/smartcontractkit/chainlink-automation/pkg/v3/config" - "github.com/smartcontractkit/chainlink-testing-framework/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/contracts" diff --git a/integration-tests/actions/automationv2/actions.go b/integration-tests/actions/automationv2/actions.go index c0d751b96c..d3504b8fb1 100644 --- a/integration-tests/actions/automationv2/actions.go +++ b/integration-tests/actions/automationv2/actions.go @@ -44,9 +44,9 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/keystore/chaintype" "github.com/smartcontractkit/chainlink/v2/core/store/models" - ctf_concurrency "github.com/smartcontractkit/chainlink-testing-framework/concurrency" - ctfTestEnv "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env" - "github.com/smartcontractkit/chainlink-testing-framework/logging" + ctf_concurrency "github.com/smartcontractkit/chainlink-testing-framework/lib/concurrency" + ctfTestEnv "github.com/smartcontractkit/chainlink-testing-framework/lib/docker/test_env" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" ) type NodeDetails struct { diff --git a/integration-tests/actions/keeper_helpers.go b/integration-tests/actions/keeper_helpers.go index 84353ff9b2..d5bb3462f1 100644 --- a/integration-tests/actions/keeper_helpers.go +++ b/integration-tests/actions/keeper_helpers.go @@ -14,8 +14,8 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/seth" - ctf_concurrency "github.com/smartcontractkit/chainlink-testing-framework/concurrency" - "github.com/smartcontractkit/chainlink-testing-framework/logging" + ctf_concurrency "github.com/smartcontractkit/chainlink-testing-framework/lib/concurrency" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" "github.com/ethereum/go-ethereum/common" diff --git a/integration-tests/actions/ocr2_helpers.go b/integration-tests/actions/ocr2_helpers.go index 0f8dd9b29f..f487368dfd 100644 --- a/integration-tests/actions/ocr2_helpers.go +++ b/integration-tests/actions/ocr2_helpers.go @@ -18,7 +18,7 @@ import ( "github.com/smartcontractkit/libocr/offchainreporting2plus/confighelper" "github.com/smartcontractkit/libocr/offchainreporting2plus/types" - ctfClient "github.com/smartcontractkit/chainlink-testing-framework/client" + ctfClient "github.com/smartcontractkit/chainlink-testing-framework/lib/client" "github.com/smartcontractkit/chainlink/v2/core/services/job" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/chaintype" diff --git a/integration-tests/actions/ocr2_helpers_local.go b/integration-tests/actions/ocr2_helpers_local.go index 4be6c47667..692d9502e1 100644 --- a/integration-tests/actions/ocr2_helpers_local.go +++ b/integration-tests/actions/ocr2_helpers_local.go @@ -19,7 +19,7 @@ import ( "gopkg.in/guregu/null.v4" "github.com/smartcontractkit/chainlink-common/pkg/codec" - "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env" + "github.com/smartcontractkit/chainlink-testing-framework/lib/docker/test_env" evmtypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types" diff --git a/integration-tests/actions/ocr_helpers.go b/integration-tests/actions/ocr_helpers.go index b0292dc518..19cad817b7 100644 --- a/integration-tests/actions/ocr_helpers.go +++ b/integration-tests/actions/ocr_helpers.go @@ -17,7 +17,7 @@ import ( "github.com/stretchr/testify/require" "golang.org/x/sync/errgroup" - ctfClient "github.com/smartcontractkit/chainlink-testing-framework/client" + ctfClient "github.com/smartcontractkit/chainlink-testing-framework/lib/client" "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/contracts" diff --git a/integration-tests/actions/ocr_helpers_local.go b/integration-tests/actions/ocr_helpers_local.go index 0b415277f2..b546139dc3 100644 --- a/integration-tests/actions/ocr_helpers_local.go +++ b/integration-tests/actions/ocr_helpers_local.go @@ -10,7 +10,7 @@ import ( "github.com/google/uuid" "golang.org/x/sync/errgroup" - "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env" + "github.com/smartcontractkit/chainlink-testing-framework/lib/docker/test_env" "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/contracts" diff --git a/integration-tests/actions/private_network.go b/integration-tests/actions/private_network.go index f10371d41a..40fe317ab3 100644 --- a/integration-tests/actions/private_network.go +++ b/integration-tests/actions/private_network.go @@ -3,9 +3,9 @@ package actions import ( "github.com/rs/zerolog" - ctf_config "github.com/smartcontractkit/chainlink-testing-framework/config" - ctf_config_types "github.com/smartcontractkit/chainlink-testing-framework/config/types" - ctf_test_env "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env" + ctf_config "github.com/smartcontractkit/chainlink-testing-framework/lib/config" + ctf_config_types "github.com/smartcontractkit/chainlink-testing-framework/lib/config/types" + ctf_test_env "github.com/smartcontractkit/chainlink-testing-framework/lib/docker/test_env" ) func EthereumNetworkConfigFromConfig(l zerolog.Logger, config ctf_config.GlobalTestConfig) (network ctf_test_env.EthereumNetwork, err error) { diff --git a/integration-tests/actions/refund.go b/integration-tests/actions/refund.go index d49b74c699..1835d9a04a 100644 --- a/integration-tests/actions/refund.go +++ b/integration-tests/actions/refund.go @@ -19,7 +19,7 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/seth" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" + "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" clClient "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/contracts" diff --git a/integration-tests/actions/vrf/common/actions.go b/integration-tests/actions/vrf/common/actions.go index 1fcba02fa7..7d9feb275c 100644 --- a/integration-tests/actions/vrf/common/actions.go +++ b/integration-tests/actions/vrf/common/actions.go @@ -18,9 +18,9 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/seth" - ctf_test_env "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env" - "github.com/smartcontractkit/chainlink-testing-framework/utils/conversions" - seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" + ctf_test_env "github.com/smartcontractkit/chainlink-testing-framework/lib/docker/test_env" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/conversions" + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/seth" "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/client" diff --git a/integration-tests/actions/vrf/vrfv2/contract_steps.go b/integration-tests/actions/vrf/vrfv2/contract_steps.go index 053b06758d..bab4de8624 100644 --- a/integration-tests/actions/vrf/vrfv2/contract_steps.go +++ b/integration-tests/actions/vrf/vrfv2/contract_steps.go @@ -13,7 +13,7 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/seth" - "github.com/smartcontractkit/chainlink-testing-framework/utils/conversions" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/conversions" "github.com/smartcontractkit/chainlink/integration-tests/actions" vrfcommon "github.com/smartcontractkit/chainlink/integration-tests/actions/vrf/common" "github.com/smartcontractkit/chainlink/integration-tests/client" diff --git a/integration-tests/actions/vrf/vrfv2/setup_steps.go b/integration-tests/actions/vrf/vrfv2/setup_steps.go index 25b1f4c077..6f1edc6b04 100644 --- a/integration-tests/actions/vrf/vrfv2/setup_steps.go +++ b/integration-tests/actions/vrf/vrfv2/setup_steps.go @@ -8,7 +8,7 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/seth" - seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/seth" "github.com/ethereum/go-ethereum/common" "github.com/rs/zerolog" @@ -16,7 +16,7 @@ import ( "github.com/google/uuid" - "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" testconfig "github.com/smartcontractkit/chainlink/integration-tests/testconfig/vrfv2" diff --git a/integration-tests/actions/vrf/vrfv2plus/contract_steps.go b/integration-tests/actions/vrf/vrfv2plus/contract_steps.go index 882bd97792..6aa9ef6c70 100644 --- a/integration-tests/actions/vrf/vrfv2plus/contract_steps.go +++ b/integration-tests/actions/vrf/vrfv2plus/contract_steps.go @@ -13,7 +13,7 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/seth" - "github.com/smartcontractkit/chainlink-testing-framework/utils/conversions" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/conversions" "github.com/smartcontractkit/chainlink/integration-tests/actions" vrfcommon "github.com/smartcontractkit/chainlink/integration-tests/actions/vrf/common" "github.com/smartcontractkit/chainlink/integration-tests/client" diff --git a/integration-tests/actions/vrf/vrfv2plus/setup_steps.go b/integration-tests/actions/vrf/vrfv2plus/setup_steps.go index b7698e6429..caa5e26a69 100644 --- a/integration-tests/actions/vrf/vrfv2plus/setup_steps.go +++ b/integration-tests/actions/vrf/vrfv2plus/setup_steps.go @@ -8,7 +8,7 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/seth" - seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/seth" "github.com/shopspring/decimal" "golang.org/x/sync/errgroup" @@ -17,8 +17,8 @@ import ( "github.com/google/uuid" "github.com/rs/zerolog" - "github.com/smartcontractkit/chainlink-testing-framework/utils/conversions" - "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/conversions" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" "github.com/smartcontractkit/chainlink/integration-tests/actions" vrfcommon "github.com/smartcontractkit/chainlink/integration-tests/actions/vrf/common" tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" diff --git a/integration-tests/benchmark/keeper_test.go b/integration-tests/benchmark/keeper_test.go index 177b352101..7c947d0b64 100644 --- a/integration-tests/benchmark/keeper_test.go +++ b/integration-tests/benchmark/keeper_test.go @@ -9,16 +9,16 @@ import ( "github.com/stretchr/testify/require" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - ctf_config "github.com/smartcontractkit/chainlink-testing-framework/config" - env_client "github.com/smartcontractkit/chainlink-testing-framework/k8s/client" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/chainlink" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/ethereum" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/reorg" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/networks" - seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" + "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" + ctf_config "github.com/smartcontractkit/chainlink-testing-framework/lib/config" + env_client "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/client" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/environment" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/pkg/helm/chainlink" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/pkg/helm/ethereum" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/pkg/helm/reorg" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/networks" + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/seth" "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/contracts" diff --git a/integration-tests/ccip-tests/actions/ccip_helpers.go b/integration-tests/ccip-tests/actions/ccip_helpers.go index e07a97dbf2..15a737c031 100644 --- a/integration-tests/ccip-tests/actions/ccip_helpers.go +++ b/integration-tests/ccip-tests/actions/ccip_helpers.go @@ -31,19 +31,19 @@ import ( "golang.org/x/exp/rand" "golang.org/x/sync/errgroup" - "github.com/smartcontractkit/chainlink-testing-framework/utils/ptr" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/ptr" chainselectors "github.com/smartcontractkit/chain-selectors" commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - ctfClient "github.com/smartcontractkit/chainlink-testing-framework/client" - ctftestenv "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/foundry" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/mockserver" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/reorg" - "github.com/smartcontractkit/chainlink-testing-framework/networks" + "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" + ctfClient "github.com/smartcontractkit/chainlink-testing-framework/lib/client" + ctftestenv "github.com/smartcontractkit/chainlink-testing-framework/lib/docker/test_env" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/environment" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/pkg/helm/foundry" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/pkg/helm/mockserver" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/pkg/helm/reorg" + "github.com/smartcontractkit/chainlink-testing-framework/lib/networks" "github.com/smartcontractkit/chainlink/integration-tests/ccip-tests/contracts" "github.com/smartcontractkit/chainlink/integration-tests/ccip-tests/contracts/laneconfig" "github.com/smartcontractkit/chainlink/integration-tests/ccip-tests/testconfig" diff --git a/integration-tests/ccip-tests/actions/lm_helpers.go b/integration-tests/ccip-tests/actions/lm_helpers.go index 1ec02e313f..b7e9419ff2 100644 --- a/integration-tests/ccip-tests/actions/lm_helpers.go +++ b/integration-tests/ccip-tests/actions/lm_helpers.go @@ -5,7 +5,7 @@ import ( "github.com/ethereum/go-ethereum/common" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" + "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" "github.com/smartcontractkit/chainlink/integration-tests/ccip-tests/contracts" ) diff --git a/integration-tests/ccip-tests/actions/reorg_helpers.go b/integration-tests/ccip-tests/actions/reorg_helpers.go index eb7751b822..017b8ffab6 100644 --- a/integration-tests/ccip-tests/actions/reorg_helpers.go +++ b/integration-tests/ccip-tests/actions/reorg_helpers.go @@ -8,7 +8,7 @@ import ( "github.com/rs/zerolog" "github.com/stretchr/testify/assert" - "github.com/smartcontractkit/chainlink-testing-framework/client" + "github.com/smartcontractkit/chainlink-testing-framework/lib/client" ) // ReorgSuite is a test suite that generates reorgs on source/dest chains diff --git a/integration-tests/ccip-tests/chaos/ccip_test.go b/integration-tests/ccip-tests/chaos/ccip_test.go index 4b1dda7a91..125e683dc5 100644 --- a/integration-tests/ccip-tests/chaos/ccip_test.go +++ b/integration-tests/ccip-tests/chaos/ccip_test.go @@ -7,9 +7,9 @@ import ( "github.com/stretchr/testify/require" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/chaos" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/utils/ptr" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/chaos" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/ptr" "github.com/smartcontractkit/chainlink/integration-tests/ccip-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/ccip-tests/testconfig" diff --git a/integration-tests/ccip-tests/contracts/contract_deployer.go b/integration-tests/ccip-tests/contracts/contract_deployer.go index c051531fb9..211bbc1ebb 100644 --- a/integration-tests/ccip-tests/contracts/contract_deployer.go +++ b/integration-tests/ccip-tests/contracts/contract_deployer.go @@ -22,7 +22,7 @@ import ( ocrtypes2 "github.com/smartcontractkit/libocr/offchainreporting2/types" "github.com/smartcontractkit/chainlink-common/pkg/config" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" + "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/contracts" diff --git a/integration-tests/ccip-tests/contracts/contract_models.go b/integration-tests/ccip-tests/contracts/contract_models.go index 9b59ce4008..e3f6e45fad 100644 --- a/integration-tests/ccip-tests/contracts/contract_models.go +++ b/integration-tests/ccip-tests/contracts/contract_models.go @@ -17,7 +17,7 @@ import ( "github.com/rs/zerolog" "golang.org/x/exp/rand" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" + "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" "github.com/smartcontractkit/chainlink/integration-tests/wrappers" diff --git a/integration-tests/ccip-tests/contracts/lm_contracts.go b/integration-tests/ccip-tests/contracts/lm_contracts.go index 2ee5078aa7..521324c11b 100644 --- a/integration-tests/ccip-tests/contracts/lm_contracts.go +++ b/integration-tests/ccip-tests/contracts/lm_contracts.go @@ -11,7 +11,7 @@ import ( "github.com/smartcontractkit/chainlink/integration-tests/wrappers" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" + "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_proxy_contract" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/liquiditymanager/generated/arbitrum_l1_bridge_adapter" diff --git a/integration-tests/ccip-tests/contracts/multicall.go b/integration-tests/ccip-tests/contracts/multicall.go index 7db7f37519..094a6152be 100644 --- a/integration-tests/ccip-tests/contracts/multicall.go +++ b/integration-tests/ccip-tests/contracts/multicall.go @@ -13,7 +13,7 @@ import ( "github.com/pkg/errors" "github.com/rs/zerolog/log" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" + "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/shared/generated/erc20" diff --git a/integration-tests/ccip-tests/load/ccip_loadgen.go b/integration-tests/ccip-tests/load/ccip_loadgen.go index 4ed54a45fd..9dc8ce16e5 100644 --- a/integration-tests/ccip-tests/load/ccip_loadgen.go +++ b/integration-tests/ccip-tests/load/ccip_loadgen.go @@ -15,10 +15,11 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/rs/zerolog" chain_selectors "github.com/smartcontractkit/chain-selectors" - "github.com/smartcontractkit/wasp" "github.com/stretchr/testify/require" "go.uber.org/atomic" + "github.com/smartcontractkit/chainlink-testing-framework/wasp" + "github.com/smartcontractkit/chainlink-common/pkg/config" "github.com/smartcontractkit/chainlink/integration-tests/ccip-tests/testconfig" diff --git a/integration-tests/ccip-tests/load/ccip_multicall_loadgen.go b/integration-tests/ccip-tests/load/ccip_multicall_loadgen.go index ad3960dee2..04fcffaa4b 100644 --- a/integration-tests/ccip-tests/load/ccip_multicall_loadgen.go +++ b/integration-tests/ccip-tests/load/ccip_multicall_loadgen.go @@ -12,10 +12,11 @@ import ( "golang.org/x/sync/errgroup" chain_selectors "github.com/smartcontractkit/chain-selectors" - "github.com/smartcontractkit/wasp" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - "github.com/smartcontractkit/chainlink-testing-framework/logging" + "github.com/smartcontractkit/chainlink-testing-framework/wasp" + + "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" "github.com/smartcontractkit/chainlink/integration-tests/ccip-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/ccip-tests/contracts" diff --git a/integration-tests/ccip-tests/load/ccip_test.go b/integration-tests/ccip-tests/load/ccip_test.go index 0d14549ec9..a8297dd209 100644 --- a/integration-tests/ccip-tests/load/ccip_test.go +++ b/integration-tests/ccip-tests/load/ccip_test.go @@ -8,9 +8,9 @@ import ( "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink-common/pkg/config" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/chaos" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/utils/ptr" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/chaos" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/ptr" "github.com/smartcontractkit/chainlink/integration-tests/ccip-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/ccip-tests/testsetups" diff --git a/integration-tests/ccip-tests/load/helper.go b/integration-tests/ccip-tests/load/helper.go index dbb5ffc3e9..f38186f817 100644 --- a/integration-tests/ccip-tests/load/helper.go +++ b/integration-tests/ccip-tests/load/helper.go @@ -12,15 +12,16 @@ import ( "github.com/AlekSi/pointer" "github.com/rs/zerolog" - "github.com/smartcontractkit/wasp" "github.com/stretchr/testify/require" "go.uber.org/atomic" "golang.org/x/sync/errgroup" + "github.com/smartcontractkit/chainlink-testing-framework/wasp" + "github.com/smartcontractkit/chainlink-common/pkg/config" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/chaos" - "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/chaos" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" "github.com/smartcontractkit/chainlink/integration-tests/ccip-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/ccip-tests/testconfig" diff --git a/integration-tests/ccip-tests/smoke/ccip_test.go b/integration-tests/ccip-tests/smoke/ccip_test.go index 37cc4ea394..c07d0216a7 100644 --- a/integration-tests/ccip-tests/smoke/ccip_test.go +++ b/integration-tests/ccip-tests/smoke/ccip_test.go @@ -11,8 +11,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/utils/ptr" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/ptr" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/evm_2_evm_onramp" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/lock_release_token_pool" diff --git a/integration-tests/ccip-tests/smoke/lm_test.go b/integration-tests/ccip-tests/smoke/lm_test.go index 9ac55b1612..45337426a0 100644 --- a/integration-tests/ccip-tests/smoke/lm_test.go +++ b/integration-tests/ccip-tests/smoke/lm_test.go @@ -6,7 +6,7 @@ import ( "github.com/stretchr/testify/require" - "github.com/smartcontractkit/chainlink-testing-framework/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" "github.com/smartcontractkit/chainlink/integration-tests/ccip-tests/testconfig" "github.com/smartcontractkit/chainlink/integration-tests/ccip-tests/testsetups" diff --git a/integration-tests/ccip-tests/testconfig/ccip.go b/integration-tests/ccip-tests/testconfig/ccip.go index 9dc416da56..a3e322b70a 100644 --- a/integration-tests/ccip-tests/testconfig/ccip.go +++ b/integration-tests/ccip-tests/testconfig/ccip.go @@ -10,8 +10,8 @@ import ( "github.com/rs/zerolog" "github.com/smartcontractkit/chainlink-common/pkg/config" - ctfconfig "github.com/smartcontractkit/chainlink-testing-framework/config" - ctfK8config "github.com/smartcontractkit/chainlink-testing-framework/k8s/config" + ctfconfig "github.com/smartcontractkit/chainlink-testing-framework/lib/config" + ctfK8config "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/config" ccipcontracts "github.com/smartcontractkit/chainlink/integration-tests/ccip-tests/contracts" testutils "github.com/smartcontractkit/chainlink/integration-tests/ccip-tests/utils" diff --git a/integration-tests/ccip-tests/testconfig/global.go b/integration-tests/ccip-tests/testconfig/global.go index e8d955fae9..2545bb83ca 100644 --- a/integration-tests/ccip-tests/testconfig/global.go +++ b/integration-tests/ccip-tests/testconfig/global.go @@ -15,15 +15,15 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/seth" - "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/networks" + "github.com/smartcontractkit/chainlink-testing-framework/lib/docker/test_env" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/networks" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - "github.com/smartcontractkit/chainlink-testing-framework/utils/osutil" + "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/osutil" "github.com/smartcontractkit/chainlink-common/pkg/config" - ctfconfig "github.com/smartcontractkit/chainlink-testing-framework/config" + ctfconfig "github.com/smartcontractkit/chainlink-testing-framework/lib/config" "github.com/smartcontractkit/chainlink/integration-tests/client" ) @@ -343,10 +343,6 @@ func (p *Common) Validate() error { // read the default network config, if specified p.Network.UpperCaseNetworkNames() p.Network.OverrideURLsAndKeysFromEVMNetwork() - err := p.Network.Default() - if err != nil { - return fmt.Errorf("error reading default network config %w", err) - } if err := p.Network.Validate(); err != nil { return fmt.Errorf("error validating networks config %w", err) } diff --git a/integration-tests/ccip-tests/testreporters/ccip.go b/integration-tests/ccip-tests/testreporters/ccip.go index b567f6a629..d9c2908304 100644 --- a/integration-tests/ccip-tests/testreporters/ccip.go +++ b/integration-tests/ccip-tests/testreporters/ccip.go @@ -13,8 +13,8 @@ import ( "github.com/rs/zerolog" "github.com/slack-go/slack" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/config" - "github.com/smartcontractkit/chainlink-testing-framework/testreporters" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/config" + "github.com/smartcontractkit/chainlink-testing-framework/lib/testreporters" ) type Phase string diff --git a/integration-tests/ccip-tests/testsetups/ccip.go b/integration-tests/ccip-tests/testsetups/ccip.go index 6e3ee5b7e8..75a32f8b9e 100644 --- a/integration-tests/ccip-tests/testsetups/ccip.go +++ b/integration-tests/ccip-tests/testsetups/ccip.go @@ -27,15 +27,15 @@ import ( chainselectors "github.com/smartcontractkit/chain-selectors" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - ctfClient "github.com/smartcontractkit/chainlink-testing-framework/client" - ctfconfig "github.com/smartcontractkit/chainlink-testing-framework/config" - ctfconfigtypes "github.com/smartcontractkit/chainlink-testing-framework/config/types" - ctftestenv "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/config" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment" - "github.com/smartcontractkit/chainlink-testing-framework/networks" - "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" + "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" + ctfClient "github.com/smartcontractkit/chainlink-testing-framework/lib/client" + ctfconfig "github.com/smartcontractkit/chainlink-testing-framework/lib/config" + ctfconfigtypes "github.com/smartcontractkit/chainlink-testing-framework/lib/config/types" + ctftestenv "github.com/smartcontractkit/chainlink-testing-framework/lib/docker/test_env" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/config" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/environment" + "github.com/smartcontractkit/chainlink-testing-framework/lib/networks" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" integrationactions "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/ccip-tests/actions" diff --git a/integration-tests/ccip-tests/testsetups/lm_setup.go b/integration-tests/ccip-tests/testsetups/lm_setup.go index 9884d9661c..a7e7f88d13 100644 --- a/integration-tests/ccip-tests/testsetups/lm_setup.go +++ b/integration-tests/ccip-tests/testsetups/lm_setup.go @@ -42,10 +42,10 @@ import ( integrationactions "github.com/smartcontractkit/chainlink/integration-tests/actions" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - ctfClient "github.com/smartcontractkit/chainlink-testing-framework/client" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/config" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment" + "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" + ctfClient "github.com/smartcontractkit/chainlink-testing-framework/lib/client" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/config" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/environment" "github.com/smartcontractkit/chainlink/integration-tests/ccip-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/ccip-tests/contracts" diff --git a/integration-tests/ccip-tests/testsetups/test_env.go b/integration-tests/ccip-tests/testsetups/test_env.go index 1eb7ebd452..e7c77fbf41 100644 --- a/integration-tests/ccip-tests/testsetups/test_env.go +++ b/integration-tests/ccip-tests/testsetups/test_env.go @@ -13,24 +13,24 @@ import ( "github.com/rs/zerolog" "github.com/stretchr/testify/require" - ctfconfig "github.com/smartcontractkit/chainlink-testing-framework/config" - ctfconfigtypes "github.com/smartcontractkit/chainlink-testing-framework/config/types" - "github.com/smartcontractkit/chainlink-testing-framework/networks" - "github.com/smartcontractkit/chainlink-testing-framework/utils/conversions" + ctfconfig "github.com/smartcontractkit/chainlink-testing-framework/lib/config" + ctfconfigtypes "github.com/smartcontractkit/chainlink-testing-framework/lib/config/types" + "github.com/smartcontractkit/chainlink-testing-framework/lib/networks" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/conversions" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/foundry" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/pkg/helm/foundry" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/mockserver" - mockservercfg "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/mockserver-cfg" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/pkg/helm/mockserver" + mockservercfg "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/pkg/helm/mockserver-cfg" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - ctftestenv "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/chainlink" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/reorg" + "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" + ctftestenv "github.com/smartcontractkit/chainlink-testing-framework/lib/docker/test_env" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/environment" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/pkg/helm/chainlink" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/pkg/helm/reorg" "github.com/smartcontractkit/chainlink-common/pkg/config" - k8config "github.com/smartcontractkit/chainlink-testing-framework/k8s/config" + k8config "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/config" "github.com/smartcontractkit/chainlink/integration-tests/ccip-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/ccip-tests/types/config/node" diff --git a/integration-tests/ccip-tests/types/config/node/core.go b/integration-tests/ccip-tests/types/config/node/core.go index eb12598f94..5c9defbbb5 100644 --- a/integration-tests/ccip-tests/types/config/node/core.go +++ b/integration-tests/ccip-tests/types/config/node/core.go @@ -5,8 +5,8 @@ import ( "fmt" "math/big" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - "github.com/smartcontractkit/chainlink-testing-framework/utils/ptr" + "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/ptr" "github.com/smartcontractkit/chainlink-common/pkg/config" diff --git a/integration-tests/chaos/automation_chaos_test.go b/integration-tests/chaos/automation_chaos_test.go index 467f371ad1..59b52f8e0f 100644 --- a/integration-tests/chaos/automation_chaos_test.go +++ b/integration-tests/chaos/automation_chaos_test.go @@ -11,21 +11,21 @@ import ( ocr2keepers30config "github.com/smartcontractkit/chainlink-automation/pkg/v3/config" "github.com/smartcontractkit/chainlink/integration-tests/actions/automationv2" - seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/seth" "github.com/onsi/gomega" "github.com/stretchr/testify/require" "go.uber.org/zap/zapcore" - ctf_config "github.com/smartcontractkit/chainlink-testing-framework/config" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/chaos" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/chainlink" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/ethereum" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/networks" - "github.com/smartcontractkit/chainlink-testing-framework/utils/ptr" - "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" + ctf_config "github.com/smartcontractkit/chainlink-testing-framework/lib/config" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/chaos" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/environment" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/pkg/helm/chainlink" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/pkg/helm/ethereum" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/networks" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/ptr" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/client" diff --git a/integration-tests/chaos/ocr_chaos_test.go b/integration-tests/chaos/ocr_chaos_test.go index 052726afda..89417d782d 100644 --- a/integration-tests/chaos/ocr_chaos_test.go +++ b/integration-tests/chaos/ocr_chaos_test.go @@ -9,19 +9,19 @@ import ( "github.com/onsi/gomega" "github.com/stretchr/testify/require" - ctfClient "github.com/smartcontractkit/chainlink-testing-framework/client" - ctf_config "github.com/smartcontractkit/chainlink-testing-framework/config" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/chaos" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/chainlink" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/ethereum" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/mockserver" - mockservercfg "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/mockserver-cfg" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/networks" - "github.com/smartcontractkit/chainlink-testing-framework/utils/ptr" - seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" - "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" + ctfClient "github.com/smartcontractkit/chainlink-testing-framework/lib/client" + ctf_config "github.com/smartcontractkit/chainlink-testing-framework/lib/config" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/chaos" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/environment" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/pkg/helm/chainlink" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/pkg/helm/ethereum" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/pkg/helm/mockserver" + mockservercfg "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/pkg/helm/mockserver-cfg" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/networks" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/ptr" + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/seth" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/client" @@ -84,7 +84,7 @@ func TestOCRChaos(t *testing.T) { // and chaos.NewNetworkPartition method (https://chaos-mesh.org/docs/simulate-network-chaos-on-kubernetes/) // in order to regenerate Go bindings if k8s version will be updated // you can pull new CRD spec from your current cluster and check README here - // https://github.com/smartcontractkit/chainlink-testing-framework/k8s/blob/master/README.md + // https://github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/blob/master/README.md NetworkChaosFailMajorityNetwork: { ethereum.New(nil), chainlinkCfg, diff --git a/integration-tests/citool/cmd/create_test_config_cmd.go b/integration-tests/citool/cmd/create_test_config_cmd.go index 518a041318..3a285a4e98 100644 --- a/integration-tests/citool/cmd/create_test_config_cmd.go +++ b/integration-tests/citool/cmd/create_test_config_cmd.go @@ -7,8 +7,8 @@ import ( "github.com/pelletier/go-toml/v2" "github.com/spf13/cobra" - ctfconfig "github.com/smartcontractkit/chainlink-testing-framework/config" - ctfconfigtypes "github.com/smartcontractkit/chainlink-testing-framework/config/types" + ctfconfig "github.com/smartcontractkit/chainlink-testing-framework/lib/config" + ctfconfigtypes "github.com/smartcontractkit/chainlink-testing-framework/lib/config/types" ) var createTestConfigCmd = &cobra.Command{ diff --git a/integration-tests/citool/cmd/filter_cmd.go b/integration-tests/citool/cmd/filter_cmd.go index c1d5f22357..5d1d41cb9d 100644 --- a/integration-tests/citool/cmd/filter_cmd.go +++ b/integration-tests/citool/cmd/filter_cmd.go @@ -12,7 +12,7 @@ import ( "github.com/spf13/cobra" "gopkg.in/yaml.v2" - "github.com/smartcontractkit/chainlink-testing-framework/utils" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils" ) // Filter tests based on workflow, test type, and test IDs. diff --git a/integration-tests/citool/cmd/test_config_cmd.go b/integration-tests/citool/cmd/test_config_cmd.go index 0c0e272353..3d0766ca0c 100644 --- a/integration-tests/citool/cmd/test_config_cmd.go +++ b/integration-tests/citool/cmd/test_config_cmd.go @@ -5,7 +5,7 @@ import ( "github.com/spf13/cobra" - "github.com/smartcontractkit/chainlink-testing-framework/utils" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils" ) var testConfigCmd = &cobra.Command{ diff --git a/integration-tests/citool/cmd/test_config_cmd_test.go b/integration-tests/citool/cmd/test_config_cmd_test.go index 3fcc25fd17..4e710d06f6 100644 --- a/integration-tests/citool/cmd/test_config_cmd_test.go +++ b/integration-tests/citool/cmd/test_config_cmd_test.go @@ -8,8 +8,8 @@ import ( "github.com/spf13/cobra" "github.com/stretchr/testify/assert" - ctf_config "github.com/smartcontractkit/chainlink-testing-framework/config" - ctfconfigtypes "github.com/smartcontractkit/chainlink-testing-framework/config/types" + ctf_config "github.com/smartcontractkit/chainlink-testing-framework/lib/config" + ctfconfigtypes "github.com/smartcontractkit/chainlink-testing-framework/lib/config/types" ) func TestCreateTestConfigCmd(t *testing.T) { diff --git a/integration-tests/client/chainlink_k8s.go b/integration-tests/client/chainlink_k8s.go index 794e93f727..969e060ca1 100644 --- a/integration-tests/client/chainlink_k8s.go +++ b/integration-tests/client/chainlink_k8s.go @@ -7,7 +7,7 @@ import ( "github.com/rs/zerolog/log" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/environment" ) const ( diff --git a/integration-tests/contracts/ethereum/OffchainAggregatorEventsMock.go b/integration-tests/contracts/ethereum/OffchainAggregatorEventsMock.go index 86963e01a4..1006daa034 100644 --- a/integration-tests/contracts/ethereum/OffchainAggregatorEventsMock.go +++ b/integration-tests/contracts/ethereum/OffchainAggregatorEventsMock.go @@ -15,6 +15,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/event" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated" ) diff --git a/integration-tests/contracts/ethereum/StakingEventsMock.go b/integration-tests/contracts/ethereum/StakingEventsMock.go index 5a1a1663ba..b3b695ea30 100644 --- a/integration-tests/contracts/ethereum/StakingEventsMock.go +++ b/integration-tests/contracts/ethereum/StakingEventsMock.go @@ -15,6 +15,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/event" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated" ) diff --git a/integration-tests/contracts/ethereum_contracts_automation.go b/integration-tests/contracts/ethereum_contracts_automation.go index b15cb6c172..02132b1a12 100644 --- a/integration-tests/contracts/ethereum_contracts_automation.go +++ b/integration-tests/contracts/ethereum_contracts_automation.go @@ -20,8 +20,8 @@ import ( cltypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" registrylogicc23 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/automation_registry_logic_c_wrapper_2_3" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - "github.com/smartcontractkit/chainlink-testing-framework/networks" + "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" + "github.com/smartcontractkit/chainlink-testing-framework/lib/networks" "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" eth_contracts "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" "github.com/smartcontractkit/chainlink/integration-tests/testreporters" diff --git a/integration-tests/contracts/ethereum_vrf_contracts.go b/integration-tests/contracts/ethereum_vrf_contracts.go index 8fcd6c7bfa..71da9baa36 100644 --- a/integration-tests/contracts/ethereum_vrf_contracts.go +++ b/integration-tests/contracts/ethereum_vrf_contracts.go @@ -17,7 +17,7 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/seth" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" + "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" "github.com/smartcontractkit/chainlink/integration-tests/wrappers" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/batch_blockhash_store" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/blockhash_store" diff --git a/integration-tests/crib/chaos.go b/integration-tests/crib/chaos.go index bbf6ca681c..985ca2dc2d 100644 --- a/integration-tests/crib/chaos.go +++ b/integration-tests/crib/chaos.go @@ -3,17 +3,18 @@ package crib import ( "time" + "github.com/smartcontractkit/chainlink-testing-framework/havoc" + "github.com/chaos-mesh/chaos-mesh/api/v1alpha1" - "github.com/smartcontractkit/havoc/k8schaos" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) -func rebootCLNamespace(delay time.Duration, namespace string) (*k8schaos.Chaos, error) { - k8sClient, err := k8schaos.NewChaosMeshClient() +func rebootCLNamespace(delay time.Duration, namespace string) (*havoc.Chaos, error) { + k8sClient, err := havoc.NewChaosMeshClient() if err != nil { return nil, err } - return k8schaos.NewChaos(k8schaos.ChaosOpts{ + return havoc.NewChaos(havoc.ChaosOpts{ Description: "Reboot CRIB", DelayCreate: delay, Object: &v1alpha1.PodChaos{ @@ -40,6 +41,6 @@ func rebootCLNamespace(delay time.Duration, namespace string) (*k8schaos.Chaos, }, }, Client: k8sClient, - Logger: &k8schaos.Logger, + Logger: &havoc.Logger, }) } diff --git a/integration-tests/crib/connect.go b/integration-tests/crib/connect.go index f8ab8db282..3289ed52c4 100644 --- a/integration-tests/crib/connect.go +++ b/integration-tests/crib/connect.go @@ -10,12 +10,12 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/seth" - "github.com/smartcontractkit/chainlink-testing-framework/utils/ptr" - seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/ptr" + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/seth" tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - msClient "github.com/smartcontractkit/chainlink-testing-framework/client" + "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" + msClient "github.com/smartcontractkit/chainlink-testing-framework/lib/client" "github.com/smartcontractkit/chainlink/integration-tests/client" ) diff --git a/integration-tests/crib/ocr_test.go b/integration-tests/crib/ocr_test.go index b84af02a19..327283c150 100644 --- a/integration-tests/crib/ocr_test.go +++ b/integration-tests/crib/ocr_test.go @@ -6,13 +6,14 @@ import ( "testing" "time" - "github.com/smartcontractkit/havoc/k8schaos" "github.com/stretchr/testify/require" + "github.com/smartcontractkit/chainlink-testing-framework/havoc" + "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/contracts" - "github.com/smartcontractkit/chainlink-testing-framework/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" ) func TestCRIB(t *testing.T) { @@ -38,7 +39,7 @@ func TestCRIB(t *testing.T) { os.Getenv("CRIB_NAMESPACE"), ) ch.Create(context.Background()) - ch.AddListener(k8schaos.NewChaosLogger(l)) + ch.AddListener(havoc.NewChaosLogger(l)) t.Cleanup(func() { err := ch.Delete(context.Background()) require.NoError(t, err) diff --git a/integration-tests/docker/cmd/internal/commands.go b/integration-tests/docker/cmd/internal/commands.go index 9939765f7f..bd9d505a7e 100644 --- a/integration-tests/docker/cmd/internal/commands.go +++ b/integration-tests/docker/cmd/internal/commands.go @@ -8,8 +8,8 @@ import ( "github.com/rs/zerolog/log" "github.com/spf13/cobra" - ctf_test_env "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env" - "github.com/smartcontractkit/chainlink-testing-framework/logging" + ctf_test_env "github.com/smartcontractkit/chainlink-testing-framework/lib/docker/test_env" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" "github.com/smartcontractkit/chainlink/integration-tests/testconfig" ) diff --git a/integration-tests/docker/test_env/cl_node.go b/integration-tests/docker/test_env/cl_node.go index b28d954688..a37a6204f6 100644 --- a/integration-tests/docker/test_env/cl_node.go +++ b/integration-tests/docker/test_env/cl_node.go @@ -21,11 +21,11 @@ import ( tc "github.com/testcontainers/testcontainers-go" tcwait "github.com/testcontainers/testcontainers-go/wait" - "github.com/smartcontractkit/chainlink-testing-framework/docker" - "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/logstream" - "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" + "github.com/smartcontractkit/chainlink-testing-framework/lib/docker" + "github.com/smartcontractkit/chainlink-testing-framework/lib/docker/test_env" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logstream" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/chaintype" diff --git a/integration-tests/docker/test_env/test_env.go b/integration-tests/docker/test_env/test_env.go index 4a7964ddd2..ff891f1b7d 100644 --- a/integration-tests/docker/test_env/test_env.go +++ b/integration-tests/docker/test_env/test_env.go @@ -13,13 +13,13 @@ import ( "github.com/rs/zerolog/log" tc "github.com/testcontainers/testcontainers-go" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - ctf_config "github.com/smartcontractkit/chainlink-testing-framework/config" - "github.com/smartcontractkit/chainlink-testing-framework/docker" - "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/logstream" - "github.com/smartcontractkit/chainlink-testing-framework/utils/runid" + "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" + ctf_config "github.com/smartcontractkit/chainlink-testing-framework/lib/config" + "github.com/smartcontractkit/chainlink-testing-framework/lib/docker" + "github.com/smartcontractkit/chainlink-testing-framework/lib/docker/test_env" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logstream" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/runid" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" diff --git a/integration-tests/docker/test_env/test_env_builder.go b/integration-tests/docker/test_env/test_env_builder.go index 334334036f..249bb8c39a 100644 --- a/integration-tests/docker/test_env/test_env_builder.go +++ b/integration-tests/docker/test_env/test_env_builder.go @@ -12,14 +12,14 @@ import ( "go.uber.org/zap/zapcore" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - ctf_config "github.com/smartcontractkit/chainlink-testing-framework/config" - "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/logstream" - "github.com/smartcontractkit/chainlink-testing-framework/networks" - "github.com/smartcontractkit/chainlink-testing-framework/testreporters" - "github.com/smartcontractkit/chainlink-testing-framework/utils/osutil" + "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" + ctf_config "github.com/smartcontractkit/chainlink-testing-framework/lib/config" + "github.com/smartcontractkit/chainlink-testing-framework/lib/docker/test_env" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logstream" + "github.com/smartcontractkit/chainlink-testing-framework/lib/networks" + "github.com/smartcontractkit/chainlink-testing-framework/lib/testreporters" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/osutil" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/integration-tests/types/config/node" diff --git a/integration-tests/docker/test_env/test_env_config.go b/integration-tests/docker/test_env/test_env_config.go index 9aefa9615c..b29cc3e8b5 100644 --- a/integration-tests/docker/test_env/test_env_config.go +++ b/integration-tests/docker/test_env/test_env_config.go @@ -3,7 +3,7 @@ package test_env import ( "encoding/json" - ctf_config "github.com/smartcontractkit/chainlink-testing-framework/config" + ctf_config "github.com/smartcontractkit/chainlink-testing-framework/lib/config" env "github.com/smartcontractkit/chainlink/integration-tests/types/envcommon" ) diff --git a/integration-tests/experiments/gas_test.go b/integration-tests/experiments/gas_test.go index 4d1f459711..42e408a152 100644 --- a/integration-tests/experiments/gas_test.go +++ b/integration-tests/experiments/gas_test.go @@ -5,12 +5,12 @@ import ( "testing" "time" - seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/seth" "github.com/stretchr/testify/require" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/networks" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/networks" "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/contracts" tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" diff --git a/integration-tests/go.mod b/integration-tests/go.mod index 20f43c4b7b..635332c58e 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -6,16 +6,16 @@ go 1.22.5 replace github.com/smartcontractkit/chainlink/v2 => ../ require ( - dario.cat/mergo v1.0.0 + dario.cat/mergo v1.0.1 github.com/AlekSi/pointer v1.1.0 github.com/Khan/genqlient v0.7.0 github.com/Masterminds/semver/v3 v3.2.1 github.com/avast/retry-go/v4 v4.6.0 github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df - github.com/chaos-mesh/chaos-mesh/api v0.0.0-20240709130330-9f4feec7553f + github.com/chaos-mesh/chaos-mesh/api v0.0.0-20240821051457-da69c6d9617a github.com/cli/go-gh/v2 v2.0.0 github.com/ethereum/go-ethereum v1.13.8 - github.com/fxamacker/cbor/v2 v2.6.0 + github.com/fxamacker/cbor/v2 v2.7.0 github.com/go-resty/resty/v2 v2.11.0 github.com/google/go-cmp v0.6.0 github.com/google/uuid v1.6.0 @@ -27,7 +27,7 @@ require ( github.com/pelletier/go-toml/v2 v2.2.2 github.com/pkg/errors v0.9.1 github.com/prometheus/common v0.55.0 - github.com/rs/zerolog v1.32.0 + github.com/rs/zerolog v1.33.0 github.com/scylladb/go-reflectx v1.0.1 github.com/segmentio/ksuid v1.0.4 github.com/shopspring/decimal v1.4.0 @@ -35,14 +35,14 @@ require ( github.com/smartcontractkit/chain-selectors v1.0.23 github.com/smartcontractkit/chainlink-automation v1.0.4 github.com/smartcontractkit/chainlink-common v0.2.2-0.20240723123524-e407ecd120b1 - github.com/smartcontractkit/chainlink-testing-framework v1.34.10 - github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240405215812-5a72bc9af239 - github.com/smartcontractkit/chainlink-testing-framework/seth v1.2.1-0.20240827112945-bd8c580392d6 + github.com/smartcontractkit/chainlink-testing-framework/havoc v1.50.0 + github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.5 + github.com/smartcontractkit/chainlink-testing-framework/lib/grafana v1.50.0 + github.com/smartcontractkit/chainlink-testing-framework/seth v1.50.2 + github.com/smartcontractkit/chainlink-testing-framework/wasp v1.50.0 github.com/smartcontractkit/chainlink/integration-tests v0.0.0-00010101000000-000000000000 github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000 - github.com/smartcontractkit/havoc/k8schaos v0.0.0-20240409145249-e78d20847e37 github.com/smartcontractkit/libocr v0.0.0-20240717100443-f6226e09bee7 - github.com/smartcontractkit/wasp v0.4.5 github.com/spf13/cobra v1.8.1 github.com/stretchr/testify v1.9.0 github.com/test-go/testify v1.1.4 @@ -51,14 +51,14 @@ require ( go.uber.org/atomic v1.11.0 go.uber.org/multierr v1.11.0 go.uber.org/zap v1.27.0 - golang.org/x/crypto v0.26.0 + golang.org/x/crypto v0.27.0 golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 golang.org/x/sync v0.8.0 - golang.org/x/text v0.17.0 + golang.org/x/text v0.18.0 gopkg.in/guregu/null.v4 v4.0.0 gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v3 v3.0.1 - k8s.io/apimachinery v0.28.2 + k8s.io/apimachinery v0.31.0 ) // avoids ambigious imports of indirect dependencies @@ -84,8 +84,6 @@ require ( github.com/CosmWasm/wasmd v0.40.1 // indirect github.com/CosmWasm/wasmvm v1.2.4 // indirect github.com/DataDog/zstd v1.5.2 // indirect - github.com/K-Phoen/grabana v0.22.1 // indirect - github.com/K-Phoen/sdk v0.12.4 // indirect github.com/MakeNowJust/heredoc v1.0.0 // indirect github.com/Masterminds/goutils v1.1.1 // indirect github.com/Masterminds/sprig/v3 v3.2.3 // indirect @@ -125,6 +123,7 @@ require ( github.com/beorn7/perks v1.0.1 // indirect github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 // indirect github.com/bits-and-blooms/bitset v1.10.0 // indirect + github.com/blang/semver/v4 v4.0.0 // indirect github.com/blendle/zapdriver v1.3.1 // indirect github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect github.com/buger/jsonparser v1.1.1 // indirect @@ -190,7 +189,6 @@ require ( github.com/emicklei/go-restful/v3 v3.12.1 // indirect github.com/esote/minmaxheap v1.0.0 // indirect github.com/ethereum/c-kzg-4844 v0.4.0 // indirect - github.com/evanphx/json-patch v5.6.0+incompatible // indirect github.com/evanphx/json-patch/v5 v5.9.0 // indirect github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f // indirect github.com/facette/natsort v0.0.0-20181210072756-2cd4dd1e2dcb // indirect @@ -198,7 +196,6 @@ require ( github.com/fatih/color v1.16.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect - github.com/fvbommel/sortorder v1.1.0 // indirect github.com/gabriel-vasile/mimetype v1.4.3 // indirect github.com/gagliardetto/binary v0.7.7 // indirect github.com/gagliardetto/solana-go v1.8.4 // indirect @@ -251,21 +248,19 @@ require ( github.com/google/go-querystring v1.1.0 // indirect github.com/google/go-tpm v0.9.0 // indirect github.com/google/gofuzz v1.2.0 // indirect - github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6 // indirect + github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect github.com/gorilla/context v1.1.1 // indirect github.com/gorilla/mux v1.8.0 // indirect github.com/gorilla/securecookie v1.1.2 // indirect github.com/gorilla/sessions v1.2.2 // indirect github.com/gorilla/websocket v1.5.1 // indirect - github.com/gosimple/slug v1.13.1 // indirect - github.com/gosimple/unidecode v1.0.1 // indirect github.com/grafana/dskit v0.0.0-20231120170505-765e343eda4f // indirect github.com/grafana/gomemcache v0.0.0-20231023152154-6947259a0586 // indirect github.com/grafana/grafana-foundation-sdk/go v0.0.0-20240326122733-6f96a993222b // indirect github.com/grafana/loki v1.6.2-0.20231215164305-b51b7d7b5503 // indirect github.com/grafana/loki/pkg/push v0.0.0-20231201111602-11ef833ed3e4 // indirect - github.com/grafana/pyroscope-go v1.1.1 // indirect + github.com/grafana/pyroscope-go v1.1.2 // indirect github.com/grafana/pyroscope-go/godeltaprof v0.1.8 // indirect github.com/grafana/regexp v0.0.0-20221122212121-6b5c0a4cb7fd // indirect github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect @@ -365,6 +360,7 @@ require ( github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f // indirect github.com/mwitkow/grpc-proxy v0.0.0-20230212185441-f345521cb9c9 // indirect + github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect github.com/oklog/run v1.1.0 // indirect github.com/oklog/ulid v1.3.1 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect @@ -409,7 +405,6 @@ require ( github.com/smartcontractkit/chainlink-feeds v0.0.0-20240710170203-5b41615da827 // indirect github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240712132946-267a37c5ac6e // indirect github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240709043547-03612098f799 // indirect - github.com/smartcontractkit/chainlink-testing-framework/wasp v0.4.9 // indirect github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 // indirect github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1 // indirect github.com/smartcontractkit/wsrpc v0.8.1 // indirect @@ -451,10 +446,10 @@ require ( github.com/zondax/ledger-go v0.14.3 // indirect go.dedis.ch/fixbuf v1.0.3 // indirect go.dedis.ch/kyber/v3 v3.1.0 // indirect - go.etcd.io/bbolt v1.3.8 // indirect - go.etcd.io/etcd/api/v3 v3.5.12 // indirect - go.etcd.io/etcd/client/pkg/v3 v3.5.12 // indirect - go.etcd.io/etcd/client/v3 v3.5.12 // indirect + go.etcd.io/bbolt v1.3.9 // indirect + go.etcd.io/etcd/api/v3 v3.5.14 // indirect + go.etcd.io/etcd/client/pkg/v3 v3.5.14 // indirect + go.etcd.io/etcd/client/v3 v3.5.14 // indirect go.mongodb.org/mongo-driver v1.15.0 // indirect go.opencensus.io v0.24.0 // indirect go.opentelemetry.io/collector/pdata v1.0.0-rcv0016 // indirect @@ -474,10 +469,10 @@ require ( go4.org/netipx v0.0.0-20230125063823-8449b0a6169f // indirect golang.org/x/arch v0.8.0 // indirect golang.org/x/mod v0.19.0 // indirect - golang.org/x/net v0.27.0 // indirect + golang.org/x/net v0.29.0 // indirect golang.org/x/oauth2 v0.21.0 // indirect - golang.org/x/sys v0.23.0 // indirect - golang.org/x/term v0.23.0 // indirect + golang.org/x/sys v0.25.0 // indirect + golang.org/x/term v0.24.0 // indirect golang.org/x/time v0.6.0 // indirect golang.org/x/tools v0.23.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect @@ -487,25 +482,26 @@ require ( google.golang.org/genproto/googleapis/rpc v0.0.0-20240711142825-46eb208f015d // indirect google.golang.org/grpc v1.65.0 // indirect google.golang.org/protobuf v1.34.2 // indirect + gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect - k8s.io/api v0.28.2 // indirect - k8s.io/apiextensions-apiserver v0.28.2 // indirect - k8s.io/cli-runtime v0.28.2 // indirect - k8s.io/client-go v0.28.2 // indirect - k8s.io/component-base v0.28.2 // indirect + k8s.io/api v0.31.0 // indirect + k8s.io/apiextensions-apiserver v0.31.0 // indirect + k8s.io/cli-runtime v0.31.0 // indirect + k8s.io/client-go v0.31.0 // indirect + k8s.io/component-base v0.31.0 // indirect k8s.io/klog/v2 v2.130.1 // indirect k8s.io/kube-openapi v0.0.0-20240709000822-3c01b740850f // indirect - k8s.io/kubectl v0.28.2 // indirect - k8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0 // indirect + k8s.io/kubectl v0.31.0 // indirect + k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 // indirect nhooyr.io/websocket v1.8.10 // indirect pgregory.net/rapid v1.1.0 // indirect rsc.io/tmplfunc v0.0.3 // indirect - sigs.k8s.io/controller-runtime v0.16.2 // indirect + sigs.k8s.io/controller-runtime v0.19.0 // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect - sigs.k8s.io/kustomize/api v0.13.5-0.20230601165947-6ce0bf390ce3 // indirect - sigs.k8s.io/kustomize/kyaml v0.14.3-0.20230601165947-6ce0bf390ce3 // indirect + sigs.k8s.io/kustomize/api v0.17.2 // indirect + sigs.k8s.io/kustomize/kyaml v0.17.1 // indirect sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect sigs.k8s.io/yaml v1.4.0 // indirect ) @@ -534,3 +530,5 @@ replace ( github.com/smartcontractkit/chainlink/integration-tests => ../integration-tests ) + +exclude github.com/sourcegraph/sourcegraph/lib v0.0.0-20221216004406-749998a2ac74 diff --git a/integration-tests/go.sum b/integration-tests/go.sum index 5e6f9b279d..727c8bf04a 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -64,8 +64,8 @@ cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= cosmossdk.io/tools/rosetta v0.2.1 h1:ddOMatOH+pbxWbrGJKRAawdBkPYLfKXutK9IETnjYxw= cosmossdk.io/tools/rosetta v0.2.1/go.mod h1:Pqdc1FdvkNV3LcNIkYWt2RQY6IP1ge6YWZk8MhhO9Hw= -dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= -dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= +dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= +dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= filippo.io/edwards25519 v1.0.0-rc.1/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= @@ -125,10 +125,6 @@ github.com/GeertJohan/go.incremental v1.0.0/go.mod h1:6fAjUhbVuX1KcMD3c8TEgVUqmo github.com/GeertJohan/go.rice v1.0.0/go.mod h1:eH6gbSOAUv07dQuZVnBmoDP8mgsM1rtixis4Tib9if0= github.com/HdrHistogram/hdrhistogram-go v1.1.2 h1:5IcZpTvzydCQeHzK4Ef/D5rrSqwxob0t8PQPMybUNFM= github.com/HdrHistogram/hdrhistogram-go v1.1.2/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo= -github.com/K-Phoen/grabana v0.22.1 h1:b/O+C3H2H6VNYSeMCYUO4X4wYuwFXgBcRkvYa+fjpQA= -github.com/K-Phoen/grabana v0.22.1/go.mod h1:3LTXrTzQzTKTgvKSXdRjlsJbizSOW/V23Q3iX00R5bU= -github.com/K-Phoen/sdk v0.12.4 h1:j2EYuBJm3zDTD0fGKACVFWxAXtkR0q5QzfVqxmHSeGQ= -github.com/K-Phoen/sdk v0.12.4/go.mod h1:qmM0wO23CtoDux528MXPpYvS4XkRWkWX6rvX9Za8EVU= github.com/Khan/genqlient v0.7.0 h1:GZ1meyRnzcDTK48EjqB8t3bcfYvHArCUUvgOwpz1D4w= github.com/Khan/genqlient v0.7.0/go.mod h1:HNyy3wZvuYwmW3Y7mkoQLZsa/R5n5yIRajS1kPBvSFM= github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ= @@ -264,6 +260,8 @@ github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816/go.mod h1:+zsy github.com/bits-and-blooms/bitset v1.10.0 h1:ePXTeiPEazB5+opbv5fr8umg2R/1NlzgDsyepwsSr88= github.com/bits-and-blooms/bitset v1.10.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= +github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= +github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= github.com/blendle/zapdriver v1.3.1 h1:C3dydBOWYRiOk+B8X9IVZ5IOe+7cl+tGOexN4QqHfpE= github.com/blendle/zapdriver v1.3.1/go.mod h1:mdXfREi6u5MArG4j9fewC+FGnXaBR+T4Ox4J2u4eHCc= github.com/bradleyjkemp/cupaloy/v2 v2.6.0 h1:knToPYa2xtfg42U3I6punFEjaGFKWQRXJwj0JTv4mTs= @@ -307,8 +305,8 @@ github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UF github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chai2010/gettext-go v1.0.2 h1:1Lwwip6Q2QGsAdl/ZKPCwTe9fe0CjlUbqj5bFNSjIRk= github.com/chai2010/gettext-go v1.0.2/go.mod h1:y+wnP2cHYaVj19NZhYKAwEMH2CI1gNHeQQ+5AjwawxA= -github.com/chaos-mesh/chaos-mesh/api v0.0.0-20240709130330-9f4feec7553f h1:onZ3oc6l1Gz8pVpQ0c1U1Cb11kIMoDb3xtEy/iZbYZM= -github.com/chaos-mesh/chaos-mesh/api v0.0.0-20240709130330-9f4feec7553f/go.mod h1:x11iCbZV6hzzSQWMq610B6Wl5Lg1dhwqcVfeiWQQnQQ= +github.com/chaos-mesh/chaos-mesh/api v0.0.0-20240821051457-da69c6d9617a h1:6Pg3a6j/41QDzH/oYcMLwwKsf3x/HXcu9W/dBaf2Hzs= +github.com/chaos-mesh/chaos-mesh/api v0.0.0-20240821051457-da69c6d9617a/go.mod h1:x11iCbZV6hzzSQWMq610B6Wl5Lg1dhwqcVfeiWQQnQQ= github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY= github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk= github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d h1:77cEq6EriyTZ0g/qfRdp61a3Uu/AWrgIq2s0ClJV1g0= @@ -529,10 +527,8 @@ github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4 github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= -github.com/fvbommel/sortorder v1.1.0 h1:fUmoe+HLsBTctBDoaBwpQo5N+nrCp8g/BjKb/6ZQmYw= -github.com/fvbommel/sortorder v1.1.0/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0= -github.com/fxamacker/cbor/v2 v2.6.0 h1:sU6J2usfADwWlYDAFhZBQ6TnLFBHxgesMrQfQgk1tWA= -github.com/fxamacker/cbor/v2 v2.6.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= +github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= +github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= github.com/gagliardetto/binary v0.7.7 h1:QZpT38+sgoPg+TIQjH94sLbl/vX+nlIRA37pEyOsjfY= @@ -589,8 +585,8 @@ github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/go-logr/zapr v1.2.4 h1:QHVo+6stLbfJmYGkQ7uGHUCu5hnAFAj6mDe6Ea0SeOo= -github.com/go-logr/zapr v1.2.4/go.mod h1:FyHWQIzQORZ0QVE1BtVHv3cKtNLuXsbNLtpuhNapBOA= +github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= +github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= @@ -786,8 +782,8 @@ github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6 h1:k7nVchz72niMH6YLQNvHSdIE7iqsQxK1P41mySCvssg= -github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw= +github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af h1:kmjWCqn2qkEml422C2Rrd27c3VGxi6a/6HNq8QmHRKM= +github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= @@ -822,10 +818,6 @@ github.com/gorilla/sessions v1.2.2/go.mod h1:ePLdVu+jbEgHH+KWw8I1z2wqd0BAdAQh/8L github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= -github.com/gosimple/slug v1.13.1 h1:bQ+kpX9Qa6tHRaK+fZR0A0M2Kd7Pa5eHPPsb1JpHD+Q= -github.com/gosimple/slug v1.13.1/go.mod h1:UiRaFH+GEilHstLUmcBgWcI42viBN7mAb818JrYOeFQ= -github.com/gosimple/unidecode v1.0.1 h1:hZzFTMMqSswvf0LBJZCZgThIZrpDHFXux9KeGmn6T/o= -github.com/gosimple/unidecode v1.0.1/go.mod h1:CP0Cr1Y1kogOtx0bJblKzsVWrqYaqfNOnHzpgWw4Awc= github.com/grafana/dskit v0.0.0-20231120170505-765e343eda4f h1:gyojr97YeWZ70pKNakWv5/tKwBHuLy3icnIeCo9gQr4= github.com/grafana/dskit v0.0.0-20231120170505-765e343eda4f/go.mod h1:8dsy5tQOkeNQyjXpm5mQsbCu3H5uzeBD35MzRQFznKU= github.com/grafana/gomemcache v0.0.0-20231023152154-6947259a0586 h1:/of8Z8taCPftShATouOrBVy6GaTTjgQd/VfNiZp/VXQ= @@ -836,8 +828,8 @@ github.com/grafana/loki v1.6.2-0.20231215164305-b51b7d7b5503 h1:gdrsYbmk8822v6qv github.com/grafana/loki v1.6.2-0.20231215164305-b51b7d7b5503/go.mod h1:d8seWXCEXkL42mhuIJYcGi6DxfehzoIpLrMQWJojvOo= github.com/grafana/loki/pkg/push v0.0.0-20231201111602-11ef833ed3e4 h1:wQ0FnSeebhJIBkgYOD06Mxk9HV2KhtEG0hp/7R+5RUQ= github.com/grafana/loki/pkg/push v0.0.0-20231201111602-11ef833ed3e4/go.mod h1:f3JSoxBTPXX5ec4FxxeC19nTBSxoTz+cBgS3cYLMcr0= -github.com/grafana/pyroscope-go v1.1.1 h1:PQoUU9oWtO3ve/fgIiklYuGilvsm8qaGhlY4Vw6MAcQ= -github.com/grafana/pyroscope-go v1.1.1/go.mod h1:Mw26jU7jsL/KStNSGGuuVYdUq7Qghem5P8aXYXSXG88= +github.com/grafana/pyroscope-go v1.1.2 h1:7vCfdORYQMCxIzI3NlYAs3FcBP760+gWuYWOyiVyYx8= +github.com/grafana/pyroscope-go v1.1.2/go.mod h1:HSSmHo2KRn6FasBA4vK7BMiQqyQq8KSuBKvrhkXxYPU= github.com/grafana/pyroscope-go/godeltaprof v0.1.8 h1:iwOtYXeeVSAeYefJNaxDytgjKtUuKQbJqgAIjlnicKg= github.com/grafana/pyroscope-go/godeltaprof v0.1.8/go.mod h1:2+l7K7twW49Ct4wFluZD3tZ6e0SjanjcUUBPVD/UuGU= github.com/grafana/regexp v0.0.0-20221122212121-6b5c0a4cb7fd h1:PpuIBO5P3e9hpqBD0O/HjhShYuM6XE0i/lbE6J94kww= @@ -1106,6 +1098,8 @@ github.com/linode/linodego v1.19.0 h1:n4WJrcr9+30e9JGZ6DI0nZbm5SdAj1kSwvvt/998YU github.com/linode/linodego v1.19.0/go.mod h1:XZFR+yJ9mm2kwf6itZ6SCpu+6w3KnIevV0Uu5HNWJgQ= github.com/linxGnu/grocksdb v1.7.16 h1:Q2co1xrpdkr5Hx3Fp+f+f7fRGhQFQhvi/+226dtLmA8= github.com/linxGnu/grocksdb v1.7.16/go.mod h1:JkS7pl5qWpGpuVb3bPqTz8nC12X3YtPZT+Xq7+QfQo4= +github.com/lithammer/dedent v1.1.0 h1:VNzHMVCBNG1j0fh3OrsFRkVUwStdDArbgBWoPAffktY= +github.com/lithammer/dedent v1.1.0/go.mod h1:jrXYCQtgg0nJiN+StA2KgR7w6CiQNv9Fd/Z9BP0jIOc= github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczGlG91VSDkswnjF5A8= github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= @@ -1234,6 +1228,8 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus= +github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nkovacs/streamquote v0.0.0-20170412213628-49af9bddb229/go.mod h1:0aYXnNPJ8l7uZxf45rWW1a/uME32OF0rhiYGNQ2oF2E= github.com/nsf/jsondiff v0.0.0-20210926074059-1e845ec5d249 h1:NHrXEjTNQY7P0Zfx1aMrNhpgxHmow66XQtm0aQLY0AE= @@ -1253,8 +1249,8 @@ github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vv github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= -github.com/onsi/ginkgo/v2 v2.17.2 h1:7eMhcy3GimbsA3hEnVKdw/PQM9XN9krpKVXsZdph0/g= -github.com/onsi/ginkgo/v2 v2.17.2/go.mod h1:nP2DPOQoNsQmsVyv5rDA8JkXQoCs6goXIvr/PRJ1eCc= +github.com/onsi/ginkgo/v2 v2.19.0 h1:9Cnnf7UHo57Hy3k6/m5k3dRfGTMXGvxhHFvkDTCTpvA= +github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= @@ -1340,10 +1336,6 @@ github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0leargg github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/prometheus/prometheus v0.47.2-0.20231010075449-4b9c19fe5510 h1:6ksZ7t1hNOzGPPs8DK7SvXQf6UfWzi+W5Z7PCBl8gx4= github.com/prometheus/prometheus v0.47.2-0.20231010075449-4b9c19fe5510/go.mod h1:UC0TwJiF90m2T3iYPQBKnGu8gv3s55dF/EgpTq8gyvo= -github.com/pyroscope-io/client v0.7.1 h1:yFRhj3vbgjBxehvxQmedmUWJQ4CAfCHhn+itPsuWsHw= -github.com/pyroscope-io/client v0.7.1/go.mod h1:4h21iOU4pUOq0prKyDlvYRL+SCKsBc5wKiEtV+rJGqU= -github.com/pyroscope-io/godeltaprof v0.1.2 h1:MdlEmYELd5w+lvIzmZvXGNMVzW2Qc9jDMuJaPOR75g4= -github.com/pyroscope-io/godeltaprof v0.1.2/go.mod h1:psMITXp90+8pFenXkKIpNhrfmI9saQnPbba27VIaiQE= github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ= github.com/rakyll/statik v0.1.7/go.mod h1:AlZONWzMtEnMs7W4e/1LURLiI49pIMmp6V9Unghqrcc= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= @@ -1369,8 +1361,8 @@ github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= -github.com/rs/zerolog v1.32.0 h1:keLypqrlIjaFsbmJOBdB/qvyF8KEtCWHwobLp5l/mQ0= -github.com/rs/zerolog v1.32.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= +github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8= +github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= @@ -1437,28 +1429,26 @@ github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240712132946-267a37c5ac6 github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240712132946-267a37c5ac6e/go.mod h1:hsFhop+SlQHKD+DEFjZrMJmbauT1A/wvtZIeeo4PxFU= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240709043547-03612098f799 h1:HyLTySm7BR+oNfZqDTkVJ25wnmcTtxBBD31UkFL+kEM= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240709043547-03612098f799/go.mod h1:UVFRacRkP7O7TQAzFmR52v5mUlxf+G1ovMlCQAB/cHU= -github.com/smartcontractkit/chainlink-testing-framework v1.34.10 h1:7boGJr/wkX5TF6TBb4wRnP6t1IFL6RD98+fZBJBZyCY= -github.com/smartcontractkit/chainlink-testing-framework v1.34.10/go.mod h1:ekYJbRAxXcs/YgOjHsY9/tlvDvXzv3lxcZK2eFUZduc= -github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240405215812-5a72bc9af239 h1:Kk5OVlx/5g9q3Z3lhxytZS4/f8ds1MiNM8yaHgK3Oe8= -github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240405215812-5a72bc9af239/go.mod h1:DC8sQMyTlI/44UCTL8QWFwb0bYNoXCfjwCv2hMivYZU= -github.com/smartcontractkit/chainlink-testing-framework/seth v1.2.1-0.20240827112945-bd8c580392d6 h1:ItZ75xmt+VHR/lw+GJwSWj9XICpgZ94dJ+I/5jdet7c= -github.com/smartcontractkit/chainlink-testing-framework/seth v1.2.1-0.20240827112945-bd8c580392d6/go.mod h1:afY3QmNgeR/VI1pRbGH8g3YXGy7C2RrFOwUzEFvL3L8= -github.com/smartcontractkit/chainlink-testing-framework/wasp v0.4.9 h1:zyp3Ic0lvseZEKh4/Afcsjk9RAnnxHEI6ajqNXWbRL0= -github.com/smartcontractkit/chainlink-testing-framework/wasp v0.4.9/go.mod h1:OMadmu2D8J0ju4XZ+tiTX3EOz0QBsfrw1zym+ZXuNVk= +github.com/smartcontractkit/chainlink-testing-framework/havoc v1.50.0 h1:mgjBQIEy+3V3G6K8e+6by3xndgsXdYYsdy+7kzQZwSk= +github.com/smartcontractkit/chainlink-testing-framework/havoc v1.50.0/go.mod h1:pdIxrooP5CFGmC0p5NTOBiZAFtMw+5pTT4de5GY3ywA= +github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.5 h1:Owb1MQZn0NZHwtZAnPZE6TVoTx6xLrfPaUdeOYswE9M= +github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.5/go.mod h1:hS4yNF94C1lkS9gvtFXW8Km8K9NzGeR20aNfkqo5qbE= +github.com/smartcontractkit/chainlink-testing-framework/lib/grafana v1.50.0 h1:VIxK8u0Jd0Q/VuhmsNm6Bls6Tb31H/sA3A/rbc5hnhg= +github.com/smartcontractkit/chainlink-testing-framework/lib/grafana v1.50.0/go.mod h1:lyAu+oMXdNUzEDScj2DXB2IueY+SDXPPfyl/kb63tMM= +github.com/smartcontractkit/chainlink-testing-framework/seth v1.50.2 h1:sA4bnFVMwzhR/uxjHcMc5ccFLIv3Qr9XUsUS7aY+Yyc= +github.com/smartcontractkit/chainlink-testing-framework/seth v1.50.2/go.mod h1:afY3QmNgeR/VI1pRbGH8g3YXGy7C2RrFOwUzEFvL3L8= +github.com/smartcontractkit/chainlink-testing-framework/wasp v1.50.0 h1:gfhfTn7HkbUHNooSF3c9vzQyN8meWJVGt6G/pNUbpYk= +github.com/smartcontractkit/chainlink-testing-framework/wasp v1.50.0/go.mod h1:tqajhpUJA/9OaMCLitghBXjAgqYO4i27St0F4TUO3+M= github.com/smartcontractkit/go-plugin v0.0.0-20240208201424-b3b91517de16 h1:TFe+FvzxClblt6qRfqEhUfa4kFQx5UobuoFGO2W4mMo= github.com/smartcontractkit/go-plugin v0.0.0-20240208201424-b3b91517de16/go.mod h1:lBS5MtSSBZk0SHc66KACcjjlU6WzEVP/8pwz68aMkCI= github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f h1:hgJif132UCdjo8u43i7iPN1/MFnu49hv7lFGFftCHKU= github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f/go.mod h1:MvMXoufZAtqExNexqi4cjrNYE9MefKddKylxjS+//n0= -github.com/smartcontractkit/havoc/k8schaos v0.0.0-20240409145249-e78d20847e37 h1:ZEhn2Yo1jY4hqy8nasDL4k4pNtopT3rS3Ap1GDb7ODc= -github.com/smartcontractkit/havoc/k8schaos v0.0.0-20240409145249-e78d20847e37/go.mod h1:/kFr0D7SI/vueXl1N03uzOun4nViGPFRyA5X6eL3jXw= github.com/smartcontractkit/libocr v0.0.0-20240717100443-f6226e09bee7 h1:e38V5FYE7DA1JfKXeD5Buo/7lczALuVXlJ8YNTAUxcw= github.com/smartcontractkit/libocr v0.0.0-20240717100443-f6226e09bee7/go.mod h1:fb1ZDVXACvu4frX3APHZaEBp0xi1DIm34DcA0CwTsZM= github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 h1:yiKnypAqP8l0OX0P3klzZ7SCcBUxy5KqTAKZmQOvSQE= github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1/go.mod h1:q6f4fe39oZPdsh1i57WznEZgxd8siidMaSFq3wdPmVg= github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1 h1:Dai1bn+Q5cpeGMQwRdjOdVjG8mmFFROVkSKuUgBErRQ= github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1/go.mod h1:G5Sd/yzHWf26rQ+X0nG9E0buKPqRGPMJAfk2gwCzOOw= -github.com/smartcontractkit/wasp v0.4.5 h1:pgiXwBci2m15eo33AzspzhpNG/gxg+8QGxl+I5LpfsQ= -github.com/smartcontractkit/wasp v0.4.5/go.mod h1:eVhBVLbVv0qORUlN7aR5C4aTN/lTYO3KnN1erO4ROOI= github.com/smartcontractkit/wsrpc v0.8.1 h1:kk0SXLqWrWaZ3J6c7n8D0NZ2uTMBBBpG5dZZXZX8UGE= github.com/smartcontractkit/wsrpc v0.8.1/go.mod h1:yfg8v8fPLXkb6Mcnx6Pm/snP6jJ0r5Kf762Yd1a/KpA= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= @@ -1629,14 +1619,14 @@ go.dedis.ch/protobuf v1.0.5/go.mod h1:eIV4wicvi6JK0q/QnfIEGeSFNG0ZeB24kzut5+HaRL go.dedis.ch/protobuf v1.0.7/go.mod h1:pv5ysfkDX/EawiPqcW3ikOxsL5t+BqnV6xHSmE79KI4= go.dedis.ch/protobuf v1.0.11/go.mod h1:97QR256dnkimeNdfmURz0wAMNVbd1VmLXhG1CrTYrJ4= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/bbolt v1.3.8 h1:xs88BrvEv273UsB79e0hcVrlUWmS0a8upikMFhSyAtA= -go.etcd.io/bbolt v1.3.8/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= -go.etcd.io/etcd/api/v3 v3.5.12 h1:W4sw5ZoU2Juc9gBWuLk5U6fHfNVyY1WC5g9uiXZio/c= -go.etcd.io/etcd/api/v3 v3.5.12/go.mod h1:Ot+o0SWSyT6uHhA56al1oCED0JImsRiU9Dc26+C2a+4= -go.etcd.io/etcd/client/pkg/v3 v3.5.12 h1:EYDL6pWwyOsylrQyLp2w+HkQ46ATiOvoEdMarindU2A= -go.etcd.io/etcd/client/pkg/v3 v3.5.12/go.mod h1:seTzl2d9APP8R5Y2hFL3NVlD6qC/dOT+3kvrqPyTas4= -go.etcd.io/etcd/client/v3 v3.5.12 h1:v5lCPXn1pf1Uu3M4laUE2hp/geOTc5uPcYYsNe1lDxg= -go.etcd.io/etcd/client/v3 v3.5.12/go.mod h1:tSbBCakoWmmddL+BKVAJHa9km+O/E+bumDe9mSbPiqw= +go.etcd.io/bbolt v1.3.9 h1:8x7aARPEXiXbHmtUwAIv7eV2fQFHrLLavdiJ3uzJXoI= +go.etcd.io/bbolt v1.3.9/go.mod h1:zaO32+Ti0PK1ivdPtgMESzuzL2VPoIG1PCQNvOdo/dE= +go.etcd.io/etcd/api/v3 v3.5.14 h1:vHObSCxyB9zlF60w7qzAdTcGaglbJOpSj1Xj9+WGxq0= +go.etcd.io/etcd/api/v3 v3.5.14/go.mod h1:BmtWcRlQvwa1h3G2jvKYwIQy4PkHlDej5t7uLMUdJUU= +go.etcd.io/etcd/client/pkg/v3 v3.5.14 h1:SaNH6Y+rVEdxfpA2Jr5wkEvN6Zykme5+YnbCkxvuWxQ= +go.etcd.io/etcd/client/pkg/v3 v3.5.14/go.mod h1:8uMgAokyG1czCtIdsq+AGyYQMvpIKnSvPjFMunkgeZI= +go.etcd.io/etcd/client/v3 v3.5.14 h1:CWfRs4FDaDoSz81giL7zPpZH2Z35tbOrAJkkjMqOupg= +go.etcd.io/etcd/client/v3 v3.5.14/go.mod h1:k3XfdV/VIHy/97rqWjoUzrj9tk7GgJGH9J8L4dNXmAk= go.mongodb.org/mongo-driver v1.7.3/go.mod h1:NqaYOwnXWr5Pm7AOpO5QFxKJ503nbMse/R79oO62zWg= go.mongodb.org/mongo-driver v1.7.5/go.mod h1:VXEWRZ6URJIkUq2SCAyapmhH0ZLRBP+FT4xhp5Zvxng= go.mongodb.org/mongo-driver v1.10.0/go.mod h1:wsihk0Kdgv8Kqu1Anit4sfK+22vSFbUrAVEYRhCXrA8= @@ -1742,8 +1732,8 @@ golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0 golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= -golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= -golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= +golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= +golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1837,8 +1827,8 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= -golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= -golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= +golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= +golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1951,8 +1941,8 @@ golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM= -golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= +golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -1964,8 +1954,8 @@ golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= -golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU= -golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk= +golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM= +golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1979,8 +1969,8 @@ golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= -golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= +golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -2174,6 +2164,8 @@ gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4= +gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/guregu/null.v4 v4.0.0 h1:1Wm3S1WEA2I26Kq+6vcW+w0gcDo44YKYD7YIEJNHDjg= gopkg.in/guregu/null.v4 v4.0.0/go.mod h1:YoQhUrADuG3i9WqesrCmpNRwm1ypAgSHYqoOcTu/JrI= @@ -2213,26 +2205,26 @@ honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las= -k8s.io/api v0.28.2 h1:9mpl5mOb6vXZvqbQmankOfPIGiudghwCoLl1EYfUZbw= -k8s.io/api v0.28.2/go.mod h1:RVnJBsjU8tcMq7C3iaRSGMeaKt2TWEUXcpIt/90fjEg= -k8s.io/apiextensions-apiserver v0.28.2 h1:J6/QRWIKV2/HwBhHRVITMLYoypCoPY1ftigDM0Kn+QU= -k8s.io/apiextensions-apiserver v0.28.2/go.mod h1:5tnkxLGa9nefefYzWuAlWZ7RZYuN/765Au8cWLA6SRg= -k8s.io/apimachinery v0.28.2 h1:KCOJLrc6gu+wV1BYgwik4AF4vXOlVJPdiqn0yAWWwXQ= -k8s.io/apimachinery v0.28.2/go.mod h1:RdzF87y/ngqk9H4z3EL2Rppv5jj95vGS/HaFXrLDApU= -k8s.io/cli-runtime v0.28.2 h1:64meB2fDj10/ThIMEJLO29a1oujSm0GQmKzh1RtA/uk= -k8s.io/cli-runtime v0.28.2/go.mod h1:bTpGOvpdsPtDKoyfG4EG041WIyFZLV9qq4rPlkyYfDA= -k8s.io/client-go v0.28.2 h1:DNoYI1vGq0slMBN/SWKMZMw0Rq+0EQW6/AK4v9+3VeY= -k8s.io/client-go v0.28.2/go.mod h1:sMkApowspLuc7omj1FOSUxSoqjr+d5Q0Yc0LOFnYFJY= -k8s.io/component-base v0.28.2 h1:Yc1yU+6AQSlpJZyvehm/NkJBII72rzlEsd6MkBQ+G0E= -k8s.io/component-base v0.28.2/go.mod h1:4IuQPQviQCg3du4si8GpMrhAIegxpsgPngPRR/zWpzc= +k8s.io/api v0.31.0 h1:b9LiSjR2ym/SzTOlfMHm1tr7/21aD7fSkqgD/CVJBCo= +k8s.io/api v0.31.0/go.mod h1:0YiFF+JfFxMM6+1hQei8FY8M7s1Mth+z/q7eF1aJkTE= +k8s.io/apiextensions-apiserver v0.31.0 h1:fZgCVhGwsclj3qCw1buVXCV6khjRzKC5eCFt24kyLSk= +k8s.io/apiextensions-apiserver v0.31.0/go.mod h1:b9aMDEYaEe5sdK+1T0KU78ApR/5ZVp4i56VacZYEHxk= +k8s.io/apimachinery v0.31.0 h1:m9jOiSr3FoSSL5WO9bjm1n6B9KROYYgNZOb4tyZ1lBc= +k8s.io/apimachinery v0.31.0/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo= +k8s.io/cli-runtime v0.31.0 h1:V2Q1gj1u3/WfhD475HBQrIYsoryg/LrhhK4RwpN+DhA= +k8s.io/cli-runtime v0.31.0/go.mod h1:vg3H94wsubuvWfSmStDbekvbla5vFGC+zLWqcf+bGDw= +k8s.io/client-go v0.31.0 h1:QqEJzNjbN2Yv1H79SsS+SWnXkBgVu4Pj3CJQgbx0gI8= +k8s.io/client-go v0.31.0/go.mod h1:Y9wvC76g4fLjmU0BA+rV+h2cncoadjvjjkkIGoTLcGU= +k8s.io/component-base v0.31.0 h1:/KIzGM5EvPNQcYgwq5NwoQBaOlVFrghoVGr8lG6vNRs= +k8s.io/component-base v0.31.0/go.mod h1:TYVuzI1QmN4L5ItVdMSXKvH7/DtvIuas5/mm8YT3rTo= k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/kube-openapi v0.0.0-20240709000822-3c01b740850f h1:2sXuKesAYbRHxL3aE2PN6zX/gcJr22cjrsej+W784Tc= k8s.io/kube-openapi v0.0.0-20240709000822-3c01b740850f/go.mod h1:UxDHUPsUwTOOxSU+oXURfFBcAS6JwiRXTYqYwfuGowc= -k8s.io/kubectl v0.28.2 h1:fOWOtU6S0smdNjG1PB9WFbqEIMlkzU5ahyHkc7ESHgM= -k8s.io/kubectl v0.28.2/go.mod h1:6EQWTPySF1fn7yKoQZHYf9TPwIl2AygHEcJoxFekr64= -k8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0 h1:jgGTlFYnhF1PM1Ax/lAlxUPE+KfCIXHaathvJg1C3ak= -k8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +k8s.io/kubectl v0.31.0 h1:kANwAAPVY02r4U4jARP/C+Q1sssCcN/1p9Nk+7BQKVg= +k8s.io/kubectl v0.31.0/go.mod h1:pB47hhFypGsaHAPjlwrNbvhXgmuAr01ZBvAIIUaI8d4= +k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A= +k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= nhooyr.io/websocket v1.8.10 h1:mv4p+MnGrLDcPlBoWsvPP7XCzTYMXP9F9eIGoKbgx7Q= nhooyr.io/websocket v1.8.10/go.mod h1:rN9OFWIUwuxg4fR5tELlYC04bXYowCP9GX47ivo2l+c= nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50= @@ -2244,14 +2236,14 @@ rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU= rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA= -sigs.k8s.io/controller-runtime v0.16.2 h1:mwXAVuEk3EQf478PQwQ48zGOXvW27UJc8NHktQVuIPU= -sigs.k8s.io/controller-runtime v0.16.2/go.mod h1:vpMu3LpI5sYWtujJOa2uPK61nB5rbwlN7BAB8aSLvGU= +sigs.k8s.io/controller-runtime v0.19.0 h1:nWVM7aq+Il2ABxwiCizrVDSlmDcshi9llbaFbC0ji/Q= +sigs.k8s.io/controller-runtime v0.19.0/go.mod h1:iRmWllt8IlaLjvTTDLhRBXIEtkCK6hwVBJJsYS9Ajf4= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= -sigs.k8s.io/kustomize/api v0.13.5-0.20230601165947-6ce0bf390ce3 h1:XX3Ajgzov2RKUdc5jW3t5jwY7Bo7dcRm+tFxT+NfgY0= -sigs.k8s.io/kustomize/api v0.13.5-0.20230601165947-6ce0bf390ce3/go.mod h1:9n16EZKMhXBNSiUC5kSdFQJkdH3zbxS/JoO619G1VAY= -sigs.k8s.io/kustomize/kyaml v0.14.3-0.20230601165947-6ce0bf390ce3 h1:W6cLQc5pnqM7vh3b7HvGNfXrJ/xL6BDMS0v1V/HHg5U= -sigs.k8s.io/kustomize/kyaml v0.14.3-0.20230601165947-6ce0bf390ce3/go.mod h1:JWP1Fj0VWGHyw3YUPjXSQnRnrwezrZSrApfX5S0nIag= +sigs.k8s.io/kustomize/api v0.17.2 h1:E7/Fjk7V5fboiuijoZHgs4aHuexi5Y2loXlVOAVAG5g= +sigs.k8s.io/kustomize/api v0.17.2/go.mod h1:UWTz9Ct+MvoeQsHcJ5e+vziRRkwimm3HytpZgIYqye0= +sigs.k8s.io/kustomize/kyaml v0.17.1 h1:TnxYQxFXzbmNG6gOINgGWQt09GghzgTP6mIurOgrLCQ= +sigs.k8s.io/kustomize/kyaml v0.17.1/go.mod h1:9V0mCjIEYjlXuCdYsSXvyoy2BTsLESH7TlGV81S282U= sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= diff --git a/integration-tests/load/automationv2_1/automationv2_1_test.go b/integration-tests/load/automationv2_1/automationv2_1_test.go index 0fe13d4bc7..cb2606f00b 100644 --- a/integration-tests/load/automationv2_1/automationv2_1_test.go +++ b/integration-tests/load/automationv2_1/automationv2_1_test.go @@ -23,20 +23,21 @@ import ( "github.com/stretchr/testify/require" ocr3 "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3confighelper" - "github.com/smartcontractkit/wasp" + + "github.com/smartcontractkit/chainlink-testing-framework/wasp" ocr2keepers30config "github.com/smartcontractkit/chainlink-automation/pkg/v3/config" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/chainlink" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/ethereum" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/wiremock" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/networks" - seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" - - ctfconfig "github.com/smartcontractkit/chainlink-testing-framework/config" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/environment" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/pkg/helm/chainlink" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/pkg/helm/ethereum" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/pkg/helm/wiremock" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/networks" + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/seth" + + ctfconfig "github.com/smartcontractkit/chainlink-testing-framework/lib/config" gowiremock "github.com/wiremock/go-wiremock" diff --git a/integration-tests/load/automationv2_1/gun.go b/integration-tests/load/automationv2_1/gun.go index a5fd52c40c..aa61562741 100644 --- a/integration-tests/load/automationv2_1/gun.go +++ b/integration-tests/load/automationv2_1/gun.go @@ -5,7 +5,8 @@ import ( "sync" "github.com/rs/zerolog" - "github.com/smartcontractkit/wasp" + + "github.com/smartcontractkit/chainlink-testing-framework/wasp" "github.com/smartcontractkit/chainlink-testing-framework/seth" diff --git a/integration-tests/load/automationv2_1/helpers.go b/integration-tests/load/automationv2_1/helpers.go index f770ba7573..41fa9a0ce1 100644 --- a/integration-tests/load/automationv2_1/helpers.go +++ b/integration-tests/load/automationv2_1/helpers.go @@ -11,8 +11,8 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/seth" - ctf_concurrency "github.com/smartcontractkit/chainlink-testing-framework/concurrency" - reportModel "github.com/smartcontractkit/chainlink-testing-framework/testreporters" + ctf_concurrency "github.com/smartcontractkit/chainlink-testing-framework/lib/concurrency" + reportModel "github.com/smartcontractkit/chainlink-testing-framework/lib/testreporters" "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/contracts" tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" diff --git a/integration-tests/load/functions/functions_test.go b/integration-tests/load/functions/functions_test.go index 374b3df705..90c163ca37 100644 --- a/integration-tests/load/functions/functions_test.go +++ b/integration-tests/load/functions/functions_test.go @@ -4,9 +4,10 @@ import ( "testing" "time" - "github.com/smartcontractkit/wasp" "github.com/stretchr/testify/require" + "github.com/smartcontractkit/chainlink-testing-framework/wasp" + tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" ) diff --git a/integration-tests/load/functions/functionscmd/dashboard.go b/integration-tests/load/functions/functionscmd/dashboard.go index ccf5674023..b0a00602f8 100644 --- a/integration-tests/load/functions/functionscmd/dashboard.go +++ b/integration-tests/load/functions/functionscmd/dashboard.go @@ -4,7 +4,8 @@ import ( "github.com/K-Phoen/grabana/dashboard" "github.com/K-Phoen/grabana/logs" "github.com/K-Phoen/grabana/row" - db "github.com/smartcontractkit/wasp/dashboard" + + db "github.com/smartcontractkit/chainlink-testing-framework/wasp/dashboard" ) func main() { diff --git a/integration-tests/load/functions/gateway_gun.go b/integration-tests/load/functions/gateway_gun.go index cc6132e94e..38eddd3163 100644 --- a/integration-tests/load/functions/gateway_gun.go +++ b/integration-tests/load/functions/gateway_gun.go @@ -10,7 +10,8 @@ import ( "github.com/go-resty/resty/v2" "github.com/rs/zerolog/log" "github.com/smartcontractkit/tdh2/go/tdh2/tdh2easy" - "github.com/smartcontractkit/wasp" + + "github.com/smartcontractkit/chainlink-testing-framework/wasp" "github.com/smartcontractkit/chainlink/integration-tests/types" ) diff --git a/integration-tests/load/functions/gateway_test.go b/integration-tests/load/functions/gateway_test.go index dd1092a595..9812b7ea08 100644 --- a/integration-tests/load/functions/gateway_test.go +++ b/integration-tests/load/functions/gateway_test.go @@ -3,9 +3,10 @@ package loadfunctions import ( "testing" - "github.com/smartcontractkit/wasp" "github.com/stretchr/testify/require" + "github.com/smartcontractkit/chainlink-testing-framework/wasp" + tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" "github.com/smartcontractkit/chainlink/v2/core/services/gateway/handlers/functions" ) diff --git a/integration-tests/load/functions/onchain_monitoring.go b/integration-tests/load/functions/onchain_monitoring.go index 31ca8752dd..39c4bdcf94 100644 --- a/integration-tests/load/functions/onchain_monitoring.go +++ b/integration-tests/load/functions/onchain_monitoring.go @@ -5,9 +5,10 @@ import ( "time" "github.com/rs/zerolog/log" - "github.com/smartcontractkit/wasp" - ctf_config "github.com/smartcontractkit/chainlink-testing-framework/config" + "github.com/smartcontractkit/chainlink-testing-framework/wasp" + + ctf_config "github.com/smartcontractkit/chainlink-testing-framework/lib/config" ) /* Monitors on-chain stats of LoadConsumer and pushes them to Loki every second */ diff --git a/integration-tests/load/functions/request_gun.go b/integration-tests/load/functions/request_gun.go index 6b79a2f19e..ca9ba82c51 100644 --- a/integration-tests/load/functions/request_gun.go +++ b/integration-tests/load/functions/request_gun.go @@ -1,7 +1,7 @@ package loadfunctions import ( - "github.com/smartcontractkit/wasp" + "github.com/smartcontractkit/chainlink-testing-framework/wasp" ) type TestMode int diff --git a/integration-tests/load/functions/setup.go b/integration-tests/load/functions/setup.go index 8151342021..46c2c12921 100644 --- a/integration-tests/load/functions/setup.go +++ b/integration-tests/load/functions/setup.go @@ -8,7 +8,7 @@ import ( "strconv" "time" - seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/seth" "github.com/ethereum/go-ethereum/crypto" "github.com/go-resty/resty/v2" @@ -19,8 +19,8 @@ import ( chainlinkutils "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" - ctf_config "github.com/smartcontractkit/chainlink-testing-framework/config" - "github.com/smartcontractkit/chainlink-testing-framework/networks" + ctf_config "github.com/smartcontractkit/chainlink-testing-framework/lib/config" + "github.com/smartcontractkit/chainlink-testing-framework/lib/networks" "github.com/smartcontractkit/chainlink/integration-tests/contracts" "github.com/smartcontractkit/chainlink/integration-tests/types" diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index 6ce1049562..2956080624 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -17,13 +17,13 @@ require ( github.com/slack-go/slack v0.12.2 github.com/smartcontractkit/chainlink-automation v1.0.4 github.com/smartcontractkit/chainlink-common v0.2.2-0.20240723123524-e407ecd120b1 - github.com/smartcontractkit/chainlink-testing-framework v1.34.10 - github.com/smartcontractkit/chainlink-testing-framework/seth v1.2.1-0.20240827112945-bd8c580392d6 + github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.5 + github.com/smartcontractkit/chainlink-testing-framework/seth v1.50.2 + github.com/smartcontractkit/chainlink-testing-framework/wasp v1.50.0 github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20240214231432-4ad5eb95178c github.com/smartcontractkit/chainlink/v2 v2.9.0-beta0.0.20240216210048-da02459ddad8 github.com/smartcontractkit/libocr v0.0.0-20240717100443-f6226e09bee7 github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1 - github.com/smartcontractkit/wasp v0.4.7 github.com/stretchr/testify v1.9.0 github.com/wiremock/go-wiremock v1.9.0 go.uber.org/ratelimit v0.3.0 @@ -50,15 +50,19 @@ require ( github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.5 // indirect github.com/aws/aws-sdk-go-v2/service/sts v1.30.4 // indirect github.com/aws/smithy-go v1.20.4 // indirect + github.com/blang/semver/v4 v4.0.0 // indirect github.com/containerd/errdefs v0.1.0 // indirect github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect + github.com/sergi/go-diff v1.3.1 // indirect github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240710121324-3ed288aa9b45 // indirect - github.com/smartcontractkit/chainlink-testing-framework/wasp v0.4.9 // indirect + github.com/smartcontractkit/chainlink-testing-framework/havoc v1.50.0 // indirect + github.com/smartcontractkit/chainlink-testing-framework/lib/grafana v1.50.0 // indirect github.com/testcontainers/testcontainers-go v0.28.0 // indirect + gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect k8s.io/apimachinery v0.31.0 // indirect ) @@ -67,7 +71,7 @@ exclude github.com/hashicorp/consul v1.2.1 require ( contrib.go.opencensus.io/exporter/stackdriver v0.13.5 // indirect - dario.cat/mergo v1.0.0 // indirect + dario.cat/mergo v1.0.1 // indirect filippo.io/edwards25519 v1.1.0 // indirect github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect github.com/99designs/keyring v1.2.1 // indirect @@ -394,8 +398,6 @@ require ( github.com/smartcontractkit/chainlink-feeds v0.0.0-20240710170203-5b41615da827 // indirect github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240712132946-267a37c5ac6e // indirect github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240709043547-03612098f799 // indirect - github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.1 // indirect - github.com/smartcontractkit/havoc/k8schaos v0.0.0-20240409145249-e78d20847e37 // indirect github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 // indirect github.com/smartcontractkit/wsrpc v0.8.1 // indirect github.com/soheilhy/cmux v0.1.5 // indirect @@ -462,15 +464,15 @@ require ( go.uber.org/zap v1.27.0 // indirect go4.org/netipx v0.0.0-20230125063823-8449b0a6169f // indirect golang.org/x/arch v0.8.0 // indirect - golang.org/x/crypto v0.26.0 // indirect + golang.org/x/crypto v0.27.0 // indirect golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa // indirect golang.org/x/mod v0.20.0 // indirect - golang.org/x/net v0.28.0 // indirect + golang.org/x/net v0.29.0 // indirect golang.org/x/oauth2 v0.22.0 // indirect golang.org/x/sync v0.8.0 // indirect - golang.org/x/sys v0.24.0 // indirect - golang.org/x/term v0.23.0 // indirect - golang.org/x/text v0.17.0 // indirect + golang.org/x/sys v0.25.0 // indirect + golang.org/x/term v0.24.0 // indirect + golang.org/x/text v0.18.0 // indirect golang.org/x/time v0.6.0 // indirect golang.org/x/tools v0.24.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect @@ -488,20 +490,20 @@ require ( gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/api v0.31.0 // indirect k8s.io/apiextensions-apiserver v0.31.0 // indirect - k8s.io/cli-runtime v0.28.2 // indirect + k8s.io/cli-runtime v0.31.0 // indirect k8s.io/client-go v1.5.2 // indirect k8s.io/component-base v0.31.0 // indirect k8s.io/klog/v2 v2.130.1 // indirect k8s.io/kube-openapi v0.0.0-20240709000822-3c01b740850f // indirect - k8s.io/kubectl v0.28.2 // indirect + k8s.io/kubectl v0.31.0 // indirect k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 // indirect nhooyr.io/websocket v1.8.10 // indirect pgregory.net/rapid v1.1.0 // indirect rsc.io/tmplfunc v0.0.3 // indirect - sigs.k8s.io/controller-runtime v0.18.4 // indirect + sigs.k8s.io/controller-runtime v0.19.0 // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect - sigs.k8s.io/kustomize/api v0.13.5-0.20230601165947-6ce0bf390ce3 // indirect - sigs.k8s.io/kustomize/kyaml v0.14.3-0.20230601165947-6ce0bf390ce3 // indirect + sigs.k8s.io/kustomize/api v0.17.2 // indirect + sigs.k8s.io/kustomize/kyaml v0.17.1 // indirect sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect sigs.k8s.io/yaml v1.4.0 // indirect; indirect nhooyr.io/websocket v1.8.7 // indirect ) @@ -562,3 +564,5 @@ replace ( k8s.io/sample-controller => k8s.io/sample-controller v0.28.2 sigs.k8s.io/controller-runtime => sigs.k8s.io/controller-runtime v0.16.2 ) + +exclude github.com/sourcegraph/sourcegraph/lib v0.0.0-20221216004406-749998a2ac74 diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index 760e624daf..8162c16965 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -64,8 +64,8 @@ cosmossdk.io/math v1.3.0 h1:RC+jryuKeytIiictDslBP9i1fhkVm6ZDmZEoNP316zE= cosmossdk.io/math v1.3.0/go.mod h1:vnRTxewy+M7BtXBNFybkuhSH4WfedVAAnERHgVFhp3k= cosmossdk.io/tools/rosetta v0.2.1 h1:ddOMatOH+pbxWbrGJKRAawdBkPYLfKXutK9IETnjYxw= cosmossdk.io/tools/rosetta v0.2.1/go.mod h1:Pqdc1FdvkNV3LcNIkYWt2RQY6IP1ge6YWZk8MhhO9Hw= -dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= -dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= +dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= +dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= filippo.io/edwards25519 v1.0.0-rc.1/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= @@ -252,6 +252,8 @@ github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816/go.mod h1:+zsy github.com/bits-and-blooms/bitset v1.10.0 h1:ePXTeiPEazB5+opbv5fr8umg2R/1NlzgDsyepwsSr88= github.com/bits-and-blooms/bitset v1.10.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= +github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= +github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= github.com/blendle/zapdriver v1.3.1 h1:C3dydBOWYRiOk+B8X9IVZ5IOe+7cl+tGOexN4QqHfpE= github.com/blendle/zapdriver v1.3.1/go.mod h1:mdXfREi6u5MArG4j9fewC+FGnXaBR+T4Ox4J2u4eHCc= github.com/btcsuite/btcd v0.22.1 h1:CnwP9LM/M9xuRrGSCGeMVs9iv09uMqwsVX7EeIpgV2c= @@ -1306,10 +1308,6 @@ github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0leargg github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/prometheus/prometheus v0.47.2-0.20231010075449-4b9c19fe5510 h1:6ksZ7t1hNOzGPPs8DK7SvXQf6UfWzi+W5Z7PCBl8gx4= github.com/prometheus/prometheus v0.47.2-0.20231010075449-4b9c19fe5510/go.mod h1:UC0TwJiF90m2T3iYPQBKnGu8gv3s55dF/EgpTq8gyvo= -github.com/pyroscope-io/client v0.7.1 h1:yFRhj3vbgjBxehvxQmedmUWJQ4CAfCHhn+itPsuWsHw= -github.com/pyroscope-io/client v0.7.1/go.mod h1:4h21iOU4pUOq0prKyDlvYRL+SCKsBc5wKiEtV+rJGqU= -github.com/pyroscope-io/godeltaprof v0.1.2 h1:MdlEmYELd5w+lvIzmZvXGNMVzW2Qc9jDMuJaPOR75g4= -github.com/pyroscope-io/godeltaprof v0.1.2/go.mod h1:psMITXp90+8pFenXkKIpNhrfmI9saQnPbba27VIaiQE= github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ= github.com/rakyll/statik v0.1.7/go.mod h1:AlZONWzMtEnMs7W4e/1LURLiI49pIMmp6V9Unghqrcc= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= @@ -1403,28 +1401,26 @@ github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240712132946-267a37c5ac6 github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240712132946-267a37c5ac6e/go.mod h1:hsFhop+SlQHKD+DEFjZrMJmbauT1A/wvtZIeeo4PxFU= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240709043547-03612098f799 h1:HyLTySm7BR+oNfZqDTkVJ25wnmcTtxBBD31UkFL+kEM= github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240709043547-03612098f799/go.mod h1:UVFRacRkP7O7TQAzFmR52v5mUlxf+G1ovMlCQAB/cHU= -github.com/smartcontractkit/chainlink-testing-framework v1.34.10 h1:7boGJr/wkX5TF6TBb4wRnP6t1IFL6RD98+fZBJBZyCY= -github.com/smartcontractkit/chainlink-testing-framework v1.34.10/go.mod h1:ekYJbRAxXcs/YgOjHsY9/tlvDvXzv3lxcZK2eFUZduc= -github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.1 h1:1/r1wQZ4TOFpZ13w94r7amdF096Z96RuEnkOmrz1BGE= -github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.1/go.mod h1:DC8sQMyTlI/44UCTL8QWFwb0bYNoXCfjwCv2hMivYZU= -github.com/smartcontractkit/chainlink-testing-framework/seth v1.2.1-0.20240827112945-bd8c580392d6 h1:ItZ75xmt+VHR/lw+GJwSWj9XICpgZ94dJ+I/5jdet7c= -github.com/smartcontractkit/chainlink-testing-framework/seth v1.2.1-0.20240827112945-bd8c580392d6/go.mod h1:afY3QmNgeR/VI1pRbGH8g3YXGy7C2RrFOwUzEFvL3L8= -github.com/smartcontractkit/chainlink-testing-framework/wasp v0.4.9 h1:zyp3Ic0lvseZEKh4/Afcsjk9RAnnxHEI6ajqNXWbRL0= -github.com/smartcontractkit/chainlink-testing-framework/wasp v0.4.9/go.mod h1:OMadmu2D8J0ju4XZ+tiTX3EOz0QBsfrw1zym+ZXuNVk= +github.com/smartcontractkit/chainlink-testing-framework/havoc v1.50.0 h1:mgjBQIEy+3V3G6K8e+6by3xndgsXdYYsdy+7kzQZwSk= +github.com/smartcontractkit/chainlink-testing-framework/havoc v1.50.0/go.mod h1:pdIxrooP5CFGmC0p5NTOBiZAFtMw+5pTT4de5GY3ywA= +github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.5 h1:Owb1MQZn0NZHwtZAnPZE6TVoTx6xLrfPaUdeOYswE9M= +github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.5/go.mod h1:hS4yNF94C1lkS9gvtFXW8Km8K9NzGeR20aNfkqo5qbE= +github.com/smartcontractkit/chainlink-testing-framework/lib/grafana v1.50.0 h1:VIxK8u0Jd0Q/VuhmsNm6Bls6Tb31H/sA3A/rbc5hnhg= +github.com/smartcontractkit/chainlink-testing-framework/lib/grafana v1.50.0/go.mod h1:lyAu+oMXdNUzEDScj2DXB2IueY+SDXPPfyl/kb63tMM= +github.com/smartcontractkit/chainlink-testing-framework/seth v1.50.2 h1:sA4bnFVMwzhR/uxjHcMc5ccFLIv3Qr9XUsUS7aY+Yyc= +github.com/smartcontractkit/chainlink-testing-framework/seth v1.50.2/go.mod h1:afY3QmNgeR/VI1pRbGH8g3YXGy7C2RrFOwUzEFvL3L8= +github.com/smartcontractkit/chainlink-testing-framework/wasp v1.50.0 h1:gfhfTn7HkbUHNooSF3c9vzQyN8meWJVGt6G/pNUbpYk= +github.com/smartcontractkit/chainlink-testing-framework/wasp v1.50.0/go.mod h1:tqajhpUJA/9OaMCLitghBXjAgqYO4i27St0F4TUO3+M= github.com/smartcontractkit/go-plugin v0.0.0-20240208201424-b3b91517de16 h1:TFe+FvzxClblt6qRfqEhUfa4kFQx5UobuoFGO2W4mMo= github.com/smartcontractkit/go-plugin v0.0.0-20240208201424-b3b91517de16/go.mod h1:lBS5MtSSBZk0SHc66KACcjjlU6WzEVP/8pwz68aMkCI= github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f h1:hgJif132UCdjo8u43i7iPN1/MFnu49hv7lFGFftCHKU= github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f/go.mod h1:MvMXoufZAtqExNexqi4cjrNYE9MefKddKylxjS+//n0= -github.com/smartcontractkit/havoc/k8schaos v0.0.0-20240409145249-e78d20847e37 h1:ZEhn2Yo1jY4hqy8nasDL4k4pNtopT3rS3Ap1GDb7ODc= -github.com/smartcontractkit/havoc/k8schaos v0.0.0-20240409145249-e78d20847e37/go.mod h1:/kFr0D7SI/vueXl1N03uzOun4nViGPFRyA5X6eL3jXw= github.com/smartcontractkit/libocr v0.0.0-20240717100443-f6226e09bee7 h1:e38V5FYE7DA1JfKXeD5Buo/7lczALuVXlJ8YNTAUxcw= github.com/smartcontractkit/libocr v0.0.0-20240717100443-f6226e09bee7/go.mod h1:fb1ZDVXACvu4frX3APHZaEBp0xi1DIm34DcA0CwTsZM= github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 h1:yiKnypAqP8l0OX0P3klzZ7SCcBUxy5KqTAKZmQOvSQE= github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1/go.mod h1:q6f4fe39oZPdsh1i57WznEZgxd8siidMaSFq3wdPmVg= github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1 h1:Dai1bn+Q5cpeGMQwRdjOdVjG8mmFFROVkSKuUgBErRQ= github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1/go.mod h1:G5Sd/yzHWf26rQ+X0nG9E0buKPqRGPMJAfk2gwCzOOw= -github.com/smartcontractkit/wasp v0.4.7 h1:7mKJfwzFbuE8xVLUYtLt7Bjw8q/bmVZRW6Ks8kc1LVM= -github.com/smartcontractkit/wasp v0.4.7/go.mod h1:jeabvyXikb2aNoLQwcZGqaz17efrR8NJhpq4seAmdgs= github.com/smartcontractkit/wsrpc v0.8.1 h1:kk0SXLqWrWaZ3J6c7n8D0NZ2uTMBBBpG5dZZXZX8UGE= github.com/smartcontractkit/wsrpc v0.8.1/go.mod h1:yfg8v8fPLXkb6Mcnx6Pm/snP6jJ0r5Kf762Yd1a/KpA= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= @@ -1706,8 +1702,8 @@ golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0 golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= -golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= -golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= +golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= +golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1801,8 +1797,8 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= -golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= -golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= +golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= +golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1913,8 +1909,8 @@ golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= -golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= +golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -1926,8 +1922,8 @@ golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= -golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU= -golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk= +golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM= +golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1941,8 +1937,8 @@ golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= -golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= +golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -2136,6 +2132,8 @@ gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4= +gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/guregu/null.v4 v4.0.0 h1:1Wm3S1WEA2I26Kq+6vcW+w0gcDo44YKYD7YIEJNHDjg= gopkg.in/guregu/null.v4 v4.0.0/go.mod h1:YoQhUrADuG3i9WqesrCmpNRwm1ypAgSHYqoOcTu/JrI= @@ -2210,10 +2208,10 @@ sigs.k8s.io/controller-runtime v0.16.2 h1:mwXAVuEk3EQf478PQwQ48zGOXvW27UJc8NHktQ sigs.k8s.io/controller-runtime v0.16.2/go.mod h1:vpMu3LpI5sYWtujJOa2uPK61nB5rbwlN7BAB8aSLvGU= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= -sigs.k8s.io/kustomize/api v0.13.5-0.20230601165947-6ce0bf390ce3 h1:XX3Ajgzov2RKUdc5jW3t5jwY7Bo7dcRm+tFxT+NfgY0= -sigs.k8s.io/kustomize/api v0.13.5-0.20230601165947-6ce0bf390ce3/go.mod h1:9n16EZKMhXBNSiUC5kSdFQJkdH3zbxS/JoO619G1VAY= -sigs.k8s.io/kustomize/kyaml v0.14.3-0.20230601165947-6ce0bf390ce3 h1:W6cLQc5pnqM7vh3b7HvGNfXrJ/xL6BDMS0v1V/HHg5U= -sigs.k8s.io/kustomize/kyaml v0.14.3-0.20230601165947-6ce0bf390ce3/go.mod h1:JWP1Fj0VWGHyw3YUPjXSQnRnrwezrZSrApfX5S0nIag= +sigs.k8s.io/kustomize/api v0.17.2 h1:E7/Fjk7V5fboiuijoZHgs4aHuexi5Y2loXlVOAVAG5g= +sigs.k8s.io/kustomize/api v0.17.2/go.mod h1:UWTz9Ct+MvoeQsHcJ5e+vziRRkwimm3HytpZgIYqye0= +sigs.k8s.io/kustomize/kyaml v0.17.1 h1:TnxYQxFXzbmNG6gOINgGWQt09GghzgTP6mIurOgrLCQ= +sigs.k8s.io/kustomize/kyaml v0.17.1/go.mod h1:9V0mCjIEYjlXuCdYsSXvyoy2BTsLESH7TlGV81S282U= sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= diff --git a/integration-tests/load/ocr/gun.go b/integration-tests/load/ocr/gun.go index 5ed71f1672..990c77e0b3 100644 --- a/integration-tests/load/ocr/gun.go +++ b/integration-tests/load/ocr/gun.go @@ -6,7 +6,8 @@ import ( "time" "github.com/rs/zerolog" - "github.com/smartcontractkit/wasp" + + "github.com/smartcontractkit/chainlink-testing-framework/wasp" "github.com/smartcontractkit/chainlink-testing-framework/seth" diff --git a/integration-tests/load/ocr/ocr_test.go b/integration-tests/load/ocr/ocr_test.go index 49bce3eca5..71caa9d222 100644 --- a/integration-tests/load/ocr/ocr_test.go +++ b/integration-tests/load/ocr/ocr_test.go @@ -7,9 +7,9 @@ import ( "github.com/stretchr/testify/require" - "github.com/smartcontractkit/wasp" + "github.com/smartcontractkit/chainlink-testing-framework/wasp" - "github.com/smartcontractkit/chainlink-testing-framework/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" "github.com/smartcontractkit/chainlink/integration-tests/crib" tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" diff --git a/integration-tests/load/ocr/vu.go b/integration-tests/load/ocr/vu.go index a50b52c690..aece9cb74b 100644 --- a/integration-tests/load/ocr/vu.go +++ b/integration-tests/load/ocr/vu.go @@ -11,10 +11,11 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/seth" - "github.com/smartcontractkit/wasp" "go.uber.org/ratelimit" - client2 "github.com/smartcontractkit/chainlink-testing-framework/client" + "github.com/smartcontractkit/chainlink-testing-framework/wasp" + + client2 "github.com/smartcontractkit/chainlink-testing-framework/lib/client" "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/client" diff --git a/integration-tests/load/vrfv2/gun.go b/integration-tests/load/vrfv2/gun.go index 0eef5b1481..20a20b4083 100644 --- a/integration-tests/load/vrfv2/gun.go +++ b/integration-tests/load/vrfv2/gun.go @@ -4,11 +4,12 @@ import ( "math/rand" "github.com/rs/zerolog" - "github.com/smartcontractkit/wasp" + + "github.com/smartcontractkit/chainlink-testing-framework/wasp" "github.com/smartcontractkit/chainlink-testing-framework/seth" - seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/seth" vrfcommon "github.com/smartcontractkit/chainlink/integration-tests/actions/vrf/common" "github.com/smartcontractkit/chainlink/integration-tests/actions/vrf/vrfv2" diff --git a/integration-tests/load/vrfv2/onchain_monitoring.go b/integration-tests/load/vrfv2/onchain_monitoring.go index e057e7f8d2..9ba53f39e7 100644 --- a/integration-tests/load/vrfv2/onchain_monitoring.go +++ b/integration-tests/load/vrfv2/onchain_monitoring.go @@ -6,7 +6,8 @@ import ( "time" "github.com/rs/zerolog/log" - "github.com/smartcontractkit/wasp" + + "github.com/smartcontractkit/chainlink-testing-framework/wasp" "github.com/smartcontractkit/chainlink/integration-tests/contracts" ) diff --git a/integration-tests/load/vrfv2/vrfv2_test.go b/integration-tests/load/vrfv2/vrfv2_test.go index 6d3c199d7e..49bd2dd9c0 100644 --- a/integration-tests/load/vrfv2/vrfv2_test.go +++ b/integration-tests/load/vrfv2/vrfv2_test.go @@ -10,12 +10,13 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/seth" "github.com/rs/zerolog/log" - "github.com/smartcontractkit/wasp" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/networks" - "github.com/smartcontractkit/chainlink-testing-framework/utils/ptr" - "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" + "github.com/smartcontractkit/chainlink-testing-framework/wasp" + + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/networks" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/ptr" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" "github.com/smartcontractkit/chainlink/integration-tests/actions" vrfcommon "github.com/smartcontractkit/chainlink/integration-tests/actions/vrf/common" diff --git a/integration-tests/load/vrfv2/vrfv2cmd/dashboard.go b/integration-tests/load/vrfv2/vrfv2cmd/dashboard.go index e80d7516fd..24e6799138 100644 --- a/integration-tests/load/vrfv2/vrfv2cmd/dashboard.go +++ b/integration-tests/load/vrfv2/vrfv2cmd/dashboard.go @@ -3,7 +3,7 @@ package main import ( "os" - db "github.com/smartcontractkit/wasp/dashboard" + db "github.com/smartcontractkit/chainlink-testing-framework/wasp/dashboard" "github.com/K-Phoen/grabana/dashboard" "github.com/K-Phoen/grabana/logs" diff --git a/integration-tests/load/vrfv2plus/gun.go b/integration-tests/load/vrfv2plus/gun.go index 8d4162ab88..4aac392751 100644 --- a/integration-tests/load/vrfv2plus/gun.go +++ b/integration-tests/load/vrfv2plus/gun.go @@ -5,11 +5,12 @@ import ( "math/rand" "github.com/rs/zerolog" - "github.com/smartcontractkit/wasp" + + "github.com/smartcontractkit/chainlink-testing-framework/wasp" "github.com/smartcontractkit/chainlink-testing-framework/seth" - seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/seth" "github.com/smartcontractkit/chainlink/integration-tests/actions" vrfcommon "github.com/smartcontractkit/chainlink/integration-tests/actions/vrf/common" diff --git a/integration-tests/load/vrfv2plus/onchain_monitoring.go b/integration-tests/load/vrfv2plus/onchain_monitoring.go index 50c0ac18a9..2bb082dc11 100644 --- a/integration-tests/load/vrfv2plus/onchain_monitoring.go +++ b/integration-tests/load/vrfv2plus/onchain_monitoring.go @@ -6,7 +6,8 @@ import ( "time" "github.com/rs/zerolog/log" - "github.com/smartcontractkit/wasp" + + "github.com/smartcontractkit/chainlink-testing-framework/wasp" "github.com/smartcontractkit/chainlink/integration-tests/contracts" ) diff --git a/integration-tests/load/vrfv2plus/vrfv2plus_test.go b/integration-tests/load/vrfv2plus/vrfv2plus_test.go index 98a9375389..bcefe510a6 100644 --- a/integration-tests/load/vrfv2plus/vrfv2plus_test.go +++ b/integration-tests/load/vrfv2plus/vrfv2plus_test.go @@ -9,13 +9,14 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/seth" "github.com/rs/zerolog/log" - "github.com/smartcontractkit/wasp" "github.com/stretchr/testify/require" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/networks" - "github.com/smartcontractkit/chainlink-testing-framework/utils/ptr" - "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" + "github.com/smartcontractkit/chainlink-testing-framework/wasp" + + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/networks" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/ptr" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" "github.com/smartcontractkit/chainlink/integration-tests/actions/vrf/vrfv2plus" "github.com/smartcontractkit/chainlink/integration-tests/contracts" "github.com/smartcontractkit/chainlink/integration-tests/testreporters" diff --git a/integration-tests/load/vrfv2plus/vrfv2pluscmd/dashboard.go b/integration-tests/load/vrfv2plus/vrfv2pluscmd/dashboard.go index 75853e7e21..569a0bd134 100644 --- a/integration-tests/load/vrfv2plus/vrfv2pluscmd/dashboard.go +++ b/integration-tests/load/vrfv2plus/vrfv2pluscmd/dashboard.go @@ -3,7 +3,7 @@ package main import ( "os" - db "github.com/smartcontractkit/wasp/dashboard" + db "github.com/smartcontractkit/chainlink-testing-framework/wasp/dashboard" "github.com/K-Phoen/grabana/dashboard" "github.com/K-Phoen/grabana/logs" diff --git a/integration-tests/load/zcluster/cluster_entrypoint_test.go b/integration-tests/load/zcluster/cluster_entrypoint_test.go index aace97b082..0f3ea5e404 100644 --- a/integration-tests/load/zcluster/cluster_entrypoint_test.go +++ b/integration-tests/load/zcluster/cluster_entrypoint_test.go @@ -3,9 +3,10 @@ package zcluster import ( "testing" - "github.com/smartcontractkit/wasp" "github.com/stretchr/testify/require" + "github.com/smartcontractkit/chainlink-testing-framework/wasp" + tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" ) diff --git a/integration-tests/migration/upgrade_version_test.go b/integration-tests/migration/upgrade_version_test.go index a17f00e179..12f0c2a1e7 100644 --- a/integration-tests/migration/upgrade_version_test.go +++ b/integration-tests/migration/upgrade_version_test.go @@ -5,7 +5,7 @@ import ( "github.com/stretchr/testify/require" - "github.com/smartcontractkit/chainlink-testing-framework/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" diff --git a/integration-tests/reorg/automation_reorg_test.go b/integration-tests/reorg/automation_reorg_test.go index fbfac20d40..22cfaa7ca6 100644 --- a/integration-tests/reorg/automation_reorg_test.go +++ b/integration-tests/reorg/automation_reorg_test.go @@ -14,17 +14,17 @@ import ( "go.uber.org/zap/zapcore" ocr2keepers30config "github.com/smartcontractkit/chainlink-automation/pkg/v3/config" - "github.com/smartcontractkit/chainlink-testing-framework/testreporters" - sethUtils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" + "github.com/smartcontractkit/chainlink-testing-framework/lib/testreporters" + sethUtils "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/seth" "github.com/smartcontractkit/chainlink/integration-tests/actions/automationv2" "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" "github.com/onsi/gomega" "github.com/stretchr/testify/require" - ctfClient "github.com/smartcontractkit/chainlink-testing-framework/client" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" + ctfClient "github.com/smartcontractkit/chainlink-testing-framework/lib/client" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/contracts" diff --git a/integration-tests/runner_helpers.go b/integration-tests/runner_helpers.go index def2ebdc1d..bd3ebfa3e3 100644 --- a/integration-tests/runner_helpers.go +++ b/integration-tests/runner_helpers.go @@ -17,7 +17,7 @@ import ( "github.com/manifoldco/promptui" "github.com/rs/zerolog/log" - "github.com/smartcontractkit/chainlink-testing-framework/networks" + "github.com/smartcontractkit/chainlink-testing-framework/lib/networks" ) func waitForWorkflowRun(branch, ghUser string) (string, error) { diff --git a/integration-tests/smoke/automation_test.go b/integration-tests/smoke/automation_test.go index 92b25dfd52..92cbc95a9d 100644 --- a/integration-tests/smoke/automation_test.go +++ b/integration-tests/smoke/automation_test.go @@ -12,7 +12,7 @@ import ( "testing" "time" - seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/seth" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" @@ -23,9 +23,9 @@ import ( ocr3 "github.com/smartcontractkit/libocr/offchainreporting2plus/ocr3confighelper" ocr2keepers30config "github.com/smartcontractkit/chainlink-automation/pkg/v3/config" - ctfTestEnv "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" + ctfTestEnv "github.com/smartcontractkit/chainlink-testing-framework/lib/docker/test_env" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" "github.com/smartcontractkit/chainlink/integration-tests/actions/automationv2" "github.com/smartcontractkit/chainlink/integration-tests/contracts" diff --git a/integration-tests/smoke/cron_test.go b/integration-tests/smoke/cron_test.go index 98c1fe0caf..51db721518 100644 --- a/integration-tests/smoke/cron_test.go +++ b/integration-tests/smoke/cron_test.go @@ -9,7 +9,7 @@ import ( "github.com/onsi/gomega" "github.com/stretchr/testify/require" - "github.com/smartcontractkit/chainlink-testing-framework/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/client" diff --git a/integration-tests/smoke/flux_test.go b/integration-tests/smoke/flux_test.go index d8773690b2..6f007166b1 100644 --- a/integration-tests/smoke/flux_test.go +++ b/integration-tests/smoke/flux_test.go @@ -12,9 +12,9 @@ import ( "github.com/google/uuid" "github.com/stretchr/testify/require" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" - "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/seth" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/client" diff --git a/integration-tests/smoke/forwarder_ocr_test.go b/integration-tests/smoke/forwarder_ocr_test.go index a249775dc6..e7c550e1d3 100644 --- a/integration-tests/smoke/forwarder_ocr_test.go +++ b/integration-tests/smoke/forwarder_ocr_test.go @@ -6,13 +6,13 @@ import ( "testing" "time" - seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/seth" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/contracts" diff --git a/integration-tests/smoke/forwarders_ocr2_test.go b/integration-tests/smoke/forwarders_ocr2_test.go index 863b36e4ed..58de6d7b11 100644 --- a/integration-tests/smoke/forwarders_ocr2_test.go +++ b/integration-tests/smoke/forwarders_ocr2_test.go @@ -7,13 +7,13 @@ import ( "testing" "time" - seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/seth" "github.com/ethereum/go-ethereum/common" "github.com/stretchr/testify/require" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/contracts" diff --git a/integration-tests/smoke/keeper_test.go b/integration-tests/smoke/keeper_test.go index 9e979dd0ff..21eaf23122 100644 --- a/integration-tests/smoke/keeper_test.go +++ b/integration-tests/smoke/keeper_test.go @@ -8,7 +8,7 @@ import ( "testing" "time" - seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/seth" "github.com/ethereum/go-ethereum/common" "github.com/onsi/gomega" @@ -17,8 +17,8 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/seth" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/client" diff --git a/integration-tests/smoke/log_poller_test.go b/integration-tests/smoke/log_poller_test.go index 18862e13b7..c7f5483ac1 100644 --- a/integration-tests/smoke/log_poller_test.go +++ b/integration-tests/smoke/log_poller_test.go @@ -15,9 +15,9 @@ import ( "github.com/stretchr/testify/require" "go.uber.org/zap/zapcore" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/testreporters" - "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/testreporters" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/contracts" "github.com/smartcontractkit/chainlink/integration-tests/contracts/ethereum" diff --git a/integration-tests/smoke/ocr2_test.go b/integration-tests/smoke/ocr2_test.go index 05f3dfa05c..adcc99ae09 100644 --- a/integration-tests/smoke/ocr2_test.go +++ b/integration-tests/smoke/ocr2_test.go @@ -8,7 +8,7 @@ import ( "testing" "time" - seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/seth" "github.com/ethereum/go-ethereum/common" "github.com/rs/zerolog" @@ -16,9 +16,9 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/seth" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/logstream" - "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logstream" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" "github.com/smartcontractkit/chainlink/v2/core/config/env" diff --git a/integration-tests/smoke/ocr_test.go b/integration-tests/smoke/ocr_test.go index 3d0ec83174..cd6954ac2c 100644 --- a/integration-tests/smoke/ocr_test.go +++ b/integration-tests/smoke/ocr_test.go @@ -5,7 +5,7 @@ import ( "testing" "time" - seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/seth" "github.com/ethereum/go-ethereum/common" "github.com/rs/zerolog" @@ -13,8 +13,8 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/seth" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/contracts" diff --git a/integration-tests/smoke/reorg_above_finality_test.go b/integration-tests/smoke/reorg_above_finality_test.go index 78132848e5..ea7757a9e7 100644 --- a/integration-tests/smoke/reorg_above_finality_test.go +++ b/integration-tests/smoke/reorg_above_finality_test.go @@ -4,12 +4,12 @@ import ( "testing" "time" - ctf_client "github.com/smartcontractkit/chainlink-testing-framework/client" + ctf_client "github.com/smartcontractkit/chainlink-testing-framework/lib/client" "github.com/pelletier/go-toml/v2" "github.com/stretchr/testify/require" - "github.com/smartcontractkit/chainlink-testing-framework/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" diff --git a/integration-tests/smoke/runlog_test.go b/integration-tests/smoke/runlog_test.go index 515d9dea33..922cc9c372 100644 --- a/integration-tests/smoke/runlog_test.go +++ b/integration-tests/smoke/runlog_test.go @@ -7,14 +7,14 @@ import ( "strings" "testing" - seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/seth" "github.com/google/uuid" "github.com/onsi/gomega" "github.com/stretchr/testify/require" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/client" diff --git a/integration-tests/smoke/vrf_test.go b/integration-tests/smoke/vrf_test.go index ac22270216..afef09841b 100644 --- a/integration-tests/smoke/vrf_test.go +++ b/integration-tests/smoke/vrf_test.go @@ -13,9 +13,9 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/seth" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" - "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/seth" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/actions/vrf/vrfv1" diff --git a/integration-tests/smoke/vrfv2_test.go b/integration-tests/smoke/vrfv2_test.go index 73e3d9054b..4ae2553fa0 100644 --- a/integration-tests/smoke/vrfv2_test.go +++ b/integration-tests/smoke/vrfv2_test.go @@ -20,12 +20,12 @@ import ( "go.uber.org/zap/zapcore" commonassets "github.com/smartcontractkit/chainlink-common/pkg/assets" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/networks" - "github.com/smartcontractkit/chainlink-testing-framework/testreporters" - "github.com/smartcontractkit/chainlink-testing-framework/utils/conversions" - "github.com/smartcontractkit/chainlink-testing-framework/utils/ptr" - "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/networks" + "github.com/smartcontractkit/chainlink-testing-framework/lib/testreporters" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/conversions" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/ptr" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" "github.com/smartcontractkit/chainlink/integration-tests/actions" vrfcommon "github.com/smartcontractkit/chainlink/integration-tests/actions/vrf/common" diff --git a/integration-tests/smoke/vrfv2plus_test.go b/integration-tests/smoke/vrfv2plus_test.go index 2d95074ef0..36c61ee91b 100644 --- a/integration-tests/smoke/vrfv2plus_test.go +++ b/integration-tests/smoke/vrfv2plus_test.go @@ -18,12 +18,12 @@ import ( "github.com/stretchr/testify/require" "go.uber.org/zap/zapcore" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/networks" - "github.com/smartcontractkit/chainlink-testing-framework/testreporters" - "github.com/smartcontractkit/chainlink-testing-framework/utils/ptr" - "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" + "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/networks" + "github.com/smartcontractkit/chainlink-testing-framework/lib/testreporters" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/ptr" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" "github.com/smartcontractkit/chainlink/integration-tests/actions" vrfcommon "github.com/smartcontractkit/chainlink/integration-tests/actions/vrf/common" "github.com/smartcontractkit/chainlink/integration-tests/actions/vrf/vrfv2plus" diff --git a/integration-tests/soak/forwarder_ocr_test.go b/integration-tests/soak/forwarder_ocr_test.go index dd7eb10217..3017a1cef2 100644 --- a/integration-tests/soak/forwarder_ocr_test.go +++ b/integration-tests/soak/forwarder_ocr_test.go @@ -5,7 +5,7 @@ import ( "github.com/stretchr/testify/require" - "github.com/smartcontractkit/chainlink-testing-framework/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" "github.com/smartcontractkit/chainlink/integration-tests/actions" tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" diff --git a/integration-tests/soak/ocr_test.go b/integration-tests/soak/ocr_test.go index 1f437e565e..5e53c7d098 100644 --- a/integration-tests/soak/ocr_test.go +++ b/integration-tests/soak/ocr_test.go @@ -4,21 +4,22 @@ import ( "fmt" "testing" - seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" + "github.com/smartcontractkit/chainlink-testing-framework/havoc" + + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/seth" "github.com/stretchr/testify/require" - "github.com/smartcontractkit/chainlink-testing-framework/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" "time" "github.com/chaos-mesh/chaos-mesh/api/v1alpha1" "github.com/google/uuid" - "github.com/smartcontractkit/havoc/k8schaos" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "github.com/smartcontractkit/chainlink-testing-framework/networks" - "github.com/smartcontractkit/chainlink-testing-framework/utils/ptr" + "github.com/smartcontractkit/chainlink-testing-framework/lib/networks" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/ptr" "github.com/smartcontractkit/chainlink/integration-tests/actions" tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" "github.com/smartcontractkit/chainlink/integration-tests/testsetups" @@ -100,7 +101,7 @@ func TestOCRSoak_RPCDownForAllCLNodes(t *testing.T) { require.NoError(t, err, "Error creating chaos") ocrSoakTest, err := testsetups.NewOCRSoakTest(t, &config, testsetups.WithNamespace(namespace), - testsetups.WithChaos([]*k8schaos.Chaos{chaos}), + testsetups.WithChaos([]*havoc.Chaos{chaos}), ) require.NoError(t, err, "Error creating OCR soak test") executeOCRSoakTest(t, ocrSoakTest, &config) @@ -133,7 +134,7 @@ func TestOCRSoak_RPCDownForHalfCLNodes(t *testing.T) { require.NoError(t, err, "Error creating chaos") ocrSoakTest, err := testsetups.NewOCRSoakTest(t, &config, testsetups.WithNamespace(namespace), - testsetups.WithChaos([]*k8schaos.Chaos{chaos}), + testsetups.WithChaos([]*havoc.Chaos{chaos}), ) require.NoError(t, err, "Error creating OCR soak test") executeOCRSoakTest(t, ocrSoakTest, &config) @@ -181,12 +182,12 @@ type GethNetworkDownChaosOpts struct { Duration time.Duration } -func gethNetworkDownChaos(opts GethNetworkDownChaosOpts) (*k8schaos.Chaos, error) { - k8sClient, err := k8schaos.NewChaosMeshClient() +func gethNetworkDownChaos(opts GethNetworkDownChaosOpts) (*havoc.Chaos, error) { + k8sClient, err := havoc.NewChaosMeshClient() if err != nil { return nil, err } - return k8schaos.NewChaos(k8schaos.ChaosOpts{ + return havoc.NewChaos(havoc.ChaosOpts{ Description: opts.Description, DelayCreate: opts.DelayCreate, Object: &v1alpha1.NetworkChaos{ @@ -220,7 +221,7 @@ func gethNetworkDownChaos(opts GethNetworkDownChaosOpts) (*k8schaos.Chaos, error }, }, Client: k8sClient, - Logger: &k8schaos.Logger, + Logger: &havoc.Logger, }) } diff --git a/integration-tests/testconfig/common/vrf/common.go b/integration-tests/testconfig/common/vrf/common.go index e213191075..120bd5c864 100644 --- a/integration-tests/testconfig/common/vrf/common.go +++ b/integration-tests/testconfig/common/vrf/common.go @@ -4,7 +4,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/pkg/errors" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" + "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" ) type Config struct { diff --git a/integration-tests/testconfig/functions/config.go b/integration-tests/testconfig/functions/config.go index 88c0e05295..03adc2f1ec 100644 --- a/integration-tests/testconfig/functions/config.go +++ b/integration-tests/testconfig/functions/config.go @@ -6,8 +6,8 @@ import ( "github.com/ethereum/go-ethereum/common" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - "github.com/smartcontractkit/chainlink-testing-framework/utils/net" + "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/net" ) const ( diff --git a/integration-tests/testconfig/keeper/config.go b/integration-tests/testconfig/keeper/config.go index 0e11266d39..60bdfd8697 100644 --- a/integration-tests/testconfig/keeper/config.go +++ b/integration-tests/testconfig/keeper/config.go @@ -3,7 +3,7 @@ package keeper import ( "errors" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" + "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" ) type Config struct { diff --git a/integration-tests/testconfig/log_poller/config.go b/integration-tests/testconfig/log_poller/config.go index f6e3249432..00b61f6b1b 100644 --- a/integration-tests/testconfig/log_poller/config.go +++ b/integration-tests/testconfig/log_poller/config.go @@ -5,7 +5,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" + "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" ) type GeneratorType = string diff --git a/integration-tests/testconfig/ocr/ocr.go b/integration-tests/testconfig/ocr/ocr.go index f23d647364..d8250d407f 100644 --- a/integration-tests/testconfig/ocr/ocr.go +++ b/integration-tests/testconfig/ocr/ocr.go @@ -3,7 +3,7 @@ package ocr import ( "errors" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" + "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" ) type Config struct { diff --git a/integration-tests/testconfig/ocr2/ocr2.go b/integration-tests/testconfig/ocr2/ocr2.go index 73c9cd1005..1e7f034e04 100644 --- a/integration-tests/testconfig/ocr2/ocr2.go +++ b/integration-tests/testconfig/ocr2/ocr2.go @@ -3,7 +3,7 @@ package ocr2 import ( "errors" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" + "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" ) type Config struct { diff --git a/integration-tests/testconfig/testconfig.go b/integration-tests/testconfig/testconfig.go index 11f73a6ab0..9a910b7e8c 100644 --- a/integration-tests/testconfig/testconfig.go +++ b/integration-tests/testconfig/testconfig.go @@ -19,12 +19,12 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/seth" - ctf_config "github.com/smartcontractkit/chainlink-testing-framework/config" - k8s_config "github.com/smartcontractkit/chainlink-testing-framework/k8s/config" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/networks" - "github.com/smartcontractkit/chainlink-testing-framework/utils/conversions" - "github.com/smartcontractkit/chainlink-testing-framework/utils/osutil" + ctf_config "github.com/smartcontractkit/chainlink-testing-framework/lib/config" + k8s_config "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/config" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/networks" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/conversions" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/osutil" a_config "github.com/smartcontractkit/chainlink/integration-tests/testconfig/automation" f_config "github.com/smartcontractkit/chainlink/integration-tests/testconfig/functions" @@ -522,10 +522,6 @@ func (c *TestConfig) readNetworkConfiguration() error { c.Network.UpperCaseNetworkNames() c.Network.OverrideURLsAndKeysFromEVMNetwork() - err := c.Network.Default() - if err != nil { - return errors.Wrapf(err, "error reading default network config") - } // this is the only value we need to generate dynamically before starting a new simulated chain if c.PrivateEthereumNetwork != nil && c.PrivateEthereumNetwork.EthereumChainConfig != nil { diff --git a/integration-tests/testconfig/testconfig_test.go b/integration-tests/testconfig/testconfig_test.go index 91d2524fcf..6a025c35cc 100644 --- a/integration-tests/testconfig/testconfig_test.go +++ b/integration-tests/testconfig/testconfig_test.go @@ -9,23 +9,24 @@ import ( "github.com/pelletier/go-toml/v2" "github.com/test-go/testify/require" - ctf_config "github.com/smartcontractkit/chainlink-testing-framework/config" - "github.com/smartcontractkit/chainlink-testing-framework/utils/ptr" + ctf_config "github.com/smartcontractkit/chainlink-testing-framework/lib/config" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/ptr" a_config "github.com/smartcontractkit/chainlink/integration-tests/testconfig/automation" ) func TestBase64ConfigRead(t *testing.T) { - networkConfigTOML := ` - [RpcHttpUrls] - arbitrum_goerli = ["https://devnet-1.mt/ABC/rpc/"] - optimism_goerli = ["https://devnet-3.mt/ABC/rpc/"] - - [RpcWsUrls] - arbitrum_goerli = ["wss://devnet-1.mt/ABC/rpc/"] - optimism_goerli = ["wss://devnet-2.mt/ABC/rpc/"] - ` - networksEncoded := base64.StdEncoding.EncodeToString([]byte(networkConfigTOML)) - os.Setenv(ctf_config.Base64NetworkConfigEnvVarName, networksEncoded) + os.Setenv("E2E_TEST_ARBITRUM_GOERLI_RPC_HTTP_URL", "https://devnet-1.mt/ABC/rpc/") + os.Setenv("E2E_TEST_ARBITRUM_GOERLI_RPC_WS_URL", "wss://devnet-1.mt/ABC/rpc/") + os.Setenv("E2E_TEST_ARBITRUM_GOERLI_WALLET_KEY", "0x3333333333333333333333333333333333333333") + defer os.Unsetenv("E2E_TEST_ARBITRUM_GOERLI_RPC_HTTP_URL") + defer os.Unsetenv("E2E_TEST_ARBITRUM_GOERLI_RPC_WS_URL") + defer os.Unsetenv("E2E_TEST_ARBITRUM_GOERLI_WALLET_KEY") + os.Setenv("E2E_TEST_OPTIMISM_GOERLI_RPC_HTTP_URL", "https://devnet-3.mt/ABC/rpc/") + os.Setenv("E2E_TEST_OPTIMISM_GOERLI_RPC_WS_URL", "wss://devnet-3.mt/ABC/rpc/") + os.Setenv("E2E_TEST_OPTIMISM_GOERLI_WALLET_KEY", "0x3333333333333333333333333333333333333333") + defer os.Unsetenv("E2E_TEST_OPTIMISM_GOERLI_RPC_HTTP_URL") + defer os.Unsetenv("E2E_TEST_OPTIMISM_GOERLI_RPC_WS_URL") + defer os.Unsetenv("E2E_TEST_OPTIMISM_GOERLI_WALLET_KEY") testConfig := TestConfig{ Automation: &a_config.Config{ @@ -35,6 +36,8 @@ func TestBase64ConfigRead(t *testing.T) { BlockTime: ptr.Ptr(10), SpecType: ptr.Ptr("minimum"), ChainlinkNodeLogLevel: ptr.Ptr("debug"), + UsePrometheus: ptr.Ptr(true), + RemoveNamespace: ptr.Ptr(true), }, Load: []a_config.Load{ { diff --git a/integration-tests/testreporters/keeper.go b/integration-tests/testreporters/keeper.go index 0861203f31..64e3cfa3d6 100644 --- a/integration-tests/testreporters/keeper.go +++ b/integration-tests/testreporters/keeper.go @@ -13,7 +13,7 @@ import ( "github.com/rs/zerolog/log" "github.com/slack-go/slack" - "github.com/smartcontractkit/chainlink-testing-framework/testreporters" + "github.com/smartcontractkit/chainlink-testing-framework/lib/testreporters" "github.com/smartcontractkit/chainlink/integration-tests/client" ) diff --git a/integration-tests/testreporters/keeper_benchmark.go b/integration-tests/testreporters/keeper_benchmark.go index 230855abb3..4c00c99251 100644 --- a/integration-tests/testreporters/keeper_benchmark.go +++ b/integration-tests/testreporters/keeper_benchmark.go @@ -14,7 +14,7 @@ import ( "github.com/rs/zerolog/log" "github.com/slack-go/slack" - "github.com/smartcontractkit/chainlink-testing-framework/testreporters" + "github.com/smartcontractkit/chainlink-testing-framework/lib/testreporters" "github.com/smartcontractkit/chainlink/integration-tests/client" ) diff --git a/integration-tests/testreporters/ocr.go b/integration-tests/testreporters/ocr.go index 9a9c4d0d4a..89e24fb796 100644 --- a/integration-tests/testreporters/ocr.go +++ b/integration-tests/testreporters/ocr.go @@ -12,7 +12,7 @@ import ( "github.com/rs/zerolog/log" "github.com/slack-go/slack" - "github.com/smartcontractkit/chainlink-testing-framework/testreporters" + "github.com/smartcontractkit/chainlink-testing-framework/lib/testreporters" ) //TODO: This whole process can definitely be simplified and improved, but for some reason I'm getting brain block at the moment diff --git a/integration-tests/testreporters/profile.go b/integration-tests/testreporters/profile.go index 464cfd685e..967ae9eaed 100644 --- a/integration-tests/testreporters/profile.go +++ b/integration-tests/testreporters/profile.go @@ -10,7 +10,7 @@ import ( "github.com/slack-go/slack" "golang.org/x/sync/errgroup" - "github.com/smartcontractkit/chainlink-testing-framework/testreporters" + "github.com/smartcontractkit/chainlink-testing-framework/lib/testreporters" "github.com/smartcontractkit/chainlink/integration-tests/client" ) diff --git a/integration-tests/testreporters/vrfv2.go b/integration-tests/testreporters/vrfv2.go index 5f4e9dcc1f..ba17859512 100644 --- a/integration-tests/testreporters/vrfv2.go +++ b/integration-tests/testreporters/vrfv2.go @@ -8,7 +8,7 @@ import ( "github.com/slack-go/slack" - "github.com/smartcontractkit/chainlink-testing-framework/testreporters" + "github.com/smartcontractkit/chainlink-testing-framework/lib/testreporters" "github.com/smartcontractkit/chainlink/integration-tests/types" ) diff --git a/integration-tests/testreporters/vrfv2plus.go b/integration-tests/testreporters/vrfv2plus.go index cb65b0f3d4..b71c0b7d92 100644 --- a/integration-tests/testreporters/vrfv2plus.go +++ b/integration-tests/testreporters/vrfv2plus.go @@ -11,7 +11,7 @@ import ( "github.com/slack-go/slack" - "github.com/smartcontractkit/chainlink-testing-framework/testreporters" + "github.com/smartcontractkit/chainlink-testing-framework/lib/testreporters" ) type VRFV2PlusTestReporter struct { diff --git a/integration-tests/testsetups/keeper_benchmark.go b/integration-tests/testsetups/keeper_benchmark.go index f6bb041de8..af1e76b1d7 100644 --- a/integration-tests/testsetups/keeper_benchmark.go +++ b/integration-tests/testsetups/keeper_benchmark.go @@ -26,12 +26,12 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/seth" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - reportModel "github.com/smartcontractkit/chainlink-testing-framework/testreporters" - "github.com/smartcontractkit/chainlink-testing-framework/utils/ptr" - "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" + "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/environment" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + reportModel "github.com/smartcontractkit/chainlink-testing-framework/lib/testreporters" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/ptr" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/client" diff --git a/integration-tests/testsetups/ocr.go b/integration-tests/testsetups/ocr.go index 858f6d08a5..34b57558cb 100644 --- a/integration-tests/testsetups/ocr.go +++ b/integration-tests/testsetups/ocr.go @@ -15,8 +15,10 @@ import ( "testing" "time" - "github.com/smartcontractkit/chainlink-testing-framework/grafana" - seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" + "github.com/smartcontractkit/chainlink-testing-framework/havoc" + + "github.com/smartcontractkit/chainlink-testing-framework/lib/grafana" + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/seth" geth "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" @@ -30,21 +32,19 @@ import ( "github.com/smartcontractkit/libocr/gethwrappers/offchainaggregator" "github.com/smartcontractkit/libocr/gethwrappers2/ocr2aggregator" - "github.com/smartcontractkit/havoc/k8schaos" - - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - ctf_client "github.com/smartcontractkit/chainlink-testing-framework/client" - ctf_config "github.com/smartcontractkit/chainlink-testing-framework/config" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/environment" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/chainlink" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/ethereum" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/foundry" - "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/mockserver" - mockservercfg "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/mockserver-cfg" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/networks" - reportModel "github.com/smartcontractkit/chainlink-testing-framework/testreporters" - "github.com/smartcontractkit/chainlink-testing-framework/utils/testcontext" + "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" + ctf_client "github.com/smartcontractkit/chainlink-testing-framework/lib/client" + ctf_config "github.com/smartcontractkit/chainlink-testing-framework/lib/config" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/environment" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/pkg/helm/chainlink" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/pkg/helm/ethereum" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/pkg/helm/foundry" + "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/pkg/helm/mockserver" + mockservercfg "github.com/smartcontractkit/chainlink-testing-framework/lib/k8s/pkg/helm/mockserver-cfg" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/networks" + reportModel "github.com/smartcontractkit/chainlink-testing-framework/lib/testreporters" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/client" @@ -92,12 +92,12 @@ type OCRSoakTest struct { reorgHappened bool // flag to indicate if a reorg happened during the test gasSpikeSimulationHappened bool // flag to indicate if a gas spike simulation happened during the test gasLimitSimulationHappened bool // flag to indicate if a gas limit simulation happened during the test - chaosList []*k8schaos.Chaos // list of chaos simulations to run during the test + chaosList []*havoc.Chaos // list of chaos simulations to run during the test } type OCRSoakTestOption = func(c *OCRSoakTest) -func WithChaos(chaosList []*k8schaos.Chaos) OCRSoakTestOption { +func WithChaos(chaosList []*havoc.Chaos) OCRSoakTestOption { return func(c *OCRSoakTest) { c.chaosList = chaosList } @@ -680,11 +680,11 @@ func (o *OCRSoakTest) testLoop(testDuration time.Duration, newValue int) { if len(o.chaosList) > 0 { for _, chaos := range o.chaosList { chaos.Create(context.Background()) - chaos.AddListener(k8schaos.NewChaosLogger(o.log)) + chaos.AddListener(havoc.NewChaosLogger(o.log)) chaos.AddListener(ocrTestChaosListener{t: o.t}) // Add Grafana annotation if configured if o.Config.Logging.Grafana != nil && o.Config.Logging.Grafana.BaseUrl != nil && o.Config.Logging.Grafana.BearerToken != nil && o.Config.Logging.Grafana.DashboardUID != nil { - chaos.AddListener(k8schaos.NewSingleLineGrafanaAnnotator(*o.Config.Logging.Grafana.BaseUrl, *o.Config.Logging.Grafana.BearerToken, *o.Config.Logging.Grafana.DashboardUID, o.log)) + chaos.AddListener(havoc.NewSingleLineGrafanaAnnotator(*o.Config.Logging.Grafana.BaseUrl, *o.Config.Logging.Grafana.BearerToken, *o.Config.Logging.Grafana.DashboardUID, o.log)) } else { o.log.Warn().Msg("Skipping Grafana annotation for chaos simulation. Grafana config is missing either BearerToken, BaseUrl or DashboardUID") } @@ -1109,28 +1109,28 @@ type ocrTestChaosListener struct { t *testing.T } -func (l ocrTestChaosListener) OnChaosCreated(_ k8schaos.Chaos) { +func (l ocrTestChaosListener) OnChaosCreated(_ havoc.Chaos) { } -func (l ocrTestChaosListener) OnChaosCreationFailed(chaos k8schaos.Chaos, reason error) { +func (l ocrTestChaosListener) OnChaosCreationFailed(chaos havoc.Chaos, reason error) { // Fail the test if chaos creation fails during chaos simulation require.FailNow(l.t, "Error creating chaos simulation", reason.Error(), chaos) } -func (l ocrTestChaosListener) OnChaosStarted(_ k8schaos.Chaos) { +func (l ocrTestChaosListener) OnChaosStarted(_ havoc.Chaos) { } -func (l ocrTestChaosListener) OnChaosPaused(_ k8schaos.Chaos) { +func (l ocrTestChaosListener) OnChaosPaused(_ havoc.Chaos) { } -func (l ocrTestChaosListener) OnChaosEnded(_ k8schaos.Chaos) { +func (l ocrTestChaosListener) OnChaosEnded(_ havoc.Chaos) { } -func (l ocrTestChaosListener) OnChaosStatusUnknown(_ k8schaos.Chaos) { +func (l ocrTestChaosListener) OnChaosStatusUnknown(_ havoc.Chaos) { } -func (l ocrTestChaosListener) OnScheduleCreated(_ k8schaos.Schedule) { +func (l ocrTestChaosListener) OnScheduleCreated(_ havoc.Schedule) { } -func (l ocrTestChaosListener) OnScheduleDeleted(_ k8schaos.Schedule) { +func (l ocrTestChaosListener) OnScheduleDeleted(_ havoc.Schedule) { } diff --git a/integration-tests/types/config/node/core.go b/integration-tests/types/config/node/core.go index 181d57a17e..7b5230f401 100644 --- a/integration-tests/types/config/node/core.go +++ b/integration-tests/types/config/node/core.go @@ -14,8 +14,8 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/config" commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - "github.com/smartcontractkit/chainlink-testing-framework/utils/ptr" + "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/ptr" itutils "github.com/smartcontractkit/chainlink/integration-tests/utils" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" evmcfg "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" diff --git a/integration-tests/types/testconfigs.go b/integration-tests/types/testconfigs.go index ee8a614bae..ee9183589c 100644 --- a/integration-tests/types/testconfigs.go +++ b/integration-tests/types/testconfigs.go @@ -1,8 +1,8 @@ package types import ( - ctf_config "github.com/smartcontractkit/chainlink-testing-framework/config" - "github.com/smartcontractkit/chainlink-testing-framework/testreporters" + ctf_config "github.com/smartcontractkit/chainlink-testing-framework/lib/config" + "github.com/smartcontractkit/chainlink-testing-framework/lib/testreporters" tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" ) diff --git a/integration-tests/universal/log_poller/gun.go b/integration-tests/universal/log_poller/gun.go index a75209aa10..287041ce41 100644 --- a/integration-tests/universal/log_poller/gun.go +++ b/integration-tests/universal/log_poller/gun.go @@ -7,7 +7,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi" "github.com/rs/zerolog" - "github.com/smartcontractkit/wasp" + "github.com/smartcontractkit/chainlink-testing-framework/wasp" "github.com/smartcontractkit/chainlink/integration-tests/contracts" ) diff --git a/integration-tests/universal/log_poller/helpers.go b/integration-tests/universal/log_poller/helpers.go index ce352440ac..d13f40025b 100644 --- a/integration-tests/universal/log_poller/helpers.go +++ b/integration-tests/universal/log_poller/helpers.go @@ -14,7 +14,8 @@ import ( "time" "github.com/jmoiron/sqlx" - "github.com/smartcontractkit/wasp" + + "github.com/smartcontractkit/chainlink-testing-framework/wasp" "github.com/smartcontractkit/chainlink-testing-framework/seth" @@ -26,12 +27,12 @@ import ( "github.com/scylladb/go-reflectx" "github.com/stretchr/testify/require" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" - ctf_concurrency "github.com/smartcontractkit/chainlink-testing-framework/concurrency" - ctf_test_env "github.com/smartcontractkit/chainlink-testing-framework/docker/test_env" - "github.com/smartcontractkit/chainlink-testing-framework/logging" - "github.com/smartcontractkit/chainlink-testing-framework/networks" - seth_utils "github.com/smartcontractkit/chainlink-testing-framework/utils/seth" + "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" + ctf_concurrency "github.com/smartcontractkit/chainlink-testing-framework/lib/concurrency" + ctf_test_env "github.com/smartcontractkit/chainlink-testing-framework/lib/docker/test_env" + "github.com/smartcontractkit/chainlink-testing-framework/lib/logging" + "github.com/smartcontractkit/chainlink-testing-framework/lib/networks" + seth_utils "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/seth" "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/contracts" diff --git a/integration-tests/utils/templates/secrets.go b/integration-tests/utils/templates/secrets.go index 45edf0d012..96a16bdb3e 100644 --- a/integration-tests/utils/templates/secrets.go +++ b/integration-tests/utils/templates/secrets.go @@ -3,7 +3,7 @@ package templates import ( "github.com/google/uuid" - "github.com/smartcontractkit/chainlink-testing-framework/utils/templates" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/templates" ) // NodeSecretsTemplate are used as text templates because of secret redacted fields of chainlink.Secrets diff --git a/integration-tests/web/sdk/internal/generated/generated.go b/integration-tests/web/sdk/internal/generated/generated.go index bcb8106959..6fada0aaa0 100644 --- a/integration-tests/web/sdk/internal/generated/generated.go +++ b/integration-tests/web/sdk/internal/generated/generated.go @@ -8,6 +8,7 @@ import ( "fmt" "github.com/Khan/genqlient/graphql" + "github.com/smartcontractkit/chainlink/v2/core/web/gqlscalar" ) diff --git a/integration-tests/wrappers/contract_caller.go b/integration-tests/wrappers/contract_caller.go index 31672cb915..8669b11e49 100644 --- a/integration-tests/wrappers/contract_caller.go +++ b/integration-tests/wrappers/contract_caller.go @@ -19,7 +19,7 @@ import ( "github.com/smartcontractkit/chainlink-testing-framework/seth" - "github.com/smartcontractkit/chainlink-testing-framework/blockchain" + "github.com/smartcontractkit/chainlink-testing-framework/lib/blockchain" evmClient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" ) From 1eba056f0e9a977d62e76082af7e27a11645d8db Mon Sep 17 00:00:00 2001 From: Balamurali Gopalswami <167726375+b-gopalswami@users.noreply.github.com> Date: Tue, 17 Sep 2024 10:55:09 -0400 Subject: [PATCH 099/115] CCIP-3407: Add release testing configs (#1436) ## Motivation Need to add default configs that are usually used for release testing in beta-testnet or prod-testnet. https://smartcontract-it.atlassian.net/browse/CCIP-3407 ## Solution Have segregated and generalized the configs for release testing however this might need changes depends on the releases. --- integration-tests/ccip-tests/README.md | 6 + .../testnet-beta-workinglane.toml | 283 +++++ .../testnet-beta-workinglane_native.toml | 295 +++++ .../load-prod-testnet.toml} | 2 +- .../smoke-release-testing_native.toml | 1035 +++++++++++++++++ ...release-testing_token_transfer_native.toml | 1035 +++++++++++++++++ ...g_token_transfer_with_native_feetoken.toml | 1013 ++++++++++++++++ 7 files changed, 3668 insertions(+), 1 deletion(-) create mode 100644 integration-tests/ccip-tests/testconfig/tomls/beta-testnet/testnet-beta-workinglane.toml create mode 100644 integration-tests/ccip-tests/testconfig/tomls/beta-testnet/testnet-beta-workinglane_native.toml rename integration-tests/ccip-tests/testconfig/tomls/{ccip1.4-stress/prod-testnet.toml => prod-testnet/load-prod-testnet.toml} (99%) create mode 100644 integration-tests/ccip-tests/testconfig/tomls/prod-testnet/smoke-release-testing_native.toml create mode 100644 integration-tests/ccip-tests/testconfig/tomls/prod-testnet/smoke-release-testing_token_transfer_native.toml create mode 100644 integration-tests/ccip-tests/testconfig/tomls/prod-testnet/soak-release-testing_token_transfer_with_native_feetoken.toml diff --git a/integration-tests/ccip-tests/README.md b/integration-tests/ccip-tests/README.md index 39b8360428..9c4da98dcb 100644 --- a/integration-tests/ccip-tests/README.md +++ b/integration-tests/ccip-tests/README.md @@ -109,3 +109,9 @@ flowchart ### Using Remote Kubernetes Cluster For running more complex and intensive tests (like load and chaos tests) you need to connect the test to a Kubernetes cluster. These tests have more complex setup and running instructions. We endeavor to make these easier to run and configure, but for the time being please seek a member of the QA/Test Tooling team if you want to run these. + +### Live environment testing + +To run against live environments, use the configs available under [beta-testnet](./testconfig/tomls/beta-testnet) +or [prod-testnet](./testconfig/tomls/prod-testnet) directory. Prod testnet has configs for smoke, load and +soak test separately and beta-testnet has smoke and soak combined. \ No newline at end of file diff --git a/integration-tests/ccip-tests/testconfig/tomls/beta-testnet/testnet-beta-workinglane.toml b/integration-tests/ccip-tests/testconfig/tomls/beta-testnet/testnet-beta-workinglane.toml new file mode 100644 index 0000000000..592cb046ad --- /dev/null +++ b/integration-tests/ccip-tests/testconfig/tomls/beta-testnet/testnet-beta-workinglane.toml @@ -0,0 +1,283 @@ +[CCIP] +[CCIP.ContractVersions] +PriceRegistry = 'latest' +OffRamp = 'latest' +OnRamp = 'latest' +TokenPool = 'latest' +CommitStore = 'latest' + +[CCIP.Deployments] +Data = """ +{ + "lane_configs": { + "Arbitrum Sepolia": { + "is_mock_arm": true, + "fee_token": "0xb1D4538B4571d411F07960EF2838Ce337FE1E80E", + "bridge_tokens": null, + "bridge_tokens_pools": null, + "price_aggregators": null, + "arm": "0x2aE6d5495fc20226F433be50e37D59c05D186AaA", + "router": "0x0fF6b6F3Ad10D66600Fd5CC25b98542A05Aa7Bc2", + "price_registry": "0x25d997d8618e1299418b3D905E40bC353ec89F61", + "wrapped_native": "0xE591bf0A0CF924A0674d7792db046B23CEbF5f34", + "src_contracts": { + "Base Sepolia": { + "on_ramp": "0x6BD0f1efA261Ea84DB219c1284b538A65E530ea1", + "deployed_at": 29428386 + }, + "Optimism Sepolia": { + "on_ramp": "0x94cd0d171eF08924F0008305e5Bb90b0fC1b61AB", + "deployed_at": 13945916 + }, + "Sepolia Testnet": { + "on_ramp": "0x44225eb3B73B1b52Dd2ecD258F9b63418eC6Bf79", + "deployed_at": 13730868 + } + }, + "dest_contracts": { + "Base Sepolia": { + "off_ramp": "0x21560B4ACAEdb8AA2Dd935618F15da43197bdc12", + "commit_store": "0x27B882c393151ADD910F3557849AF0bb09c7d5A6", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Optimism Sepolia": { + "off_ramp": "0xAE32FD8Ae148BD88E3da6FaE8Cd7561Eed3ec5Cc", + "commit_store": "0x1f1160Ac7828B647A85c9a6b3A58A232C59D67Ab", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Sepolia Testnet": { + "off_ramp": "0xc136114F379b812345bb7e467ECDdb6D0c87De8b", + "commit_store": "0x42b3EbEA14F6CB803e3C7df84392Efb85CE90168", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "Avalanche Fuji": { + "is_mock_arm": true, + "fee_token": "0x0b9d5D9136855f6FEc3c0993feE6E9CE8a297846", + "bridge_tokens": null, + "bridge_tokens_pools": null, + "price_aggregators": null, + "arm": "0xD4A51dC0F5C680A8A18eA4Ec3A2f25C6db9424B7", + "router": "0xa62e685aDFF45f38eC94378513D128F168964E99", + "price_registry": "0xdbeA1a10AC6a2B729bF128aE9281Ed420dbE7113", + "wrapped_native": "0xd00ae08403B9bbb9124bB305C09058E32C39A48c", + "src_contracts": { + "BSC Testnet": { + "on_ramp": "0xe4f1F7750352f1c37C15C4A314554d6A79d7d146", + "deployed_at": 31437550 + } + }, + "dest_contracts": { + "BSC Testnet": { + "off_ramp": "0x796D720ea9D4326ff356eadE13b123B267C03C80", + "commit_store": "0xaDb37cFd91fa9b6Df1DaAcbAfB4cDFF41e06c956", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "BSC Testnet": { + "is_mock_arm": true, + "fee_token": "0x84b9B910527Ad5C03A9Ca831909E21e236EA7b06", + "bridge_tokens": null, + "bridge_tokens_pools": null, + "price_aggregators": null, + "arm": "0xbBF534D89d9640e3886db25FE1ffE603Fe160D75", + "router": "0x9CdA5b77eA23459eBaf2e3092c570a6B5605850A", + "price_registry": "0x9213967a47FC3F15A16A0b813208e8Ccb63Dbba6", + "wrapped_native": "0xae13d989daC2f0dEbFf460aC112a837C89BAa7cd", + "src_contracts": { + "Avalanche Fuji": { + "on_ramp": "0x0B4F541a7fcE5c251993Bc19D5A40B661e0463f5", + "deployed_at": 39097639 + } + }, + "dest_contracts": { + "Avalanche Fuji": { + "off_ramp": "0x41E59DCdDec18d7f79DA5F76Ce567d2c5e301E6B", + "commit_store": "0x9487C01D4b3Ae1c9Ac8740A07f3862D646548A14", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "Base Sepolia": { + "is_mock_arm": true, + "fee_token": "0xE4aB69C077896252FAFBD49EFD26B5D171A32410", + "bridge_tokens": null, + "bridge_tokens_pools": null, + "price_aggregators": null, + "arm": "0x866faB92E04bAE5EDa238A9cbFf1e56E09508Ade", + "router": "0x2aE6d5495fc20226F433be50e37D59c05D186AaA", + "price_registry": "0xD886E2286Fd1073df82462ea1822119600Af80b6", + "wrapped_native": "0x4200000000000000000000000000000000000006", + "src_contracts": { + "Arbitrum Sepolia": { + "on_ramp": "0xAE32FD8Ae148BD88E3da6FaE8Cd7561Eed3ec5Cc", + "deployed_at": 8133125 + }, + "Optimism Sepolia": { + "on_ramp": "0x9213967a47FC3F15A16A0b813208e8Ccb63Dbba6", + "deployed_at": 11607777 + } + }, + "dest_contracts": { + "Arbitrum Sepolia": { + "off_ramp": "0x34433469A4d6c8b1B0a1a7B91a5C5C2Dd74c67Fb", + "commit_store": "0xFEE7c8E229F538a98437b9A7D0Dd8fCd8A1Ab569", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Optimism Sepolia": { + "off_ramp": "0x0f30449bcCaCCaA7221B3f7C3304c4AaD68068E8", + "commit_store": "0x17a5746c9cf7eAf23533F060F395B2E38eb976ea", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "Optimism Sepolia": { + "is_mock_arm": true, + "fee_token": "0xE4aB69C077896252FAFBD49EFD26B5D171A32410", + "bridge_tokens": null, + "bridge_tokens_pools": null, + "price_aggregators": null, + "arm": "0x2aE6d5495fc20226F433be50e37D59c05D186AaA", + "router": "0x0fF6b6F3Ad10D66600Fd5CC25b98542A05Aa7Bc2", + "price_registry": "0x3B80b7Ef5c00Eb892CBe72800C028C47AD6380EF", + "wrapped_native": "0x4200000000000000000000000000000000000006", + "src_contracts": { + "Arbitrum Sepolia": { + "on_ramp": "0x622CB640F52bFfA68b78b2BD12c1940Ca4899621", + "deployed_at": 8020540 + }, + "Base Sepolia": { + "on_ramp": "0x12c164d0778E215873A062cEE2814507417339cB", + "deployed_at": 13590651 + }, + "Sepolia Testnet": { + "on_ramp": "0x0c2c8D4266C98f1b9333D5E1a42f3f775A0005d4", + "deployed_at": 8020948 + } + }, + "dest_contracts": { + "Arbitrum Sepolia": { + "off_ramp": "0x37004c1245a2D5541377e87cA29699492a4114D5", + "commit_store": "0x51158Ca439feA9E809Bc063CfA6701747b05254e", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Base Sepolia": { + "off_ramp": "0xB3F3f362FbeD49fA0086B434051C822B55BaADbD", + "commit_store": "0xD4995B99c484CCABc868b26c0B2C2Ef10ecde3d7", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Sepolia Testnet": { + "off_ramp": "0x80C2aa80F202FeFdFEEF80f516cFd89768c54057", + "commit_store": "0xc1fE981A040D679511ccb9139ca107aCA67520ef", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "Sepolia Testnet": { + "is_mock_arm": true, + "fee_token": "0x779877A7B0D9E8603169DdbD7836e478b4624789", + "bridge_tokens": null, + "bridge_tokens_pools": null, + "price_aggregators": null, + "arm": "0x9912a7389382ff55f85A29C9378B38F7B992c4aE", + "router": "0x1E1F3d8Ac7Df65fCcFcc52dbF03929cEE95430ac", + "price_registry": "0x4358e81f88bB27222779c1BC85003A11A1c66f6F", + "wrapped_native": "0x097D90c9d3E0B50Ca60e1ae45F6A81010f9FB534", + "src_contracts": { + "Arbitrum Sepolia": { + "on_ramp": "0x420a7B5ABB8CF27A70E1906F797e24509B11093D", + "deployed_at": 5275652 + }, + "Optimism Sepolia": { + "on_ramp": "0xEb4EBC1930bA81416A48a59142D89722163D85ae", + "deployed_at": 5281150 + } + }, + "dest_contracts": { + "Arbitrum Sepolia": { + "off_ramp": "0x224D1eB3aB2b7F23b66f093F9cBBC68dA77a1986", + "commit_store": "0x35c54cF12FF9B29dBa60dc23EdD1de0F13CC7fc5", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Optimism Sepolia": { + "off_ramp": "0xF21d01D6Ef822FBC56FC6c8F23f74fE3A0cb39aa", + "commit_store": "0x7F6AF440Bcc54f70Fd8AC2E534d37196c0bA1A38", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + } + } +} +""" + +[CCIP.Env] +TTL = '8h' + +[CCIP.Env.Network] +selected_networks = [ + 'ARBITRUM_SEPOLIA', + 'AVALANCHE_FUJI', + 'BASE_SEPOLIA', + 'BSC_TESTNET', + 'OPTIMISM_SEPOLIA', + 'SEPOLIA' +] + + + +[CCIP.Groups.smoke] +# these are all the valid network pairs +NetworkPairs = [ + 'BSC_TESTNET,AVALANCHE_FUJI', + 'SEPOLIA,ARBITRUM_SEPOLIA', + 'BASE_SEPOLIA,OPTIMISM_SEPOLIA' +] + +BiDirectionalLane = true +PhaseTimeout = '40m' +LocalCluster = false +ExistingDeployment = true +ReuseContracts = true + + +[CCIP.Groups.smoke.TokenConfig] +NoOfTokensPerChain = 1 +CCIPOwnerTokens = true + +[CCIP.Groups.smoke.MsgDetails] +MsgType = 'Data' +DestGasLimit = 0 +DataLength = 100 +NoOfTokens = 1 +AmountPerToken = 1 + +[CCIP.Groups.load] +NetworkPairs = [ + 'AVALANCHE_FUJI,BSC_TESTNET', + 'SEPOLIA,ARBITRUM_SEPOLIA', + 'BASE_SEPOLIA,OPTIMISM_SEPOLIA' +] + +BiDirectionalLane = true +PhaseTimeout = '40m' +ExistingDeployment = true + +[CCIP.Groups.load.TokenConfig] +NoOfTokensPerChain = 1 + +# Soak Test profile +[CCIP.Groups.load.LoadProfile] +RequestPerUnitTime = [1] +TimeUnit = '6m' +TestDuration = '3h' +TestRunName = 'BetaSoakTest_CCIPV1dot5' +FailOnFirstErrorInLoad = true + +[[CCIP.Groups.load.LoadProfile.MsgProfile.MsgDetails]] +MsgType = 'Data' +DestGasLimit = 0 +DataLength = 100 +NoOfTokens = 1 +AmountPerToken = 1 \ No newline at end of file diff --git a/integration-tests/ccip-tests/testconfig/tomls/beta-testnet/testnet-beta-workinglane_native.toml b/integration-tests/ccip-tests/testconfig/tomls/beta-testnet/testnet-beta-workinglane_native.toml new file mode 100644 index 0000000000..fcc063c765 --- /dev/null +++ b/integration-tests/ccip-tests/testconfig/tomls/beta-testnet/testnet-beta-workinglane_native.toml @@ -0,0 +1,295 @@ +[CCIP] +[CCIP.ContractVersions] +PriceRegistry = 'latest' +OffRamp = 'latest' +OnRamp = 'latest' +TokenPool = 'latest' +CommitStore = 'latest' + +[CCIP.Deployments] +Data = """ +{ + "lane_configs": { + "Arbitrum Sepolia": { + "is_native_fee_token": true, + "is_mock_arm": true, + "fee_token": "0xE591bf0A0CF924A0674d7792db046B23CEbF5f34", + "bridge_tokens": null, + "bridge_tokens_pools": null, + "price_aggregators": null, + "arm": "0x2aE6d5495fc20226F433be50e37D59c05D186AaA", + "router": "0x0fF6b6F3Ad10D66600Fd5CC25b98542A05Aa7Bc2", + "price_registry": "0x25d997d8618e1299418b3D905E40bC353ec89F61", + "wrapped_native": "0xE591bf0A0CF924A0674d7792db046B23CEbF5f34", + "src_contracts": { + "Base Sepolia": { + "on_ramp": "0x6BD0f1efA261Ea84DB219c1284b538A65E530ea1", + "deployed_at": 29428386 + }, + "Optimism Sepolia": { + "on_ramp": "0x94cd0d171eF08924F0008305e5Bb90b0fC1b61AB", + "deployed_at": 13945916 + }, + "Sepolia Testnet": { + "on_ramp": "0x44225eb3B73B1b52Dd2ecD258F9b63418eC6Bf79", + "deployed_at": 13730868 + } + }, + "dest_contracts": { + "Base Sepolia": { + "off_ramp": "0x21560B4ACAEdb8AA2Dd935618F15da43197bdc12", + "commit_store": "0x27B882c393151ADD910F3557849AF0bb09c7d5A6", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Optimism Sepolia": { + "off_ramp": "0xAE32FD8Ae148BD88E3da6FaE8Cd7561Eed3ec5Cc", + "commit_store": "0x1f1160Ac7828B647A85c9a6b3A58A232C59D67Ab", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Sepolia Testnet": { + "off_ramp": "0xc136114F379b812345bb7e467ECDdb6D0c87De8b", + "commit_store": "0x42b3EbEA14F6CB803e3C7df84392Efb85CE90168", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "Avalanche Fuji": { + "is_native_fee_token": true, + "is_mock_arm": true, + "fee_token": "0xd00ae08403B9bbb9124bB305C09058E32C39A48c", + "bridge_tokens": [ + "0x0b9d5D9136855f6FEc3c0993feE6E9CE8a297846" + ], + "bridge_tokens_pools": [ + "0x156943ae87AaF63eA9272902Cb05407ec7bc9464" + ], + "price_aggregators": null, + "arm": "0xD4A51dC0F5C680A8A18eA4Ec3A2f25C6db9424B7", + "router": "0xa62e685aDFF45f38eC94378513D128F168964E99", + "price_registry": "0xdbeA1a10AC6a2B729bF128aE9281Ed420dbE7113", + "wrapped_native": "0xd00ae08403B9bbb9124bB305C09058E32C39A48c", + "src_contracts": { + "BSC Testnet": { + "on_ramp": "0xe4f1F7750352f1c37C15C4A314554d6A79d7d146", + "deployed_at": 31437550 + } + }, + "dest_contracts": { + "BSC Testnet": { + "off_ramp": "0x796D720ea9D4326ff356eadE13b123B267C03C80", + "commit_store": "0xaDb37cFd91fa9b6Df1DaAcbAfB4cDFF41e06c956", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "BSC Testnet": { + "is_native_fee_token": true, + "is_mock_arm": true, + "fee_token": "0xae13d989daC2f0dEbFf460aC112a837C89BAa7cd", + "bridge_tokens": null, + "bridge_tokens_pools": null, + "price_aggregators": null, + "arm": "0xbBF534D89d9640e3886db25FE1ffE603Fe160D75", + "router": "0x9CdA5b77eA23459eBaf2e3092c570a6B5605850A", + "price_registry": "0x9213967a47FC3F15A16A0b813208e8Ccb63Dbba6", + "wrapped_native": "0xae13d989daC2f0dEbFf460aC112a837C89BAa7cd", + "src_contracts": { + "Avalanche Fuji": { + "on_ramp": "0x0B4F541a7fcE5c251993Bc19D5A40B661e0463f5", + "deployed_at": 39097639 + } + }, + "dest_contracts": { + "Avalanche Fuji": { + "off_ramp": "0x41E59DCdDec18d7f79DA5F76Ce567d2c5e301E6B", + "commit_store": "0x9487C01D4b3Ae1c9Ac8740A07f3862D646548A14", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "Base Sepolia": { + "is_native_fee_token": true, + "is_mock_arm": true, + "fee_token": "0x4200000000000000000000000000000000000006", + "bridge_tokens": null, + "bridge_tokens_pools": null, + "price_aggregators": null, + "arm": "0x866faB92E04bAE5EDa238A9cbFf1e56E09508Ade", + "router": "0x2aE6d5495fc20226F433be50e37D59c05D186AaA", + "price_registry": "0xD886E2286Fd1073df82462ea1822119600Af80b6", + "wrapped_native": "0x4200000000000000000000000000000000000006", + "src_contracts": { + "Arbitrum Sepolia": { + "on_ramp": "0xAE32FD8Ae148BD88E3da6FaE8Cd7561Eed3ec5Cc", + "deployed_at": 8133125 + }, + "Optimism Sepolia": { + "on_ramp": "0x9213967a47FC3F15A16A0b813208e8Ccb63Dbba6", + "deployed_at": 11607777 + } + }, + "dest_contracts": { + "Arbitrum Sepolia": { + "off_ramp": "0x34433469A4d6c8b1B0a1a7B91a5C5C2Dd74c67Fb", + "commit_store": "0xFEE7c8E229F538a98437b9A7D0Dd8fCd8A1Ab569", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Optimism Sepolia": { + "off_ramp": "0x0f30449bcCaCCaA7221B3f7C3304c4AaD68068E8", + "commit_store": "0x17a5746c9cf7eAf23533F060F395B2E38eb976ea", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "Optimism Sepolia": { + "is_native_fee_token": true, + "is_mock_arm": true, + "fee_token": "0x4200000000000000000000000000000000000006", + "bridge_tokens": null, + "bridge_tokens_pools": null, + "price_aggregators": null, + "arm": "0x2aE6d5495fc20226F433be50e37D59c05D186AaA", + "router": "0x0fF6b6F3Ad10D66600Fd5CC25b98542A05Aa7Bc2", + "price_registry": "0x3B80b7Ef5c00Eb892CBe72800C028C47AD6380EF", + "wrapped_native": "0x4200000000000000000000000000000000000006", + "src_contracts": { + "Arbitrum Sepolia": { + "on_ramp": "0x622CB640F52bFfA68b78b2BD12c1940Ca4899621", + "deployed_at": 8020540 + }, + "Base Sepolia": { + "on_ramp": "0x12c164d0778E215873A062cEE2814507417339cB", + "deployed_at": 13590651 + }, + "Sepolia Testnet": { + "on_ramp": "0x0c2c8D4266C98f1b9333D5E1a42f3f775A0005d4", + "deployed_at": 8020948 + } + }, + "dest_contracts": { + "Arbitrum Sepolia": { + "off_ramp": "0x37004c1245a2D5541377e87cA29699492a4114D5", + "commit_store": "0x51158Ca439feA9E809Bc063CfA6701747b05254e", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Base Sepolia": { + "off_ramp": "0xB3F3f362FbeD49fA0086B434051C822B55BaADbD", + "commit_store": "0xD4995B99c484CCABc868b26c0B2C2Ef10ecde3d7", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Sepolia Testnet": { + "off_ramp": "0x80C2aa80F202FeFdFEEF80f516cFd89768c54057", + "commit_store": "0xc1fE981A040D679511ccb9139ca107aCA67520ef", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "Sepolia Testnet": { + "is_native_fee_token": true, + "is_mock_arm": true, + "fee_token": "0x097D90c9d3E0B50Ca60e1ae45F6A81010f9FB534", + "bridge_tokens": null, + "bridge_tokens_pools": null, + "price_aggregators": null, + "arm": "0x9912a7389382ff55f85A29C9378B38F7B992c4aE", + "router": "0x1E1F3d8Ac7Df65fCcFcc52dbF03929cEE95430ac", + "price_registry": "0x4358e81f88bB27222779c1BC85003A11A1c66f6F", + "wrapped_native": "0x097D90c9d3E0B50Ca60e1ae45F6A81010f9FB534", + "src_contracts": { + "Arbitrum Sepolia": { + "on_ramp": "0x420a7B5ABB8CF27A70E1906F797e24509B11093D", + "deployed_at": 5275652 + }, + "Optimism Sepolia": { + "on_ramp": "0xEb4EBC1930bA81416A48a59142D89722163D85ae", + "deployed_at": 5281150 + } + }, + "dest_contracts": { + "Arbitrum Sepolia": { + "off_ramp": "0x224D1eB3aB2b7F23b66f093F9cBBC68dA77a1986", + "commit_store": "0x35c54cF12FF9B29dBa60dc23EdD1de0F13CC7fc5", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Optimism Sepolia": { + "off_ramp": "0xF21d01D6Ef822FBC56FC6c8F23f74fE3A0cb39aa", + "commit_store": "0x7F6AF440Bcc54f70Fd8AC2E534d37196c0bA1A38", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + } + } +} +""" + +[CCIP.Env] +TTL = '8h' + +[CCIP.Env.Network] +selected_networks = [ + 'ARBITRUM_SEPOLIA', + 'AVALANCHE_FUJI', + 'BASE_SEPOLIA', + 'BSC_TESTNET', + 'OPTIMISM_SEPOLIA', + 'SEPOLIA', +] + + +[CCIP.Env.NewCLCluster.Common.ChainlinkImage] +version = "sha-17ce920" + +[CCIP.Groups.smoke] +# these are all the valid network pairs +NetworkPairs = [ + 'AVALANCHE_FUJI,BSC_TESTNET', + 'SEPOLIA,ARBITRUM_SEPOLIA', + 'BASE_SEPOLIA,OPTIMISM_SEPOLIA', +] + +BiDirectionalLane = true +PhaseTimeout = '30m' +LocalCluster = false +ExistingDeployment = true +ReuseContracts = true + + +[CCIP.Groups.smoke.TokenConfig] +NoOfTokensPerChain = 1 +CCIPOwnerTokens = true + +[CCIP.Groups.smoke.MsgDetails] +MsgType = 'Data' +DestGasLimit = 0 +DataLength = 100 +NoOfTokens = 1 +AmountPerToken = 1 + +[CCIP.Groups.load] +NetworkPairs = [ + 'AVALANCHE_FUJI,BSC_TESTNET', + 'SEPOLIA,ARBITRUM_SEPOLIA', + 'BASE_SEPOLIA,OPTIMISM_SEPOLIA' +] + +BiDirectionalLane = true +PhaseTimeout = '40m' +ExistingDeployment = true + +[CCIP.Groups.load.TokenConfig] +NoOfTokensPerChain = 1 + +# Soak Test profile +[CCIP.Groups.load.LoadProfile] +RequestPerUnitTime = [1] +TimeUnit = '6m' +TestDuration = '3h' +TestRunName = 'BetaSoakTest_V2.14.0-1.5.1' +FailOnFirstErrorInLoad = true + +[[CCIP.Groups.load.LoadProfile.MsgProfile.MsgDetails]] +MsgType = 'Data' +DestGasLimit = 0 +DataLength = 100 +NoOfTokens = 1 +AmountPerToken = 1 \ No newline at end of file diff --git a/integration-tests/ccip-tests/testconfig/tomls/ccip1.4-stress/prod-testnet.toml b/integration-tests/ccip-tests/testconfig/tomls/prod-testnet/load-prod-testnet.toml similarity index 99% rename from integration-tests/ccip-tests/testconfig/tomls/ccip1.4-stress/prod-testnet.toml rename to integration-tests/ccip-tests/testconfig/tomls/prod-testnet/load-prod-testnet.toml index c4aadb998d..d3c23b0bcb 100644 --- a/integration-tests/ccip-tests/testconfig/tomls/ccip1.4-stress/prod-testnet.toml +++ b/integration-tests/ccip-tests/testconfig/tomls/prod-testnet/load-prod-testnet.toml @@ -199,7 +199,7 @@ NoOfTokensPerChain = 1 RequestPerUnitTime = [12] TimeUnit = '1m' TestDuration = '1h' -TestRunName = 'v2.12.0-ccip1.4.16-load' +TestRunName = 'ccip-prod-testnet-stress' # There is slower exec rounds in Sepolia/Ethereum, therefore reducing the frequency # 1msg/12sec = 5msg/min diff --git a/integration-tests/ccip-tests/testconfig/tomls/prod-testnet/smoke-release-testing_native.toml b/integration-tests/ccip-tests/testconfig/tomls/prod-testnet/smoke-release-testing_native.toml new file mode 100644 index 0000000000..24e7cbc9c8 --- /dev/null +++ b/integration-tests/ccip-tests/testconfig/tomls/prod-testnet/smoke-release-testing_native.toml @@ -0,0 +1,1035 @@ +[CCIP] +[CCIP.ContractVersions] +PriceRegistry = 'latest' +OffRamp = 'latest' +OnRamp = 'latest' +CommitStore = 'latest' +TokenPool = 'latest' + + +[CCIP.Deployments] +Data = """ +{ + "lane_configs": { + "Arbitrum Sepolia": { + "is_native_fee_token": true, + "fee_token": "0xE591bf0A0CF924A0674d7792db046B23CEbF5f34", + "bridge_tokens": [ + "0xA8C0c11bf64AF62CDCA6f93D3769B88BdD7cb93D" + ], + "bridge_tokens_pools": [ + "0x99685281Ec520a003F1A726A5a8078c2124c1477" + ], + "arm": "0xbcBDf0aDEDC9a33ED5338Bdb4B6F7CE664DC2e8B", + "router": "0x2a9C5afB0d0e4BAb2BCdaE109EC4b0c4Be15a165", + "price_registry": "0x89D5b13908b9063abCC6791dc724bF7B7c93634C", + "wrapped_native": "0xE591bf0A0CF924A0674d7792db046B23CEbF5f34", + "src_contracts": { + "Avalanche Fuji": { + "on_ramp": "0x1Cb56374296ED19E86F68fA437ee679FD7798DaA", + "deployed_at": 0 + }, + "Base Sepolia": { + "on_ramp": "0x7854E73C73e7F9bb5b0D5B4861E997f4C6E8dcC6", + "deployed_at": 0 + }, + "Gnosis Chiado": { + "on_ramp": "0x973CbE752258D32AE82b60CD1CB656Eebb588dF0", + "deployed_at": 0 + }, + "Optimism Sepolia": { + "on_ramp": "0x701Fe16916dd21EFE2f535CA59611D818B017877", + "deployed_at": 0 + }, + "Sepolia Testnet": { + "on_ramp": "0x4205E1Ca0202A248A5D42F5975A8FE56F3E302e9", + "deployed_at": 0 + }, + "WeMix Testnet": { + "on_ramp": "0xBD4106fBE4699FE212A34Cc21b10BFf22b02d959", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Avalanche Fuji": { + "off_ramp": "0xcab0EF91Bee323d1A617c0a027eE753aFd6997E4", + "commit_store": "0x0d90b9b96cBFa0D01635ce12982ccE1b70827c7a", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Base Sepolia": { + "off_ramp": "0xc1982985720B959E66c19b64F783361Eb9B60F26", + "commit_store": "0x28F66bB336f6db713d6ad2a3bd1B7a531282A159", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Gnosis Chiado": { + "off_ramp": "0x935C26F9a9122E5F9a27f2d3803e74c75B94f5a3", + "commit_store": "0xEdb963Ec5c2E5AbdFdCF137eF44A445a7fa4787A", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Optimism Sepolia": { + "off_ramp": "0xfD404A89e1d195F0c65be1A9042C77745197659e", + "commit_store": "0x84B7B012c95f8A152B44Ab3e952f2dEE424fA8e1", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Sepolia Testnet": { + "off_ramp": "0x1c71f141b4630EBE52d6aF4894812960abE207eB", + "commit_store": "0xaB0c8Ba51E7Fa3E5693a4Fbb39473520FD85d173", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "WeMix Testnet": { + "off_ramp": "0x262e16C8D42aa07bE13e58F81e7D9F62F6DE2830", + "commit_store": "0xc132eFAf929299E5ee704Fa6D9796CFa23Bb8b2C", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "Avalanche Fuji": { + "is_native_fee_token": true, + "fee_token": "0xd00ae08403B9bbb9124bB305C09058E32C39A48c", + "bridge_tokens": [ + "0xD21341536c5cF5EB1bcb58f6723cE26e8D8E90e4" + ], + "bridge_tokens_pools": [ + "0xEC1062cbDf4fBf31B3A6Aac62B6F6F123bb70E12" + ], + "arm": "0x7e28DD790214139798446A121cFe950B51304684", + "router": "0xF694E193200268f9a4868e4Aa017A0118C9a8177", + "price_registry": "0x19e157E5fb1DAec1aE4BaB113fdf077F980704AA", + "wrapped_native": "0xd00ae08403B9bbb9124bB305C09058E32C39A48c", + "src_contracts": { + "Arbitrum Sepolia": { + "on_ramp": "0x8bB16BEDbFd62D1f905ACe8DBBF2954c8EEB4f66", + "deployed_at": 0 + }, + "BSC Testnet": { + "on_ramp": "0xF25ECF1Aad9B2E43EDc2960cF66f325783245535", + "deployed_at": 0 + }, + "Base Sepolia": { + "on_ramp": "0x1A674645f3EB4147543FCA7d40C5719cbd997362", + "deployed_at": 0 + }, + "Gnosis Chiado": { + "on_ramp": "0x1532e5b204ee2b2244170c78E743CB9c168F4DF9", + "deployed_at": 0 + }, + "Optimism Sepolia": { + "on_ramp": "0xC334DE5b020e056d0fE766dE46e8d9f306Ffa1E2", + "deployed_at": 0 + }, + "Polygon Amoy": { + "on_ramp": "0x610F76A35E17DA4542518D85FfEa12645eF111Fc", + "deployed_at": 0 + }, + "Sepolia Testnet": { + "on_ramp": "0x5724B4Cc39a9690135F7273b44Dfd3BA6c0c69aD", + "deployed_at": 0 + }, + "WeMix Testnet": { + "on_ramp": "0x677B5ab5C8522d929166c064d5700F147b15fa33", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Arbitrum Sepolia": { + "off_ramp": "0x90A74072e7B0c2d59e13aB4d8f93c8198c413194", + "commit_store": "0xf3458CFd2fdf4a6CF0Ce296d520DD21eB194828b", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "BSC Testnet": { + "off_ramp": "0x10b28009E5D776F1f5AAA73941CE8953B8f42d26", + "commit_store": "0xacDD582F271eCF22FAd6764cCDe1c4a534b732A8", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Base Sepolia": { + "off_ramp": "0xdBdE8510226d1E060A3bf982b67705C67f5697e2", + "commit_store": "0x8Ee73BC9492b4182D289E5C1e66e40CD876CC00F", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Gnosis Chiado": { + "off_ramp": "0x56dF55aF5F0A4689f3364230587a68eD6A314fAd", + "commit_store": "0xabA7ff98094c4cc7A075812EefF2CD21f6400235", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Optimism Sepolia": { + "off_ramp": "0x3d7CbC95DCC33257F14D6Eb780c88Bd56C6335BB", + "commit_store": "0x1fcDC02edDfb405f378ba53cF9E6104feBcB7542", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Polygon Amoy": { + "off_ramp": "0x3e33290B90fD0FF30a3FA138934DF028E4eCA348", + "commit_store": "0xCFe3556Aa42d40be09BD23aa80448a19443BE5B1", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Sepolia Testnet": { + "off_ramp": "0x9e5e4324F8608D54A50a317832d456a392E4F8C2", + "commit_store": "0x92A51eD3F041B39EbD1e464C1f7cb1e8f8A8c63f", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "WeMix Testnet": { + "off_ramp": "0xD0D338318bC6837b091FC7AB5F2a94B7783507d5", + "commit_store": "0xd9D479208235c7355848ff4aF26eB5aacfDC30c6", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "BSC Testnet": { + "is_native_fee_token": true, + "fee_token": "0xae13d989daC2f0dEbFf460aC112a837C89BAa7cd", + "bridge_tokens": [ + "0xbFA2ACd33ED6EEc0ed3Cc06bF1ac38d22b36B9e9" + ], + "bridge_tokens_pools": [ + "0x31eDe84776DA37e2404eE88d71c234e92cB672e5" + ], + "arm": "0x7D899D26F2E94fFcd4b440C3008B0C6BEfcD3cca", + "router": "0xE1053aE1857476f36A3C62580FF9b016E8EE8F6f", + "price_registry": "0xCCDf022c9d31DC26Ebab4FB92432724a5b79809a", + "wrapped_native": "0xae13d989daC2f0dEbFf460aC112a837C89BAa7cd", + "src_contracts": { + "Avalanche Fuji": { + "on_ramp": "0xa2515683E99F50ADbE177519A46bb20FfdBaA5de", + "deployed_at": 0 + }, + "Base Sepolia": { + "on_ramp": "0x3E807220Ca84b997c0d1928162227b46C618e0c5", + "deployed_at": 0 + }, + "Gnosis Chiado": { + "on_ramp": "0x8735f991d41eA9cA9D2CC75cD201e4B7C866E63e", + "deployed_at": 0 + }, + "Polygon Amoy": { + "on_ramp": "0xf37CcbfC04adc1B56a46B36F811D52C744a1AF78", + "deployed_at": 0 + }, + "Sepolia Testnet": { + "on_ramp": "0xB1DE44B04C00eaFe9915a3C07a0CaeA4410537dF", + "deployed_at": 0 + }, + "WeMix Testnet": { + "on_ramp": "0x89268Afc1BEA0782a27ba84124E3F42b196af927", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Avalanche Fuji": { + "off_ramp": "0x6e6fFCb6B4BED91ff0CC8C2e57EC029dA7DB80C2", + "commit_store": "0x38Bc38Bd824b6eE87571f9D3CFbe6D6E28E3Dc62", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Base Sepolia": { + "off_ramp": "0x2C61FD7E93Dc79422861282145c59B56dFbc3a8c", + "commit_store": "0x42fAe5B3605804CF6d08632d7A25864e24F792Ae", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Gnosis Chiado": { + "off_ramp": "0x71a44a60832B0F8B63232C9516e7E6aEc3A373Dc", + "commit_store": "0xAC24299a91b72d1Cb5B31147e3CF54964D896974", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Polygon Amoy": { + "off_ramp": "0x63440C7747d37bc6154b5538AE32b54FE0965AfA", + "commit_store": "0xAD22fA198CECfC534927aE1D480c460d5bB3460F", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Sepolia Testnet": { + "off_ramp": "0xf1c128Fe52Ea78CcAAB407509292E61ce38C1523", + "commit_store": "0x59dFD870dC4bd76A7B879A4f705Fdcd2595f85f9", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "WeMix Testnet": { + "off_ramp": "0xfd9B19c3725da5B517aA705B848ff3f21F98280e", + "commit_store": "0x3c1F1412563188aBc8FE3fd53E8F1Cb601CaB4f9", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "Base Sepolia": { + "is_native_fee_token": true, + "fee_token": "0x4200000000000000000000000000000000000006", + "bridge_tokens": [ + "0x88A2d74F47a237a62e7A51cdDa67270CE381555e" + ], + "bridge_tokens_pools": [ + "0x875207858c691F192C606068f417dCf666b2EC6B" + ], + "arm": "0x7827dD0481EE18DB646bD250d20A8eA43da52146", + "router": "0xD3b06cEbF099CE7DA4AcCf578aaebFDBd6e88a93", + "price_registry": "0x4D20536e60832bE579Cd38E89Dc03d11E1741FbA", + "wrapped_native": "0x4200000000000000000000000000000000000006", + "src_contracts": { + "Arbitrum Sepolia": { + "on_ramp": "0x58622a80c6DdDc072F2b527a99BE1D0934eb2b50", + "deployed_at": 0 + }, + "Avalanche Fuji": { + "on_ramp": "0xAbA09a1b7b9f13E05A6241292a66793Ec7d43357", + "deployed_at": 0 + }, + "BSC Testnet": { + "on_ramp": "0xD806966beAB5A3C75E5B90CDA4a6922C6A9F0c9d", + "deployed_at": 0 + }, + "Gnosis Chiado": { + "on_ramp": "0x2Eff2d1BF5C557d6289D208a7a43608f5E3FeCc2", + "deployed_at": 0 + }, + "Mode Sepolia": { + "on_ramp": "0x3d0115386C01436870a2c47e6297962284E70BA6", + "deployed_at": 0 + }, + "Optimism Sepolia": { + "on_ramp": "0x3b39Cd9599137f892Ad57A4f54158198D445D147", + "deployed_at": 0 + }, + "Sepolia Testnet": { + "on_ramp": "0x6486906bB2d85A6c0cCEf2A2831C11A2059ebfea", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Arbitrum Sepolia": { + "off_ramp": "0xd364C06ac99a82a00d3eFF9F2F78E4Abe4b9baAA", + "commit_store": "0xdE8d0f47a71eA3fDFBD3162271652f2847939097", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Avalanche Fuji": { + "off_ramp": "0xAd91214efFee446500940c764DF77AF18427294F", + "commit_store": "0x1242b6c5e0e349b8d4BCf0938f961C4B4f7EA3Fa", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "BSC Testnet": { + "off_ramp": "0xd5E9508921434e8758f4540D55c1c066b7cc1598", + "commit_store": "0x1a86b29364D1B3fA3386329A361aA98A104b2742", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Gnosis Chiado": { + "off_ramp": "0x9Bb7e398ef9Acfe9cA584C39B1E233Cba62BB9f7", + "commit_store": "0x1F4B82cDebaC5e3a0Dd53183D47e51808B4a64cB", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Mode Sepolia": { + "off_ramp": "0xB26647A23e8b4284375e5C74b77c9557aE709D03", + "commit_store": "0x4b4fEB401d3E613e1D6242E155C83A80BF9ac2C9", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Optimism Sepolia": { + "off_ramp": "0x86a3910908eCaAA31Fcd9F0fC8841D8E98f1511d", + "commit_store": "0xE99a87C9b5ed4D2b6060195DEea5106ffF655736", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Sepolia Testnet": { + "off_ramp": "0x189F61D9B886Dd2975D5Abc893c8Cf5f5effda71", + "commit_store": "0xEE7e27346DCD1e711348D0F7f7ECB53a9a3a08a7", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "Blast Sepolia": { + "is_native_fee_token": true, + "fee_token": "0x4200000000000000000000000000000000000023", + "bridge_tokens": [ + "0x8D122C3e8ce9C8B62b87d3551bDfD8C259Bb0771" + ], + "bridge_tokens_pools": [ + "0xFb04129aD1EEDB741CC705ebC1978a7aB63e51f6" + ], + "arm": "0x09c1Ed4b112Fb33e594F2aACfEF407e2F14d7F9b", + "router": "0xfb2f2A207dC428da81fbAFfDDe121761f8Be1194", + "price_registry": "0xc8acE9dF450FaD007755C6C9AB4f0e9c8626E29C", + "wrapped_native": "0x4200000000000000000000000000000000000023", + "src_contracts": { + "Sepolia Testnet": { + "on_ramp": "0x85Ef19FC4C63c70744995DC38CAAEC185E0c619f", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Sepolia Testnet": { + "off_ramp": "0x92cD24C278D34C726f377703E50875d8f9535dC2", + "commit_store": "0xcE1b4D50CeD56850182Bd58Ace91171cB249B873", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "Celo Alfajores": { + "is_native_fee_token": true, + "fee_token": "0x99604d0e2EfE7ABFb58BdE565b5330Bb46Ab3Dca", + "bridge_tokens": [ + "0x7e503dd1dAF90117A1b79953321043d9E6815C72" + ], + "bridge_tokens_pools": [ + "0xC6683ac4a0F62803Bec89a5355B36495ddF2C38b" + ], + "arm": "0xEbe35aA4F5e707485484c992AF2069a457b9bBB1", + "router": "0xb00E95b773528E2Ea724DB06B75113F239D15Dca", + "price_registry": "0x8F048206D11B2c69b8963E2EBd5968D141e022f4", + "wrapped_native": "0x99604d0e2EfE7ABFb58BdE565b5330Bb46Ab3Dca", + "src_contracts": { + "Sepolia Testnet": { + "on_ramp": "0x16a020c4bbdE363FaB8481262D30516AdbcfcFc8", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Sepolia Testnet": { + "off_ramp": "0xa1b97F92D806BA040daf419AFC2765DC723683a4", + "commit_store": "0xcd92C0599Ac515e7588865cC45Eee21A74816aFc", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "Gnosis Chiado": { + "is_native_fee_token": true, + "fee_token": "0x18c8a7ec7897177E4529065a7E7B0878358B3BfF", + "bridge_tokens": [ + "0xA189971a2c5AcA0DFC5Ee7a2C44a2Ae27b3CF389" + ], + "bridge_tokens_pools": [ + "0xF9a21B587111e7E8745Fb8b13750014f19DB0014" + ], + "arm": "0xfE4fB161D870D0F672Ed9C5A898569603f77983F", + "router": "0x19b1bac554111517831ACadc0FD119D23Bb14391", + "price_registry": "0x2F4ACd1f8986c6B1788159C4c9a5fC3fceCCE363", + "wrapped_native": "0x18c8a7ec7897177E4529065a7E7B0878358B3BfF", + "src_contracts": { + "Arbitrum Sepolia": { + "on_ramp": "0x473b49fb592B54a4BfCD55d40E048431982879C9", + "deployed_at": 0 + }, + "Avalanche Fuji": { + "on_ramp": "0x610F76A35E17DA4542518D85FfEa12645eF111Fc", + "deployed_at": 0 + }, + "BSC Testnet": { + "on_ramp": "0xE48E6AA1fc7D0411acEA95F8C6CaD972A37721D4", + "deployed_at": 0 + }, + "Base Sepolia": { + "on_ramp": "0x41b4A51cAfb699D9504E89d19D71F92E886028a8", + "deployed_at": 0 + }, + "Optimism Sepolia": { + "on_ramp": "0xAae733212981e06D9C978Eb5148F8af03F54b6EF", + "deployed_at": 0 + }, + "Polygon Amoy": { + "on_ramp": "0x01800fCDd892e37f7829937271840A6F041bE62E", + "deployed_at": 0 + }, + "Sepolia Testnet": { + "on_ramp": "0x4ac7FBEc2A7298AbDf0E0F4fDC45015836C4bAFe", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Arbitrum Sepolia": { + "off_ramp": "0x9aA82DBB53bf02096B771D40e9432A323a78fB26", + "commit_store": "0x5CdbA91aBC0cD81FC56bc10Ad1835C9E5fB38e5F", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Avalanche Fuji": { + "off_ramp": "0x3e33290B90fD0FF30a3FA138934DF028E4eCA348", + "commit_store": "0xCFe3556Aa42d40be09BD23aa80448a19443BE5B1", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "BSC Testnet": { + "off_ramp": "0xbc4AD54e91b213D4279af92c0C5518c0b96cf62D", + "commit_store": "0xff84e8Dd4Fd17eaBb23b6AeA6e1981830e54389C", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Base Sepolia": { + "off_ramp": "0x4117953A5ceeF12f5B8C1E973b470ab83a8CebA6", + "commit_store": "0x94ad41296186E81f31e1ed0B1BcF5fa9e1721C27", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Optimism Sepolia": { + "off_ramp": "0x33d2898F8fb7714FD1661791766f40754982a343", + "commit_store": "0x55d6Df194472f02CD481e506A277c4A29D0D1bCc", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Polygon Amoy": { + "off_ramp": "0x450543b1d85ca79885851D7b74dc982981b78229", + "commit_store": "0x23B79d940A769FE31b4C867A8BAE80117f24Ca81", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Sepolia Testnet": { + "off_ramp": "0xbf9036529123DE264bFA0FC7362fE25B650D4B16", + "commit_store": "0x5f7F1abD5c5EdaF2636D58B980e85355AF0Ef80d", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "Kroma Sepolia": { + "is_native_fee_token": true, + "fee_token": "0x4200000000000000000000000000000000000001", + "bridge_tokens": [ + "0x6AC3e353D1DDda24d5A5416024d6E436b8817A4e" + ], + "bridge_tokens_pools": [ + "0x0eE8add19554C7bb1920A183Ed47b4FAB9Eb7601" + ], + "arm": "0x08f9Af992368FAc58C936A2c5eBc9092894CEa9b", + "router": "0xA8C0c11bf64AF62CDCA6f93D3769B88BdD7cb93D", + "price_registry": "0xa1ed3A3aA29166C9c8448654A8cA6b7916BC8379", + "wrapped_native": "0x4200000000000000000000000000000000000001", + "src_contracts": { + "WeMix Testnet": { + "on_ramp": "0x6ea155Fc77566D9dcE01B8aa5D7968665dc4f0C5", + "deployed_at": 0 + } + }, + "dest_contracts": { + "WeMix Testnet": { + "off_ramp": "0xB602B6E5Caf08ac0C920EAE585aed100a8cF6f3B", + "commit_store": "0x89D5b13908b9063abCC6791dc724bF7B7c93634C", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "Metis Sepolia": { + "is_native_fee_token": true, + "fee_token": "0x5c48e07062aC4E2Cf4b9A768a711Aef18e8fbdA0", + "bridge_tokens": [ + "0x20Aa09AAb761e2E600d65c6929A9fd1E59821D3f" + ], + "bridge_tokens_pools": [ + "0xdE8451E952Eb43350614839cCAA84f7C8701a09C" + ], + "arm": "0xf0607A9BDdB5F54dB59ACaA0837aFec2D1c95df6", + "router": "0xaCdaBa07ECad81dc634458b98673931DD9d3Bc14", + "price_registry": "0x5DCE866b3ae6E0Ed153f0e149D7203A1B266cdF5", + "wrapped_native": "0x5c48e07062aC4E2Cf4b9A768a711Aef18e8fbdA0", + "src_contracts": { + "Sepolia Testnet": { + "on_ramp": "0x2Eff2d1BF5C557d6289D208a7a43608f5E3FeCc2", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Sepolia Testnet": { + "off_ramp": "0x9Bb7e398ef9Acfe9cA584C39B1E233Cba62BB9f7", + "commit_store": "0x1F4B82cDebaC5e3a0Dd53183D47e51808B4a64cB", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "Mode Sepolia": { + "is_native_fee_token": true, + "fee_token": "0x4200000000000000000000000000000000000006", + "bridge_tokens": [ + "0xB9d4e1141E67ECFedC8A8139b5229b7FF2BF16F5" + ], + "bridge_tokens_pools": [ + "0x20bBc874bE3Cd94C3E4689EDD5D89dD1cE8Cb7C4" + ], + "arm": "0x9eC8a0AbC75ce08978FAf67958482461bCd93B18", + "router": "0xc49ec0eB4beb48B8Da4cceC51AA9A5bD0D0A4c43", + "price_registry": "0xa733ce82a84335b2E9D864312225B0F3D5d80600", + "wrapped_native": "0x4200000000000000000000000000000000000006", + "src_contracts": { + "Base Sepolia": { + "on_ramp": "0x73f7E074bd7291706a0C5412f51DB46441B1aDCB", + "deployed_at": 0 + }, + "Sepolia Testnet": { + "on_ramp": "0xfFdE9E8c34A27BEBeaCcAcB7b3044A0A364455C9", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Base Sepolia": { + "off_ramp": "0x137a38c6b1Ad20101F93516aB2159Df525309168", + "commit_store": "0x8F43d867969F14619895d71E0A5b89E0bb20bF70", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Sepolia Testnet": { + "off_ramp": "0xcD44cec849B6a8eBd5551D6DFeEcA452257Dfe4d", + "commit_store": "0xbA66f08733E6715D33edDfb5a5947676bb45d0e0", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "Optimism Sepolia": { + "is_native_fee_token": true, + "fee_token": "0x4200000000000000000000000000000000000006", + "bridge_tokens": [ + "0x8aF4204e30565DF93352fE8E1De78925F6664dA7" + ], + "bridge_tokens_pools": [ + "0x3Cc9364260D80F09ccAC1eE6B07366dB598900E6" + ], + "arm": "0xF51366F72184E22cF4a7a8362508DB0d3370392d", + "router": "0x114A20A10b43D4115e5aeef7345a1A71d2a60C57", + "price_registry": "0x782a7Ba95215f2F7c3dD4C153cbB2Ae3Ec2d3215", + "wrapped_native": "0x4200000000000000000000000000000000000006", + "src_contracts": { + "Arbitrum Sepolia": { + "on_ramp": "0x1a86b29364D1B3fA3386329A361aA98A104b2742", + "deployed_at": 0 + }, + "Avalanche Fuji": { + "on_ramp": "0x6b38CC6Fa938D5AB09Bdf0CFe580E226fDD793cE", + "deployed_at": 0 + }, + "Base Sepolia": { + "on_ramp": "0xe284D2315a28c4d62C419e8474dC457b219DB969", + "deployed_at": 0 + }, + "Gnosis Chiado": { + "on_ramp": "0x835a5b8e6CA17c2bB5A336c93a4E22478E6F1C8A", + "deployed_at": 0 + }, + "Polygon Amoy": { + "on_ramp": "0x2Cf26fb01E9ccDb831414B766287c0A9e4551089", + "deployed_at": 0 + }, + "Sepolia Testnet": { + "on_ramp": "0xC8b93b46BF682c39B3F65Aa1c135bC8A95A5E43a", + "deployed_at": 0 + }, + "WeMix Testnet": { + "on_ramp": "0xc7E53f6aB982af7A7C3e470c8cCa283d3399BDAd", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Arbitrum Sepolia": { + "off_ramp": "0xDc2c7A3d8068C6F09F0F3648d24C84e372F6014d", + "commit_store": "0xb1aFb5cbE3c29b5Db71F21442BA9EfD450BC23C3", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Avalanche Fuji": { + "off_ramp": "0x1F350718e015EB20E5065C09F4A7a3f66888aEeD", + "commit_store": "0x98650A8EB59f75D93563aB34FcF603b1A30e4CBF", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Base Sepolia": { + "off_ramp": "0x0a750ca77369e03613d7640548F4b2b1c695c3Bb", + "commit_store": "0x8fEBC74C26129C8d7E60288C6dCCc75eb494aA3C", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Gnosis Chiado": { + "off_ramp": "0xCE2CE7F940B7c839384e5D7e079A6aE80e8AD6dB", + "commit_store": "0x1b9D78Ec1CEEC439F0b7eA6C428A1a607D9FA7e4", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Polygon Amoy": { + "off_ramp": "0xD667b5706592D0b040C78fEe5EE17D243b7dCB41", + "commit_store": "0x96101BA5250EE9295c193693C1e08A55bC593664", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Sepolia Testnet": { + "off_ramp": "0x260AF9b83e0d2Bb6C9015fC9f0BfF8858A0CCE68", + "commit_store": "0x7a0bB92Bc8663abe6296d0162A9b41a2Cb2E0358", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "WeMix Testnet": { + "off_ramp": "0x9C08B7712af0344188aa5087D9e6aD0f47191037", + "commit_store": "0x4BE6DB0B884169a6A207fe5cad01eB4C025a13dB", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "Polygon Amoy": { + "is_native_fee_token": true, + "fee_token": "0x360ad4f9a9A8EFe9A8DCB5f461c4Cc1047E1Dcf9", + "bridge_tokens": [ + "0xcab0EF91Bee323d1A617c0a027eE753aFd6997E4" + ], + "bridge_tokens_pools": [ + "0x3064fB3EA546EE09A63AB3bD93E83D8B8525C636" + ], + "arm": "0x8b88C39D2875157aB4CE4AD3814409523d539ee1", + "router": "0x9C32fCB86BF0f4a1A8921a9Fe46de3198bb884B2", + "price_registry": "0xfb2f2A207dC428da81fbAFfDDe121761f8Be1194", + "wrapped_native": "0x360ad4f9a9A8EFe9A8DCB5f461c4Cc1047E1Dcf9", + "src_contracts": { + "Avalanche Fuji": { + "on_ramp": "0x8Fb98b3837578aceEA32b454f3221FE18D7Ce903", + "deployed_at": 0 + }, + "BSC Testnet": { + "on_ramp": "0xC6683ac4a0F62803Bec89a5355B36495ddF2C38b", + "deployed_at": 0 + }, + "Gnosis Chiado": { + "on_ramp": "0x2331F6D614C9Fd613Ff59a1aB727f1EDf6c37A68", + "deployed_at": 0 + }, + "Optimism Sepolia": { + "on_ramp": "0xA52cDAeb43803A80B3c0C2296f5cFe57e695BE11", + "deployed_at": 0 + }, + "Sepolia Testnet": { + "on_ramp": "0x35347A2fC1f2a4c5Eae03339040d0b83b09e6FDA", + "deployed_at": 0 + }, + "WeMix Testnet": { + "on_ramp": "0x26546096F64B5eF9A1DcDAe70Df6F4f8c2E10C61", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Avalanche Fuji": { + "off_ramp": "0xa733ce82a84335b2E9D864312225B0F3D5d80600", + "commit_store": "0x09B0F93fC2111aE439e853884173AC5b2F809885", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "BSC Testnet": { + "off_ramp": "0x948dfaa4842fc23e0e362Fe8D4396AaE4E6DF7EA", + "commit_store": "0x7F4e739D40E58BBd59dAD388171d18e37B26326f", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Gnosis Chiado": { + "off_ramp": "0x17c542a28e08AEF5697251601C7b2B621d153D42", + "commit_store": "0x811250c20fAB9a1b7ca245453aC214ba637fBEB5", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Optimism Sepolia": { + "off_ramp": "0xfFdE9E8c34A27BEBeaCcAcB7b3044A0A364455C9", + "commit_store": "0x74ED442ad211050e9C05Dc9A267E037E3d74A03B", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Sepolia Testnet": { + "off_ramp": "0xFb04129aD1EEDB741CC705ebC1978a7aB63e51f6", + "commit_store": "0x63f875240149d29136053C954Ca164a9BfA81F77", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "WeMix Testnet": { + "off_ramp": "0xdE8451E952Eb43350614839cCAA84f7C8701a09C", + "commit_store": "0xaCdaBa07ECad81dc634458b98673931DD9d3Bc14", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "Sepolia Testnet": { + "is_native_fee_token": true, + "fee_token": "0x097D90c9d3E0B50Ca60e1ae45F6A81010f9FB534", + "bridge_tokens": [ + "0xFd57b4ddBf88a4e07fF4e34C487b99af2Fe82a05" + ], + "bridge_tokens_pools": [ + "0x38d1ef9619Cd40cf5482C045660Ae7C82Ada062c" + ], + "arm": "0x27Da8735d8d1402cEc072C234759fbbB4dABBC4A", + "router": "0x0BF3dE8c5D3e8A2B34D2BEeB17ABfCeBaf363A59", + "price_registry": "0x9EF7D57a4ea30b9e37794E55b0C75F2A70275dCc", + "wrapped_native": "0x097D90c9d3E0B50Ca60e1ae45F6A81010f9FB534", + "src_contracts": { + "Arbitrum Sepolia": { + "on_ramp": "0xe4Dd3B16E09c016402585a8aDFdB4A18f772a07e", + "deployed_at": 0 + }, + "Avalanche Fuji": { + "on_ramp": "0x0477cA0a35eE05D3f9f424d88bC0977ceCf339D4", + "deployed_at": 0 + }, + "BSC Testnet": { + "on_ramp": "0xD990f8aFA5BCB02f95eEd88ecB7C68f5998bD618", + "deployed_at": 0 + }, + "Base Sepolia": { + "on_ramp": "0x2B70a05320cB069e0fB55084D402343F832556E7", + "deployed_at": 0 + }, + "Blast Sepolia": { + "on_ramp": "0xDB75E9D9ca7577CcBd7232741be954cf26194a66", + "deployed_at": 0 + }, + "Celo Alfajores": { + "on_ramp": "0x3C86d16F52C10B2ff6696a0e1b8E0BcfCC085948", + "deployed_at": 0 + }, + "Gnosis Chiado": { + "on_ramp": "0x3E842E3A79A00AFdd03B52390B1caC6306Ea257E", + "deployed_at": 0 + }, + "Metis Sepolia": { + "on_ramp": "0x1C4640914cd57c5f02a68048A0fbb0E12d904223", + "deployed_at": 0 + }, + "Mode Sepolia": { + "on_ramp": "0xc630fbD4D0F6AEB00aD0793FB827b54fBB78e981", + "deployed_at": 0 + }, + "Optimism Sepolia": { + "on_ramp": "0x69CaB5A0a08a12BaFD8f5B195989D709E396Ed4d", + "deployed_at": 0 + }, + "Polygon Amoy": { + "on_ramp": "0x9f656e0361Fb5Df2ac446102c8aB31855B591692", + "deployed_at": 0 + }, + "WeMix Testnet": { + "on_ramp": "0xedFc22336Eb0B9B11Ff37C07777db27BCcDe3C65", + "deployed_at": 0 + }, + "ZKSync Sepolia": { + "on_ramp": "0x1Acb3A885feA37bdA30AB99b99327b14391f500F", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Arbitrum Sepolia": { + "off_ramp": "0xF18896AB20a09A29e64fdEbA99FDb8EC328f43b1", + "commit_store": "0x93Ff9Dd39Dc01eac1fc4d2c9211D95Ee458CAB94", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Avalanche Fuji": { + "off_ramp": "0x000b26f604eAadC3D874a4404bde6D64a97d95ca", + "commit_store": "0x2dD9273F8208B8393350508131270A6574A69784", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "BSC Testnet": { + "off_ramp": "0xdE2d8E126e08d675fCD7fFa5a6CE49925f3Dc692", + "commit_store": "0x0050ac355a82caB31194507f94174297bf0655A7", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Base Sepolia": { + "off_ramp": "0x31c0B81832B333419f0DfD36A69F502cF9094aed", + "commit_store": "0xDFcde9d698a2B32DB2537DC9B752Cadd1D846a52", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Blast Sepolia": { + "off_ramp": "0x4e897e5cF3aC307F0541B2151A88bCD781c153a3", + "commit_store": "0xB656652841F347178e193951C4663652aCe36B74", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Celo Alfajores": { + "off_ramp": "0xB435E0f73c18C5a12C324CA1d02F81F2C3e6e761", + "commit_store": "0xbc5d74957F171e75F92c8F0E1C317A25a56a416D", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Gnosis Chiado": { + "off_ramp": "0x7db0115A0b3AAb01d30bf81123c5DD7B0C41Add5", + "commit_store": "0x6640723Ea801178c4383FA016b9781e7ef1016EF", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Metis Sepolia": { + "off_ramp": "0x4DB693A93E9d5196ECD42EC56CDEAe99dFC652ED", + "commit_store": "0xBfACd78F1412B6f93Ac23409bf456aFec1ABd845", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Mode Sepolia": { + "off_ramp": "0xbEfd8D65F6643De54F0b1268A3bf4618ff85dcB4", + "commit_store": "0x0C161D3470b45Cc677661654C30ce4AdE6aCD288", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Optimism Sepolia": { + "off_ramp": "0xD50590D4438411EDe47029b0FD7901A7145E5Df6", + "commit_store": "0xe85EEE9Fd434A7b8a586Ee086E828abF41839479", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Polygon Amoy": { + "off_ramp": "0x5032cbC0C4aEeD25bb6E45D8B3fAF05DB0688C5d", + "commit_store": "0xe6201C9996Cc7B6E828E10CbE937E693d577D318", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "WeMix Testnet": { + "off_ramp": "0x46b639a3C1a4CBfD326b94a2dB7415c27157282f", + "commit_store": "0x7b74554678816b045c1e7409327E086bD436aa46", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "ZKSync Sepolia": { + "off_ramp": "0xBaABd4166C892a1081a26535875A8fA3f22937b2", + "commit_store": "0xfda2e83F4D3f42B7629134ecD6E4b29FB8A7A07B", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "WeMix Testnet": { + "is_native_fee_token": true, + "fee_token": "0xbE3686643c05f00eC46e73da594c78098F7a9Ae7", + "bridge_tokens": [ + "0xF4E4057FbBc86915F4b2d63EEFFe641C03294ffc" + ], + "bridge_tokens_pools": [ + "0x82A92B2863F93Be70D20660088Ec060720bA2fdb" + ], + "arm": "0x8f6cb63eD5e379722580DFF0A051C140C64F9619", + "router": "0xA8C0c11bf64AF62CDCA6f93D3769B88BdD7cb93D", + "price_registry": "0x89D17571DB7C9540eeB36760E3c749C8fb984569", + "wrapped_native": "0xbE3686643c05f00eC46e73da594c78098F7a9Ae7", + "src_contracts": { + "Arbitrum Sepolia": { + "on_ramp": "0xA9DE3F7A617D67bC50c56baaCb9E0373C15EbfC6", + "deployed_at": 0 + }, + "Avalanche Fuji": { + "on_ramp": "0xC4aC84da458ba8e40210D2dF94C76E9a41f70069", + "deployed_at": 0 + }, + "BSC Testnet": { + "on_ramp": "0x5AD6eed6Be0ffaDCA4105050CF0E584D87E0c2F1", + "deployed_at": 0 + }, + "Kroma Sepolia": { + "on_ramp": "0x428C4dc89b6Bf908B82d77C9CBceA786ea8cc7D0", + "deployed_at": 0 + }, + "Optimism Sepolia": { + "on_ramp": "0x1961a7De751451F410391c251D4D4F98D71B767D", + "deployed_at": 0 + }, + "Polygon Amoy": { + "on_ramp": "0xd55148e841e76265B484d399eC71b7076ecB1216", + "deployed_at": 0 + }, + "Sepolia Testnet": { + "on_ramp": "0x4d57C6d8037C65fa66D6231844785a428310a735", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Arbitrum Sepolia": { + "off_ramp": "0xeB1dFaB2464Bf0574D43e764E0c758f92e7ecAFb", + "commit_store": "0xcEaCa2B7890065c485f3E58657358a185Ad33791", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Avalanche Fuji": { + "off_ramp": "0x98e811Df9D2512f1aaf58D534607F583D6c54A4F", + "commit_store": "0x8e538351F6E5B2daF3c90C565C3738bca69a2716", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "BSC Testnet": { + "off_ramp": "0xB0e7f0fCcD3c961C473E7c44D939C1cDb4Cec1cB", + "commit_store": "0x4B56D8d53f1A6e0117B09700067De99581aA5542", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Kroma Sepolia": { + "off_ramp": "0xD685D2d224dd6D0Db2D56497db6270D77D9a7966", + "commit_store": "0x7e062D6880779a0347e7742058C1b1Ee4AA0B137", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Optimism Sepolia": { + "off_ramp": "0xA5f97Bc69Bf06e7C37B93265c5457420A92c5F4b", + "commit_store": "0xd48b9213583074f518D8f4336FDf35370D450132", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Polygon Amoy": { + "off_ramp": "0x6c8f5999B06FDE17B11E4e3C1062b761766F960f", + "commit_store": "0x957c3c2056192e58A8485eF31165fC490d474239", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Sepolia Testnet": { + "off_ramp": "0x8AB103843ED9D28D2C5DAf5FdB9c3e1CE2B6c876", + "commit_store": "0x7d5297c5506ee2A7Ef121Da9bE02b6a6AD30b392", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "ZKSync Sepolia": { + "is_native_fee_token": true, + "fee_token": "0x4317b2eCD41851173175005783322D29E9bAee9E", + "arm": "0x926b4f90610Aa448f27c8e0Fd0afa4A17B7305F9", + "router": "0xA1fdA8aa9A8C4b945C45aD30647b01f07D7A0B16", + "price_registry": "0x648B6BB09bE1C5766C8AC578B9B4aC8497eA671F", + "wrapped_native": "0x4317b2eCD41851173175005783322D29E9bAee9E", + "src_contracts": { + "Sepolia Testnet": { + "on_ramp": "0x79a9a5e9e318e8e109776569574814bbf935125a", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Sepolia Testnet": { + "off_ramp": "0x18FF69051479796175852578725Fc74F58E963F8", + "commit_store": "0xF694b4FD7889480dca3CD41244e8e3395a9EFBa0", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + } + } +} +""" + +[CCIP.Env] +TTL = '8h' + +[CCIP.Env.Network] +selected_networks = [ + 'ARBITRUM_SEPOLIA', + 'AVALANCHE_FUJI', + 'BASE_SEPOLIA', + 'BLAST_SEPOLIA', + 'BSC_TESTNET', + 'CELO_ALFAJORES', + 'GNOSIS_CHIADO', + 'KROMA_SEPOLIA', + 'MODE_SEPOLIA', + 'OPTIMISM_SEPOLIA', + 'POLYGON_AMOY', + 'SEPOLIA', + 'METIS_SEPOLIA', + 'WEMIX_TESTNET', + 'ZKSYNC_SEPOLIA' +] + +[CCIP.Groups.smoke] +# these are all the valid network pairs +NetworkPairs = [ + 'SEPOLIA,AVALANCHE_FUJI', + 'SEPOLIA,BSC_TESTNET', + 'SEPOLIA,CELO_ALFAJORES', + 'SEPOLIA,ARBITRUM_SEPOLIA', + 'SEPOLIA,BASE_SEPOLIA', + 'SEPOLIA,BLAST_SEPOLIA', + 'SEPOLIA,MODE_SEPOLIA', + 'SEPOLIA,OPTIMISM_SEPOLIA', + 'SEPOLIA,POLYGON_AMOY', + 'SEPOLIA,WEMIX_TESTNET', + 'SEPOLIA,GNOSIS_CHIADO', + 'SEPOLIA,METIS_SEPOLIA', + 'SEPOLIA,ZKSYNC_SEPOLIA', + + 'AVALANCHE_FUJI,BSC_TESTNET', + 'AVALANCHE_FUJI,ARBITRUM_SEPOLIA', + 'AVALANCHE_FUJI,BASE_SEPOLIA', + 'AVALANCHE_FUJI,OPTIMISM_SEPOLIA', + 'AVALANCHE_FUJI,POLYGON_AMOY', + 'AVALANCHE_FUJI,WEMIX_TESTNET', + 'AVALANCHE_FUJI,GNOSIS_CHIADO', + + 'BSC_TESTNET,BASE_SEPOLIA', + 'BSC_TESTNET,POLYGON_AMOY', + 'BSC_TESTNET,WEMIX_TESTNET', + 'BSC_TESTNET,GNOSIS_CHIADO', + + 'ARBITRUM_SEPOLIA,BASE_SEPOLIA', + 'ARBITRUM_SEPOLIA,OPTIMISM_SEPOLIA', + 'ARBITRUM_SEPOLIA,WEMIX_TESTNET', + 'ARBITRUM_SEPOLIA,GNOSIS_CHIADO', + + 'BASE_SEPOLIA,MODE_SEPOLIA', + 'BASE_SEPOLIA,OPTIMISM_SEPOLIA', + 'BASE_SEPOLIA,GNOSIS_CHIADO', + + 'KROMA_SEPOLIA,WEMIX_TESTNET', + + 'OPTIMISM_SEPOLIA,POLYGON_AMOY', + 'OPTIMISM_SEPOLIA,WEMIX_TESTNET', + 'OPTIMISM_SEPOLIA,GNOSIS_CHIADO', + + 'POLYGON_AMOY,WEMIX_TESTNET', + 'POLYGON_AMOY,GNOSIS_CHIADO', +] + +BiDirectionalLane = true +PhaseTimeout = '30m' +LocalCluster = false +ExistingDeployment = true +ReuseContracts = true + + +[CCIP.Groups.smoke.TokenConfig] +NoOfTokensPerChain = 1 +CCIPOwnerTokens = true + +[CCIP.Groups.smoke.MsgDetails] +MsgType = 'Data' +DestGasLimit = 0 +DataLength = 100 +NoOfTokens = 1 +AmountPerToken = 1 \ No newline at end of file diff --git a/integration-tests/ccip-tests/testconfig/tomls/prod-testnet/smoke-release-testing_token_transfer_native.toml b/integration-tests/ccip-tests/testconfig/tomls/prod-testnet/smoke-release-testing_token_transfer_native.toml new file mode 100644 index 0000000000..b1549377fd --- /dev/null +++ b/integration-tests/ccip-tests/testconfig/tomls/prod-testnet/smoke-release-testing_token_transfer_native.toml @@ -0,0 +1,1035 @@ +[CCIP] +[CCIP.ContractVersions] +PriceRegistry = 'latest' +OffRamp = 'latest' +OnRamp = 'latest' +CommitStore = 'latest' +TokenPool = 'latest' + + +[CCIP.Deployments] +Data = """ +{ + "lane_configs": { + "Arbitrum Sepolia": { + "is_native_fee_token": true, + "fee_token": "0xE591bf0A0CF924A0674d7792db046B23CEbF5f34", + "bridge_tokens": [ + "0xA8C0c11bf64AF62CDCA6f93D3769B88BdD7cb93D" + ], + "bridge_tokens_pools": [ + "0x99685281Ec520a003F1A726A5a8078c2124c1477" + ], + "arm": "0xbcBDf0aDEDC9a33ED5338Bdb4B6F7CE664DC2e8B", + "router": "0x2a9C5afB0d0e4BAb2BCdaE109EC4b0c4Be15a165", + "price_registry": "0x89D5b13908b9063abCC6791dc724bF7B7c93634C", + "wrapped_native": "0xE591bf0A0CF924A0674d7792db046B23CEbF5f34", + "src_contracts": { + "Avalanche Fuji": { + "on_ramp": "0x1Cb56374296ED19E86F68fA437ee679FD7798DaA", + "deployed_at": 0 + }, + "Base Sepolia": { + "on_ramp": "0x7854E73C73e7F9bb5b0D5B4861E997f4C6E8dcC6", + "deployed_at": 0 + }, + "Gnosis Chiado": { + "on_ramp": "0x973CbE752258D32AE82b60CD1CB656Eebb588dF0", + "deployed_at": 0 + }, + "Optimism Sepolia": { + "on_ramp": "0x701Fe16916dd21EFE2f535CA59611D818B017877", + "deployed_at": 0 + }, + "Sepolia Testnet": { + "on_ramp": "0x4205E1Ca0202A248A5D42F5975A8FE56F3E302e9", + "deployed_at": 0 + }, + "WeMix Testnet": { + "on_ramp": "0xBD4106fBE4699FE212A34Cc21b10BFf22b02d959", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Avalanche Fuji": { + "off_ramp": "0xcab0EF91Bee323d1A617c0a027eE753aFd6997E4", + "commit_store": "0x0d90b9b96cBFa0D01635ce12982ccE1b70827c7a", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Base Sepolia": { + "off_ramp": "0xc1982985720B959E66c19b64F783361Eb9B60F26", + "commit_store": "0x28F66bB336f6db713d6ad2a3bd1B7a531282A159", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Gnosis Chiado": { + "off_ramp": "0x935C26F9a9122E5F9a27f2d3803e74c75B94f5a3", + "commit_store": "0xEdb963Ec5c2E5AbdFdCF137eF44A445a7fa4787A", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Optimism Sepolia": { + "off_ramp": "0xfD404A89e1d195F0c65be1A9042C77745197659e", + "commit_store": "0x84B7B012c95f8A152B44Ab3e952f2dEE424fA8e1", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Sepolia Testnet": { + "off_ramp": "0x1c71f141b4630EBE52d6aF4894812960abE207eB", + "commit_store": "0xaB0c8Ba51E7Fa3E5693a4Fbb39473520FD85d173", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "WeMix Testnet": { + "off_ramp": "0x262e16C8D42aa07bE13e58F81e7D9F62F6DE2830", + "commit_store": "0xc132eFAf929299E5ee704Fa6D9796CFa23Bb8b2C", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "Avalanche Fuji": { + "is_native_fee_token": true, + "fee_token": "0xd00ae08403B9bbb9124bB305C09058E32C39A48c", + "bridge_tokens": [ + "0xD21341536c5cF5EB1bcb58f6723cE26e8D8E90e4" + ], + "bridge_tokens_pools": [ + "0xEC1062cbDf4fBf31B3A6Aac62B6F6F123bb70E12" + ], + "arm": "0x7e28DD790214139798446A121cFe950B51304684", + "router": "0xF694E193200268f9a4868e4Aa017A0118C9a8177", + "price_registry": "0x19e157E5fb1DAec1aE4BaB113fdf077F980704AA", + "wrapped_native": "0xd00ae08403B9bbb9124bB305C09058E32C39A48c", + "src_contracts": { + "Arbitrum Sepolia": { + "on_ramp": "0x8bB16BEDbFd62D1f905ACe8DBBF2954c8EEB4f66", + "deployed_at": 0 + }, + "BSC Testnet": { + "on_ramp": "0xF25ECF1Aad9B2E43EDc2960cF66f325783245535", + "deployed_at": 0 + }, + "Base Sepolia": { + "on_ramp": "0x1A674645f3EB4147543FCA7d40C5719cbd997362", + "deployed_at": 0 + }, + "Gnosis Chiado": { + "on_ramp": "0x1532e5b204ee2b2244170c78E743CB9c168F4DF9", + "deployed_at": 0 + }, + "Optimism Sepolia": { + "on_ramp": "0xC334DE5b020e056d0fE766dE46e8d9f306Ffa1E2", + "deployed_at": 0 + }, + "Polygon Amoy": { + "on_ramp": "0x610F76A35E17DA4542518D85FfEa12645eF111Fc", + "deployed_at": 0 + }, + "Sepolia Testnet": { + "on_ramp": "0x5724B4Cc39a9690135F7273b44Dfd3BA6c0c69aD", + "deployed_at": 0 + }, + "WeMix Testnet": { + "on_ramp": "0x677B5ab5C8522d929166c064d5700F147b15fa33", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Arbitrum Sepolia": { + "off_ramp": "0x90A74072e7B0c2d59e13aB4d8f93c8198c413194", + "commit_store": "0xf3458CFd2fdf4a6CF0Ce296d520DD21eB194828b", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "BSC Testnet": { + "off_ramp": "0x10b28009E5D776F1f5AAA73941CE8953B8f42d26", + "commit_store": "0xacDD582F271eCF22FAd6764cCDe1c4a534b732A8", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Base Sepolia": { + "off_ramp": "0xdBdE8510226d1E060A3bf982b67705C67f5697e2", + "commit_store": "0x8Ee73BC9492b4182D289E5C1e66e40CD876CC00F", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Gnosis Chiado": { + "off_ramp": "0x56dF55aF5F0A4689f3364230587a68eD6A314fAd", + "commit_store": "0xabA7ff98094c4cc7A075812EefF2CD21f6400235", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Optimism Sepolia": { + "off_ramp": "0x3d7CbC95DCC33257F14D6Eb780c88Bd56C6335BB", + "commit_store": "0x1fcDC02edDfb405f378ba53cF9E6104feBcB7542", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Polygon Amoy": { + "off_ramp": "0x3e33290B90fD0FF30a3FA138934DF028E4eCA348", + "commit_store": "0xCFe3556Aa42d40be09BD23aa80448a19443BE5B1", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Sepolia Testnet": { + "off_ramp": "0x9e5e4324F8608D54A50a317832d456a392E4F8C2", + "commit_store": "0x92A51eD3F041B39EbD1e464C1f7cb1e8f8A8c63f", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "WeMix Testnet": { + "off_ramp": "0xD0D338318bC6837b091FC7AB5F2a94B7783507d5", + "commit_store": "0xd9D479208235c7355848ff4aF26eB5aacfDC30c6", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "BSC Testnet": { + "is_native_fee_token": true, + "fee_token": "0xae13d989daC2f0dEbFf460aC112a837C89BAa7cd", + "bridge_tokens": [ + "0xbFA2ACd33ED6EEc0ed3Cc06bF1ac38d22b36B9e9" + ], + "bridge_tokens_pools": [ + "0x31eDe84776DA37e2404eE88d71c234e92cB672e5" + ], + "arm": "0x7D899D26F2E94fFcd4b440C3008B0C6BEfcD3cca", + "router": "0xE1053aE1857476f36A3C62580FF9b016E8EE8F6f", + "price_registry": "0xCCDf022c9d31DC26Ebab4FB92432724a5b79809a", + "wrapped_native": "0xae13d989daC2f0dEbFf460aC112a837C89BAa7cd", + "src_contracts": { + "Avalanche Fuji": { + "on_ramp": "0xa2515683E99F50ADbE177519A46bb20FfdBaA5de", + "deployed_at": 0 + }, + "Base Sepolia": { + "on_ramp": "0x3E807220Ca84b997c0d1928162227b46C618e0c5", + "deployed_at": 0 + }, + "Gnosis Chiado": { + "on_ramp": "0x8735f991d41eA9cA9D2CC75cD201e4B7C866E63e", + "deployed_at": 0 + }, + "Polygon Amoy": { + "on_ramp": "0xf37CcbfC04adc1B56a46B36F811D52C744a1AF78", + "deployed_at": 0 + }, + "Sepolia Testnet": { + "on_ramp": "0xB1DE44B04C00eaFe9915a3C07a0CaeA4410537dF", + "deployed_at": 0 + }, + "WeMix Testnet": { + "on_ramp": "0x89268Afc1BEA0782a27ba84124E3F42b196af927", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Avalanche Fuji": { + "off_ramp": "0x6e6fFCb6B4BED91ff0CC8C2e57EC029dA7DB80C2", + "commit_store": "0x38Bc38Bd824b6eE87571f9D3CFbe6D6E28E3Dc62", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Base Sepolia": { + "off_ramp": "0x2C61FD7E93Dc79422861282145c59B56dFbc3a8c", + "commit_store": "0x42fAe5B3605804CF6d08632d7A25864e24F792Ae", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Gnosis Chiado": { + "off_ramp": "0x71a44a60832B0F8B63232C9516e7E6aEc3A373Dc", + "commit_store": "0xAC24299a91b72d1Cb5B31147e3CF54964D896974", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Polygon Amoy": { + "off_ramp": "0x63440C7747d37bc6154b5538AE32b54FE0965AfA", + "commit_store": "0xAD22fA198CECfC534927aE1D480c460d5bB3460F", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Sepolia Testnet": { + "off_ramp": "0xf1c128Fe52Ea78CcAAB407509292E61ce38C1523", + "commit_store": "0x59dFD870dC4bd76A7B879A4f705Fdcd2595f85f9", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "WeMix Testnet": { + "off_ramp": "0xfd9B19c3725da5B517aA705B848ff3f21F98280e", + "commit_store": "0x3c1F1412563188aBc8FE3fd53E8F1Cb601CaB4f9", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "Base Sepolia": { + "is_native_fee_token": true, + "fee_token": "0x4200000000000000000000000000000000000006", + "bridge_tokens": [ + "0x88A2d74F47a237a62e7A51cdDa67270CE381555e" + ], + "bridge_tokens_pools": [ + "0x875207858c691F192C606068f417dCf666b2EC6B" + ], + "arm": "0x7827dD0481EE18DB646bD250d20A8eA43da52146", + "router": "0xD3b06cEbF099CE7DA4AcCf578aaebFDBd6e88a93", + "price_registry": "0x4D20536e60832bE579Cd38E89Dc03d11E1741FbA", + "wrapped_native": "0x4200000000000000000000000000000000000006", + "src_contracts": { + "Arbitrum Sepolia": { + "on_ramp": "0x58622a80c6DdDc072F2b527a99BE1D0934eb2b50", + "deployed_at": 0 + }, + "Avalanche Fuji": { + "on_ramp": "0xAbA09a1b7b9f13E05A6241292a66793Ec7d43357", + "deployed_at": 0 + }, + "BSC Testnet": { + "on_ramp": "0xD806966beAB5A3C75E5B90CDA4a6922C6A9F0c9d", + "deployed_at": 0 + }, + "Gnosis Chiado": { + "on_ramp": "0x2Eff2d1BF5C557d6289D208a7a43608f5E3FeCc2", + "deployed_at": 0 + }, + "Mode Sepolia": { + "on_ramp": "0x3d0115386C01436870a2c47e6297962284E70BA6", + "deployed_at": 0 + }, + "Optimism Sepolia": { + "on_ramp": "0x3b39Cd9599137f892Ad57A4f54158198D445D147", + "deployed_at": 0 + }, + "Sepolia Testnet": { + "on_ramp": "0x6486906bB2d85A6c0cCEf2A2831C11A2059ebfea", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Arbitrum Sepolia": { + "off_ramp": "0xd364C06ac99a82a00d3eFF9F2F78E4Abe4b9baAA", + "commit_store": "0xdE8d0f47a71eA3fDFBD3162271652f2847939097", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Avalanche Fuji": { + "off_ramp": "0xAd91214efFee446500940c764DF77AF18427294F", + "commit_store": "0x1242b6c5e0e349b8d4BCf0938f961C4B4f7EA3Fa", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "BSC Testnet": { + "off_ramp": "0xd5E9508921434e8758f4540D55c1c066b7cc1598", + "commit_store": "0x1a86b29364D1B3fA3386329A361aA98A104b2742", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Gnosis Chiado": { + "off_ramp": "0x9Bb7e398ef9Acfe9cA584C39B1E233Cba62BB9f7", + "commit_store": "0x1F4B82cDebaC5e3a0Dd53183D47e51808B4a64cB", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Mode Sepolia": { + "off_ramp": "0xB26647A23e8b4284375e5C74b77c9557aE709D03", + "commit_store": "0x4b4fEB401d3E613e1D6242E155C83A80BF9ac2C9", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Optimism Sepolia": { + "off_ramp": "0x86a3910908eCaAA31Fcd9F0fC8841D8E98f1511d", + "commit_store": "0xE99a87C9b5ed4D2b6060195DEea5106ffF655736", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Sepolia Testnet": { + "off_ramp": "0x189F61D9B886Dd2975D5Abc893c8Cf5f5effda71", + "commit_store": "0xEE7e27346DCD1e711348D0F7f7ECB53a9a3a08a7", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "Blast Sepolia": { + "is_native_fee_token": true, + "fee_token": "0x4200000000000000000000000000000000000023", + "bridge_tokens": [ + "0x8D122C3e8ce9C8B62b87d3551bDfD8C259Bb0771" + ], + "bridge_tokens_pools": [ + "0xFb04129aD1EEDB741CC705ebC1978a7aB63e51f6" + ], + "arm": "0x09c1Ed4b112Fb33e594F2aACfEF407e2F14d7F9b", + "router": "0xfb2f2A207dC428da81fbAFfDDe121761f8Be1194", + "price_registry": "0xc8acE9dF450FaD007755C6C9AB4f0e9c8626E29C", + "wrapped_native": "0x4200000000000000000000000000000000000023", + "src_contracts": { + "Sepolia Testnet": { + "on_ramp": "0x85Ef19FC4C63c70744995DC38CAAEC185E0c619f", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Sepolia Testnet": { + "off_ramp": "0x92cD24C278D34C726f377703E50875d8f9535dC2", + "commit_store": "0xcE1b4D50CeD56850182Bd58Ace91171cB249B873", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "Celo Alfajores": { + "is_native_fee_token": true, + "fee_token": "0x99604d0e2EfE7ABFb58BdE565b5330Bb46Ab3Dca", + "bridge_tokens": [ + "0x7e503dd1dAF90117A1b79953321043d9E6815C72" + ], + "bridge_tokens_pools": [ + "0xC6683ac4a0F62803Bec89a5355B36495ddF2C38b" + ], + "arm": "0xEbe35aA4F5e707485484c992AF2069a457b9bBB1", + "router": "0xb00E95b773528E2Ea724DB06B75113F239D15Dca", + "price_registry": "0x8F048206D11B2c69b8963E2EBd5968D141e022f4", + "wrapped_native": "0x99604d0e2EfE7ABFb58BdE565b5330Bb46Ab3Dca", + "src_contracts": { + "Sepolia Testnet": { + "on_ramp": "0x16a020c4bbdE363FaB8481262D30516AdbcfcFc8", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Sepolia Testnet": { + "off_ramp": "0xa1b97F92D806BA040daf419AFC2765DC723683a4", + "commit_store": "0xcd92C0599Ac515e7588865cC45Eee21A74816aFc", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "Gnosis Chiado": { + "is_native_fee_token": true, + "fee_token": "0x18c8a7ec7897177E4529065a7E7B0878358B3BfF", + "bridge_tokens": [ + "0xA189971a2c5AcA0DFC5Ee7a2C44a2Ae27b3CF389" + ], + "bridge_tokens_pools": [ + "0xF9a21B587111e7E8745Fb8b13750014f19DB0014" + ], + "arm": "0xfE4fB161D870D0F672Ed9C5A898569603f77983F", + "router": "0x19b1bac554111517831ACadc0FD119D23Bb14391", + "price_registry": "0x2F4ACd1f8986c6B1788159C4c9a5fC3fceCCE363", + "wrapped_native": "0x18c8a7ec7897177E4529065a7E7B0878358B3BfF", + "src_contracts": { + "Arbitrum Sepolia": { + "on_ramp": "0x473b49fb592B54a4BfCD55d40E048431982879C9", + "deployed_at": 0 + }, + "Avalanche Fuji": { + "on_ramp": "0x610F76A35E17DA4542518D85FfEa12645eF111Fc", + "deployed_at": 0 + }, + "BSC Testnet": { + "on_ramp": "0xE48E6AA1fc7D0411acEA95F8C6CaD972A37721D4", + "deployed_at": 0 + }, + "Base Sepolia": { + "on_ramp": "0x41b4A51cAfb699D9504E89d19D71F92E886028a8", + "deployed_at": 0 + }, + "Optimism Sepolia": { + "on_ramp": "0xAae733212981e06D9C978Eb5148F8af03F54b6EF", + "deployed_at": 0 + }, + "Polygon Amoy": { + "on_ramp": "0x01800fCDd892e37f7829937271840A6F041bE62E", + "deployed_at": 0 + }, + "Sepolia Testnet": { + "on_ramp": "0x4ac7FBEc2A7298AbDf0E0F4fDC45015836C4bAFe", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Arbitrum Sepolia": { + "off_ramp": "0x9aA82DBB53bf02096B771D40e9432A323a78fB26", + "commit_store": "0x5CdbA91aBC0cD81FC56bc10Ad1835C9E5fB38e5F", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Avalanche Fuji": { + "off_ramp": "0x3e33290B90fD0FF30a3FA138934DF028E4eCA348", + "commit_store": "0xCFe3556Aa42d40be09BD23aa80448a19443BE5B1", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "BSC Testnet": { + "off_ramp": "0xbc4AD54e91b213D4279af92c0C5518c0b96cf62D", + "commit_store": "0xff84e8Dd4Fd17eaBb23b6AeA6e1981830e54389C", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Base Sepolia": { + "off_ramp": "0x4117953A5ceeF12f5B8C1E973b470ab83a8CebA6", + "commit_store": "0x94ad41296186E81f31e1ed0B1BcF5fa9e1721C27", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Optimism Sepolia": { + "off_ramp": "0x33d2898F8fb7714FD1661791766f40754982a343", + "commit_store": "0x55d6Df194472f02CD481e506A277c4A29D0D1bCc", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Polygon Amoy": { + "off_ramp": "0x450543b1d85ca79885851D7b74dc982981b78229", + "commit_store": "0x23B79d940A769FE31b4C867A8BAE80117f24Ca81", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Sepolia Testnet": { + "off_ramp": "0xbf9036529123DE264bFA0FC7362fE25B650D4B16", + "commit_store": "0x5f7F1abD5c5EdaF2636D58B980e85355AF0Ef80d", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "Kroma Sepolia": { + "is_native_fee_token": true, + "fee_token": "0x4200000000000000000000000000000000000001", + "bridge_tokens": [ + "0x6AC3e353D1DDda24d5A5416024d6E436b8817A4e" + ], + "bridge_tokens_pools": [ + "0x0eE8add19554C7bb1920A183Ed47b4FAB9Eb7601" + ], + "arm": "0x08f9Af992368FAc58C936A2c5eBc9092894CEa9b", + "router": "0xA8C0c11bf64AF62CDCA6f93D3769B88BdD7cb93D", + "price_registry": "0xa1ed3A3aA29166C9c8448654A8cA6b7916BC8379", + "wrapped_native": "0x4200000000000000000000000000000000000001", + "src_contracts": { + "WeMix Testnet": { + "on_ramp": "0x6ea155Fc77566D9dcE01B8aa5D7968665dc4f0C5", + "deployed_at": 0 + } + }, + "dest_contracts": { + "WeMix Testnet": { + "off_ramp": "0xB602B6E5Caf08ac0C920EAE585aed100a8cF6f3B", + "commit_store": "0x89D5b13908b9063abCC6791dc724bF7B7c93634C", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "Metis Sepolia": { + "is_native_fee_token": true, + "fee_token": "0x5c48e07062aC4E2Cf4b9A768a711Aef18e8fbdA0", + "bridge_tokens": [ + "0x20Aa09AAb761e2E600d65c6929A9fd1E59821D3f" + ], + "bridge_tokens_pools": [ + "0xdE8451E952Eb43350614839cCAA84f7C8701a09C" + ], + "arm": "0xf0607A9BDdB5F54dB59ACaA0837aFec2D1c95df6", + "router": "0xaCdaBa07ECad81dc634458b98673931DD9d3Bc14", + "price_registry": "0x5DCE866b3ae6E0Ed153f0e149D7203A1B266cdF5", + "wrapped_native": "0x5c48e07062aC4E2Cf4b9A768a711Aef18e8fbdA0", + "src_contracts": { + "Sepolia Testnet": { + "on_ramp": "0x2Eff2d1BF5C557d6289D208a7a43608f5E3FeCc2", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Sepolia Testnet": { + "off_ramp": "0x9Bb7e398ef9Acfe9cA584C39B1E233Cba62BB9f7", + "commit_store": "0x1F4B82cDebaC5e3a0Dd53183D47e51808B4a64cB", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "Mode Sepolia": { + "is_native_fee_token": true, + "fee_token": "0x4200000000000000000000000000000000000006", + "bridge_tokens": [ + "0xB9d4e1141E67ECFedC8A8139b5229b7FF2BF16F5" + ], + "bridge_tokens_pools": [ + "0x20bBc874bE3Cd94C3E4689EDD5D89dD1cE8Cb7C4" + ], + "arm": "0x9eC8a0AbC75ce08978FAf67958482461bCd93B18", + "router": "0xc49ec0eB4beb48B8Da4cceC51AA9A5bD0D0A4c43", + "price_registry": "0xa733ce82a84335b2E9D864312225B0F3D5d80600", + "wrapped_native": "0x4200000000000000000000000000000000000006", + "src_contracts": { + "Base Sepolia": { + "on_ramp": "0x73f7E074bd7291706a0C5412f51DB46441B1aDCB", + "deployed_at": 0 + }, + "Sepolia Testnet": { + "on_ramp": "0xfFdE9E8c34A27BEBeaCcAcB7b3044A0A364455C9", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Base Sepolia": { + "off_ramp": "0x137a38c6b1Ad20101F93516aB2159Df525309168", + "commit_store": "0x8F43d867969F14619895d71E0A5b89E0bb20bF70", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Sepolia Testnet": { + "off_ramp": "0xcD44cec849B6a8eBd5551D6DFeEcA452257Dfe4d", + "commit_store": "0xbA66f08733E6715D33edDfb5a5947676bb45d0e0", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "Optimism Sepolia": { + "is_native_fee_token": true, + "fee_token": "0x4200000000000000000000000000000000000006", + "bridge_tokens": [ + "0x8aF4204e30565DF93352fE8E1De78925F6664dA7" + ], + "bridge_tokens_pools": [ + "0x3Cc9364260D80F09ccAC1eE6B07366dB598900E6" + ], + "arm": "0xF51366F72184E22cF4a7a8362508DB0d3370392d", + "router": "0x114A20A10b43D4115e5aeef7345a1A71d2a60C57", + "price_registry": "0x782a7Ba95215f2F7c3dD4C153cbB2Ae3Ec2d3215", + "wrapped_native": "0x4200000000000000000000000000000000000006", + "src_contracts": { + "Arbitrum Sepolia": { + "on_ramp": "0x1a86b29364D1B3fA3386329A361aA98A104b2742", + "deployed_at": 0 + }, + "Avalanche Fuji": { + "on_ramp": "0x6b38CC6Fa938D5AB09Bdf0CFe580E226fDD793cE", + "deployed_at": 0 + }, + "Base Sepolia": { + "on_ramp": "0xe284D2315a28c4d62C419e8474dC457b219DB969", + "deployed_at": 0 + }, + "Gnosis Chiado": { + "on_ramp": "0x835a5b8e6CA17c2bB5A336c93a4E22478E6F1C8A", + "deployed_at": 0 + }, + "Polygon Amoy": { + "on_ramp": "0x2Cf26fb01E9ccDb831414B766287c0A9e4551089", + "deployed_at": 0 + }, + "Sepolia Testnet": { + "on_ramp": "0xC8b93b46BF682c39B3F65Aa1c135bC8A95A5E43a", + "deployed_at": 0 + }, + "WeMix Testnet": { + "on_ramp": "0xc7E53f6aB982af7A7C3e470c8cCa283d3399BDAd", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Arbitrum Sepolia": { + "off_ramp": "0xDc2c7A3d8068C6F09F0F3648d24C84e372F6014d", + "commit_store": "0xb1aFb5cbE3c29b5Db71F21442BA9EfD450BC23C3", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Avalanche Fuji": { + "off_ramp": "0x1F350718e015EB20E5065C09F4A7a3f66888aEeD", + "commit_store": "0x98650A8EB59f75D93563aB34FcF603b1A30e4CBF", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Base Sepolia": { + "off_ramp": "0x0a750ca77369e03613d7640548F4b2b1c695c3Bb", + "commit_store": "0x8fEBC74C26129C8d7E60288C6dCCc75eb494aA3C", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Gnosis Chiado": { + "off_ramp": "0xCE2CE7F940B7c839384e5D7e079A6aE80e8AD6dB", + "commit_store": "0x1b9D78Ec1CEEC439F0b7eA6C428A1a607D9FA7e4", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Polygon Amoy": { + "off_ramp": "0xD667b5706592D0b040C78fEe5EE17D243b7dCB41", + "commit_store": "0x96101BA5250EE9295c193693C1e08A55bC593664", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Sepolia Testnet": { + "off_ramp": "0x260AF9b83e0d2Bb6C9015fC9f0BfF8858A0CCE68", + "commit_store": "0x7a0bB92Bc8663abe6296d0162A9b41a2Cb2E0358", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "WeMix Testnet": { + "off_ramp": "0x9C08B7712af0344188aa5087D9e6aD0f47191037", + "commit_store": "0x4BE6DB0B884169a6A207fe5cad01eB4C025a13dB", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "Polygon Amoy": { + "is_native_fee_token": true, + "fee_token": "0x360ad4f9a9A8EFe9A8DCB5f461c4Cc1047E1Dcf9", + "bridge_tokens": [ + "0xcab0EF91Bee323d1A617c0a027eE753aFd6997E4" + ], + "bridge_tokens_pools": [ + "0x3064fB3EA546EE09A63AB3bD93E83D8B8525C636" + ], + "arm": "0x8b88C39D2875157aB4CE4AD3814409523d539ee1", + "router": "0x9C32fCB86BF0f4a1A8921a9Fe46de3198bb884B2", + "price_registry": "0xfb2f2A207dC428da81fbAFfDDe121761f8Be1194", + "wrapped_native": "0x360ad4f9a9A8EFe9A8DCB5f461c4Cc1047E1Dcf9", + "src_contracts": { + "Avalanche Fuji": { + "on_ramp": "0x8Fb98b3837578aceEA32b454f3221FE18D7Ce903", + "deployed_at": 0 + }, + "BSC Testnet": { + "on_ramp": "0xC6683ac4a0F62803Bec89a5355B36495ddF2C38b", + "deployed_at": 0 + }, + "Gnosis Chiado": { + "on_ramp": "0x2331F6D614C9Fd613Ff59a1aB727f1EDf6c37A68", + "deployed_at": 0 + }, + "Optimism Sepolia": { + "on_ramp": "0xA52cDAeb43803A80B3c0C2296f5cFe57e695BE11", + "deployed_at": 0 + }, + "Sepolia Testnet": { + "on_ramp": "0x35347A2fC1f2a4c5Eae03339040d0b83b09e6FDA", + "deployed_at": 0 + }, + "WeMix Testnet": { + "on_ramp": "0x26546096F64B5eF9A1DcDAe70Df6F4f8c2E10C61", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Avalanche Fuji": { + "off_ramp": "0xa733ce82a84335b2E9D864312225B0F3D5d80600", + "commit_store": "0x09B0F93fC2111aE439e853884173AC5b2F809885", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "BSC Testnet": { + "off_ramp": "0x948dfaa4842fc23e0e362Fe8D4396AaE4E6DF7EA", + "commit_store": "0x7F4e739D40E58BBd59dAD388171d18e37B26326f", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Gnosis Chiado": { + "off_ramp": "0x17c542a28e08AEF5697251601C7b2B621d153D42", + "commit_store": "0x811250c20fAB9a1b7ca245453aC214ba637fBEB5", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Optimism Sepolia": { + "off_ramp": "0xfFdE9E8c34A27BEBeaCcAcB7b3044A0A364455C9", + "commit_store": "0x74ED442ad211050e9C05Dc9A267E037E3d74A03B", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Sepolia Testnet": { + "off_ramp": "0xFb04129aD1EEDB741CC705ebC1978a7aB63e51f6", + "commit_store": "0x63f875240149d29136053C954Ca164a9BfA81F77", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "WeMix Testnet": { + "off_ramp": "0xdE8451E952Eb43350614839cCAA84f7C8701a09C", + "commit_store": "0xaCdaBa07ECad81dc634458b98673931DD9d3Bc14", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "Sepolia Testnet": { + "is_native_fee_token": true, + "fee_token": "0x097D90c9d3E0B50Ca60e1ae45F6A81010f9FB534", + "bridge_tokens": [ + "0xFd57b4ddBf88a4e07fF4e34C487b99af2Fe82a05" + ], + "bridge_tokens_pools": [ + "0x38d1ef9619Cd40cf5482C045660Ae7C82Ada062c" + ], + "arm": "0x27Da8735d8d1402cEc072C234759fbbB4dABBC4A", + "router": "0x0BF3dE8c5D3e8A2B34D2BEeB17ABfCeBaf363A59", + "price_registry": "0x9EF7D57a4ea30b9e37794E55b0C75F2A70275dCc", + "wrapped_native": "0x097D90c9d3E0B50Ca60e1ae45F6A81010f9FB534", + "src_contracts": { + "Arbitrum Sepolia": { + "on_ramp": "0xe4Dd3B16E09c016402585a8aDFdB4A18f772a07e", + "deployed_at": 0 + }, + "Avalanche Fuji": { + "on_ramp": "0x0477cA0a35eE05D3f9f424d88bC0977ceCf339D4", + "deployed_at": 0 + }, + "BSC Testnet": { + "on_ramp": "0xD990f8aFA5BCB02f95eEd88ecB7C68f5998bD618", + "deployed_at": 0 + }, + "Base Sepolia": { + "on_ramp": "0x2B70a05320cB069e0fB55084D402343F832556E7", + "deployed_at": 0 + }, + "Blast Sepolia": { + "on_ramp": "0xDB75E9D9ca7577CcBd7232741be954cf26194a66", + "deployed_at": 0 + }, + "Celo Alfajores": { + "on_ramp": "0x3C86d16F52C10B2ff6696a0e1b8E0BcfCC085948", + "deployed_at": 0 + }, + "Gnosis Chiado": { + "on_ramp": "0x3E842E3A79A00AFdd03B52390B1caC6306Ea257E", + "deployed_at": 0 + }, + "Metis Sepolia": { + "on_ramp": "0x1C4640914cd57c5f02a68048A0fbb0E12d904223", + "deployed_at": 0 + }, + "Mode Sepolia": { + "on_ramp": "0xc630fbD4D0F6AEB00aD0793FB827b54fBB78e981", + "deployed_at": 0 + }, + "Optimism Sepolia": { + "on_ramp": "0x69CaB5A0a08a12BaFD8f5B195989D709E396Ed4d", + "deployed_at": 0 + }, + "Polygon Amoy": { + "on_ramp": "0x9f656e0361Fb5Df2ac446102c8aB31855B591692", + "deployed_at": 0 + }, + "WeMix Testnet": { + "on_ramp": "0xedFc22336Eb0B9B11Ff37C07777db27BCcDe3C65", + "deployed_at": 0 + }, + "ZKSync Sepolia": { + "on_ramp": "0x1Acb3A885feA37bdA30AB99b99327b14391f500F", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Arbitrum Sepolia": { + "off_ramp": "0xF18896AB20a09A29e64fdEbA99FDb8EC328f43b1", + "commit_store": "0x93Ff9Dd39Dc01eac1fc4d2c9211D95Ee458CAB94", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Avalanche Fuji": { + "off_ramp": "0x000b26f604eAadC3D874a4404bde6D64a97d95ca", + "commit_store": "0x2dD9273F8208B8393350508131270A6574A69784", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "BSC Testnet": { + "off_ramp": "0xdE2d8E126e08d675fCD7fFa5a6CE49925f3Dc692", + "commit_store": "0x0050ac355a82caB31194507f94174297bf0655A7", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Base Sepolia": { + "off_ramp": "0x31c0B81832B333419f0DfD36A69F502cF9094aed", + "commit_store": "0xDFcde9d698a2B32DB2537DC9B752Cadd1D846a52", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Blast Sepolia": { + "off_ramp": "0x4e897e5cF3aC307F0541B2151A88bCD781c153a3", + "commit_store": "0xB656652841F347178e193951C4663652aCe36B74", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Celo Alfajores": { + "off_ramp": "0xB435E0f73c18C5a12C324CA1d02F81F2C3e6e761", + "commit_store": "0xbc5d74957F171e75F92c8F0E1C317A25a56a416D", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Gnosis Chiado": { + "off_ramp": "0x7db0115A0b3AAb01d30bf81123c5DD7B0C41Add5", + "commit_store": "0x6640723Ea801178c4383FA016b9781e7ef1016EF", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Metis Sepolia": { + "off_ramp": "0x4DB693A93E9d5196ECD42EC56CDEAe99dFC652ED", + "commit_store": "0xBfACd78F1412B6f93Ac23409bf456aFec1ABd845", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Mode Sepolia": { + "off_ramp": "0xbEfd8D65F6643De54F0b1268A3bf4618ff85dcB4", + "commit_store": "0x0C161D3470b45Cc677661654C30ce4AdE6aCD288", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Optimism Sepolia": { + "off_ramp": "0xD50590D4438411EDe47029b0FD7901A7145E5Df6", + "commit_store": "0xe85EEE9Fd434A7b8a586Ee086E828abF41839479", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Polygon Amoy": { + "off_ramp": "0x5032cbC0C4aEeD25bb6E45D8B3fAF05DB0688C5d", + "commit_store": "0xe6201C9996Cc7B6E828E10CbE937E693d577D318", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "WeMix Testnet": { + "off_ramp": "0x46b639a3C1a4CBfD326b94a2dB7415c27157282f", + "commit_store": "0x7b74554678816b045c1e7409327E086bD436aa46", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "ZKSync Sepolia": { + "off_ramp": "0xBaABd4166C892a1081a26535875A8fA3f22937b2", + "commit_store": "0xfda2e83F4D3f42B7629134ecD6E4b29FB8A7A07B", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "WeMix Testnet": { + "is_native_fee_token": true, + "fee_token": "0xbE3686643c05f00eC46e73da594c78098F7a9Ae7", + "bridge_tokens": [ + "0xF4E4057FbBc86915F4b2d63EEFFe641C03294ffc" + ], + "bridge_tokens_pools": [ + "0x82A92B2863F93Be70D20660088Ec060720bA2fdb" + ], + "arm": "0x8f6cb63eD5e379722580DFF0A051C140C64F9619", + "router": "0xA8C0c11bf64AF62CDCA6f93D3769B88BdD7cb93D", + "price_registry": "0x89D17571DB7C9540eeB36760E3c749C8fb984569", + "wrapped_native": "0xbE3686643c05f00eC46e73da594c78098F7a9Ae7", + "src_contracts": { + "Arbitrum Sepolia": { + "on_ramp": "0xA9DE3F7A617D67bC50c56baaCb9E0373C15EbfC6", + "deployed_at": 0 + }, + "Avalanche Fuji": { + "on_ramp": "0xC4aC84da458ba8e40210D2dF94C76E9a41f70069", + "deployed_at": 0 + }, + "BSC Testnet": { + "on_ramp": "0x5AD6eed6Be0ffaDCA4105050CF0E584D87E0c2F1", + "deployed_at": 0 + }, + "Kroma Sepolia": { + "on_ramp": "0x428C4dc89b6Bf908B82d77C9CBceA786ea8cc7D0", + "deployed_at": 0 + }, + "Optimism Sepolia": { + "on_ramp": "0x1961a7De751451F410391c251D4D4F98D71B767D", + "deployed_at": 0 + }, + "Polygon Amoy": { + "on_ramp": "0xd55148e841e76265B484d399eC71b7076ecB1216", + "deployed_at": 0 + }, + "Sepolia Testnet": { + "on_ramp": "0x4d57C6d8037C65fa66D6231844785a428310a735", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Arbitrum Sepolia": { + "off_ramp": "0xeB1dFaB2464Bf0574D43e764E0c758f92e7ecAFb", + "commit_store": "0xcEaCa2B7890065c485f3E58657358a185Ad33791", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Avalanche Fuji": { + "off_ramp": "0x98e811Df9D2512f1aaf58D534607F583D6c54A4F", + "commit_store": "0x8e538351F6E5B2daF3c90C565C3738bca69a2716", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "BSC Testnet": { + "off_ramp": "0xB0e7f0fCcD3c961C473E7c44D939C1cDb4Cec1cB", + "commit_store": "0x4B56D8d53f1A6e0117B09700067De99581aA5542", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Kroma Sepolia": { + "off_ramp": "0xD685D2d224dd6D0Db2D56497db6270D77D9a7966", + "commit_store": "0x7e062D6880779a0347e7742058C1b1Ee4AA0B137", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Optimism Sepolia": { + "off_ramp": "0xA5f97Bc69Bf06e7C37B93265c5457420A92c5F4b", + "commit_store": "0xd48b9213583074f518D8f4336FDf35370D450132", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Polygon Amoy": { + "off_ramp": "0x6c8f5999B06FDE17B11E4e3C1062b761766F960f", + "commit_store": "0x957c3c2056192e58A8485eF31165fC490d474239", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Sepolia Testnet": { + "off_ramp": "0x8AB103843ED9D28D2C5DAf5FdB9c3e1CE2B6c876", + "commit_store": "0x7d5297c5506ee2A7Ef121Da9bE02b6a6AD30b392", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "ZKSync Sepolia": { + "is_native_fee_token": true, + "fee_token": "0x4317b2eCD41851173175005783322D29E9bAee9E", + "arm": "0x926b4f90610Aa448f27c8e0Fd0afa4A17B7305F9", + "router": "0xA1fdA8aa9A8C4b945C45aD30647b01f07D7A0B16", + "price_registry": "0x648B6BB09bE1C5766C8AC578B9B4aC8497eA671F", + "wrapped_native": "0x4317b2eCD41851173175005783322D29E9bAee9E", + "src_contracts": { + "Sepolia Testnet": { + "on_ramp": "0x79a9a5e9e318e8e109776569574814bbf935125a", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Sepolia Testnet": { + "off_ramp": "0x18FF69051479796175852578725Fc74F58E963F8", + "commit_store": "0xF694b4FD7889480dca3CD41244e8e3395a9EFBa0", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + } + } +} +""" + +[CCIP.Env] +TTL = '8h' + +[CCIP.Env.Network] +selected_networks = [ + 'ARBITRUM_SEPOLIA', + 'AVALANCHE_FUJI', + 'BASE_SEPOLIA', + 'BLAST_SEPOLIA', + 'BSC_TESTNET', + 'CELO_ALFAJORES', + 'GNOSIS_CHIADO', + 'KROMA_SEPOLIA', + 'MODE_SEPOLIA', + 'OPTIMISM_SEPOLIA', + 'POLYGON_AMOY', + 'SEPOLIA', + 'METIS_SEPOLIA', + 'WEMIX_TESTNET', + 'ZKSYNC_SEPOLIA' +] + +[CCIP.Groups.smoke] +# these are all the valid network pairs +NetworkPairs = [ + 'SEPOLIA,AVALANCHE_FUJI', + 'SEPOLIA,BSC_TESTNET', + 'SEPOLIA,CELO_ALFAJORES', + 'SEPOLIA,ARBITRUM_SEPOLIA', + 'SEPOLIA,BASE_SEPOLIA', + 'SEPOLIA,BLAST_SEPOLIA', + 'SEPOLIA,MODE_SEPOLIA', + 'SEPOLIA,OPTIMISM_SEPOLIA', + 'SEPOLIA,POLYGON_AMOY', + 'SEPOLIA,WEMIX_TESTNET', + 'SEPOLIA,GNOSIS_CHIADO', + 'SEPOLIA,METIS_SEPOLIA', + 'SEPOLIA,ZKSYNC_SEPOLIA', + + 'AVALANCHE_FUJI,BSC_TESTNET', + 'AVALANCHE_FUJI,ARBITRUM_SEPOLIA', + 'AVALANCHE_FUJI,BASE_SEPOLIA', + 'AVALANCHE_FUJI,OPTIMISM_SEPOLIA', + 'AVALANCHE_FUJI,POLYGON_AMOY', + 'AVALANCHE_FUJI,WEMIX_TESTNET', + 'AVALANCHE_FUJI,GNOSIS_CHIADO', + + 'BSC_TESTNET,BASE_SEPOLIA', + 'BSC_TESTNET,POLYGON_AMOY', + 'BSC_TESTNET,WEMIX_TESTNET', + 'BSC_TESTNET,GNOSIS_CHIADO', + + 'ARBITRUM_SEPOLIA,BASE_SEPOLIA', + 'ARBITRUM_SEPOLIA,OPTIMISM_SEPOLIA', + 'ARBITRUM_SEPOLIA,WEMIX_TESTNET', + 'ARBITRUM_SEPOLIA,GNOSIS_CHIADO', + + 'BASE_SEPOLIA,MODE_SEPOLIA', + 'BASE_SEPOLIA,OPTIMISM_SEPOLIA', + 'BASE_SEPOLIA,GNOSIS_CHIADO', + + 'KROMA_SEPOLIA,WEMIX_TESTNET', + + 'OPTIMISM_SEPOLIA,POLYGON_AMOY', + 'OPTIMISM_SEPOLIA,WEMIX_TESTNET', + 'OPTIMISM_SEPOLIA,GNOSIS_CHIADO', + + 'POLYGON_AMOY,WEMIX_TESTNET', + 'POLYGON_AMOY,GNOSIS_CHIADO', +] + +BiDirectionalLane = true +PhaseTimeout = '30m' +LocalCluster = false +ExistingDeployment = true +ReuseContracts = true + + +[CCIP.Groups.smoke.TokenConfig] +NoOfTokensPerChain = 1 +CCIPOwnerTokens = true + +[CCIP.Groups.smoke.MsgDetails] +MsgType = 'DataWithToken' +DestGasLimit = 0 +DataLength = 100 +NoOfTokens = 1 +AmountPerToken = 1 \ No newline at end of file diff --git a/integration-tests/ccip-tests/testconfig/tomls/prod-testnet/soak-release-testing_token_transfer_with_native_feetoken.toml b/integration-tests/ccip-tests/testconfig/tomls/prod-testnet/soak-release-testing_token_transfer_with_native_feetoken.toml new file mode 100644 index 0000000000..6a6aa205fc --- /dev/null +++ b/integration-tests/ccip-tests/testconfig/tomls/prod-testnet/soak-release-testing_token_transfer_with_native_feetoken.toml @@ -0,0 +1,1013 @@ +[CCIP] +[CCIP.ContractVersions] +PriceRegistry = '1.2.0' +OffRamp = '1.2.0' +OnRamp = '1.2.0' +TokenPool = '1.4.0' +CommitStore = '1.2.0' + + +[CCIP.Deployments] +Data = """ +{ + "lane_configs": { + "Arbitrum Sepolia": { + "is_native_fee_token": true, + "fee_token": "0xE591bf0A0CF924A0674d7792db046B23CEbF5f34", + "bridge_tokens": [ + "0xA8C0c11bf64AF62CDCA6f93D3769B88BdD7cb93D" + ], + "bridge_tokens_pools": [ + "0x99685281Ec520a003F1A726A5a8078c2124c1477" + ], + "arm": "0xbcBDf0aDEDC9a33ED5338Bdb4B6F7CE664DC2e8B", + "router": "0x2a9C5afB0d0e4BAb2BCdaE109EC4b0c4Be15a165", + "price_registry": "0x89D5b13908b9063abCC6791dc724bF7B7c93634C", + "wrapped_native": "0xE591bf0A0CF924A0674d7792db046B23CEbF5f34", + "src_contracts": { + "Avalanche Fuji": { + "on_ramp": "0x1Cb56374296ED19E86F68fA437ee679FD7798DaA", + "deployed_at": 0 + }, + "Base Sepolia": { + "on_ramp": "0x7854E73C73e7F9bb5b0D5B4861E997f4C6E8dcC6", + "deployed_at": 0 + }, + "Gnosis Chiado": { + "on_ramp": "0x973CbE752258D32AE82b60CD1CB656Eebb588dF0", + "deployed_at": 0 + }, + "Optimism Sepolia": { + "on_ramp": "0x701Fe16916dd21EFE2f535CA59611D818B017877", + "deployed_at": 0 + }, + "Sepolia Testnet": { + "on_ramp": "0x4205E1Ca0202A248A5D42F5975A8FE56F3E302e9", + "deployed_at": 0 + }, + "WeMix Testnet": { + "on_ramp": "0xBD4106fBE4699FE212A34Cc21b10BFf22b02d959", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Avalanche Fuji": { + "off_ramp": "0xcab0EF91Bee323d1A617c0a027eE753aFd6997E4", + "commit_store": "0x0d90b9b96cBFa0D01635ce12982ccE1b70827c7a", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Base Sepolia": { + "off_ramp": "0xc1982985720B959E66c19b64F783361Eb9B60F26", + "commit_store": "0x28F66bB336f6db713d6ad2a3bd1B7a531282A159", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Gnosis Chiado": { + "off_ramp": "0x935C26F9a9122E5F9a27f2d3803e74c75B94f5a3", + "commit_store": "0xEdb963Ec5c2E5AbdFdCF137eF44A445a7fa4787A", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Optimism Sepolia": { + "off_ramp": "0xfD404A89e1d195F0c65be1A9042C77745197659e", + "commit_store": "0x84B7B012c95f8A152B44Ab3e952f2dEE424fA8e1", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Sepolia Testnet": { + "off_ramp": "0x1c71f141b4630EBE52d6aF4894812960abE207eB", + "commit_store": "0xaB0c8Ba51E7Fa3E5693a4Fbb39473520FD85d173", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "WeMix Testnet": { + "off_ramp": "0x262e16C8D42aa07bE13e58F81e7D9F62F6DE2830", + "commit_store": "0xc132eFAf929299E5ee704Fa6D9796CFa23Bb8b2C", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "Avalanche Fuji": { + "is_native_fee_token": true, + "fee_token": "0xd00ae08403B9bbb9124bB305C09058E32C39A48c", + "bridge_tokens": [ + "0xD21341536c5cF5EB1bcb58f6723cE26e8D8E90e4" + ], + "bridge_tokens_pools": [ + "0xEC1062cbDf4fBf31B3A6Aac62B6F6F123bb70E12" + ], + "arm": "0x7e28DD790214139798446A121cFe950B51304684", + "router": "0xF694E193200268f9a4868e4Aa017A0118C9a8177", + "price_registry": "0x19e157E5fb1DAec1aE4BaB113fdf077F980704AA", + "wrapped_native": "0xd00ae08403B9bbb9124bB305C09058E32C39A48c", + "src_contracts": { + "Arbitrum Sepolia": { + "on_ramp": "0x8bB16BEDbFd62D1f905ACe8DBBF2954c8EEB4f66", + "deployed_at": 0 + }, + "BSC Testnet": { + "on_ramp": "0xF25ECF1Aad9B2E43EDc2960cF66f325783245535", + "deployed_at": 0 + }, + "Base Sepolia": { + "on_ramp": "0x1A674645f3EB4147543FCA7d40C5719cbd997362", + "deployed_at": 0 + }, + "Gnosis Chiado": { + "on_ramp": "0x1532e5b204ee2b2244170c78E743CB9c168F4DF9", + "deployed_at": 0 + }, + "Optimism Sepolia": { + "on_ramp": "0xC334DE5b020e056d0fE766dE46e8d9f306Ffa1E2", + "deployed_at": 0 + }, + "Polygon Amoy": { + "on_ramp": "0x610F76A35E17DA4542518D85FfEa12645eF111Fc", + "deployed_at": 0 + }, + "Sepolia Testnet": { + "on_ramp": "0x5724B4Cc39a9690135F7273b44Dfd3BA6c0c69aD", + "deployed_at": 0 + }, + "WeMix Testnet": { + "on_ramp": "0x677B5ab5C8522d929166c064d5700F147b15fa33", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Arbitrum Sepolia": { + "off_ramp": "0x90A74072e7B0c2d59e13aB4d8f93c8198c413194", + "commit_store": "0xf3458CFd2fdf4a6CF0Ce296d520DD21eB194828b", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "BSC Testnet": { + "off_ramp": "0x10b28009E5D776F1f5AAA73941CE8953B8f42d26", + "commit_store": "0xacDD582F271eCF22FAd6764cCDe1c4a534b732A8", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Base Sepolia": { + "off_ramp": "0xdBdE8510226d1E060A3bf982b67705C67f5697e2", + "commit_store": "0x8Ee73BC9492b4182D289E5C1e66e40CD876CC00F", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Gnosis Chiado": { + "off_ramp": "0x56dF55aF5F0A4689f3364230587a68eD6A314fAd", + "commit_store": "0xabA7ff98094c4cc7A075812EefF2CD21f6400235", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Optimism Sepolia": { + "off_ramp": "0x3d7CbC95DCC33257F14D6Eb780c88Bd56C6335BB", + "commit_store": "0x1fcDC02edDfb405f378ba53cF9E6104feBcB7542", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Polygon Amoy": { + "off_ramp": "0x3e33290B90fD0FF30a3FA138934DF028E4eCA348", + "commit_store": "0xCFe3556Aa42d40be09BD23aa80448a19443BE5B1", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Sepolia Testnet": { + "off_ramp": "0x9e5e4324F8608D54A50a317832d456a392E4F8C2", + "commit_store": "0x92A51eD3F041B39EbD1e464C1f7cb1e8f8A8c63f", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "WeMix Testnet": { + "off_ramp": "0xD0D338318bC6837b091FC7AB5F2a94B7783507d5", + "commit_store": "0xd9D479208235c7355848ff4aF26eB5aacfDC30c6", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "BSC Testnet": { + "is_native_fee_token": true, + "fee_token": "0xae13d989daC2f0dEbFf460aC112a837C89BAa7cd", + "bridge_tokens": [ + "0xbFA2ACd33ED6EEc0ed3Cc06bF1ac38d22b36B9e9" + ], + "bridge_tokens_pools": [ + "0x31eDe84776DA37e2404eE88d71c234e92cB672e5" + ], + "arm": "0x7D899D26F2E94fFcd4b440C3008B0C6BEfcD3cca", + "router": "0xE1053aE1857476f36A3C62580FF9b016E8EE8F6f", + "price_registry": "0xCCDf022c9d31DC26Ebab4FB92432724a5b79809a", + "wrapped_native": "0xae13d989daC2f0dEbFf460aC112a837C89BAa7cd", + "src_contracts": { + "Avalanche Fuji": { + "on_ramp": "0xa2515683E99F50ADbE177519A46bb20FfdBaA5de", + "deployed_at": 0 + }, + "Base Sepolia": { + "on_ramp": "0x3E807220Ca84b997c0d1928162227b46C618e0c5", + "deployed_at": 0 + }, + "Gnosis Chiado": { + "on_ramp": "0x8735f991d41eA9cA9D2CC75cD201e4B7C866E63e", + "deployed_at": 0 + }, + "Polygon Amoy": { + "on_ramp": "0xf37CcbfC04adc1B56a46B36F811D52C744a1AF78", + "deployed_at": 0 + }, + "Sepolia Testnet": { + "on_ramp": "0xB1DE44B04C00eaFe9915a3C07a0CaeA4410537dF", + "deployed_at": 0 + }, + "WeMix Testnet": { + "on_ramp": "0x89268Afc1BEA0782a27ba84124E3F42b196af927", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Avalanche Fuji": { + "off_ramp": "0x6e6fFCb6B4BED91ff0CC8C2e57EC029dA7DB80C2", + "commit_store": "0x38Bc38Bd824b6eE87571f9D3CFbe6D6E28E3Dc62", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Base Sepolia": { + "off_ramp": "0x2C61FD7E93Dc79422861282145c59B56dFbc3a8c", + "commit_store": "0x42fAe5B3605804CF6d08632d7A25864e24F792Ae", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Gnosis Chiado": { + "off_ramp": "0x71a44a60832B0F8B63232C9516e7E6aEc3A373Dc", + "commit_store": "0xAC24299a91b72d1Cb5B31147e3CF54964D896974", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Polygon Amoy": { + "off_ramp": "0x63440C7747d37bc6154b5538AE32b54FE0965AfA", + "commit_store": "0xAD22fA198CECfC534927aE1D480c460d5bB3460F", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Sepolia Testnet": { + "off_ramp": "0xf1c128Fe52Ea78CcAAB407509292E61ce38C1523", + "commit_store": "0x59dFD870dC4bd76A7B879A4f705Fdcd2595f85f9", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "WeMix Testnet": { + "off_ramp": "0xfd9B19c3725da5B517aA705B848ff3f21F98280e", + "commit_store": "0x3c1F1412563188aBc8FE3fd53E8F1Cb601CaB4f9", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "Base Sepolia": { + "is_native_fee_token": true, + "fee_token": "0x4200000000000000000000000000000000000006", + "bridge_tokens": [ + "0x88A2d74F47a237a62e7A51cdDa67270CE381555e" + ], + "bridge_tokens_pools": [ + "0x875207858c691F192C606068f417dCf666b2EC6B" + ], + "arm": "0x7827dD0481EE18DB646bD250d20A8eA43da52146", + "router": "0xD3b06cEbF099CE7DA4AcCf578aaebFDBd6e88a93", + "price_registry": "0x4D20536e60832bE579Cd38E89Dc03d11E1741FbA", + "wrapped_native": "0x4200000000000000000000000000000000000006", + "src_contracts": { + "Arbitrum Sepolia": { + "on_ramp": "0x58622a80c6DdDc072F2b527a99BE1D0934eb2b50", + "deployed_at": 0 + }, + "Avalanche Fuji": { + "on_ramp": "0xAbA09a1b7b9f13E05A6241292a66793Ec7d43357", + "deployed_at": 0 + }, + "BSC Testnet": { + "on_ramp": "0xD806966beAB5A3C75E5B90CDA4a6922C6A9F0c9d", + "deployed_at": 0 + }, + "Gnosis Chiado": { + "on_ramp": "0x2Eff2d1BF5C557d6289D208a7a43608f5E3FeCc2", + "deployed_at": 0 + }, + "Mode Sepolia": { + "on_ramp": "0x3d0115386C01436870a2c47e6297962284E70BA6", + "deployed_at": 0 + }, + "Optimism Sepolia": { + "on_ramp": "0x3b39Cd9599137f892Ad57A4f54158198D445D147", + "deployed_at": 0 + }, + "Sepolia Testnet": { + "on_ramp": "0x6486906bB2d85A6c0cCEf2A2831C11A2059ebfea", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Arbitrum Sepolia": { + "off_ramp": "0xd364C06ac99a82a00d3eFF9F2F78E4Abe4b9baAA", + "commit_store": "0xdE8d0f47a71eA3fDFBD3162271652f2847939097", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Avalanche Fuji": { + "off_ramp": "0xAd91214efFee446500940c764DF77AF18427294F", + "commit_store": "0x1242b6c5e0e349b8d4BCf0938f961C4B4f7EA3Fa", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "BSC Testnet": { + "off_ramp": "0xd5E9508921434e8758f4540D55c1c066b7cc1598", + "commit_store": "0x1a86b29364D1B3fA3386329A361aA98A104b2742", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Gnosis Chiado": { + "off_ramp": "0x9Bb7e398ef9Acfe9cA584C39B1E233Cba62BB9f7", + "commit_store": "0x1F4B82cDebaC5e3a0Dd53183D47e51808B4a64cB", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Mode Sepolia": { + "off_ramp": "0xB26647A23e8b4284375e5C74b77c9557aE709D03", + "commit_store": "0x4b4fEB401d3E613e1D6242E155C83A80BF9ac2C9", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Optimism Sepolia": { + "off_ramp": "0x86a3910908eCaAA31Fcd9F0fC8841D8E98f1511d", + "commit_store": "0xE99a87C9b5ed4D2b6060195DEea5106ffF655736", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Sepolia Testnet": { + "off_ramp": "0x189F61D9B886Dd2975D5Abc893c8Cf5f5effda71", + "commit_store": "0xEE7e27346DCD1e711348D0F7f7ECB53a9a3a08a7", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "Blast Sepolia": { + "is_native_fee_token": true, + "fee_token": "0x4200000000000000000000000000000000000023", + "bridge_tokens": [ + "0x8D122C3e8ce9C8B62b87d3551bDfD8C259Bb0771" + ], + "bridge_tokens_pools": [ + "0xFb04129aD1EEDB741CC705ebC1978a7aB63e51f6" + ], + "arm": "0x09c1Ed4b112Fb33e594F2aACfEF407e2F14d7F9b", + "router": "0xfb2f2A207dC428da81fbAFfDDe121761f8Be1194", + "price_registry": "0xc8acE9dF450FaD007755C6C9AB4f0e9c8626E29C", + "wrapped_native": "0x4200000000000000000000000000000000000023", + "src_contracts": { + "Sepolia Testnet": { + "on_ramp": "0x85Ef19FC4C63c70744995DC38CAAEC185E0c619f", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Sepolia Testnet": { + "off_ramp": "0x92cD24C278D34C726f377703E50875d8f9535dC2", + "commit_store": "0xcE1b4D50CeD56850182Bd58Ace91171cB249B873", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "Celo Alfajores": { + "is_native_fee_token": true, + "fee_token": "0x99604d0e2EfE7ABFb58BdE565b5330Bb46Ab3Dca", + "bridge_tokens": [ + "0x7e503dd1dAF90117A1b79953321043d9E6815C72" + ], + "bridge_tokens_pools": [ + "0xC6683ac4a0F62803Bec89a5355B36495ddF2C38b" + ], + "arm": "0xEbe35aA4F5e707485484c992AF2069a457b9bBB1", + "router": "0xb00E95b773528E2Ea724DB06B75113F239D15Dca", + "price_registry": "0x8F048206D11B2c69b8963E2EBd5968D141e022f4", + "wrapped_native": "0x99604d0e2EfE7ABFb58BdE565b5330Bb46Ab3Dca", + "src_contracts": { + "Sepolia Testnet": { + "on_ramp": "0x16a020c4bbdE363FaB8481262D30516AdbcfcFc8", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Sepolia Testnet": { + "off_ramp": "0xa1b97F92D806BA040daf419AFC2765DC723683a4", + "commit_store": "0xcd92C0599Ac515e7588865cC45Eee21A74816aFc", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "Gnosis Chiado": { + "is_native_fee_token": true, + "fee_token": "0x18c8a7ec7897177E4529065a7E7B0878358B3BfF", + "bridge_tokens": [ + "0xA189971a2c5AcA0DFC5Ee7a2C44a2Ae27b3CF389" + ], + "bridge_tokens_pools": [ + "0xF9a21B587111e7E8745Fb8b13750014f19DB0014" + ], + "arm": "0xfE4fB161D870D0F672Ed9C5A898569603f77983F", + "router": "0x19b1bac554111517831ACadc0FD119D23Bb14391", + "price_registry": "0x2F4ACd1f8986c6B1788159C4c9a5fC3fceCCE363", + "wrapped_native": "0x18c8a7ec7897177E4529065a7E7B0878358B3BfF", + "src_contracts": { + "Arbitrum Sepolia": { + "on_ramp": "0x473b49fb592B54a4BfCD55d40E048431982879C9", + "deployed_at": 0 + }, + "Avalanche Fuji": { + "on_ramp": "0x610F76A35E17DA4542518D85FfEa12645eF111Fc", + "deployed_at": 0 + }, + "BSC Testnet": { + "on_ramp": "0xE48E6AA1fc7D0411acEA95F8C6CaD972A37721D4", + "deployed_at": 0 + }, + "Base Sepolia": { + "on_ramp": "0x41b4A51cAfb699D9504E89d19D71F92E886028a8", + "deployed_at": 0 + }, + "Optimism Sepolia": { + "on_ramp": "0xAae733212981e06D9C978Eb5148F8af03F54b6EF", + "deployed_at": 0 + }, + "Polygon Amoy": { + "on_ramp": "0x01800fCDd892e37f7829937271840A6F041bE62E", + "deployed_at": 0 + }, + "Sepolia Testnet": { + "on_ramp": "0x4ac7FBEc2A7298AbDf0E0F4fDC45015836C4bAFe", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Arbitrum Sepolia": { + "off_ramp": "0x9aA82DBB53bf02096B771D40e9432A323a78fB26", + "commit_store": "0x5CdbA91aBC0cD81FC56bc10Ad1835C9E5fB38e5F", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Avalanche Fuji": { + "off_ramp": "0x3e33290B90fD0FF30a3FA138934DF028E4eCA348", + "commit_store": "0xCFe3556Aa42d40be09BD23aa80448a19443BE5B1", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "BSC Testnet": { + "off_ramp": "0xbc4AD54e91b213D4279af92c0C5518c0b96cf62D", + "commit_store": "0xff84e8Dd4Fd17eaBb23b6AeA6e1981830e54389C", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Base Sepolia": { + "off_ramp": "0x4117953A5ceeF12f5B8C1E973b470ab83a8CebA6", + "commit_store": "0x94ad41296186E81f31e1ed0B1BcF5fa9e1721C27", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Optimism Sepolia": { + "off_ramp": "0x33d2898F8fb7714FD1661791766f40754982a343", + "commit_store": "0x55d6Df194472f02CD481e506A277c4A29D0D1bCc", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Polygon Amoy": { + "off_ramp": "0x450543b1d85ca79885851D7b74dc982981b78229", + "commit_store": "0x23B79d940A769FE31b4C867A8BAE80117f24Ca81", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Sepolia Testnet": { + "off_ramp": "0xbf9036529123DE264bFA0FC7362fE25B650D4B16", + "commit_store": "0x5f7F1abD5c5EdaF2636D58B980e85355AF0Ef80d", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "Kroma Sepolia": { + "is_native_fee_token": true, + "fee_token": "0x4200000000000000000000000000000000000001", + "bridge_tokens": [ + "0x6AC3e353D1DDda24d5A5416024d6E436b8817A4e" + ], + "bridge_tokens_pools": [ + "0x0eE8add19554C7bb1920A183Ed47b4FAB9Eb7601" + ], + "arm": "0x08f9Af992368FAc58C936A2c5eBc9092894CEa9b", + "router": "0xA8C0c11bf64AF62CDCA6f93D3769B88BdD7cb93D", + "price_registry": "0xa1ed3A3aA29166C9c8448654A8cA6b7916BC8379", + "wrapped_native": "0x4200000000000000000000000000000000000001", + "src_contracts": { + "WeMix Testnet": { + "on_ramp": "0x6ea155Fc77566D9dcE01B8aa5D7968665dc4f0C5", + "deployed_at": 0 + } + }, + "dest_contracts": { + "WeMix Testnet": { + "off_ramp": "0xB602B6E5Caf08ac0C920EAE585aed100a8cF6f3B", + "commit_store": "0x89D5b13908b9063abCC6791dc724bF7B7c93634C", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "Metis Sepolia": { + "is_native_fee_token": true, + "fee_token": "0x5c48e07062aC4E2Cf4b9A768a711Aef18e8fbdA0", + "bridge_tokens": [ + "0x20Aa09AAb761e2E600d65c6929A9fd1E59821D3f" + ], + "bridge_tokens_pools": [ + "0xdE8451E952Eb43350614839cCAA84f7C8701a09C" + ], + "arm": "0xf0607A9BDdB5F54dB59ACaA0837aFec2D1c95df6", + "router": "0xaCdaBa07ECad81dc634458b98673931DD9d3Bc14", + "price_registry": "0x5DCE866b3ae6E0Ed153f0e149D7203A1B266cdF5", + "wrapped_native": "0x5c48e07062aC4E2Cf4b9A768a711Aef18e8fbdA0", + "src_contracts": { + "Sepolia Testnet": { + "on_ramp": "0x2Eff2d1BF5C557d6289D208a7a43608f5E3FeCc2", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Sepolia Testnet": { + "off_ramp": "0x9Bb7e398ef9Acfe9cA584C39B1E233Cba62BB9f7", + "commit_store": "0x1F4B82cDebaC5e3a0Dd53183D47e51808B4a64cB", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "Mode Sepolia": { + "is_native_fee_token": true, + "fee_token": "0x4200000000000000000000000000000000000006", + "bridge_tokens": [ + "0xB9d4e1141E67ECFedC8A8139b5229b7FF2BF16F5" + ], + "bridge_tokens_pools": [ + "0x20bBc874bE3Cd94C3E4689EDD5D89dD1cE8Cb7C4" + ], + "arm": "0x9eC8a0AbC75ce08978FAf67958482461bCd93B18", + "router": "0xc49ec0eB4beb48B8Da4cceC51AA9A5bD0D0A4c43", + "price_registry": "0xa733ce82a84335b2E9D864312225B0F3D5d80600", + "wrapped_native": "0x4200000000000000000000000000000000000006", + "src_contracts": { + "Base Sepolia": { + "on_ramp": "0x73f7E074bd7291706a0C5412f51DB46441B1aDCB", + "deployed_at": 0 + }, + "Sepolia Testnet": { + "on_ramp": "0xfFdE9E8c34A27BEBeaCcAcB7b3044A0A364455C9", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Base Sepolia": { + "off_ramp": "0x137a38c6b1Ad20101F93516aB2159Df525309168", + "commit_store": "0x8F43d867969F14619895d71E0A5b89E0bb20bF70", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Sepolia Testnet": { + "off_ramp": "0xcD44cec849B6a8eBd5551D6DFeEcA452257Dfe4d", + "commit_store": "0xbA66f08733E6715D33edDfb5a5947676bb45d0e0", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "Optimism Sepolia": { + "is_native_fee_token": true, + "fee_token": "0x4200000000000000000000000000000000000006", + "bridge_tokens": [ + "0x8aF4204e30565DF93352fE8E1De78925F6664dA7" + ], + "bridge_tokens_pools": [ + "0x3Cc9364260D80F09ccAC1eE6B07366dB598900E6" + ], + "arm": "0xF51366F72184E22cF4a7a8362508DB0d3370392d", + "router": "0x114A20A10b43D4115e5aeef7345a1A71d2a60C57", + "price_registry": "0x782a7Ba95215f2F7c3dD4C153cbB2Ae3Ec2d3215", + "wrapped_native": "0x4200000000000000000000000000000000000006", + "src_contracts": { + "Arbitrum Sepolia": { + "on_ramp": "0x1a86b29364D1B3fA3386329A361aA98A104b2742", + "deployed_at": 0 + }, + "Avalanche Fuji": { + "on_ramp": "0x6b38CC6Fa938D5AB09Bdf0CFe580E226fDD793cE", + "deployed_at": 0 + }, + "Base Sepolia": { + "on_ramp": "0xe284D2315a28c4d62C419e8474dC457b219DB969", + "deployed_at": 0 + }, + "Gnosis Chiado": { + "on_ramp": "0x835a5b8e6CA17c2bB5A336c93a4E22478E6F1C8A", + "deployed_at": 0 + }, + "Polygon Amoy": { + "on_ramp": "0x2Cf26fb01E9ccDb831414B766287c0A9e4551089", + "deployed_at": 0 + }, + "Sepolia Testnet": { + "on_ramp": "0xC8b93b46BF682c39B3F65Aa1c135bC8A95A5E43a", + "deployed_at": 0 + }, + "WeMix Testnet": { + "on_ramp": "0xc7E53f6aB982af7A7C3e470c8cCa283d3399BDAd", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Arbitrum Sepolia": { + "off_ramp": "0xDc2c7A3d8068C6F09F0F3648d24C84e372F6014d", + "commit_store": "0xb1aFb5cbE3c29b5Db71F21442BA9EfD450BC23C3", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Avalanche Fuji": { + "off_ramp": "0x1F350718e015EB20E5065C09F4A7a3f66888aEeD", + "commit_store": "0x98650A8EB59f75D93563aB34FcF603b1A30e4CBF", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Base Sepolia": { + "off_ramp": "0x0a750ca77369e03613d7640548F4b2b1c695c3Bb", + "commit_store": "0x8fEBC74C26129C8d7E60288C6dCCc75eb494aA3C", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Gnosis Chiado": { + "off_ramp": "0xCE2CE7F940B7c839384e5D7e079A6aE80e8AD6dB", + "commit_store": "0x1b9D78Ec1CEEC439F0b7eA6C428A1a607D9FA7e4", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Polygon Amoy": { + "off_ramp": "0xD667b5706592D0b040C78fEe5EE17D243b7dCB41", + "commit_store": "0x96101BA5250EE9295c193693C1e08A55bC593664", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Sepolia Testnet": { + "off_ramp": "0x260AF9b83e0d2Bb6C9015fC9f0BfF8858A0CCE68", + "commit_store": "0x7a0bB92Bc8663abe6296d0162A9b41a2Cb2E0358", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "WeMix Testnet": { + "off_ramp": "0x9C08B7712af0344188aa5087D9e6aD0f47191037", + "commit_store": "0x4BE6DB0B884169a6A207fe5cad01eB4C025a13dB", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "Polygon Amoy": { + "is_native_fee_token": true, + "fee_token": "0x360ad4f9a9A8EFe9A8DCB5f461c4Cc1047E1Dcf9", + "bridge_tokens": [ + "0xcab0EF91Bee323d1A617c0a027eE753aFd6997E4" + ], + "bridge_tokens_pools": [ + "0x3064fB3EA546EE09A63AB3bD93E83D8B8525C636" + ], + "arm": "0x8b88C39D2875157aB4CE4AD3814409523d539ee1", + "router": "0x9C32fCB86BF0f4a1A8921a9Fe46de3198bb884B2", + "price_registry": "0xfb2f2A207dC428da81fbAFfDDe121761f8Be1194", + "wrapped_native": "0x360ad4f9a9A8EFe9A8DCB5f461c4Cc1047E1Dcf9", + "src_contracts": { + "Avalanche Fuji": { + "on_ramp": "0x8Fb98b3837578aceEA32b454f3221FE18D7Ce903", + "deployed_at": 0 + }, + "BSC Testnet": { + "on_ramp": "0xC6683ac4a0F62803Bec89a5355B36495ddF2C38b", + "deployed_at": 0 + }, + "Gnosis Chiado": { + "on_ramp": "0x2331F6D614C9Fd613Ff59a1aB727f1EDf6c37A68", + "deployed_at": 0 + }, + "Optimism Sepolia": { + "on_ramp": "0xA52cDAeb43803A80B3c0C2296f5cFe57e695BE11", + "deployed_at": 0 + }, + "Sepolia Testnet": { + "on_ramp": "0x35347A2fC1f2a4c5Eae03339040d0b83b09e6FDA", + "deployed_at": 0 + }, + "WeMix Testnet": { + "on_ramp": "0x26546096F64B5eF9A1DcDAe70Df6F4f8c2E10C61", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Avalanche Fuji": { + "off_ramp": "0xa733ce82a84335b2E9D864312225B0F3D5d80600", + "commit_store": "0x09B0F93fC2111aE439e853884173AC5b2F809885", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "BSC Testnet": { + "off_ramp": "0x948dfaa4842fc23e0e362Fe8D4396AaE4E6DF7EA", + "commit_store": "0x7F4e739D40E58BBd59dAD388171d18e37B26326f", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Gnosis Chiado": { + "off_ramp": "0x17c542a28e08AEF5697251601C7b2B621d153D42", + "commit_store": "0x811250c20fAB9a1b7ca245453aC214ba637fBEB5", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Optimism Sepolia": { + "off_ramp": "0xfFdE9E8c34A27BEBeaCcAcB7b3044A0A364455C9", + "commit_store": "0x74ED442ad211050e9C05Dc9A267E037E3d74A03B", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Sepolia Testnet": { + "off_ramp": "0xFb04129aD1EEDB741CC705ebC1978a7aB63e51f6", + "commit_store": "0x63f875240149d29136053C954Ca164a9BfA81F77", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "WeMix Testnet": { + "off_ramp": "0xdE8451E952Eb43350614839cCAA84f7C8701a09C", + "commit_store": "0xaCdaBa07ECad81dc634458b98673931DD9d3Bc14", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "Sepolia Testnet": { + "is_native_fee_token": true, + "fee_token": "0x097D90c9d3E0B50Ca60e1ae45F6A81010f9FB534", + "bridge_tokens": [ + "0xFd57b4ddBf88a4e07fF4e34C487b99af2Fe82a05" + ], + "bridge_tokens_pools": [ + "0x38d1ef9619Cd40cf5482C045660Ae7C82Ada062c" + ], + "arm": "0x27Da8735d8d1402cEc072C234759fbbB4dABBC4A", + "router": "0x0BF3dE8c5D3e8A2B34D2BEeB17ABfCeBaf363A59", + "price_registry": "0x9EF7D57a4ea30b9e37794E55b0C75F2A70275dCc", + "wrapped_native": "0x097D90c9d3E0B50Ca60e1ae45F6A81010f9FB534", + "src_contracts": { + "Arbitrum Sepolia": { + "on_ramp": "0xe4Dd3B16E09c016402585a8aDFdB4A18f772a07e", + "deployed_at": 0 + }, + "Avalanche Fuji": { + "on_ramp": "0x0477cA0a35eE05D3f9f424d88bC0977ceCf339D4", + "deployed_at": 0 + }, + "BSC Testnet": { + "on_ramp": "0xD990f8aFA5BCB02f95eEd88ecB7C68f5998bD618", + "deployed_at": 0 + }, + "Base Sepolia": { + "on_ramp": "0x2B70a05320cB069e0fB55084D402343F832556E7", + "deployed_at": 0 + }, + "Blast Sepolia": { + "on_ramp": "0xDB75E9D9ca7577CcBd7232741be954cf26194a66", + "deployed_at": 0 + }, + "Celo Alfajores": { + "on_ramp": "0x3C86d16F52C10B2ff6696a0e1b8E0BcfCC085948", + "deployed_at": 0 + }, + "Gnosis Chiado": { + "on_ramp": "0x3E842E3A79A00AFdd03B52390B1caC6306Ea257E", + "deployed_at": 0 + }, + "Metis Sepolia": { + "on_ramp": "0x1C4640914cd57c5f02a68048A0fbb0E12d904223", + "deployed_at": 0 + }, + "Mode Sepolia": { + "on_ramp": "0xc630fbD4D0F6AEB00aD0793FB827b54fBB78e981", + "deployed_at": 0 + }, + "Optimism Sepolia": { + "on_ramp": "0x69CaB5A0a08a12BaFD8f5B195989D709E396Ed4d", + "deployed_at": 0 + }, + "Polygon Amoy": { + "on_ramp": "0x9f656e0361Fb5Df2ac446102c8aB31855B591692", + "deployed_at": 0 + }, + "WeMix Testnet": { + "on_ramp": "0xedFc22336Eb0B9B11Ff37C07777db27BCcDe3C65", + "deployed_at": 0 + }, + "ZKSync Sepolia": { + "on_ramp": "0x1Acb3A885feA37bdA30AB99b99327b14391f500F", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Arbitrum Sepolia": { + "off_ramp": "0xF18896AB20a09A29e64fdEbA99FDb8EC328f43b1", + "commit_store": "0x93Ff9Dd39Dc01eac1fc4d2c9211D95Ee458CAB94", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Avalanche Fuji": { + "off_ramp": "0x000b26f604eAadC3D874a4404bde6D64a97d95ca", + "commit_store": "0x2dD9273F8208B8393350508131270A6574A69784", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "BSC Testnet": { + "off_ramp": "0xdE2d8E126e08d675fCD7fFa5a6CE49925f3Dc692", + "commit_store": "0x0050ac355a82caB31194507f94174297bf0655A7", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Base Sepolia": { + "off_ramp": "0x31c0B81832B333419f0DfD36A69F502cF9094aed", + "commit_store": "0xDFcde9d698a2B32DB2537DC9B752Cadd1D846a52", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Blast Sepolia": { + "off_ramp": "0x4e897e5cF3aC307F0541B2151A88bCD781c153a3", + "commit_store": "0xB656652841F347178e193951C4663652aCe36B74", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Celo Alfajores": { + "off_ramp": "0xB435E0f73c18C5a12C324CA1d02F81F2C3e6e761", + "commit_store": "0xbc5d74957F171e75F92c8F0E1C317A25a56a416D", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Gnosis Chiado": { + "off_ramp": "0x7db0115A0b3AAb01d30bf81123c5DD7B0C41Add5", + "commit_store": "0x6640723Ea801178c4383FA016b9781e7ef1016EF", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Metis Sepolia": { + "off_ramp": "0x4DB693A93E9d5196ECD42EC56CDEAe99dFC652ED", + "commit_store": "0xBfACd78F1412B6f93Ac23409bf456aFec1ABd845", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Mode Sepolia": { + "off_ramp": "0xbEfd8D65F6643De54F0b1268A3bf4618ff85dcB4", + "commit_store": "0x0C161D3470b45Cc677661654C30ce4AdE6aCD288", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Optimism Sepolia": { + "off_ramp": "0xD50590D4438411EDe47029b0FD7901A7145E5Df6", + "commit_store": "0xe85EEE9Fd434A7b8a586Ee086E828abF41839479", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Polygon Amoy": { + "off_ramp": "0x5032cbC0C4aEeD25bb6E45D8B3fAF05DB0688C5d", + "commit_store": "0xe6201C9996Cc7B6E828E10CbE937E693d577D318", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "WeMix Testnet": { + "off_ramp": "0x46b639a3C1a4CBfD326b94a2dB7415c27157282f", + "commit_store": "0x7b74554678816b045c1e7409327E086bD436aa46", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "ZKSync Sepolia": { + "off_ramp": "0xBaABd4166C892a1081a26535875A8fA3f22937b2", + "commit_store": "0xfda2e83F4D3f42B7629134ecD6E4b29FB8A7A07B", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "WeMix Testnet": { + "is_native_fee_token": true, + "fee_token": "0xbE3686643c05f00eC46e73da594c78098F7a9Ae7", + "bridge_tokens": [ + "0xF4E4057FbBc86915F4b2d63EEFFe641C03294ffc" + ], + "bridge_tokens_pools": [ + "0x82A92B2863F93Be70D20660088Ec060720bA2fdb" + ], + "arm": "0x8f6cb63eD5e379722580DFF0A051C140C64F9619", + "router": "0xA8C0c11bf64AF62CDCA6f93D3769B88BdD7cb93D", + "price_registry": "0x89D17571DB7C9540eeB36760E3c749C8fb984569", + "wrapped_native": "0xbE3686643c05f00eC46e73da594c78098F7a9Ae7", + "src_contracts": { + "Arbitrum Sepolia": { + "on_ramp": "0xA9DE3F7A617D67bC50c56baaCb9E0373C15EbfC6", + "deployed_at": 0 + }, + "Avalanche Fuji": { + "on_ramp": "0xC4aC84da458ba8e40210D2dF94C76E9a41f70069", + "deployed_at": 0 + }, + "BSC Testnet": { + "on_ramp": "0x5AD6eed6Be0ffaDCA4105050CF0E584D87E0c2F1", + "deployed_at": 0 + }, + "Kroma Sepolia": { + "on_ramp": "0x428C4dc89b6Bf908B82d77C9CBceA786ea8cc7D0", + "deployed_at": 0 + }, + "Optimism Sepolia": { + "on_ramp": "0x1961a7De751451F410391c251D4D4F98D71B767D", + "deployed_at": 0 + }, + "Polygon Amoy": { + "on_ramp": "0xd55148e841e76265B484d399eC71b7076ecB1216", + "deployed_at": 0 + }, + "Sepolia Testnet": { + "on_ramp": "0x4d57C6d8037C65fa66D6231844785a428310a735", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Arbitrum Sepolia": { + "off_ramp": "0xeB1dFaB2464Bf0574D43e764E0c758f92e7ecAFb", + "commit_store": "0xcEaCa2B7890065c485f3E58657358a185Ad33791", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Avalanche Fuji": { + "off_ramp": "0x98e811Df9D2512f1aaf58D534607F583D6c54A4F", + "commit_store": "0x8e538351F6E5B2daF3c90C565C3738bca69a2716", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "BSC Testnet": { + "off_ramp": "0xB0e7f0fCcD3c961C473E7c44D939C1cDb4Cec1cB", + "commit_store": "0x4B56D8d53f1A6e0117B09700067De99581aA5542", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Kroma Sepolia": { + "off_ramp": "0xD685D2d224dd6D0Db2D56497db6270D77D9a7966", + "commit_store": "0x7e062D6880779a0347e7742058C1b1Ee4AA0B137", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Optimism Sepolia": { + "off_ramp": "0xA5f97Bc69Bf06e7C37B93265c5457420A92c5F4b", + "commit_store": "0xd48b9213583074f518D8f4336FDf35370D450132", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Polygon Amoy": { + "off_ramp": "0x6c8f5999B06FDE17B11E4e3C1062b761766F960f", + "commit_store": "0x957c3c2056192e58A8485eF31165fC490d474239", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + }, + "Sepolia Testnet": { + "off_ramp": "0x8AB103843ED9D28D2C5DAf5FdB9c3e1CE2B6c876", + "commit_store": "0x7d5297c5506ee2A7Ef121Da9bE02b6a6AD30b392", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + }, + "ZKSync Sepolia": { + "is_native_fee_token": true, + "fee_token": "0x4317b2eCD41851173175005783322D29E9bAee9E", + "arm": "0x926b4f90610Aa448f27c8e0Fd0afa4A17B7305F9", + "router": "0xA1fdA8aa9A8C4b945C45aD30647b01f07D7A0B16", + "price_registry": "0x648B6BB09bE1C5766C8AC578B9B4aC8497eA671F", + "wrapped_native": "0x4317b2eCD41851173175005783322D29E9bAee9E", + "src_contracts": { + "Sepolia Testnet": { + "on_ramp": "0x79a9a5e9e318e8e109776569574814bbf935125a", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Sepolia Testnet": { + "off_ramp": "0x18FF69051479796175852578725Fc74F58E963F8", + "commit_store": "0xF694b4FD7889480dca3CD41244e8e3395a9EFBa0", + "receiver_dapp": "0xea387241d834D04CC408f4C2FE7ef2c477E4B3E7" + } + } + } + } +} +""" + +[CCIP.Env] +TTL = '8h' + +[CCIP.Env.Network] +selected_networks = [ + 'ARBITRUM_SEPOLIA', + 'AVALANCHE_FUJI', + 'BASE_SEPOLIA', + 'BLAST_SEPOLIA', + 'BSC_TESTNET', + 'CELO_ALFAJORES', + 'GNOSIS_CHIADO', + 'KROMA_SEPOLIA', + 'MODE_SEPOLIA', + 'OPTIMISM_SEPOLIA', + 'POLYGON_AMOY', + 'SEPOLIA', + 'METIS_SEPOLIA', + 'WEMIX_TESTNET', + 'ZKSYNC_SEPOLIA' +] + +[CCIP.Groups.load] +NetworkPairs = [ + 'AVALANCHE_FUJI,ARBITRUM_SEPOLIA', + 'AVALANCHE_FUJI,BASE_SEPOLIA', + 'AVALANCHE_FUJI,OPTIMISM_SEPOLIA', + 'AVALANCHE_FUJI,POLYGON_AMOY', + 'AVALANCHE_FUJI,GNOSIS_CHIADO', + 'ARBITRUM_SEPOLIA,BASE_SEPOLIA', + 'ARBITRUM_SEPOLIA,OPTIMISM_SEPOLIA', + 'ARBITRUM_SEPOLIA,SEPOLIA', + 'ARBITRUM_SEPOLIA,GNOSIS_CHIADO', + 'BASE_SEPOLIA,MODE_SEPOLIA', + 'BASE_SEPOLIA,OPTIMISM_SEPOLIA', + 'BASE_SEPOLIA,GNOSIS_CHIADO', + 'SEPOLIA,MODE_SEPOLIA', + 'SEPOLIA,CELO_ALFAJORES', + 'SEPOLIA,METIS_SEPOLIA', + 'SEPOLIA,BLAST_SEPOLIA', + 'SEPOLIA,ZKSYNC_SEPOLIA', + 'KROMA_SEPOLIA,WEMIX_TESTNET', + 'OPTIMISM_SEPOLIA,GNOSIS_CHIADO', + 'BSC_TESTNET,GNOSIS_CHIADO', +] + +BiDirectionalLane = true +PhaseTimeout = '20m' +ExistingDeployment = true + +[CCIP.Groups.load.TokenConfig] +NoOfTokensPerChain = 1 + +[CCIP.Groups.load.LoadProfile] +RequestPerUnitTime = [1] +TimeUnit = '6m' +TestDuration = '24h' +TestRunName = 'SoakTest_prod_testnet' +FailOnFirstErrorInLoad = true + +[[CCIP.Groups.load.LoadProfile.MsgProfile.MsgDetails]] +MsgType = 'Data' +DestGasLimit = 0 +DataLength = 100 +NoOfTokens = 1 +AmountPerToken = 1 \ No newline at end of file From 7728bfa002b3061feff105a61fea1f6d01fc118e Mon Sep 17 00:00:00 2001 From: Adam Hamrick <adam.hamrick@smartcontract.com> Date: Tue, 17 Sep 2024 11:19:04 -0400 Subject: [PATCH 100/115] Enables Out of Order Execution for E2E Tests (#1393) ZK chains introduce the need to send CCIP messages out of order. This change enables us to do so at will in our E2E tests. --------- Co-authored-by: Balamurali Gopalswami <balamurali.gopalswami@smartcontract.com> --- .github/workflows/ccip-load-tests.yml | 1 - .github/workflows/integration-tests.yml | 6 +- .../ccip/testhelpers/ccip_contracts.go | 2 + .../ocr2/plugins/ccip/testhelpers/config.go | 1 + .../testhelpers_1_4_0/ccip_contracts_1_4_0.go | 2 + .../testhelpers_1_4_0/config_1_4_0.go | 1 + .../ccip-tests/actions/ccip_helpers.go | 89 ++++++++++++------- .../ccip-tests/contracts/contract_deployer.go | 7 +- .../ccip-tests/contracts/contract_models.go | 54 +++++++++-- .../contracts/laneconfig/parse_contracts.go | 1 + .../ccip-tests/load/ccip_loadgen.go | 25 +++++- integration-tests/ccip-tests/load/helper.go | 5 +- .../ccip-tests/smoke/ccip_test.go | 28 ++---- .../ccip-tests/testconfig/README.md | 4 + .../ccip-tests/testconfig/ccip.go | 1 + .../testconfig/tomls/ccip-default.toml | 9 +- 16 files changed, 160 insertions(+), 76 deletions(-) diff --git a/.github/workflows/ccip-load-tests.yml b/.github/workflows/ccip-load-tests.yml index 633effd86c..a9b1af2f30 100644 --- a/.github/workflows/ccip-load-tests.yml +++ b/.github/workflows/ccip-load-tests.yml @@ -14,7 +14,6 @@ on: description: 'Key to run tests with custom test secrets' required: false type: string - pull_request: # DEBUG: Checking run conditions # Only run 1 of this workflow at a time per PR concurrency: diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index 3a61256c8c..c359887e0f 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -373,21 +373,21 @@ jobs: file: ccip run: -run ^TestSmokeCCIPForBidirectionalLane$ config_path: ./integration-tests/ccip-tests/testconfig/tomls/leader-lane.toml - - name: ccip-smoke-reorg + - name: ccip-smoke-reorg-bidirectional nodes: 1 dir: ccip-tests/smoke os: ubuntu-latest file: ccip run: -run ^TestSmokeCCIPReorgBelowFinality$ -v config_path: ./integration-tests/ccip-tests/testconfig/tomls/ccip-reorg.toml - - name: ccip-smoke-reorg + - name: ccip-smoke-reorg-below-finality nodes: 1 dir: ccip-tests/smoke os: ubuntu-latest file: ccip run: -run ^TestSmokeCCIPReorgAboveFinalityAtDestination$ -v config_path: ./integration-tests/ccip-tests/testconfig/tomls/ccip-reorg.toml - - name: ccip-smoke-reorg + - name: ccip-smoke-reorg-above-finality nodes: 1 dir: ccip-tests/smoke os: ubuntu-latest diff --git a/core/services/ocr2/plugins/ccip/testhelpers/ccip_contracts.go b/core/services/ocr2/plugins/ccip/testhelpers/ccip_contracts.go index 7b3351ce06..0442f09c47 100644 --- a/core/services/ocr2/plugins/ccip/testhelpers/ccip_contracts.go +++ b/core/services/ocr2/plugins/ccip/testhelpers/ccip_contracts.go @@ -150,6 +150,7 @@ func NewExecOffchainConfig( RelativeBoostPerWaitHour float64, InflightCacheExpiry config.Duration, RootSnoozeTime config.Duration, + BatchingStrategyID uint32, // 0 = Standard, 1 = Out of Order ) ExecOffchainConfig { return ExecOffchainConfig{v1_2_0.JSONExecOffchainConfig{ DestOptimisticConfirmations: DestOptimisticConfirmations, @@ -157,6 +158,7 @@ func NewExecOffchainConfig( RelativeBoostPerWaitHour: RelativeBoostPerWaitHour, InflightCacheExpiry: InflightCacheExpiry, RootSnoozeTime: RootSnoozeTime, + BatchingStrategyID: BatchingStrategyID, }} } diff --git a/core/services/ocr2/plugins/ccip/testhelpers/config.go b/core/services/ocr2/plugins/ccip/testhelpers/config.go index c9d1ca5a12..4dcb627347 100644 --- a/core/services/ocr2/plugins/ccip/testhelpers/config.go +++ b/core/services/ocr2/plugins/ccip/testhelpers/config.go @@ -70,6 +70,7 @@ func (c *CCIPContracts) createExecOffchainConfig(t *testing.T, inflightCacheExpi 0.07, *config.MustNewDuration(inflightCacheExpiry), *config.MustNewDuration(rootSnoozeTime), + uint32(0), ).Encode() require.NoError(t, err) return config diff --git a/core/services/ocr2/plugins/ccip/testhelpers/testhelpers_1_4_0/ccip_contracts_1_4_0.go b/core/services/ocr2/plugins/ccip/testhelpers/testhelpers_1_4_0/ccip_contracts_1_4_0.go index b8db2dfff7..9906a7b365 100644 --- a/core/services/ocr2/plugins/ccip/testhelpers/testhelpers_1_4_0/ccip_contracts_1_4_0.go +++ b/core/services/ocr2/plugins/ccip/testhelpers/testhelpers_1_4_0/ccip_contracts_1_4_0.go @@ -157,6 +157,7 @@ func NewExecOffchainConfig( RelativeBoostPerWaitHour float64, InflightCacheExpiry config.Duration, RootSnoozeTime config.Duration, + BatchingStrategyID uint32, ) ExecOffchainConfig { return ExecOffchainConfig{v1_2_0.JSONExecOffchainConfig{ DestOptimisticConfirmations: DestOptimisticConfirmations, @@ -164,6 +165,7 @@ func NewExecOffchainConfig( RelativeBoostPerWaitHour: RelativeBoostPerWaitHour, InflightCacheExpiry: InflightCacheExpiry, RootSnoozeTime: RootSnoozeTime, + BatchingStrategyID: BatchingStrategyID, }} } diff --git a/core/services/ocr2/plugins/ccip/testhelpers/testhelpers_1_4_0/config_1_4_0.go b/core/services/ocr2/plugins/ccip/testhelpers/testhelpers_1_4_0/config_1_4_0.go index 666ad79e59..087c21e933 100644 --- a/core/services/ocr2/plugins/ccip/testhelpers/testhelpers_1_4_0/config_1_4_0.go +++ b/core/services/ocr2/plugins/ccip/testhelpers/testhelpers_1_4_0/config_1_4_0.go @@ -68,6 +68,7 @@ func (c *CCIPContracts) createExecOffchainConfig(t *testing.T, inflightCacheExpi 0.07, *config.MustNewDuration(inflightCacheExpiry), *config.MustNewDuration(rootSnoozeTime), + uint32(0), ).Encode() require.NoError(t, err) return config diff --git a/integration-tests/ccip-tests/actions/ccip_helpers.go b/integration-tests/ccip-tests/actions/ccip_helpers.go index 15a737c031..f0af063ac6 100644 --- a/integration-tests/ccip-tests/actions/ccip_helpers.go +++ b/integration-tests/ccip-tests/actions/ccip_helpers.go @@ -61,6 +61,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/rmn_contract" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/router" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/ccip/generated/token_pool" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/ccipexec" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/config" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/testhelpers" integrationtesthelpers "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/testhelpers/integration" @@ -185,6 +186,7 @@ type CCIPCommon struct { gasUpdateWatcherMu *sync.Mutex gasUpdateWatcher map[uint64]*big.Int // key - destchain id; value - timestamp of update GasUpdateEvents []contracts.GasUpdateEvent + AllowOutOfOrder bool } // FreeUpUnusedSpace sets nil to various elements of ccipModule which are only used @@ -273,6 +275,9 @@ func (ccipModule *CCIPCommon) CurseARM() (*types.Transaction, error) { func (ccipModule *CCIPCommon) LoadContractAddresses(conf *laneconfig.LaneConfig, noOfTokens *int) { if conf != nil { + if conf.AllowOutOfOrder { + ccipModule.AllowOutOfOrder = true + } if common.IsHexAddress(conf.FeeToken) { ccipModule.FeeToken = &contracts.LinkToken{ EthAddress: common.HexToAddress(conf.FeeToken), @@ -725,17 +730,16 @@ func (ccipModule *CCIPCommon) WriteLaneConfig(conf *laneconfig.LaneConfig) { for k, v := range ccipModule.PriceAggregators { priceAggrs[k.Hex()] = v.ContractAddress.Hex() } - conf.CommonContracts = laneconfig.CommonContracts{ - FeeToken: ccipModule.FeeToken.Address(), - BridgeTokens: btAddresses, - BridgeTokenPools: btpAddresses, - ARM: ccipModule.RMNContract.Hex(), - Router: ccipModule.Router.Address(), - PriceRegistry: ccipModule.PriceRegistry.Address(), - PriceAggregators: priceAggrs, - WrappedNative: ccipModule.WrappedNative.Hex(), - Multicall: ccipModule.MulticallContract.Hex(), - } + conf.CommonContracts.FeeToken = ccipModule.FeeToken.Address() + conf.CommonContracts.BridgeTokens = btAddresses + conf.CommonContracts.BridgeTokenPools = btpAddresses + conf.CommonContracts.ARM = ccipModule.RMNContract.Hex() + conf.CommonContracts.Router = ccipModule.Router.Address() + conf.CommonContracts.PriceRegistry = ccipModule.PriceRegistry.Address() + conf.CommonContracts.PriceAggregators = priceAggrs + conf.CommonContracts.WrappedNative = ccipModule.WrappedNative.Hex() + conf.CommonContracts.Multicall = ccipModule.MulticallContract.Hex() + if ccipModule.TokenAdminRegistry != nil { conf.CommonContracts.TokenAdminRegistry = ccipModule.TokenAdminRegistry.Address() } @@ -1626,7 +1630,7 @@ func (sourceCCIP *SourceCCIPModule) IsRequestTriggeredWithinTimeframe(timeframe if sendRequestedEvents, exists := value.([]*evm_2_evm_onramp.EVM2EVMOnRampCCIPSendRequested); exists { for _, sendRequestedEvent := range sendRequestedEvents { raw := sendRequestedEvent.Raw - hdr, err := sourceCCIP.Common.ChainClient.HeaderByNumber(context.Background(), big.NewInt(int64(raw.BlockNumber))) + hdr, err := sourceCCIP.Common.ChainClient.HeaderByNumber(context.Background(), new(big.Int).SetUint64(raw.BlockNumber)) if err == nil { if hdr.Timestamp.After(lastSeenTimestamp) { foundAt = pointer.ToTime(hdr.Timestamp) @@ -1709,6 +1713,7 @@ func (sourceCCIP *SourceCCIPModule) AssertEventCCIPSendRequested( // CCIPMsg constructs the message for a CCIP request func (sourceCCIP *SourceCCIPModule) CCIPMsg( receiver common.Address, + allowOutOfOrder bool, gasLimit *big.Int, ) (router.ClientEVM2AnyMessage, error) { length := sourceCCIP.MsgDataLength @@ -1750,7 +1755,15 @@ func (sourceCCIP *SourceCCIPModule) CCIPMsg( return router.ClientEVM2AnyMessage{}, fmt.Errorf("failed encoding the receiver address: %w", err) } - extraArgsV1, err := testhelpers.GetEVMExtraArgsV1(gasLimit, false) + var extraArgs []byte + matchErr := contracts.MatchContractVersionsOrAbove(map[contracts.Name]contracts.Version{ + contracts.OnRampContract: contracts.V1_5_0, + }) + if matchErr != nil { + extraArgs, err = testhelpers.GetEVMExtraArgsV1(gasLimit, false) + } else { + extraArgs, err = testhelpers.GetEVMExtraArgsV2(gasLimit, allowOutOfOrder) + } if err != nil { return router.ClientEVM2AnyMessage{}, fmt.Errorf("failed encoding the options field: %w", err) } @@ -1760,22 +1773,19 @@ func (sourceCCIP *SourceCCIPModule) CCIPMsg( Data: []byte(data), TokenAmounts: tokenAndAmounts, FeeToken: common.HexToAddress(sourceCCIP.Common.FeeToken.Address()), - ExtraArgs: extraArgsV1, + ExtraArgs: extraArgs, }, nil } // SendRequest sends a CCIP request to the source chain's router contract -func (sourceCCIP *SourceCCIPModule) SendRequest( - receiver common.Address, - gasLimit *big.Int, -) (common.Hash, time.Duration, *big.Int, error) { +func (sourceCCIP *SourceCCIPModule) SendRequest(receiver common.Address, gasLimit *big.Int) (common.Hash, time.Duration, *big.Int, error) { var d time.Duration destChainSelector, err := chainselectors.SelectorFromChainId(sourceCCIP.DestinationChainId) if err != nil { return common.Hash{}, d, nil, fmt.Errorf("failed getting the chain selector: %w", err) } // form the message for transfer - msg, err := sourceCCIP.CCIPMsg(receiver, gasLimit) + msg, err := sourceCCIP.CCIPMsg(receiver, sourceCCIP.Common.AllowOutOfOrder, gasLimit) if err != nil { return common.Hash{}, d, nil, fmt.Errorf("failed forming the ccip msg: %w", err) } @@ -2218,7 +2228,7 @@ func (destCCIP *DestCCIPModule) AssertNoReportAcceptedEventReceived(lggr *zerolo e, exists := value.(*evm_2_evm_offramp.EVM2EVMOffRampExecutionStateChanged) if exists { vLogs := e.Raw - hdr, err := destCCIP.Common.ChainClient.HeaderByNumber(ctx, big.NewInt(int64(vLogs.BlockNumber))) + hdr, err := destCCIP.Common.ChainClient.HeaderByNumber(ctx, new(big.Int).SetUint64(vLogs.BlockNumber)) if err != nil { return true } @@ -2259,7 +2269,7 @@ func (destCCIP *DestCCIPModule) AssertNoExecutionStateChangedEventReceived( e, exists := value.(*contracts.EVM2EVMOffRampExecutionStateChanged) if exists { vLogs := e.LogInfo - hdr, err := destCCIP.Common.ChainClient.HeaderByNumber(ctx, big.NewInt(int64(vLogs.BlockNumber))) + hdr, err := destCCIP.Common.ChainClient.HeaderByNumber(ctx, new(big.Int).SetUint64(vLogs.BlockNumber)) if err != nil { return true } @@ -2288,7 +2298,7 @@ func (destCCIP *DestCCIPModule) AssertEventExecutionStateChanged( reqStat *testreporters.RequestStat, execState testhelpers.MessageExecutionState, ) (uint8, error) { - lggr.Info().Int64("seqNum", int64(seqNum)).Str("Timeout", timeout.String()).Msg("Waiting for ExecutionStateChanged event") + lggr.Info().Uint64("seqNum", seqNum).Str("Timeout", timeout.String()).Msg("Waiting for ExecutionStateChanged event") timer := time.NewTimer(timeout) defer timer.Stop() ticker := time.NewTicker(time.Second) @@ -2306,7 +2316,7 @@ func (destCCIP *DestCCIPModule) AssertEventExecutionStateChanged( destCCIP.ExecStateChangedWatcher.Delete(seqNum) vLogs := e.LogInfo receivedAt := time.Now().UTC() - hdr, err := destCCIP.Common.ChainClient.HeaderByNumber(context.Background(), big.NewInt(int64(vLogs.BlockNumber))) + hdr, err := destCCIP.Common.ChainClient.HeaderByNumber(context.Background(), new(big.Int).SetUint64(vLogs.BlockNumber)) if err == nil { receivedAt = hdr.Timestamp } @@ -2319,7 +2329,7 @@ func (destCCIP *DestCCIPModule) AssertEventExecutionStateChanged( gasUsed = receipt.GasUsed } if testhelpers.MessageExecutionState(e.State) == execState { - lggr.Info().Int64("seqNum", int64(seqNum)).Uint8("ExecutionState", e.State).Msg("ExecutionStateChanged event received") + lggr.Info().Uint64("seqNum", seqNum).Uint8("ExecutionState", e.State).Msg("ExecutionStateChanged event received") reqStat.UpdateState(lggr, seqNum, testreporters.ExecStateChanged, receivedAt.Sub(timeNow), testreporters.Success, &testreporters.TransactionStats{ @@ -2363,7 +2373,7 @@ func (destCCIP *DestCCIPModule) AssertEventReportAccepted( prevEventAt time.Time, reqStat *testreporters.RequestStat, ) (*contracts.CommitStoreReportAccepted, time.Time, error) { - lggr.Info().Int64("seqNum", int64(seqNum)).Str("Timeout", timeout.String()).Msg("Waiting for ReportAccepted event") + lggr.Info().Uint64("seqNum", seqNum).Str("Timeout", timeout.String()).Msg("Waiting for ReportAccepted event") timer := time.NewTimer(timeout) defer timer.Stop() resetTimerCount := 0 @@ -2379,7 +2389,7 @@ func (destCCIP *DestCCIPModule) AssertEventReportAccepted( // if the value is processed, delete it from the map destCCIP.ReportAcceptedWatcher.Delete(seqNum) receivedAt := time.Now().UTC() - hdr, err := destCCIP.Common.ChainClient.HeaderByNumber(context.Background(), big.NewInt(int64(reportAccepted.LogInfo.BlockNumber))) + hdr, err := destCCIP.Common.ChainClient.HeaderByNumber(context.Background(), new(big.Int).SetUint64(reportAccepted.LogInfo.BlockNumber)) if err == nil { receivedAt = hdr.Timestamp } @@ -2488,7 +2498,7 @@ func (destCCIP *DestCCIPModule) AssertReportBlessed( // if the value is processed, delete it from the map destCCIP.ReportBlessedBySeqNum.Delete(seqNum) } - hdr, err := destCCIP.Common.ChainClient.HeaderByNumber(context.Background(), big.NewInt(int64(vLogs.BlockNumber))) + hdr, err := destCCIP.Common.ChainClient.HeaderByNumber(context.Background(), new(big.Int).SetUint64(vLogs.BlockNumber)) if err == nil { receivedAt = hdr.Timestamp } @@ -2536,7 +2546,7 @@ func (destCCIP *DestCCIPModule) AssertSeqNumberExecuted( timeNow time.Time, reqStat *testreporters.RequestStat, ) error { - lggr.Info().Int64("seqNum", int64(seqNumberBefore)).Str("Timeout", timeout.String()).Msg("Waiting to be processed by commit store") + lggr.Info().Uint64("seqNum", seqNumberBefore).Str("Timeout", timeout.String()).Msg("Waiting to be processed by commit store") timer := time.NewTimer(timeout) defer timer.Stop() resetTimerCount := 0 @@ -2793,7 +2803,8 @@ func (lane *CCIPLane) AddToSentReqs(txHash common.Hash, reqStats []*testreporter func (lane *CCIPLane) Multicall(noOfRequests int, multiSendAddr common.Address) error { var ccipMultipleMsg []contracts.CCIPMsgData feeToken := common.HexToAddress(lane.Source.Common.FeeToken.Address()) - genericMsg, err := lane.Source.CCIPMsg(lane.Dest.ReceiverDapp.EthAddress, big.NewInt(DefaultDestinationGasLimit)) + genericMsg, err := lane.Source.CCIPMsg(lane.Dest.ReceiverDapp.EthAddress, lane.Source.Common.AllowOutOfOrder, + big.NewInt(DefaultDestinationGasLimit)) if err != nil { return fmt.Errorf("failed to form the ccip message: %w", err) } @@ -2885,10 +2896,7 @@ func (lane *CCIPLane) Multicall(noOfRequests int, multiSendAddr common.Address) func (lane *CCIPLane) SendRequests(noOfRequests int, gasLimit *big.Int) error { for i := 1; i <= noOfRequests; i++ { stat := testreporters.NewCCIPRequestStats(int64(lane.NumberOfReq+i), lane.SourceNetworkName, lane.DestNetworkName) - txHash, txConfirmationDur, fee, err := lane.Source.SendRequest( - lane.Dest.ReceiverDapp.EthAddress, - gasLimit, - ) + txHash, txConfirmationDur, fee, err := lane.Source.SendRequest(lane.Dest.ReceiverDapp.EthAddress, gasLimit) if err != nil { stat.UpdateState(lane.Logger, 0, testreporters.TX, txConfirmationDur, testreporters.Failure, nil) return fmt.Errorf("could not send request: %w", err) @@ -3522,6 +3530,7 @@ func (lane *CCIPLane) DeployNewCCIPLane( srcConf = lane.SrcNetworkLaneCfg destConf = lane.DstNetworkLaneCfg commitAndExecOnSameDON = pointer.GetBool(testConf.CommitAndExecuteOnSameDON) + allowOutOfOrder = pointer.GetBool(testConf.AllowOutOfOrder) withPipeline = pointer.GetBool(testConf.TokenConfig.WithPipeline) configureCLNodes = !pointer.GetBool(testConf.ExistingDeployment) ) @@ -3536,6 +3545,13 @@ func (lane *CCIPLane) DeployNewCCIPLane( if err != nil { return fmt.Errorf("failed to create source module: %w", err) } + + // If AllowOutOfOrder is set globally in test config, then assumption is to set it for every lane. + //However, if this is set as false, and set as true for specific chain in lane_configs then apply it + //only for a lane where source network is of that chain. + if allowOutOfOrder { + lane.Source.Common.AllowOutOfOrder = true + } lane.Dest, err = DefaultDestinationCCIPModule( lane.Logger, testConf, destChainClient, sourceChainClient.GetChainID().Uint64(), @@ -3787,6 +3803,12 @@ func SetOCR2Config( if len(execNodes) > 0 { nodes = execNodes } + + // Use out of order batching strategy if we expect to be sending out of order messages + batchingStrategyID := ccipexec.BestEffortBatchingStrategyID + if pointer.GetBool(testConf.AllowOutOfOrder) { + batchingStrategyID = ccipexec.ZKOverflowBatchingStrategyID + } if destCCIP.OffRamp != nil { execOffchainCfg, err := contracts.NewExecOffchainConfig( 1, @@ -3794,6 +3816,7 @@ func SetOCR2Config( 0.7, *inflightExpiryExec, *commonconfig.MustNewDuration(RootSnoozeTime), + batchingStrategyID, ) if err != nil { return fmt.Errorf("failed to create exec offchain config: %w", err) diff --git a/integration-tests/ccip-tests/contracts/contract_deployer.go b/integration-tests/ccip-tests/contracts/contract_deployer.go index 211bbc1ebb..579d16da4f 100644 --- a/integration-tests/ccip-tests/contracts/contract_deployer.go +++ b/integration-tests/ccip-tests/contracts/contract_deployer.go @@ -77,7 +77,7 @@ func MatchContractVersionsOrAbove(requiredContractVersions map[Name]Version) err // if the version is less than 1.5.0, then token admin registry is not needed func NeedTokenAdminRegistry() bool { return MatchContractVersionsOrAbove(map[Name]Version{ - TokenPoolContract: V1_5_0_dev, + TokenPoolContract: V1_5_0, }) == nil } @@ -1044,6 +1044,7 @@ func (e *CCIPContractsDeployer) DeployOnRamp( MaxPerMsgGasLimit: 4_000_000, DefaultTokenFeeUSDCents: 50, DefaultTokenDestGasOverhead: 125_000, + EnforceOutOfOrder: false, }, evm_2_evm_onramp.RateLimiterConfig{ Capacity: opts.Capacity, @@ -1465,12 +1466,14 @@ func NewExecOnchainConfig( } } +// NewExecOffchainConfig creates a config for the OffChain portion of how CCIP operates func NewExecOffchainConfig( destOptimisticConfirmations uint32, batchGasLimit uint32, relativeBoostPerWaitHour float64, inflightCacheExpiry config.Duration, rootSnoozeTime config.Duration, + batchingStrategyID uint32, // See ccipexec package ) (ccipconfig.OffchainConfig, error) { switch VersionMap[OffRampContract] { case Latest: @@ -1480,6 +1483,7 @@ func NewExecOffchainConfig( relativeBoostPerWaitHour, inflightCacheExpiry, rootSnoozeTime, + batchingStrategyID, ), nil case V1_2_0: return testhelpers_1_4_0.NewExecOffchainConfig( @@ -1488,6 +1492,7 @@ func NewExecOffchainConfig( relativeBoostPerWaitHour, inflightCacheExpiry, rootSnoozeTime, + batchingStrategyID, ), nil default: return nil, fmt.Errorf("version not supported: %s", VersionMap[OffRampContract]) diff --git a/integration-tests/ccip-tests/contracts/contract_models.go b/integration-tests/ccip-tests/contracts/contract_models.go index e3f6e45fad..83fe12a60a 100644 --- a/integration-tests/ccip-tests/contracts/contract_models.go +++ b/integration-tests/ccip-tests/contracts/contract_models.go @@ -112,9 +112,9 @@ const ( var ( V1_2_0 = MustVersion("1.2.0") V1_4_0 = MustVersion("1.4.0") - V1_5_0_dev = MustVersion("1.5.0") - LatestPoolVersion = V1_5_0_dev - Latest = V1_5_0_dev + V1_5_0 = MustVersion("1.5.0") + LatestPoolVersion = V1_5_0 + Latest = V1_5_0 VersionMap = map[Name]Version{ PriceRegistryContract: V1_2_0, OffRampContract: Latest, @@ -1616,22 +1616,58 @@ func (w OnRampWrapper) ParseCCIPSendRequested(l types.Log) (uint64, error) { return 0, fmt.Errorf("no instance found to parse CCIPSendRequested") } -func (w OnRampWrapper) GetDynamicConfig(opts *bind.CallOpts) (uint32, error) { +// GetDynamicConfig retrieves the dynamic config for the onramp +func (w OnRampWrapper) GetDynamicConfig(opts *bind.CallOpts) (evm_2_evm_onramp.EVM2EVMOnRampDynamicConfig, error) { if w.Latest != nil { cfg, err := w.Latest.GetDynamicConfig(opts) if err != nil { - return 0, err + return evm_2_evm_onramp.EVM2EVMOnRampDynamicConfig{}, err } - return cfg.MaxDataBytes, nil + return cfg, nil } if w.V1_2_0 != nil { cfg, err := w.V1_2_0.GetDynamicConfig(opts) if err != nil { - return 0, err + return evm_2_evm_onramp.EVM2EVMOnRampDynamicConfig{}, err } - return cfg.MaxDataBytes, nil + return evm_2_evm_onramp.EVM2EVMOnRampDynamicConfig{ + Router: cfg.Router, + MaxNumberOfTokensPerMsg: cfg.MaxNumberOfTokensPerMsg, + DestGasOverhead: cfg.DestGasOverhead, + DestGasPerPayloadByte: cfg.DestGasPerPayloadByte, + DestDataAvailabilityOverheadGas: cfg.DestDataAvailabilityOverheadGas, + DestGasPerDataAvailabilityByte: cfg.DestGasPerDataAvailabilityByte, + DestDataAvailabilityMultiplierBps: cfg.DestDataAvailabilityMultiplierBps, + PriceRegistry: cfg.PriceRegistry, + MaxDataBytes: cfg.MaxDataBytes, + MaxPerMsgGasLimit: cfg.MaxPerMsgGasLimit, + }, nil + } + return evm_2_evm_onramp.EVM2EVMOnRampDynamicConfig{}, fmt.Errorf("no instance found to get dynamic config") +} + +// SetDynamicConfig sets the dynamic config for the onramp +// Note that you cannot set only a single field, you must set all fields or they will be reset to zero values +// You can use GetDynamicConfig to get the current config and modify it as needed +func (w OnRampWrapper) SetDynamicConfig(opts *bind.TransactOpts, dynamicConfig evm_2_evm_onramp.EVM2EVMOnRampDynamicConfig) (*types.Transaction, error) { + if w.Latest != nil { + return w.Latest.SetDynamicConfig(opts, dynamicConfig) + } + if w.V1_2_0 != nil { + return w.V1_2_0.SetDynamicConfig(opts, evm_2_evm_onramp_1_2_0.EVM2EVMOnRampDynamicConfig{ + Router: dynamicConfig.Router, + MaxNumberOfTokensPerMsg: dynamicConfig.MaxNumberOfTokensPerMsg, + DestGasOverhead: dynamicConfig.DestGasOverhead, + DestGasPerPayloadByte: dynamicConfig.DestGasPerPayloadByte, + DestDataAvailabilityOverheadGas: dynamicConfig.DestDataAvailabilityOverheadGas, + DestGasPerDataAvailabilityByte: dynamicConfig.DestGasPerDataAvailabilityByte, + DestDataAvailabilityMultiplierBps: dynamicConfig.DestDataAvailabilityMultiplierBps, + PriceRegistry: dynamicConfig.PriceRegistry, + MaxDataBytes: dynamicConfig.MaxDataBytes, + MaxPerMsgGasLimit: dynamicConfig.MaxPerMsgGasLimit, + }) } - return 0, fmt.Errorf("no instance found to get dynamic config") + return nil, fmt.Errorf("no instance found to set dynamic config") } func (w OnRampWrapper) ApplyPoolUpdates(opts *bind.TransactOpts, tokens []common.Address, pools []common.Address) (*types.Transaction, error) { diff --git a/integration-tests/ccip-tests/contracts/laneconfig/parse_contracts.go b/integration-tests/ccip-tests/contracts/laneconfig/parse_contracts.go index 332bd48ab3..c96cb3dfdc 100644 --- a/integration-tests/ccip-tests/contracts/laneconfig/parse_contracts.go +++ b/integration-tests/ccip-tests/contracts/laneconfig/parse_contracts.go @@ -21,6 +21,7 @@ var ( type CommonContracts struct { IsNativeFeeToken bool `json:"is_native_fee_token,omitempty"` + AllowOutOfOrder bool `json:"allow_out_of_order,omitempty"` // expected to set this value as True for ZK chain source networks IsMockARM bool `json:"is_mock_arm,omitempty"` FeeToken string `json:"fee_token"` BridgeTokens []string `json:"bridge_tokens,omitempty"` diff --git a/integration-tests/ccip-tests/load/ccip_loadgen.go b/integration-tests/ccip-tests/load/ccip_loadgen.go index 9dc8ce16e5..9d24fd1dd0 100644 --- a/integration-tests/ccip-tests/load/ccip_loadgen.go +++ b/integration-tests/ccip-tests/load/ccip_loadgen.go @@ -14,6 +14,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/rs/zerolog" + "github.com/smartcontractkit/ccip/integration-tests/ccip-tests/contracts" chain_selectors "github.com/smartcontractkit/chain-selectors" "github.com/stretchr/testify/require" "go.uber.org/atomic" @@ -132,8 +133,9 @@ func (c *CCIPE2ELoad) BeforeAllCall() { c.EOAReceiver = c.msg.Receiver } if c.SendMaxDataIntermittentlyInMsgCount > 0 { - c.MaxDataBytes, err = sourceCCIP.OnRamp.Instance.GetDynamicConfig(nil) + cfg, err := sourceCCIP.OnRamp.Instance.GetDynamicConfig(nil) require.NoError(c.t, err, "failed to fetch dynamic config") + c.MaxDataBytes = cfg.MaxDataBytes } // if the msg is sent via multicall, transfer the token transfer amount to multicall contract if sourceCCIP.Common.MulticallEnabled && @@ -189,11 +191,28 @@ func (c *CCIPE2ELoad) CCIPMsg() (router.ClientEVM2AnyMessage, *testreporters.Req if !msgDetails.IsTokenTransfer() { msg.TokenAmounts = []router.ClientEVMTokenAmount{} } - extraArgsV1, err := testhelpers.GetEVMExtraArgsV1(big.NewInt(gasLimit), false) + + var ( + extraArgs []byte + err error + ) + // v1.5.0 and later starts using V2 extra args + matchErr := contracts.MatchContractVersionsOrAbove(map[contracts.Name]contracts.Version{ + contracts.OnRampContract: contracts.V1_5_0, + }) + // TODO: The CCIP Offchain upgrade tests make the AllowOutOfOrder flag tricky in this case. + // It runs with out of date contract versions at first, then upgrades them. So transactions will assume that the new contracts are there + // before being deployed. So setting v2 args will break the test. This is a bit of a hack to get around that. + // The test will soon be deprecated, so a temporary solution is fine. + if matchErr != nil || !c.Lane.Source.Common.AllowOutOfOrder { + extraArgs, err = testhelpers.GetEVMExtraArgsV1(big.NewInt(gasLimit), false) + } else { + extraArgs, err = testhelpers.GetEVMExtraArgsV2(big.NewInt(gasLimit), c.Lane.Source.Common.AllowOutOfOrder) + } if err != nil { return router.ClientEVM2AnyMessage{}, stats, err } - msg.ExtraArgs = extraArgsV1 + msg.ExtraArgs = extraArgs // if gaslimit is 0, set the receiver to EOA if gasLimit == 0 { msg.Receiver = c.EOAReceiver diff --git a/integration-tests/ccip-tests/load/helper.go b/integration-tests/ccip-tests/load/helper.go index f38186f817..3465b58204 100644 --- a/integration-tests/ccip-tests/load/helper.go +++ b/integration-tests/ccip-tests/load/helper.go @@ -206,10 +206,7 @@ func (l *LoadArgs) ValidateCurseFollowedByUncurse() { // try to send requests on lanes on which curse is applied on source RMN and the request should revert // data-only transfer is sufficient lane.Source.TransferAmount = []*big.Int{} - failedTx, _, _, err := lane.Source.SendRequest( - lane.Dest.ReceiverDapp.EthAddress, - big.NewInt(actions.DefaultDestinationGasLimit), // gas limit - ) + failedTx, _, _, err := lane.Source.SendRequest(lane.Dest.ReceiverDapp.EthAddress, big.NewInt(actions.DefaultDestinationGasLimit)) if lane.Source.Common.ChainClient.GetNetworkConfig().MinimumConfirmations > 0 { require.Error(l.t, err) } else { diff --git a/integration-tests/ccip-tests/smoke/ccip_test.go b/integration-tests/ccip-tests/smoke/ccip_test.go index c07d0216a7..83bed78507 100644 --- a/integration-tests/ccip-tests/smoke/ccip_test.go +++ b/integration-tests/ccip-tests/smoke/ccip_test.go @@ -244,7 +244,7 @@ func TestSmokeCCIPRateLimit(t *testing.T) { require.NoError(t, tc.lane.Source.Common.ChainClient.WaitForEvents()) failedTx, _, _, err := tc.lane.Source.SendRequest( tc.lane.Dest.ReceiverDapp.EthAddress, - big.NewInt(actions.DefaultDestinationGasLimit), // gas limit + big.NewInt(actions.DefaultDestinationGasLimit), ) require.NoError(t, err) require.Error(t, tc.lane.Source.Common.ChainClient.WaitForEvents()) @@ -270,10 +270,7 @@ func TestSmokeCCIPRateLimit(t *testing.T) { // try to send again with amount more than the amount refilled by rate and // this should fail, as the refill rate is not enough to refill the capacity src.TransferAmount[0] = new(big.Int).Mul(AggregatedRateLimitRate, big.NewInt(10)) - failedTx, _, _, err = tc.lane.Source.SendRequest( - tc.lane.Dest.ReceiverDapp.EthAddress, - big.NewInt(actions.DefaultDestinationGasLimit), // gas limit - ) + failedTx, _, _, err = tc.lane.Source.SendRequest(tc.lane.Dest.ReceiverDapp.EthAddress, big.NewInt(actions.DefaultDestinationGasLimit)) tc.lane.Logger.Info().Str("tokensToSend", src.TransferAmount[0].String()).Msg("More than Aggregated Rate") require.NoError(t, err) require.Error(t, tc.lane.Source.Common.ChainClient.WaitForEvents()) @@ -337,10 +334,7 @@ func TestSmokeCCIPRateLimit(t *testing.T) { src.TransferAmount[0] = tokensToSend tc.lane.Logger.Info().Str("tokensToSend", tokensToSend.String()).Msg("More than Token Pool Capacity") - failedTx, _, _, err = tc.lane.Source.SendRequest( - tc.lane.Dest.ReceiverDapp.EthAddress, - big.NewInt(actions.DefaultDestinationGasLimit), // gas limit - ) + failedTx, _, _, err = tc.lane.Source.SendRequest(tc.lane.Dest.ReceiverDapp.EthAddress, big.NewInt(actions.DefaultDestinationGasLimit)) require.NoError(t, err) require.Error(t, tc.lane.Source.Common.ChainClient.WaitForEvents()) errReason, v, err = tc.lane.Source.Common.ChainClient.RevertReasonFromTx(failedTx, lock_release_token_pool.LockReleaseTokenPoolABI) @@ -372,10 +366,7 @@ func TestSmokeCCIPRateLimit(t *testing.T) { src.Common.ChainClient.GetDefaultWallet(), src.Common.Router.Address(), src.TransferAmount[0]), ) require.NoError(t, tc.lane.Source.Common.ChainClient.WaitForEvents()) - failedTx, _, _, err = tc.lane.Source.SendRequest( - tc.lane.Dest.ReceiverDapp.EthAddress, - big.NewInt(actions.DefaultDestinationGasLimit), - ) + failedTx, _, _, err = tc.lane.Source.SendRequest(tc.lane.Dest.ReceiverDapp.EthAddress, big.NewInt(actions.DefaultDestinationGasLimit)) require.NoError(t, err) require.Error(t, tc.lane.Source.Common.ChainClient.WaitForEvents()) errReason, v, err = tc.lane.Source.Common.ChainClient.RevertReasonFromTx(failedTx, lock_release_token_pool.LockReleaseTokenPoolABI) @@ -404,8 +395,8 @@ func TestSmokeCCIPOnRampLimits(t *testing.T) { "This test modifies contract state. Before running it, ensure you are willing and able to do so.", ) err := contracts.MatchContractVersionsOrAbove(map[contracts.Name]contracts.Version{ - contracts.OffRampContract: contracts.V1_5_0_dev, - contracts.OnRampContract: contracts.V1_5_0_dev, + contracts.OffRampContract: contracts.V1_5_0, + contracts.OnRampContract: contracts.V1_5_0, }) require.NoError(t, err, "Required contract versions not met") @@ -625,8 +616,8 @@ func TestSmokeCCIPTokenPoolRateLimits(t *testing.T) { "This test modifies contract state. Before running it, ensure you are willing and able to do so.", ) err := contracts.MatchContractVersionsOrAbove(map[contracts.Name]contracts.Version{ - contracts.OffRampContract: contracts.V1_5_0_dev, - contracts.OnRampContract: contracts.V1_5_0_dev, + contracts.OffRampContract: contracts.V1_5_0, + contracts.OnRampContract: contracts.V1_5_0, }) require.NoError(t, err, "Required contract versions not met") @@ -1004,7 +995,7 @@ func testOffRampRateLimits(t *testing.T, rateLimiterConfig contracts.RateLimiter "This test modifies contract state. Before running it, ensure you are willing and able to do so.", ) err := contracts.MatchContractVersionsOrAbove(map[contracts.Name]contracts.Version{ - contracts.OffRampContract: contracts.V1_5_0_dev, + contracts.OffRampContract: contracts.V1_5_0, }) require.NoError(t, err, "Required contract versions not met") require.False(t, pointer.GetBool(TestCfg.TestGroupInput.ExistingDeployment), "This test modifies contract state and cannot be run on existing deployments") @@ -1129,7 +1120,6 @@ func testOffRampRateLimits(t *testing.T, rateLimiterConfig contracts.RateLimiter require.NoError(t, err, "Error manually executing transaction after rate limit is lifted") }) } - } // SetupReorgSuite defines the setup required to perform re-org step diff --git a/integration-tests/ccip-tests/testconfig/README.md b/integration-tests/ccip-tests/testconfig/README.md index bcf468a36c..474ac2a3af 100644 --- a/integration-tests/ccip-tests/testconfig/README.md +++ b/integration-tests/ccip-tests/testconfig/README.md @@ -473,6 +473,10 @@ Specifies whether to set up bi-directional lanes between networks. Specifies whether commit and execution jobs are to be run on the same Chainlink node. +### CCIP.Groups.[testgroup].AllowOutOfOrder + +Specifies whether out of order execution is allowed globally for all the chains. + ### CCIP.Groups.[testgroup].NoOfCommitNodes Specifies the number of nodes on which commit jobs are to be run. This needs to be lesser than the total number of nodes mentioned in [CCIP.Env.NewCLCluster.NoOfNodes](#ccipenvnewclclusternoofnodes) or [CCIP.Env.ExistingCLCluster.NoOfNodes](#ccipenvexistingclclusternoofnodes). diff --git a/integration-tests/ccip-tests/testconfig/ccip.go b/integration-tests/ccip-tests/testconfig/ccip.go index a3e322b70a..1eff991403 100644 --- a/integration-tests/ccip-tests/testconfig/ccip.go +++ b/integration-tests/ccip-tests/testconfig/ccip.go @@ -266,6 +266,7 @@ type CCIPTestGroupConfig struct { KeepEnvAlive *bool `toml:",omitempty"` BiDirectionalLane *bool `toml:",omitempty"` CommitAndExecuteOnSameDON *bool `toml:",omitempty"` + AllowOutOfOrder *bool `toml:",omitempty"` // To set out of order execution globally NoOfCommitNodes int `toml:",omitempty"` MsgDetails *MsgDetails `toml:",omitempty"` TokenConfig *TokenConfig `toml:",omitempty"` diff --git a/integration-tests/ccip-tests/testconfig/tomls/ccip-default.toml b/integration-tests/ccip-tests/testconfig/tomls/ccip-default.toml index 076c334e07..15bf443bca 100644 --- a/integration-tests/ccip-tests/testconfig/tomls/ccip-default.toml +++ b/integration-tests/ccip-tests/testconfig/tomls/ccip-default.toml @@ -27,7 +27,7 @@ ethereum_version = "eth1" # geth, besu, erigon or nethermind execution_layer = "geth" # eth2-only, if set to true environment startup will wait until at least 1 epoch has been finalised -wait_for_finalization=false +wait_for_finalization = false [CCIP.Env.PrivateEthereumNetworks.SIMULATED_1.EthereumChainConfig] # eth2-only, the lower the value the faster the block production (3 is minimum) @@ -244,6 +244,7 @@ version = "ccip-develop" KeepEnvAlive = false # if true, the test will not tear down the test environment after the test is finished CommitAndExecuteOnSameDON = true # if true, and the test is building the env from scratch, same chainlink nodes will be used for Commit and Execution jobs. # Otherwise Commit and execution jobs will be set up in different nodes based on the number of nodes specified in NoOfCommitNodes and CCIP.Env.NewCLCluster.NoOfNodes +AllowOutOfOrder = false # if true, all lanes will set all transactions to allow out of order execution. This setting overrides individual settings from lane_config. To allow out of order execution per lane, then send "allow_out_of_order":true, similar to is_native_fee_token variable. BiDirectionalLane = true # True uses both the lanes. If bidirectional is false only one way lane is set up. NoOfCommitNodes = 5 # no of chainlink nodes with Commit job PhaseTimeout = '10m' # Duration to wait for the each phase validation(SendRequested, Commit, RMN Blessing, Execution) to time-out. @@ -275,7 +276,7 @@ TimeoutForPriceUpdate = '15m' # Duration to wait for the price update to time-ou # Now testing only with dynamic price getter (no pipeline). # Could be removed once the pipeline is completely removed. WithPipeline = false -NoOfTokensPerChain = 2 # number of bridge tokens to be deployed per network; if MsgType = 'Token'/'DataWithToken' +NoOfTokensPerChain = 2 # number of bridge tokens to be deployed per network; if MsgType = 'Token'/'DataWithToken' CCIPOwnerTokens = false # if true, the test will use deploy the tokens by the CCIPOwner, otherwise the tokens will be deployed by a non-owner account, only applicable for 1.5 pools and onwards #NoOfTokensWithDynamicPrice = 15 # number of tokens with dynamic price to be deployed @@ -297,6 +298,7 @@ CCIPOwnerTokens = false # if true, the test will use deploy the tokens by the CC KeepEnvAlive = false # same as above CommitAndExecuteOnSameDON = true # same as above +AllowOutOfOrder = false # same as above BiDirectionalLane = true # same as above NoOfCommitNodes = 5 # same as above PhaseTimeout = '10m' # same as above @@ -355,7 +357,7 @@ TimeoutForPriceUpdate = '15m' # Duration to wait for the price update to time-ou # Now testing only with dynamic price getter (no pipeline). # Could be removed once the pipeline is completely removed. WithPipeline = false -NoOfTokensPerChain = 2 # number of bridge tokens to be deployed per network; if MsgType = 'Token'/'DataWithToken' +NoOfTokensPerChain = 2 # number of bridge tokens to be deployed per network; if MsgType = 'Token'/'DataWithToken' CCIPOwnerTokens = false # if true, the test will use deploy the tokens by the CCIPOwner, otherwise the tokens and pools will be deployed by a non-owner account, # only applicable for 1.5 pools and onwards, if you are running with pre-1.5 pools, then set this to true to deploy token pools by CCIPOwner, otherwise # the test will fail @@ -407,6 +409,7 @@ CCIPOwnerTokens = false # if true, the test will use deploy the tokens by the CC #NetworkPairs = ['SEPOLIA,OPTIMISM_GOERLI','SEPOLIA,POLYGON_MUMBAI','AVALANCHE_FUJI,SEPOLIA','SEPOLIA,BASE_GOERLI','SEPOLIA,BSC_TESTNET','SEPOLIA,WEMIX_TESTNET','AVALANCHE_FUJI,OPTIMISM_GOERLI','AVALANCHE_FUJI,POLYGON_MUMBAI','AVALANCHE_FUJI,BSC_TESTNET','AVALANCHE_FUJI,BASE_GOERLI','OPTIMISM_GOERLI,BASE_GOERLI','OPTIMISM_GOERLI,POLYGON_MUMBAI','BSC_TESTNET,POLYGON_MUMBAI','BSC_TESTNET,BASE_GOERLI','WEMIX_TESTNET,KROMA_SEPOLIA'] KeepEnvAlive = false CommitAndExecuteOnSameDON = false +AllowOutOfOrder = false BiDirectionalLane = true NoOfCommitNodes = 5 PhaseTimeout = '50m' From f95dce64f5b685601ebc422ca4659a563c7f1626 Mon Sep 17 00:00:00 2001 From: Ryan Hall <RyanRHall@users.noreply.github.com> Date: Wed, 18 Sep 2024 03:36:06 -0400 Subject: [PATCH 101/115] Productionize RMN remote contract (#1431) ## Background [Original PR](https://github.com/smartcontractkit/ccip/pull/1308) - there is some discussion here that is possibly still relevant) [Open PR to add cursing](https://github.com/smartcontractkit/ccip/pull/1400) - I copied the relevant parts for the `RMNRemote`. Note: we are intentionally separating `RMNRemote` and `RMNHome` since they have different timelines. ## Motivation Productionize the RMNRemote and include it in integration tests --------- Co-authored-by: Makram <makramkd@users.noreply.github.com> --- contracts/.solhintignore | 7 +- contracts/gas-snapshots/ccip.gas-snapshot | 423 ++++++++-------- contracts/src/v0.8/ccip/interfaces/IRMNV2.sol | 19 +- contracts/src/v0.8/ccip/offRamp/OffRamp.sol | 5 +- contracts/src/v0.8/ccip/rmn/RMNHome.sol | 41 +- contracts/src/v0.8/ccip/rmn/RMNRemote.sol | 297 ++++++----- contracts/src/v0.8/ccip/test/BaseTest.t.sol | 18 + .../ccip/test/e2e/MultiRampsEnd2End.t.sol | 9 +- .../src/v0.8/ccip/test/offRamp/OffRamp.t.sol | 91 +++- .../src/v0.8/ccip/test/rmn/RMNHome.t.sol | 15 + .../src/v0.8/ccip/test/rmn/RMNRemote.t.sol | 280 +++++++++++ .../v0.8/ccip/test/rmn/RMNRemoteSetup.t.sol | 144 ++++++ .../enumerable/EnumerableSetWithBytes16.sol | 454 +++++++++++++++++ .../ccip_encoding_utils.go | 4 +- .../ccip_reader_tester/ccip_reader_tester.go | 7 +- .../ccip/generated/offramp/offramp.go | 2 +- .../generated/report_codec/report_codec.go | 7 +- .../ccip/generated/rmn_remote/rmn_remote.go | 461 ++++++++++++++++-- ...rapper-dependency-versions-do-not-edit.txt | 10 +- tools/ci/ccip_lcov_prune | 1 + 20 files changed, 1864 insertions(+), 431 deletions(-) create mode 100644 contracts/src/v0.8/ccip/test/rmn/RMNHome.t.sol create mode 100644 contracts/src/v0.8/ccip/test/rmn/RMNRemote.t.sol create mode 100644 contracts/src/v0.8/ccip/test/rmn/RMNRemoteSetup.t.sol create mode 100644 contracts/src/v0.8/shared/enumerable/EnumerableSetWithBytes16.sol diff --git a/contracts/.solhintignore b/contracts/.solhintignore index 5ae38e28d9..82f217fa2a 100644 --- a/contracts/.solhintignore +++ b/contracts/.solhintignore @@ -42,5 +42,8 @@ ./src/v0.8/vendor ./node_modules/ -# Ignore RMN contracts temporarily -./src/v0.8/ccip/rmn \ No newline at end of file +# Ignore RMNHome contract temporarily +./src/v0.8/ccip/rmn/RMNHome.sol + +# Ignore tweaked vendored contracts +./src/v0.8/shared/enumerable/EnumerableSetWithBytes16.sol \ No newline at end of file diff --git a/contracts/gas-snapshots/ccip.gas-snapshot b/contracts/gas-snapshots/ccip.gas-snapshot index c3f52691d9..7562ea5cb3 100644 --- a/contracts/gas-snapshots/ccip.gas-snapshot +++ b/contracts/gas-snapshots/ccip.gas-snapshot @@ -34,7 +34,7 @@ BurnWithFromMintTokenPool_lockOrBurn:test_ChainNotAllowed_Revert() (gas: 28842) BurnWithFromMintTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 55271) BurnWithFromMintTokenPool_lockOrBurn:test_PoolBurn_Success() (gas: 244050) BurnWithFromMintTokenPool_lockOrBurn:test_Setup_Success() (gas: 24170) -CCIPClientExample_sanity:test_ImmutableExamples_Success() (gas: 2052437) +CCIPClientExample_sanity:test_ImmutableExamples_Success() (gas: 2052431) CCIPConfigSetup:test_getCapabilityConfiguration_Success() (gas: 9508) CCIPConfig_ConfigStateMachine:test__computeConfigDigest_Success() (gas: 83274) CCIPConfig_ConfigStateMachine:test__computeNewConfigWithMeta_InitToRunning_Success() (gas: 354656) @@ -123,73 +123,73 @@ CommitStore_verify:test_TooManyLeaves_Revert() (gas: 36848) DefensiveExampleTest:test_HappyPath_Success() (gas: 200200) DefensiveExampleTest:test_Recovery() (gas: 424479) E2E:test_E2E_3MessagesSuccess_gas() (gas: 1106985) -EVM2EVMOffRamp__releaseOrMintToken:test__releaseOrMintToken_NotACompatiblePool_Revert() (gas: 38313) -EVM2EVMOffRamp__releaseOrMintToken:test__releaseOrMintToken_Success() (gas: 104441) -EVM2EVMOffRamp__releaseOrMintToken:test__releaseOrMintToken_TokenHandlingError_transfer_Revert() (gas: 86029) -EVM2EVMOffRamp__releaseOrMintToken:test_releaseOrMintToken_InvalidDataLength_Revert() (gas: 37362) -EVM2EVMOffRamp__releaseOrMintToken:test_releaseOrMintToken_ReleaseOrMintBalanceMismatch_Revert() (gas: 95010) -EVM2EVMOffRamp__releaseOrMintToken:test_releaseOrMintToken_TokenHandlingError_BalanceOf_Revert() (gas: 40338) +EVM2EVMOffRamp__releaseOrMintToken:test__releaseOrMintToken_NotACompatiblePool_Revert() (gas: 38322) +EVM2EVMOffRamp__releaseOrMintToken:test__releaseOrMintToken_Success() (gas: 104438) +EVM2EVMOffRamp__releaseOrMintToken:test__releaseOrMintToken_TokenHandlingError_transfer_Revert() (gas: 86026) +EVM2EVMOffRamp__releaseOrMintToken:test_releaseOrMintToken_InvalidDataLength_Revert() (gas: 37365) +EVM2EVMOffRamp__releaseOrMintToken:test_releaseOrMintToken_ReleaseOrMintBalanceMismatch_Revert() (gas: 95013) +EVM2EVMOffRamp__releaseOrMintToken:test_releaseOrMintToken_TokenHandlingError_BalanceOf_Revert() (gas: 40341) EVM2EVMOffRamp__releaseOrMintToken:test_releaseOrMintToken_skip_ReleaseOrMintBalanceMismatch_if_pool_Revert() (gas: 87189) EVM2EVMOffRamp__releaseOrMintTokens:test_OverValueWithARLOff_Success() (gas: 381594) EVM2EVMOffRamp__releaseOrMintTokens:test_PriceNotFoundForToken_Reverts() (gas: 140568) EVM2EVMOffRamp__releaseOrMintTokens:test_RateLimitErrors_Reverts() (gas: 798833) EVM2EVMOffRamp__releaseOrMintTokens:test_TokenHandlingError_Reverts() (gas: 178400) -EVM2EVMOffRamp__releaseOrMintTokens:test__releaseOrMintTokens_NotACompatiblePool_Reverts() (gas: 29684) +EVM2EVMOffRamp__releaseOrMintTokens:test__releaseOrMintTokens_NotACompatiblePool_Reverts() (gas: 29681) EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_InvalidDataLengthReturnData_Revert() (gas: 67146) EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_InvalidEVMAddress_Revert() (gas: 43605) EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_Success() (gas: 208068) EVM2EVMOffRamp__releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals_Success() (gas: 219365) -EVM2EVMOffRamp__report:test_Report_Success() (gas: 127777) -EVM2EVMOffRamp__trialExecute:test_RateLimitError_Success() (gas: 237403) -EVM2EVMOffRamp__trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 246036) +EVM2EVMOffRamp__report:test_Report_Success() (gas: 127774) +EVM2EVMOffRamp__trialExecute:test_RateLimitError_Success() (gas: 237406) +EVM2EVMOffRamp__trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 246039) EVM2EVMOffRamp__trialExecute:test_TokenPoolIsNotAContract_Success() (gas: 329283) EVM2EVMOffRamp__trialExecute:test_trialExecute_Success() (gas: 310166) -EVM2EVMOffRamp_ccipReceive:test_Reverts() (gas: 17051) +EVM2EVMOffRamp_ccipReceive:test_Reverts() (gas: 17048) EVM2EVMOffRamp_constructor:test_CommitStoreAlreadyInUse_Revert() (gas: 153120) -EVM2EVMOffRamp_constructor:test_Constructor_Success() (gas: 5212744) +EVM2EVMOffRamp_constructor:test_Constructor_Success() (gas: 5212732) EVM2EVMOffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 143845) -EVM2EVMOffRamp_execute:test_EmptyReport_Revert() (gas: 21504) -EVM2EVMOffRamp_execute:test_InvalidMessageId_Revert() (gas: 36933) +EVM2EVMOffRamp_execute:test_EmptyReport_Revert() (gas: 21507) +EVM2EVMOffRamp_execute:test_InvalidMessageId_Revert() (gas: 36936) EVM2EVMOffRamp_execute:test_InvalidSourceChain_Revert() (gas: 52324) EVM2EVMOffRamp_execute:test_InvalidSourcePoolAddress_Success() (gas: 473387) EVM2EVMOffRamp_execute:test_ManualExecutionNotYetEnabled_Revert() (gas: 48346) -EVM2EVMOffRamp_execute:test_MessageTooLarge_Revert() (gas: 153016) +EVM2EVMOffRamp_execute:test_MessageTooLarge_Revert() (gas: 153019) EVM2EVMOffRamp_execute:test_Paused_Revert() (gas: 103946) -EVM2EVMOffRamp_execute:test_ReceiverError_Success() (gas: 165364) +EVM2EVMOffRamp_execute:test_ReceiverError_Success() (gas: 165358) EVM2EVMOffRamp_execute:test_RetryFailedMessageWithoutManualExecution_Success() (gas: 180107) EVM2EVMOffRamp_execute:test_RootNotCommitted_Revert() (gas: 43157) EVM2EVMOffRamp_execute:test_SingleMessageNoTokensUnordered_Success() (gas: 160119) EVM2EVMOffRamp_execute:test_SingleMessageNoTokens_Success() (gas: 175497) EVM2EVMOffRamp_execute:test_SingleMessageToNonCCIPReceiver_Success() (gas: 237901) -EVM2EVMOffRamp_execute:test_SingleMessagesNoTokensSuccess_gas() (gas: 115045) +EVM2EVMOffRamp_execute:test_SingleMessagesNoTokensSuccess_gas() (gas: 115048) EVM2EVMOffRamp_execute:test_SkippedIncorrectNonceStillExecutes_Success() (gas: 406606) EVM2EVMOffRamp_execute:test_SkippedIncorrectNonce_Success() (gas: 54774) -EVM2EVMOffRamp_execute:test_StrictUntouchedToSuccess_Success() (gas: 132562) -EVM2EVMOffRamp_execute:test_TokenDataMismatch_Revert() (gas: 52783) -EVM2EVMOffRamp_execute:test_TwoMessagesWithTokensAndGE_Success() (gas: 564477) -EVM2EVMOffRamp_execute:test_TwoMessagesWithTokensSuccess_gas() (gas: 494716) -EVM2EVMOffRamp_execute:test_UnexpectedTokenData_Revert() (gas: 35884) +EVM2EVMOffRamp_execute:test_StrictUntouchedToSuccess_Success() (gas: 132556) +EVM2EVMOffRamp_execute:test_TokenDataMismatch_Revert() (gas: 52786) +EVM2EVMOffRamp_execute:test_TwoMessagesWithTokensAndGE_Success() (gas: 564471) +EVM2EVMOffRamp_execute:test_TwoMessagesWithTokensSuccess_gas() (gas: 494719) +EVM2EVMOffRamp_execute:test_UnexpectedTokenData_Revert() (gas: 35887) EVM2EVMOffRamp_execute:test_Unhealthy_Revert() (gas: 546333) -EVM2EVMOffRamp_execute:test_UnsupportedNumberOfTokens_Revert() (gas: 65295) +EVM2EVMOffRamp_execute:test_UnsupportedNumberOfTokens_Revert() (gas: 65298) EVM2EVMOffRamp_execute:test__execute_SkippedAlreadyExecutedMessageUnordered_Success() (gas: 124107) EVM2EVMOffRamp_execute:test__execute_SkippedAlreadyExecutedMessage_Success() (gas: 144365) EVM2EVMOffRamp_execute:test_execute_RouterYULCall_Success() (gas: 394187) EVM2EVMOffRamp_executeSingleMessage:test_MessageSender_Revert() (gas: 18685) -EVM2EVMOffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 275266) -EVM2EVMOffRamp_executeSingleMessage:test_NonContract_Success() (gas: 18824) -EVM2EVMOffRamp_executeSingleMessage:test_TokenHandlingError_Revert() (gas: 223179) +EVM2EVMOffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 275257) +EVM2EVMOffRamp_executeSingleMessage:test_NonContract_Success() (gas: 18815) +EVM2EVMOffRamp_executeSingleMessage:test_TokenHandlingError_Revert() (gas: 223182) EVM2EVMOffRamp_executeSingleMessage:test_ZeroGasDONExecution_Revert() (gas: 48391) EVM2EVMOffRamp_executeSingleMessage:test_executeSingleMessage_NoTokens_Success() (gas: 47823) EVM2EVMOffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens_Success() (gas: 311554) EVM2EVMOffRamp_executeSingleMessage:test_executeSingleMessage_ZeroGasZeroData_Success() (gas: 70839) -EVM2EVMOffRamp_execute_upgrade:test_V2NonceNewSenderStartsAtZero_Success() (gas: 232142) +EVM2EVMOffRamp_execute_upgrade:test_V2NonceNewSenderStartsAtZero_Success() (gas: 232136) EVM2EVMOffRamp_execute_upgrade:test_V2NonceStartsAtV1Nonce_Success() (gas: 281170) EVM2EVMOffRamp_execute_upgrade:test_V2OffRampNonceSkipsIfMsgInFlight_Success() (gas: 262488) EVM2EVMOffRamp_execute_upgrade:test_V2SenderNoncesReadsPreviousRamp_Success() (gas: 230645) EVM2EVMOffRamp_execute_upgrade:test_V2_Success() (gas: 132092) EVM2EVMOffRamp_getAllRateLimitTokens:test_GetAllRateLimitTokens_Success() (gas: 38626) -EVM2EVMOffRamp_getExecutionState:test_FillExecutionState_Success() (gas: 3402112) -EVM2EVMOffRamp_getExecutionState:test_GetExecutionState_Success() (gas: 84887) +EVM2EVMOffRamp_getExecutionState:test_FillExecutionState_Success() (gas: 3397486) +EVM2EVMOffRamp_getExecutionState:test_GetExecutionState_Success() (gas: 84833) EVM2EVMOffRamp_manuallyExecute:test_ManualExecFailedTx_Revert() (gas: 188280) EVM2EVMOffRamp_manuallyExecute:test_ManualExecForkedChain_Revert() (gas: 27574) EVM2EVMOffRamp_manuallyExecute:test_ManualExecGasLimitMismatch_Revert() (gas: 46457) @@ -197,7 +197,7 @@ EVM2EVMOffRamp_manuallyExecute:test_ManualExecInvalidGasLimit_Revert() (gas: 279 EVM2EVMOffRamp_manuallyExecute:test_ManualExecWithMultipleMessagesAndSourceTokens_Success() (gas: 531330) EVM2EVMOffRamp_manuallyExecute:test_ManualExecWithSourceTokens_Success() (gas: 344463) EVM2EVMOffRamp_manuallyExecute:test_ManualExec_Success() (gas: 189760) -EVM2EVMOffRamp_manuallyExecute:test_ReentrancyManualExecuteFails_Success() (gas: 2195134) +EVM2EVMOffRamp_manuallyExecute:test_ReentrancyManualExecuteFails_Success() (gas: 2195128) EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_DestinationGasAmountCountMismatch_Revert() (gas: 362054) EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_DoesNotRevertIfUntouched_Success() (gas: 145457) EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_InvalidTokenGasOverride_Revert() (gas: 365283) @@ -205,21 +205,21 @@ EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_LowGasLimitManualExec_Succes EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_WithGasOverride_Success() (gas: 192223) EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_WithInvalidReceiverExecutionGasOverride_Revert() (gas: 155387) EVM2EVMOffRamp_manuallyExecute:test_manuallyExecute_WithInvalidSourceTokenDataCount_Revert() (gas: 60494) -EVM2EVMOffRamp_metadataHash:test_MetadataHash_Success() (gas: 8916) -EVM2EVMOffRamp_setDynamicConfig:test_NonOwner_Revert() (gas: 40360) -EVM2EVMOffRamp_setDynamicConfig:test_RouterZeroAddress_Revert() (gas: 38422) -EVM2EVMOffRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 142430) -EVM2EVMOffRamp_updateRateLimitTokens:test_updateRateLimitTokens_AddsAndRemoves_Success() (gas: 162820) -EVM2EVMOffRamp_updateRateLimitTokens:test_updateRateLimitTokens_NonOwner_Revert() (gas: 16939) -EVM2EVMOffRamp_updateRateLimitTokens:test_updateRateLimitTokens_Success() (gas: 197992) -EVM2EVMOnRamp_constructor:test_Constructor_Success() (gas: 5056686) +EVM2EVMOffRamp_metadataHash:test_MetadataHash_Success() (gas: 8895) +EVM2EVMOffRamp_setDynamicConfig:test_NonOwner_Revert() (gas: 40357) +EVM2EVMOffRamp_setDynamicConfig:test_RouterZeroAddress_Revert() (gas: 38419) +EVM2EVMOffRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 142469) +EVM2EVMOffRamp_updateRateLimitTokens:test_updateRateLimitTokens_AddsAndRemoves_Success() (gas: 162818) +EVM2EVMOffRamp_updateRateLimitTokens:test_updateRateLimitTokens_NonOwner_Revert() (gas: 16936) +EVM2EVMOffRamp_updateRateLimitTokens:test_updateRateLimitTokens_Success() (gas: 197985) +EVM2EVMOnRamp_constructor:test_Constructor_Success() (gas: 5056698) EVM2EVMOnRamp_forwardFromRouter:test_CannotSendZeroTokens_Revert() (gas: 36063) -EVM2EVMOnRamp_forwardFromRouter:test_EnforceOutOfOrder_Revert() (gas: 99028) -EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() (gas: 114931) -EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2_Success() (gas: 114973) -EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterSuccessCustomExtraArgs() (gas: 130997) -EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterSuccessLegacyExtraArgs() (gas: 139437) -EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouter_Success() (gas: 130616) +EVM2EVMOnRamp_forwardFromRouter:test_EnforceOutOfOrder_Revert() (gas: 99010) +EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() (gas: 114925) +EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2_Success() (gas: 114967) +EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterSuccessCustomExtraArgs() (gas: 130991) +EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouterSuccessLegacyExtraArgs() (gas: 139431) +EVM2EVMOnRamp_forwardFromRouter:test_ForwardFromRouter_Success() (gas: 130607) EVM2EVMOnRamp_forwardFromRouter:test_InvalidAddressEncodePacked_Revert() (gas: 38647) EVM2EVMOnRamp_forwardFromRouter:test_InvalidAddress_Revert() (gas: 38830) EVM2EVMOnRamp_forwardFromRouter:test_InvalidChainSelector_Revert() (gas: 25726) @@ -241,7 +241,7 @@ EVM2EVMOnRamp_forwardFromRouter:test_TooManyTokens_Revert() (gas: 30472) EVM2EVMOnRamp_forwardFromRouter:test_Unhealthy_Revert() (gas: 43480) EVM2EVMOnRamp_forwardFromRouter:test_UnsupportedToken_Revert() (gas: 110111) EVM2EVMOnRamp_forwardFromRouter:test_ZeroAddressReceiver_Revert() (gas: 316020) -EVM2EVMOnRamp_forwardFromRouter:test_forwardFromRouter_ShouldStoreLinkFees_Success() (gas: 113042) +EVM2EVMOnRamp_forwardFromRouter:test_forwardFromRouter_ShouldStoreLinkFees_Success() (gas: 113033) EVM2EVMOnRamp_forwardFromRouter:test_forwardFromRouter_UnsupportedToken_Revert() (gas: 72824) EVM2EVMOnRamp_forwardFromRouter:test_forwardFromRouter_correctSourceTokenData_Success() (gas: 714726) EVM2EVMOnRamp_forwardFromRouter_upgrade:test_V2NonceNewSenderStartsAtZero_Success() (gas: 148808) @@ -250,14 +250,14 @@ EVM2EVMOnRamp_forwardFromRouter_upgrade:test_V2SenderNoncesReadsPreviousRamp_Suc EVM2EVMOnRamp_forwardFromRouter_upgrade:test_V2_Success() (gas: 96028) EVM2EVMOnRamp_getDataAvailabilityCost:test_EmptyMessageCalculatesDataAvailabilityCost_Success() (gas: 20598) EVM2EVMOnRamp_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCost_Success() (gas: 20966) -EVM2EVMOnRamp_getFee:test_EmptyMessage_Success() (gas: 74897) +EVM2EVMOnRamp_getFee:test_EmptyMessage_Success() (gas: 74894) EVM2EVMOnRamp_getFee:test_GetFeeOfZeroForTokenMessage_Success() (gas: 80393) -EVM2EVMOnRamp_getFee:test_HighGasMessage_Success() (gas: 230745) +EVM2EVMOnRamp_getFee:test_HighGasMessage_Success() (gas: 230742) EVM2EVMOnRamp_getFee:test_MessageGasLimitTooHigh_Revert() (gas: 16943) EVM2EVMOnRamp_getFee:test_MessageTooLarge_Revert() (gas: 95505) -EVM2EVMOnRamp_getFee:test_MessageWithDataAndTokenTransfer_Success() (gas: 154013) +EVM2EVMOnRamp_getFee:test_MessageWithDataAndTokenTransfer_Success() (gas: 154010) EVM2EVMOnRamp_getFee:test_NotAFeeToken_Revert() (gas: 24323) -EVM2EVMOnRamp_getFee:test_SingleTokenMessage_Success() (gas: 114743) +EVM2EVMOnRamp_getFee:test_SingleTokenMessage_Success() (gas: 114740) EVM2EVMOnRamp_getFee:test_TooManyTokens_Revert() (gas: 20142) EVM2EVMOnRamp_getFee:test_ZeroDataAvailabilityMultiplier_Success() (gas: 63070) EVM2EVMOnRamp_getSupportedTokens:test_GetSupportedTokens_Revert() (gas: 10532) @@ -280,7 +280,7 @@ EVM2EVMOnRamp_payNops:test_NoFeesToPay_Revert() (gas: 127718) EVM2EVMOnRamp_payNops:test_NoNopsToPay_Revert() (gas: 133580) EVM2EVMOnRamp_payNops:test_NopPayNops_Success() (gas: 146947) EVM2EVMOnRamp_payNops:test_OwnerPayNops_Success() (gas: 141522) -EVM2EVMOnRamp_payNops:test_PayNopsSuccessAfterSetNops() (gas: 298728) +EVM2EVMOnRamp_payNops:test_PayNopsSuccessAfterSetNops() (gas: 298719) EVM2EVMOnRamp_payNops:test_WrongPermissions_Revert() (gas: 15378) EVM2EVMOnRamp_setDynamicConfig:test_SetConfigInvalidConfig_Revert() (gas: 42524) EVM2EVMOnRamp_setDynamicConfig:test_SetConfigOnlyOwner_Revert() (gas: 21426) @@ -352,10 +352,10 @@ FeeQuoter_convertTokenAmount:test_LinkTokenNotSupported_Revert() (gas: 29076) FeeQuoter_getDataAvailabilityCost:test_EmptyMessageCalculatesDataAvailabilityCost_Success() (gas: 94781) FeeQuoter_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCostUnsupportedDestChainSelector_Success() (gas: 14670) FeeQuoter_getDataAvailabilityCost:test_SimpleMessageCalculatesDataAvailabilityCost_Success() (gas: 20550) -FeeQuoter_getTokenAndGasPrices:test_GetFeeTokenAndGasPrices_Success() (gas: 68313) +FeeQuoter_getTokenAndGasPrices:test_GetFeeTokenAndGasPrices_Success() (gas: 68298) FeeQuoter_getTokenAndGasPrices:test_StaleGasPrice_Revert() (gas: 16892) FeeQuoter_getTokenAndGasPrices:test_UnsupportedChain_Revert() (gas: 16188) -FeeQuoter_getTokenAndGasPrices:test_ZeroGasPrice_Success() (gas: 43682) +FeeQuoter_getTokenAndGasPrices:test_ZeroGasPrice_Success() (gas: 43667) FeeQuoter_getTokenPrice:test_GetTokenPriceFromFeed_Success() (gas: 66273) FeeQuoter_getTokenPrices:test_GetTokenPrices_Success() (gas: 78322) FeeQuoter_getTokenTransferCost:test_CustomTokenBpsFee_Success() (gas: 39244) @@ -368,15 +368,15 @@ FeeQuoter_getTokenTransferCost:test_ZeroAmountTokenTransferChargesMinFeeAndGas_S FeeQuoter_getTokenTransferCost:test_ZeroFeeConfigChargesMinFee_Success() (gas: 40376) FeeQuoter_getTokenTransferCost:test_getTokenTransferCost_selfServeUsesDefaults_Success() (gas: 29503) FeeQuoter_getValidatedFee:test_DestinationChainNotEnabled_Revert() (gas: 18315) -FeeQuoter_getValidatedFee:test_EmptyMessage_Success() (gas: 82347) +FeeQuoter_getValidatedFee:test_EmptyMessage_Success() (gas: 82344) FeeQuoter_getValidatedFee:test_EnforceOutOfOrder_Revert() (gas: 52638) -FeeQuoter_getValidatedFee:test_HighGasMessage_Success() (gas: 238765) +FeeQuoter_getValidatedFee:test_HighGasMessage_Success() (gas: 238762) FeeQuoter_getValidatedFee:test_InvalidEVMAddress_Revert() (gas: 22555) FeeQuoter_getValidatedFee:test_MessageGasLimitTooHigh_Revert() (gas: 29847) FeeQuoter_getValidatedFee:test_MessageTooLarge_Revert() (gas: 100292) -FeeQuoter_getValidatedFee:test_MessageWithDataAndTokenTransfer_Success() (gas: 141895) +FeeQuoter_getValidatedFee:test_MessageWithDataAndTokenTransfer_Success() (gas: 141892) FeeQuoter_getValidatedFee:test_NotAFeeToken_Revert() (gas: 21172) -FeeQuoter_getValidatedFee:test_SingleTokenMessage_Success() (gas: 113312) +FeeQuoter_getValidatedFee:test_SingleTokenMessage_Success() (gas: 113309) FeeQuoter_getValidatedFee:test_TooManyTokens_Revert() (gas: 22691) FeeQuoter_getValidatedFee:test_ZeroDataAvailabilityMultiplier_Success() (gas: 62714) FeeQuoter_getValidatedTokenPrice:test_GetValidatedTokenPriceFromFeedErc20Above18Decimals_Success() (gas: 1973907) @@ -431,56 +431,56 @@ FeeQuoter_validateDestFamilyAddress:test_InvalidEVMAddressPrecompiles_Revert() ( FeeQuoter_validateDestFamilyAddress:test_InvalidEVMAddress_Revert() (gas: 10839) FeeQuoter_validateDestFamilyAddress:test_ValidEVMAddress_Success() (gas: 6731) FeeQuoter_validateDestFamilyAddress:test_ValidNonEVMAddress_Success() (gas: 6511) -HybridUSDCTokenPoolMigrationTests:test_LockOrBurn_LockReleaseMechanism_then_switchToPrimary_Success() (gas: 209257) -HybridUSDCTokenPoolMigrationTests:test_LockOrBurn_PrimaryMechanism_Success() (gas: 135884) -HybridUSDCTokenPoolMigrationTests:test_LockOrBurn_WhileMigrationPause_Revert() (gas: 107099) -HybridUSDCTokenPoolMigrationTests:test_LockOrBurn_onLockReleaseMechanism_Success() (gas: 144595) -HybridUSDCTokenPoolMigrationTests:test_MintOrRelease_OnLockReleaseMechanism_Success() (gas: 214814) -HybridUSDCTokenPoolMigrationTests:test_MintOrRelease_OnLockReleaseMechanism_then_switchToPrimary_Success() (gas: 423659) -HybridUSDCTokenPoolMigrationTests:test_MintOrRelease_incomingMessageWithPrimaryMechanism() (gas: 268944) -HybridUSDCTokenPoolMigrationTests:test_ReleaseOrMint_WhileMigrationPause_Revert() (gas: 111487) +HybridUSDCTokenPoolMigrationTests:test_LockOrBurn_LockReleaseMechanism_then_switchToPrimary_Success() (gas: 209248) +HybridUSDCTokenPoolMigrationTests:test_LockOrBurn_PrimaryMechanism_Success() (gas: 135879) +HybridUSDCTokenPoolMigrationTests:test_LockOrBurn_WhileMigrationPause_Revert() (gas: 107090) +HybridUSDCTokenPoolMigrationTests:test_LockOrBurn_onLockReleaseMechanism_Success() (gas: 144586) +HybridUSDCTokenPoolMigrationTests:test_MintOrRelease_OnLockReleaseMechanism_Success() (gas: 214817) +HybridUSDCTokenPoolMigrationTests:test_MintOrRelease_OnLockReleaseMechanism_then_switchToPrimary_Success() (gas: 423641) +HybridUSDCTokenPoolMigrationTests:test_MintOrRelease_incomingMessageWithPrimaryMechanism() (gas: 268928) +HybridUSDCTokenPoolMigrationTests:test_ReleaseOrMint_WhileMigrationPause_Revert() (gas: 111484) HybridUSDCTokenPoolMigrationTests:test_burnLockedUSDC_invalidPermissions_Revert() (gas: 39362) HybridUSDCTokenPoolMigrationTests:test_cancelExistingCCTPMigrationProposal() (gas: 33189) HybridUSDCTokenPoolMigrationTests:test_cannotCancelANonExistentMigrationProposal() (gas: 12669) HybridUSDCTokenPoolMigrationTests:test_cannotModifyLiquidityWithoutPermissions_Revert() (gas: 13329) HybridUSDCTokenPoolMigrationTests:test_cannotTransferLiquidityDuringPendingMigration_Revert() (gas: 160900) -HybridUSDCTokenPoolMigrationTests:test_lockOrBurn_then_BurnInCCTPMigration_Success() (gas: 255996) +HybridUSDCTokenPoolMigrationTests:test_lockOrBurn_then_BurnInCCTPMigration_Success() (gas: 255982) HybridUSDCTokenPoolMigrationTests:test_transferLiquidity_Success() (gas: 165921) HybridUSDCTokenPoolMigrationTests:test_unstickManualTxAfterMigration_destChain_Success() (gas: 154242) -HybridUSDCTokenPoolMigrationTests:test_unstickManualTxAfterMigration_homeChain_Success() (gas: 463757) -HybridUSDCTokenPoolTests:test_LockOrBurn_LockReleaseMechanism_then_switchToPrimary_Success() (gas: 209240) -HybridUSDCTokenPoolTests:test_LockOrBurn_PrimaryMechanism_Success() (gas: 135884) -HybridUSDCTokenPoolTests:test_LockOrBurn_WhileMigrationPause_Revert() (gas: 107144) -HybridUSDCTokenPoolTests:test_LockOrBurn_onLockReleaseMechanism_Success() (gas: 144616) -HybridUSDCTokenPoolTests:test_MintOrRelease_OnLockReleaseMechanism_Success() (gas: 214792) -HybridUSDCTokenPoolTests:test_MintOrRelease_OnLockReleaseMechanism_then_switchToPrimary_Success() (gas: 423637) -HybridUSDCTokenPoolTests:test_MintOrRelease_incomingMessageWithPrimaryMechanism() (gas: 268927) -HybridUSDCTokenPoolTests:test_ReleaseOrMint_WhileMigrationPause_Revert() (gas: 111531) +HybridUSDCTokenPoolMigrationTests:test_unstickManualTxAfterMigration_homeChain_Success() (gas: 463740) +HybridUSDCTokenPoolTests:test_LockOrBurn_LockReleaseMechanism_then_switchToPrimary_Success() (gas: 209230) +HybridUSDCTokenPoolTests:test_LockOrBurn_PrimaryMechanism_Success() (gas: 135880) +HybridUSDCTokenPoolTests:test_LockOrBurn_WhileMigrationPause_Revert() (gas: 107135) +HybridUSDCTokenPoolTests:test_LockOrBurn_onLockReleaseMechanism_Success() (gas: 144607) +HybridUSDCTokenPoolTests:test_MintOrRelease_OnLockReleaseMechanism_Success() (gas: 214795) +HybridUSDCTokenPoolTests:test_MintOrRelease_OnLockReleaseMechanism_then_switchToPrimary_Success() (gas: 423619) +HybridUSDCTokenPoolTests:test_MintOrRelease_incomingMessageWithPrimaryMechanism() (gas: 268910) +HybridUSDCTokenPoolTests:test_ReleaseOrMint_WhileMigrationPause_Revert() (gas: 111528) HybridUSDCTokenPoolTests:test_cannotTransferLiquidityDuringPendingMigration_Revert() (gas: 160845) HybridUSDCTokenPoolTests:test_transferLiquidity_Success() (gas: 165904) LockReleaseTokenPoolAndProxy_setRebalancer:test_SetRebalancer_Revert() (gas: 10989) LockReleaseTokenPoolAndProxy_setRebalancer:test_SetRebalancer_Success() (gas: 18028) -LockReleaseTokenPoolPoolAndProxy_canAcceptLiquidity:test_CanAcceptLiquidity_Success() (gas: 3051555) -LockReleaseTokenPoolPoolAndProxy_provideLiquidity:test_LiquidityNotAccepted_Revert() (gas: 3047994) +LockReleaseTokenPoolPoolAndProxy_canAcceptLiquidity:test_CanAcceptLiquidity_Success() (gas: 3051552) +LockReleaseTokenPoolPoolAndProxy_provideLiquidity:test_LiquidityNotAccepted_Revert() (gas: 3047988) LockReleaseTokenPoolPoolAndProxy_provideLiquidity:test_Unauthorized_Revert() (gas: 11489) -LockReleaseTokenPoolPoolAndProxy_supportsInterface:test_SupportsInterface_Success() (gas: 10184) -LockReleaseTokenPoolPoolAndProxy_withdrawalLiquidity:test_InsufficientLiquidity_Revert() (gas: 60189) +LockReleaseTokenPoolPoolAndProxy_supportsInterface:test_SupportsInterface_Success() (gas: 10196) +LockReleaseTokenPoolPoolAndProxy_withdrawalLiquidity:test_InsufficientLiquidity_Revert() (gas: 60187) LockReleaseTokenPoolPoolAndProxy_withdrawalLiquidity:test_Unauthorized_Revert() (gas: 11464) -LockReleaseTokenPool_canAcceptLiquidity:test_CanAcceptLiquidity_Success() (gas: 2836141) +LockReleaseTokenPool_canAcceptLiquidity:test_CanAcceptLiquidity_Success() (gas: 2836138) LockReleaseTokenPool_lockOrBurn:test_LockOrBurnWithAllowList_Revert() (gas: 30062) LockReleaseTokenPool_lockOrBurn:test_LockOrBurnWithAllowList_Success() (gas: 79943) LockReleaseTokenPool_lockOrBurn:test_PoolBurnRevertNotHealthy_Revert() (gas: 59620) -LockReleaseTokenPool_provideLiquidity:test_LiquidityNotAccepted_Revert() (gas: 2832624) +LockReleaseTokenPool_provideLiquidity:test_LiquidityNotAccepted_Revert() (gas: 2832618) LockReleaseTokenPool_provideLiquidity:test_Unauthorized_Revert() (gas: 11489) LockReleaseTokenPool_releaseOrMint:test_ChainNotAllowed_Revert() (gas: 72743) LockReleaseTokenPool_releaseOrMint:test_PoolMintNotHealthy_Revert() (gas: 56352) LockReleaseTokenPool_releaseOrMint:test_ReleaseOrMint_Success() (gas: 225548) LockReleaseTokenPool_setRebalancer:test_SetRebalancer_Revert() (gas: 11011) LockReleaseTokenPool_setRebalancer:test_SetRebalancer_Success() (gas: 18094) -LockReleaseTokenPool_supportsInterface:test_SupportsInterface_Success() (gas: 10184) -LockReleaseTokenPool_transferLiquidity:test_transferLiquidity_Success() (gas: 83234) -LockReleaseTokenPool_transferLiquidity:test_transferLiquidity_transferTooMuch_Revert() (gas: 55947) -LockReleaseTokenPool_withdrawalLiquidity:test_InsufficientLiquidity_Revert() (gas: 60189) +LockReleaseTokenPool_supportsInterface:test_SupportsInterface_Success() (gas: 10196) +LockReleaseTokenPool_transferLiquidity:test_transferLiquidity_Success() (gas: 83231) +LockReleaseTokenPool_transferLiquidity:test_transferLiquidity_transferTooMuch_Revert() (gas: 55953) +LockReleaseTokenPool_withdrawalLiquidity:test_InsufficientLiquidity_Revert() (gas: 60187) LockReleaseTokenPool_withdrawalLiquidity:test_Unauthorized_Revert() (gas: 11464) LockRelease_setRateLimitAdmin:test_SetRateLimitAdmin_Revert() (gas: 11054) LockRelease_setRateLimitAdmin:test_SetRateLimitAdmin_Success() (gas: 35060) @@ -491,7 +491,7 @@ MerkleMultiProofTest:test_MerkleRootSingleLeaf_Success() (gas: 3661) MerkleMultiProofTest:test_SpecSync_gas() (gas: 34129) MockRouterTest:test_ccipSendWithInsufficientNativeTokens_Revert() (gas: 34037) MockRouterTest:test_ccipSendWithInvalidMsgValue_Revert() (gas: 60842) -MockRouterTest:test_ccipSendWithLinkFeeTokenAndValidMsgValue_Success() (gas: 126588) +MockRouterTest:test_ccipSendWithLinkFeeTokenAndValidMsgValue_Success() (gas: 126576) MockRouterTest:test_ccipSendWithLinkFeeTokenbutInsufficientAllowance_Revert() (gas: 63455) MockRouterTest:test_ccipSendWithSufficientNativeFeeTokens_Success() (gas: 44012) MultiAggregateRateLimiter_applyRateLimiterConfigUpdates:test_MultipleConfigsBothLanes_Success() (gas: 133528) @@ -539,7 +539,7 @@ MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokens_AddsA MultiAggregateRateLimiter_updateRateLimitTokens:test_UpdateRateLimitTokens_RemoveNonExistentToken_Success() (gas: 28826) MultiAggregateRateLimiter_updateRateLimitTokens:test_ZeroDestToken_Revert() (gas: 18324) MultiAggregateRateLimiter_updateRateLimitTokens:test_ZeroSourceToken_Revert() (gas: 18253) -MultiOCR3Base_setOCR3Configs:test_FMustBePositive_Revert() (gas: 59294) +MultiOCR3Base_setOCR3Configs:test_FMustBePositive_Revert() (gas: 59397) MultiOCR3Base_setOCR3Configs:test_FTooHigh_Revert() (gas: 44190) MultiOCR3Base_setOCR3Configs:test_MoreTransmittersThanSigners_Revert() (gas: 104822) MultiOCR3Base_setOCR3Configs:test_NoTransmitters_Revert() (gas: 18886) @@ -550,7 +550,7 @@ MultiOCR3Base_setOCR3Configs:test_SetConfigWithSignersMismatchingTransmitters_Su MultiOCR3Base_setOCR3Configs:test_SetConfigWithSigners_Success() (gas: 828900) MultiOCR3Base_setOCR3Configs:test_SetConfigWithoutSigners_Success() (gas: 457292) MultiOCR3Base_setOCR3Configs:test_SetConfigsZeroInput_Success() (gas: 12481) -MultiOCR3Base_setOCR3Configs:test_SetMultipleConfigs_Success() (gas: 2141622) +MultiOCR3Base_setOCR3Configs:test_SetMultipleConfigs_Success() (gas: 2141722) MultiOCR3Base_setOCR3Configs:test_SignerCannotBeZeroAddress_Revert() (gas: 141835) MultiOCR3Base_setOCR3Configs:test_StaticConfigChange_Revert() (gas: 807623) MultiOCR3Base_setOCR3Configs:test_TooManySigners_Revert() (gas: 158867) @@ -572,12 +572,12 @@ MultiOCR3Base_transmit:test_UnAuthorizedTransmitter_Revert() (gas: 24234) MultiOCR3Base_transmit:test_UnauthorizedSigner_Revert() (gas: 61275) MultiOCR3Base_transmit:test_UnconfiguredPlugin_Revert() (gas: 39933) MultiOCR3Base_transmit:test_ZeroSignatures_Revert() (gas: 33049) -MultiOnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 233781) -MultiRampsE2E:test_E2E_3MessagesMMultiOffRampSuccess_gas() (gas: 1504341) +MultiOnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 233778) +MultiRampsE2E:test_E2E_3MessagesMMultiOffRampSuccess_gas() (gas: 1504663) NonceManager_NonceIncrementation:test_getIncrementedOutboundNonce_Success() (gas: 37934) -NonceManager_NonceIncrementation:test_incrementInboundNonce_Skip() (gas: 23721) -NonceManager_NonceIncrementation:test_incrementInboundNonce_Success() (gas: 38805) -NonceManager_NonceIncrementation:test_incrementNoncesInboundAndOutbound_Success() (gas: 71934) +NonceManager_NonceIncrementation:test_incrementInboundNonce_Skip() (gas: 23706) +NonceManager_NonceIncrementation:test_incrementInboundNonce_Success() (gas: 38778) +NonceManager_NonceIncrementation:test_incrementNoncesInboundAndOutbound_Success() (gas: 71901) NonceManager_OffRampUpgrade:test_NoPrevOffRampForChain_Success() (gas: 262159) NonceManager_OffRampUpgrade:test_UpgradedNonceNewSenderStartsAtZero_Success() (gas: 265836) NonceManager_OffRampUpgrade:test_UpgradedNonceStartsAtV1Nonce_Success() (gas: 329824) @@ -585,16 +585,16 @@ NonceManager_OffRampUpgrade:test_UpgradedOffRampNonceSkipsIfMsgInFlight_Success( NonceManager_OffRampUpgrade:test_UpgradedSenderNoncesReadsPreviousRampTransitive_Success() (gas: 249120) NonceManager_OffRampUpgrade:test_UpgradedSenderNoncesReadsPreviousRamp_Success() (gas: 237027) NonceManager_OffRampUpgrade:test_Upgraded_Success() (gas: 153748) -NonceManager_OnRampUpgrade:test_UpgradeNonceNewSenderStartsAtZero_Success() (gas: 168962) -NonceManager_OnRampUpgrade:test_UpgradeNonceStartsAtV1Nonce_Success() (gas: 221139) -NonceManager_OnRampUpgrade:test_UpgradeSenderNoncesReadsPreviousRamp_Success() (gas: 126858) +NonceManager_OnRampUpgrade:test_UpgradeNonceNewSenderStartsAtZero_Success() (gas: 168959) +NonceManager_OnRampUpgrade:test_UpgradeNonceStartsAtV1Nonce_Success() (gas: 221148) +NonceManager_OnRampUpgrade:test_UpgradeSenderNoncesReadsPreviousRamp_Success() (gas: 126861) NonceManager_OnRampUpgrade:test_Upgrade_Success() (gas: 107723) -NonceManager_applyPreviousRampsUpdates:test_MultipleRampsUpdates() (gas: 123201) -NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySetOffRamp_Revert() (gas: 43073) -NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySetOnRampAndOffRamp_Revert() (gas: 64402) -NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySetOnRamp_Revert() (gas: 42937) -NonceManager_applyPreviousRampsUpdates:test_SingleRampUpdate() (gas: 66690) -NonceManager_applyPreviousRampsUpdates:test_ZeroInput() (gas: 12067) +NonceManager_applyPreviousRampsUpdates:test_MultipleRampsUpdates() (gas: 123207) +NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySetOffRamp_Revert() (gas: 43079) +NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySetOnRampAndOffRamp_Revert() (gas: 64408) +NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySetOnRamp_Revert() (gas: 42943) +NonceManager_applyPreviousRampsUpdates:test_SingleRampUpdate() (gas: 66696) +NonceManager_applyPreviousRampsUpdates:test_ZeroInput() (gas: 12070) NonceManager_typeAndVersion:test_typeAndVersion() (gas: 9705) OCR2BaseNoChecks_setOCR2Config:test_FMustBePositive_Revert() (gas: 12210) OCR2BaseNoChecks_setOCR2Config:test_RepeatAddress_Revert() (gas: 42431) @@ -621,11 +621,11 @@ OCR2Base_transmit:test_Transmit2SignersSuccess_gas() (gas: 51689) OCR2Base_transmit:test_UnAuthorizedTransmitter_Revert() (gas: 23511) OCR2Base_transmit:test_UnauthorizedSigner_Revert() (gas: 39707) OCR2Base_transmit:test_WrongNumberOfSignatures_Revert() (gas: 20584) -OffRamp_afterOC3ConfigSet:test_afterOCR3ConfigSet_SignatureVerificationDisabled_Revert() (gas: 5647759) +OffRamp_afterOC3ConfigSet:test_afterOCR3ConfigSet_SignatureVerificationDisabled_Revert() (gas: 5656596) OffRamp_applySourceChainConfigUpdates:test_AddMultipleChains_Success() (gas: 469391) OffRamp_applySourceChainConfigUpdates:test_AddNewChain_Success() (gas: 99637) OffRamp_applySourceChainConfigUpdates:test_ApplyZeroUpdates_Success() (gas: 12591) -OffRamp_applySourceChainConfigUpdates:test_InvalidOnRampUpdate_Revert() (gas: 205004) +OffRamp_applySourceChainConfigUpdates:test_InvalidOnRampUpdate_Revert() (gas: 205322) OffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChainOnRamp_Success() (gas: 101437) OffRamp_applySourceChainConfigUpdates:test_ReplaceExistingChain_Success() (gas: 111307) OffRamp_applySourceChainConfigUpdates:test_RouterAddress_Revert() (gas: 13441) @@ -640,62 +640,62 @@ OffRamp_batchExecute:test_SingleReport_Success() (gas: 157132) OffRamp_batchExecute:test_Unhealthy_Success() (gas: 554208) OffRamp_batchExecute:test_ZeroReports_Revert() (gas: 10600) OffRamp_ccipReceive:test_Reverts() (gas: 15385) -OffRamp_commit:test_CommitOnRampMismatch_Revert() (gas: 92593) -OffRamp_commit:test_FailedRMNVerification_Reverts() (gas: 63787) -OffRamp_commit:test_InvalidIntervalMinLargerThanMax_Revert() (gas: 67826) -OffRamp_commit:test_InvalidInterval_Revert() (gas: 63993) -OffRamp_commit:test_InvalidRootRevert() (gas: 63066) -OffRamp_commit:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6251632) -OffRamp_commit:test_NoConfig_Revert() (gas: 5835304) -OffRamp_commit:test_OnlyGasPriceUpdates_Success() (gas: 112835) -OffRamp_commit:test_OnlyPriceUpdateStaleReport_Revert() (gas: 121022) -OffRamp_commit:test_OnlyTokenPriceUpdates_Success() (gas: 112856) -OffRamp_commit:test_PriceSequenceNumberCleared_Success() (gas: 354804) -OffRamp_commit:test_ReportAndPriceUpdate_Success() (gas: 164033) -OffRamp_commit:test_ReportOnlyRootSuccess_gas() (gas: 139074) -OffRamp_commit:test_RootAlreadyCommitted_Revert() (gas: 145995) -OffRamp_commit:test_SourceChainNotEnabled_Revert() (gas: 59555) -OffRamp_commit:test_StaleReportWithRoot_Success() (gas: 231514) -OffRamp_commit:test_UnauthorizedTransmitter_Revert() (gas: 125104) -OffRamp_commit:test_Unhealthy_Revert() (gas: 58334) -OffRamp_commit:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 206251) -OffRamp_commit:test_ZeroEpochAndRound_Revert() (gas: 51522) -OffRamp_constructor:test_Constructor_Success() (gas: 5836579) -OffRamp_constructor:test_SourceChainSelector_Revert() (gas: 135495) -OffRamp_constructor:test_ZeroChainSelector_Revert() (gas: 102930) -OffRamp_constructor:test_ZeroNonceManager_Revert() (gas: 100824) -OffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 161021) -OffRamp_constructor:test_ZeroRMNRemote_Revert() (gas: 100744) -OffRamp_constructor:test_ZeroTokenAdminRegistry_Revert() (gas: 100782) +OffRamp_commit:test_CommitOnRampMismatch_Revert() (gas: 92905) +OffRamp_commit:test_FailedRMNVerification_Reverts() (gas: 64099) +OffRamp_commit:test_InvalidIntervalMinLargerThanMax_Revert() (gas: 68124) +OffRamp_commit:test_InvalidInterval_Revert() (gas: 64291) +OffRamp_commit:test_InvalidRootRevert() (gas: 63356) +OffRamp_commit:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6260756) +OffRamp_commit:test_NoConfig_Revert() (gas: 5844428) +OffRamp_commit:test_OnlyGasPriceUpdates_Success() (gas: 113042) +OffRamp_commit:test_OnlyPriceUpdateStaleReport_Revert() (gas: 121403) +OffRamp_commit:test_OnlyTokenPriceUpdates_Success() (gas: 113063) +OffRamp_commit:test_PriceSequenceNumberCleared_Success() (gas: 355198) +OffRamp_commit:test_ReportAndPriceUpdate_Success() (gas: 164351) +OffRamp_commit:test_ReportOnlyRootSuccess_gas() (gas: 139364) +OffRamp_commit:test_RootAlreadyCommitted_Revert() (gas: 146555) +OffRamp_commit:test_SourceChainNotEnabled_Revert() (gas: 59858) +OffRamp_commit:test_StaleReportWithRoot_Success() (gas: 232074) +OffRamp_commit:test_UnauthorizedTransmitter_Revert() (gas: 125409) +OffRamp_commit:test_Unhealthy_Revert() (gas: 58633) +OffRamp_commit:test_ValidPriceUpdateThenStaleReportWithRoot_Success() (gas: 206729) +OffRamp_commit:test_ZeroEpochAndRound_Revert() (gas: 51722) +OffRamp_constructor:test_Constructor_Success() (gas: 5845416) +OffRamp_constructor:test_SourceChainSelector_Revert() (gas: 135514) +OffRamp_constructor:test_ZeroChainSelector_Revert() (gas: 102949) +OffRamp_constructor:test_ZeroNonceManager_Revert() (gas: 100843) +OffRamp_constructor:test_ZeroOnRampAddress_Revert() (gas: 161040) +OffRamp_constructor:test_ZeroRMNRemote_Revert() (gas: 100763) +OffRamp_constructor:test_ZeroTokenAdminRegistry_Revert() (gas: 100801) OffRamp_execute:test_IncorrectArrayType_Revert() (gas: 17639) OffRamp_execute:test_LargeBatch_Success() (gas: 3426635) -OffRamp_execute:test_MultipleReportsWithPartialValidationFailures_Success() (gas: 373122) +OffRamp_execute:test_MultipleReportsWithPartialValidationFailures_Success() (gas: 373095) OffRamp_execute:test_MultipleReports_Success() (gas: 301009) -OffRamp_execute:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6660824) -OffRamp_execute:test_NoConfig_Revert() (gas: 5885299) +OffRamp_execute:test_NoConfigWithOtherConfigPresent_Revert() (gas: 6669661) +OffRamp_execute:test_NoConfig_Revert() (gas: 5894136) OffRamp_execute:test_NonArray_Revert() (gas: 27562) OffRamp_execute:test_SingleReport_Success() (gas: 176364) OffRamp_execute:test_UnauthorizedTransmitter_Revert() (gas: 148382) -OffRamp_execute:test_WrongConfigWithSigners_Revert() (gas: 6663573) +OffRamp_execute:test_WrongConfigWithSigners_Revert() (gas: 6672410) OffRamp_execute:test_ZeroReports_Revert() (gas: 17361) OffRamp_executeSingleMessage:test_MessageSender_Revert() (gas: 18511) OffRamp_executeSingleMessage:test_NonContractWithTokens_Success() (gas: 244057) OffRamp_executeSingleMessage:test_NonContract_Success() (gas: 20759) -OffRamp_executeSingleMessage:test_TokenHandlingError_Revert() (gas: 205097) +OffRamp_executeSingleMessage:test_TokenHandlingError_Revert() (gas: 205094) OffRamp_executeSingleMessage:test_ZeroGasDONExecution_Revert() (gas: 49316) OffRamp_executeSingleMessage:test_executeSingleMessage_NoTokens_Success() (gas: 48760) -OffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidationNoRouterCall_Revert() (gas: 218108) -OffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidation_Revert() (gas: 85376) +OffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidationNoRouterCall_Revert() (gas: 218081) +OffRamp_executeSingleMessage:test_executeSingleMessage_WithFailingValidation_Revert() (gas: 85349) OffRamp_executeSingleMessage:test_executeSingleMessage_WithTokens_Success() (gas: 274194) -OffRamp_executeSingleMessage:test_executeSingleMessage_WithVInterception_Success() (gas: 91836) +OffRamp_executeSingleMessage:test_executeSingleMessage_WithVInterception_Success() (gas: 91809) OffRamp_executeSingleReport:test_DisabledSourceChain_Revert() (gas: 28260) OffRamp_executeSingleReport:test_EmptyReport_Revert() (gas: 22062) OffRamp_executeSingleReport:test_InvalidSourcePoolAddress_Success() (gas: 481748) OffRamp_executeSingleReport:test_ManualExecutionNotYetEnabled_Revert() (gas: 48372) OffRamp_executeSingleReport:test_MismatchingDestChainSelector_Revert() (gas: 33959) OffRamp_executeSingleReport:test_NonExistingSourceChain_Revert() (gas: 28436) -OffRamp_executeSingleReport:test_ReceiverError_Success() (gas: 188081) -OffRamp_executeSingleReport:test_RetryFailedMessageWithoutManualExecution_Revert() (gas: 198515) +OffRamp_executeSingleReport:test_ReceiverError_Success() (gas: 188084) +OffRamp_executeSingleReport:test_RetryFailedMessageWithoutManualExecution_Revert() (gas: 198518) OffRamp_executeSingleReport:test_RootNotCommitted_Revert() (gas: 40741) OffRamp_executeSingleReport:test_RouterYULCall_Revert() (gas: 413233) OffRamp_executeSingleReport:test_SingleMessageNoTokensOtherChain_Success() (gas: 249776) @@ -719,8 +719,8 @@ OffRamp_getExecutionState:test_GetDifferentChainExecutionState_Success() (gas: 1 OffRamp_getExecutionState:test_GetExecutionState_Success() (gas: 89178) OffRamp_manuallyExecute:test_ManualExecGasLimitMismatchSingleReport_Revert() (gas: 81284) OffRamp_manuallyExecute:test_manuallyExecute_DestinationGasAmountCountMismatch_Revert() (gas: 74161) -OffRamp_manuallyExecute:test_manuallyExecute_DoesNotRevertIfUntouched_Success() (gas: 173241) -OffRamp_manuallyExecute:test_manuallyExecute_FailedTx_Revert() (gas: 214186) +OffRamp_manuallyExecute:test_manuallyExecute_DoesNotRevertIfUntouched_Success() (gas: 173244) +OffRamp_manuallyExecute:test_manuallyExecute_FailedTx_Revert() (gas: 214189) OffRamp_manuallyExecute:test_manuallyExecute_ForkedChain_Revert() (gas: 27152) OffRamp_manuallyExecute:test_manuallyExecute_GasLimitMismatchMultipleReports_Revert() (gas: 165098) OffRamp_manuallyExecute:test_manuallyExecute_InvalidReceiverExecutionGasLimit_Revert() (gas: 27689) @@ -729,10 +729,10 @@ OffRamp_manuallyExecute:test_manuallyExecute_LowGasLimit_Success() (gas: 498614) OffRamp_manuallyExecute:test_manuallyExecute_MultipleReportsWithSingleCursedLane_Revert() (gas: 316158) OffRamp_manuallyExecute:test_manuallyExecute_ReentrancyFails_Success() (gas: 2245360) OffRamp_manuallyExecute:test_manuallyExecute_SourceChainSelectorMismatch_Revert() (gas: 165602) -OffRamp_manuallyExecute:test_manuallyExecute_Success() (gas: 227231) -OffRamp_manuallyExecute:test_manuallyExecute_WithGasOverride_Success() (gas: 227771) -OffRamp_manuallyExecute:test_manuallyExecute_WithMultiReportGasOverride_Success() (gas: 781507) -OffRamp_manuallyExecute:test_manuallyExecute_WithPartialMessages_Success() (gas: 347428) +OffRamp_manuallyExecute:test_manuallyExecute_Success() (gas: 227234) +OffRamp_manuallyExecute:test_manuallyExecute_WithGasOverride_Success() (gas: 227774) +OffRamp_manuallyExecute:test_manuallyExecute_WithMultiReportGasOverride_Success() (gas: 781510) +OffRamp_manuallyExecute:test_manuallyExecute_WithPartialMessages_Success() (gas: 347431) OffRamp_releaseOrMintSingleToken:test__releaseOrMintSingleToken_NotACompatiblePool_Revert() (gas: 37634) OffRamp_releaseOrMintSingleToken:test__releaseOrMintSingleToken_Success() (gas: 104404) OffRamp_releaseOrMintSingleToken:test__releaseOrMintSingleToken_TokenHandlingError_transfer_Revert() (gas: 85342) @@ -747,53 +747,53 @@ OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_PoolDoesNotSupportDest_Reve OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_Success() (gas: 174512) OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_WithGasOverride_Success() (gas: 176424) OffRamp_releaseOrMintTokens:test_releaseOrMintTokens_destDenominatedDecimals_Success() (gas: 187723) -OffRamp_setDynamicConfig:test_FeeQuoterZeroAddress_Revert() (gas: 11296) -OffRamp_setDynamicConfig:test_NonOwner_Revert() (gas: 13911) -OffRamp_setDynamicConfig:test_SetDynamicConfigWithInterceptor_Success() (gas: 46448) -OffRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 24490) -OffRamp_trialExecute:test_RateLimitError_Success() (gas: 219358) -OffRamp_trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 227980) +OffRamp_setDynamicConfig:test_FeeQuoterZeroAddress_Revert() (gas: 11269) +OffRamp_setDynamicConfig:test_NonOwner_Revert() (gas: 13884) +OffRamp_setDynamicConfig:test_SetDynamicConfigWithInterceptor_Success() (gas: 46421) +OffRamp_setDynamicConfig:test_SetDynamicConfig_Success() (gas: 24463) +OffRamp_trialExecute:test_RateLimitError_Success() (gas: 219355) +OffRamp_trialExecute:test_TokenHandlingErrorIsCaught_Success() (gas: 227977) OffRamp_trialExecute:test_TokenPoolIsNotAContract_Success() (gas: 295350) OffRamp_trialExecute:test_trialExecute_Success() (gas: 277894) OnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 390842) OnRamp_applyAllowListUpdates:test_applyAllowListUpdates_InvalidAllowListRequestDisabledAllowListWithAdds() (gas: 18030) -OnRamp_applyAllowListUpdates:test_applyAllowListUpdates_Revert() (gas: 67429) -OnRamp_applyAllowListUpdates:test_applyAllowListUpdates_Success() (gas: 325126) -OnRamp_applyDestChainConfigUpdates:test_ApplyDestChainConfigUpdates_Success() (gas: 65230) +OnRamp_applyAllowListUpdates:test_applyAllowListUpdates_Revert() (gas: 67426) +OnRamp_applyAllowListUpdates:test_applyAllowListUpdates_Success() (gas: 325124) +OnRamp_applyDestChainConfigUpdates:test_ApplyDestChainConfigUpdates_Success() (gas: 65227) OnRamp_applyDestChainConfigUpdates:test_ApplyDestChainConfigUpdates_WithInvalidChainSelector_Revert() (gas: 13446) OnRamp_constructor:test_Constructor_InvalidConfigChainSelectorEqZero_Revert() (gas: 95048) OnRamp_constructor:test_Constructor_InvalidConfigNonceManagerEqAddressZero_Revert() (gas: 92990) OnRamp_constructor:test_Constructor_InvalidConfigRMNProxyEqAddressZero_Revert() (gas: 98023) OnRamp_constructor:test_Constructor_InvalidConfigTokenAdminRegistryEqAddressZero_Revert() (gas: 93046) OnRamp_constructor:test_Constructor_Success() (gas: 2750875) -OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() (gas: 115152) -OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2_Success() (gas: 145975) -OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessCustomExtraArgs() (gas: 145551) -OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessEmptyExtraArgs() (gas: 143790) -OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessLegacyExtraArgs() (gas: 145769) -OnRamp_forwardFromRouter:test_ForwardFromRouter_Success() (gas: 145148) -OnRamp_forwardFromRouter:test_ForwardFromRouter_Success_ConfigurableSourceRouter() (gas: 145980) +OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() (gas: 115146) +OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2_Success() (gas: 145969) +OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessCustomExtraArgs() (gas: 145545) +OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessEmptyExtraArgs() (gas: 143772) +OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessLegacyExtraArgs() (gas: 145763) +OnRamp_forwardFromRouter:test_ForwardFromRouter_Success() (gas: 145139) +OnRamp_forwardFromRouter:test_ForwardFromRouter_Success_ConfigurableSourceRouter() (gas: 145974) OnRamp_forwardFromRouter:test_InvalidExtraArgsTag_Revert() (gas: 38593) -OnRamp_forwardFromRouter:test_MessageInterceptionError_Revert() (gas: 143071) +OnRamp_forwardFromRouter:test_MessageInterceptionError_Revert() (gas: 143056) OnRamp_forwardFromRouter:test_MesssageFeeTooHigh_Revert() (gas: 36706) OnRamp_forwardFromRouter:test_MultiCannotSendZeroTokens_Revert() (gas: 36509) OnRamp_forwardFromRouter:test_OriginalSender_Revert() (gas: 18291) OnRamp_forwardFromRouter:test_Paused_Revert() (gas: 38454) OnRamp_forwardFromRouter:test_Permissions_Revert() (gas: 23663) -OnRamp_forwardFromRouter:test_ShouldIncrementNonceOnlyOnOrdered_Success() (gas: 186184) -OnRamp_forwardFromRouter:test_ShouldIncrementSeqNumAndNonce_Success() (gas: 212569) -OnRamp_forwardFromRouter:test_ShouldStoreLinkFees() (gas: 125136) +OnRamp_forwardFromRouter:test_ShouldIncrementNonceOnlyOnOrdered_Success() (gas: 186202) +OnRamp_forwardFromRouter:test_ShouldIncrementSeqNumAndNonce_Success() (gas: 212587) +OnRamp_forwardFromRouter:test_ShouldStoreLinkFees() (gas: 125127) OnRamp_forwardFromRouter:test_ShouldStoreNonLinkFees() (gas: 141767) OnRamp_forwardFromRouter:test_SourceTokenDataTooLarge_Revert() (gas: 3618195) OnRamp_forwardFromRouter:test_UnAllowedOriginalSender_Revert() (gas: 24010) OnRamp_forwardFromRouter:test_UnsupportedToken_Revert() (gas: 75826) OnRamp_forwardFromRouter:test_forwardFromRouter_UnsupportedToken_Revert() (gas: 38559) -OnRamp_forwardFromRouter:test_forwardFromRouter_WithInterception_Success() (gas: 280065) -OnRamp_getFee:test_EmptyMessage_Success() (gas: 98760) +OnRamp_forwardFromRouter:test_forwardFromRouter_WithInterception_Success() (gas: 280050) +OnRamp_getFee:test_EmptyMessage_Success() (gas: 98757) OnRamp_getFee:test_EnforceOutOfOrder_Revert() (gas: 64779) OnRamp_getFee:test_GetFeeOfZeroForTokenMessage_Success() (gas: 86359) OnRamp_getFee:test_NotAFeeTokenButPricedToken_Revert() (gas: 35185) -OnRamp_getFee:test_SingleTokenMessage_Success() (gas: 113919) +OnRamp_getFee:test_SingleTokenMessage_Success() (gas: 113916) OnRamp_getFee:test_Unhealthy_Revert() (gas: 17171) OnRamp_getSupportedTokens:test_GetSupportedTokens_Revert() (gas: 10510) OnRamp_getTokenPool:test_GetTokenPool_Success() (gas: 35372) @@ -803,13 +803,34 @@ OnRamp_setDynamicConfig:test_setDynamicConfig_InvalidConfigInvalidConfig_Revert( OnRamp_setDynamicConfig:test_setDynamicConfig_InvalidConfigOnlyOwner_Revert() (gas: 16850) OnRamp_setDynamicConfig:test_setDynamicConfig_InvalidConfigReentrancyGuardEnteredEqTrue_Revert() (gas: 13265) OnRamp_setDynamicConfig:test_setDynamicConfig_Success() (gas: 56460) -OnRamp_withdrawFeeTokens:test_WithdrawFeeTokens_Success() (gas: 97290) +OnRamp_withdrawFeeTokens:test_WithdrawFeeTokens_Success() (gas: 97302) PingPong_ccipReceive:test_CcipReceive_Success() (gas: 151349) PingPong_plumbing:test_OutOfOrderExecution_Success() (gas: 20310) PingPong_plumbing:test_Pausing_Success() (gas: 17810) PingPong_startPingPong:test_StartPingPong_With_OOO_Success() (gas: 162091) PingPong_startPingPong:test_StartPingPong_With_Sequenced_Ordered_Success() (gas: 181509) -RMNHome:test() (gas: 186) +RMNRemote_constructor:test_constructor_success() (gas: 8334) +RMNRemote_constructor:test_constructor_zeroChainSelector_reverts() (gas: 59151) +RMNRemote_curse:test_curse_AlreadyCursed_duplicateSubject_reverts() (gas: 154457) +RMNRemote_curse:test_curse_calledByNonOwner_reverts() (gas: 18780) +RMNRemote_curse:test_curse_success() (gas: 149164) +RMNRemote_global_and_legacy_curses:test_global_and_legacy_curses_success() (gas: 133319) +RMNRemote_setConfig:test_setConfig_addSigner_removeSigner_success() (gas: 976479) +RMNRemote_setConfig:test_setConfig_duplicateOnChainPublicKey_reverts() (gas: 323272) +RMNRemote_setConfig:test_setConfig_invalidSignerOrder_reverts() (gas: 80138) +RMNRemote_setConfig:test_setConfig_minSignersIs0_success() (gas: 700548) +RMNRemote_setConfig:test_setConfig_minSignersTooHigh_reverts() (gas: 54024) +RMNRemote_uncurse:test_uncurse_NotCursed_duplicatedUncurseSubject_reverts() (gas: 51912) +RMNRemote_uncurse:test_uncurse_calledByNonOwner_reverts() (gas: 18748) +RMNRemote_uncurse:test_uncurse_success() (gas: 40044) +RMNRemote_verify_withConfigNotSet:test_verify_reverts() (gas: 13650) +RMNRemote_verify_withConfigSet:test_verify_InvalidSignature_reverts() (gas: 78519) +RMNRemote_verify_withConfigSet:test_verify_OutOfOrderSignatures_duplicateSignature_reverts() (gas: 76336) +RMNRemote_verify_withConfigSet:test_verify_OutOfOrderSignatures_not_sorted_reverts() (gas: 83399) +RMNRemote_verify_withConfigSet:test_verify_ThresholdNotMet_reverts() (gas: 152265) +RMNRemote_verify_withConfigSet:test_verify_UnexpectedSigner_reverts() (gas: 386487) +RMNRemote_verify_withConfigSet:test_verify_minSignersIsZero_success() (gas: 184524) +RMNRemote_verify_withConfigSet:test_verify_success() (gas: 68207) RMN_constructor:test_Constructor_Success() (gas: 48994) RMN_getRecordedCurseRelatedOps:test_OpsPostDeployment() (gas: 19732) RMN_lazyVoteToCurseUpdate_Benchmark:test_VoteToCurseLazilyRetain3VotersUponConfigChange_gas() (gas: 152296) @@ -887,24 +908,24 @@ RegistryModuleOwnerCustom_registerAdminViaOwner:test_registerAdminViaOwner_Rever RegistryModuleOwnerCustom_registerAdminViaOwner:test_registerAdminViaOwner_Success() (gas: 129905) Router_applyRampUpdates:test_OffRampMismatch_Revert() (gas: 89366) Router_applyRampUpdates:test_OffRampUpdatesWithRouting() (gas: 10662612) -Router_applyRampUpdates:test_OnRampDisable() (gas: 56028) +Router_applyRampUpdates:test_OnRampDisable() (gas: 56007) Router_applyRampUpdates:test_OnlyOwner_Revert() (gas: 12356) Router_ccipSend:test_CCIPSendLinkFeeNoTokenSuccess_gas() (gas: 114599) Router_ccipSend:test_CCIPSendLinkFeeOneTokenSuccess_gas() (gas: 202430) Router_ccipSend:test_CCIPSendNativeFeeNoTokenSuccess_gas() (gas: 126968) Router_ccipSend:test_CCIPSendNativeFeeOneTokenSuccess_gas() (gas: 214801) -Router_ccipSend:test_FeeTokenAmountTooLow_Revert() (gas: 64532) +Router_ccipSend:test_FeeTokenAmountTooLow_Revert() (gas: 64520) Router_ccipSend:test_InvalidMsgValue() (gas: 32155) -Router_ccipSend:test_NativeFeeTokenInsufficientValue() (gas: 67174) +Router_ccipSend:test_NativeFeeTokenInsufficientValue() (gas: 67177) Router_ccipSend:test_NativeFeeTokenOverpay_Success() (gas: 170385) Router_ccipSend:test_NativeFeeTokenZeroValue() (gas: 54279) Router_ccipSend:test_NativeFeeToken_Success() (gas: 168901) -Router_ccipSend:test_NonLinkFeeToken_Success() (gas: 239230) +Router_ccipSend:test_NonLinkFeeToken_Success() (gas: 239227) Router_ccipSend:test_UnsupportedDestinationChain_Revert() (gas: 24854) Router_ccipSend:test_WhenNotHealthy_Revert() (gas: 44811) -Router_ccipSend:test_WrappedNativeFeeToken_Success() (gas: 171159) +Router_ccipSend:test_WrappedNativeFeeToken_Success() (gas: 171189) Router_ccipSend:test_ZeroFeeAndGasPrice_Success() (gas: 241701) -Router_constructor:test_Constructor_Success() (gas: 13124) +Router_constructor:test_Constructor_Success() (gas: 13128) Router_getArmProxy:test_getArmProxy() (gas: 10573) Router_getFee:test_GetFeeSupportedChain_Success() (gas: 44673) Router_getFee:test_UnsupportedDestinationChain_Revert() (gas: 17192) @@ -915,7 +936,7 @@ Router_recoverTokens:test_RecoverTokensNonOwner_Revert() (gas: 11171) Router_recoverTokens:test_RecoverTokensValueReceiver_Revert() (gas: 358049) Router_recoverTokens:test_RecoverTokens_Success() (gas: 52480) Router_routeMessage:test_AutoExec_Success() (gas: 42816) -Router_routeMessage:test_ExecutionEvent_Success() (gas: 158529) +Router_routeMessage:test_ExecutionEvent_Success() (gas: 158520) Router_routeMessage:test_ManualExec_Success() (gas: 35546) Router_routeMessage:test_OnlyOffRamp_Revert() (gas: 25224) Router_routeMessage:test_WhenNotHealthy_Revert() (gas: 44799) @@ -945,19 +966,19 @@ TokenAdminRegistry_setPool:test_setPool_Success() (gas: 36135) TokenAdminRegistry_setPool:test_setPool_ZeroAddressRemovesPool_Success() (gas: 30842) TokenAdminRegistry_transferAdminRole:test_transferAdminRole_OnlyAdministrator_Revert() (gas: 18103) TokenAdminRegistry_transferAdminRole:test_transferAdminRole_Success() (gas: 49438) -TokenPoolAndProxy:test_lockOrBurn_burnMint_Success() (gas: 5586496) -TokenPoolAndProxy:test_lockOrBurn_burnWithFromMint_Success() (gas: 5617966) -TokenPoolAndProxy:test_lockOrBurn_lockRelease_Success() (gas: 5793243) +TokenPoolAndProxy:test_lockOrBurn_burnMint_Success() (gas: 5586499) +TokenPoolAndProxy:test_lockOrBurn_burnWithFromMint_Success() (gas: 5617969) +TokenPoolAndProxy:test_lockOrBurn_lockRelease_Success() (gas: 5793246) TokenPoolAndProxy:test_setPreviousPool_Success() (gas: 3070731) -TokenPoolAndProxyMigration:test_tokenPoolMigration_Success_1_2() (gas: 6434780) -TokenPoolAndProxyMigration:test_tokenPoolMigration_Success_1_4() (gas: 6634919) -TokenPoolWithAllowList_applyAllowListUpdates:test_AllowListNotEnabled_Revert() (gas: 1979949) -TokenPoolWithAllowList_applyAllowListUpdates:test_OnlyOwner_Revert() (gas: 12107) +TokenPoolAndProxyMigration:test_tokenPoolMigration_Success_1_2() (gas: 6434801) +TokenPoolAndProxyMigration:test_tokenPoolMigration_Success_1_4() (gas: 6634934) +TokenPoolWithAllowList_applyAllowListUpdates:test_AllowListNotEnabled_Revert() (gas: 1979943) +TokenPoolWithAllowList_applyAllowListUpdates:test_OnlyOwner_Revert() (gas: 12113) TokenPoolWithAllowList_applyAllowListUpdates:test_SetAllowListSkipsZero_Success() (gas: 23476) -TokenPoolWithAllowList_applyAllowListUpdates:test_SetAllowList_Success() (gas: 177845) +TokenPoolWithAllowList_applyAllowListUpdates:test_SetAllowList_Success() (gas: 177848) TokenPoolWithAllowList_getAllowList:test_GetAllowList_Success() (gas: 23764) TokenPoolWithAllowList_getAllowListEnabled:test_GetAllowListEnabled_Success() (gas: 8375) -TokenPoolWithAllowList_setRouter:test_SetRouter_Success() (gas: 24879) +TokenPoolWithAllowList_setRouter:test_SetRouter_Success() (gas: 24867) TokenPool_applyChainUpdates:test_applyChainUpdates_DisabledNonZeroRateLimit_Revert() (gas: 271569) TokenPool_applyChainUpdates:test_applyChainUpdates_InvalidRateLimitRate_Revert() (gas: 542359) TokenPool_applyChainUpdates:test_applyChainUpdates_NonExistentChain_Revert() (gas: 18449) @@ -966,13 +987,13 @@ TokenPool_applyChainUpdates:test_applyChainUpdates_Success() (gas: 479160) TokenPool_applyChainUpdates:test_applyChainUpdates_ZeroAddressNotAllowed_Revert() (gas: 157422) TokenPool_constructor:test_ZeroAddressNotAllowed_Revert() (gas: 70484) TokenPool_constructor:test_immutableFields_Success() (gas: 20586) -TokenPool_getRemotePool:test_getRemotePool_Success() (gas: 274175) +TokenPool_getRemotePool:test_getRemotePool_Success() (gas: 274181) TokenPool_onlyOffRamp:test_CallerIsNotARampOnRouter_Revert() (gas: 277296) -TokenPool_onlyOffRamp:test_ChainNotAllowed_Revert() (gas: 290035) -TokenPool_onlyOffRamp:test_onlyOffRamp_Success() (gas: 350059) +TokenPool_onlyOffRamp:test_ChainNotAllowed_Revert() (gas: 290028) +TokenPool_onlyOffRamp:test_onlyOffRamp_Success() (gas: 350050) TokenPool_onlyOnRamp:test_CallerIsNotARampOnRouter_Revert() (gas: 277036) -TokenPool_onlyOnRamp:test_ChainNotAllowed_Revert() (gas: 254072) -TokenPool_onlyOnRamp:test_onlyOnRamp_Success() (gas: 305115) +TokenPool_onlyOnRamp:test_ChainNotAllowed_Revert() (gas: 254065) +TokenPool_onlyOnRamp:test_onlyOnRamp_Success() (gas: 305106) TokenPool_setChainRateLimiterConfig:test_NonExistentChain_Revert() (gas: 17187) TokenPool_setChainRateLimiterConfig:test_OnlyOwnerOrRateLimitAdmin_Revert() (gas: 15227) TokenPool_setRemotePool:test_setRemotePool_NonExistentChain_Reverts() (gas: 15671) @@ -987,16 +1008,16 @@ TokenProxy_ccipSend:test_CcipSend_Success() (gas: 262651) TokenProxy_constructor:test_Constructor() (gas: 13836) TokenProxy_getFee:test_GetFeeGasShouldBeZero_Revert() (gas: 16899) TokenProxy_getFee:test_GetFeeInvalidToken_Revert() (gas: 12706) -TokenProxy_getFee:test_GetFeeNoDataAllowed_Revert() (gas: 15888) +TokenProxy_getFee:test_GetFeeNoDataAllowed_Revert() (gas: 15885) TokenProxy_getFee:test_GetFee_Success() (gas: 85240) USDCTokenPool__validateMessage:test_ValidateInvalidMessage_Revert() (gas: 25704) -USDCTokenPool_lockOrBurn:test_CallerIsNotARampOnRouter_Revert() (gas: 35499) -USDCTokenPool_lockOrBurn:test_LockOrBurnWithAllowList_Revert() (gas: 30244) -USDCTokenPool_lockOrBurn:test_LockOrBurn_Success() (gas: 133512) -USDCTokenPool_lockOrBurn:test_UnknownDomain_Revert() (gas: 478191) -USDCTokenPool_releaseOrMint:test_ReleaseOrMintRealTx_Success() (gas: 268689) -USDCTokenPool_releaseOrMint:test_TokenMaxCapacityExceeded_Revert() (gas: 50964) -USDCTokenPool_releaseOrMint:test_UnlockingUSDCFailed_Revert() (gas: 99005) +USDCTokenPool_lockOrBurn:test_CallerIsNotARampOnRouter_Revert() (gas: 35481) +USDCTokenPool_lockOrBurn:test_LockOrBurnWithAllowList_Revert() (gas: 30235) +USDCTokenPool_lockOrBurn:test_LockOrBurn_Success() (gas: 133508) +USDCTokenPool_lockOrBurn:test_UnknownDomain_Revert() (gas: 478182) +USDCTokenPool_releaseOrMint:test_ReleaseOrMintRealTx_Success() (gas: 268672) +USDCTokenPool_releaseOrMint:test_TokenMaxCapacityExceeded_Revert() (gas: 50952) +USDCTokenPool_releaseOrMint:test_UnlockingUSDCFailed_Revert() (gas: 98987) USDCTokenPool_setDomains:test_InvalidDomain_Revert() (gas: 66393) USDCTokenPool_setDomains:test_OnlyOwner_Revert() (gas: 11363) USDCTokenPool_supportsInterface:test_SupportsInterface_Success() (gas: 10041) \ No newline at end of file diff --git a/contracts/src/v0.8/ccip/interfaces/IRMNV2.sol b/contracts/src/v0.8/ccip/interfaces/IRMNV2.sol index 9af3de6cab..ba6f652e36 100644 --- a/contracts/src/v0.8/ccip/interfaces/IRMNV2.sol +++ b/contracts/src/v0.8/ccip/interfaces/IRMNV2.sol @@ -11,12 +11,29 @@ interface IRMNV2 { bytes32 s; } - function verify(Internal.MerkleRoot[] memory merkleRoots, Signature[] memory signatures) external view; + /// @notice Verifies signatures of RMN nodes, on dest lane updates as provided in the CommitReport + /// @param offRampAddress is not inferred by msg.sender, in case the call is made through ARMProxy + /// @param merkleRoots must be well formed, and is a representation of the CommitReport received from the oracles + /// @param signatures rmnNodes ECDSA sigs, only r & s, must be sorted in ascending order by signer address + /// @param rawVs rmnNodes ECDSA sigs, part v bitmap + /// @dev Will revert if verification fails + function verify( + address offRampAddress, + Internal.MerkleRoot[] memory merkleRoots, + Signature[] memory signatures, + uint256 rawVs + ) external view; + + /// @notice gets the current set of cursed subjects + /// @return subjects the list of cursed subjects + function getCursedSubjects() external view returns (bytes16[] memory subjects); /// @notice If there is an active global or legacy curse, this function returns true. + /// @return bool true if there is an active global curse function isCursed() external view returns (bool); /// @notice If there is an active global curse, or an active curse for `subject`, this function returns true. /// @param subject To check whether a particular chain is cursed, set to bytes16(uint128(chainSelector)). + /// @return bool true if the provided subject is cured *or* if there is an active global curse function isCursed(bytes16 subject) external view returns (bool); } diff --git a/contracts/src/v0.8/ccip/offRamp/OffRamp.sol b/contracts/src/v0.8/ccip/offRamp/OffRamp.sol index 99872451b8..5fcddb486e 100644 --- a/contracts/src/v0.8/ccip/offRamp/OffRamp.sol +++ b/contracts/src/v0.8/ccip/offRamp/OffRamp.sol @@ -131,6 +131,7 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { Internal.PriceUpdates priceUpdates; // Collection of gas and price updates to commit Internal.MerkleRoot[] merkleRoots; // Collection of merkle roots per source chain to commit IRMNV2.Signature[] rmnSignatures; // RMN signatures on the merkle roots + uint256 rmnRawVs; // Raw v values of the RMN signatures } struct GasLimitOverride { @@ -778,13 +779,13 @@ contract OffRamp is ITypeAndVersion, MultiOCR3Base { bytes calldata report, bytes32[] calldata rs, bytes32[] calldata ss, - bytes32 rawVs // signatures + bytes32 rawVs ) external { CommitReport memory commitReport = abi.decode(report, (CommitReport)); // Verify RMN signatures if (commitReport.merkleRoots.length > 0) { - i_rmn.verify(commitReport.merkleRoots, commitReport.rmnSignatures); + i_rmn.verify(address(this), commitReport.merkleRoots, commitReport.rmnSignatures, commitReport.rmnRawVs); } // Check if the report contains price updates diff --git a/contracts/src/v0.8/ccip/rmn/RMNHome.sol b/contracts/src/v0.8/ccip/rmn/RMNHome.sol index 0d3d7d9803..ec479bf663 100644 --- a/contracts/src/v0.8/ccip/rmn/RMNHome.sol +++ b/contracts/src/v0.8/ccip/rmn/RMNHome.sol @@ -1,18 +1,22 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; - -import "@openzeppelin/contracts/access/Ownable2Step.sol"; +pragma solidity 0.8.24; import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; +import {OwnerIsCreator} from "../../shared/access/OwnerIsCreator.sol"; + /// @notice Stores the home configuration for RMN, that is referenced by CCIP oracles, RMN nodes, and the RMNRemote /// contracts. -contract RMNHome is Ownable2Step, ITypeAndVersion { - /// @dev temp placeholder to exclude this contract from coverage - function test() public {} +contract RMNHome is OwnerIsCreator, ITypeAndVersion { + error DuplicatePeerId(); + error DuplicateOffchainPublicKey(); + error OutOfOrderSourceChains(); + error OutOfOrderObserverNodeIndices(); + error OutOfBoundsObserverNodeIndex(); + error MinObserversTooHigh(); - string public constant override typeAndVersion = "RMNHome 1.6.0-dev"; - uint256 public constant CONFIG_RING_BUFFER_SIZE = 2; + event ConfigSet(bytes32 configDigest, VersionedConfig versionedConfig); + event ConfigRevoked(bytes32 configDigest); struct Node { string peerId; // used for p2p communication, base58 encoded @@ -38,6 +42,9 @@ contract RMNHome is Ownable2Step, ITypeAndVersion { Config config; } + string public constant override typeAndVersion = "RMNHome 1.6.0-dev"; + uint256 public constant CONFIG_RING_BUFFER_SIZE = 2; + function _configDigest(VersionedConfig memory versionedConfig) internal pure returns (bytes32) { uint256 h = uint256(keccak256(abi.encode(versionedConfig))); uint256 prefixMask = type(uint256).max << (256 - 16); // 0xFFFF00..00 @@ -143,22 +150,4 @@ contract RMNHome is Ownable2Step, ITypeAndVersion { } } } - - /// - /// Events - /// - - event ConfigSet(bytes32 configDigest, VersionedConfig versionedConfig); - event ConfigRevoked(bytes32 configDigest); - - /// - /// Errors - /// - - error DuplicatePeerId(); - error DuplicateOffchainPublicKey(); - error OutOfOrderSourceChains(); - error OutOfOrderObserverNodeIndices(); - error OutOfBoundsObserverNodeIndex(); - error MinObserversTooHigh(); } diff --git a/contracts/src/v0.8/ccip/rmn/RMNRemote.sol b/contracts/src/v0.8/ccip/rmn/RMNRemote.sol index 3ebbf4af80..1a7270d846 100644 --- a/contracts/src/v0.8/ccip/rmn/RMNRemote.sol +++ b/contracts/src/v0.8/ccip/rmn/RMNRemote.sol @@ -1,168 +1,241 @@ // SPDX-License-Identifier: BUSL-1.1 -pragma solidity ^0.8.24; +pragma solidity 0.8.24; -import {OwnerIsCreator} from "../../shared/access/OwnerIsCreator.sol"; import {ITypeAndVersion} from "../../shared/interfaces/ITypeAndVersion.sol"; import {IRMNV2} from "../interfaces/IRMNV2.sol"; + +import {OwnerIsCreator} from "../../shared/access/OwnerIsCreator.sol"; +import {EnumerableSet} from "../../shared/enumerable/EnumerableSetWithBytes16.sol"; import {Internal} from "../libraries/Internal.sol"; +/// @dev this is included in the preimage of the digest that RMN nodes sign bytes32 constant RMN_V1_6_ANY2EVM_REPORT = keccak256("RMN_V1_6_ANY2EVM_REPORT"); -/// @dev XXX DO NOT USE THIS CONTRACT, NOT PRODUCTION READY XXX +/// @dev An active curse on this subject will cause isCursed() to return true. Use this subject if there is an issue with a +/// remote chain, for which there exists a legacy lane contract deployed on the same chain as this RMN contract is +/// deployed, relying on isCursed(). +bytes16 constant LEGACY_CURSE_SUBJECT = 0x01000000000000000000000000000000; + +/// @dev An active curse on this subject will cause isCursed() and isCursed(bytes16) to return true. Use this subject for +/// issues affecting all of CCIP chains, or pertaining to the chain that this contract is deployed on, instead of using +/// the local chain selector as a subject. +bytes16 constant GLOBAL_CURSE_SUBJECT = 0x01000000000000000000000000000001; + /// @notice This contract supports verification of RMN reports for any Any2EVM OffRamp. contract RMNRemote is OwnerIsCreator, ITypeAndVersion, IRMNV2 { - /// @dev temp placeholder to exclude this contract from coverage - function test() public {} + using EnumerableSet for EnumerableSet.Bytes16Set; - string public constant override typeAndVersion = "RMNRemote 1.6.0-dev"; - - uint64 internal immutable i_chainSelector; + error AlreadyCursed(bytes16 subject); + error ConfigNotSet(); + error DuplicateOnchainPublicKey(); + error InvalidSignature(); + error InvalidSignerOrder(); + error MinSignersTooHigh(); + error NotCursed(bytes16 subject); + error OutOfOrderSignatures(); + error ThresholdNotMet(); + error UnexpectedSigner(); + error ZeroValueNotAllowed(); - constructor(uint64 chainSelector) { - i_chainSelector = chainSelector; - } + event ConfigSet(uint32 indexed version, Config config); + event Cursed(bytes16[] subjects); + event Uncursed(bytes16[] subjects); + /// @dev the configuration of an RMN signer struct Signer { - address onchainPublicKey; // for signing reports - uint64 nodeIndex; // maps to nodes in home chain config, should be strictly increasing + address onchainPublicKey; // ────╮ For signing reports + uint64 nodeIndex; // ────────────╯ Maps to nodes in home chain config, should be strictly increasing } + /// @dev the contract config + /// @dev note: minSigners can be set to 0 to disable verification for chains without RMN support struct Config { - bytes32 rmnHomeContractConfigDigest; - Signer[] signers; - uint64 minSigners; + bytes32 rmnHomeContractConfigDigest; // Digest of the RMNHome contract config + Signer[] signers; // List of signers + uint64 minSigners; // Threshold for the number of signers required to verify a report } - struct VersionedConfig { - uint32 version; - Config config; + /// @dev part of the payload that RMN nodes sign: keccak256(abi.encode(RMN_V1_6_ANY2EVM_REPORT, report)) + /// @dev this struct is only ever abi-encoded and hashed; it is never stored + struct Report { + uint256 destChainId; // To guard against chain selector misconfiguration + uint64 destChainSelector; // ────────────╮ The chain selector of the destination chain + address rmnRemoteContractAddress; // ─────╯ The address of this contract + address offrampAddress; // The address of the offramp on the same chain as this contract + bytes32 rmnHomeContractConfigDigest; // The digest of the RMNHome contract config + Internal.MerkleRoot[] merkleRoots; // The dest lane updates + } + + string public constant override typeAndVersion = "RMNRemote 1.6.0-dev"; + uint64 internal immutable i_localChainSelector; + + Config private s_config; + uint32 private s_configCount; + + EnumerableSet.Bytes16Set private s_cursedSubjects; + mapping(address signer => bool exists) private s_signers; // for more gas efficient verify + + /// @param localChainSelector the chain selector of the chain this contract is deployed to + constructor(uint64 localChainSelector) { + if (localChainSelector == 0) revert ZeroValueNotAllowed(); + i_localChainSelector = localChainSelector; } - Config s_config; - uint32 s_configCount; + // ================================================================ + // │ Verification │ + // ================================================================ + + /// @inheritdoc IRMNV2 + function verify( + address offrampAddress, + Internal.MerkleRoot[] calldata merkleRoots, + Signature[] calldata signatures, + uint256 rawVs + ) external view { + if (s_configCount == 0) { + revert ConfigNotSet(); + } + if (signatures.length < s_config.minSigners) revert ThresholdNotMet(); + + bytes32 digest = keccak256( + abi.encode( + RMN_V1_6_ANY2EVM_REPORT, + Report({ + destChainId: block.chainid, + destChainSelector: i_localChainSelector, + rmnRemoteContractAddress: address(this), + offrampAddress: offrampAddress, + rmnHomeContractConfigDigest: s_config.rmnHomeContractConfigDigest, + merkleRoots: merkleRoots + }) + ) + ); + + address prevAddress; + address signerAddress; + for (uint256 i = 0; i < signatures.length; ++i) { + // The v value is bit-encoded into rawVs + signerAddress = ecrecover(digest, 27 + uint8(rawVs & 0x01 << i), signatures[i].r, signatures[i].s); + if (signerAddress == address(0)) revert InvalidSignature(); + if (prevAddress >= signerAddress) revert OutOfOrderSignatures(); + if (!s_signers[signerAddress]) revert UnexpectedSigner(); + prevAddress = signerAddress; + } + } - mapping(address signer => bool exists) s_signers; // for more gas efficient verify + // ================================================================ + // │ Config │ + // ================================================================ + /// @notice Sets the configuration of the contract + /// @param newConfig the new configuration + /// @dev setting config is atomic; we delete all pre-existing config and set everything from scratch function setConfig(Config calldata newConfig) external onlyOwner { - // sanity checks - { - // signers are in ascending order of nodeIndex - for (uint256 i = 1; i < newConfig.signers.length; ++i) { - if (!(newConfig.signers[i - 1].nodeIndex < newConfig.signers[i].nodeIndex)) { - revert InvalidSignerOrder(); - } + // signers are in ascending order of nodeIndex + for (uint256 i = 1; i < newConfig.signers.length; ++i) { + if (!(newConfig.signers[i - 1].nodeIndex < newConfig.signers[i].nodeIndex)) { + revert InvalidSignerOrder(); } + } - // minSigners is tenable - if (!(newConfig.minSigners <= newConfig.signers.length)) { - revert MinSignersTooHigh(); - } + // minSigners is tenable + if (!(newConfig.minSigners <= newConfig.signers.length)) { + revert MinSignersTooHigh(); } // clear the old signers - { - Config storage oldConfig = s_config; - while (oldConfig.signers.length > 0) { - delete s_signers[oldConfig.signers[oldConfig.signers.length - 1].onchainPublicKey]; - oldConfig.signers.pop(); - } + for (uint256 i = s_config.signers.length; i > 0; --i) { + delete s_signers[s_config.signers[i - 1].onchainPublicKey]; } // set the new signers - { - for (uint256 i = 0; i < newConfig.signers.length; ++i) { - if (s_signers[newConfig.signers[i].onchainPublicKey]) { - revert DuplicateOnchainPublicKey(); - } - s_signers[newConfig.signers[i].onchainPublicKey] = true; + for (uint256 i = 0; i < newConfig.signers.length; ++i) { + if (s_signers[newConfig.signers[i].onchainPublicKey]) { + revert DuplicateOnchainPublicKey(); } + s_signers[newConfig.signers[i].onchainPublicKey] = true; } s_config = newConfig; uint32 newConfigCount = ++s_configCount; - emit ConfigSet(VersionedConfig({version: newConfigCount, config: newConfig})); + emit ConfigSet(newConfigCount, newConfig); } - function getVersionedConfig() external view returns (VersionedConfig memory) { - return VersionedConfig({version: s_configCount, config: s_config}); + /// @notice Returns the current configuration of the contract and a version number + /// @return version the current configs version + /// @return config the current config + function getVersionedConfig() external view returns (uint32 version, Config memory config) { + return (s_configCount, s_config); } - struct Report { - uint256 destChainId; // to guard against chain selector misconfiguration - uint64 destChainSelector; - address rmnRemoteContractAddress; - address offrampAddress; - bytes32 rmnHomeContractConfigDigest; - Internal.MerkleRoot[] destLaneUpdates; + /// @notice Returns the chain selector configured at deployment time + /// @return localChainSelector the chain selector (not the chain ID) + function getLocalChainSelector() external view returns (uint64 localChainSelector) { + return i_localChainSelector; } - /// @notice Verifies signatures of RMN nodes, on dest lane updates as provided in the CommitReport - /// @param destLaneUpdates must be well formed, and is a representation of the CommitReport received from the oracles - /// @param signatures must be sorted in ascending order by signer address - /// @dev Will revert if verification fails. Needs to be called by the OffRamp for which the signatures are produced, - /// otherwise verification will fail. - function verify(Internal.MerkleRoot[] memory destLaneUpdates, Signature[] memory signatures) external view { - return; // XXX temporary workaround to fix integration tests while we wait to productionize this contract + // ================================================================ + // │ Cursing │ + // ================================================================ - if (s_configCount == 0) { - revert ConfigNotSet(); + /// @notice Curse a single subject + /// @param subject the subject to curse + function curse(bytes16 subject) external { + bytes16[] memory subjects = new bytes16[](1); + subjects[0] = subject; + curse(subjects); + } + + /// @notice Curse an array of subjects + /// @param subjects the subjects to curse + /// @dev reverts if any of the subjects are already cursed or if there is a duplicate + function curse(bytes16[] memory subjects) public onlyOwner { + for (uint256 i = 0; i < subjects.length; ++i) { + if (!s_cursedSubjects.add(subjects[i])) { + revert AlreadyCursed(subjects[i]); + } } + emit Cursed(subjects); + } - bytes32 signedHash = keccak256( - abi.encode( - RMN_V1_6_ANY2EVM_REPORT, - Report({ - destChainId: block.chainid, - destChainSelector: i_chainSelector, - rmnRemoteContractAddress: address(this), - offrampAddress: msg.sender, - rmnHomeContractConfigDigest: s_config.rmnHomeContractConfigDigest, - destLaneUpdates: destLaneUpdates - }) - ) - ); + /// @notice Uncurse a single subject + /// @param subject the subject to uncurse + function uncurse(bytes16 subject) external { + bytes16[] memory subjects = new bytes16[](1); + subjects[0] = subject; + uncurse(subjects); + } - uint256 numSigners = 0; - address prevAddress = address(0); - for (uint256 i = 0; i < signatures.length; ++i) { - Signature memory sig = signatures[i]; - address signerAddress = ecrecover(signedHash, 27, sig.r, sig.s); - if (signerAddress == address(0)) revert InvalidSignature(); - if (!(prevAddress < signerAddress)) revert OutOfOrderSignatures(); - if (!s_signers[signerAddress]) revert UnexpectedSigner(); - prevAddress = signerAddress; - ++numSigners; + /// @notice Uncurse an array of subjects + /// @param subjects the subjects to uncurse + /// @dev reverts if any of the subjects are not cursed or if there is a duplicate + function uncurse(bytes16[] memory subjects) public onlyOwner { + for (uint256 i = 0; i < subjects.length; ++i) { + if (!s_cursedSubjects.remove(subjects[i])) { + revert NotCursed(subjects[i]); + } } - if (numSigners < s_config.minSigners) revert ThresholdNotMet(); + emit Uncursed(subjects); } - /// @notice If there is an active global or legacy curse, this function returns true. + /// @inheritdoc IRMNV2 + function getCursedSubjects() external view returns (bytes16[] memory subjects) { + return s_cursedSubjects.values(); + } + + /// @inheritdoc IRMNV2 function isCursed() external view returns (bool) { - return false; // XXX temporary workaround + if (s_cursedSubjects.length() == 0) { + return false; + } + return s_cursedSubjects.contains(LEGACY_CURSE_SUBJECT) || s_cursedSubjects.contains(GLOBAL_CURSE_SUBJECT); } - /// @notice If there is an active global curse, or an active curse for `subject`, this function returns true. - /// @param subject To check whether a particular chain is cursed, set to bytes16(uint128(chainSelector)). + /// @inheritdoc IRMNV2 function isCursed(bytes16 subject) external view returns (bool) { - return false; // XXX temporary workaround + if (s_cursedSubjects.length() == 0) { + return false; + } + return s_cursedSubjects.contains(subject) || s_cursedSubjects.contains(GLOBAL_CURSE_SUBJECT); } - - /// - /// Events - /// - - event ConfigSet(VersionedConfig versionedConfig); - - /// - /// Errors - /// - - error InvalidSignature(); - error OutOfOrderSignatures(); - error UnexpectedSigner(); - error ThresholdNotMet(); - error ConfigNotSet(); - error InvalidSignerOrder(); - error MinSignersTooHigh(); - error DuplicateOnchainPublicKey(); } diff --git a/contracts/src/v0.8/ccip/test/BaseTest.t.sol b/contracts/src/v0.8/ccip/test/BaseTest.t.sol index e8003cab15..f6cd83672e 100644 --- a/contracts/src/v0.8/ccip/test/BaseTest.t.sol +++ b/contracts/src/v0.8/ccip/test/BaseTest.t.sol @@ -73,6 +73,9 @@ contract BaseTest is Test { MockRMN internal s_mockRMN; IRMNV2 internal s_mockRMNRemote; + // nonce for pseudo-random number generation, not to be exposed to test suites + uint256 private randNonce; + function setUp() public virtual { // BaseTest.setUp is often called multiple times from tests' setUp due to inheritance. if (s_baseTestInitialized) return; @@ -128,4 +131,19 @@ contract BaseTest is Test { return priceUpdates; } + + /// @dev returns a pseudo-random bytes32 + function _randomBytes32() internal returns (bytes32) { + return keccak256(abi.encodePacked(++randNonce)); + } + + /// @dev returns a pseudo-random number + function _randomNum() internal returns (uint256) { + return uint256(_randomBytes32()); + } + + /// @dev returns a pseudo-random address + function _randomAddress() internal returns (address) { + return address(uint160(_randomNum())); + } } diff --git a/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.t.sol b/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.t.sol index 12967558ce..5f06a37e13 100644 --- a/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.t.sol +++ b/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.t.sol @@ -168,8 +168,12 @@ contract MultiRampsE2E is OnRampSetup, OffRampSetup { merkleRoot: merkleRoots[1] }); - OffRamp.CommitReport memory report = - OffRamp.CommitReport({priceUpdates: _getEmptyPriceUpdates(), merkleRoots: roots, rmnSignatures: rmnSignatures}); + OffRamp.CommitReport memory report = OffRamp.CommitReport({ + priceUpdates: _getEmptyPriceUpdates(), + merkleRoots: roots, + rmnSignatures: rmnSignatures, + rmnRawVs: 0 + }); vm.resumeGasMetering(); _commit(report, ++s_latestSequenceNumber); @@ -269,6 +273,7 @@ contract MultiRampsE2E is OnRampSetup, OffRampSetup { Internal.Any2EVMTokenTransfer[] memory any2EVMTokenTransfer = new Internal.Any2EVMTokenTransfer[](message.tokenAmounts.length); + for (uint256 i = 0; i < msgEvent.tokenAmounts.length; ++i) { any2EVMTokenTransfer[i] = Internal.Any2EVMTokenTransfer({ sourcePoolAddress: abi.encode(msgEvent.tokenAmounts[i].sourcePoolAddress), diff --git a/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol b/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol index 1a31691c22..73adbb12c0 100644 --- a/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol +++ b/contracts/src/v0.8/ccip/test/offRamp/OffRamp.t.sol @@ -995,7 +995,8 @@ contract OffRamp_executeSingleReport is OffRampSetup { return OffRamp.CommitReport({ priceUpdates: _getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), merkleRoots: roots, - rmnSignatures: s_rmnSignatures + rmnSignatures: s_rmnSignatures, + rmnRawVs: 0 }); } } @@ -3243,7 +3244,8 @@ contract OffRamp_applySourceChainConfigUpdates is OffRampSetup { OffRamp.CommitReport({ priceUpdates: _getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), merkleRoots: roots, - rmnSignatures: s_rmnSignatures + rmnSignatures: s_rmnSignatures, + rmnRawVs: 0 }), s_latestSequenceNumber ); @@ -3296,8 +3298,12 @@ contract OffRamp_commit is OffRampSetup { merkleRoot: root }); - OffRamp.CommitReport memory commitReport = - OffRamp.CommitReport({priceUpdates: _getEmptyPriceUpdates(), merkleRoots: roots, rmnSignatures: s_rmnSignatures}); + OffRamp.CommitReport memory commitReport = OffRamp.CommitReport({ + priceUpdates: _getEmptyPriceUpdates(), + merkleRoots: roots, + rmnSignatures: s_rmnSignatures, + rmnRawVs: 0 + }); vm.expectEmit(); emit OffRamp.CommitReportAccepted(commitReport.merkleRoots, commitReport.priceUpdates); @@ -3324,8 +3330,12 @@ contract OffRamp_commit is OffRampSetup { maxSeqNr: maxSeq, merkleRoot: "stale report 1" }); - OffRamp.CommitReport memory commitReport = - OffRamp.CommitReport({priceUpdates: _getEmptyPriceUpdates(), merkleRoots: roots, rmnSignatures: s_rmnSignatures}); + OffRamp.CommitReport memory commitReport = OffRamp.CommitReport({ + priceUpdates: _getEmptyPriceUpdates(), + merkleRoots: roots, + rmnSignatures: s_rmnSignatures, + rmnRawVs: 0 + }); vm.expectEmit(); emit OffRamp.CommitReportAccepted(commitReport.merkleRoots, commitReport.priceUpdates); @@ -3363,7 +3373,8 @@ contract OffRamp_commit is OffRampSetup { OffRamp.CommitReport memory commitReport = OffRamp.CommitReport({ priceUpdates: _getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), merkleRoots: roots, - rmnSignatures: s_rmnSignatures + rmnSignatures: s_rmnSignatures, + rmnRawVs: 0 }); vm.expectEmit(); @@ -3385,7 +3396,8 @@ contract OffRamp_commit is OffRampSetup { OffRamp.CommitReport memory commitReport = OffRamp.CommitReport({ priceUpdates: _getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), merkleRoots: roots, - rmnSignatures: s_rmnSignatures + rmnSignatures: s_rmnSignatures, + rmnRawVs: 0 }); vm.expectEmit(); @@ -3403,7 +3415,8 @@ contract OffRamp_commit is OffRampSetup { OffRamp.CommitReport memory commitReport = OffRamp.CommitReport({ priceUpdates: _getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), merkleRoots: roots, - rmnSignatures: s_rmnSignatures + rmnSignatures: s_rmnSignatures, + rmnRawVs: 0 }); vm.expectEmit(); @@ -3455,7 +3468,8 @@ contract OffRamp_commit is OffRampSetup { OffRamp.CommitReport memory commitReport = OffRamp.CommitReport({ priceUpdates: _getSingleTokenPriceUpdateStruct(s_sourceFeeToken, tokenPrice1), merkleRoots: roots, - rmnSignatures: s_rmnSignatures + rmnSignatures: s_rmnSignatures, + rmnRawVs: 0 }); vm.expectEmit(); @@ -3565,8 +3579,12 @@ contract OffRamp_commit is OffRampSetup { onRampAddress: abi.encode(ON_RAMP_ADDRESS_1) }); - OffRamp.CommitReport memory commitReport = - OffRamp.CommitReport({priceUpdates: _getEmptyPriceUpdates(), merkleRoots: roots, rmnSignatures: s_rmnSignatures}); + OffRamp.CommitReport memory commitReport = OffRamp.CommitReport({ + priceUpdates: _getEmptyPriceUpdates(), + merkleRoots: roots, + rmnSignatures: s_rmnSignatures, + rmnRawVs: 0 + }); vm.expectRevert(abi.encodeWithSelector(OffRamp.CursedByRMN.selector, roots[0].sourceChainSelector)); _commit(commitReport, s_latestSequenceNumber); @@ -3581,8 +3599,12 @@ contract OffRamp_commit is OffRampSetup { maxSeqNr: 4, merkleRoot: bytes32(0) }); - OffRamp.CommitReport memory commitReport = - OffRamp.CommitReport({priceUpdates: _getEmptyPriceUpdates(), merkleRoots: roots, rmnSignatures: s_rmnSignatures}); + OffRamp.CommitReport memory commitReport = OffRamp.CommitReport({ + priceUpdates: _getEmptyPriceUpdates(), + merkleRoots: roots, + rmnSignatures: s_rmnSignatures, + rmnRawVs: 0 + }); vm.expectRevert(OffRamp.InvalidRoot.selector); _commit(commitReport, s_latestSequenceNumber); @@ -3597,8 +3619,12 @@ contract OffRamp_commit is OffRampSetup { maxSeqNr: 2, merkleRoot: bytes32(0) }); - OffRamp.CommitReport memory commitReport = - OffRamp.CommitReport({priceUpdates: _getEmptyPriceUpdates(), merkleRoots: roots, rmnSignatures: s_rmnSignatures}); + OffRamp.CommitReport memory commitReport = OffRamp.CommitReport({ + priceUpdates: _getEmptyPriceUpdates(), + merkleRoots: roots, + rmnSignatures: s_rmnSignatures, + rmnRawVs: 0 + }); vm.expectRevert( abi.encodeWithSelector( @@ -3618,8 +3644,12 @@ contract OffRamp_commit is OffRampSetup { maxSeqNr: 0, merkleRoot: bytes32(0) }); - OffRamp.CommitReport memory commitReport = - OffRamp.CommitReport({priceUpdates: _getEmptyPriceUpdates(), merkleRoots: roots, rmnSignatures: s_rmnSignatures}); + OffRamp.CommitReport memory commitReport = OffRamp.CommitReport({ + priceUpdates: _getEmptyPriceUpdates(), + merkleRoots: roots, + rmnSignatures: s_rmnSignatures, + rmnRawVs: 0 + }); vm.expectRevert( abi.encodeWithSelector( @@ -3634,7 +3664,8 @@ contract OffRamp_commit is OffRampSetup { OffRamp.CommitReport memory commitReport = OffRamp.CommitReport({ priceUpdates: _getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), merkleRoots: roots, - rmnSignatures: s_rmnSignatures + rmnSignatures: s_rmnSignatures, + rmnRawVs: 0 }); vm.expectRevert(OffRamp.StaleCommitReport.selector); @@ -3646,7 +3677,8 @@ contract OffRamp_commit is OffRampSetup { OffRamp.CommitReport memory commitReport = OffRamp.CommitReport({ priceUpdates: _getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), merkleRoots: roots, - rmnSignatures: s_rmnSignatures + rmnSignatures: s_rmnSignatures, + rmnRawVs: 0 }); vm.expectEmit(); @@ -3667,8 +3699,12 @@ contract OffRamp_commit is OffRampSetup { merkleRoot: "Only a single root" }); - OffRamp.CommitReport memory commitReport = - OffRamp.CommitReport({priceUpdates: _getEmptyPriceUpdates(), merkleRoots: roots, rmnSignatures: s_rmnSignatures}); + OffRamp.CommitReport memory commitReport = OffRamp.CommitReport({ + priceUpdates: _getEmptyPriceUpdates(), + merkleRoots: roots, + rmnSignatures: s_rmnSignatures, + rmnRawVs: 0 + }); vm.expectRevert(abi.encodeWithSelector(OffRamp.SourceChainNotEnabled.selector, 0)); _commit(commitReport, s_latestSequenceNumber); @@ -3683,8 +3719,12 @@ contract OffRamp_commit is OffRampSetup { maxSeqNr: 2, merkleRoot: "Only a single root" }); - OffRamp.CommitReport memory commitReport = - OffRamp.CommitReport({priceUpdates: _getEmptyPriceUpdates(), merkleRoots: roots, rmnSignatures: s_rmnSignatures}); + OffRamp.CommitReport memory commitReport = OffRamp.CommitReport({ + priceUpdates: _getEmptyPriceUpdates(), + merkleRoots: roots, + rmnSignatures: s_rmnSignatures, + rmnRawVs: 0 + }); _commit(commitReport, s_latestSequenceNumber); commitReport.merkleRoots[0].minSeqNr = 3; @@ -3718,7 +3758,8 @@ contract OffRamp_commit is OffRampSetup { return OffRamp.CommitReport({ priceUpdates: _getSingleTokenPriceUpdateStruct(s_sourceFeeToken, 4e18), merkleRoots: roots, - rmnSignatures: s_rmnSignatures + rmnSignatures: s_rmnSignatures, + rmnRawVs: 0 }); } } diff --git a/contracts/src/v0.8/ccip/test/rmn/RMNHome.t.sol b/contracts/src/v0.8/ccip/test/rmn/RMNHome.t.sol new file mode 100644 index 0000000000..40cb1e4a07 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/rmn/RMNHome.t.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {Internal} from "../../libraries/Internal.sol"; +import {RMNHome} from "../../rmn/RMNHome.sol"; +import {BaseTest} from "../BaseTest.t.sol"; + +contract RMNHomeTest is BaseTest { + RMNHome public s_rmnHome; + + function setUp() public virtual override { + super.setUp(); + s_rmnHome = new RMNHome(); + } +} diff --git a/contracts/src/v0.8/ccip/test/rmn/RMNRemote.t.sol b/contracts/src/v0.8/ccip/test/rmn/RMNRemote.t.sol new file mode 100644 index 0000000000..f24b3ac9c9 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/rmn/RMNRemote.t.sol @@ -0,0 +1,280 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {IRMNV2} from "../../interfaces/IRMNV2.sol"; +import {Internal} from "../../libraries/Internal.sol"; +import {GLOBAL_CURSE_SUBJECT, LEGACY_CURSE_SUBJECT, RMNRemote} from "../../rmn/RMNRemote.sol"; +import {RMNRemoteSetup} from "./RMNRemoteSetup.t.sol"; + +contract RMNRemote_constructor is RMNRemoteSetup { + function test_constructor_success() public view { + assertEq(s_rmnRemote.getLocalChainSelector(), 1); + } + + function test_constructor_zeroChainSelector_reverts() public { + vm.expectRevert(RMNRemote.ZeroValueNotAllowed.selector); + new RMNRemote(0); + } +} + +contract RMNRemote_setConfig is RMNRemoteSetup { + function test_setConfig_minSignersIs0_success() public { + // Initially there is no config, the version is 0 + uint32 currentConfigVersion = 0; + RMNRemote.Config memory config = + RMNRemote.Config({rmnHomeContractConfigDigest: _randomBytes32(), signers: s_signers, minSigners: 0}); + + vm.expectEmit(); + emit RMNRemote.ConfigSet(++currentConfigVersion, config); + + s_rmnRemote.setConfig(config); + + (uint32 version, RMNRemote.Config memory gotConfig) = s_rmnRemote.getVersionedConfig(); + assertEq(gotConfig.minSigners, 0); + assertEq(version, currentConfigVersion); + + // A new config should increment the version + vm.expectEmit(); + emit RMNRemote.ConfigSet(++currentConfigVersion, config); + + s_rmnRemote.setConfig(config); + } + + function test_setConfig_addSigner_removeSigner_success() public { + uint32 currentConfigVersion = 0; + uint256 numSigners = s_signers.length; + RMNRemote.Config memory config = + RMNRemote.Config({rmnHomeContractConfigDigest: _randomBytes32(), signers: s_signers, minSigners: 0}); + + vm.expectEmit(); + emit RMNRemote.ConfigSet(++currentConfigVersion, config); + + s_rmnRemote.setConfig(config); + + // add a signer + address newSigner = makeAddr("new signer"); + s_signers.push(RMNRemote.Signer({onchainPublicKey: newSigner, nodeIndex: uint64(numSigners)})); + config = RMNRemote.Config({rmnHomeContractConfigDigest: _randomBytes32(), signers: s_signers, minSigners: 0}); + + vm.expectEmit(); + emit RMNRemote.ConfigSet(++currentConfigVersion, config); + + s_rmnRemote.setConfig(config); + + (uint32 version, RMNRemote.Config memory gotConfig) = s_rmnRemote.getVersionedConfig(); + assertEq(gotConfig.signers.length, s_signers.length); + assertEq(gotConfig.signers[numSigners].onchainPublicKey, newSigner); + assertEq(gotConfig.signers[numSigners].nodeIndex, uint64(numSigners)); + assertEq(version, currentConfigVersion); + + // remove two signers + s_signers.pop(); + s_signers.pop(); + config = RMNRemote.Config({rmnHomeContractConfigDigest: _randomBytes32(), signers: s_signers, minSigners: 0}); + + vm.expectEmit(); + emit RMNRemote.ConfigSet(++currentConfigVersion, config); + + s_rmnRemote.setConfig(config); + + (version, gotConfig) = s_rmnRemote.getVersionedConfig(); + assertEq(gotConfig.signers.length, s_signers.length); + assertEq(version, currentConfigVersion); + } + + function test_setConfig_invalidSignerOrder_reverts() public { + s_signers.push(RMNRemote.Signer({onchainPublicKey: address(4), nodeIndex: 0})); + RMNRemote.Config memory config = + RMNRemote.Config({rmnHomeContractConfigDigest: _randomBytes32(), signers: s_signers, minSigners: 0}); + + vm.expectRevert(RMNRemote.InvalidSignerOrder.selector); + s_rmnRemote.setConfig(config); + } + + function test_setConfig_minSignersTooHigh_reverts() public { + RMNRemote.Config memory config = RMNRemote.Config({ + rmnHomeContractConfigDigest: _randomBytes32(), + signers: s_signers, + minSigners: uint64(s_signers.length + 1) + }); + + vm.expectRevert(RMNRemote.MinSignersTooHigh.selector); + s_rmnRemote.setConfig(config); + } + + function test_setConfig_duplicateOnChainPublicKey_reverts() public { + s_signers.push(RMNRemote.Signer({onchainPublicKey: s_signerWallets[0].addr, nodeIndex: uint64(s_signers.length)})); + RMNRemote.Config memory config = + RMNRemote.Config({rmnHomeContractConfigDigest: _randomBytes32(), signers: s_signers, minSigners: 0}); + + vm.expectRevert(RMNRemote.DuplicateOnchainPublicKey.selector); + s_rmnRemote.setConfig(config); + } +} + +contract RMNRemote_verify_withConfigNotSet is RMNRemoteSetup { + function test_verify_reverts() public { + Internal.MerkleRoot[] memory merkleRoots = new Internal.MerkleRoot[](0); + IRMNV2.Signature[] memory signatures = new IRMNV2.Signature[](0); + + vm.expectRevert(RMNRemote.ConfigNotSet.selector); + s_rmnRemote.verify(OFF_RAMP_ADDRESS, merkleRoots, signatures, 0); + } +} + +contract RMNRemote_verify_withConfigSet is RMNRemoteSetup { + function setUp() public override { + super.setUp(); + RMNRemote.Config memory config = + RMNRemote.Config({rmnHomeContractConfigDigest: _randomBytes32(), signers: s_signers, minSigners: 2}); + s_rmnRemote.setConfig(config); + _generatePayloadAndSigs(2, 2); + } + + function test_verify_success() public view { + s_rmnRemote.verify(OFF_RAMP_ADDRESS, s_merkleRoots, s_signatures, s_v); + } + + function test_verify_minSignersIsZero_success() public { + vm.stopPrank(); + vm.prank(OWNER); + s_rmnRemote.setConfig( + RMNRemote.Config({rmnHomeContractConfigDigest: _randomBytes32(), signers: s_signers, minSigners: 0}) + ); + + vm.stopPrank(); + vm.prank(OFF_RAMP_ADDRESS); + s_rmnRemote.verify(OFF_RAMP_ADDRESS, s_merkleRoots, new IRMNV2.Signature[](0), s_v); + } + + function test_verify_InvalidSignature_reverts() public { + IRMNV2.Signature memory sig = s_signatures[s_signatures.length - 1]; + sig.r = _randomBytes32(); + s_signatures.pop(); + s_signatures.push(sig); + + vm.expectRevert(RMNRemote.InvalidSignature.selector); + s_rmnRemote.verify(OFF_RAMP_ADDRESS, s_merkleRoots, s_signatures, s_v); + } + + function test_verify_OutOfOrderSignatures_not_sorted_reverts() public { + IRMNV2.Signature memory sig1 = s_signatures[s_signatures.length - 1]; + s_signatures.pop(); + IRMNV2.Signature memory sig2 = s_signatures[s_signatures.length - 1]; + s_signatures.pop(); + s_signatures.push(sig1); + s_signatures.push(sig2); + + vm.expectRevert(RMNRemote.OutOfOrderSignatures.selector); + s_rmnRemote.verify(OFF_RAMP_ADDRESS, s_merkleRoots, s_signatures, s_v); + } + + function test_verify_OutOfOrderSignatures_duplicateSignature_reverts() public { + IRMNV2.Signature memory sig = s_signatures[s_signatures.length - 2]; + s_signatures.pop(); + s_signatures.push(sig); + + vm.expectRevert(RMNRemote.OutOfOrderSignatures.selector); + s_rmnRemote.verify(OFF_RAMP_ADDRESS, s_merkleRoots, s_signatures, s_v); + } + + function test_verify_UnexpectedSigner_reverts() public { + _setupSigners(2); // create 2 new signers that aren't configured on RMNRemote + _generatePayloadAndSigs(2, 2); + + vm.expectRevert(RMNRemote.UnexpectedSigner.selector); + s_rmnRemote.verify(OFF_RAMP_ADDRESS, s_merkleRoots, s_signatures, s_v); + } + + function test_verify_ThresholdNotMet_reverts() public { + _generatePayloadAndSigs(2, 1); // 1 sig requested, but 2 required + + vm.expectRevert(RMNRemote.ThresholdNotMet.selector); + s_rmnRemote.verify(OFF_RAMP_ADDRESS, s_merkleRoots, s_signatures, s_v); + } +} + +contract RMNRemote_curse is RMNRemoteSetup { + function test_curse_success() public { + vm.expectEmit(); + emit RMNRemote.Cursed(s_curseSubjects); + + s_rmnRemote.curse(s_curseSubjects); + + assertEq(abi.encode(s_rmnRemote.getCursedSubjects()), abi.encode(s_curseSubjects)); + assertTrue(s_rmnRemote.isCursed(curseSubj1)); + assertTrue(s_rmnRemote.isCursed(curseSubj2)); + // Should not have cursed a random subject + assertFalse(s_rmnRemote.isCursed(bytes16(keccak256("subject 3")))); + } + + function test_curse_AlreadyCursed_duplicateSubject_reverts() public { + s_curseSubjects.push(curseSubj1); + + vm.expectRevert(abi.encodeWithSelector(RMNRemote.AlreadyCursed.selector, curseSubj1)); + s_rmnRemote.curse(s_curseSubjects); + } + + function test_curse_calledByNonOwner_reverts() public { + vm.expectRevert("Only callable by owner"); + vm.stopPrank(); + vm.prank(STRANGER); + s_rmnRemote.curse(s_curseSubjects); + } +} + +contract RMNRemote_uncurse is RMNRemoteSetup { + function setUp() public override { + super.setUp(); + s_rmnRemote.curse(s_curseSubjects); + } + + function test_uncurse_success() public { + vm.expectEmit(); + emit RMNRemote.Uncursed(s_curseSubjects); + + s_rmnRemote.uncurse(s_curseSubjects); + + assertEq(s_rmnRemote.getCursedSubjects().length, 0); + assertFalse(s_rmnRemote.isCursed(curseSubj1)); + assertFalse(s_rmnRemote.isCursed(curseSubj2)); + } + + function test_uncurse_NotCursed_duplicatedUncurseSubject_reverts() public { + s_curseSubjects.push(curseSubj1); + + vm.expectRevert(abi.encodeWithSelector(RMNRemote.NotCursed.selector, curseSubj1)); + s_rmnRemote.uncurse(s_curseSubjects); + } + + function test_uncurse_calledByNonOwner_reverts() public { + vm.expectRevert("Only callable by owner"); + vm.stopPrank(); + vm.prank(STRANGER); + s_rmnRemote.uncurse(s_curseSubjects); + } +} + +contract RMNRemote_global_and_legacy_curses is RMNRemoteSetup { + function test_global_and_legacy_curses_success() public { + bytes16 randSubject = bytes16(keccak256("random subject")); + assertFalse(s_rmnRemote.isCursed()); + assertFalse(s_rmnRemote.isCursed(randSubject)); + + s_rmnRemote.curse(GLOBAL_CURSE_SUBJECT); + assertTrue(s_rmnRemote.isCursed()); + assertTrue(s_rmnRemote.isCursed(randSubject)); + + s_rmnRemote.uncurse(GLOBAL_CURSE_SUBJECT); + assertFalse(s_rmnRemote.isCursed()); + assertFalse(s_rmnRemote.isCursed(randSubject)); + + s_rmnRemote.curse(LEGACY_CURSE_SUBJECT); + assertTrue(s_rmnRemote.isCursed()); + assertFalse(s_rmnRemote.isCursed(randSubject)); // legacy curse doesn't affect specific subjects + + s_rmnRemote.uncurse(LEGACY_CURSE_SUBJECT); + assertFalse(s_rmnRemote.isCursed()); + assertFalse(s_rmnRemote.isCursed(randSubject)); + } +} diff --git a/contracts/src/v0.8/ccip/test/rmn/RMNRemoteSetup.t.sol b/contracts/src/v0.8/ccip/test/rmn/RMNRemoteSetup.t.sol new file mode 100644 index 0000000000..01bd5bd1b6 --- /dev/null +++ b/contracts/src/v0.8/ccip/test/rmn/RMNRemoteSetup.t.sol @@ -0,0 +1,144 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.24; + +import {IRMNV2} from "../../interfaces/IRMNV2.sol"; +import {Internal} from "../../libraries/Internal.sol"; +import {RMNRemote, RMN_V1_6_ANY2EVM_REPORT} from "../../rmn/RMNRemote.sol"; +import {BaseTest} from "../BaseTest.t.sol"; +import {Vm} from "forge-std/Vm.sol"; + +import "forge-std/console.sol"; + +contract RMNRemoteSetup is BaseTest { + RMNRemote public s_rmnRemote; + address public OFF_RAMP_ADDRESS; + + RMNRemote.Signer[] public s_signers; + Vm.Wallet[] public s_signerWallets; + + Internal.MerkleRoot[] s_merkleRoots; + IRMNV2.Signature[] s_signatures; + uint256 internal s_v; + + bytes16 internal constant curseSubj1 = bytes16(keccak256("subject 1")); + bytes16 internal constant curseSubj2 = bytes16(keccak256("subject 2")); + bytes16[] internal s_curseSubjects; + + function setUp() public virtual override { + super.setUp(); + s_rmnRemote = new RMNRemote(1); + OFF_RAMP_ADDRESS = makeAddr("OFF RAMP"); + s_curseSubjects = [curseSubj1, curseSubj2]; + + _setupSigners(10); + } + + /// @notice sets up a list of signers with strictly increasing onchain public keys + /// @dev signers do not have to be in order when configured, but they do when generating signatures + /// rather than sort signers every time, we do it once here and store the sorted list + function _setupSigners(uint256 numSigners) internal { + // remove any existing config + while (s_signerWallets.length > 0) { + s_signerWallets.pop(); + } + while (s_signers.length > 0) { + s_signers.pop(); + } + + for (uint256 i = 0; i < numSigners; i++) { + s_signerWallets.push(vm.createWallet(_randomNum())); + } + + _sort(s_signerWallets); + + for (uint256 i = 0; i < numSigners; i++) { + s_signers.push(RMNRemote.Signer({onchainPublicKey: s_signerWallets[i].addr, nodeIndex: uint64(i)})); + } + } + + /// @notice generates n merkleRoots and matching valid signatures and populates them into + /// the shared storage vars + function _generatePayloadAndSigs(uint256 numUpdates, uint256 numSigs) internal { + require(numUpdates > 0, "need at least 1 dest lane update"); + require(numSigs <= s_signerWallets.length, "cannot generate more sigs than signers"); + + // remove any existing merkleRoots and sigs + while (s_merkleRoots.length > 0) { + s_merkleRoots.pop(); + } + while (s_signatures.length > 0) { + s_signatures.pop(); + } + s_v = 0; + + for (uint256 i = 0; i < numUpdates; i++) { + s_merkleRoots.push(_generateRandomDestLaneUpdate()); + } + + for (uint256 i = 0; i < numSigs; i++) { + (uint8 v, IRMNV2.Signature memory sig) = _signDestLaneUpdate(s_merkleRoots, s_signerWallets[i]); + s_signatures.push(sig); + if (v == 28) { + s_v += 1 << i; + } + } + } + + /// @notice generates a random dest lane update + function _generateRandomDestLaneUpdate() private returns (Internal.MerkleRoot memory) { + uint64 minSeqNum = uint32(_randomNum()); + uint64 maxSeqNum = minSeqNum + 100; + return Internal.MerkleRoot({ + sourceChainSelector: uint64(_randomNum()), + onRampAddress: abi.encode(_randomAddress()), + minSeqNr: minSeqNum, + maxSeqNr: maxSeqNum, + merkleRoot: _randomBytes32() + }); + } + + /// @notice signs the provided payload with the provided wallet + /// @return sigV v, either 27 of 28 + /// @return sig the signature + function _signDestLaneUpdate( + Internal.MerkleRoot[] memory merkleRoots, + Vm.Wallet memory wallet + ) private returns (uint8 sigV, IRMNV2.Signature memory) { + (, RMNRemote.Config memory config) = s_rmnRemote.getVersionedConfig(); + bytes32 digest = keccak256( + abi.encode( + RMN_V1_6_ANY2EVM_REPORT, + RMNRemote.Report({ + destChainId: block.chainid, + destChainSelector: s_rmnRemote.getLocalChainSelector(), + rmnRemoteContractAddress: address(s_rmnRemote), + offrampAddress: OFF_RAMP_ADDRESS, + rmnHomeContractConfigDigest: config.rmnHomeContractConfigDigest, + merkleRoots: merkleRoots + }) + ) + ); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(wallet, digest); + return (v, IRMNV2.Signature({r: r, s: s})); + } + + /// @notice bubble sort on a storage array of wallets + function _sort(Vm.Wallet[] storage wallets) private { + bool swapped; + for (uint256 i = 1; i < wallets.length; i++) { + swapped = false; + for (uint256 j = 0; j < wallets.length - i; j++) { + Vm.Wallet memory next = wallets[j + 1]; + Vm.Wallet memory actual = wallets[j]; + if (next.addr < actual.addr) { + wallets[j] = next; + wallets[j + 1] = actual; + swapped = true; + } + } + if (!swapped) { + return; + } + } + } +} diff --git a/contracts/src/v0.8/shared/enumerable/EnumerableSetWithBytes16.sol b/contracts/src/v0.8/shared/enumerable/EnumerableSetWithBytes16.sol new file mode 100644 index 0000000000..b78096773a --- /dev/null +++ b/contracts/src/v0.8/shared/enumerable/EnumerableSetWithBytes16.sol @@ -0,0 +1,454 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/EnumerableSet.sol) +// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js. + +/// @dev this is a fully copy of OZ's EnumerableSet library with the addition of a Bytes16Set + +pragma solidity ^0.8.0; + +/** + * @dev Library for managing + * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive + * types. + * + * Sets have the following properties: + * + * - Elements are added, removed, and checked for existence in constant time + * (O(1)). + * - Elements are enumerated in O(n). No guarantees are made on the ordering. + * + * ```solidity + * contract Example { + * // Add the library methods + * using EnumerableSet for EnumerableSet.AddressSet; + * + * // Declare a set state variable + * EnumerableSet.AddressSet private mySet; + * } + * ``` + * + * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) + * and `uint256` (`UintSet`) are supported. + * + * [WARNING] + * ==== + * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure + * unusable. + * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. + * + * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an + * array of EnumerableSet. + * ==== + */ +library EnumerableSet { + // To implement this library for multiple types with as little code + // repetition as possible, we write it in terms of a generic Set type with + // bytes32 values. + // The Set implementation uses private functions, and user-facing + // implementations (such as AddressSet) are just wrappers around the + // underlying Set. + // This means that we can only create new EnumerableSets for types that fit + // in bytes32. + + struct Set { + // Storage of set values + bytes32[] _values; + // Position is the index of the value in the `values` array plus 1. + // Position 0 is used to mean a value is not in the set. + mapping(bytes32 value => uint256) _positions; + } + + /** + * @dev Add a value to a set. O(1). + * + * Returns true if the value was added to the set, that is if it was not + * already present. + */ + function _add(Set storage set, bytes32 value) private returns (bool) { + if (!_contains(set, value)) { + set._values.push(value); + // The value is stored at length-1, but we add 1 to all indexes + // and use 0 as a sentinel value + set._positions[value] = set._values.length; + return true; + } else { + return false; + } + } + + /** + * @dev Removes a value from a set. O(1). + * + * Returns true if the value was removed from the set, that is if it was + * present. + */ + function _remove(Set storage set, bytes32 value) private returns (bool) { + // We cache the value's position to prevent multiple reads from the same storage slot + uint256 position = set._positions[value]; + + if (position != 0) { + // Equivalent to contains(set, value) + // To delete an element from the _values array in O(1), we swap the element to delete with the last one in + // the array, and then remove the last element (sometimes called as 'swap and pop'). + // This modifies the order of the array, as noted in {at}. + + uint256 valueIndex = position - 1; + uint256 lastIndex = set._values.length - 1; + + if (valueIndex != lastIndex) { + bytes32 lastValue = set._values[lastIndex]; + + // Move the lastValue to the index where the value to delete is + set._values[valueIndex] = lastValue; + // Update the tracked position of the lastValue (that was just moved) + set._positions[lastValue] = position; + } + + // Delete the slot where the moved value was stored + set._values.pop(); + + // Delete the tracked position for the deleted slot + delete set._positions[value]; + + return true; + } else { + return false; + } + } + + /** + * @dev Returns true if the value is in the set. O(1). + */ + function _contains(Set storage set, bytes32 value) private view returns (bool) { + return set._positions[value] != 0; + } + + /** + * @dev Returns the number of values on the set. O(1). + */ + function _length(Set storage set) private view returns (uint256) { + return set._values.length; + } + + /** + * @dev Returns the value stored at position `index` in the set. O(1). + * + * Note that there are no guarantees on the ordering of values inside the + * array, and it may change when more values are added or removed. + * + * Requirements: + * + * - `index` must be strictly less than {length}. + */ + function _at(Set storage set, uint256 index) private view returns (bytes32) { + return set._values[index]; + } + + /** + * @dev Return the entire set in an array + * + * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed + * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that + * this function has an unbounded cost, and using it as part of a state-changing function may render the function + * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. + */ + function _values(Set storage set) private view returns (bytes32[] memory) { + return set._values; + } + + // Bytes32Set + + struct Bytes32Set { + Set _inner; + } + + /** + * @dev Add a value to a set. O(1). + * + * Returns true if the value was added to the set, that is if it was not + * already present. + */ + function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { + return _add(set._inner, value); + } + + /** + * @dev Removes a value from a set. O(1). + * + * Returns true if the value was removed from the set, that is if it was + * present. + */ + function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { + return _remove(set._inner, value); + } + + /** + * @dev Returns true if the value is in the set. O(1). + */ + function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { + return _contains(set._inner, value); + } + + /** + * @dev Returns the number of values in the set. O(1). + */ + function length(Bytes32Set storage set) internal view returns (uint256) { + return _length(set._inner); + } + + /** + * @dev Returns the value stored at position `index` in the set. O(1). + * + * Note that there are no guarantees on the ordering of values inside the + * array, and it may change when more values are added or removed. + * + * Requirements: + * + * - `index` must be strictly less than {length}. + */ + function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { + return _at(set._inner, index); + } + + /** + * @dev Return the entire set in an array + * + * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed + * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that + * this function has an unbounded cost, and using it as part of a state-changing function may render the function + * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. + */ + function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { + bytes32[] memory store = _values(set._inner); + bytes32[] memory result; + + /// @solidity memory-safe-assembly + assembly { + result := store + } + + return result; + } + + // AddressSet + + struct AddressSet { + Set _inner; + } + + /** + * @dev Add a value to a set. O(1). + * + * Returns true if the value was added to the set, that is if it was not + * already present. + */ + function add(AddressSet storage set, address value) internal returns (bool) { + return _add(set._inner, bytes32(uint256(uint160(value)))); + } + + /** + * @dev Removes a value from a set. O(1). + * + * Returns true if the value was removed from the set, that is if it was + * present. + */ + function remove(AddressSet storage set, address value) internal returns (bool) { + return _remove(set._inner, bytes32(uint256(uint160(value)))); + } + + /** + * @dev Returns true if the value is in the set. O(1). + */ + function contains(AddressSet storage set, address value) internal view returns (bool) { + return _contains(set._inner, bytes32(uint256(uint160(value)))); + } + + /** + * @dev Returns the number of values in the set. O(1). + */ + function length(AddressSet storage set) internal view returns (uint256) { + return _length(set._inner); + } + + /** + * @dev Returns the value stored at position `index` in the set. O(1). + * + * Note that there are no guarantees on the ordering of values inside the + * array, and it may change when more values are added or removed. + * + * Requirements: + * + * - `index` must be strictly less than {length}. + */ + function at(AddressSet storage set, uint256 index) internal view returns (address) { + return address(uint160(uint256(_at(set._inner, index)))); + } + + /** + * @dev Return the entire set in an array + * + * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed + * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that + * this function has an unbounded cost, and using it as part of a state-changing function may render the function + * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. + */ + function values(AddressSet storage set) internal view returns (address[] memory) { + bytes32[] memory store = _values(set._inner); + address[] memory result; + + /// @solidity memory-safe-assembly + assembly { + result := store + } + + return result; + } + + // UintSet + + struct UintSet { + Set _inner; + } + + /** + * @dev Add a value to a set. O(1). + * + * Returns true if the value was added to the set, that is if it was not + * already present. + */ + function add(UintSet storage set, uint256 value) internal returns (bool) { + return _add(set._inner, bytes32(value)); + } + + /** + * @dev Removes a value from a set. O(1). + * + * Returns true if the value was removed from the set, that is if it was + * present. + */ + function remove(UintSet storage set, uint256 value) internal returns (bool) { + return _remove(set._inner, bytes32(value)); + } + + /** + * @dev Returns true if the value is in the set. O(1). + */ + function contains(UintSet storage set, uint256 value) internal view returns (bool) { + return _contains(set._inner, bytes32(value)); + } + + /** + * @dev Returns the number of values in the set. O(1). + */ + function length(UintSet storage set) internal view returns (uint256) { + return _length(set._inner); + } + + /** + * @dev Returns the value stored at position `index` in the set. O(1). + * + * Note that there are no guarantees on the ordering of values inside the + * array, and it may change when more values are added or removed. + * + * Requirements: + * + * - `index` must be strictly less than {length}. + */ + function at(UintSet storage set, uint256 index) internal view returns (uint256) { + return uint256(_at(set._inner, index)); + } + + /** + * @dev Return the entire set in an array + * + * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed + * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that + * this function has an unbounded cost, and using it as part of a state-changing function may render the function + * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. + */ + function values(UintSet storage set) internal view returns (uint256[] memory) { + bytes32[] memory store = _values(set._inner); + uint256[] memory result; + + /// @solidity memory-safe-assembly + assembly { + result := store + } + + return result; + } + + // Bytes16Set + + struct Bytes16Set { + Set _inner; + } + + /** + * @dev Add a value to a set. O(1). + * + * Returns true if the value was added to the set, that is if it was not + * already present. + */ + function add(Bytes16Set storage set, bytes16 value) internal returns (bool) { + return _add(set._inner, bytes32(value)); + } + + /** + * @dev Removes a value from a set. O(1). + * + * Returns true if the value was removed from the set, that is if it was + * present. + */ + function remove(Bytes16Set storage set, bytes16 value) internal returns (bool) { + return _remove(set._inner, bytes32(value)); + } + + /** + * @dev Returns true if the value is in the set. O(1). + */ + function contains(Bytes16Set storage set, bytes16 value) internal view returns (bool) { + return _contains(set._inner, bytes32(value)); + } + + /** + * @dev Returns the number of values in the set. O(1). + */ + function length(Bytes16Set storage set) internal view returns (uint256) { + return _length(set._inner); + } + + /** + * @dev Returns the value stored at position `index` in the set. O(1). + * + * Note that there are no guarantees on the ordering of values inside the + * array, and it may change when more values are added or removed. + * + * Requirements: + * + * - `index` must be strictly less than {length}. + */ + function at(Bytes16Set storage set, uint256 index) internal view returns (bytes16) { + return bytes16(_at(set._inner, index)); + } + + /** + * @dev Return the entire set in an array + * + * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed + * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that + * this function has an unbounded cost, and using it as part of a state-changing function may render the function + * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. + */ + function values(Bytes16Set storage set) internal view returns (bytes16[] memory) { + bytes32[] memory store = _values(set._inner); + bytes16[] memory result; + + /// @solidity memory-safe-assembly + assembly { + result := store + } + + return result; + } +} diff --git a/core/gethwrappers/ccip/generated/ccip_encoding_utils/ccip_encoding_utils.go b/core/gethwrappers/ccip/generated/ccip_encoding_utils/ccip_encoding_utils.go index 60daca1c57..6331211b4b 100644 --- a/core/gethwrappers/ccip/generated/ccip_encoding_utils/ccip_encoding_utils.go +++ b/core/gethwrappers/ccip/generated/ccip_encoding_utils/ccip_encoding_utils.go @@ -42,11 +42,11 @@ type RMNRemoteReport struct { RmnRemoteContractAddress common.Address OfframpAddress common.Address RmnHomeContractConfigDigest [32]byte - DestLaneUpdates []InternalMerkleRoot + MerkleRoots []InternalMerkleRoot } var EncodingUtilsMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"DoNotDeploy\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"rmnReportVersion\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"destChainId\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnRemoteContractAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"offrampAddress\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"rmnHomeContractConfigDigest\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"destLaneUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structRMNRemote.Report\",\"name\":\"rmnReport\",\"type\":\"tuple\"}],\"name\":\"_rmnReport\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + ABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"DoNotDeploy\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"rmnReportVersion\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"destChainId\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"rmnRemoteContractAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"offrampAddress\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"rmnHomeContractConfigDigest\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"}],\"internalType\":\"structRMNRemote.Report\",\"name\":\"rmnReport\",\"type\":\"tuple\"}],\"name\":\"_rmnReport\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", Bin: "0x608060405234801561001057600080fd5b50604051636f1e4f5f60e01b815260040160405180910390fdfe", } diff --git a/core/gethwrappers/ccip/generated/ccip_reader_tester/ccip_reader_tester.go b/core/gethwrappers/ccip/generated/ccip_reader_tester/ccip_reader_tester.go index 127de4a3c8..efdc46ebf2 100644 --- a/core/gethwrappers/ccip/generated/ccip_reader_tester/ccip_reader_tester.go +++ b/core/gethwrappers/ccip/generated/ccip_reader_tester/ccip_reader_tester.go @@ -89,6 +89,7 @@ type OffRampCommitReport struct { PriceUpdates InternalPriceUpdates MerkleRoots []InternalMerkleRoot RmnSignatures []IRMNV2Signature + RmnRawVs *big.Int } type OffRampSourceChainConfig struct { @@ -99,8 +100,8 @@ type OffRampSourceChainConfig struct { } var CCIPReaderTesterMetaData = &bind.MetaData{ - ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"sourcePoolAddress\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.EVM2AnyTokenTransfer[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"CCIPSendRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"structIRMNV2.Signature[]\",\"name\":\"rmnSignatures\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"report\",\"type\":\"tuple\"}],\"name\":\"CommitReportAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"name\":\"ExecutionStateChanged\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"sourcePoolAddress\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.EVM2AnyTokenTransfer[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"emitCCIPSendRequested\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"structIRMNV2.Signature[]\",\"name\":\"rmnSignatures\",\"type\":\"tuple[]\"}],\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"report\",\"type\":\"tuple\"}],\"name\":\"emitCommitReportAccepted\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"name\":\"emitExecutionStateChanged\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getExpectedNextSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"getSourceChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"setDestChainSeqNr\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"sourceChainConfig\",\"type\":\"tuple\"}],\"name\":\"setSourceChainConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x608060405234801561001057600080fd5b506113d9806100206000396000f3fe608060405234801561001057600080fd5b506004361061006d5760003560e01c80634cf66e36146100725780639041be3d14610087578063bfc9b789146100b7578063c1a5a355146100ca578063e4d0223414610106578063e83eabba14610119578063e9d68a8e1461012c575b600080fd5b610085610080366004610571565b61014c565b005b61009a6100953660046105ef565b6101a1565b6040516001600160401b0390911681526020015b60405180910390f35b6100856100c536600461087f565b6101d0565b6100856100d8366004610a09565b6001600160401b03918216600090815260016020526040902080546001600160401b03191691909216179055565b610085610114366004610bca565b61020a565b610085610127366004610cf8565b61024f565b61013f61013a3660046105ef565b6102db565b6040516100ae9190610df9565b82846001600160401b0316866001600160401b03167f8c324ce1367b83031769f6a813e3bb4c117aba2185789d66b98b791405be6df28585604051610192929190610e51565b60405180910390a45050505050565b6001600160401b03808216600090815260016020819052604082205491926101ca921690610e88565b92915050565b7f23bc80217a08968cec0790cd045b396fa7eea0a21af469e603329940b883d86d816040516101ff9190611001565b60405180910390a150565b816001600160401b03167fe07a589f12eccf1bc0f7421666687a6986a0c8dbbdc877d1af562a97ba60ecfd826040516102439190611180565b60405180910390a25050565b6001600160401b0380831660009081526020818152604091829020845181549286015193860151909416600160a81b02600160a81b600160e81b0319931515600160a01b026001600160a81b03199093166001600160a01b03909516949094179190911791909116919091178155606082015182919060018201906102d4908261130d565b5050505050565b60408051608080820183526000808352602080840182905283850182905260608085018190526001600160401b038781168452838352928690208651948501875280546001600160a01b0381168652600160a01b810460ff16151593860193909352600160a81b90920490921694830194909452600184018054939492939184019161036690611282565b80601f016020809104026020016040519081016040528092919081815260200182805461039290611282565b80156103df5780601f106103b4576101008083540402835291602001916103df565b820191906000526020600020905b8154815290600101906020018083116103c257829003601f168201915b5050505050815250509050919050565b80356001600160401b038116811461040657600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b03811182821017156104435761044361040b565b60405290565b60405160a081016001600160401b03811182821017156104435761044361040b565b604051606081016001600160401b03811182821017156104435761044361040b565b60405161010081016001600160401b03811182821017156104435761044361040b565b604051608081016001600160401b03811182821017156104435761044361040b565b604051601f8201601f191681016001600160401b03811182821017156104fa576104fa61040b565b604052919050565b600082601f83011261051357600080fd5b81356001600160401b0381111561052c5761052c61040b565b61053f601f8201601f19166020016104d2565b81815284602083860101111561055457600080fd5b816020850160208301376000918101602001919091529392505050565b600080600080600060a0868803121561058957600080fd5b610592866103ef565b94506105a0602087016103ef565b9350604086013592506060860135600481106105bb57600080fd5b915060808601356001600160401b038111156105d657600080fd5b6105e288828901610502565b9150509295509295909350565b60006020828403121561060157600080fd5b61060a826103ef565b9392505050565b60006001600160401b0382111561062a5761062a61040b565b5060051b60200190565b6001600160a01b038116811461064957600080fd5b50565b803561040681610634565b80356001600160e01b038116811461040657600080fd5b600082601f83011261067f57600080fd5b8135602061069461068f83610611565b6104d2565b82815260069290921b840181019181810190868411156106b357600080fd5b8286015b8481101561070057604081890312156106d05760008081fd5b6106d8610421565b6106e1826103ef565b81526106ee858301610657565b818601528352918301916040016106b7565b509695505050505050565b600082601f83011261071c57600080fd5b8135602061072c61068f83610611565b82815260059290921b8401810191818101908684111561074b57600080fd5b8286015b848110156107005780356001600160401b038082111561076f5760008081fd5b9088019060a0828b03601f19018113156107895760008081fd5b610791610449565b61079c8885016103ef565b8152604080850135848111156107b25760008081fd5b6107c08e8b83890101610502565b8a84015250606093506107d48486016103ef565b9082015260806107e58582016103ef565b9382019390935292013590820152835291830191830161074f565b600082601f83011261081157600080fd5b8135602061082161068f83610611565b82815260069290921b8401810191818101908684111561084057600080fd5b8286015b84811015610700576040818903121561085d5760008081fd5b610865610421565b813581528482013585820152835291830191604001610844565b6000602080838503121561089257600080fd5b82356001600160401b03808211156108a957600080fd5b90840190606082870312156108bd57600080fd5b6108c561046b565b8235828111156108d457600080fd5b830160408189038113156108e757600080fd5b6108ef610421565b8235858111156108fe57600080fd5b8301601f81018b1361090f57600080fd5b803561091d61068f82610611565b81815260069190911b8201890190898101908d83111561093c57600080fd5b928a01925b8284101561098c5785848f0312156109595760008081fd5b610961610421565b843561096c81610634565b8152610979858d01610657565b818d0152825292850192908a0190610941565b8452505050828701359150848211156109a457600080fd5b6109b08a83850161066e565b818801528352505082840135828111156109c957600080fd5b6109d58882860161070b565b858301525060408301359350818411156109ee57600080fd5b6109fa87858501610800565b60408201529695505050505050565b60008060408385031215610a1c57600080fd5b610a25836103ef565b9150610a33602084016103ef565b90509250929050565b600060a08284031215610a4e57600080fd5b610a56610449565b905081358152610a68602083016103ef565b6020820152610a79604083016103ef565b6040820152610a8a606083016103ef565b6060820152610a9b608083016103ef565b608082015292915050565b600082601f830112610ab757600080fd5b81356020610ac761068f83610611565b82815260059290921b84018101918181019086841115610ae657600080fd5b8286015b848110156107005780356001600160401b0380821115610b0a5760008081fd5b9088019060a0828b03601f1901811315610b245760008081fd5b610b2c610449565b610b3788850161064c565b815260408085013584811115610b4d5760008081fd5b610b5b8e8b83890101610502565b8a8401525060608086013585811115610b745760008081fd5b610b828f8c838a0101610502565b83850152506080915081860135818401525082850135925083831115610ba85760008081fd5b610bb68d8a85880101610502565b908201528652505050918301918301610aea565b60008060408385031215610bdd57600080fd5b610be6836103ef565b915060208301356001600160401b0380821115610c0257600080fd5b908401906101808287031215610c1757600080fd5b610c1f61048d565b610c298784610a3c565b8152610c3760a0840161064c565b602082015260c083013582811115610c4e57600080fd5b610c5a88828601610502565b60408301525060e083013582811115610c7257600080fd5b610c7e88828601610502565b60608301525061010083013582811115610c9757600080fd5b610ca388828601610502565b608083015250610cb6610120840161064c565b60a082015261014083013560c082015261016083013582811115610cd957600080fd5b610ce588828601610aa6565b60e0830152508093505050509250929050565b60008060408385031215610d0b57600080fd5b610d14836103ef565b915060208301356001600160401b0380821115610d3057600080fd5b9084019060808287031215610d4457600080fd5b610d4c6104b0565b8235610d5781610634565b815260208301358015158114610d6c57600080fd5b6020820152610d7d604084016103ef565b6040820152606083013582811115610d9457600080fd5b610da088828601610502565b6060830152508093505050509250929050565b6000815180845260005b81811015610dd957602081850181015186830182015201610dbd565b506000602082860101526020601f19601f83011685010191505092915050565b602080825282516001600160a01b03168282015282015115156040808301919091528201516001600160401b0316606080830191909152820151608080830152600090610e4960a0840182610db3565b949350505050565b600060048410610e7157634e487b7160e01b600052602160045260246000fd5b83825260406020830152610e496040830184610db3565b6001600160401b03818116838216019080821115610eb657634e487b7160e01b600052601160045260246000fd5b5092915050565b6001600160a01b03169052565b60008151808452602080850194506020840160005b83811015610f1857815180516001600160401b031688528301516001600160e01b03168388015260409096019590820190600101610edf565b509495945050505050565b600082825180855260208086019550808260051b84010181860160005b84811015610fb857858303601f19018952815180516001600160401b0390811685528582015160a08787018190529190610f7c83880182610db3565b60408581015184169089015260608086015190931692880192909252506080928301519290950191909152509783019790830190600101610f40565b5090979650505050505050565b60008151808452602080850194506020840160005b83811015610f18578151805188528301518388015260409096019590820190600101610fda565b602080825282516060838301528051604060808501819052815160c086018190526000949392840191859160e08801905b8084101561106d57845180516001600160a01b031683528701516001600160e01b031687830152938601936001939093019290820190611032565b5093850151878503607f190160a0890152936110898186610eca565b945050505050818501519150601f19808583030160408601526110ac8284610f23565b92506040860151915080858403016060860152506110ca8282610fc5565b95945050505050565b600082825180855260208086019550808260051b84010181860160005b84811015610fb857858303601f19018952815180516001600160a01b031684528481015160a08686018190529061112982870182610db3565b915050604080830151868303828801526111438382610db3565b9250505060608083015181870152506080808301519250858203818701525061116c8183610db3565b9a86019a94505050908301906001016110f0565b602081526111cd602082018351805182526020808201516001600160401b039081169184019190915260408083015182169084015260608083015182169084015260809182015116910152565b600060208301516111e160c0840182610ebd565b5060408301516101808060e08501526111fe6101a0850183610db3565b91506060850151601f19808685030161010087015261121d8483610db3565b935060808701519150808685030161012087015261123b8483610db3565b935060a08701519150611252610140870183610ebd565b60c087015161016087015260e087015191508086850301838701525061127883826110d3565b9695505050505050565b600181811c9082168061129657607f821691505b6020821081036112b657634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115611308576000816000526020600020601f850160051c810160208610156112e55750805b601f850160051c820191505b81811015611304578281556001016112f1565b5050505b505050565b81516001600160401b038111156113265761132661040b565b61133a816113348454611282565b846112bc565b602080601f83116001811461136f57600084156113575750858301515b600019600386901b1c1916600185901b178555611304565b600085815260208120601f198616915b8281101561139e5788860151825594840194600190910190840161137f565b50858210156113bc5787850151600019600388901b60f8161c191681555b5050505050600190811b0190555056fea164736f6c6343000818000a", + ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"sourcePoolAddress\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.EVM2AnyTokenTransfer[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"CCIPSendRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"structIRMNV2.Signature[]\",\"name\":\"rmnSignatures\",\"type\":\"tuple[]\"},{\"internalType\":\"uint256\",\"name\":\"rmnRawVs\",\"type\":\"uint256\"}],\"indexed\":false,\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"report\",\"type\":\"tuple\"}],\"name\":\"CommitReportAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"name\":\"ExecutionStateChanged\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"sourcePoolAddress\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.EVM2AnyTokenTransfer[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"emitCCIPSendRequested\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"structIRMNV2.Signature[]\",\"name\":\"rmnSignatures\",\"type\":\"tuple[]\"},{\"internalType\":\"uint256\",\"name\":\"rmnRawVs\",\"type\":\"uint256\"}],\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"report\",\"type\":\"tuple\"}],\"name\":\"emitCommitReportAccepted\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"name\":\"emitExecutionStateChanged\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getExpectedNextSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"getSourceChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"setDestChainSeqNr\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"sourceChainConfig\",\"type\":\"tuple\"}],\"name\":\"setSourceChainConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x608060405234801561001057600080fd5b506113d3806100206000396000f3fe608060405234801561001057600080fd5b506004361061006d5760003560e01c8063198b821c146100725780634cf66e36146100875780639041be3d1461009a578063c1a5a355146100ca578063e4d0223414610106578063e83eabba14610119578063e9d68a8e1461012c575b600080fd5b6100856100803660046107bd565b61014c565b005b610085610095366004610954565b610186565b6100ad6100a83660046109d2565b6101db565b6040516001600160401b0390911681526020015b60405180910390f35b6100856100d83660046109f4565b6001600160401b03918216600090815260016020526040902080546001600160401b03191691909216179055565b610085610114366004610bb5565b61020a565b610085610127366004610ce3565b61024f565b61013f61013a3660046109d2565b6102db565b6040516100c19190610de4565b7f062172a2ae1a84d7c8d18965d6267b71d579aeca033bbd2e0548947798c3d4628160405161017b9190610f80565b60405180910390a150565b82846001600160401b0316866001600160401b03167f8c324ce1367b83031769f6a813e3bb4c117aba2185789d66b98b791405be6df285856040516101cc929190611061565b60405180910390a45050505050565b6001600160401b0380821660009081526001602081905260408220549192610204921690611098565b92915050565b816001600160401b03167fe07a589f12eccf1bc0f7421666687a6986a0c8dbbdc877d1af562a97ba60ecfd82604051610243919061117a565b60405180910390a25050565b6001600160401b0380831660009081526020818152604091829020845181549286015193860151909416600160a81b02600160a81b600160e81b0319931515600160a01b026001600160a81b03199093166001600160a01b03909516949094179190911791909116919091178155606082015182919060018201906102d49082611307565b5050505050565b60408051608080820183526000808352602080840182905283850182905260608085018190526001600160401b038781168452838352928690208651948501875280546001600160a01b0381168652600160a01b810460ff16151593860193909352600160a81b9092049092169483019490945260018401805493949293918401916103669061127c565b80601f01602080910402602001604051908101604052809291908181526020018280546103929061127c565b80156103df5780601f106103b4576101008083540402835291602001916103df565b820191906000526020600020905b8154815290600101906020018083116103c257829003601f168201915b5050505050815250509050919050565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b0381118282101715610427576104276103ef565b60405290565b60405160a081016001600160401b0381118282101715610427576104276103ef565b604051608081016001600160401b0381118282101715610427576104276103ef565b60405161010081016001600160401b0381118282101715610427576104276103ef565b604051601f8201601f191681016001600160401b03811182821017156104bc576104bc6103ef565b604052919050565b60006001600160401b038211156104dd576104dd6103ef565b5060051b60200190565b6001600160a01b03811681146104fc57600080fd5b50565b803561050a816104e7565b919050565b80356001600160e01b038116811461050a57600080fd5b80356001600160401b038116811461050a57600080fd5b600082601f83011261054e57600080fd5b8135602061056361055e836104c4565b610494565b82815260069290921b8401810191818101908684111561058257600080fd5b8286015b848110156105cf576040818903121561059f5760008081fd5b6105a7610405565b6105b082610526565b81526105bd85830161050f565b81860152835291830191604001610586565b509695505050505050565b600082601f8301126105eb57600080fd5b81356001600160401b03811115610604576106046103ef565b610617601f8201601f1916602001610494565b81815284602083860101111561062c57600080fd5b816020850160208301376000918101602001919091529392505050565b600082601f83011261065a57600080fd5b8135602061066a61055e836104c4565b82815260059290921b8401810191818101908684111561068957600080fd5b8286015b848110156105cf5780356001600160401b03808211156106ad5760008081fd5b9088019060a0828b03601f19018113156106c75760008081fd5b6106cf61042d565b6106da888501610526565b8152604080850135848111156106f05760008081fd5b6106fe8e8b838901016105da565b8a8401525060609350610712848601610526565b908201526080610723858201610526565b9382019390935292013590820152835291830191830161068d565b600082601f83011261074f57600080fd5b8135602061075f61055e836104c4565b82815260069290921b8401810191818101908684111561077e57600080fd5b8286015b848110156105cf576040818903121561079b5760008081fd5b6107a3610405565b813581528482013585820152835291830191604001610782565b600060208083850312156107d057600080fd5b82356001600160401b03808211156107e757600080fd5b90840190608082870312156107fb57600080fd5b61080361044f565b82358281111561081257600080fd5b8301604081890381131561082557600080fd5b61082d610405565b82358581111561083c57600080fd5b8301601f81018b1361084d57600080fd5b803561085b61055e826104c4565b81815260069190911b8201890190898101908d83111561087a57600080fd5b928a01925b828410156108ca5785848f0312156108975760008081fd5b61089f610405565b84356108aa816104e7565b81526108b7858d0161050f565b818d0152825292850192908a019061087f565b8452505050828701359150848211156108e257600080fd5b6108ee8a83850161053d565b8188015283525050828401358281111561090757600080fd5b61091388828601610649565b8583015250604083013593508184111561092c57600080fd5b6109388785850161073e565b6040820152606083013560608201528094505050505092915050565b600080600080600060a0868803121561096c57600080fd5b61097586610526565b945061098360208701610526565b93506040860135925060608601356004811061099e57600080fd5b915060808601356001600160401b038111156109b957600080fd5b6109c5888289016105da565b9150509295509295909350565b6000602082840312156109e457600080fd5b6109ed82610526565b9392505050565b60008060408385031215610a0757600080fd5b610a1083610526565b9150610a1e60208401610526565b90509250929050565b600060a08284031215610a3957600080fd5b610a4161042d565b905081358152610a5360208301610526565b6020820152610a6460408301610526565b6040820152610a7560608301610526565b6060820152610a8660808301610526565b608082015292915050565b600082601f830112610aa257600080fd5b81356020610ab261055e836104c4565b82815260059290921b84018101918181019086841115610ad157600080fd5b8286015b848110156105cf5780356001600160401b0380821115610af55760008081fd5b9088019060a0828b03601f1901811315610b0f5760008081fd5b610b1761042d565b610b228885016104ff565b815260408085013584811115610b385760008081fd5b610b468e8b838901016105da565b8a8401525060608086013585811115610b5f5760008081fd5b610b6d8f8c838a01016105da565b83850152506080915081860135818401525082850135925083831115610b935760008081fd5b610ba18d8a858801016105da565b908201528652505050918301918301610ad5565b60008060408385031215610bc857600080fd5b610bd183610526565b915060208301356001600160401b0380821115610bed57600080fd5b908401906101808287031215610c0257600080fd5b610c0a610471565b610c148784610a27565b8152610c2260a084016104ff565b602082015260c083013582811115610c3957600080fd5b610c45888286016105da565b60408301525060e083013582811115610c5d57600080fd5b610c69888286016105da565b60608301525061010083013582811115610c8257600080fd5b610c8e888286016105da565b608083015250610ca161012084016104ff565b60a082015261014083013560c082015261016083013582811115610cc457600080fd5b610cd088828601610a91565b60e0830152508093505050509250929050565b60008060408385031215610cf657600080fd5b610cff83610526565b915060208301356001600160401b0380821115610d1b57600080fd5b9084019060808287031215610d2f57600080fd5b610d3761044f565b8235610d42816104e7565b815260208301358015158114610d5757600080fd5b6020820152610d6860408401610526565b6040820152606083013582811115610d7f57600080fd5b610d8b888286016105da565b6060830152508093505050509250929050565b6000815180845260005b81811015610dc457602081850181015186830182015201610da8565b506000602082860101526020601f19601f83011685010191505092915050565b602080825282516001600160a01b03168282015282015115156040808301919091528201516001600160401b0316606080830191909152820151608080830152600090610e3460a0840182610d9e565b949350505050565b6001600160a01b03169052565b60008151808452602080850194506020840160005b83811015610e9757815180516001600160401b031688528301516001600160e01b03168388015260409096019590820190600101610e5e565b509495945050505050565b600082825180855260208086019550808260051b84010181860160005b84811015610f3757858303601f19018952815180516001600160401b0390811685528582015160a08787018190529190610efb83880182610d9e565b60408581015184169089015260608086015190931692880192909252506080928301519290950191909152509783019790830190600101610ebf565b5090979650505050505050565b60008151808452602080850194506020840160005b83811015610e97578151805188528301518388015260409096019590820190600101610f59565b602080825282516080838301528051604060a08501819052815160e08601819052600094939284019185916101008801905b80841015610fed57845180516001600160a01b031683528701516001600160e01b031687830152938601936001939093019290820190610fb2565b5093850151878503609f190160c0890152936110098186610e49565b945050505050818501519150601f198085830301604086015261102c8284610ea2565b925060408601519150808584030160608601525061104a8282610f44565b915050606084015160808401528091505092915050565b60006004841061108157634e487b7160e01b600052602160045260246000fd5b83825260406020830152610e346040830184610d9e565b6001600160401b038181168382160190808211156110c657634e487b7160e01b600052601160045260246000fd5b5092915050565b600082825180855260208086019550808260051b84010181860160005b84811015610f3757858303601f19018952815180516001600160a01b031684528481015160a08686018190529061112382870182610d9e565b9150506040808301518683038288015261113d8382610d9e565b925050506060808301518187015250608080830151925085820381870152506111668183610d9e565b9a86019a94505050908301906001016110ea565b602081526111c7602082018351805182526020808201516001600160401b039081169184019190915260408083015182169084015260608083015182169084015260809182015116910152565b600060208301516111db60c0840182610e3c565b5060408301516101808060e08501526111f86101a0850183610d9e565b91506060850151601f1980868503016101008701526112178483610d9e565b93506080870151915080868503016101208701526112358483610d9e565b935060a0870151915061124c610140870183610e3c565b60c087015161016087015260e087015191508086850301838701525061127283826110cd565b9695505050505050565b600181811c9082168061129057607f821691505b6020821081036112b057634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115611302576000816000526020600020601f850160051c810160208610156112df5750805b601f850160051c820191505b818110156112fe578281556001016112eb565b5050505b505050565b81516001600160401b03811115611320576113206103ef565b6113348161132e845461127c565b846112b6565b602080601f83116001811461136957600084156113515750858301515b600019600386901b1c1916600185901b1785556112fe565b600085815260208120601f198616915b8281101561139857888601518255948401946001909101908401611379565b50858210156113b65787850151600019600388901b60f8161c191681555b5050505050600190811b0190555056fea164736f6c6343000818000a", } var CCIPReaderTesterABI = CCIPReaderTesterMetaData.ABI @@ -754,7 +755,7 @@ func (CCIPReaderTesterCCIPSendRequested) Topic() common.Hash { } func (CCIPReaderTesterCommitReportAccepted) Topic() common.Hash { - return common.HexToHash("0x23bc80217a08968cec0790cd045b396fa7eea0a21af469e603329940b883d86d") + return common.HexToHash("0x062172a2ae1a84d7c8d18965d6267b71d579aeca033bbd2e0548947798c3d462") } func (CCIPReaderTesterExecutionStateChanged) Topic() common.Hash { diff --git a/core/gethwrappers/ccip/generated/offramp/offramp.go b/core/gethwrappers/ccip/generated/offramp/offramp.go index 5b063866b4..9ef94b601b 100644 --- a/core/gethwrappers/ccip/generated/offramp/offramp.go +++ b/core/gethwrappers/ccip/generated/offramp/offramp.go @@ -155,7 +155,7 @@ type OffRampStaticConfig struct { var OffRampMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CanOnlySelfCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"reportOnRamp\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"configOnRamp\",\"type\":\"bytes\"}],\"name\":\"CommitOnRampMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"expected\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"actual\",\"type\":\"bytes32\"}],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ExecutionError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"ForkedChain\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enumMultiOCR3Base.InvalidConfigErrorType\",\"name\":\"errorType\",\"type\":\"uint8\"}],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"got\",\"type\":\"uint256\"}],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"min\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"max\",\"type\":\"uint64\"}],\"name\":\"InvalidInterval\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"newLimit\",\"type\":\"uint256\"}],\"name\":\"InvalidManualExecutionGasLimit\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"tokenIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"oldLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"tokenGasOverride\",\"type\":\"uint256\"}],\"name\":\"InvalidManualExecutionTokenGasOverride\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"messageDestChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidMessageDestChainSelector\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"newState\",\"type\":\"uint8\"}],\"name\":\"InvalidNewState\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidOnRampUpdate\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidProof\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRoot\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LeavesCannotBeEmpty\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"ManualExecutionGasAmountCountMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ManualExecutionGasLimitMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"ManualExecutionNotYetEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"errorReason\",\"type\":\"bytes\"}],\"name\":\"MessageValidationError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NonUniqueSignatures\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"notPool\",\"type\":\"address\"}],\"name\":\"NotACompatiblePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OracleCannotBeZeroAddress\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"ReceiverError\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountReleased\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePre\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"balancePost\",\"type\":\"uint256\"}],\"name\":\"ReleaseOrMintBalanceMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"name\":\"RootAlreadyCommitted\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"RootNotCommitted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignatureVerificationDisabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SignaturesOutOfRegistration\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainNotEnabled\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"reportSourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"messageSourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainSelectorMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"StaleCommitReport\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"StaticConfigCannotBeChanged\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"TokenDataMismatch\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"err\",\"type\":\"bytes\"}],\"name\":\"TokenHandlingError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnauthorizedTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnexpectedTokenData\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expected\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"actual\",\"type\":\"uint256\"}],\"name\":\"WrongMessageLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"WrongNumberOfSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroChainSelectorNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"AlreadyAttempted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"indexed\":false,\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"}],\"name\":\"CommitReportAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"DynamicConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"messageHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"name\":\"ExecutionStateChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"RootRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"SkippedAlreadyExecutedMessage\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SkippedReportExecution\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"indexed\":false,\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"sourceConfig\",\"type\":\"tuple\"}],\"name\":\"SourceChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"SourceChainSelectorAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"}],\"name\":\"StaticConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfigArgs[]\",\"name\":\"sourceChainConfigUpdates\",\"type\":\"tuple[]\"}],\"name\":\"applySourceChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"destTokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structClient.Any2EVMMessage\",\"name\":\"\",\"type\":\"tuple\"}],\"name\":\"ccipReceive\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"rawVs\",\"type\":\"bytes32\"}],\"name\":\"commit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"execute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"destTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"destGasAmount\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.Any2EVMTokenTransfer[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"bytes[]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[]\"},{\"internalType\":\"uint32[]\",\"name\":\"tokenGasOverrides\",\"type\":\"uint32[]\"}],\"name\":\"executeSingleMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"getExecutionState\",\"outputs\":[{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLatestPriceSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"root\",\"type\":\"bytes32\"}],\"name\":\"getMerkleRoot\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"getSourceChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"}],\"name\":\"latestConfigDetails\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"n\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"}],\"internalType\":\"structMultiOCR3Base.ConfigInfo\",\"name\":\"configInfo\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfig\",\"name\":\"ocrConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"destTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"destGasAmount\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.Any2EVMTokenTransfer[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage[]\",\"name\":\"messages\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[][]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[][]\"},{\"internalType\":\"bytes32[]\",\"name\":\"proofs\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"proofFlagBits\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.ExecutionReportSingleChain[]\",\"name\":\"reports\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"receiverExecutionGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint32[]\",\"name\":\"tokenGasOverrides\",\"type\":\"uint32[]\"}],\"internalType\":\"structOffRamp.GasLimitOverride[][]\",\"name\":\"gasLimitOverrides\",\"type\":\"tuple[][]\"}],\"name\":\"manuallyExecute\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"permissionLessExecutionThresholdSeconds\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"}],\"internalType\":\"structOffRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"setDynamicConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"ocrPluginType\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"F\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"isSignatureVerificationEnabled\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"}],\"internalType\":\"structMultiOCR3Base.OCRConfigArgs[]\",\"name\":\"ocrConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"setOCR3Configs\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x6101206040523480156200001257600080fd5b50604051620067b2380380620067b2833981016040819052620000359162000806565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf81620001fa565b5050466080525060208301516001600160a01b03161580620000ec575060408301516001600160a01b0316155b8062000103575060608301516001600160a01b0316155b1562000122576040516342bcdf7f60e11b815260040160405180910390fd5b82516001600160401b03166000036200014e5760405163c656089560e01b815260040160405180910390fd5b82516001600160401b0390811660a052602080850180516001600160a01b0390811660c05260408088018051831660e0526060808a01805185166101005283518b519098168852945184169587019590955251821690850152905116908201527f683eb52ee924eb817377cfa8f41f238f4bb7a877da5267869dfffbad85f564d89060800160405180910390a1620001e682620002a5565b620001f1816200036d565b50505062000b8d565b336001600160a01b03821603620002545760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b0316620002ce576040516342bcdf7f60e11b815260040160405180910390fd5b805160048054602080850180516001600160a01b039586166001600160c01b03199094168417600160a01b63ffffffff928316021790945560408087018051600580546001600160a01b031916918916919091179055815194855291519094169183019190915251909216908201527fa1c15688cb2c24508e158f6942b9276c6f3028a85e1af8cf3fff0c3ff3d5fc8d9060600160405180910390a150565b60005b8151811015620005ba57600082828151811062000391576200039162000943565b60200260200101519050600081602001519050806001600160401b0316600003620003cf5760405163c656089560e01b815260040160405180910390fd5b81516001600160a01b0316620003f8576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160401b03811660009081526006602052604090206060830151600182018054620004269062000959565b905060000362000489578154600160a81b600160e81b031916600160a81b1782556040516001600160401b03841681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1620004c8565b8154600160a81b90046001600160401b0316600114620004c857604051632105803760e11b81526001600160401b038416600482015260240162000083565b80511580620004fe5750604080516000602082015201604051602081830303815290604052805190602001208180519060200120145b156200051d576040516342bcdf7f60e11b815260040160405180910390fd5b600182016200052d8282620009ea565b50604080850151835486516001600160a01b03166001600160a01b0319921515600160a01b02929092166001600160a81b031990911617178355516001600160401b038416907f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b90620005a290859062000ab6565b60405180910390a25050505080600101905062000370565b5050565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b0381118282101715620005f957620005f9620005be565b60405290565b604051601f8201601f191681016001600160401b03811182821017156200062a576200062a620005be565b604052919050565b80516001600160401b03811681146200064a57600080fd5b919050565b6001600160a01b03811681146200066557600080fd5b50565b6000601f83601f8401126200067c57600080fd5b825160206001600160401b03808311156200069b576200069b620005be565b8260051b620006ac838201620005ff565b9384528681018301938381019089861115620006c757600080fd5b84890192505b85831015620007f957825184811115620006e75760008081fd5b89016080601f19828d038101821315620007015760008081fd5b6200070b620005d4565b888401516200071a816200064f565b815260406200072b85820162000632565b8a8301526060808601518015158114620007455760008081fd5b838301529385015193898511156200075d5760008081fd5b84860195508f603f8701126200077557600094508485fd5b8a8601519450898511156200078e576200078e620005be565b6200079f8b858f88011601620005ff565b93508484528f82868801011115620007b75760008081fd5b60005b85811015620007d7578681018301518582018d01528b01620007ba565b5060009484018b019490945250918201528352509184019190840190620006cd565b9998505050505050505050565b60008060008385036101008112156200081e57600080fd5b60808112156200082d57600080fd5b62000837620005d4565b620008428662000632565b8152602086015162000854816200064f565b6020820152604086015162000869816200064f565b604082015260608601516200087e816200064f565b606082810191909152909450607f19820112156200089b57600080fd5b50604051606081016001600160401b038082118383101715620008c257620008c2620005be565b8160405260808701519150620008d8826200064f565b90825260a08601519063ffffffff82168214620008f457600080fd5b81602084015260c087015191506200090c826200064f565b6040830182905260e0870151929450808311156200092957600080fd5b5050620009398682870162000668565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b600181811c908216806200096e57607f821691505b6020821081036200098f57634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115620009e5576000816000526020600020601f850160051c81016020861015620009c05750805b601f850160051c820191505b81811015620009e157828155600101620009cc565b5050505b505050565b81516001600160401b0381111562000a065762000a06620005be565b62000a1e8162000a17845462000959565b8462000995565b602080601f83116001811462000a56576000841562000a3d5750858301515b600019600386901b1c1916600185901b178555620009e1565b600085815260208120601f198616915b8281101562000a875788860151825594840194600190910190840162000a66565b508582101562000aa65787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b602080825282546001600160a01b0381168383015260a081901c60ff161515604084015260a81c6001600160401b0316606083015260808083015260018084018054600093929190849062000b0b8162000959565b8060a089015260c0600183166000811462000b2f576001811462000b4c5762000b7e565b60ff19841660c08b015260c083151560051b8b0101945062000b7e565b85600052602060002060005b8481101562000b755781548c820185015290880190890162000b58565b8b0160c0019550505b50929998505050505050505050565b60805160a05160c05160e05161010051615baf62000c036000396000818161022c01526129ca0152600081816101fd0152612c8f0152600081816101ce01528181610552015281816106ff015261238b01526000818161019f01526125ca015260008181611abc0152611aef0152615baf6000f3fe608060405234801561001057600080fd5b50600436106101515760003560e01c80636f9e320f116100cd578063c673e58411610081578063e9d68a8e11610066578063e9d68a8e146104bc578063f2fde38b146104dc578063f716f99f146104ef57600080fd5b8063c673e58414610458578063ccd37ba31461047857600080fd5b806379ba5097116100b257806379ba50971461042757806385572ffb1461042f5780638da5cb5b1461043d57600080fd5b80636f9e320f146103825780637437ff9f1461039557600080fd5b8063311cd513116101245780635e36480c116101095780635e36480c1461033c5780635e7bb0081461035c57806360987c201461036f57600080fd5b8063311cd5131461030e5780633f4b04aa1461032157600080fd5b806304666f9c1461015657806306285c691461016b578063181f5a77146102b25780632d04ab76146102fb575b600080fd5b610169610164366004613bb7565b610502565b005b61025c60408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160401b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316815250905090565b6040516102a9919081516001600160401b031681526020808301516001600160a01b0390811691830191909152604080840151821690830152606092830151169181019190915260800190565b60405180910390f35b6102ee6040518060400160405280601181526020017f4f666652616d7020312e362e302d64657600000000000000000000000000000081525081565b6040516102a99190613d25565b610169610309366004613dd5565b610516565b61016961031c366004613e87565b610a12565b6009546040516001600160401b0390911681526020016102a9565b61034f61034a366004613eda565b610a7b565b6040516102a99190613f37565b61016961036a3660046144a0565b610ad0565b61016961037d3660046146e4565b610d5f565b610169610390366004614778565b61103f565b6103f1604080516060810182526000808252602082018190529181019190915250604080516060810182526004546001600160a01b038082168352600160a01b90910463ffffffff166020830152600554169181019190915290565b6040805182516001600160a01b03908116825260208085015163ffffffff169083015292820151909216908201526060016102a9565b610169611050565b6101696101513660046147ca565b6000546040516001600160a01b0390911681526020016102a9565b61046b610466366004614815565b611101565b6040516102a99190614875565b6104ae6104863660046148ea565b6001600160401b03919091166000908152600860209081526040808320938352929052205490565b6040519081526020016102a9565b6104cf6104ca366004614914565b61125f565b6040516102a9919061492f565b6101696104ea36600461497c565b61136b565b6101696104fd366004614a01565b61137c565b61050a6113be565b6105138161141a565b50565b600061052487890189614d56565b602081015151909150156105b6576020810151604080830151905162ccd5af60e81b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169263ccd5af009261058592600401614f7e565b60006040518083038186803b15801561059d57600080fd5b505afa1580156105b1573d6000803e3d6000fd5b505050505b805151511515806105cc57508051602001515115155b156106985760095460208a0135906001600160401b0380831691161015610670576009805467ffffffffffffffff19166001600160401b038316179055600480548351604051633937306f60e01b81526001600160a01b0390921692633937306f926106399291016150b2565b600060405180830381600087803b15801561065357600080fd5b505af1158015610667573d6000803e3d6000fd5b50505050610696565b81602001515160000361069657604051632261116760e01b815260040160405180910390fd5b505b60005b816020015151811015610953576000826020015182815181106106c0576106c0614fe0565b60209081029190910101518051604051632cbc26bb60e01b815267ffffffffffffffff60801b608083901b166004820152919250906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632cbc26bb90602401602060405180830381865afa158015610746573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061076a91906150c5565b1561079857604051637edeb53960e11b81526001600160401b03821660048201526024015b60405180910390fd5b60006107a38261166d565b9050806001016040516107b6919061511c565b6040518091039020836020015180519060200120146107f35782602001518160010160405163b80d8fa960e01b815260040161078f92919061520f565b60408301518154600160a81b90046001600160401b039081169116141580610834575082606001516001600160401b031683604001516001600160401b0316115b1561087957825160408085015160608601519151636af0786b60e11b81526001600160401b03938416600482015290831660248201529116604482015260640161078f565b60808301518061089c5760405163504570e360e01b815260040160405180910390fd5b83516001600160401b03166000908152600860209081526040808320848452909152902054156108f45783516040516332cf0cbf60e01b81526001600160401b0390911660048201526024810182905260440161078f565b606084015161090490600161524a565b825467ffffffffffffffff60a81b1916600160a81b6001600160401b0392831602179092559251166000908152600860209081526040808320948352939052919091204290555060010161069b565b50602081015181516040517f35c02761bcd3ef995c6a601a1981f4ed3934dcbe5041e24e286c89f5531d17e49261098b929091615271565b60405180910390a1610a0760008a8a8a8a8a8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808e0282810182019093528d82529093508d92508c9182918501908490808284376000920191909152508b92506116b9915050565b505050505050505050565b610a52610a2182840184615296565b6040805160008082526020820190925290610a4c565b6060815260200190600190039081610a375790505b506119b2565b604080516000808252602082019092529050610a756001858585858660006116b9565b50505050565b6000610a89600160046152ca565b6002610a966080856152f3565b6001600160401b0316610aa99190615319565b610ab38585611a74565b901c166003811115610ac757610ac7613f0d565b90505b92915050565b610ad8611ab9565b815181518114610afb576040516320f8fd5960e21b815260040160405180910390fd5b60005b81811015610d4f576000848281518110610b1a57610b1a614fe0565b60200260200101519050600081602001515190506000858481518110610b4257610b42614fe0565b6020026020010151905080518214610b6d576040516320f8fd5960e21b815260040160405180910390fd5b60005b82811015610d40576000828281518110610b8c57610b8c614fe0565b6020026020010151600001519050600085602001518381518110610bb257610bb2614fe0565b6020026020010151905081600014610c06578060800151821015610c06578551815151604051633a98d46360e11b81526001600160401b03909216600483015260248201526044810183905260640161078f565b838381518110610c1857610c18614fe0565b602002602001015160200151518160a001515114610c6557805180516060909101516040516370a193fd60e01b815260048101929092526001600160401b0316602482015260440161078f565b60005b8160a0015151811015610d32576000858581518110610c8957610c89614fe0565b6020026020010151602001518281518110610ca657610ca6614fe0565b602002602001015163ffffffff16905080600014610d295760008360a001518381518110610cd657610cd6614fe0565b60200260200101516040015163ffffffff16905080821015610d27578351516040516348e617b360e01b8152600481019190915260248101849052604481018290526064810183905260840161078f565b505b50600101610c68565b505050806001019050610b70565b50505050806001019050610afe565b50610d5a83836119b2565b505050565b333014610d7f576040516306e34e6560e31b815260040160405180910390fd5b6040805160008082526020820190925281610dbc565b6040805180820190915260008082526020820152815260200190600190039081610d955790505b5060a08701515190915015610df257610def8660a001518760200151886060015189600001516020015189898989611b21565b90505b6040805160a081018252875151815287516020908101516001600160401b031681830152808901518351600094840192610e2d929101613d25565b60408051601f19818403018152918152908252898101516020830152018390526005549091506001600160a01b03168015610f08576040516308d450a160e01b81526001600160a01b038216906308d450a190610e8e9085906004016153d1565b600060405180830381600087803b158015610ea857600080fd5b505af1925050508015610eb9575060015b610f08573d808015610ee7576040519150601f19603f3d011682016040523d82523d6000602084013e610eec565b606091505b50806040516309c2532560e01b815260040161078f9190613d25565b604088015151158015610f1d57506080880151155b80610f34575060608801516001600160a01b03163b155b80610f5b57506060880151610f59906001600160a01b03166385572ffb60e01b611cd2565b155b15610f6857505050611038565b87516020908101516001600160401b03166000908152600690915260408082205460808b015160608c01519251633cf9798360e01b815284936001600160a01b0390931692633cf9798392610fc692899261138892916004016153e4565b6000604051808303816000875af1158015610fe5573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261100d9190810190615420565b50915091508161103257806040516302a35ba360e21b815260040161078f9190613d25565b50505050505b5050505050565b6110476113be565b61051381611cee565b6001546001600160a01b031633146110aa5760405162461bcd60e51b815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e657200000000000000000000604482015260640161078f565b60008054336001600160a01b0319808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6111446040805160e081019091526000606082018181526080830182905260a0830182905260c08301919091528190815260200160608152602001606081525090565b60ff808316600090815260026020818152604092839020835160e081018552815460608201908152600183015480881660808401526101008104881660a0840152620100009004909616151560c0820152948552918201805484518184028101840190955280855292938583019390928301828280156111ed57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116111cf575b505050505081526020016003820180548060200260200160405190810160405280929190818152602001828054801561124f57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611231575b5050505050815250509050919050565b60408051608080820183526000808352602080840182905283850182905260608085018190526001600160401b03878116845260068352928690208651948501875280546001600160a01b0381168652600160a01b810460ff16151593860193909352600160a81b9092049092169483019490945260018401805493949293918401916112eb906150e2565b80601f0160208091040260200160405190810160405280929190818152602001828054611317906150e2565b801561124f5780601f106113395761010080835404028352916020019161124f565b820191906000526020600020905b81548152906001019060200180831161134757505050919092525091949350505050565b6113736113be565b61051381611dcd565b6113846113be565b60005b81518110156113ba576113b28282815181106113a5576113a5614fe0565b6020026020010151611e76565b600101611387565b5050565b6000546001600160a01b031633146114185760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640161078f565b565b60005b81518110156113ba57600082828151811061143a5761143a614fe0565b60200260200101519050600081602001519050806001600160401b03166000036114775760405163c656089560e01b815260040160405180910390fd5b81516001600160a01b031661149f576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160401b038116600090815260066020526040902060608301516001820180546114cb906150e2565b905060000361152d57815467ffffffffffffffff60a81b1916600160a81b1782556040516001600160401b03841681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a161156a565b8154600160a81b90046001600160401b031660011461156a57604051632105803760e11b81526001600160401b038416600482015260240161078f565b8051158061159f5750604080516000602082015201604051602081830303815290604052805190602001208180519060200120145b156115bd576040516342bcdf7f60e11b815260040160405180910390fd5b600182016115cb8282615505565b50604080850151835486516001600160a01b03166001600160a01b0319921515600160a01b02929092167fffffffffffffffffffffff00000000000000000000000000000000000000000090911617178355516001600160401b038416907f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b906116569085906155c4565b60405180910390a25050505080600101905061141d565b6001600160401b03811660009081526006602052604081208054600160a01b900460ff16610aca5760405163ed053c5960e01b81526001600160401b038416600482015260240161078f565b60ff878116600090815260026020908152604080832081516080810183528154815260019091015480861693820193909352610100830485169181019190915262010000909104909216151560608301528735906117188760a4615612565b9050826060015115611760578451611731906020615319565b865161173e906020615319565b6117499060a0615612565b6117539190615612565b61175d9082615612565b90505b36811461178957604051638e1192e160e01b81526004810182905236602482015260440161078f565b50815181146117b85781516040516324f7d61360e21b815260048101919091526024810182905260440161078f565b6117c0611ab9565b60ff808a166000908152600360209081526040808320338452825280832081518083019092528054808616835293949193909284019161010090910416600281111561180e5761180e613f0d565b600281111561181f5761181f613f0d565b905250905060028160200151600281111561183c5761183c613f0d565b1480156118905750600260008b60ff1660ff168152602001908152602001600020600301816000015160ff168154811061187857611878614fe0565b6000918252602090912001546001600160a01b031633145b6118ad57604051631b41e11d60e31b815260040160405180910390fd5b5081606001511561195d5760208201516118c8906001615625565b60ff168551146118eb576040516371253a2560e01b815260040160405180910390fd5b835185511461190d5760405163a75d88af60e01b815260040160405180910390fd5b6000878760405161191f92919061563e565b604051908190038120611936918b9060200161564e565b60405160208183030381529060405280519060200120905061195b8a828888886121a0565b505b6040805182815260208a8101356001600160401b03169082015260ff8b16917f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef0910160405180910390a2505050505050505050565b81516000036119d35760405162bf199760e01b815260040160405180910390fd5b80516040805160008082526020820190925291159181611a16565b6040805180820190915260008152606060208201528152602001906001900390816119ee5790505b50905060005b845181101561103857611a6c858281518110611a3a57611a3a614fe0565b602002602001015184611a6657858381518110611a5957611a59614fe0565b602002602001015161235d565b8361235d565b600101611a1c565b6001600160401b038216600090815260076020526040812081611a98608085615662565b6001600160401b031681526020810191909152604001600020549392505050565b467f00000000000000000000000000000000000000000000000000000000000000001461141857604051630f01ce8560e01b81527f0000000000000000000000000000000000000000000000000000000000000000600482015246602482015260440161078f565b606088516001600160401b03811115611b3c57611b3c6139d7565b604051908082528060200260200182016040528015611b8157816020015b6040805180820190915260008082526020820152815260200190600190039081611b5a5790505b509050811560005b8a51811015611cc45781611c2157848482818110611ba957611ba9614fe0565b9050602002016020810190611bbe9190615688565b63ffffffff1615611c2157848482818110611bdb57611bdb614fe0565b9050602002016020810190611bf09190615688565b8b8281518110611c0257611c02614fe0565b60200260200101516040019063ffffffff16908163ffffffff16815250505b611c9f8b8281518110611c3657611c36614fe0565b60200260200101518b8b8b8b8b87818110611c5357611c53614fe0565b9050602002810190611c6591906156a3565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612c5492505050565b838281518110611cb157611cb1614fe0565b6020908102919091010152600101611b89565b505098975050505050505050565b6000611cdd83612f34565b8015610ac75750610ac78383612f7f565b80516001600160a01b0316611d16576040516342bcdf7f60e11b815260040160405180910390fd5b805160048054602080850180516001600160a01b039586167fffffffffffffffff0000000000000000000000000000000000000000000000009094168417600160a01b63ffffffff928316021790945560408087018051600580546001600160a01b031916918916919091179055815194855291519094169183019190915251909216908201527fa1c15688cb2c24508e158f6942b9276c6f3028a85e1af8cf3fff0c3ff3d5fc8d9060600160405180910390a150565b336001600160a01b03821603611e255760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161078f565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b806040015160ff16600003611ea1576000604051631b3fab5160e11b815260040161078f91906156e9565b60208082015160ff80821660009081526002909352604083206001810154929390928392169003611ef2576060840151600182018054911515620100000262ff000019909216919091179055611f2e565b6060840151600182015460ff6201000090910416151590151514611f2e576040516321fd80df60e21b815260ff8416600482015260240161078f565b60a084015180516101001015611f5a576001604051631b3fab5160e11b815260040161078f91906156e9565b8051600003611f7f576005604051631b3fab5160e11b815260040161078f91906156e9565b611fe58484600301805480602002602001604051908101604052809291908181526020018280548015611fdb57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611fbd575b5050505050613021565b846060015115612115576120538484600201805480602002602001604051908101604052809291908181526020018280548015611fdb576020028201919060005260206000209081546001600160a01b03168152600190910190602001808311611fbd575050505050613021565b60808501518051610100101561207f576002604051631b3fab5160e11b815260040161078f91906156e9565b604086015161208f906003615703565b60ff168151116120b5576003604051631b3fab5160e11b815260040161078f91906156e9565b8151815110156120db576001604051631b3fab5160e11b815260040161078f91906156e9565b805160018401805461ff00191661010060ff841602179055612106906002860190602084019061395d565b506121138582600161308a565b505b6121218482600261308a565b8051612136906003850190602084019061395d565b5060408581015160018401805460ff191660ff8316179055865180855560a088015192517fab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f5479361218f9389939260028a0192919061571f565b60405180910390a1611038846131e5565b8251600090815b818110156123535760006001888684602081106121c6576121c6614fe0565b6121d391901a601b615625565b8985815181106121e5576121e5614fe0565b60200260200101518986815181106121ff576121ff614fe0565b60200260200101516040516000815260200160405260405161223d949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa15801561225f573d6000803e3d6000fd5b505060408051601f1981015160ff808e166000908152600360209081528582206001600160a01b038516835281528582208587019096528554808416865293975090955092939284019161010090041660028111156122c0576122c0613f0d565b60028111156122d1576122d1613f0d565b90525090506001816020015160028111156122ee576122ee613f0d565b1461230c57604051636518c33d60e11b815260040160405180910390fd5b8051600160ff9091161b85161561233657604051633d9ef1f160e21b815260040160405180910390fd5b806000015160ff166001901b8517945050508060010190506121a7565b5050505050505050565b81518151604051632cbc26bb60e01b8152608083901b67ffffffffffffffff60801b166004820152901515907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632cbc26bb90602401602060405180830381865afa1580156123da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123fe91906150c5565b1561246f57801561242d57604051637edeb53960e11b81526001600160401b038316600482015260240161078f565b6040516001600160401b03831681527faab522ed53d887e56ed53dd37398a01aeef6a58e0fa77c2173beb9512d8949339060200160405180910390a150505050565b600061247a8361166d565b6001018054612488906150e2565b80601f01602080910402602001604051908101604052809291908181526020018280546124b4906150e2565b80156125015780601f106124d657610100808354040283529160200191612501565b820191906000526020600020905b8154815290600101906020018083116124e457829003601f168201915b505050602088015151929350505060008190036125305760405162bf199760e01b815260040160405180910390fd5b8560400151518114612555576040516357e0e08360e01b815260040160405180910390fd5b6000816001600160401b0381111561256f5761256f6139d7565b604051908082528060200260200182016040528015612598578160200160208202803683370190505b50905060005b8281101561273c576000886020015182815181106125be576125be614fe0565b602002602001015190507f00000000000000000000000000000000000000000000000000000000000000006001600160401b03168160000151604001516001600160401b0316146126355780516040908101519051631c21951160e11b81526001600160401b03909116600482015260240161078f565b866001600160401b03168160000151602001516001600160401b03161461268957805160200151604051636c95f1eb60e01b81526001600160401b03808a166004830152909116602482015260440161078f565b612716817f2425b0b9f9054c76ff151b0a175b18f37a4a4e82013a72e9f15c9caa095ed21f83600001516020015184600001516040015189805190602001206040516020016126fb94939291909384526001600160401b03928316602085015291166040830152606082015260800190565b6040516020818303038152906040528051906020012061323c565b83838151811061272857612728614fe0565b60209081029190910101525060010161259e565b50600061275386838a606001518b60800151613344565b90508060000361278157604051633ee8bd3f60e11b81526001600160401b038716600482015260240161078f565b60005b83811015610a075760005a905060008a6020015183815181106127a9576127a9614fe0565b6020026020010151905060006127c78a836000015160600151610a7b565b905060008160038111156127dd576127dd613f0d565b14806127fa575060038160038111156127f8576127f8613f0d565b145b61285057815160600151604080516001600160401b03808e16825290921660208301527f3b575419319662b2a6f5e2467d84521517a3382b908eb3d557bb3fdb0c50e23c910160405180910390a1505050612c4c565b6060891561292f578b858151811061286a5761286a614fe0565b6020908102919091018101510151600454909150600090600160a01b900463ffffffff1661289888426152ca565b11905080806128b8575060038360038111156128b6576128b6613f0d565b145b6128e0576040516354e7e43160e11b81526001600160401b038d16600482015260240161078f565b8c86815181106128f2576128f2614fe0565b602002602001015160000151600014612929578c868151811061291757612917614fe0565b60209081029190910101515160808501525b5061299b565b600082600381111561294357612943613f0d565b1461299b57825160600151604080516001600160401b03808f16825290921660208301527f3ef2a99c550a751d4b0b261268f05a803dfb049ab43616a1ffb388f61fe65120910160405180910390a150505050612c4c565b8251608001516001600160401b031615612a745760008260038111156129c3576129c3613f0d565b03612a74577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e0e03cae8c85600001516080015186602001516040518463ffffffff1660e01b8152600401612a24939291906157d1565b6020604051808303816000875af1158015612a43573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a6791906150c5565b612a745750505050612c4c565b60008d604001518681518110612a8c57612a8c614fe0565b6020026020010151905080518460a001515114612ad657835160600151604051631cfe6d8b60e01b81526001600160401b03808f166004830152909116602482015260440161078f565b612aea8c8560000151606001516001613381565b600080612af8868486613426565b91509150612b0f8e87600001516060015184613381565b8c15612b66576003826003811115612b2957612b29613f0d565b03612b66576000856003811115612b4257612b42613f0d565b14612b6657855151604051632b11b8d960e01b815261078f919083906004016157fd565b6002826003811115612b7a57612b7a613f0d565b14612bbf576003826003811115612b9357612b93613f0d565b14612bbf578d866000015160600151836040516349362d1f60e11b815260040161078f93929190615816565b8560000151600001518660000151606001516001600160401b03168f6001600160401b03167f05665fe9ad095383d018353f4cbcba77e84db27dd215081bbf7cdf9ae6fbe48b8d8c81518110612c1757612c17614fe0565b602002602001015186865a612c2c908f6152ca565b604051612c3c949392919061583b565b60405180910390a4505050505050505b600101612784565b6040805180820190915260008082526020820152602086015160405163bbe4f6db60e01b81526001600160a01b0380831660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063bbe4f6db90602401602060405180830381865afa158015612cd8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cfc9190615872565b90506001600160a01b0381161580612d2b5750612d296001600160a01b03821663aff2afbf60e01b611cd2565b155b15612d545760405163ae9b4ce960e01b81526001600160a01b038216600482015260240161078f565b600080612d6c88858c6040015163ffffffff166134da565b915091506000806000612e1f6040518061010001604052808e81526020018c6001600160401b031681526020018d6001600160a01b031681526020018f608001518152602001896001600160a01b031681526020018f6000015181526020018f6060015181526020018b815250604051602401612de9919061588f565b60408051601f198184030181529190526020810180516001600160e01b0316633907753760e01b179052878661138860846135bd565b92509250925082612e45578160405163e1cd550960e01b815260040161078f9190613d25565b8151602014612e74578151604051631e3be00960e21b815260206004820152602481019190915260440161078f565b600082806020019051810190612e8a919061595b565b9050866001600160a01b03168c6001600160a01b031614612f06576000612ebb8d8a612eb6868a6152ca565b6134da565b50905086811080612ed5575081612ed288836152ca565b14155b15612f045760405163a966e21f60e01b815260048101839052602481018890526044810182905260640161078f565b505b604080518082019091526001600160a01b039098168852602088015250949550505050505095945050505050565b6000612f47826301ffc9a760e01b612f7f565b8015610aca5750612f78827fffffffff00000000000000000000000000000000000000000000000000000000612f7f565b1592915050565b6040517fffffffff0000000000000000000000000000000000000000000000000000000082166024820152600090819060440160408051601f19818403018152919052602080820180516001600160e01b03166301ffc9a760e01b178152825192935060009283928392909183918a617530fa92503d9150600051905082801561300a575060208210155b80156130165750600081115b979650505050505050565b60005b8151811015610d5a5760ff83166000908152600360205260408120835190919084908490811061305657613056614fe0565b6020908102919091018101516001600160a01b03168252810191909152604001600020805461ffff19169055600101613024565b60005b8251811015610a755760008382815181106130aa576130aa614fe0565b60200260200101519050600060028111156130c7576130c7613f0d565b60ff80871660009081526003602090815260408083206001600160a01b0387168452909152902054610100900416600281111561310657613106613f0d565b14613127576004604051631b3fab5160e11b815260040161078f91906156e9565b6001600160a01b03811661314e5760405163d6c62c9b60e01b815260040160405180910390fd5b60405180604001604052808360ff16815260200184600281111561317457613174613f0d565b905260ff80871660009081526003602090815260408083206001600160a01b0387168452825290912083518154931660ff198416811782559184015190929091839161ffff1916176101008360028111156131d1576131d1613f0d565b02179055509050505080600101905061308d565b60ff81166105135760ff8082166000908152600260205260409020600101546201000090041661322857604051631e8ed32560e21b815260040160405180910390fd5b6009805467ffffffffffffffff1916905550565b8151805160608085015190830151608080870151940151604051600095869588956132a095919490939192916020019485526001600160a01b039390931660208501526001600160401b039182166040850152606084015216608082015260a00190565b604051602081830303815290604052805190602001208560200151805190602001208660400151805190602001208760a001516040516020016132e39190615a15565b60408051601f198184030181528282528051602091820120908301979097528101949094526060840192909252608083015260a082015260c081019190915260e0015b60405160208183030381529060405280519060200120905092915050565b600080613352858585613697565b6001600160401b038716600090815260086020908152604080832093835292905220549150505b949350505050565b600060026133906080856152f3565b6001600160401b03166133a39190615319565b905060006133b18585611a74565b9050816133c0600160046152ca565b901b1916818360038111156133d7576133d7613f0d565b6001600160401b03871660009081526007602052604081209190921b92909217918291613405608088615662565b6001600160401b031681526020810191909152604001600020555050505050565b604051630304c3e160e51b815260009060609030906360987c209061345390889088908890600401615aac565b600060405180830381600087803b15801561346d57600080fd5b505af192505050801561347e575060015b6134bd573d8080156134ac576040519150601f19603f3d011682016040523d82523d6000602084013e6134b1565b606091505b506003925090506134d2565b50506040805160208101909152600081526002905b935093915050565b600080600080600061353b8860405160240161350591906001600160a01b0391909116815260200190565b60408051601f198184030181529190526020810180516001600160e01b03166370a0823160e01b179052888861138860846135bd565b92509250925082613561578160405163e1cd550960e01b815260040161078f9190613d25565b6020825114613590578151604051631e3be00960e21b815260206004820152602481019190915260440161078f565b818060200190518101906135a4919061595b565b6135ae82886152ca565b94509450505050935093915050565b6000606060008361ffff166001600160401b038111156135df576135df6139d7565b6040519080825280601f01601f191660200182016040528015613609576020820181803683370190505b509150863b6136235763030ed58f60e21b60005260046000fd5b5a8581101561363d57632be8ca8b60e21b60005260046000fd5b859003604081048103871061365d576337c3be2960e01b60005260046000fd5b505a6000808a5160208c0160008c8cf193505a900390503d848111156136805750835b808352806000602085013e50955095509592505050565b82518251600091908183036136bf57604051630469ac9960e21b815260040160405180910390fd5b61010182118015906136d357506101018111155b6136f0576040516309bde33960e01b815260040160405180910390fd5b6000198282010161010081111561371a576040516309bde33960e01b815260040160405180910390fd5b80600003613747578660008151811061373557613735614fe0565b60200260200101519350505050613915565b6000816001600160401b03811115613761576137616139d7565b60405190808252806020026020018201604052801561378a578160200160208202803683370190505b50905060008080805b858110156138b45760006001821b8b8116036137ee57888510156137d7578c5160018601958e9181106137c8576137c8614fe0565b60200260200101519050613810565b85516001850194879181106137c8576137c8614fe0565b8b5160018401938d91811061380557613805614fe0565b602002602001015190505b600089861015613840578d5160018701968f91811061383157613831614fe0565b60200260200101519050613862565b865160018601958891811061385757613857614fe0565b602002602001015190505b82851115613883576040516309bde33960e01b815260040160405180910390fd5b61388d828261391c565b87848151811061389f5761389f614fe0565b60209081029190910101525050600101613793565b5060018503821480156138c657508683145b80156138d157508581145b6138ee576040516309bde33960e01b815260040160405180910390fd5b83600186038151811061390357613903614fe0565b60200260200101519750505050505050505b9392505050565b60008183106139345761392f828461393a565b610ac7565b610ac783835b604080516001602082015290810183905260608101829052600090608001613326565b8280548282559060005260206000209081019282156139b2579160200282015b828111156139b257825182546001600160a01b0319166001600160a01b0390911617825560209092019160019091019061397d565b506139be9291506139c2565b5090565b5b808211156139be57600081556001016139c3565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b0381118282101715613a0f57613a0f6139d7565b60405290565b60405160a081016001600160401b0381118282101715613a0f57613a0f6139d7565b60405160c081016001600160401b0381118282101715613a0f57613a0f6139d7565b604080519081016001600160401b0381118282101715613a0f57613a0f6139d7565b604051606081016001600160401b0381118282101715613a0f57613a0f6139d7565b604051601f8201601f191681016001600160401b0381118282101715613ac557613ac56139d7565b604052919050565b60006001600160401b03821115613ae657613ae66139d7565b5060051b60200190565b6001600160a01b038116811461051357600080fd5b80356001600160401b0381168114613b1c57600080fd5b919050565b801515811461051357600080fd5b8035613b1c81613b21565b60006001600160401b03821115613b5357613b536139d7565b50601f01601f191660200190565b600082601f830112613b7257600080fd5b8135613b85613b8082613b3a565b613a9d565b818152846020838601011115613b9a57600080fd5b816020850160208301376000918101602001919091529392505050565b60006020808385031215613bca57600080fd5b82356001600160401b0380821115613be157600080fd5b818501915085601f830112613bf557600080fd5b8135613c03613b8082613acd565b81815260059190911b83018401908481019088831115613c2257600080fd5b8585015b83811015613cc857803585811115613c3e5760008081fd5b86016080818c03601f1901811315613c565760008081fd5b613c5e6139ed565b89830135613c6b81613af0565b81526040613c7a848201613b05565b8b830152606080850135613c8d81613b21565b83830152928401359289841115613ca657600091508182fd5b613cb48f8d86880101613b61565b908301525085525050918601918601613c26565b5098975050505050505050565b60005b83811015613cf0578181015183820152602001613cd8565b50506000910152565b60008151808452613d11816020860160208601613cd5565b601f01601f19169290920160200192915050565b602081526000610ac76020830184613cf9565b8060608101831015610aca57600080fd5b60008083601f840112613d5b57600080fd5b5081356001600160401b03811115613d7257600080fd5b602083019150836020828501011115613d8a57600080fd5b9250929050565b60008083601f840112613da357600080fd5b5081356001600160401b03811115613dba57600080fd5b6020830191508360208260051b8501011115613d8a57600080fd5b60008060008060008060008060e0898b031215613df157600080fd5b613dfb8a8a613d38565b975060608901356001600160401b0380821115613e1757600080fd5b613e238c838d01613d49565b909950975060808b0135915080821115613e3c57600080fd5b613e488c838d01613d91565b909750955060a08b0135915080821115613e6157600080fd5b50613e6e8b828c01613d91565b999c989b50969995989497949560c00135949350505050565b600080600060808486031215613e9c57600080fd5b613ea68585613d38565b925060608401356001600160401b03811115613ec157600080fd5b613ecd86828701613d49565b9497909650939450505050565b60008060408385031215613eed57600080fd5b613ef683613b05565b9150613f0460208401613b05565b90509250929050565b634e487b7160e01b600052602160045260246000fd5b60048110613f3357613f33613f0d565b9052565b60208101610aca8284613f23565b600060a08284031215613f5757600080fd5b613f5f613a15565b905081358152613f7160208301613b05565b6020820152613f8260408301613b05565b6040820152613f9360608301613b05565b6060820152613fa460808301613b05565b608082015292915050565b8035613b1c81613af0565b803563ffffffff81168114613b1c57600080fd5b600082601f830112613fdf57600080fd5b81356020613fef613b8083613acd565b82815260059290921b8401810191818101908684111561400e57600080fd5b8286015b848110156140de5780356001600160401b03808211156140325760008081fd5b9088019060a0828b03601f190181131561404c5760008081fd5b614054613a15565b87840135838111156140665760008081fd5b6140748d8a83880101613b61565b82525060408085013561408681613af0565b828a01526060614097868201613fba565b828401526080915081860135858111156140b15760008081fd5b6140bf8f8c838a0101613b61565b9184019190915250919093013590830152508352918301918301614012565b509695505050505050565b600061014082840312156140fc57600080fd5b614104613a37565b90506141108383613f45565b815260a08201356001600160401b038082111561412c57600080fd5b61413885838601613b61565b602084015260c084013591508082111561415157600080fd5b61415d85838601613b61565b604084015261416e60e08501613faf565b6060840152610100840135608084015261012084013591508082111561419357600080fd5b506141a084828501613fce565b60a08301525092915050565b600082601f8301126141bd57600080fd5b813560206141cd613b8083613acd565b82815260059290921b840181019181810190868411156141ec57600080fd5b8286015b848110156140de5780356001600160401b0381111561420f5760008081fd5b61421d8986838b01016140e9565b8452509183019183016141f0565b600082601f83011261423c57600080fd5b8135602061424c613b8083613acd565b82815260059290921b8401810191818101908684111561426b57600080fd5b8286015b848110156140de5780356001600160401b038082111561428e57600080fd5b818901915089603f8301126142a257600080fd5b858201356142b2613b8082613acd565b81815260059190911b830160400190878101908c8311156142d257600080fd5b604085015b8381101561430b578035858111156142ee57600080fd5b6142fd8f6040838a0101613b61565b8452509189019189016142d7565b5087525050509284019250830161426f565b600082601f83011261432e57600080fd5b8135602061433e613b8083613acd565b8083825260208201915060208460051b87010193508684111561436057600080fd5b602086015b848110156140de5780358352918301918301614365565b600082601f83011261438d57600080fd5b8135602061439d613b8083613acd565b82815260059290921b840181019181810190868411156143bc57600080fd5b8286015b848110156140de5780356001600160401b03808211156143e05760008081fd5b9088019060a0828b03601f19018113156143fa5760008081fd5b614402613a15565b61440d888501613b05565b8152604080850135848111156144235760008081fd5b6144318e8b838901016141ac565b8a840152506060808601358581111561444a5760008081fd5b6144588f8c838a010161422b565b83850152506080915081860135858111156144735760008081fd5b6144818f8c838a010161431d565b91840191909152509190930135908301525083529183019183016143c0565b600080604083850312156144b357600080fd5b6001600160401b03833511156144c857600080fd5b6144d5848435850161437c565b91506001600160401b03602084013511156144ef57600080fd5b6020830135830184601f82011261450557600080fd5b614512613b808235613acd565b81358082526020808301929160051b84010187101561453057600080fd5b602083015b6020843560051b8501018110156146d6576001600160401b038135111561455b57600080fd5b87603f82358601011261456d57600080fd5b614580613b806020833587010135613acd565b81358501602081810135808452908301929160059190911b016040018a10156145a857600080fd5b604083358701015b83358701602081013560051b016040018110156146c6576001600160401b03813511156145dc57600080fd5b833587018135016040818d03603f190112156145f757600080fd5b6145ff613a59565b604082013581526001600160401b036060830135111561461e57600080fd5b8c605f60608401358401011261463357600080fd5b604060608301358301013561464a613b8082613acd565b808282526020820191508f60608460051b606088013588010101111561466f57600080fd5b6060808601358601015b60608460051b6060880135880101018110156146a65761469881613fba565b835260209283019201614679565b5080602085015250505080855250506020830192506020810190506145b0565b5084525060209283019201614535565b508093505050509250929050565b6000806000806000606086880312156146fc57600080fd5b85356001600160401b038082111561471357600080fd5b61471f89838a016140e9565b9650602088013591508082111561473557600080fd5b61474189838a01613d91565b9096509450604088013591508082111561475a57600080fd5b5061476788828901613d91565b969995985093965092949392505050565b60006060828403121561478a57600080fd5b614792613a7b565b823561479d81613af0565b81526147ab60208401613fba565b602082015260408301356147be81613af0565b60408201529392505050565b6000602082840312156147dc57600080fd5b81356001600160401b038111156147f257600080fd5b820160a0818503121561391557600080fd5b803560ff81168114613b1c57600080fd5b60006020828403121561482757600080fd5b610ac782614804565b60008151808452602080850194506020840160005b8381101561486a5781516001600160a01b031687529582019590820190600101614845565b509495945050505050565b60208152600082518051602084015260ff602082015116604084015260ff604082015116606084015260608101511515608084015250602083015160c060a08401526148c460e0840182614830565b90506040840151601f198483030160c08501526148e18282614830565b95945050505050565b600080604083850312156148fd57600080fd5b61490683613b05565b946020939093013593505050565b60006020828403121561492657600080fd5b610ac782613b05565b602081526001600160a01b0382511660208201526020820151151560408201526001600160401b0360408301511660608201526000606083015160808084015261337960a0840182613cf9565b60006020828403121561498e57600080fd5b813561391581613af0565b600082601f8301126149aa57600080fd5b813560206149ba613b8083613acd565b8083825260208201915060208460051b8701019350868411156149dc57600080fd5b602086015b848110156140de5780356149f481613af0565b83529183019183016149e1565b60006020808385031215614a1457600080fd5b82356001600160401b0380821115614a2b57600080fd5b818501915085601f830112614a3f57600080fd5b8135614a4d613b8082613acd565b81815260059190911b83018401908481019088831115614a6c57600080fd5b8585015b83811015613cc857803585811115614a8757600080fd5b860160c0818c03601f19011215614a9e5760008081fd5b614aa6613a37565b8882013581526040614ab9818401614804565b8a8301526060614aca818501614804565b8284015260809150614add828501613b2f565b9083015260a08381013589811115614af55760008081fd5b614b038f8d83880101614999565b838501525060c0840135915088821115614b1d5760008081fd5b614b2b8e8c84870101614999565b9083015250845250918601918601614a70565b80356001600160e01b0381168114613b1c57600080fd5b600082601f830112614b6657600080fd5b81356020614b76613b8083613acd565b82815260069290921b84018101918181019086841115614b9557600080fd5b8286015b848110156140de5760408189031215614bb25760008081fd5b614bba613a59565b614bc382613b05565b8152614bd0858301614b3e565b81860152835291830191604001614b99565b600082601f830112614bf357600080fd5b81356020614c03613b8083613acd565b82815260059290921b84018101918181019086841115614c2257600080fd5b8286015b848110156140de5780356001600160401b0380821115614c465760008081fd5b9088019060a0828b03601f1901811315614c605760008081fd5b614c68613a15565b614c73888501613b05565b815260408085013584811115614c895760008081fd5b614c978e8b83890101613b61565b8a8401525060609350614cab848601613b05565b908201526080614cbc858201613b05565b93820193909352920135908201528352918301918301614c26565b600082601f830112614ce857600080fd5b81356020614cf8613b8083613acd565b82815260069290921b84018101918181019086841115614d1757600080fd5b8286015b848110156140de5760408189031215614d345760008081fd5b614d3c613a59565b813581528482013585820152835291830191604001614d1b565b60006020808385031215614d6957600080fd5b82356001600160401b0380821115614d8057600080fd5b9084019060608287031215614d9457600080fd5b614d9c613a7b565b823582811115614dab57600080fd5b83016040818903811315614dbe57600080fd5b614dc6613a59565b823585811115614dd557600080fd5b8301601f81018b13614de657600080fd5b8035614df4613b8082613acd565b81815260069190911b8201890190898101908d831115614e1357600080fd5b928a01925b82841015614e635785848f031215614e305760008081fd5b614e38613a59565b8435614e4381613af0565b8152614e50858d01614b3e565b818d0152825292850192908a0190614e18565b845250505082870135915084821115614e7b57600080fd5b614e878a838501614b55565b81880152835250508284013582811115614ea057600080fd5b614eac88828601614be2565b85830152506040830135935081841115614ec557600080fd5b614ed187858501614cd7565b60408201529695505050505050565b600082825180855260208086019550808260051b84010181860160005b84811015614f7157601f19868403018952815160a06001600160401b03808351168652868301518288880152614f3583880182613cf9565b60408581015184169089015260608086015190931692880192909252506080928301519290950191909152509783019790830190600101614efd565b5090979650505050505050565b60006040808352614f926040840186614ee0565b83810360208581019190915285518083528682019282019060005b81811015614fd257845180518452840151848401529383019391850191600101614fad565b509098975050505050505050565b634e487b7160e01b600052603260045260246000fd5b805160408084528151848201819052600092602091908201906060870190855b8181101561504d57835180516001600160a01b031684528501516001600160e01b0316858401529284019291850191600101615016565b50508583015187820388850152805180835290840192506000918401905b808310156150a657835180516001600160401b031683528501516001600160e01b03168583015292840192600192909201919085019061506b565b50979650505050505050565b602081526000610ac76020830184614ff6565b6000602082840312156150d757600080fd5b815161391581613b21565b600181811c908216806150f657607f821691505b60208210810361511657634e487b7160e01b600052602260045260246000fd5b50919050565b600080835461512a816150e2565b60018281168015615142576001811461515757615186565b60ff1984168752821515830287019450615186565b8760005260208060002060005b8581101561517d5781548a820152908401908201615164565b50505082870194505b50929695505050505050565b6000815461519f816150e2565b8085526020600183811680156151bc57600181146151d657615204565b60ff1985168884015283151560051b880183019550615204565b866000528260002060005b858110156151fc5781548a82018601529083019084016151e1565b890184019650505b505050505092915050565b6040815260006152226040830185613cf9565b82810360208401526148e18185615192565b634e487b7160e01b600052601160045260246000fd5b6001600160401b0381811683821601908082111561526a5761526a615234565b5092915050565b6040815260006152846040830185614ee0565b82810360208401526148e18185614ff6565b6000602082840312156152a857600080fd5b81356001600160401b038111156152be57600080fd5b6133798482850161437c565b81810381811115610aca57610aca615234565b634e487b7160e01b600052601260045260246000fd5b60006001600160401b038084168061530d5761530d6152dd565b92169190910692915050565b8082028115828204841417610aca57610aca615234565b80518252600060206001600160401b0381840151168185015260408084015160a0604087015261536360a0870182613cf9565b90506060850151868203606088015261537c8282613cf9565b608087810151898303918a01919091528051808352908601935060009250908501905b808310156150a657835180516001600160a01b031683528601518683015292850192600192909201919084019061539f565b602081526000610ac76020830184615330565b6080815260006153f76080830187615330565b61ffff9590951660208301525060408101929092526001600160a01b0316606090910152919050565b60008060006060848603121561543557600080fd5b835161544081613b21565b60208501519093506001600160401b0381111561545c57600080fd5b8401601f8101861361546d57600080fd5b805161547b613b8082613b3a565b81815287602083850101111561549057600080fd5b6154a1826020830160208601613cd5565b809450505050604084015190509250925092565b601f821115610d5a576000816000526020600020601f850160051c810160208610156154de5750805b601f850160051c820191505b818110156154fd578281556001016154ea565b505050505050565b81516001600160401b0381111561551e5761551e6139d7565b6155328161552c84546150e2565b846154b5565b602080601f831160018114615567576000841561554f5750858301515b600019600386901b1c1916600185901b1785556154fd565b600085815260208120601f198616915b8281101561559657888601518255948401946001909101908401615577565b50858210156155b45787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60208152600082546001600160a01b038116602084015260ff8160a01c16151560408401526001600160401b038160a81c16606084015250608080830152610ac760a0830160018501615192565b80820180821115610aca57610aca615234565b60ff8181168382160190811115610aca57610aca615234565b8183823760009101908152919050565b828152606082602083013760800192915050565b60006001600160401b038084168061567c5761567c6152dd565b92169190910492915050565b60006020828403121561569a57600080fd5b610ac782613fba565b6000808335601e198436030181126156ba57600080fd5b8301803591506001600160401b038211156156d457600080fd5b602001915036819003821315613d8a57600080fd5b60208101600683106156fd576156fd613f0d565b91905290565b60ff818116838216029081169081811461526a5761526a615234565b600060a0820160ff881683526020878185015260a0604085015281875480845260c0860191508860005282600020935060005b818110156157775784546001600160a01b031683526001948501949284019201615752565b50508481036060860152865180825290820192508187019060005b818110156157b75782516001600160a01b031685529383019391830191600101615792565b50505060ff851660808501525090505b9695505050505050565b60006001600160401b038086168352808516602084015250606060408301526148e16060830184613cf9565b8281526040602082015260006133796040830184613cf9565b6001600160401b03848116825283166020820152606081016133796040830184613f23565b84815261584b6020820185613f23565b6080604082015260006158616080830185613cf9565b905082606083015295945050505050565b60006020828403121561588457600080fd5b815161391581613af0565b60208152600082516101008060208501526158ae610120850183613cf9565b915060208501516158ca60408601826001600160401b03169052565b5060408501516001600160a01b03811660608601525060608501516080850152608085015161590460a08601826001600160a01b03169052565b5060a0850151601f19808685030160c08701526159218483613cf9565b935060c08701519150808685030160e087015261593e8483613cf9565b935060e08701519150808685030183870152506157c78382613cf9565b60006020828403121561596d57600080fd5b5051919050565b600082825180855260208086019550808260051b84010181860160005b84811015614f7157601f19868403018952815160a081518186526159b782870182613cf9565b9150506001600160a01b03868301511686860152604063ffffffff81840151168187015250606080830151868303828801526159f38382613cf9565b6080948501519790940196909652505098840198925090830190600101615991565b602081526000610ac76020830184615974565b60008282518085526020808601955060208260051b8401016020860160005b84811015614f7157601f19868403018952615a63838351613cf9565b98840198925090830190600101615a47565b60008151808452602080850194506020840160005b8381101561486a57815163ffffffff1687529582019590820190600101615a8a565b60608152600084518051606084015260208101516001600160401b0380821660808601528060408401511660a08601528060608401511660c08601528060808401511660e0860152505050602085015161014080610100850152615b146101a0850183613cf9565b91506040870151605f198086850301610120870152615b338483613cf9565b935060608901519150615b50838701836001600160a01b03169052565b608089015161016087015260a0890151925080868503016101808701525050615b798282615974565b9150508281036020840152615b8e8186615a28565b905082810360408401526157c78185615a7556fea164736f6c6343000818000a", + Bin: "0x6101206040523480156200001257600080fd5b50604051620067de380380620067de833981016040819052620000359162000806565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf81620001fa565b5050466080525060208301516001600160a01b03161580620000ec575060408301516001600160a01b0316155b8062000103575060608301516001600160a01b0316155b1562000122576040516342bcdf7f60e11b815260040160405180910390fd5b82516001600160401b03166000036200014e5760405163c656089560e01b815260040160405180910390fd5b82516001600160401b0390811660a052602080850180516001600160a01b0390811660c05260408088018051831660e0526060808a01805185166101005283518b519098168852945184169587019590955251821690850152905116908201527f683eb52ee924eb817377cfa8f41f238f4bb7a877da5267869dfffbad85f564d89060800160405180910390a1620001e682620002a5565b620001f1816200036d565b50505062000b8d565b336001600160a01b03821603620002545760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b0316620002ce576040516342bcdf7f60e11b815260040160405180910390fd5b805160048054602080850180516001600160a01b039586166001600160c01b03199094168417600160a01b63ffffffff928316021790945560408087018051600580546001600160a01b031916918916919091179055815194855291519094169183019190915251909216908201527fa1c15688cb2c24508e158f6942b9276c6f3028a85e1af8cf3fff0c3ff3d5fc8d9060600160405180910390a150565b60005b8151811015620005ba57600082828151811062000391576200039162000943565b60200260200101519050600081602001519050806001600160401b0316600003620003cf5760405163c656089560e01b815260040160405180910390fd5b81516001600160a01b0316620003f8576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160401b03811660009081526006602052604090206060830151600182018054620004269062000959565b905060000362000489578154600160a81b600160e81b031916600160a81b1782556040516001600160401b03841681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1620004c8565b8154600160a81b90046001600160401b0316600114620004c857604051632105803760e11b81526001600160401b038416600482015260240162000083565b80511580620004fe5750604080516000602082015201604051602081830303815290604052805190602001208180519060200120145b156200051d576040516342bcdf7f60e11b815260040160405180910390fd5b600182016200052d8282620009ea565b50604080850151835486516001600160a01b03166001600160a01b0319921515600160a01b02929092166001600160a81b031990911617178355516001600160401b038416907f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b90620005a290859062000ab6565b60405180910390a25050505080600101905062000370565b5050565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b0381118282101715620005f957620005f9620005be565b60405290565b604051601f8201601f191681016001600160401b03811182821017156200062a576200062a620005be565b604052919050565b80516001600160401b03811681146200064a57600080fd5b919050565b6001600160a01b03811681146200066557600080fd5b50565b6000601f83601f8401126200067c57600080fd5b825160206001600160401b03808311156200069b576200069b620005be565b8260051b620006ac838201620005ff565b9384528681018301938381019089861115620006c757600080fd5b84890192505b85831015620007f957825184811115620006e75760008081fd5b89016080601f19828d038101821315620007015760008081fd5b6200070b620005d4565b888401516200071a816200064f565b815260406200072b85820162000632565b8a8301526060808601518015158114620007455760008081fd5b838301529385015193898511156200075d5760008081fd5b84860195508f603f8701126200077557600094508485fd5b8a8601519450898511156200078e576200078e620005be565b6200079f8b858f88011601620005ff565b93508484528f82868801011115620007b75760008081fd5b60005b85811015620007d7578681018301518582018d01528b01620007ba565b5060009484018b019490945250918201528352509184019190840190620006cd565b9998505050505050505050565b60008060008385036101008112156200081e57600080fd5b60808112156200082d57600080fd5b62000837620005d4565b620008428662000632565b8152602086015162000854816200064f565b6020820152604086015162000869816200064f565b604082015260608601516200087e816200064f565b606082810191909152909450607f19820112156200089b57600080fd5b50604051606081016001600160401b038082118383101715620008c257620008c2620005be565b8160405260808701519150620008d8826200064f565b90825260a08601519063ffffffff82168214620008f457600080fd5b81602084015260c087015191506200090c826200064f565b6040830182905260e0870151929450808311156200092957600080fd5b5050620009398682870162000668565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b600181811c908216806200096e57607f821691505b6020821081036200098f57634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115620009e5576000816000526020600020601f850160051c81016020861015620009c05750805b601f850160051c820191505b81811015620009e157828155600101620009cc565b5050505b505050565b81516001600160401b0381111562000a065762000a06620005be565b62000a1e8162000a17845462000959565b8462000995565b602080601f83116001811462000a56576000841562000a3d5750858301515b600019600386901b1c1916600185901b178555620009e1565b600085815260208120601f198616915b8281101562000a875788860151825594840194600190910190840162000a66565b508582101562000aa65787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b602080825282546001600160a01b0381168383015260a081901c60ff161515604084015260a81c6001600160401b0316606083015260808083015260018084018054600093929190849062000b0b8162000959565b8060a089015260c0600183166000811462000b2f576001811462000b4c5762000b7e565b60ff19841660c08b015260c083151560051b8b0101945062000b7e565b85600052602060002060005b8481101562000b755781548c820185015290880190890162000b58565b8b0160c0019550505b50929998505050505050505050565b60805160a05160c05160e05161010051615bdb62000c036000396000818161022c01526129d50152600081816101fd0152612c9a0152600081816101ce015281816105580152818161070a015261239601526000818161019f01526125d5015260008181611ac70152611afa0152615bdb6000f3fe608060405234801561001057600080fd5b50600436106101515760003560e01c80636f9e320f116100cd578063c673e58411610081578063e9d68a8e11610066578063e9d68a8e146104bc578063f2fde38b146104dc578063f716f99f146104ef57600080fd5b8063c673e58414610458578063ccd37ba31461047857600080fd5b806379ba5097116100b257806379ba50971461042757806385572ffb1461042f5780638da5cb5b1461043d57600080fd5b80636f9e320f146103825780637437ff9f1461039557600080fd5b8063311cd513116101245780635e36480c116101095780635e36480c1461033c5780635e7bb0081461035c57806360987c201461036f57600080fd5b8063311cd5131461030e5780633f4b04aa1461032157600080fd5b806304666f9c1461015657806306285c691461016b578063181f5a77146102b25780632d04ab76146102fb575b600080fd5b610169610164366004613ba0565b610502565b005b61025c60408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160401b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316815250905090565b6040516102a9919081516001600160401b031681526020808301516001600160a01b0390811691830191909152604080840151821690830152606092830151169181019190915260800190565b60405180910390f35b6102ee6040518060400160405280601181526020017f4f666652616d7020312e362e302d64657600000000000000000000000000000081525081565b6040516102a99190613d0e565b610169610309366004613dbe565b610516565b61016961031c366004613e70565b610a1d565b6009546040516001600160401b0390911681526020016102a9565b61034f61034a366004613ec3565b610a86565b6040516102a99190613f20565b61016961036a366004614489565b610adb565b61016961037d3660046146cd565b610d6a565b610169610390366004614761565b61104a565b6103f1604080516060810182526000808252602082018190529181019190915250604080516060810182526004546001600160a01b038082168352600160a01b90910463ffffffff166020830152600554169181019190915290565b6040805182516001600160a01b03908116825260208085015163ffffffff169083015292820151909216908201526060016102a9565b61016961105b565b6101696101513660046147d0565b6000546040516001600160a01b0390911681526020016102a9565b61046b61046636600461481b565b61110c565b6040516102a9919061487b565b6104ae6104863660046148f0565b6001600160401b03919091166000908152600860209081526040808320938352929052205490565b6040519081526020016102a9565b6104cf6104ca36600461491a565b61126a565b6040516102a99190614935565b6101696104ea366004614982565b611376565b6101696104fd366004614a07565b611387565b61050a6113c9565b61051381611425565b50565b600061052487890189614d5c565b602081015151909150156105c157602081015160408083015160608401519151638d8741cb60e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001693638d8741cb93610590933093909190600401614f91565b60006040518083038186803b1580156105a857600080fd5b505afa1580156105bc573d6000803e3d6000fd5b505050505b805151511515806105d757508051602001515115155b156106a35760095460208a0135906001600160401b038083169116101561067b576009805467ffffffffffffffff19166001600160401b038316179055600480548351604051633937306f60e01b81526001600160a01b0390921692633937306f926106449291016150de565b600060405180830381600087803b15801561065e57600080fd5b505af1158015610672573d6000803e3d6000fd5b505050506106a1565b8160200151516000036106a157604051632261116760e01b815260040160405180910390fd5b505b60005b81602001515181101561095e576000826020015182815181106106cb576106cb61500c565b60209081029190910101518051604051632cbc26bb60e01b815267ffffffffffffffff60801b608083901b166004820152919250906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632cbc26bb90602401602060405180830381865afa158015610751573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061077591906150f1565b156107a357604051637edeb53960e11b81526001600160401b03821660048201526024015b60405180910390fd5b60006107ae82611678565b9050806001016040516107c19190615148565b6040518091039020836020015180519060200120146107fe5782602001518160010160405163b80d8fa960e01b815260040161079a92919061523b565b60408301518154600160a81b90046001600160401b03908116911614158061083f575082606001516001600160401b031683604001516001600160401b0316115b1561088457825160408085015160608601519151636af0786b60e11b81526001600160401b03938416600482015290831660248201529116604482015260640161079a565b6080830151806108a75760405163504570e360e01b815260040160405180910390fd5b83516001600160401b03166000908152600860209081526040808320848452909152902054156108ff5783516040516332cf0cbf60e01b81526001600160401b0390911660048201526024810182905260440161079a565b606084015161090f906001615276565b825467ffffffffffffffff60a81b1916600160a81b6001600160401b039283160217909255925116600090815260086020908152604080832094835293905291909120429055506001016106a6565b50602081015181516040517f35c02761bcd3ef995c6a601a1981f4ed3934dcbe5041e24e286c89f5531d17e49261099692909161529d565b60405180910390a1610a1260008a8a8a8a8a8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808e0282810182019093528d82529093508d92508c9182918501908490808284376000920191909152508b92506116c4915050565b505050505050505050565b610a5d610a2c828401846152c2565b6040805160008082526020820190925290610a57565b6060815260200190600190039081610a425790505b506119bd565b604080516000808252602082019092529050610a806001858585858660006116c4565b50505050565b6000610a94600160046152f6565b6002610aa160808561531f565b6001600160401b0316610ab49190615345565b610abe8585611a7f565b901c166003811115610ad257610ad2613ef6565b90505b92915050565b610ae3611ac4565b815181518114610b06576040516320f8fd5960e21b815260040160405180910390fd5b60005b81811015610d5a576000848281518110610b2557610b2561500c565b60200260200101519050600081602001515190506000858481518110610b4d57610b4d61500c565b6020026020010151905080518214610b78576040516320f8fd5960e21b815260040160405180910390fd5b60005b82811015610d4b576000828281518110610b9757610b9761500c565b6020026020010151600001519050600085602001518381518110610bbd57610bbd61500c565b6020026020010151905081600014610c11578060800151821015610c11578551815151604051633a98d46360e11b81526001600160401b03909216600483015260248201526044810183905260640161079a565b838381518110610c2357610c2361500c565b602002602001015160200151518160a001515114610c7057805180516060909101516040516370a193fd60e01b815260048101929092526001600160401b0316602482015260440161079a565b60005b8160a0015151811015610d3d576000858581518110610c9457610c9461500c565b6020026020010151602001518281518110610cb157610cb161500c565b602002602001015163ffffffff16905080600014610d345760008360a001518381518110610ce157610ce161500c565b60200260200101516040015163ffffffff16905080821015610d32578351516040516348e617b360e01b8152600481019190915260248101849052604481018290526064810183905260840161079a565b505b50600101610c73565b505050806001019050610b7b565b50505050806001019050610b09565b50610d6583836119bd565b505050565b333014610d8a576040516306e34e6560e31b815260040160405180910390fd5b6040805160008082526020820190925281610dc7565b6040805180820190915260008082526020820152815260200190600190039081610da05790505b5060a08701515190915015610dfd57610dfa8660a001518760200151886060015189600001516020015189898989611b2c565b90505b6040805160a081018252875151815287516020908101516001600160401b031681830152808901518351600094840192610e38929101613d0e565b60408051601f19818403018152918152908252898101516020830152018390526005549091506001600160a01b03168015610f13576040516308d450a160e01b81526001600160a01b038216906308d450a190610e999085906004016153fd565b600060405180830381600087803b158015610eb357600080fd5b505af1925050508015610ec4575060015b610f13573d808015610ef2576040519150601f19603f3d011682016040523d82523d6000602084013e610ef7565b606091505b50806040516309c2532560e01b815260040161079a9190613d0e565b604088015151158015610f2857506080880151155b80610f3f575060608801516001600160a01b03163b155b80610f6657506060880151610f64906001600160a01b03166385572ffb60e01b611cdd565b155b15610f7357505050611043565b87516020908101516001600160401b03166000908152600690915260408082205460808b015160608c01519251633cf9798360e01b815284936001600160a01b0390931692633cf9798392610fd19289926113889291600401615410565b6000604051808303816000875af1158015610ff0573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611018919081019061544c565b50915091508161103d57806040516302a35ba360e21b815260040161079a9190613d0e565b50505050505b5050505050565b6110526113c9565b61051381611cf9565b6001546001600160a01b031633146110b55760405162461bcd60e51b815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e657200000000000000000000604482015260640161079a565b60008054336001600160a01b0319808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b61114f6040805160e081019091526000606082018181526080830182905260a0830182905260c08301919091528190815260200160608152602001606081525090565b60ff808316600090815260026020818152604092839020835160e081018552815460608201908152600183015480881660808401526101008104881660a0840152620100009004909616151560c0820152948552918201805484518184028101840190955280855292938583019390928301828280156111f857602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116111da575b505050505081526020016003820180548060200260200160405190810160405280929190818152602001828054801561125a57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161123c575b5050505050815250509050919050565b60408051608080820183526000808352602080840182905283850182905260608085018190526001600160401b03878116845260068352928690208651948501875280546001600160a01b0381168652600160a01b810460ff16151593860193909352600160a81b9092049092169483019490945260018401805493949293918401916112f69061510e565b80601f01602080910402602001604051908101604052809291908181526020018280546113229061510e565b801561125a5780601f106113445761010080835404028352916020019161125a565b820191906000526020600020905b81548152906001019060200180831161135257505050919092525091949350505050565b61137e6113c9565b61051381611dd8565b61138f6113c9565b60005b81518110156113c5576113bd8282815181106113b0576113b061500c565b6020026020010151611e81565b600101611392565b5050565b6000546001600160a01b031633146114235760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640161079a565b565b60005b81518110156113c55760008282815181106114455761144561500c565b60200260200101519050600081602001519050806001600160401b03166000036114825760405163c656089560e01b815260040160405180910390fd5b81516001600160a01b03166114aa576040516342bcdf7f60e11b815260040160405180910390fd5b6001600160401b038116600090815260066020526040902060608301516001820180546114d69061510e565b905060000361153857815467ffffffffffffffff60a81b1916600160a81b1782556040516001600160401b03841681527ff4c1390c70e5c0f491ae1ccbc06f9117cbbadf2767b247b3bc203280f24c0fb99060200160405180910390a1611575565b8154600160a81b90046001600160401b031660011461157557604051632105803760e11b81526001600160401b038416600482015260240161079a565b805115806115aa5750604080516000602082015201604051602081830303815290604052805190602001208180519060200120145b156115c8576040516342bcdf7f60e11b815260040160405180910390fd5b600182016115d68282615531565b50604080850151835486516001600160a01b03166001600160a01b0319921515600160a01b02929092167fffffffffffffffffffffff00000000000000000000000000000000000000000090911617178355516001600160401b038416907f49f51971edd25182e97182d6ea372a0488ce2ab639f6a3a7ab4df0d2636fe56b906116619085906155f0565b60405180910390a250505050806001019050611428565b6001600160401b03811660009081526006602052604081208054600160a01b900460ff16610ad55760405163ed053c5960e01b81526001600160401b038416600482015260240161079a565b60ff878116600090815260026020908152604080832081516080810183528154815260019091015480861693820193909352610100830485169181019190915262010000909104909216151560608301528735906117238760a461563e565b905082606001511561176b57845161173c906020615345565b8651611749906020615345565b6117549060a061563e565b61175e919061563e565b611768908261563e565b90505b36811461179457604051638e1192e160e01b81526004810182905236602482015260440161079a565b50815181146117c35781516040516324f7d61360e21b815260048101919091526024810182905260440161079a565b6117cb611ac4565b60ff808a166000908152600360209081526040808320338452825280832081518083019092528054808616835293949193909284019161010090910416600281111561181957611819613ef6565b600281111561182a5761182a613ef6565b905250905060028160200151600281111561184757611847613ef6565b14801561189b5750600260008b60ff1660ff168152602001908152602001600020600301816000015160ff16815481106118835761188361500c565b6000918252602090912001546001600160a01b031633145b6118b857604051631b41e11d60e31b815260040160405180910390fd5b508160600151156119685760208201516118d3906001615651565b60ff168551146118f6576040516371253a2560e01b815260040160405180910390fd5b83518551146119185760405163a75d88af60e01b815260040160405180910390fd5b6000878760405161192a92919061566a565b604051908190038120611941918b9060200161567a565b6040516020818303038152906040528051906020012090506119668a828888886121ab565b505b6040805182815260208a8101356001600160401b03169082015260ff8b16917f198d6990ef96613a9026203077e422916918b03ff47f0be6bee7b02d8e139ef0910160405180910390a2505050505050505050565b81516000036119de5760405162bf199760e01b815260040160405180910390fd5b80516040805160008082526020820190925291159181611a21565b6040805180820190915260008152606060208201528152602001906001900390816119f95790505b50905060005b845181101561104357611a77858281518110611a4557611a4561500c565b602002602001015184611a7157858381518110611a6457611a6461500c565b6020026020010151612368565b83612368565b600101611a27565b6001600160401b038216600090815260076020526040812081611aa360808561568e565b6001600160401b031681526020810191909152604001600020549392505050565b467f00000000000000000000000000000000000000000000000000000000000000001461142357604051630f01ce8560e01b81527f0000000000000000000000000000000000000000000000000000000000000000600482015246602482015260440161079a565b606088516001600160401b03811115611b4757611b476139e2565b604051908082528060200260200182016040528015611b8c57816020015b6040805180820190915260008082526020820152815260200190600190039081611b655790505b509050811560005b8a51811015611ccf5781611c2c57848482818110611bb457611bb461500c565b9050602002016020810190611bc991906156b4565b63ffffffff1615611c2c57848482818110611be657611be661500c565b9050602002016020810190611bfb91906156b4565b8b8281518110611c0d57611c0d61500c565b60200260200101516040019063ffffffff16908163ffffffff16815250505b611caa8b8281518110611c4157611c4161500c565b60200260200101518b8b8b8b8b87818110611c5e57611c5e61500c565b9050602002810190611c7091906156cf565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612c5f92505050565b838281518110611cbc57611cbc61500c565b6020908102919091010152600101611b94565b505098975050505050505050565b6000611ce883612f3f565b8015610ad25750610ad28383612f8a565b80516001600160a01b0316611d21576040516342bcdf7f60e11b815260040160405180910390fd5b805160048054602080850180516001600160a01b039586167fffffffffffffffff0000000000000000000000000000000000000000000000009094168417600160a01b63ffffffff928316021790945560408087018051600580546001600160a01b031916918916919091179055815194855291519094169183019190915251909216908201527fa1c15688cb2c24508e158f6942b9276c6f3028a85e1af8cf3fff0c3ff3d5fc8d9060600160405180910390a150565b336001600160a01b03821603611e305760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161079a565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b806040015160ff16600003611eac576000604051631b3fab5160e11b815260040161079a9190615715565b60208082015160ff80821660009081526002909352604083206001810154929390928392169003611efd576060840151600182018054911515620100000262ff000019909216919091179055611f39565b6060840151600182015460ff6201000090910416151590151514611f39576040516321fd80df60e21b815260ff8416600482015260240161079a565b60a084015180516101001015611f65576001604051631b3fab5160e11b815260040161079a9190615715565b8051600003611f8a576005604051631b3fab5160e11b815260040161079a9190615715565b611ff08484600301805480602002602001604051908101604052809291908181526020018280548015611fe657602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611fc8575b505050505061302c565b8460600151156121205761205e8484600201805480602002602001604051908101604052809291908181526020018280548015611fe6576020028201919060005260206000209081546001600160a01b03168152600190910190602001808311611fc857505050505061302c565b60808501518051610100101561208a576002604051631b3fab5160e11b815260040161079a9190615715565b604086015161209a90600361572f565b60ff168151116120c0576003604051631b3fab5160e11b815260040161079a9190615715565b8151815110156120e6576001604051631b3fab5160e11b815260040161079a9190615715565b805160018401805461ff00191661010060ff8416021790556121119060028601906020840190613968565b5061211e85826001613095565b505b61212c84826002613095565b80516121419060038501906020840190613968565b5060408581015160018401805460ff191660ff8316179055865180855560a088015192517fab8b1b57514019638d7b5ce9c638fe71366fe8e2be1c40a7a80f1733d0e9f5479361219a9389939260028a0192919061574b565b60405180910390a1611043846131f0565b8251600090815b8181101561235e5760006001888684602081106121d1576121d161500c565b6121de91901a601b615651565b8985815181106121f0576121f061500c565b602002602001015189868151811061220a5761220a61500c565b602002602001015160405160008152602001604052604051612248949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa15801561226a573d6000803e3d6000fd5b505060408051601f1981015160ff808e166000908152600360209081528582206001600160a01b038516835281528582208587019096528554808416865293975090955092939284019161010090041660028111156122cb576122cb613ef6565b60028111156122dc576122dc613ef6565b90525090506001816020015160028111156122f9576122f9613ef6565b1461231757604051636518c33d60e11b815260040160405180910390fd5b8051600160ff9091161b85161561234157604051633d9ef1f160e21b815260040160405180910390fd5b806000015160ff166001901b8517945050508060010190506121b2565b5050505050505050565b81518151604051632cbc26bb60e01b8152608083901b67ffffffffffffffff60801b166004820152901515907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632cbc26bb90602401602060405180830381865afa1580156123e5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061240991906150f1565b1561247a57801561243857604051637edeb53960e11b81526001600160401b038316600482015260240161079a565b6040516001600160401b03831681527faab522ed53d887e56ed53dd37398a01aeef6a58e0fa77c2173beb9512d8949339060200160405180910390a150505050565b600061248583611678565b60010180546124939061510e565b80601f01602080910402602001604051908101604052809291908181526020018280546124bf9061510e565b801561250c5780601f106124e15761010080835404028352916020019161250c565b820191906000526020600020905b8154815290600101906020018083116124ef57829003601f168201915b5050506020880151519293505050600081900361253b5760405162bf199760e01b815260040160405180910390fd5b8560400151518114612560576040516357e0e08360e01b815260040160405180910390fd5b6000816001600160401b0381111561257a5761257a6139e2565b6040519080825280602002602001820160405280156125a3578160200160208202803683370190505b50905060005b82811015612747576000886020015182815181106125c9576125c961500c565b602002602001015190507f00000000000000000000000000000000000000000000000000000000000000006001600160401b03168160000151604001516001600160401b0316146126405780516040908101519051631c21951160e11b81526001600160401b03909116600482015260240161079a565b866001600160401b03168160000151602001516001600160401b03161461269457805160200151604051636c95f1eb60e01b81526001600160401b03808a166004830152909116602482015260440161079a565b612721817f2425b0b9f9054c76ff151b0a175b18f37a4a4e82013a72e9f15c9caa095ed21f836000015160200151846000015160400151898051906020012060405160200161270694939291909384526001600160401b03928316602085015291166040830152606082015260800190565b60405160208183030381529060405280519060200120613247565b8383815181106127335761273361500c565b6020908102919091010152506001016125a9565b50600061275e86838a606001518b6080015161334f565b90508060000361278c57604051633ee8bd3f60e11b81526001600160401b038716600482015260240161079a565b60005b83811015610a125760005a905060008a6020015183815181106127b4576127b461500c565b6020026020010151905060006127d28a836000015160600151610a86565b905060008160038111156127e8576127e8613ef6565b14806128055750600381600381111561280357612803613ef6565b145b61285b57815160600151604080516001600160401b03808e16825290921660208301527f3b575419319662b2a6f5e2467d84521517a3382b908eb3d557bb3fdb0c50e23c910160405180910390a1505050612c57565b6060891561293a578b85815181106128755761287561500c565b6020908102919091018101510151600454909150600090600160a01b900463ffffffff166128a388426152f6565b11905080806128c3575060038360038111156128c1576128c1613ef6565b145b6128eb576040516354e7e43160e11b81526001600160401b038d16600482015260240161079a565b8c86815181106128fd576128fd61500c565b602002602001015160000151600014612934578c86815181106129225761292261500c565b60209081029190910101515160808501525b506129a6565b600082600381111561294e5761294e613ef6565b146129a657825160600151604080516001600160401b03808f16825290921660208301527f3ef2a99c550a751d4b0b261268f05a803dfb049ab43616a1ffb388f61fe65120910160405180910390a150505050612c57565b8251608001516001600160401b031615612a7f5760008260038111156129ce576129ce613ef6565b03612a7f577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e0e03cae8c85600001516080015186602001516040518463ffffffff1660e01b8152600401612a2f939291906157fd565b6020604051808303816000875af1158015612a4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a7291906150f1565b612a7f5750505050612c57565b60008d604001518681518110612a9757612a9761500c565b6020026020010151905080518460a001515114612ae157835160600151604051631cfe6d8b60e01b81526001600160401b03808f166004830152909116602482015260440161079a565b612af58c856000015160600151600161338c565b600080612b03868486613431565b91509150612b1a8e8760000151606001518461338c565b8c15612b71576003826003811115612b3457612b34613ef6565b03612b71576000856003811115612b4d57612b4d613ef6565b14612b7157855151604051632b11b8d960e01b815261079a91908390600401615829565b6002826003811115612b8557612b85613ef6565b14612bca576003826003811115612b9e57612b9e613ef6565b14612bca578d866000015160600151836040516349362d1f60e11b815260040161079a93929190615842565b8560000151600001518660000151606001516001600160401b03168f6001600160401b03167f05665fe9ad095383d018353f4cbcba77e84db27dd215081bbf7cdf9ae6fbe48b8d8c81518110612c2257612c2261500c565b602002602001015186865a612c37908f6152f6565b604051612c479493929190615867565b60405180910390a4505050505050505b60010161278f565b6040805180820190915260008082526020820152602086015160405163bbe4f6db60e01b81526001600160a01b0380831660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063bbe4f6db90602401602060405180830381865afa158015612ce3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d07919061589e565b90506001600160a01b0381161580612d365750612d346001600160a01b03821663aff2afbf60e01b611cdd565b155b15612d5f5760405163ae9b4ce960e01b81526001600160a01b038216600482015260240161079a565b600080612d7788858c6040015163ffffffff166134e5565b915091506000806000612e2a6040518061010001604052808e81526020018c6001600160401b031681526020018d6001600160a01b031681526020018f608001518152602001896001600160a01b031681526020018f6000015181526020018f6060015181526020018b815250604051602401612df491906158bb565b60408051601f198184030181529190526020810180516001600160e01b0316633907753760e01b179052878661138860846135c8565b92509250925082612e50578160405163e1cd550960e01b815260040161079a9190613d0e565b8151602014612e7f578151604051631e3be00960e21b815260206004820152602481019190915260440161079a565b600082806020019051810190612e959190615987565b9050866001600160a01b03168c6001600160a01b031614612f11576000612ec68d8a612ec1868a6152f6565b6134e5565b50905086811080612ee0575081612edd88836152f6565b14155b15612f0f5760405163a966e21f60e01b815260048101839052602481018890526044810182905260640161079a565b505b604080518082019091526001600160a01b039098168852602088015250949550505050505095945050505050565b6000612f52826301ffc9a760e01b612f8a565b8015610ad55750612f83827fffffffff00000000000000000000000000000000000000000000000000000000612f8a565b1592915050565b6040517fffffffff0000000000000000000000000000000000000000000000000000000082166024820152600090819060440160408051601f19818403018152919052602080820180516001600160e01b03166301ffc9a760e01b178152825192935060009283928392909183918a617530fa92503d91506000519050828015613015575060208210155b80156130215750600081115b979650505050505050565b60005b8151811015610d655760ff8316600090815260036020526040812083519091908490849081106130615761306161500c565b6020908102919091018101516001600160a01b03168252810191909152604001600020805461ffff1916905560010161302f565b60005b8251811015610a805760008382815181106130b5576130b561500c565b60200260200101519050600060028111156130d2576130d2613ef6565b60ff80871660009081526003602090815260408083206001600160a01b0387168452909152902054610100900416600281111561311157613111613ef6565b14613132576004604051631b3fab5160e11b815260040161079a9190615715565b6001600160a01b0381166131595760405163d6c62c9b60e01b815260040160405180910390fd5b60405180604001604052808360ff16815260200184600281111561317f5761317f613ef6565b905260ff80871660009081526003602090815260408083206001600160a01b0387168452825290912083518154931660ff198416811782559184015190929091839161ffff1916176101008360028111156131dc576131dc613ef6565b021790555090505050806001019050613098565b60ff81166105135760ff8082166000908152600260205260409020600101546201000090041661323357604051631e8ed32560e21b815260040160405180910390fd5b6009805467ffffffffffffffff1916905550565b8151805160608085015190830151608080870151940151604051600095869588956132ab95919490939192916020019485526001600160a01b039390931660208501526001600160401b039182166040850152606084015216608082015260a00190565b604051602081830303815290604052805190602001208560200151805190602001208660400151805190602001208760a001516040516020016132ee9190615a41565b60408051601f198184030181528282528051602091820120908301979097528101949094526060840192909252608083015260a082015260c081019190915260e0015b60405160208183030381529060405280519060200120905092915050565b60008061335d8585856136a2565b6001600160401b038716600090815260086020908152604080832093835292905220549150505b949350505050565b6000600261339b60808561531f565b6001600160401b03166133ae9190615345565b905060006133bc8585611a7f565b9050816133cb600160046152f6565b901b1916818360038111156133e2576133e2613ef6565b6001600160401b03871660009081526007602052604081209190921b9290921791829161341060808861568e565b6001600160401b031681526020810191909152604001600020555050505050565b604051630304c3e160e51b815260009060609030906360987c209061345e90889088908890600401615ad8565b600060405180830381600087803b15801561347857600080fd5b505af1925050508015613489575060015b6134c8573d8080156134b7576040519150601f19603f3d011682016040523d82523d6000602084013e6134bc565b606091505b506003925090506134dd565b50506040805160208101909152600081526002905b935093915050565b60008060008060006135468860405160240161351091906001600160a01b0391909116815260200190565b60408051601f198184030181529190526020810180516001600160e01b03166370a0823160e01b179052888861138860846135c8565b9250925092508261356c578160405163e1cd550960e01b815260040161079a9190613d0e565b602082511461359b578151604051631e3be00960e21b815260206004820152602481019190915260440161079a565b818060200190518101906135af9190615987565b6135b982886152f6565b94509450505050935093915050565b6000606060008361ffff166001600160401b038111156135ea576135ea6139e2565b6040519080825280601f01601f191660200182016040528015613614576020820181803683370190505b509150863b61362e5763030ed58f60e21b60005260046000fd5b5a8581101561364857632be8ca8b60e21b60005260046000fd5b8590036040810481038710613668576337c3be2960e01b60005260046000fd5b505a6000808a5160208c0160008c8cf193505a900390503d8481111561368b5750835b808352806000602085013e50955095509592505050565b82518251600091908183036136ca57604051630469ac9960e21b815260040160405180910390fd5b61010182118015906136de57506101018111155b6136fb576040516309bde33960e01b815260040160405180910390fd5b60001982820101610100811115613725576040516309bde33960e01b815260040160405180910390fd5b8060000361375257866000815181106137405761374061500c565b60200260200101519350505050613920565b6000816001600160401b0381111561376c5761376c6139e2565b604051908082528060200260200182016040528015613795578160200160208202803683370190505b50905060008080805b858110156138bf5760006001821b8b8116036137f957888510156137e2578c5160018601958e9181106137d3576137d361500c565b6020026020010151905061381b565b85516001850194879181106137d3576137d361500c565b8b5160018401938d9181106138105761381061500c565b602002602001015190505b60008986101561384b578d5160018701968f91811061383c5761383c61500c565b6020026020010151905061386d565b86516001860195889181106138625761386261500c565b602002602001015190505b8285111561388e576040516309bde33960e01b815260040160405180910390fd5b6138988282613927565b8784815181106138aa576138aa61500c565b6020908102919091010152505060010161379e565b5060018503821480156138d157508683145b80156138dc57508581145b6138f9576040516309bde33960e01b815260040160405180910390fd5b83600186038151811061390e5761390e61500c565b60200260200101519750505050505050505b9392505050565b600081831061393f5761393a8284613945565b610ad2565b610ad283835b604080516001602082015290810183905260608101829052600090608001613331565b8280548282559060005260206000209081019282156139bd579160200282015b828111156139bd57825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190613988565b506139c99291506139cd565b5090565b5b808211156139c957600081556001016139ce565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b0381118282101715613a1a57613a1a6139e2565b60405290565b60405160a081016001600160401b0381118282101715613a1a57613a1a6139e2565b60405160c081016001600160401b0381118282101715613a1a57613a1a6139e2565b604080519081016001600160401b0381118282101715613a1a57613a1a6139e2565b604051601f8201601f191681016001600160401b0381118282101715613aae57613aae6139e2565b604052919050565b60006001600160401b03821115613acf57613acf6139e2565b5060051b60200190565b6001600160a01b038116811461051357600080fd5b80356001600160401b0381168114613b0557600080fd5b919050565b801515811461051357600080fd5b8035613b0581613b0a565b60006001600160401b03821115613b3c57613b3c6139e2565b50601f01601f191660200190565b600082601f830112613b5b57600080fd5b8135613b6e613b6982613b23565b613a86565b818152846020838601011115613b8357600080fd5b816020850160208301376000918101602001919091529392505050565b60006020808385031215613bb357600080fd5b82356001600160401b0380821115613bca57600080fd5b818501915085601f830112613bde57600080fd5b8135613bec613b6982613ab6565b81815260059190911b83018401908481019088831115613c0b57600080fd5b8585015b83811015613cb157803585811115613c275760008081fd5b86016080818c03601f1901811315613c3f5760008081fd5b613c476139f8565b89830135613c5481613ad9565b81526040613c63848201613aee565b8b830152606080850135613c7681613b0a565b83830152928401359289841115613c8f57600091508182fd5b613c9d8f8d86880101613b4a565b908301525085525050918601918601613c0f565b5098975050505050505050565b60005b83811015613cd9578181015183820152602001613cc1565b50506000910152565b60008151808452613cfa816020860160208601613cbe565b601f01601f19169290920160200192915050565b602081526000610ad26020830184613ce2565b8060608101831015610ad557600080fd5b60008083601f840112613d4457600080fd5b5081356001600160401b03811115613d5b57600080fd5b602083019150836020828501011115613d7357600080fd5b9250929050565b60008083601f840112613d8c57600080fd5b5081356001600160401b03811115613da357600080fd5b6020830191508360208260051b8501011115613d7357600080fd5b60008060008060008060008060e0898b031215613dda57600080fd5b613de48a8a613d21565b975060608901356001600160401b0380821115613e0057600080fd5b613e0c8c838d01613d32565b909950975060808b0135915080821115613e2557600080fd5b613e318c838d01613d7a565b909750955060a08b0135915080821115613e4a57600080fd5b50613e578b828c01613d7a565b999c989b50969995989497949560c00135949350505050565b600080600060808486031215613e8557600080fd5b613e8f8585613d21565b925060608401356001600160401b03811115613eaa57600080fd5b613eb686828701613d32565b9497909650939450505050565b60008060408385031215613ed657600080fd5b613edf83613aee565b9150613eed60208401613aee565b90509250929050565b634e487b7160e01b600052602160045260246000fd5b60048110613f1c57613f1c613ef6565b9052565b60208101610ad58284613f0c565b600060a08284031215613f4057600080fd5b613f48613a20565b905081358152613f5a60208301613aee565b6020820152613f6b60408301613aee565b6040820152613f7c60608301613aee565b6060820152613f8d60808301613aee565b608082015292915050565b8035613b0581613ad9565b803563ffffffff81168114613b0557600080fd5b600082601f830112613fc857600080fd5b81356020613fd8613b6983613ab6565b82815260059290921b84018101918181019086841115613ff757600080fd5b8286015b848110156140c75780356001600160401b038082111561401b5760008081fd5b9088019060a0828b03601f19018113156140355760008081fd5b61403d613a20565b878401358381111561404f5760008081fd5b61405d8d8a83880101613b4a565b82525060408085013561406f81613ad9565b828a01526060614080868201613fa3565b8284015260809150818601358581111561409a5760008081fd5b6140a88f8c838a0101613b4a565b9184019190915250919093013590830152508352918301918301613ffb565b509695505050505050565b600061014082840312156140e557600080fd5b6140ed613a42565b90506140f98383613f2e565b815260a08201356001600160401b038082111561411557600080fd5b61412185838601613b4a565b602084015260c084013591508082111561413a57600080fd5b61414685838601613b4a565b604084015261415760e08501613f98565b6060840152610100840135608084015261012084013591508082111561417c57600080fd5b5061418984828501613fb7565b60a08301525092915050565b600082601f8301126141a657600080fd5b813560206141b6613b6983613ab6565b82815260059290921b840181019181810190868411156141d557600080fd5b8286015b848110156140c75780356001600160401b038111156141f85760008081fd5b6142068986838b01016140d2565b8452509183019183016141d9565b600082601f83011261422557600080fd5b81356020614235613b6983613ab6565b82815260059290921b8401810191818101908684111561425457600080fd5b8286015b848110156140c75780356001600160401b038082111561427757600080fd5b818901915089603f83011261428b57600080fd5b8582013561429b613b6982613ab6565b81815260059190911b830160400190878101908c8311156142bb57600080fd5b604085015b838110156142f4578035858111156142d757600080fd5b6142e68f6040838a0101613b4a565b8452509189019189016142c0565b50875250505092840192508301614258565b600082601f83011261431757600080fd5b81356020614327613b6983613ab6565b8083825260208201915060208460051b87010193508684111561434957600080fd5b602086015b848110156140c7578035835291830191830161434e565b600082601f83011261437657600080fd5b81356020614386613b6983613ab6565b82815260059290921b840181019181810190868411156143a557600080fd5b8286015b848110156140c75780356001600160401b03808211156143c95760008081fd5b9088019060a0828b03601f19018113156143e35760008081fd5b6143eb613a20565b6143f6888501613aee565b81526040808501358481111561440c5760008081fd5b61441a8e8b83890101614195565b8a84015250606080860135858111156144335760008081fd5b6144418f8c838a0101614214565b838501525060809150818601358581111561445c5760008081fd5b61446a8f8c838a0101614306565b91840191909152509190930135908301525083529183019183016143a9565b6000806040838503121561449c57600080fd5b6001600160401b03833511156144b157600080fd5b6144be8484358501614365565b91506001600160401b03602084013511156144d857600080fd5b6020830135830184601f8201126144ee57600080fd5b6144fb613b698235613ab6565b81358082526020808301929160051b84010187101561451957600080fd5b602083015b6020843560051b8501018110156146bf576001600160401b038135111561454457600080fd5b87603f82358601011261455657600080fd5b614569613b696020833587010135613ab6565b81358501602081810135808452908301929160059190911b016040018a101561459157600080fd5b604083358701015b83358701602081013560051b016040018110156146af576001600160401b03813511156145c557600080fd5b833587018135016040818d03603f190112156145e057600080fd5b6145e8613a64565b604082013581526001600160401b036060830135111561460757600080fd5b8c605f60608401358401011261461c57600080fd5b6040606083013583010135614633613b6982613ab6565b808282526020820191508f60608460051b606088013588010101111561465857600080fd5b6060808601358601015b60608460051b60608801358801010181101561468f5761468181613fa3565b835260209283019201614662565b508060208501525050508085525050602083019250602081019050614599565b508452506020928301920161451e565b508093505050509250929050565b6000806000806000606086880312156146e557600080fd5b85356001600160401b03808211156146fc57600080fd5b61470889838a016140d2565b9650602088013591508082111561471e57600080fd5b61472a89838a01613d7a565b9096509450604088013591508082111561474357600080fd5b5061475088828901613d7a565b969995985093965092949392505050565b60006060828403121561477357600080fd5b604051606081018181106001600160401b0382111715614795576147956139e2565b60405282356147a381613ad9565b81526147b160208401613fa3565b602082015260408301356147c481613ad9565b60408201529392505050565b6000602082840312156147e257600080fd5b81356001600160401b038111156147f857600080fd5b820160a0818503121561392057600080fd5b803560ff81168114613b0557600080fd5b60006020828403121561482d57600080fd5b610ad28261480a565b60008151808452602080850194506020840160005b838110156148705781516001600160a01b03168752958201959082019060010161484b565b509495945050505050565b60208152600082518051602084015260ff602082015116604084015260ff604082015116606084015260608101511515608084015250602083015160c060a08401526148ca60e0840182614836565b90506040840151601f198483030160c08501526148e78282614836565b95945050505050565b6000806040838503121561490357600080fd5b61490c83613aee565b946020939093013593505050565b60006020828403121561492c57600080fd5b610ad282613aee565b602081526001600160a01b0382511660208201526020820151151560408201526001600160401b0360408301511660608201526000606083015160808084015261338460a0840182613ce2565b60006020828403121561499457600080fd5b813561392081613ad9565b600082601f8301126149b057600080fd5b813560206149c0613b6983613ab6565b8083825260208201915060208460051b8701019350868411156149e257600080fd5b602086015b848110156140c75780356149fa81613ad9565b83529183019183016149e7565b60006020808385031215614a1a57600080fd5b82356001600160401b0380821115614a3157600080fd5b818501915085601f830112614a4557600080fd5b8135614a53613b6982613ab6565b81815260059190911b83018401908481019088831115614a7257600080fd5b8585015b83811015613cb157803585811115614a8d57600080fd5b860160c0818c03601f19011215614aa45760008081fd5b614aac613a42565b8882013581526040614abf81840161480a565b8a8301526060614ad081850161480a565b8284015260809150614ae3828501613b18565b9083015260a08381013589811115614afb5760008081fd5b614b098f8d8388010161499f565b838501525060c0840135915088821115614b235760008081fd5b614b318e8c8487010161499f565b9083015250845250918601918601614a76565b80356001600160e01b0381168114613b0557600080fd5b600082601f830112614b6c57600080fd5b81356020614b7c613b6983613ab6565b82815260069290921b84018101918181019086841115614b9b57600080fd5b8286015b848110156140c75760408189031215614bb85760008081fd5b614bc0613a64565b614bc982613aee565b8152614bd6858301614b44565b81860152835291830191604001614b9f565b600082601f830112614bf957600080fd5b81356020614c09613b6983613ab6565b82815260059290921b84018101918181019086841115614c2857600080fd5b8286015b848110156140c75780356001600160401b0380821115614c4c5760008081fd5b9088019060a0828b03601f1901811315614c665760008081fd5b614c6e613a20565b614c79888501613aee565b815260408085013584811115614c8f5760008081fd5b614c9d8e8b83890101613b4a565b8a8401525060609350614cb1848601613aee565b908201526080614cc2858201613aee565b93820193909352920135908201528352918301918301614c2c565b600082601f830112614cee57600080fd5b81356020614cfe613b6983613ab6565b82815260069290921b84018101918181019086841115614d1d57600080fd5b8286015b848110156140c75760408189031215614d3a5760008081fd5b614d42613a64565b813581528482013585820152835291830191604001614d21565b60006020808385031215614d6f57600080fd5b82356001600160401b0380821115614d8657600080fd5b9084019060808287031215614d9a57600080fd5b614da26139f8565b823582811115614db157600080fd5b83016040818903811315614dc457600080fd5b614dcc613a64565b823585811115614ddb57600080fd5b8301601f81018b13614dec57600080fd5b8035614dfa613b6982613ab6565b81815260069190911b8201890190898101908d831115614e1957600080fd5b928a01925b82841015614e695785848f031215614e365760008081fd5b614e3e613a64565b8435614e4981613ad9565b8152614e56858d01614b44565b818d0152825292850192908a0190614e1e565b845250505082870135915084821115614e8157600080fd5b614e8d8a838501614b5b565b81880152835250508284013582811115614ea657600080fd5b614eb288828601614be8565b85830152506040830135935081841115614ecb57600080fd5b614ed787858501614cdd565b6040820152606083013560608201528094505050505092915050565b600082825180855260208086019550808260051b84010181860160005b84811015614f8457601f19868403018952815160a06001600160401b03808351168652868301518288880152614f4883880182613ce2565b60408581015184169089015260608086015190931692880192909252506080928301519290950191909152509783019790830190600101614f10565b5090979650505050505050565b6001600160a01b038516815260006020608081840152614fb46080840187614ef3565b83810360408581019190915286518083528388019284019060005b81811015614ff457845180518452860151868401529385019391830191600101614fcf565b50508094505050505082606083015295945050505050565b634e487b7160e01b600052603260045260246000fd5b805160408084528151848201819052600092602091908201906060870190855b8181101561507957835180516001600160a01b031684528501516001600160e01b0316858401529284019291850191600101615042565b50508583015187820388850152805180835290840192506000918401905b808310156150d257835180516001600160401b031683528501516001600160e01b031685830152928401926001929092019190850190615097565b50979650505050505050565b602081526000610ad26020830184615022565b60006020828403121561510357600080fd5b815161392081613b0a565b600181811c9082168061512257607f821691505b60208210810361514257634e487b7160e01b600052602260045260246000fd5b50919050565b60008083546151568161510e565b6001828116801561516e5760018114615183576151b2565b60ff19841687528215158302870194506151b2565b8760005260208060002060005b858110156151a95781548a820152908401908201615190565b50505082870194505b50929695505050505050565b600081546151cb8161510e565b8085526020600183811680156151e8576001811461520257615230565b60ff1985168884015283151560051b880183019550615230565b866000528260002060005b858110156152285781548a820186015290830190840161520d565b890184019650505b505050505092915050565b60408152600061524e6040830185613ce2565b82810360208401526148e781856151be565b634e487b7160e01b600052601160045260246000fd5b6001600160401b0381811683821601908082111561529657615296615260565b5092915050565b6040815260006152b06040830185614ef3565b82810360208401526148e78185615022565b6000602082840312156152d457600080fd5b81356001600160401b038111156152ea57600080fd5b61338484828501614365565b81810381811115610ad557610ad5615260565b634e487b7160e01b600052601260045260246000fd5b60006001600160401b038084168061533957615339615309565b92169190910692915050565b8082028115828204841417610ad557610ad5615260565b80518252600060206001600160401b0381840151168185015260408084015160a0604087015261538f60a0870182613ce2565b9050606085015186820360608801526153a88282613ce2565b608087810151898303918a01919091528051808352908601935060009250908501905b808310156150d257835180516001600160a01b03168352860151868301529285019260019290920191908401906153cb565b602081526000610ad2602083018461535c565b608081526000615423608083018761535c565b61ffff9590951660208301525060408101929092526001600160a01b0316606090910152919050565b60008060006060848603121561546157600080fd5b835161546c81613b0a565b60208501519093506001600160401b0381111561548857600080fd5b8401601f8101861361549957600080fd5b80516154a7613b6982613b23565b8181528760208385010111156154bc57600080fd5b6154cd826020830160208601613cbe565b809450505050604084015190509250925092565b601f821115610d65576000816000526020600020601f850160051c8101602086101561550a5750805b601f850160051c820191505b8181101561552957828155600101615516565b505050505050565b81516001600160401b0381111561554a5761554a6139e2565b61555e81615558845461510e565b846154e1565b602080601f831160018114615593576000841561557b5750858301515b600019600386901b1c1916600185901b178555615529565b600085815260208120601f198616915b828110156155c2578886015182559484019460019091019084016155a3565b50858210156155e05787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60208152600082546001600160a01b038116602084015260ff8160a01c16151560408401526001600160401b038160a81c16606084015250608080830152610ad260a08301600185016151be565b80820180821115610ad557610ad5615260565b60ff8181168382160190811115610ad557610ad5615260565b8183823760009101908152919050565b828152606082602083013760800192915050565b60006001600160401b03808416806156a8576156a8615309565b92169190910492915050565b6000602082840312156156c657600080fd5b610ad282613fa3565b6000808335601e198436030181126156e657600080fd5b8301803591506001600160401b0382111561570057600080fd5b602001915036819003821315613d7357600080fd5b602081016006831061572957615729613ef6565b91905290565b60ff818116838216029081169081811461529657615296615260565b600060a0820160ff881683526020878185015260a0604085015281875480845260c0860191508860005282600020935060005b818110156157a35784546001600160a01b03168352600194850194928401920161577e565b50508481036060860152865180825290820192508187019060005b818110156157e35782516001600160a01b0316855293830193918301916001016157be565b50505060ff851660808501525090505b9695505050505050565b60006001600160401b038086168352808516602084015250606060408301526148e76060830184613ce2565b8281526040602082015260006133846040830184613ce2565b6001600160401b03848116825283166020820152606081016133846040830184613f0c565b8481526158776020820185613f0c565b60806040820152600061588d6080830185613ce2565b905082606083015295945050505050565b6000602082840312156158b057600080fd5b815161392081613ad9565b60208152600082516101008060208501526158da610120850183613ce2565b915060208501516158f660408601826001600160401b03169052565b5060408501516001600160a01b03811660608601525060608501516080850152608085015161593060a08601826001600160a01b03169052565b5060a0850151601f19808685030160c087015261594d8483613ce2565b935060c08701519150808685030160e087015261596a8483613ce2565b935060e08701519150808685030183870152506157f38382613ce2565b60006020828403121561599957600080fd5b5051919050565b600082825180855260208086019550808260051b84010181860160005b84811015614f8457601f19868403018952815160a081518186526159e382870182613ce2565b9150506001600160a01b03868301511686860152604063ffffffff8184015116818701525060608083015186830382880152615a1f8382613ce2565b60809485015197909401969096525050988401989250908301906001016159bd565b602081526000610ad260208301846159a0565b60008282518085526020808601955060208260051b8401016020860160005b84811015614f8457601f19868403018952615a8f838351613ce2565b98840198925090830190600101615a73565b60008151808452602080850194506020840160005b8381101561487057815163ffffffff1687529582019590820190600101615ab6565b60608152600084518051606084015260208101516001600160401b0380821660808601528060408401511660a08601528060608401511660c08601528060808401511660e0860152505050602085015161014080610100850152615b406101a0850183613ce2565b91506040870151605f198086850301610120870152615b5f8483613ce2565b935060608901519150615b7c838701836001600160a01b03169052565b608089015161016087015260a0890151925080868503016101808701525050615ba582826159a0565b9150508281036020840152615bba8186615a54565b905082810360408401526157f38185615aa156fea164736f6c6343000818000a", } var OffRampABI = OffRampMetaData.ABI diff --git a/core/gethwrappers/ccip/generated/report_codec/report_codec.go b/core/gethwrappers/ccip/generated/report_codec/report_codec.go index 06ec6c7b41..c693335bc4 100644 --- a/core/gethwrappers/ccip/generated/report_codec/report_codec.go +++ b/core/gethwrappers/ccip/generated/report_codec/report_codec.go @@ -95,11 +95,12 @@ type OffRampCommitReport struct { PriceUpdates InternalPriceUpdates MerkleRoots []InternalMerkleRoot RmnSignatures []IRMNV2Signature + RmnRawVs *big.Int } var ReportCodecMetaData = &bind.MetaData{ - ABI: "[{\"anonymous\":false,\"inputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"structIRMNV2.Signature[]\",\"name\":\"rmnSignatures\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"report\",\"type\":\"tuple\"}],\"name\":\"CommitReportDecoded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"destTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"destGasAmount\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.Any2EVMTokenTransfer[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage[]\",\"name\":\"messages\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[][]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[][]\"},{\"internalType\":\"bytes32[]\",\"name\":\"proofs\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"proofFlagBits\",\"type\":\"uint256\"}],\"indexed\":false,\"internalType\":\"structInternal.ExecutionReportSingleChain[]\",\"name\":\"report\",\"type\":\"tuple[]\"}],\"name\":\"ExecuteReportDecoded\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"decodeCommitReport\",\"outputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"structIRMNV2.Signature[]\",\"name\":\"rmnSignatures\",\"type\":\"tuple[]\"}],\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"decodeExecuteReport\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"destTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"destGasAmount\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.Any2EVMTokenTransfer[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage[]\",\"name\":\"messages\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[][]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[][]\"},{\"internalType\":\"bytes32[]\",\"name\":\"proofs\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"proofFlagBits\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.ExecutionReportSingleChain[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]", - Bin: "0x608060405234801561001057600080fd5b506113c3806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80636fb349561461003b578063f816ec6014610064575b600080fd5b61004e610049366004610231565b610084565b60405161005b91906104ee565b60405180910390f35b610077610072366004610231565b6100a0565b60405161005b9190610833565b60608180602001905181019061009a9190610e6d565b92915050565b6040805160a08101825260608082018181526080830182905282526020808301829052928201528251909161009a918401810190840161122d565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff8111828210171561012d5761012d6100db565b60405290565b60405160c0810167ffffffffffffffff8111828210171561012d5761012d6100db565b6040805190810167ffffffffffffffff8111828210171561012d5761012d6100db565b6040516060810167ffffffffffffffff8111828210171561012d5761012d6100db565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156101e3576101e36100db565b604052919050565b600067ffffffffffffffff821115610205576102056100db565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b60006020828403121561024357600080fd5b813567ffffffffffffffff81111561025a57600080fd5b8201601f8101841361026b57600080fd5b803561027e610279826101eb565b61019c565b81815285602083850101111561029357600080fd5b81602084016020830137600091810160200191909152949350505050565b60005b838110156102cc5781810151838201526020016102b4565b50506000910152565b600081518084526102ed8160208601602086016102b1565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b600082825180855260208086019550808260051b84010181860160005b848110156103eb577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018952815160a08151818652610380828701826102d5565b91505073ffffffffffffffffffffffffffffffffffffffff868301511686860152604063ffffffff81840151168187015250606080830151868303828801526103c983826102d5565b608094850151979094019690965250509884019892509083019060010161033c565b5090979650505050505050565b6000828251808552602080860195506005818360051b8501018287016000805b868110156104a3577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe088850381018c5283518051808752908801908887019080891b88018a01865b8281101561048c57858a830301845261047a8286516102d5565b948c0194938c01939150600101610460565b509e8a019e97505050938701935050600101610418565b50919998505050505050505050565b60008151808452602080850194506020840160005b838110156104e3578151875295820195908201906001016104c7565b509495945050505050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b828110156106d6577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0888603018452815160a0860167ffffffffffffffff8083511688528883015160a08a8a015282815180855260c08b01915060c08160051b8c010194508b8301925060005b8181101561067f577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff408c87030183528351805180518852868f820151168f890152866040820151166040890152866060820151166060890152866080820151166080890152508d81015161014060a08901526106026101408901826102d5565b9050604082015188820360c08a015261061b82826102d5565b915050606082015161064560e08a018273ffffffffffffffffffffffffffffffffffffffff169052565b50608082015161010089015260a0820151915087810361012089015261066b818361031f565b97505050928c0192918c0191600101610582565b50505050506040820151878203604089015261069b82826103f8565b915050606082015187820360608901526106b582826104b2565b60809384015198909301979097525094509285019290850190600101610515565b5092979650505050505050565b60008151808452602080850194506020840160005b838110156104e3578151805167ffffffffffffffff1688528301517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1683880152604090960195908201906001016106f8565b600082825180855260208086019550808260051b84010181860160005b848110156103eb577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018952815160a067ffffffffffffffff8083511686528683015182888801526107bb838801826102d5565b60408581015184169089015260608086015190931692880192909252506080928301519290950191909152509783019790830190600101610764565b60008151808452602080850194506020840160005b838110156104e357815180518852830151838801526040909601959082019060010161080c565b602080825282516060838301528051604060808501819052815160c086018190526000949392840191859160e08801905b808410156108c1578451805173ffffffffffffffffffffffffffffffffffffffff1683528701517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1687830152938601936001939093019290820190610864565b50938501518785037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff800160a0890152936108fb81866106e3565b9450505050508185015191507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08085830301604086015261093c8284610747565b925060408601519150808584030160608601525061095a82826107f7565b95945050505050565b600067ffffffffffffffff82111561097d5761097d6100db565b5060051b60200190565b805167ffffffffffffffff8116811461099f57600080fd5b919050565b600060a082840312156109b657600080fd5b6109be61010a565b9050815181526109d060208301610987565b60208201526109e160408301610987565b60408201526109f260608301610987565b6060820152610a0360808301610987565b608082015292915050565b600082601f830112610a1f57600080fd5b8151610a2d610279826101eb565b818152846020838601011115610a4257600080fd5b610a538260208301602087016102b1565b949350505050565b805173ffffffffffffffffffffffffffffffffffffffff8116811461099f57600080fd5b600082601f830112610a9057600080fd5b81516020610aa061027983610963565b82815260059290921b84018101918181019086841115610abf57600080fd5b8286015b84811015610bbb57805167ffffffffffffffff80821115610ae45760008081fd5b818901915060a0807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848d03011215610b1d5760008081fd5b610b2561010a565b8784015183811115610b375760008081fd5b610b458d8a83880101610a0e565b8252506040610b55818601610a5b565b8983015260608086015163ffffffff81168114610b725760008081fd5b808385015250608091508186015185811115610b8e5760008081fd5b610b9c8f8c838a0101610a0e565b9184019190915250919093015190830152508352918301918301610ac3565b509695505050505050565b600082601f830112610bd757600080fd5b81516020610be761027983610963565b82815260059290921b84018101918181019086841115610c0657600080fd5b8286015b84811015610bbb57805167ffffffffffffffff80821115610c2b5760008081fd5b8189019150610140807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848d03011215610c655760008081fd5b610c6d610133565b610c798c8986016109a4565b815260c084015183811115610c8e5760008081fd5b610c9c8d8a83880101610a0e565b898301525060e084015183811115610cb45760008081fd5b610cc28d8a83880101610a0e565b604083015250610cd56101008501610a5b565b60608201526101208401516080820152908301519082821115610cf85760008081fd5b610d068c8984870101610a7f565b60a08201528652505050918301918301610c0a565b600082601f830112610d2c57600080fd5b81516020610d3c61027983610963565b82815260059290921b84018101918181019086841115610d5b57600080fd5b8286015b84811015610bbb57805167ffffffffffffffff80821115610d7f57600080fd5b818901915089603f830112610d9357600080fd5b85820151610da361027982610963565b81815260059190911b830160400190878101908c831115610dc357600080fd5b604085015b83811015610dfc57805185811115610ddf57600080fd5b610dee8f6040838a0101610a0e565b845250918901918901610dc8565b50875250505092840192508301610d5f565b600082601f830112610e1f57600080fd5b81516020610e2f61027983610963565b8083825260208201915060208460051b870101935086841115610e5157600080fd5b602086015b84811015610bbb5780518352918301918301610e56565b60006020808385031215610e8057600080fd5b825167ffffffffffffffff80821115610e9857600080fd5b818501915085601f830112610eac57600080fd5b8151610eba61027982610963565b81815260059190911b83018401908481019088831115610ed957600080fd5b8585015b83811015610fd357805185811115610ef457600080fd5b860160a0818c037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0011215610f295760008081fd5b610f3161010a565b610f3c898301610987565b815260408083015188811115610f525760008081fd5b610f608e8c83870101610bc6565b8b8401525060608084015189811115610f795760008081fd5b610f878f8d83880101610d1b565b8385015250608091508184015189811115610fa25760008081fd5b610fb08f8d83880101610e0e565b918401919091525060a09290920151918101919091528352918601918601610edd565b5098975050505050505050565b80517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8116811461099f57600080fd5b600082601f83011261101d57600080fd5b8151602061102d61027983610963565b82815260069290921b8401810191818101908684111561104c57600080fd5b8286015b84811015610bbb57604081890312156110695760008081fd5b611071610156565b61107a82610987565b8152611087858301610fe0565b81860152835291830191604001611050565b600082601f8301126110aa57600080fd5b815160206110ba61027983610963565b82815260059290921b840181019181810190868411156110d957600080fd5b8286015b84811015610bbb57805167ffffffffffffffff808211156110fe5760008081fd5b818901915060a0807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848d030112156111375760008081fd5b61113f61010a565b61114a888501610987565b8152604080850151848111156111605760008081fd5b61116e8e8b83890101610a0e565b8a8401525060609350611182848601610987565b908201526080611193858201610987565b938201939093529201519082015283529183019183016110dd565b600082601f8301126111bf57600080fd5b815160206111cf61027983610963565b82815260069290921b840181019181810190868411156111ee57600080fd5b8286015b84811015610bbb576040818903121561120b5760008081fd5b611213610156565b8151815284820151858201528352918301916040016111f2565b6000602080838503121561124057600080fd5b825167ffffffffffffffff8082111561125857600080fd5b908401906060828703121561126c57600080fd5b611274610179565b82518281111561128357600080fd5b8301604081890381131561129657600080fd5b61129e610156565b8251858111156112ad57600080fd5b8301601f81018b136112be57600080fd5b80516112cc61027982610963565b81815260069190911b8201890190898101908d8311156112eb57600080fd5b928a01925b828410156113395785848f0312156113085760008081fd5b611310610156565b61131985610a5b565b81526113268c8601610fe0565b818d0152825292850192908a01906112f0565b84525050508287015191508482111561135157600080fd5b61135d8a83850161100c565b8188015283525050828401518281111561137657600080fd5b61138288828601611099565b8583015250604083015193508184111561139b57600080fd5b6113a7878585016111ae565b6040820152969550505050505056fea164736f6c6343000818000a", + ABI: "[{\"anonymous\":false,\"inputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"structIRMNV2.Signature[]\",\"name\":\"rmnSignatures\",\"type\":\"tuple[]\"},{\"internalType\":\"uint256\",\"name\":\"rmnRawVs\",\"type\":\"uint256\"}],\"indexed\":false,\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"report\",\"type\":\"tuple\"}],\"name\":\"CommitReportDecoded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"destTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"destGasAmount\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.Any2EVMTokenTransfer[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage[]\",\"name\":\"messages\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[][]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[][]\"},{\"internalType\":\"bytes32[]\",\"name\":\"proofs\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"proofFlagBits\",\"type\":\"uint256\"}],\"indexed\":false,\"internalType\":\"structInternal.ExecutionReportSingleChain[]\",\"name\":\"report\",\"type\":\"tuple[]\"}],\"name\":\"ExecuteReportDecoded\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"decodeCommitReport\",\"outputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"structIRMNV2.Signature[]\",\"name\":\"rmnSignatures\",\"type\":\"tuple[]\"},{\"internalType\":\"uint256\",\"name\":\"rmnRawVs\",\"type\":\"uint256\"}],\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"report\",\"type\":\"bytes\"}],\"name\":\"decodeExecuteReport\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"sender\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"sourcePoolAddress\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"destTokenAddress\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"destGasAmount\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.Any2EVMTokenTransfer[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.Any2EVMRampMessage[]\",\"name\":\"messages\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[][]\",\"name\":\"offchainTokenData\",\"type\":\"bytes[][]\"},{\"internalType\":\"bytes32[]\",\"name\":\"proofs\",\"type\":\"bytes32[]\"},{\"internalType\":\"uint256\",\"name\":\"proofFlagBits\",\"type\":\"uint256\"}],\"internalType\":\"structInternal.ExecutionReportSingleChain[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]", + Bin: "0x608060405234801561001057600080fd5b506113e8806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80636fb349561461003b578063f816ec6014610064575b600080fd5b61004e61004936600461023a565b610084565b60405161005b91906104f7565b60405180910390f35b61007761007236600461023a565b6100a0565b60405161005b919061083c565b60608180602001905181019061009a9190610e85565b92915050565b6040805160c08101825260606080820181815260a08301829052825260208083018290529282018190526000908201528251909161009a9184018101908401611245565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff81118282101715610136576101366100e4565b60405290565b60405160c0810167ffffffffffffffff81118282101715610136576101366100e4565b6040805190810167ffffffffffffffff81118282101715610136576101366100e4565b6040516080810167ffffffffffffffff81118282101715610136576101366100e4565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156101ec576101ec6100e4565b604052919050565b600067ffffffffffffffff82111561020e5761020e6100e4565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b60006020828403121561024c57600080fd5b813567ffffffffffffffff81111561026357600080fd5b8201601f8101841361027457600080fd5b8035610287610282826101f4565b6101a5565b81815285602083850101111561029c57600080fd5b81602084016020830137600091810160200191909152949350505050565b60005b838110156102d55781810151838201526020016102bd565b50506000910152565b600081518084526102f68160208601602086016102ba565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b600082825180855260208086019550808260051b84010181860160005b848110156103f4577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018952815160a08151818652610389828701826102de565b91505073ffffffffffffffffffffffffffffffffffffffff868301511686860152604063ffffffff81840151168187015250606080830151868303828801526103d283826102de565b6080948501519790940196909652505098840198925090830190600101610345565b5090979650505050505050565b6000828251808552602080860195506005818360051b8501018287016000805b868110156104ac577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe088850381018c5283518051808752908801908887019080891b88018a01865b8281101561049557858a83030184526104838286516102de565b948c0194938c01939150600101610469565b509e8a019e97505050938701935050600101610421565b50919998505050505050505050565b60008151808452602080850194506020840160005b838110156104ec578151875295820195908201906001016104d0565b509495945050505050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b828110156106df577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0888603018452815160a0860167ffffffffffffffff8083511688528883015160a08a8a015282815180855260c08b01915060c08160051b8c010194508b8301925060005b81811015610688577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff408c87030183528351805180518852868f820151168f890152866040820151166040890152866060820151166060890152866080820151166080890152508d81015161014060a089015261060b6101408901826102de565b9050604082015188820360c08a015261062482826102de565b915050606082015161064e60e08a018273ffffffffffffffffffffffffffffffffffffffff169052565b50608082015161010089015260a082015191508781036101208901526106748183610328565b97505050928c0192918c019160010161058b565b5050505050604082015187820360408901526106a48282610401565b915050606082015187820360608901526106be82826104bb565b6080938401519890930197909752509450928501929085019060010161051e565b5092979650505050505050565b60008151808452602080850194506020840160005b838110156104ec578151805167ffffffffffffffff1688528301517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168388015260409096019590820190600101610701565b600082825180855260208086019550808260051b84010181860160005b848110156103f4577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018952815160a067ffffffffffffffff8083511686528683015182888801526107c4838801826102de565b6040858101518416908901526060808601519093169288019290925250608092830151929095019190915250978301979083019060010161076d565b60008151808452602080850194506020840160005b838110156104ec578151805188528301518388015260409096019590820190600101610815565b602080825282516080838301528051604060a08501819052815160e08601819052600094939284019185916101008801905b808410156108cb578451805173ffffffffffffffffffffffffffffffffffffffff1683528701517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff168783015293860193600193909301929082019061086e565b50938501518785037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600160c08901529361090581866106ec565b9450505050508185015191507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0808583030160408601526109468284610750565b92506040860151915080858403016060860152506109648282610800565b915050606084015160808401528091505092915050565b600067ffffffffffffffff821115610995576109956100e4565b5060051b60200190565b805167ffffffffffffffff811681146109b757600080fd5b919050565b600060a082840312156109ce57600080fd5b6109d6610113565b9050815181526109e86020830161099f565b60208201526109f96040830161099f565b6040820152610a0a6060830161099f565b6060820152610a1b6080830161099f565b608082015292915050565b600082601f830112610a3757600080fd5b8151610a45610282826101f4565b818152846020838601011115610a5a57600080fd5b610a6b8260208301602087016102ba565b949350505050565b805173ffffffffffffffffffffffffffffffffffffffff811681146109b757600080fd5b600082601f830112610aa857600080fd5b81516020610ab86102828361097b565b82815260059290921b84018101918181019086841115610ad757600080fd5b8286015b84811015610bd357805167ffffffffffffffff80821115610afc5760008081fd5b818901915060a0807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848d03011215610b355760008081fd5b610b3d610113565b8784015183811115610b4f5760008081fd5b610b5d8d8a83880101610a26565b8252506040610b6d818601610a73565b8983015260608086015163ffffffff81168114610b8a5760008081fd5b808385015250608091508186015185811115610ba65760008081fd5b610bb48f8c838a0101610a26565b9184019190915250919093015190830152508352918301918301610adb565b509695505050505050565b600082601f830112610bef57600080fd5b81516020610bff6102828361097b565b82815260059290921b84018101918181019086841115610c1e57600080fd5b8286015b84811015610bd357805167ffffffffffffffff80821115610c435760008081fd5b8189019150610140807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848d03011215610c7d5760008081fd5b610c8561013c565b610c918c8986016109bc565b815260c084015183811115610ca65760008081fd5b610cb48d8a83880101610a26565b898301525060e084015183811115610ccc5760008081fd5b610cda8d8a83880101610a26565b604083015250610ced6101008501610a73565b60608201526101208401516080820152908301519082821115610d105760008081fd5b610d1e8c8984870101610a97565b60a08201528652505050918301918301610c22565b600082601f830112610d4457600080fd5b81516020610d546102828361097b565b82815260059290921b84018101918181019086841115610d7357600080fd5b8286015b84811015610bd357805167ffffffffffffffff80821115610d9757600080fd5b818901915089603f830112610dab57600080fd5b85820151610dbb6102828261097b565b81815260059190911b830160400190878101908c831115610ddb57600080fd5b604085015b83811015610e1457805185811115610df757600080fd5b610e068f6040838a0101610a26565b845250918901918901610de0565b50875250505092840192508301610d77565b600082601f830112610e3757600080fd5b81516020610e476102828361097b565b8083825260208201915060208460051b870101935086841115610e6957600080fd5b602086015b84811015610bd35780518352918301918301610e6e565b60006020808385031215610e9857600080fd5b825167ffffffffffffffff80821115610eb057600080fd5b818501915085601f830112610ec457600080fd5b8151610ed26102828261097b565b81815260059190911b83018401908481019088831115610ef157600080fd5b8585015b83811015610feb57805185811115610f0c57600080fd5b860160a0818c037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0011215610f415760008081fd5b610f49610113565b610f5489830161099f565b815260408083015188811115610f6a5760008081fd5b610f788e8c83870101610bde565b8b8401525060608084015189811115610f915760008081fd5b610f9f8f8d83880101610d33565b8385015250608091508184015189811115610fba5760008081fd5b610fc88f8d83880101610e26565b918401919091525060a09290920151918101919091528352918601918601610ef5565b5098975050505050505050565b80517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff811681146109b757600080fd5b600082601f83011261103557600080fd5b815160206110456102828361097b565b82815260069290921b8401810191818101908684111561106457600080fd5b8286015b84811015610bd357604081890312156110815760008081fd5b61108961015f565b6110928261099f565b815261109f858301610ff8565b81860152835291830191604001611068565b600082601f8301126110c257600080fd5b815160206110d26102828361097b565b82815260059290921b840181019181810190868411156110f157600080fd5b8286015b84811015610bd357805167ffffffffffffffff808211156111165760008081fd5b818901915060a0807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0848d0301121561114f5760008081fd5b611157610113565b61116288850161099f565b8152604080850151848111156111785760008081fd5b6111868e8b83890101610a26565b8a840152506060935061119a84860161099f565b9082015260806111ab85820161099f565b938201939093529201519082015283529183019183016110f5565b600082601f8301126111d757600080fd5b815160206111e76102828361097b565b82815260069290921b8401810191818101908684111561120657600080fd5b8286015b84811015610bd357604081890312156112235760008081fd5b61122b61015f565b81518152848201518582015283529183019160400161120a565b6000602080838503121561125857600080fd5b825167ffffffffffffffff8082111561127057600080fd5b908401906080828703121561128457600080fd5b61128c610182565b82518281111561129b57600080fd5b830160408189038113156112ae57600080fd5b6112b661015f565b8251858111156112c557600080fd5b8301601f81018b136112d657600080fd5b80516112e46102828261097b565b81815260069190911b8201890190898101908d83111561130357600080fd5b928a01925b828410156113515785848f0312156113205760008081fd5b61132861015f565b61133185610a73565b815261133e8c8601610ff8565b818d0152825292850192908a0190611308565b84525050508287015191508482111561136957600080fd5b6113758a838501611024565b8188015283525050828401518281111561138e57600080fd5b61139a888286016110b1565b858301525060408301519350818411156113b357600080fd5b6113bf878585016111c6565b604082015260608301516060820152809450505050509291505056fea164736f6c6343000818000a", } var ReportCodecABI = ReportCodecMetaData.ABI @@ -529,7 +530,7 @@ func (_ReportCodec *ReportCodec) ParseLog(log types.Log) (generated.AbigenLog, e } func (ReportCodecCommitReportDecoded) Topic() common.Hash { - return common.HexToHash("0x31a4e1cb25733cdb9679561cd59cdc238d70a7d486f8bfc1f13242efd60fc29d") + return common.HexToHash("0x39ecb9cbf9994ec2d914cd3ec4bff76f953a004c8f16cd9d8fdd5e620b956834") } func (ReportCodecExecuteReportDecoded) Topic() common.Hash { diff --git a/core/gethwrappers/ccip/generated/rmn_remote/rmn_remote.go b/core/gethwrappers/ccip/generated/rmn_remote/rmn_remote.go index bf210e2eb1..f830b9da14 100644 --- a/core/gethwrappers/ccip/generated/rmn_remote/rmn_remote.go +++ b/core/gethwrappers/ccip/generated/rmn_remote/rmn_remote.go @@ -54,21 +54,16 @@ type RMNRemoteSigner struct { NodeIndex uint64 } -type RMNRemoteVersionedConfig struct { - Version uint32 - Config RMNRemoteConfig -} - var RMNRemoteMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"ConfigNotSet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateOnchainPublicKey\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSignature\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSignerOrder\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MinSignersTooHigh\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OutOfOrderSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ThresholdNotMet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnexpectedSigner\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"rmnHomeContractConfigDigest\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"onchainPublicKey\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"nodeIndex\",\"type\":\"uint64\"}],\"internalType\":\"structRMNRemote.Signer[]\",\"name\":\"signers\",\"type\":\"tuple[]\"},{\"internalType\":\"uint64\",\"name\":\"minSigners\",\"type\":\"uint64\"}],\"internalType\":\"structRMNRemote.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"indexed\":false,\"internalType\":\"structRMNRemote.VersionedConfig\",\"name\":\"versionedConfig\",\"type\":\"tuple\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getVersionedConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"rmnHomeContractConfigDigest\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"onchainPublicKey\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"nodeIndex\",\"type\":\"uint64\"}],\"internalType\":\"structRMNRemote.Signer[]\",\"name\":\"signers\",\"type\":\"tuple[]\"},{\"internalType\":\"uint64\",\"name\":\"minSigners\",\"type\":\"uint64\"}],\"internalType\":\"structRMNRemote.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"internalType\":\"structRMNRemote.VersionedConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes16\",\"name\":\"subject\",\"type\":\"bytes16\"}],\"name\":\"isCursed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isCursed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"rmnHomeContractConfigDigest\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"onchainPublicKey\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"nodeIndex\",\"type\":\"uint64\"}],\"internalType\":\"structRMNRemote.Signer[]\",\"name\":\"signers\",\"type\":\"tuple[]\"},{\"internalType\":\"uint64\",\"name\":\"minSigners\",\"type\":\"uint64\"}],\"internalType\":\"structRMNRemote.Config\",\"name\":\"newConfig\",\"type\":\"tuple\"}],\"name\":\"setConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"test\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"destLaneUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"structIRMNV2.Signature[]\",\"name\":\"signatures\",\"type\":\"tuple[]\"}],\"name\":\"verify\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x60a06040523480156200001157600080fd5b50604051620018293803806200182983398101604081905262000034916200017e565b33806000816200008b5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000be57620000be81620000d3565b5050506001600160401b0316608052620001b0565b336001600160a01b038216036200012d5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000082565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000602082840312156200019157600080fd5b81516001600160401b0381168114620001a957600080fd5b9392505050565b608051611660620001c9600039600050506116606000f3fe608060405234801561001057600080fd5b50600436106100be5760003560e01c806379ba509711610076578063ccd5af001161005b578063ccd5af001461019a578063f2fde38b146101ac578063f8a8fd6d1461012857600080fd5b806379ba50971461016a5780638da5cb5b1461017257600080fd5b80631add205f116100a75780631add205f1461012a5780632cbc26bb1461013f578063397796f71461016357600080fd5b8063181f5a77146100c3578063198f0f7714610115575b600080fd5b6100ff6040518060400160405280601381526020017f524d4e52656d6f746520312e362e302d6465760000000000000000000000000081525081565b60405161010c9190610c4b565b60405180910390f35b610128610123366004610c65565b6101bf565b005b6101326105f0565b60405161010c9190610ca0565b61015361014d366004610d58565b50600090565b604051901515815260200161010c565b6000610153565b6101286106d6565b60005460405173ffffffffffffffffffffffffffffffffffffffff909116815260200161010c565b6101286101a8366004610f60565b5050565b6101286101ba366004611137565b610a0d565b6101c7610a23565b60015b6101d76020830183611154565b90508110156102a7576101ed6020830183611154565b828181106101fd576101fd6111c3565b905060400201602001602081019061021591906111f2565b67ffffffffffffffff1661022c6020840184611154565b61023760018561123e565b818110610246576102466111c3565b905060400201602001602081019061025e91906111f2565b67ffffffffffffffff161061029f576040517f4485151700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001016101ca565b506102b56020820182611154565b90506102c760608301604084016111f2565b67ffffffffffffffff161115610309576040517ffba0d9e600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60025b60018101541561040557600180820180546006926000929161032e919061123e565b8154811061033e5761033e6111c3565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055600181018054806103a8576103a8611257565b60008281526020902081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffff0000000000000000000000000000000000000000000000000000000016905501905561030c565b5060005b6104166020830183611154565b905081101561054b57600660006104306020850185611154565b84818110610440576104406111c3565b6104569260206040909202019081019150611137565b73ffffffffffffffffffffffffffffffffffffffff16815260208101919091526040016000205460ff16156104b7576040517f28cae27d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001600660006104ca6020860186611154565b858181106104da576104da6111c3565b6104f09260206040909202019081019150611137565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055600101610409565b50806002610559828261133f565b5050600580546000919082906105749063ffffffff1661147a565b91906101000a81548163ffffffff021916908363ffffffff160217905590507f6cc65868ae41a007e6c3ed18ce591c123dd4e5864b421888c68ce92dae98cea460405180604001604052808363ffffffff168152602001846105d59061149d565b90526040516105e49190610ca0565b60405180910390a15050565b6105f8610b99565b60408051808201825260055463ffffffff1681528151606081018352600280548252600380548551602082810282018101909752818152949580870195858201939092909160009084015b828210156106b1576000848152602090819020604080518082019091529084015473ffffffffffffffffffffffffffffffffffffffff8116825274010000000000000000000000000000000000000000900467ffffffffffffffff1681830152825260019092019101610643565b505050908252506002919091015467ffffffffffffffff166020909101529052919050565b60015473ffffffffffffffffffffffffffffffffffffffff16331461075c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b84518110156109bf5760008582815181106107f5576107f56111c3565b602002602001015190506000600186601b8460000151856020015160405160008152602001604052604051610846949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015610868573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff81166108e0576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1610610945576040517fbbe15e7f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff811660009081526006602052604090205460ff166109a4576040517faaaa914100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b9250826109b08561161b565b945050508060010190506107d8565b5060045467ffffffffffffffff16821015610a06576040517f59fa4a9300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050505050565b610a15610a23565b610a1e81610aa4565b50565b565b60005473ffffffffffffffffffffffffffffffffffffffff163314610a21576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610753565b3373ffffffffffffffffffffffffffffffffffffffff821603610b23576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610753565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6040518060400160405280600063ffffffff168152602001610be260405180606001604052806000801916815260200160608152602001600067ffffffffffffffff1681525090565b905290565b6000815180845260005b81811015610c0d57602081850181015186830182015201610bf1565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000610c5e6020830184610be7565b9392505050565b600060208284031215610c7757600080fd5b813567ffffffffffffffff811115610c8e57600080fd5b820160608185031215610c5e57600080fd5b6000602080835263ffffffff8451168184015280840151604080604086015260c0850182516060870152838301516060608088015281815180845260e0890191508683019350600092505b80831015610d34578351805173ffffffffffffffffffffffffffffffffffffffff16835287015167ffffffffffffffff1687830152928601926001929092019190840190610ceb565b50604085015167ffffffffffffffff811660a08a0152955098975050505050505050565b600060208284031215610d6a57600080fd5b81357fffffffffffffffffffffffffffffffff0000000000000000000000000000000081168114610c5e57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715610dec57610dec610d9a565b60405290565b60405160a0810167ffffffffffffffff81118282101715610dec57610dec610d9a565b6040516060810167ffffffffffffffff81118282101715610dec57610dec610d9a565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715610e7f57610e7f610d9a565b604052919050565b600067ffffffffffffffff821115610ea157610ea1610d9a565b5060051b60200190565b67ffffffffffffffff81168114610a1e57600080fd5b8035610ecc81610eab565b919050565b600082601f830112610ee257600080fd5b81356020610ef7610ef283610e87565b610e38565b82815260069290921b84018101918181019086841115610f1657600080fd5b8286015b84811015610f555760408189031215610f335760008081fd5b610f3b610dc9565b813581528482013585820152835291830191604001610f1a565b509695505050505050565b60008060408385031215610f7357600080fd5b823567ffffffffffffffff80821115610f8b57600080fd5b818501915085601f830112610f9f57600080fd5b81356020610faf610ef283610e87565b82815260059290921b84018101918181019089841115610fce57600080fd5b8286015b848110156110e757803586811115610fe957600080fd5b87017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe060a0828e038201121561101e57600080fd5b611026610df2565b8683013561103381610eab565b815260408301358981111561104757600080fd5b8301603f81018f1361105857600080fd5b878101358a81111561106c5761106c610d9a565b61107c8985601f84011601610e38565b93508084528f604082840101111561109357600080fd5b80604083018a8601376000898286010152505081878201526110b760608401610ec1565b60408201526110c860808401610ec1565b606082015260a092909201356080830152508352918301918301610fd2565b50965050860135925050808211156110fe57600080fd5b5061110b85828601610ed1565b9150509250929050565b73ffffffffffffffffffffffffffffffffffffffff81168114610a1e57600080fd5b60006020828403121561114957600080fd5b8135610c5e81611115565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261118957600080fd5b83018035915067ffffffffffffffff8211156111a457600080fd5b6020019150600681901b36038213156111bc57600080fd5b9250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561120457600080fd5b8135610c5e81610eab565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818103818111156112515761125161120f565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b6000813561125181610eab565b813561129e81611115565b73ffffffffffffffffffffffffffffffffffffffff811690508154817fffffffffffffffffffffffff0000000000000000000000000000000000000000821617835560208401356112ee81610eab565b7bffffffffffffffff00000000000000000000000000000000000000008160a01b16837fffffffff000000000000000000000000000000000000000000000000000000008416171784555050505050565b81358155600180820160208401357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe185360301811261137d57600080fd5b8401803567ffffffffffffffff81111561139657600080fd5b6020820191508060061b36038213156113ae57600080fd5b680100000000000000008111156113c7576113c7610d9a565b8254818455808210156113fc576000848152602081208381019083015b808210156113f857828255908701906113e4565b5050505b50600092835260208320925b8181101561142c5761141a8385611293565b92840192604092909201918401611408565b50505050506101a861144060408401611286565b6002830167ffffffffffffffff82167fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000008254161781555050565b600063ffffffff8083168181036114935761149361120f565b6001019392505050565b6000606082360312156114af57600080fd5b6114b7610e15565b8235815260208084013567ffffffffffffffff8111156114d657600080fd5b840136601f8201126114e757600080fd5b80356114f5610ef282610e87565b81815260069190911b8201830190838101903683111561151457600080fd5b928401925b8284101561156a57604084360312156115325760008081fd5b61153a610dc9565b843561154581611115565b81528486013561155481610eab565b8187015282526040939093019290840190611519565b8085870152505050505061158060408401610ec1565b604082015292915050565b81811015611608577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee08d8a030184528751868151168a528a810151848c8c01526115d7858c0182610be7565b828e015189168c8f01528983015189168a8d0152918701519a87019a909a529850968901969289019260010161158b565b50969d9c50505050505050505050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361164c5761164c61120f565b506001019056fea164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"localChainSelector\",\"type\":\"uint64\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"bytes16\",\"name\":\"subject\",\"type\":\"bytes16\"}],\"name\":\"AlreadyCursed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConfigNotSet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateOnchainPublicKey\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSignature\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSignerOrder\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MinSignersTooHigh\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes16\",\"name\":\"subject\",\"type\":\"bytes16\"}],\"name\":\"NotCursed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OutOfOrderSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ThresholdNotMet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnexpectedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroValueNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"rmnHomeContractConfigDigest\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"onchainPublicKey\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"nodeIndex\",\"type\":\"uint64\"}],\"internalType\":\"structRMNRemote.Signer[]\",\"name\":\"signers\",\"type\":\"tuple[]\"},{\"internalType\":\"uint64\",\"name\":\"minSigners\",\"type\":\"uint64\"}],\"indexed\":false,\"internalType\":\"structRMNRemote.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes16[]\",\"name\":\"subjects\",\"type\":\"bytes16[]\"}],\"name\":\"Cursed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes16[]\",\"name\":\"subjects\",\"type\":\"bytes16[]\"}],\"name\":\"Uncursed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes16\",\"name\":\"subject\",\"type\":\"bytes16\"}],\"name\":\"curse\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes16[]\",\"name\":\"subjects\",\"type\":\"bytes16[]\"}],\"name\":\"curse\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCursedSubjects\",\"outputs\":[{\"internalType\":\"bytes16[]\",\"name\":\"subjects\",\"type\":\"bytes16[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLocalChainSelector\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"localChainSelector\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getVersionedConfig\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"rmnHomeContractConfigDigest\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"onchainPublicKey\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"nodeIndex\",\"type\":\"uint64\"}],\"internalType\":\"structRMNRemote.Signer[]\",\"name\":\"signers\",\"type\":\"tuple[]\"},{\"internalType\":\"uint64\",\"name\":\"minSigners\",\"type\":\"uint64\"}],\"internalType\":\"structRMNRemote.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes16\",\"name\":\"subject\",\"type\":\"bytes16\"}],\"name\":\"isCursed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isCursed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"rmnHomeContractConfigDigest\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"onchainPublicKey\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"nodeIndex\",\"type\":\"uint64\"}],\"internalType\":\"structRMNRemote.Signer[]\",\"name\":\"signers\",\"type\":\"tuple[]\"},{\"internalType\":\"uint64\",\"name\":\"minSigners\",\"type\":\"uint64\"}],\"internalType\":\"structRMNRemote.Config\",\"name\":\"newConfig\",\"type\":\"tuple\"}],\"name\":\"setConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes16\",\"name\":\"subject\",\"type\":\"bytes16\"}],\"name\":\"uncurse\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes16[]\",\"name\":\"subjects\",\"type\":\"bytes16[]\"}],\"name\":\"uncurse\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"offrampAddress\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"structIRMNV2.Signature[]\",\"name\":\"signatures\",\"type\":\"tuple[]\"},{\"internalType\":\"uint256\",\"name\":\"rawVs\",\"type\":\"uint256\"}],\"name\":\"verify\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x60a06040523480156200001157600080fd5b5060405162002131380380620021318339810160408190526200003491620001a9565b33806000816200008b5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000be57620000be81620000fe565b505050806001600160401b0316600003620000ec5760405163273e150360e21b815260040160405180910390fd5b6001600160401b0316608052620001db565b336001600160a01b03821603620001585760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000082565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600060208284031215620001bc57600080fd5b81516001600160401b0381168114620001d457600080fd5b9392505050565b608051611f33620001fe600039600081816102410152610a920152611f336000f3fe608060405234801561001057600080fd5b50600436106100f55760003560e01c806379ba509711610097578063d881e09211610066578063d881e0921461021e578063eaa83ddd14610233578063f2fde38b1461026b578063f8bb876e1461027e57600080fd5b806379ba5097146101c85780638d8741cb146101d05780638da5cb5b146101e35780639a19b3291461020b57600080fd5b80632cbc26bb116100d35780632cbc26bb14610177578063397796f71461019a57806362eed415146101a25780636d2d3993146101b557600080fd5b8063181f5a77146100fa578063198f0f771461014c5780631add205f14610161575b600080fd5b6101366040518060400160405280601381526020017f524d4e52656d6f746520312e362e302d6465760000000000000000000000000081525081565b6040516101439190611380565b60405180910390f35b61015f61015a366004611393565b610291565b005b61016961063d565b6040516101439291906113ce565b61018a6101853660046114ac565b610735565b6040519015158152602001610143565b61018a610792565b61015f6101b03660046114ac565b61080c565b61015f6101c33660046114ac565b610880565b61015f6108f0565b61015f6101de366004611535565b6109f2565b60005460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610143565b61015f6102193660046116bc565b610d46565b610226610e43565b6040516101439190611759565b60405167ffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152602001610143565b61015f6102793660046117bf565b610e4f565b61015f61028c3660046116bc565b610e63565b610299610f55565b60015b6102a960208301836117dc565b9050811015610379576102bf60208301836117dc565b828181106102cf576102cf611844565b90506040020160200160208101906102e79190611894565b67ffffffffffffffff166102fe60208401846117dc565b6103096001856118e0565b81811061031857610318611844565b90506040020160200160208101906103309190611894565b67ffffffffffffffff1610610371576040517f4485151700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60010161029c565b5061038760208201826117dc565b90506103996060830160408401611894565b67ffffffffffffffff1611156103db576040517ffba0d9e600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6003545b801561046d576008600060036103f66001856118e0565b8154811061040657610406611844565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055610466816118f3565b90506103df565b5060005b61047e60208301836117dc565b90508110156105b3576008600061049860208501856117dc565b848181106104a8576104a8611844565b6104be92602060409092020190810191506117bf565b73ffffffffffffffffffffffffffffffffffffffff16815260208101919091526040016000205460ff161561051f576040517f28cae27d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60016008600061053260208601866117dc565b8581811061054257610542611844565b61055892602060409092020190810191506117bf565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055600101610471565b508060026105c182826119e1565b5050600580546000919082906105dc9063ffffffff16611b1c565b91906101000a81548163ffffffff021916908363ffffffff160217905590508063ffffffff167f7f22bf988149dbe8de8fb879c6b97a4e56e68b2bd57421ce1a4e79d4ef6b496c836040516106319190611b3f565b60405180910390a25050565b6040805160608082018352600080835260208301919091529181018290526005546040805160608101825260028054825260038054845160208281028201810190965281815263ffffffff9096169592948593818601939092909160009084015b8282101561070c576000848152602090819020604080518082019091529084015473ffffffffffffffffffffffffffffffffffffffff8116825274010000000000000000000000000000000000000000900467ffffffffffffffff168183015282526001909201910161069e565b505050908252506002919091015467ffffffffffffffff16602090910152919491935090915050565b60006107416006610fd8565b60000361075057506000919050565b61075b600683610fe2565b8061078c575061078c60067f0100000000000000000000000000000100000000000000000000000000000000610fe2565b92915050565b600061079e6006610fd8565b6000036107ab5750600090565b6107d660067f0100000000000000000000000000000000000000000000000000000000000000610fe2565b80610807575061080760067f0100000000000000000000000000000100000000000000000000000000000000610fe2565b905090565b60408051600180825281830190925260009160208083019080368337019050509050818160008151811061084257610842611844565b7fffffffffffffffffffffffffffffffff000000000000000000000000000000009092166020928302919091019091015261087c81610e63565b5050565b6040805160018082528183019092526000916020808301908036833701905050905081816000815181106108b6576108b6611844565b7fffffffffffffffffffffffffffffffff000000000000000000000000000000009092166020928302919091019091015261087c81610d46565b60015473ffffffffffffffffffffffffffffffffffffffff163314610976576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b60055463ffffffff16600003610a34576040517face124bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60045467ffffffffffffffff16821015610a7a576040517f59fa4a9300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160c08101825246815267ffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166020820152309181019190915273ffffffffffffffffffffffffffffffffffffffff8716606082015260025460808201526000907f9651943783dbf81935a60e98f218a9d9b5b28823fb2228bbd91320d632facf539060a08101610b16888a611c49565b9052604051610b29929190602001611da9565b60405160208183030381529060405280519060200120905060008060005b85811015610d3a57600184610b6182841b8816601b611ede565b898985818110610b7357610b73611844565b905060400201600001358a8a86818110610b8f57610b8f611844565b9050604002016020013560405160008152602001604052604051610bcf949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015610bf1573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015192505073ffffffffffffffffffffffffffffffffffffffff8216610c69576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1610610cce576040517fbbe15e7f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff821660009081526008602052604090205460ff16610d2d576040517faaaa914100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b9091508190600101610b47565b50505050505050505050565b610d4e610f55565b60005b8151811015610e0857610d87828281518110610d6f57610d6f611844565b6020026020010151600661102090919063ffffffff16565b610e0057818181518110610d9d57610d9d611844565b60200260200101516040517f73281fa100000000000000000000000000000000000000000000000000000000815260040161096d91907fffffffffffffffffffffffffffffffff0000000000000000000000000000000091909116815260200190565b600101610d51565b507f0676e709c9cc74fa0519fd78f7c33be0f1b2b0bae0507c724aef7229379c6ba181604051610e389190611759565b60405180910390a150565b6060610807600661104e565b610e57610f55565b610e608161105b565b50565b610e6b610f55565b60005b8151811015610f2557610ea4828281518110610e8c57610e8c611844565b6020026020010151600661115090919063ffffffff16565b610f1d57818181518110610eba57610eba611844565b60200260200101516040517f19d5c79b00000000000000000000000000000000000000000000000000000000815260040161096d91907fffffffffffffffffffffffffffffffff0000000000000000000000000000000091909116815260200190565b600101610e6e565b507f1716e663a90a76d3b6c7e5f680673d1b051454c19c627e184c8daf28f3104f7481604051610e389190611759565b60005473ffffffffffffffffffffffffffffffffffffffff163314610fd6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640161096d565b565b600061078c825490565b7fffffffffffffffffffffffffffffffff000000000000000000000000000000008116600090815260018301602052604081205415155b9392505050565b6000611019837fffffffffffffffffffffffffffffffff00000000000000000000000000000000841661117e565b6060600061101983611271565b3373ffffffffffffffffffffffffffffffffffffffff8216036110da576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161096d565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000611019837fffffffffffffffffffffffffffffffff0000000000000000000000000000000084166112cd565b600081815260018301602052604081205480156112675760006111a26001836118e0565b85549091506000906111b6906001906118e0565b905080821461121b5760008660000182815481106111d6576111d6611844565b90600052602060002001549050808760000184815481106111f9576111f9611844565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061122c5761122c611ef7565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061078c565b600091505061078c565b6060816000018054806020026020016040519081016040528092919081815260200182805480156112c157602002820191906000526020600020905b8154815260200190600101908083116112ad575b50505050509050919050565b60008181526001830160205260408120546113145750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561078c565b50600061078c565b6000815180845260005b8181101561134257602081850181015186830182015201611326565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000611019602083018461131c565b6000602082840312156113a557600080fd5b813567ffffffffffffffff8111156113bc57600080fd5b82016060818503121561101957600080fd5b63ffffffff831681526040602080830182905283518383015283810151606080850152805160a085018190526000939291820190849060c08701905b80831015611453578351805173ffffffffffffffffffffffffffffffffffffffff16835285015167ffffffffffffffff168583015292840192600192909201919085019061140a565b50604088015167ffffffffffffffff81166080890152945098975050505050505050565b80357fffffffffffffffffffffffffffffffff00000000000000000000000000000000811681146114a757600080fd5b919050565b6000602082840312156114be57600080fd5b61101982611477565b73ffffffffffffffffffffffffffffffffffffffff81168114610e6057600080fd5b60008083601f8401126114fb57600080fd5b50813567ffffffffffffffff81111561151357600080fd5b6020830191508360208260061b850101111561152e57600080fd5b9250929050565b6000806000806000806080878903121561154e57600080fd5b8635611559816114c7565b9550602087013567ffffffffffffffff8082111561157657600080fd5b818901915089601f83011261158a57600080fd5b81358181111561159957600080fd5b8a60208260051b85010111156115ae57600080fd5b6020830197508096505060408901359150808211156115cc57600080fd5b506115d989828a016114e9565b979a9699509497949695606090950135949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff81118282101715611643576116436115f1565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611690576116906115f1565b604052919050565b600067ffffffffffffffff8211156116b2576116b26115f1565b5060051b60200190565b600060208083850312156116cf57600080fd5b823567ffffffffffffffff8111156116e657600080fd5b8301601f810185136116f757600080fd5b803561170a61170582611698565b611649565b81815260059190911b8201830190838101908783111561172957600080fd5b928401925b8284101561174e5761173f84611477565b8252928401929084019061172e565b979650505050505050565b6020808252825182820181905260009190848201906040850190845b818110156117b35783517fffffffffffffffffffffffffffffffff000000000000000000000000000000001683529284019291840191600101611775565b50909695505050505050565b6000602082840312156117d157600080fd5b8135611019816114c7565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261181157600080fd5b83018035915067ffffffffffffffff82111561182c57600080fd5b6020019150600681901b360382131561152e57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b67ffffffffffffffff81168114610e6057600080fd5b80356114a781611873565b6000602082840312156118a657600080fd5b813561101981611873565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8181038181111561078c5761078c6118b1565b600081611902576119026118b1565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b6000813561078c81611873565b8135611940816114c7565b73ffffffffffffffffffffffffffffffffffffffff811690508154817fffffffffffffffffffffffff00000000000000000000000000000000000000008216178355602084013561199081611873565b7bffffffffffffffff00000000000000000000000000000000000000008160a01b16837fffffffff000000000000000000000000000000000000000000000000000000008416171784555050505050565b81358155600180820160208401357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1853603018112611a1f57600080fd5b8401803567ffffffffffffffff811115611a3857600080fd5b6020820191508060061b3603821315611a5057600080fd5b68010000000000000000811115611a6957611a696115f1565b825481845580821015611a9e576000848152602081208381019083015b80821015611a9a5782825590870190611a86565b5050505b50600092835260208320925b81811015611ace57611abc8385611935565b92840192604092909201918401611aaa565b505050505061087c611ae260408401611928565b6002830167ffffffffffffffff82167fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000008254161781555050565b600063ffffffff808316818103611b3557611b356118b1565b6001019392505050565b6000602080835260808301843582850152818501357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1863603018112611b8457600080fd5b8501828101903567ffffffffffffffff80821115611ba157600080fd5b8160061b3603831315611bb357600080fd5b6040606060408901528483865260a089019050849550600094505b83851015611c1e578535611be1816114c7565b73ffffffffffffffffffffffffffffffffffffffff16815285870135611c0681611873565b83168188015294810194600194909401938101611bce565b611c2a60408b01611889565b67ffffffffffffffff811660608b015296509998505050505050505050565b6000611c5761170584611698565b80848252602080830192508560051b850136811115611c7557600080fd5b855b81811015611d9d57803567ffffffffffffffff80821115611c985760008081fd5b818901915060a08236031215611cae5760008081fd5b611cb6611620565b8235611cc181611873565b81528286013582811115611cd55760008081fd5b8301601f3681830112611ce85760008081fd5b813584811115611cfa57611cfa6115f1565b611d29897fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08484011601611649565b94508085523689828501011115611d4257600091508182fd5b808984018a8701376000898287010152505050818682015260409150611d69828401611889565b8282015260609150611d7c828401611889565b91810191909152608091820135918101919091528552938201938201611c77565b50919695505050505050565b60006040848352602060408185015261010084018551604086015281860151606067ffffffffffffffff808316606089015260408901519250608073ffffffffffffffffffffffffffffffffffffffff80851660808b015260608b0151945060a081861660a08c015260808c015160c08c015260a08c0151955060c060e08c015286915085518088526101209750878c019250878160051b8d01019750888701965060005b81811015611ecb577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee08d8a030184528751868151168a528a810151848c8c0152611e9a858c018261131c565b828e015189168c8f01528983015189168a8d0152918701519a87019a909a5298509689019692890192600101611e4e565b50969d9c50505050505050505050505050565b60ff818116838216019081111561078c5761078c6118b1565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea164736f6c6343000818000a", } var RMNRemoteABI = RMNRemoteMetaData.ABI var RMNRemoteBin = RMNRemoteMetaData.Bin -func DeployRMNRemote(auth *bind.TransactOpts, backend bind.ContractBackend, chainSelector uint64) (common.Address, *types.Transaction, *RMNRemote, error) { +func DeployRMNRemote(auth *bind.TransactOpts, backend bind.ContractBackend, localChainSelector uint64) (common.Address, *types.Transaction, *RMNRemote, error) { parsed, err := RMNRemoteMetaData.GetAbi() if err != nil { return common.Address{}, nil, nil, err @@ -77,7 +72,7 @@ func DeployRMNRemote(auth *bind.TransactOpts, backend bind.ContractBackend, chai return common.Address{}, nil, nil, errors.New("GetABI returned nil") } - address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(RMNRemoteBin), backend, chainSelector) + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(RMNRemoteBin), backend, localChainSelector) if err != nil { return common.Address{}, nil, nil, err } @@ -200,25 +195,77 @@ func (_RMNRemote *RMNRemoteTransactorRaw) Transact(opts *bind.TransactOpts, meth return _RMNRemote.Contract.contract.Transact(opts, method, params...) } -func (_RMNRemote *RMNRemoteCaller) GetVersionedConfig(opts *bind.CallOpts) (RMNRemoteVersionedConfig, error) { +func (_RMNRemote *RMNRemoteCaller) GetCursedSubjects(opts *bind.CallOpts) ([][16]byte, error) { var out []interface{} - err := _RMNRemote.contract.Call(opts, &out, "getVersionedConfig") + err := _RMNRemote.contract.Call(opts, &out, "getCursedSubjects") + + if err != nil { + return *new([][16]byte), err + } + + out0 := *abi.ConvertType(out[0], new([][16]byte)).(*[][16]byte) + + return out0, err + +} + +func (_RMNRemote *RMNRemoteSession) GetCursedSubjects() ([][16]byte, error) { + return _RMNRemote.Contract.GetCursedSubjects(&_RMNRemote.CallOpts) +} + +func (_RMNRemote *RMNRemoteCallerSession) GetCursedSubjects() ([][16]byte, error) { + return _RMNRemote.Contract.GetCursedSubjects(&_RMNRemote.CallOpts) +} + +func (_RMNRemote *RMNRemoteCaller) GetLocalChainSelector(opts *bind.CallOpts) (uint64, error) { + var out []interface{} + err := _RMNRemote.contract.Call(opts, &out, "getLocalChainSelector") if err != nil { - return *new(RMNRemoteVersionedConfig), err + return *new(uint64), err } - out0 := *abi.ConvertType(out[0], new(RMNRemoteVersionedConfig)).(*RMNRemoteVersionedConfig) + out0 := *abi.ConvertType(out[0], new(uint64)).(*uint64) return out0, err } -func (_RMNRemote *RMNRemoteSession) GetVersionedConfig() (RMNRemoteVersionedConfig, error) { +func (_RMNRemote *RMNRemoteSession) GetLocalChainSelector() (uint64, error) { + return _RMNRemote.Contract.GetLocalChainSelector(&_RMNRemote.CallOpts) +} + +func (_RMNRemote *RMNRemoteCallerSession) GetLocalChainSelector() (uint64, error) { + return _RMNRemote.Contract.GetLocalChainSelector(&_RMNRemote.CallOpts) +} + +func (_RMNRemote *RMNRemoteCaller) GetVersionedConfig(opts *bind.CallOpts) (GetVersionedConfig, + + error) { + var out []interface{} + err := _RMNRemote.contract.Call(opts, &out, "getVersionedConfig") + + outstruct := new(GetVersionedConfig) + if err != nil { + return *outstruct, err + } + + outstruct.Version = *abi.ConvertType(out[0], new(uint32)).(*uint32) + outstruct.Config = *abi.ConvertType(out[1], new(RMNRemoteConfig)).(*RMNRemoteConfig) + + return *outstruct, err + +} + +func (_RMNRemote *RMNRemoteSession) GetVersionedConfig() (GetVersionedConfig, + + error) { return _RMNRemote.Contract.GetVersionedConfig(&_RMNRemote.CallOpts) } -func (_RMNRemote *RMNRemoteCallerSession) GetVersionedConfig() (RMNRemoteVersionedConfig, error) { +func (_RMNRemote *RMNRemoteCallerSession) GetVersionedConfig() (GetVersionedConfig, + + error) { return _RMNRemote.Contract.GetVersionedConfig(&_RMNRemote.CallOpts) } @@ -310,9 +357,9 @@ func (_RMNRemote *RMNRemoteCallerSession) TypeAndVersion() (string, error) { return _RMNRemote.Contract.TypeAndVersion(&_RMNRemote.CallOpts) } -func (_RMNRemote *RMNRemoteCaller) Verify(opts *bind.CallOpts, destLaneUpdates []InternalMerkleRoot, signatures []IRMNV2Signature) error { +func (_RMNRemote *RMNRemoteCaller) Verify(opts *bind.CallOpts, offrampAddress common.Address, merkleRoots []InternalMerkleRoot, signatures []IRMNV2Signature, rawVs *big.Int) error { var out []interface{} - err := _RMNRemote.contract.Call(opts, &out, "verify", destLaneUpdates, signatures) + err := _RMNRemote.contract.Call(opts, &out, "verify", offrampAddress, merkleRoots, signatures, rawVs) if err != nil { return err @@ -322,12 +369,12 @@ func (_RMNRemote *RMNRemoteCaller) Verify(opts *bind.CallOpts, destLaneUpdates [ } -func (_RMNRemote *RMNRemoteSession) Verify(destLaneUpdates []InternalMerkleRoot, signatures []IRMNV2Signature) error { - return _RMNRemote.Contract.Verify(&_RMNRemote.CallOpts, destLaneUpdates, signatures) +func (_RMNRemote *RMNRemoteSession) Verify(offrampAddress common.Address, merkleRoots []InternalMerkleRoot, signatures []IRMNV2Signature, rawVs *big.Int) error { + return _RMNRemote.Contract.Verify(&_RMNRemote.CallOpts, offrampAddress, merkleRoots, signatures, rawVs) } -func (_RMNRemote *RMNRemoteCallerSession) Verify(destLaneUpdates []InternalMerkleRoot, signatures []IRMNV2Signature) error { - return _RMNRemote.Contract.Verify(&_RMNRemote.CallOpts, destLaneUpdates, signatures) +func (_RMNRemote *RMNRemoteCallerSession) Verify(offrampAddress common.Address, merkleRoots []InternalMerkleRoot, signatures []IRMNV2Signature, rawVs *big.Int) error { + return _RMNRemote.Contract.Verify(&_RMNRemote.CallOpts, offrampAddress, merkleRoots, signatures, rawVs) } func (_RMNRemote *RMNRemoteTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { @@ -342,28 +389,40 @@ func (_RMNRemote *RMNRemoteTransactorSession) AcceptOwnership() (*types.Transact return _RMNRemote.Contract.AcceptOwnership(&_RMNRemote.TransactOpts) } -func (_RMNRemote *RMNRemoteTransactor) SetConfig(opts *bind.TransactOpts, newConfig RMNRemoteConfig) (*types.Transaction, error) { - return _RMNRemote.contract.Transact(opts, "setConfig", newConfig) +func (_RMNRemote *RMNRemoteTransactor) Curse(opts *bind.TransactOpts, subject [16]byte) (*types.Transaction, error) { + return _RMNRemote.contract.Transact(opts, "curse", subject) } -func (_RMNRemote *RMNRemoteSession) SetConfig(newConfig RMNRemoteConfig) (*types.Transaction, error) { - return _RMNRemote.Contract.SetConfig(&_RMNRemote.TransactOpts, newConfig) +func (_RMNRemote *RMNRemoteSession) Curse(subject [16]byte) (*types.Transaction, error) { + return _RMNRemote.Contract.Curse(&_RMNRemote.TransactOpts, subject) } -func (_RMNRemote *RMNRemoteTransactorSession) SetConfig(newConfig RMNRemoteConfig) (*types.Transaction, error) { - return _RMNRemote.Contract.SetConfig(&_RMNRemote.TransactOpts, newConfig) +func (_RMNRemote *RMNRemoteTransactorSession) Curse(subject [16]byte) (*types.Transaction, error) { + return _RMNRemote.Contract.Curse(&_RMNRemote.TransactOpts, subject) +} + +func (_RMNRemote *RMNRemoteTransactor) Curse0(opts *bind.TransactOpts, subjects [][16]byte) (*types.Transaction, error) { + return _RMNRemote.contract.Transact(opts, "curse0", subjects) +} + +func (_RMNRemote *RMNRemoteSession) Curse0(subjects [][16]byte) (*types.Transaction, error) { + return _RMNRemote.Contract.Curse0(&_RMNRemote.TransactOpts, subjects) } -func (_RMNRemote *RMNRemoteTransactor) Test(opts *bind.TransactOpts) (*types.Transaction, error) { - return _RMNRemote.contract.Transact(opts, "test") +func (_RMNRemote *RMNRemoteTransactorSession) Curse0(subjects [][16]byte) (*types.Transaction, error) { + return _RMNRemote.Contract.Curse0(&_RMNRemote.TransactOpts, subjects) } -func (_RMNRemote *RMNRemoteSession) Test() (*types.Transaction, error) { - return _RMNRemote.Contract.Test(&_RMNRemote.TransactOpts) +func (_RMNRemote *RMNRemoteTransactor) SetConfig(opts *bind.TransactOpts, newConfig RMNRemoteConfig) (*types.Transaction, error) { + return _RMNRemote.contract.Transact(opts, "setConfig", newConfig) } -func (_RMNRemote *RMNRemoteTransactorSession) Test() (*types.Transaction, error) { - return _RMNRemote.Contract.Test(&_RMNRemote.TransactOpts) +func (_RMNRemote *RMNRemoteSession) SetConfig(newConfig RMNRemoteConfig) (*types.Transaction, error) { + return _RMNRemote.Contract.SetConfig(&_RMNRemote.TransactOpts, newConfig) +} + +func (_RMNRemote *RMNRemoteTransactorSession) SetConfig(newConfig RMNRemoteConfig) (*types.Transaction, error) { + return _RMNRemote.Contract.SetConfig(&_RMNRemote.TransactOpts, newConfig) } func (_RMNRemote *RMNRemoteTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { @@ -378,6 +437,30 @@ func (_RMNRemote *RMNRemoteTransactorSession) TransferOwnership(to common.Addres return _RMNRemote.Contract.TransferOwnership(&_RMNRemote.TransactOpts, to) } +func (_RMNRemote *RMNRemoteTransactor) Uncurse(opts *bind.TransactOpts, subject [16]byte) (*types.Transaction, error) { + return _RMNRemote.contract.Transact(opts, "uncurse", subject) +} + +func (_RMNRemote *RMNRemoteSession) Uncurse(subject [16]byte) (*types.Transaction, error) { + return _RMNRemote.Contract.Uncurse(&_RMNRemote.TransactOpts, subject) +} + +func (_RMNRemote *RMNRemoteTransactorSession) Uncurse(subject [16]byte) (*types.Transaction, error) { + return _RMNRemote.Contract.Uncurse(&_RMNRemote.TransactOpts, subject) +} + +func (_RMNRemote *RMNRemoteTransactor) Uncurse0(opts *bind.TransactOpts, subjects [][16]byte) (*types.Transaction, error) { + return _RMNRemote.contract.Transact(opts, "uncurse0", subjects) +} + +func (_RMNRemote *RMNRemoteSession) Uncurse0(subjects [][16]byte) (*types.Transaction, error) { + return _RMNRemote.Contract.Uncurse0(&_RMNRemote.TransactOpts, subjects) +} + +func (_RMNRemote *RMNRemoteTransactorSession) Uncurse0(subjects [][16]byte) (*types.Transaction, error) { + return _RMNRemote.Contract.Uncurse0(&_RMNRemote.TransactOpts, subjects) +} + type RMNRemoteConfigSetIterator struct { Event *RMNRemoteConfigSet @@ -439,22 +522,33 @@ func (it *RMNRemoteConfigSetIterator) Close() error { } type RMNRemoteConfigSet struct { - VersionedConfig RMNRemoteVersionedConfig - Raw types.Log + Version uint32 + Config RMNRemoteConfig + Raw types.Log } -func (_RMNRemote *RMNRemoteFilterer) FilterConfigSet(opts *bind.FilterOpts) (*RMNRemoteConfigSetIterator, error) { +func (_RMNRemote *RMNRemoteFilterer) FilterConfigSet(opts *bind.FilterOpts, version []uint32) (*RMNRemoteConfigSetIterator, error) { - logs, sub, err := _RMNRemote.contract.FilterLogs(opts, "ConfigSet") + var versionRule []interface{} + for _, versionItem := range version { + versionRule = append(versionRule, versionItem) + } + + logs, sub, err := _RMNRemote.contract.FilterLogs(opts, "ConfigSet", versionRule) if err != nil { return nil, err } return &RMNRemoteConfigSetIterator{contract: _RMNRemote.contract, event: "ConfigSet", logs: logs, sub: sub}, nil } -func (_RMNRemote *RMNRemoteFilterer) WatchConfigSet(opts *bind.WatchOpts, sink chan<- *RMNRemoteConfigSet) (event.Subscription, error) { +func (_RMNRemote *RMNRemoteFilterer) WatchConfigSet(opts *bind.WatchOpts, sink chan<- *RMNRemoteConfigSet, version []uint32) (event.Subscription, error) { + + var versionRule []interface{} + for _, versionItem := range version { + versionRule = append(versionRule, versionItem) + } - logs, sub, err := _RMNRemote.contract.WatchLogs(opts, "ConfigSet") + logs, sub, err := _RMNRemote.contract.WatchLogs(opts, "ConfigSet", versionRule) if err != nil { return nil, err } @@ -495,6 +589,123 @@ func (_RMNRemote *RMNRemoteFilterer) ParseConfigSet(log types.Log) (*RMNRemoteCo return event, nil } +type RMNRemoteCursedIterator struct { + Event *RMNRemoteCursed + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *RMNRemoteCursedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(RMNRemoteCursed) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(RMNRemoteCursed) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *RMNRemoteCursedIterator) Error() error { + return it.fail +} + +func (it *RMNRemoteCursedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type RMNRemoteCursed struct { + Subjects [][16]byte + Raw types.Log +} + +func (_RMNRemote *RMNRemoteFilterer) FilterCursed(opts *bind.FilterOpts) (*RMNRemoteCursedIterator, error) { + + logs, sub, err := _RMNRemote.contract.FilterLogs(opts, "Cursed") + if err != nil { + return nil, err + } + return &RMNRemoteCursedIterator{contract: _RMNRemote.contract, event: "Cursed", logs: logs, sub: sub}, nil +} + +func (_RMNRemote *RMNRemoteFilterer) WatchCursed(opts *bind.WatchOpts, sink chan<- *RMNRemoteCursed) (event.Subscription, error) { + + logs, sub, err := _RMNRemote.contract.WatchLogs(opts, "Cursed") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(RMNRemoteCursed) + if err := _RMNRemote.contract.UnpackLog(event, "Cursed", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_RMNRemote *RMNRemoteFilterer) ParseCursed(log types.Log) (*RMNRemoteCursed, error) { + event := new(RMNRemoteCursed) + if err := _RMNRemote.contract.UnpackLog(event, "Cursed", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + type RMNRemoteOwnershipTransferRequestedIterator struct { Event *RMNRemoteOwnershipTransferRequested @@ -767,14 +978,140 @@ func (_RMNRemote *RMNRemoteFilterer) ParseOwnershipTransferred(log types.Log) (* return event, nil } +type RMNRemoteUncursedIterator struct { + Event *RMNRemoteUncursed + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *RMNRemoteUncursedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(RMNRemoteUncursed) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(RMNRemoteUncursed) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *RMNRemoteUncursedIterator) Error() error { + return it.fail +} + +func (it *RMNRemoteUncursedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type RMNRemoteUncursed struct { + Subjects [][16]byte + Raw types.Log +} + +func (_RMNRemote *RMNRemoteFilterer) FilterUncursed(opts *bind.FilterOpts) (*RMNRemoteUncursedIterator, error) { + + logs, sub, err := _RMNRemote.contract.FilterLogs(opts, "Uncursed") + if err != nil { + return nil, err + } + return &RMNRemoteUncursedIterator{contract: _RMNRemote.contract, event: "Uncursed", logs: logs, sub: sub}, nil +} + +func (_RMNRemote *RMNRemoteFilterer) WatchUncursed(opts *bind.WatchOpts, sink chan<- *RMNRemoteUncursed) (event.Subscription, error) { + + logs, sub, err := _RMNRemote.contract.WatchLogs(opts, "Uncursed") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(RMNRemoteUncursed) + if err := _RMNRemote.contract.UnpackLog(event, "Uncursed", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_RMNRemote *RMNRemoteFilterer) ParseUncursed(log types.Log) (*RMNRemoteUncursed, error) { + event := new(RMNRemoteUncursed) + if err := _RMNRemote.contract.UnpackLog(event, "Uncursed", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type GetVersionedConfig struct { + Version uint32 + Config RMNRemoteConfig +} + func (_RMNRemote *RMNRemote) ParseLog(log types.Log) (generated.AbigenLog, error) { switch log.Topics[0] { case _RMNRemote.abi.Events["ConfigSet"].ID: return _RMNRemote.ParseConfigSet(log) + case _RMNRemote.abi.Events["Cursed"].ID: + return _RMNRemote.ParseCursed(log) case _RMNRemote.abi.Events["OwnershipTransferRequested"].ID: return _RMNRemote.ParseOwnershipTransferRequested(log) case _RMNRemote.abi.Events["OwnershipTransferred"].ID: return _RMNRemote.ParseOwnershipTransferred(log) + case _RMNRemote.abi.Events["Uncursed"].ID: + return _RMNRemote.ParseUncursed(log) default: return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) @@ -782,7 +1119,11 @@ func (_RMNRemote *RMNRemote) ParseLog(log types.Log) (generated.AbigenLog, error } func (RMNRemoteConfigSet) Topic() common.Hash { - return common.HexToHash("0x6cc65868ae41a007e6c3ed18ce591c123dd4e5864b421888c68ce92dae98cea4") + return common.HexToHash("0x7f22bf988149dbe8de8fb879c6b97a4e56e68b2bd57421ce1a4e79d4ef6b496c") +} + +func (RMNRemoteCursed) Topic() common.Hash { + return common.HexToHash("0x1716e663a90a76d3b6c7e5f680673d1b051454c19c627e184c8daf28f3104f74") } func (RMNRemoteOwnershipTransferRequested) Topic() common.Hash { @@ -793,12 +1134,22 @@ func (RMNRemoteOwnershipTransferred) Topic() common.Hash { return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") } +func (RMNRemoteUncursed) Topic() common.Hash { + return common.HexToHash("0x0676e709c9cc74fa0519fd78f7c33be0f1b2b0bae0507c724aef7229379c6ba1") +} + func (_RMNRemote *RMNRemote) Address() common.Address { return _RMNRemote.address } type RMNRemoteInterface interface { - GetVersionedConfig(opts *bind.CallOpts) (RMNRemoteVersionedConfig, error) + GetCursedSubjects(opts *bind.CallOpts) ([][16]byte, error) + + GetLocalChainSelector(opts *bind.CallOpts) (uint64, error) + + GetVersionedConfig(opts *bind.CallOpts) (GetVersionedConfig, + + error) IsCursed(opts *bind.CallOpts, subject [16]byte) (bool, error) @@ -808,22 +1159,34 @@ type RMNRemoteInterface interface { TypeAndVersion(opts *bind.CallOpts) (string, error) - Verify(opts *bind.CallOpts, destLaneUpdates []InternalMerkleRoot, signatures []IRMNV2Signature) error + Verify(opts *bind.CallOpts, offrampAddress common.Address, merkleRoots []InternalMerkleRoot, signatures []IRMNV2Signature, rawVs *big.Int) error AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) - SetConfig(opts *bind.TransactOpts, newConfig RMNRemoteConfig) (*types.Transaction, error) + Curse(opts *bind.TransactOpts, subject [16]byte) (*types.Transaction, error) + + Curse0(opts *bind.TransactOpts, subjects [][16]byte) (*types.Transaction, error) - Test(opts *bind.TransactOpts) (*types.Transaction, error) + SetConfig(opts *bind.TransactOpts, newConfig RMNRemoteConfig) (*types.Transaction, error) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) - FilterConfigSet(opts *bind.FilterOpts) (*RMNRemoteConfigSetIterator, error) + Uncurse(opts *bind.TransactOpts, subject [16]byte) (*types.Transaction, error) + + Uncurse0(opts *bind.TransactOpts, subjects [][16]byte) (*types.Transaction, error) + + FilterConfigSet(opts *bind.FilterOpts, version []uint32) (*RMNRemoteConfigSetIterator, error) - WatchConfigSet(opts *bind.WatchOpts, sink chan<- *RMNRemoteConfigSet) (event.Subscription, error) + WatchConfigSet(opts *bind.WatchOpts, sink chan<- *RMNRemoteConfigSet, version []uint32) (event.Subscription, error) ParseConfigSet(log types.Log) (*RMNRemoteConfigSet, error) + FilterCursed(opts *bind.FilterOpts) (*RMNRemoteCursedIterator, error) + + WatchCursed(opts *bind.WatchOpts, sink chan<- *RMNRemoteCursed) (event.Subscription, error) + + ParseCursed(log types.Log) (*RMNRemoteCursed, error) + FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*RMNRemoteOwnershipTransferRequestedIterator, error) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *RMNRemoteOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) @@ -836,6 +1199,12 @@ type RMNRemoteInterface interface { ParseOwnershipTransferred(log types.Log) (*RMNRemoteOwnershipTransferred, error) + FilterUncursed(opts *bind.FilterOpts) (*RMNRemoteUncursedIterator, error) + + WatchUncursed(opts *bind.WatchOpts, sink chan<- *RMNRemoteUncursed) (event.Subscription, error) + + ParseUncursed(log types.Log) (*RMNRemoteUncursed, error) + ParseLog(log types.Log) (generated.AbigenLog, error) Address() common.Address diff --git a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt index c71e5d53dd..8a70af06e5 100644 --- a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -5,8 +5,8 @@ burn_mint_token_pool_and_proxy: ../../../contracts/solc/v0.8.24/BurnMintTokenPoo burn_with_from_mint_token_pool: ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.abi ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.bin 6333d0314d0bd29e75ea5e05fe62a4516ade0c6db91c30b6f93645035db52ed8 burn_with_from_mint_token_pool_and_proxy: ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPoolAndProxy/BurnWithFromMintTokenPoolAndProxy.abi ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPoolAndProxy/BurnWithFromMintTokenPoolAndProxy.bin 08ed1235dda921ce8841b26aa18d0c0f36db4884779dd7670857159801b6d597 ccip_config: ../../../contracts/solc/v0.8.24/CCIPConfig/CCIPConfig.abi ../../../contracts/solc/v0.8.24/CCIPConfig/CCIPConfig.bin f67d4a98804a9534a6554da3a57779632d55ad76db5ecc16ade74774769cdd69 -ccip_encoding_utils: ../../../contracts/solc/v0.8.24/CCIPEncodingUtils/CCIPEncodingUtils.abi ../../../contracts/solc/v0.8.24/CCIPEncodingUtils/CCIPEncodingUtils.bin 1d48b49fc0668c4f8c5e19a208cf4cae124a9a5c361e7900fbc35b97a62dd1bc -ccip_reader_tester: ../../../contracts/solc/v0.8.24/CCIPReaderTester/CCIPReaderTester.abi ../../../contracts/solc/v0.8.24/CCIPReaderTester/CCIPReaderTester.bin f6405e2c1e76b22810953572079710a5aa28d1171c70d3a0dc3ca8b365c8df1c +ccip_encoding_utils: ../../../contracts/solc/v0.8.24/CCIPEncodingUtils/CCIPEncodingUtils.abi ../../../contracts/solc/v0.8.24/CCIPEncodingUtils/CCIPEncodingUtils.bin ebabd5311ad4374df0f2f5cd5640bb58d938d92f5a82962ac4df7b6e5af2c197 +ccip_reader_tester: ../../../contracts/solc/v0.8.24/CCIPReaderTester/CCIPReaderTester.abi ../../../contracts/solc/v0.8.24/CCIPReaderTester/CCIPReaderTester.bin 1181c7150062d6f0793beb50cb6b984c7f7adef0b9528ef1b419923fffcfdcac commit_store: ../../../contracts/solc/v0.8.24/CommitStore/CommitStore.abi ../../../contracts/solc/v0.8.24/CommitStore/CommitStore.bin 274d87db70b643e00ab0a7e7845bb4b791f3b613bfc87708d33fc5a8369e2a41 commit_store_helper: ../../../contracts/solc/v0.8.24/CommitStoreHelper/CommitStoreHelper.abi ../../../contracts/solc/v0.8.24/CommitStoreHelper/CommitStoreHelper.bin f7128dcc2ee6dbcbc976288abcc16970ffb19b59412c5202ef6b259d2007f801 ether_sender_receiver: ../../../contracts/solc/v0.8.24/EtherSenderReceiver/EtherSenderReceiver.abi ../../../contracts/solc/v0.8.24/EtherSenderReceiver/EtherSenderReceiver.bin 09510a3f773f108a3c231e8d202835c845ded862d071ec54c4f89c12d868b8de @@ -24,15 +24,15 @@ multi_aggregate_rate_limiter: ../../../contracts/solc/v0.8.24/MultiAggregateRate multi_ocr3_helper: ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Helper.abi ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Helper.bin 04b6b261dd71925670bf4d904aaf7bf08543452009feefb88e07d4c49d12e969 nonce_manager: ../../../contracts/solc/v0.8.24/NonceManager/NonceManager.abi ../../../contracts/solc/v0.8.24/NonceManager/NonceManager.bin 6f64e1083b356c06ee66b9138e398b9c97a4cd3e8c9ec38cf3010cebc79af536 ocr3_config_encoder: ../../../contracts/solc/v0.8.24/IOCR3ConfigEncoder/IOCR3ConfigEncoder.abi ../../../contracts/solc/v0.8.24/IOCR3ConfigEncoder/IOCR3ConfigEncoder.bin d507c3ac70a7d1033b75151c1e5b854b41aaee164dfaa3e5477de400db1aa1f7 -offramp: ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.abi ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.bin 2eb54a0993aee70490421597d0ada1de92abe0929d415b56f527ba52050bb948 +offramp: ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.abi ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.bin 941b18b4e2aef977195fefba514e17c9475667e6f8513b18cabfb07ff90136ce onramp: ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.abi ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.bin 1f31a62ebb3fa5f4702ee27d4fa86604de5afff56787ef67c8dac764eefd2956 ping_pong_demo: ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.abi ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.bin c1c2f8a65c7ffd971899cae7fe62f2da57d09e936151e2b92163c4bebe699d6b price_registry: ../../../contracts/solc/v0.8.24/PriceRegistry/PriceRegistry.abi ../../../contracts/solc/v0.8.24/PriceRegistry/PriceRegistry.bin e7781d600c1bb7aa4620106af7f6e146a109b97f4cb6a7d06c9e15773340ecb2 registry_module_owner_custom: ../../../contracts/solc/v0.8.24/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.abi ../../../contracts/solc/v0.8.24/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.bin 75be86323c227917a9bbc3f799d7ed02f92db546653a36db30ed0ebe64461353 -report_codec: ../../../contracts/solc/v0.8.24/ReportCodec/ReportCodec.abi ../../../contracts/solc/v0.8.24/ReportCodec/ReportCodec.bin 314427fc02cbf208d6b27197b89bb98bb81d1b9b18dc46e6a761cdc024b1e538 +report_codec: ../../../contracts/solc/v0.8.24/ReportCodec/ReportCodec.abi ../../../contracts/solc/v0.8.24/ReportCodec/ReportCodec.bin 7413576693f76bac7c01fbaec4a161d37a1de51b13dcab78455d2c484ed938b1 rmn_contract: ../../../contracts/solc/v0.8.24/RMN/RMN.abi ../../../contracts/solc/v0.8.24/RMN/RMN.bin 8b45b0fb08631c6b582fd3c0b4052a79cc2b4e091e6286af1ab131bef63661f9 rmn_proxy_contract: ../../../contracts/solc/v0.8.24/ARMProxy/ARMProxy.abi ../../../contracts/solc/v0.8.24/ARMProxy/ARMProxy.bin b048d8e752e3c41113ebb305c1efa06737ad36b4907b93e627fb0a3113023454 -rmn_remote: ../../../contracts/solc/v0.8.24/RMNRemote/RMNRemote.abi ../../../contracts/solc/v0.8.24/RMNRemote/RMNRemote.bin c58cc9f0102413373f45882e87d69b4bf9a4f4516ecfa866584618a1384a8416 +rmn_remote: ../../../contracts/solc/v0.8.24/RMNRemote/RMNRemote.abi ../../../contracts/solc/v0.8.24/RMNRemote/RMNRemote.bin ed08711d211cbe7e2ed389838864a33044fa5a95c4a2fcdeb4ac049d1c225475 router: ../../../contracts/solc/v0.8.24/Router/Router.abi ../../../contracts/solc/v0.8.24/Router/Router.bin 2e4f0a7826c8abb49d882bb49fc5ff20a186dbd3137624b9097ffed903ae4888 self_funded_ping_pong: ../../../contracts/solc/v0.8.24/SelfFundedPingPong/SelfFundedPingPong.abi ../../../contracts/solc/v0.8.24/SelfFundedPingPong/SelfFundedPingPong.bin 8ea5d75dbc3f8afd90d22c4a665a94e02892259cd16520c1c6b4cf0dc80c9148 token_admin_registry: ../../../contracts/solc/v0.8.24/TokenAdminRegistry/TokenAdminRegistry.abi ../../../contracts/solc/v0.8.24/TokenAdminRegistry/TokenAdminRegistry.bin 942be7d1681ac102e0615bee13f76838ebb0b261697cf1270d2bf82c12e57aeb diff --git a/tools/ci/ccip_lcov_prune b/tools/ci/ccip_lcov_prune index 494b2d526c..9ec51e5353 100755 --- a/tools/ci/ccip_lcov_prune +++ b/tools/ci/ccip_lcov_prune @@ -27,4 +27,5 @@ lcov --remove $1 -o $2 \ 'src/v0.8/tests/MockV3Aggregator.sol' \ 'src/v0.8/ccip/applications/CCIPClientExample.sol' \ 'src/v0.8/ccip/pools/BurnWithFromMintTokenPool.sol' \ + 'src/v0.8/ccip/rmn/RMNHome.sol' \ --rc lcov_branch_coverage=1 \ No newline at end of file From 0a2d96055489a0701d9fbf13c75fae082c3443da Mon Sep 17 00:00:00 2001 From: Ryan Hall <RyanRHall@users.noreply.github.com> Date: Wed, 18 Sep 2024 12:28:55 -0400 Subject: [PATCH 102/115] Add RMN_V1_6_ANY2EVM_REPORT to RMNRemote and make public (#1447) ## Motivation https://github.com/smartcontractkit/ccip/pull/1431#discussion_r1763653570 ## Solution Expose the constant as public --- contracts/gas-snapshots/ccip.gas-snapshot | 12 ++++---- contracts/src/v0.8/ccip/rmn/RMNRemote.sol | 12 ++++++-- .../v0.8/ccip/test/rmn/RMNRemoteSetup.t.sol | 4 +-- .../ccip/generated/rmn_remote/rmn_remote.go | 28 +++++++++++++++++-- ...rapper-dependency-versions-do-not-edit.txt | 2 +- 5 files changed, 44 insertions(+), 14 deletions(-) diff --git a/contracts/gas-snapshots/ccip.gas-snapshot b/contracts/gas-snapshots/ccip.gas-snapshot index 7562ea5cb3..9861ed236c 100644 --- a/contracts/gas-snapshots/ccip.gas-snapshot +++ b/contracts/gas-snapshots/ccip.gas-snapshot @@ -810,11 +810,11 @@ PingPong_plumbing:test_Pausing_Success() (gas: 17810) PingPong_startPingPong:test_StartPingPong_With_OOO_Success() (gas: 162091) PingPong_startPingPong:test_StartPingPong_With_Sequenced_Ordered_Success() (gas: 181509) RMNRemote_constructor:test_constructor_success() (gas: 8334) -RMNRemote_constructor:test_constructor_zeroChainSelector_reverts() (gas: 59151) +RMNRemote_constructor:test_constructor_zeroChainSelector_reverts() (gas: 59165) RMNRemote_curse:test_curse_AlreadyCursed_duplicateSubject_reverts() (gas: 154457) RMNRemote_curse:test_curse_calledByNonOwner_reverts() (gas: 18780) -RMNRemote_curse:test_curse_success() (gas: 149164) -RMNRemote_global_and_legacy_curses:test_global_and_legacy_curses_success() (gas: 133319) +RMNRemote_curse:test_curse_success() (gas: 149365) +RMNRemote_global_and_legacy_curses:test_global_and_legacy_curses_success() (gas: 133464) RMNRemote_setConfig:test_setConfig_addSigner_removeSigner_success() (gas: 976479) RMNRemote_setConfig:test_setConfig_duplicateOnChainPublicKey_reverts() (gas: 323272) RMNRemote_setConfig:test_setConfig_invalidSignerOrder_reverts() (gas: 80138) @@ -822,13 +822,13 @@ RMNRemote_setConfig:test_setConfig_minSignersIs0_success() (gas: 700548) RMNRemote_setConfig:test_setConfig_minSignersTooHigh_reverts() (gas: 54024) RMNRemote_uncurse:test_uncurse_NotCursed_duplicatedUncurseSubject_reverts() (gas: 51912) RMNRemote_uncurse:test_uncurse_calledByNonOwner_reverts() (gas: 18748) -RMNRemote_uncurse:test_uncurse_success() (gas: 40044) +RMNRemote_uncurse:test_uncurse_success() (gas: 40151) RMNRemote_verify_withConfigNotSet:test_verify_reverts() (gas: 13650) RMNRemote_verify_withConfigSet:test_verify_InvalidSignature_reverts() (gas: 78519) RMNRemote_verify_withConfigSet:test_verify_OutOfOrderSignatures_duplicateSignature_reverts() (gas: 76336) RMNRemote_verify_withConfigSet:test_verify_OutOfOrderSignatures_not_sorted_reverts() (gas: 83399) -RMNRemote_verify_withConfigSet:test_verify_ThresholdNotMet_reverts() (gas: 152265) -RMNRemote_verify_withConfigSet:test_verify_UnexpectedSigner_reverts() (gas: 386487) +RMNRemote_verify_withConfigSet:test_verify_ThresholdNotMet_reverts() (gas: 153002) +RMNRemote_verify_withConfigSet:test_verify_UnexpectedSigner_reverts() (gas: 387667) RMNRemote_verify_withConfigSet:test_verify_minSignersIsZero_success() (gas: 184524) RMNRemote_verify_withConfigSet:test_verify_success() (gas: 68207) RMN_constructor:test_Constructor_Success() (gas: 48994) diff --git a/contracts/src/v0.8/ccip/rmn/RMNRemote.sol b/contracts/src/v0.8/ccip/rmn/RMNRemote.sol index 1a7270d846..88fdd20577 100644 --- a/contracts/src/v0.8/ccip/rmn/RMNRemote.sol +++ b/contracts/src/v0.8/ccip/rmn/RMNRemote.sol @@ -8,9 +8,6 @@ import {OwnerIsCreator} from "../../shared/access/OwnerIsCreator.sol"; import {EnumerableSet} from "../../shared/enumerable/EnumerableSetWithBytes16.sol"; import {Internal} from "../libraries/Internal.sol"; -/// @dev this is included in the preimage of the digest that RMN nodes sign -bytes32 constant RMN_V1_6_ANY2EVM_REPORT = keccak256("RMN_V1_6_ANY2EVM_REPORT"); - /// @dev An active curse on this subject will cause isCursed() to return true. Use this subject if there is an issue with a /// remote chain, for which there exists a legacy lane contract deployed on the same chain as this RMN contract is /// deployed, relying on isCursed(). @@ -66,6 +63,9 @@ contract RMNRemote is OwnerIsCreator, ITypeAndVersion, IRMNV2 { Internal.MerkleRoot[] merkleRoots; // The dest lane updates } + /// @dev this is included in the preimage of the digest that RMN nodes sign + bytes32 private constant RMN_V1_6_ANY2EVM_REPORT = keccak256("RMN_V1_6_ANY2EVM_REPORT"); + string public constant override typeAndVersion = "RMNRemote 1.6.0-dev"; uint64 internal immutable i_localChainSelector; @@ -174,6 +174,12 @@ contract RMNRemote is OwnerIsCreator, ITypeAndVersion, IRMNV2 { return i_localChainSelector; } + /// @notice Returns the 32 byte header used in computing the report digest + /// @return digestHeader the digest header + function getReportDigestHeader() external pure returns (bytes32 digestHeader) { + return RMN_V1_6_ANY2EVM_REPORT; + } + // ================================================================ // │ Cursing │ // ================================================================ diff --git a/contracts/src/v0.8/ccip/test/rmn/RMNRemoteSetup.t.sol b/contracts/src/v0.8/ccip/test/rmn/RMNRemoteSetup.t.sol index 01bd5bd1b6..6896cb91c6 100644 --- a/contracts/src/v0.8/ccip/test/rmn/RMNRemoteSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/rmn/RMNRemoteSetup.t.sol @@ -3,7 +3,7 @@ pragma solidity 0.8.24; import {IRMNV2} from "../../interfaces/IRMNV2.sol"; import {Internal} from "../../libraries/Internal.sol"; -import {RMNRemote, RMN_V1_6_ANY2EVM_REPORT} from "../../rmn/RMNRemote.sol"; +import {RMNRemote} from "../../rmn/RMNRemote.sol"; import {BaseTest} from "../BaseTest.t.sol"; import {Vm} from "forge-std/Vm.sol"; @@ -107,7 +107,7 @@ contract RMNRemoteSetup is BaseTest { (, RMNRemote.Config memory config) = s_rmnRemote.getVersionedConfig(); bytes32 digest = keccak256( abi.encode( - RMN_V1_6_ANY2EVM_REPORT, + s_rmnRemote.getReportDigestHeader(), RMNRemote.Report({ destChainId: block.chainid, destChainSelector: s_rmnRemote.getLocalChainSelector(), diff --git a/core/gethwrappers/ccip/generated/rmn_remote/rmn_remote.go b/core/gethwrappers/ccip/generated/rmn_remote/rmn_remote.go index f830b9da14..71ef173042 100644 --- a/core/gethwrappers/ccip/generated/rmn_remote/rmn_remote.go +++ b/core/gethwrappers/ccip/generated/rmn_remote/rmn_remote.go @@ -55,8 +55,8 @@ type RMNRemoteSigner struct { } var RMNRemoteMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"localChainSelector\",\"type\":\"uint64\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"bytes16\",\"name\":\"subject\",\"type\":\"bytes16\"}],\"name\":\"AlreadyCursed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConfigNotSet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateOnchainPublicKey\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSignature\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSignerOrder\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MinSignersTooHigh\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes16\",\"name\":\"subject\",\"type\":\"bytes16\"}],\"name\":\"NotCursed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OutOfOrderSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ThresholdNotMet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnexpectedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroValueNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"rmnHomeContractConfigDigest\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"onchainPublicKey\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"nodeIndex\",\"type\":\"uint64\"}],\"internalType\":\"structRMNRemote.Signer[]\",\"name\":\"signers\",\"type\":\"tuple[]\"},{\"internalType\":\"uint64\",\"name\":\"minSigners\",\"type\":\"uint64\"}],\"indexed\":false,\"internalType\":\"structRMNRemote.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes16[]\",\"name\":\"subjects\",\"type\":\"bytes16[]\"}],\"name\":\"Cursed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes16[]\",\"name\":\"subjects\",\"type\":\"bytes16[]\"}],\"name\":\"Uncursed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes16\",\"name\":\"subject\",\"type\":\"bytes16\"}],\"name\":\"curse\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes16[]\",\"name\":\"subjects\",\"type\":\"bytes16[]\"}],\"name\":\"curse\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCursedSubjects\",\"outputs\":[{\"internalType\":\"bytes16[]\",\"name\":\"subjects\",\"type\":\"bytes16[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLocalChainSelector\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"localChainSelector\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getVersionedConfig\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"rmnHomeContractConfigDigest\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"onchainPublicKey\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"nodeIndex\",\"type\":\"uint64\"}],\"internalType\":\"structRMNRemote.Signer[]\",\"name\":\"signers\",\"type\":\"tuple[]\"},{\"internalType\":\"uint64\",\"name\":\"minSigners\",\"type\":\"uint64\"}],\"internalType\":\"structRMNRemote.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes16\",\"name\":\"subject\",\"type\":\"bytes16\"}],\"name\":\"isCursed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isCursed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"rmnHomeContractConfigDigest\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"onchainPublicKey\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"nodeIndex\",\"type\":\"uint64\"}],\"internalType\":\"structRMNRemote.Signer[]\",\"name\":\"signers\",\"type\":\"tuple[]\"},{\"internalType\":\"uint64\",\"name\":\"minSigners\",\"type\":\"uint64\"}],\"internalType\":\"structRMNRemote.Config\",\"name\":\"newConfig\",\"type\":\"tuple\"}],\"name\":\"setConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes16\",\"name\":\"subject\",\"type\":\"bytes16\"}],\"name\":\"uncurse\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes16[]\",\"name\":\"subjects\",\"type\":\"bytes16[]\"}],\"name\":\"uncurse\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"offrampAddress\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"structIRMNV2.Signature[]\",\"name\":\"signatures\",\"type\":\"tuple[]\"},{\"internalType\":\"uint256\",\"name\":\"rawVs\",\"type\":\"uint256\"}],\"name\":\"verify\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x60a06040523480156200001157600080fd5b5060405162002131380380620021318339810160408190526200003491620001a9565b33806000816200008b5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000be57620000be81620000fe565b505050806001600160401b0316600003620000ec5760405163273e150360e21b815260040160405180910390fd5b6001600160401b0316608052620001db565b336001600160a01b03821603620001585760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000082565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600060208284031215620001bc57600080fd5b81516001600160401b0381168114620001d457600080fd5b9392505050565b608051611f33620001fe600039600081816102410152610a920152611f336000f3fe608060405234801561001057600080fd5b50600436106100f55760003560e01c806379ba509711610097578063d881e09211610066578063d881e0921461021e578063eaa83ddd14610233578063f2fde38b1461026b578063f8bb876e1461027e57600080fd5b806379ba5097146101c85780638d8741cb146101d05780638da5cb5b146101e35780639a19b3291461020b57600080fd5b80632cbc26bb116100d35780632cbc26bb14610177578063397796f71461019a57806362eed415146101a25780636d2d3993146101b557600080fd5b8063181f5a77146100fa578063198f0f771461014c5780631add205f14610161575b600080fd5b6101366040518060400160405280601381526020017f524d4e52656d6f746520312e362e302d6465760000000000000000000000000081525081565b6040516101439190611380565b60405180910390f35b61015f61015a366004611393565b610291565b005b61016961063d565b6040516101439291906113ce565b61018a6101853660046114ac565b610735565b6040519015158152602001610143565b61018a610792565b61015f6101b03660046114ac565b61080c565b61015f6101c33660046114ac565b610880565b61015f6108f0565b61015f6101de366004611535565b6109f2565b60005460405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610143565b61015f6102193660046116bc565b610d46565b610226610e43565b6040516101439190611759565b60405167ffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152602001610143565b61015f6102793660046117bf565b610e4f565b61015f61028c3660046116bc565b610e63565b610299610f55565b60015b6102a960208301836117dc565b9050811015610379576102bf60208301836117dc565b828181106102cf576102cf611844565b90506040020160200160208101906102e79190611894565b67ffffffffffffffff166102fe60208401846117dc565b6103096001856118e0565b81811061031857610318611844565b90506040020160200160208101906103309190611894565b67ffffffffffffffff1610610371576040517f4485151700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60010161029c565b5061038760208201826117dc565b90506103996060830160408401611894565b67ffffffffffffffff1611156103db576040517ffba0d9e600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6003545b801561046d576008600060036103f66001856118e0565b8154811061040657610406611844565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055610466816118f3565b90506103df565b5060005b61047e60208301836117dc565b90508110156105b3576008600061049860208501856117dc565b848181106104a8576104a8611844565b6104be92602060409092020190810191506117bf565b73ffffffffffffffffffffffffffffffffffffffff16815260208101919091526040016000205460ff161561051f576040517f28cae27d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60016008600061053260208601866117dc565b8581811061054257610542611844565b61055892602060409092020190810191506117bf565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055600101610471565b508060026105c182826119e1565b5050600580546000919082906105dc9063ffffffff16611b1c565b91906101000a81548163ffffffff021916908363ffffffff160217905590508063ffffffff167f7f22bf988149dbe8de8fb879c6b97a4e56e68b2bd57421ce1a4e79d4ef6b496c836040516106319190611b3f565b60405180910390a25050565b6040805160608082018352600080835260208301919091529181018290526005546040805160608101825260028054825260038054845160208281028201810190965281815263ffffffff9096169592948593818601939092909160009084015b8282101561070c576000848152602090819020604080518082019091529084015473ffffffffffffffffffffffffffffffffffffffff8116825274010000000000000000000000000000000000000000900467ffffffffffffffff168183015282526001909201910161069e565b505050908252506002919091015467ffffffffffffffff16602090910152919491935090915050565b60006107416006610fd8565b60000361075057506000919050565b61075b600683610fe2565b8061078c575061078c60067f0100000000000000000000000000000100000000000000000000000000000000610fe2565b92915050565b600061079e6006610fd8565b6000036107ab5750600090565b6107d660067f0100000000000000000000000000000000000000000000000000000000000000610fe2565b80610807575061080760067f0100000000000000000000000000000100000000000000000000000000000000610fe2565b905090565b60408051600180825281830190925260009160208083019080368337019050509050818160008151811061084257610842611844565b7fffffffffffffffffffffffffffffffff000000000000000000000000000000009092166020928302919091019091015261087c81610e63565b5050565b6040805160018082528183019092526000916020808301908036833701905050905081816000815181106108b6576108b6611844565b7fffffffffffffffffffffffffffffffff000000000000000000000000000000009092166020928302919091019091015261087c81610d46565b60015473ffffffffffffffffffffffffffffffffffffffff163314610976576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b60055463ffffffff16600003610a34576040517face124bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60045467ffffffffffffffff16821015610a7a576040517f59fa4a9300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160c08101825246815267ffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166020820152309181019190915273ffffffffffffffffffffffffffffffffffffffff8716606082015260025460808201526000907f9651943783dbf81935a60e98f218a9d9b5b28823fb2228bbd91320d632facf539060a08101610b16888a611c49565b9052604051610b29929190602001611da9565b60405160208183030381529060405280519060200120905060008060005b85811015610d3a57600184610b6182841b8816601b611ede565b898985818110610b7357610b73611844565b905060400201600001358a8a86818110610b8f57610b8f611844565b9050604002016020013560405160008152602001604052604051610bcf949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015610bf1573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015192505073ffffffffffffffffffffffffffffffffffffffff8216610c69576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1610610cce576040517fbbe15e7f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff821660009081526008602052604090205460ff16610d2d576040517faaaa914100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b9091508190600101610b47565b50505050505050505050565b610d4e610f55565b60005b8151811015610e0857610d87828281518110610d6f57610d6f611844565b6020026020010151600661102090919063ffffffff16565b610e0057818181518110610d9d57610d9d611844565b60200260200101516040517f73281fa100000000000000000000000000000000000000000000000000000000815260040161096d91907fffffffffffffffffffffffffffffffff0000000000000000000000000000000091909116815260200190565b600101610d51565b507f0676e709c9cc74fa0519fd78f7c33be0f1b2b0bae0507c724aef7229379c6ba181604051610e389190611759565b60405180910390a150565b6060610807600661104e565b610e57610f55565b610e608161105b565b50565b610e6b610f55565b60005b8151811015610f2557610ea4828281518110610e8c57610e8c611844565b6020026020010151600661115090919063ffffffff16565b610f1d57818181518110610eba57610eba611844565b60200260200101516040517f19d5c79b00000000000000000000000000000000000000000000000000000000815260040161096d91907fffffffffffffffffffffffffffffffff0000000000000000000000000000000091909116815260200190565b600101610e6e565b507f1716e663a90a76d3b6c7e5f680673d1b051454c19c627e184c8daf28f3104f7481604051610e389190611759565b60005473ffffffffffffffffffffffffffffffffffffffff163314610fd6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640161096d565b565b600061078c825490565b7fffffffffffffffffffffffffffffffff000000000000000000000000000000008116600090815260018301602052604081205415155b9392505050565b6000611019837fffffffffffffffffffffffffffffffff00000000000000000000000000000000841661117e565b6060600061101983611271565b3373ffffffffffffffffffffffffffffffffffffffff8216036110da576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161096d565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000611019837fffffffffffffffffffffffffffffffff0000000000000000000000000000000084166112cd565b600081815260018301602052604081205480156112675760006111a26001836118e0565b85549091506000906111b6906001906118e0565b905080821461121b5760008660000182815481106111d6576111d6611844565b90600052602060002001549050808760000184815481106111f9576111f9611844565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061122c5761122c611ef7565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061078c565b600091505061078c565b6060816000018054806020026020016040519081016040528092919081815260200182805480156112c157602002820191906000526020600020905b8154815260200190600101908083116112ad575b50505050509050919050565b60008181526001830160205260408120546113145750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561078c565b50600061078c565b6000815180845260005b8181101561134257602081850181015186830182015201611326565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000611019602083018461131c565b6000602082840312156113a557600080fd5b813567ffffffffffffffff8111156113bc57600080fd5b82016060818503121561101957600080fd5b63ffffffff831681526040602080830182905283518383015283810151606080850152805160a085018190526000939291820190849060c08701905b80831015611453578351805173ffffffffffffffffffffffffffffffffffffffff16835285015167ffffffffffffffff168583015292840192600192909201919085019061140a565b50604088015167ffffffffffffffff81166080890152945098975050505050505050565b80357fffffffffffffffffffffffffffffffff00000000000000000000000000000000811681146114a757600080fd5b919050565b6000602082840312156114be57600080fd5b61101982611477565b73ffffffffffffffffffffffffffffffffffffffff81168114610e6057600080fd5b60008083601f8401126114fb57600080fd5b50813567ffffffffffffffff81111561151357600080fd5b6020830191508360208260061b850101111561152e57600080fd5b9250929050565b6000806000806000806080878903121561154e57600080fd5b8635611559816114c7565b9550602087013567ffffffffffffffff8082111561157657600080fd5b818901915089601f83011261158a57600080fd5b81358181111561159957600080fd5b8a60208260051b85010111156115ae57600080fd5b6020830197508096505060408901359150808211156115cc57600080fd5b506115d989828a016114e9565b979a9699509497949695606090950135949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff81118282101715611643576116436115f1565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611690576116906115f1565b604052919050565b600067ffffffffffffffff8211156116b2576116b26115f1565b5060051b60200190565b600060208083850312156116cf57600080fd5b823567ffffffffffffffff8111156116e657600080fd5b8301601f810185136116f757600080fd5b803561170a61170582611698565b611649565b81815260059190911b8201830190838101908783111561172957600080fd5b928401925b8284101561174e5761173f84611477565b8252928401929084019061172e565b979650505050505050565b6020808252825182820181905260009190848201906040850190845b818110156117b35783517fffffffffffffffffffffffffffffffff000000000000000000000000000000001683529284019291840191600101611775565b50909695505050505050565b6000602082840312156117d157600080fd5b8135611019816114c7565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261181157600080fd5b83018035915067ffffffffffffffff82111561182c57600080fd5b6020019150600681901b360382131561152e57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b67ffffffffffffffff81168114610e6057600080fd5b80356114a781611873565b6000602082840312156118a657600080fd5b813561101981611873565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8181038181111561078c5761078c6118b1565b600081611902576119026118b1565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b6000813561078c81611873565b8135611940816114c7565b73ffffffffffffffffffffffffffffffffffffffff811690508154817fffffffffffffffffffffffff00000000000000000000000000000000000000008216178355602084013561199081611873565b7bffffffffffffffff00000000000000000000000000000000000000008160a01b16837fffffffff000000000000000000000000000000000000000000000000000000008416171784555050505050565b81358155600180820160208401357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1853603018112611a1f57600080fd5b8401803567ffffffffffffffff811115611a3857600080fd5b6020820191508060061b3603821315611a5057600080fd5b68010000000000000000811115611a6957611a696115f1565b825481845580821015611a9e576000848152602081208381019083015b80821015611a9a5782825590870190611a86565b5050505b50600092835260208320925b81811015611ace57611abc8385611935565b92840192604092909201918401611aaa565b505050505061087c611ae260408401611928565b6002830167ffffffffffffffff82167fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000008254161781555050565b600063ffffffff808316818103611b3557611b356118b1565b6001019392505050565b6000602080835260808301843582850152818501357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1863603018112611b8457600080fd5b8501828101903567ffffffffffffffff80821115611ba157600080fd5b8160061b3603831315611bb357600080fd5b6040606060408901528483865260a089019050849550600094505b83851015611c1e578535611be1816114c7565b73ffffffffffffffffffffffffffffffffffffffff16815285870135611c0681611873565b83168188015294810194600194909401938101611bce565b611c2a60408b01611889565b67ffffffffffffffff811660608b015296509998505050505050505050565b6000611c5761170584611698565b80848252602080830192508560051b850136811115611c7557600080fd5b855b81811015611d9d57803567ffffffffffffffff80821115611c985760008081fd5b818901915060a08236031215611cae5760008081fd5b611cb6611620565b8235611cc181611873565b81528286013582811115611cd55760008081fd5b8301601f3681830112611ce85760008081fd5b813584811115611cfa57611cfa6115f1565b611d29897fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08484011601611649565b94508085523689828501011115611d4257600091508182fd5b808984018a8701376000898287010152505050818682015260409150611d69828401611889565b8282015260609150611d7c828401611889565b91810191909152608091820135918101919091528552938201938201611c77565b50919695505050505050565b60006040848352602060408185015261010084018551604086015281860151606067ffffffffffffffff808316606089015260408901519250608073ffffffffffffffffffffffffffffffffffffffff80851660808b015260608b0151945060a081861660a08c015260808c015160c08c015260a08c0151955060c060e08c015286915085518088526101209750878c019250878160051b8d01019750888701965060005b81811015611ecb577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee08d8a030184528751868151168a528a810151848c8c0152611e9a858c018261131c565b828e015189168c8f01528983015189168a8d0152918701519a87019a909a5298509689019692890192600101611e4e565b50969d9c50505050505050505050505050565b60ff818116838216019081111561078c5761078c6118b1565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"localChainSelector\",\"type\":\"uint64\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"bytes16\",\"name\":\"subject\",\"type\":\"bytes16\"}],\"name\":\"AlreadyCursed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConfigNotSet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateOnchainPublicKey\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSignature\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSignerOrder\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MinSignersTooHigh\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes16\",\"name\":\"subject\",\"type\":\"bytes16\"}],\"name\":\"NotCursed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OutOfOrderSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ThresholdNotMet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UnexpectedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroValueNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"rmnHomeContractConfigDigest\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"onchainPublicKey\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"nodeIndex\",\"type\":\"uint64\"}],\"internalType\":\"structRMNRemote.Signer[]\",\"name\":\"signers\",\"type\":\"tuple[]\"},{\"internalType\":\"uint64\",\"name\":\"minSigners\",\"type\":\"uint64\"}],\"indexed\":false,\"internalType\":\"structRMNRemote.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes16[]\",\"name\":\"subjects\",\"type\":\"bytes16[]\"}],\"name\":\"Cursed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes16[]\",\"name\":\"subjects\",\"type\":\"bytes16[]\"}],\"name\":\"Uncursed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes16\",\"name\":\"subject\",\"type\":\"bytes16\"}],\"name\":\"curse\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes16[]\",\"name\":\"subjects\",\"type\":\"bytes16[]\"}],\"name\":\"curse\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCursedSubjects\",\"outputs\":[{\"internalType\":\"bytes16[]\",\"name\":\"subjects\",\"type\":\"bytes16[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLocalChainSelector\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"localChainSelector\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getReportDigestHeader\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"digestHeader\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getVersionedConfig\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"version\",\"type\":\"uint32\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"rmnHomeContractConfigDigest\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"onchainPublicKey\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"nodeIndex\",\"type\":\"uint64\"}],\"internalType\":\"structRMNRemote.Signer[]\",\"name\":\"signers\",\"type\":\"tuple[]\"},{\"internalType\":\"uint64\",\"name\":\"minSigners\",\"type\":\"uint64\"}],\"internalType\":\"structRMNRemote.Config\",\"name\":\"config\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes16\",\"name\":\"subject\",\"type\":\"bytes16\"}],\"name\":\"isCursed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isCursed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"rmnHomeContractConfigDigest\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"onchainPublicKey\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"nodeIndex\",\"type\":\"uint64\"}],\"internalType\":\"structRMNRemote.Signer[]\",\"name\":\"signers\",\"type\":\"tuple[]\"},{\"internalType\":\"uint64\",\"name\":\"minSigners\",\"type\":\"uint64\"}],\"internalType\":\"structRMNRemote.Config\",\"name\":\"newConfig\",\"type\":\"tuple\"}],\"name\":\"setConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes16\",\"name\":\"subject\",\"type\":\"bytes16\"}],\"name\":\"uncurse\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes16[]\",\"name\":\"subjects\",\"type\":\"bytes16[]\"}],\"name\":\"uncurse\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"offrampAddress\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"structIRMNV2.Signature[]\",\"name\":\"signatures\",\"type\":\"tuple[]\"},{\"internalType\":\"uint256\",\"name\":\"rawVs\",\"type\":\"uint256\"}],\"name\":\"verify\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x60a06040523480156200001157600080fd5b506040516200216a3803806200216a8339810160408190526200003491620001a9565b33806000816200008b5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000be57620000be81620000fe565b505050806001600160401b0316600003620000ec5760405163273e150360e21b815260040160405180910390fd5b6001600160401b0316608052620001db565b336001600160a01b03821603620001585760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000082565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600060208284031215620001bc57600080fd5b81516001600160401b0381168114620001d457600080fd5b9392505050565b608051611f6c620001fe6000396000818161027a0152610acb0152611f6c6000f3fe608060405234801561001057600080fd5b50600436106101005760003560e01c806379ba509711610097578063d881e09211610066578063d881e09214610257578063eaa83ddd1461026c578063f2fde38b146102a4578063f8bb876e146102b757600080fd5b806379ba5097146102015780638d8741cb146102095780638da5cb5b1461021c5780639a19b3291461024457600080fd5b8063397796f7116100d3578063397796f7146101a557806362eed415146101ad5780636509a954146101c05780636d2d3993146101ee57600080fd5b8063181f5a7714610105578063198f0f77146101575780631add205f1461016c5780632cbc26bb14610182575b600080fd5b6101416040518060400160405280601381526020017f524d4e52656d6f746520312e362e302d6465760000000000000000000000000081525081565b60405161014e91906113b9565b60405180910390f35b61016a6101653660046113cc565b6102ca565b005b610174610676565b60405161014e929190611407565b6101956101903660046114e5565b61076e565b604051901515815260200161014e565b6101956107cb565b61016a6101bb3660046114e5565b610845565b6040517f9651943783dbf81935a60e98f218a9d9b5b28823fb2228bbd91320d632facf53815260200161014e565b61016a6101fc3660046114e5565b6108b9565b61016a610929565b61016a61021736600461156e565b610a2b565b60005460405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014e565b61016a6102523660046116f5565b610d7f565b61025f610e7c565b60405161014e9190611792565b60405167ffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016815260200161014e565b61016a6102b23660046117f8565b610e88565b61016a6102c53660046116f5565b610e9c565b6102d2610f8e565b60015b6102e26020830183611815565b90508110156103b2576102f86020830183611815565b828181106103085761030861187d565b905060400201602001602081019061032091906118cd565b67ffffffffffffffff166103376020840184611815565b610342600185611919565b8181106103515761035161187d565b905060400201602001602081019061036991906118cd565b67ffffffffffffffff16106103aa576040517f4485151700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6001016102d5565b506103c06020820182611815565b90506103d260608301604084016118cd565b67ffffffffffffffff161115610414576040517ffba0d9e600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6003545b80156104a65760086000600361042f600185611919565b8154811061043f5761043f61187d565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905561049f8161192c565b9050610418565b5060005b6104b76020830183611815565b90508110156105ec57600860006104d16020850185611815565b848181106104e1576104e161187d565b6104f792602060409092020190810191506117f8565b73ffffffffffffffffffffffffffffffffffffffff16815260208101919091526040016000205460ff1615610558576040517f28cae27d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60016008600061056b6020860186611815565b8581811061057b5761057b61187d565b61059192602060409092020190810191506117f8565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169115159190911790556001016104aa565b508060026105fa8282611a1a565b5050600580546000919082906106159063ffffffff16611b55565b91906101000a81548163ffffffff021916908363ffffffff160217905590508063ffffffff167f7f22bf988149dbe8de8fb879c6b97a4e56e68b2bd57421ce1a4e79d4ef6b496c8360405161066a9190611b78565b60405180910390a25050565b6040805160608082018352600080835260208301919091529181018290526005546040805160608101825260028054825260038054845160208281028201810190965281815263ffffffff9096169592948593818601939092909160009084015b82821015610745576000848152602090819020604080518082019091529084015473ffffffffffffffffffffffffffffffffffffffff8116825274010000000000000000000000000000000000000000900467ffffffffffffffff16818301528252600190920191016106d7565b505050908252506002919091015467ffffffffffffffff16602090910152919491935090915050565b600061077a6006611011565b60000361078957506000919050565b61079460068361101b565b806107c557506107c560067f010000000000000000000000000000010000000000000000000000000000000061101b565b92915050565b60006107d76006611011565b6000036107e45750600090565b61080f60067f010000000000000000000000000000000000000000000000000000000000000061101b565b80610840575061084060067f010000000000000000000000000000010000000000000000000000000000000061101b565b905090565b60408051600180825281830190925260009160208083019080368337019050509050818160008151811061087b5761087b61187d565b7fffffffffffffffffffffffffffffffff00000000000000000000000000000000909216602092830291909101909101526108b581610e9c565b5050565b6040805160018082528183019092526000916020808301908036833701905050905081816000815181106108ef576108ef61187d565b7fffffffffffffffffffffffffffffffff00000000000000000000000000000000909216602092830291909101909101526108b581610d7f565b60015473ffffffffffffffffffffffffffffffffffffffff1633146109af576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b60055463ffffffff16600003610a6d576040517face124bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60045467ffffffffffffffff16821015610ab3576040517f59fa4a9300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805160c08101825246815267ffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166020820152309181019190915273ffffffffffffffffffffffffffffffffffffffff8716606082015260025460808201526000907f9651943783dbf81935a60e98f218a9d9b5b28823fb2228bbd91320d632facf539060a08101610b4f888a611c82565b9052604051610b62929190602001611de2565b60405160208183030381529060405280519060200120905060008060005b85811015610d7357600184610b9a82841b8816601b611f17565b898985818110610bac57610bac61187d565b905060400201600001358a8a86818110610bc857610bc861187d565b9050604002016020013560405160008152602001604052604051610c08949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015610c2a573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015192505073ffffffffffffffffffffffffffffffffffffffff8216610ca2576040517f8baa579f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1610610d07576040517fbbe15e7f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff821660009081526008602052604090205460ff16610d66576040517faaaa914100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b9091508190600101610b80565b50505050505050505050565b610d87610f8e565b60005b8151811015610e4157610dc0828281518110610da857610da861187d565b6020026020010151600661105990919063ffffffff16565b610e3957818181518110610dd657610dd661187d565b60200260200101516040517f73281fa10000000000000000000000000000000000000000000000000000000081526004016109a691907fffffffffffffffffffffffffffffffff0000000000000000000000000000000091909116815260200190565b600101610d8a565b507f0676e709c9cc74fa0519fd78f7c33be0f1b2b0bae0507c724aef7229379c6ba181604051610e719190611792565b60405180910390a150565b60606108406006611087565b610e90610f8e565b610e9981611094565b50565b610ea4610f8e565b60005b8151811015610f5e57610edd828281518110610ec557610ec561187d565b6020026020010151600661118990919063ffffffff16565b610f5657818181518110610ef357610ef361187d565b60200260200101516040517f19d5c79b0000000000000000000000000000000000000000000000000000000081526004016109a691907fffffffffffffffffffffffffffffffff0000000000000000000000000000000091909116815260200190565b600101610ea7565b507f1716e663a90a76d3b6c7e5f680673d1b051454c19c627e184c8daf28f3104f7481604051610e719190611792565b60005473ffffffffffffffffffffffffffffffffffffffff16331461100f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016109a6565b565b60006107c5825490565b7fffffffffffffffffffffffffffffffff000000000000000000000000000000008116600090815260018301602052604081205415155b9392505050565b6000611052837fffffffffffffffffffffffffffffffff0000000000000000000000000000000084166111b7565b60606000611052836112aa565b3373ffffffffffffffffffffffffffffffffffffffff821603611113576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016109a6565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000611052837fffffffffffffffffffffffffffffffff000000000000000000000000000000008416611306565b600081815260018301602052604081205480156112a05760006111db600183611919565b85549091506000906111ef90600190611919565b905080821461125457600086600001828154811061120f5761120f61187d565b90600052602060002001549050808760000184815481106112325761123261187d565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061126557611265611f30565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506107c5565b60009150506107c5565b6060816000018054806020026020016040519081016040528092919081815260200182805480156112fa57602002820191906000526020600020905b8154815260200190600101908083116112e6575b50505050509050919050565b600081815260018301602052604081205461134d575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556107c5565b5060006107c5565b6000815180845260005b8181101561137b5760208185018101518683018201520161135f565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b6020815260006110526020830184611355565b6000602082840312156113de57600080fd5b813567ffffffffffffffff8111156113f557600080fd5b82016060818503121561105257600080fd5b63ffffffff831681526040602080830182905283518383015283810151606080850152805160a085018190526000939291820190849060c08701905b8083101561148c578351805173ffffffffffffffffffffffffffffffffffffffff16835285015167ffffffffffffffff1685830152928401926001929092019190850190611443565b50604088015167ffffffffffffffff81166080890152945098975050505050505050565b80357fffffffffffffffffffffffffffffffff00000000000000000000000000000000811681146114e057600080fd5b919050565b6000602082840312156114f757600080fd5b611052826114b0565b73ffffffffffffffffffffffffffffffffffffffff81168114610e9957600080fd5b60008083601f84011261153457600080fd5b50813567ffffffffffffffff81111561154c57600080fd5b6020830191508360208260061b850101111561156757600080fd5b9250929050565b6000806000806000806080878903121561158757600080fd5b863561159281611500565b9550602087013567ffffffffffffffff808211156115af57600080fd5b818901915089601f8301126115c357600080fd5b8135818111156115d257600080fd5b8a60208260051b85010111156115e757600080fd5b60208301975080965050604089013591508082111561160557600080fd5b5061161289828a01611522565b979a9699509497949695606090950135949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160a0810167ffffffffffffffff8111828210171561167c5761167c61162a565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156116c9576116c961162a565b604052919050565b600067ffffffffffffffff8211156116eb576116eb61162a565b5060051b60200190565b6000602080838503121561170857600080fd5b823567ffffffffffffffff81111561171f57600080fd5b8301601f8101851361173057600080fd5b803561174361173e826116d1565b611682565b81815260059190911b8201830190838101908783111561176257600080fd5b928401925b8284101561178757611778846114b0565b82529284019290840190611767565b979650505050505050565b6020808252825182820181905260009190848201906040850190845b818110156117ec5783517fffffffffffffffffffffffffffffffff0000000000000000000000000000000016835292840192918401916001016117ae565b50909695505050505050565b60006020828403121561180a57600080fd5b813561105281611500565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261184a57600080fd5b83018035915067ffffffffffffffff82111561186557600080fd5b6020019150600681901b360382131561156757600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b67ffffffffffffffff81168114610e9957600080fd5b80356114e0816118ac565b6000602082840312156118df57600080fd5b8135611052816118ac565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818103818111156107c5576107c56118ea565b60008161193b5761193b6118ea565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b600081356107c5816118ac565b813561197981611500565b73ffffffffffffffffffffffffffffffffffffffff811690508154817fffffffffffffffffffffffff0000000000000000000000000000000000000000821617835560208401356119c9816118ac565b7bffffffffffffffff00000000000000000000000000000000000000008160a01b16837fffffffff000000000000000000000000000000000000000000000000000000008416171784555050505050565b81358155600180820160208401357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1853603018112611a5857600080fd5b8401803567ffffffffffffffff811115611a7157600080fd5b6020820191508060061b3603821315611a8957600080fd5b68010000000000000000811115611aa257611aa261162a565b825481845580821015611ad7576000848152602081208381019083015b80821015611ad35782825590870190611abf565b5050505b50600092835260208320925b81811015611b0757611af5838561196e565b92840192604092909201918401611ae3565b50505050506108b5611b1b60408401611961565b6002830167ffffffffffffffff82167fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000008254161781555050565b600063ffffffff808316818103611b6e57611b6e6118ea565b6001019392505050565b6000602080835260808301843582850152818501357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1863603018112611bbd57600080fd5b8501828101903567ffffffffffffffff80821115611bda57600080fd5b8160061b3603831315611bec57600080fd5b6040606060408901528483865260a089019050849550600094505b83851015611c57578535611c1a81611500565b73ffffffffffffffffffffffffffffffffffffffff16815285870135611c3f816118ac565b83168188015294810194600194909401938101611c07565b611c6360408b016118c2565b67ffffffffffffffff811660608b015296509998505050505050505050565b6000611c9061173e846116d1565b80848252602080830192508560051b850136811115611cae57600080fd5b855b81811015611dd657803567ffffffffffffffff80821115611cd15760008081fd5b818901915060a08236031215611ce75760008081fd5b611cef611659565b8235611cfa816118ac565b81528286013582811115611d0e5760008081fd5b8301601f3681830112611d215760008081fd5b813584811115611d3357611d3361162a565b611d62897fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08484011601611682565b94508085523689828501011115611d7b57600091508182fd5b808984018a8701376000898287010152505050818682015260409150611da28284016118c2565b8282015260609150611db58284016118c2565b91810191909152608091820135918101919091528552938201938201611cb0565b50919695505050505050565b60006040848352602060408185015261010084018551604086015281860151606067ffffffffffffffff808316606089015260408901519250608073ffffffffffffffffffffffffffffffffffffffff80851660808b015260608b0151945060a081861660a08c015260808c015160c08c015260a08c0151955060c060e08c015286915085518088526101209750878c019250878160051b8d01019750888701965060005b81811015611f04577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee08d8a030184528751868151168a528a810151848c8c0152611ed3858c0182611355565b828e015189168c8f01528983015189168a8d0152918701519a87019a909a5298509689019692890192600101611e87565b50969d9c50505050505050505050505050565b60ff81811683821601908111156107c5576107c56118ea565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea164736f6c6343000818000a", } var RMNRemoteABI = RMNRemoteMetaData.ABI @@ -239,6 +239,28 @@ func (_RMNRemote *RMNRemoteCallerSession) GetLocalChainSelector() (uint64, error return _RMNRemote.Contract.GetLocalChainSelector(&_RMNRemote.CallOpts) } +func (_RMNRemote *RMNRemoteCaller) GetReportDigestHeader(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _RMNRemote.contract.Call(opts, &out, "getReportDigestHeader") + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +func (_RMNRemote *RMNRemoteSession) GetReportDigestHeader() ([32]byte, error) { + return _RMNRemote.Contract.GetReportDigestHeader(&_RMNRemote.CallOpts) +} + +func (_RMNRemote *RMNRemoteCallerSession) GetReportDigestHeader() ([32]byte, error) { + return _RMNRemote.Contract.GetReportDigestHeader(&_RMNRemote.CallOpts) +} + func (_RMNRemote *RMNRemoteCaller) GetVersionedConfig(opts *bind.CallOpts) (GetVersionedConfig, error) { @@ -1147,6 +1169,8 @@ type RMNRemoteInterface interface { GetLocalChainSelector(opts *bind.CallOpts) (uint64, error) + GetReportDigestHeader(opts *bind.CallOpts) ([32]byte, error) + GetVersionedConfig(opts *bind.CallOpts) (GetVersionedConfig, error) diff --git a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt index 8a70af06e5..4a2054edf2 100644 --- a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -32,7 +32,7 @@ registry_module_owner_custom: ../../../contracts/solc/v0.8.24/RegistryModuleOwne report_codec: ../../../contracts/solc/v0.8.24/ReportCodec/ReportCodec.abi ../../../contracts/solc/v0.8.24/ReportCodec/ReportCodec.bin 7413576693f76bac7c01fbaec4a161d37a1de51b13dcab78455d2c484ed938b1 rmn_contract: ../../../contracts/solc/v0.8.24/RMN/RMN.abi ../../../contracts/solc/v0.8.24/RMN/RMN.bin 8b45b0fb08631c6b582fd3c0b4052a79cc2b4e091e6286af1ab131bef63661f9 rmn_proxy_contract: ../../../contracts/solc/v0.8.24/ARMProxy/ARMProxy.abi ../../../contracts/solc/v0.8.24/ARMProxy/ARMProxy.bin b048d8e752e3c41113ebb305c1efa06737ad36b4907b93e627fb0a3113023454 -rmn_remote: ../../../contracts/solc/v0.8.24/RMNRemote/RMNRemote.abi ../../../contracts/solc/v0.8.24/RMNRemote/RMNRemote.bin ed08711d211cbe7e2ed389838864a33044fa5a95c4a2fcdeb4ac049d1c225475 +rmn_remote: ../../../contracts/solc/v0.8.24/RMNRemote/RMNRemote.abi ../../../contracts/solc/v0.8.24/RMNRemote/RMNRemote.bin 515b0b7038284f8970edddf58d23cd1492237206dbe047dcbe045248db07e8a5 router: ../../../contracts/solc/v0.8.24/Router/Router.abi ../../../contracts/solc/v0.8.24/Router/Router.bin 2e4f0a7826c8abb49d882bb49fc5ff20a186dbd3137624b9097ffed903ae4888 self_funded_ping_pong: ../../../contracts/solc/v0.8.24/SelfFundedPingPong/SelfFundedPingPong.abi ../../../contracts/solc/v0.8.24/SelfFundedPingPong/SelfFundedPingPong.bin 8ea5d75dbc3f8afd90d22c4a665a94e02892259cd16520c1c6b4cf0dc80c9148 token_admin_registry: ../../../contracts/solc/v0.8.24/TokenAdminRegistry/TokenAdminRegistry.abi ../../../contracts/solc/v0.8.24/TokenAdminRegistry/TokenAdminRegistry.bin 942be7d1681ac102e0615bee13f76838ebb0b261697cf1270d2bf82c12e57aeb From b08c4beea761472529ac5842e51d68c78d842c87 Mon Sep 17 00:00:00 2001 From: Balamurali Gopalswami <167726375+b-gopalswami@users.noreply.github.com> Date: Wed, 18 Sep 2024 12:46:27 -0400 Subject: [PATCH 103/115] CCIP-3445: Update 1.5 RMN contract address (#1448) ## Motivation RMN contract is updated to 1.5 version. Need to update in config. ## Solution Update config with latest 1.5 RMN contract address and remove unwanted secondary config. --- .../override/mainnet-secondary.toml | 712 ------- .../testconfig/override/mainnet.toml | 1677 +++++++++++------ 2 files changed, 1054 insertions(+), 1335 deletions(-) delete mode 100644 integration-tests/ccip-tests/testconfig/override/mainnet-secondary.toml diff --git a/integration-tests/ccip-tests/testconfig/override/mainnet-secondary.toml b/integration-tests/ccip-tests/testconfig/override/mainnet-secondary.toml deleted file mode 100644 index 7d457774b0..0000000000 --- a/integration-tests/ccip-tests/testconfig/override/mainnet-secondary.toml +++ /dev/null @@ -1,712 +0,0 @@ -[CCIP] -[CCIP.ContractVersions] -PriceRegistry = '1.2.0' -OffRamp = '1.2.0' -OnRamp = '1.2.0' -TokenPool = '1.4.0' -CommitStore = '1.2.0' - -[CCIP.Deployments] -Data = """ -{ - "lane_configs": { - "Arbitrum Mainnet": { - "is_native_fee_token": true, - "fee_token": "0xf97f4df75117a78c1A5a0DBb814Af92458539FB4", - "bridge_tokens": ["0x82aF49447D8a07e3bd95BD0d56f35241523fBab1"], - "bridge_tokens_pools": ["0x34700F5faE61Ba628c4269BdCbA12DA53bbfa726"], - "arm": "0xe06b0e8c4bd455153e8794ad7Ea8Ff5A14B64E4b", - "router": "0x141fa059441E0ca23ce184B6A78bafD2A517DdE8", - "price_registry": "0x13015e4E6f839E1Aa1016DF521ea458ecA20438c", - "wrapped_native": "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1", - "version" : "1.4.0", - "src_contracts": { - "Avalanche Mainnet": { - "on_ramp": "0x05B723f3db92430FbE4395fD03E40Cc7e9D17988", - "deployed_at": 11111111 - }, - "Base Mainnet": { - "on_ramp": "0x77b60F85b25fD501E3ddED6C1fe7bF565C08A22A", - "deployed_at": 11111111 - }, - "BSC Mainnet": { - "on_ramp": "0x79f3ABeCe5A3AFFf32D47F4CFe45e7b65c9a2D91", - "deployed_at": 11111111 - }, - "Ethereum Mainnet": { - "on_ramp": "0xCe11020D56e5FDbfE46D9FC3021641FfbBB5AdEE", - "deployed_at": 11111111 - }, - "Optimism Mainnet": { - "on_ramp": "0xC09b72E8128620C40D89649019d995Cc79f030C3", - "deployed_at": 11111111 - }, - "Polygon Mainnet": { - "on_ramp": "0x122F05F49e90508F089eE8D0d868d1a4f3E5a809", - "deployed_at": 11111111 - }, - "WeMix Mainnet": { - "on_ramp": "0x66a0046ac9FA104eB38B04cfF391CcD0122E6FbC", - "deployed_at": 11111111 - } - }, - "dest_contracts": { - "Avalanche Mainnet": { - "off_ramp": "0xe0109912157d5B75ea8b3181123Cf32c73bc9920", - "commit_store": "0xDaa61b8Cd85977820f92d1e749E1D9F55Da6CCEA", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Base Mainnet": { - "off_ramp": "0xdB19F77F87661f9be0F557cf9a1ebeCf7D8F206c", - "commit_store": "0x6e37f4c82d9A31cc42B445874dd3c3De97AB553f", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "BSC Mainnet": { - "off_ramp": "0xB1b705c2315fced1B38baE463BE7DDef531e47fA", - "commit_store": "0x310cECbFf14Ad0307EfF762F461a487C1abb90bf", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Ethereum Mainnet": { - "off_ramp": "0x542ba1902044069330e8c5b36A84EC503863722f", - "commit_store": "0x060331fEdA35691e54876D957B4F9e3b8Cb47d20", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Optimism Mainnet": { - "off_ramp": "0xeeed4D86F3E0e6d32A6Ad29d8De6A0Dc91963A5f", - "commit_store": "0xbbB563c4d98020b9c0f3Cc34c2C0Ef9676806E35", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Polygon Mainnet": { - "off_ramp": "0x9bDA7c8DCda4E39aFeB483cc0B7E3C1f6E0D5AB1", - "commit_store": "0x63a0AeaadAe851b990bBD9dc41f5C1B08b32026d", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "WeMix Mainnet": { - "off_ramp": "0xEEf5Fb4c4953F9cA9ab1f25cE590776AfFc2c455", - "commit_store": "0xD268286A277095a9C3C90205110831a84505881c", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - } - } - }, - "Avalanche Mainnet": { - "is_native_fee_token": true, - "fee_token": "0x5947BB275c521040051D82396192181b413227A3", - "bridge_tokens": [], - "bridge_tokens_pools": [], - "arm": "0xdFD6C0dc67666DE3bB36b31eec5c7B1542A82C1E", - "router": "0xF4c7E640EdA248ef95972845a62bdC74237805dB", - "price_registry": "0xfA4edD04eaAcDB07c8D73621bc1790eC50D8c489", - "wrapped_native": "0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7", - "src_contracts": { - "Arbitrum Mainnet": { - "on_ramp": "0x98f51B041e493fc4d72B8BD33218480bA0c66DDF", - "deployed_at": 11111111 - }, - "Base Mainnet": { - "on_ramp": "0x268fb4311D2c6CB2bbA01CCA9AC073Fb3bfd1C7c", - "deployed_at": 11111111 - }, - "BSC Mainnet": { - "on_ramp": "0x8eaae6462816CB4957184c48B86afA7642D8Bf2B", - "deployed_at": 11111111 - }, - "Ethereum Mainnet": { - "on_ramp": "0xD0701FcC7818c31935331B02Eb21e91eC71a1704", - "deployed_at": 11111111 - }, - "Optimism Mainnet": { - "on_ramp": "0x8629008887E073260c5434D6CaCFc83C3001d211", - "deployed_at": 11111111 - }, - "Polygon Mainnet": { - "on_ramp": "0x97500490d9126f34cf9aA0126d64623E170319Ef", - "deployed_at": 11111111 - }, - "WeMix Mainnet": { - "on_ramp": "0x9b1ed9De069Be4d50957464b359f98eD0Bf34dd5", - "deployed_at": 11111111 - } - }, - "dest_contracts": { - "Arbitrum Mainnet": { - "off_ramp": "0x770b1375F86E7a9bf30DBe3F97bea67193dC9135", - "commit_store": "0x23E2b34Ce8e12c53f8a39AD4b3FFCa845f8E617C", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Base Mainnet": { - "off_ramp": "0x4d6A796Bc85dcDF41ce9AaEB50B094C6b589748f", - "commit_store": "0xc4C4358FA01a04D6c6FE3b96a351946d4c2715C2", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "BSC Mainnet": { - "off_ramp": "0x83F53Fc798FEbfFbdF84830AD403b9989187a06C", - "commit_store": "0xD8ceCE2D7794385E00Ce3EF94550E732b0A0B959", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Ethereum Mainnet": { - "off_ramp": "0x5B833BD6456c604Eb396C0fBa477aD49e82B1A2a", - "commit_store": "0x23E23958D220B774680f91c2c91a6f2B2f610d7e", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Optimism Mainnet": { - "off_ramp": "0xb68A3EE8bD0A09eE221cf1859Dd5a4d5765188Fe", - "commit_store": "0x83DCeeCf822981F9F8552925eEfd88CAc1905dEA", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Polygon Mainnet": { - "off_ramp": "0x19250aBE66B88F214d02B6f3BF80F4118290C619", - "commit_store": "0x87A0935cE6254dB1252bBac90d1D07D04846aDCA", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "WeMix Mainnet": { - "off_ramp": "0x317dE8bc5c3292E494b6496586696d4966A922B0", - "commit_store": "0x97Fbf3d6DEac16adC721aE9187CeEa1e610aC7Af", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - } - } - }, - "Base Mainnet": { - "is_native_fee_token": true, - "fee_token": "0x88Fb150BDc53A65fe94Dea0c9BA0a6dAf8C6e196", - "bridge_tokens": [], - "bridge_tokens_pools": [], - "arm": "0x38660c8CC222c0192b635c2ac09687B4F25cCE5F", - "router": "0x881e3A65B4d4a04dD529061dd0071cf975F58bCD", - "price_registry": "0x6337a58D4BD7Ba691B66341779e8f87d4679923a", - "wrapped_native": "0x4200000000000000000000000000000000000006", - "src_contracts": { - "Arbitrum Mainnet": { - "on_ramp": "0x1E5Ca70d1e7A1B26061125738a880BBeA42FeB21", - "deployed_at": 11111111 - }, - "Avalanche Mainnet": { - "on_ramp": "0xBE5a9E336D9614024B4Fa10D8112671fc9A42d96", - "deployed_at": 11111111 - }, - "BSC Mainnet": { - "on_ramp": "0xdd4Fb402d41Beb0eEeF6CfB1bf445f50bDC8c981", - "deployed_at": 11111111 - }, - "Ethereum Mainnet": { - "on_ramp": "0xDEA286dc0E01Cb4755650A6CF8d1076b454eA1cb", - "deployed_at": 11111111 - }, - "Optimism Mainnet": { - "on_ramp": "0xd952FEAcDd5919Cc5E9454b53bF45d4E73dD6457", - "deployed_at": 11111111 - }, - "Polygon Mainnet": { - "on_ramp": "0x3DB8Bea142e41cA3633890d0e5640F99a895D6A5", - "deployed_at": 11111111 - } - }, - "dest_contracts": { - "Arbitrum Mainnet": { - "off_ramp": "0x8531E63aE9279a1f0D09eba566CD1b092b95f3D5", - "commit_store": "0x327E13f54c7871a2416006B33B4822eAAD357916", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Avalanche Mainnet": { - "off_ramp": "0x8345F2fF67e5A65e85dc955DE1414832608E00aD", - "commit_store": "0xd0b13be4c53A6262b47C5DDd36F0257aa714F562", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "BSC Mainnet": { - "off_ramp": "0x48a51f5D38BE630Ddd6417Ea2D9052B8efc91a18", - "commit_store": "0xF97127e77252284EC9D4bc13C247c9D1A99F72B0", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Ethereum Mainnet": { - "off_ramp": "0xEC0cFe335a4d53dBA70CB650Ab56eEc32788F0BB", - "commit_store": "0x0ae3c2c7FB789bd05A450CD3075D11f6c2Ca4F77", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Optimism Mainnet": { - "off_ramp": "0xf50c0d2a8B6Db60f1D93E60f03d0413D56153E4F", - "commit_store": "0x16f72C15165f7C9d74c12fDF188E399d4d3724e4", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Polygon Mainnet": { - "off_ramp": "0x75F29f058b31106F99caFdc17c9b26ADfcC7b5D7", - "commit_store": "0xb719616E732581B570232DfB13Ca49D27667Af9f", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - } - } - }, - "BSC Mainnet": { - "is_native_fee_token": true, - "fee_token": "0x404460C6A5EdE2D891e8297795264fDe62ADBB75", - "bridge_tokens": [], - "bridge_tokens_pools": [], - "arm": "0x3DB43b96B2625F4232e9Df900d464dd2c64C0021", - "router": "0x34B03Cb9086d7D758AC55af71584F81A598759FE", - "price_registry": "0xd64aAbD70A71d9f0A00B99F6EFc1626aA2dD43C7", - "wrapped_native": "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c", - "src_contracts": { - "Avalanche Mainnet": { - "on_ramp": "0x6aa72a998859eF93356c6521B72155D355D0Cfd2", - "deployed_at": 11111111 - }, - "Arbitrum Mainnet": { - "on_ramp": "0x2788b46BAcFF49BD89562e6bA5c5FBbbE5Fa92F7", - "deployed_at": 11111111 - }, - "Base Mainnet": { - "on_ramp": "0x70bC7f7a6D936b289bBF5c0E19ECE35B437E2e36", - "deployed_at": 11111111 - }, - "Ethereum Mainnet": { - "on_ramp": "0x0Bf40b034872D0b364f3DCec04C7434a4Da1C8d9", - "deployed_at": 11111111 - }, - "Optimism Mainnet": { - "on_ramp": "0x4FEB11A454C9E8038A8d0aDF599Fe7612ce114bA", - "deployed_at": 11111111 - }, - "Polygon Mainnet": { - "on_ramp": "0x6bD4754D86fc87FE5b463D368f26a3587a08347c", - "deployed_at": 11111111 - }, - "WeMix Mainnet": { - "on_ramp": "0x1467fF8f249f5bc604119Af26a47035886f856BE", - "deployed_at": 11111111 - } - }, - "dest_contracts": { - "Avalanche Mainnet": { - "off_ramp": "0x37a6fa55fe61061Ae97bF7314Ae270eCF71c5ED3", - "commit_store": "0x1f558F6dcf0224Ef1F78A24814FED548B9602c80", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Arbitrum Mainnet": { - "off_ramp": "0x3DA330fd8Ef10d93cFB7D4f8ecE7BC1F10811feC", - "commit_store": "0x86D55Ff492cfBBAf0c0D42D4EE615144E78b3D02", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Base Mainnet": { - "off_ramp": "0x574c697deab06B805D8780898B3F136a1F4892Dc", - "commit_store": "0x002B164b1dcf4E92F352DC625A01Be0E890EdEea", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Ethereum Mainnet": { - "off_ramp": "0x181Bb1E97b0bDD1D85E741ad0943552D3682cc35", - "commit_store": "0x3fF27A34fF0FA77921C3438e67f58da1a83e9Ce1", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Optimism Mainnet": { - "off_ramp": "0xE7E080C8d62d595a223C577C7C8d1f75d9A5E664", - "commit_store": "0xF4d53346bDb6d393C74B0B72Aa7D6689a3eAad79", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Polygon Mainnet": { - "off_ramp": "0x26af2046Da85d7f6712D5edCa81B9E3b2e7A60Ab", - "commit_store": "0x4C1dA405a789AC2853A69D8290B8B9b47a0374F8", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "WeMix Mainnet": { - "off_ramp": "0xC027C5AEb230008c243Be463A73571e581F94c13", - "commit_store": "0x2EB426C8C54D740d1FC856eB3Ff96feA03957978", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - } - } - }, - "Ethereum Mainnet": { - "is_native_fee_token": true, - "fee_token": "0x514910771AF9Ca656af840dff83E8264EcF986CA", - "bridge_tokens": ["0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"], - "bridge_tokens_pools": ["0x69c24c970B65e22Ac26864aF10b2295B7d78f93A"], - "arm": "0x8B63b3DE93431C0f756A493644d128134291fA1b", - "router": "0x80226fc0Ee2b096224EeAc085Bb9a8cba1146f7D", - "price_registry": "0x8c9b2Efb7c64C394119270bfecE7f54763b958Ad", - "wrapped_native": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", - "src_contracts": { - "Arbitrum Mainnet": { - "on_ramp": "0x925228D7B82d883Dde340A55Fe8e6dA56244A22C", - "deployed_at": 11111111 - }, - "Avalanche Mainnet": { - "on_ramp": "0x3df8dAe2d123081c4D5E946E655F7c109B9Dd630", - "deployed_at": 11111111 - }, - "Base Mainnet": { - "on_ramp": "0xe2c2AB221AA0b957805f229d2AA57fBE2f4dADf7", - "deployed_at": 11111111 - }, - "BSC Mainnet": { - "on_ramp": "0x91D25A56Db77aD5147437d8B83Eb563D46eBFa69", - "deployed_at": 11111111 - }, - "Optimism Mainnet": { - "on_ramp": "0x86B47d8411006874eEf8E4584BdFD7be8e5549d1", - "deployed_at": 11111111 - }, - "Polygon Mainnet": { - "on_ramp": "0x35F0ca9Be776E4B38659944c257bDd0ba75F1B8B", - "deployed_at": 11111111 - }, - "WeMix Mainnet": { - "on_ramp": "0xCbE7e5DA76dC99Ac317adF6d99137005FDA4E2C4", - "deployed_at": 11111111 - } - }, - "dest_contracts": { - "Arbitrum Mainnet": { - "off_ramp": "0xeFC4a18af59398FF23bfe7325F2401aD44286F4d", - "commit_store": "0x9B2EEd6A1e16cB50Ed4c876D2dD69468B21b7749", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Avalanche Mainnet": { - "off_ramp": "0x569940e02D4425eac61A7601632eC00d69f75c17", - "commit_store": "0x2aa101BF99CaeF7fc1355D4c493a1fe187A007cE", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Base Mainnet": { - "off_ramp": "0xdf85c8381954694E74abD07488f452b4c2Cddfb3", - "commit_store": "0x8DC27D621c41a32140e22E2a4dAf1259639BAe04", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "BSC Mainnet": { - "off_ramp": "0x7Afe7088aff57173565F4b034167643AA8b9171c", - "commit_store": "0x87c55D48DF6EF7B08153Ab079e76bFEcbb793D75", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Optimism Mainnet": { - "off_ramp": "0xB095900fB91db00E6abD247A5A5AD1cee3F20BF7", - "commit_store": "0x4af4B497c998007eF83ad130318eB2b925a79dc8", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Polygon Mainnet": { - "off_ramp": "0x0af338F0E314c7551bcE0EF516d46d855b0Ee395", - "commit_store": "0xD37a60E8C36E802D2E1a6321832Ee85556Beeb76", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "WeMix Mainnet": { - "off_ramp": "0x3a129e6C18b23d18BA9E6Aa14Dc2e79d1f91c6c5", - "commit_store": "0x31f6ab382DDeb9A316Ab61C3945a5292a50a89AB", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - } - } - }, - "Kroma Mainnet": { - "is_native_fee_token": true, - "fee_token": "0xC1F6f7622ad37C3f46cDF6F8AA0344ADE80BF450", - "bridge_tokens": [], - "bridge_tokens_pools": [], - "arm": "0xB59779d3364BC6d71168245f9ebb96469E5a5a98", - "router": "0xE93E8B0d1b1CEB44350C8758ed1E2799CCee31aB", - "price_registry": "0x8155B4710e7bbC90924E957104F94Afd4f95Eca2", - "wrapped_native": "0x4200000000000000000000000000000000000001", - "src_contracts": { - "WeMix Mainnet": { - "on_ramp": "0x3C5Ab46fA1dB1dECD854224654313a69bf9fcAD3", - "deployed_at": 11111111 - } - }, - "dest_contracts": { - "WeMix Mainnet": { - "off_ramp": "0x2B555774B3D1dcbcd76efb7751F3c5FbCFABC5C4", - "commit_store": "0x213124614aAf31eBCE7c612A12aac5f8aAD77DE4", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - } - } - }, - "Optimism Mainnet": { - "is_native_fee_token": true, - "fee_token": "0x350a791Bfc2C21F9Ed5d10980Dad2e2638ffa7f6", - "bridge_tokens": ["0x4200000000000000000000000000000000000006"], - "bridge_tokens_pools": ["0x86E715415D8C8435903d1e8204fA1e9784Aa7305"], - "arm": "0x8C7C2C3362a42308BB5c368677Ad321D11693b81", - "router": "0x3206695CaE29952f4b0c22a169725a865bc8Ce0f", - "price_registry": "0xb52545aECE8C73A97E52a146757EC15b90Ed8488", - "wrapped_native": "0x4200000000000000000000000000000000000006", - "src_contracts": { - "Arbitrum Mainnet": { - "on_ramp": "0x0C9BE7Cfd12c735E5aaE047C1dCB845d54E518C3", - "deployed_at": 11111111 - }, - "Avalanche Mainnet": { - "on_ramp": "0xD0D3E757bFBce7ae1881DDD7F6d798DDcE588445", - "deployed_at": 11111111 - }, - "Base Mainnet": { - "on_ramp": "0x0b1760A8112183303c5526C6b24569fd3A274f3B", - "deployed_at": 11111111 - }, - "BSC Mainnet": { - "on_ramp": "0xa3c9544B82846C45BE37593d5d9ACffbE61BF3A6", - "deployed_at": 11111111 - }, - "Ethereum Mainnet": { - "on_ramp": "0x55183Db1d2aE0b63e4c92A64bEF2CBfc2032B127", - "deployed_at": 11111111 - }, - "Polygon Mainnet": { - "on_ramp": "0x6B57145e322c877E7D91Ed8E31266eB5c02F7EfC", - "deployed_at": 11111111 - }, - "WeMix Mainnet": { - "on_ramp": "0x82e9f4C5ec4a84E310d60D462a12042E5cbA0954", - "deployed_at": 11111111 - } - }, - "dest_contracts": { - "Arbitrum Mainnet": { - "off_ramp": "0x0C9BE7Cfd12c735E5aaE047C1dCB845d54E518C3", - "commit_store": "0x55028780918330FD00a34a61D9a7Efd3f43ca845", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Avalanche Mainnet": { - "off_ramp": "0x8dc6490A6204dF846BaBE809cB695ba17Df1F9B1", - "commit_store": "0xA190660787B6B183Dd82B243eA10e609327c7308", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Base Mainnet": { - "off_ramp": "0xBAE6560eCa9B77Cb047158C783e36F7735C86037", - "commit_store": "0x6168aDF58e1Ad446BaD45c6275Bef60Ef4FFBAb8", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "BSC Mainnet": { - "off_ramp": "0xE14501F2838F2fA1Ceb52E78ABdA289EcE1705EA", - "commit_store": "0xa8DD25B29787527Df283211C24Ac72B17150A696", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Ethereum Mainnet": { - "off_ramp": "0xd2D98Be6a1C241e86C807e51cED6ABb51d044203", - "commit_store": "0x4d75A5cE454b264b187BeE9e189aF1564a68408D", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Polygon Mainnet": { - "off_ramp": "0x7c6221880A1D62506b1A08Dab3Bf695A49AcDD22", - "commit_store": "0x0684076EE3595221861C50cDb9Cb66402Ec11Cb9", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "WeMix Mainnet": { - "off_ramp": "0x3e5B3b7559D39563a74434157b31781322dA712D", - "commit_store": "0x7954372FF6f80908e5A2dC2a19d796A1005f91D2", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - } - } - }, - "Polygon Mainnet": { - "is_native_fee_token": true, - "fee_token": "0xb0897686c545045aFc77CF20eC7A532E3120E0F1", - "bridge_tokens": [], - "bridge_tokens_pools": [], - "arm": "0xD7AcF65dA1E1f34b663aB199a474F209bF2b0523", - "router": "0x849c5ED5a80F5B408Dd4969b78c2C8fdf0565Bfe", - "price_registry": "0x30D873664Ba766C983984C7AF9A921ccE36D34e1", - "wrapped_native": "0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270", - "src_contracts": { - "Arbitrum Mainnet": { - "on_ramp": "0xD16D025330Edb91259EEA8ed499daCd39087c295", - "deployed_at": 11111111 - }, - "Avalanche Mainnet": { - "on_ramp": "0x5FA30697e90eB30954895c45b028F7C0dDD39b12", - "deployed_at": 11111111 - }, - "Base Mainnet": { - "on_ramp": "0x20B028A2e0F6CCe3A11f3CE5F2B8986F932e89b4", - "deployed_at": 11111111 - }, - "BSC Mainnet": { - "on_ramp": "0xF5b5A2fC11BF46B1669C3B19d98B19C79109Dca9", - "deployed_at": 11111111 - }, - "Ethereum Mainnet": { - "on_ramp": "0xFd77c53AA4eF0E3C01f5Ac012BF7Cc7A3ECf5168", - "deployed_at": 11111111 - }, - "Optimism Mainnet": { - "on_ramp": "0x3111cfbF5e84B5D9BD952dd8e957f4Ca75f728Cf", - "deployed_at": 11111111 - }, - "WeMix Mainnet": { - "on_ramp": "0x5060eF647a1F66BE6eE27FAe3046faf8D53CeB2d", - "deployed_at": 11111111 - } - }, - "dest_contracts": { - "Arbitrum Mainnet": { - "off_ramp": "0xa8a9eDa2867c2E0CE0d5ECe273961F1EcC3CC25B", - "commit_store": "0xbD4480658dca8496a65046dfD1BDD44EF897Bdb5", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Avalanche Mainnet": { - "off_ramp": "0xB9e3680639c9F0C4e0b02FD81C445094426244Ae", - "commit_store": "0x8c63d4e67f7c4af6FEd2f56A34fB4e01CB807CFF", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Base Mainnet": { - "off_ramp": "0xD0FA7DE2D18A0c59D3fD7dfC7aB4e913C6Aa7b68", - "commit_store": "0xF88053B9DAC8Dd3039a4eFa8639159aaa3F2D4Cb", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "BSC Mainnet": { - "off_ramp": "0x592773924741F0Da889a0dfdab71171Dd11E054C", - "commit_store": "0xEC4d35E1A85f770f4D93BA43a462c9d87Ef7017e", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Ethereum Mainnet": { - "off_ramp": "0x45320085fF051361D301eC1044318213A5387A15", - "commit_store": "0x4Dc771B5ef21ef60c33e2987E092345f2b63aE08", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Optimism Mainnet": { - "off_ramp": "0xBa754ecd3CFA7E9093F688EAc3860cf9D07Fc0AC", - "commit_store": "0x04C0D5302E3D8Ca0A0019141a52a23B59cdb70e4", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "WeMix Mainnet": { - "off_ramp": "0xd7c877ea02310Cce9278D9A048Aa1Bb9aF72F00d", - "commit_store": "0x92A1C927E8E10Ab6A40E5A5154e2300D278d1a67", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - } - } - }, - "WeMix Mainnet": { - "is_native_fee_token": true, - "fee_token": "0x80f1FcdC96B55e459BF52b998aBBE2c364935d69", - "bridge_tokens": [], - "bridge_tokens_pools": [], - "arm": "0x07aaC8B69A62dB5bd3d244091916EbF2fac17b76", - "router": "0x7798b795Fde864f4Cd1b124a38Ba9619B7F8A442", - "price_registry": "0x252863688762aD86868D3d3076233Eacd80c7055", - "wrapped_native": "0x7D72b22a74A216Af4a002a1095C8C707d6eC1C5f", - "src_contracts": { - "Arbitrum Mainnet": { - "on_ramp": "0x9aBfd6f4C865610692AB6fb1Be862575809fFabf", - "deployed_at": 11111111 - }, - "Avalanche Mainnet": { - "on_ramp": "0xbE0Cfae74677F8dd16a246a3a5c8cbB1973118f4", - "deployed_at": 11111111 - }, - "BSC Mainnet": { - "on_ramp": "0x56657ec4D15C71f7F3C17ba2b21C853A24Dc5381", - "deployed_at": 11111111 - }, - "Optimism Mainnet": { - "on_ramp": "0x70f3b0FD7e6a4B9B623e9AB859604A9EE03e48BD", - "deployed_at": 11111111 - }, - "Polygon Mainnet": { - "on_ramp": "0x777058C1e1dcE4eB8001F38631a1cd9450816e5a", - "deployed_at": 11111111 - }, - "Ethereum Mainnet": { - "on_ramp": "0x190bcE84CF2d500B878966F4Cf98a50d78f2675E", - "deployed_at": 11111111 - }, - "Kroma Mainnet": { - "on_ramp": "0x47E9AE0A815C94836202E696748A5d5476aD8735", - "deployed_at": 11111111 - } - }, - "dest_contracts": { - "Arbitrum Mainnet": { - "off_ramp": "0x2ba68a395B72a6E3498D312efeD755ed2f3CF223", - "commit_store": "0xdAeC234DA83F68707Bb8AcB2ee6a01a5FD4c2391", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Avalanche Mainnet": { - "off_ramp": "0xFac907F9a1087B846Faa75A14C5d34A8639233d8", - "commit_store": "0xF2812063446c7deD2CA306c67A68364BdDcbEfc5", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "BSC Mainnet": { - "off_ramp": "0x6ec9ca4Cba62cA17c55F05ad2000B46192f02035", - "commit_store": "0x84534BE763366a69710E119c100832955795B34B", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Optimism Mainnet": { - "off_ramp": "0x87220D01DF0fF27149B47227897074653788fd23", - "commit_store": "0xF8dD2be2C6FA43e48A17146380CbEBBB4291807b", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Polygon Mainnet": { - "off_ramp": "0x8f0229804513A9Bc00c1308414AB279Dbc718ae1", - "commit_store": "0x3A85D1b8641d83a87957C6ECF1b62151213e0842", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Ethereum Mainnet": { - "off_ramp": "0xF92Fa796F5307b029c65CA26f322a6D86f211194", - "commit_store": "0xbeC110FF43D52be2066B06525304A9924E16b73b", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - }, - "Kroma Mainnet": { - "off_ramp": "0xF886d8DC64E544af4835cbf91e5678A54D95B80e", - "commit_store": "0x8794C9534658fdCC44f2FF6645Bf31cf9F6d2d5D", - "receiver_dapp": "0x1A2A69e3eB1382FE34Bc579AdD5Bae39e31d4A2c" - } - } - } - } -} -""" - -[CCIP.Env] -TTL = '8h' - -[CCIP.Env.Network] -selected_networks = [ - 'ETHEREUM_MAINNET', - 'ARBITRUM_MAINNET', - 'OPTIMISM_MAINNET' - ] - -[CCIP.Groups.load] -NetworkPairs = [ - 'ETHEREUM_MAINNET,OPTIMISM_MAINNET', - 'ETHEREUM_MAINNET,ARBITRUM_MAINNET', - 'ARBITRUM_MAINNET,OPTIMISM_MAINNET' # added as batch 1 -] - -BiDirectionalLane = true -PhaseTimeout = '40m' -ExistingDeployment = true - -[CCIP.Groups.load.TokenConfig] -NoOfTokensPerChain = 1 -CCIPOwnerTokens = true - -[CCIP.Groups.load.LoadProfile] -RequestPerUnitTime = [1] -TimeUnit = '3h' -TestDuration = '24h' -TestRunName = 'mainnet-2.7-ccip1.2' -FailOnFirstErrorInLoad = true -SkipRequestIfAnotherRequestTriggeredWithin = '40m' - -[[CCIP.Groups.load.LoadProfile.MsgProfile.MsgDetails]] -MsgType = 'Data' -DestGasLimit = 0 -DataLength = 100 -NoOfTokens = 1 -AmountPerToken = 1 - -[CCIP.Groups.smoke] -# these are all the valid network pairs -NetworkPairs = [ - 'ETHEREUM_MAINNET,OPTIMISM_MAINNET', - 'ETHEREUM_MAINNET,ARBITRUM_MAINNET', - 'ARBITRUM_MAINNET,OPTIMISM_MAINNET' -] - -BiDirectionalLane = true -DestGasLimit = 0 -PhaseTimeout = '20m' -LocalCluster = false -ExistingDeployment = true -ReuseContracts = true - -[CCIP.Groups.smoke.TokenConfig] -NoOfTokensPerChain = 1 -CCIPOwnerTokens = true - -[CCIP.Groups.smoke.MsgDetails] -MsgType = 'Data' -DestGasLimit = 0 -DataLength = 100 -NoOfTokens = 1 -AmountPerToken = 1 \ No newline at end of file diff --git a/integration-tests/ccip-tests/testconfig/override/mainnet.toml b/integration-tests/ccip-tests/testconfig/override/mainnet.toml index 5b76b3803a..f723411eaf 100644 --- a/integration-tests/ccip-tests/testconfig/override/mainnet.toml +++ b/integration-tests/ccip-tests/testconfig/override/mainnet.toml @@ -9,639 +9,1070 @@ CommitStore = '1.2.0' [CCIP.Deployments] Data = """ { - "lane_configs": { + "lane_configs": { + "Arbitrum Mainnet": { + "is_native_fee_token": true, + "fee_token": "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1", + "arm": "0xC2C5E22a2d9715ed5C5BCC4D8eFf5966cf260744", + "router": "0x141fa059441E0ca23ce184B6A78bafD2A517DdE8", + "price_registry": "0x13015e4E6f839E1Aa1016DF521ea458ecA20438c", + "wrapped_native": "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1", + "src_contracts": { + "Avalanche Mainnet": { + "on_ramp": "0x05B723f3db92430FbE4395fD03E40Cc7e9D17988", + "deployed_at": 0 + }, + "BSC Mainnet": { + "on_ramp": "0x79f3ABeCe5A3AFFf32D47F4CFe45e7b65c9a2D91", + "deployed_at": 0 + }, + "Base Mainnet": { + "on_ramp": "0x77b60F85b25fD501E3ddED6C1fe7bF565C08A22A", + "deployed_at": 0 + }, + "Blast Mainnet": { + "on_ramp": "0x54480425E9e24138fdF1644a1F70007F25abfB46", + "deployed_at": 0 + }, + "Ethereum Mainnet": { + "on_ramp": "0xCe11020D56e5FDbfE46D9FC3021641FfbBB5AdEE", + "deployed_at": 0 + }, + "Gnosis Mainnet": { + "on_ramp": "0x1216DC856Af47a833254a280A038185F51C1B5c4", + "deployed_at": 0 + }, + "Metis Andromeda": { + "on_ramp": "0x5b23A0a103fC9028363B3BC3577e8Bd45B8E819F", + "deployed_at": 0 + }, + "Mode Mainnet": { + "on_ramp": "0x3920BF474BB50fffb4B77c1e6e66F65210D1D722", + "deployed_at": 0 + }, + "Optimism Mainnet": { + "on_ramp": "0xC09b72E8128620C40D89649019d995Cc79f030C3", + "deployed_at": 0 + }, + "Polygon Mainnet": { + "on_ramp": "0x122F05F49e90508F089eE8D0d868d1a4f3E5a809", + "deployed_at": 0 + }, + "WeMix Mainnet": { + "on_ramp": "0x66a0046ac9FA104eB38B04cfF391CcD0122E6FbC", + "deployed_at": 0 + }, + "ZKSync Mainnet": { + "on_ramp": "0x2C1016053d9873270d71613cA321aE97Fc89201d", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Avalanche Mainnet": { + "off_ramp": "0xe0109912157d5B75ea8b3181123Cf32c73bc9920", + "commit_store": "0xDaa61b8Cd85977820f92d1e749E1D9F55Da6CCEA", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "BSC Mainnet": { + "off_ramp": "0xB1b705c2315fced1B38baE463BE7DDef531e47fA", + "commit_store": "0x310cECbFf14Ad0307EfF762F461a487C1abb90bf", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Base Mainnet": { + "off_ramp": "0xdB19F77F87661f9be0F557cf9a1ebeCf7D8F206c", + "commit_store": "0x6e37f4c82d9A31cc42B445874dd3c3De97AB553f", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Blast Mainnet": { + "off_ramp": "0x449C59F4Ef3b1802DD054dd7837Eb2Ca91aFAB84", + "commit_store": "0x1E0e8B01693A248b3Aa1e5aca36336F9022Ceac0", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Ethereum Mainnet": { + "off_ramp": "0x542ba1902044069330e8c5b36A84EC503863722f", + "commit_store": "0x060331fEdA35691e54876D957B4F9e3b8Cb47d20", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Gnosis Mainnet": { + "off_ramp": "0x0C00414D9dcDB2DA7BF8AF26aE2deb617f09e756", + "commit_store": "0x1d464cd86c5C8358d56281aB31d2213534CCEA13", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Metis Andromeda": { + "off_ramp": "0xeF8dEb0c01f7389AD4ae05DAB30120dba915D53c", + "commit_store": "0xE594a09Aa8bCb55188758826A160615B95A6F3fE", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Mode Mainnet": { + "off_ramp": "0xEDE7ADACFbD27DBEBbE2d6C3BaDf12a634a72Faa", + "commit_store": "0x032B209a6B7a00336047505b55a4cBFBd29eE2c1", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Optimism Mainnet": { + "off_ramp": "0xeeed4D86F3E0e6d32A6Ad29d8De6A0Dc91963A5f", + "commit_store": "0xbbB563c4d98020b9c0f3Cc34c2C0Ef9676806E35", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Polygon Mainnet": { + "off_ramp": "0x9bDA7c8DCda4E39aFeB483cc0B7E3C1f6E0D5AB1", + "commit_store": "0x63a0AeaadAe851b990bBD9dc41f5C1B08b32026d", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "WeMix Mainnet": { + "off_ramp": "0xEEf5Fb4c4953F9cA9ab1f25cE590776AfFc2c455", + "commit_store": "0xD268286A277095a9C3C90205110831a84505881c", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "ZKSync Mainnet": { + "off_ramp": "0x50Fc0de671c775301e1Bdf19C17E778D0f978f6F", + "commit_store": "0x87732C2647168818ED49268EdA8A98C2e62ed744", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + } + } + }, + "Avalanche Mainnet": { + "is_native_fee_token": true, + "fee_token": "0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7", + "arm": "0x4f6Ec25f06A114ADD3154DC17fb637F750AdaA31", + "router": "0xF4c7E640EdA248ef95972845a62bdC74237805dB", + "price_registry": "0x2d3b38E0a4DFFDad2A613f7760bE1683F272eA18", + "wrapped_native": "0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7", + "src_contracts": { + "Arbitrum Mainnet": { + "on_ramp": "0x98f51B041e493fc4d72B8BD33218480bA0c66DDF", + "deployed_at": 0 + }, + "BSC Mainnet": { + "on_ramp": "0x8eaae6462816CB4957184c48B86afA7642D8Bf2B", + "deployed_at": 0 + }, + "Base Mainnet": { + "on_ramp": "0x268fb4311D2c6CB2bbA01CCA9AC073Fb3bfd1C7c", + "deployed_at": 0 + }, + "Ethereum Mainnet": { + "on_ramp": "0xD0701FcC7818c31935331B02Eb21e91eC71a1704", + "deployed_at": 0 + }, + "Gnosis Mainnet": { + "on_ramp": "0xBd0B9317F6AaA1085993F7b4CD468dE7A6428722", + "deployed_at": 0 + }, + "Optimism Mainnet": { + "on_ramp": "0x8629008887E073260c5434D6CaCFc83C3001d211", + "deployed_at": 0 + }, + "Polygon Mainnet": { + "on_ramp": "0x97500490d9126f34cf9aA0126d64623E170319Ef", + "deployed_at": 0 + }, + "WeMix Mainnet": { + "on_ramp": "0x9b1ed9De069Be4d50957464b359f98eD0Bf34dd5", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Arbitrum Mainnet": { + "off_ramp": "0x770b1375F86E7a9bf30DBe3F97bea67193dC9135", + "commit_store": "0x23E2b34Ce8e12c53f8a39AD4b3FFCa845f8E617C", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "BSC Mainnet": { + "off_ramp": "0x83F53Fc798FEbfFbdF84830AD403b9989187a06C", + "commit_store": "0xD8ceCE2D7794385E00Ce3EF94550E732b0A0B959", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Base Mainnet": { + "off_ramp": "0x4d6A796Bc85dcDF41ce9AaEB50B094C6b589748f", + "commit_store": "0xc4C4358FA01a04D6c6FE3b96a351946d4c2715C2", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Ethereum Mainnet": { + "off_ramp": "0x5B833BD6456c604Eb396C0fBa477aD49e82B1A2a", + "commit_store": "0x23E23958D220B774680f91c2c91a6f2B2f610d7e", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Gnosis Mainnet": { + "off_ramp": "0xDE7ebf1Dc753D916A9fbEC4ae521Ee74EC2d0B5f", + "commit_store": "0x2dbc917b4DD455532015949c3103B64fcDB891b2", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Optimism Mainnet": { + "off_ramp": "0xb68A3EE8bD0A09eE221cf1859Dd5a4d5765188Fe", + "commit_store": "0x83DCeeCf822981F9F8552925eEfd88CAc1905dEA", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Polygon Mainnet": { + "off_ramp": "0x19250aBE66B88F214d02B6f3BF80F4118290C619", + "commit_store": "0x87A0935cE6254dB1252bBac90d1D07D04846aDCA", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "WeMix Mainnet": { + "off_ramp": "0x317dE8bc5c3292E494b6496586696d4966A922B0", + "commit_store": "0x97Fbf3d6DEac16adC721aE9187CeEa1e610aC7Af", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + } + } + }, + "BSC Mainnet": { + "is_native_fee_token": true, + "fee_token": "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c", + "arm": "0x56491A98199aD2e687Ea9D0cFB7b4AC57B4980Fc", + "router": "0x34B03Cb9086d7D758AC55af71584F81A598759FE", + "price_registry": "0x18C3D917D55Bc1784a3d4729AA3e2C1ecd662fFd", + "wrapped_native": "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c", + "src_contracts": { + "Arbitrum Mainnet": { + "on_ramp": "0x2788b46BAcFF49BD89562e6bA5c5FBbbE5Fa92F7", + "deployed_at": 0 + }, + "Avalanche Mainnet": { + "on_ramp": "0x6aa72a998859eF93356c6521B72155D355D0Cfd2", + "deployed_at": 0 + }, + "Base Mainnet": { + "on_ramp": "0x70bC7f7a6D936b289bBF5c0E19ECE35B437E2e36", + "deployed_at": 0 + }, + "Blast Mainnet": { + "on_ramp": "0x02082b23D35d2670B8a636A431F3C30AF9d21e07", + "deployed_at": 0 + }, + "Ethereum Mainnet": { + "on_ramp": "0x0Bf40b034872D0b364f3DCec04C7434a4Da1C8d9", + "deployed_at": 0 + }, + "Gnosis Mainnet": { + "on_ramp": "0xAc9fE4179816077674d769698306CE6A7C6A1096", + "deployed_at": 0 + }, + "Mode Mainnet": { + "on_ramp": "0x4A83dA46c148AB5941a379b4cA49f42d14281C78", + "deployed_at": 0 + }, + "Optimism Mainnet": { + "on_ramp": "0x4FEB11A454C9E8038A8d0aDF599Fe7612ce114bA", + "deployed_at": 0 + }, + "Polygon Mainnet": { + "on_ramp": "0x6bD4754D86fc87FE5b463D368f26a3587a08347c", + "deployed_at": 0 + }, + "WeMix Mainnet": { + "on_ramp": "0x1467fF8f249f5bc604119Af26a47035886f856BE", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Arbitrum Mainnet": { + "off_ramp": "0x3DA330fd8Ef10d93cFB7D4f8ecE7BC1F10811feC", + "commit_store": "0x86D55Ff492cfBBAf0c0D42D4EE615144E78b3D02", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Avalanche Mainnet": { + "off_ramp": "0x37a6fa55fe61061Ae97bF7314Ae270eCF71c5ED3", + "commit_store": "0x1f558F6dcf0224Ef1F78A24814FED548B9602c80", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Base Mainnet": { + "off_ramp": "0x574c697deab06B805D8780898B3F136a1F4892Dc", + "commit_store": "0x002B164b1dcf4E92F352DC625A01Be0E890EdEea", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Blast Mainnet": { + "off_ramp": "0x6500EDFBD27d34b7B69D0D45865ddaC4A1ceafE1", + "commit_store": "0x3A328B3fA852409415c15271442EFE4c77C04992", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Ethereum Mainnet": { + "off_ramp": "0x181Bb1E97b0bDD1D85E741ad0943552D3682cc35", + "commit_store": "0x3fF27A34fF0FA77921C3438e67f58da1a83e9Ce1", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Gnosis Mainnet": { + "off_ramp": "0xBE9b0cc569E970dAb953d336c670fc6b7c856c19", + "commit_store": "0xEe89CC6C2236d3b99C2D9c0b3b911690F757FadF", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Mode Mainnet": { + "off_ramp": "0x6C702159daA4DEbae32E294c584B1EaF2356cB1A", + "commit_store": "0x73C8d1E9e240331E3345c6fBe6CDFC71B742B69C", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Optimism Mainnet": { + "off_ramp": "0xE7E080C8d62d595a223C577C7C8d1f75d9A5E664", + "commit_store": "0xF4d53346bDb6d393C74B0B72Aa7D6689a3eAad79", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Polygon Mainnet": { + "off_ramp": "0x26af2046Da85d7f6712D5edCa81B9E3b2e7A60Ab", + "commit_store": "0x4C1dA405a789AC2853A69D8290B8B9b47a0374F8", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "WeMix Mainnet": { + "off_ramp": "0xC027C5AEb230008c243Be463A73571e581F94c13", + "commit_store": "0x2EB426C8C54D740d1FC856eB3Ff96feA03957978", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + } + } + }, + "Base Mainnet": { + "is_native_fee_token": true, + "fee_token": "0x4200000000000000000000000000000000000006", + "arm": "0x91cB19E7c4Ba9B08CF544cDc9143042150B007C3", + "router": "0x881e3A65B4d4a04dD529061dd0071cf975F58bCD", + "price_registry": "0x1bA15c57c8b74cD32443D7583E7f6d7c638aCf46", + "wrapped_native": "0x4200000000000000000000000000000000000006", + "src_contracts": { "Arbitrum Mainnet": { - "is_native_fee_token": true, - "fee_token": "0xf97f4df75117a78c1A5a0DBb814Af92458539FB4", - "bridge_tokens": [], - "bridge_tokens_pools": [], - "arm": "0xe06b0e8c4bd455153e8794ad7Ea8Ff5A14B64E4b", - "router": "0x141fa059441E0ca23ce184B6A78bafD2A517DdE8", - "price_registry": "0x13015e4E6f839E1Aa1016DF521ea458ecA20438c", - "wrapped_native": "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1", - "version" : "1.4.0", - "src_contracts": { - "Avalanche Mainnet": { - "on_ramp": "0x05B723f3db92430FbE4395fD03E40Cc7e9D17988", - "deployed_at": 11111111 - }, - "Base Mainnet": { - "on_ramp": "0x77b60F85b25fD501E3ddED6C1fe7bF565C08A22A", - "deployed_at": 11111111 - }, - "BSC Mainnet": { - "on_ramp": "0x79f3ABeCe5A3AFFf32D47F4CFe45e7b65c9a2D91", - "deployed_at": 11111111 - }, - "Ethereum Mainnet": { - "on_ramp": "0xCe11020D56e5FDbfE46D9FC3021641FfbBB5AdEE", - "deployed_at": 11111111 - }, - "Optimism Mainnet": { - "on_ramp": "0xC09b72E8128620C40D89649019d995Cc79f030C3", - "deployed_at": 11111111 - }, - "Polygon Mainnet": { - "on_ramp": "0x122F05F49e90508F089eE8D0d868d1a4f3E5a809", - "deployed_at": 11111111 - }, - "WeMix Mainnet": { - "on_ramp": "0x66a0046ac9FA104eB38B04cfF391CcD0122E6FbC", - "deployed_at": 11111111 - } - }, - "dest_contracts": { - "Avalanche Mainnet": { - "off_ramp": "0xe0109912157d5B75ea8b3181123Cf32c73bc9920", - "commit_store": "0xDaa61b8Cd85977820f92d1e749E1D9F55Da6CCEA", - "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" - }, - "Base Mainnet": { - "off_ramp": "0xdB19F77F87661f9be0F557cf9a1ebeCf7D8F206c", - "commit_store": "0x6e37f4c82d9A31cc42B445874dd3c3De97AB553f", - "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" - }, - "BSC Mainnet": { - "off_ramp": "0xB1b705c2315fced1B38baE463BE7DDef531e47fA", - "commit_store": "0x310cECbFf14Ad0307EfF762F461a487C1abb90bf", - "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" - }, - "Ethereum Mainnet": { - "off_ramp": "0x542ba1902044069330e8c5b36A84EC503863722f", - "commit_store": "0x060331fEdA35691e54876D957B4F9e3b8Cb47d20", - "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" - }, - "Optimism Mainnet": { - "off_ramp": "0xeeed4D86F3E0e6d32A6Ad29d8De6A0Dc91963A5f", - "commit_store": "0xbbB563c4d98020b9c0f3Cc34c2C0Ef9676806E35", - "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" - }, - "Polygon Mainnet": { - "off_ramp": "0x9bDA7c8DCda4E39aFeB483cc0B7E3C1f6E0D5AB1", - "commit_store": "0x63a0AeaadAe851b990bBD9dc41f5C1B08b32026d", - "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" - }, - "WeMix Mainnet": { - "off_ramp": "0xEEf5Fb4c4953F9cA9ab1f25cE590776AfFc2c455", - "commit_store": "0xD268286A277095a9C3C90205110831a84505881c", - "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" - } - } + "on_ramp": "0x1E5Ca70d1e7A1B26061125738a880BBeA42FeB21", + "deployed_at": 0 }, "Avalanche Mainnet": { - "is_native_fee_token": true, - "fee_token": "0x5947BB275c521040051D82396192181b413227A3", - "bridge_tokens": [], - "bridge_tokens_pools": [], - "arm": "0xdFD6C0dc67666DE3bB36b31eec5c7B1542A82C1E", - "router": "0xF4c7E640EdA248ef95972845a62bdC74237805dB", - "price_registry": "0xfA4edD04eaAcDB07c8D73621bc1790eC50D8c489", - "wrapped_native": "0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7", - "src_contracts": { - "Arbitrum Mainnet": { - "on_ramp": "0x98f51B041e493fc4d72B8BD33218480bA0c66DDF", - "deployed_at": 11111111 - }, - "Base Mainnet": { - "on_ramp": "0x268fb4311D2c6CB2bbA01CCA9AC073Fb3bfd1C7c", - "deployed_at": 11111111 - }, - "BSC Mainnet": { - "on_ramp": "0x8eaae6462816CB4957184c48B86afA7642D8Bf2B", - "deployed_at": 11111111 - }, - "Ethereum Mainnet": { - "on_ramp": "0xD0701FcC7818c31935331B02Eb21e91eC71a1704", - "deployed_at": 11111111 - }, - "Optimism Mainnet": { - "on_ramp": "0x8629008887E073260c5434D6CaCFc83C3001d211", - "deployed_at": 11111111 - }, - "Polygon Mainnet": { - "on_ramp": "0x97500490d9126f34cf9aA0126d64623E170319Ef", - "deployed_at": 11111111 - }, - "WeMix Mainnet": { - "on_ramp": "0x9b1ed9De069Be4d50957464b359f98eD0Bf34dd5", - "deployed_at": 11111111 - } - }, - "dest_contracts": { - "Arbitrum Mainnet": { - "off_ramp": "0x770b1375F86E7a9bf30DBe3F97bea67193dC9135", - "commit_store": "0x23E2b34Ce8e12c53f8a39AD4b3FFCa845f8E617C", - "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" - }, - "Base Mainnet": { - "off_ramp": "0x4d6A796Bc85dcDF41ce9AaEB50B094C6b589748f", - "commit_store": "0xc4C4358FA01a04D6c6FE3b96a351946d4c2715C2", - "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" - }, - "BSC Mainnet": { - "off_ramp": "0x83F53Fc798FEbfFbdF84830AD403b9989187a06C", - "commit_store": "0xD8ceCE2D7794385E00Ce3EF94550E732b0A0B959", - "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" - }, - "Ethereum Mainnet": { - "off_ramp": "0x5B833BD6456c604Eb396C0fBa477aD49e82B1A2a", - "commit_store": "0x23E23958D220B774680f91c2c91a6f2B2f610d7e", - "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" - }, - "Optimism Mainnet": { - "off_ramp": "0xb68A3EE8bD0A09eE221cf1859Dd5a4d5765188Fe", - "commit_store": "0x83DCeeCf822981F9F8552925eEfd88CAc1905dEA", - "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" - }, - "Polygon Mainnet": { - "off_ramp": "0x19250aBE66B88F214d02B6f3BF80F4118290C619", - "commit_store": "0x87A0935cE6254dB1252bBac90d1D07D04846aDCA", - "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" - }, - "WeMix Mainnet": { - "off_ramp": "0x317dE8bc5c3292E494b6496586696d4966A922B0", - "commit_store": "0x97Fbf3d6DEac16adC721aE9187CeEa1e610aC7Af", - "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" - } - } + "on_ramp": "0xBE5a9E336D9614024B4Fa10D8112671fc9A42d96", + "deployed_at": 0 + }, + "BSC Mainnet": { + "on_ramp": "0xdd4Fb402d41Beb0eEeF6CfB1bf445f50bDC8c981", + "deployed_at": 0 + }, + "Blast Mainnet": { + "on_ramp": "0xCCC32e2794EaD73f0a0a514Ac1c78D048968ab81", + "deployed_at": 0 + }, + "Ethereum Mainnet": { + "on_ramp": "0xDEA286dc0E01Cb4755650A6CF8d1076b454eA1cb", + "deployed_at": 0 + }, + "Gnosis Mainnet": { + "on_ramp": "0xcDD0e963E0708a4E936202396983E458cFA4A363", + "deployed_at": 0 + }, + "Mode Mainnet": { + "on_ramp": "0x626aCCbDDD73532df1caEDb5628Fdc40C5f429Ba", + "deployed_at": 0 + }, + "Optimism Mainnet": { + "on_ramp": "0xd952FEAcDd5919Cc5E9454b53bF45d4E73dD6457", + "deployed_at": 0 + }, + "Polygon Mainnet": { + "on_ramp": "0x3DB8Bea142e41cA3633890d0e5640F99a895D6A5", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Arbitrum Mainnet": { + "off_ramp": "0x8531E63aE9279a1f0D09eba566CD1b092b95f3D5", + "commit_store": "0x327E13f54c7871a2416006B33B4822eAAD357916", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Avalanche Mainnet": { + "off_ramp": "0x8345F2fF67e5A65e85dc955DE1414832608E00aD", + "commit_store": "0xd0b13be4c53A6262b47C5DDd36F0257aa714F562", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "BSC Mainnet": { + "off_ramp": "0x48a51f5D38BE630Ddd6417Ea2D9052B8efc91a18", + "commit_store": "0xF97127e77252284EC9D4bc13C247c9D1A99F72B0", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Blast Mainnet": { + "off_ramp": "0x15F54FDd37ccC8E5a0b64633C95Ef8209Fd86401", + "commit_store": "0x52b5b4f3Cc50E38f736f23897f192430E131ccB8", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Ethereum Mainnet": { + "off_ramp": "0xEC0cFe335a4d53dBA70CB650Ab56eEc32788F0BB", + "commit_store": "0x0ae3c2c7FB789bd05A450CD3075D11f6c2Ca4F77", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Gnosis Mainnet": { + "off_ramp": "0xA24D3Bc3A59798a57AF58f69c89DC1C8aFD78F18", + "commit_store": "0x672dbdC3aF7eE37436fe101531D33266D85F33c9", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Mode Mainnet": { + "off_ramp": "0xFC30bFe46b11D4E25C6f7492fd064A70FbF18848", + "commit_store": "0xaeDBe55633F74A291F0A43Daa0Fd719615b78363", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Optimism Mainnet": { + "off_ramp": "0xf50c0d2a8B6Db60f1D93E60f03d0413D56153E4F", + "commit_store": "0x16f72C15165f7C9d74c12fDF188E399d4d3724e4", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Polygon Mainnet": { + "off_ramp": "0x75F29f058b31106F99caFdc17c9b26ADfcC7b5D7", + "commit_store": "0xb719616E732581B570232DfB13Ca49D27667Af9f", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + } + } + }, + "Blast Mainnet": { + "is_native_fee_token": true, + "fee_token": "0x4300000000000000000000000000000000000004", + "arm": "0x96aFe20249C4f6f55d2fe0E792138f6a4dC566A4", + "router": "0x12e0B8E349C6fb7E6E40713E8125C3cF1127ea8C", + "price_registry": "0x4f66d9e65af0d3DC27897E29f571f933291bb07c", + "wrapped_native": "0x4300000000000000000000000000000000000004", + "src_contracts": { + "Arbitrum Mainnet": { + "on_ramp": "0x42E1f5f5ACCe6e4971D9B9468D7A9Abed8D69DdD", + "deployed_at": 0 + }, + "BSC Mainnet": { + "on_ramp": "0x9c98d7aE731b0A53bedffBc1a12d9d43501Ea464", + "deployed_at": 0 }, "Base Mainnet": { - "is_native_fee_token": true, - "fee_token": "0x88Fb150BDc53A65fe94Dea0c9BA0a6dAf8C6e196", - "bridge_tokens": [], - "bridge_tokens_pools": [], - "arm": "0x38660c8CC222c0192b635c2ac09687B4F25cCE5F", - "router": "0x881e3A65B4d4a04dD529061dd0071cf975F58bCD", - "price_registry": "0x6337a58D4BD7Ba691B66341779e8f87d4679923a", - "wrapped_native": "0x4200000000000000000000000000000000000006", - "src_contracts": { - "Arbitrum Mainnet": { - "on_ramp": "0x1E5Ca70d1e7A1B26061125738a880BBeA42FeB21", - "deployed_at": 11111111 - }, - "Avalanche Mainnet": { - "on_ramp": "0xBE5a9E336D9614024B4Fa10D8112671fc9A42d96", - "deployed_at": 11111111 - }, - "BSC Mainnet": { - "on_ramp": "0xdd4Fb402d41Beb0eEeF6CfB1bf445f50bDC8c981", - "deployed_at": 11111111 - }, - "Ethereum Mainnet": { - "on_ramp": "0xDEA286dc0E01Cb4755650A6CF8d1076b454eA1cb", - "deployed_at": 11111111 - }, - "Optimism Mainnet": { - "on_ramp": "0xd952FEAcDd5919Cc5E9454b53bF45d4E73dD6457", - "deployed_at": 11111111 - }, - "Polygon Mainnet": { - "on_ramp": "0x3DB8Bea142e41cA3633890d0e5640F99a895D6A5", - "deployed_at": 11111111 - } - }, - "dest_contracts": { - "Arbitrum Mainnet": { - "off_ramp": "0x8531E63aE9279a1f0D09eba566CD1b092b95f3D5", - "commit_store": "0x327E13f54c7871a2416006B33B4822eAAD357916", - "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" - }, - "Avalanche Mainnet": { - "off_ramp": "0x8345F2fF67e5A65e85dc955DE1414832608E00aD", - "commit_store": "0xd0b13be4c53A6262b47C5DDd36F0257aa714F562", - "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" - }, - "BSC Mainnet": { - "off_ramp": "0x48a51f5D38BE630Ddd6417Ea2D9052B8efc91a18", - "commit_store": "0xF97127e77252284EC9D4bc13C247c9D1A99F72B0", - "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" - }, - "Ethereum Mainnet": { - "off_ramp": "0xEC0cFe335a4d53dBA70CB650Ab56eEc32788F0BB", - "commit_store": "0x0ae3c2c7FB789bd05A450CD3075D11f6c2Ca4F77", - "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" - }, - "Optimism Mainnet": { - "off_ramp": "0xf50c0d2a8B6Db60f1D93E60f03d0413D56153E4F", - "commit_store": "0x16f72C15165f7C9d74c12fDF188E399d4d3724e4", - "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" - }, - "Polygon Mainnet": { - "off_ramp": "0x75F29f058b31106F99caFdc17c9b26ADfcC7b5D7", - "commit_store": "0xb719616E732581B570232DfB13Ca49D27667Af9f", - "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" - } - } + "on_ramp": "0x955f139225F5d7021EB911ED2787a795f71E5eb6", + "deployed_at": 0 + }, + "Ethereum Mainnet": { + "on_ramp": "0xBD9bf9AA79adF083BB7100848Eb15F4e8282E27e", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Arbitrum Mainnet": { + "off_ramp": "0x01A38cd2da195C704bA192fCCDddd8986cb7EdE9", + "commit_store": "0xab6D69db1C1E9B97a26eB3983b0878AdeD248200", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" }, "BSC Mainnet": { - "is_native_fee_token": true, - "fee_token": "0x404460C6A5EdE2D891e8297795264fDe62ADBB75", - "bridge_tokens": [], - "bridge_tokens_pools": [], - "arm": "0x3DB43b96B2625F4232e9Df900d464dd2c64C0021", - "router": "0x34B03Cb9086d7D758AC55af71584F81A598759FE", - "price_registry": "0xd64aAbD70A71d9f0A00B99F6EFc1626aA2dD43C7", - "wrapped_native": "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c", - "src_contracts": { - "Avalanche Mainnet": { - "on_ramp": "0x6aa72a998859eF93356c6521B72155D355D0Cfd2", - "deployed_at": 11111111 - }, - "Arbitrum Mainnet": { - "on_ramp": "0x2788b46BAcFF49BD89562e6bA5c5FBbbE5Fa92F7", - "deployed_at": 11111111 - }, - "Base Mainnet": { - "on_ramp": "0x70bC7f7a6D936b289bBF5c0E19ECE35B437E2e36", - "deployed_at": 11111111 - }, - "Ethereum Mainnet": { - "on_ramp": "0x0Bf40b034872D0b364f3DCec04C7434a4Da1C8d9", - "deployed_at": 11111111 - }, - "Optimism Mainnet": { - "on_ramp": "0x4FEB11A454C9E8038A8d0aDF599Fe7612ce114bA", - "deployed_at": 11111111 - }, - "Polygon Mainnet": { - "on_ramp": "0x6bD4754D86fc87FE5b463D368f26a3587a08347c", - "deployed_at": 11111111 - }, - "WeMix Mainnet": { - "on_ramp": "0x1467fF8f249f5bc604119Af26a47035886f856BE", - "deployed_at": 11111111 - } - }, - "dest_contracts": { - "Avalanche Mainnet": { - "off_ramp": "0x37a6fa55fe61061Ae97bF7314Ae270eCF71c5ED3", - "commit_store": "0x1f558F6dcf0224Ef1F78A24814FED548B9602c80", - "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" - }, - "Arbitrum Mainnet": { - "off_ramp": "0x3DA330fd8Ef10d93cFB7D4f8ecE7BC1F10811feC", - "commit_store": "0x86D55Ff492cfBBAf0c0D42D4EE615144E78b3D02", - "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" - }, - "Base Mainnet": { - "off_ramp": "0x574c697deab06B805D8780898B3F136a1F4892Dc", - "commit_store": "0x002B164b1dcf4E92F352DC625A01Be0E890EdEea", - "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" - }, - "Ethereum Mainnet": { - "off_ramp": "0x181Bb1E97b0bDD1D85E741ad0943552D3682cc35", - "commit_store": "0x3fF27A34fF0FA77921C3438e67f58da1a83e9Ce1", - "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" - }, - "Optimism Mainnet": { - "off_ramp": "0xE7E080C8d62d595a223C577C7C8d1f75d9A5E664", - "commit_store": "0xF4d53346bDb6d393C74B0B72Aa7D6689a3eAad79", - "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" - }, - "Polygon Mainnet": { - "off_ramp": "0x26af2046Da85d7f6712D5edCa81B9E3b2e7A60Ab", - "commit_store": "0x4C1dA405a789AC2853A69D8290B8B9b47a0374F8", - "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" - }, - "WeMix Mainnet": { - "off_ramp": "0xC027C5AEb230008c243Be463A73571e581F94c13", - "commit_store": "0x2EB426C8C54D740d1FC856eB3Ff96feA03957978", - "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" - } - } + "off_ramp": "0xabC7Dffb2590c44a201EC7532382e1fc01Cd9eEb", + "commit_store": "0xA3086bf1D609d8e8028E8339e4aa4362C7da339D", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Base Mainnet": { + "off_ramp": "0x0406F8f66C10Da99ff518bc2242e0Ec486a2c787", + "commit_store": "0xc6A97d753a3001e0B893e5FA2b0ec3d623af6C20", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" }, "Ethereum Mainnet": { - "is_native_fee_token": true, - "fee_token": "0x514910771AF9Ca656af840dff83E8264EcF986CA", - "bridge_tokens": [], - "bridge_tokens_pools": [], - "arm": "0x8B63b3DE93431C0f756A493644d128134291fA1b", - "router": "0x80226fc0Ee2b096224EeAc085Bb9a8cba1146f7D", - "price_registry": "0x8c9b2Efb7c64C394119270bfecE7f54763b958Ad", - "wrapped_native": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", - "src_contracts": { - "Arbitrum Mainnet": { - "on_ramp": "0x925228D7B82d883Dde340A55Fe8e6dA56244A22C", - "deployed_at": 11111111 - }, - "Avalanche Mainnet": { - "on_ramp": "0x3df8dAe2d123081c4D5E946E655F7c109B9Dd630", - "deployed_at": 11111111 - }, - "Base Mainnet": { - "on_ramp": "0xe2c2AB221AA0b957805f229d2AA57fBE2f4dADf7", - "deployed_at": 11111111 - }, - "BSC Mainnet": { - "on_ramp": "0x91D25A56Db77aD5147437d8B83Eb563D46eBFa69", - "deployed_at": 11111111 - }, - "Optimism Mainnet": { - "on_ramp": "0x86B47d8411006874eEf8E4584BdFD7be8e5549d1", - "deployed_at": 11111111 - }, - "Polygon Mainnet": { - "on_ramp": "0x35F0ca9Be776E4B38659944c257bDd0ba75F1B8B", - "deployed_at": 11111111 - }, - "WeMix Mainnet": { - "on_ramp": "0xCbE7e5DA76dC99Ac317adF6d99137005FDA4E2C4", - "deployed_at": 11111111 - } - }, - "dest_contracts": { - "Arbitrum Mainnet": { - "off_ramp": "0xeFC4a18af59398FF23bfe7325F2401aD44286F4d", - "commit_store": "0x9B2EEd6A1e16cB50Ed4c876D2dD69468B21b7749", - "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" - }, - "Avalanche Mainnet": { - "off_ramp": "0x569940e02D4425eac61A7601632eC00d69f75c17", - "commit_store": "0x2aa101BF99CaeF7fc1355D4c493a1fe187A007cE", - "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" - }, - "Base Mainnet": { - "off_ramp": "0xdf85c8381954694E74abD07488f452b4c2Cddfb3", - "commit_store": "0x8DC27D621c41a32140e22E2a4dAf1259639BAe04", - "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" - }, - "BSC Mainnet": { - "off_ramp": "0x7Afe7088aff57173565F4b034167643AA8b9171c", - "commit_store": "0x87c55D48DF6EF7B08153Ab079e76bFEcbb793D75", - "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" - }, - "Optimism Mainnet": { - "off_ramp": "0xB095900fB91db00E6abD247A5A5AD1cee3F20BF7", - "commit_store": "0x4af4B497c998007eF83ad130318eB2b925a79dc8", - "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" - }, - "Polygon Mainnet": { - "off_ramp": "0x0af338F0E314c7551bcE0EF516d46d855b0Ee395", - "commit_store": "0xD37a60E8C36E802D2E1a6321832Ee85556Beeb76", - "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" - }, - "WeMix Mainnet": { - "off_ramp": "0x3a129e6C18b23d18BA9E6Aa14Dc2e79d1f91c6c5", - "commit_store": "0x31f6ab382DDeb9A316Ab61C3945a5292a50a89AB", - "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" - } - } + "off_ramp": "0x4e0092bBC8EfAb6Eca295caB66986193b90a1Bb9", + "commit_store": "0xd7cA96B58EE33FdB3aa1392c30eD02645b1F28e2", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + } + } + }, + "Celo": { + "is_native_fee_token": true, + "fee_token": "0x2021B12D8138e2D63cF0895eccABC0DFc92416c6", + "arm": "0x832Ca6A279D8F8c695986086B35c70D4E0c817CC", + "router": "0xfB48f15480926A4ADf9116Dca468bDd2EE6C5F62", + "price_registry": "0xD9FcEEA20dBB3Dfb91763B301819C9666429DC26", + "wrapped_native": "0x2021B12D8138e2D63cF0895eccABC0DFc92416c6", + "src_contracts": { + "Ethereum Mainnet": { + "on_ramp": "0x27C96A8a2f70a8408aD6c620717a3bDaA54bb10b", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Ethereum Mainnet": { + "off_ramp": "0x90902C0AEE857F3A42f2beBEa38724cE7b7a0cff", + "commit_store": "0x25adA90B241143DD5Df04Fb06C1fF6E7f7624ad9", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + } + } + }, + "Ethereum Mainnet": { + "is_native_fee_token": true, + "fee_token": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", + "arm": "0xdCD48419bD5Cd9d1b097695F2af4Ee125aADF84F", + "router": "0x80226fc0Ee2b096224EeAc085Bb9a8cba1146f7D", + "price_registry": "0x020082A7a9c2510e1921116001152DEE4da81985", + "wrapped_native": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", + "src_contracts": { + "Arbitrum Mainnet": { + "on_ramp": "0x925228D7B82d883Dde340A55Fe8e6dA56244A22C", + "deployed_at": 0 }, - "Kroma Mainnet": { - "is_native_fee_token": true, - "fee_token": "0xC1F6f7622ad37C3f46cDF6F8AA0344ADE80BF450", - "bridge_tokens": [], - "bridge_tokens_pools": [], - "arm": "0xB59779d3364BC6d71168245f9ebb96469E5a5a98", - "router": "0xE93E8B0d1b1CEB44350C8758ed1E2799CCee31aB", - "price_registry": "0x8155B4710e7bbC90924E957104F94Afd4f95Eca2", - "wrapped_native": "0x4200000000000000000000000000000000000001", - "src_contracts": { - "WeMix Mainnet": { - "on_ramp": "0x3C5Ab46fA1dB1dECD854224654313a69bf9fcAD3", - "deployed_at": 11111111 - } - }, - "dest_contracts": { - "WeMix Mainnet": { - "off_ramp": "0x2B555774B3D1dcbcd76efb7751F3c5FbCFABC5C4", - "commit_store": "0x213124614aAf31eBCE7c612A12aac5f8aAD77DE4", - "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" - } - } + "Avalanche Mainnet": { + "on_ramp": "0x3df8dAe2d123081c4D5E946E655F7c109B9Dd630", + "deployed_at": 0 + }, + "BSC Mainnet": { + "on_ramp": "0x91D25A56Db77aD5147437d8B83Eb563D46eBFa69", + "deployed_at": 0 + }, + "Base Mainnet": { + "on_ramp": "0xe2c2AB221AA0b957805f229d2AA57fBE2f4dADf7", + "deployed_at": 0 + }, + "Blast Mainnet": { + "on_ramp": "0x4545F9a17DA50110632C14704a15d893BF9CBD27", + "deployed_at": 0 + }, + "Celo": { + "on_ramp": "0xEd5bE9508ae56531cc0EDe6A3bD588Eb9E2e3cfa", + "deployed_at": 0 + }, + "Gnosis Mainnet": { + "on_ramp": "0xF538dA6c673A30338269655f4e019B71ba58CFd4", + "deployed_at": 0 + }, + "Metis Andromeda": { + "on_ramp": "0xa5ef33B57dD8B653F9A9EA7114f46376d18264aC", + "deployed_at": 0 + }, + "Mode Mainnet": { + "on_ramp": "0x466a078d17e3706a9414ACc48029EE9Bae4C9b65", + "deployed_at": 0 + }, + "Optimism Mainnet": { + "on_ramp": "0x86B47d8411006874eEf8E4584BdFD7be8e5549d1", + "deployed_at": 0 + }, + "Polygon Mainnet": { + "on_ramp": "0x35F0ca9Be776E4B38659944c257bDd0ba75F1B8B", + "deployed_at": 0 + }, + "WeMix Mainnet": { + "on_ramp": "0xCbE7e5DA76dC99Ac317adF6d99137005FDA4E2C4", + "deployed_at": 0 + }, + "ZKSync Mainnet": { + "on_ramp": "0xD54C93A99CBCb8D865E13DA321B540171795A89f", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Arbitrum Mainnet": { + "off_ramp": "0xeFC4a18af59398FF23bfe7325F2401aD44286F4d", + "commit_store": "0x9B2EEd6A1e16cB50Ed4c876D2dD69468B21b7749", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Avalanche Mainnet": { + "off_ramp": "0x569940e02D4425eac61A7601632eC00d69f75c17", + "commit_store": "0x2aa101BF99CaeF7fc1355D4c493a1fe187A007cE", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "BSC Mainnet": { + "off_ramp": "0x7Afe7088aff57173565F4b034167643AA8b9171c", + "commit_store": "0x87c55D48DF6EF7B08153Ab079e76bFEcbb793D75", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Base Mainnet": { + "off_ramp": "0xdf85c8381954694E74abD07488f452b4c2Cddfb3", + "commit_store": "0x8DC27D621c41a32140e22E2a4dAf1259639BAe04", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Blast Mainnet": { + "off_ramp": "0x1a904DbbaDdE629a1460e2F6E2E485Ce06Ed7599", + "commit_store": "0x3CB2A81bb8a188C5353CdFa9994ed8666556FC53", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Celo": { + "off_ramp": "0xd5083684eE92dDeA117636ae5E2F1cb7fE4dfd46", + "commit_store": "0x831097033C88c82a7F1897b168Aa88cC44540C8f", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Gnosis Mainnet": { + "off_ramp": "0xE93ec2A57e38C8541c893348cCafEAB01F7D47d4", + "commit_store": "0x118a9389960F86390A4F14ce4C95D6ff076C6bFC", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Metis Andromeda": { + "off_ramp": "0xCe6364dBe64D2789D916180131fAda2ABFF702E8", + "commit_store": "0x3d8a95adA63D406ee8232562AbD83CEdb0B90466", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Mode Mainnet": { + "off_ramp": "0xE8af3b68eDfFf65Ce48648009982380701f09B92", + "commit_store": "0x76264869a3eBF51a59FCa5ABa84ee2867c7F190e", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Optimism Mainnet": { + "off_ramp": "0xB095900fB91db00E6abD247A5A5AD1cee3F20BF7", + "commit_store": "0x4af4B497c998007eF83ad130318eB2b925a79dc8", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Polygon Mainnet": { + "off_ramp": "0x0af338F0E314c7551bcE0EF516d46d855b0Ee395", + "commit_store": "0xD37a60E8C36E802D2E1a6321832Ee85556Beeb76", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "WeMix Mainnet": { + "off_ramp": "0x3a129e6C18b23d18BA9E6Aa14Dc2e79d1f91c6c5", + "commit_store": "0x31f6ab382DDeb9A316Ab61C3945a5292a50a89AB", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "ZKSync Mainnet": { + "off_ramp": "0xb368c8946D9fa5A497cDe1Dff7213f9CdfD143Bf", + "commit_store": "0xa4d264470a67D9f6682EE12Bdc9c35Df44e3F194", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + } + } + }, + "Gnosis Mainnet": { + "is_native_fee_token": true, + "fee_token": "0xe91D153E0b41518A2Ce8Dd3D7944Fa863463a97d", + "arm": "0x2ab5ff904CFFdD37f19cC34597cF425916F2DAcA", + "router": "0x4aAD6071085df840abD9Baf1697d5D5992bDadce", + "price_registry": "0xec00a50EFb62F5f686E0FdEFDD6e10744dc53cAD", + "wrapped_native": "0xe91D153E0b41518A2Ce8Dd3D7944Fa863463a97d", + "src_contracts": { + "Arbitrum Mainnet": { + "on_ramp": "0x7A36511202f54a8A3Bc62Cc1df24bd391f7c9864", + "deployed_at": 0 + }, + "Avalanche Mainnet": { + "on_ramp": "0x732753869bc6bB07Ec81A403F926bbF6fC2FeaE2", + "deployed_at": 0 + }, + "BSC Mainnet": { + "on_ramp": "0xD5d33bc0BF395B39514B7f9f8F66ebc9D8e650Cb", + "deployed_at": 0 + }, + "Base Mainnet": { + "on_ramp": "0x400eFb50480a73FEc02b115b53F0Ec6EcFf03C67", + "deployed_at": 0 + }, + "Ethereum Mainnet": { + "on_ramp": "0x0F246651F1c2275B4E14d8ae166D1fd3Af05c405", + "deployed_at": 0 + }, + "Optimism Mainnet": { + "on_ramp": "0x391516732884d3F8Eec3301C19b819E6e6044C17", + "deployed_at": 0 + }, + "Polygon Mainnet": { + "on_ramp": "0x566c7A2Cb557c36082301B97E998721D14E4bF7d", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Arbitrum Mainnet": { + "off_ramp": "0x1bee1FD97824288a36B725f9CF20E07A67d5113b", + "commit_store": "0xB3a48e8664C5dE26822ae44577b100b717C36a54", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Avalanche Mainnet": { + "off_ramp": "0x633c19cCD7A818770f7BF59eB9C5AB632CDbc4D5", + "commit_store": "0xbbC073fb2D424eA45A571cc4dd91745E45d0aC73", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "BSC Mainnet": { + "off_ramp": "0x4D90524de5783257fd64d1a20689a5b9Bad25de0", + "commit_store": "0xAae8De9f1B7e2FFF0563c2BBf0c69593BD517b52", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Base Mainnet": { + "off_ramp": "0x9118303DE7f4342F9B057f6EC1Be282aa543D99C", + "commit_store": "0xa75f463b8a1d8bf7694Ac13E02938894F45eFbaA", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Ethereum Mainnet": { + "off_ramp": "0xFF61E57A2eE83FA262006C2DaF0D5fB2b36F3070", + "commit_store": "0xF433De9A293553c133E2dB90e226c2F2911f435C", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Optimism Mainnet": { + "off_ramp": "0x9D3aA479525a5BcE776dD83769e9F9b5B4dD4193", + "commit_store": "0x2B721632693A8BbABa3bA5F125C8cD33D66F28F7", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Polygon Mainnet": { + "off_ramp": "0x9714098CDdAc380D4443293C55B6CBf6D6bbDbEb", + "commit_store": "0x4338f204C7698eE678d6c44117503f812ca1FA69", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + } + } + }, + "Kroma Mainnet": { + "is_native_fee_token": true, + "fee_token": "0x4200000000000000000000000000000000000001", + "arm": "0xB558b375D1D8a1aE2c3d5bBe43634BcF4d0d108c", + "router": "0xE93E8B0d1b1CEB44350C8758ed1E2799CCee31aB", + "price_registry": "0x8155B4710e7bbC90924E957104F94Afd4f95Eca2", + "wrapped_native": "0x4200000000000000000000000000000000000001", + "src_contracts": { + "WeMix Mainnet": { + "on_ramp": "0x3C5Ab46fA1dB1dECD854224654313a69bf9fcAD3", + "deployed_at": 0 + } + }, + "dest_contracts": { + "WeMix Mainnet": { + "off_ramp": "0x2B555774B3D1dcbcd76efb7751F3c5FbCFABC5C4", + "commit_store": "0x213124614aAf31eBCE7c612A12aac5f8aAD77DE4", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + } + } + }, + "Metis Andromeda": { + "is_native_fee_token": true, + "fee_token": "0x75cb093E4D61d2A2e65D8e0BBb01DE8d89b53481", + "arm": "0xC4BFAc3D31C524A4958c5d5d1e68394d8DEbbE69", + "router": "0x7b9FB8717D306e2e08ce2e1Efa81F026bf9AD13c", + "price_registry": "0xe1A7e2f9E88a72aF3E4790f33FfcDEa43d5eCC7B", + "wrapped_native": "0x75cb093E4D61d2A2e65D8e0BBb01DE8d89b53481", + "src_contracts": { + "Arbitrum Mainnet": { + "on_ramp": "0x87353b87A373E1551D27EDacDaC1644741c6499F", + "deployed_at": 0 + }, + "Ethereum Mainnet": { + "on_ramp": "0xE43f9eD3146d76E627C2504E5140005027992De6", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Arbitrum Mainnet": { + "off_ramp": "0x2cc33de75dAFDb3F8F4f24244a9C420374e2C001", + "commit_store": "0x67fE38dB73be154a1f1a63221F898B9d5EE4eF63", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Ethereum Mainnet": { + "off_ramp": "0xc2B1A8c931582D041ba5fF30AEB9fA828B30754d", + "commit_store": "0x90073Ea7A1Ee4Fe5d638B4216Bc60479Eba52001", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + } + } + }, + "Mode Mainnet": { + "is_native_fee_token": true, + "fee_token": "0x4200000000000000000000000000000000000006", + "arm": "0x77EAF440c5d24e25D1834CBBF623bFd83b8b5dA1", + "router": "0x24C40f13E77De2aFf37c280BA06c333531589bf1", + "price_registry": "0xffDEc5d752dd1fa1f56C236183ACB022e5D9d79e", + "wrapped_native": "0x4200000000000000000000000000000000000006", + "src_contracts": { + "Arbitrum Mainnet": { + "on_ramp": "0x65Ad802d80aD6a96C5a4bc9e57E16099de99Dc7F", + "deployed_at": 0 + }, + "BSC Mainnet": { + "on_ramp": "0x8C5149ff7Cfd99dd561caE9B7abFAA0Ef79eAbeC", + "deployed_at": 0 + }, + "Base Mainnet": { + "on_ramp": "0x71dB32eF442c29d8cbf72a9AFcb1Ef12B35b0BF4", + "deployed_at": 0 + }, + "Ethereum Mainnet": { + "on_ramp": "0xbD5F9C193a7fEF5D578C55Ddfe4d08d6BCc15648", + "deployed_at": 0 }, "Optimism Mainnet": { - "is_native_fee_token": true, - "fee_token": "0x350a791Bfc2C21F9Ed5d10980Dad2e2638ffa7f6", - "bridge_tokens": [], - "bridge_tokens_pools": [], - "arm": "0x8C7C2C3362a42308BB5c368677Ad321D11693b81", - "router": "0x3206695CaE29952f4b0c22a169725a865bc8Ce0f", - "price_registry": "0xb52545aECE8C73A97E52a146757EC15b90Ed8488", - "wrapped_native": "0x4200000000000000000000000000000000000006", - "src_contracts": { - "Arbitrum Mainnet": { - "on_ramp": "0x0C9BE7Cfd12c735E5aaE047C1dCB845d54E518C3", - "deployed_at": 11111111 - }, - "Avalanche Mainnet": { - "on_ramp": "0xD0D3E757bFBce7ae1881DDD7F6d798DDcE588445", - "deployed_at": 11111111 - }, - "Base Mainnet": { - "on_ramp": "0x0b1760A8112183303c5526C6b24569fd3A274f3B", - "deployed_at": 11111111 - }, - "BSC Mainnet": { - "on_ramp": "0xa3c9544B82846C45BE37593d5d9ACffbE61BF3A6", - "deployed_at": 11111111 - }, - "Ethereum Mainnet": { - "on_ramp": "0x55183Db1d2aE0b63e4c92A64bEF2CBfc2032B127", - "deployed_at": 11111111 - }, - "Polygon Mainnet": { - "on_ramp": "0x6B57145e322c877E7D91Ed8E31266eB5c02F7EfC", - "deployed_at": 11111111 - }, - "WeMix Mainnet": { - "on_ramp": "0x82e9f4C5ec4a84E310d60D462a12042E5cbA0954", - "deployed_at": 11111111 - } - }, - "dest_contracts": { - "Arbitrum Mainnet": { - "off_ramp": "0x0C9BE7Cfd12c735E5aaE047C1dCB845d54E518C3", - "commit_store": "0x55028780918330FD00a34a61D9a7Efd3f43ca845", - "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" - }, - "Avalanche Mainnet": { - "off_ramp": "0x8dc6490A6204dF846BaBE809cB695ba17Df1F9B1", - "commit_store": "0xA190660787B6B183Dd82B243eA10e609327c7308", - "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" - }, - "Base Mainnet": { - "off_ramp": "0xBAE6560eCa9B77Cb047158C783e36F7735C86037", - "commit_store": "0x6168aDF58e1Ad446BaD45c6275Bef60Ef4FFBAb8", - "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" - }, - "BSC Mainnet": { - "off_ramp": "0xE14501F2838F2fA1Ceb52E78ABdA289EcE1705EA", - "commit_store": "0xa8DD25B29787527Df283211C24Ac72B17150A696", - "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" - }, - "Ethereum Mainnet": { - "off_ramp": "0xd2D98Be6a1C241e86C807e51cED6ABb51d044203", - "commit_store": "0x4d75A5cE454b264b187BeE9e189aF1564a68408D", - "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" - }, - "Polygon Mainnet": { - "off_ramp": "0x7c6221880A1D62506b1A08Dab3Bf695A49AcDD22", - "commit_store": "0x0684076EE3595221861C50cDb9Cb66402Ec11Cb9", - "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" - }, - "WeMix Mainnet": { - "off_ramp": "0x3e5B3b7559D39563a74434157b31781322dA712D", - "commit_store": "0x7954372FF6f80908e5A2dC2a19d796A1005f91D2", - "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" - } - } + "on_ramp": "0x659303e8d4306D3ea8676FB034d56FB6f37E19d9", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Arbitrum Mainnet": { + "off_ramp": "0x8d3E1b15ebC96cec1ffc092cEcAeA6c1DD00aF9b", + "commit_store": "0x1f1DEa0210aE346A20E270a1C3355d99b0B949D2", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "BSC Mainnet": { + "off_ramp": "0x7a57670Fa0Cf1Bc2665a1Ae0f5031b9f5a43dD3a", + "commit_store": "0x18ffb74D94175d00D8bB67B70737dE2cE45eed07", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Base Mainnet": { + "off_ramp": "0xEfa90cE6289A2777cd5B8fb991B2D0Be44cA5067", + "commit_store": "0xACa5f0942Bb7fF297A7c25E8364373702D81bb3f", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Ethereum Mainnet": { + "off_ramp": "0xdF8f09AB4DfB49dEC8a0B8b7f1B7F4134252D3e9", + "commit_store": "0x8Ae635d264f20f1dbC0dea03712C194AdbeF50D1", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Optimism Mainnet": { + "off_ramp": "0xE4D6AAF678b986D3E6B7A85FA33d0519716a5525", + "commit_store": "0xBF80E30c8c013Ec0d05e2a959CF8000407C813EC", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + } + } + }, + "Optimism Mainnet": { + "is_native_fee_token": true, + "fee_token": "0x4200000000000000000000000000000000000006", + "arm": "0x1c51b6D5BFcFB7ee82C80949DFD146dB157a7E49", + "router": "0x3206695CaE29952f4b0c22a169725a865bc8Ce0f", + "price_registry": "0x9270AAA75F4B9038f4c25fEc665B02a150a90361", + "wrapped_native": "0x4200000000000000000000000000000000000006", + "src_contracts": { + "Arbitrum Mainnet": { + "on_ramp": "0x0C9BE7Cfd12c735E5aaE047C1dCB845d54E518C3", + "deployed_at": 0 + }, + "Avalanche Mainnet": { + "on_ramp": "0xD0D3E757bFBce7ae1881DDD7F6d798DDcE588445", + "deployed_at": 0 + }, + "BSC Mainnet": { + "on_ramp": "0xa3c9544B82846C45BE37593d5d9ACffbE61BF3A6", + "deployed_at": 0 + }, + "Base Mainnet": { + "on_ramp": "0x0b1760A8112183303c5526C6b24569fd3A274f3B", + "deployed_at": 0 + }, + "Ethereum Mainnet": { + "on_ramp": "0x55183Db1d2aE0b63e4c92A64bEF2CBfc2032B127", + "deployed_at": 0 + }, + "Gnosis Mainnet": { + "on_ramp": "0x14aA3CC03583aA557DBca4ce72288Cc5F37DDE34", + "deployed_at": 0 + }, + "Mode Mainnet": { + "on_ramp": "0x034eA573B049210315110f7eA11c9618E32F08Ae", + "deployed_at": 0 + }, + "Polygon Mainnet": { + "on_ramp": "0x6B57145e322c877E7D91Ed8E31266eB5c02F7EfC", + "deployed_at": 0 + }, + "WeMix Mainnet": { + "on_ramp": "0x82e9f4C5ec4a84E310d60D462a12042E5cbA0954", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Arbitrum Mainnet": { + "off_ramp": "0xaC8C94242aa8234Bf89682aBcDDf805AE8cff61D", + "commit_store": "0x55028780918330FD00a34a61D9a7Efd3f43ca845", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Avalanche Mainnet": { + "off_ramp": "0x8dc6490A6204dF846BaBE809cB695ba17Df1F9B1", + "commit_store": "0xA190660787B6B183Dd82B243eA10e609327c7308", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "BSC Mainnet": { + "off_ramp": "0xE14501F2838F2fA1Ceb52E78ABdA289EcE1705EA", + "commit_store": "0xa8DD25B29787527Df283211C24Ac72B17150A696", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Base Mainnet": { + "off_ramp": "0xBAE6560eCa9B77Cb047158C783e36F7735C86037", + "commit_store": "0x6168aDF58e1Ad446BaD45c6275Bef60Ef4FFBAb8", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Ethereum Mainnet": { + "off_ramp": "0xd2D98Be6a1C241e86C807e51cED6ABb51d044203", + "commit_store": "0x4d75A5cE454b264b187BeE9e189aF1564a68408D", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Gnosis Mainnet": { + "off_ramp": "0x4358640A2419119DBe0933b5F2c288c3EB2c082C", + "commit_store": "0x44d1a05ef6e54a3CB35a1497303bA272f15f45ed", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Mode Mainnet": { + "off_ramp": "0xDf9717d724828537902Fb0c3B7C56c641463Fa38", + "commit_store": "0x8aEFF283381914E07Fc371601D59648ab6D2C0B1", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" }, "Polygon Mainnet": { - "is_native_fee_token": true, - "fee_token": "0xb0897686c545045aFc77CF20eC7A532E3120E0F1", - "bridge_tokens": [], - "bridge_tokens_pools": [], - "arm": "0xD7AcF65dA1E1f34b663aB199a474F209bF2b0523", - "router": "0x849c5ED5a80F5B408Dd4969b78c2C8fdf0565Bfe", - "price_registry": "0x30D873664Ba766C983984C7AF9A921ccE36D34e1", - "wrapped_native": "0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270", - "src_contracts": { - "Arbitrum Mainnet": { - "on_ramp": "0xD16D025330Edb91259EEA8ed499daCd39087c295", - "deployed_at": 11111111 - }, - "Avalanche Mainnet": { - "on_ramp": "0x5FA30697e90eB30954895c45b028F7C0dDD39b12", - "deployed_at": 11111111 - }, - "Base Mainnet": { - "on_ramp": "0x20B028A2e0F6CCe3A11f3CE5F2B8986F932e89b4", - "deployed_at": 11111111 - }, - "BSC Mainnet": { - "on_ramp": "0xF5b5A2fC11BF46B1669C3B19d98B19C79109Dca9", - "deployed_at": 11111111 - }, - "Ethereum Mainnet": { - "on_ramp": "0xFd77c53AA4eF0E3C01f5Ac012BF7Cc7A3ECf5168", - "deployed_at": 11111111 - }, - "Optimism Mainnet": { - "on_ramp": "0x3111cfbF5e84B5D9BD952dd8e957f4Ca75f728Cf", - "deployed_at": 11111111 - }, - "WeMix Mainnet": { - "on_ramp": "0x5060eF647a1F66BE6eE27FAe3046faf8D53CeB2d", - "deployed_at": 11111111 - } - }, - "dest_contracts": { - "Arbitrum Mainnet": { - "off_ramp": "0xa8a9eDa2867c2E0CE0d5ECe273961F1EcC3CC25B", - "commit_store": "0xbD4480658dca8496a65046dfD1BDD44EF897Bdb5", - "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" - }, - "Avalanche Mainnet": { - "off_ramp": "0xB9e3680639c9F0C4e0b02FD81C445094426244Ae", - "commit_store": "0x8c63d4e67f7c4af6FEd2f56A34fB4e01CB807CFF", - "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" - }, - "Base Mainnet": { - "off_ramp": "0xD0FA7DE2D18A0c59D3fD7dfC7aB4e913C6Aa7b68", - "commit_store": "0xF88053B9DAC8Dd3039a4eFa8639159aaa3F2D4Cb", - "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" - }, - "BSC Mainnet": { - "off_ramp": "0x592773924741F0Da889a0dfdab71171Dd11E054C", - "commit_store": "0xEC4d35E1A85f770f4D93BA43a462c9d87Ef7017e", - "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" - }, - "Ethereum Mainnet": { - "off_ramp": "0x45320085fF051361D301eC1044318213A5387A15", - "commit_store": "0x4Dc771B5ef21ef60c33e2987E092345f2b63aE08", - "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" - }, - "Optimism Mainnet": { - "off_ramp": "0xBa754ecd3CFA7E9093F688EAc3860cf9D07Fc0AC", - "commit_store": "0x04C0D5302E3D8Ca0A0019141a52a23B59cdb70e4", - "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" - }, - "WeMix Mainnet": { - "off_ramp": "0xd7c877ea02310Cce9278D9A048Aa1Bb9aF72F00d", - "commit_store": "0x92A1C927E8E10Ab6A40E5A5154e2300D278d1a67", - "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" - } - } + "off_ramp": "0x7c6221880A1D62506b1A08Dab3Bf695A49AcDD22", + "commit_store": "0x0684076EE3595221861C50cDb9Cb66402Ec11Cb9", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" }, "WeMix Mainnet": { - "is_native_fee_token": true, - "fee_token": "0x80f1FcdC96B55e459BF52b998aBBE2c364935d69", - "bridge_tokens": [], - "bridge_tokens_pools": [], - "arm": "0x07aaC8B69A62dB5bd3d244091916EbF2fac17b76", - "router": "0x7798b795Fde864f4Cd1b124a38Ba9619B7F8A442", - "price_registry": "0x252863688762aD86868D3d3076233Eacd80c7055", - "wrapped_native": "0x7D72b22a74A216Af4a002a1095C8C707d6eC1C5f", - "src_contracts": { - "Arbitrum Mainnet": { - "on_ramp": "0x9aBfd6f4C865610692AB6fb1Be862575809fFabf", - "deployed_at": 11111111 - }, - "Avalanche Mainnet": { - "on_ramp": "0xbE0Cfae74677F8dd16a246a3a5c8cbB1973118f4", - "deployed_at": 11111111 - }, - "BSC Mainnet": { - "on_ramp": "0x56657ec4D15C71f7F3C17ba2b21C853A24Dc5381", - "deployed_at": 11111111 - }, - "Optimism Mainnet": { - "on_ramp": "0x70f3b0FD7e6a4B9B623e9AB859604A9EE03e48BD", - "deployed_at": 11111111 - }, - "Polygon Mainnet": { - "on_ramp": "0x777058C1e1dcE4eB8001F38631a1cd9450816e5a", - "deployed_at": 11111111 - }, - "Ethereum Mainnet": { - "on_ramp": "0x190bcE84CF2d500B878966F4Cf98a50d78f2675E", - "deployed_at": 11111111 - }, - "Kroma Mainnet": { - "on_ramp": "0x47E9AE0A815C94836202E696748A5d5476aD8735", - "deployed_at": 11111111 - } - }, - "dest_contracts": { - "Arbitrum Mainnet": { - "off_ramp": "0x2ba68a395B72a6E3498D312efeD755ed2f3CF223", - "commit_store": "0xdAeC234DA83F68707Bb8AcB2ee6a01a5FD4c2391", - "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" - }, - "Avalanche Mainnet": { - "off_ramp": "0xFac907F9a1087B846Faa75A14C5d34A8639233d8", - "commit_store": "0xF2812063446c7deD2CA306c67A68364BdDcbEfc5", - "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" - }, - "BSC Mainnet": { - "off_ramp": "0x6ec9ca4Cba62cA17c55F05ad2000B46192f02035", - "commit_store": "0x84534BE763366a69710E119c100832955795B34B", - "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" - }, - "Optimism Mainnet": { - "off_ramp": "0x87220D01DF0fF27149B47227897074653788fd23", - "commit_store": "0xF8dD2be2C6FA43e48A17146380CbEBBB4291807b", - "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" - }, - "Polygon Mainnet": { - "off_ramp": "0x8f0229804513A9Bc00c1308414AB279Dbc718ae1", - "commit_store": "0x3A85D1b8641d83a87957C6ECF1b62151213e0842", - "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" - }, - "Ethereum Mainnet": { - "off_ramp": "0xF92Fa796F5307b029c65CA26f322a6D86f211194", - "commit_store": "0xbeC110FF43D52be2066B06525304A9924E16b73b", - "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" - }, - "Kroma Mainnet": { - "off_ramp": "0xF886d8DC64E544af4835cbf91e5678A54D95B80e", - "commit_store": "0x8794C9534658fdCC44f2FF6645Bf31cf9F6d2d5D", - "receiver_dapp": "0xB509c046e1182c7B36d2D9733554BC268716803C" - } - } + "off_ramp": "0x3e5B3b7559D39563a74434157b31781322dA712D", + "commit_store": "0x7954372FF6f80908e5A2dC2a19d796A1005f91D2", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + } + } + }, + "Polygon Mainnet": { + "is_native_fee_token": true, + "fee_token": "0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270", + "arm": "0x569a295a09634Ac9414c3efe4E8931986d68F937", + "router": "0x849c5ED5a80F5B408Dd4969b78c2C8fdf0565Bfe", + "price_registry": "0x30D873664Ba766C983984C7AF9A921ccE36D34e1", + "wrapped_native": "0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270", + "src_contracts": { + "Arbitrum Mainnet": { + "on_ramp": "0xD16D025330Edb91259EEA8ed499daCd39087c295", + "deployed_at": 0 + }, + "Avalanche Mainnet": { + "on_ramp": "0x5FA30697e90eB30954895c45b028F7C0dDD39b12", + "deployed_at": 0 + }, + "BSC Mainnet": { + "on_ramp": "0xF5b5A2fC11BF46B1669C3B19d98B19C79109Dca9", + "deployed_at": 0 + }, + "Base Mainnet": { + "on_ramp": "0x20B028A2e0F6CCe3A11f3CE5F2B8986F932e89b4", + "deployed_at": 0 + }, + "Ethereum Mainnet": { + "on_ramp": "0xFd77c53AA4eF0E3C01f5Ac012BF7Cc7A3ECf5168", + "deployed_at": 0 + }, + "Gnosis Mainnet": { + "on_ramp": "0x4616621704C81801A56D29c961F9395ee153d46C", + "deployed_at": 0 + }, + "Optimism Mainnet": { + "on_ramp": "0x3111cfbF5e84B5D9BD952dd8e957f4Ca75f728Cf", + "deployed_at": 0 + }, + "WeMix Mainnet": { + "on_ramp": "0x5060eF647a1F66BE6eE27FAe3046faf8D53CeB2d", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Arbitrum Mainnet": { + "off_ramp": "0xa8a9eDa2867c2E0CE0d5ECe273961F1EcC3CC25B", + "commit_store": "0xbD4480658dca8496a65046dfD1BDD44EF897Bdb5", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Avalanche Mainnet": { + "off_ramp": "0xB9e3680639c9F0C4e0b02FD81C445094426244Ae", + "commit_store": "0x8c63d4e67f7c4af6FEd2f56A34fB4e01CB807CFF", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "BSC Mainnet": { + "off_ramp": "0x592773924741F0Da889a0dfdab71171Dd11E054C", + "commit_store": "0xEC4d35E1A85f770f4D93BA43a462c9d87Ef7017e", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Base Mainnet": { + "off_ramp": "0xD0FA7DE2D18A0c59D3fD7dfC7aB4e913C6Aa7b68", + "commit_store": "0xF88053B9DAC8Dd3039a4eFa8639159aaa3F2D4Cb", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Ethereum Mainnet": { + "off_ramp": "0x45320085fF051361D301eC1044318213A5387A15", + "commit_store": "0x4Dc771B5ef21ef60c33e2987E092345f2b63aE08", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Gnosis Mainnet": { + "off_ramp": "0x0A04eC196454825d361886cf4FA113A948164Ef8", + "commit_store": "0x74b72633b63A8f4374a12DB6F609305BC5a1b2d5", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Optimism Mainnet": { + "off_ramp": "0xBa754ecd3CFA7E9093F688EAc3860cf9D07Fc0AC", + "commit_store": "0x04C0D5302E3D8Ca0A0019141a52a23B59cdb70e4", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "WeMix Mainnet": { + "off_ramp": "0xd7c877ea02310Cce9278D9A048Aa1Bb9aF72F00d", + "commit_store": "0x92A1C927E8E10Ab6A40E5A5154e2300D278d1a67", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + } + } + }, + "WeMix Mainnet": { + "is_native_fee_token": true, + "fee_token": "0x7D72b22a74A216Af4a002a1095C8C707d6eC1C5f", + "arm": "0xdBa0afF04bf63Ba6b75DEC94d1A934a367CAA782", + "router": "0x7798b795Fde864f4Cd1b124a38Ba9619B7F8A442", + "price_registry": "0x252863688762aD86868D3d3076233Eacd80c7055", + "wrapped_native": "0x7D72b22a74A216Af4a002a1095C8C707d6eC1C5f", + "src_contracts": { + "Arbitrum Mainnet": { + "on_ramp": "0x9aBfd6f4C865610692AB6fb1Be862575809fFabf", + "deployed_at": 0 + }, + "Avalanche Mainnet": { + "on_ramp": "0xbE0Cfae74677F8dd16a246a3a5c8cbB1973118f4", + "deployed_at": 0 + }, + "BSC Mainnet": { + "on_ramp": "0x56657ec4D15C71f7F3C17ba2b21C853A24Dc5381", + "deployed_at": 0 + }, + "Ethereum Mainnet": { + "on_ramp": "0x190bcE84CF2d500B878966F4Cf98a50d78f2675E", + "deployed_at": 0 + }, + "Kroma Mainnet": { + "on_ramp": "0x47E9AE0A815C94836202E696748A5d5476aD8735", + "deployed_at": 0 + }, + "Optimism Mainnet": { + "on_ramp": "0x70f3b0FD7e6a4B9B623e9AB859604A9EE03e48BD", + "deployed_at": 0 + }, + "Polygon Mainnet": { + "on_ramp": "0x777058C1e1dcE4eB8001F38631a1cd9450816e5a", + "deployed_at": 0 } + }, + "dest_contracts": { + "Arbitrum Mainnet": { + "off_ramp": "0x2ba68a395B72a6E3498D312efeD755ed2f3CF223", + "commit_store": "0xdAeC234DA83F68707Bb8AcB2ee6a01a5FD4c2391", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Avalanche Mainnet": { + "off_ramp": "0xFac907F9a1087B846Faa75A14C5d34A8639233d8", + "commit_store": "0xF2812063446c7deD2CA306c67A68364BdDcbEfc5", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "BSC Mainnet": { + "off_ramp": "0x6ec9ca4Cba62cA17c55F05ad2000B46192f02035", + "commit_store": "0x84534BE763366a69710E119c100832955795B34B", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Ethereum Mainnet": { + "off_ramp": "0xF92Fa796F5307b029c65CA26f322a6D86f211194", + "commit_store": "0xbeC110FF43D52be2066B06525304A9924E16b73b", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Kroma Mainnet": { + "off_ramp": "0xF886d8DC64E544af4835cbf91e5678A54D95B80e", + "commit_store": "0x8794C9534658fdCC44f2FF6645Bf31cf9F6d2d5D", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Optimism Mainnet": { + "off_ramp": "0x87220D01DF0fF27149B47227897074653788fd23", + "commit_store": "0xF8dD2be2C6FA43e48A17146380CbEBBB4291807b", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Polygon Mainnet": { + "off_ramp": "0x8f0229804513A9Bc00c1308414AB279Dbc718ae1", + "commit_store": "0x3A85D1b8641d83a87957C6ECF1b62151213e0842", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + } + } + }, + "ZKSync Mainnet": { + "is_native_fee_token": true, + "fee_token": "0x5AEa5775959fBC2557Cc8789bC1bf90A239D9a91", + "arm": "0x4e2438b1395a462E2e8D164b5f3c65d080919449", + "router": "0x748Fd769d81F5D94752bf8B0875E9301d0ba71bB", + "price_registry": "0xa0C6E00a9Fa10A04989c237dF6dfDCe2AaceE4A3", + "wrapped_native": "0x5AEa5775959fBC2557Cc8789bC1bf90A239D9a91", + "src_contracts": { + "Arbitrum Mainnet": { + "on_ramp": "0x9033687a0f03012e015f8f8f2a59da57531d2B43", + "deployed_at": 0 + }, + "Ethereum Mainnet": { + "on_ramp": "0x3B80Fe300c9A611abA0496e2543B66Ff7bD4B9e9", + "deployed_at": 0 + } + }, + "dest_contracts": { + "Arbitrum Mainnet": { + "off_ramp": "0xF0a08aC528668D4fe8C4cF235a8B82cbf242Fa9d", + "commit_store": "0x5a3C9b21b03E4eBcccb57D296e7ff54102F04424", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + }, + "Ethereum Mainnet": { + "off_ramp": "0x7c887B97F9Bba9355EC10e2bA949AdB491Ef44Fd", + "commit_store": "0xA42bf0c8794FA8853Ec0F1B24a489972e8CF4C30", + "receiver_dapp": "0xb509c046e1182c7b36d2d9733554bc268716803c" + } + } } + } } """ @@ -650,15 +1081,15 @@ TTL = '8h' [CCIP.Env.Network] selected_networks = [ - 'ETHEREUM_MAINNET', 'ARBITRUM_MAINNET', + 'AVALANCHE_MAINNET', + 'BSC_MAINNET', 'BASE_MAINNET', - 'WEMIX_MAINNET', + 'ETHEREUM_MAINNET', + 'KROMA_MAINNET', 'OPTIMISM_MAINNET', 'POLYGON_MAINNET', - 'AVALANCHE_MAINNET', - 'BSC_MAINNET', - 'KROMA_MAINNET' + 'WEMIX_MAINNET', ] [CCIP.Groups.load] @@ -694,7 +1125,7 @@ NetworkPairs = [ ] BiDirectionalLane = true -PhaseTimeout = '20m' +PhaseTimeout = '30m' ExistingDeployment = true [CCIP.Groups.load.TokenConfig] @@ -704,7 +1135,7 @@ NoOfTokensPerChain = 1 RequestPerUnitTime = [1] TimeUnit = '1h' TestDuration = '5h' -TestRunName = 'mainnet-2.7-ccip1.2' +TestRunName = 'Soak_test_mainnet' FailOnFirstErrorInLoad = true SkipRequestIfAnotherRequestTriggeredWithin = '40m' @@ -718,7 +1149,7 @@ AmountPerToken = 1 [CCIP.Groups.smoke] # these are all the valid network pairs NetworkPairs = [ - 'ETHEREUM_MAINNET,OPTIMISM_MAINNET', + 'ETHEREUM_MAINNET,OPTIMISM_MAINNET', 'ETHEREUM_MAINNET,AVALANCHE_MAINNET', 'ETHEREUM_MAINNET,POLYGON_MAINNET', 'ETHEREUM_MAINNET,BSC_MAINNET', From f1adcc24ed2f369deb23fb7348c0ff494d4f7ddc Mon Sep 17 00:00:00 2001 From: Balamurali Gopalswami <167726375+b-gopalswami@users.noreply.github.com> Date: Wed, 18 Sep 2024 13:35:00 -0400 Subject: [PATCH 104/115] CCIP-3420: Fix IsRequestTriggeredWithinTimeframe (#1445) ## Motivation The prior approach to find if there is traffic in a lane was not detecting the transactions properly. It could be due to the `CCIPSendRequestedWatcher` captures the event after it is initiated not any transaction before that. ## Solution The revised approach is to use the FilterCCIPSendRequested by a past derived block number and see if there is any traffic. The block number is derived by this formula: `filterFromBlock = latestBlockNumber - (SkipRequestIfAnotherRequestTriggeredWithin/avgBlockTime)` By this approach, we will be able to find traffic better. https://smartcontract-it.atlassian.net/browse/CCIP-3420 --- .../ccip-tests/actions/ccip_helpers.go | 44 +++++++++++++++++++ .../ccip-tests/load/ccip_loadgen.go | 15 ++++++- .../ccip-tests/testconfig/ccip.go | 3 ++ 3 files changed, 61 insertions(+), 1 deletion(-) diff --git a/integration-tests/ccip-tests/actions/ccip_helpers.go b/integration-tests/ccip-tests/actions/ccip_helpers.go index f0af063ac6..2bbc77f1c2 100644 --- a/integration-tests/ccip-tests/actions/ccip_helpers.go +++ b/integration-tests/ccip-tests/actions/ccip_helpers.go @@ -1620,6 +1620,8 @@ func (sourceCCIP *SourceCCIPModule) AssertSendRequestedLogFinalized( return finalizedAt, finalizedBlockNum.Uint64(), nil } +// IsRequestTriggeredWithinTimeframe monitors for live events occurring within the specified timeframe. +// Live events refer to those that are triggered after subscribing to the CCIP Send Requested event. func (sourceCCIP *SourceCCIPModule) IsRequestTriggeredWithinTimeframe(timeframe *commonconfig.Duration) *time.Time { if timeframe == nil { return nil @@ -1644,6 +1646,48 @@ func (sourceCCIP *SourceCCIPModule) IsRequestTriggeredWithinTimeframe(timeframe return foundAt } +// IsPastRequestTriggeredWithinTimeframe determines the average block time and calculates the block numbers +// within the specified timeframe. It then uses FilterCCIPSendRequested to identify the past events. +func (sourceCCIP *SourceCCIPModule) IsPastRequestTriggeredWithinTimeframe(ctx context.Context, timeframe *commonconfig.Duration) (*time.Time, error) { + if timeframe == nil { + return nil, nil + } + //var foundAt *time.Time + latestBlock, err := sourceCCIP.Common.ChainClient.LatestBlockNumber(ctx) + if err != nil { + return nil, fmt.Errorf("error while getting latest source block number. Error: %w", err) + } + avgBlockTime, err := sourceCCIP.Common.ChainClient.AvgBlockTime(ctx) + if err != nil { + return nil, fmt.Errorf("error while getting average source block time. Error: %w", err) + } + filterFromBlock := latestBlock - uint64(timeframe.Duration()/avgBlockTime) + + onRampContract, err := evm_2_evm_onramp.NewEVM2EVMOnRamp(common.HexToAddress(sourceCCIP.OnRamp.EthAddress.Hex()), + sourceCCIP.Common.ChainClient.Backend()) + if err != nil { + return nil, fmt.Errorf("error while on ramp contract. Error: %w", err) + } + iterator, err := onRampContract.FilterCCIPSendRequested(&bind.FilterOpts{ + Start: filterFromBlock, + }) + if err != nil { + return nil, fmt.Errorf("error while filtering CCIP send requested starting block number: %d. Error: %w", filterFromBlock, err) + } + defer func() { + _ = iterator.Close() + }() + if iterator.Next() { + hdr, err := sourceCCIP.Common.ChainClient.HeaderByNumber(context.Background(), big.NewInt(int64(iterator.Event.Raw.BlockNumber))) + if err != nil { + return nil, fmt.Errorf("error getting header for block: %d, Error: %w", iterator.Event.Raw.BlockNumber, err) + } + return pointer.ToTime(hdr.Timestamp), nil + } + + return nil, nil +} + func (sourceCCIP *SourceCCIPModule) AssertEventCCIPSendRequested( lggr *zerolog.Logger, txHash string, diff --git a/integration-tests/ccip-tests/load/ccip_loadgen.go b/integration-tests/ccip-tests/load/ccip_loadgen.go index 9d24fd1dd0..d3af128309 100644 --- a/integration-tests/ccip-tests/load/ccip_loadgen.go +++ b/integration-tests/ccip-tests/load/ccip_loadgen.go @@ -10,6 +10,8 @@ import ( "testing" "time" + "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/testcontext" + "github.com/AlekSi/pointer" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" @@ -223,7 +225,18 @@ func (c *CCIPE2ELoad) CCIPMsg() (router.ClientEVM2AnyMessage, *testreporters.Req func (c *CCIPE2ELoad) Call(_ *wasp.Generator) *wasp.Response { res := &wasp.Response{} sourceCCIP := c.Lane.Source - recentRequestFoundAt := sourceCCIP.IsRequestTriggeredWithinTimeframe(c.SkipRequestIfAnotherRequestTriggeredWithin) + var recentRequestFoundAt *time.Time + var err error + // Use IsPastRequestTriggeredWithinTimeframe to check for any historical CCIP send request events + // within the specified timeframe for the first message. Subsequently, use the watcher method to monitor + // and detect any new events as they occur. + if c.CurrentMsgSerialNo.Load() == int64(1) { + recentRequestFoundAt, err = sourceCCIP.IsPastRequestTriggeredWithinTimeframe(testcontext.Get(c.t), c.SkipRequestIfAnotherRequestTriggeredWithin) + require.NoError(c.t, err, "error while filtering past requests") + } else { + recentRequestFoundAt = sourceCCIP.IsRequestTriggeredWithinTimeframe(c.SkipRequestIfAnotherRequestTriggeredWithin) + } + if recentRequestFoundAt != nil { c.Lane.Logger. Info(). diff --git a/integration-tests/ccip-tests/testconfig/ccip.go b/integration-tests/ccip-tests/testconfig/ccip.go index 1eff991403..1f4dfaac51 100644 --- a/integration-tests/ccip-tests/testconfig/ccip.go +++ b/integration-tests/ccip-tests/testconfig/ccip.go @@ -242,6 +242,9 @@ func (l *LoadProfile) Validate() error { if l.TestDuration == nil || l.TestDuration.Duration().Minutes() == 0 { return fmt.Errorf("test duration should be set") } + if l.SkipRequestIfAnotherRequestTriggeredWithin != nil && l.TimeUnit.Duration() < l.SkipRequestIfAnotherRequestTriggeredWithin.Duration() { + return fmt.Errorf("SkipRequestIfAnotherRequestTriggeredWithin should be set below the TimeUnit duration") + } return nil } From 70c85991f43962a0c8cc37c8089fc8836b61c744 Mon Sep 17 00:00:00 2001 From: amit-momin <108959691+amit-momin@users.noreply.github.com> Date: Thu, 22 Aug 2024 15:15:45 -0500 Subject: [PATCH 105/115] Gas limit estimation feature (#14041) * Added gas limit estimation feature to EVM gas estimators * Added changeset * Fixed linting * Added new failure tests * Fixed test * Fixed mock configs in ccip capabilities * Fixed configs * Fixed test * Refactored GetFee method * Added EstimatedGasBuffer and addressed feedback * Fixed linting * Fixed config doc and tests * Addressed feedback * Fixed typo * Repurposed LimitMultiplier to be used as a buffer for estimated gas * Updated mocks * Removed LimitMultiplier if gas estimation fails and updated config docs * Fixed Broadcaster test * Enabled uncapped gas limit estimation if provided fee limit is 0 * Updated estimate gas buffer to be a fixed value instead of using LimitMultiplier * Updated log message * Updated logs --------- Co-authored-by: Prashant Yadav <34992934+prashantkumar1982@users.noreply.github.com> --- .changeset/loud-windows-call.md | 5 + common/fee/models.go | 1 + common/txmgr/broadcaster.go | 7 +- .../evm/config/chain_scoped_gas_estimator.go | 4 + core/chains/evm/config/config.go | 1 + core/chains/evm/config/mocks/gas_estimator.go | 45 ++++ core/chains/evm/config/toml/config.go | 14 +- .../evm/config/toml/defaults/fallback.toml | 1 + core/chains/evm/gas/helpers_test.go | 5 + .../chains/evm/gas/mocks/evm_fee_estimator.go | 76 +++---- .../evm/gas/mocks/fee_estimator_client.go | 57 +++++ core/chains/evm/gas/models.go | 89 ++++++-- core/chains/evm/gas/models_test.go | 199 ++++++++++++++++-- core/chains/evm/txmgr/attempts.go | 6 +- core/chains/evm/txmgr/attempts_test.go | 2 +- core/chains/evm/txmgr/broadcaster_test.go | 81 ++++++- core/chains/evm/txmgr/confirmer_test.go | 10 +- core/chains/evm/txmgr/stuck_tx_detector.go | 4 +- .../evm/txmgr/stuck_tx_detector_test.go | 4 +- core/chains/evm/txmgr/test_helpers.go | 1 + core/config/docs/chains-evm.toml | 2 + core/internal/features/features_test.go | 4 +- core/services/chainlink/config_test.go | 2 + .../chainlink/testdata/config-full.toml | 1 + .../config-multi-chain-effective.toml | 3 + core/services/keeper/upkeep_executer_test.go | 2 +- .../ccipdata/commit_store_reader_test.go | 2 +- .../ccip/prices/exec_price_estimator.go | 2 +- .../ccip/prices/exec_price_estimator_test.go | 3 +- .../evmregistry/v21/gasprice/gasprice.go | 2 +- .../evmregistry/v21/gasprice/gasprice_test.go | 6 +- core/services/relay/evm/chain_writer.go | 2 +- core/services/relay/evm/chain_writer_test.go | 10 +- core/web/evm_transfer_controller.go | 6 +- core/web/resolver/testdata/config-full.toml | 1 + .../config-multi-chain-effective.toml | 3 + docs/CONFIG.md | 68 ++++++ .../disk-based-logging-disabled.txtar | 1 + .../validate/disk-based-logging-no-dir.txtar | 1 + .../node/validate/disk-based-logging.txtar | 1 + testdata/scripts/node/validate/invalid.txtar | 1 + testdata/scripts/node/validate/valid.txtar | 1 + 42 files changed, 620 insertions(+), 116 deletions(-) create mode 100644 .changeset/loud-windows-call.md diff --git a/.changeset/loud-windows-call.md b/.changeset/loud-windows-call.md new file mode 100644 index 0000000000..e05bed706a --- /dev/null +++ b/.changeset/loud-windows-call.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +Added gas limit estimation feature to EVM gas estimators #added diff --git a/common/fee/models.go b/common/fee/models.go index 0568a2f143..0496d3929c 100644 --- a/common/fee/models.go +++ b/common/fee/models.go @@ -14,6 +14,7 @@ var ( ErrBumpFeeExceedsLimit = errors.New("fee bump exceeds limit") ErrBump = errors.New("fee bump failed") ErrConnectivity = errors.New("transaction propagation issue: transactions are not being mined") + ErrFeeLimitTooLow = errors.New("provided fee limit too low") ) func IsBumpErr(err error) bool { diff --git a/common/txmgr/broadcaster.go b/common/txmgr/broadcaster.go index be3d3ca2f6..1606f58ce0 100644 --- a/common/txmgr/broadcaster.go +++ b/common/txmgr/broadcaster.go @@ -20,6 +20,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/common/client" + commonfee "github.com/smartcontractkit/chainlink/v2/common/fee" feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types" txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types" "github.com/smartcontractkit/chainlink/v2/common/types" @@ -434,7 +435,11 @@ func (eb *Broadcaster[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) hand } attempt, _, _, retryable, err := eb.NewTxAttempt(ctx, *etx, eb.lggr) - if err != nil { + // Mark transaction as fatal if provided gas limit is set too low + if errors.Is(err, commonfee.ErrFeeLimitTooLow) { + etx.Error = null.StringFrom(commonfee.ErrFeeLimitTooLow.Error()) + return eb.saveFatallyErroredTransaction(eb.lggr, etx), false + } else if err != nil { return fmt.Errorf("processUnstartedTxs failed on NewAttempt: %w", err), retryable } diff --git a/core/chains/evm/config/chain_scoped_gas_estimator.go b/core/chains/evm/config/chain_scoped_gas_estimator.go index 689d5e38b8..4f2d8872d8 100644 --- a/core/chains/evm/config/chain_scoped_gas_estimator.go +++ b/core/chains/evm/config/chain_scoped_gas_estimator.go @@ -108,6 +108,10 @@ func (g *gasEstimatorConfig) LimitJobType() LimitJobType { return &limitJobTypeConfig{c: g.c.LimitJobType} } +func (g *gasEstimatorConfig) EstimateGasLimit() bool { + return *g.c.EstimateGasLimit +} + type limitJobTypeConfig struct { c toml.GasLimitJobType } diff --git a/core/chains/evm/config/config.go b/core/chains/evm/config/config.go index 3ccdfeea8b..9517c68716 100644 --- a/core/chains/evm/config/config.go +++ b/core/chains/evm/config/config.go @@ -136,6 +136,7 @@ type GasEstimator interface { PriceMin() *assets.Wei Mode() string PriceMaxKey(gethcommon.Address) *assets.Wei + EstimateGasLimit() bool } type LimitJobType interface { diff --git a/core/chains/evm/config/mocks/gas_estimator.go b/core/chains/evm/config/mocks/gas_estimator.go index b8e813e806..40c10757b8 100644 --- a/core/chains/evm/config/mocks/gas_estimator.go +++ b/core/chains/evm/config/mocks/gas_estimator.go @@ -298,6 +298,51 @@ func (_c *GasEstimator_EIP1559DynamicFees_Call) RunAndReturn(run func() bool) *G return _c } +// EstimateGasLimit provides a mock function with given fields: +func (_m *GasEstimator) EstimateGasLimit() bool { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for EstimateGasLimit") + } + + var r0 bool + if rf, ok := ret.Get(0).(func() bool); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(bool) + } + + return r0 +} + +// GasEstimator_EstimateGasLimit_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'EstimateGasLimit' +type GasEstimator_EstimateGasLimit_Call struct { + *mock.Call +} + +// EstimateGasLimit is a helper method to define mock.On call +func (_e *GasEstimator_Expecter) EstimateGasLimit() *GasEstimator_EstimateGasLimit_Call { + return &GasEstimator_EstimateGasLimit_Call{Call: _e.mock.On("EstimateGasLimit")} +} + +func (_c *GasEstimator_EstimateGasLimit_Call) Run(run func()) *GasEstimator_EstimateGasLimit_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *GasEstimator_EstimateGasLimit_Call) Return(_a0 bool) *GasEstimator_EstimateGasLimit_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *GasEstimator_EstimateGasLimit_Call) RunAndReturn(run func() bool) *GasEstimator_EstimateGasLimit_Call { + _c.Call.Return(run) + return _c +} + // FeeCapDefault provides a mock function with given fields: func (_m *GasEstimator) FeeCapDefault() *assets.Wei { ret := _m.Called() diff --git a/core/chains/evm/config/toml/config.go b/core/chains/evm/config/toml/config.go index ac7841ac49..99e61a394b 100644 --- a/core/chains/evm/config/toml/config.go +++ b/core/chains/evm/config/toml/config.go @@ -549,11 +549,12 @@ type GasEstimator struct { PriceMax *assets.Wei PriceMin *assets.Wei - LimitDefault *uint64 - LimitMax *uint64 - LimitMultiplier *decimal.Decimal - LimitTransfer *uint64 - LimitJobType GasLimitJobType `toml:",omitempty"` + LimitDefault *uint64 + LimitMax *uint64 + LimitMultiplier *decimal.Decimal + LimitTransfer *uint64 + LimitJobType GasLimitJobType `toml:",omitempty"` + EstimateGasLimit *bool BumpMin *assets.Wei BumpPercent *uint16 @@ -641,6 +642,9 @@ func (e *GasEstimator) setFrom(f *GasEstimator) { if v := f.LimitTransfer; v != nil { e.LimitTransfer = v } + if v := f.EstimateGasLimit; v != nil { + e.EstimateGasLimit = v + } if v := f.PriceDefault; v != nil { e.PriceDefault = v } diff --git a/core/chains/evm/config/toml/defaults/fallback.toml b/core/chains/evm/config/toml/defaults/fallback.toml index e3136323f6..71da1df208 100644 --- a/core/chains/evm/config/toml/defaults/fallback.toml +++ b/core/chains/evm/config/toml/defaults/fallback.toml @@ -48,6 +48,7 @@ EIP1559DynamicFees = false FeeCapDefault = '100 gwei' TipCapDefault = '1' TipCapMin = '1' +EstimateGasLimit = false [GasEstimator.BlockHistory] BatchSize = 25 diff --git a/core/chains/evm/gas/helpers_test.go b/core/chains/evm/gas/helpers_test.go index 2c12ed426a..d6af645fe8 100644 --- a/core/chains/evm/gas/helpers_test.go +++ b/core/chains/evm/gas/helpers_test.go @@ -157,6 +157,7 @@ type MockGasEstimatorConfig struct { FeeCapDefaultF *assets.Wei LimitMaxF uint64 ModeF string + EstimateGasLimitF bool } func NewMockGasConfig() *MockGasEstimatorConfig { @@ -214,3 +215,7 @@ func (m *MockGasEstimatorConfig) LimitMax() uint64 { func (m *MockGasEstimatorConfig) Mode() string { return m.ModeF } + +func (m *MockGasEstimatorConfig) EstimateGasLimit() bool { + return m.EstimateGasLimitF +} diff --git a/core/chains/evm/gas/mocks/evm_fee_estimator.go b/core/chains/evm/gas/mocks/evm_fee_estimator.go index a9adc261ce..603115a94c 100644 --- a/core/chains/evm/gas/mocks/evm_fee_estimator.go +++ b/core/chains/evm/gas/mocks/evm_fee_estimator.go @@ -7,6 +7,8 @@ import ( assets "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" + common "github.com/ethereum/go-ethereum/common" + context "context" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" @@ -145,14 +147,14 @@ func (_c *EvmFeeEstimator_Close_Call) RunAndReturn(run func() error) *EvmFeeEsti return _c } -// GetFee provides a mock function with given fields: ctx, calldata, feeLimit, maxFeePrice, opts -func (_m *EvmFeeEstimator) GetFee(ctx context.Context, calldata []byte, feeLimit uint64, maxFeePrice *assets.Wei, opts ...types.Opt) (gas.EvmFee, uint64, error) { +// GetFee provides a mock function with given fields: ctx, calldata, feeLimit, maxFeePrice, toAddress, opts +func (_m *EvmFeeEstimator) GetFee(ctx context.Context, calldata []byte, feeLimit uint64, maxFeePrice *assets.Wei, toAddress *common.Address, opts ...types.Opt) (gas.EvmFee, uint64, error) { _va := make([]interface{}, len(opts)) for _i := range opts { _va[_i] = opts[_i] } var _ca []interface{} - _ca = append(_ca, ctx, calldata, feeLimit, maxFeePrice) + _ca = append(_ca, ctx, calldata, feeLimit, maxFeePrice, toAddress) _ca = append(_ca, _va...) ret := _m.Called(_ca...) @@ -163,23 +165,23 @@ func (_m *EvmFeeEstimator) GetFee(ctx context.Context, calldata []byte, feeLimit var r0 gas.EvmFee var r1 uint64 var r2 error - if rf, ok := ret.Get(0).(func(context.Context, []byte, uint64, *assets.Wei, ...types.Opt) (gas.EvmFee, uint64, error)); ok { - return rf(ctx, calldata, feeLimit, maxFeePrice, opts...) + if rf, ok := ret.Get(0).(func(context.Context, []byte, uint64, *assets.Wei, *common.Address, ...types.Opt) (gas.EvmFee, uint64, error)); ok { + return rf(ctx, calldata, feeLimit, maxFeePrice, toAddress, opts...) } - if rf, ok := ret.Get(0).(func(context.Context, []byte, uint64, *assets.Wei, ...types.Opt) gas.EvmFee); ok { - r0 = rf(ctx, calldata, feeLimit, maxFeePrice, opts...) + if rf, ok := ret.Get(0).(func(context.Context, []byte, uint64, *assets.Wei, *common.Address, ...types.Opt) gas.EvmFee); ok { + r0 = rf(ctx, calldata, feeLimit, maxFeePrice, toAddress, opts...) } else { r0 = ret.Get(0).(gas.EvmFee) } - if rf, ok := ret.Get(1).(func(context.Context, []byte, uint64, *assets.Wei, ...types.Opt) uint64); ok { - r1 = rf(ctx, calldata, feeLimit, maxFeePrice, opts...) + if rf, ok := ret.Get(1).(func(context.Context, []byte, uint64, *assets.Wei, *common.Address, ...types.Opt) uint64); ok { + r1 = rf(ctx, calldata, feeLimit, maxFeePrice, toAddress, opts...) } else { r1 = ret.Get(1).(uint64) } - if rf, ok := ret.Get(2).(func(context.Context, []byte, uint64, *assets.Wei, ...types.Opt) error); ok { - r2 = rf(ctx, calldata, feeLimit, maxFeePrice, opts...) + if rf, ok := ret.Get(2).(func(context.Context, []byte, uint64, *assets.Wei, *common.Address, ...types.Opt) error); ok { + r2 = rf(ctx, calldata, feeLimit, maxFeePrice, toAddress, opts...) } else { r2 = ret.Error(2) } @@ -197,43 +199,44 @@ type EvmFeeEstimator_GetFee_Call struct { // - calldata []byte // - feeLimit uint64 // - maxFeePrice *assets.Wei +// - toAddress *common.Address // - opts ...types.Opt -func (_e *EvmFeeEstimator_Expecter) GetFee(ctx interface{}, calldata interface{}, feeLimit interface{}, maxFeePrice interface{}, opts ...interface{}) *EvmFeeEstimator_GetFee_Call { +func (_e *EvmFeeEstimator_Expecter) GetFee(ctx interface{}, calldata interface{}, feeLimit interface{}, maxFeePrice interface{}, toAddress interface{}, opts ...interface{}) *EvmFeeEstimator_GetFee_Call { return &EvmFeeEstimator_GetFee_Call{Call: _e.mock.On("GetFee", - append([]interface{}{ctx, calldata, feeLimit, maxFeePrice}, opts...)...)} + append([]interface{}{ctx, calldata, feeLimit, maxFeePrice, toAddress}, opts...)...)} } -func (_c *EvmFeeEstimator_GetFee_Call) Run(run func(ctx context.Context, calldata []byte, feeLimit uint64, maxFeePrice *assets.Wei, opts ...types.Opt)) *EvmFeeEstimator_GetFee_Call { +func (_c *EvmFeeEstimator_GetFee_Call) Run(run func(ctx context.Context, calldata []byte, feeLimit uint64, maxFeePrice *assets.Wei, toAddress *common.Address, opts ...types.Opt)) *EvmFeeEstimator_GetFee_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]types.Opt, len(args)-4) - for i, a := range args[4:] { + variadicArgs := make([]types.Opt, len(args)-5) + for i, a := range args[5:] { if a != nil { variadicArgs[i] = a.(types.Opt) } } - run(args[0].(context.Context), args[1].([]byte), args[2].(uint64), args[3].(*assets.Wei), variadicArgs...) + run(args[0].(context.Context), args[1].([]byte), args[2].(uint64), args[3].(*assets.Wei), args[4].(*common.Address), variadicArgs...) }) return _c } -func (_c *EvmFeeEstimator_GetFee_Call) Return(fee gas.EvmFee, chainSpecificFeeLimit uint64, err error) *EvmFeeEstimator_GetFee_Call { - _c.Call.Return(fee, chainSpecificFeeLimit, err) +func (_c *EvmFeeEstimator_GetFee_Call) Return(fee gas.EvmFee, estimatedFeeLimit uint64, err error) *EvmFeeEstimator_GetFee_Call { + _c.Call.Return(fee, estimatedFeeLimit, err) return _c } -func (_c *EvmFeeEstimator_GetFee_Call) RunAndReturn(run func(context.Context, []byte, uint64, *assets.Wei, ...types.Opt) (gas.EvmFee, uint64, error)) *EvmFeeEstimator_GetFee_Call { +func (_c *EvmFeeEstimator_GetFee_Call) RunAndReturn(run func(context.Context, []byte, uint64, *assets.Wei, *common.Address, ...types.Opt) (gas.EvmFee, uint64, error)) *EvmFeeEstimator_GetFee_Call { _c.Call.Return(run) return _c } -// GetMaxCost provides a mock function with given fields: ctx, amount, calldata, feeLimit, maxFeePrice, opts -func (_m *EvmFeeEstimator) GetMaxCost(ctx context.Context, amount assets.Eth, calldata []byte, feeLimit uint64, maxFeePrice *assets.Wei, opts ...types.Opt) (*big.Int, error) { +// GetMaxCost provides a mock function with given fields: ctx, amount, calldata, feeLimit, maxFeePrice, toAddress, opts +func (_m *EvmFeeEstimator) GetMaxCost(ctx context.Context, amount assets.Eth, calldata []byte, feeLimit uint64, maxFeePrice *assets.Wei, toAddress *common.Address, opts ...types.Opt) (*big.Int, error) { _va := make([]interface{}, len(opts)) for _i := range opts { _va[_i] = opts[_i] } var _ca []interface{} - _ca = append(_ca, ctx, amount, calldata, feeLimit, maxFeePrice) + _ca = append(_ca, ctx, amount, calldata, feeLimit, maxFeePrice, toAddress) _ca = append(_ca, _va...) ret := _m.Called(_ca...) @@ -243,19 +246,19 @@ func (_m *EvmFeeEstimator) GetMaxCost(ctx context.Context, amount assets.Eth, ca var r0 *big.Int var r1 error - if rf, ok := ret.Get(0).(func(context.Context, assets.Eth, []byte, uint64, *assets.Wei, ...types.Opt) (*big.Int, error)); ok { - return rf(ctx, amount, calldata, feeLimit, maxFeePrice, opts...) + if rf, ok := ret.Get(0).(func(context.Context, assets.Eth, []byte, uint64, *assets.Wei, *common.Address, ...types.Opt) (*big.Int, error)); ok { + return rf(ctx, amount, calldata, feeLimit, maxFeePrice, toAddress, opts...) } - if rf, ok := ret.Get(0).(func(context.Context, assets.Eth, []byte, uint64, *assets.Wei, ...types.Opt) *big.Int); ok { - r0 = rf(ctx, amount, calldata, feeLimit, maxFeePrice, opts...) + if rf, ok := ret.Get(0).(func(context.Context, assets.Eth, []byte, uint64, *assets.Wei, *common.Address, ...types.Opt) *big.Int); ok { + r0 = rf(ctx, amount, calldata, feeLimit, maxFeePrice, toAddress, opts...) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*big.Int) } } - if rf, ok := ret.Get(1).(func(context.Context, assets.Eth, []byte, uint64, *assets.Wei, ...types.Opt) error); ok { - r1 = rf(ctx, amount, calldata, feeLimit, maxFeePrice, opts...) + if rf, ok := ret.Get(1).(func(context.Context, assets.Eth, []byte, uint64, *assets.Wei, *common.Address, ...types.Opt) error); ok { + r1 = rf(ctx, amount, calldata, feeLimit, maxFeePrice, toAddress, opts...) } else { r1 = ret.Error(1) } @@ -274,21 +277,22 @@ type EvmFeeEstimator_GetMaxCost_Call struct { // - calldata []byte // - feeLimit uint64 // - maxFeePrice *assets.Wei +// - toAddress *common.Address // - opts ...types.Opt -func (_e *EvmFeeEstimator_Expecter) GetMaxCost(ctx interface{}, amount interface{}, calldata interface{}, feeLimit interface{}, maxFeePrice interface{}, opts ...interface{}) *EvmFeeEstimator_GetMaxCost_Call { +func (_e *EvmFeeEstimator_Expecter) GetMaxCost(ctx interface{}, amount interface{}, calldata interface{}, feeLimit interface{}, maxFeePrice interface{}, toAddress interface{}, opts ...interface{}) *EvmFeeEstimator_GetMaxCost_Call { return &EvmFeeEstimator_GetMaxCost_Call{Call: _e.mock.On("GetMaxCost", - append([]interface{}{ctx, amount, calldata, feeLimit, maxFeePrice}, opts...)...)} + append([]interface{}{ctx, amount, calldata, feeLimit, maxFeePrice, toAddress}, opts...)...)} } -func (_c *EvmFeeEstimator_GetMaxCost_Call) Run(run func(ctx context.Context, amount assets.Eth, calldata []byte, feeLimit uint64, maxFeePrice *assets.Wei, opts ...types.Opt)) *EvmFeeEstimator_GetMaxCost_Call { +func (_c *EvmFeeEstimator_GetMaxCost_Call) Run(run func(ctx context.Context, amount assets.Eth, calldata []byte, feeLimit uint64, maxFeePrice *assets.Wei, toAddress *common.Address, opts ...types.Opt)) *EvmFeeEstimator_GetMaxCost_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]types.Opt, len(args)-5) - for i, a := range args[5:] { + variadicArgs := make([]types.Opt, len(args)-6) + for i, a := range args[6:] { if a != nil { variadicArgs[i] = a.(types.Opt) } } - run(args[0].(context.Context), args[1].(assets.Eth), args[2].([]byte), args[3].(uint64), args[4].(*assets.Wei), variadicArgs...) + run(args[0].(context.Context), args[1].(assets.Eth), args[2].([]byte), args[3].(uint64), args[4].(*assets.Wei), args[5].(*common.Address), variadicArgs...) }) return _c } @@ -298,7 +302,7 @@ func (_c *EvmFeeEstimator_GetMaxCost_Call) Return(_a0 *big.Int, _a1 error) *EvmF return _c } -func (_c *EvmFeeEstimator_GetMaxCost_Call) RunAndReturn(run func(context.Context, assets.Eth, []byte, uint64, *assets.Wei, ...types.Opt) (*big.Int, error)) *EvmFeeEstimator_GetMaxCost_Call { +func (_c *EvmFeeEstimator_GetMaxCost_Call) RunAndReturn(run func(context.Context, assets.Eth, []byte, uint64, *assets.Wei, *common.Address, ...types.Opt) (*big.Int, error)) *EvmFeeEstimator_GetMaxCost_Call { _c.Call.Return(run) return _c } diff --git a/core/chains/evm/gas/mocks/fee_estimator_client.go b/core/chains/evm/gas/mocks/fee_estimator_client.go index 8e10107597..ab99eb7b0d 100644 --- a/core/chains/evm/gas/mocks/fee_estimator_client.go +++ b/core/chains/evm/gas/mocks/fee_estimator_client.go @@ -241,6 +241,63 @@ func (_c *FeeEstimatorClient_ConfiguredChainID_Call) RunAndReturn(run func() *bi return _c } +// EstimateGas provides a mock function with given fields: ctx, call +func (_m *FeeEstimatorClient) EstimateGas(ctx context.Context, call ethereum.CallMsg) (uint64, error) { + ret := _m.Called(ctx, call) + + if len(ret) == 0 { + panic("no return value specified for EstimateGas") + } + + var r0 uint64 + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, ethereum.CallMsg) (uint64, error)); ok { + return rf(ctx, call) + } + if rf, ok := ret.Get(0).(func(context.Context, ethereum.CallMsg) uint64); ok { + r0 = rf(ctx, call) + } else { + r0 = ret.Get(0).(uint64) + } + + if rf, ok := ret.Get(1).(func(context.Context, ethereum.CallMsg) error); ok { + r1 = rf(ctx, call) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeEstimatorClient_EstimateGas_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'EstimateGas' +type FeeEstimatorClient_EstimateGas_Call struct { + *mock.Call +} + +// EstimateGas is a helper method to define mock.On call +// - ctx context.Context +// - call ethereum.CallMsg +func (_e *FeeEstimatorClient_Expecter) EstimateGas(ctx interface{}, call interface{}) *FeeEstimatorClient_EstimateGas_Call { + return &FeeEstimatorClient_EstimateGas_Call{Call: _e.mock.On("EstimateGas", ctx, call)} +} + +func (_c *FeeEstimatorClient_EstimateGas_Call) Run(run func(ctx context.Context, call ethereum.CallMsg)) *FeeEstimatorClient_EstimateGas_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(ethereum.CallMsg)) + }) + return _c +} + +func (_c *FeeEstimatorClient_EstimateGas_Call) Return(_a0 uint64, _a1 error) *FeeEstimatorClient_EstimateGas_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeEstimatorClient_EstimateGas_Call) RunAndReturn(run func(context.Context, ethereum.CallMsg) (uint64, error)) *FeeEstimatorClient_EstimateGas_Call { + _c.Call.Return(run) + return _c +} + // HeadByNumber provides a mock function with given fields: ctx, n func (_m *FeeEstimatorClient) HeadByNumber(ctx context.Context, n *big.Int) (*types.Head, error) { ret := _m.Called(ctx, n) diff --git a/core/chains/evm/gas/models.go b/core/chains/evm/gas/models.go index c9607091fb..0da56a84d8 100644 --- a/core/chains/evm/gas/models.go +++ b/core/chains/evm/gas/models.go @@ -26,6 +26,9 @@ import ( evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" ) +// EstimateGasBuffer is a multiplier applied to estimated gas when the EstimateGasLimit feature is enabled +const EstimateGasBuffer = float32(1.15) + // EvmFeeEstimator provides a unified interface that wraps EvmEstimator and can determine if legacy or dynamic fee estimation should be used type EvmFeeEstimator interface { services.Service @@ -33,11 +36,11 @@ type EvmFeeEstimator interface { // L1Oracle returns the L1 gas price oracle only if the chain has one, e.g. OP stack L2s and Arbitrum. L1Oracle() rollups.L1Oracle - GetFee(ctx context.Context, calldata []byte, feeLimit uint64, maxFeePrice *assets.Wei, opts ...feetypes.Opt) (fee EvmFee, chainSpecificFeeLimit uint64, err error) + GetFee(ctx context.Context, calldata []byte, feeLimit uint64, maxFeePrice *assets.Wei, toAddress *common.Address, opts ...feetypes.Opt) (fee EvmFee, estimatedFeeLimit uint64, err error) BumpFee(ctx context.Context, originalFee EvmFee, feeLimit uint64, maxFeePrice *assets.Wei, attempts []EvmPriorAttempt) (bumpedFee EvmFee, chainSpecificFeeLimit uint64, err error) // GetMaxCost returns the total value = max price x fee units + transferred value - GetMaxCost(ctx context.Context, amount assets.Eth, calldata []byte, feeLimit uint64, maxFeePrice *assets.Wei, opts ...feetypes.Opt) (*big.Int, error) + GetMaxCost(ctx context.Context, amount assets.Eth, calldata []byte, feeLimit uint64, maxFeePrice *assets.Wei, toAddress *common.Address, opts ...feetypes.Opt) (*big.Int, error) } type feeEstimatorClient interface { @@ -46,6 +49,7 @@ type feeEstimatorClient interface { CallContext(ctx context.Context, result interface{}, method string, args ...interface{}) error ConfiguredChainID() *big.Int HeadByNumber(ctx context.Context, n *big.Int) (*evmtypes.Head, error) + EstimateGas(ctx context.Context, call ethereum.CallMsg) (uint64, error) } // NewEstimator returns the estimator for a given config @@ -70,6 +74,7 @@ func NewEstimator(lggr logger.Logger, ethClient feeEstimatorClient, cfg Config, "tipCapMin", geCfg.TipCapMin(), "priceMax", geCfg.PriceMax(), "priceMin", geCfg.PriceMin(), + "estimateGasLimit", geCfg.EstimateGasLimit(), ) df := geCfg.EIP1559DynamicFees() @@ -111,7 +116,7 @@ func NewEstimator(lggr logger.Logger, ethClient feeEstimatorClient, cfg Config, return NewFixedPriceEstimator(geCfg, ethClient, bh, lggr, l1Oracle) } } - return NewEvmFeeEstimator(lggr, newEstimator, df, geCfg), nil + return NewEvmFeeEstimator(lggr, newEstimator, df, geCfg, ethClient), nil } // DynamicFee encompasses both FeeCap and TipCap for EIP1559 transactions @@ -182,17 +187,19 @@ type evmFeeEstimator struct { EvmEstimator EIP1559Enabled bool geCfg GasEstimatorConfig + ethClient feeEstimatorClient } var _ EvmFeeEstimator = (*evmFeeEstimator)(nil) -func NewEvmFeeEstimator(lggr logger.Logger, newEstimator func(logger.Logger) EvmEstimator, eip1559Enabled bool, geCfg GasEstimatorConfig) EvmFeeEstimator { +func NewEvmFeeEstimator(lggr logger.Logger, newEstimator func(logger.Logger) EvmEstimator, eip1559Enabled bool, geCfg GasEstimatorConfig, ethClient feeEstimatorClient) EvmFeeEstimator { lggr = logger.Named(lggr, "WrappedEvmEstimator") return &evmFeeEstimator{ lggr: lggr, EvmEstimator: newEstimator(lggr), EIP1559Enabled: eip1559Enabled, geCfg: geCfg, + ethClient: ethClient, } } @@ -262,7 +269,10 @@ func (e *evmFeeEstimator) L1Oracle() rollups.L1Oracle { return e.EvmEstimator.L1Oracle() } -func (e *evmFeeEstimator) GetFee(ctx context.Context, calldata []byte, feeLimit uint64, maxFeePrice *assets.Wei, opts ...feetypes.Opt) (fee EvmFee, chainSpecificFeeLimit uint64, err error) { +// GetFee returns an initial estimated gas price and gas limit for a transaction +// The gas limit provided by the caller can be adjusted by gas estimation or for 2D fees +func (e *evmFeeEstimator) GetFee(ctx context.Context, calldata []byte, feeLimit uint64, maxFeePrice *assets.Wei, toAddress *common.Address, opts ...feetypes.Opt) (fee EvmFee, estimatedFeeLimit uint64, err error) { + var chainSpecificFeeLimit uint64 // get dynamic fee if e.EIP1559Enabled { var dynamicFee DynamicFee @@ -270,24 +280,23 @@ func (e *evmFeeEstimator) GetFee(ctx context.Context, calldata []byte, feeLimit if err != nil { return } - chainSpecificFeeLimit, err = commonfee.ApplyMultiplier(feeLimit, e.geCfg.LimitMultiplier()) fee.DynamicFeeCap = dynamicFee.FeeCap fee.DynamicTipCap = dynamicFee.TipCap - return - } - - // get legacy fee - fee.Legacy, chainSpecificFeeLimit, err = e.EvmEstimator.GetLegacyGas(ctx, calldata, feeLimit, maxFeePrice, opts...) - if err != nil { - return + chainSpecificFeeLimit = feeLimit + } else { + // get legacy fee + fee.Legacy, chainSpecificFeeLimit, err = e.EvmEstimator.GetLegacyGas(ctx, calldata, feeLimit, maxFeePrice, opts...) + if err != nil { + return + } } - chainSpecificFeeLimit, err = commonfee.ApplyMultiplier(chainSpecificFeeLimit, e.geCfg.LimitMultiplier()) + estimatedFeeLimit, err = e.estimateFeeLimit(ctx, chainSpecificFeeLimit, calldata, toAddress) return } -func (e *evmFeeEstimator) GetMaxCost(ctx context.Context, amount assets.Eth, calldata []byte, feeLimit uint64, maxFeePrice *assets.Wei, opts ...feetypes.Opt) (*big.Int, error) { - fees, gasLimit, err := e.GetFee(ctx, calldata, feeLimit, maxFeePrice, opts...) +func (e *evmFeeEstimator) GetMaxCost(ctx context.Context, amount assets.Eth, calldata []byte, feeLimit uint64, maxFeePrice *assets.Wei, toAddress *common.Address, opts ...feetypes.Opt) (*big.Int, error) { + fees, gasLimit, err := e.GetFee(ctx, calldata, feeLimit, maxFeePrice, toAddress, opts...) if err != nil { return nil, err } @@ -338,6 +347,53 @@ func (e *evmFeeEstimator) BumpFee(ctx context.Context, originalFee EvmFee, feeLi return } +func (e *evmFeeEstimator) estimateFeeLimit(ctx context.Context, feeLimit uint64, calldata []byte, toAddress *common.Address) (estimatedFeeLimit uint64, err error) { + // Use the feeLimit * LimitMultiplier as the provided gas limit since this multiplier is applied on top of the caller specified gas limit + providedGasLimit, err := commonfee.ApplyMultiplier(feeLimit, e.geCfg.LimitMultiplier()) + if err != nil { + return estimatedFeeLimit, err + } + // Use provided fee limit by default if EstimateGasLimit is disabled + if !e.geCfg.EstimateGasLimit() { + return providedGasLimit, nil + } + // Create call msg for gas limit estimation + // Skip setting Gas to avoid capping the results of the estimation + callMsg := ethereum.CallMsg{ + To: toAddress, + Data: calldata, + } + estimatedGas, estimateErr := e.ethClient.EstimateGas(ctx, callMsg) + if estimateErr != nil { + if providedGasLimit > 0 { + // Do not return error if estimate gas failed, we can still use the provided limit instead since it is an upper limit + e.lggr.Errorw("failed to estimate gas limit. falling back to the provided gas limit with multiplier", "callMsg", callMsg, "providedGasLimitWithMultiplier", providedGasLimit, "error", estimateErr) + return providedGasLimit, nil + } + return estimatedFeeLimit, fmt.Errorf("gas estimation failed and provided gas limit is 0: %w", estimateErr) + } + e.lggr.Debugw("estimated gas", "estimatedGas", estimatedGas, "providedGasLimitWithMultiplier", providedGasLimit) + // Return error if estimated gas without the buffer exceeds the provided gas limit, if provided + // Transaction would be destined to run out of gas and fail + if providedGasLimit > 0 && estimatedGas > providedGasLimit { + e.lggr.Errorw("estimated gas exceeds provided gas limit with multiplier", "estimatedGas", estimatedGas, "providedGasLimitWithMultiplier", providedGasLimit) + return estimatedFeeLimit, commonfee.ErrFeeLimitTooLow + } + // Apply EstimateGasBuffer to the estimated gas limit + estimatedFeeLimit, err = commonfee.ApplyMultiplier(estimatedGas, EstimateGasBuffer) + if err != nil { + return + } + // If provided gas limit is not 0, fallback to it if the buffer causes the estimated gas limit to exceed it + // The provided gas limit should be used as an upper bound to avoid unexpected behavior for products + if providedGasLimit > 0 && estimatedFeeLimit > providedGasLimit { + e.lggr.Debugw("estimated gas limit with buffer exceeds the provided gas limit with multiplier. falling back to the provided gas limit with multiplier", "estimatedGasLimit", estimatedFeeLimit, "providedGasLimitWithMultiplier", providedGasLimit) + estimatedFeeLimit = providedGasLimit + } + + return +} + // Config defines an interface for configuration in the gas package type Config interface { ChainType() chaintype.ChainType @@ -359,6 +415,7 @@ type GasEstimatorConfig interface { PriceMin() *assets.Wei PriceMax() *assets.Wei Mode() string + EstimateGasLimit() bool } type BlockHistoryConfig interface { diff --git a/core/chains/evm/gas/models_test.go b/core/chains/evm/gas/models_test.go index 92ea901596..14ef085497 100644 --- a/core/chains/evm/gas/models_test.go +++ b/core/chains/evm/gas/models_test.go @@ -1,6 +1,7 @@ package gas_test import ( + "errors" "math/big" "testing" @@ -12,12 +13,14 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + commonfee "github.com/smartcontractkit/chainlink/v2/common/fee" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/chaintype" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/mocks" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/rollups" rollupMocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/rollups/mocks" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/testutils" ) func TestWrappedEvmEstimator(t *testing.T) { @@ -35,9 +38,9 @@ func TestWrappedEvmEstimator(t *testing.T) { est := mocks.NewEvmEstimator(t) est.On("GetDynamicFee", mock.Anything, mock.Anything). - Return(dynamicFee, nil).Twice() + Return(dynamicFee, nil).Times(6) est.On("GetLegacyGas", mock.Anything, mock.Anything, mock.Anything, mock.Anything). - Return(legacyFee, gasLimit, nil).Twice() + Return(legacyFee, gasLimit, nil).Times(6) est.On("BumpDynamicFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything). Return(dynamicFee, nil).Once() est.On("BumpLegacyGas", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything). @@ -59,7 +62,7 @@ func TestWrappedEvmEstimator(t *testing.T) { getEst := func(logger.Logger) gas.EvmEstimator { return evmEstimator } // expect nil - estimator := gas.NewEvmFeeEstimator(lggr, getEst, false, nil) + estimator := gas.NewEvmFeeEstimator(lggr, getEst, false, nil, nil) l1Oracle := estimator.L1Oracle() assert.Nil(t, l1Oracle) @@ -68,7 +71,7 @@ func TestWrappedEvmEstimator(t *testing.T) { oracle, err := rollups.NewL1GasOracle(lggr, nil, chaintype.ChainOptimismBedrock) require.NoError(t, err) // cast oracle to L1Oracle interface - estimator = gas.NewEvmFeeEstimator(lggr, getEst, false, geCfg) + estimator = gas.NewEvmFeeEstimator(lggr, getEst, false, geCfg, nil) evmEstimator.On("L1Oracle").Return(oracle).Once() l1Oracle = estimator.L1Oracle() @@ -80,8 +83,8 @@ func TestWrappedEvmEstimator(t *testing.T) { lggr := logger.Test(t) // expect legacy fee data dynamicFees := false - estimator := gas.NewEvmFeeEstimator(lggr, getRootEst, dynamicFees, geCfg) - fee, max, err := estimator.GetFee(ctx, nil, 0, nil) + estimator := gas.NewEvmFeeEstimator(lggr, getRootEst, dynamicFees, geCfg, nil) + fee, max, err := estimator.GetFee(ctx, nil, 0, nil, nil) require.NoError(t, err) assert.Equal(t, uint64(float32(gasLimit)*limitMultiplier), max) assert.True(t, legacyFee.Equal(fee.Legacy)) @@ -90,8 +93,8 @@ func TestWrappedEvmEstimator(t *testing.T) { // expect dynamic fee data dynamicFees = true - estimator = gas.NewEvmFeeEstimator(lggr, getRootEst, dynamicFees, geCfg) - fee, max, err = estimator.GetFee(ctx, nil, gasLimit, nil) + estimator = gas.NewEvmFeeEstimator(lggr, getRootEst, dynamicFees, geCfg, nil) + fee, max, err = estimator.GetFee(ctx, nil, gasLimit, nil, nil) require.NoError(t, err) assert.Equal(t, uint64(float32(gasLimit)*limitMultiplier), max) assert.True(t, dynamicFee.FeeCap.Equal(fee.DynamicFeeCap)) @@ -103,7 +106,7 @@ func TestWrappedEvmEstimator(t *testing.T) { t.Run("BumpFee", func(t *testing.T) { lggr := logger.Test(t) dynamicFees := false - estimator := gas.NewEvmFeeEstimator(lggr, getRootEst, dynamicFees, geCfg) + estimator := gas.NewEvmFeeEstimator(lggr, getRootEst, dynamicFees, geCfg, nil) // expect legacy fee data fee, max, err := estimator.BumpFee(ctx, gas.EvmFee{Legacy: assets.NewWeiI(0)}, 0, nil, nil) @@ -141,8 +144,8 @@ func TestWrappedEvmEstimator(t *testing.T) { // expect legacy fee data dynamicFees := false - estimator := gas.NewEvmFeeEstimator(lggr, getRootEst, dynamicFees, geCfg) - total, err := estimator.GetMaxCost(ctx, val, nil, gasLimit, nil) + estimator := gas.NewEvmFeeEstimator(lggr, getRootEst, dynamicFees, geCfg, nil) + total, err := estimator.GetMaxCost(ctx, val, nil, gasLimit, nil, nil) require.NoError(t, err) fee := new(big.Int).Mul(legacyFee.ToInt(), big.NewInt(int64(gasLimit))) fee, _ = new(big.Float).Mul(new(big.Float).SetInt(fee), big.NewFloat(float64(limitMultiplier))).Int(nil) @@ -150,8 +153,8 @@ func TestWrappedEvmEstimator(t *testing.T) { // expect dynamic fee data dynamicFees = true - estimator = gas.NewEvmFeeEstimator(lggr, getRootEst, dynamicFees, geCfg) - total, err = estimator.GetMaxCost(ctx, val, nil, gasLimit, nil) + estimator = gas.NewEvmFeeEstimator(lggr, getRootEst, dynamicFees, geCfg, nil) + total, err = estimator.GetMaxCost(ctx, val, nil, gasLimit, nil, nil) require.NoError(t, err) fee = new(big.Int).Mul(dynamicFee.FeeCap.ToInt(), big.NewInt(int64(gasLimit))) fee, _ = new(big.Float).Mul(new(big.Float).SetInt(fee), big.NewFloat(float64(limitMultiplier))).Int(nil) @@ -166,7 +169,7 @@ func TestWrappedEvmEstimator(t *testing.T) { estimator := gas.NewEvmFeeEstimator(lggr, func(logger.Logger) gas.EvmEstimator { return evmEstimator - }, false, geCfg) + }, false, geCfg, nil) require.Equal(t, mockEstimatorName, estimator.Name()) require.Equal(t, mockEvmEstimatorName, evmEstimator.Name()) @@ -185,7 +188,7 @@ func TestWrappedEvmEstimator(t *testing.T) { evmEstimator.On("L1Oracle", mock.Anything).Return(nil).Twice() - estimator := gas.NewEvmFeeEstimator(lggr, getEst, false, geCfg) + estimator := gas.NewEvmFeeEstimator(lggr, getEst, false, geCfg, nil) err := estimator.Start(ctx) require.NoError(t, err) err = estimator.Close() @@ -193,7 +196,7 @@ func TestWrappedEvmEstimator(t *testing.T) { evmEstimator.On("L1Oracle", mock.Anything).Return(oracle).Twice() - estimator = gas.NewEvmFeeEstimator(lggr, getEst, false, geCfg) + estimator = gas.NewEvmFeeEstimator(lggr, getEst, false, geCfg, nil) err = estimator.Start(ctx) require.NoError(t, err) err = estimator.Close() @@ -210,11 +213,11 @@ func TestWrappedEvmEstimator(t *testing.T) { oracle.On("Ready").Return(nil).Twice() getEst := func(logger.Logger) gas.EvmEstimator { return evmEstimator } - estimator := gas.NewEvmFeeEstimator(lggr, getEst, false, geCfg) + estimator := gas.NewEvmFeeEstimator(lggr, getEst, false, geCfg, nil) err := estimator.Ready() require.NoError(t, err) - estimator = gas.NewEvmFeeEstimator(lggr, getEst, false, geCfg) + estimator = gas.NewEvmFeeEstimator(lggr, getEst, false, geCfg, nil) err = estimator.Ready() require.NoError(t, err) }) @@ -235,7 +238,7 @@ func TestWrappedEvmEstimator(t *testing.T) { oracle.On("HealthReport").Return(map[string]error{oracleKey: oracleError}).Once() getEst := func(logger.Logger) gas.EvmEstimator { return evmEstimator } - estimator := gas.NewEvmFeeEstimator(lggr, getEst, false, geCfg) + estimator := gas.NewEvmFeeEstimator(lggr, getEst, false, geCfg, nil) report := estimator.HealthReport() require.True(t, pkgerrors.Is(report[evmEstimatorKey], evmEstimatorError)) require.Nil(t, report[oracleKey]) @@ -243,10 +246,166 @@ func TestWrappedEvmEstimator(t *testing.T) { evmEstimator.On("L1Oracle").Return(oracle).Once() - estimator = gas.NewEvmFeeEstimator(lggr, getEst, false, geCfg) + estimator = gas.NewEvmFeeEstimator(lggr, getEst, false, geCfg, nil) report = estimator.HealthReport() require.True(t, pkgerrors.Is(report[evmEstimatorKey], evmEstimatorError)) require.True(t, pkgerrors.Is(report[oracleKey], oracleError)) require.NotNil(t, report[mockEstimatorName]) }) + + t.Run("GetFee, estimate gas limit enabled, succeeds", func(t *testing.T) { + estimatedGasLimit := uint64(5) + lggr := logger.Test(t) + // expect legacy fee data + dynamicFees := false + geCfg.EstimateGasLimitF = true + ethClient := testutils.NewEthClientMockWithDefaultChain(t) + ethClient.On("EstimateGas", mock.Anything, mock.Anything).Return(estimatedGasLimit, nil).Twice() + estimator := gas.NewEvmFeeEstimator(lggr, getRootEst, dynamicFees, geCfg, ethClient) + toAddress := testutils.NewAddress() + fee, limit, err := estimator.GetFee(ctx, []byte{}, gasLimit, nil, &toAddress) + require.NoError(t, err) + assert.Equal(t, uint64(float32(estimatedGasLimit)*gas.EstimateGasBuffer), limit) + assert.True(t, legacyFee.Equal(fee.Legacy)) + assert.Nil(t, fee.DynamicTipCap) + assert.Nil(t, fee.DynamicFeeCap) + + // expect dynamic fee data + dynamicFees = true + estimator = gas.NewEvmFeeEstimator(lggr, getRootEst, dynamicFees, geCfg, ethClient) + fee, limit, err = estimator.GetFee(ctx, []byte{}, gasLimit, nil, &toAddress) + require.NoError(t, err) + assert.Equal(t, uint64(float32(estimatedGasLimit)*gas.EstimateGasBuffer), limit) + assert.True(t, dynamicFee.FeeCap.Equal(fee.DynamicFeeCap)) + assert.True(t, dynamicFee.TipCap.Equal(fee.DynamicTipCap)) + assert.Nil(t, fee.Legacy) + }) + + t.Run("GetFee, estimate gas limit enabled, estimate exceeds provided limit, returns error", func(t *testing.T) { + estimatedGasLimit := uint64(100) + lggr := logger.Test(t) + // expect legacy fee data + dynamicFees := false + geCfg.EstimateGasLimitF = true + ethClient := testutils.NewEthClientMockWithDefaultChain(t) + ethClient.On("EstimateGas", mock.Anything, mock.Anything).Return(estimatedGasLimit, nil).Twice() + estimator := gas.NewEvmFeeEstimator(lggr, getRootEst, dynamicFees, geCfg, ethClient) + toAddress := testutils.NewAddress() + _, _, err := estimator.GetFee(ctx, []byte{}, gasLimit, nil, &toAddress) + require.ErrorIs(t, err, commonfee.ErrFeeLimitTooLow) + + // expect dynamic fee data + dynamicFees = true + estimator = gas.NewEvmFeeEstimator(lggr, getRootEst, dynamicFees, geCfg, ethClient) + _, _, err = estimator.GetFee(ctx, []byte{}, gasLimit, nil, &toAddress) + require.ErrorIs(t, err, commonfee.ErrFeeLimitTooLow) + }) + + t.Run("GetFee, estimate gas limit enabled, buffer exceeds provided limit, fallsback to provided limit", func(t *testing.T) { + estimatedGasLimit := uint64(15) // same as provided limit + lggr := logger.Test(t) + dynamicFees := false // expect legacy fee data + geCfg.EstimateGasLimitF = true + ethClient := testutils.NewEthClientMockWithDefaultChain(t) + ethClient.On("EstimateGas", mock.Anything, mock.Anything).Return(estimatedGasLimit, nil).Twice() + estimator := gas.NewEvmFeeEstimator(lggr, getRootEst, dynamicFees, geCfg, ethClient) + toAddress := testutils.NewAddress() + fee, limit, err := estimator.GetFee(ctx, []byte{}, gasLimit, nil, &toAddress) + require.NoError(t, err) + assert.Equal(t, uint64(float32(gasLimit)*limitMultiplier), limit) + assert.True(t, legacyFee.Equal(fee.Legacy)) + assert.Nil(t, fee.DynamicTipCap) + assert.Nil(t, fee.DynamicFeeCap) + + dynamicFees = true // expect dynamic fee data + estimator = gas.NewEvmFeeEstimator(lggr, getRootEst, dynamicFees, geCfg, ethClient) + fee, limit, err = estimator.GetFee(ctx, []byte{}, gasLimit, nil, &toAddress) + require.NoError(t, err) + assert.Equal(t, uint64(float32(gasLimit)*limitMultiplier), limit) + assert.True(t, dynamicFee.FeeCap.Equal(fee.DynamicFeeCap)) + assert.True(t, dynamicFee.TipCap.Equal(fee.DynamicTipCap)) + assert.Nil(t, fee.Legacy) + }) + + t.Run("GetFee, estimate gas limit enabled, RPC fails and fallsback to provided gas limit", func(t *testing.T) { + lggr := logger.Test(t) + // expect legacy fee data + dynamicFees := false + geCfg.EstimateGasLimitF = true + ethClient := testutils.NewEthClientMockWithDefaultChain(t) + ethClient.On("EstimateGas", mock.Anything, mock.Anything).Return(uint64(0), errors.New("something broke")).Twice() + estimator := gas.NewEvmFeeEstimator(lggr, getRootEst, dynamicFees, geCfg, ethClient) + toAddress := testutils.NewAddress() + fee, limit, err := estimator.GetFee(ctx, []byte{}, gasLimit, nil, &toAddress) + require.NoError(t, err) + assert.Equal(t, uint64(float32(gasLimit)*limitMultiplier), limit) + assert.True(t, legacyFee.Equal(fee.Legacy)) + assert.Nil(t, fee.DynamicTipCap) + assert.Nil(t, fee.DynamicFeeCap) + + // expect dynamic fee data + dynamicFees = true + estimator = gas.NewEvmFeeEstimator(lggr, getRootEst, dynamicFees, geCfg, ethClient) + fee, limit, err = estimator.GetFee(ctx, []byte{}, gasLimit, nil, &toAddress) + require.NoError(t, err) + assert.Equal(t, uint64(float32(gasLimit)*limitMultiplier), limit) + assert.True(t, dynamicFee.FeeCap.Equal(fee.DynamicFeeCap)) + assert.True(t, dynamicFee.TipCap.Equal(fee.DynamicTipCap)) + assert.Nil(t, fee.Legacy) + }) + + t.Run("GetFee, estimate gas limit enabled, provided fee limit 0, returns uncapped estimation", func(t *testing.T) { + est.On("GetDynamicFee", mock.Anything, mock.Anything). + Return(dynamicFee, nil).Once() + est.On("GetLegacyGas", mock.Anything, mock.Anything, uint64(0), mock.Anything). + Return(legacyFee, uint64(0), nil).Once() + estimatedGasLimit := uint64(100) // same as provided limit + lggr := logger.Test(t) + // expect legacy fee data + dynamicFees := false + geCfg.EstimateGasLimitF = true + ethClient := testutils.NewEthClientMockWithDefaultChain(t) + ethClient.On("EstimateGas", mock.Anything, mock.Anything).Return(estimatedGasLimit, nil).Twice() + estimator := gas.NewEvmFeeEstimator(lggr, getRootEst, dynamicFees, geCfg, ethClient) + toAddress := testutils.NewAddress() + fee, limit, err := estimator.GetFee(ctx, []byte{}, uint64(0), nil, &toAddress) + require.NoError(t, err) + assert.Equal(t, uint64(float32(estimatedGasLimit)*gas.EstimateGasBuffer), limit) + assert.True(t, legacyFee.Equal(fee.Legacy)) + assert.Nil(t, fee.DynamicTipCap) + assert.Nil(t, fee.DynamicFeeCap) + + // expect dynamic fee data + dynamicFees = true + estimator = gas.NewEvmFeeEstimator(lggr, getRootEst, dynamicFees, geCfg, ethClient) + fee, limit, err = estimator.GetFee(ctx, []byte{}, 0, nil, &toAddress) + require.NoError(t, err) + assert.Equal(t, uint64(float32(estimatedGasLimit)*gas.EstimateGasBuffer), limit) + assert.True(t, dynamicFee.FeeCap.Equal(fee.DynamicFeeCap)) + assert.True(t, dynamicFee.TipCap.Equal(fee.DynamicTipCap)) + assert.Nil(t, fee.Legacy) + }) + + t.Run("GetFee, estimate gas limit enabled, provided fee limit 0, returns error on failure", func(t *testing.T) { + est.On("GetDynamicFee", mock.Anything, mock.Anything). + Return(dynamicFee, nil).Once() + est.On("GetLegacyGas", mock.Anything, mock.Anything, uint64(0), mock.Anything). + Return(legacyFee, uint64(0), nil).Once() + lggr := logger.Test(t) + // expect legacy fee data + dynamicFees := false + geCfg.EstimateGasLimitF = true + ethClient := testutils.NewEthClientMockWithDefaultChain(t) + ethClient.On("EstimateGas", mock.Anything, mock.Anything).Return(uint64(0), errors.New("something broke")).Twice() + estimator := gas.NewEvmFeeEstimator(lggr, getRootEst, dynamicFees, geCfg, ethClient) + toAddress := testutils.NewAddress() + _, _, err := estimator.GetFee(ctx, []byte{}, 0, nil, &toAddress) + require.Error(t, err) + + // expect dynamic fee data + dynamicFees = true + estimator = gas.NewEvmFeeEstimator(lggr, getRootEst, dynamicFees, geCfg, ethClient) + _, _, err = estimator.GetFee(ctx, []byte{}, 0, nil, &toAddress) + require.Error(t, err) + }) } diff --git a/core/chains/evm/txmgr/attempts.go b/core/chains/evm/txmgr/attempts.go index 8566adcb5c..c57ecc4412 100644 --- a/core/chains/evm/txmgr/attempts.go +++ b/core/chains/evm/txmgr/attempts.go @@ -58,7 +58,7 @@ func (c *evmTxAttemptBuilder) NewTxAttempt(ctx context.Context, etx Tx, lggr log // used for L2 re-estimation on broadcasting (note EIP1559 must be disabled otherwise this will fail with mismatched fees + tx type) func (c *evmTxAttemptBuilder) NewTxAttemptWithType(ctx context.Context, etx Tx, lggr logger.Logger, txType int, opts ...feetypes.Opt) (attempt TxAttempt, fee gas.EvmFee, feeLimit uint64, retryable bool, err error) { keySpecificMaxGasPriceWei := c.feeConfig.PriceMaxKey(etx.FromAddress) - fee, feeLimit, err = c.EvmFeeEstimator.GetFee(ctx, etx.EncodedPayload, etx.FeeLimit, keySpecificMaxGasPriceWei, opts...) + fee, feeLimit, err = c.EvmFeeEstimator.GetFee(ctx, etx.EncodedPayload, etx.FeeLimit, keySpecificMaxGasPriceWei, &etx.ToAddress, opts...) if err != nil { return attempt, fee, feeLimit, true, pkgerrors.Wrap(err, "failed to get fee") // estimator errors are retryable } @@ -71,8 +71,8 @@ func (c *evmTxAttemptBuilder) NewTxAttemptWithType(ctx context.Context, etx Tx, // used in the txm broadcaster + confirmer when tx ix rejected for too low fee or is not included in a timely manner func (c *evmTxAttemptBuilder) NewBumpTxAttempt(ctx context.Context, etx Tx, previousAttempt TxAttempt, priorAttempts []TxAttempt, lggr logger.Logger) (attempt TxAttempt, bumpedFee gas.EvmFee, bumpedFeeLimit uint64, retryable bool, err error) { keySpecificMaxGasPriceWei := c.feeConfig.PriceMaxKey(etx.FromAddress) - - bumpedFee, bumpedFeeLimit, err = c.EvmFeeEstimator.BumpFee(ctx, previousAttempt.TxFee, etx.FeeLimit, keySpecificMaxGasPriceWei, newEvmPriorAttempts(priorAttempts)) + // Use the fee limit from the previous attempt to maintain limits adjusted for 2D fees or by estimation + bumpedFee, bumpedFeeLimit, err = c.EvmFeeEstimator.BumpFee(ctx, previousAttempt.TxFee, previousAttempt.ChainSpecificFeeLimit, keySpecificMaxGasPriceWei, newEvmPriorAttempts(priorAttempts)) if err != nil { return attempt, bumpedFee, bumpedFeeLimit, true, pkgerrors.Wrap(err, "failed to bump fee") // estimator errors are retryable } diff --git a/core/chains/evm/txmgr/attempts_test.go b/core/chains/evm/txmgr/attempts_test.go index 6be8cd7067..ea00f7a347 100644 --- a/core/chains/evm/txmgr/attempts_test.go +++ b/core/chains/evm/txmgr/attempts_test.go @@ -339,7 +339,7 @@ func TestTxm_NewCustomTxAttempt_NonRetryableErrors(t *testing.T) { func TestTxm_EvmTxAttemptBuilder_RetryableEstimatorError(t *testing.T) { est := gasmocks.NewEvmFeeEstimator(t) - est.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(gas.EvmFee{}, uint64(0), pkgerrors.New("fail")) + est.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(gas.EvmFee{}, uint64(0), pkgerrors.New("fail")) est.On("BumpFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(gas.EvmFee{}, uint64(0), pkgerrors.New("fail")) kst := ksmocks.NewEth(t) diff --git a/core/chains/evm/txmgr/broadcaster_test.go b/core/chains/evm/txmgr/broadcaster_test.go index cbbe522ba1..343988196c 100644 --- a/core/chains/evm/txmgr/broadcaster_test.go +++ b/core/chains/evm/txmgr/broadcaster_test.go @@ -29,8 +29,10 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" commonclient "github.com/smartcontractkit/chainlink/v2/common/client" + commmonfee "github.com/smartcontractkit/chainlink/v2/common/fee" txmgrcommon "github.com/smartcontractkit/chainlink/v2/common/txmgr" txmgrtypes "github.com/smartcontractkit/chainlink/v2/common/txmgr/types" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" evmconfig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config" @@ -69,7 +71,7 @@ func NewTestEthBroadcaster( estimator := gas.NewEvmFeeEstimator(lggr, func(lggr logger.Logger) gas.EvmEstimator { return gas.NewFixedPriceEstimator(config.EVM().GasEstimator(), nil, ge.BlockHistory(), lggr, nil) - }, ge.EIP1559DynamicFees(), ge) + }, ge.EIP1559DynamicFees(), ge, ethClient) txBuilder := txmgr.NewEvmTxAttemptBuilder(*ethClient.ConfiguredChainID(), ge, keyStore, estimator) ethBroadcaster := txmgrcommon.NewBroadcaster(txStore, txmgr.NewEvmTxmClient(ethClient, nil), txmgr.NewEvmTxmConfig(config.EVM()), txmgr.NewEvmTxmFeeConfig(config.EVM().GasEstimator()), config.EVM().Transactions(), gconfig.Database().Listener(), keyStore, txBuilder, nonceTracker, lggr, checkerFactory, nonceAutoSync, "") @@ -642,7 +644,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_OptimisticLockingOnEthTx(t *testi chStartEstimate := make(chan struct{}) chBlock := make(chan struct{}) - estimator.On("GetFee", mock.Anything, mock.Anything, mock.Anything, ccfg.EVM().GasEstimator().PriceMaxKey(fromAddress)).Return(gas.EvmFee{Legacy: assets.GWei(32)}, uint64(500), nil).Run(func(_ mock.Arguments) { + estimator.On("GetFee", mock.Anything, mock.Anything, mock.Anything, ccfg.EVM().GasEstimator().PriceMaxKey(fromAddress), mock.Anything).Return(gas.EvmFee{Legacy: assets.GWei(32)}, uint64(500), nil).Run(func(_ mock.Arguments) { close(chStartEstimate) <-chBlock }).Once() @@ -1177,7 +1179,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) { t.Run("callback set by ctor", func(t *testing.T) { estimator := gas.NewEvmFeeEstimator(lggr, func(lggr logger.Logger) gas.EvmEstimator { return gas.NewFixedPriceEstimator(evmcfg.EVM().GasEstimator(), nil, evmcfg.EVM().GasEstimator().BlockHistory(), lggr, nil) - }, evmcfg.EVM().GasEstimator().EIP1559DynamicFees(), evmcfg.EVM().GasEstimator()) + }, evmcfg.EVM().GasEstimator().EIP1559DynamicFees(), evmcfg.EVM().GasEstimator(), ethClient) txBuilder := txmgr.NewEvmTxAttemptBuilder(*ethClient.ConfiguredChainID(), evmcfg.EVM().GasEstimator(), ethKeyStore, estimator) localNextNonce = getLocalNextNonce(t, nonceTracker, fromAddress) eb2 := txmgr.NewEvmBroadcaster(txStore, txmClient, txmgr.NewEvmTxmConfig(evmcfg.EVM()), txmgr.NewEvmTxmFeeConfig(evmcfg.EVM().GasEstimator()), evmcfg.EVM().Transactions(), cfg.Database().Listener(), ethKeyStore, txBuilder, lggr, &testCheckerFactory{}, false, "") @@ -1666,6 +1668,73 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) { }) } +func TestEthBroadcaster_ProcessUnstartedEthTxs_GasEstimationError(t *testing.T) { + toAddress := testutils.NewAddress() + value := big.Int(assets.NewEthValue(142)) + gasLimit := uint64(242) + encodedPayload := []byte{0, 1} + + db := pgtest.NewSqlxDB(t) + cfg := configtest.NewTestGeneralConfig(t) + cfg.EVMConfigs()[0].GasEstimator.EstimateGasLimit = ptr(true) // Enabled gas limit estimation + limitMultiplier := float32(1.25) + cfg.EVMConfigs()[0].GasEstimator.LimitMultiplier = ptr(decimal.NewFromFloat32(limitMultiplier)) // Set LimitMultiplier for the buffer + txStore := cltest.NewTestTxStore(t, db) + + ethKeyStore := cltest.NewKeyStore(t, db).Eth() + _, fromAddress := cltest.MustInsertRandomKey(t, ethKeyStore) + + config := evmtest.NewChainScopedConfig(t, cfg) + ethClient := testutils.NewEthClientMockWithDefaultChain(t) + ethClient.On("PendingNonceAt", mock.Anything, fromAddress).Return(uint64(0), nil).Once() + lggr := logger.Test(t) + txmClient := txmgr.NewEvmTxmClient(ethClient, nil) + nonceTracker := txmgr.NewNonceTracker(lggr, txStore, txmClient) + ge := config.EVM().GasEstimator() + estimator := gas.NewEvmFeeEstimator(lggr, func(lggr logger.Logger) gas.EvmEstimator { + return gas.NewFixedPriceEstimator(ge, nil, ge.BlockHistory(), lggr, nil) + }, ge.EIP1559DynamicFees(), ge, ethClient) + txBuilder := txmgr.NewEvmTxAttemptBuilder(*ethClient.ConfiguredChainID(), ge, ethKeyStore, estimator) + eb := txmgrcommon.NewBroadcaster(txStore, txmgr.NewEvmTxmClient(ethClient, nil), txmgr.NewEvmTxmConfig(config.EVM()), txmgr.NewEvmTxmFeeConfig(config.EVM().GasEstimator()), config.EVM().Transactions(), cfg.Database().Listener(), ethKeyStore, txBuilder, nonceTracker, lggr, &testCheckerFactory{}, false, "") + + // Mark instance as test + eb.XXXTestDisableUnstartedTxAutoProcessing() + servicetest.Run(t, eb) + ctx := tests.Context(t) + t.Run("gas limit lowered after estimation", func(t *testing.T) { + estimatedGasLimit := uint64(100) + etx := mustCreateUnstartedTx(t, txStore, fromAddress, toAddress, encodedPayload, gasLimit, value, testutils.FixtureChainID) + ethClient.On("EstimateGas", mock.Anything, mock.Anything).Return(estimatedGasLimit, nil).Once() + ethClient.On("SendTransactionReturnCode", mock.Anything, mock.MatchedBy(func(tx *gethTypes.Transaction) bool { + return tx.Nonce() == uint64(0) + }), fromAddress).Return(commonclient.Successful, nil).Once() + + // Do the thing + retryable, err := eb.ProcessUnstartedTxs(ctx, fromAddress) + assert.NoError(t, err) + assert.False(t, retryable) + + dbEtx, err := txStore.FindTxWithAttempts(ctx, etx.ID) + require.NoError(t, err) + attempt := dbEtx.TxAttempts[0] + require.Equal(t, uint64(float32(estimatedGasLimit)*gas.EstimateGasBuffer), attempt.ChainSpecificFeeLimit) + }) + t.Run("provided gas limit too low, transaction marked as fatal error", func(t *testing.T) { + etx := mustCreateUnstartedTx(t, txStore, fromAddress, toAddress, encodedPayload, gasLimit, value, testutils.FixtureChainID) + ethClient.On("EstimateGas", mock.Anything, mock.Anything).Return(uint64(float32(gasLimit)*limitMultiplier)+1, nil).Once() + + // Do the thing + retryable, err := eb.ProcessUnstartedTxs(ctx, fromAddress) + assert.NoError(t, err) + assert.False(t, retryable) + + dbEtx, err := txStore.FindTxWithAttempts(ctx, etx.ID) + require.NoError(t, err) + require.Equal(t, txmgrcommon.TxFatalError, dbEtx.State) + require.Equal(t, commmonfee.ErrFeeLimitTooLow.Error(), dbEtx.Error.String) + }) +} + func TestEthBroadcaster_ProcessUnstartedEthTxs_KeystoreErrors(t *testing.T) { toAddress := gethCommon.HexToAddress("0x6C03DDA95a2AEd917EeCc6eddD4b9D16E6380411") value := big.Int(assets.NewEthValue(142)) @@ -1760,15 +1829,15 @@ func TestEthBroadcaster_SyncNonce(t *testing.T) { kst := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.RandomKey{Disabled: false}.MustInsertWithState(t, kst) + ethClient := testutils.NewEthClientMockWithDefaultChain(t) estimator := gas.NewEvmFeeEstimator(lggr, func(lggr logger.Logger) gas.EvmEstimator { return gas.NewFixedPriceEstimator(evmcfg.EVM().GasEstimator(), nil, evmcfg.EVM().GasEstimator().BlockHistory(), lggr, nil) - }, evmcfg.EVM().GasEstimator().EIP1559DynamicFees(), evmcfg.EVM().GasEstimator()) + }, evmcfg.EVM().GasEstimator().EIP1559DynamicFees(), evmcfg.EVM().GasEstimator(), ethClient) checkerFactory := &testCheckerFactory{} ge := evmcfg.EVM().GasEstimator() t.Run("does nothing if nonce sync is disabled", func(t *testing.T) { - ethClient := testutils.NewEthClientMockWithDefaultChain(t) txBuilder := txmgr.NewEvmTxAttemptBuilder(*ethClient.ConfiguredChainID(), ge, kst, estimator) kst := ksmocks.NewEth(t) @@ -1838,7 +1907,7 @@ func TestEthBroadcaster_HederaBroadcastValidation(t *testing.T) { ge := evmcfg.EVM().GasEstimator() estimator := gas.NewEvmFeeEstimator(lggr, func(lggr logger.Logger) gas.EvmEstimator { return gas.NewFixedPriceEstimator(evmcfg.EVM().GasEstimator(), nil, ge.BlockHistory(), lggr, nil) - }, ge.EIP1559DynamicFees(), ge) + }, ge.EIP1559DynamicFees(), ge, ethClient) txBuilder := txmgr.NewEvmTxAttemptBuilder(*ethClient.ConfiguredChainID(), ge, ethKeyStore, estimator) checkerFactory := &txmgr.CheckerFactory{Client: ethClient} ctx := tests.Context(t) diff --git a/core/chains/evm/txmgr/confirmer_test.go b/core/chains/evm/txmgr/confirmer_test.go index 45d7ac9e12..daba2e8d92 100644 --- a/core/chains/evm/txmgr/confirmer_test.go +++ b/core/chains/evm/txmgr/confirmer_test.go @@ -128,7 +128,7 @@ func TestEthConfirmer_Lifecycle(t *testing.T) { newEst := func(logger.Logger) gas.EvmEstimator { return estimator } lggr := logger.Test(t) ge := config.EVM().GasEstimator() - feeEstimator := gas.NewEvmFeeEstimator(lggr, newEst, ge.EIP1559DynamicFees(), ge) + feeEstimator := gas.NewEvmFeeEstimator(lggr, newEst, ge.EIP1559DynamicFees(), ge, ethClient) txBuilder := txmgr.NewEvmTxAttemptBuilder(*ethClient.ConfiguredChainID(), ge, ethKeyStore, feeEstimator) stuckTxDetector := txmgr.NewStuckTxDetector(lggr, testutils.FixtureChainID, "", assets.NewWei(assets.NewEth(100).ToInt()), config.EVM().Transactions().AutoPurge(), feeEstimator, txStore, ethClient) ec := txmgr.NewEvmConfirmer(txStore, txmgr.NewEvmTxmClient(ethClient, nil), txmgr.NewEvmTxmConfig(config.EVM()), txmgr.NewEvmTxmFeeConfig(ge), config.EVM().Transactions(), gconfig.Database(), ethKeyStore, txBuilder, lggr, stuckTxDetector) @@ -1646,7 +1646,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_WithConnectivityCheck(t *testing newEst := func(logger.Logger) gas.EvmEstimator { return estimator } estimator.On("BumpLegacyGas", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, uint64(0), pkgerrors.Wrapf(commonfee.ErrConnectivity, "transaction...")) ge := ccfg.EVM().GasEstimator() - feeEstimator := gas.NewEvmFeeEstimator(lggr, newEst, ge.EIP1559DynamicFees(), ge) + feeEstimator := gas.NewEvmFeeEstimator(lggr, newEst, ge.EIP1559DynamicFees(), ge, ethClient) txBuilder := txmgr.NewEvmTxAttemptBuilder(*ethClient.ConfiguredChainID(), ge, kst, feeEstimator) addresses := []gethCommon.Address{fromAddress} kst.On("EnabledAddressesForChain", mock.Anything, &cltest.FixtureChainID).Return(addresses, nil).Maybe() @@ -1695,7 +1695,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_WithConnectivityCheck(t *testing newEst := func(logger.Logger) gas.EvmEstimator { return estimator } // Create confirmer with necessary state ge := ccfg.EVM().GasEstimator() - feeEstimator := gas.NewEvmFeeEstimator(lggr, newEst, ge.EIP1559DynamicFees(), ge) + feeEstimator := gas.NewEvmFeeEstimator(lggr, newEst, ge.EIP1559DynamicFees(), ge, ethClient) txBuilder := txmgr.NewEvmTxAttemptBuilder(*ethClient.ConfiguredChainID(), ge, kst, feeEstimator) addresses := []gethCommon.Address{fromAddress} kst.On("EnabledAddressesForChain", mock.Anything, &cltest.FixtureChainID).Return(addresses, nil).Maybe() @@ -3195,7 +3195,7 @@ func TestEthConfirmer_ProcessStuckTransactions(t *testing.T) { fee := gas.EvmFee{Legacy: marketGasPrice} bumpedLegacy := assets.GWei(30) bumpedFee := gas.EvmFee{Legacy: bumpedLegacy} - feeEstimator.On("GetFee", mock.Anything, []byte{}, uint64(0), mock.Anything).Return(fee, uint64(0), nil) + feeEstimator.On("GetFee", mock.Anything, []byte{}, uint64(0), mock.Anything, mock.Anything).Return(fee, uint64(0), nil) feeEstimator.On("BumpFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(bumpedFee, uint64(10_000), nil) autoPurgeThreshold := uint32(5) autoPurgeMinAttempts := uint32(3) @@ -3286,7 +3286,7 @@ func newEthConfirmer(t testing.TB, txStore txmgr.EvmTxStore, ethClient client.Cl ge := config.EVM().GasEstimator() estimator := gas.NewEvmFeeEstimator(lggr, func(lggr logger.Logger) gas.EvmEstimator { return gas.NewFixedPriceEstimator(ge, nil, ge.BlockHistory(), lggr, nil) - }, ge.EIP1559DynamicFees(), ge) + }, ge.EIP1559DynamicFees(), ge, ethClient) txBuilder := txmgr.NewEvmTxAttemptBuilder(*ethClient.ConfiguredChainID(), ge, ks, estimator) stuckTxDetector := txmgr.NewStuckTxDetector(lggr, testutils.FixtureChainID, "", assets.NewWei(assets.NewEth(100).ToInt()), config.EVM().Transactions().AutoPurge(), estimator, txStore, ethClient) ec := txmgr.NewEvmConfirmer(txStore, txmgr.NewEvmTxmClient(ethClient, nil), txmgr.NewEvmTxmConfig(config.EVM()), txmgr.NewEvmTxmFeeConfig(ge), config.EVM().Transactions(), gconfig.Database(), ks, txBuilder, lggr, stuckTxDetector) diff --git a/core/chains/evm/txmgr/stuck_tx_detector.go b/core/chains/evm/txmgr/stuck_tx_detector.go index 5d621dc0b2..4e521d5f8f 100644 --- a/core/chains/evm/txmgr/stuck_tx_detector.go +++ b/core/chains/evm/txmgr/stuck_tx_detector.go @@ -25,7 +25,7 @@ import ( ) type stuckTxDetectorGasEstimator interface { - GetFee(ctx context.Context, calldata []byte, feeLimit uint64, maxFeePrice *assets.Wei, opts ...feetypes.Opt) (fee gas.EvmFee, chainSpecificFeeLimit uint64, err error) + GetFee(ctx context.Context, calldata []byte, feeLimit uint64, maxFeePrice *assets.Wei, toAddress *common.Address, opts ...feetypes.Opt) (fee gas.EvmFee, chainSpecificFeeLimit uint64, err error) } type stuckTxDetectorClient interface { @@ -199,7 +199,7 @@ func (d *stuckTxDetector) detectStuckTransactionsHeuristic(ctx context.Context, defer d.purgeBlockNumLock.RUnlock() // Get gas price from internal gas estimator // Send with max gas price time 2 to prevent the results from being capped. Need the market gas price here. - marketGasPrice, _, err := d.gasEstimator.GetFee(ctx, []byte{}, 0, d.maxPrice.Mul(big.NewInt(2))) + marketGasPrice, _, err := d.gasEstimator.GetFee(ctx, []byte{}, 0, d.maxPrice.Mul(big.NewInt(2)), nil) if err != nil { return txs, fmt.Errorf("failed to get market gas price for overflow detection: %w", err) } diff --git a/core/chains/evm/txmgr/stuck_tx_detector_test.go b/core/chains/evm/txmgr/stuck_tx_detector_test.go index def49f8e11..5e022091a6 100644 --- a/core/chains/evm/txmgr/stuck_tx_detector_test.go +++ b/core/chains/evm/txmgr/stuck_tx_detector_test.go @@ -73,7 +73,7 @@ func TestStuckTxDetector_LoadPurgeBlockNumMap(t *testing.T) { feeEstimator := gasmocks.NewEvmFeeEstimator(t) marketGasPrice := assets.GWei(15) fee := gas.EvmFee{Legacy: marketGasPrice} - feeEstimator.On("GetFee", mock.Anything, []byte{}, uint64(0), mock.Anything).Return(fee, uint64(0), nil) + feeEstimator.On("GetFee", mock.Anything, []byte{}, uint64(0), mock.Anything, mock.Anything).Return(fee, uint64(0), nil) autoPurgeThreshold := uint32(5) autoPurgeMinAttempts := uint32(3) autoPurgeCfg := testAutoPurgeConfig{ @@ -194,7 +194,7 @@ func TestStuckTxDetector_DetectStuckTransactionsHeuristic(t *testing.T) { // Return 10 gwei as market gas price marketGasPrice := tenGwei fee := gas.EvmFee{Legacy: marketGasPrice} - feeEstimator.On("GetFee", mock.Anything, []byte{}, uint64(0), mock.Anything).Return(fee, uint64(0), nil) + feeEstimator.On("GetFee", mock.Anything, []byte{}, uint64(0), mock.Anything, mock.Anything).Return(fee, uint64(0), nil) ethClient := testutils.NewEthClientMockWithDefaultChain(t) autoPurgeThreshold := uint32(5) autoPurgeMinAttempts := uint32(3) diff --git a/core/chains/evm/txmgr/test_helpers.go b/core/chains/evm/txmgr/test_helpers.go index 3b3584a988..a4f326d480 100644 --- a/core/chains/evm/txmgr/test_helpers.go +++ b/core/chains/evm/txmgr/test_helpers.go @@ -89,6 +89,7 @@ func (g *TestGasEstimatorConfig) LimitTransfer() uint64 { return 42 } func (g *TestGasEstimatorConfig) PriceMax() *assets.Wei { return assets.NewWeiI(42) } func (g *TestGasEstimatorConfig) PriceMin() *assets.Wei { return assets.NewWeiI(42) } func (g *TestGasEstimatorConfig) Mode() string { return "FixedPrice" } +func (g *TestGasEstimatorConfig) EstimateGasLimit() bool { return false } func (g *TestGasEstimatorConfig) LimitJobType() evmconfig.LimitJobType { return &TestLimitJobTypeConfig{} } diff --git a/core/config/docs/chains-evm.toml b/core/config/docs/chains-evm.toml index 73ea0ebb35..3e54d2cd0f 100644 --- a/core/config/docs/chains-evm.toml +++ b/core/config/docs/chains-evm.toml @@ -194,6 +194,8 @@ LimitMax = 8_000_000 # Default LimitMultiplier = '1.0' # Default # LimitTransfer is the gas limit used for an ordinary ETH transfer. LimitTransfer = 21_000 # Default +# EstimateGasLimit enables estimating gas limits for transactions. This feature respects the gas limit provided during transaction creation as an upper bound. +EstimateGasLimit = false # Default # BumpMin is the minimum fixed amount of wei by which gas is bumped on each transaction attempt. BumpMin = '5 gwei' # Default # BumpPercent is the percentage by which to bump gas on a transaction that has exceeded `BumpThreshold`. The larger of `BumpPercent` and `BumpMin` is taken for gas bumps. diff --git a/core/internal/features/features_test.go b/core/internal/features/features_test.go index 1259597379..3ce14ef284 100644 --- a/core/internal/features/features_test.go +++ b/core/internal/features/features_test.go @@ -1339,7 +1339,7 @@ func TestIntegration_BlockHistoryEstimator(t *testing.T) { chain := evmtest.MustGetDefaultChain(t, legacyChains) estimator := chain.GasEstimator() - gasPrice, gasLimit, err := estimator.GetFee(testutils.Context(t), nil, 500_000, maxGasPrice) + gasPrice, gasLimit, err := estimator.GetFee(testutils.Context(t), nil, 500_000, maxGasPrice, nil) require.NoError(t, err) assert.Equal(t, uint64(500000), gasLimit) assert.Equal(t, "41.5 gwei", gasPrice.Legacy.String()) @@ -1360,7 +1360,7 @@ func TestIntegration_BlockHistoryEstimator(t *testing.T) { newHeads.TrySend(h43) gomega.NewWithT(t).Eventually(func() string { - gasPrice, _, err := estimator.GetFee(testutils.Context(t), nil, 500000, maxGasPrice) + gasPrice, _, err := estimator.GetFee(testutils.Context(t), nil, 500000, maxGasPrice, nil) require.NoError(t, err) return gasPrice.Legacy.String() }, testutils.WaitTimeout(t), cltest.DBPollingInterval).Should(gomega.Equal("45 gwei")) diff --git a/core/services/chainlink/config_test.go b/core/services/chainlink/config_test.go index e9ed223b9b..3ded57cf76 100644 --- a/core/services/chainlink/config_test.go +++ b/core/services/chainlink/config_test.go @@ -520,6 +520,7 @@ func TestConfig_Marshal(t *testing.T) { LimitMax: ptr[uint64](17), LimitMultiplier: mustDecimal("1.234"), LimitTransfer: ptr[uint64](100), + EstimateGasLimit: ptr(false), TipCapDefault: assets.NewWeiI(2), TipCapMin: assets.NewWeiI(1), PriceDefault: assets.NewWeiI(math.MaxInt64), @@ -1024,6 +1025,7 @@ LimitDefault = 12 LimitMax = 17 LimitMultiplier = '1.234' LimitTransfer = 100 +EstimateGasLimit = false BumpMin = '100 wei' BumpPercent = 10 BumpThreshold = 6 diff --git a/core/services/chainlink/testdata/config-full.toml b/core/services/chainlink/testdata/config-full.toml index 9df2e70508..ea62617018 100644 --- a/core/services/chainlink/testdata/config-full.toml +++ b/core/services/chainlink/testdata/config-full.toml @@ -316,6 +316,7 @@ LimitDefault = 12 LimitMax = 17 LimitMultiplier = '1.234' LimitTransfer = 100 +EstimateGasLimit = false BumpMin = '100 wei' BumpPercent = 10 BumpThreshold = 6 diff --git a/core/services/chainlink/testdata/config-multi-chain-effective.toml b/core/services/chainlink/testdata/config-multi-chain-effective.toml index e560099c2c..dacb04fe9d 100644 --- a/core/services/chainlink/testdata/config-multi-chain-effective.toml +++ b/core/services/chainlink/testdata/config-multi-chain-effective.toml @@ -303,6 +303,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateGasLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -403,6 +404,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateGasLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -497,6 +499,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateGasLimit = false BumpMin = '20 gwei' BumpPercent = 20 BumpThreshold = 5 diff --git a/core/services/keeper/upkeep_executer_test.go b/core/services/keeper/upkeep_executer_test.go index c70a92c725..0f68543904 100644 --- a/core/services/keeper/upkeep_executer_test.go +++ b/core/services/keeper/upkeep_executer_test.go @@ -48,7 +48,7 @@ func mockEstimator(t *testing.T) gas.EvmFeeEstimator { // note: estimator will only return 1 of legacy or dynamic fees (not both) // assumed to call legacy estimator only estimator := gasmocks.NewEvmFeeEstimator(t) - estimator.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Maybe().Return(gas.EvmFee{ + estimator.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Maybe().Return(gas.EvmFee{ Legacy: assets.GWei(60), }, uint32(60), nil) return estimator diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/commit_store_reader_test.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/commit_store_reader_test.go index 6b075be50c..30ed2bf83b 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/commit_store_reader_test.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/commit_store_reader_test.go @@ -286,7 +286,7 @@ func TestCommitStoreReaders(t *testing.T) { } gasPrice := big.NewInt(10) daPrice := big.NewInt(20) - ge.On("GetFee", mock.Anything, mock.Anything, mock.Anything, assets.NewWei(maxGasPrice)).Return(gas.EvmFee{Legacy: assets.NewWei(gasPrice)}, uint64(0), nil) + ge.On("GetFee", mock.Anything, mock.Anything, mock.Anything, assets.NewWei(maxGasPrice), (*common.Address)(nil)).Return(gas.EvmFee{Legacy: assets.NewWei(gasPrice)}, uint64(0), nil) lm.On("GasPrice", mock.Anything).Return(assets.NewWei(daPrice), nil) for v, cr := range crs { diff --git a/core/services/ocr2/plugins/ccip/prices/exec_price_estimator.go b/core/services/ocr2/plugins/ccip/prices/exec_price_estimator.go index 56e1ddb583..031dc25ed8 100644 --- a/core/services/ocr2/plugins/ccip/prices/exec_price_estimator.go +++ b/core/services/ocr2/plugins/ccip/prices/exec_price_estimator.go @@ -26,7 +26,7 @@ func NewExecGasPriceEstimator(estimator gas.EvmFeeEstimator, maxGasPrice *big.In } func (g ExecGasPriceEstimator) GetGasPrice(ctx context.Context) (*big.Int, error) { - gasPriceWei, _, err := g.estimator.GetFee(ctx, nil, 0, assets.NewWei(g.maxGasPrice)) + gasPriceWei, _, err := g.estimator.GetFee(ctx, nil, 0, assets.NewWei(g.maxGasPrice), nil) if err != nil { return nil, err } diff --git a/core/services/ocr2/plugins/ccip/prices/exec_price_estimator_test.go b/core/services/ocr2/plugins/ccip/prices/exec_price_estimator_test.go index e1c2fa0398..6953805709 100644 --- a/core/services/ocr2/plugins/ccip/prices/exec_price_estimator_test.go +++ b/core/services/ocr2/plugins/ccip/prices/exec_price_estimator_test.go @@ -5,6 +5,7 @@ import ( "math/big" "testing" + "github.com/ethereum/go-ethereum/common" "github.com/pkg/errors" "github.com/stretchr/testify/assert" @@ -85,7 +86,7 @@ func TestExecPriceEstimator_GetGasPrice(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { sourceFeeEstimator := mocks.NewEvmFeeEstimator(t) - sourceFeeEstimator.On("GetFee", ctx, []byte(nil), uint64(0), assets.NewWei(tc.maxGasPrice)).Return( + sourceFeeEstimator.On("GetFee", ctx, []byte(nil), uint64(0), assets.NewWei(tc.maxGasPrice), (*common.Address)(nil)).Return( tc.sourceFeeEstimatorRespFee, uint64(0), tc.sourceFeeEstimatorRespErr) g := ExecGasPriceEstimator{ diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/gasprice/gasprice.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/gasprice/gasprice.go index f84a48c1ff..cc65203e54 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/gasprice/gasprice.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/gasprice/gasprice.go @@ -45,7 +45,7 @@ func CheckGasPrice(ctx context.Context, upkeepId *big.Int, offchainConfigBytes [ } lggr.Debugf("successfully decode offchain config for %s, max gas price is %s", upkeepId.String(), offchainConfig.MaxGasPrice.String()) - fee, _, err := ge.GetFee(ctx, []byte{}, feeLimit, assets.NewWei(big.NewInt(maxFeePrice))) + fee, _, err := ge.GetFee(ctx, []byte{}, feeLimit, assets.NewWei(big.NewInt(maxFeePrice)), nil) if err != nil { lggr.Errorw("failed to get fee, gas price check is disabled", "upkeepId", upkeepId.String(), "err", err) return encoding.UpkeepFailureReasonNone diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/gasprice/gasprice_test.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/gasprice/gasprice_test.go index 9b5640051d..4418dd0f7c 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/gasprice/gasprice_test.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/gasprice/gasprice_test.go @@ -86,13 +86,13 @@ func TestGasPrice_Check(t *testing.T) { ctx := testutils.Context(t) ge := gasMocks.NewEvmFeeEstimator(t) if test.FailedToGetFee { - ge.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return( + ge.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return( gas.EvmFee{}, feeLimit, errors.New("failed to retrieve gas price"), ) } else if test.CurrentLegacyGasPrice != nil { - ge.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return( + ge.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return( gas.EvmFee{ Legacy: assets.NewWei(test.CurrentLegacyGasPrice), }, @@ -100,7 +100,7 @@ func TestGasPrice_Check(t *testing.T) { nil, ) } else if test.CurrentDynamicGasPrice != nil { - ge.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return( + ge.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return( gas.EvmFee{ DynamicFeeCap: assets.NewWei(test.CurrentDynamicGasPrice), DynamicTipCap: assets.NewWei(big.NewInt(1_000_000_000)), diff --git a/core/services/relay/evm/chain_writer.go b/core/services/relay/evm/chain_writer.go index f188ffeced..dd2a0684c6 100644 --- a/core/services/relay/evm/chain_writer.go +++ b/core/services/relay/evm/chain_writer.go @@ -186,7 +186,7 @@ func (w *chainWriter) GetFeeComponents(ctx context.Context) (*commontypes.ChainF return nil, fmt.Errorf("gas estimator not available") } - fee, _, err := w.ge.GetFee(ctx, nil, 0, w.maxGasPrice) + fee, _, err := w.ge.GetFee(ctx, nil, 0, w.maxGasPrice, nil) if err != nil { return nil, err } diff --git a/core/services/relay/evm/chain_writer_test.go b/core/services/relay/evm/chain_writer_test.go index 66c85bfc2c..e3906a09bd 100644 --- a/core/services/relay/evm/chain_writer_test.go +++ b/core/services/relay/evm/chain_writer_test.go @@ -86,7 +86,7 @@ func TestChainWriter(t *testing.T) { }) t.Run("GetFeeComponents", func(t *testing.T) { - ge.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(gas.EvmFee{ + ge.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(gas.EvmFee{ Legacy: assets.NewWei(big.NewInt(1000000001)), DynamicFeeCap: assets.NewWei(big.NewInt(1000000002)), DynamicTipCap: assets.NewWei(big.NewInt(1000000003)), @@ -112,7 +112,7 @@ func TestChainWriter(t *testing.T) { }) t.Run("Returns Legacy Fee in absence of Dynamic Fee", func(t *testing.T) { - ge.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(gas.EvmFee{ + ge.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(gas.EvmFee{ Legacy: assets.NewWei(big.NewInt(1000000001)), DynamicFeeCap: nil, DynamicTipCap: assets.NewWei(big.NewInt(1000000003)), @@ -124,7 +124,7 @@ func TestChainWriter(t *testing.T) { }) t.Run("Fails when neither legacy or dynamic fee is available", func(t *testing.T) { - ge.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(gas.EvmFee{ + ge.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(gas.EvmFee{ Legacy: nil, DynamicFeeCap: nil, DynamicTipCap: nil, @@ -136,7 +136,7 @@ func TestChainWriter(t *testing.T) { t.Run("Fails when GetFee returns an error", func(t *testing.T) { expectedErr := fmt.Errorf("GetFee error") - ge.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(gas.EvmFee{ + ge.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(gas.EvmFee{ Legacy: nil, DynamicFeeCap: nil, DynamicTipCap: nil, @@ -146,7 +146,7 @@ func TestChainWriter(t *testing.T) { }) t.Run("Fails when L1Oracle returns error", func(t *testing.T) { - ge.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(gas.EvmFee{ + ge.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(gas.EvmFee{ Legacy: assets.NewWei(big.NewInt(1000000001)), DynamicFeeCap: assets.NewWei(big.NewInt(1000000002)), DynamicTipCap: assets.NewWei(big.NewInt(1000000003)), diff --git a/core/web/evm_transfer_controller.go b/core/web/evm_transfer_controller.go index 88d3dead4c..3e14aaccd3 100644 --- a/core/web/evm_transfer_controller.go +++ b/core/web/evm_transfer_controller.go @@ -54,7 +54,7 @@ func (tc *EVMTransfersController) Create(c *gin.Context) { } if !tr.AllowHigherAmounts { - err = ValidateEthBalanceForTransfer(c, chain, tr.FromAddress, tr.Amount) + err = ValidateEthBalanceForTransfer(c, chain, tr.FromAddress, tr.Amount, tr.DestinationAddress) if err != nil { jsonAPIError(c, http.StatusUnprocessableEntity, errors.Errorf("transaction failed: %v", err)) return @@ -92,7 +92,7 @@ func (tc *EVMTransfersController) Create(c *gin.Context) { } // ValidateEthBalanceForTransfer validates that the current balance can cover the transaction amount -func ValidateEthBalanceForTransfer(c *gin.Context, chain legacyevm.Chain, fromAddr common.Address, amount assets.Eth) error { +func ValidateEthBalanceForTransfer(c *gin.Context, chain legacyevm.Chain, fromAddr common.Address, amount assets.Eth, toAddr common.Address) error { var err error var balance *big.Int @@ -116,7 +116,7 @@ func ValidateEthBalanceForTransfer(c *gin.Context, chain legacyevm.Chain, fromAd gasLimit := chain.Config().EVM().GasEstimator().LimitTransfer() estimator := chain.GasEstimator() - amountWithFees, err := estimator.GetMaxCost(c, amount, nil, gasLimit, chain.Config().EVM().GasEstimator().PriceMaxKey(fromAddr)) + amountWithFees, err := estimator.GetMaxCost(c, amount, nil, gasLimit, chain.Config().EVM().GasEstimator().PriceMaxKey(fromAddr), &toAddr) if err != nil { return err } diff --git a/core/web/resolver/testdata/config-full.toml b/core/web/resolver/testdata/config-full.toml index c5547f8698..668ca74ced 100644 --- a/core/web/resolver/testdata/config-full.toml +++ b/core/web/resolver/testdata/config-full.toml @@ -316,6 +316,7 @@ LimitDefault = 12 LimitMax = 17 LimitMultiplier = '1.234' LimitTransfer = 100 +EstimateGasLimit = false BumpMin = '100 wei' BumpPercent = 10 BumpThreshold = 6 diff --git a/core/web/resolver/testdata/config-multi-chain-effective.toml b/core/web/resolver/testdata/config-multi-chain-effective.toml index 8c063d0e9e..108dd401a7 100644 --- a/core/web/resolver/testdata/config-multi-chain-effective.toml +++ b/core/web/resolver/testdata/config-multi-chain-effective.toml @@ -303,6 +303,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateGasLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -403,6 +404,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateGasLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -497,6 +499,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateGasLimit = false BumpMin = '20 gwei' BumpPercent = 20 BumpThreshold = 5 diff --git a/docs/CONFIG.md b/docs/CONFIG.md index 71ddf1c2c8..7153b8cadd 100644 --- a/docs/CONFIG.md +++ b/docs/CONFIG.md @@ -1818,6 +1818,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateGasLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -1912,6 +1913,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateGasLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -2006,6 +2008,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateGasLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -2100,6 +2103,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateGasLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -2195,6 +2199,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateGasLimit = false BumpMin = '100 wei' BumpPercent = 20 BumpThreshold = 3 @@ -2289,6 +2294,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateGasLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -2383,6 +2389,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateGasLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -2478,6 +2485,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateGasLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -2572,6 +2580,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateGasLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 5 @@ -2665,6 +2674,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateGasLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -2851,6 +2861,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateGasLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -2945,6 +2956,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateGasLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 5 @@ -3040,6 +3052,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateGasLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -3134,6 +3147,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateGasLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 5 @@ -3228,6 +3242,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateGasLimit = false BumpMin = '20 gwei' BumpPercent = 20 BumpThreshold = 5 @@ -3322,6 +3337,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateGasLimit = false BumpMin = '20 mwei' BumpPercent = 40 BumpThreshold = 3 @@ -3416,6 +3432,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateGasLimit = false BumpMin = '100 mwei' BumpPercent = 40 BumpThreshold = 3 @@ -3510,6 +3527,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateGasLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -3604,6 +3622,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateGasLimit = false BumpMin = '100 wei' BumpPercent = 20 BumpThreshold = 3 @@ -3698,6 +3717,7 @@ LimitDefault = 100000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateGasLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -3792,6 +3812,7 @@ LimitDefault = 2500000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateGasLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -3886,6 +3907,7 @@ LimitDefault = 2500000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateGasLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -3981,6 +4003,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateGasLimit = false BumpMin = '100 wei' BumpPercent = 20 BumpThreshold = 3 @@ -4075,6 +4098,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateGasLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -4356,6 +4380,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateGasLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 5 @@ -4450,6 +4475,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateGasLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -4544,6 +4570,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateGasLimit = false BumpMin = '100 mwei' BumpPercent = 40 BumpThreshold = 3 @@ -4638,6 +4665,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateGasLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -4732,6 +4760,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateGasLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -4825,6 +4854,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateGasLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 0 @@ -4919,6 +4949,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateGasLimit = false BumpMin = '20 mwei' BumpPercent = 40 BumpThreshold = 3 @@ -5013,6 +5044,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateGasLimit = false BumpMin = '100 wei' BumpPercent = 20 BumpThreshold = 3 @@ -5107,6 +5139,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateGasLimit = false BumpMin = '20 mwei' BumpPercent = 40 BumpThreshold = 3 @@ -5201,6 +5234,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateGasLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -5389,6 +5423,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateGasLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 5 @@ -5483,6 +5518,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateGasLimit = false BumpMin = '100 wei' BumpPercent = 20 BumpThreshold = 3 @@ -5577,6 +5613,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateGasLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -5672,6 +5709,7 @@ LimitDefault = 8000000 LimitMax = 1000000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateGasLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 5 @@ -5767,6 +5805,7 @@ LimitDefault = 8000000 LimitMax = 1000000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateGasLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 5 @@ -5957,6 +5996,7 @@ LimitDefault = 8000000 LimitMax = 1000000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateGasLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 5 @@ -6051,6 +6091,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateGasLimit = false BumpMin = '2 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -6145,6 +6186,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateGasLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -6239,6 +6281,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateGasLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -6333,6 +6376,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateGasLimit = false BumpMin = '2 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -6426,6 +6470,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateGasLimit = false BumpMin = '5 gwei' BumpPercent = 40 BumpThreshold = 3 @@ -6519,6 +6564,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateGasLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -6612,6 +6658,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateGasLimit = false BumpMin = '5 gwei' BumpPercent = 40 BumpThreshold = 3 @@ -6706,6 +6753,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateGasLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -6894,6 +6942,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateGasLimit = false BumpMin = '20 gwei' BumpPercent = 20 BumpThreshold = 5 @@ -6987,6 +7036,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateGasLimit = false BumpMin = '20 gwei' BumpPercent = 20 BumpThreshold = 5 @@ -7176,6 +7226,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateGasLimit = false BumpMin = '100 wei' BumpPercent = 20 BumpThreshold = 3 @@ -7271,6 +7322,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateGasLimit = false BumpMin = '100 wei' BumpPercent = 20 BumpThreshold = 3 @@ -7366,6 +7418,7 @@ LimitDefault = 8000000 LimitMax = 1000000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateGasLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 5 @@ -7461,6 +7514,7 @@ LimitDefault = 8000000 LimitMax = 1000000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateGasLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 5 @@ -7556,6 +7610,7 @@ LimitDefault = 8000000 LimitMax = 1000000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateGasLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 5 @@ -7650,6 +7705,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateGasLimit = false BumpMin = '1 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -7744,6 +7800,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateGasLimit = false BumpMin = '1 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -7838,6 +7895,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateGasLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -7932,6 +7990,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateGasLimit = false BumpMin = '100 wei' BumpPercent = 20 BumpThreshold = 3 @@ -8121,6 +8180,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateGasLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -8215,6 +8275,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateGasLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -8577,6 +8638,7 @@ LimitDefault = 8_000_000 # Default LimitMax = 8_000_000 # Default LimitMultiplier = '1.0' # Default LimitTransfer = 21_000 # Default +EstimateGasLimit = false # Default BumpMin = '5 gwei' # Default BumpPercent = 20 # Default BumpThreshold = 3 # Default @@ -8671,6 +8733,12 @@ LimitTransfer = 21_000 # Default ``` LimitTransfer is the gas limit used for an ordinary ETH transfer. +### EstimateGasLimit +```toml +EstimateGasLimit = false # Default +``` +EstimateGasLimit enables estimating gas limits for transactions. This feature respects the gas limit provided during transaction creation as an upper bound. + ### BumpMin ```toml BumpMin = '5 gwei' # Default diff --git a/testdata/scripts/node/validate/disk-based-logging-disabled.txtar b/testdata/scripts/node/validate/disk-based-logging-disabled.txtar index fe522ca1bb..135e062cf7 100644 --- a/testdata/scripts/node/validate/disk-based-logging-disabled.txtar +++ b/testdata/scripts/node/validate/disk-based-logging-disabled.txtar @@ -359,6 +359,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateGasLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 diff --git a/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar b/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar index 5a5ce42d6b..9fa53d50b6 100644 --- a/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar +++ b/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar @@ -359,6 +359,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateGasLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 diff --git a/testdata/scripts/node/validate/disk-based-logging.txtar b/testdata/scripts/node/validate/disk-based-logging.txtar index 12773dc99c..ad38875f18 100644 --- a/testdata/scripts/node/validate/disk-based-logging.txtar +++ b/testdata/scripts/node/validate/disk-based-logging.txtar @@ -359,6 +359,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateGasLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 diff --git a/testdata/scripts/node/validate/invalid.txtar b/testdata/scripts/node/validate/invalid.txtar index e709b24d5b..6baa4ce92c 100644 --- a/testdata/scripts/node/validate/invalid.txtar +++ b/testdata/scripts/node/validate/invalid.txtar @@ -349,6 +349,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateGasLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 diff --git a/testdata/scripts/node/validate/valid.txtar b/testdata/scripts/node/validate/valid.txtar index 9b22da4850..985cf03970 100644 --- a/testdata/scripts/node/validate/valid.txtar +++ b/testdata/scripts/node/validate/valid.txtar @@ -356,6 +356,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateGasLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 From 0245db8ba3d2cfa40391c9f173655a16719d3cdd Mon Sep 17 00:00:00 2001 From: amit-momin <108959691+amit-momin@users.noreply.github.com> Date: Tue, 27 Aug 2024 11:53:17 -0500 Subject: [PATCH 106/115] Set From address for gas limit estimation feature (#14246) * Set from address for gas limit estimation * Updated tests * Added changeset --- .changeset/great-timers-agree.md | 5 ++ .../chains/evm/gas/mocks/evm_fee_estimator.go | 70 ++++++++++--------- core/chains/evm/gas/models.go | 17 +++-- core/chains/evm/gas/models_test.go | 41 +++++------ core/chains/evm/txmgr/attempts.go | 2 +- core/chains/evm/txmgr/attempts_test.go | 2 +- core/chains/evm/txmgr/broadcaster_test.go | 2 +- core/chains/evm/txmgr/confirmer_test.go | 2 +- core/chains/evm/txmgr/stuck_tx_detector.go | 4 +- .../evm/txmgr/stuck_tx_detector_test.go | 4 +- core/internal/features/features_test.go | 4 +- core/services/keeper/upkeep_executer_test.go | 2 +- .../ccipdata/commit_store_reader_test.go | 2 +- .../ccip/prices/exec_price_estimator.go | 2 +- .../ccip/prices/exec_price_estimator_test.go | 2 +- .../evmregistry/v21/gasprice/gasprice.go | 2 +- .../evmregistry/v21/gasprice/gasprice_test.go | 6 +- core/services/relay/evm/chain_writer.go | 2 +- core/services/relay/evm/chain_writer_test.go | 10 +-- core/web/evm_transfer_controller.go | 2 +- 20 files changed, 95 insertions(+), 88 deletions(-) create mode 100644 .changeset/great-timers-agree.md diff --git a/.changeset/great-timers-agree.md b/.changeset/great-timers-agree.md new file mode 100644 index 0000000000..bfa27761fb --- /dev/null +++ b/.changeset/great-timers-agree.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +Updated gas limit estimation feature to set From address #internal diff --git a/core/chains/evm/gas/mocks/evm_fee_estimator.go b/core/chains/evm/gas/mocks/evm_fee_estimator.go index 603115a94c..a7deca2c63 100644 --- a/core/chains/evm/gas/mocks/evm_fee_estimator.go +++ b/core/chains/evm/gas/mocks/evm_fee_estimator.go @@ -147,14 +147,14 @@ func (_c *EvmFeeEstimator_Close_Call) RunAndReturn(run func() error) *EvmFeeEsti return _c } -// GetFee provides a mock function with given fields: ctx, calldata, feeLimit, maxFeePrice, toAddress, opts -func (_m *EvmFeeEstimator) GetFee(ctx context.Context, calldata []byte, feeLimit uint64, maxFeePrice *assets.Wei, toAddress *common.Address, opts ...types.Opt) (gas.EvmFee, uint64, error) { +// GetFee provides a mock function with given fields: ctx, calldata, feeLimit, maxFeePrice, fromAddress, toAddress, opts +func (_m *EvmFeeEstimator) GetFee(ctx context.Context, calldata []byte, feeLimit uint64, maxFeePrice *assets.Wei, fromAddress *common.Address, toAddress *common.Address, opts ...types.Opt) (gas.EvmFee, uint64, error) { _va := make([]interface{}, len(opts)) for _i := range opts { _va[_i] = opts[_i] } var _ca []interface{} - _ca = append(_ca, ctx, calldata, feeLimit, maxFeePrice, toAddress) + _ca = append(_ca, ctx, calldata, feeLimit, maxFeePrice, fromAddress, toAddress) _ca = append(_ca, _va...) ret := _m.Called(_ca...) @@ -165,23 +165,23 @@ func (_m *EvmFeeEstimator) GetFee(ctx context.Context, calldata []byte, feeLimit var r0 gas.EvmFee var r1 uint64 var r2 error - if rf, ok := ret.Get(0).(func(context.Context, []byte, uint64, *assets.Wei, *common.Address, ...types.Opt) (gas.EvmFee, uint64, error)); ok { - return rf(ctx, calldata, feeLimit, maxFeePrice, toAddress, opts...) + if rf, ok := ret.Get(0).(func(context.Context, []byte, uint64, *assets.Wei, *common.Address, *common.Address, ...types.Opt) (gas.EvmFee, uint64, error)); ok { + return rf(ctx, calldata, feeLimit, maxFeePrice, fromAddress, toAddress, opts...) } - if rf, ok := ret.Get(0).(func(context.Context, []byte, uint64, *assets.Wei, *common.Address, ...types.Opt) gas.EvmFee); ok { - r0 = rf(ctx, calldata, feeLimit, maxFeePrice, toAddress, opts...) + if rf, ok := ret.Get(0).(func(context.Context, []byte, uint64, *assets.Wei, *common.Address, *common.Address, ...types.Opt) gas.EvmFee); ok { + r0 = rf(ctx, calldata, feeLimit, maxFeePrice, fromAddress, toAddress, opts...) } else { r0 = ret.Get(0).(gas.EvmFee) } - if rf, ok := ret.Get(1).(func(context.Context, []byte, uint64, *assets.Wei, *common.Address, ...types.Opt) uint64); ok { - r1 = rf(ctx, calldata, feeLimit, maxFeePrice, toAddress, opts...) + if rf, ok := ret.Get(1).(func(context.Context, []byte, uint64, *assets.Wei, *common.Address, *common.Address, ...types.Opt) uint64); ok { + r1 = rf(ctx, calldata, feeLimit, maxFeePrice, fromAddress, toAddress, opts...) } else { r1 = ret.Get(1).(uint64) } - if rf, ok := ret.Get(2).(func(context.Context, []byte, uint64, *assets.Wei, *common.Address, ...types.Opt) error); ok { - r2 = rf(ctx, calldata, feeLimit, maxFeePrice, toAddress, opts...) + if rf, ok := ret.Get(2).(func(context.Context, []byte, uint64, *assets.Wei, *common.Address, *common.Address, ...types.Opt) error); ok { + r2 = rf(ctx, calldata, feeLimit, maxFeePrice, fromAddress, toAddress, opts...) } else { r2 = ret.Error(2) } @@ -199,22 +199,23 @@ type EvmFeeEstimator_GetFee_Call struct { // - calldata []byte // - feeLimit uint64 // - maxFeePrice *assets.Wei +// - fromAddress *common.Address // - toAddress *common.Address // - opts ...types.Opt -func (_e *EvmFeeEstimator_Expecter) GetFee(ctx interface{}, calldata interface{}, feeLimit interface{}, maxFeePrice interface{}, toAddress interface{}, opts ...interface{}) *EvmFeeEstimator_GetFee_Call { +func (_e *EvmFeeEstimator_Expecter) GetFee(ctx interface{}, calldata interface{}, feeLimit interface{}, maxFeePrice interface{}, fromAddress interface{}, toAddress interface{}, opts ...interface{}) *EvmFeeEstimator_GetFee_Call { return &EvmFeeEstimator_GetFee_Call{Call: _e.mock.On("GetFee", - append([]interface{}{ctx, calldata, feeLimit, maxFeePrice, toAddress}, opts...)...)} + append([]interface{}{ctx, calldata, feeLimit, maxFeePrice, fromAddress, toAddress}, opts...)...)} } -func (_c *EvmFeeEstimator_GetFee_Call) Run(run func(ctx context.Context, calldata []byte, feeLimit uint64, maxFeePrice *assets.Wei, toAddress *common.Address, opts ...types.Opt)) *EvmFeeEstimator_GetFee_Call { +func (_c *EvmFeeEstimator_GetFee_Call) Run(run func(ctx context.Context, calldata []byte, feeLimit uint64, maxFeePrice *assets.Wei, fromAddress *common.Address, toAddress *common.Address, opts ...types.Opt)) *EvmFeeEstimator_GetFee_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]types.Opt, len(args)-5) - for i, a := range args[5:] { + variadicArgs := make([]types.Opt, len(args)-6) + for i, a := range args[6:] { if a != nil { variadicArgs[i] = a.(types.Opt) } } - run(args[0].(context.Context), args[1].([]byte), args[2].(uint64), args[3].(*assets.Wei), args[4].(*common.Address), variadicArgs...) + run(args[0].(context.Context), args[1].([]byte), args[2].(uint64), args[3].(*assets.Wei), args[4].(*common.Address), args[5].(*common.Address), variadicArgs...) }) return _c } @@ -224,19 +225,19 @@ func (_c *EvmFeeEstimator_GetFee_Call) Return(fee gas.EvmFee, estimatedFeeLimit return _c } -func (_c *EvmFeeEstimator_GetFee_Call) RunAndReturn(run func(context.Context, []byte, uint64, *assets.Wei, *common.Address, ...types.Opt) (gas.EvmFee, uint64, error)) *EvmFeeEstimator_GetFee_Call { +func (_c *EvmFeeEstimator_GetFee_Call) RunAndReturn(run func(context.Context, []byte, uint64, *assets.Wei, *common.Address, *common.Address, ...types.Opt) (gas.EvmFee, uint64, error)) *EvmFeeEstimator_GetFee_Call { _c.Call.Return(run) return _c } -// GetMaxCost provides a mock function with given fields: ctx, amount, calldata, feeLimit, maxFeePrice, toAddress, opts -func (_m *EvmFeeEstimator) GetMaxCost(ctx context.Context, amount assets.Eth, calldata []byte, feeLimit uint64, maxFeePrice *assets.Wei, toAddress *common.Address, opts ...types.Opt) (*big.Int, error) { +// GetMaxCost provides a mock function with given fields: ctx, amount, calldata, feeLimit, maxFeePrice, fromAddress, toAddress, opts +func (_m *EvmFeeEstimator) GetMaxCost(ctx context.Context, amount assets.Eth, calldata []byte, feeLimit uint64, maxFeePrice *assets.Wei, fromAddress *common.Address, toAddress *common.Address, opts ...types.Opt) (*big.Int, error) { _va := make([]interface{}, len(opts)) for _i := range opts { _va[_i] = opts[_i] } var _ca []interface{} - _ca = append(_ca, ctx, amount, calldata, feeLimit, maxFeePrice, toAddress) + _ca = append(_ca, ctx, amount, calldata, feeLimit, maxFeePrice, fromAddress, toAddress) _ca = append(_ca, _va...) ret := _m.Called(_ca...) @@ -246,19 +247,19 @@ func (_m *EvmFeeEstimator) GetMaxCost(ctx context.Context, amount assets.Eth, ca var r0 *big.Int var r1 error - if rf, ok := ret.Get(0).(func(context.Context, assets.Eth, []byte, uint64, *assets.Wei, *common.Address, ...types.Opt) (*big.Int, error)); ok { - return rf(ctx, amount, calldata, feeLimit, maxFeePrice, toAddress, opts...) + if rf, ok := ret.Get(0).(func(context.Context, assets.Eth, []byte, uint64, *assets.Wei, *common.Address, *common.Address, ...types.Opt) (*big.Int, error)); ok { + return rf(ctx, amount, calldata, feeLimit, maxFeePrice, fromAddress, toAddress, opts...) } - if rf, ok := ret.Get(0).(func(context.Context, assets.Eth, []byte, uint64, *assets.Wei, *common.Address, ...types.Opt) *big.Int); ok { - r0 = rf(ctx, amount, calldata, feeLimit, maxFeePrice, toAddress, opts...) + if rf, ok := ret.Get(0).(func(context.Context, assets.Eth, []byte, uint64, *assets.Wei, *common.Address, *common.Address, ...types.Opt) *big.Int); ok { + r0 = rf(ctx, amount, calldata, feeLimit, maxFeePrice, fromAddress, toAddress, opts...) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*big.Int) } } - if rf, ok := ret.Get(1).(func(context.Context, assets.Eth, []byte, uint64, *assets.Wei, *common.Address, ...types.Opt) error); ok { - r1 = rf(ctx, amount, calldata, feeLimit, maxFeePrice, toAddress, opts...) + if rf, ok := ret.Get(1).(func(context.Context, assets.Eth, []byte, uint64, *assets.Wei, *common.Address, *common.Address, ...types.Opt) error); ok { + r1 = rf(ctx, amount, calldata, feeLimit, maxFeePrice, fromAddress, toAddress, opts...) } else { r1 = ret.Error(1) } @@ -277,22 +278,23 @@ type EvmFeeEstimator_GetMaxCost_Call struct { // - calldata []byte // - feeLimit uint64 // - maxFeePrice *assets.Wei +// - fromAddress *common.Address // - toAddress *common.Address // - opts ...types.Opt -func (_e *EvmFeeEstimator_Expecter) GetMaxCost(ctx interface{}, amount interface{}, calldata interface{}, feeLimit interface{}, maxFeePrice interface{}, toAddress interface{}, opts ...interface{}) *EvmFeeEstimator_GetMaxCost_Call { +func (_e *EvmFeeEstimator_Expecter) GetMaxCost(ctx interface{}, amount interface{}, calldata interface{}, feeLimit interface{}, maxFeePrice interface{}, fromAddress interface{}, toAddress interface{}, opts ...interface{}) *EvmFeeEstimator_GetMaxCost_Call { return &EvmFeeEstimator_GetMaxCost_Call{Call: _e.mock.On("GetMaxCost", - append([]interface{}{ctx, amount, calldata, feeLimit, maxFeePrice, toAddress}, opts...)...)} + append([]interface{}{ctx, amount, calldata, feeLimit, maxFeePrice, fromAddress, toAddress}, opts...)...)} } -func (_c *EvmFeeEstimator_GetMaxCost_Call) Run(run func(ctx context.Context, amount assets.Eth, calldata []byte, feeLimit uint64, maxFeePrice *assets.Wei, toAddress *common.Address, opts ...types.Opt)) *EvmFeeEstimator_GetMaxCost_Call { +func (_c *EvmFeeEstimator_GetMaxCost_Call) Run(run func(ctx context.Context, amount assets.Eth, calldata []byte, feeLimit uint64, maxFeePrice *assets.Wei, fromAddress *common.Address, toAddress *common.Address, opts ...types.Opt)) *EvmFeeEstimator_GetMaxCost_Call { _c.Call.Run(func(args mock.Arguments) { - variadicArgs := make([]types.Opt, len(args)-6) - for i, a := range args[6:] { + variadicArgs := make([]types.Opt, len(args)-7) + for i, a := range args[7:] { if a != nil { variadicArgs[i] = a.(types.Opt) } } - run(args[0].(context.Context), args[1].(assets.Eth), args[2].([]byte), args[3].(uint64), args[4].(*assets.Wei), args[5].(*common.Address), variadicArgs...) + run(args[0].(context.Context), args[1].(assets.Eth), args[2].([]byte), args[3].(uint64), args[4].(*assets.Wei), args[5].(*common.Address), args[6].(*common.Address), variadicArgs...) }) return _c } @@ -302,7 +304,7 @@ func (_c *EvmFeeEstimator_GetMaxCost_Call) Return(_a0 *big.Int, _a1 error) *EvmF return _c } -func (_c *EvmFeeEstimator_GetMaxCost_Call) RunAndReturn(run func(context.Context, assets.Eth, []byte, uint64, *assets.Wei, *common.Address, ...types.Opt) (*big.Int, error)) *EvmFeeEstimator_GetMaxCost_Call { +func (_c *EvmFeeEstimator_GetMaxCost_Call) RunAndReturn(run func(context.Context, assets.Eth, []byte, uint64, *assets.Wei, *common.Address, *common.Address, ...types.Opt) (*big.Int, error)) *EvmFeeEstimator_GetMaxCost_Call { _c.Call.Return(run) return _c } diff --git a/core/chains/evm/gas/models.go b/core/chains/evm/gas/models.go index 0da56a84d8..36e42771af 100644 --- a/core/chains/evm/gas/models.go +++ b/core/chains/evm/gas/models.go @@ -36,11 +36,11 @@ type EvmFeeEstimator interface { // L1Oracle returns the L1 gas price oracle only if the chain has one, e.g. OP stack L2s and Arbitrum. L1Oracle() rollups.L1Oracle - GetFee(ctx context.Context, calldata []byte, feeLimit uint64, maxFeePrice *assets.Wei, toAddress *common.Address, opts ...feetypes.Opt) (fee EvmFee, estimatedFeeLimit uint64, err error) + GetFee(ctx context.Context, calldata []byte, feeLimit uint64, maxFeePrice *assets.Wei, fromAddress, toAddress *common.Address, opts ...feetypes.Opt) (fee EvmFee, estimatedFeeLimit uint64, err error) BumpFee(ctx context.Context, originalFee EvmFee, feeLimit uint64, maxFeePrice *assets.Wei, attempts []EvmPriorAttempt) (bumpedFee EvmFee, chainSpecificFeeLimit uint64, err error) // GetMaxCost returns the total value = max price x fee units + transferred value - GetMaxCost(ctx context.Context, amount assets.Eth, calldata []byte, feeLimit uint64, maxFeePrice *assets.Wei, toAddress *common.Address, opts ...feetypes.Opt) (*big.Int, error) + GetMaxCost(ctx context.Context, amount assets.Eth, calldata []byte, feeLimit uint64, maxFeePrice *assets.Wei, fromAddress, toAddress *common.Address, opts ...feetypes.Opt) (*big.Int, error) } type feeEstimatorClient interface { @@ -271,7 +271,7 @@ func (e *evmFeeEstimator) L1Oracle() rollups.L1Oracle { // GetFee returns an initial estimated gas price and gas limit for a transaction // The gas limit provided by the caller can be adjusted by gas estimation or for 2D fees -func (e *evmFeeEstimator) GetFee(ctx context.Context, calldata []byte, feeLimit uint64, maxFeePrice *assets.Wei, toAddress *common.Address, opts ...feetypes.Opt) (fee EvmFee, estimatedFeeLimit uint64, err error) { +func (e *evmFeeEstimator) GetFee(ctx context.Context, calldata []byte, feeLimit uint64, maxFeePrice *assets.Wei, fromAddress, toAddress *common.Address, opts ...feetypes.Opt) (fee EvmFee, estimatedFeeLimit uint64, err error) { var chainSpecificFeeLimit uint64 // get dynamic fee if e.EIP1559Enabled { @@ -291,12 +291,12 @@ func (e *evmFeeEstimator) GetFee(ctx context.Context, calldata []byte, feeLimit } } - estimatedFeeLimit, err = e.estimateFeeLimit(ctx, chainSpecificFeeLimit, calldata, toAddress) + estimatedFeeLimit, err = e.estimateFeeLimit(ctx, chainSpecificFeeLimit, calldata, fromAddress, toAddress) return } -func (e *evmFeeEstimator) GetMaxCost(ctx context.Context, amount assets.Eth, calldata []byte, feeLimit uint64, maxFeePrice *assets.Wei, toAddress *common.Address, opts ...feetypes.Opt) (*big.Int, error) { - fees, gasLimit, err := e.GetFee(ctx, calldata, feeLimit, maxFeePrice, toAddress, opts...) +func (e *evmFeeEstimator) GetMaxCost(ctx context.Context, amount assets.Eth, calldata []byte, feeLimit uint64, maxFeePrice *assets.Wei, fromAddress, toAddress *common.Address, opts ...feetypes.Opt) (*big.Int, error) { + fees, gasLimit, err := e.GetFee(ctx, calldata, feeLimit, maxFeePrice, fromAddress, toAddress, opts...) if err != nil { return nil, err } @@ -347,7 +347,7 @@ func (e *evmFeeEstimator) BumpFee(ctx context.Context, originalFee EvmFee, feeLi return } -func (e *evmFeeEstimator) estimateFeeLimit(ctx context.Context, feeLimit uint64, calldata []byte, toAddress *common.Address) (estimatedFeeLimit uint64, err error) { +func (e *evmFeeEstimator) estimateFeeLimit(ctx context.Context, feeLimit uint64, calldata []byte, fromAddress, toAddress *common.Address) (estimatedFeeLimit uint64, err error) { // Use the feeLimit * LimitMultiplier as the provided gas limit since this multiplier is applied on top of the caller specified gas limit providedGasLimit, err := commonfee.ApplyMultiplier(feeLimit, e.geCfg.LimitMultiplier()) if err != nil { @@ -363,6 +363,9 @@ func (e *evmFeeEstimator) estimateFeeLimit(ctx context.Context, feeLimit uint64, To: toAddress, Data: calldata, } + if fromAddress != nil { + callMsg.From = *fromAddress + } estimatedGas, estimateErr := e.ethClient.EstimateGas(ctx, callMsg) if estimateErr != nil { if providedGasLimit > 0 { diff --git a/core/chains/evm/gas/models_test.go b/core/chains/evm/gas/models_test.go index 14ef085497..ea5e53c228 100644 --- a/core/chains/evm/gas/models_test.go +++ b/core/chains/evm/gas/models_test.go @@ -52,6 +52,9 @@ func TestWrappedEvmEstimator(t *testing.T) { mockEstimatorName := "WrappedEvmEstimator" mockEvmEstimatorName := "WrappedEvmEstimator.MockEstimator" + fromAddress := testutils.NewAddress() + toAddress := testutils.NewAddress() + // L1Oracle returns the correct L1Oracle interface t.Run("L1Oracle", func(t *testing.T) { lggr := logger.Test(t) @@ -84,7 +87,7 @@ func TestWrappedEvmEstimator(t *testing.T) { // expect legacy fee data dynamicFees := false estimator := gas.NewEvmFeeEstimator(lggr, getRootEst, dynamicFees, geCfg, nil) - fee, max, err := estimator.GetFee(ctx, nil, 0, nil, nil) + fee, max, err := estimator.GetFee(ctx, nil, 0, nil, nil, nil) require.NoError(t, err) assert.Equal(t, uint64(float32(gasLimit)*limitMultiplier), max) assert.True(t, legacyFee.Equal(fee.Legacy)) @@ -94,7 +97,7 @@ func TestWrappedEvmEstimator(t *testing.T) { // expect dynamic fee data dynamicFees = true estimator = gas.NewEvmFeeEstimator(lggr, getRootEst, dynamicFees, geCfg, nil) - fee, max, err = estimator.GetFee(ctx, nil, gasLimit, nil, nil) + fee, max, err = estimator.GetFee(ctx, nil, gasLimit, nil, nil, nil) require.NoError(t, err) assert.Equal(t, uint64(float32(gasLimit)*limitMultiplier), max) assert.True(t, dynamicFee.FeeCap.Equal(fee.DynamicFeeCap)) @@ -145,7 +148,7 @@ func TestWrappedEvmEstimator(t *testing.T) { // expect legacy fee data dynamicFees := false estimator := gas.NewEvmFeeEstimator(lggr, getRootEst, dynamicFees, geCfg, nil) - total, err := estimator.GetMaxCost(ctx, val, nil, gasLimit, nil, nil) + total, err := estimator.GetMaxCost(ctx, val, nil, gasLimit, nil, nil, nil) require.NoError(t, err) fee := new(big.Int).Mul(legacyFee.ToInt(), big.NewInt(int64(gasLimit))) fee, _ = new(big.Float).Mul(new(big.Float).SetInt(fee), big.NewFloat(float64(limitMultiplier))).Int(nil) @@ -154,7 +157,7 @@ func TestWrappedEvmEstimator(t *testing.T) { // expect dynamic fee data dynamicFees = true estimator = gas.NewEvmFeeEstimator(lggr, getRootEst, dynamicFees, geCfg, nil) - total, err = estimator.GetMaxCost(ctx, val, nil, gasLimit, nil, nil) + total, err = estimator.GetMaxCost(ctx, val, nil, gasLimit, nil, nil, nil) require.NoError(t, err) fee = new(big.Int).Mul(dynamicFee.FeeCap.ToInt(), big.NewInt(int64(gasLimit))) fee, _ = new(big.Float).Mul(new(big.Float).SetInt(fee), big.NewFloat(float64(limitMultiplier))).Int(nil) @@ -262,8 +265,7 @@ func TestWrappedEvmEstimator(t *testing.T) { ethClient := testutils.NewEthClientMockWithDefaultChain(t) ethClient.On("EstimateGas", mock.Anything, mock.Anything).Return(estimatedGasLimit, nil).Twice() estimator := gas.NewEvmFeeEstimator(lggr, getRootEst, dynamicFees, geCfg, ethClient) - toAddress := testutils.NewAddress() - fee, limit, err := estimator.GetFee(ctx, []byte{}, gasLimit, nil, &toAddress) + fee, limit, err := estimator.GetFee(ctx, []byte{}, gasLimit, nil, &fromAddress, &toAddress) require.NoError(t, err) assert.Equal(t, uint64(float32(estimatedGasLimit)*gas.EstimateGasBuffer), limit) assert.True(t, legacyFee.Equal(fee.Legacy)) @@ -273,7 +275,7 @@ func TestWrappedEvmEstimator(t *testing.T) { // expect dynamic fee data dynamicFees = true estimator = gas.NewEvmFeeEstimator(lggr, getRootEst, dynamicFees, geCfg, ethClient) - fee, limit, err = estimator.GetFee(ctx, []byte{}, gasLimit, nil, &toAddress) + fee, limit, err = estimator.GetFee(ctx, []byte{}, gasLimit, nil, &fromAddress, &toAddress) require.NoError(t, err) assert.Equal(t, uint64(float32(estimatedGasLimit)*gas.EstimateGasBuffer), limit) assert.True(t, dynamicFee.FeeCap.Equal(fee.DynamicFeeCap)) @@ -290,14 +292,13 @@ func TestWrappedEvmEstimator(t *testing.T) { ethClient := testutils.NewEthClientMockWithDefaultChain(t) ethClient.On("EstimateGas", mock.Anything, mock.Anything).Return(estimatedGasLimit, nil).Twice() estimator := gas.NewEvmFeeEstimator(lggr, getRootEst, dynamicFees, geCfg, ethClient) - toAddress := testutils.NewAddress() - _, _, err := estimator.GetFee(ctx, []byte{}, gasLimit, nil, &toAddress) + _, _, err := estimator.GetFee(ctx, []byte{}, gasLimit, nil, &fromAddress, &toAddress) require.ErrorIs(t, err, commonfee.ErrFeeLimitTooLow) // expect dynamic fee data dynamicFees = true estimator = gas.NewEvmFeeEstimator(lggr, getRootEst, dynamicFees, geCfg, ethClient) - _, _, err = estimator.GetFee(ctx, []byte{}, gasLimit, nil, &toAddress) + _, _, err = estimator.GetFee(ctx, []byte{}, gasLimit, nil, &fromAddress, &toAddress) require.ErrorIs(t, err, commonfee.ErrFeeLimitTooLow) }) @@ -309,8 +310,7 @@ func TestWrappedEvmEstimator(t *testing.T) { ethClient := testutils.NewEthClientMockWithDefaultChain(t) ethClient.On("EstimateGas", mock.Anything, mock.Anything).Return(estimatedGasLimit, nil).Twice() estimator := gas.NewEvmFeeEstimator(lggr, getRootEst, dynamicFees, geCfg, ethClient) - toAddress := testutils.NewAddress() - fee, limit, err := estimator.GetFee(ctx, []byte{}, gasLimit, nil, &toAddress) + fee, limit, err := estimator.GetFee(ctx, []byte{}, gasLimit, nil, &fromAddress, &toAddress) require.NoError(t, err) assert.Equal(t, uint64(float32(gasLimit)*limitMultiplier), limit) assert.True(t, legacyFee.Equal(fee.Legacy)) @@ -319,7 +319,7 @@ func TestWrappedEvmEstimator(t *testing.T) { dynamicFees = true // expect dynamic fee data estimator = gas.NewEvmFeeEstimator(lggr, getRootEst, dynamicFees, geCfg, ethClient) - fee, limit, err = estimator.GetFee(ctx, []byte{}, gasLimit, nil, &toAddress) + fee, limit, err = estimator.GetFee(ctx, []byte{}, gasLimit, nil, &fromAddress, &toAddress) require.NoError(t, err) assert.Equal(t, uint64(float32(gasLimit)*limitMultiplier), limit) assert.True(t, dynamicFee.FeeCap.Equal(fee.DynamicFeeCap)) @@ -335,8 +335,7 @@ func TestWrappedEvmEstimator(t *testing.T) { ethClient := testutils.NewEthClientMockWithDefaultChain(t) ethClient.On("EstimateGas", mock.Anything, mock.Anything).Return(uint64(0), errors.New("something broke")).Twice() estimator := gas.NewEvmFeeEstimator(lggr, getRootEst, dynamicFees, geCfg, ethClient) - toAddress := testutils.NewAddress() - fee, limit, err := estimator.GetFee(ctx, []byte{}, gasLimit, nil, &toAddress) + fee, limit, err := estimator.GetFee(ctx, []byte{}, gasLimit, nil, &fromAddress, &toAddress) require.NoError(t, err) assert.Equal(t, uint64(float32(gasLimit)*limitMultiplier), limit) assert.True(t, legacyFee.Equal(fee.Legacy)) @@ -346,7 +345,7 @@ func TestWrappedEvmEstimator(t *testing.T) { // expect dynamic fee data dynamicFees = true estimator = gas.NewEvmFeeEstimator(lggr, getRootEst, dynamicFees, geCfg, ethClient) - fee, limit, err = estimator.GetFee(ctx, []byte{}, gasLimit, nil, &toAddress) + fee, limit, err = estimator.GetFee(ctx, []byte{}, gasLimit, nil, &fromAddress, &toAddress) require.NoError(t, err) assert.Equal(t, uint64(float32(gasLimit)*limitMultiplier), limit) assert.True(t, dynamicFee.FeeCap.Equal(fee.DynamicFeeCap)) @@ -367,8 +366,7 @@ func TestWrappedEvmEstimator(t *testing.T) { ethClient := testutils.NewEthClientMockWithDefaultChain(t) ethClient.On("EstimateGas", mock.Anything, mock.Anything).Return(estimatedGasLimit, nil).Twice() estimator := gas.NewEvmFeeEstimator(lggr, getRootEst, dynamicFees, geCfg, ethClient) - toAddress := testutils.NewAddress() - fee, limit, err := estimator.GetFee(ctx, []byte{}, uint64(0), nil, &toAddress) + fee, limit, err := estimator.GetFee(ctx, []byte{}, uint64(0), nil, &fromAddress, &toAddress) require.NoError(t, err) assert.Equal(t, uint64(float32(estimatedGasLimit)*gas.EstimateGasBuffer), limit) assert.True(t, legacyFee.Equal(fee.Legacy)) @@ -378,7 +376,7 @@ func TestWrappedEvmEstimator(t *testing.T) { // expect dynamic fee data dynamicFees = true estimator = gas.NewEvmFeeEstimator(lggr, getRootEst, dynamicFees, geCfg, ethClient) - fee, limit, err = estimator.GetFee(ctx, []byte{}, 0, nil, &toAddress) + fee, limit, err = estimator.GetFee(ctx, []byte{}, 0, nil, &fromAddress, &toAddress) require.NoError(t, err) assert.Equal(t, uint64(float32(estimatedGasLimit)*gas.EstimateGasBuffer), limit) assert.True(t, dynamicFee.FeeCap.Equal(fee.DynamicFeeCap)) @@ -398,14 +396,13 @@ func TestWrappedEvmEstimator(t *testing.T) { ethClient := testutils.NewEthClientMockWithDefaultChain(t) ethClient.On("EstimateGas", mock.Anything, mock.Anything).Return(uint64(0), errors.New("something broke")).Twice() estimator := gas.NewEvmFeeEstimator(lggr, getRootEst, dynamicFees, geCfg, ethClient) - toAddress := testutils.NewAddress() - _, _, err := estimator.GetFee(ctx, []byte{}, 0, nil, &toAddress) + _, _, err := estimator.GetFee(ctx, []byte{}, 0, nil, &fromAddress, &toAddress) require.Error(t, err) // expect dynamic fee data dynamicFees = true estimator = gas.NewEvmFeeEstimator(lggr, getRootEst, dynamicFees, geCfg, ethClient) - _, _, err = estimator.GetFee(ctx, []byte{}, 0, nil, &toAddress) + _, _, err = estimator.GetFee(ctx, []byte{}, 0, nil, &fromAddress, &toAddress) require.Error(t, err) }) } diff --git a/core/chains/evm/txmgr/attempts.go b/core/chains/evm/txmgr/attempts.go index c57ecc4412..c284ee77bd 100644 --- a/core/chains/evm/txmgr/attempts.go +++ b/core/chains/evm/txmgr/attempts.go @@ -58,7 +58,7 @@ func (c *evmTxAttemptBuilder) NewTxAttempt(ctx context.Context, etx Tx, lggr log // used for L2 re-estimation on broadcasting (note EIP1559 must be disabled otherwise this will fail with mismatched fees + tx type) func (c *evmTxAttemptBuilder) NewTxAttemptWithType(ctx context.Context, etx Tx, lggr logger.Logger, txType int, opts ...feetypes.Opt) (attempt TxAttempt, fee gas.EvmFee, feeLimit uint64, retryable bool, err error) { keySpecificMaxGasPriceWei := c.feeConfig.PriceMaxKey(etx.FromAddress) - fee, feeLimit, err = c.EvmFeeEstimator.GetFee(ctx, etx.EncodedPayload, etx.FeeLimit, keySpecificMaxGasPriceWei, &etx.ToAddress, opts...) + fee, feeLimit, err = c.EvmFeeEstimator.GetFee(ctx, etx.EncodedPayload, etx.FeeLimit, keySpecificMaxGasPriceWei, &etx.FromAddress, &etx.ToAddress, opts...) if err != nil { return attempt, fee, feeLimit, true, pkgerrors.Wrap(err, "failed to get fee") // estimator errors are retryable } diff --git a/core/chains/evm/txmgr/attempts_test.go b/core/chains/evm/txmgr/attempts_test.go index ea00f7a347..5c43368fcc 100644 --- a/core/chains/evm/txmgr/attempts_test.go +++ b/core/chains/evm/txmgr/attempts_test.go @@ -339,7 +339,7 @@ func TestTxm_NewCustomTxAttempt_NonRetryableErrors(t *testing.T) { func TestTxm_EvmTxAttemptBuilder_RetryableEstimatorError(t *testing.T) { est := gasmocks.NewEvmFeeEstimator(t) - est.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(gas.EvmFee{}, uint64(0), pkgerrors.New("fail")) + est.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(gas.EvmFee{}, uint64(0), pkgerrors.New("fail")) est.On("BumpFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(gas.EvmFee{}, uint64(0), pkgerrors.New("fail")) kst := ksmocks.NewEth(t) diff --git a/core/chains/evm/txmgr/broadcaster_test.go b/core/chains/evm/txmgr/broadcaster_test.go index 343988196c..41f50f4434 100644 --- a/core/chains/evm/txmgr/broadcaster_test.go +++ b/core/chains/evm/txmgr/broadcaster_test.go @@ -644,7 +644,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_OptimisticLockingOnEthTx(t *testi chStartEstimate := make(chan struct{}) chBlock := make(chan struct{}) - estimator.On("GetFee", mock.Anything, mock.Anything, mock.Anything, ccfg.EVM().GasEstimator().PriceMaxKey(fromAddress), mock.Anything).Return(gas.EvmFee{Legacy: assets.GWei(32)}, uint64(500), nil).Run(func(_ mock.Arguments) { + estimator.On("GetFee", mock.Anything, mock.Anything, mock.Anything, ccfg.EVM().GasEstimator().PriceMaxKey(fromAddress), mock.Anything, mock.Anything).Return(gas.EvmFee{Legacy: assets.GWei(32)}, uint64(500), nil).Run(func(_ mock.Arguments) { close(chStartEstimate) <-chBlock }).Once() diff --git a/core/chains/evm/txmgr/confirmer_test.go b/core/chains/evm/txmgr/confirmer_test.go index daba2e8d92..82b668f168 100644 --- a/core/chains/evm/txmgr/confirmer_test.go +++ b/core/chains/evm/txmgr/confirmer_test.go @@ -3195,7 +3195,7 @@ func TestEthConfirmer_ProcessStuckTransactions(t *testing.T) { fee := gas.EvmFee{Legacy: marketGasPrice} bumpedLegacy := assets.GWei(30) bumpedFee := gas.EvmFee{Legacy: bumpedLegacy} - feeEstimator.On("GetFee", mock.Anything, []byte{}, uint64(0), mock.Anything, mock.Anything).Return(fee, uint64(0), nil) + feeEstimator.On("GetFee", mock.Anything, []byte{}, uint64(0), mock.Anything, mock.Anything, mock.Anything).Return(fee, uint64(0), nil) feeEstimator.On("BumpFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(bumpedFee, uint64(10_000), nil) autoPurgeThreshold := uint32(5) autoPurgeMinAttempts := uint32(3) diff --git a/core/chains/evm/txmgr/stuck_tx_detector.go b/core/chains/evm/txmgr/stuck_tx_detector.go index 4e521d5f8f..362bb6c0a5 100644 --- a/core/chains/evm/txmgr/stuck_tx_detector.go +++ b/core/chains/evm/txmgr/stuck_tx_detector.go @@ -25,7 +25,7 @@ import ( ) type stuckTxDetectorGasEstimator interface { - GetFee(ctx context.Context, calldata []byte, feeLimit uint64, maxFeePrice *assets.Wei, toAddress *common.Address, opts ...feetypes.Opt) (fee gas.EvmFee, chainSpecificFeeLimit uint64, err error) + GetFee(ctx context.Context, calldata []byte, feeLimit uint64, maxFeePrice *assets.Wei, fromAddress, toAddress *common.Address, opts ...feetypes.Opt) (fee gas.EvmFee, chainSpecificFeeLimit uint64, err error) } type stuckTxDetectorClient interface { @@ -199,7 +199,7 @@ func (d *stuckTxDetector) detectStuckTransactionsHeuristic(ctx context.Context, defer d.purgeBlockNumLock.RUnlock() // Get gas price from internal gas estimator // Send with max gas price time 2 to prevent the results from being capped. Need the market gas price here. - marketGasPrice, _, err := d.gasEstimator.GetFee(ctx, []byte{}, 0, d.maxPrice.Mul(big.NewInt(2)), nil) + marketGasPrice, _, err := d.gasEstimator.GetFee(ctx, []byte{}, 0, d.maxPrice.Mul(big.NewInt(2)), nil, nil) if err != nil { return txs, fmt.Errorf("failed to get market gas price for overflow detection: %w", err) } diff --git a/core/chains/evm/txmgr/stuck_tx_detector_test.go b/core/chains/evm/txmgr/stuck_tx_detector_test.go index 5e022091a6..eb22830ef3 100644 --- a/core/chains/evm/txmgr/stuck_tx_detector_test.go +++ b/core/chains/evm/txmgr/stuck_tx_detector_test.go @@ -73,7 +73,7 @@ func TestStuckTxDetector_LoadPurgeBlockNumMap(t *testing.T) { feeEstimator := gasmocks.NewEvmFeeEstimator(t) marketGasPrice := assets.GWei(15) fee := gas.EvmFee{Legacy: marketGasPrice} - feeEstimator.On("GetFee", mock.Anything, []byte{}, uint64(0), mock.Anything, mock.Anything).Return(fee, uint64(0), nil) + feeEstimator.On("GetFee", mock.Anything, []byte{}, uint64(0), mock.Anything, mock.Anything, mock.Anything).Return(fee, uint64(0), nil) autoPurgeThreshold := uint32(5) autoPurgeMinAttempts := uint32(3) autoPurgeCfg := testAutoPurgeConfig{ @@ -194,7 +194,7 @@ func TestStuckTxDetector_DetectStuckTransactionsHeuristic(t *testing.T) { // Return 10 gwei as market gas price marketGasPrice := tenGwei fee := gas.EvmFee{Legacy: marketGasPrice} - feeEstimator.On("GetFee", mock.Anything, []byte{}, uint64(0), mock.Anything, mock.Anything).Return(fee, uint64(0), nil) + feeEstimator.On("GetFee", mock.Anything, []byte{}, uint64(0), mock.Anything, mock.Anything, mock.Anything).Return(fee, uint64(0), nil) ethClient := testutils.NewEthClientMockWithDefaultChain(t) autoPurgeThreshold := uint32(5) autoPurgeMinAttempts := uint32(3) diff --git a/core/internal/features/features_test.go b/core/internal/features/features_test.go index 3ce14ef284..7be0307798 100644 --- a/core/internal/features/features_test.go +++ b/core/internal/features/features_test.go @@ -1339,7 +1339,7 @@ func TestIntegration_BlockHistoryEstimator(t *testing.T) { chain := evmtest.MustGetDefaultChain(t, legacyChains) estimator := chain.GasEstimator() - gasPrice, gasLimit, err := estimator.GetFee(testutils.Context(t), nil, 500_000, maxGasPrice, nil) + gasPrice, gasLimit, err := estimator.GetFee(testutils.Context(t), nil, 500_000, maxGasPrice, nil, nil) require.NoError(t, err) assert.Equal(t, uint64(500000), gasLimit) assert.Equal(t, "41.5 gwei", gasPrice.Legacy.String()) @@ -1360,7 +1360,7 @@ func TestIntegration_BlockHistoryEstimator(t *testing.T) { newHeads.TrySend(h43) gomega.NewWithT(t).Eventually(func() string { - gasPrice, _, err := estimator.GetFee(testutils.Context(t), nil, 500000, maxGasPrice, nil) + gasPrice, _, err := estimator.GetFee(testutils.Context(t), nil, 500000, maxGasPrice, nil, nil) require.NoError(t, err) return gasPrice.Legacy.String() }, testutils.WaitTimeout(t), cltest.DBPollingInterval).Should(gomega.Equal("45 gwei")) diff --git a/core/services/keeper/upkeep_executer_test.go b/core/services/keeper/upkeep_executer_test.go index 0f68543904..55926242a2 100644 --- a/core/services/keeper/upkeep_executer_test.go +++ b/core/services/keeper/upkeep_executer_test.go @@ -48,7 +48,7 @@ func mockEstimator(t *testing.T) gas.EvmFeeEstimator { // note: estimator will only return 1 of legacy or dynamic fees (not both) // assumed to call legacy estimator only estimator := gasmocks.NewEvmFeeEstimator(t) - estimator.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Maybe().Return(gas.EvmFee{ + estimator.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Maybe().Return(gas.EvmFee{ Legacy: assets.GWei(60), }, uint32(60), nil) return estimator diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/commit_store_reader_test.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/commit_store_reader_test.go index 30ed2bf83b..e9266c4fb2 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/commit_store_reader_test.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/commit_store_reader_test.go @@ -286,7 +286,7 @@ func TestCommitStoreReaders(t *testing.T) { } gasPrice := big.NewInt(10) daPrice := big.NewInt(20) - ge.On("GetFee", mock.Anything, mock.Anything, mock.Anything, assets.NewWei(maxGasPrice), (*common.Address)(nil)).Return(gas.EvmFee{Legacy: assets.NewWei(gasPrice)}, uint64(0), nil) + ge.On("GetFee", mock.Anything, mock.Anything, mock.Anything, assets.NewWei(maxGasPrice), (*common.Address)(nil), (*common.Address)(nil)).Return(gas.EvmFee{Legacy: assets.NewWei(gasPrice)}, uint64(0), nil) lm.On("GasPrice", mock.Anything).Return(assets.NewWei(daPrice), nil) for v, cr := range crs { diff --git a/core/services/ocr2/plugins/ccip/prices/exec_price_estimator.go b/core/services/ocr2/plugins/ccip/prices/exec_price_estimator.go index 031dc25ed8..84a6014bef 100644 --- a/core/services/ocr2/plugins/ccip/prices/exec_price_estimator.go +++ b/core/services/ocr2/plugins/ccip/prices/exec_price_estimator.go @@ -26,7 +26,7 @@ func NewExecGasPriceEstimator(estimator gas.EvmFeeEstimator, maxGasPrice *big.In } func (g ExecGasPriceEstimator) GetGasPrice(ctx context.Context) (*big.Int, error) { - gasPriceWei, _, err := g.estimator.GetFee(ctx, nil, 0, assets.NewWei(g.maxGasPrice), nil) + gasPriceWei, _, err := g.estimator.GetFee(ctx, nil, 0, assets.NewWei(g.maxGasPrice), nil, nil) if err != nil { return nil, err } diff --git a/core/services/ocr2/plugins/ccip/prices/exec_price_estimator_test.go b/core/services/ocr2/plugins/ccip/prices/exec_price_estimator_test.go index 6953805709..f9ba1523e5 100644 --- a/core/services/ocr2/plugins/ccip/prices/exec_price_estimator_test.go +++ b/core/services/ocr2/plugins/ccip/prices/exec_price_estimator_test.go @@ -86,7 +86,7 @@ func TestExecPriceEstimator_GetGasPrice(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { sourceFeeEstimator := mocks.NewEvmFeeEstimator(t) - sourceFeeEstimator.On("GetFee", ctx, []byte(nil), uint64(0), assets.NewWei(tc.maxGasPrice), (*common.Address)(nil)).Return( + sourceFeeEstimator.On("GetFee", ctx, []byte(nil), uint64(0), assets.NewWei(tc.maxGasPrice), (*common.Address)(nil), (*common.Address)(nil)).Return( tc.sourceFeeEstimatorRespFee, uint64(0), tc.sourceFeeEstimatorRespErr) g := ExecGasPriceEstimator{ diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/gasprice/gasprice.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/gasprice/gasprice.go index cc65203e54..36460683d4 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/gasprice/gasprice.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/gasprice/gasprice.go @@ -45,7 +45,7 @@ func CheckGasPrice(ctx context.Context, upkeepId *big.Int, offchainConfigBytes [ } lggr.Debugf("successfully decode offchain config for %s, max gas price is %s", upkeepId.String(), offchainConfig.MaxGasPrice.String()) - fee, _, err := ge.GetFee(ctx, []byte{}, feeLimit, assets.NewWei(big.NewInt(maxFeePrice)), nil) + fee, _, err := ge.GetFee(ctx, []byte{}, feeLimit, assets.NewWei(big.NewInt(maxFeePrice)), nil, nil) if err != nil { lggr.Errorw("failed to get fee, gas price check is disabled", "upkeepId", upkeepId.String(), "err", err) return encoding.UpkeepFailureReasonNone diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/gasprice/gasprice_test.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/gasprice/gasprice_test.go index 4418dd0f7c..7b5ef999f3 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/gasprice/gasprice_test.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/gasprice/gasprice_test.go @@ -86,13 +86,13 @@ func TestGasPrice_Check(t *testing.T) { ctx := testutils.Context(t) ge := gasMocks.NewEvmFeeEstimator(t) if test.FailedToGetFee { - ge.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return( + ge.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return( gas.EvmFee{}, feeLimit, errors.New("failed to retrieve gas price"), ) } else if test.CurrentLegacyGasPrice != nil { - ge.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return( + ge.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return( gas.EvmFee{ Legacy: assets.NewWei(test.CurrentLegacyGasPrice), }, @@ -100,7 +100,7 @@ func TestGasPrice_Check(t *testing.T) { nil, ) } else if test.CurrentDynamicGasPrice != nil { - ge.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return( + ge.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return( gas.EvmFee{ DynamicFeeCap: assets.NewWei(test.CurrentDynamicGasPrice), DynamicTipCap: assets.NewWei(big.NewInt(1_000_000_000)), diff --git a/core/services/relay/evm/chain_writer.go b/core/services/relay/evm/chain_writer.go index dd2a0684c6..466811d115 100644 --- a/core/services/relay/evm/chain_writer.go +++ b/core/services/relay/evm/chain_writer.go @@ -186,7 +186,7 @@ func (w *chainWriter) GetFeeComponents(ctx context.Context) (*commontypes.ChainF return nil, fmt.Errorf("gas estimator not available") } - fee, _, err := w.ge.GetFee(ctx, nil, 0, w.maxGasPrice, nil) + fee, _, err := w.ge.GetFee(ctx, nil, 0, w.maxGasPrice, nil, nil) if err != nil { return nil, err } diff --git a/core/services/relay/evm/chain_writer_test.go b/core/services/relay/evm/chain_writer_test.go index e3906a09bd..e3fc8f8e22 100644 --- a/core/services/relay/evm/chain_writer_test.go +++ b/core/services/relay/evm/chain_writer_test.go @@ -86,7 +86,7 @@ func TestChainWriter(t *testing.T) { }) t.Run("GetFeeComponents", func(t *testing.T) { - ge.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(gas.EvmFee{ + ge.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(gas.EvmFee{ Legacy: assets.NewWei(big.NewInt(1000000001)), DynamicFeeCap: assets.NewWei(big.NewInt(1000000002)), DynamicTipCap: assets.NewWei(big.NewInt(1000000003)), @@ -112,7 +112,7 @@ func TestChainWriter(t *testing.T) { }) t.Run("Returns Legacy Fee in absence of Dynamic Fee", func(t *testing.T) { - ge.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(gas.EvmFee{ + ge.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(gas.EvmFee{ Legacy: assets.NewWei(big.NewInt(1000000001)), DynamicFeeCap: nil, DynamicTipCap: assets.NewWei(big.NewInt(1000000003)), @@ -124,7 +124,7 @@ func TestChainWriter(t *testing.T) { }) t.Run("Fails when neither legacy or dynamic fee is available", func(t *testing.T) { - ge.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(gas.EvmFee{ + ge.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(gas.EvmFee{ Legacy: nil, DynamicFeeCap: nil, DynamicTipCap: nil, @@ -136,7 +136,7 @@ func TestChainWriter(t *testing.T) { t.Run("Fails when GetFee returns an error", func(t *testing.T) { expectedErr := fmt.Errorf("GetFee error") - ge.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(gas.EvmFee{ + ge.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(gas.EvmFee{ Legacy: nil, DynamicFeeCap: nil, DynamicTipCap: nil, @@ -146,7 +146,7 @@ func TestChainWriter(t *testing.T) { }) t.Run("Fails when L1Oracle returns error", func(t *testing.T) { - ge.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(gas.EvmFee{ + ge.On("GetFee", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(gas.EvmFee{ Legacy: assets.NewWei(big.NewInt(1000000001)), DynamicFeeCap: assets.NewWei(big.NewInt(1000000002)), DynamicTipCap: assets.NewWei(big.NewInt(1000000003)), diff --git a/core/web/evm_transfer_controller.go b/core/web/evm_transfer_controller.go index 3e14aaccd3..75f6c07b6d 100644 --- a/core/web/evm_transfer_controller.go +++ b/core/web/evm_transfer_controller.go @@ -116,7 +116,7 @@ func ValidateEthBalanceForTransfer(c *gin.Context, chain legacyevm.Chain, fromAd gasLimit := chain.Config().EVM().GasEstimator().LimitTransfer() estimator := chain.GasEstimator() - amountWithFees, err := estimator.GetMaxCost(c, amount, nil, gasLimit, chain.Config().EVM().GasEstimator().PriceMaxKey(fromAddr), &toAddr) + amountWithFees, err := estimator.GetMaxCost(c, amount, nil, gasLimit, chain.Config().EVM().GasEstimator().PriceMaxKey(fromAddr), &fromAddr, &toAddr) if err != nil { return err } From 3f6ac83fc431094d7959e77acce903a6a5bdbd75 Mon Sep 17 00:00:00 2001 From: amit-momin <108959691+amit-momin@users.noreply.github.com> Date: Tue, 3 Sep 2024 12:33:45 -0500 Subject: [PATCH 107/115] Update EstimateGasLimit config name to EstimateLimit (#14297) * Updated EstimateGasLimit config name to EstimateLimit * Updated mocks * Fixed linting * Updated changeset --- .changeset/loud-windows-call.md | 2 +- .../evm/config/chain_scoped_gas_estimator.go | 4 +- core/chains/evm/config/config.go | 2 +- core/chains/evm/config/config_test.go | 1 + core/chains/evm/config/mocks/gas_estimator.go | 22 +-- core/chains/evm/config/toml/config.go | 16 +-- .../evm/config/toml/defaults/fallback.toml | 2 +- core/chains/evm/gas/helpers_test.go | 6 +- core/chains/evm/gas/models.go | 10 +- core/chains/evm/gas/models_test.go | 12 +- core/chains/evm/txmgr/broadcaster_test.go | 2 +- core/chains/evm/txmgr/test_helpers.go | 2 +- core/config/docs/chains-evm.toml | 4 +- core/services/chainlink/config_test.go | 4 +- .../chainlink/testdata/config-full.toml | 2 +- .../config-multi-chain-effective.toml | 6 +- core/web/resolver/testdata/config-full.toml | 2 +- .../config-multi-chain-effective.toml | 6 +- docs/CONFIG.md | 130 +++++++++--------- .../disk-based-logging-disabled.txtar | 2 +- .../validate/disk-based-logging-no-dir.txtar | 2 +- .../node/validate/disk-based-logging.txtar | 2 +- testdata/scripts/node/validate/invalid.txtar | 2 +- testdata/scripts/node/validate/valid.txtar | 2 +- 24 files changed, 123 insertions(+), 122 deletions(-) diff --git a/.changeset/loud-windows-call.md b/.changeset/loud-windows-call.md index e05bed706a..6dc8d6fac7 100644 --- a/.changeset/loud-windows-call.md +++ b/.changeset/loud-windows-call.md @@ -2,4 +2,4 @@ "chainlink": minor --- -Added gas limit estimation feature to EVM gas estimators #added +Added gas limit estimation feature to EVM gas estimators. Introduced a new config `EVM.GasEstimator.EstimateLimit` to toggle this feature. #added diff --git a/core/chains/evm/config/chain_scoped_gas_estimator.go b/core/chains/evm/config/chain_scoped_gas_estimator.go index 4f2d8872d8..6f43839b01 100644 --- a/core/chains/evm/config/chain_scoped_gas_estimator.go +++ b/core/chains/evm/config/chain_scoped_gas_estimator.go @@ -108,8 +108,8 @@ func (g *gasEstimatorConfig) LimitJobType() LimitJobType { return &limitJobTypeConfig{c: g.c.LimitJobType} } -func (g *gasEstimatorConfig) EstimateGasLimit() bool { - return *g.c.EstimateGasLimit +func (g *gasEstimatorConfig) EstimateLimit() bool { + return *g.c.EstimateLimit } type limitJobTypeConfig struct { diff --git a/core/chains/evm/config/config.go b/core/chains/evm/config/config.go index 9517c68716..9237cf5e1e 100644 --- a/core/chains/evm/config/config.go +++ b/core/chains/evm/config/config.go @@ -136,7 +136,7 @@ type GasEstimator interface { PriceMin() *assets.Wei Mode() string PriceMaxKey(gethcommon.Address) *assets.Wei - EstimateGasLimit() bool + EstimateLimit() bool } type LimitJobType interface { diff --git a/core/chains/evm/config/config_test.go b/core/chains/evm/config/config_test.go index 617a1605d8..305737a87c 100644 --- a/core/chains/evm/config/config_test.go +++ b/core/chains/evm/config/config_test.go @@ -243,6 +243,7 @@ func TestChainScopedConfig_GasEstimator(t *testing.T) { assert.Equal(t, assets.GWei(100), ge.FeeCapDefault()) assert.Equal(t, assets.NewWeiI(1), ge.TipCapDefault()) assert.Equal(t, assets.NewWeiI(1), ge.TipCapMin()) + assert.Equal(t, false, ge.EstimateLimit()) } func TestChainScopedConfig_BSCDefaults(t *testing.T) { diff --git a/core/chains/evm/config/mocks/gas_estimator.go b/core/chains/evm/config/mocks/gas_estimator.go index 40c10757b8..96ffff08ae 100644 --- a/core/chains/evm/config/mocks/gas_estimator.go +++ b/core/chains/evm/config/mocks/gas_estimator.go @@ -298,12 +298,12 @@ func (_c *GasEstimator_EIP1559DynamicFees_Call) RunAndReturn(run func() bool) *G return _c } -// EstimateGasLimit provides a mock function with given fields: -func (_m *GasEstimator) EstimateGasLimit() bool { +// EstimateLimit provides a mock function with given fields: +func (_m *GasEstimator) EstimateLimit() bool { ret := _m.Called() if len(ret) == 0 { - panic("no return value specified for EstimateGasLimit") + panic("no return value specified for EstimateLimit") } var r0 bool @@ -316,29 +316,29 @@ func (_m *GasEstimator) EstimateGasLimit() bool { return r0 } -// GasEstimator_EstimateGasLimit_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'EstimateGasLimit' -type GasEstimator_EstimateGasLimit_Call struct { +// GasEstimator_EstimateLimit_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'EstimateLimit' +type GasEstimator_EstimateLimit_Call struct { *mock.Call } -// EstimateGasLimit is a helper method to define mock.On call -func (_e *GasEstimator_Expecter) EstimateGasLimit() *GasEstimator_EstimateGasLimit_Call { - return &GasEstimator_EstimateGasLimit_Call{Call: _e.mock.On("EstimateGasLimit")} +// EstimateLimit is a helper method to define mock.On call +func (_e *GasEstimator_Expecter) EstimateLimit() *GasEstimator_EstimateLimit_Call { + return &GasEstimator_EstimateLimit_Call{Call: _e.mock.On("EstimateLimit")} } -func (_c *GasEstimator_EstimateGasLimit_Call) Run(run func()) *GasEstimator_EstimateGasLimit_Call { +func (_c *GasEstimator_EstimateLimit_Call) Run(run func()) *GasEstimator_EstimateLimit_Call { _c.Call.Run(func(args mock.Arguments) { run() }) return _c } -func (_c *GasEstimator_EstimateGasLimit_Call) Return(_a0 bool) *GasEstimator_EstimateGasLimit_Call { +func (_c *GasEstimator_EstimateLimit_Call) Return(_a0 bool) *GasEstimator_EstimateLimit_Call { _c.Call.Return(_a0) return _c } -func (_c *GasEstimator_EstimateGasLimit_Call) RunAndReturn(run func() bool) *GasEstimator_EstimateGasLimit_Call { +func (_c *GasEstimator_EstimateLimit_Call) RunAndReturn(run func() bool) *GasEstimator_EstimateLimit_Call { _c.Call.Return(run) return _c } diff --git a/core/chains/evm/config/toml/config.go b/core/chains/evm/config/toml/config.go index 99e61a394b..0e823ffdda 100644 --- a/core/chains/evm/config/toml/config.go +++ b/core/chains/evm/config/toml/config.go @@ -549,12 +549,12 @@ type GasEstimator struct { PriceMax *assets.Wei PriceMin *assets.Wei - LimitDefault *uint64 - LimitMax *uint64 - LimitMultiplier *decimal.Decimal - LimitTransfer *uint64 - LimitJobType GasLimitJobType `toml:",omitempty"` - EstimateGasLimit *bool + LimitDefault *uint64 + LimitMax *uint64 + LimitMultiplier *decimal.Decimal + LimitTransfer *uint64 + LimitJobType GasLimitJobType `toml:",omitempty"` + EstimateLimit *bool BumpMin *assets.Wei BumpPercent *uint16 @@ -642,8 +642,8 @@ func (e *GasEstimator) setFrom(f *GasEstimator) { if v := f.LimitTransfer; v != nil { e.LimitTransfer = v } - if v := f.EstimateGasLimit; v != nil { - e.EstimateGasLimit = v + if v := f.EstimateLimit; v != nil { + e.EstimateLimit = v } if v := f.PriceDefault; v != nil { e.PriceDefault = v diff --git a/core/chains/evm/config/toml/defaults/fallback.toml b/core/chains/evm/config/toml/defaults/fallback.toml index 71da1df208..be3b19677d 100644 --- a/core/chains/evm/config/toml/defaults/fallback.toml +++ b/core/chains/evm/config/toml/defaults/fallback.toml @@ -48,7 +48,7 @@ EIP1559DynamicFees = false FeeCapDefault = '100 gwei' TipCapDefault = '1' TipCapMin = '1' -EstimateGasLimit = false +EstimateLimit = false [GasEstimator.BlockHistory] BatchSize = 25 diff --git a/core/chains/evm/gas/helpers_test.go b/core/chains/evm/gas/helpers_test.go index d6af645fe8..ae93d9e8c7 100644 --- a/core/chains/evm/gas/helpers_test.go +++ b/core/chains/evm/gas/helpers_test.go @@ -157,7 +157,7 @@ type MockGasEstimatorConfig struct { FeeCapDefaultF *assets.Wei LimitMaxF uint64 ModeF string - EstimateGasLimitF bool + EstimateLimitF bool } func NewMockGasConfig() *MockGasEstimatorConfig { @@ -216,6 +216,6 @@ func (m *MockGasEstimatorConfig) Mode() string { return m.ModeF } -func (m *MockGasEstimatorConfig) EstimateGasLimit() bool { - return m.EstimateGasLimitF +func (m *MockGasEstimatorConfig) EstimateLimit() bool { + return m.EstimateLimitF } diff --git a/core/chains/evm/gas/models.go b/core/chains/evm/gas/models.go index 36e42771af..af569a1332 100644 --- a/core/chains/evm/gas/models.go +++ b/core/chains/evm/gas/models.go @@ -26,7 +26,7 @@ import ( evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" ) -// EstimateGasBuffer is a multiplier applied to estimated gas when the EstimateGasLimit feature is enabled +// EstimateGasBuffer is a multiplier applied to estimated gas when the EstimateLimit feature is enabled const EstimateGasBuffer = float32(1.15) // EvmFeeEstimator provides a unified interface that wraps EvmEstimator and can determine if legacy or dynamic fee estimation should be used @@ -74,7 +74,7 @@ func NewEstimator(lggr logger.Logger, ethClient feeEstimatorClient, cfg Config, "tipCapMin", geCfg.TipCapMin(), "priceMax", geCfg.PriceMax(), "priceMin", geCfg.PriceMin(), - "estimateGasLimit", geCfg.EstimateGasLimit(), + "estimateLimit", geCfg.EstimateLimit(), ) df := geCfg.EIP1559DynamicFees() @@ -353,8 +353,8 @@ func (e *evmFeeEstimator) estimateFeeLimit(ctx context.Context, feeLimit uint64, if err != nil { return estimatedFeeLimit, err } - // Use provided fee limit by default if EstimateGasLimit is disabled - if !e.geCfg.EstimateGasLimit() { + // Use provided fee limit by default if EstimateLimit is disabled + if !e.geCfg.EstimateLimit() { return providedGasLimit, nil } // Create call msg for gas limit estimation @@ -418,7 +418,7 @@ type GasEstimatorConfig interface { PriceMin() *assets.Wei PriceMax() *assets.Wei Mode() string - EstimateGasLimit() bool + EstimateLimit() bool } type BlockHistoryConfig interface { diff --git a/core/chains/evm/gas/models_test.go b/core/chains/evm/gas/models_test.go index ea5e53c228..f2afc26c85 100644 --- a/core/chains/evm/gas/models_test.go +++ b/core/chains/evm/gas/models_test.go @@ -261,7 +261,7 @@ func TestWrappedEvmEstimator(t *testing.T) { lggr := logger.Test(t) // expect legacy fee data dynamicFees := false - geCfg.EstimateGasLimitF = true + geCfg.EstimateLimitF = true ethClient := testutils.NewEthClientMockWithDefaultChain(t) ethClient.On("EstimateGas", mock.Anything, mock.Anything).Return(estimatedGasLimit, nil).Twice() estimator := gas.NewEvmFeeEstimator(lggr, getRootEst, dynamicFees, geCfg, ethClient) @@ -288,7 +288,7 @@ func TestWrappedEvmEstimator(t *testing.T) { lggr := logger.Test(t) // expect legacy fee data dynamicFees := false - geCfg.EstimateGasLimitF = true + geCfg.EstimateLimitF = true ethClient := testutils.NewEthClientMockWithDefaultChain(t) ethClient.On("EstimateGas", mock.Anything, mock.Anything).Return(estimatedGasLimit, nil).Twice() estimator := gas.NewEvmFeeEstimator(lggr, getRootEst, dynamicFees, geCfg, ethClient) @@ -306,7 +306,7 @@ func TestWrappedEvmEstimator(t *testing.T) { estimatedGasLimit := uint64(15) // same as provided limit lggr := logger.Test(t) dynamicFees := false // expect legacy fee data - geCfg.EstimateGasLimitF = true + geCfg.EstimateLimitF = true ethClient := testutils.NewEthClientMockWithDefaultChain(t) ethClient.On("EstimateGas", mock.Anything, mock.Anything).Return(estimatedGasLimit, nil).Twice() estimator := gas.NewEvmFeeEstimator(lggr, getRootEst, dynamicFees, geCfg, ethClient) @@ -331,7 +331,7 @@ func TestWrappedEvmEstimator(t *testing.T) { lggr := logger.Test(t) // expect legacy fee data dynamicFees := false - geCfg.EstimateGasLimitF = true + geCfg.EstimateLimitF = true ethClient := testutils.NewEthClientMockWithDefaultChain(t) ethClient.On("EstimateGas", mock.Anything, mock.Anything).Return(uint64(0), errors.New("something broke")).Twice() estimator := gas.NewEvmFeeEstimator(lggr, getRootEst, dynamicFees, geCfg, ethClient) @@ -362,7 +362,7 @@ func TestWrappedEvmEstimator(t *testing.T) { lggr := logger.Test(t) // expect legacy fee data dynamicFees := false - geCfg.EstimateGasLimitF = true + geCfg.EstimateLimitF = true ethClient := testutils.NewEthClientMockWithDefaultChain(t) ethClient.On("EstimateGas", mock.Anything, mock.Anything).Return(estimatedGasLimit, nil).Twice() estimator := gas.NewEvmFeeEstimator(lggr, getRootEst, dynamicFees, geCfg, ethClient) @@ -392,7 +392,7 @@ func TestWrappedEvmEstimator(t *testing.T) { lggr := logger.Test(t) // expect legacy fee data dynamicFees := false - geCfg.EstimateGasLimitF = true + geCfg.EstimateLimitF = true ethClient := testutils.NewEthClientMockWithDefaultChain(t) ethClient.On("EstimateGas", mock.Anything, mock.Anything).Return(uint64(0), errors.New("something broke")).Twice() estimator := gas.NewEvmFeeEstimator(lggr, getRootEst, dynamicFees, geCfg, ethClient) diff --git a/core/chains/evm/txmgr/broadcaster_test.go b/core/chains/evm/txmgr/broadcaster_test.go index 41f50f4434..514d533159 100644 --- a/core/chains/evm/txmgr/broadcaster_test.go +++ b/core/chains/evm/txmgr/broadcaster_test.go @@ -1676,7 +1676,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_GasEstimationError(t *testing.T) db := pgtest.NewSqlxDB(t) cfg := configtest.NewTestGeneralConfig(t) - cfg.EVMConfigs()[0].GasEstimator.EstimateGasLimit = ptr(true) // Enabled gas limit estimation + cfg.EVMConfigs()[0].GasEstimator.EstimateLimit = ptr(true) // Enabled gas limit estimation limitMultiplier := float32(1.25) cfg.EVMConfigs()[0].GasEstimator.LimitMultiplier = ptr(decimal.NewFromFloat32(limitMultiplier)) // Set LimitMultiplier for the buffer txStore := cltest.NewTestTxStore(t, db) diff --git a/core/chains/evm/txmgr/test_helpers.go b/core/chains/evm/txmgr/test_helpers.go index a4f326d480..963c608b53 100644 --- a/core/chains/evm/txmgr/test_helpers.go +++ b/core/chains/evm/txmgr/test_helpers.go @@ -89,7 +89,7 @@ func (g *TestGasEstimatorConfig) LimitTransfer() uint64 { return 42 } func (g *TestGasEstimatorConfig) PriceMax() *assets.Wei { return assets.NewWeiI(42) } func (g *TestGasEstimatorConfig) PriceMin() *assets.Wei { return assets.NewWeiI(42) } func (g *TestGasEstimatorConfig) Mode() string { return "FixedPrice" } -func (g *TestGasEstimatorConfig) EstimateGasLimit() bool { return false } +func (g *TestGasEstimatorConfig) EstimateLimit() bool { return false } func (g *TestGasEstimatorConfig) LimitJobType() evmconfig.LimitJobType { return &TestLimitJobTypeConfig{} } diff --git a/core/config/docs/chains-evm.toml b/core/config/docs/chains-evm.toml index 3e54d2cd0f..385432e12c 100644 --- a/core/config/docs/chains-evm.toml +++ b/core/config/docs/chains-evm.toml @@ -194,8 +194,8 @@ LimitMax = 8_000_000 # Default LimitMultiplier = '1.0' # Default # LimitTransfer is the gas limit used for an ordinary ETH transfer. LimitTransfer = 21_000 # Default -# EstimateGasLimit enables estimating gas limits for transactions. This feature respects the gas limit provided during transaction creation as an upper bound. -EstimateGasLimit = false # Default +# EstimateLimit enables estimating gas limits for transactions. This feature respects the gas limit provided during transaction creation as an upper bound. +EstimateLimit = false # Default # BumpMin is the minimum fixed amount of wei by which gas is bumped on each transaction attempt. BumpMin = '5 gwei' # Default # BumpPercent is the percentage by which to bump gas on a transaction that has exceeded `BumpThreshold`. The larger of `BumpPercent` and `BumpMin` is taken for gas bumps. diff --git a/core/services/chainlink/config_test.go b/core/services/chainlink/config_test.go index 3ded57cf76..2aae93e45d 100644 --- a/core/services/chainlink/config_test.go +++ b/core/services/chainlink/config_test.go @@ -520,7 +520,7 @@ func TestConfig_Marshal(t *testing.T) { LimitMax: ptr[uint64](17), LimitMultiplier: mustDecimal("1.234"), LimitTransfer: ptr[uint64](100), - EstimateGasLimit: ptr(false), + EstimateLimit: ptr(false), TipCapDefault: assets.NewWeiI(2), TipCapMin: assets.NewWeiI(1), PriceDefault: assets.NewWeiI(math.MaxInt64), @@ -1025,7 +1025,7 @@ LimitDefault = 12 LimitMax = 17 LimitMultiplier = '1.234' LimitTransfer = 100 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '100 wei' BumpPercent = 10 BumpThreshold = 6 diff --git a/core/services/chainlink/testdata/config-full.toml b/core/services/chainlink/testdata/config-full.toml index ea62617018..08f688dfac 100644 --- a/core/services/chainlink/testdata/config-full.toml +++ b/core/services/chainlink/testdata/config-full.toml @@ -316,7 +316,7 @@ LimitDefault = 12 LimitMax = 17 LimitMultiplier = '1.234' LimitTransfer = 100 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '100 wei' BumpPercent = 10 BumpThreshold = 6 diff --git a/core/services/chainlink/testdata/config-multi-chain-effective.toml b/core/services/chainlink/testdata/config-multi-chain-effective.toml index dacb04fe9d..4de06be86d 100644 --- a/core/services/chainlink/testdata/config-multi-chain-effective.toml +++ b/core/services/chainlink/testdata/config-multi-chain-effective.toml @@ -303,7 +303,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -404,7 +404,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -499,7 +499,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '20 gwei' BumpPercent = 20 BumpThreshold = 5 diff --git a/core/web/resolver/testdata/config-full.toml b/core/web/resolver/testdata/config-full.toml index 668ca74ced..d046a2ab8b 100644 --- a/core/web/resolver/testdata/config-full.toml +++ b/core/web/resolver/testdata/config-full.toml @@ -316,7 +316,7 @@ LimitDefault = 12 LimitMax = 17 LimitMultiplier = '1.234' LimitTransfer = 100 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '100 wei' BumpPercent = 10 BumpThreshold = 6 diff --git a/core/web/resolver/testdata/config-multi-chain-effective.toml b/core/web/resolver/testdata/config-multi-chain-effective.toml index 108dd401a7..df335e0474 100644 --- a/core/web/resolver/testdata/config-multi-chain-effective.toml +++ b/core/web/resolver/testdata/config-multi-chain-effective.toml @@ -303,7 +303,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -404,7 +404,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -499,7 +499,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '20 gwei' BumpPercent = 20 BumpThreshold = 5 diff --git a/docs/CONFIG.md b/docs/CONFIG.md index 7153b8cadd..f0c5b1808b 100644 --- a/docs/CONFIG.md +++ b/docs/CONFIG.md @@ -1818,7 +1818,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -1913,7 +1913,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -2008,7 +2008,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -2103,7 +2103,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -2199,7 +2199,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '100 wei' BumpPercent = 20 BumpThreshold = 3 @@ -2294,7 +2294,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -2389,7 +2389,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -2485,7 +2485,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -2580,7 +2580,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 5 @@ -2674,7 +2674,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -2861,7 +2861,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -2956,7 +2956,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 5 @@ -3052,7 +3052,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -3147,7 +3147,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 5 @@ -3242,7 +3242,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '20 gwei' BumpPercent = 20 BumpThreshold = 5 @@ -3337,7 +3337,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '20 mwei' BumpPercent = 40 BumpThreshold = 3 @@ -3432,7 +3432,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '100 mwei' BumpPercent = 40 BumpThreshold = 3 @@ -3527,7 +3527,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -3622,7 +3622,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '100 wei' BumpPercent = 20 BumpThreshold = 3 @@ -3717,7 +3717,7 @@ LimitDefault = 100000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -3812,7 +3812,7 @@ LimitDefault = 2500000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -3907,7 +3907,7 @@ LimitDefault = 2500000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -4003,7 +4003,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '100 wei' BumpPercent = 20 BumpThreshold = 3 @@ -4098,7 +4098,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -4380,7 +4380,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 5 @@ -4475,7 +4475,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -4570,7 +4570,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '100 mwei' BumpPercent = 40 BumpThreshold = 3 @@ -4665,7 +4665,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -4760,7 +4760,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -4854,7 +4854,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 0 @@ -4949,7 +4949,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '20 mwei' BumpPercent = 40 BumpThreshold = 3 @@ -5044,7 +5044,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '100 wei' BumpPercent = 20 BumpThreshold = 3 @@ -5139,7 +5139,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '20 mwei' BumpPercent = 40 BumpThreshold = 3 @@ -5234,7 +5234,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -5423,7 +5423,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 5 @@ -5518,7 +5518,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '100 wei' BumpPercent = 20 BumpThreshold = 3 @@ -5613,7 +5613,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -5709,7 +5709,7 @@ LimitDefault = 8000000 LimitMax = 1000000000 LimitMultiplier = '1' LimitTransfer = 21000 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 5 @@ -5805,7 +5805,7 @@ LimitDefault = 8000000 LimitMax = 1000000000 LimitMultiplier = '1' LimitTransfer = 21000 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 5 @@ -5996,7 +5996,7 @@ LimitDefault = 8000000 LimitMax = 1000000000 LimitMultiplier = '1' LimitTransfer = 21000 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 5 @@ -6091,7 +6091,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '2 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -6186,7 +6186,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -6281,7 +6281,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -6376,7 +6376,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '2 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -6470,7 +6470,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 40 BumpThreshold = 3 @@ -6564,7 +6564,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -6658,7 +6658,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 40 BumpThreshold = 3 @@ -6753,7 +6753,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -6942,7 +6942,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '20 gwei' BumpPercent = 20 BumpThreshold = 5 @@ -7036,7 +7036,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '20 gwei' BumpPercent = 20 BumpThreshold = 5 @@ -7226,7 +7226,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '100 wei' BumpPercent = 20 BumpThreshold = 3 @@ -7322,7 +7322,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '100 wei' BumpPercent = 20 BumpThreshold = 3 @@ -7418,7 +7418,7 @@ LimitDefault = 8000000 LimitMax = 1000000000 LimitMultiplier = '1' LimitTransfer = 21000 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 5 @@ -7514,7 +7514,7 @@ LimitDefault = 8000000 LimitMax = 1000000000 LimitMultiplier = '1' LimitTransfer = 21000 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 5 @@ -7610,7 +7610,7 @@ LimitDefault = 8000000 LimitMax = 1000000000 LimitMultiplier = '1' LimitTransfer = 21000 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 5 @@ -7705,7 +7705,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '1 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -7800,7 +7800,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '1 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -7895,7 +7895,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -7990,7 +7990,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '100 wei' BumpPercent = 20 BumpThreshold = 3 @@ -8180,7 +8180,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -8275,7 +8275,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -8638,7 +8638,7 @@ LimitDefault = 8_000_000 # Default LimitMax = 8_000_000 # Default LimitMultiplier = '1.0' # Default LimitTransfer = 21_000 # Default -EstimateGasLimit = false # Default +EstimateLimit = false # Default BumpMin = '5 gwei' # Default BumpPercent = 20 # Default BumpThreshold = 3 # Default @@ -8733,11 +8733,11 @@ LimitTransfer = 21_000 # Default ``` LimitTransfer is the gas limit used for an ordinary ETH transfer. -### EstimateGasLimit +### EstimateLimit ```toml -EstimateGasLimit = false # Default +EstimateLimit = false # Default ``` -EstimateGasLimit enables estimating gas limits for transactions. This feature respects the gas limit provided during transaction creation as an upper bound. +EstimateLimit enables estimating gas limits for transactions. This feature respects the gas limit provided during transaction creation as an upper bound. ### BumpMin ```toml diff --git a/testdata/scripts/node/validate/disk-based-logging-disabled.txtar b/testdata/scripts/node/validate/disk-based-logging-disabled.txtar index 135e062cf7..fbcb4725d6 100644 --- a/testdata/scripts/node/validate/disk-based-logging-disabled.txtar +++ b/testdata/scripts/node/validate/disk-based-logging-disabled.txtar @@ -359,7 +359,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 diff --git a/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar b/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar index 9fa53d50b6..5fa31dd1aa 100644 --- a/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar +++ b/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar @@ -359,7 +359,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 diff --git a/testdata/scripts/node/validate/disk-based-logging.txtar b/testdata/scripts/node/validate/disk-based-logging.txtar index ad38875f18..832185c53f 100644 --- a/testdata/scripts/node/validate/disk-based-logging.txtar +++ b/testdata/scripts/node/validate/disk-based-logging.txtar @@ -359,7 +359,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 diff --git a/testdata/scripts/node/validate/invalid.txtar b/testdata/scripts/node/validate/invalid.txtar index 6baa4ce92c..972c6c10fc 100644 --- a/testdata/scripts/node/validate/invalid.txtar +++ b/testdata/scripts/node/validate/invalid.txtar @@ -349,7 +349,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 diff --git a/testdata/scripts/node/validate/valid.txtar b/testdata/scripts/node/validate/valid.txtar index 985cf03970..c7b5261d26 100644 --- a/testdata/scripts/node/validate/valid.txtar +++ b/testdata/scripts/node/validate/valid.txtar @@ -356,7 +356,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 -EstimateGasLimit = false +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 From a684f360742b7371921a29d039ef64027e0639b4 Mon Sep 17 00:00:00 2001 From: Dylan Tinianov <dylantinianov@gmail.com> Date: Thu, 8 Aug 2024 10:33:44 -0400 Subject: [PATCH 108/115] Add Mantle errors (#14053) * Add Mantle errors * Add tests for Mantle errors * changeset * Update seven-kiwis-run.md --- .changeset/seven-kiwis-run.md | 5 +++++ core/chains/evm/client/errors_test.go | 3 +++ 2 files changed, 8 insertions(+) create mode 100644 .changeset/seven-kiwis-run.md diff --git a/.changeset/seven-kiwis-run.md b/.changeset/seven-kiwis-run.md new file mode 100644 index 0000000000..3b56117c46 --- /dev/null +++ b/.changeset/seven-kiwis-run.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +Added custom client error messages for Mantle to capture InsufficientEth and Fatal errors. #added diff --git a/core/chains/evm/client/errors_test.go b/core/chains/evm/client/errors_test.go index 47e8ee610b..a7e9ebac10 100644 --- a/core/chains/evm/client/errors_test.go +++ b/core/chains/evm/client/errors_test.go @@ -215,6 +215,7 @@ func Test_Eth_Errors(t *testing.T) { {"insufficient funds for gas + value. balance: 42719769622667482000, fee: 48098250000000, value: 42719769622667482000", true, "celo"}, {"client error insufficient eth", true, "tomlConfig"}, {"transaction would cause overdraft", true, "Geth"}, + {"failed to forward tx to sequencer, please try again. Error message: 'insufficient funds for gas * price + value'", true, "Mantle"}, } for _, test := range tests { err = evmclient.NewSendErrorS(test.message) @@ -400,6 +401,8 @@ func Test_Eth_Errors_Fatal(t *testing.T) { {"Failed to serialize transaction: max priority fee per gas higher than 2^64-1", true, "zkSync"}, {"Failed to serialize transaction: oversized data. max: 1000000; actual: 1000000", true, "zkSync"}, + {"failed to forward tx to sequencer, please try again. Error message: 'invalid sender'", true, "Mantle"}, + {"client error fatal", true, "tomlConfig"}, {"invalid chain id for signer", true, "Treasure"}, } From f40af8028441b2e258c0103b118b74fd7986ab81 Mon Sep 17 00:00:00 2001 From: Matthew Romage <33700623+ma33r@users.noreply.github.com> Date: Thu, 22 Aug 2024 15:31:00 -0400 Subject: [PATCH 109/115] Changed Optimism L1 Oracle to support Mantle (#14160) * edited op stack oracle to include tokenRatio for Mantle * typo fix * fixed syntax errors * fixed compilation errors in test * added unit tests for Mantle oracle changes * typo fix * added changeset file * added hashtag to changeset * changed unit test to include new chaintype * changed test to include new chaintype * typo fix * addressed alphabetical order and error issues * used batch call instead of separate calls for L1 Base Fee * added test cases for RPC errors to Mantle --- .changeset/two-mugs-complain.md | 5 ++ core/chains/evm/config/chaintype/chaintype.go | 6 +- core/chains/evm/gas/rollups/l1_oracle.go | 4 +- core/chains/evm/gas/rollups/l1_oracle_abi.go | 1 + core/chains/evm/gas/rollups/op_l1_oracle.go | 87 +++++++++++++++++- .../evm/gas/rollups/op_l1_oracle_test.go | 88 +++++++++++++++++++ core/services/chainlink/config_test.go | 4 +- 7 files changed, 188 insertions(+), 7 deletions(-) create mode 100644 .changeset/two-mugs-complain.md diff --git a/.changeset/two-mugs-complain.md b/.changeset/two-mugs-complain.md new file mode 100644 index 0000000000..77cdcbfe9e --- /dev/null +++ b/.changeset/two-mugs-complain.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +Edited the Optimism Stack L1 Oracle to add support for Mantle #added diff --git a/core/chains/evm/config/chaintype/chaintype.go b/core/chains/evm/config/chaintype/chaintype.go index 07ea620624..35dd214b1f 100644 --- a/core/chains/evm/config/chaintype/chaintype.go +++ b/core/chains/evm/config/chaintype/chaintype.go @@ -14,6 +14,7 @@ const ( ChainGnosis ChainType = "gnosis" ChainHedera ChainType = "hedera" ChainKroma ChainType = "kroma" + ChainMantle ChainType = "mantle" ChainMetis ChainType = "metis" ChainOptimismBedrock ChainType = "optimismBedrock" ChainScroll ChainType = "scroll" @@ -37,7 +38,7 @@ func (c ChainType) IsL2() bool { func (c ChainType) IsValid() bool { switch c { - case "", ChainArbitrum, ChainAstar, ChainCelo, ChainGnosis, ChainHedera, ChainKroma, ChainMetis, ChainOptimismBedrock, ChainScroll, ChainWeMix, ChainXLayer, ChainZkEvm, ChainZkSync: + case "", ChainArbitrum, ChainAstar, ChainCelo, ChainGnosis, ChainHedera, ChainKroma, ChainMantle, ChainMetis, ChainOptimismBedrock, ChainScroll, ChainWeMix, ChainXLayer, ChainZkEvm, ChainZkSync: return true } return false @@ -57,6 +58,8 @@ func ChainTypeFromSlug(slug string) ChainType { return ChainHedera case "kroma": return ChainKroma + case "mantle": + return ChainMantle case "metis": return ChainMetis case "optimismBedrock": @@ -129,6 +132,7 @@ var ErrInvalidChainType = fmt.Errorf("must be one of %s or omitted", strings.Joi string(ChainGnosis), string(ChainHedera), string(ChainKroma), + string(ChainMantle), string(ChainMetis), string(ChainOptimismBedrock), string(ChainScroll), diff --git a/core/chains/evm/gas/rollups/l1_oracle.go b/core/chains/evm/gas/rollups/l1_oracle.go index f707fab684..e1249fdb7e 100644 --- a/core/chains/evm/gas/rollups/l1_oracle.go +++ b/core/chains/evm/gas/rollups/l1_oracle.go @@ -43,7 +43,7 @@ const ( PollPeriod = 6 * time.Second ) -var supportedChainTypes = []chaintype.ChainType{chaintype.ChainArbitrum, chaintype.ChainOptimismBedrock, chaintype.ChainKroma, chaintype.ChainScroll, chaintype.ChainZkSync} +var supportedChainTypes = []chaintype.ChainType{chaintype.ChainArbitrum, chaintype.ChainOptimismBedrock, chaintype.ChainKroma, chaintype.ChainScroll, chaintype.ChainZkSync, chaintype.ChainMantle} func IsRollupWithL1Support(chainType chaintype.ChainType) bool { return slices.Contains(supportedChainTypes, chainType) @@ -56,7 +56,7 @@ func NewL1GasOracle(lggr logger.Logger, ethClient l1OracleClient, chainType chai var l1Oracle L1Oracle var err error switch chainType { - case chaintype.ChainOptimismBedrock, chaintype.ChainKroma, chaintype.ChainScroll: + case chaintype.ChainOptimismBedrock, chaintype.ChainKroma, chaintype.ChainScroll, chaintype.ChainMantle: l1Oracle, err = NewOpStackL1GasOracle(lggr, ethClient, chainType) case chaintype.ChainArbitrum: l1Oracle, err = NewArbitrumL1GasOracle(lggr, ethClient) diff --git a/core/chains/evm/gas/rollups/l1_oracle_abi.go b/core/chains/evm/gas/rollups/l1_oracle_abi.go index fa5d9c8539..848957ce53 100644 --- a/core/chains/evm/gas/rollups/l1_oracle_abi.go +++ b/core/chains/evm/gas/rollups/l1_oracle_abi.go @@ -19,3 +19,4 @@ const OPBaseFeeScalarAbiString = `[{"inputs":[],"name":"baseFeeScalar","outputs" const OPBlobBaseFeeAbiString = `[{"inputs":[],"name":"blobBaseFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]` const OPBlobBaseFeeScalarAbiString = `[{"inputs":[],"name":"blobBaseFeeScalar","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"}]` const OPDecimalsAbiString = `[{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"}]` +const MantleTokenRatioAbiString = `[{"inputs":[],"name":"tokenRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]` diff --git a/core/chains/evm/gas/rollups/op_l1_oracle.go b/core/chains/evm/gas/rollups/op_l1_oracle.go index 6805cd7095..1b93f8fc3f 100644 --- a/core/chains/evm/gas/rollups/op_l1_oracle.go +++ b/core/chains/evm/gas/rollups/op_l1_oracle.go @@ -50,6 +50,7 @@ type optimismL1Oracle struct { blobBaseFeeCalldata []byte blobBaseFeeScalarCalldata []byte decimalsCalldata []byte + tokenRatioCalldata []byte isEcotoneCalldata []byte isEcotoneMethodAbi abi.ABI isFjordCalldata []byte @@ -87,7 +88,11 @@ const ( // decimals is a hex encoded call to: // `function decimals() public pure returns (uint256);` decimalsMethod = "decimals" - // OPGasOracleAddress is the address of the precompiled contract that exists on Optimism and Base. + // tokenRatio fetches the tokenRatio used for Mantle's gas price calculation + // tokenRatio is a hex encoded call to: + // `function tokenRatio() public pure returns (uint256);` + tokenRatioMethod = "tokenRatio" + // OPGasOracleAddress is the address of the precompiled contract that exists on Optimism, Base and Mantle. OPGasOracleAddress = "0x420000000000000000000000000000000000000F" // KromaGasOracleAddress is the address of the precompiled contract that exists on Kroma. KromaGasOracleAddress = "0x4200000000000000000000000000000000000005" @@ -98,7 +103,7 @@ const ( func NewOpStackL1GasOracle(lggr logger.Logger, ethClient l1OracleClient, chainType chaintype.ChainType) (*optimismL1Oracle, error) { var precompileAddress string switch chainType { - case chaintype.ChainOptimismBedrock: + case chaintype.ChainOptimismBedrock, chaintype.ChainMantle: precompileAddress = OPGasOracleAddress case chaintype.ChainKroma: precompileAddress = KromaGasOracleAddress @@ -187,6 +192,16 @@ func newOpStackL1GasOracle(lggr logger.Logger, ethClient l1OracleClient, chainTy return nil, fmt.Errorf("failed to parse GasPriceOracle %s() calldata for chain: %s; %w", decimalsMethod, chainType, err) } + // Encode calldata for tokenRatio method + tokenRatioMethodAbi, err := abi.JSON(strings.NewReader(MantleTokenRatioAbiString)) + if err != nil { + return nil, fmt.Errorf("failed to parse GasPriceOracle %s() method ABI for chain: %s; %w", tokenRatioMethod, chainType, err) + } + tokenRatioCalldata, err := tokenRatioMethodAbi.Pack(tokenRatioMethod) + if err != nil { + return nil, fmt.Errorf("failed to parse GasPriceOracle %s() calldata for chain: %s; %w", tokenRatioMethod, chainType, err) + } + return &optimismL1Oracle{ client: ethClient, pollPeriod: PollPeriod, @@ -208,6 +223,7 @@ func newOpStackL1GasOracle(lggr logger.Logger, ethClient l1OracleClient, chainTy blobBaseFeeCalldata: blobBaseFeeCalldata, blobBaseFeeScalarCalldata: blobBaseFeeScalarCalldata, decimalsCalldata: decimalsCalldata, + tokenRatioCalldata: tokenRatioCalldata, isEcotoneCalldata: isEcotoneCalldata, isEcotoneMethodAbi: isEcotoneMethodAbi, isFjordCalldata: isFjordCalldata, @@ -346,6 +362,10 @@ func (o *optimismL1Oracle) GetGasCost(ctx context.Context, tx *gethtypes.Transac } func (o *optimismL1Oracle) GetDAGasPrice(ctx context.Context) (*big.Int, error) { + if o.chainType == chaintype.ChainMantle { + return o.getMantleGasPrice(ctx) + } + err := o.checkForUpgrade(ctx) if err != nil { return nil, err @@ -443,6 +463,69 @@ func (o *optimismL1Oracle) getV1GasPrice(ctx context.Context) (*big.Int, error) return new(big.Int).SetBytes(b), nil } +// Returns the gas price for Mantle. The formula is the same as Optimism Bedrock (getV1GasPrice), but the tokenRatio parameter is multiplied +func (o *optimismL1Oracle) getMantleGasPrice(ctx context.Context) (*big.Int, error) { + // call oracle to get l1BaseFee and tokenRatio + rpcBatchCalls := []rpc.BatchElem{ + { + Method: "eth_call", + Args: []any{ + map[string]interface{}{ + "from": common.Address{}, + "to": o.l1OracleAddress, + "data": hexutil.Bytes(o.l1BaseFeeCalldata), + }, + "latest", + }, + Result: new(string), + }, + { + Method: "eth_call", + Args: []any{ + map[string]interface{}{ + "from": common.Address{}, + "to": o.l1OracleAddress, + "data": hexutil.Bytes(o.tokenRatioCalldata), + }, + "latest", + }, + Result: new(string), + }, + } + + err := o.client.BatchCallContext(ctx, rpcBatchCalls) + if err != nil { + return nil, fmt.Errorf("fetch gas price parameters batch call failed: %w", err) + } + if rpcBatchCalls[0].Error != nil { + return nil, fmt.Errorf("%s call failed in a batch: %w", l1BaseFeeMethod, err) + } + if rpcBatchCalls[1].Error != nil { + return nil, fmt.Errorf("%s call failed in a batch: %w", tokenRatioMethod, err) + } + + // Extract values from responses + l1BaseFeeResult := *(rpcBatchCalls[0].Result.(*string)) + tokenRatioResult := *(rpcBatchCalls[1].Result.(*string)) + + // Decode the responses into bytes + l1BaseFeeBytes, err := hexutil.Decode(l1BaseFeeResult) + if err != nil { + return nil, fmt.Errorf("failed to decode %s rpc result: %w", l1BaseFeeMethod, err) + } + tokenRatioBytes, err := hexutil.Decode(tokenRatioResult) + if err != nil { + return nil, fmt.Errorf("failed to decode %s rpc result: %w", tokenRatioMethod, err) + } + + // Convert bytes to big int for calculations + l1BaseFee := new(big.Int).SetBytes(l1BaseFeeBytes) + tokenRatio := new(big.Int).SetBytes(tokenRatioBytes) + + // multiply l1BaseFee and tokenRatio and return + return new(big.Int).Mul(l1BaseFee, tokenRatio), nil +} + // Returns the scaled gas price using baseFeeScalar, l1BaseFee, blobBaseFeeScalar, and blobBaseFee fields from the oracle // Confirmed the same calculation is used to determine gas price for both Ecotone and Fjord func (o *optimismL1Oracle) getEcotoneFjordGasPrice(ctx context.Context) (*big.Int, error) { diff --git a/core/chains/evm/gas/rollups/op_l1_oracle_test.go b/core/chains/evm/gas/rollups/op_l1_oracle_test.go index f5f009f1ea..88bb96534d 100644 --- a/core/chains/evm/gas/rollups/op_l1_oracle_test.go +++ b/core/chains/evm/gas/rollups/op_l1_oracle_test.go @@ -111,6 +111,94 @@ func TestOPL1Oracle_ReadV1GasPrice(t *testing.T) { } } +func TestOPL1Oracle_ReadMantleGasPrice(t *testing.T) { + l1BaseFee := big.NewInt(100) + tokenRatio := big.NewInt(40) + oracleAddress := common.HexToAddress("0x1234").String() + + t.Parallel() + t.Run("correctly fetches gas price if chain is Mantle", func(t *testing.T) { + // Encode calldata for l1BaseFee method + l1BaseFeeMethodAbi, err := abi.JSON(strings.NewReader(L1BaseFeeAbiString)) + require.NoError(t, err) + l1BaseFeeCalldata, err := l1BaseFeeMethodAbi.Pack(l1BaseFeeMethod) + require.NoError(t, err) + + // Encode calldata for tokenRatio method + tokenRatioMethodAbi, err := abi.JSON(strings.NewReader(MantleTokenRatioAbiString)) + require.NoError(t, err) + tokenRatioCalldata, err := tokenRatioMethodAbi.Pack(tokenRatioMethod) + require.NoError(t, err) + + ethClient := mocks.NewL1OracleClient(t) + ethClient.On("BatchCallContext", mock.Anything, mock.IsType([]rpc.BatchElem{})).Run(func(args mock.Arguments) { + rpcElements := args.Get(1).([]rpc.BatchElem) + require.Equal(t, 2, len(rpcElements)) + for _, rE := range rpcElements { + require.Equal(t, "eth_call", rE.Method) + require.Equal(t, oracleAddress, rE.Args[0].(map[string]interface{})["to"]) + require.Equal(t, "latest", rE.Args[1]) + } + require.Equal(t, hexutil.Bytes(l1BaseFeeCalldata), rpcElements[0].Args[0].(map[string]interface{})["data"]) + require.Equal(t, hexutil.Bytes(tokenRatioCalldata), rpcElements[1].Args[0].(map[string]interface{})["data"]) + + res1 := common.BigToHash(l1BaseFee).Hex() + res2 := common.BigToHash(tokenRatio).Hex() + + rpcElements[0].Result = &res1 + rpcElements[1].Result = &res2 + }).Return(nil).Once() + + oracle, err := newOpStackL1GasOracle(logger.Test(t), ethClient, chaintype.ChainMantle, oracleAddress) + require.NoError(t, err) + + gasPrice, err := oracle.GetDAGasPrice(tests.Context(t)) + require.NoError(t, err) + + assert.Equal(t, new(big.Int).Mul(l1BaseFee, tokenRatio), gasPrice) + }) + + t.Run("fetching Mantle price but rpc returns bad data", func(t *testing.T) { + ethClient := mocks.NewL1OracleClient(t) + ethClient.On("BatchCallContext", mock.Anything, mock.IsType([]rpc.BatchElem{})).Run(func(args mock.Arguments) { + rpcElements := args.Get(1).([]rpc.BatchElem) + var badData = "zzz" + rpcElements[0].Result = &badData + rpcElements[1].Result = &badData + }).Return(nil).Once() + + oracle, err := newOpStackL1GasOracle(logger.Test(t), ethClient, chaintype.ChainMantle, oracleAddress) + require.NoError(t, err) + _, err = oracle.GetDAGasPrice(tests.Context(t)) + assert.Error(t, err) + }) + + t.Run("fetching Mantle price but rpc parent call errors", func(t *testing.T) { + ethClient := mocks.NewL1OracleClient(t) + ethClient.On("BatchCallContext", mock.Anything, mock.IsType([]rpc.BatchElem{})).Return(fmt.Errorf("revert")).Once() + + oracle, err := newOpStackL1GasOracle(logger.Test(t), ethClient, chaintype.ChainMantle, oracleAddress) + require.NoError(t, err) + _, err = oracle.GetDAGasPrice(tests.Context(t)) + assert.Error(t, err) + }) + + t.Run("fetching Mantle price but one of the sub rpc call errors", func(t *testing.T) { + ethClient := mocks.NewL1OracleClient(t) + ethClient.On("BatchCallContext", mock.Anything, mock.IsType([]rpc.BatchElem{})).Run(func(args mock.Arguments) { + rpcElements := args.Get(1).([]rpc.BatchElem) + res := common.BigToHash(l1BaseFee).Hex() + rpcElements[0].Result = &res + rpcElements[1].Error = fmt.Errorf("revert") + }).Return(nil).Once() + + oracle, err := newOpStackL1GasOracle(logger.Test(t), ethClient, chaintype.ChainMantle, oracleAddress) + require.NoError(t, err) + _, err = oracle.GetDAGasPrice(tests.Context(t)) + assert.Error(t, err) + }) +} + func setupUpgradeCheck(t *testing.T, oracleAddress string, isFjord, isEcotone bool) *mocks.L1OracleClient { trueHex := "0x0000000000000000000000000000000000000000000000000000000000000001" falseHex := "0x0000000000000000000000000000000000000000000000000000000000000000" diff --git a/core/services/chainlink/config_test.go b/core/services/chainlink/config_test.go index 2aae93e45d..76150d2680 100644 --- a/core/services/chainlink/config_test.go +++ b/core/services/chainlink/config_test.go @@ -1306,7 +1306,7 @@ func TestConfig_Validate(t *testing.T) { - 1: 10 errors: - ChainType: invalid value (Foo): must not be set with this chain id - Nodes: missing: must have at least one node - - ChainType: invalid value (Foo): must be one of arbitrum, astar, celo, gnosis, hedera, kroma, metis, optimismBedrock, scroll, wemix, xlayer, zkevm, zksync or omitted + - ChainType: invalid value (Foo): must be one of arbitrum, astar, celo, gnosis, hedera, kroma, mantle, metis, optimismBedrock, scroll, wemix, xlayer, zkevm, zksync or omitted - HeadTracker.HistoryDepth: invalid value (30): must be greater than or equal to FinalizedBlockOffset - GasEstimator.BumpThreshold: invalid value (0): cannot be 0 if auto-purge feature is enabled for Foo - Transactions.AutoPurge.Threshold: missing: needs to be set if auto-purge feature is enabled for Foo @@ -1319,7 +1319,7 @@ func TestConfig_Validate(t *testing.T) { - 2: 5 errors: - ChainType: invalid value (Arbitrum): only "optimismBedrock" can be used with this chain id - Nodes: missing: must have at least one node - - ChainType: invalid value (Arbitrum): must be one of arbitrum, astar, celo, gnosis, hedera, kroma, metis, optimismBedrock, scroll, wemix, xlayer, zkevm, zksync or omitted + - ChainType: invalid value (Arbitrum): must be one of arbitrum, astar, celo, gnosis, hedera, kroma, mantle, metis, optimismBedrock, scroll, wemix, xlayer, zkevm, zksync or omitted - FinalityDepth: invalid value (0): must be greater than or equal to 1 - MinIncomingConfirmations: invalid value (0): must be greater than or equal to 1 - 3.Nodes: 5 errors: From 047602a52071d19a2efe3750fc30a560226d6857 Mon Sep 17 00:00:00 2001 From: Chunkai Yang <matYang@users.noreply.github.com> Date: Wed, 18 Sep 2024 10:07:05 -0400 Subject: [PATCH 110/115] Mantle use vanilla l1 oracle (#14471) * make Mantle use vanilla OP gas price oracle * changeset * bring back l1 oracle * update mock * [BCI-4072] changeset update --------- Co-authored-by: valerii.kabisov <valerii.kabisov@smartcontract.com> Co-authored-by: Valerii Kabisov <172247313+valerii-kabisov-cll@users.noreply.github.com> --- .changeset/curly-onions-tell.md | 5 ++ .../evm/gas/rollups/arbitrum_l1_oracle.go | 4 + core/chains/evm/gas/rollups/l1_oracle.go | 1 + core/chains/evm/gas/rollups/l1_oracle_abi.go | 1 - .../chains/evm/gas/rollups/mocks/l1_oracle.go | 48 ++++++++++ core/chains/evm/gas/rollups/op_l1_oracle.go | 86 +----------------- .../evm/gas/rollups/op_l1_oracle_test.go | 88 ------------------- .../evm/gas/rollups/zkSync_l1_oracle.go | 4 + 8 files changed, 66 insertions(+), 171 deletions(-) create mode 100644 .changeset/curly-onions-tell.md diff --git a/.changeset/curly-onions-tell.md b/.changeset/curly-onions-tell.md new file mode 100644 index 0000000000..249f616c01 --- /dev/null +++ b/.changeset/curly-onions-tell.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#changed Make Mantle use default OP stack l1 gas oracle in core diff --git a/core/chains/evm/gas/rollups/arbitrum_l1_oracle.go b/core/chains/evm/gas/rollups/arbitrum_l1_oracle.go index c01244db70..d758dc711e 100644 --- a/core/chains/evm/gas/rollups/arbitrum_l1_oracle.go +++ b/core/chains/evm/gas/rollups/arbitrum_l1_oracle.go @@ -112,6 +112,10 @@ func (o *arbitrumL1Oracle) Name() string { return o.logger.Name() } +func (o *arbitrumL1Oracle) ChainType(_ context.Context) chaintype.ChainType { + return o.chainType +} + func (o *arbitrumL1Oracle) Start(ctx context.Context) error { return o.StartOnce(o.Name(), func() error { go o.run() diff --git a/core/chains/evm/gas/rollups/l1_oracle.go b/core/chains/evm/gas/rollups/l1_oracle.go index e1249fdb7e..4195175598 100644 --- a/core/chains/evm/gas/rollups/l1_oracle.go +++ b/core/chains/evm/gas/rollups/l1_oracle.go @@ -26,6 +26,7 @@ type L1Oracle interface { GasPrice(ctx context.Context) (*assets.Wei, error) GetGasCost(ctx context.Context, tx *types.Transaction, blockNum *big.Int) (*assets.Wei, error) + ChainType(ctx context.Context) chaintype.ChainType } type l1OracleClient interface { diff --git a/core/chains/evm/gas/rollups/l1_oracle_abi.go b/core/chains/evm/gas/rollups/l1_oracle_abi.go index 848957ce53..fa5d9c8539 100644 --- a/core/chains/evm/gas/rollups/l1_oracle_abi.go +++ b/core/chains/evm/gas/rollups/l1_oracle_abi.go @@ -19,4 +19,3 @@ const OPBaseFeeScalarAbiString = `[{"inputs":[],"name":"baseFeeScalar","outputs" const OPBlobBaseFeeAbiString = `[{"inputs":[],"name":"blobBaseFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]` const OPBlobBaseFeeScalarAbiString = `[{"inputs":[],"name":"blobBaseFeeScalar","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"}]` const OPDecimalsAbiString = `[{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"}]` -const MantleTokenRatioAbiString = `[{"inputs":[],"name":"tokenRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]` diff --git a/core/chains/evm/gas/rollups/mocks/l1_oracle.go b/core/chains/evm/gas/rollups/mocks/l1_oracle.go index e82cb4ee90..25bb3a2db5 100644 --- a/core/chains/evm/gas/rollups/mocks/l1_oracle.go +++ b/core/chains/evm/gas/rollups/mocks/l1_oracle.go @@ -7,6 +7,8 @@ import ( assets "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" + chaintype "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/chaintype" + context "context" mock "github.com/stretchr/testify/mock" @@ -27,6 +29,52 @@ func (_m *L1Oracle) EXPECT() *L1Oracle_Expecter { return &L1Oracle_Expecter{mock: &_m.Mock} } +// ChainType provides a mock function with given fields: ctx +func (_m *L1Oracle) ChainType(ctx context.Context) chaintype.ChainType { + ret := _m.Called(ctx) + + if len(ret) == 0 { + panic("no return value specified for ChainType") + } + + var r0 chaintype.ChainType + if rf, ok := ret.Get(0).(func(context.Context) chaintype.ChainType); ok { + r0 = rf(ctx) + } else { + r0 = ret.Get(0).(chaintype.ChainType) + } + + return r0 +} + +// L1Oracle_ChainType_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ChainType' +type L1Oracle_ChainType_Call struct { + *mock.Call +} + +// ChainType is a helper method to define mock.On call +// - ctx context.Context +func (_e *L1Oracle_Expecter) ChainType(ctx interface{}) *L1Oracle_ChainType_Call { + return &L1Oracle_ChainType_Call{Call: _e.mock.On("ChainType", ctx)} +} + +func (_c *L1Oracle_ChainType_Call) Run(run func(ctx context.Context)) *L1Oracle_ChainType_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context)) + }) + return _c +} + +func (_c *L1Oracle_ChainType_Call) Return(_a0 chaintype.ChainType) *L1Oracle_ChainType_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *L1Oracle_ChainType_Call) RunAndReturn(run func(context.Context) chaintype.ChainType) *L1Oracle_ChainType_Call { + _c.Call.Return(run) + return _c +} + // Close provides a mock function with given fields: func (_m *L1Oracle) Close() error { ret := _m.Called() diff --git a/core/chains/evm/gas/rollups/op_l1_oracle.go b/core/chains/evm/gas/rollups/op_l1_oracle.go index 1b93f8fc3f..11babc5ca5 100644 --- a/core/chains/evm/gas/rollups/op_l1_oracle.go +++ b/core/chains/evm/gas/rollups/op_l1_oracle.go @@ -88,10 +88,6 @@ const ( // decimals is a hex encoded call to: // `function decimals() public pure returns (uint256);` decimalsMethod = "decimals" - // tokenRatio fetches the tokenRatio used for Mantle's gas price calculation - // tokenRatio is a hex encoded call to: - // `function tokenRatio() public pure returns (uint256);` - tokenRatioMethod = "tokenRatio" // OPGasOracleAddress is the address of the precompiled contract that exists on Optimism, Base and Mantle. OPGasOracleAddress = "0x420000000000000000000000000000000000000F" // KromaGasOracleAddress is the address of the precompiled contract that exists on Kroma. @@ -192,16 +188,6 @@ func newOpStackL1GasOracle(lggr logger.Logger, ethClient l1OracleClient, chainTy return nil, fmt.Errorf("failed to parse GasPriceOracle %s() calldata for chain: %s; %w", decimalsMethod, chainType, err) } - // Encode calldata for tokenRatio method - tokenRatioMethodAbi, err := abi.JSON(strings.NewReader(MantleTokenRatioAbiString)) - if err != nil { - return nil, fmt.Errorf("failed to parse GasPriceOracle %s() method ABI for chain: %s; %w", tokenRatioMethod, chainType, err) - } - tokenRatioCalldata, err := tokenRatioMethodAbi.Pack(tokenRatioMethod) - if err != nil { - return nil, fmt.Errorf("failed to parse GasPriceOracle %s() calldata for chain: %s; %w", tokenRatioMethod, chainType, err) - } - return &optimismL1Oracle{ client: ethClient, pollPeriod: PollPeriod, @@ -223,7 +209,6 @@ func newOpStackL1GasOracle(lggr logger.Logger, ethClient l1OracleClient, chainTy blobBaseFeeCalldata: blobBaseFeeCalldata, blobBaseFeeScalarCalldata: blobBaseFeeScalarCalldata, decimalsCalldata: decimalsCalldata, - tokenRatioCalldata: tokenRatioCalldata, isEcotoneCalldata: isEcotoneCalldata, isEcotoneMethodAbi: isEcotoneMethodAbi, isFjordCalldata: isFjordCalldata, @@ -235,6 +220,10 @@ func (o *optimismL1Oracle) Name() string { return o.logger.Name() } +func (o *optimismL1Oracle) ChainType(_ context.Context) chaintype.ChainType { + return o.chainType +} + func (o *optimismL1Oracle) Start(ctx context.Context) error { return o.StartOnce(o.Name(), func() error { go o.run() @@ -362,10 +351,6 @@ func (o *optimismL1Oracle) GetGasCost(ctx context.Context, tx *gethtypes.Transac } func (o *optimismL1Oracle) GetDAGasPrice(ctx context.Context) (*big.Int, error) { - if o.chainType == chaintype.ChainMantle { - return o.getMantleGasPrice(ctx) - } - err := o.checkForUpgrade(ctx) if err != nil { return nil, err @@ -463,69 +448,6 @@ func (o *optimismL1Oracle) getV1GasPrice(ctx context.Context) (*big.Int, error) return new(big.Int).SetBytes(b), nil } -// Returns the gas price for Mantle. The formula is the same as Optimism Bedrock (getV1GasPrice), but the tokenRatio parameter is multiplied -func (o *optimismL1Oracle) getMantleGasPrice(ctx context.Context) (*big.Int, error) { - // call oracle to get l1BaseFee and tokenRatio - rpcBatchCalls := []rpc.BatchElem{ - { - Method: "eth_call", - Args: []any{ - map[string]interface{}{ - "from": common.Address{}, - "to": o.l1OracleAddress, - "data": hexutil.Bytes(o.l1BaseFeeCalldata), - }, - "latest", - }, - Result: new(string), - }, - { - Method: "eth_call", - Args: []any{ - map[string]interface{}{ - "from": common.Address{}, - "to": o.l1OracleAddress, - "data": hexutil.Bytes(o.tokenRatioCalldata), - }, - "latest", - }, - Result: new(string), - }, - } - - err := o.client.BatchCallContext(ctx, rpcBatchCalls) - if err != nil { - return nil, fmt.Errorf("fetch gas price parameters batch call failed: %w", err) - } - if rpcBatchCalls[0].Error != nil { - return nil, fmt.Errorf("%s call failed in a batch: %w", l1BaseFeeMethod, err) - } - if rpcBatchCalls[1].Error != nil { - return nil, fmt.Errorf("%s call failed in a batch: %w", tokenRatioMethod, err) - } - - // Extract values from responses - l1BaseFeeResult := *(rpcBatchCalls[0].Result.(*string)) - tokenRatioResult := *(rpcBatchCalls[1].Result.(*string)) - - // Decode the responses into bytes - l1BaseFeeBytes, err := hexutil.Decode(l1BaseFeeResult) - if err != nil { - return nil, fmt.Errorf("failed to decode %s rpc result: %w", l1BaseFeeMethod, err) - } - tokenRatioBytes, err := hexutil.Decode(tokenRatioResult) - if err != nil { - return nil, fmt.Errorf("failed to decode %s rpc result: %w", tokenRatioMethod, err) - } - - // Convert bytes to big int for calculations - l1BaseFee := new(big.Int).SetBytes(l1BaseFeeBytes) - tokenRatio := new(big.Int).SetBytes(tokenRatioBytes) - - // multiply l1BaseFee and tokenRatio and return - return new(big.Int).Mul(l1BaseFee, tokenRatio), nil -} - // Returns the scaled gas price using baseFeeScalar, l1BaseFee, blobBaseFeeScalar, and blobBaseFee fields from the oracle // Confirmed the same calculation is used to determine gas price for both Ecotone and Fjord func (o *optimismL1Oracle) getEcotoneFjordGasPrice(ctx context.Context) (*big.Int, error) { diff --git a/core/chains/evm/gas/rollups/op_l1_oracle_test.go b/core/chains/evm/gas/rollups/op_l1_oracle_test.go index 88bb96534d..f5f009f1ea 100644 --- a/core/chains/evm/gas/rollups/op_l1_oracle_test.go +++ b/core/chains/evm/gas/rollups/op_l1_oracle_test.go @@ -111,94 +111,6 @@ func TestOPL1Oracle_ReadV1GasPrice(t *testing.T) { } } -func TestOPL1Oracle_ReadMantleGasPrice(t *testing.T) { - l1BaseFee := big.NewInt(100) - tokenRatio := big.NewInt(40) - oracleAddress := common.HexToAddress("0x1234").String() - - t.Parallel() - t.Run("correctly fetches gas price if chain is Mantle", func(t *testing.T) { - // Encode calldata for l1BaseFee method - l1BaseFeeMethodAbi, err := abi.JSON(strings.NewReader(L1BaseFeeAbiString)) - require.NoError(t, err) - l1BaseFeeCalldata, err := l1BaseFeeMethodAbi.Pack(l1BaseFeeMethod) - require.NoError(t, err) - - // Encode calldata for tokenRatio method - tokenRatioMethodAbi, err := abi.JSON(strings.NewReader(MantleTokenRatioAbiString)) - require.NoError(t, err) - tokenRatioCalldata, err := tokenRatioMethodAbi.Pack(tokenRatioMethod) - require.NoError(t, err) - - ethClient := mocks.NewL1OracleClient(t) - ethClient.On("BatchCallContext", mock.Anything, mock.IsType([]rpc.BatchElem{})).Run(func(args mock.Arguments) { - rpcElements := args.Get(1).([]rpc.BatchElem) - require.Equal(t, 2, len(rpcElements)) - for _, rE := range rpcElements { - require.Equal(t, "eth_call", rE.Method) - require.Equal(t, oracleAddress, rE.Args[0].(map[string]interface{})["to"]) - require.Equal(t, "latest", rE.Args[1]) - } - require.Equal(t, hexutil.Bytes(l1BaseFeeCalldata), rpcElements[0].Args[0].(map[string]interface{})["data"]) - require.Equal(t, hexutil.Bytes(tokenRatioCalldata), rpcElements[1].Args[0].(map[string]interface{})["data"]) - - res1 := common.BigToHash(l1BaseFee).Hex() - res2 := common.BigToHash(tokenRatio).Hex() - - rpcElements[0].Result = &res1 - rpcElements[1].Result = &res2 - }).Return(nil).Once() - - oracle, err := newOpStackL1GasOracle(logger.Test(t), ethClient, chaintype.ChainMantle, oracleAddress) - require.NoError(t, err) - - gasPrice, err := oracle.GetDAGasPrice(tests.Context(t)) - require.NoError(t, err) - - assert.Equal(t, new(big.Int).Mul(l1BaseFee, tokenRatio), gasPrice) - }) - - t.Run("fetching Mantle price but rpc returns bad data", func(t *testing.T) { - ethClient := mocks.NewL1OracleClient(t) - ethClient.On("BatchCallContext", mock.Anything, mock.IsType([]rpc.BatchElem{})).Run(func(args mock.Arguments) { - rpcElements := args.Get(1).([]rpc.BatchElem) - var badData = "zzz" - rpcElements[0].Result = &badData - rpcElements[1].Result = &badData - }).Return(nil).Once() - - oracle, err := newOpStackL1GasOracle(logger.Test(t), ethClient, chaintype.ChainMantle, oracleAddress) - require.NoError(t, err) - _, err = oracle.GetDAGasPrice(tests.Context(t)) - assert.Error(t, err) - }) - - t.Run("fetching Mantle price but rpc parent call errors", func(t *testing.T) { - ethClient := mocks.NewL1OracleClient(t) - ethClient.On("BatchCallContext", mock.Anything, mock.IsType([]rpc.BatchElem{})).Return(fmt.Errorf("revert")).Once() - - oracle, err := newOpStackL1GasOracle(logger.Test(t), ethClient, chaintype.ChainMantle, oracleAddress) - require.NoError(t, err) - _, err = oracle.GetDAGasPrice(tests.Context(t)) - assert.Error(t, err) - }) - - t.Run("fetching Mantle price but one of the sub rpc call errors", func(t *testing.T) { - ethClient := mocks.NewL1OracleClient(t) - ethClient.On("BatchCallContext", mock.Anything, mock.IsType([]rpc.BatchElem{})).Run(func(args mock.Arguments) { - rpcElements := args.Get(1).([]rpc.BatchElem) - res := common.BigToHash(l1BaseFee).Hex() - rpcElements[0].Result = &res - rpcElements[1].Error = fmt.Errorf("revert") - }).Return(nil).Once() - - oracle, err := newOpStackL1GasOracle(logger.Test(t), ethClient, chaintype.ChainMantle, oracleAddress) - require.NoError(t, err) - _, err = oracle.GetDAGasPrice(tests.Context(t)) - assert.Error(t, err) - }) -} - func setupUpgradeCheck(t *testing.T, oracleAddress string, isFjord, isEcotone bool) *mocks.L1OracleClient { trueHex := "0x0000000000000000000000000000000000000000000000000000000000000001" falseHex := "0x0000000000000000000000000000000000000000000000000000000000000000" diff --git a/core/chains/evm/gas/rollups/zkSync_l1_oracle.go b/core/chains/evm/gas/rollups/zkSync_l1_oracle.go index 31d93bc587..c294123354 100644 --- a/core/chains/evm/gas/rollups/zkSync_l1_oracle.go +++ b/core/chains/evm/gas/rollups/zkSync_l1_oracle.go @@ -83,6 +83,10 @@ func (o *zkSyncL1Oracle) Name() string { return o.logger.Name() } +func (o *zkSyncL1Oracle) ChainType(_ context.Context) chaintype.ChainType { + return o.chainType +} + func (o *zkSyncL1Oracle) Start(ctx context.Context) error { return o.StartOnce(o.Name(), func() error { go o.run() From 19d25f86d72e963e9563fc5da44ee74e9451f6e6 Mon Sep 17 00:00:00 2001 From: Dimitris Grigoriou <dimitris.grigoriou@smartcontract.com> Date: Wed, 4 Sep 2024 05:13:55 +0300 Subject: [PATCH 111/115] FeeHistory estimator (#13833) * Introduce universal estimator * Fixes * Use WeiMin to cap bump price * Update connectivity logic * Fix error * Fixes * Cover an edge case when enforcing limits * Add changeset * Update mempool check logic * Update config names * Convert Universal Estimator to service * Client changes to support UE * Introduce configs * Update mocks * Fix lint * Fix test cases * Fix mockery * Fix test cases * Update comment * Fix Start/Close sync issue * Address feedback * Fix lint * Fix lint * More changes * Add more comments * Fix merge conflicts * Update CONFIG * Rename to FeeHistory estimator * Rename * Exclude zero priced priority fees * Remove HasMempool * Remove testing commit * Fixes * Add DefaultJitter * Add optimizations * Fix testscripts * Fix name * Update error messages --- .changeset/shiny-hornets-pretend.md | 5 + .mockery.yaml | 3 + common/fee/models.go | 2 +- common/fee/utils.go | 2 +- core/chains/evm/client/chain_client.go | 9 + core/chains/evm/client/mocks/client.go | 60 ++ core/chains/evm/client/mocks/rpc_client.go | 60 ++ core/chains/evm/client/null_client.go | 4 + core/chains/evm/client/rpc_client.go | 25 + .../evm/client/simulated_backend_client.go | 4 + .../evm/config/chain_scoped_gas_estimator.go | 14 + core/chains/evm/config/config.go | 5 + core/chains/evm/config/config_test.go | 7 + core/chains/evm/config/mocks/gas_estimator.go | 47 ++ core/chains/evm/config/toml/config.go | 12 + .../evm/config/toml/defaults/fallback.toml | 3 + core/chains/evm/gas/fee_history_estimator.go | 440 +++++++++++++++ .../evm/gas/fee_history_estimator_test.go | 513 ++++++++++++++++++ .../evm/gas/mocks/fee_estimator_client.go | 118 ++++ .../gas/mocks/fee_history_estimator_client.go | 157 ++++++ core/chains/evm/gas/models.go | 14 + core/chains/evm/txmgr/test_helpers.go | 10 + core/config/docs/chains-evm.toml | 9 + core/services/chainlink/config_test.go | 6 + .../chainlink/testdata/config-full.toml | 3 + .../config-multi-chain-effective.toml | 9 + core/web/resolver/testdata/config-full.toml | 3 + .../config-multi-chain-effective.toml | 9 + docs/CONFIG.md | 201 +++++++ .../disk-based-logging-disabled.txtar | 3 + .../validate/disk-based-logging-no-dir.txtar | 3 + .../node/validate/disk-based-logging.txtar | 3 + testdata/scripts/node/validate/invalid.txtar | 3 + testdata/scripts/node/validate/valid.txtar | 3 + 34 files changed, 1767 insertions(+), 2 deletions(-) create mode 100644 .changeset/shiny-hornets-pretend.md create mode 100644 core/chains/evm/gas/fee_history_estimator.go create mode 100644 core/chains/evm/gas/fee_history_estimator_test.go create mode 100644 core/chains/evm/gas/mocks/fee_history_estimator_client.go diff --git a/.changeset/shiny-hornets-pretend.md b/.changeset/shiny-hornets-pretend.md new file mode 100644 index 0000000000..ff9946f4e7 --- /dev/null +++ b/.changeset/shiny-hornets-pretend.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +Introduce new gas estimator #internal diff --git a/.mockery.yaml b/.mockery.yaml index 34b886d187..fa36213ff7 100644 --- a/.mockery.yaml +++ b/.mockery.yaml @@ -65,6 +65,9 @@ packages: feeEstimatorClient: config: mockname: FeeEstimatorClient + feeHistoryEstimatorClient: + config: + mockname: FeeHistoryEstimatorClient EvmEstimator: github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/rollups: interfaces: diff --git a/common/fee/models.go b/common/fee/models.go index 0496d3929c..0cc479d356 100644 --- a/common/fee/models.go +++ b/common/fee/models.go @@ -64,7 +64,7 @@ func CalculateBumpedFee( // Returns highest bumped fee price of originalFeePrice bumped by fixed units or percentage. func MaxBumpedFee(originalFeePrice *big.Int, feeBumpPercent uint16, feeBumpUnits *big.Int) *big.Int { return bigmath.Max( - addPercentage(originalFeePrice, feeBumpPercent), + AddPercentage(originalFeePrice, feeBumpPercent), new(big.Int).Add(originalFeePrice, feeBumpUnits), ) } diff --git a/common/fee/utils.go b/common/fee/utils.go index 26323e11e2..3d4b001e83 100644 --- a/common/fee/utils.go +++ b/common/fee/utils.go @@ -18,7 +18,7 @@ func ApplyMultiplier(feeLimit uint64, multiplier float32) (uint64, error) { } // Returns the input value increased by the given percentage. -func addPercentage(value *big.Int, percentage uint16) *big.Int { +func AddPercentage(value *big.Int, percentage uint16) *big.Int { bumped := new(big.Int) bumped.Mul(value, big.NewInt(int64(100+percentage))) bumped.Div(bumped, big.NewInt(100)) diff --git a/core/chains/evm/client/chain_client.go b/core/chains/evm/client/chain_client.go index c27d294ebf..310528424d 100644 --- a/core/chains/evm/client/chain_client.go +++ b/core/chains/evm/client/chain_client.go @@ -84,6 +84,7 @@ type Client interface { SuggestGasPrice(ctx context.Context) (*big.Int, error) SuggestGasTipCap(ctx context.Context) (*big.Int, error) LatestBlockHeight(ctx context.Context) (*big.Int, error) + FeeHistory(ctx context.Context, blockCount uint64, rewardPercentiles []float64) (feeHistory *ethereum.FeeHistory, err error) HeaderByNumber(ctx context.Context, n *big.Int) (*types.Header, error) HeaderByHash(ctx context.Context, h common.Hash) (*types.Header, error) @@ -353,6 +354,14 @@ func (c *chainClient) LatestFinalizedBlock(ctx context.Context) (*evmtypes.Head, return c.multiNode.LatestFinalizedBlock(ctx) } +func (c *chainClient) FeeHistory(ctx context.Context, blockCount uint64, rewardPercentiles []float64) (feeHistory *ethereum.FeeHistory, err error) { + rpc, err := c.multiNode.SelectNodeRPC() + if err != nil { + return feeHistory, err + } + return rpc.FeeHistory(ctx, blockCount, rewardPercentiles) +} + func (c *chainClient) CheckTxValidity(ctx context.Context, from common.Address, to common.Address, data []byte) *SendError { msg := ethereum.CallMsg{ From: from, diff --git a/core/chains/evm/client/mocks/client.go b/core/chains/evm/client/mocks/client.go index 7b5220033b..da034d9577 100644 --- a/core/chains/evm/client/mocks/client.go +++ b/core/chains/evm/client/mocks/client.go @@ -780,6 +780,66 @@ func (_c *Client_EstimateGas_Call) RunAndReturn(run func(context.Context, ethere return _c } +// FeeHistory provides a mock function with given fields: ctx, blockCount, rewardPercentiles +func (_m *Client) FeeHistory(ctx context.Context, blockCount uint64, rewardPercentiles []float64) (*ethereum.FeeHistory, error) { + ret := _m.Called(ctx, blockCount, rewardPercentiles) + + if len(ret) == 0 { + panic("no return value specified for FeeHistory") + } + + var r0 *ethereum.FeeHistory + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, uint64, []float64) (*ethereum.FeeHistory, error)); ok { + return rf(ctx, blockCount, rewardPercentiles) + } + if rf, ok := ret.Get(0).(func(context.Context, uint64, []float64) *ethereum.FeeHistory); ok { + r0 = rf(ctx, blockCount, rewardPercentiles) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*ethereum.FeeHistory) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, uint64, []float64) error); ok { + r1 = rf(ctx, blockCount, rewardPercentiles) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Client_FeeHistory_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FeeHistory' +type Client_FeeHistory_Call struct { + *mock.Call +} + +// FeeHistory is a helper method to define mock.On call +// - ctx context.Context +// - blockCount uint64 +// - rewardPercentiles []float64 +func (_e *Client_Expecter) FeeHistory(ctx interface{}, blockCount interface{}, rewardPercentiles interface{}) *Client_FeeHistory_Call { + return &Client_FeeHistory_Call{Call: _e.mock.On("FeeHistory", ctx, blockCount, rewardPercentiles)} +} + +func (_c *Client_FeeHistory_Call) Run(run func(ctx context.Context, blockCount uint64, rewardPercentiles []float64)) *Client_FeeHistory_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(uint64), args[2].([]float64)) + }) + return _c +} + +func (_c *Client_FeeHistory_Call) Return(feeHistory *ethereum.FeeHistory, err error) *Client_FeeHistory_Call { + _c.Call.Return(feeHistory, err) + return _c +} + +func (_c *Client_FeeHistory_Call) RunAndReturn(run func(context.Context, uint64, []float64) (*ethereum.FeeHistory, error)) *Client_FeeHistory_Call { + _c.Call.Return(run) + return _c +} + // FilterLogs provides a mock function with given fields: ctx, q func (_m *Client) FilterLogs(ctx context.Context, q ethereum.FilterQuery) ([]types.Log, error) { ret := _m.Called(ctx, q) diff --git a/core/chains/evm/client/mocks/rpc_client.go b/core/chains/evm/client/mocks/rpc_client.go index 06f79efd55..5567b3f897 100644 --- a/core/chains/evm/client/mocks/rpc_client.go +++ b/core/chains/evm/client/mocks/rpc_client.go @@ -889,6 +889,66 @@ func (_c *RPCClient_EstimateGas_Call) RunAndReturn(run func(context.Context, int return _c } +// FeeHistory provides a mock function with given fields: ctx, blockCount, rewardPercentiles +func (_m *RPCClient) FeeHistory(ctx context.Context, blockCount uint64, rewardPercentiles []float64) (*ethereum.FeeHistory, error) { + ret := _m.Called(ctx, blockCount, rewardPercentiles) + + if len(ret) == 0 { + panic("no return value specified for FeeHistory") + } + + var r0 *ethereum.FeeHistory + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, uint64, []float64) (*ethereum.FeeHistory, error)); ok { + return rf(ctx, blockCount, rewardPercentiles) + } + if rf, ok := ret.Get(0).(func(context.Context, uint64, []float64) *ethereum.FeeHistory); ok { + r0 = rf(ctx, blockCount, rewardPercentiles) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*ethereum.FeeHistory) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, uint64, []float64) error); ok { + r1 = rf(ctx, blockCount, rewardPercentiles) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// RPCClient_FeeHistory_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FeeHistory' +type RPCClient_FeeHistory_Call struct { + *mock.Call +} + +// FeeHistory is a helper method to define mock.On call +// - ctx context.Context +// - blockCount uint64 +// - rewardPercentiles []float64 +func (_e *RPCClient_Expecter) FeeHistory(ctx interface{}, blockCount interface{}, rewardPercentiles interface{}) *RPCClient_FeeHistory_Call { + return &RPCClient_FeeHistory_Call{Call: _e.mock.On("FeeHistory", ctx, blockCount, rewardPercentiles)} +} + +func (_c *RPCClient_FeeHistory_Call) Run(run func(ctx context.Context, blockCount uint64, rewardPercentiles []float64)) *RPCClient_FeeHistory_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(uint64), args[2].([]float64)) + }) + return _c +} + +func (_c *RPCClient_FeeHistory_Call) Return(feeHistory *ethereum.FeeHistory, err error) *RPCClient_FeeHistory_Call { + _c.Call.Return(feeHistory, err) + return _c +} + +func (_c *RPCClient_FeeHistory_Call) RunAndReturn(run func(context.Context, uint64, []float64) (*ethereum.FeeHistory, error)) *RPCClient_FeeHistory_Call { + _c.Call.Return(run) + return _c +} + // FilterEvents provides a mock function with given fields: ctx, query func (_m *RPCClient) FilterEvents(ctx context.Context, query ethereum.FilterQuery) ([]coretypes.Log, error) { ret := _m.Called(ctx, query) diff --git a/core/chains/evm/client/null_client.go b/core/chains/evm/client/null_client.go index 3129bcff9b..5b1a4d7e1b 100644 --- a/core/chains/evm/client/null_client.go +++ b/core/chains/evm/client/null_client.go @@ -235,3 +235,7 @@ func (nc *NullClient) LatestFinalizedBlock(_ context.Context) (*evmtypes.Head, e func (nc *NullClient) CheckTxValidity(_ context.Context, _ common.Address, _ common.Address, _ []byte) *SendError { return nil } + +func (nc *NullClient) FeeHistory(ctx context.Context, blockCount uint64, rewardPercentiles []float64) (feeHistory *ethereum.FeeHistory, err error) { + return nil, nil +} diff --git a/core/chains/evm/client/rpc_client.go b/core/chains/evm/client/rpc_client.go index 72071199d4..295e24f7c9 100644 --- a/core/chains/evm/client/rpc_client.go +++ b/core/chains/evm/client/rpc_client.go @@ -103,6 +103,7 @@ type RPCClient interface { SuggestGasTipCap(ctx context.Context) (t *big.Int, err error) TransactionReceiptGeth(ctx context.Context, txHash common.Hash) (r *types.Receipt, err error) GetInterceptedChainInfo() (latest, highestUserObservations commonclient.ChainInfo) + FeeHistory(ctx context.Context, blockCount uint64, rewardPercentiles []float64) (feeHistory *ethereum.FeeHistory, err error) } const rpcSubscriptionMethodNewHeads = "newHeads" @@ -599,6 +600,7 @@ func (r *rpcClient) TransactionReceiptGeth(ctx context.Context, txHash common.Ha return } + func (r *rpcClient) TransactionByHash(ctx context.Context, txHash common.Hash) (tx *types.Transaction, err error) { ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx, r.rpcTimeout) defer cancel() @@ -1119,6 +1121,29 @@ func (r *rpcClient) BalanceAt(ctx context.Context, account common.Address, block return } +func (r *rpcClient) FeeHistory(ctx context.Context, blockCount uint64, rewardPercentiles []float64) (feeHistory *ethereum.FeeHistory, err error) { + ctx, cancel, ws, http := r.makeLiveQueryCtxAndSafeGetClients(ctx, r.rpcTimeout) + defer cancel() + lggr := r.newRqLggr().With("blockCount", blockCount, "rewardPercentiles", rewardPercentiles) + + lggr.Debug("RPC call: evmclient.Client#FeeHistory") + start := time.Now() + if http != nil { + feeHistory, err = http.geth.FeeHistory(ctx, blockCount, nil, rewardPercentiles) + err = r.wrapHTTP(err) + } else { + feeHistory, err = ws.geth.FeeHistory(ctx, blockCount, nil, rewardPercentiles) + err = r.wrapWS(err) + } + duration := time.Since(start) + + r.logResult(lggr, err, duration, r.getRPCDomain(), "FeeHistory", + "feeHistory", feeHistory, + ) + + return +} + // CallArgs represents the data used to call the balance method of a contract. // "To" is the address of the ERC contract. "Data" is the message sent // to the contract. "From" is the sender address. diff --git a/core/chains/evm/client/simulated_backend_client.go b/core/chains/evm/client/simulated_backend_client.go index 7dfd39f444..3ec1bff577 100644 --- a/core/chains/evm/client/simulated_backend_client.go +++ b/core/chains/evm/client/simulated_backend_client.go @@ -156,6 +156,10 @@ func (c *SimulatedBackendClient) LINKBalance(ctx context.Context, address common panic("not implemented") } +func (c *SimulatedBackendClient) FeeHistory(ctx context.Context, blockCount uint64, rewardPercentiles []float64) (feeHistory *ethereum.FeeHistory, err error) { + panic("not implemented") +} + // TransactionReceipt returns the transaction receipt for the given transaction hash. func (c *SimulatedBackendClient) TransactionReceipt(ctx context.Context, receipt common.Hash) (*types.Receipt, error) { return c.b.TransactionReceipt(ctx, receipt) diff --git a/core/chains/evm/config/chain_scoped_gas_estimator.go b/core/chains/evm/config/chain_scoped_gas_estimator.go index 6f43839b01..54c7c36063 100644 --- a/core/chains/evm/config/chain_scoped_gas_estimator.go +++ b/core/chains/evm/config/chain_scoped_gas_estimator.go @@ -1,6 +1,8 @@ package config import ( + "time" + gethcommon "github.com/ethereum/go-ethereum/common" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" @@ -36,6 +38,10 @@ func (g *gasEstimatorConfig) BlockHistory() BlockHistory { return &blockHistoryConfig{c: g.c.BlockHistory, blockDelay: g.blockDelay, bumpThreshold: g.c.BumpThreshold} } +func (g *gasEstimatorConfig) FeeHistory() FeeHistory { + return &feeHistoryConfig{c: g.c.FeeHistory} +} + func (g *gasEstimatorConfig) EIP1559DynamicFees() bool { return *g.c.EIP1559DynamicFees } @@ -176,3 +182,11 @@ func (b *blockHistoryConfig) TransactionPercentile() uint16 { func (b *blockHistoryConfig) BlockDelay() uint16 { return *b.blockDelay } + +type feeHistoryConfig struct { + c toml.FeeHistoryEstimator +} + +func (u *feeHistoryConfig) CacheTimeout() time.Duration { + return u.c.CacheTimeout.Duration() +} diff --git a/core/chains/evm/config/config.go b/core/chains/evm/config/config.go index 9237cf5e1e..3d00fe86a4 100644 --- a/core/chains/evm/config/config.go +++ b/core/chains/evm/config/config.go @@ -117,6 +117,7 @@ type AutoPurgeConfig interface { type GasEstimator interface { BlockHistory() BlockHistory + FeeHistory() FeeHistory LimitJobType() LimitJobType EIP1559DynamicFees() bool @@ -158,6 +159,10 @@ type BlockHistory interface { TransactionPercentile() uint16 } +type FeeHistory interface { + CacheTimeout() time.Duration +} + type Workflow interface { FromAddress() *types.EIP55Address ForwarderAddress() *types.EIP55Address diff --git a/core/chains/evm/config/config_test.go b/core/chains/evm/config/config_test.go index 305737a87c..e0dec00e68 100644 --- a/core/chains/evm/config/config_test.go +++ b/core/chains/evm/config/config_test.go @@ -220,6 +220,13 @@ func TestChainScopedConfig_BlockHistory(t *testing.T) { assert.Equal(t, uint16(1), bh.BlockDelay()) assert.Equal(t, uint16(4), bh.EIP1559FeeCapBufferBlocks()) } +func TestChainScopedConfig_FeeHistory(t *testing.T) { + t.Parallel() + cfg := testutils.NewTestChainScopedConfig(t, nil) + + u := cfg.EVM().GasEstimator().FeeHistory() + assert.Equal(t, 10*time.Second, u.CacheTimeout()) +} func TestChainScopedConfig_GasEstimator(t *testing.T) { t.Parallel() diff --git a/core/chains/evm/config/mocks/gas_estimator.go b/core/chains/evm/config/mocks/gas_estimator.go index 96ffff08ae..70b9c18d0b 100644 --- a/core/chains/evm/config/mocks/gas_estimator.go +++ b/core/chains/evm/config/mocks/gas_estimator.go @@ -390,6 +390,53 @@ func (_c *GasEstimator_FeeCapDefault_Call) RunAndReturn(run func() *assets.Wei) return _c } +// FeeHistory provides a mock function with given fields: +func (_m *GasEstimator) FeeHistory() config.FeeHistory { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for FeeHistory") + } + + var r0 config.FeeHistory + if rf, ok := ret.Get(0).(func() config.FeeHistory); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(config.FeeHistory) + } + } + + return r0 +} + +// GasEstimator_FeeHistory_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FeeHistory' +type GasEstimator_FeeHistory_Call struct { + *mock.Call +} + +// FeeHistory is a helper method to define mock.On call +func (_e *GasEstimator_Expecter) FeeHistory() *GasEstimator_FeeHistory_Call { + return &GasEstimator_FeeHistory_Call{Call: _e.mock.On("FeeHistory")} +} + +func (_c *GasEstimator_FeeHistory_Call) Run(run func()) *GasEstimator_FeeHistory_Call { + _c.Call.Run(func(args mock.Arguments) { + run() + }) + return _c +} + +func (_c *GasEstimator_FeeHistory_Call) Return(_a0 config.FeeHistory) *GasEstimator_FeeHistory_Call { + _c.Call.Return(_a0) + return _c +} + +func (_c *GasEstimator_FeeHistory_Call) RunAndReturn(run func() config.FeeHistory) *GasEstimator_FeeHistory_Call { + _c.Call.Return(run) + return _c +} + // LimitDefault provides a mock function with given fields: func (_m *GasEstimator) LimitDefault() uint64 { ret := _m.Called() diff --git a/core/chains/evm/config/toml/config.go b/core/chains/evm/config/toml/config.go index 0e823ffdda..90854d90cf 100644 --- a/core/chains/evm/config/toml/config.go +++ b/core/chains/evm/config/toml/config.go @@ -568,6 +568,7 @@ type GasEstimator struct { TipCapMin *assets.Wei BlockHistory BlockHistoryEstimator `toml:",omitempty"` + FeeHistory FeeHistoryEstimator `toml:",omitempty"` } func (e *GasEstimator) ValidateConfig() (err error) { @@ -662,6 +663,7 @@ func (e *GasEstimator) setFrom(f *GasEstimator) { } e.LimitJobType.setFrom(&f.LimitJobType) e.BlockHistory.setFrom(&f.BlockHistory) + e.FeeHistory.setFrom(&f.FeeHistory) } type GasLimitJobType struct { @@ -724,6 +726,16 @@ func (e *BlockHistoryEstimator) setFrom(f *BlockHistoryEstimator) { } } +type FeeHistoryEstimator struct { + CacheTimeout *commonconfig.Duration +} + +func (u *FeeHistoryEstimator) setFrom(f *FeeHistoryEstimator) { + if v := f.CacheTimeout; v != nil { + u.CacheTimeout = v + } +} + type KeySpecificConfig []KeySpecific func (ks KeySpecificConfig) ValidateConfig() (err error) { diff --git a/core/chains/evm/config/toml/defaults/fallback.toml b/core/chains/evm/config/toml/defaults/fallback.toml index be3b19677d..fb8eed3949 100644 --- a/core/chains/evm/config/toml/defaults/fallback.toml +++ b/core/chains/evm/config/toml/defaults/fallback.toml @@ -57,6 +57,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 diff --git a/core/chains/evm/gas/fee_history_estimator.go b/core/chains/evm/gas/fee_history_estimator.go new file mode 100644 index 0000000000..ba3192be10 --- /dev/null +++ b/core/chains/evm/gas/fee_history_estimator.go @@ -0,0 +1,440 @@ +package gas + +import ( + "context" + "fmt" + "math/big" + "strconv" + "sync" + "time" + + "github.com/ethereum/go-ethereum" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promauto" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-common/pkg/services" + bigmath "github.com/smartcontractkit/chainlink-common/pkg/utils/big_math" + + commonfee "github.com/smartcontractkit/chainlink/v2/common/fee" + feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" + evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/rollups" + evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" +) + +// metrics are thread safe +var ( + promFeeHistoryEstimatorGasPrice = promauto.NewGaugeVec(prometheus.GaugeOpts{ + Name: "gas_price_updater", + Help: "Sets latest gas price (in Wei)", + }, + []string{"evmChainID"}, + ) + promFeeHistoryEstimatorBaseFee = promauto.NewGaugeVec(prometheus.GaugeOpts{ + Name: "base_fee_updater", + Help: "Sets latest BaseFee (in Wei)", + }, + []string{"evmChainID"}, + ) + promFeeHistoryEstimatorMaxPriorityFeePerGas = promauto.NewGaugeVec(prometheus.GaugeOpts{ + Name: "max_priority_fee_per_gas_updater", + Help: "Sets latest MaxPriorityFeePerGas (in Wei)", + }, + []string{"evmChainID"}, + ) + promFeeHistoryEstimatorMaxFeePerGas = promauto.NewGaugeVec(prometheus.GaugeOpts{ + Name: "max_fee_per_gas_updater", + Help: "Sets latest MaxFeePerGas (in Wei)", + }, + []string{"evmChainID"}, + ) +) + +const ( + MinimumBumpPercentage = 10 // based on geth's spec + ConnectivityPercentile = 85 + BaseFeeBufferPercentage = 40 +) + +type FeeHistoryEstimatorConfig struct { + BumpPercent uint16 + CacheTimeout time.Duration + + EIP1559 bool + BlockHistorySize uint64 + RewardPercentile float64 +} + +type feeHistoryEstimatorClient interface { + SuggestGasPrice(ctx context.Context) (*big.Int, error) + FeeHistory(ctx context.Context, blockCount uint64, rewardPercentiles []float64) (feeHistory *ethereum.FeeHistory, err error) +} + +type FeeHistoryEstimator struct { + services.StateMachine + + client feeHistoryEstimatorClient + logger logger.Logger + config FeeHistoryEstimatorConfig + chainID *big.Int + + gasPriceMu sync.RWMutex + gasPrice *assets.Wei + + dynamicPriceMu sync.RWMutex + dynamicPrice DynamicFee + + priorityFeeThresholdMu sync.RWMutex + priorityFeeThreshold *assets.Wei + + l1Oracle rollups.L1Oracle + + wg *sync.WaitGroup + stopCh services.StopChan + refreshCh chan struct{} +} + +func NewFeeHistoryEstimator(lggr logger.Logger, client feeHistoryEstimatorClient, cfg FeeHistoryEstimatorConfig, chainID *big.Int, l1Oracle rollups.L1Oracle) *FeeHistoryEstimator { + return &FeeHistoryEstimator{ + client: client, + logger: logger.Named(lggr, "FeeHistoryEstimator"), + config: cfg, + chainID: chainID, + l1Oracle: l1Oracle, + wg: new(sync.WaitGroup), + stopCh: make(chan struct{}), + refreshCh: make(chan struct{}), + } +} + +func (f *FeeHistoryEstimator) Start(context.Context) error { + return f.StartOnce("FeeHistoryEstimator", func() error { + if f.config.BumpPercent < MinimumBumpPercentage { + return fmt.Errorf("BumpPercent: %s is less than minimum allowed percentage: %s", + strconv.FormatUint(uint64(f.config.BumpPercent), 10), strconv.Itoa(MinimumBumpPercentage)) + } + if f.config.EIP1559 && f.config.RewardPercentile > ConnectivityPercentile { + return fmt.Errorf("RewardPercentile: %s is greater than maximum allowed percentile: %s", + strconv.FormatUint(uint64(f.config.RewardPercentile), 10), strconv.Itoa(ConnectivityPercentile)) + } + f.wg.Add(1) + go f.run() + + return nil + }) +} + +func (f *FeeHistoryEstimator) Close() error { + return f.StopOnce("FeeHistoryEstimator", func() error { + close(f.stopCh) + f.wg.Wait() + return nil + }) +} + +func (f *FeeHistoryEstimator) run() { + defer f.wg.Done() + + t := services.TickerConfig{ + JitterPct: services.DefaultJitter, + }.NewTicker(f.config.CacheTimeout) + + for { + select { + case <-f.stopCh: + return + case <-f.refreshCh: + t.Reset() + case <-t.C: + if f.config.EIP1559 { + if err := f.RefreshDynamicPrice(); err != nil { + f.logger.Error(err) + } + } else { + if _, err := f.RefreshGasPrice(); err != nil { + f.logger.Error(err) + } + } + } + } +} + +// GetLegacyGas will fetch the cached gas price value. +func (f *FeeHistoryEstimator) GetLegacyGas(ctx context.Context, _ []byte, gasLimit uint64, maxPrice *assets.Wei, opts ...feetypes.Opt) (gasPrice *assets.Wei, chainSpecificGasLimit uint64, err error) { + chainSpecificGasLimit = gasLimit + if gasPrice, err = f.getGasPrice(); err != nil { + return + } + + if gasPrice.Cmp(maxPrice) > 0 { + f.logger.Warnf("estimated gas price: %s is greater than the maximum gas price configured: %s, returning the maximum price instead.", gasPrice, maxPrice) + return maxPrice, chainSpecificGasLimit, nil + } + return +} + +// RefreshGasPrice will use eth_gasPrice to fetch and cache the latest gas price from the RPC. +func (f *FeeHistoryEstimator) RefreshGasPrice() (*assets.Wei, error) { + ctx, cancel := f.stopCh.CtxCancel(evmclient.ContextWithDefaultTimeout()) + defer cancel() + + gasPrice, err := f.client.SuggestGasPrice(ctx) + if err != nil { + return nil, err + } + + promFeeHistoryEstimatorGasPrice.WithLabelValues(f.chainID.String()).Set(float64(gasPrice.Int64())) + + gasPriceWei := assets.NewWei(gasPrice) + + f.logger.Debugf("fetched new gas price: %v", gasPriceWei) + + f.gasPriceMu.Lock() + defer f.gasPriceMu.Unlock() + f.gasPrice = gasPriceWei + return f.gasPrice, nil +} + +func (f *FeeHistoryEstimator) getGasPrice() (*assets.Wei, error) { + f.gasPriceMu.RLock() + defer f.gasPriceMu.RUnlock() + if f.gasPrice == nil { + return f.gasPrice, fmt.Errorf("gas price not set") + } + return f.gasPrice, nil +} + +// GetDynamicFee will fetch the cached dynamic prices. +func (f *FeeHistoryEstimator) GetDynamicFee(ctx context.Context, maxPrice *assets.Wei) (fee DynamicFee, err error) { + if fee, err = f.getDynamicPrice(); err != nil { + return + } + + if fee.FeeCap.Cmp(maxPrice) > 0 { + f.logger.Warnf("estimated maxFeePerGas: %v is greater than the maximum price configured: %v, returning the maximum price instead.", + fee.FeeCap, maxPrice) + fee.FeeCap = maxPrice + if fee.TipCap.Cmp(maxPrice) > 0 { + f.logger.Warnf("estimated maxPriorityFeePerGas: %v is greater than the maximum price configured: %v, returning the maximum price instead.", + fee.TipCap, maxPrice) + fee.TipCap = maxPrice + } + } + + return +} + +// RefreshDynamicPrice uses eth_feeHistory to fetch the baseFee of the next block and the Nth maxPriorityFeePerGas percentiles +// of the past X blocks. It also fetches the highest 85th maxPriorityFeePerGas percentile of the past X blocks, which represents +// the highest percentile we're willing to pay. A buffer is added on top of the latest baseFee to catch fluctuations in the next +// blocks. On Ethereum the increase is baseFee * 1.125 per block, however in some chains that may vary. +func (f *FeeHistoryEstimator) RefreshDynamicPrice() error { + ctx, cancel := f.stopCh.CtxCancel(evmclient.ContextWithDefaultTimeout()) + defer cancel() + + // RewardPercentile will be used for maxPriorityFeePerGas estimations and connectivityPercentile to set the highest threshold for bumping. + feeHistory, err := f.client.FeeHistory(ctx, max(f.config.BlockHistorySize, 1), []float64{f.config.RewardPercentile, ConnectivityPercentile}) + if err != nil { + return err + } + + // eth_feeHistory doesn't return the latest baseFee of the range but rather the latest + 1, because it can be derived from the existing + // values. Source: https://github.com/ethereum/go-ethereum/blob/b0f66e34ca2a4ea7ae23475224451c8c9a569826/eth/gasprice/feehistory.go#L235 + // nextBlock is the latest returned + 1 to be aligned with the base fee value. + nextBaseFee := assets.NewWei(feeHistory.BaseFee[len(feeHistory.BaseFee)-1]) + nextBlock := big.NewInt(0).Add(feeHistory.OldestBlock, big.NewInt(int64(f.config.BlockHistorySize))) + + // If BlockHistorySize is 0 it means priority fees will be ignored from the calculations, so we set them to 0. + // If it's not we exclude 0 priced priority fees from the RPC response, even though some networks allow them. For empty blocks, eth_feeHistory + // returns priority fees with 0 values so it's safer to discard them in order to pick values from a more representative sample. + maxPriorityFeePerGas := assets.NewWeiI(0) + priorityFeeThresholdWei := assets.NewWeiI(0) + if f.config.BlockHistorySize > 0 { + var nonZeroRewardsLen int64 = 0 + priorityFee := big.NewInt(0) + priorityFeeThreshold := big.NewInt(0) + for _, reward := range feeHistory.Reward { + // reward needs to have values for two percentiles + if len(reward) < 2 { + return fmt.Errorf("reward size incorrect: %d", len(reward)) + } + // We'll calculate the average of non-zero priority fees + if reward[0].Cmp(big.NewInt(0)) > 0 { + priorityFee = priorityFee.Add(priorityFee, reward[0]) + nonZeroRewardsLen += 1 + } + // We take the max value for the bumping threshold + if reward[1].Cmp(big.NewInt(0)) > 0 { + priorityFeeThreshold = bigmath.Max(priorityFeeThreshold, reward[1]) + } + } + + if nonZeroRewardsLen == 0 || priorityFeeThreshold.Cmp(big.NewInt(0)) == 0 { + return nil + } + priorityFeeThresholdWei = assets.NewWei(priorityFeeThreshold) + maxPriorityFeePerGas = assets.NewWei(priorityFee.Div(priorityFee, big.NewInt(nonZeroRewardsLen))) + } + // baseFeeBufferPercentage is added on top as a safety to catch fluctuations in the next blocks. + maxFeePerGas := nextBaseFee.AddPercentage(BaseFeeBufferPercentage).Add(maxPriorityFeePerGas) + + promFeeHistoryEstimatorBaseFee.WithLabelValues(f.chainID.String()).Set(float64(nextBaseFee.Int64())) + promFeeHistoryEstimatorMaxPriorityFeePerGas.WithLabelValues(f.chainID.String()).Set(float64(maxPriorityFeePerGas.Int64())) + promFeeHistoryEstimatorMaxFeePerGas.WithLabelValues(f.chainID.String()).Set(float64(maxFeePerGas.Int64())) + + f.logger.Debugf("Fetched new dynamic prices, nextBlock#: %v - oldestBlock#: %v - nextBaseFee: %v - maxFeePerGas: %v - maxPriorityFeePerGas: %v - maxPriorityFeeThreshold: %v", + nextBlock, feeHistory.OldestBlock, nextBaseFee, maxFeePerGas, maxPriorityFeePerGas, priorityFeeThresholdWei) + + f.priorityFeeThresholdMu.Lock() + f.priorityFeeThreshold = priorityFeeThresholdWei + f.priorityFeeThresholdMu.Unlock() + + f.dynamicPriceMu.Lock() + defer f.dynamicPriceMu.Unlock() + f.dynamicPrice.FeeCap = maxFeePerGas + f.dynamicPrice.TipCap = maxPriorityFeePerGas + return nil +} + +func (f *FeeHistoryEstimator) getDynamicPrice() (fee DynamicFee, err error) { + f.dynamicPriceMu.RLock() + defer f.dynamicPriceMu.RUnlock() + if f.dynamicPrice.FeeCap == nil || f.dynamicPrice.TipCap == nil { + return fee, fmt.Errorf("dynamic price not set") + } + return f.dynamicPrice, nil +} + +// BumpLegacyGas provides a bumped gas price value by bumping the previous one by BumpPercent. +// If the original value is higher than the max price it returns an error as there is no room for bumping. +// It aggregates the market, bumped, and max gas price to provide a correct value. +func (f *FeeHistoryEstimator) BumpLegacyGas(ctx context.Context, originalGasPrice *assets.Wei, gasLimit uint64, maxPrice *assets.Wei, _ []EvmPriorAttempt) (*assets.Wei, uint64, error) { + // Sanitize original fee input + if originalGasPrice == nil || originalGasPrice.Cmp(maxPrice) >= 0 { + return nil, 0, fmt.Errorf("%w: error while retrieving original gas price: originalGasPrice: %s. Maximum price configured: %s", + commonfee.ErrBump, originalGasPrice, maxPrice) + } + + currentGasPrice, err := f.RefreshGasPrice() + if err != nil { + return nil, 0, err + } + f.IfStarted(func() { f.refreshCh <- struct{}{} }) + + bumpedGasPrice := originalGasPrice.AddPercentage(f.config.BumpPercent) + bumpedGasPrice, err = LimitBumpedFee(originalGasPrice, currentGasPrice, bumpedGasPrice, maxPrice) + if err != nil { + return nil, 0, fmt.Errorf("failed to limit gas price: %w", err) + } + + f.logger.Debugw("bumped gas price", "originalGasPrice", originalGasPrice, "marketGasPrice", currentGasPrice, "bumpedGasPrice", bumpedGasPrice) + + return bumpedGasPrice, gasLimit, nil +} + +// BumpDynamicFee provides a bumped dynamic fee by bumping the previous one by BumpPercent. +// If the original values are higher than the max price it returns an error as there is no room for bumping. If maxPriorityFeePerGas is bumped +// above the priority fee threshold then there is a good chance there is a connectivity issue and we shouldn't bump. +// Both maxFeePerGas as well as maxPriorityFeePerGas need to be bumped otherwise the RPC won't accept the transaction and throw an error. +// See: https://github.com/ethereum/go-ethereum/issues/24284 +// It aggregates the market, bumped, and max price to provide a correct value, for both maxFeePerGas as well as maxPriorityFerPergas. +func (f *FeeHistoryEstimator) BumpDynamicFee(ctx context.Context, originalFee DynamicFee, maxPrice *assets.Wei, _ []EvmPriorAttempt) (bumped DynamicFee, err error) { + // For chains that don't have a mempool there is no concept of gas bumping so we force-call RefreshDynamicPrice to update the underlying base fee value + if f.config.BlockHistorySize == 0 { + if !f.IfStarted(func() { + if refreshErr := f.RefreshDynamicPrice(); refreshErr != nil { + err = refreshErr + return + } + f.refreshCh <- struct{}{} + bumped, err = f.GetDynamicFee(ctx, maxPrice) + }) { + return bumped, fmt.Errorf("estimator not started") + } + return bumped, err + } + + // Sanitize original fee input + // According to geth's spec we need to bump both maxFeePerGas and maxPriorityFeePerGas for the new attempt to be accepted by the RPC + if originalFee.FeeCap == nil || + originalFee.TipCap == nil || + ((originalFee.TipCap.Cmp(originalFee.FeeCap)) > 0) || + (originalFee.FeeCap.Cmp(maxPrice) >= 0) { + return bumped, fmt.Errorf("%w: error while retrieving original dynamic fees: (originalFeePerGas: %s - originalPriorityFeePerGas: %s). Maximum price configured: %s", + commonfee.ErrBump, originalFee.FeeCap, originalFee.TipCap, maxPrice) + } + + currentDynamicPrice, err := f.getDynamicPrice() + if err != nil { + return + } + + bumpedMaxPriorityFeePerGas := originalFee.TipCap.AddPercentage(f.config.BumpPercent) + bumpedMaxFeePerGas := originalFee.FeeCap.AddPercentage(f.config.BumpPercent) + + bumpedMaxPriorityFeePerGas, err = LimitBumpedFee(originalFee.TipCap, currentDynamicPrice.TipCap, bumpedMaxPriorityFeePerGas, maxPrice) + if err != nil { + return bumped, fmt.Errorf("failed to limit maxPriorityFeePerGas: %w", err) + } + + priorityFeeThreshold, e := f.getPriorityFeeThreshold() + if e != nil { + return bumped, e + } + + if bumpedMaxPriorityFeePerGas.Cmp(priorityFeeThreshold) > 0 { + return bumped, fmt.Errorf("bumpedMaxPriorityFeePerGas: %s is above market's %sth percentile: %s, bumping is halted", + bumpedMaxPriorityFeePerGas, strconv.Itoa(ConnectivityPercentile), priorityFeeThreshold) + } + + bumpedMaxFeePerGas, err = LimitBumpedFee(originalFee.FeeCap, currentDynamicPrice.FeeCap, bumpedMaxFeePerGas, maxPrice) + if err != nil { + return bumped, fmt.Errorf("failed to limit maxFeePerGas: %w", err) + } + + bumpedFee := DynamicFee{FeeCap: bumpedMaxFeePerGas, TipCap: bumpedMaxPriorityFeePerGas} + f.logger.Debugw("bumped dynamic fee", "originalFee", originalFee, "marketFee", currentDynamicPrice, "bumpedFee", bumpedFee) + + return bumpedFee, nil +} + +// LimitBumpedFee selects the maximum value between the bumped attempt and the current fee, if there is one. If the result is higher than the max price it gets capped. +// Geth's implementation has a hard 10% minimum limit for the bumped values, otherwise it rejects the transaction with an error. +// See: https://github.com/ethereum/go-ethereum/blob/bff330335b94af3643ac2fb809793f77de3069d4/core/tx_list.go#L298 +// +// Note: for chains that support EIP-1559 but we still choose to send Legacy transactions to them, the limit is still enforcable due to the fact that Legacy transactions +// are treated the same way as Dynamic transactions under the hood. For chains that don't support EIP-1559 at all, the limit isn't enforcable but a 10% minimum bump percentage +// makes sense anyway. +func LimitBumpedFee(originalFee *assets.Wei, currentFee *assets.Wei, bumpedFee *assets.Wei, maxPrice *assets.Wei) (*assets.Wei, error) { + if currentFee != nil { + bumpedFee = assets.WeiMax(currentFee, bumpedFee) + } + bumpedFee = assets.WeiMin(bumpedFee, maxPrice) + + // The first check is added for the following edge case: + // If originalFee is below 10 wei, then adding the minimum bump percentage won't have any effect on the final value because of rounding down. + // Similarly for bumpedFee, it can have the exact same value as the originalFee, even if we bumped, given an originalFee of less than 10 wei + // and a small enough BumpPercent. + if bumpedFee.Cmp(originalFee) == 0 || + bumpedFee.Cmp(originalFee.AddPercentage(MinimumBumpPercentage)) < 0 { + return nil, fmt.Errorf("%w: %s is bumped less than minimum allowed percentage(%s) from originalFee: %s - maxPrice: %s", + commonfee.ErrBump, bumpedFee, strconv.Itoa(MinimumBumpPercentage), originalFee, maxPrice) + } + return bumpedFee, nil +} + +func (f *FeeHistoryEstimator) getPriorityFeeThreshold() (*assets.Wei, error) { + f.priorityFeeThresholdMu.RLock() + defer f.priorityFeeThresholdMu.RUnlock() + if f.priorityFeeThreshold == nil { + return f.priorityFeeThreshold, fmt.Errorf("priorityFeeThreshold not set") + } + return f.priorityFeeThreshold, nil +} + +func (f *FeeHistoryEstimator) Name() string { return f.logger.Name() } +func (f *FeeHistoryEstimator) L1Oracle() rollups.L1Oracle { return f.l1Oracle } +func (f *FeeHistoryEstimator) HealthReport() map[string]error { return map[string]error{f.Name(): nil} } +func (f *FeeHistoryEstimator) OnNewLongestChain(context.Context, *evmtypes.Head) {} diff --git a/core/chains/evm/gas/fee_history_estimator_test.go b/core/chains/evm/gas/fee_history_estimator_test.go new file mode 100644 index 0000000000..6e42e0e209 --- /dev/null +++ b/core/chains/evm/gas/fee_history_estimator_test.go @@ -0,0 +1,513 @@ +package gas_test + +import ( + "math/big" + "testing" + "time" + + "github.com/ethereum/go-ethereum" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-common/pkg/services/servicetest" + "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/mocks" +) + +func TestFeeHistoryEstimatorLifecycle(t *testing.T) { + t.Parallel() + var gasLimit uint64 = 21000 + maxPrice := assets.NewWeiI(100) + chainID := big.NewInt(0) + + t.Run("fails if you fetch gas price before the estimator starts", func(t *testing.T) { + cfg := gas.FeeHistoryEstimatorConfig{ + BumpPercent: 20, + RewardPercentile: 60, + EIP1559: false, + } + + u := gas.NewFeeHistoryEstimator(logger.Test(t), nil, cfg, chainID, nil) + _, _, err := u.GetLegacyGas(tests.Context(t), nil, gasLimit, maxPrice) + assert.ErrorContains(t, err, "gas price not set") + }) + + t.Run("fails to start if BumpPercent is lower than the minimum cap", func(t *testing.T) { + cfg := gas.FeeHistoryEstimatorConfig{BumpPercent: 9} + + u := gas.NewFeeHistoryEstimator(logger.Test(t), nil, cfg, chainID, nil) + assert.ErrorContains(t, u.Start(tests.Context(t)), "BumpPercent") + }) + + t.Run("fails to start if RewardPercentile is higher than ConnectivityPercentile in EIP-1559", func(t *testing.T) { + cfg := gas.FeeHistoryEstimatorConfig{ + BumpPercent: 20, + RewardPercentile: 99, + EIP1559: true, + } + + u := gas.NewFeeHistoryEstimator(logger.Test(t), nil, cfg, chainID, nil) + assert.ErrorContains(t, u.Start(tests.Context(t)), "RewardPercentile") + }) + + t.Run("starts if configs are correct", func(t *testing.T) { + client := mocks.NewFeeHistoryEstimatorClient(t) + client.On("SuggestGasPrice", mock.Anything).Return(big.NewInt(10), nil).Maybe() + + cfg := gas.FeeHistoryEstimatorConfig{ + BumpPercent: 20, + RewardPercentile: 10, + CacheTimeout: 10 * time.Second, + } + + u := gas.NewFeeHistoryEstimator(logger.Test(t), nil, cfg, chainID, nil) + err := u.Start(tests.Context(t)) + assert.NoError(t, err) + err = u.Close() + assert.NoError(t, err) + }) +} + +func TestFeeHistoryEstimatorGetLegacyGas(t *testing.T) { + t.Parallel() + + var gasLimit uint64 = 21000 + maxPrice := assets.NewWeiI(100) + chainID := big.NewInt(0) + + t.Run("fetches a new gas price when first called", func(t *testing.T) { + client := mocks.NewFeeHistoryEstimatorClient(t) + client.On("SuggestGasPrice", mock.Anything).Return(big.NewInt(10), nil).Once() + + cfg := gas.FeeHistoryEstimatorConfig{} + + u := gas.NewFeeHistoryEstimator(logger.Test(t), client, cfg, chainID, nil) + _, err := u.RefreshGasPrice() + assert.NoError(t, err) + gasPrice, _, err := u.GetLegacyGas(tests.Context(t), nil, gasLimit, maxPrice) + assert.NoError(t, err) + assert.Equal(t, assets.NewWeiI(10), gasPrice) + }) + + t.Run("will return max price if estimation exceeds it", func(t *testing.T) { + client := mocks.NewFeeHistoryEstimatorClient(t) + client.On("SuggestGasPrice", mock.Anything).Return(big.NewInt(10), nil).Once() + + cfg := gas.FeeHistoryEstimatorConfig{} + + maxPrice := assets.NewWeiI(1) + u := gas.NewFeeHistoryEstimator(logger.Test(t), client, cfg, chainID, nil) + _, err := u.RefreshGasPrice() + assert.NoError(t, err) + gas1, _, err := u.GetLegacyGas(tests.Context(t), nil, gasLimit, maxPrice) + assert.NoError(t, err) + assert.Equal(t, maxPrice, gas1) + }) + + t.Run("fails if gas price has not been set yet", func(t *testing.T) { + cfg := gas.FeeHistoryEstimatorConfig{} + + maxPrice := assets.NewWeiI(1) + u := gas.NewFeeHistoryEstimator(logger.Test(t), nil, cfg, chainID, nil) + _, _, err := u.GetLegacyGas(tests.Context(t), nil, gasLimit, maxPrice) + assert.Error(t, err) + assert.ErrorContains(t, err, "gas price not set") + }) +} + +func TestFeeHistoryEstimatorBumpLegacyGas(t *testing.T) { + t.Parallel() + + var gasLimit uint64 = 21000 + maxPrice := assets.NewWeiI(100) + chainID := big.NewInt(0) + + t.Run("bumps a previous attempt by BumpPercent", func(t *testing.T) { + client := mocks.NewFeeHistoryEstimatorClient(t) + originalGasPrice := assets.NewWeiI(10) + client.On("SuggestGasPrice", mock.Anything).Return(big.NewInt(10), nil) + + cfg := gas.FeeHistoryEstimatorConfig{BumpPercent: 50, CacheTimeout: 5 * time.Second} + + u := gas.NewFeeHistoryEstimator(logger.Test(t), client, cfg, chainID, nil) + servicetest.RunHealthy(t, u) + gasPrice, _, err := u.BumpLegacyGas(tests.Context(t), originalGasPrice, gasLimit, maxPrice, nil) + assert.NoError(t, err) + assert.Equal(t, assets.NewWeiI(15), gasPrice) + }) + + t.Run("fails if the original attempt is nil, or equal or higher than the max price", func(t *testing.T) { + client := mocks.NewFeeHistoryEstimatorClient(t) + + cfg := gas.FeeHistoryEstimatorConfig{} + u := gas.NewFeeHistoryEstimator(logger.Test(t), client, cfg, chainID, nil) + + var originalPrice *assets.Wei + _, _, err := u.BumpLegacyGas(tests.Context(t), originalPrice, gasLimit, maxPrice, nil) + assert.Error(t, err) + + originalPrice = assets.NewWeiI(100) + _, _, err = u.BumpLegacyGas(tests.Context(t), originalPrice, gasLimit, maxPrice, nil) + assert.Error(t, err) + }) + + t.Run("returns market gas price if bumped original fee is lower", func(t *testing.T) { + client := mocks.NewFeeHistoryEstimatorClient(t) + client.On("SuggestGasPrice", mock.Anything).Return(big.NewInt(80), nil).Once() + originalGasPrice := assets.NewWeiI(10) + + cfg := gas.FeeHistoryEstimatorConfig{} + + u := gas.NewFeeHistoryEstimator(logger.Test(t), client, cfg, chainID, nil) + gas, _, err := u.BumpLegacyGas(tests.Context(t), originalGasPrice, gasLimit, maxPrice, nil) + assert.NoError(t, err) + assert.Equal(t, assets.NewWeiI(80), gas) + }) + + t.Run("returns max gas price if bumped original fee is higher", func(t *testing.T) { + client := mocks.NewFeeHistoryEstimatorClient(t) + client.On("SuggestGasPrice", mock.Anything).Return(big.NewInt(1), nil).Once() + originalGasPrice := assets.NewWeiI(10) + + cfg := gas.FeeHistoryEstimatorConfig{BumpPercent: 50} + + maxPrice := assets.NewWeiI(14) + u := gas.NewFeeHistoryEstimator(logger.Test(t), client, cfg, chainID, nil) + gas, _, err := u.BumpLegacyGas(tests.Context(t), originalGasPrice, gasLimit, maxPrice, nil) + assert.NoError(t, err) + assert.Equal(t, maxPrice, gas) + }) + + t.Run("returns max gas price if the aggregation of max and original bumped fee is higher", func(t *testing.T) { + client := mocks.NewFeeHistoryEstimatorClient(t) + client.On("SuggestGasPrice", mock.Anything).Return(big.NewInt(1), nil).Once() + originalGasPrice := assets.NewWeiI(10) + + cfg := gas.FeeHistoryEstimatorConfig{BumpPercent: 50} + + maxPrice := assets.NewWeiI(14) + u := gas.NewFeeHistoryEstimator(logger.Test(t), client, cfg, chainID, nil) + gas, _, err := u.BumpLegacyGas(tests.Context(t), originalGasPrice, gasLimit, maxPrice, nil) + assert.NoError(t, err) + assert.Equal(t, maxPrice, gas) + }) + + t.Run("fails if the bumped gas price is lower than the minimum bump percentage", func(t *testing.T) { + client := mocks.NewFeeHistoryEstimatorClient(t) + client.On("SuggestGasPrice", mock.Anything).Return(big.NewInt(100), nil).Once() + originalGasPrice := assets.NewWeiI(100) + + cfg := gas.FeeHistoryEstimatorConfig{BumpPercent: 20} + + // Price will be capped by the max price + maxPrice := assets.NewWeiI(101) + u := gas.NewFeeHistoryEstimator(logger.Test(t), client, cfg, chainID, nil) + _, _, err := u.BumpLegacyGas(tests.Context(t), originalGasPrice, gasLimit, maxPrice, nil) + assert.Error(t, err) + }) +} + +func TestFeeHistoryEstimatorGetDynamicFee(t *testing.T) { + t.Parallel() + + maxPrice := assets.NewWeiI(100) + chainID := big.NewInt(0) + + t.Run("fetches a new dynamic fee when first called", func(t *testing.T) { + client := mocks.NewFeeHistoryEstimatorClient(t) + baseFee := big.NewInt(5) + maxPriorityFeePerGas1 := big.NewInt(33) + maxPriorityFeePerGas2 := big.NewInt(20) + + feeHistoryResult := &ethereum.FeeHistory{ + OldestBlock: big.NewInt(1), + Reward: [][]*big.Int{{maxPriorityFeePerGas1, big.NewInt(5)}, {maxPriorityFeePerGas2, big.NewInt(5)}}, // first one represents market price and second one connectivity price + BaseFee: []*big.Int{baseFee, baseFee}, + GasUsedRatio: nil, + } + client.On("FeeHistory", mock.Anything, mock.Anything, mock.Anything).Return(feeHistoryResult, nil).Once() + + blockHistoryLength := 2 + cfg := gas.FeeHistoryEstimatorConfig{BlockHistorySize: uint64(blockHistoryLength)} + avrgPriorityFee := big.NewInt(0) + avrgPriorityFee.Add(maxPriorityFeePerGas1, maxPriorityFeePerGas2).Div(avrgPriorityFee, big.NewInt(int64(blockHistoryLength))) + maxFee := (*assets.Wei)(baseFee).AddPercentage(gas.BaseFeeBufferPercentage).Add((*assets.Wei)(avrgPriorityFee)) + + u := gas.NewFeeHistoryEstimator(logger.Test(t), client, cfg, chainID, nil) + err := u.RefreshDynamicPrice() + assert.NoError(t, err) + dynamicFee, err := u.GetDynamicFee(tests.Context(t), maxPrice) + assert.NoError(t, err) + assert.Equal(t, maxFee, dynamicFee.FeeCap) + assert.Equal(t, (*assets.Wei)(avrgPriorityFee), dynamicFee.TipCap) + }) + + t.Run("fails if dynamic prices have not been set yet", func(t *testing.T) { + cfg := gas.FeeHistoryEstimatorConfig{} + + maxPrice := assets.NewWeiI(1) + u := gas.NewFeeHistoryEstimator(logger.Test(t), nil, cfg, chainID, nil) + _, err := u.GetDynamicFee(tests.Context(t), maxPrice) + assert.Error(t, err) + assert.ErrorContains(t, err, "dynamic price not set") + }) + + t.Run("will return max price if tip cap or fee cap exceed it", func(t *testing.T) { + client := mocks.NewFeeHistoryEstimatorClient(t) + baseFee := big.NewInt(1) + maxPriorityFeePerGas := big.NewInt(3) + maxPrice := assets.NewWeiI(2) + + feeHistoryResult := &ethereum.FeeHistory{ + OldestBlock: big.NewInt(1), + Reward: [][]*big.Int{{maxPriorityFeePerGas, big.NewInt(5)}}, // first one represents market price and second one connectivity price + BaseFee: []*big.Int{baseFee}, + GasUsedRatio: nil, + } + client.On("FeeHistory", mock.Anything, mock.Anything, mock.Anything).Return(feeHistoryResult, nil).Once() + + cfg := gas.FeeHistoryEstimatorConfig{BlockHistorySize: 1} + + u := gas.NewFeeHistoryEstimator(logger.Test(t), client, cfg, chainID, nil) + err := u.RefreshDynamicPrice() + assert.NoError(t, err) + dynamicFee, err := u.GetDynamicFee(tests.Context(t), maxPrice) + assert.NoError(t, err) + assert.Equal(t, maxPrice, dynamicFee.FeeCap) + assert.Equal(t, maxPrice, dynamicFee.TipCap) + }) +} + +func TestFeeHistoryEstimatorBumpDynamicFee(t *testing.T) { + t.Parallel() + + globalMaxPrice := assets.NewWeiI(100) + chainID := big.NewInt(0) + + t.Run("bumps a previous attempt by BumpPercent", func(t *testing.T) { + client := mocks.NewFeeHistoryEstimatorClient(t) + originalFee := gas.DynamicFee{ + FeeCap: assets.NewWeiI(20), + TipCap: assets.NewWeiI(10), + } + + // These values will be ignored because they are lower prices than the originalFee + feeHistoryResult := &ethereum.FeeHistory{ + OldestBlock: big.NewInt(1), + Reward: [][]*big.Int{{big.NewInt(5), big.NewInt(50)}}, // first one represents market price and second one connectivity price + BaseFee: []*big.Int{big.NewInt(5)}, + GasUsedRatio: nil, + } + client.On("FeeHistory", mock.Anything, mock.Anything, mock.Anything).Return(feeHistoryResult, nil).Once() + + cfg := gas.FeeHistoryEstimatorConfig{ + BlockHistorySize: 2, + BumpPercent: 50, + } + + expectedFeeCap := originalFee.FeeCap.AddPercentage(cfg.BumpPercent) + expectedTipCap := originalFee.TipCap.AddPercentage(cfg.BumpPercent) + + u := gas.NewFeeHistoryEstimator(logger.Test(t), client, cfg, chainID, nil) + err := u.RefreshDynamicPrice() + assert.NoError(t, err) + dynamicFee, err := u.BumpDynamicFee(tests.Context(t), originalFee, globalMaxPrice, nil) + assert.NoError(t, err) + assert.Equal(t, expectedFeeCap, dynamicFee.FeeCap) + assert.Equal(t, expectedTipCap, dynamicFee.TipCap) + }) + + t.Run("fails if the original attempt is invalid", func(t *testing.T) { + client := mocks.NewFeeHistoryEstimatorClient(t) + maxPrice := assets.NewWeiI(20) + cfg := gas.FeeHistoryEstimatorConfig{BlockHistorySize: 1} + + u := gas.NewFeeHistoryEstimator(logger.Test(t), client, cfg, chainID, nil) + // nil original fee + var originalFee gas.DynamicFee + _, err := u.BumpDynamicFee(tests.Context(t), originalFee, maxPrice, nil) + assert.Error(t, err) + + // tip cap is higher than fee cap + originalFee = gas.DynamicFee{ + FeeCap: assets.NewWeiI(10), + TipCap: assets.NewWeiI(11), + } + _, err = u.BumpDynamicFee(tests.Context(t), originalFee, maxPrice, nil) + assert.Error(t, err) + + // fee cap is equal or higher to max price + originalFee = gas.DynamicFee{ + FeeCap: assets.NewWeiI(20), + TipCap: assets.NewWeiI(10), + } + _, err = u.BumpDynamicFee(tests.Context(t), originalFee, maxPrice, nil) + assert.Error(t, err) + }) + + t.Run("returns market prices if bumped original fee is lower", func(t *testing.T) { + client := mocks.NewFeeHistoryEstimatorClient(t) + originalFee := gas.DynamicFee{ + FeeCap: assets.NewWeiI(20), + TipCap: assets.NewWeiI(10), + } + + // Market fees + baseFee := big.NewInt(5) + maxPriorityFeePerGas := big.NewInt(33) + feeHistoryResult := &ethereum.FeeHistory{ + OldestBlock: big.NewInt(1), + Reward: [][]*big.Int{{maxPriorityFeePerGas, big.NewInt(100)}}, // first one represents market price and second one connectivity price + BaseFee: []*big.Int{baseFee}, + GasUsedRatio: nil, + } + client.On("FeeHistory", mock.Anything, mock.Anything, mock.Anything).Return(feeHistoryResult, nil).Once() + + maxFee := (*assets.Wei)(baseFee).AddPercentage(gas.BaseFeeBufferPercentage).Add((*assets.Wei)(maxPriorityFeePerGas)) + + cfg := gas.FeeHistoryEstimatorConfig{ + BlockHistorySize: 1, + BumpPercent: 50, + } + + u := gas.NewFeeHistoryEstimator(logger.Test(t), client, cfg, chainID, nil) + err := u.RefreshDynamicPrice() + assert.NoError(t, err) + bumpedFee, err := u.BumpDynamicFee(tests.Context(t), originalFee, globalMaxPrice, nil) + assert.NoError(t, err) + assert.Equal(t, (*assets.Wei)(maxPriorityFeePerGas), bumpedFee.TipCap) + assert.Equal(t, maxFee, bumpedFee.FeeCap) + }) + + t.Run("fails if connectivity percentile value is reached", func(t *testing.T) { + client := mocks.NewFeeHistoryEstimatorClient(t) + originalFee := gas.DynamicFee{ + FeeCap: assets.NewWeiI(20), + TipCap: assets.NewWeiI(10), + } + + // Market fees + baseFee := big.NewInt(5) + maxPriorityFeePerGas := big.NewInt(33) + feeHistoryResult := &ethereum.FeeHistory{ + OldestBlock: big.NewInt(1), + Reward: [][]*big.Int{{maxPriorityFeePerGas, big.NewInt(30)}}, // first one represents market price and second one connectivity price + BaseFee: []*big.Int{baseFee}, + GasUsedRatio: nil, + } + client.On("FeeHistory", mock.Anything, mock.Anything, mock.Anything).Return(feeHistoryResult, nil).Once() + + cfg := gas.FeeHistoryEstimatorConfig{ + BlockHistorySize: 1, + BumpPercent: 50, + } + + u := gas.NewFeeHistoryEstimator(logger.Test(t), client, cfg, chainID, nil) + err := u.RefreshDynamicPrice() + assert.NoError(t, err) + _, err = u.BumpDynamicFee(tests.Context(t), originalFee, globalMaxPrice, nil) + assert.Error(t, err) + }) + + t.Run("returns max price if the aggregation of max and original bumped fee is higher", func(t *testing.T) { + client := mocks.NewFeeHistoryEstimatorClient(t) + originalFee := gas.DynamicFee{ + FeeCap: assets.NewWeiI(20), + TipCap: assets.NewWeiI(18), + } + + maxPrice := assets.NewWeiI(25) + // Market fees + baseFee := big.NewInt(1) + maxPriorityFeePerGas := big.NewInt(1) + feeHistoryResult := &ethereum.FeeHistory{ + OldestBlock: big.NewInt(1), + Reward: [][]*big.Int{{maxPriorityFeePerGas, big.NewInt(30)}}, // first one represents market price and second one connectivity price + BaseFee: []*big.Int{baseFee}, + GasUsedRatio: nil, + } + client.On("FeeHistory", mock.Anything, mock.Anything, mock.Anything).Return(feeHistoryResult, nil).Once() + + cfg := gas.FeeHistoryEstimatorConfig{ + BlockHistorySize: 1, + BumpPercent: 50, + } + + u := gas.NewFeeHistoryEstimator(logger.Test(t), client, cfg, chainID, nil) + err := u.RefreshDynamicPrice() + assert.NoError(t, err) + bumpedFee, err := u.BumpDynamicFee(tests.Context(t), originalFee, maxPrice, nil) + assert.NoError(t, err) + assert.Equal(t, maxPrice, bumpedFee.TipCap) + assert.Equal(t, maxPrice, bumpedFee.FeeCap) + }) + + t.Run("fails if the bumped gas price is lower than the minimum bump percentage", func(t *testing.T) { + client := mocks.NewFeeHistoryEstimatorClient(t) + originalFee := gas.DynamicFee{ + FeeCap: assets.NewWeiI(20), + TipCap: assets.NewWeiI(18), + } + + maxPrice := assets.NewWeiI(21) + // Market fees + baseFee := big.NewInt(1) + maxPriorityFeePerGas := big.NewInt(1) + feeHistoryResult := &ethereum.FeeHistory{ + OldestBlock: big.NewInt(1), + Reward: [][]*big.Int{{maxPriorityFeePerGas, big.NewInt(30)}}, // first one represents market price and second one connectivity price + BaseFee: []*big.Int{baseFee}, + GasUsedRatio: nil, + } + client.On("FeeHistory", mock.Anything, mock.Anything, mock.Anything).Return(feeHistoryResult, nil).Once() + + cfg := gas.FeeHistoryEstimatorConfig{ + BlockHistorySize: 1, + BumpPercent: 50, + } + + u := gas.NewFeeHistoryEstimator(logger.Test(t), client, cfg, chainID, nil) + err := u.RefreshDynamicPrice() + assert.NoError(t, err) + _, err = u.BumpDynamicFee(tests.Context(t), originalFee, maxPrice, nil) + assert.Error(t, err) + }) + + t.Run("ignores maxPriorityFeePerGas if there is no mempool and forces refetch", func(t *testing.T) { + client := mocks.NewFeeHistoryEstimatorClient(t) + originalFee := gas.DynamicFee{ + FeeCap: assets.NewWeiI(40), + TipCap: assets.NewWeiI(0), + } + + // Market fees + baseFee := big.NewInt(10) + maxPriorityFeePerGas := big.NewInt(0) + feeHistoryResult := &ethereum.FeeHistory{ + OldestBlock: big.NewInt(1), + Reward: [][]*big.Int{{maxPriorityFeePerGas, big.NewInt(0)}}, // first one represents market price and second one connectivity price + BaseFee: []*big.Int{baseFee}, + GasUsedRatio: nil, + } + client.On("FeeHistory", mock.Anything, mock.Anything, mock.Anything).Return(feeHistoryResult, nil) + + cfg := gas.FeeHistoryEstimatorConfig{ + BlockHistorySize: 0, + BumpPercent: 20, + CacheTimeout: 10 * time.Second, + EIP1559: true, + } + + maxFeePerGas := assets.NewWei(baseFee).AddPercentage(gas.BaseFeeBufferPercentage) + u := gas.NewFeeHistoryEstimator(logger.Test(t), client, cfg, chainID, nil) + servicetest.RunHealthy(t, u) + bumpedFee, err := u.BumpDynamicFee(tests.Context(t), originalFee, globalMaxPrice, nil) + assert.NoError(t, err) + assert.Equal(t, assets.NewWeiI(0), (*assets.Wei)(maxPriorityFeePerGas)) + assert.Equal(t, maxFeePerGas, bumpedFee.FeeCap) + }) +} diff --git a/core/chains/evm/gas/mocks/fee_estimator_client.go b/core/chains/evm/gas/mocks/fee_estimator_client.go index ab99eb7b0d..f5ca52ec92 100644 --- a/core/chains/evm/gas/mocks/fee_estimator_client.go +++ b/core/chains/evm/gas/mocks/fee_estimator_client.go @@ -298,6 +298,66 @@ func (_c *FeeEstimatorClient_EstimateGas_Call) RunAndReturn(run func(context.Con return _c } +// FeeHistory provides a mock function with given fields: ctx, blockCount, rewardPercentiles +func (_m *FeeEstimatorClient) FeeHistory(ctx context.Context, blockCount uint64, rewardPercentiles []float64) (*ethereum.FeeHistory, error) { + ret := _m.Called(ctx, blockCount, rewardPercentiles) + + if len(ret) == 0 { + panic("no return value specified for FeeHistory") + } + + var r0 *ethereum.FeeHistory + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, uint64, []float64) (*ethereum.FeeHistory, error)); ok { + return rf(ctx, blockCount, rewardPercentiles) + } + if rf, ok := ret.Get(0).(func(context.Context, uint64, []float64) *ethereum.FeeHistory); ok { + r0 = rf(ctx, blockCount, rewardPercentiles) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*ethereum.FeeHistory) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, uint64, []float64) error); ok { + r1 = rf(ctx, blockCount, rewardPercentiles) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeEstimatorClient_FeeHistory_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FeeHistory' +type FeeEstimatorClient_FeeHistory_Call struct { + *mock.Call +} + +// FeeHistory is a helper method to define mock.On call +// - ctx context.Context +// - blockCount uint64 +// - rewardPercentiles []float64 +func (_e *FeeEstimatorClient_Expecter) FeeHistory(ctx interface{}, blockCount interface{}, rewardPercentiles interface{}) *FeeEstimatorClient_FeeHistory_Call { + return &FeeEstimatorClient_FeeHistory_Call{Call: _e.mock.On("FeeHistory", ctx, blockCount, rewardPercentiles)} +} + +func (_c *FeeEstimatorClient_FeeHistory_Call) Run(run func(ctx context.Context, blockCount uint64, rewardPercentiles []float64)) *FeeEstimatorClient_FeeHistory_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(uint64), args[2].([]float64)) + }) + return _c +} + +func (_c *FeeEstimatorClient_FeeHistory_Call) Return(feeHistory *ethereum.FeeHistory, err error) *FeeEstimatorClient_FeeHistory_Call { + _c.Call.Return(feeHistory, err) + return _c +} + +func (_c *FeeEstimatorClient_FeeHistory_Call) RunAndReturn(run func(context.Context, uint64, []float64) (*ethereum.FeeHistory, error)) *FeeEstimatorClient_FeeHistory_Call { + _c.Call.Return(run) + return _c +} + // HeadByNumber provides a mock function with given fields: ctx, n func (_m *FeeEstimatorClient) HeadByNumber(ctx context.Context, n *big.Int) (*types.Head, error) { ret := _m.Called(ctx, n) @@ -357,6 +417,64 @@ func (_c *FeeEstimatorClient_HeadByNumber_Call) RunAndReturn(run func(context.Co return _c } +// SuggestGasPrice provides a mock function with given fields: ctx +func (_m *FeeEstimatorClient) SuggestGasPrice(ctx context.Context) (*big.Int, error) { + ret := _m.Called(ctx) + + if len(ret) == 0 { + panic("no return value specified for SuggestGasPrice") + } + + var r0 *big.Int + var r1 error + if rf, ok := ret.Get(0).(func(context.Context) (*big.Int, error)); ok { + return rf(ctx) + } + if rf, ok := ret.Get(0).(func(context.Context) *big.Int); ok { + r0 = rf(ctx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*big.Int) + } + } + + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeEstimatorClient_SuggestGasPrice_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SuggestGasPrice' +type FeeEstimatorClient_SuggestGasPrice_Call struct { + *mock.Call +} + +// SuggestGasPrice is a helper method to define mock.On call +// - ctx context.Context +func (_e *FeeEstimatorClient_Expecter) SuggestGasPrice(ctx interface{}) *FeeEstimatorClient_SuggestGasPrice_Call { + return &FeeEstimatorClient_SuggestGasPrice_Call{Call: _e.mock.On("SuggestGasPrice", ctx)} +} + +func (_c *FeeEstimatorClient_SuggestGasPrice_Call) Run(run func(ctx context.Context)) *FeeEstimatorClient_SuggestGasPrice_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context)) + }) + return _c +} + +func (_c *FeeEstimatorClient_SuggestGasPrice_Call) Return(_a0 *big.Int, _a1 error) *FeeEstimatorClient_SuggestGasPrice_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeEstimatorClient_SuggestGasPrice_Call) RunAndReturn(run func(context.Context) (*big.Int, error)) *FeeEstimatorClient_SuggestGasPrice_Call { + _c.Call.Return(run) + return _c +} + // NewFeeEstimatorClient creates a new instance of FeeEstimatorClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. // The first argument is typically a *testing.T value. func NewFeeEstimatorClient(t interface { diff --git a/core/chains/evm/gas/mocks/fee_history_estimator_client.go b/core/chains/evm/gas/mocks/fee_history_estimator_client.go new file mode 100644 index 0000000000..7486214501 --- /dev/null +++ b/core/chains/evm/gas/mocks/fee_history_estimator_client.go @@ -0,0 +1,157 @@ +// Code generated by mockery v2.43.2. DO NOT EDIT. + +package mocks + +import ( + context "context" + big "math/big" + + ethereum "github.com/ethereum/go-ethereum" + + mock "github.com/stretchr/testify/mock" +) + +// FeeHistoryEstimatorClient is an autogenerated mock type for the feeHistoryEstimatorClient type +type FeeHistoryEstimatorClient struct { + mock.Mock +} + +type FeeHistoryEstimatorClient_Expecter struct { + mock *mock.Mock +} + +func (_m *FeeHistoryEstimatorClient) EXPECT() *FeeHistoryEstimatorClient_Expecter { + return &FeeHistoryEstimatorClient_Expecter{mock: &_m.Mock} +} + +// FeeHistory provides a mock function with given fields: ctx, blockCount, rewardPercentiles +func (_m *FeeHistoryEstimatorClient) FeeHistory(ctx context.Context, blockCount uint64, rewardPercentiles []float64) (*ethereum.FeeHistory, error) { + ret := _m.Called(ctx, blockCount, rewardPercentiles) + + if len(ret) == 0 { + panic("no return value specified for FeeHistory") + } + + var r0 *ethereum.FeeHistory + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, uint64, []float64) (*ethereum.FeeHistory, error)); ok { + return rf(ctx, blockCount, rewardPercentiles) + } + if rf, ok := ret.Get(0).(func(context.Context, uint64, []float64) *ethereum.FeeHistory); ok { + r0 = rf(ctx, blockCount, rewardPercentiles) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*ethereum.FeeHistory) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, uint64, []float64) error); ok { + r1 = rf(ctx, blockCount, rewardPercentiles) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeHistoryEstimatorClient_FeeHistory_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'FeeHistory' +type FeeHistoryEstimatorClient_FeeHistory_Call struct { + *mock.Call +} + +// FeeHistory is a helper method to define mock.On call +// - ctx context.Context +// - blockCount uint64 +// - rewardPercentiles []float64 +func (_e *FeeHistoryEstimatorClient_Expecter) FeeHistory(ctx interface{}, blockCount interface{}, rewardPercentiles interface{}) *FeeHistoryEstimatorClient_FeeHistory_Call { + return &FeeHistoryEstimatorClient_FeeHistory_Call{Call: _e.mock.On("FeeHistory", ctx, blockCount, rewardPercentiles)} +} + +func (_c *FeeHistoryEstimatorClient_FeeHistory_Call) Run(run func(ctx context.Context, blockCount uint64, rewardPercentiles []float64)) *FeeHistoryEstimatorClient_FeeHistory_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(uint64), args[2].([]float64)) + }) + return _c +} + +func (_c *FeeHistoryEstimatorClient_FeeHistory_Call) Return(feeHistory *ethereum.FeeHistory, err error) *FeeHistoryEstimatorClient_FeeHistory_Call { + _c.Call.Return(feeHistory, err) + return _c +} + +func (_c *FeeHistoryEstimatorClient_FeeHistory_Call) RunAndReturn(run func(context.Context, uint64, []float64) (*ethereum.FeeHistory, error)) *FeeHistoryEstimatorClient_FeeHistory_Call { + _c.Call.Return(run) + return _c +} + +// SuggestGasPrice provides a mock function with given fields: ctx +func (_m *FeeHistoryEstimatorClient) SuggestGasPrice(ctx context.Context) (*big.Int, error) { + ret := _m.Called(ctx) + + if len(ret) == 0 { + panic("no return value specified for SuggestGasPrice") + } + + var r0 *big.Int + var r1 error + if rf, ok := ret.Get(0).(func(context.Context) (*big.Int, error)); ok { + return rf(ctx) + } + if rf, ok := ret.Get(0).(func(context.Context) *big.Int); ok { + r0 = rf(ctx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*big.Int) + } + } + + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FeeHistoryEstimatorClient_SuggestGasPrice_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SuggestGasPrice' +type FeeHistoryEstimatorClient_SuggestGasPrice_Call struct { + *mock.Call +} + +// SuggestGasPrice is a helper method to define mock.On call +// - ctx context.Context +func (_e *FeeHistoryEstimatorClient_Expecter) SuggestGasPrice(ctx interface{}) *FeeHistoryEstimatorClient_SuggestGasPrice_Call { + return &FeeHistoryEstimatorClient_SuggestGasPrice_Call{Call: _e.mock.On("SuggestGasPrice", ctx)} +} + +func (_c *FeeHistoryEstimatorClient_SuggestGasPrice_Call) Run(run func(ctx context.Context)) *FeeHistoryEstimatorClient_SuggestGasPrice_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context)) + }) + return _c +} + +func (_c *FeeHistoryEstimatorClient_SuggestGasPrice_Call) Return(_a0 *big.Int, _a1 error) *FeeHistoryEstimatorClient_SuggestGasPrice_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *FeeHistoryEstimatorClient_SuggestGasPrice_Call) RunAndReturn(run func(context.Context) (*big.Int, error)) *FeeHistoryEstimatorClient_SuggestGasPrice_Call { + _c.Call.Return(run) + return _c +} + +// NewFeeHistoryEstimatorClient creates a new instance of FeeHistoryEstimatorClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewFeeHistoryEstimatorClient(t interface { + mock.TestingT + Cleanup(func()) +}) *FeeHistoryEstimatorClient { + mock := &FeeHistoryEstimatorClient{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/core/chains/evm/gas/models.go b/core/chains/evm/gas/models.go index af569a1332..d844f8774a 100644 --- a/core/chains/evm/gas/models.go +++ b/core/chains/evm/gas/models.go @@ -50,6 +50,8 @@ type feeEstimatorClient interface { ConfiguredChainID() *big.Int HeadByNumber(ctx context.Context, n *big.Int) (*evmtypes.Head, error) EstimateGas(ctx context.Context, call ethereum.CallMsg) (uint64, error) + SuggestGasPrice(ctx context.Context) (*big.Int, error) + FeeHistory(ctx context.Context, blockCount uint64, rewardPercentiles []float64) (feeHistory *ethereum.FeeHistory, err error) } // NewEstimator returns the estimator for a given config @@ -110,6 +112,18 @@ func NewEstimator(lggr logger.Logger, ethClient feeEstimatorClient, cfg Config, newEstimator = func(l logger.Logger) EvmEstimator { return NewSuggestedPriceEstimator(lggr, ethClient, geCfg, l1Oracle) } + case "FeeHistory": + newEstimator = func(l logger.Logger) EvmEstimator { + ccfg := FeeHistoryEstimatorConfig{ + BumpPercent: geCfg.BumpPercent(), + CacheTimeout: geCfg.FeeHistory().CacheTimeout(), + EIP1559: geCfg.EIP1559DynamicFees(), + BlockHistorySize: uint64(geCfg.BlockHistory().BlockHistorySize()), + RewardPercentile: float64(geCfg.BlockHistory().TransactionPercentile()), + } + return NewFeeHistoryEstimator(lggr, ethClient, ccfg, ethClient.ConfiguredChainID(), l1Oracle) + } + default: lggr.Warnf("GasEstimator: unrecognised mode '%s', falling back to FixedPriceEstimator", s) newEstimator = func(l logger.Logger) EvmEstimator { diff --git a/core/chains/evm/txmgr/test_helpers.go b/core/chains/evm/txmgr/test_helpers.go index 963c608b53..b1317cb421 100644 --- a/core/chains/evm/txmgr/test_helpers.go +++ b/core/chains/evm/txmgr/test_helpers.go @@ -73,6 +73,10 @@ func (g *TestGasEstimatorConfig) BlockHistory() evmconfig.BlockHistory { return &TestBlockHistoryConfig{} } +func (g *TestGasEstimatorConfig) FeeHistory() evmconfig.FeeHistory { + return &TestFeeHistoryConfig{} +} + func (g *TestGasEstimatorConfig) EIP1559DynamicFees() bool { return false } func (g *TestGasEstimatorConfig) LimitDefault() uint64 { return 42 } func (g *TestGasEstimatorConfig) BumpPercent() uint16 { return 42 } @@ -121,6 +125,12 @@ func (b *TestBlockHistoryConfig) BlockHistorySize() uint16 { return 42 func (b *TestBlockHistoryConfig) EIP1559FeeCapBufferBlocks() uint16 { return 42 } func (b *TestBlockHistoryConfig) TransactionPercentile() uint16 { return 42 } +type TestFeeHistoryConfig struct { + evmconfig.FeeHistory +} + +func (b *TestFeeHistoryConfig) CacheTimeout() time.Duration { return 0 * time.Second } + type transactionsConfig struct { evmconfig.Transactions e *TestEvmConfig diff --git a/core/config/docs/chains-evm.toml b/core/config/docs/chains-evm.toml index 385432e12c..bffc9ddf0c 100644 --- a/core/config/docs/chains-evm.toml +++ b/core/config/docs/chains-evm.toml @@ -312,6 +312,15 @@ EIP1559FeeCapBufferBlocks = 13 # Example # Setting it lower will tend to set lower gas prices. TransactionPercentile = 60 # Default +[EVM.GasEstimator.FeeHistory] +# CacheTimeout is the time to wait in order to refresh the cached values stored in the FeeHistory estimator. A small jitter is applied so the timeout won't be exactly the same each time. +# +# You want this value to be close to the block time. For slower chains, like Ethereum, you can set it to 12s, the same as the block time. For faster chains you can skip a block or two +# and set it to two times the block time i.e. on Optimism you can set it to 4s. Ideally, you don't want to go lower than 1s since the RTT times of the RPC requests will be comparable to +# the timeout. The estimator is already adding a buffer to account for a potential increase in prices within one or two blocks. On the other hand, slower frequency will fail to refresh +# the prices and end up in stale values. +CacheTimeout = '10s' # Default + # The head tracker continually listens for new heads from the chain. # # In addition to these settings, it log warnings if `EVM.NoNewHeadsThreshold` is exceeded without any new blocks being emitted. diff --git a/core/services/chainlink/config_test.go b/core/services/chainlink/config_test.go index 76150d2680..9afc0aa942 100644 --- a/core/services/chainlink/config_test.go +++ b/core/services/chainlink/config_test.go @@ -544,6 +544,9 @@ func TestConfig_Marshal(t *testing.T) { EIP1559FeeCapBufferBlocks: ptr[uint16](13), TransactionPercentile: ptr[uint16](15), }, + FeeHistory: evmcfg.FeeHistoryEstimator{ + CacheTimeout: &second, + }, }, KeySpecific: []evmcfg.KeySpecific{ @@ -1051,6 +1054,9 @@ CheckInclusionPercentile = 19 EIP1559FeeCapBufferBlocks = 13 TransactionPercentile = 15 +[EVM.GasEstimator.FeeHistory] +CacheTimeout = '1s' + [EVM.HeadTracker] HistoryDepth = 15 MaxBufferSize = 17 diff --git a/core/services/chainlink/testdata/config-full.toml b/core/services/chainlink/testdata/config-full.toml index 08f688dfac..c10d59f339 100644 --- a/core/services/chainlink/testdata/config-full.toml +++ b/core/services/chainlink/testdata/config-full.toml @@ -342,6 +342,9 @@ CheckInclusionPercentile = 19 EIP1559FeeCapBufferBlocks = 13 TransactionPercentile = 15 +[EVM.GasEstimator.FeeHistory] +CacheTimeout = '1s' + [EVM.HeadTracker] HistoryDepth = 15 MaxBufferSize = 17 diff --git a/core/services/chainlink/testdata/config-multi-chain-effective.toml b/core/services/chainlink/testdata/config-multi-chain-effective.toml index 4de06be86d..edb8d0a249 100644 --- a/core/services/chainlink/testdata/config-multi-chain-effective.toml +++ b/core/services/chainlink/testdata/config-multi-chain-effective.toml @@ -319,6 +319,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 50 +[EVM.GasEstimator.FeeHistory] +CacheTimeout = '10s' + [EVM.HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 @@ -420,6 +423,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 50 +[EVM.GasEstimator.FeeHistory] +CacheTimeout = '10s' + [EVM.HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 @@ -515,6 +521,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[EVM.GasEstimator.FeeHistory] +CacheTimeout = '10s' + [EVM.HeadTracker] HistoryDepth = 2000 MaxBufferSize = 3 diff --git a/core/web/resolver/testdata/config-full.toml b/core/web/resolver/testdata/config-full.toml index d046a2ab8b..b546042756 100644 --- a/core/web/resolver/testdata/config-full.toml +++ b/core/web/resolver/testdata/config-full.toml @@ -341,6 +341,9 @@ CheckInclusionPercentile = 19 EIP1559FeeCapBufferBlocks = 13 TransactionPercentile = 15 +[EVM.GasEstimator.FeeHistory] +CacheTimeout = '1s' + [EVM.HeadTracker] HistoryDepth = 15 MaxBufferSize = 17 diff --git a/core/web/resolver/testdata/config-multi-chain-effective.toml b/core/web/resolver/testdata/config-multi-chain-effective.toml index df335e0474..ca9edca06f 100644 --- a/core/web/resolver/testdata/config-multi-chain-effective.toml +++ b/core/web/resolver/testdata/config-multi-chain-effective.toml @@ -319,6 +319,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 50 +[EVM.GasEstimator.FeeHistory] +CacheTimeout = '10s' + [EVM.HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 @@ -420,6 +423,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 50 +[EVM.GasEstimator.FeeHistory] +CacheTimeout = '10s' + [EVM.HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 @@ -515,6 +521,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[EVM.GasEstimator.FeeHistory] +CacheTimeout = '10s' + [EVM.HeadTracker] HistoryDepth = 2000 MaxBufferSize = 3 diff --git a/docs/CONFIG.md b/docs/CONFIG.md index f0c5b1808b..c315b574e7 100644 --- a/docs/CONFIG.md +++ b/docs/CONFIG.md @@ -1834,6 +1834,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 50 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 @@ -1929,6 +1932,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 50 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 @@ -2024,6 +2030,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 50 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 @@ -2119,6 +2128,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 50 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 @@ -2215,6 +2227,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 300 MaxBufferSize = 3 @@ -2310,6 +2325,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 @@ -2405,6 +2423,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 @@ -2501,6 +2522,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 50 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 @@ -2596,6 +2620,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 @@ -2690,6 +2717,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 @@ -2877,6 +2907,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 @@ -2972,6 +3005,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 @@ -3068,6 +3104,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 @@ -3163,6 +3202,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 @@ -3258,6 +3300,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 2000 MaxBufferSize = 3 @@ -3353,6 +3398,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 2000 MaxBufferSize = 3 @@ -3448,6 +3496,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 2000 MaxBufferSize = 3 @@ -3543,6 +3594,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 @@ -3638,6 +3692,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 400 MaxBufferSize = 3 @@ -3733,6 +3790,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 50 MaxBufferSize = 3 @@ -3828,6 +3888,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 250 MaxBufferSize = 3 @@ -3923,6 +3986,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 1500 MaxBufferSize = 3 @@ -4019,6 +4085,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 300 MaxBufferSize = 3 @@ -4114,6 +4183,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 @@ -4396,6 +4468,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 @@ -4491,6 +4566,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 @@ -4586,6 +4664,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 2000 MaxBufferSize = 3 @@ -4681,6 +4762,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 @@ -4776,6 +4860,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 @@ -4870,6 +4957,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 10 MaxBufferSize = 100 @@ -4965,6 +5055,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 2000 MaxBufferSize = 3 @@ -5060,6 +5153,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 400 MaxBufferSize = 3 @@ -5155,6 +5251,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 2000 MaxBufferSize = 3 @@ -5250,6 +5349,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 @@ -5439,6 +5541,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 @@ -5534,6 +5639,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 300 MaxBufferSize = 3 @@ -5629,6 +5737,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 @@ -5725,6 +5836,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 @@ -5821,6 +5935,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 @@ -6012,6 +6129,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 @@ -6107,6 +6227,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 50 MaxBufferSize = 3 @@ -6202,6 +6325,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 @@ -6297,6 +6423,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 @@ -6392,6 +6521,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 50 MaxBufferSize = 3 @@ -6486,6 +6618,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 @@ -6580,6 +6715,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 1000 MaxBufferSize = 3 @@ -6674,6 +6812,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 350 MaxBufferSize = 3 @@ -6769,6 +6910,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 @@ -6958,6 +7102,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 2000 MaxBufferSize = 3 @@ -7052,6 +7199,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 2000 MaxBufferSize = 3 @@ -7242,6 +7392,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 300 MaxBufferSize = 3 @@ -7338,6 +7491,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 300 MaxBufferSize = 3 @@ -7434,6 +7590,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 @@ -7530,6 +7689,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 @@ -7626,6 +7788,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 @@ -7721,6 +7886,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 50 MaxBufferSize = 3 @@ -7816,6 +7984,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 50 MaxBufferSize = 3 @@ -7911,6 +8082,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 50 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 @@ -8006,6 +8180,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 300 MaxBufferSize = 3 @@ -8196,6 +8373,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 @@ -8291,6 +8471,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 @@ -8952,6 +9135,24 @@ Setting this number higher will cause the Chainlink node to select higher gas pr Setting it lower will tend to set lower gas prices. +## EVM.GasEstimator.FeeHistory +```toml +[EVM.GasEstimator.FeeHistory] +CacheTimeout = '10s' # Default +``` + + +### CacheTimeout +```toml +CacheTimeout = '10s' # Default +``` +CacheTimeout is the time to wait in order to refresh the cached values stored in the FeeHistory estimator. A small jitter is applied so the timeout won't be exactly the same each time. + +You want this value to be close to the block time. For slower chains, like Ethereum, you can set it to 12s, the same as the block time. For faster chains you can skip a block or two +and set it to two times the block time i.e. on Optimism you can set it to 4s. Ideally, you don't want to go lower than 1s since the RTT times of the RPC requests will be comparable to +the timeout. The estimator is already adding a buffer to account for a potential increase in prices within one or two blocks. On the other hand, slower frequency will fail to refresh +the prices and end up in stale values. + ## EVM.HeadTracker ```toml [EVM.HeadTracker] diff --git a/testdata/scripts/node/validate/disk-based-logging-disabled.txtar b/testdata/scripts/node/validate/disk-based-logging-disabled.txtar index fbcb4725d6..a6612cc8f1 100644 --- a/testdata/scripts/node/validate/disk-based-logging-disabled.txtar +++ b/testdata/scripts/node/validate/disk-based-logging-disabled.txtar @@ -375,6 +375,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 50 +[EVM.GasEstimator.FeeHistory] +CacheTimeout = '10s' + [EVM.HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 diff --git a/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar b/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar index 5fa31dd1aa..79dcfa776d 100644 --- a/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar +++ b/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar @@ -375,6 +375,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 50 +[EVM.GasEstimator.FeeHistory] +CacheTimeout = '10s' + [EVM.HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 diff --git a/testdata/scripts/node/validate/disk-based-logging.txtar b/testdata/scripts/node/validate/disk-based-logging.txtar index 832185c53f..efa27eec11 100644 --- a/testdata/scripts/node/validate/disk-based-logging.txtar +++ b/testdata/scripts/node/validate/disk-based-logging.txtar @@ -375,6 +375,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 50 +[EVM.GasEstimator.FeeHistory] +CacheTimeout = '10s' + [EVM.HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 diff --git a/testdata/scripts/node/validate/invalid.txtar b/testdata/scripts/node/validate/invalid.txtar index 972c6c10fc..6932eb5038 100644 --- a/testdata/scripts/node/validate/invalid.txtar +++ b/testdata/scripts/node/validate/invalid.txtar @@ -365,6 +365,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 50 +[EVM.GasEstimator.FeeHistory] +CacheTimeout = '10s' + [EVM.HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 diff --git a/testdata/scripts/node/validate/valid.txtar b/testdata/scripts/node/validate/valid.txtar index c7b5261d26..7074c82bf5 100644 --- a/testdata/scripts/node/validate/valid.txtar +++ b/testdata/scripts/node/validate/valid.txtar @@ -372,6 +372,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 50 +[EVM.GasEstimator.FeeHistory] +CacheTimeout = '10s' + [EVM.HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 From 97f6f556bbe4090cc8a40ad68e9acc8dc10e13d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Friedemann=20F=C3=BCrst?= <59653747+friedemannf@users.noreply.github.com> Date: Thu, 5 Sep 2024 18:57:08 +0200 Subject: [PATCH 112/115] Add node level OOC error (#14315) * Add node level OOC error * Add changeset --- .changeset/green-eagles-deliver.md | 5 +++++ core/chains/evm/client/errors.go | 2 +- core/chains/evm/client/errors_test.go | 2 ++ 3 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 .changeset/green-eagles-deliver.md diff --git a/.changeset/green-eagles-deliver.md b/.changeset/green-eagles-deliver.md new file mode 100644 index 0000000000..179b93b108 --- /dev/null +++ b/.changeset/green-eagles-deliver.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +Handle zkEVM node level OOC error as TerminallyStuck #internal diff --git a/core/chains/evm/client/errors.go b/core/chains/evm/client/errors.go index 5980b0dd96..ff4bd15a7b 100644 --- a/core/chains/evm/client/errors.go +++ b/core/chains/evm/client/errors.go @@ -253,7 +253,7 @@ var zkSync = ClientErrors{ } var zkEvm = ClientErrors{ - TerminallyStuck: regexp.MustCompile(`(?:: |^)not enough .* counters to continue the execution$`), + TerminallyStuck: regexp.MustCompile(`(?:: |^)(?:not enough .* counters to continue the execution|out of counters at node level (?:.*))$`), } var aStar = ClientErrors{ diff --git a/core/chains/evm/client/errors_test.go b/core/chains/evm/client/errors_test.go index a7e9ebac10..49543b16e9 100644 --- a/core/chains/evm/client/errors_test.go +++ b/core/chains/evm/client/errors_test.go @@ -317,6 +317,8 @@ func Test_Eth_Errors(t *testing.T) { {"failed to add tx to the pool: not enough step counters to continue the execution", true, "Xlayer"}, {"failed to add tx to the pool: not enough keccak counters to continue the execution", true, "zkEVM"}, {"failed to add tx to the pool: not enough keccak counters to continue the execution", true, "Xlayer"}, + {"RPC error response: failed to add tx to the pool: out of counters at node level (Steps)", true, "zkEVM"}, + {"RPC error response: failed to add tx to the pool: out of counters at node level (GasUsed, KeccakHashes, PoseidonHashes, PoseidonPaddings, MemAligns, Arithmetics, Binaries, Steps, Sha256Hashes)", true, "Xlayer"}, } for _, test := range tests { From 2a08e17813f00bb8b23c6b56360d1b2361080279 Mon Sep 17 00:00:00 2001 From: Ryan Hall <RyanRHall@users.noreply.github.com> Date: Fri, 20 Sep 2024 11:11:12 -0400 Subject: [PATCH 113/115] update CONFIG.md (#1453) ## Motivation We want a functional CI ## Solution Fix CI issues from ccip-develop --- core/chains/evm/gas/fee_history_estimator.go | 4 +-- core/chains/evm/gas/helpers_test.go | 2 +- core/chains/evm/gas/models.go | 2 +- core/chains/evm/gas/rollups/op_l1_oracle.go | 1 - core/services/ocr/contract_tracker.go | 2 +- docs/CONFIG.md | 32 ++++++++++++++++++++ 6 files changed, 37 insertions(+), 6 deletions(-) diff --git a/core/chains/evm/gas/fee_history_estimator.go b/core/chains/evm/gas/fee_history_estimator.go index ba3192be10..53af03ac7a 100644 --- a/core/chains/evm/gas/fee_history_estimator.go +++ b/core/chains/evm/gas/fee_history_estimator.go @@ -252,7 +252,7 @@ func (f *FeeHistoryEstimator) RefreshDynamicPrice() error { maxPriorityFeePerGas := assets.NewWeiI(0) priorityFeeThresholdWei := assets.NewWeiI(0) if f.config.BlockHistorySize > 0 { - var nonZeroRewardsLen int64 = 0 + var nonZeroRewardsLen int64 priorityFee := big.NewInt(0) priorityFeeThreshold := big.NewInt(0) for _, reward := range feeHistory.Reward { @@ -263,7 +263,7 @@ func (f *FeeHistoryEstimator) RefreshDynamicPrice() error { // We'll calculate the average of non-zero priority fees if reward[0].Cmp(big.NewInt(0)) > 0 { priorityFee = priorityFee.Add(priorityFee, reward[0]) - nonZeroRewardsLen += 1 + nonZeroRewardsLen++ } // We take the max value for the bumping threshold if reward[1].Cmp(big.NewInt(0)) > 0 { diff --git a/core/chains/evm/gas/helpers_test.go b/core/chains/evm/gas/helpers_test.go index ae93d9e8c7..0c9a74a18d 100644 --- a/core/chains/evm/gas/helpers_test.go +++ b/core/chains/evm/gas/helpers_test.go @@ -157,7 +157,7 @@ type MockGasEstimatorConfig struct { FeeCapDefaultF *assets.Wei LimitMaxF uint64 ModeF string - EstimateLimitF bool + EstimateLimitF bool } func NewMockGasConfig() *MockGasEstimatorConfig { diff --git a/core/chains/evm/gas/models.go b/core/chains/evm/gas/models.go index d844f8774a..92ae439492 100644 --- a/core/chains/evm/gas/models.go +++ b/core/chains/evm/gas/models.go @@ -407,7 +407,7 @@ func (e *evmFeeEstimator) estimateFeeLimit(ctx context.Context, feeLimit uint64, e.lggr.Debugw("estimated gas limit with buffer exceeds the provided gas limit with multiplier. falling back to the provided gas limit with multiplier", "estimatedGasLimit", estimatedFeeLimit, "providedGasLimitWithMultiplier", providedGasLimit) estimatedFeeLimit = providedGasLimit } - + return } diff --git a/core/chains/evm/gas/rollups/op_l1_oracle.go b/core/chains/evm/gas/rollups/op_l1_oracle.go index 11babc5ca5..28071a268f 100644 --- a/core/chains/evm/gas/rollups/op_l1_oracle.go +++ b/core/chains/evm/gas/rollups/op_l1_oracle.go @@ -50,7 +50,6 @@ type optimismL1Oracle struct { blobBaseFeeCalldata []byte blobBaseFeeScalarCalldata []byte decimalsCalldata []byte - tokenRatioCalldata []byte isEcotoneCalldata []byte isEcotoneMethodAbi abi.ABI isFjordCalldata []byte diff --git a/core/services/ocr/contract_tracker.go b/core/services/ocr/contract_tracker.go index d7199874a9..6e742e48fb 100644 --- a/core/services/ocr/contract_tracker.go +++ b/core/services/ocr/contract_tracker.go @@ -399,7 +399,7 @@ func (t *OCRContractTracker) LatestBlockHeight(ctx context.Context) (blockheight // care about the block height; we have no way of getting the L1 block // height anyway return 0, nil - case "", chaintype.ChainArbitrum, chaintype.ChainAstar, chaintype.ChainCelo, chaintype.ChainGnosis, chaintype.ChainHedera, chaintype.ChainKroma, chaintype.ChainOptimismBedrock, chaintype.ChainScroll, chaintype.ChainWeMix, chaintype.ChainXLayer, chaintype.ChainZkEvm, chaintype.ChainZkSync: + case "", chaintype.ChainArbitrum, chaintype.ChainAstar, chaintype.ChainCelo, chaintype.ChainGnosis, chaintype.ChainHedera, chaintype.ChainKroma, chaintype.ChainOptimismBedrock, chaintype.ChainScroll, chaintype.ChainWeMix, chaintype.ChainXLayer, chaintype.ChainZkEvm, chaintype.ChainZkSync, chaintype.ChainMantle: // continue } latestBlockHeight := t.getLatestBlockHeight() diff --git a/docs/CONFIG.md b/docs/CONFIG.md index c315b574e7..95743363ab 100644 --- a/docs/CONFIG.md +++ b/docs/CONFIG.md @@ -2798,6 +2798,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -2813,6 +2814,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 @@ -4264,6 +4268,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -4279,6 +4284,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 @@ -4358,6 +4366,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateLimit = false BumpMin = '100 wei' BumpPercent = 20 BumpThreshold = 60 @@ -4374,6 +4383,9 @@ CheckInclusionPercentile = 90 EIP1559FeeCapBufferBlocks = 0 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 300 MaxBufferSize = 3 @@ -5431,6 +5443,7 @@ LimitDefault = 100000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -5447,6 +5460,9 @@ CheckInclusionPercentile = 90 EIP1559FeeCapBufferBlocks = 0 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 600 MaxBufferSize = 3 @@ -6017,6 +6033,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateLimit = false BumpMin = '100 wei' BumpPercent = 20 BumpThreshold = 60 @@ -6033,6 +6050,9 @@ CheckInclusionPercentile = 90 EIP1559FeeCapBufferBlocks = 0 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 300 MaxBufferSize = 3 @@ -6992,6 +7012,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateLimit = false BumpMin = '5 gwei' BumpPercent = 20 BumpThreshold = 3 @@ -7007,6 +7028,9 @@ CheckInclusionBlocks = 12 CheckInclusionPercentile = 90 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 100 MaxBufferSize = 3 @@ -7281,6 +7305,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateLimit = false BumpMin = '100 wei' BumpPercent = 20 BumpThreshold = 60 @@ -7297,6 +7322,9 @@ CheckInclusionPercentile = 90 EIP1559FeeCapBufferBlocks = 0 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 300 MaxBufferSize = 3 @@ -8262,6 +8290,7 @@ LimitDefault = 8000000 LimitMax = 8000000 LimitMultiplier = '1' LimitTransfer = 21000 +EstimateLimit = false BumpMin = '100 wei' BumpPercent = 20 BumpThreshold = 60 @@ -8278,6 +8307,9 @@ CheckInclusionPercentile = 90 EIP1559FeeCapBufferBlocks = 0 TransactionPercentile = 60 +[GasEstimator.FeeHistory] +CacheTimeout = '10s' + [HeadTracker] HistoryDepth = 300 MaxBufferSize = 3 From c8753d1d3997b35a266d480b1f34c182447d52ea Mon Sep 17 00:00:00 2001 From: Ryan Hall <RyanRHall@users.noreply.github.com> Date: Mon, 23 Sep 2024 12:11:15 -0400 Subject: [PATCH 114/115] merge FeePaid event into CCIPMessageSent (#1456) ## Motivation Not sure actually why this was needed. Request was [made here](https://smartcontract-it.atlassian.net/browse/CCIP-3446?atlOrigin=eyJpIjoiMTQ4ODMwNzU2N2I3NDI0NGE0ZDhiOTIyZTYwOTNjN2IiLCJwIjoiaiJ9). This is the 2nd version, that alters the MessageSent struct. First version [here](https://github.com/smartcontractkit/ccip/pull/1452). ## Solution Merge fields from FeePaid event into CCIPMessageSent event --- contracts/gas-snapshots/ccip.gas-snapshot | 94 +++++------ .../src/v0.8/ccip/libraries/Internal.sol | 1 + contracts/src/v0.8/ccip/onRamp/OnRamp.sol | 16 +- .../ccip/test/e2e/MultiRampsEnd2End.t.sol | 5 +- .../ccip/test/feeQuoter/FeeQuoterSetup.t.sol | 2 + .../src/v0.8/ccip/test/onRamp/OnRamp.t.sol | 8 +- .../v0.8/ccip/test/onRamp/OnRampSetup.t.sol | 23 ++- .../ccip_reader_tester/ccip_reader_tester.go | 7 +- .../ccip/generated/onramp/onramp.go | 147 +----------------- ...rapper-dependency-versions-do-not-edit.txt | 4 +- 10 files changed, 97 insertions(+), 210 deletions(-) diff --git a/contracts/gas-snapshots/ccip.gas-snapshot b/contracts/gas-snapshots/ccip.gas-snapshot index 9861ed236c..740dfc0c8f 100644 --- a/contracts/gas-snapshots/ccip.gas-snapshot +++ b/contracts/gas-snapshots/ccip.gas-snapshot @@ -572,8 +572,8 @@ MultiOCR3Base_transmit:test_UnAuthorizedTransmitter_Revert() (gas: 24234) MultiOCR3Base_transmit:test_UnauthorizedSigner_Revert() (gas: 61275) MultiOCR3Base_transmit:test_UnconfiguredPlugin_Revert() (gas: 39933) MultiOCR3Base_transmit:test_ZeroSignatures_Revert() (gas: 33049) -MultiOnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 233778) -MultiRampsE2E:test_E2E_3MessagesMMultiOffRampSuccess_gas() (gas: 1504663) +MultiOnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 233701) +MultiRampsE2E:test_E2E_3MessagesMMultiOffRampSuccess_gas() (gas: 1500580) NonceManager_NonceIncrementation:test_getIncrementedOutboundNonce_Success() (gas: 37934) NonceManager_NonceIncrementation:test_incrementInboundNonce_Skip() (gas: 23706) NonceManager_NonceIncrementation:test_incrementInboundNonce_Success() (gas: 38778) @@ -585,15 +585,15 @@ NonceManager_OffRampUpgrade:test_UpgradedOffRampNonceSkipsIfMsgInFlight_Success( NonceManager_OffRampUpgrade:test_UpgradedSenderNoncesReadsPreviousRampTransitive_Success() (gas: 249120) NonceManager_OffRampUpgrade:test_UpgradedSenderNoncesReadsPreviousRamp_Success() (gas: 237027) NonceManager_OffRampUpgrade:test_Upgraded_Success() (gas: 153748) -NonceManager_OnRampUpgrade:test_UpgradeNonceNewSenderStartsAtZero_Success() (gas: 168959) -NonceManager_OnRampUpgrade:test_UpgradeNonceStartsAtV1Nonce_Success() (gas: 221148) -NonceManager_OnRampUpgrade:test_UpgradeSenderNoncesReadsPreviousRamp_Success() (gas: 126861) -NonceManager_OnRampUpgrade:test_Upgrade_Success() (gas: 107723) -NonceManager_applyPreviousRampsUpdates:test_MultipleRampsUpdates() (gas: 123207) +NonceManager_OnRampUpgrade:test_UpgradeNonceNewSenderStartsAtZero_Success() (gas: 168256) +NonceManager_OnRampUpgrade:test_UpgradeNonceStartsAtV1Nonce_Success() (gas: 219631) +NonceManager_OnRampUpgrade:test_UpgradeSenderNoncesReadsPreviousRamp_Success() (gas: 126745) +NonceManager_OnRampUpgrade:test_Upgrade_Success() (gas: 106975) +NonceManager_applyPreviousRampsUpdates:test_MultipleRampsUpdates() (gas: 123102) NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySetOffRamp_Revert() (gas: 43079) NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySetOnRampAndOffRamp_Revert() (gas: 64408) NonceManager_applyPreviousRampsUpdates:test_PreviousRampAlreadySetOnRamp_Revert() (gas: 42943) -NonceManager_applyPreviousRampsUpdates:test_SingleRampUpdate() (gas: 66696) +NonceManager_applyPreviousRampsUpdates:test_SingleRampUpdate() (gas: 66666) NonceManager_applyPreviousRampsUpdates:test_ZeroInput() (gas: 12070) NonceManager_typeAndVersion:test_typeAndVersion() (gas: 9705) OCR2BaseNoChecks_setOCR2Config:test_FMustBePositive_Revert() (gas: 12210) @@ -758,51 +758,51 @@ OffRamp_trialExecute:test_trialExecute_Success() (gas: 277894) OnRampTokenPoolReentrancy:test_OnRampTokenPoolReentrancy_Success() (gas: 390842) OnRamp_applyAllowListUpdates:test_applyAllowListUpdates_InvalidAllowListRequestDisabledAllowListWithAdds() (gas: 18030) OnRamp_applyAllowListUpdates:test_applyAllowListUpdates_Revert() (gas: 67426) -OnRamp_applyAllowListUpdates:test_applyAllowListUpdates_Success() (gas: 325124) -OnRamp_applyDestChainConfigUpdates:test_ApplyDestChainConfigUpdates_Success() (gas: 65227) -OnRamp_applyDestChainConfigUpdates:test_ApplyDestChainConfigUpdates_WithInvalidChainSelector_Revert() (gas: 13446) -OnRamp_constructor:test_Constructor_InvalidConfigChainSelectorEqZero_Revert() (gas: 95048) -OnRamp_constructor:test_Constructor_InvalidConfigNonceManagerEqAddressZero_Revert() (gas: 92990) -OnRamp_constructor:test_Constructor_InvalidConfigRMNProxyEqAddressZero_Revert() (gas: 98023) -OnRamp_constructor:test_Constructor_InvalidConfigTokenAdminRegistryEqAddressZero_Revert() (gas: 93046) -OnRamp_constructor:test_Constructor_Success() (gas: 2750875) -OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() (gas: 115146) -OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2_Success() (gas: 145969) -OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessCustomExtraArgs() (gas: 145545) -OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessEmptyExtraArgs() (gas: 143772) -OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessLegacyExtraArgs() (gas: 145763) -OnRamp_forwardFromRouter:test_ForwardFromRouter_Success() (gas: 145139) -OnRamp_forwardFromRouter:test_ForwardFromRouter_Success_ConfigurableSourceRouter() (gas: 145974) -OnRamp_forwardFromRouter:test_InvalidExtraArgsTag_Revert() (gas: 38593) -OnRamp_forwardFromRouter:test_MessageInterceptionError_Revert() (gas: 143056) -OnRamp_forwardFromRouter:test_MesssageFeeTooHigh_Revert() (gas: 36706) -OnRamp_forwardFromRouter:test_MultiCannotSendZeroTokens_Revert() (gas: 36509) +OnRamp_applyAllowListUpdates:test_applyAllowListUpdates_Success() (gas: 325083) +OnRamp_applyDestChainConfigUpdates:test_ApplyDestChainConfigUpdates_Success() (gas: 65095) +OnRamp_applyDestChainConfigUpdates:test_ApplyDestChainConfigUpdates_WithInvalidChainSelector_Revert() (gas: 13422) +OnRamp_constructor:test_Constructor_InvalidConfigChainSelectorEqZero_Revert() (gas: 94996) +OnRamp_constructor:test_Constructor_InvalidConfigNonceManagerEqAddressZero_Revert() (gas: 92938) +OnRamp_constructor:test_Constructor_InvalidConfigRMNProxyEqAddressZero_Revert() (gas: 97971) +OnRamp_constructor:test_Constructor_InvalidConfigTokenAdminRegistryEqAddressZero_Revert() (gas: 92972) +OnRamp_constructor:test_Constructor_Success() (gas: 2734391) +OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2AllowOutOfOrderTrue_Success() (gas: 114527) +OnRamp_forwardFromRouter:test_ForwardFromRouterExtraArgsV2_Success() (gas: 145328) +OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessCustomExtraArgs() (gas: 144925) +OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessEmptyExtraArgs() (gas: 143086) +OnRamp_forwardFromRouter:test_ForwardFromRouterSuccessLegacyExtraArgs() (gas: 145122) +OnRamp_forwardFromRouter:test_ForwardFromRouter_Success() (gas: 144520) +OnRamp_forwardFromRouter:test_ForwardFromRouter_Success_ConfigurableSourceRouter() (gas: 144604) +OnRamp_forwardFromRouter:test_InvalidExtraArgsTag_Revert() (gas: 38554) +OnRamp_forwardFromRouter:test_MessageInterceptionError_Revert() (gas: 143051) +OnRamp_forwardFromRouter:test_MesssageFeeTooHigh_Revert() (gas: 36596) +OnRamp_forwardFromRouter:test_MultiCannotSendZeroTokens_Revert() (gas: 36527) OnRamp_forwardFromRouter:test_OriginalSender_Revert() (gas: 18291) -OnRamp_forwardFromRouter:test_Paused_Revert() (gas: 38454) -OnRamp_forwardFromRouter:test_Permissions_Revert() (gas: 23663) -OnRamp_forwardFromRouter:test_ShouldIncrementNonceOnlyOnOrdered_Success() (gas: 186202) -OnRamp_forwardFromRouter:test_ShouldIncrementSeqNumAndNonce_Success() (gas: 212587) -OnRamp_forwardFromRouter:test_ShouldStoreLinkFees() (gas: 125127) -OnRamp_forwardFromRouter:test_ShouldStoreNonLinkFees() (gas: 141767) -OnRamp_forwardFromRouter:test_SourceTokenDataTooLarge_Revert() (gas: 3618195) +OnRamp_forwardFromRouter:test_Paused_Revert() (gas: 38431) +OnRamp_forwardFromRouter:test_Permissions_Revert() (gas: 23640) +OnRamp_forwardFromRouter:test_ShouldIncrementNonceOnlyOnOrdered_Success() (gas: 183954) +OnRamp_forwardFromRouter:test_ShouldIncrementSeqNumAndNonce_Success() (gas: 210338) +OnRamp_forwardFromRouter:test_ShouldStoreLinkFees() (gas: 146154) +OnRamp_forwardFromRouter:test_ShouldStoreNonLinkFees() (gas: 160259) +OnRamp_forwardFromRouter:test_SourceTokenDataTooLarge_Revert() (gas: 3613942) OnRamp_forwardFromRouter:test_UnAllowedOriginalSender_Revert() (gas: 24010) -OnRamp_forwardFromRouter:test_UnsupportedToken_Revert() (gas: 75826) -OnRamp_forwardFromRouter:test_forwardFromRouter_UnsupportedToken_Revert() (gas: 38559) -OnRamp_forwardFromRouter:test_forwardFromRouter_WithInterception_Success() (gas: 280050) -OnRamp_getFee:test_EmptyMessage_Success() (gas: 98757) -OnRamp_getFee:test_EnforceOutOfOrder_Revert() (gas: 64779) -OnRamp_getFee:test_GetFeeOfZeroForTokenMessage_Success() (gas: 86359) -OnRamp_getFee:test_NotAFeeTokenButPricedToken_Revert() (gas: 35185) -OnRamp_getFee:test_SingleTokenMessage_Success() (gas: 113916) -OnRamp_getFee:test_Unhealthy_Revert() (gas: 17171) -OnRamp_getSupportedTokens:test_GetSupportedTokens_Revert() (gas: 10510) -OnRamp_getTokenPool:test_GetTokenPool_Success() (gas: 35372) -OnRamp_setDynamicConfig:test_setDynamicConfig_InvalidConfigFeeAggregatorEqAddressZero_Revert() (gas: 11581) +OnRamp_forwardFromRouter:test_UnsupportedToken_Revert() (gas: 75866) +OnRamp_forwardFromRouter:test_forwardFromRouter_UnsupportedToken_Revert() (gas: 38599) +OnRamp_forwardFromRouter:test_forwardFromRouter_WithInterception_Success() (gas: 279390) +OnRamp_getFee:test_EmptyMessage_Success() (gas: 98513) +OnRamp_getFee:test_EnforceOutOfOrder_Revert() (gas: 64645) +OnRamp_getFee:test_GetFeeOfZeroForTokenMessage_Success() (gas: 86177) +OnRamp_getFee:test_NotAFeeTokenButPricedToken_Revert() (gas: 35097) +OnRamp_getFee:test_SingleTokenMessage_Success() (gas: 113639) +OnRamp_getFee:test_Unhealthy_Revert() (gas: 17061) +OnRamp_getSupportedTokens:test_GetSupportedTokens_Revert() (gas: 10474) +OnRamp_getTokenPool:test_GetTokenPool_Success() (gas: 35348) +OnRamp_setDynamicConfig:test_setDynamicConfig_InvalidConfigFeeAggregatorEqAddressZero_Revert() (gas: 11536) OnRamp_setDynamicConfig:test_setDynamicConfig_InvalidConfigFeeQuoterEqAddressZero_Revert() (gas: 13195) OnRamp_setDynamicConfig:test_setDynamicConfig_InvalidConfigInvalidConfig_Revert() (gas: 11522) OnRamp_setDynamicConfig:test_setDynamicConfig_InvalidConfigOnlyOwner_Revert() (gas: 16850) OnRamp_setDynamicConfig:test_setDynamicConfig_InvalidConfigReentrancyGuardEnteredEqTrue_Revert() (gas: 13265) -OnRamp_setDynamicConfig:test_setDynamicConfig_Success() (gas: 56460) +OnRamp_setDynamicConfig:test_setDynamicConfig_Success() (gas: 56369) OnRamp_withdrawFeeTokens:test_WithdrawFeeTokens_Success() (gas: 97302) PingPong_ccipReceive:test_CcipReceive_Success() (gas: 151349) PingPong_plumbing:test_OutOfOrderExecution_Success() (gas: 20310) diff --git a/contracts/src/v0.8/ccip/libraries/Internal.sol b/contracts/src/v0.8/ccip/libraries/Internal.sol index d09717f63a..13ffc56b91 100644 --- a/contracts/src/v0.8/ccip/libraries/Internal.sol +++ b/contracts/src/v0.8/ccip/libraries/Internal.sol @@ -342,6 +342,7 @@ library Internal { bytes extraArgs; // destination-chain specific extra args, such as the gasLimit for EVM chains address feeToken; // fee token uint256 feeTokenAmount; // fee token amount + uint256 feeValueJuels; // fee amount in Juels EVM2AnyTokenTransfer[] tokenAmounts; // array of tokens and amounts to transfer } diff --git a/contracts/src/v0.8/ccip/onRamp/OnRamp.sol b/contracts/src/v0.8/ccip/onRamp/OnRamp.sol index 76e966311d..959d831a39 100644 --- a/contracts/src/v0.8/ccip/onRamp/OnRamp.sol +++ b/contracts/src/v0.8/ccip/onRamp/OnRamp.sol @@ -46,7 +46,6 @@ contract OnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCreator { event DestChainConfigSet( uint64 indexed destChainSelector, uint64 sequenceNumber, IRouter router, bool allowListEnabled ); - event FeePaid(address indexed feeToken, uint256 feeValueJuels); event FeeTokenWithdrawn(address indexed feeAggregator, address indexed feeToken, uint256 amount); /// RMN depends on this event, if changing, please notify the RMN maintainers. event CCIPMessageSent(uint64 indexed destChainSelector, Internal.EVM2AnyRampMessage message); @@ -211,6 +210,7 @@ contract OnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCreator { receiver: message.receiver, feeToken: message.feeToken, feeTokenAmount: feeTokenAmount, + feeValueJuels: 0, // calculated later // Should be populated via lock / burn pool calls tokenAmounts: new Internal.EVM2AnyTokenTransfer[](message.tokenAmounts.length) }); @@ -224,17 +224,15 @@ contract OnRamp is IEVM2AnyOnRampClient, ITypeAndVersion, OwnerIsCreator { // Convert message fee to juels and retrieve converted args // Validate pool return data after it is populated (view function - no state changes) - ( - uint256 msgFeeJuels, - bool isOutOfOrderExecution, - bytes memory convertedExtraArgs, - bytes[] memory destExecDataPerToken - ) = IFeeQuoter(s_dynamicConfig.feeQuoter).processMessageArgs( + bool isOutOfOrderExecution; + bytes memory convertedExtraArgs; + bytes[] memory destExecDataPerToken; + (newMessage.feeValueJuels, isOutOfOrderExecution, convertedExtraArgs, destExecDataPerToken) = IFeeQuoter( + s_dynamicConfig.feeQuoter + ).processMessageArgs( destChainSelector, message.feeToken, feeTokenAmount, message.extraArgs, newMessage.tokenAmounts, tokenAmounts ); - emit FeePaid(message.feeToken, msgFeeJuels); - newMessage.header.nonce = isOutOfOrderExecution ? 0 : INonceManager(i_nonceManager).getIncrementedOutboundNonce(destChainSelector, originalSender); diff --git a/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.t.sol b/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.t.sol index 5f06a37e13..59f727c251 100644 --- a/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.t.sol +++ b/contracts/src/v0.8/ccip/test/e2e/MultiRampsEnd2End.t.sol @@ -251,6 +251,8 @@ contract MultiRampsE2E is OnRampSetup, OffRampSetup { IERC20(s_sourceTokens[0]).approve(address(router), i_tokenAmount0 + router.getFee(DEST_CHAIN_SELECTOR, message)); IERC20(s_sourceTokens[1]).approve(address(router), i_tokenAmount1); + uint256 feeAmount = router.getFee(DEST_CHAIN_SELECTOR, message); + message.receiver = abi.encode(address(s_receiver)); Internal.EVM2AnyRampMessage memory msgEvent = _messageToEvent( message, @@ -258,7 +260,8 @@ contract MultiRampsE2E is OnRampSetup, OffRampSetup { DEST_CHAIN_SELECTOR, expectedSeqNum, nonce, - router.getFee(DEST_CHAIN_SELECTOR, message), + feeAmount, + feeAmount, OWNER, metadataHash, tokenAdminRegistry diff --git a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoterSetup.t.sol b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoterSetup.t.sol index 340fe3662d..d630c55c0d 100644 --- a/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoterSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/feeQuoter/FeeQuoterSetup.t.sol @@ -367,6 +367,7 @@ contract FeeQuoterFeeSetup is FeeQuoterSetup { uint64 seqNum, uint64 nonce, uint256 feeTokenAmount, + uint256 feeValueJuels, address originalSender, bytes32 metadataHash, TokenAdminRegistry tokenAdminRegistry @@ -388,6 +389,7 @@ contract FeeQuoterFeeSetup is FeeQuoterSetup { extraArgs: Client._argsToBytes(extraArgs), feeToken: message.feeToken, feeTokenAmount: feeTokenAmount, + feeValueJuels: feeValueJuels, tokenAmounts: new Internal.EVM2AnyTokenTransfer[](message.tokenAmounts.length) }); diff --git a/contracts/src/v0.8/ccip/test/onRamp/OnRamp.t.sol b/contracts/src/v0.8/ccip/test/onRamp/OnRamp.t.sol index 72be798738..2a7fac892c 100644 --- a/contracts/src/v0.8/ccip/test/onRamp/OnRamp.t.sol +++ b/contracts/src/v0.8/ccip/test/onRamp/OnRamp.t.sol @@ -287,7 +287,8 @@ contract OnRamp_forwardFromRouter is OnRampSetup { IERC20(s_sourceFeeToken).transferFrom(OWNER, address(s_onRamp), feeAmount); vm.expectEmit(); - emit OnRamp.FeePaid(s_sourceFeeToken, feeAmount); + emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, _messageToEvent(message, 1, 1, feeAmount, OWNER)); + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); assertEq(IERC20(s_sourceFeeToken).balanceOf(address(s_onRamp)), feeAmount); @@ -307,7 +308,8 @@ contract OnRamp_forwardFromRouter is OnRampSetup { uint256 expectedJuels = (feeAmount * conversionRate) / 1e18; vm.expectEmit(); - emit OnRamp.FeePaid(s_sourceTokens[1], expectedJuels); + emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, _messageToEvent(message, 1, 1, feeAmount, expectedJuels, OWNER)); + s_onRamp.forwardFromRouter(DEST_CHAIN_SELECTOR, message, feeAmount, OWNER); assertEq(IERC20(s_sourceTokens[1]).balanceOf(address(s_onRamp)), feeAmount); @@ -352,8 +354,6 @@ contract OnRamp_forwardFromRouter is OnRampSetup { Internal.EVM2AnyRampMessage memory expectedEvent = _messageToEvent(message, 1, 1, feeTokenAmount, originalSender); vm.expectEmit(); - emit OnRamp.FeePaid(s_sourceFeeToken, feeTokenAmount); - vm.expectEmit(false, false, false, true); emit OnRamp.CCIPMessageSent(DEST_CHAIN_SELECTOR, expectedEvent); // Assert the message Id is correct diff --git a/contracts/src/v0.8/ccip/test/onRamp/OnRampSetup.t.sol b/contracts/src/v0.8/ccip/test/onRamp/OnRampSetup.t.sol index ddcbbd5620..6ecd3a5807 100644 --- a/contracts/src/v0.8/ccip/test/onRamp/OnRampSetup.t.sol +++ b/contracts/src/v0.8/ccip/test/onRamp/OnRampSetup.t.sol @@ -64,13 +64,33 @@ contract OnRampSetup is FeeQuoterFeeSetup { }); } + /// @dev a helper function to compose EVM2AnyRampMessage messages + /// @dev it is assummed that LINK is the payment token because feeTokenAmount == feeValueJuels function _messageToEvent( Client.EVM2AnyMessage memory message, uint64 seqNum, uint64 nonce, uint256 feeTokenAmount, address originalSender - ) public view returns (Internal.EVM2AnyRampMessage memory) { + ) internal view returns (Internal.EVM2AnyRampMessage memory) { + return _messageToEvent( + message, + seqNum, + nonce, + feeTokenAmount, // fee paid + feeTokenAmount, // converstion to jules is the same + originalSender + ); + } + + function _messageToEvent( + Client.EVM2AnyMessage memory message, + uint64 seqNum, + uint64 nonce, + uint256 feeTokenAmount, + uint256 feeValueJuels, + address originalSender + ) internal view returns (Internal.EVM2AnyRampMessage memory) { return _messageToEvent( message, SOURCE_CHAIN_SELECTOR, @@ -78,6 +98,7 @@ contract OnRampSetup is FeeQuoterFeeSetup { seqNum, nonce, feeTokenAmount, + feeValueJuels, originalSender, s_metadataHash, s_tokenAdminRegistry diff --git a/core/gethwrappers/ccip/generated/ccip_reader_tester/ccip_reader_tester.go b/core/gethwrappers/ccip/generated/ccip_reader_tester/ccip_reader_tester.go index efdc46ebf2..bb6639d7e8 100644 --- a/core/gethwrappers/ccip/generated/ccip_reader_tester/ccip_reader_tester.go +++ b/core/gethwrappers/ccip/generated/ccip_reader_tester/ccip_reader_tester.go @@ -43,6 +43,7 @@ type InternalEVM2AnyRampMessage struct { ExtraArgs []byte FeeToken common.Address FeeTokenAmount *big.Int + FeeValueJuels *big.Int TokenAmounts []InternalEVM2AnyTokenTransfer } @@ -100,8 +101,8 @@ type OffRampSourceChainConfig struct { } var CCIPReaderTesterMetaData = &bind.MetaData{ - ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"sourcePoolAddress\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.EVM2AnyTokenTransfer[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"CCIPSendRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"structIRMNV2.Signature[]\",\"name\":\"rmnSignatures\",\"type\":\"tuple[]\"},{\"internalType\":\"uint256\",\"name\":\"rmnRawVs\",\"type\":\"uint256\"}],\"indexed\":false,\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"report\",\"type\":\"tuple\"}],\"name\":\"CommitReportAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"name\":\"ExecutionStateChanged\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"sourcePoolAddress\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.EVM2AnyTokenTransfer[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"emitCCIPSendRequested\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"structIRMNV2.Signature[]\",\"name\":\"rmnSignatures\",\"type\":\"tuple[]\"},{\"internalType\":\"uint256\",\"name\":\"rmnRawVs\",\"type\":\"uint256\"}],\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"report\",\"type\":\"tuple\"}],\"name\":\"emitCommitReportAccepted\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"name\":\"emitExecutionStateChanged\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getExpectedNextSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"getSourceChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"setDestChainSeqNr\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"sourceChainConfig\",\"type\":\"tuple\"}],\"name\":\"setSourceChainConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x608060405234801561001057600080fd5b506113d3806100206000396000f3fe608060405234801561001057600080fd5b506004361061006d5760003560e01c8063198b821c146100725780634cf66e36146100875780639041be3d1461009a578063c1a5a355146100ca578063e4d0223414610106578063e83eabba14610119578063e9d68a8e1461012c575b600080fd5b6100856100803660046107bd565b61014c565b005b610085610095366004610954565b610186565b6100ad6100a83660046109d2565b6101db565b6040516001600160401b0390911681526020015b60405180910390f35b6100856100d83660046109f4565b6001600160401b03918216600090815260016020526040902080546001600160401b03191691909216179055565b610085610114366004610bb5565b61020a565b610085610127366004610ce3565b61024f565b61013f61013a3660046109d2565b6102db565b6040516100c19190610de4565b7f062172a2ae1a84d7c8d18965d6267b71d579aeca033bbd2e0548947798c3d4628160405161017b9190610f80565b60405180910390a150565b82846001600160401b0316866001600160401b03167f8c324ce1367b83031769f6a813e3bb4c117aba2185789d66b98b791405be6df285856040516101cc929190611061565b60405180910390a45050505050565b6001600160401b0380821660009081526001602081905260408220549192610204921690611098565b92915050565b816001600160401b03167fe07a589f12eccf1bc0f7421666687a6986a0c8dbbdc877d1af562a97ba60ecfd82604051610243919061117a565b60405180910390a25050565b6001600160401b0380831660009081526020818152604091829020845181549286015193860151909416600160a81b02600160a81b600160e81b0319931515600160a01b026001600160a81b03199093166001600160a01b03909516949094179190911791909116919091178155606082015182919060018201906102d49082611307565b5050505050565b60408051608080820183526000808352602080840182905283850182905260608085018190526001600160401b038781168452838352928690208651948501875280546001600160a01b0381168652600160a01b810460ff16151593860193909352600160a81b9092049092169483019490945260018401805493949293918401916103669061127c565b80601f01602080910402602001604051908101604052809291908181526020018280546103929061127c565b80156103df5780601f106103b4576101008083540402835291602001916103df565b820191906000526020600020905b8154815290600101906020018083116103c257829003601f168201915b5050505050815250509050919050565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b0381118282101715610427576104276103ef565b60405290565b60405160a081016001600160401b0381118282101715610427576104276103ef565b604051608081016001600160401b0381118282101715610427576104276103ef565b60405161010081016001600160401b0381118282101715610427576104276103ef565b604051601f8201601f191681016001600160401b03811182821017156104bc576104bc6103ef565b604052919050565b60006001600160401b038211156104dd576104dd6103ef565b5060051b60200190565b6001600160a01b03811681146104fc57600080fd5b50565b803561050a816104e7565b919050565b80356001600160e01b038116811461050a57600080fd5b80356001600160401b038116811461050a57600080fd5b600082601f83011261054e57600080fd5b8135602061056361055e836104c4565b610494565b82815260069290921b8401810191818101908684111561058257600080fd5b8286015b848110156105cf576040818903121561059f5760008081fd5b6105a7610405565b6105b082610526565b81526105bd85830161050f565b81860152835291830191604001610586565b509695505050505050565b600082601f8301126105eb57600080fd5b81356001600160401b03811115610604576106046103ef565b610617601f8201601f1916602001610494565b81815284602083860101111561062c57600080fd5b816020850160208301376000918101602001919091529392505050565b600082601f83011261065a57600080fd5b8135602061066a61055e836104c4565b82815260059290921b8401810191818101908684111561068957600080fd5b8286015b848110156105cf5780356001600160401b03808211156106ad5760008081fd5b9088019060a0828b03601f19018113156106c75760008081fd5b6106cf61042d565b6106da888501610526565b8152604080850135848111156106f05760008081fd5b6106fe8e8b838901016105da565b8a8401525060609350610712848601610526565b908201526080610723858201610526565b9382019390935292013590820152835291830191830161068d565b600082601f83011261074f57600080fd5b8135602061075f61055e836104c4565b82815260069290921b8401810191818101908684111561077e57600080fd5b8286015b848110156105cf576040818903121561079b5760008081fd5b6107a3610405565b813581528482013585820152835291830191604001610782565b600060208083850312156107d057600080fd5b82356001600160401b03808211156107e757600080fd5b90840190608082870312156107fb57600080fd5b61080361044f565b82358281111561081257600080fd5b8301604081890381131561082557600080fd5b61082d610405565b82358581111561083c57600080fd5b8301601f81018b1361084d57600080fd5b803561085b61055e826104c4565b81815260069190911b8201890190898101908d83111561087a57600080fd5b928a01925b828410156108ca5785848f0312156108975760008081fd5b61089f610405565b84356108aa816104e7565b81526108b7858d0161050f565b818d0152825292850192908a019061087f565b8452505050828701359150848211156108e257600080fd5b6108ee8a83850161053d565b8188015283525050828401358281111561090757600080fd5b61091388828601610649565b8583015250604083013593508184111561092c57600080fd5b6109388785850161073e565b6040820152606083013560608201528094505050505092915050565b600080600080600060a0868803121561096c57600080fd5b61097586610526565b945061098360208701610526565b93506040860135925060608601356004811061099e57600080fd5b915060808601356001600160401b038111156109b957600080fd5b6109c5888289016105da565b9150509295509295909350565b6000602082840312156109e457600080fd5b6109ed82610526565b9392505050565b60008060408385031215610a0757600080fd5b610a1083610526565b9150610a1e60208401610526565b90509250929050565b600060a08284031215610a3957600080fd5b610a4161042d565b905081358152610a5360208301610526565b6020820152610a6460408301610526565b6040820152610a7560608301610526565b6060820152610a8660808301610526565b608082015292915050565b600082601f830112610aa257600080fd5b81356020610ab261055e836104c4565b82815260059290921b84018101918181019086841115610ad157600080fd5b8286015b848110156105cf5780356001600160401b0380821115610af55760008081fd5b9088019060a0828b03601f1901811315610b0f5760008081fd5b610b1761042d565b610b228885016104ff565b815260408085013584811115610b385760008081fd5b610b468e8b838901016105da565b8a8401525060608086013585811115610b5f5760008081fd5b610b6d8f8c838a01016105da565b83850152506080915081860135818401525082850135925083831115610b935760008081fd5b610ba18d8a858801016105da565b908201528652505050918301918301610ad5565b60008060408385031215610bc857600080fd5b610bd183610526565b915060208301356001600160401b0380821115610bed57600080fd5b908401906101808287031215610c0257600080fd5b610c0a610471565b610c148784610a27565b8152610c2260a084016104ff565b602082015260c083013582811115610c3957600080fd5b610c45888286016105da565b60408301525060e083013582811115610c5d57600080fd5b610c69888286016105da565b60608301525061010083013582811115610c8257600080fd5b610c8e888286016105da565b608083015250610ca161012084016104ff565b60a082015261014083013560c082015261016083013582811115610cc457600080fd5b610cd088828601610a91565b60e0830152508093505050509250929050565b60008060408385031215610cf657600080fd5b610cff83610526565b915060208301356001600160401b0380821115610d1b57600080fd5b9084019060808287031215610d2f57600080fd5b610d3761044f565b8235610d42816104e7565b815260208301358015158114610d5757600080fd5b6020820152610d6860408401610526565b6040820152606083013582811115610d7f57600080fd5b610d8b888286016105da565b6060830152508093505050509250929050565b6000815180845260005b81811015610dc457602081850181015186830182015201610da8565b506000602082860101526020601f19601f83011685010191505092915050565b602080825282516001600160a01b03168282015282015115156040808301919091528201516001600160401b0316606080830191909152820151608080830152600090610e3460a0840182610d9e565b949350505050565b6001600160a01b03169052565b60008151808452602080850194506020840160005b83811015610e9757815180516001600160401b031688528301516001600160e01b03168388015260409096019590820190600101610e5e565b509495945050505050565b600082825180855260208086019550808260051b84010181860160005b84811015610f3757858303601f19018952815180516001600160401b0390811685528582015160a08787018190529190610efb83880182610d9e565b60408581015184169089015260608086015190931692880192909252506080928301519290950191909152509783019790830190600101610ebf565b5090979650505050505050565b60008151808452602080850194506020840160005b83811015610e97578151805188528301518388015260409096019590820190600101610f59565b602080825282516080838301528051604060a08501819052815160e08601819052600094939284019185916101008801905b80841015610fed57845180516001600160a01b031683528701516001600160e01b031687830152938601936001939093019290820190610fb2565b5093850151878503609f190160c0890152936110098186610e49565b945050505050818501519150601f198085830301604086015261102c8284610ea2565b925060408601519150808584030160608601525061104a8282610f44565b915050606084015160808401528091505092915050565b60006004841061108157634e487b7160e01b600052602160045260246000fd5b83825260406020830152610e346040830184610d9e565b6001600160401b038181168382160190808211156110c657634e487b7160e01b600052601160045260246000fd5b5092915050565b600082825180855260208086019550808260051b84010181860160005b84811015610f3757858303601f19018952815180516001600160a01b031684528481015160a08686018190529061112382870182610d9e565b9150506040808301518683038288015261113d8382610d9e565b925050506060808301518187015250608080830151925085820381870152506111668183610d9e565b9a86019a94505050908301906001016110ea565b602081526111c7602082018351805182526020808201516001600160401b039081169184019190915260408083015182169084015260608083015182169084015260809182015116910152565b600060208301516111db60c0840182610e3c565b5060408301516101808060e08501526111f86101a0850183610d9e565b91506060850151601f1980868503016101008701526112178483610d9e565b93506080870151915080868503016101208701526112358483610d9e565b935060a0870151915061124c610140870183610e3c565b60c087015161016087015260e087015191508086850301838701525061127283826110cd565b9695505050505050565b600181811c9082168061129057607f821691505b6020821081036112b057634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115611302576000816000526020600020601f850160051c810160208610156112df5750805b601f850160051c820191505b818110156112fe578281556001016112eb565b5050505b505050565b81516001600160401b03811115611320576113206103ef565b6113348161132e845461127c565b846112b6565b602080601f83116001811461136957600084156113515750858301515b600019600386901b1c1916600185901b1785556112fe565b600085815260208120601f198616915b8281101561139857888601518255948401946001909101908401611379565b50858210156113b65787850151600019600388901b60f8161c191681555b5050505050600190811b0190555056fea164736f6c6343000818000a", + ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"feeValueJuels\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"sourcePoolAddress\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.EVM2AnyTokenTransfer[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"CCIPSendRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"structIRMNV2.Signature[]\",\"name\":\"rmnSignatures\",\"type\":\"tuple[]\"},{\"internalType\":\"uint256\",\"name\":\"rmnRawVs\",\"type\":\"uint256\"}],\"indexed\":false,\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"report\",\"type\":\"tuple\"}],\"name\":\"CommitReportAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"name\":\"ExecutionStateChanged\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"feeValueJuels\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"sourcePoolAddress\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.EVM2AnyTokenTransfer[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"emitCCIPSendRequested\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sourceToken\",\"type\":\"address\"},{\"internalType\":\"uint224\",\"name\":\"usdPerToken\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.TokenPriceUpdate[]\",\"name\":\"tokenPriceUpdates\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint224\",\"name\":\"usdPerUnitGas\",\"type\":\"uint224\"}],\"internalType\":\"structInternal.GasPriceUpdate[]\",\"name\":\"gasPriceUpdates\",\"type\":\"tuple[]\"}],\"internalType\":\"structInternal.PriceUpdates\",\"name\":\"priceUpdates\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRampAddress\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"maxSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"structInternal.MerkleRoot[]\",\"name\":\"merkleRoots\",\"type\":\"tuple[]\"},{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"structIRMNV2.Signature[]\",\"name\":\"rmnSignatures\",\"type\":\"tuple[]\"},{\"internalType\":\"uint256\",\"name\":\"rmnRawVs\",\"type\":\"uint256\"}],\"internalType\":\"structOffRamp.CommitReport\",\"name\":\"report\",\"type\":\"tuple\"}],\"name\":\"emitCommitReportAccepted\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"enumInternal.MessageExecutionState\",\"name\":\"state\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"returnData\",\"type\":\"bytes\"}],\"name\":\"emitExecutionStateChanged\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getExpectedNextSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"getSourceChainConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"}],\"name\":\"setDestChainSeqNr\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"minSeqNr\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"onRamp\",\"type\":\"bytes\"}],\"internalType\":\"structOffRamp.SourceChainConfig\",\"name\":\"sourceChainConfig\",\"type\":\"tuple\"}],\"name\":\"setSourceChainConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x608060405234801561001057600080fd5b506113e9806100206000396000f3fe608060405234801561001057600080fd5b506004361061006d5760003560e01c8063198b821c146100725780634cf66e36146100875780639041be3d1461009a578063c081a962146100ca578063c1a5a355146100dd578063e83eabba14610119578063e9d68a8e1461012c575b600080fd5b6100856100803660046107bd565b61014c565b005b610085610095366004610954565b610186565b6100ad6100a83660046109d2565b6101db565b6040516001600160401b0390911681526020015b60405180910390f35b6100856100d8366004610b82565b61020a565b6100856100eb366004610cbc565b6001600160401b03918216600090815260016020526040902080546001600160401b03191691909216179055565b610085610127366004610cef565b61024f565b61013f61013a3660046109d2565b6102db565b6040516100c19190610df0565b7f062172a2ae1a84d7c8d18965d6267b71d579aeca033bbd2e0548947798c3d4628160405161017b9190610f8c565b60405180910390a150565b82846001600160401b0316866001600160401b03167f8c324ce1367b83031769f6a813e3bb4c117aba2185789d66b98b791405be6df285856040516101cc92919061106d565b60405180910390a45050505050565b6001600160401b03808216600090815260016020819052604082205491926102049216906110a4565b92915050565b816001600160401b03167f273f5ec254c4821d9795f26fddd245b3658bf1126d45d9d1c13a1d18a4c77750826040516102439190611186565b60405180910390a25050565b6001600160401b0380831660009081526020818152604091829020845181549286015193860151909416600160a81b02600160a81b600160e81b0319931515600160a01b026001600160a81b03199093166001600160a01b03909516949094179190911791909116919091178155606082015182919060018201906102d4908261131d565b5050505050565b60408051608080820183526000808352602080840182905283850182905260608085018190526001600160401b038781168452838352928690208651948501875280546001600160a01b0381168652600160a01b810460ff16151593860193909352600160a81b90920490921694830194909452600184018054939492939184019161036690611292565b80601f016020809104026020016040519081016040528092919081815260200182805461039290611292565b80156103df5780601f106103b4576101008083540402835291602001916103df565b820191906000526020600020905b8154815290600101906020018083116103c257829003601f168201915b5050505050815250509050919050565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b0381118282101715610427576104276103ef565b60405290565b60405160a081016001600160401b0381118282101715610427576104276103ef565b604051608081016001600160401b0381118282101715610427576104276103ef565b60405161012081016001600160401b0381118282101715610427576104276103ef565b604051601f8201601f191681016001600160401b03811182821017156104bc576104bc6103ef565b604052919050565b60006001600160401b038211156104dd576104dd6103ef565b5060051b60200190565b6001600160a01b03811681146104fc57600080fd5b50565b803561050a816104e7565b919050565b80356001600160e01b038116811461050a57600080fd5b80356001600160401b038116811461050a57600080fd5b600082601f83011261054e57600080fd5b8135602061056361055e836104c4565b610494565b82815260069290921b8401810191818101908684111561058257600080fd5b8286015b848110156105cf576040818903121561059f5760008081fd5b6105a7610405565b6105b082610526565b81526105bd85830161050f565b81860152835291830191604001610586565b509695505050505050565b600082601f8301126105eb57600080fd5b81356001600160401b03811115610604576106046103ef565b610617601f8201601f1916602001610494565b81815284602083860101111561062c57600080fd5b816020850160208301376000918101602001919091529392505050565b600082601f83011261065a57600080fd5b8135602061066a61055e836104c4565b82815260059290921b8401810191818101908684111561068957600080fd5b8286015b848110156105cf5780356001600160401b03808211156106ad5760008081fd5b9088019060a0828b03601f19018113156106c75760008081fd5b6106cf61042d565b6106da888501610526565b8152604080850135848111156106f05760008081fd5b6106fe8e8b838901016105da565b8a8401525060609350610712848601610526565b908201526080610723858201610526565b9382019390935292013590820152835291830191830161068d565b600082601f83011261074f57600080fd5b8135602061075f61055e836104c4565b82815260069290921b8401810191818101908684111561077e57600080fd5b8286015b848110156105cf576040818903121561079b5760008081fd5b6107a3610405565b813581528482013585820152835291830191604001610782565b600060208083850312156107d057600080fd5b82356001600160401b03808211156107e757600080fd5b90840190608082870312156107fb57600080fd5b61080361044f565b82358281111561081257600080fd5b8301604081890381131561082557600080fd5b61082d610405565b82358581111561083c57600080fd5b8301601f81018b1361084d57600080fd5b803561085b61055e826104c4565b81815260069190911b8201890190898101908d83111561087a57600080fd5b928a01925b828410156108ca5785848f0312156108975760008081fd5b61089f610405565b84356108aa816104e7565b81526108b7858d0161050f565b818d0152825292850192908a019061087f565b8452505050828701359150848211156108e257600080fd5b6108ee8a83850161053d565b8188015283525050828401358281111561090757600080fd5b61091388828601610649565b8583015250604083013593508184111561092c57600080fd5b6109388785850161073e565b6040820152606083013560608201528094505050505092915050565b600080600080600060a0868803121561096c57600080fd5b61097586610526565b945061098360208701610526565b93506040860135925060608601356004811061099e57600080fd5b915060808601356001600160401b038111156109b957600080fd5b6109c5888289016105da565b9150509295509295909350565b6000602082840312156109e457600080fd5b6109ed82610526565b9392505050565b600060a08284031215610a0657600080fd5b610a0e61042d565b905081358152610a2060208301610526565b6020820152610a3160408301610526565b6040820152610a4260608301610526565b6060820152610a5360808301610526565b608082015292915050565b600082601f830112610a6f57600080fd5b81356020610a7f61055e836104c4565b82815260059290921b84018101918181019086841115610a9e57600080fd5b8286015b848110156105cf5780356001600160401b0380821115610ac25760008081fd5b9088019060a0828b03601f1901811315610adc5760008081fd5b610ae461042d565b610aef8885016104ff565b815260408085013584811115610b055760008081fd5b610b138e8b838901016105da565b8a8401525060608086013585811115610b2c5760008081fd5b610b3a8f8c838a01016105da565b83850152506080915081860135818401525082850135925083831115610b605760008081fd5b610b6e8d8a858801016105da565b908201528652505050918301918301610aa2565b60008060408385031215610b9557600080fd5b610b9e83610526565b915060208301356001600160401b0380821115610bba57600080fd5b908401906101a08287031215610bcf57600080fd5b610bd7610471565b610be187846109f4565b8152610bef60a084016104ff565b602082015260c083013582811115610c0657600080fd5b610c12888286016105da565b60408301525060e083013582811115610c2a57600080fd5b610c36888286016105da565b6060830152506101008084013583811115610c5057600080fd5b610c5c898287016105da565b608084015250610c6f61012085016104ff565b60a083015261014084013560c083015261016084013560e083015261018084013583811115610c9d57600080fd5b610ca989828701610a5e565b8284015250508093505050509250929050565b60008060408385031215610ccf57600080fd5b610cd883610526565b9150610ce660208401610526565b90509250929050565b60008060408385031215610d0257600080fd5b610d0b83610526565b915060208301356001600160401b0380821115610d2757600080fd5b9084019060808287031215610d3b57600080fd5b610d4361044f565b8235610d4e816104e7565b815260208301358015158114610d6357600080fd5b6020820152610d7460408401610526565b6040820152606083013582811115610d8b57600080fd5b610d97888286016105da565b6060830152508093505050509250929050565b6000815180845260005b81811015610dd057602081850181015186830182015201610db4565b506000602082860101526020601f19601f83011685010191505092915050565b602080825282516001600160a01b03168282015282015115156040808301919091528201516001600160401b0316606080830191909152820151608080830152600090610e4060a0840182610daa565b949350505050565b6001600160a01b03169052565b60008151808452602080850194506020840160005b83811015610ea357815180516001600160401b031688528301516001600160e01b03168388015260409096019590820190600101610e6a565b509495945050505050565b600082825180855260208086019550808260051b84010181860160005b84811015610f4357858303601f19018952815180516001600160401b0390811685528582015160a08787018190529190610f0783880182610daa565b60408581015184169089015260608086015190931692880192909252506080928301519290950191909152509783019790830190600101610ecb565b5090979650505050505050565b60008151808452602080850194506020840160005b83811015610ea3578151805188528301518388015260409096019590820190600101610f65565b602080825282516080838301528051604060a08501819052815160e08601819052600094939284019185916101008801905b80841015610ff957845180516001600160a01b031683528701516001600160e01b031687830152938601936001939093019290820190610fbe565b5093850151878503609f190160c0890152936110158186610e55565b945050505050818501519150601f19808583030160408601526110388284610eae565b92506040860151915080858403016060860152506110568282610f50565b915050606084015160808401528091505092915050565b60006004841061108d57634e487b7160e01b600052602160045260246000fd5b83825260406020830152610e406040830184610daa565b6001600160401b038181168382160190808211156110d257634e487b7160e01b600052601160045260246000fd5b5092915050565b600082825180855260208086019550808260051b84010181860160005b84811015610f4357858303601f19018952815180516001600160a01b031684528481015160a08686018190529061112f82870182610daa565b915050604080830151868303828801526111498382610daa565b925050506060808301518187015250608080830151925085820381870152506111728183610daa565b9a86019a94505050908301906001016110f6565b602081526111d3602082018351805182526020808201516001600160401b039081169184019190915260408083015182169084015260608083015182169084015260809182015116910152565b600060208301516111e760c0840182610e48565b5060408301516101a08060e08501526112046101c0850183610daa565b91506060850151601f196101008187860301818801526112248584610daa565b94506080880151925081878603016101208801526112428584610daa565b945060a08801519250611259610140880184610e48565b60c088015161016088015260e088015161018088015287015186850390910183870152905061128883826110d9565b9695505050505050565b600181811c908216806112a657607f821691505b6020821081036112c657634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115611318576000816000526020600020601f850160051c810160208610156112f55750805b601f850160051c820191505b8181101561131457828155600101611301565b5050505b505050565b81516001600160401b03811115611336576113366103ef565b61134a816113448454611292565b846112cc565b602080601f83116001811461137f57600084156113675750858301515b600019600386901b1c1916600185901b178555611314565b600085815260208120601f198616915b828110156113ae5788860151825594840194600190910190840161138f565b50858210156113cc5787850151600019600388901b60f8161c191681555b5050505050600190811b0190555056fea164736f6c6343000818000a", } var CCIPReaderTesterABI = CCIPReaderTesterMetaData.ABI @@ -751,7 +752,7 @@ func (_CCIPReaderTester *CCIPReaderTester) ParseLog(log types.Log) (generated.Ab } func (CCIPReaderTesterCCIPSendRequested) Topic() common.Hash { - return common.HexToHash("0xe07a589f12eccf1bc0f7421666687a6986a0c8dbbdc877d1af562a97ba60ecfd") + return common.HexToHash("0x273f5ec254c4821d9795f26fddd245b3658bf1126d45d9d1c13a1d18a4c77750") } func (CCIPReaderTesterCommitReportAccepted) Topic() common.Hash { diff --git a/core/gethwrappers/ccip/generated/onramp/onramp.go b/core/gethwrappers/ccip/generated/onramp/onramp.go index 25dd768201..71d25dec61 100644 --- a/core/gethwrappers/ccip/generated/onramp/onramp.go +++ b/core/gethwrappers/ccip/generated/onramp/onramp.go @@ -51,6 +51,7 @@ type InternalEVM2AnyRampMessage struct { ExtraArgs []byte FeeToken common.Address FeeTokenAmount *big.Int + FeeValueJuels *big.Int TokenAmounts []InternalEVM2AnyTokenTransfer } @@ -98,8 +99,8 @@ type OnRampStaticConfig struct { } var OnRampMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"reentrancyGuardEntered\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CannotSendZeroTokens\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GetSupportedTokensFunctionalityRemovedCheckAdminRegistry\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidAllowListRequest\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidDestChainConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeCalledByRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrAllowlistAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrancyGuardReentrantCall\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RouterMustSetOriginalSender\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"UnsupportedToken\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"name\":\"AllowListAdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"senders\",\"type\":\"address[]\"}],\"name\":\"AllowListSendersAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"senders\",\"type\":\"address[]\"}],\"name\":\"AllowListSendersRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"sourcePoolAddress\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.EVM2AnyTokenTransfer[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"CCIPMessageSent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOnRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"reentrancyGuardEntered\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"allowListEnabled\",\"type\":\"bool\"}],\"name\":\"DestChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"feeValueJuels\",\"type\":\"uint256\"}],\"name\":\"FeePaid\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeeTokenWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"allowListEnabled\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"addedAllowlistedSenders\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"removedAllowlistedSenders\",\"type\":\"address[]\"}],\"internalType\":\"structOnRamp.AllowListConfigArgs[]\",\"name\":\"allowListConfigArgsItems\",\"type\":\"tuple[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyDestChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"}],\"name\":\"forwardFromRouter\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getAllowedSendersList\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getDestChainConfig\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"allowListEnabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"reentrancyGuardEntered\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getExpectedNextSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"getFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"},{\"internalType\":\"contractIERC20\",\"name\":\"sourceToken\",\"type\":\"address\"}],\"name\":\"getPoolBySourceToken\",\"outputs\":[{\"internalType\":\"contractIPoolV1\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"contractIRouter\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"name\":\"getSupportedTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"reentrancyGuardEntered\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"setDynamicConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"withdrawFeeTokens\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x6101006040523480156200001257600080fd5b506040516200429a3803806200429a83398101604081905262000035916200073f565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf8162000186565b505083516001600160401b031615905080620000e6575060208301516001600160a01b0316155b80620000fd575060408301516001600160a01b0316155b8062000114575060608301516001600160a01b0316155b1562000133576040516306b7c75960e31b815260040160405180910390fd5b82516001600160401b031660805260208301516001600160a01b0390811660a0526040840151811660c05260608401511660e052620001728262000231565b6200017d81620003e0565b50505062000840565b336001600160a01b03821603620001e05760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b0316158062000254575060608101516001600160a01b0316155b8062000261575080602001515b1562000280576040516306b7c75960e31b815260040160405180910390fd5b8051600280546020808501511515600160a01b026001600160a81b03199092166001600160a01b039485161791909117909155604080840151600380549185166001600160a01b0319928316179055606080860151600480549187169184169190911790556080808701516005805491881691909416179092558251808301845291516001600160401b0316825260a05185169382019390935260c05184168183015260e05190931691830191909152517fc7372d2d886367d7bb1b0e0708a5436f2c91d6963de210eb2dc1ec2ecd6d21f191620003d591849082516001600160401b031681526020808401516001600160a01b03908116828401526040858101518216818501526060958601518216868501528451821660808086019190915292850151151560a0850152840151811660c084015293830151841660e0830152909101519091166101008201526101200190565b60405180910390a150565b60005b81518110156200051f5760008282815181106200040457620004046200082a565b6020026020010151905060008383815181106200042557620004256200082a565b6020026020010151600001519050806001600160401b03166000036200046a5760405163c35aa79d60e01b81526001600160401b038216600482015260240162000083565b6001600160401b03818116600081815260066020908152604091829020868201518154600160481b600160e81b0319811669010000000000000000006001600160a01b03909316928302908117808555865192891691909816178152928301526801000000000000000090940460ff161515918101919091527fd5ad72bc37dc7a80a8b9b9df20500046fd7341adb1be2258a540466fdd7dcef59060600160405180910390a2505050806001019050620003e3565b5050565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b03811182821017156200055e576200055e62000523565b60405290565b604051601f8201601f191681016001600160401b03811182821017156200058f576200058f62000523565b604052919050565b80516001600160401b0381168114620005af57600080fd5b919050565b6001600160a01b0381168114620005ca57600080fd5b50565b600060a08284031215620005e057600080fd5b60405160a081016001600160401b038111828210171562000605576200060562000523565b806040525080915082516200061a81620005b4565b8152602083015180151581146200063057600080fd5b602082015260408301516200064581620005b4565b604082015260608301516200065a81620005b4565b606082015260808301516200066f81620005b4565b6080919091015292915050565b600082601f8301126200068e57600080fd5b815160206001600160401b03821115620006ac57620006ac62000523565b620006bc818360051b0162000564565b82815260069290921b84018101918181019086841115620006dc57600080fd5b8286015b84811015620007345760408189031215620006fb5760008081fd5b6200070562000539565b620007108262000597565b8152848201516200072181620005b4565b81860152835291830191604001620006e0565b509695505050505050565b60008060008385036101408112156200075757600080fd5b60808112156200076657600080fd5b50604051608081016001600160401b0380821183831017156200078d576200078d62000523565b816040526200079c8762000597565b835260208701519150620007b082620005b4565b81602084015260408701519150620007c882620005b4565b81604084015260608701519150620007e082620005b4565b816060840152829550620007f88860808901620005cd565b94506101208701519250808311156200081057600080fd5b505062000820868287016200067c565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b60805160a05160c05160e0516139e1620008b96000396000818161022c01528181610cfd0152611c3f0152600081816101f00152818161163a0152611c180152600081816101b4015281816106080152611bee0152600081816101840152818161114b015281816117550152611bca01526139e16000f3fe608060405234801561001057600080fd5b50600436106101365760003560e01c80637437ff9f116100b2578063972b461211610081578063df0aa9e911610066578063df0aa9e914610557578063f2fde38b1461056a578063fbca3b741461057d57600080fd5b8063972b4612146104ea578063d77d5ed01461050a57600080fd5b80637437ff9f146103ee57806379ba5097146104985780638da5cb5b146104a05780639041be3d146104be57600080fd5b806327e936f1116101095780633a019940116100ee5780633a0199401461030f57806348a98aa4146103175780636def4ce71461034f57600080fd5b806327e936f1146102e957806334adf494146102fc57600080fd5b80630242cf601461013b57806306285c6914610150578063181f5a771461027f57806320487ded146102c8575b600080fd5b61014e610149366004612837565b610590565b005b61026960408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16815250905090565b60405161027691906128fa565b60405180910390f35b6102bb6040518060400160405280601081526020017f4f6e52616d7020312e362e302d6465760000000000000000000000000000000081525081565b60405161027691906129bf565b6102db6102d63660046129ea565b6105a4565b604051908152602001610276565b61014e6102f7366004612a58565b61075d565b61014e61030a366004612af0565b61076e565b61014e610a8a565b61032a610325366004612b65565b610cb5565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610276565b6103b261035d366004612b9e565b67ffffffffffffffff9081166000908152600660205260409020549081169168010000000000000000820460ff16916901000000000000000000900473ffffffffffffffffffffffffffffffffffffffff1690565b6040805167ffffffffffffffff9094168452911515602084015273ffffffffffffffffffffffffffffffffffffffff1690820152606001610276565b61048b6040805160a081018252600080825260208201819052918101829052606081018290526080810191909152506040805160a08101825260025473ffffffffffffffffffffffffffffffffffffffff80821683527401000000000000000000000000000000000000000090910460ff161515602083015260035481169282019290925260045482166060820152600554909116608082015290565b6040516102769190612bbb565b61014e610d6a565b60005473ffffffffffffffffffffffffffffffffffffffff1661032a565b6104d16104cc366004612b9e565b610e67565b60405167ffffffffffffffff9091168152602001610276565b6104fd6104f8366004612b9e565b610e90565b6040516102769190612c14565b61032a610518366004612b9e565b67ffffffffffffffff166000908152600660205260409020546901000000000000000000900473ffffffffffffffffffffffffffffffffffffffff1690565b6102db610565366004612c6e565b610eb8565b61014e610578366004612cda565b611832565b6104fd61058b366004612b9e565b611843565b610598611877565b6105a1816118fa565b50565b6040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815277ffffffffffffffff00000000000000000000000000000000608084901b16600482015260009073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690632cbc26bb90602401602060405180830381865afa15801561064f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106739190612cf7565b156106bb576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024015b60405180910390fd5b6002546040517fd8694ccd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063d8694ccd906107139086908690600401612e28565b602060405180830381865afa158015610730573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107549190612f71565b90505b92915050565b610765611877565b6105a181611a71565b60005473ffffffffffffffffffffffffffffffffffffffff1633146107de5760055473ffffffffffffffffffffffffffffffffffffffff1633146107de576040517f905d7d9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015610a855760008383838181106107fd576107fd612f8a565b905060200281019061080f9190612fb9565b6108189061306a565b805167ffffffffffffffff1660009081526006602090815260409182902090830151815490151568010000000000000000027fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff909116178155908201515191925090156109d8578160200151156109975760005b826040015151811015610947576000836040015182815181106108b1576108b1612f8a565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036109305783516040517f463258ff00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016106b2565b61093d6001840182611ca1565b505060010161088c565b50816000015167ffffffffffffffff167f330939f6eafe8bb516716892fe962ff19770570838686e6579dbc1cc51fc3281836040015160405161098a9190612c14565b60405180910390a26109d8565b81516040517f463258ff00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016106b2565b60005b826060015151811015610a2457610a1b83606001518281518110610a0157610a01612f8a565b602002602001015183600101611cc390919063ffffffff16565b506001016109db565b5060608201515115610a7b57816000015167ffffffffffffffff167fc237ec1921f855ccd5e9a5af9733f2d58943a5a8501ec5988e305d7a4d4215868360600151604051610a729190612c14565b60405180910390a25b50506001016107e1565b505050565b600254604080517fcdc73d51000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163cdc73d5191600480830192869291908290030181865afa158015610af9573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610b3f919081019061311b565b60045490915073ffffffffffffffffffffffffffffffffffffffff1660005b8251811015610a85576000838281518110610b7b57610b7b612f8a565b60209081029190910101516040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915060009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa158015610bf6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c1a9190612f71565b90508015610cab57610c4373ffffffffffffffffffffffffffffffffffffffff83168583611ce5565b8173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f508d7d183612c18fc339b42618912b9fa3239f631dd7ec0671f950200a0fa66e83604051610ca291815260200190565b60405180910390a35b5050600101610b5e565b6040517fbbe4f6db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063bbe4f6db90602401602060405180830381865afa158015610d46573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061075491906131aa565b60015473ffffffffffffffffffffffffffffffffffffffff163314610deb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064016106b2565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b67ffffffffffffffff8082166000908152600660205260408120549091610757911660016131f6565b67ffffffffffffffff8116600090815260066020526040902060609061075790600101611d72565b60025460009074010000000000000000000000000000000000000000900460ff1615610f10576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905567ffffffffffffffff8516600090815260066020526040902073ffffffffffffffffffffffffffffffffffffffff8316610fb5576040517fa4ec747900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805468010000000000000000900460ff161561102657610fd86001820184611d86565b611026576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841660048201526024016106b2565b80546901000000000000000000900473ffffffffffffffffffffffffffffffffffffffff163314611083576040517f1c0a352900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60035473ffffffffffffffffffffffffffffffffffffffff168015611129576040517fe0a0e50600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82169063e0a0e506906110f6908a908a90600401612e28565b600060405180830381600087803b15801561111057600080fd5b505af1158015611124573d6000803e3d6000fd5b505050505b50604080516101a081019091526000610100820181815267ffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000081166101208501528981166101408501528454929392839291610160840191879187916111979116613217565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905567ffffffffffffffff168152602001600067ffffffffffffffff1681525081526020018573ffffffffffffffffffffffffffffffffffffffff16815260200187806020019061120b919061323e565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050509082525060200161124f888061323e565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920182905250938552505060408051602081810183529381529284019290925250016112ab6080890160608a01612cda565b73ffffffffffffffffffffffffffffffffffffffff1681526020018681526020018780604001906112dc91906132a3565b905067ffffffffffffffff8111156112f6576112f6612734565b60405190808252806020026020018201604052801561136f57816020015b61135c6040518060a00160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001606081526020016060815260200160008152602001606081525090565b8152602001906001900390816113145790505b5090529050600061138360408801886132a3565b808060200260200160405190810160405280939291908181526020016000905b828210156113cf576113c06040830286013681900381019061330b565b815260200190600101906113a3565b5050505050905060005b6113e660408901896132a3565b905081101561147f5761145682828151811061140457611404612f8a565b60209081029190910101518a61141a8b8061323e565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508c9250611db5915050565b8360e00151828151811061146c5761146c612f8a565b60209081029190910101526001016113d9565b50600080600080600260000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663430d138c8d8d60600160208101906114db9190612cda565b8d8f80608001906114ec919061323e565b8c60e001518c6040518863ffffffff1660e01b81526004016115149796959493929190613428565b600060405180830381865afa158015611531573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611577919081019061355a565b9296509094509250905061159160808c0160608d01612cda565b73ffffffffffffffffffffffffffffffffffffffff167f075a2720282fdf622141dae0b048ef90a21a7e57c134c76912d19d006b3b3f6f856040516115d891815260200190565b60405180910390a2826116ac576040517fea458c0c00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8d16600482015273ffffffffffffffffffffffffffffffffffffffff8a811660248301527f0000000000000000000000000000000000000000000000000000000000000000169063ea458c0c906044016020604051808303816000875af1158015611683573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a7919061364d565b6116af565b60005b865167ffffffffffffffff909116608091820152860182905260005b8660e001515181101561171f578181815181106116ea576116ea612f8a565b60200260200101518760e00151828151811061170857611708612f8a565b6020908102919091010151608001526001016116cb565b50604080517f130ac867e79e2789f923760a88743d292acdf7002139a588206e2260f73f7321602082015267ffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811692820192909252908d1660608201523060808201526117af90879060a001604051602081830303815290604052805190602001206120cc565b86515260405167ffffffffffffffff8d16907f9f4bd3af5ec85ce7c750c95aca08cf5460a4a3f952cf1db9c2bbf22cdfe78bbf906117ee90899061366a565b60405180910390a25050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1690555050905151925050505b949350505050565b61183a611877565b6105a18161221d565b60606040517f9e7177c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005473ffffffffffffffffffffffffffffffffffffffff1633146118f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016106b2565b565b60005b8151811015611a6d57600082828151811061191a5761191a612f8a565b60200260200101519050600083838151811061193857611938612f8a565b60200260200101516000015190508067ffffffffffffffff16600003611996576040517fc35aa79d00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff821660048201526024016106b2565b67ffffffffffffffff8181166000818152600660209081526040918290208682015181547fffffff0000000000000000000000000000000000000000ffffffffffffffffff8116690100000000000000000073ffffffffffffffffffffffffffffffffffffffff909316928302908117808555865192891691909816178152928301526801000000000000000090940460ff161515918101919091527fd5ad72bc37dc7a80a8b9b9df20500046fd7341adb1be2258a540466fdd7dcef59060600160405180910390a25050508060010190506118fd565b5050565b805173ffffffffffffffffffffffffffffffffffffffff161580611aad5750606081015173ffffffffffffffffffffffffffffffffffffffff16155b80611ab9575080602001515b15611af0576040517f35be3ac800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160028054602080850151151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00000000000000000000000000000000000000000090921673ffffffffffffffffffffffffffffffffffffffff9485161791909117909155604080840151600380549185167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316179055606080860151600480549187169184169190911790556080808701516005805491881691909416179092558251918201835267ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001682527f00000000000000000000000000000000000000000000000000000000000000008516938201939093527f00000000000000000000000000000000000000000000000000000000000000008416818301527f000000000000000000000000000000000000000000000000000000000000000090931691830191909152517fc7372d2d886367d7bb1b0e0708a5436f2c91d6963de210eb2dc1ec2ecd6d21f191611c969184906137b8565b60405180910390a150565b60006107548373ffffffffffffffffffffffffffffffffffffffff8416612312565b60006107548373ffffffffffffffffffffffffffffffffffffffff8416612361565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052610a8590849061245b565b60606000611d7f83612567565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515610754565b611dfd6040518060a00160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001606081526020016060815260200160008152602001606081525090565b8460200151600003611e3b576040517f5cf0444900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611e4b858760000151610cb5565b905073ffffffffffffffffffffffffffffffffffffffff81161580611f1b57506040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527faff2afbf00000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff8216906301ffc9a790602401602060405180830381865afa158015611ef5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f199190612cf7565b155b15611f6d5785516040517fbf16aab600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911660048201526024016106b2565b60008173ffffffffffffffffffffffffffffffffffffffff16639a4575b96040518060a001604052808881526020018967ffffffffffffffff1681526020018773ffffffffffffffffffffffffffffffffffffffff1681526020018a6020015181526020018a6000015173ffffffffffffffffffffffffffffffffffffffff168152506040518263ffffffff1660e01b815260040161200c9190613866565b6000604051808303816000875af115801561202b573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261207191908101906138dc565b6040805160a08101825273ffffffffffffffffffffffffffffffffffffffff90941684528151602080860191909152918201518482015288820151606085015280519182019052600081526080830152509050949350505050565b60008060001b8284602001518560000151606001518660000151608001518760a001518860c0015160405160200161214a95949392919073ffffffffffffffffffffffffffffffffffffffff958616815267ffffffffffffffff94851660208201529290931660408301529092166060830152608082015260a00190565b604051602081830303815290604052805190602001208560600151805190602001208660400151805190602001208760e0015160405160200161218d919061396d565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201206080808d0151805190840120928501999099529183019690965260608201949094529485019190915260a084015260c083015260e08201526101000160405160208183030381529060405280519060200120905092915050565b3373ffffffffffffffffffffffffffffffffffffffff82160361229c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016106b2565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600081815260018301602052604081205461235957508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610757565b506000610757565b6000818152600183016020526040812054801561244a576000612385600183613980565b855490915060009061239990600190613980565b90508082146123fe5760008660000182815481106123b9576123b9612f8a565b90600052602060002001549050808760000184815481106123dc576123dc612f8a565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061240f5761240f613993565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610757565b6000915050610757565b5092915050565b60006124bd826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166125c39092919063ffffffff16565b805190915015610a8557808060200190518101906124db9190612cf7565b610a85576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016106b2565b6060816000018054806020026020016040519081016040528092919081815260200182805480156125b757602002820191906000526020600020905b8154815260200190600101908083116125a3575b50505050509050919050565b606061182a8484600085856000808673ffffffffffffffffffffffffffffffffffffffff1685876040516125f791906139c2565b60006040518083038185875af1925050503d8060008114612634576040519150601f19603f3d011682016040523d82523d6000602084013e612639565b606091505b509150915061264a87838387612655565b979650505050505050565b606083156126eb5782516000036126e45773ffffffffffffffffffffffffffffffffffffffff85163b6126e4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016106b2565b508161182a565b61182a83838151156127005781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106b291906129bf565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561278657612786612734565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156127d3576127d3612734565b604052919050565b600067ffffffffffffffff8211156127f5576127f5612734565b5060051b60200190565b67ffffffffffffffff811681146105a157600080fd5b73ffffffffffffffffffffffffffffffffffffffff811681146105a157600080fd5b6000602080838503121561284a57600080fd5b823567ffffffffffffffff81111561286157600080fd5b8301601f8101851361287257600080fd5b8035612885612880826127db565b61278c565b81815260069190911b820183019083810190878311156128a457600080fd5b928401925b8284101561264a57604084890312156128c25760008081fd5b6128ca612763565b84356128d5816127ff565b8152848601356128e481612815565b81870152825260409390930192908401906128a9565b60808101610757828467ffffffffffffffff8151168252602081015173ffffffffffffffffffffffffffffffffffffffff808216602085015280604084015116604085015280606084015116606085015250505050565b60005b8381101561296c578181015183820152602001612954565b50506000910152565b6000815180845261298d816020860160208601612951565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006107546020830184612975565b600060a082840312156129e457600080fd5b50919050565b600080604083850312156129fd57600080fd5b8235612a08816127ff565b9150602083013567ffffffffffffffff811115612a2457600080fd5b612a30858286016129d2565b9150509250929050565b8035612a4581612815565b919050565b80151581146105a157600080fd5b600060a08284031215612a6a57600080fd5b60405160a0810181811067ffffffffffffffff82111715612a8d57612a8d612734565b6040528235612a9b81612815565b81526020830135612aab81612a4a565b60208201526040830135612abe81612815565b60408201526060830135612ad181612815565b60608201526080830135612ae481612815565b60808201529392505050565b60008060208385031215612b0357600080fd5b823567ffffffffffffffff80821115612b1b57600080fd5b818501915085601f830112612b2f57600080fd5b813581811115612b3e57600080fd5b8660208260051b8501011115612b5357600080fd5b60209290920196919550909350505050565b60008060408385031215612b7857600080fd5b8235612b83816127ff565b91506020830135612b9381612815565b809150509250929050565b600060208284031215612bb057600080fd5b8135611d7f816127ff565b60a08101610757828473ffffffffffffffffffffffffffffffffffffffff808251168352602082015115156020840152806040830151166040840152806060830151166060840152806080830151166080840152505050565b6020808252825182820181905260009190848201906040850190845b81811015612c6257835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101612c30565b50909695505050505050565b60008060008060808587031215612c8457600080fd5b8435612c8f816127ff565b9350602085013567ffffffffffffffff811115612cab57600080fd5b612cb7878288016129d2565b935050604085013591506060850135612ccf81612815565b939692955090935050565b600060208284031215612cec57600080fd5b8135611d7f81612815565b600060208284031215612d0957600080fd5b8151611d7f81612a4a565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112612d4957600080fd5b830160208101925035905067ffffffffffffffff811115612d6957600080fd5b803603821315612d7857600080fd5b9250929050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b8183526000602080850194508260005b85811015612e1d578135612deb81612815565b73ffffffffffffffffffffffffffffffffffffffff168752818301358388015260409687019690910190600101612dd8565b509495945050505050565b600067ffffffffffffffff808516835260406020840152612e498485612d14565b60a06040860152612e5e60e086018284612d7f565b915050612e6e6020860186612d14565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc080878503016060880152612ea4848385612d7f565b9350604088013592507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1883603018312612edd57600080fd5b60209288019283019235915084821115612ef657600080fd5b8160061b3603831315612f0857600080fd5b80878503016080880152612f1d848385612dc8565b9450612f2b60608901612a3a565b73ffffffffffffffffffffffffffffffffffffffff811660a08901529350612f566080890189612d14565b94509250808786030160c0880152505061264a838383612d7f565b600060208284031215612f8357600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81833603018112612fed57600080fd5b9190910192915050565b600082601f83011261300857600080fd5b81356020613018612880836127db565b8083825260208201915060208460051b87010193508684111561303a57600080fd5b602086015b8481101561305f57803561305281612815565b835291830191830161303f565b509695505050505050565b60006080823603121561307c57600080fd5b6040516080810167ffffffffffffffff82821081831117156130a0576130a0612734565b81604052843591506130b1826127ff565b9082526020840135906130c382612a4a565b81602084015260408501359150808211156130dd57600080fd5b6130e936838701612ff7565b6040840152606085013591508082111561310257600080fd5b5061310f36828601612ff7565b60608301525092915050565b6000602080838503121561312e57600080fd5b825167ffffffffffffffff81111561314557600080fd5b8301601f8101851361315657600080fd5b8051613164612880826127db565b81815260059190911b8201830190838101908783111561318357600080fd5b928401925b8284101561264a57835161319b81612815565b82529284019290840190613188565b6000602082840312156131bc57600080fd5b8151611d7f81612815565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b67ffffffffffffffff818116838216019080821115612454576124546131c7565b600067ffffffffffffffff808316818103613234576132346131c7565b6001019392505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261327357600080fd5b83018035915067ffffffffffffffff82111561328e57600080fd5b602001915036819003821315612d7857600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126132d857600080fd5b83018035915067ffffffffffffffff8211156132f357600080fd5b6020019150600681901b3603821315612d7857600080fd5b60006040828403121561331d57600080fd5b613325612763565b823561333081612815565b81526020928301359281019290925250919050565b600082825180855260208086019550808260051b84010181860160005b8481101561341b577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018952815160a073ffffffffffffffffffffffffffffffffffffffff82511685528582015181878701526133c482870182612975565b915050604080830151868303828801526133de8382612975565b925050506060808301518187015250608080830151925085820381870152506134078183612975565b9a86019a9450505090830190600101613362565b5090979650505050505050565b67ffffffffffffffff881681526000602073ffffffffffffffffffffffffffffffffffffffff808a1682850152604089604086015260c0606086015261347260c08601898b612d7f565b85810360808701526134848189613345565b86810360a0880152875180825285890192509085019060005b818110156134c457835180518716845287015187840152928601929184019160010161349d565b50909e9d5050505050505050505050505050565b600082601f8301126134e957600080fd5b815167ffffffffffffffff81111561350357613503612734565b61353460207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160161278c565b81815284602083860101111561354957600080fd5b61182a826020830160208701612951565b6000806000806080858703121561357057600080fd5b8451935060208086015161358381612a4a565b604087015190945067ffffffffffffffff808211156135a157600080fd5b6135ad89838a016134d8565b945060608801519150808211156135c357600080fd5b818801915088601f8301126135d757600080fd5b81516135e5612880826127db565b81815260059190911b8301840190848101908b83111561360457600080fd5b8585015b8381101561363c578051858111156136205760008081fd5b61362e8e89838a01016134d8565b845250918601918601613608565b50989b979a50959850505050505050565b60006020828403121561365f57600080fd5b8151611d7f816127ff565b602081526136bb60208201835180518252602081015167ffffffffffffffff808216602085015280604084015116604085015280606084015116606085015280608084015116608085015250505050565b600060208301516136e460c084018273ffffffffffffffffffffffffffffffffffffffff169052565b5060408301516101808060e08501526137016101a0850183612975565b915060608501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0808685030161010087015261373e8483612975565b935060808701519150808685030161012087015261375c8483612975565b935060a0870151915061378861014087018373ffffffffffffffffffffffffffffffffffffffff169052565b60c087015161016087015260e08701519150808685030183870152506137ae8382613345565b9695505050505050565b6101208101613810828567ffffffffffffffff8151168252602081015173ffffffffffffffffffffffffffffffffffffffff808216602085015280604084015116604085015280606084015116606085015250505050565b825173ffffffffffffffffffffffffffffffffffffffff9081166080848101919091526020850151151560a08501526040850151821660c08501526060850151821660e085015284015116610100830152611d7f565b602081526000825160a0602084015261388260c0840182612975565b905067ffffffffffffffff6020850151166040840152604084015173ffffffffffffffffffffffffffffffffffffffff8082166060860152606086015160808601528060808701511660a086015250508091505092915050565b6000602082840312156138ee57600080fd5b815167ffffffffffffffff8082111561390657600080fd5b908301906040828603121561391a57600080fd5b613922612763565b82518281111561393157600080fd5b61393d878286016134d8565b82525060208301518281111561395257600080fd5b61395e878286016134d8565b60208301525095945050505050565b6020815260006107546020830184613345565b81810381811115610757576107576131c7565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b60008251612fed81846020870161295156fea164736f6c6343000818000a", + ABI: "[{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"reentrancyGuardEntered\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"CannotSendZeroTokens\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"CursedByRMN\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GetSupportedTokensFunctionalityRemovedCheckAdminRegistry\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidAllowListRequest\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidConfig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"}],\"name\":\"InvalidDestChainConfig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustBeCalledByRouter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrAllowlistAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrancyGuardReentrantCall\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RouterMustSetOriginalSender\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAllowed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"UnsupportedToken\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"name\":\"AllowListAdminSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"senders\",\"type\":\"address[]\"}],\"name\":\"AllowListSendersAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"senders\",\"type\":\"address[]\"}],\"name\":\"AllowListSendersRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"messageId\",\"type\":\"bytes32\"},{\"internalType\":\"uint64\",\"name\":\"sourceChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"internalType\":\"structInternal.RampMessageHeader\",\"name\":\"header\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"feeValueJuels\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"sourcePoolAddress\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"destTokenAddress\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"destExecData\",\"type\":\"bytes\"}],\"internalType\":\"structInternal.EVM2AnyTokenTransfer[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"}],\"indexed\":false,\"internalType\":\"structInternal.EVM2AnyRampMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"CCIPMessageSent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOnRamp.StaticConfig\",\"name\":\"staticConfig\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"reentrancyGuardEntered\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"indexed\":false,\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"allowListEnabled\",\"type\":\"bool\"}],\"name\":\"DestChainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeeTokenWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"allowListEnabled\",\"type\":\"bool\"},{\"internalType\":\"address[]\",\"name\":\"addedAllowlistedSenders\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"removedAllowlistedSenders\",\"type\":\"address[]\"}],\"internalType\":\"structOnRamp.AllowListConfigArgs[]\",\"name\":\"allowListConfigArgsItems\",\"type\":\"tuple[]\"}],\"name\":\"applyAllowListUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRouter\",\"name\":\"router\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DestChainConfigArgs[]\",\"name\":\"destChainConfigArgs\",\"type\":\"tuple[]\"}],\"name\":\"applyDestChainConfigUpdates\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"originalSender\",\"type\":\"address\"}],\"name\":\"forwardFromRouter\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getAllowedSendersList\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getDestChainConfig\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"sequenceNumber\",\"type\":\"uint64\"},{\"internalType\":\"bool\",\"name\":\"allowListEnabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"router\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getDynamicConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"reentrancyGuardEntered\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getExpectedNextSequenceNumber\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"receiver\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"internalType\":\"structClient.EVMTokenAmount[]\",\"name\":\"tokenAmounts\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"feeToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structClient.EVM2AnyMessage\",\"name\":\"message\",\"type\":\"tuple\"}],\"name\":\"getFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"feeTokenAmount\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"},{\"internalType\":\"contractIERC20\",\"name\":\"sourceToken\",\"type\":\"address\"}],\"name\":\"getPoolBySourceToken\",\"outputs\":[{\"internalType\":\"contractIPoolV1\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"destChainSelector\",\"type\":\"uint64\"}],\"name\":\"getRouter\",\"outputs\":[{\"internalType\":\"contractIRouter\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStaticConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"chainSelector\",\"type\":\"uint64\"},{\"internalType\":\"contractIRMNV2\",\"name\":\"rmn\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nonceManager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenAdminRegistry\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.StaticConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"name\":\"getSupportedTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"feeQuoter\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"reentrancyGuardEntered\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"messageInterceptor\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeAggregator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"allowListAdmin\",\"type\":\"address\"}],\"internalType\":\"structOnRamp.DynamicConfig\",\"name\":\"dynamicConfig\",\"type\":\"tuple\"}],\"name\":\"setDynamicConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"withdrawFeeTokens\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x6101006040523480156200001257600080fd5b506040516200422f3803806200422f83398101604081905262000035916200073f565b33806000816200008c5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000bf57620000bf8162000186565b505083516001600160401b031615905080620000e6575060208301516001600160a01b0316155b80620000fd575060408301516001600160a01b0316155b8062000114575060608301516001600160a01b0316155b1562000133576040516306b7c75960e31b815260040160405180910390fd5b82516001600160401b031660805260208301516001600160a01b0390811660a0526040840151811660c05260608401511660e052620001728262000231565b6200017d81620003e0565b50505062000840565b336001600160a01b03821603620001e05760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000083565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b0316158062000254575060608101516001600160a01b0316155b8062000261575080602001515b1562000280576040516306b7c75960e31b815260040160405180910390fd5b8051600280546020808501511515600160a01b026001600160a81b03199092166001600160a01b039485161791909117909155604080840151600380549185166001600160a01b0319928316179055606080860151600480549187169184169190911790556080808701516005805491881691909416179092558251808301845291516001600160401b0316825260a05185169382019390935260c05184168183015260e05190931691830191909152517fc7372d2d886367d7bb1b0e0708a5436f2c91d6963de210eb2dc1ec2ecd6d21f191620003d591849082516001600160401b031681526020808401516001600160a01b03908116828401526040858101518216818501526060958601518216868501528451821660808086019190915292850151151560a0850152840151811660c084015293830151841660e0830152909101519091166101008201526101200190565b60405180910390a150565b60005b81518110156200051f5760008282815181106200040457620004046200082a565b6020026020010151905060008383815181106200042557620004256200082a565b6020026020010151600001519050806001600160401b03166000036200046a5760405163c35aa79d60e01b81526001600160401b038216600482015260240162000083565b6001600160401b03818116600081815260066020908152604091829020868201518154600160481b600160e81b0319811669010000000000000000006001600160a01b03909316928302908117808555865192891691909816178152928301526801000000000000000090940460ff161515918101919091527fd5ad72bc37dc7a80a8b9b9df20500046fd7341adb1be2258a540466fdd7dcef59060600160405180910390a2505050806001019050620003e3565b5050565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b03811182821017156200055e576200055e62000523565b60405290565b604051601f8201601f191681016001600160401b03811182821017156200058f576200058f62000523565b604052919050565b80516001600160401b0381168114620005af57600080fd5b919050565b6001600160a01b0381168114620005ca57600080fd5b50565b600060a08284031215620005e057600080fd5b60405160a081016001600160401b038111828210171562000605576200060562000523565b806040525080915082516200061a81620005b4565b8152602083015180151581146200063057600080fd5b602082015260408301516200064581620005b4565b604082015260608301516200065a81620005b4565b606082015260808301516200066f81620005b4565b6080919091015292915050565b600082601f8301126200068e57600080fd5b815160206001600160401b03821115620006ac57620006ac62000523565b620006bc818360051b0162000564565b82815260069290921b84018101918181019086841115620006dc57600080fd5b8286015b84811015620007345760408189031215620006fb5760008081fd5b6200070562000539565b620007108262000597565b8152848201516200072181620005b4565b81860152835291830191604001620006e0565b509695505050505050565b60008060008385036101408112156200075757600080fd5b60808112156200076657600080fd5b50604051608081016001600160401b0380821183831017156200078d576200078d62000523565b816040526200079c8762000597565b835260208701519150620007b082620005b4565b81602084015260408701519150620007c882620005b4565b81604084015260608701519150620007e082620005b4565b816060840152829550620007f88860808901620005cd565b94506101208701519250808311156200081057600080fd5b505062000820868287016200067c565b9150509250925092565b634e487b7160e01b600052603260045260246000fd5b60805160a05160c05160e051613976620008b96000396000818161022c01528181610cfd0152611bc90152600081816101f0015281816115c40152611ba20152600081816101b4015281816106080152611b780152600081816101840152818161114b015281816116e10152611b5401526139766000f3fe608060405234801561001057600080fd5b50600436106101365760003560e01c80637437ff9f116100b2578063972b461211610081578063df0aa9e911610066578063df0aa9e914610557578063f2fde38b1461056a578063fbca3b741461057d57600080fd5b8063972b4612146104ea578063d77d5ed01461050a57600080fd5b80637437ff9f146103ee57806379ba5097146104985780638da5cb5b146104a05780639041be3d146104be57600080fd5b806327e936f1116101095780633a019940116100ee5780633a0199401461030f57806348a98aa4146103175780636def4ce71461034f57600080fd5b806327e936f1146102e957806334adf494146102fc57600080fd5b80630242cf601461013b57806306285c6914610150578063181f5a771461027f57806320487ded146102c8575b600080fd5b61014e6101493660046127c2565b610590565b005b61026960408051608081018252600080825260208201819052918101829052606081019190915260405180608001604052807f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681526020017f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16815250905090565b6040516102769190612885565b60405180910390f35b6102bb6040518060400160405280601081526020017f4f6e52616d7020312e362e302d6465760000000000000000000000000000000081525081565b604051610276919061294a565b6102db6102d6366004612975565b6105a4565b604051908152602001610276565b61014e6102f73660046129e3565b61075d565b61014e61030a366004612a7b565b61076e565b61014e610a8a565b61032a610325366004612af0565b610cb5565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610276565b6103b261035d366004612b29565b67ffffffffffffffff9081166000908152600660205260409020549081169168010000000000000000820460ff16916901000000000000000000900473ffffffffffffffffffffffffffffffffffffffff1690565b6040805167ffffffffffffffff9094168452911515602084015273ffffffffffffffffffffffffffffffffffffffff1690820152606001610276565b61048b6040805160a081018252600080825260208201819052918101829052606081018290526080810191909152506040805160a08101825260025473ffffffffffffffffffffffffffffffffffffffff80821683527401000000000000000000000000000000000000000090910460ff161515602083015260035481169282019290925260045482166060820152600554909116608082015290565b6040516102769190612b46565b61014e610d6a565b60005473ffffffffffffffffffffffffffffffffffffffff1661032a565b6104d16104cc366004612b29565b610e67565b60405167ffffffffffffffff9091168152602001610276565b6104fd6104f8366004612b29565b610e90565b6040516102769190612b9f565b61032a610518366004612b29565b67ffffffffffffffff166000908152600660205260409020546901000000000000000000900473ffffffffffffffffffffffffffffffffffffffff1690565b6102db610565366004612bf9565b610eb8565b61014e610578366004612c65565b6117bc565b6104fd61058b366004612b29565b6117cd565b610598611801565b6105a181611884565b50565b6040517f2cbc26bb00000000000000000000000000000000000000000000000000000000815277ffffffffffffffff00000000000000000000000000000000608084901b16600482015260009073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690632cbc26bb90602401602060405180830381865afa15801561064f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106739190612c82565b156106bb576040517ffdbd6a7200000000000000000000000000000000000000000000000000000000815267ffffffffffffffff841660048201526024015b60405180910390fd5b6002546040517fd8694ccd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091169063d8694ccd906107139086908690600401612db3565b602060405180830381865afa158015610730573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107549190612efc565b90505b92915050565b610765611801565b6105a1816119fb565b60005473ffffffffffffffffffffffffffffffffffffffff1633146107de5760055473ffffffffffffffffffffffffffffffffffffffff1633146107de576040517f905d7d9b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b81811015610a855760008383838181106107fd576107fd612f15565b905060200281019061080f9190612f44565b61081890612ff5565b805167ffffffffffffffff1660009081526006602090815260409182902090830151815490151568010000000000000000027fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff909116178155908201515191925090156109d8578160200151156109975760005b826040015151811015610947576000836040015182815181106108b1576108b1612f15565b60200260200101519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036109305783516040517f463258ff00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016106b2565b61093d6001840182611c2b565b505060010161088c565b50816000015167ffffffffffffffff167f330939f6eafe8bb516716892fe962ff19770570838686e6579dbc1cc51fc3281836040015160405161098a9190612b9f565b60405180910390a26109d8565b81516040517f463258ff00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff90911660048201526024016106b2565b60005b826060015151811015610a2457610a1b83606001518281518110610a0157610a01612f15565b602002602001015183600101611c4d90919063ffffffff16565b506001016109db565b5060608201515115610a7b57816000015167ffffffffffffffff167fc237ec1921f855ccd5e9a5af9733f2d58943a5a8501ec5988e305d7a4d4215868360600151604051610a729190612b9f565b60405180910390a25b50506001016107e1565b505050565b600254604080517fcdc73d51000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163cdc73d5191600480830192869291908290030181865afa158015610af9573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052610b3f91908101906130a6565b60045490915073ffffffffffffffffffffffffffffffffffffffff1660005b8251811015610a85576000838281518110610b7b57610b7b612f15565b60209081029190910101516040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915060009073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa158015610bf6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c1a9190612efc565b90508015610cab57610c4373ffffffffffffffffffffffffffffffffffffffff83168583611c6f565b8173ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f508d7d183612c18fc339b42618912b9fa3239f631dd7ec0671f950200a0fa66e83604051610ca291815260200190565b60405180910390a35b5050600101610b5e565b6040517fbbe4f6db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063bbe4f6db90602401602060405180830381865afa158015610d46573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107549190613135565b60015473ffffffffffffffffffffffffffffffffffffffff163314610deb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064016106b2565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b67ffffffffffffffff808216600090815260066020526040812054909161075791166001613181565b67ffffffffffffffff8116600090815260066020526040902060609061075790600101611cfc565b60025460009074010000000000000000000000000000000000000000900460ff1615610f10576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905567ffffffffffffffff8516600090815260066020526040902073ffffffffffffffffffffffffffffffffffffffff8316610fb5576040517fa4ec747900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805468010000000000000000900460ff161561102657610fd86001820184611d10565b611026576040517fd0d2597600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841660048201526024016106b2565b80546901000000000000000000900473ffffffffffffffffffffffffffffffffffffffff163314611083576040517f1c0a352900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60035473ffffffffffffffffffffffffffffffffffffffff168015611129576040517fe0a0e50600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82169063e0a0e506906110f6908a908a90600401612db3565b600060405180830381600087803b15801561111057600080fd5b505af1158015611124573d6000803e3d6000fd5b505050505b50604080516101c081019091526000610120820181815267ffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811661014085015289811661016085015284549293928392916101808401918791879161119791166131a2565b91906101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905567ffffffffffffffff168152602001600067ffffffffffffffff1681525081526020018573ffffffffffffffffffffffffffffffffffffffff16815260200187806020019061120b91906131c9565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050509082525060200161124f88806131c9565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920182905250938552505060408051602081810183529381529284019290925250016112ab6080890160608a01612c65565b73ffffffffffffffffffffffffffffffffffffffff168152602001868152602001600081526020018780604001906112e3919061322e565b905067ffffffffffffffff8111156112fd576112fd6126bf565b60405190808252806020026020018201604052801561137657816020015b6113636040518060a00160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001606081526020016060815260200160008152602001606081525090565b81526020019060019003908161131b5790505b5090529050600061138a604088018861322e565b808060200260200160405190810160405280939291908181526020016000905b828210156113d6576113c760408302860136819003810190613296565b815260200190600101906113aa565b5050505050905060005b6113ed604089018961322e565b90508110156114875761145d82828151811061140b5761140b612f15565b60209081029190910101518a6114218b806131c9565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508c9250611d3f915050565b836101000151828151811061147457611474612f15565b60209081029190910101526001016113e0565b50600254600090606090819073ffffffffffffffffffffffffffffffffffffffff1663430d138c8c6114be60808e018e8601612c65565b8c8e80608001906114cf91906131c9565b8b61010001518b6040518863ffffffff1660e01b81526004016114f897969594939291906133b3565b600060405180830381865afa158015611515573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261155b91908101906134e5565b60e08901939093529094509250905082611636576040517fea458c0c00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff8c16600482015273ffffffffffffffffffffffffffffffffffffffff89811660248301527f0000000000000000000000000000000000000000000000000000000000000000169063ea458c0c906044016020604051808303816000875af115801561160d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061163191906135d8565b611639565b60005b855167ffffffffffffffff909116608091820152850182905260005b856101000151518110156116ab5781818151811061167557611675612f15565b6020026020010151866101000151828151811061169457611694612f15565b602090810291909101015160800152600101611655565b50604080517f130ac867e79e2789f923760a88743d292acdf7002139a588206e2260f73f7321602082015267ffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811692820192909252908c16606082015230608082015261173b90869060a00160405160208183030381529060405280519060200120612056565b85515260405167ffffffffffffffff8c16907f8cd775d4a25bd349439a70817fd110144d6ab229ae1b9f54a1e5777d2041bfed9061177a9088906135f5565b60405180910390a25050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff169055505051519150505b949350505050565b6117c4611801565b6105a1816121a8565b60606040517f9e7177c800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005473ffffffffffffffffffffffffffffffffffffffff163314611882576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016106b2565b565b60005b81518110156119f75760008282815181106118a4576118a4612f15565b6020026020010151905060008383815181106118c2576118c2612f15565b60200260200101516000015190508067ffffffffffffffff16600003611920576040517fc35aa79d00000000000000000000000000000000000000000000000000000000815267ffffffffffffffff821660048201526024016106b2565b67ffffffffffffffff8181166000818152600660209081526040918290208682015181547fffffff0000000000000000000000000000000000000000ffffffffffffffffff8116690100000000000000000073ffffffffffffffffffffffffffffffffffffffff909316928302908117808555865192891691909816178152928301526801000000000000000090940460ff161515918101919091527fd5ad72bc37dc7a80a8b9b9df20500046fd7341adb1be2258a540466fdd7dcef59060600160405180910390a2505050806001019050611887565b5050565b805173ffffffffffffffffffffffffffffffffffffffff161580611a375750606081015173ffffffffffffffffffffffffffffffffffffffff16155b80611a43575080602001515b15611a7a576040517f35be3ac800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805160028054602080850151151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00000000000000000000000000000000000000000090921673ffffffffffffffffffffffffffffffffffffffff9485161791909117909155604080840151600380549185167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316179055606080860151600480549187169184169190911790556080808701516005805491881691909416179092558251918201835267ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001682527f00000000000000000000000000000000000000000000000000000000000000008516938201939093527f00000000000000000000000000000000000000000000000000000000000000008416818301527f000000000000000000000000000000000000000000000000000000000000000090931691830191909152517fc7372d2d886367d7bb1b0e0708a5436f2c91d6963de210eb2dc1ec2ecd6d21f191611c2091849061374d565b60405180910390a150565b60006107548373ffffffffffffffffffffffffffffffffffffffff841661229d565b60006107548373ffffffffffffffffffffffffffffffffffffffff84166122ec565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052610a859084906123e6565b60606000611d09836124f2565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515610754565b611d876040518060a00160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001606081526020016060815260200160008152602001606081525090565b8460200151600003611dc5576040517f5cf0444900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611dd5858760000151610cb5565b905073ffffffffffffffffffffffffffffffffffffffff81161580611ea557506040517f01ffc9a70000000000000000000000000000000000000000000000000000000081527faff2afbf00000000000000000000000000000000000000000000000000000000600482015273ffffffffffffffffffffffffffffffffffffffff8216906301ffc9a790602401602060405180830381865afa158015611e7f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ea39190612c82565b155b15611ef75785516040517fbf16aab600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff90911660048201526024016106b2565b60008173ffffffffffffffffffffffffffffffffffffffff16639a4575b96040518060a001604052808881526020018967ffffffffffffffff1681526020018773ffffffffffffffffffffffffffffffffffffffff1681526020018a6020015181526020018a6000015173ffffffffffffffffffffffffffffffffffffffff168152506040518263ffffffff1660e01b8152600401611f9691906137fb565b6000604051808303816000875af1158015611fb5573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052611ffb9190810190613871565b6040805160a08101825273ffffffffffffffffffffffffffffffffffffffff90941684528151602080860191909152918201518482015288820151606085015280519182019052600081526080830152509050949350505050565b60008060001b8284602001518560000151606001518660000151608001518760a001518860c001516040516020016120d495949392919073ffffffffffffffffffffffffffffffffffffffff958616815267ffffffffffffffff94851660208201529290931660408301529092166060830152608082015260a00190565b604051602081830303815290604052805190602001208560600151805190602001208660400151805190602001208761010001516040516020016121189190613902565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201206080808d0151805190840120928501999099529183019690965260608201949094529485019190915260a084015260c083015260e08201526101000160405160208183030381529060405280519060200120905092915050565b3373ffffffffffffffffffffffffffffffffffffffff821603612227576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016106b2565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60008181526001830160205260408120546122e457508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610757565b506000610757565b600081815260018301602052604081205480156123d5576000612310600183613915565b855490915060009061232490600190613915565b905080821461238957600086600001828154811061234457612344612f15565b906000526020600020015490508087600001848154811061236757612367612f15565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061239a5761239a613928565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610757565b6000915050610757565b5092915050565b6000612448826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff1661254e9092919063ffffffff16565b805190915015610a8557808060200190518101906124669190612c82565b610a85576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016106b2565b60608160000180548060200260200160405190810160405280929190818152602001828054801561254257602002820191906000526020600020905b81548152602001906001019080831161252e575b50505050509050919050565b60606117b48484600085856000808673ffffffffffffffffffffffffffffffffffffffff1685876040516125829190613957565b60006040518083038185875af1925050503d80600081146125bf576040519150601f19603f3d011682016040523d82523d6000602084013e6125c4565b606091505b50915091506125d5878383876125e0565b979650505050505050565b6060831561267657825160000361266f5773ffffffffffffffffffffffffffffffffffffffff85163b61266f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016106b2565b50816117b4565b6117b4838381511561268b5781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106b2919061294a565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715612711576127116126bf565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561275e5761275e6126bf565b604052919050565b600067ffffffffffffffff821115612780576127806126bf565b5060051b60200190565b67ffffffffffffffff811681146105a157600080fd5b73ffffffffffffffffffffffffffffffffffffffff811681146105a157600080fd5b600060208083850312156127d557600080fd5b823567ffffffffffffffff8111156127ec57600080fd5b8301601f810185136127fd57600080fd5b803561281061280b82612766565b612717565b81815260069190911b8201830190838101908783111561282f57600080fd5b928401925b828410156125d5576040848903121561284d5760008081fd5b6128556126ee565b84356128608161278a565b81528486013561286f816127a0565b8187015282526040939093019290840190612834565b60808101610757828467ffffffffffffffff8151168252602081015173ffffffffffffffffffffffffffffffffffffffff808216602085015280604084015116604085015280606084015116606085015250505050565b60005b838110156128f75781810151838201526020016128df565b50506000910152565b600081518084526129188160208601602086016128dc565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006107546020830184612900565b600060a0828403121561296f57600080fd5b50919050565b6000806040838503121561298857600080fd5b82356129938161278a565b9150602083013567ffffffffffffffff8111156129af57600080fd5b6129bb8582860161295d565b9150509250929050565b80356129d0816127a0565b919050565b80151581146105a157600080fd5b600060a082840312156129f557600080fd5b60405160a0810181811067ffffffffffffffff82111715612a1857612a186126bf565b6040528235612a26816127a0565b81526020830135612a36816129d5565b60208201526040830135612a49816127a0565b60408201526060830135612a5c816127a0565b60608201526080830135612a6f816127a0565b60808201529392505050565b60008060208385031215612a8e57600080fd5b823567ffffffffffffffff80821115612aa657600080fd5b818501915085601f830112612aba57600080fd5b813581811115612ac957600080fd5b8660208260051b8501011115612ade57600080fd5b60209290920196919550909350505050565b60008060408385031215612b0357600080fd5b8235612b0e8161278a565b91506020830135612b1e816127a0565b809150509250929050565b600060208284031215612b3b57600080fd5b8135611d098161278a565b60a08101610757828473ffffffffffffffffffffffffffffffffffffffff808251168352602082015115156020840152806040830151166040840152806060830151166060840152806080830151166080840152505050565b6020808252825182820181905260009190848201906040850190845b81811015612bed57835173ffffffffffffffffffffffffffffffffffffffff1683529284019291840191600101612bbb565b50909695505050505050565b60008060008060808587031215612c0f57600080fd5b8435612c1a8161278a565b9350602085013567ffffffffffffffff811115612c3657600080fd5b612c428782880161295d565b935050604085013591506060850135612c5a816127a0565b939692955090935050565b600060208284031215612c7757600080fd5b8135611d09816127a0565b600060208284031215612c9457600080fd5b8151611d09816129d5565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112612cd457600080fd5b830160208101925035905067ffffffffffffffff811115612cf457600080fd5b803603821315612d0357600080fd5b9250929050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b8183526000602080850194508260005b85811015612da8578135612d76816127a0565b73ffffffffffffffffffffffffffffffffffffffff168752818301358388015260409687019690910190600101612d63565b509495945050505050565b600067ffffffffffffffff808516835260406020840152612dd48485612c9f565b60a06040860152612de960e086018284612d0a565b915050612df96020860186612c9f565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc080878503016060880152612e2f848385612d0a565b9350604088013592507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1883603018312612e6857600080fd5b60209288019283019235915084821115612e8157600080fd5b8160061b3603831315612e9357600080fd5b80878503016080880152612ea8848385612d53565b9450612eb6606089016129c5565b73ffffffffffffffffffffffffffffffffffffffff811660a08901529350612ee16080890189612c9f565b94509250808786030160c088015250506125d5838383612d0a565b600060208284031215612f0e57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81833603018112612f7857600080fd5b9190910192915050565b600082601f830112612f9357600080fd5b81356020612fa361280b83612766565b8083825260208201915060208460051b870101935086841115612fc557600080fd5b602086015b84811015612fea578035612fdd816127a0565b8352918301918301612fca565b509695505050505050565b60006080823603121561300757600080fd5b6040516080810167ffffffffffffffff828210818311171561302b5761302b6126bf565b816040528435915061303c8261278a565b90825260208401359061304e826129d5565b816020840152604085013591508082111561306857600080fd5b61307436838701612f82565b6040840152606085013591508082111561308d57600080fd5b5061309a36828601612f82565b60608301525092915050565b600060208083850312156130b957600080fd5b825167ffffffffffffffff8111156130d057600080fd5b8301601f810185136130e157600080fd5b80516130ef61280b82612766565b81815260059190911b8201830190838101908783111561310e57600080fd5b928401925b828410156125d5578351613126816127a0565b82529284019290840190613113565b60006020828403121561314757600080fd5b8151611d09816127a0565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b67ffffffffffffffff8181168382160190808211156123df576123df613152565b600067ffffffffffffffff8083168181036131bf576131bf613152565b6001019392505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126131fe57600080fd5b83018035915067ffffffffffffffff82111561321957600080fd5b602001915036819003821315612d0357600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261326357600080fd5b83018035915067ffffffffffffffff82111561327e57600080fd5b6020019150600681901b3603821315612d0357600080fd5b6000604082840312156132a857600080fd5b6132b06126ee565b82356132bb816127a0565b81526020928301359281019290925250919050565b600082825180855260208086019550808260051b84010181860160005b848110156133a6577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0868403018952815160a073ffffffffffffffffffffffffffffffffffffffff825116855285820151818787015261334f82870182612900565b915050604080830151868303828801526133698382612900565b925050506060808301518187015250608080830151925085820381870152506133928183612900565b9a86019a94505050908301906001016132ed565b5090979650505050505050565b67ffffffffffffffff881681526000602073ffffffffffffffffffffffffffffffffffffffff808a1682850152604089604086015260c060608601526133fd60c08601898b612d0a565b858103608087015261340f81896132d0565b86810360a0880152875180825285890192509085019060005b8181101561344f578351805187168452870151878401529286019291840191600101613428565b50909e9d5050505050505050505050505050565b600082601f83011261347457600080fd5b815167ffffffffffffffff81111561348e5761348e6126bf565b6134bf60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601612717565b8181528460208386010111156134d457600080fd5b6117b48260208301602087016128dc565b600080600080608085870312156134fb57600080fd5b8451935060208086015161350e816129d5565b604087015190945067ffffffffffffffff8082111561352c57600080fd5b61353889838a01613463565b9450606088015191508082111561354e57600080fd5b818801915088601f83011261356257600080fd5b815161357061280b82612766565b81815260059190911b8301840190848101908b83111561358f57600080fd5b8585015b838110156135c7578051858111156135ab5760008081fd5b6135b98e89838a0101613463565b845250918601918601613593565b50989b979a50959850505050505050565b6000602082840312156135ea57600080fd5b8151611d098161278a565b6020815261364660208201835180518252602081015167ffffffffffffffff808216602085015280604084015116604085015280606084015116606085015280608084015116608085015250505050565b6000602083015161366f60c084018273ffffffffffffffffffffffffffffffffffffffff169052565b5060408301516101a08060e085015261368c6101c0850183612900565b915060608501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06101008187860301818801526136ca8584612900565b94506080880151925081878603016101208801526136e88584612900565b945060a0880151925061371461014088018473ffffffffffffffffffffffffffffffffffffffff169052565b60c088015161016088015260e088015161018088015287015186850390910183870152905061374383826132d0565b9695505050505050565b61012081016137a5828567ffffffffffffffff8151168252602081015173ffffffffffffffffffffffffffffffffffffffff808216602085015280604084015116604085015280606084015116606085015250505050565b825173ffffffffffffffffffffffffffffffffffffffff9081166080848101919091526020850151151560a08501526040850151821660c08501526060850151821660e085015284015116610100830152611d09565b602081526000825160a0602084015261381760c0840182612900565b905067ffffffffffffffff6020850151166040840152604084015173ffffffffffffffffffffffffffffffffffffffff8082166060860152606086015160808601528060808701511660a086015250508091505092915050565b60006020828403121561388357600080fd5b815167ffffffffffffffff8082111561389b57600080fd5b90830190604082860312156138af57600080fd5b6138b76126ee565b8251828111156138c657600080fd5b6138d287828601613463565b8252506020830151828111156138e757600080fd5b6138f387828601613463565b60208301525095945050505050565b60208152600061075460208301846132d0565b8181038181111561075757610757613152565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b60008251612f788184602087016128dc56fea164736f6c6343000818000a", } var OnRampABI = OnRampMetaData.ABI @@ -1332,134 +1333,6 @@ func (_OnRamp *OnRampFilterer) ParseDestChainConfigSet(log types.Log) (*OnRampDe return event, nil } -type OnRampFeePaidIterator struct { - Event *OnRampFeePaid - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *OnRampFeePaidIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(OnRampFeePaid) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - - select { - case log := <-it.logs: - it.Event = new(OnRampFeePaid) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -func (it *OnRampFeePaidIterator) Error() error { - return it.fail -} - -func (it *OnRampFeePaidIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type OnRampFeePaid struct { - FeeToken common.Address - FeeValueJuels *big.Int - Raw types.Log -} - -func (_OnRamp *OnRampFilterer) FilterFeePaid(opts *bind.FilterOpts, feeToken []common.Address) (*OnRampFeePaidIterator, error) { - - var feeTokenRule []interface{} - for _, feeTokenItem := range feeToken { - feeTokenRule = append(feeTokenRule, feeTokenItem) - } - - logs, sub, err := _OnRamp.contract.FilterLogs(opts, "FeePaid", feeTokenRule) - if err != nil { - return nil, err - } - return &OnRampFeePaidIterator{contract: _OnRamp.contract, event: "FeePaid", logs: logs, sub: sub}, nil -} - -func (_OnRamp *OnRampFilterer) WatchFeePaid(opts *bind.WatchOpts, sink chan<- *OnRampFeePaid, feeToken []common.Address) (event.Subscription, error) { - - var feeTokenRule []interface{} - for _, feeTokenItem := range feeToken { - feeTokenRule = append(feeTokenRule, feeTokenItem) - } - - logs, sub, err := _OnRamp.contract.WatchLogs(opts, "FeePaid", feeTokenRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(OnRampFeePaid) - if err := _OnRamp.contract.UnpackLog(event, "FeePaid", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -func (_OnRamp *OnRampFilterer) ParseFeePaid(log types.Log) (*OnRampFeePaid, error) { - event := new(OnRampFeePaid) - if err := _OnRamp.contract.UnpackLog(event, "FeePaid", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - type OnRampFeeTokenWithdrawnIterator struct { Event *OnRampFeeTokenWithdrawn @@ -1889,8 +1762,6 @@ func (_OnRamp *OnRamp) ParseLog(log types.Log) (generated.AbigenLog, error) { return _OnRamp.ParseConfigSet(log) case _OnRamp.abi.Events["DestChainConfigSet"].ID: return _OnRamp.ParseDestChainConfigSet(log) - case _OnRamp.abi.Events["FeePaid"].ID: - return _OnRamp.ParseFeePaid(log) case _OnRamp.abi.Events["FeeTokenWithdrawn"].ID: return _OnRamp.ParseFeeTokenWithdrawn(log) case _OnRamp.abi.Events["OwnershipTransferRequested"].ID: @@ -1916,7 +1787,7 @@ func (OnRampAllowListSendersRemoved) Topic() common.Hash { } func (OnRampCCIPMessageSent) Topic() common.Hash { - return common.HexToHash("0x9f4bd3af5ec85ce7c750c95aca08cf5460a4a3f952cf1db9c2bbf22cdfe78bbf") + return common.HexToHash("0x8cd775d4a25bd349439a70817fd110144d6ab229ae1b9f54a1e5777d2041bfed") } func (OnRampConfigSet) Topic() common.Hash { @@ -1927,10 +1798,6 @@ func (OnRampDestChainConfigSet) Topic() common.Hash { return common.HexToHash("0xd5ad72bc37dc7a80a8b9b9df20500046fd7341adb1be2258a540466fdd7dcef5") } -func (OnRampFeePaid) Topic() common.Hash { - return common.HexToHash("0x075a2720282fdf622141dae0b048ef90a21a7e57c134c76912d19d006b3b3f6f") -} - func (OnRampFeeTokenWithdrawn) Topic() common.Hash { return common.HexToHash("0x508d7d183612c18fc339b42618912b9fa3239f631dd7ec0671f950200a0fa66e") } @@ -2022,12 +1889,6 @@ type OnRampInterface interface { ParseDestChainConfigSet(log types.Log) (*OnRampDestChainConfigSet, error) - FilterFeePaid(opts *bind.FilterOpts, feeToken []common.Address) (*OnRampFeePaidIterator, error) - - WatchFeePaid(opts *bind.WatchOpts, sink chan<- *OnRampFeePaid, feeToken []common.Address) (event.Subscription, error) - - ParseFeePaid(log types.Log) (*OnRampFeePaid, error) - FilterFeeTokenWithdrawn(opts *bind.FilterOpts, feeAggregator []common.Address, feeToken []common.Address) (*OnRampFeeTokenWithdrawnIterator, error) WatchFeeTokenWithdrawn(opts *bind.WatchOpts, sink chan<- *OnRampFeeTokenWithdrawn, feeAggregator []common.Address, feeToken []common.Address) (event.Subscription, error) diff --git a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt index 4a2054edf2..fca33c5443 100644 --- a/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/ccip/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -6,7 +6,7 @@ burn_with_from_mint_token_pool: ../../../contracts/solc/v0.8.24/BurnWithFromMint burn_with_from_mint_token_pool_and_proxy: ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPoolAndProxy/BurnWithFromMintTokenPoolAndProxy.abi ../../../contracts/solc/v0.8.24/BurnWithFromMintTokenPoolAndProxy/BurnWithFromMintTokenPoolAndProxy.bin 08ed1235dda921ce8841b26aa18d0c0f36db4884779dd7670857159801b6d597 ccip_config: ../../../contracts/solc/v0.8.24/CCIPConfig/CCIPConfig.abi ../../../contracts/solc/v0.8.24/CCIPConfig/CCIPConfig.bin f67d4a98804a9534a6554da3a57779632d55ad76db5ecc16ade74774769cdd69 ccip_encoding_utils: ../../../contracts/solc/v0.8.24/CCIPEncodingUtils/CCIPEncodingUtils.abi ../../../contracts/solc/v0.8.24/CCIPEncodingUtils/CCIPEncodingUtils.bin ebabd5311ad4374df0f2f5cd5640bb58d938d92f5a82962ac4df7b6e5af2c197 -ccip_reader_tester: ../../../contracts/solc/v0.8.24/CCIPReaderTester/CCIPReaderTester.abi ../../../contracts/solc/v0.8.24/CCIPReaderTester/CCIPReaderTester.bin 1181c7150062d6f0793beb50cb6b984c7f7adef0b9528ef1b419923fffcfdcac +ccip_reader_tester: ../../../contracts/solc/v0.8.24/CCIPReaderTester/CCIPReaderTester.abi ../../../contracts/solc/v0.8.24/CCIPReaderTester/CCIPReaderTester.bin 32916b41e0070cb6853d558bbff06ab367324fa52cac59893065e8f616ff14f0 commit_store: ../../../contracts/solc/v0.8.24/CommitStore/CommitStore.abi ../../../contracts/solc/v0.8.24/CommitStore/CommitStore.bin 274d87db70b643e00ab0a7e7845bb4b791f3b613bfc87708d33fc5a8369e2a41 commit_store_helper: ../../../contracts/solc/v0.8.24/CommitStoreHelper/CommitStoreHelper.abi ../../../contracts/solc/v0.8.24/CommitStoreHelper/CommitStoreHelper.bin f7128dcc2ee6dbcbc976288abcc16970ffb19b59412c5202ef6b259d2007f801 ether_sender_receiver: ../../../contracts/solc/v0.8.24/EtherSenderReceiver/EtherSenderReceiver.abi ../../../contracts/solc/v0.8.24/EtherSenderReceiver/EtherSenderReceiver.bin 09510a3f773f108a3c231e8d202835c845ded862d071ec54c4f89c12d868b8de @@ -25,7 +25,7 @@ multi_ocr3_helper: ../../../contracts/solc/v0.8.24/MultiOCR3Helper/MultiOCR3Help nonce_manager: ../../../contracts/solc/v0.8.24/NonceManager/NonceManager.abi ../../../contracts/solc/v0.8.24/NonceManager/NonceManager.bin 6f64e1083b356c06ee66b9138e398b9c97a4cd3e8c9ec38cf3010cebc79af536 ocr3_config_encoder: ../../../contracts/solc/v0.8.24/IOCR3ConfigEncoder/IOCR3ConfigEncoder.abi ../../../contracts/solc/v0.8.24/IOCR3ConfigEncoder/IOCR3ConfigEncoder.bin d507c3ac70a7d1033b75151c1e5b854b41aaee164dfaa3e5477de400db1aa1f7 offramp: ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.abi ../../../contracts/solc/v0.8.24/OffRamp/OffRamp.bin 941b18b4e2aef977195fefba514e17c9475667e6f8513b18cabfb07ff90136ce -onramp: ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.abi ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.bin 1f31a62ebb3fa5f4702ee27d4fa86604de5afff56787ef67c8dac764eefd2956 +onramp: ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.abi ../../../contracts/solc/v0.8.24/OnRamp/OnRamp.bin 4f29f05261bdaf9b99e675c1169c0d5cba841b6dd7ca3a8997cc0d3cae7ba850 ping_pong_demo: ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.abi ../../../contracts/solc/v0.8.24/PingPongDemo/PingPongDemo.bin c1c2f8a65c7ffd971899cae7fe62f2da57d09e936151e2b92163c4bebe699d6b price_registry: ../../../contracts/solc/v0.8.24/PriceRegistry/PriceRegistry.abi ../../../contracts/solc/v0.8.24/PriceRegistry/PriceRegistry.bin e7781d600c1bb7aa4620106af7f6e146a109b97f4cb6a7d06c9e15773340ecb2 registry_module_owner_custom: ../../../contracts/solc/v0.8.24/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.abi ../../../contracts/solc/v0.8.24/RegistryModuleOwnerCustom/RegistryModuleOwnerCustom.bin 75be86323c227917a9bbc3f799d7ed02f92db546653a36db30ed0ebe64461353 From ebc7094c3e722e693ee7dc59f445b65887fbd5be Mon Sep 17 00:00:00 2001 From: Valerii Kabisov <172247313+valerii-kabisov-cll@users.noreply.github.com> Date: Wed, 25 Sep 2024 00:31:37 +0900 Subject: [PATCH 115/115] =?UTF-8?q?[CCIP-3376]=20Add=20component=20into=20?= =?UTF-8?q?CCIP=20price=20estimators=20to=20account=20for=20c=E2=80=A6=20(?= =?UTF-8?q?#1446)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [https://smartcontract-it.atlassian.net/browse/CCIP-3376](https://smartcontract-it.atlassian.net/browse/CCIP-3376) The CCIP gas limit is set by customers. This cannot be changed because this limit is directly used within the contracts (which expect limits in terms of ETH). Also, the L2 gas price returned from our current estimators for Mantle is in MNT. Therefore, the final formula needed for CCIP to calculate L2 transaction fees is the following: gasLimit_EVM * (gasPrice_Mantle * TokenRatio) Therefore, we need to multiply the gas price returned from our gas estimators by tokenRatio for CCIP. This should happen in the CCIP price estimator. Currently, we have no component here for chain-specific logic, so we will need to add this functionality. --------- Co-authored-by: Matt Yang <matt.yang@smartcontract.com> --- .mockery.yaml | 7 +- .../plugins/ccip/estimatorconfig/config.go | 37 +++++- .../ccip/estimatorconfig/config_test.go | 64 +++++++++++ .../interceptors/mantle/interceptor.go | 80 +++++++++++++ .../interceptors/mantle/interceptor_test.go | 96 ++++++++++++++++ .../mocks/gas_price_interceptor_mock.go | 106 ++++++++++++++++++ .../ccipdata/commit_store_reader_test.go | 11 +- .../internal/ccipdata/fee_estimator_config.go | 2 + .../mocks/fee_estimator_config_mock.go | 71 ++++++++++++ .../plugins/ccip/prices/da_price_estimator.go | 10 +- .../ccip/prices/da_price_estimator_test.go | 52 ++++++++- core/services/relay/evm/evm.go | 22 ++++ .../evm/interceptors/mantle/interceptor.go | 80 +++++++++++++ .../interceptors/mantle/interceptor_test.go | 96 ++++++++++++++++ 14 files changed, 725 insertions(+), 9 deletions(-) create mode 100644 core/services/ocr2/plugins/ccip/estimatorconfig/interceptors/mantle/interceptor.go create mode 100644 core/services/ocr2/plugins/ccip/estimatorconfig/interceptors/mantle/interceptor_test.go create mode 100644 core/services/ocr2/plugins/ccip/estimatorconfig/mocks/gas_price_interceptor_mock.go create mode 100644 core/services/relay/evm/interceptors/mantle/interceptor.go create mode 100644 core/services/relay/evm/interceptors/mantle/interceptor_test.go diff --git a/.mockery.yaml b/.mockery.yaml index fa36213ff7..cfe202ac59 100644 --- a/.mockery.yaml +++ b/.mockery.yaml @@ -467,7 +467,7 @@ packages: filename: optimism_portal2_interface.go outpkg: mock_optimism_portal_2 interfaces: - OptimismPortal2Interface: + OptimismPortal2Interface: github.com/smartcontractkit/chainlink/v2/core/gethwrappers/liquiditymanager/generated/optimism_dispute_game_factory: config: dir: core/gethwrappers/liquiditymanager/mocks/mock_optimism_dispute_game_factory/ @@ -503,6 +503,11 @@ packages: USDCReader: config: filename: usdc_reader_mock.go + github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/estimatorconfig: + interfaces: + GasPriceInterceptor: + config: + filename: gas_price_interceptor_mock.go github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/batchreader: config: filename: token_pool_batched_reader_mock.go diff --git a/core/services/ocr2/plugins/ccip/estimatorconfig/config.go b/core/services/ocr2/plugins/ccip/estimatorconfig/config.go index 2eda88d441..0e66f4fb39 100644 --- a/core/services/ocr2/plugins/ccip/estimatorconfig/config.go +++ b/core/services/ocr2/plugins/ccip/estimatorconfig/config.go @@ -3,6 +3,7 @@ package estimatorconfig import ( "context" "errors" + "math/big" "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" ) @@ -13,11 +14,18 @@ import ( // fields for the daGasEstimator from the encapsulated onRampReader. type FeeEstimatorConfigProvider interface { SetOnRampReader(reader ccip.OnRampReader) + AddGasPriceInterceptor(GasPriceInterceptor) + ModifyGasPriceComponents(ctx context.Context, execGasPrice, daGasPrice *big.Int) (modExecGasPrice, modDAGasPrice *big.Int, err error) GetDataAvailabilityConfig(ctx context.Context) (destDataAvailabilityOverheadGas, destGasPerDataAvailabilityByte, destDataAvailabilityMultiplierBps int64, err error) } +type GasPriceInterceptor interface { + ModifyGasPriceComponents(ctx context.Context, execGasPrice, daGasPrice *big.Int) (modExecGasPrice, modDAGasPrice *big.Int, err error) +} + type FeeEstimatorConfigService struct { - onRampReader ccip.OnRampReader + onRampReader ccip.OnRampReader + gasPriceInterceptors []GasPriceInterceptor } func NewFeeEstimatorConfigService() *FeeEstimatorConfigService { @@ -47,3 +55,30 @@ func (c *FeeEstimatorConfigService) GetDataAvailabilityConfig(ctx context.Contex int64(cfg.DestDataAvailabilityMultiplierBps), err } + +// AddGasPriceInterceptor adds price interceptors that can modify gas price. +func (c *FeeEstimatorConfigService) AddGasPriceInterceptor(gpi GasPriceInterceptor) { + if gpi != nil { + c.gasPriceInterceptors = append(c.gasPriceInterceptors, gpi) + } +} + +// ModifyGasPriceComponents applies gasPrice interceptors and returns modified gasPrice. +func (c *FeeEstimatorConfigService) ModifyGasPriceComponents(ctx context.Context, gasPrice, daGasPrice *big.Int) (*big.Int, *big.Int, error) { + if len(c.gasPriceInterceptors) == 0 { + return gasPrice, daGasPrice, nil + } + + // values are mutable, it is necessary to copy the values to protect the arguments from modification. + cpGasPrice := new(big.Int).Set(gasPrice) + cpDAGasPrice := new(big.Int).Set(daGasPrice) + + var err error + for _, interceptor := range c.gasPriceInterceptors { + if cpGasPrice, cpDAGasPrice, err = interceptor.ModifyGasPriceComponents(ctx, cpGasPrice, cpDAGasPrice); err != nil { + return nil, nil, err + } + } + + return cpGasPrice, cpDAGasPrice, nil +} diff --git a/core/services/ocr2/plugins/ccip/estimatorconfig/config_test.go b/core/services/ocr2/plugins/ccip/estimatorconfig/config_test.go index 05226f8b48..0ed7510591 100644 --- a/core/services/ocr2/plugins/ccip/estimatorconfig/config_test.go +++ b/core/services/ocr2/plugins/ccip/estimatorconfig/config_test.go @@ -3,10 +3,13 @@ package estimatorconfig_test import ( "context" "errors" + "math/big" "testing" "github.com/stretchr/testify/require" + mocks2 "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/estimatorconfig/mocks" + "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/estimatorconfig" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/internal/ccipdata/mocks" @@ -43,3 +46,64 @@ func TestFeeEstimatorConfigService(t *testing.T) { _, _, _, err = svc.GetDataAvailabilityConfig(ctx) require.Error(t, err) } + +func TestModifyGasPriceComponents(t *testing.T) { + t.Run("success modification", func(t *testing.T) { + svc := estimatorconfig.NewFeeEstimatorConfigService() + ctx := context.Background() + + initialExecGasPrice, initialDaGasPrice := big.NewInt(10), big.NewInt(1) + + gpi1 := mocks2.NewGasPriceInterceptor(t) + svc.AddGasPriceInterceptor(gpi1) + + // change in first interceptor + firstModExecGasPrice, firstModDaGasPrice := big.NewInt(5), big.NewInt(2) + gpi1.On("ModifyGasPriceComponents", ctx, initialExecGasPrice, initialDaGasPrice). + Return(firstModExecGasPrice, firstModDaGasPrice, nil) + + gpi2 := mocks2.NewGasPriceInterceptor(t) + svc.AddGasPriceInterceptor(gpi2) + + // change in second iterceptor + secondModExecGasPrice, secondModDaGasPrice := big.NewInt(50), big.NewInt(20) + gpi2.On("ModifyGasPriceComponents", ctx, firstModExecGasPrice, firstModDaGasPrice). + Return(secondModExecGasPrice, secondModDaGasPrice, nil) + + // has to return second interceptor values + resGasPrice, resDAGasPrice, err := svc.ModifyGasPriceComponents(ctx, initialExecGasPrice, initialDaGasPrice) + require.NoError(t, err) + require.Equal(t, secondModExecGasPrice.Int64(), resGasPrice.Int64()) + require.Equal(t, secondModDaGasPrice.Int64(), resDAGasPrice.Int64()) + }) + + t.Run("error modification", func(t *testing.T) { + svc := estimatorconfig.NewFeeEstimatorConfigService() + ctx := context.Background() + + initialExecGasPrice, initialDaGasPrice := big.NewInt(10), big.NewInt(1) + gpi1 := mocks2.NewGasPriceInterceptor(t) + svc.AddGasPriceInterceptor(gpi1) + gpi1.On("ModifyGasPriceComponents", ctx, initialExecGasPrice, initialDaGasPrice). + Return(nil, nil, errors.New("test")) + + // has to return second interceptor values + _, _, err := svc.ModifyGasPriceComponents(ctx, initialExecGasPrice, initialDaGasPrice) + require.Error(t, err) + }) + + t.Run("without interceptors", func(t *testing.T) { + svc := estimatorconfig.NewFeeEstimatorConfigService() + ctx := context.Background() + + initialExecGasPrice, initialDaGasPrice := big.NewInt(10), big.NewInt(1) + + // has to return second interceptor values + resGasPrice, resDAGasPrice, err := svc.ModifyGasPriceComponents(ctx, initialExecGasPrice, initialDaGasPrice) + require.NoError(t, err) + + // values should not be modified + require.Equal(t, initialExecGasPrice, resGasPrice) + require.Equal(t, initialDaGasPrice, resDAGasPrice) + }) +} diff --git a/core/services/ocr2/plugins/ccip/estimatorconfig/interceptors/mantle/interceptor.go b/core/services/ocr2/plugins/ccip/estimatorconfig/interceptors/mantle/interceptor.go new file mode 100644 index 0000000000..8d5d3bb6c2 --- /dev/null +++ b/core/services/ocr2/plugins/ccip/estimatorconfig/interceptors/mantle/interceptor.go @@ -0,0 +1,80 @@ +package mantle + +import ( + "context" + "fmt" + "math/big" + "strings" + "time" + + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + + evmClient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/rollups" +) + +const ( + // tokenRatio is not volatile and can be requested not often. + tokenRatioUpdateInterval = 60 * time.Minute + // tokenRatio fetches the tokenRatio used for Mantle's gas price calculation + tokenRatioMethod = "tokenRatio" + mantleTokenRatioAbiString = `[{"inputs":[],"name":"tokenRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]` +) + +type Interceptor struct { + client evmClient.Client + tokenRatioCallData []byte + tokenRatio *big.Int + tokenRatioLastUpdate time.Time +} + +func NewInterceptor(_ context.Context, client evmClient.Client) (*Interceptor, error) { + // Encode calldata for tokenRatio method + tokenRatioMethodAbi, err := abi.JSON(strings.NewReader(mantleTokenRatioAbiString)) + if err != nil { + return nil, fmt.Errorf("failed to parse GasPriceOracle %s() method ABI for Mantle; %v", tokenRatioMethod, err) + } + tokenRatioCallData, err := tokenRatioMethodAbi.Pack(tokenRatioMethod) + if err != nil { + return nil, fmt.Errorf("failed to parse GasPriceOracle %s() calldata for Mantle; %v", tokenRatioMethod, err) + } + + return &Interceptor{ + client: client, + tokenRatioCallData: tokenRatioCallData, + }, nil +} + +// ModifyGasPriceComponents returns modified gasPrice. +func (i *Interceptor) ModifyGasPriceComponents(ctx context.Context, execGasPrice, daGasPrice *big.Int) (*big.Int, *big.Int, error) { + if time.Since(i.tokenRatioLastUpdate) > tokenRatioUpdateInterval { + mantleTokenRatio, err := i.getMantleTokenRatio(ctx) + if err != nil { + return nil, nil, err + } + + i.tokenRatio, i.tokenRatioLastUpdate = mantleTokenRatio, time.Now() + } + + // multiply daGasPrice and execGas price by tokenRatio + newExecGasPrice := new(big.Int).Mul(execGasPrice, i.tokenRatio) + newDAGasPrice := new(big.Int).Mul(daGasPrice, i.tokenRatio) + return newExecGasPrice, newDAGasPrice, nil +} + +// getMantleTokenRatio Requests and returns a token ratio value for the Mantle chain. +func (i *Interceptor) getMantleTokenRatio(ctx context.Context) (*big.Int, error) { + precompile := common.HexToAddress(rollups.OPGasOracleAddress) + tokenRatio, err := i.client.CallContract(ctx, ethereum.CallMsg{ + To: &precompile, + Data: i.tokenRatioCallData, + }, nil) + + if err != nil { + return nil, fmt.Errorf("getMantleTokenRatio call failed: %w", err) + } + + return new(big.Int).SetBytes(tokenRatio), nil +} diff --git a/core/services/ocr2/plugins/ccip/estimatorconfig/interceptors/mantle/interceptor_test.go b/core/services/ocr2/plugins/ccip/estimatorconfig/interceptors/mantle/interceptor_test.go new file mode 100644 index 0000000000..9134d996c2 --- /dev/null +++ b/core/services/ocr2/plugins/ccip/estimatorconfig/interceptors/mantle/interceptor_test.go @@ -0,0 +1,96 @@ +package mantle + +import ( + "context" + "math/big" + "testing" + + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks" +) + +func TestInterceptor(t *testing.T) { + ethClient := mocks.NewClient(t) + ctx := context.Background() + + tokenRatio := big.NewInt(10) + interceptor, err := NewInterceptor(ctx, ethClient) + require.NoError(t, err) + + // request token ratio + ethClient.On("CallContract", ctx, mock.IsType(ethereum.CallMsg{}), mock.IsType(&big.Int{})). + Return(common.BigToHash(tokenRatio).Bytes(), nil).Once() + + modExecGasPrice, modDAGasPrice, err := interceptor.ModifyGasPriceComponents(ctx, big.NewInt(1), big.NewInt(1)) + require.NoError(t, err) + require.Equal(t, int64(10), modExecGasPrice.Int64()) + require.Equal(t, int64(10), modDAGasPrice.Int64()) + + // second call won't invoke eth client + modExecGasPrice, modDAGasPrice, err = interceptor.ModifyGasPriceComponents(ctx, big.NewInt(2), big.NewInt(1)) + require.NoError(t, err) + require.Equal(t, int64(20), modExecGasPrice.Int64()) + require.Equal(t, int64(10), modDAGasPrice.Int64()) +} + +func TestModifyGasPriceComponents(t *testing.T) { + testCases := map[string]struct { + execGasPrice *big.Int + daGasPrice *big.Int + tokenRatio *big.Int + resultExecGasPrice *big.Int + resultDAGasPrice *big.Int + }{ + "regular": { + execGasPrice: big.NewInt(1000), + daGasPrice: big.NewInt(100), + resultExecGasPrice: big.NewInt(2000), + resultDAGasPrice: big.NewInt(200), + tokenRatio: big.NewInt(2), + }, + "zero DAGasPrice": { + execGasPrice: big.NewInt(1000), + daGasPrice: big.NewInt(0), + resultExecGasPrice: big.NewInt(5000), + resultDAGasPrice: big.NewInt(0), + tokenRatio: big.NewInt(5), + }, + "zero ExecGasPrice": { + execGasPrice: big.NewInt(0), + daGasPrice: big.NewInt(10), + resultExecGasPrice: big.NewInt(0), + resultDAGasPrice: big.NewInt(50), + tokenRatio: big.NewInt(5), + }, + "zero token ratio": { + execGasPrice: big.NewInt(15), + daGasPrice: big.NewInt(10), + resultExecGasPrice: big.NewInt(0), + resultDAGasPrice: big.NewInt(0), + tokenRatio: big.NewInt(0), + }, + } + + for tcName, tc := range testCases { + t.Run(tcName, func(t *testing.T) { + ethClient := mocks.NewClient(t) + ctx := context.Background() + + interceptor, err := NewInterceptor(ctx, ethClient) + require.NoError(t, err) + + // request token ratio + ethClient.On("CallContract", ctx, mock.IsType(ethereum.CallMsg{}), mock.IsType(&big.Int{})). + Return(common.BigToHash(tc.tokenRatio).Bytes(), nil).Once() + + modExecGasPrice, modDAGasPrice, err := interceptor.ModifyGasPriceComponents(ctx, tc.execGasPrice, tc.daGasPrice) + require.NoError(t, err) + require.Equal(t, tc.resultExecGasPrice.Int64(), modExecGasPrice.Int64()) + require.Equal(t, tc.resultDAGasPrice.Int64(), modDAGasPrice.Int64()) + }) + } +} diff --git a/core/services/ocr2/plugins/ccip/estimatorconfig/mocks/gas_price_interceptor_mock.go b/core/services/ocr2/plugins/ccip/estimatorconfig/mocks/gas_price_interceptor_mock.go new file mode 100644 index 0000000000..62ec5a2207 --- /dev/null +++ b/core/services/ocr2/plugins/ccip/estimatorconfig/mocks/gas_price_interceptor_mock.go @@ -0,0 +1,106 @@ +// Code generated by mockery v2.43.2. DO NOT EDIT. + +package mocks + +import ( + context "context" + big "math/big" + + mock "github.com/stretchr/testify/mock" +) + +// GasPriceInterceptor is an autogenerated mock type for the GasPriceInterceptor type +type GasPriceInterceptor struct { + mock.Mock +} + +type GasPriceInterceptor_Expecter struct { + mock *mock.Mock +} + +func (_m *GasPriceInterceptor) EXPECT() *GasPriceInterceptor_Expecter { + return &GasPriceInterceptor_Expecter{mock: &_m.Mock} +} + +// ModifyGasPriceComponents provides a mock function with given fields: ctx, execGasPrice, daGasPrice +func (_m *GasPriceInterceptor) ModifyGasPriceComponents(ctx context.Context, execGasPrice *big.Int, daGasPrice *big.Int) (*big.Int, *big.Int, error) { + ret := _m.Called(ctx, execGasPrice, daGasPrice) + + if len(ret) == 0 { + panic("no return value specified for ModifyGasPriceComponents") + } + + var r0 *big.Int + var r1 *big.Int + var r2 error + if rf, ok := ret.Get(0).(func(context.Context, *big.Int, *big.Int) (*big.Int, *big.Int, error)); ok { + return rf(ctx, execGasPrice, daGasPrice) + } + if rf, ok := ret.Get(0).(func(context.Context, *big.Int, *big.Int) *big.Int); ok { + r0 = rf(ctx, execGasPrice, daGasPrice) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*big.Int) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *big.Int, *big.Int) *big.Int); ok { + r1 = rf(ctx, execGasPrice, daGasPrice) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*big.Int) + } + } + + if rf, ok := ret.Get(2).(func(context.Context, *big.Int, *big.Int) error); ok { + r2 = rf(ctx, execGasPrice, daGasPrice) + } else { + r2 = ret.Error(2) + } + + return r0, r1, r2 +} + +// GasPriceInterceptor_ModifyGasPriceComponents_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ModifyGasPriceComponents' +type GasPriceInterceptor_ModifyGasPriceComponents_Call struct { + *mock.Call +} + +// ModifyGasPriceComponents is a helper method to define mock.On call +// - ctx context.Context +// - execGasPrice *big.Int +// - daGasPrice *big.Int +func (_e *GasPriceInterceptor_Expecter) ModifyGasPriceComponents(ctx interface{}, execGasPrice interface{}, daGasPrice interface{}) *GasPriceInterceptor_ModifyGasPriceComponents_Call { + return &GasPriceInterceptor_ModifyGasPriceComponents_Call{Call: _e.mock.On("ModifyGasPriceComponents", ctx, execGasPrice, daGasPrice)} +} + +func (_c *GasPriceInterceptor_ModifyGasPriceComponents_Call) Run(run func(ctx context.Context, execGasPrice *big.Int, daGasPrice *big.Int)) *GasPriceInterceptor_ModifyGasPriceComponents_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(*big.Int), args[2].(*big.Int)) + }) + return _c +} + +func (_c *GasPriceInterceptor_ModifyGasPriceComponents_Call) Return(modExecGasPrice *big.Int, modDAGasPrice *big.Int, err error) *GasPriceInterceptor_ModifyGasPriceComponents_Call { + _c.Call.Return(modExecGasPrice, modDAGasPrice, err) + return _c +} + +func (_c *GasPriceInterceptor_ModifyGasPriceComponents_Call) RunAndReturn(run func(context.Context, *big.Int, *big.Int) (*big.Int, *big.Int, error)) *GasPriceInterceptor_ModifyGasPriceComponents_Call { + _c.Call.Return(run) + return _c +} + +// NewGasPriceInterceptor creates a new instance of GasPriceInterceptor. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewGasPriceInterceptor(t interface { + mock.TestingT + Cleanup(func()) +}) *GasPriceInterceptor { + mock := &GasPriceInterceptor{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/commit_store_reader_test.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/commit_store_reader_test.go index e9266c4fb2..81807e66fe 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/commit_store_reader_test.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/commit_store_reader_test.go @@ -194,7 +194,14 @@ func TestCommitStoreReaders(t *testing.T) { ge.On("L1Oracle").Return(lm) feeEstimatorConfig := ccipdatamocks.NewFeeEstimatorConfigReader(t) - + feeEstimatorConfig.On( + "ModifyGasPriceComponents", + mock.AnythingOfType("context.backgroundCtx"), + mock.AnythingOfType("*big.Int"), + mock.AnythingOfType("*big.Int"), + ).Return(func(ctx context.Context, x, y *big.Int) (*big.Int, *big.Int, error) { + return x, y, nil + }) maxGasPrice := big.NewInt(1e8) c10r, err := factory.NewCommitStoreReader(lggr, factory.NewEvmVersionFinder(), ccipcalc.EvmAddrToGeneric(addr), ec, lp, feeEstimatorConfig) // ge, maxGasPrice require.NoError(t, err) @@ -372,8 +379,10 @@ func TestCommitStoreReaders(t *testing.T) { require.NoError(t, err) assert.Equal(t, commonOffchain, c2) // We should be able to query for gas prices now. + gpe, err := cr.GasPriceEstimator(ctx) require.NoError(t, err) + gp, err := gpe.GetGasPrice(context.Background()) require.NoError(t, err) assert.True(t, gp.Cmp(big.NewInt(0)) > 0) diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/fee_estimator_config.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/fee_estimator_config.go index a1a9370528..0b4d1ce75a 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/fee_estimator_config.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/fee_estimator_config.go @@ -2,8 +2,10 @@ package ccipdata import ( "context" + "math/big" ) type FeeEstimatorConfigReader interface { GetDataAvailabilityConfig(ctx context.Context) (destDAOverheadGas, destGasPerDAByte, destDAMultiplierBps int64, err error) + ModifyGasPriceComponents(ctx context.Context, execGasPrice, daGasPrice *big.Int) (modExecGasPrice, modDAGasPrice *big.Int, err error) } diff --git a/core/services/ocr2/plugins/ccip/internal/ccipdata/mocks/fee_estimator_config_mock.go b/core/services/ocr2/plugins/ccip/internal/ccipdata/mocks/fee_estimator_config_mock.go index b19f4cd882..e62cdec87a 100644 --- a/core/services/ocr2/plugins/ccip/internal/ccipdata/mocks/fee_estimator_config_mock.go +++ b/core/services/ocr2/plugins/ccip/internal/ccipdata/mocks/fee_estimator_config_mock.go @@ -3,6 +3,8 @@ package mocks import ( + big "math/big" + context "context" mock "github.com/stretchr/testify/mock" @@ -91,6 +93,75 @@ func (_c *FeeEstimatorConfigReader_GetDataAvailabilityConfig_Call) RunAndReturn( return _c } +// ModifyGasPriceComponents provides a mock function with given fields: ctx, execGasPrice, daGasPrice +func (_m *FeeEstimatorConfigReader) ModifyGasPriceComponents(ctx context.Context, execGasPrice *big.Int, daGasPrice *big.Int) (*big.Int, *big.Int, error) { + ret := _m.Called(ctx, execGasPrice, daGasPrice) + + if len(ret) == 0 { + panic("no return value specified for ModifyGasPriceComponents") + } + + var r0 *big.Int + var r1 *big.Int + var r2 error + if rf, ok := ret.Get(0).(func(context.Context, *big.Int, *big.Int) (*big.Int, *big.Int, error)); ok { + return rf(ctx, execGasPrice, daGasPrice) + } + if rf, ok := ret.Get(0).(func(context.Context, *big.Int, *big.Int) *big.Int); ok { + r0 = rf(ctx, execGasPrice, daGasPrice) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*big.Int) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *big.Int, *big.Int) *big.Int); ok { + r1 = rf(ctx, execGasPrice, daGasPrice) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*big.Int) + } + } + + if rf, ok := ret.Get(2).(func(context.Context, *big.Int, *big.Int) error); ok { + r2 = rf(ctx, execGasPrice, daGasPrice) + } else { + r2 = ret.Error(2) + } + + return r0, r1, r2 +} + +// FeeEstimatorConfigReader_ModifyGasPriceComponents_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ModifyGasPriceComponents' +type FeeEstimatorConfigReader_ModifyGasPriceComponents_Call struct { + *mock.Call +} + +// ModifyGasPriceComponents is a helper method to define mock.On call +// - ctx context.Context +// - execGasPrice *big.Int +// - daGasPrice *big.Int +func (_e *FeeEstimatorConfigReader_Expecter) ModifyGasPriceComponents(ctx interface{}, execGasPrice interface{}, daGasPrice interface{}) *FeeEstimatorConfigReader_ModifyGasPriceComponents_Call { + return &FeeEstimatorConfigReader_ModifyGasPriceComponents_Call{Call: _e.mock.On("ModifyGasPriceComponents", ctx, execGasPrice, daGasPrice)} +} + +func (_c *FeeEstimatorConfigReader_ModifyGasPriceComponents_Call) Run(run func(ctx context.Context, execGasPrice *big.Int, daGasPrice *big.Int)) *FeeEstimatorConfigReader_ModifyGasPriceComponents_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(*big.Int), args[2].(*big.Int)) + }) + return _c +} + +func (_c *FeeEstimatorConfigReader_ModifyGasPriceComponents_Call) Return(modExecGasPrice *big.Int, modDAGasPrice *big.Int, err error) *FeeEstimatorConfigReader_ModifyGasPriceComponents_Call { + _c.Call.Return(modExecGasPrice, modDAGasPrice, err) + return _c +} + +func (_c *FeeEstimatorConfigReader_ModifyGasPriceComponents_Call) RunAndReturn(run func(context.Context, *big.Int, *big.Int) (*big.Int, *big.Int, error)) *FeeEstimatorConfigReader_ModifyGasPriceComponents_Call { + _c.Call.Return(run) + return _c +} + // NewFeeEstimatorConfigReader creates a new instance of FeeEstimatorConfigReader. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. // The first argument is typically a *testing.T value. func NewFeeEstimatorConfigReader(t interface { diff --git a/core/services/ocr2/plugins/ccip/prices/da_price_estimator.go b/core/services/ocr2/plugins/ccip/prices/da_price_estimator.go index b27494ad60..34239398c8 100644 --- a/core/services/ocr2/plugins/ccip/prices/da_price_estimator.go +++ b/core/services/ocr2/plugins/ccip/prices/da_price_estimator.go @@ -43,6 +43,7 @@ func (g DAGasPriceEstimator) GetGasPrice(ctx context.Context) (*big.Int, error) return nil, err } var gasPrice *big.Int = execGasPrice + if gasPrice.BitLen() > int(g.priceEncodingLength) { return nil, fmt.Errorf("native gas price exceeded max range %+v", gasPrice) } @@ -56,7 +57,14 @@ func (g DAGasPriceEstimator) GetGasPrice(ctx context.Context) (*big.Int, error) return nil, err } - if daGasPrice := daGasPriceWei.ToInt(); daGasPrice.Cmp(big.NewInt(0)) > 0 { + daGasPrice := daGasPriceWei.ToInt() + + gasPrice, daGasPrice, err = g.feeEstimatorConfig.ModifyGasPriceComponents(ctx, gasPrice, daGasPrice) + if err != nil { + return nil, fmt.Errorf("gasPrice modification failed: %v", err) + } + + if daGasPrice.Cmp(big.NewInt(0)) > 0 { if daGasPrice.BitLen() > int(g.priceEncodingLength) { return nil, fmt.Errorf("data availability gas price exceeded max range %+v", daGasPrice) } diff --git a/core/services/ocr2/plugins/ccip/prices/da_price_estimator_test.go b/core/services/ocr2/plugins/ccip/prices/da_price_estimator_test.go index 158f02c4f0..52ef8c3800 100644 --- a/core/services/ocr2/plugins/ccip/prices/da_price_estimator_test.go +++ b/core/services/ocr2/plugins/ccip/prices/da_price_estimator_test.go @@ -23,11 +23,13 @@ func TestDAPriceEstimator_GetGasPrice(t *testing.T) { ctx := context.Background() testCases := []struct { - name string - daGasPrice *big.Int - execGasPrice *big.Int - expPrice *big.Int - expErr bool + name string + daGasPrice *big.Int + execGasPrice *big.Int + expPrice *big.Int + modExecGasPrice *big.Int + modDAGasPrice *big.Int + expErr bool }{ { name: "base", @@ -57,6 +59,31 @@ func TestDAPriceEstimator_GetGasPrice(t *testing.T) { expPrice: encodeGasPrice(big.NewInt(1e9), big.NewInt(0)), expErr: false, }, + { + name: "execGasPrice Modified", + daGasPrice: big.NewInt(1e9), + execGasPrice: big.NewInt(0), + modExecGasPrice: big.NewInt(1), + expPrice: encodeGasPrice(big.NewInt(1e9), big.NewInt(1)), + expErr: false, + }, + { + name: "daGasPrice Modified", + daGasPrice: big.NewInt(1e9), + execGasPrice: big.NewInt(0), + modDAGasPrice: big.NewInt(1), + expPrice: encodeGasPrice(big.NewInt(1), big.NewInt(0)), + expErr: false, + }, + { + name: "daGasPrice and execGasPrice Modified", + daGasPrice: big.NewInt(1e9), + execGasPrice: big.NewInt(0), + modDAGasPrice: big.NewInt(1), + modExecGasPrice: big.NewInt(2), + expPrice: encodeGasPrice(big.NewInt(1), big.NewInt(2)), + expErr: false, + }, { name: "price out of bounds", daGasPrice: new(big.Int).Lsh(big.NewInt(1), daGasPriceEncodingLength), @@ -74,10 +101,25 @@ func TestDAPriceEstimator_GetGasPrice(t *testing.T) { l1Oracle := mocks.NewL1Oracle(t) l1Oracle.On("GasPrice", ctx).Return(assets.NewWei(tc.daGasPrice), nil) + feeEstimatorConfig := ccipdatamocks.NewFeeEstimatorConfigReader(t) + + modRespExecGasPrice := tc.execGasPrice + if tc.modExecGasPrice != nil { + modRespExecGasPrice = tc.modExecGasPrice + } + + modRespDAGasPrice := tc.daGasPrice + if tc.modDAGasPrice != nil { + modRespDAGasPrice = tc.modDAGasPrice + } + feeEstimatorConfig.On("ModifyGasPriceComponents", mock.Anything, tc.execGasPrice, tc.daGasPrice). + Return(modRespExecGasPrice, modRespDAGasPrice, nil) + g := DAGasPriceEstimator{ execEstimator: execEstimator, l1Oracle: l1Oracle, priceEncodingLength: daGasPriceEncodingLength, + feeEstimatorConfig: feeEstimatorConfig, } gasPrice, err := g.GetGasPrice(ctx) diff --git a/core/services/relay/evm/evm.go b/core/services/relay/evm/evm.go index 85cb3486ca..ae5244f5f0 100644 --- a/core/services/relay/evm/evm.go +++ b/core/services/relay/evm/evm.go @@ -12,6 +12,8 @@ import ( "sync" cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/chaintype" + "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/estimatorconfig/interceptors/mantle" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ccip/ccipcommit" @@ -409,6 +411,16 @@ func (r *Relayer) NewCCIPCommitProvider(rargs commontypes.RelayArgs, pargs commo feeEstimatorConfig := estimatorconfig.NewFeeEstimatorConfigService() + // CCIPCommit reads only when source chain is Mantle, then reports to dest chain + // to minimize misconfigure risk, might make sense to wire Mantle only when Commit + Mantle + IsSourceProvider + if r.chain.Config().EVM().ChainType() == chaintype.ChainMantle && commitPluginConfig.IsSourceProvider { + mantleInterceptor, iErr := mantle.NewInterceptor(ctx, r.chain.Client()) + if iErr != nil { + return nil, iErr + } + feeEstimatorConfig.AddGasPriceInterceptor(mantleInterceptor) + } + // The src chain implementation of this provider does not need a configWatcher or contractTransmitter; // bail early. if commitPluginConfig.IsSourceProvider { @@ -480,6 +492,16 @@ func (r *Relayer) NewCCIPExecProvider(rargs commontypes.RelayArgs, pargs commont feeEstimatorConfig := estimatorconfig.NewFeeEstimatorConfigService() + // CCIPExec reads when dest chain is mantle, and uses it to calc boosting in batching + // to minimize misconfigure risk, make sense to wire Mantle only when Exec + Mantle + !IsSourceProvider + if r.chain.Config().EVM().ChainType() == chaintype.ChainMantle && !execPluginConfig.IsSourceProvider { + mantleInterceptor, iErr := mantle.NewInterceptor(ctx, r.chain.Client()) + if iErr != nil { + return nil, iErr + } + feeEstimatorConfig.AddGasPriceInterceptor(mantleInterceptor) + } + // The src chain implementation of this provider does not need a configWatcher or contractTransmitter; // bail early. if execPluginConfig.IsSourceProvider { diff --git a/core/services/relay/evm/interceptors/mantle/interceptor.go b/core/services/relay/evm/interceptors/mantle/interceptor.go new file mode 100644 index 0000000000..8d5d3bb6c2 --- /dev/null +++ b/core/services/relay/evm/interceptors/mantle/interceptor.go @@ -0,0 +1,80 @@ +package mantle + +import ( + "context" + "fmt" + "math/big" + "strings" + "time" + + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + + evmClient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/rollups" +) + +const ( + // tokenRatio is not volatile and can be requested not often. + tokenRatioUpdateInterval = 60 * time.Minute + // tokenRatio fetches the tokenRatio used for Mantle's gas price calculation + tokenRatioMethod = "tokenRatio" + mantleTokenRatioAbiString = `[{"inputs":[],"name":"tokenRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]` +) + +type Interceptor struct { + client evmClient.Client + tokenRatioCallData []byte + tokenRatio *big.Int + tokenRatioLastUpdate time.Time +} + +func NewInterceptor(_ context.Context, client evmClient.Client) (*Interceptor, error) { + // Encode calldata for tokenRatio method + tokenRatioMethodAbi, err := abi.JSON(strings.NewReader(mantleTokenRatioAbiString)) + if err != nil { + return nil, fmt.Errorf("failed to parse GasPriceOracle %s() method ABI for Mantle; %v", tokenRatioMethod, err) + } + tokenRatioCallData, err := tokenRatioMethodAbi.Pack(tokenRatioMethod) + if err != nil { + return nil, fmt.Errorf("failed to parse GasPriceOracle %s() calldata for Mantle; %v", tokenRatioMethod, err) + } + + return &Interceptor{ + client: client, + tokenRatioCallData: tokenRatioCallData, + }, nil +} + +// ModifyGasPriceComponents returns modified gasPrice. +func (i *Interceptor) ModifyGasPriceComponents(ctx context.Context, execGasPrice, daGasPrice *big.Int) (*big.Int, *big.Int, error) { + if time.Since(i.tokenRatioLastUpdate) > tokenRatioUpdateInterval { + mantleTokenRatio, err := i.getMantleTokenRatio(ctx) + if err != nil { + return nil, nil, err + } + + i.tokenRatio, i.tokenRatioLastUpdate = mantleTokenRatio, time.Now() + } + + // multiply daGasPrice and execGas price by tokenRatio + newExecGasPrice := new(big.Int).Mul(execGasPrice, i.tokenRatio) + newDAGasPrice := new(big.Int).Mul(daGasPrice, i.tokenRatio) + return newExecGasPrice, newDAGasPrice, nil +} + +// getMantleTokenRatio Requests and returns a token ratio value for the Mantle chain. +func (i *Interceptor) getMantleTokenRatio(ctx context.Context) (*big.Int, error) { + precompile := common.HexToAddress(rollups.OPGasOracleAddress) + tokenRatio, err := i.client.CallContract(ctx, ethereum.CallMsg{ + To: &precompile, + Data: i.tokenRatioCallData, + }, nil) + + if err != nil { + return nil, fmt.Errorf("getMantleTokenRatio call failed: %w", err) + } + + return new(big.Int).SetBytes(tokenRatio), nil +} diff --git a/core/services/relay/evm/interceptors/mantle/interceptor_test.go b/core/services/relay/evm/interceptors/mantle/interceptor_test.go new file mode 100644 index 0000000000..9134d996c2 --- /dev/null +++ b/core/services/relay/evm/interceptors/mantle/interceptor_test.go @@ -0,0 +1,96 @@ +package mantle + +import ( + "context" + "math/big" + "testing" + + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client/mocks" +) + +func TestInterceptor(t *testing.T) { + ethClient := mocks.NewClient(t) + ctx := context.Background() + + tokenRatio := big.NewInt(10) + interceptor, err := NewInterceptor(ctx, ethClient) + require.NoError(t, err) + + // request token ratio + ethClient.On("CallContract", ctx, mock.IsType(ethereum.CallMsg{}), mock.IsType(&big.Int{})). + Return(common.BigToHash(tokenRatio).Bytes(), nil).Once() + + modExecGasPrice, modDAGasPrice, err := interceptor.ModifyGasPriceComponents(ctx, big.NewInt(1), big.NewInt(1)) + require.NoError(t, err) + require.Equal(t, int64(10), modExecGasPrice.Int64()) + require.Equal(t, int64(10), modDAGasPrice.Int64()) + + // second call won't invoke eth client + modExecGasPrice, modDAGasPrice, err = interceptor.ModifyGasPriceComponents(ctx, big.NewInt(2), big.NewInt(1)) + require.NoError(t, err) + require.Equal(t, int64(20), modExecGasPrice.Int64()) + require.Equal(t, int64(10), modDAGasPrice.Int64()) +} + +func TestModifyGasPriceComponents(t *testing.T) { + testCases := map[string]struct { + execGasPrice *big.Int + daGasPrice *big.Int + tokenRatio *big.Int + resultExecGasPrice *big.Int + resultDAGasPrice *big.Int + }{ + "regular": { + execGasPrice: big.NewInt(1000), + daGasPrice: big.NewInt(100), + resultExecGasPrice: big.NewInt(2000), + resultDAGasPrice: big.NewInt(200), + tokenRatio: big.NewInt(2), + }, + "zero DAGasPrice": { + execGasPrice: big.NewInt(1000), + daGasPrice: big.NewInt(0), + resultExecGasPrice: big.NewInt(5000), + resultDAGasPrice: big.NewInt(0), + tokenRatio: big.NewInt(5), + }, + "zero ExecGasPrice": { + execGasPrice: big.NewInt(0), + daGasPrice: big.NewInt(10), + resultExecGasPrice: big.NewInt(0), + resultDAGasPrice: big.NewInt(50), + tokenRatio: big.NewInt(5), + }, + "zero token ratio": { + execGasPrice: big.NewInt(15), + daGasPrice: big.NewInt(10), + resultExecGasPrice: big.NewInt(0), + resultDAGasPrice: big.NewInt(0), + tokenRatio: big.NewInt(0), + }, + } + + for tcName, tc := range testCases { + t.Run(tcName, func(t *testing.T) { + ethClient := mocks.NewClient(t) + ctx := context.Background() + + interceptor, err := NewInterceptor(ctx, ethClient) + require.NoError(t, err) + + // request token ratio + ethClient.On("CallContract", ctx, mock.IsType(ethereum.CallMsg{}), mock.IsType(&big.Int{})). + Return(common.BigToHash(tc.tokenRatio).Bytes(), nil).Once() + + modExecGasPrice, modDAGasPrice, err := interceptor.ModifyGasPriceComponents(ctx, tc.execGasPrice, tc.daGasPrice) + require.NoError(t, err) + require.Equal(t, tc.resultExecGasPrice.Int64(), modExecGasPrice.Int64()) + require.Equal(t, tc.resultDAGasPrice.Int64(), modDAGasPrice.Int64()) + }) + } +}